testing commit
[official-gcc.git] / libffi / src / s390 / ffi.c
blob8adb5bc0ba39e72eb93cc6d1d42d07813770094e
1 /* -----------------------------------------------------------------------
2 ffi.c - Copyright (c) 2000, 2007 Software AG
3 Copyright (c) 2008 Red Hat, Inc
5 S390 Foreign Function Interface
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:
15 The above copyright notice and this permission notice shall be included
16 in all copies or substantial portions of the Software.
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 /*====================================================================*/
31 #include <ffi.h>
32 #include <ffi_common.h>
34 #include <stdlib.h>
35 #include <stdio.h>
37 /*====================== End of Includes =============================*/
39 /*====================================================================*/
40 /* Defines */
41 /* ------- */
42 /*====================================================================*/
44 /* Maximum number of GPRs available for argument passing. */
45 #define MAX_GPRARGS 5
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
54 /* Round to multiple of 16. */
55 #define ROUND_SIZE(size) (((size) + 15) & ~15)
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
65 /*===================== End of Defines ===============================*/
67 /*====================================================================*/
68 /* Prototypes */
69 /* ---------- */
70 /*====================================================================*/
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 *);
80 /*====================== End of Prototypes ===========================*/
82 /*====================================================================*/
83 /* Externals */
84 /* --------- */
85 /*====================================================================*/
87 extern void ffi_call_SYSV(unsigned,
88 extended_cif *,
89 void (*)(unsigned char *, extended_cif *),
90 unsigned,
91 void *,
92 void (*fn)(void));
94 extern void ffi_closure_SYSV(void);
96 /*====================== End of Externals ============================*/
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 /*====================================================================*/
107 static int
108 ffi_check_struct_type (ffi_type *arg)
110 size_t size = arg->size;
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];
118 /* Structs of size 1, 2, 4, and 8 are passed in registers,
119 just like the corresponding int/float types. */
120 switch (size)
122 case 1:
123 return FFI_TYPE_UINT8;
125 case 2:
126 return FFI_TYPE_UINT16;
128 case 4:
129 if (arg->type == FFI_TYPE_FLOAT)
130 return FFI_TYPE_FLOAT;
131 else
132 return FFI_TYPE_UINT32;
134 case 8:
135 if (arg->type == FFI_TYPE_DOUBLE)
136 return FFI_TYPE_DOUBLE;
137 else
138 return FFI_TYPE_UINT64;
140 default:
141 break;
144 /* Other structs are passed via a pointer to the data. */
145 return FFI_TYPE_POINTER;
148 /*======================== End of Routine ============================*/
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 /*====================================================================*/
161 static void
162 ffi_prep_args (unsigned char *stack, extended_cif *ecif)
164 /* The stack space will be filled with those areas:
166 FPR argument register save area (highest addresses)
167 GPR argument register save area
168 temporary struct copies
169 overflow argument area (lowest addresses)
171 We set up the following pointers:
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)
178 All areas are kept aligned to twice the word size. */
180 int gpr_off = ecif->cif->bytes;
181 int fpr_off = gpr_off + ROUND_SIZE (MAX_GPRARGS * sizeof (long));
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;
188 int n_fpr = 0;
189 int n_gpr = 0;
190 int n_ov = 0;
192 ffi_type **ptr;
193 void **p_argv = ecif->avalue;
194 int i;
196 /* If we returning a structure then we set the first parameter register
197 to the address of where we are returning this structure. */
199 if (ecif->cif->flags == FFI390_RET_STRUCT)
200 p_gpr[n_gpr++] = (unsigned long) ecif->rvalue;
202 /* Now for the arguments. */
204 for (ptr = ecif->cif->arg_types, i = ecif->cif->nargs;
205 i > 0;
206 i--, ptr++, p_argv++)
208 void *arg = *p_argv;
209 int type = (*ptr)->type;
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
217 /* Check how a structure type is passed. */
218 if (type == FFI_TYPE_STRUCT)
220 type = ffi_check_struct_type (*ptr);
222 /* If we pass the struct via pointer, copy the data. */
223 if (type == FFI_TYPE_POINTER)
225 p_struct -= ROUND_SIZE ((*ptr)->size);
226 memcpy (p_struct, (char *)arg, (*ptr)->size);
227 arg = &p_struct;
231 /* Now handle all primitive int/pointer/float data types. */
232 switch (type)
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;
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;
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;
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;
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;
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;
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;
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;
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;
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;
322 default:
323 FFI_ASSERT (0);
324 break;
329 /*======================== End of Routine ============================*/
331 /*====================================================================*/
332 /* */
333 /* Name - ffi_prep_cif_machdep. */
334 /* */
335 /* Function - Perform machine dependent CIF processing. */
336 /* */
337 /*====================================================================*/
339 ffi_status
340 ffi_prep_cif_machdep(ffi_cif *cif)
342 size_t struct_size = 0;
343 int n_gpr = 0;
344 int n_fpr = 0;
345 int n_ov = 0;
347 ffi_type **ptr;
348 int i;
350 /* Determine return value handling. */
352 switch (cif->rtype->type)
354 /* Void is easy. */
355 case FFI_TYPE_VOID:
356 cif->flags = FFI390_RET_VOID;
357 break;
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;
365 /* Floating point values are returned in fpr 0. */
366 case FFI_TYPE_FLOAT:
367 cif->flags = FFI390_RET_FLOAT;
368 break;
370 case FFI_TYPE_DOUBLE:
371 cif->flags = FFI390_RET_DOUBLE;
372 break;
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;
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;
403 default:
404 FFI_ASSERT (0);
405 break;
408 /* Now for the arguments. */
410 for (ptr = cif->arg_types, i = cif->nargs;
411 i > 0;
412 i--, ptr++)
414 int type = (*ptr)->type;
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
422 /* Check how a structure type is passed. */
423 if (type == FFI_TYPE_STRUCT)
425 type = ffi_check_struct_type (*ptr);
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);
433 /* Now handle all primitive int/float data types. */
434 switch (type)
436 /* The first MAX_FPRARGS floating point arguments
437 go in FPRs, the rest overflow to the stack. */
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;
446 case FFI_TYPE_FLOAT:
447 if (n_fpr < MAX_FPRARGS)
448 n_fpr++;
449 else
450 n_ov++;
451 break;
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). */
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
470 /* Everything else is passed in GPRs (until MAX_GPRARGS
471 have been used) or overflows to the stack. */
473 default:
474 if (n_gpr < MAX_GPRARGS)
475 n_gpr++;
476 else
477 n_ov++;
478 break;
482 /* Total stack space as required for overflow arguments
483 and temporary structure copies. */
485 cif->bytes = ROUND_SIZE (n_ov * sizeof (long)) + struct_size;
487 return FFI_OK;
490 /*======================== End of Routine ============================*/
492 /*====================================================================*/
493 /* */
494 /* Name - ffi_call. */
495 /* */
496 /* Function - Call the FFI routine. */
497 /* */
498 /*====================================================================*/
500 void
501 ffi_call(ffi_cif *cif,
502 void (*fn)(void),
503 void *rvalue,
504 void **avalue)
506 int ret_type = cif->flags;
507 extended_cif ecif;
509 ecif.cif = cif;
510 ecif.avalue = avalue;
511 ecif.rvalue = rvalue;
513 /* If we don't have a return value, we need to fake one. */
514 if (rvalue == NULL)
516 if (ret_type == FFI390_RET_STRUCT)
517 ecif.rvalue = alloca (cif->rtype->size);
518 else
519 ret_type = FFI390_RET_VOID;
522 switch (cif->abi)
524 case FFI_SYSV:
525 ffi_call_SYSV (cif->bytes, &ecif, ffi_prep_args,
526 ret_type, ecif.rvalue, fn);
527 break;
529 default:
530 FFI_ASSERT (0);
531 break;
535 /*======================== End of Routine ============================*/
537 /*====================================================================*/
538 /* */
539 /* Name - ffi_closure_helper_SYSV. */
540 /* */
541 /* Function - Call a FFI closure target function. */
542 /* */
543 /*====================================================================*/
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)
551 unsigned long long ret_buffer;
553 void *rvalue = &ret_buffer;
554 void **avalue;
555 void **p_arg;
557 int n_gpr = 0;
558 int n_fpr = 0;
559 int n_ov = 0;
561 ffi_type **ptr;
562 int i;
564 /* Allocate buffer for argument list pointers. */
566 p_arg = avalue = alloca (closure->cif->nargs * sizeof (void *));
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. */
572 if (closure->cif->flags == FFI390_RET_STRUCT)
573 rvalue = (void *) p_gpr[n_gpr++];
575 /* Now for the arguments. */
577 for (ptr = closure->cif->arg_types, i = closure->cif->nargs;
578 i > 0;
579 i--, p_arg++, ptr++)
581 int deref_struct_pointer = 0;
582 int type = (*ptr)->type;
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
590 /* Check how a structure type is passed. */
591 if (type == FFI_TYPE_STRUCT)
593 type = ffi_check_struct_type (*ptr);
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;
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
609 /* Now handle all primitive int/float data types. */
610 switch (type)
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;
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;
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;
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;
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;
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;
669 default:
670 FFI_ASSERT (0);
671 break;
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;
681 /* Call the target function. */
682 (closure->fun) (closure->cif, rvalue, avalue, closure->user_data);
684 /* Convert the return value. */
685 switch (closure->cif->rtype->type)
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;
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;
700 case FFI_TYPE_DOUBLE:
701 p_fpr[0] = *(unsigned long long *) rvalue;
702 break;
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;
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;
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;
730 default:
731 FFI_ASSERT (0);
732 break;
736 /*======================== End of Routine ============================*/
738 /*====================================================================*/
739 /* */
740 /* Name - ffi_prep_closure_loc. */
741 /* */
742 /* Function - Prepare a FFI closure. */
743 /* */
744 /*====================================================================*/
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)
753 if (cif->abi != FFI_SYSV)
754 return FFI_BAD_ABI;
756 #ifndef __s390x__
757 *(short *)&closure->tramp [0] = 0x0d10; /* basr %r1,0 */
758 *(short *)&closure->tramp [2] = 0x9801; /* lm %r0,%r1,6(%r1) */
759 *(short *)&closure->tramp [4] = 0x1006;
760 *(short *)&closure->tramp [6] = 0x07f1; /* br %r1 */
761 *(long *)&closure->tramp [8] = (long)codeloc;
762 *(long *)&closure->tramp[12] = (long)&ffi_closure_SYSV;
763 #else
764 *(short *)&closure->tramp [0] = 0x0d10; /* basr %r1,0 */
765 *(short *)&closure->tramp [2] = 0xeb01; /* lmg %r0,%r1,14(%r1) */
766 *(short *)&closure->tramp [4] = 0x100e;
767 *(short *)&closure->tramp [6] = 0x0004;
768 *(short *)&closure->tramp [8] = 0x07f1; /* br %r1 */
769 *(long *)&closure->tramp[16] = (long)codeloc;
770 *(long *)&closure->tramp[24] = (long)&ffi_closure_SYSV;
771 #endif
773 closure->cif = cif;
774 closure->user_data = user_data;
775 closure->fun = fun;
777 return FFI_OK;
780 /*======================== End of Routine ============================*/