mirror of
git://sourceware.org/git/glibc.git
synced 2024-12-15 04:20:28 +08:00
40244be372
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. [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.
90 lines
1.4 KiB
ArmAsm
90 lines
1.4 KiB
ArmAsm
/*
|
|
* Written by J.T. Conklin <jtc@netbsd.org>.
|
|
* Public domain.
|
|
*
|
|
* Adapted for `long double' by Ulrich Drepper <drepper@cygnus.com>.
|
|
* Adapted for x86-64 by Andreas Jaeger <aj@suse.de>
|
|
*
|
|
* Correct handling of y==-inf <drepper@gnu>
|
|
*/
|
|
|
|
#include <machine/asm.h>
|
|
|
|
.section .rodata
|
|
|
|
.align ALIGNARG(4)
|
|
.type zero_nan,@object
|
|
zero_nan:
|
|
.double 0.0
|
|
nan: .byte 0, 0, 0, 0, 0, 0, 0xff, 0x7f
|
|
.byte 0, 0, 0, 0, 0, 0, 0, 0x80
|
|
.byte 0, 0, 0, 0, 0, 0, 0xff, 0x7f
|
|
ASM_SIZE_DIRECTIVE(zero_nan)
|
|
|
|
|
|
#ifdef PIC
|
|
# define MO(op) op##(%rip)
|
|
#else
|
|
# define MO(op) op
|
|
#endif
|
|
|
|
.text
|
|
ENTRY(__ieee754_scalbl)
|
|
fldt 24(%rsp)
|
|
fxam
|
|
fnstsw
|
|
fldt 8(%rsp)
|
|
andl $0x4700, %eax
|
|
cmpl $0x0700, %eax
|
|
je 1f
|
|
andl $0x4500, %eax
|
|
cmpl $0x0100, %eax
|
|
je 2f
|
|
fxam
|
|
fnstsw
|
|
andl $0x4500, %eax
|
|
cmpl $0x0100, %eax
|
|
je 2f
|
|
fld %st(1)
|
|
frndint
|
|
fcomip %st(2), %st
|
|
jne 4f
|
|
fscale
|
|
fstp %st(1)
|
|
ret
|
|
|
|
/* y is -inf */
|
|
1: fxam
|
|
fnstsw
|
|
movl 16(%rsp), %edx
|
|
shrl $5, %eax
|
|
fstp %st
|
|
fstp %st
|
|
andl $0x8000, %edx
|
|
andl $0x0228, %eax
|
|
cmpl $0x0028, %eax
|
|
je 4f
|
|
andl $8, %eax
|
|
shrl $11, %edx
|
|
addl %edx, %eax
|
|
#ifdef PIC
|
|
lea zero_nan(%rip),%rdx
|
|
fldl (%rdx,%rax,1)
|
|
#else
|
|
fldl zero_nan(%rax, 1)
|
|
#endif
|
|
ret
|
|
|
|
/* The result is NaN; raise an exception for sNaN arguments. */
|
|
2: faddp
|
|
ret
|
|
|
|
/* Return NaN and raise the invalid exception. */
|
|
4: fstp %st
|
|
fstp %st
|
|
fldz
|
|
fdiv %st
|
|
ret
|
|
END(__ieee754_scalbl)
|
|
strong_alias (__ieee754_scalbl, __scalbl_finite)
|