From patchwork Tue Oct 2 19:53:47 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Richard Henderson X-Patchwork-Id: 148013 Delivered-To: patch@linaro.org Received: by 2002:a2e:8595:0:0:0:0:0 with SMTP id b21-v6csp5570331lji; Tue, 2 Oct 2018 12:55:14 -0700 (PDT) X-Google-Smtp-Source: ACcGV61QsXM76o9+sefRxv+GqwOG+smRjz0bU7HdXB5CZ+sTMQpEWOxDmr7nkEGib/nueXvrzKDu X-Received: by 2002:aed:3539:: with SMTP id a54-v6mr13792632qte.153.1538510114639; Tue, 02 Oct 2018 12:55:14 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1538510114; cv=none; d=google.com; s=arc-20160816; b=SuGOQz1Sv2Di9BEsu+NzAB/d0N0HDF8zPQLhBI+YIjFEdK2djFB7Umn6rwDih2LJRA M0UvOYQaVxwxZdhDmnsW496lBXZI4+6bbeFuQh2Tr9jgv8ruEOSUHF6a/Rtcil0Rc5Nx rIH09njMKc9VBVCHU8QM+7g7HMMXaqDd5vhvmXaIMyhaEVoL6J6UEO7iFkaOw0OdG6DI otCQq5J0UxJUC5DvAp73dWo7NsruyHxzoyJJ+zw+ss60iOEZFQN0Om6cd4eYl1JMvQXP XJoKnSYs6wTwalfSdaR0MhuwZ22N1arKDcBOXIXcCb3WdEQbueVe8zQaL8iTILMowtgw vL3g== 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:message-id:date:to:from :dkim-signature; bh=fuJzerRCk5TogAmigrMxjQtsaB/o7SaXgNsZD0NNenA=; b=EMiP2twovrxnenZ+iXghUbICxCYoRJdaXlE5C3pfu1ba9dfD13MN+U364207Eozdft 1X7wv2eCf7XpLIqjT0DcN8A9K2dEEzYvNjQCrKZYxdEzkIz5vrCDfV4y3FDGkd4XuCG6 xQOt+zikzMC4WSGvAnmhsnVJr7nPuNEvtW7xIXKR1WphleHFCAP2UB/3pIddY3bforqf qkifr/IKxo3L1WhqmA4tQIn2M5ofGlJXPkW+wiH6wQJR4UZWDVqPdHji68a3ggOGllhu nck8hmEvMDNUiyx05nmeehaoT1lQQYj1AvrRwKEHTr/ObM9eTsKdCX34Orp7QXOcucBy VPPQ== ARC-Authentication-Results: i=1; mx.google.com; dkim=fail header.i=@linaro.org header.s=google header.b=Ll+tulgX; 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 d64-v6si1052663qkf.137.2018.10.02.12.55.14 for (version=TLS1 cipher=AES128-SHA bits=128/128); Tue, 02 Oct 2018 12:55:14 -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=Ll+tulgX; 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]:45367 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1g7QlG-0001Rt-44 for patch@linaro.org; Tue, 02 Oct 2018 15:55:14 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:52010) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1g7Qjz-0000nI-Lb for qemu-devel@nongnu.org; Tue, 02 Oct 2018 15:53:57 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1g7Qjw-0005bt-3X for qemu-devel@nongnu.org; Tue, 02 Oct 2018 15:53:55 -0400 Received: from mail-ot1-x342.google.com ([2607:f8b0:4864:20::342]:43217) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1g7Qjv-0005bF-Qx for qemu-devel@nongnu.org; Tue, 02 Oct 2018 15:53:51 -0400 Received: by mail-ot1-x342.google.com with SMTP id e21-v6so3157719otk.10 for ; Tue, 02 Oct 2018 12:53:51 -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; bh=fuJzerRCk5TogAmigrMxjQtsaB/o7SaXgNsZD0NNenA=; b=Ll+tulgX47KYiGNzrF+6YbPJ9ZVh8nvN9/aHxlGfOul7j42Hm7H78stDYN8nTiwFUb At/ekXL9RVRR1aAh24uakttKclTrnDfG7mq4RojAhUw5kTj1FpyWU1P1YgajGDuBhJfP a5qMaDEtg7AheRkhaIhh6qsKbDSx/abT+/aXI= 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; bh=fuJzerRCk5TogAmigrMxjQtsaB/o7SaXgNsZD0NNenA=; b=OviU7Hd/9jUUAvlJ5IiPYsTiIQgnMJkTNkND4vfyJAFcNCn6ghltPrwecgP7JZg2ni MjSWCZe0TbG+oXKXUEjvh8iJhezUpSuInRc6TV3AmXB6JyQhys4U3UdPFtstk8z08Lne G37u38l5XH/Izy6zrf7yzEZ+Db2/6nsBK/8G0oNgCTzRd7Ud3kBF1Q2kLHX+yY48hOer fW36sCaJNeIqdtfnAbQPbPDQLcHN/5Sv3I403yNGNxqAF6FYGsWcAP/qD+1Zv3/TfVwP 4FRRtU6QHi0w6odJ+iKj+PgmIM3IjjtJHFdoyft5Rc7fCZOTVu2HtlmgZNnWdrDtNNP+ wa1Q== X-Gm-Message-State: ABuFfojRmVH/GhAjg/Ncc87CYBzhPjQD22v3tnTRDucRkkYpbXtsKziB c+EgwSSDmOzGq0SHG4XB+K1sP7t9TfdfoQ== X-Received: by 2002:a9d:11b2:: with SMTP id v47mr4068492otf.281.1538510030725; Tue, 02 Oct 2018 12:53:50 -0700 (PDT) Received: from cloudburst.twiddle.net ([187.217.227.243]) by smtp.gmail.com with ESMTPSA id v124-v6sm1641717oie.48.2018.10.02.12.53.48 (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Tue, 02 Oct 2018 12:53:49 -0700 (PDT) From: Richard Henderson To: qemu-devel@nongnu.org Date: Tue, 2 Oct 2018 14:53:47 -0500 Message-Id: <20181002195347.26712-1-richard.henderson@linaro.org> X-Mailer: git-send-email 2.17.1 X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 2607:f8b0:4864:20::342 Subject: [Qemu-devel] [PATCH] 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: cota@braap.org, alex.bennee@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. Inline div128to64 into its one user, because it is no longer a general-purpose routine. Fixes: cf07323d494 Fixes: https://bugs.launchpad.net/qemu/+bug/1793119 Signed-off-by: Richard Henderson --- include/fpu/softfloat-macros.h | 48 ----------------------- fpu/softfloat.c | 72 ++++++++++++++++++++++++++++++---- 2 files changed, 64 insertions(+), 56 deletions(-) -- 2.17.1 Tested-by: Emilio G. Cota Reviewed-by: Alex Bennée Tested-by: Alex Bennée diff --git a/include/fpu/softfloat-macros.h b/include/fpu/softfloat-macros.h index 35e1603a5e..f29426ac46 100644 --- a/include/fpu/softfloat-macros.h +++ b/include/fpu/softfloat-macros.h @@ -625,54 +625,6 @@ static inline uint64_t estimateDiv128To64(uint64_t a0, uint64_t a1, uint64_t b) } -/* From the GNU Multi Precision Library - longlong.h __udiv_qrnnd - * (https://gmplib.org/repo/gmp/file/tip/longlong.h) - * - * Licensed under the GPLv2/LGPLv3 - */ -static inline uint64_t div128To64(uint64_t n0, uint64_t n1, 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; - - /* Return remainder in LSB */ - return (q1 << 32) | q0 | (r0 != 0); -} - /*---------------------------------------------------------------------------- | Returns an approximation to the square root of the 32-bit significand given | by `a'. Considered as an integer, `a' must be at least 2^31. If bit 0 of diff --git a/fpu/softfloat.c b/fpu/softfloat.c index 9405f12a03..93edc06996 100644 --- a/fpu/softfloat.c +++ b/fpu/softfloat.c @@ -1112,19 +1112,75 @@ 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, d0, d1, q0, q1, r1, r0, m, d; int exp = a.exp - b.exp; + + /* + * We want the 2*N / N-bit division to produce exactly an N-bit + * result, so that we do not have to renormalize afterward. + * If A < B, 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, everything must be shifted left + * by one more. + */ if (a.frac < b.frac) { exp -= 1; - shortShift128Left(0, a.frac, DECOMPOSED_BINARY_POINT + 1, - &temp_hi, &temp_lo); + shortShift128Left(0, a.frac, DECOMPOSED_BINARY_POINT + 2, &n1, &n0); } else { - shortShift128Left(0, a.frac, DECOMPOSED_BINARY_POINT, - &temp_hi, &temp_lo); + shortShift128Left(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); + d = b.frac << 1; + + /* + * From the GNU Multi Precision Library - longlong.h __udiv_qrnnd + * (https://gmplib.org/repo/gmp/file/tip/longlong.h) + * Licensed under the GPLv2/LGPLv3. + */ + 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; + /* End of __udiv_qrnnd. */ + + /* Adjust remainder for normalization step. */ + r0 >>= 1; + + /* Set lsb if there is a remainder, to set inexact. */ + a.frac = (q1 << 32) | q0 | (r0 != 0); a.sign = sign; a.exp = exp; return a;