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 // This is an implementation of the x86-64 ABI as described in 'System V 32 // Application Binary Interface, AMD64 Architecture Processor Supplement' 33 // (http://www.x86-64.org/documentation/abi-0.95.pdf) 34 // 35 // The code in this file is a modification of src/x86/ffi64.c from libffi 36 // (http://sources.redhat.com/libffi/) which is under the following license: 37 38 /* ----------------------------------------------------------------------- 39 ffi.c - Copyright (c) 2002 Bo Thorsen <bo@suse.de> 40 41 x86-64 Foreign Function Interface 42 43 Permission is hereby granted, free of charge, to any person obtaining 44 a copy of this software and associated documentation files (the 45 ``Software''), to deal in the Software without restriction, including 46 without limitation the rights to use, copy, modify, merge, publish, 47 distribute, sublicense, and/or sell copies of the Software, and to 48 permit persons to whom the Software is furnished to do so, subject to 49 the following conditions: 50 51 The above copyright notice and this permission notice shall be included 52 in all copies or substantial portions of the Software. 53 54 THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS 55 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 56 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 57 IN NO EVENT SHALL CYGNUS SOLUTIONS BE LIABLE FOR ANY CLAIM, DAMAGES OR 58 OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 59 ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 60 OTHER DEALINGS IN THE SOFTWARE. 61 ----------------------------------------------------------------------- */ 62 63 #include <abi.hxx> 64 65 #include <rtl/ustring.hxx> 66 67 using namespace x86_64; 68 69 typedef struct 70 { 71 /* Registers for argument passing. */ 72 long gpr[MAX_GPR_REGS]; 73 __int128_t sse[MAX_SSE_REGS]; 74 75 /* Stack space for arguments. */ 76 char argspace[0]; 77 } stackLayout; 78 79 /* Register class used for passing given 64bit part of the argument. 80 These represent classes as documented by the PS ABI, with the exception 81 of SSESF, SSEDF classes, that are basically SSE class, just gcc will 82 use SF or DFmode move instead of DImode to avoid reformating penalties. 83 84 Similary we play games with INTEGERSI_CLASS to use cheaper SImode moves 85 whenever possible (upper half does contain padding). 86 */ 87 enum x86_64_reg_class 88 { 89 X86_64_NO_CLASS, 90 X86_64_INTEGER_CLASS, 91 X86_64_INTEGERSI_CLASS, 92 X86_64_SSE_CLASS, 93 X86_64_SSESF_CLASS, 94 X86_64_SSEDF_CLASS, 95 X86_64_SSEUP_CLASS, 96 X86_64_X87_CLASS, 97 X86_64_X87UP_CLASS, 98 X86_64_MEMORY_CLASS 99 }; 100 101 #define MAX_CLASSES 4 102 103 /* x86-64 register passing implementation. See x86-64 ABI for details. Goal 104 of this code is to classify each 8bytes of incoming argument by the register 105 class and assign registers accordingly. */ 106 107 /* Return the union class of CLASS1 and CLASS2. 108 See the x86-64 PS ABI for details. */ 109 110 static enum x86_64_reg_class 111 merge_classes (enum x86_64_reg_class class1, enum x86_64_reg_class class2) 112 { 113 /* Rule #1: If both classes are equal, this is the resulting class. */ 114 if (class1 == class2) 115 return class1; 116 117 /* Rule #2: If one of the classes is NO_CLASS, the resulting class is 118 the other class. */ 119 if (class1 == X86_64_NO_CLASS) 120 return class2; 121 if (class2 == X86_64_NO_CLASS) 122 return class1; 123 124 /* Rule #3: If one of the classes is MEMORY, the result is MEMORY. */ 125 if (class1 == X86_64_MEMORY_CLASS || class2 == X86_64_MEMORY_CLASS) 126 return X86_64_MEMORY_CLASS; 127 128 /* Rule #4: If one of the classes is INTEGER, the result is INTEGER. */ 129 if ((class1 == X86_64_INTEGERSI_CLASS && class2 == X86_64_SSESF_CLASS) 130 || (class2 == X86_64_INTEGERSI_CLASS && class1 == X86_64_SSESF_CLASS)) 131 return X86_64_INTEGERSI_CLASS; 132 if (class1 == X86_64_INTEGER_CLASS || class1 == X86_64_INTEGERSI_CLASS 133 || class2 == X86_64_INTEGER_CLASS || class2 == X86_64_INTEGERSI_CLASS) 134 return X86_64_INTEGER_CLASS; 135 136 /* Rule #5: If one of the classes is X87 or X87UP class, MEMORY is used. */ 137 if (class1 == X86_64_X87_CLASS || class1 == X86_64_X87UP_CLASS 138 || class2 == X86_64_X87_CLASS || class2 == X86_64_X87UP_CLASS) 139 return X86_64_MEMORY_CLASS; 140 141 /* Rule #6: Otherwise class SSE is used. */ 142 return X86_64_SSE_CLASS; 143 } 144 145 /* Classify the argument of type TYPE and mode MODE. 146 CLASSES will be filled by the register class used to pass each word 147 of the operand. The number of words is returned. In case the parameter 148 should be passed in memory, 0 is returned. As a special case for zero 149 sized containers, classes[0] will be NO_CLASS and 1 is returned. 150 151 See the x86-64 PS ABI for details. 152 */ 153 static int 154 classify_argument( typelib_TypeDescriptionReference *pTypeRef, enum x86_64_reg_class classes[], int byteOffset ) 155 { 156 switch ( pTypeRef->eTypeClass ) 157 { 158 case typelib_TypeClass_VOID: 159 classes[0] = X86_64_NO_CLASS; 160 return 1; 161 case typelib_TypeClass_CHAR: 162 case typelib_TypeClass_BOOLEAN: 163 case typelib_TypeClass_BYTE: 164 case typelib_TypeClass_SHORT: 165 case typelib_TypeClass_UNSIGNED_SHORT: 166 case typelib_TypeClass_LONG: 167 case typelib_TypeClass_UNSIGNED_LONG: 168 case typelib_TypeClass_HYPER: 169 case typelib_TypeClass_UNSIGNED_HYPER: 170 case typelib_TypeClass_ENUM: 171 if ( ( byteOffset % 8 + pTypeRef->pType->nSize ) <= 4 ) 172 classes[0] = X86_64_INTEGERSI_CLASS; 173 else 174 classes[0] = X86_64_INTEGER_CLASS; 175 return 1; 176 case typelib_TypeClass_FLOAT: 177 if ( ( byteOffset % 8 ) == 0 ) 178 classes[0] = X86_64_SSESF_CLASS; 179 else 180 classes[0] = X86_64_SSE_CLASS; 181 return 1; 182 case typelib_TypeClass_DOUBLE: 183 classes[0] = X86_64_SSEDF_CLASS; 184 return 1; 185 /*case LONGDOUBLE: 186 classes[0] = X86_64_X87_CLASS; 187 classes[1] = X86_64_X87UP_CLASS; 188 return 2;*/ 189 case typelib_TypeClass_STRING: 190 case typelib_TypeClass_TYPE: 191 case typelib_TypeClass_ANY: 192 case typelib_TypeClass_TYPEDEF: 193 case typelib_TypeClass_UNION: 194 case typelib_TypeClass_SEQUENCE: 195 case typelib_TypeClass_ARRAY: 196 case typelib_TypeClass_INTERFACE: 197 return 0; 198 case typelib_TypeClass_STRUCT: 199 case typelib_TypeClass_EXCEPTION: 200 { 201 typelib_TypeDescription * pTypeDescr = 0; 202 TYPELIB_DANGER_GET( &pTypeDescr, pTypeRef ); 203 204 const int UNITS_PER_WORD = 8; 205 int words = ( pTypeDescr->nSize + UNITS_PER_WORD - 1 ) / UNITS_PER_WORD; 206 enum x86_64_reg_class subclasses[MAX_CLASSES]; 207 208 /* If the struct is larger than 16 bytes, pass it on the stack. */ 209 if ( pTypeDescr->nSize > 16 ) 210 { 211 TYPELIB_DANGER_RELEASE( pTypeDescr ); 212 return 0; 213 } 214 215 for ( int i = 0; i < words; i++ ) 216 classes[i] = X86_64_NO_CLASS; 217 218 const typelib_CompoundTypeDescription *pStruct = reinterpret_cast<const typelib_CompoundTypeDescription*>( pTypeDescr ); 219 220 /* Merge the fields of structure. */ 221 for ( sal_Int32 nMember = 0; nMember < pStruct->nMembers; ++nMember ) 222 { 223 typelib_TypeDescriptionReference *pTypeInStruct = pStruct->ppTypeRefs[ nMember ]; 224 int offset = byteOffset + pStruct->pMemberOffsets[ nMember ]; 225 226 int num = classify_argument( pTypeInStruct, subclasses, offset ); 227 228 if ( num == 0 ) 229 { 230 TYPELIB_DANGER_RELEASE( pTypeDescr ); 231 return 0; 232 } 233 234 for ( int i = 0; i < num; i++ ) 235 { 236 int pos = offset / 8; 237 classes[i + pos] = merge_classes( subclasses[i], classes[i + pos] ); 238 } 239 } 240 241 TYPELIB_DANGER_RELEASE( pTypeDescr ); 242 243 /* Final merger cleanup. */ 244 for ( int i = 0; i < words; i++ ) 245 { 246 /* If one class is MEMORY, everything should be passed in 247 memory. */ 248 if ( classes[i] == X86_64_MEMORY_CLASS ) 249 return 0; 250 251 /* The X86_64_SSEUP_CLASS should be always preceded by 252 X86_64_SSE_CLASS. */ 253 if ( classes[i] == X86_64_SSEUP_CLASS 254 && ( i == 0 || classes[i - 1] != X86_64_SSE_CLASS ) ) 255 classes[i] = X86_64_SSE_CLASS; 256 257 /* X86_64_X87UP_CLASS should be preceded by X86_64_X87_CLASS. */ 258 if ( classes[i] == X86_64_X87UP_CLASS 259 && ( i == 0 || classes[i - 1] != X86_64_X87_CLASS ) ) 260 classes[i] = X86_64_SSE_CLASS; 261 } 262 return words; 263 } 264 265 default: 266 #if OSL_DEBUG_LEVEL > 1 267 OSL_TRACE( "Unhandled case: pType->eTypeClass == %d\n", pTypeRef->eTypeClass ); 268 #endif 269 OSL_ASSERT(0); 270 } 271 return 0; /* Never reached. */ 272 } 273 274 /* Examine the argument and return set number of register required in each 275 class. Return 0 iff parameter should be passed in memory. */ 276 bool x86_64::examine_argument( typelib_TypeDescriptionReference *pTypeRef, bool bInReturn, int &nUsedGPR, int &nUsedSSE ) 277 { 278 enum x86_64_reg_class classes[MAX_CLASSES]; 279 int n; 280 281 n = classify_argument( pTypeRef, classes, 0 ); 282 283 if ( n == 0 ) 284 return false; 285 286 nUsedGPR = 0; 287 nUsedSSE = 0; 288 for ( n--; n >= 0; n-- ) 289 switch ( classes[n] ) 290 { 291 case X86_64_INTEGER_CLASS: 292 case X86_64_INTEGERSI_CLASS: 293 nUsedGPR++; 294 break; 295 case X86_64_SSE_CLASS: 296 case X86_64_SSESF_CLASS: 297 case X86_64_SSEDF_CLASS: 298 nUsedSSE++; 299 break; 300 case X86_64_NO_CLASS: 301 case X86_64_SSEUP_CLASS: 302 break; 303 case X86_64_X87_CLASS: 304 case X86_64_X87UP_CLASS: 305 if ( !bInReturn ) 306 return false; 307 break; 308 default: 309 #if OSL_DEBUG_LEVEL > 1 310 OSL_TRACE( "Unhandled case: classes[n] == %d\n", classes[n] ); 311 #endif 312 OSL_ASSERT(0); 313 } 314 return true; 315 } 316 317 bool x86_64::return_in_hidden_param( typelib_TypeDescriptionReference *pTypeRef ) 318 { 319 int g, s; 320 321 return examine_argument( pTypeRef, true, g, s ) == 0; 322 } 323 324 void x86_64::fill_struct( typelib_TypeDescriptionReference *pTypeRef, const sal_uInt64 *pGPR, const double *pSSE, void *pStruct ) 325 { 326 enum x86_64_reg_class classes[MAX_CLASSES]; 327 int n; 328 329 n = classify_argument( pTypeRef, classes, 0 ); 330 331 sal_uInt64 *pStructAlign = reinterpret_cast<sal_uInt64 *>( pStruct ); 332 for ( n--; n >= 0; n-- ) 333 switch ( classes[n] ) 334 { 335 case X86_64_INTEGER_CLASS: 336 case X86_64_INTEGERSI_CLASS: 337 *pStructAlign++ = *pGPR++; 338 break; 339 case X86_64_SSE_CLASS: 340 case X86_64_SSESF_CLASS: 341 case X86_64_SSEDF_CLASS: 342 *pStructAlign++ = *reinterpret_cast<const sal_uInt64 *>( pSSE++ ); 343 break; 344 default: 345 break; 346 } 347 } 348 349 #if 0 350 351 /* Functions to load floats and double to an SSE register placeholder. */ 352 extern void float2sse (float, __int128_t *); 353 extern void double2sse (double, __int128_t *); 354 extern void floatfloat2sse (void *, __int128_t *); 355 356 /* Functions to put the floats and doubles back. */ 357 extern float sse2float (__int128_t *); 358 extern double sse2double (__int128_t *); 359 extern void sse2floatfloat(__int128_t *, void *); 360 361 /*@-exportheader@*/ 362 void 363 ffi_prep_args (stackLayout *stack, extended_cif *ecif) 364 /*@=exportheader@*/ 365 { 366 int gprcount, ssecount, i, g, s; 367 void **p_argv; 368 void *argp = &stack->argspace; 369 ffi_type **p_arg; 370 371 /* First check if the return value should be passed in memory. If so, 372 pass the pointer as the first argument. */ 373 gprcount = ssecount = 0; 374 if (ecif->cif->rtype->type != FFI_TYPE_VOID 375 && examine_argument (ecif->cif->rtype, 1, &g, &s) == 0) 376 (void *)stack->gpr[gprcount++] = ecif->rvalue; 377 378 for (i=ecif->cif->nargs, p_arg=ecif->cif->arg_types, p_argv = ecif->avalue; 379 i!=0; i--, p_arg++, p_argv++) 380 { 381 int in_register = 0; 382 383 switch ((*p_arg)->type) 384 { 385 case FFI_TYPE_SINT8: 386 case FFI_TYPE_SINT16: 387 case FFI_TYPE_SINT32: 388 case FFI_TYPE_SINT64: 389 case FFI_TYPE_UINT8: 390 case FFI_TYPE_UINT16: 391 case FFI_TYPE_UINT32: 392 case FFI_TYPE_UINT64: 393 case FFI_TYPE_POINTER: 394 if (gprcount < MAX_GPR_REGS) 395 { 396 stack->gpr[gprcount] = 0; 397 stack->gpr[gprcount++] = *(long long *)(*p_argv); 398 in_register = 1; 399 } 400 break; 401 402 case FFI_TYPE_FLOAT: 403 if (ssecount < MAX_SSE_REGS) 404 { 405 float2sse (*(float *)(*p_argv), &stack->sse[ssecount++]); 406 in_register = 1; 407 } 408 break; 409 410 case FFI_TYPE_DOUBLE: 411 if (ssecount < MAX_SSE_REGS) 412 { 413 double2sse (*(double *)(*p_argv), &stack->sse[ssecount++]); 414 in_register = 1; 415 } 416 break; 417 } 418 419 if (in_register) 420 continue; 421 422 /* Either all places in registers where filled, or this is a 423 type that potentially goes into a memory slot. */ 424 if (examine_argument (*p_arg, 0, &g, &s) == 0 425 || gprcount + g > MAX_GPR_REGS || ssecount + s > MAX_SSE_REGS) 426 { 427 /* Pass this argument in memory. */ 428 argp = (void *)ALIGN(argp, (*p_arg)->alignment); 429 memcpy (argp, *p_argv, (*p_arg)->size); 430 argp += (*p_arg)->size; 431 } 432 else 433 { 434 /* All easy cases are eliminated. Now fire the big guns. */ 435 436 enum x86_64_reg_class classes[MAX_CLASSES]; 437 int j, num; 438 void *a; 439 440 num = classify_argument (*p_arg, classes, 0); 441 for (j=0, a=*p_argv; j<num; j++, a+=8) 442 { 443 switch (classes[j]) 444 { 445 case X86_64_INTEGER_CLASS: 446 case X86_64_INTEGERSI_CLASS: 447 stack->gpr[gprcount++] = *(long long *)a; 448 break; 449 case X86_64_SSE_CLASS: 450 floatfloat2sse (a, &stack->sse[ssecount++]); 451 break; 452 case X86_64_SSESF_CLASS: 453 float2sse (*(float *)a, &stack->sse[ssecount++]); 454 break; 455 case X86_64_SSEDF_CLASS: 456 double2sse (*(double *)a, &stack->sse[ssecount++]); 457 break; 458 default: 459 abort(); 460 } 461 } 462 } 463 } 464 } 465 466 /* Perform machine dependent cif processing. */ 467 ffi_status 468 ffi_prep_cif_machdep (ffi_cif *cif) 469 { 470 int gprcount, ssecount, i, g, s; 471 472 gprcount = ssecount = 0; 473 474 /* Reset the byte count. We handle this size estimation here. */ 475 cif->bytes = 0; 476 477 /* If the return value should be passed in memory, pass the pointer 478 as the first argument. The actual memory isn't allocated here. */ 479 if (cif->rtype->type != FFI_TYPE_VOID 480 && examine_argument (cif->rtype, 1, &g, &s) == 0) 481 gprcount = 1; 482 483 /* Go over all arguments and determine the way they should be passed. 484 If it's in a register and there is space for it, let that be so. If 485 not, add it's size to the stack byte count. */ 486 for (i=0; i<cif->nargs; i++) 487 { 488 if (examine_argument (cif->arg_types[i], 0, &g, &s) == 0 489 || gprcount + g > MAX_GPR_REGS || ssecount + s > MAX_SSE_REGS) 490 { 491 /* This is passed in memory. First align to the basic type. */ 492 cif->bytes = ALIGN(cif->bytes, cif->arg_types[i]->alignment); 493 494 /* Stack arguments are *always* at least 8 byte aligned. */ 495 cif->bytes = ALIGN(cif->bytes, 8); 496 497 /* Now add the size of this argument. */ 498 cif->bytes += cif->arg_types[i]->size; 499 } 500 else 501 { 502 gprcount += g; 503 ssecount += s; 504 } 505 } 506 507 /* Set the flag for the closures return. */ 508 switch (cif->rtype->type) 509 { 510 case FFI_TYPE_VOID: 511 case FFI_TYPE_STRUCT: 512 case FFI_TYPE_SINT64: 513 case FFI_TYPE_FLOAT: 514 case FFI_TYPE_DOUBLE: 515 case FFI_TYPE_LONGDOUBLE: 516 cif->flags = (unsigned) cif->rtype->type; 517 break; 518 519 case FFI_TYPE_UINT64: 520 cif->flags = FFI_TYPE_SINT64; 521 break; 522 523 default: 524 cif->flags = FFI_TYPE_INT; 525 break; 526 } 527 528 return FFI_OK; 529 } 530 531 typedef struct 532 { 533 long gpr[2]; 534 __int128_t sse[2]; 535 long double st0; 536 } return_value; 537 538 //#endif 539 540 void 541 ffi_fill_return_value (return_value *rv, extended_cif *ecif) 542 { 543 enum x86_64_reg_class classes[MAX_CLASSES]; 544 int i = 0, num; 545 long *gpr = rv->gpr; 546 __int128_t *sse = rv->sse; 547 signed char sc; 548 signed short ss; 549 550 /* This is needed because of the way x86-64 handles signed short 551 integers. */ 552 switch (ecif->cif->rtype->type) 553 { 554 case FFI_TYPE_SINT8: 555 sc = *(signed char *)gpr; 556 *(long long *)ecif->rvalue = (long long)sc; 557 return; 558 case FFI_TYPE_SINT16: 559 ss = *(signed short *)gpr; 560 *(long long *)ecif->rvalue = (long long)ss; 561 return; 562 default: 563 /* Just continue. */ 564 ; 565 } 566 567 num = classify_argument (ecif->cif->rtype, classes, 0); 568 569 if (num == 0) 570 /* Return in memory. */ 571 ecif->rvalue = (void *) rv->gpr[0]; 572 else if (num == 2 && classes[0] == X86_64_X87_CLASS && 573 classes[1] == X86_64_X87UP_CLASS) 574 /* This is a long double (this is easiest to handle this way instead 575 of an eightbyte at a time as in the loop below. */ 576 *((long double *)ecif->rvalue) = rv->st0; 577 else 578 { 579 void *a; 580 581 for (i=0, a=ecif->rvalue; i<num; i++, a+=8) 582 { 583 switch (classes[i]) 584 { 585 case X86_64_INTEGER_CLASS: 586 case X86_64_INTEGERSI_CLASS: 587 *(long long *)a = *gpr; 588 gpr++; 589 break; 590 case X86_64_SSE_CLASS: 591 sse2floatfloat (sse++, a); 592 break; 593 case X86_64_SSESF_CLASS: 594 *(float *)a = sse2float (sse++); 595 break; 596 case X86_64_SSEDF_CLASS: 597 *(double *)a = sse2double (sse++); 598 break; 599 default: 600 abort(); 601 } 602 } 603 } 604 } 605 606 //#if 0 607 608 /*@-declundef@*/ 609 /*@-exportheader@*/ 610 extern void ffi_call_UNIX64(void (*)(stackLayout *, extended_cif *), 611 void (*) (return_value *, extended_cif *), 612 /*@out@*/ extended_cif *, 613 unsigned, /*@out@*/ unsigned *, void (*fn)()); 614 /*@=declundef@*/ 615 /*@=exportheader@*/ 616 617 void ffi_call(/*@dependent@*/ ffi_cif *cif, 618 void (*fn)(), 619 /*@out@*/ void *rvalue, 620 /*@dependent@*/ void **avalue) 621 { 622 extended_cif ecif; 623 int dummy; 624 625 ecif.cif = cif; 626 ecif.avalue = avalue; 627 628 /* If the return value is a struct and we don't have a return */ 629 /* value address then we need to make one */ 630 631 if ((rvalue == NULL) && 632 (examine_argument (cif->rtype, 1, &dummy, &dummy) == 0)) 633 { 634 /*@-sysunrecog@*/ 635 ecif.rvalue = alloca(cif->rtype->size); 636 /*@=sysunrecog@*/ 637 } 638 else 639 ecif.rvalue = rvalue; 640 641 /* Stack must always be 16byte aligned. Make it so. */ 642 cif->bytes = ALIGN(cif->bytes, 16); 643 644 switch (cif->abi) 645 { 646 case FFI_SYSV: 647 /* Calling 32bit code from 64bit is not possible */ 648 FFI_ASSERT(0); 649 break; 650 651 case FFI_UNIX64: 652 /*@-usedef@*/ 653 ffi_call_UNIX64 (ffi_prep_args, ffi_fill_return_value, &ecif, 654 cif->bytes, ecif.rvalue, fn); 655 /*@=usedef@*/ 656 break; 657 658 default: 659 FFI_ASSERT(0); 660 break; 661 } 662 } 663 664 extern void ffi_closure_UNIX64(void); 665 666 ffi_status 667 ffi_prep_closure (ffi_closure* closure, 668 ffi_cif* cif, 669 void (*fun)(ffi_cif*, void*, void**, void*), 670 void *user_data) 671 { 672 volatile unsigned short *tramp; 673 674 /* FFI_ASSERT (cif->abi == FFI_OSF); */ 675 676 tramp = (volatile unsigned short *) &closure->tramp[0]; 677 tramp[0] = 0xbb49; /* mov <code>, %r11 */ 678 tramp[5] = 0xba49; /* mov <data>, %r10 */ 679 tramp[10] = 0xff49; /* jmp *%r11 */ 680 tramp[11] = 0x00e3; 681 *(void * volatile *) &tramp[1] = ffi_closure_UNIX64; 682 *(void * volatile *) &tramp[6] = closure; 683 684 closure->cif = cif; 685 closure->fun = fun; 686 closure->user_data = user_data; 687 688 return FFI_OK; 689 } 690 691 int 692 ffi_closure_UNIX64_inner(ffi_closure *closure, va_list l, void *rp) 693 { 694 ffi_cif *cif; 695 void **avalue; 696 ffi_type **arg_types; 697 long i, avn, argn; 698 699 cif = closure->cif; 700 avalue = alloca(cif->nargs * sizeof(void *)); 701 702 argn = 0; 703 704 i = 0; 705 avn = cif->nargs; 706 arg_types = cif->arg_types; 707 708 /* Grab the addresses of the arguments from the stack frame. */ 709 while (i < avn) 710 { 711 switch (arg_types[i]->type) 712 { 713 case FFI_TYPE_SINT8: 714 case FFI_TYPE_UINT8: 715 case FFI_TYPE_SINT16: 716 case FFI_TYPE_UINT16: 717 case FFI_TYPE_SINT32: 718 case FFI_TYPE_UINT32: 719 case FFI_TYPE_SINT64: 720 case FFI_TYPE_UINT64: 721 case FFI_TYPE_POINTER: 722 { 723 if (l->gp_offset > 48-8) 724 { 725 avalue[i] = l->overflow_arg_area; 726 l->overflow_arg_area = (char *)l->overflow_arg_area + 8; 727 } 728 else 729 { 730 avalue[i] = (char *)l->reg_save_area + l->gp_offset; 731 l->gp_offset += 8; 732 } 733 } 734 break; 735 736 case FFI_TYPE_STRUCT: 737 /* FIXME */ 738 FFI_ASSERT(0); 739 break; 740 741 case FFI_TYPE_DOUBLE: 742 { 743 if (l->fp_offset > 176-16) 744 { 745 avalue[i] = l->overflow_arg_area; 746 l->overflow_arg_area = (char *)l->overflow_arg_area + 8; 747 } 748 else 749 { 750 avalue[i] = (char *)l->reg_save_area + l->fp_offset; 751 l->fp_offset += 16; 752 } 753 } 754 #if DEBUG_FFI 755 fprintf (stderr, "double arg %d = %g\n", i, *(double *)avalue[i]); 756 #endif 757 break; 758 759 case FFI_TYPE_FLOAT: 760 { 761 if (l->fp_offset > 176-16) 762 { 763 avalue[i] = l->overflow_arg_area; 764 l->overflow_arg_area = (char *)l->overflow_arg_area + 8; 765 } 766 else 767 { 768 avalue[i] = (char *)l->reg_save_area + l->fp_offset; 769 l->fp_offset += 16; 770 } 771 } 772 #if DEBUG_FFI 773 fprintf (stderr, "float arg %d = %g\n", i, *(float *)avalue[i]); 774 #endif 775 break; 776 777 default: 778 FFI_ASSERT(0); 779 } 780 781 argn += ALIGN(arg_types[i]->size, SIZEOF_ARG) / SIZEOF_ARG; 782 i++; 783 } 784 785 /* Invoke the closure. */ 786 (closure->fun) (cif, rp, avalue, closure->user_data); 787 788 /* FIXME: Structs not supported. */ 789 FFI_ASSERT(cif->rtype->type != FFI_TYPE_STRUCT); 790 791 /* Tell ffi_closure_UNIX64 how to perform return type promotions. */ 792 793 return cif->rtype->type; 794 } 795 796 #endif 797