sparc: Add support for complex types

This commit is contained in:
Richard Henderson
2014-10-26 13:16:03 -07:00
parent 20da5b4132
commit ad89c2d9e9
8 changed files with 227 additions and 73 deletions

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)
/* Passed by reference. */ {
z = 4; case FFI_TYPE_STRUCT:
else case FFI_TYPE_LONGDOUBLE:
z = ALIGN(z, 4); by_reference:
/* Passed by reference. */
z = 4;
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);
}
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();
} }

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)

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 ----------------------------------------- */

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

View File

@@ -1,8 +1,8 @@
/* ----------------------------------------------------------------------- /* -----------------------------------------------------------------------
v8.S - Copyright (c) 2013 The Written Word, Inc. v8.S - Copyright (c) 2013 The Written Word, Inc.
Copyright (c) 1996, 1997, 2003, 2004, 2008 Red Hat, Inc. Copyright (c) 1996, 1997, 2003, 2004, 2008 Red Hat, Inc.
SPARC Foreign Function Interface SPARC Foreign Function Interface
Permission is hereby granted, free of charge, to any person obtaining Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the a copy of this software and associated documentation files (the
@@ -25,7 +25,7 @@
DEALINGS IN THE SOFTWARE. DEALINGS IN THE SOFTWARE.
----------------------------------------------------------------------- */ ----------------------------------------------------------------------- */
#define LIBFFI_ASM #define LIBFFI_ASM
#include <fficonfig.h> #include <fficonfig.h>
#include <ffi.h> #include <ffi.h>
#include <ffi_cfi.h> #include <ffi_cfi.h>
@@ -45,7 +45,7 @@
.text .text
#ifndef __GNUC__ #ifndef __GNUC__
.align 8 .align 8
.globl C(ffi_flush_icache) .globl C(ffi_flush_icache)
.type C(ffi_flush_icache),@function .type C(ffi_flush_icache),@function
@@ -75,7 +75,7 @@ C(ffi_flush_icache):
.globl C(ffi_call_v8) .globl C(ffi_call_v8)
.type C(ffi_call_v8),@function .type C(ffi_call_v8),@function
FFI_HIDDEN(C(ffi_call_v8)) FFI_HIDDEN(C(ffi_call_v8))
C(ffi_call_v8): C(ffi_call_v8):
cfi_startproc cfi_startproc
! Allocate a stack frame sized by ffi_call. ! Allocate a stack frame sized by ffi_call.
@@ -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,8 +244,8 @@ 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
2: 2:
@@ -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
E SPARC_RET_F_8 ldd [%i2+8], %i2
unimp ret
E SPARC_RET_F_6 restore
unimp E SPARC_RET_F_8
E SPARC_RET_F_4 ld [%i2+7*4], %f7
unimp nop
E SPARC_RET_F_2 ld [%i2+6*4], %f6
ldd [%fp-8], %f0 nop
E SPARC_RET_F_6
ld [%i2+5*4], %f5
nop
ld [%i2+4*4], %f4
nop
E SPARC_RET_F_4
ld [%i2+3*4], %f3
nop
ld [%i2+2*4], %f2
nop
E SPARC_RET_F_2
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

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

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 {

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