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
,
54 register void **p_argv
;
56 register ffi_type
**p_arg
;
58 #if _MIPS_SIM == _MIPS_SIM_NABI32
59 /* If more than 8 double words are used, the remainder go
60 on the stack. We reorder stuff on the stack here to
61 support this easily. */
62 if (bytes
> 8 * SIZEOF_ARG
)
63 argp
= &stack
[bytes
- (8 * SIZEOF_ARG
)];
70 memset(stack
, 0, bytes
);
72 #if _MIPS_SIM == _MIPS_SIM_NABI32
73 if ( ecif
->cif
->rstruct_flag
!= 0 )
75 if ( ecif
->cif
->rtype
->type
== FFI_TYPE_STRUCT
)
78 *(SLOT_TYPE_UNSIGNED
*) argp
= (SLOT_TYPE_UNSIGNED
) ecif
->rvalue
;
79 argp
+= sizeof(SLOT_TYPE_UNSIGNED
);
83 p_argv
= ecif
->avalue
;
85 for (i
= ecif
->cif
->nargs
, p_arg
= ecif
->cif
->arg_types
; i
; i
--, p_arg
++)
89 /* Align if necessary */
90 if (((*p_arg
)->alignment
- 1) & (unsigned) argp
) {
91 argp
= (char *) ALIGN(argp
, (*p_arg
)->alignment
);
95 #if _MIPS_SIM == _MIPS_SIM_ABI32
98 #define OFFSET sizeof(int)
102 if (z
< sizeof(SLOT_TYPE_UNSIGNED
))
104 z
= sizeof(SLOT_TYPE_UNSIGNED
);
106 switch ((*p_arg
)->type
)
109 *(SINT32
*) &argp
[OFFSET
] = (SINT32
)*(SINT8
*)(* p_argv
);
113 *(UINT32
*) &argp
[OFFSET
] = (UINT32
)*(UINT8
*)(* p_argv
);
116 case FFI_TYPE_SINT16
:
117 *(SINT32
*) &argp
[OFFSET
] = (SINT32
)*(SINT16
*)(* p_argv
);
120 case FFI_TYPE_UINT16
:
121 *(UINT32
*) &argp
[OFFSET
] = (UINT32
)*(UINT16
*)(* p_argv
);
124 case FFI_TYPE_SINT32
:
125 *(SINT32
*) &argp
[OFFSET
] = (SINT32
)*(SINT32
*)(* p_argv
);
128 case FFI_TYPE_UINT32
:
129 case FFI_TYPE_POINTER
:
130 *(UINT32
*) &argp
[OFFSET
] = (UINT32
)*(UINT32
*)(* p_argv
);
133 /* This can only happen with 64bit slots */
135 *(float *) argp
= *(float *)(* p_argv
);
138 /* Handle small structures */
139 case FFI_TYPE_STRUCT
:
140 memcpy(argp
, *p_argv
, (*p_arg
)->size
);
149 #if _MIPS_SIM == _MIPS_SIM_ABI32
150 memcpy(argp
, *p_argv
, z
);
153 unsigned end
= (unsigned) argp
+z
;
154 unsigned cap
= (unsigned) stack
+bytes
;
156 /* Check if the data will fit within the register
157 space. Handle it if it doesn't. */
160 memcpy(argp
, *p_argv
, z
);
163 unsigned portion
= end
- cap
;
165 memcpy(argp
, *p_argv
, portion
);
168 (void*)((unsigned)(*p_argv
)+portion
), z
- portion
);
181 #if _MIPS_SIM == _MIPS_SIM_NABI32
183 /* The n32 spec says that if "a chunk consists solely of a double
184 float field (but not a double, which is part of a union), it
185 is passed in a floating point register. Any other chunk is
186 passed in an integer register". This code traverses structure
187 definitions and generates the appropriate flags. */
189 unsigned calc_n32_struct_flags(ffi_type
*arg
, unsigned *shift
)
196 while (e
= arg
->elements
[index
])
198 if (e
->type
== FFI_TYPE_DOUBLE
)
200 flags
+= (FFI_TYPE_DOUBLE
<< *shift
);
201 *shift
+= FFI_FLAG_BITS
;
203 else if (e
->type
== FFI_TYPE_STRUCT
)
204 flags
+= calc_n32_struct_flags(e
, shift
);
206 *shift
+= FFI_FLAG_BITS
;
214 unsigned calc_n32_return_struct_flags(ffi_type
*arg
)
218 unsigned small
= FFI_TYPE_SMALLSTRUCT
;
221 /* Returning structures under n32 is a tricky thing.
222 A struct with only one or two floating point fields
223 is returned in $f0 (and $f2 if necessary). Any other
224 struct results at most 128 bits are returned in $2
225 (the first 64 bits) and $3 (remainder, if necessary).
226 Larger structs are handled normally. */
232 small
= FFI_TYPE_SMALLSTRUCT2
;
234 e
= arg
->elements
[0];
235 if (e
->type
== FFI_TYPE_DOUBLE
)
236 flags
= FFI_TYPE_DOUBLE
<< FFI_FLAG_BITS
;
237 else if (e
->type
== FFI_TYPE_FLOAT
)
238 flags
= FFI_TYPE_FLOAT
<< FFI_FLAG_BITS
;
240 if (flags
&& (e
= arg
->elements
[1]))
242 if (e
->type
== FFI_TYPE_DOUBLE
)
243 flags
+= FFI_TYPE_DOUBLE
;
244 else if (e
->type
== FFI_TYPE_FLOAT
)
245 flags
+= FFI_TYPE_FLOAT
;
249 if (flags
&& (arg
->elements
[2]))
251 /* There are three arguments and the first two are
252 floats! This must be passed the old way. */
265 /* Perform machine dependent cif processing */
266 ffi_status
ffi_prep_cif_machdep(ffi_cif
*cif
)
270 #if _MIPS_SIM == _MIPS_SIM_ABI32
271 /* Set the flags necessary for O32 processing */
273 if (cif
->rtype
->type
!= FFI_TYPE_STRUCT
)
277 switch ((cif
->arg_types
)[0]->type
)
280 case FFI_TYPE_DOUBLE
:
281 cif
->flags
+= (cif
->arg_types
)[0]->type
;
290 /* Only handle the second argument if the first
291 is a float or double. */
294 switch ((cif
->arg_types
)[1]->type
)
297 case FFI_TYPE_DOUBLE
:
298 cif
->flags
+= (cif
->arg_types
)[1]->type
<< FFI_FLAG_BITS
;
309 /* Set the return type flag */
310 switch (cif
->rtype
->type
)
313 case FFI_TYPE_STRUCT
:
315 case FFI_TYPE_DOUBLE
:
316 cif
->flags
+= cif
->rtype
->type
<< (FFI_FLAG_BITS
* 2);
320 cif
->flags
+= FFI_TYPE_INT
<< (FFI_FLAG_BITS
* 2);
325 #if _MIPS_SIM == _MIPS_SIM_NABI32
326 /* Set the flags necessary for N32 processing */
329 unsigned count
= (cif
->nargs
< 8) ? cif
->nargs
: 8;
332 unsigned struct_flags
= 0;
334 if (cif
->rtype
->type
== FFI_TYPE_STRUCT
)
336 struct_flags
= calc_n32_return_struct_flags(cif
->rtype
);
338 if (struct_flags
== 0)
340 /* This means that the structure is being passed as
343 shift
= FFI_FLAG_BITS
;
344 count
= (cif
->nargs
< 7) ? cif
->nargs
: 7;
346 cif
->rstruct_flag
= !0;
349 cif
->rstruct_flag
= 0;
352 cif
->rstruct_flag
= 0;
356 switch ((cif
->arg_types
)[index
]->type
)
359 case FFI_TYPE_DOUBLE
:
360 cif
->flags
+= ((cif
->arg_types
)[index
]->type
<< shift
);
361 shift
+= FFI_FLAG_BITS
;
364 case FFI_TYPE_STRUCT
:
365 cif
->flags
+= calc_n32_struct_flags((cif
->arg_types
)[index
],
370 shift
+= FFI_FLAG_BITS
;
376 /* Set the return type flag */
377 switch (cif
->rtype
->type
)
379 case FFI_TYPE_STRUCT
:
381 if (struct_flags
== 0)
383 /* The structure is returned through a hidden
384 first argument. Do nothing, 'cause FFI_TYPE_VOID
389 /* The structure is returned via some tricky
391 cif
->flags
+= FFI_TYPE_STRUCT
<< (FFI_FLAG_BITS
* 8);
392 cif
->flags
+= struct_flags
<< (4 + (FFI_FLAG_BITS
* 8));
398 /* Do nothing, 'cause FFI_TYPE_VOID is 0 */
402 case FFI_TYPE_DOUBLE
:
403 cif
->flags
+= cif
->rtype
->type
<< (FFI_FLAG_BITS
* 8);
407 cif
->flags
+= FFI_TYPE_INT
<< (FFI_FLAG_BITS
* 8);
416 /* Low level routine for calling O32 functions */
417 extern int ffi_call_O32(void (*)(char *, extended_cif
*, int, int),
418 extended_cif
*, unsigned,
419 unsigned, unsigned *, void (*)());
421 /* Low level routine for calling N32 functions */
422 extern int ffi_call_N32(void (*)(char *, extended_cif
*, int, int),
423 extended_cif
*, unsigned,
424 unsigned, unsigned *, void (*)());
426 void ffi_call(ffi_cif
*cif
, void (*fn
)(), void *rvalue
, void **avalue
)
431 ecif
.avalue
= avalue
;
433 /* If the return value is a struct and we don't have a return */
434 /* value address then we need to make one */
436 if ((rvalue
== NULL
) &&
437 (cif
->rtype
->type
== FFI_TYPE_STRUCT
))
438 ecif
.rvalue
= alloca(cif
->rtype
->size
);
440 ecif
.rvalue
= rvalue
;
444 #if _MIPS_SIM == _MIPS_SIM_ABI32
446 ffi_call_O32(ffi_prep_args
, &ecif
, cif
->bytes
,
447 cif
->flags
, ecif
.rvalue
, fn
);
451 #if _MIPS_SIM == _MIPS_SIM_NABI32
453 ffi_call_N32(ffi_prep_args
, &ecif
, cif
->bytes
,
454 cif
->flags
, ecif
.rvalue
, fn
);