Update.
[glibc.git] / sysdeps / i386 / fpu / e_scalb.S
blob1596f6a700a2a0eb225c55f1e326895e96418bd8
1 /*
2  * Written by J.T. Conklin <jtc@netbsd.org>.
3  * Public domain.
4  *
5  * Correct handling of y==-inf <drepper@gnu>
6  */
8 #include <machine/asm.h>
10 RCSID("$NetBSD: e_scalb.S,v 1.4 1995/05/08 23:49:52 jtc Exp $")
12 #ifdef __ELF__
13         .section .rodata
14 #else
15         .text
16 #endif
18         .align ALIGNARG(4)
19         ASM_TYPE_DIRECTIVE(zero_nan,@object)
20 zero_nan:
21         .double 0.0
22 nan:    .byte 0, 0, 0, 0, 0, 0, 0xff, 0x7f
23 minus_zero:
24         .byte 0, 0, 0, 0, 0, 0, 0, 0x80
25         .byte 0, 0, 0, 0, 0, 0, 0xff, 0x7f
26         ASM_SIZE_DIRECTIVE(zero_nan)
29 #ifdef PIC
30 #define MO(op) op##@GOTOFF(%ecx)
31 #define MOX(op,x,f) op##@GOTOFF(%ecx,x,f)
32 #else
33 #define MO(op) op
34 #define MOX(op,x,f) op(,x,f)
35 #endif
37         .text
38 ENTRY(__ieee754_scalb)
39         fldl    12(%esp)
40         fxam
41         fnstsw
42         fldl    4(%esp)
43         andl    $0x4700, %eax
44         cmpl    $0x0700, %eax
45         je      1f
46         andl    $0x4500, %eax
47         cmpl    $0x0100, %eax
48         je      2f
49         fxam
50         fnstsw
51         andl    $0x4500, %eax
52         cmpl    $0x0100, %eax
53         je      3f
54         fld     %st(1)
55         frndint
56         fcomp   %st(2)
57         fnstsw
58         sahf
59         jne     4f
60         fscale
61         fstp    %st(1)
62         ret
64         /* y is -inf */
65 1:      fxam
66 #ifdef  PIC
67         call    1f
68 1:      popl    %ecx
69         addl    $_GLOBAL_OFFSET_TABLE_+[.-1b], %ecx
70 #endif
71         fnstsw
72         movl    8(%esp), %edx
73         shrl    $5, %eax
74         fstp    %st
75         fstp    %st
76         andl    $0x80000000, %edx
77         andl    $8, %eax
78         jnz     4f
79         shrl    $27, %edx
80         addl    %edx, %eax
81         fldl    MOX(zero_nan, %eax, 1)
82         ret
84         /* The result is NaN, but we must not raise an exception.
85            So use a variable.  */
86 2:      fstp    %st
87         fstp    %st
88 #ifdef  PIC
89         call    1f
90 1:      popl    %ecx
91         addl    $_GLOBAL_OFFSET_TABLE_+[.-1b], %ecx
92 #endif
93         fldl    MO(nan)
94         ret
96         /* The first parameter is a NaN.  Return it.  */
97 3:      fstp    %st(1)
98         ret
100         /* Return NaN and raise the invalid exception.  */
101 4:      fstp    %st
102         fstp    %st
103         fldz
104         fdiv    %st
105         ret
106 END(__ieee754_scalb)