sparc: Handle more cases of structure return directly
This commit is contained in:
@@ -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:
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
112
src/sparc/v9.S
112
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
|
||||
|
||||
Reference in New Issue
Block a user