From: Richard Henderson Date: Sun, 26 Oct 2014 20:16:03 +0000 (-0700) Subject: sparc: Add support for complex types X-Git-Tag: upstream/3.3~371^2~1^2~3 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=ad89c2d9e93d5a713ae4113567b4ca6c4fbbf17c;p=platform%2Fupstream%2Flibffi.git sparc: Add support for complex types --- diff --git a/src/sparc/ffi.c b/src/sparc/ffi.c index 1b8f48e..d319c03 100644 --- a/src/sparc/ffi.c +++ b/src/sparc/ffi.c @@ -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(); } diff --git a/src/sparc/ffi64.c b/src/sparc/ffi64.c index ab3ed09..1e2d3f4 100644 --- a/src/sparc/ffi64.c +++ b/src/sparc/ffi64.c @@ -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) diff --git a/src/sparc/ffitarget.h b/src/sparc/ffitarget.h index ff4dc0b..f70c937 100644 --- a/src/sparc/ffitarget.h +++ b/src/sparc/ffitarget.h @@ -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 ----------------------------------------- */ diff --git a/src/sparc/internal.h b/src/sparc/internal.h index b4494d9..f9387d4 100644 --- a/src/sparc/internal.h +++ b/src/sparc/internal.h @@ -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 diff --git a/src/sparc/v8.S b/src/sparc/v8.S index 4adcf6d..e76d813 100644 --- a/src/sparc/v8.S +++ b/src/sparc/v8.S @@ -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 #include #include @@ -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 + std %o0, [%i2] + std %o2, [%i2+8] + ret + restore E SPARC_RET_F_8 - unimp + st %f7, [%i2+7*4] + nop + st %f6, [%i2+6*4] + nop E SPARC_RET_F_6 - unimp + st %f5, [%i2+5*4] + nop + st %f4, [%i2+4*4] + nop E SPARC_RET_F_4 - unimp + st %f3, [%i2+3*4] + nop + st %f2, [%i2+2*4] + nop E SPARC_RET_F_2 - std %f0, [%i2] + st %f1, [%i2+4] + st %f0, [%i2] ret restore -E SPARC_RET_F_3 - unimp +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 + ldd [%i2], %i0 + ldd [%i2+8], %i2 + ret + restore E SPARC_RET_F_8 - unimp + ld [%i2+7*4], %f7 + nop + ld [%i2+6*4], %f6 + nop E SPARC_RET_F_6 - unimp + ld [%i2+5*4], %f5 + nop + ld [%i2+4*4], %f4 + nop E SPARC_RET_F_4 - unimp + ld [%i2+3*4], %f3 + nop + ld [%i2+2*4], %f2 + nop E SPARC_RET_F_2 - ldd [%fp-8], %f0 + 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 diff --git a/src/sparc/v9.S b/src/sparc/v9.S index d893d2f..5c3f27b 100644 --- a/src/sparc/v9.S +++ b/src/sparc/v9.S @@ -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 diff --git a/testsuite/libffi.call/call.exp b/testsuite/libffi.call/call.exp index 7a5c44f..982c03e 100644 --- a/testsuite/libffi.call/call.exp +++ b/testsuite/libffi.call/call.exp @@ -31,6 +31,7 @@ if { [istarget aarch64*] || [istarget arm*] || [istarget i?86*] || [istarget s390*] + || [istarget sparc*] || [istarget x86_64*] } { run-many-tests $ctlist "" } else { diff --git a/testsuite/libffi.call/complex_int.c b/testsuite/libffi.call/complex_int.c index 4c8e864..bac3190 100644 --- a/testsuite/libffi.call/complex_int.c +++ b/testsuite/libffi.call/complex_int.c @@ -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; }