* cfgloop.c (flow_loop_entry_edges_find): Fix typo.
[official-gcc.git] / libffi / src / m68k / ffi.c
blobc5d950786f788056ea2fd4c062d74cd36076aa86
1 /* -----------------------------------------------------------------------
2 ffi.c
4 m68k Foreign Function Interface
5 ----------------------------------------------------------------------- */
7 #include <ffi.h>
8 #include <ffi_common.h>
10 #include <stdlib.h>
12 /* ffi_prep_args is called by the assembly routine once stack space has
13 been allocated for the function's arguments. */
15 static void *
16 ffi_prep_args (void *stack, extended_cif *ecif)
18 unsigned int i;
19 int tmp;
20 unsigned int avn;
21 void **p_argv;
22 char *argp;
23 ffi_type **p_arg;
24 void *struct_value_ptr;
26 tmp = 0;
27 argp = stack;
29 if (ecif->cif->rtype->type == FFI_TYPE_STRUCT
30 && ecif->cif->rtype->size > 8)
31 struct_value_ptr = ecif->rvalue;
32 else
33 struct_value_ptr = NULL;
35 avn = ecif->cif->nargs;
36 p_argv = ecif->avalue;
38 for (i = ecif->cif->nargs, p_arg = ecif->cif->arg_types;
39 i != 0 && avn != 0;
40 i--, p_arg++)
42 size_t z;
44 /* Align if necessary. */
45 if (((*p_arg)->alignment - 1) & (unsigned) argp)
46 argp = (char *) ALIGN (argp, (*p_arg)->alignment);
48 if (avn != 0)
50 avn--;
51 z = (*p_arg)->size;
52 if (z < sizeof (int))
54 switch ((*p_arg)->type)
56 case FFI_TYPE_SINT8:
57 *(signed int *) argp = (signed int) *(SINT8 *) *p_argv;
58 break;
60 case FFI_TYPE_UINT8:
61 *(unsigned int *) argp = (unsigned int) *(UINT8 *) *p_argv;
62 break;
64 case FFI_TYPE_SINT16:
65 *(signed int *) argp = (signed int) *(SINT16 *) *p_argv;
66 break;
68 case FFI_TYPE_UINT16:
69 *(unsigned int *) argp = (unsigned int) *(UINT16 *) *p_argv;
70 break;
72 case FFI_TYPE_STRUCT:
73 memcpy (argp + sizeof (int) - z, *p_argv, z);
74 break;
76 default:
77 FFI_ASSERT (0);
79 z = sizeof (int);
81 else
82 memcpy (argp, *p_argv, z);
83 p_argv++;
84 argp += z;
88 return struct_value_ptr;
91 #define CIF_FLAGS_INT 1
92 #define CIF_FLAGS_DINT 2
93 #define CIF_FLAGS_FLOAT 4
94 #define CIF_FLAGS_DOUBLE 8
95 #define CIF_FLAGS_LDOUBLE 16
96 #define CIF_FLAGS_POINTER 32
97 #define CIF_FLAGS_STRUCT 64
99 /* Perform machine dependent cif processing */
100 ffi_status
101 ffi_prep_cif_machdep (ffi_cif *cif)
103 /* Set the return type flag */
104 switch (cif->rtype->type)
106 case FFI_TYPE_VOID:
107 cif->flags = 0;
108 break;
110 case FFI_TYPE_STRUCT:
111 if (cif->rtype->size > 4 && cif->rtype->size <= 8)
112 cif->flags = CIF_FLAGS_DINT;
113 else if (cif->rtype->size <= 4)
114 cif->flags = CIF_FLAGS_STRUCT;
115 else
116 cif->flags = 0;
117 break;
119 case FFI_TYPE_FLOAT:
120 cif->flags = CIF_FLAGS_FLOAT;
121 break;
123 case FFI_TYPE_DOUBLE:
124 cif->flags = CIF_FLAGS_DOUBLE;
125 break;
127 case FFI_TYPE_LONGDOUBLE:
128 cif->flags = CIF_FLAGS_LDOUBLE;
129 break;
131 case FFI_TYPE_POINTER:
132 cif->flags = CIF_FLAGS_POINTER;
133 break;
135 case FFI_TYPE_SINT64:
136 case FFI_TYPE_UINT64:
137 cif->flags = CIF_FLAGS_DINT;
138 break;
140 default:
141 cif->flags = CIF_FLAGS_INT;
142 break;
145 return FFI_OK;
148 extern void ffi_call_SYSV (void *(*) (void *, extended_cif *),
149 extended_cif *,
150 unsigned, unsigned, unsigned,
151 void *, void (*fn) ());
153 void
154 ffi_call (ffi_cif *cif, void (*fn) (), void *rvalue, void **avalue)
156 extended_cif ecif;
158 ecif.cif = cif;
159 ecif.avalue = avalue;
161 /* If the return value is a struct and we don't have a return value
162 address then we need to make one. */
164 if (rvalue == NULL
165 && cif->rtype->type == FFI_TYPE_STRUCT
166 && cif->rtype->size > 8)
167 ecif.rvalue = alloca (cif->rtype->size);
168 else
169 ecif.rvalue = rvalue;
172 switch (cif->abi)
174 case FFI_SYSV:
175 ffi_call_SYSV (ffi_prep_args, &ecif, cif->bytes,
176 cif->flags, cif->rtype->size * 8,
177 ecif.rvalue, fn);
178 break;
180 default:
181 FFI_ASSERT (0);
182 break;