sparc: Add support for complex types

This commit is contained in:
Richard Henderson
2014-11-12 09:36:09 +01:00
parent 20da5b4132
commit ad89c2d9e9
8 changed files with 223 additions and 69 deletions
+83 -3
View File
@@ -90,6 +90,40 @@ ffi_prep_cif_machdep(ffi_cif *cif)
case FFI_TYPE_UINT64: case FFI_TYPE_UINT64:
flags = SPARC_RET_INT64; flags = SPARC_RET_INT64;
break; break;
case FFI_TYPE_COMPLEX:
rtt = rtype->elements[0]->type;
switch (rtt)
{
case FFI_TYPE_FLOAT:
flags = SPARC_RET_F_2;
break;
case FFI_TYPE_DOUBLE:
flags = SPARC_RET_F_4;
break;
case FFI_TYPE_LONGDOUBLE:
flags = SPARC_RET_F_8;
break;
case FFI_TYPE_SINT64:
case FFI_TYPE_UINT64:
flags = SPARC_RET_INT128;
break;
case FFI_TYPE_INT:
case FFI_TYPE_SINT32:
case FFI_TYPE_UINT32:
flags = SPARC_RET_INT64;
break;
case FFI_TYPE_SINT16:
case FFI_TYPE_UINT16:
flags = SP_V8_RET_CPLX16;
break;
case FFI_TYPE_SINT8:
case FFI_TYPE_UINT8:
flags = SP_V8_RET_CPLX8;
break;
default:
abort();
}
break;
default: default:
abort(); abort();
} }
@@ -102,11 +136,24 @@ ffi_prep_cif_machdep(ffi_cif *cif)
size_t z = ty->size; size_t z = ty->size;
int tt = ty->type; int tt = ty->type;
if (tt == FFI_TYPE_STRUCT || tt == FFI_TYPE_LONGDOUBLE) switch (tt)
{
case FFI_TYPE_STRUCT:
case FFI_TYPE_LONGDOUBLE:
by_reference:
/* Passed by reference. */ /* Passed by reference. */
z = 4; z = 4;
else break;
case FFI_TYPE_COMPLEX:
tt = ty->elements[0]->type;
if (tt == FFI_TYPE_FLOAT || z > 8)
goto by_reference;
/* FALLTHRU */
default:
z = ALIGN(z, 4); z = ALIGN(z, 4);
}
bytes += z; bytes += z;
} }
@@ -169,11 +216,14 @@ ffi_prep_args_v8(ffi_cif *cif, unsigned long *argp, void *rvalue, void **avalue)
{ {
ffi_type *ty = p_arg[i]; ffi_type *ty = p_arg[i];
void *a = avalue[i]; void *a = avalue[i];
int tt = ty->type;
size_t z;
switch (ty->type) switch (tt)
{ {
case FFI_TYPE_STRUCT: case FFI_TYPE_STRUCT:
case FFI_TYPE_LONGDOUBLE: case FFI_TYPE_LONGDOUBLE:
by_reference:
*argp++ = (unsigned long)a; *argp++ = (unsigned long)a;
break; break;
@@ -205,6 +255,23 @@ ffi_prep_args_v8(ffi_cif *cif, unsigned long *argp, void *rvalue, void **avalue)
*argp++ = *(SINT16 *)a; *argp++ = *(SINT16 *)a;
break; break;
case FFI_TYPE_COMPLEX:
tt = ty->elements[0]->type;
z = ty->size;
if (tt == FFI_TYPE_FLOAT || z > 8)
goto by_reference;
if (z < 4)
{
memcpy((char *)argp + 4 - z, a, z);
argp++;
}
else
{
memcpy(argp, a, z);
argp += z / 4;
}
break;
default: default:
abort(); abort();
} }
@@ -299,11 +366,13 @@ ffi_closure_sparc_inner_v8(ffi_closure *closure, void *rvalue,
ffi_type *ty = arg_types[i]; ffi_type *ty = arg_types[i];
int tt = ty->type; int tt = ty->type;
void *a = argp; void *a = argp;
size_t z;
switch (tt) switch (tt)
{ {
case FFI_TYPE_STRUCT: case FFI_TYPE_STRUCT:
case FFI_TYPE_LONGDOUBLE: case FFI_TYPE_LONGDOUBLE:
by_reference:
/* Straight copy of invisible reference. */ /* Straight copy of invisible reference. */
a = (void *)*argp; a = (void *)*argp;
break; break;
@@ -336,6 +405,17 @@ ffi_closure_sparc_inner_v8(ffi_closure *closure, void *rvalue,
a += 3; a += 3;
break; break;
case FFI_TYPE_COMPLEX:
tt = ty->elements[0]->type;
z = ty->size;
if (tt == FFI_TYPE_FLOAT || z > 8)
goto by_reference;
if (z < 4)
a += 4 - z;
else if (z > 4)
argp++;
break;
default: default:
abort(); abort();
} }
+39 -9
View File
@@ -52,14 +52,28 @@
and addition work correctly. The mask is placed in the second byte. */ and addition work correctly. The mask is placed in the second byte. */
static int static int
ffi_struct_float_mask (ffi_type *struct_type, int size_mask) ffi_struct_float_mask (ffi_type *outer_type, int size_mask)
{ {
ffi_type **elts, *t; ffi_type **elts;
ffi_type *t;
for (elts = struct_type->elements; (t = *elts) != NULL; elts++) if (outer_type->type == FFI_TYPE_COMPLEX)
{
int m = 0, tt = outer_type->elements[0]->type;
size_t z = outer_type->size;
if (tt == FFI_TYPE_FLOAT
|| tt == FFI_TYPE_DOUBLE
|| tt == FFI_TYPE_LONGDOUBLE)
m = (1 << (z / 4)) - 1;
return (m << 8) | z;
}
FFI_ASSERT (outer_type->type == FFI_TYPE_STRUCT);
for (elts = outer_type->elements; (t = *elts) != NULL; elts++)
{ {
size_t z = t->size; size_t z = t->size;
int o, m; int o, m, tt;
size_mask = ALIGN(size_mask, t->alignment); size_mask = ALIGN(size_mask, t->alignment);
switch (t->type) switch (t->type)
@@ -67,6 +81,13 @@ ffi_struct_float_mask (ffi_type *struct_type, int size_mask)
case FFI_TYPE_STRUCT: case FFI_TYPE_STRUCT:
size_mask = ffi_struct_float_mask (t, size_mask); size_mask = ffi_struct_float_mask (t, size_mask);
continue; continue;
case FFI_TYPE_COMPLEX:
tt = t->elements[0]->type;
if (tt != FFI_TYPE_FLOAT
&& tt != FFI_TYPE_DOUBLE
&& tt != FFI_TYPE_LONGDOUBLE)
break;
/* FALLTHRU */
case FFI_TYPE_FLOAT: case FFI_TYPE_FLOAT:
case FFI_TYPE_DOUBLE: case FFI_TYPE_DOUBLE:
case FFI_TYPE_LONGDOUBLE: case FFI_TYPE_LONGDOUBLE:
@@ -78,8 +99,8 @@ ffi_struct_float_mask (ffi_type *struct_type, int size_mask)
size_mask += z; size_mask += z;
} }
size_mask = ALIGN(size_mask, struct_type->alignment); size_mask = ALIGN(size_mask, outer_type->alignment);
FFI_ASSERT ((size_mask & 0xff) == struct_type->size); FFI_ASSERT ((size_mask & 0xff) == outer_type->size);
return size_mask; return size_mask;
} }
@@ -162,6 +183,7 @@ ffi_prep_cif_machdep(ffi_cif *cif)
flags = SPARC_RET_F_4; flags = SPARC_RET_F_4;
break; break;
case FFI_TYPE_COMPLEX:
case FFI_TYPE_STRUCT: case FFI_TYPE_STRUCT:
if (rtype->size > 32) if (rtype->size > 32)
{ {
@@ -194,7 +216,7 @@ ffi_prep_cif_machdep(ffi_cif *cif)
{ {
case 1: flags = SPARC_RET_F_1; break; case 1: flags = SPARC_RET_F_1; break;
case 2: flags = SPARC_RET_F_2; break; case 2: flags = SPARC_RET_F_2; break;
case 3: flags = SPARC_RET_F_3; break; case 3: flags = SP_V9_RET_F_3; break;
case 4: flags = SPARC_RET_F_4; break; case 4: flags = SPARC_RET_F_4; break;
/* 5 word structures skipped; handled via RET_STRUCT. */ /* 5 word structures skipped; handled via RET_STRUCT. */
case 6: flags = SPARC_RET_F_6; break; case 6: flags = SPARC_RET_F_6; break;
@@ -218,7 +240,7 @@ ffi_prep_cif_machdep(ffi_cif *cif)
break; break;
case FFI_TYPE_INT: case FFI_TYPE_INT:
case FFI_TYPE_SINT32: case FFI_TYPE_SINT32:
flags = SPARC_RET_SINT32; flags = SP_V9_RET_SINT32;
break; break;
case FFI_TYPE_UINT32: case FFI_TYPE_UINT32:
flags = SPARC_RET_UINT32; flags = SPARC_RET_UINT32;
@@ -242,6 +264,7 @@ ffi_prep_cif_machdep(ffi_cif *cif)
switch (ty->type) switch (ty->type)
{ {
case FFI_TYPE_COMPLEX:
case FFI_TYPE_STRUCT: case FFI_TYPE_STRUCT:
/* Large structs passed by reference. */ /* Large structs passed by reference. */
if (z > 16) if (z > 16)
@@ -249,7 +272,12 @@ ffi_prep_cif_machdep(ffi_cif *cif)
a = z = 8; a = z = 8;
break; break;
} }
/* ??? FALLTHRU -- check for fp members in the struct. */ /* Small structs may be passed in integer or fp regs or both. */
if (bytes >= 16*8)
break;
if ((ffi_struct_float_mask (ty, 0) & 0xff00) == 0)
break;
/* FALLTHRU */
case FFI_TYPE_FLOAT: case FFI_TYPE_FLOAT:
case FFI_TYPE_DOUBLE: case FFI_TYPE_DOUBLE:
case FFI_TYPE_LONGDOUBLE: case FFI_TYPE_LONGDOUBLE:
@@ -351,6 +379,7 @@ ffi_prep_args_v9(ffi_cif *cif, unsigned long *argp, void *rvalue, void **avalue)
break; break;
case FFI_TYPE_LONGDOUBLE: case FFI_TYPE_LONGDOUBLE:
case FFI_TYPE_COMPLEX:
case FFI_TYPE_STRUCT: case FFI_TYPE_STRUCT:
z = ty->size; z = ty->size;
if (z > 16) if (z > 16)
@@ -466,6 +495,7 @@ ffi_closure_sparc_inner_v9(ffi_closure *closure, void *rvalue,
argx = argn + 1; argx = argn + 1;
switch (ty->type) switch (ty->type)
{ {
case FFI_TYPE_COMPLEX:
case FFI_TYPE_STRUCT: case FFI_TYPE_STRUCT:
z = ty->size; z = ty->size;
if (z > 16) if (z > 16)
+1
View File
@@ -58,6 +58,7 @@ typedef enum ffi_abi {
#endif #endif
#define FFI_TARGET_SPECIFIC_STACK_SPACE_ALLOCATION #define FFI_TARGET_SPECIFIC_STACK_SPACE_ALLOCATION
#define FFI_TARGET_HAS_COMPLEX_TYPE
/* ---- Definitions for closures ----------------------------------------- */ /* ---- Definitions for closures ----------------------------------------- */
+6 -4
View File
@@ -5,16 +5,18 @@
#define SPARC_RET_UINT16 4 #define SPARC_RET_UINT16 4
#define SPARC_RET_SINT16 5 #define SPARC_RET_SINT16 5
#define SPARC_RET_UINT32 6 #define SPARC_RET_UINT32 6
#define SPARC_RET_SINT32 7 /* v9 only */ #define SP_V9_RET_SINT32 7 /* v9 only */
#define SP_V8_RET_CPLX16 7 /* v8 only */
#define SPARC_RET_INT64 8 #define SPARC_RET_INT64 8
#define SPARC_RET_INT128 9 /* v9 only */ #define SPARC_RET_INT128 9
/* Note that F_7 is missing, and is handled by SPARC_RET_STRUCT. */ /* Note that F_7 is missing, and is handled by SPARC_RET_STRUCT. */
#define SPARC_RET_F_8 10 #define SPARC_RET_F_8 10
#define SPARC_RET_F_6 11 /* v9 only */ #define SPARC_RET_F_6 11
#define SPARC_RET_F_4 12 #define SPARC_RET_F_4 12
#define SPARC_RET_F_2 13 #define SPARC_RET_F_2 13
#define SPARC_RET_F_3 14 /* v9 only */ #define SP_V9_RET_F_3 14 /* v9 only */
#define SP_V8_RET_CPLX8 14 /* v8 only */
#define SPARC_RET_F_1 15 #define SPARC_RET_F_1 15
#define SPARC_FLAG_RET_MASK 15 #define SPARC_FLAG_RET_MASK 15
+78 -38
View File
@@ -139,26 +139,44 @@ E SPARC_RET_UINT32
7: st %o0, [%i2] 7: st %o0, [%i2]
ret ret
restore restore
E SPARC_RET_SINT32 E SP_V8_RET_CPLX16
unimp sth %o0, [%i2+2]
b 9f
srl %o0, 16, %o0
E SPARC_RET_INT64 E SPARC_RET_INT64
std %o0, [%i2] st %o0, [%i2]
st %o1, [%i2+4]
ret ret
restore restore
E SPARC_RET_INT128 E SPARC_RET_INT128
unimp std %o0, [%i2]
E SPARC_RET_F_8 std %o2, [%i2+8]
unimp
E SPARC_RET_F_6
unimp
E SPARC_RET_F_4
unimp
E SPARC_RET_F_2
std %f0, [%i2]
ret ret
restore restore
E SPARC_RET_F_3 E SPARC_RET_F_8
unimp 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
st %f3, [%i2+3*4]
nop
st %f2, [%i2+2*4]
nop
E SPARC_RET_F_2
st %f1, [%i2+4]
st %f0, [%i2]
ret
restore
E SP_V8_RET_CPLX8
stb %o0, [%i2+1]
b 10f
srl %o0, 8, %o0
E SPARC_RET_F_1 E SPARC_RET_F_1
st %f0, [%i2] st %f0, [%i2]
ret ret
@@ -172,16 +190,22 @@ E SPARC_RET_F_1
ret ret
restore restore
.align 8
9: sth %o0, [%i2]
ret
restore
.align 8
10: stb %o0, [%i2]
ret
restore
cfi_endproc cfi_endproc
.size C(ffi_call_v8),. - C(ffi_call_v8) .size C(ffi_call_v8),. - C(ffi_call_v8)
#undef STACKFRAME /* 16*4 register window + 1*4 struct return + 6*4 args backing store
#define STACKFRAME 104 /* 16*4 register window + + 8*4 return storage + 1*4 alignment. */
1*4 struct return + #define STACKFRAME (16*4 + 4 + 6*4 + 8*4 + 4)
6*4 args backing store +
2*4 return storage +
1*4 alignment */
/* ffi_closure_v8(...) /* ffi_closure_v8(...)
@@ -211,7 +235,7 @@ C(ffi_closure_v8):
! Call ffi_closure_sparc_inner to do the bulk of the work. ! Call ffi_closure_sparc_inner to do the bulk of the work.
mov %g2, %o0 mov %g2, %o0
add %fp, -8, %o1 add %fp, -8*4, %o1
call ffi_closure_sparc_inner_v8 call ffi_closure_sparc_inner_v8
add %fp, 64, %o2 add %fp, 64, %o2
@@ -220,7 +244,7 @@ C(ffi_closure_v8):
1: sll %o0, 4, %o0 ! o0 = o0 * 16 1: sll %o0, 4, %o0 ! o0 = o0 * 16
add %o7, %o0, %o7 ! o7 = 0b + o0*16 add %o7, %o0, %o7 ! o7 = 0b + o0*16
jmp %o7+(2f-0b) jmp %o7+(2f-0b)
nop add %fp, -8*4, %i2
! Note that each entry is 4 insns, enforced by the E macro. ! Note that each entry is 4 insns, enforced by the E macro.
.align 16 .align 16
@@ -232,47 +256,63 @@ E SPARC_RET_STRUCT
jmp %i7+12 jmp %i7+12
restore restore
E SPARC_RET_UINT8 E SPARC_RET_UINT8
ldub [%fp-8+3], %i0 ldub [%i2+3], %i0
ret ret
restore restore
E SPARC_RET_SINT8 E SPARC_RET_SINT8
ldsb [%fp-8+3], %i0 ldsb [%i2+3], %i0
ret ret
restore restore
E SPARC_RET_UINT16 E SPARC_RET_UINT16
lduh [%fp-8+2], %i0 lduh [%i2+2], %i0
ret ret
restore restore
E SPARC_RET_SINT16 E SPARC_RET_SINT16
ldsh [%fp-8+2], %i0 ldsh [%i2+2], %i0
ret ret
restore restore
E SPARC_RET_UINT32 E SPARC_RET_UINT32
ld [%fp-8], %i0 ld [%i2], %i0
ret
restore
E SP_V8_RET_CPLX16
ld [%i2], %i0
ret ret
restore restore
E SPARC_RET_SINT32
unimp
E SPARC_RET_INT64 E SPARC_RET_INT64
ldd [%fp-8], %i0 ldd [%i2], %i0
ret ret
restore restore
E SPARC_RET_INT128 E SPARC_RET_INT128
unimp ldd [%i2], %i0
ldd [%i2+8], %i2
ret
restore
E SPARC_RET_F_8 E SPARC_RET_F_8
unimp ld [%i2+7*4], %f7
nop
ld [%i2+6*4], %f6
nop
E SPARC_RET_F_6 E SPARC_RET_F_6
unimp ld [%i2+5*4], %f5
nop
ld [%i2+4*4], %f4
nop
E SPARC_RET_F_4 E SPARC_RET_F_4
unimp ld [%i2+3*4], %f3
nop
ld [%i2+2*4], %f2
nop
E SPARC_RET_F_2 E SPARC_RET_F_2
ldd [%fp-8], %f0 ldd [%i2], %f0
ret
restore
E SP_V8_RET_CPLX8
lduh [%i2], %i0
ret ret
restore restore
E SPARC_RET_F_3
unimp
E SPARC_RET_F_1 E SPARC_RET_F_1
ld [%fp-8], %f0 ld [%i2], %f0
ret ret
restore restore
+4 -4
View File
@@ -137,7 +137,7 @@ E SPARC_RET_UINT32
srl %o0, 0, %i0 srl %o0, 0, %i0
return %i7+8 return %i7+8
stx %o0, [%o2] stx %o0, [%o2]
E SPARC_RET_SINT32 E SP_V9_RET_SINT32
sra %o0, 0, %i0 sra %o0, 0, %i0
return %i7+8 return %i7+8
stx %o0, [%o2] stx %o0, [%o2]
@@ -167,7 +167,7 @@ E SPARC_RET_F_4
E SPARC_RET_F_2 E SPARC_RET_F_2
return %i7+8 return %i7+8
std %f0, [%o2] std %f0, [%o2]
E SPARC_RET_F_3 E SP_V9_RET_F_3
st %f2, [%i2+2*4] st %f2, [%i2+2*4]
nop nop
st %f1, [%i2+1*4] st %f1, [%i2+1*4]
@@ -294,7 +294,7 @@ E SPARC_RET_UINT32
lduw [FP-160+4], %i0 lduw [FP-160+4], %i0
return %i7+8 return %i7+8
nop nop
E SPARC_RET_SINT32 E SP_V9_RET_SINT32
ldsw [FP-160+4], %i0 ldsw [FP-160+4], %i0
return %i7+8 return %i7+8
nop nop
@@ -326,7 +326,7 @@ E SPARC_RET_F_2
ldd [FP-160], %f0 ldd [FP-160], %f0
return %i7+8 return %i7+8
nop nop
E SPARC_RET_F_3 E SP_V9_RET_F_3
ld [FP-160+2*4], %f2 ld [FP-160+2*4], %f2
nop nop
ld [FP-160+1*4], %f1 ld [FP-160+1*4], %f1
+1
View File
@@ -31,6 +31,7 @@ if { [istarget aarch64*]
|| [istarget arm*] || [istarget arm*]
|| [istarget i?86*] || [istarget i?86*]
|| [istarget s390*] || [istarget s390*]
|| [istarget sparc*]
|| [istarget x86_64*] } { || [istarget x86_64*] } {
run-many-tests $ctlist "" run-many-tests $ctlist ""
} else { } else {
+2 -2
View File
@@ -12,9 +12,9 @@
_Complex int f_complex(_Complex int c, int x, int *py) _Complex int f_complex(_Complex int c, int x, int *py)
{ {
c = -(2 * creal (c)) + (cimag (c) + 1)* I; __real__ c = -2 * __real__ c;
__imag__ c = __imag__ c + 1;
*py += x; *py += x;
return c; return c;
} }