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
*);
72 static int ffi_check_float_struct (ffi_type
*);
73 void ffi_closure_helper_SYSV (ffi_closure
*, unsigned long *,
74 unsigned long long *, unsigned long *);
76 /*====================== End of Prototypes ===========================*/
78 /*====================================================================*/
81 /*====================================================================*/
83 extern void ffi_call_SYSV(unsigned,
85 void (*)(unsigned char *, extended_cif
*),
90 extern void ffi_closure_SYSV(void);
92 /*====================== End of Externals ============================*/
94 /*====================================================================*/
96 /* Name - ffi_check_struct_type. */
98 /* Function - Determine if a structure can be passed within a */
99 /* general purpose or floating point register. */
101 /*====================================================================*/
104 ffi_check_struct_type (ffi_type
*arg
)
106 size_t size
= arg
->size
;
108 /* If the struct has just one element, look at that element
109 to find out whether to consider the struct as floating point. */
110 while (arg
->type
== FFI_TYPE_STRUCT
111 && arg
->elements
[0] && !arg
->elements
[1])
112 arg
= arg
->elements
[0];
114 /* Structs of size 1, 2, 4, and 8 are passed in registers,
115 just like the corresponding int/float types. */
119 return FFI_TYPE_UINT8
;
122 return FFI_TYPE_UINT16
;
125 if (arg
->type
== FFI_TYPE_FLOAT
)
126 return FFI_TYPE_FLOAT
;
128 return FFI_TYPE_UINT32
;
131 if (arg
->type
== FFI_TYPE_DOUBLE
)
132 return FFI_TYPE_DOUBLE
;
134 return FFI_TYPE_UINT64
;
140 /* Other structs are passed via a pointer to the data. */
141 return FFI_TYPE_POINTER
;
144 /*======================== End of Routine ============================*/
146 /*====================================================================*/
148 /* Name - ffi_prep_args. */
150 /* Function - Prepare parameters for call to function. */
152 /* ffi_prep_args is called by the assembly routine once stack space */
153 /* has been allocated for the function's arguments. */
155 /*====================================================================*/
158 ffi_prep_args (unsigned char *stack
, extended_cif
*ecif
)
160 /* The stack space will be filled with those areas:
162 FPR argument register save area (highest addresses)
163 GPR argument register save area
164 temporary struct copies
165 overflow argument area (lowest addresses)
167 We set up the following pointers:
169 p_fpr: bottom of the FPR area (growing upwards)
170 p_gpr: bottom of the GPR area (growing upwards)
171 p_ov: bottom of the overflow area (growing upwards)
172 p_struct: top of the struct copy area (growing downwards)
174 All areas are kept aligned to twice the word size. */
176 int gpr_off
= ecif
->cif
->bytes
;
177 int fpr_off
= gpr_off
+ ROUND_SIZE (MAX_GPRARGS
* sizeof (long));
179 unsigned long long *p_fpr
= (unsigned long long *)(stack
+ fpr_off
);
180 unsigned long *p_gpr
= (unsigned long *)(stack
+ gpr_off
);
181 unsigned char *p_struct
= (unsigned char *)p_gpr
;
182 unsigned long *p_ov
= (unsigned long *)stack
;
189 void **p_argv
= ecif
->avalue
;
192 /* If we returning a structure then we set the first parameter register
193 to the address of where we are returning this structure. */
195 if (ecif
->cif
->flags
== FFI390_RET_STRUCT
)
196 p_gpr
[n_gpr
++] = (unsigned long) ecif
->rvalue
;
198 /* Now for the arguments. */
200 for (ptr
= ecif
->cif
->arg_types
, i
= ecif
->cif
->nargs
;
202 i
--, ptr
++, p_argv
++)
205 int type
= (*ptr
)->type
;
207 /* Check how a structure type is passed. */
208 if (type
== FFI_TYPE_STRUCT
)
210 type
= ffi_check_struct_type (*ptr
);
212 /* If we pass the struct via pointer, copy the data. */
213 if (type
== FFI_TYPE_POINTER
)
215 p_struct
-= ROUND_SIZE ((*ptr
)->size
);
216 memcpy (p_struct
, (char *)arg
, (*ptr
)->size
);
221 /* Pointers are passed like UINTs of the same size. */
222 if (type
== FFI_TYPE_POINTER
)
224 type
= FFI_TYPE_UINT64
;
226 type
= FFI_TYPE_UINT32
;
229 /* Now handle all primitive int/float data types. */
232 case FFI_TYPE_DOUBLE
:
233 if (n_fpr
< MAX_FPRARGS
)
234 p_fpr
[n_fpr
++] = *(unsigned long long *) arg
;
237 p_ov
[n_ov
++] = *(unsigned long *) arg
;
239 p_ov
[n_ov
++] = ((unsigned long *) arg
)[0],
240 p_ov
[n_ov
++] = ((unsigned long *) arg
)[1];
245 if (n_fpr
< MAX_FPRARGS
)
246 p_fpr
[n_fpr
++] = (long long) *(unsigned int *) arg
<< 32;
248 p_ov
[n_ov
++] = *(unsigned int *) arg
;
251 case FFI_TYPE_UINT64
:
252 case FFI_TYPE_SINT64
:
254 if (n_gpr
< MAX_GPRARGS
)
255 p_gpr
[n_gpr
++] = *(unsigned long *) arg
;
257 p_ov
[n_ov
++] = *(unsigned long *) arg
;
259 if (n_gpr
== MAX_GPRARGS
-1)
261 if (n_gpr
< MAX_GPRARGS
)
262 p_gpr
[n_gpr
++] = ((unsigned long *) arg
)[0],
263 p_gpr
[n_gpr
++] = ((unsigned long *) arg
)[1];
265 p_ov
[n_ov
++] = ((unsigned long *) arg
)[0],
266 p_ov
[n_ov
++] = ((unsigned long *) arg
)[1];
270 case FFI_TYPE_UINT32
:
271 if (n_gpr
< MAX_GPRARGS
)
272 p_gpr
[n_gpr
++] = *(unsigned int *) arg
;
274 p_ov
[n_ov
++] = *(unsigned int *) arg
;
278 case FFI_TYPE_SINT32
:
279 if (n_gpr
< MAX_GPRARGS
)
280 p_gpr
[n_gpr
++] = *(signed int *) arg
;
282 p_ov
[n_ov
++] = *(signed int *) arg
;
285 case FFI_TYPE_UINT16
:
286 if (n_gpr
< MAX_GPRARGS
)
287 p_gpr
[n_gpr
++] = *(unsigned short *) arg
;
289 p_ov
[n_ov
++] = *(unsigned short *) arg
;
292 case FFI_TYPE_SINT16
:
293 if (n_gpr
< MAX_GPRARGS
)
294 p_gpr
[n_gpr
++] = *(signed short *) arg
;
296 p_ov
[n_ov
++] = *(signed short *) arg
;
300 if (n_gpr
< MAX_GPRARGS
)
301 p_gpr
[n_gpr
++] = *(unsigned char *) arg
;
303 p_ov
[n_ov
++] = *(unsigned char *) arg
;
307 if (n_gpr
< MAX_GPRARGS
)
308 p_gpr
[n_gpr
++] = *(signed char *) arg
;
310 p_ov
[n_ov
++] = *(signed char *) arg
;
320 /*======================== End of Routine ============================*/
322 /*====================================================================*/
324 /* Name - ffi_prep_cif_machdep. */
326 /* Function - Perform machine dependent CIF processing. */
328 /*====================================================================*/
331 ffi_prep_cif_machdep(ffi_cif
*cif
)
333 size_t struct_size
= 0;
341 /* Determine return value handling. */
343 switch (cif
->rtype
->type
)
347 cif
->flags
= FFI390_RET_VOID
;
350 /* Structures are returned via a hidden pointer. */
351 case FFI_TYPE_STRUCT
:
352 cif
->flags
= FFI390_RET_STRUCT
;
353 n_gpr
++; /* We need one GPR to pass the pointer. */
356 /* Floating point values are returned in fpr 0. */
358 cif
->flags
= FFI390_RET_FLOAT
;
361 case FFI_TYPE_DOUBLE
:
362 cif
->flags
= FFI390_RET_DOUBLE
;
365 /* Integer values are returned in gpr 2 (and gpr 3
366 for 64-bit values on 31-bit machines). */
367 case FFI_TYPE_UINT64
:
368 case FFI_TYPE_SINT64
:
369 cif
->flags
= FFI390_RET_INT64
;
372 case FFI_TYPE_POINTER
:
374 case FFI_TYPE_UINT32
:
375 case FFI_TYPE_SINT32
:
376 case FFI_TYPE_UINT16
:
377 case FFI_TYPE_SINT16
:
380 /* These are to be extended to word size. */
382 cif
->flags
= FFI390_RET_INT64
;
384 cif
->flags
= FFI390_RET_INT32
;
393 /* Now for the arguments. */
395 for (ptr
= cif
->arg_types
, i
= cif
->nargs
;
399 int type
= (*ptr
)->type
;
401 /* Check how a structure type is passed. */
402 if (type
== FFI_TYPE_STRUCT
)
404 type
= ffi_check_struct_type (*ptr
);
406 /* If we pass the struct via pointer, we must reserve space
407 to copy its data for proper call-by-value semantics. */
408 if (type
== FFI_TYPE_POINTER
)
409 struct_size
+= ROUND_SIZE ((*ptr
)->size
);
412 /* Now handle all primitive int/float data types. */
415 /* The first MAX_FPRARGS floating point arguments
416 go in FPRs, the rest overflow to the stack. */
418 case FFI_TYPE_DOUBLE
:
419 if (n_fpr
< MAX_FPRARGS
)
422 n_ov
+= sizeof (double) / sizeof (long);
426 if (n_fpr
< MAX_FPRARGS
)
432 /* On 31-bit machines, 64-bit integers are passed in GPR pairs,
433 if one is still available, or else on the stack. If only one
434 register is free, skip the register (it won't be used for any
435 subsequent argument either). */
438 case FFI_TYPE_UINT64
:
439 case FFI_TYPE_SINT64
:
440 if (n_gpr
== MAX_GPRARGS
-1)
442 if (n_gpr
< MAX_GPRARGS
)
449 /* Everything else is passed in GPRs (until MAX_GPRARGS
450 have been used) or overflows to the stack. */
453 if (n_gpr
< MAX_GPRARGS
)
461 /* Total stack space as required for overflow arguments
462 and temporary structure copies. */
464 cif
->bytes
= ROUND_SIZE (n_ov
* sizeof (long)) + struct_size
;
469 /*======================== End of Routine ============================*/
471 /*====================================================================*/
473 /* Name - ffi_call. */
475 /* Function - Call the FFI routine. */
477 /*====================================================================*/
480 ffi_call(ffi_cif
*cif
,
485 int ret_type
= cif
->flags
;
489 ecif
.avalue
= avalue
;
490 ecif
.rvalue
= rvalue
;
492 /* If we don't have a return value, we need to fake one. */
495 if (ret_type
== FFI390_RET_STRUCT
)
496 ecif
.rvalue
= alloca (cif
->rtype
->size
);
498 ret_type
= FFI390_RET_VOID
;
504 ffi_call_SYSV (cif
->bytes
, &ecif
, ffi_prep_args
,
505 ret_type
, ecif
.rvalue
, fn
);
514 /*======================== End of Routine ============================*/
516 /*====================================================================*/
518 /* Name - ffi_closure_helper_SYSV. */
520 /* Function - Call a FFI closure target function. */
522 /*====================================================================*/
525 ffi_closure_helper_SYSV (ffi_closure
*closure
,
526 unsigned long *p_gpr
,
527 unsigned long long *p_fpr
,
530 unsigned long long ret_buffer
;
532 void *rvalue
= &ret_buffer
;
543 /* Allocate buffer for argument list pointers. */
545 p_arg
= avalue
= alloca (closure
->cif
->nargs
* sizeof (void *));
547 /* If we returning a structure, pass the structure address
548 directly to the target function. Otherwise, have the target
549 function store the return value to the GPR save area. */
551 if (closure
->cif
->flags
== FFI390_RET_STRUCT
)
552 rvalue
= (void *) p_gpr
[n_gpr
++];
554 /* Now for the arguments. */
556 for (ptr
= closure
->cif
->arg_types
, i
= closure
->cif
->nargs
;
560 int deref_struct_pointer
= 0;
561 int type
= (*ptr
)->type
;
563 /* Check how a structure type is passed. */
564 if (type
== FFI_TYPE_STRUCT
)
566 type
= ffi_check_struct_type (*ptr
);
568 /* If we pass the struct via pointer, remember to
569 retrieve the pointer later. */
570 if (type
== FFI_TYPE_POINTER
)
571 deref_struct_pointer
= 1;
574 /* Pointers are passed like UINTs of the same size. */
575 if (type
== FFI_TYPE_POINTER
)
577 type
= FFI_TYPE_UINT64
;
579 type
= FFI_TYPE_UINT32
;
582 /* Now handle all primitive int/float data types. */
585 case FFI_TYPE_DOUBLE
:
586 if (n_fpr
< MAX_FPRARGS
)
587 *p_arg
= &p_fpr
[n_fpr
++];
589 *p_arg
= &p_ov
[n_ov
],
590 n_ov
+= sizeof (double) / sizeof (long);
594 if (n_fpr
< MAX_FPRARGS
)
595 *p_arg
= &p_fpr
[n_fpr
++];
597 *p_arg
= (char *)&p_ov
[n_ov
++] + sizeof (long) - 4;
600 case FFI_TYPE_UINT64
:
601 case FFI_TYPE_SINT64
:
603 if (n_gpr
< MAX_GPRARGS
)
604 *p_arg
= &p_gpr
[n_gpr
++];
606 *p_arg
= &p_ov
[n_ov
++];
608 if (n_gpr
== MAX_GPRARGS
-1)
610 if (n_gpr
< MAX_GPRARGS
)
611 *p_arg
= &p_gpr
[n_gpr
], n_gpr
+= 2;
613 *p_arg
= &p_ov
[n_ov
], n_ov
+= 2;
618 case FFI_TYPE_UINT32
:
619 case FFI_TYPE_SINT32
:
620 if (n_gpr
< MAX_GPRARGS
)
621 *p_arg
= (char *)&p_gpr
[n_gpr
++] + sizeof (long) - 4;
623 *p_arg
= (char *)&p_ov
[n_ov
++] + sizeof (long) - 4;
626 case FFI_TYPE_UINT16
:
627 case FFI_TYPE_SINT16
:
628 if (n_gpr
< MAX_GPRARGS
)
629 *p_arg
= (char *)&p_gpr
[n_gpr
++] + sizeof (long) - 2;
631 *p_arg
= (char *)&p_ov
[n_ov
++] + sizeof (long) - 2;
636 if (n_gpr
< MAX_GPRARGS
)
637 *p_arg
= (char *)&p_gpr
[n_gpr
++] + sizeof (long) - 1;
639 *p_arg
= (char *)&p_ov
[n_ov
++] + sizeof (long) - 1;
647 /* If this is a struct passed via pointer, we need to
648 actually retrieve that pointer. */
649 if (deref_struct_pointer
)
650 *p_arg
= *(void **)*p_arg
;
654 /* Call the target function. */
655 (closure
->fun
) (closure
->cif
, rvalue
, avalue
, closure
->user_data
);
657 /* Convert the return value. */
658 switch (closure
->cif
->rtype
->type
)
660 /* Void is easy, and so is struct. */
662 case FFI_TYPE_STRUCT
:
665 /* Floating point values are returned in fpr 0. */
667 p_fpr
[0] = (long long) *(unsigned int *) rvalue
<< 32;
670 case FFI_TYPE_DOUBLE
:
671 p_fpr
[0] = *(unsigned long long *) rvalue
;
674 /* Integer values are returned in gpr 2 (and gpr 3
675 for 64-bit values on 31-bit machines). */
676 case FFI_TYPE_UINT64
:
677 case FFI_TYPE_SINT64
:
679 p_gpr
[0] = *(unsigned long *) rvalue
;
681 p_gpr
[0] = ((unsigned long *) rvalue
)[0],
682 p_gpr
[1] = ((unsigned long *) rvalue
)[1];
686 case FFI_TYPE_POINTER
:
687 case FFI_TYPE_UINT32
:
688 case FFI_TYPE_UINT16
:
690 p_gpr
[0] = *(unsigned long *) rvalue
;
694 case FFI_TYPE_SINT32
:
695 case FFI_TYPE_SINT16
:
697 p_gpr
[0] = *(signed long *) rvalue
;
706 /*======================== End of Routine ============================*/
708 /*====================================================================*/
710 /* Name - ffi_prep_closure. */
712 /* Function - Prepare a FFI closure. */
714 /*====================================================================*/
717 ffi_prep_closure (ffi_closure
*closure
,
719 void (*fun
) (ffi_cif
*, void *, void **, void *),
722 FFI_ASSERT (cif
->abi
== FFI_SYSV
);
725 *(short *)&closure
->tramp
[0] = 0x0d10; /* basr %r1,0 */
726 *(short *)&closure
->tramp
[2] = 0x9801; /* lm %r0,%r1,6(%r1) */
727 *(short *)&closure
->tramp
[4] = 0x1006;
728 *(short *)&closure
->tramp
[6] = 0x07f1; /* br %r1 */
729 *(long *)&closure
->tramp
[8] = (long)closure
;
730 *(long *)&closure
->tramp
[12] = (long)&ffi_closure_SYSV
;
732 *(short *)&closure
->tramp
[0] = 0x0d10; /* basr %r1,0 */
733 *(short *)&closure
->tramp
[2] = 0xeb01; /* lmg %r0,%r1,14(%r1) */
734 *(short *)&closure
->tramp
[4] = 0x100e;
735 *(short *)&closure
->tramp
[6] = 0x0004;
736 *(short *)&closure
->tramp
[8] = 0x07f1; /* br %r1 */
737 *(long *)&closure
->tramp
[16] = (long)closure
;
738 *(long *)&closure
->tramp
[24] = (long)&ffi_closure_SYSV
;
742 closure
->user_data
= user_data
;
748 /*======================== End of Routine ============================*/