1*1fd5a2e1SPrashanth Swaminathan /* -----------------------------------------------------------------------
2*1fd5a2e1SPrashanth Swaminathan ffi_sysv.c - Copyright (C) 2013 IBM
3*1fd5a2e1SPrashanth Swaminathan Copyright (C) 2011 Anthony Green
4*1fd5a2e1SPrashanth Swaminathan Copyright (C) 2011 Kyle Moffett
5*1fd5a2e1SPrashanth Swaminathan Copyright (C) 2008 Red Hat, Inc
6*1fd5a2e1SPrashanth Swaminathan Copyright (C) 2007, 2008 Free Software Foundation, Inc
7*1fd5a2e1SPrashanth Swaminathan Copyright (c) 1998 Geoffrey Keating
8*1fd5a2e1SPrashanth Swaminathan
9*1fd5a2e1SPrashanth Swaminathan PowerPC Foreign Function Interface
10*1fd5a2e1SPrashanth Swaminathan
11*1fd5a2e1SPrashanth Swaminathan Permission is hereby granted, free of charge, to any person obtaining
12*1fd5a2e1SPrashanth Swaminathan a copy of this software and associated documentation files (the
13*1fd5a2e1SPrashanth Swaminathan ``Software''), to deal in the Software without restriction, including
14*1fd5a2e1SPrashanth Swaminathan without limitation the rights to use, copy, modify, merge, publish,
15*1fd5a2e1SPrashanth Swaminathan distribute, sublicense, and/or sell copies of the Software, and to
16*1fd5a2e1SPrashanth Swaminathan permit persons to whom the Software is furnished to do so, subject to
17*1fd5a2e1SPrashanth Swaminathan the following conditions:
18*1fd5a2e1SPrashanth Swaminathan
19*1fd5a2e1SPrashanth Swaminathan The above copyright notice and this permission notice shall be included
20*1fd5a2e1SPrashanth Swaminathan in all copies or substantial portions of the Software.
21*1fd5a2e1SPrashanth Swaminathan
22*1fd5a2e1SPrashanth Swaminathan THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS
23*1fd5a2e1SPrashanth Swaminathan OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
24*1fd5a2e1SPrashanth Swaminathan MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
25*1fd5a2e1SPrashanth Swaminathan IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR
26*1fd5a2e1SPrashanth Swaminathan OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
27*1fd5a2e1SPrashanth Swaminathan ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
28*1fd5a2e1SPrashanth Swaminathan OTHER DEALINGS IN THE SOFTWARE.
29*1fd5a2e1SPrashanth Swaminathan ----------------------------------------------------------------------- */
30*1fd5a2e1SPrashanth Swaminathan
31*1fd5a2e1SPrashanth Swaminathan #include "ffi.h"
32*1fd5a2e1SPrashanth Swaminathan
33*1fd5a2e1SPrashanth Swaminathan #ifndef POWERPC64
34*1fd5a2e1SPrashanth Swaminathan #include "ffi_common.h"
35*1fd5a2e1SPrashanth Swaminathan #include "ffi_powerpc.h"
36*1fd5a2e1SPrashanth Swaminathan
37*1fd5a2e1SPrashanth Swaminathan
38*1fd5a2e1SPrashanth Swaminathan /* About the SYSV ABI. */
39*1fd5a2e1SPrashanth Swaminathan #define ASM_NEEDS_REGISTERS 6
40*1fd5a2e1SPrashanth Swaminathan #define NUM_GPR_ARG_REGISTERS 8
41*1fd5a2e1SPrashanth Swaminathan #define NUM_FPR_ARG_REGISTERS 8
42*1fd5a2e1SPrashanth Swaminathan
43*1fd5a2e1SPrashanth Swaminathan
44*1fd5a2e1SPrashanth Swaminathan #if HAVE_LONG_DOUBLE_VARIANT && FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
45*1fd5a2e1SPrashanth Swaminathan /* Adjust size of ffi_type_longdouble. */
46*1fd5a2e1SPrashanth Swaminathan void FFI_HIDDEN
ffi_prep_types_sysv(ffi_abi abi)47*1fd5a2e1SPrashanth Swaminathan ffi_prep_types_sysv (ffi_abi abi)
48*1fd5a2e1SPrashanth Swaminathan {
49*1fd5a2e1SPrashanth Swaminathan if ((abi & (FFI_SYSV | FFI_SYSV_LONG_DOUBLE_128)) == FFI_SYSV)
50*1fd5a2e1SPrashanth Swaminathan {
51*1fd5a2e1SPrashanth Swaminathan ffi_type_longdouble.size = 8;
52*1fd5a2e1SPrashanth Swaminathan ffi_type_longdouble.alignment = 8;
53*1fd5a2e1SPrashanth Swaminathan }
54*1fd5a2e1SPrashanth Swaminathan else
55*1fd5a2e1SPrashanth Swaminathan {
56*1fd5a2e1SPrashanth Swaminathan ffi_type_longdouble.size = 16;
57*1fd5a2e1SPrashanth Swaminathan ffi_type_longdouble.alignment = 16;
58*1fd5a2e1SPrashanth Swaminathan }
59*1fd5a2e1SPrashanth Swaminathan }
60*1fd5a2e1SPrashanth Swaminathan #endif
61*1fd5a2e1SPrashanth Swaminathan
62*1fd5a2e1SPrashanth Swaminathan /* Transform long double, double and float to other types as per abi. */
63*1fd5a2e1SPrashanth Swaminathan static int
translate_float(int abi,int type)64*1fd5a2e1SPrashanth Swaminathan translate_float (int abi, int type)
65*1fd5a2e1SPrashanth Swaminathan {
66*1fd5a2e1SPrashanth Swaminathan #if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
67*1fd5a2e1SPrashanth Swaminathan if (type == FFI_TYPE_LONGDOUBLE
68*1fd5a2e1SPrashanth Swaminathan && (abi & FFI_SYSV_LONG_DOUBLE_128) == 0)
69*1fd5a2e1SPrashanth Swaminathan type = FFI_TYPE_DOUBLE;
70*1fd5a2e1SPrashanth Swaminathan #endif
71*1fd5a2e1SPrashanth Swaminathan if ((abi & FFI_SYSV_SOFT_FLOAT) != 0)
72*1fd5a2e1SPrashanth Swaminathan {
73*1fd5a2e1SPrashanth Swaminathan if (type == FFI_TYPE_FLOAT)
74*1fd5a2e1SPrashanth Swaminathan type = FFI_TYPE_UINT32;
75*1fd5a2e1SPrashanth Swaminathan else if (type == FFI_TYPE_DOUBLE)
76*1fd5a2e1SPrashanth Swaminathan type = FFI_TYPE_UINT64;
77*1fd5a2e1SPrashanth Swaminathan #if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
78*1fd5a2e1SPrashanth Swaminathan else if (type == FFI_TYPE_LONGDOUBLE)
79*1fd5a2e1SPrashanth Swaminathan type = FFI_TYPE_UINT128;
80*1fd5a2e1SPrashanth Swaminathan }
81*1fd5a2e1SPrashanth Swaminathan else if ((abi & FFI_SYSV_IBM_LONG_DOUBLE) == 0)
82*1fd5a2e1SPrashanth Swaminathan {
83*1fd5a2e1SPrashanth Swaminathan if (type == FFI_TYPE_LONGDOUBLE)
84*1fd5a2e1SPrashanth Swaminathan type = FFI_TYPE_STRUCT;
85*1fd5a2e1SPrashanth Swaminathan #endif
86*1fd5a2e1SPrashanth Swaminathan }
87*1fd5a2e1SPrashanth Swaminathan return type;
88*1fd5a2e1SPrashanth Swaminathan }
89*1fd5a2e1SPrashanth Swaminathan
90*1fd5a2e1SPrashanth Swaminathan /* Perform machine dependent cif processing */
91*1fd5a2e1SPrashanth Swaminathan static ffi_status
ffi_prep_cif_sysv_core(ffi_cif * cif)92*1fd5a2e1SPrashanth Swaminathan ffi_prep_cif_sysv_core (ffi_cif *cif)
93*1fd5a2e1SPrashanth Swaminathan {
94*1fd5a2e1SPrashanth Swaminathan ffi_type **ptr;
95*1fd5a2e1SPrashanth Swaminathan unsigned bytes;
96*1fd5a2e1SPrashanth Swaminathan unsigned i, fpr_count = 0, gpr_count = 0, stack_count = 0;
97*1fd5a2e1SPrashanth Swaminathan unsigned flags = cif->flags;
98*1fd5a2e1SPrashanth Swaminathan unsigned struct_copy_size = 0;
99*1fd5a2e1SPrashanth Swaminathan unsigned type = cif->rtype->type;
100*1fd5a2e1SPrashanth Swaminathan unsigned size = cif->rtype->size;
101*1fd5a2e1SPrashanth Swaminathan
102*1fd5a2e1SPrashanth Swaminathan /* The machine-independent calculation of cif->bytes doesn't work
103*1fd5a2e1SPrashanth Swaminathan for us. Redo the calculation. */
104*1fd5a2e1SPrashanth Swaminathan
105*1fd5a2e1SPrashanth Swaminathan /* Space for the frame pointer, callee's LR, and the asm's temp regs. */
106*1fd5a2e1SPrashanth Swaminathan bytes = (2 + ASM_NEEDS_REGISTERS) * sizeof (int);
107*1fd5a2e1SPrashanth Swaminathan
108*1fd5a2e1SPrashanth Swaminathan /* Space for the GPR registers. */
109*1fd5a2e1SPrashanth Swaminathan bytes += NUM_GPR_ARG_REGISTERS * sizeof (int);
110*1fd5a2e1SPrashanth Swaminathan
111*1fd5a2e1SPrashanth Swaminathan /* Return value handling. The rules for SYSV are as follows:
112*1fd5a2e1SPrashanth Swaminathan - 32-bit (or less) integer values are returned in gpr3;
113*1fd5a2e1SPrashanth Swaminathan - Structures of size <= 4 bytes also returned in gpr3;
114*1fd5a2e1SPrashanth Swaminathan - 64-bit integer values and structures between 5 and 8 bytes are returned
115*1fd5a2e1SPrashanth Swaminathan in gpr3 and gpr4;
116*1fd5a2e1SPrashanth Swaminathan - Larger structures are allocated space and a pointer is passed as
117*1fd5a2e1SPrashanth Swaminathan the first argument.
118*1fd5a2e1SPrashanth Swaminathan - Single/double FP values are returned in fpr1;
119*1fd5a2e1SPrashanth Swaminathan - long doubles (if not equivalent to double) are returned in
120*1fd5a2e1SPrashanth Swaminathan fpr1,fpr2 for Linux and as for large structs for SysV. */
121*1fd5a2e1SPrashanth Swaminathan
122*1fd5a2e1SPrashanth Swaminathan type = translate_float (cif->abi, type);
123*1fd5a2e1SPrashanth Swaminathan
124*1fd5a2e1SPrashanth Swaminathan switch (type)
125*1fd5a2e1SPrashanth Swaminathan {
126*1fd5a2e1SPrashanth Swaminathan #if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
127*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_LONGDOUBLE:
128*1fd5a2e1SPrashanth Swaminathan flags |= FLAG_RETURNS_128BITS;
129*1fd5a2e1SPrashanth Swaminathan /* Fall through. */
130*1fd5a2e1SPrashanth Swaminathan #endif
131*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_DOUBLE:
132*1fd5a2e1SPrashanth Swaminathan flags |= FLAG_RETURNS_64BITS;
133*1fd5a2e1SPrashanth Swaminathan /* Fall through. */
134*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_FLOAT:
135*1fd5a2e1SPrashanth Swaminathan flags |= FLAG_RETURNS_FP;
136*1fd5a2e1SPrashanth Swaminathan #ifdef __NO_FPRS__
137*1fd5a2e1SPrashanth Swaminathan return FFI_BAD_ABI;
138*1fd5a2e1SPrashanth Swaminathan #endif
139*1fd5a2e1SPrashanth Swaminathan break;
140*1fd5a2e1SPrashanth Swaminathan
141*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_UINT128:
142*1fd5a2e1SPrashanth Swaminathan flags |= FLAG_RETURNS_128BITS;
143*1fd5a2e1SPrashanth Swaminathan /* Fall through. */
144*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_UINT64:
145*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_SINT64:
146*1fd5a2e1SPrashanth Swaminathan flags |= FLAG_RETURNS_64BITS;
147*1fd5a2e1SPrashanth Swaminathan break;
148*1fd5a2e1SPrashanth Swaminathan
149*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_STRUCT:
150*1fd5a2e1SPrashanth Swaminathan /* The final SYSV ABI says that structures smaller or equal 8 bytes
151*1fd5a2e1SPrashanth Swaminathan are returned in r3/r4. A draft ABI used by linux instead
152*1fd5a2e1SPrashanth Swaminathan returns them in memory. */
153*1fd5a2e1SPrashanth Swaminathan if ((cif->abi & FFI_SYSV_STRUCT_RET) != 0 && size <= 8)
154*1fd5a2e1SPrashanth Swaminathan {
155*1fd5a2e1SPrashanth Swaminathan flags |= FLAG_RETURNS_SMST;
156*1fd5a2e1SPrashanth Swaminathan break;
157*1fd5a2e1SPrashanth Swaminathan }
158*1fd5a2e1SPrashanth Swaminathan gpr_count++;
159*1fd5a2e1SPrashanth Swaminathan flags |= FLAG_RETVAL_REFERENCE;
160*1fd5a2e1SPrashanth Swaminathan /* Fall through. */
161*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_VOID:
162*1fd5a2e1SPrashanth Swaminathan flags |= FLAG_RETURNS_NOTHING;
163*1fd5a2e1SPrashanth Swaminathan break;
164*1fd5a2e1SPrashanth Swaminathan
165*1fd5a2e1SPrashanth Swaminathan default:
166*1fd5a2e1SPrashanth Swaminathan /* Returns 32-bit integer, or similar. Nothing to do here. */
167*1fd5a2e1SPrashanth Swaminathan break;
168*1fd5a2e1SPrashanth Swaminathan }
169*1fd5a2e1SPrashanth Swaminathan
170*1fd5a2e1SPrashanth Swaminathan /* The first NUM_GPR_ARG_REGISTERS words of integer arguments, and the
171*1fd5a2e1SPrashanth Swaminathan first NUM_FPR_ARG_REGISTERS fp arguments, go in registers; the rest
172*1fd5a2e1SPrashanth Swaminathan goes on the stack. Structures and long doubles (if not equivalent
173*1fd5a2e1SPrashanth Swaminathan to double) are passed as a pointer to a copy of the structure.
174*1fd5a2e1SPrashanth Swaminathan Stuff on the stack needs to keep proper alignment. */
175*1fd5a2e1SPrashanth Swaminathan for (ptr = cif->arg_types, i = cif->nargs; i > 0; i--, ptr++)
176*1fd5a2e1SPrashanth Swaminathan {
177*1fd5a2e1SPrashanth Swaminathan unsigned short typenum = (*ptr)->type;
178*1fd5a2e1SPrashanth Swaminathan
179*1fd5a2e1SPrashanth Swaminathan typenum = translate_float (cif->abi, typenum);
180*1fd5a2e1SPrashanth Swaminathan
181*1fd5a2e1SPrashanth Swaminathan switch (typenum)
182*1fd5a2e1SPrashanth Swaminathan {
183*1fd5a2e1SPrashanth Swaminathan #if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
184*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_LONGDOUBLE:
185*1fd5a2e1SPrashanth Swaminathan if (fpr_count >= NUM_FPR_ARG_REGISTERS - 1)
186*1fd5a2e1SPrashanth Swaminathan {
187*1fd5a2e1SPrashanth Swaminathan fpr_count = NUM_FPR_ARG_REGISTERS;
188*1fd5a2e1SPrashanth Swaminathan /* 8-byte align long doubles. */
189*1fd5a2e1SPrashanth Swaminathan stack_count += stack_count & 1;
190*1fd5a2e1SPrashanth Swaminathan stack_count += 4;
191*1fd5a2e1SPrashanth Swaminathan }
192*1fd5a2e1SPrashanth Swaminathan else
193*1fd5a2e1SPrashanth Swaminathan fpr_count += 2;
194*1fd5a2e1SPrashanth Swaminathan #ifdef __NO_FPRS__
195*1fd5a2e1SPrashanth Swaminathan return FFI_BAD_ABI;
196*1fd5a2e1SPrashanth Swaminathan #endif
197*1fd5a2e1SPrashanth Swaminathan break;
198*1fd5a2e1SPrashanth Swaminathan #endif
199*1fd5a2e1SPrashanth Swaminathan
200*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_DOUBLE:
201*1fd5a2e1SPrashanth Swaminathan if (fpr_count >= NUM_FPR_ARG_REGISTERS)
202*1fd5a2e1SPrashanth Swaminathan {
203*1fd5a2e1SPrashanth Swaminathan /* 8-byte align doubles. */
204*1fd5a2e1SPrashanth Swaminathan stack_count += stack_count & 1;
205*1fd5a2e1SPrashanth Swaminathan stack_count += 2;
206*1fd5a2e1SPrashanth Swaminathan }
207*1fd5a2e1SPrashanth Swaminathan else
208*1fd5a2e1SPrashanth Swaminathan fpr_count += 1;
209*1fd5a2e1SPrashanth Swaminathan #ifdef __NO_FPRS__
210*1fd5a2e1SPrashanth Swaminathan return FFI_BAD_ABI;
211*1fd5a2e1SPrashanth Swaminathan #endif
212*1fd5a2e1SPrashanth Swaminathan break;
213*1fd5a2e1SPrashanth Swaminathan
214*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_FLOAT:
215*1fd5a2e1SPrashanth Swaminathan if (fpr_count >= NUM_FPR_ARG_REGISTERS)
216*1fd5a2e1SPrashanth Swaminathan /* Yes, we don't follow the ABI, but neither does gcc. */
217*1fd5a2e1SPrashanth Swaminathan stack_count += 1;
218*1fd5a2e1SPrashanth Swaminathan else
219*1fd5a2e1SPrashanth Swaminathan fpr_count += 1;
220*1fd5a2e1SPrashanth Swaminathan #ifdef __NO_FPRS__
221*1fd5a2e1SPrashanth Swaminathan return FFI_BAD_ABI;
222*1fd5a2e1SPrashanth Swaminathan #endif
223*1fd5a2e1SPrashanth Swaminathan break;
224*1fd5a2e1SPrashanth Swaminathan
225*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_UINT128:
226*1fd5a2e1SPrashanth Swaminathan /* A long double in FFI_LINUX_SOFT_FLOAT can use only a set
227*1fd5a2e1SPrashanth Swaminathan of four consecutive gprs. If we do not have enough, we
228*1fd5a2e1SPrashanth Swaminathan have to adjust the gpr_count value. */
229*1fd5a2e1SPrashanth Swaminathan if (gpr_count >= NUM_GPR_ARG_REGISTERS - 3)
230*1fd5a2e1SPrashanth Swaminathan gpr_count = NUM_GPR_ARG_REGISTERS;
231*1fd5a2e1SPrashanth Swaminathan if (gpr_count >= NUM_GPR_ARG_REGISTERS)
232*1fd5a2e1SPrashanth Swaminathan stack_count += 4;
233*1fd5a2e1SPrashanth Swaminathan else
234*1fd5a2e1SPrashanth Swaminathan gpr_count += 4;
235*1fd5a2e1SPrashanth Swaminathan break;
236*1fd5a2e1SPrashanth Swaminathan
237*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_UINT64:
238*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_SINT64:
239*1fd5a2e1SPrashanth Swaminathan /* 'long long' arguments are passed as two words, but
240*1fd5a2e1SPrashanth Swaminathan either both words must fit in registers or both go
241*1fd5a2e1SPrashanth Swaminathan on the stack. If they go on the stack, they must
242*1fd5a2e1SPrashanth Swaminathan be 8-byte-aligned.
243*1fd5a2e1SPrashanth Swaminathan
244*1fd5a2e1SPrashanth Swaminathan Also, only certain register pairs can be used for
245*1fd5a2e1SPrashanth Swaminathan passing long long int -- specifically (r3,r4), (r5,r6),
246*1fd5a2e1SPrashanth Swaminathan (r7,r8), (r9,r10). */
247*1fd5a2e1SPrashanth Swaminathan gpr_count += gpr_count & 1;
248*1fd5a2e1SPrashanth Swaminathan if (gpr_count >= NUM_GPR_ARG_REGISTERS)
249*1fd5a2e1SPrashanth Swaminathan {
250*1fd5a2e1SPrashanth Swaminathan stack_count += stack_count & 1;
251*1fd5a2e1SPrashanth Swaminathan stack_count += 2;
252*1fd5a2e1SPrashanth Swaminathan }
253*1fd5a2e1SPrashanth Swaminathan else
254*1fd5a2e1SPrashanth Swaminathan gpr_count += 2;
255*1fd5a2e1SPrashanth Swaminathan break;
256*1fd5a2e1SPrashanth Swaminathan
257*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_STRUCT:
258*1fd5a2e1SPrashanth Swaminathan /* We must allocate space for a copy of these to enforce
259*1fd5a2e1SPrashanth Swaminathan pass-by-value. Pad the space up to a multiple of 16
260*1fd5a2e1SPrashanth Swaminathan bytes (the maximum alignment required for anything under
261*1fd5a2e1SPrashanth Swaminathan the SYSV ABI). */
262*1fd5a2e1SPrashanth Swaminathan struct_copy_size += ((*ptr)->size + 15) & ~0xF;
263*1fd5a2e1SPrashanth Swaminathan /* Fall through (allocate space for the pointer). */
264*1fd5a2e1SPrashanth Swaminathan
265*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_POINTER:
266*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_INT:
267*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_UINT32:
268*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_SINT32:
269*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_UINT16:
270*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_SINT16:
271*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_UINT8:
272*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_SINT8:
273*1fd5a2e1SPrashanth Swaminathan /* Everything else is passed as a 4-byte word in a GPR, either
274*1fd5a2e1SPrashanth Swaminathan the object itself or a pointer to it. */
275*1fd5a2e1SPrashanth Swaminathan if (gpr_count >= NUM_GPR_ARG_REGISTERS)
276*1fd5a2e1SPrashanth Swaminathan stack_count += 1;
277*1fd5a2e1SPrashanth Swaminathan else
278*1fd5a2e1SPrashanth Swaminathan gpr_count += 1;
279*1fd5a2e1SPrashanth Swaminathan break;
280*1fd5a2e1SPrashanth Swaminathan
281*1fd5a2e1SPrashanth Swaminathan default:
282*1fd5a2e1SPrashanth Swaminathan FFI_ASSERT (0);
283*1fd5a2e1SPrashanth Swaminathan }
284*1fd5a2e1SPrashanth Swaminathan }
285*1fd5a2e1SPrashanth Swaminathan
286*1fd5a2e1SPrashanth Swaminathan if (fpr_count != 0)
287*1fd5a2e1SPrashanth Swaminathan flags |= FLAG_FP_ARGUMENTS;
288*1fd5a2e1SPrashanth Swaminathan if (gpr_count > 4)
289*1fd5a2e1SPrashanth Swaminathan flags |= FLAG_4_GPR_ARGUMENTS;
290*1fd5a2e1SPrashanth Swaminathan if (struct_copy_size != 0)
291*1fd5a2e1SPrashanth Swaminathan flags |= FLAG_ARG_NEEDS_COPY;
292*1fd5a2e1SPrashanth Swaminathan
293*1fd5a2e1SPrashanth Swaminathan /* Space for the FPR registers, if needed. */
294*1fd5a2e1SPrashanth Swaminathan if (fpr_count != 0)
295*1fd5a2e1SPrashanth Swaminathan bytes += NUM_FPR_ARG_REGISTERS * sizeof (double);
296*1fd5a2e1SPrashanth Swaminathan
297*1fd5a2e1SPrashanth Swaminathan /* Stack space. */
298*1fd5a2e1SPrashanth Swaminathan bytes += stack_count * sizeof (int);
299*1fd5a2e1SPrashanth Swaminathan
300*1fd5a2e1SPrashanth Swaminathan /* The stack space allocated needs to be a multiple of 16 bytes. */
301*1fd5a2e1SPrashanth Swaminathan bytes = (bytes + 15) & ~0xF;
302*1fd5a2e1SPrashanth Swaminathan
303*1fd5a2e1SPrashanth Swaminathan /* Add in the space for the copied structures. */
304*1fd5a2e1SPrashanth Swaminathan bytes += struct_copy_size;
305*1fd5a2e1SPrashanth Swaminathan
306*1fd5a2e1SPrashanth Swaminathan cif->flags = flags;
307*1fd5a2e1SPrashanth Swaminathan cif->bytes = bytes;
308*1fd5a2e1SPrashanth Swaminathan
309*1fd5a2e1SPrashanth Swaminathan return FFI_OK;
310*1fd5a2e1SPrashanth Swaminathan }
311*1fd5a2e1SPrashanth Swaminathan
312*1fd5a2e1SPrashanth Swaminathan ffi_status FFI_HIDDEN
ffi_prep_cif_sysv(ffi_cif * cif)313*1fd5a2e1SPrashanth Swaminathan ffi_prep_cif_sysv (ffi_cif *cif)
314*1fd5a2e1SPrashanth Swaminathan {
315*1fd5a2e1SPrashanth Swaminathan if ((cif->abi & FFI_SYSV) == 0)
316*1fd5a2e1SPrashanth Swaminathan {
317*1fd5a2e1SPrashanth Swaminathan /* This call is from old code. Translate to new ABI values. */
318*1fd5a2e1SPrashanth Swaminathan cif->flags |= FLAG_COMPAT;
319*1fd5a2e1SPrashanth Swaminathan switch (cif->abi)
320*1fd5a2e1SPrashanth Swaminathan {
321*1fd5a2e1SPrashanth Swaminathan default:
322*1fd5a2e1SPrashanth Swaminathan return FFI_BAD_ABI;
323*1fd5a2e1SPrashanth Swaminathan
324*1fd5a2e1SPrashanth Swaminathan case FFI_COMPAT_SYSV:
325*1fd5a2e1SPrashanth Swaminathan cif->abi = FFI_SYSV | FFI_SYSV_STRUCT_RET | FFI_SYSV_LONG_DOUBLE_128;
326*1fd5a2e1SPrashanth Swaminathan break;
327*1fd5a2e1SPrashanth Swaminathan
328*1fd5a2e1SPrashanth Swaminathan case FFI_COMPAT_GCC_SYSV:
329*1fd5a2e1SPrashanth Swaminathan cif->abi = FFI_SYSV | FFI_SYSV_LONG_DOUBLE_128;
330*1fd5a2e1SPrashanth Swaminathan break;
331*1fd5a2e1SPrashanth Swaminathan
332*1fd5a2e1SPrashanth Swaminathan case FFI_COMPAT_LINUX:
333*1fd5a2e1SPrashanth Swaminathan cif->abi = (FFI_SYSV | FFI_SYSV_IBM_LONG_DOUBLE
334*1fd5a2e1SPrashanth Swaminathan | FFI_SYSV_LONG_DOUBLE_128);
335*1fd5a2e1SPrashanth Swaminathan break;
336*1fd5a2e1SPrashanth Swaminathan
337*1fd5a2e1SPrashanth Swaminathan case FFI_COMPAT_LINUX_SOFT_FLOAT:
338*1fd5a2e1SPrashanth Swaminathan cif->abi = (FFI_SYSV | FFI_SYSV_SOFT_FLOAT | FFI_SYSV_IBM_LONG_DOUBLE
339*1fd5a2e1SPrashanth Swaminathan | FFI_SYSV_LONG_DOUBLE_128);
340*1fd5a2e1SPrashanth Swaminathan break;
341*1fd5a2e1SPrashanth Swaminathan }
342*1fd5a2e1SPrashanth Swaminathan }
343*1fd5a2e1SPrashanth Swaminathan return ffi_prep_cif_sysv_core (cif);
344*1fd5a2e1SPrashanth Swaminathan }
345*1fd5a2e1SPrashanth Swaminathan
346*1fd5a2e1SPrashanth Swaminathan /* ffi_prep_args_SYSV is called by the assembly routine once stack space
347*1fd5a2e1SPrashanth Swaminathan has been allocated for the function's arguments.
348*1fd5a2e1SPrashanth Swaminathan
349*1fd5a2e1SPrashanth Swaminathan The stack layout we want looks like this:
350*1fd5a2e1SPrashanth Swaminathan
351*1fd5a2e1SPrashanth Swaminathan | Return address from ffi_call_SYSV 4bytes | higher addresses
352*1fd5a2e1SPrashanth Swaminathan |--------------------------------------------|
353*1fd5a2e1SPrashanth Swaminathan | Previous backchain pointer 4 | stack pointer here
354*1fd5a2e1SPrashanth Swaminathan |--------------------------------------------|<+ <<< on entry to
355*1fd5a2e1SPrashanth Swaminathan | Saved r28-r31 4*4 | | ffi_call_SYSV
356*1fd5a2e1SPrashanth Swaminathan |--------------------------------------------| |
357*1fd5a2e1SPrashanth Swaminathan | GPR registers r3-r10 8*4 | | ffi_call_SYSV
358*1fd5a2e1SPrashanth Swaminathan |--------------------------------------------| |
359*1fd5a2e1SPrashanth Swaminathan | FPR registers f1-f8 (optional) 8*8 | |
360*1fd5a2e1SPrashanth Swaminathan |--------------------------------------------| | stack |
361*1fd5a2e1SPrashanth Swaminathan | Space for copied structures | | grows |
362*1fd5a2e1SPrashanth Swaminathan |--------------------------------------------| | down V
363*1fd5a2e1SPrashanth Swaminathan | Parameters that didn't fit in registers | |
364*1fd5a2e1SPrashanth Swaminathan |--------------------------------------------| | lower addresses
365*1fd5a2e1SPrashanth Swaminathan | Space for callee's LR 4 | |
366*1fd5a2e1SPrashanth Swaminathan |--------------------------------------------| | stack pointer here
367*1fd5a2e1SPrashanth Swaminathan | Current backchain pointer 4 |-/ during
368*1fd5a2e1SPrashanth Swaminathan |--------------------------------------------| <<< ffi_call_SYSV
369*1fd5a2e1SPrashanth Swaminathan
370*1fd5a2e1SPrashanth Swaminathan */
371*1fd5a2e1SPrashanth Swaminathan
372*1fd5a2e1SPrashanth Swaminathan void FFI_HIDDEN
ffi_prep_args_SYSV(extended_cif * ecif,unsigned * const stack)373*1fd5a2e1SPrashanth Swaminathan ffi_prep_args_SYSV (extended_cif *ecif, unsigned *const stack)
374*1fd5a2e1SPrashanth Swaminathan {
375*1fd5a2e1SPrashanth Swaminathan const unsigned bytes = ecif->cif->bytes;
376*1fd5a2e1SPrashanth Swaminathan const unsigned flags = ecif->cif->flags;
377*1fd5a2e1SPrashanth Swaminathan
378*1fd5a2e1SPrashanth Swaminathan typedef union
379*1fd5a2e1SPrashanth Swaminathan {
380*1fd5a2e1SPrashanth Swaminathan char *c;
381*1fd5a2e1SPrashanth Swaminathan unsigned *u;
382*1fd5a2e1SPrashanth Swaminathan long long *ll;
383*1fd5a2e1SPrashanth Swaminathan float *f;
384*1fd5a2e1SPrashanth Swaminathan double *d;
385*1fd5a2e1SPrashanth Swaminathan } valp;
386*1fd5a2e1SPrashanth Swaminathan
387*1fd5a2e1SPrashanth Swaminathan /* 'stacktop' points at the previous backchain pointer. */
388*1fd5a2e1SPrashanth Swaminathan valp stacktop;
389*1fd5a2e1SPrashanth Swaminathan
390*1fd5a2e1SPrashanth Swaminathan /* 'gpr_base' points at the space for gpr3, and grows upwards as
391*1fd5a2e1SPrashanth Swaminathan we use GPR registers. */
392*1fd5a2e1SPrashanth Swaminathan valp gpr_base;
393*1fd5a2e1SPrashanth Swaminathan valp gpr_end;
394*1fd5a2e1SPrashanth Swaminathan
395*1fd5a2e1SPrashanth Swaminathan #ifndef __NO_FPRS__
396*1fd5a2e1SPrashanth Swaminathan /* 'fpr_base' points at the space for fpr1, and grows upwards as
397*1fd5a2e1SPrashanth Swaminathan we use FPR registers. */
398*1fd5a2e1SPrashanth Swaminathan valp fpr_base;
399*1fd5a2e1SPrashanth Swaminathan valp fpr_end;
400*1fd5a2e1SPrashanth Swaminathan #endif
401*1fd5a2e1SPrashanth Swaminathan
402*1fd5a2e1SPrashanth Swaminathan /* 'copy_space' grows down as we put structures in it. It should
403*1fd5a2e1SPrashanth Swaminathan stay 16-byte aligned. */
404*1fd5a2e1SPrashanth Swaminathan valp copy_space;
405*1fd5a2e1SPrashanth Swaminathan
406*1fd5a2e1SPrashanth Swaminathan /* 'next_arg' grows up as we put parameters in it. */
407*1fd5a2e1SPrashanth Swaminathan valp next_arg;
408*1fd5a2e1SPrashanth Swaminathan
409*1fd5a2e1SPrashanth Swaminathan int i;
410*1fd5a2e1SPrashanth Swaminathan ffi_type **ptr;
411*1fd5a2e1SPrashanth Swaminathan #ifndef __NO_FPRS__
412*1fd5a2e1SPrashanth Swaminathan double double_tmp;
413*1fd5a2e1SPrashanth Swaminathan #endif
414*1fd5a2e1SPrashanth Swaminathan union
415*1fd5a2e1SPrashanth Swaminathan {
416*1fd5a2e1SPrashanth Swaminathan void **v;
417*1fd5a2e1SPrashanth Swaminathan char **c;
418*1fd5a2e1SPrashanth Swaminathan signed char **sc;
419*1fd5a2e1SPrashanth Swaminathan unsigned char **uc;
420*1fd5a2e1SPrashanth Swaminathan signed short **ss;
421*1fd5a2e1SPrashanth Swaminathan unsigned short **us;
422*1fd5a2e1SPrashanth Swaminathan unsigned int **ui;
423*1fd5a2e1SPrashanth Swaminathan long long **ll;
424*1fd5a2e1SPrashanth Swaminathan float **f;
425*1fd5a2e1SPrashanth Swaminathan double **d;
426*1fd5a2e1SPrashanth Swaminathan } p_argv;
427*1fd5a2e1SPrashanth Swaminathan size_t struct_copy_size;
428*1fd5a2e1SPrashanth Swaminathan unsigned gprvalue;
429*1fd5a2e1SPrashanth Swaminathan
430*1fd5a2e1SPrashanth Swaminathan stacktop.c = (char *) stack + bytes;
431*1fd5a2e1SPrashanth Swaminathan gpr_end.u = stacktop.u - ASM_NEEDS_REGISTERS;
432*1fd5a2e1SPrashanth Swaminathan gpr_base.u = gpr_end.u - NUM_GPR_ARG_REGISTERS;
433*1fd5a2e1SPrashanth Swaminathan #ifndef __NO_FPRS__
434*1fd5a2e1SPrashanth Swaminathan fpr_end.d = gpr_base.d;
435*1fd5a2e1SPrashanth Swaminathan fpr_base.d = fpr_end.d - NUM_FPR_ARG_REGISTERS;
436*1fd5a2e1SPrashanth Swaminathan copy_space.c = ((flags & FLAG_FP_ARGUMENTS) ? fpr_base.c : gpr_base.c);
437*1fd5a2e1SPrashanth Swaminathan #else
438*1fd5a2e1SPrashanth Swaminathan copy_space.c = gpr_base.c;
439*1fd5a2e1SPrashanth Swaminathan #endif
440*1fd5a2e1SPrashanth Swaminathan next_arg.u = stack + 2;
441*1fd5a2e1SPrashanth Swaminathan
442*1fd5a2e1SPrashanth Swaminathan /* Check that everything starts aligned properly. */
443*1fd5a2e1SPrashanth Swaminathan FFI_ASSERT (((unsigned long) (char *) stack & 0xF) == 0);
444*1fd5a2e1SPrashanth Swaminathan FFI_ASSERT (((unsigned long) copy_space.c & 0xF) == 0);
445*1fd5a2e1SPrashanth Swaminathan FFI_ASSERT (((unsigned long) stacktop.c & 0xF) == 0);
446*1fd5a2e1SPrashanth Swaminathan FFI_ASSERT ((bytes & 0xF) == 0);
447*1fd5a2e1SPrashanth Swaminathan FFI_ASSERT (copy_space.c >= next_arg.c);
448*1fd5a2e1SPrashanth Swaminathan
449*1fd5a2e1SPrashanth Swaminathan /* Deal with return values that are actually pass-by-reference. */
450*1fd5a2e1SPrashanth Swaminathan if (flags & FLAG_RETVAL_REFERENCE)
451*1fd5a2e1SPrashanth Swaminathan *gpr_base.u++ = (unsigned) (char *) ecif->rvalue;
452*1fd5a2e1SPrashanth Swaminathan
453*1fd5a2e1SPrashanth Swaminathan /* Now for the arguments. */
454*1fd5a2e1SPrashanth Swaminathan p_argv.v = ecif->avalue;
455*1fd5a2e1SPrashanth Swaminathan for (ptr = ecif->cif->arg_types, i = ecif->cif->nargs;
456*1fd5a2e1SPrashanth Swaminathan i > 0;
457*1fd5a2e1SPrashanth Swaminathan i--, ptr++, p_argv.v++)
458*1fd5a2e1SPrashanth Swaminathan {
459*1fd5a2e1SPrashanth Swaminathan unsigned int typenum = (*ptr)->type;
460*1fd5a2e1SPrashanth Swaminathan
461*1fd5a2e1SPrashanth Swaminathan typenum = translate_float (ecif->cif->abi, typenum);
462*1fd5a2e1SPrashanth Swaminathan
463*1fd5a2e1SPrashanth Swaminathan /* Now test the translated value */
464*1fd5a2e1SPrashanth Swaminathan switch (typenum)
465*1fd5a2e1SPrashanth Swaminathan {
466*1fd5a2e1SPrashanth Swaminathan #ifndef __NO_FPRS__
467*1fd5a2e1SPrashanth Swaminathan # if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
468*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_LONGDOUBLE:
469*1fd5a2e1SPrashanth Swaminathan double_tmp = (*p_argv.d)[0];
470*1fd5a2e1SPrashanth Swaminathan
471*1fd5a2e1SPrashanth Swaminathan if (fpr_base.d >= fpr_end.d - 1)
472*1fd5a2e1SPrashanth Swaminathan {
473*1fd5a2e1SPrashanth Swaminathan fpr_base.d = fpr_end.d;
474*1fd5a2e1SPrashanth Swaminathan if (((next_arg.u - stack) & 1) != 0)
475*1fd5a2e1SPrashanth Swaminathan next_arg.u += 1;
476*1fd5a2e1SPrashanth Swaminathan *next_arg.d = double_tmp;
477*1fd5a2e1SPrashanth Swaminathan next_arg.u += 2;
478*1fd5a2e1SPrashanth Swaminathan double_tmp = (*p_argv.d)[1];
479*1fd5a2e1SPrashanth Swaminathan *next_arg.d = double_tmp;
480*1fd5a2e1SPrashanth Swaminathan next_arg.u += 2;
481*1fd5a2e1SPrashanth Swaminathan }
482*1fd5a2e1SPrashanth Swaminathan else
483*1fd5a2e1SPrashanth Swaminathan {
484*1fd5a2e1SPrashanth Swaminathan *fpr_base.d++ = double_tmp;
485*1fd5a2e1SPrashanth Swaminathan double_tmp = (*p_argv.d)[1];
486*1fd5a2e1SPrashanth Swaminathan *fpr_base.d++ = double_tmp;
487*1fd5a2e1SPrashanth Swaminathan }
488*1fd5a2e1SPrashanth Swaminathan FFI_ASSERT (flags & FLAG_FP_ARGUMENTS);
489*1fd5a2e1SPrashanth Swaminathan break;
490*1fd5a2e1SPrashanth Swaminathan # endif
491*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_DOUBLE:
492*1fd5a2e1SPrashanth Swaminathan double_tmp = **p_argv.d;
493*1fd5a2e1SPrashanth Swaminathan
494*1fd5a2e1SPrashanth Swaminathan if (fpr_base.d >= fpr_end.d)
495*1fd5a2e1SPrashanth Swaminathan {
496*1fd5a2e1SPrashanth Swaminathan if (((next_arg.u - stack) & 1) != 0)
497*1fd5a2e1SPrashanth Swaminathan next_arg.u += 1;
498*1fd5a2e1SPrashanth Swaminathan *next_arg.d = double_tmp;
499*1fd5a2e1SPrashanth Swaminathan next_arg.u += 2;
500*1fd5a2e1SPrashanth Swaminathan }
501*1fd5a2e1SPrashanth Swaminathan else
502*1fd5a2e1SPrashanth Swaminathan *fpr_base.d++ = double_tmp;
503*1fd5a2e1SPrashanth Swaminathan FFI_ASSERT (flags & FLAG_FP_ARGUMENTS);
504*1fd5a2e1SPrashanth Swaminathan break;
505*1fd5a2e1SPrashanth Swaminathan
506*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_FLOAT:
507*1fd5a2e1SPrashanth Swaminathan double_tmp = **p_argv.f;
508*1fd5a2e1SPrashanth Swaminathan if (fpr_base.d >= fpr_end.d)
509*1fd5a2e1SPrashanth Swaminathan {
510*1fd5a2e1SPrashanth Swaminathan *next_arg.f = (float) double_tmp;
511*1fd5a2e1SPrashanth Swaminathan next_arg.u += 1;
512*1fd5a2e1SPrashanth Swaminathan }
513*1fd5a2e1SPrashanth Swaminathan else
514*1fd5a2e1SPrashanth Swaminathan *fpr_base.d++ = double_tmp;
515*1fd5a2e1SPrashanth Swaminathan FFI_ASSERT (flags & FLAG_FP_ARGUMENTS);
516*1fd5a2e1SPrashanth Swaminathan break;
517*1fd5a2e1SPrashanth Swaminathan #endif /* have FPRs */
518*1fd5a2e1SPrashanth Swaminathan
519*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_UINT128:
520*1fd5a2e1SPrashanth Swaminathan /* The soft float ABI for long doubles works like this, a long double
521*1fd5a2e1SPrashanth Swaminathan is passed in four consecutive GPRs if available. A maximum of 2
522*1fd5a2e1SPrashanth Swaminathan long doubles can be passed in gprs. If we do not have 4 GPRs
523*1fd5a2e1SPrashanth Swaminathan left, the long double is passed on the stack, 4-byte aligned. */
524*1fd5a2e1SPrashanth Swaminathan if (gpr_base.u >= gpr_end.u - 3)
525*1fd5a2e1SPrashanth Swaminathan {
526*1fd5a2e1SPrashanth Swaminathan unsigned int ii;
527*1fd5a2e1SPrashanth Swaminathan gpr_base.u = gpr_end.u;
528*1fd5a2e1SPrashanth Swaminathan for (ii = 0; ii < 4; ii++)
529*1fd5a2e1SPrashanth Swaminathan {
530*1fd5a2e1SPrashanth Swaminathan unsigned int int_tmp = (*p_argv.ui)[ii];
531*1fd5a2e1SPrashanth Swaminathan *next_arg.u++ = int_tmp;
532*1fd5a2e1SPrashanth Swaminathan }
533*1fd5a2e1SPrashanth Swaminathan }
534*1fd5a2e1SPrashanth Swaminathan else
535*1fd5a2e1SPrashanth Swaminathan {
536*1fd5a2e1SPrashanth Swaminathan unsigned int ii;
537*1fd5a2e1SPrashanth Swaminathan for (ii = 0; ii < 4; ii++)
538*1fd5a2e1SPrashanth Swaminathan {
539*1fd5a2e1SPrashanth Swaminathan unsigned int int_tmp = (*p_argv.ui)[ii];
540*1fd5a2e1SPrashanth Swaminathan *gpr_base.u++ = int_tmp;
541*1fd5a2e1SPrashanth Swaminathan }
542*1fd5a2e1SPrashanth Swaminathan }
543*1fd5a2e1SPrashanth Swaminathan break;
544*1fd5a2e1SPrashanth Swaminathan
545*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_UINT64:
546*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_SINT64:
547*1fd5a2e1SPrashanth Swaminathan if (gpr_base.u >= gpr_end.u - 1)
548*1fd5a2e1SPrashanth Swaminathan {
549*1fd5a2e1SPrashanth Swaminathan gpr_base.u = gpr_end.u;
550*1fd5a2e1SPrashanth Swaminathan if (((next_arg.u - stack) & 1) != 0)
551*1fd5a2e1SPrashanth Swaminathan next_arg.u++;
552*1fd5a2e1SPrashanth Swaminathan *next_arg.ll = **p_argv.ll;
553*1fd5a2e1SPrashanth Swaminathan next_arg.u += 2;
554*1fd5a2e1SPrashanth Swaminathan }
555*1fd5a2e1SPrashanth Swaminathan else
556*1fd5a2e1SPrashanth Swaminathan {
557*1fd5a2e1SPrashanth Swaminathan /* The abi states only certain register pairs can be
558*1fd5a2e1SPrashanth Swaminathan used for passing long long int specifically (r3,r4),
559*1fd5a2e1SPrashanth Swaminathan (r5,r6), (r7,r8), (r9,r10). If next arg is long long
560*1fd5a2e1SPrashanth Swaminathan but not correct starting register of pair then skip
561*1fd5a2e1SPrashanth Swaminathan until the proper starting register. */
562*1fd5a2e1SPrashanth Swaminathan if (((gpr_end.u - gpr_base.u) & 1) != 0)
563*1fd5a2e1SPrashanth Swaminathan gpr_base.u++;
564*1fd5a2e1SPrashanth Swaminathan *gpr_base.ll++ = **p_argv.ll;
565*1fd5a2e1SPrashanth Swaminathan }
566*1fd5a2e1SPrashanth Swaminathan break;
567*1fd5a2e1SPrashanth Swaminathan
568*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_STRUCT:
569*1fd5a2e1SPrashanth Swaminathan struct_copy_size = ((*ptr)->size + 15) & ~0xF;
570*1fd5a2e1SPrashanth Swaminathan copy_space.c -= struct_copy_size;
571*1fd5a2e1SPrashanth Swaminathan memcpy (copy_space.c, *p_argv.c, (*ptr)->size);
572*1fd5a2e1SPrashanth Swaminathan
573*1fd5a2e1SPrashanth Swaminathan gprvalue = (unsigned long) copy_space.c;
574*1fd5a2e1SPrashanth Swaminathan
575*1fd5a2e1SPrashanth Swaminathan FFI_ASSERT (copy_space.c > next_arg.c);
576*1fd5a2e1SPrashanth Swaminathan FFI_ASSERT (flags & FLAG_ARG_NEEDS_COPY);
577*1fd5a2e1SPrashanth Swaminathan goto putgpr;
578*1fd5a2e1SPrashanth Swaminathan
579*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_UINT8:
580*1fd5a2e1SPrashanth Swaminathan gprvalue = **p_argv.uc;
581*1fd5a2e1SPrashanth Swaminathan goto putgpr;
582*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_SINT8:
583*1fd5a2e1SPrashanth Swaminathan gprvalue = **p_argv.sc;
584*1fd5a2e1SPrashanth Swaminathan goto putgpr;
585*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_UINT16:
586*1fd5a2e1SPrashanth Swaminathan gprvalue = **p_argv.us;
587*1fd5a2e1SPrashanth Swaminathan goto putgpr;
588*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_SINT16:
589*1fd5a2e1SPrashanth Swaminathan gprvalue = **p_argv.ss;
590*1fd5a2e1SPrashanth Swaminathan goto putgpr;
591*1fd5a2e1SPrashanth Swaminathan
592*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_INT:
593*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_UINT32:
594*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_SINT32:
595*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_POINTER:
596*1fd5a2e1SPrashanth Swaminathan
597*1fd5a2e1SPrashanth Swaminathan gprvalue = **p_argv.ui;
598*1fd5a2e1SPrashanth Swaminathan
599*1fd5a2e1SPrashanth Swaminathan putgpr:
600*1fd5a2e1SPrashanth Swaminathan if (gpr_base.u >= gpr_end.u)
601*1fd5a2e1SPrashanth Swaminathan *next_arg.u++ = gprvalue;
602*1fd5a2e1SPrashanth Swaminathan else
603*1fd5a2e1SPrashanth Swaminathan *gpr_base.u++ = gprvalue;
604*1fd5a2e1SPrashanth Swaminathan break;
605*1fd5a2e1SPrashanth Swaminathan }
606*1fd5a2e1SPrashanth Swaminathan }
607*1fd5a2e1SPrashanth Swaminathan
608*1fd5a2e1SPrashanth Swaminathan /* Check that we didn't overrun the stack... */
609*1fd5a2e1SPrashanth Swaminathan FFI_ASSERT (copy_space.c >= next_arg.c);
610*1fd5a2e1SPrashanth Swaminathan FFI_ASSERT (gpr_base.u <= gpr_end.u);
611*1fd5a2e1SPrashanth Swaminathan #ifndef __NO_FPRS__
612*1fd5a2e1SPrashanth Swaminathan FFI_ASSERT (fpr_base.u <= fpr_end.u);
613*1fd5a2e1SPrashanth Swaminathan #endif
614*1fd5a2e1SPrashanth Swaminathan FFI_ASSERT (((flags & FLAG_4_GPR_ARGUMENTS) != 0)
615*1fd5a2e1SPrashanth Swaminathan == (gpr_end.u - gpr_base.u < 4));
616*1fd5a2e1SPrashanth Swaminathan }
617*1fd5a2e1SPrashanth Swaminathan
618*1fd5a2e1SPrashanth Swaminathan #define MIN_CACHE_LINE_SIZE 8
619*1fd5a2e1SPrashanth Swaminathan
620*1fd5a2e1SPrashanth Swaminathan static void
flush_icache(char * wraddr,char * xaddr,int size)621*1fd5a2e1SPrashanth Swaminathan flush_icache (char *wraddr, char *xaddr, int size)
622*1fd5a2e1SPrashanth Swaminathan {
623*1fd5a2e1SPrashanth Swaminathan int i;
624*1fd5a2e1SPrashanth Swaminathan for (i = 0; i < size; i += MIN_CACHE_LINE_SIZE)
625*1fd5a2e1SPrashanth Swaminathan __asm__ volatile ("icbi 0,%0;" "dcbf 0,%1;"
626*1fd5a2e1SPrashanth Swaminathan : : "r" (xaddr + i), "r" (wraddr + i) : "memory");
627*1fd5a2e1SPrashanth Swaminathan __asm__ volatile ("icbi 0,%0;" "dcbf 0,%1;" "sync;" "isync;"
628*1fd5a2e1SPrashanth Swaminathan : : "r"(xaddr + size - 1), "r"(wraddr + size - 1)
629*1fd5a2e1SPrashanth Swaminathan : "memory");
630*1fd5a2e1SPrashanth Swaminathan }
631*1fd5a2e1SPrashanth Swaminathan
632*1fd5a2e1SPrashanth Swaminathan ffi_status FFI_HIDDEN
ffi_prep_closure_loc_sysv(ffi_closure * closure,ffi_cif * cif,void (* fun)(ffi_cif *,void *,void **,void *),void * user_data,void * codeloc)633*1fd5a2e1SPrashanth Swaminathan ffi_prep_closure_loc_sysv (ffi_closure *closure,
634*1fd5a2e1SPrashanth Swaminathan ffi_cif *cif,
635*1fd5a2e1SPrashanth Swaminathan void (*fun) (ffi_cif *, void *, void **, void *),
636*1fd5a2e1SPrashanth Swaminathan void *user_data,
637*1fd5a2e1SPrashanth Swaminathan void *codeloc)
638*1fd5a2e1SPrashanth Swaminathan {
639*1fd5a2e1SPrashanth Swaminathan unsigned int *tramp;
640*1fd5a2e1SPrashanth Swaminathan
641*1fd5a2e1SPrashanth Swaminathan if (cif->abi < FFI_SYSV || cif->abi >= FFI_LAST_ABI)
642*1fd5a2e1SPrashanth Swaminathan return FFI_BAD_ABI;
643*1fd5a2e1SPrashanth Swaminathan
644*1fd5a2e1SPrashanth Swaminathan tramp = (unsigned int *) &closure->tramp[0];
645*1fd5a2e1SPrashanth Swaminathan tramp[0] = 0x7c0802a6; /* mflr r0 */
646*1fd5a2e1SPrashanth Swaminathan tramp[1] = 0x429f0005; /* bcl 20,31,.+4 */
647*1fd5a2e1SPrashanth Swaminathan tramp[2] = 0x7d6802a6; /* mflr r11 */
648*1fd5a2e1SPrashanth Swaminathan tramp[3] = 0x7c0803a6; /* mtlr r0 */
649*1fd5a2e1SPrashanth Swaminathan tramp[4] = 0x800b0018; /* lwz r0,24(r11) */
650*1fd5a2e1SPrashanth Swaminathan tramp[5] = 0x816b001c; /* lwz r11,28(r11) */
651*1fd5a2e1SPrashanth Swaminathan tramp[6] = 0x7c0903a6; /* mtctr r0 */
652*1fd5a2e1SPrashanth Swaminathan tramp[7] = 0x4e800420; /* bctr */
653*1fd5a2e1SPrashanth Swaminathan *(void **) &tramp[8] = (void *) ffi_closure_SYSV; /* function */
654*1fd5a2e1SPrashanth Swaminathan *(void **) &tramp[9] = codeloc; /* context */
655*1fd5a2e1SPrashanth Swaminathan
656*1fd5a2e1SPrashanth Swaminathan /* Flush the icache. */
657*1fd5a2e1SPrashanth Swaminathan flush_icache ((char *)tramp, (char *)codeloc, 8 * 4);
658*1fd5a2e1SPrashanth Swaminathan
659*1fd5a2e1SPrashanth Swaminathan closure->cif = cif;
660*1fd5a2e1SPrashanth Swaminathan closure->fun = fun;
661*1fd5a2e1SPrashanth Swaminathan closure->user_data = user_data;
662*1fd5a2e1SPrashanth Swaminathan
663*1fd5a2e1SPrashanth Swaminathan return FFI_OK;
664*1fd5a2e1SPrashanth Swaminathan }
665*1fd5a2e1SPrashanth Swaminathan
666*1fd5a2e1SPrashanth Swaminathan /* Basically the trampoline invokes ffi_closure_SYSV, and on
667*1fd5a2e1SPrashanth Swaminathan entry, r11 holds the address of the closure.
668*1fd5a2e1SPrashanth Swaminathan After storing the registers that could possibly contain
669*1fd5a2e1SPrashanth Swaminathan parameters to be passed into the stack frame and setting
670*1fd5a2e1SPrashanth Swaminathan up space for a return value, ffi_closure_SYSV invokes the
671*1fd5a2e1SPrashanth Swaminathan following helper function to do most of the work. */
672*1fd5a2e1SPrashanth Swaminathan
673*1fd5a2e1SPrashanth Swaminathan int
ffi_closure_helper_SYSV(ffi_cif * cif,void (* fun)(ffi_cif *,void *,void **,void *),void * user_data,void * rvalue,unsigned long * pgr,ffi_dblfl * pfr,unsigned long * pst)674*1fd5a2e1SPrashanth Swaminathan ffi_closure_helper_SYSV (ffi_cif *cif,
675*1fd5a2e1SPrashanth Swaminathan void (*fun) (ffi_cif *, void *, void **, void *),
676*1fd5a2e1SPrashanth Swaminathan void *user_data,
677*1fd5a2e1SPrashanth Swaminathan void *rvalue,
678*1fd5a2e1SPrashanth Swaminathan unsigned long *pgr,
679*1fd5a2e1SPrashanth Swaminathan ffi_dblfl *pfr,
680*1fd5a2e1SPrashanth Swaminathan unsigned long *pst)
681*1fd5a2e1SPrashanth Swaminathan {
682*1fd5a2e1SPrashanth Swaminathan /* rvalue is the pointer to space for return value in closure assembly */
683*1fd5a2e1SPrashanth Swaminathan /* pgr is the pointer to where r3-r10 are stored in ffi_closure_SYSV */
684*1fd5a2e1SPrashanth Swaminathan /* pfr is the pointer to where f1-f8 are stored in ffi_closure_SYSV */
685*1fd5a2e1SPrashanth Swaminathan /* pst is the pointer to outgoing parameter stack in original caller */
686*1fd5a2e1SPrashanth Swaminathan
687*1fd5a2e1SPrashanth Swaminathan void ** avalue;
688*1fd5a2e1SPrashanth Swaminathan ffi_type ** arg_types;
689*1fd5a2e1SPrashanth Swaminathan long i, avn;
690*1fd5a2e1SPrashanth Swaminathan #ifndef __NO_FPRS__
691*1fd5a2e1SPrashanth Swaminathan long nf = 0; /* number of floating registers already used */
692*1fd5a2e1SPrashanth Swaminathan #endif
693*1fd5a2e1SPrashanth Swaminathan long ng = 0; /* number of general registers already used */
694*1fd5a2e1SPrashanth Swaminathan
695*1fd5a2e1SPrashanth Swaminathan unsigned size = cif->rtype->size;
696*1fd5a2e1SPrashanth Swaminathan unsigned short rtypenum = cif->rtype->type;
697*1fd5a2e1SPrashanth Swaminathan
698*1fd5a2e1SPrashanth Swaminathan avalue = alloca (cif->nargs * sizeof (void *));
699*1fd5a2e1SPrashanth Swaminathan
700*1fd5a2e1SPrashanth Swaminathan /* First translate for softfloat/nonlinux */
701*1fd5a2e1SPrashanth Swaminathan rtypenum = translate_float (cif->abi, rtypenum);
702*1fd5a2e1SPrashanth Swaminathan
703*1fd5a2e1SPrashanth Swaminathan /* Copy the caller's structure return value address so that the closure
704*1fd5a2e1SPrashanth Swaminathan returns the data directly to the caller.
705*1fd5a2e1SPrashanth Swaminathan For FFI_SYSV the result is passed in r3/r4 if the struct size is less
706*1fd5a2e1SPrashanth Swaminathan or equal 8 bytes. */
707*1fd5a2e1SPrashanth Swaminathan if (rtypenum == FFI_TYPE_STRUCT
708*1fd5a2e1SPrashanth Swaminathan && !((cif->abi & FFI_SYSV_STRUCT_RET) != 0 && size <= 8))
709*1fd5a2e1SPrashanth Swaminathan {
710*1fd5a2e1SPrashanth Swaminathan rvalue = (void *) *pgr;
711*1fd5a2e1SPrashanth Swaminathan ng++;
712*1fd5a2e1SPrashanth Swaminathan pgr++;
713*1fd5a2e1SPrashanth Swaminathan }
714*1fd5a2e1SPrashanth Swaminathan
715*1fd5a2e1SPrashanth Swaminathan i = 0;
716*1fd5a2e1SPrashanth Swaminathan avn = cif->nargs;
717*1fd5a2e1SPrashanth Swaminathan arg_types = cif->arg_types;
718*1fd5a2e1SPrashanth Swaminathan
719*1fd5a2e1SPrashanth Swaminathan /* Grab the addresses of the arguments from the stack frame. */
720*1fd5a2e1SPrashanth Swaminathan while (i < avn) {
721*1fd5a2e1SPrashanth Swaminathan unsigned short typenum = arg_types[i]->type;
722*1fd5a2e1SPrashanth Swaminathan
723*1fd5a2e1SPrashanth Swaminathan /* We may need to handle some values depending on ABI. */
724*1fd5a2e1SPrashanth Swaminathan typenum = translate_float (cif->abi, typenum);
725*1fd5a2e1SPrashanth Swaminathan
726*1fd5a2e1SPrashanth Swaminathan switch (typenum)
727*1fd5a2e1SPrashanth Swaminathan {
728*1fd5a2e1SPrashanth Swaminathan #ifndef __NO_FPRS__
729*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_FLOAT:
730*1fd5a2e1SPrashanth Swaminathan /* Unfortunately float values are stored as doubles
731*1fd5a2e1SPrashanth Swaminathan in the ffi_closure_SYSV code (since we don't check
732*1fd5a2e1SPrashanth Swaminathan the type in that routine). */
733*1fd5a2e1SPrashanth Swaminathan if (nf < NUM_FPR_ARG_REGISTERS)
734*1fd5a2e1SPrashanth Swaminathan {
735*1fd5a2e1SPrashanth Swaminathan /* FIXME? here we are really changing the values
736*1fd5a2e1SPrashanth Swaminathan stored in the original calling routines outgoing
737*1fd5a2e1SPrashanth Swaminathan parameter stack. This is probably a really
738*1fd5a2e1SPrashanth Swaminathan naughty thing to do but... */
739*1fd5a2e1SPrashanth Swaminathan double temp = pfr->d;
740*1fd5a2e1SPrashanth Swaminathan pfr->f = (float) temp;
741*1fd5a2e1SPrashanth Swaminathan avalue[i] = pfr;
742*1fd5a2e1SPrashanth Swaminathan nf++;
743*1fd5a2e1SPrashanth Swaminathan pfr++;
744*1fd5a2e1SPrashanth Swaminathan }
745*1fd5a2e1SPrashanth Swaminathan else
746*1fd5a2e1SPrashanth Swaminathan {
747*1fd5a2e1SPrashanth Swaminathan avalue[i] = pst;
748*1fd5a2e1SPrashanth Swaminathan pst += 1;
749*1fd5a2e1SPrashanth Swaminathan }
750*1fd5a2e1SPrashanth Swaminathan break;
751*1fd5a2e1SPrashanth Swaminathan
752*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_DOUBLE:
753*1fd5a2e1SPrashanth Swaminathan if (nf < NUM_FPR_ARG_REGISTERS)
754*1fd5a2e1SPrashanth Swaminathan {
755*1fd5a2e1SPrashanth Swaminathan avalue[i] = pfr;
756*1fd5a2e1SPrashanth Swaminathan nf++;
757*1fd5a2e1SPrashanth Swaminathan pfr++;
758*1fd5a2e1SPrashanth Swaminathan }
759*1fd5a2e1SPrashanth Swaminathan else
760*1fd5a2e1SPrashanth Swaminathan {
761*1fd5a2e1SPrashanth Swaminathan if (((long) pst) & 4)
762*1fd5a2e1SPrashanth Swaminathan pst++;
763*1fd5a2e1SPrashanth Swaminathan avalue[i] = pst;
764*1fd5a2e1SPrashanth Swaminathan pst += 2;
765*1fd5a2e1SPrashanth Swaminathan }
766*1fd5a2e1SPrashanth Swaminathan break;
767*1fd5a2e1SPrashanth Swaminathan
768*1fd5a2e1SPrashanth Swaminathan # if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
769*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_LONGDOUBLE:
770*1fd5a2e1SPrashanth Swaminathan if (nf < NUM_FPR_ARG_REGISTERS - 1)
771*1fd5a2e1SPrashanth Swaminathan {
772*1fd5a2e1SPrashanth Swaminathan avalue[i] = pfr;
773*1fd5a2e1SPrashanth Swaminathan pfr += 2;
774*1fd5a2e1SPrashanth Swaminathan nf += 2;
775*1fd5a2e1SPrashanth Swaminathan }
776*1fd5a2e1SPrashanth Swaminathan else
777*1fd5a2e1SPrashanth Swaminathan {
778*1fd5a2e1SPrashanth Swaminathan if (((long) pst) & 4)
779*1fd5a2e1SPrashanth Swaminathan pst++;
780*1fd5a2e1SPrashanth Swaminathan avalue[i] = pst;
781*1fd5a2e1SPrashanth Swaminathan pst += 4;
782*1fd5a2e1SPrashanth Swaminathan nf = 8;
783*1fd5a2e1SPrashanth Swaminathan }
784*1fd5a2e1SPrashanth Swaminathan break;
785*1fd5a2e1SPrashanth Swaminathan # endif
786*1fd5a2e1SPrashanth Swaminathan #endif
787*1fd5a2e1SPrashanth Swaminathan
788*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_UINT128:
789*1fd5a2e1SPrashanth Swaminathan /* Test if for the whole long double, 4 gprs are available.
790*1fd5a2e1SPrashanth Swaminathan otherwise the stuff ends up on the stack. */
791*1fd5a2e1SPrashanth Swaminathan if (ng < NUM_GPR_ARG_REGISTERS - 3)
792*1fd5a2e1SPrashanth Swaminathan {
793*1fd5a2e1SPrashanth Swaminathan avalue[i] = pgr;
794*1fd5a2e1SPrashanth Swaminathan pgr += 4;
795*1fd5a2e1SPrashanth Swaminathan ng += 4;
796*1fd5a2e1SPrashanth Swaminathan }
797*1fd5a2e1SPrashanth Swaminathan else
798*1fd5a2e1SPrashanth Swaminathan {
799*1fd5a2e1SPrashanth Swaminathan avalue[i] = pst;
800*1fd5a2e1SPrashanth Swaminathan pst += 4;
801*1fd5a2e1SPrashanth Swaminathan ng = 8+4;
802*1fd5a2e1SPrashanth Swaminathan }
803*1fd5a2e1SPrashanth Swaminathan break;
804*1fd5a2e1SPrashanth Swaminathan
805*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_SINT8:
806*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_UINT8:
807*1fd5a2e1SPrashanth Swaminathan #ifndef __LITTLE_ENDIAN__
808*1fd5a2e1SPrashanth Swaminathan if (ng < NUM_GPR_ARG_REGISTERS)
809*1fd5a2e1SPrashanth Swaminathan {
810*1fd5a2e1SPrashanth Swaminathan avalue[i] = (char *) pgr + 3;
811*1fd5a2e1SPrashanth Swaminathan ng++;
812*1fd5a2e1SPrashanth Swaminathan pgr++;
813*1fd5a2e1SPrashanth Swaminathan }
814*1fd5a2e1SPrashanth Swaminathan else
815*1fd5a2e1SPrashanth Swaminathan {
816*1fd5a2e1SPrashanth Swaminathan avalue[i] = (char *) pst + 3;
817*1fd5a2e1SPrashanth Swaminathan pst++;
818*1fd5a2e1SPrashanth Swaminathan }
819*1fd5a2e1SPrashanth Swaminathan break;
820*1fd5a2e1SPrashanth Swaminathan #endif
821*1fd5a2e1SPrashanth Swaminathan
822*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_SINT16:
823*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_UINT16:
824*1fd5a2e1SPrashanth Swaminathan #ifndef __LITTLE_ENDIAN__
825*1fd5a2e1SPrashanth Swaminathan if (ng < NUM_GPR_ARG_REGISTERS)
826*1fd5a2e1SPrashanth Swaminathan {
827*1fd5a2e1SPrashanth Swaminathan avalue[i] = (char *) pgr + 2;
828*1fd5a2e1SPrashanth Swaminathan ng++;
829*1fd5a2e1SPrashanth Swaminathan pgr++;
830*1fd5a2e1SPrashanth Swaminathan }
831*1fd5a2e1SPrashanth Swaminathan else
832*1fd5a2e1SPrashanth Swaminathan {
833*1fd5a2e1SPrashanth Swaminathan avalue[i] = (char *) pst + 2;
834*1fd5a2e1SPrashanth Swaminathan pst++;
835*1fd5a2e1SPrashanth Swaminathan }
836*1fd5a2e1SPrashanth Swaminathan break;
837*1fd5a2e1SPrashanth Swaminathan #endif
838*1fd5a2e1SPrashanth Swaminathan
839*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_SINT32:
840*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_UINT32:
841*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_POINTER:
842*1fd5a2e1SPrashanth Swaminathan if (ng < NUM_GPR_ARG_REGISTERS)
843*1fd5a2e1SPrashanth Swaminathan {
844*1fd5a2e1SPrashanth Swaminathan avalue[i] = pgr;
845*1fd5a2e1SPrashanth Swaminathan ng++;
846*1fd5a2e1SPrashanth Swaminathan pgr++;
847*1fd5a2e1SPrashanth Swaminathan }
848*1fd5a2e1SPrashanth Swaminathan else
849*1fd5a2e1SPrashanth Swaminathan {
850*1fd5a2e1SPrashanth Swaminathan avalue[i] = pst;
851*1fd5a2e1SPrashanth Swaminathan pst++;
852*1fd5a2e1SPrashanth Swaminathan }
853*1fd5a2e1SPrashanth Swaminathan break;
854*1fd5a2e1SPrashanth Swaminathan
855*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_STRUCT:
856*1fd5a2e1SPrashanth Swaminathan /* Structs are passed by reference. The address will appear in a
857*1fd5a2e1SPrashanth Swaminathan gpr if it is one of the first 8 arguments. */
858*1fd5a2e1SPrashanth Swaminathan if (ng < NUM_GPR_ARG_REGISTERS)
859*1fd5a2e1SPrashanth Swaminathan {
860*1fd5a2e1SPrashanth Swaminathan avalue[i] = (void *) *pgr;
861*1fd5a2e1SPrashanth Swaminathan ng++;
862*1fd5a2e1SPrashanth Swaminathan pgr++;
863*1fd5a2e1SPrashanth Swaminathan }
864*1fd5a2e1SPrashanth Swaminathan else
865*1fd5a2e1SPrashanth Swaminathan {
866*1fd5a2e1SPrashanth Swaminathan avalue[i] = (void *) *pst;
867*1fd5a2e1SPrashanth Swaminathan pst++;
868*1fd5a2e1SPrashanth Swaminathan }
869*1fd5a2e1SPrashanth Swaminathan break;
870*1fd5a2e1SPrashanth Swaminathan
871*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_SINT64:
872*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_UINT64:
873*1fd5a2e1SPrashanth Swaminathan /* Passing long long ints are complex, they must
874*1fd5a2e1SPrashanth Swaminathan be passed in suitable register pairs such as
875*1fd5a2e1SPrashanth Swaminathan (r3,r4) or (r5,r6) or (r6,r7), or (r7,r8) or (r9,r10)
876*1fd5a2e1SPrashanth Swaminathan and if the entire pair aren't available then the outgoing
877*1fd5a2e1SPrashanth Swaminathan parameter stack is used for both but an alignment of 8
878*1fd5a2e1SPrashanth Swaminathan must will be kept. So we must either look in pgr
879*1fd5a2e1SPrashanth Swaminathan or pst to find the correct address for this type
880*1fd5a2e1SPrashanth Swaminathan of parameter. */
881*1fd5a2e1SPrashanth Swaminathan if (ng < NUM_GPR_ARG_REGISTERS - 1)
882*1fd5a2e1SPrashanth Swaminathan {
883*1fd5a2e1SPrashanth Swaminathan if (ng & 1)
884*1fd5a2e1SPrashanth Swaminathan {
885*1fd5a2e1SPrashanth Swaminathan /* skip r4, r6, r8 as starting points */
886*1fd5a2e1SPrashanth Swaminathan ng++;
887*1fd5a2e1SPrashanth Swaminathan pgr++;
888*1fd5a2e1SPrashanth Swaminathan }
889*1fd5a2e1SPrashanth Swaminathan avalue[i] = pgr;
890*1fd5a2e1SPrashanth Swaminathan ng += 2;
891*1fd5a2e1SPrashanth Swaminathan pgr += 2;
892*1fd5a2e1SPrashanth Swaminathan }
893*1fd5a2e1SPrashanth Swaminathan else
894*1fd5a2e1SPrashanth Swaminathan {
895*1fd5a2e1SPrashanth Swaminathan if (((long) pst) & 4)
896*1fd5a2e1SPrashanth Swaminathan pst++;
897*1fd5a2e1SPrashanth Swaminathan avalue[i] = pst;
898*1fd5a2e1SPrashanth Swaminathan pst += 2;
899*1fd5a2e1SPrashanth Swaminathan ng = NUM_GPR_ARG_REGISTERS;
900*1fd5a2e1SPrashanth Swaminathan }
901*1fd5a2e1SPrashanth Swaminathan break;
902*1fd5a2e1SPrashanth Swaminathan
903*1fd5a2e1SPrashanth Swaminathan default:
904*1fd5a2e1SPrashanth Swaminathan FFI_ASSERT (0);
905*1fd5a2e1SPrashanth Swaminathan }
906*1fd5a2e1SPrashanth Swaminathan
907*1fd5a2e1SPrashanth Swaminathan i++;
908*1fd5a2e1SPrashanth Swaminathan }
909*1fd5a2e1SPrashanth Swaminathan
910*1fd5a2e1SPrashanth Swaminathan (*fun) (cif, rvalue, avalue, user_data);
911*1fd5a2e1SPrashanth Swaminathan
912*1fd5a2e1SPrashanth Swaminathan /* Tell ffi_closure_SYSV how to perform return type promotions.
913*1fd5a2e1SPrashanth Swaminathan Because the FFI_SYSV ABI returns the structures <= 8 bytes in
914*1fd5a2e1SPrashanth Swaminathan r3/r4 we have to tell ffi_closure_SYSV how to treat them. We
915*1fd5a2e1SPrashanth Swaminathan combine the base type FFI_SYSV_TYPE_SMALL_STRUCT with the size of
916*1fd5a2e1SPrashanth Swaminathan the struct less one. We never have a struct with size zero.
917*1fd5a2e1SPrashanth Swaminathan See the comment in ffitarget.h about ordering. */
918*1fd5a2e1SPrashanth Swaminathan if (rtypenum == FFI_TYPE_STRUCT
919*1fd5a2e1SPrashanth Swaminathan && (cif->abi & FFI_SYSV_STRUCT_RET) != 0 && size <= 8)
920*1fd5a2e1SPrashanth Swaminathan return FFI_SYSV_TYPE_SMALL_STRUCT - 1 + size;
921*1fd5a2e1SPrashanth Swaminathan return rtypenum;
922*1fd5a2e1SPrashanth Swaminathan }
923*1fd5a2e1SPrashanth Swaminathan #endif
924