1*1fd5a2e1SPrashanth Swaminathan /* -----------------------------------------------------------------------
2*1fd5a2e1SPrashanth Swaminathan ffiw64.c - Copyright (c) 2018 Anthony Green
3*1fd5a2e1SPrashanth Swaminathan Copyright (c) 2014 Red Hat, Inc.
4*1fd5a2e1SPrashanth Swaminathan
5*1fd5a2e1SPrashanth Swaminathan x86 win64 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 #if defined(__x86_64__) || defined(_M_AMD64)
29*1fd5a2e1SPrashanth Swaminathan #include <ffi.h>
30*1fd5a2e1SPrashanth Swaminathan #include <ffi_common.h>
31*1fd5a2e1SPrashanth Swaminathan #include <stdlib.h>
32*1fd5a2e1SPrashanth Swaminathan #include <stdint.h>
33*1fd5a2e1SPrashanth Swaminathan
34*1fd5a2e1SPrashanth Swaminathan #ifdef X86_WIN64
35*1fd5a2e1SPrashanth Swaminathan #define EFI64(name) name
36*1fd5a2e1SPrashanth Swaminathan #else
37*1fd5a2e1SPrashanth Swaminathan #define EFI64(name) FFI_HIDDEN name##_efi64
38*1fd5a2e1SPrashanth Swaminathan #endif
39*1fd5a2e1SPrashanth Swaminathan
40*1fd5a2e1SPrashanth Swaminathan struct win64_call_frame
41*1fd5a2e1SPrashanth Swaminathan {
42*1fd5a2e1SPrashanth Swaminathan UINT64 rbp; /* 0 */
43*1fd5a2e1SPrashanth Swaminathan UINT64 retaddr; /* 8 */
44*1fd5a2e1SPrashanth Swaminathan UINT64 fn; /* 16 */
45*1fd5a2e1SPrashanth Swaminathan UINT64 flags; /* 24 */
46*1fd5a2e1SPrashanth Swaminathan UINT64 rvalue; /* 32 */
47*1fd5a2e1SPrashanth Swaminathan };
48*1fd5a2e1SPrashanth Swaminathan
49*1fd5a2e1SPrashanth Swaminathan extern void ffi_call_win64 (void *stack, struct win64_call_frame *,
50*1fd5a2e1SPrashanth Swaminathan void *closure) FFI_HIDDEN;
51*1fd5a2e1SPrashanth Swaminathan
52*1fd5a2e1SPrashanth Swaminathan ffi_status FFI_HIDDEN
EFI64(ffi_prep_cif_machdep)53*1fd5a2e1SPrashanth Swaminathan EFI64(ffi_prep_cif_machdep)(ffi_cif *cif)
54*1fd5a2e1SPrashanth Swaminathan {
55*1fd5a2e1SPrashanth Swaminathan int flags, n;
56*1fd5a2e1SPrashanth Swaminathan
57*1fd5a2e1SPrashanth Swaminathan switch (cif->abi)
58*1fd5a2e1SPrashanth Swaminathan {
59*1fd5a2e1SPrashanth Swaminathan case FFI_WIN64:
60*1fd5a2e1SPrashanth Swaminathan case FFI_GNUW64:
61*1fd5a2e1SPrashanth Swaminathan break;
62*1fd5a2e1SPrashanth Swaminathan default:
63*1fd5a2e1SPrashanth Swaminathan return FFI_BAD_ABI;
64*1fd5a2e1SPrashanth Swaminathan }
65*1fd5a2e1SPrashanth Swaminathan
66*1fd5a2e1SPrashanth Swaminathan flags = cif->rtype->type;
67*1fd5a2e1SPrashanth Swaminathan switch (flags)
68*1fd5a2e1SPrashanth Swaminathan {
69*1fd5a2e1SPrashanth Swaminathan default:
70*1fd5a2e1SPrashanth Swaminathan break;
71*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_LONGDOUBLE:
72*1fd5a2e1SPrashanth Swaminathan /* GCC returns long double values by reference, like a struct */
73*1fd5a2e1SPrashanth Swaminathan if (cif->abi == FFI_GNUW64)
74*1fd5a2e1SPrashanth Swaminathan flags = FFI_TYPE_STRUCT;
75*1fd5a2e1SPrashanth Swaminathan break;
76*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_COMPLEX:
77*1fd5a2e1SPrashanth Swaminathan flags = FFI_TYPE_STRUCT;
78*1fd5a2e1SPrashanth Swaminathan /* FALLTHRU */
79*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_STRUCT:
80*1fd5a2e1SPrashanth Swaminathan switch (cif->rtype->size)
81*1fd5a2e1SPrashanth Swaminathan {
82*1fd5a2e1SPrashanth Swaminathan case 8:
83*1fd5a2e1SPrashanth Swaminathan flags = FFI_TYPE_UINT64;
84*1fd5a2e1SPrashanth Swaminathan break;
85*1fd5a2e1SPrashanth Swaminathan case 4:
86*1fd5a2e1SPrashanth Swaminathan flags = FFI_TYPE_SMALL_STRUCT_4B;
87*1fd5a2e1SPrashanth Swaminathan break;
88*1fd5a2e1SPrashanth Swaminathan case 2:
89*1fd5a2e1SPrashanth Swaminathan flags = FFI_TYPE_SMALL_STRUCT_2B;
90*1fd5a2e1SPrashanth Swaminathan break;
91*1fd5a2e1SPrashanth Swaminathan case 1:
92*1fd5a2e1SPrashanth Swaminathan flags = FFI_TYPE_SMALL_STRUCT_1B;
93*1fd5a2e1SPrashanth Swaminathan break;
94*1fd5a2e1SPrashanth Swaminathan }
95*1fd5a2e1SPrashanth Swaminathan break;
96*1fd5a2e1SPrashanth Swaminathan }
97*1fd5a2e1SPrashanth Swaminathan cif->flags = flags;
98*1fd5a2e1SPrashanth Swaminathan
99*1fd5a2e1SPrashanth Swaminathan /* Each argument either fits in a register, an 8 byte slot, or is
100*1fd5a2e1SPrashanth Swaminathan passed by reference with the pointer in the 8 byte slot. */
101*1fd5a2e1SPrashanth Swaminathan n = cif->nargs;
102*1fd5a2e1SPrashanth Swaminathan n += (flags == FFI_TYPE_STRUCT);
103*1fd5a2e1SPrashanth Swaminathan if (n < 4)
104*1fd5a2e1SPrashanth Swaminathan n = 4;
105*1fd5a2e1SPrashanth Swaminathan cif->bytes = n * 8;
106*1fd5a2e1SPrashanth Swaminathan
107*1fd5a2e1SPrashanth Swaminathan return FFI_OK;
108*1fd5a2e1SPrashanth Swaminathan }
109*1fd5a2e1SPrashanth Swaminathan
110*1fd5a2e1SPrashanth Swaminathan static void
ffi_call_int(ffi_cif * cif,void (* fn)(void),void * rvalue,void ** avalue,void * closure)111*1fd5a2e1SPrashanth Swaminathan ffi_call_int (ffi_cif *cif, void (*fn)(void), void *rvalue,
112*1fd5a2e1SPrashanth Swaminathan void **avalue, void *closure)
113*1fd5a2e1SPrashanth Swaminathan {
114*1fd5a2e1SPrashanth Swaminathan int i, j, n, flags;
115*1fd5a2e1SPrashanth Swaminathan UINT64 *stack;
116*1fd5a2e1SPrashanth Swaminathan size_t rsize;
117*1fd5a2e1SPrashanth Swaminathan struct win64_call_frame *frame;
118*1fd5a2e1SPrashanth Swaminathan
119*1fd5a2e1SPrashanth Swaminathan FFI_ASSERT(cif->abi == FFI_GNUW64 || cif->abi == FFI_WIN64);
120*1fd5a2e1SPrashanth Swaminathan
121*1fd5a2e1SPrashanth Swaminathan flags = cif->flags;
122*1fd5a2e1SPrashanth Swaminathan rsize = 0;
123*1fd5a2e1SPrashanth Swaminathan
124*1fd5a2e1SPrashanth Swaminathan /* If we have no return value for a structure, we need to create one.
125*1fd5a2e1SPrashanth Swaminathan Otherwise we can ignore the return type entirely. */
126*1fd5a2e1SPrashanth Swaminathan if (rvalue == NULL)
127*1fd5a2e1SPrashanth Swaminathan {
128*1fd5a2e1SPrashanth Swaminathan if (flags == FFI_TYPE_STRUCT)
129*1fd5a2e1SPrashanth Swaminathan rsize = cif->rtype->size;
130*1fd5a2e1SPrashanth Swaminathan else
131*1fd5a2e1SPrashanth Swaminathan flags = FFI_TYPE_VOID;
132*1fd5a2e1SPrashanth Swaminathan }
133*1fd5a2e1SPrashanth Swaminathan
134*1fd5a2e1SPrashanth Swaminathan stack = alloca(cif->bytes + sizeof(struct win64_call_frame) + rsize);
135*1fd5a2e1SPrashanth Swaminathan frame = (struct win64_call_frame *)((char *)stack + cif->bytes);
136*1fd5a2e1SPrashanth Swaminathan if (rsize)
137*1fd5a2e1SPrashanth Swaminathan rvalue = frame + 1;
138*1fd5a2e1SPrashanth Swaminathan
139*1fd5a2e1SPrashanth Swaminathan frame->fn = (uintptr_t)fn;
140*1fd5a2e1SPrashanth Swaminathan frame->flags = flags;
141*1fd5a2e1SPrashanth Swaminathan frame->rvalue = (uintptr_t)rvalue;
142*1fd5a2e1SPrashanth Swaminathan
143*1fd5a2e1SPrashanth Swaminathan j = 0;
144*1fd5a2e1SPrashanth Swaminathan if (flags == FFI_TYPE_STRUCT)
145*1fd5a2e1SPrashanth Swaminathan {
146*1fd5a2e1SPrashanth Swaminathan stack[0] = (uintptr_t)rvalue;
147*1fd5a2e1SPrashanth Swaminathan j = 1;
148*1fd5a2e1SPrashanth Swaminathan }
149*1fd5a2e1SPrashanth Swaminathan
150*1fd5a2e1SPrashanth Swaminathan for (i = 0, n = cif->nargs; i < n; ++i, ++j)
151*1fd5a2e1SPrashanth Swaminathan {
152*1fd5a2e1SPrashanth Swaminathan switch (cif->arg_types[i]->size)
153*1fd5a2e1SPrashanth Swaminathan {
154*1fd5a2e1SPrashanth Swaminathan case 8:
155*1fd5a2e1SPrashanth Swaminathan stack[j] = *(UINT64 *)avalue[i];
156*1fd5a2e1SPrashanth Swaminathan break;
157*1fd5a2e1SPrashanth Swaminathan case 4:
158*1fd5a2e1SPrashanth Swaminathan stack[j] = *(UINT32 *)avalue[i];
159*1fd5a2e1SPrashanth Swaminathan break;
160*1fd5a2e1SPrashanth Swaminathan case 2:
161*1fd5a2e1SPrashanth Swaminathan stack[j] = *(UINT16 *)avalue[i];
162*1fd5a2e1SPrashanth Swaminathan break;
163*1fd5a2e1SPrashanth Swaminathan case 1:
164*1fd5a2e1SPrashanth Swaminathan stack[j] = *(UINT8 *)avalue[i];
165*1fd5a2e1SPrashanth Swaminathan break;
166*1fd5a2e1SPrashanth Swaminathan default:
167*1fd5a2e1SPrashanth Swaminathan stack[j] = (uintptr_t)avalue[i];
168*1fd5a2e1SPrashanth Swaminathan break;
169*1fd5a2e1SPrashanth Swaminathan }
170*1fd5a2e1SPrashanth Swaminathan }
171*1fd5a2e1SPrashanth Swaminathan
172*1fd5a2e1SPrashanth Swaminathan ffi_call_win64 (stack, frame, closure);
173*1fd5a2e1SPrashanth Swaminathan }
174*1fd5a2e1SPrashanth Swaminathan
175*1fd5a2e1SPrashanth Swaminathan void
EFI64(ffi_call)176*1fd5a2e1SPrashanth Swaminathan EFI64(ffi_call)(ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue)
177*1fd5a2e1SPrashanth Swaminathan {
178*1fd5a2e1SPrashanth Swaminathan ffi_call_int (cif, fn, rvalue, avalue, NULL);
179*1fd5a2e1SPrashanth Swaminathan }
180*1fd5a2e1SPrashanth Swaminathan
181*1fd5a2e1SPrashanth Swaminathan void
EFI64(ffi_call_go)182*1fd5a2e1SPrashanth Swaminathan EFI64(ffi_call_go)(ffi_cif *cif, void (*fn)(void), void *rvalue,
183*1fd5a2e1SPrashanth Swaminathan void **avalue, void *closure)
184*1fd5a2e1SPrashanth Swaminathan {
185*1fd5a2e1SPrashanth Swaminathan ffi_call_int (cif, fn, rvalue, avalue, closure);
186*1fd5a2e1SPrashanth Swaminathan }
187*1fd5a2e1SPrashanth Swaminathan
188*1fd5a2e1SPrashanth Swaminathan
189*1fd5a2e1SPrashanth Swaminathan extern void ffi_closure_win64(void) FFI_HIDDEN;
190*1fd5a2e1SPrashanth Swaminathan extern void ffi_go_closure_win64(void) FFI_HIDDEN;
191*1fd5a2e1SPrashanth Swaminathan
192*1fd5a2e1SPrashanth Swaminathan ffi_status
EFI64(ffi_prep_closure_loc)193*1fd5a2e1SPrashanth Swaminathan EFI64(ffi_prep_closure_loc)(ffi_closure* closure,
194*1fd5a2e1SPrashanth Swaminathan ffi_cif* cif,
195*1fd5a2e1SPrashanth Swaminathan void (*fun)(ffi_cif*, void*, void**, void*),
196*1fd5a2e1SPrashanth Swaminathan void *user_data,
197*1fd5a2e1SPrashanth Swaminathan void *codeloc)
198*1fd5a2e1SPrashanth Swaminathan {
199*1fd5a2e1SPrashanth Swaminathan static const unsigned char trampoline[16] = {
200*1fd5a2e1SPrashanth Swaminathan /* leaq -0x7(%rip),%r10 # 0x0 */
201*1fd5a2e1SPrashanth Swaminathan 0x4c, 0x8d, 0x15, 0xf9, 0xff, 0xff, 0xff,
202*1fd5a2e1SPrashanth Swaminathan /* jmpq *0x3(%rip) # 0x10 */
203*1fd5a2e1SPrashanth Swaminathan 0xff, 0x25, 0x03, 0x00, 0x00, 0x00,
204*1fd5a2e1SPrashanth Swaminathan /* nopl (%rax) */
205*1fd5a2e1SPrashanth Swaminathan 0x0f, 0x1f, 0x00
206*1fd5a2e1SPrashanth Swaminathan };
207*1fd5a2e1SPrashanth Swaminathan char *tramp = closure->tramp;
208*1fd5a2e1SPrashanth Swaminathan
209*1fd5a2e1SPrashanth Swaminathan switch (cif->abi)
210*1fd5a2e1SPrashanth Swaminathan {
211*1fd5a2e1SPrashanth Swaminathan case FFI_WIN64:
212*1fd5a2e1SPrashanth Swaminathan case FFI_GNUW64:
213*1fd5a2e1SPrashanth Swaminathan break;
214*1fd5a2e1SPrashanth Swaminathan default:
215*1fd5a2e1SPrashanth Swaminathan return FFI_BAD_ABI;
216*1fd5a2e1SPrashanth Swaminathan }
217*1fd5a2e1SPrashanth Swaminathan
218*1fd5a2e1SPrashanth Swaminathan memcpy (tramp, trampoline, sizeof(trampoline));
219*1fd5a2e1SPrashanth Swaminathan *(UINT64 *)(tramp + 16) = (uintptr_t)ffi_closure_win64;
220*1fd5a2e1SPrashanth Swaminathan
221*1fd5a2e1SPrashanth Swaminathan closure->cif = cif;
222*1fd5a2e1SPrashanth Swaminathan closure->fun = fun;
223*1fd5a2e1SPrashanth Swaminathan closure->user_data = user_data;
224*1fd5a2e1SPrashanth Swaminathan
225*1fd5a2e1SPrashanth Swaminathan return FFI_OK;
226*1fd5a2e1SPrashanth Swaminathan }
227*1fd5a2e1SPrashanth Swaminathan
228*1fd5a2e1SPrashanth Swaminathan ffi_status
EFI64(ffi_prep_go_closure)229*1fd5a2e1SPrashanth Swaminathan EFI64(ffi_prep_go_closure)(ffi_go_closure* closure, ffi_cif* cif,
230*1fd5a2e1SPrashanth Swaminathan void (*fun)(ffi_cif*, void*, void**, void*))
231*1fd5a2e1SPrashanth Swaminathan {
232*1fd5a2e1SPrashanth Swaminathan switch (cif->abi)
233*1fd5a2e1SPrashanth Swaminathan {
234*1fd5a2e1SPrashanth Swaminathan case FFI_WIN64:
235*1fd5a2e1SPrashanth Swaminathan case FFI_GNUW64:
236*1fd5a2e1SPrashanth Swaminathan break;
237*1fd5a2e1SPrashanth Swaminathan default:
238*1fd5a2e1SPrashanth Swaminathan return FFI_BAD_ABI;
239*1fd5a2e1SPrashanth Swaminathan }
240*1fd5a2e1SPrashanth Swaminathan
241*1fd5a2e1SPrashanth Swaminathan closure->tramp = ffi_go_closure_win64;
242*1fd5a2e1SPrashanth Swaminathan closure->cif = cif;
243*1fd5a2e1SPrashanth Swaminathan closure->fun = fun;
244*1fd5a2e1SPrashanth Swaminathan
245*1fd5a2e1SPrashanth Swaminathan return FFI_OK;
246*1fd5a2e1SPrashanth Swaminathan }
247*1fd5a2e1SPrashanth Swaminathan
248*1fd5a2e1SPrashanth Swaminathan struct win64_closure_frame
249*1fd5a2e1SPrashanth Swaminathan {
250*1fd5a2e1SPrashanth Swaminathan UINT64 rvalue[2];
251*1fd5a2e1SPrashanth Swaminathan UINT64 fargs[4];
252*1fd5a2e1SPrashanth Swaminathan UINT64 retaddr;
253*1fd5a2e1SPrashanth Swaminathan UINT64 args[];
254*1fd5a2e1SPrashanth Swaminathan };
255*1fd5a2e1SPrashanth Swaminathan
256*1fd5a2e1SPrashanth Swaminathan /* Force the inner function to use the MS ABI. When compiling on win64
257*1fd5a2e1SPrashanth Swaminathan this is a nop. When compiling on unix, this simplifies the assembly,
258*1fd5a2e1SPrashanth Swaminathan and places the burden of saving the extra call-saved registers on
259*1fd5a2e1SPrashanth Swaminathan the compiler. */
260*1fd5a2e1SPrashanth Swaminathan int FFI_HIDDEN __attribute__((ms_abi))
ffi_closure_win64_inner(ffi_cif * cif,void (* fun)(ffi_cif *,void *,void **,void *),void * user_data,struct win64_closure_frame * frame)261*1fd5a2e1SPrashanth Swaminathan ffi_closure_win64_inner(ffi_cif *cif,
262*1fd5a2e1SPrashanth Swaminathan void (*fun)(ffi_cif*, void*, void**, void*),
263*1fd5a2e1SPrashanth Swaminathan void *user_data,
264*1fd5a2e1SPrashanth Swaminathan struct win64_closure_frame *frame)
265*1fd5a2e1SPrashanth Swaminathan {
266*1fd5a2e1SPrashanth Swaminathan void **avalue;
267*1fd5a2e1SPrashanth Swaminathan void *rvalue;
268*1fd5a2e1SPrashanth Swaminathan int i, n, nreg, flags;
269*1fd5a2e1SPrashanth Swaminathan
270*1fd5a2e1SPrashanth Swaminathan avalue = alloca(cif->nargs * sizeof(void *));
271*1fd5a2e1SPrashanth Swaminathan rvalue = frame->rvalue;
272*1fd5a2e1SPrashanth Swaminathan nreg = 0;
273*1fd5a2e1SPrashanth Swaminathan
274*1fd5a2e1SPrashanth Swaminathan /* When returning a structure, the address is in the first argument.
275*1fd5a2e1SPrashanth Swaminathan We must also be prepared to return the same address in eax, so
276*1fd5a2e1SPrashanth Swaminathan install that address in the frame and pretend we return a pointer. */
277*1fd5a2e1SPrashanth Swaminathan flags = cif->flags;
278*1fd5a2e1SPrashanth Swaminathan if (flags == FFI_TYPE_STRUCT)
279*1fd5a2e1SPrashanth Swaminathan {
280*1fd5a2e1SPrashanth Swaminathan rvalue = (void *)(uintptr_t)frame->args[0];
281*1fd5a2e1SPrashanth Swaminathan frame->rvalue[0] = frame->args[0];
282*1fd5a2e1SPrashanth Swaminathan nreg = 1;
283*1fd5a2e1SPrashanth Swaminathan }
284*1fd5a2e1SPrashanth Swaminathan
285*1fd5a2e1SPrashanth Swaminathan for (i = 0, n = cif->nargs; i < n; ++i, ++nreg)
286*1fd5a2e1SPrashanth Swaminathan {
287*1fd5a2e1SPrashanth Swaminathan size_t size = cif->arg_types[i]->size;
288*1fd5a2e1SPrashanth Swaminathan size_t type = cif->arg_types[i]->type;
289*1fd5a2e1SPrashanth Swaminathan void *a;
290*1fd5a2e1SPrashanth Swaminathan
291*1fd5a2e1SPrashanth Swaminathan if (type == FFI_TYPE_DOUBLE || type == FFI_TYPE_FLOAT)
292*1fd5a2e1SPrashanth Swaminathan {
293*1fd5a2e1SPrashanth Swaminathan if (nreg < 4)
294*1fd5a2e1SPrashanth Swaminathan a = &frame->fargs[nreg];
295*1fd5a2e1SPrashanth Swaminathan else
296*1fd5a2e1SPrashanth Swaminathan a = &frame->args[nreg];
297*1fd5a2e1SPrashanth Swaminathan }
298*1fd5a2e1SPrashanth Swaminathan else if (size == 1 || size == 2 || size == 4 || size == 8)
299*1fd5a2e1SPrashanth Swaminathan a = &frame->args[nreg];
300*1fd5a2e1SPrashanth Swaminathan else
301*1fd5a2e1SPrashanth Swaminathan a = (void *)(uintptr_t)frame->args[nreg];
302*1fd5a2e1SPrashanth Swaminathan
303*1fd5a2e1SPrashanth Swaminathan avalue[i] = a;
304*1fd5a2e1SPrashanth Swaminathan }
305*1fd5a2e1SPrashanth Swaminathan
306*1fd5a2e1SPrashanth Swaminathan /* Invoke the closure. */
307*1fd5a2e1SPrashanth Swaminathan fun (cif, rvalue, avalue, user_data);
308*1fd5a2e1SPrashanth Swaminathan return flags;
309*1fd5a2e1SPrashanth Swaminathan }
310*1fd5a2e1SPrashanth Swaminathan
311*1fd5a2e1SPrashanth Swaminathan #endif /* __x86_64__ */
312