From patchwork Fri Oct 4 22:51:54 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Joseph Myers X-Patchwork-Id: 280802 Return-Path: X-Original-To: patchwork-incoming@ozlabs.org Delivered-To: patchwork-incoming@ozlabs.org Received: from ozlabs.org (localhost [IPv6:::1]) by ozlabs.org (Postfix) with ESMTP id A866F2C0397 for ; Sun, 6 Oct 2013 08:15:58 +1100 (EST) X-Greylist: delayed 1530 seconds by postgrey-1.34 at bilbo; Sat, 05 Oct 2013 09:16:18 EST Received: from relay1.mentorg.com (relay1.mentorg.com [192.94.38.131]) (using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits)) (Client CN "relay1.mentorg.com", Issuer "Entrust Certification Authority - L1C" (not verified)) by ozlabs.org (Postfix) with ESMTPS id 4CCFD2C00CB for ; Sat, 5 Oct 2013 09:16:17 +1000 (EST) Received: from svr-orw-fem-01.mgc.mentorg.com ([147.34.98.93]) by relay1.mentorg.com with esmtp id 1VSEGX-00021c-46 from joseph_myers@mentor.com ; Fri, 04 Oct 2013 15:54:33 -0700 Received: from SVR-IES-FEM-01.mgc.mentorg.com ([137.202.0.104]) by svr-orw-fem-01.mgc.mentorg.com over TLS secured channel with Microsoft SMTPSVC(6.0.3790.4675); Fri, 4 Oct 2013 15:52:04 -0700 Received: from digraph.polyomino.org.uk (137.202.0.76) by SVR-IES-FEM-01.mgc.mentorg.com (137.202.0.104) with Microsoft SMTP Server id 14.2.247.3; Fri, 4 Oct 2013 23:51:55 +0100 Received: from jsm28 (helo=localhost) by digraph.polyomino.org.uk with local-esmtp (Exim 4.76) (envelope-from ) id 1VSEDy-0008SX-5n; Fri, 04 Oct 2013 22:51:54 +0000 Date: Fri, 4 Oct 2013 22:51:54 +0000 From: "Joseph S. Myers" X-X-Sender: jsm28@digraph.polyomino.org.uk To: Subject: [PATCH] powerpc: fix e500 SPE float rounding inexactness detection Message-ID: MIME-Version: 1.0 X-OriginalArrivalTime: 04 Oct 2013 22:52:04.0004 (UTC) FILETIME=[581D1E40:01CEC154] X-Mailman-Approved-At: Sun, 06 Oct 2013 08:15:30 +1100 Cc: linux-kernel@vger.kernel.org X-BeenThere: linuxppc-dev@lists.ozlabs.org X-Mailman-Version: 2.1.16rc2 Precedence: list List-Id: Linux on PowerPC Developers Mail List List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: linuxppc-dev-bounces+patchwork-incoming=ozlabs.org@lists.ozlabs.org Sender: "Linuxppc-dev" From: Joseph Myers The e500 SPE floating-point emulation code for the rounding modes rounding to positive or negative infinity (which may not be implemented in hardware) tries to avoid emulating rounding if the result was inexact. However, it tests inexactness using the sticky bit with the cumulative result of previous operations, rather than with the non-sticky bits relating to the operation that generated the interrupt. Furthermore, when a vector operation generates the interrupt, it's possible that only one of the low and high parts is inexact, and so only that part should have rounding emulated. This results in incorrect rounding of exact results in these modes when the sticky bit is set from a previous operation. (I'm not sure why the rounding interrupts are generated at all when the result is exact, but empirically the hardware does generate them.) This patch checks for inexactness using the correct bits of SPEFSCR, and ensures that rounding only occurs when the relevant part of the result was actually inexact. Signed-off-by: Joseph Myers diff --git a/arch/powerpc/math-emu/math_efp.c b/arch/powerpc/math-emu/math_efp.c index a73f088..ecdf35d 100644 --- a/arch/powerpc/math-emu/math_efp.c +++ b/arch/powerpc/math-emu/math_efp.c @@ -662,7 +680,8 @@ int speround_handler(struct pt_regs *regs) { union dw_union fgpr; int s_lo, s_hi; - unsigned long speinsn, type, fc; + int lo_inexact, hi_inexact; + unsigned long speinsn, type, fc, fptype; if (get_user(speinsn, (unsigned int __user *) regs->nip)) return -EFAULT; @@ -675,8 +694,12 @@ int speround_handler(struct pt_regs *regs) __FPU_FPSCR = mfspr(SPRN_SPEFSCR); pr_debug("speinsn:%08lx spefscr:%08lx\n", speinsn, __FPU_FPSCR); + fptype = (speinsn >> 5) & 0x7; + /* No need to round if the result is exact */ - if (!(__FPU_FPSCR & FP_EX_INEXACT)) + lo_inexact = __FPU_FPSCR & (SPEFSCR_FG | SPEFSCR_FX); + hi_inexact = __FPU_FPSCR & (SPEFSCR_FGH | SPEFSCR_FXH); + if (!(lo_inexact || (hi_inexact && fptype == VCT))) return 0; fc = (speinsn >> 21) & 0x1f; @@ -687,7 +710,7 @@ int speround_handler(struct pt_regs *regs) pr_debug("round fgpr: %08x %08x\n", fgpr.wp[0], fgpr.wp[1]); - switch ((speinsn >> 5) & 0x7) { + switch (fptype) { /* Since SPE instructions on E500 core can handle round to nearest * and round toward zero with IEEE-754 complied, we just need * to handle round toward +Inf and round toward -Inf by software. @@ -710,11 +733,15 @@ int speround_handler(struct pt_regs *regs) case VCT: if (FP_ROUNDMODE == FP_RND_PINF) { - if (!s_lo) fgpr.wp[1]++; /* Z_low > 0, choose Z1 */ - if (!s_hi) fgpr.wp[0]++; /* Z_high word > 0, choose Z1 */ + if (lo_inexact && !s_lo) + fgpr.wp[1]++; /* Z_low > 0, choose Z1 */ + if (hi_inexact && !s_hi) + fgpr.wp[0]++; /* Z_high word > 0, choose Z1 */ } else { /* round to -Inf */ - if (s_lo) fgpr.wp[1]++; /* Z_low < 0, choose Z2 */ - if (s_hi) fgpr.wp[0]++; /* Z_high < 0, choose Z2 */ + if (lo_inexact && s_lo) + fgpr.wp[1]++; /* Z_low < 0, choose Z2 */ + if (hi_inexact && s_hi) + fgpr.wp[0]++; /* Z_high < 0, choose Z2 */ } break;