From patchwork Tue Aug 21 04:33:25 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: David Gibson X-Patchwork-Id: 144674 Delivered-To: patch@linaro.org Received: by 2002:a2e:9754:0:0:0:0:0 with SMTP id f20-v6csp4788112ljj; Mon, 20 Aug 2018 21:40:58 -0700 (PDT) X-Google-Smtp-Source: AA+uWPyMIFngfOH0Qi0iXMvDBFl8BJ+5dR6tY4ZsiaVmvjqw8WbSaESZW2smwjc58XwZpW0aMSqo X-Received: by 2002:ac8:60d7:: with SMTP id i23-v6mr10224411qtm.403.1534826458698; Mon, 20 Aug 2018 21:40:58 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1534826458; cv=none; d=google.com; s=arc-20160816; b=Vsi22P6BQVxDB1dMbKFUHpx26JSYS5KYar7iiG7lZFEUtRrlsSBXNCR3KGavRUNQ+J Ds9efGg6P6/iVIawJN0sVpDy01rGG5M++U0eTcM1qsoDb7GZCWGj3N3xH8C2onT2oiym O1xjeTdKWrKmipfsClAuU/wUKB97m79NieZvAUXzR51rNghPbA+lB/qAY4Fsqp69+q2A Ik34wdZfdRHl5T6qKHNzDd5OS+23Qy8lZR5s2OX1OJFGYNH4hEDVI79TmsaawbXK2tKr Ul2taYYZ6Ac+V0teyx6pMy//BemrgTZom89fuO+j93Q5CJyQo9ksBMnqNa0X41tPSG1z 6qHw== 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=IXXBaTw69CdLZyuZjS5xhTLSZlGdTS2N2W4F+5gesIk=; b=zXAvNEjxSVgLfkAt+GuYjt6uLR/DrIP6oLEuYC0qwNFTrwD2QNM9emIkSXw0+Puop4 YfAQWZw56ZDY32h7GLR32DqsbbW5imncNqXu0Y01KGcJPVMeGDmwMbdAIcp9Bp5+bJNP O8+/dGfcN02yhMa1sZ6lzGTWF45f2WCqTCReJNJZ/kmEDXdeLCOQyvEc1SQnN5S5iSup SiAGBg3Ql10iTBR0hdX792qGCnclql+XrAS2yyJiV3O0KX89zZgW2aQGwxFNkascVNek aAvQHDl3B/TRQa1KoZRTrR3z+zg2eVgUcEkmjrAv63eJafCRkXPUerAeO8ZO/xKl2nWK TSFA== ARC-Authentication-Results: i=1; mx.google.com; dkim=fail header.i=@gibson.dropbear.id.au header.s=201602 header.b=AmlXoGor; 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" Return-Path: Received: from lists.gnu.org (lists.gnu.org. [2001:4830:134:3::11]) by mx.google.com with ESMTPS id g25-v6si8898263qkm.263.2018.08.20.21.40.58 for (version=TLS1 cipher=AES128-SHA bits=128/128); Mon, 20 Aug 2018 21:40:58 -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=@gibson.dropbear.id.au header.s=201602 header.b=AmlXoGor; 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" Received: from localhost ([::1]:50666 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fryTS-0000J8-59 for patch@linaro.org; Tue, 21 Aug 2018 00:40:58 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:56420) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fryMp-00047P-7K for qemu-devel@nongnu.org; Tue, 21 Aug 2018 00:34:09 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1fryMl-0000It-2v for qemu-devel@nongnu.org; Tue, 21 Aug 2018 00:34:06 -0400 Received: from ozlabs.org ([203.11.71.1]:33979) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1fryMk-0000EU-5v; Tue, 21 Aug 2018 00:34:02 -0400 Received: by ozlabs.org (Postfix, from userid 1007) id 41vd9D4YQdz9s8F; Tue, 21 Aug 2018 14:33:51 +1000 (AEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=gibson.dropbear.id.au; s=201602; t=1534826032; bh=ymmkFgW2+kau1eTvEWlF10Lv92x+ZQOpCHYcA09KofI=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=AmlXoGorRRY5xVup48CYOHk8MT1B7PtpHBeuWb/91AloWA0tWtJ4FfCQ+nEMEmBFw 3RndllKVHW4YCAUyVPu6I0uMo0ueLUsYYpwhKN1KVDF9qa3YdA3lCQAjt2jk1WCPKi Z9NFtLDzKmKpSkWftPBHusyCII6N1Z3MZZ2aV+Bg= From: David Gibson To: peter.maydell@linaro.org Date: Tue, 21 Aug 2018 14:33:25 +1000 Message-Id: <20180821043343.7514-9-david@gibson.dropbear.id.au> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20180821043343.7514-1-david@gibson.dropbear.id.au> References: <20180821043343.7514-1-david@gibson.dropbear.id.au> X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] X-Received-From: 203.11.71.1 Subject: [Qemu-devel] [PULL 08/26] target/ppc: Honor fpscr_ze semantics and tidy fre, fresqrt 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: lvivier@redhat.com, aik@ozlabs.ru, Richard Henderson , groug@kaod.org, qemu-devel@nongnu.org, qemu-ppc@nongnu.org, clg@kaod.org, David Gibson Errors-To: qemu-devel-bounces+patch=linaro.org@nongnu.org Sender: "Qemu-devel" From: Richard Henderson Divide by zero, exception taken, leaves the destination register unmodified. Therefore we must raise the exception before returning from the respective helpers. >From helper_fre, divide by zero exception not taken, return the documented +/- 0.5. At the same time, tidy the invalid exception checking so that we rely on softfloat for initial argument validation, and select the kind of invalid operand exception only when we know we must. At the same time, pass and return float64 values directly rather than bounce through the CPU_DoubleU union. Signed-off-by: Richard Henderson Signed-off-by: David Gibson --- target/ppc/fpu_helper.c | 62 ++++++++++++++++++++++++----------------- 1 file changed, 37 insertions(+), 25 deletions(-) -- 2.17.1 diff --git a/target/ppc/fpu_helper.c b/target/ppc/fpu_helper.c index 44f3fed17d..5af5241ab0 100644 --- a/target/ppc/fpu_helper.c +++ b/target/ppc/fpu_helper.c @@ -879,18 +879,27 @@ float64 helper_fsqrt(CPUPPCState *env, float64 arg) } /* fre - fre. */ -uint64_t helper_fre(CPUPPCState *env, uint64_t arg) +float64 helper_fre(CPUPPCState *env, float64 arg) { - CPU_DoubleU farg; - - farg.ll = arg; + /* "Estimate" the reciprocal with actual division. */ + float64 ret = float64_div(float64_one, arg, &env->fp_status); + int status = get_float_exception_flags(&env->fp_status); - if (unlikely(float64_is_signaling_nan(farg.d, &env->fp_status))) { - /* sNaN reciprocal */ - float_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN, 1); + if (unlikely(status)) { + if (status & float_flag_invalid) { + if (float64_is_signaling_nan(arg, &env->fp_status)) { + /* sNaN reciprocal */ + float_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN, 1); + } + } + if (status & float_flag_divbyzero) { + float_zero_divide_excp(env, GETPC()); + /* For FPSCR.ZE == 0, the result is 1/2. */ + ret = float64_set_sign(float64_half, float64_is_neg(arg)); + } } - farg.d = float64_div(float64_one, farg.d, &env->fp_status); - return farg.d; + + return ret; } /* fres - fres. */ @@ -913,27 +922,30 @@ uint64_t helper_fres(CPUPPCState *env, uint64_t arg) } /* frsqrte - frsqrte. */ -uint64_t helper_frsqrte(CPUPPCState *env, uint64_t arg) +float64 helper_frsqrte(CPUPPCState *env, float64 arg) { - CPU_DoubleU farg; - - farg.ll = arg; + /* "Estimate" the reciprocal with actual division. */ + float64 rets = float64_sqrt(arg, &env->fp_status); + float64 retd = float64_div(float64_one, rets, &env->fp_status); + int status = get_float_exception_flags(&env->fp_status); - if (unlikely(float64_is_any_nan(farg.d))) { - if (unlikely(float64_is_signaling_nan(farg.d, &env->fp_status))) { - /* sNaN reciprocal square root */ - float_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN, 1); - farg.ll = float64_snan_to_qnan(farg.ll); + if (unlikely(status)) { + if (status & float_flag_invalid) { + if (float64_is_signaling_nan(arg, &env->fp_status)) { + /* sNaN reciprocal */ + float_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN, 1); + } else { + /* Square root of a negative nonzero number */ + float_invalid_op_excp(env, POWERPC_EXCP_FP_VXSQRT, 1); + } + } + if (status & float_flag_divbyzero) { + /* Reciprocal of (square root of) zero. */ + float_zero_divide_excp(env, GETPC()); } - } else if (unlikely(float64_is_neg(farg.d) && !float64_is_zero(farg.d))) { - /* Reciprocal square root of a negative nonzero number */ - farg.ll = float_invalid_op_excp(env, POWERPC_EXCP_FP_VXSQRT, 1); - } else { - farg.d = float64_sqrt(farg.d, &env->fp_status); - farg.d = float64_div(float64_one, farg.d, &env->fp_status); } - return farg.ll; + return retd; } /* fsel - fsel. */