Imported File#ftype spec from rubyspecs.
[rbx.git] / shotgun / external_libs / libffi / src / sh / ffi.c
bloba5d61d2067c8401bcb7b085db7f1b255fa206fad
1 /* -----------------------------------------------------------------------
2 ffi.c - Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007 Kaz Kojima
4 SuperH 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,
18 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
20 NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
21 HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
22 WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
24 DEALINGS IN THE SOFTWARE.
25 ----------------------------------------------------------------------- */
27 #include <ffi.h>
28 #include <ffi_common.h>
30 #include <stdlib.h>
32 #define NGREGARG 4
33 #if defined(__SH4__)
34 #define NFREGARG 8
35 #endif
37 #if defined(__HITACHI__)
38 #define STRUCT_VALUE_ADDRESS_WITH_ARG 1
39 #else
40 #define STRUCT_VALUE_ADDRESS_WITH_ARG 0
41 #endif
43 /* If the structure has essentialy an unique element, return its type. */
44 static int
45 simple_type (ffi_type *arg)
47 if (arg->type != FFI_TYPE_STRUCT)
48 return arg->type;
49 else if (arg->elements[1])
50 return FFI_TYPE_STRUCT;
52 return simple_type (arg->elements[0]);
55 static int
56 return_type (ffi_type *arg)
58 unsigned short type;
60 if (arg->type != FFI_TYPE_STRUCT)
61 return arg->type;
63 type = simple_type (arg->elements[0]);
64 if (! arg->elements[1])
66 switch (type)
68 case FFI_TYPE_SINT8:
69 case FFI_TYPE_UINT8:
70 case FFI_TYPE_SINT16:
71 case FFI_TYPE_UINT16:
72 case FFI_TYPE_SINT32:
73 case FFI_TYPE_UINT32:
74 return FFI_TYPE_INT;
76 default:
77 return type;
81 /* gcc uses r0/r1 pair for some kind of structures. */
82 if (arg->size <= 2 * sizeof (int))
84 int i = 0;
85 ffi_type *e;
87 while ((e = arg->elements[i++]))
89 type = simple_type (e);
90 switch (type)
92 case FFI_TYPE_SINT32:
93 case FFI_TYPE_UINT32:
94 case FFI_TYPE_INT:
95 case FFI_TYPE_FLOAT:
96 return FFI_TYPE_UINT64;
98 default:
99 break;
104 return FFI_TYPE_STRUCT;
107 /* ffi_prep_args is called by the assembly routine once stack space
108 has been allocated for the function's arguments */
110 void ffi_prep_args(char *stack, extended_cif *ecif)
112 register unsigned int i;
113 register int tmp;
114 register unsigned int avn;
115 register void **p_argv;
116 register char *argp;
117 register ffi_type **p_arg;
118 int greg, ireg;
119 #if defined(__SH4__)
120 int freg = 0;
121 #endif
123 tmp = 0;
124 argp = stack;
126 if (return_type (ecif->cif->rtype) == FFI_TYPE_STRUCT)
128 *(void **) argp = ecif->rvalue;
129 argp += 4;
130 ireg = STRUCT_VALUE_ADDRESS_WITH_ARG ? 1 : 0;
132 else
133 ireg = 0;
135 /* Set arguments for registers. */
136 greg = ireg;
137 avn = ecif->cif->nargs;
138 p_argv = ecif->avalue;
140 for (i = 0, p_arg = ecif->cif->arg_types; i < avn; i++, p_arg++, p_argv++)
142 size_t z;
144 z = (*p_arg)->size;
145 if (z < sizeof(int))
147 if (greg++ >= NGREGARG)
148 continue;
150 z = sizeof(int);
151 switch ((*p_arg)->type)
153 case FFI_TYPE_SINT8:
154 *(signed int *) argp = (signed int)*(SINT8 *)(* p_argv);
155 break;
157 case FFI_TYPE_UINT8:
158 *(unsigned int *) argp = (unsigned int)*(UINT8 *)(* p_argv);
159 break;
161 case FFI_TYPE_SINT16:
162 *(signed int *) argp = (signed int)*(SINT16 *)(* p_argv);
163 break;
165 case FFI_TYPE_UINT16:
166 *(unsigned int *) argp = (unsigned int)*(UINT16 *)(* p_argv);
167 break;
169 case FFI_TYPE_STRUCT:
170 *(unsigned int *) argp = (unsigned int)*(UINT32 *)(* p_argv);
171 break;
173 default:
174 FFI_ASSERT(0);
176 argp += z;
178 else if (z == sizeof(int))
180 #if defined(__SH4__)
181 if ((*p_arg)->type == FFI_TYPE_FLOAT)
183 if (freg++ >= NFREGARG)
184 continue;
186 else
187 #endif
189 if (greg++ >= NGREGARG)
190 continue;
192 *(unsigned int *) argp = (unsigned int)*(UINT32 *)(* p_argv);
193 argp += z;
195 #if defined(__SH4__)
196 else if ((*p_arg)->type == FFI_TYPE_DOUBLE)
198 if (freg + 1 >= NFREGARG)
199 continue;
200 freg = (freg + 1) & ~1;
201 freg += 2;
202 memcpy (argp, *p_argv, z);
203 argp += z;
205 #endif
206 else
208 int n = (z + sizeof (int) - 1) / sizeof (int);
209 #if defined(__SH4__)
210 if (greg + n - 1 >= NGREGARG)
211 continue;
212 #else
213 if (greg >= NGREGARG)
214 continue;
215 #endif
216 greg += n;
217 memcpy (argp, *p_argv, z);
218 argp += n * sizeof (int);
222 /* Set arguments on stack. */
223 greg = ireg;
224 #if defined(__SH4__)
225 freg = 0;
226 #endif
227 p_argv = ecif->avalue;
229 for (i = 0, p_arg = ecif->cif->arg_types; i < avn; i++, p_arg++, p_argv++)
231 size_t z;
233 z = (*p_arg)->size;
234 if (z < sizeof(int))
236 if (greg++ < NGREGARG)
237 continue;
239 z = sizeof(int);
240 switch ((*p_arg)->type)
242 case FFI_TYPE_SINT8:
243 *(signed int *) argp = (signed int)*(SINT8 *)(* p_argv);
244 break;
246 case FFI_TYPE_UINT8:
247 *(unsigned int *) argp = (unsigned int)*(UINT8 *)(* p_argv);
248 break;
250 case FFI_TYPE_SINT16:
251 *(signed int *) argp = (signed int)*(SINT16 *)(* p_argv);
252 break;
254 case FFI_TYPE_UINT16:
255 *(unsigned int *) argp = (unsigned int)*(UINT16 *)(* p_argv);
256 break;
258 case FFI_TYPE_STRUCT:
259 *(unsigned int *) argp = (unsigned int)*(UINT32 *)(* p_argv);
260 break;
262 default:
263 FFI_ASSERT(0);
265 argp += z;
267 else if (z == sizeof(int))
269 #if defined(__SH4__)
270 if ((*p_arg)->type == FFI_TYPE_FLOAT)
272 if (freg++ < NFREGARG)
273 continue;
275 else
276 #endif
278 if (greg++ < NGREGARG)
279 continue;
281 *(unsigned int *) argp = (unsigned int)*(UINT32 *)(* p_argv);
282 argp += z;
284 #if defined(__SH4__)
285 else if ((*p_arg)->type == FFI_TYPE_DOUBLE)
287 if (freg + 1 < NFREGARG)
289 freg = (freg + 1) & ~1;
290 freg += 2;
291 continue;
293 memcpy (argp, *p_argv, z);
294 argp += z;
296 #endif
297 else
299 int n = (z + sizeof (int) - 1) / sizeof (int);
300 if (greg + n - 1 < NGREGARG)
302 greg += n;
303 continue;
305 #if (! defined(__SH4__))
306 else if (greg < NGREGARG)
308 greg = NGREGARG;
309 continue;
311 #endif
312 memcpy (argp, *p_argv, z);
313 argp += n * sizeof (int);
317 return;
320 /* Perform machine dependent cif processing */
321 ffi_status ffi_prep_cif_machdep(ffi_cif *cif)
323 int i, j;
324 int size, type;
325 int n, m;
326 int greg;
327 #if defined(__SH4__)
328 int freg = 0;
329 #endif
331 cif->flags = 0;
333 greg = ((return_type (cif->rtype) == FFI_TYPE_STRUCT) &&
334 STRUCT_VALUE_ADDRESS_WITH_ARG) ? 1 : 0;
336 #if defined(__SH4__)
337 for (i = j = 0; i < cif->nargs && j < 12; i++)
339 type = (cif->arg_types)[i]->type;
340 switch (type)
342 case FFI_TYPE_FLOAT:
343 if (freg >= NFREGARG)
344 continue;
345 freg++;
346 cif->flags += ((cif->arg_types)[i]->type) << (2 * j);
347 j++;
348 break;
350 case FFI_TYPE_DOUBLE:
351 if ((freg + 1) >= NFREGARG)
352 continue;
353 freg = (freg + 1) & ~1;
354 freg += 2;
355 cif->flags += ((cif->arg_types)[i]->type) << (2 * j);
356 j++;
357 break;
359 default:
360 size = (cif->arg_types)[i]->size;
361 n = (size + sizeof (int) - 1) / sizeof (int);
362 if (greg + n - 1 >= NGREGARG)
363 continue;
364 greg += n;
365 for (m = 0; m < n; m++)
366 cif->flags += FFI_TYPE_INT << (2 * j++);
367 break;
370 #else
371 for (i = j = 0; i < cif->nargs && j < 4; i++)
373 size = (cif->arg_types)[i]->size;
374 n = (size + sizeof (int) - 1) / sizeof (int);
375 if (greg >= NGREGARG)
376 continue;
377 else if (greg + n - 1 >= NGREGARG)
378 n = NGREGARG - greg;
379 greg += n;
380 for (m = 0; m < n; m++)
381 cif->flags += FFI_TYPE_INT << (2 * j++);
383 #endif
385 /* Set the return type flag */
386 switch (cif->rtype->type)
388 case FFI_TYPE_STRUCT:
389 cif->flags += (unsigned) (return_type (cif->rtype)) << 24;
390 break;
392 case FFI_TYPE_VOID:
393 case FFI_TYPE_FLOAT:
394 case FFI_TYPE_DOUBLE:
395 case FFI_TYPE_SINT64:
396 case FFI_TYPE_UINT64:
397 cif->flags += (unsigned) cif->rtype->type << 24;
398 break;
400 default:
401 cif->flags += FFI_TYPE_INT << 24;
402 break;
405 return FFI_OK;
408 extern void ffi_call_SYSV(void (*)(char *, extended_cif *), extended_cif *,
409 unsigned, unsigned, unsigned *, void (*fn)());
411 void ffi_call(ffi_cif *cif, void (*fn)(), void *rvalue, void **avalue)
413 extended_cif ecif;
414 UINT64 trvalue;
416 ecif.cif = cif;
417 ecif.avalue = avalue;
419 /* If the return value is a struct and we don't have a return */
420 /* value address then we need to make one */
422 if (cif->rtype->type == FFI_TYPE_STRUCT
423 && return_type (cif->rtype) != FFI_TYPE_STRUCT)
424 ecif.rvalue = &trvalue;
425 else if ((rvalue == NULL) &&
426 (cif->rtype->type == FFI_TYPE_STRUCT))
428 ecif.rvalue = alloca(cif->rtype->size);
430 else
431 ecif.rvalue = rvalue;
433 switch (cif->abi)
435 case FFI_SYSV:
436 ffi_call_SYSV(ffi_prep_args, &ecif, cif->bytes, cif->flags, ecif.rvalue,
437 fn);
438 break;
439 default:
440 FFI_ASSERT(0);
441 break;
444 if (rvalue
445 && cif->rtype->type == FFI_TYPE_STRUCT
446 && return_type (cif->rtype) != FFI_TYPE_STRUCT)
447 memcpy (rvalue, &trvalue, cif->rtype->size);
450 extern void ffi_closure_SYSV (void);
451 #if defined(__SH4__)
452 extern void __ic_invalidate (void *line);
453 #endif
455 ffi_status
456 ffi_prep_closure_loc (ffi_closure* closure,
457 ffi_cif* cif,
458 void (*fun)(ffi_cif*, void*, void**, void*),
459 void *user_data,
460 void *codeloc)
462 unsigned int *tramp;
463 unsigned short insn;
465 FFI_ASSERT (cif->abi == FFI_GCC_SYSV);
467 tramp = (unsigned int *) &closure->tramp[0];
468 /* Set T bit if the function returns a struct pointed with R2. */
469 insn = (return_type (cif->rtype) == FFI_TYPE_STRUCT
470 ? 0x0018 /* sett */
471 : 0x0008 /* clrt */);
473 #ifdef __LITTLE_ENDIAN__
474 tramp[0] = 0xd301d102;
475 tramp[1] = 0x0000412b | (insn << 16);
476 #else
477 tramp[0] = 0xd102d301;
478 tramp[1] = 0x412b0000 | insn;
479 #endif
480 *(void **) &tramp[2] = (void *)codeloc; /* ctx */
481 *(void **) &tramp[3] = (void *)ffi_closure_SYSV; /* funaddr */
483 closure->cif = cif;
484 closure->fun = fun;
485 closure->user_data = user_data;
487 #if defined(__SH4__)
488 /* Flush the icache. */
489 __ic_invalidate(codeloc);
490 #endif
492 return FFI_OK;
495 /* Basically the trampoline invokes ffi_closure_SYSV, and on
496 * entry, r3 holds the address of the closure.
497 * After storing the registers that could possibly contain
498 * parameters to be passed into the stack frame and setting
499 * up space for a return value, ffi_closure_SYSV invokes the
500 * following helper function to do most of the work.
503 #ifdef __LITTLE_ENDIAN__
504 #define OFS_INT8 0
505 #define OFS_INT16 0
506 #else
507 #define OFS_INT8 3
508 #define OFS_INT16 2
509 #endif
512 ffi_closure_helper_SYSV (ffi_closure *closure, void *rvalue,
513 unsigned long *pgr, unsigned long *pfr,
514 unsigned long *pst)
516 void **avalue;
517 ffi_type **p_arg;
518 int i, avn;
519 int ireg, greg = 0;
520 #if defined(__SH4__)
521 int freg = 0;
522 #endif
523 ffi_cif *cif;
525 cif = closure->cif;
526 avalue = alloca(cif->nargs * sizeof(void *));
528 /* Copy the caller's structure return value address so that the closure
529 returns the data directly to the caller. */
530 if (cif->rtype->type == FFI_TYPE_STRUCT && STRUCT_VALUE_ADDRESS_WITH_ARG)
532 rvalue = (void *) *pgr++;
533 ireg = 1;
535 else
536 ireg = 0;
538 cif = closure->cif;
539 greg = ireg;
540 avn = cif->nargs;
542 /* Grab the addresses of the arguments from the stack frame. */
543 for (i = 0, p_arg = cif->arg_types; i < avn; i++, p_arg++)
545 size_t z;
547 z = (*p_arg)->size;
548 if (z < sizeof(int))
550 if (greg++ >= NGREGARG)
551 continue;
553 z = sizeof(int);
554 switch ((*p_arg)->type)
556 case FFI_TYPE_SINT8:
557 case FFI_TYPE_UINT8:
558 avalue[i] = (((char *)pgr) + OFS_INT8);
559 break;
561 case FFI_TYPE_SINT16:
562 case FFI_TYPE_UINT16:
563 avalue[i] = (((char *)pgr) + OFS_INT16);
564 break;
566 case FFI_TYPE_STRUCT:
567 avalue[i] = pgr;
568 break;
570 default:
571 FFI_ASSERT(0);
573 pgr++;
575 else if (z == sizeof(int))
577 #if defined(__SH4__)
578 if ((*p_arg)->type == FFI_TYPE_FLOAT)
580 if (freg++ >= NFREGARG)
581 continue;
582 avalue[i] = pfr;
583 pfr++;
585 else
586 #endif
588 if (greg++ >= NGREGARG)
589 continue;
590 avalue[i] = pgr;
591 pgr++;
594 #if defined(__SH4__)
595 else if ((*p_arg)->type == FFI_TYPE_DOUBLE)
597 if (freg + 1 >= NFREGARG)
598 continue;
599 if (freg & 1)
600 pfr++;
601 freg = (freg + 1) & ~1;
602 freg += 2;
603 avalue[i] = pfr;
604 pfr += 2;
606 #endif
607 else
609 int n = (z + sizeof (int) - 1) / sizeof (int);
610 #if defined(__SH4__)
611 if (greg + n - 1 >= NGREGARG)
612 continue;
613 #else
614 if (greg >= NGREGARG)
615 continue;
616 #endif
617 greg += n;
618 avalue[i] = pgr;
619 pgr += n;
623 greg = ireg;
624 #if defined(__SH4__)
625 freg = 0;
626 #endif
628 for (i = 0, p_arg = cif->arg_types; i < avn; i++, p_arg++)
630 size_t z;
632 z = (*p_arg)->size;
633 if (z < sizeof(int))
635 if (greg++ < NGREGARG)
636 continue;
638 z = sizeof(int);
639 switch ((*p_arg)->type)
641 case FFI_TYPE_SINT8:
642 case FFI_TYPE_UINT8:
643 avalue[i] = (((char *)pst) + OFS_INT8);
644 break;
646 case FFI_TYPE_SINT16:
647 case FFI_TYPE_UINT16:
648 avalue[i] = (((char *)pst) + OFS_INT16);
649 break;
651 case FFI_TYPE_STRUCT:
652 avalue[i] = pst;
653 break;
655 default:
656 FFI_ASSERT(0);
658 pst++;
660 else if (z == sizeof(int))
662 #if defined(__SH4__)
663 if ((*p_arg)->type == FFI_TYPE_FLOAT)
665 if (freg++ < NFREGARG)
666 continue;
668 else
669 #endif
671 if (greg++ < NGREGARG)
672 continue;
674 avalue[i] = pst;
675 pst++;
677 #if defined(__SH4__)
678 else if ((*p_arg)->type == FFI_TYPE_DOUBLE)
680 if (freg + 1 < NFREGARG)
682 freg = (freg + 1) & ~1;
683 freg += 2;
684 continue;
686 avalue[i] = pst;
687 pst += 2;
689 #endif
690 else
692 int n = (z + sizeof (int) - 1) / sizeof (int);
693 if (greg + n - 1 < NGREGARG)
695 greg += n;
696 continue;
698 #if (! defined(__SH4__))
699 else if (greg < NGREGARG)
701 greg += n;
702 pst += greg - NGREGARG;
703 continue;
705 #endif
706 avalue[i] = pst;
707 pst += n;
711 (closure->fun) (cif, rvalue, avalue, closure->user_data);
713 /* Tell ffi_closure_SYSV how to perform return type promotions. */
714 return return_type (cif->rtype);