Merge from mainline (gomp-merge-2005-02-26).
[official-gcc.git] / libffi / src / sh / ffi.c
blob2045419df7cb79dfb3af1c567624f324b65d5bcd
1 /* -----------------------------------------------------------------------
2 ffi.c - Copyright (c) 2002, 2003, 2004 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 greg += n;
214 #else
215 if (greg >= NGREGARG)
216 continue;
217 else if (greg + n - 1 >= NGREGARG)
218 greg = NGREGARG;
219 else
220 greg += n;
221 #endif
222 memcpy (argp, *p_argv, z);
223 argp += n * sizeof (int);
227 /* Set arguments on stack. */
228 greg = ireg;
229 #if defined(__SH4__)
230 freg = 0;
231 #endif
232 p_argv = ecif->avalue;
234 for (i = 0, p_arg = ecif->cif->arg_types; i < avn; i++, p_arg++, p_argv++)
236 size_t z;
238 z = (*p_arg)->size;
239 if (z < sizeof(int))
241 if (greg++ < NGREGARG)
242 continue;
244 z = sizeof(int);
245 switch ((*p_arg)->type)
247 case FFI_TYPE_SINT8:
248 *(signed int *) argp = (signed int)*(SINT8 *)(* p_argv);
249 break;
251 case FFI_TYPE_UINT8:
252 *(unsigned int *) argp = (unsigned int)*(UINT8 *)(* p_argv);
253 break;
255 case FFI_TYPE_SINT16:
256 *(signed int *) argp = (signed int)*(SINT16 *)(* p_argv);
257 break;
259 case FFI_TYPE_UINT16:
260 *(unsigned int *) argp = (unsigned int)*(UINT16 *)(* p_argv);
261 break;
263 case FFI_TYPE_STRUCT:
264 *(unsigned int *) argp = (unsigned int)*(UINT32 *)(* p_argv);
265 break;
267 default:
268 FFI_ASSERT(0);
270 argp += z;
272 else if (z == sizeof(int))
274 #if defined(__SH4__)
275 if ((*p_arg)->type == FFI_TYPE_FLOAT)
277 if (freg++ < NFREGARG)
278 continue;
280 else
281 #endif
283 if (greg++ < NGREGARG)
284 continue;
286 *(unsigned int *) argp = (unsigned int)*(UINT32 *)(* p_argv);
287 argp += z;
289 #if defined(__SH4__)
290 else if ((*p_arg)->type == FFI_TYPE_DOUBLE)
292 if (freg + 1 < NFREGARG)
294 freg = (freg + 1) & ~1;
295 freg += 2;
296 continue;
298 memcpy (argp, *p_argv, z);
299 argp += z;
301 #endif
302 else
304 int n = (z + sizeof (int) - 1) / sizeof (int);
305 if (greg + n - 1 < NGREGARG)
307 greg += n;
308 continue;
310 #if (! defined(__SH4__))
311 else if (greg < NGREGARG)
313 greg = NGREGARG;
314 continue;
316 #endif
317 memcpy (argp, *p_argv, z);
318 argp += n * sizeof (int);
322 return;
325 /* Perform machine dependent cif processing */
326 ffi_status ffi_prep_cif_machdep(ffi_cif *cif)
328 int i, j;
329 int size, type;
330 int n, m;
331 int greg;
332 #if defined(__SH4__)
333 int freg = 0;
334 #endif
336 cif->flags = 0;
338 greg = ((return_type (cif->rtype) == FFI_TYPE_STRUCT) &&
339 STRUCT_VALUE_ADDRESS_WITH_ARG) ? 1 : 0;
341 #if defined(__SH4__)
342 for (i = j = 0; i < cif->nargs && j < 12; i++)
344 type = (cif->arg_types)[i]->type;
345 switch (type)
347 case FFI_TYPE_FLOAT:
348 if (freg >= NFREGARG)
349 continue;
350 freg++;
351 cif->flags += ((cif->arg_types)[i]->type) << (2 * j);
352 j++;
353 break;
355 case FFI_TYPE_DOUBLE:
356 if ((freg + 1) >= NFREGARG)
357 continue;
358 freg = (freg + 1) & ~1;
359 freg += 2;
360 cif->flags += ((cif->arg_types)[i]->type) << (2 * j);
361 j++;
362 break;
364 default:
365 size = (cif->arg_types)[i]->size;
366 n = (size + sizeof (int) - 1) / sizeof (int);
367 if (greg + n - 1 >= NGREGARG)
368 continue;
369 greg += n;
370 for (m = 0; m < n; m++)
371 cif->flags += FFI_TYPE_INT << (2 * j++);
372 break;
375 #else
376 for (i = j = 0; i < cif->nargs && j < 4; i++)
378 size = (cif->arg_types)[i]->size;
379 n = (size + sizeof (int) - 1) / sizeof (int);
380 if (greg >= NGREGARG)
381 continue;
382 else if (greg + n - 1 >= NGREGARG)
383 greg = NGREGARG;
384 else
385 greg += n;
386 for (m = 0; m < n; m++)
387 cif->flags += FFI_TYPE_INT << (2 * j++);
389 #endif
391 /* Set the return type flag */
392 switch (cif->rtype->type)
394 case FFI_TYPE_STRUCT:
395 cif->flags += (unsigned) (return_type (cif->rtype)) << 24;
396 break;
398 case FFI_TYPE_VOID:
399 case FFI_TYPE_FLOAT:
400 case FFI_TYPE_DOUBLE:
401 case FFI_TYPE_SINT64:
402 case FFI_TYPE_UINT64:
403 cif->flags += (unsigned) cif->rtype->type << 24;
404 break;
406 default:
407 cif->flags += FFI_TYPE_INT << 24;
408 break;
411 return FFI_OK;
414 /*@-declundef@*/
415 /*@-exportheader@*/
416 extern void ffi_call_SYSV(void (*)(char *, extended_cif *),
417 /*@out@*/ extended_cif *,
418 unsigned, unsigned,
419 /*@out@*/ unsigned *,
420 void (*fn)());
421 /*@=declundef@*/
422 /*@=exportheader@*/
424 void ffi_call(/*@dependent@*/ ffi_cif *cif,
425 void (*fn)(),
426 /*@out@*/ void *rvalue,
427 /*@dependent@*/ void **avalue)
429 extended_cif ecif;
431 ecif.cif = cif;
432 ecif.avalue = avalue;
434 /* If the return value is a struct and we don't have a return */
435 /* value address then we need to make one */
437 if ((rvalue == NULL) &&
438 (cif->rtype->type == FFI_TYPE_STRUCT))
440 /*@-sysunrecog@*/
441 ecif.rvalue = alloca(cif->rtype->size);
442 /*@=sysunrecog@*/
444 else
445 ecif.rvalue = rvalue;
448 switch (cif->abi)
450 case FFI_SYSV:
451 /*@-usedef@*/
452 ffi_call_SYSV(ffi_prep_args, &ecif, cif->bytes,
453 cif->flags, ecif.rvalue, fn);
454 /*@=usedef@*/
455 break;
456 default:
457 FFI_ASSERT(0);
458 break;
462 extern void ffi_closure_SYSV (void);
463 #if defined(__SH4__)
464 extern void __ic_invalidate (void *line);
465 #endif
467 ffi_status
468 ffi_prep_closure (ffi_closure* closure,
469 ffi_cif* cif,
470 void (*fun)(ffi_cif*, void*, void**, void*),
471 void *user_data)
473 unsigned int *tramp;
474 unsigned short insn;
476 FFI_ASSERT (cif->abi == FFI_GCC_SYSV);
478 tramp = (unsigned int *) &closure->tramp[0];
479 /* Set T bit if the function returns a struct pointed with R2. */
480 insn = (return_type (cif->rtype) == FFI_TYPE_STRUCT
481 ? 0x0018 /* sett */
482 : 0x0008 /* clrt */);
484 #ifdef __LITTLE_ENDIAN__
485 tramp[0] = 0xd301d102;
486 tramp[1] = 0x0000412b | (insn << 16);
487 #else
488 tramp[0] = 0xd102d301;
489 tramp[1] = 0x412b0000 | insn;
490 #endif
491 *(void **) &tramp[2] = (void *)closure; /* ctx */
492 *(void **) &tramp[3] = (void *)ffi_closure_SYSV; /* funaddr */
494 closure->cif = cif;
495 closure->fun = fun;
496 closure->user_data = user_data;
498 #if defined(__SH4__)
499 /* Flush the icache. */
500 __ic_invalidate(&closure->tramp[0]);
501 #endif
503 return FFI_OK;
506 /* Basically the trampoline invokes ffi_closure_SYSV, and on
507 * entry, r3 holds the address of the closure.
508 * After storing the registers that could possibly contain
509 * parameters to be passed into the stack frame and setting
510 * up space for a return value, ffi_closure_SYSV invokes the
511 * following helper function to do most of the work.
514 #ifdef __LITTLE_ENDIAN__
515 #define OFS_INT8 0
516 #define OFS_INT16 0
517 #else
518 #define OFS_INT8 3
519 #define OFS_INT16 2
520 #endif
523 ffi_closure_helper_SYSV (ffi_closure *closure, void *rvalue,
524 unsigned long *pgr, unsigned long *pfr,
525 unsigned long *pst)
527 void **avalue;
528 ffi_type **p_arg;
529 int i, avn;
530 int ireg, greg = 0;
531 #if defined(__SH4__)
532 int freg = 0;
533 #endif
534 ffi_cif *cif;
535 double temp;
537 cif = closure->cif;
538 avalue = alloca(cif->nargs * sizeof(void *));
540 /* Copy the caller's structure return value address so that the closure
541 returns the data directly to the caller. */
542 if (cif->rtype->type == FFI_TYPE_STRUCT && STRUCT_VALUE_ADDRESS_WITH_ARG)
544 rvalue = *pgr++;
545 ireg = 1;
547 else
548 ireg = 0;
550 cif = closure->cif;
551 greg = ireg;
552 avn = cif->nargs;
554 /* Grab the addresses of the arguments from the stack frame. */
555 for (i = 0, p_arg = cif->arg_types; i < avn; i++, p_arg++)
557 size_t z;
559 z = (*p_arg)->size;
560 if (z < sizeof(int))
562 if (greg++ >= NGREGARG)
563 continue;
565 z = sizeof(int);
566 switch ((*p_arg)->type)
568 case FFI_TYPE_SINT8:
569 case FFI_TYPE_UINT8:
570 avalue[i] = (((char *)pgr) + OFS_INT8);
571 break;
573 case FFI_TYPE_SINT16:
574 case FFI_TYPE_UINT16:
575 avalue[i] = (((char *)pgr) + OFS_INT16);
576 break;
578 case FFI_TYPE_STRUCT:
579 avalue[i] = pgr;
580 break;
582 default:
583 FFI_ASSERT(0);
585 pgr++;
587 else if (z == sizeof(int))
589 #if defined(__SH4__)
590 if ((*p_arg)->type == FFI_TYPE_FLOAT)
592 if (freg++ >= NFREGARG)
593 continue;
594 avalue[i] = pfr;
595 pfr++;
597 else
598 #endif
600 if (greg++ >= NGREGARG)
601 continue;
602 avalue[i] = pgr;
603 pgr++;
606 #if defined(__SH4__)
607 else if ((*p_arg)->type == FFI_TYPE_DOUBLE)
609 if (freg + 1 >= NFREGARG)
610 continue;
611 freg = (freg + 1) & ~1;
612 freg += 2;
613 avalue[i] = pfr;
614 pfr += 2;
616 #endif
617 else
619 int n = (z + sizeof (int) - 1) / sizeof (int);
620 #if defined(__SH4__)
621 if (greg + n - 1 >= NGREGARG)
622 continue;
623 greg += n;
624 #else
625 if (greg >= NGREGARG)
626 continue;
627 else if (greg + n - 1 >= NGREGARG)
628 greg = NGREGARG;
629 else
630 greg += n;
631 #endif
632 avalue[i] = pgr;
633 pgr += n;
637 greg = ireg;
638 #if defined(__SH4__)
639 freg = 0;
640 #endif
642 for (i = 0, p_arg = cif->arg_types; i < avn; i++, p_arg++)
644 size_t z;
646 z = (*p_arg)->size;
647 if (z < sizeof(int))
649 if (greg++ < NGREGARG)
650 continue;
652 z = sizeof(int);
653 switch ((*p_arg)->type)
655 case FFI_TYPE_SINT8:
656 case FFI_TYPE_UINT8:
657 avalue[i] = (((char *)pst) + OFS_INT8);
658 break;
660 case FFI_TYPE_SINT16:
661 case FFI_TYPE_UINT16:
662 avalue[i] = (((char *)pst) + OFS_INT16);
663 break;
665 case FFI_TYPE_STRUCT:
666 avalue[i] = pst;
667 break;
669 default:
670 FFI_ASSERT(0);
672 pst++;
674 else if (z == sizeof(int))
676 #if defined(__SH4__)
677 if ((*p_arg)->type == FFI_TYPE_FLOAT)
679 if (freg++ < NFREGARG)
680 continue;
682 else
683 #endif
685 if (greg++ < NGREGARG)
686 continue;
688 avalue[i] = pst;
689 pst++;
691 #if defined(__SH4__)
692 else if ((*p_arg)->type == FFI_TYPE_DOUBLE)
694 if (freg + 1 < NFREGARG)
696 freg = (freg + 1) & ~1;
697 freg += 2;
698 continue;
700 avalue[i] = pst;
701 pst += 2;
703 #endif
704 else
706 int n = (z + sizeof (int) - 1) / sizeof (int);
707 if (greg + n - 1 < NGREGARG)
709 greg += n;
710 continue;
712 #if (! defined(__SH4__))
713 else if (greg < NGREGARG)
715 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);