1 /* -----------------------------------------------------------------------
2 ffi.c - Copyright (c) 1996 Cygnus Solutions
4 MIPS Foreign Function Interface
6 Permission is hereby granted, free of charge, to any person obtaining
7 a copy of this software and associated documentation files (the
8 ``Software''), to deal in the Software without restriction, including
9 without limitation the rights to use, copy, modify, merge, publish,
10 distribute, sublicense, and/or sell copies of the Software, and to
11 permit persons to whom the Software is furnished to do so, subject to
12 the following conditions:
14 The above copyright notice and this permission notice shall be included
15 in all copies or substantial portions of the Software.
17 THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS
18 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
20 IN NO EVENT SHALL CYGNUS SOLUTIONS BE LIABLE FOR ANY CLAIM, DAMAGES OR
21 OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
22 ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
23 OTHER DEALINGS IN THE SOFTWARE.
24 ----------------------------------------------------------------------- */
28 #include <ffi_common.h>
32 #if _MIPS_SIM == _MIPS_SIM_NABI32
34 FFI_ASSERT(argp <= &stack[bytes]); \
35 if (argp == &stack[bytes]) \
45 /* ffi_prep_args is called by the assembly routine once stack space
46 has been allocated for the function's arguments */
48 static void ffi_prep_args(char *stack,
55 register void **p_argv;
57 register ffi_type **p_arg;
59 #if _MIPS_SIM == _MIPS_SIM_NABI32
60 /* If more than 8 double words are used, the remainder go
61 on the stack. We reorder stuff on the stack here to
62 support this easily. */
63 if (bytes > 8 * SIZEOF_ARG)
64 argp = &stack[bytes - (8 * SIZEOF_ARG)];
71 memset(stack, 0, bytes);
73 #if _MIPS_SIM == _MIPS_SIM_NABI32
74 if ( ecif->cif->rstruct_flag != 0 )
76 if ( ecif->cif->rtype->type == FFI_TYPE_STRUCT )
79 *(SLOT_TYPE_UNSIGNED *) argp = (SLOT_TYPE_UNSIGNED) ecif->rvalue;
80 argp += sizeof(SLOT_TYPE_UNSIGNED);
84 avn = ecif->cif->nargs;
85 p_argv = ecif->avalue;
87 for (i = ecif->cif->nargs, p_arg = ecif->cif->arg_types;
93 /* Align if necessary */
94 if (((*p_arg)->alignment - 1) & (unsigned) argp) {
95 argp = (char *) ALIGN(argp, (*p_arg)->alignment);
99 #if _MIPS_SIM == _MIPS_SIM_ABI32
102 #define OFFSET sizeof(int)
109 if (z < sizeof(SLOT_TYPE_UNSIGNED))
111 z = sizeof(SLOT_TYPE_UNSIGNED);
113 switch ((*p_arg)->type)
116 *(SINT32 *) &argp[OFFSET] = (SINT32)*(SINT8 *)(* p_argv);
120 *(UINT32 *) &argp[OFFSET] = (UINT32)*(UINT8 *)(* p_argv);
123 case FFI_TYPE_SINT16:
124 *(SINT32 *) &argp[OFFSET] = (SINT32)*(SINT16 *)(* p_argv);
127 case FFI_TYPE_UINT16:
128 *(UINT32 *) &argp[OFFSET] = (UINT32)*(UINT16 *)(* p_argv);
131 case FFI_TYPE_SINT32:
132 *(SINT32 *) &argp[OFFSET] = (SINT32)*(SINT32 *)(* p_argv);
135 case FFI_TYPE_UINT32:
136 case FFI_TYPE_POINTER:
137 *(UINT32 *) &argp[OFFSET] = (UINT32)*(UINT32 *)(* p_argv);
140 /* This can only happen with 64bit slots */
142 *(float *) argp = *(float *)(* p_argv);
145 /* Handle small structures */
146 case FFI_TYPE_STRUCT:
147 memcpy(argp, *p_argv, (*p_arg)->size);
156 #if _MIPS_SIM == _MIPS_SIM_ABI32
157 memcpy(argp, *p_argv, z);
160 unsigned end = (unsigned) argp+z;
161 unsigned cap = (unsigned) stack+bytes;
163 /* Check if the data will fit within the register
164 space. Handle it if it doesn't. */
167 memcpy(argp, *p_argv, z);
170 unsigned portion = end - cap;
172 memcpy(argp, *p_argv, portion);
175 (void*)((unsigned)(*p_argv)+portion), z - portion);
189 #if _MIPS_SIM == _MIPS_SIM_NABI32
191 /* The n32 spec says that if "a chunk consists solely of a double
192 float field (but not a double, which is part of a union), it
193 is passed in a floating point register. Any other chunk is
194 passed in an integer register". This code traverses structure
195 definitions and generates the appropriate flags. */
197 unsigned calc_n32_struct_flags(ffi_type *arg, unsigned *shift)
204 while (e = arg->elements[index])
206 if (e->type == FFI_TYPE_DOUBLE)
208 flags += (FFI_TYPE_DOUBLE << *shift);
209 *shift += FFI_FLAG_BITS;
211 else if (e->type == FFI_TYPE_STRUCT)
212 flags += calc_n32_struct_flags(e, shift);
214 *shift += FFI_FLAG_BITS;
222 unsigned calc_n32_return_struct_flags(ffi_type *arg)
226 unsigned small = FFI_TYPE_SMALLSTRUCT;
229 /* Returning structures under n32 is a tricky thing.
230 A struct with only one or two floating point fields
231 is returned in $f0 (and $f2 if necessary). Any other
232 struct results at most 128 bits are returned in $2
233 (the first 64 bits) and $3 (remainder, if necessary).
234 Larger structs are handled normally. */
240 small = FFI_TYPE_SMALLSTRUCT2;
242 e = arg->elements[0];
243 if (e->type == FFI_TYPE_DOUBLE)
244 flags = FFI_TYPE_DOUBLE << FFI_FLAG_BITS;
245 else if (e->type == FFI_TYPE_FLOAT)
246 flags = FFI_TYPE_FLOAT << FFI_FLAG_BITS;
248 if (flags && (e = arg->elements[1]))
250 if (e->type == FFI_TYPE_DOUBLE)
251 flags += FFI_TYPE_DOUBLE;
252 else if (e->type == FFI_TYPE_FLOAT)
253 flags += FFI_TYPE_FLOAT;
257 if (flags && (arg->elements[2]))
259 /* There are three arguments and the first two are
260 floats! This must be passed the old way. */
273 /* Perform machine dependent cif processing */
274 ffi_status ffi_prep_cif_machdep(ffi_cif *cif)
278 #if _MIPS_SIM == _MIPS_SIM_ABI32
279 /* Set the flags necessary for O32 processing */
281 if (cif->rtype->type != FFI_TYPE_STRUCT)
285 switch ((cif->arg_types)[0]->type)
288 case FFI_TYPE_DOUBLE:
289 cif->flags += (cif->arg_types)[0]->type;
298 /* Only handle the second argument if the first
299 is a float or double. */
302 switch ((cif->arg_types)[1]->type)
305 case FFI_TYPE_DOUBLE:
306 cif->flags += (cif->arg_types)[1]->type << FFI_FLAG_BITS;
317 /* Set the return type flag */
318 switch (cif->rtype->type)
321 case FFI_TYPE_STRUCT:
323 case FFI_TYPE_DOUBLE:
324 cif->flags += cif->rtype->type << (FFI_FLAG_BITS * 2);
328 cif->flags += FFI_TYPE_INT << (FFI_FLAG_BITS * 2);
333 #if _MIPS_SIM == _MIPS_SIM_NABI32
334 /* Set the flags necessary for N32 processing */
337 unsigned count = (cif->nargs < 8) ? cif->nargs : 8;
340 unsigned struct_flags = 0;
342 if (cif->rtype->type == FFI_TYPE_STRUCT)
344 struct_flags = calc_n32_return_struct_flags(cif->rtype);
346 if (struct_flags == 0)
348 /* This means that the structure is being passed as
351 shift = FFI_FLAG_BITS;
352 count = (cif->nargs < 7) ? cif->nargs : 7;
354 cif->rstruct_flag = !0;
357 cif->rstruct_flag = 0;
360 cif->rstruct_flag = 0;
364 switch ((cif->arg_types)[index]->type)
367 case FFI_TYPE_DOUBLE:
368 cif->flags += ((cif->arg_types)[index]->type << shift);
369 shift += FFI_FLAG_BITS;
372 case FFI_TYPE_STRUCT:
373 cif->flags += calc_n32_struct_flags((cif->arg_types)[index],
378 shift += FFI_FLAG_BITS;
384 /* Set the return type flag */
385 switch (cif->rtype->type)
387 case FFI_TYPE_STRUCT:
389 if (struct_flags == 0)
391 /* The structure is returned through a hidden
392 first argument. Do nothing, 'cause FFI_TYPE_VOID
397 /* The structure is returned via some tricky
399 cif->flags += FFI_TYPE_STRUCT << (FFI_FLAG_BITS * 8);
400 cif->flags += struct_flags << (4 + (FFI_FLAG_BITS * 8));
406 /* Do nothing, 'cause FFI_TYPE_VOID is 0 */
410 case FFI_TYPE_DOUBLE:
411 cif->flags += cif->rtype->type << (FFI_FLAG_BITS * 8);
415 cif->flags += FFI_TYPE_INT << (FFI_FLAG_BITS * 8);
424 /* Low level routine for calling O32 functions */
425 extern int ffi_call_O32(void (*)(char *, extended_cif *, int, int),
426 extended_cif *, unsigned,
427 unsigned, unsigned *, void (*)());
429 /* Low level routine for calling N32 functions */
430 extern int ffi_call_N32(void (*)(char *, extended_cif *, int, int),
431 extended_cif *, unsigned,
432 unsigned, unsigned *, void (*)());
434 void ffi_call(ffi_cif *cif, void (*fn)(), void *rvalue, void **avalue)
439 ecif.avalue = avalue;
441 /* If the return value is a struct and we don't have a return */
442 /* value address then we need to make one */
444 if ((rvalue == NULL) &&
445 (cif->rtype->type == FFI_TYPE_STRUCT))
446 ecif.rvalue = alloca(cif->rtype->size);
448 ecif.rvalue = rvalue;
452 #if _MIPS_SIM == _MIPS_SIM_ABI32
454 ffi_call_O32(ffi_prep_args, &ecif, cif->bytes,
455 cif->flags, ecif.rvalue, fn);
459 #if _MIPS_SIM == _MIPS_SIM_NABI32
461 ffi_call_N32(ffi_prep_args, &ecif, cif->bytes,
462 cif->flags, ecif.rvalue, fn);