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