2 /*---------------------------------------------------------------------------+
5 | Core floating point subtraction routine. |
7 | Copyright (C) 1992,1993,1995,1997 |
8 | W. Metzenthen, 22 Parker St, Ormond, Vic 3163, Australia |
9 | E-mail billm@suburbia.net |
12 | int FPU_u_sub(FPU_REG *arg1, FPU_REG *arg2, FPU_REG *answ, |
14 | Return value is the tag of the answer, or-ed with FPU_Exception if |
15 | one was raised, or -1 on internal error. |
17 +---------------------------------------------------------------------------*/
20 | Kernel subtraction routine FPU_u_sub(reg *arg1, reg *arg2, reg *answ).
21 | Takes two valid reg f.p. numbers (TAG_Valid), which are
22 | treated as unsigned numbers,
23 | and returns their difference as a TAG_Valid or TAG_Zero f.p.
25 | The first number (arg1) must be the larger.
26 | The returned number is normalized.
27 | Basic checks are performed if PARANOID is defined.
30 #include "exception.h"
32 #include "control_w.h"
42 movl PARAM1,%esi /* source 1 */
43 movl PARAM2,%edi /* source 2 */
46 subl PARAM7,%ecx /* exp1 - exp2 */
49 /* source 2 is always smaller than source 1 */
52 testl $0x80000000,SIGH(%edi) /* The args are assumed to be be normalized */
55 testl $0x80000000,SIGH(%esi)
59 /*--------------------------------------+
60 | Form a register holding the |
62 +--------------------------------------*/
63 movl SIGH(%edi),%eax /* register ms word */
64 movl SIGL(%edi),%ebx /* register ls word */
66 movl PARAM3,%edi /* destination */
68 movw %dx,EXP(%edi) /* Copy exponent to destination */
70 xorl %edx,%edx /* register extension */
72 /*--------------------------------------+
73 | Shift the temporary register |
74 | right the required number of |
76 +--------------------------------------*/
78 cmpw $32,%cx /* shrd only works for 0..31 bits */
81 /* less than 32 bits */
97 jz L_more_31_no_low /* none of the lowest bits is set */
99 orl $1,%edx /* record the fact in the extension */
116 /* Shift right by 64 bits */
127 /* Shift right by 65 bits */
128 /* Carry is clear if we get here */
144 movl $1,%edx /* The shifted nr always at least one '1' */
152 /*------------------------------+
153 | Do the subtraction |
154 +------------------------------*/
166 /* We can never get a borrow */
168 #endif /* PARANOID */
170 /*--------------------------------------+
171 | Normalize the result |
172 +--------------------------------------*/
173 testl $0x80000000,%eax
174 jnz L_round /* no shifting needed */
177 jnz L_shift_1 /* shift left 1 - 31 bits */
180 jnz L_shift_32 /* shift left 32 - 63 bits */
183 * A rare case, the only one which is non-zero if we got here
184 * is: 1000000 .... 0000
185 * -0111111 .... 1111 1
186 * --------------------
187 * 0000000 .... 0000 1
190 cmpl $0x80000000,%edx
193 /* Shift left 64 bits */
202 #endif /* PARANOID */
204 /* The result is zero */
205 movw $0,EXP(%edi) /* exponent */
215 subw $32,EXP(%edi) /* Can get underflow here */
217 /* We need to shift left by 1 - 31 bits */
219 bsrl %eax,%ecx /* get the required shift in %ecx */
225 subw %cx,EXP(%edi) /* Can get underflow here */
228 jmp fpu_reg_round /* Round the result */
233 pushl EX_INTERNAL|0x206
239 pushl EX_INTERNAL|0x209
245 pushl EX_INTERNAL|0x210
251 pushl EX_INTERNAL|0x211
257 pushl EX_INTERNAL|0x212
265 #endif /* PARANOID */