xref: /aosp_15_r20/external/libffi/src/sh/ffi.c (revision 1fd5a2e1d639cd1ddf29dd0c484c123bbd850c21)
1*1fd5a2e1SPrashanth Swaminathan /* -----------------------------------------------------------------------
2*1fd5a2e1SPrashanth Swaminathan    ffi.c - Copyright (c) 2002-2008, 2012 Kaz Kojima
3*1fd5a2e1SPrashanth Swaminathan            Copyright (c) 2008 Red Hat, Inc.
4*1fd5a2e1SPrashanth Swaminathan 
5*1fd5a2e1SPrashanth Swaminathan    SuperH Foreign Function Interface
6*1fd5a2e1SPrashanth Swaminathan 
7*1fd5a2e1SPrashanth Swaminathan    Permission is hereby granted, free of charge, to any person obtaining
8*1fd5a2e1SPrashanth Swaminathan    a copy of this software and associated documentation files (the
9*1fd5a2e1SPrashanth Swaminathan    ``Software''), to deal in the Software without restriction, including
10*1fd5a2e1SPrashanth Swaminathan    without limitation the rights to use, copy, modify, merge, publish,
11*1fd5a2e1SPrashanth Swaminathan    distribute, sublicense, and/or sell copies of the Software, and to
12*1fd5a2e1SPrashanth Swaminathan    permit persons to whom the Software is furnished to do so, subject to
13*1fd5a2e1SPrashanth Swaminathan    the following conditions:
14*1fd5a2e1SPrashanth Swaminathan 
15*1fd5a2e1SPrashanth Swaminathan    The above copyright notice and this permission notice shall be included
16*1fd5a2e1SPrashanth Swaminathan    in all copies or substantial portions of the Software.
17*1fd5a2e1SPrashanth Swaminathan 
18*1fd5a2e1SPrashanth Swaminathan    THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND,
19*1fd5a2e1SPrashanth Swaminathan    EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20*1fd5a2e1SPrashanth Swaminathan    MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
21*1fd5a2e1SPrashanth Swaminathan    NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
22*1fd5a2e1SPrashanth Swaminathan    HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
23*1fd5a2e1SPrashanth Swaminathan    WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24*1fd5a2e1SPrashanth Swaminathan    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
25*1fd5a2e1SPrashanth Swaminathan    DEALINGS IN THE SOFTWARE.
26*1fd5a2e1SPrashanth Swaminathan    ----------------------------------------------------------------------- */
27*1fd5a2e1SPrashanth Swaminathan 
28*1fd5a2e1SPrashanth Swaminathan #include <ffi.h>
29*1fd5a2e1SPrashanth Swaminathan #include <ffi_common.h>
30*1fd5a2e1SPrashanth Swaminathan 
31*1fd5a2e1SPrashanth Swaminathan #include <stdlib.h>
32*1fd5a2e1SPrashanth Swaminathan 
33*1fd5a2e1SPrashanth Swaminathan #define NGREGARG 4
34*1fd5a2e1SPrashanth Swaminathan #if defined(__SH4__)
35*1fd5a2e1SPrashanth Swaminathan #define NFREGARG 8
36*1fd5a2e1SPrashanth Swaminathan #endif
37*1fd5a2e1SPrashanth Swaminathan 
38*1fd5a2e1SPrashanth Swaminathan #if defined(__HITACHI__)
39*1fd5a2e1SPrashanth Swaminathan #define STRUCT_VALUE_ADDRESS_WITH_ARG 1
40*1fd5a2e1SPrashanth Swaminathan #else
41*1fd5a2e1SPrashanth Swaminathan #define STRUCT_VALUE_ADDRESS_WITH_ARG 0
42*1fd5a2e1SPrashanth Swaminathan #endif
43*1fd5a2e1SPrashanth Swaminathan 
44*1fd5a2e1SPrashanth Swaminathan /* If the structure has essentially an unique element, return its type.  */
45*1fd5a2e1SPrashanth Swaminathan static int
simple_type(ffi_type * arg)46*1fd5a2e1SPrashanth Swaminathan simple_type (ffi_type *arg)
47*1fd5a2e1SPrashanth Swaminathan {
48*1fd5a2e1SPrashanth Swaminathan   if (arg->type != FFI_TYPE_STRUCT)
49*1fd5a2e1SPrashanth Swaminathan     return arg->type;
50*1fd5a2e1SPrashanth Swaminathan   else if (arg->elements[1])
51*1fd5a2e1SPrashanth Swaminathan     return FFI_TYPE_STRUCT;
52*1fd5a2e1SPrashanth Swaminathan 
53*1fd5a2e1SPrashanth Swaminathan   return simple_type (arg->elements[0]);
54*1fd5a2e1SPrashanth Swaminathan }
55*1fd5a2e1SPrashanth Swaminathan 
56*1fd5a2e1SPrashanth Swaminathan static int
return_type(ffi_type * arg)57*1fd5a2e1SPrashanth Swaminathan return_type (ffi_type *arg)
58*1fd5a2e1SPrashanth Swaminathan {
59*1fd5a2e1SPrashanth Swaminathan   unsigned short type;
60*1fd5a2e1SPrashanth Swaminathan 
61*1fd5a2e1SPrashanth Swaminathan   if (arg->type != FFI_TYPE_STRUCT)
62*1fd5a2e1SPrashanth Swaminathan     return arg->type;
63*1fd5a2e1SPrashanth Swaminathan 
64*1fd5a2e1SPrashanth Swaminathan   type = simple_type (arg->elements[0]);
65*1fd5a2e1SPrashanth Swaminathan   if (! arg->elements[1])
66*1fd5a2e1SPrashanth Swaminathan     {
67*1fd5a2e1SPrashanth Swaminathan       switch (type)
68*1fd5a2e1SPrashanth Swaminathan 	{
69*1fd5a2e1SPrashanth Swaminathan 	case FFI_TYPE_SINT8:
70*1fd5a2e1SPrashanth Swaminathan 	case FFI_TYPE_UINT8:
71*1fd5a2e1SPrashanth Swaminathan 	case FFI_TYPE_SINT16:
72*1fd5a2e1SPrashanth Swaminathan 	case FFI_TYPE_UINT16:
73*1fd5a2e1SPrashanth Swaminathan 	case FFI_TYPE_SINT32:
74*1fd5a2e1SPrashanth Swaminathan 	case FFI_TYPE_UINT32:
75*1fd5a2e1SPrashanth Swaminathan 	  return FFI_TYPE_INT;
76*1fd5a2e1SPrashanth Swaminathan 
77*1fd5a2e1SPrashanth Swaminathan 	default:
78*1fd5a2e1SPrashanth Swaminathan 	  return type;
79*1fd5a2e1SPrashanth Swaminathan 	}
80*1fd5a2e1SPrashanth Swaminathan     }
81*1fd5a2e1SPrashanth Swaminathan 
82*1fd5a2e1SPrashanth Swaminathan   /* gcc uses r0/r1 pair for some kind of structures.  */
83*1fd5a2e1SPrashanth Swaminathan   if (arg->size <= 2 * sizeof (int))
84*1fd5a2e1SPrashanth Swaminathan     {
85*1fd5a2e1SPrashanth Swaminathan       int i = 0;
86*1fd5a2e1SPrashanth Swaminathan       ffi_type *e;
87*1fd5a2e1SPrashanth Swaminathan 
88*1fd5a2e1SPrashanth Swaminathan       while ((e = arg->elements[i++]))
89*1fd5a2e1SPrashanth Swaminathan 	{
90*1fd5a2e1SPrashanth Swaminathan 	  type = simple_type (e);
91*1fd5a2e1SPrashanth Swaminathan 	  switch (type)
92*1fd5a2e1SPrashanth Swaminathan 	    {
93*1fd5a2e1SPrashanth Swaminathan 	    case FFI_TYPE_SINT32:
94*1fd5a2e1SPrashanth Swaminathan 	    case FFI_TYPE_UINT32:
95*1fd5a2e1SPrashanth Swaminathan 	    case FFI_TYPE_INT:
96*1fd5a2e1SPrashanth Swaminathan 	    case FFI_TYPE_FLOAT:
97*1fd5a2e1SPrashanth Swaminathan 	      return FFI_TYPE_UINT64;
98*1fd5a2e1SPrashanth Swaminathan 
99*1fd5a2e1SPrashanth Swaminathan 	    default:
100*1fd5a2e1SPrashanth Swaminathan 	      break;
101*1fd5a2e1SPrashanth Swaminathan 	    }
102*1fd5a2e1SPrashanth Swaminathan 	}
103*1fd5a2e1SPrashanth Swaminathan     }
104*1fd5a2e1SPrashanth Swaminathan 
105*1fd5a2e1SPrashanth Swaminathan   return FFI_TYPE_STRUCT;
106*1fd5a2e1SPrashanth Swaminathan }
107*1fd5a2e1SPrashanth Swaminathan 
108*1fd5a2e1SPrashanth Swaminathan /* ffi_prep_args is called by the assembly routine once stack space
109*1fd5a2e1SPrashanth Swaminathan    has been allocated for the function's arguments */
110*1fd5a2e1SPrashanth Swaminathan 
ffi_prep_args(char * stack,extended_cif * ecif)111*1fd5a2e1SPrashanth Swaminathan void ffi_prep_args(char *stack, extended_cif *ecif)
112*1fd5a2e1SPrashanth Swaminathan {
113*1fd5a2e1SPrashanth Swaminathan   register unsigned int i;
114*1fd5a2e1SPrashanth Swaminathan   register int tmp;
115*1fd5a2e1SPrashanth Swaminathan   register unsigned int avn;
116*1fd5a2e1SPrashanth Swaminathan   register void **p_argv;
117*1fd5a2e1SPrashanth Swaminathan   register char *argp;
118*1fd5a2e1SPrashanth Swaminathan   register ffi_type **p_arg;
119*1fd5a2e1SPrashanth Swaminathan   int greg, ireg;
120*1fd5a2e1SPrashanth Swaminathan #if defined(__SH4__)
121*1fd5a2e1SPrashanth Swaminathan   int freg = 0;
122*1fd5a2e1SPrashanth Swaminathan #endif
123*1fd5a2e1SPrashanth Swaminathan 
124*1fd5a2e1SPrashanth Swaminathan   tmp = 0;
125*1fd5a2e1SPrashanth Swaminathan   argp = stack;
126*1fd5a2e1SPrashanth Swaminathan 
127*1fd5a2e1SPrashanth Swaminathan   if (return_type (ecif->cif->rtype) == FFI_TYPE_STRUCT)
128*1fd5a2e1SPrashanth Swaminathan     {
129*1fd5a2e1SPrashanth Swaminathan       *(void **) argp = ecif->rvalue;
130*1fd5a2e1SPrashanth Swaminathan       argp += 4;
131*1fd5a2e1SPrashanth Swaminathan       ireg = STRUCT_VALUE_ADDRESS_WITH_ARG ? 1 : 0;
132*1fd5a2e1SPrashanth Swaminathan     }
133*1fd5a2e1SPrashanth Swaminathan   else
134*1fd5a2e1SPrashanth Swaminathan     ireg = 0;
135*1fd5a2e1SPrashanth Swaminathan 
136*1fd5a2e1SPrashanth Swaminathan   /* Set arguments for registers.  */
137*1fd5a2e1SPrashanth Swaminathan   greg = ireg;
138*1fd5a2e1SPrashanth Swaminathan   avn = ecif->cif->nargs;
139*1fd5a2e1SPrashanth Swaminathan   p_argv = ecif->avalue;
140*1fd5a2e1SPrashanth Swaminathan 
141*1fd5a2e1SPrashanth Swaminathan   for (i = 0, p_arg = ecif->cif->arg_types; i < avn; i++, p_arg++, p_argv++)
142*1fd5a2e1SPrashanth Swaminathan     {
143*1fd5a2e1SPrashanth Swaminathan       size_t z;
144*1fd5a2e1SPrashanth Swaminathan 
145*1fd5a2e1SPrashanth Swaminathan       z = (*p_arg)->size;
146*1fd5a2e1SPrashanth Swaminathan       if (z < sizeof(int))
147*1fd5a2e1SPrashanth Swaminathan 	{
148*1fd5a2e1SPrashanth Swaminathan 	  if (greg++ >= NGREGARG)
149*1fd5a2e1SPrashanth Swaminathan 	    continue;
150*1fd5a2e1SPrashanth Swaminathan 
151*1fd5a2e1SPrashanth Swaminathan 	  z = sizeof(int);
152*1fd5a2e1SPrashanth Swaminathan 	  switch ((*p_arg)->type)
153*1fd5a2e1SPrashanth Swaminathan 	    {
154*1fd5a2e1SPrashanth Swaminathan 	    case FFI_TYPE_SINT8:
155*1fd5a2e1SPrashanth Swaminathan 	      *(signed int *) argp = (signed int)*(SINT8 *)(* p_argv);
156*1fd5a2e1SPrashanth Swaminathan 	      break;
157*1fd5a2e1SPrashanth Swaminathan 
158*1fd5a2e1SPrashanth Swaminathan 	    case FFI_TYPE_UINT8:
159*1fd5a2e1SPrashanth Swaminathan 	      *(unsigned int *) argp = (unsigned int)*(UINT8 *)(* p_argv);
160*1fd5a2e1SPrashanth Swaminathan 	      break;
161*1fd5a2e1SPrashanth Swaminathan 
162*1fd5a2e1SPrashanth Swaminathan 	    case FFI_TYPE_SINT16:
163*1fd5a2e1SPrashanth Swaminathan 	      *(signed int *) argp = (signed int)*(SINT16 *)(* p_argv);
164*1fd5a2e1SPrashanth Swaminathan 	      break;
165*1fd5a2e1SPrashanth Swaminathan 
166*1fd5a2e1SPrashanth Swaminathan 	    case FFI_TYPE_UINT16:
167*1fd5a2e1SPrashanth Swaminathan 	      *(unsigned int *) argp = (unsigned int)*(UINT16 *)(* p_argv);
168*1fd5a2e1SPrashanth Swaminathan 	      break;
169*1fd5a2e1SPrashanth Swaminathan 
170*1fd5a2e1SPrashanth Swaminathan 	    case FFI_TYPE_STRUCT:
171*1fd5a2e1SPrashanth Swaminathan 	      *(unsigned int *) argp = (unsigned int)*(UINT32 *)(* p_argv);
172*1fd5a2e1SPrashanth Swaminathan 	      break;
173*1fd5a2e1SPrashanth Swaminathan 
174*1fd5a2e1SPrashanth Swaminathan 	    default:
175*1fd5a2e1SPrashanth Swaminathan 	      FFI_ASSERT(0);
176*1fd5a2e1SPrashanth Swaminathan 	    }
177*1fd5a2e1SPrashanth Swaminathan 	  argp += z;
178*1fd5a2e1SPrashanth Swaminathan 	}
179*1fd5a2e1SPrashanth Swaminathan       else if (z == sizeof(int))
180*1fd5a2e1SPrashanth Swaminathan 	{
181*1fd5a2e1SPrashanth Swaminathan #if defined(__SH4__)
182*1fd5a2e1SPrashanth Swaminathan 	  if ((*p_arg)->type == FFI_TYPE_FLOAT)
183*1fd5a2e1SPrashanth Swaminathan 	    {
184*1fd5a2e1SPrashanth Swaminathan 	      if (freg++ >= NFREGARG)
185*1fd5a2e1SPrashanth Swaminathan 		continue;
186*1fd5a2e1SPrashanth Swaminathan 	    }
187*1fd5a2e1SPrashanth Swaminathan 	  else
188*1fd5a2e1SPrashanth Swaminathan #endif
189*1fd5a2e1SPrashanth Swaminathan 	    {
190*1fd5a2e1SPrashanth Swaminathan 	      if (greg++ >= NGREGARG)
191*1fd5a2e1SPrashanth Swaminathan 		continue;
192*1fd5a2e1SPrashanth Swaminathan 	    }
193*1fd5a2e1SPrashanth Swaminathan 	  *(unsigned int *) argp = (unsigned int)*(UINT32 *)(* p_argv);
194*1fd5a2e1SPrashanth Swaminathan 	  argp += z;
195*1fd5a2e1SPrashanth Swaminathan 	}
196*1fd5a2e1SPrashanth Swaminathan #if defined(__SH4__)
197*1fd5a2e1SPrashanth Swaminathan       else if ((*p_arg)->type == FFI_TYPE_DOUBLE)
198*1fd5a2e1SPrashanth Swaminathan 	{
199*1fd5a2e1SPrashanth Swaminathan 	  if (freg + 1 >= NFREGARG)
200*1fd5a2e1SPrashanth Swaminathan 	    continue;
201*1fd5a2e1SPrashanth Swaminathan 	  freg = (freg + 1) & ~1;
202*1fd5a2e1SPrashanth Swaminathan 	  freg += 2;
203*1fd5a2e1SPrashanth Swaminathan 	  memcpy (argp, *p_argv, z);
204*1fd5a2e1SPrashanth Swaminathan 	  argp += z;
205*1fd5a2e1SPrashanth Swaminathan 	}
206*1fd5a2e1SPrashanth Swaminathan #endif
207*1fd5a2e1SPrashanth Swaminathan       else
208*1fd5a2e1SPrashanth Swaminathan 	{
209*1fd5a2e1SPrashanth Swaminathan 	  int n = (z + sizeof (int) - 1) / sizeof (int);
210*1fd5a2e1SPrashanth Swaminathan #if defined(__SH4__)
211*1fd5a2e1SPrashanth Swaminathan 	  if (greg + n - 1 >= NGREGARG)
212*1fd5a2e1SPrashanth Swaminathan 	    continue;
213*1fd5a2e1SPrashanth Swaminathan #else
214*1fd5a2e1SPrashanth Swaminathan 	  if (greg >= NGREGARG)
215*1fd5a2e1SPrashanth Swaminathan 	    continue;
216*1fd5a2e1SPrashanth Swaminathan #endif
217*1fd5a2e1SPrashanth Swaminathan 	  greg += n;
218*1fd5a2e1SPrashanth Swaminathan 	  memcpy (argp, *p_argv, z);
219*1fd5a2e1SPrashanth Swaminathan 	  argp += n * sizeof (int);
220*1fd5a2e1SPrashanth Swaminathan 	}
221*1fd5a2e1SPrashanth Swaminathan     }
222*1fd5a2e1SPrashanth Swaminathan 
223*1fd5a2e1SPrashanth Swaminathan   /* Set arguments on stack.  */
224*1fd5a2e1SPrashanth Swaminathan   greg = ireg;
225*1fd5a2e1SPrashanth Swaminathan #if defined(__SH4__)
226*1fd5a2e1SPrashanth Swaminathan   freg = 0;
227*1fd5a2e1SPrashanth Swaminathan #endif
228*1fd5a2e1SPrashanth Swaminathan   p_argv = ecif->avalue;
229*1fd5a2e1SPrashanth Swaminathan 
230*1fd5a2e1SPrashanth Swaminathan   for (i = 0, p_arg = ecif->cif->arg_types; i < avn; i++, p_arg++, p_argv++)
231*1fd5a2e1SPrashanth Swaminathan     {
232*1fd5a2e1SPrashanth Swaminathan       size_t z;
233*1fd5a2e1SPrashanth Swaminathan 
234*1fd5a2e1SPrashanth Swaminathan       z = (*p_arg)->size;
235*1fd5a2e1SPrashanth Swaminathan       if (z < sizeof(int))
236*1fd5a2e1SPrashanth Swaminathan 	{
237*1fd5a2e1SPrashanth Swaminathan 	  if (greg++ < NGREGARG)
238*1fd5a2e1SPrashanth Swaminathan 	    continue;
239*1fd5a2e1SPrashanth Swaminathan 
240*1fd5a2e1SPrashanth Swaminathan 	  z = sizeof(int);
241*1fd5a2e1SPrashanth Swaminathan 	  switch ((*p_arg)->type)
242*1fd5a2e1SPrashanth Swaminathan 	    {
243*1fd5a2e1SPrashanth Swaminathan 	    case FFI_TYPE_SINT8:
244*1fd5a2e1SPrashanth Swaminathan 	      *(signed int *) argp = (signed int)*(SINT8 *)(* p_argv);
245*1fd5a2e1SPrashanth Swaminathan 	      break;
246*1fd5a2e1SPrashanth Swaminathan 
247*1fd5a2e1SPrashanth Swaminathan 	    case FFI_TYPE_UINT8:
248*1fd5a2e1SPrashanth Swaminathan 	      *(unsigned int *) argp = (unsigned int)*(UINT8 *)(* p_argv);
249*1fd5a2e1SPrashanth Swaminathan 	      break;
250*1fd5a2e1SPrashanth Swaminathan 
251*1fd5a2e1SPrashanth Swaminathan 	    case FFI_TYPE_SINT16:
252*1fd5a2e1SPrashanth Swaminathan 	      *(signed int *) argp = (signed int)*(SINT16 *)(* p_argv);
253*1fd5a2e1SPrashanth Swaminathan 	      break;
254*1fd5a2e1SPrashanth Swaminathan 
255*1fd5a2e1SPrashanth Swaminathan 	    case FFI_TYPE_UINT16:
256*1fd5a2e1SPrashanth Swaminathan 	      *(unsigned int *) argp = (unsigned int)*(UINT16 *)(* p_argv);
257*1fd5a2e1SPrashanth Swaminathan 	      break;
258*1fd5a2e1SPrashanth Swaminathan 
259*1fd5a2e1SPrashanth Swaminathan 	    case FFI_TYPE_STRUCT:
260*1fd5a2e1SPrashanth Swaminathan 	      *(unsigned int *) argp = (unsigned int)*(UINT32 *)(* p_argv);
261*1fd5a2e1SPrashanth Swaminathan 	      break;
262*1fd5a2e1SPrashanth Swaminathan 
263*1fd5a2e1SPrashanth Swaminathan 	    default:
264*1fd5a2e1SPrashanth Swaminathan 	      FFI_ASSERT(0);
265*1fd5a2e1SPrashanth Swaminathan 	    }
266*1fd5a2e1SPrashanth Swaminathan 	  argp += z;
267*1fd5a2e1SPrashanth Swaminathan 	}
268*1fd5a2e1SPrashanth Swaminathan       else if (z == sizeof(int))
269*1fd5a2e1SPrashanth Swaminathan 	{
270*1fd5a2e1SPrashanth Swaminathan #if defined(__SH4__)
271*1fd5a2e1SPrashanth Swaminathan 	  if ((*p_arg)->type == FFI_TYPE_FLOAT)
272*1fd5a2e1SPrashanth Swaminathan 	    {
273*1fd5a2e1SPrashanth Swaminathan 	      if (freg++ < NFREGARG)
274*1fd5a2e1SPrashanth Swaminathan 		continue;
275*1fd5a2e1SPrashanth Swaminathan 	    }
276*1fd5a2e1SPrashanth Swaminathan 	  else
277*1fd5a2e1SPrashanth Swaminathan #endif
278*1fd5a2e1SPrashanth Swaminathan 	    {
279*1fd5a2e1SPrashanth Swaminathan 	      if (greg++ < NGREGARG)
280*1fd5a2e1SPrashanth Swaminathan 		continue;
281*1fd5a2e1SPrashanth Swaminathan 	    }
282*1fd5a2e1SPrashanth Swaminathan 	  *(unsigned int *) argp = (unsigned int)*(UINT32 *)(* p_argv);
283*1fd5a2e1SPrashanth Swaminathan 	  argp += z;
284*1fd5a2e1SPrashanth Swaminathan 	}
285*1fd5a2e1SPrashanth Swaminathan #if defined(__SH4__)
286*1fd5a2e1SPrashanth Swaminathan       else if ((*p_arg)->type == FFI_TYPE_DOUBLE)
287*1fd5a2e1SPrashanth Swaminathan 	{
288*1fd5a2e1SPrashanth Swaminathan 	  if (freg + 1 < NFREGARG)
289*1fd5a2e1SPrashanth Swaminathan 	    {
290*1fd5a2e1SPrashanth Swaminathan 	      freg = (freg + 1) & ~1;
291*1fd5a2e1SPrashanth Swaminathan 	      freg += 2;
292*1fd5a2e1SPrashanth Swaminathan 	      continue;
293*1fd5a2e1SPrashanth Swaminathan 	    }
294*1fd5a2e1SPrashanth Swaminathan 	  memcpy (argp, *p_argv, z);
295*1fd5a2e1SPrashanth Swaminathan 	  argp += z;
296*1fd5a2e1SPrashanth Swaminathan 	}
297*1fd5a2e1SPrashanth Swaminathan #endif
298*1fd5a2e1SPrashanth Swaminathan       else
299*1fd5a2e1SPrashanth Swaminathan 	{
300*1fd5a2e1SPrashanth Swaminathan 	  int n = (z + sizeof (int) - 1) / sizeof (int);
301*1fd5a2e1SPrashanth Swaminathan 	  if (greg + n - 1 < NGREGARG)
302*1fd5a2e1SPrashanth Swaminathan 	    {
303*1fd5a2e1SPrashanth Swaminathan 	      greg += n;
304*1fd5a2e1SPrashanth Swaminathan 	      continue;
305*1fd5a2e1SPrashanth Swaminathan 	    }
306*1fd5a2e1SPrashanth Swaminathan #if (! defined(__SH4__))
307*1fd5a2e1SPrashanth Swaminathan 	  else if (greg < NGREGARG)
308*1fd5a2e1SPrashanth Swaminathan 	    {
309*1fd5a2e1SPrashanth Swaminathan 	      greg = NGREGARG;
310*1fd5a2e1SPrashanth Swaminathan 	      continue;
311*1fd5a2e1SPrashanth Swaminathan 	    }
312*1fd5a2e1SPrashanth Swaminathan #endif
313*1fd5a2e1SPrashanth Swaminathan 	  memcpy (argp, *p_argv, z);
314*1fd5a2e1SPrashanth Swaminathan 	  argp += n * sizeof (int);
315*1fd5a2e1SPrashanth Swaminathan 	}
316*1fd5a2e1SPrashanth Swaminathan     }
317*1fd5a2e1SPrashanth Swaminathan 
318*1fd5a2e1SPrashanth Swaminathan   return;
319*1fd5a2e1SPrashanth Swaminathan }
320*1fd5a2e1SPrashanth Swaminathan 
321*1fd5a2e1SPrashanth Swaminathan /* Perform machine dependent cif processing */
ffi_prep_cif_machdep(ffi_cif * cif)322*1fd5a2e1SPrashanth Swaminathan ffi_status ffi_prep_cif_machdep(ffi_cif *cif)
323*1fd5a2e1SPrashanth Swaminathan {
324*1fd5a2e1SPrashanth Swaminathan   int i, j;
325*1fd5a2e1SPrashanth Swaminathan   int size, type;
326*1fd5a2e1SPrashanth Swaminathan   int n, m;
327*1fd5a2e1SPrashanth Swaminathan   int greg;
328*1fd5a2e1SPrashanth Swaminathan #if defined(__SH4__)
329*1fd5a2e1SPrashanth Swaminathan   int freg = 0;
330*1fd5a2e1SPrashanth Swaminathan #endif
331*1fd5a2e1SPrashanth Swaminathan 
332*1fd5a2e1SPrashanth Swaminathan   cif->flags = 0;
333*1fd5a2e1SPrashanth Swaminathan 
334*1fd5a2e1SPrashanth Swaminathan   greg = ((return_type (cif->rtype) == FFI_TYPE_STRUCT) &&
335*1fd5a2e1SPrashanth Swaminathan 	  STRUCT_VALUE_ADDRESS_WITH_ARG) ? 1 : 0;
336*1fd5a2e1SPrashanth Swaminathan 
337*1fd5a2e1SPrashanth Swaminathan #if defined(__SH4__)
338*1fd5a2e1SPrashanth Swaminathan   for (i = j = 0; i < cif->nargs && j < 12; i++)
339*1fd5a2e1SPrashanth Swaminathan     {
340*1fd5a2e1SPrashanth Swaminathan       type = (cif->arg_types)[i]->type;
341*1fd5a2e1SPrashanth Swaminathan       switch (type)
342*1fd5a2e1SPrashanth Swaminathan 	{
343*1fd5a2e1SPrashanth Swaminathan 	case FFI_TYPE_FLOAT:
344*1fd5a2e1SPrashanth Swaminathan 	  if (freg >= NFREGARG)
345*1fd5a2e1SPrashanth Swaminathan 	    continue;
346*1fd5a2e1SPrashanth Swaminathan 	  freg++;
347*1fd5a2e1SPrashanth Swaminathan 	  cif->flags += ((cif->arg_types)[i]->type) << (2 * j);
348*1fd5a2e1SPrashanth Swaminathan 	  j++;
349*1fd5a2e1SPrashanth Swaminathan 	  break;
350*1fd5a2e1SPrashanth Swaminathan 
351*1fd5a2e1SPrashanth Swaminathan 	case FFI_TYPE_DOUBLE:
352*1fd5a2e1SPrashanth Swaminathan 	  if ((freg + 1) >= NFREGARG)
353*1fd5a2e1SPrashanth Swaminathan 	    continue;
354*1fd5a2e1SPrashanth Swaminathan 	  freg = (freg + 1) & ~1;
355*1fd5a2e1SPrashanth Swaminathan 	  freg += 2;
356*1fd5a2e1SPrashanth Swaminathan 	  cif->flags += ((cif->arg_types)[i]->type) << (2 * j);
357*1fd5a2e1SPrashanth Swaminathan 	  j++;
358*1fd5a2e1SPrashanth Swaminathan 	  break;
359*1fd5a2e1SPrashanth Swaminathan 
360*1fd5a2e1SPrashanth Swaminathan 	default:
361*1fd5a2e1SPrashanth Swaminathan 	  size = (cif->arg_types)[i]->size;
362*1fd5a2e1SPrashanth Swaminathan 	  n = (size + sizeof (int) - 1) / sizeof (int);
363*1fd5a2e1SPrashanth Swaminathan 	  if (greg + n - 1 >= NGREGARG)
364*1fd5a2e1SPrashanth Swaminathan 		continue;
365*1fd5a2e1SPrashanth Swaminathan 	  greg += n;
366*1fd5a2e1SPrashanth Swaminathan 	  for (m = 0; m < n; m++)
367*1fd5a2e1SPrashanth Swaminathan 	    cif->flags += FFI_TYPE_INT << (2 * j++);
368*1fd5a2e1SPrashanth Swaminathan 	  break;
369*1fd5a2e1SPrashanth Swaminathan 	}
370*1fd5a2e1SPrashanth Swaminathan     }
371*1fd5a2e1SPrashanth Swaminathan #else
372*1fd5a2e1SPrashanth Swaminathan   for (i = j = 0; i < cif->nargs && j < 4; i++)
373*1fd5a2e1SPrashanth Swaminathan     {
374*1fd5a2e1SPrashanth Swaminathan       size = (cif->arg_types)[i]->size;
375*1fd5a2e1SPrashanth Swaminathan       n = (size + sizeof (int) - 1) / sizeof (int);
376*1fd5a2e1SPrashanth Swaminathan       if (greg >= NGREGARG)
377*1fd5a2e1SPrashanth Swaminathan 	continue;
378*1fd5a2e1SPrashanth Swaminathan       else if (greg + n - 1 >= NGREGARG)
379*1fd5a2e1SPrashanth Swaminathan 	n = NGREGARG - greg;
380*1fd5a2e1SPrashanth Swaminathan       greg += n;
381*1fd5a2e1SPrashanth Swaminathan       for (m = 0; m < n; m++)
382*1fd5a2e1SPrashanth Swaminathan         cif->flags += FFI_TYPE_INT << (2 * j++);
383*1fd5a2e1SPrashanth Swaminathan     }
384*1fd5a2e1SPrashanth Swaminathan #endif
385*1fd5a2e1SPrashanth Swaminathan 
386*1fd5a2e1SPrashanth Swaminathan   /* Set the return type flag */
387*1fd5a2e1SPrashanth Swaminathan   switch (cif->rtype->type)
388*1fd5a2e1SPrashanth Swaminathan     {
389*1fd5a2e1SPrashanth Swaminathan     case FFI_TYPE_STRUCT:
390*1fd5a2e1SPrashanth Swaminathan       cif->flags += (unsigned) (return_type (cif->rtype)) << 24;
391*1fd5a2e1SPrashanth Swaminathan       break;
392*1fd5a2e1SPrashanth Swaminathan 
393*1fd5a2e1SPrashanth Swaminathan     case FFI_TYPE_VOID:
394*1fd5a2e1SPrashanth Swaminathan     case FFI_TYPE_FLOAT:
395*1fd5a2e1SPrashanth Swaminathan     case FFI_TYPE_DOUBLE:
396*1fd5a2e1SPrashanth Swaminathan     case FFI_TYPE_SINT64:
397*1fd5a2e1SPrashanth Swaminathan     case FFI_TYPE_UINT64:
398*1fd5a2e1SPrashanth Swaminathan       cif->flags += (unsigned) cif->rtype->type << 24;
399*1fd5a2e1SPrashanth Swaminathan       break;
400*1fd5a2e1SPrashanth Swaminathan 
401*1fd5a2e1SPrashanth Swaminathan     default:
402*1fd5a2e1SPrashanth Swaminathan       cif->flags += FFI_TYPE_INT << 24;
403*1fd5a2e1SPrashanth Swaminathan       break;
404*1fd5a2e1SPrashanth Swaminathan     }
405*1fd5a2e1SPrashanth Swaminathan 
406*1fd5a2e1SPrashanth Swaminathan   return FFI_OK;
407*1fd5a2e1SPrashanth Swaminathan }
408*1fd5a2e1SPrashanth Swaminathan 
409*1fd5a2e1SPrashanth Swaminathan extern void ffi_call_SYSV(void (*)(char *, extended_cif *), extended_cif *,
410*1fd5a2e1SPrashanth Swaminathan 			  unsigned, unsigned, unsigned *, void (*fn)(void));
411*1fd5a2e1SPrashanth Swaminathan 
ffi_call(ffi_cif * cif,void (* fn)(void),void * rvalue,void ** avalue)412*1fd5a2e1SPrashanth Swaminathan void ffi_call(ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue)
413*1fd5a2e1SPrashanth Swaminathan {
414*1fd5a2e1SPrashanth Swaminathan   extended_cif ecif;
415*1fd5a2e1SPrashanth Swaminathan   UINT64 trvalue;
416*1fd5a2e1SPrashanth Swaminathan 
417*1fd5a2e1SPrashanth Swaminathan   ecif.cif = cif;
418*1fd5a2e1SPrashanth Swaminathan   ecif.avalue = avalue;
419*1fd5a2e1SPrashanth Swaminathan 
420*1fd5a2e1SPrashanth Swaminathan   /* If the return value is a struct and we don't have a return	*/
421*1fd5a2e1SPrashanth Swaminathan   /* value address then we need to make one		        */
422*1fd5a2e1SPrashanth Swaminathan 
423*1fd5a2e1SPrashanth Swaminathan   if (cif->rtype->type == FFI_TYPE_STRUCT
424*1fd5a2e1SPrashanth Swaminathan       && return_type (cif->rtype) != FFI_TYPE_STRUCT)
425*1fd5a2e1SPrashanth Swaminathan     ecif.rvalue = &trvalue;
426*1fd5a2e1SPrashanth Swaminathan   else if ((rvalue == NULL) &&
427*1fd5a2e1SPrashanth Swaminathan       (cif->rtype->type == FFI_TYPE_STRUCT))
428*1fd5a2e1SPrashanth Swaminathan     {
429*1fd5a2e1SPrashanth Swaminathan       ecif.rvalue = alloca(cif->rtype->size);
430*1fd5a2e1SPrashanth Swaminathan     }
431*1fd5a2e1SPrashanth Swaminathan   else
432*1fd5a2e1SPrashanth Swaminathan     ecif.rvalue = rvalue;
433*1fd5a2e1SPrashanth Swaminathan 
434*1fd5a2e1SPrashanth Swaminathan   switch (cif->abi)
435*1fd5a2e1SPrashanth Swaminathan     {
436*1fd5a2e1SPrashanth Swaminathan     case FFI_SYSV:
437*1fd5a2e1SPrashanth Swaminathan       ffi_call_SYSV(ffi_prep_args, &ecif, cif->bytes, cif->flags, ecif.rvalue,
438*1fd5a2e1SPrashanth Swaminathan 		    fn);
439*1fd5a2e1SPrashanth Swaminathan       break;
440*1fd5a2e1SPrashanth Swaminathan     default:
441*1fd5a2e1SPrashanth Swaminathan       FFI_ASSERT(0);
442*1fd5a2e1SPrashanth Swaminathan       break;
443*1fd5a2e1SPrashanth Swaminathan     }
444*1fd5a2e1SPrashanth Swaminathan 
445*1fd5a2e1SPrashanth Swaminathan   if (rvalue
446*1fd5a2e1SPrashanth Swaminathan       && cif->rtype->type == FFI_TYPE_STRUCT
447*1fd5a2e1SPrashanth Swaminathan       && return_type (cif->rtype) != FFI_TYPE_STRUCT)
448*1fd5a2e1SPrashanth Swaminathan     memcpy (rvalue, &trvalue, cif->rtype->size);
449*1fd5a2e1SPrashanth Swaminathan }
450*1fd5a2e1SPrashanth Swaminathan 
451*1fd5a2e1SPrashanth Swaminathan extern void ffi_closure_SYSV (void);
452*1fd5a2e1SPrashanth Swaminathan #if defined(__SH4__)
453*1fd5a2e1SPrashanth Swaminathan extern void __ic_invalidate (void *line);
454*1fd5a2e1SPrashanth Swaminathan #endif
455*1fd5a2e1SPrashanth Swaminathan 
456*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)457*1fd5a2e1SPrashanth Swaminathan ffi_prep_closure_loc (ffi_closure* closure,
458*1fd5a2e1SPrashanth Swaminathan 		      ffi_cif* cif,
459*1fd5a2e1SPrashanth Swaminathan 		      void (*fun)(ffi_cif*, void*, void**, void*),
460*1fd5a2e1SPrashanth Swaminathan 		      void *user_data,
461*1fd5a2e1SPrashanth Swaminathan 		      void *codeloc)
462*1fd5a2e1SPrashanth Swaminathan {
463*1fd5a2e1SPrashanth Swaminathan   unsigned int *tramp;
464*1fd5a2e1SPrashanth Swaminathan   unsigned int insn;
465*1fd5a2e1SPrashanth Swaminathan 
466*1fd5a2e1SPrashanth Swaminathan   if (cif->abi != FFI_SYSV)
467*1fd5a2e1SPrashanth Swaminathan     return FFI_BAD_ABI;
468*1fd5a2e1SPrashanth Swaminathan 
469*1fd5a2e1SPrashanth Swaminathan   tramp = (unsigned int *) &closure->tramp[0];
470*1fd5a2e1SPrashanth Swaminathan   /* Set T bit if the function returns a struct pointed with R2.  */
471*1fd5a2e1SPrashanth Swaminathan   insn = (return_type (cif->rtype) == FFI_TYPE_STRUCT
472*1fd5a2e1SPrashanth Swaminathan 	  ? 0x0018 /* sett */
473*1fd5a2e1SPrashanth Swaminathan 	  : 0x0008 /* clrt */);
474*1fd5a2e1SPrashanth Swaminathan 
475*1fd5a2e1SPrashanth Swaminathan #ifdef __LITTLE_ENDIAN__
476*1fd5a2e1SPrashanth Swaminathan   tramp[0] = 0xd301d102;
477*1fd5a2e1SPrashanth Swaminathan   tramp[1] = 0x0000412b | (insn << 16);
478*1fd5a2e1SPrashanth Swaminathan #else
479*1fd5a2e1SPrashanth Swaminathan   tramp[0] = 0xd102d301;
480*1fd5a2e1SPrashanth Swaminathan   tramp[1] = 0x412b0000 | insn;
481*1fd5a2e1SPrashanth Swaminathan #endif
482*1fd5a2e1SPrashanth Swaminathan   *(void **) &tramp[2] = (void *)codeloc;          /* ctx */
483*1fd5a2e1SPrashanth Swaminathan   *(void **) &tramp[3] = (void *)ffi_closure_SYSV; /* funaddr */
484*1fd5a2e1SPrashanth Swaminathan 
485*1fd5a2e1SPrashanth Swaminathan   closure->cif = cif;
486*1fd5a2e1SPrashanth Swaminathan   closure->fun = fun;
487*1fd5a2e1SPrashanth Swaminathan   closure->user_data = user_data;
488*1fd5a2e1SPrashanth Swaminathan 
489*1fd5a2e1SPrashanth Swaminathan #if defined(__SH4__)
490*1fd5a2e1SPrashanth Swaminathan   /* Flush the icache.  */
491*1fd5a2e1SPrashanth Swaminathan   __ic_invalidate(codeloc);
492*1fd5a2e1SPrashanth Swaminathan #endif
493*1fd5a2e1SPrashanth Swaminathan 
494*1fd5a2e1SPrashanth Swaminathan   return FFI_OK;
495*1fd5a2e1SPrashanth Swaminathan }
496*1fd5a2e1SPrashanth Swaminathan 
497*1fd5a2e1SPrashanth Swaminathan /* Basically the trampoline invokes ffi_closure_SYSV, and on
498*1fd5a2e1SPrashanth Swaminathan  * entry, r3 holds the address of the closure.
499*1fd5a2e1SPrashanth Swaminathan  * After storing the registers that could possibly contain
500*1fd5a2e1SPrashanth Swaminathan  * parameters to be passed into the stack frame and setting
501*1fd5a2e1SPrashanth Swaminathan  * up space for a return value, ffi_closure_SYSV invokes the
502*1fd5a2e1SPrashanth Swaminathan  * following helper function to do most of the work.
503*1fd5a2e1SPrashanth Swaminathan  */
504*1fd5a2e1SPrashanth Swaminathan 
505*1fd5a2e1SPrashanth Swaminathan #ifdef __LITTLE_ENDIAN__
506*1fd5a2e1SPrashanth Swaminathan #define OFS_INT8	0
507*1fd5a2e1SPrashanth Swaminathan #define OFS_INT16	0
508*1fd5a2e1SPrashanth Swaminathan #else
509*1fd5a2e1SPrashanth Swaminathan #define OFS_INT8	3
510*1fd5a2e1SPrashanth Swaminathan #define OFS_INT16	2
511*1fd5a2e1SPrashanth Swaminathan #endif
512*1fd5a2e1SPrashanth Swaminathan 
513*1fd5a2e1SPrashanth Swaminathan int
ffi_closure_helper_SYSV(ffi_closure * closure,void * rvalue,unsigned long * pgr,unsigned long * pfr,unsigned long * pst)514*1fd5a2e1SPrashanth Swaminathan ffi_closure_helper_SYSV (ffi_closure *closure, void *rvalue,
515*1fd5a2e1SPrashanth Swaminathan 			 unsigned long *pgr, unsigned long *pfr,
516*1fd5a2e1SPrashanth Swaminathan 			 unsigned long *pst)
517*1fd5a2e1SPrashanth Swaminathan {
518*1fd5a2e1SPrashanth Swaminathan   void **avalue;
519*1fd5a2e1SPrashanth Swaminathan   ffi_type **p_arg;
520*1fd5a2e1SPrashanth Swaminathan   int i, avn;
521*1fd5a2e1SPrashanth Swaminathan   int ireg, greg = 0;
522*1fd5a2e1SPrashanth Swaminathan #if defined(__SH4__)
523*1fd5a2e1SPrashanth Swaminathan   int freg = 0;
524*1fd5a2e1SPrashanth Swaminathan #endif
525*1fd5a2e1SPrashanth Swaminathan   ffi_cif *cif;
526*1fd5a2e1SPrashanth Swaminathan 
527*1fd5a2e1SPrashanth Swaminathan   cif = closure->cif;
528*1fd5a2e1SPrashanth Swaminathan   avalue = alloca(cif->nargs * sizeof(void *));
529*1fd5a2e1SPrashanth Swaminathan 
530*1fd5a2e1SPrashanth Swaminathan   /* Copy the caller's structure return value address so that the closure
531*1fd5a2e1SPrashanth Swaminathan      returns the data directly to the caller.  */
532*1fd5a2e1SPrashanth Swaminathan   if (cif->rtype->type == FFI_TYPE_STRUCT && STRUCT_VALUE_ADDRESS_WITH_ARG)
533*1fd5a2e1SPrashanth Swaminathan     {
534*1fd5a2e1SPrashanth Swaminathan       rvalue = (void *) *pgr++;
535*1fd5a2e1SPrashanth Swaminathan       ireg = 1;
536*1fd5a2e1SPrashanth Swaminathan     }
537*1fd5a2e1SPrashanth Swaminathan   else
538*1fd5a2e1SPrashanth Swaminathan     ireg = 0;
539*1fd5a2e1SPrashanth Swaminathan 
540*1fd5a2e1SPrashanth Swaminathan   cif = closure->cif;
541*1fd5a2e1SPrashanth Swaminathan   greg = ireg;
542*1fd5a2e1SPrashanth Swaminathan   avn = cif->nargs;
543*1fd5a2e1SPrashanth Swaminathan 
544*1fd5a2e1SPrashanth Swaminathan   /* Grab the addresses of the arguments from the stack frame.  */
545*1fd5a2e1SPrashanth Swaminathan   for (i = 0, p_arg = cif->arg_types; i < avn; i++, p_arg++)
546*1fd5a2e1SPrashanth Swaminathan     {
547*1fd5a2e1SPrashanth Swaminathan       size_t z;
548*1fd5a2e1SPrashanth Swaminathan 
549*1fd5a2e1SPrashanth Swaminathan       z = (*p_arg)->size;
550*1fd5a2e1SPrashanth Swaminathan       if (z < sizeof(int))
551*1fd5a2e1SPrashanth Swaminathan 	{
552*1fd5a2e1SPrashanth Swaminathan 	  if (greg++ >= NGREGARG)
553*1fd5a2e1SPrashanth Swaminathan 	    continue;
554*1fd5a2e1SPrashanth Swaminathan 
555*1fd5a2e1SPrashanth Swaminathan 	  z = sizeof(int);
556*1fd5a2e1SPrashanth Swaminathan 	  switch ((*p_arg)->type)
557*1fd5a2e1SPrashanth Swaminathan 	    {
558*1fd5a2e1SPrashanth Swaminathan 	    case FFI_TYPE_SINT8:
559*1fd5a2e1SPrashanth Swaminathan 	    case FFI_TYPE_UINT8:
560*1fd5a2e1SPrashanth Swaminathan 	      avalue[i] = (((char *)pgr) + OFS_INT8);
561*1fd5a2e1SPrashanth Swaminathan 	      break;
562*1fd5a2e1SPrashanth Swaminathan 
563*1fd5a2e1SPrashanth Swaminathan 	    case FFI_TYPE_SINT16:
564*1fd5a2e1SPrashanth Swaminathan 	    case FFI_TYPE_UINT16:
565*1fd5a2e1SPrashanth Swaminathan 	      avalue[i] = (((char *)pgr) + OFS_INT16);
566*1fd5a2e1SPrashanth Swaminathan 	      break;
567*1fd5a2e1SPrashanth Swaminathan 
568*1fd5a2e1SPrashanth Swaminathan 	    case FFI_TYPE_STRUCT:
569*1fd5a2e1SPrashanth Swaminathan 	      avalue[i] = pgr;
570*1fd5a2e1SPrashanth Swaminathan 	      break;
571*1fd5a2e1SPrashanth Swaminathan 
572*1fd5a2e1SPrashanth Swaminathan 	    default:
573*1fd5a2e1SPrashanth Swaminathan 	      FFI_ASSERT(0);
574*1fd5a2e1SPrashanth Swaminathan 	    }
575*1fd5a2e1SPrashanth Swaminathan 	  pgr++;
576*1fd5a2e1SPrashanth Swaminathan 	}
577*1fd5a2e1SPrashanth Swaminathan       else if (z == sizeof(int))
578*1fd5a2e1SPrashanth Swaminathan 	{
579*1fd5a2e1SPrashanth Swaminathan #if defined(__SH4__)
580*1fd5a2e1SPrashanth Swaminathan 	  if ((*p_arg)->type == FFI_TYPE_FLOAT)
581*1fd5a2e1SPrashanth Swaminathan 	    {
582*1fd5a2e1SPrashanth Swaminathan 	      if (freg++ >= NFREGARG)
583*1fd5a2e1SPrashanth Swaminathan 		continue;
584*1fd5a2e1SPrashanth Swaminathan 	      avalue[i] = pfr;
585*1fd5a2e1SPrashanth Swaminathan 	      pfr++;
586*1fd5a2e1SPrashanth Swaminathan 	    }
587*1fd5a2e1SPrashanth Swaminathan 	  else
588*1fd5a2e1SPrashanth Swaminathan #endif
589*1fd5a2e1SPrashanth Swaminathan 	    {
590*1fd5a2e1SPrashanth Swaminathan 	      if (greg++ >= NGREGARG)
591*1fd5a2e1SPrashanth Swaminathan 		continue;
592*1fd5a2e1SPrashanth Swaminathan 	      avalue[i] = pgr;
593*1fd5a2e1SPrashanth Swaminathan 	      pgr++;
594*1fd5a2e1SPrashanth Swaminathan 	    }
595*1fd5a2e1SPrashanth Swaminathan 	}
596*1fd5a2e1SPrashanth Swaminathan #if defined(__SH4__)
597*1fd5a2e1SPrashanth Swaminathan       else if ((*p_arg)->type == FFI_TYPE_DOUBLE)
598*1fd5a2e1SPrashanth Swaminathan 	{
599*1fd5a2e1SPrashanth Swaminathan 	  if (freg + 1 >= NFREGARG)
600*1fd5a2e1SPrashanth Swaminathan 	    continue;
601*1fd5a2e1SPrashanth Swaminathan 	  if (freg & 1)
602*1fd5a2e1SPrashanth Swaminathan 	    pfr++;
603*1fd5a2e1SPrashanth Swaminathan 	  freg = (freg + 1) & ~1;
604*1fd5a2e1SPrashanth Swaminathan 	  freg += 2;
605*1fd5a2e1SPrashanth Swaminathan 	  avalue[i] = pfr;
606*1fd5a2e1SPrashanth Swaminathan 	  pfr += 2;
607*1fd5a2e1SPrashanth Swaminathan 	}
608*1fd5a2e1SPrashanth Swaminathan #endif
609*1fd5a2e1SPrashanth Swaminathan       else
610*1fd5a2e1SPrashanth Swaminathan 	{
611*1fd5a2e1SPrashanth Swaminathan 	  int n = (z + sizeof (int) - 1) / sizeof (int);
612*1fd5a2e1SPrashanth Swaminathan #if defined(__SH4__)
613*1fd5a2e1SPrashanth Swaminathan 	  if (greg + n - 1 >= NGREGARG)
614*1fd5a2e1SPrashanth Swaminathan 	    continue;
615*1fd5a2e1SPrashanth Swaminathan #else
616*1fd5a2e1SPrashanth Swaminathan 	  if (greg >= NGREGARG)
617*1fd5a2e1SPrashanth Swaminathan 	    continue;
618*1fd5a2e1SPrashanth Swaminathan #endif
619*1fd5a2e1SPrashanth Swaminathan 	  greg += n;
620*1fd5a2e1SPrashanth Swaminathan 	  avalue[i] = pgr;
621*1fd5a2e1SPrashanth Swaminathan 	  pgr += n;
622*1fd5a2e1SPrashanth Swaminathan 	}
623*1fd5a2e1SPrashanth Swaminathan     }
624*1fd5a2e1SPrashanth Swaminathan 
625*1fd5a2e1SPrashanth Swaminathan   greg = ireg;
626*1fd5a2e1SPrashanth Swaminathan #if defined(__SH4__)
627*1fd5a2e1SPrashanth Swaminathan   freg = 0;
628*1fd5a2e1SPrashanth Swaminathan #endif
629*1fd5a2e1SPrashanth Swaminathan 
630*1fd5a2e1SPrashanth Swaminathan   for (i = 0, p_arg = cif->arg_types; i < avn; i++, p_arg++)
631*1fd5a2e1SPrashanth Swaminathan     {
632*1fd5a2e1SPrashanth Swaminathan       size_t z;
633*1fd5a2e1SPrashanth Swaminathan 
634*1fd5a2e1SPrashanth Swaminathan       z = (*p_arg)->size;
635*1fd5a2e1SPrashanth Swaminathan       if (z < sizeof(int))
636*1fd5a2e1SPrashanth Swaminathan 	{
637*1fd5a2e1SPrashanth Swaminathan 	  if (greg++ < NGREGARG)
638*1fd5a2e1SPrashanth Swaminathan 	    continue;
639*1fd5a2e1SPrashanth Swaminathan 
640*1fd5a2e1SPrashanth Swaminathan 	  z = sizeof(int);
641*1fd5a2e1SPrashanth Swaminathan 	  switch ((*p_arg)->type)
642*1fd5a2e1SPrashanth Swaminathan 	    {
643*1fd5a2e1SPrashanth Swaminathan 	    case FFI_TYPE_SINT8:
644*1fd5a2e1SPrashanth Swaminathan 	    case FFI_TYPE_UINT8:
645*1fd5a2e1SPrashanth Swaminathan 	      avalue[i] = (((char *)pst) + OFS_INT8);
646*1fd5a2e1SPrashanth Swaminathan 	      break;
647*1fd5a2e1SPrashanth Swaminathan 
648*1fd5a2e1SPrashanth Swaminathan 	    case FFI_TYPE_SINT16:
649*1fd5a2e1SPrashanth Swaminathan 	    case FFI_TYPE_UINT16:
650*1fd5a2e1SPrashanth Swaminathan 	      avalue[i] = (((char *)pst) + OFS_INT16);
651*1fd5a2e1SPrashanth Swaminathan 	      break;
652*1fd5a2e1SPrashanth Swaminathan 
653*1fd5a2e1SPrashanth Swaminathan 	    case FFI_TYPE_STRUCT:
654*1fd5a2e1SPrashanth Swaminathan 	      avalue[i] = pst;
655*1fd5a2e1SPrashanth Swaminathan 	      break;
656*1fd5a2e1SPrashanth Swaminathan 
657*1fd5a2e1SPrashanth Swaminathan 	    default:
658*1fd5a2e1SPrashanth Swaminathan 	      FFI_ASSERT(0);
659*1fd5a2e1SPrashanth Swaminathan 	    }
660*1fd5a2e1SPrashanth Swaminathan 	  pst++;
661*1fd5a2e1SPrashanth Swaminathan 	}
662*1fd5a2e1SPrashanth Swaminathan       else if (z == sizeof(int))
663*1fd5a2e1SPrashanth Swaminathan 	{
664*1fd5a2e1SPrashanth Swaminathan #if defined(__SH4__)
665*1fd5a2e1SPrashanth Swaminathan 	  if ((*p_arg)->type == FFI_TYPE_FLOAT)
666*1fd5a2e1SPrashanth Swaminathan 	    {
667*1fd5a2e1SPrashanth Swaminathan 	      if (freg++ < NFREGARG)
668*1fd5a2e1SPrashanth Swaminathan 		continue;
669*1fd5a2e1SPrashanth Swaminathan 	    }
670*1fd5a2e1SPrashanth Swaminathan 	  else
671*1fd5a2e1SPrashanth Swaminathan #endif
672*1fd5a2e1SPrashanth Swaminathan 	    {
673*1fd5a2e1SPrashanth Swaminathan 	      if (greg++ < NGREGARG)
674*1fd5a2e1SPrashanth Swaminathan 		continue;
675*1fd5a2e1SPrashanth Swaminathan 	    }
676*1fd5a2e1SPrashanth Swaminathan 	  avalue[i] = pst;
677*1fd5a2e1SPrashanth Swaminathan 	  pst++;
678*1fd5a2e1SPrashanth Swaminathan 	}
679*1fd5a2e1SPrashanth Swaminathan #if defined(__SH4__)
680*1fd5a2e1SPrashanth Swaminathan       else if ((*p_arg)->type == FFI_TYPE_DOUBLE)
681*1fd5a2e1SPrashanth Swaminathan 	{
682*1fd5a2e1SPrashanth Swaminathan 	  if (freg + 1 < NFREGARG)
683*1fd5a2e1SPrashanth Swaminathan 	    {
684*1fd5a2e1SPrashanth Swaminathan 	      freg = (freg + 1) & ~1;
685*1fd5a2e1SPrashanth Swaminathan 	      freg += 2;
686*1fd5a2e1SPrashanth Swaminathan 	      continue;
687*1fd5a2e1SPrashanth Swaminathan 	    }
688*1fd5a2e1SPrashanth Swaminathan 	  avalue[i] = pst;
689*1fd5a2e1SPrashanth Swaminathan 	  pst += 2;
690*1fd5a2e1SPrashanth Swaminathan 	}
691*1fd5a2e1SPrashanth Swaminathan #endif
692*1fd5a2e1SPrashanth Swaminathan       else
693*1fd5a2e1SPrashanth Swaminathan 	{
694*1fd5a2e1SPrashanth Swaminathan 	  int n = (z + sizeof (int) - 1) / sizeof (int);
695*1fd5a2e1SPrashanth Swaminathan 	  if (greg + n - 1 < NGREGARG)
696*1fd5a2e1SPrashanth Swaminathan 	    {
697*1fd5a2e1SPrashanth Swaminathan 	      greg += n;
698*1fd5a2e1SPrashanth Swaminathan 	      continue;
699*1fd5a2e1SPrashanth Swaminathan 	    }
700*1fd5a2e1SPrashanth Swaminathan #if (! defined(__SH4__))
701*1fd5a2e1SPrashanth Swaminathan 	  else if (greg < NGREGARG)
702*1fd5a2e1SPrashanth Swaminathan 	    {
703*1fd5a2e1SPrashanth Swaminathan 	      greg += n;
704*1fd5a2e1SPrashanth Swaminathan 	      pst += greg - NGREGARG;
705*1fd5a2e1SPrashanth Swaminathan 	      continue;
706*1fd5a2e1SPrashanth Swaminathan 	    }
707*1fd5a2e1SPrashanth Swaminathan #endif
708*1fd5a2e1SPrashanth Swaminathan 	  avalue[i] = pst;
709*1fd5a2e1SPrashanth Swaminathan 	  pst += n;
710*1fd5a2e1SPrashanth Swaminathan 	}
711*1fd5a2e1SPrashanth Swaminathan     }
712*1fd5a2e1SPrashanth Swaminathan 
713*1fd5a2e1SPrashanth Swaminathan   (closure->fun) (cif, rvalue, avalue, closure->user_data);
714*1fd5a2e1SPrashanth Swaminathan 
715*1fd5a2e1SPrashanth Swaminathan   /* Tell ffi_closure_SYSV how to perform return type promotions.  */
716*1fd5a2e1SPrashanth Swaminathan   return return_type (cif->rtype);
717*1fd5a2e1SPrashanth Swaminathan }
718