/cp
[official-gcc.git] / libffi / src / mips / ffi.c
blob5d0dd70cb32884a838d1855f8232a8f64d13113a
1 /* -----------------------------------------------------------------------
2 ffi.c - Copyright (c) 2011 Anthony Green
3 Copyright (c) 2008 David Daney
4 Copyright (c) 1996, 2007, 2008, 2011 Red Hat, Inc.
6 MIPS Foreign Function Interface
8 Permission is hereby granted, free of charge, to any person obtaining
9 a copy of this software and associated documentation files (the
10 ``Software''), to deal in the Software without restriction, including
11 without limitation the rights to use, copy, modify, merge, publish,
12 distribute, sublicense, and/or sell copies of the Software, and to
13 permit persons to whom the Software is furnished to do so, subject to
14 the following conditions:
16 The above copyright notice and this permission notice shall be included
17 in all copies or substantial portions of the Software.
19 THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND,
20 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
21 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
22 NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
23 HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
24 WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
25 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
26 DEALINGS IN THE SOFTWARE.
27 ----------------------------------------------------------------------- */
29 #include <ffi.h>
30 #include <ffi_common.h>
32 #include <stdlib.h>
34 #ifdef __GNUC__
35 # if (__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 3))
36 # define USE__BUILTIN___CLEAR_CACHE 1
37 # endif
38 #endif
40 #ifndef USE__BUILTIN___CLEAR_CACHE
41 # if defined(__OpenBSD__)
42 # include <mips64/sysarch.h>
43 # else
44 # include <sys/cachectl.h>
45 # endif
46 #endif
48 #ifdef FFI_DEBUG
49 # define FFI_MIPS_STOP_HERE() ffi_stop_here()
50 #else
51 # define FFI_MIPS_STOP_HERE() do {} while(0)
52 #endif
54 #ifdef FFI_MIPS_N32
55 #define FIX_ARGP \
56 FFI_ASSERT(argp <= &stack[bytes]); \
57 if (argp == &stack[bytes]) \
58 { \
59 argp = stack; \
60 FFI_MIPS_STOP_HERE(); \
62 #else
63 #define FIX_ARGP
64 #endif
67 /* ffi_prep_args is called by the assembly routine once stack space
68 has been allocated for the function's arguments */
70 static void ffi_prep_args(char *stack,
71 extended_cif *ecif,
72 int bytes,
73 int flags)
75 int i;
76 void **p_argv;
77 char *argp;
78 ffi_type **p_arg;
80 #ifdef FFI_MIPS_N32
81 /* If more than 8 double words are used, the remainder go
82 on the stack. We reorder stuff on the stack here to
83 support this easily. */
84 if (bytes > 8 * sizeof(ffi_arg))
85 argp = &stack[bytes - (8 * sizeof(ffi_arg))];
86 else
87 argp = stack;
88 #else
89 argp = stack;
90 #endif
92 memset(stack, 0, bytes);
94 #ifdef FFI_MIPS_N32
95 if ( ecif->cif->rstruct_flag != 0 )
96 #else
97 if ( ecif->cif->rtype->type == FFI_TYPE_STRUCT )
98 #endif
100 *(ffi_arg *) argp = (ffi_arg) ecif->rvalue;
101 argp += sizeof(ffi_arg);
102 FIX_ARGP;
105 p_argv = ecif->avalue;
107 for (i = 0, p_arg = ecif->cif->arg_types; i < ecif->cif->nargs; i++, p_arg++)
109 size_t z;
110 unsigned int a;
112 /* Align if necessary. */
113 a = (*p_arg)->alignment;
114 if (a < sizeof(ffi_arg))
115 a = sizeof(ffi_arg);
117 if ((a - 1) & (unsigned long) argp)
119 argp = (char *) ALIGN(argp, a);
120 FIX_ARGP;
123 z = (*p_arg)->size;
124 if (z <= sizeof(ffi_arg))
126 int type = (*p_arg)->type;
127 z = sizeof(ffi_arg);
129 /* The size of a pointer depends on the ABI */
130 if (type == FFI_TYPE_POINTER)
131 type = (ecif->cif->abi == FFI_N64
132 || ecif->cif->abi == FFI_N64_SOFT_FLOAT)
133 ? FFI_TYPE_SINT64 : FFI_TYPE_SINT32;
135 if (i < 8 && (ecif->cif->abi == FFI_N32_SOFT_FLOAT
136 || ecif->cif->abi == FFI_N64_SOFT_FLOAT))
138 switch (type)
140 case FFI_TYPE_FLOAT:
141 type = FFI_TYPE_UINT32;
142 break;
143 case FFI_TYPE_DOUBLE:
144 type = FFI_TYPE_UINT64;
145 break;
146 default:
147 break;
150 switch (type)
152 case FFI_TYPE_SINT8:
153 *(ffi_arg *)argp = *(SINT8 *)(* p_argv);
154 break;
156 case FFI_TYPE_UINT8:
157 *(ffi_arg *)argp = *(UINT8 *)(* p_argv);
158 break;
160 case FFI_TYPE_SINT16:
161 *(ffi_arg *)argp = *(SINT16 *)(* p_argv);
162 break;
164 case FFI_TYPE_UINT16:
165 *(ffi_arg *)argp = *(UINT16 *)(* p_argv);
166 break;
168 case FFI_TYPE_SINT32:
169 *(ffi_arg *)argp = *(SINT32 *)(* p_argv);
170 break;
172 case FFI_TYPE_UINT32:
173 #ifdef FFI_MIPS_N32
174 /* The N32 ABI requires that 32-bit integers
175 be sign-extended to 64-bits, regardless of
176 whether they are signed or unsigned. */
177 *(ffi_arg *)argp = *(SINT32 *)(* p_argv);
178 #else
179 *(ffi_arg *)argp = *(UINT32 *)(* p_argv);
180 #endif
181 break;
183 /* This can only happen with 64bit slots. */
184 case FFI_TYPE_FLOAT:
185 *(float *) argp = *(float *)(* p_argv);
186 break;
188 /* Handle structures. */
189 default:
190 memcpy(argp, *p_argv, (*p_arg)->size);
191 break;
194 else
196 #ifdef FFI_MIPS_O32
197 memcpy(argp, *p_argv, z);
198 #else
200 unsigned long end = (unsigned long) argp + z;
201 unsigned long cap = (unsigned long) stack + bytes;
203 /* Check if the data will fit within the register space.
204 Handle it if it doesn't. */
206 if (end <= cap)
207 memcpy(argp, *p_argv, z);
208 else
210 unsigned long portion = cap - (unsigned long)argp;
212 memcpy(argp, *p_argv, portion);
213 argp = stack;
214 z -= portion;
215 memcpy(argp, (void*)((unsigned long)(*p_argv) + portion),
219 #endif
221 p_argv++;
222 argp += z;
223 FIX_ARGP;
227 #ifdef FFI_MIPS_N32
229 /* The n32 spec says that if "a chunk consists solely of a double
230 float field (but not a double, which is part of a union), it
231 is passed in a floating point register. Any other chunk is
232 passed in an integer register". This code traverses structure
233 definitions and generates the appropriate flags. */
235 static unsigned
236 calc_n32_struct_flags(int soft_float, ffi_type *arg,
237 unsigned *loc, unsigned *arg_reg)
239 unsigned flags = 0;
240 unsigned index = 0;
242 ffi_type *e;
244 if (soft_float)
245 return 0;
247 while ((e = arg->elements[index]))
249 /* Align this object. */
250 *loc = ALIGN(*loc, e->alignment);
251 if (e->type == FFI_TYPE_DOUBLE)
253 /* Already aligned to FFI_SIZEOF_ARG. */
254 *arg_reg = *loc / FFI_SIZEOF_ARG;
255 if (*arg_reg > 7)
256 break;
257 flags += (FFI_TYPE_DOUBLE << (*arg_reg * FFI_FLAG_BITS));
258 *loc += e->size;
260 else
261 *loc += e->size;
262 index++;
264 /* Next Argument register at alignment of FFI_SIZEOF_ARG. */
265 *arg_reg = ALIGN(*loc, FFI_SIZEOF_ARG) / FFI_SIZEOF_ARG;
267 return flags;
270 static unsigned
271 calc_n32_return_struct_flags(int soft_float, ffi_type *arg)
273 unsigned flags = 0;
274 unsigned small = FFI_TYPE_SMALLSTRUCT;
275 ffi_type *e;
277 /* Returning structures under n32 is a tricky thing.
278 A struct with only one or two floating point fields
279 is returned in $f0 (and $f2 if necessary). Any other
280 struct results at most 128 bits are returned in $2
281 (the first 64 bits) and $3 (remainder, if necessary).
282 Larger structs are handled normally. */
284 if (arg->size > 16)
285 return 0;
287 if (arg->size > 8)
288 small = FFI_TYPE_SMALLSTRUCT2;
290 e = arg->elements[0];
292 if (e->type == FFI_TYPE_DOUBLE)
293 flags = FFI_TYPE_DOUBLE;
294 else if (e->type == FFI_TYPE_FLOAT)
295 flags = FFI_TYPE_FLOAT;
297 if (flags && (e = arg->elements[1]))
299 if (e->type == FFI_TYPE_DOUBLE)
300 flags += FFI_TYPE_DOUBLE << FFI_FLAG_BITS;
301 else if (e->type == FFI_TYPE_FLOAT)
302 flags += FFI_TYPE_FLOAT << FFI_FLAG_BITS;
303 else
304 return small;
306 if (flags && (arg->elements[2]))
308 /* There are three arguments and the first two are
309 floats! This must be passed the old way. */
310 return small;
312 if (soft_float)
313 flags += FFI_TYPE_STRUCT_SOFT;
315 else
316 if (!flags)
317 return small;
319 return flags;
322 #endif
324 /* Perform machine dependent cif processing */
325 ffi_status ffi_prep_cif_machdep(ffi_cif *cif)
327 cif->flags = 0;
329 #ifdef FFI_MIPS_O32
330 /* Set the flags necessary for O32 processing. FFI_O32_SOFT_FLOAT
331 * does not have special handling for floating point args.
334 if (cif->rtype->type != FFI_TYPE_STRUCT && cif->abi == FFI_O32)
336 if (cif->nargs > 0)
338 switch ((cif->arg_types)[0]->type)
340 case FFI_TYPE_FLOAT:
341 case FFI_TYPE_DOUBLE:
342 cif->flags += (cif->arg_types)[0]->type;
343 break;
345 default:
346 break;
349 if (cif->nargs > 1)
351 /* Only handle the second argument if the first
352 is a float or double. */
353 if (cif->flags)
355 switch ((cif->arg_types)[1]->type)
357 case FFI_TYPE_FLOAT:
358 case FFI_TYPE_DOUBLE:
359 cif->flags += (cif->arg_types)[1]->type << FFI_FLAG_BITS;
360 break;
362 default:
363 break;
370 /* Set the return type flag */
372 if (cif->abi == FFI_O32_SOFT_FLOAT)
374 switch (cif->rtype->type)
376 case FFI_TYPE_VOID:
377 case FFI_TYPE_STRUCT:
378 cif->flags += cif->rtype->type << (FFI_FLAG_BITS * 2);
379 break;
381 case FFI_TYPE_SINT64:
382 case FFI_TYPE_UINT64:
383 case FFI_TYPE_DOUBLE:
384 cif->flags += FFI_TYPE_UINT64 << (FFI_FLAG_BITS * 2);
385 break;
387 case FFI_TYPE_FLOAT:
388 default:
389 cif->flags += FFI_TYPE_INT << (FFI_FLAG_BITS * 2);
390 break;
393 else
395 /* FFI_O32 */
396 switch (cif->rtype->type)
398 case FFI_TYPE_VOID:
399 case FFI_TYPE_STRUCT:
400 case FFI_TYPE_FLOAT:
401 case FFI_TYPE_DOUBLE:
402 cif->flags += cif->rtype->type << (FFI_FLAG_BITS * 2);
403 break;
405 case FFI_TYPE_SINT64:
406 case FFI_TYPE_UINT64:
407 cif->flags += FFI_TYPE_UINT64 << (FFI_FLAG_BITS * 2);
408 break;
410 default:
411 cif->flags += FFI_TYPE_INT << (FFI_FLAG_BITS * 2);
412 break;
415 #endif
417 #ifdef FFI_MIPS_N32
418 /* Set the flags necessary for N32 processing */
420 int type;
421 unsigned arg_reg = 0;
422 unsigned loc = 0;
423 unsigned count = (cif->nargs < 8) ? cif->nargs : 8;
424 unsigned index = 0;
426 unsigned struct_flags = 0;
427 int soft_float = (cif->abi == FFI_N32_SOFT_FLOAT
428 || cif->abi == FFI_N64_SOFT_FLOAT);
430 if (cif->rtype->type == FFI_TYPE_STRUCT)
432 struct_flags = calc_n32_return_struct_flags(soft_float, cif->rtype);
434 if (struct_flags == 0)
436 /* This means that the structure is being passed as
437 a hidden argument */
439 arg_reg = 1;
440 count = (cif->nargs < 7) ? cif->nargs : 7;
442 cif->rstruct_flag = !0;
444 else
445 cif->rstruct_flag = 0;
447 else
448 cif->rstruct_flag = 0;
450 while (count-- > 0 && arg_reg < 8)
452 type = (cif->arg_types)[index]->type;
453 if (soft_float)
455 switch (type)
457 case FFI_TYPE_FLOAT:
458 type = FFI_TYPE_UINT32;
459 break;
460 case FFI_TYPE_DOUBLE:
461 type = FFI_TYPE_UINT64;
462 break;
463 default:
464 break;
467 switch (type)
469 case FFI_TYPE_FLOAT:
470 case FFI_TYPE_DOUBLE:
471 cif->flags +=
472 ((cif->arg_types)[index]->type << (arg_reg * FFI_FLAG_BITS));
473 arg_reg++;
474 break;
475 case FFI_TYPE_LONGDOUBLE:
476 /* Align it. */
477 arg_reg = ALIGN(arg_reg, 2);
478 /* Treat it as two adjacent doubles. */
479 if (soft_float)
481 arg_reg += 2;
483 else
485 cif->flags +=
486 (FFI_TYPE_DOUBLE << (arg_reg * FFI_FLAG_BITS));
487 arg_reg++;
488 cif->flags +=
489 (FFI_TYPE_DOUBLE << (arg_reg * FFI_FLAG_BITS));
490 arg_reg++;
492 break;
494 case FFI_TYPE_STRUCT:
495 loc = arg_reg * FFI_SIZEOF_ARG;
496 cif->flags += calc_n32_struct_flags(soft_float,
497 (cif->arg_types)[index],
498 &loc, &arg_reg);
499 break;
501 default:
502 arg_reg++;
503 break;
506 index++;
509 /* Set the return type flag */
510 switch (cif->rtype->type)
512 case FFI_TYPE_STRUCT:
514 if (struct_flags == 0)
516 /* The structure is returned through a hidden
517 first argument. Do nothing, 'cause FFI_TYPE_VOID
518 is 0 */
520 else
522 /* The structure is returned via some tricky
523 mechanism */
524 cif->flags += FFI_TYPE_STRUCT << (FFI_FLAG_BITS * 8);
525 cif->flags += struct_flags << (4 + (FFI_FLAG_BITS * 8));
527 break;
530 case FFI_TYPE_VOID:
531 /* Do nothing, 'cause FFI_TYPE_VOID is 0 */
532 break;
534 case FFI_TYPE_POINTER:
535 if (cif->abi == FFI_N32_SOFT_FLOAT || cif->abi == FFI_N32)
536 cif->flags += FFI_TYPE_SINT32 << (FFI_FLAG_BITS * 8);
537 else
538 cif->flags += FFI_TYPE_INT << (FFI_FLAG_BITS * 8);
539 break;
541 case FFI_TYPE_FLOAT:
542 if (soft_float)
544 cif->flags += FFI_TYPE_SINT32 << (FFI_FLAG_BITS * 8);
545 break;
547 /* else fall through */
548 case FFI_TYPE_DOUBLE:
549 if (soft_float)
550 cif->flags += FFI_TYPE_INT << (FFI_FLAG_BITS * 8);
551 else
552 cif->flags += cif->rtype->type << (FFI_FLAG_BITS * 8);
553 break;
555 case FFI_TYPE_LONGDOUBLE:
556 /* Long double is returned as if it were a struct containing
557 two doubles. */
558 if (soft_float)
560 cif->flags += FFI_TYPE_STRUCT << (FFI_FLAG_BITS * 8);
561 cif->flags += FFI_TYPE_SMALLSTRUCT2 << (4 + (FFI_FLAG_BITS * 8));
563 else
565 cif->flags += FFI_TYPE_STRUCT << (FFI_FLAG_BITS * 8);
566 cif->flags += (FFI_TYPE_DOUBLE
567 + (FFI_TYPE_DOUBLE << FFI_FLAG_BITS))
568 << (4 + (FFI_FLAG_BITS * 8));
570 break;
571 default:
572 cif->flags += FFI_TYPE_INT << (FFI_FLAG_BITS * 8);
573 break;
576 #endif
578 return FFI_OK;
581 /* Low level routine for calling O32 functions */
582 extern int ffi_call_O32(void (*)(char *, extended_cif *, int, int),
583 extended_cif *, unsigned,
584 unsigned, unsigned *, void (*)(void));
586 /* Low level routine for calling N32 functions */
587 extern int ffi_call_N32(void (*)(char *, extended_cif *, int, int),
588 extended_cif *, unsigned,
589 unsigned, void *, void (*)(void));
591 void ffi_call(ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue)
593 extended_cif ecif;
595 ecif.cif = cif;
596 ecif.avalue = avalue;
598 /* If the return value is a struct and we don't have a return */
599 /* value address then we need to make one */
601 if ((rvalue == NULL) &&
602 (cif->rtype->type == FFI_TYPE_STRUCT))
603 ecif.rvalue = alloca(cif->rtype->size);
604 else
605 ecif.rvalue = rvalue;
607 switch (cif->abi)
609 #ifdef FFI_MIPS_O32
610 case FFI_O32:
611 case FFI_O32_SOFT_FLOAT:
612 ffi_call_O32(ffi_prep_args, &ecif, cif->bytes,
613 cif->flags, ecif.rvalue, fn);
614 break;
615 #endif
617 #ifdef FFI_MIPS_N32
618 case FFI_N32:
619 case FFI_N32_SOFT_FLOAT:
620 case FFI_N64:
621 case FFI_N64_SOFT_FLOAT:
623 int copy_rvalue = 0;
624 int copy_offset = 0;
625 char *rvalue_copy = ecif.rvalue;
626 if (cif->rtype->type == FFI_TYPE_STRUCT && cif->rtype->size < 16)
628 /* For structures smaller than 16 bytes we clobber memory
629 in 8 byte increments. Make a copy so we don't clobber
630 the callers memory outside of the struct bounds. */
631 rvalue_copy = alloca(16);
632 copy_rvalue = 1;
634 else if (cif->rtype->type == FFI_TYPE_FLOAT
635 && (cif->abi == FFI_N64_SOFT_FLOAT
636 || cif->abi == FFI_N32_SOFT_FLOAT))
638 rvalue_copy = alloca (8);
639 copy_rvalue = 1;
640 #if defined(__MIPSEB__) || defined(_MIPSEB)
641 copy_offset = 4;
642 #endif
644 ffi_call_N32(ffi_prep_args, &ecif, cif->bytes,
645 cif->flags, rvalue_copy, fn);
646 if (copy_rvalue)
647 memcpy(ecif.rvalue, rvalue_copy + copy_offset, cif->rtype->size);
649 break;
650 #endif
652 default:
653 FFI_ASSERT(0);
654 break;
658 #if FFI_CLOSURES
659 #if defined(FFI_MIPS_O32)
660 extern void ffi_closure_O32(void);
661 #else
662 extern void ffi_closure_N32(void);
663 #endif /* FFI_MIPS_O32 */
665 ffi_status
666 ffi_prep_closure_loc (ffi_closure *closure,
667 ffi_cif *cif,
668 void (*fun)(ffi_cif*,void*,void**,void*),
669 void *user_data,
670 void *codeloc)
672 unsigned int *tramp = (unsigned int *) &closure->tramp[0];
673 void * fn;
674 char *clear_location = (char *) codeloc;
676 #if defined(FFI_MIPS_O32)
677 if (cif->abi != FFI_O32 && cif->abi != FFI_O32_SOFT_FLOAT)
678 return FFI_BAD_ABI;
679 fn = ffi_closure_O32;
680 #else
681 #if _MIPS_SIM ==_ABIN32
682 if (cif->abi != FFI_N32
683 && cif->abi != FFI_N32_SOFT_FLOAT)
684 return FFI_BAD_ABI;
685 #else
686 if (cif->abi != FFI_N64
687 && cif->abi != FFI_N64_SOFT_FLOAT)
688 return FFI_BAD_ABI;
689 #endif
690 fn = ffi_closure_N32;
691 #endif /* FFI_MIPS_O32 */
693 #if defined(FFI_MIPS_O32) || (_MIPS_SIM ==_ABIN32)
694 /* lui $25,high(fn) */
695 tramp[0] = 0x3c190000 | ((unsigned)fn >> 16);
696 /* ori $25,low(fn) */
697 tramp[1] = 0x37390000 | ((unsigned)fn & 0xffff);
698 /* lui $12,high(codeloc) */
699 tramp[2] = 0x3c0c0000 | ((unsigned)codeloc >> 16);
700 /* jr $25 */
701 tramp[3] = 0x03200008;
702 /* ori $12,low(codeloc) */
703 tramp[4] = 0x358c0000 | ((unsigned)codeloc & 0xffff);
704 #else
705 /* N64 has a somewhat larger trampoline. */
706 /* lui $25,high(fn) */
707 tramp[0] = 0x3c190000 | ((unsigned long)fn >> 48);
708 /* lui $12,high(codeloc) */
709 tramp[1] = 0x3c0c0000 | ((unsigned long)codeloc >> 48);
710 /* ori $25,mid-high(fn) */
711 tramp[2] = 0x37390000 | (((unsigned long)fn >> 32 ) & 0xffff);
712 /* ori $12,mid-high(codeloc) */
713 tramp[3] = 0x358c0000 | (((unsigned long)codeloc >> 32) & 0xffff);
714 /* dsll $25,$25,16 */
715 tramp[4] = 0x0019cc38;
716 /* dsll $12,$12,16 */
717 tramp[5] = 0x000c6438;
718 /* ori $25,mid-low(fn) */
719 tramp[6] = 0x37390000 | (((unsigned long)fn >> 16 ) & 0xffff);
720 /* ori $12,mid-low(codeloc) */
721 tramp[7] = 0x358c0000 | (((unsigned long)codeloc >> 16) & 0xffff);
722 /* dsll $25,$25,16 */
723 tramp[8] = 0x0019cc38;
724 /* dsll $12,$12,16 */
725 tramp[9] = 0x000c6438;
726 /* ori $25,low(fn) */
727 tramp[10] = 0x37390000 | ((unsigned long)fn & 0xffff);
728 /* jr $25 */
729 tramp[11] = 0x03200008;
730 /* ori $12,low(codeloc) */
731 tramp[12] = 0x358c0000 | ((unsigned long)codeloc & 0xffff);
733 #endif
735 closure->cif = cif;
736 closure->fun = fun;
737 closure->user_data = user_data;
739 #ifdef USE__BUILTIN___CLEAR_CACHE
740 __builtin___clear_cache(clear_location, clear_location + FFI_TRAMPOLINE_SIZE);
741 #else
742 cacheflush (clear_location, FFI_TRAMPOLINE_SIZE, ICACHE);
743 #endif
744 return FFI_OK;
748 * Decodes the arguments to a function, which will be stored on the
749 * stack. AR is the pointer to the beginning of the integer arguments
750 * (and, depending upon the arguments, some floating-point arguments
751 * as well). FPR is a pointer to the area where floating point
752 * registers have been saved, if any.
754 * RVALUE is the location where the function return value will be
755 * stored. CLOSURE is the prepared closure to invoke.
757 * This function should only be called from assembly, which is in
758 * turn called from a trampoline.
760 * Returns the function return type.
762 * Based on the similar routine for sparc.
765 ffi_closure_mips_inner_O32 (ffi_closure *closure,
766 void *rvalue, ffi_arg *ar,
767 double *fpr)
769 ffi_cif *cif;
770 void **avaluep;
771 ffi_arg *avalue;
772 ffi_type **arg_types;
773 int i, avn, argn, seen_int;
775 cif = closure->cif;
776 avalue = alloca (cif->nargs * sizeof (ffi_arg));
777 avaluep = alloca (cif->nargs * sizeof (ffi_arg));
779 seen_int = (cif->abi == FFI_O32_SOFT_FLOAT);
780 argn = 0;
782 if ((cif->flags >> (FFI_FLAG_BITS * 2)) == FFI_TYPE_STRUCT)
784 rvalue = (void *)(UINT32)ar[0];
785 argn = 1;
788 i = 0;
789 avn = cif->nargs;
790 arg_types = cif->arg_types;
792 while (i < avn)
794 if (i < 2 && !seen_int &&
795 (arg_types[i]->type == FFI_TYPE_FLOAT ||
796 arg_types[i]->type == FFI_TYPE_DOUBLE ||
797 arg_types[i]->type == FFI_TYPE_LONGDOUBLE))
799 #if defined(__MIPSEB__) || defined(_MIPSEB)
800 if (arg_types[i]->type == FFI_TYPE_FLOAT)
801 avaluep[i] = ((char *) &fpr[i]) + sizeof (float);
802 else
803 #endif
804 avaluep[i] = (char *) &fpr[i];
806 else
808 if (arg_types[i]->alignment == 8 && (argn & 0x1))
809 argn++;
810 switch (arg_types[i]->type)
812 case FFI_TYPE_SINT8:
813 avaluep[i] = &avalue[i];
814 *(SINT8 *) &avalue[i] = (SINT8) ar[argn];
815 break;
817 case FFI_TYPE_UINT8:
818 avaluep[i] = &avalue[i];
819 *(UINT8 *) &avalue[i] = (UINT8) ar[argn];
820 break;
822 case FFI_TYPE_SINT16:
823 avaluep[i] = &avalue[i];
824 *(SINT16 *) &avalue[i] = (SINT16) ar[argn];
825 break;
827 case FFI_TYPE_UINT16:
828 avaluep[i] = &avalue[i];
829 *(UINT16 *) &avalue[i] = (UINT16) ar[argn];
830 break;
832 default:
833 avaluep[i] = (char *) &ar[argn];
834 break;
836 seen_int = 1;
838 argn += ALIGN(arg_types[i]->size, FFI_SIZEOF_ARG) / FFI_SIZEOF_ARG;
839 i++;
842 /* Invoke the closure. */
843 (closure->fun) (cif, rvalue, avaluep, closure->user_data);
845 if (cif->abi == FFI_O32_SOFT_FLOAT)
847 switch (cif->rtype->type)
849 case FFI_TYPE_FLOAT:
850 return FFI_TYPE_INT;
851 case FFI_TYPE_DOUBLE:
852 return FFI_TYPE_UINT64;
853 default:
854 return cif->rtype->type;
857 else
859 return cif->rtype->type;
863 #if defined(FFI_MIPS_N32)
865 static void
866 copy_struct_N32(char *target, unsigned offset, ffi_abi abi, ffi_type *type,
867 int argn, unsigned arg_offset, ffi_arg *ar,
868 ffi_arg *fpr, int soft_float)
870 ffi_type **elt_typep = type->elements;
871 while(*elt_typep)
873 ffi_type *elt_type = *elt_typep;
874 unsigned o;
875 char *tp;
876 char *argp;
877 char *fpp;
879 o = ALIGN(offset, elt_type->alignment);
880 arg_offset += o - offset;
881 offset = o;
882 argn += arg_offset / sizeof(ffi_arg);
883 arg_offset = arg_offset % sizeof(ffi_arg);
885 argp = (char *)(ar + argn);
886 fpp = (char *)(argn >= 8 ? ar + argn : fpr + argn);
888 tp = target + offset;
890 if (elt_type->type == FFI_TYPE_DOUBLE && !soft_float)
891 *(double *)tp = *(double *)fpp;
892 else
893 memcpy(tp, argp + arg_offset, elt_type->size);
895 offset += elt_type->size;
896 arg_offset += elt_type->size;
897 elt_typep++;
898 argn += arg_offset / sizeof(ffi_arg);
899 arg_offset = arg_offset % sizeof(ffi_arg);
904 * Decodes the arguments to a function, which will be stored on the
905 * stack. AR is the pointer to the beginning of the integer
906 * arguments. FPR is a pointer to the area where floating point
907 * registers have been saved.
909 * RVALUE is the location where the function return value will be
910 * stored. CLOSURE is the prepared closure to invoke.
912 * This function should only be called from assembly, which is in
913 * turn called from a trampoline.
915 * Returns the function return flags.
919 ffi_closure_mips_inner_N32 (ffi_closure *closure,
920 void *rvalue, ffi_arg *ar,
921 ffi_arg *fpr)
923 ffi_cif *cif;
924 void **avaluep;
925 ffi_arg *avalue;
926 ffi_type **arg_types;
927 int i, avn, argn;
928 int soft_float;
929 ffi_arg *argp;
931 cif = closure->cif;
932 soft_float = cif->abi == FFI_N64_SOFT_FLOAT
933 || cif->abi == FFI_N32_SOFT_FLOAT;
934 avalue = alloca (cif->nargs * sizeof (ffi_arg));
935 avaluep = alloca (cif->nargs * sizeof (ffi_arg));
937 argn = 0;
939 if (cif->rstruct_flag)
941 #if _MIPS_SIM==_ABIN32
942 rvalue = (void *)(UINT32)ar[0];
943 #else /* N64 */
944 rvalue = (void *)ar[0];
945 #endif
946 argn = 1;
949 i = 0;
950 avn = cif->nargs;
951 arg_types = cif->arg_types;
953 while (i < avn)
955 if (arg_types[i]->type == FFI_TYPE_FLOAT
956 || arg_types[i]->type == FFI_TYPE_DOUBLE
957 || arg_types[i]->type == FFI_TYPE_LONGDOUBLE)
959 argp = (argn >= 8 || soft_float) ? ar + argn : fpr + argn;
960 if ((arg_types[i]->type == FFI_TYPE_LONGDOUBLE) && ((unsigned)argp & (arg_types[i]->alignment-1)))
962 argp=(ffi_arg*)ALIGN(argp,arg_types[i]->alignment);
963 argn++;
965 #if defined(__MIPSEB__) || defined(_MIPSEB)
966 if (arg_types[i]->type == FFI_TYPE_FLOAT && argn < 8)
967 avaluep[i] = ((char *) argp) + sizeof (float);
968 else
969 #endif
970 avaluep[i] = (char *) argp;
972 else
974 unsigned type = arg_types[i]->type;
976 if (arg_types[i]->alignment > sizeof(ffi_arg))
977 argn = ALIGN(argn, arg_types[i]->alignment / sizeof(ffi_arg));
979 argp = ar + argn;
981 /* The size of a pointer depends on the ABI */
982 if (type == FFI_TYPE_POINTER)
983 type = (cif->abi == FFI_N64 || cif->abi == FFI_N64_SOFT_FLOAT)
984 ? FFI_TYPE_SINT64 : FFI_TYPE_SINT32;
986 if (soft_float && type == FFI_TYPE_FLOAT)
987 type = FFI_TYPE_UINT32;
989 switch (type)
991 case FFI_TYPE_SINT8:
992 avaluep[i] = &avalue[i];
993 *(SINT8 *) &avalue[i] = (SINT8) *argp;
994 break;
996 case FFI_TYPE_UINT8:
997 avaluep[i] = &avalue[i];
998 *(UINT8 *) &avalue[i] = (UINT8) *argp;
999 break;
1001 case FFI_TYPE_SINT16:
1002 avaluep[i] = &avalue[i];
1003 *(SINT16 *) &avalue[i] = (SINT16) *argp;
1004 break;
1006 case FFI_TYPE_UINT16:
1007 avaluep[i] = &avalue[i];
1008 *(UINT16 *) &avalue[i] = (UINT16) *argp;
1009 break;
1011 case FFI_TYPE_SINT32:
1012 avaluep[i] = &avalue[i];
1013 *(SINT32 *) &avalue[i] = (SINT32) *argp;
1014 break;
1016 case FFI_TYPE_UINT32:
1017 avaluep[i] = &avalue[i];
1018 *(UINT32 *) &avalue[i] = (UINT32) *argp;
1019 break;
1021 case FFI_TYPE_STRUCT:
1022 if (argn < 8)
1024 /* Allocate space for the struct as at least part of
1025 it was passed in registers. */
1026 avaluep[i] = alloca(arg_types[i]->size);
1027 copy_struct_N32(avaluep[i], 0, cif->abi, arg_types[i],
1028 argn, 0, ar, fpr, soft_float);
1030 break;
1032 /* Else fall through. */
1033 default:
1034 avaluep[i] = (char *) argp;
1035 break;
1038 argn += ALIGN(arg_types[i]->size, sizeof(ffi_arg)) / sizeof(ffi_arg);
1039 i++;
1042 /* Invoke the closure. */
1043 (closure->fun) (cif, rvalue, avaluep, closure->user_data);
1045 return cif->flags >> (FFI_FLAG_BITS * 8);
1048 #endif /* FFI_MIPS_N32 */
1050 #endif /* FFI_CLOSURES */