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