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