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