1*1fd5a2e1SPrashanth Swaminathan /* -----------------------------------------------------------------------
2*1fd5a2e1SPrashanth Swaminathan ffi_linux64.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 #ifdef 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 LINUX64 ABI. */
39*1fd5a2e1SPrashanth Swaminathan enum {
40*1fd5a2e1SPrashanth Swaminathan NUM_GPR_ARG_REGISTERS64 = 8,
41*1fd5a2e1SPrashanth Swaminathan NUM_FPR_ARG_REGISTERS64 = 13,
42*1fd5a2e1SPrashanth Swaminathan NUM_VEC_ARG_REGISTERS64 = 12,
43*1fd5a2e1SPrashanth Swaminathan };
44*1fd5a2e1SPrashanth Swaminathan enum { ASM_NEEDS_REGISTERS64 = 4 };
45*1fd5a2e1SPrashanth Swaminathan
46*1fd5a2e1SPrashanth Swaminathan
47*1fd5a2e1SPrashanth Swaminathan #if HAVE_LONG_DOUBLE_VARIANT && FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
48*1fd5a2e1SPrashanth Swaminathan /* Adjust size of ffi_type_longdouble. */
49*1fd5a2e1SPrashanth Swaminathan void FFI_HIDDEN
ffi_prep_types_linux64(ffi_abi abi)50*1fd5a2e1SPrashanth Swaminathan ffi_prep_types_linux64 (ffi_abi abi)
51*1fd5a2e1SPrashanth Swaminathan {
52*1fd5a2e1SPrashanth Swaminathan if ((abi & (FFI_LINUX | FFI_LINUX_LONG_DOUBLE_128)) == FFI_LINUX)
53*1fd5a2e1SPrashanth Swaminathan {
54*1fd5a2e1SPrashanth Swaminathan ffi_type_longdouble.size = 8;
55*1fd5a2e1SPrashanth Swaminathan ffi_type_longdouble.alignment = 8;
56*1fd5a2e1SPrashanth Swaminathan }
57*1fd5a2e1SPrashanth Swaminathan else
58*1fd5a2e1SPrashanth Swaminathan {
59*1fd5a2e1SPrashanth Swaminathan ffi_type_longdouble.size = 16;
60*1fd5a2e1SPrashanth Swaminathan ffi_type_longdouble.alignment = 16;
61*1fd5a2e1SPrashanth Swaminathan }
62*1fd5a2e1SPrashanth Swaminathan }
63*1fd5a2e1SPrashanth Swaminathan #endif
64*1fd5a2e1SPrashanth Swaminathan
65*1fd5a2e1SPrashanth Swaminathan
66*1fd5a2e1SPrashanth Swaminathan static unsigned int
discover_homogeneous_aggregate(ffi_abi abi,const ffi_type * t,unsigned int * elnum)67*1fd5a2e1SPrashanth Swaminathan discover_homogeneous_aggregate (ffi_abi abi,
68*1fd5a2e1SPrashanth Swaminathan const ffi_type *t,
69*1fd5a2e1SPrashanth Swaminathan unsigned int *elnum)
70*1fd5a2e1SPrashanth Swaminathan {
71*1fd5a2e1SPrashanth Swaminathan switch (t->type)
72*1fd5a2e1SPrashanth Swaminathan {
73*1fd5a2e1SPrashanth Swaminathan #if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
74*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_LONGDOUBLE:
75*1fd5a2e1SPrashanth Swaminathan /* 64-bit long doubles are equivalent to doubles. */
76*1fd5a2e1SPrashanth Swaminathan if ((abi & FFI_LINUX_LONG_DOUBLE_128) == 0)
77*1fd5a2e1SPrashanth Swaminathan {
78*1fd5a2e1SPrashanth Swaminathan *elnum = 1;
79*1fd5a2e1SPrashanth Swaminathan return FFI_TYPE_DOUBLE;
80*1fd5a2e1SPrashanth Swaminathan }
81*1fd5a2e1SPrashanth Swaminathan /* IBM extended precision values use unaligned pairs
82*1fd5a2e1SPrashanth Swaminathan of FPRs, but according to the ABI must be considered
83*1fd5a2e1SPrashanth Swaminathan distinct from doubles. They are also limited to a
84*1fd5a2e1SPrashanth Swaminathan maximum of four members in a homogeneous aggregate. */
85*1fd5a2e1SPrashanth Swaminathan else if ((abi & FFI_LINUX_LONG_DOUBLE_IEEE128) == 0)
86*1fd5a2e1SPrashanth Swaminathan {
87*1fd5a2e1SPrashanth Swaminathan *elnum = 2;
88*1fd5a2e1SPrashanth Swaminathan return FFI_TYPE_LONGDOUBLE;
89*1fd5a2e1SPrashanth Swaminathan }
90*1fd5a2e1SPrashanth Swaminathan /* Fall through. */
91*1fd5a2e1SPrashanth Swaminathan #endif
92*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_FLOAT:
93*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_DOUBLE:
94*1fd5a2e1SPrashanth Swaminathan *elnum = 1;
95*1fd5a2e1SPrashanth Swaminathan return (int) t->type;
96*1fd5a2e1SPrashanth Swaminathan
97*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_STRUCT:;
98*1fd5a2e1SPrashanth Swaminathan {
99*1fd5a2e1SPrashanth Swaminathan unsigned int base_elt = 0, total_elnum = 0;
100*1fd5a2e1SPrashanth Swaminathan ffi_type **el = t->elements;
101*1fd5a2e1SPrashanth Swaminathan while (*el)
102*1fd5a2e1SPrashanth Swaminathan {
103*1fd5a2e1SPrashanth Swaminathan unsigned int el_elt, el_elnum = 0;
104*1fd5a2e1SPrashanth Swaminathan el_elt = discover_homogeneous_aggregate (abi, *el, &el_elnum);
105*1fd5a2e1SPrashanth Swaminathan if (el_elt == 0
106*1fd5a2e1SPrashanth Swaminathan || (base_elt && base_elt != el_elt))
107*1fd5a2e1SPrashanth Swaminathan return 0;
108*1fd5a2e1SPrashanth Swaminathan base_elt = el_elt;
109*1fd5a2e1SPrashanth Swaminathan total_elnum += el_elnum;
110*1fd5a2e1SPrashanth Swaminathan #if _CALL_ELF == 2
111*1fd5a2e1SPrashanth Swaminathan if (total_elnum > 8)
112*1fd5a2e1SPrashanth Swaminathan return 0;
113*1fd5a2e1SPrashanth Swaminathan #else
114*1fd5a2e1SPrashanth Swaminathan if (total_elnum > 1)
115*1fd5a2e1SPrashanth Swaminathan return 0;
116*1fd5a2e1SPrashanth Swaminathan #endif
117*1fd5a2e1SPrashanth Swaminathan el++;
118*1fd5a2e1SPrashanth Swaminathan }
119*1fd5a2e1SPrashanth Swaminathan *elnum = total_elnum;
120*1fd5a2e1SPrashanth Swaminathan return base_elt;
121*1fd5a2e1SPrashanth Swaminathan }
122*1fd5a2e1SPrashanth Swaminathan
123*1fd5a2e1SPrashanth Swaminathan default:
124*1fd5a2e1SPrashanth Swaminathan return 0;
125*1fd5a2e1SPrashanth Swaminathan }
126*1fd5a2e1SPrashanth Swaminathan }
127*1fd5a2e1SPrashanth Swaminathan
128*1fd5a2e1SPrashanth Swaminathan
129*1fd5a2e1SPrashanth Swaminathan /* Perform machine dependent cif processing */
130*1fd5a2e1SPrashanth Swaminathan static ffi_status
ffi_prep_cif_linux64_core(ffi_cif * cif)131*1fd5a2e1SPrashanth Swaminathan ffi_prep_cif_linux64_core (ffi_cif *cif)
132*1fd5a2e1SPrashanth Swaminathan {
133*1fd5a2e1SPrashanth Swaminathan ffi_type **ptr;
134*1fd5a2e1SPrashanth Swaminathan unsigned bytes;
135*1fd5a2e1SPrashanth Swaminathan unsigned i, fparg_count = 0, intarg_count = 0, vecarg_count = 0;
136*1fd5a2e1SPrashanth Swaminathan unsigned flags = cif->flags;
137*1fd5a2e1SPrashanth Swaminathan unsigned elt, elnum, rtype;
138*1fd5a2e1SPrashanth Swaminathan
139*1fd5a2e1SPrashanth Swaminathan #if FFI_TYPE_LONGDOUBLE == FFI_TYPE_DOUBLE
140*1fd5a2e1SPrashanth Swaminathan /* If compiled without long double support... */
141*1fd5a2e1SPrashanth Swaminathan if ((cif->abi & FFI_LINUX_LONG_DOUBLE_128) != 0 ||
142*1fd5a2e1SPrashanth Swaminathan (cif->abi & FFI_LINUX_LONG_DOUBLE_IEEE128) != 0)
143*1fd5a2e1SPrashanth Swaminathan return FFI_BAD_ABI;
144*1fd5a2e1SPrashanth Swaminathan #elif !defined(__VEC__)
145*1fd5a2e1SPrashanth Swaminathan /* If compiled without vector register support (used by assembly)... */
146*1fd5a2e1SPrashanth Swaminathan if ((cif->abi & FFI_LINUX_LONG_DOUBLE_IEEE128) != 0)
147*1fd5a2e1SPrashanth Swaminathan return FFI_BAD_ABI;
148*1fd5a2e1SPrashanth Swaminathan #else
149*1fd5a2e1SPrashanth Swaminathan /* If the IEEE128 flag is set, but long double is only 64 bits wide... */
150*1fd5a2e1SPrashanth Swaminathan if ((cif->abi & FFI_LINUX_LONG_DOUBLE_128) == 0 &&
151*1fd5a2e1SPrashanth Swaminathan (cif->abi & FFI_LINUX_LONG_DOUBLE_IEEE128) != 0)
152*1fd5a2e1SPrashanth Swaminathan return FFI_BAD_ABI;
153*1fd5a2e1SPrashanth Swaminathan #endif
154*1fd5a2e1SPrashanth Swaminathan
155*1fd5a2e1SPrashanth Swaminathan /* The machine-independent calculation of cif->bytes doesn't work
156*1fd5a2e1SPrashanth Swaminathan for us. Redo the calculation. */
157*1fd5a2e1SPrashanth Swaminathan #if _CALL_ELF == 2
158*1fd5a2e1SPrashanth Swaminathan /* Space for backchain, CR, LR, TOC and the asm's temp regs. */
159*1fd5a2e1SPrashanth Swaminathan bytes = (4 + ASM_NEEDS_REGISTERS64) * sizeof (long);
160*1fd5a2e1SPrashanth Swaminathan
161*1fd5a2e1SPrashanth Swaminathan /* Space for the general registers. */
162*1fd5a2e1SPrashanth Swaminathan bytes += NUM_GPR_ARG_REGISTERS64 * sizeof (long);
163*1fd5a2e1SPrashanth Swaminathan #else
164*1fd5a2e1SPrashanth Swaminathan /* Space for backchain, CR, LR, cc/ld doubleword, TOC and the asm's temp
165*1fd5a2e1SPrashanth Swaminathan regs. */
166*1fd5a2e1SPrashanth Swaminathan bytes = (6 + ASM_NEEDS_REGISTERS64) * sizeof (long);
167*1fd5a2e1SPrashanth Swaminathan
168*1fd5a2e1SPrashanth Swaminathan /* Space for the mandatory parm save area and general registers. */
169*1fd5a2e1SPrashanth Swaminathan bytes += 2 * NUM_GPR_ARG_REGISTERS64 * sizeof (long);
170*1fd5a2e1SPrashanth Swaminathan #endif
171*1fd5a2e1SPrashanth Swaminathan
172*1fd5a2e1SPrashanth Swaminathan /* Return value handling. */
173*1fd5a2e1SPrashanth Swaminathan rtype = cif->rtype->type;
174*1fd5a2e1SPrashanth Swaminathan #if _CALL_ELF == 2
175*1fd5a2e1SPrashanth Swaminathan homogeneous:
176*1fd5a2e1SPrashanth Swaminathan #endif
177*1fd5a2e1SPrashanth Swaminathan switch (rtype)
178*1fd5a2e1SPrashanth Swaminathan {
179*1fd5a2e1SPrashanth Swaminathan #if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
180*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_LONGDOUBLE:
181*1fd5a2e1SPrashanth Swaminathan if ((cif->abi & FFI_LINUX_LONG_DOUBLE_IEEE128) != 0)
182*1fd5a2e1SPrashanth Swaminathan {
183*1fd5a2e1SPrashanth Swaminathan flags |= FLAG_RETURNS_VEC;
184*1fd5a2e1SPrashanth Swaminathan break;
185*1fd5a2e1SPrashanth Swaminathan }
186*1fd5a2e1SPrashanth Swaminathan if ((cif->abi & FFI_LINUX_LONG_DOUBLE_128) != 0)
187*1fd5a2e1SPrashanth Swaminathan flags |= FLAG_RETURNS_128BITS;
188*1fd5a2e1SPrashanth Swaminathan /* Fall through. */
189*1fd5a2e1SPrashanth Swaminathan #endif
190*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_DOUBLE:
191*1fd5a2e1SPrashanth Swaminathan flags |= FLAG_RETURNS_64BITS;
192*1fd5a2e1SPrashanth Swaminathan /* Fall through. */
193*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_FLOAT:
194*1fd5a2e1SPrashanth Swaminathan flags |= FLAG_RETURNS_FP;
195*1fd5a2e1SPrashanth Swaminathan break;
196*1fd5a2e1SPrashanth Swaminathan
197*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_UINT128:
198*1fd5a2e1SPrashanth Swaminathan flags |= FLAG_RETURNS_128BITS;
199*1fd5a2e1SPrashanth Swaminathan /* Fall through. */
200*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_UINT64:
201*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_SINT64:
202*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_POINTER:
203*1fd5a2e1SPrashanth Swaminathan flags |= FLAG_RETURNS_64BITS;
204*1fd5a2e1SPrashanth Swaminathan break;
205*1fd5a2e1SPrashanth Swaminathan
206*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_STRUCT:
207*1fd5a2e1SPrashanth Swaminathan #if _CALL_ELF == 2
208*1fd5a2e1SPrashanth Swaminathan elt = discover_homogeneous_aggregate (cif->abi, cif->rtype, &elnum);
209*1fd5a2e1SPrashanth Swaminathan if (elt)
210*1fd5a2e1SPrashanth Swaminathan {
211*1fd5a2e1SPrashanth Swaminathan flags |= FLAG_RETURNS_SMST;
212*1fd5a2e1SPrashanth Swaminathan rtype = elt;
213*1fd5a2e1SPrashanth Swaminathan goto homogeneous;
214*1fd5a2e1SPrashanth Swaminathan }
215*1fd5a2e1SPrashanth Swaminathan if (cif->rtype->size <= 16)
216*1fd5a2e1SPrashanth Swaminathan {
217*1fd5a2e1SPrashanth Swaminathan flags |= FLAG_RETURNS_SMST;
218*1fd5a2e1SPrashanth Swaminathan break;
219*1fd5a2e1SPrashanth Swaminathan }
220*1fd5a2e1SPrashanth Swaminathan #endif
221*1fd5a2e1SPrashanth Swaminathan intarg_count++;
222*1fd5a2e1SPrashanth Swaminathan flags |= FLAG_RETVAL_REFERENCE;
223*1fd5a2e1SPrashanth Swaminathan /* Fall through. */
224*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_VOID:
225*1fd5a2e1SPrashanth Swaminathan flags |= FLAG_RETURNS_NOTHING;
226*1fd5a2e1SPrashanth Swaminathan break;
227*1fd5a2e1SPrashanth Swaminathan
228*1fd5a2e1SPrashanth Swaminathan default:
229*1fd5a2e1SPrashanth Swaminathan /* Returns 32-bit integer, or similar. Nothing to do here. */
230*1fd5a2e1SPrashanth Swaminathan break;
231*1fd5a2e1SPrashanth Swaminathan }
232*1fd5a2e1SPrashanth Swaminathan
233*1fd5a2e1SPrashanth Swaminathan for (ptr = cif->arg_types, i = cif->nargs; i > 0; i--, ptr++)
234*1fd5a2e1SPrashanth Swaminathan {
235*1fd5a2e1SPrashanth Swaminathan unsigned int align;
236*1fd5a2e1SPrashanth Swaminathan
237*1fd5a2e1SPrashanth Swaminathan switch ((*ptr)->type)
238*1fd5a2e1SPrashanth Swaminathan {
239*1fd5a2e1SPrashanth Swaminathan #if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
240*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_LONGDOUBLE:
241*1fd5a2e1SPrashanth Swaminathan if ((cif->abi & FFI_LINUX_LONG_DOUBLE_IEEE128) != 0)
242*1fd5a2e1SPrashanth Swaminathan {
243*1fd5a2e1SPrashanth Swaminathan vecarg_count++;
244*1fd5a2e1SPrashanth Swaminathan /* Align to 16 bytes, plus the 16-byte argument. */
245*1fd5a2e1SPrashanth Swaminathan intarg_count = (intarg_count + 3) & ~0x1;
246*1fd5a2e1SPrashanth Swaminathan if (vecarg_count > NUM_VEC_ARG_REGISTERS64)
247*1fd5a2e1SPrashanth Swaminathan flags |= FLAG_ARG_NEEDS_PSAVE;
248*1fd5a2e1SPrashanth Swaminathan break;
249*1fd5a2e1SPrashanth Swaminathan }
250*1fd5a2e1SPrashanth Swaminathan if ((cif->abi & FFI_LINUX_LONG_DOUBLE_128) != 0)
251*1fd5a2e1SPrashanth Swaminathan {
252*1fd5a2e1SPrashanth Swaminathan fparg_count++;
253*1fd5a2e1SPrashanth Swaminathan intarg_count++;
254*1fd5a2e1SPrashanth Swaminathan }
255*1fd5a2e1SPrashanth Swaminathan /* Fall through. */
256*1fd5a2e1SPrashanth Swaminathan #endif
257*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_DOUBLE:
258*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_FLOAT:
259*1fd5a2e1SPrashanth Swaminathan fparg_count++;
260*1fd5a2e1SPrashanth Swaminathan intarg_count++;
261*1fd5a2e1SPrashanth Swaminathan if (fparg_count > NUM_FPR_ARG_REGISTERS64)
262*1fd5a2e1SPrashanth Swaminathan flags |= FLAG_ARG_NEEDS_PSAVE;
263*1fd5a2e1SPrashanth Swaminathan break;
264*1fd5a2e1SPrashanth Swaminathan
265*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_STRUCT:
266*1fd5a2e1SPrashanth Swaminathan if ((cif->abi & FFI_LINUX_STRUCT_ALIGN) != 0)
267*1fd5a2e1SPrashanth Swaminathan {
268*1fd5a2e1SPrashanth Swaminathan align = (*ptr)->alignment;
269*1fd5a2e1SPrashanth Swaminathan if (align > 16)
270*1fd5a2e1SPrashanth Swaminathan align = 16;
271*1fd5a2e1SPrashanth Swaminathan align = align / 8;
272*1fd5a2e1SPrashanth Swaminathan if (align > 1)
273*1fd5a2e1SPrashanth Swaminathan intarg_count = FFI_ALIGN (intarg_count, align);
274*1fd5a2e1SPrashanth Swaminathan }
275*1fd5a2e1SPrashanth Swaminathan intarg_count += ((*ptr)->size + 7) / 8;
276*1fd5a2e1SPrashanth Swaminathan elt = discover_homogeneous_aggregate (cif->abi, *ptr, &elnum);
277*1fd5a2e1SPrashanth Swaminathan #if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
278*1fd5a2e1SPrashanth Swaminathan if (elt == FFI_TYPE_LONGDOUBLE &&
279*1fd5a2e1SPrashanth Swaminathan (cif->abi & FFI_LINUX_LONG_DOUBLE_IEEE128) != 0)
280*1fd5a2e1SPrashanth Swaminathan {
281*1fd5a2e1SPrashanth Swaminathan vecarg_count += elnum;
282*1fd5a2e1SPrashanth Swaminathan if (vecarg_count > NUM_VEC_ARG_REGISTERS64)
283*1fd5a2e1SPrashanth Swaminathan flags |= FLAG_ARG_NEEDS_PSAVE;
284*1fd5a2e1SPrashanth Swaminathan break;
285*1fd5a2e1SPrashanth Swaminathan }
286*1fd5a2e1SPrashanth Swaminathan else
287*1fd5a2e1SPrashanth Swaminathan #endif
288*1fd5a2e1SPrashanth Swaminathan if (elt)
289*1fd5a2e1SPrashanth Swaminathan {
290*1fd5a2e1SPrashanth Swaminathan fparg_count += elnum;
291*1fd5a2e1SPrashanth Swaminathan if (fparg_count > NUM_FPR_ARG_REGISTERS64)
292*1fd5a2e1SPrashanth Swaminathan flags |= FLAG_ARG_NEEDS_PSAVE;
293*1fd5a2e1SPrashanth Swaminathan }
294*1fd5a2e1SPrashanth Swaminathan else
295*1fd5a2e1SPrashanth Swaminathan {
296*1fd5a2e1SPrashanth Swaminathan if (intarg_count > NUM_GPR_ARG_REGISTERS64)
297*1fd5a2e1SPrashanth Swaminathan flags |= FLAG_ARG_NEEDS_PSAVE;
298*1fd5a2e1SPrashanth Swaminathan }
299*1fd5a2e1SPrashanth Swaminathan break;
300*1fd5a2e1SPrashanth Swaminathan
301*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_POINTER:
302*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_UINT64:
303*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_SINT64:
304*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_INT:
305*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_UINT32:
306*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_SINT32:
307*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_UINT16:
308*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_SINT16:
309*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_UINT8:
310*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_SINT8:
311*1fd5a2e1SPrashanth Swaminathan /* Everything else is passed as a 8-byte word in a GPR, either
312*1fd5a2e1SPrashanth Swaminathan the object itself or a pointer to it. */
313*1fd5a2e1SPrashanth Swaminathan intarg_count++;
314*1fd5a2e1SPrashanth Swaminathan if (intarg_count > NUM_GPR_ARG_REGISTERS64)
315*1fd5a2e1SPrashanth Swaminathan flags |= FLAG_ARG_NEEDS_PSAVE;
316*1fd5a2e1SPrashanth Swaminathan break;
317*1fd5a2e1SPrashanth Swaminathan default:
318*1fd5a2e1SPrashanth Swaminathan FFI_ASSERT (0);
319*1fd5a2e1SPrashanth Swaminathan }
320*1fd5a2e1SPrashanth Swaminathan }
321*1fd5a2e1SPrashanth Swaminathan
322*1fd5a2e1SPrashanth Swaminathan if (fparg_count != 0)
323*1fd5a2e1SPrashanth Swaminathan flags |= FLAG_FP_ARGUMENTS;
324*1fd5a2e1SPrashanth Swaminathan if (intarg_count > 4)
325*1fd5a2e1SPrashanth Swaminathan flags |= FLAG_4_GPR_ARGUMENTS;
326*1fd5a2e1SPrashanth Swaminathan if (vecarg_count != 0)
327*1fd5a2e1SPrashanth Swaminathan flags |= FLAG_VEC_ARGUMENTS;
328*1fd5a2e1SPrashanth Swaminathan
329*1fd5a2e1SPrashanth Swaminathan /* Space for the FPR registers, if needed. */
330*1fd5a2e1SPrashanth Swaminathan if (fparg_count != 0)
331*1fd5a2e1SPrashanth Swaminathan bytes += NUM_FPR_ARG_REGISTERS64 * sizeof (double);
332*1fd5a2e1SPrashanth Swaminathan /* Space for the vector registers, if needed, aligned to 16 bytes. */
333*1fd5a2e1SPrashanth Swaminathan if (vecarg_count != 0) {
334*1fd5a2e1SPrashanth Swaminathan bytes = (bytes + 15) & ~0xF;
335*1fd5a2e1SPrashanth Swaminathan bytes += NUM_VEC_ARG_REGISTERS64 * sizeof (float128);
336*1fd5a2e1SPrashanth Swaminathan }
337*1fd5a2e1SPrashanth Swaminathan
338*1fd5a2e1SPrashanth Swaminathan /* Stack space. */
339*1fd5a2e1SPrashanth Swaminathan #if _CALL_ELF == 2
340*1fd5a2e1SPrashanth Swaminathan if ((flags & FLAG_ARG_NEEDS_PSAVE) != 0)
341*1fd5a2e1SPrashanth Swaminathan bytes += intarg_count * sizeof (long);
342*1fd5a2e1SPrashanth Swaminathan #else
343*1fd5a2e1SPrashanth Swaminathan if (intarg_count > NUM_GPR_ARG_REGISTERS64)
344*1fd5a2e1SPrashanth Swaminathan bytes += (intarg_count - NUM_GPR_ARG_REGISTERS64) * sizeof (long);
345*1fd5a2e1SPrashanth Swaminathan #endif
346*1fd5a2e1SPrashanth Swaminathan
347*1fd5a2e1SPrashanth Swaminathan /* The stack space allocated needs to be a multiple of 16 bytes. */
348*1fd5a2e1SPrashanth Swaminathan bytes = (bytes + 15) & ~0xF;
349*1fd5a2e1SPrashanth Swaminathan
350*1fd5a2e1SPrashanth Swaminathan cif->flags = flags;
351*1fd5a2e1SPrashanth Swaminathan cif->bytes = bytes;
352*1fd5a2e1SPrashanth Swaminathan
353*1fd5a2e1SPrashanth Swaminathan return FFI_OK;
354*1fd5a2e1SPrashanth Swaminathan }
355*1fd5a2e1SPrashanth Swaminathan
356*1fd5a2e1SPrashanth Swaminathan ffi_status FFI_HIDDEN
ffi_prep_cif_linux64(ffi_cif * cif)357*1fd5a2e1SPrashanth Swaminathan ffi_prep_cif_linux64 (ffi_cif *cif)
358*1fd5a2e1SPrashanth Swaminathan {
359*1fd5a2e1SPrashanth Swaminathan if ((cif->abi & FFI_LINUX) != 0)
360*1fd5a2e1SPrashanth Swaminathan cif->nfixedargs = cif->nargs;
361*1fd5a2e1SPrashanth Swaminathan #if _CALL_ELF != 2
362*1fd5a2e1SPrashanth Swaminathan else if (cif->abi == FFI_COMPAT_LINUX64)
363*1fd5a2e1SPrashanth Swaminathan {
364*1fd5a2e1SPrashanth Swaminathan /* This call is from old code. Don't touch cif->nfixedargs
365*1fd5a2e1SPrashanth Swaminathan since old code will be using a smaller cif. */
366*1fd5a2e1SPrashanth Swaminathan cif->flags |= FLAG_COMPAT;
367*1fd5a2e1SPrashanth Swaminathan /* Translate to new abi value. */
368*1fd5a2e1SPrashanth Swaminathan cif->abi = FFI_LINUX | FFI_LINUX_LONG_DOUBLE_128;
369*1fd5a2e1SPrashanth Swaminathan }
370*1fd5a2e1SPrashanth Swaminathan #endif
371*1fd5a2e1SPrashanth Swaminathan else
372*1fd5a2e1SPrashanth Swaminathan return FFI_BAD_ABI;
373*1fd5a2e1SPrashanth Swaminathan return ffi_prep_cif_linux64_core (cif);
374*1fd5a2e1SPrashanth Swaminathan }
375*1fd5a2e1SPrashanth Swaminathan
376*1fd5a2e1SPrashanth Swaminathan ffi_status FFI_HIDDEN
ffi_prep_cif_linux64_var(ffi_cif * cif,unsigned int nfixedargs,unsigned int ntotalargs MAYBE_UNUSED)377*1fd5a2e1SPrashanth Swaminathan ffi_prep_cif_linux64_var (ffi_cif *cif,
378*1fd5a2e1SPrashanth Swaminathan unsigned int nfixedargs,
379*1fd5a2e1SPrashanth Swaminathan unsigned int ntotalargs MAYBE_UNUSED)
380*1fd5a2e1SPrashanth Swaminathan {
381*1fd5a2e1SPrashanth Swaminathan if ((cif->abi & FFI_LINUX) != 0)
382*1fd5a2e1SPrashanth Swaminathan cif->nfixedargs = nfixedargs;
383*1fd5a2e1SPrashanth Swaminathan #if _CALL_ELF != 2
384*1fd5a2e1SPrashanth Swaminathan else if (cif->abi == FFI_COMPAT_LINUX64)
385*1fd5a2e1SPrashanth Swaminathan {
386*1fd5a2e1SPrashanth Swaminathan /* This call is from old code. Don't touch cif->nfixedargs
387*1fd5a2e1SPrashanth Swaminathan since old code will be using a smaller cif. */
388*1fd5a2e1SPrashanth Swaminathan cif->flags |= FLAG_COMPAT;
389*1fd5a2e1SPrashanth Swaminathan /* Translate to new abi value. */
390*1fd5a2e1SPrashanth Swaminathan cif->abi = FFI_LINUX | FFI_LINUX_LONG_DOUBLE_128;
391*1fd5a2e1SPrashanth Swaminathan }
392*1fd5a2e1SPrashanth Swaminathan #endif
393*1fd5a2e1SPrashanth Swaminathan else
394*1fd5a2e1SPrashanth Swaminathan return FFI_BAD_ABI;
395*1fd5a2e1SPrashanth Swaminathan #if _CALL_ELF == 2
396*1fd5a2e1SPrashanth Swaminathan cif->flags |= FLAG_ARG_NEEDS_PSAVE;
397*1fd5a2e1SPrashanth Swaminathan #endif
398*1fd5a2e1SPrashanth Swaminathan return ffi_prep_cif_linux64_core (cif);
399*1fd5a2e1SPrashanth Swaminathan }
400*1fd5a2e1SPrashanth Swaminathan
401*1fd5a2e1SPrashanth Swaminathan
402*1fd5a2e1SPrashanth Swaminathan /* ffi_prep_args64 is called by the assembly routine once stack space
403*1fd5a2e1SPrashanth Swaminathan has been allocated for the function's arguments.
404*1fd5a2e1SPrashanth Swaminathan
405*1fd5a2e1SPrashanth Swaminathan The stack layout we want looks like this:
406*1fd5a2e1SPrashanth Swaminathan
407*1fd5a2e1SPrashanth Swaminathan | Ret addr from ffi_call_LINUX64 8bytes | higher addresses
408*1fd5a2e1SPrashanth Swaminathan |--------------------------------------------|
409*1fd5a2e1SPrashanth Swaminathan | CR save area 8bytes |
410*1fd5a2e1SPrashanth Swaminathan |--------------------------------------------|
411*1fd5a2e1SPrashanth Swaminathan | Previous backchain pointer 8 | stack pointer here
412*1fd5a2e1SPrashanth Swaminathan |--------------------------------------------|<+ <<< on entry to
413*1fd5a2e1SPrashanth Swaminathan | Saved r28-r31 4*8 | | ffi_call_LINUX64
414*1fd5a2e1SPrashanth Swaminathan |--------------------------------------------| |
415*1fd5a2e1SPrashanth Swaminathan | GPR registers r3-r10 8*8 | |
416*1fd5a2e1SPrashanth Swaminathan |--------------------------------------------| |
417*1fd5a2e1SPrashanth Swaminathan | FPR registers f1-f13 (optional) 13*8 | |
418*1fd5a2e1SPrashanth Swaminathan |--------------------------------------------| |
419*1fd5a2e1SPrashanth Swaminathan | VEC registers v2-v13 (optional) 12*16 | |
420*1fd5a2e1SPrashanth Swaminathan |--------------------------------------------| |
421*1fd5a2e1SPrashanth Swaminathan | Parameter save area | |
422*1fd5a2e1SPrashanth Swaminathan |--------------------------------------------| |
423*1fd5a2e1SPrashanth Swaminathan | TOC save area 8 | |
424*1fd5a2e1SPrashanth Swaminathan |--------------------------------------------| | stack |
425*1fd5a2e1SPrashanth Swaminathan | Linker doubleword 8 | | grows |
426*1fd5a2e1SPrashanth Swaminathan |--------------------------------------------| | down V
427*1fd5a2e1SPrashanth Swaminathan | Compiler doubleword 8 | |
428*1fd5a2e1SPrashanth Swaminathan |--------------------------------------------| | lower addresses
429*1fd5a2e1SPrashanth Swaminathan | Space for callee's LR 8 | |
430*1fd5a2e1SPrashanth Swaminathan |--------------------------------------------| |
431*1fd5a2e1SPrashanth Swaminathan | CR save area 8 | |
432*1fd5a2e1SPrashanth Swaminathan |--------------------------------------------| | stack pointer here
433*1fd5a2e1SPrashanth Swaminathan | Current backchain pointer 8 |-/ during
434*1fd5a2e1SPrashanth Swaminathan |--------------------------------------------| <<< ffi_call_LINUX64
435*1fd5a2e1SPrashanth Swaminathan
436*1fd5a2e1SPrashanth Swaminathan */
437*1fd5a2e1SPrashanth Swaminathan
438*1fd5a2e1SPrashanth Swaminathan void FFI_HIDDEN
ffi_prep_args64(extended_cif * ecif,unsigned long * const stack)439*1fd5a2e1SPrashanth Swaminathan ffi_prep_args64 (extended_cif *ecif, unsigned long *const stack)
440*1fd5a2e1SPrashanth Swaminathan {
441*1fd5a2e1SPrashanth Swaminathan const unsigned long bytes = ecif->cif->bytes;
442*1fd5a2e1SPrashanth Swaminathan const unsigned long flags = ecif->cif->flags;
443*1fd5a2e1SPrashanth Swaminathan
444*1fd5a2e1SPrashanth Swaminathan typedef union
445*1fd5a2e1SPrashanth Swaminathan {
446*1fd5a2e1SPrashanth Swaminathan char *c;
447*1fd5a2e1SPrashanth Swaminathan unsigned long *ul;
448*1fd5a2e1SPrashanth Swaminathan float *f;
449*1fd5a2e1SPrashanth Swaminathan double *d;
450*1fd5a2e1SPrashanth Swaminathan float128 *f128;
451*1fd5a2e1SPrashanth Swaminathan size_t p;
452*1fd5a2e1SPrashanth Swaminathan } valp;
453*1fd5a2e1SPrashanth Swaminathan
454*1fd5a2e1SPrashanth Swaminathan /* 'stacktop' points at the previous backchain pointer. */
455*1fd5a2e1SPrashanth Swaminathan valp stacktop;
456*1fd5a2e1SPrashanth Swaminathan
457*1fd5a2e1SPrashanth Swaminathan /* 'next_arg' points at the space for gpr3, and grows upwards as
458*1fd5a2e1SPrashanth Swaminathan we use GPR registers, then continues at rest. */
459*1fd5a2e1SPrashanth Swaminathan valp gpr_base;
460*1fd5a2e1SPrashanth Swaminathan valp gpr_end;
461*1fd5a2e1SPrashanth Swaminathan valp rest;
462*1fd5a2e1SPrashanth Swaminathan valp next_arg;
463*1fd5a2e1SPrashanth Swaminathan
464*1fd5a2e1SPrashanth Swaminathan /* 'fpr_base' points at the space for f1, and grows upwards as
465*1fd5a2e1SPrashanth Swaminathan we use FPR registers. */
466*1fd5a2e1SPrashanth Swaminathan valp fpr_base;
467*1fd5a2e1SPrashanth Swaminathan unsigned int fparg_count;
468*1fd5a2e1SPrashanth Swaminathan
469*1fd5a2e1SPrashanth Swaminathan /* 'vec_base' points at the space for v2, and grows upwards as
470*1fd5a2e1SPrashanth Swaminathan we use vector registers. */
471*1fd5a2e1SPrashanth Swaminathan valp vec_base;
472*1fd5a2e1SPrashanth Swaminathan unsigned int vecarg_count;
473*1fd5a2e1SPrashanth Swaminathan
474*1fd5a2e1SPrashanth Swaminathan unsigned int i, words, nargs, nfixedargs;
475*1fd5a2e1SPrashanth Swaminathan ffi_type **ptr;
476*1fd5a2e1SPrashanth Swaminathan double double_tmp;
477*1fd5a2e1SPrashanth Swaminathan union
478*1fd5a2e1SPrashanth Swaminathan {
479*1fd5a2e1SPrashanth Swaminathan void **v;
480*1fd5a2e1SPrashanth Swaminathan char **c;
481*1fd5a2e1SPrashanth Swaminathan signed char **sc;
482*1fd5a2e1SPrashanth Swaminathan unsigned char **uc;
483*1fd5a2e1SPrashanth Swaminathan signed short **ss;
484*1fd5a2e1SPrashanth Swaminathan unsigned short **us;
485*1fd5a2e1SPrashanth Swaminathan signed int **si;
486*1fd5a2e1SPrashanth Swaminathan unsigned int **ui;
487*1fd5a2e1SPrashanth Swaminathan unsigned long **ul;
488*1fd5a2e1SPrashanth Swaminathan float **f;
489*1fd5a2e1SPrashanth Swaminathan double **d;
490*1fd5a2e1SPrashanth Swaminathan float128 **f128;
491*1fd5a2e1SPrashanth Swaminathan } p_argv;
492*1fd5a2e1SPrashanth Swaminathan unsigned long gprvalue;
493*1fd5a2e1SPrashanth Swaminathan unsigned long align;
494*1fd5a2e1SPrashanth Swaminathan
495*1fd5a2e1SPrashanth Swaminathan stacktop.c = (char *) stack + bytes;
496*1fd5a2e1SPrashanth Swaminathan gpr_base.ul = stacktop.ul - ASM_NEEDS_REGISTERS64 - NUM_GPR_ARG_REGISTERS64;
497*1fd5a2e1SPrashanth Swaminathan gpr_end.ul = gpr_base.ul + NUM_GPR_ARG_REGISTERS64;
498*1fd5a2e1SPrashanth Swaminathan #if _CALL_ELF == 2
499*1fd5a2e1SPrashanth Swaminathan rest.ul = stack + 4 + NUM_GPR_ARG_REGISTERS64;
500*1fd5a2e1SPrashanth Swaminathan #else
501*1fd5a2e1SPrashanth Swaminathan rest.ul = stack + 6 + NUM_GPR_ARG_REGISTERS64;
502*1fd5a2e1SPrashanth Swaminathan #endif
503*1fd5a2e1SPrashanth Swaminathan fpr_base.d = gpr_base.d - NUM_FPR_ARG_REGISTERS64;
504*1fd5a2e1SPrashanth Swaminathan fparg_count = 0;
505*1fd5a2e1SPrashanth Swaminathan /* Place the vector args below the FPRs, if used, else the GPRs. */
506*1fd5a2e1SPrashanth Swaminathan if (ecif->cif->flags & FLAG_FP_ARGUMENTS)
507*1fd5a2e1SPrashanth Swaminathan vec_base.p = fpr_base.p & ~0xF;
508*1fd5a2e1SPrashanth Swaminathan else
509*1fd5a2e1SPrashanth Swaminathan vec_base.p = gpr_base.p;
510*1fd5a2e1SPrashanth Swaminathan vec_base.f128 -= NUM_VEC_ARG_REGISTERS64;
511*1fd5a2e1SPrashanth Swaminathan vecarg_count = 0;
512*1fd5a2e1SPrashanth Swaminathan next_arg.ul = gpr_base.ul;
513*1fd5a2e1SPrashanth Swaminathan
514*1fd5a2e1SPrashanth Swaminathan /* Check that everything starts aligned properly. */
515*1fd5a2e1SPrashanth Swaminathan FFI_ASSERT (((unsigned long) (char *) stack & 0xF) == 0);
516*1fd5a2e1SPrashanth Swaminathan FFI_ASSERT (((unsigned long) stacktop.c & 0xF) == 0);
517*1fd5a2e1SPrashanth Swaminathan FFI_ASSERT (((unsigned long) gpr_base.c & 0xF) == 0);
518*1fd5a2e1SPrashanth Swaminathan FFI_ASSERT (((unsigned long) gpr_end.c & 0xF) == 0);
519*1fd5a2e1SPrashanth Swaminathan FFI_ASSERT (((unsigned long) vec_base.c & 0xF) == 0);
520*1fd5a2e1SPrashanth Swaminathan FFI_ASSERT ((bytes & 0xF) == 0);
521*1fd5a2e1SPrashanth Swaminathan
522*1fd5a2e1SPrashanth Swaminathan /* Deal with return values that are actually pass-by-reference. */
523*1fd5a2e1SPrashanth Swaminathan if (flags & FLAG_RETVAL_REFERENCE)
524*1fd5a2e1SPrashanth Swaminathan *next_arg.ul++ = (unsigned long) (char *) ecif->rvalue;
525*1fd5a2e1SPrashanth Swaminathan
526*1fd5a2e1SPrashanth Swaminathan /* Now for the arguments. */
527*1fd5a2e1SPrashanth Swaminathan p_argv.v = ecif->avalue;
528*1fd5a2e1SPrashanth Swaminathan nargs = ecif->cif->nargs;
529*1fd5a2e1SPrashanth Swaminathan #if _CALL_ELF != 2
530*1fd5a2e1SPrashanth Swaminathan nfixedargs = (unsigned) -1;
531*1fd5a2e1SPrashanth Swaminathan if ((flags & FLAG_COMPAT) == 0)
532*1fd5a2e1SPrashanth Swaminathan #endif
533*1fd5a2e1SPrashanth Swaminathan nfixedargs = ecif->cif->nfixedargs;
534*1fd5a2e1SPrashanth Swaminathan for (ptr = ecif->cif->arg_types, i = 0;
535*1fd5a2e1SPrashanth Swaminathan i < nargs;
536*1fd5a2e1SPrashanth Swaminathan i++, ptr++, p_argv.v++)
537*1fd5a2e1SPrashanth Swaminathan {
538*1fd5a2e1SPrashanth Swaminathan unsigned int elt, elnum;
539*1fd5a2e1SPrashanth Swaminathan
540*1fd5a2e1SPrashanth Swaminathan switch ((*ptr)->type)
541*1fd5a2e1SPrashanth Swaminathan {
542*1fd5a2e1SPrashanth Swaminathan #if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
543*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_LONGDOUBLE:
544*1fd5a2e1SPrashanth Swaminathan if ((ecif->cif->abi & FFI_LINUX_LONG_DOUBLE_IEEE128) != 0)
545*1fd5a2e1SPrashanth Swaminathan {
546*1fd5a2e1SPrashanth Swaminathan next_arg.p = FFI_ALIGN (next_arg.p, 16);
547*1fd5a2e1SPrashanth Swaminathan if (next_arg.ul == gpr_end.ul)
548*1fd5a2e1SPrashanth Swaminathan next_arg.ul = rest.ul;
549*1fd5a2e1SPrashanth Swaminathan if (vecarg_count < NUM_VEC_ARG_REGISTERS64 && i < nfixedargs)
550*1fd5a2e1SPrashanth Swaminathan *vec_base.f128++ = **p_argv.f128;
551*1fd5a2e1SPrashanth Swaminathan else
552*1fd5a2e1SPrashanth Swaminathan *next_arg.f128 = **p_argv.f128;
553*1fd5a2e1SPrashanth Swaminathan if (++next_arg.f128 == gpr_end.f128)
554*1fd5a2e1SPrashanth Swaminathan next_arg.f128 = rest.f128;
555*1fd5a2e1SPrashanth Swaminathan vecarg_count++;
556*1fd5a2e1SPrashanth Swaminathan FFI_ASSERT (__LDBL_MANT_DIG__ == 113);
557*1fd5a2e1SPrashanth Swaminathan FFI_ASSERT (flags & FLAG_VEC_ARGUMENTS);
558*1fd5a2e1SPrashanth Swaminathan break;
559*1fd5a2e1SPrashanth Swaminathan }
560*1fd5a2e1SPrashanth Swaminathan if ((ecif->cif->abi & FFI_LINUX_LONG_DOUBLE_128) != 0)
561*1fd5a2e1SPrashanth Swaminathan {
562*1fd5a2e1SPrashanth Swaminathan double_tmp = (*p_argv.d)[0];
563*1fd5a2e1SPrashanth Swaminathan if (fparg_count < NUM_FPR_ARG_REGISTERS64 && i < nfixedargs)
564*1fd5a2e1SPrashanth Swaminathan {
565*1fd5a2e1SPrashanth Swaminathan *fpr_base.d++ = double_tmp;
566*1fd5a2e1SPrashanth Swaminathan # if _CALL_ELF != 2
567*1fd5a2e1SPrashanth Swaminathan if ((flags & FLAG_COMPAT) != 0)
568*1fd5a2e1SPrashanth Swaminathan *next_arg.d = double_tmp;
569*1fd5a2e1SPrashanth Swaminathan # endif
570*1fd5a2e1SPrashanth Swaminathan }
571*1fd5a2e1SPrashanth Swaminathan else
572*1fd5a2e1SPrashanth Swaminathan *next_arg.d = double_tmp;
573*1fd5a2e1SPrashanth Swaminathan if (++next_arg.ul == gpr_end.ul)
574*1fd5a2e1SPrashanth Swaminathan next_arg.ul = rest.ul;
575*1fd5a2e1SPrashanth Swaminathan fparg_count++;
576*1fd5a2e1SPrashanth Swaminathan double_tmp = (*p_argv.d)[1];
577*1fd5a2e1SPrashanth Swaminathan if (fparg_count < NUM_FPR_ARG_REGISTERS64 && i < nfixedargs)
578*1fd5a2e1SPrashanth Swaminathan {
579*1fd5a2e1SPrashanth Swaminathan *fpr_base.d++ = double_tmp;
580*1fd5a2e1SPrashanth Swaminathan # if _CALL_ELF != 2
581*1fd5a2e1SPrashanth Swaminathan if ((flags & FLAG_COMPAT) != 0)
582*1fd5a2e1SPrashanth Swaminathan *next_arg.d = double_tmp;
583*1fd5a2e1SPrashanth Swaminathan # endif
584*1fd5a2e1SPrashanth Swaminathan }
585*1fd5a2e1SPrashanth Swaminathan else
586*1fd5a2e1SPrashanth Swaminathan *next_arg.d = double_tmp;
587*1fd5a2e1SPrashanth Swaminathan if (++next_arg.ul == gpr_end.ul)
588*1fd5a2e1SPrashanth Swaminathan next_arg.ul = rest.ul;
589*1fd5a2e1SPrashanth Swaminathan fparg_count++;
590*1fd5a2e1SPrashanth Swaminathan FFI_ASSERT (__LDBL_MANT_DIG__ == 106);
591*1fd5a2e1SPrashanth Swaminathan FFI_ASSERT (flags & FLAG_FP_ARGUMENTS);
592*1fd5a2e1SPrashanth Swaminathan break;
593*1fd5a2e1SPrashanth Swaminathan }
594*1fd5a2e1SPrashanth Swaminathan /* Fall through. */
595*1fd5a2e1SPrashanth Swaminathan #endif
596*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_DOUBLE:
597*1fd5a2e1SPrashanth Swaminathan #if _CALL_ELF != 2
598*1fd5a2e1SPrashanth Swaminathan do_double:
599*1fd5a2e1SPrashanth Swaminathan #endif
600*1fd5a2e1SPrashanth Swaminathan double_tmp = **p_argv.d;
601*1fd5a2e1SPrashanth Swaminathan if (fparg_count < NUM_FPR_ARG_REGISTERS64 && i < nfixedargs)
602*1fd5a2e1SPrashanth Swaminathan {
603*1fd5a2e1SPrashanth Swaminathan *fpr_base.d++ = double_tmp;
604*1fd5a2e1SPrashanth Swaminathan #if _CALL_ELF != 2
605*1fd5a2e1SPrashanth Swaminathan if ((flags & FLAG_COMPAT) != 0)
606*1fd5a2e1SPrashanth Swaminathan *next_arg.d = double_tmp;
607*1fd5a2e1SPrashanth Swaminathan #endif
608*1fd5a2e1SPrashanth Swaminathan }
609*1fd5a2e1SPrashanth Swaminathan else
610*1fd5a2e1SPrashanth Swaminathan *next_arg.d = double_tmp;
611*1fd5a2e1SPrashanth Swaminathan if (++next_arg.ul == gpr_end.ul)
612*1fd5a2e1SPrashanth Swaminathan next_arg.ul = rest.ul;
613*1fd5a2e1SPrashanth Swaminathan fparg_count++;
614*1fd5a2e1SPrashanth Swaminathan FFI_ASSERT (flags & FLAG_FP_ARGUMENTS);
615*1fd5a2e1SPrashanth Swaminathan break;
616*1fd5a2e1SPrashanth Swaminathan
617*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_FLOAT:
618*1fd5a2e1SPrashanth Swaminathan #if _CALL_ELF != 2
619*1fd5a2e1SPrashanth Swaminathan do_float:
620*1fd5a2e1SPrashanth Swaminathan #endif
621*1fd5a2e1SPrashanth Swaminathan double_tmp = **p_argv.f;
622*1fd5a2e1SPrashanth Swaminathan if (fparg_count < NUM_FPR_ARG_REGISTERS64 && i < nfixedargs)
623*1fd5a2e1SPrashanth Swaminathan {
624*1fd5a2e1SPrashanth Swaminathan *fpr_base.d++ = double_tmp;
625*1fd5a2e1SPrashanth Swaminathan #if _CALL_ELF != 2
626*1fd5a2e1SPrashanth Swaminathan if ((flags & FLAG_COMPAT) != 0)
627*1fd5a2e1SPrashanth Swaminathan {
628*1fd5a2e1SPrashanth Swaminathan # ifndef __LITTLE_ENDIAN__
629*1fd5a2e1SPrashanth Swaminathan next_arg.f[1] = (float) double_tmp;
630*1fd5a2e1SPrashanth Swaminathan # else
631*1fd5a2e1SPrashanth Swaminathan next_arg.f[0] = (float) double_tmp;
632*1fd5a2e1SPrashanth Swaminathan # endif
633*1fd5a2e1SPrashanth Swaminathan }
634*1fd5a2e1SPrashanth Swaminathan #endif
635*1fd5a2e1SPrashanth Swaminathan }
636*1fd5a2e1SPrashanth Swaminathan else
637*1fd5a2e1SPrashanth Swaminathan {
638*1fd5a2e1SPrashanth Swaminathan # ifndef __LITTLE_ENDIAN__
639*1fd5a2e1SPrashanth Swaminathan next_arg.f[1] = (float) double_tmp;
640*1fd5a2e1SPrashanth Swaminathan # else
641*1fd5a2e1SPrashanth Swaminathan next_arg.f[0] = (float) double_tmp;
642*1fd5a2e1SPrashanth Swaminathan # endif
643*1fd5a2e1SPrashanth Swaminathan }
644*1fd5a2e1SPrashanth Swaminathan if (++next_arg.ul == gpr_end.ul)
645*1fd5a2e1SPrashanth Swaminathan next_arg.ul = rest.ul;
646*1fd5a2e1SPrashanth Swaminathan fparg_count++;
647*1fd5a2e1SPrashanth Swaminathan FFI_ASSERT (flags & FLAG_FP_ARGUMENTS);
648*1fd5a2e1SPrashanth Swaminathan break;
649*1fd5a2e1SPrashanth Swaminathan
650*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_STRUCT:
651*1fd5a2e1SPrashanth Swaminathan if ((ecif->cif->abi & FFI_LINUX_STRUCT_ALIGN) != 0)
652*1fd5a2e1SPrashanth Swaminathan {
653*1fd5a2e1SPrashanth Swaminathan align = (*ptr)->alignment;
654*1fd5a2e1SPrashanth Swaminathan if (align > 16)
655*1fd5a2e1SPrashanth Swaminathan align = 16;
656*1fd5a2e1SPrashanth Swaminathan if (align > 1)
657*1fd5a2e1SPrashanth Swaminathan {
658*1fd5a2e1SPrashanth Swaminathan next_arg.p = FFI_ALIGN (next_arg.p, align);
659*1fd5a2e1SPrashanth Swaminathan if (next_arg.ul == gpr_end.ul)
660*1fd5a2e1SPrashanth Swaminathan next_arg.ul = rest.ul;
661*1fd5a2e1SPrashanth Swaminathan }
662*1fd5a2e1SPrashanth Swaminathan }
663*1fd5a2e1SPrashanth Swaminathan elt = discover_homogeneous_aggregate (ecif->cif->abi, *ptr, &elnum);
664*1fd5a2e1SPrashanth Swaminathan if (elt)
665*1fd5a2e1SPrashanth Swaminathan {
666*1fd5a2e1SPrashanth Swaminathan #if _CALL_ELF == 2
667*1fd5a2e1SPrashanth Swaminathan union {
668*1fd5a2e1SPrashanth Swaminathan void *v;
669*1fd5a2e1SPrashanth Swaminathan float *f;
670*1fd5a2e1SPrashanth Swaminathan double *d;
671*1fd5a2e1SPrashanth Swaminathan float128 *f128;
672*1fd5a2e1SPrashanth Swaminathan } arg;
673*1fd5a2e1SPrashanth Swaminathan
674*1fd5a2e1SPrashanth Swaminathan arg.v = *p_argv.v;
675*1fd5a2e1SPrashanth Swaminathan #if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
676*1fd5a2e1SPrashanth Swaminathan if (elt == FFI_TYPE_LONGDOUBLE &&
677*1fd5a2e1SPrashanth Swaminathan (ecif->cif->abi & FFI_LINUX_LONG_DOUBLE_IEEE128) != 0)
678*1fd5a2e1SPrashanth Swaminathan {
679*1fd5a2e1SPrashanth Swaminathan do
680*1fd5a2e1SPrashanth Swaminathan {
681*1fd5a2e1SPrashanth Swaminathan if (vecarg_count < NUM_VEC_ARG_REGISTERS64
682*1fd5a2e1SPrashanth Swaminathan && i < nfixedargs)
683*1fd5a2e1SPrashanth Swaminathan *vec_base.f128++ = *arg.f128++;
684*1fd5a2e1SPrashanth Swaminathan else
685*1fd5a2e1SPrashanth Swaminathan *next_arg.f128 = *arg.f128++;
686*1fd5a2e1SPrashanth Swaminathan if (++next_arg.f128 == gpr_end.f128)
687*1fd5a2e1SPrashanth Swaminathan next_arg.f128 = rest.f128;
688*1fd5a2e1SPrashanth Swaminathan vecarg_count++;
689*1fd5a2e1SPrashanth Swaminathan }
690*1fd5a2e1SPrashanth Swaminathan while (--elnum != 0);
691*1fd5a2e1SPrashanth Swaminathan }
692*1fd5a2e1SPrashanth Swaminathan else
693*1fd5a2e1SPrashanth Swaminathan #endif
694*1fd5a2e1SPrashanth Swaminathan if (elt == FFI_TYPE_FLOAT)
695*1fd5a2e1SPrashanth Swaminathan {
696*1fd5a2e1SPrashanth Swaminathan do
697*1fd5a2e1SPrashanth Swaminathan {
698*1fd5a2e1SPrashanth Swaminathan double_tmp = *arg.f++;
699*1fd5a2e1SPrashanth Swaminathan if (fparg_count < NUM_FPR_ARG_REGISTERS64
700*1fd5a2e1SPrashanth Swaminathan && i < nfixedargs)
701*1fd5a2e1SPrashanth Swaminathan *fpr_base.d++ = double_tmp;
702*1fd5a2e1SPrashanth Swaminathan else
703*1fd5a2e1SPrashanth Swaminathan *next_arg.f = (float) double_tmp;
704*1fd5a2e1SPrashanth Swaminathan if (++next_arg.f == gpr_end.f)
705*1fd5a2e1SPrashanth Swaminathan next_arg.f = rest.f;
706*1fd5a2e1SPrashanth Swaminathan fparg_count++;
707*1fd5a2e1SPrashanth Swaminathan }
708*1fd5a2e1SPrashanth Swaminathan while (--elnum != 0);
709*1fd5a2e1SPrashanth Swaminathan if ((next_arg.p & 7) != 0)
710*1fd5a2e1SPrashanth Swaminathan if (++next_arg.f == gpr_end.f)
711*1fd5a2e1SPrashanth Swaminathan next_arg.f = rest.f;
712*1fd5a2e1SPrashanth Swaminathan }
713*1fd5a2e1SPrashanth Swaminathan else
714*1fd5a2e1SPrashanth Swaminathan do
715*1fd5a2e1SPrashanth Swaminathan {
716*1fd5a2e1SPrashanth Swaminathan double_tmp = *arg.d++;
717*1fd5a2e1SPrashanth Swaminathan if (fparg_count < NUM_FPR_ARG_REGISTERS64 && i < nfixedargs)
718*1fd5a2e1SPrashanth Swaminathan *fpr_base.d++ = double_tmp;
719*1fd5a2e1SPrashanth Swaminathan else
720*1fd5a2e1SPrashanth Swaminathan *next_arg.d = double_tmp;
721*1fd5a2e1SPrashanth Swaminathan if (++next_arg.d == gpr_end.d)
722*1fd5a2e1SPrashanth Swaminathan next_arg.d = rest.d;
723*1fd5a2e1SPrashanth Swaminathan fparg_count++;
724*1fd5a2e1SPrashanth Swaminathan }
725*1fd5a2e1SPrashanth Swaminathan while (--elnum != 0);
726*1fd5a2e1SPrashanth Swaminathan #else
727*1fd5a2e1SPrashanth Swaminathan if (elt == FFI_TYPE_FLOAT)
728*1fd5a2e1SPrashanth Swaminathan goto do_float;
729*1fd5a2e1SPrashanth Swaminathan else
730*1fd5a2e1SPrashanth Swaminathan goto do_double;
731*1fd5a2e1SPrashanth Swaminathan #endif
732*1fd5a2e1SPrashanth Swaminathan }
733*1fd5a2e1SPrashanth Swaminathan else
734*1fd5a2e1SPrashanth Swaminathan {
735*1fd5a2e1SPrashanth Swaminathan words = ((*ptr)->size + 7) / 8;
736*1fd5a2e1SPrashanth Swaminathan if (next_arg.ul >= gpr_base.ul && next_arg.ul + words > gpr_end.ul)
737*1fd5a2e1SPrashanth Swaminathan {
738*1fd5a2e1SPrashanth Swaminathan size_t first = gpr_end.c - next_arg.c;
739*1fd5a2e1SPrashanth Swaminathan memcpy (next_arg.c, *p_argv.c, first);
740*1fd5a2e1SPrashanth Swaminathan memcpy (rest.c, *p_argv.c + first, (*ptr)->size - first);
741*1fd5a2e1SPrashanth Swaminathan next_arg.c = rest.c + words * 8 - first;
742*1fd5a2e1SPrashanth Swaminathan }
743*1fd5a2e1SPrashanth Swaminathan else
744*1fd5a2e1SPrashanth Swaminathan {
745*1fd5a2e1SPrashanth Swaminathan char *where = next_arg.c;
746*1fd5a2e1SPrashanth Swaminathan
747*1fd5a2e1SPrashanth Swaminathan #ifndef __LITTLE_ENDIAN__
748*1fd5a2e1SPrashanth Swaminathan /* Structures with size less than eight bytes are passed
749*1fd5a2e1SPrashanth Swaminathan left-padded. */
750*1fd5a2e1SPrashanth Swaminathan if ((*ptr)->size < 8)
751*1fd5a2e1SPrashanth Swaminathan where += 8 - (*ptr)->size;
752*1fd5a2e1SPrashanth Swaminathan #endif
753*1fd5a2e1SPrashanth Swaminathan memcpy (where, *p_argv.c, (*ptr)->size);
754*1fd5a2e1SPrashanth Swaminathan next_arg.ul += words;
755*1fd5a2e1SPrashanth Swaminathan if (next_arg.ul == gpr_end.ul)
756*1fd5a2e1SPrashanth Swaminathan next_arg.ul = rest.ul;
757*1fd5a2e1SPrashanth Swaminathan }
758*1fd5a2e1SPrashanth Swaminathan }
759*1fd5a2e1SPrashanth Swaminathan break;
760*1fd5a2e1SPrashanth Swaminathan
761*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_UINT8:
762*1fd5a2e1SPrashanth Swaminathan gprvalue = **p_argv.uc;
763*1fd5a2e1SPrashanth Swaminathan goto putgpr;
764*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_SINT8:
765*1fd5a2e1SPrashanth Swaminathan gprvalue = **p_argv.sc;
766*1fd5a2e1SPrashanth Swaminathan goto putgpr;
767*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_UINT16:
768*1fd5a2e1SPrashanth Swaminathan gprvalue = **p_argv.us;
769*1fd5a2e1SPrashanth Swaminathan goto putgpr;
770*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_SINT16:
771*1fd5a2e1SPrashanth Swaminathan gprvalue = **p_argv.ss;
772*1fd5a2e1SPrashanth Swaminathan goto putgpr;
773*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_UINT32:
774*1fd5a2e1SPrashanth Swaminathan gprvalue = **p_argv.ui;
775*1fd5a2e1SPrashanth Swaminathan goto putgpr;
776*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_INT:
777*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_SINT32:
778*1fd5a2e1SPrashanth Swaminathan gprvalue = **p_argv.si;
779*1fd5a2e1SPrashanth Swaminathan goto putgpr;
780*1fd5a2e1SPrashanth Swaminathan
781*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_UINT64:
782*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_SINT64:
783*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_POINTER:
784*1fd5a2e1SPrashanth Swaminathan gprvalue = **p_argv.ul;
785*1fd5a2e1SPrashanth Swaminathan putgpr:
786*1fd5a2e1SPrashanth Swaminathan *next_arg.ul++ = gprvalue;
787*1fd5a2e1SPrashanth Swaminathan if (next_arg.ul == gpr_end.ul)
788*1fd5a2e1SPrashanth Swaminathan next_arg.ul = rest.ul;
789*1fd5a2e1SPrashanth Swaminathan break;
790*1fd5a2e1SPrashanth Swaminathan }
791*1fd5a2e1SPrashanth Swaminathan }
792*1fd5a2e1SPrashanth Swaminathan
793*1fd5a2e1SPrashanth Swaminathan FFI_ASSERT (flags & FLAG_4_GPR_ARGUMENTS
794*1fd5a2e1SPrashanth Swaminathan || (next_arg.ul >= gpr_base.ul
795*1fd5a2e1SPrashanth Swaminathan && next_arg.ul <= gpr_base.ul + 4));
796*1fd5a2e1SPrashanth Swaminathan }
797*1fd5a2e1SPrashanth Swaminathan
798*1fd5a2e1SPrashanth Swaminathan
799*1fd5a2e1SPrashanth Swaminathan #if _CALL_ELF == 2
800*1fd5a2e1SPrashanth Swaminathan #define MIN_CACHE_LINE_SIZE 8
801*1fd5a2e1SPrashanth Swaminathan
802*1fd5a2e1SPrashanth Swaminathan static void
flush_icache(char * wraddr,char * xaddr,int size)803*1fd5a2e1SPrashanth Swaminathan flush_icache (char *wraddr, char *xaddr, int size)
804*1fd5a2e1SPrashanth Swaminathan {
805*1fd5a2e1SPrashanth Swaminathan int i;
806*1fd5a2e1SPrashanth Swaminathan for (i = 0; i < size; i += MIN_CACHE_LINE_SIZE)
807*1fd5a2e1SPrashanth Swaminathan __asm__ volatile ("icbi 0,%0;" "dcbf 0,%1;"
808*1fd5a2e1SPrashanth Swaminathan : : "r" (xaddr + i), "r" (wraddr + i) : "memory");
809*1fd5a2e1SPrashanth Swaminathan __asm__ volatile ("icbi 0,%0;" "dcbf 0,%1;" "sync;" "isync;"
810*1fd5a2e1SPrashanth Swaminathan : : "r"(xaddr + size - 1), "r"(wraddr + size - 1)
811*1fd5a2e1SPrashanth Swaminathan : "memory");
812*1fd5a2e1SPrashanth Swaminathan }
813*1fd5a2e1SPrashanth Swaminathan #endif
814*1fd5a2e1SPrashanth Swaminathan
815*1fd5a2e1SPrashanth Swaminathan
816*1fd5a2e1SPrashanth Swaminathan ffi_status FFI_HIDDEN
ffi_prep_closure_loc_linux64(ffi_closure * closure,ffi_cif * cif,void (* fun)(ffi_cif *,void *,void **,void *),void * user_data,void * codeloc)817*1fd5a2e1SPrashanth Swaminathan ffi_prep_closure_loc_linux64 (ffi_closure *closure,
818*1fd5a2e1SPrashanth Swaminathan ffi_cif *cif,
819*1fd5a2e1SPrashanth Swaminathan void (*fun) (ffi_cif *, void *, void **, void *),
820*1fd5a2e1SPrashanth Swaminathan void *user_data,
821*1fd5a2e1SPrashanth Swaminathan void *codeloc)
822*1fd5a2e1SPrashanth Swaminathan {
823*1fd5a2e1SPrashanth Swaminathan #if _CALL_ELF == 2
824*1fd5a2e1SPrashanth Swaminathan unsigned int *tramp = (unsigned int *) &closure->tramp[0];
825*1fd5a2e1SPrashanth Swaminathan
826*1fd5a2e1SPrashanth Swaminathan if (cif->abi < FFI_LINUX || cif->abi >= FFI_LAST_ABI)
827*1fd5a2e1SPrashanth Swaminathan return FFI_BAD_ABI;
828*1fd5a2e1SPrashanth Swaminathan
829*1fd5a2e1SPrashanth Swaminathan tramp[0] = 0xe96c0018; /* 0: ld 11,2f-0b(12) */
830*1fd5a2e1SPrashanth Swaminathan tramp[1] = 0xe98c0010; /* ld 12,1f-0b(12) */
831*1fd5a2e1SPrashanth Swaminathan tramp[2] = 0x7d8903a6; /* mtctr 12 */
832*1fd5a2e1SPrashanth Swaminathan tramp[3] = 0x4e800420; /* bctr */
833*1fd5a2e1SPrashanth Swaminathan /* 1: .quad function_addr */
834*1fd5a2e1SPrashanth Swaminathan /* 2: .quad context */
835*1fd5a2e1SPrashanth Swaminathan *(void **) &tramp[4] = (void *) ffi_closure_LINUX64;
836*1fd5a2e1SPrashanth Swaminathan *(void **) &tramp[6] = codeloc;
837*1fd5a2e1SPrashanth Swaminathan flush_icache ((char *) tramp, (char *) codeloc, 4 * 4);
838*1fd5a2e1SPrashanth Swaminathan #else
839*1fd5a2e1SPrashanth Swaminathan void **tramp = (void **) &closure->tramp[0];
840*1fd5a2e1SPrashanth Swaminathan
841*1fd5a2e1SPrashanth Swaminathan if (cif->abi < FFI_LINUX || cif->abi >= FFI_LAST_ABI)
842*1fd5a2e1SPrashanth Swaminathan return FFI_BAD_ABI;
843*1fd5a2e1SPrashanth Swaminathan
844*1fd5a2e1SPrashanth Swaminathan /* Copy function address and TOC from ffi_closure_LINUX64 OPD. */
845*1fd5a2e1SPrashanth Swaminathan memcpy (&tramp[0], (void **) ffi_closure_LINUX64, sizeof (void *));
846*1fd5a2e1SPrashanth Swaminathan tramp[1] = codeloc;
847*1fd5a2e1SPrashanth Swaminathan memcpy (&tramp[2], (void **) ffi_closure_LINUX64 + 1, sizeof (void *));
848*1fd5a2e1SPrashanth Swaminathan #endif
849*1fd5a2e1SPrashanth Swaminathan
850*1fd5a2e1SPrashanth Swaminathan closure->cif = cif;
851*1fd5a2e1SPrashanth Swaminathan closure->fun = fun;
852*1fd5a2e1SPrashanth Swaminathan closure->user_data = user_data;
853*1fd5a2e1SPrashanth Swaminathan
854*1fd5a2e1SPrashanth Swaminathan return FFI_OK;
855*1fd5a2e1SPrashanth Swaminathan }
856*1fd5a2e1SPrashanth Swaminathan
857*1fd5a2e1SPrashanth Swaminathan
858*1fd5a2e1SPrashanth Swaminathan int FFI_HIDDEN
ffi_closure_helper_LINUX64(ffi_cif * cif,void (* fun)(ffi_cif *,void *,void **,void *),void * user_data,void * rvalue,unsigned long * pst,ffi_dblfl * pfr,float128 * pvec)859*1fd5a2e1SPrashanth Swaminathan ffi_closure_helper_LINUX64 (ffi_cif *cif,
860*1fd5a2e1SPrashanth Swaminathan void (*fun) (ffi_cif *, void *, void **, void *),
861*1fd5a2e1SPrashanth Swaminathan void *user_data,
862*1fd5a2e1SPrashanth Swaminathan void *rvalue,
863*1fd5a2e1SPrashanth Swaminathan unsigned long *pst,
864*1fd5a2e1SPrashanth Swaminathan ffi_dblfl *pfr,
865*1fd5a2e1SPrashanth Swaminathan float128 *pvec)
866*1fd5a2e1SPrashanth Swaminathan {
867*1fd5a2e1SPrashanth Swaminathan /* rvalue is the pointer to space for return value in closure assembly */
868*1fd5a2e1SPrashanth Swaminathan /* pst is the pointer to parameter save area
869*1fd5a2e1SPrashanth Swaminathan (r3-r10 are stored into its first 8 slots by ffi_closure_LINUX64) */
870*1fd5a2e1SPrashanth Swaminathan /* pfr is the pointer to where f1-f13 are stored in ffi_closure_LINUX64 */
871*1fd5a2e1SPrashanth Swaminathan /* pvec is the pointer to where v2-v13 are stored in ffi_closure_LINUX64 */
872*1fd5a2e1SPrashanth Swaminathan
873*1fd5a2e1SPrashanth Swaminathan void **avalue;
874*1fd5a2e1SPrashanth Swaminathan ffi_type **arg_types;
875*1fd5a2e1SPrashanth Swaminathan unsigned long i, avn, nfixedargs;
876*1fd5a2e1SPrashanth Swaminathan ffi_dblfl *end_pfr = pfr + NUM_FPR_ARG_REGISTERS64;
877*1fd5a2e1SPrashanth Swaminathan float128 *end_pvec = pvec + NUM_VEC_ARG_REGISTERS64;
878*1fd5a2e1SPrashanth Swaminathan unsigned long align;
879*1fd5a2e1SPrashanth Swaminathan
880*1fd5a2e1SPrashanth Swaminathan avalue = alloca (cif->nargs * sizeof (void *));
881*1fd5a2e1SPrashanth Swaminathan
882*1fd5a2e1SPrashanth Swaminathan /* Copy the caller's structure return value address so that the
883*1fd5a2e1SPrashanth Swaminathan closure returns the data directly to the caller. */
884*1fd5a2e1SPrashanth Swaminathan if (cif->rtype->type == FFI_TYPE_STRUCT
885*1fd5a2e1SPrashanth Swaminathan && (cif->flags & FLAG_RETURNS_SMST) == 0)
886*1fd5a2e1SPrashanth Swaminathan {
887*1fd5a2e1SPrashanth Swaminathan rvalue = (void *) *pst;
888*1fd5a2e1SPrashanth Swaminathan pst++;
889*1fd5a2e1SPrashanth Swaminathan }
890*1fd5a2e1SPrashanth Swaminathan
891*1fd5a2e1SPrashanth Swaminathan i = 0;
892*1fd5a2e1SPrashanth Swaminathan avn = cif->nargs;
893*1fd5a2e1SPrashanth Swaminathan #if _CALL_ELF != 2
894*1fd5a2e1SPrashanth Swaminathan nfixedargs = (unsigned) -1;
895*1fd5a2e1SPrashanth Swaminathan if ((cif->flags & FLAG_COMPAT) == 0)
896*1fd5a2e1SPrashanth Swaminathan #endif
897*1fd5a2e1SPrashanth Swaminathan nfixedargs = cif->nfixedargs;
898*1fd5a2e1SPrashanth Swaminathan arg_types = cif->arg_types;
899*1fd5a2e1SPrashanth Swaminathan
900*1fd5a2e1SPrashanth Swaminathan /* Grab the addresses of the arguments from the stack frame. */
901*1fd5a2e1SPrashanth Swaminathan while (i < avn)
902*1fd5a2e1SPrashanth Swaminathan {
903*1fd5a2e1SPrashanth Swaminathan unsigned int elt, elnum;
904*1fd5a2e1SPrashanth Swaminathan
905*1fd5a2e1SPrashanth Swaminathan switch (arg_types[i]->type)
906*1fd5a2e1SPrashanth Swaminathan {
907*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_SINT8:
908*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_UINT8:
909*1fd5a2e1SPrashanth Swaminathan #ifndef __LITTLE_ENDIAN__
910*1fd5a2e1SPrashanth Swaminathan avalue[i] = (char *) pst + 7;
911*1fd5a2e1SPrashanth Swaminathan pst++;
912*1fd5a2e1SPrashanth Swaminathan break;
913*1fd5a2e1SPrashanth Swaminathan #endif
914*1fd5a2e1SPrashanth Swaminathan
915*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_SINT16:
916*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_UINT16:
917*1fd5a2e1SPrashanth Swaminathan #ifndef __LITTLE_ENDIAN__
918*1fd5a2e1SPrashanth Swaminathan avalue[i] = (char *) pst + 6;
919*1fd5a2e1SPrashanth Swaminathan pst++;
920*1fd5a2e1SPrashanth Swaminathan break;
921*1fd5a2e1SPrashanth Swaminathan #endif
922*1fd5a2e1SPrashanth Swaminathan
923*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_SINT32:
924*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_UINT32:
925*1fd5a2e1SPrashanth Swaminathan #ifndef __LITTLE_ENDIAN__
926*1fd5a2e1SPrashanth Swaminathan avalue[i] = (char *) pst + 4;
927*1fd5a2e1SPrashanth Swaminathan pst++;
928*1fd5a2e1SPrashanth Swaminathan break;
929*1fd5a2e1SPrashanth Swaminathan #endif
930*1fd5a2e1SPrashanth Swaminathan
931*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_SINT64:
932*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_UINT64:
933*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_POINTER:
934*1fd5a2e1SPrashanth Swaminathan avalue[i] = pst;
935*1fd5a2e1SPrashanth Swaminathan pst++;
936*1fd5a2e1SPrashanth Swaminathan break;
937*1fd5a2e1SPrashanth Swaminathan
938*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_STRUCT:
939*1fd5a2e1SPrashanth Swaminathan if ((cif->abi & FFI_LINUX_STRUCT_ALIGN) != 0)
940*1fd5a2e1SPrashanth Swaminathan {
941*1fd5a2e1SPrashanth Swaminathan align = arg_types[i]->alignment;
942*1fd5a2e1SPrashanth Swaminathan if (align > 16)
943*1fd5a2e1SPrashanth Swaminathan align = 16;
944*1fd5a2e1SPrashanth Swaminathan if (align > 1)
945*1fd5a2e1SPrashanth Swaminathan pst = (unsigned long *) FFI_ALIGN ((size_t) pst, align);
946*1fd5a2e1SPrashanth Swaminathan }
947*1fd5a2e1SPrashanth Swaminathan elt = discover_homogeneous_aggregate (cif->abi, arg_types[i], &elnum);
948*1fd5a2e1SPrashanth Swaminathan if (elt)
949*1fd5a2e1SPrashanth Swaminathan {
950*1fd5a2e1SPrashanth Swaminathan #if _CALL_ELF == 2
951*1fd5a2e1SPrashanth Swaminathan union {
952*1fd5a2e1SPrashanth Swaminathan void *v;
953*1fd5a2e1SPrashanth Swaminathan unsigned long *ul;
954*1fd5a2e1SPrashanth Swaminathan float *f;
955*1fd5a2e1SPrashanth Swaminathan double *d;
956*1fd5a2e1SPrashanth Swaminathan float128 *f128;
957*1fd5a2e1SPrashanth Swaminathan size_t p;
958*1fd5a2e1SPrashanth Swaminathan } to, from;
959*1fd5a2e1SPrashanth Swaminathan
960*1fd5a2e1SPrashanth Swaminathan /* Repackage the aggregate from its parts. The
961*1fd5a2e1SPrashanth Swaminathan aggregate size is not greater than the space taken by
962*1fd5a2e1SPrashanth Swaminathan the registers so store back to the register/parameter
963*1fd5a2e1SPrashanth Swaminathan save arrays. */
964*1fd5a2e1SPrashanth Swaminathan #if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
965*1fd5a2e1SPrashanth Swaminathan if (elt == FFI_TYPE_LONGDOUBLE &&
966*1fd5a2e1SPrashanth Swaminathan (cif->abi & FFI_LINUX_LONG_DOUBLE_IEEE128) != 0)
967*1fd5a2e1SPrashanth Swaminathan {
968*1fd5a2e1SPrashanth Swaminathan if (pvec + elnum <= end_pvec)
969*1fd5a2e1SPrashanth Swaminathan to.v = pvec;
970*1fd5a2e1SPrashanth Swaminathan else
971*1fd5a2e1SPrashanth Swaminathan to.v = pst;
972*1fd5a2e1SPrashanth Swaminathan }
973*1fd5a2e1SPrashanth Swaminathan else
974*1fd5a2e1SPrashanth Swaminathan #endif
975*1fd5a2e1SPrashanth Swaminathan if (pfr + elnum <= end_pfr)
976*1fd5a2e1SPrashanth Swaminathan to.v = pfr;
977*1fd5a2e1SPrashanth Swaminathan else
978*1fd5a2e1SPrashanth Swaminathan to.v = pst;
979*1fd5a2e1SPrashanth Swaminathan
980*1fd5a2e1SPrashanth Swaminathan avalue[i] = to.v;
981*1fd5a2e1SPrashanth Swaminathan from.ul = pst;
982*1fd5a2e1SPrashanth Swaminathan #if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
983*1fd5a2e1SPrashanth Swaminathan if (elt == FFI_TYPE_LONGDOUBLE &&
984*1fd5a2e1SPrashanth Swaminathan (cif->abi & FFI_LINUX_LONG_DOUBLE_IEEE128) != 0)
985*1fd5a2e1SPrashanth Swaminathan {
986*1fd5a2e1SPrashanth Swaminathan do
987*1fd5a2e1SPrashanth Swaminathan {
988*1fd5a2e1SPrashanth Swaminathan if (pvec < end_pvec && i < nfixedargs)
989*1fd5a2e1SPrashanth Swaminathan *to.f128 = *pvec++;
990*1fd5a2e1SPrashanth Swaminathan else
991*1fd5a2e1SPrashanth Swaminathan *to.f128 = *from.f128;
992*1fd5a2e1SPrashanth Swaminathan to.f128++;
993*1fd5a2e1SPrashanth Swaminathan from.f128++;
994*1fd5a2e1SPrashanth Swaminathan }
995*1fd5a2e1SPrashanth Swaminathan while (--elnum != 0);
996*1fd5a2e1SPrashanth Swaminathan }
997*1fd5a2e1SPrashanth Swaminathan else
998*1fd5a2e1SPrashanth Swaminathan #endif
999*1fd5a2e1SPrashanth Swaminathan if (elt == FFI_TYPE_FLOAT)
1000*1fd5a2e1SPrashanth Swaminathan {
1001*1fd5a2e1SPrashanth Swaminathan do
1002*1fd5a2e1SPrashanth Swaminathan {
1003*1fd5a2e1SPrashanth Swaminathan if (pfr < end_pfr && i < nfixedargs)
1004*1fd5a2e1SPrashanth Swaminathan {
1005*1fd5a2e1SPrashanth Swaminathan *to.f = (float) pfr->d;
1006*1fd5a2e1SPrashanth Swaminathan pfr++;
1007*1fd5a2e1SPrashanth Swaminathan }
1008*1fd5a2e1SPrashanth Swaminathan else
1009*1fd5a2e1SPrashanth Swaminathan *to.f = *from.f;
1010*1fd5a2e1SPrashanth Swaminathan to.f++;
1011*1fd5a2e1SPrashanth Swaminathan from.f++;
1012*1fd5a2e1SPrashanth Swaminathan }
1013*1fd5a2e1SPrashanth Swaminathan while (--elnum != 0);
1014*1fd5a2e1SPrashanth Swaminathan }
1015*1fd5a2e1SPrashanth Swaminathan else
1016*1fd5a2e1SPrashanth Swaminathan {
1017*1fd5a2e1SPrashanth Swaminathan do
1018*1fd5a2e1SPrashanth Swaminathan {
1019*1fd5a2e1SPrashanth Swaminathan if (pfr < end_pfr && i < nfixedargs)
1020*1fd5a2e1SPrashanth Swaminathan {
1021*1fd5a2e1SPrashanth Swaminathan *to.d = pfr->d;
1022*1fd5a2e1SPrashanth Swaminathan pfr++;
1023*1fd5a2e1SPrashanth Swaminathan }
1024*1fd5a2e1SPrashanth Swaminathan else
1025*1fd5a2e1SPrashanth Swaminathan *to.d = *from.d;
1026*1fd5a2e1SPrashanth Swaminathan to.d++;
1027*1fd5a2e1SPrashanth Swaminathan from.d++;
1028*1fd5a2e1SPrashanth Swaminathan }
1029*1fd5a2e1SPrashanth Swaminathan while (--elnum != 0);
1030*1fd5a2e1SPrashanth Swaminathan }
1031*1fd5a2e1SPrashanth Swaminathan #else
1032*1fd5a2e1SPrashanth Swaminathan if (elt == FFI_TYPE_FLOAT)
1033*1fd5a2e1SPrashanth Swaminathan goto do_float;
1034*1fd5a2e1SPrashanth Swaminathan else
1035*1fd5a2e1SPrashanth Swaminathan goto do_double;
1036*1fd5a2e1SPrashanth Swaminathan #endif
1037*1fd5a2e1SPrashanth Swaminathan }
1038*1fd5a2e1SPrashanth Swaminathan else
1039*1fd5a2e1SPrashanth Swaminathan {
1040*1fd5a2e1SPrashanth Swaminathan #ifndef __LITTLE_ENDIAN__
1041*1fd5a2e1SPrashanth Swaminathan /* Structures with size less than eight bytes are passed
1042*1fd5a2e1SPrashanth Swaminathan left-padded. */
1043*1fd5a2e1SPrashanth Swaminathan if (arg_types[i]->size < 8)
1044*1fd5a2e1SPrashanth Swaminathan avalue[i] = (char *) pst + 8 - arg_types[i]->size;
1045*1fd5a2e1SPrashanth Swaminathan else
1046*1fd5a2e1SPrashanth Swaminathan #endif
1047*1fd5a2e1SPrashanth Swaminathan avalue[i] = pst;
1048*1fd5a2e1SPrashanth Swaminathan }
1049*1fd5a2e1SPrashanth Swaminathan pst += (arg_types[i]->size + 7) / 8;
1050*1fd5a2e1SPrashanth Swaminathan break;
1051*1fd5a2e1SPrashanth Swaminathan
1052*1fd5a2e1SPrashanth Swaminathan #if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
1053*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_LONGDOUBLE:
1054*1fd5a2e1SPrashanth Swaminathan if ((cif->abi & FFI_LINUX_LONG_DOUBLE_IEEE128) != 0)
1055*1fd5a2e1SPrashanth Swaminathan {
1056*1fd5a2e1SPrashanth Swaminathan if (((unsigned long) pst & 0xF) != 0)
1057*1fd5a2e1SPrashanth Swaminathan ++pst;
1058*1fd5a2e1SPrashanth Swaminathan if (pvec < end_pvec && i < nfixedargs)
1059*1fd5a2e1SPrashanth Swaminathan avalue[i] = pvec++;
1060*1fd5a2e1SPrashanth Swaminathan else
1061*1fd5a2e1SPrashanth Swaminathan avalue[i] = pst;
1062*1fd5a2e1SPrashanth Swaminathan pst += 2;
1063*1fd5a2e1SPrashanth Swaminathan break;
1064*1fd5a2e1SPrashanth Swaminathan }
1065*1fd5a2e1SPrashanth Swaminathan else if ((cif->abi & FFI_LINUX_LONG_DOUBLE_128) != 0)
1066*1fd5a2e1SPrashanth Swaminathan {
1067*1fd5a2e1SPrashanth Swaminathan if (pfr + 1 < end_pfr && i + 1 < nfixedargs)
1068*1fd5a2e1SPrashanth Swaminathan {
1069*1fd5a2e1SPrashanth Swaminathan avalue[i] = pfr;
1070*1fd5a2e1SPrashanth Swaminathan pfr += 2;
1071*1fd5a2e1SPrashanth Swaminathan }
1072*1fd5a2e1SPrashanth Swaminathan else
1073*1fd5a2e1SPrashanth Swaminathan {
1074*1fd5a2e1SPrashanth Swaminathan if (pfr < end_pfr && i < nfixedargs)
1075*1fd5a2e1SPrashanth Swaminathan {
1076*1fd5a2e1SPrashanth Swaminathan /* Passed partly in f13 and partly on the stack.
1077*1fd5a2e1SPrashanth Swaminathan Move it all to the stack. */
1078*1fd5a2e1SPrashanth Swaminathan *pst = *(unsigned long *) pfr;
1079*1fd5a2e1SPrashanth Swaminathan pfr++;
1080*1fd5a2e1SPrashanth Swaminathan }
1081*1fd5a2e1SPrashanth Swaminathan avalue[i] = pst;
1082*1fd5a2e1SPrashanth Swaminathan }
1083*1fd5a2e1SPrashanth Swaminathan pst += 2;
1084*1fd5a2e1SPrashanth Swaminathan break;
1085*1fd5a2e1SPrashanth Swaminathan }
1086*1fd5a2e1SPrashanth Swaminathan /* Fall through. */
1087*1fd5a2e1SPrashanth Swaminathan #endif
1088*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_DOUBLE:
1089*1fd5a2e1SPrashanth Swaminathan #if _CALL_ELF != 2
1090*1fd5a2e1SPrashanth Swaminathan do_double:
1091*1fd5a2e1SPrashanth Swaminathan #endif
1092*1fd5a2e1SPrashanth Swaminathan /* On the outgoing stack all values are aligned to 8 */
1093*1fd5a2e1SPrashanth Swaminathan /* there are 13 64bit floating point registers */
1094*1fd5a2e1SPrashanth Swaminathan
1095*1fd5a2e1SPrashanth Swaminathan if (pfr < end_pfr && i < nfixedargs)
1096*1fd5a2e1SPrashanth Swaminathan {
1097*1fd5a2e1SPrashanth Swaminathan avalue[i] = pfr;
1098*1fd5a2e1SPrashanth Swaminathan pfr++;
1099*1fd5a2e1SPrashanth Swaminathan }
1100*1fd5a2e1SPrashanth Swaminathan else
1101*1fd5a2e1SPrashanth Swaminathan avalue[i] = pst;
1102*1fd5a2e1SPrashanth Swaminathan pst++;
1103*1fd5a2e1SPrashanth Swaminathan break;
1104*1fd5a2e1SPrashanth Swaminathan
1105*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_FLOAT:
1106*1fd5a2e1SPrashanth Swaminathan #if _CALL_ELF != 2
1107*1fd5a2e1SPrashanth Swaminathan do_float:
1108*1fd5a2e1SPrashanth Swaminathan #endif
1109*1fd5a2e1SPrashanth Swaminathan if (pfr < end_pfr && i < nfixedargs)
1110*1fd5a2e1SPrashanth Swaminathan {
1111*1fd5a2e1SPrashanth Swaminathan /* Float values are stored as doubles in the
1112*1fd5a2e1SPrashanth Swaminathan ffi_closure_LINUX64 code. Fix them here. */
1113*1fd5a2e1SPrashanth Swaminathan pfr->f = (float) pfr->d;
1114*1fd5a2e1SPrashanth Swaminathan avalue[i] = pfr;
1115*1fd5a2e1SPrashanth Swaminathan pfr++;
1116*1fd5a2e1SPrashanth Swaminathan }
1117*1fd5a2e1SPrashanth Swaminathan else
1118*1fd5a2e1SPrashanth Swaminathan {
1119*1fd5a2e1SPrashanth Swaminathan #ifndef __LITTLE_ENDIAN__
1120*1fd5a2e1SPrashanth Swaminathan avalue[i] = (char *) pst + 4;
1121*1fd5a2e1SPrashanth Swaminathan #else
1122*1fd5a2e1SPrashanth Swaminathan avalue[i] = pst;
1123*1fd5a2e1SPrashanth Swaminathan #endif
1124*1fd5a2e1SPrashanth Swaminathan }
1125*1fd5a2e1SPrashanth Swaminathan pst++;
1126*1fd5a2e1SPrashanth Swaminathan break;
1127*1fd5a2e1SPrashanth Swaminathan
1128*1fd5a2e1SPrashanth Swaminathan default:
1129*1fd5a2e1SPrashanth Swaminathan FFI_ASSERT (0);
1130*1fd5a2e1SPrashanth Swaminathan }
1131*1fd5a2e1SPrashanth Swaminathan
1132*1fd5a2e1SPrashanth Swaminathan i++;
1133*1fd5a2e1SPrashanth Swaminathan }
1134*1fd5a2e1SPrashanth Swaminathan
1135*1fd5a2e1SPrashanth Swaminathan (*fun) (cif, rvalue, avalue, user_data);
1136*1fd5a2e1SPrashanth Swaminathan
1137*1fd5a2e1SPrashanth Swaminathan /* Tell ffi_closure_LINUX64 how to perform return type promotions. */
1138*1fd5a2e1SPrashanth Swaminathan if ((cif->flags & FLAG_RETURNS_SMST) != 0)
1139*1fd5a2e1SPrashanth Swaminathan {
1140*1fd5a2e1SPrashanth Swaminathan if ((cif->flags & (FLAG_RETURNS_FP | FLAG_RETURNS_VEC)) == 0)
1141*1fd5a2e1SPrashanth Swaminathan return FFI_V2_TYPE_SMALL_STRUCT + cif->rtype->size - 1;
1142*1fd5a2e1SPrashanth Swaminathan else if ((cif->flags & FLAG_RETURNS_VEC) != 0)
1143*1fd5a2e1SPrashanth Swaminathan return FFI_V2_TYPE_VECTOR_HOMOG;
1144*1fd5a2e1SPrashanth Swaminathan else if ((cif->flags & FLAG_RETURNS_64BITS) != 0)
1145*1fd5a2e1SPrashanth Swaminathan return FFI_V2_TYPE_DOUBLE_HOMOG;
1146*1fd5a2e1SPrashanth Swaminathan else
1147*1fd5a2e1SPrashanth Swaminathan return FFI_V2_TYPE_FLOAT_HOMOG;
1148*1fd5a2e1SPrashanth Swaminathan }
1149*1fd5a2e1SPrashanth Swaminathan if ((cif->flags & FLAG_RETURNS_VEC) != 0)
1150*1fd5a2e1SPrashanth Swaminathan return FFI_V2_TYPE_VECTOR;
1151*1fd5a2e1SPrashanth Swaminathan return cif->rtype->type;
1152*1fd5a2e1SPrashanth Swaminathan }
1153*1fd5a2e1SPrashanth Swaminathan #endif
1154