1 /* -----------------------------------------------------------------------
2 ffi_sysv.c - Copyright (C) 2013 IBM
3 Copyright (C) 2011 Anthony Green
4 Copyright (C) 2011 Kyle Moffett
5 Copyright (C) 2008 Red Hat, Inc
6 Copyright (C) 2007, 2008 Free Software Foundation, Inc
7 Copyright (c) 1998 Geoffrey Keating
9 PowerPC Foreign Function Interface
11 Permission is hereby granted, free of charge, to any person obtaining
12 a copy of this software and associated documentation files (the
13 ``Software''), to deal in the Software without restriction, including
14 without limitation the rights to use, copy, modify, merge, publish,
15 distribute, sublicense, and/or sell copies of the Software, and to
16 permit persons to whom the Software is furnished to do so, subject to
17 the following conditions:
19 The above copyright notice and this permission notice shall be included
20 in all copies or substantial portions of the Software.
22 THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS
23 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
24 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
25 IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR
26 OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
27 ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
28 OTHER DEALINGS IN THE SOFTWARE.
29 ----------------------------------------------------------------------- */
34 #include "ffi_common.h"
35 #include "ffi_powerpc.h"
38 /* About the SYSV ABI. */
39 #define ASM_NEEDS_REGISTERS 6
40 #define NUM_GPR_ARG_REGISTERS 8
41 #define NUM_FPR_ARG_REGISTERS 8
44 #if HAVE_LONG_DOUBLE_VARIANT && FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
45 /* Adjust size of ffi_type_longdouble. */
47 ffi_prep_types_sysv (ffi_abi abi
)
49 if ((abi
& (FFI_SYSV
| FFI_SYSV_LONG_DOUBLE_128
)) == FFI_SYSV
)
51 ffi_type_longdouble
.size
= 8;
52 ffi_type_longdouble
.alignment
= 8;
56 ffi_type_longdouble
.size
= 16;
57 ffi_type_longdouble
.alignment
= 16;
62 /* Transform long double, double and float to other types as per abi. */
64 translate_float (int abi
, int type
)
66 #if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
67 if (type
== FFI_TYPE_LONGDOUBLE
68 && (abi
& FFI_SYSV_LONG_DOUBLE_128
) == 0)
69 type
= FFI_TYPE_DOUBLE
;
71 if ((abi
& FFI_SYSV_SOFT_FLOAT
) != 0)
73 if (type
== FFI_TYPE_FLOAT
)
74 type
= FFI_TYPE_UINT32
;
75 else if (type
== FFI_TYPE_DOUBLE
)
76 type
= FFI_TYPE_UINT64
;
77 #if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
78 else if (type
== FFI_TYPE_LONGDOUBLE
)
79 type
= FFI_TYPE_UINT128
;
81 else if ((abi
& FFI_SYSV_IBM_LONG_DOUBLE
) == 0)
83 if (type
== FFI_TYPE_LONGDOUBLE
)
84 type
= FFI_TYPE_STRUCT
;
90 /* Perform machine dependent cif processing */
92 ffi_prep_cif_sysv_core (ffi_cif
*cif
)
96 unsigned i
, fparg_count
= 0, intarg_count
= 0;
97 unsigned flags
= cif
->flags
;
98 unsigned struct_copy_size
= 0;
99 unsigned type
= cif
->rtype
->type
;
100 unsigned size
= cif
->rtype
->size
;
102 /* The machine-independent calculation of cif->bytes doesn't work
103 for us. Redo the calculation. */
105 /* Space for the frame pointer, callee's LR, and the asm's temp regs. */
106 bytes
= (2 + ASM_NEEDS_REGISTERS
) * sizeof (int);
108 /* Space for the GPR registers. */
109 bytes
+= NUM_GPR_ARG_REGISTERS
* sizeof (int);
111 /* Return value handling. The rules for SYSV are as follows:
112 - 32-bit (or less) integer values are returned in gpr3;
113 - Structures of size <= 4 bytes also returned in gpr3;
114 - 64-bit integer values and structures between 5 and 8 bytes are returned
116 - Larger structures are allocated space and a pointer is passed as
118 - Single/double FP values are returned in fpr1;
119 - long doubles (if not equivalent to double) are returned in
120 fpr1,fpr2 for Linux and as for large structs for SysV. */
122 type
= translate_float (cif
->abi
, type
);
126 #if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
127 case FFI_TYPE_LONGDOUBLE
:
128 flags
|= FLAG_RETURNS_128BITS
;
131 case FFI_TYPE_DOUBLE
:
132 flags
|= FLAG_RETURNS_64BITS
;
135 flags
|= FLAG_RETURNS_FP
;
141 case FFI_TYPE_UINT128
:
142 flags
|= FLAG_RETURNS_128BITS
;
144 case FFI_TYPE_UINT64
:
145 case FFI_TYPE_SINT64
:
146 flags
|= FLAG_RETURNS_64BITS
;
149 case FFI_TYPE_STRUCT
:
150 /* The final SYSV ABI says that structures smaller or equal 8 bytes
151 are returned in r3/r4. A draft ABI used by linux instead
152 returns them in memory. */
153 if ((cif
->abi
& FFI_SYSV_STRUCT_RET
) != 0 && size
<= 8)
155 flags
|= FLAG_RETURNS_SMST
;
159 flags
|= FLAG_RETVAL_REFERENCE
;
162 flags
|= FLAG_RETURNS_NOTHING
;
166 /* Returns 32-bit integer, or similar. Nothing to do here. */
170 /* The first NUM_GPR_ARG_REGISTERS words of integer arguments, and the
171 first NUM_FPR_ARG_REGISTERS fp arguments, go in registers; the rest
172 goes on the stack. Structures and long doubles (if not equivalent
173 to double) are passed as a pointer to a copy of the structure.
174 Stuff on the stack needs to keep proper alignment. */
175 for (ptr
= cif
->arg_types
, i
= cif
->nargs
; i
> 0; i
--, ptr
++)
177 unsigned short typenum
= (*ptr
)->type
;
179 typenum
= translate_float (cif
->abi
, typenum
);
183 #if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
184 case FFI_TYPE_LONGDOUBLE
:
188 case FFI_TYPE_DOUBLE
:
190 /* If this FP arg is going on the stack, it must be
192 if (fparg_count
> NUM_FPR_ARG_REGISTERS
193 && intarg_count
>= NUM_GPR_ARG_REGISTERS
194 && intarg_count
% 2 != 0)
208 case FFI_TYPE_UINT128
:
209 /* A long double in FFI_LINUX_SOFT_FLOAT can use only a set
210 of four consecutive gprs. If we do not have enough, we
211 have to adjust the intarg_count value. */
212 if (intarg_count
>= NUM_GPR_ARG_REGISTERS
- 3
213 && intarg_count
< NUM_GPR_ARG_REGISTERS
)
214 intarg_count
= NUM_GPR_ARG_REGISTERS
;
218 case FFI_TYPE_UINT64
:
219 case FFI_TYPE_SINT64
:
220 /* 'long long' arguments are passed as two words, but
221 either both words must fit in registers or both go
222 on the stack. If they go on the stack, they must
225 Also, only certain register pairs can be used for
226 passing long long int -- specifically (r3,r4), (r5,r6),
227 (r7,r8), (r9,r10). */
228 if (intarg_count
== NUM_GPR_ARG_REGISTERS
-1
229 || intarg_count
% 2 != 0)
234 case FFI_TYPE_STRUCT
:
235 /* We must allocate space for a copy of these to enforce
236 pass-by-value. Pad the space up to a multiple of 16
237 bytes (the maximum alignment required for anything under
239 struct_copy_size
+= ((*ptr
)->size
+ 15) & ~0xF;
240 /* Fall through (allocate space for the pointer). */
242 case FFI_TYPE_POINTER
:
244 case FFI_TYPE_UINT32
:
245 case FFI_TYPE_SINT32
:
246 case FFI_TYPE_UINT16
:
247 case FFI_TYPE_SINT16
:
250 /* Everything else is passed as a 4-byte word in a GPR, either
251 the object itself or a pointer to it. */
260 if (fparg_count
!= 0)
261 flags
|= FLAG_FP_ARGUMENTS
;
262 if (intarg_count
> 4)
263 flags
|= FLAG_4_GPR_ARGUMENTS
;
264 if (struct_copy_size
!= 0)
265 flags
|= FLAG_ARG_NEEDS_COPY
;
267 /* Space for the FPR registers, if needed. */
268 if (fparg_count
!= 0)
269 bytes
+= NUM_FPR_ARG_REGISTERS
* sizeof (double);
272 if (intarg_count
> NUM_GPR_ARG_REGISTERS
)
273 bytes
+= (intarg_count
- NUM_GPR_ARG_REGISTERS
) * sizeof (int);
274 if (fparg_count
> NUM_FPR_ARG_REGISTERS
)
275 bytes
+= (fparg_count
- NUM_FPR_ARG_REGISTERS
) * sizeof (double);
277 /* The stack space allocated needs to be a multiple of 16 bytes. */
278 bytes
= (bytes
+ 15) & ~0xF;
280 /* Add in the space for the copied structures. */
281 bytes
+= struct_copy_size
;
289 ffi_status FFI_HIDDEN
290 ffi_prep_cif_sysv (ffi_cif
*cif
)
292 if ((cif
->abi
& FFI_SYSV
) == 0)
294 /* This call is from old code. Translate to new ABI values. */
295 cif
->flags
|= FLAG_COMPAT
;
301 case FFI_COMPAT_SYSV
:
302 cif
->abi
= FFI_SYSV
| FFI_SYSV_STRUCT_RET
| FFI_SYSV_LONG_DOUBLE_128
;
305 case FFI_COMPAT_GCC_SYSV
:
306 cif
->abi
= FFI_SYSV
| FFI_SYSV_LONG_DOUBLE_128
;
309 case FFI_COMPAT_LINUX
:
310 cif
->abi
= (FFI_SYSV
| FFI_SYSV_IBM_LONG_DOUBLE
311 | FFI_SYSV_LONG_DOUBLE_128
);
314 case FFI_COMPAT_LINUX_SOFT_FLOAT
:
315 cif
->abi
= (FFI_SYSV
| FFI_SYSV_SOFT_FLOAT
| FFI_SYSV_IBM_LONG_DOUBLE
316 | FFI_SYSV_LONG_DOUBLE_128
);
320 return ffi_prep_cif_sysv_core (cif
);
323 /* ffi_prep_args_SYSV is called by the assembly routine once stack space
324 has been allocated for the function's arguments.
326 The stack layout we want looks like this:
328 | Return address from ffi_call_SYSV 4bytes | higher addresses
329 |--------------------------------------------|
330 | Previous backchain pointer 4 | stack pointer here
331 |--------------------------------------------|<+ <<< on entry to
332 | Saved r28-r31 4*4 | | ffi_call_SYSV
333 |--------------------------------------------| |
334 | GPR registers r3-r10 8*4 | | ffi_call_SYSV
335 |--------------------------------------------| |
336 | FPR registers f1-f8 (optional) 8*8 | |
337 |--------------------------------------------| | stack |
338 | Space for copied structures | | grows |
339 |--------------------------------------------| | down V
340 | Parameters that didn't fit in registers | |
341 |--------------------------------------------| | lower addresses
342 | Space for callee's LR 4 | |
343 |--------------------------------------------| | stack pointer here
344 | Current backchain pointer 4 |-/ during
345 |--------------------------------------------| <<< ffi_call_SYSV
350 ffi_prep_args_SYSV (extended_cif
*ecif
, unsigned *const stack
)
352 const unsigned bytes
= ecif
->cif
->bytes
;
353 const unsigned flags
= ecif
->cif
->flags
;
364 /* 'stacktop' points at the previous backchain pointer. */
367 /* 'gpr_base' points at the space for gpr3, and grows upwards as
368 we use GPR registers. */
373 /* 'fpr_base' points at the space for fpr1, and grows upwards as
374 we use FPR registers. */
379 /* 'copy_space' grows down as we put structures in it. It should
380 stay 16-byte aligned. */
383 /* 'next_arg' grows up as we put parameters in it. */
404 size_t struct_copy_size
;
407 stacktop
.c
= (char *) stack
+ bytes
;
408 gpr_base
.u
= stacktop
.u
- ASM_NEEDS_REGISTERS
- NUM_GPR_ARG_REGISTERS
;
411 fpr_base
.d
= gpr_base
.d
- NUM_FPR_ARG_REGISTERS
;
413 copy_space
.c
= ((flags
& FLAG_FP_ARGUMENTS
) ? fpr_base
.c
: gpr_base
.c
);
415 copy_space
.c
= gpr_base
.c
;
417 next_arg
.u
= stack
+ 2;
419 /* Check that everything starts aligned properly. */
420 FFI_ASSERT (((unsigned long) (char *) stack
& 0xF) == 0);
421 FFI_ASSERT (((unsigned long) copy_space
.c
& 0xF) == 0);
422 FFI_ASSERT (((unsigned long) stacktop
.c
& 0xF) == 0);
423 FFI_ASSERT ((bytes
& 0xF) == 0);
424 FFI_ASSERT (copy_space
.c
>= next_arg
.c
);
426 /* Deal with return values that are actually pass-by-reference. */
427 if (flags
& FLAG_RETVAL_REFERENCE
)
429 *gpr_base
.u
++ = (unsigned long) (char *) ecif
->rvalue
;
433 /* Now for the arguments. */
434 p_argv
.v
= ecif
->avalue
;
435 for (ptr
= ecif
->cif
->arg_types
, i
= ecif
->cif
->nargs
;
437 i
--, ptr
++, p_argv
.v
++)
439 unsigned int typenum
= (*ptr
)->type
;
441 typenum
= translate_float (ecif
->cif
->abi
, typenum
);
443 /* Now test the translated value */
447 # if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
448 case FFI_TYPE_LONGDOUBLE
:
449 double_tmp
= (*p_argv
.d
)[0];
451 if (fparg_count
>= NUM_FPR_ARG_REGISTERS
- 1)
453 if (intarg_count
>= NUM_GPR_ARG_REGISTERS
454 && intarg_count
% 2 != 0)
459 *next_arg
.d
= double_tmp
;
461 double_tmp
= (*p_argv
.d
)[1];
462 *next_arg
.d
= double_tmp
;
467 *fpr_base
.d
++ = double_tmp
;
468 double_tmp
= (*p_argv
.d
)[1];
469 *fpr_base
.d
++ = double_tmp
;
473 FFI_ASSERT (flags
& FLAG_FP_ARGUMENTS
);
476 case FFI_TYPE_DOUBLE
:
477 double_tmp
= **p_argv
.d
;
479 if (fparg_count
>= NUM_FPR_ARG_REGISTERS
)
481 if (intarg_count
>= NUM_GPR_ARG_REGISTERS
482 && intarg_count
% 2 != 0)
487 *next_arg
.d
= double_tmp
;
491 *fpr_base
.d
++ = double_tmp
;
493 FFI_ASSERT (flags
& FLAG_FP_ARGUMENTS
);
497 double_tmp
= **p_argv
.f
;
498 if (fparg_count
>= NUM_FPR_ARG_REGISTERS
)
500 *next_arg
.f
= (float) double_tmp
;
505 *fpr_base
.d
++ = double_tmp
;
507 FFI_ASSERT (flags
& FLAG_FP_ARGUMENTS
);
509 #endif /* have FPRs */
511 case FFI_TYPE_UINT128
:
512 /* The soft float ABI for long doubles works like this, a long double
513 is passed in four consecutive GPRs if available. A maximum of 2
514 long doubles can be passed in gprs. If we do not have 4 GPRs
515 left, the long double is passed on the stack, 4-byte aligned. */
517 unsigned int int_tmp
;
519 if (intarg_count
>= NUM_GPR_ARG_REGISTERS
- 3)
521 if (intarg_count
< NUM_GPR_ARG_REGISTERS
)
522 intarg_count
= NUM_GPR_ARG_REGISTERS
;
523 for (ii
= 0; ii
< 4; ii
++)
525 int_tmp
= (*p_argv
.ui
)[ii
];
526 *next_arg
.u
++ = int_tmp
;
531 for (ii
= 0; ii
< 4; ii
++)
533 int_tmp
= (*p_argv
.ui
)[ii
];
534 *gpr_base
.u
++ = int_tmp
;
541 case FFI_TYPE_UINT64
:
542 case FFI_TYPE_SINT64
:
543 if (intarg_count
== NUM_GPR_ARG_REGISTERS
-1)
545 if (intarg_count
>= NUM_GPR_ARG_REGISTERS
)
547 if (intarg_count
% 2 != 0)
552 *next_arg
.ll
= **p_argv
.ll
;
557 /* The abi states only certain register pairs can be
558 used for passing long long int specifically (r3,r4),
559 (r5,r6), (r7,r8), (r9,r10). If next arg is long long
560 but not correct starting register of pair then skip
561 until the proper starting register. */
562 if (intarg_count
% 2 != 0)
567 *gpr_base
.ll
++ = **p_argv
.ll
;
572 case FFI_TYPE_STRUCT
:
573 struct_copy_size
= ((*ptr
)->size
+ 15) & ~0xF;
574 copy_space
.c
-= struct_copy_size
;
575 memcpy (copy_space
.c
, *p_argv
.c
, (*ptr
)->size
);
577 gprvalue
= (unsigned long) copy_space
.c
;
579 FFI_ASSERT (copy_space
.c
> next_arg
.c
);
580 FFI_ASSERT (flags
& FLAG_ARG_NEEDS_COPY
);
584 gprvalue
= **p_argv
.uc
;
587 gprvalue
= **p_argv
.sc
;
589 case FFI_TYPE_UINT16
:
590 gprvalue
= **p_argv
.us
;
592 case FFI_TYPE_SINT16
:
593 gprvalue
= **p_argv
.ss
;
597 case FFI_TYPE_UINT32
:
598 case FFI_TYPE_SINT32
:
599 case FFI_TYPE_POINTER
:
601 gprvalue
= **p_argv
.ui
;
604 if (intarg_count
>= NUM_GPR_ARG_REGISTERS
)
605 *next_arg
.u
++ = gprvalue
;
607 *gpr_base
.u
++ = gprvalue
;
613 /* Check that we didn't overrun the stack... */
614 FFI_ASSERT (copy_space
.c
>= next_arg
.c
);
615 FFI_ASSERT (gpr_base
.u
<= stacktop
.u
- ASM_NEEDS_REGISTERS
);
616 /* The assert below is testing that the number of integer arguments agrees
617 with the number found in ffi_prep_cif_machdep(). However, intarg_count
618 is incremented whenever we place an FP arg on the stack, so account for
619 that before our assert test. */
621 if (fparg_count
> NUM_FPR_ARG_REGISTERS
)
622 intarg_count
-= fparg_count
- NUM_FPR_ARG_REGISTERS
;
623 FFI_ASSERT (fpr_base
.u
624 <= stacktop
.u
- ASM_NEEDS_REGISTERS
- NUM_GPR_ARG_REGISTERS
);
626 FFI_ASSERT (flags
& FLAG_4_GPR_ARGUMENTS
|| intarg_count
<= 4);
629 #define MIN_CACHE_LINE_SIZE 8
632 flush_icache (char *wraddr
, char *xaddr
, int size
)
635 for (i
= 0; i
< size
; i
+= MIN_CACHE_LINE_SIZE
)
636 __asm__
volatile ("icbi 0,%0;" "dcbf 0,%1;"
637 : : "r" (xaddr
+ i
), "r" (wraddr
+ i
) : "memory");
638 __asm__
volatile ("icbi 0,%0;" "dcbf 0,%1;" "sync;" "isync;"
639 : : "r"(xaddr
+ size
- 1), "r"(wraddr
+ size
- 1)
643 ffi_status FFI_HIDDEN
644 ffi_prep_closure_loc_sysv (ffi_closure
*closure
,
646 void (*fun
) (ffi_cif
*, void *, void **, void *),
652 if (cif
->abi
< FFI_SYSV
|| cif
->abi
>= FFI_LAST_ABI
)
655 tramp
= (unsigned int *) &closure
->tramp
[0];
656 tramp
[0] = 0x7c0802a6; /* mflr r0 */
657 tramp
[1] = 0x429f0005; /* bcl 20,31,.+4 */
658 tramp
[2] = 0x7d6802a6; /* mflr r11 */
659 tramp
[3] = 0x7c0803a6; /* mtlr r0 */
660 tramp
[4] = 0x800b0018; /* lwz r0,24(r11) */
661 tramp
[5] = 0x816b001c; /* lwz r11,28(r11) */
662 tramp
[6] = 0x7c0903a6; /* mtctr r0 */
663 tramp
[7] = 0x4e800420; /* bctr */
664 *(void **) &tramp
[8] = (void *) ffi_closure_SYSV
; /* function */
665 *(void **) &tramp
[9] = codeloc
; /* context */
667 /* Flush the icache. */
668 flush_icache ((char *)tramp
, (char *)codeloc
, 8 * 4);
672 closure
->user_data
= user_data
;
677 /* Basically the trampoline invokes ffi_closure_SYSV, and on
678 entry, r11 holds the address of the closure.
679 After storing the registers that could possibly contain
680 parameters to be passed into the stack frame and setting
681 up space for a return value, ffi_closure_SYSV invokes the
682 following helper function to do most of the work. */
685 ffi_closure_helper_SYSV (ffi_cif
*cif
,
686 void (*fun
) (ffi_cif
*, void *, void **, void *),
693 /* rvalue is the pointer to space for return value in closure assembly */
694 /* pgr is the pointer to where r3-r10 are stored in ffi_closure_SYSV */
695 /* pfr is the pointer to where f1-f8 are stored in ffi_closure_SYSV */
696 /* pst is the pointer to outgoing parameter stack in original caller */
699 ffi_type
** arg_types
;
702 long nf
= 0; /* number of floating registers already used */
704 long ng
= 0; /* number of general registers already used */
706 unsigned size
= cif
->rtype
->size
;
707 unsigned short rtypenum
= cif
->rtype
->type
;
709 avalue
= alloca (cif
->nargs
* sizeof (void *));
711 /* First translate for softfloat/nonlinux */
712 rtypenum
= translate_float (cif
->abi
, rtypenum
);
714 /* Copy the caller's structure return value address so that the closure
715 returns the data directly to the caller.
716 For FFI_SYSV the result is passed in r3/r4 if the struct size is less
718 if (rtypenum
== FFI_TYPE_STRUCT
719 && !((cif
->abi
& FFI_SYSV_STRUCT_RET
) != 0 && size
<= 8))
721 rvalue
= (void *) *pgr
;
728 arg_types
= cif
->arg_types
;
730 /* Grab the addresses of the arguments from the stack frame. */
732 unsigned short typenum
= arg_types
[i
]->type
;
734 /* We may need to handle some values depending on ABI. */
735 typenum
= translate_float (cif
->abi
, typenum
);
741 /* Unfortunately float values are stored as doubles
742 in the ffi_closure_SYSV code (since we don't check
743 the type in that routine). */
744 if (nf
< NUM_FPR_ARG_REGISTERS
)
746 /* FIXME? here we are really changing the values
747 stored in the original calling routines outgoing
748 parameter stack. This is probably a really
749 naughty thing to do but... */
750 double temp
= pfr
->d
;
751 pfr
->f
= (float) temp
;
763 case FFI_TYPE_DOUBLE
:
764 if (nf
< NUM_FPR_ARG_REGISTERS
)
772 if (((long) pst
) & 4)
779 # if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
780 case FFI_TYPE_LONGDOUBLE
:
781 if (nf
< NUM_FPR_ARG_REGISTERS
- 1)
789 if (((long) pst
) & 4)
799 case FFI_TYPE_UINT128
:
800 /* Test if for the whole long double, 4 gprs are available.
801 otherwise the stuff ends up on the stack. */
802 if (ng
< NUM_GPR_ARG_REGISTERS
- 3)
818 #ifndef __LITTLE_ENDIAN__
819 if (ng
< NUM_GPR_ARG_REGISTERS
)
821 avalue
[i
] = (char *) pgr
+ 3;
827 avalue
[i
] = (char *) pst
+ 3;
833 case FFI_TYPE_SINT16
:
834 case FFI_TYPE_UINT16
:
835 #ifndef __LITTLE_ENDIAN__
836 if (ng
< NUM_GPR_ARG_REGISTERS
)
838 avalue
[i
] = (char *) pgr
+ 2;
844 avalue
[i
] = (char *) pst
+ 2;
850 case FFI_TYPE_SINT32
:
851 case FFI_TYPE_UINT32
:
852 case FFI_TYPE_POINTER
:
853 if (ng
< NUM_GPR_ARG_REGISTERS
)
866 case FFI_TYPE_STRUCT
:
867 /* Structs are passed by reference. The address will appear in a
868 gpr if it is one of the first 8 arguments. */
869 if (ng
< NUM_GPR_ARG_REGISTERS
)
871 avalue
[i
] = (void *) *pgr
;
877 avalue
[i
] = (void *) *pst
;
882 case FFI_TYPE_SINT64
:
883 case FFI_TYPE_UINT64
:
884 /* Passing long long ints are complex, they must
885 be passed in suitable register pairs such as
886 (r3,r4) or (r5,r6) or (r6,r7), or (r7,r8) or (r9,r10)
887 and if the entire pair aren't available then the outgoing
888 parameter stack is used for both but an alignment of 8
889 must will be kept. So we must either look in pgr
890 or pst to find the correct address for this type
892 if (ng
< NUM_GPR_ARG_REGISTERS
- 1)
896 /* skip r4, r6, r8 as starting points */
906 if (((long) pst
) & 4)
910 ng
= NUM_GPR_ARG_REGISTERS
;
921 (*fun
) (cif
, rvalue
, avalue
, user_data
);
923 /* Tell ffi_closure_SYSV how to perform return type promotions.
924 Because the FFI_SYSV ABI returns the structures <= 8 bytes in
925 r3/r4 we have to tell ffi_closure_SYSV how to treat them. We
926 combine the base type FFI_SYSV_TYPE_SMALL_STRUCT with the size of
927 the struct less one. We never have a struct with size zero.
928 See the comment in ffitarget.h about ordering. */
929 if (rtypenum
== FFI_TYPE_STRUCT
930 && (cif
->abi
& FFI_SYSV_STRUCT_RET
) != 0 && size
<= 8)
931 return FFI_SYSV_TYPE_SMALL_STRUCT
- 1 + size
;