mirror of
https://github.com/partic2/libffi
synced 2026-11-10 10:07:19 +00:00
GO closures for powerpc linux
Plus .cfi async unwind info, rearrangement of ffi_call_linux64 and ffi_call_SYSV function params to avoid register copies, tweaks to trampolines. * src/powerpc/ffitarget.h (FFI_GO_CLOSURES): Define. * src/powerpc/ffi.c (ffi_call_int): New function with extra closure param, and args rearranged on ffi_call_linux64 and ffi_call_SYSV calls, extracted from .. (ffi_call): ..here. (ffi_call_go, ffi_prep_go_closure): New functions. * src/powerpc/ffi_linux64.c (ffi_prep_closure_loc_linux64): Make hidden. Only flush insn part of ELFv2 trampoline. Don't shuffle ELFv1 trampoline. (ffi_closure_helper_LINUX64): Replace closure param with cif, fun, user_data params. * src/powerpc/ffi_powerpc.h (ffi_go_closure_sysv): Declare. (ffi_go_closure_linux64): Declare. (ffi_call_SYSV, fi_call_LINUX64): Update. (ffi_prep_closure_loc_sysv, ffi_prep_closure_loc_linux64): Declare. (ffi_closure_helper_SYSV, ffi_closure_helper_LINUX64): Update. * src/powerpc/ffi_sysv.c (ASM_NEEDS_REGISTERS): Increase to 6. (ffi_prep_closure_loc_sysv): Use bcl in trampoline, put data words last, flush just the insn part. (ffi_closure_helper_SYSV): Replace closure param with cif, fun and user_data params. * src/powerpc/linux64.S (ffi_call_LINUX64): Replace hand-written .eh_frame with .cfi directives. Adjust for changed param order. Pass extra "closure" param to user function in static chain. Add .cfi directives to describe epilogue. Don't provide traceback table for ELFv2 or _CALL_LINUX. * src/powerpc/linux64_closure.S (ffi_closure_LINUX64): Replace hand-written .eh_frame with .cfi directives. Adjust for changed ffi_closure_helper_LINUX64 params. Add .cfi directives to describe epilogue. Don't provide traceback table for ELFv2 or _CALL_LINUX. (ffi_go_closure_linux64): New function. * src/powerpc/sysv.S: Remove redundant .globl ffi_prep_args_SYSV. (ffi_call_SYSV): Make hidden. Replace hand-written .eh_frame with .cfi directives. Adjust for changed params. Pass extra "closure" param to user function in static chain. Add .cfi directives to describe epilogue. * src/powerpc/ppc_closure.S (ffi_closure_SYSV): Make hidden. Replace hand-written .eh_frame with .cfi directives. Adjust for changed ffi_closure_helper_SYSV params. Add .cfi directives to describe epilogue. Don't just use nops in the dead __NO_FPRS__ epilogues. (ffi_go_closure_sysv): New function.
This commit is contained in:
+18
-15
@@ -36,7 +36,7 @@
|
||||
|
||||
|
||||
/* About the SYSV ABI. */
|
||||
#define ASM_NEEDS_REGISTERS 4
|
||||
#define ASM_NEEDS_REGISTERS 6
|
||||
#define NUM_GPR_ARG_REGISTERS 8
|
||||
#define NUM_FPR_ARG_REGISTERS 8
|
||||
|
||||
@@ -654,18 +654,18 @@ ffi_prep_closure_loc_sysv (ffi_closure *closure,
|
||||
|
||||
tramp = (unsigned int *) &closure->tramp[0];
|
||||
tramp[0] = 0x7c0802a6; /* mflr r0 */
|
||||
tramp[1] = 0x4800000d; /* bl 10 <trampoline_initial+0x10> */
|
||||
tramp[4] = 0x7d6802a6; /* mflr r11 */
|
||||
tramp[5] = 0x7c0803a6; /* mtlr r0 */
|
||||
tramp[6] = 0x800b0000; /* lwz r0,0(r11) */
|
||||
tramp[7] = 0x816b0004; /* lwz r11,4(r11) */
|
||||
tramp[8] = 0x7c0903a6; /* mtctr r0 */
|
||||
tramp[9] = 0x4e800420; /* bctr */
|
||||
*(void **) &tramp[2] = (void *) ffi_closure_SYSV; /* function */
|
||||
*(void **) &tramp[3] = codeloc; /* context */
|
||||
tramp[1] = 0x429f0005; /* bcl 20,31,.+4 */
|
||||
tramp[2] = 0x7d6802a6; /* mflr r11 */
|
||||
tramp[3] = 0x7c0803a6; /* mtlr r0 */
|
||||
tramp[4] = 0x800b0018; /* lwz r0,24(r11) */
|
||||
tramp[5] = 0x816b001c; /* lwz r11,28(r11) */
|
||||
tramp[6] = 0x7c0903a6; /* mtctr r0 */
|
||||
tramp[7] = 0x4e800420; /* bctr */
|
||||
*(void **) &tramp[8] = (void *) ffi_closure_SYSV; /* function */
|
||||
*(void **) &tramp[9] = codeloc; /* context */
|
||||
|
||||
/* Flush the icache. */
|
||||
flush_icache ((char *)tramp, (char *)codeloc, FFI_TRAMPOLINE_SIZE);
|
||||
flush_icache ((char *)tramp, (char *)codeloc, 8 * 4);
|
||||
|
||||
closure->cif = cif;
|
||||
closure->fun = fun;
|
||||
@@ -682,8 +682,12 @@ ffi_prep_closure_loc_sysv (ffi_closure *closure,
|
||||
following helper function to do most of the work. */
|
||||
|
||||
int
|
||||
ffi_closure_helper_SYSV (ffi_closure *closure, void *rvalue,
|
||||
unsigned long *pgr, ffi_dblfl *pfr,
|
||||
ffi_closure_helper_SYSV (ffi_cif *cif,
|
||||
void (*fun) (ffi_cif *, void *, void **, void *),
|
||||
void *user_data,
|
||||
void *rvalue,
|
||||
unsigned long *pgr,
|
||||
ffi_dblfl *pfr,
|
||||
unsigned long *pst)
|
||||
{
|
||||
/* rvalue is the pointer to space for return value in closure assembly */
|
||||
@@ -699,7 +703,6 @@ ffi_closure_helper_SYSV (ffi_closure *closure, void *rvalue,
|
||||
#endif
|
||||
long ng = 0; /* number of general registers already used */
|
||||
|
||||
ffi_cif *cif = closure->cif;
|
||||
unsigned size = cif->rtype->size;
|
||||
unsigned short rtypenum = cif->rtype->type;
|
||||
|
||||
@@ -915,7 +918,7 @@ ffi_closure_helper_SYSV (ffi_closure *closure, void *rvalue,
|
||||
i++;
|
||||
}
|
||||
|
||||
(closure->fun) (cif, rvalue, avalue, closure->user_data);
|
||||
(*fun) (cif, rvalue, avalue, user_data);
|
||||
|
||||
/* Tell ffi_closure_SYSV how to perform return type promotions.
|
||||
Because the FFI_SYSV ABI returns the structures <= 8 bytes in
|
||||
|
||||
Reference in New Issue
Block a user