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