]>
git.ipfire.org Git - thirdparty/gcc.git/blob - libffi/src/powerpc/ffi.c
1 /* -----------------------------------------------------------------------
2 ffi.c - Copyright (c) 1998 Geoffrey Keating
4 PowerPC 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 ----------------------------------------------------------------------- */
27 #include <ffi_common.h>
32 #if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ > 1)
33 # define hidden __attribute__ ((visibility ("hidden")))
39 extern void ffi_closure_SYSV(void);
40 extern void hidden
ffi_closure_LINUX64(void);
43 /* The assembly depends on these exact flags. */
44 FLAG_RETURNS_NOTHING
= 1 << (31-30), /* These go in cr7 */
45 FLAG_RETURNS_FP
= 1 << (31-29),
46 FLAG_RETURNS_64BITS
= 1 << (31-28),
48 FLAG_ARG_NEEDS_COPY
= 1 << (31- 7),
49 FLAG_FP_ARGUMENTS
= 1 << (31- 6), /* cr1.eq; specified by ABI */
50 FLAG_4_GPR_ARGUMENTS
= 1 << (31- 5),
51 FLAG_RETVAL_REFERENCE
= 1 << (31- 4)
54 /* About the SYSV ABI. */
56 NUM_GPR_ARG_REGISTERS
= 8,
57 NUM_FPR_ARG_REGISTERS
= 8
59 enum { ASM_NEEDS_REGISTERS
= 4 };
61 /* ffi_prep_args_SYSV is called by the assembly routine once stack space
62 has been allocated for the function's arguments.
64 The stack layout we want looks like this:
66 | Return address from ffi_call_SYSV 4bytes | higher addresses
67 |--------------------------------------------|
68 | Previous backchain pointer 4 | stack pointer here
69 |--------------------------------------------|<+ <<< on entry to
70 | Saved r28-r31 4*4 | | ffi_call_SYSV
71 |--------------------------------------------| |
72 | GPR registers r3-r10 8*4 | | ffi_call_SYSV
73 |--------------------------------------------| |
74 | FPR registers f1-f8 (optional) 8*8 | |
75 |--------------------------------------------| | stack |
76 | Space for copied structures | | grows |
77 |--------------------------------------------| | down V
78 | Parameters that didn't fit in registers | |
79 |--------------------------------------------| | lower addresses
80 | Space for callee's LR 4 | |
81 |--------------------------------------------| | stack pointer here
82 | Current backchain pointer 4 |-/ during
83 |--------------------------------------------| <<< ffi_call_SYSV
88 void ffi_prep_args_SYSV(extended_cif
*ecif
, unsigned *const stack
)
91 const unsigned bytes
= ecif
->cif
->bytes
;
92 const unsigned flags
= ecif
->cif
->flags
;
94 /* 'stacktop' points at the previous backchain pointer. */
95 unsigned *const stacktop
= stack
+ (bytes
/ sizeof(unsigned));
97 /* 'gpr_base' points at the space for gpr3, and grows upwards as
98 we use GPR registers. */
99 unsigned *gpr_base
= stacktop
- ASM_NEEDS_REGISTERS
- NUM_GPR_ARG_REGISTERS
;
100 int intarg_count
= 0;
102 /* 'fpr_base' points at the space for fpr1, and grows upwards as
103 we use FPR registers. */
104 double *fpr_base
= (double *)gpr_base
- NUM_FPR_ARG_REGISTERS
;
107 /* 'copy_space' grows down as we put structures in it. It should
108 stay 16-byte aligned. */
109 char *copy_space
= ((flags
& FLAG_FP_ARGUMENTS
)
113 /* 'next_arg' grows up as we put parameters in it. */
114 unsigned *next_arg
= stack
+ 2;
120 size_t struct_copy_size
;
123 /* Check that everything starts aligned properly. */
124 FFI_ASSERT(((unsigned)(char *)stack
& 0xF) == 0);
125 FFI_ASSERT(((unsigned)(char *)copy_space
& 0xF) == 0);
126 FFI_ASSERT(((unsigned)(char *)stacktop
& 0xF) == 0);
127 FFI_ASSERT((bytes
& 0xF) == 0);
128 FFI_ASSERT(copy_space
>= (char *)next_arg
);
130 /* Deal with return values that are actually pass-by-reference. */
131 if (flags
& FLAG_RETVAL_REFERENCE
)
133 *gpr_base
++ = (unsigned long)(char *)ecif
->rvalue
;
137 /* Now for the arguments. */
138 p_argv
= ecif
->avalue
;
139 for (ptr
= ecif
->cif
->arg_types
, i
= ecif
->cif
->nargs
;
141 i
--, ptr
++, p_argv
++)
143 switch ((*ptr
)->type
)
146 double_tmp
= *(float *)*p_argv
;
147 if (fparg_count
>= NUM_FPR_ARG_REGISTERS
)
149 *(float *)next_arg
= (float)double_tmp
;
153 *fpr_base
++ = double_tmp
;
155 FFI_ASSERT(flags
& FLAG_FP_ARGUMENTS
);
158 case FFI_TYPE_DOUBLE
:
159 double_tmp
= *(double *)*p_argv
;
161 if (fparg_count
>= NUM_FPR_ARG_REGISTERS
)
163 if (intarg_count
%2 != 0)
168 *(double *)next_arg
= double_tmp
;
172 *fpr_base
++ = double_tmp
;
174 FFI_ASSERT(flags
& FLAG_FP_ARGUMENTS
);
177 case FFI_TYPE_UINT64
:
178 case FFI_TYPE_SINT64
:
179 if (intarg_count
== NUM_GPR_ARG_REGISTERS
-1)
181 if (intarg_count
>= NUM_GPR_ARG_REGISTERS
)
183 if (intarg_count
%2 != 0)
188 *(long long *)next_arg
= *(long long *)*p_argv
;
193 /* whoops: abi states only certain register pairs
194 * can be used for passing long long int
195 * specifically (r3,r4), (r5,r6), (r7,r8),
196 * (r9,r10) and if next arg is long long but
197 * not correct starting register of pair then skip
198 * until the proper starting register
200 if (intarg_count
%2 != 0)
205 *(long long *)gpr_base
= *(long long *)*p_argv
;
211 case FFI_TYPE_STRUCT
:
212 #if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
213 case FFI_TYPE_LONGDOUBLE
:
215 struct_copy_size
= ((*ptr
)->size
+ 15) & ~0xF;
216 copy_space
-= struct_copy_size
;
217 memcpy(copy_space
, (char *)*p_argv
, (*ptr
)->size
);
219 gprvalue
= (unsigned long)copy_space
;
221 FFI_ASSERT(copy_space
> (char *)next_arg
);
222 FFI_ASSERT(flags
& FLAG_ARG_NEEDS_COPY
);
226 gprvalue
= *(unsigned char *)*p_argv
;
229 gprvalue
= *(signed char *)*p_argv
;
231 case FFI_TYPE_UINT16
:
232 gprvalue
= *(unsigned short *)*p_argv
;
234 case FFI_TYPE_SINT16
:
235 gprvalue
= *(signed short *)*p_argv
;
239 case FFI_TYPE_UINT32
:
240 case FFI_TYPE_SINT32
:
241 case FFI_TYPE_POINTER
:
242 gprvalue
= *(unsigned *)*p_argv
;
244 if (intarg_count
>= NUM_GPR_ARG_REGISTERS
)
245 *next_arg
++ = gprvalue
;
247 *gpr_base
++ = gprvalue
;
253 /* Check that we didn't overrun the stack... */
254 FFI_ASSERT(copy_space
>= (char *)next_arg
);
255 FFI_ASSERT(gpr_base
<= stacktop
- ASM_NEEDS_REGISTERS
);
256 FFI_ASSERT((unsigned *)fpr_base
257 <= stacktop
- ASM_NEEDS_REGISTERS
- NUM_GPR_ARG_REGISTERS
);
258 FFI_ASSERT(flags
& FLAG_4_GPR_ARGUMENTS
|| intarg_count
<= 4);
261 /* About the LINUX64 ABI. */
263 NUM_GPR_ARG_REGISTERS64
= 8,
264 NUM_FPR_ARG_REGISTERS64
= 13
266 enum { ASM_NEEDS_REGISTERS64
= 4 };
268 /* ffi_prep_args64 is called by the assembly routine once stack space
269 has been allocated for the function's arguments.
271 The stack layout we want looks like this:
273 | Ret addr from ffi_call_LINUX64 8bytes | higher addresses
274 |--------------------------------------------|
275 | CR save area 8bytes |
276 |--------------------------------------------|
277 | Previous backchain pointer 8 | stack pointer here
278 |--------------------------------------------|<+ <<< on entry to
279 | Saved r28-r31 4*8 | | ffi_call_LINUX64
280 |--------------------------------------------| |
281 | GPR registers r3-r10 8*8 | |
282 |--------------------------------------------| |
283 | FPR registers f1-f13 (optional) 13*8 | |
284 |--------------------------------------------| |
285 | Parameter save area | |
286 |--------------------------------------------| |
287 | TOC save area 8 | |
288 |--------------------------------------------| | stack |
289 | Linker doubleword 8 | | grows |
290 |--------------------------------------------| | down V
291 | Compiler doubleword 8 | |
292 |--------------------------------------------| | lower addresses
293 | Space for callee's LR 8 | |
294 |--------------------------------------------| |
296 |--------------------------------------------| | stack pointer here
297 | Current backchain pointer 8 |-/ during
298 |--------------------------------------------| <<< ffi_call_LINUX64
303 void hidden
ffi_prep_args64(extended_cif
*ecif
, unsigned long *const stack
)
306 const unsigned long bytes
= ecif
->cif
->bytes
;
307 const unsigned long flags
= ecif
->cif
->flags
;
309 /* 'stacktop' points at the previous backchain pointer. */
310 unsigned long *const stacktop
= stack
+ (bytes
/ sizeof(unsigned long));
312 /* 'next_arg' points at the space for gpr3, and grows upwards as
313 we use GPR registers, then continues at rest. */
314 unsigned long *const gpr_base
= stacktop
- ASM_NEEDS_REGISTERS64
315 - NUM_GPR_ARG_REGISTERS64
;
316 unsigned long *const gpr_end
= gpr_base
+ NUM_GPR_ARG_REGISTERS64
;
317 unsigned long *const rest
= stack
+ 6 + NUM_GPR_ARG_REGISTERS64
;
318 unsigned long *next_arg
= gpr_base
;
320 /* 'fpr_base' points at the space for fpr3, and grows upwards as
321 we use FPR registers. */
322 double *fpr_base
= (double *)gpr_base
- NUM_FPR_ARG_REGISTERS64
;
329 unsigned long gprvalue
;
331 /* Check that everything starts aligned properly. */
332 FFI_ASSERT(((unsigned long)(char *)stack
& 0xF) == 0);
333 FFI_ASSERT(((unsigned long)(char *)stacktop
& 0xF) == 0);
334 FFI_ASSERT((bytes
& 0xF) == 0);
336 /* Deal with return values that are actually pass-by-reference. */
337 if (flags
& FLAG_RETVAL_REFERENCE
)
338 *next_arg
++ = (unsigned long)(char *)ecif
->rvalue
;
340 /* Now for the arguments. */
341 p_argv
= ecif
->avalue
;
342 for (ptr
= ecif
->cif
->arg_types
, i
= ecif
->cif
->nargs
;
344 i
--, ptr
++, p_argv
++)
346 switch ((*ptr
)->type
)
349 double_tmp
= *(float *)*p_argv
;
350 *(float *)next_arg
= (float)double_tmp
;
351 if (++next_arg
== gpr_end
)
353 if (fparg_count
< NUM_FPR_ARG_REGISTERS64
)
354 *fpr_base
++ = double_tmp
;
356 FFI_ASSERT(flags
& FLAG_FP_ARGUMENTS
);
359 case FFI_TYPE_DOUBLE
:
360 double_tmp
= *(double *)*p_argv
;
361 *(double *)next_arg
= double_tmp
;
362 if (++next_arg
== gpr_end
)
364 if (fparg_count
< NUM_FPR_ARG_REGISTERS64
)
365 *fpr_base
++ = double_tmp
;
367 FFI_ASSERT(flags
& FLAG_FP_ARGUMENTS
);
370 #if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
371 case FFI_TYPE_LONGDOUBLE
:
372 double_tmp
= ((double *) *p_argv
)[0];
373 *(double *) next_arg
= double_tmp
;
374 if (++next_arg
== gpr_end
)
376 if (fparg_count
< NUM_FPR_ARG_REGISTERS64
)
377 *fpr_base
++ = double_tmp
;
379 double_tmp
= ((double *) *p_argv
)[1];
380 *(double *) next_arg
= double_tmp
;
381 if (++next_arg
== gpr_end
)
383 if (fparg_count
< NUM_FPR_ARG_REGISTERS64
)
384 *fpr_base
++ = double_tmp
;
386 FFI_ASSERT(flags
& FLAG_FP_ARGUMENTS
);
390 case FFI_TYPE_STRUCT
:
391 words
= ((*ptr
)->size
+ 7) / 8;
392 if (next_arg
>= gpr_base
&& next_arg
+ words
> gpr_end
)
394 size_t first
= (char *) gpr_end
- (char *) next_arg
;
395 memcpy((char *) next_arg
, (char *) *p_argv
, first
);
396 memcpy((char *) rest
, (char *) *p_argv
+ first
,
397 (*ptr
)->size
- first
);
398 next_arg
= (unsigned long *) ((char *) rest
+ words
* 8 - first
);
402 char *where
= (char *) next_arg
;
404 /* Structures with size less than eight bytes are passed
406 if ((*ptr
)->size
< 8)
407 where
+= 8 - (*ptr
)->size
;
409 memcpy (where
, (char *) *p_argv
, (*ptr
)->size
);
411 if (next_arg
== gpr_end
)
417 gprvalue
= *(unsigned char *)*p_argv
;
420 gprvalue
= *(signed char *)*p_argv
;
422 case FFI_TYPE_UINT16
:
423 gprvalue
= *(unsigned short *)*p_argv
;
425 case FFI_TYPE_SINT16
:
426 gprvalue
= *(signed short *)*p_argv
;
428 case FFI_TYPE_UINT32
:
429 gprvalue
= *(unsigned int *)*p_argv
;
432 case FFI_TYPE_SINT32
:
433 gprvalue
= *(signed int *)*p_argv
;
436 case FFI_TYPE_UINT64
:
437 case FFI_TYPE_SINT64
:
438 case FFI_TYPE_POINTER
:
439 gprvalue
= *(unsigned long *)*p_argv
;
441 *next_arg
++ = gprvalue
;
442 if (next_arg
== gpr_end
)
448 FFI_ASSERT(flags
& FLAG_4_GPR_ARGUMENTS
449 || (next_arg
>= gpr_base
&& next_arg
<= gpr_base
+ 4));
454 /* Perform machine dependent cif processing */
455 ffi_status
ffi_prep_cif_machdep(ffi_cif
*cif
)
457 /* All this is for the SYSV and LINUX64 ABI. */
461 int fparg_count
= 0, intarg_count
= 0;
463 unsigned struct_copy_size
= 0;
464 unsigned type
= cif
->rtype
->type
;
466 if (cif
->abi
!= FFI_LINUX64
)
468 /* All the machine-independent calculation of cif->bytes will be wrong.
469 Redo the calculation for SYSV. */
471 /* Space for the frame pointer, callee's LR, and the asm's temp regs. */
472 bytes
= (2 + ASM_NEEDS_REGISTERS
) * sizeof(int);
474 /* Space for the GPR registers. */
475 bytes
+= NUM_GPR_ARG_REGISTERS
* sizeof(int);
481 /* Space for backchain, CR, LR, cc/ld doubleword, TOC and the asm's temp
483 bytes
= (6 + ASM_NEEDS_REGISTERS64
) * sizeof(long);
485 /* Space for the mandatory parm save area and general registers. */
486 bytes
+= 2 * NUM_GPR_ARG_REGISTERS64
* sizeof(long);
488 #if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
489 if (type
== FFI_TYPE_LONGDOUBLE
)
490 type
= FFI_TYPE_DOUBLE
;
494 /* Return value handling. The rules for SYSV are as follows:
495 - 32-bit (or less) integer values are returned in gpr3;
496 - Structures of size <= 4 bytes also returned in gpr3;
497 - 64-bit integer values and structures between 5 and 8 bytes are returned
499 - Single/double FP values are returned in fpr1;
500 - Larger structures and long double (if not equivalent to double) values
501 are allocated space and a pointer is passed as the first argument.
503 - integer values in gpr3;
504 - Structures/Unions by reference;
505 - Single/double FP values in fpr1, long double in fpr1,fpr2. */
508 case FFI_TYPE_DOUBLE
:
509 flags
|= FLAG_RETURNS_64BITS
;
512 flags
|= FLAG_RETURNS_FP
;
515 case FFI_TYPE_UINT64
:
516 case FFI_TYPE_SINT64
:
517 flags
|= FLAG_RETURNS_64BITS
;
520 case FFI_TYPE_STRUCT
:
521 if (cif
->abi
!= FFI_GCC_SYSV
&& cif
->abi
!= FFI_LINUX64
)
523 if (cif
->rtype
->size
<= 4)
525 else if (cif
->rtype
->size
<= 8)
527 flags
|= FLAG_RETURNS_64BITS
;
531 /* else fall through. */
532 #if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
533 case FFI_TYPE_LONGDOUBLE
:
536 flags
|= FLAG_RETVAL_REFERENCE
;
539 flags
|= FLAG_RETURNS_NOTHING
;
543 /* Returns 32-bit integer, or similar. Nothing to do here. */
547 if (cif
->abi
!= FFI_LINUX64
)
548 /* The first NUM_GPR_ARG_REGISTERS words of integer arguments, and the
549 first NUM_FPR_ARG_REGISTERS fp arguments, go in registers; the rest
550 goes on the stack. Structures and long doubles (if not equivalent
551 to double) are passed as a pointer to a copy of the structure.
552 Stuff on the stack needs to keep proper alignment. */
553 for (ptr
= cif
->arg_types
, i
= cif
->nargs
; i
> 0; i
--, ptr
++)
555 switch ((*ptr
)->type
)
559 /* floating singles are not 8-aligned on stack */
562 case FFI_TYPE_DOUBLE
:
564 /* If this FP arg is going on the stack, it must be
566 if (fparg_count
> NUM_FPR_ARG_REGISTERS
567 && intarg_count
%2 != 0)
571 case FFI_TYPE_UINT64
:
572 case FFI_TYPE_SINT64
:
573 /* 'long long' arguments are passed as two words, but
574 either both words must fit in registers or both go
575 on the stack. If they go on the stack, they must
576 be 8-byte-aligned. */
577 if (intarg_count
== NUM_GPR_ARG_REGISTERS
-1
578 || (intarg_count
>= NUM_GPR_ARG_REGISTERS
579 && intarg_count
%2 != 0))
584 case FFI_TYPE_STRUCT
:
585 #if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
586 case FFI_TYPE_LONGDOUBLE
:
588 /* We must allocate space for a copy of these to enforce
589 pass-by-value. Pad the space up to a multiple of 16
590 bytes (the maximum alignment required for anything under
592 struct_copy_size
+= ((*ptr
)->size
+ 15) & ~0xF;
593 /* Fall through (allocate space for the pointer). */
596 /* Everything else is passed as a 4-byte word in a GPR, either
597 the object itself or a pointer to it. */
603 for (ptr
= cif
->arg_types
, i
= cif
->nargs
; i
> 0; i
--, ptr
++)
605 switch ((*ptr
)->type
)
607 #if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
608 case FFI_TYPE_LONGDOUBLE
:
614 case FFI_TYPE_DOUBLE
:
619 case FFI_TYPE_STRUCT
:
620 intarg_count
+= ((*ptr
)->size
+ 7) / 8;
624 /* Everything else is passed as a 8-byte word in a GPR, either
625 the object itself or a pointer to it. */
631 if (fparg_count
!= 0)
632 flags
|= FLAG_FP_ARGUMENTS
;
633 if (intarg_count
> 4)
634 flags
|= FLAG_4_GPR_ARGUMENTS
;
635 if (struct_copy_size
!= 0)
636 flags
|= FLAG_ARG_NEEDS_COPY
;
638 if (cif
->abi
!= FFI_LINUX64
)
640 /* Space for the FPR registers, if needed. */
641 if (fparg_count
!= 0)
642 bytes
+= NUM_FPR_ARG_REGISTERS
* sizeof(double);
645 if (intarg_count
> NUM_GPR_ARG_REGISTERS
)
646 bytes
+= (intarg_count
- NUM_GPR_ARG_REGISTERS
) * sizeof(int);
647 if (fparg_count
> NUM_FPR_ARG_REGISTERS
)
648 bytes
+= (fparg_count
- NUM_FPR_ARG_REGISTERS
) * sizeof(double);
652 /* Space for the FPR registers, if needed. */
653 if (fparg_count
!= 0)
654 bytes
+= NUM_FPR_ARG_REGISTERS64
* sizeof(double);
657 if (intarg_count
> NUM_GPR_ARG_REGISTERS64
)
658 bytes
+= (intarg_count
- NUM_GPR_ARG_REGISTERS64
) * sizeof(long);
661 /* The stack space allocated needs to be a multiple of 16 bytes. */
662 bytes
= (bytes
+ 15) & ~0xF;
664 /* Add in the space for the copied structures. */
665 bytes
+= struct_copy_size
;
675 extern void ffi_call_SYSV(/*@out@*/ extended_cif
*,
677 /*@out@*/ unsigned *,
679 extern void hidden
ffi_call_LINUX64(/*@out@*/ extended_cif
*,
680 unsigned long, unsigned long,
681 /*@out@*/ unsigned long *,
686 void ffi_call(/*@dependent@*/ ffi_cif
*cif
,
688 /*@out@*/ void *rvalue
,
689 /*@dependent@*/ void **avalue
)
694 ecif
.avalue
= avalue
;
696 /* If the return value is a struct and we don't have a return */
697 /* value address then we need to make one */
699 if ((rvalue
== NULL
) &&
700 (cif
->rtype
->type
== FFI_TYPE_STRUCT
))
703 ecif
.rvalue
= alloca(cif
->rtype
->size
);
707 ecif
.rvalue
= rvalue
;
716 ffi_call_SYSV(&ecif
, -cif
->bytes
,
717 cif
->flags
, ecif
.rvalue
, fn
);
723 ffi_call_LINUX64(&ecif
, -(long) cif
->bytes
,
724 cif
->flags
, ecif
.rvalue
, fn
);
736 static void flush_icache(char *, int);
738 #define MIN_CACHE_LINE_SIZE 8
740 static void flush_icache(char * addr1
, int size
)
744 for (i
= 0; i
< size
; i
+= MIN_CACHE_LINE_SIZE
) {
746 __asm__
volatile ("icbi 0,%0;" "dcbf 0,%0;" : : "r"(addr
) : "memory");
748 addr
= addr1
+ size
- 1;
749 __asm__
volatile ("icbi 0,%0;" "dcbf 0,%0;" "sync;" "isync;" : : "r"(addr
) : "memory");
754 ffi_prep_closure (ffi_closure
* closure
,
756 void (*fun
)(ffi_cif
*, void*, void**, void*),
760 void **tramp
= (void **) &closure
->tramp
[0];
762 FFI_ASSERT (cif
->abi
== FFI_LINUX64
);
763 /* Copy function address and TOC from ffi_closure_LINUX64. */
764 memcpy (tramp
, (char *) ffi_closure_LINUX64
, 16);
765 tramp
[2] = (void *) closure
;
769 FFI_ASSERT (cif
->abi
== FFI_GCC_SYSV
);
771 tramp
= (unsigned int *) &closure
->tramp
[0];
772 tramp
[0] = 0x7c0802a6; /* mflr r0 */
773 tramp
[1] = 0x4800000d; /* bl 10 <trampoline_initial+0x10> */
774 tramp
[4] = 0x7d6802a6; /* mflr r11 */
775 tramp
[5] = 0x7c0803a6; /* mtlr r0 */
776 tramp
[6] = 0x800b0000; /* lwz r0,0(r11) */
777 tramp
[7] = 0x816b0004; /* lwz r11,4(r11) */
778 tramp
[8] = 0x7c0903a6; /* mtctr r0 */
779 tramp
[9] = 0x4e800420; /* bctr */
780 *(void **) &tramp
[2] = (void *)ffi_closure_SYSV
; /* function */
781 *(void **) &tramp
[3] = (void *)closure
; /* context */
783 /* Flush the icache. */
784 flush_icache(&closure
->tramp
[0],FFI_TRAMPOLINE_SIZE
);
789 closure
->user_data
= user_data
;
800 int ffi_closure_helper_SYSV (ffi_closure
*, void*, unsigned long*,
801 ffi_dblfl
*, unsigned long*);
803 /* Basically the trampoline invokes ffi_closure_SYSV, and on
804 * entry, r11 holds the address of the closure.
805 * After storing the registers that could possibly contain
806 * parameters to be passed into the stack frame and setting
807 * up space for a return value, ffi_closure_SYSV invokes the
808 * following helper function to do most of the work
812 ffi_closure_helper_SYSV (ffi_closure
* closure
, void * rvalue
,
813 unsigned long * pgr
, ffi_dblfl
* pfr
,
816 /* rvalue is the pointer to space for return value in closure assembly */
817 /* pgr is the pointer to where r3-r10 are stored in ffi_closure_SYSV */
818 /* pfr is the pointer to where f1-f8 are stored in ffi_closure_SYSV */
819 /* pst is the pointer to outgoing parameter stack in original caller */
822 ffi_type
** arg_types
;
824 long nf
; /* number of floating registers already used */
825 long ng
; /* number of general registers already used */
830 avalue
= alloca(cif
->nargs
* sizeof(void *));
835 /* Copy the caller's structure return value address so that the closure
836 returns the data directly to the caller. */
837 if (cif
->rtype
->type
== FFI_TYPE_STRUCT
)
839 rvalue
= (void *) *pgr
;
846 arg_types
= cif
->arg_types
;
848 /* Grab the addresses of the arguments from the stack frame. */
851 switch (arg_types
[i
]->type
)
855 /* there are 8 gpr registers used to pass values */
857 avalue
[i
] = (((char *)pgr
)+3);
861 avalue
[i
] = (((char *)pst
)+3);
866 case FFI_TYPE_SINT16
:
867 case FFI_TYPE_UINT16
:
868 /* there are 8 gpr registers used to pass values */
870 avalue
[i
] = (((char *)pgr
)+2);
874 avalue
[i
] = (((char *)pst
)+2);
879 case FFI_TYPE_SINT32
:
880 case FFI_TYPE_UINT32
:
881 case FFI_TYPE_POINTER
:
882 /* there are 8 gpr registers used to pass values */
893 case FFI_TYPE_STRUCT
:
894 /* Structs are passed by reference. The address will appear in a
895 gpr if it is one of the first 8 arguments. */
897 avalue
[i
] = (void *) *pgr
;
901 avalue
[i
] = (void *) *pst
;
906 case FFI_TYPE_SINT64
:
907 case FFI_TYPE_UINT64
:
908 /* passing long long ints are complex, they must
909 * be passed in suitable register pairs such as
910 * (r3,r4) or (r5,r6) or (r6,r7), or (r7,r8) or (r9,r10)
911 * and if the entire pair aren't available then the outgoing
912 * parameter stack is used for both but an alignment of 8
913 * must will be kept. So we must either look in pgr
914 * or pst to find the correct address for this type
919 /* skip r4, r6, r8 as starting points */
927 if (((long)pst
) & 4) pst
++;
934 /* unfortunately float values are stored as doubles
935 * in the ffi_closure_SYSV code (since we don't check
936 * the type in that routine).
939 /* there are 8 64bit floating point registers */
943 pfr
->f
= (float)temp
;
948 /* FIXME? here we are really changing the values
949 * stored in the original calling routines outgoing
950 * parameter stack. This is probably a really
951 * naughty thing to do but...
959 case FFI_TYPE_DOUBLE
:
960 /* On the outgoing stack all values are aligned to 8 */
961 /* there are 8 64bit floating point registers */
968 if (((long)pst
) & 4) pst
++;
983 (closure
->fun
) (cif
, rvalue
, avalue
, closure
->user_data
);
985 /* Tell ffi_closure_SYSV how to perform return type promotions. */
986 return cif
->rtype
->type
;
990 int hidden
ffi_closure_helper_LINUX64 (ffi_closure
*, void*, unsigned long*,
994 ffi_closure_helper_LINUX64 (ffi_closure
*closure
, void *rvalue
,
995 unsigned long *pst
, ffi_dblfl
*pfr
)
997 /* rvalue is the pointer to space for return value in closure assembly */
998 /* pst is the pointer to parameter save area
999 (r3-r10 are stored into its first 8 slots by ffi_closure_LINUX64) */
1000 /* pfr is the pointer to where f1-f13 are stored in ffi_closure_LINUX64 */
1003 ffi_type
**arg_types
;
1006 ffi_dblfl
*end_pfr
= pfr
+ NUM_FPR_ARG_REGISTERS64
;
1009 avalue
= alloca (cif
->nargs
* sizeof (void *));
1011 /* Copy the caller's structure return value address so that the closure
1012 returns the data directly to the caller. */
1013 if (cif
->rtype
->type
== FFI_TYPE_STRUCT
)
1015 rvalue
= (void *) *pst
;
1021 arg_types
= cif
->arg_types
;
1023 /* Grab the addresses of the arguments from the stack frame. */
1026 switch (arg_types
[i
]->type
)
1028 case FFI_TYPE_SINT8
:
1029 case FFI_TYPE_UINT8
:
1030 avalue
[i
] = (char *) pst
+ 7;
1034 case FFI_TYPE_SINT16
:
1035 case FFI_TYPE_UINT16
:
1036 avalue
[i
] = (char *) pst
+ 6;
1040 case FFI_TYPE_SINT32
:
1041 case FFI_TYPE_UINT32
:
1042 avalue
[i
] = (char *) pst
+ 4;
1046 case FFI_TYPE_SINT64
:
1047 case FFI_TYPE_UINT64
:
1048 case FFI_TYPE_POINTER
:
1053 case FFI_TYPE_STRUCT
:
1054 /* Structures with size less than eight bytes are passed
1056 if (arg_types
[i
]->size
< 8)
1057 avalue
[i
] = (char *) pst
+ 8 - arg_types
[i
]->size
;
1060 pst
+= (arg_types
[i
]->size
+ 7) / 8;
1063 case FFI_TYPE_FLOAT
:
1064 /* unfortunately float values are stored as doubles
1065 * in the ffi_closure_LINUX64 code (since we don't check
1066 * the type in that routine).
1069 /* there are 13 64bit floating point registers */
1073 double temp
= pfr
->d
;
1074 pfr
->f
= (float) temp
;
1083 case FFI_TYPE_DOUBLE
:
1084 /* On the outgoing stack all values are aligned to 8 */
1085 /* there are 13 64bit floating point registers */
1097 #if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
1098 case FFI_TYPE_LONGDOUBLE
:
1099 if (pfr
+ 1 < end_pfr
)
1108 /* Passed partly in f13 and partly on the stack.
1109 Move it all to the stack. */
1110 *pst
= *(unsigned long *) pfr
;
1127 (closure
->fun
) (cif
, rvalue
, avalue
, closure
->user_data
);
1129 /* Tell ffi_closure_LINUX64 how to perform return type promotions. */
1130 return cif
->rtype
->type
;