72bed06796e42c0608c24eef67f4136af1e28925
[platform/upstream/libffi.git] / src / x86 / ffi.c
1 /* -----------------------------------------------------------------------
2    ffi.c - Copyright (c) 1996, 1998, 1999, 2001, 2007, 2008  Red Hat, Inc.
3            Copyright (c) 2002  Ranjit Mathew
4            Copyright (c) 2002  Bo Thorsen
5            Copyright (c) 2002  Roger Sayle
6            Copyright (C) 2008, 2010  Free Software Foundation, Inc.
7
8    x86 Foreign Function Interface
9
10    Permission is hereby granted, free of charge, to any person obtaining
11    a copy of this software and associated documentation files (the
12    ``Software''), to deal in the Software without restriction, including
13    without limitation the rights to use, copy, modify, merge, publish,
14    distribute, sublicense, and/or sell copies of the Software, and to
15    permit persons to whom the Software is furnished to do so, subject to
16    the following conditions:
17
18    The above copyright notice and this permission notice shall be included
19    in all copies or substantial portions of the Software.
20
21    THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND,
22    EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
23    MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
24    NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
25    HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
26    WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
27    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
28    DEALINGS IN THE SOFTWARE.
29    ----------------------------------------------------------------------- */
30
31 #if !defined(__x86_64__) || defined(_WIN64)
32
33 #ifdef _WIN64
34 #include <windows.h>
35 #endif
36
37 #include <ffi.h>
38 #include <ffi_common.h>
39
40 #include <stdlib.h>
41
42
43 /* ffi_prep_args is called by the assembly routine once stack space
44    has been allocated for the function's arguments */
45
46 void ffi_prep_args(char *stack, extended_cif *ecif);
47 void ffi_prep_args(char *stack, extended_cif *ecif)
48 {
49   register unsigned int i;
50   register void **p_argv;
51   register char *argp;
52   register ffi_type **p_arg;
53 #ifndef X86_WIN64
54   size_t p_stack_args[2];
55   void *p_stack_data[2];
56   char *argp2 = stack;
57   int stack_args_count = 0;
58   int cabi = ecif->cif->abi;
59 #endif
60
61   argp = stack;
62
63   if ((ecif->cif->flags == FFI_TYPE_STRUCT
64        || ecif->cif->flags == FFI_TYPE_MS_STRUCT)
65 #ifdef X86_WIN64
66       && (ecif->cif->rtype->size != 1 && ecif->cif->rtype->size != 2
67           && ecif->cif->rtype->size != 4 && ecif->cif->rtype->size != 8)
68 #endif
69       )
70     {
71       *(void **) argp = ecif->rvalue;
72 #ifndef X86_WIN64
73       /* For fastcall/thiscall this is first register-passed
74          argument.  */
75       if (cabi == FFI_THISCALL || cabi == FFI_FASTCALL)
76         {
77           p_stack_args[stack_args_count] = sizeof (void*);
78           p_stack_data[stack_args_count] = argp;
79           ++stack_args_count;
80         }
81 #endif
82       argp += sizeof(void*);
83     }
84
85   p_argv = ecif->avalue;
86
87   for (i = ecif->cif->nargs, p_arg = ecif->cif->arg_types;
88        i != 0;
89        i--, p_arg++)
90     {
91       size_t z;
92
93       /* Align if necessary */
94       if ((sizeof(void*) - 1) & (size_t) argp)
95         argp = (char *) ALIGN(argp, sizeof(void*));
96
97       z = (*p_arg)->size;
98 #ifdef X86_WIN64
99       if (z > sizeof(ffi_arg)
100           || ((*p_arg)->type == FFI_TYPE_STRUCT
101               && (z != 1 && z != 2 && z != 4 && z != 8))
102 #if FFI_TYPE_DOUBLE != FFI_TYPE_LONGDOUBLE
103           || ((*p_arg)->type == FFI_TYPE_LONGDOUBLE)
104 #endif
105           )
106         {
107           z = sizeof(ffi_arg);
108           *(void **)argp = *p_argv;
109         }
110       else if ((*p_arg)->type == FFI_TYPE_FLOAT)
111         {
112           memcpy(argp, *p_argv, z);
113         }
114       else
115 #endif
116       if (z < sizeof(ffi_arg))
117         {
118           z = sizeof(ffi_arg);
119           switch ((*p_arg)->type)
120             {
121             case FFI_TYPE_SINT8:
122               *(ffi_sarg *) argp = (ffi_sarg)*(SINT8 *)(* p_argv);
123               break;
124
125             case FFI_TYPE_UINT8:
126               *(ffi_arg *) argp = (ffi_arg)*(UINT8 *)(* p_argv);
127               break;
128
129             case FFI_TYPE_SINT16:
130               *(ffi_sarg *) argp = (ffi_sarg)*(SINT16 *)(* p_argv);
131               break;
132
133             case FFI_TYPE_UINT16:
134               *(ffi_arg *) argp = (ffi_arg)*(UINT16 *)(* p_argv);
135               break;
136
137             case FFI_TYPE_SINT32:
138               *(ffi_sarg *) argp = (ffi_sarg)*(SINT32 *)(* p_argv);
139               break;
140
141             case FFI_TYPE_UINT32:
142               *(ffi_arg *) argp = (ffi_arg)*(UINT32 *)(* p_argv);
143               break;
144
145             case FFI_TYPE_STRUCT:
146               *(ffi_arg *) argp = *(ffi_arg *)(* p_argv);
147               break;
148
149             default:
150               FFI_ASSERT(0);
151             }
152         }
153       else
154         {
155           memcpy(argp, *p_argv, z);
156         }
157
158 #ifndef X86_WIN64
159     /* For thiscall/fastcall convention register-passed arguments
160        are the first two none-floating-point arguments with a size
161        smaller or equal to sizeof (void*).  */
162     if ((cabi == FFI_THISCALL && stack_args_count < 1)
163         || (cabi == FFI_FASTCALL && stack_args_count < 2))
164       {
165         if (z <= 4
166             && ((*p_arg)->type != FFI_TYPE_FLOAT
167                 && (*p_arg)->type != FFI_TYPE_STRUCT))
168           {
169             p_stack_args[stack_args_count] = z;
170             p_stack_data[stack_args_count] = argp;
171             ++stack_args_count;
172           }
173       }
174 #endif
175       p_argv++;
176 #ifdef X86_WIN64
177       argp += (z + sizeof(void*) - 1) & ~(sizeof(void*) - 1);
178 #else
179       argp += z;
180 #endif
181     }
182
183 #ifndef X86_WIN64
184   /* We need to move the register-passed arguments for thiscall/fastcall
185      on top of stack, so that those can be moved to registers ecx/edx by
186      call-handler.  */
187   if (stack_args_count > 0)
188     {
189       size_t zz = (p_stack_args[0] + 3) & ~3;
190       char *h;
191
192       /* Move first argument to top-stack position.  */
193       if (p_stack_data[0] != argp2)
194         {
195           h = alloca (zz + 1);
196           memcpy (h, p_stack_data[0], zz);
197           memmove (argp2 + zz, argp2,
198                    (size_t) ((char *) p_stack_data[0] - (char*)argp2));
199           memcpy (argp2, h, zz);
200         }
201
202       argp2 += zz;
203       --stack_args_count;
204       if (zz > 4)
205         stack_args_count = 0;
206
207       /* If we have a second argument, then move it on top
208          after the first one.  */
209       if (stack_args_count > 0 && p_stack_data[1] != argp2)
210         {
211           zz = p_stack_args[1];
212           zz = (zz + 3) & ~3;
213           h = alloca (zz + 1);
214           h = alloca (zz + 1);
215           memcpy (h, p_stack_data[1], zz);
216           memmove (argp2 + zz, argp2, (size_t) ((char*) p_stack_data[1] - (char*)argp2));
217           memcpy (argp2, h, zz);
218         }
219     }
220 #endif
221   return;
222 }
223
224 /* Perform machine dependent cif processing */
225 ffi_status ffi_prep_cif_machdep(ffi_cif *cif)
226 {
227   unsigned int i;
228   ffi_type **ptr;
229
230   /* Set the return type flag */
231   switch (cif->rtype->type)
232     {
233     case FFI_TYPE_VOID:
234     case FFI_TYPE_UINT8:
235     case FFI_TYPE_UINT16:
236     case FFI_TYPE_SINT8:
237     case FFI_TYPE_SINT16:
238 #ifdef X86_WIN64
239     case FFI_TYPE_UINT32:
240     case FFI_TYPE_SINT32:
241 #endif
242     case FFI_TYPE_SINT64:
243     case FFI_TYPE_FLOAT:
244     case FFI_TYPE_DOUBLE:
245 #ifndef X86_WIN64
246 #if FFI_TYPE_DOUBLE != FFI_TYPE_LONGDOUBLE
247     case FFI_TYPE_LONGDOUBLE:
248 #endif
249 #endif
250       cif->flags = (unsigned) cif->rtype->type;
251       break;
252
253     case FFI_TYPE_UINT64:
254 #ifdef X86_WIN64
255     case FFI_TYPE_POINTER:
256 #endif
257       cif->flags = FFI_TYPE_SINT64;
258       break;
259
260     case FFI_TYPE_STRUCT:
261 #ifndef X86
262       if (cif->rtype->size == 1)
263         {
264           cif->flags = FFI_TYPE_SMALL_STRUCT_1B; /* same as char size */
265         }
266       else if (cif->rtype->size == 2)
267         {
268           cif->flags = FFI_TYPE_SMALL_STRUCT_2B; /* same as short size */
269         }
270       else if (cif->rtype->size == 4)
271         {
272 #ifdef X86_WIN64
273           cif->flags = FFI_TYPE_SMALL_STRUCT_4B;
274 #else
275           cif->flags = FFI_TYPE_INT; /* same as int type */
276 #endif
277         }
278       else if (cif->rtype->size == 8)
279         {
280           cif->flags = FFI_TYPE_SINT64; /* same as int64 type */
281         }
282       else
283 #endif
284         {
285 #ifdef X86_WIN32
286           if (cif->abi == FFI_MS_CDECL)
287             cif->flags = FFI_TYPE_MS_STRUCT;
288           else
289 #endif
290             cif->flags = FFI_TYPE_STRUCT;
291           /* allocate space for return value pointer */
292           cif->bytes += ALIGN(sizeof(void*), FFI_SIZEOF_ARG);
293         }
294       break;
295
296     default:
297 #ifdef X86_WIN64
298       cif->flags = FFI_TYPE_SINT64;
299       break;
300     case FFI_TYPE_INT:
301       cif->flags = FFI_TYPE_SINT32;
302 #else
303       cif->flags = FFI_TYPE_INT;
304 #endif
305       break;
306     }
307
308   for (ptr = cif->arg_types, i = cif->nargs; i > 0; i--, ptr++)
309     {
310       if (((*ptr)->alignment - 1) & cif->bytes)
311         cif->bytes = ALIGN(cif->bytes, (*ptr)->alignment);
312       cif->bytes += (unsigned)ALIGN((*ptr)->size, FFI_SIZEOF_ARG);
313     }
314
315 #ifdef X86_WIN64
316   /* ensure space for storing four registers */
317   cif->bytes += 4 * sizeof(ffi_arg);
318 #endif
319
320 #ifndef X86_WIN32
321 #ifndef X86_WIN64
322   if (cif->abi != FFI_STDCALL && cif->abi != FFI_THISCALL && cif->abi != FFI_FASTCALL)
323 #endif
324     cif->bytes = (cif->bytes + 15) & ~0xF;
325 #endif
326
327   return FFI_OK;
328 }
329
330 #ifdef X86_WIN64
331 extern int
332 ffi_call_win64(void (*)(char *, extended_cif *), extended_cif *,
333                unsigned, unsigned, unsigned *, void (*fn)(void));
334 #else
335 extern void
336 ffi_call_win32(void (*)(char *, extended_cif *), extended_cif *,
337                unsigned, unsigned, unsigned, unsigned *, void (*fn)(void));
338 extern void ffi_call_SYSV(void (*)(char *, extended_cif *), extended_cif *,
339                           unsigned, unsigned, unsigned *, void (*fn)(void));
340 #endif
341
342 void ffi_call(ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue)
343 {
344   extended_cif ecif;
345
346   ecif.cif = cif;
347   ecif.avalue = avalue;
348   
349   /* If the return value is a struct and we don't have a return */
350   /* value address then we need to make one                     */
351
352 #ifdef X86_WIN64
353   if (rvalue == NULL
354       && cif->flags == FFI_TYPE_STRUCT
355       && cif->rtype->size != 1 && cif->rtype->size != 2
356       && cif->rtype->size != 4 && cif->rtype->size != 8)
357     {
358       ecif.rvalue = alloca((cif->rtype->size + 0xF) & ~0xF);
359     }
360 #else
361   if (rvalue == NULL
362       && (cif->flags == FFI_TYPE_STRUCT
363           || cif->flags == FFI_TYPE_MS_STRUCT))
364     {
365       ecif.rvalue = alloca(cif->rtype->size);
366     }
367 #endif
368   else
369     ecif.rvalue = rvalue;
370     
371   
372   switch (cif->abi) 
373     {
374 #ifdef X86_WIN64
375     case FFI_WIN64:
376       ffi_call_win64(ffi_prep_args, &ecif, cif->bytes,
377                      cif->flags, ecif.rvalue, fn);
378       break;
379 #else
380 #ifndef X86_WIN32
381     case FFI_SYSV:
382       ffi_call_SYSV(ffi_prep_args, &ecif, cif->bytes, cif->flags, ecif.rvalue,
383                     fn);
384       break;
385 #else
386     case FFI_SYSV:
387     case FFI_MS_CDECL:
388 #endif
389     case FFI_STDCALL:
390       ffi_call_win32(ffi_prep_args, &ecif, cif->abi, cif->bytes, cif->flags,
391                      ecif.rvalue, fn);
392       break;
393     case FFI_THISCALL:
394     case FFI_FASTCALL:
395       {
396         unsigned int abi = cif->abi;
397         unsigned int i, passed_regs = 0;
398
399         if (cif->flags == FFI_TYPE_STRUCT)
400           ++passed_regs;
401
402         for (i=0; i < cif->nargs && passed_regs < 2;i++)
403           {
404             size_t sz;
405
406             if (cif->arg_types[i]->type == FFI_TYPE_FLOAT
407                 || cif->arg_types[i]->type == FFI_TYPE_STRUCT)
408               continue;
409             sz = (cif->arg_types[i]->size + 3) & ~3;
410             if (sz == 0 || sz > 4)
411               continue;
412             ++passed_regs;
413           }
414         if (passed_regs < 2 && abi == FFI_FASTCALL)
415           abi = FFI_THISCALL;
416         if (passed_regs < 1 && abi == FFI_THISCALL)
417           abi = FFI_STDCALL;
418         ffi_call_win32(ffi_prep_args, &ecif, abi, cif->bytes, cif->flags,
419                        ecif.rvalue, fn);
420       }
421       break;
422 #endif
423     default:
424       FFI_ASSERT(0);
425       break;
426     }
427 }
428
429
430 /** private members **/
431
432 /* The following __attribute__((regparm(1))) decorations will have no effect
433    on MSVC or SUNPRO_C -- standard conventions apply. */
434 static void ffi_prep_incoming_args_SYSV (char *stack, void **ret,
435                                          void** args, ffi_cif* cif);
436 void FFI_HIDDEN ffi_closure_SYSV (ffi_closure *)
437      __attribute__ ((regparm(1)));
438 unsigned int FFI_HIDDEN ffi_closure_SYSV_inner (ffi_closure *, void **, void *)
439      __attribute__ ((regparm(1)));
440 void FFI_HIDDEN ffi_closure_raw_SYSV (ffi_raw_closure *)
441      __attribute__ ((regparm(1)));
442 #ifdef X86_WIN32
443 void FFI_HIDDEN ffi_closure_raw_THISCALL (ffi_raw_closure *)
444      __attribute__ ((regparm(1)));
445 #endif
446 #ifndef X86_WIN64
447 void FFI_HIDDEN ffi_closure_STDCALL (ffi_closure *)
448      __attribute__ ((regparm(1)));
449 void FFI_HIDDEN ffi_closure_THISCALL (ffi_closure *)
450      __attribute__ ((regparm(1)));
451 #else
452 void FFI_HIDDEN ffi_closure_win64 (ffi_closure *);
453 #endif
454
455 /* This function is jumped to by the trampoline */
456
457 #ifdef X86_WIN64
458 void * FFI_HIDDEN
459 ffi_closure_win64_inner (ffi_closure *closure, void *args) {
460   ffi_cif       *cif;
461   void         **arg_area;
462   void          *result;
463   void          *resp = &result;
464
465   cif         = closure->cif;
466   arg_area    = (void**) alloca (cif->nargs * sizeof (void*));  
467
468   /* this call will initialize ARG_AREA, such that each
469    * element in that array points to the corresponding 
470    * value on the stack; and if the function returns
471    * a structure, it will change RESP to point to the
472    * structure return address.  */
473
474   ffi_prep_incoming_args_SYSV(args, &resp, arg_area, cif);
475   
476   (closure->fun) (cif, resp, arg_area, closure->user_data);
477
478   /* The result is returned in rax.  This does the right thing for
479      result types except for floats; we have to 'mov xmm0, rax' in the
480      caller to correct this.
481      TODO: structure sizes of 3 5 6 7 are returned by reference, too!!!
482   */
483   return cif->rtype->size > sizeof(void *) ? resp : *(void **)resp;
484 }
485
486 #else
487 unsigned int FFI_HIDDEN __attribute__ ((regparm(1)))
488 ffi_closure_SYSV_inner (ffi_closure *closure, void **respp, void *args)
489 {
490   /* our various things...  */
491   ffi_cif       *cif;
492   void         **arg_area;
493
494   cif         = closure->cif;
495   arg_area    = (void**) alloca (cif->nargs * sizeof (void*));  
496
497   /* this call will initialize ARG_AREA, such that each
498    * element in that array points to the corresponding 
499    * value on the stack; and if the function returns
500    * a structure, it will change RESP to point to the
501    * structure return address.  */
502
503   ffi_prep_incoming_args_SYSV(args, respp, arg_area, cif);
504
505   (closure->fun) (cif, *respp, arg_area, closure->user_data);
506
507   return cif->flags;
508 }
509 #endif /* !X86_WIN64 */
510
511 static void
512 ffi_prep_incoming_args_SYSV(char *stack, void **rvalue, void **avalue,
513                             ffi_cif *cif)
514 {
515   register unsigned int i;
516   register void **p_argv;
517   register char *argp;
518   register ffi_type **p_arg;
519
520   argp = stack;
521
522 #ifdef X86_WIN64
523   if (cif->rtype->size > sizeof(ffi_arg)
524       || (cif->flags == FFI_TYPE_STRUCT
525           && (cif->rtype->size != 1 && cif->rtype->size != 2
526               && cif->rtype->size != 4 && cif->rtype->size != 8))) {
527     *rvalue = *(void **) argp;
528     argp += sizeof(void *);
529   }
530 #else
531   if ( cif->flags == FFI_TYPE_STRUCT
532        || cif->flags == FFI_TYPE_MS_STRUCT ) {
533     *rvalue = *(void **) argp;
534     argp += sizeof(void *);
535   }
536 #endif
537
538   p_argv = avalue;
539
540   for (i = cif->nargs, p_arg = cif->arg_types; (i != 0); i--, p_arg++)
541     {
542       size_t z;
543
544       /* Align if necessary */
545       if ((sizeof(void*) - 1) & (size_t) argp) {
546         argp = (char *) ALIGN(argp, sizeof(void*));
547       }
548
549 #ifdef X86_WIN64
550       if ((*p_arg)->size > sizeof(ffi_arg)
551           || ((*p_arg)->type == FFI_TYPE_STRUCT
552               && ((*p_arg)->size != 1 && (*p_arg)->size != 2
553                   && (*p_arg)->size != 4 && (*p_arg)->size != 8)))
554         {
555           z = sizeof(void *);
556           *p_argv = *(void **)argp;
557         }
558       else
559 #endif
560         {
561           z = (*p_arg)->size;
562           
563           /* because we're little endian, this is what it turns into.   */
564           
565           *p_argv = (void*) argp;
566         }
567           
568       p_argv++;
569 #ifdef X86_WIN64
570       argp += (z + sizeof(void*) - 1) & ~(sizeof(void*) - 1);
571 #else
572       argp += z;
573 #endif
574     }
575   
576   return;
577 }
578
579 #define FFI_INIT_TRAMPOLINE_WIN64(TRAMP,FUN,CTX,MASK) \
580 { unsigned char *__tramp = (unsigned char*)(TRAMP); \
581    void*  __fun = (void*)(FUN); \
582    void*  __ctx = (void*)(CTX); \
583    *(unsigned char*) &__tramp[0] = 0x41; \
584    *(unsigned char*) &__tramp[1] = 0xbb; \
585    *(unsigned int*) &__tramp[2] = MASK; /* mov $mask, %r11 */ \
586    *(unsigned char*) &__tramp[6] = 0x48; \
587    *(unsigned char*) &__tramp[7] = 0xb8; \
588    *(void**) &__tramp[8] = __ctx; /* mov __ctx, %rax */ \
589    *(unsigned char *)  &__tramp[16] = 0x49; \
590    *(unsigned char *)  &__tramp[17] = 0xba; \
591    *(void**) &__tramp[18] = __fun; /* mov __fun, %r10 */ \
592    *(unsigned char *)  &__tramp[26] = 0x41; \
593    *(unsigned char *)  &__tramp[27] = 0xff; \
594    *(unsigned char *)  &__tramp[28] = 0xe2; /* jmp %r10 */ \
595  }
596
597 /* How to make a trampoline.  Derived from gcc/config/i386/i386.c. */
598
599 #define FFI_INIT_TRAMPOLINE(TRAMP,FUN,CTX) \
600 { unsigned char *__tramp = (unsigned char*)(TRAMP); \
601    unsigned int  __fun = (unsigned int)(FUN); \
602    unsigned int  __ctx = (unsigned int)(CTX); \
603    unsigned int  __dis = __fun - (__ctx + 10);  \
604    *(unsigned char*) &__tramp[0] = 0xb8; \
605    *(unsigned int*)  &__tramp[1] = __ctx; /* movl __ctx, %eax */ \
606    *(unsigned char *)  &__tramp[5] = 0xe9; \
607    *(unsigned int*)  &__tramp[6] = __dis; /* jmp __fun  */ \
608  }
609
610 #define FFI_INIT_TRAMPOLINE_RAW_THISCALL(TRAMP,FUN,CTX,SIZE) \
611 { unsigned char *__tramp = (unsigned char*)(TRAMP); \
612    unsigned int  __fun = (unsigned int)(FUN); \
613    unsigned int  __ctx = (unsigned int)(CTX); \
614    unsigned int  __dis = __fun - (__ctx + 49);  \
615    unsigned short __size = (unsigned short)(SIZE); \
616    *(unsigned int *) &__tramp[0] = 0x8324048b;  /* mov (%esp), %eax */ \
617    *(unsigned int *) &__tramp[4] = 0x4c890cec;  /* sub $12, %esp */ \
618    *(unsigned int *) &__tramp[8] = 0x04890424;  /* mov %ecx, 4(%esp) */ \
619    *(unsigned char*) &__tramp[12] = 0x24;       /* mov %eax, (%esp) */ \
620    *(unsigned char*) &__tramp[13] = 0xb8; \
621    *(unsigned int *) &__tramp[14] = __size;     /* mov __size, %eax */ \
622    *(unsigned int *) &__tramp[18] = 0x08244c8d; /* lea 8(%esp), %ecx */ \
623    *(unsigned int *) &__tramp[22] = 0x4802e8c1; /* shr $2, %eax ; dec %eax */ \
624    *(unsigned short*) &__tramp[26] = 0x0b74;    /* jz 1f */ \
625    *(unsigned int *) &__tramp[28] = 0x8908518b; /* 2b: mov 8(%ecx), %edx */ \
626    *(unsigned int *) &__tramp[32] = 0x04c18311; /* mov %edx, (%ecx) ; add $4, %ecx */ \
627    *(unsigned char*) &__tramp[36] = 0x48;       /* dec %eax */ \
628    *(unsigned short*) &__tramp[37] = 0xf575;    /* jnz 2b ; 1f: */ \
629    *(unsigned char*) &__tramp[39] = 0xb8; \
630    *(unsigned int*)  &__tramp[40] = __ctx; /* movl __ctx, %eax */ \
631    *(unsigned char *)  &__tramp[44] = 0xe8; \
632    *(unsigned int*)  &__tramp[45] = __dis; /* call __fun  */ \
633    *(unsigned char*)  &__tramp[49] = 0xc2; /* ret  */ \
634    *(unsigned short*)  &__tramp[50] = (__size + 8); /* ret (__size + 8)  */ \
635  }
636
637 #define FFI_INIT_TRAMPOLINE_STDCALL(TRAMP,FUN,CTX)  \
638 { unsigned char *__tramp = (unsigned char*)(TRAMP); \
639    unsigned int  __fun = (unsigned int)(FUN); \
640    unsigned int  __ctx = (unsigned int)(CTX); \
641    unsigned int  __dis = __fun - (__ctx + 10); \
642    *(unsigned char*) &__tramp[0] = 0xb8; \
643    *(unsigned int*)  &__tramp[1] = __ctx; /* movl __ctx, %eax */ \
644    *(unsigned char *)  &__tramp[5] = 0xe8; \
645    *(unsigned int*)  &__tramp[6] = __dis; /* call __fun  */ \
646  }
647
648 /* the cif must already be prep'ed */
649
650 ffi_status
651 ffi_prep_closure_loc (ffi_closure* closure,
652                       ffi_cif* cif,
653                       void (*fun)(ffi_cif*,void*,void**,void*),
654                       void *user_data,
655                       void *codeloc)
656 {
657 #ifdef X86_WIN64
658 #define ISFLOAT(IDX) (cif->arg_types[IDX]->type == FFI_TYPE_FLOAT || cif->arg_types[IDX]->type == FFI_TYPE_DOUBLE)
659 #define FLAG(IDX) (cif->nargs>(IDX)&&ISFLOAT(IDX)?(1<<(IDX)):0)
660   if (cif->abi == FFI_WIN64) 
661     {
662       int mask = FLAG(0)|FLAG(1)|FLAG(2)|FLAG(3);
663       FFI_INIT_TRAMPOLINE_WIN64 (&closure->tramp[0],
664                                  &ffi_closure_win64,
665                                  codeloc, mask);
666       /* make sure we can execute here */
667     }
668 #else
669   if (cif->abi == FFI_SYSV)
670     {
671       FFI_INIT_TRAMPOLINE (&closure->tramp[0],
672                            &ffi_closure_SYSV,
673                            (void*)codeloc);
674     }
675   else if (cif->abi == FFI_THISCALL)
676     {
677       FFI_INIT_TRAMPOLINE_STDCALL (&closure->tramp[0],
678                                    &ffi_closure_THISCALL,
679                                    (void*)codeloc);
680     }
681   else if (cif->abi == FFI_STDCALL)
682     {
683       FFI_INIT_TRAMPOLINE_STDCALL (&closure->tramp[0],
684                                    &ffi_closure_STDCALL,
685                                    (void*)codeloc);
686     }
687 #ifdef X86_WIN32
688   else if (cif->abi == FFI_MS_CDECL)
689     {
690       FFI_INIT_TRAMPOLINE (&closure->tramp[0],
691                            &ffi_closure_SYSV,
692                            (void*)codeloc);
693     }
694 #endif /* X86_WIN32 */
695 #endif /* !X86_WIN64 */
696   else
697     {
698       return FFI_BAD_ABI;
699     }
700     
701   closure->cif  = cif;
702   closure->user_data = user_data;
703   closure->fun  = fun;
704
705   return FFI_OK;
706 }
707
708 /* ------- Native raw API support -------------------------------- */
709
710 #if !FFI_NO_RAW_API
711
712 ffi_status
713 ffi_prep_raw_closure_loc (ffi_raw_closure* closure,
714                           ffi_cif* cif,
715                           void (*fun)(ffi_cif*,void*,ffi_raw*,void*),
716                           void *user_data,
717                           void *codeloc)
718 {
719   int i;
720
721   if (cif->abi != FFI_SYSV
722 #ifdef X86_WIN32
723       && cif->abi != FFI_THISCALL
724 #endif
725      )
726     return FFI_BAD_ABI;
727
728   /* we currently don't support certain kinds of arguments for raw
729      closures.  This should be implemented by a separate assembly
730      language routine, since it would require argument processing,
731      something we don't do now for performance.  */
732
733   for (i = cif->nargs-1; i >= 0; i--)
734     {
735       FFI_ASSERT (cif->arg_types[i]->type != FFI_TYPE_STRUCT);
736       FFI_ASSERT (cif->arg_types[i]->type != FFI_TYPE_LONGDOUBLE);
737     }
738   
739 #ifdef X86_WIN32
740   if (cif->abi == FFI_SYSV)
741     {
742 #endif
743   FFI_INIT_TRAMPOLINE (&closure->tramp[0], &ffi_closure_raw_SYSV,
744                        codeloc);
745 #ifdef X86_WIN32
746     }
747   else if (cif->abi == FFI_THISCALL)
748     {
749       FFI_INIT_TRAMPOLINE_RAW_THISCALL (&closure->tramp[0], &ffi_closure_raw_THISCALL, codeloc);
750     }
751 #endif
752   closure->cif  = cif;
753   closure->user_data = user_data;
754   closure->fun  = fun;
755
756   return FFI_OK;
757 }
758
759 static void 
760 ffi_prep_args_raw(char *stack, extended_cif *ecif)
761 {
762   memcpy (stack, ecif->avalue, ecif->cif->bytes);
763 }
764
765 /* we borrow this routine from libffi (it must be changed, though, to
766  * actually call the function passed in the first argument.  as of
767  * libffi-1.20, this is not the case.)
768  */
769
770 void
771 ffi_raw_call(ffi_cif *cif, void (*fn)(void), void *rvalue, ffi_raw *fake_avalue)
772 {
773   extended_cif ecif;
774   void **avalue = (void **)fake_avalue;
775
776   ecif.cif = cif;
777   ecif.avalue = avalue;
778   
779   /* If the return value is a struct and we don't have a return */
780   /* value address then we need to make one                     */
781
782   if (rvalue == NULL
783       && (cif->flags == FFI_TYPE_STRUCT
784           || cif->flags == FFI_TYPE_MS_STRUCT))
785     {
786       ecif.rvalue = alloca(cif->rtype->size);
787     }
788   else
789     ecif.rvalue = rvalue;
790     
791   
792   switch (cif->abi) 
793     {
794 #ifndef X86_WIN32
795     case FFI_SYSV:
796       ffi_call_SYSV(ffi_prep_args_raw, &ecif, cif->bytes, cif->flags,
797                     ecif.rvalue, fn);
798       break;
799 #else
800     case FFI_SYSV:
801     case FFI_MS_CDECL:
802 #endif
803 #ifndef X86_WIN64
804     case FFI_STDCALL:
805       ffi_call_win32(ffi_prep_args_raw, &ecif, cif->abi, cif->bytes, cif->flags,
806                      ecif.rvalue, fn);
807       break;
808     case FFI_THISCALL:
809     case FFI_FASTCALL:
810       {
811         unsigned int abi = cif->abi;
812         unsigned int i, passed_regs = 0;
813
814         if (cif->flags == FFI_TYPE_STRUCT)
815           ++passed_regs;
816
817         for (i=0; i < cif->nargs && passed_regs < 2;i++)
818           {
819             size_t sz;
820
821             if (cif->arg_types[i]->type == FFI_TYPE_FLOAT
822                 || cif->arg_types[i]->type == FFI_TYPE_STRUCT)
823               continue;
824             sz = (cif->arg_types[i]->size + 3) & ~3;
825             if (sz == 0 || sz > 4)
826               continue;
827             ++passed_regs;
828           }
829         if (passed_regs < 2 && abi == FFI_FASTCALL)
830           cif->abi = abi = FFI_THISCALL;
831         if (passed_regs < 1 && abi == FFI_THISCALL)
832           cif->abi = abi = FFI_STDCALL;
833         ffi_call_win32(ffi_prep_args_raw, &ecif, abi, cif->bytes, cif->flags,
834                        ecif.rvalue, fn);
835       }
836       break;
837 #endif
838     default:
839       FFI_ASSERT(0);
840       break;
841     }
842 }
843
844 #endif
845
846 #endif /* !__x86_64__  || X86_WIN64 */
847