Linux-2.6.12-rc2
[linux-2.6] / arch / i386 / math-emu / reg_norm.S
1 /*---------------------------------------------------------------------------+
2  |  reg_norm.S                                                               |
3  |                                                                           |
4  | Copyright (C) 1992,1993,1994,1995,1997                                    |
5  |                       W. Metzenthen, 22 Parker St, Ormond, Vic 3163,      |
6  |                       Australia.  E-mail billm@suburbia.net               |
7  |                                                                           |
8  | Normalize the value in a FPU_REG.                                         |
9  |                                                                           |
10  | Call from C as:                                                           |
11  |    int FPU_normalize(FPU_REG *n)                                          |
12  |                                                                           |
13  |    int FPU_normalize_nuo(FPU_REG *n)                                      |
14  |                                                                           |
15  |    Return value is the tag of the answer, or-ed with FPU_Exception if     |
16  |    one was raised, or -1 on internal error.                               |
17  |                                                                           |
18  +---------------------------------------------------------------------------*/
19
20 #include "fpu_emu.h"
21
22
23 .text
24 ENTRY(FPU_normalize)
25         pushl   %ebp
26         movl    %esp,%ebp
27         pushl   %ebx
28
29         movl    PARAM1,%ebx
30
31         movl    SIGH(%ebx),%edx
32         movl    SIGL(%ebx),%eax
33
34         orl     %edx,%edx       /* ms bits */
35         js      L_done          /* Already normalized */
36         jnz     L_shift_1       /* Shift left 1 - 31 bits */
37
38         orl     %eax,%eax
39         jz      L_zero          /* The contents are zero */
40
41         movl    %eax,%edx
42         xorl    %eax,%eax
43         subw    $32,EXP(%ebx)   /* This can cause an underflow */
44
45 /* We need to shift left by 1 - 31 bits */
46 L_shift_1:
47         bsrl    %edx,%ecx       /* get the required shift in %ecx */
48         subl    $31,%ecx
49         negl    %ecx
50         shld    %cl,%eax,%edx
51         shl     %cl,%eax
52         subw    %cx,EXP(%ebx)   /* This can cause an underflow */
53
54         movl    %edx,SIGH(%ebx)
55         movl    %eax,SIGL(%ebx)
56
57 L_done:
58         cmpw    EXP_OVER,EXP(%ebx)
59         jge     L_overflow
60
61         cmpw    EXP_UNDER,EXP(%ebx)
62         jle     L_underflow
63
64 L_exit_valid:
65         movl    TAG_Valid,%eax
66
67         /* Convert the exponent to 80x87 form. */
68         addw    EXTENDED_Ebias,EXP(%ebx)
69         andw    $0x7fff,EXP(%ebx)
70
71 L_exit:
72         popl    %ebx
73         leave
74         ret
75
76
77 L_zero:
78         movw    $0,EXP(%ebx)
79         movl    TAG_Zero,%eax
80         jmp     L_exit
81
82 L_underflow:
83         /* Convert the exponent to 80x87 form. */
84         addw    EXTENDED_Ebias,EXP(%ebx)
85         push    %ebx
86         call    arith_underflow
87         pop     %ebx
88         jmp     L_exit
89
90 L_overflow:
91         /* Convert the exponent to 80x87 form. */
92         addw    EXTENDED_Ebias,EXP(%ebx)
93         push    %ebx
94         call    arith_overflow
95         pop     %ebx
96         jmp     L_exit
97
98
99
100 /* Normalise without reporting underflow or overflow */
101 ENTRY(FPU_normalize_nuo)
102         pushl   %ebp
103         movl    %esp,%ebp
104         pushl   %ebx
105
106         movl    PARAM1,%ebx
107
108         movl    SIGH(%ebx),%edx
109         movl    SIGL(%ebx),%eax
110
111         orl     %edx,%edx       /* ms bits */
112         js      L_exit_nuo_valid        /* Already normalized */
113         jnz     L_nuo_shift_1   /* Shift left 1 - 31 bits */
114
115         orl     %eax,%eax
116         jz      L_exit_nuo_zero         /* The contents are zero */
117
118         movl    %eax,%edx
119         xorl    %eax,%eax
120         subw    $32,EXP(%ebx)   /* This can cause an underflow */
121
122 /* We need to shift left by 1 - 31 bits */
123 L_nuo_shift_1:
124         bsrl    %edx,%ecx       /* get the required shift in %ecx */
125         subl    $31,%ecx
126         negl    %ecx
127         shld    %cl,%eax,%edx
128         shl     %cl,%eax
129         subw    %cx,EXP(%ebx)   /* This can cause an underflow */
130
131         movl    %edx,SIGH(%ebx)
132         movl    %eax,SIGL(%ebx)
133
134 L_exit_nuo_valid:
135         movl    TAG_Valid,%eax
136
137         popl    %ebx
138         leave
139         ret
140
141 L_exit_nuo_zero:
142         movl    TAG_Zero,%eax
143         movw    EXP_UNDER,EXP(%ebx)
144
145         popl    %ebx
146         leave
147         ret