From patchwork Fri Oct 5 18:01:58 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Richard Henderson X-Patchwork-Id: 148292 Delivered-To: patch@linaro.org Received: by 2002:a2e:8595:0:0:0:0:0 with SMTP id b21-v6csp765483lji; Fri, 5 Oct 2018 11:14:34 -0700 (PDT) X-Google-Smtp-Source: ACcGV63zDb2IIOJwoQxT2vbALS57MCJXgbsMbOyBywKNLSz5Hj//aTPn78SYM4I20ynj8TWH2QXb X-Received: by 2002:aed:2d86:: with SMTP id i6-v6mr10044894qtd.279.1538763274682; Fri, 05 Oct 2018 11:14:34 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1538763274; cv=none; d=google.com; s=arc-20160816; b=d+Fi/W17uEBZubmnW+X+fqj82f60IFd4eA9NBIyGz4R7Vcpqx00XtZl35tA2ShpERt WsMRPeXHaTovXsECFGd7HzMFxjlVABEeDPSmH9cXUrMxqiMy/oR2GXYCfQxSl1lSPP4t hIQniXtzpwvr4ilImthmr3nFmqMrQ7XH318fc8hU4wf2ozmMLPrJkRdcQfjw5s+2+iCP C99iW2VP+47ND3e8A3M/pJG274/+OzqFkb/KVPNSHvPYT8LtO7GL5/Q4oW7X072mS6Eg 5+wCOzZ8e0EZ/QaO1osqO0tIsdwZ530rP+XVllliafteT8ogaRq1WG9e0rlfcog7gaPz Xz3g== 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; bh=eoQfmeIbqQYNxqFOPaK1rddW7v/35ufvgMSTkPh3uTI=; b=a4N+dNSCAewyKpk/6l8p9rWNkCQK+1soTLsU0jVNUc/tKbz/n5Yoa/8AczcUDuJ7Hc 192zOPoagTdQJvxM2vxSGEZZ7PM2D+qIOOBRSeMe3KjQMtjZxwfnekcdk77qN152Kej/ zThPolDxLRCWmxXnmaOhXHxlbJ1+BixPBE2Vjvp+ChNwiwwu/v51mZEhHDrU4ix17Pxe zKgD/9U5jAm7cmZBB4Iyf7sJz1gtJu9X54xtLLHlH3C79ej32sKFB7QGs8BuRB2IFOYp 8xlGZwc083B7m1BJ45rITCsOvfHypr+wLav1nOK9M8oO13goxedYNnYe8KUEo6dyVlOJ LcsA== ARC-Authentication-Results: i=1; mx.google.com; dkim=fail header.i=@linaro.org header.s=google header.b=Y4urqlPQ; 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 t29-v6si1315909qvc.47.2018.10.05.11.14.34 for (version=TLS1 cipher=AES128-SHA bits=128/128); Fri, 05 Oct 2018 11:14:34 -0700 (PDT) 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=Y4urqlPQ; 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]:36454 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1g8UcT-0004Xs-MR for patch@linaro.org; Fri, 05 Oct 2018 14:14:33 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:38628) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1g8UQg-0000Wv-K9 for qemu-devel@nongnu.org; Fri, 05 Oct 2018 14:02:29 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1g8UQd-0004vB-Km for qemu-devel@nongnu.org; Fri, 05 Oct 2018 14:02:22 -0400 Received: from mail-oi1-x244.google.com ([2607:f8b0:4864:20::244]:43202) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1g8UQc-0004KX-KN for qemu-devel@nongnu.org; Fri, 05 Oct 2018 14:02:19 -0400 Received: by mail-oi1-x244.google.com with SMTP id s69-v6so11088230oie.10 for ; Fri, 05 Oct 2018 11:02:16 -0700 (PDT) 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=eoQfmeIbqQYNxqFOPaK1rddW7v/35ufvgMSTkPh3uTI=; b=Y4urqlPQlb0iVk4XHPAq48tfS6akXHDuAR9jHvemwZbleKD07q3fLctEHQjkV1u5MB EnuN22uKCoAhZdkA6+QEHuOMIrM7+rU+9ryQ6AN8omaZq3HALCciT1QeApwZEyM497bn ThP+srKswDydp+zFuWcTHcmSlcGtesOSNfJQk= 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=eoQfmeIbqQYNxqFOPaK1rddW7v/35ufvgMSTkPh3uTI=; b=mq9fZwPUBaeeWZ9kshn6TA1H5AcyZYNdZt9biWS4YMDcZy8OxRdOqafbKkGPYTImYC BoV/k5BxCN1yshF5PmDVw/I7c2FVRL5VgXWJw5Hz0GC8Tc/Kdf8bHm/G9DlhoOh+08tG YeZ90WzZ7jiFXHk/OXobpkoATLiX/St3rGUXxCblDowh1CxxgWd+b2jQ/8Ew79lbVEHF xP7kaobQ5+zr10jxlATIpX69gfPQSZmC3Wr6tKplPJVunmqY6MSERWi5EjeJp1+DoL1j cwSzdZcFTBK7A9lTLlN8kglfOcMfHT2KN645b55f4+W6nCwfHdFe7J9OnoUroZOB7/UV I+EQ== X-Gm-Message-State: ABuFfoibAKYyNqMuV0n1ZUSWcr2fSFZYHowy+P1DG9QXr14OS4ceGj+6 5SephnJtT7V2zYUabd/MEPFH0nQfpTF2B7wOkEA= X-Received: by 2002:aca:c402:: with SMTP id u2-v6mr23988oif.141.1538762535269; Fri, 05 Oct 2018 11:02:15 -0700 (PDT) Received: from cloudburst.twiddle.net ([187.217.230.84]) by smtp.gmail.com with ESMTPSA id d37-v6sm2601302otb.0.2018.10.05.11.02.13 (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Fri, 05 Oct 2018 11:02:14 -0700 (PDT) From: Richard Henderson To: qemu-devel@nongnu.org Date: Fri, 5 Oct 2018 13:01:58 -0500 Message-Id: <20181005180201.11387-6-richard.henderson@linaro.org> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20181005180201.11387-1-richard.henderson@linaro.org> References: <20181005180201.11387-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:4864:20::244 Subject: [Qemu-devel] [PULL 5/8] softfloat: Fix division 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 Errors-To: qemu-devel-bounces+patch=linaro.org@nongnu.org Sender: "Qemu-devel" The __udiv_qrnnd primitive that we nicked from gmp requires its inputs to be normalized. We were not doing that. Because the inputs are nearly normalized already, finishing that is trivial. Replace div128to64 with a "proper" udiv_qrnnd, so that this remains a reusable primitive. Fixes: cf07323d494 Fixes: https://bugs.launchpad.net/qemu/+bug/1793119 Tested-by: Emilio G. Cota Tested-by: Alex Bennée Reviewed-by: Alex Bennée Signed-off-by: Richard Henderson --- include/fpu/softfloat-macros.h | 34 ++++++++++++++++++++++++--------- fpu/softfloat.c | 35 ++++++++++++++++++++++++++-------- 2 files changed, 52 insertions(+), 17 deletions(-) -- 2.17.1 diff --git a/include/fpu/softfloat-macros.h b/include/fpu/softfloat-macros.h index edc682139e..a1d99c730d 100644 --- a/include/fpu/softfloat-macros.h +++ b/include/fpu/softfloat-macros.h @@ -329,15 +329,30 @@ static inline void | pieces which are stored at the locations pointed to by `z0Ptr' and `z1Ptr'. *----------------------------------------------------------------------------*/ -static inline void - shortShift128Left( - uint64_t a0, uint64_t a1, int count, uint64_t *z0Ptr, uint64_t *z1Ptr) +static inline void shortShift128Left(uint64_t a0, uint64_t a1, int count, + uint64_t *z0Ptr, uint64_t *z1Ptr) { + *z1Ptr = a1 << count; + *z0Ptr = count == 0 ? a0 : (a0 << count) | (a1 >> (-count & 63)); +} - *z1Ptr = a1<>( ( - count ) & 63 ) ); +/*---------------------------------------------------------------------------- +| Shifts the 128-bit value formed by concatenating `a0' and `a1' left by the +| number of bits given in `count'. Any bits shifted off are lost. The value +| of `count' may be greater than 64. The result is broken into two 64-bit +| pieces which are stored at the locations pointed to by `z0Ptr' and `z1Ptr'. +*----------------------------------------------------------------------------*/ +static inline void shift128Left(uint64_t a0, uint64_t a1, int count, + uint64_t *z0Ptr, uint64_t *z1Ptr) +{ + if (count < 64) { + *z1Ptr = a1 << count; + *z0Ptr = count == 0 ? a0 : (a0 << count) | (a1 >> (-count & 63)); + } else { + *z1Ptr = 0; + *z0Ptr = a1 << (count - 64); + } } /*---------------------------------------------------------------------------- @@ -619,7 +634,8 @@ static inline uint64_t estimateDiv128To64(uint64_t a0, uint64_t a1, uint64_t b) * * Licensed under the GPLv2/LGPLv3 */ -static inline uint64_t div128To64(uint64_t n0, uint64_t n1, uint64_t d) +static inline uint64_t udiv_qrnnd(uint64_t *r, uint64_t n1, + uint64_t n0, uint64_t d) { uint64_t d0, d1, q0, q1, r1, r0, m; @@ -658,8 +674,8 @@ static inline uint64_t div128To64(uint64_t n0, uint64_t n1, uint64_t d) } r0 -= m; - /* Return remainder in LSB */ - return (q1 << 32) | q0 | (r0 != 0); + *r = r0; + return (q1 << 32) | q0; } /*---------------------------------------------------------------------------- diff --git a/fpu/softfloat.c b/fpu/softfloat.c index 71da0f68bb..46ae206172 100644 --- a/fpu/softfloat.c +++ b/fpu/softfloat.c @@ -1112,19 +1112,38 @@ static FloatParts div_floats(FloatParts a, FloatParts b, float_status *s) bool sign = a.sign ^ b.sign; if (a.cls == float_class_normal && b.cls == float_class_normal) { - uint64_t temp_lo, temp_hi; + uint64_t n0, n1, q, r; int exp = a.exp - b.exp; + + /* + * We want a 2*N / N-bit division to produce exactly an N-bit + * result, so that we do not lose any precision and so that we + * do not have to renormalize afterward. If A.frac < B.frac, + * then division would produce an (N-1)-bit result; shift A left + * by one to produce the an N-bit result, and decrement the + * exponent to match. + * + * The udiv_qrnnd algorithm that we're using requires normalization, + * i.e. the msb of the denominator must be set. Since we know that + * DECOMPOSED_BINARY_POINT is msb-1, the inputs must be shifted left + * by one (more), and the remainder must be shifted right by one. + */ if (a.frac < b.frac) { exp -= 1; - shortShift128Left(0, a.frac, DECOMPOSED_BINARY_POINT + 1, - &temp_hi, &temp_lo); + shift128Left(0, a.frac, DECOMPOSED_BINARY_POINT + 2, &n1, &n0); } else { - shortShift128Left(0, a.frac, DECOMPOSED_BINARY_POINT, - &temp_hi, &temp_lo); + shift128Left(0, a.frac, DECOMPOSED_BINARY_POINT + 1, &n1, &n0); } - /* LSB of quot is set if inexact which roundandpack will use - * to set flags. Yet again we re-use a for the result */ - a.frac = div128To64(temp_lo, temp_hi, b.frac); + q = udiv_qrnnd(&r, n1, n0, b.frac << 1); + + /* + * Set lsb if there is a remainder, to set inexact. + * As mentioned above, to find the actual value of the remainder we + * would need to shift right, but (1) we are only concerned about + * non-zero-ness, and (2) the remainder will always be even because + * both inputs to the division primitive are even. + */ + a.frac = q | (r != 0); a.sign = sign; a.exp = exp; return a;