From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 11672 invoked by alias); 30 Oct 2014 03:54:53 -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 11584 invoked by uid 89); 30 Oct 2014 03:54:52 -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-pd0-f172.google.com Received: from mail-pd0-f172.google.com (HELO mail-pd0-f172.google.com) (209.85.192.172) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with (AES128-SHA encrypted) ESMTPS; Thu, 30 Oct 2014 03:54:50 +0000 Received: by mail-pd0-f172.google.com with SMTP id r10so4303062pdi.31 for ; Wed, 29 Oct 2014 20:54:48 -0700 (PDT) X-Received: by 10.70.95.162 with SMTP id dl2mr14544030pdb.71.1414641288269; Wed, 29 Oct 2014 20:54:48 -0700 (PDT) Received: from pike.twiddle.home (50-194-63-110-static.hfc.comcastbusiness.net. [50.194.63.110]) by mx.google.com with ESMTPSA id qh7sm5676184pab.48.2014.10.29.20.54.46 for (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Wed, 29 Oct 2014 20:54:47 -0700 (PDT) From: Richard Henderson To: libffi-discuss@sourceware.org Subject: [PATCH 2/4] alpha: Clean up conversion of float values Date: Thu, 30 Oct 2014 03:54:00 -0000 Message-Id: <1414641281-15172-3-git-send-email-rth@twiddle.net> In-Reply-To: <1414641281-15172-1-git-send-email-rth@twiddle.net> References: <1414641281-15172-1-git-send-email-rth@twiddle.net> X-SW-Source: 2014/txt/msg00176.txt.bz2 Don't use "real" conversion to double, lest we raise exceptions when passing signalling nans. --- src/alpha/ffi.c | 95 +++++++++++++++++++++++++++++++-------------------------- 1 file changed, 51 insertions(+), 44 deletions(-) diff --git a/src/alpha/ffi.c b/src/alpha/ffi.c index 519bd2c..2f9e7e5 100644 --- a/src/alpha/ffi.c +++ b/src/alpha/ffi.c @@ -45,6 +45,20 @@ extern void ffi_call_osf(void *, unsigned long, unsigned, void *, void (*)(void) FFI_HIDDEN; extern void ffi_closure_osf(void) FFI_HIDDEN; +/* Promote a float value to its in-register double representation. + Unlike actually casting to double, this does not trap on NaN. */ +static inline UINT64 lds(void *ptr) +{ + UINT64 ret; + asm("lds %0,%1" : "=f"(ret) : "m"(*(UINT32 *)ptr)); + return ret; +} + +/* And the reverse. */ +static inline void sts(void *ptr, UINT64 val) +{ + asm("sts %1,%0" : "=m"(*(UINT32 *)ptr) : "f"(val)); +} ffi_status ffi_prep_cif_machdep(ffi_cif *cif) @@ -127,71 +141,67 @@ ffi_call(ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue) avn = cif->nargs; arg_types = cif->arg_types; - while (i < avn) + for (i = 0, avn = cif->nargs; i < avn; i++) { - size_t size = (*arg_types)->size; + ffi_type *ty = arg_types[i]; + void *valp = avalue[i]; + unsigned long val; + size_t size; - switch ((*arg_types)->type) + switch (ty->type) { case FFI_TYPE_SINT8: - *(SINT64 *) argp = *(SINT8 *)(* avalue); + val = *(SINT8 *)valp; break; case FFI_TYPE_UINT8: - *(SINT64 *) argp = *(UINT8 *)(* avalue); + val = *(UINT8 *)valp; break; case FFI_TYPE_SINT16: - *(SINT64 *) argp = *(SINT16 *)(* avalue); + val = *(SINT16 *)valp; break; case FFI_TYPE_UINT16: - *(SINT64 *) argp = *(UINT16 *)(* avalue); + val = *(UINT16 *)valp; break; case FFI_TYPE_SINT32: case FFI_TYPE_UINT32: /* Note that unsigned 32-bit quantities are sign extended. */ - *(SINT64 *) argp = *(SINT32 *)(* avalue); + val = *(SINT32 *)valp; break; - + case FFI_TYPE_SINT64: case FFI_TYPE_UINT64: case FFI_TYPE_POINTER: - *(UINT64 *) argp = *(UINT64 *)(* avalue); + case FFI_TYPE_DOUBLE: + val = *(UINT64 *)valp; + break; + + case FFI_TYPE_LONGDOUBLE: + /* Note that 128-bit long double is passed by reference. */ + val = (unsigned long)valp; break; case FFI_TYPE_FLOAT: if (argp - stack < 6) - { - /* Note the conversion -- all the fp regs are loaded as - doubles. The in-register format is the same. */ - *(double *) argp = *(float *)(* avalue); - } + val = lds(valp); else - *(float *) argp = *(float *)(* avalue); - break; - - case FFI_TYPE_DOUBLE: - *(double *) argp = *(double *)(* avalue); - break; - - case FFI_TYPE_LONGDOUBLE: - /* 128-bit long double is passed by reference. */ - *(long double **) argp = (long double *)(* avalue); - size = sizeof (long double *); + val = *(UINT32 *)valp; break; case FFI_TYPE_STRUCT: - memcpy(argp, *avalue, (*arg_types)->size); - break; + size = ty->size; + memcpy(argp, valp, size); + argp += ALIGN(size, FFI_SIZEOF_ARG) / FFI_SIZEOF_ARG; + continue; default: - FFI_ASSERT(0); + abort(); } - argp += ALIGN(size, FFI_SIZEOF_ARG) / FFI_SIZEOF_ARG; - i++, arg_types++, avalue++; + *argp++ = val; } flags = (flags >> ALPHA_ST_SHIFT) & 0xff; @@ -255,14 +265,13 @@ ffi_closure_osf_inner(ffi_closure *closure, void *rvalue, unsigned long *argp) argn = 1; } - i = 0; - avn = cif->nargs; arg_types = cif->arg_types; /* Grab the addresses of the arguments from the stack frame. */ - while (i < avn) + for (i = 0, avn = cif->nargs; i < avn; i++) { size_t size = arg_types[i]->size; + void *valp = &argp[argn]; switch (arg_types[i]->type) { @@ -276,28 +285,26 @@ ffi_closure_osf_inner(ffi_closure *closure, void *rvalue, unsigned long *argp) case FFI_TYPE_UINT64: case FFI_TYPE_POINTER: case FFI_TYPE_STRUCT: - avalue[i] = &argp[argn]; break; case FFI_TYPE_FLOAT: + /* Floats coming from registers need conversion from double + back to float format. */ if (argn < 6) { - /* Floats coming from registers need conversion from double - back to float format. */ - *(float *)&argp[argn - 6] = *(double *)&argp[argn - 6]; - avalue[i] = &argp[argn - 6]; + valp = &argp[argn - 6]; + sts(valp, argp[argn - 6]); } - else - avalue[i] = &argp[argn]; break; case FFI_TYPE_DOUBLE: - avalue[i] = &argp[argn - (argn < 6 ? 6 : 0)]; + if (argn < 6) + valp = &argp[argn - 6]; break; case FFI_TYPE_LONGDOUBLE: /* 128-bit long double is passed by reference. */ - avalue[i] = (long double *) argp[argn]; + valp = (long double *) argp[argn]; size = sizeof (long double *); break; @@ -305,8 +312,8 @@ ffi_closure_osf_inner(ffi_closure *closure, void *rvalue, unsigned long *argp) abort (); } + avalue[i] = valp; argn += ALIGN(size, FFI_SIZEOF_ARG) / FFI_SIZEOF_ARG; - i++; } /* Invoke the closure. */ -- 1.9.3