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 */
40 ffi_prep_args_v9(char *stack
, extended_cif
*ecif
)
50 /* Skip 16 words for the window save area */
51 argp
= stack
+ 16*sizeof(long long);
54 /* Purify will probably complain in our assembly routine, unless we
55 zero out this memory. */
57 ((long long*)argp
)[0] = 0;
58 ((long long*)argp
)[1] = 0;
59 ((long long*)argp
)[2] = 0;
60 ((long long*)argp
)[3] = 0;
61 ((long long*)argp
)[4] = 0;
62 ((long long*)argp
)[5] = 0;
65 p_argv
= ecif
->avalue
;
67 if (ecif
->cif
->rtype
->type
== FFI_TYPE_STRUCT
&&
68 ecif
->cif
->rtype
->size
> 32)
70 *(unsigned long long *) argp
= (unsigned long)ecif
->rvalue
;
71 argp
+= sizeof(long long);
75 for (i
= 0, p_arg
= ecif
->cif
->arg_types
; i
< ecif
->cif
->nargs
;
81 switch ((*p_arg
)->type
)
86 /* For structures larger than 16 bytes we pass reference. */
87 *(unsigned long long *) argp
= (unsigned long)* p_argv
;
88 argp
+= sizeof(long long);
96 #if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
97 case FFI_TYPE_LONGDOUBLE
:
99 ret
= 1; /* We should promote into FP regs as well as integer. */
102 if (z
< sizeof(long long))
104 switch ((*p_arg
)->type
)
107 *(signed long long *) argp
= *(SINT8
*)(* p_argv
);
111 *(unsigned long long *) argp
= *(UINT8
*)(* p_argv
);
114 case FFI_TYPE_SINT16
:
115 *(signed long long *) argp
= *(SINT16
*)(* p_argv
);
118 case FFI_TYPE_UINT16
:
119 *(unsigned long long *) argp
= *(UINT16
*)(* p_argv
);
122 case FFI_TYPE_SINT32
:
123 *(signed long long *) argp
= *(SINT32
*)(* p_argv
);
126 case FFI_TYPE_UINT32
:
127 *(unsigned long long *) argp
= *(UINT32
*)(* p_argv
);
131 *(float *) (argp
+ 4) = *(FLOAT32
*)(* p_argv
); /* Right justify */
134 case FFI_TYPE_STRUCT
:
135 memcpy(argp
, *p_argv
, z
);
141 z
= sizeof(long long);
144 else if (z
== sizeof(long long))
146 memcpy(argp
, *p_argv
, z
);
147 z
= sizeof(long long);
152 if ((tmp
& 1) && (*p_arg
)->alignment
> 8)
155 argp
+= sizeof(long long);
157 memcpy(argp
, *p_argv
, z
);
158 z
= 2 * sizeof(long long);
171 ffi_prep_args_v8(char *stack
, extended_cif
*ecif
)
178 /* Skip 16 words for the window save area */
179 argp
= stack
+ 16*sizeof(int);
181 /* This should only really be done when we are returning a structure,
182 however, it's faster just to do it all the time...
184 if ( ecif->cif->rtype->type == FFI_TYPE_STRUCT ) */
185 *(int *) argp
= (long)ecif
->rvalue
;
187 /* And 1 word for the structure return value. */
191 /* Purify will probably complain in our assembly routine, unless we
192 zero out this memory. */
202 p_argv
= ecif
->avalue
;
204 for (i
= ecif
->cif
->nargs
, p_arg
= ecif
->cif
->arg_types
; i
; i
--, p_arg
++)
208 if ((*p_arg
)->type
== FFI_TYPE_STRUCT
209 #if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
210 || (*p_arg
)->type
== FFI_TYPE_LONGDOUBLE
214 *(unsigned int *) argp
= (unsigned long)(* p_argv
);
223 switch ((*p_arg
)->type
)
226 *(signed int *) argp
= *(SINT8
*)(* p_argv
);
230 *(unsigned int *) argp
= *(UINT8
*)(* p_argv
);
233 case FFI_TYPE_SINT16
:
234 *(signed int *) argp
= *(SINT16
*)(* p_argv
);
237 case FFI_TYPE_UINT16
:
238 *(unsigned int *) argp
= *(UINT16
*)(* p_argv
);
247 memcpy(argp
, *p_argv
, z
);
259 /* Perform machine dependent cif processing */
262 ffi_status
ffi_prep_cif_machdep_core(ffi_cif
*cif
)
266 if (!V9_ABI_P (cif
->abi
))
270 /* If we are returning a struct, this will already have been added.
271 Otherwise we need to add it because it's always got to be there! */
273 if (cif
->rtype
->type
!= FFI_TYPE_STRUCT
)
274 cif
->bytes
+= wordsize
;
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
< 4*6+4)
286 /* sparc call frames require that space is allocated for 6 args,
287 even if they aren't used. Make that space if necessary. */
289 if (cif
->bytes
< 8*6)
293 /* Adjust cif->bytes. to include 16 words for the window save area,
294 and maybe the struct/union return pointer area, */
296 cif
->bytes
+= 16 * wordsize
;
298 /* The stack must be 2 word aligned, so round bytes up
301 cif
->bytes
= ALIGN(cif
->bytes
, 2 * wordsize
);
303 /* Set the return type flag */
304 switch (cif
->rtype
->type
)
308 case FFI_TYPE_DOUBLE
:
309 #if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
310 case FFI_TYPE_LONGDOUBLE
:
312 cif
->flags
= cif
->rtype
->type
;
315 case FFI_TYPE_STRUCT
:
316 if (V9_ABI_P (cif
->abi
) && cif
->rtype
->size
> 32)
317 cif
->flags
= FFI_TYPE_VOID
;
319 cif
->flags
= FFI_TYPE_STRUCT
;
324 case FFI_TYPE_SINT16
:
325 case FFI_TYPE_UINT16
:
326 if (V9_ABI_P (cif
->abi
))
327 cif
->flags
= FFI_TYPE_INT
;
329 cif
->flags
= cif
->rtype
->type
;
332 case FFI_TYPE_SINT64
:
333 case FFI_TYPE_UINT64
:
334 if (V9_ABI_P (cif
->abi
))
335 cif
->flags
= FFI_TYPE_INT
;
337 cif
->flags
= FFI_TYPE_SINT64
;
341 cif
->flags
= FFI_TYPE_INT
;
348 ffi_prep_cif_machdep(ffi_cif
*cif
)
351 if (cif
->abi
!= FFI_COMPAT_V9
)
352 cif
->nfixedargs
= cif
->nargs
;
354 return ffi_prep_cif_machdep_core (cif
);
358 ffi_prep_cif_machdep_var(ffi_cif
*cif
, unsigned int nfixedargs
,
359 unsigned int ntotalargs
)
362 if (cif
->abi
!= FFI_COMPAT_V9
)
363 cif
->nfixedargs
= nfixedargs
;
365 return ffi_prep_cif_machdep_core (cif
);
371 ffi_v9_layout_struct(ffi_type
*arg
, int off
, char *ret
, char *intg
, char *flt
)
373 ffi_type
**ptr
= &arg
->elements
[0];
377 if (off
& ((*ptr
)->alignment
- 1))
378 off
= ALIGN(off
, (*ptr
)->alignment
);
380 switch ((*ptr
)->type
)
382 case FFI_TYPE_STRUCT
:
383 off
= ffi_v9_layout_struct(*ptr
, off
, ret
, intg
, flt
);
384 off
= ALIGN(off
, FFI_SIZEOF_ARG
);
387 case FFI_TYPE_DOUBLE
:
388 #if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
389 case FFI_TYPE_LONGDOUBLE
:
391 memmove(ret
+ off
, flt
+ off
, (*ptr
)->size
);
395 memmove(ret
+ off
, intg
+ off
, (*ptr
)->size
);
407 extern int ffi_call_v9(void *, extended_cif
*, unsigned,
408 unsigned, unsigned *, void (*fn
)(void));
410 extern int ffi_call_v8(void *, extended_cif
*, unsigned,
411 unsigned, unsigned *, void (*fn
)(void));
415 ffi_call(ffi_cif
*cif
, void (*fn
)(void), void *rvalue
, void **avalue
)
423 ecif
.avalue
= avalue
;
424 ecif
.rvalue
= rvalue
;
426 /* If the return value is a struct and we don't have a return value address,
427 then we need to make one. */
428 if (cif
->rtype
->type
== FFI_TYPE_STRUCT
)
430 if (ecif
.rvalue
== NULL
)
431 ecif
.rvalue
= alloca(cif
->rtype
->size
);
434 if (cif
->rtype
->size
<= 32)
446 /* We don't yet support calling 32bit code from 64bit */
449 if (rvalue
&& (cif
->rtype
->type
== FFI_TYPE_STRUCT
450 #if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
451 || cif
->flags
== FFI_TYPE_LONGDOUBLE
455 /* For v8, we need an "unimp" with size of returning struct */
456 /* behind "call", so we alloc some executable space for it. */
457 /* l7 is used, we need to make sure v8.S doesn't use %l7. */
458 unsigned int *call_struct
= NULL
;
459 ffi_closure_alloc(32, (void **)&call_struct
);
462 unsigned long f
= (unsigned long)fn
;
463 call_struct
[0] = 0xae10001f; /* mov %i7, %l7 */
464 call_struct
[1] = 0xbe10000f; /* mov %o7, %i7 */
465 call_struct
[2] = 0x03000000 | f
>> 10; /* sethi %hi(fn), %g1 */
466 call_struct
[3] = 0x9fc06000 | (f
& 0x3ff); /* jmp %g1+%lo(fn), %o7 */
467 call_struct
[4] = 0x01000000; /* nop */
468 if (cif
->rtype
->size
< 0x7f)
469 call_struct
[5] = cif
->rtype
->size
; /* unimp */
471 call_struct
[5] = 0x01000000; /* nop */
472 call_struct
[6] = 0x81c7e008; /* ret */
473 call_struct
[7] = 0xbe100017; /* mov %l7, %i7 */
474 asm volatile ("iflush %0; iflush %0+8; iflush %0+16; iflush %0+24" : :
475 "r" (call_struct
) : "memory");
476 /* SPARC v8 requires 5 instructions for flush to be visible */
477 asm volatile ("nop; nop; nop; nop; nop");
478 ffi_call_v8(ffi_prep_args_v8
, &ecif
, cif
->bytes
,
479 cif
->flags
, rvalue
, (void (*)(void)) call_struct
);
480 ffi_closure_free(call_struct
);
484 ffi_call_v8(ffi_prep_args_v8
, &ecif
, cif
->bytes
,
485 cif
->flags
, rvalue
, fn
);
490 ffi_call_v8(ffi_prep_args_v8
, &ecif
, cif
->bytes
,
491 cif
->flags
, rvalue
, fn
);
498 ffi_call_v9(ffi_prep_args_v9
, &ecif
, cif
->bytes
, cif
->flags
, rval
, fn
);
499 if (rvalue
&& rval
&& cif
->rtype
->type
== FFI_TYPE_STRUCT
)
500 ffi_v9_layout_struct(cif
->rtype
, 0, (char *)rvalue
, (char *)rval
,
515 extern void ffi_closure_v9(void);
517 extern void ffi_closure_v8(void);
521 ffi_prep_closure_loc (ffi_closure
* closure
,
523 void (*fun
)(ffi_cif
*, void*, void**, void*),
527 unsigned int *tramp
= (unsigned int *) &closure
->tramp
[0];
530 /* Trampoline address is equal to the closure address. We take advantage
531 of that to reduce the trampoline size by 8 bytes. */
532 if (!V9_ABI_P (cif
->abi
))
534 fn
= (unsigned long) ffi_closure_v9
;
535 tramp
[0] = 0x83414000; /* rd %pc, %g1 */
536 tramp
[1] = 0xca586010; /* ldx [%g1+16], %g5 */
537 tramp
[2] = 0x81c14000; /* jmp %g5 */
538 tramp
[3] = 0x01000000; /* nop */
539 *((unsigned long *) &tramp
[4]) = fn
;
541 unsigned long ctx
= (unsigned long) codeloc
;
542 if (!V8_ABI_P (cif
->abi
))
544 fn
= (unsigned long) ffi_closure_v8
;
545 tramp
[0] = 0x03000000 | fn
>> 10; /* sethi %hi(fn), %g1 */
546 tramp
[1] = 0x05000000 | ctx
>> 10; /* sethi %hi(ctx), %g2 */
547 tramp
[2] = 0x81c06000 | (fn
& 0x3ff); /* jmp %g1+%lo(fn) */
548 tramp
[3] = 0x8410a000 | (ctx
& 0x3ff);/* or %g2, %lo(ctx) */
553 closure
->user_data
= user_data
;
555 /* Flush the Icache. closure is 8 bytes aligned. */
557 asm volatile ("flush %0; flush %0+8" : : "r" (closure
) : "memory");
559 asm volatile ("iflush %0; iflush %0+8" : : "r" (closure
) : "memory");
560 /* SPARC v8 requires 5 instructions for flush to be visible */
561 asm volatile ("nop; nop; nop; nop; nop");
570 ffi_closure_sparc_inner_v9(ffi_closure
*closure
, void *rvalue
,
571 unsigned long *gpr
, double *fpr
)
574 ffi_type
**arg_types
;
576 int i
, argn
, fp_slot_max
;
579 arg_types
= cif
->arg_types
;
580 avalue
= alloca(cif
->nargs
* sizeof(void *));
582 /* Copy the caller's structure return address so that the closure
583 returns the data directly to the caller. */
584 if (cif
->flags
== FFI_TYPE_VOID
&& cif
->rtype
->type
== FFI_TYPE_STRUCT
)
586 rvalue
= (void *) gpr
[0];
587 /* Skip the structure return address. */
593 fp_slot_max
= 16 - argn
;
595 /* Grab the addresses of the arguments from the stack frame. */
596 for (i
= 0; i
< cif
->nargs
; i
++)
598 /* If the function is variadic, FP arguments are passed in FP
599 registers only if the corresponding parameter is named. */
601 = (cif
->abi
== FFI_COMPAT_V9
? 1 : i
< cif
->nfixedargs
);
603 if (arg_types
[i
]->type
== FFI_TYPE_STRUCT
)
605 if (arg_types
[i
]->size
> 16)
607 /* Straight copy of invisible reference. */
608 avalue
[i
] = (void *)gpr
[argn
++];
613 ffi_v9_layout_struct(arg_types
[i
],
618 ? (char *) &fpr
[argn
]
619 : (char *) &gpr
[argn
]);
620 avalue
[i
] = &gpr
[argn
];
622 += ALIGN(arg_types
[i
]->size
, FFI_SIZEOF_ARG
) / FFI_SIZEOF_ARG
;
628 argn
+= ALIGN(arg_types
[i
]->size
, FFI_SIZEOF_ARG
) / FFI_SIZEOF_ARG
;
630 /* Align on a 16-byte boundary. */
631 #if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
632 if (arg_types
[i
]->type
== FFI_TYPE_LONGDOUBLE
&& (argn
% 2) != 0)
637 && (arg_types
[i
]->type
== FFI_TYPE_FLOAT
638 || arg_types
[i
]->type
== FFI_TYPE_DOUBLE
639 #if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
640 || arg_types
[i
]->type
== FFI_TYPE_LONGDOUBLE
643 avalue
[i
] = ((char *) &fpr
[argn
]) - arg_types
[i
]->size
;
645 avalue
[i
] = ((char *) &gpr
[argn
]) - arg_types
[i
]->size
;
649 /* Invoke the closure. */
650 closure
->fun (cif
, rvalue
, avalue
, closure
->user_data
);
652 /* Tell ffi_closure_sparc how to perform return type promotions. */
653 return cif
->rtype
->type
;
659 ffi_closure_sparc_inner_v8(ffi_closure
*closure
, void *rvalue
,
660 unsigned long *gpr
, unsigned long *scratch
)
663 ffi_type
**arg_types
;
668 arg_types
= cif
->arg_types
;
669 avalue
= alloca(cif
->nargs
* sizeof(void *));
671 /* Copy the caller's structure return address so that the closure
672 returns the data directly to the caller. */
673 if (cif
->flags
== FFI_TYPE_STRUCT
674 #if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
675 || cif
->flags
== FFI_TYPE_LONGDOUBLE
678 rvalue
= (void *) gpr
[0];
680 /* Always skip the structure return address. */
683 /* Grab the addresses of the arguments from the stack frame. */
684 for (i
= 0; i
< cif
->nargs
; i
++)
686 if (arg_types
[i
]->type
== FFI_TYPE_STRUCT
687 #if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
688 || arg_types
[i
]->type
== FFI_TYPE_LONGDOUBLE
692 /* Straight copy of invisible reference. */
693 avalue
[i
] = (void *)gpr
[argn
++];
695 else if ((arg_types
[i
]->type
== FFI_TYPE_DOUBLE
696 || arg_types
[i
]->type
== FFI_TYPE_SINT64
697 || arg_types
[i
]->type
== FFI_TYPE_UINT64
)
698 /* gpr is 8-byte aligned. */
701 /* Align on a 8-byte boundary. */
702 scratch
[0] = gpr
[argn
];
703 scratch
[1] = gpr
[argn
+1];
710 /* Always right-justify. */
711 argn
+= ALIGN(arg_types
[i
]->size
, FFI_SIZEOF_ARG
) / FFI_SIZEOF_ARG
;
712 avalue
[i
] = ((char *) &gpr
[argn
]) - arg_types
[i
]->size
;
716 /* Invoke the closure. */
717 closure
->fun (cif
, rvalue
, avalue
, closure
->user_data
);
719 /* Tell ffi_closure_sparc how to perform return type promotions. */
720 return cif
->rtype
->type
;