Fix x86/x86_64 scalb (qNaN, -Inf) (bug 16783).
[glibc.git] / sysdeps / i386 / fpu / e_scalbl.S
blobd10b22ea834424efe1ffc046810ff8606837703e
1 /*
2  * Written by J.T. Conklin <jtc@netbsd.org>.
3  * Public domain.
4  *
5  * Adapted for `long double' by Ulrich Drepper <drepper@cygnus.com>.
6  *
7  * Correct handling of y==-inf <drepper@gnu>
8  */
10 #include <machine/asm.h>
12         .section .rodata
14         .align ALIGNARG(4)
15         .type zero_nan,@object
16 zero_nan:
17         .double 0.0
18 nan:    .byte 0, 0, 0, 0, 0, 0, 0xff, 0x7f
19         .byte 0, 0, 0, 0, 0, 0, 0, 0x80
20         .byte 0, 0, 0, 0, 0, 0, 0xff, 0x7f
21         ASM_SIZE_DIRECTIVE(zero_nan)
24 #ifdef PIC
25 # define MO(op) op##@GOTOFF(%ecx)
26 # define MOX(op,x,f) op##@GOTOFF(%ecx,x,f)
27 #else
28 # define MO(op) op
29 # define MOX(op,x,f) op(,x,f)
30 #endif
32         .text
33 ENTRY(__ieee754_scalbl)
34         fldt    16(%esp)
35         fxam
36         fnstsw
37         fldt    4(%esp)
38         andl    $0x4700, %eax
39         cmpl    $0x0700, %eax
40         je      1f
41         andl    $0x4500, %eax
42         cmpl    $0x0100, %eax
43         je      2f
44         fxam
45         fnstsw
46         andl    $0x4500, %eax
47         cmpl    $0x0100, %eax
48         je      3f
49         fld     %st(1)
50         frndint
51         fcomp   %st(2)
52         fnstsw
53         sahf
54         jne     4f
55         fscale
56         fstp    %st(1)
57         ret
59         /* y is -inf */
60 1:      fxam
61 #ifdef  PIC
62         LOAD_PIC_REG (cx)
63 #endif
64         fnstsw
65         movl    12(%esp), %edx
66         shrl    $5, %eax
67         fstp    %st
68         fstp    %st
69         andl    $0x8000, %edx
70         andl    $0x0228, %eax
71         cmpl    $0x0028, %eax
72         je      4f
73         andl    $8, %eax
74         shrl    $11, %edx
75         addl    %edx, %eax
76         fldl    MOX(zero_nan, %eax, 1)
77         ret
79         /* The result is NaN, but we must not raise an exception.
80            So use a variable.  */
81 2:      fstp    %st
82         fstp    %st
83 #ifdef  PIC
84         LOAD_PIC_REG (cx)
85 #endif
86         fldl    MO(nan)
87         ret
89         /* The first parameter is a NaN.  Return it.  */
90 3:      fstp    %st(1)
91         ret
93         /* Return NaN and raise the invalid exception.  */
94 4:      fstp    %st
95         fstp    %st
96         fldz
97         fdiv    %st
98         ret
99 END(__ieee754_scalbl)
100 strong_alias (__ieee754_scalbl, __scalbl_finite)