1 /**************************************************************
2 *
3 * Licensed to the Apache Software Foundation (ASF) under one
4 * or more contributor license agreements. See the NOTICE file
5 * distributed with this work for additional information
6 * regarding copyright ownership. The ASF licenses this file
7 * to you under the Apache License, Version 2.0 (the
8 * "License"); you may not use this file except in compliance
9 * with the License. You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing,
14 * software distributed under the License is distributed on an
15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16 * KIND, either express or implied. See the License for the
17 * specific language governing permissions and limitations
18 * under the License.
19 *
20 *************************************************************/
21
22
23
24 #include <malloc.h>
25 #include <hash_map>
26
27 #include <rtl/alloc.h>
28 #include <osl/mutex.hxx>
29
30 #include <com/sun/star/uno/genfunc.hxx>
31 #include "com/sun/star/uno/RuntimeException.hpp"
32 #include <uno/data.h>
33 #include <typelib/typedescription.hxx>
34
35 #include "bridges/cpp_uno/shared/bridge.hxx"
36 #include "bridges/cpp_uno/shared/cppinterfaceproxy.hxx"
37 #include "bridges/cpp_uno/shared/types.hxx"
38 #include "bridges/cpp_uno/shared/vtablefactory.hxx"
39
40 #include "share.hxx"
41
42 #include <dlfcn.h>
43
44
45 using namespace ::osl;
46 using namespace ::rtl;
47 using namespace ::com::sun::star::uno;
48
49 namespace
50 {
51
cpp2uno_call(bridges::cpp_uno::shared::CppInterfaceProxy * pThis,const typelib_TypeDescription * pMemberTypeDescr,typelib_TypeDescriptionReference * pReturnTypeRef,sal_Int32 nParams,typelib_MethodParameter * pParams,long r8,void ** gpreg,double * fpreg,void ** ovrflw,sal_Int64 * pRegisterReturn)52 static typelib_TypeClass cpp2uno_call(
53 bridges::cpp_uno::shared::CppInterfaceProxy* pThis,
54 const typelib_TypeDescription * pMemberTypeDescr,
55 typelib_TypeDescriptionReference * pReturnTypeRef,
56 sal_Int32 nParams, typelib_MethodParameter * pParams,
57 long r8, void ** gpreg, double *fpreg, void ** ovrflw,
58 sal_Int64 * pRegisterReturn /* space for register return */ )
59 {
60 void ** startovrflw = ovrflw;
61 int nregs = 0; //number of words passed in registers
62
63 #ifdef CMC_DEBUG
64 fprintf(stderr, "cpp2uno_call\n");
65 #endif
66 // return
67 typelib_TypeDescription * pReturnTypeDescr = 0;
68 if (pReturnTypeRef)
69 TYPELIB_DANGER_GET( &pReturnTypeDescr, pReturnTypeRef );
70
71 void * pUnoReturn = 0;
72 // complex return ptr: if != 0 && != pUnoReturn, reconversion need
73 void * pCppReturn = 0;
74
75 if (pReturnTypeDescr)
76 {
77 if (hppa::isRegisterReturn(pReturnTypeRef))
78 {
79 #ifdef CMC_DEBUG
80 fprintf(stderr, "simple return\n");
81 #endif
82 pUnoReturn = pRegisterReturn; // direct way for simple types
83 }
84 else
85 {
86 #ifdef CMC_DEBUG
87 fprintf(stderr, "complex return via r8\n");
88 #endif
89 pCppReturn = (void *)r8;
90
91 pUnoReturn = (bridges::cpp_uno::shared::relatesToInterfaceType( pReturnTypeDescr )
92 ? alloca( pReturnTypeDescr->nSize )
93 : pCppReturn); // direct way
94 }
95 }
96 // pop this
97 gpreg++;
98 fpreg++;
99 nregs++;
100
101 // stack space
102 OSL_ENSURE( sizeof(void *) == sizeof(sal_Int32), "### unexpected size!" );
103 // parameters
104 void ** pUnoArgs = (void **)alloca( 4 * sizeof(void *) * nParams );
105 void ** pCppArgs = pUnoArgs + nParams;
106 // indizes of values this have to be converted (interface conversion
107 // cpp<=>uno)
108 sal_Int32 * pTempIndizes = (sal_Int32 *)(pUnoArgs + (2 * nParams));
109 // type descriptions for reconversions
110 typelib_TypeDescription ** ppTempParamTypeDescr =
111 (typelib_TypeDescription **)(pUnoArgs + (3 * nParams));
112
113 sal_Int32 nTempIndizes = 0;
114 bool bOverFlowUsed = false;
115 for ( sal_Int32 nPos = 0; nPos < nParams; ++nPos )
116 {
117 const typelib_MethodParameter & rParam = pParams[nPos];
118 typelib_TypeDescription * pParamTypeDescr = 0;
119 TYPELIB_DANGER_GET( &pParamTypeDescr, rParam.pTypeRef );
120
121 if (!rParam.bOut && bridges::cpp_uno::shared::isSimpleType( pParamTypeDescr ))
122 {
123 switch (pParamTypeDescr->eTypeClass)
124 {
125 case typelib_TypeClass_DOUBLE:
126 if (nregs < hppa::MAX_WORDS_IN_REGS && (nregs & 1))
127 {
128 gpreg++;
129 fpreg++;
130 nregs++;
131 }
132 if (nregs < hppa::MAX_WORDS_IN_REGS-1)
133 {
134 fpreg++;
135 pCppArgs[nPos] = pUnoArgs[nPos] = fpreg;
136 gpreg+=2;
137 fpreg+=2;
138 nregs+=2;
139 }
140 else
141 {
142 if ((startovrflw-ovrflw) & 1)
143 ovrflw--;
144 pCppArgs[nPos] = pUnoArgs[nPos] = ((char*)ovrflw - 4);
145 bOverFlowUsed = true;
146 }
147 if (bOverFlowUsed) ovrflw-=2;
148 break;
149 case typelib_TypeClass_FLOAT:
150 if (nregs < hppa::MAX_WORDS_IN_REGS)
151 {
152 pCppArgs[nPos] = pUnoArgs[nPos] = fpreg;
153 gpreg++;
154 fpreg++;
155 nregs++;
156 }
157 else
158 {
159 pCppArgs[nPos] = pUnoArgs[nPos] = ovrflw;
160 bOverFlowUsed = true;
161 }
162 if (bOverFlowUsed) ovrflw--;
163 break;
164 case typelib_TypeClass_HYPER:
165 case typelib_TypeClass_UNSIGNED_HYPER:
166 if (nregs < hppa::MAX_WORDS_IN_REGS && (nregs & 1))
167 {
168 gpreg++;
169 fpreg++;
170 nregs++;
171 }
172 if (nregs < hppa::MAX_WORDS_IN_REGS-1)
173 {
174 pCppArgs[nPos] = pUnoArgs[nPos] = gpreg;
175 gpreg+=2;
176 fpreg+=2;
177 nregs+=2;
178 }
179 else
180 {
181 if ((startovrflw-ovrflw) & 1)
182 ovrflw--;
183 pCppArgs[nPos] = pUnoArgs[nPos] = ((char*)ovrflw - 4);
184 bOverFlowUsed = true;
185 }
186 if (bOverFlowUsed) ovrflw-=2;
187 break;
188 case typelib_TypeClass_BYTE:
189 case typelib_TypeClass_BOOLEAN:
190 if (nregs < hppa::MAX_WORDS_IN_REGS)
191 {
192 pCppArgs[nPos] = pUnoArgs[nPos] = ((char*)gpreg + 3);
193 gpreg++;
194 fpreg++;
195 nregs++;
196 }
197 else
198 {
199 pCppArgs[nPos] = pUnoArgs[nPos] = ((char*)ovrflw+3);
200 bOverFlowUsed = true;
201 }
202 if (bOverFlowUsed) ovrflw--;
203 break;
204 case typelib_TypeClass_CHAR:
205 case typelib_TypeClass_SHORT:
206 case typelib_TypeClass_UNSIGNED_SHORT:
207 if (nregs < hppa::MAX_WORDS_IN_REGS)
208 {
209 pCppArgs[nPos] = pUnoArgs[nPos] = ((char*)gpreg+2);
210 gpreg++;
211 fpreg++;
212 nregs++;
213 }
214 else
215 {
216 pCppArgs[nPos] = pUnoArgs[nPos] = ((char*)ovrflw+2);
217 bOverFlowUsed = true;
218 }
219 if (bOverFlowUsed) ovrflw--;
220 break;
221 case typelib_TypeClass_ENUM:
222 case typelib_TypeClass_LONG:
223 case typelib_TypeClass_UNSIGNED_LONG:
224 default:
225 if (nregs < hppa::MAX_WORDS_IN_REGS)
226 {
227 pCppArgs[nPos] = pUnoArgs[nPos] = gpreg;
228 gpreg++;
229 fpreg++;
230 nregs++;
231 }
232 else
233 {
234 pCppArgs[nPos] = pUnoArgs[nPos] = ovrflw;
235 bOverFlowUsed = true;
236 }
237 if (bOverFlowUsed) ovrflw--;
238 break;
239 }
240 // no longer needed
241 TYPELIB_DANGER_RELEASE( pParamTypeDescr );
242 }
243 else // ptr to complex value | ref
244 {
245 void *pCppStack;
246
247 if (nregs < hppa::MAX_WORDS_IN_REGS)
248 {
249 pCppArgs[nPos] = pCppStack = *gpreg;
250 gpreg++;
251 fpreg++;
252 nregs++;
253 }
254 else
255 {
256 pCppArgs[nPos] = pCppStack = *ovrflw;
257 bOverFlowUsed = true;
258 }
259 if (bOverFlowUsed) ovrflw--;
260
261 if (! rParam.bIn) // is pure out
262 {
263 // uno out is unconstructed mem!
264 pUnoArgs[nPos] = alloca( pParamTypeDescr->nSize );
265 pTempIndizes[nTempIndizes] = nPos;
266 // will be released at reconversion
267 ppTempParamTypeDescr[nTempIndizes++] = pParamTypeDescr;
268 }
269 // is in/inout
270 else if (bridges::cpp_uno::shared::relatesToInterfaceType(
271 pParamTypeDescr ))
272 {
273 uno_copyAndConvertData( pUnoArgs[nPos] = alloca( pParamTypeDescr->nSize ),
274 pCppStack, pParamTypeDescr,
275 pThis->getBridge()->getCpp2Uno() );
276 pTempIndizes[nTempIndizes] = nPos; // has to be reconverted
277 // will be released at reconversion
278 ppTempParamTypeDescr[nTempIndizes++] = pParamTypeDescr;
279 }
280 else // direct way
281 {
282 pUnoArgs[nPos] = pCppStack;
283 // no longer needed
284 TYPELIB_DANGER_RELEASE( pParamTypeDescr );
285 }
286 }
287 }
288
289 // ExceptionHolder
290 uno_Any aUnoExc; // Any will be constructed by callee
291 uno_Any * pUnoExc = &aUnoExc;
292
293 #ifdef CMC_DEBUG
294 fprintf(stderr, "before dispatch\n");
295 #endif
296 // invoke uno dispatch call
297 (*pThis->getUnoI()->pDispatcher)(
298 pThis->getUnoI(), pMemberTypeDescr, pUnoReturn, pUnoArgs, &pUnoExc );
299
300 #ifdef CMC_DEBUG
301 fprintf(stderr, "after dispatch\n");
302 #endif
303
304 // in case an exception occured...
305 if (pUnoExc)
306 {
307 // destruct temporary in/inout params
308 for ( ; nTempIndizes--; )
309 {
310 sal_Int32 nIndex = pTempIndizes[nTempIndizes];
311
312 if (pParams[nIndex].bIn) // is in/inout => was constructed
313 uno_destructData( pUnoArgs[nIndex],
314 ppTempParamTypeDescr[nTempIndizes], 0 );
315 TYPELIB_DANGER_RELEASE( ppTempParamTypeDescr[nTempIndizes] );
316 }
317 if (pReturnTypeDescr)
318 TYPELIB_DANGER_RELEASE( pReturnTypeDescr );
319
320 CPPU_CURRENT_NAMESPACE::raiseException( &aUnoExc,
321 pThis->getBridge()->getUno2Cpp() ); // has to destruct the any
322 // is here for dummy
323 return typelib_TypeClass_VOID;
324 }
325 else // else no exception occured...
326 {
327 // temporary params
328 for ( ; nTempIndizes--; )
329 {
330 sal_Int32 nIndex = pTempIndizes[nTempIndizes];
331 typelib_TypeDescription * pParamTypeDescr =
332 ppTempParamTypeDescr[nTempIndizes];
333
334 if (pParams[nIndex].bOut) // inout/out
335 {
336 // convert and assign
337 uno_destructData( pCppArgs[nIndex], pParamTypeDescr,
338 cpp_release );
339 uno_copyAndConvertData( pCppArgs[nIndex], pUnoArgs[nIndex],
340 pParamTypeDescr, pThis->getBridge()->getUno2Cpp() );
341 }
342 // destroy temp uno param
343 uno_destructData( pUnoArgs[nIndex], pParamTypeDescr, 0 );
344
345 TYPELIB_DANGER_RELEASE( pParamTypeDescr );
346 }
347 // return
348 if (pCppReturn) // has complex return
349 {
350 if (pUnoReturn != pCppReturn) // needs reconversion
351 {
352 uno_copyAndConvertData( pCppReturn, pUnoReturn,
353 pReturnTypeDescr, pThis->getBridge()->getUno2Cpp() );
354 // destroy temp uno return
355 uno_destructData( pUnoReturn, pReturnTypeDescr, 0 );
356 }
357 // complex return ptr is set to eax
358 *(void **)pRegisterReturn = pCppReturn;
359 }
360 if (pReturnTypeDescr)
361 {
362 typelib_TypeClass eRet =
363 (typelib_TypeClass)pReturnTypeDescr->eTypeClass;
364 TYPELIB_DANGER_RELEASE( pReturnTypeDescr );
365 return eRet;
366 }
367 else
368 return typelib_TypeClass_VOID;
369 }
370 }
371
372
373 //=====================================================================
cpp_mediate(sal_Int32 nFunctionIndex,sal_Int32 nVtableOffset,void ** gpreg,double * fpreg,long sp,long r8,sal_Int64 * pRegisterReturn)374 static typelib_TypeClass cpp_mediate(
375 sal_Int32 nFunctionIndex, sal_Int32 nVtableOffset,
376 void ** gpreg, double* fpreg,
377 long sp, long r8,
378 sal_Int64 * pRegisterReturn /* space for register return */ )
379
380 {
381 void ** ovrflw = (void**)(sp);
382 #ifdef CMC_DEBUG
383 fprintf(stderr, "cpp_mediate with\n");
384 fprintf(stderr, "%x %x\n", nFunctionIndex, nVtableOffset);
385 fprintf(stderr, "and %x %x\n", (long)(ovrflw[0]), (long)(ovrflw[-1]));
386 fprintf(stderr, "and %x %x\n", (long)(ovrflw[-2]), (long)(ovrflw[-3]));
387 fprintf(stderr, "and %x %x\n", (long)(ovrflw[-4]), (long)(ovrflw[-5]));
388 fprintf(stderr, "and %x %x\n", (long)(ovrflw[-6]), (long)(ovrflw[-7]));
389 fprintf(stderr, "and %x %x\n", (long)(ovrflw[-8]), (long)(ovrflw[-9]));
390 fprintf(stderr, "and %x %x\n", (long)(ovrflw[-10]), (long)(ovrflw[-11]));
391 fprintf(stderr, "and %x %x\n", (long)(ovrflw[-12]), (long)(ovrflw[-13]));
392 fprintf(stderr, "and %x %x\n", (long)(ovrflw[-14]), (long)(ovrflw[-15]));
393 #endif
394 OSL_ENSURE( sizeof(sal_Int32)==sizeof(void *), "### unexpected!" );
395
396 // gpreg: [ret *], this, [other gpr params]
397 // fpreg: [fpr params]
398 // ovrflw: [gpr or fpr params (properly aligned)]
399
400 void * pThis;
401 if (nFunctionIndex & 0x80000000 )
402 {
403 nFunctionIndex &= 0x7fffffff;
404 pThis = gpreg[1];
405 #ifdef CMC_DEBUG
406 fprintf(stderr, "pThis is gpreg[1]\n");
407 #endif
408 }
409 else
410 {
411 pThis = gpreg[0];
412 #ifdef CMC_DEBUG
413 fprintf(stderr, "pThis is gpreg[0]\n");
414 #endif
415 }
416
417 pThis = static_cast< char * >(pThis) - nVtableOffset;
418
419 bridges::cpp_uno::shared::CppInterfaceProxy * pCppI =
420 bridges::cpp_uno::shared::CppInterfaceProxy::castInterfaceToProxy(
421 pThis);
422
423 typelib_InterfaceTypeDescription * pTypeDescr = pCppI->getTypeDescr();
424
425 OSL_ENSURE( nFunctionIndex < pTypeDescr->nMapFunctionIndexToMemberIndex,
426 "### illegal vtable index!" );
427 if (nFunctionIndex >= pTypeDescr->nMapFunctionIndexToMemberIndex)
428 {
429 throw RuntimeException(
430 OUString::createFromAscii("illegal vtable index!"),
431 (XInterface *)pCppI );
432 }
433
434 // determine called method
435 OSL_ENSURE( nFunctionIndex < pTypeDescr->nMapFunctionIndexToMemberIndex,
436 "### illegal vtable index!" );
437 sal_Int32 nMemberPos =
438 pTypeDescr->pMapFunctionIndexToMemberIndex[nFunctionIndex];
439 OSL_ENSURE( nMemberPos < pTypeDescr->nAllMembers,
440 "### illegal member index!" );
441
442 TypeDescription aMemberDescr( pTypeDescr->ppAllMembers[nMemberPos] );
443
444 typelib_TypeClass eRet;
445 switch (aMemberDescr.get()->eTypeClass)
446 {
447 case typelib_TypeClass_INTERFACE_ATTRIBUTE:
448 {
449 if (pTypeDescr->pMapMemberIndexToFunctionIndex[nMemberPos] ==
450 nFunctionIndex)
451 {
452 // is GET method
453 eRet = cpp2uno_call(
454 pCppI, aMemberDescr.get(),
455 ((typelib_InterfaceAttributeTypeDescription *)aMemberDescr.get())->pAttributeTypeRef,
456 0, 0, // no params
457 r8, gpreg, fpreg, ovrflw, pRegisterReturn );
458 }
459 else
460 {
461 // is SET method
462 typelib_MethodParameter aParam;
463 aParam.pTypeRef =
464 ((typelib_InterfaceAttributeTypeDescription *)aMemberDescr.get())->pAttributeTypeRef;
465 aParam.bIn = sal_True;
466 aParam.bOut = sal_False;
467
468 eRet = cpp2uno_call(
469 pCppI, aMemberDescr.get(),
470 0, // indicates void return
471 1, &aParam,
472 r8, gpreg, fpreg, ovrflw, pRegisterReturn );
473 }
474 break;
475 }
476 case typelib_TypeClass_INTERFACE_METHOD:
477 {
478 // is METHOD
479 switch (nFunctionIndex)
480 {
481 case 1: // acquire()
482 pCppI->acquireProxy(); // non virtual call!
483 eRet = typelib_TypeClass_VOID;
484 break;
485 case 2: // release()
486 pCppI->releaseProxy(); // non virtual call!
487 eRet = typelib_TypeClass_VOID;
488 break;
489 case 0: // queryInterface() opt
490 {
491 typelib_TypeDescription * pTD = 0;
492 TYPELIB_DANGER_GET(&pTD,
493 reinterpret_cast<Type *>(gpreg[1])->getTypeLibType());
494 if (pTD)
495 {
496 XInterface * pInterface = 0;
497 (*pCppI->getBridge()->getCppEnv()->getRegisteredInterface)(
498 pCppI->getBridge()->getCppEnv(),
499 (void **)&pInterface, pCppI->getOid().pData,
500 (typelib_InterfaceTypeDescription *)pTD );
501
502 if (pInterface)
503 {
504 ::uno_any_construct(
505 reinterpret_cast< uno_Any * >( r8 ),
506 &pInterface, pTD, cpp_acquire );
507 pInterface->release();
508 TYPELIB_DANGER_RELEASE( pTD );
509 *(void **)pRegisterReturn = (void*)r8;
510 eRet = typelib_TypeClass_ANY;
511 break;
512 }
513 TYPELIB_DANGER_RELEASE( pTD );
514 }
515 } // else perform queryInterface()
516 default:
517 eRet = cpp2uno_call(
518 pCppI, aMemberDescr.get(),
519 ((typelib_InterfaceMethodTypeDescription *)aMemberDescr.get())->pReturnTypeRef,
520 ((typelib_InterfaceMethodTypeDescription *)aMemberDescr.get())->nParams,
521 ((typelib_InterfaceMethodTypeDescription *)aMemberDescr.get())->pParams,
522 r8, gpreg, fpreg, ovrflw, pRegisterReturn );
523 }
524 break;
525 }
526 default:
527 {
528 throw RuntimeException(
529 OUString::createFromAscii("no member description found!"),
530 (XInterface *)pCppI );
531 // is here for dummy
532 eRet = typelib_TypeClass_VOID;
533 }
534 }
535
536 return eRet;
537 }
538 }
539
540 //=======================================================================
541 /**
542 * is called on incoming vtable calls
543 * (called by asm snippets)
544 */
545
cpp_vtable_call(sal_uInt32 in0,sal_uInt32 in1,sal_uInt32 in2,sal_uInt32 in3,sal_uInt32 firstonstack)546 sal_Int64 cpp_vtable_call( sal_uInt32 in0, sal_uInt32 in1, sal_uInt32 in2, sal_uInt32 in3, sal_uInt32 firstonstack )
547 {
548 register sal_Int32 r21 asm("r21");
549 register sal_Int32 r22 asm("r22");
550 register sal_Int32 r28 asm("r28");
551 sal_Int32 functionIndex = r21;
552 sal_Int32 vtableOffset = r22;
553 sal_Int32 r8 = r28;
554
555 long sp = (long)&firstonstack;
556
557 sal_uInt32 gpreg[hppa::MAX_GPR_REGS];
558 gpreg[0] = in0;
559 gpreg[1] = in1;
560 gpreg[2] = in2;
561 gpreg[3] = in3;
562
563 float fpreg[hppa::MAX_SSE_REGS]; //todo
564 register float f0 asm("fr4"); fpreg[0] = f0;
565 register float f1 asm("fr5"); fpreg[1] = f1;
566 register float f2 asm("fr6"); fpreg[2] = f2;
567 register float f3 asm("fr7"); fpreg[3] = f3;
568
569 double dpreg[hppa::MAX_SSE_REGS]; //todo
570 register double d0 asm("fr4"); dpreg[0] = d0;
571 register double d1 asm("fr5"); dpreg[1] = d1;
572 register double d2 asm("fr6"); dpreg[2] = d2;
573 register double d3 asm("fr7"); dpreg[3] = d3;
574
575
576 #ifdef CMC_DEBUG
577 fprintf(stderr, "got to cpp_vtable_call with %x %x\n", functionIndex, vtableOffset);
578 for (int i = 0; i < hppa::MAX_GPR_REGS; ++i)
579 fprintf(stderr, "reg %d is %d %x\n", i, gpreg[i], gpreg[i]);
580 for (int i = 0; i < hppa::MAX_SSE_REGS; ++i)
581 fprintf(stderr, "float reg %d is %f %x\n", i, fpreg[i], ((long*)fpreg)[i]);
582 for (int i = 0; i < 4; ++i)
583 fprintf(stderr, "double reg %d is %f %llx\n", i, dpreg[i], ((long long*)dpreg)[i]);
584 #endif
585
586 sal_Int64 nRegReturn;
587
588 typelib_TypeClass aType =
589 cpp_mediate( functionIndex, vtableOffset, (void**)gpreg, dpreg, sp, r8, &nRegReturn);
590
591 switch( aType )
592 {
593 case typelib_TypeClass_FLOAT:
594 f0 = (*((float*)&nRegReturn));
595 break;
596 case typelib_TypeClass_DOUBLE:
597 d0 = (*((double*)&nRegReturn));
598 break;
599 default:
600 break;
601 }
602
603 return nRegReturn;
604 }
605
606
607 namespace
608 {
609 const int codeSnippetSize = 44;
610
611 # define unldil(v) (((v & 0x7c) << 14) | ((v & 0x180) << 7) | ((v & 0x3) << 12) | ((v & 0xffe00) >> 8) | ((v & 0x100000) >> 20))
612 # define L21(v) unldil(((unsigned long)(v) >> 11) & 0x1fffff) //Left 21 bits
613 # define R11(v) (((unsigned long)(v) & 0x7FF) << 1) //Right 11 bits
614
codeSnippet(unsigned char * code,sal_Int32 functionIndex,sal_Int32 vtableOffset,bool bHasHiddenParam)615 unsigned char *codeSnippet(unsigned char* code, sal_Int32 functionIndex,
616 sal_Int32 vtableOffset, bool bHasHiddenParam)
617 {
618 if (bHasHiddenParam)
619 functionIndex |= 0x80000000;
620
621 unsigned char * p = code;
622 *(unsigned long*)&p[0] = 0xeaa00000; // b,l 0x8,r21
623 *(unsigned long*)&p[4] = 0xd6a01c1e; // depwi 0,31,2,r21
624 *(unsigned long*)&p[8] = 0x4aa10040; // ldw 32(r21),r1
625
626 *(unsigned long*)&p[12] = 0x22A00000 | L21(functionIndex); // ldil L<functionIndex>,r21
627 *(unsigned long*)&p[16] = 0x36B50000 | R11(functionIndex); // ldo R<functionIndex>,r21
628
629 *(unsigned long*)&p[20] = 0x22C00000 | L21(vtableOffset); // ldil L<vtableOffset>,r22
630 *(unsigned long*)&p[24] = 0x36D60000 | R11(vtableOffset); // ldo R<vtableOffset>,r22
631
632 *(unsigned long*)&p[28] = 0x0c201094; // ldw 0(r1),r20
633 *(unsigned long*)&p[32] = 0xea80c000; // bv r0(r20)
634 *(unsigned long*)&p[36] = 0x0c281093; // ldw 4(r1),r19
635 *(unsigned long*)&p[40] = ((unsigned long)(cpp_vtable_call) & ~2);
636
637 return code + codeSnippetSize;
638 }
639 }
640
641 struct bridges::cpp_uno::shared::VtableFactory::Slot { void * fn; };
642
643 bridges::cpp_uno::shared::VtableFactory::Slot *
mapBlockToVtable(void * block)644 bridges::cpp_uno::shared::VtableFactory::mapBlockToVtable(void * block)
645 {
646 return static_cast< Slot * >(block) + 2;
647 }
648
getBlockSize(sal_Int32 slotCount)649 sal_Size bridges::cpp_uno::shared::VtableFactory::getBlockSize(
650 sal_Int32 slotCount)
651 {
652 return (slotCount + 2) * sizeof (Slot) + slotCount * codeSnippetSize;
653 }
654
655 bridges::cpp_uno::shared::VtableFactory::Slot *
initializeBlock(void * block,sal_Int32 slotCount)656 bridges::cpp_uno::shared::VtableFactory::initializeBlock(
657 void * block, sal_Int32 slotCount)
658 {
659 Slot * slots = mapBlockToVtable(block);
660 slots[-2].fn = 0;
661 slots[-1].fn = 0;
662 return slots + slotCount;
663 }
664
addLocalFunctions(Slot ** slots,unsigned char * code,sal_PtrDiff writetoexecdiff,typelib_InterfaceTypeDescription const * type,sal_Int32 functionOffset,sal_Int32 functionCount,sal_Int32 vtableOffset)665 unsigned char * bridges::cpp_uno::shared::VtableFactory::addLocalFunctions(
666 Slot ** slots, unsigned char * code, sal_PtrDiff writetoexecdiff,
667 typelib_InterfaceTypeDescription const * type, sal_Int32 functionOffset,
668 sal_Int32 functionCount, sal_Int32 vtableOffset)
669 {
670 (*slots) -= functionCount;
671 Slot * s = *slots;
672 for (sal_Int32 i = 0; i < type->nMembers; ++i)
673 {
674 typelib_TypeDescription * member = 0;
675 TYPELIB_DANGER_GET(&member, type->ppMembers[i]);
676 OSL_ASSERT(member != 0);
677 switch (member->eTypeClass)
678 {
679 case typelib_TypeClass_INTERFACE_ATTRIBUTE:
680 // Getter:
681 (s++)->fn = code + writetoexecdiff;
682 code = codeSnippet(code, functionOffset++, vtableOffset, false);
683 // Setter:
684 if (!reinterpret_cast<
685 typelib_InterfaceAttributeTypeDescription * >(
686 member)->bReadOnly)
687 {
688 (s++)->fn = code + writetoexecdiff;
689 code = codeSnippet(code, functionOffset++, vtableOffset, false);
690 }
691 break;
692 case typelib_TypeClass_INTERFACE_METHOD:
693 {
694 (s++)->fn = code + writetoexecdiff;
695 code = codeSnippet(code, functionOffset++, vtableOffset, false);
696 break;
697 }
698 default:
699 OSL_ASSERT(false);
700 break;
701 }
702 TYPELIB_DANGER_RELEASE(member);
703 }
704 return code;
705 }
706
flushCode(unsigned char const * beg,unsigned char const * end)707 void bridges::cpp_uno::shared::VtableFactory::flushCode(
708 unsigned char const *beg, unsigned char const *end)
709 {
710 void *p = (void*)((size_t)beg & ~31);
711 size_t stride = 32;
712 while (p < end)
713 {
714 asm volatile("fdc (%0)\n\t"
715 "sync\n\t"
716 "fic,m %1(%%sr4, %0)\n\t"
717 "sync" : "+r"(p) : "r"(stride) : "memory");
718 }
719 }
720
721 /* vi:set tabstop=4 shiftwidth=4 expandtab: */
722