From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 9464 invoked by alias); 28 Oct 2014 19:46:45 -0000 Mailing-List: contact libffi-discuss-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: libffi-discuss-owner@sourceware.org Received: (qmail 9369 invoked by uid 89); 28 Oct 2014 19:46:43 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-2.3 required=5.0 tests=AWL,BAYES_00,FREEMAIL_ENVFROM_END_DIGIT,FREEMAIL_FROM,RCVD_IN_DNSWL_LOW,SPF_PASS autolearn=ham version=3.3.2 X-HELO: mail-qg0-f49.google.com Received: from mail-qg0-f49.google.com (HELO mail-qg0-f49.google.com) (209.85.192.49) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with (AES128-SHA encrypted) ESMTPS; Tue, 28 Oct 2014 19:46:39 +0000 Received: by mail-qg0-f49.google.com with SMTP id e89so1110516qgf.8 for ; Tue, 28 Oct 2014 12:46:37 -0700 (PDT) X-Received: by 10.140.109.244 with SMTP id l107mr7853736qgf.80.1414525597234; Tue, 28 Oct 2014 12:46:37 -0700 (PDT) Received: from anchor.com (50-194-63-110-static.hfc.comcastbusiness.net. [50.194.63.110]) by mx.google.com with ESMTPSA id 11sm2042715qgj.34.2014.10.28.12.46.35 for (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Tue, 28 Oct 2014 12:46:36 -0700 (PDT) From: Richard Henderson To: libffi-discuss@sourceware.org Cc: davem@davemloft.net Subject: [PATCH 6/8] sparc: Add support for complex types Date: Tue, 28 Oct 2014 19:46:00 -0000 Message-Id: <1414525555-21256-7-git-send-email-rth@twiddle.net> In-Reply-To: <1414525555-21256-1-git-send-email-rth@twiddle.net> References: <1414525555-21256-1-git-send-email-rth@twiddle.net> X-SW-Source: 2014/txt/msg00153.txt.bz2 --- src/sparc/ffi.c | 92 +++++++++++++++++++++++++-- src/sparc/ffi64.c | 48 ++++++++++++--- src/sparc/ffitarget.h | 1 + src/sparc/internal.h | 10 +-- src/sparc/v8.S | 120 ++++++++++++++++++++++++------------ src/sparc/v9.S | 8 +-- testsuite/libffi.call/call.exp | 12 ++-- testsuite/libffi.call/complex_int.c | 4 +- 8 files changed, 223 insertions(+), 72 deletions(-) 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 5177f07..f144a65 100644 --- a/testsuite/libffi.call/call.exp +++ b/testsuite/libffi.call/call.exp @@ -24,16 +24,14 @@ set ctlist [lsearch -inline -all -glob [lsort [glob -nocomplain -- $srcdir/$subd run-many-tests $tlist "" -if { ![istarget s390*] } { - +# ??? We really should preprocess ffi.h and grep +# for FFI_TARGET_HAS_COMPLEX_TYPE. +if { [istarget s390*] || [istarget sparc*] } { + run-many-tests $ctlist "" +} else { foreach test $ctlist { unsupported "$test" } - -} else { - - run-many-tests $ctlist "" - } dg-finish 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; } -- 1.9.3