* configure.ac: Bump version to 2.99.7.
[libffi.git] / libffi / src / sh / ffi.c
1 /* -----------------------------------------------------------------------
2 ffi.c - Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007 Kaz Kojima
3
4 SuperH Foreign Function Interface
5
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:
13
14 The above copyright notice and this permission notice shall be included
15 in all copies or substantial portions of the Software.
16
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 ----------------------------------------------------------------------- */
26
27 #include <ffi.h>
28 #include <ffi_common.h>
29
30 #include <stdlib.h>
31
32 #define NGREGARG 4
33 #if defined(__SH4__)
34 #define NFREGARG 8
35 #endif
36
37 #if defined(__HITACHI__)
38 #define STRUCT_VALUE_ADDRESS_WITH_ARG 1
39 #else
40 #define STRUCT_VALUE_ADDRESS_WITH_ARG 0
41 #endif
42
43 /* If the structure has essentialy an unique element, return its type. */
44 static int
45 simple_type (ffi_type *arg)
46 {
47 if (arg->type != FFI_TYPE_STRUCT)
48 return arg->type;
49 else if (arg->elements[1])
50 return FFI_TYPE_STRUCT;
51
52 return simple_type (arg->elements[0]);
53 }
54
55 static int
56 return_type (ffi_type *arg)
57 {
58 unsigned short type;
59
60 if (arg->type != FFI_TYPE_STRUCT)
61 return arg->type;
62
63 type = simple_type (arg->elements[0]);
64 if (! arg->elements[1])
65 {
66 switch (type)
67 {
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;
75
76 default:
77 return type;
78 }
79 }
80
81 /* gcc uses r0/r1 pair for some kind of structures. */
82 if (arg->size <= 2 * sizeof (int))
83 {
84 int i = 0;
85 ffi_type *e;
86
87 while ((e = arg->elements[i++]))
88 {
89 type = simple_type (e);
90 switch (type)
91 {
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;
97
98 default:
99 break;
100 }
101 }
102 }
103
104 return FFI_TYPE_STRUCT;
105 }
106
107 /* ffi_prep_args is called by the assembly routine once stack space
108 has been allocated for the function's arguments */
109
110 void ffi_prep_args(char *stack, extended_cif *ecif)
111 {
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
122
123 tmp = 0;
124 argp = stack;
125
126 if (return_type (ecif->cif->rtype) == FFI_TYPE_STRUCT)
127 {
128 *(void **) argp = ecif->rvalue;
129 argp += 4;
130 ireg = STRUCT_VALUE_ADDRESS_WITH_ARG ? 1 : 0;
131 }
132 else
133 ireg = 0;
134
135 /* Set arguments for registers. */
136 greg = ireg;
137 avn = ecif->cif->nargs;
138 p_argv = ecif->avalue;
139
140 for (i = 0, p_arg = ecif->cif->arg_types; i < avn; i++, p_arg++, p_argv++)
141 {
142 size_t z;
143
144 z = (*p_arg)->size;
145 if (z < sizeof(int))
146 {
147 if (greg++ >= NGREGARG)
148 continue;
149
150 z = sizeof(int);
151 switch ((*p_arg)->type)
152 {
153 case FFI_TYPE_SINT8:
154 *(signed int *) argp = (signed int)*(SINT8 *)(* p_argv);
155 break;
156
157 case FFI_TYPE_UINT8:
158 *(unsigned int *) argp = (unsigned int)*(UINT8 *)(* p_argv);
159 break;
160
161 case FFI_TYPE_SINT16:
162 *(signed int *) argp = (signed int)*(SINT16 *)(* p_argv);
163 break;
164
165 case FFI_TYPE_UINT16:
166 *(unsigned int *) argp = (unsigned int)*(UINT16 *)(* p_argv);
167 break;
168
169 case FFI_TYPE_STRUCT:
170 *(unsigned int *) argp = (unsigned int)*(UINT32 *)(* p_argv);
171 break;
172
173 default:
174 FFI_ASSERT(0);
175 }
176 argp += z;
177 }
178 else if (z == sizeof(int))
179 {
180 #if defined(__SH4__)
181 if ((*p_arg)->type == FFI_TYPE_FLOAT)
182 {
183 if (freg++ >= NFREGARG)
184 continue;
185 }
186 else
187 #endif
188 {
189 if (greg++ >= NGREGARG)
190 continue;
191 }
192 *(unsigned int *) argp = (unsigned int)*(UINT32 *)(* p_argv);
193 argp += z;
194 }
195 #if defined(__SH4__)
196 else if ((*p_arg)->type == FFI_TYPE_DOUBLE)
197 {
198 if (freg + 1 >= NFREGARG)
199 continue;
200 freg = (freg + 1) & ~1;
201 freg += 2;
202 memcpy (argp, *p_argv, z);
203 argp += z;
204 }
205 #endif
206 else
207 {
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);
219 }
220 }
221
222 /* Set arguments on stack. */
223 greg = ireg;
224 #if defined(__SH4__)
225 freg = 0;
226 #endif
227 p_argv = ecif->avalue;
228
229 for (i = 0, p_arg = ecif->cif->arg_types; i < avn; i++, p_arg++, p_argv++)
230 {
231 size_t z;
232
233 z = (*p_arg)->size;
234 if (z < sizeof(int))
235 {
236 if (greg++ < NGREGARG)
237 continue;
238
239 z = sizeof(int);
240 switch ((*p_arg)->type)
241 {
242 case FFI_TYPE_SINT8:
243 *(signed int *) argp = (signed int)*(SINT8 *)(* p_argv);
244 break;
245
246 case FFI_TYPE_UINT8:
247 *(unsigned int *) argp = (unsigned int)*(UINT8 *)(* p_argv);
248 break;
249
250 case FFI_TYPE_SINT16:
251 *(signed int *) argp = (signed int)*(SINT16 *)(* p_argv);
252 break;
253
254 case FFI_TYPE_UINT16:
255 *(unsigned int *) argp = (unsigned int)*(UINT16 *)(* p_argv);
256 break;
257
258 case FFI_TYPE_STRUCT:
259 *(unsigned int *) argp = (unsigned int)*(UINT32 *)(* p_argv);
260 break;
261
262 default:
263 FFI_ASSERT(0);
264 }
265 argp += z;
266 }
267 else if (z == sizeof(int))
268 {
269 #if defined(__SH4__)
270 if ((*p_arg)->type == FFI_TYPE_FLOAT)
271 {
272 if (freg++ < NFREGARG)
273 continue;
274 }
275 else
276 #endif
277 {
278 if (greg++ < NGREGARG)
279 continue;
280 }
281 *(unsigned int *) argp = (unsigned int)*(UINT32 *)(* p_argv);
282 argp += z;
283 }
284 #if defined(__SH4__)
285 else if ((*p_arg)->type == FFI_TYPE_DOUBLE)
286 {
287 if (freg + 1 < NFREGARG)
288 {
289 freg = (freg + 1) & ~1;
290 freg += 2;
291 continue;
292 }
293 memcpy (argp, *p_argv, z);
294 argp += z;
295 }
296 #endif
297 else
298 {
299 int n = (z + sizeof (int) - 1) / sizeof (int);
300 if (greg + n - 1 < NGREGARG)
301 {
302 greg += n;
303 continue;
304 }
305 #if (! defined(__SH4__))
306 else if (greg < NGREGARG)
307 {
308 greg = NGREGARG;
309 continue;
310 }
311 #endif
312 memcpy (argp, *p_argv, z);
313 argp += n * sizeof (int);
314 }
315 }
316
317 return;
318 }
319
320 /* Perform machine dependent cif processing */
321 ffi_status ffi_prep_cif_machdep(ffi_cif *cif)
322 {
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
330
331 cif->flags = 0;
332
333 greg = ((return_type (cif->rtype) == FFI_TYPE_STRUCT) &&
334 STRUCT_VALUE_ADDRESS_WITH_ARG) ? 1 : 0;
335
336 #if defined(__SH4__)
337 for (i = j = 0; i < cif->nargs && j < 12; i++)
338 {
339 type = (cif->arg_types)[i]->type;
340 switch (type)
341 {
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;
349
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;
358
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;
368 }
369 }
370 #else
371 for (i = j = 0; i < cif->nargs && j < 4; i++)
372 {
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++);
382 }
383 #endif
384
385 /* Set the return type flag */
386 switch (cif->rtype->type)
387 {
388 case FFI_TYPE_STRUCT:
389 cif->flags += (unsigned) (return_type (cif->rtype)) << 24;
390 break;
391
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;
399
400 default:
401 cif->flags += FFI_TYPE_INT << 24;
402 break;
403 }
404
405 return FFI_OK;
406 }
407
408 extern void ffi_call_SYSV(void (*)(char *, extended_cif *), extended_cif *,
409 unsigned, unsigned, unsigned *, void (*fn)());
410
411 void ffi_call(ffi_cif *cif, void (*fn)(), void *rvalue, void **avalue)
412 {
413 extended_cif ecif;
414 UINT64 trvalue;
415
416 ecif.cif = cif;
417 ecif.avalue = avalue;
418
419 /* If the return value is a struct and we don't have a return */
420 /* value address then we need to make one */
421
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))
427 {
428 ecif.rvalue = alloca(cif->rtype->size);
429 }
430 else
431 ecif.rvalue = rvalue;
432
433 switch (cif->abi)
434 {
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;
442 }
443
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);
448 }
449
450 extern void ffi_closure_SYSV (void);
451 #if defined(__SH4__)
452 extern void __ic_invalidate (void *line);
453 #endif
454
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)
461 {
462 unsigned int *tramp;
463 unsigned short insn;
464
465 FFI_ASSERT (cif->abi == FFI_GCC_SYSV);
466
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 */);
472
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 */
482
483 closure->cif = cif;
484 closure->fun = fun;
485 closure->user_data = user_data;
486
487 #if defined(__SH4__)
488 /* Flush the icache. */
489 __ic_invalidate(codeloc);
490 #endif
491
492 return FFI_OK;
493 }
494
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.
501 */
502
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
510
511 int
512 ffi_closure_helper_SYSV (ffi_closure *closure, void *rvalue,
513 unsigned long *pgr, unsigned long *pfr,
514 unsigned long *pst)
515 {
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;
524
525 cif = closure->cif;
526 avalue = alloca(cif->nargs * sizeof(void *));
527
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)
531 {
532 rvalue = (void *) *pgr++;
533 ireg = 1;
534 }
535 else
536 ireg = 0;
537
538 cif = closure->cif;
539 greg = ireg;
540 avn = cif->nargs;
541
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++)
544 {
545 size_t z;
546
547 z = (*p_arg)->size;
548 if (z < sizeof(int))
549 {
550 if (greg++ >= NGREGARG)
551 continue;
552
553 z = sizeof(int);
554 switch ((*p_arg)->type)
555 {
556 case FFI_TYPE_SINT8:
557 case FFI_TYPE_UINT8:
558 avalue[i] = (((char *)pgr) + OFS_INT8);
559 break;
560
561 case FFI_TYPE_SINT16:
562 case FFI_TYPE_UINT16:
563 avalue[i] = (((char *)pgr) + OFS_INT16);
564 break;
565
566 case FFI_TYPE_STRUCT:
567 avalue[i] = pgr;
568 break;
569
570 default:
571 FFI_ASSERT(0);
572 }
573 pgr++;
574 }
575 else if (z == sizeof(int))
576 {
577 #if defined(__SH4__)
578 if ((*p_arg)->type == FFI_TYPE_FLOAT)
579 {
580 if (freg++ >= NFREGARG)
581 continue;
582 avalue[i] = pfr;
583 pfr++;
584 }
585 else
586 #endif
587 {
588 if (greg++ >= NGREGARG)
589 continue;
590 avalue[i] = pgr;
591 pgr++;
592 }
593 }
594 #if defined(__SH4__)
595 else if ((*p_arg)->type == FFI_TYPE_DOUBLE)
596 {
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;
605 }
606 #endif
607 else
608 {
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;
620 }
621 }
622
623 greg = ireg;
624 #if defined(__SH4__)
625 freg = 0;
626 #endif
627
628 for (i = 0, p_arg = cif->arg_types; i < avn; i++, p_arg++)
629 {
630 size_t z;
631
632 z = (*p_arg)->size;
633 if (z < sizeof(int))
634 {
635 if (greg++ < NGREGARG)
636 continue;
637
638 z = sizeof(int);
639 switch ((*p_arg)->type)
640 {
641 case FFI_TYPE_SINT8:
642 case FFI_TYPE_UINT8:
643 avalue[i] = (((char *)pst) + OFS_INT8);
644 break;
645
646 case FFI_TYPE_SINT16:
647 case FFI_TYPE_UINT16:
648 avalue[i] = (((char *)pst) + OFS_INT16);
649 break;
650
651 case FFI_TYPE_STRUCT:
652 avalue[i] = pst;
653 break;
654
655 default:
656 FFI_ASSERT(0);
657 }
658 pst++;
659 }
660 else if (z == sizeof(int))
661 {
662 #if defined(__SH4__)
663 if ((*p_arg)->type == FFI_TYPE_FLOAT)
664 {
665 if (freg++ < NFREGARG)
666 continue;
667 }
668 else
669 #endif
670 {
671 if (greg++ < NGREGARG)
672 continue;
673 }
674 avalue[i] = pst;
675 pst++;
676 }
677 #if defined(__SH4__)
678 else if ((*p_arg)->type == FFI_TYPE_DOUBLE)
679 {
680 if (freg + 1 < NFREGARG)
681 {
682 freg = (freg + 1) & ~1;
683 freg += 2;
684 continue;
685 }
686 avalue[i] = pst;
687 pst += 2;
688 }
689 #endif
690 else
691 {
692 int n = (z + sizeof (int) - 1) / sizeof (int);
693 if (greg + n - 1 < NGREGARG)
694 {
695 greg += n;
696 continue;
697 }
698 #if (! defined(__SH4__))
699 else if (greg < NGREGARG)
700 {
701 greg += n;
702 pst += greg - NGREGARG;
703 continue;
704 }
705 #endif
706 avalue[i] = pst;
707 pst += n;
708 }
709 }
710
711 (closure->fun) (cif, rvalue, avalue, closure->user_data);
712
713 /* Tell ffi_closure_SYSV how to perform return type promotions. */
714 return return_type (cif->rtype);
715 }