From patchwork Sun Feb 4 04:11:13 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Richard Henderson X-Patchwork-Id: 126794 Delivered-To: patch@linaro.org Received: by 10.46.124.24 with SMTP id x24csp923322ljc; Sat, 3 Feb 2018 20:12:15 -0800 (PST) X-Google-Smtp-Source: AH8x225vYhFXKsrCJyOoKADLcFdJNi7krWfGzytPlpZqfsCFoxyNPHs7t9QpoUMcPF44+KB8X3C6 X-Received: by 10.37.113.8 with SMTP id m8mr29729374ybc.56.1517717535382; Sat, 03 Feb 2018 20:12:15 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1517717535; cv=none; d=google.com; s=arc-20160816; b=DEZsU3uuS4RGlu4wtdHZAvfJ+DpZwn4rKOcBrPMlrRztdRCTkUUQSaebTRS77AYBl8 FVZtHhHldRJ8Ug44Xo2iAV6WteklE4DDhUadSsRY7kXFQGrKeWb+bQDmznhtlm5qYyiu 6/wxX2MEOlEwndAtFYu3uFvY/7UhEMkJGuTDNEwP26sqK6rLD4f08pl0Bc8doWp0rc0t z54+yQxxuop3BlesPURivxsW46Laeo7guefJdu9f8w4uegc15AwY+OAv/hSnQRyjLQzS I2T3GfwVNkpluU8TVNyH047WOCVAJQ1Ex4NWxEeIf551RMkf2kv2MB+5DKTUVgVoRsgD wGSw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=sender:errors-to:cc:list-subscribe:list-help:list-post:list-archive :list-unsubscribe:list-id:precedence:subject :content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:to:from:dkim-signature:arc-authentication-results; bh=mChd7TEwq3ZdrA6gGr+Hje5KtLZ1BEWCJIdlh6JiFBM=; b=pUAK3x8kIgbdjxr4vLViak0DPEcuxkDtIJYrDH4AT/efv+sEAD6TQQRxiHl+8sFaKQ UL/1yY8StneUYz8bNZSqmrTM0kmY4NyT/3UPGJl2v/SkAEpR1Vds3QBsg3exG4Dn+A7F 7RSBdGJ0Hw9NdULWNQepRlPC8EK6ka8MdL5txwF8CSeB6mZCf7IFKivjMfd8xhBL6/FD 0mRyb6Y9GZeekyhdoWSyUY5qpSoMeNZSRsMcytzBlUayw4djDlVRt1UKvoau3c7Ryh6k vpxGMlYdd9hmAWIBeMKqxsJMq5K8/KNtEW1Oxc/K4vrpifclTMHD5sRkObnlIvncfN79 oDgw== ARC-Authentication-Results: i=1; mx.google.com; dkim=fail header.i=@linaro.org header.s=google header.b=gb9Mo6Em; spf=pass (google.com: domain of qemu-devel-bounces+patch=linaro.org@nongnu.org designates 2001:4830:134:3::11 as permitted sender) smtp.mailfrom=qemu-devel-bounces+patch=linaro.org@nongnu.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=linaro.org Return-Path: Received: from lists.gnu.org (lists.gnu.org. [2001:4830:134:3::11]) by mx.google.com with ESMTPS id d36si491109ybe.750.2018.02.03.20.12.15 for (version=TLS1 cipher=AES128-SHA bits=128/128); Sat, 03 Feb 2018 20:12:15 -0800 (PST) Received-SPF: pass (google.com: domain of qemu-devel-bounces+patch=linaro.org@nongnu.org designates 2001:4830:134:3::11 as permitted sender) client-ip=2001:4830:134:3::11; Authentication-Results: mx.google.com; dkim=fail header.i=@linaro.org header.s=google header.b=gb9Mo6Em; spf=pass (google.com: domain of qemu-devel-bounces+patch=linaro.org@nongnu.org designates 2001:4830:134:3::11 as permitted sender) smtp.mailfrom=qemu-devel-bounces+patch=linaro.org@nongnu.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=linaro.org Received: from localhost ([::1]:58236 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1eiBf4-0004Vb-NV for patch@linaro.org; Sat, 03 Feb 2018 23:12:14 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:47233) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1eiBed-0004UD-1o for qemu-devel@nongnu.org; Sat, 03 Feb 2018 23:11:48 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1eiBeY-0004od-Vg for qemu-devel@nongnu.org; Sat, 03 Feb 2018 23:11:47 -0500 Received: from mail-pf0-x244.google.com ([2607:f8b0:400e:c00::244]:42782) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1eiBeY-0004oV-Pt for qemu-devel@nongnu.org; Sat, 03 Feb 2018 23:11:42 -0500 Received: by mail-pf0-x244.google.com with SMTP id b25so19452745pfd.9 for ; Sat, 03 Feb 2018 20:11:42 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=mChd7TEwq3ZdrA6gGr+Hje5KtLZ1BEWCJIdlh6JiFBM=; b=gb9Mo6EmmYrXEihtLOxQVULIiwo60nI7Hxrs5XGmYO3DDkrill0R1hFcBV0a1qi11s tBwciWvwKNwQJINp2g5igiHS0mSiFsKDCEd9Z0XBs5VWLFQLEVI5CGnUYlnJsb0xFNXS 4Q9202RKD4XVgPzOTziK+FLk9IWyG8YQSAzCI= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=mChd7TEwq3ZdrA6gGr+Hje5KtLZ1BEWCJIdlh6JiFBM=; b=FX+IPX+cKPN1F5fMCUSmKFxie4w4dudzkXJJca4G5L0rUdxSJf/tsQPF7D+pLMzR1y UcTafgztmGGMbufGiex5R15uUfVX4j+eZ/mEdCZ5r542s1HpboaWhKpauLFtrD8wgEfz DVQNvxRlyYC1o6sKrnZiGDVvY36FZFJX7S4IM4humu39NWy8EX589d6YvTYG8K3fGCw0 BADTl1lp4XoXQpvm4+7Ox8uJ8Jpz/Tz52sUcKbnptJphtzNFkS9kBpZjGPUJuaCuthU8 mrQlg8f0FQu7BzSzzQc9BBs2DGpWj//GB5aldKqwM10bgVBWNKV88J4hnkJwrkYdTN30 0jxQ== X-Gm-Message-State: AKwxytcf3ly5ragMELBvI8DyJc9AahNVnmEojyaPjcR6H434lhehNHup 33FmhxhfRyjLsceU6qJKLX2NjaRTC88= X-Received: by 10.98.31.131 with SMTP id l3mr45360146pfj.116.1517717501378; Sat, 03 Feb 2018 20:11:41 -0800 (PST) Received: from cloudburst.twiddle.net (174-21-6-47.tukw.qwest.net. [174.21.6.47]) by smtp.gmail.com with ESMTPSA id k3sm1399425pgr.12.2018.02.03.20.11.40 (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Sat, 03 Feb 2018 20:11:40 -0800 (PST) From: Richard Henderson To: qemu-devel@nongnu.org Date: Sat, 3 Feb 2018 20:11:13 -0800 Message-Id: <20180204041136.17525-2-richard.henderson@linaro.org> X-Mailer: git-send-email 2.14.3 In-Reply-To: <20180204041136.17525-1-richard.henderson@linaro.org> References: <20180204041136.17525-1-richard.henderson@linaro.org> MIME-Version: 1.0 X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 2607:f8b0:400e:c00::244 Subject: [Qemu-devel] [PATCH 01/24] fpu/softfloat: implement float16_squash_input_denormal X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: peter.maydell@linaro.org, cota@braap.org, alex.bennee@linaro.org, hsp.cat7@gmail.com Errors-To: qemu-devel-bounces+patch=linaro.org@nongnu.org Sender: "Qemu-devel" From: Alex Bennée This will be required when expanding the MINMAX() macro for 16 bit/half-precision operations. Signed-off-by: Alex Bennée Reviewed-by: Richard Henderson Reviewed-by: Peter Maydell --- include/fpu/softfloat.h | 1 + fpu/softfloat.c | 15 +++++++++++++++ 2 files changed, 16 insertions(+) -- 2.14.3 diff --git a/include/fpu/softfloat.h b/include/fpu/softfloat.h index 0f96a0edd1..d5e99667b6 100644 --- a/include/fpu/softfloat.h +++ b/include/fpu/softfloat.h @@ -277,6 +277,7 @@ void float_raise(uint8_t flags, float_status *status); | If `a' is denormal and we are in flush-to-zero mode then set the | input-denormal exception and return zero. Otherwise just return the value. *----------------------------------------------------------------------------*/ +float16 float16_squash_input_denormal(float16 a, float_status *status); float32 float32_squash_input_denormal(float32 a, float_status *status); float64 float64_squash_input_denormal(float64 a, float_status *status); diff --git a/fpu/softfloat.c b/fpu/softfloat.c index 433c5dad2d..3a4ab1355f 100644 --- a/fpu/softfloat.c +++ b/fpu/softfloat.c @@ -3488,6 +3488,21 @@ static float16 roundAndPackFloat16(flag zSign, int zExp, return packFloat16(zSign, zExp, zSig >> 13); } +/*---------------------------------------------------------------------------- +| If `a' is denormal and we are in flush-to-zero mode then set the +| input-denormal exception and return zero. Otherwise just return the value. +*----------------------------------------------------------------------------*/ +float16 float16_squash_input_denormal(float16 a, float_status *status) +{ + if (status->flush_inputs_to_zero) { + if (extractFloat16Exp(a) == 0 && extractFloat16Frac(a) != 0) { + float_raise(float_flag_input_denormal, status); + return make_float16(float16_val(a) & 0x8000); + } + } + return a; +} + static void normalizeFloat16Subnormal(uint32_t aSig, int *zExpPtr, uint32_t *zSigPtr) { From patchwork Sun Feb 4 04:11:14 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Richard Henderson X-Patchwork-Id: 126795 Delivered-To: patch@linaro.org Received: by 10.46.124.24 with SMTP id x24csp924184ljc; Sat, 3 Feb 2018 20:14:32 -0800 (PST) X-Google-Smtp-Source: AH8x225rDLU2ujRQuoNtmZD2Zrd6bKhxNdb8ZAE1yyG23vX/TYKDR4FyeyifKowt+4KXCDMkDnEI X-Received: by 10.129.183.8 with SMTP id v8mr30356419ywh.68.1517717672399; Sat, 03 Feb 2018 20:14:32 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1517717672; cv=none; d=google.com; s=arc-20160816; b=bZ06sYhz3UNAuS+PEJhNfbI2T/sGiZa0yPqYqJ8gmmc+VRKveVnB23k/mnp3W3VhP2 LQFBOiPJFYgfOuCYrYetsX9G77sG4UI3XTFgfoiypKy0oEC4COsaY+3GT0kDL9vr2wSM vbXmUJZo7n72WhoM1shHfth1sWxB6q7gswWkMIZsVCCFlOVWINaFspg4sH/G0Rc7yhQY dK2C74/cOhPFpx/PKWWPe1Db4OwLV8WkhT5Z5Jrh7py96ty8T9zk6DVm9P5BF+hojNu3 K7iJ6+Qw26hcBdJJCyuDBEZsFHfnBJ0s6Myl2RmxHh+U0Mfh8e9t5BZceiyItmB2OmIU 02Gw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=sender:errors-to:cc:list-subscribe:list-help:list-post:list-archive :list-unsubscribe:list-id:precedence:subject :content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:to:from:dkim-signature:arc-authentication-results; bh=M/X47EYVfE46yjRXI8il0rh0nfUtsk7EalgOH1v3J/k=; b=AI5j3ATHrjg49tM6oLm7dIPqXxbuIA3L12N4t8fzVkrHXIqVAZqvapenakNF/nPKOG 5ZlXgsR2mpDuAnm4xC0k6A0QJLroJUSl/DaDh+JI1YZ0iGNVFwV5coIRro6s71aUKeJ/ 87ooJ67o2U1r8XDWmkgzzlAIw3OxAQIsEkHOp0FEMyH+gR03BSx6FXLQc2qlDYkwgY+s FqsAoJVFKVbi78inG3mrdLoSO3zcx0TRdFZ7+NpW8NGHTbJ0huXL9EchIQAXkSBMH4zW ZlkHRc5QQF8KgYS2gRFrOUqqHqmE37ECtWYicOK3tlyOBDpClrwlUHHlLUr0oZnuMaPc 0onA== ARC-Authentication-Results: i=1; mx.google.com; dkim=fail header.i=@linaro.org header.s=google header.b=Wjsn+f3J; spf=pass (google.com: domain of qemu-devel-bounces+patch=linaro.org@nongnu.org designates 2001:4830:134:3::11 as permitted sender) smtp.mailfrom=qemu-devel-bounces+patch=linaro.org@nongnu.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=linaro.org Return-Path: Received: from lists.gnu.org (lists.gnu.org. [2001:4830:134:3::11]) by mx.google.com with ESMTPS id 84si1007306ywd.494.2018.02.03.20.14.32 for (version=TLS1 cipher=AES128-SHA bits=128/128); Sat, 03 Feb 2018 20:14:32 -0800 (PST) Received-SPF: pass (google.com: domain of qemu-devel-bounces+patch=linaro.org@nongnu.org designates 2001:4830:134:3::11 as permitted sender) client-ip=2001:4830:134:3::11; Authentication-Results: mx.google.com; dkim=fail header.i=@linaro.org header.s=google header.b=Wjsn+f3J; spf=pass (google.com: domain of qemu-devel-bounces+patch=linaro.org@nongnu.org designates 2001:4830:134:3::11 as permitted sender) smtp.mailfrom=qemu-devel-bounces+patch=linaro.org@nongnu.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=linaro.org Received: from localhost ([::1]:58239 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1eiBhH-0005qa-Lk for patch@linaro.org; Sat, 03 Feb 2018 23:14:31 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:47235) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1eiBed-0004UE-20 for qemu-devel@nongnu.org; Sat, 03 Feb 2018 23:11:48 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1eiBea-0004p0-H0 for qemu-devel@nongnu.org; Sat, 03 Feb 2018 23:11:47 -0500 Received: from mail-pg0-x241.google.com ([2607:f8b0:400e:c05::241]:36832) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1eiBea-0004or-BB for qemu-devel@nongnu.org; Sat, 03 Feb 2018 23:11:44 -0500 Received: by mail-pg0-x241.google.com with SMTP id x25so3376250pge.3 for ; Sat, 03 Feb 2018 20:11:44 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=M/X47EYVfE46yjRXI8il0rh0nfUtsk7EalgOH1v3J/k=; b=Wjsn+f3J1ygxiKBZWUW1IE4BCrO4xLYCZiwsxdlBIqSz0WruAmysKE5mHR7ndGdUKq SI5HA7yd/Mh/LLnth6LRgQnKBEJXOAeL93GrfHOtM/M8+9MoO195jscNRi1CTQGz76zP AiTMpwrJPEdP1B/a3l82bQQL0n6iGtDFdlEBY= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=M/X47EYVfE46yjRXI8il0rh0nfUtsk7EalgOH1v3J/k=; b=rwsofkLfWxC0M3yDoVKv1WUixdD30Bz5fKHMiq4lZMNnerPx2KC7Gr59RM9di10PFp GEbeMXqEm878tHmfzIJb95J4ozLMjMY5oSmYxryhii11tfrGPMF6qNtI58Th+JQ4H1Y4 xIXV2yc5jRi+iEVmuVYyuMn55RwoOUhypCM9Rrxo18nnfuYV+KJ4SJuKlF7s2O+5cCof K9cBee62+r60ri/GXHp1osK47Xo57g6z3blqJliDqIgDfPkaG65K3wTZ9Awm+UfDsTdh cM1FzfHFuiN8/MXSBh9EZCxrLxJSME1zY5fu8NyceDsSQO3W19HnHr7oDKlOueo2nKbl WR+A== X-Gm-Message-State: AKwxyteed3JqBYHpWIW9v2ZkxbXFZeIi9xSaH4L6S8ttlcKAGiR/x6q7 XDxdgwCEKig6fxj9BVVaRLgUAkJ6ajc= X-Received: by 10.98.66.67 with SMTP id p64mr44688933pfa.227.1517717503103; Sat, 03 Feb 2018 20:11:43 -0800 (PST) Received: from cloudburst.twiddle.net (174-21-6-47.tukw.qwest.net. [174.21.6.47]) by smtp.gmail.com with ESMTPSA id k3sm1399425pgr.12.2018.02.03.20.11.41 (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Sat, 03 Feb 2018 20:11:42 -0800 (PST) From: Richard Henderson To: qemu-devel@nongnu.org Date: Sat, 3 Feb 2018 20:11:14 -0800 Message-Id: <20180204041136.17525-3-richard.henderson@linaro.org> X-Mailer: git-send-email 2.14.3 In-Reply-To: <20180204041136.17525-1-richard.henderson@linaro.org> References: <20180204041136.17525-1-richard.henderson@linaro.org> MIME-Version: 1.0 X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 2607:f8b0:400e:c05::241 Subject: [Qemu-devel] [PATCH 02/24] include/fpu/softfloat: remove USE_SOFTFLOAT_STRUCT_TYPES X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: peter.maydell@linaro.org, cota@braap.org, alex.bennee@linaro.org, hsp.cat7@gmail.com Errors-To: qemu-devel-bounces+patch=linaro.org@nongnu.org Sender: "Qemu-devel" From: Alex Bennée It's not actively built and when enabled things fail to compile. I'm not sure the type-checking is really helping here. Seeing as we "own" our softfloat now lets remove the cruft. Signed-off-by: Alex Bennée Reviewed-by: Richard Henderson --- include/fpu/softfloat.h | 27 --------------------------- 1 file changed, 27 deletions(-) -- 2.14.3 diff --git a/include/fpu/softfloat.h b/include/fpu/softfloat.h index d5e99667b6..52af1412de 100644 --- a/include/fpu/softfloat.h +++ b/include/fpu/softfloat.h @@ -103,32 +103,6 @@ enum { /*---------------------------------------------------------------------------- | Software IEC/IEEE floating-point types. *----------------------------------------------------------------------------*/ -/* Use structures for soft-float types. This prevents accidentally mixing - them with native int/float types. A sufficiently clever compiler and - sane ABI should be able to see though these structs. However - x86/gcc 3.x seems to struggle a bit, so leave them disabled by default. */ -//#define USE_SOFTFLOAT_STRUCT_TYPES -#ifdef USE_SOFTFLOAT_STRUCT_TYPES -typedef struct { - uint16_t v; -} float16; -#define float16_val(x) (((float16)(x)).v) -#define make_float16(x) __extension__ ({ float16 f16_val = {x}; f16_val; }) -#define const_float16(x) { x } -typedef struct { - uint32_t v; -} float32; -/* The cast ensures an error if the wrong type is passed. */ -#define float32_val(x) (((float32)(x)).v) -#define make_float32(x) __extension__ ({ float32 f32_val = {x}; f32_val; }) -#define const_float32(x) { x } -typedef struct { - uint64_t v; -} float64; -#define float64_val(x) (((float64)(x)).v) -#define make_float64(x) __extension__ ({ float64 f64_val = {x}; f64_val; }) -#define const_float64(x) { x } -#else typedef uint16_t float16; typedef uint32_t float32; typedef uint64_t float64; @@ -141,7 +115,6 @@ typedef uint64_t float64; #define const_float16(x) (x) #define const_float32(x) (x) #define const_float64(x) (x) -#endif typedef struct { uint64_t low; uint16_t high; From patchwork Sun Feb 4 04:11:15 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Richard Henderson X-Patchwork-Id: 126800 Delivered-To: patch@linaro.org Received: by 10.46.124.24 with SMTP id x24csp925422ljc; Sat, 3 Feb 2018 20:17:34 -0800 (PST) X-Google-Smtp-Source: AH8x225ddbTZ2dqLt9O9Zgrb1xSQsPKpK2X78nN8Yccf4r/YeqwrnM3CbEz+XfU/Qb+daZXruBD1 X-Received: by 10.37.95.70 with SMTP id h6mr28975812ybm.508.1517717853919; Sat, 03 Feb 2018 20:17:33 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1517717853; cv=none; d=google.com; s=arc-20160816; b=upZo39maUz/hd0BgdhLtr0eHbaVqA3PTiqRe0zEMjbRoi6CclmPlpiH2mgKUet/TLV toBnMIkcWQvWcOFdg010ymlhAzgpB7aZPekuhx8N33M3vWt//zt+yAmJHs6mObTJoQNU IJsyAgorXO3HJoMa+EuWepyBLeCs7uRL9BL7n8LlG88EF9K6kkhZa0xKEFL4qNXd4qdR jQhriWJmbTbdcy2dudeQydzf1qiXw3aZYKV8Hn4+H6GjWYAIE4/MTx501BNJxGRTb1G5 RzLin/vsQIDK8h5rPUXN0Hrv67gR3+D/nQhA5H+thrUx3ktJmoiGGJKMAb6A36nVzYaL +SxA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=sender:errors-to:cc:list-subscribe:list-help:list-post:list-archive :list-unsubscribe:list-id:precedence:subject :content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:to:from:dkim-signature:arc-authentication-results; bh=u7F7TwNvKd7ym1gJTvfgy5p0qKnWv6+eBTzXwmeejyA=; b=C5RoWNAr+jxhF3D3GiZXWGNzRVZMfJdSdiaUCdS+YEEK+Sd2AyAQUVSEdXGP/R1yjp +QzoTfLgyEt6RVmtUk5v+97yTTaCzxXtrSNh8U3P9O8dW5Fwl4Iyp4qxjIMIHz3+5ACz tVlhivjTrDgrk4PcwLgstTuX7KUb2tPKnt/KEhEFKdf9NVkePIEok7/yamt9nahDVQZe gBtVCgVHE51HubaSF1uLRcPZ41BbxmZERxDkRkgbXHcRaBim5lwmfm19hBKAmUdF1FjW Q9+1Iy2+Axp8kpqkAk00L8WWL5oMOUwtfaTYOFAF11xr3XQMExI8XH3lb0lo38h8og29 iBsQ== ARC-Authentication-Results: i=1; mx.google.com; dkim=fail header.i=@linaro.org header.s=google header.b=U497lR0S; spf=pass (google.com: domain of qemu-devel-bounces+patch=linaro.org@nongnu.org designates 2001:4830:134:3::11 as permitted sender) smtp.mailfrom=qemu-devel-bounces+patch=linaro.org@nongnu.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=linaro.org Return-Path: Received: from lists.gnu.org (lists.gnu.org. [2001:4830:134:3::11]) by mx.google.com with ESMTPS id w194si1095730ybe.535.2018.02.03.20.17.33 for (version=TLS1 cipher=AES128-SHA bits=128/128); Sat, 03 Feb 2018 20:17:33 -0800 (PST) Received-SPF: pass (google.com: domain of qemu-devel-bounces+patch=linaro.org@nongnu.org designates 2001:4830:134:3::11 as permitted sender) client-ip=2001:4830:134:3::11; Authentication-Results: mx.google.com; dkim=fail header.i=@linaro.org header.s=google header.b=U497lR0S; spf=pass (google.com: domain of qemu-devel-bounces+patch=linaro.org@nongnu.org designates 2001:4830:134:3::11 as permitted sender) smtp.mailfrom=qemu-devel-bounces+patch=linaro.org@nongnu.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=linaro.org Received: from localhost ([::1]:58265 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1eiBkD-0000C5-7p for patch@linaro.org; Sat, 03 Feb 2018 23:17:33 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:47242) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1eiBed-0004UQ-Ld for qemu-devel@nongnu.org; Sat, 03 Feb 2018 23:11:49 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1eiBec-0004pY-1Y for qemu-devel@nongnu.org; Sat, 03 Feb 2018 23:11:47 -0500 Received: from mail-pf0-x241.google.com ([2607:f8b0:400e:c00::241]:33370) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1eiBeb-0004pL-Pa for qemu-devel@nongnu.org; Sat, 03 Feb 2018 23:11:45 -0500 Received: by mail-pf0-x241.google.com with SMTP id u15so3375988pfa.0 for ; Sat, 03 Feb 2018 20:11:45 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=u7F7TwNvKd7ym1gJTvfgy5p0qKnWv6+eBTzXwmeejyA=; b=U497lR0SEr5AuGO/aFBpQIG3d2alq5h/WbzMIMhS/3wxYNqNQyoYw6rsHXTci9TnCb cJNbumVfADIbuPZuQGDrO7y0lD/dJZNX2FZqJo7f6rvh/14cufkSuMzwrY+DK06q9TPj 3agLcN0cAQaIu7ou45QFnUgEIvh8pCg42mn/Q= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=u7F7TwNvKd7ym1gJTvfgy5p0qKnWv6+eBTzXwmeejyA=; b=b38kIOFRoIiCLn/kxb/G9D98Y8bCua6l1rHY9xDHJbMUxnEUEFk0PFBK9/mk9TTcS/ 9+bCk9mgQcsuO8sFhoxq5xdfsTCK5qxMz97Zs7AFqlOieTSXHkDTLZ1PhuYwsQOdNcvj 5WyBWN2koz5BYt9HDHIQnjwmY2W9OG/v7Zj8PxYxYFUIxS4+JTMrjVV0T3Z5Vhn1ro+I C1Jo6GLIu15GCB6pSu9xSmCvfdMLKyY60EtySIVioUkKTsPhR7yuqOYRRkr6GXCNd0ic zyTTrdu/MzVZj3jn2wm7tqH/Krz6sBb8a6z/VR1siygW4GAefnZix6AcZZMXy/kGALoy qbqQ== X-Gm-Message-State: AKwxyteJSOlwzDWaZbg9QJIrTthRCQqsiaUFnTrhPCj7d6JbNqQmDRUm rnQxPvs56gO8tUfrjt8GB/ZQhT8M6PU= X-Received: by 10.98.15.27 with SMTP id x27mr45505364pfi.197.1517717504398; Sat, 03 Feb 2018 20:11:44 -0800 (PST) Received: from cloudburst.twiddle.net (174-21-6-47.tukw.qwest.net. [174.21.6.47]) by smtp.gmail.com with ESMTPSA id k3sm1399425pgr.12.2018.02.03.20.11.43 (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Sat, 03 Feb 2018 20:11:43 -0800 (PST) From: Richard Henderson To: qemu-devel@nongnu.org Date: Sat, 3 Feb 2018 20:11:15 -0800 Message-Id: <20180204041136.17525-4-richard.henderson@linaro.org> X-Mailer: git-send-email 2.14.3 In-Reply-To: <20180204041136.17525-1-richard.henderson@linaro.org> References: <20180204041136.17525-1-richard.henderson@linaro.org> MIME-Version: 1.0 X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 2607:f8b0:400e:c00::241 Subject: [Qemu-devel] [PATCH 03/24] fpu/softfloat-types: new header to prevent excessive re-builds X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: peter.maydell@linaro.org, cota@braap.org, alex.bennee@linaro.org, hsp.cat7@gmail.com Errors-To: qemu-devel-bounces+patch=linaro.org@nongnu.org Sender: "Qemu-devel" From: Alex Bennée The main culprit here is bswap.h which pulled in softfloat.h so it could use the types in its CPU_Float* and ldfl/stfql functions. As bswap.h is very widely included this added a compile dependency every time we touch softfloat.h. Move the typedefs for each float type into their own file so we don't re-build the world every time we tweak the main softfloat.h header. Signed-off-by: Alex Bennée Reviewed-by: Richard Henderson --- v3 - new in v3 --- include/fpu/softfloat-types.h | 115 ++++++++++++++++++++++++++++++++++++++++++ include/fpu/softfloat.h | 31 +----------- include/qemu/bswap.h | 2 +- 3 files changed, 117 insertions(+), 31 deletions(-) create mode 100644 include/fpu/softfloat-types.h -- 2.14.3 diff --git a/include/fpu/softfloat-types.h b/include/fpu/softfloat-types.h new file mode 100644 index 0000000000..8210a94ea1 --- /dev/null +++ b/include/fpu/softfloat-types.h @@ -0,0 +1,115 @@ +/* + * QEMU float support + * + * The code in this source file is derived from release 2a of the SoftFloat + * IEC/IEEE Floating-point Arithmetic Package. Those parts of the code (and + * some later contributions) are provided under that license, as detailed below. + * It has subsequently been modified by contributors to the QEMU Project, + * so some portions are provided under: + * the SoftFloat-2a license + * the BSD license + * GPL-v2-or-later + * + * This header holds definitions for code that might be dealing with + * softfloat types but not need access to the actual library functions. + */ +/* +=============================================================================== +This C header file is part of the SoftFloat IEC/IEEE Floating-point +Arithmetic Package, Release 2a. + +Written by John R. Hauser. This work was made possible in part by the +International Computer Science Institute, located at Suite 600, 1947 Center +Street, Berkeley, California 94704. Funding was partially provided by the +National Science Foundation under grant MIP-9311980. The original version +of this code was written as part of a project to build a fixed-point vector +processor in collaboration with the University of California at Berkeley, +overseen by Profs. Nelson Morgan and John Wawrzynek. More information +is available through the Web page `http://HTTP.CS.Berkeley.EDU/~jhauser/ +arithmetic/SoftFloat.html'. + +THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE. Although reasonable effort +has been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT +TIMES RESULT IN INCORRECT BEHAVIOR. USE OF THIS SOFTWARE IS RESTRICTED TO +PERSONS AND ORGANIZATIONS WHO CAN AND WILL TAKE FULL RESPONSIBILITY FOR ANY +AND ALL LOSSES, COSTS, OR OTHER PROBLEMS ARISING FROM ITS USE. + +Derivative works are acceptable, even for commercial purposes, so long as +(1) they include prominent notice that the work is derivative, and (2) they +include prominent notice akin to these four paragraphs for those parts of +this code that are retained. + +=============================================================================== +*/ + +/* BSD licensing: + * Copyright (c) 2006, Fabrice Bellard + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* Portions of this work are licensed under the terms of the GNU GPL, + * version 2 or later. See the COPYING file in the top-level directory. + */ + +#ifndef SOFTFLOAT_TYPES_H +#define SOFTFLOAT_TYPES_H + +/* + * Software IEC/IEEE floating-point types. + */ + +typedef uint16_t float16; +typedef uint32_t float32; +typedef uint64_t float64; +#define float16_val(x) (x) +#define float32_val(x) (x) +#define float64_val(x) (x) +#define make_float16(x) (x) +#define make_float32(x) (x) +#define make_float64(x) (x) +#define const_float16(x) (x) +#define const_float32(x) (x) +#define const_float64(x) (x) +typedef struct { + uint64_t low; + uint16_t high; +} floatx80; +#define make_floatx80(exp, mant) ((floatx80) { mant, exp }) +#define make_floatx80_init(exp, mant) { .low = mant, .high = exp } +typedef struct { +#ifdef HOST_WORDS_BIGENDIAN + uint64_t high, low; +#else + uint64_t low, high; +#endif +} float128; +#define make_float128(high_, low_) ((float128) { .high = high_, .low = low_ }) +#define make_float128_init(high_, low_) { .high = high_, .low = low_ } + +#endif /* SOFTFLOAT_TYPES_H */ diff --git a/include/fpu/softfloat.h b/include/fpu/softfloat.h index 52af1412de..4e16e22e58 100644 --- a/include/fpu/softfloat.h +++ b/include/fpu/softfloat.h @@ -100,36 +100,7 @@ enum { float_relation_unordered = 2 }; -/*---------------------------------------------------------------------------- -| Software IEC/IEEE floating-point types. -*----------------------------------------------------------------------------*/ -typedef uint16_t float16; -typedef uint32_t float32; -typedef uint64_t float64; -#define float16_val(x) (x) -#define float32_val(x) (x) -#define float64_val(x) (x) -#define make_float16(x) (x) -#define make_float32(x) (x) -#define make_float64(x) (x) -#define const_float16(x) (x) -#define const_float32(x) (x) -#define const_float64(x) (x) -typedef struct { - uint64_t low; - uint16_t high; -} floatx80; -#define make_floatx80(exp, mant) ((floatx80) { mant, exp }) -#define make_floatx80_init(exp, mant) { .low = mant, .high = exp } -typedef struct { -#ifdef HOST_WORDS_BIGENDIAN - uint64_t high, low; -#else - uint64_t low, high; -#endif -} float128; -#define make_float128(high_, low_) ((float128) { .high = high_, .low = low_ }) -#define make_float128_init(high_, low_) { .high = high_, .low = low_ } +#include "fpu/softfloat-types.h" /*---------------------------------------------------------------------------- | Software IEC/IEEE floating-point underflow tininess-detection mode. diff --git a/include/qemu/bswap.h b/include/qemu/bswap.h index 09c78fd28a..3f28f661b1 100644 --- a/include/qemu/bswap.h +++ b/include/qemu/bswap.h @@ -1,7 +1,7 @@ #ifndef BSWAP_H #define BSWAP_H -#include "fpu/softfloat.h" +#include "fpu/softfloat-types.h" #ifdef CONFIG_MACHINE_BSWAP_H # include From patchwork Sun Feb 4 04:11:16 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Richard Henderson X-Patchwork-Id: 126799 Delivered-To: patch@linaro.org Received: by 10.46.124.24 with SMTP id x24csp924405ljc; Sat, 3 Feb 2018 20:15:02 -0800 (PST) X-Google-Smtp-Source: AH8x224b6NaNq14kOLEOThEl7DjIswkgdTfpmBf4pozgspV385RalJwjtmVTeCNBzdKDA0pTW8le X-Received: by 10.129.175.95 with SMTP id x31mr29804041ywj.219.1517717702826; Sat, 03 Feb 2018 20:15:02 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1517717702; cv=none; d=google.com; s=arc-20160816; b=nvWfPlUqslFxXuy4ZIfZ691bC9wci4iEuZZ5To0vswOe+BMRsf6rMjU+umElSoJET+ ouOEkTU9gO1sw3BaGznA8b9qO1hMyLiZ9NMkI9TR0+lp6jKGLv17Ln1AaJEC8yXeVfne n4ZtZEFLIiZftD60ROL8PTaGUMtYlLogFZfy+izHUJIQMap7m5yRGJoeOsRjM7/Chgmf x8PO49Dlxb/EluvZ1IkYGRN9AJxHGjzPi3z0brF7jMn4Gu3uu7LcmqUivb3/Xtyfb4Go mqvYfFm5FnCfNexoWzCBpcoRKMt/ex9MWZGWwmjJR5D5EdYSwzcMhGElr0k0ZOukz9et lOhQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=sender:errors-to:cc:list-subscribe:list-help:list-post:list-archive :list-unsubscribe:list-id:precedence:subject :content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:to:from:dkim-signature:arc-authentication-results; bh=MCeTCJ2YvgTzXJKIwhnHMhvMVtoxxIyJta3uXM9si8M=; b=kjYH+lmePPfTNvGxJajjNbLanwgkPtQakjVGelBSsDLkUFftMV7ie5CnW0cFGYSnMF e53XmdZfmyVUyGbin+b53NjPsJt6m+obYeiO5CIH8nUNlwMbcxyowdM3MKFi7N4QUqfq mVSXcFxUdMZ2ntaILI4TOjiWG7f42ZJN+KHDZaDtS3KLaVD0KQRrY0yTBm/UB0U7yCNT /kVYH+LW+L2sMeq0S0rbXcJTsl892HTc2fL5x+mFr3Sg5jI+XB+pLSN+yO0qa82loeh/ +DaHNrnjQl5i+hwwtka7+IlfD+Tle+t27fAnaShy8+RLSWdNXa4QyRC7e0PIlqysDKld qAcg== ARC-Authentication-Results: i=1; mx.google.com; dkim=fail header.i=@linaro.org header.s=google header.b=jDDyNNSJ; spf=pass (google.com: domain of qemu-devel-bounces+patch=linaro.org@nongnu.org designates 2001:4830:134:3::11 as permitted sender) smtp.mailfrom=qemu-devel-bounces+patch=linaro.org@nongnu.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=linaro.org Return-Path: Received: from lists.gnu.org (lists.gnu.org. [2001:4830:134:3::11]) by mx.google.com with ESMTPS id m67si1058105ybm.773.2018.02.03.20.15.02 for (version=TLS1 cipher=AES128-SHA bits=128/128); Sat, 03 Feb 2018 20:15:02 -0800 (PST) Received-SPF: pass (google.com: domain of qemu-devel-bounces+patch=linaro.org@nongnu.org designates 2001:4830:134:3::11 as permitted sender) client-ip=2001:4830:134:3::11; Authentication-Results: mx.google.com; dkim=fail header.i=@linaro.org header.s=google header.b=jDDyNNSJ; spf=pass (google.com: domain of qemu-devel-bounces+patch=linaro.org@nongnu.org designates 2001:4830:134:3::11 as permitted sender) smtp.mailfrom=qemu-devel-bounces+patch=linaro.org@nongnu.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=linaro.org Received: from localhost ([::1]:58258 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1eiBhm-0007F1-3J for patch@linaro.org; Sat, 03 Feb 2018 23:15:02 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:47288) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1eiBeg-0004Wv-U6 for qemu-devel@nongnu.org; Sat, 03 Feb 2018 23:11:53 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1eiBed-0004qO-P8 for qemu-devel@nongnu.org; Sat, 03 Feb 2018 23:11:50 -0500 Received: from mail-pl0-x242.google.com ([2607:f8b0:400e:c01::242]:39320) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1eiBed-0004pk-Gp for qemu-devel@nongnu.org; Sat, 03 Feb 2018 23:11:47 -0500 Received: by mail-pl0-x242.google.com with SMTP id o13so9359506pli.6 for ; Sat, 03 Feb 2018 20:11:47 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=MCeTCJ2YvgTzXJKIwhnHMhvMVtoxxIyJta3uXM9si8M=; b=jDDyNNSJ0qCyRfjUFmAHjpc5jZYtGyX+qNguEyAAEQ9BL4NbYucSiSlcFidypT+8fW r6THY6gEt46YV0b3uhBbBn831GZw+Us0Ouplo0vKCUXVK/Z2QwBokIrn+nVobd5waZ0S nOBDSt+GMA8/uG0XOKayWQl11h4w0ZzAIsOps= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=MCeTCJ2YvgTzXJKIwhnHMhvMVtoxxIyJta3uXM9si8M=; b=tjh2ufNB51Znq9DtL+jBXteFHAtiGoPj1Eq93hHFk9phQvD7eGUOn8HSEnt92ImrE8 VAAnGE542adKOsi4t82JWoQ5VgYdIlYzwDRpMoslEjdFmMsvtyqfkxOwvv5wnnbXNdiI 9uZ+M30boHdOuKBc85UfobfexU33181NWVaPIw3j+qV0cL0r5AJTSuWFxq1xOFmfnL7E vJNwfaBYBy1m52Kq/mIHdLYLlkJlbqTaco1EQJcnV74gYE2nGw/5A2Wl6L+QIkX9uGM0 QWcLSrcM9/qU4c6BeWSfwR3eJtchsCIKWhtd1xLU+S6rifl/MAnGQhHJCqKM6YZpYB6f wwEQ== X-Gm-Message-State: AKwxytdyYC9zmW4txSSutZFBbtYtjJANV7ANf57IzHhfReIc4QGnKhtc Tih10dC3lQZI3OP5KU0t2p8Y2x5132E= X-Received: by 2002:a17:902:70cc:: with SMTP id l12-v6mr9176270plt.67.1517717505914; Sat, 03 Feb 2018 20:11:45 -0800 (PST) Received: from cloudburst.twiddle.net (174-21-6-47.tukw.qwest.net. [174.21.6.47]) by smtp.gmail.com with ESMTPSA id k3sm1399425pgr.12.2018.02.03.20.11.44 (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Sat, 03 Feb 2018 20:11:44 -0800 (PST) From: Richard Henderson To: qemu-devel@nongnu.org Date: Sat, 3 Feb 2018 20:11:16 -0800 Message-Id: <20180204041136.17525-5-richard.henderson@linaro.org> X-Mailer: git-send-email 2.14.3 In-Reply-To: <20180204041136.17525-1-richard.henderson@linaro.org> References: <20180204041136.17525-1-richard.henderson@linaro.org> MIME-Version: 1.0 X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 2607:f8b0:400e:c01::242 Subject: [Qemu-devel] [PATCH 04/24] target/*/cpu.h: remove softfloat.h X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: peter.maydell@linaro.org, cota@braap.org, alex.bennee@linaro.org, hsp.cat7@gmail.com Errors-To: qemu-devel-bounces+patch=linaro.org@nongnu.org Sender: "Qemu-devel" From: Alex Bennée As cpu.h is another typically widely included file which doesn't need full access to the softfloat API we can remove the includes from here as well. Where they do need types it's typically for float_status and the rounding modes so we move that to softfloat-types.h as well. As a result of not having softfloat in every cpu.h call we now need to add it to various helpers that do need the full softfloat.h definitions. Signed-off-by: Alex Bennée Reviewed-by: Philippe Mathieu-Daudé Reviewed-by: Richard Henderson [For PPC parts] Acked-by: David Gibson --- include/fpu/softfloat-types.h | 64 +++++++++++++++++++++++++++++++++++++++++ include/fpu/softfloat.h | 53 ---------------------------------- target/alpha/cpu.h | 2 -- target/arm/cpu.h | 2 -- target/hppa/cpu.h | 1 - target/i386/cpu.h | 4 --- target/m68k/cpu.h | 1 - target/microblaze/cpu.h | 2 +- target/moxie/cpu.h | 1 - target/nios2/cpu.h | 1 - target/openrisc/cpu.h | 1 - target/ppc/cpu.h | 1 - target/s390x/cpu.h | 2 -- target/sh4/cpu.h | 2 -- target/sparc/cpu.h | 2 -- target/tricore/cpu.h | 1 - target/unicore32/cpu.h | 1 - target/xtensa/cpu.h | 1 - target/arm/cpu.c | 1 + target/arm/helper-a64.c | 1 + target/arm/helper.c | 1 + target/arm/neon_helper.c | 1 + target/hppa/cpu.c | 1 + target/hppa/op_helper.c | 1 + target/i386/fpu_helper.c | 1 + target/m68k/cpu.c | 2 +- target/m68k/fpu_helper.c | 1 + target/m68k/helper.c | 1 + target/m68k/translate.c | 2 ++ target/microblaze/cpu.c | 1 + target/microblaze/op_helper.c | 1 + target/openrisc/fpu_helper.c | 1 + target/ppc/fpu_helper.c | 1 + target/ppc/int_helper.c | 1 + target/ppc/translate_init.c | 1 + target/s390x/cpu.c | 1 + target/s390x/fpu_helper.c | 1 + target/sh4/cpu.c | 1 + target/sh4/op_helper.c | 1 + target/sparc/fop_helper.c | 1 + target/tricore/fpu_helper.c | 1 + target/tricore/helper.c | 1 + target/unicore32/cpu.c | 1 + target/unicore32/ucf64_helper.c | 1 + target/xtensa/op_helper.c | 1 + 45 files changed, 93 insertions(+), 78 deletions(-) -- 2.14.3 diff --git a/include/fpu/softfloat-types.h b/include/fpu/softfloat-types.h index 8210a94ea1..4e378cb612 100644 --- a/include/fpu/softfloat-types.h +++ b/include/fpu/softfloat-types.h @@ -80,6 +80,12 @@ this code that are retained. #ifndef SOFTFLOAT_TYPES_H #define SOFTFLOAT_TYPES_H +/* This 'flag' type must be able to hold at least 0 and 1. It should + * probably be replaced with 'bool' but the uses would need to be audited + * to check that they weren't accidentally relying on it being a larger type. + */ +typedef uint8_t flag; + /* * Software IEC/IEEE floating-point types. */ @@ -112,4 +118,62 @@ typedef struct { #define make_float128(high_, low_) ((float128) { .high = high_, .low = low_ }) #define make_float128_init(high_, low_) { .high = high_, .low = low_ } +/* + * Software IEC/IEEE floating-point underflow tininess-detection mode. + */ + +enum { + float_tininess_after_rounding = 0, + float_tininess_before_rounding = 1 +}; + +/* + *Software IEC/IEEE floating-point rounding mode. + */ + +enum { + float_round_nearest_even = 0, + float_round_down = 1, + float_round_up = 2, + float_round_to_zero = 3, + float_round_ties_away = 4, + /* Not an IEEE rounding mode: round to the closest odd mantissa value */ + float_round_to_odd = 5, +}; + +/* + * Software IEC/IEEE floating-point exception flags. + */ + +enum { + float_flag_invalid = 1, + float_flag_divbyzero = 4, + float_flag_overflow = 8, + float_flag_underflow = 16, + float_flag_inexact = 32, + float_flag_input_denormal = 64, + float_flag_output_denormal = 128 +}; + + +/* + * Floating Point Status. Individual architectures may maintain + * several versions of float_status for different functions. The + * correct status for the operation is then passed by reference to + * most of the softfloat functions. + */ + +typedef struct float_status { + signed char float_detect_tininess; + signed char float_rounding_mode; + uint8_t float_exception_flags; + signed char floatx80_rounding_precision; + /* should denormalised results go to zero and set the inexact flag? */ + flag flush_to_zero; + /* should denormalised inputs go to zero and set the input_denormal flag? */ + flag flush_inputs_to_zero; + flag default_nan_mode; + flag snan_bit_is_one; +} float_status; + #endif /* SOFTFLOAT_TYPES_H */ diff --git a/include/fpu/softfloat.h b/include/fpu/softfloat.h index 4e16e22e58..f3b9008f78 100644 --- a/include/fpu/softfloat.h +++ b/include/fpu/softfloat.h @@ -82,12 +82,6 @@ this code that are retained. #ifndef SOFTFLOAT_H #define SOFTFLOAT_H -/* This 'flag' type must be able to hold at least 0 and 1. It should - * probably be replaced with 'bool' but the uses would need to be audited - * to check that they weren't accidentally relying on it being a larger type. - */ -typedef uint8_t flag; - #define LIT64( a ) a##LL /*---------------------------------------------------------------------------- @@ -102,53 +96,6 @@ enum { #include "fpu/softfloat-types.h" -/*---------------------------------------------------------------------------- -| Software IEC/IEEE floating-point underflow tininess-detection mode. -*----------------------------------------------------------------------------*/ -enum { - float_tininess_after_rounding = 0, - float_tininess_before_rounding = 1 -}; - -/*---------------------------------------------------------------------------- -| Software IEC/IEEE floating-point rounding mode. -*----------------------------------------------------------------------------*/ -enum { - float_round_nearest_even = 0, - float_round_down = 1, - float_round_up = 2, - float_round_to_zero = 3, - float_round_ties_away = 4, - /* Not an IEEE rounding mode: round to the closest odd mantissa value */ - float_round_to_odd = 5, -}; - -/*---------------------------------------------------------------------------- -| Software IEC/IEEE floating-point exception flags. -*----------------------------------------------------------------------------*/ -enum { - float_flag_invalid = 1, - float_flag_divbyzero = 4, - float_flag_overflow = 8, - float_flag_underflow = 16, - float_flag_inexact = 32, - float_flag_input_denormal = 64, - float_flag_output_denormal = 128 -}; - -typedef struct float_status { - signed char float_detect_tininess; - signed char float_rounding_mode; - uint8_t float_exception_flags; - signed char floatx80_rounding_precision; - /* should denormalised results go to zero and set the inexact flag? */ - flag flush_to_zero; - /* should denormalised inputs go to zero and set the input_denormal flag? */ - flag flush_inputs_to_zero; - flag default_nan_mode; - flag snan_bit_is_one; -} float_status; - static inline void set_float_detect_tininess(int val, float_status *status) { status->float_detect_tininess = val; diff --git a/target/alpha/cpu.h b/target/alpha/cpu.h index 09720c2f3b..a79fc2e780 100644 --- a/target/alpha/cpu.h +++ b/target/alpha/cpu.h @@ -33,8 +33,6 @@ #include "exec/cpu-defs.h" -#include "fpu/softfloat.h" - #define ICACHE_LINE_SIZE 32 #define DCACHE_LINE_SIZE 32 diff --git a/target/arm/cpu.h b/target/arm/cpu.h index d2bb59eded..c7c922d79b 100644 --- a/target/arm/cpu.h +++ b/target/arm/cpu.h @@ -39,8 +39,6 @@ #include "cpu-qom.h" #include "exec/cpu-defs.h" -#include "fpu/softfloat.h" - #define EXCP_UDEF 1 /* undefined instruction */ #define EXCP_SWI 2 /* software interrupt */ #define EXCP_PREFETCH_ABORT 3 diff --git a/target/hppa/cpu.h b/target/hppa/cpu.h index 7640c81221..c88d844938 100644 --- a/target/hppa/cpu.h +++ b/target/hppa/cpu.h @@ -51,7 +51,6 @@ #define CPUArchState struct CPUHPPAState #include "exec/cpu-defs.h" -#include "fpu/softfloat.h" #define TARGET_PAGE_BITS 12 diff --git a/target/i386/cpu.h b/target/i386/cpu.h index f91e37d25d..faf39ec1ce 100644 --- a/target/i386/cpu.h +++ b/target/i386/cpu.h @@ -52,10 +52,6 @@ #define CPUArchState struct CPUX86State -#ifdef CONFIG_TCG -#include "fpu/softfloat.h" -#endif - enum { R_EAX = 0, R_ECX = 1, diff --git a/target/m68k/cpu.h b/target/m68k/cpu.h index 627fb787b6..e250dc5278 100644 --- a/target/m68k/cpu.h +++ b/target/m68k/cpu.h @@ -28,7 +28,6 @@ #include "qemu-common.h" #include "exec/cpu-defs.h" #include "cpu-qom.h" -#include "fpu/softfloat.h" #define OS_BYTE 0 #define OS_WORD 1 diff --git a/target/microblaze/cpu.h b/target/microblaze/cpu.h index f3e7405a62..1fe21c8539 100644 --- a/target/microblaze/cpu.h +++ b/target/microblaze/cpu.h @@ -28,7 +28,7 @@ #define CPUArchState struct CPUMBState #include "exec/cpu-defs.h" -#include "fpu/softfloat.h" +#include "fpu/softfloat-types.h" struct CPUMBState; typedef struct CPUMBState CPUMBState; #if !defined(CONFIG_USER_ONLY) diff --git a/target/moxie/cpu.h b/target/moxie/cpu.h index a01f480821..d85e1fc061 100644 --- a/target/moxie/cpu.h +++ b/target/moxie/cpu.h @@ -34,7 +34,6 @@ #define MOXIE_EX_BREAK 16 #include "exec/cpu-defs.h" -#include "fpu/softfloat.h" #define TARGET_PAGE_BITS 12 /* 4k */ diff --git a/target/nios2/cpu.h b/target/nios2/cpu.h index 204b39add7..cd4e40d1b4 100644 --- a/target/nios2/cpu.h +++ b/target/nios2/cpu.h @@ -27,7 +27,6 @@ #define CPUArchState struct CPUNios2State #include "exec/cpu-defs.h" -#include "fpu/softfloat.h" #include "qom/cpu.h" struct CPUNios2State; typedef struct CPUNios2State CPUNios2State; diff --git a/target/openrisc/cpu.h b/target/openrisc/cpu.h index fb46cc9986..5050b1135c 100644 --- a/target/openrisc/cpu.h +++ b/target/openrisc/cpu.h @@ -29,7 +29,6 @@ struct OpenRISCCPU; #include "qemu-common.h" #include "exec/cpu-defs.h" -#include "fpu/softfloat.h" #include "qom/cpu.h" #define TYPE_OPENRISC_CPU "or1k-cpu" diff --git a/target/ppc/cpu.h b/target/ppc/cpu.h index 9f8cbbe7aa..7bde1884a1 100644 --- a/target/ppc/cpu.h +++ b/target/ppc/cpu.h @@ -79,7 +79,6 @@ #include "exec/cpu-defs.h" #include "cpu-qom.h" -#include "fpu/softfloat.h" #if defined (TARGET_PPC64) #define PPC_ELF_MACHINE EM_PPC64 diff --git a/target/s390x/cpu.h b/target/s390x/cpu.h index a1123ad621..96264ad4cb 100644 --- a/target/s390x/cpu.h +++ b/target/s390x/cpu.h @@ -41,8 +41,6 @@ #include "exec/cpu-all.h" -#include "fpu/softfloat.h" - #define NB_MMU_MODES 4 #define TARGET_INSN_START_EXTRA_WORDS 1 diff --git a/target/sh4/cpu.h b/target/sh4/cpu.h index 52a4568dd5..a649b68d78 100644 --- a/target/sh4/cpu.h +++ b/target/sh4/cpu.h @@ -40,8 +40,6 @@ #include "exec/cpu-defs.h" -#include "fpu/softfloat.h" - #define TARGET_PAGE_BITS 12 /* 4k XXXXX */ #define TARGET_PHYS_ADDR_SPACE_BITS 32 diff --git a/target/sparc/cpu.h b/target/sparc/cpu.h index 3eaffb354e..9724134a5b 100644 --- a/target/sparc/cpu.h +++ b/target/sparc/cpu.h @@ -29,8 +29,6 @@ #include "exec/cpu-defs.h" -#include "fpu/softfloat.h" - /*#define EXCP_INTERRUPT 0x100*/ /* trap definitions */ diff --git a/target/tricore/cpu.h b/target/tricore/cpu.h index f41d2ceb69..e7dfe4bcc6 100644 --- a/target/tricore/cpu.h +++ b/target/tricore/cpu.h @@ -24,7 +24,6 @@ #include "qemu-common.h" #include "cpu-qom.h" #include "exec/cpu-defs.h" -#include "fpu/softfloat.h" #define CPUArchState struct CPUTriCoreState diff --git a/target/unicore32/cpu.h b/target/unicore32/cpu.h index a3cc71416d..42e1d52478 100644 --- a/target/unicore32/cpu.h +++ b/target/unicore32/cpu.h @@ -23,7 +23,6 @@ #include "qemu-common.h" #include "cpu-qom.h" #include "exec/cpu-defs.h" -#include "fpu/softfloat.h" #define NB_MMU_MODES 2 diff --git a/target/xtensa/cpu.h b/target/xtensa/cpu.h index f300c02c07..49c2e3cf9a 100644 --- a/target/xtensa/cpu.h +++ b/target/xtensa/cpu.h @@ -36,7 +36,6 @@ #include "qemu-common.h" #include "cpu-qom.h" #include "exec/cpu-defs.h" -#include "fpu/softfloat.h" #include "xtensa-isa.h" #define NB_MMU_MODES 4 diff --git a/target/arm/cpu.c b/target/arm/cpu.c index 9da6ea505c..2d6ac054bd 100644 --- a/target/arm/cpu.c +++ b/target/arm/cpu.c @@ -34,6 +34,7 @@ #include "sysemu/hw_accel.h" #include "kvm_arm.h" #include "disas/capstone.h" +#include "fpu/softfloat.h" static void arm_cpu_set_pc(CPUState *cs, vaddr value) { diff --git a/target/arm/helper-a64.c b/target/arm/helper-a64.c index 06fd321fae..10e08bdc1f 100644 --- a/target/arm/helper-a64.c +++ b/target/arm/helper-a64.c @@ -31,6 +31,7 @@ #include "exec/cpu_ldst.h" #include "qemu/int128.h" #include "tcg.h" +#include "fpu/softfloat.h" #include /* For crc32 */ /* C2.4.7 Multiply and divide */ diff --git a/target/arm/helper.c b/target/arm/helper.c index bfce09643b..4ef99882c4 100644 --- a/target/arm/helper.c +++ b/target/arm/helper.c @@ -15,6 +15,7 @@ #include /* For crc32 */ #include "exec/semihost.h" #include "sysemu/kvm.h" +#include "fpu/softfloat.h" #define ARM_CPU_FREQ 1000000000 /* FIXME: 1 GHz, should be configurable */ diff --git a/target/arm/neon_helper.c b/target/arm/neon_helper.c index 689491cad3..a1ec6537eb 100644 --- a/target/arm/neon_helper.c +++ b/target/arm/neon_helper.c @@ -11,6 +11,7 @@ #include "cpu.h" #include "exec/exec-all.h" #include "exec/helper-proto.h" +#include "fpu/softfloat.h" #define SIGNBIT (uint32_t)0x80000000 #define SIGNBIT64 ((uint64_t)1 << 63) diff --git a/target/hppa/cpu.c b/target/hppa/cpu.c index 5213347720..9224331165 100644 --- a/target/hppa/cpu.c +++ b/target/hppa/cpu.c @@ -23,6 +23,7 @@ #include "cpu.h" #include "qemu-common.h" #include "exec/exec-all.h" +#include "fpu/softfloat.h" static void hppa_cpu_set_pc(CPUState *cs, vaddr value) diff --git a/target/hppa/op_helper.c b/target/hppa/op_helper.c index 4ee936bf86..ff74327cda 100644 --- a/target/hppa/op_helper.c +++ b/target/hppa/op_helper.c @@ -24,6 +24,7 @@ #include "exec/cpu_ldst.h" #include "sysemu/sysemu.h" #include "qemu/timer.h" +#include "fpu/softfloat.h" void QEMU_NORETURN HELPER(excp)(CPUHPPAState *env, int excp) diff --git a/target/i386/fpu_helper.c b/target/i386/fpu_helper.c index 9014b6f88a..ea5a0c4861 100644 --- a/target/i386/fpu_helper.c +++ b/target/i386/fpu_helper.c @@ -24,6 +24,7 @@ #include "qemu/host-utils.h" #include "exec/exec-all.h" #include "exec/cpu_ldst.h" +#include "fpu/softfloat.h" #define FPU_RC_MASK 0xc00 #define FPU_RC_NEAR 0x000 diff --git a/target/m68k/cpu.c b/target/m68k/cpu.c index 98919b358b..cbd5f08ce8 100644 --- a/target/m68k/cpu.c +++ b/target/m68k/cpu.c @@ -24,7 +24,7 @@ #include "qemu-common.h" #include "migration/vmstate.h" #include "exec/exec-all.h" - +#include "fpu/softfloat.h" static void m68k_cpu_set_pc(CPUState *cs, vaddr value) { diff --git a/target/m68k/fpu_helper.c b/target/m68k/fpu_helper.c index 665e7609af..3c5a82aaa0 100644 --- a/target/m68k/fpu_helper.c +++ b/target/m68k/fpu_helper.c @@ -23,6 +23,7 @@ #include "exec/helper-proto.h" #include "exec/exec-all.h" #include "exec/cpu_ldst.h" +#include "fpu/softfloat.h" /* Undefined offsets may be different on various FPU. * On 68040 they return 0.0 (floatx80_zero) diff --git a/target/m68k/helper.c b/target/m68k/helper.c index 20155c7801..917d46efcc 100644 --- a/target/m68k/helper.c +++ b/target/m68k/helper.c @@ -24,6 +24,7 @@ #include "exec/gdbstub.h" #include "exec/helper-proto.h" +#include "fpu/softfloat.h" #define SIGNBIT (1u << 31) diff --git a/target/m68k/translate.c b/target/m68k/translate.c index 34db97b8a0..bbbc3d8a0e 100644 --- a/target/m68k/translate.c +++ b/target/m68k/translate.c @@ -32,6 +32,8 @@ #include "trace-tcg.h" #include "exec/log.h" +#include "fpu/softfloat.h" + //#define DEBUG_DISPATCH 1 diff --git a/target/microblaze/cpu.c b/target/microblaze/cpu.c index 5700652e06..393520f3ef 100644 --- a/target/microblaze/cpu.c +++ b/target/microblaze/cpu.c @@ -28,6 +28,7 @@ #include "hw/qdev-properties.h" #include "migration/vmstate.h" #include "exec/exec-all.h" +#include "fpu/softfloat.h" static const struct { const char *name; diff --git a/target/microblaze/op_helper.c b/target/microblaze/op_helper.c index 869072a2d1..1b4fe796e7 100644 --- a/target/microblaze/op_helper.c +++ b/target/microblaze/op_helper.c @@ -24,6 +24,7 @@ #include "qemu/host-utils.h" #include "exec/exec-all.h" #include "exec/cpu_ldst.h" +#include "fpu/softfloat.h" #define D(x) diff --git a/target/openrisc/fpu_helper.c b/target/openrisc/fpu_helper.c index 1375cea948..977a1e8e55 100644 --- a/target/openrisc/fpu_helper.c +++ b/target/openrisc/fpu_helper.c @@ -22,6 +22,7 @@ #include "cpu.h" #include "exec/helper-proto.h" #include "exception.h" +#include "fpu/softfloat.h" static inline uint32_t ieee_ex_to_openrisc(OpenRISCCPU *cpu, int fexcp) { diff --git a/target/ppc/fpu_helper.c b/target/ppc/fpu_helper.c index c4dab159e4..9ae418a577 100644 --- a/target/ppc/fpu_helper.c +++ b/target/ppc/fpu_helper.c @@ -21,6 +21,7 @@ #include "exec/helper-proto.h" #include "exec/exec-all.h" #include "internal.h" +#include "fpu/softfloat.h" static inline float128 float128_snan_to_qnan(float128 x) { diff --git a/target/ppc/int_helper.c b/target/ppc/int_helper.c index 3a50f1e1b7..35bdf09773 100644 --- a/target/ppc/int_helper.c +++ b/target/ppc/int_helper.c @@ -23,6 +23,7 @@ #include "qemu/host-utils.h" #include "exec/helper-proto.h" #include "crypto/aes.h" +#include "fpu/softfloat.h" #include "helper_regs.h" /*****************************************************************************/ diff --git a/target/ppc/translate_init.c b/target/ppc/translate_init.c index 55c99c97e3..54ec2e122a 100644 --- a/target/ppc/translate_init.c +++ b/target/ppc/translate_init.c @@ -36,6 +36,7 @@ #include "sysemu/qtest.h" #include "qemu/cutils.h" #include "disas/capstone.h" +#include "fpu/softfloat.h" //#define PPC_DUMP_CPU //#define PPC_DEBUG_SPR diff --git a/target/s390x/cpu.c b/target/s390x/cpu.c index d2e6b9f5c7..7acb827f1b 100644 --- a/target/s390x/cpu.c +++ b/target/s390x/cpu.c @@ -42,6 +42,7 @@ #include "sysemu/arch_init.h" #include "sysemu/sysemu.h" #endif +#include "fpu/softfloat.h" #define CR0_RESET 0xE0UL #define CR14_RESET 0xC2000000UL; diff --git a/target/s390x/fpu_helper.c b/target/s390x/fpu_helper.c index 334159119f..43f8bf1c94 100644 --- a/target/s390x/fpu_helper.c +++ b/target/s390x/fpu_helper.c @@ -24,6 +24,7 @@ #include "exec/exec-all.h" #include "exec/cpu_ldst.h" #include "exec/helper-proto.h" +#include "fpu/softfloat.h" /* #define DEBUG_HELPER */ #ifdef DEBUG_HELPER diff --git a/target/sh4/cpu.c b/target/sh4/cpu.c index e0b99fbc89..4f8c830fe3 100644 --- a/target/sh4/cpu.c +++ b/target/sh4/cpu.c @@ -25,6 +25,7 @@ #include "qemu-common.h" #include "migration/vmstate.h" #include "exec/exec-all.h" +#include "fpu/softfloat.h" static void superh_cpu_set_pc(CPUState *cs, vaddr value) diff --git a/target/sh4/op_helper.c b/target/sh4/op_helper.c index 4b8bbf63b4..4f825bae5a 100644 --- a/target/sh4/op_helper.c +++ b/target/sh4/op_helper.c @@ -21,6 +21,7 @@ #include "exec/helper-proto.h" #include "exec/exec-all.h" #include "exec/cpu_ldst.h" +#include "fpu/softfloat.h" #ifndef CONFIG_USER_ONLY diff --git a/target/sparc/fop_helper.c b/target/sparc/fop_helper.c index c7fb176e4c..b6642fd1d7 100644 --- a/target/sparc/fop_helper.c +++ b/target/sparc/fop_helper.c @@ -21,6 +21,7 @@ #include "cpu.h" #include "exec/exec-all.h" #include "exec/helper-proto.h" +#include "fpu/softfloat.h" #define QT0 (env->qt0) #define QT1 (env->qt1) diff --git a/target/tricore/fpu_helper.c b/target/tricore/fpu_helper.c index 7979bb6692..df162902d6 100644 --- a/target/tricore/fpu_helper.c +++ b/target/tricore/fpu_helper.c @@ -20,6 +20,7 @@ #include "qemu/osdep.h" #include "cpu.h" #include "exec/helper-proto.h" +#include "fpu/softfloat.h" #define QUIET_NAN 0x7fc00000 #define ADD_NAN 0x7fc00001 diff --git a/target/tricore/helper.c b/target/tricore/helper.c index 378c2a4a76..45276d3782 100644 --- a/target/tricore/helper.c +++ b/target/tricore/helper.c @@ -19,6 +19,7 @@ #include "cpu.h" #include "exec/exec-all.h" +#include "fpu/softfloat.h" enum { TLBRET_DIRTY = -4, diff --git a/target/unicore32/cpu.c b/target/unicore32/cpu.c index 17dc1504d7..93cbae39d9 100644 --- a/target/unicore32/cpu.c +++ b/target/unicore32/cpu.c @@ -18,6 +18,7 @@ #include "qemu-common.h" #include "migration/vmstate.h" #include "exec/exec-all.h" +#include "fpu/softfloat.h" static void uc32_cpu_set_pc(CPUState *cs, vaddr value) { diff --git a/target/unicore32/ucf64_helper.c b/target/unicore32/ucf64_helper.c index 6c919010c3..fad3fa6618 100644 --- a/target/unicore32/ucf64_helper.c +++ b/target/unicore32/ucf64_helper.c @@ -11,6 +11,7 @@ #include "qemu/osdep.h" #include "cpu.h" #include "exec/helper-proto.h" +#include "fpu/softfloat.h" /* * The convention used for UniCore-F64 instructions: diff --git a/target/xtensa/op_helper.c b/target/xtensa/op_helper.c index 43182b113e..7486b99799 100644 --- a/target/xtensa/op_helper.c +++ b/target/xtensa/op_helper.c @@ -34,6 +34,7 @@ #include "exec/cpu_ldst.h" #include "exec/address-spaces.h" #include "qemu/timer.h" +#include "fpu/softfloat.h" void xtensa_cpu_do_unaligned_access(CPUState *cs, vaddr addr, MMUAccessType access_type, From patchwork Sun Feb 4 04:11:17 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Richard Henderson X-Patchwork-Id: 126796 Delivered-To: patch@linaro.org Received: by 10.46.124.24 with SMTP id x24csp924194ljc; Sat, 3 Feb 2018 20:14:33 -0800 (PST) X-Google-Smtp-Source: AH8x224KlyaUym25zMh+8xpyyL11RquZJwFOpzvoB33sHcJP51bGyZspKPXsxKahsIU/2x4R8nh2 X-Received: by 10.13.223.12 with SMTP id i12mr29500192ywe.385.1517717673090; Sat, 03 Feb 2018 20:14:33 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1517717673; cv=none; d=google.com; s=arc-20160816; b=PQ1PwstoJyeQ5RDtDYPJx2mo0o/qkOPpunA9uRSS+xCfldnVlf3RRDIEV+NDyghVQf 4XCwDxo6NFPYzoidqfE+LCIzTOMKj3vg8YF1ucTCJvnhh4y7L4nLMOvTauB9wz0QYd4i GR/mZuQd0nYfNcY9Xw0eEKrgaXWVad7Qc/Pczzfm+aPMXf5uYioKlqotwyI0sdFZyAXu 1xU1SvoAJj74xKS6GnG5e4I6Lk9K9bt4zL6Vc/W5NMIO02YaoECzq/VAkf4BC4xPWbWI xjmJiV7B8EultGR/7rUaof/Bz04lpN5XPZ/jvDVR5CW2gAUwNQW1/RFNoEPVT4XFm9FU pKvw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=sender:errors-to:cc:list-subscribe:list-help:list-post:list-archive :list-unsubscribe:list-id:precedence:subject :content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:to:from:dkim-signature:arc-authentication-results; bh=HGk+sRcaO/3VZ+HlNs35hRcgSdkKsfPLIie4AKk36lM=; b=TG18/kaxeHPsHIkjqiBBirLHeNkhs/SiikMpN9IsdCv0v5gz/oh4o+Df+NvmU4mApJ e5i7CLAsiaEt71ZqzXIXxhVMoFHUxgE0bIUkESqfXYwzF3DpxLvd9lYnePGuRnBK7R5k iYxt39hNKAZY4QZSuJb9crVJOOzp9wVIUynyZtYja0wCCx2e1XEm/uCHmrhhPEC3bIfF 1v1zKBZ97ZMKDhNbvP5DKp5QomvXGcnO2MB+QJ0OnZkpx/LsdY/MmtqwGLCPWBWfgTLF xNp410Oe96p6qzb8twpC2FO35I2LlrmLaarYOvOFm83MDvgR34M/E6sHbY7Pv77piGWs LMfg== ARC-Authentication-Results: i=1; mx.google.com; dkim=fail header.i=@linaro.org header.s=google header.b=dkgT7sLH; spf=pass (google.com: domain of qemu-devel-bounces+patch=linaro.org@nongnu.org designates 2001:4830:134:3::11 as permitted sender) smtp.mailfrom=qemu-devel-bounces+patch=linaro.org@nongnu.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=linaro.org Return-Path: Received: from lists.gnu.org (lists.gnu.org. [2001:4830:134:3::11]) by mx.google.com with ESMTPS id a185si108820ywe.13.2018.02.03.20.14.32 for (version=TLS1 cipher=AES128-SHA bits=128/128); Sat, 03 Feb 2018 20:14:33 -0800 (PST) Received-SPF: pass (google.com: domain of qemu-devel-bounces+patch=linaro.org@nongnu.org designates 2001:4830:134:3::11 as permitted sender) client-ip=2001:4830:134:3::11; Authentication-Results: mx.google.com; dkim=fail header.i=@linaro.org header.s=google header.b=dkgT7sLH; spf=pass (google.com: domain of qemu-devel-bounces+patch=linaro.org@nongnu.org designates 2001:4830:134:3::11 as permitted sender) smtp.mailfrom=qemu-devel-bounces+patch=linaro.org@nongnu.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=linaro.org Received: from localhost ([::1]:58241 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1eiBhI-0005sq-Em for patch@linaro.org; Sat, 03 Feb 2018 23:14:32 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:47266) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1eiBef-0004V8-Et for qemu-devel@nongnu.org; Sat, 03 Feb 2018 23:11:50 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1eiBee-0004qd-K9 for qemu-devel@nongnu.org; Sat, 03 Feb 2018 23:11:49 -0500 Received: from mail-pl0-x244.google.com ([2607:f8b0:400e:c01::244]:36507) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1eiBee-0004qS-E7 for qemu-devel@nongnu.org; Sat, 03 Feb 2018 23:11:48 -0500 Received: by mail-pl0-x244.google.com with SMTP id v3so9363299plg.3 for ; Sat, 03 Feb 2018 20:11:48 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=HGk+sRcaO/3VZ+HlNs35hRcgSdkKsfPLIie4AKk36lM=; b=dkgT7sLH+MOxeKUL4GfojQySoD2FWMVc9qvZJUMMQ0hZUphs+vuVaEdGkICOZj+Uib OmHcHQMNgyNvtQE+36iC36Kn2h3iqX84SuZUkMg4R2ZpYmB2OxRMUQKBRHFa1iBOxr2d Si1CRV+Lv+r63x0IcIV7C1Sl560OFuI791nKY= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=HGk+sRcaO/3VZ+HlNs35hRcgSdkKsfPLIie4AKk36lM=; b=A34nx3g/PTUFVcigr4z4P3kL3uUl0A1tZ+j62tIqvVpxC6Byhwb0nVxeA1cXf3tSyo AWFEvQhl8HfsyicKp2k77C0XT/2kgP9E8fCmhyam4xF0s5SYIHLm6QcDklVW3jw8sUuA aJ4OzLV2CDt/dvqg84bKCBLkVzBOx9D9B4FPAacKKEFSmO0J9oBuKcNWaszbVTPx8YCA t353DvP3KcyTQqv/uzsJnpegp6pEdtSv81gcN2Xpi05y5rfNvhHYghzXDxSXTJVdzV0b vkY15n9gcjwjLEzwErR1UuOmFe5e3yYsSiTbELHKn72ARu/sTW57NYZpoiLFdBBdmAoO mBSg== X-Gm-Message-State: AKwxyteB9gkjrTs5h37zNDG5kuebDpnleJaZMpxV+9sGFttrYGCKXk3J x4WaIewlLukXFOWfRK4Wyeud/f6du5o= X-Received: by 2002:a17:902:6006:: with SMTP id r6-v6mr23300022plj.78.1517717507180; Sat, 03 Feb 2018 20:11:47 -0800 (PST) Received: from cloudburst.twiddle.net (174-21-6-47.tukw.qwest.net. [174.21.6.47]) by smtp.gmail.com with ESMTPSA id k3sm1399425pgr.12.2018.02.03.20.11.45 (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Sat, 03 Feb 2018 20:11:46 -0800 (PST) From: Richard Henderson To: qemu-devel@nongnu.org Date: Sat, 3 Feb 2018 20:11:17 -0800 Message-Id: <20180204041136.17525-6-richard.henderson@linaro.org> X-Mailer: git-send-email 2.14.3 In-Reply-To: <20180204041136.17525-1-richard.henderson@linaro.org> References: <20180204041136.17525-1-richard.henderson@linaro.org> MIME-Version: 1.0 X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 2607:f8b0:400e:c01::244 Subject: [Qemu-devel] [PATCH 05/24] include/fpu/softfloat: implement float16_abs helper X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: peter.maydell@linaro.org, cota@braap.org, alex.bennee@linaro.org, hsp.cat7@gmail.com Errors-To: qemu-devel-bounces+patch=linaro.org@nongnu.org Sender: "Qemu-devel" From: Alex Bennée This will be required when expanding the MINMAX() macro for 16 bit/half-precision operations. Signed-off-by: Alex Bennée Reviewed-by: Richard Henderson Reviewed-by: Philippe Mathieu-Daudé Reviewed-by: Peter Maydell --- include/fpu/softfloat.h | 7 +++++++ 1 file changed, 7 insertions(+) -- 2.14.3 diff --git a/include/fpu/softfloat.h b/include/fpu/softfloat.h index f3b9008f78..1d34f2c3eb 100644 --- a/include/fpu/softfloat.h +++ b/include/fpu/softfloat.h @@ -265,6 +265,13 @@ static inline int float16_is_zero_or_denormal(float16 a) return (float16_val(a) & 0x7c00) == 0; } +static inline float16 float16_abs(float16 a) +{ + /* Note that abs does *not* handle NaN specially, nor does + * it flush denormal inputs to zero. + */ + return make_float16(float16_val(a) & 0x7fff); +} /*---------------------------------------------------------------------------- | The pattern for a default generated half-precision NaN. *----------------------------------------------------------------------------*/ From patchwork Sun Feb 4 04:11:18 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Richard Henderson X-Patchwork-Id: 126801 Delivered-To: patch@linaro.org Received: by 10.46.124.24 with SMTP id x24csp925650ljc; Sat, 3 Feb 2018 20:18:09 -0800 (PST) X-Google-Smtp-Source: AH8x224nyfX1TLOQtNfXRvfJR+6KB2qpq9FKCeUSza85soIqKXemOJ+0wmWfHIvYikYdwPqk4SIw X-Received: by 10.129.37.5 with SMTP id l5mr29337720ywl.161.1517717889404; Sat, 03 Feb 2018 20:18:09 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1517717889; cv=none; d=google.com; s=arc-20160816; b=PpzGp3mhYJlDUutIHaas5RIXeuX/M2b/XTMC5bvATw1nknocgF4U3zpqtbe0j75Yme W8CbhmqqXOJipyN75fLOrEgUFgisr4Qb04q2qrkAemAMgadjKsqeVZ0pvCedIBeggO8v w5XgDrjxhSWRqwyHeAkPB/tRmi6SpmreQ4L2RCrvIhnUJVuIR90AdZYp9MVP1ttNAlEw 0LQD9MMGDMuf8qFXYV++qBMxCoVNFPZfIZ8On+cnLol9cYMgBn+8ZqtLXopq45XM08dG Mc7MPOGPMPXzNG4BYqmmH1ugYrTc9jBuW/W9ITYBWerTOkutqB47Ya0BvOYM3ZT31N1e 12hQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=sender:errors-to:cc:list-subscribe:list-help:list-post:list-archive :list-unsubscribe:list-id:precedence:subject :content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:to:from:dkim-signature:arc-authentication-results; bh=vHPnIprtX/tb6NYsozovplAJVcOT+i+E13slBVdPE64=; b=xB+5lu6ODLOfmickppAJ37rpvPpyFSJ8VeMm7ToTnLaAWSBZ8is07Ciz1izOYTWCDf NcWaSIttLt/x8Ri9c4xDxbAYvSTyBLjI+2cDK7ll28MMed3NH0wseizqlzYsvFP3BLxB Vl+ntkxYgiNX/FuMHqChM8mBCcxZPGnQnHLIR1reG3lgAxEPpRJXE9N/tbLmUWvbXq9z XG/eYT2bfWPEvGn5mRtcFTE4Va7GXohAf9bcjFip4eKoUzbH9EeO5MLqdgv1D6G0Zrgx +pKnFcLFmDRuF3fkakQwjv5szIvetswVFqP3k6lygyv0OnMMbc9FDXRzOpMOISbGubrD 1v9w== ARC-Authentication-Results: i=1; mx.google.com; dkim=fail header.i=@linaro.org header.s=google header.b=OhOutUFb; spf=pass (google.com: domain of qemu-devel-bounces+patch=linaro.org@nongnu.org designates 2001:4830:134:3::11 as permitted sender) smtp.mailfrom=qemu-devel-bounces+patch=linaro.org@nongnu.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=linaro.org Return-Path: Received: from lists.gnu.org (lists.gnu.org. [2001:4830:134:3::11]) by mx.google.com with ESMTPS id 202si1015104yws.623.2018.02.03.20.18.09 for (version=TLS1 cipher=AES128-SHA bits=128/128); Sat, 03 Feb 2018 20:18:09 -0800 (PST) Received-SPF: pass (google.com: domain of qemu-devel-bounces+patch=linaro.org@nongnu.org designates 2001:4830:134:3::11 as permitted sender) client-ip=2001:4830:134:3::11; Authentication-Results: mx.google.com; dkim=fail header.i=@linaro.org header.s=google header.b=OhOutUFb; spf=pass (google.com: domain of qemu-devel-bounces+patch=linaro.org@nongnu.org designates 2001:4830:134:3::11 as permitted sender) smtp.mailfrom=qemu-devel-bounces+patch=linaro.org@nongnu.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=linaro.org Received: from localhost ([::1]:58276 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1eiBkm-0001PR-P6 for patch@linaro.org; Sat, 03 Feb 2018 23:18:08 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:47286) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1eiBeg-0004Wb-LE for qemu-devel@nongnu.org; Sat, 03 Feb 2018 23:11:51 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1eiBef-0004rI-SZ for qemu-devel@nongnu.org; Sat, 03 Feb 2018 23:11:50 -0500 Received: from mail-pl0-x244.google.com ([2607:f8b0:400e:c01::244]:34684) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1eiBef-0004qv-NH for qemu-devel@nongnu.org; Sat, 03 Feb 2018 23:11:49 -0500 Received: by mail-pl0-x244.google.com with SMTP id q17so7155990pll.1 for ; Sat, 03 Feb 2018 20:11:49 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=vHPnIprtX/tb6NYsozovplAJVcOT+i+E13slBVdPE64=; b=OhOutUFbr5nI/h9cF1STq+YGaJSeBpAWwMYvM2RpMrWtvjIxAOM22Q2i1FfdaziGjE mMaAzHz7q5/XVFT4Vawk++qFDvruPnlDgd6tV0leKKy11PzjfCItGCfJLOz4fN0c+cLJ +8CHniwWEjhzrax7CrlL6E3FNj3CakeSc+1SY= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=vHPnIprtX/tb6NYsozovplAJVcOT+i+E13slBVdPE64=; b=RmnIXzY2SnTPqSvks+IfsnUCREnECjiG2EjublYMfxo9dvowh5STvF5Xczsjhwjzv3 nVzRLysASYdqrZBJMkksEMTRijIYCxl1pQObpkcogDOoVGcYsiMYQDLdFQI5HIrPcW+l Tz2hmyGJ5QPDoKdBdowBtJ81PGJgH5unkBqPk6TiQZr8pJqvZWL6rsSw5hDYuQwDTudO r94Tkok+MjyMeV3cM5yoyLyEidLUskcYlidV4IT06vUIZsWbfxx05uGFEcOzWjqXOnd7 EQ8F/hVjRS5f/O2mC2XwObxMq0FtEFvxogAv9kD/vFIByQctsKQQAGpoSs0ten3ybNPz GzeA== X-Gm-Message-State: AKwxytfrWKzH8ij6DXZTgqVxG2e85T0m3riIbDKSN0qVSRs1myYbtjAK e/EI5b1ZY19Yn1dncrNUUS6bLfNLnhI= X-Received: by 2002:a17:902:28c4:: with SMTP id f62-v6mr37146649plb.31.1517717508616; Sat, 03 Feb 2018 20:11:48 -0800 (PST) Received: from cloudburst.twiddle.net (174-21-6-47.tukw.qwest.net. [174.21.6.47]) by smtp.gmail.com with ESMTPSA id k3sm1399425pgr.12.2018.02.03.20.11.47 (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Sat, 03 Feb 2018 20:11:47 -0800 (PST) From: Richard Henderson To: qemu-devel@nongnu.org Date: Sat, 3 Feb 2018 20:11:18 -0800 Message-Id: <20180204041136.17525-7-richard.henderson@linaro.org> X-Mailer: git-send-email 2.14.3 In-Reply-To: <20180204041136.17525-1-richard.henderson@linaro.org> References: <20180204041136.17525-1-richard.henderson@linaro.org> MIME-Version: 1.0 X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 2607:f8b0:400e:c01::244 Subject: [Qemu-devel] [PATCH 06/24] include/fpu/softfloat: implement float16_chs helper X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: peter.maydell@linaro.org, cota@braap.org, alex.bennee@linaro.org, hsp.cat7@gmail.com Errors-To: qemu-devel-bounces+patch=linaro.org@nongnu.org Sender: "Qemu-devel" From: Alex Bennée Signed-off-by: Alex Bennée Reviewed-by: Richard Henderson Reviewed-by: Peter Maydell --- include/fpu/softfloat.h | 9 +++++++++ 1 file changed, 9 insertions(+) -- 2.14.3 diff --git a/include/fpu/softfloat.h b/include/fpu/softfloat.h index 1d34f2c3eb..f75aa59100 100644 --- a/include/fpu/softfloat.h +++ b/include/fpu/softfloat.h @@ -272,6 +272,15 @@ static inline float16 float16_abs(float16 a) */ return make_float16(float16_val(a) & 0x7fff); } + +static inline float16 float16_chs(float16 a) +{ + /* Note that chs does *not* handle NaN specially, nor does + * it flush denormal inputs to zero. + */ + return make_float16(float16_val(a) ^ 0x8000); +} + /*---------------------------------------------------------------------------- | The pattern for a default generated half-precision NaN. *----------------------------------------------------------------------------*/ From patchwork Sun Feb 4 04:11:19 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Richard Henderson X-Patchwork-Id: 126798 Delivered-To: patch@linaro.org Received: by 10.46.124.24 with SMTP id x24csp924401ljc; Sat, 3 Feb 2018 20:15:01 -0800 (PST) X-Google-Smtp-Source: AH8x2242jKDC0Y0v2HM1LcKfwpfOH++CGYrgdbBoCvajgFSZxkapnyXtZa5H21JF+2rTGsfEnP0s X-Received: by 10.129.46.3 with SMTP id u3mr7262503ywu.481.1517717701350; Sat, 03 Feb 2018 20:15:01 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1517717701; cv=none; d=google.com; s=arc-20160816; b=h1P2lcSRGNRpoOI7RQsSy9cSYZo/jo83jeLUki1GrXoBfimwAKzAer6u+nLax4ku4A WQlymSAx/tqSIn9XWWuWCsSzcuo4cy1bGtyzwRotfPf8JTvIE6EnjIrlyildGBYK/Fcb lsl67xfzT1HE5hlkoUZJG074Ezw37Xd9V//TKjutVGsYpdKsq/etUWB5w9pnmEZJKMh8 Bh532/NNotyJ/ZwsZhuoJ/BAviDbyLUWVU2vo2JIq2awBHJ5O0ZLPJVf1rGpuSG0KZrs pTwRhs5EDUw8KvqoRElTigZ9l3xse19QaqV/6b4xaFuoaSg7Jp9tmVMFCJ6WaJFprzdI DY3w== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=sender:errors-to:cc:list-subscribe:list-help:list-post:list-archive :list-unsubscribe:list-id:precedence:subject :content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:to:from:dkim-signature:arc-authentication-results; bh=QefWOD5QoOoi8TNKVFq33z0FgQ9NAGQGNRsIESMBXUI=; b=H/6PyINOkKavBXZICoIPfuWZXiO9SlpwDIDJNrZZNidHvCntt780budgiIpxIOgtlv Oqnvjj/8omM4d5+UVlTAlgee35C2AGux1F3UYpKcIdT3HVxrZoaTpEJZf8OS7UK77KxU wTlu9HUAGT0jlEf4R8rqq2isK9fLyRWJ4n5e6C5u/A+8qqHhY0MckwzLH2FwmIG2Hy3e S40f3uuvNVbr29NtKj6wVU4I5pTPMD4J1lzfADw7Wjh64toL/7XjBg6XeKrGJu4bHndJ q178I1//Z3Rj4UeJ60SbAngs2e/76/bhvk5hWBD88Pp1haDvF+3Plo8CnA70Rr4l8Skm QRKw== ARC-Authentication-Results: i=1; mx.google.com; dkim=fail header.i=@linaro.org header.s=google header.b=Dnkndd4U; spf=pass (google.com: domain of qemu-devel-bounces+patch=linaro.org@nongnu.org designates 2001:4830:134:3::11 as permitted sender) smtp.mailfrom=qemu-devel-bounces+patch=linaro.org@nongnu.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=linaro.org Return-Path: Received: from lists.gnu.org (lists.gnu.org. [2001:4830:134:3::11]) by mx.google.com with ESMTPS id 205si1020475yws.342.2018.02.03.20.15.01 for (version=TLS1 cipher=AES128-SHA bits=128/128); Sat, 03 Feb 2018 20:15:01 -0800 (PST) Received-SPF: pass (google.com: domain of qemu-devel-bounces+patch=linaro.org@nongnu.org designates 2001:4830:134:3::11 as permitted sender) client-ip=2001:4830:134:3::11; Authentication-Results: mx.google.com; dkim=fail header.i=@linaro.org header.s=google header.b=Dnkndd4U; spf=pass (google.com: domain of qemu-devel-bounces+patch=linaro.org@nongnu.org designates 2001:4830:134:3::11 as permitted sender) smtp.mailfrom=qemu-devel-bounces+patch=linaro.org@nongnu.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=linaro.org Received: from localhost ([::1]:58257 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1eiBhk-0007Ez-Nr for patch@linaro.org; Sat, 03 Feb 2018 23:15:00 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:47299) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1eiBei-0004Yg-Ai for qemu-devel@nongnu.org; Sat, 03 Feb 2018 23:11:57 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1eiBeh-0004rx-HZ for qemu-devel@nongnu.org; Sat, 03 Feb 2018 23:11:52 -0500 Received: from mail-pg0-x242.google.com ([2607:f8b0:400e:c05::242]:41094) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1eiBeh-0004rh-B1 for qemu-devel@nongnu.org; Sat, 03 Feb 2018 23:11:51 -0500 Received: by mail-pg0-x242.google.com with SMTP id 141so5380855pgd.8 for ; Sat, 03 Feb 2018 20:11:51 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=QefWOD5QoOoi8TNKVFq33z0FgQ9NAGQGNRsIESMBXUI=; b=Dnkndd4U7LBnRXqPrBfAT+gmeWe5sH1LBgTVxyAe7pjqD5tKaiTfR/AhHTu9BjQCZo obcllywv/uBn0NKJRPzTZQ+DfH6hEyTeiU2BJ/CxrW2aXaf2HUI63Y7cb9oEjvpTzBxq Q2m/Ov5H2nmMFDUUrmk+u0JikrThhkeV/cxR4= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=QefWOD5QoOoi8TNKVFq33z0FgQ9NAGQGNRsIESMBXUI=; b=QRkk22xWkL9v2BJqjiTsqPGXQqgl8A9R+GTumGKBrXu13ppU/E0cf1VInPnhYyFYGQ RDh5p73e+HWe6OMIWzKd4EvPNIJXxA5f1dQ7Vhf5TpAq4rzsu03dWOZodvActz4g/qZU WSdQMjRBVHcwgQpgZaAw4pVhzStHPwsLpAOL/4we4gIRSDt6Z3nvGC8LGJfMbpnoEVP5 n8XN06QAGoBFLIAH0JOzTS3JlE/FTcWIXTy6U+qeF8gTaSG///MJIrIxAAW7pDiqA+kB K4rJ1jpMT29BFLLfUA1/Igmjdp1S8KWd/agrEyyyQbywiXHhV/OAcenHVqRWh6YAoL13 XGKw== X-Gm-Message-State: APf1xPBBNlMT2+QsuCNSF0V6YVSJXZmFKn0x5xfFhKxtshCPvbBltwO3 Ea2XfP2PbmCiGW5oQ0RzP5eD9XeQiLY= X-Received: by 10.99.6.201 with SMTP id 192mr1372598pgg.50.1517717510099; Sat, 03 Feb 2018 20:11:50 -0800 (PST) Received: from cloudburst.twiddle.net (174-21-6-47.tukw.qwest.net. [174.21.6.47]) by smtp.gmail.com with ESMTPSA id k3sm1399425pgr.12.2018.02.03.20.11.48 (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Sat, 03 Feb 2018 20:11:49 -0800 (PST) From: Richard Henderson To: qemu-devel@nongnu.org Date: Sat, 3 Feb 2018 20:11:19 -0800 Message-Id: <20180204041136.17525-8-richard.henderson@linaro.org> X-Mailer: git-send-email 2.14.3 In-Reply-To: <20180204041136.17525-1-richard.henderson@linaro.org> References: <20180204041136.17525-1-richard.henderson@linaro.org> MIME-Version: 1.0 X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 2607:f8b0:400e:c05::242 Subject: [Qemu-devel] [PATCH 07/24] include/fpu/softfloat: implement float16_set_sign helper X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: peter.maydell@linaro.org, cota@braap.org, alex.bennee@linaro.org, hsp.cat7@gmail.com Errors-To: qemu-devel-bounces+patch=linaro.org@nongnu.org Sender: "Qemu-devel" From: Alex Bennée Signed-off-by: Alex Bennée Reviewed-by: Peter Maydell Reviewed-by: Philippe Mathieu-Daudé Reviewed-by: Richard Henderson --- include/fpu/softfloat.h | 5 +++++ 1 file changed, 5 insertions(+) -- 2.14.3 diff --git a/include/fpu/softfloat.h b/include/fpu/softfloat.h index f75aa59100..59c06ef192 100644 --- a/include/fpu/softfloat.h +++ b/include/fpu/softfloat.h @@ -281,6 +281,11 @@ static inline float16 float16_chs(float16 a) return make_float16(float16_val(a) ^ 0x8000); } +static inline float16 float16_set_sign(float16 a, int sign) +{ + return make_float16((float16_val(a) & 0x7fff) | (sign << 15)); +} + /*---------------------------------------------------------------------------- | The pattern for a default generated half-precision NaN. *----------------------------------------------------------------------------*/ From patchwork Sun Feb 4 04:11:20 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Richard Henderson X-Patchwork-Id: 126806 Delivered-To: patch@linaro.org Received: by 10.46.124.24 with SMTP id x24csp927010ljc; Sat, 3 Feb 2018 20:21:22 -0800 (PST) X-Google-Smtp-Source: AH8x226ds1kxAgFKEut7MNKFf2sm1VfTssgDeKdvdqAJr/MVc17IlbwLcUwsaHDevHuJ70XO4DfW X-Received: by 10.129.118.18 with SMTP id r18mr29712909ywc.96.1517718082315; Sat, 03 Feb 2018 20:21:22 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1517718082; cv=none; d=google.com; s=arc-20160816; b=d5vX7PmLvYJbTOiUqWaDP5R/n21yf1FwuLpNfHziQrpREX7x1SXQkxT5hgIS7mNKu6 Wa+h4yaxFZcCNiL5vunKe1vv6kRrC9MsfKJhKQQtU8k9Y0XwQFfbiXl+PcNfT2RejVNW V/lCLrd+1ngLACCBycfayC5fCNiSC9gN5q5WNrJl3oraE8QUYlRyT/tg96tlKO8Sj+ZW sc39LGFSrFDzOudMzBtziMEQya97PlGjtfTGhjPvQUoZmaX66lLX2q7OUu+AWRz6OPKe 9Rtfw7EmRFV7TtV5TrUGxubrbdVH6wBWztNK/JfxXrUGV6z11W/HzFNau1+MXuM0EXTY JVdA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=sender:errors-to:cc:list-subscribe:list-help:list-post:list-archive :list-unsubscribe:list-id:precedence:subject :content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:to:from:dkim-signature:arc-authentication-results; bh=mGirWZOwyS8TVU5YKMT+3Lan0MY1gV2C5QIm3hckiT8=; b=0nNYFJJNAZSBgmzwyNGHTV0xxIFSz5gcn4ixHMZnY2eUusGh00cjdCvaMV4qto613j bimulfZ6lqz/VQ1g+qOkL7ylpv9RhstDRfxPc3NsemUaZ+55UT5D7CO092rXNSFD7ddo qjZh3QwEClvdEj1zrxZmOZ4XlKBFjtH/Kb6Wlg08BgAYGqy1BBMAkkq2HRb1WFSZOyzN jLRBOhZzjc4ED2LFtPMHhvbbrekSc5PLd4NHgPGMPYOYkYyxjcnghdJbhZaRo1mPb4jz Tjwj/HYwsqwS0Nhpl8Wdi2vp91FYn2SOQX3TRtYMWbKh22bY46omqtxXNhGBPixlWk8q zyDA== ARC-Authentication-Results: i=1; mx.google.com; dkim=fail header.i=@linaro.org header.s=google header.b=emPeIkzC; spf=pass (google.com: domain of qemu-devel-bounces+patch=linaro.org@nongnu.org designates 2001:4830:134:3::11 as permitted sender) smtp.mailfrom=qemu-devel-bounces+patch=linaro.org@nongnu.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=linaro.org Return-Path: Received: from lists.gnu.org (lists.gnu.org. [2001:4830:134:3::11]) by mx.google.com with ESMTPS id j206si1021374ywg.275.2018.02.03.20.21.22 for (version=TLS1 cipher=AES128-SHA bits=128/128); Sat, 03 Feb 2018 20:21:22 -0800 (PST) Received-SPF: pass (google.com: domain of qemu-devel-bounces+patch=linaro.org@nongnu.org designates 2001:4830:134:3::11 as permitted sender) client-ip=2001:4830:134:3::11; Authentication-Results: mx.google.com; dkim=fail header.i=@linaro.org header.s=google header.b=emPeIkzC; spf=pass (google.com: domain of qemu-devel-bounces+patch=linaro.org@nongnu.org designates 2001:4830:134:3::11 as permitted sender) smtp.mailfrom=qemu-devel-bounces+patch=linaro.org@nongnu.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=linaro.org Received: from localhost ([::1]:58305 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1eiBnt-0004IW-J8 for patch@linaro.org; Sat, 03 Feb 2018 23:21:21 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:47327) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1eiBen-0004f9-AJ for qemu-devel@nongnu.org; Sat, 03 Feb 2018 23:11:58 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1eiBei-0004sv-Tm for qemu-devel@nongnu.org; Sat, 03 Feb 2018 23:11:57 -0500 Received: from mail-pg0-x243.google.com ([2607:f8b0:400e:c05::243]:44775) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1eiBei-0004sG-Nx for qemu-devel@nongnu.org; Sat, 03 Feb 2018 23:11:52 -0500 Received: by mail-pg0-x243.google.com with SMTP id r1so395422pgn.11 for ; Sat, 03 Feb 2018 20:11:52 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=mGirWZOwyS8TVU5YKMT+3Lan0MY1gV2C5QIm3hckiT8=; b=emPeIkzCOY77OaWXoRZoli64hsgL2NgY+lWE01lFhOlxD3WeJZo3sk7R7SPr1HkAz+ P0uGPeWM7skUy7FVHc2sSj9d/fjLrYuxIW171g747U+MSg4i2fMizwV5ox5OXzcPPSM4 jKUTWQwqCRVe/jig1fgDc08AkZ/v9NhL0gpo0= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=mGirWZOwyS8TVU5YKMT+3Lan0MY1gV2C5QIm3hckiT8=; b=UUGOquSnS1rXsOzJtVO40dltQAOlzF2G+oAc1ckxxeakASZJQmhYDxAoLni93hO0pj qjaCZJnr5o15xFAoFL4mamGjOk7erIQGC/TSqTjiMugehocZHoq35oSarWtOQl3m/A/H i/iSG2IrSxBoKQUVjRzpM621rWWMpOvRFqn0SbCrateVHVI9pSNsTUS9FIL9JqZg+BCI 9hTo/0OuLhFXO+2Cq+uz5jNMeQgOCgcYD2nHW1TKqnRWRHN02uQYKk57SIXn8FTlYbup EJPBmPRSWt8pOcILiDFADjGwrWqHPv3UbKSYWbGkW7q+oSD1eno06HTzpkVAt0D03O9c XBsA== X-Gm-Message-State: AKwxytc7dGpH0s6LIWCuzR3LBtaMw6FYyB28mmMU2W6gs+qtoqU7k0BD paZbyM6Ph4bTJaRq9+BqtrTpWbFalyU= X-Received: by 10.101.64.139 with SMTP id t11mr8448293pgp.162.1517717511500; Sat, 03 Feb 2018 20:11:51 -0800 (PST) Received: from cloudburst.twiddle.net (174-21-6-47.tukw.qwest.net. [174.21.6.47]) by smtp.gmail.com with ESMTPSA id k3sm1399425pgr.12.2018.02.03.20.11.50 (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Sat, 03 Feb 2018 20:11:50 -0800 (PST) From: Richard Henderson To: qemu-devel@nongnu.org Date: Sat, 3 Feb 2018 20:11:20 -0800 Message-Id: <20180204041136.17525-9-richard.henderson@linaro.org> X-Mailer: git-send-email 2.14.3 In-Reply-To: <20180204041136.17525-1-richard.henderson@linaro.org> References: <20180204041136.17525-1-richard.henderson@linaro.org> MIME-Version: 1.0 X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 2607:f8b0:400e:c05::243 Subject: [Qemu-devel] [PATCH 08/24] include/fpu/softfloat: add some float16 constants X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: peter.maydell@linaro.org, cota@braap.org, alex.bennee@linaro.org, hsp.cat7@gmail.com Errors-To: qemu-devel-bounces+patch=linaro.org@nongnu.org Sender: "Qemu-devel" From: Alex Bennée This defines the same set of common constants for float 16 as defined for 32 and 64 bit floats. These are often used by target helper functions. I've also removed constants that are not used by anybody. Signed-off-by: Alex Bennée Reviewed-by: Philippe Mathieu-Daudé Reviewed-by: Richard Henderson --- v2 - fixup constants, remove unused onces --- include/fpu/softfloat.h | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) -- 2.14.3 diff --git a/include/fpu/softfloat.h b/include/fpu/softfloat.h index 59c06ef192..23824a3000 100644 --- a/include/fpu/softfloat.h +++ b/include/fpu/softfloat.h @@ -286,6 +286,11 @@ static inline float16 float16_set_sign(float16 a, int sign) return make_float16((float16_val(a) & 0x7fff) | (sign << 15)); } +#define float16_zero make_float16(0) +#define float16_one make_float16(0x3c00) +#define float16_half make_float16(0x3800) +#define float16_infinity make_float16(0x7c00) + /*---------------------------------------------------------------------------- | The pattern for a default generated half-precision NaN. *----------------------------------------------------------------------------*/ @@ -392,8 +397,6 @@ static inline float32 float32_set_sign(float32 a, int sign) #define float32_zero make_float32(0) #define float32_one make_float32(0x3f800000) -#define float32_ln2 make_float32(0x3f317218) -#define float32_pi make_float32(0x40490fdb) #define float32_half make_float32(0x3f000000) #define float32_infinity make_float32(0x7f800000) @@ -506,7 +509,6 @@ static inline float64 float64_set_sign(float64 a, int sign) #define float64_zero make_float64(0) #define float64_one make_float64(0x3ff0000000000000LL) #define float64_ln2 make_float64(0x3fe62e42fefa39efLL) -#define float64_pi make_float64(0x400921fb54442d18LL) #define float64_half make_float64(0x3fe0000000000000LL) #define float64_infinity make_float64(0x7ff0000000000000LL) From patchwork Sun Feb 4 04:11:21 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Richard Henderson X-Patchwork-Id: 126797 Delivered-To: patch@linaro.org Received: by 10.46.124.24 with SMTP id x24csp924396ljc; Sat, 3 Feb 2018 20:15:00 -0800 (PST) X-Google-Smtp-Source: AH8x227FkfbliVTTZxvEY2WJ3D5BYwk8hpvnY/6GsdZ9F6oTP91/berjHXXTq6JBYTuwKiaHrktA X-Received: by 10.37.223.19 with SMTP id w19mr10477572ybg.214.1517717700579; Sat, 03 Feb 2018 20:15:00 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1517717700; cv=none; d=google.com; s=arc-20160816; b=ze5H2Yep4mTp9Pr5nCfbs5k4DpNz6zL16xmYVEeARzv1XV8blWELZL71LLMRpWXJ2O +oaelpjcjQOnKW42CIjOG/1LSgDVJkKz6Er4sQhx1uy5jyc569u+0i6YdP84vX0YWXBE CkTPq/duoOr45zIOvDsK/BqkiM5T/+foMgwwx3NNPyA8kPFrnnzUEktM5CMWe5ah65S/ us/GJJgJpmPw/z2THsoCAupmZGDCiquFX7Ad3drQp1a3DJW9Wro4d+wwgS8gzeJhr5zA nWExId+kABoUn6qGLt/PKOzou04BfO9OeeOcku7lvSw4IHuNIsQ+nUdgz3qWYX7JJ27h YYFA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=sender:errors-to:cc:list-subscribe:list-help:list-post:list-archive :list-unsubscribe:list-id:precedence:subject :content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:to:from:dkim-signature:arc-authentication-results; bh=LYBDYqhPqW1KJM/7G3vqGhglHsM3X7ZibH4HrpCwWvI=; b=LURF4Mga3YIeqpZayJY1zrOlVXCt753og7kWat3TJ5JjEqbhHaYAzfIXJ9JUzAkavS i4NhH33qzMPePxuduvXOa8Gf+/SMWABQxpZYI6uUUmg8QhdjruqSFQ24+7NOOYkcIXBR HtQzf0DOZUSo+zel4CuPnHWR3hWdBDQzWrsr7StLZJPNqgKYNZli8zmRrAACqd7DR2mg bM6CHE7uehfQSSZbbRXu+Csm0OUZBxZHq5AfemwsYVyFLHLYAeyBkJUwqRBqRZBY6JS4 yeibueyK1MkJdx4OCta62i4DybfDWFjraWGZUO2zjIU1kWVrRIf+8VbYp5MN1DrT1vzG KlJg== ARC-Authentication-Results: i=1; mx.google.com; dkim=fail header.i=@linaro.org header.s=google header.b=WL0VcCHL; spf=pass (google.com: domain of qemu-devel-bounces+patch=linaro.org@nongnu.org designates 2001:4830:134:3::11 as permitted sender) smtp.mailfrom=qemu-devel-bounces+patch=linaro.org@nongnu.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=linaro.org Return-Path: Received: from lists.gnu.org (lists.gnu.org. [2001:4830:134:3::11]) by mx.google.com with ESMTPS id d76si611504ywb.35.2018.02.03.20.15.00 for (version=TLS1 cipher=AES128-SHA bits=128/128); Sat, 03 Feb 2018 20:15:00 -0800 (PST) Received-SPF: pass (google.com: domain of qemu-devel-bounces+patch=linaro.org@nongnu.org designates 2001:4830:134:3::11 as permitted sender) client-ip=2001:4830:134:3::11; Authentication-Results: mx.google.com; dkim=fail header.i=@linaro.org header.s=google header.b=WL0VcCHL; spf=pass (google.com: domain of qemu-devel-bounces+patch=linaro.org@nongnu.org designates 2001:4830:134:3::11 as permitted sender) smtp.mailfrom=qemu-devel-bounces+patch=linaro.org@nongnu.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=linaro.org Received: from localhost ([::1]:58252 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1eiBhj-0007Dy-Vj for patch@linaro.org; Sat, 03 Feb 2018 23:15:00 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:47329) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1eiBen-0004fB-BB for qemu-devel@nongnu.org; Sat, 03 Feb 2018 23:11:58 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1eiBek-0004un-5I for qemu-devel@nongnu.org; Sat, 03 Feb 2018 23:11:57 -0500 Received: from mail-pg0-x244.google.com ([2607:f8b0:400e:c05::244]:37298) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1eiBej-0004u1-W5 for qemu-devel@nongnu.org; Sat, 03 Feb 2018 23:11:54 -0500 Received: by mail-pg0-x244.google.com with SMTP id o1so1773104pgn.4 for ; Sat, 03 Feb 2018 20:11:53 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=LYBDYqhPqW1KJM/7G3vqGhglHsM3X7ZibH4HrpCwWvI=; b=WL0VcCHLxg8TgnxxHs24VMx4hop87k1Wd/AAayaE92zQ7ZiXgYB1xu9bwhBkV7q4aD Brl2HuPXShRse4OY8ZMbCRfL8t2cQcE8w87IgiqRdbP9rmHfthcvVGuBghN4GVqJZntg 8qVYogu9929rVUJzPngSS/flJKHcNyL58j2I4= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=LYBDYqhPqW1KJM/7G3vqGhglHsM3X7ZibH4HrpCwWvI=; b=obfl/+YFe0hWYIarozgzYVc4UXQM0Wd7DHqBHZzYobZ9q3TA5yfqFpvLMEvc6i/tJH fnmed/mJ19rtcJjrctYlwafe7fK2fGybn24Y8QkBYMG9XIHxtoprikmmfrAU/U1Smf27 /yjjT9upQBgahPV8iNtRbYZdulwhXTmpqc1gZ9WqVVCJ26MI6LfJMi2M1/YD0jMYAT9s sByK16Enq5asY0wHiUVUx+mLvS8WVWTGQtNdJXUX0xxVJ35HFWOgrFD8NmSSI0tSyaJX ne3UyobZXYItpiGJ4VW7ACYbUnSIy/tKvAoGUPJVmMmM5cRmovwjmfI+IfFc+YofZ+2q h1dw== X-Gm-Message-State: AKwxyte6yUkhlSctr+fPTVVqY5NFGSUBKnN6Qd5htjYZj6ulptVNhEtq NLguM3QltAUNwJHZapg/Vy69HWD/eGM= X-Received: by 10.101.81.68 with SMTP id g4mr33920122pgq.276.1517717512755; Sat, 03 Feb 2018 20:11:52 -0800 (PST) Received: from cloudburst.twiddle.net (174-21-6-47.tukw.qwest.net. [174.21.6.47]) by smtp.gmail.com with ESMTPSA id k3sm1399425pgr.12.2018.02.03.20.11.51 (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Sat, 03 Feb 2018 20:11:51 -0800 (PST) From: Richard Henderson To: qemu-devel@nongnu.org Date: Sat, 3 Feb 2018 20:11:21 -0800 Message-Id: <20180204041136.17525-10-richard.henderson@linaro.org> X-Mailer: git-send-email 2.14.3 In-Reply-To: <20180204041136.17525-1-richard.henderson@linaro.org> References: <20180204041136.17525-1-richard.henderson@linaro.org> MIME-Version: 1.0 X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 2607:f8b0:400e:c05::244 Subject: [Qemu-devel] [PATCH 09/24] fpu/softfloat: improve comments on ARM NaN propagation X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: peter.maydell@linaro.org, cota@braap.org, alex.bennee@linaro.org, hsp.cat7@gmail.com Errors-To: qemu-devel-bounces+patch=linaro.org@nongnu.org Sender: "Qemu-devel" From: Alex Bennée Mention the pseudo-code fragment from which this is based. Signed-off-by: Alex Bennée Reviewed-by: Richard Henderson --- fpu/softfloat-specialize.h | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) -- 2.14.3 diff --git a/fpu/softfloat-specialize.h b/fpu/softfloat-specialize.h index de2c5d5702..4be0fb21ba 100644 --- a/fpu/softfloat-specialize.h +++ b/fpu/softfloat-specialize.h @@ -445,9 +445,10 @@ static float32 commonNaNToFloat32(commonNaNT a, float_status *status) #if defined(TARGET_ARM) static int pickNaN(flag aIsQNaN, flag aIsSNaN, flag bIsQNaN, flag bIsSNaN, - flag aIsLargerSignificand) + flag aIsLargerSignificand) { - /* ARM mandated NaN propagation rules: take the first of: + /* ARM mandated NaN propagation rules (see FPProcessNaNs()), take + * the first of: * 1. A if it is signaling * 2. B if it is signaling * 3. A (quiet) From patchwork Sun Feb 4 04:11:22 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Richard Henderson X-Patchwork-Id: 126815 Delivered-To: patch@linaro.org Received: by 10.80.172.228 with SMTP id x91csp1228598edc; Sat, 3 Feb 2018 20:27:46 -0800 (PST) X-Google-Smtp-Source: AH8x226qm4DYbUyOwl1cpc8Jv1f2VkHT/IimMxZIeG/C7oQhrM7BPeu9lpb12XHUrk/N3QTNs6p5 X-Received: by 10.37.130.69 with SMTP id d5mr29492313ybn.168.1517718465993; Sat, 03 Feb 2018 20:27:45 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1517718465; cv=none; d=google.com; s=arc-20160816; b=yEnM2QSQV7KmxrexcZ2w+V2K46AAAd3DMMxCywP1bgV6Cv8OJX5fxA14nyT4b28j13 wRndnNSh5kHfX9AS8nHsWWnDz0wajxHtcLtwCXm4SJPqlyKTpblzIokHe5BBwefSfO5L UcR6rdOnxy2n8zVjNrFZBrCLveolU4KsXe2pHd417RCljXH9GSAFN/txBUR6/gGx6XrE lencUh2i7TvVsphzlkmOF7Rvmfc7E0zKIrPxq8mU58jeGSepgunIDm6YyR6ULVN/VSkb 4IPWILvdV5XsnxzSGoPWP2OyYLPXhX5qB48IPOW/MHH/Xdvy10eZF/3dOMNvVU3tIkzP KJSg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=sender:errors-to:cc:list-subscribe:list-help:list-post:list-archive :list-unsubscribe:list-id:precedence:subject:references:in-reply-to :message-id:date:to:from:dkim-signature:arc-authentication-results; bh=mYbQHFaBUILvEl2q1vHzcnUMq9enuUjUj82qbmWmrW8=; b=u2QBjCI9h9cmqLvtQGgFrOxZZhBhdkw1vNAqoFMKnGRJaow8GK5PT4p2EaCWVZFM/C lE/k4o9wKoH0fKh0RNi8cGRtMCUyuGBLCjqRRxTXvR8I3WU0Ic2iaDfpKz8V1SaADkSb a+2X2BPLB+JYeHnYxuc6O+DGdcvamcFAYv6Vinc9lrz/ib+SLkjlX8A6A6xXbqsuDChW /FywJVApim303olqym/Vv4rMik8MeDSUC/VRCxTdb68I0D/0dX4wL25UclwtxXfTHDfs OvVy8LNtciagthZog2ksgvRGviJOmpgMkvy3YKzHPTpbbhYisSQyGxWFf78TvrlgU+g+ fyjA== ARC-Authentication-Results: i=1; mx.google.com; dkim=fail header.i=@linaro.org header.s=google header.b=YTBqdJtX; spf=pass (google.com: domain of qemu-devel-bounces+patch=linaro.org@nongnu.org designates 2001:4830:134:3::11 as permitted sender) smtp.mailfrom=qemu-devel-bounces+patch=linaro.org@nongnu.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=linaro.org Return-Path: Received: from lists.gnu.org (lists.gnu.org. [2001:4830:134:3::11]) by mx.google.com with ESMTPS id x16si1023149ybj.53.2018.02.03.20.27.45 for (version=TLS1 cipher=AES128-SHA bits=128/128); Sat, 03 Feb 2018 20:27:45 -0800 (PST) Received-SPF: pass (google.com: domain of qemu-devel-bounces+patch=linaro.org@nongnu.org designates 2001:4830:134:3::11 as permitted sender) client-ip=2001:4830:134:3::11; Authentication-Results: mx.google.com; dkim=fail header.i=@linaro.org header.s=google header.b=YTBqdJtX; spf=pass (google.com: domain of qemu-devel-bounces+patch=linaro.org@nongnu.org designates 2001:4830:134:3::11 as permitted sender) smtp.mailfrom=qemu-devel-bounces+patch=linaro.org@nongnu.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=linaro.org Received: from localhost ([::1]:58351 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1eiBu5-0001sC-38 for patch@linaro.org; Sat, 03 Feb 2018 23:27:45 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:47490) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1eiBf6-0004xe-92 for qemu-devel@nongnu.org; Sat, 03 Feb 2018 23:12:30 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1eiBeq-0004yp-TP for qemu-devel@nongnu.org; Sat, 03 Feb 2018 23:12:16 -0500 Received: from mail-pf0-x22c.google.com ([2607:f8b0:400e:c00::22c]:35513) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1eiBeq-0004yL-A2 for qemu-devel@nongnu.org; Sat, 03 Feb 2018 23:12:00 -0500 Received: by mail-pf0-x22c.google.com with SMTP id t12so19470059pfg.2 for ; Sat, 03 Feb 2018 20:12:00 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=mYbQHFaBUILvEl2q1vHzcnUMq9enuUjUj82qbmWmrW8=; b=YTBqdJtXAlzGcjOTjTftr82Snl6vMIczGBRgh48tbD14IjhNB3kLu92WX7+0bL3/lB 65TJRQmrL+M7vrSGM6lB9ioY39Jb/2kkBPkvg+1cIS2grz3IHJz1CqJWq3lY312iCYFJ OMiAfXShE3BOP4kmACBQwzctqi5T90Lr0yjwc= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=mYbQHFaBUILvEl2q1vHzcnUMq9enuUjUj82qbmWmrW8=; b=VCR2VZaNCOBzoMT0UGOiFlAYs64q7hchUpo0VZgurB/dLFbI5VfObjRGdYeWvYhCjv /Kw4IZOTElAp2ZkUIX+cGunu6lK5Vl2WLxj+gpuro98TryCtSen0kerQtt6VYtbXN7IS 1lVGuZs7prSFtMjjHnO5WNvTSwwKqkmbwOZQ/Itd8R45p7IQvRwpEhGjMPoBtAlsMBvX SF59lP9o/tI7doAmWBSiXyCEpZ2kJUF46dlgjEy0seZFg20gpAisUZ/belboRNmE5svT XEcVG+VI8y+DzccUA0k8BzvL7nH90CWcezOeNopdqbjIXJ11U5CR5yZviF/7svc4KI5X W3jg== X-Gm-Message-State: AKwxytdVRh7AdqMFQbnoepDmleK1gibxQlAS3wKSEsGMAynIOiG2mmXC QjZNGXGVU5dXFSn2qv4bjd8iw6sbiwQ= X-Received: by 10.99.169.26 with SMTP id u26mr34787444pge.270.1517717514702; Sat, 03 Feb 2018 20:11:54 -0800 (PST) Received: from cloudburst.twiddle.net (174-21-6-47.tukw.qwest.net. [174.21.6.47]) by smtp.gmail.com with ESMTPSA id k3sm1399425pgr.12.2018.02.03.20.11.52 (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Sat, 03 Feb 2018 20:11:53 -0800 (PST) From: Richard Henderson To: qemu-devel@nongnu.org Date: Sat, 3 Feb 2018 20:11:22 -0800 Message-Id: <20180204041136.17525-11-richard.henderson@linaro.org> X-Mailer: git-send-email 2.14.3 In-Reply-To: <20180204041136.17525-1-richard.henderson@linaro.org> References: <20180204041136.17525-1-richard.henderson@linaro.org> X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 2607:f8b0:400e:c00::22c Subject: [Qemu-devel] [PATCH 10/24] fpu/soft-fp: Import soft-fp from glibc X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: peter.maydell@linaro.org, cota@braap.org, alex.bennee@linaro.org, hsp.cat7@gmail.com Errors-To: qemu-devel-bounces+patch=linaro.org@nongnu.org Sender: "Qemu-devel" This has support for 16, 32, 64, and 128-bit floats. Upstream has some support for floatx80, but it is specific to Intel and has not been updated for Motorola differences. Signed-off-by: Richard Henderson --- fpu/double.h | 323 +++++++++ fpu/half.h | 170 +++++ fpu/op-1.h | 369 ++++++++++ fpu/op-2.h | 705 ++++++++++++++++++ fpu/op-4.h | 875 +++++++++++++++++++++++ fpu/op-8.h | 1 + fpu/op-common.h | 2134 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ fpu/quad.h | 330 +++++++++ fpu/single.h | 199 ++++++ fpu/soft-fp.h | 354 +++++++++ 10 files changed, 5460 insertions(+) create mode 100644 fpu/double.h create mode 100644 fpu/half.h create mode 100644 fpu/op-1.h create mode 100644 fpu/op-2.h create mode 100644 fpu/op-4.h create mode 100644 fpu/op-8.h create mode 100644 fpu/op-common.h create mode 100644 fpu/quad.h create mode 100644 fpu/single.h create mode 100644 fpu/soft-fp.h -- 2.14.3 diff --git a/fpu/double.h b/fpu/double.h new file mode 100644 index 0000000000..f6c83d7253 --- /dev/null +++ b/fpu/double.h @@ -0,0 +1,323 @@ +/* Software floating-point emulation. + Definitions for IEEE Double Precision + Copyright (C) 1997-2018 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Richard Henderson (rth@cygnus.com), + Jakub Jelinek (jj@ultra.linux.cz), + David S. Miller (davem@redhat.com) and + Peter Maydell (pmaydell@chiark.greenend.org.uk). + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + In addition to the permissions in the GNU Lesser General Public + License, the Free Software Foundation gives you unlimited + permission to link the compiled version of this file into + combinations with other programs, and to distribute those + combinations without any restriction coming from the use of this + file. (The Lesser General Public License restrictions do apply in + other respects; for example, they cover modification of the file, + and distribution when not linked into a combine executable.) + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + . */ + +#ifndef SOFT_FP_DOUBLE_H +#define SOFT_FP_DOUBLE_H 1 + +#if _FP_W_TYPE_SIZE < 32 +# error "Here's a nickel kid. Go buy yourself a real computer." +#endif + +#if _FP_W_TYPE_SIZE < 64 +# define _FP_FRACTBITS_D (2 * _FP_W_TYPE_SIZE) +# define _FP_FRACTBITS_DW_D (4 * _FP_W_TYPE_SIZE) +#else +# define _FP_FRACTBITS_D _FP_W_TYPE_SIZE +# define _FP_FRACTBITS_DW_D (2 * _FP_W_TYPE_SIZE) +#endif + +#define _FP_FRACBITS_D 53 +#define _FP_FRACXBITS_D (_FP_FRACTBITS_D - _FP_FRACBITS_D) +#define _FP_WFRACBITS_D (_FP_WORKBITS + _FP_FRACBITS_D) +#define _FP_WFRACXBITS_D (_FP_FRACTBITS_D - _FP_WFRACBITS_D) +#define _FP_EXPBITS_D 11 +#define _FP_EXPBIAS_D 1023 +#define _FP_EXPMAX_D 2047 + +#define _FP_QNANBIT_D \ + ((_FP_W_TYPE) 1 << (_FP_FRACBITS_D-2) % _FP_W_TYPE_SIZE) +#define _FP_QNANBIT_SH_D \ + ((_FP_W_TYPE) 1 << (_FP_FRACBITS_D-2+_FP_WORKBITS) % _FP_W_TYPE_SIZE) +#define _FP_IMPLBIT_D \ + ((_FP_W_TYPE) 1 << (_FP_FRACBITS_D-1) % _FP_W_TYPE_SIZE) +#define _FP_IMPLBIT_SH_D \ + ((_FP_W_TYPE) 1 << (_FP_FRACBITS_D-1+_FP_WORKBITS) % _FP_W_TYPE_SIZE) +#define _FP_OVERFLOW_D \ + ((_FP_W_TYPE) 1 << _FP_WFRACBITS_D % _FP_W_TYPE_SIZE) + +#define _FP_WFRACBITS_DW_D (2 * _FP_WFRACBITS_D) +#define _FP_WFRACXBITS_DW_D (_FP_FRACTBITS_DW_D - _FP_WFRACBITS_DW_D) +#define _FP_HIGHBIT_DW_D \ + ((_FP_W_TYPE) 1 << (_FP_WFRACBITS_DW_D - 1) % _FP_W_TYPE_SIZE) + +typedef float DFtype __attribute__ ((mode (DF))); + +#if _FP_W_TYPE_SIZE < 64 + +union _FP_UNION_D +{ + DFtype flt; + struct _FP_STRUCT_LAYOUT + { +# if __BYTE_ORDER == __BIG_ENDIAN + unsigned sign : 1; + unsigned exp : _FP_EXPBITS_D; + unsigned frac1 : _FP_FRACBITS_D - (_FP_IMPLBIT_D != 0) - _FP_W_TYPE_SIZE; + unsigned frac0 : _FP_W_TYPE_SIZE; +# else + unsigned frac0 : _FP_W_TYPE_SIZE; + unsigned frac1 : _FP_FRACBITS_D - (_FP_IMPLBIT_D != 0) - _FP_W_TYPE_SIZE; + unsigned exp : _FP_EXPBITS_D; + unsigned sign : 1; +# endif + } bits __attribute__ ((packed)); +}; + +# define FP_DECL_D(X) _FP_DECL (2, X) +# define FP_UNPACK_RAW_D(X, val) _FP_UNPACK_RAW_2 (D, X, (val)) +# define FP_UNPACK_RAW_DP(X, val) _FP_UNPACK_RAW_2_P (D, X, (val)) +# define FP_PACK_RAW_D(val, X) _FP_PACK_RAW_2 (D, (val), X) +# define FP_PACK_RAW_DP(val, X) \ + do \ + { \ + if (!FP_INHIBIT_RESULTS) \ + _FP_PACK_RAW_2_P (D, (val), X); \ + } \ + while (0) + +# define FP_UNPACK_D(X, val) \ + do \ + { \ + _FP_UNPACK_RAW_2 (D, X, (val)); \ + _FP_UNPACK_CANONICAL (D, 2, X); \ + } \ + while (0) + +# define FP_UNPACK_DP(X, val) \ + do \ + { \ + _FP_UNPACK_RAW_2_P (D, X, (val)); \ + _FP_UNPACK_CANONICAL (D, 2, X); \ + } \ + while (0) + +# define FP_UNPACK_SEMIRAW_D(X, val) \ + do \ + { \ + _FP_UNPACK_RAW_2 (D, X, (val)); \ + _FP_UNPACK_SEMIRAW (D, 2, X); \ + } \ + while (0) + +# define FP_UNPACK_SEMIRAW_DP(X, val) \ + do \ + { \ + _FP_UNPACK_RAW_2_P (D, X, (val)); \ + _FP_UNPACK_SEMIRAW (D, 2, X); \ + } \ + while (0) + +# define FP_PACK_D(val, X) \ + do \ + { \ + _FP_PACK_CANONICAL (D, 2, X); \ + _FP_PACK_RAW_2 (D, (val), X); \ + } \ + while (0) + +# define FP_PACK_DP(val, X) \ + do \ + { \ + _FP_PACK_CANONICAL (D, 2, X); \ + if (!FP_INHIBIT_RESULTS) \ + _FP_PACK_RAW_2_P (D, (val), X); \ + } \ + while (0) + +# define FP_PACK_SEMIRAW_D(val, X) \ + do \ + { \ + _FP_PACK_SEMIRAW (D, 2, X); \ + _FP_PACK_RAW_2 (D, (val), X); \ + } \ + while (0) + +# define FP_PACK_SEMIRAW_DP(val, X) \ + do \ + { \ + _FP_PACK_SEMIRAW (D, 2, X); \ + if (!FP_INHIBIT_RESULTS) \ + _FP_PACK_RAW_2_P (D, (val), X); \ + } \ + while (0) + +# define FP_ISSIGNAN_D(X) _FP_ISSIGNAN (D, 2, X) +# define FP_NEG_D(R, X) _FP_NEG (D, 2, R, X) +# define FP_ADD_D(R, X, Y) _FP_ADD (D, 2, R, X, Y) +# define FP_SUB_D(R, X, Y) _FP_SUB (D, 2, R, X, Y) +# define FP_MUL_D(R, X, Y) _FP_MUL (D, 2, R, X, Y) +# define FP_DIV_D(R, X, Y) _FP_DIV (D, 2, R, X, Y) +# define FP_SQRT_D(R, X) _FP_SQRT (D, 2, R, X) +# define _FP_SQRT_MEAT_D(R, S, T, X, Q) _FP_SQRT_MEAT_2 (R, S, T, X, (Q)) +# define FP_FMA_D(R, X, Y, Z) _FP_FMA (D, 2, 4, R, X, Y, Z) + +# define FP_CMP_D(r, X, Y, un, ex) _FP_CMP (D, 2, (r), X, Y, (un), (ex)) +# define FP_CMP_EQ_D(r, X, Y, ex) _FP_CMP_EQ (D, 2, (r), X, Y, (ex)) +# define FP_CMP_UNORD_D(r, X, Y, ex) _FP_CMP_UNORD (D, 2, (r), X, Y, (ex)) + +# define FP_TO_INT_D(r, X, rsz, rsg) _FP_TO_INT (D, 2, (r), X, (rsz), (rsg)) +# define FP_TO_INT_ROUND_D(r, X, rsz, rsg) \ + _FP_TO_INT_ROUND (D, 2, (r), X, (rsz), (rsg)) +# define FP_FROM_INT_D(X, r, rs, rt) _FP_FROM_INT (D, 2, X, (r), (rs), rt) + +# define _FP_FRAC_HIGH_D(X) _FP_FRAC_HIGH_2 (X) +# define _FP_FRAC_HIGH_RAW_D(X) _FP_FRAC_HIGH_2 (X) + +# define _FP_FRAC_HIGH_DW_D(X) _FP_FRAC_HIGH_4 (X) + +#else + +union _FP_UNION_D +{ + DFtype flt; + struct _FP_STRUCT_LAYOUT + { +# if __BYTE_ORDER == __BIG_ENDIAN + unsigned sign : 1; + unsigned exp : _FP_EXPBITS_D; + _FP_W_TYPE frac : _FP_FRACBITS_D - (_FP_IMPLBIT_D != 0); +# else + _FP_W_TYPE frac : _FP_FRACBITS_D - (_FP_IMPLBIT_D != 0); + unsigned exp : _FP_EXPBITS_D; + unsigned sign : 1; +# endif + } bits __attribute__ ((packed)); +}; + +# define FP_DECL_D(X) _FP_DECL (1, X) +# define FP_UNPACK_RAW_D(X, val) _FP_UNPACK_RAW_1 (D, X, (val)) +# define FP_UNPACK_RAW_DP(X, val) _FP_UNPACK_RAW_1_P (D, X, (val)) +# define FP_PACK_RAW_D(val, X) _FP_PACK_RAW_1 (D, (val), X) +# define FP_PACK_RAW_DP(val, X) \ + do \ + { \ + if (!FP_INHIBIT_RESULTS) \ + _FP_PACK_RAW_1_P (D, (val), X); \ + } \ + while (0) + +# define FP_UNPACK_D(X, val) \ + do \ + { \ + _FP_UNPACK_RAW_1 (D, X, (val)); \ + _FP_UNPACK_CANONICAL (D, 1, X); \ + } \ + while (0) + +# define FP_UNPACK_DP(X, val) \ + do \ + { \ + _FP_UNPACK_RAW_1_P (D, X, (val)); \ + _FP_UNPACK_CANONICAL (D, 1, X); \ + } \ + while (0) + +# define FP_UNPACK_SEMIRAW_D(X, val) \ + do \ + { \ + _FP_UNPACK_RAW_1 (D, X, (val)); \ + _FP_UNPACK_SEMIRAW (D, 1, X); \ + } \ + while (0) + +# define FP_UNPACK_SEMIRAW_DP(X, val) \ + do \ + { \ + _FP_UNPACK_RAW_1_P (D, X, (val)); \ + _FP_UNPACK_SEMIRAW (D, 1, X); \ + } \ + while (0) + +# define FP_PACK_D(val, X) \ + do \ + { \ + _FP_PACK_CANONICAL (D, 1, X); \ + _FP_PACK_RAW_1 (D, (val), X); \ + } \ + while (0) + +# define FP_PACK_DP(val, X) \ + do \ + { \ + _FP_PACK_CANONICAL (D, 1, X); \ + if (!FP_INHIBIT_RESULTS) \ + _FP_PACK_RAW_1_P (D, (val), X); \ + } \ + while (0) + +# define FP_PACK_SEMIRAW_D(val, X) \ + do \ + { \ + _FP_PACK_SEMIRAW (D, 1, X); \ + _FP_PACK_RAW_1 (D, (val), X); \ + } \ + while (0) + +# define FP_PACK_SEMIRAW_DP(val, X) \ + do \ + { \ + _FP_PACK_SEMIRAW (D, 1, X); \ + if (!FP_INHIBIT_RESULTS) \ + _FP_PACK_RAW_1_P (D, (val), X); \ + } \ + while (0) + +# define FP_ISSIGNAN_D(X) _FP_ISSIGNAN (D, 1, X) +# define FP_NEG_D(R, X) _FP_NEG (D, 1, R, X) +# define FP_ADD_D(R, X, Y) _FP_ADD (D, 1, R, X, Y) +# define FP_SUB_D(R, X, Y) _FP_SUB (D, 1, R, X, Y) +# define FP_MUL_D(R, X, Y) _FP_MUL (D, 1, R, X, Y) +# define FP_DIV_D(R, X, Y) _FP_DIV (D, 1, R, X, Y) +# define FP_SQRT_D(R, X) _FP_SQRT (D, 1, R, X) +# define _FP_SQRT_MEAT_D(R, S, T, X, Q) _FP_SQRT_MEAT_1 (R, S, T, X, (Q)) +# define FP_FMA_D(R, X, Y, Z) _FP_FMA (D, 1, 2, R, X, Y, Z) + +/* The implementation of _FP_MUL_D and _FP_DIV_D should be chosen by + the target machine. */ + +# define FP_CMP_D(r, X, Y, un, ex) _FP_CMP (D, 1, (r), X, Y, (un), (ex)) +# define FP_CMP_EQ_D(r, X, Y, ex) _FP_CMP_EQ (D, 1, (r), X, Y, (ex)) +# define FP_CMP_UNORD_D(r, X, Y, ex) _FP_CMP_UNORD (D, 1, (r), X, Y, (ex)) + +# define FP_TO_INT_D(r, X, rsz, rsg) _FP_TO_INT (D, 1, (r), X, (rsz), (rsg)) +# define FP_TO_INT_ROUND_D(r, X, rsz, rsg) \ + _FP_TO_INT_ROUND (D, 1, (r), X, (rsz), (rsg)) +# define FP_FROM_INT_D(X, r, rs, rt) _FP_FROM_INT (D, 1, X, (r), (rs), rt) + +# define _FP_FRAC_HIGH_D(X) _FP_FRAC_HIGH_1 (X) +# define _FP_FRAC_HIGH_RAW_D(X) _FP_FRAC_HIGH_1 (X) + +# define _FP_FRAC_HIGH_DW_D(X) _FP_FRAC_HIGH_2 (X) + +#endif /* W_TYPE_SIZE < 64 */ + +#endif /* !SOFT_FP_DOUBLE_H */ diff --git a/fpu/half.h b/fpu/half.h new file mode 100644 index 0000000000..ea28db6c18 --- /dev/null +++ b/fpu/half.h @@ -0,0 +1,170 @@ +/* Software floating-point emulation. + Definitions for IEEE Half Precision. + Copyright (C) 1997-2018 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + In addition to the permissions in the GNU Lesser General Public + License, the Free Software Foundation gives you unlimited + permission to link the compiled version of this file into + combinations with other programs, and to distribute those + combinations without any restriction coming from the use of this + file. (The Lesser General Public License restrictions do apply in + other respects; for example, they cover modification of the file, + and distribution when not linked into a combine executable.) + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + . */ + +#ifndef SOFT_FP_HALF_H +#define SOFT_FP_HALF_H 1 + +#if _FP_W_TYPE_SIZE < 32 +# error "Here's a nickel kid. Go buy yourself a real computer." +#endif + +#define _FP_FRACTBITS_H (_FP_W_TYPE_SIZE) + +#define _FP_FRACTBITS_DW_H (_FP_W_TYPE_SIZE) + +#define _FP_FRACBITS_H 11 +#define _FP_FRACXBITS_H (_FP_FRACTBITS_H - _FP_FRACBITS_H) +#define _FP_WFRACBITS_H (_FP_WORKBITS + _FP_FRACBITS_H) +#define _FP_WFRACXBITS_H (_FP_FRACTBITS_H - _FP_WFRACBITS_H) +#define _FP_EXPBITS_H 5 +#define _FP_EXPBIAS_H 15 +#define _FP_EXPMAX_H 31 + +#define _FP_QNANBIT_H ((_FP_W_TYPE) 1 << (_FP_FRACBITS_H-2)) +#define _FP_QNANBIT_SH_H ((_FP_W_TYPE) 1 << (_FP_FRACBITS_H-2+_FP_WORKBITS)) +#define _FP_IMPLBIT_H ((_FP_W_TYPE) 1 << (_FP_FRACBITS_H-1)) +#define _FP_IMPLBIT_SH_H ((_FP_W_TYPE) 1 << (_FP_FRACBITS_H-1+_FP_WORKBITS)) +#define _FP_OVERFLOW_H ((_FP_W_TYPE) 1 << (_FP_WFRACBITS_H)) + +#define _FP_WFRACBITS_DW_H (2 * _FP_WFRACBITS_H) +#define _FP_WFRACXBITS_DW_H (_FP_FRACTBITS_DW_H - _FP_WFRACBITS_DW_H) +#define _FP_HIGHBIT_DW_H \ + ((_FP_W_TYPE) 1 << (_FP_WFRACBITS_DW_H - 1) % _FP_W_TYPE_SIZE) + +/* The implementation of _FP_MUL_MEAT_H and _FP_DIV_MEAT_H should be + chosen by the target machine. */ + +typedef float HFtype __attribute__ ((mode (HF))); + +union _FP_UNION_H +{ + HFtype flt; + struct _FP_STRUCT_LAYOUT + { +#if __BYTE_ORDER == __BIG_ENDIAN + unsigned sign : 1; + unsigned exp : _FP_EXPBITS_H; + unsigned frac : _FP_FRACBITS_H - (_FP_IMPLBIT_H != 0); +#else + unsigned frac : _FP_FRACBITS_H - (_FP_IMPLBIT_H != 0); + unsigned exp : _FP_EXPBITS_H; + unsigned sign : 1; +#endif + } bits __attribute__ ((packed)); +}; + +#define FP_DECL_H(X) _FP_DECL (1, X) +#define FP_UNPACK_RAW_H(X, val) _FP_UNPACK_RAW_1 (H, X, (val)) +#define FP_UNPACK_RAW_HP(X, val) _FP_UNPACK_RAW_1_P (H, X, (val)) +#define FP_PACK_RAW_H(val, X) _FP_PACK_RAW_1 (H, (val), X) +#define FP_PACK_RAW_HP(val, X) \ + do \ + { \ + if (!FP_INHIBIT_RESULTS) \ + _FP_PACK_RAW_1_P (H, (val), X); \ + } \ + while (0) + +#define FP_UNPACK_H(X, val) \ + do \ + { \ + _FP_UNPACK_RAW_1 (H, X, (val)); \ + _FP_UNPACK_CANONICAL (H, 1, X); \ + } \ + while (0) + +#define FP_UNPACK_HP(X, val) \ + do \ + { \ + _FP_UNPACK_RAW_1_P (H, X, (val)); \ + _FP_UNPACK_CANONICAL (H, 1, X); \ + } \ + while (0) + +#define FP_UNPACK_SEMIRAW_H(X, val) \ + do \ + { \ + _FP_UNPACK_RAW_1 (H, X, (val)); \ + _FP_UNPACK_SEMIRAW (H, 1, X); \ + } \ + while (0) + +#define FP_UNPACK_SEMIRAW_HP(X, val) \ + do \ + { \ + _FP_UNPACK_RAW_1_P (H, X, (val)); \ + _FP_UNPACK_SEMIRAW (H, 1, X); \ + } \ + while (0) + +#define FP_PACK_H(val, X) \ + do \ + { \ + _FP_PACK_CANONICAL (H, 1, X); \ + _FP_PACK_RAW_1 (H, (val), X); \ + } \ + while (0) + +#define FP_PACK_HP(val, X) \ + do \ + { \ + _FP_PACK_CANONICAL (H, 1, X); \ + if (!FP_INHIBIT_RESULTS) \ + _FP_PACK_RAW_1_P (H, (val), X); \ + } \ + while (0) + +#define FP_PACK_SEMIRAW_H(val, X) \ + do \ + { \ + _FP_PACK_SEMIRAW (H, 1, X); \ + _FP_PACK_RAW_1 (H, (val), X); \ + } \ + while (0) + +#define FP_PACK_SEMIRAW_HP(val, X) \ + do \ + { \ + _FP_PACK_SEMIRAW (H, 1, X); \ + if (!FP_INHIBIT_RESULTS) \ + _FP_PACK_RAW_1_P (H, (val), X); \ + } \ + while (0) + +#define FP_TO_INT_H(r, X, rsz, rsg) _FP_TO_INT (H, 1, (r), X, (rsz), (rsg)) +#define FP_TO_INT_ROUND_H(r, X, rsz, rsg) \ + _FP_TO_INT_ROUND (H, 1, (r), X, (rsz), (rsg)) +#define FP_FROM_INT_H(X, r, rs, rt) _FP_FROM_INT (H, 1, X, (r), (rs), rt) + +/* HFmode arithmetic is not implemented. */ + +#define _FP_FRAC_HIGH_H(X) _FP_FRAC_HIGH_1 (X) +#define _FP_FRAC_HIGH_RAW_H(X) _FP_FRAC_HIGH_1 (X) +#define _FP_FRAC_HIGH_DW_H(X) _FP_FRAC_HIGH_1 (X) + +#endif /* !SOFT_FP_HALF_H */ diff --git a/fpu/op-1.h b/fpu/op-1.h new file mode 100644 index 0000000000..bafa7f46e6 --- /dev/null +++ b/fpu/op-1.h @@ -0,0 +1,369 @@ +/* Software floating-point emulation. + Basic one-word fraction declaration and manipulation. + Copyright (C) 1997-2018 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Richard Henderson (rth@cygnus.com), + Jakub Jelinek (jj@ultra.linux.cz), + David S. Miller (davem@redhat.com) and + Peter Maydell (pmaydell@chiark.greenend.org.uk). + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + In addition to the permissions in the GNU Lesser General Public + License, the Free Software Foundation gives you unlimited + permission to link the compiled version of this file into + combinations with other programs, and to distribute those + combinations without any restriction coming from the use of this + file. (The Lesser General Public License restrictions do apply in + other respects; for example, they cover modification of the file, + and distribution when not linked into a combine executable.) + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + . */ + +#ifndef SOFT_FP_OP_1_H +#define SOFT_FP_OP_1_H 1 + +#define _FP_FRAC_DECL_1(X) _FP_W_TYPE X##_f _FP_ZERO_INIT +#define _FP_FRAC_COPY_1(D, S) (D##_f = S##_f) +#define _FP_FRAC_SET_1(X, I) (X##_f = I) +#define _FP_FRAC_HIGH_1(X) (X##_f) +#define _FP_FRAC_LOW_1(X) (X##_f) +#define _FP_FRAC_WORD_1(X, w) (X##_f) + +#define _FP_FRAC_ADDI_1(X, I) (X##_f += I) +#define _FP_FRAC_SLL_1(X, N) \ + do \ + { \ + if (__builtin_constant_p (N) && (N) == 1) \ + X##_f += X##_f; \ + else \ + X##_f <<= (N); \ + } \ + while (0) +#define _FP_FRAC_SRL_1(X, N) (X##_f >>= N) + +/* Right shift with sticky-lsb. */ +#define _FP_FRAC_SRST_1(X, S, N, sz) __FP_FRAC_SRST_1 (X##_f, S, (N), (sz)) +#define _FP_FRAC_SRS_1(X, N, sz) __FP_FRAC_SRS_1 (X##_f, (N), (sz)) + +#define __FP_FRAC_SRST_1(X, S, N, sz) \ + do \ + { \ + S = (__builtin_constant_p (N) && (N) == 1 \ + ? X & 1 \ + : (X << (_FP_W_TYPE_SIZE - (N))) != 0); \ + X = X >> (N); \ + } \ + while (0) + +#define __FP_FRAC_SRS_1(X, N, sz) \ + (X = (X >> (N) | (__builtin_constant_p (N) && (N) == 1 \ + ? X & 1 \ + : (X << (_FP_W_TYPE_SIZE - (N))) != 0))) + +#define _FP_FRAC_ADD_1(R, X, Y) (R##_f = X##_f + Y##_f) +#define _FP_FRAC_SUB_1(R, X, Y) (R##_f = X##_f - Y##_f) +#define _FP_FRAC_DEC_1(X, Y) (X##_f -= Y##_f) +#define _FP_FRAC_CLZ_1(z, X) __FP_CLZ ((z), X##_f) + +/* Predicates. */ +#define _FP_FRAC_NEGP_1(X) ((_FP_WS_TYPE) X##_f < 0) +#define _FP_FRAC_ZEROP_1(X) (X##_f == 0) +#define _FP_FRAC_OVERP_1(fs, X) (X##_f & _FP_OVERFLOW_##fs) +#define _FP_FRAC_CLEAR_OVERP_1(fs, X) (X##_f &= ~_FP_OVERFLOW_##fs) +#define _FP_FRAC_HIGHBIT_DW_1(fs, X) (X##_f & _FP_HIGHBIT_DW_##fs) +#define _FP_FRAC_EQ_1(X, Y) (X##_f == Y##_f) +#define _FP_FRAC_GE_1(X, Y) (X##_f >= Y##_f) +#define _FP_FRAC_GT_1(X, Y) (X##_f > Y##_f) + +#define _FP_ZEROFRAC_1 0 +#define _FP_MINFRAC_1 1 +#define _FP_MAXFRAC_1 (~(_FP_WS_TYPE) 0) + +/* Unpack the raw bits of a native fp value. Do not classify or + normalize the data. */ + +#define _FP_UNPACK_RAW_1(fs, X, val) \ + do \ + { \ + union _FP_UNION_##fs _FP_UNPACK_RAW_1_flo; \ + _FP_UNPACK_RAW_1_flo.flt = (val); \ + \ + X##_f = _FP_UNPACK_RAW_1_flo.bits.frac; \ + X##_e = _FP_UNPACK_RAW_1_flo.bits.exp; \ + X##_s = _FP_UNPACK_RAW_1_flo.bits.sign; \ + } \ + while (0) + +#define _FP_UNPACK_RAW_1_P(fs, X, val) \ + do \ + { \ + union _FP_UNION_##fs *_FP_UNPACK_RAW_1_P_flo \ + = (union _FP_UNION_##fs *) (val); \ + \ + X##_f = _FP_UNPACK_RAW_1_P_flo->bits.frac; \ + X##_e = _FP_UNPACK_RAW_1_P_flo->bits.exp; \ + X##_s = _FP_UNPACK_RAW_1_P_flo->bits.sign; \ + } \ + while (0) + +/* Repack the raw bits of a native fp value. */ + +#define _FP_PACK_RAW_1(fs, val, X) \ + do \ + { \ + union _FP_UNION_##fs _FP_PACK_RAW_1_flo; \ + \ + _FP_PACK_RAW_1_flo.bits.frac = X##_f; \ + _FP_PACK_RAW_1_flo.bits.exp = X##_e; \ + _FP_PACK_RAW_1_flo.bits.sign = X##_s; \ + \ + (val) = _FP_PACK_RAW_1_flo.flt; \ + } \ + while (0) + +#define _FP_PACK_RAW_1_P(fs, val, X) \ + do \ + { \ + union _FP_UNION_##fs *_FP_PACK_RAW_1_P_flo \ + = (union _FP_UNION_##fs *) (val); \ + \ + _FP_PACK_RAW_1_P_flo->bits.frac = X##_f; \ + _FP_PACK_RAW_1_P_flo->bits.exp = X##_e; \ + _FP_PACK_RAW_1_P_flo->bits.sign = X##_s; \ + } \ + while (0) + + +/* Multiplication algorithms: */ + +/* Basic. Assuming the host word size is >= 2*FRACBITS, we can do the + multiplication immediately. */ + +#define _FP_MUL_MEAT_DW_1_imm(wfracbits, R, X, Y) \ + do \ + { \ + R##_f = X##_f * Y##_f; \ + } \ + while (0) + +#define _FP_MUL_MEAT_1_imm(wfracbits, R, X, Y) \ + do \ + { \ + _FP_MUL_MEAT_DW_1_imm ((wfracbits), R, X, Y); \ + /* Normalize since we know where the msb of the multiplicands \ + were (bit B), we know that the msb of the of the product is \ + at either 2B or 2B-1. */ \ + _FP_FRAC_SRS_1 (R, (wfracbits)-1, 2*(wfracbits)); \ + } \ + while (0) + +/* Given a 1W * 1W => 2W primitive, do the extended multiplication. */ + +#define _FP_MUL_MEAT_DW_1_wide(wfracbits, R, X, Y, doit) \ + do \ + { \ + doit (R##_f1, R##_f0, X##_f, Y##_f); \ + } \ + while (0) + +#define _FP_MUL_MEAT_1_wide(wfracbits, R, X, Y, doit) \ + do \ + { \ + _FP_FRAC_DECL_2 (_FP_MUL_MEAT_1_wide_Z); \ + _FP_MUL_MEAT_DW_1_wide ((wfracbits), _FP_MUL_MEAT_1_wide_Z, \ + X, Y, doit); \ + /* Normalize since we know where the msb of the multiplicands \ + were (bit B), we know that the msb of the of the product is \ + at either 2B or 2B-1. */ \ + _FP_FRAC_SRS_2 (_FP_MUL_MEAT_1_wide_Z, (wfracbits)-1, \ + 2*(wfracbits)); \ + R##_f = _FP_MUL_MEAT_1_wide_Z_f0; \ + } \ + while (0) + +/* Finally, a simple widening multiply algorithm. What fun! */ + +#define _FP_MUL_MEAT_DW_1_hard(wfracbits, R, X, Y) \ + do \ + { \ + _FP_W_TYPE _FP_MUL_MEAT_DW_1_hard_xh, _FP_MUL_MEAT_DW_1_hard_xl; \ + _FP_W_TYPE _FP_MUL_MEAT_DW_1_hard_yh, _FP_MUL_MEAT_DW_1_hard_yl; \ + _FP_FRAC_DECL_2 (_FP_MUL_MEAT_DW_1_hard_a); \ + \ + /* Split the words in half. */ \ + _FP_MUL_MEAT_DW_1_hard_xh = X##_f >> (_FP_W_TYPE_SIZE/2); \ + _FP_MUL_MEAT_DW_1_hard_xl \ + = X##_f & (((_FP_W_TYPE) 1 << (_FP_W_TYPE_SIZE/2)) - 1); \ + _FP_MUL_MEAT_DW_1_hard_yh = Y##_f >> (_FP_W_TYPE_SIZE/2); \ + _FP_MUL_MEAT_DW_1_hard_yl \ + = Y##_f & (((_FP_W_TYPE) 1 << (_FP_W_TYPE_SIZE/2)) - 1); \ + \ + /* Multiply the pieces. */ \ + R##_f0 = _FP_MUL_MEAT_DW_1_hard_xl * _FP_MUL_MEAT_DW_1_hard_yl; \ + _FP_MUL_MEAT_DW_1_hard_a_f0 \ + = _FP_MUL_MEAT_DW_1_hard_xh * _FP_MUL_MEAT_DW_1_hard_yl; \ + _FP_MUL_MEAT_DW_1_hard_a_f1 \ + = _FP_MUL_MEAT_DW_1_hard_xl * _FP_MUL_MEAT_DW_1_hard_yh; \ + R##_f1 = _FP_MUL_MEAT_DW_1_hard_xh * _FP_MUL_MEAT_DW_1_hard_yh; \ + \ + /* Reassemble into two full words. */ \ + if ((_FP_MUL_MEAT_DW_1_hard_a_f0 += _FP_MUL_MEAT_DW_1_hard_a_f1) \ + < _FP_MUL_MEAT_DW_1_hard_a_f1) \ + R##_f1 += (_FP_W_TYPE) 1 << (_FP_W_TYPE_SIZE/2); \ + _FP_MUL_MEAT_DW_1_hard_a_f1 \ + = _FP_MUL_MEAT_DW_1_hard_a_f0 >> (_FP_W_TYPE_SIZE/2); \ + _FP_MUL_MEAT_DW_1_hard_a_f0 \ + = _FP_MUL_MEAT_DW_1_hard_a_f0 << (_FP_W_TYPE_SIZE/2); \ + _FP_FRAC_ADD_2 (R, R, _FP_MUL_MEAT_DW_1_hard_a); \ + } \ + while (0) + +#define _FP_MUL_MEAT_1_hard(wfracbits, R, X, Y) \ + do \ + { \ + _FP_FRAC_DECL_2 (_FP_MUL_MEAT_1_hard_z); \ + _FP_MUL_MEAT_DW_1_hard ((wfracbits), \ + _FP_MUL_MEAT_1_hard_z, X, Y); \ + \ + /* Normalize. */ \ + _FP_FRAC_SRS_2 (_FP_MUL_MEAT_1_hard_z, \ + (wfracbits) - 1, 2*(wfracbits)); \ + R##_f = _FP_MUL_MEAT_1_hard_z_f0; \ + } \ + while (0) + + +/* Division algorithms: */ + +/* Basic. Assuming the host word size is >= 2*FRACBITS, we can do the + division immediately. Give this macro either _FP_DIV_HELP_imm for + C primitives or _FP_DIV_HELP_ldiv for the ISO function. Which you + choose will depend on what the compiler does with divrem4. */ + +#define _FP_DIV_MEAT_1_imm(fs, R, X, Y, doit) \ + do \ + { \ + _FP_W_TYPE _FP_DIV_MEAT_1_imm_q, _FP_DIV_MEAT_1_imm_r; \ + X##_f <<= (X##_f < Y##_f \ + ? R##_e--, _FP_WFRACBITS_##fs \ + : _FP_WFRACBITS_##fs - 1); \ + doit (_FP_DIV_MEAT_1_imm_q, _FP_DIV_MEAT_1_imm_r, X##_f, Y##_f); \ + R##_f = _FP_DIV_MEAT_1_imm_q | (_FP_DIV_MEAT_1_imm_r != 0); \ + } \ + while (0) + +/* GCC's longlong.h defines a 2W / 1W => (1W,1W) primitive udiv_qrnnd + that may be useful in this situation. This first is for a primitive + that requires normalization, the second for one that does not. Look + for UDIV_NEEDS_NORMALIZATION to tell which your machine needs. */ + +#define _FP_DIV_MEAT_1_udiv_norm(fs, R, X, Y) \ + do \ + { \ + _FP_W_TYPE _FP_DIV_MEAT_1_udiv_norm_nh; \ + _FP_W_TYPE _FP_DIV_MEAT_1_udiv_norm_nl; \ + _FP_W_TYPE _FP_DIV_MEAT_1_udiv_norm_q; \ + _FP_W_TYPE _FP_DIV_MEAT_1_udiv_norm_r; \ + _FP_W_TYPE _FP_DIV_MEAT_1_udiv_norm_y; \ + \ + /* Normalize Y -- i.e. make the most significant bit set. */ \ + _FP_DIV_MEAT_1_udiv_norm_y = Y##_f << _FP_WFRACXBITS_##fs; \ + \ + /* Shift X op correspondingly high, that is, up one full word. */ \ + if (X##_f < Y##_f) \ + { \ + R##_e--; \ + _FP_DIV_MEAT_1_udiv_norm_nl = 0; \ + _FP_DIV_MEAT_1_udiv_norm_nh = X##_f; \ + } \ + else \ + { \ + _FP_DIV_MEAT_1_udiv_norm_nl = X##_f << (_FP_W_TYPE_SIZE - 1); \ + _FP_DIV_MEAT_1_udiv_norm_nh = X##_f >> 1; \ + } \ + \ + udiv_qrnnd (_FP_DIV_MEAT_1_udiv_norm_q, \ + _FP_DIV_MEAT_1_udiv_norm_r, \ + _FP_DIV_MEAT_1_udiv_norm_nh, \ + _FP_DIV_MEAT_1_udiv_norm_nl, \ + _FP_DIV_MEAT_1_udiv_norm_y); \ + R##_f = (_FP_DIV_MEAT_1_udiv_norm_q \ + | (_FP_DIV_MEAT_1_udiv_norm_r != 0)); \ + } \ + while (0) + +#define _FP_DIV_MEAT_1_udiv(fs, R, X, Y) \ + do \ + { \ + _FP_W_TYPE _FP_DIV_MEAT_1_udiv_nh, _FP_DIV_MEAT_1_udiv_nl; \ + _FP_W_TYPE _FP_DIV_MEAT_1_udiv_q, _FP_DIV_MEAT_1_udiv_r; \ + if (X##_f < Y##_f) \ + { \ + R##_e--; \ + _FP_DIV_MEAT_1_udiv_nl = X##_f << _FP_WFRACBITS_##fs; \ + _FP_DIV_MEAT_1_udiv_nh = X##_f >> _FP_WFRACXBITS_##fs; \ + } \ + else \ + { \ + _FP_DIV_MEAT_1_udiv_nl = X##_f << (_FP_WFRACBITS_##fs - 1); \ + _FP_DIV_MEAT_1_udiv_nh = X##_f >> (_FP_WFRACXBITS_##fs + 1); \ + } \ + udiv_qrnnd (_FP_DIV_MEAT_1_udiv_q, _FP_DIV_MEAT_1_udiv_r, \ + _FP_DIV_MEAT_1_udiv_nh, _FP_DIV_MEAT_1_udiv_nl, \ + Y##_f); \ + R##_f = _FP_DIV_MEAT_1_udiv_q | (_FP_DIV_MEAT_1_udiv_r != 0); \ + } \ + while (0) + + +/* Square root algorithms: + We have just one right now, maybe Newton approximation + should be added for those machines where division is fast. */ + +#define _FP_SQRT_MEAT_1(R, S, T, X, q) \ + do \ + { \ + while ((q) != _FP_WORK_ROUND) \ + { \ + T##_f = S##_f + (q); \ + if (T##_f <= X##_f) \ + { \ + S##_f = T##_f + (q); \ + X##_f -= T##_f; \ + R##_f += (q); \ + } \ + _FP_FRAC_SLL_1 (X, 1); \ + (q) >>= 1; \ + } \ + if (X##_f) \ + { \ + if (S##_f < X##_f) \ + R##_f |= _FP_WORK_ROUND; \ + R##_f |= _FP_WORK_STICKY; \ + } \ + } \ + while (0) + +/* Assembly/disassembly for converting to/from integral types. + No shifting or overflow handled here. */ + +#define _FP_FRAC_ASSEMBLE_1(r, X, rsize) ((r) = X##_f) +#define _FP_FRAC_DISASSEMBLE_1(X, r, rsize) (X##_f = (r)) + + +/* Convert FP values between word sizes. */ + +#define _FP_FRAC_COPY_1_1(D, S) (D##_f = S##_f) + +#endif /* !SOFT_FP_OP_1_H */ diff --git a/fpu/op-2.h b/fpu/op-2.h new file mode 100644 index 0000000000..6020d663d4 --- /dev/null +++ b/fpu/op-2.h @@ -0,0 +1,705 @@ +/* Software floating-point emulation. + Basic two-word fraction declaration and manipulation. + Copyright (C) 1997-2018 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Richard Henderson (rth@cygnus.com), + Jakub Jelinek (jj@ultra.linux.cz), + David S. Miller (davem@redhat.com) and + Peter Maydell (pmaydell@chiark.greenend.org.uk). + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + In addition to the permissions in the GNU Lesser General Public + License, the Free Software Foundation gives you unlimited + permission to link the compiled version of this file into + combinations with other programs, and to distribute those + combinations without any restriction coming from the use of this + file. (The Lesser General Public License restrictions do apply in + other respects; for example, they cover modification of the file, + and distribution when not linked into a combine executable.) + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + . */ + +#ifndef SOFT_FP_OP_2_H +#define SOFT_FP_OP_2_H 1 + +#define _FP_FRAC_DECL_2(X) \ + _FP_W_TYPE X##_f0 _FP_ZERO_INIT, X##_f1 _FP_ZERO_INIT +#define _FP_FRAC_COPY_2(D, S) (D##_f0 = S##_f0, D##_f1 = S##_f1) +#define _FP_FRAC_SET_2(X, I) __FP_FRAC_SET_2 (X, I) +#define _FP_FRAC_HIGH_2(X) (X##_f1) +#define _FP_FRAC_LOW_2(X) (X##_f0) +#define _FP_FRAC_WORD_2(X, w) (X##_f##w) + +#define _FP_FRAC_SLL_2(X, N) \ + (void) (((N) < _FP_W_TYPE_SIZE) \ + ? ({ \ + if (__builtin_constant_p (N) && (N) == 1) \ + { \ + X##_f1 = X##_f1 + X##_f1 + (((_FP_WS_TYPE) (X##_f0)) < 0); \ + X##_f0 += X##_f0; \ + } \ + else \ + { \ + X##_f1 = X##_f1 << (N) | X##_f0 >> (_FP_W_TYPE_SIZE - (N)); \ + X##_f0 <<= (N); \ + } \ + 0; \ + }) \ + : ({ \ + X##_f1 = X##_f0 << ((N) - _FP_W_TYPE_SIZE); \ + X##_f0 = 0; \ + })) + + +#define _FP_FRAC_SRL_2(X, N) \ + (void) (((N) < _FP_W_TYPE_SIZE) \ + ? ({ \ + X##_f0 = X##_f0 >> (N) | X##_f1 << (_FP_W_TYPE_SIZE - (N)); \ + X##_f1 >>= (N); \ + }) \ + : ({ \ + X##_f0 = X##_f1 >> ((N) - _FP_W_TYPE_SIZE); \ + X##_f1 = 0; \ + })) + +/* Right shift with sticky-lsb. */ +#define _FP_FRAC_SRST_2(X, S, N, sz) \ + (void) (((N) < _FP_W_TYPE_SIZE) \ + ? ({ \ + S = (__builtin_constant_p (N) && (N) == 1 \ + ? X##_f0 & 1 \ + : (X##_f0 << (_FP_W_TYPE_SIZE - (N))) != 0); \ + X##_f0 = (X##_f1 << (_FP_W_TYPE_SIZE - (N)) | X##_f0 >> (N)); \ + X##_f1 >>= (N); \ + }) \ + : ({ \ + S = ((((N) == _FP_W_TYPE_SIZE \ + ? 0 \ + : (X##_f1 << (2*_FP_W_TYPE_SIZE - (N)))) \ + | X##_f0) != 0); \ + X##_f0 = (X##_f1 >> ((N) - _FP_W_TYPE_SIZE)); \ + X##_f1 = 0; \ + })) + +#define _FP_FRAC_SRS_2(X, N, sz) \ + (void) (((N) < _FP_W_TYPE_SIZE) \ + ? ({ \ + X##_f0 = (X##_f1 << (_FP_W_TYPE_SIZE - (N)) | X##_f0 >> (N) \ + | (__builtin_constant_p (N) && (N) == 1 \ + ? X##_f0 & 1 \ + : (X##_f0 << (_FP_W_TYPE_SIZE - (N))) != 0)); \ + X##_f1 >>= (N); \ + }) \ + : ({ \ + X##_f0 = (X##_f1 >> ((N) - _FP_W_TYPE_SIZE) \ + | ((((N) == _FP_W_TYPE_SIZE \ + ? 0 \ + : (X##_f1 << (2*_FP_W_TYPE_SIZE - (N)))) \ + | X##_f0) != 0)); \ + X##_f1 = 0; \ + })) + +#define _FP_FRAC_ADDI_2(X, I) \ + __FP_FRAC_ADDI_2 (X##_f1, X##_f0, I) + +#define _FP_FRAC_ADD_2(R, X, Y) \ + __FP_FRAC_ADD_2 (R##_f1, R##_f0, X##_f1, X##_f0, Y##_f1, Y##_f0) + +#define _FP_FRAC_SUB_2(R, X, Y) \ + __FP_FRAC_SUB_2 (R##_f1, R##_f0, X##_f1, X##_f0, Y##_f1, Y##_f0) + +#define _FP_FRAC_DEC_2(X, Y) \ + __FP_FRAC_DEC_2 (X##_f1, X##_f0, Y##_f1, Y##_f0) + +#define _FP_FRAC_CLZ_2(R, X) \ + do \ + { \ + if (X##_f1) \ + __FP_CLZ ((R), X##_f1); \ + else \ + { \ + __FP_CLZ ((R), X##_f0); \ + (R) += _FP_W_TYPE_SIZE; \ + } \ + } \ + while (0) + +/* Predicates. */ +#define _FP_FRAC_NEGP_2(X) ((_FP_WS_TYPE) X##_f1 < 0) +#define _FP_FRAC_ZEROP_2(X) ((X##_f1 | X##_f0) == 0) +#define _FP_FRAC_OVERP_2(fs, X) (_FP_FRAC_HIGH_##fs (X) & _FP_OVERFLOW_##fs) +#define _FP_FRAC_CLEAR_OVERP_2(fs, X) (_FP_FRAC_HIGH_##fs (X) &= ~_FP_OVERFLOW_##fs) +#define _FP_FRAC_HIGHBIT_DW_2(fs, X) \ + (_FP_FRAC_HIGH_DW_##fs (X) & _FP_HIGHBIT_DW_##fs) +#define _FP_FRAC_EQ_2(X, Y) (X##_f1 == Y##_f1 && X##_f0 == Y##_f0) +#define _FP_FRAC_GT_2(X, Y) \ + (X##_f1 > Y##_f1 || (X##_f1 == Y##_f1 && X##_f0 > Y##_f0)) +#define _FP_FRAC_GE_2(X, Y) \ + (X##_f1 > Y##_f1 || (X##_f1 == Y##_f1 && X##_f0 >= Y##_f0)) + +#define _FP_ZEROFRAC_2 0, 0 +#define _FP_MINFRAC_2 0, 1 +#define _FP_MAXFRAC_2 (~(_FP_WS_TYPE) 0), (~(_FP_WS_TYPE) 0) + +/* Internals. */ + +#define __FP_FRAC_SET_2(X, I1, I0) (X##_f0 = I0, X##_f1 = I1) + +#define __FP_CLZ_2(R, xh, xl) \ + do \ + { \ + if (xh) \ + __FP_CLZ ((R), xh); \ + else \ + { \ + __FP_CLZ ((R), xl); \ + (R) += _FP_W_TYPE_SIZE; \ + } \ + } \ + while (0) + +#if 0 + +# ifndef __FP_FRAC_ADDI_2 +# define __FP_FRAC_ADDI_2(xh, xl, i) \ + (xh += ((xl += i) < i)) +# endif +# ifndef __FP_FRAC_ADD_2 +# define __FP_FRAC_ADD_2(rh, rl, xh, xl, yh, yl) \ + (rh = xh + yh + ((rl = xl + yl) < xl)) +# endif +# ifndef __FP_FRAC_SUB_2 +# define __FP_FRAC_SUB_2(rh, rl, xh, xl, yh, yl) \ + (rh = xh - yh - ((rl = xl - yl) > xl)) +# endif +# ifndef __FP_FRAC_DEC_2 +# define __FP_FRAC_DEC_2(xh, xl, yh, yl) \ + do \ + { \ + UWtype __FP_FRAC_DEC_2_t = xl; \ + xh -= yh + ((xl -= yl) > __FP_FRAC_DEC_2_t); \ + } \ + while (0) +# endif + +#else + +# undef __FP_FRAC_ADDI_2 +# define __FP_FRAC_ADDI_2(xh, xl, i) add_ssaaaa (xh, xl, xh, xl, 0, i) +# undef __FP_FRAC_ADD_2 +# define __FP_FRAC_ADD_2 add_ssaaaa +# undef __FP_FRAC_SUB_2 +# define __FP_FRAC_SUB_2 sub_ddmmss +# undef __FP_FRAC_DEC_2 +# define __FP_FRAC_DEC_2(xh, xl, yh, yl) \ + sub_ddmmss (xh, xl, xh, xl, yh, yl) + +#endif + +/* Unpack the raw bits of a native fp value. Do not classify or + normalize the data. */ + +#define _FP_UNPACK_RAW_2(fs, X, val) \ + do \ + { \ + union _FP_UNION_##fs _FP_UNPACK_RAW_2_flo; \ + _FP_UNPACK_RAW_2_flo.flt = (val); \ + \ + X##_f0 = _FP_UNPACK_RAW_2_flo.bits.frac0; \ + X##_f1 = _FP_UNPACK_RAW_2_flo.bits.frac1; \ + X##_e = _FP_UNPACK_RAW_2_flo.bits.exp; \ + X##_s = _FP_UNPACK_RAW_2_flo.bits.sign; \ + } \ + while (0) + +#define _FP_UNPACK_RAW_2_P(fs, X, val) \ + do \ + { \ + union _FP_UNION_##fs *_FP_UNPACK_RAW_2_P_flo \ + = (union _FP_UNION_##fs *) (val); \ + \ + X##_f0 = _FP_UNPACK_RAW_2_P_flo->bits.frac0; \ + X##_f1 = _FP_UNPACK_RAW_2_P_flo->bits.frac1; \ + X##_e = _FP_UNPACK_RAW_2_P_flo->bits.exp; \ + X##_s = _FP_UNPACK_RAW_2_P_flo->bits.sign; \ + } \ + while (0) + + +/* Repack the raw bits of a native fp value. */ + +#define _FP_PACK_RAW_2(fs, val, X) \ + do \ + { \ + union _FP_UNION_##fs _FP_PACK_RAW_2_flo; \ + \ + _FP_PACK_RAW_2_flo.bits.frac0 = X##_f0; \ + _FP_PACK_RAW_2_flo.bits.frac1 = X##_f1; \ + _FP_PACK_RAW_2_flo.bits.exp = X##_e; \ + _FP_PACK_RAW_2_flo.bits.sign = X##_s; \ + \ + (val) = _FP_PACK_RAW_2_flo.flt; \ + } \ + while (0) + +#define _FP_PACK_RAW_2_P(fs, val, X) \ + do \ + { \ + union _FP_UNION_##fs *_FP_PACK_RAW_2_P_flo \ + = (union _FP_UNION_##fs *) (val); \ + \ + _FP_PACK_RAW_2_P_flo->bits.frac0 = X##_f0; \ + _FP_PACK_RAW_2_P_flo->bits.frac1 = X##_f1; \ + _FP_PACK_RAW_2_P_flo->bits.exp = X##_e; \ + _FP_PACK_RAW_2_P_flo->bits.sign = X##_s; \ + } \ + while (0) + + +/* Multiplication algorithms: */ + +/* Given a 1W * 1W => 2W primitive, do the extended multiplication. */ + +#define _FP_MUL_MEAT_DW_2_wide(wfracbits, R, X, Y, doit) \ + do \ + { \ + _FP_FRAC_DECL_2 (_FP_MUL_MEAT_DW_2_wide_b); \ + _FP_FRAC_DECL_2 (_FP_MUL_MEAT_DW_2_wide_c); \ + \ + doit (_FP_FRAC_WORD_4 (R, 1), _FP_FRAC_WORD_4 (R, 0), \ + X##_f0, Y##_f0); \ + doit (_FP_MUL_MEAT_DW_2_wide_b_f1, _FP_MUL_MEAT_DW_2_wide_b_f0, \ + X##_f0, Y##_f1); \ + doit (_FP_MUL_MEAT_DW_2_wide_c_f1, _FP_MUL_MEAT_DW_2_wide_c_f0, \ + X##_f1, Y##_f0); \ + doit (_FP_FRAC_WORD_4 (R, 3), _FP_FRAC_WORD_4 (R, 2), \ + X##_f1, Y##_f1); \ + \ + __FP_FRAC_ADD_3 (_FP_FRAC_WORD_4 (R, 3), _FP_FRAC_WORD_4 (R, 2), \ + _FP_FRAC_WORD_4 (R, 1), 0, \ + _FP_MUL_MEAT_DW_2_wide_b_f1, \ + _FP_MUL_MEAT_DW_2_wide_b_f0, \ + _FP_FRAC_WORD_4 (R, 3), _FP_FRAC_WORD_4 (R, 2), \ + _FP_FRAC_WORD_4 (R, 1)); \ + __FP_FRAC_ADD_3 (_FP_FRAC_WORD_4 (R, 3), _FP_FRAC_WORD_4 (R, 2), \ + _FP_FRAC_WORD_4 (R, 1), 0, \ + _FP_MUL_MEAT_DW_2_wide_c_f1, \ + _FP_MUL_MEAT_DW_2_wide_c_f0, \ + _FP_FRAC_WORD_4 (R, 3), _FP_FRAC_WORD_4 (R, 2), \ + _FP_FRAC_WORD_4 (R, 1)); \ + } \ + while (0) + +#define _FP_MUL_MEAT_2_wide(wfracbits, R, X, Y, doit) \ + do \ + { \ + _FP_FRAC_DECL_4 (_FP_MUL_MEAT_2_wide_z); \ + \ + _FP_MUL_MEAT_DW_2_wide ((wfracbits), _FP_MUL_MEAT_2_wide_z, \ + X, Y, doit); \ + \ + /* Normalize since we know where the msb of the multiplicands \ + were (bit B), we know that the msb of the of the product is \ + at either 2B or 2B-1. */ \ + _FP_FRAC_SRS_4 (_FP_MUL_MEAT_2_wide_z, (wfracbits)-1, \ + 2*(wfracbits)); \ + R##_f0 = _FP_FRAC_WORD_4 (_FP_MUL_MEAT_2_wide_z, 0); \ + R##_f1 = _FP_FRAC_WORD_4 (_FP_MUL_MEAT_2_wide_z, 1); \ + } \ + while (0) + +/* Given a 1W * 1W => 2W primitive, do the extended multiplication. + Do only 3 multiplications instead of four. This one is for machines + where multiplication is much more expensive than subtraction. */ + +#define _FP_MUL_MEAT_DW_2_wide_3mul(wfracbits, R, X, Y, doit) \ + do \ + { \ + _FP_FRAC_DECL_2 (_FP_MUL_MEAT_DW_2_wide_3mul_b); \ + _FP_FRAC_DECL_2 (_FP_MUL_MEAT_DW_2_wide_3mul_c); \ + _FP_W_TYPE _FP_MUL_MEAT_DW_2_wide_3mul_d; \ + int _FP_MUL_MEAT_DW_2_wide_3mul_c1; \ + int _FP_MUL_MEAT_DW_2_wide_3mul_c2; \ + \ + _FP_MUL_MEAT_DW_2_wide_3mul_b_f0 = X##_f0 + X##_f1; \ + _FP_MUL_MEAT_DW_2_wide_3mul_c1 \ + = _FP_MUL_MEAT_DW_2_wide_3mul_b_f0 < X##_f0; \ + _FP_MUL_MEAT_DW_2_wide_3mul_b_f1 = Y##_f0 + Y##_f1; \ + _FP_MUL_MEAT_DW_2_wide_3mul_c2 \ + = _FP_MUL_MEAT_DW_2_wide_3mul_b_f1 < Y##_f0; \ + doit (_FP_MUL_MEAT_DW_2_wide_3mul_d, _FP_FRAC_WORD_4 (R, 0), \ + X##_f0, Y##_f0); \ + doit (_FP_FRAC_WORD_4 (R, 2), _FP_FRAC_WORD_4 (R, 1), \ + _FP_MUL_MEAT_DW_2_wide_3mul_b_f0, \ + _FP_MUL_MEAT_DW_2_wide_3mul_b_f1); \ + doit (_FP_MUL_MEAT_DW_2_wide_3mul_c_f1, \ + _FP_MUL_MEAT_DW_2_wide_3mul_c_f0, X##_f1, Y##_f1); \ + \ + _FP_MUL_MEAT_DW_2_wide_3mul_b_f0 \ + &= -_FP_MUL_MEAT_DW_2_wide_3mul_c2; \ + _FP_MUL_MEAT_DW_2_wide_3mul_b_f1 \ + &= -_FP_MUL_MEAT_DW_2_wide_3mul_c1; \ + __FP_FRAC_ADD_3 (_FP_FRAC_WORD_4 (R, 3), _FP_FRAC_WORD_4 (R, 2), \ + _FP_FRAC_WORD_4 (R, 1), \ + (_FP_MUL_MEAT_DW_2_wide_3mul_c1 \ + & _FP_MUL_MEAT_DW_2_wide_3mul_c2), 0, \ + _FP_MUL_MEAT_DW_2_wide_3mul_d, \ + 0, _FP_FRAC_WORD_4 (R, 2), _FP_FRAC_WORD_4 (R, 1)); \ + __FP_FRAC_ADDI_2 (_FP_FRAC_WORD_4 (R, 3), _FP_FRAC_WORD_4 (R, 2), \ + _FP_MUL_MEAT_DW_2_wide_3mul_b_f0); \ + __FP_FRAC_ADDI_2 (_FP_FRAC_WORD_4 (R, 3), _FP_FRAC_WORD_4 (R, 2), \ + _FP_MUL_MEAT_DW_2_wide_3mul_b_f1); \ + __FP_FRAC_DEC_3 (_FP_FRAC_WORD_4 (R, 3), _FP_FRAC_WORD_4 (R, 2), \ + _FP_FRAC_WORD_4 (R, 1), \ + 0, _FP_MUL_MEAT_DW_2_wide_3mul_d, \ + _FP_FRAC_WORD_4 (R, 0)); \ + __FP_FRAC_DEC_3 (_FP_FRAC_WORD_4 (R, 3), _FP_FRAC_WORD_4 (R, 2), \ + _FP_FRAC_WORD_4 (R, 1), 0, \ + _FP_MUL_MEAT_DW_2_wide_3mul_c_f1, \ + _FP_MUL_MEAT_DW_2_wide_3mul_c_f0); \ + __FP_FRAC_ADD_2 (_FP_FRAC_WORD_4 (R, 3), _FP_FRAC_WORD_4 (R, 2), \ + _FP_MUL_MEAT_DW_2_wide_3mul_c_f1, \ + _FP_MUL_MEAT_DW_2_wide_3mul_c_f0, \ + _FP_FRAC_WORD_4 (R, 3), _FP_FRAC_WORD_4 (R, 2)); \ + } \ + while (0) + +#define _FP_MUL_MEAT_2_wide_3mul(wfracbits, R, X, Y, doit) \ + do \ + { \ + _FP_FRAC_DECL_4 (_FP_MUL_MEAT_2_wide_3mul_z); \ + \ + _FP_MUL_MEAT_DW_2_wide_3mul ((wfracbits), \ + _FP_MUL_MEAT_2_wide_3mul_z, \ + X, Y, doit); \ + \ + /* Normalize since we know where the msb of the multiplicands \ + were (bit B), we know that the msb of the of the product is \ + at either 2B or 2B-1. */ \ + _FP_FRAC_SRS_4 (_FP_MUL_MEAT_2_wide_3mul_z, \ + (wfracbits)-1, 2*(wfracbits)); \ + R##_f0 = _FP_FRAC_WORD_4 (_FP_MUL_MEAT_2_wide_3mul_z, 0); \ + R##_f1 = _FP_FRAC_WORD_4 (_FP_MUL_MEAT_2_wide_3mul_z, 1); \ + } \ + while (0) + +#define _FP_MUL_MEAT_DW_2_gmp(wfracbits, R, X, Y) \ + do \ + { \ + _FP_W_TYPE _FP_MUL_MEAT_DW_2_gmp_x[2]; \ + _FP_W_TYPE _FP_MUL_MEAT_DW_2_gmp_y[2]; \ + _FP_MUL_MEAT_DW_2_gmp_x[0] = X##_f0; \ + _FP_MUL_MEAT_DW_2_gmp_x[1] = X##_f1; \ + _FP_MUL_MEAT_DW_2_gmp_y[0] = Y##_f0; \ + _FP_MUL_MEAT_DW_2_gmp_y[1] = Y##_f1; \ + \ + mpn_mul_n (R##_f, _FP_MUL_MEAT_DW_2_gmp_x, \ + _FP_MUL_MEAT_DW_2_gmp_y, 2); \ + } \ + while (0) + +#define _FP_MUL_MEAT_2_gmp(wfracbits, R, X, Y) \ + do \ + { \ + _FP_FRAC_DECL_4 (_FP_MUL_MEAT_2_gmp_z); \ + \ + _FP_MUL_MEAT_DW_2_gmp ((wfracbits), _FP_MUL_MEAT_2_gmp_z, X, Y); \ + \ + /* Normalize since we know where the msb of the multiplicands \ + were (bit B), we know that the msb of the of the product is \ + at either 2B or 2B-1. */ \ + _FP_FRAC_SRS_4 (_FP_MUL_MEAT_2_gmp_z, (wfracbits)-1, \ + 2*(wfracbits)); \ + R##_f0 = _FP_MUL_MEAT_2_gmp_z_f[0]; \ + R##_f1 = _FP_MUL_MEAT_2_gmp_z_f[1]; \ + } \ + while (0) + +/* Do at most 120x120=240 bits multiplication using double floating + point multiplication. This is useful if floating point + multiplication has much bigger throughput than integer multiply. + It is supposed to work for _FP_W_TYPE_SIZE 64 and wfracbits + between 106 and 120 only. + Caller guarantees that X and Y has (1LLL << (wfracbits - 1)) set. + SETFETZ is a macro which will disable all FPU exceptions and set rounding + towards zero, RESETFE should optionally reset it back. */ + +#define _FP_MUL_MEAT_2_120_240_double(wfracbits, R, X, Y, setfetz, resetfe) \ + do \ + { \ + static const double _const[] = \ + { \ + /* 2^-24 */ 5.9604644775390625e-08, \ + /* 2^-48 */ 3.5527136788005009e-15, \ + /* 2^-72 */ 2.1175823681357508e-22, \ + /* 2^-96 */ 1.2621774483536189e-29, \ + /* 2^28 */ 2.68435456e+08, \ + /* 2^4 */ 1.600000e+01, \ + /* 2^-20 */ 9.5367431640625e-07, \ + /* 2^-44 */ 5.6843418860808015e-14, \ + /* 2^-68 */ 3.3881317890172014e-21, \ + /* 2^-92 */ 2.0194839173657902e-28, \ + /* 2^-116 */ 1.2037062152420224e-35 \ + }; \ + double _a240, _b240, _c240, _d240, _e240, _f240, \ + _g240, _h240, _i240, _j240, _k240; \ + union { double d; UDItype i; } _l240, _m240, _n240, _o240, \ + _p240, _q240, _r240, _s240; \ + UDItype _t240, _u240, _v240, _w240, _x240, _y240 = 0; \ + \ + _FP_STATIC_ASSERT ((wfracbits) >= 106 && (wfracbits) <= 120, \ + "wfracbits out of range"); \ + \ + setfetz; \ + \ + _e240 = (double) (long) (X##_f0 & 0xffffff); \ + _j240 = (double) (long) (Y##_f0 & 0xffffff); \ + _d240 = (double) (long) ((X##_f0 >> 24) & 0xffffff); \ + _i240 = (double) (long) ((Y##_f0 >> 24) & 0xffffff); \ + _c240 = (double) (long) (((X##_f1 << 16) & 0xffffff) | (X##_f0 >> 48)); \ + _h240 = (double) (long) (((Y##_f1 << 16) & 0xffffff) | (Y##_f0 >> 48)); \ + _b240 = (double) (long) ((X##_f1 >> 8) & 0xffffff); \ + _g240 = (double) (long) ((Y##_f1 >> 8) & 0xffffff); \ + _a240 = (double) (long) (X##_f1 >> 32); \ + _f240 = (double) (long) (Y##_f1 >> 32); \ + _e240 *= _const[3]; \ + _j240 *= _const[3]; \ + _d240 *= _const[2]; \ + _i240 *= _const[2]; \ + _c240 *= _const[1]; \ + _h240 *= _const[1]; \ + _b240 *= _const[0]; \ + _g240 *= _const[0]; \ + _s240.d = _e240*_j240; \ + _r240.d = _d240*_j240 + _e240*_i240; \ + _q240.d = _c240*_j240 + _d240*_i240 + _e240*_h240; \ + _p240.d = _b240*_j240 + _c240*_i240 + _d240*_h240 + _e240*_g240; \ + _o240.d = _a240*_j240 + _b240*_i240 + _c240*_h240 + _d240*_g240 + _e240*_f240; \ + _n240.d = _a240*_i240 + _b240*_h240 + _c240*_g240 + _d240*_f240; \ + _m240.d = _a240*_h240 + _b240*_g240 + _c240*_f240; \ + _l240.d = _a240*_g240 + _b240*_f240; \ + _k240 = _a240*_f240; \ + _r240.d += _s240.d; \ + _q240.d += _r240.d; \ + _p240.d += _q240.d; \ + _o240.d += _p240.d; \ + _n240.d += _o240.d; \ + _m240.d += _n240.d; \ + _l240.d += _m240.d; \ + _k240 += _l240.d; \ + _s240.d -= ((_const[10]+_s240.d)-_const[10]); \ + _r240.d -= ((_const[9]+_r240.d)-_const[9]); \ + _q240.d -= ((_const[8]+_q240.d)-_const[8]); \ + _p240.d -= ((_const[7]+_p240.d)-_const[7]); \ + _o240.d += _const[7]; \ + _n240.d += _const[6]; \ + _m240.d += _const[5]; \ + _l240.d += _const[4]; \ + if (_s240.d != 0.0) \ + _y240 = 1; \ + if (_r240.d != 0.0) \ + _y240 = 1; \ + if (_q240.d != 0.0) \ + _y240 = 1; \ + if (_p240.d != 0.0) \ + _y240 = 1; \ + _t240 = (DItype) _k240; \ + _u240 = _l240.i; \ + _v240 = _m240.i; \ + _w240 = _n240.i; \ + _x240 = _o240.i; \ + R##_f1 = ((_t240 << (128 - (wfracbits - 1))) \ + | ((_u240 & 0xffffff) >> ((wfracbits - 1) - 104))); \ + R##_f0 = (((_u240 & 0xffffff) << (168 - (wfracbits - 1))) \ + | ((_v240 & 0xffffff) << (144 - (wfracbits - 1))) \ + | ((_w240 & 0xffffff) << (120 - (wfracbits - 1))) \ + | ((_x240 & 0xffffff) >> ((wfracbits - 1) - 96)) \ + | _y240); \ + resetfe; \ + } \ + while (0) + +/* Division algorithms: */ + +#define _FP_DIV_MEAT_2_udiv(fs, R, X, Y) \ + do \ + { \ + _FP_W_TYPE _FP_DIV_MEAT_2_udiv_n_f2; \ + _FP_W_TYPE _FP_DIV_MEAT_2_udiv_n_f1; \ + _FP_W_TYPE _FP_DIV_MEAT_2_udiv_n_f0; \ + _FP_W_TYPE _FP_DIV_MEAT_2_udiv_r_f1; \ + _FP_W_TYPE _FP_DIV_MEAT_2_udiv_r_f0; \ + _FP_W_TYPE _FP_DIV_MEAT_2_udiv_m_f1; \ + _FP_W_TYPE _FP_DIV_MEAT_2_udiv_m_f0; \ + if (_FP_FRAC_GE_2 (X, Y)) \ + { \ + _FP_DIV_MEAT_2_udiv_n_f2 = X##_f1 >> 1; \ + _FP_DIV_MEAT_2_udiv_n_f1 \ + = X##_f1 << (_FP_W_TYPE_SIZE - 1) | X##_f0 >> 1; \ + _FP_DIV_MEAT_2_udiv_n_f0 \ + = X##_f0 << (_FP_W_TYPE_SIZE - 1); \ + } \ + else \ + { \ + R##_e--; \ + _FP_DIV_MEAT_2_udiv_n_f2 = X##_f1; \ + _FP_DIV_MEAT_2_udiv_n_f1 = X##_f0; \ + _FP_DIV_MEAT_2_udiv_n_f0 = 0; \ + } \ + \ + /* Normalize, i.e. make the most significant bit of the \ + denominator set. */ \ + _FP_FRAC_SLL_2 (Y, _FP_WFRACXBITS_##fs); \ + \ + udiv_qrnnd (R##_f1, _FP_DIV_MEAT_2_udiv_r_f1, \ + _FP_DIV_MEAT_2_udiv_n_f2, _FP_DIV_MEAT_2_udiv_n_f1, \ + Y##_f1); \ + umul_ppmm (_FP_DIV_MEAT_2_udiv_m_f1, _FP_DIV_MEAT_2_udiv_m_f0, \ + R##_f1, Y##_f0); \ + _FP_DIV_MEAT_2_udiv_r_f0 = _FP_DIV_MEAT_2_udiv_n_f0; \ + if (_FP_FRAC_GT_2 (_FP_DIV_MEAT_2_udiv_m, _FP_DIV_MEAT_2_udiv_r)) \ + { \ + R##_f1--; \ + _FP_FRAC_ADD_2 (_FP_DIV_MEAT_2_udiv_r, Y, \ + _FP_DIV_MEAT_2_udiv_r); \ + if (_FP_FRAC_GE_2 (_FP_DIV_MEAT_2_udiv_r, Y) \ + && _FP_FRAC_GT_2 (_FP_DIV_MEAT_2_udiv_m, \ + _FP_DIV_MEAT_2_udiv_r)) \ + { \ + R##_f1--; \ + _FP_FRAC_ADD_2 (_FP_DIV_MEAT_2_udiv_r, Y, \ + _FP_DIV_MEAT_2_udiv_r); \ + } \ + } \ + _FP_FRAC_DEC_2 (_FP_DIV_MEAT_2_udiv_r, _FP_DIV_MEAT_2_udiv_m); \ + \ + if (_FP_DIV_MEAT_2_udiv_r_f1 == Y##_f1) \ + { \ + /* This is a special case, not an optimization \ + (_FP_DIV_MEAT_2_udiv_r/Y##_f1 would not fit into UWtype). \ + As _FP_DIV_MEAT_2_udiv_r is guaranteed to be < Y, \ + R##_f0 can be either (UWtype)-1 or (UWtype)-2. But as we \ + know what kind of bits it is (sticky, guard, round), \ + we don't care. We also don't care what the reminder is, \ + because the guard bit will be set anyway. -jj */ \ + R##_f0 = -1; \ + } \ + else \ + { \ + udiv_qrnnd (R##_f0, _FP_DIV_MEAT_2_udiv_r_f1, \ + _FP_DIV_MEAT_2_udiv_r_f1, \ + _FP_DIV_MEAT_2_udiv_r_f0, Y##_f1); \ + umul_ppmm (_FP_DIV_MEAT_2_udiv_m_f1, \ + _FP_DIV_MEAT_2_udiv_m_f0, R##_f0, Y##_f0); \ + _FP_DIV_MEAT_2_udiv_r_f0 = 0; \ + if (_FP_FRAC_GT_2 (_FP_DIV_MEAT_2_udiv_m, \ + _FP_DIV_MEAT_2_udiv_r)) \ + { \ + R##_f0--; \ + _FP_FRAC_ADD_2 (_FP_DIV_MEAT_2_udiv_r, Y, \ + _FP_DIV_MEAT_2_udiv_r); \ + if (_FP_FRAC_GE_2 (_FP_DIV_MEAT_2_udiv_r, Y) \ + && _FP_FRAC_GT_2 (_FP_DIV_MEAT_2_udiv_m, \ + _FP_DIV_MEAT_2_udiv_r)) \ + { \ + R##_f0--; \ + _FP_FRAC_ADD_2 (_FP_DIV_MEAT_2_udiv_r, Y, \ + _FP_DIV_MEAT_2_udiv_r); \ + } \ + } \ + if (!_FP_FRAC_EQ_2 (_FP_DIV_MEAT_2_udiv_r, \ + _FP_DIV_MEAT_2_udiv_m)) \ + R##_f0 |= _FP_WORK_STICKY; \ + } \ + } \ + while (0) + + +/* Square root algorithms: + We have just one right now, maybe Newton approximation + should be added for those machines where division is fast. */ + +#define _FP_SQRT_MEAT_2(R, S, T, X, q) \ + do \ + { \ + while (q) \ + { \ + T##_f1 = S##_f1 + (q); \ + if (T##_f1 <= X##_f1) \ + { \ + S##_f1 = T##_f1 + (q); \ + X##_f1 -= T##_f1; \ + R##_f1 += (q); \ + } \ + _FP_FRAC_SLL_2 (X, 1); \ + (q) >>= 1; \ + } \ + (q) = (_FP_W_TYPE) 1 << (_FP_W_TYPE_SIZE - 1); \ + while ((q) != _FP_WORK_ROUND) \ + { \ + T##_f0 = S##_f0 + (q); \ + T##_f1 = S##_f1; \ + if (T##_f1 < X##_f1 \ + || (T##_f1 == X##_f1 && T##_f0 <= X##_f0)) \ + { \ + S##_f0 = T##_f0 + (q); \ + S##_f1 += (T##_f0 > S##_f0); \ + _FP_FRAC_DEC_2 (X, T); \ + R##_f0 += (q); \ + } \ + _FP_FRAC_SLL_2 (X, 1); \ + (q) >>= 1; \ + } \ + if (X##_f0 | X##_f1) \ + { \ + if (S##_f1 < X##_f1 \ + || (S##_f1 == X##_f1 && S##_f0 < X##_f0)) \ + R##_f0 |= _FP_WORK_ROUND; \ + R##_f0 |= _FP_WORK_STICKY; \ + } \ + } \ + while (0) + + +/* Assembly/disassembly for converting to/from integral types. + No shifting or overflow handled here. */ + +#define _FP_FRAC_ASSEMBLE_2(r, X, rsize) \ + (void) (((rsize) <= _FP_W_TYPE_SIZE) \ + ? ({ (r) = X##_f0; }) \ + : ({ \ + (r) = X##_f1; \ + (r) <<= _FP_W_TYPE_SIZE; \ + (r) += X##_f0; \ + })) + +#define _FP_FRAC_DISASSEMBLE_2(X, r, rsize) \ + do \ + { \ + X##_f0 = (r); \ + X##_f1 = ((rsize) <= _FP_W_TYPE_SIZE \ + ? 0 \ + : (r) >> _FP_W_TYPE_SIZE); \ + } \ + while (0) + +/* Convert FP values between word sizes. */ + +#define _FP_FRAC_COPY_1_2(D, S) (D##_f = S##_f0) + +#define _FP_FRAC_COPY_2_1(D, S) ((D##_f0 = S##_f), (D##_f1 = 0)) + +#define _FP_FRAC_COPY_2_2(D, S) _FP_FRAC_COPY_2 (D, S) + +#endif /* !SOFT_FP_OP_2_H */ diff --git a/fpu/op-4.h b/fpu/op-4.h new file mode 100644 index 0000000000..01b87d01a1 --- /dev/null +++ b/fpu/op-4.h @@ -0,0 +1,875 @@ +/* Software floating-point emulation. + Basic four-word fraction declaration and manipulation. + Copyright (C) 1997-2018 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Richard Henderson (rth@cygnus.com), + Jakub Jelinek (jj@ultra.linux.cz), + David S. Miller (davem@redhat.com) and + Peter Maydell (pmaydell@chiark.greenend.org.uk). + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + In addition to the permissions in the GNU Lesser General Public + License, the Free Software Foundation gives you unlimited + permission to link the compiled version of this file into + combinations with other programs, and to distribute those + combinations without any restriction coming from the use of this + file. (The Lesser General Public License restrictions do apply in + other respects; for example, they cover modification of the file, + and distribution when not linked into a combine executable.) + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + . */ + +#ifndef SOFT_FP_OP_4_H +#define SOFT_FP_OP_4_H 1 + +#define _FP_FRAC_DECL_4(X) _FP_W_TYPE X##_f[4] +#define _FP_FRAC_COPY_4(D, S) \ + (D##_f[0] = S##_f[0], D##_f[1] = S##_f[1], \ + D##_f[2] = S##_f[2], D##_f[3] = S##_f[3]) +#define _FP_FRAC_SET_4(X, I) __FP_FRAC_SET_4 (X, I) +#define _FP_FRAC_HIGH_4(X) (X##_f[3]) +#define _FP_FRAC_LOW_4(X) (X##_f[0]) +#define _FP_FRAC_WORD_4(X, w) (X##_f[w]) + +#define _FP_FRAC_SLL_4(X, N) \ + do \ + { \ + _FP_I_TYPE _FP_FRAC_SLL_4_up, _FP_FRAC_SLL_4_down; \ + _FP_I_TYPE _FP_FRAC_SLL_4_skip, _FP_FRAC_SLL_4_i; \ + _FP_FRAC_SLL_4_skip = (N) / _FP_W_TYPE_SIZE; \ + _FP_FRAC_SLL_4_up = (N) % _FP_W_TYPE_SIZE; \ + _FP_FRAC_SLL_4_down = _FP_W_TYPE_SIZE - _FP_FRAC_SLL_4_up; \ + if (!_FP_FRAC_SLL_4_up) \ + for (_FP_FRAC_SLL_4_i = 3; \ + _FP_FRAC_SLL_4_i >= _FP_FRAC_SLL_4_skip; \ + --_FP_FRAC_SLL_4_i) \ + X##_f[_FP_FRAC_SLL_4_i] \ + = X##_f[_FP_FRAC_SLL_4_i-_FP_FRAC_SLL_4_skip]; \ + else \ + { \ + for (_FP_FRAC_SLL_4_i = 3; \ + _FP_FRAC_SLL_4_i > _FP_FRAC_SLL_4_skip; \ + --_FP_FRAC_SLL_4_i) \ + X##_f[_FP_FRAC_SLL_4_i] \ + = ((X##_f[_FP_FRAC_SLL_4_i-_FP_FRAC_SLL_4_skip] \ + << _FP_FRAC_SLL_4_up) \ + | (X##_f[_FP_FRAC_SLL_4_i-_FP_FRAC_SLL_4_skip-1] \ + >> _FP_FRAC_SLL_4_down)); \ + X##_f[_FP_FRAC_SLL_4_i--] = X##_f[0] << _FP_FRAC_SLL_4_up; \ + } \ + for (; _FP_FRAC_SLL_4_i >= 0; --_FP_FRAC_SLL_4_i) \ + X##_f[_FP_FRAC_SLL_4_i] = 0; \ + } \ + while (0) + +/* This one was broken too. */ +#define _FP_FRAC_SRL_4(X, N) \ + do \ + { \ + _FP_I_TYPE _FP_FRAC_SRL_4_up, _FP_FRAC_SRL_4_down; \ + _FP_I_TYPE _FP_FRAC_SRL_4_skip, _FP_FRAC_SRL_4_i; \ + _FP_FRAC_SRL_4_skip = (N) / _FP_W_TYPE_SIZE; \ + _FP_FRAC_SRL_4_down = (N) % _FP_W_TYPE_SIZE; \ + _FP_FRAC_SRL_4_up = _FP_W_TYPE_SIZE - _FP_FRAC_SRL_4_down; \ + if (!_FP_FRAC_SRL_4_down) \ + for (_FP_FRAC_SRL_4_i = 0; \ + _FP_FRAC_SRL_4_i <= 3-_FP_FRAC_SRL_4_skip; \ + ++_FP_FRAC_SRL_4_i) \ + X##_f[_FP_FRAC_SRL_4_i] \ + = X##_f[_FP_FRAC_SRL_4_i+_FP_FRAC_SRL_4_skip]; \ + else \ + { \ + for (_FP_FRAC_SRL_4_i = 0; \ + _FP_FRAC_SRL_4_i < 3-_FP_FRAC_SRL_4_skip; \ + ++_FP_FRAC_SRL_4_i) \ + X##_f[_FP_FRAC_SRL_4_i] \ + = ((X##_f[_FP_FRAC_SRL_4_i+_FP_FRAC_SRL_4_skip] \ + >> _FP_FRAC_SRL_4_down) \ + | (X##_f[_FP_FRAC_SRL_4_i+_FP_FRAC_SRL_4_skip+1] \ + << _FP_FRAC_SRL_4_up)); \ + X##_f[_FP_FRAC_SRL_4_i++] = X##_f[3] >> _FP_FRAC_SRL_4_down; \ + } \ + for (; _FP_FRAC_SRL_4_i < 4; ++_FP_FRAC_SRL_4_i) \ + X##_f[_FP_FRAC_SRL_4_i] = 0; \ + } \ + while (0) + + +/* Right shift with sticky-lsb. + What this actually means is that we do a standard right-shift, + but that if any of the bits that fall off the right hand side + were one then we always set the LSbit. */ +#define _FP_FRAC_SRST_4(X, S, N, size) \ + do \ + { \ + _FP_I_TYPE _FP_FRAC_SRST_4_up, _FP_FRAC_SRST_4_down; \ + _FP_I_TYPE _FP_FRAC_SRST_4_skip, _FP_FRAC_SRST_4_i; \ + _FP_W_TYPE _FP_FRAC_SRST_4_s; \ + _FP_FRAC_SRST_4_skip = (N) / _FP_W_TYPE_SIZE; \ + _FP_FRAC_SRST_4_down = (N) % _FP_W_TYPE_SIZE; \ + _FP_FRAC_SRST_4_up = _FP_W_TYPE_SIZE - _FP_FRAC_SRST_4_down; \ + for (_FP_FRAC_SRST_4_s = _FP_FRAC_SRST_4_i = 0; \ + _FP_FRAC_SRST_4_i < _FP_FRAC_SRST_4_skip; \ + ++_FP_FRAC_SRST_4_i) \ + _FP_FRAC_SRST_4_s |= X##_f[_FP_FRAC_SRST_4_i]; \ + if (!_FP_FRAC_SRST_4_down) \ + for (_FP_FRAC_SRST_4_i = 0; \ + _FP_FRAC_SRST_4_i <= 3-_FP_FRAC_SRST_4_skip; \ + ++_FP_FRAC_SRST_4_i) \ + X##_f[_FP_FRAC_SRST_4_i] \ + = X##_f[_FP_FRAC_SRST_4_i+_FP_FRAC_SRST_4_skip]; \ + else \ + { \ + _FP_FRAC_SRST_4_s \ + |= X##_f[_FP_FRAC_SRST_4_i] << _FP_FRAC_SRST_4_up; \ + for (_FP_FRAC_SRST_4_i = 0; \ + _FP_FRAC_SRST_4_i < 3-_FP_FRAC_SRST_4_skip; \ + ++_FP_FRAC_SRST_4_i) \ + X##_f[_FP_FRAC_SRST_4_i] \ + = ((X##_f[_FP_FRAC_SRST_4_i+_FP_FRAC_SRST_4_skip] \ + >> _FP_FRAC_SRST_4_down) \ + | (X##_f[_FP_FRAC_SRST_4_i+_FP_FRAC_SRST_4_skip+1] \ + << _FP_FRAC_SRST_4_up)); \ + X##_f[_FP_FRAC_SRST_4_i++] \ + = X##_f[3] >> _FP_FRAC_SRST_4_down; \ + } \ + for (; _FP_FRAC_SRST_4_i < 4; ++_FP_FRAC_SRST_4_i) \ + X##_f[_FP_FRAC_SRST_4_i] = 0; \ + S = (_FP_FRAC_SRST_4_s != 0); \ + } \ + while (0) + +#define _FP_FRAC_SRS_4(X, N, size) \ + do \ + { \ + int _FP_FRAC_SRS_4_sticky; \ + _FP_FRAC_SRST_4 (X, _FP_FRAC_SRS_4_sticky, (N), (size)); \ + X##_f[0] |= _FP_FRAC_SRS_4_sticky; \ + } \ + while (0) + +#define _FP_FRAC_ADD_4(R, X, Y) \ + __FP_FRAC_ADD_4 (R##_f[3], R##_f[2], R##_f[1], R##_f[0], \ + X##_f[3], X##_f[2], X##_f[1], X##_f[0], \ + Y##_f[3], Y##_f[2], Y##_f[1], Y##_f[0]) + +#define _FP_FRAC_SUB_4(R, X, Y) \ + __FP_FRAC_SUB_4 (R##_f[3], R##_f[2], R##_f[1], R##_f[0], \ + X##_f[3], X##_f[2], X##_f[1], X##_f[0], \ + Y##_f[3], Y##_f[2], Y##_f[1], Y##_f[0]) + +#define _FP_FRAC_DEC_4(X, Y) \ + __FP_FRAC_DEC_4 (X##_f[3], X##_f[2], X##_f[1], X##_f[0], \ + Y##_f[3], Y##_f[2], Y##_f[1], Y##_f[0]) + +#define _FP_FRAC_ADDI_4(X, I) \ + __FP_FRAC_ADDI_4 (X##_f[3], X##_f[2], X##_f[1], X##_f[0], I) + +#define _FP_ZEROFRAC_4 0, 0, 0, 0 +#define _FP_MINFRAC_4 0, 0, 0, 1 +#define _FP_MAXFRAC_4 (~(_FP_WS_TYPE) 0), (~(_FP_WS_TYPE) 0), (~(_FP_WS_TYPE) 0), (~(_FP_WS_TYPE) 0) + +#define _FP_FRAC_ZEROP_4(X) ((X##_f[0] | X##_f[1] | X##_f[2] | X##_f[3]) == 0) +#define _FP_FRAC_NEGP_4(X) ((_FP_WS_TYPE) X##_f[3] < 0) +#define _FP_FRAC_OVERP_4(fs, X) (_FP_FRAC_HIGH_##fs (X) & _FP_OVERFLOW_##fs) +#define _FP_FRAC_HIGHBIT_DW_4(fs, X) \ + (_FP_FRAC_HIGH_DW_##fs (X) & _FP_HIGHBIT_DW_##fs) +#define _FP_FRAC_CLEAR_OVERP_4(fs, X) (_FP_FRAC_HIGH_##fs (X) &= ~_FP_OVERFLOW_##fs) + +#define _FP_FRAC_EQ_4(X, Y) \ + (X##_f[0] == Y##_f[0] && X##_f[1] == Y##_f[1] \ + && X##_f[2] == Y##_f[2] && X##_f[3] == Y##_f[3]) + +#define _FP_FRAC_GT_4(X, Y) \ + (X##_f[3] > Y##_f[3] \ + || (X##_f[3] == Y##_f[3] \ + && (X##_f[2] > Y##_f[2] \ + || (X##_f[2] == Y##_f[2] \ + && (X##_f[1] > Y##_f[1] \ + || (X##_f[1] == Y##_f[1] \ + && X##_f[0] > Y##_f[0])))))) + +#define _FP_FRAC_GE_4(X, Y) \ + (X##_f[3] > Y##_f[3] \ + || (X##_f[3] == Y##_f[3] \ + && (X##_f[2] > Y##_f[2] \ + || (X##_f[2] == Y##_f[2] \ + && (X##_f[1] > Y##_f[1] \ + || (X##_f[1] == Y##_f[1] \ + && X##_f[0] >= Y##_f[0])))))) + + +#define _FP_FRAC_CLZ_4(R, X) \ + do \ + { \ + if (X##_f[3]) \ + __FP_CLZ ((R), X##_f[3]); \ + else if (X##_f[2]) \ + { \ + __FP_CLZ ((R), X##_f[2]); \ + (R) += _FP_W_TYPE_SIZE; \ + } \ + else if (X##_f[1]) \ + { \ + __FP_CLZ ((R), X##_f[1]); \ + (R) += _FP_W_TYPE_SIZE*2; \ + } \ + else \ + { \ + __FP_CLZ ((R), X##_f[0]); \ + (R) += _FP_W_TYPE_SIZE*3; \ + } \ + } \ + while (0) + + +#define _FP_UNPACK_RAW_4(fs, X, val) \ + do \ + { \ + union _FP_UNION_##fs _FP_UNPACK_RAW_4_flo; \ + _FP_UNPACK_RAW_4_flo.flt = (val); \ + X##_f[0] = _FP_UNPACK_RAW_4_flo.bits.frac0; \ + X##_f[1] = _FP_UNPACK_RAW_4_flo.bits.frac1; \ + X##_f[2] = _FP_UNPACK_RAW_4_flo.bits.frac2; \ + X##_f[3] = _FP_UNPACK_RAW_4_flo.bits.frac3; \ + X##_e = _FP_UNPACK_RAW_4_flo.bits.exp; \ + X##_s = _FP_UNPACK_RAW_4_flo.bits.sign; \ + } \ + while (0) + +#define _FP_UNPACK_RAW_4_P(fs, X, val) \ + do \ + { \ + union _FP_UNION_##fs *_FP_UNPACK_RAW_4_P_flo \ + = (union _FP_UNION_##fs *) (val); \ + \ + X##_f[0] = _FP_UNPACK_RAW_4_P_flo->bits.frac0; \ + X##_f[1] = _FP_UNPACK_RAW_4_P_flo->bits.frac1; \ + X##_f[2] = _FP_UNPACK_RAW_4_P_flo->bits.frac2; \ + X##_f[3] = _FP_UNPACK_RAW_4_P_flo->bits.frac3; \ + X##_e = _FP_UNPACK_RAW_4_P_flo->bits.exp; \ + X##_s = _FP_UNPACK_RAW_4_P_flo->bits.sign; \ + } \ + while (0) + +#define _FP_PACK_RAW_4(fs, val, X) \ + do \ + { \ + union _FP_UNION_##fs _FP_PACK_RAW_4_flo; \ + _FP_PACK_RAW_4_flo.bits.frac0 = X##_f[0]; \ + _FP_PACK_RAW_4_flo.bits.frac1 = X##_f[1]; \ + _FP_PACK_RAW_4_flo.bits.frac2 = X##_f[2]; \ + _FP_PACK_RAW_4_flo.bits.frac3 = X##_f[3]; \ + _FP_PACK_RAW_4_flo.bits.exp = X##_e; \ + _FP_PACK_RAW_4_flo.bits.sign = X##_s; \ + (val) = _FP_PACK_RAW_4_flo.flt; \ + } \ + while (0) + +#define _FP_PACK_RAW_4_P(fs, val, X) \ + do \ + { \ + union _FP_UNION_##fs *_FP_PACK_RAW_4_P_flo \ + = (union _FP_UNION_##fs *) (val); \ + \ + _FP_PACK_RAW_4_P_flo->bits.frac0 = X##_f[0]; \ + _FP_PACK_RAW_4_P_flo->bits.frac1 = X##_f[1]; \ + _FP_PACK_RAW_4_P_flo->bits.frac2 = X##_f[2]; \ + _FP_PACK_RAW_4_P_flo->bits.frac3 = X##_f[3]; \ + _FP_PACK_RAW_4_P_flo->bits.exp = X##_e; \ + _FP_PACK_RAW_4_P_flo->bits.sign = X##_s; \ + } \ + while (0) + +/* Multiplication algorithms: */ + +/* Given a 1W * 1W => 2W primitive, do the extended multiplication. */ + +#define _FP_MUL_MEAT_DW_4_wide(wfracbits, R, X, Y, doit) \ + do \ + { \ + _FP_FRAC_DECL_2 (_FP_MUL_MEAT_DW_4_wide_b); \ + _FP_FRAC_DECL_2 (_FP_MUL_MEAT_DW_4_wide_c); \ + _FP_FRAC_DECL_2 (_FP_MUL_MEAT_DW_4_wide_d); \ + _FP_FRAC_DECL_2 (_FP_MUL_MEAT_DW_4_wide_e); \ + _FP_FRAC_DECL_2 (_FP_MUL_MEAT_DW_4_wide_f); \ + \ + doit (_FP_FRAC_WORD_8 (R, 1), _FP_FRAC_WORD_8 (R, 0), \ + X##_f[0], Y##_f[0]); \ + doit (_FP_MUL_MEAT_DW_4_wide_b_f1, _FP_MUL_MEAT_DW_4_wide_b_f0, \ + X##_f[0], Y##_f[1]); \ + doit (_FP_MUL_MEAT_DW_4_wide_c_f1, _FP_MUL_MEAT_DW_4_wide_c_f0, \ + X##_f[1], Y##_f[0]); \ + doit (_FP_MUL_MEAT_DW_4_wide_d_f1, _FP_MUL_MEAT_DW_4_wide_d_f0, \ + X##_f[1], Y##_f[1]); \ + doit (_FP_MUL_MEAT_DW_4_wide_e_f1, _FP_MUL_MEAT_DW_4_wide_e_f0, \ + X##_f[0], Y##_f[2]); \ + doit (_FP_MUL_MEAT_DW_4_wide_f_f1, _FP_MUL_MEAT_DW_4_wide_f_f0, \ + X##_f[2], Y##_f[0]); \ + __FP_FRAC_ADD_3 (_FP_FRAC_WORD_8 (R, 3), _FP_FRAC_WORD_8 (R, 2), \ + _FP_FRAC_WORD_8 (R, 1), 0, \ + _FP_MUL_MEAT_DW_4_wide_b_f1, \ + _FP_MUL_MEAT_DW_4_wide_b_f0, \ + 0, 0, _FP_FRAC_WORD_8 (R, 1)); \ + __FP_FRAC_ADD_3 (_FP_FRAC_WORD_8 (R, 3), _FP_FRAC_WORD_8 (R, 2), \ + _FP_FRAC_WORD_8 (R, 1), 0, \ + _FP_MUL_MEAT_DW_4_wide_c_f1, \ + _FP_MUL_MEAT_DW_4_wide_c_f0, \ + _FP_FRAC_WORD_8 (R, 3), _FP_FRAC_WORD_8 (R, 2), \ + _FP_FRAC_WORD_8 (R, 1)); \ + __FP_FRAC_ADD_3 (_FP_FRAC_WORD_8 (R, 4), _FP_FRAC_WORD_8 (R, 3), \ + _FP_FRAC_WORD_8 (R, 2), 0, \ + _FP_MUL_MEAT_DW_4_wide_d_f1, \ + _FP_MUL_MEAT_DW_4_wide_d_f0, \ + 0, _FP_FRAC_WORD_8 (R, 3), _FP_FRAC_WORD_8 (R, 2)); \ + __FP_FRAC_ADD_3 (_FP_FRAC_WORD_8 (R, 4), _FP_FRAC_WORD_8 (R, 3), \ + _FP_FRAC_WORD_8 (R, 2), 0, \ + _FP_MUL_MEAT_DW_4_wide_e_f1, \ + _FP_MUL_MEAT_DW_4_wide_e_f0, \ + _FP_FRAC_WORD_8 (R, 4), _FP_FRAC_WORD_8 (R, 3), \ + _FP_FRAC_WORD_8 (R, 2)); \ + __FP_FRAC_ADD_3 (_FP_FRAC_WORD_8 (R, 4), _FP_FRAC_WORD_8 (R, 3), \ + _FP_FRAC_WORD_8 (R, 2), 0, \ + _FP_MUL_MEAT_DW_4_wide_f_f1, \ + _FP_MUL_MEAT_DW_4_wide_f_f0, \ + _FP_FRAC_WORD_8 (R, 4), _FP_FRAC_WORD_8 (R, 3), \ + _FP_FRAC_WORD_8 (R, 2)); \ + doit (_FP_MUL_MEAT_DW_4_wide_b_f1, \ + _FP_MUL_MEAT_DW_4_wide_b_f0, X##_f[0], Y##_f[3]); \ + doit (_FP_MUL_MEAT_DW_4_wide_c_f1, \ + _FP_MUL_MEAT_DW_4_wide_c_f0, X##_f[3], Y##_f[0]); \ + doit (_FP_MUL_MEAT_DW_4_wide_d_f1, _FP_MUL_MEAT_DW_4_wide_d_f0, \ + X##_f[1], Y##_f[2]); \ + doit (_FP_MUL_MEAT_DW_4_wide_e_f1, _FP_MUL_MEAT_DW_4_wide_e_f0, \ + X##_f[2], Y##_f[1]); \ + __FP_FRAC_ADD_3 (_FP_FRAC_WORD_8 (R, 5), _FP_FRAC_WORD_8 (R, 4), \ + _FP_FRAC_WORD_8 (R, 3), 0, \ + _FP_MUL_MEAT_DW_4_wide_b_f1, \ + _FP_MUL_MEAT_DW_4_wide_b_f0, \ + 0, _FP_FRAC_WORD_8 (R, 4), _FP_FRAC_WORD_8 (R, 3)); \ + __FP_FRAC_ADD_3 (_FP_FRAC_WORD_8 (R, 5), _FP_FRAC_WORD_8 (R, 4), \ + _FP_FRAC_WORD_8 (R, 3), 0, \ + _FP_MUL_MEAT_DW_4_wide_c_f1, \ + _FP_MUL_MEAT_DW_4_wide_c_f0, \ + _FP_FRAC_WORD_8 (R, 5), _FP_FRAC_WORD_8 (R, 4), \ + _FP_FRAC_WORD_8 (R, 3)); \ + __FP_FRAC_ADD_3 (_FP_FRAC_WORD_8 (R, 5), _FP_FRAC_WORD_8 (R, 4), \ + _FP_FRAC_WORD_8 (R, 3), 0, \ + _FP_MUL_MEAT_DW_4_wide_d_f1, \ + _FP_MUL_MEAT_DW_4_wide_d_f0, \ + _FP_FRAC_WORD_8 (R, 5), _FP_FRAC_WORD_8 (R, 4), \ + _FP_FRAC_WORD_8 (R, 3)); \ + __FP_FRAC_ADD_3 (_FP_FRAC_WORD_8 (R, 5), _FP_FRAC_WORD_8 (R, 4), \ + _FP_FRAC_WORD_8 (R, 3), 0, \ + _FP_MUL_MEAT_DW_4_wide_e_f1, \ + _FP_MUL_MEAT_DW_4_wide_e_f0, \ + _FP_FRAC_WORD_8 (R, 5), _FP_FRAC_WORD_8 (R, 4), \ + _FP_FRAC_WORD_8 (R, 3)); \ + doit (_FP_MUL_MEAT_DW_4_wide_b_f1, _FP_MUL_MEAT_DW_4_wide_b_f0, \ + X##_f[2], Y##_f[2]); \ + doit (_FP_MUL_MEAT_DW_4_wide_c_f1, _FP_MUL_MEAT_DW_4_wide_c_f0, \ + X##_f[1], Y##_f[3]); \ + doit (_FP_MUL_MEAT_DW_4_wide_d_f1, _FP_MUL_MEAT_DW_4_wide_d_f0, \ + X##_f[3], Y##_f[1]); \ + doit (_FP_MUL_MEAT_DW_4_wide_e_f1, _FP_MUL_MEAT_DW_4_wide_e_f0, \ + X##_f[2], Y##_f[3]); \ + doit (_FP_MUL_MEAT_DW_4_wide_f_f1, _FP_MUL_MEAT_DW_4_wide_f_f0, \ + X##_f[3], Y##_f[2]); \ + __FP_FRAC_ADD_3 (_FP_FRAC_WORD_8 (R, 6), _FP_FRAC_WORD_8 (R, 5), \ + _FP_FRAC_WORD_8 (R, 4), 0, \ + _FP_MUL_MEAT_DW_4_wide_b_f1, \ + _FP_MUL_MEAT_DW_4_wide_b_f0, \ + 0, _FP_FRAC_WORD_8 (R, 5), _FP_FRAC_WORD_8 (R, 4)); \ + __FP_FRAC_ADD_3 (_FP_FRAC_WORD_8 (R, 6), _FP_FRAC_WORD_8 (R, 5), \ + _FP_FRAC_WORD_8 (R, 4), 0, \ + _FP_MUL_MEAT_DW_4_wide_c_f1, \ + _FP_MUL_MEAT_DW_4_wide_c_f0, \ + _FP_FRAC_WORD_8 (R, 6), _FP_FRAC_WORD_8 (R, 5), \ + _FP_FRAC_WORD_8 (R, 4)); \ + __FP_FRAC_ADD_3 (_FP_FRAC_WORD_8 (R, 6), _FP_FRAC_WORD_8 (R, 5), \ + _FP_FRAC_WORD_8 (R, 4), 0, \ + _FP_MUL_MEAT_DW_4_wide_d_f1, \ + _FP_MUL_MEAT_DW_4_wide_d_f0, \ + _FP_FRAC_WORD_8 (R, 6), _FP_FRAC_WORD_8 (R, 5), \ + _FP_FRAC_WORD_8 (R, 4)); \ + __FP_FRAC_ADD_3 (_FP_FRAC_WORD_8 (R, 7), _FP_FRAC_WORD_8 (R, 6), \ + _FP_FRAC_WORD_8 (R, 5), 0, \ + _FP_MUL_MEAT_DW_4_wide_e_f1, \ + _FP_MUL_MEAT_DW_4_wide_e_f0, \ + 0, _FP_FRAC_WORD_8 (R, 6), _FP_FRAC_WORD_8 (R, 5)); \ + __FP_FRAC_ADD_3 (_FP_FRAC_WORD_8 (R, 7), _FP_FRAC_WORD_8 (R, 6), \ + _FP_FRAC_WORD_8 (R, 5), 0, \ + _FP_MUL_MEAT_DW_4_wide_f_f1, \ + _FP_MUL_MEAT_DW_4_wide_f_f0, \ + _FP_FRAC_WORD_8 (R, 7), _FP_FRAC_WORD_8 (R, 6), \ + _FP_FRAC_WORD_8 (R, 5)); \ + doit (_FP_MUL_MEAT_DW_4_wide_b_f1, _FP_MUL_MEAT_DW_4_wide_b_f0, \ + X##_f[3], Y##_f[3]); \ + __FP_FRAC_ADD_2 (_FP_FRAC_WORD_8 (R, 7), _FP_FRAC_WORD_8 (R, 6), \ + _FP_MUL_MEAT_DW_4_wide_b_f1, \ + _FP_MUL_MEAT_DW_4_wide_b_f0, \ + _FP_FRAC_WORD_8 (R, 7), _FP_FRAC_WORD_8 (R, 6)); \ + } \ + while (0) + +#define _FP_MUL_MEAT_4_wide(wfracbits, R, X, Y, doit) \ + do \ + { \ + _FP_FRAC_DECL_8 (_FP_MUL_MEAT_4_wide_z); \ + \ + _FP_MUL_MEAT_DW_4_wide ((wfracbits), _FP_MUL_MEAT_4_wide_z, \ + X, Y, doit); \ + \ + /* Normalize since we know where the msb of the multiplicands \ + were (bit B), we know that the msb of the of the product is \ + at either 2B or 2B-1. */ \ + _FP_FRAC_SRS_8 (_FP_MUL_MEAT_4_wide_z, (wfracbits)-1, \ + 2*(wfracbits)); \ + __FP_FRAC_SET_4 (R, _FP_FRAC_WORD_8 (_FP_MUL_MEAT_4_wide_z, 3), \ + _FP_FRAC_WORD_8 (_FP_MUL_MEAT_4_wide_z, 2), \ + _FP_FRAC_WORD_8 (_FP_MUL_MEAT_4_wide_z, 1), \ + _FP_FRAC_WORD_8 (_FP_MUL_MEAT_4_wide_z, 0)); \ + } \ + while (0) + +#define _FP_MUL_MEAT_DW_4_gmp(wfracbits, R, X, Y) \ + do \ + { \ + mpn_mul_n (R##_f, _x_f, _y_f, 4); \ + } \ + while (0) + +#define _FP_MUL_MEAT_4_gmp(wfracbits, R, X, Y) \ + do \ + { \ + _FP_FRAC_DECL_8 (_FP_MUL_MEAT_4_gmp_z); \ + \ + _FP_MUL_MEAT_DW_4_gmp ((wfracbits), _FP_MUL_MEAT_4_gmp_z, X, Y); \ + \ + /* Normalize since we know where the msb of the multiplicands \ + were (bit B), we know that the msb of the of the product is \ + at either 2B or 2B-1. */ \ + _FP_FRAC_SRS_8 (_FP_MUL_MEAT_4_gmp_z, (wfracbits)-1, \ + 2*(wfracbits)); \ + __FP_FRAC_SET_4 (R, _FP_FRAC_WORD_8 (_FP_MUL_MEAT_4_gmp_z, 3), \ + _FP_FRAC_WORD_8 (_FP_MUL_MEAT_4_gmp_z, 2), \ + _FP_FRAC_WORD_8 (_FP_MUL_MEAT_4_gmp_z, 1), \ + _FP_FRAC_WORD_8 (_FP_MUL_MEAT_4_gmp_z, 0)); \ + } \ + while (0) + +/* Helper utility for _FP_DIV_MEAT_4_udiv: + * pppp = m * nnn. */ +#define umul_ppppmnnn(p3, p2, p1, p0, m, n2, n1, n0) \ + do \ + { \ + UWtype umul_ppppmnnn_t; \ + umul_ppmm (p1, p0, m, n0); \ + umul_ppmm (p2, umul_ppppmnnn_t, m, n1); \ + __FP_FRAC_ADDI_2 (p2, p1, umul_ppppmnnn_t); \ + umul_ppmm (p3, umul_ppppmnnn_t, m, n2); \ + __FP_FRAC_ADDI_2 (p3, p2, umul_ppppmnnn_t); \ + } \ + while (0) + +/* Division algorithms: */ + +#define _FP_DIV_MEAT_4_udiv(fs, R, X, Y) \ + do \ + { \ + int _FP_DIV_MEAT_4_udiv_i; \ + _FP_FRAC_DECL_4 (_FP_DIV_MEAT_4_udiv_n); \ + _FP_FRAC_DECL_4 (_FP_DIV_MEAT_4_udiv_m); \ + _FP_FRAC_SET_4 (_FP_DIV_MEAT_4_udiv_n, _FP_ZEROFRAC_4); \ + if (_FP_FRAC_GE_4 (X, Y)) \ + { \ + _FP_DIV_MEAT_4_udiv_n_f[3] \ + = X##_f[0] << (_FP_W_TYPE_SIZE - 1); \ + _FP_FRAC_SRL_4 (X, 1); \ + } \ + else \ + R##_e--; \ + \ + /* Normalize, i.e. make the most significant bit of the \ + denominator set. */ \ + _FP_FRAC_SLL_4 (Y, _FP_WFRACXBITS_##fs); \ + \ + for (_FP_DIV_MEAT_4_udiv_i = 3; ; _FP_DIV_MEAT_4_udiv_i--) \ + { \ + if (X##_f[3] == Y##_f[3]) \ + { \ + /* This is a special case, not an optimization \ + (X##_f[3]/Y##_f[3] would not fit into UWtype). \ + As X## is guaranteed to be < Y, \ + R##_f[_FP_DIV_MEAT_4_udiv_i] can be either \ + (UWtype)-1 or (UWtype)-2. */ \ + R##_f[_FP_DIV_MEAT_4_udiv_i] = -1; \ + if (!_FP_DIV_MEAT_4_udiv_i) \ + break; \ + __FP_FRAC_SUB_4 (X##_f[3], X##_f[2], X##_f[1], X##_f[0], \ + Y##_f[2], Y##_f[1], Y##_f[0], 0, \ + X##_f[2], X##_f[1], X##_f[0], \ + _FP_DIV_MEAT_4_udiv_n_f[_FP_DIV_MEAT_4_udiv_i]); \ + _FP_FRAC_SUB_4 (X, Y, X); \ + if (X##_f[3] > Y##_f[3]) \ + { \ + R##_f[_FP_DIV_MEAT_4_udiv_i] = -2; \ + _FP_FRAC_ADD_4 (X, Y, X); \ + } \ + } \ + else \ + { \ + udiv_qrnnd (R##_f[_FP_DIV_MEAT_4_udiv_i], \ + X##_f[3], X##_f[3], X##_f[2], Y##_f[3]); \ + umul_ppppmnnn (_FP_DIV_MEAT_4_udiv_m_f[3], \ + _FP_DIV_MEAT_4_udiv_m_f[2], \ + _FP_DIV_MEAT_4_udiv_m_f[1], \ + _FP_DIV_MEAT_4_udiv_m_f[0], \ + R##_f[_FP_DIV_MEAT_4_udiv_i], \ + Y##_f[2], Y##_f[1], Y##_f[0]); \ + X##_f[2] = X##_f[1]; \ + X##_f[1] = X##_f[0]; \ + X##_f[0] \ + = _FP_DIV_MEAT_4_udiv_n_f[_FP_DIV_MEAT_4_udiv_i]; \ + if (_FP_FRAC_GT_4 (_FP_DIV_MEAT_4_udiv_m, X)) \ + { \ + R##_f[_FP_DIV_MEAT_4_udiv_i]--; \ + _FP_FRAC_ADD_4 (X, Y, X); \ + if (_FP_FRAC_GE_4 (X, Y) \ + && _FP_FRAC_GT_4 (_FP_DIV_MEAT_4_udiv_m, X)) \ + { \ + R##_f[_FP_DIV_MEAT_4_udiv_i]--; \ + _FP_FRAC_ADD_4 (X, Y, X); \ + } \ + } \ + _FP_FRAC_DEC_4 (X, _FP_DIV_MEAT_4_udiv_m); \ + if (!_FP_DIV_MEAT_4_udiv_i) \ + { \ + if (!_FP_FRAC_EQ_4 (X, _FP_DIV_MEAT_4_udiv_m)) \ + R##_f[0] |= _FP_WORK_STICKY; \ + break; \ + } \ + } \ + } \ + } \ + while (0) + + +/* Square root algorithms: + We have just one right now, maybe Newton approximation + should be added for those machines where division is fast. */ + +#define _FP_SQRT_MEAT_4(R, S, T, X, q) \ + do \ + { \ + while (q) \ + { \ + T##_f[3] = S##_f[3] + (q); \ + if (T##_f[3] <= X##_f[3]) \ + { \ + S##_f[3] = T##_f[3] + (q); \ + X##_f[3] -= T##_f[3]; \ + R##_f[3] += (q); \ + } \ + _FP_FRAC_SLL_4 (X, 1); \ + (q) >>= 1; \ + } \ + (q) = (_FP_W_TYPE) 1 << (_FP_W_TYPE_SIZE - 1); \ + while (q) \ + { \ + T##_f[2] = S##_f[2] + (q); \ + T##_f[3] = S##_f[3]; \ + if (T##_f[3] < X##_f[3] \ + || (T##_f[3] == X##_f[3] && T##_f[2] <= X##_f[2])) \ + { \ + S##_f[2] = T##_f[2] + (q); \ + S##_f[3] += (T##_f[2] > S##_f[2]); \ + __FP_FRAC_DEC_2 (X##_f[3], X##_f[2], \ + T##_f[3], T##_f[2]); \ + R##_f[2] += (q); \ + } \ + _FP_FRAC_SLL_4 (X, 1); \ + (q) >>= 1; \ + } \ + (q) = (_FP_W_TYPE) 1 << (_FP_W_TYPE_SIZE - 1); \ + while (q) \ + { \ + T##_f[1] = S##_f[1] + (q); \ + T##_f[2] = S##_f[2]; \ + T##_f[3] = S##_f[3]; \ + if (T##_f[3] < X##_f[3] \ + || (T##_f[3] == X##_f[3] \ + && (T##_f[2] < X##_f[2] \ + || (T##_f[2] == X##_f[2] \ + && T##_f[1] <= X##_f[1])))) \ + { \ + S##_f[1] = T##_f[1] + (q); \ + S##_f[2] += (T##_f[1] > S##_f[1]); \ + S##_f[3] += (T##_f[2] > S##_f[2]); \ + __FP_FRAC_DEC_3 (X##_f[3], X##_f[2], X##_f[1], \ + T##_f[3], T##_f[2], T##_f[1]); \ + R##_f[1] += (q); \ + } \ + _FP_FRAC_SLL_4 (X, 1); \ + (q) >>= 1; \ + } \ + (q) = (_FP_W_TYPE) 1 << (_FP_W_TYPE_SIZE - 1); \ + while ((q) != _FP_WORK_ROUND) \ + { \ + T##_f[0] = S##_f[0] + (q); \ + T##_f[1] = S##_f[1]; \ + T##_f[2] = S##_f[2]; \ + T##_f[3] = S##_f[3]; \ + if (_FP_FRAC_GE_4 (X, T)) \ + { \ + S##_f[0] = T##_f[0] + (q); \ + S##_f[1] += (T##_f[0] > S##_f[0]); \ + S##_f[2] += (T##_f[1] > S##_f[1]); \ + S##_f[3] += (T##_f[2] > S##_f[2]); \ + _FP_FRAC_DEC_4 (X, T); \ + R##_f[0] += (q); \ + } \ + _FP_FRAC_SLL_4 (X, 1); \ + (q) >>= 1; \ + } \ + if (!_FP_FRAC_ZEROP_4 (X)) \ + { \ + if (_FP_FRAC_GT_4 (X, S)) \ + R##_f[0] |= _FP_WORK_ROUND; \ + R##_f[0] |= _FP_WORK_STICKY; \ + } \ + } \ + while (0) + + +/* Internals. */ + +#define __FP_FRAC_SET_4(X, I3, I2, I1, I0) \ + (X##_f[3] = I3, X##_f[2] = I2, X##_f[1] = I1, X##_f[0] = I0) + +#ifndef __FP_FRAC_ADD_3 +# define __FP_FRAC_ADD_3(r2, r1, r0, x2, x1, x0, y2, y1, y0) \ + do \ + { \ + _FP_W_TYPE __FP_FRAC_ADD_3_c1, __FP_FRAC_ADD_3_c2; \ + r0 = x0 + y0; \ + __FP_FRAC_ADD_3_c1 = r0 < x0; \ + r1 = x1 + y1; \ + __FP_FRAC_ADD_3_c2 = r1 < x1; \ + r1 += __FP_FRAC_ADD_3_c1; \ + __FP_FRAC_ADD_3_c2 |= r1 < __FP_FRAC_ADD_3_c1; \ + r2 = x2 + y2 + __FP_FRAC_ADD_3_c2; \ + } \ + while (0) +#endif + +#ifndef __FP_FRAC_ADD_4 +# define __FP_FRAC_ADD_4(r3, r2, r1, r0, x3, x2, x1, x0, y3, y2, y1, y0) \ + do \ + { \ + _FP_W_TYPE __FP_FRAC_ADD_4_c1, __FP_FRAC_ADD_4_c2; \ + _FP_W_TYPE __FP_FRAC_ADD_4_c3; \ + r0 = x0 + y0; \ + __FP_FRAC_ADD_4_c1 = r0 < x0; \ + r1 = x1 + y1; \ + __FP_FRAC_ADD_4_c2 = r1 < x1; \ + r1 += __FP_FRAC_ADD_4_c1; \ + __FP_FRAC_ADD_4_c2 |= r1 < __FP_FRAC_ADD_4_c1; \ + r2 = x2 + y2; \ + __FP_FRAC_ADD_4_c3 = r2 < x2; \ + r2 += __FP_FRAC_ADD_4_c2; \ + __FP_FRAC_ADD_4_c3 |= r2 < __FP_FRAC_ADD_4_c2; \ + r3 = x3 + y3 + __FP_FRAC_ADD_4_c3; \ + } \ + while (0) +#endif + +#ifndef __FP_FRAC_SUB_3 +# define __FP_FRAC_SUB_3(r2, r1, r0, x2, x1, x0, y2, y1, y0) \ + do \ + { \ + _FP_W_TYPE __FP_FRAC_SUB_3_c1, __FP_FRAC_SUB_3_c2; \ + r0 = x0 - y0; \ + __FP_FRAC_SUB_3_c1 = r0 > x0; \ + r1 = x1 - y1; \ + __FP_FRAC_SUB_3_c2 = r1 > x1; \ + r1 -= __FP_FRAC_SUB_3_c1; \ + __FP_FRAC_SUB_3_c2 |= __FP_FRAC_SUB_3_c1 && (y1 == x1); \ + r2 = x2 - y2 - __FP_FRAC_SUB_3_c2; \ + } \ + while (0) +#endif + +#ifndef __FP_FRAC_SUB_4 +# define __FP_FRAC_SUB_4(r3, r2, r1, r0, x3, x2, x1, x0, y3, y2, y1, y0) \ + do \ + { \ + _FP_W_TYPE __FP_FRAC_SUB_4_c1, __FP_FRAC_SUB_4_c2; \ + _FP_W_TYPE __FP_FRAC_SUB_4_c3; \ + r0 = x0 - y0; \ + __FP_FRAC_SUB_4_c1 = r0 > x0; \ + r1 = x1 - y1; \ + __FP_FRAC_SUB_4_c2 = r1 > x1; \ + r1 -= __FP_FRAC_SUB_4_c1; \ + __FP_FRAC_SUB_4_c2 |= __FP_FRAC_SUB_4_c1 && (y1 == x1); \ + r2 = x2 - y2; \ + __FP_FRAC_SUB_4_c3 = r2 > x2; \ + r2 -= __FP_FRAC_SUB_4_c2; \ + __FP_FRAC_SUB_4_c3 |= __FP_FRAC_SUB_4_c2 && (y2 == x2); \ + r3 = x3 - y3 - __FP_FRAC_SUB_4_c3; \ + } \ + while (0) +#endif + +#ifndef __FP_FRAC_DEC_3 +# define __FP_FRAC_DEC_3(x2, x1, x0, y2, y1, y0) \ + do \ + { \ + UWtype __FP_FRAC_DEC_3_t0, __FP_FRAC_DEC_3_t1; \ + UWtype __FP_FRAC_DEC_3_t2; \ + __FP_FRAC_DEC_3_t0 = x0; \ + __FP_FRAC_DEC_3_t1 = x1; \ + __FP_FRAC_DEC_3_t2 = x2; \ + __FP_FRAC_SUB_3 (x2, x1, x0, __FP_FRAC_DEC_3_t2, \ + __FP_FRAC_DEC_3_t1, __FP_FRAC_DEC_3_t0, \ + y2, y1, y0); \ + } \ + while (0) +#endif + +#ifndef __FP_FRAC_DEC_4 +# define __FP_FRAC_DEC_4(x3, x2, x1, x0, y3, y2, y1, y0) \ + do \ + { \ + UWtype __FP_FRAC_DEC_4_t0, __FP_FRAC_DEC_4_t1; \ + UWtype __FP_FRAC_DEC_4_t2, __FP_FRAC_DEC_4_t3; \ + __FP_FRAC_DEC_4_t0 = x0; \ + __FP_FRAC_DEC_4_t1 = x1; \ + __FP_FRAC_DEC_4_t2 = x2; \ + __FP_FRAC_DEC_4_t3 = x3; \ + __FP_FRAC_SUB_4 (x3, x2, x1, x0, __FP_FRAC_DEC_4_t3, \ + __FP_FRAC_DEC_4_t2, __FP_FRAC_DEC_4_t1, \ + __FP_FRAC_DEC_4_t0, y3, y2, y1, y0); \ + } \ + while (0) +#endif + +#ifndef __FP_FRAC_ADDI_4 +# define __FP_FRAC_ADDI_4(x3, x2, x1, x0, i) \ + do \ + { \ + UWtype __FP_FRAC_ADDI_4_t; \ + __FP_FRAC_ADDI_4_t = ((x0 += i) < i); \ + x1 += __FP_FRAC_ADDI_4_t; \ + __FP_FRAC_ADDI_4_t = (x1 < __FP_FRAC_ADDI_4_t); \ + x2 += __FP_FRAC_ADDI_4_t; \ + __FP_FRAC_ADDI_4_t = (x2 < __FP_FRAC_ADDI_4_t); \ + x3 += __FP_FRAC_ADDI_4_t; \ + } \ + while (0) +#endif + +/* Convert FP values between word sizes. This appears to be more + complicated than I'd have expected it to be, so these might be + wrong... These macros are in any case somewhat bogus because they + use information about what various FRAC_n variables look like + internally [eg, that 2 word vars are X_f0 and x_f1]. But so do + the ones in op-2.h and op-1.h. */ +#define _FP_FRAC_COPY_1_4(D, S) (D##_f = S##_f[0]) + +#define _FP_FRAC_COPY_2_4(D, S) \ + do \ + { \ + D##_f0 = S##_f[0]; \ + D##_f1 = S##_f[1]; \ + } \ + while (0) + +/* Assembly/disassembly for converting to/from integral types. + No shifting or overflow handled here. */ +/* Put the FP value X into r, which is an integer of size rsize. */ +#define _FP_FRAC_ASSEMBLE_4(r, X, rsize) \ + do \ + { \ + if ((rsize) <= _FP_W_TYPE_SIZE) \ + (r) = X##_f[0]; \ + else if ((rsize) <= 2*_FP_W_TYPE_SIZE) \ + { \ + (r) = X##_f[1]; \ + (r) = ((rsize) <= _FP_W_TYPE_SIZE \ + ? 0 \ + : (r) << _FP_W_TYPE_SIZE); \ + (r) += X##_f[0]; \ + } \ + else \ + { \ + /* I'm feeling lazy so we deal with int == 3words \ + (implausible) and int == 4words as a single case. */ \ + (r) = X##_f[3]; \ + (r) = ((rsize) <= _FP_W_TYPE_SIZE \ + ? 0 \ + : (r) << _FP_W_TYPE_SIZE); \ + (r) += X##_f[2]; \ + (r) = ((rsize) <= _FP_W_TYPE_SIZE \ + ? 0 \ + : (r) << _FP_W_TYPE_SIZE); \ + (r) += X##_f[1]; \ + (r) = ((rsize) <= _FP_W_TYPE_SIZE \ + ? 0 \ + : (r) << _FP_W_TYPE_SIZE); \ + (r) += X##_f[0]; \ + } \ + } \ + while (0) + +/* "No disassemble Number Five!" */ +/* Move an integer of size rsize into X's fractional part. We rely on + the _f[] array consisting of words of size _FP_W_TYPE_SIZE to avoid + having to mask the values we store into it. */ +#define _FP_FRAC_DISASSEMBLE_4(X, r, rsize) \ + do \ + { \ + X##_f[0] = (r); \ + X##_f[1] = ((rsize) <= _FP_W_TYPE_SIZE \ + ? 0 \ + : (r) >> _FP_W_TYPE_SIZE); \ + X##_f[2] = ((rsize) <= 2*_FP_W_TYPE_SIZE \ + ? 0 \ + : (r) >> 2*_FP_W_TYPE_SIZE); \ + X##_f[3] = ((rsize) <= 3*_FP_W_TYPE_SIZE \ + ? 0 \ + : (r) >> 3*_FP_W_TYPE_SIZE); \ + } \ + while (0) + +#define _FP_FRAC_COPY_4_1(D, S) \ + do \ + { \ + D##_f[0] = S##_f; \ + D##_f[1] = D##_f[2] = D##_f[3] = 0; \ + } \ + while (0) + +#define _FP_FRAC_COPY_4_2(D, S) \ + do \ + { \ + D##_f[0] = S##_f0; \ + D##_f[1] = S##_f1; \ + D##_f[2] = D##_f[3] = 0; \ + } \ + while (0) + +#define _FP_FRAC_COPY_4_4(D, S) _FP_FRAC_COPY_4 (D, S) + +#endif /* !SOFT_FP_OP_4_H */ diff --git a/fpu/op-8.h b/fpu/op-8.h new file mode 100644 index 0000000000..4af64ae45c --- /dev/null +++ b/fpu/op-8.h @@ -0,0 +1 @@ +/* Stubbed out because we don't use it in QEMU. */ diff --git a/fpu/op-common.h b/fpu/op-common.h new file mode 100644 index 0000000000..4526afd1b6 --- /dev/null +++ b/fpu/op-common.h @@ -0,0 +1,2134 @@ +/* Software floating-point emulation. Common operations. + Copyright (C) 1997-2018 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Richard Henderson (rth@cygnus.com), + Jakub Jelinek (jj@ultra.linux.cz), + David S. Miller (davem@redhat.com) and + Peter Maydell (pmaydell@chiark.greenend.org.uk). + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + In addition to the permissions in the GNU Lesser General Public + License, the Free Software Foundation gives you unlimited + permission to link the compiled version of this file into + combinations with other programs, and to distribute those + combinations without any restriction coming from the use of this + file. (The Lesser General Public License restrictions do apply in + other respects; for example, they cover modification of the file, + and distribution when not linked into a combine executable.) + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + . */ + +#ifndef SOFT_FP_OP_COMMON_H +#define SOFT_FP_OP_COMMON_H 1 + +#define _FP_DECL(wc, X) \ + _FP_I_TYPE X##_c __attribute__ ((unused)) _FP_ZERO_INIT; \ + _FP_I_TYPE X##_s __attribute__ ((unused)) _FP_ZERO_INIT; \ + _FP_I_TYPE X##_e __attribute__ ((unused)) _FP_ZERO_INIT; \ + _FP_FRAC_DECL_##wc (X) + +/* Test whether the qNaN bit denotes a signaling NaN. */ +#define _FP_FRAC_SNANP(fs, X) \ + ((_FP_QNANNEGATEDP) \ + ? (_FP_FRAC_HIGH_RAW_##fs (X) & _FP_QNANBIT_##fs) \ + : !(_FP_FRAC_HIGH_RAW_##fs (X) & _FP_QNANBIT_##fs)) +#define _FP_FRAC_SNANP_SEMIRAW(fs, X) \ + ((_FP_QNANNEGATEDP) \ + ? (_FP_FRAC_HIGH_##fs (X) & _FP_QNANBIT_SH_##fs) \ + : !(_FP_FRAC_HIGH_##fs (X) & _FP_QNANBIT_SH_##fs)) + +/* Finish truly unpacking a native fp value by classifying the kind + of fp value and normalizing both the exponent and the fraction. */ + +#define _FP_UNPACK_CANONICAL(fs, wc, X) \ + do \ + { \ + switch (X##_e) \ + { \ + default: \ + _FP_FRAC_HIGH_RAW_##fs (X) |= _FP_IMPLBIT_##fs; \ + _FP_FRAC_SLL_##wc (X, _FP_WORKBITS); \ + X##_e -= _FP_EXPBIAS_##fs; \ + X##_c = FP_CLS_NORMAL; \ + break; \ + \ + case 0: \ + if (_FP_FRAC_ZEROP_##wc (X)) \ + X##_c = FP_CLS_ZERO; \ + else if (FP_DENORM_ZERO) \ + { \ + X##_c = FP_CLS_ZERO; \ + _FP_FRAC_SET_##wc (X, _FP_ZEROFRAC_##wc); \ + FP_SET_EXCEPTION (FP_EX_DENORM); \ + } \ + else \ + { \ + /* A denormalized number. */ \ + _FP_I_TYPE _FP_UNPACK_CANONICAL_shift; \ + _FP_FRAC_CLZ_##wc (_FP_UNPACK_CANONICAL_shift, \ + X); \ + _FP_UNPACK_CANONICAL_shift -= _FP_FRACXBITS_##fs; \ + _FP_FRAC_SLL_##wc (X, (_FP_UNPACK_CANONICAL_shift \ + + _FP_WORKBITS)); \ + X##_e -= (_FP_EXPBIAS_##fs - 1 \ + + _FP_UNPACK_CANONICAL_shift); \ + X##_c = FP_CLS_NORMAL; \ + FP_SET_EXCEPTION (FP_EX_DENORM); \ + } \ + break; \ + \ + case _FP_EXPMAX_##fs: \ + if (_FP_FRAC_ZEROP_##wc (X)) \ + X##_c = FP_CLS_INF; \ + else \ + { \ + X##_c = FP_CLS_NAN; \ + /* Check for signaling NaN. */ \ + if (_FP_FRAC_SNANP (fs, X)) \ + FP_SET_EXCEPTION (FP_EX_INVALID \ + | FP_EX_INVALID_SNAN); \ + } \ + break; \ + } \ + } \ + while (0) + +/* Finish unpacking an fp value in semi-raw mode: the mantissa is + shifted by _FP_WORKBITS but the implicit MSB is not inserted and + other classification is not done. */ +#define _FP_UNPACK_SEMIRAW(fs, wc, X) _FP_FRAC_SLL_##wc (X, _FP_WORKBITS) + +/* Check whether a raw or semi-raw input value should be flushed to + zero, and flush it to zero if so. */ +#define _FP_CHECK_FLUSH_ZERO(fs, wc, X) \ + do \ + { \ + if (FP_DENORM_ZERO \ + && X##_e == 0 \ + && !_FP_FRAC_ZEROP_##wc (X)) \ + { \ + _FP_FRAC_SET_##wc (X, _FP_ZEROFRAC_##wc); \ + FP_SET_EXCEPTION (FP_EX_DENORM); \ + } \ + } \ + while (0) + +/* A semi-raw value has overflowed to infinity. Adjust the mantissa + and exponent appropriately. */ +#define _FP_OVERFLOW_SEMIRAW(fs, wc, X) \ + do \ + { \ + if (FP_ROUNDMODE == FP_RND_NEAREST \ + || (FP_ROUNDMODE == FP_RND_PINF && !X##_s) \ + || (FP_ROUNDMODE == FP_RND_MINF && X##_s)) \ + { \ + X##_e = _FP_EXPMAX_##fs; \ + _FP_FRAC_SET_##wc (X, _FP_ZEROFRAC_##wc); \ + } \ + else \ + { \ + X##_e = _FP_EXPMAX_##fs - 1; \ + _FP_FRAC_SET_##wc (X, _FP_MAXFRAC_##wc); \ + } \ + FP_SET_EXCEPTION (FP_EX_INEXACT); \ + FP_SET_EXCEPTION (FP_EX_OVERFLOW); \ + } \ + while (0) + +/* Check for a semi-raw value being a signaling NaN and raise the + invalid exception if so. */ +#define _FP_CHECK_SIGNAN_SEMIRAW(fs, wc, X) \ + do \ + { \ + if (X##_e == _FP_EXPMAX_##fs \ + && !_FP_FRAC_ZEROP_##wc (X) \ + && _FP_FRAC_SNANP_SEMIRAW (fs, X)) \ + FP_SET_EXCEPTION (FP_EX_INVALID | FP_EX_INVALID_SNAN); \ + } \ + while (0) + +/* Choose a NaN result from an operation on two semi-raw NaN + values. */ +#define _FP_CHOOSENAN_SEMIRAW(fs, wc, R, X, Y, OP) \ + do \ + { \ + /* _FP_CHOOSENAN expects raw values, so shift as required. */ \ + _FP_FRAC_SRL_##wc (X, _FP_WORKBITS); \ + _FP_FRAC_SRL_##wc (Y, _FP_WORKBITS); \ + _FP_CHOOSENAN (fs, wc, R, X, Y, OP); \ + _FP_FRAC_SLL_##wc (R, _FP_WORKBITS); \ + } \ + while (0) + +/* Make the fractional part a quiet NaN, preserving the payload + if possible, otherwise make it the canonical quiet NaN and set + the sign bit accordingly. */ +#define _FP_SETQNAN(fs, wc, X) \ + do \ + { \ + if (_FP_QNANNEGATEDP) \ + { \ + _FP_FRAC_HIGH_RAW_##fs (X) &= _FP_QNANBIT_##fs - 1; \ + if (_FP_FRAC_ZEROP_##wc (X)) \ + { \ + X##_s = _FP_NANSIGN_##fs; \ + _FP_FRAC_SET_##wc (X, _FP_NANFRAC_##fs); \ + } \ + } \ + else \ + _FP_FRAC_HIGH_RAW_##fs (X) |= _FP_QNANBIT_##fs; \ + } \ + while (0) +#define _FP_SETQNAN_SEMIRAW(fs, wc, X) \ + do \ + { \ + if (_FP_QNANNEGATEDP) \ + { \ + _FP_FRAC_HIGH_##fs (X) &= _FP_QNANBIT_SH_##fs - 1; \ + if (_FP_FRAC_ZEROP_##wc (X)) \ + { \ + X##_s = _FP_NANSIGN_##fs; \ + _FP_FRAC_SET_##wc (X, _FP_NANFRAC_##fs); \ + _FP_FRAC_SLL_##wc (X, _FP_WORKBITS); \ + } \ + } \ + else \ + _FP_FRAC_HIGH_##fs (X) |= _FP_QNANBIT_SH_##fs; \ + } \ + while (0) + +/* Test whether a biased exponent is normal (not zero or maximum). */ +#define _FP_EXP_NORMAL(fs, wc, X) (((X##_e + 1) & _FP_EXPMAX_##fs) > 1) + +/* Prepare to pack an fp value in semi-raw mode: the mantissa is + rounded and shifted right, with the rounding possibly increasing + the exponent (including changing a finite value to infinity). */ +#define _FP_PACK_SEMIRAW(fs, wc, X) \ + do \ + { \ + int _FP_PACK_SEMIRAW_is_tiny \ + = X##_e == 0 && !_FP_FRAC_ZEROP_##wc (X); \ + if (_FP_TININESS_AFTER_ROUNDING \ + && _FP_PACK_SEMIRAW_is_tiny) \ + { \ + FP_DECL_##fs (_FP_PACK_SEMIRAW_T); \ + _FP_FRAC_COPY_##wc (_FP_PACK_SEMIRAW_T, X); \ + _FP_PACK_SEMIRAW_T##_s = X##_s; \ + _FP_PACK_SEMIRAW_T##_e = X##_e; \ + _FP_FRAC_SLL_##wc (_FP_PACK_SEMIRAW_T, 1); \ + _FP_ROUND (wc, _FP_PACK_SEMIRAW_T); \ + if (_FP_FRAC_OVERP_##wc (fs, _FP_PACK_SEMIRAW_T)) \ + _FP_PACK_SEMIRAW_is_tiny = 0; \ + } \ + _FP_ROUND (wc, X); \ + if (_FP_PACK_SEMIRAW_is_tiny) \ + { \ + if ((FP_CUR_EXCEPTIONS & FP_EX_INEXACT) \ + || (FP_TRAPPING_EXCEPTIONS & FP_EX_UNDERFLOW)) \ + FP_SET_EXCEPTION (FP_EX_UNDERFLOW); \ + } \ + if (_FP_FRAC_HIGH_##fs (X) \ + & (_FP_OVERFLOW_##fs >> 1)) \ + { \ + _FP_FRAC_HIGH_##fs (X) &= ~(_FP_OVERFLOW_##fs >> 1); \ + X##_e++; \ + if (X##_e == _FP_EXPMAX_##fs) \ + _FP_OVERFLOW_SEMIRAW (fs, wc, X); \ + } \ + _FP_FRAC_SRL_##wc (X, _FP_WORKBITS); \ + if (X##_e == _FP_EXPMAX_##fs && !_FP_FRAC_ZEROP_##wc (X)) \ + { \ + if (!_FP_KEEPNANFRACP) \ + { \ + _FP_FRAC_SET_##wc (X, _FP_NANFRAC_##fs); \ + X##_s = _FP_NANSIGN_##fs; \ + } \ + else \ + _FP_SETQNAN (fs, wc, X); \ + } \ + } \ + while (0) + +/* Before packing the bits back into the native fp result, take care + of such mundane things as rounding and overflow. Also, for some + kinds of fp values, the original parts may not have been fully + extracted -- but that is ok, we can regenerate them now. */ + +#define _FP_PACK_CANONICAL(fs, wc, X) \ + do \ + { \ + switch (X##_c) \ + { \ + case FP_CLS_NORMAL: \ + X##_e += _FP_EXPBIAS_##fs; \ + if (X##_e > 0) \ + { \ + _FP_ROUND (wc, X); \ + if (_FP_FRAC_OVERP_##wc (fs, X)) \ + { \ + _FP_FRAC_CLEAR_OVERP_##wc (fs, X); \ + X##_e++; \ + } \ + _FP_FRAC_SRL_##wc (X, _FP_WORKBITS); \ + if (X##_e >= _FP_EXPMAX_##fs) \ + { \ + /* Overflow. */ \ + switch (FP_ROUNDMODE) \ + { \ + case FP_RND_NEAREST: \ + X##_c = FP_CLS_INF; \ + break; \ + case FP_RND_PINF: \ + if (!X##_s) \ + X##_c = FP_CLS_INF; \ + break; \ + case FP_RND_MINF: \ + if (X##_s) \ + X##_c = FP_CLS_INF; \ + break; \ + } \ + if (X##_c == FP_CLS_INF) \ + { \ + /* Overflow to infinity. */ \ + X##_e = _FP_EXPMAX_##fs; \ + _FP_FRAC_SET_##wc (X, _FP_ZEROFRAC_##wc); \ + } \ + else \ + { \ + /* Overflow to maximum normal. */ \ + X##_e = _FP_EXPMAX_##fs - 1; \ + _FP_FRAC_SET_##wc (X, _FP_MAXFRAC_##wc); \ + } \ + FP_SET_EXCEPTION (FP_EX_OVERFLOW); \ + FP_SET_EXCEPTION (FP_EX_INEXACT); \ + } \ + } \ + else \ + { \ + /* We've got a denormalized number. */ \ + int _FP_PACK_CANONICAL_is_tiny = 1; \ + if (_FP_TININESS_AFTER_ROUNDING && X##_e == 0) \ + { \ + FP_DECL_##fs (_FP_PACK_CANONICAL_T); \ + _FP_FRAC_COPY_##wc (_FP_PACK_CANONICAL_T, X); \ + _FP_PACK_CANONICAL_T##_s = X##_s; \ + _FP_PACK_CANONICAL_T##_e = X##_e; \ + _FP_ROUND (wc, _FP_PACK_CANONICAL_T); \ + if (_FP_FRAC_OVERP_##wc (fs, _FP_PACK_CANONICAL_T)) \ + _FP_PACK_CANONICAL_is_tiny = 0; \ + } \ + X##_e = -X##_e + 1; \ + if (X##_e <= _FP_WFRACBITS_##fs) \ + { \ + _FP_FRAC_SRS_##wc (X, X##_e, _FP_WFRACBITS_##fs); \ + _FP_ROUND (wc, X); \ + if (_FP_FRAC_HIGH_##fs (X) \ + & (_FP_OVERFLOW_##fs >> 1)) \ + { \ + X##_e = 1; \ + _FP_FRAC_SET_##wc (X, _FP_ZEROFRAC_##wc); \ + FP_SET_EXCEPTION (FP_EX_INEXACT); \ + } \ + else \ + { \ + X##_e = 0; \ + _FP_FRAC_SRL_##wc (X, _FP_WORKBITS); \ + } \ + if (_FP_PACK_CANONICAL_is_tiny \ + && ((FP_CUR_EXCEPTIONS & FP_EX_INEXACT) \ + || (FP_TRAPPING_EXCEPTIONS \ + & FP_EX_UNDERFLOW))) \ + FP_SET_EXCEPTION (FP_EX_UNDERFLOW); \ + } \ + else \ + { \ + /* Underflow to zero. */ \ + X##_e = 0; \ + if (!_FP_FRAC_ZEROP_##wc (X)) \ + { \ + _FP_FRAC_SET_##wc (X, _FP_MINFRAC_##wc); \ + _FP_ROUND (wc, X); \ + _FP_FRAC_LOW_##wc (X) >>= (_FP_WORKBITS); \ + } \ + FP_SET_EXCEPTION (FP_EX_UNDERFLOW); \ + } \ + } \ + break; \ + \ + case FP_CLS_ZERO: \ + X##_e = 0; \ + _FP_FRAC_SET_##wc (X, _FP_ZEROFRAC_##wc); \ + break; \ + \ + case FP_CLS_INF: \ + X##_e = _FP_EXPMAX_##fs; \ + _FP_FRAC_SET_##wc (X, _FP_ZEROFRAC_##wc); \ + break; \ + \ + case FP_CLS_NAN: \ + X##_e = _FP_EXPMAX_##fs; \ + if (!_FP_KEEPNANFRACP) \ + { \ + _FP_FRAC_SET_##wc (X, _FP_NANFRAC_##fs); \ + X##_s = _FP_NANSIGN_##fs; \ + } \ + else \ + _FP_SETQNAN (fs, wc, X); \ + break; \ + } \ + } \ + while (0) + +/* This one accepts raw argument and not cooked, returns + 1 if X is a signaling NaN. */ +#define _FP_ISSIGNAN(fs, wc, X) \ + ({ \ + int _FP_ISSIGNAN_ret = 0; \ + if (X##_e == _FP_EXPMAX_##fs) \ + { \ + if (!_FP_FRAC_ZEROP_##wc (X) \ + && _FP_FRAC_SNANP (fs, X)) \ + _FP_ISSIGNAN_ret = 1; \ + } \ + _FP_ISSIGNAN_ret; \ + }) + + + + + +/* Addition on semi-raw values. */ +#define _FP_ADD_INTERNAL(fs, wc, R, X, Y, OP) \ + do \ + { \ + _FP_CHECK_FLUSH_ZERO (fs, wc, X); \ + _FP_CHECK_FLUSH_ZERO (fs, wc, Y); \ + if (X##_s == Y##_s) \ + { \ + /* Addition. */ \ + __label__ add1, add2, add3, add_done; \ + R##_s = X##_s; \ + int _FP_ADD_INTERNAL_ediff = X##_e - Y##_e; \ + if (_FP_ADD_INTERNAL_ediff > 0) \ + { \ + R##_e = X##_e; \ + if (Y##_e == 0) \ + { \ + /* Y is zero or denormalized. */ \ + if (_FP_FRAC_ZEROP_##wc (Y)) \ + { \ + _FP_CHECK_SIGNAN_SEMIRAW (fs, wc, X); \ + _FP_FRAC_COPY_##wc (R, X); \ + goto add_done; \ + } \ + else \ + { \ + FP_SET_EXCEPTION (FP_EX_DENORM); \ + _FP_ADD_INTERNAL_ediff--; \ + if (_FP_ADD_INTERNAL_ediff == 0) \ + { \ + _FP_FRAC_ADD_##wc (R, X, Y); \ + goto add3; \ + } \ + if (X##_e == _FP_EXPMAX_##fs) \ + { \ + _FP_CHECK_SIGNAN_SEMIRAW (fs, wc, X); \ + _FP_FRAC_COPY_##wc (R, X); \ + goto add_done; \ + } \ + goto add1; \ + } \ + } \ + else if (X##_e == _FP_EXPMAX_##fs) \ + { \ + /* X is NaN or Inf, Y is normal. */ \ + _FP_CHECK_SIGNAN_SEMIRAW (fs, wc, X); \ + _FP_FRAC_COPY_##wc (R, X); \ + goto add_done; \ + } \ + \ + /* Insert implicit MSB of Y. */ \ + _FP_FRAC_HIGH_##fs (Y) |= _FP_IMPLBIT_SH_##fs; \ + \ + add1: \ + /* Shift the mantissa of Y to the right \ + _FP_ADD_INTERNAL_EDIFF steps; remember to account \ + later for the implicit MSB of X. */ \ + if (_FP_ADD_INTERNAL_ediff <= _FP_WFRACBITS_##fs) \ + _FP_FRAC_SRS_##wc (Y, _FP_ADD_INTERNAL_ediff, \ + _FP_WFRACBITS_##fs); \ + else if (!_FP_FRAC_ZEROP_##wc (Y)) \ + _FP_FRAC_SET_##wc (Y, _FP_MINFRAC_##wc); \ + _FP_FRAC_ADD_##wc (R, X, Y); \ + } \ + else if (_FP_ADD_INTERNAL_ediff < 0) \ + { \ + _FP_ADD_INTERNAL_ediff = -_FP_ADD_INTERNAL_ediff; \ + R##_e = Y##_e; \ + if (X##_e == 0) \ + { \ + /* X is zero or denormalized. */ \ + if (_FP_FRAC_ZEROP_##wc (X)) \ + { \ + _FP_CHECK_SIGNAN_SEMIRAW (fs, wc, Y); \ + _FP_FRAC_COPY_##wc (R, Y); \ + goto add_done; \ + } \ + else \ + { \ + FP_SET_EXCEPTION (FP_EX_DENORM); \ + _FP_ADD_INTERNAL_ediff--; \ + if (_FP_ADD_INTERNAL_ediff == 0) \ + { \ + _FP_FRAC_ADD_##wc (R, Y, X); \ + goto add3; \ + } \ + if (Y##_e == _FP_EXPMAX_##fs) \ + { \ + _FP_CHECK_SIGNAN_SEMIRAW (fs, wc, Y); \ + _FP_FRAC_COPY_##wc (R, Y); \ + goto add_done; \ + } \ + goto add2; \ + } \ + } \ + else if (Y##_e == _FP_EXPMAX_##fs) \ + { \ + /* Y is NaN or Inf, X is normal. */ \ + _FP_CHECK_SIGNAN_SEMIRAW (fs, wc, Y); \ + _FP_FRAC_COPY_##wc (R, Y); \ + goto add_done; \ + } \ + \ + /* Insert implicit MSB of X. */ \ + _FP_FRAC_HIGH_##fs (X) |= _FP_IMPLBIT_SH_##fs; \ + \ + add2: \ + /* Shift the mantissa of X to the right \ + _FP_ADD_INTERNAL_EDIFF steps; remember to account \ + later for the implicit MSB of Y. */ \ + if (_FP_ADD_INTERNAL_ediff <= _FP_WFRACBITS_##fs) \ + _FP_FRAC_SRS_##wc (X, _FP_ADD_INTERNAL_ediff, \ + _FP_WFRACBITS_##fs); \ + else if (!_FP_FRAC_ZEROP_##wc (X)) \ + _FP_FRAC_SET_##wc (X, _FP_MINFRAC_##wc); \ + _FP_FRAC_ADD_##wc (R, Y, X); \ + } \ + else \ + { \ + /* _FP_ADD_INTERNAL_ediff == 0. */ \ + if (!_FP_EXP_NORMAL (fs, wc, X)) \ + { \ + if (X##_e == 0) \ + { \ + /* X and Y are zero or denormalized. */ \ + R##_e = 0; \ + if (_FP_FRAC_ZEROP_##wc (X)) \ + { \ + if (!_FP_FRAC_ZEROP_##wc (Y)) \ + FP_SET_EXCEPTION (FP_EX_DENORM); \ + _FP_FRAC_COPY_##wc (R, Y); \ + goto add_done; \ + } \ + else if (_FP_FRAC_ZEROP_##wc (Y)) \ + { \ + FP_SET_EXCEPTION (FP_EX_DENORM); \ + _FP_FRAC_COPY_##wc (R, X); \ + goto add_done; \ + } \ + else \ + { \ + FP_SET_EXCEPTION (FP_EX_DENORM); \ + _FP_FRAC_ADD_##wc (R, X, Y); \ + if (_FP_FRAC_HIGH_##fs (R) & _FP_IMPLBIT_SH_##fs) \ + { \ + /* Normalized result. */ \ + _FP_FRAC_HIGH_##fs (R) \ + &= ~(_FP_W_TYPE) _FP_IMPLBIT_SH_##fs; \ + R##_e = 1; \ + } \ + goto add_done; \ + } \ + } \ + else \ + { \ + /* X and Y are NaN or Inf. */ \ + _FP_CHECK_SIGNAN_SEMIRAW (fs, wc, X); \ + _FP_CHECK_SIGNAN_SEMIRAW (fs, wc, Y); \ + R##_e = _FP_EXPMAX_##fs; \ + if (_FP_FRAC_ZEROP_##wc (X)) \ + _FP_FRAC_COPY_##wc (R, Y); \ + else if (_FP_FRAC_ZEROP_##wc (Y)) \ + _FP_FRAC_COPY_##wc (R, X); \ + else \ + _FP_CHOOSENAN_SEMIRAW (fs, wc, R, X, Y, OP); \ + goto add_done; \ + } \ + } \ + /* The exponents of X and Y, both normal, are equal. The \ + implicit MSBs will always add to increase the \ + exponent. */ \ + _FP_FRAC_ADD_##wc (R, X, Y); \ + R##_e = X##_e + 1; \ + _FP_FRAC_SRS_##wc (R, 1, _FP_WFRACBITS_##fs); \ + if (R##_e == _FP_EXPMAX_##fs) \ + /* Overflow to infinity (depending on rounding mode). */ \ + _FP_OVERFLOW_SEMIRAW (fs, wc, R); \ + goto add_done; \ + } \ + add3: \ + if (_FP_FRAC_HIGH_##fs (R) & _FP_IMPLBIT_SH_##fs) \ + { \ + /* Overflow. */ \ + _FP_FRAC_HIGH_##fs (R) &= ~(_FP_W_TYPE) _FP_IMPLBIT_SH_##fs; \ + R##_e++; \ + _FP_FRAC_SRS_##wc (R, 1, _FP_WFRACBITS_##fs); \ + if (R##_e == _FP_EXPMAX_##fs) \ + /* Overflow to infinity (depending on rounding mode). */ \ + _FP_OVERFLOW_SEMIRAW (fs, wc, R); \ + } \ + add_done: ; \ + } \ + else \ + { \ + /* Subtraction. */ \ + __label__ sub1, sub2, sub3, norm, sub_done; \ + int _FP_ADD_INTERNAL_ediff = X##_e - Y##_e; \ + if (_FP_ADD_INTERNAL_ediff > 0) \ + { \ + R##_e = X##_e; \ + R##_s = X##_s; \ + if (Y##_e == 0) \ + { \ + /* Y is zero or denormalized. */ \ + if (_FP_FRAC_ZEROP_##wc (Y)) \ + { \ + _FP_CHECK_SIGNAN_SEMIRAW (fs, wc, X); \ + _FP_FRAC_COPY_##wc (R, X); \ + goto sub_done; \ + } \ + else \ + { \ + FP_SET_EXCEPTION (FP_EX_DENORM); \ + _FP_ADD_INTERNAL_ediff--; \ + if (_FP_ADD_INTERNAL_ediff == 0) \ + { \ + _FP_FRAC_SUB_##wc (R, X, Y); \ + goto sub3; \ + } \ + if (X##_e == _FP_EXPMAX_##fs) \ + { \ + _FP_CHECK_SIGNAN_SEMIRAW (fs, wc, X); \ + _FP_FRAC_COPY_##wc (R, X); \ + goto sub_done; \ + } \ + goto sub1; \ + } \ + } \ + else if (X##_e == _FP_EXPMAX_##fs) \ + { \ + /* X is NaN or Inf, Y is normal. */ \ + _FP_CHECK_SIGNAN_SEMIRAW (fs, wc, X); \ + _FP_FRAC_COPY_##wc (R, X); \ + goto sub_done; \ + } \ + \ + /* Insert implicit MSB of Y. */ \ + _FP_FRAC_HIGH_##fs (Y) |= _FP_IMPLBIT_SH_##fs; \ + \ + sub1: \ + /* Shift the mantissa of Y to the right \ + _FP_ADD_INTERNAL_EDIFF steps; remember to account \ + later for the implicit MSB of X. */ \ + if (_FP_ADD_INTERNAL_ediff <= _FP_WFRACBITS_##fs) \ + _FP_FRAC_SRS_##wc (Y, _FP_ADD_INTERNAL_ediff, \ + _FP_WFRACBITS_##fs); \ + else if (!_FP_FRAC_ZEROP_##wc (Y)) \ + _FP_FRAC_SET_##wc (Y, _FP_MINFRAC_##wc); \ + _FP_FRAC_SUB_##wc (R, X, Y); \ + } \ + else if (_FP_ADD_INTERNAL_ediff < 0) \ + { \ + _FP_ADD_INTERNAL_ediff = -_FP_ADD_INTERNAL_ediff; \ + R##_e = Y##_e; \ + R##_s = Y##_s; \ + if (X##_e == 0) \ + { \ + /* X is zero or denormalized. */ \ + if (_FP_FRAC_ZEROP_##wc (X)) \ + { \ + _FP_CHECK_SIGNAN_SEMIRAW (fs, wc, Y); \ + _FP_FRAC_COPY_##wc (R, Y); \ + goto sub_done; \ + } \ + else \ + { \ + FP_SET_EXCEPTION (FP_EX_DENORM); \ + _FP_ADD_INTERNAL_ediff--; \ + if (_FP_ADD_INTERNAL_ediff == 0) \ + { \ + _FP_FRAC_SUB_##wc (R, Y, X); \ + goto sub3; \ + } \ + if (Y##_e == _FP_EXPMAX_##fs) \ + { \ + _FP_CHECK_SIGNAN_SEMIRAW (fs, wc, Y); \ + _FP_FRAC_COPY_##wc (R, Y); \ + goto sub_done; \ + } \ + goto sub2; \ + } \ + } \ + else if (Y##_e == _FP_EXPMAX_##fs) \ + { \ + /* Y is NaN or Inf, X is normal. */ \ + _FP_CHECK_SIGNAN_SEMIRAW (fs, wc, Y); \ + _FP_FRAC_COPY_##wc (R, Y); \ + goto sub_done; \ + } \ + \ + /* Insert implicit MSB of X. */ \ + _FP_FRAC_HIGH_##fs (X) |= _FP_IMPLBIT_SH_##fs; \ + \ + sub2: \ + /* Shift the mantissa of X to the right \ + _FP_ADD_INTERNAL_EDIFF steps; remember to account \ + later for the implicit MSB of Y. */ \ + if (_FP_ADD_INTERNAL_ediff <= _FP_WFRACBITS_##fs) \ + _FP_FRAC_SRS_##wc (X, _FP_ADD_INTERNAL_ediff, \ + _FP_WFRACBITS_##fs); \ + else if (!_FP_FRAC_ZEROP_##wc (X)) \ + _FP_FRAC_SET_##wc (X, _FP_MINFRAC_##wc); \ + _FP_FRAC_SUB_##wc (R, Y, X); \ + } \ + else \ + { \ + /* ediff == 0. */ \ + if (!_FP_EXP_NORMAL (fs, wc, X)) \ + { \ + if (X##_e == 0) \ + { \ + /* X and Y are zero or denormalized. */ \ + R##_e = 0; \ + if (_FP_FRAC_ZEROP_##wc (X)) \ + { \ + _FP_FRAC_COPY_##wc (R, Y); \ + if (_FP_FRAC_ZEROP_##wc (Y)) \ + R##_s = (FP_ROUNDMODE == FP_RND_MINF); \ + else \ + { \ + FP_SET_EXCEPTION (FP_EX_DENORM); \ + R##_s = Y##_s; \ + } \ + goto sub_done; \ + } \ + else if (_FP_FRAC_ZEROP_##wc (Y)) \ + { \ + FP_SET_EXCEPTION (FP_EX_DENORM); \ + _FP_FRAC_COPY_##wc (R, X); \ + R##_s = X##_s; \ + goto sub_done; \ + } \ + else \ + { \ + FP_SET_EXCEPTION (FP_EX_DENORM); \ + _FP_FRAC_SUB_##wc (R, X, Y); \ + R##_s = X##_s; \ + if (_FP_FRAC_HIGH_##fs (R) & _FP_IMPLBIT_SH_##fs) \ + { \ + /* |X| < |Y|, negate result. */ \ + _FP_FRAC_SUB_##wc (R, Y, X); \ + R##_s = Y##_s; \ + } \ + else if (_FP_FRAC_ZEROP_##wc (R)) \ + R##_s = (FP_ROUNDMODE == FP_RND_MINF); \ + goto sub_done; \ + } \ + } \ + else \ + { \ + /* X and Y are NaN or Inf, of opposite signs. */ \ + _FP_CHECK_SIGNAN_SEMIRAW (fs, wc, X); \ + _FP_CHECK_SIGNAN_SEMIRAW (fs, wc, Y); \ + R##_e = _FP_EXPMAX_##fs; \ + if (_FP_FRAC_ZEROP_##wc (X)) \ + { \ + if (_FP_FRAC_ZEROP_##wc (Y)) \ + { \ + /* Inf - Inf. */ \ + R##_s = _FP_NANSIGN_##fs; \ + _FP_FRAC_SET_##wc (R, _FP_NANFRAC_##fs); \ + _FP_FRAC_SLL_##wc (R, _FP_WORKBITS); \ + FP_SET_EXCEPTION (FP_EX_INVALID \ + | FP_EX_INVALID_ISI); \ + } \ + else \ + { \ + /* Inf - NaN. */ \ + R##_s = Y##_s; \ + _FP_FRAC_COPY_##wc (R, Y); \ + } \ + } \ + else \ + { \ + if (_FP_FRAC_ZEROP_##wc (Y)) \ + { \ + /* NaN - Inf. */ \ + R##_s = X##_s; \ + _FP_FRAC_COPY_##wc (R, X); \ + } \ + else \ + { \ + /* NaN - NaN. */ \ + _FP_CHOOSENAN_SEMIRAW (fs, wc, R, X, Y, OP); \ + } \ + } \ + goto sub_done; \ + } \ + } \ + /* The exponents of X and Y, both normal, are equal. The \ + implicit MSBs cancel. */ \ + R##_e = X##_e; \ + _FP_FRAC_SUB_##wc (R, X, Y); \ + R##_s = X##_s; \ + if (_FP_FRAC_HIGH_##fs (R) & _FP_IMPLBIT_SH_##fs) \ + { \ + /* |X| < |Y|, negate result. */ \ + _FP_FRAC_SUB_##wc (R, Y, X); \ + R##_s = Y##_s; \ + } \ + else if (_FP_FRAC_ZEROP_##wc (R)) \ + { \ + R##_e = 0; \ + R##_s = (FP_ROUNDMODE == FP_RND_MINF); \ + goto sub_done; \ + } \ + goto norm; \ + } \ + sub3: \ + if (_FP_FRAC_HIGH_##fs (R) & _FP_IMPLBIT_SH_##fs) \ + { \ + int _FP_ADD_INTERNAL_diff; \ + /* Carry into most significant bit of larger one of X and Y, \ + canceling it; renormalize. */ \ + _FP_FRAC_HIGH_##fs (R) &= _FP_IMPLBIT_SH_##fs - 1; \ + norm: \ + _FP_FRAC_CLZ_##wc (_FP_ADD_INTERNAL_diff, R); \ + _FP_ADD_INTERNAL_diff -= _FP_WFRACXBITS_##fs; \ + _FP_FRAC_SLL_##wc (R, _FP_ADD_INTERNAL_diff); \ + if (R##_e <= _FP_ADD_INTERNAL_diff) \ + { \ + /* R is denormalized. */ \ + _FP_ADD_INTERNAL_diff \ + = _FP_ADD_INTERNAL_diff - R##_e + 1; \ + _FP_FRAC_SRS_##wc (R, _FP_ADD_INTERNAL_diff, \ + _FP_WFRACBITS_##fs); \ + R##_e = 0; \ + } \ + else \ + { \ + R##_e -= _FP_ADD_INTERNAL_diff; \ + _FP_FRAC_HIGH_##fs (R) &= ~(_FP_W_TYPE) _FP_IMPLBIT_SH_##fs; \ + } \ + } \ + sub_done: ; \ + } \ + } \ + while (0) + +#define _FP_ADD(fs, wc, R, X, Y) _FP_ADD_INTERNAL (fs, wc, R, X, Y, '+') +#define _FP_SUB(fs, wc, R, X, Y) \ + do \ + { \ + if (!(Y##_e == _FP_EXPMAX_##fs && !_FP_FRAC_ZEROP_##wc (Y))) \ + Y##_s ^= 1; \ + _FP_ADD_INTERNAL (fs, wc, R, X, Y, '-'); \ + } \ + while (0) + + +/* Main negation routine. The input value is raw. */ + +#define _FP_NEG(fs, wc, R, X) \ + do \ + { \ + _FP_FRAC_COPY_##wc (R, X); \ + R##_e = X##_e; \ + R##_s = 1 ^ X##_s; \ + } \ + while (0) + + +/* Main multiplication routine. The input values should be cooked. */ + +#define _FP_MUL(fs, wc, R, X, Y) \ + do \ + { \ + R##_s = X##_s ^ Y##_s; \ + R##_e = X##_e + Y##_e + 1; \ + switch (_FP_CLS_COMBINE (X##_c, Y##_c)) \ + { \ + case _FP_CLS_COMBINE (FP_CLS_NORMAL, FP_CLS_NORMAL): \ + R##_c = FP_CLS_NORMAL; \ + \ + _FP_MUL_MEAT_##fs (R, X, Y); \ + \ + if (_FP_FRAC_OVERP_##wc (fs, R)) \ + _FP_FRAC_SRS_##wc (R, 1, _FP_WFRACBITS_##fs); \ + else \ + R##_e--; \ + break; \ + \ + case _FP_CLS_COMBINE (FP_CLS_NAN, FP_CLS_NAN): \ + _FP_CHOOSENAN (fs, wc, R, X, Y, '*'); \ + break; \ + \ + case _FP_CLS_COMBINE (FP_CLS_NAN, FP_CLS_NORMAL): \ + case _FP_CLS_COMBINE (FP_CLS_NAN, FP_CLS_INF): \ + case _FP_CLS_COMBINE (FP_CLS_NAN, FP_CLS_ZERO): \ + R##_s = X##_s; \ + /* FALLTHRU */ \ + \ + case _FP_CLS_COMBINE (FP_CLS_INF, FP_CLS_INF): \ + case _FP_CLS_COMBINE (FP_CLS_INF, FP_CLS_NORMAL): \ + case _FP_CLS_COMBINE (FP_CLS_ZERO, FP_CLS_NORMAL): \ + case _FP_CLS_COMBINE (FP_CLS_ZERO, FP_CLS_ZERO): \ + _FP_FRAC_COPY_##wc (R, X); \ + R##_c = X##_c; \ + break; \ + \ + case _FP_CLS_COMBINE (FP_CLS_NORMAL, FP_CLS_NAN): \ + case _FP_CLS_COMBINE (FP_CLS_INF, FP_CLS_NAN): \ + case _FP_CLS_COMBINE (FP_CLS_ZERO, FP_CLS_NAN): \ + R##_s = Y##_s; \ + /* FALLTHRU */ \ + \ + case _FP_CLS_COMBINE (FP_CLS_NORMAL, FP_CLS_INF): \ + case _FP_CLS_COMBINE (FP_CLS_NORMAL, FP_CLS_ZERO): \ + _FP_FRAC_COPY_##wc (R, Y); \ + R##_c = Y##_c; \ + break; \ + \ + case _FP_CLS_COMBINE (FP_CLS_INF, FP_CLS_ZERO): \ + case _FP_CLS_COMBINE (FP_CLS_ZERO, FP_CLS_INF): \ + R##_s = _FP_NANSIGN_##fs; \ + R##_c = FP_CLS_NAN; \ + _FP_FRAC_SET_##wc (R, _FP_NANFRAC_##fs); \ + FP_SET_EXCEPTION (FP_EX_INVALID | FP_EX_INVALID_IMZ); \ + break; \ + \ + default: \ + _FP_UNREACHABLE; \ + } \ + } \ + while (0) + + +/* Fused multiply-add. The input values should be cooked. */ + +#define _FP_FMA(fs, wc, dwc, R, X, Y, Z) \ + do \ + { \ + __label__ done_fma; \ + FP_DECL_##fs (_FP_FMA_T); \ + _FP_FMA_T##_s = X##_s ^ Y##_s; \ + _FP_FMA_T##_e = X##_e + Y##_e + 1; \ + switch (_FP_CLS_COMBINE (X##_c, Y##_c)) \ + { \ + case _FP_CLS_COMBINE (FP_CLS_NORMAL, FP_CLS_NORMAL): \ + switch (Z##_c) \ + { \ + case FP_CLS_INF: \ + case FP_CLS_NAN: \ + R##_s = Z##_s; \ + _FP_FRAC_COPY_##wc (R, Z); \ + R##_c = Z##_c; \ + break; \ + \ + case FP_CLS_ZERO: \ + R##_c = FP_CLS_NORMAL; \ + R##_s = _FP_FMA_T##_s; \ + R##_e = _FP_FMA_T##_e; \ + \ + _FP_MUL_MEAT_##fs (R, X, Y); \ + \ + if (_FP_FRAC_OVERP_##wc (fs, R)) \ + _FP_FRAC_SRS_##wc (R, 1, _FP_WFRACBITS_##fs); \ + else \ + R##_e--; \ + break; \ + \ + case FP_CLS_NORMAL:; \ + _FP_FRAC_DECL_##dwc (_FP_FMA_TD); \ + _FP_FRAC_DECL_##dwc (_FP_FMA_ZD); \ + _FP_FRAC_DECL_##dwc (_FP_FMA_RD); \ + _FP_MUL_MEAT_DW_##fs (_FP_FMA_TD, X, Y); \ + R##_e = _FP_FMA_T##_e; \ + int _FP_FMA_tsh \ + = _FP_FRAC_HIGHBIT_DW_##dwc (fs, _FP_FMA_TD) == 0; \ + _FP_FMA_T##_e -= _FP_FMA_tsh; \ + int _FP_FMA_ediff = _FP_FMA_T##_e - Z##_e; \ + if (_FP_FMA_ediff >= 0) \ + { \ + int _FP_FMA_shift \ + = _FP_WFRACBITS_##fs - _FP_FMA_tsh - _FP_FMA_ediff; \ + if (_FP_FMA_shift <= -_FP_WFRACBITS_##fs) \ + _FP_FRAC_SET_##dwc (_FP_FMA_ZD, _FP_MINFRAC_##dwc); \ + else \ + { \ + _FP_FRAC_COPY_##dwc##_##wc (_FP_FMA_ZD, Z); \ + if (_FP_FMA_shift < 0) \ + _FP_FRAC_SRS_##dwc (_FP_FMA_ZD, -_FP_FMA_shift, \ + _FP_WFRACBITS_DW_##fs); \ + else if (_FP_FMA_shift > 0) \ + _FP_FRAC_SLL_##dwc (_FP_FMA_ZD, _FP_FMA_shift); \ + } \ + R##_s = _FP_FMA_T##_s; \ + if (_FP_FMA_T##_s == Z##_s) \ + _FP_FRAC_ADD_##dwc (_FP_FMA_RD, _FP_FMA_TD, \ + _FP_FMA_ZD); \ + else \ + { \ + _FP_FRAC_SUB_##dwc (_FP_FMA_RD, _FP_FMA_TD, \ + _FP_FMA_ZD); \ + if (_FP_FRAC_NEGP_##dwc (_FP_FMA_RD)) \ + { \ + R##_s = Z##_s; \ + _FP_FRAC_SUB_##dwc (_FP_FMA_RD, _FP_FMA_ZD, \ + _FP_FMA_TD); \ + } \ + } \ + } \ + else \ + { \ + R##_e = Z##_e; \ + R##_s = Z##_s; \ + _FP_FRAC_COPY_##dwc##_##wc (_FP_FMA_ZD, Z); \ + _FP_FRAC_SLL_##dwc (_FP_FMA_ZD, _FP_WFRACBITS_##fs); \ + int _FP_FMA_shift = -_FP_FMA_ediff - _FP_FMA_tsh; \ + if (_FP_FMA_shift >= _FP_WFRACBITS_DW_##fs) \ + _FP_FRAC_SET_##dwc (_FP_FMA_TD, _FP_MINFRAC_##dwc); \ + else if (_FP_FMA_shift > 0) \ + _FP_FRAC_SRS_##dwc (_FP_FMA_TD, _FP_FMA_shift, \ + _FP_WFRACBITS_DW_##fs); \ + if (Z##_s == _FP_FMA_T##_s) \ + _FP_FRAC_ADD_##dwc (_FP_FMA_RD, _FP_FMA_ZD, \ + _FP_FMA_TD); \ + else \ + _FP_FRAC_SUB_##dwc (_FP_FMA_RD, _FP_FMA_ZD, \ + _FP_FMA_TD); \ + } \ + if (_FP_FRAC_ZEROP_##dwc (_FP_FMA_RD)) \ + { \ + if (_FP_FMA_T##_s == Z##_s) \ + R##_s = Z##_s; \ + else \ + R##_s = (FP_ROUNDMODE == FP_RND_MINF); \ + _FP_FRAC_SET_##wc (R, _FP_ZEROFRAC_##wc); \ + R##_c = FP_CLS_ZERO; \ + } \ + else \ + { \ + int _FP_FMA_rlz; \ + _FP_FRAC_CLZ_##dwc (_FP_FMA_rlz, _FP_FMA_RD); \ + _FP_FMA_rlz -= _FP_WFRACXBITS_DW_##fs; \ + R##_e -= _FP_FMA_rlz; \ + int _FP_FMA_shift = _FP_WFRACBITS_##fs - _FP_FMA_rlz; \ + if (_FP_FMA_shift > 0) \ + _FP_FRAC_SRS_##dwc (_FP_FMA_RD, _FP_FMA_shift, \ + _FP_WFRACBITS_DW_##fs); \ + else if (_FP_FMA_shift < 0) \ + _FP_FRAC_SLL_##dwc (_FP_FMA_RD, -_FP_FMA_shift); \ + _FP_FRAC_COPY_##wc##_##dwc (R, _FP_FMA_RD); \ + R##_c = FP_CLS_NORMAL; \ + } \ + break; \ + } \ + goto done_fma; \ + \ + case _FP_CLS_COMBINE (FP_CLS_NAN, FP_CLS_NAN): \ + _FP_CHOOSENAN (fs, wc, _FP_FMA_T, X, Y, '*'); \ + break; \ + \ + case _FP_CLS_COMBINE (FP_CLS_NAN, FP_CLS_NORMAL): \ + case _FP_CLS_COMBINE (FP_CLS_NAN, FP_CLS_INF): \ + case _FP_CLS_COMBINE (FP_CLS_NAN, FP_CLS_ZERO): \ + _FP_FMA_T##_s = X##_s; \ + /* FALLTHRU */ \ + \ + case _FP_CLS_COMBINE (FP_CLS_INF, FP_CLS_INF): \ + case _FP_CLS_COMBINE (FP_CLS_INF, FP_CLS_NORMAL): \ + case _FP_CLS_COMBINE (FP_CLS_ZERO, FP_CLS_NORMAL): \ + case _FP_CLS_COMBINE (FP_CLS_ZERO, FP_CLS_ZERO): \ + _FP_FRAC_COPY_##wc (_FP_FMA_T, X); \ + _FP_FMA_T##_c = X##_c; \ + break; \ + \ + case _FP_CLS_COMBINE (FP_CLS_NORMAL, FP_CLS_NAN): \ + case _FP_CLS_COMBINE (FP_CLS_INF, FP_CLS_NAN): \ + case _FP_CLS_COMBINE (FP_CLS_ZERO, FP_CLS_NAN): \ + _FP_FMA_T##_s = Y##_s; \ + /* FALLTHRU */ \ + \ + case _FP_CLS_COMBINE (FP_CLS_NORMAL, FP_CLS_INF): \ + case _FP_CLS_COMBINE (FP_CLS_NORMAL, FP_CLS_ZERO): \ + _FP_FRAC_COPY_##wc (_FP_FMA_T, Y); \ + _FP_FMA_T##_c = Y##_c; \ + break; \ + \ + case _FP_CLS_COMBINE (FP_CLS_INF, FP_CLS_ZERO): \ + case _FP_CLS_COMBINE (FP_CLS_ZERO, FP_CLS_INF): \ + _FP_FMA_T##_s = _FP_NANSIGN_##fs; \ + _FP_FMA_T##_c = FP_CLS_NAN; \ + _FP_FRAC_SET_##wc (_FP_FMA_T, _FP_NANFRAC_##fs); \ + FP_SET_EXCEPTION (FP_EX_INVALID | FP_EX_INVALID_IMZ_FMA); \ + break; \ + \ + default: \ + _FP_UNREACHABLE; \ + } \ + \ + /* T = X * Y is zero, infinity or NaN. */ \ + switch (_FP_CLS_COMBINE (_FP_FMA_T##_c, Z##_c)) \ + { \ + case _FP_CLS_COMBINE (FP_CLS_NAN, FP_CLS_NAN): \ + _FP_CHOOSENAN (fs, wc, R, _FP_FMA_T, Z, '+'); \ + break; \ + \ + case _FP_CLS_COMBINE (FP_CLS_NAN, FP_CLS_NORMAL): \ + case _FP_CLS_COMBINE (FP_CLS_NAN, FP_CLS_INF): \ + case _FP_CLS_COMBINE (FP_CLS_NAN, FP_CLS_ZERO): \ + case _FP_CLS_COMBINE (FP_CLS_INF, FP_CLS_NORMAL): \ + case _FP_CLS_COMBINE (FP_CLS_INF, FP_CLS_ZERO): \ + R##_s = _FP_FMA_T##_s; \ + _FP_FRAC_COPY_##wc (R, _FP_FMA_T); \ + R##_c = _FP_FMA_T##_c; \ + break; \ + \ + case _FP_CLS_COMBINE (FP_CLS_INF, FP_CLS_NAN): \ + case _FP_CLS_COMBINE (FP_CLS_ZERO, FP_CLS_NAN): \ + case _FP_CLS_COMBINE (FP_CLS_ZERO, FP_CLS_NORMAL): \ + case _FP_CLS_COMBINE (FP_CLS_ZERO, FP_CLS_INF): \ + R##_s = Z##_s; \ + _FP_FRAC_COPY_##wc (R, Z); \ + R##_c = Z##_c; \ + R##_e = Z##_e; \ + break; \ + \ + case _FP_CLS_COMBINE (FP_CLS_INF, FP_CLS_INF): \ + if (_FP_FMA_T##_s == Z##_s) \ + { \ + R##_s = Z##_s; \ + _FP_FRAC_COPY_##wc (R, Z); \ + R##_c = Z##_c; \ + } \ + else \ + { \ + R##_s = _FP_NANSIGN_##fs; \ + R##_c = FP_CLS_NAN; \ + _FP_FRAC_SET_##wc (R, _FP_NANFRAC_##fs); \ + FP_SET_EXCEPTION (FP_EX_INVALID | FP_EX_INVALID_ISI); \ + } \ + break; \ + \ + case _FP_CLS_COMBINE (FP_CLS_ZERO, FP_CLS_ZERO): \ + if (_FP_FMA_T##_s == Z##_s) \ + R##_s = Z##_s; \ + else \ + R##_s = (FP_ROUNDMODE == FP_RND_MINF); \ + _FP_FRAC_COPY_##wc (R, Z); \ + R##_c = Z##_c; \ + break; \ + \ + default: \ + _FP_UNREACHABLE; \ + } \ + done_fma: ; \ + } \ + while (0) + + +/* Main division routine. The input values should be cooked. */ + +#define _FP_DIV(fs, wc, R, X, Y) \ + do \ + { \ + R##_s = X##_s ^ Y##_s; \ + R##_e = X##_e - Y##_e; \ + switch (_FP_CLS_COMBINE (X##_c, Y##_c)) \ + { \ + case _FP_CLS_COMBINE (FP_CLS_NORMAL, FP_CLS_NORMAL): \ + R##_c = FP_CLS_NORMAL; \ + \ + _FP_DIV_MEAT_##fs (R, X, Y); \ + break; \ + \ + case _FP_CLS_COMBINE (FP_CLS_NAN, FP_CLS_NAN): \ + _FP_CHOOSENAN (fs, wc, R, X, Y, '/'); \ + break; \ + \ + case _FP_CLS_COMBINE (FP_CLS_NAN, FP_CLS_NORMAL): \ + case _FP_CLS_COMBINE (FP_CLS_NAN, FP_CLS_INF): \ + case _FP_CLS_COMBINE (FP_CLS_NAN, FP_CLS_ZERO): \ + R##_s = X##_s; \ + _FP_FRAC_COPY_##wc (R, X); \ + R##_c = X##_c; \ + break; \ + \ + case _FP_CLS_COMBINE (FP_CLS_NORMAL, FP_CLS_NAN): \ + case _FP_CLS_COMBINE (FP_CLS_INF, FP_CLS_NAN): \ + case _FP_CLS_COMBINE (FP_CLS_ZERO, FP_CLS_NAN): \ + R##_s = Y##_s; \ + _FP_FRAC_COPY_##wc (R, Y); \ + R##_c = Y##_c; \ + break; \ + \ + case _FP_CLS_COMBINE (FP_CLS_NORMAL, FP_CLS_INF): \ + case _FP_CLS_COMBINE (FP_CLS_ZERO, FP_CLS_INF): \ + case _FP_CLS_COMBINE (FP_CLS_ZERO, FP_CLS_NORMAL): \ + R##_c = FP_CLS_ZERO; \ + break; \ + \ + case _FP_CLS_COMBINE (FP_CLS_NORMAL, FP_CLS_ZERO): \ + FP_SET_EXCEPTION (FP_EX_DIVZERO); \ + /* FALLTHRU */ \ + case _FP_CLS_COMBINE (FP_CLS_INF, FP_CLS_ZERO): \ + case _FP_CLS_COMBINE (FP_CLS_INF, FP_CLS_NORMAL): \ + R##_c = FP_CLS_INF; \ + break; \ + \ + case _FP_CLS_COMBINE (FP_CLS_INF, FP_CLS_INF): \ + case _FP_CLS_COMBINE (FP_CLS_ZERO, FP_CLS_ZERO): \ + R##_s = _FP_NANSIGN_##fs; \ + R##_c = FP_CLS_NAN; \ + _FP_FRAC_SET_##wc (R, _FP_NANFRAC_##fs); \ + FP_SET_EXCEPTION (FP_EX_INVALID \ + | (X##_c == FP_CLS_INF \ + ? FP_EX_INVALID_IDI \ + : FP_EX_INVALID_ZDZ)); \ + break; \ + \ + default: \ + _FP_UNREACHABLE; \ + } \ + } \ + while (0) + + +/* Helper for comparisons. EX is 0 not to raise exceptions, 1 to + raise exceptions for signaling NaN operands, 2 to raise exceptions + for all NaN operands. Conditionals are organized to allow the + compiler to optimize away code based on the value of EX. */ + +#define _FP_CMP_CHECK_NAN(fs, wc, X, Y, ex) \ + do \ + { \ + /* The arguments are unordered, which may or may not result in \ + an exception. */ \ + if (ex) \ + { \ + /* At least some cases of unordered arguments result in \ + exceptions; check whether this is one. */ \ + if (FP_EX_INVALID_SNAN || FP_EX_INVALID_VC) \ + { \ + /* Check separately for each case of "invalid" \ + exceptions. */ \ + if ((ex) == 2) \ + FP_SET_EXCEPTION (FP_EX_INVALID | FP_EX_INVALID_VC); \ + if (_FP_ISSIGNAN (fs, wc, X) \ + || _FP_ISSIGNAN (fs, wc, Y)) \ + FP_SET_EXCEPTION (FP_EX_INVALID | FP_EX_INVALID_SNAN); \ + } \ + /* Otherwise, we only need to check whether to raise an \ + exception, not which case or cases it is. */ \ + else if ((ex) == 2 \ + || _FP_ISSIGNAN (fs, wc, X) \ + || _FP_ISSIGNAN (fs, wc, Y)) \ + FP_SET_EXCEPTION (FP_EX_INVALID); \ + } \ + } \ + while (0) + +/* Helper for comparisons. If denormal operands would raise an + exception, check for them, and flush to zero as appropriate + (otherwise, we need only check and flush to zero if it might affect + the result, which is done later with _FP_CMP_CHECK_FLUSH_ZERO). */ +#define _FP_CMP_CHECK_DENORM(fs, wc, X, Y) \ + do \ + { \ + if (FP_EX_DENORM != 0) \ + { \ + /* We must ensure the correct exceptions are raised for \ + denormal operands, even though this may not affect the \ + result of the comparison. */ \ + if (FP_DENORM_ZERO) \ + { \ + _FP_CHECK_FLUSH_ZERO (fs, wc, X); \ + _FP_CHECK_FLUSH_ZERO (fs, wc, Y); \ + } \ + else \ + { \ + if ((X##_e == 0 && !_FP_FRAC_ZEROP_##wc (X)) \ + || (Y##_e == 0 && !_FP_FRAC_ZEROP_##wc (Y))) \ + FP_SET_EXCEPTION (FP_EX_DENORM); \ + } \ + } \ + } \ + while (0) + +/* Helper for comparisons. Check for flushing denormals for zero if + we didn't need to check earlier for any denormal operands. */ +#define _FP_CMP_CHECK_FLUSH_ZERO(fs, wc, X, Y) \ + do \ + { \ + if (FP_EX_DENORM == 0) \ + { \ + _FP_CHECK_FLUSH_ZERO (fs, wc, X); \ + _FP_CHECK_FLUSH_ZERO (fs, wc, Y); \ + } \ + } \ + while (0) + +/* Main differential comparison routine. The inputs should be raw not + cooked. The return is -1, 0, 1 for normal values, UN + otherwise. */ + +#define _FP_CMP(fs, wc, ret, X, Y, un, ex) \ + do \ + { \ + _FP_CMP_CHECK_DENORM (fs, wc, X, Y); \ + /* NANs are unordered. */ \ + if ((X##_e == _FP_EXPMAX_##fs && !_FP_FRAC_ZEROP_##wc (X)) \ + || (Y##_e == _FP_EXPMAX_##fs && !_FP_FRAC_ZEROP_##wc (Y))) \ + { \ + (ret) = (un); \ + _FP_CMP_CHECK_NAN (fs, wc, X, Y, (ex)); \ + } \ + else \ + { \ + int _FP_CMP_is_zero_x; \ + int _FP_CMP_is_zero_y; \ + \ + _FP_CMP_CHECK_FLUSH_ZERO (fs, wc, X, Y); \ + \ + _FP_CMP_is_zero_x \ + = (!X##_e && _FP_FRAC_ZEROP_##wc (X)) ? 1 : 0; \ + _FP_CMP_is_zero_y \ + = (!Y##_e && _FP_FRAC_ZEROP_##wc (Y)) ? 1 : 0; \ + \ + if (_FP_CMP_is_zero_x && _FP_CMP_is_zero_y) \ + (ret) = 0; \ + else if (_FP_CMP_is_zero_x) \ + (ret) = Y##_s ? 1 : -1; \ + else if (_FP_CMP_is_zero_y) \ + (ret) = X##_s ? -1 : 1; \ + else if (X##_s != Y##_s) \ + (ret) = X##_s ? -1 : 1; \ + else if (X##_e > Y##_e) \ + (ret) = X##_s ? -1 : 1; \ + else if (X##_e < Y##_e) \ + (ret) = X##_s ? 1 : -1; \ + else if (_FP_FRAC_GT_##wc (X, Y)) \ + (ret) = X##_s ? -1 : 1; \ + else if (_FP_FRAC_GT_##wc (Y, X)) \ + (ret) = X##_s ? 1 : -1; \ + else \ + (ret) = 0; \ + } \ + } \ + while (0) + + +/* Simplification for strict equality. */ + +#define _FP_CMP_EQ(fs, wc, ret, X, Y, ex) \ + do \ + { \ + _FP_CMP_CHECK_DENORM (fs, wc, X, Y); \ + /* NANs are unordered. */ \ + if ((X##_e == _FP_EXPMAX_##fs && !_FP_FRAC_ZEROP_##wc (X)) \ + || (Y##_e == _FP_EXPMAX_##fs && !_FP_FRAC_ZEROP_##wc (Y))) \ + { \ + (ret) = 1; \ + _FP_CMP_CHECK_NAN (fs, wc, X, Y, (ex)); \ + } \ + else \ + { \ + _FP_CMP_CHECK_FLUSH_ZERO (fs, wc, X, Y); \ + \ + (ret) = !(X##_e == Y##_e \ + && _FP_FRAC_EQ_##wc (X, Y) \ + && (X##_s == Y##_s \ + || (!X##_e && _FP_FRAC_ZEROP_##wc (X)))); \ + } \ + } \ + while (0) + +/* Version to test unordered. */ + +#define _FP_CMP_UNORD(fs, wc, ret, X, Y, ex) \ + do \ + { \ + _FP_CMP_CHECK_DENORM (fs, wc, X, Y); \ + (ret) = ((X##_e == _FP_EXPMAX_##fs && !_FP_FRAC_ZEROP_##wc (X)) \ + || (Y##_e == _FP_EXPMAX_##fs && !_FP_FRAC_ZEROP_##wc (Y))); \ + if (ret) \ + _FP_CMP_CHECK_NAN (fs, wc, X, Y, (ex)); \ + } \ + while (0) + +/* Main square root routine. The input value should be cooked. */ + +#define _FP_SQRT(fs, wc, R, X) \ + do \ + { \ + _FP_FRAC_DECL_##wc (_FP_SQRT_T); \ + _FP_FRAC_DECL_##wc (_FP_SQRT_S); \ + _FP_W_TYPE _FP_SQRT_q; \ + switch (X##_c) \ + { \ + case FP_CLS_NAN: \ + _FP_FRAC_COPY_##wc (R, X); \ + R##_s = X##_s; \ + R##_c = FP_CLS_NAN; \ + break; \ + case FP_CLS_INF: \ + if (X##_s) \ + { \ + R##_s = _FP_NANSIGN_##fs; \ + R##_c = FP_CLS_NAN; /* NAN */ \ + _FP_FRAC_SET_##wc (R, _FP_NANFRAC_##fs); \ + FP_SET_EXCEPTION (FP_EX_INVALID | FP_EX_INVALID_SQRT); \ + } \ + else \ + { \ + R##_s = 0; \ + R##_c = FP_CLS_INF; /* sqrt(+inf) = +inf */ \ + } \ + break; \ + case FP_CLS_ZERO: \ + R##_s = X##_s; \ + R##_c = FP_CLS_ZERO; /* sqrt(+-0) = +-0 */ \ + break; \ + case FP_CLS_NORMAL: \ + R##_s = 0; \ + if (X##_s) \ + { \ + R##_c = FP_CLS_NAN; /* NAN */ \ + R##_s = _FP_NANSIGN_##fs; \ + _FP_FRAC_SET_##wc (R, _FP_NANFRAC_##fs); \ + FP_SET_EXCEPTION (FP_EX_INVALID | FP_EX_INVALID_SQRT); \ + break; \ + } \ + R##_c = FP_CLS_NORMAL; \ + if (X##_e & 1) \ + _FP_FRAC_SLL_##wc (X, 1); \ + R##_e = X##_e >> 1; \ + _FP_FRAC_SET_##wc (_FP_SQRT_S, _FP_ZEROFRAC_##wc); \ + _FP_FRAC_SET_##wc (R, _FP_ZEROFRAC_##wc); \ + _FP_SQRT_q = _FP_OVERFLOW_##fs >> 1; \ + _FP_SQRT_MEAT_##wc (R, _FP_SQRT_S, _FP_SQRT_T, X, \ + _FP_SQRT_q); \ + } \ + } \ + while (0) + +/* Convert from FP to integer. Input is raw. */ + +/* RSIGNED can have following values: + 0: the number is required to be 0..(2^rsize)-1, if not, NV is set plus + the result is either 0 or (2^rsize)-1 depending on the sign in such + case. + 1: the number is required to be -(2^(rsize-1))..(2^(rsize-1))-1, if not, + NV is set plus the result is either -(2^(rsize-1)) or (2^(rsize-1))-1 + depending on the sign in such case. + 2: the number is required to be -(2^(rsize-1))..(2^(rsize-1))-1, if not, + NV is set plus the result is reduced modulo 2^rsize. + -1: the number is required to be -(2^(rsize-1))..(2^rsize)-1, if not, NV is + set plus the result is either -(2^(rsize-1)) or (2^(rsize-1))-1 + depending on the sign in such case. */ +#define _FP_TO_INT(fs, wc, r, X, rsize, rsigned) \ + do \ + { \ + if (X##_e < _FP_EXPBIAS_##fs) \ + { \ + (r) = 0; \ + if (X##_e == 0) \ + { \ + if (!_FP_FRAC_ZEROP_##wc (X)) \ + { \ + if (!FP_DENORM_ZERO) \ + FP_SET_EXCEPTION (FP_EX_INEXACT); \ + FP_SET_EXCEPTION (FP_EX_DENORM); \ + } \ + } \ + else \ + FP_SET_EXCEPTION (FP_EX_INEXACT); \ + } \ + else if ((rsigned) == 2 \ + && (X##_e \ + >= ((_FP_EXPMAX_##fs \ + < _FP_EXPBIAS_##fs + _FP_FRACBITS_##fs + (rsize) - 1) \ + ? _FP_EXPMAX_##fs \ + : _FP_EXPBIAS_##fs + _FP_FRACBITS_##fs + (rsize) - 1))) \ + { \ + /* Overflow resulting in 0. */ \ + (r) = 0; \ + FP_SET_EXCEPTION (FP_EX_INVALID \ + | FP_EX_INVALID_CVI \ + | ((FP_EX_INVALID_SNAN \ + && _FP_ISSIGNAN (fs, wc, X)) \ + ? FP_EX_INVALID_SNAN \ + : 0)); \ + } \ + else if ((rsigned) != 2 \ + && (X##_e >= (_FP_EXPMAX_##fs < _FP_EXPBIAS_##fs + (rsize) \ + ? _FP_EXPMAX_##fs \ + : (_FP_EXPBIAS_##fs + (rsize) \ + - ((rsigned) > 0 || X##_s))) \ + || (!(rsigned) && X##_s))) \ + { \ + /* Overflow or converting to the most negative integer. */ \ + if (rsigned) \ + { \ + (r) = 1; \ + (r) <<= (rsize) - 1; \ + (r) -= 1 - X##_s; \ + } \ + else \ + { \ + (r) = 0; \ + if (!X##_s) \ + (r) = ~(r); \ + } \ + \ + if (_FP_EXPBIAS_##fs + (rsize) - 1 < _FP_EXPMAX_##fs \ + && (rsigned) \ + && X##_s \ + && X##_e == _FP_EXPBIAS_##fs + (rsize) - 1) \ + { \ + /* Possibly converting to most negative integer; check the \ + mantissa. */ \ + int _FP_TO_INT_inexact = 0; \ + (void) ((_FP_FRACBITS_##fs > (rsize)) \ + ? ({ \ + _FP_FRAC_SRST_##wc (X, _FP_TO_INT_inexact, \ + _FP_FRACBITS_##fs - (rsize), \ + _FP_FRACBITS_##fs); \ + 0; \ + }) \ + : 0); \ + if (!_FP_FRAC_ZEROP_##wc (X)) \ + FP_SET_EXCEPTION (FP_EX_INVALID | FP_EX_INVALID_CVI); \ + else if (_FP_TO_INT_inexact) \ + FP_SET_EXCEPTION (FP_EX_INEXACT); \ + } \ + else \ + FP_SET_EXCEPTION (FP_EX_INVALID \ + | FP_EX_INVALID_CVI \ + | ((FP_EX_INVALID_SNAN \ + && _FP_ISSIGNAN (fs, wc, X)) \ + ? FP_EX_INVALID_SNAN \ + : 0)); \ + } \ + else \ + { \ + int _FP_TO_INT_inexact = 0; \ + _FP_FRAC_HIGH_RAW_##fs (X) |= _FP_IMPLBIT_##fs; \ + if (X##_e >= _FP_EXPBIAS_##fs + _FP_FRACBITS_##fs - 1) \ + { \ + _FP_FRAC_ASSEMBLE_##wc ((r), X, (rsize)); \ + (r) <<= X##_e - _FP_EXPBIAS_##fs - _FP_FRACBITS_##fs + 1; \ + } \ + else \ + { \ + _FP_FRAC_SRST_##wc (X, _FP_TO_INT_inexact, \ + (_FP_FRACBITS_##fs + _FP_EXPBIAS_##fs - 1 \ + - X##_e), \ + _FP_FRACBITS_##fs); \ + _FP_FRAC_ASSEMBLE_##wc ((r), X, (rsize)); \ + } \ + if ((rsigned) && X##_s) \ + (r) = -(r); \ + if ((rsigned) == 2 && X##_e >= _FP_EXPBIAS_##fs + (rsize) - 1) \ + { \ + /* Overflow or converting to the most negative integer. */ \ + if (X##_e > _FP_EXPBIAS_##fs + (rsize) - 1 \ + || !X##_s \ + || (r) != (((typeof (r)) 1) << ((rsize) - 1))) \ + { \ + _FP_TO_INT_inexact = 0; \ + FP_SET_EXCEPTION (FP_EX_INVALID | FP_EX_INVALID_CVI); \ + } \ + } \ + if (_FP_TO_INT_inexact) \ + FP_SET_EXCEPTION (FP_EX_INEXACT); \ + } \ + } \ + while (0) + +/* Convert from floating point to integer, rounding according to the + current rounding direction. Input is raw. RSIGNED is as for + _FP_TO_INT. */ +#define _FP_TO_INT_ROUND(fs, wc, r, X, rsize, rsigned) \ + do \ + { \ + __label__ _FP_TO_INT_ROUND_done; \ + if (X##_e < _FP_EXPBIAS_##fs) \ + { \ + int _FP_TO_INT_ROUND_rounds_away = 0; \ + if (X##_e == 0) \ + { \ + if (_FP_FRAC_ZEROP_##wc (X)) \ + { \ + (r) = 0; \ + goto _FP_TO_INT_ROUND_done; \ + } \ + else \ + { \ + FP_SET_EXCEPTION (FP_EX_DENORM); \ + if (FP_DENORM_ZERO) \ + { \ + (r) = 0; \ + goto _FP_TO_INT_ROUND_done; \ + } \ + } \ + } \ + /* The result is 0, 1 or -1 depending on the rounding mode; \ + -1 may cause overflow in the unsigned case. */ \ + switch (FP_ROUNDMODE) \ + { \ + case FP_RND_NEAREST: \ + _FP_TO_INT_ROUND_rounds_away \ + = (X##_e == _FP_EXPBIAS_##fs - 1 \ + && !_FP_FRAC_ZEROP_##wc (X)); \ + break; \ + case FP_RND_ZERO: \ + /* _FP_TO_INT_ROUND_rounds_away is already 0. */ \ + break; \ + case FP_RND_PINF: \ + _FP_TO_INT_ROUND_rounds_away = !X##_s; \ + break; \ + case FP_RND_MINF: \ + _FP_TO_INT_ROUND_rounds_away = X##_s; \ + break; \ + } \ + if ((rsigned) == 0 && _FP_TO_INT_ROUND_rounds_away && X##_s) \ + { \ + /* Result of -1 for an unsigned conversion. */ \ + (r) = 0; \ + FP_SET_EXCEPTION (FP_EX_INVALID | FP_EX_INVALID_CVI); \ + } \ + else if ((rsize) == 1 && (rsigned) > 0 \ + && _FP_TO_INT_ROUND_rounds_away && !X##_s) \ + { \ + /* Converting to a 1-bit signed bit-field, which cannot \ + represent +1. */ \ + (r) = ((rsigned) == 2 ? -1 : 0); \ + FP_SET_EXCEPTION (FP_EX_INVALID | FP_EX_INVALID_CVI); \ + } \ + else \ + { \ + (r) = (_FP_TO_INT_ROUND_rounds_away \ + ? (X##_s ? -1 : 1) \ + : 0); \ + FP_SET_EXCEPTION (FP_EX_INEXACT); \ + } \ + } \ + else if ((rsigned) == 2 \ + && (X##_e \ + >= ((_FP_EXPMAX_##fs \ + < _FP_EXPBIAS_##fs + _FP_FRACBITS_##fs + (rsize) - 1) \ + ? _FP_EXPMAX_##fs \ + : _FP_EXPBIAS_##fs + _FP_FRACBITS_##fs + (rsize) - 1))) \ + { \ + /* Overflow resulting in 0. */ \ + (r) = 0; \ + FP_SET_EXCEPTION (FP_EX_INVALID \ + | FP_EX_INVALID_CVI \ + | ((FP_EX_INVALID_SNAN \ + && _FP_ISSIGNAN (fs, wc, X)) \ + ? FP_EX_INVALID_SNAN \ + : 0)); \ + } \ + else if ((rsigned) != 2 \ + && (X##_e >= (_FP_EXPMAX_##fs < _FP_EXPBIAS_##fs + (rsize) \ + ? _FP_EXPMAX_##fs \ + : (_FP_EXPBIAS_##fs + (rsize) \ + - ((rsigned) > 0 && !X##_s))) \ + || ((rsigned) == 0 && X##_s))) \ + { \ + /* Definite overflow (does not require rounding to tell). */ \ + if ((rsigned) != 0) \ + { \ + (r) = 1; \ + (r) <<= (rsize) - 1; \ + (r) -= 1 - X##_s; \ + } \ + else \ + { \ + (r) = 0; \ + if (!X##_s) \ + (r) = ~(r); \ + } \ + \ + FP_SET_EXCEPTION (FP_EX_INVALID \ + | FP_EX_INVALID_CVI \ + | ((FP_EX_INVALID_SNAN \ + && _FP_ISSIGNAN (fs, wc, X)) \ + ? FP_EX_INVALID_SNAN \ + : 0)); \ + } \ + else \ + { \ + /* The value is finite, with magnitude at least 1. If \ + the conversion is unsigned, the value is positive. \ + If RSIGNED is not 2, the value does not definitely \ + overflow by virtue of its exponent, but may still turn \ + out to overflow after rounding; if RSIGNED is 2, the \ + exponent may be such that the value definitely overflows, \ + but at least one mantissa bit will not be shifted out. */ \ + int _FP_TO_INT_ROUND_inexact = 0; \ + _FP_FRAC_HIGH_RAW_##fs (X) |= _FP_IMPLBIT_##fs; \ + if (X##_e >= _FP_EXPBIAS_##fs + _FP_FRACBITS_##fs - 1) \ + { \ + /* The value is an integer, no rounding needed. */ \ + _FP_FRAC_ASSEMBLE_##wc ((r), X, (rsize)); \ + (r) <<= X##_e - _FP_EXPBIAS_##fs - _FP_FRACBITS_##fs + 1; \ + } \ + else \ + { \ + /* May need to shift in order to round (unless there \ + are exactly _FP_WORKBITS fractional bits already). */ \ + int _FP_TO_INT_ROUND_rshift \ + = (_FP_FRACBITS_##fs + _FP_EXPBIAS_##fs \ + - 1 - _FP_WORKBITS - X##_e); \ + if (_FP_TO_INT_ROUND_rshift > 0) \ + _FP_FRAC_SRS_##wc (X, _FP_TO_INT_ROUND_rshift, \ + _FP_WFRACBITS_##fs); \ + else if (_FP_TO_INT_ROUND_rshift < 0) \ + _FP_FRAC_SLL_##wc (X, -_FP_TO_INT_ROUND_rshift); \ + /* Round like _FP_ROUND, but setting \ + _FP_TO_INT_ROUND_inexact instead of directly setting \ + the "inexact" exception, since it may turn out we \ + should set "invalid" instead. */ \ + if (_FP_FRAC_LOW_##wc (X) & 7) \ + { \ + _FP_TO_INT_ROUND_inexact = 1; \ + switch (FP_ROUNDMODE) \ + { \ + case FP_RND_NEAREST: \ + _FP_ROUND_NEAREST (wc, X); \ + break; \ + case FP_RND_ZERO: \ + _FP_ROUND_ZERO (wc, X); \ + break; \ + case FP_RND_PINF: \ + _FP_ROUND_PINF (wc, X); \ + break; \ + case FP_RND_MINF: \ + _FP_ROUND_MINF (wc, X); \ + break; \ + } \ + } \ + _FP_FRAC_SRL_##wc (X, _FP_WORKBITS); \ + _FP_FRAC_ASSEMBLE_##wc ((r), X, (rsize)); \ + } \ + if ((rsigned) != 0 && X##_s) \ + (r) = -(r); \ + /* An exponent of RSIZE - 1 always needs testing for \ + overflow (either directly overflowing, or overflowing \ + when rounding up results in 2^RSIZE). An exponent of \ + RSIZE - 2 can overflow for positive values when rounding \ + up to 2^(RSIZE-1), but cannot overflow for negative \ + values. Smaller exponents cannot overflow. */ \ + if (X##_e >= (_FP_EXPBIAS_##fs + (rsize) - 1 \ + - ((rsigned) > 0 && !X##_s))) \ + { \ + if (X##_e > _FP_EXPBIAS_##fs + (rsize) - 1 \ + || (X##_e == _FP_EXPBIAS_##fs + (rsize) - 1 \ + && (X##_s \ + ? (r) != (((typeof (r)) 1) << ((rsize) - 1)) \ + : ((rsigned) > 0 || (r) == 0))) \ + || ((rsigned) > 0 \ + && !X##_s \ + && X##_e == _FP_EXPBIAS_##fs + (rsize) - 2 \ + && (r) == (((typeof (r)) 1) << ((rsize) - 1)))) \ + { \ + if ((rsigned) != 2) \ + { \ + if ((rsigned) != 0) \ + { \ + (r) = 1; \ + (r) <<= (rsize) - 1; \ + (r) -= 1 - X##_s; \ + } \ + else \ + { \ + (r) = 0; \ + (r) = ~(r); \ + } \ + } \ + _FP_TO_INT_ROUND_inexact = 0; \ + FP_SET_EXCEPTION (FP_EX_INVALID | FP_EX_INVALID_CVI); \ + } \ + } \ + if (_FP_TO_INT_ROUND_inexact) \ + FP_SET_EXCEPTION (FP_EX_INEXACT); \ + } \ + _FP_TO_INT_ROUND_done: ; \ + } \ + while (0) + +/* Convert integer to fp. Output is raw. RTYPE is unsigned even if + input is signed. */ +#define _FP_FROM_INT(fs, wc, X, r, rsize, rtype) \ + do \ + { \ + __label__ pack_semiraw; \ + if (r) \ + { \ + rtype _FP_FROM_INT_ur = (r); \ + \ + if ((X##_s = ((r) < 0))) \ + _FP_FROM_INT_ur = -_FP_FROM_INT_ur; \ + \ + _FP_STATIC_ASSERT ((rsize) <= 2 * _FP_W_TYPE_SIZE, \ + "rsize too large"); \ + (void) (((rsize) <= _FP_W_TYPE_SIZE) \ + ? ({ \ + int _FP_FROM_INT_lz; \ + __FP_CLZ (_FP_FROM_INT_lz, \ + (_FP_W_TYPE) _FP_FROM_INT_ur); \ + X##_e = (_FP_EXPBIAS_##fs + _FP_W_TYPE_SIZE - 1 \ + - _FP_FROM_INT_lz); \ + }) \ + : ({ \ + int _FP_FROM_INT_lz; \ + __FP_CLZ_2 (_FP_FROM_INT_lz, \ + (_FP_W_TYPE) (_FP_FROM_INT_ur \ + >> _FP_W_TYPE_SIZE), \ + (_FP_W_TYPE) _FP_FROM_INT_ur); \ + X##_e = (_FP_EXPBIAS_##fs + 2 * _FP_W_TYPE_SIZE - 1 \ + - _FP_FROM_INT_lz); \ + })); \ + \ + if ((rsize) - 1 + _FP_EXPBIAS_##fs >= _FP_EXPMAX_##fs \ + && X##_e >= _FP_EXPMAX_##fs) \ + { \ + /* Exponent too big; overflow to infinity. (May also \ + happen after rounding below.) */ \ + _FP_OVERFLOW_SEMIRAW (fs, wc, X); \ + goto pack_semiraw; \ + } \ + \ + if ((rsize) <= _FP_FRACBITS_##fs \ + || X##_e < _FP_EXPBIAS_##fs + _FP_FRACBITS_##fs) \ + { \ + /* Exactly representable; shift left. */ \ + _FP_FRAC_DISASSEMBLE_##wc (X, _FP_FROM_INT_ur, (rsize)); \ + if (_FP_EXPBIAS_##fs + _FP_FRACBITS_##fs - 1 - X##_e > 0) \ + _FP_FRAC_SLL_##wc (X, (_FP_EXPBIAS_##fs \ + + _FP_FRACBITS_##fs - 1 - X##_e)); \ + } \ + else \ + { \ + /* More bits in integer than in floating type; need to \ + round. */ \ + if (_FP_EXPBIAS_##fs + _FP_WFRACBITS_##fs - 1 < X##_e) \ + _FP_FROM_INT_ur \ + = ((_FP_FROM_INT_ur >> (X##_e - _FP_EXPBIAS_##fs \ + - _FP_WFRACBITS_##fs + 1)) \ + | ((_FP_FROM_INT_ur \ + << ((rsize) - (X##_e - _FP_EXPBIAS_##fs \ + - _FP_WFRACBITS_##fs + 1))) \ + != 0)); \ + _FP_FRAC_DISASSEMBLE_##wc (X, _FP_FROM_INT_ur, (rsize)); \ + if ((_FP_EXPBIAS_##fs + _FP_WFRACBITS_##fs - 1 - X##_e) > 0) \ + _FP_FRAC_SLL_##wc (X, (_FP_EXPBIAS_##fs \ + + _FP_WFRACBITS_##fs - 1 - X##_e)); \ + _FP_FRAC_HIGH_##fs (X) &= ~(_FP_W_TYPE) _FP_IMPLBIT_SH_##fs; \ + pack_semiraw: \ + _FP_PACK_SEMIRAW (fs, wc, X); \ + } \ + } \ + else \ + { \ + X##_s = 0; \ + X##_e = 0; \ + _FP_FRAC_SET_##wc (X, _FP_ZEROFRAC_##wc); \ + } \ + } \ + while (0) + + +/* Extend from a narrower floating-point format to a wider one. Input + and output are raw. If CHECK_NAN, then signaling NaNs are + converted to quiet with the "invalid" exception raised; otherwise + signaling NaNs remain signaling with no exception. */ +#define _FP_EXTEND_CNAN(dfs, sfs, dwc, swc, D, S, check_nan) \ + do \ + { \ + _FP_STATIC_ASSERT (_FP_FRACBITS_##dfs >= _FP_FRACBITS_##sfs, \ + "destination mantissa narrower than source"); \ + _FP_STATIC_ASSERT ((_FP_EXPMAX_##dfs - _FP_EXPBIAS_##dfs \ + >= _FP_EXPMAX_##sfs - _FP_EXPBIAS_##sfs), \ + "destination max exponent smaller" \ + " than source"); \ + _FP_STATIC_ASSERT (((_FP_EXPBIAS_##dfs \ + >= (_FP_EXPBIAS_##sfs \ + + _FP_FRACBITS_##sfs - 1)) \ + || (_FP_EXPBIAS_##dfs == _FP_EXPBIAS_##sfs)), \ + "source subnormals do not all become normal," \ + " but bias not the same"); \ + D##_s = S##_s; \ + _FP_FRAC_COPY_##dwc##_##swc (D, S); \ + if (_FP_EXP_NORMAL (sfs, swc, S)) \ + { \ + D##_e = S##_e + _FP_EXPBIAS_##dfs - _FP_EXPBIAS_##sfs; \ + _FP_FRAC_SLL_##dwc (D, (_FP_FRACBITS_##dfs - _FP_FRACBITS_##sfs)); \ + } \ + else \ + { \ + if (S##_e == 0) \ + { \ + _FP_CHECK_FLUSH_ZERO (sfs, swc, S); \ + if (_FP_FRAC_ZEROP_##swc (S)) \ + D##_e = 0; \ + else if (_FP_EXPBIAS_##dfs \ + < _FP_EXPBIAS_##sfs + _FP_FRACBITS_##sfs - 1) \ + { \ + FP_SET_EXCEPTION (FP_EX_DENORM); \ + _FP_FRAC_SLL_##dwc (D, (_FP_FRACBITS_##dfs \ + - _FP_FRACBITS_##sfs)); \ + D##_e = 0; \ + if (FP_TRAPPING_EXCEPTIONS & FP_EX_UNDERFLOW) \ + FP_SET_EXCEPTION (FP_EX_UNDERFLOW); \ + } \ + else \ + { \ + int FP_EXTEND_lz; \ + FP_SET_EXCEPTION (FP_EX_DENORM); \ + _FP_FRAC_CLZ_##swc (FP_EXTEND_lz, S); \ + _FP_FRAC_SLL_##dwc (D, \ + FP_EXTEND_lz + _FP_FRACBITS_##dfs \ + - _FP_FRACTBITS_##sfs); \ + D##_e = (_FP_EXPBIAS_##dfs - _FP_EXPBIAS_##sfs + 1 \ + + _FP_FRACXBITS_##sfs - FP_EXTEND_lz); \ + } \ + } \ + else \ + { \ + D##_e = _FP_EXPMAX_##dfs; \ + if (!_FP_FRAC_ZEROP_##swc (S)) \ + { \ + if (check_nan && _FP_FRAC_SNANP (sfs, S)) \ + FP_SET_EXCEPTION (FP_EX_INVALID \ + | FP_EX_INVALID_SNAN); \ + _FP_FRAC_SLL_##dwc (D, (_FP_FRACBITS_##dfs \ + - _FP_FRACBITS_##sfs)); \ + if (check_nan) \ + _FP_SETQNAN (dfs, dwc, D); \ + } \ + } \ + } \ + } \ + while (0) + +#define FP_EXTEND(dfs, sfs, dwc, swc, D, S) \ + _FP_EXTEND_CNAN (dfs, sfs, dwc, swc, D, S, 1) + +/* Truncate from a wider floating-point format to a narrower one. + Input and output are semi-raw. */ +#define FP_TRUNC(dfs, sfs, dwc, swc, D, S) \ + do \ + { \ + _FP_STATIC_ASSERT (_FP_FRACBITS_##sfs >= _FP_FRACBITS_##dfs, \ + "destination mantissa wider than source"); \ + _FP_STATIC_ASSERT (((_FP_EXPBIAS_##sfs \ + >= (_FP_EXPBIAS_##dfs \ + + _FP_FRACBITS_##dfs - 1)) \ + || _FP_EXPBIAS_##sfs == _FP_EXPBIAS_##dfs), \ + "source subnormals do not all become same," \ + " but bias not the same"); \ + D##_s = S##_s; \ + if (_FP_EXP_NORMAL (sfs, swc, S)) \ + { \ + D##_e = S##_e + _FP_EXPBIAS_##dfs - _FP_EXPBIAS_##sfs; \ + if (D##_e >= _FP_EXPMAX_##dfs) \ + _FP_OVERFLOW_SEMIRAW (dfs, dwc, D); \ + else \ + { \ + if (D##_e <= 0) \ + { \ + if (D##_e < 1 - _FP_FRACBITS_##dfs) \ + { \ + _FP_FRAC_SET_##swc (S, _FP_ZEROFRAC_##swc); \ + _FP_FRAC_LOW_##swc (S) |= 1; \ + } \ + else \ + { \ + _FP_FRAC_HIGH_##sfs (S) |= _FP_IMPLBIT_SH_##sfs; \ + _FP_FRAC_SRS_##swc (S, (_FP_WFRACBITS_##sfs \ + - _FP_WFRACBITS_##dfs \ + + 1 - D##_e), \ + _FP_WFRACBITS_##sfs); \ + } \ + D##_e = 0; \ + } \ + else \ + _FP_FRAC_SRS_##swc (S, (_FP_WFRACBITS_##sfs \ + - _FP_WFRACBITS_##dfs), \ + _FP_WFRACBITS_##sfs); \ + _FP_FRAC_COPY_##dwc##_##swc (D, S); \ + } \ + } \ + else \ + { \ + if (S##_e == 0) \ + { \ + _FP_CHECK_FLUSH_ZERO (sfs, swc, S); \ + D##_e = 0; \ + if (_FP_FRAC_ZEROP_##swc (S)) \ + _FP_FRAC_SET_##dwc (D, _FP_ZEROFRAC_##dwc); \ + else \ + { \ + FP_SET_EXCEPTION (FP_EX_DENORM); \ + if (_FP_EXPBIAS_##sfs \ + < _FP_EXPBIAS_##dfs + _FP_FRACBITS_##dfs - 1) \ + { \ + _FP_FRAC_SRS_##swc (S, (_FP_WFRACBITS_##sfs \ + - _FP_WFRACBITS_##dfs), \ + _FP_WFRACBITS_##sfs); \ + _FP_FRAC_COPY_##dwc##_##swc (D, S); \ + } \ + else \ + { \ + _FP_FRAC_SET_##dwc (D, _FP_ZEROFRAC_##dwc); \ + _FP_FRAC_LOW_##dwc (D) |= 1; \ + } \ + } \ + } \ + else \ + { \ + D##_e = _FP_EXPMAX_##dfs; \ + if (_FP_FRAC_ZEROP_##swc (S)) \ + _FP_FRAC_SET_##dwc (D, _FP_ZEROFRAC_##dwc); \ + else \ + { \ + _FP_CHECK_SIGNAN_SEMIRAW (sfs, swc, S); \ + _FP_FRAC_SRL_##swc (S, (_FP_WFRACBITS_##sfs \ + - _FP_WFRACBITS_##dfs)); \ + _FP_FRAC_COPY_##dwc##_##swc (D, S); \ + /* Semi-raw NaN must have all workbits cleared. */ \ + _FP_FRAC_LOW_##dwc (D) \ + &= ~(_FP_W_TYPE) ((1 << _FP_WORKBITS) - 1); \ + _FP_SETQNAN_SEMIRAW (dfs, dwc, D); \ + } \ + } \ + } \ + } \ + while (0) + +/* Helper primitives. */ + +/* Count leading zeros in a word. */ + +#ifndef __FP_CLZ +/* GCC 3.4 and later provide the builtins for us. */ +# define __FP_CLZ(r, x) \ + do \ + { \ + _FP_STATIC_ASSERT ((sizeof (_FP_W_TYPE) == sizeof (unsigned int) \ + || (sizeof (_FP_W_TYPE) \ + == sizeof (unsigned long)) \ + || (sizeof (_FP_W_TYPE) \ + == sizeof (unsigned long long))), \ + "_FP_W_TYPE size unsupported for clz"); \ + if (sizeof (_FP_W_TYPE) == sizeof (unsigned int)) \ + (r) = __builtin_clz (x); \ + else if (sizeof (_FP_W_TYPE) == sizeof (unsigned long)) \ + (r) = __builtin_clzl (x); \ + else /* sizeof (_FP_W_TYPE) == sizeof (unsigned long long). */ \ + (r) = __builtin_clzll (x); \ + } \ + while (0) +#endif /* ndef __FP_CLZ */ + +#define _FP_DIV_HELP_imm(q, r, n, d) \ + do \ + { \ + (q) = (n) / (d), (r) = (n) % (d); \ + } \ + while (0) + + +/* A restoring bit-by-bit division primitive. */ + +#define _FP_DIV_MEAT_N_loop(fs, wc, R, X, Y) \ + do \ + { \ + int _FP_DIV_MEAT_N_loop_count = _FP_WFRACBITS_##fs; \ + _FP_FRAC_DECL_##wc (_FP_DIV_MEAT_N_loop_u); \ + _FP_FRAC_DECL_##wc (_FP_DIV_MEAT_N_loop_v); \ + _FP_FRAC_COPY_##wc (_FP_DIV_MEAT_N_loop_u, X); \ + _FP_FRAC_COPY_##wc (_FP_DIV_MEAT_N_loop_v, Y); \ + _FP_FRAC_SET_##wc (R, _FP_ZEROFRAC_##wc); \ + /* Normalize _FP_DIV_MEAT_N_LOOP_U and _FP_DIV_MEAT_N_LOOP_V. */ \ + _FP_FRAC_SLL_##wc (_FP_DIV_MEAT_N_loop_u, _FP_WFRACXBITS_##fs); \ + _FP_FRAC_SLL_##wc (_FP_DIV_MEAT_N_loop_v, _FP_WFRACXBITS_##fs); \ + /* First round. Since the operands are normalized, either the \ + first or second bit will be set in the fraction. Produce a \ + normalized result by checking which and adjusting the loop \ + count and exponent accordingly. */ \ + if (_FP_FRAC_GE_1 (_FP_DIV_MEAT_N_loop_u, _FP_DIV_MEAT_N_loop_v)) \ + { \ + _FP_FRAC_SUB_##wc (_FP_DIV_MEAT_N_loop_u, \ + _FP_DIV_MEAT_N_loop_u, \ + _FP_DIV_MEAT_N_loop_v); \ + _FP_FRAC_LOW_##wc (R) |= 1; \ + _FP_DIV_MEAT_N_loop_count--; \ + } \ + else \ + R##_e--; \ + /* Subsequent rounds. */ \ + do \ + { \ + int _FP_DIV_MEAT_N_loop_msb \ + = (_FP_WS_TYPE) _FP_FRAC_HIGH_##wc (_FP_DIV_MEAT_N_loop_u) < 0; \ + _FP_FRAC_SLL_##wc (_FP_DIV_MEAT_N_loop_u, 1); \ + _FP_FRAC_SLL_##wc (R, 1); \ + if (_FP_DIV_MEAT_N_loop_msb \ + || _FP_FRAC_GE_1 (_FP_DIV_MEAT_N_loop_u, \ + _FP_DIV_MEAT_N_loop_v)) \ + { \ + _FP_FRAC_SUB_##wc (_FP_DIV_MEAT_N_loop_u, \ + _FP_DIV_MEAT_N_loop_u, \ + _FP_DIV_MEAT_N_loop_v); \ + _FP_FRAC_LOW_##wc (R) |= 1; \ + } \ + } \ + while (--_FP_DIV_MEAT_N_loop_count > 0); \ + /* If there's anything left in _FP_DIV_MEAT_N_LOOP_U, the result \ + is inexact. */ \ + _FP_FRAC_LOW_##wc (R) \ + |= !_FP_FRAC_ZEROP_##wc (_FP_DIV_MEAT_N_loop_u); \ + } \ + while (0) + +#define _FP_DIV_MEAT_1_loop(fs, R, X, Y) _FP_DIV_MEAT_N_loop (fs, 1, R, X, Y) +#define _FP_DIV_MEAT_2_loop(fs, R, X, Y) _FP_DIV_MEAT_N_loop (fs, 2, R, X, Y) +#define _FP_DIV_MEAT_4_loop(fs, R, X, Y) _FP_DIV_MEAT_N_loop (fs, 4, R, X, Y) + +#endif /* !SOFT_FP_OP_COMMON_H */ diff --git a/fpu/quad.h b/fpu/quad.h new file mode 100644 index 0000000000..71621f01bf --- /dev/null +++ b/fpu/quad.h @@ -0,0 +1,330 @@ +/* Software floating-point emulation. + Definitions for IEEE Quad Precision. + Copyright (C) 1997-2018 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Richard Henderson (rth@cygnus.com), + Jakub Jelinek (jj@ultra.linux.cz), + David S. Miller (davem@redhat.com) and + Peter Maydell (pmaydell@chiark.greenend.org.uk). + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + In addition to the permissions in the GNU Lesser General Public + License, the Free Software Foundation gives you unlimited + permission to link the compiled version of this file into + combinations with other programs, and to distribute those + combinations without any restriction coming from the use of this + file. (The Lesser General Public License restrictions do apply in + other respects; for example, they cover modification of the file, + and distribution when not linked into a combine executable.) + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + . */ + +#ifndef SOFT_FP_QUAD_H +#define SOFT_FP_QUAD_H 1 + +#if _FP_W_TYPE_SIZE < 32 +# error "Here's a nickel, kid. Go buy yourself a real computer." +#endif + +#if _FP_W_TYPE_SIZE < 64 +# define _FP_FRACTBITS_Q (4*_FP_W_TYPE_SIZE) +# define _FP_FRACTBITS_DW_Q (8*_FP_W_TYPE_SIZE) +#else +# define _FP_FRACTBITS_Q (2*_FP_W_TYPE_SIZE) +# define _FP_FRACTBITS_DW_Q (4*_FP_W_TYPE_SIZE) +#endif + +#define _FP_FRACBITS_Q 113 +#define _FP_FRACXBITS_Q (_FP_FRACTBITS_Q - _FP_FRACBITS_Q) +#define _FP_WFRACBITS_Q (_FP_WORKBITS + _FP_FRACBITS_Q) +#define _FP_WFRACXBITS_Q (_FP_FRACTBITS_Q - _FP_WFRACBITS_Q) +#define _FP_EXPBITS_Q 15 +#define _FP_EXPBIAS_Q 16383 +#define _FP_EXPMAX_Q 32767 + +#define _FP_QNANBIT_Q \ + ((_FP_W_TYPE) 1 << (_FP_FRACBITS_Q-2) % _FP_W_TYPE_SIZE) +#define _FP_QNANBIT_SH_Q \ + ((_FP_W_TYPE) 1 << (_FP_FRACBITS_Q-2+_FP_WORKBITS) % _FP_W_TYPE_SIZE) +#define _FP_IMPLBIT_Q \ + ((_FP_W_TYPE) 1 << (_FP_FRACBITS_Q-1) % _FP_W_TYPE_SIZE) +#define _FP_IMPLBIT_SH_Q \ + ((_FP_W_TYPE) 1 << (_FP_FRACBITS_Q-1+_FP_WORKBITS) % _FP_W_TYPE_SIZE) +#define _FP_OVERFLOW_Q \ + ((_FP_W_TYPE) 1 << (_FP_WFRACBITS_Q % _FP_W_TYPE_SIZE)) + +#define _FP_WFRACBITS_DW_Q (2 * _FP_WFRACBITS_Q) +#define _FP_WFRACXBITS_DW_Q (_FP_FRACTBITS_DW_Q - _FP_WFRACBITS_DW_Q) +#define _FP_HIGHBIT_DW_Q \ + ((_FP_W_TYPE) 1 << (_FP_WFRACBITS_DW_Q - 1) % _FP_W_TYPE_SIZE) + +typedef float TFtype __attribute__ ((mode (TF))); + +#if _FP_W_TYPE_SIZE < 64 + +union _FP_UNION_Q +{ + TFtype flt; + struct _FP_STRUCT_LAYOUT + { +# if __BYTE_ORDER == __BIG_ENDIAN + unsigned sign : 1; + unsigned exp : _FP_EXPBITS_Q; + unsigned long frac3 : _FP_FRACBITS_Q - (_FP_IMPLBIT_Q != 0)-(_FP_W_TYPE_SIZE * 3); + unsigned long frac2 : _FP_W_TYPE_SIZE; + unsigned long frac1 : _FP_W_TYPE_SIZE; + unsigned long frac0 : _FP_W_TYPE_SIZE; +# else + unsigned long frac0 : _FP_W_TYPE_SIZE; + unsigned long frac1 : _FP_W_TYPE_SIZE; + unsigned long frac2 : _FP_W_TYPE_SIZE; + unsigned long frac3 : _FP_FRACBITS_Q - (_FP_IMPLBIT_Q != 0)-(_FP_W_TYPE_SIZE * 3); + unsigned exp : _FP_EXPBITS_Q; + unsigned sign : 1; +# endif /* not bigendian */ + } bits __attribute__ ((packed)); +}; + + +# define FP_DECL_Q(X) _FP_DECL (4, X) +# define FP_UNPACK_RAW_Q(X, val) _FP_UNPACK_RAW_4 (Q, X, (val)) +# define FP_UNPACK_RAW_QP(X, val) _FP_UNPACK_RAW_4_P (Q, X, (val)) +# define FP_PACK_RAW_Q(val, X) _FP_PACK_RAW_4 (Q, (val), X) +# define FP_PACK_RAW_QP(val, X) \ + do \ + { \ + if (!FP_INHIBIT_RESULTS) \ + _FP_PACK_RAW_4_P (Q, (val), X); \ + } \ + while (0) + +# define FP_UNPACK_Q(X, val) \ + do \ + { \ + _FP_UNPACK_RAW_4 (Q, X, (val)); \ + _FP_UNPACK_CANONICAL (Q, 4, X); \ + } \ + while (0) + +# define FP_UNPACK_QP(X, val) \ + do \ + { \ + _FP_UNPACK_RAW_4_P (Q, X, (val)); \ + _FP_UNPACK_CANONICAL (Q, 4, X); \ + } \ + while (0) + +# define FP_UNPACK_SEMIRAW_Q(X, val) \ + do \ + { \ + _FP_UNPACK_RAW_4 (Q, X, (val)); \ + _FP_UNPACK_SEMIRAW (Q, 4, X); \ + } \ + while (0) + +# define FP_UNPACK_SEMIRAW_QP(X, val) \ + do \ + { \ + _FP_UNPACK_RAW_4_P (Q, X, (val)); \ + _FP_UNPACK_SEMIRAW (Q, 4, X); \ + } \ + while (0) + +# define FP_PACK_Q(val, X) \ + do \ + { \ + _FP_PACK_CANONICAL (Q, 4, X); \ + _FP_PACK_RAW_4 (Q, (val), X); \ + } \ + while (0) + +# define FP_PACK_QP(val, X) \ + do \ + { \ + _FP_PACK_CANONICAL (Q, 4, X); \ + if (!FP_INHIBIT_RESULTS) \ + _FP_PACK_RAW_4_P (Q, (val), X); \ + } \ + while (0) + +# define FP_PACK_SEMIRAW_Q(val, X) \ + do \ + { \ + _FP_PACK_SEMIRAW (Q, 4, X); \ + _FP_PACK_RAW_4 (Q, (val), X); \ + } \ + while (0) + +# define FP_PACK_SEMIRAW_QP(val, X) \ + do \ + { \ + _FP_PACK_SEMIRAW (Q, 4, X); \ + if (!FP_INHIBIT_RESULTS) \ + _FP_PACK_RAW_4_P (Q, (val), X); \ + } \ + while (0) + +# define FP_ISSIGNAN_Q(X) _FP_ISSIGNAN (Q, 4, X) +# define FP_NEG_Q(R, X) _FP_NEG (Q, 4, R, X) +# define FP_ADD_Q(R, X, Y) _FP_ADD (Q, 4, R, X, Y) +# define FP_SUB_Q(R, X, Y) _FP_SUB (Q, 4, R, X, Y) +# define FP_MUL_Q(R, X, Y) _FP_MUL (Q, 4, R, X, Y) +# define FP_DIV_Q(R, X, Y) _FP_DIV (Q, 4, R, X, Y) +# define FP_SQRT_Q(R, X) _FP_SQRT (Q, 4, R, X) +# define _FP_SQRT_MEAT_Q(R, S, T, X, Q) _FP_SQRT_MEAT_4 (R, S, T, X, (Q)) +# define FP_FMA_Q(R, X, Y, Z) _FP_FMA (Q, 4, 8, R, X, Y, Z) + +# define FP_CMP_Q(r, X, Y, un, ex) _FP_CMP (Q, 4, (r), X, Y, (un), (ex)) +# define FP_CMP_EQ_Q(r, X, Y, ex) _FP_CMP_EQ (Q, 4, (r), X, Y, (ex)) +# define FP_CMP_UNORD_Q(r, X, Y, ex) _FP_CMP_UNORD (Q, 4, (r), X, Y, (ex)) + +# define FP_TO_INT_Q(r, X, rsz, rsg) _FP_TO_INT (Q, 4, (r), X, (rsz), (rsg)) +# define FP_TO_INT_ROUND_Q(r, X, rsz, rsg) \ + _FP_TO_INT_ROUND (Q, 4, (r), X, (rsz), (rsg)) +# define FP_FROM_INT_Q(X, r, rs, rt) _FP_FROM_INT (Q, 4, X, (r), (rs), rt) + +# define _FP_FRAC_HIGH_Q(X) _FP_FRAC_HIGH_4 (X) +# define _FP_FRAC_HIGH_RAW_Q(X) _FP_FRAC_HIGH_4 (X) + +# define _FP_FRAC_HIGH_DW_Q(X) _FP_FRAC_HIGH_8 (X) + +#else /* not _FP_W_TYPE_SIZE < 64 */ +union _FP_UNION_Q +{ + TFtype flt /* __attribute__ ((mode (TF))) */ ; + struct _FP_STRUCT_LAYOUT + { + _FP_W_TYPE a, b; + } longs; + struct _FP_STRUCT_LAYOUT + { +# if __BYTE_ORDER == __BIG_ENDIAN + unsigned sign : 1; + unsigned exp : _FP_EXPBITS_Q; + _FP_W_TYPE frac1 : _FP_FRACBITS_Q - (_FP_IMPLBIT_Q != 0) - _FP_W_TYPE_SIZE; + _FP_W_TYPE frac0 : _FP_W_TYPE_SIZE; +# else + _FP_W_TYPE frac0 : _FP_W_TYPE_SIZE; + _FP_W_TYPE frac1 : _FP_FRACBITS_Q - (_FP_IMPLBIT_Q != 0) - _FP_W_TYPE_SIZE; + unsigned exp : _FP_EXPBITS_Q; + unsigned sign : 1; +# endif + } bits; +}; + +# define FP_DECL_Q(X) _FP_DECL (2, X) +# define FP_UNPACK_RAW_Q(X, val) _FP_UNPACK_RAW_2 (Q, X, (val)) +# define FP_UNPACK_RAW_QP(X, val) _FP_UNPACK_RAW_2_P (Q, X, (val)) +# define FP_PACK_RAW_Q(val, X) _FP_PACK_RAW_2 (Q, (val), X) +# define FP_PACK_RAW_QP(val, X) \ + do \ + { \ + if (!FP_INHIBIT_RESULTS) \ + _FP_PACK_RAW_2_P (Q, (val), X); \ + } \ + while (0) + +# define FP_UNPACK_Q(X, val) \ + do \ + { \ + _FP_UNPACK_RAW_2 (Q, X, (val)); \ + _FP_UNPACK_CANONICAL (Q, 2, X); \ + } \ + while (0) + +# define FP_UNPACK_QP(X, val) \ + do \ + { \ + _FP_UNPACK_RAW_2_P (Q, X, (val)); \ + _FP_UNPACK_CANONICAL (Q, 2, X); \ + } \ + while (0) + +# define FP_UNPACK_SEMIRAW_Q(X, val) \ + do \ + { \ + _FP_UNPACK_RAW_2 (Q, X, (val)); \ + _FP_UNPACK_SEMIRAW (Q, 2, X); \ + } \ + while (0) + +# define FP_UNPACK_SEMIRAW_QP(X, val) \ + do \ + { \ + _FP_UNPACK_RAW_2_P (Q, X, (val)); \ + _FP_UNPACK_SEMIRAW (Q, 2, X); \ + } \ + while (0) + +# define FP_PACK_Q(val, X) \ + do \ + { \ + _FP_PACK_CANONICAL (Q, 2, X); \ + _FP_PACK_RAW_2 (Q, (val), X); \ + } \ + while (0) + +# define FP_PACK_QP(val, X) \ + do \ + { \ + _FP_PACK_CANONICAL (Q, 2, X); \ + if (!FP_INHIBIT_RESULTS) \ + _FP_PACK_RAW_2_P (Q, (val), X); \ + } \ + while (0) + +# define FP_PACK_SEMIRAW_Q(val, X) \ + do \ + { \ + _FP_PACK_SEMIRAW (Q, 2, X); \ + _FP_PACK_RAW_2 (Q, (val), X); \ + } \ + while (0) + +# define FP_PACK_SEMIRAW_QP(val, X) \ + do \ + { \ + _FP_PACK_SEMIRAW (Q, 2, X); \ + if (!FP_INHIBIT_RESULTS) \ + _FP_PACK_RAW_2_P (Q, (val), X); \ + } \ + while (0) + +# define FP_ISSIGNAN_Q(X) _FP_ISSIGNAN (Q, 2, X) +# define FP_NEG_Q(R, X) _FP_NEG (Q, 2, R, X) +# define FP_ADD_Q(R, X, Y) _FP_ADD (Q, 2, R, X, Y) +# define FP_SUB_Q(R, X, Y) _FP_SUB (Q, 2, R, X, Y) +# define FP_MUL_Q(R, X, Y) _FP_MUL (Q, 2, R, X, Y) +# define FP_DIV_Q(R, X, Y) _FP_DIV (Q, 2, R, X, Y) +# define FP_SQRT_Q(R, X) _FP_SQRT (Q, 2, R, X) +# define _FP_SQRT_MEAT_Q(R, S, T, X, Q) _FP_SQRT_MEAT_2 (R, S, T, X, (Q)) +# define FP_FMA_Q(R, X, Y, Z) _FP_FMA (Q, 2, 4, R, X, Y, Z) + +# define FP_CMP_Q(r, X, Y, un, ex) _FP_CMP (Q, 2, (r), X, Y, (un), (ex)) +# define FP_CMP_EQ_Q(r, X, Y, ex) _FP_CMP_EQ (Q, 2, (r), X, Y, (ex)) +# define FP_CMP_UNORD_Q(r, X, Y, ex) _FP_CMP_UNORD (Q, 2, (r), X, Y, (ex)) + +# define FP_TO_INT_Q(r, X, rsz, rsg) _FP_TO_INT (Q, 2, (r), X, (rsz), (rsg)) +# define FP_TO_INT_ROUND_Q(r, X, rsz, rsg) \ + _FP_TO_INT_ROUND (Q, 2, (r), X, (rsz), (rsg)) +# define FP_FROM_INT_Q(X, r, rs, rt) _FP_FROM_INT (Q, 2, X, (r), (rs), rt) + +# define _FP_FRAC_HIGH_Q(X) _FP_FRAC_HIGH_2 (X) +# define _FP_FRAC_HIGH_RAW_Q(X) _FP_FRAC_HIGH_2 (X) + +# define _FP_FRAC_HIGH_DW_Q(X) _FP_FRAC_HIGH_4 (X) + +#endif /* not _FP_W_TYPE_SIZE < 64 */ + +#endif /* !SOFT_FP_QUAD_H */ diff --git a/fpu/single.h b/fpu/single.h new file mode 100644 index 0000000000..2918f78d97 --- /dev/null +++ b/fpu/single.h @@ -0,0 +1,199 @@ +/* Software floating-point emulation. + Definitions for IEEE Single Precision. + Copyright (C) 1997-2018 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Richard Henderson (rth@cygnus.com), + Jakub Jelinek (jj@ultra.linux.cz), + David S. Miller (davem@redhat.com) and + Peter Maydell (pmaydell@chiark.greenend.org.uk). + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + In addition to the permissions in the GNU Lesser General Public + License, the Free Software Foundation gives you unlimited + permission to link the compiled version of this file into + combinations with other programs, and to distribute those + combinations without any restriction coming from the use of this + file. (The Lesser General Public License restrictions do apply in + other respects; for example, they cover modification of the file, + and distribution when not linked into a combine executable.) + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + . */ + +#ifndef SOFT_FP_SINGLE_H +#define SOFT_FP_SINGLE_H 1 + +#if _FP_W_TYPE_SIZE < 32 +# error "Here's a nickel kid. Go buy yourself a real computer." +#endif + +#define _FP_FRACTBITS_S _FP_W_TYPE_SIZE + +#if _FP_W_TYPE_SIZE < 64 +# define _FP_FRACTBITS_DW_S (2 * _FP_W_TYPE_SIZE) +#else +# define _FP_FRACTBITS_DW_S _FP_W_TYPE_SIZE +#endif + +#define _FP_FRACBITS_S 24 +#define _FP_FRACXBITS_S (_FP_FRACTBITS_S - _FP_FRACBITS_S) +#define _FP_WFRACBITS_S (_FP_WORKBITS + _FP_FRACBITS_S) +#define _FP_WFRACXBITS_S (_FP_FRACTBITS_S - _FP_WFRACBITS_S) +#define _FP_EXPBITS_S 8 +#define _FP_EXPBIAS_S 127 +#define _FP_EXPMAX_S 255 +#define _FP_QNANBIT_S ((_FP_W_TYPE) 1 << (_FP_FRACBITS_S-2)) +#define _FP_QNANBIT_SH_S ((_FP_W_TYPE) 1 << (_FP_FRACBITS_S-2+_FP_WORKBITS)) +#define _FP_IMPLBIT_S ((_FP_W_TYPE) 1 << (_FP_FRACBITS_S-1)) +#define _FP_IMPLBIT_SH_S ((_FP_W_TYPE) 1 << (_FP_FRACBITS_S-1+_FP_WORKBITS)) +#define _FP_OVERFLOW_S ((_FP_W_TYPE) 1 << (_FP_WFRACBITS_S)) + +#define _FP_WFRACBITS_DW_S (2 * _FP_WFRACBITS_S) +#define _FP_WFRACXBITS_DW_S (_FP_FRACTBITS_DW_S - _FP_WFRACBITS_DW_S) +#define _FP_HIGHBIT_DW_S \ + ((_FP_W_TYPE) 1 << (_FP_WFRACBITS_DW_S - 1) % _FP_W_TYPE_SIZE) + +/* The implementation of _FP_MUL_MEAT_S and _FP_DIV_MEAT_S should be + chosen by the target machine. */ + +typedef float SFtype __attribute__ ((mode (SF))); + +union _FP_UNION_S +{ + SFtype flt; + struct _FP_STRUCT_LAYOUT + { +#if __BYTE_ORDER == __BIG_ENDIAN + unsigned sign : 1; + unsigned exp : _FP_EXPBITS_S; + unsigned frac : _FP_FRACBITS_S - (_FP_IMPLBIT_S != 0); +#else + unsigned frac : _FP_FRACBITS_S - (_FP_IMPLBIT_S != 0); + unsigned exp : _FP_EXPBITS_S; + unsigned sign : 1; +#endif + } bits __attribute__ ((packed)); +}; + +#define FP_DECL_S(X) _FP_DECL (1, X) +#define FP_UNPACK_RAW_S(X, val) _FP_UNPACK_RAW_1 (S, X, (val)) +#define FP_UNPACK_RAW_SP(X, val) _FP_UNPACK_RAW_1_P (S, X, (val)) +#define FP_PACK_RAW_S(val, X) _FP_PACK_RAW_1 (S, (val), X) +#define FP_PACK_RAW_SP(val, X) \ + do \ + { \ + if (!FP_INHIBIT_RESULTS) \ + _FP_PACK_RAW_1_P (S, (val), X); \ + } \ + while (0) + +#define FP_UNPACK_S(X, val) \ + do \ + { \ + _FP_UNPACK_RAW_1 (S, X, (val)); \ + _FP_UNPACK_CANONICAL (S, 1, X); \ + } \ + while (0) + +#define FP_UNPACK_SP(X, val) \ + do \ + { \ + _FP_UNPACK_RAW_1_P (S, X, (val)); \ + _FP_UNPACK_CANONICAL (S, 1, X); \ + } \ + while (0) + +#define FP_UNPACK_SEMIRAW_S(X, val) \ + do \ + { \ + _FP_UNPACK_RAW_1 (S, X, (val)); \ + _FP_UNPACK_SEMIRAW (S, 1, X); \ + } \ + while (0) + +#define FP_UNPACK_SEMIRAW_SP(X, val) \ + do \ + { \ + _FP_UNPACK_RAW_1_P (S, X, (val)); \ + _FP_UNPACK_SEMIRAW (S, 1, X); \ + } \ + while (0) + +#define FP_PACK_S(val, X) \ + do \ + { \ + _FP_PACK_CANONICAL (S, 1, X); \ + _FP_PACK_RAW_1 (S, (val), X); \ + } \ + while (0) + +#define FP_PACK_SP(val, X) \ + do \ + { \ + _FP_PACK_CANONICAL (S, 1, X); \ + if (!FP_INHIBIT_RESULTS) \ + _FP_PACK_RAW_1_P (S, (val), X); \ + } \ + while (0) + +#define FP_PACK_SEMIRAW_S(val, X) \ + do \ + { \ + _FP_PACK_SEMIRAW (S, 1, X); \ + _FP_PACK_RAW_1 (S, (val), X); \ + } \ + while (0) + +#define FP_PACK_SEMIRAW_SP(val, X) \ + do \ + { \ + _FP_PACK_SEMIRAW (S, 1, X); \ + if (!FP_INHIBIT_RESULTS) \ + _FP_PACK_RAW_1_P (S, (val), X); \ + } \ + while (0) + +#define FP_ISSIGNAN_S(X) _FP_ISSIGNAN (S, 1, X) +#define FP_NEG_S(R, X) _FP_NEG (S, 1, R, X) +#define FP_ADD_S(R, X, Y) _FP_ADD (S, 1, R, X, Y) +#define FP_SUB_S(R, X, Y) _FP_SUB (S, 1, R, X, Y) +#define FP_MUL_S(R, X, Y) _FP_MUL (S, 1, R, X, Y) +#define FP_DIV_S(R, X, Y) _FP_DIV (S, 1, R, X, Y) +#define FP_SQRT_S(R, X) _FP_SQRT (S, 1, R, X) +#define _FP_SQRT_MEAT_S(R, S, T, X, Q) _FP_SQRT_MEAT_1 (R, S, T, X, (Q)) + +#if _FP_W_TYPE_SIZE < 64 +# define FP_FMA_S(R, X, Y, Z) _FP_FMA (S, 1, 2, R, X, Y, Z) +#else +# define FP_FMA_S(R, X, Y, Z) _FP_FMA (S, 1, 1, R, X, Y, Z) +#endif + +#define FP_CMP_S(r, X, Y, un, ex) _FP_CMP (S, 1, (r), X, Y, (un), (ex)) +#define FP_CMP_EQ_S(r, X, Y, ex) _FP_CMP_EQ (S, 1, (r), X, Y, (ex)) +#define FP_CMP_UNORD_S(r, X, Y, ex) _FP_CMP_UNORD (S, 1, (r), X, Y, (ex)) + +#define FP_TO_INT_S(r, X, rsz, rsg) _FP_TO_INT (S, 1, (r), X, (rsz), (rsg)) +#define FP_TO_INT_ROUND_S(r, X, rsz, rsg) \ + _FP_TO_INT_ROUND (S, 1, (r), X, (rsz), (rsg)) +#define FP_FROM_INT_S(X, r, rs, rt) _FP_FROM_INT (S, 1, X, (r), (rs), rt) + +#define _FP_FRAC_HIGH_S(X) _FP_FRAC_HIGH_1 (X) +#define _FP_FRAC_HIGH_RAW_S(X) _FP_FRAC_HIGH_1 (X) + +#if _FP_W_TYPE_SIZE < 64 +# define _FP_FRAC_HIGH_DW_S(X) _FP_FRAC_HIGH_2 (X) +#else +# define _FP_FRAC_HIGH_DW_S(X) _FP_FRAC_HIGH_1 (X) +#endif + +#endif /* !SOFT_FP_SINGLE_H */ diff --git a/fpu/soft-fp.h b/fpu/soft-fp.h new file mode 100644 index 0000000000..a7a01334b7 --- /dev/null +++ b/fpu/soft-fp.h @@ -0,0 +1,354 @@ +/* Software floating-point emulation. + Copyright (C) 1997-2018 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Richard Henderson (rth@cygnus.com), + Jakub Jelinek (jj@ultra.linux.cz), + David S. Miller (davem@redhat.com) and + Peter Maydell (pmaydell@chiark.greenend.org.uk). + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + In addition to the permissions in the GNU Lesser General Public + License, the Free Software Foundation gives you unlimited + permission to link the compiled version of this file into + combinations with other programs, and to distribute those + combinations without any restriction coming from the use of this + file. (The Lesser General Public License restrictions do apply in + other respects; for example, they cover modification of the file, + and distribution when not linked into a combine executable.) + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + . */ + +#ifndef SOFT_FP_H +#define SOFT_FP_H 1 + +#ifdef _LIBC +# include +#elif defined __KERNEL__ +/* The Linux kernel uses asm/ names for architecture-specific + files. */ +# include +#else +# include "sfp-machine.h" +#endif + +/* Allow sfp-machine to have its own byte order definitions. */ +#ifndef __BYTE_ORDER +# ifdef _LIBC +# include +# else +# error "endianness not defined by sfp-machine.h" +# endif +#endif + +/* For unreachable default cases in switch statements over bitwise OR + of FP_CLS_* values. */ +#if (defined __GNUC__ \ + && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 5))) +# define _FP_UNREACHABLE __builtin_unreachable () +#else +# define _FP_UNREACHABLE abort () +#endif + +#if ((defined __GNUC__ \ + && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6))) \ + || (defined __STDC_VERSION__ && __STDC_VERSION__ >= 201112L)) +# define _FP_STATIC_ASSERT(expr, msg) \ + _Static_assert ((expr), msg) +#else +# define _FP_STATIC_ASSERT(expr, msg) \ + extern int (*__Static_assert_function (void)) \ + [!!sizeof (struct { int __error_if_negative: (expr) ? 2 : -1; })] +#endif + +/* In the Linux kernel, some architectures have a single function that + uses different kinds of unpacking and packing depending on the + instruction being emulated, meaning it is not readily visible to + the compiler that variables from _FP_DECL and _FP_FRAC_DECL_* + macros are only used in cases where they were initialized. */ +#ifdef __KERNEL__ +# define _FP_ZERO_INIT = 0 +#else +# define _FP_ZERO_INIT +#endif + +#define _FP_WORKBITS 3 +#define _FP_WORK_LSB ((_FP_W_TYPE) 1 << 3) +#define _FP_WORK_ROUND ((_FP_W_TYPE) 1 << 2) +#define _FP_WORK_GUARD ((_FP_W_TYPE) 1 << 1) +#define _FP_WORK_STICKY ((_FP_W_TYPE) 1 << 0) + +#ifndef FP_RND_NEAREST +# define FP_RND_NEAREST 0 +# define FP_RND_ZERO 1 +# define FP_RND_PINF 2 +# define FP_RND_MINF 3 +#endif +#ifndef FP_ROUNDMODE +# define FP_ROUNDMODE FP_RND_NEAREST +#endif + +/* By default don't care about exceptions. */ +#ifndef FP_EX_INVALID +# define FP_EX_INVALID 0 +#endif +#ifndef FP_EX_OVERFLOW +# define FP_EX_OVERFLOW 0 +#endif +#ifndef FP_EX_UNDERFLOW +# define FP_EX_UNDERFLOW 0 +#endif +#ifndef FP_EX_DIVZERO +# define FP_EX_DIVZERO 0 +#endif +#ifndef FP_EX_INEXACT +# define FP_EX_INEXACT 0 +#endif +#ifndef FP_EX_DENORM +# define FP_EX_DENORM 0 +#endif + +/* Sub-exceptions of "invalid". */ +/* Signaling NaN operand. */ +#ifndef FP_EX_INVALID_SNAN +# define FP_EX_INVALID_SNAN 0 +#endif +/* Inf * 0. */ +#ifndef FP_EX_INVALID_IMZ +# define FP_EX_INVALID_IMZ 0 +#endif +/* fma (Inf, 0, c). */ +#ifndef FP_EX_INVALID_IMZ_FMA +# define FP_EX_INVALID_IMZ_FMA 0 +#endif +/* Inf - Inf. */ +#ifndef FP_EX_INVALID_ISI +# define FP_EX_INVALID_ISI 0 +#endif +/* 0 / 0. */ +#ifndef FP_EX_INVALID_ZDZ +# define FP_EX_INVALID_ZDZ 0 +#endif +/* Inf / Inf. */ +#ifndef FP_EX_INVALID_IDI +# define FP_EX_INVALID_IDI 0 +#endif +/* sqrt (negative). */ +#ifndef FP_EX_INVALID_SQRT +# define FP_EX_INVALID_SQRT 0 +#endif +/* Invalid conversion to integer. */ +#ifndef FP_EX_INVALID_CVI +# define FP_EX_INVALID_CVI 0 +#endif +/* Invalid comparison. */ +#ifndef FP_EX_INVALID_VC +# define FP_EX_INVALID_VC 0 +#endif + +/* _FP_STRUCT_LAYOUT may be defined as an attribute to determine the + struct layout variant used for structures where bit-fields are used + to access specific parts of binary floating-point numbers. This is + required for systems where the default ABI uses struct layout with + differences in how consecutive bit-fields are laid out from the + default expected by soft-fp. */ +#ifndef _FP_STRUCT_LAYOUT +# define _FP_STRUCT_LAYOUT +#endif + +#ifdef _FP_DECL_EX +# define FP_DECL_EX \ + int _fex = 0; \ + _FP_DECL_EX +#else +# define FP_DECL_EX int _fex = 0 +#endif + +/* Initialize any machine-specific state used in FP_ROUNDMODE, + FP_TRAPPING_EXCEPTIONS or FP_HANDLE_EXCEPTIONS. */ +#ifndef FP_INIT_ROUNDMODE +# define FP_INIT_ROUNDMODE do {} while (0) +#endif + +/* Initialize any machine-specific state used in + FP_TRAPPING_EXCEPTIONS or FP_HANDLE_EXCEPTIONS. */ +#ifndef FP_INIT_TRAPPING_EXCEPTIONS +# define FP_INIT_TRAPPING_EXCEPTIONS FP_INIT_ROUNDMODE +#endif + +/* Initialize any machine-specific state used in + FP_HANDLE_EXCEPTIONS. */ +#ifndef FP_INIT_EXCEPTIONS +# define FP_INIT_EXCEPTIONS FP_INIT_TRAPPING_EXCEPTIONS +#endif + +#ifndef FP_HANDLE_EXCEPTIONS +# define FP_HANDLE_EXCEPTIONS do {} while (0) +#endif + +/* Whether to flush subnormal inputs to zero with the same sign. */ +#ifndef FP_DENORM_ZERO +# define FP_DENORM_ZERO 0 +#endif + +#ifndef FP_INHIBIT_RESULTS +/* By default we write the results always. + sfp-machine may override this and e.g. + check if some exceptions are unmasked + and inhibit it in such a case. */ +# define FP_INHIBIT_RESULTS 0 +#endif + +#define FP_SET_EXCEPTION(ex) \ + _fex |= (ex) + +#define FP_CUR_EXCEPTIONS \ + (_fex) + +#ifndef FP_TRAPPING_EXCEPTIONS +# define FP_TRAPPING_EXCEPTIONS 0 +#endif + +/* A file using soft-fp may define FP_NO_EXCEPTIONS before including + soft-fp.h to indicate that, although a macro used there could raise + exceptions, or do rounding and potentially thereby raise + exceptions, for some arguments, for the particular arguments used + in that file no exceptions or rounding can occur. Such a file + should not itself use macros relating to handling exceptions and + rounding modes; this is only for indirect uses (in particular, in + _FP_FROM_INT and the macros it calls). */ +#ifdef FP_NO_EXCEPTIONS + +# undef FP_SET_EXCEPTION +# define FP_SET_EXCEPTION(ex) do {} while (0) + +# undef FP_CUR_EXCEPTIONS +# define FP_CUR_EXCEPTIONS 0 + +# undef FP_TRAPPING_EXCEPTIONS +# define FP_TRAPPING_EXCEPTIONS 0 + +# undef FP_ROUNDMODE +# define FP_ROUNDMODE FP_RND_ZERO + +# undef _FP_TININESS_AFTER_ROUNDING +# define _FP_TININESS_AFTER_ROUNDING 0 + +#endif + +/* A file using soft-fp may define FP_NO_EXACT_UNDERFLOW before + including soft-fp.h to indicate that, although a macro used there + could allow for the case of exact underflow requiring the underflow + exception to be raised if traps are enabled, for the particular + arguments used in that file no exact underflow can occur. */ +#ifdef FP_NO_EXACT_UNDERFLOW +# undef FP_TRAPPING_EXCEPTIONS +# define FP_TRAPPING_EXCEPTIONS 0 +#endif + +#define _FP_ROUND_NEAREST(wc, X) \ + do \ + { \ + if ((_FP_FRAC_LOW_##wc (X) & 15) != _FP_WORK_ROUND) \ + _FP_FRAC_ADDI_##wc (X, _FP_WORK_ROUND); \ + } \ + while (0) + +#define _FP_ROUND_ZERO(wc, X) (void) 0 + +#define _FP_ROUND_PINF(wc, X) \ + do \ + { \ + if (!X##_s && (_FP_FRAC_LOW_##wc (X) & 7)) \ + _FP_FRAC_ADDI_##wc (X, _FP_WORK_LSB); \ + } \ + while (0) + +#define _FP_ROUND_MINF(wc, X) \ + do \ + { \ + if (X##_s && (_FP_FRAC_LOW_##wc (X) & 7)) \ + _FP_FRAC_ADDI_##wc (X, _FP_WORK_LSB); \ + } \ + while (0) + +#define _FP_ROUND(wc, X) \ + do \ + { \ + if (_FP_FRAC_LOW_##wc (X) & 7) \ + { \ + FP_SET_EXCEPTION (FP_EX_INEXACT); \ + switch (FP_ROUNDMODE) \ + { \ + case FP_RND_NEAREST: \ + _FP_ROUND_NEAREST (wc, X); \ + break; \ + case FP_RND_ZERO: \ + _FP_ROUND_ZERO (wc, X); \ + break; \ + case FP_RND_PINF: \ + _FP_ROUND_PINF (wc, X); \ + break; \ + case FP_RND_MINF: \ + _FP_ROUND_MINF (wc, X); \ + break; \ + } \ + } \ + } \ + while (0) + +#define FP_CLS_NORMAL 0 +#define FP_CLS_ZERO 1 +#define FP_CLS_INF 2 +#define FP_CLS_NAN 3 + +#define _FP_CLS_COMBINE(x, y) (((x) << 2) | (y)) + +#include "op-1.h" +#include "op-2.h" +#include "op-4.h" +#include "op-8.h" +#include "op-common.h" + +/* Sigh. Silly things longlong.h needs. */ +#define UWtype _FP_W_TYPE +#define W_TYPE_SIZE _FP_W_TYPE_SIZE + +typedef int QItype __attribute__ ((mode (QI))); +typedef int SItype __attribute__ ((mode (SI))); +typedef int DItype __attribute__ ((mode (DI))); +typedef unsigned int UQItype __attribute__ ((mode (QI))); +typedef unsigned int USItype __attribute__ ((mode (SI))); +typedef unsigned int UDItype __attribute__ ((mode (DI))); +#if _FP_W_TYPE_SIZE == 32 +typedef unsigned int UHWtype __attribute__ ((mode (HI))); +#elif _FP_W_TYPE_SIZE == 64 +typedef USItype UHWtype; +#endif + +#ifndef CMPtype +# define CMPtype int +#endif + +#define SI_BITS (__CHAR_BIT__ * (int) sizeof (SItype)) +#define DI_BITS (__CHAR_BIT__ * (int) sizeof (DItype)) + +#ifndef umul_ppmm +# ifdef _LIBC +# include +# else +# include "longlong.h" +# endif +#endif + +#endif /* !SOFT_FP_H */ From patchwork Sun Feb 4 04:11:23 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Richard Henderson X-Patchwork-Id: 126811 Delivered-To: patch@linaro.org Received: by 10.80.172.228 with SMTP id x91csp1227984edc; Sat, 3 Feb 2018 20:26:26 -0800 (PST) X-Google-Smtp-Source: AH8x225u8LKIGG28+IuuQfG5kzamVD7O51lQE7xUXalubv0QT1q5rcBJVcsgc9SkRolBwZWAq35r X-Received: by 10.37.55.138 with SMTP id e132mr8749057yba.110.1517718385931; Sat, 03 Feb 2018 20:26:25 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1517718385; cv=none; d=google.com; s=arc-20160816; b=kyINbGaQ1f8gKloedW17iCo9NVQr3vJA7xSmWRnRIMUqjxZptOQeTXTxPhCji5T6nB 06KhWBssDrdqBx8mUCxAMpWv2I/YjvwOAIQWsmUEUDvo+GSPjmaRk1RwyLco9/3FfTgv DyXBTk/fgWAj/2z3hRPS/5l+/S6Gga7PNv4J1FBzVPh8yLmlIEhUJ7YM/1avRb0gZOZR hYI2ziG0LuPbmVfpUZbPNIEXEAOMhFGrzJ7JRsJdLhAxzA3x2D/VNXCw9nZpEfMeG+OA zXoFNDEJryH2t4TvPwKZ5Iz+zBW17rlxD/E/eia0ST/5y/1+ylJhmWOpRef8sIzT9cox 18PQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=sender:errors-to:cc:list-subscribe:list-help:list-post:list-archive :list-unsubscribe:list-id:precedence:subject:references:in-reply-to :message-id:date:to:from:dkim-signature:arc-authentication-results; bh=ONpNPHQiOaInUhbuueSdhiKAc0We9zR8arc4jZRkfBs=; b=TFLFqkWvWoNhwIt0R6TkKDfWIuNFZNsmSBL2+X1F+o/O53JOJpfIP73ZrzXBGMaGt7 XroC+KEAe5CaE07EYZqH/iHnqN7tGF0d2k1i/2qjOdr2Jw6PxBILyh5rTzEkJowPdzUT QBcK78r35fLSxIsUbGpWrVpvo091CyowHTE+BRg3y34vcUJ6GbX4/KDeePJnVNWWCtN9 7D16x+x6DOEpg3vUbJbSF5R6D+ZNjdco56LRO/WJdnHL0paer/cAzSWug7l8xIiskqOb eTwk9gn6R3XvC/f7vvzKJvFbMID9TyRWfrx5pGYxykf0EPT8lV5bPW8OL+Li49UXwMgs X0iA== ARC-Authentication-Results: i=1; mx.google.com; dkim=fail header.i=@linaro.org header.s=google header.b=Ei/39uhL; spf=pass (google.com: domain of qemu-devel-bounces+patch=linaro.org@nongnu.org designates 2001:4830:134:3::11 as permitted sender) smtp.mailfrom=qemu-devel-bounces+patch=linaro.org@nongnu.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=linaro.org Return-Path: Received: from lists.gnu.org (lists.gnu.org. [2001:4830:134:3::11]) by mx.google.com with ESMTPS id g20si1058275ybh.103.2018.02.03.20.26.25 for (version=TLS1 cipher=AES128-SHA bits=128/128); Sat, 03 Feb 2018 20:26:25 -0800 (PST) Received-SPF: pass (google.com: domain of qemu-devel-bounces+patch=linaro.org@nongnu.org designates 2001:4830:134:3::11 as permitted sender) client-ip=2001:4830:134:3::11; Authentication-Results: mx.google.com; dkim=fail header.i=@linaro.org header.s=google header.b=Ei/39uhL; spf=pass (google.com: domain of qemu-devel-bounces+patch=linaro.org@nongnu.org designates 2001:4830:134:3::11 as permitted sender) smtp.mailfrom=qemu-devel-bounces+patch=linaro.org@nongnu.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=linaro.org Received: from localhost ([::1]:58329 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1eiBsn-00087V-8h for patch@linaro.org; Sat, 03 Feb 2018 23:26:25 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:47344) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1eiBeo-0004gK-Gv for qemu-devel@nongnu.org; Sat, 03 Feb 2018 23:11:59 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1eiBen-0004xY-HG for qemu-devel@nongnu.org; Sat, 03 Feb 2018 23:11:58 -0500 Received: from mail-pl0-x242.google.com ([2607:f8b0:400e:c01::242]:34683) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1eiBen-0004xE-BD for qemu-devel@nongnu.org; Sat, 03 Feb 2018 23:11:57 -0500 Received: by mail-pl0-x242.google.com with SMTP id q17so7156124pll.1 for ; Sat, 03 Feb 2018 20:11:57 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=ONpNPHQiOaInUhbuueSdhiKAc0We9zR8arc4jZRkfBs=; b=Ei/39uhLESo7vmxMp8KyosrWyanz6fAXrUMBrYfhqTKMdtWq+NfmqkL0rlzUir15CO 9uCLdnD4nfUyu79NffvHafpqRsC6jLNNzLPtKk7av6y7u9f8Ynym+qdOyzVsFjNui2NI /8NjKN25hBsf6x3CTj7Kfn206Tg/deWKJcfwk= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=ONpNPHQiOaInUhbuueSdhiKAc0We9zR8arc4jZRkfBs=; b=iNfxScT/SQvum6cdz9HORaVYryxDmWmtJM7IwlwGNP8JdW970XtnvYqJ3ZTnJ9UCLh RfeNdIIy9gSFsCUkHv0lFIX4ziLM+yWylz01nwuUyoxhduKyUSfSp0kycEA/F3yxWR9b nc7EgUCm5eojnI+n+vDFJM0EuknB3UEwfJN4mnzZkHfIywkNkABQON2JmQi0KY1PTzBs pyNuxhVLe/xRl1pZ/Z2xH4Wr6Ov0x83xf/Yf2IH+cTy04sS27meMJdX8rSHX3b6arngL VajVfPpwdKe++UbFo0aWvRYEcivbXTDNrKCkruqPk4D3PQLsjVx806jK0KerJhliO++x 5E4Q== X-Gm-Message-State: AKwxytfzmA/JoxAcTqcp8g4RRNOldgb+W9QwPLbLTviE3bTSDu3PqXOv i8DJifvGkfWcNc9NCSsz3V9Fnsl3Q28= X-Received: by 2002:a17:902:51e9:: with SMTP id y96-v6mr19993416plh.344.1517717516180; Sat, 03 Feb 2018 20:11:56 -0800 (PST) Received: from cloudburst.twiddle.net (174-21-6-47.tukw.qwest.net. [174.21.6.47]) by smtp.gmail.com with ESMTPSA id k3sm1399425pgr.12.2018.02.03.20.11.54 (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Sat, 03 Feb 2018 20:11:55 -0800 (PST) From: Richard Henderson To: qemu-devel@nongnu.org Date: Sat, 3 Feb 2018 20:11:23 -0800 Message-Id: <20180204041136.17525-12-richard.henderson@linaro.org> X-Mailer: git-send-email 2.14.3 In-Reply-To: <20180204041136.17525-1-richard.henderson@linaro.org> References: <20180204041136.17525-1-richard.henderson@linaro.org> X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 2607:f8b0:400e:c01::242 Subject: [Qemu-devel] [PATCH 11/24] fpu/soft-fp: Adjust soft-fp types X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: peter.maydell@linaro.org, cota@braap.org, alex.bennee@linaro.org, hsp.cat7@gmail.com Errors-To: qemu-devel-bounces+patch=linaro.org@nongnu.org Sender: "Qemu-devel" Glibc uses host compiler floating-point types for packing. We need to use softfloat.h types. Signed-off-by: Richard Henderson --- fpu/double.h | 6 ++---- fpu/half.h | 4 +--- fpu/quad.h | 6 ++---- fpu/single.h | 4 +--- 4 files changed, 6 insertions(+), 14 deletions(-) -- 2.14.3 diff --git a/fpu/double.h b/fpu/double.h index f6c83d7253..6f8fe49a7d 100644 --- a/fpu/double.h +++ b/fpu/double.h @@ -69,13 +69,11 @@ #define _FP_HIGHBIT_DW_D \ ((_FP_W_TYPE) 1 << (_FP_WFRACBITS_DW_D - 1) % _FP_W_TYPE_SIZE) -typedef float DFtype __attribute__ ((mode (DF))); - #if _FP_W_TYPE_SIZE < 64 union _FP_UNION_D { - DFtype flt; + float64 flt; struct _FP_STRUCT_LAYOUT { # if __BYTE_ORDER == __BIG_ENDIAN @@ -198,7 +196,7 @@ union _FP_UNION_D union _FP_UNION_D { - DFtype flt; + float64 flt; struct _FP_STRUCT_LAYOUT { # if __BYTE_ORDER == __BIG_ENDIAN diff --git a/fpu/half.h b/fpu/half.h index ea28db6c18..75a3168a75 100644 --- a/fpu/half.h +++ b/fpu/half.h @@ -59,11 +59,9 @@ /* The implementation of _FP_MUL_MEAT_H and _FP_DIV_MEAT_H should be chosen by the target machine. */ -typedef float HFtype __attribute__ ((mode (HF))); - union _FP_UNION_H { - HFtype flt; + float16 flt; struct _FP_STRUCT_LAYOUT { #if __BYTE_ORDER == __BIG_ENDIAN diff --git a/fpu/quad.h b/fpu/quad.h index 71621f01bf..24a3245fb7 100644 --- a/fpu/quad.h +++ b/fpu/quad.h @@ -69,13 +69,11 @@ #define _FP_HIGHBIT_DW_Q \ ((_FP_W_TYPE) 1 << (_FP_WFRACBITS_DW_Q - 1) % _FP_W_TYPE_SIZE) -typedef float TFtype __attribute__ ((mode (TF))); - #if _FP_W_TYPE_SIZE < 64 union _FP_UNION_Q { - TFtype flt; + float128 flt; struct _FP_STRUCT_LAYOUT { # if __BYTE_ORDER == __BIG_ENDIAN @@ -202,7 +200,7 @@ union _FP_UNION_Q #else /* not _FP_W_TYPE_SIZE < 64 */ union _FP_UNION_Q { - TFtype flt /* __attribute__ ((mode (TF))) */ ; + float128 flt; struct _FP_STRUCT_LAYOUT { _FP_W_TYPE a, b; diff --git a/fpu/single.h b/fpu/single.h index 2918f78d97..91252f82ff 100644 --- a/fpu/single.h +++ b/fpu/single.h @@ -66,11 +66,9 @@ /* The implementation of _FP_MUL_MEAT_S and _FP_DIV_MEAT_S should be chosen by the target machine. */ -typedef float SFtype __attribute__ ((mode (SF))); - union _FP_UNION_S { - SFtype flt; + float32 flt; struct _FP_STRUCT_LAYOUT { #if __BYTE_ORDER == __BIG_ENDIAN From patchwork Sun Feb 4 04:11:24 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Richard Henderson X-Patchwork-Id: 126803 Delivered-To: patch@linaro.org Received: by 10.46.124.24 with SMTP id x24csp926782ljc; Sat, 3 Feb 2018 20:20:50 -0800 (PST) X-Google-Smtp-Source: AH8x227sdLlC/X/VVUli29QsMAy/W+lZD+mcGpVWgmF2hLFks2AJ3eCjTfbnidO5uRO0TfbOrM89 X-Received: by 10.37.206.134 with SMTP id x128mr8638634ybe.83.1517718050379; Sat, 03 Feb 2018 20:20:50 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1517718050; cv=none; d=google.com; s=arc-20160816; b=kERcTsWXQ2LwV26UhifkCYLW7+O0nw8vI9bfAvqyALi9iWb65TDYxOyXHdKSomJ8FL 2pdgHQlK6nXS/7j6w9VcVrGaAR338Gq2/8NZDqDRRE+eWD9orgWjAMu0qS55LbyWR3WZ Hi0+lZ+PsHvKqenp++ajW+tCE51h+61BGm6mhugCFQLRaPoWrnLbF+69dW0qp8TwzVNk K9bOCT3TBE9CQsqarILhWJA2dYmLisROQ6uh/ogyy57Gte73BagNMZzHplahtvVrid4W m83bJHsLZeJ7SNFmkTTa7vHpHMn/Eunklfh67OEFFp2GOpy0dZxqoMXgtmBJ98s3fU8+ hKHA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=sender:errors-to:cc:list-subscribe:list-help:list-post:list-archive :list-unsubscribe:list-id:precedence:subject:references:in-reply-to :message-id:date:to:from:dkim-signature:arc-authentication-results; bh=0SCjxxEWFJsjx9dBnP24HcnJKoUvfKn58tKIdmV+sDM=; b=jWhgFyP83buwY9STppcglORPZVRP6t0WBi7juT02rPPs3CsCeavk+FEJ0I9ci5sMEX jTWzCvHg4ng8cYCmuix5MMP9aRCzAoi6IWF/7TQXrVqhtIIVqvNh7glQ5v3LNTRZnuLc qtiAzugxrcfTMDZKjHCdrBQRZDFI11ZEwh6QllyJK/j23mc2MFbMCXwoFrv2nXx1Sf9R nm/QdSFr81+pgi9S8jEu6aPwafpAA7YK/PazSPeWiYJOfxie63nzd9CRoILJu/5Tw6YJ NewXaWLtByTzdnMTg8QoOvuGbKagUj1EUSZtTZvdiU2YcMw38ahM95ms7hNXW/xCTs8l EZdA== ARC-Authentication-Results: i=1; mx.google.com; dkim=fail header.i=@linaro.org header.s=google header.b=hJeba4/q; spf=pass (google.com: domain of qemu-devel-bounces+patch=linaro.org@nongnu.org designates 2001:4830:134:3::11 as permitted sender) smtp.mailfrom=qemu-devel-bounces+patch=linaro.org@nongnu.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=linaro.org Return-Path: Received: from lists.gnu.org (lists.gnu.org. [2001:4830:134:3::11]) by mx.google.com with ESMTPS id d10si1010798ybi.758.2018.02.03.20.20.50 for (version=TLS1 cipher=AES128-SHA bits=128/128); Sat, 03 Feb 2018 20:20:50 -0800 (PST) Received-SPF: pass (google.com: domain of qemu-devel-bounces+patch=linaro.org@nongnu.org designates 2001:4830:134:3::11 as permitted sender) client-ip=2001:4830:134:3::11; Authentication-Results: mx.google.com; dkim=fail header.i=@linaro.org header.s=google header.b=hJeba4/q; spf=pass (google.com: domain of qemu-devel-bounces+patch=linaro.org@nongnu.org designates 2001:4830:134:3::11 as permitted sender) smtp.mailfrom=qemu-devel-bounces+patch=linaro.org@nongnu.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=linaro.org Received: from localhost ([::1]:58289 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1eiBnN-0002pY-Jg for patch@linaro.org; Sat, 03 Feb 2018 23:20:49 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:47355) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1eiBep-0004hf-Sq for qemu-devel@nongnu.org; Sat, 03 Feb 2018 23:12:00 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1eiBeo-0004y1-Tw for qemu-devel@nongnu.org; Sat, 03 Feb 2018 23:11:59 -0500 Received: from mail-pl0-x241.google.com ([2607:f8b0:400e:c01::241]:37814) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1eiBeo-0004xn-Ng for qemu-devel@nongnu.org; Sat, 03 Feb 2018 23:11:58 -0500 Received: by mail-pl0-x241.google.com with SMTP id ay8so9372650plb.4 for ; Sat, 03 Feb 2018 20:11:58 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=0SCjxxEWFJsjx9dBnP24HcnJKoUvfKn58tKIdmV+sDM=; b=hJeba4/qX4IsaQKHq9pIlc410L5cAviqAM8VKHGfqa7MToK/QrurxFZ0c7AROx7kAl ttUUgiqt7U5sfqIgUlDK0a4Lo+6/NDH9vXC7mmnp6eOg5eouO/60bbnMeB8gvM/6noiP sh+ID/d0kD2NciC2XQn8r3om9hVw1VeCwmupI= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=0SCjxxEWFJsjx9dBnP24HcnJKoUvfKn58tKIdmV+sDM=; b=tFdLaZYNLdwJk9G46OL12wdPD50HNkNcKmwFQDD7CMINr4K4/KcJo635V4zrj9CGAq bdQRpaIxDgG1sKDpUAW/gW3ACnblr6WtKlD+dlU/pNe5KAR4NR0zEMIFbrzR3cTqh8NH JVVcgXOXZtdvYLqskOoHHv4hnaWvQK/eoD+Dh5lR17m6dPltiBCK4Gdeb4PNOm6w7atC lgOuW4j4ubIFWfUBxcSQB1W0jssDKjbB8m7ziHEPLQhKpTSA7sF6uFm6N+y+V5KavlvL qmuJXBp7dgAPcoUE3g1JMtHC5JApc3fG0ay92xPo5aP+WsEXdkCiiIl8XvELl6qejNd0 +aSQ== X-Gm-Message-State: AKwxytfYwm2crV0iH7W0J4TAWzf2vS5LQznZCFWy6OXZY6Am3HPUExl1 Hib0kUJYZ7KwwvV4Y+DTKAUItQSbI48= X-Received: by 2002:a17:902:8c89:: with SMTP id t9-v6mr38495202plo.2.1517717517495; Sat, 03 Feb 2018 20:11:57 -0800 (PST) Received: from cloudburst.twiddle.net (174-21-6-47.tukw.qwest.net. [174.21.6.47]) by smtp.gmail.com with ESMTPSA id k3sm1399425pgr.12.2018.02.03.20.11.56 (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Sat, 03 Feb 2018 20:11:56 -0800 (PST) From: Richard Henderson To: qemu-devel@nongnu.org Date: Sat, 3 Feb 2018 20:11:24 -0800 Message-Id: <20180204041136.17525-13-richard.henderson@linaro.org> X-Mailer: git-send-email 2.14.3 In-Reply-To: <20180204041136.17525-1-richard.henderson@linaro.org> References: <20180204041136.17525-1-richard.henderson@linaro.org> X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 2607:f8b0:400e:c01::241 Subject: [Qemu-devel] [PATCH 12/24] fpu/soft-fp: Add ties_away and to_odd rounding modes X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: peter.maydell@linaro.org, cota@braap.org, alex.bennee@linaro.org, hsp.cat7@gmail.com Errors-To: qemu-devel-bounces+patch=linaro.org@nongnu.org Sender: "Qemu-devel" These rounding modes are used by ARM and PowerPC respectively. Signed-off-by: Richard Henderson --- fpu/op-common.h | 20 ++++++++++++++++++++ fpu/soft-fp.h | 25 +++++++++++++++++++++++++ 2 files changed, 45 insertions(+) -- 2.14.3 diff --git a/fpu/op-common.h b/fpu/op-common.h index 4526afd1b6..c5f33c0148 100644 --- a/fpu/op-common.h +++ b/fpu/op-common.h @@ -130,6 +130,7 @@ do \ { \ if (FP_ROUNDMODE == FP_RND_NEAREST \ + || FP_ROUNDMODE == FP_RND_TIESAWAY \ || (FP_ROUNDMODE == FP_RND_PINF && !X##_s) \ || (FP_ROUNDMODE == FP_RND_MINF && X##_s)) \ { \ @@ -287,6 +288,7 @@ switch (FP_ROUNDMODE) \ { \ case FP_RND_NEAREST: \ + case FP_RND_TIESAWAY: \ X##_c = FP_CLS_INF; \ break; \ case FP_RND_PINF: \ @@ -297,6 +299,10 @@ if (X##_s) \ X##_c = FP_CLS_INF; \ break; \ + case FP_RND_ODD: \ + break; \ + default: \ + _FP_UNREACHABLE; \ } \ if (X##_c == FP_CLS_INF) \ { \ @@ -1610,10 +1616,14 @@ switch (FP_ROUNDMODE) \ { \ case FP_RND_NEAREST: \ + case FP_RND_TIESAWAY: \ _FP_TO_INT_ROUND_rounds_away \ = (X##_e == _FP_EXPBIAS_##fs - 1 \ && !_FP_FRAC_ZEROP_##wc (X)); \ break; \ + case FP_RND_ODD: \ + _FP_TO_INT_ROUND_rounds_away = 1; \ + break; \ case FP_RND_ZERO: \ /* _FP_TO_INT_ROUND_rounds_away is already 0. */ \ break; \ @@ -1623,6 +1633,8 @@ case FP_RND_MINF: \ _FP_TO_INT_ROUND_rounds_away = X##_s; \ break; \ + default: \ + _FP_UNREACHABLE; \ } \ if ((rsigned) == 0 && _FP_TO_INT_ROUND_rounds_away && X##_s) \ { \ @@ -1740,6 +1752,14 @@ case FP_RND_MINF: \ _FP_ROUND_MINF (wc, X); \ break; \ + case FP_RND_TIESAWAY: \ + _FP_ROUND_TIESAWAY (wc, X); \ + break; \ + case FP_RND_ODD: \ + _FP_ROUND_ODD (wc, X); \ + break; \ + default: \ + _FP_UNREACHABLE; \ } \ } \ _FP_FRAC_SRL_##wc (X, _FP_WORKBITS); \ diff --git a/fpu/soft-fp.h b/fpu/soft-fp.h index a7a01334b7..a95485f465 100644 --- a/fpu/soft-fp.h +++ b/fpu/soft-fp.h @@ -93,6 +93,8 @@ # define FP_RND_ZERO 1 # define FP_RND_PINF 2 # define FP_RND_MINF 3 +# define FP_RND_TIESAWAY 4 +# define FP_RND_ODD 5 #endif #ifndef FP_ROUNDMODE # define FP_ROUNDMODE FP_RND_NEAREST @@ -282,6 +284,21 @@ } \ while (0) +#define _FP_ROUND_TIESAWAY(wc, X) \ + do \ + { \ + _FP_FRAC_ADDI_##wc (X, _FP_WORK_ROUND); \ + } \ + while (0) + +#define _FP_ROUND_ODD(wc, X) \ + do \ + { \ + if (!(_FP_FRAC_LOW_##wc (X) & _FP_WORK_LSB)) \ + _FP_FRAC_ADDI_##wc (X, _FP_WORK_LSB - 1); \ + } \ + while (0) + #define _FP_ROUND(wc, X) \ do \ { \ @@ -302,6 +319,14 @@ case FP_RND_MINF: \ _FP_ROUND_MINF (wc, X); \ break; \ + case FP_RND_TIESAWAY: \ + _FP_ROUND_TIESAWAY (wc, X); \ + break; \ + case FP_RND_ODD: \ + _FP_ROUND_ODD (wc, X); \ + break; \ + default: \ + _FP_UNREACHABLE; \ } \ } \ } \ From patchwork Sun Feb 4 04:11:25 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Richard Henderson X-Patchwork-Id: 126813 Delivered-To: patch@linaro.org Received: by 10.80.172.228 with SMTP id x91csp1228193edc; Sat, 3 Feb 2018 20:26:55 -0800 (PST) X-Google-Smtp-Source: AH8x226WaYZk/6CwqjXioArsQ6JttHILoTYXho9/l1KN3JJyXUyiswEnRHlmeP65+JxiRZQkKWvr X-Received: by 10.13.234.66 with SMTP id t63mr30470786ywe.319.1517718415042; Sat, 03 Feb 2018 20:26:55 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1517718415; cv=none; d=google.com; s=arc-20160816; b=LtVYAjt1rMUOfNTkyxfN2fUIOnr10vrsbMXTAUh/PwnPz/eLtCRcXSWpaFZ0mD8jQl Gjmll3rHwD9y8MgG+9zt0MLNO1w62C7j2zcnPTJr4Q9Z7tKwJ+7FEKmPdZFrpi0X90H4 4MFMr06tcFMNyMmyYXyXA12ir1xREPGNA/PRlFHnHGjg6uavwJZKfwFRLZFBx7o3uq0V L5eeJcTPkTcBDzxGIx/QUWOYjCCrteYOGS0FGjnGKxYa31uRf+orkJcGyP7BEDZknckf UuBAfxqX8YwjAniU6Z39AY70JKYcu6aNh2nkH6VeHF8kRERr39FCO2KuZy5UOz3qfTCE Wkzg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=sender:errors-to:cc:list-subscribe:list-help:list-post:list-archive :list-unsubscribe:list-id:precedence:subject:references:in-reply-to :message-id:date:to:from:dkim-signature:arc-authentication-results; bh=6wLWChsK8okp0FYwdcnmAQywbUh86H7poSOt5I9EA8A=; b=miwgELZsT2+BlWCLpZLBU8MH53A+pMERdHnMckKEOrP4I63qM/VAlgOW42F9GeGlOk DVmZAeRBk38wWPPXRHCwWjyu7KWEw8p34+SjZDjvRYCCYevs3c2Hv7pySK36K+nuNoU/ xO5SEAjDH5gkC/fPu2iLHTqtqzmkRWm2vpJLRe55rhn6zKA4ksqCrEkgPWj/WLdF1P9Q Ep5xz5wkpvZ+tXQOwasIZTnSAQ9MsA1iwU2TPEEe6Uny/8Tw4havdarTSg9zt7j0A2DN PlrtnQDsmzNO1oB5oV4Udb+LsQP5BxWlGMbcyL5H2yrvfs4wCUCGNZag/d5hmyBhQqvU fp8A== ARC-Authentication-Results: i=1; mx.google.com; dkim=fail header.i=@linaro.org header.s=google header.b=EdjqOqp7; spf=pass (google.com: domain of qemu-devel-bounces+patch=linaro.org@nongnu.org designates 2001:4830:134:3::11 as permitted sender) smtp.mailfrom=qemu-devel-bounces+patch=linaro.org@nongnu.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=linaro.org Return-Path: Received: from lists.gnu.org (lists.gnu.org. [2001:4830:134:3::11]) by mx.google.com with ESMTPS id m186si499091ywb.96.2018.02.03.20.26.54 for (version=TLS1 cipher=AES128-SHA bits=128/128); Sat, 03 Feb 2018 20:26:55 -0800 (PST) Received-SPF: pass (google.com: domain of qemu-devel-bounces+patch=linaro.org@nongnu.org designates 2001:4830:134:3::11 as permitted sender) client-ip=2001:4830:134:3::11; Authentication-Results: mx.google.com; dkim=fail header.i=@linaro.org header.s=google header.b=EdjqOqp7; spf=pass (google.com: domain of qemu-devel-bounces+patch=linaro.org@nongnu.org designates 2001:4830:134:3::11 as permitted sender) smtp.mailfrom=qemu-devel-bounces+patch=linaro.org@nongnu.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=linaro.org Received: from localhost ([::1]:58340 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1eiBtG-00012g-Ed for patch@linaro.org; Sat, 03 Feb 2018 23:26:54 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:47367) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1eiBer-0004j5-8A for qemu-devel@nongnu.org; Sat, 03 Feb 2018 23:12:02 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1eiBeq-0004yZ-7z for qemu-devel@nongnu.org; Sat, 03 Feb 2018 23:12:01 -0500 Received: from mail-pl0-x242.google.com ([2607:f8b0:400e:c01::242]:34892) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1eiBeq-0004yH-2K for qemu-devel@nongnu.org; Sat, 03 Feb 2018 23:12:00 -0500 Received: by mail-pl0-x242.google.com with SMTP id j19so9379034pll.2 for ; Sat, 03 Feb 2018 20:12:00 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=6wLWChsK8okp0FYwdcnmAQywbUh86H7poSOt5I9EA8A=; b=EdjqOqp7bYkQwmhyIxf1d2ZbD2D04b+ghVAdx7BjXpqapcjdDU3lCQWt6ApEVIS2aD oPv+mc6AHXaEZxojBd6kfeJZQR78WHA/jq6H6WfNkxZ0dYdbrOW8Dkw2N0i0TSrHSWf4 HYLU48GwlrWMLCZasdghp6jz3X/RdBOaP+Luc= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=6wLWChsK8okp0FYwdcnmAQywbUh86H7poSOt5I9EA8A=; b=HNluMFSdqqlTI4U7ez1vBVpiCdmJTeIa66ahvjTvqNJUy2I4rt39gNR8AzeumQEwMB y6rnkknxMkFZeMZtUzU5Z73ehFAWm5OydzCc73EFZbcBuCsPeO0GucgNTKVdXKQjqNjY WO4/gYXSGonWx+gZr7jr6Ax0Mxp5Bk4kJf/x31BJGkiqhKWtOOYwi8jOjiNJm5J/oGsF TN3DNySV+Y5jiAZO1b7byd6Qfpe5ox7oCt9y8adyAn5nRYqi/4ILSgIBJZ+ZUQHiqYXO 6JOsmujY4Lm6wHDjYGzcB0hWrsLndpJAQURk+eN3MtxSYXQlWvpETmAMsQv/ppAE7b7l AIsw== X-Gm-Message-State: AKwxytf7qL8koYRVHabmXn+/QXiPVdC7ETLlowyBUeGHxYQc8oBc1/bV TEz495auC7k1xBV/CgCO8GqXBVyzumI= X-Received: by 2002:a17:902:8:: with SMTP id 8-v6mr39418997pla.415.1517717518939; Sat, 03 Feb 2018 20:11:58 -0800 (PST) Received: from cloudburst.twiddle.net (174-21-6-47.tukw.qwest.net. [174.21.6.47]) by smtp.gmail.com with ESMTPSA id k3sm1399425pgr.12.2018.02.03.20.11.57 (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Sat, 03 Feb 2018 20:11:58 -0800 (PST) From: Richard Henderson To: qemu-devel@nongnu.org Date: Sat, 3 Feb 2018 20:11:25 -0800 Message-Id: <20180204041136.17525-14-richard.henderson@linaro.org> X-Mailer: git-send-email 2.14.3 In-Reply-To: <20180204041136.17525-1-richard.henderson@linaro.org> References: <20180204041136.17525-1-richard.henderson@linaro.org> X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 2607:f8b0:400e:c01::242 Subject: [Qemu-devel] [PATCH 13/24] fpu/soft-fp: Add arithmetic macros to half.h X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: peter.maydell@linaro.org, cota@braap.org, alex.bennee@linaro.org, hsp.cat7@gmail.com Errors-To: qemu-devel-bounces+patch=linaro.org@nongnu.org Sender: "Qemu-devel" These were omitted from upstream glibc for some reason. Signed-off-by: Richard Henderson --- fpu/half.h | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) -- 2.14.3 diff --git a/fpu/half.h b/fpu/half.h index 75a3168a75..d9e1cd5e01 100644 --- a/fpu/half.h +++ b/fpu/half.h @@ -159,7 +159,19 @@ union _FP_UNION_H _FP_TO_INT_ROUND (H, 1, (r), X, (rsz), (rsg)) #define FP_FROM_INT_H(X, r, rs, rt) _FP_FROM_INT (H, 1, X, (r), (rs), rt) -/* HFmode arithmetic is not implemented. */ +#define FP_ISSIGNAN_H(X) _FP_ISSIGNAN (H, 1, X) +#define FP_NEG_H(R, X) _FP_NEG (H, 1, R, X) +#define FP_ADD_H(R, X, Y) _FP_ADD (H, 1, R, X, Y) +#define FP_SUB_H(R, X, Y) _FP_SUB (H, 1, R, X, Y) +#define FP_MUL_H(R, X, Y) _FP_MUL (H, 1, R, X, Y) +#define FP_DIV_H(R, X, Y) _FP_DIV (H, 1, R, X, Y) +#define FP_SQRT_H(R, X) _FP_SQRT (H, 1, R, X) +#define _FP_SQRT_MEAT_H(R, S, T, X, Q) _FP_SQRT_MEAT_1 (R, S, T, X, (Q)) +#define FP_FMA_H(R, X, Y, Z) _FP_FMA (H, 1, 1, R, X, Y, Z) + +#define FP_CMP_H(r, X, Y, un, ex) _FP_CMP (H, 1, (r), X, Y, (un), (ex)) +#define FP_CMP_EQ_H(r, X, Y, ex) _FP_CMP_EQ (H, 1, (r), X, Y, (ex)) +#define FP_CMP_UNORD_H(r, X, Y, ex) _FP_CMP_UNORD (H, 1, (r), X, Y, (ex)) #define _FP_FRAC_HIGH_H(X) _FP_FRAC_HIGH_1 (X) #define _FP_FRAC_HIGH_RAW_H(X) _FP_FRAC_HIGH_1 (X) From patchwork Sun Feb 4 04:11:26 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Richard Henderson X-Patchwork-Id: 126804 Delivered-To: patch@linaro.org Received: by 10.46.124.24 with SMTP id x24csp927000ljc; Sat, 3 Feb 2018 20:21:21 -0800 (PST) X-Google-Smtp-Source: AH8x224XYmXBLZha3q8qeCzoPPNueUMsdci7xUfWR4vE4cRdtgH7xqdDdCaThPXekf9xwBnylowF X-Received: by 10.37.239.79 with SMTP id w15mr28862320ybm.293.1517718081306; Sat, 03 Feb 2018 20:21:21 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1517718081; cv=none; d=google.com; s=arc-20160816; b=MLWJURFWFaUNk9PsAqvH+OAQIqUPU/lyvkVDXwDQDcNz/MXK6r9DpI7ZNzZbbdMhZQ mCKjrG4cVx3X5RjLxT7y5KANZrWEiEhGd4JKqKy80tEA/zkZQir0YtO24FeV9TbtlHaJ lPDKQXT/v5F9AtzrkHSbh0S9buZVrAU4ZwTt17gWRC3JPvGOGn6aab5GYYyf1ai2kWJt iHoulvNotQyn2Nlbp2c+DSVIT5nUfHQ59TIXOrptONHTh6/jXet89EWC8+PUzcBI9GZ5 ADrJBr3SqDIAou5cJNj5IxrJ7rycU/o9y9GlIsIwHP4FZOJAm5KfMZfhidASvNQsM6Kp uc8w== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=sender:errors-to:cc:list-subscribe:list-help:list-post:list-archive :list-unsubscribe:list-id:precedence:subject :content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:to:from:dkim-signature:arc-authentication-results; bh=7y0D9zhkuYel2O0QBH3dwcy6DXVAIGyUN+AKLIY+j2k=; b=siJ60IbZNVPAFygMDYQE7eZ2ubY4a2zGiYUK56vfCpCGoHr2jpBNji7sYCniOyGPXb Nv0ie1sIAUmeqOt5wy1jkK5OGML3nKG0z7NKvryEwjvyfuM5BrdOQZw2UMvO+nQINkTt xPBlWE7au8VZkdT5niRgUIjb0szhZiYQOpTGY2dIl8xQDB0lNHglqy4phZ8zz/sjr7aY TWotPhBI4Opqd8LvfDe+JPdehEitcFFEAbfcJjS/7PtkQCjEHGKDdtmhGzSYEt8cHRgm DdvY8HDAT8JEKfdJnU0etQ1xOYo9OodcPtgkZvOUmOdUgFDNIxcsLIlhYU6IFtrfzjz4 IYFA== ARC-Authentication-Results: i=1; mx.google.com; dkim=fail header.i=@linaro.org header.s=google header.b=SNvmEX7s; spf=pass (google.com: domain of qemu-devel-bounces+patch=linaro.org@nongnu.org designates 2001:4830:134:3::11 as permitted sender) smtp.mailfrom=qemu-devel-bounces+patch=linaro.org@nongnu.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=linaro.org Return-Path: Received: from lists.gnu.org (lists.gnu.org. [2001:4830:134:3::11]) by mx.google.com with ESMTPS id c69si544876ybh.224.2018.02.03.20.21.21 for (version=TLS1 cipher=AES128-SHA bits=128/128); Sat, 03 Feb 2018 20:21:21 -0800 (PST) Received-SPF: pass (google.com: domain of qemu-devel-bounces+patch=linaro.org@nongnu.org designates 2001:4830:134:3::11 as permitted sender) client-ip=2001:4830:134:3::11; Authentication-Results: mx.google.com; dkim=fail header.i=@linaro.org header.s=google header.b=SNvmEX7s; spf=pass (google.com: domain of qemu-devel-bounces+patch=linaro.org@nongnu.org designates 2001:4830:134:3::11 as permitted sender) smtp.mailfrom=qemu-devel-bounces+patch=linaro.org@nongnu.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=linaro.org Received: from localhost ([::1]:58304 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1eiBns-0004Hd-Ll for patch@linaro.org; Sat, 03 Feb 2018 23:21:20 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:47378) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1eiBes-0004kd-KX for qemu-devel@nongnu.org; Sat, 03 Feb 2018 23:12:03 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1eiBer-0004zB-Og for qemu-devel@nongnu.org; Sat, 03 Feb 2018 23:12:02 -0500 Received: from mail-pf0-x242.google.com ([2607:f8b0:400e:c00::242]:37163) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1eiBer-0004yy-If for qemu-devel@nongnu.org; Sat, 03 Feb 2018 23:12:01 -0500 Received: by mail-pf0-x242.google.com with SMTP id p1so19466574pfh.4 for ; Sat, 03 Feb 2018 20:12:01 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=7y0D9zhkuYel2O0QBH3dwcy6DXVAIGyUN+AKLIY+j2k=; b=SNvmEX7sEqLh5sChXLt8iHYmOwVD9i5Hs1wRc92s3wddYyrD602b3BIxETesfeVJ0/ b4ABtL2TBJelH6DO2/iB3fl9hsfi1RYzf/054mhrSqU4WIs0uBZGbLJ6onKjkiG39Qtp IUH1LCXzkIBb9oPQ82Q2iKE05Uy66sW3fz1z8= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=7y0D9zhkuYel2O0QBH3dwcy6DXVAIGyUN+AKLIY+j2k=; b=gZyQ/cyCyed6hphryppdmme0kJpVAgE0OPcw2jfpMclSuRsV6+OlXVKFo7zja8z7IW duMRjdANZo+CcVKrsl+j2NenMkg6+TRQTQ+MtwhTzv88LUvK/jvQ0QzUSxorxsE+OZRW sUCTr9/UzMb7GaJ5pMGooAaycx9JnlEFZIGYWbjndjuraKq6rJnNm9PQc8qaIJ2WmER1 JegMmSiTQaxXB6c0lPS5MSxmegNRieqQkzwtFHJn5iWp3dXD7KsfFjPO4mxO2cHt8u5X XT8eiqTvHq5iKpzp1NjtDxtkVIfmhORnobt5JKQLxbh8yvIFmBy3QQmsvY3xknHJLxGY HweA== X-Gm-Message-State: APf1xPD2hqXrKtrbfm4ZxGiam3sJtK42bpJLVEW5o4eLdQItCErSVY// /oDIno+Rwe6aN4zC1HysR4ekvwxCXTE= X-Received: by 10.98.157.213 with SMTP id a82mr573160pfk.242.1517717520353; Sat, 03 Feb 2018 20:12:00 -0800 (PST) Received: from cloudburst.twiddle.net (174-21-6-47.tukw.qwest.net. [174.21.6.47]) by smtp.gmail.com with ESMTPSA id k3sm1399425pgr.12.2018.02.03.20.11.59 (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Sat, 03 Feb 2018 20:11:59 -0800 (PST) From: Richard Henderson To: qemu-devel@nongnu.org Date: Sat, 3 Feb 2018 20:11:26 -0800 Message-Id: <20180204041136.17525-15-richard.henderson@linaro.org> X-Mailer: git-send-email 2.14.3 In-Reply-To: <20180204041136.17525-1-richard.henderson@linaro.org> References: <20180204041136.17525-1-richard.henderson@linaro.org> MIME-Version: 1.0 X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 2607:f8b0:400e:c00::242 Subject: [Qemu-devel] [PATCH 14/24] fpu/soft-fp: Adjust _FP_CMP_CHECK_NAN X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: peter.maydell@linaro.org, cota@braap.org, alex.bennee@linaro.org, hsp.cat7@gmail.com Errors-To: qemu-devel-bounces+patch=linaro.org@nongnu.org Sender: "Qemu-devel" The fourth argument to _FP_CMP is a 4-state integer operand that controls the operation wrt raising exceptions. However, the usage that we need within QEMU produces a -Werror=int-in-bool-context: error: ?: using integer constants in boolean context, \ the expression will always evaluate to ‘true’ glue(FP_CMP_, FS)(r, A, B, float_relation_unordered, (quiet ? 1 : 2)); note: in definition of macro ‘_FP_CMP_CHECK_NAN’ if (ex) \ ^~ Adding an explicit comparison avoids this. Signed-off-by: Richard Henderson --- fpu/op-common.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) -- 2.14.3 diff --git a/fpu/op-common.h b/fpu/op-common.h index c5f33c0148..c4d8b58a03 100644 --- a/fpu/op-common.h +++ b/fpu/op-common.h @@ -1242,7 +1242,7 @@ { \ /* The arguments are unordered, which may or may not result in \ an exception. */ \ - if (ex) \ + if ((ex) != 0) \ { \ /* At least some cases of unordered arguments result in \ exceptions; check whether this is one. */ \ From patchwork Sun Feb 4 04:11:27 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Richard Henderson X-Patchwork-Id: 126814 Delivered-To: patch@linaro.org Received: by 10.80.172.228 with SMTP id x91csp1228260edc; Sat, 3 Feb 2018 20:27:01 -0800 (PST) X-Google-Smtp-Source: AH8x227AuJy/ajiyC+VYM5OqnDqLzNZcMX3IGPmwxEwezt8Q/jDnoZlyWEG/gsPi7wA5CQb8ExOp X-Received: by 10.37.46.72 with SMTP id b8mr29613894ybn.464.1517718421690; Sat, 03 Feb 2018 20:27:01 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1517718421; cv=none; d=google.com; s=arc-20160816; b=csNLa1A2w22y/QLIHjNPghPu1sOVqseflVopuVJpy2SGimFQRA2MyLn+sTDfQ9ircu AnKkodk6dqOGpEGqSFHqf18BRXPSgA6b4aD1nU5LbrBj9EIjQE46cDiHYMqg+EleV7th hxCOWDnLZyNGmKzHNIeySZhem5NNx5LCYPv+eJ7c4/SnEayKEZusACyo0KzCVPW1VUwZ +oJf6OLTwp3f53oko0oGNdoRR+cVgMm2eCow8HztslHN51KTItq9npY0cr4eo33ilbjN UYkKVcmCT43oHM4QzBNCaEDyZpErTLfO5s2g9UUruo2idq00bE+F7d0cKD+tfn3ZyK0U A6jQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=sender:errors-to:cc:list-subscribe:list-help:list-post:list-archive :list-unsubscribe:list-id:precedence:subject:references:in-reply-to :message-id:date:to:from:dkim-signature:arc-authentication-results; bh=BhC6bVlR9EBVgHbeGjv525VPncqTYv36YdWn5rMy7XQ=; b=iuZWxweqW5EIYz9OJVnZOVcNFTOK+23umrFV6qpEyB5txgR557A2wbenX0bNeUJr6w YdgJQa+3KJmzV5uemjxnszeEyiod1X9d3BrljMlhkEKpxlmRB4Xyh6tWhy1EAw36NLMp zqJJcxoP3shT+MLXesjSmZV+GFtFOGol5CRFSAFWpS6T8FVCxM4I7T8IIUhCAs+6vgF5 2MM1E1uBIbUn30fYLFd3j1uiwus35NPZNIuCc/NCEzjJAlhkNzKFLY2x6wkykbsE5V00 pP5v7jUdUWsCuaUs7cdIrT4DKF6JMHDHIsqqMWStVFo+fYkby+xEFvVknWCFoJ8iPopP pHxg== ARC-Authentication-Results: i=1; mx.google.com; dkim=fail header.i=@linaro.org header.s=google header.b=kL9OYGHy; spf=pass (google.com: domain of qemu-devel-bounces+patch=linaro.org@nongnu.org designates 2001:4830:134:3::11 as permitted sender) smtp.mailfrom=qemu-devel-bounces+patch=linaro.org@nongnu.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=linaro.org Return-Path: Received: from lists.gnu.org (lists.gnu.org. [2001:4830:134:3::11]) by mx.google.com with ESMTPS id u186si475538ybf.316.2018.02.03.20.27.01 for (version=TLS1 cipher=AES128-SHA bits=128/128); Sat, 03 Feb 2018 20:27:01 -0800 (PST) Received-SPF: pass (google.com: domain of qemu-devel-bounces+patch=linaro.org@nongnu.org designates 2001:4830:134:3::11 as permitted sender) client-ip=2001:4830:134:3::11; Authentication-Results: mx.google.com; dkim=fail header.i=@linaro.org header.s=google header.b=kL9OYGHy; spf=pass (google.com: domain of qemu-devel-bounces+patch=linaro.org@nongnu.org designates 2001:4830:134:3::11 as permitted sender) smtp.mailfrom=qemu-devel-bounces+patch=linaro.org@nongnu.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=linaro.org Received: from localhost ([::1]:58343 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1eiBtM-00018W-WA for patch@linaro.org; Sat, 03 Feb 2018 23:27:01 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:47431) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1eiBf1-0004sZ-Ju for qemu-devel@nongnu.org; Sat, 03 Feb 2018 23:12:17 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1eiBev-00050G-8b for qemu-devel@nongnu.org; Sat, 03 Feb 2018 23:12:11 -0500 Received: from mail-pg0-x242.google.com ([2607:f8b0:400e:c05::242]:35173) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1eiBeu-0004zx-SF for qemu-devel@nongnu.org; Sat, 03 Feb 2018 23:12:05 -0500 Received: by mail-pg0-x242.google.com with SMTP id o13so15997829pgs.2 for ; Sat, 03 Feb 2018 20:12:04 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=BhC6bVlR9EBVgHbeGjv525VPncqTYv36YdWn5rMy7XQ=; b=kL9OYGHyyCq0U9dwmzocJd3VMrIvbaBzKd8XybxGMNCsUz9RDdLEFLRgGo3BkLzMQH brZItYBe7AFQX5TZZbngsOq2rrchaKoXB/E/afJSCvJSkGIbj69HIPd583lS7CQRYva5 Dbu39vrpNqdWJFp7yHimt11ztyYhw8UW9uXKM= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=BhC6bVlR9EBVgHbeGjv525VPncqTYv36YdWn5rMy7XQ=; b=gLkutgttVnIzgVGzFGlN5V4Gd1IMwP9gvijlzpwxwzu+pLBu0GiJAliGySB61xT3UW TPgqZA62slvgz1aLsgGtIKMAwHYOH+KLPd1wNU303mEEE+1+xULMs6q8ZSnJ+1O0YaR9 xcRBJPmBR9GgwNGMJTSBwd2mulTEuamcpR3uZglZAqzFqFHXyoobmb26PmLs6nqjIz90 3mAD1BfgUKYJSHz+fS7uFni2/ZcmC8TcoiVsUiTyGwH8tR0ItPDKBVFWPcPUTr551ppZ AyBGX7IU9aJCQgeW9izYsCeJvb3+5xEVb3+2t/xfWVQ2KdQHQoLQ/S1OBFETIb9cKrYJ G2hw== X-Gm-Message-State: AKwxytfQMlH0F9Mk4j85ZM3YLI6h11Echto8QmGm/V3fWlCNITUJM4g0 Ho0CmfmUg/5joHaVHgkOIn+BNTUKJZU= X-Received: by 10.98.102.4 with SMTP id a4mr44677198pfc.210.1517717521832; Sat, 03 Feb 2018 20:12:01 -0800 (PST) Received: from cloudburst.twiddle.net (174-21-6-47.tukw.qwest.net. [174.21.6.47]) by smtp.gmail.com with ESMTPSA id k3sm1399425pgr.12.2018.02.03.20.12.00 (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Sat, 03 Feb 2018 20:12:00 -0800 (PST) From: Richard Henderson To: qemu-devel@nongnu.org Date: Sat, 3 Feb 2018 20:11:27 -0800 Message-Id: <20180204041136.17525-16-richard.henderson@linaro.org> X-Mailer: git-send-email 2.14.3 In-Reply-To: <20180204041136.17525-1-richard.henderson@linaro.org> References: <20180204041136.17525-1-richard.henderson@linaro.org> X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 2607:f8b0:400e:c05::242 Subject: [Qemu-devel] [PATCH 15/24] fpu: Implement add/sub/mul/div with soft-fp.h X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: peter.maydell@linaro.org, cota@braap.org, alex.bennee@linaro.org, hsp.cat7@gmail.com Errors-To: qemu-devel-bounces+patch=linaro.org@nongnu.org Sender: "Qemu-devel" Port the implementation of these 4 routines to the code imported from glibc. This allows the trivial addition of float16 support. Signed-off-by: Richard Henderson --- Makefile.target | 4 + fpu/sfp-machine.h | 222 ++++++++++ fpu/soft-fp-specialize.h | 131 ++++++ include/fpu/softfloat.h | 6 + fpu/float128.c | 35 ++ fpu/float16.c | 43 ++ fpu/float32.c | 35 ++ fpu/float64.c | 35 ++ fpu/floatxx.inc.c | 98 +++++ fpu/softfloat.c | 1075 ---------------------------------------------- 10 files changed, 609 insertions(+), 1075 deletions(-) create mode 100644 fpu/sfp-machine.h create mode 100644 fpu/soft-fp-specialize.h create mode 100644 fpu/float128.c create mode 100644 fpu/float16.c create mode 100644 fpu/float32.c create mode 100644 fpu/float64.c create mode 100644 fpu/floatxx.inc.c -- 2.14.3 diff --git a/Makefile.target b/Makefile.target index f9a9da7e7c..b904085f77 100644 --- a/Makefile.target +++ b/Makefile.target @@ -98,6 +98,10 @@ obj-$(CONFIG_TCG) += tcg/tcg-common.o obj-$(CONFIG_TCG_INTERPRETER) += tcg/tci.o obj-$(CONFIG_TCG_INTERPRETER) += disas/tci.o obj-y += fpu/softfloat.o +obj-y += fpu/float16.o +obj-y += fpu/float32.o +obj-y += fpu/float64.o +obj-y += fpu/float128.o obj-y += target/$(TARGET_BASE_ARCH)/ obj-y += disas.o obj-$(call notempty,$(TARGET_XML_FILES)) += gdbstub-xml.o diff --git a/fpu/sfp-machine.h b/fpu/sfp-machine.h new file mode 100644 index 0000000000..e02af72ba6 --- /dev/null +++ b/fpu/sfp-machine.h @@ -0,0 +1,222 @@ +/* + * QEMU configuration for soft-fp.h + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, see . + */ + +/* ??? Should notice 32-bit host. */ +#define _FP_W_TYPE_SIZE 64 +#define _FP_W_TYPE uint64_t +#define _FP_WS_TYPE int64_t +#define _FP_I_TYPE int + +#if defined(TARGET_SPARC) || defined(TARGET_M68K) +#define TARGET_NANFRAC_BITS -1 +#elif defined(TARGET_MIPS) +#define TARGET_NANFRAC_BITS (-(_FP_W_TYPE)status->snan_bit_is_one) +#else +#define TARGET_NANFRAC_BITS 0 +#endif + +#if defined(TARGET_X86) || defined(TARGET_TILEGX) +#define TARGET_NANFRAC_SIGN 1 +#else +#define TARGET_NANFRAC_SIGN 0 +#endif + +#define _FP_NANFRAC(fs) \ + (status->snan_bit_is_one \ + ? TARGET_NANFRAC_BITS & (_FP_QNANBIT_##fs - 1) \ + : TARGET_NANFRAC_BITS | _FP_QNANBIT_##fs) + +#define _FP_NANFRAC_H _FP_NANFRAC(H) +#define _FP_NANFRAC_S _FP_NANFRAC(S) +#define _FP_NANFRAC_D _FP_NANFRAC(D) +#define _FP_NANFRAC_Q _FP_NANFRAC(Q), TARGET_NANFRAC_BITS + +#define _FP_NANSIGN_H TARGET_NANFRAC_SIGN +#define _FP_NANSIGN_S TARGET_NANFRAC_SIGN +#define _FP_NANSIGN_D TARGET_NANFRAC_SIGN +#define _FP_NANSIGN_Q TARGET_NANFRAC_SIGN + +#define _FP_QNANNEGATEDP (status->snan_bit_is_one) + +/* We check default_nan_mode in _FP_CHOOSENAN; we do not need to + * duplicate that check in _FP_KEEPNANFRACP. + */ +#define _FP_KEEPNANFRACP 1 + +/* The usage withing the bulk of op-common.h only invokes _FP_CHOOSENAN + * when presented with two NaNs. However, for our own usage within + * floatxx.inc.c it is handy to be able to continue to invoke with + * non-NaN operands; check for that. + */ +#define _FP_CHOOSENAN(fs, wc, R, X, Y, OP) \ + do { \ + int x_nan = 0, y_nan = 0; \ + if (X##_e == _FP_EXPMAX_##fs && !_FP_FRAC_ZEROP_##wc(X)) { \ + x_nan = _FP_FRAC_SNANP(fs, X) * 2 - 1; \ + } \ + if (Y##_e == _FP_EXPMAX_##fs && !_FP_FRAC_ZEROP_##wc(Y)) { \ + y_nan = _FP_FRAC_SNANP(fs, Y) * 2 - 1; \ + } \ + switch (pick_nan(x_nan, y_nan, \ + _FP_FRAC_EQ_##wc(X, Y) ? X##_s < Y##_s \ + : _FP_FRAC_GT_##wc(X, Y), status)) { \ + case 0: \ + R##_s = X##_s; \ + _FP_FRAC_COPY_##wc(R, X); \ + break; \ + case 1: \ + R##_s = Y##_s; \ + _FP_FRAC_COPY_##wc(R, Y); \ + break; \ + default: \ + R##_s = _FP_NANSIGN_##fs; \ + _FP_FRAC_SET_##wc(R, _FP_NANFRAC_##fs); \ + } \ + R##_e = _FP_EXPMAX_##fs; \ + R##_c = FP_CLS_NAN; \ + } while (0) + +#define FP_ROUNDMODE (status->float_rounding_mode) + +#define FP_RND_NEAREST float_round_nearest_even +#define FP_RND_ZERO float_round_to_zero +#define FP_RND_PINF float_round_up +#define FP_RND_MINF float_round_down +#define FP_RND_TIESAWAY float_round_ties_away +#define FP_RND_ODD float_round_to_odd + +#define FP_EX_INVALID float_flag_invalid +#define FP_EX_OVERFLOW float_flag_overflow +#define FP_EX_UNDERFLOW float_flag_underflow +#define FP_EX_DIVZERO float_flag_divbyzero +#define FP_EX_INEXACT float_flag_inexact + +#define _FP_TININESS_AFTER_ROUNDING \ + (status->float_detect_tininess == float_tininess_after_rounding) + +#define FP_DENORM_ZERO (status->flush_inputs_to_zero) + +#define FP_HANDLE_EXCEPTIONS (status->float_exception_flags |= _fex) + +/* We do not need all of longlong.h. Provide the few needed. + * + * If we did use longlong.h, we would have to abide by the + * UWtype defined by that header, which would mean adjusting + * for 32-bit hosts, rather than using uint64_t unconditionally. + */ + +#include "qemu/int128.h" + +/* Double-word addition, in this case 128-bit values. */ +#define add_ssaaaa(rh, rl, ah, al, bh, bl) \ + do { \ + Int128 rr = int128_add(int128_make128(al, ah), \ + int128_make128(bl, bh)); \ + (rh) = int128_gethi(rr); \ + (rl) = int128_getlo(rr); \ + } while (0) + +/* Double-word subtraction, in this case 128-bit values. */ +#define sub_ddmmss(rh, rl, ah, al, bh, bl) \ + do { \ + Int128 rr = int128_sub(int128_make128(al, ah), \ + int128_make128(bl, bh)); \ + (rh) = int128_gethi(rr); \ + (rl) = int128_getlo(rr); \ + } while (0) + +/* Widening multiplication, in this case 64 * 64 -> 128-bit values. */ +static inline Int128 umul_ppmm_impl(uint64_t a, uint64_t b) +{ +#ifdef CONFIG_INT128 + return (__uint128_t)a * b; +#else + uint64_t al = (uint32_t)a, ah = a >> 32; + uint64_t bl = (uint32_t)b, bh = b >> 32; + uint64_t p0, p1, p2, p3; + uint64_t lo, mid, hi; + + p0 = al * bl; + p1 = ah * bl; + p2 = al * bh; + p3 = ah * bh; + + mid = (p0 >> 32) + (uint32_t)p1 + (uint32_t)p2; + lo = (uint32_t)p0 + (mid << 32); + hi = p3 + (mid >> 32) + (p1 >> 32) + (p2 >> 32); + + return int128_make128(lo, hi); +#endif +} + +#define umul_ppmm(ph, pl, m0, m1) \ + do { \ + Int128 pp = umul_ppmm_impl(m0, m1); \ + (ph) = int128_gethi(pp); \ + (pl) = int128_getlo(pp); \ + } while (0) + +/* Wide division, in this case 128 / 64 -> 64-bit values. + * The numerator (n1:n0) and denominator (d) operands must + * be normalized such that the quotient (*pq) will fit. + */ +static inline void udiv_qrnnd_impl(uint64_t *pq, uint64_t *pr, uint64_t n1, + uint64_t n0, uint64_t d) +{ + uint64_t d0, d1, q0, q1, r1, r0, m; + + d0 = (uint32_t)d; + d1 = d >> 32; + + r1 = n1 % d1; + q1 = n1 / d1; + m = q1 * d0; + r1 = (r1 << 32) | (n0 >> 32); + if (r1 < m) { + q1 -= 1; + r1 += d; + if (r1 >= d) { + if (r1 < m) { + q1 -= 1; + r1 += d; + } + } + } + r1 -= m; + + r0 = r1 % d1; + q0 = r1 / d1; + m = q0 * d0; + r0 = (r0 << 32) | (uint32_t)n0; + if (r0 < m) { + q0 -= 1; + r0 += d; + if (r0 >= d) { + if (r0 < m) { + q0 -= 1; + r0 += d; + } + } + } + r0 -= m; + + *pq = (q1 << 32) | q0; + *pr = r0; +} + +#define udiv_qrnnd(q, r, n1, n0, d) \ + udiv_qrnnd_impl(&(q), &(r), (n1), (n0), (d)) diff --git a/fpu/soft-fp-specialize.h b/fpu/soft-fp-specialize.h new file mode 100644 index 0000000000..869f5a0195 --- /dev/null +++ b/fpu/soft-fp-specialize.h @@ -0,0 +1,131 @@ +/* + * Target-specific specialization for soft-fp.h. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, see . + */ + + +/* + * Select which NaN to propagate for a two-input operation. + * IEEE754 doesn't specify all the details of this, so the + * algorithm is target-specific. + * + * A_NAN and B_NAN are positive if their respective operands are SNaN, + * negative if they are QNaN, or 0 if they are not a NaN at all. + * The return value is 0 to select NaN A, 1 for NaN B, or 2 to build + * a new default QNaN. + * + * Note that signalling NaNs are always squashed to quiet NaNs + * by the caller before returning them. + * + * A_LARGER is only valid if both A and B are NaNs of some kind, + * and is true if A has the larger significand, or if both A and B + * have the same significand but A is positive but B is negative. + * It is only needed for the x87 tie-break rule. + */ +static inline int pick_nan(int a_nan, int b_nan, bool a_larger, + float_status *status) +{ + if (status->default_nan_mode) { + return 2; + } +#if defined(TARGET_ARM) || defined(TARGET_HPPA) + /* ARM mandated NaN propagation rules (see FPProcessNaNs()), take + * the first of: + * 1. A if it is signaling + * 2. B if it is signaling + * 3. A (quiet) + * 4. B (quiet) + * A signaling NaN is always quietened before returning it. + */ + if (a_nan > 0) { + return 0; + } else if (b_nan > 0) { + return 1; + } else if (a_nan < 0) { + return 0; + } else { + return 1; + } +#elif defined(TARGET_MIPS) + /* According to MIPS specifications, if one of the two operands is + * a sNaN, a new qNaN has to be generated. For qNaN inputs the + * specifications says: "When possible, this QNaN result is one of + * the operand QNaN values." In practice it seems that most + * implementations choose the first operand if both operands are qNaN. + * In short this gives the following rules: + * 1. A if it is signaling + * 2. B if it is signaling + * 3. A (quiet) + * 4. B (quiet) + */ + if (a_nan > 0 || b_nan > 0) { + return 2; + } else if (a_nan < 0) { + return 0; + } else { + return 1; + } +#elif defined(TARGET_PPC) || defined(TARGET_XTENSA) || defined(TARGET_M68K) + /* PowerPC propagation rules: + * 1. A if it sNaN or qNaN + * 2. B if it sNaN or qNaN + * A signaling NaN is always silenced before returning it. + */ + /* M68000 FAMILY PROGRAMMER'S REFERENCE MANUAL + * 3.4 FLOATING-POINT INSTRUCTION DETAILS + * If either operand, but not both operands, of an operation is a + * nonsignaling NaN, then that NaN is returned as the result. If both + * operands are nonsignaling NaNs, then the destination operand + * nonsignaling NaN is returned as the result. + * If either operand to an operation is a signaling NaN (SNaN), then the + * SNaN bit is set in the FPSR EXC byte. If the SNaN exception enable bit + * is set in the FPCR ENABLE byte, then the exception is taken and the + * destination is not modified. If the SNaN exception enable bit is not + * set, setting the SNaN bit in the operand to a one converts the SNaN to + * a nonsignaling NaN. The operation then continues as described in the + * preceding paragraph for nonsignaling NaNs. + */ + if (a_nan) { + return 0; + } else { + return 1; + } +#else + /* This implements x87 NaN propagation rules: + * SNaN + QNaN => return the QNaN + * two SNaNs => return the one with the larger significand, silenced + * two QNaNs => return the one with the larger significand + * SNaN and a non-NaN => return the SNaN, silenced + * QNaN and a non-NaN => return the QNaN + * + * If we get down to comparing significands and they are the same, + * return the NaN with the positive sign bit (if any). + */ + /* ??? This is x87 specific and should not be the + default implementation. */ + if (a_nan > 0) { + if (b_nan <= 0) { + return b_nan < 0; + } + } else if (a_nan < 0) { + if (b_nan >= 0) { + return 0; + } + } else { + return 1; + } + return a_larger ^ 1; +#endif +} diff --git a/include/fpu/softfloat.h b/include/fpu/softfloat.h index 23824a3000..85e4a74f1b 100644 --- a/include/fpu/softfloat.h +++ b/include/fpu/softfloat.h @@ -236,6 +236,12 @@ float64 float16_to_float64(float16 a, flag ieee, float_status *status); /*---------------------------------------------------------------------------- | Software half-precision operations. *----------------------------------------------------------------------------*/ + +float16 float16_add(float16, float16, float_status *status); +float16 float16_sub(float16, float16, float_status *status); +float16 float16_mul(float16, float16, float_status *status); +float16 float16_div(float16, float16, float_status *status); + int float16_is_quiet_nan(float16, float_status *status); int float16_is_signaling_nan(float16, float_status *status); float16 float16_maybe_silence_nan(float16, float_status *status); diff --git a/fpu/float128.c b/fpu/float128.c new file mode 100644 index 0000000000..550b98a682 --- /dev/null +++ b/fpu/float128.c @@ -0,0 +1,35 @@ +/* + * Software floating point for size float64 + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, see . + */ + +#include "qemu/osdep.h" +#include "fpu/softfloat.h" +#include "soft-fp.h" +#include "soft-fp-specialize.h" +#include "quad.h" + +#define FLOATXX float128 +#define FS Q +#define WC 2 + +#define _FP_MUL_MEAT_Q(R, X, Y) \ + _FP_MUL_MEAT_2_wide(_FP_WFRACBITS_Q, R, X, Y, umul_ppmm) +#define _FP_MUL_MEAT_DW_Q(R, X, Y) \ + _FP_MUL_MEAT_DW_2_wide(_FP_WFRACBITS_Q, R, X, Y, umul_ppmm) +#define _FP_DIV_MEAT_Q(R, X, Y) \ + _FP_DIV_MEAT_2_udiv(Q, R, X, Y) + +#include "floatxx.inc.c" diff --git a/fpu/float16.c b/fpu/float16.c new file mode 100644 index 0000000000..f24f52afde --- /dev/null +++ b/fpu/float16.c @@ -0,0 +1,43 @@ +/* + * Software floating point for size float16 + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, see . + */ + +#include "qemu/osdep.h" +#include "fpu/softfloat.h" +#include "soft-fp.h" +#include "soft-fp-specialize.h" +#include "half.h" + +/* No point in using a 64-bit type for float16. */ +#undef _FP_W_TYPE_SIZE +#undef _FP_W_TYPE +#undef _FP_WS_TYPE +#define _FP_W_TYPE_SIZE 32 +#define _FP_W_TYPE uint32_t +#define _FP_WS_TYPE int32_t + +#define FLOATXX float16 +#define FS H +#define WC 1 + +#define _FP_MUL_MEAT_H(R, X, Y) \ + _FP_MUL_MEAT_1_imm(_FP_WFRACBITS_H, R, X, Y) +#define _FP_MUL_MEAT_DW_H(R, X, Y) \ + _FP_MUL_MEAT_DW_1_imm(_FP_WFRACBITS_H, R, X, Y) +#define _FP_DIV_MEAT_H(R, X, Y) \ + _FP_DIV_MEAT_1_imm(H, R, X, Y, _FP_DIV_HELP_imm) + +#include "floatxx.inc.c" diff --git a/fpu/float32.c b/fpu/float32.c new file mode 100644 index 0000000000..60d8758c80 --- /dev/null +++ b/fpu/float32.c @@ -0,0 +1,35 @@ +/* + * Software floating point for size float32 + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, see . + */ + +#include "qemu/osdep.h" +#include "fpu/softfloat.h" +#include "soft-fp.h" +#include "soft-fp-specialize.h" +#include "single.h" + +#define FLOATXX float32 +#define FS S +#define WC 1 + +#define _FP_MUL_MEAT_S(R, X, Y) \ + _FP_MUL_MEAT_1_imm(_FP_WFRACBITS_S, R, X, Y) +#define _FP_MUL_MEAT_DW_S(R, X, Y) \ + _FP_MUL_MEAT_DW_1_imm(_FP_WFRACBITS_S, R, X, Y) +#define _FP_DIV_MEAT_S(R, X, Y) \ + _FP_DIV_MEAT_1_imm(S, R, X, Y, _FP_DIV_HELP_imm) + +#include "floatxx.inc.c" diff --git a/fpu/float64.c b/fpu/float64.c new file mode 100644 index 0000000000..d838d83223 --- /dev/null +++ b/fpu/float64.c @@ -0,0 +1,35 @@ +/* + * Software floating point for size float64 + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, see . + */ + +#include "qemu/osdep.h" +#include "fpu/softfloat.h" +#include "soft-fp.h" +#include "soft-fp-specialize.h" +#include "double.h" + +#define FLOATXX float64 +#define FS D +#define WC 1 + +#define _FP_MUL_MEAT_D(R, X, Y) \ + _FP_MUL_MEAT_1_wide(_FP_WFRACBITS_D, R, X, Y, umul_ppmm) +#define _FP_MUL_MEAT_DW_D(R, X, Y) \ + _FP_MUL_MEAT_DW_1_wide(_FP_WFRACBITS_D, R, X, Y, umul_ppmm) +#define _FP_DIV_MEAT_D(R, X, Y) \ + _FP_DIV_MEAT_1_udiv_norm(D, R, X, Y) + +#include "floatxx.inc.c" diff --git a/fpu/floatxx.inc.c b/fpu/floatxx.inc.c new file mode 100644 index 0000000000..aca5ed3097 --- /dev/null +++ b/fpu/floatxx.inc.c @@ -0,0 +1,98 @@ +/* + * Software floating point for a given type. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, see . + */ + +/* Before including this file, define: + * FLOATXX the floating-point type + * FS the type letter (e.g. S, D, Q) + * WC the word count required + * and include all of the relevant files. + */ + +#define _FP_ISNAN(fs, wc, X) \ + (X##_e == _FP_EXPMAX_##fs && !_FP_FRAC_ZEROP_##wc (X)) +#define FP_ISNAN(fs, wc, X) \ + _FP_ISNAN(fs, wc, X) +#define FP_ADD_INTERNAL(fs, wc, R, A, B, OP) \ + _FP_ADD_INTERNAL(fs, wc, R, A, B, '-') + +static FLOATXX addsub_internal(FLOATXX a, FLOATXX b, float_status *status, + bool subtract) +{ + FP_DECL_EX; + glue(FP_DECL_, FS)(A); + glue(FP_DECL_, FS)(B); + glue(FP_DECL_, FS)(R); + FLOATXX r; + + FP_INIT_ROUNDMODE; + glue(FP_UNPACK_SEMIRAW_, FS)(A, a); + glue(FP_UNPACK_SEMIRAW_, FS)(B, b); + + B_s ^= (subtract & !FP_ISNAN(FS, WC, B)); + FP_ADD_INTERNAL(FS, WC, R, A, B, '+'); + + glue(FP_PACK_SEMIRAW_, FS)(r, R); + FP_HANDLE_EXCEPTIONS; + + return r; +} + +FLOATXX glue(FLOATXX,_add)(FLOATXX a, FLOATXX b, float_status *status) +{ + return addsub_internal(a, b, status, false); +} + +FLOATXX glue(FLOATXX,_sub)(FLOATXX a, FLOATXX b, float_status *status) +{ + return addsub_internal(a, b, status, true); +} + +FLOATXX glue(FLOATXX,_mul)(FLOATXX a, FLOATXX b, float_status *status) +{ + FP_DECL_EX; + glue(FP_DECL_, FS)(A); + glue(FP_DECL_, FS)(B); + glue(FP_DECL_, FS)(R); + FLOATXX r; + + FP_INIT_ROUNDMODE; + glue(FP_UNPACK_, FS)(A, a); + glue(FP_UNPACK_, FS)(B, b); + glue(FP_MUL_, FS)(R, A, B); + glue(FP_PACK_, FS)(r, R); + FP_HANDLE_EXCEPTIONS; + + return r; +} + +FLOATXX glue(FLOATXX,_div)(FLOATXX a, FLOATXX b, float_status *status) +{ + FP_DECL_EX; + glue(FP_DECL_, FS)(A); + glue(FP_DECL_, FS)(B); + glue(FP_DECL_, FS)(R); + FLOATXX r; + + FP_INIT_ROUNDMODE; + glue(FP_UNPACK_, FS)(A, a); + glue(FP_UNPACK_, FS)(B, b); + glue(FP_DIV_, FS)(R, A, B); + glue(FP_PACK_, FS)(r, R); + FP_HANDLE_EXCEPTIONS; + + return r; +} diff --git a/fpu/softfloat.c b/fpu/softfloat.c index 3a4ab1355f..7cadf8ef1e 100644 --- a/fpu/softfloat.c +++ b/fpu/softfloat.c @@ -2009,355 +2009,6 @@ float32 float32_round_to_int(float32 a, float_status *status) } -/*---------------------------------------------------------------------------- -| Returns the result of adding the absolute values of the single-precision -| floating-point values `a' and `b'. If `zSign' is 1, the sum is negated -| before being returned. `zSign' is ignored if the result is a NaN. -| The addition is performed according to the IEC/IEEE Standard for Binary -| Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -static float32 addFloat32Sigs(float32 a, float32 b, flag zSign, - float_status *status) -{ - int aExp, bExp, zExp; - uint32_t aSig, bSig, zSig; - int expDiff; - - aSig = extractFloat32Frac( a ); - aExp = extractFloat32Exp( a ); - bSig = extractFloat32Frac( b ); - bExp = extractFloat32Exp( b ); - expDiff = aExp - bExp; - aSig <<= 6; - bSig <<= 6; - if ( 0 < expDiff ) { - if ( aExp == 0xFF ) { - if (aSig) { - return propagateFloat32NaN(a, b, status); - } - return a; - } - if ( bExp == 0 ) { - --expDiff; - } - else { - bSig |= 0x20000000; - } - shift32RightJamming( bSig, expDiff, &bSig ); - zExp = aExp; - } - else if ( expDiff < 0 ) { - if ( bExp == 0xFF ) { - if (bSig) { - return propagateFloat32NaN(a, b, status); - } - return packFloat32( zSign, 0xFF, 0 ); - } - if ( aExp == 0 ) { - ++expDiff; - } - else { - aSig |= 0x20000000; - } - shift32RightJamming( aSig, - expDiff, &aSig ); - zExp = bExp; - } - else { - if ( aExp == 0xFF ) { - if (aSig | bSig) { - return propagateFloat32NaN(a, b, status); - } - return a; - } - if ( aExp == 0 ) { - if (status->flush_to_zero) { - if (aSig | bSig) { - float_raise(float_flag_output_denormal, status); - } - return packFloat32(zSign, 0, 0); - } - return packFloat32( zSign, 0, ( aSig + bSig )>>6 ); - } - zSig = 0x40000000 + aSig + bSig; - zExp = aExp; - goto roundAndPack; - } - aSig |= 0x20000000; - zSig = ( aSig + bSig )<<1; - --zExp; - if ( (int32_t) zSig < 0 ) { - zSig = aSig + bSig; - ++zExp; - } - roundAndPack: - return roundAndPackFloat32(zSign, zExp, zSig, status); - -} - -/*---------------------------------------------------------------------------- -| Returns the result of subtracting the absolute values of the single- -| precision floating-point values `a' and `b'. If `zSign' is 1, the -| difference is negated before being returned. `zSign' is ignored if the -| result is a NaN. The subtraction is performed according to the IEC/IEEE -| Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -static float32 subFloat32Sigs(float32 a, float32 b, flag zSign, - float_status *status) -{ - int aExp, bExp, zExp; - uint32_t aSig, bSig, zSig; - int expDiff; - - aSig = extractFloat32Frac( a ); - aExp = extractFloat32Exp( a ); - bSig = extractFloat32Frac( b ); - bExp = extractFloat32Exp( b ); - expDiff = aExp - bExp; - aSig <<= 7; - bSig <<= 7; - if ( 0 < expDiff ) goto aExpBigger; - if ( expDiff < 0 ) goto bExpBigger; - if ( aExp == 0xFF ) { - if (aSig | bSig) { - return propagateFloat32NaN(a, b, status); - } - float_raise(float_flag_invalid, status); - return float32_default_nan(status); - } - if ( aExp == 0 ) { - aExp = 1; - bExp = 1; - } - if ( bSig < aSig ) goto aBigger; - if ( aSig < bSig ) goto bBigger; - return packFloat32(status->float_rounding_mode == float_round_down, 0, 0); - bExpBigger: - if ( bExp == 0xFF ) { - if (bSig) { - return propagateFloat32NaN(a, b, status); - } - return packFloat32( zSign ^ 1, 0xFF, 0 ); - } - if ( aExp == 0 ) { - ++expDiff; - } - else { - aSig |= 0x40000000; - } - shift32RightJamming( aSig, - expDiff, &aSig ); - bSig |= 0x40000000; - bBigger: - zSig = bSig - aSig; - zExp = bExp; - zSign ^= 1; - goto normalizeRoundAndPack; - aExpBigger: - if ( aExp == 0xFF ) { - if (aSig) { - return propagateFloat32NaN(a, b, status); - } - return a; - } - if ( bExp == 0 ) { - --expDiff; - } - else { - bSig |= 0x40000000; - } - shift32RightJamming( bSig, expDiff, &bSig ); - aSig |= 0x40000000; - aBigger: - zSig = aSig - bSig; - zExp = aExp; - normalizeRoundAndPack: - --zExp; - return normalizeRoundAndPackFloat32(zSign, zExp, zSig, status); - -} - -/*---------------------------------------------------------------------------- -| Returns the result of adding the single-precision floating-point values `a' -| and `b'. The operation is performed according to the IEC/IEEE Standard for -| Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -float32 float32_add(float32 a, float32 b, float_status *status) -{ - flag aSign, bSign; - a = float32_squash_input_denormal(a, status); - b = float32_squash_input_denormal(b, status); - - aSign = extractFloat32Sign( a ); - bSign = extractFloat32Sign( b ); - if ( aSign == bSign ) { - return addFloat32Sigs(a, b, aSign, status); - } - else { - return subFloat32Sigs(a, b, aSign, status); - } - -} - -/*---------------------------------------------------------------------------- -| Returns the result of subtracting the single-precision floating-point values -| `a' and `b'. The operation is performed according to the IEC/IEEE Standard -| for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -float32 float32_sub(float32 a, float32 b, float_status *status) -{ - flag aSign, bSign; - a = float32_squash_input_denormal(a, status); - b = float32_squash_input_denormal(b, status); - - aSign = extractFloat32Sign( a ); - bSign = extractFloat32Sign( b ); - if ( aSign == bSign ) { - return subFloat32Sigs(a, b, aSign, status); - } - else { - return addFloat32Sigs(a, b, aSign, status); - } - -} - -/*---------------------------------------------------------------------------- -| Returns the result of multiplying the single-precision floating-point values -| `a' and `b'. The operation is performed according to the IEC/IEEE Standard -| for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -float32 float32_mul(float32 a, float32 b, float_status *status) -{ - flag aSign, bSign, zSign; - int aExp, bExp, zExp; - uint32_t aSig, bSig; - uint64_t zSig64; - uint32_t zSig; - - a = float32_squash_input_denormal(a, status); - b = float32_squash_input_denormal(b, status); - - aSig = extractFloat32Frac( a ); - aExp = extractFloat32Exp( a ); - aSign = extractFloat32Sign( a ); - bSig = extractFloat32Frac( b ); - bExp = extractFloat32Exp( b ); - bSign = extractFloat32Sign( b ); - zSign = aSign ^ bSign; - if ( aExp == 0xFF ) { - if ( aSig || ( ( bExp == 0xFF ) && bSig ) ) { - return propagateFloat32NaN(a, b, status); - } - if ( ( bExp | bSig ) == 0 ) { - float_raise(float_flag_invalid, status); - return float32_default_nan(status); - } - return packFloat32( zSign, 0xFF, 0 ); - } - if ( bExp == 0xFF ) { - if (bSig) { - return propagateFloat32NaN(a, b, status); - } - if ( ( aExp | aSig ) == 0 ) { - float_raise(float_flag_invalid, status); - return float32_default_nan(status); - } - return packFloat32( zSign, 0xFF, 0 ); - } - if ( aExp == 0 ) { - if ( aSig == 0 ) return packFloat32( zSign, 0, 0 ); - normalizeFloat32Subnormal( aSig, &aExp, &aSig ); - } - if ( bExp == 0 ) { - if ( bSig == 0 ) return packFloat32( zSign, 0, 0 ); - normalizeFloat32Subnormal( bSig, &bExp, &bSig ); - } - zExp = aExp + bExp - 0x7F; - aSig = ( aSig | 0x00800000 )<<7; - bSig = ( bSig | 0x00800000 )<<8; - shift64RightJamming( ( (uint64_t) aSig ) * bSig, 32, &zSig64 ); - zSig = zSig64; - if ( 0 <= (int32_t) ( zSig<<1 ) ) { - zSig <<= 1; - --zExp; - } - return roundAndPackFloat32(zSign, zExp, zSig, status); - -} - -/*---------------------------------------------------------------------------- -| Returns the result of dividing the single-precision floating-point value `a' -| by the corresponding value `b'. The operation is performed according to the -| IEC/IEEE Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -float32 float32_div(float32 a, float32 b, float_status *status) -{ - flag aSign, bSign, zSign; - int aExp, bExp, zExp; - uint32_t aSig, bSig, zSig; - a = float32_squash_input_denormal(a, status); - b = float32_squash_input_denormal(b, status); - - aSig = extractFloat32Frac( a ); - aExp = extractFloat32Exp( a ); - aSign = extractFloat32Sign( a ); - bSig = extractFloat32Frac( b ); - bExp = extractFloat32Exp( b ); - bSign = extractFloat32Sign( b ); - zSign = aSign ^ bSign; - if ( aExp == 0xFF ) { - if (aSig) { - return propagateFloat32NaN(a, b, status); - } - if ( bExp == 0xFF ) { - if (bSig) { - return propagateFloat32NaN(a, b, status); - } - float_raise(float_flag_invalid, status); - return float32_default_nan(status); - } - return packFloat32( zSign, 0xFF, 0 ); - } - if ( bExp == 0xFF ) { - if (bSig) { - return propagateFloat32NaN(a, b, status); - } - return packFloat32( zSign, 0, 0 ); - } - if ( bExp == 0 ) { - if ( bSig == 0 ) { - if ( ( aExp | aSig ) == 0 ) { - float_raise(float_flag_invalid, status); - return float32_default_nan(status); - } - float_raise(float_flag_divbyzero, status); - return packFloat32( zSign, 0xFF, 0 ); - } - normalizeFloat32Subnormal( bSig, &bExp, &bSig ); - } - if ( aExp == 0 ) { - if ( aSig == 0 ) return packFloat32( zSign, 0, 0 ); - normalizeFloat32Subnormal( aSig, &aExp, &aSig ); - } - zExp = aExp - bExp + 0x7D; - aSig = ( aSig | 0x00800000 )<<7; - bSig = ( bSig | 0x00800000 )<<8; - if ( bSig <= ( aSig + aSig ) ) { - aSig >>= 1; - ++zExp; - } - zSig = ( ( (uint64_t) aSig )<<32 ) / bSig; - if ( ( zSig & 0x3F ) == 0 ) { - zSig |= ( (uint64_t) bSig * zSig != ( (uint64_t) aSig )<<32 ); - } - return roundAndPackFloat32(zSign, zExp, zSig, status); - -} - /*---------------------------------------------------------------------------- | Returns the remainder of the single-precision floating-point value `a' | with respect to the corresponding value `b'. The operation is performed @@ -3819,361 +3470,6 @@ float64 float64_trunc_to_int(float64 a, float_status *status) return res; } -/*---------------------------------------------------------------------------- -| Returns the result of adding the absolute values of the double-precision -| floating-point values `a' and `b'. If `zSign' is 1, the sum is negated -| before being returned. `zSign' is ignored if the result is a NaN. -| The addition is performed according to the IEC/IEEE Standard for Binary -| Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -static float64 addFloat64Sigs(float64 a, float64 b, flag zSign, - float_status *status) -{ - int aExp, bExp, zExp; - uint64_t aSig, bSig, zSig; - int expDiff; - - aSig = extractFloat64Frac( a ); - aExp = extractFloat64Exp( a ); - bSig = extractFloat64Frac( b ); - bExp = extractFloat64Exp( b ); - expDiff = aExp - bExp; - aSig <<= 9; - bSig <<= 9; - if ( 0 < expDiff ) { - if ( aExp == 0x7FF ) { - if (aSig) { - return propagateFloat64NaN(a, b, status); - } - return a; - } - if ( bExp == 0 ) { - --expDiff; - } - else { - bSig |= LIT64( 0x2000000000000000 ); - } - shift64RightJamming( bSig, expDiff, &bSig ); - zExp = aExp; - } - else if ( expDiff < 0 ) { - if ( bExp == 0x7FF ) { - if (bSig) { - return propagateFloat64NaN(a, b, status); - } - return packFloat64( zSign, 0x7FF, 0 ); - } - if ( aExp == 0 ) { - ++expDiff; - } - else { - aSig |= LIT64( 0x2000000000000000 ); - } - shift64RightJamming( aSig, - expDiff, &aSig ); - zExp = bExp; - } - else { - if ( aExp == 0x7FF ) { - if (aSig | bSig) { - return propagateFloat64NaN(a, b, status); - } - return a; - } - if ( aExp == 0 ) { - if (status->flush_to_zero) { - if (aSig | bSig) { - float_raise(float_flag_output_denormal, status); - } - return packFloat64(zSign, 0, 0); - } - return packFloat64( zSign, 0, ( aSig + bSig )>>9 ); - } - zSig = LIT64( 0x4000000000000000 ) + aSig + bSig; - zExp = aExp; - goto roundAndPack; - } - aSig |= LIT64( 0x2000000000000000 ); - zSig = ( aSig + bSig )<<1; - --zExp; - if ( (int64_t) zSig < 0 ) { - zSig = aSig + bSig; - ++zExp; - } - roundAndPack: - return roundAndPackFloat64(zSign, zExp, zSig, status); - -} - -/*---------------------------------------------------------------------------- -| Returns the result of subtracting the absolute values of the double- -| precision floating-point values `a' and `b'. If `zSign' is 1, the -| difference is negated before being returned. `zSign' is ignored if the -| result is a NaN. The subtraction is performed according to the IEC/IEEE -| Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -static float64 subFloat64Sigs(float64 a, float64 b, flag zSign, - float_status *status) -{ - int aExp, bExp, zExp; - uint64_t aSig, bSig, zSig; - int expDiff; - - aSig = extractFloat64Frac( a ); - aExp = extractFloat64Exp( a ); - bSig = extractFloat64Frac( b ); - bExp = extractFloat64Exp( b ); - expDiff = aExp - bExp; - aSig <<= 10; - bSig <<= 10; - if ( 0 < expDiff ) goto aExpBigger; - if ( expDiff < 0 ) goto bExpBigger; - if ( aExp == 0x7FF ) { - if (aSig | bSig) { - return propagateFloat64NaN(a, b, status); - } - float_raise(float_flag_invalid, status); - return float64_default_nan(status); - } - if ( aExp == 0 ) { - aExp = 1; - bExp = 1; - } - if ( bSig < aSig ) goto aBigger; - if ( aSig < bSig ) goto bBigger; - return packFloat64(status->float_rounding_mode == float_round_down, 0, 0); - bExpBigger: - if ( bExp == 0x7FF ) { - if (bSig) { - return propagateFloat64NaN(a, b, status); - } - return packFloat64( zSign ^ 1, 0x7FF, 0 ); - } - if ( aExp == 0 ) { - ++expDiff; - } - else { - aSig |= LIT64( 0x4000000000000000 ); - } - shift64RightJamming( aSig, - expDiff, &aSig ); - bSig |= LIT64( 0x4000000000000000 ); - bBigger: - zSig = bSig - aSig; - zExp = bExp; - zSign ^= 1; - goto normalizeRoundAndPack; - aExpBigger: - if ( aExp == 0x7FF ) { - if (aSig) { - return propagateFloat64NaN(a, b, status); - } - return a; - } - if ( bExp == 0 ) { - --expDiff; - } - else { - bSig |= LIT64( 0x4000000000000000 ); - } - shift64RightJamming( bSig, expDiff, &bSig ); - aSig |= LIT64( 0x4000000000000000 ); - aBigger: - zSig = aSig - bSig; - zExp = aExp; - normalizeRoundAndPack: - --zExp; - return normalizeRoundAndPackFloat64(zSign, zExp, zSig, status); - -} - -/*---------------------------------------------------------------------------- -| Returns the result of adding the double-precision floating-point values `a' -| and `b'. The operation is performed according to the IEC/IEEE Standard for -| Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -float64 float64_add(float64 a, float64 b, float_status *status) -{ - flag aSign, bSign; - a = float64_squash_input_denormal(a, status); - b = float64_squash_input_denormal(b, status); - - aSign = extractFloat64Sign( a ); - bSign = extractFloat64Sign( b ); - if ( aSign == bSign ) { - return addFloat64Sigs(a, b, aSign, status); - } - else { - return subFloat64Sigs(a, b, aSign, status); - } - -} - -/*---------------------------------------------------------------------------- -| Returns the result of subtracting the double-precision floating-point values -| `a' and `b'. The operation is performed according to the IEC/IEEE Standard -| for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -float64 float64_sub(float64 a, float64 b, float_status *status) -{ - flag aSign, bSign; - a = float64_squash_input_denormal(a, status); - b = float64_squash_input_denormal(b, status); - - aSign = extractFloat64Sign( a ); - bSign = extractFloat64Sign( b ); - if ( aSign == bSign ) { - return subFloat64Sigs(a, b, aSign, status); - } - else { - return addFloat64Sigs(a, b, aSign, status); - } - -} - -/*---------------------------------------------------------------------------- -| Returns the result of multiplying the double-precision floating-point values -| `a' and `b'. The operation is performed according to the IEC/IEEE Standard -| for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -float64 float64_mul(float64 a, float64 b, float_status *status) -{ - flag aSign, bSign, zSign; - int aExp, bExp, zExp; - uint64_t aSig, bSig, zSig0, zSig1; - - a = float64_squash_input_denormal(a, status); - b = float64_squash_input_denormal(b, status); - - aSig = extractFloat64Frac( a ); - aExp = extractFloat64Exp( a ); - aSign = extractFloat64Sign( a ); - bSig = extractFloat64Frac( b ); - bExp = extractFloat64Exp( b ); - bSign = extractFloat64Sign( b ); - zSign = aSign ^ bSign; - if ( aExp == 0x7FF ) { - if ( aSig || ( ( bExp == 0x7FF ) && bSig ) ) { - return propagateFloat64NaN(a, b, status); - } - if ( ( bExp | bSig ) == 0 ) { - float_raise(float_flag_invalid, status); - return float64_default_nan(status); - } - return packFloat64( zSign, 0x7FF, 0 ); - } - if ( bExp == 0x7FF ) { - if (bSig) { - return propagateFloat64NaN(a, b, status); - } - if ( ( aExp | aSig ) == 0 ) { - float_raise(float_flag_invalid, status); - return float64_default_nan(status); - } - return packFloat64( zSign, 0x7FF, 0 ); - } - if ( aExp == 0 ) { - if ( aSig == 0 ) return packFloat64( zSign, 0, 0 ); - normalizeFloat64Subnormal( aSig, &aExp, &aSig ); - } - if ( bExp == 0 ) { - if ( bSig == 0 ) return packFloat64( zSign, 0, 0 ); - normalizeFloat64Subnormal( bSig, &bExp, &bSig ); - } - zExp = aExp + bExp - 0x3FF; - aSig = ( aSig | LIT64( 0x0010000000000000 ) )<<10; - bSig = ( bSig | LIT64( 0x0010000000000000 ) )<<11; - mul64To128( aSig, bSig, &zSig0, &zSig1 ); - zSig0 |= ( zSig1 != 0 ); - if ( 0 <= (int64_t) ( zSig0<<1 ) ) { - zSig0 <<= 1; - --zExp; - } - return roundAndPackFloat64(zSign, zExp, zSig0, status); - -} - -/*---------------------------------------------------------------------------- -| Returns the result of dividing the double-precision floating-point value `a' -| by the corresponding value `b'. The operation is performed according to -| the IEC/IEEE Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -float64 float64_div(float64 a, float64 b, float_status *status) -{ - flag aSign, bSign, zSign; - int aExp, bExp, zExp; - uint64_t aSig, bSig, zSig; - uint64_t rem0, rem1; - uint64_t term0, term1; - a = float64_squash_input_denormal(a, status); - b = float64_squash_input_denormal(b, status); - - aSig = extractFloat64Frac( a ); - aExp = extractFloat64Exp( a ); - aSign = extractFloat64Sign( a ); - bSig = extractFloat64Frac( b ); - bExp = extractFloat64Exp( b ); - bSign = extractFloat64Sign( b ); - zSign = aSign ^ bSign; - if ( aExp == 0x7FF ) { - if (aSig) { - return propagateFloat64NaN(a, b, status); - } - if ( bExp == 0x7FF ) { - if (bSig) { - return propagateFloat64NaN(a, b, status); - } - float_raise(float_flag_invalid, status); - return float64_default_nan(status); - } - return packFloat64( zSign, 0x7FF, 0 ); - } - if ( bExp == 0x7FF ) { - if (bSig) { - return propagateFloat64NaN(a, b, status); - } - return packFloat64( zSign, 0, 0 ); - } - if ( bExp == 0 ) { - if ( bSig == 0 ) { - if ( ( aExp | aSig ) == 0 ) { - float_raise(float_flag_invalid, status); - return float64_default_nan(status); - } - float_raise(float_flag_divbyzero, status); - return packFloat64( zSign, 0x7FF, 0 ); - } - normalizeFloat64Subnormal( bSig, &bExp, &bSig ); - } - if ( aExp == 0 ) { - if ( aSig == 0 ) return packFloat64( zSign, 0, 0 ); - normalizeFloat64Subnormal( aSig, &aExp, &aSig ); - } - zExp = aExp - bExp + 0x3FD; - aSig = ( aSig | LIT64( 0x0010000000000000 ) )<<10; - bSig = ( bSig | LIT64( 0x0010000000000000 ) )<<11; - if ( bSig <= ( aSig + aSig ) ) { - aSig >>= 1; - ++zExp; - } - zSig = estimateDiv128To64( aSig, 0, bSig ); - if ( ( zSig & 0x1FF ) <= 2 ) { - mul64To128( bSig, zSig, &term0, &term1 ); - sub128( aSig, 0, term0, term1, &rem0, &rem1 ); - while ( (int64_t) rem0 < 0 ) { - --zSig; - add128( rem0, rem1, 0, bSig, &rem0, &rem1 ); - } - zSig |= ( rem1 != 0 ); - } - return roundAndPackFloat64(zSign, zExp, zSig, status); - -} - /*---------------------------------------------------------------------------- | Returns the remainder of the double-precision floating-point value `a' | with respect to the corresponding value `b'. The operation is performed @@ -6486,377 +5782,6 @@ float128 float128_round_to_int(float128 a, float_status *status) } -/*---------------------------------------------------------------------------- -| Returns the result of adding the absolute values of the quadruple-precision -| floating-point values `a' and `b'. If `zSign' is 1, the sum is negated -| before being returned. `zSign' is ignored if the result is a NaN. -| The addition is performed according to the IEC/IEEE Standard for Binary -| Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -static float128 addFloat128Sigs(float128 a, float128 b, flag zSign, - float_status *status) -{ - int32_t aExp, bExp, zExp; - uint64_t aSig0, aSig1, bSig0, bSig1, zSig0, zSig1, zSig2; - int32_t expDiff; - - aSig1 = extractFloat128Frac1( a ); - aSig0 = extractFloat128Frac0( a ); - aExp = extractFloat128Exp( a ); - bSig1 = extractFloat128Frac1( b ); - bSig0 = extractFloat128Frac0( b ); - bExp = extractFloat128Exp( b ); - expDiff = aExp - bExp; - if ( 0 < expDiff ) { - if ( aExp == 0x7FFF ) { - if (aSig0 | aSig1) { - return propagateFloat128NaN(a, b, status); - } - return a; - } - if ( bExp == 0 ) { - --expDiff; - } - else { - bSig0 |= LIT64( 0x0001000000000000 ); - } - shift128ExtraRightJamming( - bSig0, bSig1, 0, expDiff, &bSig0, &bSig1, &zSig2 ); - zExp = aExp; - } - else if ( expDiff < 0 ) { - if ( bExp == 0x7FFF ) { - if (bSig0 | bSig1) { - return propagateFloat128NaN(a, b, status); - } - return packFloat128( zSign, 0x7FFF, 0, 0 ); - } - if ( aExp == 0 ) { - ++expDiff; - } - else { - aSig0 |= LIT64( 0x0001000000000000 ); - } - shift128ExtraRightJamming( - aSig0, aSig1, 0, - expDiff, &aSig0, &aSig1, &zSig2 ); - zExp = bExp; - } - else { - if ( aExp == 0x7FFF ) { - if ( aSig0 | aSig1 | bSig0 | bSig1 ) { - return propagateFloat128NaN(a, b, status); - } - return a; - } - add128( aSig0, aSig1, bSig0, bSig1, &zSig0, &zSig1 ); - if ( aExp == 0 ) { - if (status->flush_to_zero) { - if (zSig0 | zSig1) { - float_raise(float_flag_output_denormal, status); - } - return packFloat128(zSign, 0, 0, 0); - } - return packFloat128( zSign, 0, zSig0, zSig1 ); - } - zSig2 = 0; - zSig0 |= LIT64( 0x0002000000000000 ); - zExp = aExp; - goto shiftRight1; - } - aSig0 |= LIT64( 0x0001000000000000 ); - add128( aSig0, aSig1, bSig0, bSig1, &zSig0, &zSig1 ); - --zExp; - if ( zSig0 < LIT64( 0x0002000000000000 ) ) goto roundAndPack; - ++zExp; - shiftRight1: - shift128ExtraRightJamming( - zSig0, zSig1, zSig2, 1, &zSig0, &zSig1, &zSig2 ); - roundAndPack: - return roundAndPackFloat128(zSign, zExp, zSig0, zSig1, zSig2, status); - -} - -/*---------------------------------------------------------------------------- -| Returns the result of subtracting the absolute values of the quadruple- -| precision floating-point values `a' and `b'. If `zSign' is 1, the -| difference is negated before being returned. `zSign' is ignored if the -| result is a NaN. The subtraction is performed according to the IEC/IEEE -| Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -static float128 subFloat128Sigs(float128 a, float128 b, flag zSign, - float_status *status) -{ - int32_t aExp, bExp, zExp; - uint64_t aSig0, aSig1, bSig0, bSig1, zSig0, zSig1; - int32_t expDiff; - - aSig1 = extractFloat128Frac1( a ); - aSig0 = extractFloat128Frac0( a ); - aExp = extractFloat128Exp( a ); - bSig1 = extractFloat128Frac1( b ); - bSig0 = extractFloat128Frac0( b ); - bExp = extractFloat128Exp( b ); - expDiff = aExp - bExp; - shortShift128Left( aSig0, aSig1, 14, &aSig0, &aSig1 ); - shortShift128Left( bSig0, bSig1, 14, &bSig0, &bSig1 ); - if ( 0 < expDiff ) goto aExpBigger; - if ( expDiff < 0 ) goto bExpBigger; - if ( aExp == 0x7FFF ) { - if ( aSig0 | aSig1 | bSig0 | bSig1 ) { - return propagateFloat128NaN(a, b, status); - } - float_raise(float_flag_invalid, status); - return float128_default_nan(status); - } - if ( aExp == 0 ) { - aExp = 1; - bExp = 1; - } - if ( bSig0 < aSig0 ) goto aBigger; - if ( aSig0 < bSig0 ) goto bBigger; - if ( bSig1 < aSig1 ) goto aBigger; - if ( aSig1 < bSig1 ) goto bBigger; - return packFloat128(status->float_rounding_mode == float_round_down, - 0, 0, 0); - bExpBigger: - if ( bExp == 0x7FFF ) { - if (bSig0 | bSig1) { - return propagateFloat128NaN(a, b, status); - } - return packFloat128( zSign ^ 1, 0x7FFF, 0, 0 ); - } - if ( aExp == 0 ) { - ++expDiff; - } - else { - aSig0 |= LIT64( 0x4000000000000000 ); - } - shift128RightJamming( aSig0, aSig1, - expDiff, &aSig0, &aSig1 ); - bSig0 |= LIT64( 0x4000000000000000 ); - bBigger: - sub128( bSig0, bSig1, aSig0, aSig1, &zSig0, &zSig1 ); - zExp = bExp; - zSign ^= 1; - goto normalizeRoundAndPack; - aExpBigger: - if ( aExp == 0x7FFF ) { - if (aSig0 | aSig1) { - return propagateFloat128NaN(a, b, status); - } - return a; - } - if ( bExp == 0 ) { - --expDiff; - } - else { - bSig0 |= LIT64( 0x4000000000000000 ); - } - shift128RightJamming( bSig0, bSig1, expDiff, &bSig0, &bSig1 ); - aSig0 |= LIT64( 0x4000000000000000 ); - aBigger: - sub128( aSig0, aSig1, bSig0, bSig1, &zSig0, &zSig1 ); - zExp = aExp; - normalizeRoundAndPack: - --zExp; - return normalizeRoundAndPackFloat128(zSign, zExp - 14, zSig0, zSig1, - status); - -} - -/*---------------------------------------------------------------------------- -| Returns the result of adding the quadruple-precision floating-point values -| `a' and `b'. The operation is performed according to the IEC/IEEE Standard -| for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -float128 float128_add(float128 a, float128 b, float_status *status) -{ - flag aSign, bSign; - - aSign = extractFloat128Sign( a ); - bSign = extractFloat128Sign( b ); - if ( aSign == bSign ) { - return addFloat128Sigs(a, b, aSign, status); - } - else { - return subFloat128Sigs(a, b, aSign, status); - } - -} - -/*---------------------------------------------------------------------------- -| Returns the result of subtracting the quadruple-precision floating-point -| values `a' and `b'. The operation is performed according to the IEC/IEEE -| Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -float128 float128_sub(float128 a, float128 b, float_status *status) -{ - flag aSign, bSign; - - aSign = extractFloat128Sign( a ); - bSign = extractFloat128Sign( b ); - if ( aSign == bSign ) { - return subFloat128Sigs(a, b, aSign, status); - } - else { - return addFloat128Sigs(a, b, aSign, status); - } - -} - -/*---------------------------------------------------------------------------- -| Returns the result of multiplying the quadruple-precision floating-point -| values `a' and `b'. The operation is performed according to the IEC/IEEE -| Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -float128 float128_mul(float128 a, float128 b, float_status *status) -{ - flag aSign, bSign, zSign; - int32_t aExp, bExp, zExp; - uint64_t aSig0, aSig1, bSig0, bSig1, zSig0, zSig1, zSig2, zSig3; - - aSig1 = extractFloat128Frac1( a ); - aSig0 = extractFloat128Frac0( a ); - aExp = extractFloat128Exp( a ); - aSign = extractFloat128Sign( a ); - bSig1 = extractFloat128Frac1( b ); - bSig0 = extractFloat128Frac0( b ); - bExp = extractFloat128Exp( b ); - bSign = extractFloat128Sign( b ); - zSign = aSign ^ bSign; - if ( aExp == 0x7FFF ) { - if ( ( aSig0 | aSig1 ) - || ( ( bExp == 0x7FFF ) && ( bSig0 | bSig1 ) ) ) { - return propagateFloat128NaN(a, b, status); - } - if ( ( bExp | bSig0 | bSig1 ) == 0 ) goto invalid; - return packFloat128( zSign, 0x7FFF, 0, 0 ); - } - if ( bExp == 0x7FFF ) { - if (bSig0 | bSig1) { - return propagateFloat128NaN(a, b, status); - } - if ( ( aExp | aSig0 | aSig1 ) == 0 ) { - invalid: - float_raise(float_flag_invalid, status); - return float128_default_nan(status); - } - return packFloat128( zSign, 0x7FFF, 0, 0 ); - } - if ( aExp == 0 ) { - if ( ( aSig0 | aSig1 ) == 0 ) return packFloat128( zSign, 0, 0, 0 ); - normalizeFloat128Subnormal( aSig0, aSig1, &aExp, &aSig0, &aSig1 ); - } - if ( bExp == 0 ) { - if ( ( bSig0 | bSig1 ) == 0 ) return packFloat128( zSign, 0, 0, 0 ); - normalizeFloat128Subnormal( bSig0, bSig1, &bExp, &bSig0, &bSig1 ); - } - zExp = aExp + bExp - 0x4000; - aSig0 |= LIT64( 0x0001000000000000 ); - shortShift128Left( bSig0, bSig1, 16, &bSig0, &bSig1 ); - mul128To256( aSig0, aSig1, bSig0, bSig1, &zSig0, &zSig1, &zSig2, &zSig3 ); - add128( zSig0, zSig1, aSig0, aSig1, &zSig0, &zSig1 ); - zSig2 |= ( zSig3 != 0 ); - if ( LIT64( 0x0002000000000000 ) <= zSig0 ) { - shift128ExtraRightJamming( - zSig0, zSig1, zSig2, 1, &zSig0, &zSig1, &zSig2 ); - ++zExp; - } - return roundAndPackFloat128(zSign, zExp, zSig0, zSig1, zSig2, status); - -} - -/*---------------------------------------------------------------------------- -| Returns the result of dividing the quadruple-precision floating-point value -| `a' by the corresponding value `b'. The operation is performed according to -| the IEC/IEEE Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -float128 float128_div(float128 a, float128 b, float_status *status) -{ - flag aSign, bSign, zSign; - int32_t aExp, bExp, zExp; - uint64_t aSig0, aSig1, bSig0, bSig1, zSig0, zSig1, zSig2; - uint64_t rem0, rem1, rem2, rem3, term0, term1, term2, term3; - - aSig1 = extractFloat128Frac1( a ); - aSig0 = extractFloat128Frac0( a ); - aExp = extractFloat128Exp( a ); - aSign = extractFloat128Sign( a ); - bSig1 = extractFloat128Frac1( b ); - bSig0 = extractFloat128Frac0( b ); - bExp = extractFloat128Exp( b ); - bSign = extractFloat128Sign( b ); - zSign = aSign ^ bSign; - if ( aExp == 0x7FFF ) { - if (aSig0 | aSig1) { - return propagateFloat128NaN(a, b, status); - } - if ( bExp == 0x7FFF ) { - if (bSig0 | bSig1) { - return propagateFloat128NaN(a, b, status); - } - goto invalid; - } - return packFloat128( zSign, 0x7FFF, 0, 0 ); - } - if ( bExp == 0x7FFF ) { - if (bSig0 | bSig1) { - return propagateFloat128NaN(a, b, status); - } - return packFloat128( zSign, 0, 0, 0 ); - } - if ( bExp == 0 ) { - if ( ( bSig0 | bSig1 ) == 0 ) { - if ( ( aExp | aSig0 | aSig1 ) == 0 ) { - invalid: - float_raise(float_flag_invalid, status); - return float128_default_nan(status); - } - float_raise(float_flag_divbyzero, status); - return packFloat128( zSign, 0x7FFF, 0, 0 ); - } - normalizeFloat128Subnormal( bSig0, bSig1, &bExp, &bSig0, &bSig1 ); - } - if ( aExp == 0 ) { - if ( ( aSig0 | aSig1 ) == 0 ) return packFloat128( zSign, 0, 0, 0 ); - normalizeFloat128Subnormal( aSig0, aSig1, &aExp, &aSig0, &aSig1 ); - } - zExp = aExp - bExp + 0x3FFD; - shortShift128Left( - aSig0 | LIT64( 0x0001000000000000 ), aSig1, 15, &aSig0, &aSig1 ); - shortShift128Left( - bSig0 | LIT64( 0x0001000000000000 ), bSig1, 15, &bSig0, &bSig1 ); - if ( le128( bSig0, bSig1, aSig0, aSig1 ) ) { - shift128Right( aSig0, aSig1, 1, &aSig0, &aSig1 ); - ++zExp; - } - zSig0 = estimateDiv128To64( aSig0, aSig1, bSig0 ); - mul128By64To192( bSig0, bSig1, zSig0, &term0, &term1, &term2 ); - sub192( aSig0, aSig1, 0, term0, term1, term2, &rem0, &rem1, &rem2 ); - while ( (int64_t) rem0 < 0 ) { - --zSig0; - add192( rem0, rem1, rem2, 0, bSig0, bSig1, &rem0, &rem1, &rem2 ); - } - zSig1 = estimateDiv128To64( rem1, rem2, bSig0 ); - if ( ( zSig1 & 0x3FFF ) <= 4 ) { - mul128By64To192( bSig0, bSig1, zSig1, &term1, &term2, &term3 ); - sub192( rem1, rem2, 0, term1, term2, term3, &rem1, &rem2, &rem3 ); - while ( (int64_t) rem1 < 0 ) { - --zSig1; - add192( rem1, rem2, rem3, 0, bSig0, bSig1, &rem1, &rem2, &rem3 ); - } - zSig1 |= ( ( rem1 | rem2 | rem3 ) != 0 ); - } - shift128ExtraRightJamming( zSig0, zSig1, 0, 15, &zSig0, &zSig1, &zSig2 ); - return roundAndPackFloat128(zSign, zExp, zSig0, zSig1, zSig2, status); - -} - /*---------------------------------------------------------------------------- | Returns the remainder of the quadruple-precision floating-point value `a' | with respect to the corresponding value `b'. The operation is performed From patchwork Sun Feb 4 04:11:28 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Richard Henderson X-Patchwork-Id: 126805 Delivered-To: patch@linaro.org Received: by 10.46.124.24 with SMTP id x24csp926928ljc; Sat, 3 Feb 2018 20:21:11 -0800 (PST) X-Google-Smtp-Source: AH8x225OyrvLyKOv90l0YSBXMYV+LNAzDjzzXLnTXmuNtt1Hu0Vfwrntzjy9GIcZ7TgwVPSQ1Te0 X-Received: by 10.37.41.66 with SMTP id p63mr2971249ybp.398.1517718071396; Sat, 03 Feb 2018 20:21:11 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1517718071; cv=none; d=google.com; s=arc-20160816; b=qTSC0kVDWubelFk8sXWVzsDQhfdZvH1p0vBcUCYG1ktcP+5F6lp4tTORCJbTQhA3Fg Wr2Eeb/ObqKPjl55Ha0q1vnCvwEwKqzKB54+xBbpnckqlm9DQ5DQekgN1s8yGkWsl1es +0+8oGvD9qAZS5grZl5K9PQ2qiOEYDylwmP1WnwnYsTaE+jVcmUyN8oDGtSQjOoRfhyX /k0+Vf4J9qZ94WToYqjPiPGSgZmEwMq6uCSMrWqIgCqN0ZbMj9jd+3px2BGj0mbznO+O 60Y++4RAB9ErtU+5dX7iWMtRs0U+5mRM7n51o7bbwVUnl3BqmhQL6EApSY9QP5XSdmHT U83A== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=sender:errors-to:cc:list-subscribe:list-help:list-post:list-archive :list-unsubscribe:list-id:precedence:subject:references:in-reply-to :message-id:date:to:from:dkim-signature:arc-authentication-results; bh=qAopa50gYfq2Vf0Uf2GaUiVf4psdoSpxUudciIaTs6M=; b=BhGx92AySP+1BGOc97sCYhTkI3BqA+EypGG3SEjaY96zxHRIlEVDgyStuZuf0SGCPM 18eTtVV1VaOtp5C+QnP3/Umw6Av3ObmZChUu1e6pK0gDYKw3c7m+tQidpUIyB7QKTciB 5v4NRXJLHI0EUsV0LCIv0t1wLL5hTTgESNdfbmpXIbm4G5NOaxtDBeu54vtti2q7T+j/ tv9Ib2Dg2kN8E/iwVUgw0Yxk+5k0j9c5a3k+m2rKn1wrTmsjCtXQFQgdu+5CrggUTS51 YYKlyFGKYJz6MwHG87OIxRym6hziT+BQMP4JRnsOhoffqmLTwNGOtYdynitf1mjZ4OXR ohEQ== ARC-Authentication-Results: i=1; mx.google.com; dkim=fail header.i=@linaro.org header.s=google header.b=TcJ0GepW; spf=pass (google.com: domain of qemu-devel-bounces+patch=linaro.org@nongnu.org designates 2001:4830:134:3::11 as permitted sender) smtp.mailfrom=qemu-devel-bounces+patch=linaro.org@nongnu.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=linaro.org Return-Path: Received: from lists.gnu.org (lists.gnu.org. [2001:4830:134:3::11]) by mx.google.com with ESMTPS id o2si1040924ybm.751.2018.02.03.20.21.11 for (version=TLS1 cipher=AES128-SHA bits=128/128); Sat, 03 Feb 2018 20:21:11 -0800 (PST) Received-SPF: pass (google.com: domain of qemu-devel-bounces+patch=linaro.org@nongnu.org designates 2001:4830:134:3::11 as permitted sender) client-ip=2001:4830:134:3::11; Authentication-Results: mx.google.com; dkim=fail header.i=@linaro.org header.s=google header.b=TcJ0GepW; spf=pass (google.com: domain of qemu-devel-bounces+patch=linaro.org@nongnu.org designates 2001:4830:134:3::11 as permitted sender) smtp.mailfrom=qemu-devel-bounces+patch=linaro.org@nongnu.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=linaro.org Received: from localhost ([::1]:58291 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1eiBni-00031r-Hw for patch@linaro.org; Sat, 03 Feb 2018 23:21:10 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:47418) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1eiBf0-0004rY-Cl for qemu-devel@nongnu.org; Sat, 03 Feb 2018 23:12:15 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1eiBev-000514-P9 for qemu-devel@nongnu.org; Sat, 03 Feb 2018 23:12:10 -0500 Received: from mail-pg0-x241.google.com ([2607:f8b0:400e:c05::241]:46160) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1eiBev-00050A-DE for qemu-devel@nongnu.org; Sat, 03 Feb 2018 23:12:05 -0500 Received: by mail-pg0-x241.google.com with SMTP id s9so15973596pgq.13 for ; Sat, 03 Feb 2018 20:12:05 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=qAopa50gYfq2Vf0Uf2GaUiVf4psdoSpxUudciIaTs6M=; b=TcJ0GepWatHbj8U8WTUmwHr6BvM6zu/+tMhSj6O7o14hH7s02PjisHPMNPjXzTS/WI cTyCQILwxj36RPlOyZXn1Kpjgpj0FJh0l+2vs7rTgDItM3oMOTWku53+eobrWL69rgfn ZyPobyePYOrc8zCxHFfnhcJSlQT7PvstAmwSs= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=qAopa50gYfq2Vf0Uf2GaUiVf4psdoSpxUudciIaTs6M=; b=ODBM5Nyx3gVGv1EJbj7EXBq3bt8RbarZlrYoIcVPt+DY1aMpiWOUBYn7VHT0BCrava LPFQ0CShqFxCWelsvrNzwgjs1Hj2vfvT5KtmXqE7dto9LHuqbwCtvTybHzOhg14tYtlo 7Dn+Ibc6ZOgqzPN8xgLbe23CUFqGFarOKvnDUuS4ZLmFwqlhO9vYRNnkJ5eVYTm9n+4U xp9I8E85/13qFM8AanFENfksBJ3fzFgTzXeqOTC1hy83KxL7n4tswuxIIN54LtJbz8Vm ouTVe0dO4TTaLuYMj4Jo33yrqENcvnxxkq+NR4oIHxe+AfulyDMLh2Nb6IYM5EspttON 5ssQ== X-Gm-Message-State: AKwxytdy9fnUrCepAdmG+F+xTlSSkfp0h4cvY5KXJhmIUkjlvE62J0oG Y+ql9VQdvYPAeELa1jh8bR6Cvcb7ynE= X-Received: by 10.98.89.71 with SMTP id n68mr29736918pfb.121.1517717523219; Sat, 03 Feb 2018 20:12:03 -0800 (PST) Received: from cloudburst.twiddle.net (174-21-6-47.tukw.qwest.net. [174.21.6.47]) by smtp.gmail.com with ESMTPSA id k3sm1399425pgr.12.2018.02.03.20.12.01 (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Sat, 03 Feb 2018 20:12:02 -0800 (PST) From: Richard Henderson To: qemu-devel@nongnu.org Date: Sat, 3 Feb 2018 20:11:28 -0800 Message-Id: <20180204041136.17525-17-richard.henderson@linaro.org> X-Mailer: git-send-email 2.14.3 In-Reply-To: <20180204041136.17525-1-richard.henderson@linaro.org> References: <20180204041136.17525-1-richard.henderson@linaro.org> X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 2607:f8b0:400e:c05::241 Subject: [Qemu-devel] [PATCH 16/24] fpu: Implement float_to_int/uint with soft-fp.h X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: peter.maydell@linaro.org, cota@braap.org, alex.bennee@linaro.org, hsp.cat7@gmail.com Errors-To: qemu-devel-bounces+patch=linaro.org@nongnu.org Sender: "Qemu-devel" Add float16 conversions. For consistency, add missing float128 conversions to uint32_t. Signed-off-by: Richard Henderson --- include/fpu/softfloat.h | 20 +- fpu/floatxx.inc.c | 45 ++ fpu/softfloat.c | 1088 ----------------------------------------------- 3 files changed, 64 insertions(+), 1089 deletions(-) -- 2.14.3 diff --git a/include/fpu/softfloat.h b/include/fpu/softfloat.h index 85e4a74f1b..cd39131c10 100644 --- a/include/fpu/softfloat.h +++ b/include/fpu/softfloat.h @@ -228,6 +228,19 @@ static inline float64 uint16_to_float64(uint16_t v, float_status *status) /*---------------------------------------------------------------------------- | Software half-precision conversion routines. *----------------------------------------------------------------------------*/ +int16_t float16_to_int16(float16, float_status *status); +uint16_t float16_to_uint16(float16, float_status *status); +int16_t float16_to_int16_round_to_zero(float16, float_status *status); +uint16_t float16_to_uint16_round_to_zero(float16, float_status *status); +int32_t float16_to_int32(float16, float_status *status); +int32_t float16_to_int32_round_to_zero(float16, float_status *status); +uint32_t float16_to_uint32(float16, float_status *status); +uint32_t float16_to_uint32_round_to_zero(float16, float_status *status); +int64_t float16_to_int64(float16, float_status *status); +uint64_t float16_to_uint64(float16, float_status *status); +uint64_t float16_to_uint64_round_to_zero(float16, float_status *status); +int64_t float16_to_int64_round_to_zero(float16, float_status *status); + float16 float32_to_float16(float32, flag, float_status *status); float32 float16_to_float32(float16, flag, float_status *status); float16 float64_to_float16(float64 a, flag ieee, float_status *status); @@ -627,13 +640,18 @@ floatx80 floatx80_default_nan(float_status *status); /*---------------------------------------------------------------------------- | Software IEC/IEEE quadruple-precision conversion routines. *----------------------------------------------------------------------------*/ +int16_t float128_to_int16(float128, float_status *status); +int16_t float128_to_int16_round_to_zero(float128, float_status *status); +uint16_t float128_to_uint16(float128, float_status *status); +uint16_t float128_to_uint16_round_to_zero(float128, float_status *status); int32_t float128_to_int32(float128, float_status *status); int32_t float128_to_int32_round_to_zero(float128, float_status *status); +uint32_t float128_to_uint32(float128, float_status *status); +uint32_t float128_to_uint32_round_to_zero(float128, float_status *status); int64_t float128_to_int64(float128, float_status *status); int64_t float128_to_int64_round_to_zero(float128, float_status *status); uint64_t float128_to_uint64(float128, float_status *status); uint64_t float128_to_uint64_round_to_zero(float128, float_status *status); -uint32_t float128_to_uint32_round_to_zero(float128, float_status *status); float32 float128_to_float32(float128, float_status *status); float64 float128_to_float64(float128, float_status *status); floatx80 float128_to_floatx80(float128, float_status *status); diff --git a/fpu/floatxx.inc.c b/fpu/floatxx.inc.c index aca5ed3097..da6c17afab 100644 --- a/fpu/floatxx.inc.c +++ b/fpu/floatxx.inc.c @@ -96,3 +96,48 @@ FLOATXX glue(FLOATXX,_div)(FLOATXX a, FLOATXX b, float_status *status) return r; } + +#define DO_FLOAT_TO_INT(NAME, SZ, FP_TO_INT_WHICH) \ +int##SZ##_t NAME(FLOATXX a, float_status *status) \ +{ \ + FP_DECL_EX; \ + glue(FP_DECL_, FS)(A); \ + uint##SZ##_t r; \ + FP_INIT_ROUNDMODE; \ + glue(FP_UNPACK_RAW_, FS)(A, a); \ + glue(FP_TO_INT_WHICH, FS)(r, A, SZ, 1); \ + FP_HANDLE_EXCEPTIONS; \ + return r; \ +} + +#define DO_FLOAT_TO_UINT(NAME, SZ, FP_TO_INT_WHICH) \ +uint##SZ##_t NAME(FLOATXX a, float_status *status) \ +{ \ + FP_DECL_EX; \ + glue(FP_DECL_, FS)(A); \ + uint##SZ##_t r; \ + FP_INIT_ROUNDMODE; \ + glue(FP_UNPACK_RAW_, FS)(A, a); \ + glue(FP_TO_INT_WHICH, FS)(r, A, SZ, 0); \ + FP_HANDLE_EXCEPTIONS; \ + return r; \ +} + +DO_FLOAT_TO_INT(glue(FLOATXX,_to_int16), 16, FP_TO_INT_ROUND_) +DO_FLOAT_TO_INT(glue(FLOATXX,_to_int32), 32, FP_TO_INT_ROUND_) +DO_FLOAT_TO_INT(glue(FLOATXX,_to_int64), 64, FP_TO_INT_ROUND_) + +DO_FLOAT_TO_INT(glue(FLOATXX,_to_int16_round_to_zero), 16, FP_TO_INT_) +DO_FLOAT_TO_INT(glue(FLOATXX,_to_int32_round_to_zero), 32, FP_TO_INT_) +DO_FLOAT_TO_INT(glue(FLOATXX,_to_int64_round_to_zero), 64, FP_TO_INT_) + +DO_FLOAT_TO_UINT(glue(FLOATXX,_to_uint16), 16, FP_TO_INT_ROUND_) +DO_FLOAT_TO_UINT(glue(FLOATXX,_to_uint32), 32, FP_TO_INT_ROUND_) +DO_FLOAT_TO_UINT(glue(FLOATXX,_to_uint64), 64, FP_TO_INT_ROUND_) + +DO_FLOAT_TO_UINT(glue(FLOATXX,_to_uint16_round_to_zero), 16, FP_TO_INT_) +DO_FLOAT_TO_UINT(glue(FLOATXX,_to_uint32_round_to_zero), 32, FP_TO_INT_) +DO_FLOAT_TO_UINT(glue(FLOATXX,_to_uint64_round_to_zero), 64, FP_TO_INT_) + +#undef DO_FLOAT_TO_INT +#undef DO_FLOAT_TO_UINT diff --git a/fpu/softfloat.c b/fpu/softfloat.c index 7cadf8ef1e..3fe12abab1 100644 --- a/fpu/softfloat.c +++ b/fpu/softfloat.c @@ -244,61 +244,6 @@ static int64_t roundAndPackInt64(flag zSign, uint64_t absZ0, uint64_t absZ1, } -/*---------------------------------------------------------------------------- -| Takes the 128-bit fixed-point value formed by concatenating `absZ0' and -| `absZ1', with binary point between bits 63 and 64 (between the input words), -| and returns the properly rounded 64-bit unsigned integer corresponding to the -| input. Ordinarily, the fixed-point input is simply rounded to an integer, -| with the inexact exception raised if the input cannot be represented exactly -| as an integer. However, if the fixed-point input is too large, the invalid -| exception is raised and the largest unsigned integer is returned. -*----------------------------------------------------------------------------*/ - -static int64_t roundAndPackUint64(flag zSign, uint64_t absZ0, - uint64_t absZ1, float_status *status) -{ - int8_t roundingMode; - flag roundNearestEven, increment; - - roundingMode = status->float_rounding_mode; - roundNearestEven = (roundingMode == float_round_nearest_even); - switch (roundingMode) { - case float_round_nearest_even: - case float_round_ties_away: - increment = ((int64_t)absZ1 < 0); - break; - case float_round_to_zero: - increment = 0; - break; - case float_round_up: - increment = !zSign && absZ1; - break; - case float_round_down: - increment = zSign && absZ1; - break; - default: - abort(); - } - if (increment) { - ++absZ0; - if (absZ0 == 0) { - float_raise(float_flag_invalid, status); - return LIT64(0xFFFFFFFFFFFFFFFF); - } - absZ0 &= ~(((uint64_t)(absZ1<<1) == 0) & roundNearestEven); - } - - if (zSign && absZ0) { - float_raise(float_flag_invalid, status); - return 0; - } - - if (absZ1) { - status->float_exception_flags |= float_flag_inexact; - } - return absZ0; -} - /*---------------------------------------------------------------------------- | Returns the fraction bits of the single-precision floating-point value `a'. *----------------------------------------------------------------------------*/ @@ -1549,289 +1494,6 @@ float128 uint64_to_float128(uint64_t a, float_status *status) return normalizeRoundAndPackFloat128(0, 0x406E, a, 0, status); } -/*---------------------------------------------------------------------------- -| Returns the result of converting the single-precision floating-point value -| `a' to the 32-bit two's complement integer format. The conversion is -| performed according to the IEC/IEEE Standard for Binary Floating-Point -| Arithmetic---which means in particular that the conversion is rounded -| according to the current rounding mode. If `a' is a NaN, the largest -| positive integer is returned. Otherwise, if the conversion overflows, the -| largest integer with the same sign as `a' is returned. -*----------------------------------------------------------------------------*/ - -int32_t float32_to_int32(float32 a, float_status *status) -{ - flag aSign; - int aExp; - int shiftCount; - uint32_t aSig; - uint64_t aSig64; - - a = float32_squash_input_denormal(a, status); - aSig = extractFloat32Frac( a ); - aExp = extractFloat32Exp( a ); - aSign = extractFloat32Sign( a ); - if ( ( aExp == 0xFF ) && aSig ) aSign = 0; - if ( aExp ) aSig |= 0x00800000; - shiftCount = 0xAF - aExp; - aSig64 = aSig; - aSig64 <<= 32; - if ( 0 < shiftCount ) shift64RightJamming( aSig64, shiftCount, &aSig64 ); - return roundAndPackInt32(aSign, aSig64, status); - -} - -/*---------------------------------------------------------------------------- -| Returns the result of converting the single-precision floating-point value -| `a' to the 32-bit two's complement integer format. The conversion is -| performed according to the IEC/IEEE Standard for Binary Floating-Point -| Arithmetic, except that the conversion is always rounded toward zero. -| If `a' is a NaN, the largest positive integer is returned. Otherwise, if -| the conversion overflows, the largest integer with the same sign as `a' is -| returned. -*----------------------------------------------------------------------------*/ - -int32_t float32_to_int32_round_to_zero(float32 a, float_status *status) -{ - flag aSign; - int aExp; - int shiftCount; - uint32_t aSig; - int32_t z; - a = float32_squash_input_denormal(a, status); - - aSig = extractFloat32Frac( a ); - aExp = extractFloat32Exp( a ); - aSign = extractFloat32Sign( a ); - shiftCount = aExp - 0x9E; - if ( 0 <= shiftCount ) { - if ( float32_val(a) != 0xCF000000 ) { - float_raise(float_flag_invalid, status); - if ( ! aSign || ( ( aExp == 0xFF ) && aSig ) ) return 0x7FFFFFFF; - } - return (int32_t) 0x80000000; - } - else if ( aExp <= 0x7E ) { - if (aExp | aSig) { - status->float_exception_flags |= float_flag_inexact; - } - return 0; - } - aSig = ( aSig | 0x00800000 )<<8; - z = aSig>>( - shiftCount ); - if ( (uint32_t) ( aSig<<( shiftCount & 31 ) ) ) { - status->float_exception_flags |= float_flag_inexact; - } - if ( aSign ) z = - z; - return z; - -} - -/*---------------------------------------------------------------------------- -| Returns the result of converting the single-precision floating-point value -| `a' to the 16-bit two's complement integer format. The conversion is -| performed according to the IEC/IEEE Standard for Binary Floating-Point -| Arithmetic, except that the conversion is always rounded toward zero. -| If `a' is a NaN, the largest positive integer is returned. Otherwise, if -| the conversion overflows, the largest integer with the same sign as `a' is -| returned. -*----------------------------------------------------------------------------*/ - -int16_t float32_to_int16_round_to_zero(float32 a, float_status *status) -{ - flag aSign; - int aExp; - int shiftCount; - uint32_t aSig; - int32_t z; - - aSig = extractFloat32Frac( a ); - aExp = extractFloat32Exp( a ); - aSign = extractFloat32Sign( a ); - shiftCount = aExp - 0x8E; - if ( 0 <= shiftCount ) { - if ( float32_val(a) != 0xC7000000 ) { - float_raise(float_flag_invalid, status); - if ( ! aSign || ( ( aExp == 0xFF ) && aSig ) ) { - return 0x7FFF; - } - } - return (int32_t) 0xffff8000; - } - else if ( aExp <= 0x7E ) { - if ( aExp | aSig ) { - status->float_exception_flags |= float_flag_inexact; - } - return 0; - } - shiftCount -= 0x10; - aSig = ( aSig | 0x00800000 )<<8; - z = aSig>>( - shiftCount ); - if ( (uint32_t) ( aSig<<( shiftCount & 31 ) ) ) { - status->float_exception_flags |= float_flag_inexact; - } - if ( aSign ) { - z = - z; - } - return z; - -} - -/*---------------------------------------------------------------------------- -| Returns the result of converting the single-precision floating-point value -| `a' to the 64-bit two's complement integer format. The conversion is -| performed according to the IEC/IEEE Standard for Binary Floating-Point -| Arithmetic---which means in particular that the conversion is rounded -| according to the current rounding mode. If `a' is a NaN, the largest -| positive integer is returned. Otherwise, if the conversion overflows, the -| largest integer with the same sign as `a' is returned. -*----------------------------------------------------------------------------*/ - -int64_t float32_to_int64(float32 a, float_status *status) -{ - flag aSign; - int aExp; - int shiftCount; - uint32_t aSig; - uint64_t aSig64, aSigExtra; - a = float32_squash_input_denormal(a, status); - - aSig = extractFloat32Frac( a ); - aExp = extractFloat32Exp( a ); - aSign = extractFloat32Sign( a ); - shiftCount = 0xBE - aExp; - if ( shiftCount < 0 ) { - float_raise(float_flag_invalid, status); - if ( ! aSign || ( ( aExp == 0xFF ) && aSig ) ) { - return LIT64( 0x7FFFFFFFFFFFFFFF ); - } - return (int64_t) LIT64( 0x8000000000000000 ); - } - if ( aExp ) aSig |= 0x00800000; - aSig64 = aSig; - aSig64 <<= 40; - shift64ExtraRightJamming( aSig64, 0, shiftCount, &aSig64, &aSigExtra ); - return roundAndPackInt64(aSign, aSig64, aSigExtra, status); - -} - -/*---------------------------------------------------------------------------- -| Returns the result of converting the single-precision floating-point value -| `a' to the 64-bit unsigned integer format. The conversion is -| performed according to the IEC/IEEE Standard for Binary Floating-Point -| Arithmetic---which means in particular that the conversion is rounded -| according to the current rounding mode. If `a' is a NaN, the largest -| unsigned integer is returned. Otherwise, if the conversion overflows, the -| largest unsigned integer is returned. If the 'a' is negative, the result -| is rounded and zero is returned; values that do not round to zero will -| raise the inexact exception flag. -*----------------------------------------------------------------------------*/ - -uint64_t float32_to_uint64(float32 a, float_status *status) -{ - flag aSign; - int aExp; - int shiftCount; - uint32_t aSig; - uint64_t aSig64, aSigExtra; - a = float32_squash_input_denormal(a, status); - - aSig = extractFloat32Frac(a); - aExp = extractFloat32Exp(a); - aSign = extractFloat32Sign(a); - if ((aSign) && (aExp > 126)) { - float_raise(float_flag_invalid, status); - if (float32_is_any_nan(a)) { - return LIT64(0xFFFFFFFFFFFFFFFF); - } else { - return 0; - } - } - shiftCount = 0xBE - aExp; - if (aExp) { - aSig |= 0x00800000; - } - if (shiftCount < 0) { - float_raise(float_flag_invalid, status); - return LIT64(0xFFFFFFFFFFFFFFFF); - } - - aSig64 = aSig; - aSig64 <<= 40; - shift64ExtraRightJamming(aSig64, 0, shiftCount, &aSig64, &aSigExtra); - return roundAndPackUint64(aSign, aSig64, aSigExtra, status); -} - -/*---------------------------------------------------------------------------- -| Returns the result of converting the single-precision floating-point value -| `a' to the 64-bit unsigned integer format. The conversion is -| performed according to the IEC/IEEE Standard for Binary Floating-Point -| Arithmetic, except that the conversion is always rounded toward zero. If -| `a' is a NaN, the largest unsigned integer is returned. Otherwise, if the -| conversion overflows, the largest unsigned integer is returned. If the -| 'a' is negative, the result is rounded and zero is returned; values that do -| not round to zero will raise the inexact flag. -*----------------------------------------------------------------------------*/ - -uint64_t float32_to_uint64_round_to_zero(float32 a, float_status *status) -{ - signed char current_rounding_mode = status->float_rounding_mode; - set_float_rounding_mode(float_round_to_zero, status); - int64_t v = float32_to_uint64(a, status); - set_float_rounding_mode(current_rounding_mode, status); - return v; -} - -/*---------------------------------------------------------------------------- -| Returns the result of converting the single-precision floating-point value -| `a' to the 64-bit two's complement integer format. The conversion is -| performed according to the IEC/IEEE Standard for Binary Floating-Point -| Arithmetic, except that the conversion is always rounded toward zero. If -| `a' is a NaN, the largest positive integer is returned. Otherwise, if the -| conversion overflows, the largest integer with the same sign as `a' is -| returned. -*----------------------------------------------------------------------------*/ - -int64_t float32_to_int64_round_to_zero(float32 a, float_status *status) -{ - flag aSign; - int aExp; - int shiftCount; - uint32_t aSig; - uint64_t aSig64; - int64_t z; - a = float32_squash_input_denormal(a, status); - - aSig = extractFloat32Frac( a ); - aExp = extractFloat32Exp( a ); - aSign = extractFloat32Sign( a ); - shiftCount = aExp - 0xBE; - if ( 0 <= shiftCount ) { - if ( float32_val(a) != 0xDF000000 ) { - float_raise(float_flag_invalid, status); - if ( ! aSign || ( ( aExp == 0xFF ) && aSig ) ) { - return LIT64( 0x7FFFFFFFFFFFFFFF ); - } - } - return (int64_t) LIT64( 0x8000000000000000 ); - } - else if ( aExp <= 0x7E ) { - if (aExp | aSig) { - status->float_exception_flags |= float_flag_inexact; - } - return 0; - } - aSig64 = aSig | 0x00800000; - aSig64 <<= 40; - z = aSig64>>( - shiftCount ); - if ( (uint64_t) ( aSig64<<( shiftCount & 63 ) ) ) { - status->float_exception_flags |= float_flag_inexact; - } - if ( aSign ) z = - z; - return z; - -} - /*---------------------------------------------------------------------------- | Returns the result of converting the single-precision floating-point value | `a' to the double-precision floating-point format. The conversion is @@ -2742,237 +2404,6 @@ int float32_unordered_quiet(float32 a, float32 b, float_status *status) return 0; } -/*---------------------------------------------------------------------------- -| Returns the result of converting the double-precision floating-point value -| `a' to the 32-bit two's complement integer format. The conversion is -| performed according to the IEC/IEEE Standard for Binary Floating-Point -| Arithmetic---which means in particular that the conversion is rounded -| according to the current rounding mode. If `a' is a NaN, the largest -| positive integer is returned. Otherwise, if the conversion overflows, the -| largest integer with the same sign as `a' is returned. -*----------------------------------------------------------------------------*/ - -int32_t float64_to_int32(float64 a, float_status *status) -{ - flag aSign; - int aExp; - int shiftCount; - uint64_t aSig; - a = float64_squash_input_denormal(a, status); - - aSig = extractFloat64Frac( a ); - aExp = extractFloat64Exp( a ); - aSign = extractFloat64Sign( a ); - if ( ( aExp == 0x7FF ) && aSig ) aSign = 0; - if ( aExp ) aSig |= LIT64( 0x0010000000000000 ); - shiftCount = 0x42C - aExp; - if ( 0 < shiftCount ) shift64RightJamming( aSig, shiftCount, &aSig ); - return roundAndPackInt32(aSign, aSig, status); - -} - -/*---------------------------------------------------------------------------- -| Returns the result of converting the double-precision floating-point value -| `a' to the 32-bit two's complement integer format. The conversion is -| performed according to the IEC/IEEE Standard for Binary Floating-Point -| Arithmetic, except that the conversion is always rounded toward zero. -| If `a' is a NaN, the largest positive integer is returned. Otherwise, if -| the conversion overflows, the largest integer with the same sign as `a' is -| returned. -*----------------------------------------------------------------------------*/ - -int32_t float64_to_int32_round_to_zero(float64 a, float_status *status) -{ - flag aSign; - int aExp; - int shiftCount; - uint64_t aSig, savedASig; - int32_t z; - a = float64_squash_input_denormal(a, status); - - aSig = extractFloat64Frac( a ); - aExp = extractFloat64Exp( a ); - aSign = extractFloat64Sign( a ); - if ( 0x41E < aExp ) { - if ( ( aExp == 0x7FF ) && aSig ) aSign = 0; - goto invalid; - } - else if ( aExp < 0x3FF ) { - if (aExp || aSig) { - status->float_exception_flags |= float_flag_inexact; - } - return 0; - } - aSig |= LIT64( 0x0010000000000000 ); - shiftCount = 0x433 - aExp; - savedASig = aSig; - aSig >>= shiftCount; - z = aSig; - if ( aSign ) z = - z; - if ( ( z < 0 ) ^ aSign ) { - invalid: - float_raise(float_flag_invalid, status); - return aSign ? (int32_t) 0x80000000 : 0x7FFFFFFF; - } - if ( ( aSig<float_exception_flags |= float_flag_inexact; - } - return z; - -} - -/*---------------------------------------------------------------------------- -| Returns the result of converting the double-precision floating-point value -| `a' to the 16-bit two's complement integer format. The conversion is -| performed according to the IEC/IEEE Standard for Binary Floating-Point -| Arithmetic, except that the conversion is always rounded toward zero. -| If `a' is a NaN, the largest positive integer is returned. Otherwise, if -| the conversion overflows, the largest integer with the same sign as `a' is -| returned. -*----------------------------------------------------------------------------*/ - -int16_t float64_to_int16_round_to_zero(float64 a, float_status *status) -{ - flag aSign; - int aExp; - int shiftCount; - uint64_t aSig, savedASig; - int32_t z; - - aSig = extractFloat64Frac( a ); - aExp = extractFloat64Exp( a ); - aSign = extractFloat64Sign( a ); - if ( 0x40E < aExp ) { - if ( ( aExp == 0x7FF ) && aSig ) { - aSign = 0; - } - goto invalid; - } - else if ( aExp < 0x3FF ) { - if ( aExp || aSig ) { - status->float_exception_flags |= float_flag_inexact; - } - return 0; - } - aSig |= LIT64( 0x0010000000000000 ); - shiftCount = 0x433 - aExp; - savedASig = aSig; - aSig >>= shiftCount; - z = aSig; - if ( aSign ) { - z = - z; - } - if ( ( (int16_t)z < 0 ) ^ aSign ) { - invalid: - float_raise(float_flag_invalid, status); - return aSign ? (int32_t) 0xffff8000 : 0x7FFF; - } - if ( ( aSig<float_exception_flags |= float_flag_inexact; - } - return z; -} - -/*---------------------------------------------------------------------------- -| Returns the result of converting the double-precision floating-point value -| `a' to the 64-bit two's complement integer format. The conversion is -| performed according to the IEC/IEEE Standard for Binary Floating-Point -| Arithmetic---which means in particular that the conversion is rounded -| according to the current rounding mode. If `a' is a NaN, the largest -| positive integer is returned. Otherwise, if the conversion overflows, the -| largest integer with the same sign as `a' is returned. -*----------------------------------------------------------------------------*/ - -int64_t float64_to_int64(float64 a, float_status *status) -{ - flag aSign; - int aExp; - int shiftCount; - uint64_t aSig, aSigExtra; - a = float64_squash_input_denormal(a, status); - - aSig = extractFloat64Frac( a ); - aExp = extractFloat64Exp( a ); - aSign = extractFloat64Sign( a ); - if ( aExp ) aSig |= LIT64( 0x0010000000000000 ); - shiftCount = 0x433 - aExp; - if ( shiftCount <= 0 ) { - if ( 0x43E < aExp ) { - float_raise(float_flag_invalid, status); - if ( ! aSign - || ( ( aExp == 0x7FF ) - && ( aSig != LIT64( 0x0010000000000000 ) ) ) - ) { - return LIT64( 0x7FFFFFFFFFFFFFFF ); - } - return (int64_t) LIT64( 0x8000000000000000 ); - } - aSigExtra = 0; - aSig <<= - shiftCount; - } - else { - shift64ExtraRightJamming( aSig, 0, shiftCount, &aSig, &aSigExtra ); - } - return roundAndPackInt64(aSign, aSig, aSigExtra, status); - -} - -/*---------------------------------------------------------------------------- -| Returns the result of converting the double-precision floating-point value -| `a' to the 64-bit two's complement integer format. The conversion is -| performed according to the IEC/IEEE Standard for Binary Floating-Point -| Arithmetic, except that the conversion is always rounded toward zero. -| If `a' is a NaN, the largest positive integer is returned. Otherwise, if -| the conversion overflows, the largest integer with the same sign as `a' is -| returned. -*----------------------------------------------------------------------------*/ - -int64_t float64_to_int64_round_to_zero(float64 a, float_status *status) -{ - flag aSign; - int aExp; - int shiftCount; - uint64_t aSig; - int64_t z; - a = float64_squash_input_denormal(a, status); - - aSig = extractFloat64Frac( a ); - aExp = extractFloat64Exp( a ); - aSign = extractFloat64Sign( a ); - if ( aExp ) aSig |= LIT64( 0x0010000000000000 ); - shiftCount = aExp - 0x433; - if ( 0 <= shiftCount ) { - if ( 0x43E <= aExp ) { - if ( float64_val(a) != LIT64( 0xC3E0000000000000 ) ) { - float_raise(float_flag_invalid, status); - if ( ! aSign - || ( ( aExp == 0x7FF ) - && ( aSig != LIT64( 0x0010000000000000 ) ) ) - ) { - return LIT64( 0x7FFFFFFFFFFFFFFF ); - } - } - return (int64_t) LIT64( 0x8000000000000000 ); - } - z = aSig<float_exception_flags |= float_flag_inexact; - } - return 0; - } - z = aSig>>( - shiftCount ); - if ( (uint64_t) ( aSig<<( shiftCount & 63 ) ) ) { - status->float_exception_flags |= float_flag_inexact; - } - } - if ( aSign ) z = - z; - return z; - -} - /*---------------------------------------------------------------------------- | Returns the result of converting the double-precision floating-point value | `a' to the single-precision floating-point format. The conversion is @@ -5269,278 +4700,6 @@ int floatx80_unordered_quiet(floatx80 a, floatx80 b, float_status *status) return 0; } -/*---------------------------------------------------------------------------- -| Returns the result of converting the quadruple-precision floating-point -| value `a' to the 32-bit two's complement integer format. The conversion -| is performed according to the IEC/IEEE Standard for Binary Floating-Point -| Arithmetic---which means in particular that the conversion is rounded -| according to the current rounding mode. If `a' is a NaN, the largest -| positive integer is returned. Otherwise, if the conversion overflows, the -| largest integer with the same sign as `a' is returned. -*----------------------------------------------------------------------------*/ - -int32_t float128_to_int32(float128 a, float_status *status) -{ - flag aSign; - int32_t aExp, shiftCount; - uint64_t aSig0, aSig1; - - aSig1 = extractFloat128Frac1( a ); - aSig0 = extractFloat128Frac0( a ); - aExp = extractFloat128Exp( a ); - aSign = extractFloat128Sign( a ); - if ( ( aExp == 0x7FFF ) && ( aSig0 | aSig1 ) ) aSign = 0; - if ( aExp ) aSig0 |= LIT64( 0x0001000000000000 ); - aSig0 |= ( aSig1 != 0 ); - shiftCount = 0x4028 - aExp; - if ( 0 < shiftCount ) shift64RightJamming( aSig0, shiftCount, &aSig0 ); - return roundAndPackInt32(aSign, aSig0, status); - -} - -/*---------------------------------------------------------------------------- -| Returns the result of converting the quadruple-precision floating-point -| value `a' to the 32-bit two's complement integer format. The conversion -| is performed according to the IEC/IEEE Standard for Binary Floating-Point -| Arithmetic, except that the conversion is always rounded toward zero. If -| `a' is a NaN, the largest positive integer is returned. Otherwise, if the -| conversion overflows, the largest integer with the same sign as `a' is -| returned. -*----------------------------------------------------------------------------*/ - -int32_t float128_to_int32_round_to_zero(float128 a, float_status *status) -{ - flag aSign; - int32_t aExp, shiftCount; - uint64_t aSig0, aSig1, savedASig; - int32_t z; - - aSig1 = extractFloat128Frac1( a ); - aSig0 = extractFloat128Frac0( a ); - aExp = extractFloat128Exp( a ); - aSign = extractFloat128Sign( a ); - aSig0 |= ( aSig1 != 0 ); - if ( 0x401E < aExp ) { - if ( ( aExp == 0x7FFF ) && aSig0 ) aSign = 0; - goto invalid; - } - else if ( aExp < 0x3FFF ) { - if (aExp || aSig0) { - status->float_exception_flags |= float_flag_inexact; - } - return 0; - } - aSig0 |= LIT64( 0x0001000000000000 ); - shiftCount = 0x402F - aExp; - savedASig = aSig0; - aSig0 >>= shiftCount; - z = aSig0; - if ( aSign ) z = - z; - if ( ( z < 0 ) ^ aSign ) { - invalid: - float_raise(float_flag_invalid, status); - return aSign ? (int32_t) 0x80000000 : 0x7FFFFFFF; - } - if ( ( aSig0<float_exception_flags |= float_flag_inexact; - } - return z; - -} - -/*---------------------------------------------------------------------------- -| Returns the result of converting the quadruple-precision floating-point -| value `a' to the 64-bit two's complement integer format. The conversion -| is performed according to the IEC/IEEE Standard for Binary Floating-Point -| Arithmetic---which means in particular that the conversion is rounded -| according to the current rounding mode. If `a' is a NaN, the largest -| positive integer is returned. Otherwise, if the conversion overflows, the -| largest integer with the same sign as `a' is returned. -*----------------------------------------------------------------------------*/ - -int64_t float128_to_int64(float128 a, float_status *status) -{ - flag aSign; - int32_t aExp, shiftCount; - uint64_t aSig0, aSig1; - - aSig1 = extractFloat128Frac1( a ); - aSig0 = extractFloat128Frac0( a ); - aExp = extractFloat128Exp( a ); - aSign = extractFloat128Sign( a ); - if ( aExp ) aSig0 |= LIT64( 0x0001000000000000 ); - shiftCount = 0x402F - aExp; - if ( shiftCount <= 0 ) { - if ( 0x403E < aExp ) { - float_raise(float_flag_invalid, status); - if ( ! aSign - || ( ( aExp == 0x7FFF ) - && ( aSig1 || ( aSig0 != LIT64( 0x0001000000000000 ) ) ) - ) - ) { - return LIT64( 0x7FFFFFFFFFFFFFFF ); - } - return (int64_t) LIT64( 0x8000000000000000 ); - } - shortShift128Left( aSig0, aSig1, - shiftCount, &aSig0, &aSig1 ); - } - else { - shift64ExtraRightJamming( aSig0, aSig1, shiftCount, &aSig0, &aSig1 ); - } - return roundAndPackInt64(aSign, aSig0, aSig1, status); - -} - -/*---------------------------------------------------------------------------- -| Returns the result of converting the quadruple-precision floating-point -| value `a' to the 64-bit two's complement integer format. The conversion -| is performed according to the IEC/IEEE Standard for Binary Floating-Point -| Arithmetic, except that the conversion is always rounded toward zero. -| If `a' is a NaN, the largest positive integer is returned. Otherwise, if -| the conversion overflows, the largest integer with the same sign as `a' is -| returned. -*----------------------------------------------------------------------------*/ - -int64_t float128_to_int64_round_to_zero(float128 a, float_status *status) -{ - flag aSign; - int32_t aExp, shiftCount; - uint64_t aSig0, aSig1; - int64_t z; - - aSig1 = extractFloat128Frac1( a ); - aSig0 = extractFloat128Frac0( a ); - aExp = extractFloat128Exp( a ); - aSign = extractFloat128Sign( a ); - if ( aExp ) aSig0 |= LIT64( 0x0001000000000000 ); - shiftCount = aExp - 0x402F; - if ( 0 < shiftCount ) { - if ( 0x403E <= aExp ) { - aSig0 &= LIT64( 0x0000FFFFFFFFFFFF ); - if ( ( a.high == LIT64( 0xC03E000000000000 ) ) - && ( aSig1 < LIT64( 0x0002000000000000 ) ) ) { - if (aSig1) { - status->float_exception_flags |= float_flag_inexact; - } - } - else { - float_raise(float_flag_invalid, status); - if ( ! aSign || ( ( aExp == 0x7FFF ) && ( aSig0 | aSig1 ) ) ) { - return LIT64( 0x7FFFFFFFFFFFFFFF ); - } - } - return (int64_t) LIT64( 0x8000000000000000 ); - } - z = ( aSig0<>( ( - shiftCount ) & 63 ) ); - if ( (uint64_t) ( aSig1<float_exception_flags |= float_flag_inexact; - } - } - else { - if ( aExp < 0x3FFF ) { - if ( aExp | aSig0 | aSig1 ) { - status->float_exception_flags |= float_flag_inexact; - } - return 0; - } - z = aSig0>>( - shiftCount ); - if ( aSig1 - || ( shiftCount && (uint64_t) ( aSig0<<( shiftCount & 63 ) ) ) ) { - status->float_exception_flags |= float_flag_inexact; - } - } - if ( aSign ) z = - z; - return z; - -} - -/*---------------------------------------------------------------------------- -| Returns the result of converting the quadruple-precision floating-point value -| `a' to the 64-bit unsigned integer format. The conversion is -| performed according to the IEC/IEEE Standard for Binary Floating-Point -| Arithmetic---which means in particular that the conversion is rounded -| according to the current rounding mode. If `a' is a NaN, the largest -| positive integer is returned. If the conversion overflows, the -| largest unsigned integer is returned. If 'a' is negative, the value is -| rounded and zero is returned; negative values that do not round to zero -| will raise the inexact exception. -*----------------------------------------------------------------------------*/ - -uint64_t float128_to_uint64(float128 a, float_status *status) -{ - flag aSign; - int aExp; - int shiftCount; - uint64_t aSig0, aSig1; - - aSig0 = extractFloat128Frac0(a); - aSig1 = extractFloat128Frac1(a); - aExp = extractFloat128Exp(a); - aSign = extractFloat128Sign(a); - if (aSign && (aExp > 0x3FFE)) { - float_raise(float_flag_invalid, status); - if (float128_is_any_nan(a)) { - return LIT64(0xFFFFFFFFFFFFFFFF); - } else { - return 0; - } - } - if (aExp) { - aSig0 |= LIT64(0x0001000000000000); - } - shiftCount = 0x402F - aExp; - if (shiftCount <= 0) { - if (0x403E < aExp) { - float_raise(float_flag_invalid, status); - return LIT64(0xFFFFFFFFFFFFFFFF); - } - shortShift128Left(aSig0, aSig1, -shiftCount, &aSig0, &aSig1); - } else { - shift64ExtraRightJamming(aSig0, aSig1, shiftCount, &aSig0, &aSig1); - } - return roundAndPackUint64(aSign, aSig0, aSig1, status); -} - -uint64_t float128_to_uint64_round_to_zero(float128 a, float_status *status) -{ - uint64_t v; - signed char current_rounding_mode = status->float_rounding_mode; - - set_float_rounding_mode(float_round_to_zero, status); - v = float128_to_uint64(a, status); - set_float_rounding_mode(current_rounding_mode, status); - - return v; -} - -/*---------------------------------------------------------------------------- -| Returns the result of converting the quadruple-precision floating-point -| value `a' to the 32-bit unsigned integer format. The conversion -| is performed according to the IEC/IEEE Standard for Binary Floating-Point -| Arithmetic except that the conversion is always rounded toward zero. -| If `a' is a NaN, the largest positive integer is returned. Otherwise, -| if the conversion overflows, the largest unsigned integer is returned. -| If 'a' is negative, the value is rounded and zero is returned; negative -| values that do not round to zero will raise the inexact exception. -*----------------------------------------------------------------------------*/ - -uint32_t float128_to_uint32_round_to_zero(float128 a, float_status *status) -{ - uint64_t v; - uint32_t res; - int old_exc_flags = get_float_exception_flags(status); - - v = float128_to_uint64_round_to_zero(a, status); - if (v > 0xffffffff) { - res = 0xffffffff; - } else { - return v; - } - set_float_exception_flags(old_exc_flags, status); - float_raise(float_flag_invalid, status); - return res; -} - /*---------------------------------------------------------------------------- | Returns the result of converting the quadruple-precision floating-point | value `a' to the single-precision floating-point format. The conversion @@ -6206,253 +5365,6 @@ float64 uint32_to_float64(uint32_t a, float_status *status) return int64_to_float64(a, status); } -uint32_t float32_to_uint32(float32 a, float_status *status) -{ - int64_t v; - uint32_t res; - int old_exc_flags = get_float_exception_flags(status); - - v = float32_to_int64(a, status); - if (v < 0) { - res = 0; - } else if (v > 0xffffffff) { - res = 0xffffffff; - } else { - return v; - } - set_float_exception_flags(old_exc_flags, status); - float_raise(float_flag_invalid, status); - return res; -} - -uint32_t float32_to_uint32_round_to_zero(float32 a, float_status *status) -{ - int64_t v; - uint32_t res; - int old_exc_flags = get_float_exception_flags(status); - - v = float32_to_int64_round_to_zero(a, status); - if (v < 0) { - res = 0; - } else if (v > 0xffffffff) { - res = 0xffffffff; - } else { - return v; - } - set_float_exception_flags(old_exc_flags, status); - float_raise(float_flag_invalid, status); - return res; -} - -int16_t float32_to_int16(float32 a, float_status *status) -{ - int32_t v; - int16_t res; - int old_exc_flags = get_float_exception_flags(status); - - v = float32_to_int32(a, status); - if (v < -0x8000) { - res = -0x8000; - } else if (v > 0x7fff) { - res = 0x7fff; - } else { - return v; - } - - set_float_exception_flags(old_exc_flags, status); - float_raise(float_flag_invalid, status); - return res; -} - -uint16_t float32_to_uint16(float32 a, float_status *status) -{ - int32_t v; - uint16_t res; - int old_exc_flags = get_float_exception_flags(status); - - v = float32_to_int32(a, status); - if (v < 0) { - res = 0; - } else if (v > 0xffff) { - res = 0xffff; - } else { - return v; - } - - set_float_exception_flags(old_exc_flags, status); - float_raise(float_flag_invalid, status); - return res; -} - -uint16_t float32_to_uint16_round_to_zero(float32 a, float_status *status) -{ - int64_t v; - uint16_t res; - int old_exc_flags = get_float_exception_flags(status); - - v = float32_to_int64_round_to_zero(a, status); - if (v < 0) { - res = 0; - } else if (v > 0xffff) { - res = 0xffff; - } else { - return v; - } - set_float_exception_flags(old_exc_flags, status); - float_raise(float_flag_invalid, status); - return res; -} - -uint32_t float64_to_uint32(float64 a, float_status *status) -{ - uint64_t v; - uint32_t res; - int old_exc_flags = get_float_exception_flags(status); - - v = float64_to_uint64(a, status); - if (v > 0xffffffff) { - res = 0xffffffff; - } else { - return v; - } - set_float_exception_flags(old_exc_flags, status); - float_raise(float_flag_invalid, status); - return res; -} - -uint32_t float64_to_uint32_round_to_zero(float64 a, float_status *status) -{ - uint64_t v; - uint32_t res; - int old_exc_flags = get_float_exception_flags(status); - - v = float64_to_uint64_round_to_zero(a, status); - if (v > 0xffffffff) { - res = 0xffffffff; - } else { - return v; - } - set_float_exception_flags(old_exc_flags, status); - float_raise(float_flag_invalid, status); - return res; -} - -int16_t float64_to_int16(float64 a, float_status *status) -{ - int64_t v; - int16_t res; - int old_exc_flags = get_float_exception_flags(status); - - v = float64_to_int32(a, status); - if (v < -0x8000) { - res = -0x8000; - } else if (v > 0x7fff) { - res = 0x7fff; - } else { - return v; - } - - set_float_exception_flags(old_exc_flags, status); - float_raise(float_flag_invalid, status); - return res; -} - -uint16_t float64_to_uint16(float64 a, float_status *status) -{ - int64_t v; - uint16_t res; - int old_exc_flags = get_float_exception_flags(status); - - v = float64_to_int32(a, status); - if (v < 0) { - res = 0; - } else if (v > 0xffff) { - res = 0xffff; - } else { - return v; - } - - set_float_exception_flags(old_exc_flags, status); - float_raise(float_flag_invalid, status); - return res; -} - -uint16_t float64_to_uint16_round_to_zero(float64 a, float_status *status) -{ - int64_t v; - uint16_t res; - int old_exc_flags = get_float_exception_flags(status); - - v = float64_to_int64_round_to_zero(a, status); - if (v < 0) { - res = 0; - } else if (v > 0xffff) { - res = 0xffff; - } else { - return v; - } - set_float_exception_flags(old_exc_flags, status); - float_raise(float_flag_invalid, status); - return res; -} - -/*---------------------------------------------------------------------------- -| Returns the result of converting the double-precision floating-point value -| `a' to the 64-bit unsigned integer format. The conversion is -| performed according to the IEC/IEEE Standard for Binary Floating-Point -| Arithmetic---which means in particular that the conversion is rounded -| according to the current rounding mode. If `a' is a NaN, the largest -| positive integer is returned. If the conversion overflows, the -| largest unsigned integer is returned. If 'a' is negative, the value is -| rounded and zero is returned; negative values that do not round to zero -| will raise the inexact exception. -*----------------------------------------------------------------------------*/ - -uint64_t float64_to_uint64(float64 a, float_status *status) -{ - flag aSign; - int aExp; - int shiftCount; - uint64_t aSig, aSigExtra; - a = float64_squash_input_denormal(a, status); - - aSig = extractFloat64Frac(a); - aExp = extractFloat64Exp(a); - aSign = extractFloat64Sign(a); - if (aSign && (aExp > 1022)) { - float_raise(float_flag_invalid, status); - if (float64_is_any_nan(a)) { - return LIT64(0xFFFFFFFFFFFFFFFF); - } else { - return 0; - } - } - if (aExp) { - aSig |= LIT64(0x0010000000000000); - } - shiftCount = 0x433 - aExp; - if (shiftCount <= 0) { - if (0x43E < aExp) { - float_raise(float_flag_invalid, status); - return LIT64(0xFFFFFFFFFFFFFFFF); - } - aSigExtra = 0; - aSig <<= -shiftCount; - } else { - shift64ExtraRightJamming(aSig, 0, shiftCount, &aSig, &aSigExtra); - } - return roundAndPackUint64(aSign, aSig, aSigExtra, status); -} - -uint64_t float64_to_uint64_round_to_zero(float64 a, float_status *status) -{ - signed char current_rounding_mode = status->float_rounding_mode; - set_float_rounding_mode(float_round_to_zero, status); - uint64_t v = float64_to_uint64(a, status); - set_float_rounding_mode(current_rounding_mode, status); - return v; -} - #define COMPARE(s, nan_exp) \ static inline int float ## s ## _compare_internal(float ## s a, float ## s b,\ int is_quiet, float_status *status) \ From patchwork Sun Feb 4 04:11:29 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Richard Henderson X-Patchwork-Id: 126807 Delivered-To: patch@linaro.org Received: by 10.46.124.24 with SMTP id x24csp927027ljc; Sat, 3 Feb 2018 20:21:24 -0800 (PST) X-Google-Smtp-Source: AH8x2266ip/Qq+vyVyZNMwF4xz79M2N00p4cc22kkkDV4lpiOGjidYQeKvGWju50j0awXllY7qIT X-Received: by 10.129.31.213 with SMTP id f204mr28795440ywf.337.1517718084211; Sat, 03 Feb 2018 20:21:24 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1517718084; cv=none; d=google.com; s=arc-20160816; b=jNNxDjfe6154H9jQqYBoCqTb/1CKVWQp3ukfVzogWywDxPQbMTWpGRSWvCbCLn5SLB aLgkchiuPnqO47AJPPvc0WblrHQ+poz28JGXhb/lG87QL1LaXtW4GzmTqqYFzz+PbyxC hxxoPC4rccYY+KW07QNEIm5XYP82Z6If968XMBBmqec21p9VVTGt3o0oBHkLhBH3V5MD oBgDF14ausQhrksP7I6SNySXtN9ztkL3gNNXFZYaR3y9xcg0JQnNDdfpP8otz4DMLVvd 6H1aLOdp10vU7jQZjTAxg4detTs3MHZ2fnSvqqSCmPHA8HC4EOjA1NXPywAJfrTALBr7 aE5Q== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=sender:errors-to:cc:list-subscribe:list-help:list-post:list-archive :list-unsubscribe:list-id:precedence:subject:references:in-reply-to :message-id:date:to:from:dkim-signature:arc-authentication-results; bh=ATHx72EGmqJVtVfqfpVoh+QbN7FSKFE2TYN2C4U2Y1w=; b=P3y4lvZtOUMZh9ZmDOqY6XH/Y5mEqc9BaFM1qOhdVsBE1Ga9eBnB/16961e52nPgXC p2RwdkWqgQTt9xVlzGven7Tp51eyPJTyGU+X/QoAiWmo877+FCk2c8pspXUnzMChd+tw hwMulyNnPj22WZQuYmC8sMiYb5qZKdIs3RzA9kLNAAKDZdcMejv9J+emL/pR2Dl7l8ra qox/SibgQuwsdfOWCPqUesfPu5D8NLxA0Ql96q7k0zzesnRXEIwEB/b/p6FtLAt9Z6J5 prRmH68v7zNwM/UjtJS+fQWI5q+hvZr7599iQGorZWdx6GQZQuOINdIt3thjDvI+oYiW vk5Q== ARC-Authentication-Results: i=1; mx.google.com; dkim=fail header.i=@linaro.org header.s=google header.b=dqV0oWSU; spf=pass (google.com: domain of qemu-devel-bounces+patch=linaro.org@nongnu.org designates 2001:4830:134:3::11 as permitted sender) smtp.mailfrom=qemu-devel-bounces+patch=linaro.org@nongnu.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=linaro.org Return-Path: Received: from lists.gnu.org (lists.gnu.org. [2001:4830:134:3::11]) by mx.google.com with ESMTPS id 17si444865ywk.315.2018.02.03.20.21.23 for (version=TLS1 cipher=AES128-SHA bits=128/128); Sat, 03 Feb 2018 20:21:24 -0800 (PST) Received-SPF: pass (google.com: domain of qemu-devel-bounces+patch=linaro.org@nongnu.org designates 2001:4830:134:3::11 as permitted sender) client-ip=2001:4830:134:3::11; Authentication-Results: mx.google.com; dkim=fail header.i=@linaro.org header.s=google header.b=dqV0oWSU; spf=pass (google.com: domain of qemu-devel-bounces+patch=linaro.org@nongnu.org designates 2001:4830:134:3::11 as permitted sender) smtp.mailfrom=qemu-devel-bounces+patch=linaro.org@nongnu.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=linaro.org Received: from localhost ([::1]:58306 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1eiBnv-0004Jm-Ir for patch@linaro.org; Sat, 03 Feb 2018 23:21:23 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:47416) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1eiBf0-0004rX-C1 for qemu-devel@nongnu.org; Sat, 03 Feb 2018 23:12:12 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1eiBew-00051Q-4n for qemu-devel@nongnu.org; Sat, 03 Feb 2018 23:12:10 -0500 Received: from mail-pf0-x244.google.com ([2607:f8b0:400e:c00::244]:33373) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1eiBev-00050Q-Sn for qemu-devel@nongnu.org; Sat, 03 Feb 2018 23:12:06 -0500 Received: by mail-pf0-x244.google.com with SMTP id u15so3376195pfa.0 for ; Sat, 03 Feb 2018 20:12:05 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=ATHx72EGmqJVtVfqfpVoh+QbN7FSKFE2TYN2C4U2Y1w=; b=dqV0oWSU8YzKt7XGbnXqTv3zoHT8UPGkWwXOQGcrVwn0vVi1UazMHK7wzHqtzwMtOv lR82kdMzPrheoqZSRU8QH+EW4CcbHRqX4iItM9Ez/v82v7AlnGZxD3cxKh/UzkUNroNw DPN6I8f4EzvS6GHx8JcEZeUFo4wO5A19QhjXY= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=ATHx72EGmqJVtVfqfpVoh+QbN7FSKFE2TYN2C4U2Y1w=; b=Rog3iYKo5j5DOc3Gj8wBiW71SNbr5PexA5A58NfspjTdn7DYjM1lCjNnbghFWn1tzV NfJ57V+4OV6jyHVM2i1oZXVg1zYetQ8i7UdYgeQJrpaQzbfT1n/tRQAq8xTVqEVG07bh Y3CZMYjErorM5OpICnCz2cMEpuibv+bNufppDqPFfjNRKV406dE9mO7MgJxBNG2s6YuT Cxa7nk5HgJ1WGiCGlpor7er0M/9GyVxAE3mcF5U9D4ZDEul0CcNijx1w68XybJGfOaNr DM/IDoHswoah5hP7rc1Jx3aQYDhF3hCaOC6sTi1t5+pPkb4xBupNs2MPHt8aj3+i9rUI FQXw== X-Gm-Message-State: AKwxytdBOnaxY88wgyxKzDBB6LUlFJeyl8kMR5gqarChhv7KQazhKFRE Vyv3J49tT1U2CebiNrRK2X/zGgm6zQ8= X-Received: by 10.98.101.71 with SMTP id z68mr44831082pfb.181.1517717524574; Sat, 03 Feb 2018 20:12:04 -0800 (PST) Received: from cloudburst.twiddle.net (174-21-6-47.tukw.qwest.net. [174.21.6.47]) by smtp.gmail.com with ESMTPSA id k3sm1399425pgr.12.2018.02.03.20.12.03 (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Sat, 03 Feb 2018 20:12:03 -0800 (PST) From: Richard Henderson To: qemu-devel@nongnu.org Date: Sat, 3 Feb 2018 20:11:29 -0800 Message-Id: <20180204041136.17525-18-richard.henderson@linaro.org> X-Mailer: git-send-email 2.14.3 In-Reply-To: <20180204041136.17525-1-richard.henderson@linaro.org> References: <20180204041136.17525-1-richard.henderson@linaro.org> X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 2607:f8b0:400e:c00::244 Subject: [Qemu-devel] [PATCH 17/24] fpu: Implement int/uint_to_float with soft-fp.h X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: peter.maydell@linaro.org, cota@braap.org, alex.bennee@linaro.org, hsp.cat7@gmail.com Errors-To: qemu-devel-bounces+patch=linaro.org@nongnu.org Sender: "Qemu-devel" Add conversions to float16. For consistency, add float128 conversions from int16_t/uint16_t. Signed-off-by: Richard Henderson --- include/fpu/softfloat.h | 50 +++++------ fpu/floatxx.inc.c | 55 ++++++++++++ fpu/softfloat.c | 227 ------------------------------------------------ 3 files changed, 78 insertions(+), 254 deletions(-) -- 2.14.3 diff --git a/include/fpu/softfloat.h b/include/fpu/softfloat.h index cd39131c10..311c4aba1e 100644 --- a/include/fpu/softfloat.h +++ b/include/fpu/softfloat.h @@ -190,41 +190,37 @@ enum { /*---------------------------------------------------------------------------- | Software IEC/IEEE integer-to-floating-point conversion routines. *----------------------------------------------------------------------------*/ +float16 int16_to_float16(int16_t, float_status *status); +float16 int32_to_float16(int32_t, float_status *status); +float16 int64_to_float16(int64_t, float_status *status); +float16 uint16_to_float16(uint16_t, float_status *status); +float16 uint32_to_float16(uint32_t, float_status *status); +float16 uint64_to_float16(uint64_t, float_status *status); + +float32 int16_to_float32(int16_t, float_status *status); float32 int32_to_float32(int32_t, float_status *status); -float64 int32_to_float64(int32_t, float_status *status); +float32 int64_to_float32(int64_t, float_status *status); +float32 uint16_to_float32(uint16_t, float_status *status); float32 uint32_to_float32(uint32_t, float_status *status); +float32 uint64_to_float32(uint64_t, float_status *status); + +float64 int16_to_float64(int16_t, float_status *status); +float64 int32_to_float64(int32_t, float_status *status); +float64 int64_to_float64(int64_t, float_status *status); +float64 uint16_to_float64(uint16_t, float_status *status); float64 uint32_to_float64(uint32_t, float_status *status); +float64 uint64_to_float64(uint64_t, float_status *status); + floatx80 int32_to_floatx80(int32_t, float_status *status); -float128 int32_to_float128(int32_t, float_status *status); -float32 int64_to_float32(int64_t, float_status *status); -float64 int64_to_float64(int64_t, float_status *status); floatx80 int64_to_floatx80(int64_t, float_status *status); + +float128 int16_to_float128(int16_t, float_status *status); +float128 int32_to_float128(int32_t, float_status *status); float128 int64_to_float128(int64_t, float_status *status); -float32 uint64_to_float32(uint64_t, float_status *status); -float64 uint64_to_float64(uint64_t, float_status *status); +float128 uint16_to_float128(uint16_t, float_status *status); +float128 uint32_to_float128(uint32_t, float_status *status); float128 uint64_to_float128(uint64_t, float_status *status); -/* We provide the int16 versions for symmetry of API with float-to-int */ -static inline float32 int16_to_float32(int16_t v, float_status *status) -{ - return int32_to_float32(v, status); -} - -static inline float32 uint16_to_float32(uint16_t v, float_status *status) -{ - return uint32_to_float32(v, status); -} - -static inline float64 int16_to_float64(int16_t v, float_status *status) -{ - return int32_to_float64(v, status); -} - -static inline float64 uint16_to_float64(uint16_t v, float_status *status) -{ - return uint32_to_float64(v, status); -} - /*---------------------------------------------------------------------------- | Software half-precision conversion routines. *----------------------------------------------------------------------------*/ diff --git a/fpu/floatxx.inc.c b/fpu/floatxx.inc.c index da6c17afab..5ca6c924ab 100644 --- a/fpu/floatxx.inc.c +++ b/fpu/floatxx.inc.c @@ -141,3 +141,58 @@ DO_FLOAT_TO_UINT(glue(FLOATXX,_to_uint64_round_to_zero), 64, FP_TO_INT_) #undef DO_FLOAT_TO_INT #undef DO_FLOAT_TO_UINT + +FLOATXX glue(int64_to_,FLOATXX)(int64_t a, float_status *status) +{ + FP_DECL_EX; + glue(FP_DECL_, FS)(R); + FLOATXX r; + + FP_INIT_ROUNDMODE; + glue(FP_FROM_INT_, FS)(R, a, 64, uint64_t); + glue(FP_PACK_RAW_, FS)(r, R); + FP_HANDLE_EXCEPTIONS; + return r; +} + +FLOATXX glue(int16_to_,FLOATXX)(int16_t a, float_status *status) +{ + return glue(int64_to_,FLOATXX)(a, status); +} + +FLOATXX glue(int32_to_,FLOATXX)(int32_t a, float_status *status) +{ + return glue(int64_to_,FLOATXX)(a, status); +} + +/* The code within _FP_FROM_INT always tests A against 0. For the + unsigned conversion, this may result in a compiler warning. + For -Werror, we need to suppress this. */ + +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wtype-limits" + +FLOATXX glue(uint64_to_,FLOATXX)(uint64_t a, float_status *status) +{ + FP_DECL_EX; + glue(FP_DECL_, FS)(R); + FLOATXX r; + + FP_INIT_ROUNDMODE; + glue(FP_FROM_INT_, FS)(R, a, 64, uint64_t); + glue(FP_PACK_RAW_, FS)(r, R); + FP_HANDLE_EXCEPTIONS; + return r; +} + +#pragma GCC diagnostic pop + +FLOATXX glue(uint16_to_,FLOATXX)(uint16_t a, float_status *status) +{ + return glue(uint64_to_,FLOATXX)(a, status); +} + +FLOATXX glue(uint32_to_,FLOATXX)(uint32_t a, float_status *status) +{ + return glue(uint64_to_,FLOATXX)(a, status); +} diff --git a/fpu/softfloat.c b/fpu/softfloat.c index 3fe12abab1..47b8c4815b 100644 --- a/fpu/softfloat.c +++ b/fpu/softfloat.c @@ -1234,44 +1234,6 @@ static float128 normalizeRoundAndPackFloat128(flag zSign, int32_t zExp, } -/*---------------------------------------------------------------------------- -| Returns the result of converting the 32-bit two's complement integer `a' -| to the single-precision floating-point format. The conversion is performed -| according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -float32 int32_to_float32(int32_t a, float_status *status) -{ - flag zSign; - - if ( a == 0 ) return float32_zero; - if ( a == (int32_t) 0x80000000 ) return packFloat32( 1, 0x9E, 0 ); - zSign = ( a < 0 ); - return normalizeRoundAndPackFloat32(zSign, 0x9C, zSign ? -a : a, status); -} - -/*---------------------------------------------------------------------------- -| Returns the result of converting the 32-bit two's complement integer `a' -| to the double-precision floating-point format. The conversion is performed -| according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -float64 int32_to_float64(int32_t a, float_status *status) -{ - flag zSign; - uint32_t absA; - int8_t shiftCount; - uint64_t zSig; - - if ( a == 0 ) return float64_zero; - zSign = ( a < 0 ); - absA = zSign ? - a : a; - shiftCount = countLeadingZeros32( absA ) + 21; - zSig = absA; - return packFloat64( zSign, 0x432 - shiftCount, zSig<= 0) { - return packFloat32(0, 0x95 - shiftcount, a << shiftcount); - } - /* Otherwise we need to do a round-and-pack. roundAndPackFloat32() - * expects the binary point between bits 30 and 29, hence the + 7. - */ - shiftcount += 7; - if (shiftcount < 0) { - shift64RightJamming(a, -shiftcount, &a); - } else { - a <<= shiftcount; - } - - return roundAndPackFloat32(0, 0x9c - shiftcount, a, status); -} - -/*---------------------------------------------------------------------------- -| Returns the result of converting the 64-bit unsigned integer `a' -| to the double-precision floating-point format. The conversion is performed -| according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -float64 uint64_to_float64(uint64_t a, float_status *status) -{ - int exp = 0x43C; - int shiftcount; - - if (a == 0) { - return float64_zero; - } - - shiftcount = countLeadingZeros64(a) - 1; - if (shiftcount < 0) { - shift64RightJamming(a, -shiftcount, &a); - } else { - a <<= shiftcount; - } - return roundAndPackFloat64(0, exp - shiftcount, a, status); -} - -/*---------------------------------------------------------------------------- -| Returns the result of converting the 64-bit unsigned integer `a' -| to the quadruple-precision floating-point format. The conversion is performed -| according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -float128 uint64_to_float128(uint64_t a, float_status *status) -{ - if (a == 0) { - return float128_zero; - } - return normalizeRoundAndPackFloat128(0, 0x406E, a, 0, status); -} - /*---------------------------------------------------------------------------- | Returns the result of converting the single-precision floating-point value | `a' to the double-precision floating-point format. The conversion is @@ -5354,17 +5138,6 @@ int float128_unordered_quiet(float128 a, float128 b, float_status *status) return 0; } -/* misc functions */ -float32 uint32_to_float32(uint32_t a, float_status *status) -{ - return int64_to_float32(a, status); -} - -float64 uint32_to_float64(uint32_t a, float_status *status) -{ - return int64_to_float64(a, status); -} - #define COMPARE(s, nan_exp) \ static inline int float ## s ## _compare_internal(float ## s a, float ## s b,\ int is_quiet, float_status *status) \ From patchwork Sun Feb 4 04:11:30 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Richard Henderson X-Patchwork-Id: 126808 Delivered-To: patch@linaro.org Received: by 10.80.172.228 with SMTP id x91csp1225684edc; Sat, 3 Feb 2018 20:21:45 -0800 (PST) X-Google-Smtp-Source: AH8x227CrUw/TBkKzq8eEHoPcST3Ro2dpHfj336Z7yPSBYNTkiw/QNrZI7sof+dFvLojckkeYYAr X-Received: by 10.129.107.6 with SMTP id g6mr29422526ywc.133.1517718105049; Sat, 03 Feb 2018 20:21:45 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1517718105; cv=none; d=google.com; s=arc-20160816; b=EqhfE1ldjr8UYR7DQULCApQFFjmpYe7F7mlg8JYpFpoqpRQD+EPAZm891u9/VEavAL d0KsGENV1WBraPPRQQ+aqnLgAEnxP+m0O3kkPCfUW/vMPksJyEg8/T9BmH9mgBkZuqRL TNW9YVZgJtNU+JN5mp6OA8s5bZ/wuB58gfSREPwB/OQ7UCNskuPmZKhx9Et2RYOAGA/A +G7Dc05+cQ8c6E1FD+ylxglO+wMzJgaeWNnfiLJpHdl7P+EOiRldBLKfuIOgqEKLze7H Sg+1iih5QRGPpyTh/6VTy1Gl6jFAudBBpXHVeIORqJQmVdu2JEwpJMvTFiPT+SIpfiE7 VSHw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=sender:errors-to:cc:list-subscribe:list-help:list-post:list-archive :list-unsubscribe:list-id:precedence:subject:references:in-reply-to :message-id:date:to:from:dkim-signature:arc-authentication-results; bh=RMg7Br+8fRZbQ+YXXzz/x8lbnoiUAF9TxL3Ul9BgBPg=; b=r41xxv0SEm89qQDZiB9ncVo10eQd2foTf/T+6W4+nD7zqfmg6vfwSAkf2sSdSJh+Vm rmD7XEUIqVhg2YY8VBLXRCFX9/8D7RE4i5im8Gg7QB1kgcxQFnxUKlVM8hb7mPt1YxS4 bW39zNiLPIhsDjKnyZjpopQJET8ReOJMfcwQRTB9UlmKDYPE+5Y9/YCJBGmV/vkv46mc M+MV6gxlIVky5UCAyoRu5KmYmmAA22fxAR7q5YduxEz7U4jyoaIsQ214KveuYm2OcgUA WBYk1v8/buKJnjPiBqdJyQqWUrv2pGRw0i3fflYQrzeIzHahiWMFfi8fcsiTh7qR2On8 NXCw== ARC-Authentication-Results: i=1; mx.google.com; dkim=fail header.i=@linaro.org header.s=google header.b=ZJzNZS8r; spf=pass (google.com: domain of qemu-devel-bounces+patch=linaro.org@nongnu.org designates 2001:4830:134:3::11 as permitted sender) smtp.mailfrom=qemu-devel-bounces+patch=linaro.org@nongnu.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=linaro.org Return-Path: Received: from lists.gnu.org (lists.gnu.org. [2001:4830:134:3::11]) by mx.google.com with ESMTPS id i202si1022481ywe.799.2018.02.03.20.21.44 for (version=TLS1 cipher=AES128-SHA bits=128/128); Sat, 03 Feb 2018 20:21:45 -0800 (PST) Received-SPF: pass (google.com: domain of qemu-devel-bounces+patch=linaro.org@nongnu.org designates 2001:4830:134:3::11 as permitted sender) client-ip=2001:4830:134:3::11; Authentication-Results: mx.google.com; dkim=fail header.i=@linaro.org header.s=google header.b=ZJzNZS8r; spf=pass (google.com: domain of qemu-devel-bounces+patch=linaro.org@nongnu.org designates 2001:4830:134:3::11 as permitted sender) smtp.mailfrom=qemu-devel-bounces+patch=linaro.org@nongnu.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=linaro.org Received: from localhost ([::1]:58309 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1eiBoG-0004Yl-A4 for patch@linaro.org; Sat, 03 Feb 2018 23:21:44 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:47456) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1eiBf3-0004u9-3N for qemu-devel@nongnu.org; Sat, 03 Feb 2018 23:12:17 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1eiBey-00052x-Hz for qemu-devel@nongnu.org; Sat, 03 Feb 2018 23:12:13 -0500 Received: from mail-pg0-x242.google.com ([2607:f8b0:400e:c05::242]:46161) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1eiBey-000526-6p for qemu-devel@nongnu.org; Sat, 03 Feb 2018 23:12:08 -0500 Received: by mail-pg0-x242.google.com with SMTP id s9so15973629pgq.13 for ; Sat, 03 Feb 2018 20:12:08 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=RMg7Br+8fRZbQ+YXXzz/x8lbnoiUAF9TxL3Ul9BgBPg=; b=ZJzNZS8rJ/ZHfXjjdruLxAgCk1hLRB5vJQt71fNwKDXYaCejhR9dCcIQlFd/TI/st4 plZdR7xm1C9Duwe6Or6jFoWKvrMzoDT+kOdbWnVR/qn7SO4+6Yh94bDKCKuT8KBQ6qIj sWKtkMxyU9CItD4njTXku3EYMt54rK7SPUmwk= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=RMg7Br+8fRZbQ+YXXzz/x8lbnoiUAF9TxL3Ul9BgBPg=; b=Qo2vm3LlSE2V5LNTyhMnHH2iWyaLwPAkyTTlaQ4NDyB6JC5x9sxW6neAnksmXM6Mwo /y5t7iFXVqVzuwuYBAQBp42gVpm0kHSR0EFz7vVWFKMo68fxG4kQs4kz3ymEJtaX5r7Z IAv+4S0tR0ZbptfpCYbUygYRIFPqiSSU7hxfK3K1WPthTSfP4UJtlu0YBT4YDsoZ0mWa B8q1rB2T/7lddFZvDCcNq6lsmxcAV9rrfSLmWekLh56WynSkuxW90jtF4wllgumznmKt oC8zJaGy7DKO3HtayVoTZMbt6sy4KlIkfnVXLsmLPoI+XogYEoQkvcdgwGsfe2TVJzXo Airg== X-Gm-Message-State: AKwxytft/vJUVvg5ko67+Fjf7vTfhKq92AzpuQoH8KcVzDuqkjBebshM 7wt9ZLNAzvMGulzytmcT3v//GJZlpOY= X-Received: by 10.99.141.202 with SMTP id z193mr3454649pgd.418.1517717525925; Sat, 03 Feb 2018 20:12:05 -0800 (PST) Received: from cloudburst.twiddle.net (174-21-6-47.tukw.qwest.net. [174.21.6.47]) by smtp.gmail.com with ESMTPSA id k3sm1399425pgr.12.2018.02.03.20.12.04 (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Sat, 03 Feb 2018 20:12:05 -0800 (PST) From: Richard Henderson To: qemu-devel@nongnu.org Date: Sat, 3 Feb 2018 20:11:30 -0800 Message-Id: <20180204041136.17525-19-richard.henderson@linaro.org> X-Mailer: git-send-email 2.14.3 In-Reply-To: <20180204041136.17525-1-richard.henderson@linaro.org> References: <20180204041136.17525-1-richard.henderson@linaro.org> X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 2607:f8b0:400e:c05::242 Subject: [Qemu-devel] [PATCH 18/24] fpu: Implement compares with soft-fp.h X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: peter.maydell@linaro.org, cota@braap.org, alex.bennee@linaro.org, hsp.cat7@gmail.com Errors-To: qemu-devel-bounces+patch=linaro.org@nongnu.org Sender: "Qemu-devel" Add float16 comparisons. Signed-off-by: Richard Henderson --- include/fpu/softfloat.h | 10 + fpu/floatxx.inc.c | 67 +++ fpu/softfloat.c | 1051 ++--------------------------------------------- 3 files changed, 109 insertions(+), 1019 deletions(-) -- 2.14.3 diff --git a/include/fpu/softfloat.h b/include/fpu/softfloat.h index 311c4aba1e..80df716a55 100644 --- a/include/fpu/softfloat.h +++ b/include/fpu/softfloat.h @@ -250,6 +250,16 @@ float16 float16_add(float16, float16, float_status *status); float16 float16_sub(float16, float16, float_status *status); float16 float16_mul(float16, float16, float_status *status); float16 float16_div(float16, float16, float_status *status); +int float16_eq(float16, float16, float_status *status); +int float16_le(float16, float16, float_status *status); +int float16_lt(float16, float16, float_status *status); +int float16_unordered(float16, float16, float_status *status); +int float16_eq_quiet(float16, float16, float_status *status); +int float16_le_quiet(float16, float16, float_status *status); +int float16_lt_quiet(float16, float16, float_status *status); +int float16_unordered_quiet(float16, float16, float_status *status); +int float16_compare(float16, float16, float_status *status); +int float16_compare_quiet(float16, float16, float_status *status); int float16_is_quiet_nan(float16, float_status *status); int float16_is_signaling_nan(float16, float_status *status); diff --git a/fpu/floatxx.inc.c b/fpu/floatxx.inc.c index 5ca6c924ab..db49423723 100644 --- a/fpu/floatxx.inc.c +++ b/fpu/floatxx.inc.c @@ -196,3 +196,70 @@ FLOATXX glue(uint32_to_,FLOATXX)(uint32_t a, float_status *status) { return glue(uint64_to_,FLOATXX)(a, status); } + +static int compare_internal(FLOATXX a, FLOATXX b, + float_status *status, bool quiet) +{ + FP_DECL_EX; + glue(FP_DECL_, FS)(A); + glue(FP_DECL_, FS)(B); + int r; + + FP_INIT_EXCEPTIONS; + glue(FP_UNPACK_RAW_, FS)(A, a); + glue(FP_UNPACK_RAW_, FS)(B, b); + glue(FP_CMP_, FS)(r, A, B, float_relation_unordered, (quiet ? 1 : 2)); + FP_HANDLE_EXCEPTIONS; + + return r; +} + +int glue(FLOATXX,_compare)(FLOATXX a, FLOATXX b, float_status *status) +{ + return compare_internal(a, b, status, false); +} + +int glue(FLOATXX,_compare_quiet)(FLOATXX a, FLOATXX b, float_status *status) +{ + return compare_internal(a, b, status, true); +} + +int glue(FLOATXX,_eq)(FLOATXX a, FLOATXX b, float_status *status) +{ + return compare_internal(a, b, status, false) == 0; +} + +int glue(FLOATXX,_le)(FLOATXX a, FLOATXX b, float_status *status) +{ + return compare_internal(a, b, status, false) <= 0; +} + +int glue(FLOATXX,_lt)(FLOATXX a, FLOATXX b, float_status *status) +{ + return compare_internal(a, b, status, false) < 0; +} + +int glue(FLOATXX,_unordered)(FLOATXX a, FLOATXX b, float_status *status) +{ + return compare_internal(a, b, status, false) == float_relation_unordered; +} + +int glue(FLOATXX,_eq_quiet)(FLOATXX a, FLOATXX b, float_status *status) +{ + return compare_internal(a, b, status, true) == 0; +} + +int glue(FLOATXX,_le_quiet)(FLOATXX a, FLOATXX b, float_status *status) +{ + return compare_internal(a, b, status, true) <= 0; +} + +int glue(FLOATXX,_lt_quiet)(FLOATXX a, FLOATXX b, float_status *status) +{ + return compare_internal(a, b, status, true) < 0; +} + +int glue(FLOATXX,_unordered_quiet)(FLOATXX a, FLOATXX b, float_status *status) +{ + return compare_internal(a, b, status, true) == float_relation_unordered; +} diff --git a/fpu/softfloat.c b/fpu/softfloat.c index 47b8c4815b..f75cd0bac4 100644 --- a/fpu/softfloat.c +++ b/fpu/softfloat.c @@ -1972,222 +1972,6 @@ float32 float32_log2(float32 a, float_status *status) return normalizeRoundAndPackFloat32(zSign, 0x85, zSig, status); } -/*---------------------------------------------------------------------------- -| Returns 1 if the single-precision floating-point value `a' is equal to -| the corresponding value `b', and 0 otherwise. The invalid exception is -| raised if either operand is a NaN. Otherwise, the comparison is performed -| according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -int float32_eq(float32 a, float32 b, float_status *status) -{ - uint32_t av, bv; - a = float32_squash_input_denormal(a, status); - b = float32_squash_input_denormal(b, status); - - if ( ( ( extractFloat32Exp( a ) == 0xFF ) && extractFloat32Frac( a ) ) - || ( ( extractFloat32Exp( b ) == 0xFF ) && extractFloat32Frac( b ) ) - ) { - float_raise(float_flag_invalid, status); - return 0; - } - av = float32_val(a); - bv = float32_val(b); - return ( av == bv ) || ( (uint32_t) ( ( av | bv )<<1 ) == 0 ); -} - -/*---------------------------------------------------------------------------- -| Returns 1 if the single-precision floating-point value `a' is less than -| or equal to the corresponding value `b', and 0 otherwise. The invalid -| exception is raised if either operand is a NaN. The comparison is performed -| according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -int float32_le(float32 a, float32 b, float_status *status) -{ - flag aSign, bSign; - uint32_t av, bv; - a = float32_squash_input_denormal(a, status); - b = float32_squash_input_denormal(b, status); - - if ( ( ( extractFloat32Exp( a ) == 0xFF ) && extractFloat32Frac( a ) ) - || ( ( extractFloat32Exp( b ) == 0xFF ) && extractFloat32Frac( b ) ) - ) { - float_raise(float_flag_invalid, status); - return 0; - } - aSign = extractFloat32Sign( a ); - bSign = extractFloat32Sign( b ); - av = float32_val(a); - bv = float32_val(b); - if ( aSign != bSign ) return aSign || ( (uint32_t) ( ( av | bv )<<1 ) == 0 ); - return ( av == bv ) || ( aSign ^ ( av < bv ) ); - -} - -/*---------------------------------------------------------------------------- -| Returns 1 if the single-precision floating-point value `a' is less than -| the corresponding value `b', and 0 otherwise. The invalid exception is -| raised if either operand is a NaN. The comparison is performed according -| to the IEC/IEEE Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -int float32_lt(float32 a, float32 b, float_status *status) -{ - flag aSign, bSign; - uint32_t av, bv; - a = float32_squash_input_denormal(a, status); - b = float32_squash_input_denormal(b, status); - - if ( ( ( extractFloat32Exp( a ) == 0xFF ) && extractFloat32Frac( a ) ) - || ( ( extractFloat32Exp( b ) == 0xFF ) && extractFloat32Frac( b ) ) - ) { - float_raise(float_flag_invalid, status); - return 0; - } - aSign = extractFloat32Sign( a ); - bSign = extractFloat32Sign( b ); - av = float32_val(a); - bv = float32_val(b); - if ( aSign != bSign ) return aSign && ( (uint32_t) ( ( av | bv )<<1 ) != 0 ); - return ( av != bv ) && ( aSign ^ ( av < bv ) ); - -} - -/*---------------------------------------------------------------------------- -| Returns 1 if the single-precision floating-point values `a' and `b' cannot -| be compared, and 0 otherwise. The invalid exception is raised if either -| operand is a NaN. The comparison is performed according to the IEC/IEEE -| Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -int float32_unordered(float32 a, float32 b, float_status *status) -{ - a = float32_squash_input_denormal(a, status); - b = float32_squash_input_denormal(b, status); - - if ( ( ( extractFloat32Exp( a ) == 0xFF ) && extractFloat32Frac( a ) ) - || ( ( extractFloat32Exp( b ) == 0xFF ) && extractFloat32Frac( b ) ) - ) { - float_raise(float_flag_invalid, status); - return 1; - } - return 0; -} - -/*---------------------------------------------------------------------------- -| Returns 1 if the single-precision floating-point value `a' is equal to -| the corresponding value `b', and 0 otherwise. Quiet NaNs do not cause an -| exception. The comparison is performed according to the IEC/IEEE Standard -| for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -int float32_eq_quiet(float32 a, float32 b, float_status *status) -{ - a = float32_squash_input_denormal(a, status); - b = float32_squash_input_denormal(b, status); - - if ( ( ( extractFloat32Exp( a ) == 0xFF ) && extractFloat32Frac( a ) ) - || ( ( extractFloat32Exp( b ) == 0xFF ) && extractFloat32Frac( b ) ) - ) { - if (float32_is_signaling_nan(a, status) - || float32_is_signaling_nan(b, status)) { - float_raise(float_flag_invalid, status); - } - return 0; - } - return ( float32_val(a) == float32_val(b) ) || - ( (uint32_t) ( ( float32_val(a) | float32_val(b) )<<1 ) == 0 ); -} - -/*---------------------------------------------------------------------------- -| Returns 1 if the single-precision floating-point value `a' is less than or -| equal to the corresponding value `b', and 0 otherwise. Quiet NaNs do not -| cause an exception. Otherwise, the comparison is performed according to the -| IEC/IEEE Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -int float32_le_quiet(float32 a, float32 b, float_status *status) -{ - flag aSign, bSign; - uint32_t av, bv; - a = float32_squash_input_denormal(a, status); - b = float32_squash_input_denormal(b, status); - - if ( ( ( extractFloat32Exp( a ) == 0xFF ) && extractFloat32Frac( a ) ) - || ( ( extractFloat32Exp( b ) == 0xFF ) && extractFloat32Frac( b ) ) - ) { - if (float32_is_signaling_nan(a, status) - || float32_is_signaling_nan(b, status)) { - float_raise(float_flag_invalid, status); - } - return 0; - } - aSign = extractFloat32Sign( a ); - bSign = extractFloat32Sign( b ); - av = float32_val(a); - bv = float32_val(b); - if ( aSign != bSign ) return aSign || ( (uint32_t) ( ( av | bv )<<1 ) == 0 ); - return ( av == bv ) || ( aSign ^ ( av < bv ) ); - -} - -/*---------------------------------------------------------------------------- -| Returns 1 if the single-precision floating-point value `a' is less than -| the corresponding value `b', and 0 otherwise. Quiet NaNs do not cause an -| exception. Otherwise, the comparison is performed according to the IEC/IEEE -| Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -int float32_lt_quiet(float32 a, float32 b, float_status *status) -{ - flag aSign, bSign; - uint32_t av, bv; - a = float32_squash_input_denormal(a, status); - b = float32_squash_input_denormal(b, status); - - if ( ( ( extractFloat32Exp( a ) == 0xFF ) && extractFloat32Frac( a ) ) - || ( ( extractFloat32Exp( b ) == 0xFF ) && extractFloat32Frac( b ) ) - ) { - if (float32_is_signaling_nan(a, status) - || float32_is_signaling_nan(b, status)) { - float_raise(float_flag_invalid, status); - } - return 0; - } - aSign = extractFloat32Sign( a ); - bSign = extractFloat32Sign( b ); - av = float32_val(a); - bv = float32_val(b); - if ( aSign != bSign ) return aSign && ( (uint32_t) ( ( av | bv )<<1 ) != 0 ); - return ( av != bv ) && ( aSign ^ ( av < bv ) ); - -} - -/*---------------------------------------------------------------------------- -| Returns 1 if the single-precision floating-point values `a' and `b' cannot -| be compared, and 0 otherwise. Quiet NaNs do not cause an exception. The -| comparison is performed according to the IEC/IEEE Standard for Binary -| Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -int float32_unordered_quiet(float32 a, float32 b, float_status *status) -{ - a = float32_squash_input_denormal(a, status); - b = float32_squash_input_denormal(b, status); - - if ( ( ( extractFloat32Exp( a ) == 0xFF ) && extractFloat32Frac( a ) ) - || ( ( extractFloat32Exp( b ) == 0xFF ) && extractFloat32Frac( b ) ) - ) { - if (float32_is_signaling_nan(a, status) - || float32_is_signaling_nan(b, status)) { - float_raise(float_flag_invalid, status); - } - return 1; - } - return 0; -} - /*---------------------------------------------------------------------------- | Returns the result of converting the double-precision floating-point value | `a' to the single-precision floating-point format. The conversion is @@ -3123,226 +2907,6 @@ float64 float64_log2(float64 a, float_status *status) return normalizeRoundAndPackFloat64(zSign, 0x408, zSig, status); } -/*---------------------------------------------------------------------------- -| Returns 1 if the double-precision floating-point value `a' is equal to the -| corresponding value `b', and 0 otherwise. The invalid exception is raised -| if either operand is a NaN. Otherwise, the comparison is performed -| according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -int float64_eq(float64 a, float64 b, float_status *status) -{ - uint64_t av, bv; - a = float64_squash_input_denormal(a, status); - b = float64_squash_input_denormal(b, status); - - if ( ( ( extractFloat64Exp( a ) == 0x7FF ) && extractFloat64Frac( a ) ) - || ( ( extractFloat64Exp( b ) == 0x7FF ) && extractFloat64Frac( b ) ) - ) { - float_raise(float_flag_invalid, status); - return 0; - } - av = float64_val(a); - bv = float64_val(b); - return ( av == bv ) || ( (uint64_t) ( ( av | bv )<<1 ) == 0 ); - -} - -/*---------------------------------------------------------------------------- -| Returns 1 if the double-precision floating-point value `a' is less than or -| equal to the corresponding value `b', and 0 otherwise. The invalid -| exception is raised if either operand is a NaN. The comparison is performed -| according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -int float64_le(float64 a, float64 b, float_status *status) -{ - flag aSign, bSign; - uint64_t av, bv; - a = float64_squash_input_denormal(a, status); - b = float64_squash_input_denormal(b, status); - - if ( ( ( extractFloat64Exp( a ) == 0x7FF ) && extractFloat64Frac( a ) ) - || ( ( extractFloat64Exp( b ) == 0x7FF ) && extractFloat64Frac( b ) ) - ) { - float_raise(float_flag_invalid, status); - return 0; - } - aSign = extractFloat64Sign( a ); - bSign = extractFloat64Sign( b ); - av = float64_val(a); - bv = float64_val(b); - if ( aSign != bSign ) return aSign || ( (uint64_t) ( ( av | bv )<<1 ) == 0 ); - return ( av == bv ) || ( aSign ^ ( av < bv ) ); - -} - -/*---------------------------------------------------------------------------- -| Returns 1 if the double-precision floating-point value `a' is less than -| the corresponding value `b', and 0 otherwise. The invalid exception is -| raised if either operand is a NaN. The comparison is performed according -| to the IEC/IEEE Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -int float64_lt(float64 a, float64 b, float_status *status) -{ - flag aSign, bSign; - uint64_t av, bv; - - a = float64_squash_input_denormal(a, status); - b = float64_squash_input_denormal(b, status); - if ( ( ( extractFloat64Exp( a ) == 0x7FF ) && extractFloat64Frac( a ) ) - || ( ( extractFloat64Exp( b ) == 0x7FF ) && extractFloat64Frac( b ) ) - ) { - float_raise(float_flag_invalid, status); - return 0; - } - aSign = extractFloat64Sign( a ); - bSign = extractFloat64Sign( b ); - av = float64_val(a); - bv = float64_val(b); - if ( aSign != bSign ) return aSign && ( (uint64_t) ( ( av | bv )<<1 ) != 0 ); - return ( av != bv ) && ( aSign ^ ( av < bv ) ); - -} - -/*---------------------------------------------------------------------------- -| Returns 1 if the double-precision floating-point values `a' and `b' cannot -| be compared, and 0 otherwise. The invalid exception is raised if either -| operand is a NaN. The comparison is performed according to the IEC/IEEE -| Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -int float64_unordered(float64 a, float64 b, float_status *status) -{ - a = float64_squash_input_denormal(a, status); - b = float64_squash_input_denormal(b, status); - - if ( ( ( extractFloat64Exp( a ) == 0x7FF ) && extractFloat64Frac( a ) ) - || ( ( extractFloat64Exp( b ) == 0x7FF ) && extractFloat64Frac( b ) ) - ) { - float_raise(float_flag_invalid, status); - return 1; - } - return 0; -} - -/*---------------------------------------------------------------------------- -| Returns 1 if the double-precision floating-point value `a' is equal to the -| corresponding value `b', and 0 otherwise. Quiet NaNs do not cause an -| exception.The comparison is performed according to the IEC/IEEE Standard -| for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -int float64_eq_quiet(float64 a, float64 b, float_status *status) -{ - uint64_t av, bv; - a = float64_squash_input_denormal(a, status); - b = float64_squash_input_denormal(b, status); - - if ( ( ( extractFloat64Exp( a ) == 0x7FF ) && extractFloat64Frac( a ) ) - || ( ( extractFloat64Exp( b ) == 0x7FF ) && extractFloat64Frac( b ) ) - ) { - if (float64_is_signaling_nan(a, status) - || float64_is_signaling_nan(b, status)) { - float_raise(float_flag_invalid, status); - } - return 0; - } - av = float64_val(a); - bv = float64_val(b); - return ( av == bv ) || ( (uint64_t) ( ( av | bv )<<1 ) == 0 ); - -} - -/*---------------------------------------------------------------------------- -| Returns 1 if the double-precision floating-point value `a' is less than or -| equal to the corresponding value `b', and 0 otherwise. Quiet NaNs do not -| cause an exception. Otherwise, the comparison is performed according to the -| IEC/IEEE Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -int float64_le_quiet(float64 a, float64 b, float_status *status) -{ - flag aSign, bSign; - uint64_t av, bv; - a = float64_squash_input_denormal(a, status); - b = float64_squash_input_denormal(b, status); - - if ( ( ( extractFloat64Exp( a ) == 0x7FF ) && extractFloat64Frac( a ) ) - || ( ( extractFloat64Exp( b ) == 0x7FF ) && extractFloat64Frac( b ) ) - ) { - if (float64_is_signaling_nan(a, status) - || float64_is_signaling_nan(b, status)) { - float_raise(float_flag_invalid, status); - } - return 0; - } - aSign = extractFloat64Sign( a ); - bSign = extractFloat64Sign( b ); - av = float64_val(a); - bv = float64_val(b); - if ( aSign != bSign ) return aSign || ( (uint64_t) ( ( av | bv )<<1 ) == 0 ); - return ( av == bv ) || ( aSign ^ ( av < bv ) ); - -} - -/*---------------------------------------------------------------------------- -| Returns 1 if the double-precision floating-point value `a' is less than -| the corresponding value `b', and 0 otherwise. Quiet NaNs do not cause an -| exception. Otherwise, the comparison is performed according to the IEC/IEEE -| Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -int float64_lt_quiet(float64 a, float64 b, float_status *status) -{ - flag aSign, bSign; - uint64_t av, bv; - a = float64_squash_input_denormal(a, status); - b = float64_squash_input_denormal(b, status); - - if ( ( ( extractFloat64Exp( a ) == 0x7FF ) && extractFloat64Frac( a ) ) - || ( ( extractFloat64Exp( b ) == 0x7FF ) && extractFloat64Frac( b ) ) - ) { - if (float64_is_signaling_nan(a, status) - || float64_is_signaling_nan(b, status)) { - float_raise(float_flag_invalid, status); - } - return 0; - } - aSign = extractFloat64Sign( a ); - bSign = extractFloat64Sign( b ); - av = float64_val(a); - bv = float64_val(b); - if ( aSign != bSign ) return aSign && ( (uint64_t) ( ( av | bv )<<1 ) != 0 ); - return ( av != bv ) && ( aSign ^ ( av < bv ) ); - -} - -/*---------------------------------------------------------------------------- -| Returns 1 if the double-precision floating-point values `a' and `b' cannot -| be compared, and 0 otherwise. Quiet NaNs do not cause an exception. The -| comparison is performed according to the IEC/IEEE Standard for Binary -| Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -int float64_unordered_quiet(float64 a, float64 b, float_status *status) -{ - a = float64_squash_input_denormal(a, status); - b = float64_squash_input_denormal(b, status); - - if ( ( ( extractFloat64Exp( a ) == 0x7FF ) && extractFloat64Frac( a ) ) - || ( ( extractFloat64Exp( b ) == 0x7FF ) && extractFloat64Frac( b ) ) - ) { - if (float64_is_signaling_nan(a, status) - || float64_is_signaling_nan(b, status)) { - float_raise(float_flag_invalid, status); - } - return 1; - } - return 0; -} - /*---------------------------------------------------------------------------- | Returns the result of converting the extended double-precision floating- | point value `a' to the 32-bit two's complement integer format. The @@ -4227,263 +3791,6 @@ floatx80 floatx80_sqrt(floatx80 a, float_status *status) 0, zExp, zSig0, zSig1, status); } -/*---------------------------------------------------------------------------- -| Returns 1 if the extended double-precision floating-point value `a' is equal -| to the corresponding value `b', and 0 otherwise. The invalid exception is -| raised if either operand is a NaN. Otherwise, the comparison is performed -| according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -int floatx80_eq(floatx80 a, floatx80 b, float_status *status) -{ - - if (floatx80_invalid_encoding(a) || floatx80_invalid_encoding(b) - || (extractFloatx80Exp(a) == 0x7FFF - && (uint64_t) (extractFloatx80Frac(a) << 1)) - || (extractFloatx80Exp(b) == 0x7FFF - && (uint64_t) (extractFloatx80Frac(b) << 1)) - ) { - float_raise(float_flag_invalid, status); - return 0; - } - return - ( a.low == b.low ) - && ( ( a.high == b.high ) - || ( ( a.low == 0 ) - && ( (uint16_t) ( ( a.high | b.high )<<1 ) == 0 ) ) - ); - -} - -/*---------------------------------------------------------------------------- -| Returns 1 if the extended double-precision floating-point value `a' is -| less than or equal to the corresponding value `b', and 0 otherwise. The -| invalid exception is raised if either operand is a NaN. The comparison is -| performed according to the IEC/IEEE Standard for Binary Floating-Point -| Arithmetic. -*----------------------------------------------------------------------------*/ - -int floatx80_le(floatx80 a, floatx80 b, float_status *status) -{ - flag aSign, bSign; - - if (floatx80_invalid_encoding(a) || floatx80_invalid_encoding(b) - || (extractFloatx80Exp(a) == 0x7FFF - && (uint64_t) (extractFloatx80Frac(a) << 1)) - || (extractFloatx80Exp(b) == 0x7FFF - && (uint64_t) (extractFloatx80Frac(b) << 1)) - ) { - float_raise(float_flag_invalid, status); - return 0; - } - aSign = extractFloatx80Sign( a ); - bSign = extractFloatx80Sign( b ); - if ( aSign != bSign ) { - return - aSign - || ( ( ( (uint16_t) ( ( a.high | b.high )<<1 ) ) | a.low | b.low ) - == 0 ); - } - return - aSign ? le128( b.high, b.low, a.high, a.low ) - : le128( a.high, a.low, b.high, b.low ); - -} - -/*---------------------------------------------------------------------------- -| Returns 1 if the extended double-precision floating-point value `a' is -| less than the corresponding value `b', and 0 otherwise. The invalid -| exception is raised if either operand is a NaN. The comparison is performed -| according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -int floatx80_lt(floatx80 a, floatx80 b, float_status *status) -{ - flag aSign, bSign; - - if (floatx80_invalid_encoding(a) || floatx80_invalid_encoding(b) - || (extractFloatx80Exp(a) == 0x7FFF - && (uint64_t) (extractFloatx80Frac(a) << 1)) - || (extractFloatx80Exp(b) == 0x7FFF - && (uint64_t) (extractFloatx80Frac(b) << 1)) - ) { - float_raise(float_flag_invalid, status); - return 0; - } - aSign = extractFloatx80Sign( a ); - bSign = extractFloatx80Sign( b ); - if ( aSign != bSign ) { - return - aSign - && ( ( ( (uint16_t) ( ( a.high | b.high )<<1 ) ) | a.low | b.low ) - != 0 ); - } - return - aSign ? lt128( b.high, b.low, a.high, a.low ) - : lt128( a.high, a.low, b.high, b.low ); - -} - -/*---------------------------------------------------------------------------- -| Returns 1 if the extended double-precision floating-point values `a' and `b' -| cannot be compared, and 0 otherwise. The invalid exception is raised if -| either operand is a NaN. The comparison is performed according to the -| IEC/IEEE Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ -int floatx80_unordered(floatx80 a, floatx80 b, float_status *status) -{ - if (floatx80_invalid_encoding(a) || floatx80_invalid_encoding(b) - || (extractFloatx80Exp(a) == 0x7FFF - && (uint64_t) (extractFloatx80Frac(a) << 1)) - || (extractFloatx80Exp(b) == 0x7FFF - && (uint64_t) (extractFloatx80Frac(b) << 1)) - ) { - float_raise(float_flag_invalid, status); - return 1; - } - return 0; -} - -/*---------------------------------------------------------------------------- -| Returns 1 if the extended double-precision floating-point value `a' is -| equal to the corresponding value `b', and 0 otherwise. Quiet NaNs do not -| cause an exception. The comparison is performed according to the IEC/IEEE -| Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -int floatx80_eq_quiet(floatx80 a, floatx80 b, float_status *status) -{ - - if (floatx80_invalid_encoding(a) || floatx80_invalid_encoding(b)) { - float_raise(float_flag_invalid, status); - return 0; - } - if ( ( ( extractFloatx80Exp( a ) == 0x7FFF ) - && (uint64_t) ( extractFloatx80Frac( a )<<1 ) ) - || ( ( extractFloatx80Exp( b ) == 0x7FFF ) - && (uint64_t) ( extractFloatx80Frac( b )<<1 ) ) - ) { - if (floatx80_is_signaling_nan(a, status) - || floatx80_is_signaling_nan(b, status)) { - float_raise(float_flag_invalid, status); - } - return 0; - } - return - ( a.low == b.low ) - && ( ( a.high == b.high ) - || ( ( a.low == 0 ) - && ( (uint16_t) ( ( a.high | b.high )<<1 ) == 0 ) ) - ); - -} - -/*---------------------------------------------------------------------------- -| Returns 1 if the extended double-precision floating-point value `a' is less -| than or equal to the corresponding value `b', and 0 otherwise. Quiet NaNs -| do not cause an exception. Otherwise, the comparison is performed according -| to the IEC/IEEE Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -int floatx80_le_quiet(floatx80 a, floatx80 b, float_status *status) -{ - flag aSign, bSign; - - if (floatx80_invalid_encoding(a) || floatx80_invalid_encoding(b)) { - float_raise(float_flag_invalid, status); - return 0; - } - if ( ( ( extractFloatx80Exp( a ) == 0x7FFF ) - && (uint64_t) ( extractFloatx80Frac( a )<<1 ) ) - || ( ( extractFloatx80Exp( b ) == 0x7FFF ) - && (uint64_t) ( extractFloatx80Frac( b )<<1 ) ) - ) { - if (floatx80_is_signaling_nan(a, status) - || floatx80_is_signaling_nan(b, status)) { - float_raise(float_flag_invalid, status); - } - return 0; - } - aSign = extractFloatx80Sign( a ); - bSign = extractFloatx80Sign( b ); - if ( aSign != bSign ) { - return - aSign - || ( ( ( (uint16_t) ( ( a.high | b.high )<<1 ) ) | a.low | b.low ) - == 0 ); - } - return - aSign ? le128( b.high, b.low, a.high, a.low ) - : le128( a.high, a.low, b.high, b.low ); - -} - -/*---------------------------------------------------------------------------- -| Returns 1 if the extended double-precision floating-point value `a' is less -| than the corresponding value `b', and 0 otherwise. Quiet NaNs do not cause -| an exception. Otherwise, the comparison is performed according to the -| IEC/IEEE Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -int floatx80_lt_quiet(floatx80 a, floatx80 b, float_status *status) -{ - flag aSign, bSign; - - if (floatx80_invalid_encoding(a) || floatx80_invalid_encoding(b)) { - float_raise(float_flag_invalid, status); - return 0; - } - if ( ( ( extractFloatx80Exp( a ) == 0x7FFF ) - && (uint64_t) ( extractFloatx80Frac( a )<<1 ) ) - || ( ( extractFloatx80Exp( b ) == 0x7FFF ) - && (uint64_t) ( extractFloatx80Frac( b )<<1 ) ) - ) { - if (floatx80_is_signaling_nan(a, status) - || floatx80_is_signaling_nan(b, status)) { - float_raise(float_flag_invalid, status); - } - return 0; - } - aSign = extractFloatx80Sign( a ); - bSign = extractFloatx80Sign( b ); - if ( aSign != bSign ) { - return - aSign - && ( ( ( (uint16_t) ( ( a.high | b.high )<<1 ) ) | a.low | b.low ) - != 0 ); - } - return - aSign ? lt128( b.high, b.low, a.high, a.low ) - : lt128( a.high, a.low, b.high, b.low ); - -} - -/*---------------------------------------------------------------------------- -| Returns 1 if the extended double-precision floating-point values `a' and `b' -| cannot be compared, and 0 otherwise. Quiet NaNs do not cause an exception. -| The comparison is performed according to the IEC/IEEE Standard for Binary -| Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ -int floatx80_unordered_quiet(floatx80 a, floatx80 b, float_status *status) -{ - if (floatx80_invalid_encoding(a) || floatx80_invalid_encoding(b)) { - float_raise(float_flag_invalid, status); - return 1; - } - if ( ( ( extractFloatx80Exp( a ) == 0x7FFF ) - && (uint64_t) ( extractFloatx80Frac( a )<<1 ) ) - || ( ( extractFloatx80Exp( b ) == 0x7FFF ) - && (uint64_t) ( extractFloatx80Frac( b )<<1 ) ) - ) { - if (floatx80_is_signaling_nan(a, status) - || floatx80_is_signaling_nan(b, status)) { - float_raise(float_flag_invalid, status); - } - return 1; - } - return 0; -} - /*---------------------------------------------------------------------------- | Returns the result of converting the quadruple-precision floating-point | value `a' to the single-precision floating-point format. The conversion @@ -4900,298 +4207,6 @@ float128 float128_sqrt(float128 a, float_status *status) } -/*---------------------------------------------------------------------------- -| Returns 1 if the quadruple-precision floating-point value `a' is equal to -| the corresponding value `b', and 0 otherwise. The invalid exception is -| raised if either operand is a NaN. Otherwise, the comparison is performed -| according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -int float128_eq(float128 a, float128 b, float_status *status) -{ - - if ( ( ( extractFloat128Exp( a ) == 0x7FFF ) - && ( extractFloat128Frac0( a ) | extractFloat128Frac1( a ) ) ) - || ( ( extractFloat128Exp( b ) == 0x7FFF ) - && ( extractFloat128Frac0( b ) | extractFloat128Frac1( b ) ) ) - ) { - float_raise(float_flag_invalid, status); - return 0; - } - return - ( a.low == b.low ) - && ( ( a.high == b.high ) - || ( ( a.low == 0 ) - && ( (uint64_t) ( ( a.high | b.high )<<1 ) == 0 ) ) - ); - -} - -/*---------------------------------------------------------------------------- -| Returns 1 if the quadruple-precision floating-point value `a' is less than -| or equal to the corresponding value `b', and 0 otherwise. The invalid -| exception is raised if either operand is a NaN. The comparison is performed -| according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -int float128_le(float128 a, float128 b, float_status *status) -{ - flag aSign, bSign; - - if ( ( ( extractFloat128Exp( a ) == 0x7FFF ) - && ( extractFloat128Frac0( a ) | extractFloat128Frac1( a ) ) ) - || ( ( extractFloat128Exp( b ) == 0x7FFF ) - && ( extractFloat128Frac0( b ) | extractFloat128Frac1( b ) ) ) - ) { - float_raise(float_flag_invalid, status); - return 0; - } - aSign = extractFloat128Sign( a ); - bSign = extractFloat128Sign( b ); - if ( aSign != bSign ) { - return - aSign - || ( ( ( (uint64_t) ( ( a.high | b.high )<<1 ) ) | a.low | b.low ) - == 0 ); - } - return - aSign ? le128( b.high, b.low, a.high, a.low ) - : le128( a.high, a.low, b.high, b.low ); - -} - -/*---------------------------------------------------------------------------- -| Returns 1 if the quadruple-precision floating-point value `a' is less than -| the corresponding value `b', and 0 otherwise. The invalid exception is -| raised if either operand is a NaN. The comparison is performed according -| to the IEC/IEEE Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -int float128_lt(float128 a, float128 b, float_status *status) -{ - flag aSign, bSign; - - if ( ( ( extractFloat128Exp( a ) == 0x7FFF ) - && ( extractFloat128Frac0( a ) | extractFloat128Frac1( a ) ) ) - || ( ( extractFloat128Exp( b ) == 0x7FFF ) - && ( extractFloat128Frac0( b ) | extractFloat128Frac1( b ) ) ) - ) { - float_raise(float_flag_invalid, status); - return 0; - } - aSign = extractFloat128Sign( a ); - bSign = extractFloat128Sign( b ); - if ( aSign != bSign ) { - return - aSign - && ( ( ( (uint64_t) ( ( a.high | b.high )<<1 ) ) | a.low | b.low ) - != 0 ); - } - return - aSign ? lt128( b.high, b.low, a.high, a.low ) - : lt128( a.high, a.low, b.high, b.low ); - -} - -/*---------------------------------------------------------------------------- -| Returns 1 if the quadruple-precision floating-point values `a' and `b' cannot -| be compared, and 0 otherwise. The invalid exception is raised if either -| operand is a NaN. The comparison is performed according to the IEC/IEEE -| Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -int float128_unordered(float128 a, float128 b, float_status *status) -{ - if ( ( ( extractFloat128Exp( a ) == 0x7FFF ) - && ( extractFloat128Frac0( a ) | extractFloat128Frac1( a ) ) ) - || ( ( extractFloat128Exp( b ) == 0x7FFF ) - && ( extractFloat128Frac0( b ) | extractFloat128Frac1( b ) ) ) - ) { - float_raise(float_flag_invalid, status); - return 1; - } - return 0; -} - -/*---------------------------------------------------------------------------- -| Returns 1 if the quadruple-precision floating-point value `a' is equal to -| the corresponding value `b', and 0 otherwise. Quiet NaNs do not cause an -| exception. The comparison is performed according to the IEC/IEEE Standard -| for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -int float128_eq_quiet(float128 a, float128 b, float_status *status) -{ - - if ( ( ( extractFloat128Exp( a ) == 0x7FFF ) - && ( extractFloat128Frac0( a ) | extractFloat128Frac1( a ) ) ) - || ( ( extractFloat128Exp( b ) == 0x7FFF ) - && ( extractFloat128Frac0( b ) | extractFloat128Frac1( b ) ) ) - ) { - if (float128_is_signaling_nan(a, status) - || float128_is_signaling_nan(b, status)) { - float_raise(float_flag_invalid, status); - } - return 0; - } - return - ( a.low == b.low ) - && ( ( a.high == b.high ) - || ( ( a.low == 0 ) - && ( (uint64_t) ( ( a.high | b.high )<<1 ) == 0 ) ) - ); - -} - -/*---------------------------------------------------------------------------- -| Returns 1 if the quadruple-precision floating-point value `a' is less than -| or equal to the corresponding value `b', and 0 otherwise. Quiet NaNs do not -| cause an exception. Otherwise, the comparison is performed according to the -| IEC/IEEE Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -int float128_le_quiet(float128 a, float128 b, float_status *status) -{ - flag aSign, bSign; - - if ( ( ( extractFloat128Exp( a ) == 0x7FFF ) - && ( extractFloat128Frac0( a ) | extractFloat128Frac1( a ) ) ) - || ( ( extractFloat128Exp( b ) == 0x7FFF ) - && ( extractFloat128Frac0( b ) | extractFloat128Frac1( b ) ) ) - ) { - if (float128_is_signaling_nan(a, status) - || float128_is_signaling_nan(b, status)) { - float_raise(float_flag_invalid, status); - } - return 0; - } - aSign = extractFloat128Sign( a ); - bSign = extractFloat128Sign( b ); - if ( aSign != bSign ) { - return - aSign - || ( ( ( (uint64_t) ( ( a.high | b.high )<<1 ) ) | a.low | b.low ) - == 0 ); - } - return - aSign ? le128( b.high, b.low, a.high, a.low ) - : le128( a.high, a.low, b.high, b.low ); - -} - -/*---------------------------------------------------------------------------- -| Returns 1 if the quadruple-precision floating-point value `a' is less than -| the corresponding value `b', and 0 otherwise. Quiet NaNs do not cause an -| exception. Otherwise, the comparison is performed according to the IEC/IEEE -| Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -int float128_lt_quiet(float128 a, float128 b, float_status *status) -{ - flag aSign, bSign; - - if ( ( ( extractFloat128Exp( a ) == 0x7FFF ) - && ( extractFloat128Frac0( a ) | extractFloat128Frac1( a ) ) ) - || ( ( extractFloat128Exp( b ) == 0x7FFF ) - && ( extractFloat128Frac0( b ) | extractFloat128Frac1( b ) ) ) - ) { - if (float128_is_signaling_nan(a, status) - || float128_is_signaling_nan(b, status)) { - float_raise(float_flag_invalid, status); - } - return 0; - } - aSign = extractFloat128Sign( a ); - bSign = extractFloat128Sign( b ); - if ( aSign != bSign ) { - return - aSign - && ( ( ( (uint64_t) ( ( a.high | b.high )<<1 ) ) | a.low | b.low ) - != 0 ); - } - return - aSign ? lt128( b.high, b.low, a.high, a.low ) - : lt128( a.high, a.low, b.high, b.low ); - -} - -/*---------------------------------------------------------------------------- -| Returns 1 if the quadruple-precision floating-point values `a' and `b' cannot -| be compared, and 0 otherwise. Quiet NaNs do not cause an exception. The -| comparison is performed according to the IEC/IEEE Standard for Binary -| Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -int float128_unordered_quiet(float128 a, float128 b, float_status *status) -{ - if ( ( ( extractFloat128Exp( a ) == 0x7FFF ) - && ( extractFloat128Frac0( a ) | extractFloat128Frac1( a ) ) ) - || ( ( extractFloat128Exp( b ) == 0x7FFF ) - && ( extractFloat128Frac0( b ) | extractFloat128Frac1( b ) ) ) - ) { - if (float128_is_signaling_nan(a, status) - || float128_is_signaling_nan(b, status)) { - float_raise(float_flag_invalid, status); - } - return 1; - } - return 0; -} - -#define COMPARE(s, nan_exp) \ -static inline int float ## s ## _compare_internal(float ## s a, float ## s b,\ - int is_quiet, float_status *status) \ -{ \ - flag aSign, bSign; \ - uint ## s ## _t av, bv; \ - a = float ## s ## _squash_input_denormal(a, status); \ - b = float ## s ## _squash_input_denormal(b, status); \ - \ - if (( ( extractFloat ## s ## Exp( a ) == nan_exp ) && \ - extractFloat ## s ## Frac( a ) ) || \ - ( ( extractFloat ## s ## Exp( b ) == nan_exp ) && \ - extractFloat ## s ## Frac( b ) )) { \ - if (!is_quiet || \ - float ## s ## _is_signaling_nan(a, status) || \ - float ## s ## _is_signaling_nan(b, status)) { \ - float_raise(float_flag_invalid, status); \ - } \ - return float_relation_unordered; \ - } \ - aSign = extractFloat ## s ## Sign( a ); \ - bSign = extractFloat ## s ## Sign( b ); \ - av = float ## s ## _val(a); \ - bv = float ## s ## _val(b); \ - if ( aSign != bSign ) { \ - if ( (uint ## s ## _t) ( ( av | bv )<<1 ) == 0 ) { \ - /* zero case */ \ - return float_relation_equal; \ - } else { \ - return 1 - (2 * aSign); \ - } \ - } else { \ - if (av == bv) { \ - return float_relation_equal; \ - } else { \ - return 1 - 2 * (aSign ^ ( av < bv )); \ - } \ - } \ -} \ - \ -int float ## s ## _compare(float ## s a, float ## s b, float_status *status) \ -{ \ - return float ## s ## _compare_internal(a, b, 0, status); \ -} \ - \ -int float ## s ## _compare_quiet(float ## s a, float ## s b, \ - float_status *status) \ -{ \ - return float ## s ## _compare_internal(a, b, 1, status); \ -} - -COMPARE(32, 0xff) -COMPARE(64, 0x7ff) - static inline int floatx80_compare_internal(floatx80 a, floatx80 b, int is_quiet, float_status *status) { @@ -5242,48 +4257,46 @@ int floatx80_compare_quiet(floatx80 a, floatx80 b, float_status *status) return floatx80_compare_internal(a, b, 1, status); } -static inline int float128_compare_internal(float128 a, float128 b, - int is_quiet, float_status *status) +int floatx80_eq(floatx80 a, floatx80 b, float_status *status) { - flag aSign, bSign; + return floatx80_compare_internal(a, b, 0, status) == 0; +} - if (( ( extractFloat128Exp( a ) == 0x7fff ) && - ( extractFloat128Frac0( a ) | extractFloat128Frac1( a ) ) ) || - ( ( extractFloat128Exp( b ) == 0x7fff ) && - ( extractFloat128Frac0( b ) | extractFloat128Frac1( b ) ) )) { - if (!is_quiet || - float128_is_signaling_nan(a, status) || - float128_is_signaling_nan(b, status)) { - float_raise(float_flag_invalid, status); - } - return float_relation_unordered; - } - aSign = extractFloat128Sign( a ); - bSign = extractFloat128Sign( b ); - if ( aSign != bSign ) { - if ( ( ( ( a.high | b.high )<<1 ) | a.low | b.low ) == 0 ) { - /* zero case */ - return float_relation_equal; - } else { - return 1 - (2 * aSign); - } - } else { - if (a.low == b.low && a.high == b.high) { - return float_relation_equal; - } else { - return 1 - 2 * (aSign ^ ( lt128( a.high, a.low, b.high, b.low ) )); - } - } +int floatx80_le(floatx80 a, floatx80 b, float_status *status) +{ + return floatx80_compare_internal(a, b, 0, status) <= 0; } -int float128_compare(float128 a, float128 b, float_status *status) +int floatx80_lt(floatx80 a, floatx80 b, float_status *status) +{ + return floatx80_compare_internal(a, b, 0, status) < 0; +} + +int floatx80_unordered(floatx80 a, floatx80 b, float_status *status) +{ + return floatx80_compare_internal(a, b, 0, status) + == float_relation_unordered; +} + +int floatx80_eq_quiet(floatx80 a, floatx80 b, float_status *status) { - return float128_compare_internal(a, b, 0, status); + return floatx80_compare_internal(a, b, 1, status) == 0; } -int float128_compare_quiet(float128 a, float128 b, float_status *status) +int floatx80_le_quiet(floatx80 a, floatx80 b, float_status *status) +{ + return floatx80_compare_internal(a, b, 1, status) <= 0; +} + +int floatx80_lt_quiet(floatx80 a, floatx80 b, float_status *status) +{ + return floatx80_compare_internal(a, b, 1, status) < 0; +} + +int floatx80_unordered_quiet(floatx80 a, floatx80 b, float_status *status) { - return float128_compare_internal(a, b, 1, status); + return floatx80_compare_internal(a, b, 1, status) + == float_relation_unordered; } /* min() and max() functions. These can't be implemented as From patchwork Sun Feb 4 04:11:31 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Richard Henderson X-Patchwork-Id: 126802 Delivered-To: patch@linaro.org Received: by 10.46.124.24 with SMTP id x24csp925651ljc; Sat, 3 Feb 2018 20:18:09 -0800 (PST) X-Google-Smtp-Source: AH8x224qcs0y5MNwBmFM+y9PrbQNwYR89bKJTdlahv4PF06fWBRS/OSdg8tC8Osa5QDKH9FhyhDU X-Received: by 10.13.251.6 with SMTP id l6mr29243473ywf.323.1517717889423; Sat, 03 Feb 2018 20:18:09 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1517717889; cv=none; d=google.com; s=arc-20160816; b=QyuvpFN71Az9pgwaVcat+TKz+lPTmQHzpWwIRKFhpjoI8CtzmUU3x3QhOwbV4fVZ1e sXMzUrS1W5HA+mNM+7+ux8WrE9ISRri3sxjSVfxl54QflVKOOEyeZLKP1Wb2YQUAFFa9 1NH9rpcYl+3oQSLmlMG9lU5630GYzSvVgFn+T0xj0FmrAd0eP5UDRvsLgdgmFdgDqilj MEgp0OrHRJ7wGtAZKfPT6ITNpJZDJZEG1fLN3CpzJSgRwUwIijmUAr/xeO/oXub2kbKl ngD9J8/b6LvGcN8NLdUa+QC8TdOWAlqBqelqUQt4bVxLsQlw0XdLV9G0xzbAzECdwPF3 an8w== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=sender:errors-to:cc:list-subscribe:list-help:list-post:list-archive :list-unsubscribe:list-id:precedence:subject:references:in-reply-to :message-id:date:to:from:dkim-signature:arc-authentication-results; bh=Af/PXTq+IgzRg9HgEw7D2//efNwqImJJDPE3gWEjVgc=; b=UlWcwzJhLYkGyDK3SwBl+rEw19lL6wDexTqRCalAImoJTsFN74wmEPu1/hs7WyD5Wm cPOIPGHuvlavJ8xhrOIk6KVBilKFEeczpHmFzWK/+gwk8YE36FtjQVT/Fd9uCQa/yLs1 CwG8zkc+vB7d2L8LxJGPRD7gBNkUK2Uh/YEOHU0AeGZVLSynplDgvvD0YomgndrpQwSG XstsRhe9TH6HvYqGJYdoqgnSzzn0aDjz2uaPnJ1Fx2HWXptWuCiDo2IE22KnjYpa5jRF VEq66S6fHe80x/JH8w2KdmL1awI8zwzuT+8P3eXvVX/Q8d8VhAsuVy0xfgTaf9I+67WM dwSQ== ARC-Authentication-Results: i=1; mx.google.com; dkim=fail header.i=@linaro.org header.s=google header.b=E+XtDy52; spf=pass (google.com: domain of qemu-devel-bounces+patch=linaro.org@nongnu.org designates 2001:4830:134:3::11 as permitted sender) smtp.mailfrom=qemu-devel-bounces+patch=linaro.org@nongnu.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=linaro.org Return-Path: Received: from lists.gnu.org (lists.gnu.org. [2001:4830:134:3::11]) by mx.google.com with ESMTPS id f1si1018121ywd.449.2018.02.03.20.18.09 for (version=TLS1 cipher=AES128-SHA bits=128/128); Sat, 03 Feb 2018 20:18:09 -0800 (PST) Received-SPF: pass (google.com: domain of qemu-devel-bounces+patch=linaro.org@nongnu.org designates 2001:4830:134:3::11 as permitted sender) client-ip=2001:4830:134:3::11; Authentication-Results: mx.google.com; dkim=fail header.i=@linaro.org header.s=google header.b=E+XtDy52; spf=pass (google.com: domain of qemu-devel-bounces+patch=linaro.org@nongnu.org designates 2001:4830:134:3::11 as permitted sender) smtp.mailfrom=qemu-devel-bounces+patch=linaro.org@nongnu.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=linaro.org Received: from localhost ([::1]:58275 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1eiBkm-0001OU-Lv for patch@linaro.org; Sat, 03 Feb 2018 23:18:08 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:47421) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1eiBf0-0004rr-Nm for qemu-devel@nongnu.org; Sat, 03 Feb 2018 23:12:12 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1eiBey-00053d-QA for qemu-devel@nongnu.org; Sat, 03 Feb 2018 23:12:10 -0500 Received: from mail-pg0-x243.google.com ([2607:f8b0:400e:c05::243]:46162) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1eiBey-00052K-Fq for qemu-devel@nongnu.org; Sat, 03 Feb 2018 23:12:08 -0500 Received: by mail-pg0-x243.google.com with SMTP id s9so15973632pgq.13 for ; Sat, 03 Feb 2018 20:12:08 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=Af/PXTq+IgzRg9HgEw7D2//efNwqImJJDPE3gWEjVgc=; b=E+XtDy52dwMvOBaq2B5p7LGv4uCHx8LsTtabC0PpYAniaqkMQMg2xsSIj4X0cnAbPt DBXBBZlhXZZFzhhiRdaAPUuVe5tF9tTm0umL2+/RTNWDaqZlRhhZcbra1yk+19kz1TU3 4aW8kYzWXgF4IwgLH9C1lPMgSO/8s7qwrnsbQ= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=Af/PXTq+IgzRg9HgEw7D2//efNwqImJJDPE3gWEjVgc=; b=Cevx6ll+FgD9ONhyggi30y3LExOAyY2AtJOIZzeeL1s3TK/e3IMekAsoggSZHryp0M SKpEZfUIM6OBHInpKlgc+3KgznIfbERnnx4NK3r36xXX7DFEj0PBjinbBxrQJ4V6bXw9 U1py56X0APjQqwqNvpCFKDuMqBh/4wKcuUO3w6mNCvOZGpOJRQVB8gxRpbSE9UTEOgI0 d8bfJqVh4vxyKW/XMPhmGP3kAcgs2xIxRZriJxSvb1PPcQdxuUJsA5wZOK//9QcrL4ZR t/sDk2BN14EQm8NQqo1To0R92BoWIoxXFK+tlkyVLFhqGx5XYoTEMrQf3hiMMez8Mz5t go4A== X-Gm-Message-State: AKwxytfvgYVPSOK1w47E2uikC/vbPNWW0+ZihE5ZOTGeXOF7rNRHaOi6 KaCTrEgXT+1OhmS3Wy3pe2x+TRmhS04= X-Received: by 10.99.110.10 with SMTP id j10mr17972686pgc.72.1517717527216; Sat, 03 Feb 2018 20:12:07 -0800 (PST) Received: from cloudburst.twiddle.net (174-21-6-47.tukw.qwest.net. [174.21.6.47]) by smtp.gmail.com with ESMTPSA id k3sm1399425pgr.12.2018.02.03.20.12.05 (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Sat, 03 Feb 2018 20:12:06 -0800 (PST) From: Richard Henderson To: qemu-devel@nongnu.org Date: Sat, 3 Feb 2018 20:11:31 -0800 Message-Id: <20180204041136.17525-20-richard.henderson@linaro.org> X-Mailer: git-send-email 2.14.3 In-Reply-To: <20180204041136.17525-1-richard.henderson@linaro.org> References: <20180204041136.17525-1-richard.henderson@linaro.org> X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 2607:f8b0:400e:c05::243 Subject: [Qemu-devel] [PATCH 19/24] fpu: Implement min/max with soft-fp.h X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: peter.maydell@linaro.org, cota@braap.org, alex.bennee@linaro.org, hsp.cat7@gmail.com Errors-To: qemu-devel-bounces+patch=linaro.org@nongnu.org Sender: "Qemu-devel" Add routines for float16 and float128. Signed-off-by: Richard Henderson --- include/fpu/softfloat.h | 12 ++++++ fpu/floatxx.inc.c | 89 ++++++++++++++++++++++++++++++++++++++++ fpu/softfloat.c | 107 ------------------------------------------------ 3 files changed, 101 insertions(+), 107 deletions(-) -- 2.14.3 diff --git a/include/fpu/softfloat.h b/include/fpu/softfloat.h index 80df716a55..95590d8420 100644 --- a/include/fpu/softfloat.h +++ b/include/fpu/softfloat.h @@ -260,6 +260,12 @@ int float16_lt_quiet(float16, float16, float_status *status); int float16_unordered_quiet(float16, float16, float_status *status); int float16_compare(float16, float16, float_status *status); int float16_compare_quiet(float16, float16, float_status *status); +float16 float16_min(float16, float16, float_status *status); +float16 float16_max(float16, float16, float_status *status); +float16 float16_minnum(float16, float16, float_status *status); +float16 float16_maxnum(float16, float16, float_status *status); +float16 float16_minnummag(float16, float16, float_status *status); +float16 float16_maxnummag(float16, float16, float_status *status); int float16_is_quiet_nan(float16, float_status *status); int float16_is_signaling_nan(float16, float_status *status); @@ -682,6 +688,12 @@ int float128_lt_quiet(float128, float128, float_status *status); int float128_unordered_quiet(float128, float128, float_status *status); int float128_compare(float128, float128, float_status *status); int float128_compare_quiet(float128, float128, float_status *status); +float128 float128_min(float128, float128, float_status *status); +float128 float128_max(float128, float128, float_status *status); +float128 float128_minnum(float128, float128, float_status *status); +float128 float128_maxnum(float128, float128, float_status *status); +float128 float128_minnummag(float128, float128, float_status *status); +float128 float128_maxnummag(float128, float128, float_status *status); int float128_is_quiet_nan(float128, float_status *status); int float128_is_signaling_nan(float128, float_status *status); float128 float128_maybe_silence_nan(float128, float_status *status); diff --git a/fpu/floatxx.inc.c b/fpu/floatxx.inc.c index db49423723..0b6b8b4fd3 100644 --- a/fpu/floatxx.inc.c +++ b/fpu/floatxx.inc.c @@ -26,6 +26,10 @@ (X##_e == _FP_EXPMAX_##fs && !_FP_FRAC_ZEROP_##wc (X)) #define FP_ISNAN(fs, wc, X) \ _FP_ISNAN(fs, wc, X) +#define FP_CHOOSENAN(fs, wc, R, A, B, OP) \ + _FP_CHOOSENAN(fs, wc, R, A, B, OP) +#define FP_SETQNAN(fs, wc, X) \ + _FP_SETQNAN(fs, wc, X) #define FP_ADD_INTERNAL(fs, wc, R, A, B, OP) \ _FP_ADD_INTERNAL(fs, wc, R, A, B, '-') @@ -263,3 +267,88 @@ int glue(FLOATXX,_unordered_quiet)(FLOATXX a, FLOATXX b, float_status *status) { return compare_internal(a, b, status, true) == float_relation_unordered; } + +#define MINMAX_MAX 0 +#define MINMAX_MIN 1 +#define MINMAX_IEEE 2 +#define MINMAX_MAG 4 + +static FLOATXX minmax_internal(FLOATXX a, FLOATXX b, + float_status *status, int flags) +{ + FP_DECL_EX; + glue(FP_DECL_, FS)(A); + glue(FP_DECL_, FS)(B); + bool save_A_s; + int cmp; + + FP_INIT_EXCEPTIONS; + glue(FP_UNPACK_RAW_, FS)(A, a); + glue(FP_UNPACK_RAW_, FS)(B, b); + + /* When comparing magnitudes, squish the signs. */ + save_A_s = A_s; + if (flags & MINMAX_MAG) { + A_s = B_s = 0; + } + + glue(FP_CMP_, FS)(cmp, A, B, float_relation_unordered, 1); + FP_HANDLE_EXCEPTIONS; + + if (unlikely(cmp == float_relation_unordered)) { + glue(FP_DECL_, FS)(R); + FLOATXX r; + + if (flags & MINMAX_IEEE) { + if (glue(FP_ISSIGNAN_, FS)(A) || glue(FP_ISSIGNAN_, FS)(B)) { + /* fall through to FP_CHOOSENAN */ + } else if (!FP_ISNAN(FS, WC, A)) { + return a; + } else if (!FP_ISNAN(FS, WC, B)) { + return b; + } + } + + FP_CHOOSENAN(FS, WC, R, A, B, 'm'); + FP_SETQNAN(FS, WC, R); + glue(FP_PACK_RAW_, FS)(r, R); + return r; + } + + /* Specially handle min(+0.0, -0.0) = -0.0, which compare as equal. */ + cmp = (cmp == 0 ? save_A_s : cmp < 0); + cmp ^= flags & MINMAX_MIN; + return cmp ? b : a; +} + +FLOATXX glue(FLOATXX,_max)(FLOATXX a, FLOATXX b, float_status *status) +{ + return minmax_internal(a, b, status, MINMAX_MAX); +} + +FLOATXX glue(FLOATXX,_min)(FLOATXX a, FLOATXX b, float_status *status) +{ + return minmax_internal(a, b, status, MINMAX_MIN); +} + +FLOATXX glue(FLOATXX,_maxnum)(FLOATXX a, FLOATXX b, float_status *status) +{ + return minmax_internal(a, b, status, MINMAX_MAX | MINMAX_IEEE); +} + +FLOATXX glue(FLOATXX,_minnum)(FLOATXX a, FLOATXX b, float_status *status) +{ + return minmax_internal(a, b, status, MINMAX_MIN | MINMAX_IEEE); +} + +FLOATXX glue(FLOATXX,_maxnummag)(FLOATXX a, FLOATXX b, float_status *status) +{ + return minmax_internal(a, b, status, + MINMAX_MAX | MINMAX_IEEE | MINMAX_MAG); +} + +FLOATXX glue(FLOATXX,_minnummag)(FLOATXX a, FLOATXX b, float_status *status) +{ + return minmax_internal(a, b, status, + MINMAX_MIN | MINMAX_IEEE | MINMAX_MAG); +} diff --git a/fpu/softfloat.c b/fpu/softfloat.c index f75cd0bac4..68dfb464d5 100644 --- a/fpu/softfloat.c +++ b/fpu/softfloat.c @@ -4299,113 +4299,6 @@ int floatx80_unordered_quiet(floatx80 a, floatx80 b, float_status *status) == float_relation_unordered; } -/* min() and max() functions. These can't be implemented as - * 'compare and pick one input' because that would mishandle - * NaNs and +0 vs -0. - * - * minnum() and maxnum() functions. These are similar to the min() - * and max() functions but if one of the arguments is a QNaN and - * the other is numerical then the numerical argument is returned. - * minnum() and maxnum correspond to the IEEE 754-2008 minNum() - * and maxNum() operations. min() and max() are the typical min/max - * semantics provided by many CPUs which predate that specification. - * - * minnummag() and maxnummag() functions correspond to minNumMag() - * and minNumMag() from the IEEE-754 2008. - */ -#define MINMAX(s) \ -static inline float ## s float ## s ## _minmax(float ## s a, float ## s b, \ - int ismin, int isieee, \ - int ismag, \ - float_status *status) \ -{ \ - flag aSign, bSign; \ - uint ## s ## _t av, bv, aav, abv; \ - a = float ## s ## _squash_input_denormal(a, status); \ - b = float ## s ## _squash_input_denormal(b, status); \ - if (float ## s ## _is_any_nan(a) || \ - float ## s ## _is_any_nan(b)) { \ - if (isieee) { \ - if (float ## s ## _is_quiet_nan(a, status) && \ - !float ## s ##_is_any_nan(b)) { \ - return b; \ - } else if (float ## s ## _is_quiet_nan(b, status) && \ - !float ## s ## _is_any_nan(a)) { \ - return a; \ - } \ - } \ - return propagateFloat ## s ## NaN(a, b, status); \ - } \ - aSign = extractFloat ## s ## Sign(a); \ - bSign = extractFloat ## s ## Sign(b); \ - av = float ## s ## _val(a); \ - bv = float ## s ## _val(b); \ - if (ismag) { \ - aav = float ## s ## _abs(av); \ - abv = float ## s ## _abs(bv); \ - if (aav != abv) { \ - if (ismin) { \ - return (aav < abv) ? a : b; \ - } else { \ - return (aav < abv) ? b : a; \ - } \ - } \ - } \ - if (aSign != bSign) { \ - if (ismin) { \ - return aSign ? a : b; \ - } else { \ - return aSign ? b : a; \ - } \ - } else { \ - if (ismin) { \ - return (aSign ^ (av < bv)) ? a : b; \ - } else { \ - return (aSign ^ (av < bv)) ? b : a; \ - } \ - } \ -} \ - \ -float ## s float ## s ## _min(float ## s a, float ## s b, \ - float_status *status) \ -{ \ - return float ## s ## _minmax(a, b, 1, 0, 0, status); \ -} \ - \ -float ## s float ## s ## _max(float ## s a, float ## s b, \ - float_status *status) \ -{ \ - return float ## s ## _minmax(a, b, 0, 0, 0, status); \ -} \ - \ -float ## s float ## s ## _minnum(float ## s a, float ## s b, \ - float_status *status) \ -{ \ - return float ## s ## _minmax(a, b, 1, 1, 0, status); \ -} \ - \ -float ## s float ## s ## _maxnum(float ## s a, float ## s b, \ - float_status *status) \ -{ \ - return float ## s ## _minmax(a, b, 0, 1, 0, status); \ -} \ - \ -float ## s float ## s ## _minnummag(float ## s a, float ## s b, \ - float_status *status) \ -{ \ - return float ## s ## _minmax(a, b, 1, 1, 1, status); \ -} \ - \ -float ## s float ## s ## _maxnummag(float ## s a, float ## s b, \ - float_status *status) \ -{ \ - return float ## s ## _minmax(a, b, 0, 1, 1, status); \ -} - -MINMAX(32) -MINMAX(64) - - /* Multiply A by 2 raised to the power N. */ float32 float32_scalbn(float32 a, int n, float_status *status) { From patchwork Sun Feb 4 04:11:32 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Richard Henderson X-Patchwork-Id: 126809 Delivered-To: patch@linaro.org Received: by 10.80.172.228 with SMTP id x91csp1226892edc; Sat, 3 Feb 2018 20:24:09 -0800 (PST) X-Google-Smtp-Source: AH8x227w6Bxc4LOB47V4Vf3Z3uYO6ewv1sCXlK1WNi8b+EewWshmNfENf3G6u3lIqxvSOiod3Gu3 X-Received: by 10.129.120.203 with SMTP id t194mr29505507ywc.383.1517718249697; Sat, 03 Feb 2018 20:24:09 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1517718249; cv=none; d=google.com; s=arc-20160816; b=WECvcgmzE7/TEI60bU50kR5z/PCLPpr7IFvJjEDp/0bklwQ9/8dLaK/9rICPsP+vqe QsMxFiOGkDmytIDMEGIodVJxN3jIMVnZpQTBvaNeQDcYoSKo4PWMDDjh3z++Eg8Vrrpj JTPJbzG6nNSsEReglFy0OGc8/fp7tzghPnJRfoIMCXcCgoQLads6e4uy1r995Y7ygVsy uf1T/tU0acvI5JzUBHzY2JYko8WVI/MA5HQiHk8MQ7zTG9bvql5i/c4+DlBuz0DMfwDA V+Mv4+3IElobMziHiKaVwoda3fn65/9EVQ6WrdQk6FOdzY5Y6VljTSGjkSadRT+bbP8W 6j6Q== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=sender:errors-to:cc:list-subscribe:list-help:list-post:list-archive :list-unsubscribe:list-id:precedence:subject:references:in-reply-to :message-id:date:to:from:dkim-signature:arc-authentication-results; bh=JtVBFTZoABkvk/+9moDvgVQCJUYa1FRYh42Z64SJZtw=; b=Eajl3kLCT3z1ChC4cW+2XgXZwr8fDSRFhxdccruVtkiyjsp7G7pEJKPvLhiAZBznAe NBRdrSQeo9uIYw5KreiamPCrbjrlgPKH6x5PZL/+Qm6nJcE7mE46xAybTUmy2fD4/+Lf 93cfsZt0co2ORIa/aEzk6ilqM38kvnEOOyDLV6EocMpQJAuLv0o5IbTp+2nmDlt9tHAc 0lmfgoEVV7E6rqAYEd1zbOrPZIh0M7U/TbY5zIsLKRTwzXYV35Lx3D2L5mP/RgJw3Hp4 DWMPAWHmCMgXBoQQOjQD1ZjL+x9a9cPSf0Oq+ViJKDBYNkLdv4HZ0MIboGs7H5trkFBo dyng== ARC-Authentication-Results: i=1; mx.google.com; dkim=fail header.i=@linaro.org header.s=google header.b=Z/VUM2lu; spf=pass (google.com: domain of qemu-devel-bounces+patch=linaro.org@nongnu.org designates 2001:4830:134:3::11 as permitted sender) smtp.mailfrom=qemu-devel-bounces+patch=linaro.org@nongnu.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=linaro.org Return-Path: Received: from lists.gnu.org (lists.gnu.org. [2001:4830:134:3::11]) by mx.google.com with ESMTPS id h65si1011130ywe.473.2018.02.03.20.24.09 for (version=TLS1 cipher=AES128-SHA bits=128/128); Sat, 03 Feb 2018 20:24:09 -0800 (PST) Received-SPF: pass (google.com: domain of qemu-devel-bounces+patch=linaro.org@nongnu.org designates 2001:4830:134:3::11 as permitted sender) client-ip=2001:4830:134:3::11; Authentication-Results: mx.google.com; dkim=fail header.i=@linaro.org header.s=google header.b=Z/VUM2lu; spf=pass (google.com: domain of qemu-devel-bounces+patch=linaro.org@nongnu.org designates 2001:4830:134:3::11 as permitted sender) smtp.mailfrom=qemu-devel-bounces+patch=linaro.org@nongnu.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=linaro.org Received: from localhost ([::1]:58321 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1eiBqb-0006i0-21 for patch@linaro.org; Sat, 03 Feb 2018 23:24:09 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:47441) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1eiBf2-0004tJ-A4 for qemu-devel@nongnu.org; Sat, 03 Feb 2018 23:12:13 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1eiBf0-00054e-8H for qemu-devel@nongnu.org; Sat, 03 Feb 2018 23:12:12 -0500 Received: from mail-pl0-x243.google.com ([2607:f8b0:400e:c01::243]:43339) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1eiBf0-00053s-05 for qemu-devel@nongnu.org; Sat, 03 Feb 2018 23:12:10 -0500 Received: by mail-pl0-x243.google.com with SMTP id f4so9361191plr.10 for ; Sat, 03 Feb 2018 20:12:09 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=JtVBFTZoABkvk/+9moDvgVQCJUYa1FRYh42Z64SJZtw=; b=Z/VUM2lu5rqcjnxa4VhYE3qPwz7hurgHtH/ozp4tCjQBJYL+50HSqTO6k7AsCfaAkN DvZT5/1bUvnIpzLOzZb0tBOxX2KDIhwKiHf0kbJTwpIhbbK2LEtwKVsXWTlFxv0qbcws 3/ozFhz7RnV+w2EmDE/eGUY73dACPsVsNfI0c= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=JtVBFTZoABkvk/+9moDvgVQCJUYa1FRYh42Z64SJZtw=; b=dGUec79yOAj0JwnxOFxj5XXDnaH3D3UR+UDc6TxTE80o4mp+2tXISgWrxY+klv16OB sR679d1Nany3sL/hSeDWTfqhk/Mt7zpvolvdWZbZP1sVx0Ze8vjvxb2xFkbJ2RLiuh2k xeeek4+OmA0aWbrSUlgt/l/Oo/DBdHt7ZbSxwMAZz+B6tq9PyLcaD0Q/wHHujNWnmaqt JeHPiAduXfAFs2yLlhnWMFcvs585t9WsUbawHOvQBIrDnKMSD/195Tp79/QcsAQsY7Of cLx7oT/yvUsdONBz6GdnJZq7r8lGVsb7Guq1ndBGuo49MjTJMohIP5BA6SPQY/Aie9NC kIrQ== X-Gm-Message-State: AKwxyteM0587+6m0WjHI10KZvnRIIYpzEXpmzuN+Nyg0/BBPwb7kGO0e TyN6SeTQxQWH54YC5Vl0BQkj+ZJE7Eg= X-Received: by 2002:a17:902:8ec4:: with SMTP id x4-v6mr10806630plo.271.1517717528591; Sat, 03 Feb 2018 20:12:08 -0800 (PST) Received: from cloudburst.twiddle.net (174-21-6-47.tukw.qwest.net. [174.21.6.47]) by smtp.gmail.com with ESMTPSA id k3sm1399425pgr.12.2018.02.03.20.12.07 (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Sat, 03 Feb 2018 20:12:07 -0800 (PST) From: Richard Henderson To: qemu-devel@nongnu.org Date: Sat, 3 Feb 2018 20:11:32 -0800 Message-Id: <20180204041136.17525-21-richard.henderson@linaro.org> X-Mailer: git-send-email 2.14.3 In-Reply-To: <20180204041136.17525-1-richard.henderson@linaro.org> References: <20180204041136.17525-1-richard.henderson@linaro.org> X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 2607:f8b0:400e:c01::243 Subject: [Qemu-devel] [PATCH 20/24] fpu: Implement sqrt with soft-fp.h X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: peter.maydell@linaro.org, cota@braap.org, alex.bennee@linaro.org, hsp.cat7@gmail.com Errors-To: qemu-devel-bounces+patch=linaro.org@nongnu.org Sender: "Qemu-devel" Add float16 support. Signed-off-by: Richard Henderson --- include/fpu/softfloat.h | 1 + fpu/floatxx.inc.c | 16 +++++ fpu/softfloat.c | 179 ------------------------------------------------ 3 files changed, 17 insertions(+), 179 deletions(-) -- 2.14.3 diff --git a/include/fpu/softfloat.h b/include/fpu/softfloat.h index 95590d8420..0aae0454e2 100644 --- a/include/fpu/softfloat.h +++ b/include/fpu/softfloat.h @@ -250,6 +250,7 @@ float16 float16_add(float16, float16, float_status *status); float16 float16_sub(float16, float16, float_status *status); float16 float16_mul(float16, float16, float_status *status); float16 float16_div(float16, float16, float_status *status); +float16 float16_sqrt(float16, float_status *status); int float16_eq(float16, float16, float_status *status); int float16_le(float16, float16, float_status *status); int float16_lt(float16, float16, float_status *status); diff --git a/fpu/floatxx.inc.c b/fpu/floatxx.inc.c index 0b6b8b4fd3..7a7f53dd5d 100644 --- a/fpu/floatxx.inc.c +++ b/fpu/floatxx.inc.c @@ -101,6 +101,22 @@ FLOATXX glue(FLOATXX,_div)(FLOATXX a, FLOATXX b, float_status *status) return r; } +FLOATXX glue(FLOATXX,_sqrt)(FLOATXX a, float_status *status) +{ + FP_DECL_EX; + glue(FP_DECL_, FS)(A); + glue(FP_DECL_, FS)(R); + FLOATXX r; + + FP_INIT_ROUNDMODE; + glue(FP_UNPACK_, FS)(A, a); + glue(FP_SQRT_, FS)(R, A); + glue(FP_PACK_, FS)(r, R); + FP_HANDLE_EXCEPTIONS; + + return r; +} + #define DO_FLOAT_TO_INT(NAME, SZ, FP_TO_INT_WHICH) \ int##SZ##_t NAME(FLOATXX a, float_status *status) \ { \ diff --git a/fpu/softfloat.c b/fpu/softfloat.c index 68dfb464d5..83995cc60f 100644 --- a/fpu/softfloat.c +++ b/fpu/softfloat.c @@ -1783,63 +1783,6 @@ float32 float32_muladd(float32 a, float32 b, float32 c, int flags, } -/*---------------------------------------------------------------------------- -| Returns the square root of the single-precision floating-point value `a'. -| The operation is performed according to the IEC/IEEE Standard for Binary -| Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -float32 float32_sqrt(float32 a, float_status *status) -{ - flag aSign; - int aExp, zExp; - uint32_t aSig, zSig; - uint64_t rem, term; - a = float32_squash_input_denormal(a, status); - - aSig = extractFloat32Frac( a ); - aExp = extractFloat32Exp( a ); - aSign = extractFloat32Sign( a ); - if ( aExp == 0xFF ) { - if (aSig) { - return propagateFloat32NaN(a, float32_zero, status); - } - if ( ! aSign ) return a; - float_raise(float_flag_invalid, status); - return float32_default_nan(status); - } - if ( aSign ) { - if ( ( aExp | aSig ) == 0 ) return a; - float_raise(float_flag_invalid, status); - return float32_default_nan(status); - } - if ( aExp == 0 ) { - if ( aSig == 0 ) return float32_zero; - normalizeFloat32Subnormal( aSig, &aExp, &aSig ); - } - zExp = ( ( aExp - 0x7F )>>1 ) + 0x7E; - aSig = ( aSig | 0x00800000 )<<8; - zSig = estimateSqrt32( aExp, aSig ) + 2; - if ( ( zSig & 0x7F ) <= 5 ) { - if ( zSig < 2 ) { - zSig = 0x7FFFFFFF; - goto roundAndPack; - } - aSig >>= aExp & 1; - term = ( (uint64_t) zSig ) * zSig; - rem = ( ( (uint64_t) aSig )<<32 ) - term; - while ( (int64_t) rem < 0 ) { - --zSig; - rem += ( ( (uint64_t) zSig )<<1 ) | 1; - } - zSig |= ( rem != 0 ); - } - shift32RightJamming( zSig, 1, &zSig ); - roundAndPack: - return roundAndPackFloat32(0, zExp, zSig, status); - -} - /*---------------------------------------------------------------------------- | Returns the binary exponential of the single-precision floating-point value | `a'. The operation is performed according to the IEC/IEEE Standard for @@ -2804,60 +2747,6 @@ float64 float64_muladd(float64 a, float64 b, float64 c, int flags, } } -/*---------------------------------------------------------------------------- -| Returns the square root of the double-precision floating-point value `a'. -| The operation is performed according to the IEC/IEEE Standard for Binary -| Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -float64 float64_sqrt(float64 a, float_status *status) -{ - flag aSign; - int aExp, zExp; - uint64_t aSig, zSig, doubleZSig; - uint64_t rem0, rem1, term0, term1; - a = float64_squash_input_denormal(a, status); - - aSig = extractFloat64Frac( a ); - aExp = extractFloat64Exp( a ); - aSign = extractFloat64Sign( a ); - if ( aExp == 0x7FF ) { - if (aSig) { - return propagateFloat64NaN(a, a, status); - } - if ( ! aSign ) return a; - float_raise(float_flag_invalid, status); - return float64_default_nan(status); - } - if ( aSign ) { - if ( ( aExp | aSig ) == 0 ) return a; - float_raise(float_flag_invalid, status); - return float64_default_nan(status); - } - if ( aExp == 0 ) { - if ( aSig == 0 ) return float64_zero; - normalizeFloat64Subnormal( aSig, &aExp, &aSig ); - } - zExp = ( ( aExp - 0x3FF )>>1 ) + 0x3FE; - aSig |= LIT64( 0x0010000000000000 ); - zSig = estimateSqrt32( aExp, aSig>>21 ); - aSig <<= 9 - ( aExp & 1 ); - zSig = estimateDiv128To64( aSig, 0, zSig<<32 ) + ( zSig<<30 ); - if ( ( zSig & 0x1FF ) <= 5 ) { - doubleZSig = zSig<<1; - mul64To128( zSig, zSig, &term0, &term1 ); - sub128( aSig, 0, term0, term1, &rem0, &rem1 ); - while ( (int64_t) rem0 < 0 ) { - --zSig; - doubleZSig -= 2; - add128( rem0, rem1, zSig>>63, doubleZSig | 1, &rem0, &rem1 ); - } - zSig |= ( ( rem0 | rem1 ) != 0 ); - } - return roundAndPackFloat64(0, zExp, zSig, status); - -} - /*---------------------------------------------------------------------------- | Returns the binary log of the double-precision floating-point value `a'. | The operation is performed according to the IEC/IEEE Standard for Binary @@ -4139,74 +4028,6 @@ float128 float128_rem(float128 a, float128 b, float_status *status) status); } -/*---------------------------------------------------------------------------- -| Returns the square root of the quadruple-precision floating-point value `a'. -| The operation is performed according to the IEC/IEEE Standard for Binary -| Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -float128 float128_sqrt(float128 a, float_status *status) -{ - flag aSign; - int32_t aExp, zExp; - uint64_t aSig0, aSig1, zSig0, zSig1, zSig2, doubleZSig0; - uint64_t rem0, rem1, rem2, rem3, term0, term1, term2, term3; - - aSig1 = extractFloat128Frac1( a ); - aSig0 = extractFloat128Frac0( a ); - aExp = extractFloat128Exp( a ); - aSign = extractFloat128Sign( a ); - if ( aExp == 0x7FFF ) { - if (aSig0 | aSig1) { - return propagateFloat128NaN(a, a, status); - } - if ( ! aSign ) return a; - goto invalid; - } - if ( aSign ) { - if ( ( aExp | aSig0 | aSig1 ) == 0 ) return a; - invalid: - float_raise(float_flag_invalid, status); - return float128_default_nan(status); - } - if ( aExp == 0 ) { - if ( ( aSig0 | aSig1 ) == 0 ) return packFloat128( 0, 0, 0, 0 ); - normalizeFloat128Subnormal( aSig0, aSig1, &aExp, &aSig0, &aSig1 ); - } - zExp = ( ( aExp - 0x3FFF )>>1 ) + 0x3FFE; - aSig0 |= LIT64( 0x0001000000000000 ); - zSig0 = estimateSqrt32( aExp, aSig0>>17 ); - shortShift128Left( aSig0, aSig1, 13 - ( aExp & 1 ), &aSig0, &aSig1 ); - zSig0 = estimateDiv128To64( aSig0, aSig1, zSig0<<32 ) + ( zSig0<<30 ); - doubleZSig0 = zSig0<<1; - mul64To128( zSig0, zSig0, &term0, &term1 ); - sub128( aSig0, aSig1, term0, term1, &rem0, &rem1 ); - while ( (int64_t) rem0 < 0 ) { - --zSig0; - doubleZSig0 -= 2; - add128( rem0, rem1, zSig0>>63, doubleZSig0 | 1, &rem0, &rem1 ); - } - zSig1 = estimateDiv128To64( rem1, 0, doubleZSig0 ); - if ( ( zSig1 & 0x1FFF ) <= 5 ) { - if ( zSig1 == 0 ) zSig1 = 1; - mul64To128( doubleZSig0, zSig1, &term1, &term2 ); - sub128( rem1, 0, term1, term2, &rem1, &rem2 ); - mul64To128( zSig1, zSig1, &term2, &term3 ); - sub192( rem1, rem2, 0, 0, term2, term3, &rem1, &rem2, &rem3 ); - while ( (int64_t) rem1 < 0 ) { - --zSig1; - shortShift128Left( 0, zSig1, 1, &term2, &term3 ); - term3 |= 1; - term2 |= doubleZSig0; - add192( rem1, rem2, rem3, 0, term2, term3, &rem1, &rem2, &rem3 ); - } - zSig1 |= ( ( rem1 | rem2 | rem3 ) != 0 ); - } - shift128ExtraRightJamming( zSig0, zSig1, 0, 14, &zSig0, &zSig1, &zSig2 ); - return roundAndPackFloat128(0, zExp, zSig0, zSig1, zSig2, status); - -} - static inline int floatx80_compare_internal(floatx80 a, floatx80 b, int is_quiet, float_status *status) { From patchwork Sun Feb 4 04:11:33 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Richard Henderson X-Patchwork-Id: 126812 Delivered-To: patch@linaro.org Received: by 10.80.172.228 with SMTP id x91csp1228030edc; Sat, 3 Feb 2018 20:26:31 -0800 (PST) X-Google-Smtp-Source: AH8x226PMczWMgFurlzgJeuFie6Tc3uOnXNaPu4IcyfQEGGuxl225G6NFXi/5Fs7+Qgom6NdJW+O X-Received: by 10.37.214.213 with SMTP id n204mr29158954ybg.67.1517718391138; Sat, 03 Feb 2018 20:26:31 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1517718391; cv=none; d=google.com; s=arc-20160816; b=bdEV1AVxppPzjwby4QcqlK1pvZeaHTdqZLuDSQnbjUwenM+3Wb7IkyJNTaBF6YTN9X Yy1xMpmrk89fTIs1C7molzpT2ucPS0O3seAsyuIhB4TxdteHHLucBCG9YEcwDGzSQmv/ f1Z2Kw0OB4acLFzBvJa9vje2LGFsdofpzsSQ/bJ+DWMzqHCczNI+t4UBzi7R8CQ3zE5x XpbJo0P8ulgwmOxgpZe+a4YLlQ/FpSLToDfgM7cP/72F4CmAiGpCl6kgYo6Kc5bsJw3C qkGX0Sf/+wk+GUQEvIUY5VqzrxUo6Z/qHUmlPsbYkJK6vI3LlKleU5DWFcPdRIUO6t0X 7uhw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=sender:errors-to:cc:list-subscribe:list-help:list-post:list-archive :list-unsubscribe:list-id:precedence:subject:references:in-reply-to :message-id:date:to:from:dkim-signature:arc-authentication-results; bh=hrzvhydRP8GcrH7J589GBvfvzE6ByNOtrc6l/vYJHbY=; b=VEoS/rn4aSxAavyVZhNsur3cMyTZxhEpyLI1LOVu5rsgm8MidRqdpaxAk3oFBskgR6 XtbbBHXoO4k6Vhp/UI+W5rA5XxIA9PpbW8Hr4J+pCLaAkxnvhJAm/86cyY0A8PDL8fNJ eP/dDW9GGO+GNRJOlSTIbXIJ0sZHeKZWgr8LfgXjjBZlSRCPyF1UhjBkiOaTjukXKQw1 r5kJdKdIYRxzlOXjzmBfyboJPAFjJJwSTjeHptwFy99MIRq6mKfmlQoHXtQVm/DvNxAl C2DTTcBh0NUDZRmznT+s/9qazeKhUhXhO6cPQbK7gJ5tgVNHm1X5pCJVJ4PkjhAr/EJX 52bA== ARC-Authentication-Results: i=1; mx.google.com; dkim=fail header.i=@linaro.org header.s=google header.b=KJWnv+17; spf=pass (google.com: domain of qemu-devel-bounces+patch=linaro.org@nongnu.org designates 2001:4830:134:3::11 as permitted sender) smtp.mailfrom=qemu-devel-bounces+patch=linaro.org@nongnu.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=linaro.org Return-Path: Received: from lists.gnu.org (lists.gnu.org. [2001:4830:134:3::11]) by mx.google.com with ESMTPS id g34si1037616ybj.544.2018.02.03.20.26.30 for (version=TLS1 cipher=AES128-SHA bits=128/128); Sat, 03 Feb 2018 20:26:31 -0800 (PST) Received-SPF: pass (google.com: domain of qemu-devel-bounces+patch=linaro.org@nongnu.org designates 2001:4830:134:3::11 as permitted sender) client-ip=2001:4830:134:3::11; Authentication-Results: mx.google.com; dkim=fail header.i=@linaro.org header.s=google header.b=KJWnv+17; spf=pass (google.com: domain of qemu-devel-bounces+patch=linaro.org@nongnu.org designates 2001:4830:134:3::11 as permitted sender) smtp.mailfrom=qemu-devel-bounces+patch=linaro.org@nongnu.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=linaro.org Received: from localhost ([::1]:58332 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1eiBss-0008Bd-Ha for patch@linaro.org; Sat, 03 Feb 2018 23:26:30 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:47454) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1eiBf2-0004tn-QN for qemu-devel@nongnu.org; Sat, 03 Feb 2018 23:12:14 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1eiBf1-00055h-9W for qemu-devel@nongnu.org; Sat, 03 Feb 2018 23:12:12 -0500 Received: from mail-pl0-x244.google.com ([2607:f8b0:400e:c01::244]:39324) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1eiBf1-000553-25 for qemu-devel@nongnu.org; Sat, 03 Feb 2018 23:12:11 -0500 Received: by mail-pl0-x244.google.com with SMTP id o13so9359917pli.6 for ; Sat, 03 Feb 2018 20:12:11 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=hrzvhydRP8GcrH7J589GBvfvzE6ByNOtrc6l/vYJHbY=; b=KJWnv+17Cwh5MRsPlKHZbdFnZrjPd/RUPPyEwQ369kC10c0SGBST629xynQNMTow6m jwBTwh6qGPVzhm2PYf/mcr8GpU3xTK6uoSi1UfGYFcFIogtGjQHbuOdESQJj6E/LqZYI xXGdmJOISMOT3iPFR0qxYo1QIx1FFOQKa5nKE= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=hrzvhydRP8GcrH7J589GBvfvzE6ByNOtrc6l/vYJHbY=; b=fLxVTjzxaZaK/ccq+EDaKfcqezmS/I1UeM9rz57pe5s66IUkHWJ+RXdz2MqswKxr9R 8gx3jed0r0a4uhSCFP+2BfCjCYcdwyyzVMo0+YPgB7Z6XO/pWA5vd5fiCxj1zs3jWknR g0Lmj7l5LycNPBbUMYGlAbW51QhAQEb3fTmvokHxjful1TejBAAySSlhoHWjAKwwFt7S EfXiR3wQPQBIQudGF2rYOgbuevy8v/EktW9EJQ0G/WQpEEhxQ1wNEZsJg6oJBH/coyAy oaNbCgykCzNBI7OSMM6L8lsm9KgIDsDcz/K163oCearSCiPfM3tng1MhJUuCYAsocTQC mtQQ== X-Gm-Message-State: AKwxytdBd93hCJs6fBFACzYRNfdZbpWLWY1gQqk3Mx/fEEKqVPDajE8m 2eTomQnGPqem7Px3Qf9fCUK6eUv5luk= X-Received: by 2002:a17:902:bf41:: with SMTP id u1-v6mr29909371pls.416.1517717529892; Sat, 03 Feb 2018 20:12:09 -0800 (PST) Received: from cloudburst.twiddle.net (174-21-6-47.tukw.qwest.net. [174.21.6.47]) by smtp.gmail.com with ESMTPSA id k3sm1399425pgr.12.2018.02.03.20.12.08 (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Sat, 03 Feb 2018 20:12:09 -0800 (PST) From: Richard Henderson To: qemu-devel@nongnu.org Date: Sat, 3 Feb 2018 20:11:33 -0800 Message-Id: <20180204041136.17525-22-richard.henderson@linaro.org> X-Mailer: git-send-email 2.14.3 In-Reply-To: <20180204041136.17525-1-richard.henderson@linaro.org> References: <20180204041136.17525-1-richard.henderson@linaro.org> X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 2607:f8b0:400e:c01::244 Subject: [Qemu-devel] [PATCH 21/24] fpu: Implement scalbn with soft-fp.h X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: peter.maydell@linaro.org, cota@braap.org, alex.bennee@linaro.org, hsp.cat7@gmail.com Errors-To: qemu-devel-bounces+patch=linaro.org@nongnu.org Sender: "Qemu-devel" Add float16 support. Signed-off-by: Richard Henderson --- include/fpu/softfloat.h | 1 + fpu/floatxx.inc.c | 28 +++++++++++++ fpu/softfloat.c | 109 ------------------------------------------------ 3 files changed, 29 insertions(+), 109 deletions(-) -- 2.14.3 diff --git a/include/fpu/softfloat.h b/include/fpu/softfloat.h index 0aae0454e2..b97022be1d 100644 --- a/include/fpu/softfloat.h +++ b/include/fpu/softfloat.h @@ -267,6 +267,7 @@ float16 float16_minnum(float16, float16, float_status *status); float16 float16_maxnum(float16, float16, float_status *status); float16 float16_minnummag(float16, float16, float_status *status); float16 float16_maxnummag(float16, float16, float_status *status); +float16 float16_scalbn(float16, int, float_status *status); int float16_is_quiet_nan(float16, float_status *status); int float16_is_signaling_nan(float16, float_status *status); diff --git a/fpu/floatxx.inc.c b/fpu/floatxx.inc.c index 7a7f53dd5d..8c009dd966 100644 --- a/fpu/floatxx.inc.c +++ b/fpu/floatxx.inc.c @@ -117,6 +117,34 @@ FLOATXX glue(FLOATXX,_sqrt)(FLOATXX a, float_status *status) return r; } +FLOATXX glue(FLOATXX,_scalbn)(FLOATXX a, int n, float_status *status) +{ + FP_DECL_EX; + glue(FP_DECL_, FS)(A); + + FP_INIT_ROUNDMODE; + glue(FP_UNPACK_, FS)(A, a); + + if (likely(A_c == FP_CLS_NORMAL)) { + /* Bound N such that the exponent can safely adjusted without + overflowing. The maximum is large enough to take the smallest + denormal up beyond the largest normal, which will overflow + to infinity when we repack. */ + int max = glue(_FP_EXPMAX_, FS) + glue(_FP_FRACBITS_, FS); + if (n > max) { + n = max; + } else if (n < -max) { + n = -max; + } + A_e += n; + } + + glue(FP_PACK_, FS)(a, A); + FP_HANDLE_EXCEPTIONS; + + return a; +} + #define DO_FLOAT_TO_INT(NAME, SZ, FP_TO_INT_WHICH) \ int##SZ##_t NAME(FLOATXX a, float_status *status) \ { \ diff --git a/fpu/softfloat.c b/fpu/softfloat.c index 83995cc60f..2550028d9f 100644 --- a/fpu/softfloat.c +++ b/fpu/softfloat.c @@ -4120,79 +4120,6 @@ int floatx80_unordered_quiet(floatx80 a, floatx80 b, float_status *status) == float_relation_unordered; } -/* Multiply A by 2 raised to the power N. */ -float32 float32_scalbn(float32 a, int n, float_status *status) -{ - flag aSign; - int16_t aExp; - uint32_t aSig; - - a = float32_squash_input_denormal(a, status); - aSig = extractFloat32Frac( a ); - aExp = extractFloat32Exp( a ); - aSign = extractFloat32Sign( a ); - - if ( aExp == 0xFF ) { - if ( aSig ) { - return propagateFloat32NaN(a, a, status); - } - return a; - } - if (aExp != 0) { - aSig |= 0x00800000; - } else if (aSig == 0) { - return a; - } else { - aExp++; - } - - if (n > 0x200) { - n = 0x200; - } else if (n < -0x200) { - n = -0x200; - } - - aExp += n - 1; - aSig <<= 7; - return normalizeRoundAndPackFloat32(aSign, aExp, aSig, status); -} - -float64 float64_scalbn(float64 a, int n, float_status *status) -{ - flag aSign; - int16_t aExp; - uint64_t aSig; - - a = float64_squash_input_denormal(a, status); - aSig = extractFloat64Frac( a ); - aExp = extractFloat64Exp( a ); - aSign = extractFloat64Sign( a ); - - if ( aExp == 0x7FF ) { - if ( aSig ) { - return propagateFloat64NaN(a, a, status); - } - return a; - } - if (aExp != 0) { - aSig |= LIT64( 0x0010000000000000 ); - } else if (aSig == 0) { - return a; - } else { - aExp++; - } - - if (n > 0x1000) { - n = 0x1000; - } else if (n < -0x1000) { - n = -0x1000; - } - - aExp += n - 1; - aSig <<= 10; - return normalizeRoundAndPackFloat64(aSign, aExp, aSig, status); -} - floatx80 floatx80_scalbn(floatx80 a, int n, float_status *status) { flag aSign; @@ -4231,39 +4158,3 @@ floatx80 floatx80_scalbn(floatx80 a, int n, float_status *status) return normalizeRoundAndPackFloatx80(status->floatx80_rounding_precision, aSign, aExp, aSig, 0, status); } - -float128 float128_scalbn(float128 a, int n, float_status *status) -{ - flag aSign; - int32_t aExp; - uint64_t aSig0, aSig1; - - aSig1 = extractFloat128Frac1( a ); - aSig0 = extractFloat128Frac0( a ); - aExp = extractFloat128Exp( a ); - aSign = extractFloat128Sign( a ); - if ( aExp == 0x7FFF ) { - if ( aSig0 | aSig1 ) { - return propagateFloat128NaN(a, a, status); - } - return a; - } - if (aExp != 0) { - aSig0 |= LIT64( 0x0001000000000000 ); - } else if (aSig0 == 0 && aSig1 == 0) { - return a; - } else { - aExp++; - } - - if (n > 0x10000) { - n = 0x10000; - } else if (n < -0x10000) { - n = -0x10000; - } - - aExp += n - 1; - return normalizeRoundAndPackFloat128( aSign, aExp, aSig0, aSig1 - , status); - -} From patchwork Sun Feb 4 04:11:34 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Richard Henderson X-Patchwork-Id: 126810 Delivered-To: patch@linaro.org Received: by 10.80.172.228 with SMTP id x91csp1227156edc; Sat, 3 Feb 2018 20:24:46 -0800 (PST) X-Google-Smtp-Source: AH8x224hjhTY3UFf1aaFgcucJWrn/9uKMfAFuVNYNN1mKu5nSlDaMG0aV5nWMic1Gl5pKu3csJOC X-Received: by 10.37.187.145 with SMTP id y17mr27991637ybg.64.1517718286656; Sat, 03 Feb 2018 20:24:46 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1517718286; cv=none; d=google.com; s=arc-20160816; b=Bix4WrCYlEqoz9tk1OMasJf//g/K+rgYJKnLFZByFMT6IVUz65zKw7xtgL551FfEl7 VKLaZ6HDxxghxOCb2vpIr1U+dR9xZA+dFolJHxG7rhxVhozuXJg58h2lT61oRRiD/BJY 0R382fbqK5xkTgehfp1Jsr3PkbYlvrmVxszUsDNmSD2Rwa42V9QLisaaOD3JmuyMpehM 7iMUvosjPd7HdpCoCUW4MpWOGgcQpCaubjh9pTZNheQuqhntQtLv4Lo8MtgQhiVr5ETk /or1hYy1xowPWkZnwgKGN1nBR8cnYMHxymIwngvdSnJPAQPVkdrK8k4a+1+mQCwgIIHK BQGA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=sender:errors-to:cc:list-subscribe:list-help:list-post:list-archive :list-unsubscribe:list-id:precedence:subject:references:in-reply-to :message-id:date:to:from:dkim-signature:arc-authentication-results; bh=IGpTRsXu1vgjry67yQ7kjvdX3sIxDUEK5Nd0oubqcO4=; b=goSK9lonl+zZ15QrBP2GTACvpIhFHfhLqPfgLEYjYT2/2PJwmR+gBT3aM3Xy4Vcg8s esI9HWmrHdUg0ODOid8avktHBWoBibaazpQY+GQtyysLmq3qY9ujBnCfX+LMhZ9j2lwx jZcL+YN/xHBXCiQDG/pVlIvJXLgBKQAuVDZXonU7DRSV54BgdApWDMQSQzFhbkTd9Una Sj2JsGbahLYcZAAOyf6zEJ0B5Db6q8ABMP7HiNNyTtDUvL3Qj1ok74G1oAAeDyniAlDF DYapiBsZSGUkdTO8G7DFqjWHuXLOqTulbTity8HFxGS+s2ne9h6qxbFVDBW28zYGFsoW VZ/A== ARC-Authentication-Results: i=1; mx.google.com; dkim=fail header.i=@linaro.org header.s=google header.b=F3B9a6VS; spf=pass (google.com: domain of qemu-devel-bounces+patch=linaro.org@nongnu.org designates 2001:4830:134:3::11 as permitted sender) smtp.mailfrom=qemu-devel-bounces+patch=linaro.org@nongnu.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=linaro.org Return-Path: Received: from lists.gnu.org (lists.gnu.org. [2001:4830:134:3::11]) by mx.google.com with ESMTPS id w195si1018171ywa.110.2018.02.03.20.24.46 for (version=TLS1 cipher=AES128-SHA bits=128/128); Sat, 03 Feb 2018 20:24:46 -0800 (PST) Received-SPF: pass (google.com: domain of qemu-devel-bounces+patch=linaro.org@nongnu.org designates 2001:4830:134:3::11 as permitted sender) client-ip=2001:4830:134:3::11; Authentication-Results: mx.google.com; dkim=fail header.i=@linaro.org header.s=google header.b=F3B9a6VS; spf=pass (google.com: domain of qemu-devel-bounces+patch=linaro.org@nongnu.org designates 2001:4830:134:3::11 as permitted sender) smtp.mailfrom=qemu-devel-bounces+patch=linaro.org@nongnu.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=linaro.org Received: from localhost ([::1]:58327 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1eiBrB-0007SM-W1 for patch@linaro.org; Sat, 03 Feb 2018 23:24:46 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:47495) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1eiBf6-0004y7-O5 for qemu-devel@nongnu.org; Sat, 03 Feb 2018 23:12:21 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1eiBf3-00056a-DX for qemu-devel@nongnu.org; Sat, 03 Feb 2018 23:12:16 -0500 Received: from mail-pl0-x22e.google.com ([2607:f8b0:400e:c01::22e]:35608) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1eiBf3-00056C-1C for qemu-devel@nongnu.org; Sat, 03 Feb 2018 23:12:13 -0500 Received: by mail-pl0-x22e.google.com with SMTP id j19so9379309pll.2 for ; Sat, 03 Feb 2018 20:12:13 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=IGpTRsXu1vgjry67yQ7kjvdX3sIxDUEK5Nd0oubqcO4=; b=F3B9a6VSx5Dy3urq7Mx2aAuZ7FjjbN8R8UGMgyuFNu5HSNRSqudtieweDsY0VkH5O6 0C+4YT4pbHNTC5DVEu6IDxZW7JlABhVDDsQgxIr7t1R42BnurTsQPBOSH9N/wFeSK7+f C3GVenEP2uxNJJDXOGrkQhRwMDd7w9vvlXryI= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=IGpTRsXu1vgjry67yQ7kjvdX3sIxDUEK5Nd0oubqcO4=; b=Sx2IcmO29gl6LQ43uuIyKPcz877OmMqDjtdFZifIXaWDr917S+tIhkAywse3rkW7Uc VewZNSSNCM4y/42dG6c1n9OdR1rUssDq8jRY11aWBv+WVJC/oi5rMjJ9ya+VeU6UgluS 67wLeaMXBkjUN0Uh+uOYYxXbKhikdFFuXsXWS22NvKLOAsXd+64EZfYULEkesmym7e5D 4gdh/fRFyuwntIVGjy9CQwYuKm/DvL+Ux/mC8ugbWgBG3qOpSGGdmFUemT87RhN5K4AK A/HFIIzsixZF/P7o3/ECMYXMVCj7Alzm1fgyuXjZLgXCyD6NhQHpMTr1jynDz92zfFWJ 4rrQ== X-Gm-Message-State: AKwxytc89+UFUR2ndWqLVezFR6HQxnInK2WTCMIcLyfe3B1B5hk1rJSm CBv1b4a6ZT0XS+NwmXfz+mSVriP0q+4= X-Received: by 2002:a17:902:4383:: with SMTP id j3-v6mr39083145pld.320.1517717531384; Sat, 03 Feb 2018 20:12:11 -0800 (PST) Received: from cloudburst.twiddle.net (174-21-6-47.tukw.qwest.net. [174.21.6.47]) by smtp.gmail.com with ESMTPSA id k3sm1399425pgr.12.2018.02.03.20.12.10 (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Sat, 03 Feb 2018 20:12:10 -0800 (PST) From: Richard Henderson To: qemu-devel@nongnu.org Date: Sat, 3 Feb 2018 20:11:34 -0800 Message-Id: <20180204041136.17525-23-richard.henderson@linaro.org> X-Mailer: git-send-email 2.14.3 In-Reply-To: <20180204041136.17525-1-richard.henderson@linaro.org> References: <20180204041136.17525-1-richard.henderson@linaro.org> X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 2607:f8b0:400e:c01::22e Subject: [Qemu-devel] [PATCH 22/24] fpu: Implement float_to_float with soft-fp.h X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: peter.maydell@linaro.org, cota@braap.org, alex.bennee@linaro.org, hsp.cat7@gmail.com Errors-To: qemu-devel-bounces+patch=linaro.org@nongnu.org Sender: "Qemu-devel" Signed-off-by: Richard Henderson --- Makefile.target | 1 + fpu/softfloat-specialize.h | 40 ---- include/fpu/softfloat.h | 8 +- fpu/floatconv.c | 154 ++++++++++++++ fpu/softfloat.c | 489 --------------------------------------------- 5 files changed, 159 insertions(+), 533 deletions(-) create mode 100644 fpu/floatconv.c -- 2.14.3 diff --git a/Makefile.target b/Makefile.target index b904085f77..94efb66775 100644 --- a/Makefile.target +++ b/Makefile.target @@ -102,6 +102,7 @@ obj-y += fpu/float16.o obj-y += fpu/float32.o obj-y += fpu/float64.o obj-y += fpu/float128.o +obj-y += fpu/floatconv.o obj-y += target/$(TARGET_BASE_ARCH)/ obj-y += disas.o obj-$(call notempty,$(TARGET_XML_FILES)) += gdbstub-xml.o diff --git a/fpu/softfloat-specialize.h b/fpu/softfloat-specialize.h index 4be0fb21ba..ffc0264018 100644 --- a/fpu/softfloat-specialize.h +++ b/fpu/softfloat-specialize.h @@ -278,46 +278,6 @@ float16 float16_maybe_silence_nan(float16 a_, float_status *status) return a_; } -/*---------------------------------------------------------------------------- -| Returns the result of converting the half-precision floating-point NaN -| `a' to the canonical NaN format. If `a' is a signaling NaN, the invalid -| exception is raised. -*----------------------------------------------------------------------------*/ - -static commonNaNT float16ToCommonNaN(float16 a, float_status *status) -{ - commonNaNT z; - - if (float16_is_signaling_nan(a, status)) { - float_raise(float_flag_invalid, status); - } - z.sign = float16_val(a) >> 15; - z.low = 0; - z.high = ((uint64_t) float16_val(a)) << 54; - return z; -} - -/*---------------------------------------------------------------------------- -| Returns the result of converting the canonical NaN `a' to the half- -| precision floating-point format. -*----------------------------------------------------------------------------*/ - -static float16 commonNaNToFloat16(commonNaNT a, float_status *status) -{ - uint16_t mantissa = a.high >> 54; - - if (status->default_nan_mode) { - return float16_default_nan(status); - } - - if (mantissa) { - return make_float16(((((uint16_t) a.sign) << 15) - | (0x1F << 10) | mantissa)); - } else { - return float16_default_nan(status); - } -} - #ifdef NO_SIGNALING_NANS int float32_is_quiet_nan(float32 a_, float_status *status) { diff --git a/include/fpu/softfloat.h b/include/fpu/softfloat.h index b97022be1d..53468eec1b 100644 --- a/include/fpu/softfloat.h +++ b/include/fpu/softfloat.h @@ -237,10 +237,10 @@ uint64_t float16_to_uint64(float16, float_status *status); uint64_t float16_to_uint64_round_to_zero(float16, float_status *status); int64_t float16_to_int64_round_to_zero(float16, float_status *status); -float16 float32_to_float16(float32, flag, float_status *status); -float32 float16_to_float32(float16, flag, float_status *status); -float16 float64_to_float16(float64 a, flag ieee, float_status *status); -float64 float16_to_float64(float16 a, flag ieee, float_status *status); +float16 float32_to_float16(float32, bool ieee, float_status *status); +float32 float16_to_float32(float16, bool ieee, float_status *status); +float16 float64_to_float16(float64 a, bool ieee, float_status *status); +float64 float16_to_float64(float16 a, bool ieee, float_status *status); /*---------------------------------------------------------------------------- | Software half-precision operations. diff --git a/fpu/floatconv.c b/fpu/floatconv.c new file mode 100644 index 0000000000..7268a0e3c5 --- /dev/null +++ b/fpu/floatconv.c @@ -0,0 +1,154 @@ +/* + * Conversions between floating point types + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, see . + */ + +#include "qemu/osdep.h" +#include "fpu/softfloat.h" +#include "soft-fp.h" +#include "soft-fp-specialize.h" +#include "half.h" +#include "single.h" +#include "double.h" +#include "quad.h" + + +#define DO_EXTEND(TYPEI, TYPEO, FI, FO, NI, NO) \ +TYPEO glue(TYPEI, glue(_to_, TYPEO))(TYPEI a, float_status *status) \ +{ \ + FP_DECL_EX; \ + FP_DECL_##FI(A); \ + FP_DECL_##FO(R); \ + TYPEO r; \ + FP_INIT_EXCEPTIONS; \ + FP_UNPACK_RAW_##FI(A, a); \ + FP_EXTEND(FO, FI, NO, NI, R, A); \ + FP_PACK_RAW_##FO(r, R); \ + FP_HANDLE_EXCEPTIONS; \ + return r; \ +} + +DO_EXTEND(float32, float64, S, D, 1, 1) +DO_EXTEND(float32, float128, S, Q, 1, 2) +DO_EXTEND(float64, float128, D, Q, 1, 2) + + +#define DO_TRUNC(TYPEI, TYPEO, FI, FO, NI, NO) \ +TYPEO glue(TYPEI, glue(_to_, TYPEO))(TYPEI a, float_status *status) \ +{ \ + FP_DECL_EX; \ + FP_DECL_##FI(A); \ + FP_DECL_##FO(R); \ + TYPEO r; \ + FP_INIT_EXCEPTIONS; \ + FP_UNPACK_SEMIRAW_##FI(A, a); \ + FP_TRUNC(FO, FI, NO, NI, R, A); \ + FP_PACK_SEMIRAW_##FO(r, R); \ + FP_HANDLE_EXCEPTIONS; \ + return r; \ +} + +DO_TRUNC(float128, float64, Q, D, 2, 1) +DO_TRUNC(float128, float32, Q, S, 2, 1) +DO_TRUNC(float64, float32, D, S, 1, 1) + + +/* Half precision floats come in two formats: standard IEEE and "ARM" format. + * The latter gains extra exponent range by omitting the NaN/Inf encodings. + */ + +#define DO_EXTEND_H(TYPEO, FO) \ +TYPEO glue(float16_to_, TYPEO)(float16 a, bool ieee, float_status *status) \ +{ \ + FP_DECL_EX; \ + FP_DECL_H(A); \ + FP_DECL_##FO(R); \ + TYPEO r; \ + FP_INIT_EXCEPTIONS; \ + FP_UNPACK_RAW_H(A, a); \ + if (!ieee && A_e == _FP_EXPMAX_H) { \ + R_s = A_s; \ + R_e = A_e + _FP_EXPBIAS_##FO - _FP_EXPBIAS_H; \ + R_f = A_f; \ + _FP_FRAC_SLL_1(R, (_FP_FRACBITS_##FO - _FP_FRACBITS_H)); \ + } else { \ + FP_EXTEND(FO, H, 1, 1, R, A); \ + } \ + FP_PACK_RAW_##FO(r, R); \ + FP_HANDLE_EXCEPTIONS; \ + return r; \ +} + +DO_EXTEND_H(float32, S) +DO_EXTEND_H(float64, D) + +#define DO_TRUNC_H(TYPEI, FI) \ +float16 glue(TYPEI, _to_float16)(TYPEI a, bool ieee, float_status *status) \ +{ \ + FP_DECL_EX; \ + FP_DECL_##FI(A); \ + FP_DECL_H(R); \ + float16 r; \ + FP_INIT_EXCEPTIONS; \ + FP_UNPACK_SEMIRAW_##FI(A, a); \ + if (unlikely(!ieee)) { \ + R_s = A_s; \ + if (A_e == _FP_EXPMAX_##FI) { \ + FP_SET_EXCEPTION(FP_EX_INVALID); \ + if (A_f == 0) { \ + /* Inf maps to largest normal. */ \ + R_e = _FP_EXPMAX_H; \ + R_f = (1 << _FP_FRACBITS_H) - 1; \ + } else { \ + /* NaN maps to zero. */ \ + R_e = R_f = 0; \ + } \ + FP_PACK_RAW_H(r, R); \ + goto done; \ + } \ + /* ARM format needs different rounding near max exponent. */ \ + R_e = A_e + _FP_EXPBIAS_H - _FP_EXPBIAS_##FI; \ + if (R_e >= _FP_EXPMAX_H - 1) { \ + _FP_FRAC_SRS_1(A, (_FP_WFRACBITS_##FI - _FP_WFRACBITS_H), \ + _FP_WFRACBITS_##FI); \ + R_f = A_f; \ + _FP_ROUND(1, R); \ + if (R_f & (_FP_OVERFLOW_H >> 1)) { \ + R_f &= ~(_FP_OVERFLOW_H >> 1); \ + R_e++; \ + if (R_e > _FP_EXPMAX_H) { \ + /* Overflow saturates to largest normal. */ \ + FP_SET_EXCEPTION(FP_EX_INVALID); \ + R_e = _FP_EXPMAX_H; \ + R_f = (1 << _FP_FRACBITS_H) - 1; \ + } else { \ + R_f >>= _FP_WORKBITS; \ + } \ + } else { \ + R_f >>= _FP_WORKBITS; \ + } \ + FP_PACK_RAW_H(r, R); \ + goto done; \ + } \ + } \ + FP_TRUNC(H, FI, 1, 1, R, A); \ + FP_PACK_SEMIRAW_H(r, R); \ + done: \ + FP_HANDLE_EXCEPTIONS; \ + return r; \ +} + +DO_TRUNC_H(float64, D) +DO_TRUNC_H(float32, S) diff --git a/fpu/softfloat.c b/fpu/softfloat.c index 2550028d9f..dab9e39480 100644 --- a/fpu/softfloat.c +++ b/fpu/softfloat.c @@ -1278,38 +1278,6 @@ floatx80 int64_to_floatx80(int64_t a, float_status *status) } -/*---------------------------------------------------------------------------- -| Returns the result of converting the single-precision floating-point value -| `a' to the double-precision floating-point format. The conversion is -| performed according to the IEC/IEEE Standard for Binary Floating-Point -| Arithmetic. -*----------------------------------------------------------------------------*/ - -float64 float32_to_float64(float32 a, float_status *status) -{ - flag aSign; - int aExp; - uint32_t aSig; - a = float32_squash_input_denormal(a, status); - - aSig = extractFloat32Frac( a ); - aExp = extractFloat32Exp( a ); - aSign = extractFloat32Sign( a ); - if ( aExp == 0xFF ) { - if (aSig) { - return commonNaNToFloat64(float32ToCommonNaN(a, status), status); - } - return packFloat64( aSign, 0x7FF, 0 ); - } - if ( aExp == 0 ) { - if ( aSig == 0 ) return packFloat64( aSign, 0, 0 ); - normalizeFloat32Subnormal( aSig, &aExp, &aSig ); - --aExp; - } - return packFloat64( aSign, aExp + 0x380, ( (uint64_t) aSig )<<29 ); - -} - /*---------------------------------------------------------------------------- | Returns the result of converting the single-precision floating-point value | `a' to the extended double-precision floating-point format. The conversion @@ -1342,38 +1310,6 @@ floatx80 float32_to_floatx80(float32 a, float_status *status) } -/*---------------------------------------------------------------------------- -| Returns the result of converting the single-precision floating-point value -| `a' to the double-precision floating-point format. The conversion is -| performed according to the IEC/IEEE Standard for Binary Floating-Point -| Arithmetic. -*----------------------------------------------------------------------------*/ - -float128 float32_to_float128(float32 a, float_status *status) -{ - flag aSign; - int aExp; - uint32_t aSig; - - a = float32_squash_input_denormal(a, status); - aSig = extractFloat32Frac( a ); - aExp = extractFloat32Exp( a ); - aSign = extractFloat32Sign( a ); - if ( aExp == 0xFF ) { - if (aSig) { - return commonNaNToFloat128(float32ToCommonNaN(a, status), status); - } - return packFloat128( aSign, 0x7FFF, 0, 0 ); - } - if ( aExp == 0 ) { - if ( aSig == 0 ) return packFloat128( aSign, 0, 0, 0 ); - normalizeFloat32Subnormal( aSig, &aExp, &aSig ); - --aExp; - } - return packFloat128( aSign, aExp + 0x3F80, ( (uint64_t) aSig )<<25, 0 ); - -} - /*---------------------------------------------------------------------------- | Rounds the single-precision floating-point value `a' to an integer, and | returns the result as a single-precision floating-point value. The @@ -1915,172 +1851,6 @@ float32 float32_log2(float32 a, float_status *status) return normalizeRoundAndPackFloat32(zSign, 0x85, zSig, status); } -/*---------------------------------------------------------------------------- -| Returns the result of converting the double-precision floating-point value -| `a' to the single-precision floating-point format. The conversion is -| performed according to the IEC/IEEE Standard for Binary Floating-Point -| Arithmetic. -*----------------------------------------------------------------------------*/ - -float32 float64_to_float32(float64 a, float_status *status) -{ - flag aSign; - int aExp; - uint64_t aSig; - uint32_t zSig; - a = float64_squash_input_denormal(a, status); - - aSig = extractFloat64Frac( a ); - aExp = extractFloat64Exp( a ); - aSign = extractFloat64Sign( a ); - if ( aExp == 0x7FF ) { - if (aSig) { - return commonNaNToFloat32(float64ToCommonNaN(a, status), status); - } - return packFloat32( aSign, 0xFF, 0 ); - } - shift64RightJamming( aSig, 22, &aSig ); - zSig = aSig; - if ( aExp || zSig ) { - zSig |= 0x40000000; - aExp -= 0x381; - } - return roundAndPackFloat32(aSign, aExp, zSig, status); - -} - - -/*---------------------------------------------------------------------------- -| Packs the sign `zSign', exponent `zExp', and significand `zSig' into a -| half-precision floating-point value, returning the result. After being -| shifted into the proper positions, the three fields are simply added -| together to form the result. This means that any integer portion of `zSig' -| will be added into the exponent. Since a properly normalized significand -| will have an integer portion equal to 1, the `zExp' input should be 1 less -| than the desired result exponent whenever `zSig' is a complete, normalized -| significand. -*----------------------------------------------------------------------------*/ -static float16 packFloat16(flag zSign, int zExp, uint16_t zSig) -{ - return make_float16( - (((uint32_t)zSign) << 15) + (((uint32_t)zExp) << 10) + zSig); -} - -/*---------------------------------------------------------------------------- -| Takes an abstract floating-point value having sign `zSign', exponent `zExp', -| and significand `zSig', and returns the proper half-precision floating- -| point value corresponding to the abstract input. Ordinarily, the abstract -| value is simply rounded and packed into the half-precision format, with -| the inexact exception raised if the abstract input cannot be represented -| exactly. However, if the abstract value is too large, the overflow and -| inexact exceptions are raised and an infinity or maximal finite value is -| returned. If the abstract value is too small, the input value is rounded to -| a subnormal number, and the underflow and inexact exceptions are raised if -| the abstract input cannot be represented exactly as a subnormal half- -| precision floating-point number. -| The `ieee' flag indicates whether to use IEEE standard half precision, or -| ARM-style "alternative representation", which omits the NaN and Inf -| encodings in order to raise the maximum representable exponent by one. -| The input significand `zSig' has its binary point between bits 22 -| and 23, which is 13 bits to the left of the usual location. This shifted -| significand must be normalized or smaller. If `zSig' is not normalized, -| `zExp' must be 0; in that case, the result returned is a subnormal number, -| and it must not require rounding. In the usual case that `zSig' is -| normalized, `zExp' must be 1 less than the ``true'' floating-point exponent. -| Note the slightly odd position of the binary point in zSig compared with the -| other roundAndPackFloat functions. This should probably be fixed if we -| need to implement more float16 routines than just conversion. -| The handling of underflow and overflow follows the IEC/IEEE Standard for -| Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -static float16 roundAndPackFloat16(flag zSign, int zExp, - uint32_t zSig, flag ieee, - float_status *status) -{ - int maxexp = ieee ? 29 : 30; - uint32_t mask; - uint32_t increment; - bool rounding_bumps_exp; - bool is_tiny = false; - - /* Calculate the mask of bits of the mantissa which are not - * representable in half-precision and will be lost. - */ - if (zExp < 1) { - /* Will be denormal in halfprec */ - mask = 0x00ffffff; - if (zExp >= -11) { - mask >>= 11 + zExp; - } - } else { - /* Normal number in halfprec */ - mask = 0x00001fff; - } - - switch (status->float_rounding_mode) { - case float_round_nearest_even: - increment = (mask + 1) >> 1; - if ((zSig & mask) == increment) { - increment = zSig & (increment << 1); - } - break; - case float_round_ties_away: - increment = (mask + 1) >> 1; - break; - case float_round_up: - increment = zSign ? 0 : mask; - break; - case float_round_down: - increment = zSign ? mask : 0; - break; - default: /* round_to_zero */ - increment = 0; - break; - } - - rounding_bumps_exp = (zSig + increment >= 0x01000000); - - if (zExp > maxexp || (zExp == maxexp && rounding_bumps_exp)) { - if (ieee) { - float_raise(float_flag_overflow | float_flag_inexact, status); - return packFloat16(zSign, 0x1f, 0); - } else { - float_raise(float_flag_invalid, status); - return packFloat16(zSign, 0x1f, 0x3ff); - } - } - - if (zExp < 0) { - /* Note that flush-to-zero does not affect half-precision results */ - is_tiny = - (status->float_detect_tininess == float_tininess_before_rounding) - || (zExp < -1) - || (!rounding_bumps_exp); - } - if (zSig & mask) { - float_raise(float_flag_inexact, status); - if (is_tiny) { - float_raise(float_flag_underflow, status); - } - } - - zSig += increment; - if (rounding_bumps_exp) { - zSig >>= 1; - zExp++; - } - - if (zExp < -10) { - return packFloat16(zSign, 0, 0); - } - if (zExp < 0) { - zSig >>= -zExp; - zExp = 0; - } - return packFloat16(zSign, zExp, zSig >> 13); -} - /*---------------------------------------------------------------------------- | If `a' is denormal and we are in flush-to-zero mode then set the | input-denormal exception and return zero. Otherwise just return the value. @@ -2096,163 +1866,6 @@ float16 float16_squash_input_denormal(float16 a, float_status *status) return a; } -static void normalizeFloat16Subnormal(uint32_t aSig, int *zExpPtr, - uint32_t *zSigPtr) -{ - int8_t shiftCount = countLeadingZeros32(aSig) - 21; - *zSigPtr = aSig << shiftCount; - *zExpPtr = 1 - shiftCount; -} - -/* Half precision floats come in two formats: standard IEEE and "ARM" format. - The latter gains extra exponent range by omitting the NaN/Inf encodings. */ - -float32 float16_to_float32(float16 a, flag ieee, float_status *status) -{ - flag aSign; - int aExp; - uint32_t aSig; - - aSign = extractFloat16Sign(a); - aExp = extractFloat16Exp(a); - aSig = extractFloat16Frac(a); - - if (aExp == 0x1f && ieee) { - if (aSig) { - return commonNaNToFloat32(float16ToCommonNaN(a, status), status); - } - return packFloat32(aSign, 0xff, 0); - } - if (aExp == 0) { - if (aSig == 0) { - return packFloat32(aSign, 0, 0); - } - - normalizeFloat16Subnormal(aSig, &aExp, &aSig); - aExp--; - } - return packFloat32( aSign, aExp + 0x70, aSig << 13); -} - -float16 float32_to_float16(float32 a, flag ieee, float_status *status) -{ - flag aSign; - int aExp; - uint32_t aSig; - - a = float32_squash_input_denormal(a, status); - - aSig = extractFloat32Frac( a ); - aExp = extractFloat32Exp( a ); - aSign = extractFloat32Sign( a ); - if ( aExp == 0xFF ) { - if (aSig) { - /* Input is a NaN */ - if (!ieee) { - float_raise(float_flag_invalid, status); - return packFloat16(aSign, 0, 0); - } - return commonNaNToFloat16( - float32ToCommonNaN(a, status), status); - } - /* Infinity */ - if (!ieee) { - float_raise(float_flag_invalid, status); - return packFloat16(aSign, 0x1f, 0x3ff); - } - return packFloat16(aSign, 0x1f, 0); - } - if (aExp == 0 && aSig == 0) { - return packFloat16(aSign, 0, 0); - } - /* Decimal point between bits 22 and 23. Note that we add the 1 bit - * even if the input is denormal; however this is harmless because - * the largest possible single-precision denormal is still smaller - * than the smallest representable half-precision denormal, and so we - * will end up ignoring aSig and returning via the "always return zero" - * codepath. - */ - aSig |= 0x00800000; - aExp -= 0x71; - - return roundAndPackFloat16(aSign, aExp, aSig, ieee, status); -} - -float64 float16_to_float64(float16 a, flag ieee, float_status *status) -{ - flag aSign; - int aExp; - uint32_t aSig; - - aSign = extractFloat16Sign(a); - aExp = extractFloat16Exp(a); - aSig = extractFloat16Frac(a); - - if (aExp == 0x1f && ieee) { - if (aSig) { - return commonNaNToFloat64( - float16ToCommonNaN(a, status), status); - } - return packFloat64(aSign, 0x7ff, 0); - } - if (aExp == 0) { - if (aSig == 0) { - return packFloat64(aSign, 0, 0); - } - - normalizeFloat16Subnormal(aSig, &aExp, &aSig); - aExp--; - } - return packFloat64(aSign, aExp + 0x3f0, ((uint64_t)aSig) << 42); -} - -float16 float64_to_float16(float64 a, flag ieee, float_status *status) -{ - flag aSign; - int aExp; - uint64_t aSig; - uint32_t zSig; - - a = float64_squash_input_denormal(a, status); - - aSig = extractFloat64Frac(a); - aExp = extractFloat64Exp(a); - aSign = extractFloat64Sign(a); - if (aExp == 0x7FF) { - if (aSig) { - /* Input is a NaN */ - if (!ieee) { - float_raise(float_flag_invalid, status); - return packFloat16(aSign, 0, 0); - } - return commonNaNToFloat16( - float64ToCommonNaN(a, status), status); - } - /* Infinity */ - if (!ieee) { - float_raise(float_flag_invalid, status); - return packFloat16(aSign, 0x1f, 0x3ff); - } - return packFloat16(aSign, 0x1f, 0); - } - shift64RightJamming(aSig, 29, &aSig); - zSig = aSig; - if (aExp == 0 && zSig == 0) { - return packFloat16(aSign, 0, 0); - } - /* Decimal point between bits 22 and 23. Note that we add the 1 bit - * even if the input is denormal; however this is harmless because - * the largest possible single-precision denormal is still smaller - * than the smallest representable half-precision denormal, and so we - * will end up ignoring aSig and returning via the "always return zero" - * codepath. - */ - zSig |= 0x00800000; - aExp -= 0x3F1; - - return roundAndPackFloat16(aSign, aExp, zSig, ieee, status); -} - /*---------------------------------------------------------------------------- | Returns the result of converting the double-precision floating-point value | `a' to the extended double-precision floating-point format. The conversion @@ -2285,40 +1898,6 @@ floatx80 float64_to_floatx80(float64 a, float_status *status) aSign, aExp + 0x3C00, ( aSig | LIT64( 0x0010000000000000 ) )<<11 ); } - -/*---------------------------------------------------------------------------- -| Returns the result of converting the double-precision floating-point value -| `a' to the quadruple-precision floating-point format. The conversion is -| performed according to the IEC/IEEE Standard for Binary Floating-Point -| Arithmetic. -*----------------------------------------------------------------------------*/ - -float128 float64_to_float128(float64 a, float_status *status) -{ - flag aSign; - int aExp; - uint64_t aSig, zSig0, zSig1; - - a = float64_squash_input_denormal(a, status); - aSig = extractFloat64Frac( a ); - aExp = extractFloat64Exp( a ); - aSign = extractFloat64Sign( a ); - if ( aExp == 0x7FF ) { - if (aSig) { - return commonNaNToFloat128(float64ToCommonNaN(a, status), status); - } - return packFloat128( aSign, 0x7FFF, 0, 0 ); - } - if ( aExp == 0 ) { - if ( aSig == 0 ) return packFloat128( aSign, 0, 0, 0 ); - normalizeFloat64Subnormal( aSig, &aExp, &aSig ); - --aExp; - } - shift128Right( aSig, 0, 4, &zSig0, &zSig1 ); - return packFloat128( aSign, aExp + 0x3C00, zSig0, zSig1 ); - -} - /*---------------------------------------------------------------------------- | Rounds the double-precision floating-point value `a' to an integer, and | returns the result as a double-precision floating-point value. The @@ -3680,74 +3259,6 @@ floatx80 floatx80_sqrt(floatx80 a, float_status *status) 0, zExp, zSig0, zSig1, status); } -/*---------------------------------------------------------------------------- -| Returns the result of converting the quadruple-precision floating-point -| value `a' to the single-precision floating-point format. The conversion -| is performed according to the IEC/IEEE Standard for Binary Floating-Point -| Arithmetic. -*----------------------------------------------------------------------------*/ - -float32 float128_to_float32(float128 a, float_status *status) -{ - flag aSign; - int32_t aExp; - uint64_t aSig0, aSig1; - uint32_t zSig; - - aSig1 = extractFloat128Frac1( a ); - aSig0 = extractFloat128Frac0( a ); - aExp = extractFloat128Exp( a ); - aSign = extractFloat128Sign( a ); - if ( aExp == 0x7FFF ) { - if ( aSig0 | aSig1 ) { - return commonNaNToFloat32(float128ToCommonNaN(a, status), status); - } - return packFloat32( aSign, 0xFF, 0 ); - } - aSig0 |= ( aSig1 != 0 ); - shift64RightJamming( aSig0, 18, &aSig0 ); - zSig = aSig0; - if ( aExp || zSig ) { - zSig |= 0x40000000; - aExp -= 0x3F81; - } - return roundAndPackFloat32(aSign, aExp, zSig, status); - -} - -/*---------------------------------------------------------------------------- -| Returns the result of converting the quadruple-precision floating-point -| value `a' to the double-precision floating-point format. The conversion -| is performed according to the IEC/IEEE Standard for Binary Floating-Point -| Arithmetic. -*----------------------------------------------------------------------------*/ - -float64 float128_to_float64(float128 a, float_status *status) -{ - flag aSign; - int32_t aExp; - uint64_t aSig0, aSig1; - - aSig1 = extractFloat128Frac1( a ); - aSig0 = extractFloat128Frac0( a ); - aExp = extractFloat128Exp( a ); - aSign = extractFloat128Sign( a ); - if ( aExp == 0x7FFF ) { - if ( aSig0 | aSig1 ) { - return commonNaNToFloat64(float128ToCommonNaN(a, status), status); - } - return packFloat64( aSign, 0x7FF, 0 ); - } - shortShift128Left( aSig0, aSig1, 14, &aSig0, &aSig1 ); - aSig0 |= ( aSig1 != 0 ); - if ( aExp || aSig0 ) { - aSig0 |= LIT64( 0x4000000000000000 ); - aExp -= 0x3C01; - } - return roundAndPackFloat64(aSign, aExp, aSig0, status); - -} - /*---------------------------------------------------------------------------- | Returns the result of converting the quadruple-precision floating-point | value `a' to the extended double-precision floating-point format. The From patchwork Sun Feb 4 04:11:35 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Richard Henderson X-Patchwork-Id: 126817 Delivered-To: patch@linaro.org Received: by 10.80.172.228 with SMTP id x91csp1231857edc; Sat, 3 Feb 2018 20:33:44 -0800 (PST) X-Google-Smtp-Source: AH8x22670KW/4KqtqcvEk36roMMf2P7IGaHCACAvggdHSTMCe9F8xI/zQrNbHv0zXETRMzEISttq X-Received: by 10.37.209.132 with SMTP id i126mr30948846ybg.29.1517718824821; Sat, 03 Feb 2018 20:33:44 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1517718824; cv=none; d=google.com; s=arc-20160816; b=bPURJqVWuhkMkYj9rW4lIDZSzsJblfi0tqVlGoIp/vNJSC2PswWYVY30o50Tm2XNzV WPTRGA3QQF7TTpKngrTDqNyUJvS3zhrbwxD8CtcA55+XgAVuegfOFb7UahZ0fCXqVlfK 6FTsFpmiCO8nwKq8o/T9Ut+Qkm58ykqgBaqWmna0+5L37YRUJFT73YitlNTxAJSYw4lp TZ39xWA+zB415BlgIcn+7EhIzgNePR5b0UN1noiC3J0zXvHFodQZOUN00LWRNBcpi6VE 6pyyVhonI1CT1LBu1naIufra20TQnT7PtCcu/6L3uQ4W1VcyuziZfdSONAw7XgaZLHj+ UwTw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=sender:errors-to:cc:list-subscribe:list-help:list-post:list-archive :list-unsubscribe:list-id:precedence:subject:references:in-reply-to :message-id:date:to:from:dkim-signature:arc-authentication-results; bh=MOeoFw6nGy7LimqHDDabGfdhRttuZglEUa9wlpEAGo0=; b=c6tzPp1M1OnMzAU5tYxFUmOn85Jp0tnZuJkoLV/hyPGSAp/TFROGdjeaLGaVVD5sAl 5nY5CZJKipXX/LfA2a8BwcwpbdgSy+gS82GM0KSCAccUBV2fMPTgokE0pALboxW9EYGE hDjPEv4m1aE+MTUHgkZaCsF48QSozKHJ7md5HKb6uKstK9vXvrW0IZYtdxHYcNtKBn6w wdK4l9TkYm0QX4jdwtdOX+t95jRdq+rjo8Cmt1CWun3CNsz6khSD4R8liCo/bIeFPlqg zYPesCMYU9dUq4OFHZjnU/u7eFo1Z/AE2jbhXUR9UMEi47SdGzhSHrini9tnnnNtbnFj LMyQ== ARC-Authentication-Results: i=1; mx.google.com; dkim=fail header.i=@linaro.org header.s=google header.b=ehnL8Ah9; spf=pass (google.com: domain of qemu-devel-bounces+patch=linaro.org@nongnu.org designates 2001:4830:134:3::11 as permitted sender) smtp.mailfrom=qemu-devel-bounces+patch=linaro.org@nongnu.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=linaro.org Return-Path: Received: from lists.gnu.org (lists.gnu.org. [2001:4830:134:3::11]) by mx.google.com with ESMTPS id s187si990854ywe.527.2018.02.03.20.33.44 for (version=TLS1 cipher=AES128-SHA bits=128/128); Sat, 03 Feb 2018 20:33:44 -0800 (PST) Received-SPF: pass (google.com: domain of qemu-devel-bounces+patch=linaro.org@nongnu.org designates 2001:4830:134:3::11 as permitted sender) client-ip=2001:4830:134:3::11; Authentication-Results: mx.google.com; dkim=fail header.i=@linaro.org header.s=google header.b=ehnL8Ah9; spf=pass (google.com: domain of qemu-devel-bounces+patch=linaro.org@nongnu.org designates 2001:4830:134:3::11 as permitted sender) smtp.mailfrom=qemu-devel-bounces+patch=linaro.org@nongnu.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=linaro.org Received: from localhost ([::1]:59289 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1eiBzs-0007Bw-6y for patch@linaro.org; Sat, 03 Feb 2018 23:33:44 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:47512) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1eiBf8-00050X-Ul for qemu-devel@nongnu.org; Sat, 03 Feb 2018 23:12:22 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1eiBf5-00057J-5C for qemu-devel@nongnu.org; Sat, 03 Feb 2018 23:12:18 -0500 Received: from mail-pl0-x22e.google.com ([2607:f8b0:400e:c01::22e]:43586) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1eiBf4-00056p-OG for qemu-devel@nongnu.org; Sat, 03 Feb 2018 23:12:15 -0500 Received: by mail-pl0-x22e.google.com with SMTP id f4so9361275plr.10 for ; Sat, 03 Feb 2018 20:12:14 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=MOeoFw6nGy7LimqHDDabGfdhRttuZglEUa9wlpEAGo0=; b=ehnL8Ah9Vd4sQ2ulAD5a/zBnCA3o570CVRgOqM04WiODU6SHiSEtK3+iovEu1at0it q+VxCcDUZtpGMTYd+XneupoiKjU9kZjBfJmT5F9XwGVzAxXya1W6K771KnNAqXER82rK NOUxYnas1aTsGyWRUxCUC6wsptv5gS5TkjYHo= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=MOeoFw6nGy7LimqHDDabGfdhRttuZglEUa9wlpEAGo0=; b=NzO4bIkLlUSKhN7XaEDtf7iLzjSZKbKFaMw9xPM8wrG/RsqecNvX0gFKJU7ykFUCQ1 UizNYDlqlhrBtzedvegRSRQEde9KIBCouPwO9MZr2kbaWiLJrH/DXTybfZqjFf+DZjy9 RKmmOZsal9OhZtSFTQyQwAKvATNDIl8fOLvuFKv9irBW4hK8BDCHD2jsAbOE88cL9qF9 BnTL21ila9b+KrrWjKI0o+EhmGU70e0JGriWzJpVkdO+Ez93bS5k75VDM2IEdRgnnbaw niQa9JQil2cyFQc5c1oKpvKaDCd7w15+3TREYMOsq8oPuOrf96LpsloQVOuNlbO82O2A s0/g== X-Gm-Message-State: AKwxytdZvAShi6n4NqnaGyLcG8HHc3qi9jWWQATbCKIUEx5QeaY6xqwz VYl7ayUu0wZdd9VGxNxQaD8PhJvxBV4= X-Received: by 2002:a17:902:d24:: with SMTP id 33-v6mr39614334plu.40.1517717533164; Sat, 03 Feb 2018 20:12:13 -0800 (PST) Received: from cloudburst.twiddle.net (174-21-6-47.tukw.qwest.net. [174.21.6.47]) by smtp.gmail.com with ESMTPSA id k3sm1399425pgr.12.2018.02.03.20.12.11 (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Sat, 03 Feb 2018 20:12:11 -0800 (PST) From: Richard Henderson To: qemu-devel@nongnu.org Date: Sat, 3 Feb 2018 20:11:35 -0800 Message-Id: <20180204041136.17525-24-richard.henderson@linaro.org> X-Mailer: git-send-email 2.14.3 In-Reply-To: <20180204041136.17525-1-richard.henderson@linaro.org> References: <20180204041136.17525-1-richard.henderson@linaro.org> X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 2607:f8b0:400e:c01::22e Subject: [Qemu-devel] [PATCH 23/24] fpu: Implement muladd with soft-fp.h X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: peter.maydell@linaro.org, cota@braap.org, alex.bennee@linaro.org, hsp.cat7@gmail.com Errors-To: qemu-devel-bounces+patch=linaro.org@nongnu.org Sender: "Qemu-devel" Add routines for float16 and float128. Signed-off-by: Richard Henderson --- fpu/soft-fp-specialize.h | 123 ++++++++++++ fpu/softfloat-specialize.h | 228 ---------------------- include/fpu/softfloat.h | 3 + fpu/floatxx.inc.c | 68 +++++++ fpu/softfloat.c | 473 --------------------------------------------- 5 files changed, 194 insertions(+), 701 deletions(-) -- 2.14.3 diff --git a/fpu/soft-fp-specialize.h b/fpu/soft-fp-specialize.h index 869f5a0195..10061595a3 100644 --- a/fpu/soft-fp-specialize.h +++ b/fpu/soft-fp-specialize.h @@ -129,3 +129,126 @@ static inline int pick_nan(int a_nan, int b_nan, bool a_larger, return a_larger ^ 1; #endif } + + +/* + * Select which NaN to propagate for a three-input FMA operation. + * + * A_SNAN etc are set iff the operand is an SNaN; QNaN can be + * determined from (A_CLS == FP_CLS_NAN && !A_SNAN). + * + * The return value is 0 to select NaN A, 1 for NaN B, 2 for NaN C, + * or 3 to build a new default QNaN. + * + * Note that signalling NaNs are always squashed to quiet NaNs + * by the caller before returning them. + */ +static inline int pick_nan_muladd(int a_cls, bool a_snan, + int b_cls, bool b_snan, + int c_cls, bool c_snan, + float_status *status) +{ + /* True if the inner product would itself generate a default NaN. */ + bool infzero = (a_cls == FP_CLS_INF && b_cls == FP_CLS_ZERO) + || (b_cls == FP_CLS_INF && a_cls == FP_CLS_ZERO); + +#if defined(TARGET_ARM) + /* For ARM, the (inf,zero,qnan) case sets InvalidOp + * and returns the default NaN. + */ + if (infzero && c_cls == FP_CLS_NAN && !c_snan) { + float_raise(float_flag_invalid, status); + return 3; + } + + /* This looks different from the ARM ARM pseudocode, because the ARM ARM + * puts the operands to a fused mac operation (a*b)+c in the order c,a,b. + */ + if (c_snan) { + return 2; + } else if (a_snan) { + return 0; + } else if (b_snan) { + return 1; + } else if (c_cls == FP_CLS_NAN) { + return 2; + } else if (a_cls == FP_CLS_NAN) { + return 0; + } else { + return 1; + } +#elif defined(TARGET_MIPS) + /* For MIPS, the (inf,zero,*) case sets InvalidOp + * and returns the default NaN. + */ + if (infzero) { + float_raise(float_flag_invalid, status); + return 3; + } + if (status->snan_bit_is_one) { + /* Prefer sNaN over qNaN, in the a, b, c order. */ + if (a_snan) { + return 0; + } else if (b_snan) { + return 1; + } else if (c_snan) { + return 2; + } else if (a_cls == FP_CLS_NAN) { + return 0; + } else if (b_cls == FP_CLS_NAN) { + return 1; + } else { + return 2; + } + } else { + /* Prefer sNaN over qNaN, in the c, a, b order. */ + if (c_snan) { + return 2; + } else if (a_snan) { + return 0; + } else if (b_snan) { + return 1; + } else if (c_cls == FP_CLS_NAN) { + return 2; + } else if (a_cls == FP_CLS_NAN) { + return 0; + } else { + return 1; + } + } +#elif defined(TARGET_PPC) + /* For PPC, the (inf,zero,qnan) case sets InvalidOp, but we prefer + * to return an input NaN if we have one (ie c) rather than generating + * a default NaN + */ + if (infzero) { + float_raise(float_flag_invalid, status); + return 2; + } + + /* If fRA is a NaN return it; otherwise if fRB is a NaN return it; + * otherwise return fRC. Note that muladd on PPC is (fRA * fRC) + frB + */ + if (a_cls == FP_CLS_NAN) { + return 0; + } else if (c_cls == FP_CLS_NAN) { + return 2; + } else { + return 1; + } +#else + /* A default implementation, which is unlikely to match any + * real implementation. + */ + if (infzero) { + float_raise(float_flag_invalid, status); + } + if (a_cls == FP_CLS_NAN) { + return 0; + } else if (b_cls == FP_CLS_NAN) { + return 1; + } else { + return 2; + } +#endif +} diff --git a/fpu/softfloat-specialize.h b/fpu/softfloat-specialize.h index ffc0264018..ce5755f93d 100644 --- a/fpu/softfloat-specialize.h +++ b/fpu/softfloat-specialize.h @@ -522,130 +522,6 @@ static int pickNaN(flag aIsQNaN, flag aIsSNaN, flag bIsQNaN, flag bIsSNaN, } #endif -/*---------------------------------------------------------------------------- -| Select which NaN to propagate for a three-input operation. -| For the moment we assume that no CPU needs the 'larger significand' -| information. -| Return values : 0 : a; 1 : b; 2 : c; 3 : default-NaN -*----------------------------------------------------------------------------*/ -#if defined(TARGET_ARM) -static int pickNaNMulAdd(flag aIsQNaN, flag aIsSNaN, flag bIsQNaN, flag bIsSNaN, - flag cIsQNaN, flag cIsSNaN, flag infzero, - float_status *status) -{ - /* For ARM, the (inf,zero,qnan) case sets InvalidOp and returns - * the default NaN - */ - if (infzero && cIsQNaN) { - float_raise(float_flag_invalid, status); - return 3; - } - - /* This looks different from the ARM ARM pseudocode, because the ARM ARM - * puts the operands to a fused mac operation (a*b)+c in the order c,a,b. - */ - if (cIsSNaN) { - return 2; - } else if (aIsSNaN) { - return 0; - } else if (bIsSNaN) { - return 1; - } else if (cIsQNaN) { - return 2; - } else if (aIsQNaN) { - return 0; - } else { - return 1; - } -} -#elif defined(TARGET_MIPS) -static int pickNaNMulAdd(flag aIsQNaN, flag aIsSNaN, flag bIsQNaN, flag bIsSNaN, - flag cIsQNaN, flag cIsSNaN, flag infzero, - float_status *status) -{ - /* For MIPS, the (inf,zero,qnan) case sets InvalidOp and returns - * the default NaN - */ - if (infzero) { - float_raise(float_flag_invalid, status); - return 3; - } - - if (status->snan_bit_is_one) { - /* Prefer sNaN over qNaN, in the a, b, c order. */ - if (aIsSNaN) { - return 0; - } else if (bIsSNaN) { - return 1; - } else if (cIsSNaN) { - return 2; - } else if (aIsQNaN) { - return 0; - } else if (bIsQNaN) { - return 1; - } else { - return 2; - } - } else { - /* Prefer sNaN over qNaN, in the c, a, b order. */ - if (cIsSNaN) { - return 2; - } else if (aIsSNaN) { - return 0; - } else if (bIsSNaN) { - return 1; - } else if (cIsQNaN) { - return 2; - } else if (aIsQNaN) { - return 0; - } else { - return 1; - } - } -} -#elif defined(TARGET_PPC) -static int pickNaNMulAdd(flag aIsQNaN, flag aIsSNaN, flag bIsQNaN, flag bIsSNaN, - flag cIsQNaN, flag cIsSNaN, flag infzero, - float_status *status) -{ - /* For PPC, the (inf,zero,qnan) case sets InvalidOp, but we prefer - * to return an input NaN if we have one (ie c) rather than generating - * a default NaN - */ - if (infzero) { - float_raise(float_flag_invalid, status); - return 2; - } - - /* If fRA is a NaN return it; otherwise if fRB is a NaN return it; - * otherwise return fRC. Note that muladd on PPC is (fRA * fRC) + frB - */ - if (aIsSNaN || aIsQNaN) { - return 0; - } else if (cIsSNaN || cIsQNaN) { - return 2; - } else { - return 1; - } -} -#else -/* A default implementation: prefer a to b to c. - * This is unlikely to actually match any real implementation. - */ -static int pickNaNMulAdd(flag aIsQNaN, flag aIsSNaN, flag bIsQNaN, flag bIsSNaN, - flag cIsQNaN, flag cIsSNaN, flag infzero, - float_status *status) -{ - if (aIsSNaN || aIsQNaN) { - return 0; - } else if (bIsSNaN || bIsQNaN) { - return 1; - } else { - return 2; - } -} -#endif - /*---------------------------------------------------------------------------- | Takes two single-precision floating-point values `a' and `b', one of which | is a NaN, and returns the appropriate NaN result. If either `a' or `b' is a @@ -689,58 +565,6 @@ static float32 propagateFloat32NaN(float32 a, float32 b, float_status *status) } } -/*---------------------------------------------------------------------------- -| Takes three single-precision floating-point values `a', `b' and `c', one of -| which is a NaN, and returns the appropriate NaN result. If any of `a', -| `b' or `c' is a signaling NaN, the invalid exception is raised. -| The input infzero indicates whether a*b was 0*inf or inf*0 (in which case -| obviously c is a NaN, and whether to propagate c or some other NaN is -| implementation defined). -*----------------------------------------------------------------------------*/ - -static float32 propagateFloat32MulAddNaN(float32 a, float32 b, - float32 c, flag infzero, - float_status *status) -{ - flag aIsQuietNaN, aIsSignalingNaN, bIsQuietNaN, bIsSignalingNaN, - cIsQuietNaN, cIsSignalingNaN; - int which; - - aIsQuietNaN = float32_is_quiet_nan(a, status); - aIsSignalingNaN = float32_is_signaling_nan(a, status); - bIsQuietNaN = float32_is_quiet_nan(b, status); - bIsSignalingNaN = float32_is_signaling_nan(b, status); - cIsQuietNaN = float32_is_quiet_nan(c, status); - cIsSignalingNaN = float32_is_signaling_nan(c, status); - - if (aIsSignalingNaN | bIsSignalingNaN | cIsSignalingNaN) { - float_raise(float_flag_invalid, status); - } - - which = pickNaNMulAdd(aIsQuietNaN, aIsSignalingNaN, - bIsQuietNaN, bIsSignalingNaN, - cIsQuietNaN, cIsSignalingNaN, infzero, status); - - if (status->default_nan_mode) { - /* Note that this check is after pickNaNMulAdd so that function - * has an opportunity to set the Invalid flag. - */ - return float32_default_nan(status); - } - - switch (which) { - case 0: - return float32_maybe_silence_nan(a, status); - case 1: - return float32_maybe_silence_nan(b, status); - case 2: - return float32_maybe_silence_nan(c, status); - case 3: - default: - return float32_default_nan(status); - } -} - #ifdef NO_SIGNALING_NANS int float64_is_quiet_nan(float64 a_, float_status *status) { @@ -896,58 +720,6 @@ static float64 propagateFloat64NaN(float64 a, float64 b, float_status *status) } } -/*---------------------------------------------------------------------------- -| Takes three double-precision floating-point values `a', `b' and `c', one of -| which is a NaN, and returns the appropriate NaN result. If any of `a', -| `b' or `c' is a signaling NaN, the invalid exception is raised. -| The input infzero indicates whether a*b was 0*inf or inf*0 (in which case -| obviously c is a NaN, and whether to propagate c or some other NaN is -| implementation defined). -*----------------------------------------------------------------------------*/ - -static float64 propagateFloat64MulAddNaN(float64 a, float64 b, - float64 c, flag infzero, - float_status *status) -{ - flag aIsQuietNaN, aIsSignalingNaN, bIsQuietNaN, bIsSignalingNaN, - cIsQuietNaN, cIsSignalingNaN; - int which; - - aIsQuietNaN = float64_is_quiet_nan(a, status); - aIsSignalingNaN = float64_is_signaling_nan(a, status); - bIsQuietNaN = float64_is_quiet_nan(b, status); - bIsSignalingNaN = float64_is_signaling_nan(b, status); - cIsQuietNaN = float64_is_quiet_nan(c, status); - cIsSignalingNaN = float64_is_signaling_nan(c, status); - - if (aIsSignalingNaN | bIsSignalingNaN | cIsSignalingNaN) { - float_raise(float_flag_invalid, status); - } - - which = pickNaNMulAdd(aIsQuietNaN, aIsSignalingNaN, - bIsQuietNaN, bIsSignalingNaN, - cIsQuietNaN, cIsSignalingNaN, infzero, status); - - if (status->default_nan_mode) { - /* Note that this check is after pickNaNMulAdd so that function - * has an opportunity to set the Invalid flag. - */ - return float64_default_nan(status); - } - - switch (which) { - case 0: - return float64_maybe_silence_nan(a, status); - case 1: - return float64_maybe_silence_nan(b, status); - case 2: - return float64_maybe_silence_nan(c, status); - case 3: - default: - return float64_default_nan(status); - } -} - #ifdef NO_SIGNALING_NANS int floatx80_is_quiet_nan(floatx80 a_, float_status *status) { diff --git a/include/fpu/softfloat.h b/include/fpu/softfloat.h index 53468eec1b..3a2d148651 100644 --- a/include/fpu/softfloat.h +++ b/include/fpu/softfloat.h @@ -250,6 +250,7 @@ float16 float16_add(float16, float16, float_status *status); float16 float16_sub(float16, float16, float_status *status); float16 float16_mul(float16, float16, float_status *status); float16 float16_div(float16, float16, float_status *status); +float16 float16_muladd(float16, float16, float16, int, float_status *status); float16 float16_sqrt(float16, float_status *status); int float16_eq(float16, float16, float_status *status); int float16_le(float16, float16, float_status *status); @@ -679,6 +680,8 @@ float128 float128_sub(float128, float128, float_status *status); float128 float128_mul(float128, float128, float_status *status); float128 float128_div(float128, float128, float_status *status); float128 float128_rem(float128, float128, float_status *status); +float128 float128_muladd(float128, float128, float128, int, + float_status *status); float128 float128_sqrt(float128, float_status *status); int float128_eq(float128, float128, float_status *status); int float128_le(float128, float128, float_status *status); diff --git a/fpu/floatxx.inc.c b/fpu/floatxx.inc.c index 8c009dd966..a4b305e1ff 100644 --- a/fpu/floatxx.inc.c +++ b/fpu/floatxx.inc.c @@ -30,6 +30,8 @@ _FP_CHOOSENAN(fs, wc, R, A, B, OP) #define FP_SETQNAN(fs, wc, X) \ _FP_SETQNAN(fs, wc, X) +#define FP_FRAC_SNANP(fs, X) \ + _FP_FRAC_SNANP(fs, X) #define FP_ADD_INTERNAL(fs, wc, R, A, B, OP) \ _FP_ADD_INTERNAL(fs, wc, R, A, B, '-') @@ -145,6 +147,72 @@ FLOATXX glue(FLOATXX,_scalbn)(FLOATXX a, int n, float_status *status) return a; } +FLOATXX glue(FLOATXX,_muladd)(FLOATXX a, FLOATXX b, FLOATXX c, int flags, + float_status *status) +{ + FP_DECL_EX; + glue(FP_DECL_, FS)(A); + glue(FP_DECL_, FS)(B); + glue(FP_DECL_, FS)(C); + glue(FP_DECL_, FS)(R); + FLOATXX r; + + FP_INIT_ROUNDMODE; + glue(FP_UNPACK_, FS)(A, a); + glue(FP_UNPACK_, FS)(B, b); + glue(FP_UNPACK_, FS)(C, c); + + /* R_e is not set in cases where it is not used in packing, but the + * compiler does not see that it is set in all cases where it is used, + * resulting in warnings that it may be used uninitialized. + * For QEMU, we will usually read it before packing, for halve_result. + */ + R_e = 0; + + /* _FP_FMA does pair-wise calls to _FP_CHOOSENAN. For proper + emulation of the target cpu we need to do better than that. */ + if (A_c == FP_CLS_NAN || B_c == FP_CLS_NAN || C_c == FP_CLS_NAN) { + bool a_snan = A_c == FP_CLS_NAN && FP_FRAC_SNANP(FS, A); + bool b_snan = B_c == FP_CLS_NAN && FP_FRAC_SNANP(FS, B); + bool c_snan = C_c == FP_CLS_NAN && FP_FRAC_SNANP(FS, C); + int p = pick_nan_muladd(A_c, a_snan, B_c, b_snan, C_c, c_snan, status); + + R_c = FP_CLS_NAN; + switch (p) { + case 0: + R_s = A_s; + glue(_FP_FRAC_COPY_, WC)(R, A); + break; + case 1: + R_s = B_s; + glue(_FP_FRAC_COPY_, WC)(R, B); + break; + case 2: + R_s = C_s; + glue(_FP_FRAC_COPY_, WC)(R, C); + break; + default: + R_s = glue(_FP_NANSIGN_, FS); + glue(_FP_FRAC_SET_, WC)(R, glue(_FP_NANFRAC_, FS)); + break; + } + /* Any SNaN result will be silenced during _FP_PACK_CANONICAL. */ + } else { + C_s ^= (flags & float_muladd_negate_c) != 0; + B_s ^= (flags & float_muladd_negate_product) != 0; + + glue(FP_FMA_, FS)(R, A, B, C); + + R_s ^= ((flags & float_muladd_negate_result) && R_c != FP_CLS_NAN); + R_e -= ((flags & float_muladd_halve_result) && R_c == FP_CLS_NORMAL); + } + + glue(FP_PACK_, FS)(r, R); + FP_HANDLE_EXCEPTIONS; + + return r; +} + #define DO_FLOAT_TO_INT(NAME, SZ, FP_TO_INT_WHICH) \ int##SZ##_t NAME(FLOATXX a, float_status *status) \ { \ diff --git a/fpu/softfloat.c b/fpu/softfloat.c index dab9e39480..47b9dd9bd3 100644 --- a/fpu/softfloat.c +++ b/fpu/softfloat.c @@ -1493,232 +1493,6 @@ float32 float32_rem(float32 a, float32 b, float_status *status) return normalizeRoundAndPackFloat32(aSign ^ zSign, bExp, aSig, status); } -/*---------------------------------------------------------------------------- -| Returns the result of multiplying the single-precision floating-point values -| `a' and `b' then adding 'c', with no intermediate rounding step after the -| multiplication. The operation is performed according to the IEC/IEEE -| Standard for Binary Floating-Point Arithmetic 754-2008. -| The flags argument allows the caller to select negation of the -| addend, the intermediate product, or the final result. (The difference -| between this and having the caller do a separate negation is that negating -| externally will flip the sign bit on NaNs.) -*----------------------------------------------------------------------------*/ - -float32 float32_muladd(float32 a, float32 b, float32 c, int flags, - float_status *status) -{ - flag aSign, bSign, cSign, zSign; - int aExp, bExp, cExp, pExp, zExp, expDiff; - uint32_t aSig, bSig, cSig; - flag pInf, pZero, pSign; - uint64_t pSig64, cSig64, zSig64; - uint32_t pSig; - int shiftcount; - flag signflip, infzero; - - a = float32_squash_input_denormal(a, status); - b = float32_squash_input_denormal(b, status); - c = float32_squash_input_denormal(c, status); - aSig = extractFloat32Frac(a); - aExp = extractFloat32Exp(a); - aSign = extractFloat32Sign(a); - bSig = extractFloat32Frac(b); - bExp = extractFloat32Exp(b); - bSign = extractFloat32Sign(b); - cSig = extractFloat32Frac(c); - cExp = extractFloat32Exp(c); - cSign = extractFloat32Sign(c); - - infzero = ((aExp == 0 && aSig == 0 && bExp == 0xff && bSig == 0) || - (aExp == 0xff && aSig == 0 && bExp == 0 && bSig == 0)); - - /* It is implementation-defined whether the cases of (0,inf,qnan) - * and (inf,0,qnan) raise InvalidOperation or not (and what QNaN - * they return if they do), so we have to hand this information - * off to the target-specific pick-a-NaN routine. - */ - if (((aExp == 0xff) && aSig) || - ((bExp == 0xff) && bSig) || - ((cExp == 0xff) && cSig)) { - return propagateFloat32MulAddNaN(a, b, c, infzero, status); - } - - if (infzero) { - float_raise(float_flag_invalid, status); - return float32_default_nan(status); - } - - if (flags & float_muladd_negate_c) { - cSign ^= 1; - } - - signflip = (flags & float_muladd_negate_result) ? 1 : 0; - - /* Work out the sign and type of the product */ - pSign = aSign ^ bSign; - if (flags & float_muladd_negate_product) { - pSign ^= 1; - } - pInf = (aExp == 0xff) || (bExp == 0xff); - pZero = ((aExp | aSig) == 0) || ((bExp | bSig) == 0); - - if (cExp == 0xff) { - if (pInf && (pSign ^ cSign)) { - /* addition of opposite-signed infinities => InvalidOperation */ - float_raise(float_flag_invalid, status); - return float32_default_nan(status); - } - /* Otherwise generate an infinity of the same sign */ - return packFloat32(cSign ^ signflip, 0xff, 0); - } - - if (pInf) { - return packFloat32(pSign ^ signflip, 0xff, 0); - } - - if (pZero) { - if (cExp == 0) { - if (cSig == 0) { - /* Adding two exact zeroes */ - if (pSign == cSign) { - zSign = pSign; - } else if (status->float_rounding_mode == float_round_down) { - zSign = 1; - } else { - zSign = 0; - } - return packFloat32(zSign ^ signflip, 0, 0); - } - /* Exact zero plus a denorm */ - if (status->flush_to_zero) { - float_raise(float_flag_output_denormal, status); - return packFloat32(cSign ^ signflip, 0, 0); - } - } - /* Zero plus something non-zero : just return the something */ - if (flags & float_muladd_halve_result) { - if (cExp == 0) { - normalizeFloat32Subnormal(cSig, &cExp, &cSig); - } - /* Subtract one to halve, and one again because roundAndPackFloat32 - * wants one less than the true exponent. - */ - cExp -= 2; - cSig = (cSig | 0x00800000) << 7; - return roundAndPackFloat32(cSign ^ signflip, cExp, cSig, status); - } - return packFloat32(cSign ^ signflip, cExp, cSig); - } - - if (aExp == 0) { - normalizeFloat32Subnormal(aSig, &aExp, &aSig); - } - if (bExp == 0) { - normalizeFloat32Subnormal(bSig, &bExp, &bSig); - } - - /* Calculate the actual result a * b + c */ - - /* Multiply first; this is easy. */ - /* NB: we subtract 0x7e where float32_mul() subtracts 0x7f - * because we want the true exponent, not the "one-less-than" - * flavour that roundAndPackFloat32() takes. - */ - pExp = aExp + bExp - 0x7e; - aSig = (aSig | 0x00800000) << 7; - bSig = (bSig | 0x00800000) << 8; - pSig64 = (uint64_t)aSig * bSig; - if ((int64_t)(pSig64 << 1) >= 0) { - pSig64 <<= 1; - pExp--; - } - - zSign = pSign ^ signflip; - - /* Now pSig64 is the significand of the multiply, with the explicit bit in - * position 62. - */ - if (cExp == 0) { - if (!cSig) { - /* Throw out the special case of c being an exact zero now */ - shift64RightJamming(pSig64, 32, &pSig64); - pSig = pSig64; - if (flags & float_muladd_halve_result) { - pExp--; - } - return roundAndPackFloat32(zSign, pExp - 1, - pSig, status); - } - normalizeFloat32Subnormal(cSig, &cExp, &cSig); - } - - cSig64 = (uint64_t)cSig << (62 - 23); - cSig64 |= LIT64(0x4000000000000000); - expDiff = pExp - cExp; - - if (pSign == cSign) { - /* Addition */ - if (expDiff > 0) { - /* scale c to match p */ - shift64RightJamming(cSig64, expDiff, &cSig64); - zExp = pExp; - } else if (expDiff < 0) { - /* scale p to match c */ - shift64RightJamming(pSig64, -expDiff, &pSig64); - zExp = cExp; - } else { - /* no scaling needed */ - zExp = cExp; - } - /* Add significands and make sure explicit bit ends up in posn 62 */ - zSig64 = pSig64 + cSig64; - if ((int64_t)zSig64 < 0) { - shift64RightJamming(zSig64, 1, &zSig64); - } else { - zExp--; - } - } else { - /* Subtraction */ - if (expDiff > 0) { - shift64RightJamming(cSig64, expDiff, &cSig64); - zSig64 = pSig64 - cSig64; - zExp = pExp; - } else if (expDiff < 0) { - shift64RightJamming(pSig64, -expDiff, &pSig64); - zSig64 = cSig64 - pSig64; - zExp = cExp; - zSign ^= 1; - } else { - zExp = pExp; - if (cSig64 < pSig64) { - zSig64 = pSig64 - cSig64; - } else if (pSig64 < cSig64) { - zSig64 = cSig64 - pSig64; - zSign ^= 1; - } else { - /* Exact zero */ - zSign = signflip; - if (status->float_rounding_mode == float_round_down) { - zSign ^= 1; - } - return packFloat32(zSign, 0, 0); - } - } - --zExp; - /* Normalize to put the explicit bit back into bit 62. */ - shiftcount = countLeadingZeros64(zSig64) - 1; - zSig64 <<= shiftcount; - zExp -= shiftcount; - } - if (flags & float_muladd_halve_result) { - zExp--; - } - - shift64RightJamming(zSig64, 32, &zSig64); - return roundAndPackFloat32(zSign, zExp, zSig64, status); -} - - /*---------------------------------------------------------------------------- | Returns the binary exponential of the single-precision floating-point value | `a'. The operation is performed according to the IEC/IEEE Standard for @@ -2079,253 +1853,6 @@ float64 float64_rem(float64 a, float64 b, float_status *status) } -/*---------------------------------------------------------------------------- -| Returns the result of multiplying the double-precision floating-point values -| `a' and `b' then adding 'c', with no intermediate rounding step after the -| multiplication. The operation is performed according to the IEC/IEEE -| Standard for Binary Floating-Point Arithmetic 754-2008. -| The flags argument allows the caller to select negation of the -| addend, the intermediate product, or the final result. (The difference -| between this and having the caller do a separate negation is that negating -| externally will flip the sign bit on NaNs.) -*----------------------------------------------------------------------------*/ - -float64 float64_muladd(float64 a, float64 b, float64 c, int flags, - float_status *status) -{ - flag aSign, bSign, cSign, zSign; - int aExp, bExp, cExp, pExp, zExp, expDiff; - uint64_t aSig, bSig, cSig; - flag pInf, pZero, pSign; - uint64_t pSig0, pSig1, cSig0, cSig1, zSig0, zSig1; - int shiftcount; - flag signflip, infzero; - - a = float64_squash_input_denormal(a, status); - b = float64_squash_input_denormal(b, status); - c = float64_squash_input_denormal(c, status); - aSig = extractFloat64Frac(a); - aExp = extractFloat64Exp(a); - aSign = extractFloat64Sign(a); - bSig = extractFloat64Frac(b); - bExp = extractFloat64Exp(b); - bSign = extractFloat64Sign(b); - cSig = extractFloat64Frac(c); - cExp = extractFloat64Exp(c); - cSign = extractFloat64Sign(c); - - infzero = ((aExp == 0 && aSig == 0 && bExp == 0x7ff && bSig == 0) || - (aExp == 0x7ff && aSig == 0 && bExp == 0 && bSig == 0)); - - /* It is implementation-defined whether the cases of (0,inf,qnan) - * and (inf,0,qnan) raise InvalidOperation or not (and what QNaN - * they return if they do), so we have to hand this information - * off to the target-specific pick-a-NaN routine. - */ - if (((aExp == 0x7ff) && aSig) || - ((bExp == 0x7ff) && bSig) || - ((cExp == 0x7ff) && cSig)) { - return propagateFloat64MulAddNaN(a, b, c, infzero, status); - } - - if (infzero) { - float_raise(float_flag_invalid, status); - return float64_default_nan(status); - } - - if (flags & float_muladd_negate_c) { - cSign ^= 1; - } - - signflip = (flags & float_muladd_negate_result) ? 1 : 0; - - /* Work out the sign and type of the product */ - pSign = aSign ^ bSign; - if (flags & float_muladd_negate_product) { - pSign ^= 1; - } - pInf = (aExp == 0x7ff) || (bExp == 0x7ff); - pZero = ((aExp | aSig) == 0) || ((bExp | bSig) == 0); - - if (cExp == 0x7ff) { - if (pInf && (pSign ^ cSign)) { - /* addition of opposite-signed infinities => InvalidOperation */ - float_raise(float_flag_invalid, status); - return float64_default_nan(status); - } - /* Otherwise generate an infinity of the same sign */ - return packFloat64(cSign ^ signflip, 0x7ff, 0); - } - - if (pInf) { - return packFloat64(pSign ^ signflip, 0x7ff, 0); - } - - if (pZero) { - if (cExp == 0) { - if (cSig == 0) { - /* Adding two exact zeroes */ - if (pSign == cSign) { - zSign = pSign; - } else if (status->float_rounding_mode == float_round_down) { - zSign = 1; - } else { - zSign = 0; - } - return packFloat64(zSign ^ signflip, 0, 0); - } - /* Exact zero plus a denorm */ - if (status->flush_to_zero) { - float_raise(float_flag_output_denormal, status); - return packFloat64(cSign ^ signflip, 0, 0); - } - } - /* Zero plus something non-zero : just return the something */ - if (flags & float_muladd_halve_result) { - if (cExp == 0) { - normalizeFloat64Subnormal(cSig, &cExp, &cSig); - } - /* Subtract one to halve, and one again because roundAndPackFloat64 - * wants one less than the true exponent. - */ - cExp -= 2; - cSig = (cSig | 0x0010000000000000ULL) << 10; - return roundAndPackFloat64(cSign ^ signflip, cExp, cSig, status); - } - return packFloat64(cSign ^ signflip, cExp, cSig); - } - - if (aExp == 0) { - normalizeFloat64Subnormal(aSig, &aExp, &aSig); - } - if (bExp == 0) { - normalizeFloat64Subnormal(bSig, &bExp, &bSig); - } - - /* Calculate the actual result a * b + c */ - - /* Multiply first; this is easy. */ - /* NB: we subtract 0x3fe where float64_mul() subtracts 0x3ff - * because we want the true exponent, not the "one-less-than" - * flavour that roundAndPackFloat64() takes. - */ - pExp = aExp + bExp - 0x3fe; - aSig = (aSig | LIT64(0x0010000000000000))<<10; - bSig = (bSig | LIT64(0x0010000000000000))<<11; - mul64To128(aSig, bSig, &pSig0, &pSig1); - if ((int64_t)(pSig0 << 1) >= 0) { - shortShift128Left(pSig0, pSig1, 1, &pSig0, &pSig1); - pExp--; - } - - zSign = pSign ^ signflip; - - /* Now [pSig0:pSig1] is the significand of the multiply, with the explicit - * bit in position 126. - */ - if (cExp == 0) { - if (!cSig) { - /* Throw out the special case of c being an exact zero now */ - shift128RightJamming(pSig0, pSig1, 64, &pSig0, &pSig1); - if (flags & float_muladd_halve_result) { - pExp--; - } - return roundAndPackFloat64(zSign, pExp - 1, - pSig1, status); - } - normalizeFloat64Subnormal(cSig, &cExp, &cSig); - } - - /* Shift cSig and add the explicit bit so [cSig0:cSig1] is the - * significand of the addend, with the explicit bit in position 126. - */ - cSig0 = cSig << (126 - 64 - 52); - cSig1 = 0; - cSig0 |= LIT64(0x4000000000000000); - expDiff = pExp - cExp; - - if (pSign == cSign) { - /* Addition */ - if (expDiff > 0) { - /* scale c to match p */ - shift128RightJamming(cSig0, cSig1, expDiff, &cSig0, &cSig1); - zExp = pExp; - } else if (expDiff < 0) { - /* scale p to match c */ - shift128RightJamming(pSig0, pSig1, -expDiff, &pSig0, &pSig1); - zExp = cExp; - } else { - /* no scaling needed */ - zExp = cExp; - } - /* Add significands and make sure explicit bit ends up in posn 126 */ - add128(pSig0, pSig1, cSig0, cSig1, &zSig0, &zSig1); - if ((int64_t)zSig0 < 0) { - shift128RightJamming(zSig0, zSig1, 1, &zSig0, &zSig1); - } else { - zExp--; - } - shift128RightJamming(zSig0, zSig1, 64, &zSig0, &zSig1); - if (flags & float_muladd_halve_result) { - zExp--; - } - return roundAndPackFloat64(zSign, zExp, zSig1, status); - } else { - /* Subtraction */ - if (expDiff > 0) { - shift128RightJamming(cSig0, cSig1, expDiff, &cSig0, &cSig1); - sub128(pSig0, pSig1, cSig0, cSig1, &zSig0, &zSig1); - zExp = pExp; - } else if (expDiff < 0) { - shift128RightJamming(pSig0, pSig1, -expDiff, &pSig0, &pSig1); - sub128(cSig0, cSig1, pSig0, pSig1, &zSig0, &zSig1); - zExp = cExp; - zSign ^= 1; - } else { - zExp = pExp; - if (lt128(cSig0, cSig1, pSig0, pSig1)) { - sub128(pSig0, pSig1, cSig0, cSig1, &zSig0, &zSig1); - } else if (lt128(pSig0, pSig1, cSig0, cSig1)) { - sub128(cSig0, cSig1, pSig0, pSig1, &zSig0, &zSig1); - zSign ^= 1; - } else { - /* Exact zero */ - zSign = signflip; - if (status->float_rounding_mode == float_round_down) { - zSign ^= 1; - } - return packFloat64(zSign, 0, 0); - } - } - --zExp; - /* Do the equivalent of normalizeRoundAndPackFloat64() but - * starting with the significand in a pair of uint64_t. - */ - if (zSig0) { - shiftcount = countLeadingZeros64(zSig0) - 1; - shortShift128Left(zSig0, zSig1, shiftcount, &zSig0, &zSig1); - if (zSig1) { - zSig0 |= 1; - } - zExp -= shiftcount; - } else { - shiftcount = countLeadingZeros64(zSig1); - if (shiftcount == 0) { - zSig0 = (zSig1 >> 1) | (zSig1 & 1); - zExp -= 63; - } else { - shiftcount--; - zSig0 = zSig1 << shiftcount; - zExp -= (shiftcount + 64); - } - } - if (flags & float_muladd_halve_result) { - zExp--; - } - return roundAndPackFloat64(zSign, zExp, zSig0, status); - } -} - /*---------------------------------------------------------------------------- | Returns the binary log of the double-precision floating-point value `a'. | The operation is performed according to the IEC/IEEE Standard for Binary From patchwork Sun Feb 4 04:11:36 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Richard Henderson X-Patchwork-Id: 126816 Delivered-To: patch@linaro.org Received: by 10.80.172.228 with SMTP id x91csp1228676edc; Sat, 3 Feb 2018 20:27:55 -0800 (PST) X-Google-Smtp-Source: AH8x227k0hqCHRtakVxTaWH8B+Eg9YfCx8goXa7VxSdNLKJDXFIq5dxivgAvLa18ZAnihngCPil1 X-Received: by 10.37.207.213 with SMTP id f204mr20387943ybg.396.1517718475891; Sat, 03 Feb 2018 20:27:55 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1517718475; cv=none; d=google.com; s=arc-20160816; b=dnA05l8LtUhf+X358PeUK02VjTgev5snxLfbCuK1Dof2wIod8XNDfaW8gV7tTldR2E IzNMjDkz7G0IiLFWNQpUPZzhOkuMoPG6IAOCn9sSl4phO5ayjLfjeo5ZCHK5hHbXioBH WcFE3vPefIbZzRkM1+tIaC+h5g0C8Dk1Ax90rL7EmFkpfuFmCX5JDHPXngInGFjCQxen 2idopg7T9jeOBz6a9K9PIBa53UQaQXnJRXh1mTrOwmmG70/VmgbTknOU08vpRrazVmUW YP6fQtLLUyftwglM87ZJ9Pas8hxAqn7Ppz4uG0JxisldzxGQJzAKL2H+mnYcG1kX8b9p salQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=sender:errors-to:cc:list-subscribe:list-help:list-post:list-archive :list-unsubscribe:list-id:precedence:subject:references:in-reply-to :message-id:date:to:from:dkim-signature:arc-authentication-results; bh=M/rrn0hTeYecl0nmHZH6/01GanF2uSg86yLNwI3DnuM=; b=XFYjNEC0mT94zge6IRQA1ubuLB2kDMoVBLHzJ/faTamcFT5J1MgYhbO4BaRlAEr805 5DiGQjJJNj0OOjwtafy3MaJ56vCZ68614o0BcAAXrDvjkwUea8E4bSJW8iUFBh4bQI2G qrI07TSgeJr6Z69NDRu1VKmr2HUlFrmctDlDQfH6UTeEObDDBLzr/7qevHWSBqUwKqd3 +636U08clIMSJk4w0zOgbGSQmuPWGFhFYeyUfXguEOkIX+ZS3CFpJ2we5wbl4wBn9Rwr riJEPClrLy5igRc4yvtdBlsWsZ8ra2EiFUJ740esVCw5NV4ll+/IFcK/qVHP8eqIBk3n 7FZQ== ARC-Authentication-Results: i=1; mx.google.com; dkim=fail header.i=@linaro.org header.s=google header.b=eo7CWxRY; spf=pass (google.com: domain of qemu-devel-bounces+patch=linaro.org@nongnu.org designates 2001:4830:134:3::11 as permitted sender) smtp.mailfrom=qemu-devel-bounces+patch=linaro.org@nongnu.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=linaro.org Return-Path: Received: from lists.gnu.org (lists.gnu.org. [2001:4830:134:3::11]) by mx.google.com with ESMTPS id o205si1006040ywc.624.2018.02.03.20.27.55 for (version=TLS1 cipher=AES128-SHA bits=128/128); Sat, 03 Feb 2018 20:27:55 -0800 (PST) Received-SPF: pass (google.com: domain of qemu-devel-bounces+patch=linaro.org@nongnu.org designates 2001:4830:134:3::11 as permitted sender) client-ip=2001:4830:134:3::11; Authentication-Results: mx.google.com; dkim=fail header.i=@linaro.org header.s=google header.b=eo7CWxRY; spf=pass (google.com: domain of qemu-devel-bounces+patch=linaro.org@nongnu.org designates 2001:4830:134:3::11 as permitted sender) smtp.mailfrom=qemu-devel-bounces+patch=linaro.org@nongnu.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=linaro.org Received: from localhost ([::1]:58356 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1eiBuF-00025r-7K for patch@linaro.org; Sat, 03 Feb 2018 23:27:55 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:47531) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1eiBfB-000522-55 for qemu-devel@nongnu.org; Sat, 03 Feb 2018 23:12:22 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1eiBf6-00057j-18 for qemu-devel@nongnu.org; Sat, 03 Feb 2018 23:12:21 -0500 Received: from mail-pl0-x242.google.com ([2607:f8b0:400e:c01::242]:34685) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1eiBf5-00057N-PA for qemu-devel@nongnu.org; Sat, 03 Feb 2018 23:12:15 -0500 Received: by mail-pl0-x242.google.com with SMTP id q17so7156453pll.1 for ; Sat, 03 Feb 2018 20:12:15 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=M/rrn0hTeYecl0nmHZH6/01GanF2uSg86yLNwI3DnuM=; b=eo7CWxRYXrBxC9lPUJ/KmOb2O/dEpMUqyrEiC8SeJF/H4rhzhMVYEHvi3PvfS0rOIk uYqzp6Hf4O6XN5kS9EZxLbAvyAN6zGQGoFmSuCVVFfPwulu4jqG1yuyR9WasT2X0ZxoY vbZP+jp15rmodNNuESHFWiSuArwE6K6mDN1iw= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=M/rrn0hTeYecl0nmHZH6/01GanF2uSg86yLNwI3DnuM=; b=DWScOsUHCSkOVtVn/KOHMthWqUAMD2i3pdvu97PDpEBYkfOuznSoczGUxALuyRW71B 5MIvHR0yjpsXd8qaMUAYzr8hmCqzX8dxj2V4GDUKBpS2C7LsPPF6RScUWk7U9hmF97iw YtaUGgzMv7G+Z8FElh4ystwvFclnzacE6E5/+EihV9hDhHhDdVMLRgYBG5Gl+6cr4dfw N81N4dt9Z7X+fvtWQICbxpV2TgzTJc2qfQYch35vLOiXovR2k2oF7ClgB+D2MBzQxgfv IJBh4A6u6TuCaPPJVqNGgv0+VDQnpFILElJ5yYMMj/SJXaZIgIc/iX1SP0j4aR3tmwsr 3s9Q== X-Gm-Message-State: AKwxytc8NTNz8UD9r9lE2l17Vfpgjx5lKlS5czjBFKn9s4Psg0u1Lzbc b7+34kiLOhrG1+aknt+w/RlUPla5RGI= X-Received: by 2002:a17:902:8d97:: with SMTP id v23-v6mr34991063plo.248.1517717534419; Sat, 03 Feb 2018 20:12:14 -0800 (PST) Received: from cloudburst.twiddle.net (174-21-6-47.tukw.qwest.net. [174.21.6.47]) by smtp.gmail.com with ESMTPSA id k3sm1399425pgr.12.2018.02.03.20.12.13 (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Sat, 03 Feb 2018 20:12:13 -0800 (PST) From: Richard Henderson To: qemu-devel@nongnu.org Date: Sat, 3 Feb 2018 20:11:36 -0800 Message-Id: <20180204041136.17525-25-richard.henderson@linaro.org> X-Mailer: git-send-email 2.14.3 In-Reply-To: <20180204041136.17525-1-richard.henderson@linaro.org> References: <20180204041136.17525-1-richard.henderson@linaro.org> X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 2607:f8b0:400e:c01::242 Subject: [Qemu-devel] [PATCH 24/24] fpu: Implement round_to_int with soft-fp.h X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: peter.maydell@linaro.org, cota@braap.org, alex.bennee@linaro.org, hsp.cat7@gmail.com Errors-To: qemu-devel-bounces+patch=linaro.org@nongnu.org Sender: "Qemu-devel" Add float16 support. Remove float64_trunc_to_int as unused rather than recreating it within the new framework. Signed-off-by: Richard Henderson --- include/fpu/softfloat.h | 2 +- fpu/floatxx.inc.c | 75 ++++++++++++ fpu/softfloat.c | 311 ------------------------------------------------ 3 files changed, 76 insertions(+), 312 deletions(-) -- 2.14.3 diff --git a/include/fpu/softfloat.h b/include/fpu/softfloat.h index 3a2d148651..95e96f8557 100644 --- a/include/fpu/softfloat.h +++ b/include/fpu/softfloat.h @@ -246,6 +246,7 @@ float64 float16_to_float64(float16 a, bool ieee, float_status *status); | Software half-precision operations. *----------------------------------------------------------------------------*/ +float16 float16_round_to_int(float16, float_status *status); float16 float16_add(float16, float16, float_status *status); float16 float16_sub(float16, float16, float_status *status); float16 float16_mul(float16, float16, float_status *status); @@ -463,7 +464,6 @@ float128 float64_to_float128(float64, float_status *status); | Software IEC/IEEE double-precision operations. *----------------------------------------------------------------------------*/ float64 float64_round_to_int(float64, float_status *status); -float64 float64_trunc_to_int(float64, float_status *status); float64 float64_add(float64, float64, float_status *status); float64 float64_sub(float64, float64, float_status *status); float64 float64_mul(float64, float64, float_status *status); diff --git a/fpu/floatxx.inc.c b/fpu/floatxx.inc.c index a4b305e1ff..a90ae95f2d 100644 --- a/fpu/floatxx.inc.c +++ b/fpu/floatxx.inc.c @@ -34,6 +34,8 @@ _FP_FRAC_SNANP(fs, X) #define FP_ADD_INTERNAL(fs, wc, R, A, B, OP) \ _FP_ADD_INTERNAL(fs, wc, R, A, B, '-') +#define FP_ROUND(wc, X) \ + _FP_ROUND(wc, X) static FLOATXX addsub_internal(FLOATXX a, FLOATXX b, float_status *status, bool subtract) @@ -464,3 +466,76 @@ FLOATXX glue(FLOATXX,_minnummag)(FLOATXX a, FLOATXX b, float_status *status) return minmax_internal(a, b, status, MINMAX_MIN | MINMAX_IEEE | MINMAX_MAG); } + +FLOATXX glue(FLOATXX,_round_to_int)(FLOATXX a, float_status *status) +{ + const int fracbits = glue(_FP_FRACBITS_, FS); + const int wfracbits = glue(_FP_WFRACBITS_, FS); + FP_DECL_EX; + glue(FP_DECL_, FS)(A); + int rshift, lshift; + + FP_INIT_ROUNDMODE; + glue(FP_UNPACK_, FS)(A, a); + + switch (A_c) { + case FP_CLS_INF: + /* No fractional part, never any exceptions, return unchanged. */ + return a; + + case FP_CLS_ZERO: + case FP_CLS_NAN: + /* No fractional part, but maybe exceptions. In the cases of + denormal-flush-to-zero and SNaN, we will have raised an + exception during unpack. For those, we need to go through + repack in order to generate zero or silence the NaN. */ + if (!FP_CUR_EXCEPTIONS) { + return a; + } + break; + + case FP_CLS_NORMAL: + /* Position the 2**0 bit at _FP_WORKBIT, + where _FP_ROUND expects to work. */ + rshift = fracbits - 1 - A_e; + if (rshift <= 0) { + /* Already integral, never any exceptions, return unchanged. */ + return a; + } + if (rshift < wfracbits) { + glue(_FP_FRAC_SRS_, WC)(A, rshift, wfracbits); + } else { + glue(_FP_FRAC_SET_, WC)(A, glue(_FP_MINFRAC_, WC)); + } + FP_ROUND(WC, A); + + /* Drop the rounding bits. Normally this is done via right-shift + during the re-packing stage, but we need to put the rest of the + fraction back into place. */ + glue(_FP_FRAC_LOW_, WC)(A) &= ~(_FP_WORK_LSB - 1); + + /* Notice rounding to zero. */ + if (glue(_FP_FRAC_ZEROP_, WC)(A)) { + A_c = FP_CLS_ZERO; + break; + } + + /* Renormalize the fraction. This takes care of both overflow + and fixing up the fraction after the rshift. */ + glue(_FP_FRAC_CLZ_, WC)(lshift, A); + lshift -= glue(_FP_WFRACXBITS_, FS); + assert(lshift >= 0); + glue(_FP_FRAC_SLL_, WC)(A, lshift); + + A_e += rshift - lshift; + break; + + default: + _FP_UNREACHABLE; + } + + glue(FP_PACK_, FS)(a, A); + FP_HANDLE_EXCEPTIONS; + + return a; +} diff --git a/fpu/softfloat.c b/fpu/softfloat.c index 47b9dd9bd3..3d5201b268 100644 --- a/fpu/softfloat.c +++ b/fpu/softfloat.c @@ -1310,87 +1310,6 @@ floatx80 float32_to_floatx80(float32 a, float_status *status) } -/*---------------------------------------------------------------------------- -| Rounds the single-precision floating-point value `a' to an integer, and -| returns the result as a single-precision floating-point value. The -| operation is performed according to the IEC/IEEE Standard for Binary -| Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -float32 float32_round_to_int(float32 a, float_status *status) -{ - flag aSign; - int aExp; - uint32_t lastBitMask, roundBitsMask; - uint32_t z; - a = float32_squash_input_denormal(a, status); - - aExp = extractFloat32Exp( a ); - if ( 0x96 <= aExp ) { - if ( ( aExp == 0xFF ) && extractFloat32Frac( a ) ) { - return propagateFloat32NaN(a, a, status); - } - return a; - } - if ( aExp <= 0x7E ) { - if ( (uint32_t) ( float32_val(a)<<1 ) == 0 ) return a; - status->float_exception_flags |= float_flag_inexact; - aSign = extractFloat32Sign( a ); - switch (status->float_rounding_mode) { - case float_round_nearest_even: - if ( ( aExp == 0x7E ) && extractFloat32Frac( a ) ) { - return packFloat32( aSign, 0x7F, 0 ); - } - break; - case float_round_ties_away: - if (aExp == 0x7E) { - return packFloat32(aSign, 0x7F, 0); - } - break; - case float_round_down: - return make_float32(aSign ? 0xBF800000 : 0); - case float_round_up: - return make_float32(aSign ? 0x80000000 : 0x3F800000); - } - return packFloat32( aSign, 0, 0 ); - } - lastBitMask = 1; - lastBitMask <<= 0x96 - aExp; - roundBitsMask = lastBitMask - 1; - z = float32_val(a); - switch (status->float_rounding_mode) { - case float_round_nearest_even: - z += lastBitMask>>1; - if ((z & roundBitsMask) == 0) { - z &= ~lastBitMask; - } - break; - case float_round_ties_away: - z += lastBitMask >> 1; - break; - case float_round_to_zero: - break; - case float_round_up: - if (!extractFloat32Sign(make_float32(z))) { - z += roundBitsMask; - } - break; - case float_round_down: - if (extractFloat32Sign(make_float32(z))) { - z += roundBitsMask; - } - break; - default: - abort(); - } - z &= ~ roundBitsMask; - if (z != float32_val(a)) { - status->float_exception_flags |= float_flag_inexact; - } - return make_float32(z); - -} - /*---------------------------------------------------------------------------- | Returns the remainder of the single-precision floating-point value `a' | with respect to the corresponding value `b'. The operation is performed @@ -1672,98 +1591,6 @@ floatx80 float64_to_floatx80(float64 a, float_status *status) aSign, aExp + 0x3C00, ( aSig | LIT64( 0x0010000000000000 ) )<<11 ); } -/*---------------------------------------------------------------------------- -| Rounds the double-precision floating-point value `a' to an integer, and -| returns the result as a double-precision floating-point value. The -| operation is performed according to the IEC/IEEE Standard for Binary -| Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -float64 float64_round_to_int(float64 a, float_status *status) -{ - flag aSign; - int aExp; - uint64_t lastBitMask, roundBitsMask; - uint64_t z; - a = float64_squash_input_denormal(a, status); - - aExp = extractFloat64Exp( a ); - if ( 0x433 <= aExp ) { - if ( ( aExp == 0x7FF ) && extractFloat64Frac( a ) ) { - return propagateFloat64NaN(a, a, status); - } - return a; - } - if ( aExp < 0x3FF ) { - if ( (uint64_t) ( float64_val(a)<<1 ) == 0 ) return a; - status->float_exception_flags |= float_flag_inexact; - aSign = extractFloat64Sign( a ); - switch (status->float_rounding_mode) { - case float_round_nearest_even: - if ( ( aExp == 0x3FE ) && extractFloat64Frac( a ) ) { - return packFloat64( aSign, 0x3FF, 0 ); - } - break; - case float_round_ties_away: - if (aExp == 0x3FE) { - return packFloat64(aSign, 0x3ff, 0); - } - break; - case float_round_down: - return make_float64(aSign ? LIT64( 0xBFF0000000000000 ) : 0); - case float_round_up: - return make_float64( - aSign ? LIT64( 0x8000000000000000 ) : LIT64( 0x3FF0000000000000 )); - } - return packFloat64( aSign, 0, 0 ); - } - lastBitMask = 1; - lastBitMask <<= 0x433 - aExp; - roundBitsMask = lastBitMask - 1; - z = float64_val(a); - switch (status->float_rounding_mode) { - case float_round_nearest_even: - z += lastBitMask >> 1; - if ((z & roundBitsMask) == 0) { - z &= ~lastBitMask; - } - break; - case float_round_ties_away: - z += lastBitMask >> 1; - break; - case float_round_to_zero: - break; - case float_round_up: - if (!extractFloat64Sign(make_float64(z))) { - z += roundBitsMask; - } - break; - case float_round_down: - if (extractFloat64Sign(make_float64(z))) { - z += roundBitsMask; - } - break; - default: - abort(); - } - z &= ~ roundBitsMask; - if (z != float64_val(a)) { - status->float_exception_flags |= float_flag_inexact; - } - return make_float64(z); - -} - -float64 float64_trunc_to_int(float64 a, float_status *status) -{ - int oldmode; - float64 res; - oldmode = status->float_rounding_mode; - status->float_rounding_mode = float_round_to_zero; - res = float64_round_to_int(a, status); - status->float_rounding_mode = oldmode; - return res; -} /*---------------------------------------------------------------------------- | Returns the remainder of the double-precision floating-point value `a' @@ -2821,144 +2648,6 @@ floatx80 float128_to_floatx80(float128 a, float_status *status) } -/*---------------------------------------------------------------------------- -| Rounds the quadruple-precision floating-point value `a' to an integer, and -| returns the result as a quadruple-precision floating-point value. The -| operation is performed according to the IEC/IEEE Standard for Binary -| Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -float128 float128_round_to_int(float128 a, float_status *status) -{ - flag aSign; - int32_t aExp; - uint64_t lastBitMask, roundBitsMask; - float128 z; - - aExp = extractFloat128Exp( a ); - if ( 0x402F <= aExp ) { - if ( 0x406F <= aExp ) { - if ( ( aExp == 0x7FFF ) - && ( extractFloat128Frac0( a ) | extractFloat128Frac1( a ) ) - ) { - return propagateFloat128NaN(a, a, status); - } - return a; - } - lastBitMask = 1; - lastBitMask = ( lastBitMask<<( 0x406E - aExp ) )<<1; - roundBitsMask = lastBitMask - 1; - z = a; - switch (status->float_rounding_mode) { - case float_round_nearest_even: - if ( lastBitMask ) { - add128( z.high, z.low, 0, lastBitMask>>1, &z.high, &z.low ); - if ( ( z.low & roundBitsMask ) == 0 ) z.low &= ~ lastBitMask; - } - else { - if ( (int64_t) z.low < 0 ) { - ++z.high; - if ( (uint64_t) ( z.low<<1 ) == 0 ) z.high &= ~1; - } - } - break; - case float_round_ties_away: - if (lastBitMask) { - add128(z.high, z.low, 0, lastBitMask >> 1, &z.high, &z.low); - } else { - if ((int64_t) z.low < 0) { - ++z.high; - } - } - break; - case float_round_to_zero: - break; - case float_round_up: - if (!extractFloat128Sign(z)) { - add128(z.high, z.low, 0, roundBitsMask, &z.high, &z.low); - } - break; - case float_round_down: - if (extractFloat128Sign(z)) { - add128(z.high, z.low, 0, roundBitsMask, &z.high, &z.low); - } - break; - default: - abort(); - } - z.low &= ~ roundBitsMask; - } - else { - if ( aExp < 0x3FFF ) { - if ( ( ( (uint64_t) ( a.high<<1 ) ) | a.low ) == 0 ) return a; - status->float_exception_flags |= float_flag_inexact; - aSign = extractFloat128Sign( a ); - switch (status->float_rounding_mode) { - case float_round_nearest_even: - if ( ( aExp == 0x3FFE ) - && ( extractFloat128Frac0( a ) - | extractFloat128Frac1( a ) ) - ) { - return packFloat128( aSign, 0x3FFF, 0, 0 ); - } - break; - case float_round_ties_away: - if (aExp == 0x3FFE) { - return packFloat128(aSign, 0x3FFF, 0, 0); - } - break; - case float_round_down: - return - aSign ? packFloat128( 1, 0x3FFF, 0, 0 ) - : packFloat128( 0, 0, 0, 0 ); - case float_round_up: - return - aSign ? packFloat128( 1, 0, 0, 0 ) - : packFloat128( 0, 0x3FFF, 0, 0 ); - } - return packFloat128( aSign, 0, 0, 0 ); - } - lastBitMask = 1; - lastBitMask <<= 0x402F - aExp; - roundBitsMask = lastBitMask - 1; - z.low = 0; - z.high = a.high; - switch (status->float_rounding_mode) { - case float_round_nearest_even: - z.high += lastBitMask>>1; - if ( ( ( z.high & roundBitsMask ) | a.low ) == 0 ) { - z.high &= ~ lastBitMask; - } - break; - case float_round_ties_away: - z.high += lastBitMask>>1; - break; - case float_round_to_zero: - break; - case float_round_up: - if (!extractFloat128Sign(z)) { - z.high |= ( a.low != 0 ); - z.high += roundBitsMask; - } - break; - case float_round_down: - if (extractFloat128Sign(z)) { - z.high |= (a.low != 0); - z.high += roundBitsMask; - } - break; - default: - abort(); - } - z.high &= ~ roundBitsMask; - } - if ( ( z.low != a.low ) || ( z.high != a.high ) ) { - status->float_exception_flags |= float_flag_inexact; - } - return z; - -} - /*---------------------------------------------------------------------------- | Returns the remainder of the quadruple-precision floating-point value `a' | with respect to the corresponding value `b'. The operation is performed