]> git.ipfire.org Git - thirdparty/gcc.git/blame - libffi/src/mips/ffi.c
IRIX support
[thirdparty/gcc.git] / libffi / src / mips / ffi.c
CommitLineData
63e5e3e0 1/* -----------------------------------------------------------------------
7446546a
AH
2 ffi.c - Copyright (c) 1996, 2007, 2008 Red Hat, Inc.
3 Copyright (c) 2008 David Daney
63e5e3e0
AG
4
5 MIPS Foreign Function Interface
6
63e5e3e0
AG
7 Permission is hereby granted, free of charge, to any person obtaining
8 a copy of this software and associated documentation files (the
9 ``Software''), to deal in the Software without restriction, including
10 without limitation the rights to use, copy, modify, merge, publish,
11 distribute, sublicense, and/or sell copies of the Software, and to
12 permit persons to whom the Software is furnished to do so, subject to
13 the following conditions:
14
15 The above copyright notice and this permission notice shall be included
16 in all copies or substantial portions of the Software.
17
5f933ef0
AH
18 THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND,
19 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
21 NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
22 HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
23 WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
25 DEALINGS IN THE SOFTWARE.
63e5e3e0
AG
26 ----------------------------------------------------------------------- */
27
28#include <ffi.h>
29#include <ffi_common.h>
30
31#include <stdlib.h>
32
7446546a
AH
33#ifdef __GNUC__
34# if (__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 3))
35# define USE__BUILTIN___CLEAR_CACHE 1
36# endif
37#endif
38
39#ifndef USE__BUILTIN___CLEAR_CACHE
40#include <sys/cachectl.h>
41#endif
42
89d9d98a
DD
43#ifdef FFI_DEBUG
44# define FFI_MIPS_STOP_HERE() ffi_stop_here()
45#else
46# define FFI_MIPS_STOP_HERE() do {} while(0)
47#endif
48
49#ifdef FFI_MIPS_N32
63e5e3e0
AG
50#define FIX_ARGP \
51FFI_ASSERT(argp <= &stack[bytes]); \
52if (argp == &stack[bytes]) \
53{ \
54 argp = stack; \
89d9d98a 55 FFI_MIPS_STOP_HERE(); \
63e5e3e0
AG
56}
57#else
58#define FIX_ARGP
59#endif
60
61
62/* ffi_prep_args is called by the assembly routine once stack space
63 has been allocated for the function's arguments */
64
65static void ffi_prep_args(char *stack,
66 extended_cif *ecif,
67 int bytes,
68 int flags)
69{
8a39029d
TS
70 int i;
71 void **p_argv;
72 char *argp;
73 ffi_type **p_arg;
63e5e3e0 74
89d9d98a 75#ifdef FFI_MIPS_N32
63e5e3e0
AG
76 /* If more than 8 double words are used, the remainder go
77 on the stack. We reorder stuff on the stack here to
78 support this easily. */
8a39029d
TS
79 if (bytes > 8 * sizeof(ffi_arg))
80 argp = &stack[bytes - (8 * sizeof(ffi_arg))];
63e5e3e0
AG
81 else
82 argp = stack;
83#else
84 argp = stack;
85#endif
86
87 memset(stack, 0, bytes);
88
89d9d98a 89#ifdef FFI_MIPS_N32
63e5e3e0
AG
90 if ( ecif->cif->rstruct_flag != 0 )
91#else
92 if ( ecif->cif->rtype->type == FFI_TYPE_STRUCT )
93#endif
94 {
1450eb7a
AT
95 *(ffi_arg *) argp = (ffi_arg) ecif->rvalue;
96 argp += sizeof(ffi_arg);
63e5e3e0
AG
97 FIX_ARGP;
98 }
99
63e5e3e0
AG
100 p_argv = ecif->avalue;
101
5cbf8c8d 102 for (i = 0, p_arg = ecif->cif->arg_types; i < ecif->cif->nargs; i++, p_arg++)
63e5e3e0
AG
103 {
104 size_t z;
8a39029d 105 unsigned int a;
63e5e3e0 106
8a39029d 107 /* Align if necessary. */
39dca114 108 a = (*p_arg)->alignment;
8a39029d
TS
109 if (a < sizeof(ffi_arg))
110 a = sizeof(ffi_arg);
39dca114 111
89d9d98a 112 if ((a - 1) & (unsigned long) argp)
8a39029d
TS
113 {
114 argp = (char *) ALIGN(argp, a);
115 FIX_ARGP;
116 }
63e5e3e0 117
8a39029d
TS
118 z = (*p_arg)->size;
119 if (z <= sizeof(ffi_arg))
120 {
89d9d98a 121 int type = (*p_arg)->type;
8a39029d 122 z = sizeof(ffi_arg);
63e5e3e0 123
89d9d98a
DD
124 /* The size of a pointer depends on the ABI */
125 if (type == FFI_TYPE_POINTER)
5cbf8c8d
DD
126 type = (ecif->cif->abi == FFI_N64
127 || ecif->cif->abi == FFI_N64_SOFT_FLOAT)
128 ? FFI_TYPE_SINT64 : FFI_TYPE_SINT32;
89d9d98a 129
5cbf8c8d
DD
130 if (i < 8 && (ecif->cif->abi == FFI_N32_SOFT_FLOAT
131 || ecif->cif->abi == FFI_N64_SOFT_FLOAT))
132 {
133 switch (type)
134 {
135 case FFI_TYPE_FLOAT:
136 type = FFI_TYPE_UINT32;
137 break;
138 case FFI_TYPE_DOUBLE:
139 type = FFI_TYPE_UINT64;
140 break;
141 default:
142 break;
143 }
144 }
89d9d98a 145 switch (type)
63e5e3e0 146 {
8a39029d
TS
147 case FFI_TYPE_SINT8:
148 *(ffi_arg *)argp = *(SINT8 *)(* p_argv);
149 break;
63e5e3e0 150
8a39029d
TS
151 case FFI_TYPE_UINT8:
152 *(ffi_arg *)argp = *(UINT8 *)(* p_argv);
153 break;
63e5e3e0 154
8a39029d
TS
155 case FFI_TYPE_SINT16:
156 *(ffi_arg *)argp = *(SINT16 *)(* p_argv);
157 break;
63e5e3e0 158
8a39029d
TS
159 case FFI_TYPE_UINT16:
160 *(ffi_arg *)argp = *(UINT16 *)(* p_argv);
161 break;
63e5e3e0 162
8a39029d
TS
163 case FFI_TYPE_SINT32:
164 *(ffi_arg *)argp = *(SINT32 *)(* p_argv);
165 break;
63e5e3e0 166
8a39029d 167 case FFI_TYPE_UINT32:
8a39029d
TS
168 *(ffi_arg *)argp = *(UINT32 *)(* p_argv);
169 break;
170
171 /* This can only happen with 64bit slots. */
172 case FFI_TYPE_FLOAT:
173 *(float *) argp = *(float *)(* p_argv);
174 break;
175
89d9d98a 176 /* Handle structures. */
8a39029d
TS
177 default:
178 memcpy(argp, *p_argv, (*p_arg)->size);
179 break;
63e5e3e0 180 }
8a39029d
TS
181 }
182 else
183 {
89d9d98a 184#ifdef FFI_MIPS_O32
8a39029d 185 memcpy(argp, *p_argv, z);
63e5e3e0 186#else
8a39029d 187 {
89d9d98a
DD
188 unsigned long end = (unsigned long) argp + z;
189 unsigned long cap = (unsigned long) stack + bytes;
8a39029d
TS
190
191 /* Check if the data will fit within the register space.
192 Handle it if it doesn't. */
193
194 if (end <= cap)
195 memcpy(argp, *p_argv, z);
196 else
63e5e3e0 197 {
89d9d98a 198 unsigned long portion = cap - (unsigned long)argp;
8a39029d
TS
199
200 memcpy(argp, *p_argv, portion);
201 argp = stack;
89d9d98a
DD
202 z -= portion;
203 memcpy(argp, (void*)((unsigned long)(*p_argv) + portion),
204 z);
63e5e3e0 205 }
8a39029d 206 }
63e5e3e0 207#endif
8a39029d
TS
208 }
209 p_argv++;
210 argp += z;
211 FIX_ARGP;
63e5e3e0 212 }
63e5e3e0
AG
213}
214
89d9d98a 215#ifdef FFI_MIPS_N32
63e5e3e0
AG
216
217/* The n32 spec says that if "a chunk consists solely of a double
218 float field (but not a double, which is part of a union), it
219 is passed in a floating point register. Any other chunk is
220 passed in an integer register". This code traverses structure
221 definitions and generates the appropriate flags. */
222
89d9d98a 223static unsigned
5cbf8c8d
DD
224calc_n32_struct_flags(int soft_float, ffi_type *arg,
225 unsigned *loc, unsigned *arg_reg)
63e5e3e0
AG
226{
227 unsigned flags = 0;
228 unsigned index = 0;
229
230 ffi_type *e;
231
5cbf8c8d
DD
232 if (soft_float)
233 return 0;
234
89d9d98a 235 while ((e = arg->elements[index]))
63e5e3e0 236 {
89d9d98a
DD
237 /* Align this object. */
238 *loc = ALIGN(*loc, e->alignment);
63e5e3e0
AG
239 if (e->type == FFI_TYPE_DOUBLE)
240 {
89d9d98a
DD
241 /* Already aligned to FFI_SIZEOF_ARG. */
242 *arg_reg = *loc / FFI_SIZEOF_ARG;
243 if (*arg_reg > 7)
244 break;
245 flags += (FFI_TYPE_DOUBLE << (*arg_reg * FFI_FLAG_BITS));
246 *loc += e->size;
63e5e3e0 247 }
63e5e3e0 248 else
89d9d98a 249 *loc += e->size;
63e5e3e0
AG
250 index++;
251 }
89d9d98a
DD
252 /* Next Argument register at alignment of FFI_SIZEOF_ARG. */
253 *arg_reg = ALIGN(*loc, FFI_SIZEOF_ARG) / FFI_SIZEOF_ARG;
63e5e3e0
AG
254
255 return flags;
256}
257
89d9d98a 258static unsigned
5cbf8c8d 259calc_n32_return_struct_flags(int soft_float, ffi_type *arg)
63e5e3e0
AG
260{
261 unsigned flags = 0;
63e5e3e0
AG
262 unsigned small = FFI_TYPE_SMALLSTRUCT;
263 ffi_type *e;
264
265 /* Returning structures under n32 is a tricky thing.
266 A struct with only one or two floating point fields
267 is returned in $f0 (and $f2 if necessary). Any other
268 struct results at most 128 bits are returned in $2
269 (the first 64 bits) and $3 (remainder, if necessary).
270 Larger structs are handled normally. */
271
272 if (arg->size > 16)
273 return 0;
274
275 if (arg->size > 8)
276 small = FFI_TYPE_SMALLSTRUCT2;
277
278 e = arg->elements[0];
5cbf8c8d 279
63e5e3e0 280 if (e->type == FFI_TYPE_DOUBLE)
89d9d98a 281 flags = FFI_TYPE_DOUBLE;
63e5e3e0 282 else if (e->type == FFI_TYPE_FLOAT)
89d9d98a 283 flags = FFI_TYPE_FLOAT;
63e5e3e0
AG
284
285 if (flags && (e = arg->elements[1]))
286 {
287 if (e->type == FFI_TYPE_DOUBLE)
89d9d98a 288 flags += FFI_TYPE_DOUBLE << FFI_FLAG_BITS;
63e5e3e0 289 else if (e->type == FFI_TYPE_FLOAT)
89d9d98a 290 flags += FFI_TYPE_FLOAT << FFI_FLAG_BITS;
63e5e3e0
AG
291 else
292 return small;
293
294 if (flags && (arg->elements[2]))
295 {
296 /* There are three arguments and the first two are
297 floats! This must be passed the old way. */
298 return small;
299 }
5cbf8c8d
DD
300 if (soft_float)
301 flags += FFI_TYPE_STRUCT_SOFT;
63e5e3e0
AG
302 }
303 else
304 if (!flags)
305 return small;
306
307 return flags;
308}
309
310#endif
311
312/* Perform machine dependent cif processing */
313ffi_status ffi_prep_cif_machdep(ffi_cif *cif)
314{
315 cif->flags = 0;
316
89d9d98a 317#ifdef FFI_MIPS_O32
39dca114
DD
318 /* Set the flags necessary for O32 processing. FFI_O32_SOFT_FLOAT
319 * does not have special handling for floating point args.
320 */
63e5e3e0 321
39dca114 322 if (cif->rtype->type != FFI_TYPE_STRUCT && cif->abi == FFI_O32)
63e5e3e0
AG
323 {
324 if (cif->nargs > 0)
325 {
326 switch ((cif->arg_types)[0]->type)
327 {
328 case FFI_TYPE_FLOAT:
329 case FFI_TYPE_DOUBLE:
330 cif->flags += (cif->arg_types)[0]->type;
331 break;
332
333 default:
334 break;
335 }
336
337 if (cif->nargs > 1)
338 {
339 /* Only handle the second argument if the first
340 is a float or double. */
341 if (cif->flags)
342 {
343 switch ((cif->arg_types)[1]->type)
344 {
345 case FFI_TYPE_FLOAT:
346 case FFI_TYPE_DOUBLE:
347 cif->flags += (cif->arg_types)[1]->type << FFI_FLAG_BITS;
348 break;
349
350 default:
351 break;
352 }
353 }
354 }
355 }
356 }
357
358 /* Set the return type flag */
b790003a 359
39dca114
DD
360 if (cif->abi == FFI_O32_SOFT_FLOAT)
361 {
362 switch (cif->rtype->type)
363 {
364 case FFI_TYPE_VOID:
365 case FFI_TYPE_STRUCT:
366 cif->flags += cif->rtype->type << (FFI_FLAG_BITS * 2);
367 break;
368
369 case FFI_TYPE_SINT64:
370 case FFI_TYPE_UINT64:
371 case FFI_TYPE_DOUBLE:
372 cif->flags += FFI_TYPE_UINT64 << (FFI_FLAG_BITS * 2);
373 break;
63e5e3e0 374
39dca114
DD
375 case FFI_TYPE_FLOAT:
376 default:
377 cif->flags += FFI_TYPE_INT << (FFI_FLAG_BITS * 2);
378 break;
379 }
380 }
381 else
382 {
383 /* FFI_O32 */
384 switch (cif->rtype->type)
385 {
386 case FFI_TYPE_VOID:
387 case FFI_TYPE_STRUCT:
388 case FFI_TYPE_FLOAT:
389 case FFI_TYPE_DOUBLE:
390 cif->flags += cif->rtype->type << (FFI_FLAG_BITS * 2);
391 break;
392
393 case FFI_TYPE_SINT64:
394 case FFI_TYPE_UINT64:
395 cif->flags += FFI_TYPE_UINT64 << (FFI_FLAG_BITS * 2);
396 break;
397
398 default:
399 cif->flags += FFI_TYPE_INT << (FFI_FLAG_BITS * 2);
400 break;
401 }
63e5e3e0
AG
402 }
403#endif
404
89d9d98a 405#ifdef FFI_MIPS_N32
63e5e3e0
AG
406 /* Set the flags necessary for N32 processing */
407 {
5cbf8c8d 408 int type;
89d9d98a
DD
409 unsigned arg_reg = 0;
410 unsigned loc = 0;
63e5e3e0
AG
411 unsigned count = (cif->nargs < 8) ? cif->nargs : 8;
412 unsigned index = 0;
413
414 unsigned struct_flags = 0;
5cbf8c8d
DD
415 int soft_float = (cif->abi == FFI_N32_SOFT_FLOAT
416 || cif->abi == FFI_N64_SOFT_FLOAT);
63e5e3e0
AG
417
418 if (cif->rtype->type == FFI_TYPE_STRUCT)
419 {
5cbf8c8d 420 struct_flags = calc_n32_return_struct_flags(soft_float, cif->rtype);
63e5e3e0
AG
421
422 if (struct_flags == 0)
423 {
424 /* This means that the structure is being passed as
425 a hidden argument */
426
89d9d98a 427 arg_reg = 1;
63e5e3e0
AG
428 count = (cif->nargs < 7) ? cif->nargs : 7;
429
430 cif->rstruct_flag = !0;
431 }
432 else
433 cif->rstruct_flag = 0;
434 }
435 else
436 cif->rstruct_flag = 0;
437
89d9d98a 438 while (count-- > 0 && arg_reg < 8)
63e5e3e0 439 {
5cbf8c8d
DD
440 type = (cif->arg_types)[index]->type;
441 if (soft_float)
442 {
443 switch (type)
444 {
445 case FFI_TYPE_FLOAT:
446 type = FFI_TYPE_UINT32;
447 break;
448 case FFI_TYPE_DOUBLE:
449 type = FFI_TYPE_UINT64;
450 break;
451 default:
452 break;
453 }
454 }
455 switch (type)
63e5e3e0
AG
456 {
457 case FFI_TYPE_FLOAT:
458 case FFI_TYPE_DOUBLE:
89d9d98a
DD
459 cif->flags +=
460 ((cif->arg_types)[index]->type << (arg_reg * FFI_FLAG_BITS));
461 arg_reg++;
63e5e3e0 462 break;
89d9d98a
DD
463 case FFI_TYPE_LONGDOUBLE:
464 /* Align it. */
465 arg_reg = ALIGN(arg_reg, 2);
466 /* Treat it as two adjacent doubles. */
5cbf8c8d
DD
467 if (soft_float)
468 {
469 arg_reg += 2;
470 }
471 else
472 {
473 cif->flags +=
474 (FFI_TYPE_DOUBLE << (arg_reg * FFI_FLAG_BITS));
475 arg_reg++;
476 cif->flags +=
477 (FFI_TYPE_DOUBLE << (arg_reg * FFI_FLAG_BITS));
478 arg_reg++;
479 }
89d9d98a 480 break;
63e5e3e0
AG
481
482 case FFI_TYPE_STRUCT:
89d9d98a 483 loc = arg_reg * FFI_SIZEOF_ARG;
5cbf8c8d
DD
484 cif->flags += calc_n32_struct_flags(soft_float,
485 (cif->arg_types)[index],
89d9d98a 486 &loc, &arg_reg);
63e5e3e0
AG
487 break;
488
489 default:
89d9d98a
DD
490 arg_reg++;
491 break;
63e5e3e0
AG
492 }
493
494 index++;
495 }
496
497 /* Set the return type flag */
498 switch (cif->rtype->type)
499 {
500 case FFI_TYPE_STRUCT:
501 {
502 if (struct_flags == 0)
503 {
504 /* The structure is returned through a hidden
505 first argument. Do nothing, 'cause FFI_TYPE_VOID
506 is 0 */
507 }
508 else
509 {
510 /* The structure is returned via some tricky
511 mechanism */
512 cif->flags += FFI_TYPE_STRUCT << (FFI_FLAG_BITS * 8);
513 cif->flags += struct_flags << (4 + (FFI_FLAG_BITS * 8));
514 }
515 break;
516 }
517
518 case FFI_TYPE_VOID:
519 /* Do nothing, 'cause FFI_TYPE_VOID is 0 */
520 break;
5cbf8c8d
DD
521
522 case FFI_TYPE_POINTER:
523 if (cif->abi == FFI_N32_SOFT_FLOAT || cif->abi == FFI_N32)
524 cif->flags += FFI_TYPE_SINT32 << (FFI_FLAG_BITS * 8);
525 else
526 cif->flags += FFI_TYPE_INT << (FFI_FLAG_BITS * 8);
527 break;
528
63e5e3e0 529 case FFI_TYPE_FLOAT:
5cbf8c8d
DD
530 if (soft_float)
531 {
532 cif->flags += FFI_TYPE_SINT32 << (FFI_FLAG_BITS * 8);
533 break;
534 }
535 /* else fall through */
63e5e3e0 536 case FFI_TYPE_DOUBLE:
5cbf8c8d
DD
537 if (soft_float)
538 cif->flags += FFI_TYPE_INT << (FFI_FLAG_BITS * 8);
539 else
540 cif->flags += cif->rtype->type << (FFI_FLAG_BITS * 8);
63e5e3e0 541 break;
5cbf8c8d 542
3875b6d7
DD
543 case FFI_TYPE_LONGDOUBLE:
544 /* Long double is returned as if it were a struct containing
545 two doubles. */
5cbf8c8d
DD
546 if (soft_float)
547 {
548 cif->flags += FFI_TYPE_STRUCT << (FFI_FLAG_BITS * 8);
549 cif->flags += FFI_TYPE_SMALLSTRUCT2 << (4 + (FFI_FLAG_BITS * 8));
550 }
551 else
552 {
553 cif->flags += FFI_TYPE_STRUCT << (FFI_FLAG_BITS * 8);
554 cif->flags += (FFI_TYPE_DOUBLE
555 + (FFI_TYPE_DOUBLE << FFI_FLAG_BITS))
556 << (4 + (FFI_FLAG_BITS * 8));
557 }
3875b6d7 558 break;
63e5e3e0
AG
559 default:
560 cif->flags += FFI_TYPE_INT << (FFI_FLAG_BITS * 8);
561 break;
562 }
563 }
564#endif
565
566 return FFI_OK;
567}
568
569/* Low level routine for calling O32 functions */
570extern int ffi_call_O32(void (*)(char *, extended_cif *, int, int),
571 extended_cif *, unsigned,
7446546a 572 unsigned, unsigned *, void (*)(void));
63e5e3e0
AG
573
574/* Low level routine for calling N32 functions */
575extern int ffi_call_N32(void (*)(char *, extended_cif *, int, int),
576 extended_cif *, unsigned,
5cbf8c8d 577 unsigned, void *, void (*)(void));
63e5e3e0 578
7446546a 579void ffi_call(ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue)
63e5e3e0
AG
580{
581 extended_cif ecif;
582
583 ecif.cif = cif;
584 ecif.avalue = avalue;
585
586 /* If the return value is a struct and we don't have a return */
587 /* value address then we need to make one */
588
589 if ((rvalue == NULL) &&
590 (cif->rtype->type == FFI_TYPE_STRUCT))
591 ecif.rvalue = alloca(cif->rtype->size);
592 else
593 ecif.rvalue = rvalue;
594
595 switch (cif->abi)
596 {
89d9d98a 597#ifdef FFI_MIPS_O32
63e5e3e0 598 case FFI_O32:
39dca114 599 case FFI_O32_SOFT_FLOAT:
63e5e3e0
AG
600 ffi_call_O32(ffi_prep_args, &ecif, cif->bytes,
601 cif->flags, ecif.rvalue, fn);
602 break;
603#endif
604
89d9d98a 605#ifdef FFI_MIPS_N32
63e5e3e0 606 case FFI_N32:
5cbf8c8d 607 case FFI_N32_SOFT_FLOAT:
89d9d98a 608 case FFI_N64:
5cbf8c8d 609 case FFI_N64_SOFT_FLOAT:
89d9d98a
DD
610 {
611 int copy_rvalue = 0;
5cbf8c8d
DD
612 int copy_offset = 0;
613 char *rvalue_copy = ecif.rvalue;
89d9d98a
DD
614 if (cif->rtype->type == FFI_TYPE_STRUCT && cif->rtype->size < 16)
615 {
616 /* For structures smaller than 16 bytes we clobber memory
617 in 8 byte increments. Make a copy so we don't clobber
618 the callers memory outside of the struct bounds. */
619 rvalue_copy = alloca(16);
620 copy_rvalue = 1;
621 }
5cbf8c8d
DD
622 else if (cif->rtype->type == FFI_TYPE_FLOAT
623 && (cif->abi == FFI_N64_SOFT_FLOAT
624 || cif->abi == FFI_N32_SOFT_FLOAT))
625 {
626 rvalue_copy = alloca (8);
627 copy_rvalue = 1;
c4205f77 628#if defined(__MIPSEB__) || defined(_MIPSEB)
5cbf8c8d
DD
629 copy_offset = 4;
630#endif
631 }
89d9d98a
DD
632 ffi_call_N32(ffi_prep_args, &ecif, cif->bytes,
633 cif->flags, rvalue_copy, fn);
634 if (copy_rvalue)
5cbf8c8d 635 memcpy(ecif.rvalue, rvalue_copy + copy_offset, cif->rtype->size);
89d9d98a 636 }
63e5e3e0
AG
637 break;
638#endif
639
640 default:
641 FFI_ASSERT(0);
642 break;
643 }
644}
b790003a 645
89d9d98a 646#if FFI_CLOSURES
b790003a
CM
647#if defined(FFI_MIPS_O32)
648extern void ffi_closure_O32(void);
89d9d98a
DD
649#else
650extern void ffi_closure_N32(void);
b790003a
CM
651#endif /* FFI_MIPS_O32 */
652
653ffi_status
18fa3240
AO
654ffi_prep_closure_loc (ffi_closure *closure,
655 ffi_cif *cif,
656 void (*fun)(ffi_cif*,void*,void**,void*),
657 void *user_data,
658 void *codeloc)
b790003a
CM
659{
660 unsigned int *tramp = (unsigned int *) &closure->tramp[0];
89d9d98a 661 void * fn;
433e6a8c 662 char *clear_location = (char *) codeloc;
b790003a
CM
663
664#if defined(FFI_MIPS_O32)
39dca114 665 FFI_ASSERT(cif->abi == FFI_O32 || cif->abi == FFI_O32_SOFT_FLOAT);
89d9d98a 666 fn = ffi_closure_O32;
b790003a 667#else /* FFI_MIPS_N32 */
89d9d98a
DD
668 FFI_ASSERT(cif->abi == FFI_N32 || cif->abi == FFI_N64);
669 fn = ffi_closure_N32;
b790003a
CM
670#endif /* FFI_MIPS_O32 */
671
89d9d98a
DD
672#if defined(FFI_MIPS_O32) || (_MIPS_SIM ==_ABIN32)
673 /* lui $25,high(fn) */
674 tramp[0] = 0x3c190000 | ((unsigned)fn >> 16);
675 /* ori $25,low(fn) */
676 tramp[1] = 0x37390000 | ((unsigned)fn & 0xffff);
677 /* lui $12,high(codeloc) */
678 tramp[2] = 0x3c0c0000 | ((unsigned)codeloc >> 16);
679 /* jr $25 */
680 tramp[3] = 0x03200008;
681 /* ori $12,low(codeloc) */
682 tramp[4] = 0x358c0000 | ((unsigned)codeloc & 0xffff);
683#else
684 /* N64 has a somewhat larger trampoline. */
685 /* lui $25,high(fn) */
686 tramp[0] = 0x3c190000 | ((unsigned long)fn >> 48);
687 /* lui $12,high(codeloc) */
688 tramp[1] = 0x3c0c0000 | ((unsigned long)codeloc >> 48);
689 /* ori $25,mid-high(fn) */
690 tramp[2] = 0x37390000 | (((unsigned long)fn >> 32 ) & 0xffff);
691 /* ori $12,mid-high(codeloc) */
692 tramp[3] = 0x358c0000 | (((unsigned long)codeloc >> 32) & 0xffff);
693 /* dsll $25,$25,16 */
694 tramp[4] = 0x0019cc38;
695 /* dsll $12,$12,16 */
696 tramp[5] = 0x000c6438;
697 /* ori $25,mid-low(fn) */
698 tramp[6] = 0x37390000 | (((unsigned long)fn >> 16 ) & 0xffff);
699 /* ori $12,mid-low(codeloc) */
700 tramp[7] = 0x358c0000 | (((unsigned long)codeloc >> 16) & 0xffff);
701 /* dsll $25,$25,16 */
702 tramp[8] = 0x0019cc38;
703 /* dsll $12,$12,16 */
704 tramp[9] = 0x000c6438;
705 /* ori $25,low(fn) */
706 tramp[10] = 0x37390000 | ((unsigned long)fn & 0xffff);
707 /* jr $25 */
708 tramp[11] = 0x03200008;
709 /* ori $12,low(codeloc) */
710 tramp[12] = 0x358c0000 | ((unsigned long)codeloc & 0xffff);
711
712#endif
b790003a
CM
713
714 closure->cif = cif;
715 closure->fun = fun;
716 closure->user_data = user_data;
717
7446546a 718#ifdef USE__BUILTIN___CLEAR_CACHE
433e6a8c 719 __builtin___clear_cache(clear_location, clear_location + FFI_TRAMPOLINE_SIZE);
7446546a
AH
720#else
721 cacheflush (clear_location, FFI_TRAMPOLINE_SIZE, ICACHE);
722#endif
b790003a
CM
723 return FFI_OK;
724}
725
726/*
727 * Decodes the arguments to a function, which will be stored on the
728 * stack. AR is the pointer to the beginning of the integer arguments
729 * (and, depending upon the arguments, some floating-point arguments
730 * as well). FPR is a pointer to the area where floating point
731 * registers have been saved, if any.
732 *
733 * RVALUE is the location where the function return value will be
734 * stored. CLOSURE is the prepared closure to invoke.
735 *
736 * This function should only be called from assembly, which is in
737 * turn called from a trampoline.
738 *
739 * Returns the function return type.
740 *
741 * Based on the similar routine for sparc.
742 */
743int
744ffi_closure_mips_inner_O32 (ffi_closure *closure,
8a39029d 745 void *rvalue, ffi_arg *ar,
b790003a
CM
746 double *fpr)
747{
748 ffi_cif *cif;
8a39029d
TS
749 void **avaluep;
750 ffi_arg *avalue;
b790003a
CM
751 ffi_type **arg_types;
752 int i, avn, argn, seen_int;
753
754 cif = closure->cif;
8a39029d
TS
755 avalue = alloca (cif->nargs * sizeof (ffi_arg));
756 avaluep = alloca (cif->nargs * sizeof (ffi_arg));
b790003a 757
39dca114 758 seen_int = (cif->abi == FFI_O32_SOFT_FLOAT);
b790003a
CM
759 argn = 0;
760
39dca114 761 if ((cif->flags >> (FFI_FLAG_BITS * 2)) == FFI_TYPE_STRUCT)
b790003a 762 {
89d9d98a 763 rvalue = (void *)(UINT32)ar[0];
b790003a
CM
764 argn = 1;
765 }
766
767 i = 0;
768 avn = cif->nargs;
769 arg_types = cif->arg_types;
770
771 while (i < avn)
772 {
773 if (i < 2 && !seen_int &&
774 (arg_types[i]->type == FFI_TYPE_FLOAT ||
c4205f77
FE
775 arg_types[i]->type == FFI_TYPE_DOUBLE ||
776 arg_types[i]->type == FFI_TYPE_LONGDOUBLE))
b790003a 777 {
c4205f77 778#if defined(__MIPSEB__) || defined(_MIPSEB)
8a39029d
TS
779 if (arg_types[i]->type == FFI_TYPE_FLOAT)
780 avaluep[i] = ((char *) &fpr[i]) + sizeof (float);
781 else
782#endif
783 avaluep[i] = (char *) &fpr[i];
b790003a
CM
784 }
785 else
786 {
39dca114 787 if (arg_types[i]->alignment == 8 && (argn & 0x1))
b790003a 788 argn++;
8a39029d
TS
789 switch (arg_types[i]->type)
790 {
791 case FFI_TYPE_SINT8:
792 avaluep[i] = &avalue[i];
793 *(SINT8 *) &avalue[i] = (SINT8) ar[argn];
794 break;
795
796 case FFI_TYPE_UINT8:
797 avaluep[i] = &avalue[i];
798 *(UINT8 *) &avalue[i] = (UINT8) ar[argn];
799 break;
800
801 case FFI_TYPE_SINT16:
802 avaluep[i] = &avalue[i];
803 *(SINT16 *) &avalue[i] = (SINT16) ar[argn];
804 break;
805
806 case FFI_TYPE_UINT16:
807 avaluep[i] = &avalue[i];
808 *(UINT16 *) &avalue[i] = (UINT16) ar[argn];
809 break;
810
811 default:
812 avaluep[i] = (char *) &ar[argn];
813 break;
814 }
b790003a
CM
815 seen_int = 1;
816 }
817 argn += ALIGN(arg_types[i]->size, FFI_SIZEOF_ARG) / FFI_SIZEOF_ARG;
818 i++;
819 }
820
821 /* Invoke the closure. */
8a39029d 822 (closure->fun) (cif, rvalue, avaluep, closure->user_data);
b790003a 823
39dca114
DD
824 if (cif->abi == FFI_O32_SOFT_FLOAT)
825 {
826 switch (cif->rtype->type)
827 {
828 case FFI_TYPE_FLOAT:
829 return FFI_TYPE_INT;
830 case FFI_TYPE_DOUBLE:
831 return FFI_TYPE_UINT64;
832 default:
833 return cif->rtype->type;
834 }
835 }
836 else
837 {
838 return cif->rtype->type;
839 }
b790003a
CM
840}
841
89d9d98a
DD
842#if defined(FFI_MIPS_N32)
843
844static void
845copy_struct_N32(char *target, unsigned offset, ffi_abi abi, ffi_type *type,
846 int argn, unsigned arg_offset, ffi_arg *ar,
5cbf8c8d 847 ffi_arg *fpr, int soft_float)
89d9d98a
DD
848{
849 ffi_type **elt_typep = type->elements;
850 while(*elt_typep)
851 {
852 ffi_type *elt_type = *elt_typep;
853 unsigned o;
854 char *tp;
855 char *argp;
856 char *fpp;
857
858 o = ALIGN(offset, elt_type->alignment);
859 arg_offset += o - offset;
860 offset = o;
861 argn += arg_offset / sizeof(ffi_arg);
862 arg_offset = arg_offset % sizeof(ffi_arg);
863
864 argp = (char *)(ar + argn);
865 fpp = (char *)(argn >= 8 ? ar + argn : fpr + argn);
866
867 tp = target + offset;
868
5cbf8c8d 869 if (elt_type->type == FFI_TYPE_DOUBLE && !soft_float)
89d9d98a
DD
870 *(double *)tp = *(double *)fpp;
871 else
872 memcpy(tp, argp + arg_offset, elt_type->size);
873
874 offset += elt_type->size;
875 arg_offset += elt_type->size;
876 elt_typep++;
877 argn += arg_offset / sizeof(ffi_arg);
878 arg_offset = arg_offset % sizeof(ffi_arg);
879 }
880}
881
882/*
883 * Decodes the arguments to a function, which will be stored on the
884 * stack. AR is the pointer to the beginning of the integer
885 * arguments. FPR is a pointer to the area where floating point
886 * registers have been saved.
887 *
888 * RVALUE is the location where the function return value will be
889 * stored. CLOSURE is the prepared closure to invoke.
890 *
891 * This function should only be called from assembly, which is in
892 * turn called from a trampoline.
893 *
894 * Returns the function return flags.
895 *
896 */
897int
898ffi_closure_mips_inner_N32 (ffi_closure *closure,
899 void *rvalue, ffi_arg *ar,
900 ffi_arg *fpr)
901{
902 ffi_cif *cif;
903 void **avaluep;
904 ffi_arg *avalue;
905 ffi_type **arg_types;
906 int i, avn, argn;
5cbf8c8d
DD
907 int soft_float;
908 ffi_arg *argp;
89d9d98a
DD
909
910 cif = closure->cif;
5cbf8c8d
DD
911 soft_float = cif->abi == FFI_N64_SOFT_FLOAT
912 || cif->abi == FFI_N32_SOFT_FLOAT;
89d9d98a
DD
913 avalue = alloca (cif->nargs * sizeof (ffi_arg));
914 avaluep = alloca (cif->nargs * sizeof (ffi_arg));
915
916 argn = 0;
917
918 if (cif->rstruct_flag)
919 {
920#if _MIPS_SIM==_ABIN32
921 rvalue = (void *)(UINT32)ar[0];
922#else /* N64 */
923 rvalue = (void *)ar[0];
924#endif
925 argn = 1;
926 }
927
928 i = 0;
929 avn = cif->nargs;
930 arg_types = cif->arg_types;
931
932 while (i < avn)
933 {
934 if (arg_types[i]->type == FFI_TYPE_FLOAT
c4205f77
FE
935 || arg_types[i]->type == FFI_TYPE_DOUBLE
936 || arg_types[i]->type == FFI_TYPE_LONGDOUBLE)
89d9d98a 937 {
5cbf8c8d 938 argp = (argn >= 8 || soft_float) ? ar + argn : fpr + argn;
c4205f77
FE
939 if ((arg_types[i]->type == FFI_TYPE_LONGDOUBLE) && ((unsigned)argp & (arg_types[i]->alignment-1)))
940 {
941 argp=(ffi_arg*)ALIGN(argp,arg_types[i]->alignment);
942 argn++;
943 }
944#if defined(__MIPSEB__) || defined(_MIPSEB)
89d9d98a
DD
945 if (arg_types[i]->type == FFI_TYPE_FLOAT && argn < 8)
946 avaluep[i] = ((char *) argp) + sizeof (float);
947 else
948#endif
949 avaluep[i] = (char *) argp;
950 }
951 else
952 {
953 unsigned type = arg_types[i]->type;
954
955 if (arg_types[i]->alignment > sizeof(ffi_arg))
956 argn = ALIGN(argn, arg_types[i]->alignment / sizeof(ffi_arg));
957
5cbf8c8d 958 argp = ar + argn;
89d9d98a
DD
959
960 /* The size of a pointer depends on the ABI */
961 if (type == FFI_TYPE_POINTER)
5cbf8c8d
DD
962 type = (cif->abi == FFI_N64 || cif->abi == FFI_N64_SOFT_FLOAT)
963 ? FFI_TYPE_SINT64 : FFI_TYPE_SINT32;
964
965 if (soft_float && type == FFI_TYPE_FLOAT)
966 type = FFI_TYPE_UINT32;
89d9d98a
DD
967
968 switch (type)
969 {
970 case FFI_TYPE_SINT8:
971 avaluep[i] = &avalue[i];
972 *(SINT8 *) &avalue[i] = (SINT8) *argp;
973 break;
974
975 case FFI_TYPE_UINT8:
976 avaluep[i] = &avalue[i];
977 *(UINT8 *) &avalue[i] = (UINT8) *argp;
978 break;
979
980 case FFI_TYPE_SINT16:
981 avaluep[i] = &avalue[i];
982 *(SINT16 *) &avalue[i] = (SINT16) *argp;
983 break;
984
985 case FFI_TYPE_UINT16:
986 avaluep[i] = &avalue[i];
987 *(UINT16 *) &avalue[i] = (UINT16) *argp;
988 break;
989
990 case FFI_TYPE_SINT32:
991 avaluep[i] = &avalue[i];
992 *(SINT32 *) &avalue[i] = (SINT32) *argp;
993 break;
994
995 case FFI_TYPE_UINT32:
996 avaluep[i] = &avalue[i];
997 *(UINT32 *) &avalue[i] = (UINT32) *argp;
998 break;
999
1000 case FFI_TYPE_STRUCT:
1001 if (argn < 8)
1002 {
1003 /* Allocate space for the struct as at least part of
1004 it was passed in registers. */
1005 avaluep[i] = alloca(arg_types[i]->size);
1006 copy_struct_N32(avaluep[i], 0, cif->abi, arg_types[i],
5cbf8c8d 1007 argn, 0, ar, fpr, soft_float);
89d9d98a
DD
1008
1009 break;
1010 }
1011 /* Else fall through. */
1012 default:
1013 avaluep[i] = (char *) argp;
1014 break;
1015 }
1016 }
1017 argn += ALIGN(arg_types[i]->size, sizeof(ffi_arg)) / sizeof(ffi_arg);
1018 i++;
1019 }
1020
1021 /* Invoke the closure. */
1022 (closure->fun) (cif, rvalue, avaluep, closure->user_data);
1023
1024 return cif->flags >> (FFI_FLAG_BITS * 8);
1025}
1026
1027#endif /* FFI_MIPS_N32 */
1028
b790003a 1029#endif /* FFI_CLOSURES */