1 /* ----------------------------------------------------------------------- 2 ffi.c - Copyright (c) 2000, 2007 Software AG 3 Copyright (c) 2008 Red Hat, Inc 4 5 S390 Foreign Function Interface 6 7 Permission is hereby granted, free of charge, to any person obtaining 8 a copy of this software and associated documentation files (the 9 ``Software''), to deal in the Software without restriction, including 10 without limitation the rights to use, copy, modify, merge, publish, 11 distribute, sublicense, and/or sell copies of the Software, and to 12 permit persons to whom the Software is furnished to do so, subject to 13 the following conditions: 14 15 The above copyright notice and this permission notice shall be included 16 in all copies or substantial portions of the Software. 17 18 THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS 19 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 20 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 21 IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR 22 OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 23 ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 24 OTHER DEALINGS IN THE SOFTWARE. 25 ----------------------------------------------------------------------- */ 26 /*====================================================================*/ 27 /* Includes */ 28 /* -------- */ 29 /*====================================================================*/ 30 31 #include <ffi.h> 32 #include <ffi_common.h> 33 34 #include <stdlib.h> 35 #include <stdio.h> 36 37 /*====================== End of Includes =============================*/ 38 39 /*====================================================================*/ 40 /* Defines */ 41 /* ------- */ 42 /*====================================================================*/ 43 44 /* Maximum number of GPRs available for argument passing. */ 45 #define MAX_GPRARGS 5 46 47 /* Maximum number of FPRs available for argument passing. */ 48 #ifdef __s390x__ 49 #define MAX_FPRARGS 4 50 #else 51 #define MAX_FPRARGS 2 52 #endif 53 54 /* Round to multiple of 16. */ 55 #define ROUND_SIZE(size) (((size) + 15) & ~15) 56 57 /* If these values change, sysv.S must be adapted! */ 58 #define FFI390_RET_VOID 0 59 #define FFI390_RET_STRUCT 1 60 #define FFI390_RET_FLOAT 2 61 #define FFI390_RET_DOUBLE 3 62 #define FFI390_RET_INT32 4 63 #define FFI390_RET_INT64 5 64 65 /*===================== End of Defines ===============================*/ 66 67 /*====================================================================*/ 68 /* Prototypes */ 69 /* ---------- */ 70 /*====================================================================*/ 71 72 static void ffi_prep_args (unsigned char *, extended_cif *); 73 void 74 #if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ > 2) 75 __attribute__ ((visibility ("hidden"))) 76 #endif 77 ffi_closure_helper_SYSV (ffi_closure *, unsigned long *, 78 unsigned long long *, unsigned long *); 79 80 /*====================== End of Prototypes ===========================*/ 81 82 /*====================================================================*/ 83 /* Externals */ 84 /* --------- */ 85 /*====================================================================*/ 86 87 extern void ffi_call_SYSV(unsigned, 88 extended_cif *, 89 void (*)(unsigned char *, extended_cif *), 90 unsigned, 91 void *, 92 void (*fn)(void)); 93 94 extern void ffi_closure_SYSV(void); 95 96 /*====================== End of Externals ============================*/ 97 98 /*====================================================================*/ 99 /* */ 100 /* Name - ffi_check_struct_type. */ 101 /* */ 102 /* Function - Determine if a structure can be passed within a */ 103 /* general purpose or floating point register. */ 104 /* */ 105 /*====================================================================*/ 106 107 static int 108 ffi_check_struct_type (ffi_type *arg) 109 { 110 size_t size = arg->size; 111 112 /* If the struct has just one element, look at that element 113 to find out whether to consider the struct as floating point. */ 114 while (arg->type == FFI_TYPE_STRUCT 115 && arg->elements[0] && !arg->elements[1]) 116 arg = arg->elements[0]; 117 118 /* Structs of size 1, 2, 4, and 8 are passed in registers, 119 just like the corresponding int/float types. */ 120 switch (size) 121 { 122 case 1: 123 return FFI_TYPE_UINT8; 124 125 case 2: 126 return FFI_TYPE_UINT16; 127 128 case 4: 129 if (arg->type == FFI_TYPE_FLOAT) 130 return FFI_TYPE_FLOAT; 131 else 132 return FFI_TYPE_UINT32; 133 134 case 8: 135 if (arg->type == FFI_TYPE_DOUBLE) 136 return FFI_TYPE_DOUBLE; 137 else 138 return FFI_TYPE_UINT64; 139 140 default: 141 break; 142 } 143 144 /* Other structs are passed via a pointer to the data. */ 145 return FFI_TYPE_POINTER; 146 } 147 148 /*======================== End of Routine ============================*/ 149 150 /*====================================================================*/ 151 /* */ 152 /* Name - ffi_prep_args. */ 153 /* */ 154 /* Function - Prepare parameters for call to function. */ 155 /* */ 156 /* ffi_prep_args is called by the assembly routine once stack space */ 157 /* has been allocated for the function's arguments. */ 158 /* */ 159 /*====================================================================*/ 160 161 static void 162 ffi_prep_args (unsigned char *stack, extended_cif *ecif) 163 { 164 /* The stack space will be filled with those areas: 165 166 FPR argument register save area (highest addresses) 167 GPR argument register save area 168 temporary struct copies 169 overflow argument area (lowest addresses) 170 171 We set up the following pointers: 172 173 p_fpr: bottom of the FPR area (growing upwards) 174 p_gpr: bottom of the GPR area (growing upwards) 175 p_ov: bottom of the overflow area (growing upwards) 176 p_struct: top of the struct copy area (growing downwards) 177 178 All areas are kept aligned to twice the word size. */ 179 180 int gpr_off = ecif->cif->bytes; 181 int fpr_off = gpr_off + ROUND_SIZE (MAX_GPRARGS * sizeof (long)); 182 183 unsigned long long *p_fpr = (unsigned long long *)(stack + fpr_off); 184 unsigned long *p_gpr = (unsigned long *)(stack + gpr_off); 185 unsigned char *p_struct = (unsigned char *)p_gpr; 186 unsigned long *p_ov = (unsigned long *)stack; 187 188 int n_fpr = 0; 189 int n_gpr = 0; 190 int n_ov = 0; 191 192 ffi_type **ptr; 193 void **p_argv = ecif->avalue; 194 int i; 195 196 /* If we returning a structure then we set the first parameter register 197 to the address of where we are returning this structure. */ 198 199 if (ecif->cif->flags == FFI390_RET_STRUCT) 200 p_gpr[n_gpr++] = (unsigned long) ecif->rvalue; 201 202 /* Now for the arguments. */ 203 204 for (ptr = ecif->cif->arg_types, i = ecif->cif->nargs; 205 i > 0; 206 i--, ptr++, p_argv++) 207 { 208 void *arg = *p_argv; 209 int type = (*ptr)->type; 210 211 #if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE 212 /* 16-byte long double is passed like a struct. */ 213 if (type == FFI_TYPE_LONGDOUBLE) 214 type = FFI_TYPE_STRUCT; 215 #endif 216 217 /* Check how a structure type is passed. */ 218 if (type == FFI_TYPE_STRUCT) 219 { 220 type = ffi_check_struct_type (*ptr); 221 222 /* If we pass the struct via pointer, copy the data. */ 223 if (type == FFI_TYPE_POINTER) 224 { 225 p_struct -= ROUND_SIZE ((*ptr)->size); 226 memcpy (p_struct, (char *)arg, (*ptr)->size); 227 arg = &p_struct; 228 } 229 } 230 231 /* Now handle all primitive int/pointer/float data types. */ 232 switch (type) 233 { 234 case FFI_TYPE_DOUBLE: 235 if (n_fpr < MAX_FPRARGS) 236 p_fpr[n_fpr++] = *(unsigned long long *) arg; 237 else 238 #ifdef __s390x__ 239 p_ov[n_ov++] = *(unsigned long *) arg; 240 #else 241 p_ov[n_ov++] = ((unsigned long *) arg)[0], 242 p_ov[n_ov++] = ((unsigned long *) arg)[1]; 243 #endif 244 break; 245 246 case FFI_TYPE_FLOAT: 247 if (n_fpr < MAX_FPRARGS) 248 p_fpr[n_fpr++] = (long long) *(unsigned int *) arg << 32; 249 else 250 p_ov[n_ov++] = *(unsigned int *) arg; 251 break; 252 253 case FFI_TYPE_POINTER: 254 if (n_gpr < MAX_GPRARGS) 255 p_gpr[n_gpr++] = (unsigned long)*(unsigned char **) arg; 256 else 257 p_ov[n_ov++] = (unsigned long)*(unsigned char **) arg; 258 break; 259 260 case FFI_TYPE_UINT64: 261 case FFI_TYPE_SINT64: 262 #ifdef __s390x__ 263 if (n_gpr < MAX_GPRARGS) 264 p_gpr[n_gpr++] = *(unsigned long *) arg; 265 else 266 p_ov[n_ov++] = *(unsigned long *) arg; 267 #else 268 if (n_gpr == MAX_GPRARGS-1) 269 n_gpr = MAX_GPRARGS; 270 if (n_gpr < MAX_GPRARGS) 271 p_gpr[n_gpr++] = ((unsigned long *) arg)[0], 272 p_gpr[n_gpr++] = ((unsigned long *) arg)[1]; 273 else 274 p_ov[n_ov++] = ((unsigned long *) arg)[0], 275 p_ov[n_ov++] = ((unsigned long *) arg)[1]; 276 #endif 277 break; 278 279 case FFI_TYPE_UINT32: 280 if (n_gpr < MAX_GPRARGS) 281 p_gpr[n_gpr++] = *(unsigned int *) arg; 282 else 283 p_ov[n_ov++] = *(unsigned int *) arg; 284 break; 285 286 case FFI_TYPE_INT: 287 case FFI_TYPE_SINT32: 288 if (n_gpr < MAX_GPRARGS) 289 p_gpr[n_gpr++] = *(signed int *) arg; 290 else 291 p_ov[n_ov++] = *(signed int *) arg; 292 break; 293 294 case FFI_TYPE_UINT16: 295 if (n_gpr < MAX_GPRARGS) 296 p_gpr[n_gpr++] = *(unsigned short *) arg; 297 else 298 p_ov[n_ov++] = *(unsigned short *) arg; 299 break; 300 301 case FFI_TYPE_SINT16: 302 if (n_gpr < MAX_GPRARGS) 303 p_gpr[n_gpr++] = *(signed short *) arg; 304 else 305 p_ov[n_ov++] = *(signed short *) arg; 306 break; 307 308 case FFI_TYPE_UINT8: 309 if (n_gpr < MAX_GPRARGS) 310 p_gpr[n_gpr++] = *(unsigned char *) arg; 311 else 312 p_ov[n_ov++] = *(unsigned char *) arg; 313 break; 314 315 case FFI_TYPE_SINT8: 316 if (n_gpr < MAX_GPRARGS) 317 p_gpr[n_gpr++] = *(signed char *) arg; 318 else 319 p_ov[n_ov++] = *(signed char *) arg; 320 break; 321 322 default: 323 FFI_ASSERT (0); 324 break; 325 } 326 } 327 } 328 329 /*======================== End of Routine ============================*/ 330 331 /*====================================================================*/ 332 /* */ 333 /* Name - ffi_prep_cif_machdep. */ 334 /* */ 335 /* Function - Perform machine dependent CIF processing. */ 336 /* */ 337 /*====================================================================*/ 338 339 ffi_status 340 ffi_prep_cif_machdep(ffi_cif *cif) 341 { 342 size_t struct_size = 0; 343 int n_gpr = 0; 344 int n_fpr = 0; 345 int n_ov = 0; 346 347 ffi_type **ptr; 348 int i; 349 350 /* Determine return value handling. */ 351 352 switch (cif->rtype->type) 353 { 354 /* Void is easy. */ 355 case FFI_TYPE_VOID: 356 cif->flags = FFI390_RET_VOID; 357 break; 358 359 /* Structures are returned via a hidden pointer. */ 360 case FFI_TYPE_STRUCT: 361 cif->flags = FFI390_RET_STRUCT; 362 n_gpr++; /* We need one GPR to pass the pointer. */ 363 break; 364 365 /* Floating point values are returned in fpr 0. */ 366 case FFI_TYPE_FLOAT: 367 cif->flags = FFI390_RET_FLOAT; 368 break; 369 370 case FFI_TYPE_DOUBLE: 371 cif->flags = FFI390_RET_DOUBLE; 372 break; 373 374 #if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE 375 case FFI_TYPE_LONGDOUBLE: 376 cif->flags = FFI390_RET_STRUCT; 377 n_gpr++; 378 break; 379 #endif 380 /* Integer values are returned in gpr 2 (and gpr 3 381 for 64-bit values on 31-bit machines). */ 382 case FFI_TYPE_UINT64: 383 case FFI_TYPE_SINT64: 384 cif->flags = FFI390_RET_INT64; 385 break; 386 387 case FFI_TYPE_POINTER: 388 case FFI_TYPE_INT: 389 case FFI_TYPE_UINT32: 390 case FFI_TYPE_SINT32: 391 case FFI_TYPE_UINT16: 392 case FFI_TYPE_SINT16: 393 case FFI_TYPE_UINT8: 394 case FFI_TYPE_SINT8: 395 /* These are to be extended to word size. */ 396 #ifdef __s390x__ 397 cif->flags = FFI390_RET_INT64; 398 #else 399 cif->flags = FFI390_RET_INT32; 400 #endif 401 break; 402 403 default: 404 FFI_ASSERT (0); 405 break; 406 } 407 408 /* Now for the arguments. */ 409 410 for (ptr = cif->arg_types, i = cif->nargs; 411 i > 0; 412 i--, ptr++) 413 { 414 int type = (*ptr)->type; 415 416 #if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE 417 /* 16-byte long double is passed like a struct. */ 418 if (type == FFI_TYPE_LONGDOUBLE) 419 type = FFI_TYPE_STRUCT; 420 #endif 421 422 /* Check how a structure type is passed. */ 423 if (type == FFI_TYPE_STRUCT) 424 { 425 type = ffi_check_struct_type (*ptr); 426 427 /* If we pass the struct via pointer, we must reserve space 428 to copy its data for proper call-by-value semantics. */ 429 if (type == FFI_TYPE_POINTER) 430 struct_size += ROUND_SIZE ((*ptr)->size); 431 } 432 433 /* Now handle all primitive int/float data types. */ 434 switch (type) 435 { 436 /* The first MAX_FPRARGS floating point arguments 437 go in FPRs, the rest overflow to the stack. */ 438 439 case FFI_TYPE_DOUBLE: 440 if (n_fpr < MAX_FPRARGS) 441 n_fpr++; 442 else 443 n_ov += sizeof (double) / sizeof (long); 444 break; 445 446 case FFI_TYPE_FLOAT: 447 if (n_fpr < MAX_FPRARGS) 448 n_fpr++; 449 else 450 n_ov++; 451 break; 452 453 /* On 31-bit machines, 64-bit integers are passed in GPR pairs, 454 if one is still available, or else on the stack. If only one 455 register is free, skip the register (it won't be used for any 456 subsequent argument either). */ 457 458 #ifndef __s390x__ 459 case FFI_TYPE_UINT64: 460 case FFI_TYPE_SINT64: 461 if (n_gpr == MAX_GPRARGS-1) 462 n_gpr = MAX_GPRARGS; 463 if (n_gpr < MAX_GPRARGS) 464 n_gpr += 2; 465 else 466 n_ov += 2; 467 break; 468 #endif 469 470 /* Everything else is passed in GPRs (until MAX_GPRARGS 471 have been used) or overflows to the stack. */ 472 473 default: 474 if (n_gpr < MAX_GPRARGS) 475 n_gpr++; 476 else 477 n_ov++; 478 break; 479 } 480 } 481 482 /* Total stack space as required for overflow arguments 483 and temporary structure copies. */ 484 485 cif->bytes = ROUND_SIZE (n_ov * sizeof (long)) + struct_size; 486 487 return FFI_OK; 488 } 489 490 /*======================== End of Routine ============================*/ 491 492 /*====================================================================*/ 493 /* */ 494 /* Name - ffi_call. */ 495 /* */ 496 /* Function - Call the FFI routine. */ 497 /* */ 498 /*====================================================================*/ 499 500 void 501 ffi_call(ffi_cif *cif, 502 void (*fn)(void), 503 void *rvalue, 504 void **avalue) 505 { 506 int ret_type = cif->flags; 507 extended_cif ecif; 508 509 ecif.cif = cif; 510 ecif.avalue = avalue; 511 ecif.rvalue = rvalue; 512 513 /* If we don't have a return value, we need to fake one. */ 514 if (rvalue == NULL) 515 { 516 if (ret_type == FFI390_RET_STRUCT) 517 ecif.rvalue = alloca (cif->rtype->size); 518 else 519 ret_type = FFI390_RET_VOID; 520 } 521 522 switch (cif->abi) 523 { 524 case FFI_SYSV: 525 ffi_call_SYSV (cif->bytes, &ecif, ffi_prep_args, 526 ret_type, ecif.rvalue, fn); 527 break; 528 529 default: 530 FFI_ASSERT (0); 531 break; 532 } 533 } 534 535 /*======================== End of Routine ============================*/ 536 537 /*====================================================================*/ 538 /* */ 539 /* Name - ffi_closure_helper_SYSV. */ 540 /* */ 541 /* Function - Call a FFI closure target function. */ 542 /* */ 543 /*====================================================================*/ 544 545 void 546 ffi_closure_helper_SYSV (ffi_closure *closure, 547 unsigned long *p_gpr, 548 unsigned long long *p_fpr, 549 unsigned long *p_ov) 550 { 551 unsigned long long ret_buffer; 552 553 void *rvalue = &ret_buffer; 554 void **avalue; 555 void **p_arg; 556 557 int n_gpr = 0; 558 int n_fpr = 0; 559 int n_ov = 0; 560 561 ffi_type **ptr; 562 int i; 563 564 /* Allocate buffer for argument list pointers. */ 565 566 p_arg = avalue = alloca (closure->cif->nargs * sizeof (void *)); 567 568 /* If we returning a structure, pass the structure address 569 directly to the target function. Otherwise, have the target 570 function store the return value to the GPR save area. */ 571 572 if (closure->cif->flags == FFI390_RET_STRUCT) 573 rvalue = (void *) p_gpr[n_gpr++]; 574 575 /* Now for the arguments. */ 576 577 for (ptr = closure->cif->arg_types, i = closure->cif->nargs; 578 i > 0; 579 i--, p_arg++, ptr++) 580 { 581 int deref_struct_pointer = 0; 582 int type = (*ptr)->type; 583 584 #if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE 585 /* 16-byte long double is passed like a struct. */ 586 if (type == FFI_TYPE_LONGDOUBLE) 587 type = FFI_TYPE_STRUCT; 588 #endif 589 590 /* Check how a structure type is passed. */ 591 if (type == FFI_TYPE_STRUCT) 592 { 593 type = ffi_check_struct_type (*ptr); 594 595 /* If we pass the struct via pointer, remember to 596 retrieve the pointer later. */ 597 if (type == FFI_TYPE_POINTER) 598 deref_struct_pointer = 1; 599 } 600 601 /* Pointers are passed like UINTs of the same size. */ 602 if (type == FFI_TYPE_POINTER) 603 #ifdef __s390x__ 604 type = FFI_TYPE_UINT64; 605 #else 606 type = FFI_TYPE_UINT32; 607 #endif 608 609 /* Now handle all primitive int/float data types. */ 610 switch (type) 611 { 612 case FFI_TYPE_DOUBLE: 613 if (n_fpr < MAX_FPRARGS) 614 *p_arg = &p_fpr[n_fpr++]; 615 else 616 *p_arg = &p_ov[n_ov], 617 n_ov += sizeof (double) / sizeof (long); 618 break; 619 620 case FFI_TYPE_FLOAT: 621 if (n_fpr < MAX_FPRARGS) 622 *p_arg = &p_fpr[n_fpr++]; 623 else 624 *p_arg = (char *)&p_ov[n_ov++] + sizeof (long) - 4; 625 break; 626 627 case FFI_TYPE_UINT64: 628 case FFI_TYPE_SINT64: 629 #ifdef __s390x__ 630 if (n_gpr < MAX_GPRARGS) 631 *p_arg = &p_gpr[n_gpr++]; 632 else 633 *p_arg = &p_ov[n_ov++]; 634 #else 635 if (n_gpr == MAX_GPRARGS-1) 636 n_gpr = MAX_GPRARGS; 637 if (n_gpr < MAX_GPRARGS) 638 *p_arg = &p_gpr[n_gpr], n_gpr += 2; 639 else 640 *p_arg = &p_ov[n_ov], n_ov += 2; 641 #endif 642 break; 643 644 case FFI_TYPE_INT: 645 case FFI_TYPE_UINT32: 646 case FFI_TYPE_SINT32: 647 if (n_gpr < MAX_GPRARGS) 648 *p_arg = (char *)&p_gpr[n_gpr++] + sizeof (long) - 4; 649 else 650 *p_arg = (char *)&p_ov[n_ov++] + sizeof (long) - 4; 651 break; 652 653 case FFI_TYPE_UINT16: 654 case FFI_TYPE_SINT16: 655 if (n_gpr < MAX_GPRARGS) 656 *p_arg = (char *)&p_gpr[n_gpr++] + sizeof (long) - 2; 657 else 658 *p_arg = (char *)&p_ov[n_ov++] + sizeof (long) - 2; 659 break; 660 661 case FFI_TYPE_UINT8: 662 case FFI_TYPE_SINT8: 663 if (n_gpr < MAX_GPRARGS) 664 *p_arg = (char *)&p_gpr[n_gpr++] + sizeof (long) - 1; 665 else 666 *p_arg = (char *)&p_ov[n_ov++] + sizeof (long) - 1; 667 break; 668 669 default: 670 FFI_ASSERT (0); 671 break; 672 } 673 674 /* If this is a struct passed via pointer, we need to 675 actually retrieve that pointer. */ 676 if (deref_struct_pointer) 677 *p_arg = *(void **)*p_arg; 678 } 679 680 681 /* Call the target function. */ 682 (closure->fun) (closure->cif, rvalue, avalue, closure->user_data); 683 684 /* Convert the return value. */ 685 switch (closure->cif->rtype->type) 686 { 687 /* Void is easy, and so is struct. */ 688 case FFI_TYPE_VOID: 689 case FFI_TYPE_STRUCT: 690 #if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE 691 case FFI_TYPE_LONGDOUBLE: 692 #endif 693 break; 694 695 /* Floating point values are returned in fpr 0. */ 696 case FFI_TYPE_FLOAT: 697 p_fpr[0] = (long long) *(unsigned int *) rvalue << 32; 698 break; 699 700 case FFI_TYPE_DOUBLE: 701 p_fpr[0] = *(unsigned long long *) rvalue; 702 break; 703 704 /* Integer values are returned in gpr 2 (and gpr 3 705 for 64-bit values on 31-bit machines). */ 706 case FFI_TYPE_UINT64: 707 case FFI_TYPE_SINT64: 708 #ifdef __s390x__ 709 p_gpr[0] = *(unsigned long *) rvalue; 710 #else 711 p_gpr[0] = ((unsigned long *) rvalue)[0], 712 p_gpr[1] = ((unsigned long *) rvalue)[1]; 713 #endif 714 break; 715 716 case FFI_TYPE_POINTER: 717 case FFI_TYPE_UINT32: 718 case FFI_TYPE_UINT16: 719 case FFI_TYPE_UINT8: 720 p_gpr[0] = *(unsigned long *) rvalue; 721 break; 722 723 case FFI_TYPE_INT: 724 case FFI_TYPE_SINT32: 725 case FFI_TYPE_SINT16: 726 case FFI_TYPE_SINT8: 727 p_gpr[0] = *(signed long *) rvalue; 728 break; 729 730 default: 731 FFI_ASSERT (0); 732 break; 733 } 734 } 735 736 /*======================== End of Routine ============================*/ 737 738 /*====================================================================*/ 739 /* */ 740 /* Name - ffi_prep_closure_loc. */ 741 /* */ 742 /* Function - Prepare a FFI closure. */ 743 /* */ 744 /*====================================================================*/ 745 746 ffi_status 747 ffi_prep_closure_loc (ffi_closure *closure, 748 ffi_cif *cif, 749 void (*fun) (ffi_cif *, void *, void **, void *), 750 void *user_data, 751 void *codeloc) 752 { 753 FFI_ASSERT (cif->abi == FFI_SYSV); 754 755 #ifndef __s390x__ 756 *(short *)&closure->tramp [0] = 0x0d10; /* basr %r1,0 */ 757 *(short *)&closure->tramp [2] = 0x9801; /* lm %r0,%r1,6(%r1) */ 758 *(short *)&closure->tramp [4] = 0x1006; 759 *(short *)&closure->tramp [6] = 0x07f1; /* br %r1 */ 760 *(long *)&closure->tramp [8] = (long)codeloc; 761 *(long *)&closure->tramp[12] = (long)&ffi_closure_SYSV; 762 #else 763 *(short *)&closure->tramp [0] = 0x0d10; /* basr %r1,0 */ 764 *(short *)&closure->tramp [2] = 0xeb01; /* lmg %r0,%r1,14(%r1) */ 765 *(short *)&closure->tramp [4] = 0x100e; 766 *(short *)&closure->tramp [6] = 0x0004; 767 *(short *)&closure->tramp [8] = 0x07f1; /* br %r1 */ 768 *(long *)&closure->tramp[16] = (long)codeloc; 769 *(long *)&closure->tramp[24] = (long)&ffi_closure_SYSV; 770 #endif 771 772 closure->cif = cif; 773 closure->user_data = user_data; 774 closure->fun = fun; 775 776 return FFI_OK; 777 } 778 779 /*======================== End of Routine ============================*/ 780 781