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