1 /* SPDX-License-Identifier: GPL-2.0 */
3 /*---------------------------------------------------------------------------+
6 | Core floating point subtraction routine. |
8 | Copyright (C) 1992,1993,1995,1997 |
9 | W. Metzenthen, 22 Parker St, Ormond, Vic 3163, Australia |
10 | E-mail billm@suburbia.net |
13 | int FPU_u_sub(FPU_REG *arg1, FPU_REG *arg2, FPU_REG *answ, |
15 | Return value is the tag of the answer, or-ed with FPU_Exception if |
16 | one was raised, or -1 on internal error. |
18 +---------------------------------------------------------------------------*/
21 | Kernel subtraction routine FPU_u_sub(reg *arg1, reg *arg2, reg *answ).
22 | Takes two valid reg f.p. numbers (TAG_Valid), which are
23 | treated as unsigned numbers,
24 | and returns their difference as a TAG_Valid or TAG_Zero f.p.
26 | The first number (arg1) must be the larger.
27 | The returned number is normalized.
28 | Basic checks are performed if PARANOID is defined.
31 #include "exception.h"
33 #include "control_w.h"
43 movl PARAM1,%esi /* source 1 */
44 movl PARAM2,%edi /* source 2 */
47 subl PARAM7,%ecx /* exp1 - exp2 */
50 /* source 2 is always smaller than source 1 */
53 testl $0x80000000,SIGH(%edi) /* The args are assumed to be be normalized */
56 testl $0x80000000,SIGH(%esi)
60 /*--------------------------------------+
61 | Form a register holding the |
63 +--------------------------------------*/
64 movl SIGH(%edi),%eax /* register ms word */
65 movl SIGL(%edi),%ebx /* register ls word */
67 movl PARAM3,%edi /* destination */
69 movw %dx,EXP(%edi) /* Copy exponent to destination */
71 xorl %edx,%edx /* register extension */
73 /*--------------------------------------+
74 | Shift the temporary register |
75 | right the required number of |
77 +--------------------------------------*/
79 cmpw $32,%cx /* shrd only works for 0..31 bits */
82 /* less than 32 bits */
98 jz L_more_31_no_low /* none of the lowest bits is set */
100 orl $1,%edx /* record the fact in the extension */
117 /* Shift right by 64 bits */
128 /* Shift right by 65 bits */
129 /* Carry is clear if we get here */
145 movl $1,%edx /* The shifted nr always at least one '1' */
153 /*------------------------------+
154 | Do the subtraction |
155 +------------------------------*/
167 /* We can never get a borrow */
169 #endif /* PARANOID */
171 /*--------------------------------------+
172 | Normalize the result |
173 +--------------------------------------*/
174 testl $0x80000000,%eax
175 jnz L_round /* no shifting needed */
178 jnz L_shift_1 /* shift left 1 - 31 bits */
181 jnz L_shift_32 /* shift left 32 - 63 bits */
184 * A rare case, the only one which is non-zero if we got here
185 * is: 1000000 .... 0000
186 * -0111111 .... 1111 1
187 * --------------------
188 * 0000000 .... 0000 1
191 cmpl $0x80000000,%edx
194 /* Shift left 64 bits */
203 #endif /* PARANOID */
205 /* The result is zero */
206 movw $0,EXP(%edi) /* exponent */
216 subw $32,EXP(%edi) /* Can get underflow here */
218 /* We need to shift left by 1 - 31 bits */
220 bsrl %eax,%ecx /* get the required shift in %ecx */
226 subw %cx,EXP(%edi) /* Can get underflow here */
229 jmp fpu_reg_round /* Round the result */
234 pushl EX_INTERNAL|0x206
240 pushl EX_INTERNAL|0x209
246 pushl EX_INTERNAL|0x210
252 pushl EX_INTERNAL|0x211
258 pushl EX_INTERNAL|0x212
266 #endif /* PARANOID */