sparc: Handle more cases of structure return directly

This commit is contained in:
Richard Henderson
2014-10-25 16:24:41 -07:00
parent 0686c2e71c
commit 20da5b4132
5 changed files with 152 additions and 105 deletions

View File

@@ -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:

View File

@@ -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;

View File

@@ -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

View File

@@ -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)

View File

@@ -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