1 /* -----------------------------------------------------------------------
2 ffi.c - Copyright (c) 2011 Anthony Green
3 Copyright (c) 1996, 2003-2004, 2007-2008 Red Hat, Inc.
5 SPARC Foreign Function Interface
7 Permission is hereby granted, free of charge, to any person obtaining
8 a copy of this software and associated documentation files (the
9 ``Software''), to deal in the Software without restriction, including
10 without limitation the rights to use, copy, modify, merge, publish,
11 distribute, sublicense, and/or sell copies of the Software, and to
12 permit persons to whom the Software is furnished to do so, subject to
13 the following conditions:
15 The above copyright notice and this permission notice shall be included
16 in all copies or substantial portions of the Software.
18 THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND,
19 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
21 NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
22 HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
23 WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
25 DEALINGS IN THE SOFTWARE.
26 ----------------------------------------------------------------------- */
29 #include <ffi_common.h>
34 /* ffi_prep_args is called by the assembly routine once stack space
35 has been allocated for the function's arguments */
37 void ffi_prep_args_v8(char *stack, extended_cif *ecif)
44 /* Skip 16 words for the window save area */
45 argp = stack + 16*sizeof(int);
47 /* This should only really be done when we are returning a structure,
48 however, it's faster just to do it all the time...
50 if ( ecif->cif->rtype->type == FFI_TYPE_STRUCT ) */
51 *(int *) argp = (long)ecif->rvalue;
53 /* And 1 word for the structure return value. */
57 /* Purify will probably complain in our assembly routine, unless we
58 zero out this memory. */
68 p_argv = ecif->avalue;
70 for (i = ecif->cif->nargs, p_arg = ecif->cif->arg_types; i; i--, p_arg++)
74 if ((*p_arg)->type == FFI_TYPE_STRUCT
75 #if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
76 || (*p_arg)->type == FFI_TYPE_LONGDOUBLE
80 *(unsigned int *) argp = (unsigned long)(* p_argv);
89 switch ((*p_arg)->type)
92 *(signed int *) argp = *(SINT8 *)(* p_argv);
96 *(unsigned int *) argp = *(UINT8 *)(* p_argv);
100 *(signed int *) argp = *(SINT16 *)(* p_argv);
103 case FFI_TYPE_UINT16:
104 *(unsigned int *) argp = *(UINT16 *)(* p_argv);
113 memcpy(argp, *p_argv, z);
123 int ffi_prep_args_v9(char *stack, extended_cif *ecif)
133 /* Skip 16 words for the window save area */
134 argp = stack + 16*sizeof(long long);
137 /* Purify will probably complain in our assembly routine, unless we
138 zero out this memory. */
140 ((long long*)argp)[0] = 0;
141 ((long long*)argp)[1] = 0;
142 ((long long*)argp)[2] = 0;
143 ((long long*)argp)[3] = 0;
144 ((long long*)argp)[4] = 0;
145 ((long long*)argp)[5] = 0;
148 p_argv = ecif->avalue;
150 if (ecif->cif->rtype->type == FFI_TYPE_STRUCT &&
151 ecif->cif->rtype->size > 32)
153 *(unsigned long long *) argp = (unsigned long)ecif->rvalue;
154 argp += sizeof(long long);
158 for (i = 0, p_arg = ecif->cif->arg_types; i < ecif->cif->nargs;
164 switch ((*p_arg)->type)
166 case FFI_TYPE_STRUCT:
169 /* For structures larger than 16 bytes we pass reference. */
170 *(unsigned long long *) argp = (unsigned long)* p_argv;
171 argp += sizeof(long long);
178 case FFI_TYPE_DOUBLE:
179 #if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
180 case FFI_TYPE_LONGDOUBLE:
182 ret = 1; /* We should promote into FP regs as well as integer. */
185 if (z < sizeof(long long))
187 switch ((*p_arg)->type)
190 *(signed long long *) argp = *(SINT8 *)(* p_argv);
194 *(unsigned long long *) argp = *(UINT8 *)(* p_argv);
197 case FFI_TYPE_SINT16:
198 *(signed long long *) argp = *(SINT16 *)(* p_argv);
201 case FFI_TYPE_UINT16:
202 *(unsigned long long *) argp = *(UINT16 *)(* p_argv);
205 case FFI_TYPE_SINT32:
206 *(signed long long *) argp = *(SINT32 *)(* p_argv);
209 case FFI_TYPE_UINT32:
210 *(unsigned long long *) argp = *(UINT32 *)(* p_argv);
214 *(float *) (argp + 4) = *(FLOAT32 *)(* p_argv); /* Right justify */
217 case FFI_TYPE_STRUCT:
218 memcpy(argp, *p_argv, z);
224 z = sizeof(long long);
227 else if (z == sizeof(long long))
229 memcpy(argp, *p_argv, z);
230 z = sizeof(long long);
235 if ((tmp & 1) && (*p_arg)->alignment > 8)
238 argp += sizeof(long long);
240 memcpy(argp, *p_argv, z);
241 z = 2 * sizeof(long long);
251 /* Perform machine dependent cif processing */
252 ffi_status ffi_prep_cif_machdep(ffi_cif *cif)
256 if (cif->abi != FFI_V9)
260 /* If we are returning a struct, this will already have been added.
261 Otherwise we need to add it because it's always got to be there! */
263 if (cif->rtype->type != FFI_TYPE_STRUCT)
264 cif->bytes += wordsize;
266 /* sparc call frames require that space is allocated for 6 args,
267 even if they aren't used. Make that space if necessary. */
269 if (cif->bytes < 4*6+4)
276 /* sparc call frames require that space is allocated for 6 args,
277 even if they aren't used. Make that space if necessary. */
279 if (cif->bytes < 8*6)
283 /* Adjust cif->bytes. to include 16 words for the window save area,
284 and maybe the struct/union return pointer area, */
286 cif->bytes += 16 * wordsize;
288 /* The stack must be 2 word aligned, so round bytes up
291 cif->bytes = ALIGN(cif->bytes, 2 * wordsize);
293 /* Set the return type flag */
294 switch (cif->rtype->type)
298 case FFI_TYPE_DOUBLE:
299 #if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
300 case FFI_TYPE_LONGDOUBLE:
302 cif->flags = cif->rtype->type;
305 case FFI_TYPE_STRUCT:
306 if (cif->abi == FFI_V9 && cif->rtype->size > 32)
307 cif->flags = FFI_TYPE_VOID;
309 cif->flags = FFI_TYPE_STRUCT;
314 case FFI_TYPE_SINT16:
315 case FFI_TYPE_UINT16:
316 if (cif->abi == FFI_V9)
317 cif->flags = FFI_TYPE_INT;
319 cif->flags = cif->rtype->type;
322 case FFI_TYPE_SINT64:
323 case FFI_TYPE_UINT64:
324 if (cif->abi == FFI_V9)
325 cif->flags = FFI_TYPE_INT;
327 cif->flags = FFI_TYPE_SINT64;
331 cif->flags = FFI_TYPE_INT;
337 int ffi_v9_layout_struct(ffi_type *arg, int off, char *ret, char *intg, char *flt)
339 ffi_type **ptr = &arg->elements[0];
343 if (off & ((*ptr)->alignment - 1))
344 off = ALIGN(off, (*ptr)->alignment);
346 switch ((*ptr)->type)
348 case FFI_TYPE_STRUCT:
349 off = ffi_v9_layout_struct(*ptr, off, ret, intg, flt);
350 off = ALIGN(off, FFI_SIZEOF_ARG);
353 case FFI_TYPE_DOUBLE:
354 #if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
355 case FFI_TYPE_LONGDOUBLE:
357 memmove(ret + off, flt + off, (*ptr)->size);
361 memmove(ret + off, intg + off, (*ptr)->size);
372 extern int ffi_call_v9(void *, extended_cif *, unsigned,
373 unsigned, unsigned *, void (*fn)(void));
375 extern int ffi_call_v8(void *, extended_cif *, unsigned,
376 unsigned, unsigned *, void (*fn)(void));
379 void ffi_call(ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue)
385 ecif.avalue = avalue;
387 /* If the return value is a struct and we don't have a return */
388 /* value address then we need to make one */
390 ecif.rvalue = rvalue;
391 if (cif->rtype->type == FFI_TYPE_STRUCT)
393 if (cif->rtype->size <= 32)
399 ecif.rvalue = alloca(cif->rtype->size);
407 /* We don't yet support calling 32bit code from 64bit */
410 if (rvalue && (cif->rtype->type == FFI_TYPE_STRUCT
411 #if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
412 || cif->flags == FFI_TYPE_LONGDOUBLE
416 /* For v8, we need an "unimp" with size of returning struct */
417 /* behind "call", so we alloc some executable space for it. */
418 /* l7 is used, we need to make sure v8.S doesn't use %l7. */
419 unsigned int *call_struct = NULL;
420 ffi_closure_alloc(32, &call_struct);
423 unsigned long f = (unsigned long)fn;
424 call_struct[0] = 0xae10001f; /* mov %i7, %l7 */
425 call_struct[1] = 0xbe10000f; /* mov %o7, %i7 */
426 call_struct[2] = 0x03000000 | f >> 10; /* sethi %hi(fn), %g1 */
427 call_struct[3] = 0x9fc06000 | (f & 0x3ff); /* jmp %g1+%lo(fn), %o7 */
428 call_struct[4] = 0x01000000; /* nop */
429 if (cif->rtype->size < 0x7f)
430 call_struct[5] = cif->rtype->size; /* unimp */
432 call_struct[5] = 0x01000000; /* nop */
433 call_struct[6] = 0x81c7e008; /* ret */
434 call_struct[7] = 0xbe100017; /* mov %l7, %i7 */
435 asm volatile ("iflush %0; iflush %0+8; iflush %0+16; iflush %0+24" : :
436 "r" (call_struct) : "memory");
437 /* SPARC v8 requires 5 instructions for flush to be visible */
438 asm volatile ("nop; nop; nop; nop; nop");
439 ffi_call_v8(ffi_prep_args_v8, &ecif, cif->bytes,
440 cif->flags, rvalue, call_struct);
441 ffi_closure_free(call_struct);
445 ffi_call_v8(ffi_prep_args_v8, &ecif, cif->bytes,
446 cif->flags, rvalue, fn);
451 ffi_call_v8(ffi_prep_args_v8, &ecif, cif->bytes,
452 cif->flags, rvalue, fn);
458 ffi_call_v9(ffi_prep_args_v9, &ecif, cif->bytes,
459 cif->flags, rval, fn);
460 if (rvalue && rval && cif->rtype->type == FFI_TYPE_STRUCT)
461 ffi_v9_layout_struct(cif->rtype, 0, (char *)rvalue, (char *)rval, ((char *)rval)+32);
475 extern void ffi_closure_v9(void);
477 extern void ffi_closure_v8(void);
481 ffi_prep_closure_loc (ffi_closure* closure,
483 void (*fun)(ffi_cif*, void*, void**, void*),
487 unsigned int *tramp = (unsigned int *) &closure->tramp[0];
490 /* Trampoline address is equal to the closure address. We take advantage
491 of that to reduce the trampoline size by 8 bytes. */
492 if (cif->abi != FFI_V9)
494 fn = (unsigned long) ffi_closure_v9;
495 tramp[0] = 0x83414000; /* rd %pc, %g1 */
496 tramp[1] = 0xca586010; /* ldx [%g1+16], %g5 */
497 tramp[2] = 0x81c14000; /* jmp %g5 */
498 tramp[3] = 0x01000000; /* nop */
499 *((unsigned long *) &tramp[4]) = fn;
501 unsigned long ctx = (unsigned long) codeloc;
502 if (cif->abi != FFI_V8)
504 fn = (unsigned long) ffi_closure_v8;
505 tramp[0] = 0x03000000 | fn >> 10; /* sethi %hi(fn), %g1 */
506 tramp[1] = 0x05000000 | ctx >> 10; /* sethi %hi(ctx), %g2 */
507 tramp[2] = 0x81c06000 | (fn & 0x3ff); /* jmp %g1+%lo(fn) */
508 tramp[3] = 0x8410a000 | (ctx & 0x3ff);/* or %g2, %lo(ctx) */
513 closure->user_data = user_data;
515 /* Flush the Icache. closure is 8 bytes aligned. */
517 asm volatile ("flush %0; flush %0+8" : : "r" (closure) : "memory");
519 asm volatile ("iflush %0; iflush %0+8" : : "r" (closure) : "memory");
520 /* SPARC v8 requires 5 instructions for flush to be visible */
521 asm volatile ("nop; nop; nop; nop; nop");
528 ffi_closure_sparc_inner_v8(ffi_closure *closure,
529 void *rvalue, unsigned long *gpr, unsigned long *scratch)
532 ffi_type **arg_types;
537 arg_types = cif->arg_types;
538 avalue = alloca(cif->nargs * sizeof(void *));
540 /* Copy the caller's structure return address so that the closure
541 returns the data directly to the caller. */
542 if (cif->flags == FFI_TYPE_STRUCT
543 #if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
544 || cif->flags == FFI_TYPE_LONGDOUBLE
547 rvalue = (void *) gpr[0];
549 /* Always skip the structure return address. */
552 /* Grab the addresses of the arguments from the stack frame. */
553 for (i = 0; i < cif->nargs; i++)
555 if (arg_types[i]->type == FFI_TYPE_STRUCT
556 #if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
557 || arg_types[i]->type == FFI_TYPE_LONGDOUBLE
561 /* Straight copy of invisible reference. */
562 avalue[i] = (void *)gpr[argn++];
564 else if ((arg_types[i]->type == FFI_TYPE_DOUBLE
565 || arg_types[i]->type == FFI_TYPE_SINT64
566 || arg_types[i]->type == FFI_TYPE_UINT64)
567 /* gpr is 8-byte aligned. */
570 /* Align on a 8-byte boundary. */
571 scratch[0] = gpr[argn];
572 scratch[1] = gpr[argn+1];
579 /* Always right-justify. */
580 argn += ALIGN(arg_types[i]->size, FFI_SIZEOF_ARG) / FFI_SIZEOF_ARG;
581 avalue[i] = ((char *) &gpr[argn]) - arg_types[i]->size;
585 /* Invoke the closure. */
586 (closure->fun) (cif, rvalue, avalue, closure->user_data);
588 /* Tell ffi_closure_sparc how to perform return type promotions. */
589 return cif->rtype->type;
593 ffi_closure_sparc_inner_v9(ffi_closure *closure,
594 void *rvalue, unsigned long *gpr, double *fpr)
597 ffi_type **arg_types;
599 int i, argn, fp_slot_max;
602 arg_types = cif->arg_types;
603 avalue = alloca(cif->nargs * sizeof(void *));
605 /* Copy the caller's structure return address so that the closure
606 returns the data directly to the caller. */
607 if (cif->flags == FFI_TYPE_VOID
608 && cif->rtype->type == FFI_TYPE_STRUCT)
610 rvalue = (void *) gpr[0];
611 /* Skip the structure return address. */
617 fp_slot_max = 16 - argn;
619 /* Grab the addresses of the arguments from the stack frame. */
620 for (i = 0; i < cif->nargs; i++)
622 if (arg_types[i]->type == FFI_TYPE_STRUCT)
624 if (arg_types[i]->size > 16)
626 /* Straight copy of invisible reference. */
627 avalue[i] = (void *)gpr[argn++];
632 ffi_v9_layout_struct(arg_types[i],
636 (char *) &fpr[argn]);
637 avalue[i] = &gpr[argn];
638 argn += ALIGN(arg_types[i]->size, FFI_SIZEOF_ARG) / FFI_SIZEOF_ARG;
644 argn += ALIGN(arg_types[i]->size, FFI_SIZEOF_ARG) / FFI_SIZEOF_ARG;
646 /* Align on a 16-byte boundary. */
647 #if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
648 if (arg_types[i]->type == FFI_TYPE_LONGDOUBLE && (argn % 2) != 0)
652 && (arg_types[i]->type == FFI_TYPE_FLOAT
653 || arg_types[i]->type == FFI_TYPE_DOUBLE
654 #if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
655 || arg_types[i]->type == FFI_TYPE_LONGDOUBLE
658 avalue[i] = ((char *) &fpr[argn]) - arg_types[i]->size;
660 avalue[i] = ((char *) &gpr[argn]) - arg_types[i]->size;
664 /* Invoke the closure. */
665 (closure->fun) (cif, rvalue, avalue, closure->user_data);
667 /* Tell ffi_closure_sparc how to perform return type promotions. */
668 return cif->rtype->type;