2.9
[glibc/nacl-glibc.git] / sysdeps / x86_64 / fpu / e_scalbl.S
blob6b229705ba2afc7237626e1c1dc97f6a149eda22
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  * Adapted for x86-64 by Andreas Jaeger <aj@suse.de>
7  *
8  * Correct handling of y==-inf <drepper@gnu>
9  */
11 #include <machine/asm.h>
13 RCSID("$NetBSD: $")
15 #ifdef __ELF__
16         .section .rodata
17 #else
18         .text
19 #endif
21         .align ALIGNARG(4)
22         ASM_TYPE_DIRECTIVE(zero_nan,@object)
23 zero_nan:
24         .double 0.0
25 nan:    .byte 0, 0, 0, 0, 0, 0, 0xff, 0x7f
26 minus_zero:
27         .byte 0, 0, 0, 0, 0, 0, 0, 0x80
28         .byte 0, 0, 0, 0, 0, 0, 0xff, 0x7f
29         ASM_SIZE_DIRECTIVE(zero_nan)
32 #ifdef PIC
33 #define MO(op) op##(%rip)
34 #else
35 #define MO(op) op
36 #endif
38         .text
39 ENTRY(__ieee754_scalbl)
40         fldt    24(%rsp)
41         fxam
42         fnstsw
43         fldt    8(%rsp)
44         andl    $0x4700, %eax
45         cmpl    $0x0700, %eax
46         je      1f
47         andl    $0x4500, %eax
48         cmpl    $0x0100, %eax
49         je      2f
50         fxam
51         fnstsw
52         andl    $0x4500, %eax
53         cmpl    $0x0100, %eax
54         je      3f
55         fld     %st(1)
56         frndint
57         fcomip  %st(2), %st
58         jne     4f
59         fscale
60         fstp    %st(1)
61         ret
63         /* y is -inf */
64 1:      fxam
65         fnstsw
66         movl    16(%rsp), %edx
67         shrl    $5, %eax
68         fstp    %st
69         fstp    %st
70         andl    $0x8000, %edx
71         andl    $8, %eax
72         jnz     4f
73         shrl    $11, %edx
74         addl    %edx, %eax
75 #ifdef PIC
76         lea     zero_nan(%rip),%rdx
77         fldl    (%rdx,%rax,1)
78 #else
79         fldl    zero_nan(%rax, 1)
80 #endif
81         ret
83         /* The result is NaN, but we must not raise an exception.
84            So use a variable.  */
85 2:      fstp    %st
86         fstp    %st
87         fldl    MO(nan)
88         ret
90         /* The first parameter is a NaN.  Return it.  */
91 3:      fstp    %st(1)
92         ret
94         /* Return NaN and raise the invalid exception.  */
95 4:      fstp    %st
96         fstp    %st
97         fldz
98         fdiv    %st
99         ret
100 END(__ieee754_scalbl)