1*1fd5a2e1SPrashanth Swaminathan /* -----------------------------------------------------------------------
2*1fd5a2e1SPrashanth Swaminathan ffi.c - Copyright (c) 2011, 2013 Anthony Green
3*1fd5a2e1SPrashanth Swaminathan Copyright (c) 1996, 2003-2004, 2007-2008 Red Hat, Inc.
4*1fd5a2e1SPrashanth Swaminathan
5*1fd5a2e1SPrashanth Swaminathan SPARC Foreign Function Interface
6*1fd5a2e1SPrashanth Swaminathan
7*1fd5a2e1SPrashanth Swaminathan Permission is hereby granted, free of charge, to any person obtaining
8*1fd5a2e1SPrashanth Swaminathan a copy of this software and associated documentation files (the
9*1fd5a2e1SPrashanth Swaminathan ``Software''), to deal in the Software without restriction, including
10*1fd5a2e1SPrashanth Swaminathan without limitation the rights to use, copy, modify, merge, publish,
11*1fd5a2e1SPrashanth Swaminathan distribute, sublicense, and/or sell copies of the Software, and to
12*1fd5a2e1SPrashanth Swaminathan permit persons to whom the Software is furnished to do so, subject to
13*1fd5a2e1SPrashanth Swaminathan the following conditions:
14*1fd5a2e1SPrashanth Swaminathan
15*1fd5a2e1SPrashanth Swaminathan The above copyright notice and this permission notice shall be included
16*1fd5a2e1SPrashanth Swaminathan in all copies or substantial portions of the Software.
17*1fd5a2e1SPrashanth Swaminathan
18*1fd5a2e1SPrashanth Swaminathan THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND,
19*1fd5a2e1SPrashanth Swaminathan EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20*1fd5a2e1SPrashanth Swaminathan MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
21*1fd5a2e1SPrashanth Swaminathan NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
22*1fd5a2e1SPrashanth Swaminathan HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
23*1fd5a2e1SPrashanth Swaminathan WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24*1fd5a2e1SPrashanth Swaminathan OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
25*1fd5a2e1SPrashanth Swaminathan DEALINGS IN THE SOFTWARE.
26*1fd5a2e1SPrashanth Swaminathan ----------------------------------------------------------------------- */
27*1fd5a2e1SPrashanth Swaminathan
28*1fd5a2e1SPrashanth Swaminathan #include <ffi.h>
29*1fd5a2e1SPrashanth Swaminathan #include <ffi_common.h>
30*1fd5a2e1SPrashanth Swaminathan #include <stdlib.h>
31*1fd5a2e1SPrashanth Swaminathan #include "internal.h"
32*1fd5a2e1SPrashanth Swaminathan
33*1fd5a2e1SPrashanth Swaminathan /* Force FFI_TYPE_LONGDOUBLE to be different than FFI_TYPE_DOUBLE;
34*1fd5a2e1SPrashanth Swaminathan all further uses in this file will refer to the 128-bit type. */
35*1fd5a2e1SPrashanth Swaminathan #if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
36*1fd5a2e1SPrashanth Swaminathan # if FFI_TYPE_LONGDOUBLE != 4
37*1fd5a2e1SPrashanth Swaminathan # error FFI_TYPE_LONGDOUBLE out of date
38*1fd5a2e1SPrashanth Swaminathan # endif
39*1fd5a2e1SPrashanth Swaminathan #else
40*1fd5a2e1SPrashanth Swaminathan # undef FFI_TYPE_LONGDOUBLE
41*1fd5a2e1SPrashanth Swaminathan # define FFI_TYPE_LONGDOUBLE 4
42*1fd5a2e1SPrashanth Swaminathan #endif
43*1fd5a2e1SPrashanth Swaminathan
44*1fd5a2e1SPrashanth Swaminathan #ifdef SPARC64
45*1fd5a2e1SPrashanth Swaminathan
46*1fd5a2e1SPrashanth Swaminathan /* Flatten the contents of a structure to the parts that are passed in
47*1fd5a2e1SPrashanth Swaminathan floating point registers. The return is a bit mask wherein bit N
48*1fd5a2e1SPrashanth Swaminathan set means bytes [4*n, 4*n+3] are passed in %fN.
49*1fd5a2e1SPrashanth Swaminathan
50*1fd5a2e1SPrashanth Swaminathan We encode both the (running) size (maximum 32) and mask (maxumum 255)
51*1fd5a2e1SPrashanth Swaminathan into one integer. The size is placed in the low byte, so that align
52*1fd5a2e1SPrashanth Swaminathan and addition work correctly. The mask is placed in the second byte. */
53*1fd5a2e1SPrashanth Swaminathan
54*1fd5a2e1SPrashanth Swaminathan static int
ffi_struct_float_mask(ffi_type * outer_type,int size_mask)55*1fd5a2e1SPrashanth Swaminathan ffi_struct_float_mask (ffi_type *outer_type, int size_mask)
56*1fd5a2e1SPrashanth Swaminathan {
57*1fd5a2e1SPrashanth Swaminathan ffi_type **elts;
58*1fd5a2e1SPrashanth Swaminathan ffi_type *t;
59*1fd5a2e1SPrashanth Swaminathan
60*1fd5a2e1SPrashanth Swaminathan if (outer_type->type == FFI_TYPE_COMPLEX)
61*1fd5a2e1SPrashanth Swaminathan {
62*1fd5a2e1SPrashanth Swaminathan int m = 0, tt = outer_type->elements[0]->type;
63*1fd5a2e1SPrashanth Swaminathan size_t z = outer_type->size;
64*1fd5a2e1SPrashanth Swaminathan
65*1fd5a2e1SPrashanth Swaminathan if (tt == FFI_TYPE_FLOAT
66*1fd5a2e1SPrashanth Swaminathan || tt == FFI_TYPE_DOUBLE
67*1fd5a2e1SPrashanth Swaminathan || tt == FFI_TYPE_LONGDOUBLE)
68*1fd5a2e1SPrashanth Swaminathan m = (1 << (z / 4)) - 1;
69*1fd5a2e1SPrashanth Swaminathan return (m << 8) | z;
70*1fd5a2e1SPrashanth Swaminathan }
71*1fd5a2e1SPrashanth Swaminathan FFI_ASSERT (outer_type->type == FFI_TYPE_STRUCT);
72*1fd5a2e1SPrashanth Swaminathan
73*1fd5a2e1SPrashanth Swaminathan for (elts = outer_type->elements; (t = *elts) != NULL; elts++)
74*1fd5a2e1SPrashanth Swaminathan {
75*1fd5a2e1SPrashanth Swaminathan size_t z = t->size;
76*1fd5a2e1SPrashanth Swaminathan int o, m, tt;
77*1fd5a2e1SPrashanth Swaminathan
78*1fd5a2e1SPrashanth Swaminathan size_mask = FFI_ALIGN(size_mask, t->alignment);
79*1fd5a2e1SPrashanth Swaminathan switch (t->type)
80*1fd5a2e1SPrashanth Swaminathan {
81*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_STRUCT:
82*1fd5a2e1SPrashanth Swaminathan size_mask = ffi_struct_float_mask (t, size_mask);
83*1fd5a2e1SPrashanth Swaminathan continue;
84*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_COMPLEX:
85*1fd5a2e1SPrashanth Swaminathan tt = t->elements[0]->type;
86*1fd5a2e1SPrashanth Swaminathan if (tt != FFI_TYPE_FLOAT
87*1fd5a2e1SPrashanth Swaminathan && tt != FFI_TYPE_DOUBLE
88*1fd5a2e1SPrashanth Swaminathan && tt != FFI_TYPE_LONGDOUBLE)
89*1fd5a2e1SPrashanth Swaminathan break;
90*1fd5a2e1SPrashanth Swaminathan /* FALLTHRU */
91*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_FLOAT:
92*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_DOUBLE:
93*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_LONGDOUBLE:
94*1fd5a2e1SPrashanth Swaminathan m = (1 << (z / 4)) - 1; /* compute mask for type */
95*1fd5a2e1SPrashanth Swaminathan o = (size_mask >> 2) & 0x3f; /* extract word offset */
96*1fd5a2e1SPrashanth Swaminathan size_mask |= m << (o + 8); /* insert mask into place */
97*1fd5a2e1SPrashanth Swaminathan break;
98*1fd5a2e1SPrashanth Swaminathan }
99*1fd5a2e1SPrashanth Swaminathan size_mask += z;
100*1fd5a2e1SPrashanth Swaminathan }
101*1fd5a2e1SPrashanth Swaminathan
102*1fd5a2e1SPrashanth Swaminathan size_mask = FFI_ALIGN(size_mask, outer_type->alignment);
103*1fd5a2e1SPrashanth Swaminathan FFI_ASSERT ((size_mask & 0xff) == outer_type->size);
104*1fd5a2e1SPrashanth Swaminathan
105*1fd5a2e1SPrashanth Swaminathan return size_mask;
106*1fd5a2e1SPrashanth Swaminathan }
107*1fd5a2e1SPrashanth Swaminathan
108*1fd5a2e1SPrashanth Swaminathan /* Merge floating point data into integer data. If the structure is
109*1fd5a2e1SPrashanth Swaminathan entirely floating point, simply return a pointer to the fp data. */
110*1fd5a2e1SPrashanth Swaminathan
111*1fd5a2e1SPrashanth Swaminathan static void *
ffi_struct_float_merge(int size_mask,void * vi,void * vf)112*1fd5a2e1SPrashanth Swaminathan ffi_struct_float_merge (int size_mask, void *vi, void *vf)
113*1fd5a2e1SPrashanth Swaminathan {
114*1fd5a2e1SPrashanth Swaminathan int size = size_mask & 0xff;
115*1fd5a2e1SPrashanth Swaminathan int mask = size_mask >> 8;
116*1fd5a2e1SPrashanth Swaminathan int n = size >> 2;
117*1fd5a2e1SPrashanth Swaminathan
118*1fd5a2e1SPrashanth Swaminathan if (mask == 0)
119*1fd5a2e1SPrashanth Swaminathan return vi;
120*1fd5a2e1SPrashanth Swaminathan else if (mask == (1 << n) - 1)
121*1fd5a2e1SPrashanth Swaminathan return vf;
122*1fd5a2e1SPrashanth Swaminathan else
123*1fd5a2e1SPrashanth Swaminathan {
124*1fd5a2e1SPrashanth Swaminathan unsigned int *wi = vi, *wf = vf;
125*1fd5a2e1SPrashanth Swaminathan int i;
126*1fd5a2e1SPrashanth Swaminathan
127*1fd5a2e1SPrashanth Swaminathan for (i = 0; i < n; ++i)
128*1fd5a2e1SPrashanth Swaminathan if ((mask >> i) & 1)
129*1fd5a2e1SPrashanth Swaminathan wi[i] = wf[i];
130*1fd5a2e1SPrashanth Swaminathan
131*1fd5a2e1SPrashanth Swaminathan return vi;
132*1fd5a2e1SPrashanth Swaminathan }
133*1fd5a2e1SPrashanth Swaminathan }
134*1fd5a2e1SPrashanth Swaminathan
135*1fd5a2e1SPrashanth Swaminathan /* Similar, but place the data into VD in the end. */
136*1fd5a2e1SPrashanth Swaminathan
137*1fd5a2e1SPrashanth Swaminathan void FFI_HIDDEN
ffi_struct_float_copy(int size_mask,void * vd,void * vi,void * vf)138*1fd5a2e1SPrashanth Swaminathan ffi_struct_float_copy (int size_mask, void *vd, void *vi, void *vf)
139*1fd5a2e1SPrashanth Swaminathan {
140*1fd5a2e1SPrashanth Swaminathan int size = size_mask & 0xff;
141*1fd5a2e1SPrashanth Swaminathan int mask = size_mask >> 8;
142*1fd5a2e1SPrashanth Swaminathan int n = size >> 2;
143*1fd5a2e1SPrashanth Swaminathan
144*1fd5a2e1SPrashanth Swaminathan if (mask == 0)
145*1fd5a2e1SPrashanth Swaminathan ;
146*1fd5a2e1SPrashanth Swaminathan else if (mask == (1 << n) - 1)
147*1fd5a2e1SPrashanth Swaminathan vi = vf;
148*1fd5a2e1SPrashanth Swaminathan else
149*1fd5a2e1SPrashanth Swaminathan {
150*1fd5a2e1SPrashanth Swaminathan unsigned int *wd = vd, *wi = vi, *wf = vf;
151*1fd5a2e1SPrashanth Swaminathan int i;
152*1fd5a2e1SPrashanth Swaminathan
153*1fd5a2e1SPrashanth Swaminathan for (i = 0; i < n; ++i)
154*1fd5a2e1SPrashanth Swaminathan wd[i] = ((mask >> i) & 1 ? wf : wi)[i];
155*1fd5a2e1SPrashanth Swaminathan return;
156*1fd5a2e1SPrashanth Swaminathan }
157*1fd5a2e1SPrashanth Swaminathan memcpy (vd, vi, size);
158*1fd5a2e1SPrashanth Swaminathan }
159*1fd5a2e1SPrashanth Swaminathan
160*1fd5a2e1SPrashanth Swaminathan /* Perform machine dependent cif processing */
161*1fd5a2e1SPrashanth Swaminathan
162*1fd5a2e1SPrashanth Swaminathan static ffi_status
ffi_prep_cif_machdep_core(ffi_cif * cif)163*1fd5a2e1SPrashanth Swaminathan ffi_prep_cif_machdep_core(ffi_cif *cif)
164*1fd5a2e1SPrashanth Swaminathan {
165*1fd5a2e1SPrashanth Swaminathan ffi_type *rtype = cif->rtype;
166*1fd5a2e1SPrashanth Swaminathan int rtt = rtype->type;
167*1fd5a2e1SPrashanth Swaminathan size_t bytes = 0;
168*1fd5a2e1SPrashanth Swaminathan int i, n, flags;
169*1fd5a2e1SPrashanth Swaminathan
170*1fd5a2e1SPrashanth Swaminathan /* Set the return type flag */
171*1fd5a2e1SPrashanth Swaminathan switch (rtt)
172*1fd5a2e1SPrashanth Swaminathan {
173*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_VOID:
174*1fd5a2e1SPrashanth Swaminathan flags = SPARC_RET_VOID;
175*1fd5a2e1SPrashanth Swaminathan break;
176*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_FLOAT:
177*1fd5a2e1SPrashanth Swaminathan flags = SPARC_RET_F_1;
178*1fd5a2e1SPrashanth Swaminathan break;
179*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_DOUBLE:
180*1fd5a2e1SPrashanth Swaminathan flags = SPARC_RET_F_2;
181*1fd5a2e1SPrashanth Swaminathan break;
182*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_LONGDOUBLE:
183*1fd5a2e1SPrashanth Swaminathan flags = SPARC_RET_F_4;
184*1fd5a2e1SPrashanth Swaminathan break;
185*1fd5a2e1SPrashanth Swaminathan
186*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_COMPLEX:
187*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_STRUCT:
188*1fd5a2e1SPrashanth Swaminathan if (rtype->size > 32)
189*1fd5a2e1SPrashanth Swaminathan {
190*1fd5a2e1SPrashanth Swaminathan flags = SPARC_RET_VOID | SPARC_FLAG_RET_IN_MEM;
191*1fd5a2e1SPrashanth Swaminathan bytes = 8;
192*1fd5a2e1SPrashanth Swaminathan }
193*1fd5a2e1SPrashanth Swaminathan else
194*1fd5a2e1SPrashanth Swaminathan {
195*1fd5a2e1SPrashanth Swaminathan int size_mask = ffi_struct_float_mask (rtype, 0);
196*1fd5a2e1SPrashanth Swaminathan int word_size = (size_mask >> 2) & 0x3f;
197*1fd5a2e1SPrashanth Swaminathan int all_mask = (1 << word_size) - 1;
198*1fd5a2e1SPrashanth Swaminathan int fp_mask = size_mask >> 8;
199*1fd5a2e1SPrashanth Swaminathan
200*1fd5a2e1SPrashanth Swaminathan flags = (size_mask << SPARC_SIZEMASK_SHIFT) | SPARC_RET_STRUCT;
201*1fd5a2e1SPrashanth Swaminathan
202*1fd5a2e1SPrashanth Swaminathan /* For special cases of all-int or all-fp, we can return
203*1fd5a2e1SPrashanth Swaminathan the value directly without popping through a struct copy. */
204*1fd5a2e1SPrashanth Swaminathan if (fp_mask == 0)
205*1fd5a2e1SPrashanth Swaminathan {
206*1fd5a2e1SPrashanth Swaminathan if (rtype->alignment >= 8)
207*1fd5a2e1SPrashanth Swaminathan {
208*1fd5a2e1SPrashanth Swaminathan if (rtype->size == 8)
209*1fd5a2e1SPrashanth Swaminathan flags = SPARC_RET_INT64;
210*1fd5a2e1SPrashanth Swaminathan else if (rtype->size == 16)
211*1fd5a2e1SPrashanth Swaminathan flags = SPARC_RET_INT128;
212*1fd5a2e1SPrashanth Swaminathan }
213*1fd5a2e1SPrashanth Swaminathan }
214*1fd5a2e1SPrashanth Swaminathan else if (fp_mask == all_mask)
215*1fd5a2e1SPrashanth Swaminathan switch (word_size)
216*1fd5a2e1SPrashanth Swaminathan {
217*1fd5a2e1SPrashanth Swaminathan case 1: flags = SPARC_RET_F_1; break;
218*1fd5a2e1SPrashanth Swaminathan case 2: flags = SPARC_RET_F_2; break;
219*1fd5a2e1SPrashanth Swaminathan case 3: flags = SP_V9_RET_F_3; break;
220*1fd5a2e1SPrashanth Swaminathan case 4: flags = SPARC_RET_F_4; break;
221*1fd5a2e1SPrashanth Swaminathan /* 5 word structures skipped; handled via RET_STRUCT. */
222*1fd5a2e1SPrashanth Swaminathan case 6: flags = SPARC_RET_F_6; break;
223*1fd5a2e1SPrashanth Swaminathan /* 7 word structures skipped; handled via RET_STRUCT. */
224*1fd5a2e1SPrashanth Swaminathan case 8: flags = SPARC_RET_F_8; break;
225*1fd5a2e1SPrashanth Swaminathan }
226*1fd5a2e1SPrashanth Swaminathan }
227*1fd5a2e1SPrashanth Swaminathan break;
228*1fd5a2e1SPrashanth Swaminathan
229*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_SINT8:
230*1fd5a2e1SPrashanth Swaminathan flags = SPARC_RET_SINT8;
231*1fd5a2e1SPrashanth Swaminathan break;
232*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_UINT8:
233*1fd5a2e1SPrashanth Swaminathan flags = SPARC_RET_UINT8;
234*1fd5a2e1SPrashanth Swaminathan break;
235*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_SINT16:
236*1fd5a2e1SPrashanth Swaminathan flags = SPARC_RET_SINT16;
237*1fd5a2e1SPrashanth Swaminathan break;
238*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_UINT16:
239*1fd5a2e1SPrashanth Swaminathan flags = SPARC_RET_UINT16;
240*1fd5a2e1SPrashanth Swaminathan break;
241*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_INT:
242*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_SINT32:
243*1fd5a2e1SPrashanth Swaminathan flags = SP_V9_RET_SINT32;
244*1fd5a2e1SPrashanth Swaminathan break;
245*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_UINT32:
246*1fd5a2e1SPrashanth Swaminathan flags = SPARC_RET_UINT32;
247*1fd5a2e1SPrashanth Swaminathan break;
248*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_SINT64:
249*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_UINT64:
250*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_POINTER:
251*1fd5a2e1SPrashanth Swaminathan flags = SPARC_RET_INT64;
252*1fd5a2e1SPrashanth Swaminathan break;
253*1fd5a2e1SPrashanth Swaminathan
254*1fd5a2e1SPrashanth Swaminathan default:
255*1fd5a2e1SPrashanth Swaminathan abort();
256*1fd5a2e1SPrashanth Swaminathan }
257*1fd5a2e1SPrashanth Swaminathan
258*1fd5a2e1SPrashanth Swaminathan bytes = 0;
259*1fd5a2e1SPrashanth Swaminathan for (i = 0, n = cif->nargs; i < n; ++i)
260*1fd5a2e1SPrashanth Swaminathan {
261*1fd5a2e1SPrashanth Swaminathan ffi_type *ty = cif->arg_types[i];
262*1fd5a2e1SPrashanth Swaminathan size_t z = ty->size;
263*1fd5a2e1SPrashanth Swaminathan size_t a = ty->alignment;
264*1fd5a2e1SPrashanth Swaminathan
265*1fd5a2e1SPrashanth Swaminathan switch (ty->type)
266*1fd5a2e1SPrashanth Swaminathan {
267*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_COMPLEX:
268*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_STRUCT:
269*1fd5a2e1SPrashanth Swaminathan /* Large structs passed by reference. */
270*1fd5a2e1SPrashanth Swaminathan if (z > 16)
271*1fd5a2e1SPrashanth Swaminathan {
272*1fd5a2e1SPrashanth Swaminathan a = z = 8;
273*1fd5a2e1SPrashanth Swaminathan break;
274*1fd5a2e1SPrashanth Swaminathan }
275*1fd5a2e1SPrashanth Swaminathan /* Small structs may be passed in integer or fp regs or both. */
276*1fd5a2e1SPrashanth Swaminathan if (bytes >= 16*8)
277*1fd5a2e1SPrashanth Swaminathan break;
278*1fd5a2e1SPrashanth Swaminathan if ((ffi_struct_float_mask (ty, 0) & 0xff00) == 0)
279*1fd5a2e1SPrashanth Swaminathan break;
280*1fd5a2e1SPrashanth Swaminathan /* FALLTHRU */
281*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_FLOAT:
282*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_DOUBLE:
283*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_LONGDOUBLE:
284*1fd5a2e1SPrashanth Swaminathan flags |= SPARC_FLAG_FP_ARGS;
285*1fd5a2e1SPrashanth Swaminathan break;
286*1fd5a2e1SPrashanth Swaminathan }
287*1fd5a2e1SPrashanth Swaminathan bytes = FFI_ALIGN(bytes, a);
288*1fd5a2e1SPrashanth Swaminathan bytes += FFI_ALIGN(z, 8);
289*1fd5a2e1SPrashanth Swaminathan }
290*1fd5a2e1SPrashanth Swaminathan
291*1fd5a2e1SPrashanth Swaminathan /* Sparc call frames require that space is allocated for 6 args,
292*1fd5a2e1SPrashanth Swaminathan even if they aren't used. Make that space if necessary. */
293*1fd5a2e1SPrashanth Swaminathan if (bytes < 6 * 8)
294*1fd5a2e1SPrashanth Swaminathan bytes = 6 * 8;
295*1fd5a2e1SPrashanth Swaminathan
296*1fd5a2e1SPrashanth Swaminathan /* The stack must be 2 word aligned, so round bytes up appropriately. */
297*1fd5a2e1SPrashanth Swaminathan bytes = FFI_ALIGN(bytes, 16);
298*1fd5a2e1SPrashanth Swaminathan
299*1fd5a2e1SPrashanth Swaminathan /* Include the call frame to prep_args. */
300*1fd5a2e1SPrashanth Swaminathan bytes += 8*16 + 8*8;
301*1fd5a2e1SPrashanth Swaminathan
302*1fd5a2e1SPrashanth Swaminathan cif->bytes = bytes;
303*1fd5a2e1SPrashanth Swaminathan cif->flags = flags;
304*1fd5a2e1SPrashanth Swaminathan return FFI_OK;
305*1fd5a2e1SPrashanth Swaminathan }
306*1fd5a2e1SPrashanth Swaminathan
307*1fd5a2e1SPrashanth Swaminathan ffi_status FFI_HIDDEN
ffi_prep_cif_machdep(ffi_cif * cif)308*1fd5a2e1SPrashanth Swaminathan ffi_prep_cif_machdep(ffi_cif *cif)
309*1fd5a2e1SPrashanth Swaminathan {
310*1fd5a2e1SPrashanth Swaminathan cif->nfixedargs = cif->nargs;
311*1fd5a2e1SPrashanth Swaminathan return ffi_prep_cif_machdep_core(cif);
312*1fd5a2e1SPrashanth Swaminathan }
313*1fd5a2e1SPrashanth Swaminathan
314*1fd5a2e1SPrashanth Swaminathan ffi_status FFI_HIDDEN
ffi_prep_cif_machdep_var(ffi_cif * cif,unsigned nfixedargs,unsigned ntotalargs)315*1fd5a2e1SPrashanth Swaminathan ffi_prep_cif_machdep_var(ffi_cif *cif, unsigned nfixedargs, unsigned ntotalargs)
316*1fd5a2e1SPrashanth Swaminathan {
317*1fd5a2e1SPrashanth Swaminathan cif->nfixedargs = nfixedargs;
318*1fd5a2e1SPrashanth Swaminathan return ffi_prep_cif_machdep_core(cif);
319*1fd5a2e1SPrashanth Swaminathan }
320*1fd5a2e1SPrashanth Swaminathan
321*1fd5a2e1SPrashanth Swaminathan extern void ffi_call_v9(ffi_cif *cif, void (*fn)(void), void *rvalue,
322*1fd5a2e1SPrashanth Swaminathan void **avalue, size_t bytes, void *closure) FFI_HIDDEN;
323*1fd5a2e1SPrashanth Swaminathan
324*1fd5a2e1SPrashanth Swaminathan /* ffi_prep_args is called by the assembly routine once stack space
325*1fd5a2e1SPrashanth Swaminathan has been allocated for the function's arguments */
326*1fd5a2e1SPrashanth Swaminathan
327*1fd5a2e1SPrashanth Swaminathan int FFI_HIDDEN
ffi_prep_args_v9(ffi_cif * cif,unsigned long * argp,void * rvalue,void ** avalue)328*1fd5a2e1SPrashanth Swaminathan ffi_prep_args_v9(ffi_cif *cif, unsigned long *argp, void *rvalue, void **avalue)
329*1fd5a2e1SPrashanth Swaminathan {
330*1fd5a2e1SPrashanth Swaminathan ffi_type **p_arg;
331*1fd5a2e1SPrashanth Swaminathan int flags = cif->flags;
332*1fd5a2e1SPrashanth Swaminathan int i, nargs;
333*1fd5a2e1SPrashanth Swaminathan
334*1fd5a2e1SPrashanth Swaminathan if (rvalue == NULL)
335*1fd5a2e1SPrashanth Swaminathan {
336*1fd5a2e1SPrashanth Swaminathan if (flags & SPARC_FLAG_RET_IN_MEM)
337*1fd5a2e1SPrashanth Swaminathan {
338*1fd5a2e1SPrashanth Swaminathan /* Since we pass the pointer to the callee, we need a value.
339*1fd5a2e1SPrashanth Swaminathan We allowed for this space in ffi_call, before ffi_call_v8
340*1fd5a2e1SPrashanth Swaminathan alloca'd the space. */
341*1fd5a2e1SPrashanth Swaminathan rvalue = (char *)argp + cif->bytes;
342*1fd5a2e1SPrashanth Swaminathan }
343*1fd5a2e1SPrashanth Swaminathan else
344*1fd5a2e1SPrashanth Swaminathan {
345*1fd5a2e1SPrashanth Swaminathan /* Otherwise, we can ignore the return value. */
346*1fd5a2e1SPrashanth Swaminathan flags = SPARC_RET_VOID;
347*1fd5a2e1SPrashanth Swaminathan }
348*1fd5a2e1SPrashanth Swaminathan }
349*1fd5a2e1SPrashanth Swaminathan
350*1fd5a2e1SPrashanth Swaminathan #ifdef USING_PURIFY
351*1fd5a2e1SPrashanth Swaminathan /* Purify will probably complain in our assembly routine,
352*1fd5a2e1SPrashanth Swaminathan unless we zero out this memory. */
353*1fd5a2e1SPrashanth Swaminathan memset(argp, 0, 6*8);
354*1fd5a2e1SPrashanth Swaminathan #endif
355*1fd5a2e1SPrashanth Swaminathan
356*1fd5a2e1SPrashanth Swaminathan if (flags & SPARC_FLAG_RET_IN_MEM)
357*1fd5a2e1SPrashanth Swaminathan *argp++ = (unsigned long)rvalue;
358*1fd5a2e1SPrashanth Swaminathan
359*1fd5a2e1SPrashanth Swaminathan p_arg = cif->arg_types;
360*1fd5a2e1SPrashanth Swaminathan for (i = 0, nargs = cif->nargs; i < nargs; i++)
361*1fd5a2e1SPrashanth Swaminathan {
362*1fd5a2e1SPrashanth Swaminathan ffi_type *ty = p_arg[i];
363*1fd5a2e1SPrashanth Swaminathan void *a = avalue[i];
364*1fd5a2e1SPrashanth Swaminathan size_t z;
365*1fd5a2e1SPrashanth Swaminathan
366*1fd5a2e1SPrashanth Swaminathan switch (ty->type)
367*1fd5a2e1SPrashanth Swaminathan {
368*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_SINT8:
369*1fd5a2e1SPrashanth Swaminathan *argp++ = *(SINT8 *)a;
370*1fd5a2e1SPrashanth Swaminathan break;
371*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_UINT8:
372*1fd5a2e1SPrashanth Swaminathan *argp++ = *(UINT8 *)a;
373*1fd5a2e1SPrashanth Swaminathan break;
374*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_SINT16:
375*1fd5a2e1SPrashanth Swaminathan *argp++ = *(SINT16 *)a;
376*1fd5a2e1SPrashanth Swaminathan break;
377*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_UINT16:
378*1fd5a2e1SPrashanth Swaminathan *argp++ = *(UINT16 *)a;
379*1fd5a2e1SPrashanth Swaminathan break;
380*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_INT:
381*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_SINT32:
382*1fd5a2e1SPrashanth Swaminathan *argp++ = *(SINT32 *)a;
383*1fd5a2e1SPrashanth Swaminathan break;
384*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_UINT32:
385*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_FLOAT:
386*1fd5a2e1SPrashanth Swaminathan *argp++ = *(UINT32 *)a;
387*1fd5a2e1SPrashanth Swaminathan break;
388*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_SINT64:
389*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_UINT64:
390*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_POINTER:
391*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_DOUBLE:
392*1fd5a2e1SPrashanth Swaminathan *argp++ = *(UINT64 *)a;
393*1fd5a2e1SPrashanth Swaminathan break;
394*1fd5a2e1SPrashanth Swaminathan
395*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_LONGDOUBLE:
396*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_COMPLEX:
397*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_STRUCT:
398*1fd5a2e1SPrashanth Swaminathan z = ty->size;
399*1fd5a2e1SPrashanth Swaminathan if (z > 16)
400*1fd5a2e1SPrashanth Swaminathan {
401*1fd5a2e1SPrashanth Swaminathan /* For structures larger than 16 bytes we pass reference. */
402*1fd5a2e1SPrashanth Swaminathan *argp++ = (unsigned long)a;
403*1fd5a2e1SPrashanth Swaminathan break;
404*1fd5a2e1SPrashanth Swaminathan }
405*1fd5a2e1SPrashanth Swaminathan if (((unsigned long)argp & 15) && ty->alignment > 8)
406*1fd5a2e1SPrashanth Swaminathan argp++;
407*1fd5a2e1SPrashanth Swaminathan memcpy(argp, a, z);
408*1fd5a2e1SPrashanth Swaminathan argp += FFI_ALIGN(z, 8) / 8;
409*1fd5a2e1SPrashanth Swaminathan break;
410*1fd5a2e1SPrashanth Swaminathan
411*1fd5a2e1SPrashanth Swaminathan default:
412*1fd5a2e1SPrashanth Swaminathan abort();
413*1fd5a2e1SPrashanth Swaminathan }
414*1fd5a2e1SPrashanth Swaminathan }
415*1fd5a2e1SPrashanth Swaminathan
416*1fd5a2e1SPrashanth Swaminathan return flags;
417*1fd5a2e1SPrashanth Swaminathan }
418*1fd5a2e1SPrashanth Swaminathan
419*1fd5a2e1SPrashanth Swaminathan static void
ffi_call_int(ffi_cif * cif,void (* fn)(void),void * rvalue,void ** avalue,void * closure)420*1fd5a2e1SPrashanth Swaminathan ffi_call_int(ffi_cif *cif, void (*fn)(void), void *rvalue,
421*1fd5a2e1SPrashanth Swaminathan void **avalue, void *closure)
422*1fd5a2e1SPrashanth Swaminathan {
423*1fd5a2e1SPrashanth Swaminathan size_t bytes = cif->bytes;
424*1fd5a2e1SPrashanth Swaminathan
425*1fd5a2e1SPrashanth Swaminathan FFI_ASSERT (cif->abi == FFI_V9);
426*1fd5a2e1SPrashanth Swaminathan
427*1fd5a2e1SPrashanth Swaminathan if (rvalue == NULL && (cif->flags & SPARC_FLAG_RET_IN_MEM))
428*1fd5a2e1SPrashanth Swaminathan bytes += FFI_ALIGN (cif->rtype->size, 16);
429*1fd5a2e1SPrashanth Swaminathan
430*1fd5a2e1SPrashanth Swaminathan ffi_call_v9(cif, fn, rvalue, avalue, -bytes, closure);
431*1fd5a2e1SPrashanth Swaminathan }
432*1fd5a2e1SPrashanth Swaminathan
433*1fd5a2e1SPrashanth Swaminathan void
ffi_call(ffi_cif * cif,void (* fn)(void),void * rvalue,void ** avalue)434*1fd5a2e1SPrashanth Swaminathan ffi_call(ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue)
435*1fd5a2e1SPrashanth Swaminathan {
436*1fd5a2e1SPrashanth Swaminathan ffi_call_int(cif, fn, rvalue, avalue, NULL);
437*1fd5a2e1SPrashanth Swaminathan }
438*1fd5a2e1SPrashanth Swaminathan
439*1fd5a2e1SPrashanth Swaminathan void
ffi_call_go(ffi_cif * cif,void (* fn)(void),void * rvalue,void ** avalue,void * closure)440*1fd5a2e1SPrashanth Swaminathan ffi_call_go(ffi_cif *cif, void (*fn)(void), void *rvalue,
441*1fd5a2e1SPrashanth Swaminathan void **avalue, void *closure)
442*1fd5a2e1SPrashanth Swaminathan {
443*1fd5a2e1SPrashanth Swaminathan ffi_call_int(cif, fn, rvalue, avalue, closure);
444*1fd5a2e1SPrashanth Swaminathan }
445*1fd5a2e1SPrashanth Swaminathan
446*1fd5a2e1SPrashanth Swaminathan #ifdef __GNUC__
447*1fd5a2e1SPrashanth Swaminathan static inline void
ffi_flush_icache(void * p)448*1fd5a2e1SPrashanth Swaminathan ffi_flush_icache (void *p)
449*1fd5a2e1SPrashanth Swaminathan {
450*1fd5a2e1SPrashanth Swaminathan asm volatile ("flush %0; flush %0+8" : : "r" (p) : "memory");
451*1fd5a2e1SPrashanth Swaminathan }
452*1fd5a2e1SPrashanth Swaminathan #else
453*1fd5a2e1SPrashanth Swaminathan extern void ffi_flush_icache (void *) FFI_HIDDEN;
454*1fd5a2e1SPrashanth Swaminathan #endif
455*1fd5a2e1SPrashanth Swaminathan
456*1fd5a2e1SPrashanth Swaminathan extern void ffi_closure_v9(void) FFI_HIDDEN;
457*1fd5a2e1SPrashanth Swaminathan extern void ffi_go_closure_v9(void) FFI_HIDDEN;
458*1fd5a2e1SPrashanth Swaminathan
459*1fd5a2e1SPrashanth Swaminathan ffi_status
ffi_prep_closure_loc(ffi_closure * closure,ffi_cif * cif,void (* fun)(ffi_cif *,void *,void **,void *),void * user_data,void * codeloc)460*1fd5a2e1SPrashanth Swaminathan ffi_prep_closure_loc (ffi_closure* closure,
461*1fd5a2e1SPrashanth Swaminathan ffi_cif* cif,
462*1fd5a2e1SPrashanth Swaminathan void (*fun)(ffi_cif*, void*, void**, void*),
463*1fd5a2e1SPrashanth Swaminathan void *user_data,
464*1fd5a2e1SPrashanth Swaminathan void *codeloc)
465*1fd5a2e1SPrashanth Swaminathan {
466*1fd5a2e1SPrashanth Swaminathan unsigned int *tramp = (unsigned int *) &closure->tramp[0];
467*1fd5a2e1SPrashanth Swaminathan unsigned long fn;
468*1fd5a2e1SPrashanth Swaminathan
469*1fd5a2e1SPrashanth Swaminathan if (cif->abi != FFI_V9)
470*1fd5a2e1SPrashanth Swaminathan return FFI_BAD_ABI;
471*1fd5a2e1SPrashanth Swaminathan
472*1fd5a2e1SPrashanth Swaminathan /* Trampoline address is equal to the closure address. We take advantage
473*1fd5a2e1SPrashanth Swaminathan of that to reduce the trampoline size by 8 bytes. */
474*1fd5a2e1SPrashanth Swaminathan fn = (unsigned long) ffi_closure_v9;
475*1fd5a2e1SPrashanth Swaminathan tramp[0] = 0x83414000; /* rd %pc, %g1 */
476*1fd5a2e1SPrashanth Swaminathan tramp[1] = 0xca586010; /* ldx [%g1+16], %g5 */
477*1fd5a2e1SPrashanth Swaminathan tramp[2] = 0x81c14000; /* jmp %g5 */
478*1fd5a2e1SPrashanth Swaminathan tramp[3] = 0x01000000; /* nop */
479*1fd5a2e1SPrashanth Swaminathan *((unsigned long *) &tramp[4]) = fn;
480*1fd5a2e1SPrashanth Swaminathan
481*1fd5a2e1SPrashanth Swaminathan closure->cif = cif;
482*1fd5a2e1SPrashanth Swaminathan closure->fun = fun;
483*1fd5a2e1SPrashanth Swaminathan closure->user_data = user_data;
484*1fd5a2e1SPrashanth Swaminathan
485*1fd5a2e1SPrashanth Swaminathan ffi_flush_icache (closure);
486*1fd5a2e1SPrashanth Swaminathan
487*1fd5a2e1SPrashanth Swaminathan return FFI_OK;
488*1fd5a2e1SPrashanth Swaminathan }
489*1fd5a2e1SPrashanth Swaminathan
490*1fd5a2e1SPrashanth Swaminathan ffi_status
ffi_prep_go_closure(ffi_go_closure * closure,ffi_cif * cif,void (* fun)(ffi_cif *,void *,void **,void *))491*1fd5a2e1SPrashanth Swaminathan ffi_prep_go_closure (ffi_go_closure* closure, ffi_cif* cif,
492*1fd5a2e1SPrashanth Swaminathan void (*fun)(ffi_cif*, void*, void**, void*))
493*1fd5a2e1SPrashanth Swaminathan {
494*1fd5a2e1SPrashanth Swaminathan if (cif->abi != FFI_V9)
495*1fd5a2e1SPrashanth Swaminathan return FFI_BAD_ABI;
496*1fd5a2e1SPrashanth Swaminathan
497*1fd5a2e1SPrashanth Swaminathan closure->tramp = ffi_go_closure_v9;
498*1fd5a2e1SPrashanth Swaminathan closure->cif = cif;
499*1fd5a2e1SPrashanth Swaminathan closure->fun = fun;
500*1fd5a2e1SPrashanth Swaminathan
501*1fd5a2e1SPrashanth Swaminathan return FFI_OK;
502*1fd5a2e1SPrashanth Swaminathan }
503*1fd5a2e1SPrashanth Swaminathan
504*1fd5a2e1SPrashanth Swaminathan int FFI_HIDDEN
ffi_closure_sparc_inner_v9(ffi_cif * cif,void (* fun)(ffi_cif *,void *,void **,void *),void * user_data,void * rvalue,unsigned long * gpr,unsigned long * fpr)505*1fd5a2e1SPrashanth Swaminathan ffi_closure_sparc_inner_v9(ffi_cif *cif,
506*1fd5a2e1SPrashanth Swaminathan void (*fun)(ffi_cif*, void*, void**, void*),
507*1fd5a2e1SPrashanth Swaminathan void *user_data, void *rvalue,
508*1fd5a2e1SPrashanth Swaminathan unsigned long *gpr, unsigned long *fpr)
509*1fd5a2e1SPrashanth Swaminathan {
510*1fd5a2e1SPrashanth Swaminathan ffi_type **arg_types;
511*1fd5a2e1SPrashanth Swaminathan void **avalue;
512*1fd5a2e1SPrashanth Swaminathan int i, argn, argx, nargs, flags, nfixedargs;
513*1fd5a2e1SPrashanth Swaminathan
514*1fd5a2e1SPrashanth Swaminathan arg_types = cif->arg_types;
515*1fd5a2e1SPrashanth Swaminathan nargs = cif->nargs;
516*1fd5a2e1SPrashanth Swaminathan flags = cif->flags;
517*1fd5a2e1SPrashanth Swaminathan nfixedargs = cif->nfixedargs;
518*1fd5a2e1SPrashanth Swaminathan
519*1fd5a2e1SPrashanth Swaminathan avalue = alloca(nargs * sizeof(void *));
520*1fd5a2e1SPrashanth Swaminathan
521*1fd5a2e1SPrashanth Swaminathan /* Copy the caller's structure return address so that the closure
522*1fd5a2e1SPrashanth Swaminathan returns the data directly to the caller. */
523*1fd5a2e1SPrashanth Swaminathan if (flags & SPARC_FLAG_RET_IN_MEM)
524*1fd5a2e1SPrashanth Swaminathan {
525*1fd5a2e1SPrashanth Swaminathan rvalue = (void *) gpr[0];
526*1fd5a2e1SPrashanth Swaminathan /* Skip the structure return address. */
527*1fd5a2e1SPrashanth Swaminathan argn = 1;
528*1fd5a2e1SPrashanth Swaminathan }
529*1fd5a2e1SPrashanth Swaminathan else
530*1fd5a2e1SPrashanth Swaminathan argn = 0;
531*1fd5a2e1SPrashanth Swaminathan
532*1fd5a2e1SPrashanth Swaminathan /* Grab the addresses of the arguments from the stack frame. */
533*1fd5a2e1SPrashanth Swaminathan for (i = 0; i < nargs; i++, argn = argx)
534*1fd5a2e1SPrashanth Swaminathan {
535*1fd5a2e1SPrashanth Swaminathan int named = i < nfixedargs;
536*1fd5a2e1SPrashanth Swaminathan ffi_type *ty = arg_types[i];
537*1fd5a2e1SPrashanth Swaminathan void *a = &gpr[argn];
538*1fd5a2e1SPrashanth Swaminathan size_t z;
539*1fd5a2e1SPrashanth Swaminathan
540*1fd5a2e1SPrashanth Swaminathan argx = argn + 1;
541*1fd5a2e1SPrashanth Swaminathan switch (ty->type)
542*1fd5a2e1SPrashanth Swaminathan {
543*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_COMPLEX:
544*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_STRUCT:
545*1fd5a2e1SPrashanth Swaminathan z = ty->size;
546*1fd5a2e1SPrashanth Swaminathan if (z > 16)
547*1fd5a2e1SPrashanth Swaminathan a = *(void **)a;
548*1fd5a2e1SPrashanth Swaminathan else
549*1fd5a2e1SPrashanth Swaminathan {
550*1fd5a2e1SPrashanth Swaminathan argx = argn + FFI_ALIGN (z, 8) / 8;
551*1fd5a2e1SPrashanth Swaminathan if (named && argn < 16)
552*1fd5a2e1SPrashanth Swaminathan {
553*1fd5a2e1SPrashanth Swaminathan int size_mask = ffi_struct_float_mask (ty, 0);
554*1fd5a2e1SPrashanth Swaminathan int argn_mask = (0xffff00 >> argn) & 0xff00;
555*1fd5a2e1SPrashanth Swaminathan
556*1fd5a2e1SPrashanth Swaminathan /* Eliminate fp registers off the end. */
557*1fd5a2e1SPrashanth Swaminathan size_mask = (size_mask & 0xff) | (size_mask & argn_mask);
558*1fd5a2e1SPrashanth Swaminathan a = ffi_struct_float_merge (size_mask, gpr+argn, fpr+argn);
559*1fd5a2e1SPrashanth Swaminathan }
560*1fd5a2e1SPrashanth Swaminathan }
561*1fd5a2e1SPrashanth Swaminathan break;
562*1fd5a2e1SPrashanth Swaminathan
563*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_LONGDOUBLE:
564*1fd5a2e1SPrashanth Swaminathan argn = FFI_ALIGN (argn, 2);
565*1fd5a2e1SPrashanth Swaminathan a = (named && argn < 16 ? fpr : gpr) + argn;
566*1fd5a2e1SPrashanth Swaminathan argx = argn + 2;
567*1fd5a2e1SPrashanth Swaminathan break;
568*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_DOUBLE:
569*1fd5a2e1SPrashanth Swaminathan if (named && argn < 16)
570*1fd5a2e1SPrashanth Swaminathan a = fpr + argn;
571*1fd5a2e1SPrashanth Swaminathan break;
572*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_FLOAT:
573*1fd5a2e1SPrashanth Swaminathan if (named && argn < 16)
574*1fd5a2e1SPrashanth Swaminathan a = fpr + argn;
575*1fd5a2e1SPrashanth Swaminathan a += 4;
576*1fd5a2e1SPrashanth Swaminathan break;
577*1fd5a2e1SPrashanth Swaminathan
578*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_UINT64:
579*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_SINT64:
580*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_POINTER:
581*1fd5a2e1SPrashanth Swaminathan break;
582*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_INT:
583*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_UINT32:
584*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_SINT32:
585*1fd5a2e1SPrashanth Swaminathan a += 4;
586*1fd5a2e1SPrashanth Swaminathan break;
587*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_UINT16:
588*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_SINT16:
589*1fd5a2e1SPrashanth Swaminathan a += 6;
590*1fd5a2e1SPrashanth Swaminathan break;
591*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_UINT8:
592*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_SINT8:
593*1fd5a2e1SPrashanth Swaminathan a += 7;
594*1fd5a2e1SPrashanth Swaminathan break;
595*1fd5a2e1SPrashanth Swaminathan
596*1fd5a2e1SPrashanth Swaminathan default:
597*1fd5a2e1SPrashanth Swaminathan abort();
598*1fd5a2e1SPrashanth Swaminathan }
599*1fd5a2e1SPrashanth Swaminathan avalue[i] = a;
600*1fd5a2e1SPrashanth Swaminathan }
601*1fd5a2e1SPrashanth Swaminathan
602*1fd5a2e1SPrashanth Swaminathan /* Invoke the closure. */
603*1fd5a2e1SPrashanth Swaminathan fun (cif, rvalue, avalue, user_data);
604*1fd5a2e1SPrashanth Swaminathan
605*1fd5a2e1SPrashanth Swaminathan /* Tell ffi_closure_sparc how to perform return type promotions. */
606*1fd5a2e1SPrashanth Swaminathan return flags;
607*1fd5a2e1SPrashanth Swaminathan }
608*1fd5a2e1SPrashanth Swaminathan #endif /* SPARC64 */
609