1 /* -----------------------------------------------------------------------
2 ffi.c - Copyright (c) 2000 Software AG
4 S390 Foreign Function Interface
6 Permission is hereby granted, free of charge, to any person obtaining
7 a copy of this software and associated documentation files (the
8 ``Software''), to deal in the Software without restriction, including
9 without limitation the rights to use, copy, modify, merge, publish,
10 distribute, sublicense, and/or sell copies of the Software, and to
11 permit persons to whom the Software is furnished to do so, subject to
12 the following conditions:
14 The above copyright notice and this permission notice shall be included
15 in all copies or substantial portions of the Software.
17 THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS
18 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
20 IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR
21 OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
22 ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
23 OTHER DEALINGS IN THE SOFTWARE.
24 ----------------------------------------------------------------------- */
25 /*====================================================================*/
28 /*====================================================================*/
31 #include <ffi_common.h>
36 /*====================== End of Includes =============================*/
38 /*====================================================================*/
41 /*====================================================================*/
43 /* Maximum number of GPRs available for argument passing. */
46 /* Maximum number of FPRs available for argument passing. */
53 /* Round to multiple of 16. */
54 #define ROUND_SIZE(size) (((size) + 15) & ~15)
56 /* If these values change, sysv.S must be adapted! */
57 #define FFI390_RET_VOID 0
58 #define FFI390_RET_STRUCT 1
59 #define FFI390_RET_FLOAT 2
60 #define FFI390_RET_DOUBLE 3
61 #define FFI390_RET_INT32 4
62 #define FFI390_RET_INT64 5
64 /*===================== End of Defines ===============================*/
66 /*====================================================================*/
69 /*====================================================================*/
71 static void ffi_prep_args (unsigned char *, extended_cif
*);
73 #if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ > 2)
74 __attribute__ ((visibility ("hidden")))
76 ffi_closure_helper_SYSV (ffi_closure
*, unsigned long *,
77 unsigned long long *, unsigned long *);
79 /*====================== End of Prototypes ===========================*/
81 /*====================================================================*/
84 /*====================================================================*/
86 extern void ffi_call_SYSV(unsigned,
88 void (*)(unsigned char *, extended_cif
*),
93 extern void ffi_closure_SYSV(void);
95 /*====================== End of Externals ============================*/
97 /*====================================================================*/
99 /* Name - ffi_check_struct_type. */
101 /* Function - Determine if a structure can be passed within a */
102 /* general purpose or floating point register. */
104 /*====================================================================*/
107 ffi_check_struct_type (ffi_type
*arg
)
109 size_t size
= arg
->size
;
111 /* If the struct has just one element, look at that element
112 to find out whether to consider the struct as floating point. */
113 while (arg
->type
== FFI_TYPE_STRUCT
114 && arg
->elements
[0] && !arg
->elements
[1])
115 arg
= arg
->elements
[0];
117 /* Structs of size 1, 2, 4, and 8 are passed in registers,
118 just like the corresponding int/float types. */
122 return FFI_TYPE_UINT8
;
125 return FFI_TYPE_UINT16
;
128 if (arg
->type
== FFI_TYPE_FLOAT
)
129 return FFI_TYPE_FLOAT
;
131 return FFI_TYPE_UINT32
;
134 if (arg
->type
== FFI_TYPE_DOUBLE
)
135 return FFI_TYPE_DOUBLE
;
137 return FFI_TYPE_UINT64
;
143 /* Other structs are passed via a pointer to the data. */
144 return FFI_TYPE_POINTER
;
147 /*======================== End of Routine ============================*/
149 /*====================================================================*/
151 /* Name - ffi_prep_args. */
153 /* Function - Prepare parameters for call to function. */
155 /* ffi_prep_args is called by the assembly routine once stack space */
156 /* has been allocated for the function's arguments. */
158 /*====================================================================*/
161 ffi_prep_args (unsigned char *stack
, extended_cif
*ecif
)
163 /* The stack space will be filled with those areas:
165 FPR argument register save area (highest addresses)
166 GPR argument register save area
167 temporary struct copies
168 overflow argument area (lowest addresses)
170 We set up the following pointers:
172 p_fpr: bottom of the FPR area (growing upwards)
173 p_gpr: bottom of the GPR area (growing upwards)
174 p_ov: bottom of the overflow area (growing upwards)
175 p_struct: top of the struct copy area (growing downwards)
177 All areas are kept aligned to twice the word size. */
179 int gpr_off
= ecif
->cif
->bytes
;
180 int fpr_off
= gpr_off
+ ROUND_SIZE (MAX_GPRARGS
* sizeof (long));
182 unsigned long long *p_fpr
= (unsigned long long *)(stack
+ fpr_off
);
183 unsigned long *p_gpr
= (unsigned long *)(stack
+ gpr_off
);
184 unsigned char *p_struct
= (unsigned char *)p_gpr
;
185 unsigned long *p_ov
= (unsigned long *)stack
;
192 void **p_argv
= ecif
->avalue
;
195 /* If we returning a structure then we set the first parameter register
196 to the address of where we are returning this structure. */
198 if (ecif
->cif
->flags
== FFI390_RET_STRUCT
)
199 p_gpr
[n_gpr
++] = (unsigned long) ecif
->rvalue
;
201 /* Now for the arguments. */
203 for (ptr
= ecif
->cif
->arg_types
, i
= ecif
->cif
->nargs
;
205 i
--, ptr
++, p_argv
++)
208 int type
= (*ptr
)->type
;
210 /* Check how a structure type is passed. */
211 if (type
== FFI_TYPE_STRUCT
)
213 type
= ffi_check_struct_type (*ptr
);
215 /* If we pass the struct via pointer, copy the data. */
216 if (type
== FFI_TYPE_POINTER
)
218 p_struct
-= ROUND_SIZE ((*ptr
)->size
);
219 memcpy (p_struct
, (char *)arg
, (*ptr
)->size
);
224 /* Now handle all primitive int/pointer/float data types. */
227 case FFI_TYPE_DOUBLE
:
228 if (n_fpr
< MAX_FPRARGS
)
229 p_fpr
[n_fpr
++] = *(unsigned long long *) arg
;
232 p_ov
[n_ov
++] = *(unsigned long *) arg
;
234 p_ov
[n_ov
++] = ((unsigned long *) arg
)[0],
235 p_ov
[n_ov
++] = ((unsigned long *) arg
)[1];
240 if (n_fpr
< MAX_FPRARGS
)
241 p_fpr
[n_fpr
++] = (long long) *(unsigned int *) arg
<< 32;
243 p_ov
[n_ov
++] = *(unsigned int *) arg
;
246 case FFI_TYPE_POINTER
:
247 if (n_gpr
< MAX_GPRARGS
)
248 p_gpr
[n_gpr
++] = (unsigned long)*(unsigned char **) arg
;
250 p_ov
[n_ov
++] = (unsigned long)*(unsigned char **) arg
;
253 case FFI_TYPE_UINT64
:
254 case FFI_TYPE_SINT64
:
256 if (n_gpr
< MAX_GPRARGS
)
257 p_gpr
[n_gpr
++] = *(unsigned long *) arg
;
259 p_ov
[n_ov
++] = *(unsigned long *) arg
;
261 if (n_gpr
== MAX_GPRARGS
-1)
263 if (n_gpr
< MAX_GPRARGS
)
264 p_gpr
[n_gpr
++] = ((unsigned long *) arg
)[0],
265 p_gpr
[n_gpr
++] = ((unsigned long *) arg
)[1];
267 p_ov
[n_ov
++] = ((unsigned long *) arg
)[0],
268 p_ov
[n_ov
++] = ((unsigned long *) arg
)[1];
272 case FFI_TYPE_UINT32
:
273 if (n_gpr
< MAX_GPRARGS
)
274 p_gpr
[n_gpr
++] = *(unsigned int *) arg
;
276 p_ov
[n_ov
++] = *(unsigned int *) arg
;
280 case FFI_TYPE_SINT32
:
281 if (n_gpr
< MAX_GPRARGS
)
282 p_gpr
[n_gpr
++] = *(signed int *) arg
;
284 p_ov
[n_ov
++] = *(signed int *) arg
;
287 case FFI_TYPE_UINT16
:
288 if (n_gpr
< MAX_GPRARGS
)
289 p_gpr
[n_gpr
++] = *(unsigned short *) arg
;
291 p_ov
[n_ov
++] = *(unsigned short *) arg
;
294 case FFI_TYPE_SINT16
:
295 if (n_gpr
< MAX_GPRARGS
)
296 p_gpr
[n_gpr
++] = *(signed short *) arg
;
298 p_ov
[n_ov
++] = *(signed short *) arg
;
302 if (n_gpr
< MAX_GPRARGS
)
303 p_gpr
[n_gpr
++] = *(unsigned char *) arg
;
305 p_ov
[n_ov
++] = *(unsigned char *) arg
;
309 if (n_gpr
< MAX_GPRARGS
)
310 p_gpr
[n_gpr
++] = *(signed char *) arg
;
312 p_ov
[n_ov
++] = *(signed char *) arg
;
322 /*======================== End of Routine ============================*/
324 /*====================================================================*/
326 /* Name - ffi_prep_cif_machdep. */
328 /* Function - Perform machine dependent CIF processing. */
330 /*====================================================================*/
333 ffi_prep_cif_machdep(ffi_cif
*cif
)
335 size_t struct_size
= 0;
343 /* Determine return value handling. */
345 switch (cif
->rtype
->type
)
349 cif
->flags
= FFI390_RET_VOID
;
352 /* Structures are returned via a hidden pointer. */
353 case FFI_TYPE_STRUCT
:
354 cif
->flags
= FFI390_RET_STRUCT
;
355 n_gpr
++; /* We need one GPR to pass the pointer. */
358 /* Floating point values are returned in fpr 0. */
360 cif
->flags
= FFI390_RET_FLOAT
;
363 case FFI_TYPE_DOUBLE
:
364 cif
->flags
= FFI390_RET_DOUBLE
;
367 /* Integer values are returned in gpr 2 (and gpr 3
368 for 64-bit values on 31-bit machines). */
369 case FFI_TYPE_UINT64
:
370 case FFI_TYPE_SINT64
:
371 cif
->flags
= FFI390_RET_INT64
;
374 case FFI_TYPE_POINTER
:
376 case FFI_TYPE_UINT32
:
377 case FFI_TYPE_SINT32
:
378 case FFI_TYPE_UINT16
:
379 case FFI_TYPE_SINT16
:
382 /* These are to be extended to word size. */
384 cif
->flags
= FFI390_RET_INT64
;
386 cif
->flags
= FFI390_RET_INT32
;
395 /* Now for the arguments. */
397 for (ptr
= cif
->arg_types
, i
= cif
->nargs
;
401 int type
= (*ptr
)->type
;
403 /* Check how a structure type is passed. */
404 if (type
== FFI_TYPE_STRUCT
)
406 type
= ffi_check_struct_type (*ptr
);
408 /* If we pass the struct via pointer, we must reserve space
409 to copy its data for proper call-by-value semantics. */
410 if (type
== FFI_TYPE_POINTER
)
411 struct_size
+= ROUND_SIZE ((*ptr
)->size
);
414 /* Now handle all primitive int/float data types. */
417 /* The first MAX_FPRARGS floating point arguments
418 go in FPRs, the rest overflow to the stack. */
420 case FFI_TYPE_DOUBLE
:
421 if (n_fpr
< MAX_FPRARGS
)
424 n_ov
+= sizeof (double) / sizeof (long);
428 if (n_fpr
< MAX_FPRARGS
)
434 /* On 31-bit machines, 64-bit integers are passed in GPR pairs,
435 if one is still available, or else on the stack. If only one
436 register is free, skip the register (it won't be used for any
437 subsequent argument either). */
440 case FFI_TYPE_UINT64
:
441 case FFI_TYPE_SINT64
:
442 if (n_gpr
== MAX_GPRARGS
-1)
444 if (n_gpr
< MAX_GPRARGS
)
451 /* Everything else is passed in GPRs (until MAX_GPRARGS
452 have been used) or overflows to the stack. */
455 if (n_gpr
< MAX_GPRARGS
)
463 /* Total stack space as required for overflow arguments
464 and temporary structure copies. */
466 cif
->bytes
= ROUND_SIZE (n_ov
* sizeof (long)) + struct_size
;
471 /*======================== End of Routine ============================*/
473 /*====================================================================*/
475 /* Name - ffi_call. */
477 /* Function - Call the FFI routine. */
479 /*====================================================================*/
482 ffi_call(ffi_cif
*cif
,
487 int ret_type
= cif
->flags
;
491 ecif
.avalue
= avalue
;
492 ecif
.rvalue
= rvalue
;
494 /* If we don't have a return value, we need to fake one. */
497 if (ret_type
== FFI390_RET_STRUCT
)
498 ecif
.rvalue
= alloca (cif
->rtype
->size
);
500 ret_type
= FFI390_RET_VOID
;
506 ffi_call_SYSV (cif
->bytes
, &ecif
, ffi_prep_args
,
507 ret_type
, ecif
.rvalue
, fn
);
516 /*======================== End of Routine ============================*/
518 /*====================================================================*/
520 /* Name - ffi_closure_helper_SYSV. */
522 /* Function - Call a FFI closure target function. */
524 /*====================================================================*/
527 ffi_closure_helper_SYSV (ffi_closure
*closure
,
528 unsigned long *p_gpr
,
529 unsigned long long *p_fpr
,
532 unsigned long long ret_buffer
;
534 void *rvalue
= &ret_buffer
;
545 /* Allocate buffer for argument list pointers. */
547 p_arg
= avalue
= alloca (closure
->cif
->nargs
* sizeof (void *));
549 /* If we returning a structure, pass the structure address
550 directly to the target function. Otherwise, have the target
551 function store the return value to the GPR save area. */
553 if (closure
->cif
->flags
== FFI390_RET_STRUCT
)
554 rvalue
= (void *) p_gpr
[n_gpr
++];
556 /* Now for the arguments. */
558 for (ptr
= closure
->cif
->arg_types
, i
= closure
->cif
->nargs
;
562 int deref_struct_pointer
= 0;
563 int type
= (*ptr
)->type
;
565 /* Check how a structure type is passed. */
566 if (type
== FFI_TYPE_STRUCT
)
568 type
= ffi_check_struct_type (*ptr
);
570 /* If we pass the struct via pointer, remember to
571 retrieve the pointer later. */
572 if (type
== FFI_TYPE_POINTER
)
573 deref_struct_pointer
= 1;
576 /* Pointers are passed like UINTs of the same size. */
577 if (type
== FFI_TYPE_POINTER
)
579 type
= FFI_TYPE_UINT64
;
581 type
= FFI_TYPE_UINT32
;
584 /* Now handle all primitive int/float data types. */
587 case FFI_TYPE_DOUBLE
:
588 if (n_fpr
< MAX_FPRARGS
)
589 *p_arg
= &p_fpr
[n_fpr
++];
591 *p_arg
= &p_ov
[n_ov
],
592 n_ov
+= sizeof (double) / sizeof (long);
596 if (n_fpr
< MAX_FPRARGS
)
597 *p_arg
= &p_fpr
[n_fpr
++];
599 *p_arg
= (char *)&p_ov
[n_ov
++] + sizeof (long) - 4;
602 case FFI_TYPE_UINT64
:
603 case FFI_TYPE_SINT64
:
605 if (n_gpr
< MAX_GPRARGS
)
606 *p_arg
= &p_gpr
[n_gpr
++];
608 *p_arg
= &p_ov
[n_ov
++];
610 if (n_gpr
== MAX_GPRARGS
-1)
612 if (n_gpr
< MAX_GPRARGS
)
613 *p_arg
= &p_gpr
[n_gpr
], n_gpr
+= 2;
615 *p_arg
= &p_ov
[n_ov
], n_ov
+= 2;
620 case FFI_TYPE_UINT32
:
621 case FFI_TYPE_SINT32
:
622 if (n_gpr
< MAX_GPRARGS
)
623 *p_arg
= (char *)&p_gpr
[n_gpr
++] + sizeof (long) - 4;
625 *p_arg
= (char *)&p_ov
[n_ov
++] + sizeof (long) - 4;
628 case FFI_TYPE_UINT16
:
629 case FFI_TYPE_SINT16
:
630 if (n_gpr
< MAX_GPRARGS
)
631 *p_arg
= (char *)&p_gpr
[n_gpr
++] + sizeof (long) - 2;
633 *p_arg
= (char *)&p_ov
[n_ov
++] + sizeof (long) - 2;
638 if (n_gpr
< MAX_GPRARGS
)
639 *p_arg
= (char *)&p_gpr
[n_gpr
++] + sizeof (long) - 1;
641 *p_arg
= (char *)&p_ov
[n_ov
++] + sizeof (long) - 1;
649 /* If this is a struct passed via pointer, we need to
650 actually retrieve that pointer. */
651 if (deref_struct_pointer
)
652 *p_arg
= *(void **)*p_arg
;
656 /* Call the target function. */
657 (closure
->fun
) (closure
->cif
, rvalue
, avalue
, closure
->user_data
);
659 /* Convert the return value. */
660 switch (closure
->cif
->rtype
->type
)
662 /* Void is easy, and so is struct. */
664 case FFI_TYPE_STRUCT
:
667 /* Floating point values are returned in fpr 0. */
669 p_fpr
[0] = (long long) *(unsigned int *) rvalue
<< 32;
672 case FFI_TYPE_DOUBLE
:
673 p_fpr
[0] = *(unsigned long long *) rvalue
;
676 /* Integer values are returned in gpr 2 (and gpr 3
677 for 64-bit values on 31-bit machines). */
678 case FFI_TYPE_UINT64
:
679 case FFI_TYPE_SINT64
:
681 p_gpr
[0] = *(unsigned long *) rvalue
;
683 p_gpr
[0] = ((unsigned long *) rvalue
)[0],
684 p_gpr
[1] = ((unsigned long *) rvalue
)[1];
688 case FFI_TYPE_POINTER
:
689 case FFI_TYPE_UINT32
:
690 case FFI_TYPE_UINT16
:
692 p_gpr
[0] = *(unsigned long *) rvalue
;
696 case FFI_TYPE_SINT32
:
697 case FFI_TYPE_SINT16
:
699 p_gpr
[0] = *(signed long *) rvalue
;
708 /*======================== End of Routine ============================*/
710 /*====================================================================*/
712 /* Name - ffi_prep_closure. */
714 /* Function - Prepare a FFI closure. */
716 /*====================================================================*/
719 ffi_prep_closure (ffi_closure
*closure
,
721 void (*fun
) (ffi_cif
*, void *, void **, void *),
724 FFI_ASSERT (cif
->abi
== FFI_SYSV
);
727 *(short *)&closure
->tramp
[0] = 0x0d10; /* basr %r1,0 */
728 *(short *)&closure
->tramp
[2] = 0x9801; /* lm %r0,%r1,6(%r1) */
729 *(short *)&closure
->tramp
[4] = 0x1006;
730 *(short *)&closure
->tramp
[6] = 0x07f1; /* br %r1 */
731 *(long *)&closure
->tramp
[8] = (long)closure
;
732 *(long *)&closure
->tramp
[12] = (long)&ffi_closure_SYSV
;
734 *(short *)&closure
->tramp
[0] = 0x0d10; /* basr %r1,0 */
735 *(short *)&closure
->tramp
[2] = 0xeb01; /* lmg %r0,%r1,14(%r1) */
736 *(short *)&closure
->tramp
[4] = 0x100e;
737 *(short *)&closure
->tramp
[6] = 0x0004;
738 *(short *)&closure
->tramp
[8] = 0x07f1; /* br %r1 */
739 *(long *)&closure
->tramp
[16] = (long)closure
;
740 *(long *)&closure
->tramp
[24] = (long)&ffi_closure_SYSV
;
744 closure
->user_data
= user_data
;
750 /*======================== End of Routine ============================*/