From 20da5b41324de524ea3ee1f84f402828b7c332dc Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Sat, 25 Oct 2014 16:24:41 -0700 Subject: [PATCH] sparc: Handle more cases of structure return directly --- src/sparc/ffi.c | 4 +- src/sparc/ffi64.c | 40 +++++++++++++--- src/sparc/internal.h | 24 ++++++---- src/sparc/v8.S | 77 ++++++++++++++--------------- src/sparc/v9.S | 112 +++++++++++++++++++++++++------------------ 5 files changed, 152 insertions(+), 105 deletions(-) diff --git a/src/sparc/ffi.c b/src/sparc/ffi.c index 75428473..1b8f48ec 100644 --- a/src/sparc/ffi.c +++ b/src/sparc/ffi.c @@ -59,10 +59,10 @@ ffi_prep_cif_machdep(ffi_cif *cif) flags = SPARC_RET_VOID; break; case FFI_TYPE_FLOAT: - flags = SPARC_RET_FLOAT; + flags = SPARC_RET_F_1; break; case FFI_TYPE_DOUBLE: - flags = SPARC_RET_DOUBLE; + flags = SPARC_RET_F_2; break; case FFI_TYPE_LONGDOUBLE: case FFI_TYPE_STRUCT: diff --git a/src/sparc/ffi64.c b/src/sparc/ffi64.c index 65ae4381..ab3ed091 100644 --- a/src/sparc/ffi64.c +++ b/src/sparc/ffi64.c @@ -66,7 +66,6 @@ ffi_struct_float_mask (ffi_type *struct_type, int size_mask) { case FFI_TYPE_STRUCT: size_mask = ffi_struct_float_mask (t, size_mask); - size_mask = ALIGN(size_mask, FFI_SIZEOF_ARG); continue; case FFI_TYPE_FLOAT: case FFI_TYPE_DOUBLE: @@ -154,13 +153,13 @@ ffi_prep_cif_machdep(ffi_cif *cif) flags = SPARC_RET_VOID; break; case FFI_TYPE_FLOAT: - flags = SPARC_RET_FLOAT; + flags = SPARC_RET_F_1; break; case FFI_TYPE_DOUBLE: - flags = SPARC_RET_DOUBLE; + flags = SPARC_RET_F_2; break; case FFI_TYPE_LONGDOUBLE: - flags = SPARC_RET_LDOUBLE; + flags = SPARC_RET_F_4; break; case FFI_TYPE_STRUCT: @@ -171,8 +170,37 @@ ffi_prep_cif_machdep(ffi_cif *cif) } else { - flags = ffi_struct_float_mask (rtype, 0) << SPARC_FLTMASK_SHIFT; - flags |= SPARC_RET_STRUCT; + int size_mask = ffi_struct_float_mask (rtype, 0); + int word_size = (size_mask >> 2) & 0x3f; + int all_mask = (1 << word_size) - 1; + int fp_mask = size_mask >> 8; + + flags = (size_mask << SPARC_FLTMASK_SHIFT) | SPARC_RET_STRUCT; + + /* For special cases of all-int or all-fp, we can return + the value directly without popping through a struct copy. */ + if (fp_mask == 0) + { + if (rtype->alignment >= 8) + { + if (rtype->size == 8) + flags = SPARC_RET_INT64; + else if (rtype->size == 16) + flags = SPARC_RET_INT128; + } + } + else if (fp_mask == all_mask) + switch (word_size) + { + case 1: flags = SPARC_RET_F_1; break; + case 2: flags = SPARC_RET_F_2; break; + case 3: flags = SPARC_RET_F_3; break; + case 4: flags = SPARC_RET_F_4; break; + /* 5 word structures skipped; handled via RET_STRUCT. */ + case 6: flags = SPARC_RET_F_6; break; + /* 7 word structures skipped; handled via RET_STRUCT. */ + case 8: flags = SPARC_RET_F_8; break; + } } break; diff --git a/src/sparc/internal.h b/src/sparc/internal.h index 30189280..b4494d9e 100644 --- a/src/sparc/internal.h +++ b/src/sparc/internal.h @@ -1,17 +1,21 @@ #define SPARC_RET_VOID 0 #define SPARC_RET_STRUCT 1 -#define SPARC_RET_FLOAT 2 -#define SPARC_RET_DOUBLE 3 -#define SPARC_RET_UINT8 4 -#define SPARC_RET_SINT8 5 -#define SPARC_RET_UINT16 6 -#define SPARC_RET_SINT16 7 +#define SPARC_RET_UINT8 2 +#define SPARC_RET_SINT8 3 +#define SPARC_RET_UINT16 4 +#define SPARC_RET_SINT16 5 +#define SPARC_RET_UINT32 6 +#define SPARC_RET_SINT32 7 /* v9 only */ #define SPARC_RET_INT64 8 -#define SPARC_RET_UINT32 9 +#define SPARC_RET_INT128 9 /* v9 only */ -/* These two are only used for V9. */ -#define SPARC_RET_SINT32 10 -#define SPARC_RET_LDOUBLE 11 +/* Note that F_7 is missing, and is handled by SPARC_RET_STRUCT. */ +#define SPARC_RET_F_8 10 +#define SPARC_RET_F_6 11 /* v9 only */ +#define SPARC_RET_F_4 12 +#define SPARC_RET_F_2 13 +#define SPARC_RET_F_3 14 /* v9 only */ +#define SPARC_RET_F_1 15 #define SPARC_FLAG_RET_MASK 15 #define SPARC_FLAG_RET_IN_MEM 32 diff --git a/src/sparc/v8.S b/src/sparc/v8.S index b0d50a34..4adcf6d1 100644 --- a/src/sparc/v8.S +++ b/src/sparc/v8.S @@ -118,15 +118,6 @@ E SPARC_RET_VOID restore E SPARC_RET_STRUCT unimp -E SPARC_RET_FLOAT - st %f0, [%i2] - ret - restore -E SPARC_RET_DOUBLE - std %f0, [%i2] - ret - restore - nop E SPARC_RET_UINT8 and %o0, 0xff, %o0 st %o0, [%i2] @@ -144,28 +135,34 @@ E SPARC_RET_SINT16 sll %o0, 16, %o0 b 7f sra %o0, 16, %o0 -E SPARC_RET_INT64 - std %o0, [%i2] - ret - restore E SPARC_RET_UINT32 7: st %o0, [%i2] ret restore - - ! Unused entries. Don't allow bad data to do worse things. -E 10 +E SPARC_RET_SINT32 unimp -E 11 +E SPARC_RET_INT64 + std %o0, [%i2] + ret + restore +E SPARC_RET_INT128 unimp -E 12 +E SPARC_RET_F_8 unimp -E 13 +E SPARC_RET_F_6 unimp -E 14 +E SPARC_RET_F_4 unimp -E 15 +E SPARC_RET_F_2 + std %f0, [%i2] + ret + restore +E SPARC_RET_F_3 unimp +E SPARC_RET_F_1 + st %f0, [%i2] + ret + restore ! Struct returning functions expect and skip the unimp here. .align 8 @@ -234,14 +231,6 @@ E SPARC_RET_VOID E SPARC_RET_STRUCT jmp %i7+12 restore -E SPARC_RET_FLOAT - ld [%fp-8], %f0 - ret - restore -E SPARC_RET_DOUBLE - ldd [%fp-8], %f0 - ret - restore E SPARC_RET_UINT8 ldub [%fp-8+3], %i0 ret @@ -258,28 +247,34 @@ E SPARC_RET_SINT16 ldsh [%fp-8+2], %i0 ret restore -E SPARC_RET_INT64 - ldd [%fp-8], %i0 - ret - restore E SPARC_RET_UINT32 ld [%fp-8], %i0 ret restore - - ! Unused entries. Don't allow bad data to do worse things. -E 10 +E SPARC_RET_SINT32 unimp -E 11 +E SPARC_RET_INT64 + ldd [%fp-8], %i0 + ret + restore +E SPARC_RET_INT128 unimp -E 12 +E SPARC_RET_F_8 unimp -E 13 +E SPARC_RET_F_6 unimp -E 14 +E SPARC_RET_F_4 unimp -E 15 +E SPARC_RET_F_2 + ldd [%fp-8], %f0 + ret + restore +E SPARC_RET_F_3 unimp +E SPARC_RET_F_1 + ld [%fp-8], %f0 + ret + restore cfi_endproc .size C(ffi_closure_v8), . - C(ffi_closure_v8) diff --git a/src/sparc/v9.S b/src/sparc/v9.S index 3d91f2d1..d893d2f4 100644 --- a/src/sparc/v9.S +++ b/src/sparc/v9.S @@ -114,12 +114,6 @@ E SPARC_RET_STRUCT sub %sp, 64, %sp b 8f stx %o0, [%l2] -E SPARC_RET_FLOAT - return %i7+8 - st %f0, [%o2] -E SPARC_RET_DOUBLE - return %i7+8 - std %f0, [%o2] E SPARC_RET_UINT8 and %o0, 0xff, %i0 return %i7+8 @@ -139,10 +133,6 @@ E SPARC_RET_SINT16 sra %o0, 16, %i0 return %i7+8 stx %o0, [%o2] -E SPARC_RET_INT64 - stx %o0, [%i2] - return %i7+8 - nop E SPARC_RET_UINT32 srl %o0, 0, %i0 return %i7+8 @@ -151,20 +141,40 @@ E SPARC_RET_SINT32 sra %o0, 0, %i0 return %i7+8 stx %o0, [%o2] -E SPARC_RET_LDOUBLE - std %f0, [%i2] +E SPARC_RET_INT64 + stx %o0, [%i2] return %i7+8 - std %f2, [%o2+8] - - ! Unused entries. Don't allow bad data to do worse things. -E 12 - unimp -E 13 - unimp -E 14 - unimp -E 15 - unimp + nop +E SPARC_RET_INT128 + stx %o0, [%i2] + stx %o1, [%i2+8] + return %i7+8 + nop +E SPARC_RET_F_8 + st %f7, [%i2+7*4] + nop + st %f6, [%i2+6*4] + nop +E SPARC_RET_F_6 + st %f5, [%i2+5*4] + nop + st %f4, [%i2+4*4] + nop +E SPARC_RET_F_4 + std %f2, [%i2+2*4] + return %i7+8 + std %f0, [%o2] +E SPARC_RET_F_2 + return %i7+8 + std %f0, [%o2] +E SPARC_RET_F_3 + st %f2, [%i2+2*4] + nop + st %f1, [%i2+1*4] + nop +E SPARC_RET_F_1 + return %i7+8 + st %f0, [%o2] ! Finish the SPARC_RET_STRUCT sequence. .align 8 @@ -264,14 +274,6 @@ E SPARC_RET_STRUCT ldd [FP-160], %f0 b 8f ldx [FP-152], %i1 -E SPARC_RET_FLOAT - ld [FP-160], %f0 - return %i7+8 - nop -E SPARC_RET_DOUBLE - ldd [FP-160], %f0 - return %i7+8 - nop E SPARC_RET_UINT8 ldub [FP-160+7], %i0 return %i7+8 @@ -288,10 +290,6 @@ E SPARC_RET_SINT16 ldsh [FP-160+6], %i0 return %i7+8 nop -E SPARC_RET_INT64 - ldx [FP-160], %i0 - return %i7+8 - nop E SPARC_RET_UINT32 lduw [FP-160+4], %i0 return %i7+8 @@ -300,21 +298,43 @@ E SPARC_RET_SINT32 ldsw [FP-160+4], %i0 return %i7+8 nop -E SPARC_RET_LDOUBLE +E SPARC_RET_INT64 + ldx [FP-160], %i0 + return %i7+8 + nop +E SPARC_RET_INT128 + ldx [FP-160], %i0 + ldx [FP-160+8], %i1 + return %i7+8 + nop +E SPARC_RET_F_8 + ld [FP-160+7*4], %f7 + nop + ld [FP-160+6*4], %f6 + nop +E SPARC_RET_F_6 + ld [FP-160+5*4], %f5 + nop + ld [FP-160+4*4], %f4 + nop +E SPARC_RET_F_4 ldd [FP-160], %f0 ldd [FP-160+8], %f2 return %i7+8 nop - - ! Unused entries. Don't allow bad data to do worse things. -E 12 - unimp -E 13 - unimp -E 14 - unimp -E 15 - unimp +E SPARC_RET_F_2 + ldd [FP-160], %f0 + return %i7+8 + nop +E SPARC_RET_F_3 + ld [FP-160+2*4], %f2 + nop + ld [FP-160+1*4], %f1 + nop +E SPARC_RET_F_1 + ld [FP-160], %f0 + return %i7+8 + nop ! Finish the SPARC_RET_STRUCT sequence. .align 8