From patchwork Thu Jun 23 22:18:31 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Joseph Myers X-Patchwork-Id: 13351 Received: (qmail 9142 invoked by alias); 23 Jun 2016 22:18:38 -0000 Mailing-List: contact libc-alpha-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: libc-alpha-owner@sourceware.org Delivered-To: mailing list libc-alpha@sourceware.org Received: (qmail 9132 invoked by uid 89); 23 Jun 2016 22:18:38 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-1.0 required=5.0 tests=AWL, BAYES_20, RCVD_IN_DNSWL_NONE, SPF_PASS autolearn=ham version=3.3.2 spammy=Committed, ERRNO_UNCHANGED, sk:no_inex, TEST_ff_f X-HELO: relay1.mentorg.com Date: Thu, 23 Jun 2016 22:18:31 +0000 From: Joseph Myers To: Subject: Fix i386/x86_64 scalbl with sNaN input (bug 20296) [committed] Message-ID: User-Agent: Alpine 2.20 (DEB 67 2015-01-07) MIME-Version: 1.0 The x86_64 and i386 versions of scalbl return sNaN for some cases of sNaN input and are missing "invalid" exceptions for other cases. This results from overly complicated code that either returns a NaN input, or discards both inputs when one is NaN and loads a NaN from memory. This patch fixes this by simplifying the code to add the arguments when either one is NaN. Tested for x86_64 and x86. Committed. 2016-06-23 Joseph Myers [BZ #20296] * sysdeps/i386/fpu/e_scalbl.S (__ieee754_scalbl): Add arguments when either argument is a NaN. * sysdeps/x86_64/fpu/e_scalbl.S (__ieee754_scalbl): Likewise. * math/libm-test.inc (scalb_test_data): Add sNaN tests. diff --git a/math/libm-test.inc b/math/libm-test.inc index 3e4ef18..7334a48 100644 --- a/math/libm-test.inc +++ b/math/libm-test.inc @@ -11598,6 +11598,10 @@ static const struct test_ff_f_data scalb_test_data[] = TEST_ff_f (scalb, 0, -qnan_value, qnan_value, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED), TEST_ff_f (scalb, 1, qnan_value, qnan_value, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED), TEST_ff_f (scalb, 1, -qnan_value, qnan_value, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED), + TEST_ff_f (scalb, 0, snan_value, qnan_value, NO_INEXACT_EXCEPTION|INVALID_EXCEPTION), + TEST_ff_f (scalb, 0, -snan_value, qnan_value, NO_INEXACT_EXCEPTION|INVALID_EXCEPTION), + TEST_ff_f (scalb, 1, snan_value, qnan_value, NO_INEXACT_EXCEPTION|INVALID_EXCEPTION), + TEST_ff_f (scalb, 1, -snan_value, qnan_value, NO_INEXACT_EXCEPTION|INVALID_EXCEPTION), TEST_ff_f (scalb, 1, 0, 1, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED), TEST_ff_f (scalb, -1, 0, -1, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED), @@ -11634,28 +11638,60 @@ static const struct test_ff_f_data scalb_test_data[] = TEST_ff_f (scalb, qnan_value, 1, qnan_value, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED), TEST_ff_f (scalb, -qnan_value, 1, qnan_value, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED), + TEST_ff_f (scalb, snan_value, 1, qnan_value, NO_INEXACT_EXCEPTION|INVALID_EXCEPTION), + TEST_ff_f (scalb, -snan_value, 1, qnan_value, NO_INEXACT_EXCEPTION|INVALID_EXCEPTION), TEST_ff_f (scalb, 1, qnan_value, qnan_value, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED), TEST_ff_f (scalb, 1, -qnan_value, qnan_value, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED), + TEST_ff_f (scalb, 1, snan_value, qnan_value, NO_INEXACT_EXCEPTION|INVALID_EXCEPTION), + TEST_ff_f (scalb, 1, -snan_value, qnan_value, NO_INEXACT_EXCEPTION|INVALID_EXCEPTION), TEST_ff_f (scalb, qnan_value, 0.5, qnan_value, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED), TEST_ff_f (scalb, -qnan_value, 0.5, qnan_value, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED), + TEST_ff_f (scalb, snan_value, 0.5, qnan_value, NO_INEXACT_EXCEPTION|INVALID_EXCEPTION), + TEST_ff_f (scalb, -snan_value, 0.5, qnan_value, NO_INEXACT_EXCEPTION|INVALID_EXCEPTION), TEST_ff_f (scalb, 0.5, qnan_value, qnan_value, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED), TEST_ff_f (scalb, 0.5, -qnan_value, qnan_value, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED), + TEST_ff_f (scalb, 0.5, snan_value, qnan_value, NO_INEXACT_EXCEPTION|INVALID_EXCEPTION), + TEST_ff_f (scalb, 0.5, -snan_value, qnan_value, NO_INEXACT_EXCEPTION|INVALID_EXCEPTION), TEST_ff_f (scalb, qnan_value, 0, qnan_value, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED), TEST_ff_f (scalb, -qnan_value, 0, qnan_value, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED), + TEST_ff_f (scalb, snan_value, 0, qnan_value, NO_INEXACT_EXCEPTION|INVALID_EXCEPTION), + TEST_ff_f (scalb, -snan_value, 0, qnan_value, NO_INEXACT_EXCEPTION|INVALID_EXCEPTION), TEST_ff_f (scalb, 0, qnan_value, qnan_value, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED), TEST_ff_f (scalb, 0, -qnan_value, qnan_value, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED), + TEST_ff_f (scalb, 0, snan_value, qnan_value, NO_INEXACT_EXCEPTION|INVALID_EXCEPTION), + TEST_ff_f (scalb, 0, -snan_value, qnan_value, NO_INEXACT_EXCEPTION|INVALID_EXCEPTION), TEST_ff_f (scalb, qnan_value, plus_infty, qnan_value, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED), TEST_ff_f (scalb, -qnan_value, plus_infty, qnan_value, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED), + TEST_ff_f (scalb, snan_value, plus_infty, qnan_value, NO_INEXACT_EXCEPTION|INVALID_EXCEPTION), + TEST_ff_f (scalb, -snan_value, plus_infty, qnan_value, NO_INEXACT_EXCEPTION|INVALID_EXCEPTION), TEST_ff_f (scalb, plus_infty, qnan_value, qnan_value, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED), TEST_ff_f (scalb, plus_infty, -qnan_value, qnan_value, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED), + TEST_ff_f (scalb, plus_infty, snan_value, qnan_value, NO_INEXACT_EXCEPTION|INVALID_EXCEPTION), + TEST_ff_f (scalb, plus_infty, -snan_value, qnan_value, NO_INEXACT_EXCEPTION|INVALID_EXCEPTION), TEST_ff_f (scalb, qnan_value, minus_infty, qnan_value, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED), TEST_ff_f (scalb, -qnan_value, minus_infty, qnan_value, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED), + TEST_ff_f (scalb, snan_value, minus_infty, qnan_value, NO_INEXACT_EXCEPTION|INVALID_EXCEPTION), + TEST_ff_f (scalb, -snan_value, minus_infty, qnan_value, NO_INEXACT_EXCEPTION|INVALID_EXCEPTION), TEST_ff_f (scalb, minus_infty, qnan_value, qnan_value, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED), TEST_ff_f (scalb, minus_infty, -qnan_value, qnan_value, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED), + TEST_ff_f (scalb, minus_infty, snan_value, qnan_value, NO_INEXACT_EXCEPTION|INVALID_EXCEPTION), + TEST_ff_f (scalb, minus_infty, -snan_value, qnan_value, NO_INEXACT_EXCEPTION|INVALID_EXCEPTION), TEST_ff_f (scalb, qnan_value, qnan_value, qnan_value, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED), TEST_ff_f (scalb, qnan_value, -qnan_value, qnan_value, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED), TEST_ff_f (scalb, -qnan_value, qnan_value, qnan_value, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED), TEST_ff_f (scalb, -qnan_value, -qnan_value, qnan_value, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED), + TEST_ff_f (scalb, snan_value, qnan_value, qnan_value, NO_INEXACT_EXCEPTION|INVALID_EXCEPTION), + TEST_ff_f (scalb, snan_value, -qnan_value, qnan_value, NO_INEXACT_EXCEPTION|INVALID_EXCEPTION), + TEST_ff_f (scalb, -snan_value, qnan_value, qnan_value, NO_INEXACT_EXCEPTION|INVALID_EXCEPTION), + TEST_ff_f (scalb, -snan_value, -qnan_value, qnan_value, NO_INEXACT_EXCEPTION|INVALID_EXCEPTION), + TEST_ff_f (scalb, qnan_value, snan_value, qnan_value, NO_INEXACT_EXCEPTION|INVALID_EXCEPTION), + TEST_ff_f (scalb, qnan_value, -snan_value, qnan_value, NO_INEXACT_EXCEPTION|INVALID_EXCEPTION), + TEST_ff_f (scalb, -qnan_value, snan_value, qnan_value, NO_INEXACT_EXCEPTION|INVALID_EXCEPTION), + TEST_ff_f (scalb, -qnan_value, -snan_value, qnan_value, NO_INEXACT_EXCEPTION|INVALID_EXCEPTION), + TEST_ff_f (scalb, snan_value, snan_value, qnan_value, NO_INEXACT_EXCEPTION|INVALID_EXCEPTION), + TEST_ff_f (scalb, snan_value, -snan_value, qnan_value, NO_INEXACT_EXCEPTION|INVALID_EXCEPTION), + TEST_ff_f (scalb, -snan_value, snan_value, qnan_value, NO_INEXACT_EXCEPTION|INVALID_EXCEPTION), + TEST_ff_f (scalb, -snan_value, -snan_value, qnan_value, NO_INEXACT_EXCEPTION|INVALID_EXCEPTION), TEST_ff_f (scalb, max_value, max_value, plus_oflow, INEXACT_EXCEPTION|OVERFLOW_EXCEPTION|ERRNO_PLUS_OFLOW), TEST_ff_f (scalb, max_value, -max_value, plus_uflow, INEXACT_EXCEPTION|UNDERFLOW_EXCEPTION|ERRNO_PLUS_UFLOW), diff --git a/sysdeps/i386/fpu/e_scalbl.S b/sysdeps/i386/fpu/e_scalbl.S index d10b22e..896f599 100644 --- a/sysdeps/i386/fpu/e_scalbl.S +++ b/sysdeps/i386/fpu/e_scalbl.S @@ -45,7 +45,7 @@ ENTRY(__ieee754_scalbl) fnstsw andl $0x4500, %eax cmpl $0x0100, %eax - je 3f + je 2f fld %st(1) frndint fcomp %st(2) @@ -76,18 +76,8 @@ ENTRY(__ieee754_scalbl) fldl MOX(zero_nan, %eax, 1) ret - /* The result is NaN, but we must not raise an exception. - So use a variable. */ -2: fstp %st - fstp %st -#ifdef PIC - LOAD_PIC_REG (cx) -#endif - fldl MO(nan) - ret - - /* The first parameter is a NaN. Return it. */ -3: fstp %st(1) + /* The result is NaN; raise an exception for sNaN arguments. */ +2: faddp ret /* Return NaN and raise the invalid exception. */ diff --git a/sysdeps/x86_64/fpu/e_scalbl.S b/sysdeps/x86_64/fpu/e_scalbl.S index 331bee5..2982dc3 100644 --- a/sysdeps/x86_64/fpu/e_scalbl.S +++ b/sysdeps/x86_64/fpu/e_scalbl.S @@ -44,7 +44,7 @@ ENTRY(__ieee754_scalbl) fnstsw andl $0x4500, %eax cmpl $0x0100, %eax - je 3f + je 2f fld %st(1) frndint fcomip %st(2), %st @@ -75,15 +75,8 @@ ENTRY(__ieee754_scalbl) #endif ret - /* The result is NaN, but we must not raise an exception. - So use a variable. */ -2: fstp %st - fstp %st - fldl MO(nan) - ret - - /* The first parameter is a NaN. Return it. */ -3: fstp %st(1) + /* The result is NaN; raise an exception for sNaN arguments. */ +2: faddp ret /* Return NaN and raise the invalid exception. */