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:
Alan Modra
2014-11-10 09:42:31 +10:30
parent d3d06f4c94
commit fa1040c111
9 changed files with 403 additions and 313 deletions

View File

@@ -70,8 +70,12 @@ ffi_prep_cif_machdep_var (ffi_cif *cif,
#endif #endif
} }
void static void
ffi_call(ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue) ffi_call_int (ffi_cif *cif,
void (*fn) (void),
void *rvalue,
void **avalue,
void *closure)
{ {
/* The final SYSV ABI says that structures smaller or equal 8 bytes /* The final SYSV ABI says that structures smaller or equal 8 bytes
are returned in r3/r4. A draft ABI used by linux instead returns are returned in r3/r4. A draft ABI used by linux instead returns
@@ -97,9 +101,10 @@ ffi_call(ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue)
ecif.rvalue = alloca (cif->rtype->size); ecif.rvalue = alloca (cif->rtype->size);
#ifdef POWERPC64 #ifdef POWERPC64
ffi_call_LINUX64 (&ecif, -(long) cif->bytes, cif->flags, ecif.rvalue, fn); ffi_call_LINUX64 (&ecif, fn, ecif.rvalue, cif->flags, closure,
-(long) cif->bytes);
#else #else
ffi_call_SYSV (&ecif, -cif->bytes, cif->flags, ecif.rvalue, fn); ffi_call_SYSV (&ecif, fn, ecif.rvalue, cif->flags, closure, -cif->bytes);
#endif #endif
/* Check for a bounce-buffered return value */ /* Check for a bounce-buffered return value */
@@ -125,6 +130,18 @@ ffi_call(ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue)
} }
} }
void
ffi_call (ffi_cif *cif, void (*fn) (void), void *rvalue, void **avalue)
{
ffi_call_int (cif, fn, rvalue, avalue, NULL);
}
void
ffi_call_go (ffi_cif *cif, void (*fn) (void), void *rvalue, void **avalue,
void *closure)
{
ffi_call_int (cif, fn, rvalue, avalue, closure);
}
ffi_status ffi_status
ffi_prep_closure_loc (ffi_closure *closure, ffi_prep_closure_loc (ffi_closure *closure,
@@ -139,3 +156,18 @@ ffi_prep_closure_loc (ffi_closure *closure,
return ffi_prep_closure_loc_sysv (closure, cif, fun, user_data, codeloc); return ffi_prep_closure_loc_sysv (closure, cif, fun, user_data, codeloc);
#endif #endif
} }
ffi_status
ffi_prep_go_closure (ffi_go_closure *closure,
ffi_cif *cif,
void (*fun) (ffi_cif *, void *, void **, void *))
{
#ifdef POWERPC64
closure->tramp = ffi_go_closure_linux64;
#else
closure->tramp = ffi_go_closure_sysv;
#endif
closure->cif = cif;
closure->fun = fun;
return FFI_OK;
}

View File

@@ -667,7 +667,8 @@ flush_icache (char *wraddr, char *xaddr, int size)
} }
#endif #endif
ffi_status
ffi_status FFI_HIDDEN
ffi_prep_closure_loc_linux64 (ffi_closure *closure, ffi_prep_closure_loc_linux64 (ffi_closure *closure,
ffi_cif *cif, ffi_cif *cif,
void (*fun) (ffi_cif *, void *, void **, void *), void (*fun) (ffi_cif *, void *, void **, void *),
@@ -688,17 +689,17 @@ ffi_prep_closure_loc_linux64 (ffi_closure *closure,
/* 2: .quad context */ /* 2: .quad context */
*(void **) &tramp[4] = (void *) ffi_closure_LINUX64; *(void **) &tramp[4] = (void *) ffi_closure_LINUX64;
*(void **) &tramp[6] = codeloc; *(void **) &tramp[6] = codeloc;
flush_icache ((char *)tramp, (char *)codeloc, FFI_TRAMPOLINE_SIZE); flush_icache ((char *) tramp, (char *) codeloc, 4 * 4);
#else #else
void **tramp = (void **) &closure->tramp[0]; void **tramp = (void **) &closure->tramp[0];
if (cif->abi < FFI_LINUX || cif->abi >= FFI_LAST_ABI) if (cif->abi < FFI_LINUX || cif->abi >= FFI_LAST_ABI)
return FFI_BAD_ABI; return FFI_BAD_ABI;
/* Copy function address and TOC from ffi_closure_LINUX64. */ /* Copy function address and TOC from ffi_closure_LINUX64 OPD. */
memcpy (tramp, (char *) ffi_closure_LINUX64, 16); memcpy (&tramp[0], (void **) ffi_closure_LINUX64, sizeof (void *));
tramp[2] = tramp[1];
tramp[1] = codeloc; tramp[1] = codeloc;
memcpy (&tramp[2], (void **) ffi_closure_LINUX64 + 1, sizeof (void *));
#endif #endif
closure->cif = cif; closure->cif = cif;
@@ -710,8 +711,12 @@ ffi_prep_closure_loc_linux64 (ffi_closure *closure,
int FFI_HIDDEN int FFI_HIDDEN
ffi_closure_helper_LINUX64 (ffi_closure *closure, void *rvalue, ffi_closure_helper_LINUX64 (ffi_cif *cif,
unsigned long *pst, ffi_dblfl *pfr) void (*fun) (ffi_cif *, void *, void **, void *),
void *user_data,
void *rvalue,
unsigned long *pst,
ffi_dblfl *pfr)
{ {
/* rvalue is the pointer to space for return value in closure assembly */ /* rvalue is the pointer to space for return value in closure assembly */
/* pst is the pointer to parameter save area /* pst is the pointer to parameter save area
@@ -721,11 +726,9 @@ ffi_closure_helper_LINUX64 (ffi_closure *closure, void *rvalue,
void **avalue; void **avalue;
ffi_type **arg_types; ffi_type **arg_types;
unsigned long i, avn, nfixedargs; unsigned long i, avn, nfixedargs;
ffi_cif *cif;
ffi_dblfl *end_pfr = pfr + NUM_FPR_ARG_REGISTERS64; ffi_dblfl *end_pfr = pfr + NUM_FPR_ARG_REGISTERS64;
unsigned long align; unsigned long align;
cif = closure->cif;
avalue = alloca (cif->nargs * sizeof (void *)); avalue = alloca (cif->nargs * sizeof (void *));
/* Copy the caller's structure return value address so that the /* Copy the caller's structure return value address so that the
@@ -925,8 +928,7 @@ ffi_closure_helper_LINUX64 (ffi_closure *closure, void *rvalue,
i++; i++;
} }
(*fun) (cif, rvalue, avalue, user_data);
(closure->fun) (cif, rvalue, avalue, closure->user_data);
/* Tell ffi_closure_LINUX64 how to perform return type promotions. */ /* Tell ffi_closure_LINUX64 how to perform return type promotions. */
if ((cif->flags & FLAG_RETURNS_SMST) != 0) if ((cif->flags & FLAG_RETURNS_SMST) != 0)

View File

@@ -56,22 +56,39 @@ typedef union
} ffi_dblfl; } ffi_dblfl;
void FFI_HIDDEN ffi_closure_SYSV (void); void FFI_HIDDEN ffi_closure_SYSV (void);
void FFI_HIDDEN ffi_call_SYSV(extended_cif *, unsigned, unsigned, unsigned *, void FFI_HIDDEN ffi_go_closure_sysv (void);
void (*)(void)); void FFI_HIDDEN ffi_call_SYSV(extended_cif *, void (*)(void), void *,
unsigned, void *, int);
void FFI_HIDDEN ffi_prep_types_sysv (ffi_abi); void FFI_HIDDEN ffi_prep_types_sysv (ffi_abi);
ffi_status FFI_HIDDEN ffi_prep_cif_sysv (ffi_cif *); ffi_status FFI_HIDDEN ffi_prep_cif_sysv (ffi_cif *);
int FFI_HIDDEN ffi_closure_helper_SYSV (ffi_closure *, void *, unsigned long *, ffi_status FFI_HIDDEN ffi_prep_closure_loc_sysv (ffi_closure *,
ffi_cif *,
void (*) (ffi_cif *, void *,
void **, void *),
void *, void *);
int FFI_HIDDEN ffi_closure_helper_SYSV (ffi_cif *,
void (*) (ffi_cif *, void *,
void **, void *),
void *, void *, unsigned long *,
ffi_dblfl *, unsigned long *); ffi_dblfl *, unsigned long *);
void FFI_HIDDEN ffi_call_LINUX64(extended_cif *, unsigned long, unsigned long, void FFI_HIDDEN ffi_call_LINUX64(extended_cif *, void (*) (void), void *,
unsigned long *, void (*)(void)); unsigned long, void *, long);
void FFI_HIDDEN ffi_closure_LINUX64 (void); void FFI_HIDDEN ffi_closure_LINUX64 (void);
void FFI_HIDDEN ffi_go_closure_linux64 (void);
void FFI_HIDDEN ffi_prep_types_linux64 (ffi_abi); void FFI_HIDDEN ffi_prep_types_linux64 (ffi_abi);
ffi_status FFI_HIDDEN ffi_prep_cif_linux64 (ffi_cif *); ffi_status FFI_HIDDEN ffi_prep_cif_linux64 (ffi_cif *);
ffi_status FFI_HIDDEN ffi_prep_cif_linux64_var (ffi_cif *, unsigned int, ffi_status FFI_HIDDEN ffi_prep_cif_linux64_var (ffi_cif *, unsigned int,
unsigned int); unsigned int);
void FFI_HIDDEN ffi_prep_args64 (extended_cif *, unsigned long *const); void FFI_HIDDEN ffi_prep_args64 (extended_cif *, unsigned long *const);
int FFI_HIDDEN ffi_closure_helper_LINUX64 (ffi_closure *, void *, ffi_status FFI_HIDDEN ffi_prep_closure_loc_linux64 (ffi_closure *, ffi_cif *,
void (*) (ffi_cif *, void *,
void **, void *),
void *, void *);
int FFI_HIDDEN ffi_closure_helper_LINUX64 (ffi_cif *,
void (*) (ffi_cif *, void *,
void **, void *),
void *, void *,
unsigned long *, ffi_dblfl *); unsigned long *, ffi_dblfl *);

View File

@@ -36,7 +36,7 @@
/* About the SYSV ABI. */ /* About the SYSV ABI. */
#define ASM_NEEDS_REGISTERS 4 #define ASM_NEEDS_REGISTERS 6
#define NUM_GPR_ARG_REGISTERS 8 #define NUM_GPR_ARG_REGISTERS 8
#define NUM_FPR_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 = (unsigned int *) &closure->tramp[0];
tramp[0] = 0x7c0802a6; /* mflr r0 */ tramp[0] = 0x7c0802a6; /* mflr r0 */
tramp[1] = 0x4800000d; /* bl 10 <trampoline_initial+0x10> */ tramp[1] = 0x429f0005; /* bcl 20,31,.+4 */
tramp[4] = 0x7d6802a6; /* mflr r11 */ tramp[2] = 0x7d6802a6; /* mflr r11 */
tramp[5] = 0x7c0803a6; /* mtlr r0 */ tramp[3] = 0x7c0803a6; /* mtlr r0 */
tramp[6] = 0x800b0000; /* lwz r0,0(r11) */ tramp[4] = 0x800b0018; /* lwz r0,24(r11) */
tramp[7] = 0x816b0004; /* lwz r11,4(r11) */ tramp[5] = 0x816b001c; /* lwz r11,28(r11) */
tramp[8] = 0x7c0903a6; /* mtctr r0 */ tramp[6] = 0x7c0903a6; /* mtctr r0 */
tramp[9] = 0x4e800420; /* bctr */ tramp[7] = 0x4e800420; /* bctr */
*(void **) &tramp[2] = (void *) ffi_closure_SYSV; /* function */ *(void **) &tramp[8] = (void *) ffi_closure_SYSV; /* function */
*(void **) &tramp[3] = codeloc; /* context */ *(void **) &tramp[9] = codeloc; /* context */
/* Flush the icache. */ /* Flush the icache. */
flush_icache ((char *)tramp, (char *)codeloc, FFI_TRAMPOLINE_SIZE); flush_icache ((char *)tramp, (char *)codeloc, 8 * 4);
closure->cif = cif; closure->cif = cif;
closure->fun = fun; closure->fun = fun;
@@ -682,8 +682,12 @@ ffi_prep_closure_loc_sysv (ffi_closure *closure,
following helper function to do most of the work. */ following helper function to do most of the work. */
int int
ffi_closure_helper_SYSV (ffi_closure *closure, void *rvalue, ffi_closure_helper_SYSV (ffi_cif *cif,
unsigned long *pgr, ffi_dblfl *pfr, void (*fun) (ffi_cif *, void *, void **, void *),
void *user_data,
void *rvalue,
unsigned long *pgr,
ffi_dblfl *pfr,
unsigned long *pst) unsigned long *pst)
{ {
/* rvalue is the pointer to space for return value in closure assembly */ /* 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 #endif
long ng = 0; /* number of general registers already used */ long ng = 0; /* number of general registers already used */
ffi_cif *cif = closure->cif;
unsigned size = cif->rtype->size; unsigned size = cif->rtype->size;
unsigned short rtypenum = cif->rtype->type; unsigned short rtypenum = cif->rtype->type;
@@ -915,7 +918,7 @@ ffi_closure_helper_SYSV (ffi_closure *closure, void *rvalue,
i++; 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. /* Tell ffi_closure_SYSV how to perform return type promotions.
Because the FFI_SYSV ABI returns the structures <= 8 bytes in Because the FFI_SYSV ABI returns the structures <= 8 bytes in

View File

@@ -138,6 +138,7 @@ typedef enum ffi_abi {
#define FFI_CLOSURES 1 #define FFI_CLOSURES 1
#define FFI_NATIVE_RAW_API 0 #define FFI_NATIVE_RAW_API 0
#if defined (POWERPC) || defined (POWERPC_FREEBSD) #if defined (POWERPC) || defined (POWERPC_FREEBSD)
# define FFI_GO_CLOSURES 1
# define FFI_TARGET_SPECIFIC_VARIADIC 1 # define FFI_TARGET_SPECIFIC_VARIADIC 1
# define FFI_EXTRA_CIF_FIELDS unsigned nfixedargs # define FFI_EXTRA_CIF_FIELDS unsigned nfixedargs
#endif #endif

View File

@@ -32,8 +32,9 @@
#ifdef POWERPC64 #ifdef POWERPC64
.hidden ffi_call_LINUX64 .hidden ffi_call_LINUX64
.globl ffi_call_LINUX64 .globl ffi_call_LINUX64
# if _CALL_ELF == 2
.text .text
.cfi_startproc
# if _CALL_ELF == 2
ffi_call_LINUX64: ffi_call_LINUX64:
addis %r2, %r12, .TOC.-ffi_call_LINUX64@ha addis %r2, %r12, .TOC.-ffi_call_LINUX64@ha
addi %r2, %r2, .TOC.-ffi_call_LINUX64@l addi %r2, %r2, .TOC.-ffi_call_LINUX64@l
@@ -57,20 +58,26 @@ ffi_call_LINUX64:
.ffi_call_LINUX64: .ffi_call_LINUX64:
# endif # endif
# endif # endif
.LFB1:
mflr %r0 mflr %r0
std %r28, -32(%r1) std %r28, -32(%r1)
std %r29, -24(%r1) std %r29, -24(%r1)
std %r30, -16(%r1) std %r30, -16(%r1)
std %r31, -8(%r1) std %r31, -8(%r1)
std %r7, 8(%r1) /* closure, saved in cr field. */
std %r0, 16(%r1) std %r0, 16(%r1)
mr %r28, %r1 /* our AP. */ mr %r28, %r1 /* our AP. */
.LCFI0: .cfi_def_cfa_register 28
stdux %r1, %r1, %r4 .cfi_offset 65, 16
mr %r31, %r5 /* flags, */ .cfi_offset 31, -8
mr %r30, %r6 /* rvalue, */ .cfi_offset 30, -16
mr %r29, %r7 /* function address. */ .cfi_offset 29, -24
.cfi_offset 28, -32
stdux %r1, %r1, %r8
mr %r31, %r6 /* flags, */
mr %r30, %r5 /* rvalue, */
mr %r29, %r4 /* function address. */
/* Save toc pointer, not for the ffi_prep_args64 call, but for the later /* Save toc pointer, not for the ffi_prep_args64 call, but for the later
bctrl function call. */ bctrl function call. */
# if _CALL_ELF == 2 # if _CALL_ELF == 2
@@ -92,7 +99,6 @@ ffi_call_LINUX64:
# else # else
ld %r12, 0(%r29) ld %r12, 0(%r29)
ld %r2, 8(%r29) ld %r2, 8(%r29)
ld %r11, 16(%r29)
# endif # endif
/* Now do the call. */ /* Now do the call. */
/* Set up cr1 with bits 4-7 of the flags. */ /* Set up cr1 with bits 4-7 of the flags. */
@@ -130,6 +136,7 @@ ffi_call_LINUX64:
2: 2:
/* Make the call. */ /* Make the call. */
ld %r11, 8(%r28)
bctrl bctrl
/* This must follow the call immediately, the unwinder /* This must follow the call immediately, the unwinder
@@ -151,6 +158,7 @@ ffi_call_LINUX64:
.Ldone_return_value: .Ldone_return_value:
/* Restore the registers we used and return. */ /* Restore the registers we used and return. */
mr %r1, %r28 mr %r1, %r28
.cfi_def_cfa_register 1
ld %r0, 16(%r28) ld %r0, 16(%r28)
ld %r28, -32(%r28) ld %r28, -32(%r28)
mtlr %r0 mtlr %r0
@@ -160,6 +168,7 @@ ffi_call_LINUX64:
blr blr
.Lfp_return_value: .Lfp_return_value:
.cfi_def_cfa_register 28
bf 28, .Lfloat_return_value bf 28, .Lfloat_return_value
stfd %f1, 0(%r30) stfd %f1, 0(%r30)
mtcrf 0x02, %r31 /* cr6 */ mtcrf 0x02, %r31 /* cr6 */
@@ -199,61 +208,19 @@ ffi_call_LINUX64:
std %r4, 8(%r30) std %r4, 8(%r30)
b .Ldone_return_value b .Ldone_return_value
.LFE1: .cfi_endproc
.long 0
.byte 0,12,0,1,128,4,0,0
# if _CALL_ELF == 2 # if _CALL_ELF == 2
.size ffi_call_LINUX64,.-ffi_call_LINUX64 .size ffi_call_LINUX64,.-ffi_call_LINUX64
# else # else
# ifdef _CALL_LINUX # ifdef _CALL_LINUX
.size ffi_call_LINUX64,.-.L.ffi_call_LINUX64 .size ffi_call_LINUX64,.-.L.ffi_call_LINUX64
# else # else
.long 0
.byte 0,12,0,1,128,4,0,0
.size .ffi_call_LINUX64,.-.ffi_call_LINUX64 .size .ffi_call_LINUX64,.-.ffi_call_LINUX64
# endif # endif
# endif # endif
.section .eh_frame,EH_FRAME_FLAGS,@progbits
.Lframe1:
.4byte .LECIE1-.LSCIE1 # Length of Common Information Entry
.LSCIE1:
.4byte 0x0 # CIE Identifier Tag
.byte 0x1 # CIE Version
.ascii "zR\0" # CIE Augmentation
.uleb128 0x1 # CIE Code Alignment Factor
.sleb128 -8 # CIE Data Alignment Factor
.byte 0x41 # CIE RA Column
.uleb128 0x1 # Augmentation size
.byte 0x14 # FDE Encoding (pcrel udata8)
.byte 0xc # DW_CFA_def_cfa
.uleb128 0x1
.uleb128 0x0
.align 3
.LECIE1:
.LSFDE1:
.4byte .LEFDE1-.LASFDE1 # FDE Length
.LASFDE1:
.4byte .LASFDE1-.Lframe1 # FDE CIE offset
.8byte .LFB1-. # FDE initial location
.8byte .LFE1-.LFB1 # FDE address range
.uleb128 0x0 # Augmentation size
.byte 0x2 # DW_CFA_advance_loc1
.byte .LCFI0-.LFB1
.byte 0xd # DW_CFA_def_cfa_register
.uleb128 0x1c
.byte 0x11 # DW_CFA_offset_extended_sf
.uleb128 0x41
.sleb128 -2
.byte 0x9f # DW_CFA_offset, column 0x1f
.uleb128 0x1
.byte 0x9e # DW_CFA_offset, column 0x1e
.uleb128 0x2
.byte 0x9d # DW_CFA_offset, column 0x1d
.uleb128 0x3
.byte 0x9c # DW_CFA_offset, column 0x1c
.uleb128 0x4
.align 3
.LEFDE1:
#endif #endif
#if (defined __ELF__ && defined __linux__) || _CALL_ELF == 2 #if (defined __ELF__ && defined __linux__) || _CALL_ELF == 2

View File

@@ -33,8 +33,9 @@
#ifdef POWERPC64 #ifdef POWERPC64
FFI_HIDDEN (ffi_closure_LINUX64) FFI_HIDDEN (ffi_closure_LINUX64)
.globl ffi_closure_LINUX64 .globl ffi_closure_LINUX64
# if _CALL_ELF == 2
.text .text
.cfi_startproc
# if _CALL_ELF == 2
ffi_closure_LINUX64: ffi_closure_LINUX64:
addis %r2, %r12, .TOC.-ffi_closure_LINUX64@ha addis %r2, %r12, .TOC.-ffi_closure_LINUX64@ha
addi %r2, %r2, .TOC.-ffi_closure_LINUX64@l addi %r2, %r2, .TOC.-ffi_closure_LINUX64@l
@@ -73,20 +74,18 @@ ffi_closure_LINUX64:
# define RETVAL PARMSAVE+64 # define RETVAL PARMSAVE+64
# endif # endif
.LFB1:
# if _CALL_ELF == 2 # if _CALL_ELF == 2
ld %r12, FFI_TRAMPOLINE_SIZE(%r11) # closure->cif ld %r12, FFI_TRAMPOLINE_SIZE(%r11) # closure->cif
mflr %r0 mflr %r0
lwz %r12, 28(%r12) # cif->flags lwz %r12, 28(%r12) # cif->flags
mtcrf 0x40, %r12 mtcrf 0x40, %r12
addi %r12, %r1, PARMSAVE addi %r12, %r1, PARMSAVE
bt 7, .Lparmsave bt 7, 0f
# Our caller has not allocated a parameter save area. # Our caller has not allocated a parameter save area.
# We need to allocate one here and use it to pass gprs to # We need to allocate one here and use it to pass gprs to
# ffi_closure_helper_LINUX64. # ffi_closure_helper_LINUX64.
addi %r12, %r1, -STACKFRAME+PARMSAVE addi %r12, %r1, -STACKFRAME+PARMSAVE
.Lparmsave: 0:
std %r0, 16(%r1)
# Save general regs into parm save area # Save general regs into parm save area
std %r3, 0(%r12) std %r3, 0(%r12)
std %r4, 8(%r12) std %r4, 8(%r12)
@@ -98,7 +97,7 @@ ffi_closure_LINUX64:
std %r10, 56(%r12) std %r10, 56(%r12)
# load up the pointer to the parm save area # load up the pointer to the parm save area
mr %r5, %r12 mr %r7, %r12
# else # else
# copy r2 to r11 and load TOC into r2 # copy r2 to r11 and load TOC into r2
mr %r11, %r2 mr %r11, %r2
@@ -116,12 +115,19 @@ ffi_closure_LINUX64:
std %r9, PARMSAVE+48(%r1) std %r9, PARMSAVE+48(%r1)
std %r10, PARMSAVE+56(%r1) std %r10, PARMSAVE+56(%r1)
# load up the pointer to the parm save area
addi %r7, %r1, PARMSAVE
# endif
std %r0, 16(%r1) std %r0, 16(%r1)
# load up the pointer to the parm save area # closure->cif
addi %r5, %r1, PARMSAVE ld %r3, FFI_TRAMPOLINE_SIZE(%r11)
# endif # closure->fun
ld %r4, FFI_TRAMPOLINE_SIZE+8(%r11)
# closure->user_data
ld %r5, FFI_TRAMPOLINE_SIZE+16(%r11)
.Ldoclosure:
# next save fpr 1 to fpr 13 # next save fpr 1 to fpr 13
stfd %f1, -104+(0*8)(%r1) stfd %f1, -104+(0*8)(%r1)
stfd %f2, -104+(1*8)(%r1) stfd %f2, -104+(1*8)(%r1)
@@ -138,16 +144,14 @@ ffi_closure_LINUX64:
stfd %f13, -104+(12*8)(%r1) stfd %f13, -104+(12*8)(%r1)
# load up the pointer to the saved fpr registers */ # load up the pointer to the saved fpr registers */
addi %r6, %r1, -104 addi %r8, %r1, -104
# load up the pointer to the result storage # load up the pointer to the result storage
addi %r4, %r1, -STACKFRAME+RETVAL addi %r6, %r1, -STACKFRAME+RETVAL
stdu %r1, -STACKFRAME(%r1) stdu %r1, -STACKFRAME(%r1)
.LCFI0: .cfi_def_cfa_offset STACKFRAME
.cfi_offset 65, 16
# get the context pointer from the trampoline
mr %r3, %r11
# make the call # make the call
# if defined _CALL_LINUX || _CALL_ELF == 2 # if defined _CALL_LINUX || _CALL_ELF == 2
@@ -182,7 +186,9 @@ ffi_closure_LINUX64:
# case FFI_TYPE_VOID # case FFI_TYPE_VOID
mtlr %r0 mtlr %r0
addi %r1, %r1, STACKFRAME addi %r1, %r1, STACKFRAME
.cfi_def_cfa_offset 0
blr blr
.cfi_def_cfa_offset STACKFRAME
nop nop
# case FFI_TYPE_INT # case FFI_TYPE_INT
# ifdef __LITTLE_ENDIAN__ # ifdef __LITTLE_ENDIAN__
@@ -192,17 +198,23 @@ ffi_closure_LINUX64:
# endif # endif
mtlr %r0 mtlr %r0
addi %r1, %r1, STACKFRAME addi %r1, %r1, STACKFRAME
.cfi_def_cfa_offset 0
blr blr
.cfi_def_cfa_offset STACKFRAME
# case FFI_TYPE_FLOAT # case FFI_TYPE_FLOAT
lfs %f1, RETVAL+0(%r1) lfs %f1, RETVAL+0(%r1)
mtlr %r0 mtlr %r0
addi %r1, %r1, STACKFRAME addi %r1, %r1, STACKFRAME
.cfi_def_cfa_offset 0
blr blr
.cfi_def_cfa_offset STACKFRAME
# case FFI_TYPE_DOUBLE # case FFI_TYPE_DOUBLE
lfd %f1, RETVAL+0(%r1) lfd %f1, RETVAL+0(%r1)
mtlr %r0 mtlr %r0
addi %r1, %r1, STACKFRAME addi %r1, %r1, STACKFRAME
.cfi_def_cfa_offset 0
blr blr
.cfi_def_cfa_offset STACKFRAME
# case FFI_TYPE_LONGDOUBLE # case FFI_TYPE_LONGDOUBLE
lfd %f1, RETVAL+0(%r1) lfd %f1, RETVAL+0(%r1)
mtlr %r0 mtlr %r0
@@ -216,7 +228,9 @@ ffi_closure_LINUX64:
# endif # endif
mtlr %r0 mtlr %r0
addi %r1, %r1, STACKFRAME addi %r1, %r1, STACKFRAME
.cfi_def_cfa_offset 0
blr blr
.cfi_def_cfa_offset STACKFRAME
# case FFI_TYPE_SINT8 # case FFI_TYPE_SINT8
# ifdef __LITTLE_ENDIAN__ # ifdef __LITTLE_ENDIAN__
lbz %r3, RETVAL+0(%r1) lbz %r3, RETVAL+0(%r1)
@@ -235,7 +249,9 @@ ffi_closure_LINUX64:
mtlr %r0 mtlr %r0
.Lfinish: .Lfinish:
addi %r1, %r1, STACKFRAME addi %r1, %r1, STACKFRAME
.cfi_def_cfa_offset 0
blr blr
.cfi_def_cfa_offset STACKFRAME
# case FFI_TYPE_SINT16 # case FFI_TYPE_SINT16
# ifdef __LITTLE_ENDIAN__ # ifdef __LITTLE_ENDIAN__
lha %r3, RETVAL+0(%r1) lha %r3, RETVAL+0(%r1)
@@ -244,7 +260,9 @@ ffi_closure_LINUX64:
# endif # endif
mtlr %r0 mtlr %r0
addi %r1, %r1, STACKFRAME addi %r1, %r1, STACKFRAME
.cfi_def_cfa_offset 0
blr blr
.cfi_def_cfa_offset STACKFRAME
# case FFI_TYPE_UINT32 # case FFI_TYPE_UINT32
# ifdef __LITTLE_ENDIAN__ # ifdef __LITTLE_ENDIAN__
lwz %r3, RETVAL+0(%r1) lwz %r3, RETVAL+0(%r1)
@@ -253,7 +271,9 @@ ffi_closure_LINUX64:
# endif # endif
mtlr %r0 mtlr %r0
addi %r1, %r1, STACKFRAME addi %r1, %r1, STACKFRAME
.cfi_def_cfa_offset 0
blr blr
.cfi_def_cfa_offset STACKFRAME
# case FFI_TYPE_SINT32 # case FFI_TYPE_SINT32
# ifdef __LITTLE_ENDIAN__ # ifdef __LITTLE_ENDIAN__
lwa %r3, RETVAL+0(%r1) lwa %r3, RETVAL+0(%r1)
@@ -262,27 +282,37 @@ ffi_closure_LINUX64:
# endif # endif
mtlr %r0 mtlr %r0
addi %r1, %r1, STACKFRAME addi %r1, %r1, STACKFRAME
.cfi_def_cfa_offset 0
blr blr
.cfi_def_cfa_offset STACKFRAME
# case FFI_TYPE_UINT64 # case FFI_TYPE_UINT64
ld %r3, RETVAL+0(%r1) ld %r3, RETVAL+0(%r1)
mtlr %r0 mtlr %r0
addi %r1, %r1, STACKFRAME addi %r1, %r1, STACKFRAME
.cfi_def_cfa_offset 0
blr blr
.cfi_def_cfa_offset STACKFRAME
# case FFI_TYPE_SINT64 # case FFI_TYPE_SINT64
ld %r3, RETVAL+0(%r1) ld %r3, RETVAL+0(%r1)
mtlr %r0 mtlr %r0
addi %r1, %r1, STACKFRAME addi %r1, %r1, STACKFRAME
.cfi_def_cfa_offset 0
blr blr
.cfi_def_cfa_offset STACKFRAME
# case FFI_TYPE_STRUCT # case FFI_TYPE_STRUCT
mtlr %r0 mtlr %r0
addi %r1, %r1, STACKFRAME addi %r1, %r1, STACKFRAME
.cfi_def_cfa_offset 0
blr blr
.cfi_def_cfa_offset STACKFRAME
nop nop
# case FFI_TYPE_POINTER # case FFI_TYPE_POINTER
ld %r3, RETVAL+0(%r1) ld %r3, RETVAL+0(%r1)
mtlr %r0 mtlr %r0
addi %r1, %r1, STACKFRAME addi %r1, %r1, STACKFRAME
.cfi_def_cfa_offset 0
blr blr
.cfi_def_cfa_offset STACKFRAME
# case FFI_V2_TYPE_FLOAT_HOMOG # case FFI_V2_TYPE_FLOAT_HOMOG
lfs %f1, RETVAL+0(%r1) lfs %f1, RETVAL+0(%r1)
lfs %f2, RETVAL+4(%r1) lfs %f2, RETVAL+4(%r1)
@@ -299,7 +329,9 @@ ffi_closure_LINUX64:
lfd %f7, RETVAL+48(%r1) lfd %f7, RETVAL+48(%r1)
lfd %f8, RETVAL+56(%r1) lfd %f8, RETVAL+56(%r1)
addi %r1, %r1, STACKFRAME addi %r1, %r1, STACKFRAME
.cfi_def_cfa_offset 0
blr blr
.cfi_def_cfa_offset STACKFRAME
.Lmorefloat: .Lmorefloat:
lfs %f4, RETVAL+12(%r1) lfs %f4, RETVAL+12(%r1)
mtlr %r0 mtlr %r0
@@ -308,13 +340,16 @@ ffi_closure_LINUX64:
lfs %f7, RETVAL+24(%r1) lfs %f7, RETVAL+24(%r1)
lfs %f8, RETVAL+28(%r1) lfs %f8, RETVAL+28(%r1)
addi %r1, %r1, STACKFRAME addi %r1, %r1, STACKFRAME
.cfi_def_cfa_offset 0
blr blr
.cfi_def_cfa_offset STACKFRAME
.Lsmall: .Lsmall:
# ifdef __LITTLE_ENDIAN__ # ifdef __LITTLE_ENDIAN__
ld %r3,RETVAL+0(%r1) ld %r3,RETVAL+0(%r1)
mtlr %r0 mtlr %r0
ld %r4,RETVAL+8(%r1) ld %r4,RETVAL+8(%r1)
addi %r1, %r1, STACKFRAME addi %r1, %r1, STACKFRAME
.cfi_def_cfa_offset 0
blr blr
# else # else
# A struct smaller than a dword is returned in the low bits of r3 # A struct smaller than a dword is returned in the low bits of r3
@@ -328,63 +363,128 @@ ffi_closure_LINUX64:
mtlr %r0 mtlr %r0
ld %r4,RETVAL+8(%r1) ld %r4,RETVAL+8(%r1)
addi %r1, %r1, STACKFRAME addi %r1, %r1, STACKFRAME
.cfi_def_cfa_offset 0
blr blr
.cfi_def_cfa_offset STACKFRAME
.Lsmalldown: .Lsmalldown:
addi %r5, %r5, FFI_V2_TYPE_SMALL_STRUCT + 7 addi %r5, %r5, FFI_V2_TYPE_SMALL_STRUCT + 7
mtlr %r0 mtlr %r0
sldi %r5, %r5, 3 sldi %r5, %r5, 3
addi %r1, %r1, STACKFRAME addi %r1, %r1, STACKFRAME
.cfi_def_cfa_offset 0
srd %r3, %r3, %r5 srd %r3, %r3, %r5
blr blr
# endif # endif
.LFE1: .cfi_endproc
.long 0
.byte 0,12,0,1,128,0,0,0
# if _CALL_ELF == 2 # if _CALL_ELF == 2
.size ffi_closure_LINUX64,.-ffi_closure_LINUX64 .size ffi_closure_LINUX64,.-ffi_closure_LINUX64
# else # else
# ifdef _CALL_LINUX # ifdef _CALL_LINUX
.size ffi_closure_LINUX64,.-.L.ffi_closure_LINUX64 .size ffi_closure_LINUX64,.-.L.ffi_closure_LINUX64
# else # else
.long 0
.byte 0,12,0,1,128,0,0,0
.size .ffi_closure_LINUX64,.-.ffi_closure_LINUX64 .size .ffi_closure_LINUX64,.-.ffi_closure_LINUX64
# endif # endif
# endif # endif
.section .eh_frame,EH_FRAME_FLAGS,@progbits
.Lframe1:
.4byte .LECIE1-.LSCIE1 # Length of Common Information Entry
.LSCIE1:
.4byte 0x0 # CIE Identifier Tag
.byte 0x1 # CIE Version
.ascii "zR\0" # CIE Augmentation
.uleb128 0x1 # CIE Code Alignment Factor
.sleb128 -8 # CIE Data Alignment Factor
.byte 0x41 # CIE RA Column
.uleb128 0x1 # Augmentation size
.byte 0x14 # FDE Encoding (pcrel udata8)
.byte 0xc # DW_CFA_def_cfa
.uleb128 0x1
.uleb128 0x0
.align 3
.LECIE1:
.LSFDE1:
.4byte .LEFDE1-.LASFDE1 # FDE Length
.LASFDE1:
.4byte .LASFDE1-.Lframe1 # FDE CIE offset
.8byte .LFB1-. # FDE initial location
.8byte .LFE1-.LFB1 # FDE address range
.uleb128 0x0 # Augmentation size
.byte 0x2 # DW_CFA_advance_loc1
.byte .LCFI0-.LFB1
.byte 0xe # DW_CFA_def_cfa_offset
.uleb128 STACKFRAME
.byte 0x11 # DW_CFA_offset_extended_sf
.uleb128 0x41
.sleb128 -2
.align 3
.LEFDE1:
FFI_HIDDEN (ffi_go_closure_linux64)
.globl ffi_go_closure_linux64
.text
.cfi_startproc
# if _CALL_ELF == 2
ffi_go_closure_linux64:
addis %r2, %r12, .TOC.-ffi_go_closure_linux64@ha
addi %r2, %r2, .TOC.-ffi_go_closure_linux64@l
.localentry ffi_go_closure_linux64, . - ffi_go_closure_linux64
# else
.section ".opd","aw"
.align 3
ffi_go_closure_linux64:
# ifdef _CALL_LINUX
.quad .L.ffi_go_closure_linux64,.TOC.@tocbase,0
.type ffi_go_closure_linux64,@function
.text
.L.ffi_go_closure_linux64:
# else
FFI_HIDDEN (.ffi_go_closure_linux64)
.globl .ffi_go_closure_linux64
.quad .ffi_go_closure_linux64,.TOC.@tocbase,0
.size ffi_go_closure_linux64,24
.type .ffi_go_closure_linux64,@function
.text
.ffi_go_closure_linux64:
# endif
# endif
# if _CALL_ELF == 2
ld %r12, 8(%r11) # closure->cif
mflr %r0
lwz %r12, 28(%r12) # cif->flags
mtcrf 0x40, %r12
addi %r12, %r1, PARMSAVE
bt 7, 0f
# Our caller has not allocated a parameter save area.
# We need to allocate one here and use it to pass gprs to
# ffi_closure_helper_LINUX64.
addi %r12, %r1, -STACKFRAME+PARMSAVE
0:
# Save general regs into parm save area
std %r3, 0(%r12)
std %r4, 8(%r12)
std %r5, 16(%r12)
std %r6, 24(%r12)
std %r7, 32(%r12)
std %r8, 40(%r12)
std %r9, 48(%r12)
std %r10, 56(%r12)
# load up the pointer to the parm save area
mr %r7, %r12
# else
# copy r2 to r11 and load TOC into r2
mr %r11, %r2
ld %r2, 16(%r11)
mflr %r0
# Save general regs into parm save area
# This is the parameter save area set up by our caller.
std %r3, PARMSAVE+0(%r1)
std %r4, PARMSAVE+8(%r1)
std %r5, PARMSAVE+16(%r1)
std %r6, PARMSAVE+24(%r1)
std %r7, PARMSAVE+32(%r1)
std %r8, PARMSAVE+40(%r1)
std %r9, PARMSAVE+48(%r1)
std %r10, PARMSAVE+56(%r1)
# load up the pointer to the parm save area
addi %r7, %r1, PARMSAVE
# endif
std %r0, 16(%r1)
# closure->cif
ld %r3, 8(%r11)
# closure->fun
ld %r4, 16(%r11)
# user_data
mr %r5, %r11
b .Ldoclosure
.cfi_endproc
# if _CALL_ELF == 2
.size ffi_go_closure_linux64,.-ffi_go_closure_linux64
# else
# ifdef _CALL_LINUX
.size ffi_go_closure_linux64,.-.L.ffi_go_closure_linux64
# else
.long 0
.byte 0,12,0,1,128,0,0,0
.size .ffi_go_closure_linux64,.-.ffi_go_closure_linux64
# endif
# endif
#endif #endif
#if (defined __ELF__ && defined __linux__) || _CALL_ELF == 2 #if (defined __ELF__ && defined __linux__) || _CALL_ELF == 2

View File

@@ -33,13 +33,14 @@
#ifndef POWERPC64 #ifndef POWERPC64
FFI_HIDDEN(ffi_closure_SYSV)
ENTRY(ffi_closure_SYSV) ENTRY(ffi_closure_SYSV)
.LFB1: .cfi_startproc
stwu %r1,-144(%r1) stwu %r1,-144(%r1)
.LCFI0: .cfi_def_cfa_offset 144
mflr %r0 mflr %r0
.LCFI1:
stw %r0,148(%r1) stw %r0,148(%r1)
.cfi_offset 65, 4
# we want to build up an areas for the parameters passed # we want to build up an areas for the parameters passed
# in registers (both floating point and integer) # in registers (both floating point and integer)
@@ -48,6 +49,17 @@ ENTRY(ffi_closure_SYSV)
stw %r3, 16(%r1) stw %r3, 16(%r1)
stw %r4, 20(%r1) stw %r4, 20(%r1)
stw %r5, 24(%r1) stw %r5, 24(%r1)
# set up registers for the routine that does the work
# closure->cif
lwz %r3,FFI_TRAMPOLINE_SIZE(%r11)
# closure->fun
lwz %r4,FFI_TRAMPOLINE_SIZE+4(%r11)
# closure->user_data
lwz %r5,FFI_TRAMPOLINE_SIZE+8(%r11)
.Ldoclosure:
stw %r6, 28(%r1) stw %r6, 28(%r1)
stw %r7, 32(%r1) stw %r7, 32(%r1)
stw %r8, 36(%r1) stw %r8, 36(%r1)
@@ -66,23 +78,18 @@ ENTRY(ffi_closure_SYSV)
stfd %f8, 104(%r1) stfd %f8, 104(%r1)
#endif #endif
# set up registers for the routine that actually does the work # pointer to the result storage
# get the context pointer from the trampoline addi %r6,%r1,112
mr %r3,%r11
# now load up the pointer to the result storage # pointer to the saved gpr registers
addi %r4,%r1,112 addi %r7,%r1,16
# now load up the pointer to the saved gpr registers # pointer to the saved fpr registers
addi %r5,%r1,16 addi %r8,%r1,48
# now load up the pointer to the saved fpr registers */ # pointer to the outgoing parameter save area in the previous frame
addi %r6,%r1,48
# now load up the pointer to the outgoing parameter
# stack in the previous frame
# i.e. the previous frame pointer + 8 # i.e. the previous frame pointer + 8
addi %r7,%r1,152 addi %r9,%r1,152
# make the call # make the call
bl ffi_closure_helper_SYSV@local bl ffi_closure_helper_SYSV@local
@@ -101,7 +108,6 @@ ENTRY(ffi_closure_SYSV)
add %r3,%r3,%r4 # add contents of table to table address add %r3,%r3,%r4 # add contents of table to table address
mtctr %r3 mtctr %r3
bctr # jump to it bctr # jump to it
.LFE1:
# Each of the ret_typeX code fragments has to be exactly 16 bytes long # Each of the ret_typeX code fragments has to be exactly 16 bytes long
# (4 instructions). For cache effectiveness we align to a 16 byte boundary # (4 instructions). For cache effectiveness we align to a 16 byte boundary
@@ -111,7 +117,9 @@ ENTRY(ffi_closure_SYSV)
.Lret_type0: .Lret_type0:
mtlr %r0 mtlr %r0
addi %r1,%r1,144 addi %r1,%r1,144
.cfi_def_cfa_offset 0
blr blr
.cfi_def_cfa_offset 144
nop nop
# case FFI_TYPE_INT # case FFI_TYPE_INT
@@ -119,31 +127,33 @@ ENTRY(ffi_closure_SYSV)
mtlr %r0 mtlr %r0
.Lfinish: .Lfinish:
addi %r1,%r1,144 addi %r1,%r1,144
.cfi_def_cfa_offset 0
blr blr
.cfi_def_cfa_offset 144
# case FFI_TYPE_FLOAT # case FFI_TYPE_FLOAT
#ifndef __NO_FPRS__ #ifndef __NO_FPRS__
lfs %f1,112+0(%r1) lfs %f1,112+0(%r1)
mtlr %r0
addi %r1,%r1,144
#else #else
nop nop
nop
nop
#endif #endif
mtlr %r0
addi %r1,%r1,144
.cfi_def_cfa_offset 0
blr blr
.cfi_def_cfa_offset 144
# case FFI_TYPE_DOUBLE # case FFI_TYPE_DOUBLE
#ifndef __NO_FPRS__ #ifndef __NO_FPRS__
lfd %f1,112+0(%r1) lfd %f1,112+0(%r1)
mtlr %r0
addi %r1,%r1,144
#else #else
nop nop
nop
nop
#endif #endif
mtlr %r0
addi %r1,%r1,144
.cfi_def_cfa_offset 0
blr blr
.cfi_def_cfa_offset 144
# case FFI_TYPE_LONGDOUBLE # case FFI_TYPE_LONGDOUBLE
#ifndef __NO_FPRS__ #ifndef __NO_FPRS__
@@ -152,10 +162,12 @@ ENTRY(ffi_closure_SYSV)
mtlr %r0 mtlr %r0
b .Lfinish b .Lfinish
#else #else
nop mtlr %r0
nop addi %r1,%r1,144
nop .cfi_def_cfa_offset 0
blr blr
.cfi_def_cfa_offset 144
nop
#endif #endif
# case FFI_TYPE_UINT8 # case FFI_TYPE_UINT8
@@ -166,7 +178,9 @@ ENTRY(ffi_closure_SYSV)
#endif #endif
mtlr %r0 mtlr %r0
addi %r1,%r1,144 addi %r1,%r1,144
.cfi_def_cfa_offset 0
blr blr
.cfi_def_cfa_offset 144
# case FFI_TYPE_SINT8 # case FFI_TYPE_SINT8
#ifdef __LITTLE_ENDIAN__ #ifdef __LITTLE_ENDIAN__
@@ -186,7 +200,9 @@ ENTRY(ffi_closure_SYSV)
#endif #endif
mtlr %r0 mtlr %r0
addi %r1,%r1,144 addi %r1,%r1,144
.cfi_def_cfa_offset 0
blr blr
.cfi_def_cfa_offset 144
# case FFI_TYPE_SINT16 # case FFI_TYPE_SINT16
#ifdef __LITTLE_ENDIAN__ #ifdef __LITTLE_ENDIAN__
@@ -196,19 +212,25 @@ ENTRY(ffi_closure_SYSV)
#endif #endif
mtlr %r0 mtlr %r0
addi %r1,%r1,144 addi %r1,%r1,144
.cfi_def_cfa_offset 0
blr blr
.cfi_def_cfa_offset 144
# case FFI_TYPE_UINT32 # case FFI_TYPE_UINT32
lwz %r3,112+0(%r1) lwz %r3,112+0(%r1)
mtlr %r0 mtlr %r0
addi %r1,%r1,144 addi %r1,%r1,144
.cfi_def_cfa_offset 0
blr blr
.cfi_def_cfa_offset 144
# case FFI_TYPE_SINT32 # case FFI_TYPE_SINT32
lwz %r3,112+0(%r1) lwz %r3,112+0(%r1)
mtlr %r0 mtlr %r0
addi %r1,%r1,144 addi %r1,%r1,144
.cfi_def_cfa_offset 0
blr blr
.cfi_def_cfa_offset 144
# case FFI_TYPE_UINT64 # case FFI_TYPE_UINT64
lwz %r3,112+0(%r1) lwz %r3,112+0(%r1)
@@ -225,14 +247,18 @@ ENTRY(ffi_closure_SYSV)
# case FFI_TYPE_STRUCT # case FFI_TYPE_STRUCT
mtlr %r0 mtlr %r0
addi %r1,%r1,144 addi %r1,%r1,144
.cfi_def_cfa_offset 0
blr blr
.cfi_def_cfa_offset 144
nop nop
# case FFI_TYPE_POINTER # case FFI_TYPE_POINTER
lwz %r3,112+0(%r1) lwz %r3,112+0(%r1)
mtlr %r0 mtlr %r0
addi %r1,%r1,144 addi %r1,%r1,144
.cfi_def_cfa_offset 0
blr blr
.cfi_def_cfa_offset 144
# case FFI_TYPE_UINT128 # case FFI_TYPE_UINT128
lwz %r3,112+0(%r1) lwz %r3,112+0(%r1)
@@ -245,20 +271,26 @@ ENTRY(ffi_closure_SYSV)
lbz %r3,112+0(%r1) lbz %r3,112+0(%r1)
mtlr %r0 mtlr %r0
addi %r1,%r1,144 addi %r1,%r1,144
.cfi_def_cfa_offset 0
blr blr
.cfi_def_cfa_offset 144
# case FFI_SYSV_TYPE_SMALL_STRUCT + 2. Two byte struct. # case FFI_SYSV_TYPE_SMALL_STRUCT + 2. Two byte struct.
lhz %r3,112+0(%r1) lhz %r3,112+0(%r1)
mtlr %r0 mtlr %r0
addi %r1,%r1,144 addi %r1,%r1,144
.cfi_def_cfa_offset 0
blr blr
.cfi_def_cfa_offset 144
# case FFI_SYSV_TYPE_SMALL_STRUCT + 3. Three byte struct. # case FFI_SYSV_TYPE_SMALL_STRUCT + 3. Three byte struct.
lwz %r3,112+0(%r1) lwz %r3,112+0(%r1)
#ifdef __LITTLE_ENDIAN__ #ifdef __LITTLE_ENDIAN__
mtlr %r0 mtlr %r0
addi %r1,%r1,144 addi %r1,%r1,144
.cfi_def_cfa_offset 0
blr blr
.cfi_def_cfa_offset 144
#else #else
srwi %r3,%r3,8 srwi %r3,%r3,8
mtlr %r0 mtlr %r0
@@ -269,7 +301,9 @@ ENTRY(ffi_closure_SYSV)
lwz %r3,112+0(%r1) lwz %r3,112+0(%r1)
mtlr %r0 mtlr %r0
addi %r1,%r1,144 addi %r1,%r1,144
.cfi_def_cfa_offset 0
blr blr
.cfi_def_cfa_offset 144
# case FFI_SYSV_TYPE_SMALL_STRUCT + 5. Five byte struct. # case FFI_SYSV_TYPE_SMALL_STRUCT + 5. Five byte struct.
lwz %r3,112+0(%r1) lwz %r3,112+0(%r1)
@@ -319,64 +353,43 @@ ENTRY(ffi_closure_SYSV)
or %r4,%r6,%r4 or %r4,%r6,%r4
mtlr %r0 mtlr %r0
addi %r1,%r1,144 addi %r1,%r1,144
.cfi_def_cfa_offset 0
blr blr
.cfi_def_cfa_offset 144
#endif #endif
.Luint128: .Luint128:
lwz %r6,112+12(%r1) lwz %r6,112+12(%r1)
mtlr %r0 mtlr %r0
addi %r1,%r1,144 addi %r1,%r1,144
.cfi_def_cfa_offset 0
blr blr
.cfi_endproc
END(ffi_closure_SYSV) END(ffi_closure_SYSV)
.section ".eh_frame",EH_FRAME_FLAGS,@progbits
.Lframe1: FFI_HIDDEN(ffi_go_closure_sysv)
.4byte .LECIE1-.LSCIE1 # Length of Common Information Entry ENTRY(ffi_go_closure_sysv)
.LSCIE1: .cfi_startproc
.4byte 0x0 # CIE Identifier Tag stwu %r1,-144(%r1)
.byte 0x1 # CIE Version .cfi_def_cfa_offset 144
#if defined _RELOCATABLE || defined __PIC__ mflr %r0
.ascii "zR\0" # CIE Augmentation stw %r0,148(%r1)
#else .cfi_offset 65, 4
.ascii "\0" # CIE Augmentation
#endif stw %r3, 16(%r1)
.uleb128 0x1 # CIE Code Alignment Factor stw %r4, 20(%r1)
.sleb128 -4 # CIE Data Alignment Factor stw %r5, 24(%r1)
.byte 0x41 # CIE RA Column
#if defined _RELOCATABLE || defined __PIC__ # closure->cif
.uleb128 0x1 # Augmentation size lwz %r3,4(%r11)
.byte 0x1b # FDE Encoding (pcrel sdata4) # closure->fun
#endif lwz %r4,8(%r11)
.byte 0xc # DW_CFA_def_cfa # user_data
.uleb128 0x1 mr %r5,%r11
.uleb128 0x0 b .Ldoclosure
.align 2 .cfi_endproc
.LECIE1: END(ffi_go_closure_sysv)
.LSFDE1:
.4byte .LEFDE1-.LASFDE1 # FDE Length
.LASFDE1:
.4byte .LASFDE1-.Lframe1 # FDE CIE offset
#if defined _RELOCATABLE || defined __PIC__
.4byte .LFB1-. # FDE initial location
#else
.4byte .LFB1 # FDE initial location
#endif
.4byte .LFE1-.LFB1 # FDE address range
#if defined _RELOCATABLE || defined __PIC__
.uleb128 0x0 # Augmentation size
#endif
.byte 0x4 # DW_CFA_advance_loc4
.4byte .LCFI0-.LFB1
.byte 0xe # DW_CFA_def_cfa_offset
.uleb128 144
.byte 0x4 # DW_CFA_advance_loc4
.4byte .LCFI1-.LCFI0
.byte 0x11 # DW_CFA_offset_extended_sf
.uleb128 0x41
.sleb128 -1
.align 2
.LEFDE1:
#if defined __ELF__ && defined __linux__ #if defined __ELF__ && defined __linux__
.section .note.GNU-stack,"",@progbits .section .note.GNU-stack,"",@progbits

View File

@@ -31,34 +31,35 @@
#include <powerpc/asm.h> #include <powerpc/asm.h>
#ifndef POWERPC64 #ifndef POWERPC64
.globl ffi_prep_args_SYSV FFI_HIDDEN(ffi_call_SYSV)
ENTRY(ffi_call_SYSV) ENTRY(ffi_call_SYSV)
.LFB1: .cfi_startproc
/* Save the old stack pointer as AP. */ /* Save the old stack pointer as AP. */
mr %r8,%r1 mr %r10,%r1
.cfi_def_cfa_register 10
.LCFI0:
/* Allocate the stack space we need. */ /* Allocate the stack space we need. */
stwux %r1,%r1,%r4 stwux %r1,%r1,%r8
/* Save registers we use. */ /* Save registers we use. */
mflr %r9 mflr %r9
stw %r28,-16(%r8) stw %r28,-16(%r10)
.LCFI1: stw %r29,-12(%r10)
stw %r29,-12(%r8) stw %r30, -8(%r10)
.LCFI2: stw %r31, -4(%r10)
stw %r30, -8(%r8) stw %r9, 4(%r10)
.LCFI3: .cfi_offset 65, 4
stw %r31, -4(%r8) .cfi_offset 31, -4
.LCFI4: .cfi_offset 30, -8
stw %r9, 4(%r8) .cfi_offset 29, -12
.LCFI5: .cfi_offset 28, -16
/* Save arguments over call... */ /* Save arguments over call... */
mr %r31,%r5 /* flags, */ stw %r7, -20(%r10) /* closure, */
mr %r30,%r6 /* rvalue, */ mr %r31,%r6 /* flags, */
mr %r29,%r7 /* function address, */ mr %r30,%r5 /* rvalue, */
mr %r28,%r8 /* our AP. */ mr %r29,%r4 /* function address, */
.LCFI6: mr %r28,%r10 /* our AP. */
.cfi_def_cfa_register 28
/* Call ffi_prep_args_SYSV. */ /* Call ffi_prep_args_SYSV. */
mr %r4,%r1 mr %r4,%r1
@@ -70,35 +71,36 @@ ENTRY(ffi_call_SYSV)
/* Get the address to call into CTR. */ /* Get the address to call into CTR. */
mtctr %r29 mtctr %r29
/* Load all those argument registers. */ /* Load all those argument registers. */
lwz %r3,-16-(8*4)(%r28) lwz %r3,-24-(8*4)(%r28)
lwz %r4,-16-(7*4)(%r28) lwz %r4,-24-(7*4)(%r28)
lwz %r5,-16-(6*4)(%r28) lwz %r5,-24-(6*4)(%r28)
lwz %r6,-16-(5*4)(%r28) lwz %r6,-24-(5*4)(%r28)
bf- 5,1f bf- 5,1f
nop nop
lwz %r7,-16-(4*4)(%r28) lwz %r7,-24-(4*4)(%r28)
lwz %r8,-16-(3*4)(%r28) lwz %r8,-24-(3*4)(%r28)
lwz %r9,-16-(2*4)(%r28) lwz %r9,-24-(2*4)(%r28)
lwz %r10,-16-(1*4)(%r28) lwz %r10,-24-(1*4)(%r28)
nop nop
1: 1:
#ifndef __NO_FPRS__ #ifndef __NO_FPRS__
/* Load all the FP registers. */ /* Load all the FP registers. */
bf- 6,2f bf- 6,2f
lfd %f1,-16-(8*4)-(8*8)(%r28) lfd %f1,-24-(8*4)-(8*8)(%r28)
lfd %f2,-16-(8*4)-(7*8)(%r28) lfd %f2,-24-(8*4)-(7*8)(%r28)
lfd %f3,-16-(8*4)-(6*8)(%r28) lfd %f3,-24-(8*4)-(6*8)(%r28)
lfd %f4,-16-(8*4)-(5*8)(%r28) lfd %f4,-24-(8*4)-(5*8)(%r28)
nop nop
lfd %f5,-16-(8*4)-(4*8)(%r28) lfd %f5,-24-(8*4)-(4*8)(%r28)
lfd %f6,-16-(8*4)-(3*8)(%r28) lfd %f6,-24-(8*4)-(3*8)(%r28)
lfd %f7,-16-(8*4)-(2*8)(%r28) lfd %f7,-24-(8*4)-(2*8)(%r28)
lfd %f8,-16-(8*4)-(1*8)(%r28) lfd %f8,-24-(8*4)-(1*8)(%r28)
#endif #endif
2: 2:
/* Make the call. */ /* Make the call. */
lwz %r11, -20(%r28)
bctrl bctrl
/* Now, deal with the return value. */ /* Now, deal with the return value. */
@@ -125,11 +127,24 @@ L(done_return_value):
lwz %r30, -8(%r28) lwz %r30, -8(%r28)
lwz %r29,-12(%r28) lwz %r29,-12(%r28)
lwz %r28,-16(%r28) lwz %r28,-16(%r28)
.cfi_remember_state
/* At this point we don't have a cfa register. Say all our
saved regs have been restored. */
.cfi_same_value 65
.cfi_same_value 31
.cfi_same_value 30
.cfi_same_value 29
.cfi_same_value 28
/* Hopefully this works.. */
.cfi_def_cfa_register 1
.cfi_offset 1, 0
lwz %r1,0(%r1) lwz %r1,0(%r1)
.cfi_same_value 1
blr blr
#ifndef __NO_FPRS__ #ifndef __NO_FPRS__
L(fp_return_value): L(fp_return_value):
.cfi_restore_state
bf 28,L(float_return_value) bf 28,L(float_return_value)
stfd %f1,0(%r30) stfd %f1,0(%r30)
mtcrf 0x02,%r31 /* cr6 */ mtcrf 0x02,%r31 /* cr6 */
@@ -150,70 +165,10 @@ L(small_struct_return_value):
stw %r3, 0(%r30) stw %r3, 0(%r30)
stw %r4, 4(%r30) stw %r4, 4(%r30)
b L(done_return_value) b L(done_return_value)
.cfi_endproc
.LFE1:
END(ffi_call_SYSV) END(ffi_call_SYSV)
.section ".eh_frame",EH_FRAME_FLAGS,@progbits
.Lframe1:
.4byte .LECIE1-.LSCIE1 /* Length of Common Information Entry */
.LSCIE1:
.4byte 0x0 /* CIE Identifier Tag */
.byte 0x1 /* CIE Version */
#if defined _RELOCATABLE || defined __PIC__
.ascii "zR\0" /* CIE Augmentation */
#else
.ascii "\0" /* CIE Augmentation */
#endif
.uleb128 0x1 /* CIE Code Alignment Factor */
.sleb128 -4 /* CIE Data Alignment Factor */
.byte 0x41 /* CIE RA Column */
#if defined _RELOCATABLE || defined __PIC__
.uleb128 0x1 /* Augmentation size */
.byte 0x1b /* FDE Encoding (pcrel sdata4) */
#endif
.byte 0xc /* DW_CFA_def_cfa */
.uleb128 0x1
.uleb128 0x0
.align 2
.LECIE1:
.LSFDE1:
.4byte .LEFDE1-.LASFDE1 /* FDE Length */
.LASFDE1:
.4byte .LASFDE1-.Lframe1 /* FDE CIE offset */
#if defined _RELOCATABLE || defined __PIC__
.4byte .LFB1-. /* FDE initial location */
#else
.4byte .LFB1 /* FDE initial location */
#endif
.4byte .LFE1-.LFB1 /* FDE address range */
#if defined _RELOCATABLE || defined __PIC__
.uleb128 0x0 /* Augmentation size */
#endif
.byte 0x4 /* DW_CFA_advance_loc4 */
.4byte .LCFI0-.LFB1
.byte 0xd /* DW_CFA_def_cfa_register */
.uleb128 0x08
.byte 0x4 /* DW_CFA_advance_loc4 */
.4byte .LCFI5-.LCFI0
.byte 0x11 /* DW_CFA_offset_extended_sf */
.uleb128 0x41
.sleb128 -1
.byte 0x9f /* DW_CFA_offset, column 0x1f */
.uleb128 0x1
.byte 0x9e /* DW_CFA_offset, column 0x1e */
.uleb128 0x2
.byte 0x9d /* DW_CFA_offset, column 0x1d */
.uleb128 0x3
.byte 0x9c /* DW_CFA_offset, column 0x1c */
.uleb128 0x4
.byte 0x4 /* DW_CFA_advance_loc4 */
.4byte .LCFI6-.LCFI5
.byte 0xd /* DW_CFA_def_cfa_register */
.uleb128 0x1c
.align 2
.LEFDE1:
#if defined __ELF__ && defined __linux__ #if defined __ELF__ && defined __linux__
.section .note.GNU-stack,"",@progbits .section .note.GNU-stack,"",@progbits
#endif #endif