xref: /aosp_15_r20/external/libffi/src/mips/ffi.c (revision 1fd5a2e1d639cd1ddf29dd0c484c123bbd850c21)
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