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