libgcc: Move cfa_how into potential padding in struct frame_state_reg_info
[official-gcc.git] / libffi / src / x86 / ffi.c
blob24431c170ba539c7af5d7eff03a92614ca87286e
1 /* -----------------------------------------------------------------------
2 ffi.c - Copyright (c) 2017 Anthony Green
3 Copyright (c) 1996, 1998, 1999, 2001, 2007, 2008 Red Hat, Inc.
4 Copyright (c) 2002 Ranjit Mathew
5 Copyright (c) 2002 Bo Thorsen
6 Copyright (c) 2002 Roger Sayle
7 Copyright (C) 2008, 2010 Free Software Foundation, Inc.
9 x86 Foreign Function Interface
11 Permission is hereby granted, free of charge, to any person obtaining
12 a copy of this software and associated documentation files (the
13 ``Software''), to deal in the Software without restriction, including
14 without limitation the rights to use, copy, modify, merge, publish,
15 distribute, sublicense, and/or sell copies of the Software, and to
16 permit persons to whom the Software is furnished to do so, subject to
17 the following conditions:
19 The above copyright notice and this permission notice shall be included
20 in all copies or substantial portions of the Software.
22 THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND,
23 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
24 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
25 NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
26 HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
27 WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
28 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
29 DEALINGS IN THE SOFTWARE.
30 ----------------------------------------------------------------------- */
32 #if defined(__i386__) || defined(_M_IX86)
33 #include <ffi.h>
34 #include <ffi_common.h>
35 #include <stdint.h>
36 #include <stdlib.h>
37 #include <tramp.h>
38 #include "internal.h"
40 /* Force FFI_TYPE_LONGDOUBLE to be different than FFI_TYPE_DOUBLE;
41 all further uses in this file will refer to the 80-bit type. */
42 #if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
43 # if FFI_TYPE_LONGDOUBLE != 4
44 # error FFI_TYPE_LONGDOUBLE out of date
45 # endif
46 #else
47 # undef FFI_TYPE_LONGDOUBLE
48 # define FFI_TYPE_LONGDOUBLE 4
49 #endif
51 #if defined(__GNUC__) && !defined(__declspec)
52 # define __declspec(x) __attribute__((x))
53 #endif
55 #if defined(_MSC_VER) && defined(_M_IX86)
56 /* Stack is not 16-byte aligned on Windows. */
57 #define STACK_ALIGN(bytes) (bytes)
58 #else
59 #define STACK_ALIGN(bytes) FFI_ALIGN (bytes, 16)
60 #endif
62 /* Perform machine dependent cif processing. */
63 ffi_status FFI_HIDDEN
64 ffi_prep_cif_machdep(ffi_cif *cif)
66 size_t bytes = 0;
67 int i, n, flags, cabi = cif->abi;
69 switch (cabi)
71 case FFI_SYSV:
72 case FFI_STDCALL:
73 case FFI_THISCALL:
74 case FFI_FASTCALL:
75 case FFI_MS_CDECL:
76 case FFI_PASCAL:
77 case FFI_REGISTER:
78 break;
79 default:
80 return FFI_BAD_ABI;
83 switch (cif->rtype->type)
85 case FFI_TYPE_VOID:
86 flags = X86_RET_VOID;
87 break;
88 case FFI_TYPE_FLOAT:
89 flags = X86_RET_FLOAT;
90 break;
91 case FFI_TYPE_DOUBLE:
92 flags = X86_RET_DOUBLE;
93 break;
94 case FFI_TYPE_LONGDOUBLE:
95 flags = X86_RET_LDOUBLE;
96 break;
97 case FFI_TYPE_UINT8:
98 flags = X86_RET_UINT8;
99 break;
100 case FFI_TYPE_UINT16:
101 flags = X86_RET_UINT16;
102 break;
103 case FFI_TYPE_SINT8:
104 flags = X86_RET_SINT8;
105 break;
106 case FFI_TYPE_SINT16:
107 flags = X86_RET_SINT16;
108 break;
109 case FFI_TYPE_INT:
110 case FFI_TYPE_SINT32:
111 case FFI_TYPE_UINT32:
112 case FFI_TYPE_POINTER:
113 flags = X86_RET_INT32;
114 break;
115 case FFI_TYPE_SINT64:
116 case FFI_TYPE_UINT64:
117 flags = X86_RET_INT64;
118 break;
119 case FFI_TYPE_STRUCT:
120 #ifndef X86
121 /* ??? This should be a different ABI rather than an ifdef. */
122 if (cif->rtype->size == 1)
123 flags = X86_RET_STRUCT_1B;
124 else if (cif->rtype->size == 2)
125 flags = X86_RET_STRUCT_2B;
126 else if (cif->rtype->size == 4)
127 flags = X86_RET_INT32;
128 else if (cif->rtype->size == 8)
129 flags = X86_RET_INT64;
130 else
131 #endif
133 do_struct:
134 switch (cabi)
136 case FFI_THISCALL:
137 case FFI_FASTCALL:
138 case FFI_STDCALL:
139 case FFI_MS_CDECL:
140 flags = X86_RET_STRUCTARG;
141 break;
142 default:
143 flags = X86_RET_STRUCTPOP;
144 break;
146 /* Allocate space for return value pointer. */
147 bytes += FFI_ALIGN (sizeof(void*), FFI_SIZEOF_ARG);
149 break;
150 case FFI_TYPE_COMPLEX:
151 switch (cif->rtype->elements[0]->type)
153 case FFI_TYPE_DOUBLE:
154 case FFI_TYPE_LONGDOUBLE:
155 case FFI_TYPE_SINT64:
156 case FFI_TYPE_UINT64:
157 goto do_struct;
158 case FFI_TYPE_FLOAT:
159 case FFI_TYPE_INT:
160 case FFI_TYPE_SINT32:
161 case FFI_TYPE_UINT32:
162 flags = X86_RET_INT64;
163 break;
164 case FFI_TYPE_SINT16:
165 case FFI_TYPE_UINT16:
166 flags = X86_RET_INT32;
167 break;
168 case FFI_TYPE_SINT8:
169 case FFI_TYPE_UINT8:
170 flags = X86_RET_STRUCT_2B;
171 break;
172 default:
173 return FFI_BAD_TYPEDEF;
175 break;
176 default:
177 return FFI_BAD_TYPEDEF;
179 cif->flags = flags;
181 for (i = 0, n = cif->nargs; i < n; i++)
183 ffi_type *t = cif->arg_types[i];
185 bytes = FFI_ALIGN (bytes, t->alignment);
186 bytes += FFI_ALIGN (t->size, FFI_SIZEOF_ARG);
188 cif->bytes = bytes;
190 return FFI_OK;
193 static ffi_arg
194 extend_basic_type(void *arg, int type)
196 switch (type)
198 case FFI_TYPE_SINT8:
199 return *(SINT8 *)arg;
200 case FFI_TYPE_UINT8:
201 return *(UINT8 *)arg;
202 case FFI_TYPE_SINT16:
203 return *(SINT16 *)arg;
204 case FFI_TYPE_UINT16:
205 return *(UINT16 *)arg;
207 case FFI_TYPE_SINT32:
208 case FFI_TYPE_UINT32:
209 case FFI_TYPE_POINTER:
210 case FFI_TYPE_FLOAT:
211 return *(UINT32 *)arg;
213 default:
214 abort();
218 struct call_frame
220 void *ebp; /* 0 */
221 void *retaddr; /* 4 */
222 void (*fn)(void); /* 8 */
223 int flags; /* 12 */
224 void *rvalue; /* 16 */
225 unsigned regs[3]; /* 20-28 */
228 struct abi_params
230 int dir; /* parameter growth direction */
231 int static_chain; /* the static chain register used by gcc */
232 int nregs; /* number of register parameters */
233 int regs[3];
236 static const struct abi_params abi_params[FFI_LAST_ABI] = {
237 [FFI_SYSV] = { 1, R_ECX, 0 },
238 [FFI_THISCALL] = { 1, R_EAX, 1, { R_ECX } },
239 [FFI_FASTCALL] = { 1, R_EAX, 2, { R_ECX, R_EDX } },
240 [FFI_STDCALL] = { 1, R_ECX, 0 },
241 [FFI_PASCAL] = { -1, R_ECX, 0 },
242 /* ??? No defined static chain; gcc does not support REGISTER. */
243 [FFI_REGISTER] = { -1, R_ECX, 3, { R_EAX, R_EDX, R_ECX } },
244 [FFI_MS_CDECL] = { 1, R_ECX, 0 }
247 #ifdef HAVE_FASTCALL
248 #ifdef _MSC_VER
249 #define FFI_DECLARE_FASTCALL __fastcall
250 #else
251 #define FFI_DECLARE_FASTCALL __declspec(fastcall)
252 #endif
253 #else
254 #define FFI_DECLARE_FASTCALL
255 #endif
257 extern void FFI_DECLARE_FASTCALL ffi_call_i386(struct call_frame *, char *) FFI_HIDDEN;
259 /* We perform some black magic here to use some of the parent's stack frame in
260 * ffi_call_i386() that breaks with the MSVC compiler with the /RTCs or /GZ
261 * flags. Disable the 'Stack frame run time error checking' for this function
262 * so we don't hit weird exceptions in debug builds. */
263 #if defined(_MSC_VER)
264 #pragma runtime_checks("s", off)
265 #endif
266 static void
267 ffi_call_int (ffi_cif *cif, void (*fn)(void), void *rvalue,
268 void **avalue, void *closure)
270 size_t rsize, bytes;
271 struct call_frame *frame;
272 char *stack, *argp;
273 ffi_type **arg_types;
274 int flags, cabi, i, n, dir, narg_reg;
275 const struct abi_params *pabi;
277 flags = cif->flags;
278 cabi = cif->abi;
279 pabi = &abi_params[cabi];
280 dir = pabi->dir;
282 rsize = 0;
283 if (rvalue == NULL)
285 switch (flags)
287 case X86_RET_FLOAT:
288 case X86_RET_DOUBLE:
289 case X86_RET_LDOUBLE:
290 case X86_RET_STRUCTPOP:
291 case X86_RET_STRUCTARG:
292 /* The float cases need to pop the 387 stack.
293 The struct cases need to pass a valid pointer to the callee. */
294 rsize = cif->rtype->size;
295 break;
296 default:
297 /* We can pretend that the callee returns nothing. */
298 flags = X86_RET_VOID;
299 break;
303 bytes = STACK_ALIGN (cif->bytes);
304 stack = alloca(bytes + sizeof(*frame) + rsize);
305 argp = (dir < 0 ? stack + bytes : stack);
306 frame = (struct call_frame *)(stack + bytes);
307 if (rsize)
308 rvalue = frame + 1;
310 frame->fn = fn;
311 frame->flags = flags;
312 frame->rvalue = rvalue;
313 frame->regs[pabi->static_chain] = (unsigned)closure;
315 narg_reg = 0;
316 switch (flags)
318 case X86_RET_STRUCTARG:
319 /* The pointer is passed as the first argument. */
320 if (pabi->nregs > 0)
322 frame->regs[pabi->regs[0]] = (unsigned)rvalue;
323 narg_reg = 1;
324 break;
326 /* fallthru */
327 case X86_RET_STRUCTPOP:
328 *(void **)argp = rvalue;
329 argp += sizeof(void *);
330 break;
333 arg_types = cif->arg_types;
334 for (i = 0, n = cif->nargs; i < n; i++)
336 ffi_type *ty = arg_types[i];
337 void *valp = avalue[i];
338 size_t z = ty->size;
339 int t = ty->type;
341 if (z <= FFI_SIZEOF_ARG && t != FFI_TYPE_STRUCT)
343 ffi_arg val = extend_basic_type (valp, t);
345 if (t != FFI_TYPE_FLOAT && narg_reg < pabi->nregs)
346 frame->regs[pabi->regs[narg_reg++]] = val;
347 else if (dir < 0)
349 argp -= 4;
350 *(ffi_arg *)argp = val;
352 else
354 *(ffi_arg *)argp = val;
355 argp += 4;
358 else
360 size_t za = FFI_ALIGN (z, FFI_SIZEOF_ARG);
361 size_t align = FFI_SIZEOF_ARG;
363 /* Issue 434: For thiscall and fastcall, if the paramter passed
364 as 64-bit integer or struct, all following integer parameters
365 will be passed on stack. */
366 if ((cabi == FFI_THISCALL || cabi == FFI_FASTCALL)
367 && (t == FFI_TYPE_SINT64
368 || t == FFI_TYPE_UINT64
369 || t == FFI_TYPE_STRUCT))
370 narg_reg = 2;
372 /* Alignment rules for arguments are quite complex. Vectors and
373 structures with 16 byte alignment get it. Note that long double
374 on Darwin does have 16 byte alignment, and does not get this
375 alignment if passed directly; a structure with a long double
376 inside, however, would get 16 byte alignment. Since libffi does
377 not support vectors, we need non concern ourselves with other
378 cases. */
379 if (t == FFI_TYPE_STRUCT && ty->alignment >= 16)
380 align = 16;
382 if (dir < 0)
384 /* ??? These reverse argument ABIs are probably too old
385 to have cared about alignment. Someone should check. */
386 argp -= za;
387 memcpy (argp, valp, z);
389 else
391 argp = (char *)FFI_ALIGN (argp, align);
392 memcpy (argp, valp, z);
393 argp += za;
397 FFI_ASSERT (dir > 0 || argp == stack);
399 ffi_call_i386 (frame, stack);
401 #if defined(_MSC_VER)
402 #pragma runtime_checks("s", restore)
403 #endif
405 void
406 ffi_call (ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue)
408 ffi_call_int (cif, fn, rvalue, avalue, NULL);
411 #ifdef FFI_GO_CLOSURES
412 void
413 ffi_call_go (ffi_cif *cif, void (*fn)(void), void *rvalue,
414 void **avalue, void *closure)
416 ffi_call_int (cif, fn, rvalue, avalue, closure);
418 #endif
420 /** private members **/
422 void FFI_HIDDEN ffi_closure_i386(void);
423 void FFI_HIDDEN ffi_closure_STDCALL(void);
424 void FFI_HIDDEN ffi_closure_REGISTER(void);
425 #if defined(FFI_EXEC_STATIC_TRAMP)
426 void FFI_HIDDEN ffi_closure_i386_alt(void);
427 void FFI_HIDDEN ffi_closure_STDCALL_alt(void);
428 void FFI_HIDDEN ffi_closure_REGISTER_alt(void);
429 #endif
431 struct closure_frame
433 unsigned rettemp[4]; /* 0 */
434 unsigned regs[3]; /* 16-24 */
435 ffi_cif *cif; /* 28 */
436 void (*fun)(ffi_cif*,void*,void**,void*); /* 32 */
437 void *user_data; /* 36 */
440 int FFI_HIDDEN FFI_DECLARE_FASTCALL
441 ffi_closure_inner (struct closure_frame *frame, char *stack)
443 ffi_cif *cif = frame->cif;
444 int cabi, i, n, flags, dir, narg_reg;
445 const struct abi_params *pabi;
446 ffi_type **arg_types;
447 char *argp;
448 void *rvalue;
449 void **avalue;
451 cabi = cif->abi;
452 flags = cif->flags;
453 narg_reg = 0;
454 rvalue = frame->rettemp;
455 pabi = &abi_params[cabi];
456 dir = pabi->dir;
457 argp = (dir < 0 ? stack + STACK_ALIGN (cif->bytes) : stack);
459 switch (flags)
461 case X86_RET_STRUCTARG:
462 if (pabi->nregs > 0)
464 rvalue = (void *)frame->regs[pabi->regs[0]];
465 narg_reg = 1;
466 frame->rettemp[0] = (unsigned)rvalue;
467 break;
469 /* fallthru */
470 case X86_RET_STRUCTPOP:
471 rvalue = *(void **)argp;
472 argp += sizeof(void *);
473 frame->rettemp[0] = (unsigned)rvalue;
474 break;
477 n = cif->nargs;
478 avalue = alloca(sizeof(void *) * n);
480 arg_types = cif->arg_types;
481 for (i = 0; i < n; ++i)
483 ffi_type *ty = arg_types[i];
484 size_t z = ty->size;
485 int t = ty->type;
486 void *valp;
488 if (z <= FFI_SIZEOF_ARG && t != FFI_TYPE_STRUCT)
490 if (t != FFI_TYPE_FLOAT && narg_reg < pabi->nregs)
491 valp = &frame->regs[pabi->regs[narg_reg++]];
492 else if (dir < 0)
494 argp -= 4;
495 valp = argp;
497 else
499 valp = argp;
500 argp += 4;
503 else
505 size_t za = FFI_ALIGN (z, FFI_SIZEOF_ARG);
506 size_t align = FFI_SIZEOF_ARG;
508 /* See the comment in ffi_call_int. */
509 if (t == FFI_TYPE_STRUCT && ty->alignment >= 16)
510 align = 16;
512 /* Issue 434: For thiscall and fastcall, if the paramter passed
513 as 64-bit integer or struct, all following integer parameters
514 will be passed on stack. */
515 if ((cabi == FFI_THISCALL || cabi == FFI_FASTCALL)
516 && (t == FFI_TYPE_SINT64
517 || t == FFI_TYPE_UINT64
518 || t == FFI_TYPE_STRUCT))
519 narg_reg = 2;
521 if (dir < 0)
523 /* ??? These reverse argument ABIs are probably too old
524 to have cared about alignment. Someone should check. */
525 argp -= za;
526 valp = argp;
528 else
530 argp = (char *)FFI_ALIGN (argp, align);
531 valp = argp;
532 argp += za;
536 avalue[i] = valp;
539 frame->fun (cif, rvalue, avalue, frame->user_data);
541 switch (cabi)
543 case FFI_STDCALL:
544 return flags | (cif->bytes << X86_RET_POP_SHIFT);
545 case FFI_THISCALL:
546 case FFI_FASTCALL:
547 return flags | ((cif->bytes - (narg_reg * FFI_SIZEOF_ARG))
548 << X86_RET_POP_SHIFT);
549 default:
550 return flags;
554 ffi_status
555 ffi_prep_closure_loc (ffi_closure* closure,
556 ffi_cif* cif,
557 void (*fun)(ffi_cif*,void*,void**,void*),
558 void *user_data,
559 void *codeloc)
561 char *tramp = closure->tramp;
562 void (*dest)(void);
563 int op = 0xb8; /* movl imm, %eax */
565 switch (cif->abi)
567 case FFI_SYSV:
568 case FFI_MS_CDECL:
569 dest = ffi_closure_i386;
570 break;
571 case FFI_STDCALL:
572 case FFI_THISCALL:
573 case FFI_FASTCALL:
574 case FFI_PASCAL:
575 dest = ffi_closure_STDCALL;
576 break;
577 case FFI_REGISTER:
578 dest = ffi_closure_REGISTER;
579 op = 0x68; /* pushl imm */
580 break;
581 default:
582 return FFI_BAD_ABI;
585 #if defined(FFI_EXEC_STATIC_TRAMP)
586 if (ffi_tramp_is_present(closure))
588 /* Initialize the static trampoline's parameters. */
589 if (dest == ffi_closure_i386)
590 dest = ffi_closure_i386_alt;
591 else if (dest == ffi_closure_STDCALL)
592 dest = ffi_closure_STDCALL_alt;
593 else
594 dest = ffi_closure_REGISTER_alt;
595 ffi_tramp_set_parms (closure->ftramp, dest, closure);
596 goto out;
598 #endif
600 /* Initialize the dynamic trampoline. */
601 /* endbr32. */
602 *(UINT32 *) tramp = 0xfb1e0ff3;
604 /* movl or pushl immediate. */
605 tramp[4] = op;
606 *(void **)(tramp + 5) = codeloc;
608 /* jmp dest */
609 tramp[9] = 0xe9;
610 *(unsigned *)(tramp + 10) = (unsigned)dest - ((unsigned)codeloc + 14);
612 out:
613 closure->cif = cif;
614 closure->fun = fun;
615 closure->user_data = user_data;
617 return FFI_OK;
620 #ifdef FFI_GO_CLOSURES
622 void FFI_HIDDEN ffi_go_closure_EAX(void);
623 void FFI_HIDDEN ffi_go_closure_ECX(void);
624 void FFI_HIDDEN ffi_go_closure_STDCALL(void);
626 ffi_status
627 ffi_prep_go_closure (ffi_go_closure* closure, ffi_cif* cif,
628 void (*fun)(ffi_cif*,void*,void**,void*))
630 void (*dest)(void);
632 switch (cif->abi)
634 case FFI_SYSV:
635 case FFI_MS_CDECL:
636 dest = ffi_go_closure_ECX;
637 break;
638 case FFI_THISCALL:
639 case FFI_FASTCALL:
640 dest = ffi_go_closure_EAX;
641 break;
642 case FFI_STDCALL:
643 case FFI_PASCAL:
644 dest = ffi_go_closure_STDCALL;
645 break;
646 case FFI_REGISTER:
647 default:
648 return FFI_BAD_ABI;
651 closure->tramp = dest;
652 closure->cif = cif;
653 closure->fun = fun;
655 return FFI_OK;
658 #endif /* FFI_GO_CLOSURES */
660 /* ------- Native raw API support -------------------------------- */
662 #if !FFI_NO_RAW_API
664 void FFI_HIDDEN ffi_closure_raw_SYSV(void);
665 void FFI_HIDDEN ffi_closure_raw_THISCALL(void);
667 ffi_status
668 ffi_prep_raw_closure_loc (ffi_raw_closure *closure,
669 ffi_cif *cif,
670 void (*fun)(ffi_cif*,void*,ffi_raw*,void*),
671 void *user_data,
672 void *codeloc)
674 char *tramp = closure->tramp;
675 void (*dest)(void);
676 int i;
678 /* We currently don't support certain kinds of arguments for raw
679 closures. This should be implemented by a separate assembly
680 language routine, since it would require argument processing,
681 something we don't do now for performance. */
682 for (i = cif->nargs-1; i >= 0; i--)
683 switch (cif->arg_types[i]->type)
685 case FFI_TYPE_STRUCT:
686 case FFI_TYPE_LONGDOUBLE:
687 return FFI_BAD_TYPEDEF;
690 switch (cif->abi)
692 case FFI_THISCALL:
693 dest = ffi_closure_raw_THISCALL;
694 break;
695 case FFI_SYSV:
696 dest = ffi_closure_raw_SYSV;
697 break;
698 default:
699 return FFI_BAD_ABI;
702 /* movl imm, %eax. */
703 tramp[0] = 0xb8;
704 *(void **)(tramp + 1) = codeloc;
706 /* jmp dest */
707 tramp[5] = 0xe9;
708 *(unsigned *)(tramp + 6) = (unsigned)dest - ((unsigned)codeloc + 10);
710 closure->cif = cif;
711 closure->fun = fun;
712 closure->user_data = user_data;
714 return FFI_OK;
717 void
718 ffi_raw_call(ffi_cif *cif, void (*fn)(void), void *rvalue, ffi_raw *avalue)
720 size_t rsize, bytes;
721 struct call_frame *frame;
722 char *stack, *argp;
723 ffi_type **arg_types;
724 int flags, cabi, i, n, narg_reg;
725 const struct abi_params *pabi;
727 flags = cif->flags;
728 cabi = cif->abi;
729 pabi = &abi_params[cabi];
731 rsize = 0;
732 if (rvalue == NULL)
734 switch (flags)
736 case X86_RET_FLOAT:
737 case X86_RET_DOUBLE:
738 case X86_RET_LDOUBLE:
739 case X86_RET_STRUCTPOP:
740 case X86_RET_STRUCTARG:
741 /* The float cases need to pop the 387 stack.
742 The struct cases need to pass a valid pointer to the callee. */
743 rsize = cif->rtype->size;
744 break;
745 default:
746 /* We can pretend that the callee returns nothing. */
747 flags = X86_RET_VOID;
748 break;
752 bytes = STACK_ALIGN (cif->bytes);
753 argp = stack =
754 (void *)((uintptr_t)alloca(bytes + sizeof(*frame) + rsize + 15) & ~16);
755 frame = (struct call_frame *)(stack + bytes);
756 if (rsize)
757 rvalue = frame + 1;
759 frame->fn = fn;
760 frame->flags = flags;
761 frame->rvalue = rvalue;
763 narg_reg = 0;
764 switch (flags)
766 case X86_RET_STRUCTARG:
767 /* The pointer is passed as the first argument. */
768 if (pabi->nregs > 0)
770 frame->regs[pabi->regs[0]] = (unsigned)rvalue;
771 narg_reg = 1;
772 break;
774 /* fallthru */
775 case X86_RET_STRUCTPOP:
776 *(void **)argp = rvalue;
777 argp += sizeof(void *);
778 bytes -= sizeof(void *);
779 break;
782 arg_types = cif->arg_types;
783 for (i = 0, n = cif->nargs; narg_reg < pabi->nregs && i < n; i++)
785 ffi_type *ty = arg_types[i];
786 size_t z = ty->size;
787 int t = ty->type;
789 if (z <= FFI_SIZEOF_ARG && t != FFI_TYPE_STRUCT && t != FFI_TYPE_FLOAT)
791 ffi_arg val = extend_basic_type (avalue, t);
792 frame->regs[pabi->regs[narg_reg++]] = val;
793 z = FFI_SIZEOF_ARG;
795 else
797 memcpy (argp, avalue, z);
798 z = FFI_ALIGN (z, FFI_SIZEOF_ARG);
799 argp += z;
801 avalue += z;
802 bytes -= z;
804 if (i < n)
805 memcpy (argp, avalue, bytes);
807 ffi_call_i386 (frame, stack);
809 #endif /* !FFI_NO_RAW_API */
811 #if defined(FFI_EXEC_STATIC_TRAMP)
812 void *
813 ffi_tramp_arch (size_t *tramp_size, size_t *map_size)
815 extern void *trampoline_code_table;
817 *map_size = X86_TRAMP_MAP_SIZE;
818 *tramp_size = X86_TRAMP_SIZE;
819 return &trampoline_code_table;
821 #endif
823 #endif /* __i386__ */