1*1fd5a2e1SPrashanth Swaminathan /* -----------------------------------------------------------------------
2*1fd5a2e1SPrashanth Swaminathan ffi.c - Copyright (c) 2011 Anthony Green
3*1fd5a2e1SPrashanth Swaminathan Copyright (c) 2008 David Daney
4*1fd5a2e1SPrashanth Swaminathan Copyright (c) 1996, 2007, 2008, 2011 Red Hat, Inc.
5*1fd5a2e1SPrashanth Swaminathan
6*1fd5a2e1SPrashanth Swaminathan MIPS Foreign Function Interface
7*1fd5a2e1SPrashanth Swaminathan
8*1fd5a2e1SPrashanth Swaminathan Permission is hereby granted, free of charge, to any person obtaining
9*1fd5a2e1SPrashanth Swaminathan a copy of this software and associated documentation files (the
10*1fd5a2e1SPrashanth Swaminathan ``Software''), to deal in the Software without restriction, including
11*1fd5a2e1SPrashanth Swaminathan without limitation the rights to use, copy, modify, merge, publish,
12*1fd5a2e1SPrashanth Swaminathan distribute, sublicense, and/or sell copies of the Software, and to
13*1fd5a2e1SPrashanth Swaminathan permit persons to whom the Software is furnished to do so, subject to
14*1fd5a2e1SPrashanth Swaminathan the following conditions:
15*1fd5a2e1SPrashanth Swaminathan
16*1fd5a2e1SPrashanth Swaminathan The above copyright notice and this permission notice shall be included
17*1fd5a2e1SPrashanth Swaminathan in all copies or substantial portions of the Software.
18*1fd5a2e1SPrashanth Swaminathan
19*1fd5a2e1SPrashanth Swaminathan THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND,
20*1fd5a2e1SPrashanth Swaminathan EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
21*1fd5a2e1SPrashanth Swaminathan MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
22*1fd5a2e1SPrashanth Swaminathan NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
23*1fd5a2e1SPrashanth Swaminathan HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
24*1fd5a2e1SPrashanth Swaminathan WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
25*1fd5a2e1SPrashanth Swaminathan OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
26*1fd5a2e1SPrashanth Swaminathan DEALINGS IN THE SOFTWARE.
27*1fd5a2e1SPrashanth Swaminathan ----------------------------------------------------------------------- */
28*1fd5a2e1SPrashanth Swaminathan
29*1fd5a2e1SPrashanth Swaminathan #include <ffi.h>
30*1fd5a2e1SPrashanth Swaminathan #include <ffi_common.h>
31*1fd5a2e1SPrashanth Swaminathan
32*1fd5a2e1SPrashanth Swaminathan #include <stdint.h>
33*1fd5a2e1SPrashanth Swaminathan #include <stdlib.h>
34*1fd5a2e1SPrashanth Swaminathan
35*1fd5a2e1SPrashanth Swaminathan #ifdef __GNUC__
36*1fd5a2e1SPrashanth Swaminathan # if (__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 3))
37*1fd5a2e1SPrashanth Swaminathan # define USE__BUILTIN___CLEAR_CACHE 1
38*1fd5a2e1SPrashanth Swaminathan # endif
39*1fd5a2e1SPrashanth Swaminathan #endif
40*1fd5a2e1SPrashanth Swaminathan
41*1fd5a2e1SPrashanth Swaminathan #ifndef USE__BUILTIN___CLEAR_CACHE
42*1fd5a2e1SPrashanth Swaminathan # if defined(__OpenBSD__)
43*1fd5a2e1SPrashanth Swaminathan # include <mips64/sysarch.h>
44*1fd5a2e1SPrashanth Swaminathan # else
45*1fd5a2e1SPrashanth Swaminathan # include <sys/cachectl.h>
46*1fd5a2e1SPrashanth Swaminathan # endif
47*1fd5a2e1SPrashanth Swaminathan #endif
48*1fd5a2e1SPrashanth Swaminathan
49*1fd5a2e1SPrashanth Swaminathan #ifdef FFI_DEBUG
50*1fd5a2e1SPrashanth Swaminathan # define FFI_MIPS_STOP_HERE() ffi_stop_here()
51*1fd5a2e1SPrashanth Swaminathan #else
52*1fd5a2e1SPrashanth Swaminathan # define FFI_MIPS_STOP_HERE() do {} while(0)
53*1fd5a2e1SPrashanth Swaminathan #endif
54*1fd5a2e1SPrashanth Swaminathan
55*1fd5a2e1SPrashanth Swaminathan #ifdef FFI_MIPS_N32
56*1fd5a2e1SPrashanth Swaminathan #define FIX_ARGP \
57*1fd5a2e1SPrashanth Swaminathan FFI_ASSERT(argp <= &stack[bytes]); \
58*1fd5a2e1SPrashanth Swaminathan if (argp == &stack[bytes]) \
59*1fd5a2e1SPrashanth Swaminathan { \
60*1fd5a2e1SPrashanth Swaminathan argp = stack; \
61*1fd5a2e1SPrashanth Swaminathan FFI_MIPS_STOP_HERE(); \
62*1fd5a2e1SPrashanth Swaminathan }
63*1fd5a2e1SPrashanth Swaminathan #else
64*1fd5a2e1SPrashanth Swaminathan #define FIX_ARGP
65*1fd5a2e1SPrashanth Swaminathan #endif
66*1fd5a2e1SPrashanth Swaminathan
67*1fd5a2e1SPrashanth Swaminathan
68*1fd5a2e1SPrashanth Swaminathan /* ffi_prep_args is called by the assembly routine once stack space
69*1fd5a2e1SPrashanth Swaminathan has been allocated for the function's arguments */
70*1fd5a2e1SPrashanth Swaminathan
ffi_prep_args(char * stack,extended_cif * ecif,int bytes,int flags)71*1fd5a2e1SPrashanth Swaminathan static void ffi_prep_args(char *stack,
72*1fd5a2e1SPrashanth Swaminathan extended_cif *ecif,
73*1fd5a2e1SPrashanth Swaminathan int bytes,
74*1fd5a2e1SPrashanth Swaminathan int flags)
75*1fd5a2e1SPrashanth Swaminathan {
76*1fd5a2e1SPrashanth Swaminathan int i;
77*1fd5a2e1SPrashanth Swaminathan void **p_argv;
78*1fd5a2e1SPrashanth Swaminathan char *argp;
79*1fd5a2e1SPrashanth Swaminathan ffi_type **p_arg;
80*1fd5a2e1SPrashanth Swaminathan
81*1fd5a2e1SPrashanth Swaminathan #ifdef FFI_MIPS_N32
82*1fd5a2e1SPrashanth Swaminathan /* If more than 8 double words are used, the remainder go
83*1fd5a2e1SPrashanth Swaminathan on the stack. We reorder stuff on the stack here to
84*1fd5a2e1SPrashanth Swaminathan support this easily. */
85*1fd5a2e1SPrashanth Swaminathan if (bytes > 8 * sizeof(ffi_arg))
86*1fd5a2e1SPrashanth Swaminathan argp = &stack[bytes - (8 * sizeof(ffi_arg))];
87*1fd5a2e1SPrashanth Swaminathan else
88*1fd5a2e1SPrashanth Swaminathan argp = stack;
89*1fd5a2e1SPrashanth Swaminathan #else
90*1fd5a2e1SPrashanth Swaminathan argp = stack;
91*1fd5a2e1SPrashanth Swaminathan #endif
92*1fd5a2e1SPrashanth Swaminathan
93*1fd5a2e1SPrashanth Swaminathan memset(stack, 0, bytes);
94*1fd5a2e1SPrashanth Swaminathan
95*1fd5a2e1SPrashanth Swaminathan #ifdef FFI_MIPS_N32
96*1fd5a2e1SPrashanth Swaminathan if ( ecif->cif->rstruct_flag != 0 )
97*1fd5a2e1SPrashanth Swaminathan #else
98*1fd5a2e1SPrashanth Swaminathan if ( ecif->cif->rtype->type == FFI_TYPE_STRUCT )
99*1fd5a2e1SPrashanth Swaminathan #endif
100*1fd5a2e1SPrashanth Swaminathan {
101*1fd5a2e1SPrashanth Swaminathan *(ffi_arg *) argp = (ffi_arg) ecif->rvalue;
102*1fd5a2e1SPrashanth Swaminathan argp += sizeof(ffi_arg);
103*1fd5a2e1SPrashanth Swaminathan FIX_ARGP;
104*1fd5a2e1SPrashanth Swaminathan }
105*1fd5a2e1SPrashanth Swaminathan
106*1fd5a2e1SPrashanth Swaminathan p_argv = ecif->avalue;
107*1fd5a2e1SPrashanth Swaminathan
108*1fd5a2e1SPrashanth Swaminathan for (i = 0, p_arg = ecif->cif->arg_types; i < ecif->cif->nargs; i++, p_arg++)
109*1fd5a2e1SPrashanth Swaminathan {
110*1fd5a2e1SPrashanth Swaminathan size_t z;
111*1fd5a2e1SPrashanth Swaminathan unsigned int a;
112*1fd5a2e1SPrashanth Swaminathan
113*1fd5a2e1SPrashanth Swaminathan /* Align if necessary. */
114*1fd5a2e1SPrashanth Swaminathan a = (*p_arg)->alignment;
115*1fd5a2e1SPrashanth Swaminathan if (a < sizeof(ffi_arg))
116*1fd5a2e1SPrashanth Swaminathan a = sizeof(ffi_arg);
117*1fd5a2e1SPrashanth Swaminathan
118*1fd5a2e1SPrashanth Swaminathan if ((a - 1) & (unsigned long) argp)
119*1fd5a2e1SPrashanth Swaminathan {
120*1fd5a2e1SPrashanth Swaminathan argp = (char *) FFI_ALIGN(argp, a);
121*1fd5a2e1SPrashanth Swaminathan FIX_ARGP;
122*1fd5a2e1SPrashanth Swaminathan }
123*1fd5a2e1SPrashanth Swaminathan
124*1fd5a2e1SPrashanth Swaminathan z = (*p_arg)->size;
125*1fd5a2e1SPrashanth Swaminathan if (z <= sizeof(ffi_arg))
126*1fd5a2e1SPrashanth Swaminathan {
127*1fd5a2e1SPrashanth Swaminathan int type = (*p_arg)->type;
128*1fd5a2e1SPrashanth Swaminathan z = sizeof(ffi_arg);
129*1fd5a2e1SPrashanth Swaminathan
130*1fd5a2e1SPrashanth Swaminathan /* The size of a pointer depends on the ABI */
131*1fd5a2e1SPrashanth Swaminathan if (type == FFI_TYPE_POINTER)
132*1fd5a2e1SPrashanth Swaminathan type = (ecif->cif->abi == FFI_N64
133*1fd5a2e1SPrashanth Swaminathan || ecif->cif->abi == FFI_N64_SOFT_FLOAT)
134*1fd5a2e1SPrashanth Swaminathan ? FFI_TYPE_SINT64 : FFI_TYPE_SINT32;
135*1fd5a2e1SPrashanth Swaminathan
136*1fd5a2e1SPrashanth Swaminathan if (i < 8 && (ecif->cif->abi == FFI_N32_SOFT_FLOAT
137*1fd5a2e1SPrashanth Swaminathan || ecif->cif->abi == FFI_N64_SOFT_FLOAT))
138*1fd5a2e1SPrashanth Swaminathan {
139*1fd5a2e1SPrashanth Swaminathan switch (type)
140*1fd5a2e1SPrashanth Swaminathan {
141*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_FLOAT:
142*1fd5a2e1SPrashanth Swaminathan type = FFI_TYPE_UINT32;
143*1fd5a2e1SPrashanth Swaminathan break;
144*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_DOUBLE:
145*1fd5a2e1SPrashanth Swaminathan type = FFI_TYPE_UINT64;
146*1fd5a2e1SPrashanth Swaminathan break;
147*1fd5a2e1SPrashanth Swaminathan default:
148*1fd5a2e1SPrashanth Swaminathan break;
149*1fd5a2e1SPrashanth Swaminathan }
150*1fd5a2e1SPrashanth Swaminathan }
151*1fd5a2e1SPrashanth Swaminathan switch (type)
152*1fd5a2e1SPrashanth Swaminathan {
153*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_SINT8:
154*1fd5a2e1SPrashanth Swaminathan *(ffi_arg *)argp = *(SINT8 *)(* p_argv);
155*1fd5a2e1SPrashanth Swaminathan break;
156*1fd5a2e1SPrashanth Swaminathan
157*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_UINT8:
158*1fd5a2e1SPrashanth Swaminathan *(ffi_arg *)argp = *(UINT8 *)(* p_argv);
159*1fd5a2e1SPrashanth Swaminathan break;
160*1fd5a2e1SPrashanth Swaminathan
161*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_SINT16:
162*1fd5a2e1SPrashanth Swaminathan *(ffi_arg *)argp = *(SINT16 *)(* p_argv);
163*1fd5a2e1SPrashanth Swaminathan break;
164*1fd5a2e1SPrashanth Swaminathan
165*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_UINT16:
166*1fd5a2e1SPrashanth Swaminathan *(ffi_arg *)argp = *(UINT16 *)(* p_argv);
167*1fd5a2e1SPrashanth Swaminathan break;
168*1fd5a2e1SPrashanth Swaminathan
169*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_SINT32:
170*1fd5a2e1SPrashanth Swaminathan *(ffi_arg *)argp = *(SINT32 *)(* p_argv);
171*1fd5a2e1SPrashanth Swaminathan break;
172*1fd5a2e1SPrashanth Swaminathan
173*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_UINT32:
174*1fd5a2e1SPrashanth Swaminathan #ifdef FFI_MIPS_N32
175*1fd5a2e1SPrashanth Swaminathan /* The N32 ABI requires that 32-bit integers
176*1fd5a2e1SPrashanth Swaminathan be sign-extended to 64-bits, regardless of
177*1fd5a2e1SPrashanth Swaminathan whether they are signed or unsigned. */
178*1fd5a2e1SPrashanth Swaminathan *(ffi_arg *)argp = *(SINT32 *)(* p_argv);
179*1fd5a2e1SPrashanth Swaminathan #else
180*1fd5a2e1SPrashanth Swaminathan *(ffi_arg *)argp = *(UINT32 *)(* p_argv);
181*1fd5a2e1SPrashanth Swaminathan #endif
182*1fd5a2e1SPrashanth Swaminathan break;
183*1fd5a2e1SPrashanth Swaminathan
184*1fd5a2e1SPrashanth Swaminathan /* This can only happen with 64bit slots. */
185*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_FLOAT:
186*1fd5a2e1SPrashanth Swaminathan *(float *) argp = *(float *)(* p_argv);
187*1fd5a2e1SPrashanth Swaminathan break;
188*1fd5a2e1SPrashanth Swaminathan
189*1fd5a2e1SPrashanth Swaminathan /* Handle structures. */
190*1fd5a2e1SPrashanth Swaminathan default:
191*1fd5a2e1SPrashanth Swaminathan memcpy(argp, *p_argv, (*p_arg)->size);
192*1fd5a2e1SPrashanth Swaminathan break;
193*1fd5a2e1SPrashanth Swaminathan }
194*1fd5a2e1SPrashanth Swaminathan }
195*1fd5a2e1SPrashanth Swaminathan else
196*1fd5a2e1SPrashanth Swaminathan {
197*1fd5a2e1SPrashanth Swaminathan #ifdef FFI_MIPS_O32
198*1fd5a2e1SPrashanth Swaminathan memcpy(argp, *p_argv, z);
199*1fd5a2e1SPrashanth Swaminathan #else
200*1fd5a2e1SPrashanth Swaminathan {
201*1fd5a2e1SPrashanth Swaminathan unsigned long end = (unsigned long) argp + z;
202*1fd5a2e1SPrashanth Swaminathan unsigned long cap = (unsigned long) stack + bytes;
203*1fd5a2e1SPrashanth Swaminathan
204*1fd5a2e1SPrashanth Swaminathan /* Check if the data will fit within the register space.
205*1fd5a2e1SPrashanth Swaminathan Handle it if it doesn't. */
206*1fd5a2e1SPrashanth Swaminathan
207*1fd5a2e1SPrashanth Swaminathan if (end <= cap)
208*1fd5a2e1SPrashanth Swaminathan memcpy(argp, *p_argv, z);
209*1fd5a2e1SPrashanth Swaminathan else
210*1fd5a2e1SPrashanth Swaminathan {
211*1fd5a2e1SPrashanth Swaminathan unsigned long portion = cap - (unsigned long)argp;
212*1fd5a2e1SPrashanth Swaminathan
213*1fd5a2e1SPrashanth Swaminathan memcpy(argp, *p_argv, portion);
214*1fd5a2e1SPrashanth Swaminathan argp = stack;
215*1fd5a2e1SPrashanth Swaminathan z -= portion;
216*1fd5a2e1SPrashanth Swaminathan memcpy(argp, (void*)((unsigned long)(*p_argv) + portion),
217*1fd5a2e1SPrashanth Swaminathan z);
218*1fd5a2e1SPrashanth Swaminathan }
219*1fd5a2e1SPrashanth Swaminathan }
220*1fd5a2e1SPrashanth Swaminathan #endif
221*1fd5a2e1SPrashanth Swaminathan }
222*1fd5a2e1SPrashanth Swaminathan p_argv++;
223*1fd5a2e1SPrashanth Swaminathan argp += z;
224*1fd5a2e1SPrashanth Swaminathan FIX_ARGP;
225*1fd5a2e1SPrashanth Swaminathan }
226*1fd5a2e1SPrashanth Swaminathan }
227*1fd5a2e1SPrashanth Swaminathan
228*1fd5a2e1SPrashanth Swaminathan #ifdef FFI_MIPS_N32
229*1fd5a2e1SPrashanth Swaminathan
230*1fd5a2e1SPrashanth Swaminathan /* The n32 spec says that if "a chunk consists solely of a double
231*1fd5a2e1SPrashanth Swaminathan float field (but not a double, which is part of a union), it
232*1fd5a2e1SPrashanth Swaminathan is passed in a floating point register. Any other chunk is
233*1fd5a2e1SPrashanth Swaminathan passed in an integer register". This code traverses structure
234*1fd5a2e1SPrashanth Swaminathan definitions and generates the appropriate flags. */
235*1fd5a2e1SPrashanth Swaminathan
236*1fd5a2e1SPrashanth Swaminathan static unsigned
calc_n32_struct_flags(int soft_float,ffi_type * arg,unsigned * loc,unsigned * arg_reg)237*1fd5a2e1SPrashanth Swaminathan calc_n32_struct_flags(int soft_float, ffi_type *arg,
238*1fd5a2e1SPrashanth Swaminathan unsigned *loc, unsigned *arg_reg)
239*1fd5a2e1SPrashanth Swaminathan {
240*1fd5a2e1SPrashanth Swaminathan unsigned flags = 0;
241*1fd5a2e1SPrashanth Swaminathan unsigned index = 0;
242*1fd5a2e1SPrashanth Swaminathan
243*1fd5a2e1SPrashanth Swaminathan ffi_type *e;
244*1fd5a2e1SPrashanth Swaminathan
245*1fd5a2e1SPrashanth Swaminathan if (soft_float)
246*1fd5a2e1SPrashanth Swaminathan return 0;
247*1fd5a2e1SPrashanth Swaminathan
248*1fd5a2e1SPrashanth Swaminathan while ((e = arg->elements[index]))
249*1fd5a2e1SPrashanth Swaminathan {
250*1fd5a2e1SPrashanth Swaminathan /* Align this object. */
251*1fd5a2e1SPrashanth Swaminathan *loc = FFI_ALIGN(*loc, e->alignment);
252*1fd5a2e1SPrashanth Swaminathan if (e->type == FFI_TYPE_DOUBLE)
253*1fd5a2e1SPrashanth Swaminathan {
254*1fd5a2e1SPrashanth Swaminathan /* Already aligned to FFI_SIZEOF_ARG. */
255*1fd5a2e1SPrashanth Swaminathan *arg_reg = *loc / FFI_SIZEOF_ARG;
256*1fd5a2e1SPrashanth Swaminathan if (*arg_reg > 7)
257*1fd5a2e1SPrashanth Swaminathan break;
258*1fd5a2e1SPrashanth Swaminathan flags += (FFI_TYPE_DOUBLE << (*arg_reg * FFI_FLAG_BITS));
259*1fd5a2e1SPrashanth Swaminathan *loc += e->size;
260*1fd5a2e1SPrashanth Swaminathan }
261*1fd5a2e1SPrashanth Swaminathan else
262*1fd5a2e1SPrashanth Swaminathan *loc += e->size;
263*1fd5a2e1SPrashanth Swaminathan index++;
264*1fd5a2e1SPrashanth Swaminathan }
265*1fd5a2e1SPrashanth Swaminathan /* Next Argument register at alignment of FFI_SIZEOF_ARG. */
266*1fd5a2e1SPrashanth Swaminathan *arg_reg = FFI_ALIGN(*loc, FFI_SIZEOF_ARG) / FFI_SIZEOF_ARG;
267*1fd5a2e1SPrashanth Swaminathan
268*1fd5a2e1SPrashanth Swaminathan return flags;
269*1fd5a2e1SPrashanth Swaminathan }
270*1fd5a2e1SPrashanth Swaminathan
271*1fd5a2e1SPrashanth Swaminathan static unsigned
calc_n32_return_struct_flags(int soft_float,ffi_type * arg)272*1fd5a2e1SPrashanth Swaminathan calc_n32_return_struct_flags(int soft_float, ffi_type *arg)
273*1fd5a2e1SPrashanth Swaminathan {
274*1fd5a2e1SPrashanth Swaminathan unsigned flags = 0;
275*1fd5a2e1SPrashanth Swaminathan unsigned small = FFI_TYPE_SMALLSTRUCT;
276*1fd5a2e1SPrashanth Swaminathan ffi_type *e;
277*1fd5a2e1SPrashanth Swaminathan
278*1fd5a2e1SPrashanth Swaminathan /* Returning structures under n32 is a tricky thing.
279*1fd5a2e1SPrashanth Swaminathan A struct with only one or two floating point fields
280*1fd5a2e1SPrashanth Swaminathan is returned in $f0 (and $f2 if necessary). Any other
281*1fd5a2e1SPrashanth Swaminathan struct results at most 128 bits are returned in $2
282*1fd5a2e1SPrashanth Swaminathan (the first 64 bits) and $3 (remainder, if necessary).
283*1fd5a2e1SPrashanth Swaminathan Larger structs are handled normally. */
284*1fd5a2e1SPrashanth Swaminathan
285*1fd5a2e1SPrashanth Swaminathan if (arg->size > 16)
286*1fd5a2e1SPrashanth Swaminathan return 0;
287*1fd5a2e1SPrashanth Swaminathan
288*1fd5a2e1SPrashanth Swaminathan if (arg->size > 8)
289*1fd5a2e1SPrashanth Swaminathan small = FFI_TYPE_SMALLSTRUCT2;
290*1fd5a2e1SPrashanth Swaminathan
291*1fd5a2e1SPrashanth Swaminathan e = arg->elements[0];
292*1fd5a2e1SPrashanth Swaminathan
293*1fd5a2e1SPrashanth Swaminathan if (e->type == FFI_TYPE_DOUBLE)
294*1fd5a2e1SPrashanth Swaminathan flags = FFI_TYPE_DOUBLE;
295*1fd5a2e1SPrashanth Swaminathan else if (e->type == FFI_TYPE_FLOAT)
296*1fd5a2e1SPrashanth Swaminathan flags = FFI_TYPE_FLOAT;
297*1fd5a2e1SPrashanth Swaminathan
298*1fd5a2e1SPrashanth Swaminathan if (flags && (e = arg->elements[1]))
299*1fd5a2e1SPrashanth Swaminathan {
300*1fd5a2e1SPrashanth Swaminathan if (e->type == FFI_TYPE_DOUBLE)
301*1fd5a2e1SPrashanth Swaminathan flags += FFI_TYPE_DOUBLE << FFI_FLAG_BITS;
302*1fd5a2e1SPrashanth Swaminathan else if (e->type == FFI_TYPE_FLOAT)
303*1fd5a2e1SPrashanth Swaminathan flags += FFI_TYPE_FLOAT << FFI_FLAG_BITS;
304*1fd5a2e1SPrashanth Swaminathan else
305*1fd5a2e1SPrashanth Swaminathan return small;
306*1fd5a2e1SPrashanth Swaminathan
307*1fd5a2e1SPrashanth Swaminathan if (flags && (arg->elements[2]))
308*1fd5a2e1SPrashanth Swaminathan {
309*1fd5a2e1SPrashanth Swaminathan /* There are three arguments and the first two are
310*1fd5a2e1SPrashanth Swaminathan floats! This must be passed the old way. */
311*1fd5a2e1SPrashanth Swaminathan return small;
312*1fd5a2e1SPrashanth Swaminathan }
313*1fd5a2e1SPrashanth Swaminathan if (soft_float)
314*1fd5a2e1SPrashanth Swaminathan flags += FFI_TYPE_STRUCT_SOFT;
315*1fd5a2e1SPrashanth Swaminathan }
316*1fd5a2e1SPrashanth Swaminathan else
317*1fd5a2e1SPrashanth Swaminathan if (!flags)
318*1fd5a2e1SPrashanth Swaminathan return small;
319*1fd5a2e1SPrashanth Swaminathan
320*1fd5a2e1SPrashanth Swaminathan return flags;
321*1fd5a2e1SPrashanth Swaminathan }
322*1fd5a2e1SPrashanth Swaminathan
323*1fd5a2e1SPrashanth Swaminathan #endif
324*1fd5a2e1SPrashanth Swaminathan
325*1fd5a2e1SPrashanth Swaminathan /* Perform machine dependent cif processing */
ffi_prep_cif_machdep_int(ffi_cif * cif,unsigned nfixedargs)326*1fd5a2e1SPrashanth Swaminathan static ffi_status ffi_prep_cif_machdep_int(ffi_cif *cif, unsigned nfixedargs)
327*1fd5a2e1SPrashanth Swaminathan {
328*1fd5a2e1SPrashanth Swaminathan cif->flags = 0;
329*1fd5a2e1SPrashanth Swaminathan cif->mips_nfixedargs = nfixedargs;
330*1fd5a2e1SPrashanth Swaminathan
331*1fd5a2e1SPrashanth Swaminathan #ifdef FFI_MIPS_O32
332*1fd5a2e1SPrashanth Swaminathan /* Set the flags necessary for O32 processing. FFI_O32_SOFT_FLOAT
333*1fd5a2e1SPrashanth Swaminathan * does not have special handling for floating point args.
334*1fd5a2e1SPrashanth Swaminathan */
335*1fd5a2e1SPrashanth Swaminathan
336*1fd5a2e1SPrashanth Swaminathan if (cif->rtype->type != FFI_TYPE_STRUCT && cif->abi == FFI_O32)
337*1fd5a2e1SPrashanth Swaminathan {
338*1fd5a2e1SPrashanth Swaminathan if (cif->nargs > 0 && cif->nargs == nfixedargs)
339*1fd5a2e1SPrashanth Swaminathan {
340*1fd5a2e1SPrashanth Swaminathan switch ((cif->arg_types)[0]->type)
341*1fd5a2e1SPrashanth Swaminathan {
342*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_FLOAT:
343*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_DOUBLE:
344*1fd5a2e1SPrashanth Swaminathan cif->flags += (cif->arg_types)[0]->type;
345*1fd5a2e1SPrashanth Swaminathan break;
346*1fd5a2e1SPrashanth Swaminathan
347*1fd5a2e1SPrashanth Swaminathan default:
348*1fd5a2e1SPrashanth Swaminathan break;
349*1fd5a2e1SPrashanth Swaminathan }
350*1fd5a2e1SPrashanth Swaminathan
351*1fd5a2e1SPrashanth Swaminathan if (cif->nargs > 1)
352*1fd5a2e1SPrashanth Swaminathan {
353*1fd5a2e1SPrashanth Swaminathan /* Only handle the second argument if the first
354*1fd5a2e1SPrashanth Swaminathan is a float or double. */
355*1fd5a2e1SPrashanth Swaminathan if (cif->flags)
356*1fd5a2e1SPrashanth Swaminathan {
357*1fd5a2e1SPrashanth Swaminathan switch ((cif->arg_types)[1]->type)
358*1fd5a2e1SPrashanth Swaminathan {
359*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_FLOAT:
360*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_DOUBLE:
361*1fd5a2e1SPrashanth Swaminathan cif->flags += (cif->arg_types)[1]->type << FFI_FLAG_BITS;
362*1fd5a2e1SPrashanth Swaminathan break;
363*1fd5a2e1SPrashanth Swaminathan
364*1fd5a2e1SPrashanth Swaminathan default:
365*1fd5a2e1SPrashanth Swaminathan break;
366*1fd5a2e1SPrashanth Swaminathan }
367*1fd5a2e1SPrashanth Swaminathan }
368*1fd5a2e1SPrashanth Swaminathan }
369*1fd5a2e1SPrashanth Swaminathan }
370*1fd5a2e1SPrashanth Swaminathan }
371*1fd5a2e1SPrashanth Swaminathan
372*1fd5a2e1SPrashanth Swaminathan /* Set the return type flag */
373*1fd5a2e1SPrashanth Swaminathan
374*1fd5a2e1SPrashanth Swaminathan if (cif->abi == FFI_O32_SOFT_FLOAT)
375*1fd5a2e1SPrashanth Swaminathan {
376*1fd5a2e1SPrashanth Swaminathan switch (cif->rtype->type)
377*1fd5a2e1SPrashanth Swaminathan {
378*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_VOID:
379*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_STRUCT:
380*1fd5a2e1SPrashanth Swaminathan cif->flags += cif->rtype->type << (FFI_FLAG_BITS * 2);
381*1fd5a2e1SPrashanth Swaminathan break;
382*1fd5a2e1SPrashanth Swaminathan
383*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_SINT64:
384*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_UINT64:
385*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_DOUBLE:
386*1fd5a2e1SPrashanth Swaminathan cif->flags += FFI_TYPE_UINT64 << (FFI_FLAG_BITS * 2);
387*1fd5a2e1SPrashanth Swaminathan break;
388*1fd5a2e1SPrashanth Swaminathan
389*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_FLOAT:
390*1fd5a2e1SPrashanth Swaminathan default:
391*1fd5a2e1SPrashanth Swaminathan cif->flags += FFI_TYPE_INT << (FFI_FLAG_BITS * 2);
392*1fd5a2e1SPrashanth Swaminathan break;
393*1fd5a2e1SPrashanth Swaminathan }
394*1fd5a2e1SPrashanth Swaminathan }
395*1fd5a2e1SPrashanth Swaminathan else
396*1fd5a2e1SPrashanth Swaminathan {
397*1fd5a2e1SPrashanth Swaminathan /* FFI_O32 */
398*1fd5a2e1SPrashanth Swaminathan switch (cif->rtype->type)
399*1fd5a2e1SPrashanth Swaminathan {
400*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_VOID:
401*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_STRUCT:
402*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_FLOAT:
403*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_DOUBLE:
404*1fd5a2e1SPrashanth Swaminathan cif->flags += cif->rtype->type << (FFI_FLAG_BITS * 2);
405*1fd5a2e1SPrashanth Swaminathan break;
406*1fd5a2e1SPrashanth Swaminathan
407*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_SINT64:
408*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_UINT64:
409*1fd5a2e1SPrashanth Swaminathan cif->flags += FFI_TYPE_UINT64 << (FFI_FLAG_BITS * 2);
410*1fd5a2e1SPrashanth Swaminathan break;
411*1fd5a2e1SPrashanth Swaminathan
412*1fd5a2e1SPrashanth Swaminathan default:
413*1fd5a2e1SPrashanth Swaminathan cif->flags += FFI_TYPE_INT << (FFI_FLAG_BITS * 2);
414*1fd5a2e1SPrashanth Swaminathan break;
415*1fd5a2e1SPrashanth Swaminathan }
416*1fd5a2e1SPrashanth Swaminathan }
417*1fd5a2e1SPrashanth Swaminathan #endif
418*1fd5a2e1SPrashanth Swaminathan
419*1fd5a2e1SPrashanth Swaminathan #ifdef FFI_MIPS_N32
420*1fd5a2e1SPrashanth Swaminathan /* Set the flags necessary for N32 processing */
421*1fd5a2e1SPrashanth Swaminathan {
422*1fd5a2e1SPrashanth Swaminathan int type;
423*1fd5a2e1SPrashanth Swaminathan unsigned arg_reg = 0;
424*1fd5a2e1SPrashanth Swaminathan unsigned loc = 0;
425*1fd5a2e1SPrashanth Swaminathan unsigned count = (cif->nargs < 8) ? cif->nargs : 8;
426*1fd5a2e1SPrashanth Swaminathan unsigned index = 0;
427*1fd5a2e1SPrashanth Swaminathan
428*1fd5a2e1SPrashanth Swaminathan unsigned struct_flags = 0;
429*1fd5a2e1SPrashanth Swaminathan int soft_float = (cif->abi == FFI_N32_SOFT_FLOAT
430*1fd5a2e1SPrashanth Swaminathan || cif->abi == FFI_N64_SOFT_FLOAT);
431*1fd5a2e1SPrashanth Swaminathan
432*1fd5a2e1SPrashanth Swaminathan if (cif->rtype->type == FFI_TYPE_STRUCT)
433*1fd5a2e1SPrashanth Swaminathan {
434*1fd5a2e1SPrashanth Swaminathan struct_flags = calc_n32_return_struct_flags(soft_float, cif->rtype);
435*1fd5a2e1SPrashanth Swaminathan
436*1fd5a2e1SPrashanth Swaminathan if (struct_flags == 0)
437*1fd5a2e1SPrashanth Swaminathan {
438*1fd5a2e1SPrashanth Swaminathan /* This means that the structure is being passed as
439*1fd5a2e1SPrashanth Swaminathan a hidden argument */
440*1fd5a2e1SPrashanth Swaminathan
441*1fd5a2e1SPrashanth Swaminathan arg_reg = 1;
442*1fd5a2e1SPrashanth Swaminathan count = (cif->nargs < 7) ? cif->nargs : 7;
443*1fd5a2e1SPrashanth Swaminathan
444*1fd5a2e1SPrashanth Swaminathan cif->rstruct_flag = !0;
445*1fd5a2e1SPrashanth Swaminathan }
446*1fd5a2e1SPrashanth Swaminathan else
447*1fd5a2e1SPrashanth Swaminathan cif->rstruct_flag = 0;
448*1fd5a2e1SPrashanth Swaminathan }
449*1fd5a2e1SPrashanth Swaminathan else
450*1fd5a2e1SPrashanth Swaminathan cif->rstruct_flag = 0;
451*1fd5a2e1SPrashanth Swaminathan
452*1fd5a2e1SPrashanth Swaminathan while (count-- > 0 && arg_reg < 8)
453*1fd5a2e1SPrashanth Swaminathan {
454*1fd5a2e1SPrashanth Swaminathan type = (cif->arg_types)[index]->type;
455*1fd5a2e1SPrashanth Swaminathan
456*1fd5a2e1SPrashanth Swaminathan // Pass variadic arguments in integer registers even if they're floats
457*1fd5a2e1SPrashanth Swaminathan if (soft_float || index >= nfixedargs)
458*1fd5a2e1SPrashanth Swaminathan {
459*1fd5a2e1SPrashanth Swaminathan switch (type)
460*1fd5a2e1SPrashanth Swaminathan {
461*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_FLOAT:
462*1fd5a2e1SPrashanth Swaminathan type = FFI_TYPE_UINT32;
463*1fd5a2e1SPrashanth Swaminathan break;
464*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_DOUBLE:
465*1fd5a2e1SPrashanth Swaminathan type = FFI_TYPE_UINT64;
466*1fd5a2e1SPrashanth Swaminathan break;
467*1fd5a2e1SPrashanth Swaminathan default:
468*1fd5a2e1SPrashanth Swaminathan break;
469*1fd5a2e1SPrashanth Swaminathan }
470*1fd5a2e1SPrashanth Swaminathan }
471*1fd5a2e1SPrashanth Swaminathan switch (type)
472*1fd5a2e1SPrashanth Swaminathan {
473*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_FLOAT:
474*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_DOUBLE:
475*1fd5a2e1SPrashanth Swaminathan cif->flags +=
476*1fd5a2e1SPrashanth Swaminathan ((cif->arg_types)[index]->type << (arg_reg * FFI_FLAG_BITS));
477*1fd5a2e1SPrashanth Swaminathan arg_reg++;
478*1fd5a2e1SPrashanth Swaminathan break;
479*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_LONGDOUBLE:
480*1fd5a2e1SPrashanth Swaminathan /* Align it. */
481*1fd5a2e1SPrashanth Swaminathan arg_reg = FFI_ALIGN(arg_reg, 2);
482*1fd5a2e1SPrashanth Swaminathan /* Treat it as two adjacent doubles. */
483*1fd5a2e1SPrashanth Swaminathan if (soft_float || index >= nfixedargs)
484*1fd5a2e1SPrashanth Swaminathan {
485*1fd5a2e1SPrashanth Swaminathan arg_reg += 2;
486*1fd5a2e1SPrashanth Swaminathan }
487*1fd5a2e1SPrashanth Swaminathan else
488*1fd5a2e1SPrashanth Swaminathan {
489*1fd5a2e1SPrashanth Swaminathan cif->flags +=
490*1fd5a2e1SPrashanth Swaminathan (FFI_TYPE_DOUBLE << (arg_reg * FFI_FLAG_BITS));
491*1fd5a2e1SPrashanth Swaminathan arg_reg++;
492*1fd5a2e1SPrashanth Swaminathan cif->flags +=
493*1fd5a2e1SPrashanth Swaminathan (FFI_TYPE_DOUBLE << (arg_reg * FFI_FLAG_BITS));
494*1fd5a2e1SPrashanth Swaminathan arg_reg++;
495*1fd5a2e1SPrashanth Swaminathan }
496*1fd5a2e1SPrashanth Swaminathan break;
497*1fd5a2e1SPrashanth Swaminathan
498*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_STRUCT:
499*1fd5a2e1SPrashanth Swaminathan loc = arg_reg * FFI_SIZEOF_ARG;
500*1fd5a2e1SPrashanth Swaminathan cif->flags += calc_n32_struct_flags(soft_float || index >= nfixedargs,
501*1fd5a2e1SPrashanth Swaminathan (cif->arg_types)[index],
502*1fd5a2e1SPrashanth Swaminathan &loc, &arg_reg);
503*1fd5a2e1SPrashanth Swaminathan break;
504*1fd5a2e1SPrashanth Swaminathan
505*1fd5a2e1SPrashanth Swaminathan default:
506*1fd5a2e1SPrashanth Swaminathan arg_reg++;
507*1fd5a2e1SPrashanth Swaminathan break;
508*1fd5a2e1SPrashanth Swaminathan }
509*1fd5a2e1SPrashanth Swaminathan
510*1fd5a2e1SPrashanth Swaminathan index++;
511*1fd5a2e1SPrashanth Swaminathan }
512*1fd5a2e1SPrashanth Swaminathan
513*1fd5a2e1SPrashanth Swaminathan /* Set the return type flag */
514*1fd5a2e1SPrashanth Swaminathan switch (cif->rtype->type)
515*1fd5a2e1SPrashanth Swaminathan {
516*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_STRUCT:
517*1fd5a2e1SPrashanth Swaminathan {
518*1fd5a2e1SPrashanth Swaminathan if (struct_flags == 0)
519*1fd5a2e1SPrashanth Swaminathan {
520*1fd5a2e1SPrashanth Swaminathan /* The structure is returned through a hidden
521*1fd5a2e1SPrashanth Swaminathan first argument. Do nothing, 'cause FFI_TYPE_VOID
522*1fd5a2e1SPrashanth Swaminathan is 0 */
523*1fd5a2e1SPrashanth Swaminathan }
524*1fd5a2e1SPrashanth Swaminathan else
525*1fd5a2e1SPrashanth Swaminathan {
526*1fd5a2e1SPrashanth Swaminathan /* The structure is returned via some tricky
527*1fd5a2e1SPrashanth Swaminathan mechanism */
528*1fd5a2e1SPrashanth Swaminathan cif->flags += FFI_TYPE_STRUCT << (FFI_FLAG_BITS * 8);
529*1fd5a2e1SPrashanth Swaminathan cif->flags += struct_flags << (4 + (FFI_FLAG_BITS * 8));
530*1fd5a2e1SPrashanth Swaminathan }
531*1fd5a2e1SPrashanth Swaminathan break;
532*1fd5a2e1SPrashanth Swaminathan }
533*1fd5a2e1SPrashanth Swaminathan
534*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_VOID:
535*1fd5a2e1SPrashanth Swaminathan /* Do nothing, 'cause FFI_TYPE_VOID is 0 */
536*1fd5a2e1SPrashanth Swaminathan break;
537*1fd5a2e1SPrashanth Swaminathan
538*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_POINTER:
539*1fd5a2e1SPrashanth Swaminathan if (cif->abi == FFI_N32_SOFT_FLOAT || cif->abi == FFI_N32)
540*1fd5a2e1SPrashanth Swaminathan cif->flags += FFI_TYPE_SINT32 << (FFI_FLAG_BITS * 8);
541*1fd5a2e1SPrashanth Swaminathan else
542*1fd5a2e1SPrashanth Swaminathan cif->flags += FFI_TYPE_INT << (FFI_FLAG_BITS * 8);
543*1fd5a2e1SPrashanth Swaminathan break;
544*1fd5a2e1SPrashanth Swaminathan
545*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_FLOAT:
546*1fd5a2e1SPrashanth Swaminathan if (soft_float)
547*1fd5a2e1SPrashanth Swaminathan {
548*1fd5a2e1SPrashanth Swaminathan cif->flags += FFI_TYPE_SINT32 << (FFI_FLAG_BITS * 8);
549*1fd5a2e1SPrashanth Swaminathan break;
550*1fd5a2e1SPrashanth Swaminathan }
551*1fd5a2e1SPrashanth Swaminathan /* else fall through */
552*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_DOUBLE:
553*1fd5a2e1SPrashanth Swaminathan if (soft_float)
554*1fd5a2e1SPrashanth Swaminathan cif->flags += FFI_TYPE_INT << (FFI_FLAG_BITS * 8);
555*1fd5a2e1SPrashanth Swaminathan else
556*1fd5a2e1SPrashanth Swaminathan cif->flags += cif->rtype->type << (FFI_FLAG_BITS * 8);
557*1fd5a2e1SPrashanth Swaminathan break;
558*1fd5a2e1SPrashanth Swaminathan
559*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_LONGDOUBLE:
560*1fd5a2e1SPrashanth Swaminathan /* Long double is returned as if it were a struct containing
561*1fd5a2e1SPrashanth Swaminathan two doubles. */
562*1fd5a2e1SPrashanth Swaminathan if (soft_float)
563*1fd5a2e1SPrashanth Swaminathan {
564*1fd5a2e1SPrashanth Swaminathan cif->flags += FFI_TYPE_STRUCT << (FFI_FLAG_BITS * 8);
565*1fd5a2e1SPrashanth Swaminathan cif->flags += FFI_TYPE_SMALLSTRUCT2 << (4 + (FFI_FLAG_BITS * 8));
566*1fd5a2e1SPrashanth Swaminathan }
567*1fd5a2e1SPrashanth Swaminathan else
568*1fd5a2e1SPrashanth Swaminathan {
569*1fd5a2e1SPrashanth Swaminathan cif->flags += FFI_TYPE_STRUCT << (FFI_FLAG_BITS * 8);
570*1fd5a2e1SPrashanth Swaminathan cif->flags += (FFI_TYPE_DOUBLE
571*1fd5a2e1SPrashanth Swaminathan + (FFI_TYPE_DOUBLE << FFI_FLAG_BITS))
572*1fd5a2e1SPrashanth Swaminathan << (4 + (FFI_FLAG_BITS * 8));
573*1fd5a2e1SPrashanth Swaminathan }
574*1fd5a2e1SPrashanth Swaminathan break;
575*1fd5a2e1SPrashanth Swaminathan default:
576*1fd5a2e1SPrashanth Swaminathan cif->flags += FFI_TYPE_INT << (FFI_FLAG_BITS * 8);
577*1fd5a2e1SPrashanth Swaminathan break;
578*1fd5a2e1SPrashanth Swaminathan }
579*1fd5a2e1SPrashanth Swaminathan }
580*1fd5a2e1SPrashanth Swaminathan #endif
581*1fd5a2e1SPrashanth Swaminathan
582*1fd5a2e1SPrashanth Swaminathan return FFI_OK;
583*1fd5a2e1SPrashanth Swaminathan }
584*1fd5a2e1SPrashanth Swaminathan
ffi_prep_cif_machdep(ffi_cif * cif)585*1fd5a2e1SPrashanth Swaminathan ffi_status ffi_prep_cif_machdep(ffi_cif *cif)
586*1fd5a2e1SPrashanth Swaminathan {
587*1fd5a2e1SPrashanth Swaminathan return ffi_prep_cif_machdep_int(cif, cif->nargs);
588*1fd5a2e1SPrashanth Swaminathan }
589*1fd5a2e1SPrashanth Swaminathan
ffi_prep_cif_machdep_var(ffi_cif * cif,unsigned nfixedargs,unsigned ntotalargs MAYBE_UNUSED)590*1fd5a2e1SPrashanth Swaminathan ffi_status ffi_prep_cif_machdep_var(ffi_cif *cif,
591*1fd5a2e1SPrashanth Swaminathan unsigned nfixedargs,
592*1fd5a2e1SPrashanth Swaminathan unsigned ntotalargs MAYBE_UNUSED)
593*1fd5a2e1SPrashanth Swaminathan {
594*1fd5a2e1SPrashanth Swaminathan return ffi_prep_cif_machdep_int(cif, nfixedargs);
595*1fd5a2e1SPrashanth Swaminathan }
596*1fd5a2e1SPrashanth Swaminathan
597*1fd5a2e1SPrashanth Swaminathan /* Low level routine for calling O32 functions */
598*1fd5a2e1SPrashanth Swaminathan extern int ffi_call_O32(void (*)(char *, extended_cif *, int, int),
599*1fd5a2e1SPrashanth Swaminathan extended_cif *, unsigned,
600*1fd5a2e1SPrashanth Swaminathan unsigned, unsigned *, void (*)(void), void *closure);
601*1fd5a2e1SPrashanth Swaminathan
602*1fd5a2e1SPrashanth Swaminathan /* Low level routine for calling N32 functions */
603*1fd5a2e1SPrashanth Swaminathan extern int ffi_call_N32(void (*)(char *, extended_cif *, int, int),
604*1fd5a2e1SPrashanth Swaminathan extended_cif *, unsigned,
605*1fd5a2e1SPrashanth Swaminathan unsigned, void *, void (*)(void), void *closure);
606*1fd5a2e1SPrashanth Swaminathan
ffi_call_int(ffi_cif * cif,void (* fn)(void),void * rvalue,void ** avalue,void * closure)607*1fd5a2e1SPrashanth Swaminathan void ffi_call_int(ffi_cif *cif, void (*fn)(void), void *rvalue,
608*1fd5a2e1SPrashanth Swaminathan void **avalue, void *closure)
609*1fd5a2e1SPrashanth Swaminathan {
610*1fd5a2e1SPrashanth Swaminathan extended_cif ecif;
611*1fd5a2e1SPrashanth Swaminathan
612*1fd5a2e1SPrashanth Swaminathan ecif.cif = cif;
613*1fd5a2e1SPrashanth Swaminathan ecif.avalue = avalue;
614*1fd5a2e1SPrashanth Swaminathan
615*1fd5a2e1SPrashanth Swaminathan /* If the return value is a struct and we don't have a return */
616*1fd5a2e1SPrashanth Swaminathan /* value address then we need to make one */
617*1fd5a2e1SPrashanth Swaminathan
618*1fd5a2e1SPrashanth Swaminathan if ((rvalue == NULL) &&
619*1fd5a2e1SPrashanth Swaminathan (cif->rtype->type == FFI_TYPE_STRUCT))
620*1fd5a2e1SPrashanth Swaminathan ecif.rvalue = alloca(cif->rtype->size);
621*1fd5a2e1SPrashanth Swaminathan else
622*1fd5a2e1SPrashanth Swaminathan ecif.rvalue = rvalue;
623*1fd5a2e1SPrashanth Swaminathan
624*1fd5a2e1SPrashanth Swaminathan switch (cif->abi)
625*1fd5a2e1SPrashanth Swaminathan {
626*1fd5a2e1SPrashanth Swaminathan #ifdef FFI_MIPS_O32
627*1fd5a2e1SPrashanth Swaminathan case FFI_O32:
628*1fd5a2e1SPrashanth Swaminathan case FFI_O32_SOFT_FLOAT:
629*1fd5a2e1SPrashanth Swaminathan ffi_call_O32(ffi_prep_args, &ecif, cif->bytes,
630*1fd5a2e1SPrashanth Swaminathan cif->flags, ecif.rvalue, fn, closure);
631*1fd5a2e1SPrashanth Swaminathan break;
632*1fd5a2e1SPrashanth Swaminathan #endif
633*1fd5a2e1SPrashanth Swaminathan
634*1fd5a2e1SPrashanth Swaminathan #ifdef FFI_MIPS_N32
635*1fd5a2e1SPrashanth Swaminathan case FFI_N32:
636*1fd5a2e1SPrashanth Swaminathan case FFI_N32_SOFT_FLOAT:
637*1fd5a2e1SPrashanth Swaminathan case FFI_N64:
638*1fd5a2e1SPrashanth Swaminathan case FFI_N64_SOFT_FLOAT:
639*1fd5a2e1SPrashanth Swaminathan {
640*1fd5a2e1SPrashanth Swaminathan int copy_rvalue = 0;
641*1fd5a2e1SPrashanth Swaminathan int copy_offset = 0;
642*1fd5a2e1SPrashanth Swaminathan char *rvalue_copy = ecif.rvalue;
643*1fd5a2e1SPrashanth Swaminathan if (cif->rtype->type == FFI_TYPE_STRUCT && cif->rtype->size < 16)
644*1fd5a2e1SPrashanth Swaminathan {
645*1fd5a2e1SPrashanth Swaminathan /* For structures smaller than 16 bytes we clobber memory
646*1fd5a2e1SPrashanth Swaminathan in 8 byte increments. Make a copy so we don't clobber
647*1fd5a2e1SPrashanth Swaminathan the callers memory outside of the struct bounds. */
648*1fd5a2e1SPrashanth Swaminathan rvalue_copy = alloca(16);
649*1fd5a2e1SPrashanth Swaminathan copy_rvalue = 1;
650*1fd5a2e1SPrashanth Swaminathan }
651*1fd5a2e1SPrashanth Swaminathan else if (cif->rtype->type == FFI_TYPE_FLOAT
652*1fd5a2e1SPrashanth Swaminathan && (cif->abi == FFI_N64_SOFT_FLOAT
653*1fd5a2e1SPrashanth Swaminathan || cif->abi == FFI_N32_SOFT_FLOAT))
654*1fd5a2e1SPrashanth Swaminathan {
655*1fd5a2e1SPrashanth Swaminathan rvalue_copy = alloca (8);
656*1fd5a2e1SPrashanth Swaminathan copy_rvalue = 1;
657*1fd5a2e1SPrashanth Swaminathan #if defined(__MIPSEB__) || defined(_MIPSEB)
658*1fd5a2e1SPrashanth Swaminathan copy_offset = 4;
659*1fd5a2e1SPrashanth Swaminathan #endif
660*1fd5a2e1SPrashanth Swaminathan }
661*1fd5a2e1SPrashanth Swaminathan ffi_call_N32(ffi_prep_args, &ecif, cif->bytes,
662*1fd5a2e1SPrashanth Swaminathan cif->flags, rvalue_copy, fn, closure);
663*1fd5a2e1SPrashanth Swaminathan if (copy_rvalue)
664*1fd5a2e1SPrashanth Swaminathan memcpy(ecif.rvalue, rvalue_copy + copy_offset, cif->rtype->size);
665*1fd5a2e1SPrashanth Swaminathan }
666*1fd5a2e1SPrashanth Swaminathan break;
667*1fd5a2e1SPrashanth Swaminathan #endif
668*1fd5a2e1SPrashanth Swaminathan
669*1fd5a2e1SPrashanth Swaminathan default:
670*1fd5a2e1SPrashanth Swaminathan FFI_ASSERT(0);
671*1fd5a2e1SPrashanth Swaminathan break;
672*1fd5a2e1SPrashanth Swaminathan }
673*1fd5a2e1SPrashanth Swaminathan }
674*1fd5a2e1SPrashanth Swaminathan
675*1fd5a2e1SPrashanth Swaminathan void
ffi_call(ffi_cif * cif,void (* fn)(void),void * rvalue,void ** avalue)676*1fd5a2e1SPrashanth Swaminathan ffi_call(ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue)
677*1fd5a2e1SPrashanth Swaminathan {
678*1fd5a2e1SPrashanth Swaminathan ffi_call_int (cif, fn, rvalue, avalue, NULL);
679*1fd5a2e1SPrashanth Swaminathan }
680*1fd5a2e1SPrashanth Swaminathan
681*1fd5a2e1SPrashanth Swaminathan void
ffi_call_go(ffi_cif * cif,void (* fn)(void),void * rvalue,void ** avalue,void * closure)682*1fd5a2e1SPrashanth Swaminathan ffi_call_go (ffi_cif *cif, void (*fn)(void), void *rvalue,
683*1fd5a2e1SPrashanth Swaminathan void **avalue, void *closure)
684*1fd5a2e1SPrashanth Swaminathan {
685*1fd5a2e1SPrashanth Swaminathan ffi_call_int (cif, fn, rvalue, avalue, closure);
686*1fd5a2e1SPrashanth Swaminathan }
687*1fd5a2e1SPrashanth Swaminathan
688*1fd5a2e1SPrashanth Swaminathan
689*1fd5a2e1SPrashanth Swaminathan #if FFI_CLOSURES
690*1fd5a2e1SPrashanth Swaminathan #if defined(FFI_MIPS_O32)
691*1fd5a2e1SPrashanth Swaminathan extern void ffi_closure_O32(void);
692*1fd5a2e1SPrashanth Swaminathan extern void ffi_go_closure_O32(void);
693*1fd5a2e1SPrashanth Swaminathan #else
694*1fd5a2e1SPrashanth Swaminathan extern void ffi_closure_N32(void);
695*1fd5a2e1SPrashanth Swaminathan extern void ffi_go_closure_N32(void);
696*1fd5a2e1SPrashanth Swaminathan #endif /* FFI_MIPS_O32 */
697*1fd5a2e1SPrashanth Swaminathan
698*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)699*1fd5a2e1SPrashanth Swaminathan ffi_prep_closure_loc (ffi_closure *closure,
700*1fd5a2e1SPrashanth Swaminathan ffi_cif *cif,
701*1fd5a2e1SPrashanth Swaminathan void (*fun)(ffi_cif*,void*,void**,void*),
702*1fd5a2e1SPrashanth Swaminathan void *user_data,
703*1fd5a2e1SPrashanth Swaminathan void *codeloc)
704*1fd5a2e1SPrashanth Swaminathan {
705*1fd5a2e1SPrashanth Swaminathan unsigned int *tramp = (unsigned int *) &closure->tramp[0];
706*1fd5a2e1SPrashanth Swaminathan void * fn;
707*1fd5a2e1SPrashanth Swaminathan char *clear_location = (char *) codeloc;
708*1fd5a2e1SPrashanth Swaminathan
709*1fd5a2e1SPrashanth Swaminathan #if defined(FFI_MIPS_O32)
710*1fd5a2e1SPrashanth Swaminathan if (cif->abi != FFI_O32 && cif->abi != FFI_O32_SOFT_FLOAT)
711*1fd5a2e1SPrashanth Swaminathan return FFI_BAD_ABI;
712*1fd5a2e1SPrashanth Swaminathan fn = ffi_closure_O32;
713*1fd5a2e1SPrashanth Swaminathan #else
714*1fd5a2e1SPrashanth Swaminathan #if _MIPS_SIM ==_ABIN32
715*1fd5a2e1SPrashanth Swaminathan if (cif->abi != FFI_N32
716*1fd5a2e1SPrashanth Swaminathan && cif->abi != FFI_N32_SOFT_FLOAT)
717*1fd5a2e1SPrashanth Swaminathan return FFI_BAD_ABI;
718*1fd5a2e1SPrashanth Swaminathan #else
719*1fd5a2e1SPrashanth Swaminathan if (cif->abi != FFI_N64
720*1fd5a2e1SPrashanth Swaminathan && cif->abi != FFI_N64_SOFT_FLOAT)
721*1fd5a2e1SPrashanth Swaminathan return FFI_BAD_ABI;
722*1fd5a2e1SPrashanth Swaminathan #endif
723*1fd5a2e1SPrashanth Swaminathan fn = ffi_closure_N32;
724*1fd5a2e1SPrashanth Swaminathan #endif /* FFI_MIPS_O32 */
725*1fd5a2e1SPrashanth Swaminathan
726*1fd5a2e1SPrashanth Swaminathan #if defined(FFI_MIPS_O32) || (_MIPS_SIM ==_ABIN32)
727*1fd5a2e1SPrashanth Swaminathan /* lui $25,high(fn) */
728*1fd5a2e1SPrashanth Swaminathan tramp[0] = 0x3c190000 | ((unsigned)fn >> 16);
729*1fd5a2e1SPrashanth Swaminathan /* ori $25,low(fn) */
730*1fd5a2e1SPrashanth Swaminathan tramp[1] = 0x37390000 | ((unsigned)fn & 0xffff);
731*1fd5a2e1SPrashanth Swaminathan /* lui $12,high(codeloc) */
732*1fd5a2e1SPrashanth Swaminathan tramp[2] = 0x3c0c0000 | ((unsigned)codeloc >> 16);
733*1fd5a2e1SPrashanth Swaminathan /* jr $25 */
734*1fd5a2e1SPrashanth Swaminathan #if !defined(__mips_isa_rev) || (__mips_isa_rev<6)
735*1fd5a2e1SPrashanth Swaminathan tramp[3] = 0x03200008;
736*1fd5a2e1SPrashanth Swaminathan #else
737*1fd5a2e1SPrashanth Swaminathan tramp[3] = 0x03200009;
738*1fd5a2e1SPrashanth Swaminathan #endif
739*1fd5a2e1SPrashanth Swaminathan /* ori $12,low(codeloc) */
740*1fd5a2e1SPrashanth Swaminathan tramp[4] = 0x358c0000 | ((unsigned)codeloc & 0xffff);
741*1fd5a2e1SPrashanth Swaminathan #else
742*1fd5a2e1SPrashanth Swaminathan /* N64 has a somewhat larger trampoline. */
743*1fd5a2e1SPrashanth Swaminathan /* lui $25,high(fn) */
744*1fd5a2e1SPrashanth Swaminathan tramp[0] = 0x3c190000 | ((unsigned long)fn >> 48);
745*1fd5a2e1SPrashanth Swaminathan /* lui $12,high(codeloc) */
746*1fd5a2e1SPrashanth Swaminathan tramp[1] = 0x3c0c0000 | ((unsigned long)codeloc >> 48);
747*1fd5a2e1SPrashanth Swaminathan /* ori $25,mid-high(fn) */
748*1fd5a2e1SPrashanth Swaminathan tramp[2] = 0x37390000 | (((unsigned long)fn >> 32 ) & 0xffff);
749*1fd5a2e1SPrashanth Swaminathan /* ori $12,mid-high(codeloc) */
750*1fd5a2e1SPrashanth Swaminathan tramp[3] = 0x358c0000 | (((unsigned long)codeloc >> 32) & 0xffff);
751*1fd5a2e1SPrashanth Swaminathan /* dsll $25,$25,16 */
752*1fd5a2e1SPrashanth Swaminathan tramp[4] = 0x0019cc38;
753*1fd5a2e1SPrashanth Swaminathan /* dsll $12,$12,16 */
754*1fd5a2e1SPrashanth Swaminathan tramp[5] = 0x000c6438;
755*1fd5a2e1SPrashanth Swaminathan /* ori $25,mid-low(fn) */
756*1fd5a2e1SPrashanth Swaminathan tramp[6] = 0x37390000 | (((unsigned long)fn >> 16 ) & 0xffff);
757*1fd5a2e1SPrashanth Swaminathan /* ori $12,mid-low(codeloc) */
758*1fd5a2e1SPrashanth Swaminathan tramp[7] = 0x358c0000 | (((unsigned long)codeloc >> 16) & 0xffff);
759*1fd5a2e1SPrashanth Swaminathan /* dsll $25,$25,16 */
760*1fd5a2e1SPrashanth Swaminathan tramp[8] = 0x0019cc38;
761*1fd5a2e1SPrashanth Swaminathan /* dsll $12,$12,16 */
762*1fd5a2e1SPrashanth Swaminathan tramp[9] = 0x000c6438;
763*1fd5a2e1SPrashanth Swaminathan /* ori $25,low(fn) */
764*1fd5a2e1SPrashanth Swaminathan tramp[10] = 0x37390000 | ((unsigned long)fn & 0xffff);
765*1fd5a2e1SPrashanth Swaminathan /* jr $25 */
766*1fd5a2e1SPrashanth Swaminathan #if !defined(__mips_isa_rev) || (__mips_isa_rev<6)
767*1fd5a2e1SPrashanth Swaminathan tramp[11] = 0x03200008;
768*1fd5a2e1SPrashanth Swaminathan #else
769*1fd5a2e1SPrashanth Swaminathan tramp[11] = 0x03200009;
770*1fd5a2e1SPrashanth Swaminathan #endif
771*1fd5a2e1SPrashanth Swaminathan /* ori $12,low(codeloc) */
772*1fd5a2e1SPrashanth Swaminathan tramp[12] = 0x358c0000 | ((unsigned long)codeloc & 0xffff);
773*1fd5a2e1SPrashanth Swaminathan
774*1fd5a2e1SPrashanth Swaminathan #endif
775*1fd5a2e1SPrashanth Swaminathan
776*1fd5a2e1SPrashanth Swaminathan closure->cif = cif;
777*1fd5a2e1SPrashanth Swaminathan closure->fun = fun;
778*1fd5a2e1SPrashanth Swaminathan closure->user_data = user_data;
779*1fd5a2e1SPrashanth Swaminathan
780*1fd5a2e1SPrashanth Swaminathan #ifdef USE__BUILTIN___CLEAR_CACHE
781*1fd5a2e1SPrashanth Swaminathan __builtin___clear_cache(clear_location, clear_location + FFI_TRAMPOLINE_SIZE);
782*1fd5a2e1SPrashanth Swaminathan #else
783*1fd5a2e1SPrashanth Swaminathan cacheflush (clear_location, FFI_TRAMPOLINE_SIZE, ICACHE);
784*1fd5a2e1SPrashanth Swaminathan #endif
785*1fd5a2e1SPrashanth Swaminathan return FFI_OK;
786*1fd5a2e1SPrashanth Swaminathan }
787*1fd5a2e1SPrashanth Swaminathan
788*1fd5a2e1SPrashanth Swaminathan /*
789*1fd5a2e1SPrashanth Swaminathan * Decodes the arguments to a function, which will be stored on the
790*1fd5a2e1SPrashanth Swaminathan * stack. AR is the pointer to the beginning of the integer arguments
791*1fd5a2e1SPrashanth Swaminathan * (and, depending upon the arguments, some floating-point arguments
792*1fd5a2e1SPrashanth Swaminathan * as well). FPR is a pointer to the area where floating point
793*1fd5a2e1SPrashanth Swaminathan * registers have been saved, if any.
794*1fd5a2e1SPrashanth Swaminathan *
795*1fd5a2e1SPrashanth Swaminathan * RVALUE is the location where the function return value will be
796*1fd5a2e1SPrashanth Swaminathan * stored. CLOSURE is the prepared closure to invoke.
797*1fd5a2e1SPrashanth Swaminathan *
798*1fd5a2e1SPrashanth Swaminathan * This function should only be called from assembly, which is in
799*1fd5a2e1SPrashanth Swaminathan * turn called from a trampoline.
800*1fd5a2e1SPrashanth Swaminathan *
801*1fd5a2e1SPrashanth Swaminathan * Returns the function return type.
802*1fd5a2e1SPrashanth Swaminathan *
803*1fd5a2e1SPrashanth Swaminathan * Based on the similar routine for sparc.
804*1fd5a2e1SPrashanth Swaminathan */
805*1fd5a2e1SPrashanth Swaminathan int
ffi_closure_mips_inner_O32(ffi_cif * cif,void (* fun)(ffi_cif *,void *,void **,void *),void * user_data,void * rvalue,ffi_arg * ar,double * fpr)806*1fd5a2e1SPrashanth Swaminathan ffi_closure_mips_inner_O32 (ffi_cif *cif,
807*1fd5a2e1SPrashanth Swaminathan void (*fun)(ffi_cif*, void*, void**, void*),
808*1fd5a2e1SPrashanth Swaminathan void *user_data,
809*1fd5a2e1SPrashanth Swaminathan void *rvalue, ffi_arg *ar,
810*1fd5a2e1SPrashanth Swaminathan double *fpr)
811*1fd5a2e1SPrashanth Swaminathan {
812*1fd5a2e1SPrashanth Swaminathan void **avaluep;
813*1fd5a2e1SPrashanth Swaminathan ffi_arg *avalue;
814*1fd5a2e1SPrashanth Swaminathan ffi_type **arg_types;
815*1fd5a2e1SPrashanth Swaminathan int i, avn, argn, seen_int;
816*1fd5a2e1SPrashanth Swaminathan
817*1fd5a2e1SPrashanth Swaminathan avalue = alloca (cif->nargs * sizeof (ffi_arg));
818*1fd5a2e1SPrashanth Swaminathan avaluep = alloca (cif->nargs * sizeof (ffi_arg));
819*1fd5a2e1SPrashanth Swaminathan
820*1fd5a2e1SPrashanth Swaminathan seen_int = (cif->abi == FFI_O32_SOFT_FLOAT) || (cif->mips_nfixedargs != cif->nargs);
821*1fd5a2e1SPrashanth Swaminathan argn = 0;
822*1fd5a2e1SPrashanth Swaminathan
823*1fd5a2e1SPrashanth Swaminathan if ((cif->flags >> (FFI_FLAG_BITS * 2)) == FFI_TYPE_STRUCT)
824*1fd5a2e1SPrashanth Swaminathan {
825*1fd5a2e1SPrashanth Swaminathan rvalue = (void *)(uintptr_t)ar[0];
826*1fd5a2e1SPrashanth Swaminathan argn = 1;
827*1fd5a2e1SPrashanth Swaminathan seen_int = 1;
828*1fd5a2e1SPrashanth Swaminathan }
829*1fd5a2e1SPrashanth Swaminathan
830*1fd5a2e1SPrashanth Swaminathan i = 0;
831*1fd5a2e1SPrashanth Swaminathan avn = cif->nargs;
832*1fd5a2e1SPrashanth Swaminathan arg_types = cif->arg_types;
833*1fd5a2e1SPrashanth Swaminathan
834*1fd5a2e1SPrashanth Swaminathan while (i < avn)
835*1fd5a2e1SPrashanth Swaminathan {
836*1fd5a2e1SPrashanth Swaminathan if (arg_types[i]->alignment == 8 && (argn & 0x1))
837*1fd5a2e1SPrashanth Swaminathan argn++;
838*1fd5a2e1SPrashanth Swaminathan if (i < 2 && !seen_int &&
839*1fd5a2e1SPrashanth Swaminathan (arg_types[i]->type == FFI_TYPE_FLOAT ||
840*1fd5a2e1SPrashanth Swaminathan arg_types[i]->type == FFI_TYPE_DOUBLE ||
841*1fd5a2e1SPrashanth Swaminathan arg_types[i]->type == FFI_TYPE_LONGDOUBLE))
842*1fd5a2e1SPrashanth Swaminathan {
843*1fd5a2e1SPrashanth Swaminathan #if defined(__MIPSEB__) || defined(_MIPSEB)
844*1fd5a2e1SPrashanth Swaminathan if (arg_types[i]->type == FFI_TYPE_FLOAT)
845*1fd5a2e1SPrashanth Swaminathan avaluep[i] = ((char *) &fpr[i]) + sizeof (float);
846*1fd5a2e1SPrashanth Swaminathan else
847*1fd5a2e1SPrashanth Swaminathan #endif
848*1fd5a2e1SPrashanth Swaminathan avaluep[i] = (char *) &fpr[i];
849*1fd5a2e1SPrashanth Swaminathan }
850*1fd5a2e1SPrashanth Swaminathan else
851*1fd5a2e1SPrashanth Swaminathan {
852*1fd5a2e1SPrashanth Swaminathan switch (arg_types[i]->type)
853*1fd5a2e1SPrashanth Swaminathan {
854*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_SINT8:
855*1fd5a2e1SPrashanth Swaminathan avaluep[i] = &avalue[i];
856*1fd5a2e1SPrashanth Swaminathan *(SINT8 *) &avalue[i] = (SINT8) ar[argn];
857*1fd5a2e1SPrashanth Swaminathan break;
858*1fd5a2e1SPrashanth Swaminathan
859*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_UINT8:
860*1fd5a2e1SPrashanth Swaminathan avaluep[i] = &avalue[i];
861*1fd5a2e1SPrashanth Swaminathan *(UINT8 *) &avalue[i] = (UINT8) ar[argn];
862*1fd5a2e1SPrashanth Swaminathan break;
863*1fd5a2e1SPrashanth Swaminathan
864*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_SINT16:
865*1fd5a2e1SPrashanth Swaminathan avaluep[i] = &avalue[i];
866*1fd5a2e1SPrashanth Swaminathan *(SINT16 *) &avalue[i] = (SINT16) ar[argn];
867*1fd5a2e1SPrashanth Swaminathan break;
868*1fd5a2e1SPrashanth Swaminathan
869*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_UINT16:
870*1fd5a2e1SPrashanth Swaminathan avaluep[i] = &avalue[i];
871*1fd5a2e1SPrashanth Swaminathan *(UINT16 *) &avalue[i] = (UINT16) ar[argn];
872*1fd5a2e1SPrashanth Swaminathan break;
873*1fd5a2e1SPrashanth Swaminathan
874*1fd5a2e1SPrashanth Swaminathan default:
875*1fd5a2e1SPrashanth Swaminathan avaluep[i] = (char *) &ar[argn];
876*1fd5a2e1SPrashanth Swaminathan break;
877*1fd5a2e1SPrashanth Swaminathan }
878*1fd5a2e1SPrashanth Swaminathan seen_int = 1;
879*1fd5a2e1SPrashanth Swaminathan }
880*1fd5a2e1SPrashanth Swaminathan argn += FFI_ALIGN(arg_types[i]->size, FFI_SIZEOF_ARG) / FFI_SIZEOF_ARG;
881*1fd5a2e1SPrashanth Swaminathan i++;
882*1fd5a2e1SPrashanth Swaminathan }
883*1fd5a2e1SPrashanth Swaminathan
884*1fd5a2e1SPrashanth Swaminathan /* Invoke the closure. */
885*1fd5a2e1SPrashanth Swaminathan fun(cif, rvalue, avaluep, user_data);
886*1fd5a2e1SPrashanth Swaminathan
887*1fd5a2e1SPrashanth Swaminathan if (cif->abi == FFI_O32_SOFT_FLOAT)
888*1fd5a2e1SPrashanth Swaminathan {
889*1fd5a2e1SPrashanth Swaminathan switch (cif->rtype->type)
890*1fd5a2e1SPrashanth Swaminathan {
891*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_FLOAT:
892*1fd5a2e1SPrashanth Swaminathan return FFI_TYPE_INT;
893*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_DOUBLE:
894*1fd5a2e1SPrashanth Swaminathan return FFI_TYPE_UINT64;
895*1fd5a2e1SPrashanth Swaminathan default:
896*1fd5a2e1SPrashanth Swaminathan return cif->rtype->type;
897*1fd5a2e1SPrashanth Swaminathan }
898*1fd5a2e1SPrashanth Swaminathan }
899*1fd5a2e1SPrashanth Swaminathan else
900*1fd5a2e1SPrashanth Swaminathan {
901*1fd5a2e1SPrashanth Swaminathan return cif->rtype->type;
902*1fd5a2e1SPrashanth Swaminathan }
903*1fd5a2e1SPrashanth Swaminathan }
904*1fd5a2e1SPrashanth Swaminathan
905*1fd5a2e1SPrashanth Swaminathan #if defined(FFI_MIPS_N32)
906*1fd5a2e1SPrashanth Swaminathan
907*1fd5a2e1SPrashanth Swaminathan static void
copy_struct_N32(char * target,unsigned offset,ffi_abi abi,ffi_type * type,int argn,unsigned arg_offset,ffi_arg * ar,ffi_arg * fpr,int soft_float)908*1fd5a2e1SPrashanth Swaminathan copy_struct_N32(char *target, unsigned offset, ffi_abi abi, ffi_type *type,
909*1fd5a2e1SPrashanth Swaminathan int argn, unsigned arg_offset, ffi_arg *ar,
910*1fd5a2e1SPrashanth Swaminathan ffi_arg *fpr, int soft_float)
911*1fd5a2e1SPrashanth Swaminathan {
912*1fd5a2e1SPrashanth Swaminathan ffi_type **elt_typep = type->elements;
913*1fd5a2e1SPrashanth Swaminathan while(*elt_typep)
914*1fd5a2e1SPrashanth Swaminathan {
915*1fd5a2e1SPrashanth Swaminathan ffi_type *elt_type = *elt_typep;
916*1fd5a2e1SPrashanth Swaminathan unsigned o;
917*1fd5a2e1SPrashanth Swaminathan char *tp;
918*1fd5a2e1SPrashanth Swaminathan char *argp;
919*1fd5a2e1SPrashanth Swaminathan char *fpp;
920*1fd5a2e1SPrashanth Swaminathan
921*1fd5a2e1SPrashanth Swaminathan o = FFI_ALIGN(offset, elt_type->alignment);
922*1fd5a2e1SPrashanth Swaminathan arg_offset += o - offset;
923*1fd5a2e1SPrashanth Swaminathan offset = o;
924*1fd5a2e1SPrashanth Swaminathan argn += arg_offset / sizeof(ffi_arg);
925*1fd5a2e1SPrashanth Swaminathan arg_offset = arg_offset % sizeof(ffi_arg);
926*1fd5a2e1SPrashanth Swaminathan
927*1fd5a2e1SPrashanth Swaminathan argp = (char *)(ar + argn);
928*1fd5a2e1SPrashanth Swaminathan fpp = (char *)(argn >= 8 ? ar + argn : fpr + argn);
929*1fd5a2e1SPrashanth Swaminathan
930*1fd5a2e1SPrashanth Swaminathan tp = target + offset;
931*1fd5a2e1SPrashanth Swaminathan
932*1fd5a2e1SPrashanth Swaminathan if (elt_type->type == FFI_TYPE_DOUBLE && !soft_float)
933*1fd5a2e1SPrashanth Swaminathan *(double *)tp = *(double *)fpp;
934*1fd5a2e1SPrashanth Swaminathan else
935*1fd5a2e1SPrashanth Swaminathan memcpy(tp, argp + arg_offset, elt_type->size);
936*1fd5a2e1SPrashanth Swaminathan
937*1fd5a2e1SPrashanth Swaminathan offset += elt_type->size;
938*1fd5a2e1SPrashanth Swaminathan arg_offset += elt_type->size;
939*1fd5a2e1SPrashanth Swaminathan elt_typep++;
940*1fd5a2e1SPrashanth Swaminathan argn += arg_offset / sizeof(ffi_arg);
941*1fd5a2e1SPrashanth Swaminathan arg_offset = arg_offset % sizeof(ffi_arg);
942*1fd5a2e1SPrashanth Swaminathan }
943*1fd5a2e1SPrashanth Swaminathan }
944*1fd5a2e1SPrashanth Swaminathan
945*1fd5a2e1SPrashanth Swaminathan /*
946*1fd5a2e1SPrashanth Swaminathan * Decodes the arguments to a function, which will be stored on the
947*1fd5a2e1SPrashanth Swaminathan * stack. AR is the pointer to the beginning of the integer
948*1fd5a2e1SPrashanth Swaminathan * arguments. FPR is a pointer to the area where floating point
949*1fd5a2e1SPrashanth Swaminathan * registers have been saved.
950*1fd5a2e1SPrashanth Swaminathan *
951*1fd5a2e1SPrashanth Swaminathan * RVALUE is the location where the function return value will be
952*1fd5a2e1SPrashanth Swaminathan * stored. CLOSURE is the prepared closure to invoke.
953*1fd5a2e1SPrashanth Swaminathan *
954*1fd5a2e1SPrashanth Swaminathan * This function should only be called from assembly, which is in
955*1fd5a2e1SPrashanth Swaminathan * turn called from a trampoline.
956*1fd5a2e1SPrashanth Swaminathan *
957*1fd5a2e1SPrashanth Swaminathan * Returns the function return flags.
958*1fd5a2e1SPrashanth Swaminathan *
959*1fd5a2e1SPrashanth Swaminathan */
960*1fd5a2e1SPrashanth Swaminathan int
ffi_closure_mips_inner_N32(ffi_cif * cif,void (* fun)(ffi_cif *,void *,void **,void *),void * user_data,void * rvalue,ffi_arg * ar,ffi_arg * fpr)961*1fd5a2e1SPrashanth Swaminathan ffi_closure_mips_inner_N32 (ffi_cif *cif,
962*1fd5a2e1SPrashanth Swaminathan void (*fun)(ffi_cif*, void*, void**, void*),
963*1fd5a2e1SPrashanth Swaminathan void *user_data,
964*1fd5a2e1SPrashanth Swaminathan void *rvalue, ffi_arg *ar,
965*1fd5a2e1SPrashanth Swaminathan ffi_arg *fpr)
966*1fd5a2e1SPrashanth Swaminathan {
967*1fd5a2e1SPrashanth Swaminathan void **avaluep;
968*1fd5a2e1SPrashanth Swaminathan ffi_arg *avalue;
969*1fd5a2e1SPrashanth Swaminathan ffi_type **arg_types;
970*1fd5a2e1SPrashanth Swaminathan int i, avn, argn;
971*1fd5a2e1SPrashanth Swaminathan int soft_float;
972*1fd5a2e1SPrashanth Swaminathan ffi_arg *argp;
973*1fd5a2e1SPrashanth Swaminathan
974*1fd5a2e1SPrashanth Swaminathan soft_float = cif->abi == FFI_N64_SOFT_FLOAT
975*1fd5a2e1SPrashanth Swaminathan || cif->abi == FFI_N32_SOFT_FLOAT;
976*1fd5a2e1SPrashanth Swaminathan avalue = alloca (cif->nargs * sizeof (ffi_arg));
977*1fd5a2e1SPrashanth Swaminathan avaluep = alloca (cif->nargs * sizeof (ffi_arg));
978*1fd5a2e1SPrashanth Swaminathan
979*1fd5a2e1SPrashanth Swaminathan argn = 0;
980*1fd5a2e1SPrashanth Swaminathan
981*1fd5a2e1SPrashanth Swaminathan if (cif->rstruct_flag)
982*1fd5a2e1SPrashanth Swaminathan {
983*1fd5a2e1SPrashanth Swaminathan #if _MIPS_SIM==_ABIN32
984*1fd5a2e1SPrashanth Swaminathan rvalue = (void *)(UINT32)ar[0];
985*1fd5a2e1SPrashanth Swaminathan #else /* N64 */
986*1fd5a2e1SPrashanth Swaminathan rvalue = (void *)ar[0];
987*1fd5a2e1SPrashanth Swaminathan #endif
988*1fd5a2e1SPrashanth Swaminathan argn = 1;
989*1fd5a2e1SPrashanth Swaminathan }
990*1fd5a2e1SPrashanth Swaminathan
991*1fd5a2e1SPrashanth Swaminathan i = 0;
992*1fd5a2e1SPrashanth Swaminathan avn = cif->nargs;
993*1fd5a2e1SPrashanth Swaminathan arg_types = cif->arg_types;
994*1fd5a2e1SPrashanth Swaminathan
995*1fd5a2e1SPrashanth Swaminathan while (i < avn)
996*1fd5a2e1SPrashanth Swaminathan {
997*1fd5a2e1SPrashanth Swaminathan if (arg_types[i]->type == FFI_TYPE_FLOAT
998*1fd5a2e1SPrashanth Swaminathan || arg_types[i]->type == FFI_TYPE_DOUBLE
999*1fd5a2e1SPrashanth Swaminathan || arg_types[i]->type == FFI_TYPE_LONGDOUBLE)
1000*1fd5a2e1SPrashanth Swaminathan {
1001*1fd5a2e1SPrashanth Swaminathan argp = (argn >= 8 || i >= cif->mips_nfixedargs || soft_float) ? ar + argn : fpr + argn;
1002*1fd5a2e1SPrashanth Swaminathan if ((arg_types[i]->type == FFI_TYPE_LONGDOUBLE) && ((uintptr_t)argp & (arg_types[i]->alignment-1)))
1003*1fd5a2e1SPrashanth Swaminathan {
1004*1fd5a2e1SPrashanth Swaminathan argp=(ffi_arg*)FFI_ALIGN(argp,arg_types[i]->alignment);
1005*1fd5a2e1SPrashanth Swaminathan argn++;
1006*1fd5a2e1SPrashanth Swaminathan }
1007*1fd5a2e1SPrashanth Swaminathan #if defined(__MIPSEB__) || defined(_MIPSEB)
1008*1fd5a2e1SPrashanth Swaminathan if (arg_types[i]->type == FFI_TYPE_FLOAT && argn < 8)
1009*1fd5a2e1SPrashanth Swaminathan avaluep[i] = ((char *) argp) + sizeof (float);
1010*1fd5a2e1SPrashanth Swaminathan else
1011*1fd5a2e1SPrashanth Swaminathan #endif
1012*1fd5a2e1SPrashanth Swaminathan avaluep[i] = (char *) argp;
1013*1fd5a2e1SPrashanth Swaminathan }
1014*1fd5a2e1SPrashanth Swaminathan else
1015*1fd5a2e1SPrashanth Swaminathan {
1016*1fd5a2e1SPrashanth Swaminathan unsigned type = arg_types[i]->type;
1017*1fd5a2e1SPrashanth Swaminathan
1018*1fd5a2e1SPrashanth Swaminathan if (arg_types[i]->alignment > sizeof(ffi_arg))
1019*1fd5a2e1SPrashanth Swaminathan argn = FFI_ALIGN(argn, arg_types[i]->alignment / sizeof(ffi_arg));
1020*1fd5a2e1SPrashanth Swaminathan
1021*1fd5a2e1SPrashanth Swaminathan argp = ar + argn;
1022*1fd5a2e1SPrashanth Swaminathan
1023*1fd5a2e1SPrashanth Swaminathan /* The size of a pointer depends on the ABI */
1024*1fd5a2e1SPrashanth Swaminathan if (type == FFI_TYPE_POINTER)
1025*1fd5a2e1SPrashanth Swaminathan type = (cif->abi == FFI_N64 || cif->abi == FFI_N64_SOFT_FLOAT)
1026*1fd5a2e1SPrashanth Swaminathan ? FFI_TYPE_SINT64 : FFI_TYPE_SINT32;
1027*1fd5a2e1SPrashanth Swaminathan
1028*1fd5a2e1SPrashanth Swaminathan if (soft_float && type == FFI_TYPE_FLOAT)
1029*1fd5a2e1SPrashanth Swaminathan type = FFI_TYPE_UINT32;
1030*1fd5a2e1SPrashanth Swaminathan
1031*1fd5a2e1SPrashanth Swaminathan switch (type)
1032*1fd5a2e1SPrashanth Swaminathan {
1033*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_SINT8:
1034*1fd5a2e1SPrashanth Swaminathan avaluep[i] = &avalue[i];
1035*1fd5a2e1SPrashanth Swaminathan *(SINT8 *) &avalue[i] = (SINT8) *argp;
1036*1fd5a2e1SPrashanth Swaminathan break;
1037*1fd5a2e1SPrashanth Swaminathan
1038*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_UINT8:
1039*1fd5a2e1SPrashanth Swaminathan avaluep[i] = &avalue[i];
1040*1fd5a2e1SPrashanth Swaminathan *(UINT8 *) &avalue[i] = (UINT8) *argp;
1041*1fd5a2e1SPrashanth Swaminathan break;
1042*1fd5a2e1SPrashanth Swaminathan
1043*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_SINT16:
1044*1fd5a2e1SPrashanth Swaminathan avaluep[i] = &avalue[i];
1045*1fd5a2e1SPrashanth Swaminathan *(SINT16 *) &avalue[i] = (SINT16) *argp;
1046*1fd5a2e1SPrashanth Swaminathan break;
1047*1fd5a2e1SPrashanth Swaminathan
1048*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_UINT16:
1049*1fd5a2e1SPrashanth Swaminathan avaluep[i] = &avalue[i];
1050*1fd5a2e1SPrashanth Swaminathan *(UINT16 *) &avalue[i] = (UINT16) *argp;
1051*1fd5a2e1SPrashanth Swaminathan break;
1052*1fd5a2e1SPrashanth Swaminathan
1053*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_SINT32:
1054*1fd5a2e1SPrashanth Swaminathan avaluep[i] = &avalue[i];
1055*1fd5a2e1SPrashanth Swaminathan *(SINT32 *) &avalue[i] = (SINT32) *argp;
1056*1fd5a2e1SPrashanth Swaminathan break;
1057*1fd5a2e1SPrashanth Swaminathan
1058*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_UINT32:
1059*1fd5a2e1SPrashanth Swaminathan avaluep[i] = &avalue[i];
1060*1fd5a2e1SPrashanth Swaminathan *(UINT32 *) &avalue[i] = (UINT32) *argp;
1061*1fd5a2e1SPrashanth Swaminathan break;
1062*1fd5a2e1SPrashanth Swaminathan
1063*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_STRUCT:
1064*1fd5a2e1SPrashanth Swaminathan if (argn < 8)
1065*1fd5a2e1SPrashanth Swaminathan {
1066*1fd5a2e1SPrashanth Swaminathan /* Allocate space for the struct as at least part of
1067*1fd5a2e1SPrashanth Swaminathan it was passed in registers. */
1068*1fd5a2e1SPrashanth Swaminathan avaluep[i] = alloca(arg_types[i]->size);
1069*1fd5a2e1SPrashanth Swaminathan copy_struct_N32(avaluep[i], 0, cif->abi, arg_types[i],
1070*1fd5a2e1SPrashanth Swaminathan argn, 0, ar, fpr, i >= cif->mips_nfixedargs || soft_float);
1071*1fd5a2e1SPrashanth Swaminathan
1072*1fd5a2e1SPrashanth Swaminathan break;
1073*1fd5a2e1SPrashanth Swaminathan }
1074*1fd5a2e1SPrashanth Swaminathan /* Else fall through. */
1075*1fd5a2e1SPrashanth Swaminathan default:
1076*1fd5a2e1SPrashanth Swaminathan avaluep[i] = (char *) argp;
1077*1fd5a2e1SPrashanth Swaminathan break;
1078*1fd5a2e1SPrashanth Swaminathan }
1079*1fd5a2e1SPrashanth Swaminathan }
1080*1fd5a2e1SPrashanth Swaminathan argn += FFI_ALIGN(arg_types[i]->size, sizeof(ffi_arg)) / sizeof(ffi_arg);
1081*1fd5a2e1SPrashanth Swaminathan i++;
1082*1fd5a2e1SPrashanth Swaminathan }
1083*1fd5a2e1SPrashanth Swaminathan
1084*1fd5a2e1SPrashanth Swaminathan /* Invoke the closure. */
1085*1fd5a2e1SPrashanth Swaminathan fun (cif, rvalue, avaluep, user_data);
1086*1fd5a2e1SPrashanth Swaminathan
1087*1fd5a2e1SPrashanth Swaminathan return cif->flags >> (FFI_FLAG_BITS * 8);
1088*1fd5a2e1SPrashanth Swaminathan }
1089*1fd5a2e1SPrashanth Swaminathan
1090*1fd5a2e1SPrashanth Swaminathan #endif /* FFI_MIPS_N32 */
1091*1fd5a2e1SPrashanth Swaminathan
1092*1fd5a2e1SPrashanth Swaminathan #if defined(FFI_MIPS_O32)
1093*1fd5a2e1SPrashanth Swaminathan extern void ffi_closure_O32(void);
1094*1fd5a2e1SPrashanth Swaminathan extern void ffi_go_closure_O32(void);
1095*1fd5a2e1SPrashanth Swaminathan #else
1096*1fd5a2e1SPrashanth Swaminathan extern void ffi_closure_N32(void);
1097*1fd5a2e1SPrashanth Swaminathan extern void ffi_go_closure_N32(void);
1098*1fd5a2e1SPrashanth Swaminathan #endif /* FFI_MIPS_O32 */
1099*1fd5a2e1SPrashanth Swaminathan
1100*1fd5a2e1SPrashanth Swaminathan ffi_status
ffi_prep_go_closure(ffi_go_closure * closure,ffi_cif * cif,void (* fun)(ffi_cif *,void *,void **,void *))1101*1fd5a2e1SPrashanth Swaminathan ffi_prep_go_closure (ffi_go_closure* closure, ffi_cif* cif,
1102*1fd5a2e1SPrashanth Swaminathan void (*fun)(ffi_cif*,void*,void**,void*))
1103*1fd5a2e1SPrashanth Swaminathan {
1104*1fd5a2e1SPrashanth Swaminathan void * fn;
1105*1fd5a2e1SPrashanth Swaminathan
1106*1fd5a2e1SPrashanth Swaminathan #if defined(FFI_MIPS_O32)
1107*1fd5a2e1SPrashanth Swaminathan if (cif->abi != FFI_O32 && cif->abi != FFI_O32_SOFT_FLOAT)
1108*1fd5a2e1SPrashanth Swaminathan return FFI_BAD_ABI;
1109*1fd5a2e1SPrashanth Swaminathan fn = ffi_go_closure_O32;
1110*1fd5a2e1SPrashanth Swaminathan #else
1111*1fd5a2e1SPrashanth Swaminathan #if _MIPS_SIM ==_ABIN32
1112*1fd5a2e1SPrashanth Swaminathan if (cif->abi != FFI_N32
1113*1fd5a2e1SPrashanth Swaminathan && cif->abi != FFI_N32_SOFT_FLOAT)
1114*1fd5a2e1SPrashanth Swaminathan return FFI_BAD_ABI;
1115*1fd5a2e1SPrashanth Swaminathan #else
1116*1fd5a2e1SPrashanth Swaminathan if (cif->abi != FFI_N64
1117*1fd5a2e1SPrashanth Swaminathan && cif->abi != FFI_N64_SOFT_FLOAT)
1118*1fd5a2e1SPrashanth Swaminathan return FFI_BAD_ABI;
1119*1fd5a2e1SPrashanth Swaminathan #endif
1120*1fd5a2e1SPrashanth Swaminathan fn = ffi_go_closure_N32;
1121*1fd5a2e1SPrashanth Swaminathan #endif /* FFI_MIPS_O32 */
1122*1fd5a2e1SPrashanth Swaminathan
1123*1fd5a2e1SPrashanth Swaminathan closure->tramp = (void *)fn;
1124*1fd5a2e1SPrashanth Swaminathan closure->cif = cif;
1125*1fd5a2e1SPrashanth Swaminathan closure->fun = fun;
1126*1fd5a2e1SPrashanth Swaminathan
1127*1fd5a2e1SPrashanth Swaminathan return FFI_OK;
1128*1fd5a2e1SPrashanth Swaminathan }
1129*1fd5a2e1SPrashanth Swaminathan
1130*1fd5a2e1SPrashanth Swaminathan #endif /* FFI_CLOSURES */
1131