1 /* Copyright (c) 2009, 2010, 2011, 2012 ARM Ltd.
3 Permission is hereby granted, free of charge, to any person obtaining
4 a copy of this software and associated documentation files (the
5 ``Software''), to deal in the Software without restriction, including
6 without limitation the rights to use, copy, modify, merge, publish,
7 distribute, sublicense, and/or sell copies of the Software, and to
8 permit persons to whom the Software is furnished to do so, subject to
9 the following conditions:
11 The above copyright notice and this permission notice shall be
12 included in all copies or substantial portions of the Software.
14 THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND,
15 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
17 IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
18 CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
19 TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
20 SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
25 #include <ffi_common.h>
29 /* Stack alignment requirement in bytes */
30 #define AARCH64_STACK_ALIGN 16
35 #define AARCH64_FFI_WITH_V (1 << AARCH64_FFI_WITH_V_BIT)
45 UINT64 x
[AARCH64_N_XREG
];
53 get_x_addr (struct call_context
*context
, unsigned n
)
55 return &context
->x
[n
];
59 get_s_addr (struct call_context
*context
, unsigned n
)
61 #if defined __AARCH64EB__
62 return &context
->v
[n
].d
[1].s
[1];
64 return &context
->v
[n
].d
[0].s
[0];
69 get_d_addr (struct call_context
*context
, unsigned n
)
71 #if defined __AARCH64EB__
72 return &context
->v
[n
].d
[1];
74 return &context
->v
[n
].d
[0];
79 get_v_addr (struct call_context
*context
, unsigned n
)
81 return &context
->v
[n
];
84 /* Return the memory location at which a basic type would reside
85 were it to have been stored in register n. */
88 get_basic_type_addr (unsigned short type
, struct call_context
*context
,
94 return get_s_addr (context
, n
);
96 return get_d_addr (context
, n
);
97 case FFI_TYPE_LONGDOUBLE
:
98 return get_v_addr (context
, n
);
101 case FFI_TYPE_UINT16
:
102 case FFI_TYPE_SINT16
:
103 case FFI_TYPE_UINT32
:
104 case FFI_TYPE_SINT32
:
106 case FFI_TYPE_POINTER
:
107 case FFI_TYPE_UINT64
:
108 case FFI_TYPE_SINT64
:
109 return get_x_addr (context
, n
);
116 /* Return the alignment width for each of the basic types. */
119 get_basic_type_alignment (unsigned short type
)
124 case FFI_TYPE_DOUBLE
:
125 return sizeof (UINT64
);
126 case FFI_TYPE_LONGDOUBLE
:
127 return sizeof (long double);
130 case FFI_TYPE_UINT16
:
131 case FFI_TYPE_SINT16
:
132 case FFI_TYPE_UINT32
:
134 case FFI_TYPE_SINT32
:
135 case FFI_TYPE_POINTER
:
136 case FFI_TYPE_UINT64
:
137 case FFI_TYPE_SINT64
:
138 return sizeof (UINT64
);
146 /* Return the size in bytes for each of the basic types. */
149 get_basic_type_size (unsigned short type
)
154 return sizeof (UINT32
);
155 case FFI_TYPE_DOUBLE
:
156 return sizeof (UINT64
);
157 case FFI_TYPE_LONGDOUBLE
:
158 return sizeof (long double);
160 return sizeof (UINT8
);
162 return sizeof (SINT8
);
163 case FFI_TYPE_UINT16
:
164 return sizeof (UINT16
);
165 case FFI_TYPE_SINT16
:
166 return sizeof (SINT16
);
167 case FFI_TYPE_UINT32
:
168 return sizeof (UINT32
);
170 case FFI_TYPE_SINT32
:
171 return sizeof (SINT32
);
172 case FFI_TYPE_POINTER
:
173 case FFI_TYPE_UINT64
:
174 return sizeof (UINT64
);
175 case FFI_TYPE_SINT64
:
176 return sizeof (SINT64
);
185 ffi_call_SYSV (unsigned (*)(struct call_context
*context
, unsigned char *,
187 struct call_context
*context
,
193 ffi_closure_SYSV (ffi_closure
*);
195 /* Test for an FFI floating point representation. */
198 is_floating_type (unsigned short type
)
200 return (type
== FFI_TYPE_FLOAT
|| type
== FFI_TYPE_DOUBLE
201 || type
== FFI_TYPE_LONGDOUBLE
);
204 /* Test for a homogeneous structure. */
206 static unsigned short
207 get_homogeneous_type (ffi_type
*ty
)
209 if (ty
->type
== FFI_TYPE_STRUCT
&& ty
->elements
)
212 unsigned short candidate_type
213 = get_homogeneous_type (ty
->elements
[0]);
214 for (i
=1; ty
->elements
[i
]; i
++)
216 unsigned short iteration_type
= 0;
217 /* If we have a nested struct, we must find its homogeneous type.
218 If that fits with our candidate type, we are still
220 if (ty
->elements
[i
]->type
== FFI_TYPE_STRUCT
221 && ty
->elements
[i
]->elements
)
223 iteration_type
= get_homogeneous_type (ty
->elements
[i
]);
227 iteration_type
= ty
->elements
[i
]->type
;
230 /* If we are not homogeneous, return FFI_TYPE_STRUCT. */
231 if (candidate_type
!= iteration_type
)
232 return FFI_TYPE_STRUCT
;
234 return candidate_type
;
237 /* Base case, we have no more levels of nesting, so we
238 are a basic type, and so, trivially homogeneous in that type. */
242 /* Determine the number of elements within a STRUCT.
244 Note, we must handle nested structs.
246 If ty is not a STRUCT this function will return 0. */
249 element_count (ffi_type
*ty
)
251 if (ty
->type
== FFI_TYPE_STRUCT
&& ty
->elements
)
255 for (n
= 0; ty
->elements
[n
]; n
++)
257 if (ty
->elements
[n
]->type
== FFI_TYPE_STRUCT
258 && ty
->elements
[n
]->elements
)
259 elems
+= element_count (ty
->elements
[n
]);
268 /* Test for a homogeneous floating point aggregate.
270 A homogeneous floating point aggregate is a homogeneous aggregate of
271 a half- single- or double- precision floating point type with one
272 to four elements. Note that this includes nested structs of the
276 is_hfa (ffi_type
*ty
)
278 if (ty
->type
== FFI_TYPE_STRUCT
280 && is_floating_type (get_homogeneous_type (ty
)))
282 unsigned n
= element_count (ty
);
283 return n
>= 1 && n
<= 4;
288 /* Test if an ffi_type is a candidate for passing in a register.
290 This test does not check that sufficient registers of the
291 appropriate class are actually available, merely that IFF
292 sufficient registers are available then the argument will be passed
295 Note that an ffi_type that is deemed to be a register candidate
296 will always be returned in registers.
298 Returns 1 if a register candidate else 0. */
301 is_register_candidate (ffi_type
*ty
)
307 case FFI_TYPE_DOUBLE
:
308 case FFI_TYPE_LONGDOUBLE
:
310 case FFI_TYPE_UINT16
:
311 case FFI_TYPE_UINT32
:
312 case FFI_TYPE_UINT64
:
313 case FFI_TYPE_POINTER
:
315 case FFI_TYPE_SINT16
:
316 case FFI_TYPE_SINT32
:
318 case FFI_TYPE_SINT64
:
321 case FFI_TYPE_STRUCT
:
326 else if (ty
->size
> 16)
328 /* Too large. Will be replaced with a pointer to memory. The
329 pointer MAY be passed in a register, but the value will
330 not. This test specifically fails since the argument will
331 never be passed by value in registers. */
336 /* Might be passed in registers depending on the number of
337 registers required. */
338 return (ty
->size
+ 7) / 8 < N_X_ARG_REG
;
350 /* Test if an ffi_type argument or result is a candidate for a vector
354 is_v_register_candidate (ffi_type
*ty
)
356 return is_floating_type (ty
->type
)
357 || (ty
->type
== FFI_TYPE_STRUCT
&& is_hfa (ty
));
360 /* Representation of the procedure call argument marshalling
363 The terse state variable names match the names used in the AARCH64
368 unsigned ngrn
; /* Next general-purpose register number. */
369 unsigned nsrn
; /* Next vector register number. */
370 unsigned nsaa
; /* Next stack offset. */
373 /* Initialize a procedure call argument marshalling state. */
375 arg_init (struct arg_state
*state
, unsigned call_frame_size
)
382 /* Return the number of available consecutive core argument
386 available_x (struct arg_state
*state
)
388 return N_X_ARG_REG
- state
->ngrn
;
391 /* Return the number of available consecutive vector argument
395 available_v (struct arg_state
*state
)
397 return N_V_ARG_REG
- state
->nsrn
;
401 allocate_to_x (struct call_context
*context
, struct arg_state
*state
)
403 FFI_ASSERT (state
->ngrn
< N_X_ARG_REG
)
404 return get_x_addr (context
, (state
->ngrn
)++);
408 allocate_to_s (struct call_context
*context
, struct arg_state
*state
)
410 FFI_ASSERT (state
->nsrn
< N_V_ARG_REG
)
411 return get_s_addr (context
, (state
->nsrn
)++);
415 allocate_to_d (struct call_context
*context
, struct arg_state
*state
)
417 FFI_ASSERT (state
->nsrn
< N_V_ARG_REG
)
418 return get_d_addr (context
, (state
->nsrn
)++);
422 allocate_to_v (struct call_context
*context
, struct arg_state
*state
)
424 FFI_ASSERT (state
->nsrn
< N_V_ARG_REG
)
425 return get_v_addr (context
, (state
->nsrn
)++);
428 /* Allocate an aligned slot on the stack and return a pointer to it. */
430 allocate_to_stack (struct arg_state
*state
, void *stack
, unsigned alignment
,
435 /* Round up the NSAA to the larger of 8 or the natural
436 alignment of the argument's type. */
437 state
->nsaa
= ALIGN (state
->nsaa
, alignment
);
438 state
->nsaa
= ALIGN (state
->nsaa
, alignment
);
439 state
->nsaa
= ALIGN (state
->nsaa
, 8);
441 allocation
= stack
+ state
->nsaa
;
448 copy_basic_type (void *dest
, void *source
, unsigned short type
)
450 /* This is neccessary to ensure that basic types are copied
451 sign extended to 64-bits as libffi expects. */
455 *(float *) dest
= *(float *) source
;
457 case FFI_TYPE_DOUBLE
:
458 *(double *) dest
= *(double *) source
;
460 case FFI_TYPE_LONGDOUBLE
:
461 *(long double *) dest
= *(long double *) source
;
464 *(ffi_arg
*) dest
= *(UINT8
*) source
;
467 *(ffi_sarg
*) dest
= *(SINT8
*) source
;
469 case FFI_TYPE_UINT16
:
470 *(ffi_arg
*) dest
= *(UINT16
*) source
;
472 case FFI_TYPE_SINT16
:
473 *(ffi_sarg
*) dest
= *(SINT16
*) source
;
475 case FFI_TYPE_UINT32
:
476 *(ffi_arg
*) dest
= *(UINT32
*) source
;
479 case FFI_TYPE_SINT32
:
480 *(ffi_sarg
*) dest
= *(SINT32
*) source
;
482 case FFI_TYPE_POINTER
:
483 case FFI_TYPE_UINT64
:
484 *(ffi_arg
*) dest
= *(UINT64
*) source
;
486 case FFI_TYPE_SINT64
:
487 *(ffi_sarg
*) dest
= *(SINT64
*) source
;
496 copy_hfa_to_reg_or_stack (void *memory
,
498 struct call_context
*context
,
499 unsigned char *stack
,
500 struct arg_state
*state
)
502 unsigned elems
= element_count (ty
);
503 if (available_v (state
) < elems
)
505 /* There are insufficient V registers. Further V register allocations
506 are prevented, the NSAA is adjusted (by allocate_to_stack ())
507 and the argument is copied to memory at the adjusted NSAA. */
508 state
->nsrn
= N_V_ARG_REG
;
509 memcpy (allocate_to_stack (state
, stack
, ty
->alignment
, ty
->size
),
516 unsigned short type
= get_homogeneous_type (ty
);
517 unsigned elems
= element_count (ty
);
518 for (i
= 0; i
< elems
; i
++)
520 void *reg
= allocate_to_v (context
, state
);
521 copy_basic_type (reg
, memory
, type
);
522 memory
+= get_basic_type_size (type
);
527 /* Either allocate an appropriate register for the argument type, or if
528 none are available, allocate a stack slot and return a pointer
529 to the allocated space. */
532 allocate_to_register_or_stack (struct call_context
*context
,
533 unsigned char *stack
,
534 struct arg_state
*state
,
537 size_t alignment
= get_basic_type_alignment (type
);
538 size_t size
= alignment
;
542 /* This is the only case for which the allocated stack size
543 should not match the alignment of the type. */
544 size
= sizeof (UINT32
);
546 case FFI_TYPE_DOUBLE
:
547 if (state
->nsrn
< N_V_ARG_REG
)
548 return allocate_to_d (context
, state
);
549 state
->nsrn
= N_V_ARG_REG
;
551 case FFI_TYPE_LONGDOUBLE
:
552 if (state
->nsrn
< N_V_ARG_REG
)
553 return allocate_to_v (context
, state
);
554 state
->nsrn
= N_V_ARG_REG
;
558 case FFI_TYPE_UINT16
:
559 case FFI_TYPE_SINT16
:
560 case FFI_TYPE_UINT32
:
561 case FFI_TYPE_SINT32
:
563 case FFI_TYPE_POINTER
:
564 case FFI_TYPE_UINT64
:
565 case FFI_TYPE_SINT64
:
566 if (state
->ngrn
< N_X_ARG_REG
)
567 return allocate_to_x (context
, state
);
568 state
->ngrn
= N_X_ARG_REG
;
574 return allocate_to_stack (state
, stack
, alignment
, size
);
577 /* Copy a value to an appropriate register, or if none are
578 available, to the stack. */
581 copy_to_register_or_stack (struct call_context
*context
,
582 unsigned char *stack
,
583 struct arg_state
*state
,
588 allocate_to_register_or_stack (context
, stack
, state
, type
),
593 /* Marshall the arguments from FFI representation to procedure call
594 context and stack. */
597 aarch64_prep_args (struct call_context
*context
, unsigned char *stack
,
601 struct arg_state state
;
603 arg_init (&state
, ALIGN(ecif
->cif
->bytes
, 16));
605 for (i
= 0; i
< ecif
->cif
->nargs
; i
++)
607 ffi_type
*ty
= ecif
->cif
->arg_types
[i
];
614 /* If the argument is a basic type the argument is allocated to an
615 appropriate register, or if none are available, to the stack. */
617 case FFI_TYPE_DOUBLE
:
618 case FFI_TYPE_LONGDOUBLE
:
621 case FFI_TYPE_UINT16
:
622 case FFI_TYPE_SINT16
:
623 case FFI_TYPE_UINT32
:
625 case FFI_TYPE_SINT32
:
626 case FFI_TYPE_POINTER
:
627 case FFI_TYPE_UINT64
:
628 case FFI_TYPE_SINT64
:
629 copy_to_register_or_stack (context
, stack
, &state
,
630 ecif
->avalue
[i
], ty
->type
);
633 case FFI_TYPE_STRUCT
:
636 copy_hfa_to_reg_or_stack (ecif
->avalue
[i
], ty
, context
,
639 else if (ty
->size
> 16)
641 /* If the argument is a composite type that is larger than 16
642 bytes, then the argument has been copied to memory, and
643 the argument is replaced by a pointer to the copy. */
645 copy_to_register_or_stack (context
, stack
, &state
,
646 &(ecif
->avalue
[i
]), FFI_TYPE_POINTER
);
648 else if (available_x (&state
) >= (ty
->size
+ 7) / 8)
650 /* If the argument is a composite type and the size in
651 double-words is not more than the number of available
652 X registers, then the argument is copied into consecutive
655 for (j
= 0; j
< (ty
->size
+ 7) / 8; j
++)
657 memcpy (allocate_to_x (context
, &state
),
658 &(((UINT64
*) ecif
->avalue
[i
])[j
]),
664 /* Otherwise, there are insufficient X registers. Further X
665 register allocations are prevented, the NSAA is adjusted
666 (by allocate_to_stack ()) and the argument is copied to
667 memory at the adjusted NSAA. */
668 state
.ngrn
= N_X_ARG_REG
;
670 memcpy (allocate_to_stack (&state
, stack
, ty
->alignment
,
671 ty
->size
), ecif
->avalue
+ i
, ty
->size
);
681 return ecif
->cif
->aarch64_flags
;
685 ffi_prep_cif_machdep (ffi_cif
*cif
)
687 /* Round the stack up to a multiple of the stack alignment requirement. */
689 (cif
->bytes
+ (AARCH64_STACK_ALIGN
- 1)) & ~ (AARCH64_STACK_ALIGN
- 1);
691 /* Initialize our flags. We are interested if this CIF will touch a
692 vector register, if so we will enable context save and load to
693 those registers, otherwise not. This is intended to be friendly
694 to lazy float context switching in the kernel. */
695 cif
->aarch64_flags
= 0;
697 if (is_v_register_candidate (cif
->rtype
))
699 cif
->aarch64_flags
|= AARCH64_FFI_WITH_V
;
704 for (i
= 0; i
< cif
->nargs
; i
++)
705 if (is_v_register_candidate (cif
->arg_types
[i
]))
707 cif
->aarch64_flags
|= AARCH64_FFI_WITH_V
;
715 /* Call a function with the provided arguments and capture the return
718 ffi_call (ffi_cif
*cif
, void (*fn
)(void), void *rvalue
, void **avalue
)
723 ecif
.avalue
= avalue
;
724 ecif
.rvalue
= rvalue
;
730 struct call_context context
;
731 unsigned stack_bytes
;
733 /* Figure out the total amount of stack space we need, the
734 above call frame space needs to be 16 bytes aligned to
735 ensure correct alignment of the first object inserted in
736 that space hence the ALIGN applied to cif->bytes.*/
737 stack_bytes
= ALIGN(cif
->bytes
, 16);
739 memset (&context
, 0, sizeof (context
));
740 if (is_register_candidate (cif
->rtype
))
742 ffi_call_SYSV (aarch64_prep_args
, &context
, &ecif
, stack_bytes
, fn
);
743 switch (cif
->rtype
->type
)
747 case FFI_TYPE_DOUBLE
:
748 case FFI_TYPE_LONGDOUBLE
:
751 case FFI_TYPE_UINT16
:
752 case FFI_TYPE_SINT16
:
753 case FFI_TYPE_UINT32
:
754 case FFI_TYPE_SINT32
:
755 case FFI_TYPE_POINTER
:
756 case FFI_TYPE_UINT64
:
758 case FFI_TYPE_SINT64
:
760 void *addr
= get_basic_type_addr (cif
->rtype
->type
,
762 copy_basic_type (rvalue
, addr
, cif
->rtype
->type
);
766 case FFI_TYPE_STRUCT
:
767 if (is_hfa (cif
->rtype
))
770 unsigned short type
= get_homogeneous_type (cif
->rtype
);
771 unsigned elems
= element_count (cif
->rtype
);
772 for (j
= 0; j
< elems
; j
++)
774 void *reg
= get_basic_type_addr (type
, &context
, j
);
775 copy_basic_type (rvalue
, reg
, type
);
776 rvalue
+= get_basic_type_size (type
);
779 else if ((cif
->rtype
->size
+ 7) / 8 < N_X_ARG_REG
)
781 unsigned size
= ALIGN (cif
->rtype
->size
, sizeof (UINT64
));
782 memcpy (rvalue
, get_x_addr (&context
, 0), size
);
797 memcpy (get_x_addr (&context
, 8), &rvalue
, sizeof (UINT64
));
798 ffi_call_SYSV (aarch64_prep_args
, &context
, &ecif
,
810 static unsigned char trampoline
[] =
811 { 0x70, 0x00, 0x00, 0x58, /* ldr x16, 1f */
812 0x91, 0x00, 0x00, 0x10, /* adr x17, 2f */
813 0x00, 0x02, 0x1f, 0xd6 /* br x16 */
816 /* Build a trampoline. */
818 #define FFI_INIT_TRAMPOLINE(TRAMP,FUN,CTX,FLAGS) \
819 ({unsigned char *__tramp = (unsigned char*)(TRAMP); \
820 UINT64 __fun = (UINT64)(FUN); \
821 UINT64 __ctx = (UINT64)(CTX); \
822 UINT64 __flags = (UINT64)(FLAGS); \
823 memcpy (__tramp, trampoline, sizeof (trampoline)); \
824 memcpy (__tramp + 12, &__fun, sizeof (__fun)); \
825 memcpy (__tramp + 20, &__ctx, sizeof (__ctx)); \
826 memcpy (__tramp + 28, &__flags, sizeof (__flags)); \
827 __clear_cache(__tramp, __tramp + FFI_TRAMPOLINE_SIZE); \
831 ffi_prep_closure_loc (ffi_closure
* closure
,
833 void (*fun
)(ffi_cif
*,void*,void**,void*),
837 if (cif
->abi
!= FFI_SYSV
)
840 FFI_INIT_TRAMPOLINE (&closure
->tramp
[0], &ffi_closure_SYSV
, codeloc
,
844 closure
->user_data
= user_data
;
850 /* Primary handler to setup and invoke a function within a closure.
852 A closure when invoked enters via the assembler wrapper
853 ffi_closure_SYSV(). The wrapper allocates a call context on the
854 stack, saves the interesting registers (from the perspective of
855 the calling convention) into the context then passes control to
856 ffi_closure_SYSV_inner() passing the saved context and a pointer to
857 the stack at the point ffi_closure_SYSV() was invoked.
859 On the return path the assembler wrapper will reload call context
862 ffi_closure_SYSV_inner() marshalls the call context into ffi value
863 desriptors, invokes the wrapped function, then marshalls the return
864 value back into the call context. */
867 ffi_closure_SYSV_inner (ffi_closure
*closure
, struct call_context
*context
,
870 ffi_cif
*cif
= closure
->cif
;
871 void **avalue
= (void**) alloca (cif
->nargs
* sizeof (void*));
874 struct arg_state state
;
876 arg_init (&state
, ALIGN(cif
->bytes
, 16));
878 for (i
= 0; i
< cif
->nargs
; i
++)
880 ffi_type
*ty
= cif
->arg_types
[i
];
890 case FFI_TYPE_UINT16
:
891 case FFI_TYPE_SINT16
:
892 case FFI_TYPE_UINT32
:
893 case FFI_TYPE_SINT32
:
895 case FFI_TYPE_POINTER
:
896 case FFI_TYPE_UINT64
:
897 case FFI_TYPE_SINT64
:
899 case FFI_TYPE_DOUBLE
:
900 case FFI_TYPE_LONGDOUBLE
:
901 avalue
[i
] = allocate_to_register_or_stack (context
, stack
,
905 case FFI_TYPE_STRUCT
:
908 unsigned n
= element_count (ty
);
909 if (available_v (&state
) < n
)
911 state
.nsrn
= N_V_ARG_REG
;
912 avalue
[i
] = allocate_to_stack (&state
, stack
, ty
->alignment
,
917 switch (get_homogeneous_type (ty
))
921 /* Eeek! We need a pointer to the structure,
922 however the homogeneous float elements are
923 being passed in individual S registers,
924 therefore the structure is not represented as
925 a contiguous sequence of bytes in our saved
926 register context. We need to fake up a copy
927 of the structure layed out in memory
928 correctly. The fake can be tossed once the
929 closure function has returned hence alloca()
932 UINT32
*p
= avalue
[i
] = alloca (ty
->size
);
933 for (j
= 0; j
< element_count (ty
); j
++)
935 allocate_to_s (context
, &state
),
940 case FFI_TYPE_DOUBLE
:
942 /* Eeek! We need a pointer to the structure,
943 however the homogeneous float elements are
944 being passed in individual S registers,
945 therefore the structure is not represented as
946 a contiguous sequence of bytes in our saved
947 register context. We need to fake up a copy
948 of the structure layed out in memory
949 correctly. The fake can be tossed once the
950 closure function has returned hence alloca()
953 UINT64
*p
= avalue
[i
] = alloca (ty
->size
);
954 for (j
= 0; j
< element_count (ty
); j
++)
956 allocate_to_d (context
, &state
),
961 case FFI_TYPE_LONGDOUBLE
:
963 allocate_to_v (context
, &state
),
973 else if (ty
->size
> 16)
975 /* Replace Composite type of size greater than 16 with a
978 allocate_to_register_or_stack (context
, stack
,
979 &state
, FFI_TYPE_POINTER
),
982 else if (available_x (&state
) >= (ty
->size
+ 7) / 8)
984 avalue
[i
] = get_x_addr (context
, state
.ngrn
);
985 state
.ngrn
+= (ty
->size
+ 7) / 8;
989 state
.ngrn
= N_X_ARG_REG
;
991 avalue
[i
] = allocate_to_stack (&state
, stack
, ty
->alignment
,
1002 /* Figure out where the return value will be passed, either in
1003 registers or in a memory block allocated by the caller and passed
1006 if (is_register_candidate (cif
->rtype
))
1008 /* Register candidates are *always* returned in registers. */
1010 /* Allocate a scratchpad for the return value, we will let the
1011 callee scrible the result into the scratch pad then move the
1012 contents into the appropriate return value location for the
1014 rvalue
= alloca (cif
->rtype
->size
);
1015 (closure
->fun
) (cif
, rvalue
, avalue
, closure
->user_data
);
1017 /* Copy the return value into the call context so that it is returned
1018 as expected to our caller. */
1019 switch (cif
->rtype
->type
)
1024 case FFI_TYPE_UINT8
:
1025 case FFI_TYPE_UINT16
:
1026 case FFI_TYPE_UINT32
:
1027 case FFI_TYPE_POINTER
:
1028 case FFI_TYPE_UINT64
:
1029 case FFI_TYPE_SINT8
:
1030 case FFI_TYPE_SINT16
:
1032 case FFI_TYPE_SINT32
:
1033 case FFI_TYPE_SINT64
:
1034 case FFI_TYPE_FLOAT
:
1035 case FFI_TYPE_DOUBLE
:
1036 case FFI_TYPE_LONGDOUBLE
:
1038 void *addr
= get_basic_type_addr (cif
->rtype
->type
, context
, 0);
1039 copy_basic_type (addr
, rvalue
, cif
->rtype
->type
);
1042 case FFI_TYPE_STRUCT
:
1043 if (is_hfa (cif
->rtype
))
1046 unsigned short type
= get_homogeneous_type (cif
->rtype
);
1047 unsigned elems
= element_count (cif
->rtype
);
1048 for (i
= 0; i
< elems
; i
++)
1050 void *reg
= get_basic_type_addr (type
, context
, i
);
1051 copy_basic_type (reg
, rvalue
, type
);
1052 rvalue
+= get_basic_type_size (type
);
1055 else if ((cif
->rtype
->size
+ 7) / 8 < N_X_ARG_REG
)
1057 unsigned size
= ALIGN (cif
->rtype
->size
, sizeof (UINT64
)) ;
1058 memcpy (get_x_addr (context
, 0), rvalue
, size
);
1072 memcpy (&rvalue
, get_x_addr (context
, 8), sizeof (UINT64
));
1073 (closure
->fun
) (cif
, rvalue
, avalue
, closure
->user_data
);