2005-12-29 Paul Brook <paul@codesourcery.com>
[official-gcc.git] / libffi / src / sh / ffi.c
blob38449e9e6c117c74d32aa95eb42beea9f1e2c45d
1 /* -----------------------------------------------------------------------
2 ffi.c - Copyright (c) 2002, 2003, 2004, 2005 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, 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 #define NGREGARG 4
32 #if defined(__SH4__)
33 #define NFREGARG 8
34 #endif
36 #if defined(__HITACHI__)
37 #define STRUCT_VALUE_ADDRESS_WITH_ARG 1
38 #else
39 #define STRUCT_VALUE_ADDRESS_WITH_ARG 0
40 #endif
42 /* If the structure has essentialy an unique element, return its type. */
43 static int
44 simple_type (ffi_type *arg)
46 if (arg->type != FFI_TYPE_STRUCT)
47 return arg->type;
48 else if (arg->elements[1])
49 return FFI_TYPE_STRUCT;
51 return simple_type (arg->elements[0]);
54 static int
55 return_type (ffi_type *arg)
57 unsigned short type;
59 if (arg->type != FFI_TYPE_STRUCT)
60 return arg->type;
62 type = simple_type (arg->elements[0]);
63 if (! arg->elements[1])
65 switch (type)
67 case FFI_TYPE_SINT8:
68 case FFI_TYPE_UINT8:
69 case FFI_TYPE_SINT16:
70 case FFI_TYPE_UINT16:
71 case FFI_TYPE_SINT32:
72 case FFI_TYPE_UINT32:
73 return FFI_TYPE_INT;
75 default:
76 return type;
80 /* gcc uses r0/r1 pair for some kind of structures. */
81 if (arg->size <= 2 * sizeof (int))
83 int i = 0;
84 ffi_type *e;
86 while ((e = arg->elements[i++]))
88 type = simple_type (e);
89 switch (type)
91 case FFI_TYPE_SINT32:
92 case FFI_TYPE_UINT32:
93 case FFI_TYPE_INT:
94 case FFI_TYPE_FLOAT:
95 return FFI_TYPE_UINT64;
97 default:
98 break;
103 return FFI_TYPE_STRUCT;
106 /* ffi_prep_args is called by the assembly routine once stack space
107 has been allocated for the function's arguments */
109 /*@-exportheader@*/
110 void ffi_prep_args(char *stack, extended_cif *ecif)
111 /*@=exportheader@*/
113 register unsigned int i;
114 register int tmp;
115 register unsigned int avn;
116 register void **p_argv;
117 register char *argp;
118 register ffi_type **p_arg;
119 int greg, ireg;
120 #if defined(__SH4__)
121 int freg = 0;
122 #endif
124 tmp = 0;
125 argp = stack;
127 if (return_type (ecif->cif->rtype) == FFI_TYPE_STRUCT)
129 *(void **) argp = ecif->rvalue;
130 argp += 4;
131 ireg = STRUCT_VALUE_ADDRESS_WITH_ARG ? 1 : 0;
133 else
134 ireg = 0;
136 /* Set arguments for registers. */
137 greg = ireg;
138 avn = ecif->cif->nargs;
139 p_argv = ecif->avalue;
141 for (i = 0, p_arg = ecif->cif->arg_types; i < avn; i++, p_arg++, p_argv++)
143 size_t z;
145 z = (*p_arg)->size;
146 if (z < sizeof(int))
148 if (greg++ >= NGREGARG)
149 continue;
151 z = sizeof(int);
152 switch ((*p_arg)->type)
154 case FFI_TYPE_SINT8:
155 *(signed int *) argp = (signed int)*(SINT8 *)(* p_argv);
156 break;
158 case FFI_TYPE_UINT8:
159 *(unsigned int *) argp = (unsigned int)*(UINT8 *)(* p_argv);
160 break;
162 case FFI_TYPE_SINT16:
163 *(signed int *) argp = (signed int)*(SINT16 *)(* p_argv);
164 break;
166 case FFI_TYPE_UINT16:
167 *(unsigned int *) argp = (unsigned int)*(UINT16 *)(* p_argv);
168 break;
170 case FFI_TYPE_STRUCT:
171 *(unsigned int *) argp = (unsigned int)*(UINT32 *)(* p_argv);
172 break;
174 default:
175 FFI_ASSERT(0);
177 argp += z;
179 else if (z == sizeof(int))
181 #if defined(__SH4__)
182 if ((*p_arg)->type == FFI_TYPE_FLOAT)
184 if (freg++ >= NFREGARG)
185 continue;
187 else
188 #endif
190 if (greg++ >= NGREGARG)
191 continue;
193 *(unsigned int *) argp = (unsigned int)*(UINT32 *)(* p_argv);
194 argp += z;
196 #if defined(__SH4__)
197 else if ((*p_arg)->type == FFI_TYPE_DOUBLE)
199 if (freg + 1 >= NFREGARG)
200 continue;
201 freg = (freg + 1) & ~1;
202 freg += 2;
203 memcpy (argp, *p_argv, z);
204 argp += z;
206 #endif
207 else
209 int n = (z + sizeof (int) - 1) / sizeof (int);
210 #if defined(__SH4__)
211 if (greg + n - 1 >= NGREGARG)
212 continue;
213 #else
214 if (greg >= NGREGARG)
215 continue;
216 #endif
217 greg += n;
218 memcpy (argp, *p_argv, z);
219 argp += n * sizeof (int);
223 /* Set arguments on stack. */
224 greg = ireg;
225 #if defined(__SH4__)
226 freg = 0;
227 #endif
228 p_argv = ecif->avalue;
230 for (i = 0, p_arg = ecif->cif->arg_types; i < avn; i++, p_arg++, p_argv++)
232 size_t z;
234 z = (*p_arg)->size;
235 if (z < sizeof(int))
237 if (greg++ < NGREGARG)
238 continue;
240 z = sizeof(int);
241 switch ((*p_arg)->type)
243 case FFI_TYPE_SINT8:
244 *(signed int *) argp = (signed int)*(SINT8 *)(* p_argv);
245 break;
247 case FFI_TYPE_UINT8:
248 *(unsigned int *) argp = (unsigned int)*(UINT8 *)(* p_argv);
249 break;
251 case FFI_TYPE_SINT16:
252 *(signed int *) argp = (signed int)*(SINT16 *)(* p_argv);
253 break;
255 case FFI_TYPE_UINT16:
256 *(unsigned int *) argp = (unsigned int)*(UINT16 *)(* p_argv);
257 break;
259 case FFI_TYPE_STRUCT:
260 *(unsigned int *) argp = (unsigned int)*(UINT32 *)(* p_argv);
261 break;
263 default:
264 FFI_ASSERT(0);
266 argp += z;
268 else if (z == sizeof(int))
270 #if defined(__SH4__)
271 if ((*p_arg)->type == FFI_TYPE_FLOAT)
273 if (freg++ < NFREGARG)
274 continue;
276 else
277 #endif
279 if (greg++ < NGREGARG)
280 continue;
282 *(unsigned int *) argp = (unsigned int)*(UINT32 *)(* p_argv);
283 argp += z;
285 #if defined(__SH4__)
286 else if ((*p_arg)->type == FFI_TYPE_DOUBLE)
288 if (freg + 1 < NFREGARG)
290 freg = (freg + 1) & ~1;
291 freg += 2;
292 continue;
294 memcpy (argp, *p_argv, z);
295 argp += z;
297 #endif
298 else
300 int n = (z + sizeof (int) - 1) / sizeof (int);
301 if (greg + n - 1 < NGREGARG)
303 greg += n;
304 continue;
306 #if (! defined(__SH4__))
307 else if (greg < NGREGARG)
309 greg = NGREGARG;
310 continue;
312 #endif
313 memcpy (argp, *p_argv, z);
314 argp += n * sizeof (int);
318 return;
321 /* Perform machine dependent cif processing */
322 ffi_status ffi_prep_cif_machdep(ffi_cif *cif)
324 int i, j;
325 int size, type;
326 int n, m;
327 int greg;
328 #if defined(__SH4__)
329 int freg = 0;
330 #endif
332 cif->flags = 0;
334 greg = ((return_type (cif->rtype) == FFI_TYPE_STRUCT) &&
335 STRUCT_VALUE_ADDRESS_WITH_ARG) ? 1 : 0;
337 #if defined(__SH4__)
338 for (i = j = 0; i < cif->nargs && j < 12; i++)
340 type = (cif->arg_types)[i]->type;
341 switch (type)
343 case FFI_TYPE_FLOAT:
344 if (freg >= NFREGARG)
345 continue;
346 freg++;
347 cif->flags += ((cif->arg_types)[i]->type) << (2 * j);
348 j++;
349 break;
351 case FFI_TYPE_DOUBLE:
352 if ((freg + 1) >= NFREGARG)
353 continue;
354 freg = (freg + 1) & ~1;
355 freg += 2;
356 cif->flags += ((cif->arg_types)[i]->type) << (2 * j);
357 j++;
358 break;
360 default:
361 size = (cif->arg_types)[i]->size;
362 n = (size + sizeof (int) - 1) / sizeof (int);
363 if (greg + n - 1 >= NGREGARG)
364 continue;
365 greg += n;
366 for (m = 0; m < n; m++)
367 cif->flags += FFI_TYPE_INT << (2 * j++);
368 break;
371 #else
372 for (i = j = 0; i < cif->nargs && j < 4; i++)
374 size = (cif->arg_types)[i]->size;
375 n = (size + sizeof (int) - 1) / sizeof (int);
376 if (greg >= NGREGARG)
377 continue;
378 else if (greg + n - 1 >= NGREGARG)
379 n = NGREGARG - greg;
380 greg += n;
381 for (m = 0; m < n; m++)
382 cif->flags += FFI_TYPE_INT << (2 * j++);
384 #endif
386 /* Set the return type flag */
387 switch (cif->rtype->type)
389 case FFI_TYPE_STRUCT:
390 cif->flags += (unsigned) (return_type (cif->rtype)) << 24;
391 break;
393 case FFI_TYPE_VOID:
394 case FFI_TYPE_FLOAT:
395 case FFI_TYPE_DOUBLE:
396 case FFI_TYPE_SINT64:
397 case FFI_TYPE_UINT64:
398 cif->flags += (unsigned) cif->rtype->type << 24;
399 break;
401 default:
402 cif->flags += FFI_TYPE_INT << 24;
403 break;
406 return FFI_OK;
409 /*@-declundef@*/
410 /*@-exportheader@*/
411 extern void ffi_call_SYSV(void (*)(char *, extended_cif *),
412 /*@out@*/ extended_cif *,
413 unsigned, unsigned,
414 /*@out@*/ unsigned *,
415 void (*fn)());
416 /*@=declundef@*/
417 /*@=exportheader@*/
419 void ffi_call(/*@dependent@*/ ffi_cif *cif,
420 void (*fn)(),
421 /*@out@*/ void *rvalue,
422 /*@dependent@*/ void **avalue)
424 extended_cif ecif;
425 UINT64 trvalue;
427 ecif.cif = cif;
428 ecif.avalue = avalue;
430 /* If the return value is a struct and we don't have a return */
431 /* value address then we need to make one */
433 if (cif->rtype->type == FFI_TYPE_STRUCT
434 && return_type (cif->rtype) != FFI_TYPE_STRUCT)
435 ecif.rvalue = &trvalue;
436 else if ((rvalue == NULL) &&
437 (cif->rtype->type == FFI_TYPE_STRUCT))
439 /*@-sysunrecog@*/
440 ecif.rvalue = alloca(cif->rtype->size);
441 /*@=sysunrecog@*/
443 else
444 ecif.rvalue = rvalue;
446 switch (cif->abi)
448 case FFI_SYSV:
449 /*@-usedef@*/
450 ffi_call_SYSV(ffi_prep_args, &ecif, cif->bytes,
451 cif->flags, ecif.rvalue, fn);
452 /*@=usedef@*/
453 break;
454 default:
455 FFI_ASSERT(0);
456 break;
459 if (rvalue
460 && cif->rtype->type == FFI_TYPE_STRUCT
461 && return_type (cif->rtype) != FFI_TYPE_STRUCT)
462 memcpy (rvalue, &trvalue, cif->rtype->size);
465 extern void ffi_closure_SYSV (void);
466 #if defined(__SH4__)
467 extern void __ic_invalidate (void *line);
468 #endif
470 ffi_status
471 ffi_prep_closure (ffi_closure* closure,
472 ffi_cif* cif,
473 void (*fun)(ffi_cif*, void*, void**, void*),
474 void *user_data)
476 unsigned int *tramp;
477 unsigned short insn;
479 FFI_ASSERT (cif->abi == FFI_GCC_SYSV);
481 tramp = (unsigned int *) &closure->tramp[0];
482 /* Set T bit if the function returns a struct pointed with R2. */
483 insn = (return_type (cif->rtype) == FFI_TYPE_STRUCT
484 ? 0x0018 /* sett */
485 : 0x0008 /* clrt */);
487 #ifdef __LITTLE_ENDIAN__
488 tramp[0] = 0xd301d102;
489 tramp[1] = 0x0000412b | (insn << 16);
490 #else
491 tramp[0] = 0xd102d301;
492 tramp[1] = 0x412b0000 | insn;
493 #endif
494 *(void **) &tramp[2] = (void *)closure; /* ctx */
495 *(void **) &tramp[3] = (void *)ffi_closure_SYSV; /* funaddr */
497 closure->cif = cif;
498 closure->fun = fun;
499 closure->user_data = user_data;
501 #if defined(__SH4__)
502 /* Flush the icache. */
503 __ic_invalidate(&closure->tramp[0]);
504 #endif
506 return FFI_OK;
509 /* Basically the trampoline invokes ffi_closure_SYSV, and on
510 * entry, r3 holds the address of the closure.
511 * After storing the registers that could possibly contain
512 * parameters to be passed into the stack frame and setting
513 * up space for a return value, ffi_closure_SYSV invokes the
514 * following helper function to do most of the work.
517 #ifdef __LITTLE_ENDIAN__
518 #define OFS_INT8 0
519 #define OFS_INT16 0
520 #else
521 #define OFS_INT8 3
522 #define OFS_INT16 2
523 #endif
526 ffi_closure_helper_SYSV (ffi_closure *closure, void *rvalue,
527 unsigned long *pgr, unsigned long *pfr,
528 unsigned long *pst)
530 void **avalue;
531 ffi_type **p_arg;
532 int i, avn;
533 int ireg, greg = 0;
534 #if defined(__SH4__)
535 int freg = 0;
536 #endif
537 ffi_cif *cif;
538 double temp;
540 cif = closure->cif;
541 avalue = alloca(cif->nargs * sizeof(void *));
543 /* Copy the caller's structure return value address so that the closure
544 returns the data directly to the caller. */
545 if (cif->rtype->type == FFI_TYPE_STRUCT && STRUCT_VALUE_ADDRESS_WITH_ARG)
547 rvalue = *pgr++;
548 ireg = 1;
550 else
551 ireg = 0;
553 cif = closure->cif;
554 greg = ireg;
555 avn = cif->nargs;
557 /* Grab the addresses of the arguments from the stack frame. */
558 for (i = 0, p_arg = cif->arg_types; i < avn; i++, p_arg++)
560 size_t z;
562 z = (*p_arg)->size;
563 if (z < sizeof(int))
565 if (greg++ >= NGREGARG)
566 continue;
568 z = sizeof(int);
569 switch ((*p_arg)->type)
571 case FFI_TYPE_SINT8:
572 case FFI_TYPE_UINT8:
573 avalue[i] = (((char *)pgr) + OFS_INT8);
574 break;
576 case FFI_TYPE_SINT16:
577 case FFI_TYPE_UINT16:
578 avalue[i] = (((char *)pgr) + OFS_INT16);
579 break;
581 case FFI_TYPE_STRUCT:
582 avalue[i] = pgr;
583 break;
585 default:
586 FFI_ASSERT(0);
588 pgr++;
590 else if (z == sizeof(int))
592 #if defined(__SH4__)
593 if ((*p_arg)->type == FFI_TYPE_FLOAT)
595 if (freg++ >= NFREGARG)
596 continue;
597 avalue[i] = pfr;
598 pfr++;
600 else
601 #endif
603 if (greg++ >= NGREGARG)
604 continue;
605 avalue[i] = pgr;
606 pgr++;
609 #if defined(__SH4__)
610 else if ((*p_arg)->type == FFI_TYPE_DOUBLE)
612 if (freg + 1 >= NFREGARG)
613 continue;
614 freg = (freg + 1) & ~1;
615 freg += 2;
616 avalue[i] = pfr;
617 pfr += 2;
619 #endif
620 else
622 int n = (z + sizeof (int) - 1) / sizeof (int);
623 #if defined(__SH4__)
624 if (greg + n - 1 >= NGREGARG)
625 continue;
626 #else
627 if (greg >= NGREGARG)
628 continue;
629 #endif
630 greg += n;
631 avalue[i] = pgr;
632 pgr += n;
636 greg = ireg;
637 #if defined(__SH4__)
638 freg = 0;
639 #endif
641 for (i = 0, p_arg = cif->arg_types; i < avn; i++, p_arg++)
643 size_t z;
645 z = (*p_arg)->size;
646 if (z < sizeof(int))
648 if (greg++ < NGREGARG)
649 continue;
651 z = sizeof(int);
652 switch ((*p_arg)->type)
654 case FFI_TYPE_SINT8:
655 case FFI_TYPE_UINT8:
656 avalue[i] = (((char *)pst) + OFS_INT8);
657 break;
659 case FFI_TYPE_SINT16:
660 case FFI_TYPE_UINT16:
661 avalue[i] = (((char *)pst) + OFS_INT16);
662 break;
664 case FFI_TYPE_STRUCT:
665 avalue[i] = pst;
666 break;
668 default:
669 FFI_ASSERT(0);
671 pst++;
673 else if (z == sizeof(int))
675 #if defined(__SH4__)
676 if ((*p_arg)->type == FFI_TYPE_FLOAT)
678 if (freg++ < NFREGARG)
679 continue;
681 else
682 #endif
684 if (greg++ < NGREGARG)
685 continue;
687 avalue[i] = pst;
688 pst++;
690 #if defined(__SH4__)
691 else if ((*p_arg)->type == FFI_TYPE_DOUBLE)
693 if (freg + 1 < NFREGARG)
695 freg = (freg + 1) & ~1;
696 freg += 2;
697 continue;
699 avalue[i] = pst;
700 pst += 2;
702 #endif
703 else
705 int n = (z + sizeof (int) - 1) / sizeof (int);
706 if (greg + n - 1 < NGREGARG)
708 greg += n;
709 continue;
711 #if (! defined(__SH4__))
712 else if (greg < NGREGARG)
714 greg += n;
715 pst += greg - NGREGARG;
716 continue;
718 #endif
719 avalue[i] = pst;
720 pst += n;
724 (closure->fun) (cif, rvalue, avalue, closure->user_data);
726 /* Tell ffi_closure_SYSV how to perform return type promotions. */
727 return return_type (cif->rtype);