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