xref: /trunk/main/bridges/source/cpp_uno/gcc3_linux_powerpc/cpp2uno.cxx (revision cdf0e10c4e3984b49a9502b011690b615761d4a3)
1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_bridges.hxx"
30 
31 #include <string.h>
32 
33 #include <com/sun/star/uno/genfunc.hxx>
34 #include <uno/data.h>
35 #include <typelib/typedescription.hxx>
36 
37 #include "bridges/cpp_uno/shared/bridge.hxx"
38 #include "bridges/cpp_uno/shared/cppinterfaceproxy.hxx"
39 #include "bridges/cpp_uno/shared/types.hxx"
40 #include "bridges/cpp_uno/shared/vtablefactory.hxx"
41 
42 #include "share.hxx"
43 // #include <stdio.h>
44 
45 
46 using namespace ::com::sun::star::uno;
47 
48 namespace
49 {
50 
51 //==================================================================================================
52 static typelib_TypeClass cpp2uno_call(
53     bridges::cpp_uno::shared::CppInterfaceProxy * pThis,
54     const typelib_TypeDescription * pMemberTypeDescr,
55     typelib_TypeDescriptionReference * pReturnTypeRef, // 0 indicates void return
56     sal_Int32 nParams, typelib_MethodParameter * pParams,
57         void ** gpreg, void ** fpreg, void ** ovrflw,
58     sal_Int64 * pRegisterReturn /* space for register return */ )
59 {
60         int ng = 0; //number of gpr registers used
61 #ifndef __NO_FPRS__
62         int nf = 0; //number of fpr regsiters used
63 #endif
64         void ** pCppStack; //temporary stack pointer
65 
66         // gpreg:  [ret *], this, [gpr params]
67         // fpreg:  [fpr params]
68         // ovrflw: [gpr or fpr params (properly aligned)]
69 
70     // return
71     typelib_TypeDescription * pReturnTypeDescr = 0;
72     if (pReturnTypeRef)
73         TYPELIB_DANGER_GET( &pReturnTypeDescr, pReturnTypeRef );
74 
75     void * pUnoReturn = 0;
76     void * pCppReturn = 0; // complex return ptr: if != 0 && != pUnoReturn, reconversion need
77 
78     if (pReturnTypeDescr)
79     {
80         if (bridges::cpp_uno::shared::isSimpleType( pReturnTypeDescr ))
81         {
82             pUnoReturn = pRegisterReturn; // direct way for simple types
83         }
84         else // complex return via ptr (pCppReturn)
85         {
86             pCppReturn = *(void **)gpreg;
87                         gpreg++;
88                         ng++;
89 
90             pUnoReturn = (bridges::cpp_uno::shared::relatesToInterfaceType( pReturnTypeDescr )
91                           ? alloca( pReturnTypeDescr->nSize )
92                           : pCppReturn); // direct way
93         }
94     }
95     // pop this
96         gpreg++;
97         ng++;
98 
99     // stack space
100     OSL_ENSURE( sizeof(void *) == sizeof(sal_Int32), "### unexpected size!" );
101     // parameters
102     void ** pUnoArgs = (void **)alloca( 4 * sizeof(void *) * nParams );
103     void ** pCppArgs = pUnoArgs + nParams;
104     // indizes of values this have to be converted (interface conversion cpp<=>uno)
105     sal_Int32 * pTempIndizes = (sal_Int32 *)(pUnoArgs + (2 * nParams));
106     // type descriptions for reconversions
107     typelib_TypeDescription ** ppTempParamTypeDescr = (typelib_TypeDescription **)(pUnoArgs + (3 * nParams));
108 
109     sal_Int32 nTempIndizes   = 0;
110 
111     for ( sal_Int32 nPos = 0; nPos < nParams; ++nPos )
112     {
113         const typelib_MethodParameter & rParam = pParams[nPos];
114         typelib_TypeDescription * pParamTypeDescr = 0;
115         TYPELIB_DANGER_GET( &pParamTypeDescr, rParam.pTypeRef );
116 
117         if (!rParam.bOut && bridges::cpp_uno::shared::isSimpleType( pParamTypeDescr ))
118                 // value
119         {
120 
121             switch (pParamTypeDescr->eTypeClass)
122             {
123 
124               case typelib_TypeClass_DOUBLE:
125 #ifndef __NO_FPRS__
126                if (nf < 8) {
127                   pCppArgs[nPos] = fpreg;
128                   pUnoArgs[nPos] = fpreg;
129                   nf++;
130                   fpreg += 2;
131 #else
132                if (ng & 1) {
133                    ng++;
134                    gpreg++;
135                }
136                if (ng < 8) {
137                    pCppArgs[nPos] = gpreg;
138                    pUnoArgs[nPos] = gpreg;
139                    ng += 2;
140                    gpreg += 2;
141 #endif
142                } else {
143                 if (((long)ovrflw) & 4) ovrflw++;
144                 pCppArgs[nPos] = ovrflw;
145                 pUnoArgs[nPos] = ovrflw;
146                     ovrflw += 2;
147                }
148                break;
149 
150                case typelib_TypeClass_FLOAT:
151                 // fpreg are all double values so need to
152                 // modify fpreg to be a single word float value
153 #ifndef __NO_FPRS__
154                 if (nf < 8) {
155                    float tmp = (float) (*((double *)fpreg));
156                    (*((float *) fpreg)) = tmp;
157                    pCppArgs[nPos] = fpreg;
158                    pUnoArgs[nPos] = fpreg;
159                    nf++;
160                    fpreg += 2;
161 #else
162                 if (ng < 8) {
163                    pCppArgs[nPos] = gpreg;
164                    pUnoArgs[nPos] = gpreg;
165                    ng++;
166                    gpreg++;
167 #endif
168                 } else {
169 #if 0 /* abi is not being followed correctly */
170                   if (((long)ovrflw) & 4) ovrflw++;
171                   float tmp = (float) (*((double *)ovrflw));
172                   (*((float *) ovrflw)) = tmp;
173                   pCppArgs[nPos] = ovrflw;
174                   pUnoArgs[nPos] = ovrflw;
175                   ovrflw += 2;
176 #else
177                               pCppArgs[nPos] = ovrflw;
178                   pUnoArgs[nPos] = ovrflw;
179                   ovrflw += 1;
180 #endif
181                             }
182                 break;
183 
184             case typelib_TypeClass_HYPER:
185             case typelib_TypeClass_UNSIGNED_HYPER:
186              if (ng & 1) {
187                 ng++;
188                 gpreg++;
189              }
190              if (ng < 8) {
191                 pCppArgs[nPos] = gpreg;
192                 pUnoArgs[nPos] = gpreg;
193                 ng += 2;
194                 gpreg += 2;
195              } else {
196                 if (((long)ovrflw) & 4) ovrflw++;
197                 pCppArgs[nPos] = ovrflw;
198                 pUnoArgs[nPos] = ovrflw;
199                 ovrflw += 2;
200               }
201               break;
202 
203             case typelib_TypeClass_BYTE:
204             case typelib_TypeClass_BOOLEAN:
205              if (ng < 8) {
206                   pCppArgs[nPos] = (((char *)gpreg) + 3);
207                   pUnoArgs[nPos] = (((char *)gpreg) + 3);
208                   ng++;
209                   gpreg++;
210              } else {
211                   pCppArgs[nPos] = (((char *)ovrflw) + 3);
212                   pUnoArgs[nPos] = (((char *)ovrflw) + 3);
213                   ovrflw++;
214              }
215              break;
216 
217 
218                case typelib_TypeClass_CHAR:
219                case typelib_TypeClass_SHORT:
220                case typelib_TypeClass_UNSIGNED_SHORT:
221             if (ng < 8) {
222                   pCppArgs[nPos] = (((char *)gpreg)+ 2);
223                   pUnoArgs[nPos] = (((char *)gpreg)+ 2);
224                   ng++;
225                   gpreg++;
226             } else {
227                   pCppArgs[nPos] = (((char *)ovrflw) + 2);
228                   pUnoArgs[nPos] = (((char *)ovrflw) + 2);
229                   ovrflw++;
230             }
231             break;
232 
233 
234               default:
235             if (ng < 8) {
236                   pCppArgs[nPos] = gpreg;
237                   pUnoArgs[nPos] = gpreg;
238                   ng++;
239                   gpreg++;
240             } else {
241                   pCppArgs[nPos] = ovrflw;
242                   pUnoArgs[nPos] = ovrflw;
243                   ovrflw++;
244             }
245                         break;
246 
247                 }
248                 // no longer needed
249             TYPELIB_DANGER_RELEASE( pParamTypeDescr );
250         }
251         else // ptr to complex value | ref
252         {
253 
254                 if (ng < 8) {
255                   pCppArgs[nPos] = *(void **)gpreg;
256                   pCppStack = gpreg;
257                   ng++;
258                   gpreg++;
259                 } else {
260                   pCppArgs[nPos] = *(void **)ovrflw;
261                   pCppStack = ovrflw;
262                  ovrflw++;
263                 }
264 
265             if (! rParam.bIn) // is pure out
266             {
267                 // uno out is unconstructed mem!
268                 pUnoArgs[nPos] = alloca( pParamTypeDescr->nSize );
269                 pTempIndizes[nTempIndizes] = nPos;
270                 // will be released at reconversion
271                 ppTempParamTypeDescr[nTempIndizes++] = pParamTypeDescr;
272             }
273             // is in/inout
274             else if (bridges::cpp_uno::shared::relatesToInterfaceType( pParamTypeDescr ))
275             {
276                 uno_copyAndConvertData( pUnoArgs[nPos] = alloca( pParamTypeDescr->nSize ),
277                                         *(void **)pCppStack, pParamTypeDescr,
278                                         pThis->getBridge()->getCpp2Uno() );
279                 pTempIndizes[nTempIndizes] = nPos; // has to be reconverted
280                 // will be released at reconversion
281                 ppTempParamTypeDescr[nTempIndizes++] = pParamTypeDescr;
282             }
283             else // direct way
284             {
285                 pUnoArgs[nPos] = *(void **)pCppStack;
286                 // no longer needed
287                 TYPELIB_DANGER_RELEASE( pParamTypeDescr );
288             }
289         }
290     }
291 
292     // ExceptionHolder
293     uno_Any aUnoExc; // Any will be constructed by callee
294     uno_Any * pUnoExc = &aUnoExc;
295 
296     // invoke uno dispatch call
297     (*pThis->getUnoI()->pDispatcher)( pThis->getUnoI(), pMemberTypeDescr, pUnoReturn, pUnoArgs, &pUnoExc );
298 
299     // in case an exception occured...
300     if (pUnoExc)
301     {
302         // destruct temporary in/inout params
303         for ( ; nTempIndizes--; )
304         {
305             sal_Int32 nIndex = pTempIndizes[nTempIndizes];
306 
307             if (pParams[nIndex].bIn) // is in/inout => was constructed
308                 uno_destructData( pUnoArgs[nIndex], ppTempParamTypeDescr[nTempIndizes], 0 );
309             TYPELIB_DANGER_RELEASE( ppTempParamTypeDescr[nTempIndizes] );
310         }
311         if (pReturnTypeDescr)
312             TYPELIB_DANGER_RELEASE( pReturnTypeDescr );
313 
314         CPPU_CURRENT_NAMESPACE::raiseException( &aUnoExc, pThis->getBridge()->getUno2Cpp() );
315                 // has to destruct the any
316         // is here for dummy
317         return typelib_TypeClass_VOID;
318     }
319     else // else no exception occured...
320     {
321         // temporary params
322         for ( ; nTempIndizes--; )
323         {
324             sal_Int32 nIndex = pTempIndizes[nTempIndizes];
325             typelib_TypeDescription * pParamTypeDescr = ppTempParamTypeDescr[nTempIndizes];
326 
327             if (pParams[nIndex].bOut) // inout/out
328             {
329                 // convert and assign
330                 uno_destructData( pCppArgs[nIndex], pParamTypeDescr, cpp_release );
331                 uno_copyAndConvertData( pCppArgs[nIndex], pUnoArgs[nIndex], pParamTypeDescr,
332                                         pThis->getBridge()->getUno2Cpp() );
333             }
334             // destroy temp uno param
335             uno_destructData( pUnoArgs[nIndex], pParamTypeDescr, 0 );
336 
337             TYPELIB_DANGER_RELEASE( pParamTypeDescr );
338         }
339         // return
340         if (pCppReturn) // has complex return
341         {
342             if (pUnoReturn != pCppReturn) // needs reconversion
343             {
344                 uno_copyAndConvertData( pCppReturn, pUnoReturn, pReturnTypeDescr,
345                                         pThis->getBridge()->getUno2Cpp() );
346                 // destroy temp uno return
347                 uno_destructData( pUnoReturn, pReturnTypeDescr, 0 );
348             }
349             // complex return ptr is set to return reg
350             *(void **)pRegisterReturn = pCppReturn;
351         }
352         if (pReturnTypeDescr)
353         {
354             typelib_TypeClass eRet = (typelib_TypeClass)pReturnTypeDescr->eTypeClass;
355             TYPELIB_DANGER_RELEASE( pReturnTypeDescr );
356             return eRet;
357         }
358         else
359             return typelib_TypeClass_VOID;
360     }
361 }
362 
363 
364 //==================================================================================================
365 static typelib_TypeClass cpp_mediate(
366     sal_Int32 nFunctionIndex,
367         sal_Int32 nVtableOffset,
368         void ** gpreg, void ** fpreg, void ** ovrflw,
369     sal_Int64 * pRegisterReturn /* space for register return */ )
370 {
371     OSL_ENSURE( sizeof(sal_Int32)==sizeof(void *), "### unexpected!" );
372 
373     // gpreg:  [ret *], this, [other gpr params]
374     // fpreg:  [fpr params]
375     // ovrflw: [gpr or fpr params (properly aligned)]
376 
377         void * pThis;
378         if (nFunctionIndex & 0x80000000 )
379     {
380         nFunctionIndex &= 0x7fffffff;
381         pThis = gpreg[1];
382     }
383     else
384         {
385         pThis = gpreg[0];
386         }
387 
388         pThis = static_cast< char * >(pThis) - nVtableOffset;
389         bridges::cpp_uno::shared::CppInterfaceProxy * pCppI
390           = bridges::cpp_uno::shared::CppInterfaceProxy::castInterfaceToProxy(
391             pThis);
392 
393     typelib_InterfaceTypeDescription * pTypeDescr = pCppI->getTypeDescr();
394 
395     OSL_ENSURE( nFunctionIndex < pTypeDescr->nMapFunctionIndexToMemberIndex, "### illegal vtable index!" );
396     if (nFunctionIndex >= pTypeDescr->nMapFunctionIndexToMemberIndex)
397     {
398         throw RuntimeException(
399             rtl::OUString::createFromAscii("illegal vtable index!"),
400             (XInterface *)pThis );
401     }
402 
403     // determine called method
404     sal_Int32 nMemberPos = pTypeDescr->pMapFunctionIndexToMemberIndex[nFunctionIndex];
405     OSL_ENSURE( nMemberPos < pTypeDescr->nAllMembers, "### illegal member index!" );
406 
407     TypeDescription aMemberDescr( pTypeDescr->ppAllMembers[nMemberPos] );
408 
409     typelib_TypeClass eRet;
410     switch (aMemberDescr.get()->eTypeClass)
411     {
412     case typelib_TypeClass_INTERFACE_ATTRIBUTE:
413     {
414         if (pTypeDescr->pMapMemberIndexToFunctionIndex[nMemberPos] == nFunctionIndex)
415         {
416             // is GET method
417             eRet = cpp2uno_call(
418                 pCppI, aMemberDescr.get(),
419                 ((typelib_InterfaceAttributeTypeDescription *)aMemberDescr.get())->pAttributeTypeRef,
420                 0, 0, // no params
421                 gpreg, fpreg, ovrflw, pRegisterReturn );
422         }
423         else
424         {
425             // is SET method
426             typelib_MethodParameter aParam;
427             aParam.pTypeRef =
428                 ((typelib_InterfaceAttributeTypeDescription *)aMemberDescr.get())->pAttributeTypeRef;
429             aParam.bIn      = sal_True;
430             aParam.bOut     = sal_False;
431 
432             eRet = cpp2uno_call(
433                 pCppI, aMemberDescr.get(),
434                 0, // indicates void return
435                 1, &aParam,
436                 gpreg, fpreg, ovrflw, pRegisterReturn );
437         }
438         break;
439     }
440     case typelib_TypeClass_INTERFACE_METHOD:
441     {
442         // is METHOD
443         switch (nFunctionIndex)
444         {
445         case 1: // acquire()
446             pCppI->acquireProxy(); // non virtual call!
447             eRet = typelib_TypeClass_VOID;
448             break;
449         case 2: // release()
450             pCppI->releaseProxy(); // non virtual call!
451             eRet = typelib_TypeClass_VOID;
452             break;
453         case 0: // queryInterface() opt
454         {
455             typelib_TypeDescription * pTD = 0;
456             TYPELIB_DANGER_GET( &pTD, reinterpret_cast< Type * >( gpreg[2] )->getTypeLibType() );
457             if (pTD)
458             {
459                 XInterface * pInterface = 0;
460                 (*pCppI->getBridge()->getCppEnv()->getRegisteredInterface)(
461                     pCppI->getBridge()->getCppEnv(),
462                     (void **)&pInterface, pCppI->getOid().pData,
463                     (typelib_InterfaceTypeDescription *)pTD );
464 
465                 if (pInterface)
466                 {
467                     ::uno_any_construct(
468                         reinterpret_cast< uno_Any * >( gpreg[0] ),
469                         &pInterface, pTD, cpp_acquire );
470                     pInterface->release();
471                     TYPELIB_DANGER_RELEASE( pTD );
472                     *(void **)pRegisterReturn = gpreg[0];
473                     eRet = typelib_TypeClass_ANY;
474                     break;
475                 }
476                 TYPELIB_DANGER_RELEASE( pTD );
477             }
478         } // else perform queryInterface()
479         default:
480             eRet = cpp2uno_call(
481                 pCppI, aMemberDescr.get(),
482                 ((typelib_InterfaceMethodTypeDescription *)aMemberDescr.get())->pReturnTypeRef,
483                 ((typelib_InterfaceMethodTypeDescription *)aMemberDescr.get())->nParams,
484                 ((typelib_InterfaceMethodTypeDescription *)aMemberDescr.get())->pParams,
485                 gpreg, fpreg, ovrflw, pRegisterReturn );
486         }
487         break;
488     }
489     default:
490     {
491         throw RuntimeException(
492             rtl::OUString::createFromAscii("no member description found!"),
493             (XInterface *)pThis );
494         // is here for dummy
495         eRet = typelib_TypeClass_VOID;
496     }
497     }
498 
499     return eRet;
500 }
501 
502 //==================================================================================================
503 /**
504  * is called on incoming vtable calls
505  * (called by asm snippets)
506  */
507 static void cpp_vtable_call( int nFunctionIndex, int nVtableOffset, void** gpregptr, void** fpregptr, void** ovrflw)
508 {
509         sal_Int32     gpreg[8];
510         memcpy( gpreg, gpregptr, 32);
511 
512 #ifndef __NO_FPRS__
513         double        fpreg[8];
514         memcpy( fpreg, fpregptr, 64);
515 #endif
516 
517     volatile long nRegReturn[2];
518 
519         // fprintf(stderr,"in cpp_vtable_call nFunctionIndex is %x\n",nFunctionIndex);
520         // fprintf(stderr,"in cpp_vtable_call nVtableOffset is %x\n",nVtableOffset);
521         // fflush(stderr);
522 
523     typelib_TypeClass aType =
524              cpp_mediate( nFunctionIndex, nVtableOffset, (void**)gpreg,
525 #ifndef __NO_FPRS__
526                  (void**)fpreg,
527 #else
528                  NULL,
529 #endif
530                  ovrflw, (sal_Int64*)nRegReturn );
531 
532     switch( aType )
533     {
534 
535                 // move return value into register space
536                 // (will be loaded by machine code snippet)
537 
538                 case typelib_TypeClass_BOOLEAN:
539                 case typelib_TypeClass_BYTE:
540                   __asm__( "lbz 3,%0\n\t" : :
541                "m"(nRegReturn[0]) );
542                   break;
543 
544                 case typelib_TypeClass_CHAR:
545                 case typelib_TypeClass_SHORT:
546                 case typelib_TypeClass_UNSIGNED_SHORT:
547                   __asm__( "lhz 3,%0\n\t" : :
548                "m"(nRegReturn[0]) );
549                   break;
550 
551         case typelib_TypeClass_FLOAT:
552 #ifndef __NO_FPRS__
553                   __asm__( "lfs 1,%0\n\t" : :
554                            "m" (*((float*)nRegReturn)) );
555  #else
556                   __asm__( "lwz 3,%0\n\t" : :
557                            "m"(nRegReturn[0]) );
558 #endif
559           break;
560 
561         case typelib_TypeClass_DOUBLE:
562 #ifndef __NO_FPRS__
563           __asm__( "lfd 1,%0\n\t" : :
564                            "m" (*((double*)nRegReturn)) );
565 #else
566           __asm__( "lwz 3,%0\n\t" : :
567                            "m"(nRegReturn[0]) );
568           __asm__( "lwz 4,%0\n\t" : :
569                            "m"(nRegReturn[1]) );
570 #endif
571           break;
572 
573         case typelib_TypeClass_HYPER:
574         case typelib_TypeClass_UNSIGNED_HYPER:
575           __asm__( "lwz 4,%0\n\t" : :
576                            "m"(nRegReturn[1]) );  // fall through
577 
578         default:
579           __asm__( "lwz 3,%0\n\t" : :
580                            "m"(nRegReturn[0]) );
581           break;
582     }
583 }
584 
585 
586 int const codeSnippetSize = 108;
587 
588 unsigned char *  codeSnippet( unsigned char * code, sal_Int32 functionIndex, sal_Int32 vtableOffset,
589                               bool simpleRetType)
590 {
591 
592   // fprintf(stderr,"in codeSnippet functionIndex is %x\n", functionIndex);
593   // fprintf(stderr,"in codeSnippet vtableOffset is %x\n", vtableOffset);
594   // fflush(stderr);
595 
596     if (! simpleRetType )
597         functionIndex |= 0x80000000;
598 
599     unsigned long * p = (unsigned long *) code;
600 
601     // OSL_ASSERT( sizeof (long) == 4 );
602     OSL_ASSERT((((unsigned long)code) & 0x3) == 0 );  //aligned to 4 otherwise a mistake
603 
604     /* generate this code */
605     // # so first save gpr 3 to gpr 10 (aligned to 4)
606     //  stw r3,-2048(r1)
607     //  stw r4,-2044(r1)
608     //  stw r5,-2040(r1)
609     //  stw r6,-2036(r1)
610     //  stw r7,-2032(r1)
611     //  stw r8,-2028(r1)
612     //  stw r9,-2024(r1)
613     //  stw r10,-2020(r1)
614 
615 
616     // # next save fpr 1 to fpr 8 (aligned to 8)
617     // if dedicated floating point registers are used
618     //  stfd    f1,-2016(r1)
619     //  stfd    f2,-2008(r1)
620     //  stfd    f3,-2000(r1)
621     //  stfd    f4,-1992(r1)
622     //  stfd    f5,-1984(r1)
623     //  stfd    f6,-1976(r1)
624     //  stfd    f7,-1968(r1)
625     //  stfd    f8,-1960(r1)
626 
627     // # now here is where cpp_vtable_call must go
628     //  lis r3,-8531
629     //  ori r3,r3,48879
630     //  mtctr   r3
631 
632     // # now load up the functionIndex
633     //  lis r3,-8531
634     //  ori r3,r3,48879
635 
636     // # now load up the vtableOffset
637     //  lis r4,-8531
638     //  ori r4,r4,48879
639 
640     // #now load up the pointer to the saved gpr registers
641     //  addi    r5,r1,-2048
642 
643     // #now load up the pointer to the saved fpr registers
644     //  addi    r6,r1,-2016
645     // if no dedicated floating point registers are used than we have NULL
646     // pointer there
647     //  li      r6, 0
648     //
649 
650     // #now load up the pointer to the overflow call stack
651     //  addi    r7,r1,8
652     //  bctr
653 
654       * p++ = 0x9061f800;
655       * p++ = 0x9081f804;
656       * p++ = 0x90a1f808;
657       * p++ = 0x90c1f80c;
658       * p++ = 0x90e1f810;
659       * p++ = 0x9101f814;
660       * p++ = 0x9121f818;
661       * p++ = 0x9141f81c;
662 #ifndef __NO_FPRS__
663       * p++ = 0xd821f820;
664       * p++ = 0xd841f828;
665       * p++ = 0xd861f830;
666       * p++ = 0xd881f838;
667       * p++ = 0xd8a1f840;
668       * p++ = 0xd8c1f848;
669       * p++ = 0xd8e1f850;
670       * p++ = 0xd901f858;
671 #else
672       /* these nops could be replaced with a smaller codeSnippetSize - 8 * 4 */
673       * p++ = 0x60000000;
674       * p++ = 0x60000000;
675       * p++ = 0x60000000;
676       * p++ = 0x60000000;
677       * p++ = 0x60000000;
678       * p++ = 0x60000000;
679       * p++ = 0x60000000;
680       * p++ = 0x60000000;
681 #endif
682       * p++ = 0x3c600000 | (((unsigned long)cpp_vtable_call) >> 16);
683       * p++ = 0x60630000 | (((unsigned long)cpp_vtable_call) & 0x0000FFFF);
684       * p++ = 0x7c6903a6;
685       * p++ = 0x3c600000 | (((unsigned long)functionIndex) >> 16);
686       * p++ = 0x60630000 | (((unsigned long)functionIndex) & 0x0000FFFF);
687       * p++ = 0x3c800000 | (((unsigned long)vtableOffset) >> 16);
688       * p++ = 0x60840000 | (((unsigned long)vtableOffset) & 0x0000FFFF);
689       * p++ = 0x38a1f800;
690 #ifndef __NO_FPRS__
691       * p++ = 0x38c1f820;
692 #else
693       * p++ = 0x38c00000;
694 #endif
695       * p++ = 0x38e10008;
696       * p++ = 0x4e800420;
697       return (code + codeSnippetSize);
698 
699 }
700 
701 
702 }
703 
704 void bridges::cpp_uno::shared::VtableFactory::flushCode(unsigned char const * bptr, unsigned char const * eptr)
705 {
706     int const lineSize = 32;
707     for (unsigned char const * p = bptr; p < eptr + lineSize; p += lineSize) {
708         __asm__ volatile ("dcbst 0, %0" : : "r"(p) : "memory");
709     }
710     __asm__ volatile ("sync" : : : "memory");
711     for (unsigned char const * p = bptr; p < eptr + lineSize; p += lineSize) {
712         __asm__ volatile ("icbi 0, %0" : : "r"(p) : "memory");
713     }
714     __asm__ volatile ("isync" : : : "memory");
715 }
716 
717 struct bridges::cpp_uno::shared::VtableFactory::Slot { void * fn; };
718 
719 bridges::cpp_uno::shared::VtableFactory::Slot *
720 bridges::cpp_uno::shared::VtableFactory::mapBlockToVtable(void * block)
721 {
722     return static_cast< Slot * >(block) + 2;
723 }
724 
725 sal_Size bridges::cpp_uno::shared::VtableFactory::getBlockSize(
726     sal_Int32 slotCount)
727 {
728     return (slotCount + 2) * sizeof (Slot) + slotCount * codeSnippetSize;
729 }
730 
731 bridges::cpp_uno::shared::VtableFactory::Slot *
732 bridges::cpp_uno::shared::VtableFactory::initializeBlock(
733     void * block, sal_Int32 slotCount)
734 {
735     Slot * slots = mapBlockToVtable(block);
736     slots[-2].fn = 0;
737     slots[-1].fn = 0;
738     return slots + slotCount;
739 }
740 
741 unsigned char * bridges::cpp_uno::shared::VtableFactory::addLocalFunctions(
742     Slot ** slots, unsigned char * code, sal_PtrDiff writetoexecdiff,
743     typelib_InterfaceTypeDescription const * type, sal_Int32 functionOffset,
744     sal_Int32 functionCount, sal_Int32 vtableOffset)
745 {
746      (*slots) -= functionCount;
747      Slot * s = *slots;
748   // fprintf(stderr, "in addLocalFunctions functionOffset is %x\n",functionOffset);
749   // fprintf(stderr, "in addLocalFunctions vtableOffset is %x\n",vtableOffset);
750   // fflush(stderr);
751 
752     for (sal_Int32 i = 0; i < type->nMembers; ++i) {
753         typelib_TypeDescription * member = 0;
754         TYPELIB_DANGER_GET(&member, type->ppMembers[i]);
755         OSL_ASSERT(member != 0);
756         switch (member->eTypeClass) {
757         case typelib_TypeClass_INTERFACE_ATTRIBUTE:
758             // Getter:
759             (s++)->fn = code + writetoexecdiff;
760             code = codeSnippet(
761                 code, functionOffset++, vtableOffset,
762                 bridges::cpp_uno::shared::isSimpleType(
763                     reinterpret_cast<
764                     typelib_InterfaceAttributeTypeDescription * >(
765                         member)->pAttributeTypeRef));
766 
767             // Setter:
768             if (!reinterpret_cast<
769                 typelib_InterfaceAttributeTypeDescription * >(
770                     member)->bReadOnly)
771             {
772                 (s++)->fn = code + writetoexecdiff;
773                 code = codeSnippet(code, functionOffset++, vtableOffset, true);
774             }
775             break;
776 
777         case typelib_TypeClass_INTERFACE_METHOD:
778             (s++)->fn = code + writetoexecdiff;
779             code = codeSnippet(
780                 code, functionOffset++, vtableOffset,
781                 bridges::cpp_uno::shared::isSimpleType(
782                     reinterpret_cast<
783                     typelib_InterfaceMethodTypeDescription * >(
784                         member)->pReturnTypeRef));
785             break;
786 
787         default:
788             OSL_ASSERT(false);
789             break;
790         }
791         TYPELIB_DANGER_RELEASE(member);
792     }
793     return code;
794 }
795 
796