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 /*====================================================================*/
29 /*====================================================================*/
32 #include <ffi_common.h>
37 /*====================== End of Includes =============================*/
39 /*====================================================================*/
42 /*====================================================================*/
44 /* Maximum number of GPRs available for argument passing. */
47 /* Maximum number of FPRs available for argument passing. */
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 /*====================================================================*/
70 /*====================================================================*/
72 static void ffi_prep_args (unsigned char *, extended_cif
*);
74 #if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ > 2)
75 __attribute__ ((visibility ("hidden")))
77 ffi_closure_helper_SYSV (ffi_closure
*, unsigned long *,
78 unsigned long long *, unsigned long *);
80 /*====================== End of Prototypes ===========================*/
82 /*====================================================================*/
85 /*====================================================================*/
87 extern void ffi_call_SYSV(unsigned,
89 void (*)(unsigned char *, extended_cif
*),
94 extern void ffi_closure_SYSV(void);
96 /*====================== End of Externals ============================*/
98 /*====================================================================*/
100 /* Name - ffi_check_struct_type. */
102 /* Function - Determine if a structure can be passed within a */
103 /* general purpose or floating point register. */
105 /*====================================================================*/
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. */
123 return FFI_TYPE_UINT8
;
126 return FFI_TYPE_UINT16
;
129 if (arg
->type
== FFI_TYPE_FLOAT
)
130 return FFI_TYPE_FLOAT
;
132 return FFI_TYPE_UINT32
;
135 if (arg
->type
== FFI_TYPE_DOUBLE
)
136 return FFI_TYPE_DOUBLE
;
138 return FFI_TYPE_UINT64
;
144 /* Other structs are passed via a pointer to the data. */
145 return FFI_TYPE_POINTER
;
148 /*======================== End of Routine ============================*/
150 /*====================================================================*/
152 /* Name - ffi_prep_args. */
154 /* Function - Prepare parameters for call to function. */
156 /* ffi_prep_args is called by the assembly routine once stack space */
157 /* has been allocated for the function's arguments. */
159 /*====================================================================*/
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
;
193 void **p_argv
= ecif
->avalue
;
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
;
206 i
--, ptr
++, 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
;
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
);
231 /* Now handle all primitive int/pointer/float data types. */
234 case FFI_TYPE_DOUBLE
:
235 if (n_fpr
< MAX_FPRARGS
)
236 p_fpr
[n_fpr
++] = *(unsigned long long *) arg
;
239 p_ov
[n_ov
++] = *(unsigned long *) arg
;
241 p_ov
[n_ov
++] = ((unsigned long *) arg
)[0],
242 p_ov
[n_ov
++] = ((unsigned long *) arg
)[1];
247 if (n_fpr
< MAX_FPRARGS
)
248 p_fpr
[n_fpr
++] = (long long) *(unsigned int *) arg
<< 32;
250 p_ov
[n_ov
++] = *(unsigned int *) arg
;
253 case FFI_TYPE_POINTER
:
254 if (n_gpr
< MAX_GPRARGS
)
255 p_gpr
[n_gpr
++] = (unsigned long)*(unsigned char **) arg
;
257 p_ov
[n_ov
++] = (unsigned long)*(unsigned char **) arg
;
260 case FFI_TYPE_UINT64
:
261 case FFI_TYPE_SINT64
:
263 if (n_gpr
< MAX_GPRARGS
)
264 p_gpr
[n_gpr
++] = *(unsigned long *) arg
;
266 p_ov
[n_ov
++] = *(unsigned long *) arg
;
268 if (n_gpr
== MAX_GPRARGS
-1)
270 if (n_gpr
< MAX_GPRARGS
)
271 p_gpr
[n_gpr
++] = ((unsigned long *) arg
)[0],
272 p_gpr
[n_gpr
++] = ((unsigned long *) arg
)[1];
274 p_ov
[n_ov
++] = ((unsigned long *) arg
)[0],
275 p_ov
[n_ov
++] = ((unsigned long *) arg
)[1];
279 case FFI_TYPE_UINT32
:
280 if (n_gpr
< MAX_GPRARGS
)
281 p_gpr
[n_gpr
++] = *(unsigned int *) arg
;
283 p_ov
[n_ov
++] = *(unsigned int *) arg
;
287 case FFI_TYPE_SINT32
:
288 if (n_gpr
< MAX_GPRARGS
)
289 p_gpr
[n_gpr
++] = *(signed int *) arg
;
291 p_ov
[n_ov
++] = *(signed int *) arg
;
294 case FFI_TYPE_UINT16
:
295 if (n_gpr
< MAX_GPRARGS
)
296 p_gpr
[n_gpr
++] = *(unsigned short *) arg
;
298 p_ov
[n_ov
++] = *(unsigned short *) arg
;
301 case FFI_TYPE_SINT16
:
302 if (n_gpr
< MAX_GPRARGS
)
303 p_gpr
[n_gpr
++] = *(signed short *) arg
;
305 p_ov
[n_ov
++] = *(signed short *) arg
;
309 if (n_gpr
< MAX_GPRARGS
)
310 p_gpr
[n_gpr
++] = *(unsigned char *) arg
;
312 p_ov
[n_ov
++] = *(unsigned char *) arg
;
316 if (n_gpr
< MAX_GPRARGS
)
317 p_gpr
[n_gpr
++] = *(signed char *) arg
;
319 p_ov
[n_ov
++] = *(signed char *) arg
;
329 /*======================== End of Routine ============================*/
331 /*====================================================================*/
333 /* Name - ffi_prep_cif_machdep. */
335 /* Function - Perform machine dependent CIF processing. */
337 /*====================================================================*/
340 ffi_prep_cif_machdep(ffi_cif
*cif
)
342 size_t struct_size
= 0;
350 /* Determine return value handling. */
352 switch (cif
->rtype
->type
)
356 cif
->flags
= FFI390_RET_VOID
;
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. */
365 /* Floating point values are returned in fpr 0. */
367 cif
->flags
= FFI390_RET_FLOAT
;
370 case FFI_TYPE_DOUBLE
:
371 cif
->flags
= FFI390_RET_DOUBLE
;
374 #if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
375 case FFI_TYPE_LONGDOUBLE
:
376 cif
->flags
= FFI390_RET_STRUCT
;
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
;
387 case FFI_TYPE_POINTER
:
389 case FFI_TYPE_UINT32
:
390 case FFI_TYPE_SINT32
:
391 case FFI_TYPE_UINT16
:
392 case FFI_TYPE_SINT16
:
395 /* These are to be extended to word size. */
397 cif
->flags
= FFI390_RET_INT64
;
399 cif
->flags
= FFI390_RET_INT32
;
408 /* Now for the arguments. */
410 for (ptr
= cif
->arg_types
, i
= cif
->nargs
;
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
;
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. */
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
)
443 n_ov
+= sizeof (double) / sizeof (long);
447 if (n_fpr
< MAX_FPRARGS
)
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). */
459 case FFI_TYPE_UINT64
:
460 case FFI_TYPE_SINT64
:
461 if (n_gpr
== MAX_GPRARGS
-1)
463 if (n_gpr
< MAX_GPRARGS
)
470 /* Everything else is passed in GPRs (until MAX_GPRARGS
471 have been used) or overflows to the stack. */
474 if (n_gpr
< MAX_GPRARGS
)
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
;
490 /*======================== End of Routine ============================*/
492 /*====================================================================*/
494 /* Name - ffi_call. */
496 /* Function - Call the FFI routine. */
498 /*====================================================================*/
501 ffi_call(ffi_cif
*cif
,
506 int ret_type
= cif
->flags
;
510 ecif
.avalue
= avalue
;
511 ecif
.rvalue
= rvalue
;
513 /* If we don't have a return value, we need to fake one. */
516 if (ret_type
== FFI390_RET_STRUCT
)
517 ecif
.rvalue
= alloca (cif
->rtype
->size
);
519 ret_type
= FFI390_RET_VOID
;
525 ffi_call_SYSV (cif
->bytes
, &ecif
, ffi_prep_args
,
526 ret_type
, ecif
.rvalue
, fn
);
535 /*======================== End of Routine ============================*/
537 /*====================================================================*/
539 /* Name - ffi_closure_helper_SYSV. */
541 /* Function - Call a FFI closure target function. */
543 /*====================================================================*/
546 ffi_closure_helper_SYSV (ffi_closure
*closure
,
547 unsigned long *p_gpr
,
548 unsigned long long *p_fpr
,
551 unsigned long long ret_buffer
;
553 void *rvalue
= &ret_buffer
;
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
;
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
;
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
)
604 type
= FFI_TYPE_UINT64
;
606 type
= FFI_TYPE_UINT32
;
609 /* Now handle all primitive int/float data types. */
612 case FFI_TYPE_DOUBLE
:
613 if (n_fpr
< MAX_FPRARGS
)
614 *p_arg
= &p_fpr
[n_fpr
++];
616 *p_arg
= &p_ov
[n_ov
],
617 n_ov
+= sizeof (double) / sizeof (long);
621 if (n_fpr
< MAX_FPRARGS
)
622 *p_arg
= &p_fpr
[n_fpr
++];
624 *p_arg
= (char *)&p_ov
[n_ov
++] + sizeof (long) - 4;
627 case FFI_TYPE_UINT64
:
628 case FFI_TYPE_SINT64
:
630 if (n_gpr
< MAX_GPRARGS
)
631 *p_arg
= &p_gpr
[n_gpr
++];
633 *p_arg
= &p_ov
[n_ov
++];
635 if (n_gpr
== MAX_GPRARGS
-1)
637 if (n_gpr
< MAX_GPRARGS
)
638 *p_arg
= &p_gpr
[n_gpr
], n_gpr
+= 2;
640 *p_arg
= &p_ov
[n_ov
], n_ov
+= 2;
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;
650 *p_arg
= (char *)&p_ov
[n_ov
++] + sizeof (long) - 4;
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;
658 *p_arg
= (char *)&p_ov
[n_ov
++] + sizeof (long) - 2;
663 if (n_gpr
< MAX_GPRARGS
)
664 *p_arg
= (char *)&p_gpr
[n_gpr
++] + sizeof (long) - 1;
666 *p_arg
= (char *)&p_ov
[n_ov
++] + sizeof (long) - 1;
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. */
689 case FFI_TYPE_STRUCT
:
690 #if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
691 case FFI_TYPE_LONGDOUBLE
:
695 /* Floating point values are returned in fpr 0. */
697 p_fpr
[0] = (long long) *(unsigned int *) rvalue
<< 32;
700 case FFI_TYPE_DOUBLE
:
701 p_fpr
[0] = *(unsigned long long *) rvalue
;
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
:
709 p_gpr
[0] = *(unsigned long *) rvalue
;
711 p_gpr
[0] = ((unsigned long *) rvalue
)[0],
712 p_gpr
[1] = ((unsigned long *) rvalue
)[1];
716 case FFI_TYPE_POINTER
:
717 case FFI_TYPE_UINT32
:
718 case FFI_TYPE_UINT16
:
720 p_gpr
[0] = *(unsigned long *) rvalue
;
724 case FFI_TYPE_SINT32
:
725 case FFI_TYPE_SINT16
:
727 p_gpr
[0] = *(signed long *) rvalue
;
736 /*======================== End of Routine ============================*/
738 /*====================================================================*/
740 /* Name - ffi_prep_closure_loc. */
742 /* Function - Prepare a FFI closure. */
744 /*====================================================================*/
747 ffi_prep_closure_loc (ffi_closure
*closure
,
749 void (*fun
) (ffi_cif
*, void *, void **, void *),
753 FFI_ASSERT (cif
->abi
== FFI_SYSV
);
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
;
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
;
773 closure
->user_data
= user_data
;
779 /*======================== End of Routine ============================*/