Ruby: ext/fiddle/libffi-3.2.1/src/mips/ffi.c Source File

Ruby 3.0.5p211 (2022-11-24 revision ba5cf0f7c52d4d35cc6a173c89eda98ceffa2dcf)

ffi.c
Go to the documentation of this file.
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.
5
6 MIPS Foreign Function Interface
7
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:
15
16 The above copyright notice and this permission notice shall be included
17 in all copies or substantial portions of the Software.
18
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 ----------------------------------------------------------------------- */
28
29#include <ffi.h>
30#include <ffi_common.h>
31
32#include <stdlib.h>
33
34#ifdef __GNUC__
35# if (__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 3))
36# define USE__BUILTIN___CLEAR_CACHE 1
37# endif
38#endif
39
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
47
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
53
54#ifdef FFI_MIPS_N32
55#define FIX_ARGP \
56FFI_ASSERT(argp <= &stack[bytes]); \
57if (argp == &stack[bytes]) \
58{ \
59 argp = stack; \
60 FFI_MIPS_STOP_HERE(); \
61}
62#else
63#define FIX_ARGP
64#endif
65
66
67/* ffi_prep_args is called by the assembly routine once stack space
68 has been allocated for the function's arguments */
69
70static void ffi_prep_args(char *stack,
71 extended_cif *ecif,
72 int bytes,
73 int flags)
74{
75 int i;
76 void **p_argv;
77 char *argp;
78 ffi_type **p_arg;
79
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
91
92 memset(stack, 0, bytes);
93
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
99 {
100 *(ffi_arg *) argp = (ffi_arg) ecif->rvalue;
101 argp += sizeof(ffi_arg);
102 FIX_ARGP;
103 }
104
105 p_argv = ecif->avalue;
106
107 for (i = 0, p_arg = ecif->cif->arg_types; i < ecif->cif->nargs; i++, p_arg++)
108 {
109 size_t z;
110 unsigned int a;
111
112 /* Align if necessary. */
113 a = (*p_arg)->alignment;
114 if (a < sizeof(ffi_arg))
115 a = sizeof(ffi_arg);
116
117 if ((a - 1) & (unsigned long) argp)
118 {
119 argp = (char *) ALIGN(argp, a);
120 FIX_ARGP;
121 }
122
123 z = (*p_arg)->size;
124 if (z <= sizeof(ffi_arg))
125 {
126 int type = (*p_arg)->type;
127 z = sizeof(ffi_arg);
128
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;
134
135 if (i < 8 && (ecif->cif->abi == FFI_N32_SOFT_FLOAT
136 || ecif->cif->abi == FFI_N64_SOFT_FLOAT))
137 {
138 switch (type)
139 {
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;
148 }
149 }
150 switch (type)
151 {
152 case FFI_TYPE_SINT8:
153 *(ffi_arg *)argp = *(SINT8 *)(* p_argv);
154 break;
155
156 case FFI_TYPE_UINT8:
157 *(ffi_arg *)argp = *(UINT8 *)(* p_argv);
158 break;
159
160 case FFI_TYPE_SINT16:
161 *(ffi_arg *)argp = *(SINT16 *)(* p_argv);
162 break;
163
164 case FFI_TYPE_UINT16:
165 *(ffi_arg *)argp = *(UINT16 *)(* p_argv);
166 break;
167
168 case FFI_TYPE_SINT32:
169 *(ffi_arg *)argp = *(SINT32 *)(* p_argv);
170 break;
171
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;
182
183 /* This can only happen with 64bit slots. */
184 case FFI_TYPE_FLOAT:
185 *(float *) argp = *(float *)(* p_argv);
186 break;
187
188 /* Handle structures. */
189 default:
190 memcpy(argp, *p_argv, (*p_arg)->size);
191 break;
192 }
193 }
194 else
195 {
196#ifdef FFI_MIPS_O32
197 memcpy(argp, *p_argv, z);
198#else
199 {
200 unsigned long end = (unsigned long) argp + z;
201 unsigned long cap = (unsigned long) stack + bytes;
202
203 /* Check if the data will fit within the register space.
204 Handle it if it doesn't. */
205
206 if (end <= cap)
207 memcpy(argp, *p_argv, z);
208 else
209 {
210 unsigned long portion = cap - (unsigned long)argp;
211
212 memcpy(argp, *p_argv, portion);
213 argp = stack;
214 z -= portion;
215 memcpy(argp, (void*)((unsigned long)(*p_argv) + portion),
216 z);
217 }
218 }
219#endif
220 }
221 p_argv++;
222 argp += z;
223 FIX_ARGP;
224 }
225}
226
227#ifdef FFI_MIPS_N32
228
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. */
234
235static unsigned
236calc_n32_struct_flags(int soft_float, ffi_type *arg,
237 unsigned *loc, unsigned *arg_reg)
238{
239 unsigned flags = 0;
240 unsigned index = 0;
241
242 ffi_type *e;
243
244 if (soft_float)
245 return 0;
246
247 while ((e = arg->elements[index]))
248 {
249 /* Align this object. */
250 *loc = ALIGN(*loc, e->alignment);
251 if (e->type == FFI_TYPE_DOUBLE)
252 {
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;
259 }
260 else
261 *loc += e->size;
262 index++;
263 }
264 /* Next Argument register at alignment of FFI_SIZEOF_ARG. */
265 *arg_reg = ALIGN(*loc, FFI_SIZEOF_ARG) / FFI_SIZEOF_ARG;
266
267 return flags;
268}
269
270static unsigned
271calc_n32_return_struct_flags(int soft_float, ffi_type *arg)
272{
273 unsigned flags = 0;
274 unsigned small = FFI_TYPE_SMALLSTRUCT;
275 ffi_type *e;
276
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. */
283
284 if (arg->size > 16)
285 return 0;
286
287 if (arg->size > 8)
288 small = FFI_TYPE_SMALLSTRUCT2;
289
290 e = arg->elements[0];
291
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;
296
297 if (flags && (e = arg->elements[1]))
298 {
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;
305
306 if (flags && (arg->elements[2]))
307 {
308 /* There are three arguments and the first two are
309 floats! This must be passed the old way. */
310 return small;
311 }
312 if (soft_float)
313 flags += FFI_TYPE_STRUCT_SOFT;
314 }
315 else
316 if (!flags)
317 return small;
318
319 return flags;
320}
321
322#endif
323
324/* Perform machine dependent cif processing */
325ffi_status ffi_prep_cif_machdep(ffi_cif *cif)
326{
327 cif->flags = 0;
328
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.
332 */
333
334 if (cif->rtype->type != FFI_TYPE_STRUCT && cif->abi == FFI_O32)
335 {
336 if (cif->nargs > 0)
337 {
338 switch ((cif->arg_types)[0]->type)
339 {
340 case FFI_TYPE_FLOAT:
341 case FFI_TYPE_DOUBLE:
342 cif->flags += (cif->arg_types)[0]->type;
343 break;
344
345 default:
346 break;
347 }
348
349 if (cif->nargs > 1)
350 {
351 /* Only handle the second argument if the first
352 is a float or double. */
353 if (cif->flags)
354 {
355 switch ((cif->arg_types)[1]->type)
356 {
357 case FFI_TYPE_FLOAT:
358 case FFI_TYPE_DOUBLE:
359 cif->flags += (cif->arg_types)[1]->type << FFI_FLAG_BITS;
360 break;
361
362 default:
363 break;
364 }
365 }
366 }
367 }
368 }
369
370 /* Set the return type flag */
371
372 if (cif->abi == FFI_O32_SOFT_FLOAT)
373 {
374 switch (cif->rtype->type)
375 {
376 case FFI_TYPE_VOID:
377 case FFI_TYPE_STRUCT:
378 cif->flags += cif->rtype->type << (FFI_FLAG_BITS * 2);
379 break;
380
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;
386
387 case FFI_TYPE_FLOAT:
388 default:
389 cif->flags += FFI_TYPE_INT << (FFI_FLAG_BITS * 2);
390 break;
391 }
392 }
393 else
394 {
395 /* FFI_O32 */
396 switch (cif->rtype->type)
397 {
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;
404
405 case FFI_TYPE_SINT64:
406 case FFI_TYPE_UINT64:
407 cif->flags += FFI_TYPE_UINT64 << (FFI_FLAG_BITS * 2);
408 break;
409
410 default:
411 cif->flags += FFI_TYPE_INT << (FFI_FLAG_BITS * 2);
412 break;
413 }
414 }
415#endif
416
417#ifdef FFI_MIPS_N32
418 /* Set the flags necessary for N32 processing */
419 {
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;
425
426 unsigned struct_flags = 0;
427 int soft_float = (cif->abi == FFI_N32_SOFT_FLOAT
428 || cif->abi == FFI_N64_SOFT_FLOAT);
429
430 if (cif->rtype->type == FFI_TYPE_STRUCT)
431 {
432 struct_flags = calc_n32_return_struct_flags(soft_float, cif->rtype);
433
434 if (struct_flags == 0)
435 {
436 /* This means that the structure is being passed as
437 a hidden argument */
438
439 arg_reg = 1;
440 count = (cif->nargs < 7) ? cif->nargs : 7;
441
442 cif->rstruct_flag = !0;
443 }
444 else
445 cif->rstruct_flag = 0;
446 }
447 else
448 cif->rstruct_flag = 0;
449
450 while (count-- > 0 && arg_reg < 8)
451 {
452 type = (cif->arg_types)[index]->type;
453 if (soft_float)
454 {
455 switch (type)
456 {
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;
465 }
466 }
467 switch (type)
468 {
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)
480 {
481 arg_reg += 2;
482 }
483 else
484 {
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++;
491 }
492 break;
493
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;
500
501 default:
502 arg_reg++;
503 break;
504 }
505
506 index++;
507 }
508
509 /* Set the return type flag */
510 switch (cif->rtype->type)
511 {
512 case FFI_TYPE_STRUCT:
513 {
514 if (struct_flags == 0)
515 {
516 /* The structure is returned through a hidden
517 first argument. Do nothing, 'cause FFI_TYPE_VOID
518 is 0 */
519 }
520 else
521 {
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));
526 }
527 break;
528 }
529
530 case FFI_TYPE_VOID:
531 /* Do nothing, 'cause FFI_TYPE_VOID is 0 */
532 break;
533
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;
540
541 case FFI_TYPE_FLOAT:
542 if (soft_float)
543 {
544 cif->flags += FFI_TYPE_SINT32 << (FFI_FLAG_BITS * 8);
545 break;
546 }
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;
554
555 case FFI_TYPE_LONGDOUBLE:
556 /* Long double is returned as if it were a struct containing
557 two doubles. */
558 if (soft_float)
559 {
560 cif->flags += FFI_TYPE_STRUCT << (FFI_FLAG_BITS * 8);
561 cif->flags += FFI_TYPE_SMALLSTRUCT2 << (4 + (FFI_FLAG_BITS * 8));
562 }
563 else
564 {
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));
569 }
570 break;
571 default:
572 cif->flags += FFI_TYPE_INT << (FFI_FLAG_BITS * 8);
573 break;
574 }
575 }
576#endif
577
578 return FFI_OK;
579}
580
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));
585
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));
590
591 void ffi_call(ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue)
592{
593 extended_cif ecif;
594
595 ecif.cif = cif;
596 ecif.avalue = avalue;
597
598 /* If the return value is a struct and we don't have a return */
599 /* value address then we need to make one */
600
601 if ((rvalue == NULL) &&
602 (cif->rtype->type == FFI_TYPE_STRUCT))
603 ecif.rvalue = alloca(cif->rtype->size);
604 else
605 ecif.rvalue = rvalue;
606
607 switch (cif->abi)
608 {
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
616
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:
622 {
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)
627 {
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;
633 }
634 else if (cif->rtype->type == FFI_TYPE_FLOAT
635 && (cif->abi == FFI_N64_SOFT_FLOAT
636 || cif->abi == FFI_N32_SOFT_FLOAT))
637 {
638 rvalue_copy = alloca (8);
639 copy_rvalue = 1;
640#if defined(__MIPSEB__) || defined(_MIPSEB)
641 copy_offset = 4;
642#endif
643 }
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);
648 }
649 break;
650#endif
651
652 default:
653 FFI_ASSERT(0);
654 break;
655 }
656}
657
658#if FFI_CLOSURES
659#if defined(FFI_MIPS_O32)
660extern void ffi_closure_O32(void);
661#else
662extern void ffi_closure_N32(void);
663#endif /* FFI_MIPS_O32 */
664
665ffi_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)
671{
672 unsigned int *tramp = (unsigned int *) &closure->tramp[0];
673 void * fn;
674 char *clear_location = (char *) codeloc;
675
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 */
692
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);
732
733#endif
734
735 closure->cif = cif;
736 closure->fun = fun;
737 closure->user_data = user_data;
738
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;
745}
746
747/*
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.
753 *
754 * RVALUE is the location where the function return value will be
755 * stored. CLOSURE is the prepared closure to invoke.
756 *
757 * This function should only be called from assembly, which is in
758 * turn called from a trampoline.
759 *
760 * Returns the function return type.
761 *
762 * Based on the similar routine for sparc.
763 */
764int
765ffi_closure_mips_inner_O32 (ffi_closure *closure,
766 void *rvalue, ffi_arg *ar,
767 double *fpr)
768{
769 ffi_cif *cif;
770 void **avaluep;
771 ffi_arg *avalue;
772 ffi_type **arg_types;
773 int i, avn, argn, seen_int;
774
775 cif = closure->cif;
776 avalue = alloca (cif->nargs * sizeof (ffi_arg));
777 avaluep = alloca (cif->nargs * sizeof (ffi_arg));
778
779 seen_int = (cif->abi == FFI_O32_SOFT_FLOAT);
780 argn = 0;
781
782 if ((cif->flags >> (FFI_FLAG_BITS * 2)) == FFI_TYPE_STRUCT)
783 {
784 rvalue = (void *)(UINT32)ar[0];
785 argn = 1;
786 }
787
788 i = 0;
789 avn = cif->nargs;
790 arg_types = cif->arg_types;
791
792 while (i < avn)
793 {
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))
798 {
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];
805 }
806 else
807 {
808 if (arg_types[i]->alignment == 8 && (argn & 0x1))
809 argn++;
810 switch (arg_types[i]->type)
811 {
812 case FFI_TYPE_SINT8:
813 avaluep[i] = &avalue[i];
814 *(SINT8 *) &avalue[i] = (SINT8) ar[argn];
815 break;
816
817 case FFI_TYPE_UINT8:
818 avaluep[i] = &avalue[i];
819 *(UINT8 *) &avalue[i] = (UINT8) ar[argn];
820 break;
821
822 case FFI_TYPE_SINT16:
823 avaluep[i] = &avalue[i];
824 *(SINT16 *) &avalue[i] = (SINT16) ar[argn];
825 break;
826
827 case FFI_TYPE_UINT16:
828 avaluep[i] = &avalue[i];
829 *(UINT16 *) &avalue[i] = (UINT16) ar[argn];
830 break;
831
832 default:
833 avaluep[i] = (char *) &ar[argn];
834 break;
835 }
836 seen_int = 1;
837 }
838 argn += ALIGN(arg_types[i]->size, FFI_SIZEOF_ARG) / FFI_SIZEOF_ARG;
839 i++;
840 }
841
842 /* Invoke the closure. */
843 (closure->fun) (cif, rvalue, avaluep, closure->user_data);
844
845 if (cif->abi == FFI_O32_SOFT_FLOAT)
846 {
847 switch (cif->rtype->type)
848 {
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;
855 }
856 }
857 else
858 {
859 return cif->rtype->type;
860 }
861}
862
863#if defined(FFI_MIPS_N32)
864
865static void
866copy_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)
869{
870 ffi_type **elt_typep = type->elements;
871 while(*elt_typep)
872 {
873 ffi_type *elt_type = *elt_typep;
874 unsigned o;
875 char *tp;
876 char *argp;
877 char *fpp;
878
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);
884
885 argp = (char *)(ar + argn);
886 fpp = (char *)(argn >= 8 ? ar + argn : fpr + argn);
887
888 tp = target + offset;
889
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);
894
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);
900 }
901}
902
903/*
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.
908 *
909 * RVALUE is the location where the function return value will be
910 * stored. CLOSURE is the prepared closure to invoke.
911 *
912 * This function should only be called from assembly, which is in
913 * turn called from a trampoline.
914 *
915 * Returns the function return flags.
916 *
917 */
918int
919ffi_closure_mips_inner_N32 (ffi_closure *closure,
920 void *rvalue, ffi_arg *ar,
921 ffi_arg *fpr)
922{
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;
930
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));
936
937 argn = 0;
938
939 if (cif->rstruct_flag)
940 {
941#if _MIPS_SIM==_ABIN32
942 rvalue = (void *)(UINT32)ar[0];
943#else /* N64 */
944 rvalue = (void *)ar[0];
945#endif
946 argn = 1;
947 }
948
949 i = 0;
950 avn = cif->nargs;
951 arg_types = cif->arg_types;
952
953 while (i < avn)
954 {
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)
958 {
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)))
961 {
962 argp=(ffi_arg*)ALIGN(argp,arg_types[i]->alignment);
963 argn++;
964 }
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;
971 }
972 else
973 {
974 unsigned type = arg_types[i]->type;
975
976 if (arg_types[i]->alignment > sizeof(ffi_arg))
977 argn = ALIGN(argn, arg_types[i]->alignment / sizeof(ffi_arg));
978
979 argp = ar + argn;
980
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;
985
986 if (soft_float && type == FFI_TYPE_FLOAT)
987 type = FFI_TYPE_UINT32;
988
989 switch (type)
990 {
991 case FFI_TYPE_SINT8:
992 avaluep[i] = &avalue[i];
993 *(SINT8 *) &avalue[i] = (SINT8) *argp;
994 break;
995
996 case FFI_TYPE_UINT8:
997 avaluep[i] = &avalue[i];
998 *(UINT8 *) &avalue[i] = (UINT8) *argp;
999 break;
1000
1001 case FFI_TYPE_SINT16:
1002 avaluep[i] = &avalue[i];
1003 *(SINT16 *) &avalue[i] = (SINT16) *argp;
1004 break;
1005
1006 case FFI_TYPE_UINT16:
1007 avaluep[i] = &avalue[i];
1008 *(UINT16 *) &avalue[i] = (UINT16) *argp;
1009 break;
1010
1011 case FFI_TYPE_SINT32:
1012 avaluep[i] = &avalue[i];
1013 *(SINT32 *) &avalue[i] = (SINT32) *argp;
1014 break;
1015
1016 case FFI_TYPE_UINT32:
1017 avaluep[i] = &avalue[i];
1018 *(UINT32 *) &avalue[i] = (UINT32) *argp;
1019 break;
1020
1021 case FFI_TYPE_STRUCT:
1022 if (argn < 8)
1023 {
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);
1029
1030 break;
1031 }
1032 /* Else fall through. */
1033 default:
1034 avaluep[i] = (char *) argp;
1035 break;
1036 }
1037 }
1038 argn += ALIGN(arg_types[i]->size, sizeof(ffi_arg)) / sizeof(ffi_arg);
1039 i++;
1040 }
1041
1042 /* Invoke the closure. */
1043 (closure->fun) (cif, rvalue, avaluep, closure->user_data);
1044
1045 return cif->flags >> (FFI_FLAG_BITS * 8);
1046}
1047
1048#endif /* FFI_MIPS_N32 */
1049
1050#endif /* FFI_CLOSURES */
ffi_prep_closure_loc
ffi_status ffi_prep_closure_loc(ffi_closure *closure, ffi_cif *cif, void(*fun)(ffi_cif *, void *, void **, void *), void *user_data, void *codeloc)
Definition: ffi.c:928
ffi_prep_cif_machdep
ffi_status ffi_prep_cif_machdep(ffi_cif *cif)
Definition: ffi.c:758
ffi_call
void ffi_call(ffi_cif *cif, void(*fn)(void), void *rvalue, void **avalue)
Definition: ffi.c:813
ffi_arg
unsigned long ffi_arg
Definition: ffitarget.h:30
FFI_TRAMPOLINE_SIZE
#define FFI_TRAMPOLINE_SIZE
Definition: ffitarget.h:45
ffi_abi
ffi_abi
Definition: ffitarget.h:34
FFI_TYPE_LONGDOUBLE
#define FFI_TYPE_LONGDOUBLE
Definition: ffi.c:40
ffi_prep_args
void ffi_prep_args(char *stack, extended_cif *ecif)
Definition: ffi.c:46
ffi_common.h
UINT16
unsigned short UINT16
Definition: ffi_common.h:97
SINT16
signed short SINT16
Definition: ffi_common.h:98
alloca
#define alloca
Definition: ffi_common.h:27
SINT32
signed int SINT32
Definition: ffi_common.h:100
ALIGN
#define ALIGN(v, a)
Definition: ffi_common.h:77
SINT8
signed char SINT8
Definition: ffi_common.h:96
FFI_ASSERT
#define FFI_ASSERT(x)
Definition: ffi_common.h:72
UINT8
unsigned char UINT8
Definition: ffi_common.h:95
UINT32
unsigned int UINT32
Definition: ffi_common.h:99
memcpy
#define memcpy(d, s, n)
Definition: ffi_common.h:55
size
voidpf void uLong size
Definition: ioapi.h:138
long
typedef long(ZCALLBACK *tell_file_func) OF((voidpf opaque
offset
voidpf uLong offset
Definition: ioapi.h:144
FIX_ARGP
#define FIX_ARGP
Definition: ffi.c:63
ffi_call_O32
int ffi_call_O32(void(*)(char *, extended_cif *, int, int), extended_cif *, unsigned, unsigned, unsigned *, void(*)(void))
ffi_call_N32
int ffi_call_N32(void(*)(char *, extended_cif *, int, int), extended_cif *, unsigned, unsigned, void *, void(*)(void))
FFI_TYPE_SMALLSTRUCT
#define FFI_TYPE_SMALLSTRUCT
Definition: ffitarget.h:96
FFI_SIZEOF_ARG
#define FFI_SIZEOF_ARG
Definition: ffitarget.h:77
FFI_TYPE_SMALLSTRUCT2
#define FFI_TYPE_SMALLSTRUCT2
Definition: ffitarget.h:97
FFI_N64_SOFT_FLOAT
@ FFI_N64_SOFT_FLOAT
Definition: ffitarget.h:201
FFI_N64
@ FFI_N64
Definition: ffitarget.h:198
FFI_O32_SOFT_FLOAT
@ FFI_O32_SOFT_FLOAT
Definition: ffitarget.h:199
FFI_N32_SOFT_FLOAT
@ FFI_N32_SOFT_FLOAT
Definition: ffitarget.h:200
FFI_O32
@ FFI_O32
Definition: ffitarget.h:196
FFI_N32
@ FFI_N32
Definition: ffitarget.h:197
FFI_FLAG_BITS
#define FFI_FLAG_BITS
Definition: ffitarget.h:83
FFI_TYPE_STRUCT_SOFT
#define FFI_TYPE_STRUCT_SOFT
Definition: ffitarget.h:121
ruby::backward::cxxanyargs::type
VALUE type(ANYARGS)
ANYARGS-ed function type.
Definition: cxxanyargs.hpp:56
count
int count
Definition: nkf.c:5055
NULL
#define NULL
Definition: regenc.h:69
extended_cif
Definition: ffi_common.h:87
extended_cif::rvalue
void * rvalue
Definition: ffi_common.h:89
extended_cif::cif
ffi_cif * cif
Definition: ffi_common.h:88
extended_cif::avalue
void ** avalue
Definition: ffi_common.h:90