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