Merged with mainline at revision 128810.
[official-gcc.git] / libffi / src / mips / ffi.c
blobcc2a42e7a9f5e9072348b4880a58ac7dd5d79e7b
1 /* -----------------------------------------------------------------------
2 ffi.c - Copyright (c) 1996, 2007 Red Hat, Inc.
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 ----------------------------------------------------------------------- */
26 #include <ffi.h>
27 #include <ffi_common.h>
29 #include <stdlib.h>
31 #ifdef FFI_DEBUG
32 # define FFI_MIPS_STOP_HERE() ffi_stop_here()
33 #else
34 # define FFI_MIPS_STOP_HERE() do {} while(0)
35 #endif
37 #ifdef FFI_MIPS_N32
38 #define FIX_ARGP \
39 FFI_ASSERT(argp <= &stack[bytes]); \
40 if (argp == &stack[bytes]) \
41 { \
42 argp = stack; \
43 FFI_MIPS_STOP_HERE(); \
45 #else
46 #define FIX_ARGP
47 #endif
50 /* ffi_prep_args is called by the assembly routine once stack space
51 has been allocated for the function's arguments */
53 static void ffi_prep_args(char *stack,
54 extended_cif *ecif,
55 int bytes,
56 int flags)
58 int i;
59 void **p_argv;
60 char *argp;
61 ffi_type **p_arg;
63 #ifdef FFI_MIPS_N32
64 /* If more than 8 double words are used, the remainder go
65 on the stack. We reorder stuff on the stack here to
66 support this easily. */
67 if (bytes > 8 * sizeof(ffi_arg))
68 argp = &stack[bytes - (8 * sizeof(ffi_arg))];
69 else
70 argp = stack;
71 #else
72 argp = stack;
73 #endif
75 memset(stack, 0, bytes);
77 #ifdef FFI_MIPS_N32
78 if ( ecif->cif->rstruct_flag != 0 )
79 #else
80 if ( ecif->cif->rtype->type == FFI_TYPE_STRUCT )
81 #endif
83 *(ffi_arg *) argp = (ffi_arg) ecif->rvalue;
84 argp += sizeof(ffi_arg);
85 FIX_ARGP;
88 p_argv = ecif->avalue;
90 for (i = ecif->cif->nargs, p_arg = ecif->cif->arg_types; i; i--, p_arg++)
92 size_t z;
93 unsigned int a;
95 /* Align if necessary. */
96 a = (*p_arg)->alignment;
97 if (a < sizeof(ffi_arg))
98 a = sizeof(ffi_arg);
100 if ((a - 1) & (unsigned long) argp)
102 argp = (char *) ALIGN(argp, a);
103 FIX_ARGP;
106 z = (*p_arg)->size;
107 if (z <= sizeof(ffi_arg))
109 int type = (*p_arg)->type;
110 z = sizeof(ffi_arg);
112 /* The size of a pointer depends on the ABI */
113 if (type == FFI_TYPE_POINTER)
114 type =
115 (ecif->cif->abi == FFI_N64) ? FFI_TYPE_SINT64 : FFI_TYPE_SINT32;
117 switch (type)
119 case FFI_TYPE_SINT8:
120 *(ffi_arg *)argp = *(SINT8 *)(* p_argv);
121 break;
123 case FFI_TYPE_UINT8:
124 *(ffi_arg *)argp = *(UINT8 *)(* p_argv);
125 break;
127 case FFI_TYPE_SINT16:
128 *(ffi_arg *)argp = *(SINT16 *)(* p_argv);
129 break;
131 case FFI_TYPE_UINT16:
132 *(ffi_arg *)argp = *(UINT16 *)(* p_argv);
133 break;
135 case FFI_TYPE_SINT32:
136 *(ffi_arg *)argp = *(SINT32 *)(* p_argv);
137 break;
139 case FFI_TYPE_UINT32:
140 *(ffi_arg *)argp = *(UINT32 *)(* p_argv);
141 break;
143 /* This can only happen with 64bit slots. */
144 case FFI_TYPE_FLOAT:
145 *(float *) argp = *(float *)(* p_argv);
146 break;
148 /* Handle structures. */
149 default:
150 memcpy(argp, *p_argv, (*p_arg)->size);
151 break;
154 else
156 #ifdef FFI_MIPS_O32
157 memcpy(argp, *p_argv, z);
158 #else
160 unsigned long end = (unsigned long) argp + z;
161 unsigned long cap = (unsigned long) stack + bytes;
163 /* Check if the data will fit within the register space.
164 Handle it if it doesn't. */
166 if (end <= cap)
167 memcpy(argp, *p_argv, z);
168 else
170 unsigned long portion = cap - (unsigned long)argp;
172 memcpy(argp, *p_argv, portion);
173 argp = stack;
174 z -= portion;
175 memcpy(argp, (void*)((unsigned long)(*p_argv) + portion),
179 #endif
181 p_argv++;
182 argp += z;
183 FIX_ARGP;
187 #ifdef FFI_MIPS_N32
189 /* The n32 spec says that if "a chunk consists solely of a double
190 float field (but not a double, which is part of a union), it
191 is passed in a floating point register. Any other chunk is
192 passed in an integer register". This code traverses structure
193 definitions and generates the appropriate flags. */
195 static unsigned
196 calc_n32_struct_flags(ffi_type *arg, unsigned *loc, unsigned *arg_reg)
198 unsigned flags = 0;
199 unsigned index = 0;
201 ffi_type *e;
203 while ((e = arg->elements[index]))
205 /* Align this object. */
206 *loc = ALIGN(*loc, e->alignment);
207 if (e->type == FFI_TYPE_DOUBLE)
209 /* Already aligned to FFI_SIZEOF_ARG. */
210 *arg_reg = *loc / FFI_SIZEOF_ARG;
211 if (*arg_reg > 7)
212 break;
213 flags += (FFI_TYPE_DOUBLE << (*arg_reg * FFI_FLAG_BITS));
214 *loc += e->size;
216 else
217 *loc += e->size;
218 index++;
220 /* Next Argument register at alignment of FFI_SIZEOF_ARG. */
221 *arg_reg = ALIGN(*loc, FFI_SIZEOF_ARG) / FFI_SIZEOF_ARG;
223 return flags;
226 static unsigned
227 calc_n32_return_struct_flags(ffi_type *arg)
229 unsigned flags = 0;
230 unsigned small = FFI_TYPE_SMALLSTRUCT;
231 ffi_type *e;
233 /* Returning structures under n32 is a tricky thing.
234 A struct with only one or two floating point fields
235 is returned in $f0 (and $f2 if necessary). Any other
236 struct results at most 128 bits are returned in $2
237 (the first 64 bits) and $3 (remainder, if necessary).
238 Larger structs are handled normally. */
240 if (arg->size > 16)
241 return 0;
243 if (arg->size > 8)
244 small = FFI_TYPE_SMALLSTRUCT2;
246 e = arg->elements[0];
247 if (e->type == FFI_TYPE_DOUBLE)
248 flags = FFI_TYPE_DOUBLE;
249 else if (e->type == FFI_TYPE_FLOAT)
250 flags = FFI_TYPE_FLOAT;
252 if (flags && (e = arg->elements[1]))
254 if (e->type == FFI_TYPE_DOUBLE)
255 flags += FFI_TYPE_DOUBLE << FFI_FLAG_BITS;
256 else if (e->type == FFI_TYPE_FLOAT)
257 flags += FFI_TYPE_FLOAT << FFI_FLAG_BITS;
258 else
259 return small;
261 if (flags && (arg->elements[2]))
263 /* There are three arguments and the first two are
264 floats! This must be passed the old way. */
265 return small;
268 else
269 if (!flags)
270 return small;
272 return flags;
275 #endif
277 /* Perform machine dependent cif processing */
278 ffi_status ffi_prep_cif_machdep(ffi_cif *cif)
280 cif->flags = 0;
282 #ifdef FFI_MIPS_O32
283 /* Set the flags necessary for O32 processing. FFI_O32_SOFT_FLOAT
284 * does not have special handling for floating point args.
287 if (cif->rtype->type != FFI_TYPE_STRUCT && cif->abi == FFI_O32)
289 if (cif->nargs > 0)
291 switch ((cif->arg_types)[0]->type)
293 case FFI_TYPE_FLOAT:
294 case FFI_TYPE_DOUBLE:
295 cif->flags += (cif->arg_types)[0]->type;
296 break;
298 default:
299 break;
302 if (cif->nargs > 1)
304 /* Only handle the second argument if the first
305 is a float or double. */
306 if (cif->flags)
308 switch ((cif->arg_types)[1]->type)
310 case FFI_TYPE_FLOAT:
311 case FFI_TYPE_DOUBLE:
312 cif->flags += (cif->arg_types)[1]->type << FFI_FLAG_BITS;
313 break;
315 default:
316 break;
323 /* Set the return type flag */
325 if (cif->abi == FFI_O32_SOFT_FLOAT)
327 switch (cif->rtype->type)
329 case FFI_TYPE_VOID:
330 case FFI_TYPE_STRUCT:
331 cif->flags += cif->rtype->type << (FFI_FLAG_BITS * 2);
332 break;
334 case FFI_TYPE_SINT64:
335 case FFI_TYPE_UINT64:
336 case FFI_TYPE_DOUBLE:
337 cif->flags += FFI_TYPE_UINT64 << (FFI_FLAG_BITS * 2);
338 break;
340 case FFI_TYPE_FLOAT:
341 default:
342 cif->flags += FFI_TYPE_INT << (FFI_FLAG_BITS * 2);
343 break;
346 else
348 /* FFI_O32 */
349 switch (cif->rtype->type)
351 case FFI_TYPE_VOID:
352 case FFI_TYPE_STRUCT:
353 case FFI_TYPE_FLOAT:
354 case FFI_TYPE_DOUBLE:
355 cif->flags += cif->rtype->type << (FFI_FLAG_BITS * 2);
356 break;
358 case FFI_TYPE_SINT64:
359 case FFI_TYPE_UINT64:
360 cif->flags += FFI_TYPE_UINT64 << (FFI_FLAG_BITS * 2);
361 break;
363 default:
364 cif->flags += FFI_TYPE_INT << (FFI_FLAG_BITS * 2);
365 break;
368 #endif
370 #ifdef FFI_MIPS_N32
371 /* Set the flags necessary for N32 processing */
373 unsigned arg_reg = 0;
374 unsigned loc = 0;
375 unsigned count = (cif->nargs < 8) ? cif->nargs : 8;
376 unsigned index = 0;
378 unsigned struct_flags = 0;
380 if (cif->rtype->type == FFI_TYPE_STRUCT)
382 struct_flags = calc_n32_return_struct_flags(cif->rtype);
384 if (struct_flags == 0)
386 /* This means that the structure is being passed as
387 a hidden argument */
389 arg_reg = 1;
390 count = (cif->nargs < 7) ? cif->nargs : 7;
392 cif->rstruct_flag = !0;
394 else
395 cif->rstruct_flag = 0;
397 else
398 cif->rstruct_flag = 0;
400 while (count-- > 0 && arg_reg < 8)
402 switch ((cif->arg_types)[index]->type)
404 case FFI_TYPE_FLOAT:
405 case FFI_TYPE_DOUBLE:
406 cif->flags +=
407 ((cif->arg_types)[index]->type << (arg_reg * FFI_FLAG_BITS));
408 arg_reg++;
409 break;
410 case FFI_TYPE_LONGDOUBLE:
411 /* Align it. */
412 arg_reg = ALIGN(arg_reg, 2);
413 /* Treat it as two adjacent doubles. */
414 cif->flags +=
415 (FFI_TYPE_DOUBLE << (arg_reg * FFI_FLAG_BITS));
416 arg_reg++;
417 cif->flags +=
418 (FFI_TYPE_DOUBLE << (arg_reg * FFI_FLAG_BITS));
419 arg_reg++;
420 break;
422 case FFI_TYPE_STRUCT:
423 loc = arg_reg * FFI_SIZEOF_ARG;
424 cif->flags += calc_n32_struct_flags((cif->arg_types)[index],
425 &loc, &arg_reg);
426 break;
428 default:
429 arg_reg++;
430 break;
433 index++;
436 /* Set the return type flag */
437 switch (cif->rtype->type)
439 case FFI_TYPE_STRUCT:
441 if (struct_flags == 0)
443 /* The structure is returned through a hidden
444 first argument. Do nothing, 'cause FFI_TYPE_VOID
445 is 0 */
447 else
449 /* The structure is returned via some tricky
450 mechanism */
451 cif->flags += FFI_TYPE_STRUCT << (FFI_FLAG_BITS * 8);
452 cif->flags += struct_flags << (4 + (FFI_FLAG_BITS * 8));
454 break;
457 case FFI_TYPE_VOID:
458 /* Do nothing, 'cause FFI_TYPE_VOID is 0 */
459 break;
461 case FFI_TYPE_FLOAT:
462 case FFI_TYPE_DOUBLE:
463 cif->flags += cif->rtype->type << (FFI_FLAG_BITS * 8);
464 break;
466 default:
467 cif->flags += FFI_TYPE_INT << (FFI_FLAG_BITS * 8);
468 break;
471 #endif
473 return FFI_OK;
476 /* Low level routine for calling O32 functions */
477 extern int ffi_call_O32(void (*)(char *, extended_cif *, int, int),
478 extended_cif *, unsigned,
479 unsigned, unsigned *, void (*)());
481 /* Low level routine for calling N32 functions */
482 extern int ffi_call_N32(void (*)(char *, extended_cif *, int, int),
483 extended_cif *, unsigned,
484 unsigned, unsigned *, void (*)());
486 void ffi_call(ffi_cif *cif, void (*fn)(), void *rvalue, void **avalue)
488 extended_cif ecif;
490 ecif.cif = cif;
491 ecif.avalue = avalue;
493 /* If the return value is a struct and we don't have a return */
494 /* value address then we need to make one */
496 if ((rvalue == NULL) &&
497 (cif->rtype->type == FFI_TYPE_STRUCT))
498 ecif.rvalue = alloca(cif->rtype->size);
499 else
500 ecif.rvalue = rvalue;
502 switch (cif->abi)
504 #ifdef FFI_MIPS_O32
505 case FFI_O32:
506 case FFI_O32_SOFT_FLOAT:
507 ffi_call_O32(ffi_prep_args, &ecif, cif->bytes,
508 cif->flags, ecif.rvalue, fn);
509 break;
510 #endif
512 #ifdef FFI_MIPS_N32
513 case FFI_N32:
514 case FFI_N64:
516 int copy_rvalue = 0;
517 void *rvalue_copy = ecif.rvalue;
518 if (cif->rtype->type == FFI_TYPE_STRUCT && cif->rtype->size < 16)
520 /* For structures smaller than 16 bytes we clobber memory
521 in 8 byte increments. Make a copy so we don't clobber
522 the callers memory outside of the struct bounds. */
523 rvalue_copy = alloca(16);
524 copy_rvalue = 1;
526 ffi_call_N32(ffi_prep_args, &ecif, cif->bytes,
527 cif->flags, rvalue_copy, fn);
528 if (copy_rvalue)
529 memcpy(ecif.rvalue, rvalue_copy, cif->rtype->size);
531 break;
532 #endif
534 default:
535 FFI_ASSERT(0);
536 break;
540 #if FFI_CLOSURES
541 #if defined(FFI_MIPS_O32)
542 extern void ffi_closure_O32(void);
543 #else
544 extern void ffi_closure_N32(void);
545 #endif /* FFI_MIPS_O32 */
547 ffi_status
548 ffi_prep_closure_loc (ffi_closure *closure,
549 ffi_cif *cif,
550 void (*fun)(ffi_cif*,void*,void**,void*),
551 void *user_data,
552 void *codeloc)
554 unsigned int *tramp = (unsigned int *) &closure->tramp[0];
555 void * fn;
556 char *clear_location = (char *) codeloc;
558 #if defined(FFI_MIPS_O32)
559 FFI_ASSERT(cif->abi == FFI_O32 || cif->abi == FFI_O32_SOFT_FLOAT);
560 fn = ffi_closure_O32;
561 #else /* FFI_MIPS_N32 */
562 FFI_ASSERT(cif->abi == FFI_N32 || cif->abi == FFI_N64);
563 fn = ffi_closure_N32;
564 #endif /* FFI_MIPS_O32 */
566 #if defined(FFI_MIPS_O32) || (_MIPS_SIM ==_ABIN32)
567 /* lui $25,high(fn) */
568 tramp[0] = 0x3c190000 | ((unsigned)fn >> 16);
569 /* ori $25,low(fn) */
570 tramp[1] = 0x37390000 | ((unsigned)fn & 0xffff);
571 /* lui $12,high(codeloc) */
572 tramp[2] = 0x3c0c0000 | ((unsigned)codeloc >> 16);
573 /* jr $25 */
574 tramp[3] = 0x03200008;
575 /* ori $12,low(codeloc) */
576 tramp[4] = 0x358c0000 | ((unsigned)codeloc & 0xffff);
577 #else
578 /* N64 has a somewhat larger trampoline. */
579 /* lui $25,high(fn) */
580 tramp[0] = 0x3c190000 | ((unsigned long)fn >> 48);
581 /* lui $12,high(codeloc) */
582 tramp[1] = 0x3c0c0000 | ((unsigned long)codeloc >> 48);
583 /* ori $25,mid-high(fn) */
584 tramp[2] = 0x37390000 | (((unsigned long)fn >> 32 ) & 0xffff);
585 /* ori $12,mid-high(codeloc) */
586 tramp[3] = 0x358c0000 | (((unsigned long)codeloc >> 32) & 0xffff);
587 /* dsll $25,$25,16 */
588 tramp[4] = 0x0019cc38;
589 /* dsll $12,$12,16 */
590 tramp[5] = 0x000c6438;
591 /* ori $25,mid-low(fn) */
592 tramp[6] = 0x37390000 | (((unsigned long)fn >> 16 ) & 0xffff);
593 /* ori $12,mid-low(codeloc) */
594 tramp[7] = 0x358c0000 | (((unsigned long)codeloc >> 16) & 0xffff);
595 /* dsll $25,$25,16 */
596 tramp[8] = 0x0019cc38;
597 /* dsll $12,$12,16 */
598 tramp[9] = 0x000c6438;
599 /* ori $25,low(fn) */
600 tramp[10] = 0x37390000 | ((unsigned long)fn & 0xffff);
601 /* jr $25 */
602 tramp[11] = 0x03200008;
603 /* ori $12,low(codeloc) */
604 tramp[12] = 0x358c0000 | ((unsigned long)codeloc & 0xffff);
606 #endif
608 closure->cif = cif;
609 closure->fun = fun;
610 closure->user_data = user_data;
612 __builtin___clear_cache(clear_location, clear_location + FFI_TRAMPOLINE_SIZE);
614 return FFI_OK;
618 * Decodes the arguments to a function, which will be stored on the
619 * stack. AR is the pointer to the beginning of the integer arguments
620 * (and, depending upon the arguments, some floating-point arguments
621 * as well). FPR is a pointer to the area where floating point
622 * registers have been saved, if any.
624 * RVALUE is the location where the function return value will be
625 * stored. CLOSURE is the prepared closure to invoke.
627 * This function should only be called from assembly, which is in
628 * turn called from a trampoline.
630 * Returns the function return type.
632 * Based on the similar routine for sparc.
635 ffi_closure_mips_inner_O32 (ffi_closure *closure,
636 void *rvalue, ffi_arg *ar,
637 double *fpr)
639 ffi_cif *cif;
640 void **avaluep;
641 ffi_arg *avalue;
642 ffi_type **arg_types;
643 int i, avn, argn, seen_int;
645 cif = closure->cif;
646 avalue = alloca (cif->nargs * sizeof (ffi_arg));
647 avaluep = alloca (cif->nargs * sizeof (ffi_arg));
649 seen_int = (cif->abi == FFI_O32_SOFT_FLOAT);
650 argn = 0;
652 if ((cif->flags >> (FFI_FLAG_BITS * 2)) == FFI_TYPE_STRUCT)
654 rvalue = (void *)(UINT32)ar[0];
655 argn = 1;
658 i = 0;
659 avn = cif->nargs;
660 arg_types = cif->arg_types;
662 while (i < avn)
664 if (i < 2 && !seen_int &&
665 (arg_types[i]->type == FFI_TYPE_FLOAT ||
666 arg_types[i]->type == FFI_TYPE_DOUBLE))
668 #ifdef __MIPSEB__
669 if (arg_types[i]->type == FFI_TYPE_FLOAT)
670 avaluep[i] = ((char *) &fpr[i]) + sizeof (float);
671 else
672 #endif
673 avaluep[i] = (char *) &fpr[i];
675 else
677 if (arg_types[i]->alignment == 8 && (argn & 0x1))
678 argn++;
679 switch (arg_types[i]->type)
681 case FFI_TYPE_SINT8:
682 avaluep[i] = &avalue[i];
683 *(SINT8 *) &avalue[i] = (SINT8) ar[argn];
684 break;
686 case FFI_TYPE_UINT8:
687 avaluep[i] = &avalue[i];
688 *(UINT8 *) &avalue[i] = (UINT8) ar[argn];
689 break;
691 case FFI_TYPE_SINT16:
692 avaluep[i] = &avalue[i];
693 *(SINT16 *) &avalue[i] = (SINT16) ar[argn];
694 break;
696 case FFI_TYPE_UINT16:
697 avaluep[i] = &avalue[i];
698 *(UINT16 *) &avalue[i] = (UINT16) ar[argn];
699 break;
701 default:
702 avaluep[i] = (char *) &ar[argn];
703 break;
705 seen_int = 1;
707 argn += ALIGN(arg_types[i]->size, FFI_SIZEOF_ARG) / FFI_SIZEOF_ARG;
708 i++;
711 /* Invoke the closure. */
712 (closure->fun) (cif, rvalue, avaluep, closure->user_data);
714 if (cif->abi == FFI_O32_SOFT_FLOAT)
716 switch (cif->rtype->type)
718 case FFI_TYPE_FLOAT:
719 return FFI_TYPE_INT;
720 case FFI_TYPE_DOUBLE:
721 return FFI_TYPE_UINT64;
722 default:
723 return cif->rtype->type;
726 else
728 return cif->rtype->type;
732 #if defined(FFI_MIPS_N32)
734 static void
735 copy_struct_N32(char *target, unsigned offset, ffi_abi abi, ffi_type *type,
736 int argn, unsigned arg_offset, ffi_arg *ar,
737 ffi_arg *fpr)
739 ffi_type **elt_typep = type->elements;
740 while(*elt_typep)
742 ffi_type *elt_type = *elt_typep;
743 unsigned o;
744 char *tp;
745 char *argp;
746 char *fpp;
748 o = ALIGN(offset, elt_type->alignment);
749 arg_offset += o - offset;
750 offset = o;
751 argn += arg_offset / sizeof(ffi_arg);
752 arg_offset = arg_offset % sizeof(ffi_arg);
754 argp = (char *)(ar + argn);
755 fpp = (char *)(argn >= 8 ? ar + argn : fpr + argn);
757 tp = target + offset;
759 if (elt_type->type == FFI_TYPE_DOUBLE)
760 *(double *)tp = *(double *)fpp;
761 else
762 memcpy(tp, argp + arg_offset, elt_type->size);
764 offset += elt_type->size;
765 arg_offset += elt_type->size;
766 elt_typep++;
767 argn += arg_offset / sizeof(ffi_arg);
768 arg_offset = arg_offset % sizeof(ffi_arg);
773 * Decodes the arguments to a function, which will be stored on the
774 * stack. AR is the pointer to the beginning of the integer
775 * arguments. FPR is a pointer to the area where floating point
776 * registers have been saved.
778 * RVALUE is the location where the function return value will be
779 * stored. CLOSURE is the prepared closure to invoke.
781 * This function should only be called from assembly, which is in
782 * turn called from a trampoline.
784 * Returns the function return flags.
788 ffi_closure_mips_inner_N32 (ffi_closure *closure,
789 void *rvalue, ffi_arg *ar,
790 ffi_arg *fpr)
792 ffi_cif *cif;
793 void **avaluep;
794 ffi_arg *avalue;
795 ffi_type **arg_types;
796 int i, avn, argn;
798 cif = closure->cif;
799 avalue = alloca (cif->nargs * sizeof (ffi_arg));
800 avaluep = alloca (cif->nargs * sizeof (ffi_arg));
802 argn = 0;
804 if (cif->rstruct_flag)
806 #if _MIPS_SIM==_ABIN32
807 rvalue = (void *)(UINT32)ar[0];
808 #else /* N64 */
809 rvalue = (void *)ar[0];
810 #endif
811 argn = 1;
814 i = 0;
815 avn = cif->nargs;
816 arg_types = cif->arg_types;
818 while (i < avn)
820 if (arg_types[i]->type == FFI_TYPE_FLOAT
821 || arg_types[i]->type == FFI_TYPE_DOUBLE)
823 ffi_arg *argp = argn >= 8 ? ar + argn : fpr + argn;
824 #ifdef __MIPSEB__
825 if (arg_types[i]->type == FFI_TYPE_FLOAT && argn < 8)
826 avaluep[i] = ((char *) argp) + sizeof (float);
827 else
828 #endif
829 avaluep[i] = (char *) argp;
831 else
833 unsigned type = arg_types[i]->type;
835 if (arg_types[i]->alignment > sizeof(ffi_arg))
836 argn = ALIGN(argn, arg_types[i]->alignment / sizeof(ffi_arg));
838 ffi_arg *argp = ar + argn;
840 /* The size of a pointer depends on the ABI */
841 if (type == FFI_TYPE_POINTER)
842 type = (cif->abi == FFI_N64) ? FFI_TYPE_SINT64 : FFI_TYPE_SINT32;
844 switch (type)
846 case FFI_TYPE_SINT8:
847 avaluep[i] = &avalue[i];
848 *(SINT8 *) &avalue[i] = (SINT8) *argp;
849 break;
851 case FFI_TYPE_UINT8:
852 avaluep[i] = &avalue[i];
853 *(UINT8 *) &avalue[i] = (UINT8) *argp;
854 break;
856 case FFI_TYPE_SINT16:
857 avaluep[i] = &avalue[i];
858 *(SINT16 *) &avalue[i] = (SINT16) *argp;
859 break;
861 case FFI_TYPE_UINT16:
862 avaluep[i] = &avalue[i];
863 *(UINT16 *) &avalue[i] = (UINT16) *argp;
864 break;
866 case FFI_TYPE_SINT32:
867 avaluep[i] = &avalue[i];
868 *(SINT32 *) &avalue[i] = (SINT32) *argp;
869 break;
871 case FFI_TYPE_UINT32:
872 avaluep[i] = &avalue[i];
873 *(UINT32 *) &avalue[i] = (UINT32) *argp;
874 break;
876 case FFI_TYPE_STRUCT:
877 if (argn < 8)
879 /* Allocate space for the struct as at least part of
880 it was passed in registers. */
881 avaluep[i] = alloca(arg_types[i]->size);
882 copy_struct_N32(avaluep[i], 0, cif->abi, arg_types[i],
883 argn, 0, ar, fpr);
885 break;
887 /* Else fall through. */
888 default:
889 avaluep[i] = (char *) argp;
890 break;
893 argn += ALIGN(arg_types[i]->size, sizeof(ffi_arg)) / sizeof(ffi_arg);
894 i++;
897 /* Invoke the closure. */
898 (closure->fun) (cif, rvalue, avaluep, closure->user_data);
900 return cif->flags >> (FFI_FLAG_BITS * 8);
903 #endif /* FFI_MIPS_N32 */
905 #endif /* FFI_CLOSURES */