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:
flags = SPARC_RET_INT64;
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:
abort();
}
@@ -102,11 +136,24 @@ ffi_prep_cif_machdep(ffi_cif *cif)
size_t z = ty->size;
int tt = ty->type;
if (tt == FFI_TYPE_STRUCT || tt == FFI_TYPE_LONGDOUBLE)
/* Passed by reference. */
z = 4;
else
z = ALIGN(z, 4);
switch (tt)
{
case FFI_TYPE_STRUCT:
case FFI_TYPE_LONGDOUBLE:
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;
}
@@ -169,11 +216,14 @@ ffi_prep_args_v8(ffi_cif *cif, unsigned long *argp, void *rvalue, void **avalue)
{
ffi_type *ty = p_arg[i];
void *a = avalue[i];
int tt = ty->type;
size_t z;
switch (ty->type)
switch (tt)
{
case FFI_TYPE_STRUCT:
case FFI_TYPE_LONGDOUBLE:
by_reference:
*argp++ = (unsigned long)a;
break;
@@ -205,6 +255,23 @@ ffi_prep_args_v8(ffi_cif *cif, unsigned long *argp, void *rvalue, void **avalue)
*argp++ = *(SINT16 *)a;
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:
abort();
}
@@ -299,11 +366,13 @@ ffi_closure_sparc_inner_v8(ffi_closure *closure, void *rvalue,
ffi_type *ty = arg_types[i];
int tt = ty->type;
void *a = argp;
size_t z;
switch (tt)
{
case FFI_TYPE_STRUCT:
case FFI_TYPE_LONGDOUBLE:
by_reference:
/* Straight copy of invisible reference. */
a = (void *)*argp;
break;
@@ -336,6 +405,17 @@ ffi_closure_sparc_inner_v8(ffi_closure *closure, void *rvalue,
a += 3;
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:
abort();
}

View File

@@ -52,14 +52,28 @@
and addition work correctly. The mask is placed in the second byte. */
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;
int o, m;
int o, m, tt;
size_mask = ALIGN(size_mask, t->alignment);
switch (t->type)
@@ -67,6 +81,13 @@ ffi_struct_float_mask (ffi_type *struct_type, int size_mask)
case FFI_TYPE_STRUCT:
size_mask = ffi_struct_float_mask (t, size_mask);
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_DOUBLE:
case FFI_TYPE_LONGDOUBLE:
@@ -78,8 +99,8 @@ ffi_struct_float_mask (ffi_type *struct_type, int size_mask)
size_mask += z;
}
size_mask = ALIGN(size_mask, struct_type->alignment);
FFI_ASSERT ((size_mask & 0xff) == struct_type->size);
size_mask = ALIGN(size_mask, outer_type->alignment);
FFI_ASSERT ((size_mask & 0xff) == outer_type->size);
return size_mask;
}
@@ -162,6 +183,7 @@ ffi_prep_cif_machdep(ffi_cif *cif)
flags = SPARC_RET_F_4;
break;
case FFI_TYPE_COMPLEX:
case FFI_TYPE_STRUCT:
if (rtype->size > 32)
{
@@ -194,7 +216,7 @@ ffi_prep_cif_machdep(ffi_cif *cif)
{
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 3: flags = SP_V9_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;
@@ -218,7 +240,7 @@ ffi_prep_cif_machdep(ffi_cif *cif)
break;
case FFI_TYPE_INT:
case FFI_TYPE_SINT32:
flags = SPARC_RET_SINT32;
flags = SP_V9_RET_SINT32;
break;
case FFI_TYPE_UINT32:
flags = SPARC_RET_UINT32;
@@ -242,6 +264,7 @@ ffi_prep_cif_machdep(ffi_cif *cif)
switch (ty->type)
{
case FFI_TYPE_COMPLEX:
case FFI_TYPE_STRUCT:
/* Large structs passed by reference. */
if (z > 16)
@@ -249,7 +272,12 @@ ffi_prep_cif_machdep(ffi_cif *cif)
a = z = 8;
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_DOUBLE:
case FFI_TYPE_LONGDOUBLE:
@@ -351,6 +379,7 @@ ffi_prep_args_v9(ffi_cif *cif, unsigned long *argp, void *rvalue, void **avalue)
break;
case FFI_TYPE_LONGDOUBLE:
case FFI_TYPE_COMPLEX:
case FFI_TYPE_STRUCT:
z = ty->size;
if (z > 16)
@@ -466,6 +495,7 @@ ffi_closure_sparc_inner_v9(ffi_closure *closure, void *rvalue,
argx = argn + 1;
switch (ty->type)
{
case FFI_TYPE_COMPLEX:
case FFI_TYPE_STRUCT:
z = ty->size;
if (z > 16)

View File

@@ -58,6 +58,7 @@ typedef enum ffi_abi {
#endif
#define FFI_TARGET_SPECIFIC_STACK_SPACE_ALLOCATION
#define FFI_TARGET_HAS_COMPLEX_TYPE
/* ---- Definitions for closures ----------------------------------------- */

View File

@@ -5,16 +5,18 @@
#define SPARC_RET_UINT16 4
#define SPARC_RET_SINT16 5
#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_INT128 9 /* v9 only */
#define SPARC_RET_INT128 9
/* 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_6 11
#define SPARC_RET_F_4 12
#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_FLAG_RET_MASK 15

View File

@@ -1,8 +1,8 @@
/* -----------------------------------------------------------------------
v8.S - Copyright (c) 2013 The Written Word, 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
a copy of this software and associated documentation files (the
@@ -25,7 +25,7 @@
DEALINGS IN THE SOFTWARE.
----------------------------------------------------------------------- */
#define LIBFFI_ASM
#define LIBFFI_ASM
#include <fficonfig.h>
#include <ffi.h>
#include <ffi_cfi.h>
@@ -45,7 +45,7 @@
.text
#ifndef __GNUC__
#ifndef __GNUC__
.align 8
.globl C(ffi_flush_icache)
.type C(ffi_flush_icache),@function
@@ -75,7 +75,7 @@ C(ffi_flush_icache):
.globl C(ffi_call_v8)
.type C(ffi_call_v8),@function
FFI_HIDDEN(C(ffi_call_v8))
C(ffi_call_v8):
cfi_startproc
! Allocate a stack frame sized by ffi_call.
@@ -139,26 +139,44 @@ E SPARC_RET_UINT32
7: st %o0, [%i2]
ret
restore
E SPARC_RET_SINT32
unimp
E SP_V8_RET_CPLX16
sth %o0, [%i2+2]
b 9f
srl %o0, 16, %o0
E SPARC_RET_INT64
std %o0, [%i2]
st %o0, [%i2]
st %o1, [%i2+4]
ret
restore
E SPARC_RET_INT128
unimp
E SPARC_RET_F_8
unimp
E SPARC_RET_F_6
unimp
E SPARC_RET_F_4
unimp
E SPARC_RET_F_2
std %f0, [%i2]
std %o0, [%i2]
std %o2, [%i2+8]
ret
restore
E SPARC_RET_F_3
unimp
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
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
st %f0, [%i2]
ret
@@ -172,16 +190,22 @@ E SPARC_RET_F_1
ret
restore
.align 8
9: sth %o0, [%i2]
ret
restore
.align 8
10: stb %o0, [%i2]
ret
restore
cfi_endproc
.size C(ffi_call_v8),. - C(ffi_call_v8)
#undef STACKFRAME
#define STACKFRAME 104 /* 16*4 register window +
1*4 struct return +
6*4 args backing store +
2*4 return storage +
1*4 alignment */
/* 16*4 register window + 1*4 struct return + 6*4 args backing store
+ 8*4 return storage + 1*4 alignment. */
#define STACKFRAME (16*4 + 4 + 6*4 + 8*4 + 4)
/* ffi_closure_v8(...)
@@ -211,7 +235,7 @@ C(ffi_closure_v8):
! Call ffi_closure_sparc_inner to do the bulk of the work.
mov %g2, %o0
add %fp, -8, %o1
add %fp, -8*4, %o1
call ffi_closure_sparc_inner_v8
add %fp, 64, %o2
@@ -220,8 +244,8 @@ C(ffi_closure_v8):
1: sll %o0, 4, %o0 ! o0 = o0 * 16
add %o7, %o0, %o7 ! o7 = 0b + o0*16
jmp %o7+(2f-0b)
nop
add %fp, -8*4, %i2
! Note that each entry is 4 insns, enforced by the E macro.
.align 16
2:
@@ -232,47 +256,63 @@ E SPARC_RET_STRUCT
jmp %i7+12
restore
E SPARC_RET_UINT8
ldub [%fp-8+3], %i0
ldub [%i2+3], %i0
ret
restore
E SPARC_RET_SINT8
ldsb [%fp-8+3], %i0
ldsb [%i2+3], %i0
ret
restore
E SPARC_RET_UINT16
lduh [%fp-8+2], %i0
lduh [%i2+2], %i0
ret
restore
E SPARC_RET_SINT16
ldsh [%fp-8+2], %i0
ldsh [%i2+2], %i0
ret
restore
E SPARC_RET_UINT32
ld [%fp-8], %i0
ld [%i2], %i0
ret
restore
E SP_V8_RET_CPLX16
ld [%i2], %i0
ret
restore
E SPARC_RET_SINT32
unimp
E SPARC_RET_INT64
ldd [%fp-8], %i0
ldd [%i2], %i0
ret
restore
E SPARC_RET_INT128
unimp
E SPARC_RET_F_8
unimp
E SPARC_RET_F_6
unimp
E SPARC_RET_F_4
unimp
E SPARC_RET_F_2
ldd [%fp-8], %f0
ldd [%i2], %i0
ldd [%i2+8], %i2
ret
restore
E SPARC_RET_F_8
ld [%i2+7*4], %f7
nop
ld [%i2+6*4], %f6
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
restore
E SPARC_RET_F_3
unimp
E SPARC_RET_F_1
ld [%fp-8], %f0
ld [%i2], %f0
ret
restore

View File

@@ -137,7 +137,7 @@ E SPARC_RET_UINT32
srl %o0, 0, %i0
return %i7+8
stx %o0, [%o2]
E SPARC_RET_SINT32
E SP_V9_RET_SINT32
sra %o0, 0, %i0
return %i7+8
stx %o0, [%o2]
@@ -167,7 +167,7 @@ E SPARC_RET_F_4
E SPARC_RET_F_2
return %i7+8
std %f0, [%o2]
E SPARC_RET_F_3
E SP_V9_RET_F_3
st %f2, [%i2+2*4]
nop
st %f1, [%i2+1*4]
@@ -294,7 +294,7 @@ E SPARC_RET_UINT32
lduw [FP-160+4], %i0
return %i7+8
nop
E SPARC_RET_SINT32
E SP_V9_RET_SINT32
ldsw [FP-160+4], %i0
return %i7+8
nop
@@ -326,7 +326,7 @@ E SPARC_RET_F_2
ldd [FP-160], %f0
return %i7+8
nop
E SPARC_RET_F_3
E SP_V9_RET_F_3
ld [FP-160+2*4], %f2
nop
ld [FP-160+1*4], %f1

View File

@@ -31,6 +31,7 @@ if { [istarget aarch64*]
|| [istarget arm*]
|| [istarget i?86*]
|| [istarget s390*]
|| [istarget sparc*]
|| [istarget x86_64*] } {
run-many-tests $ctlist ""
} else {

View File

@@ -12,9 +12,9 @@
_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;
return c;
}