5 * Core floating point subtraction routine.
8 * void reg_u_sub(FPU_REG *arg1, FPU_REG *arg2, FPU_REG *answ,
12 * Copyright (C) 1992,1993,1994
13 * W. Metzenthen, 22 Parker St, Ormond, Vic 3163,
14 * Australia. E-mail billm@vaxc.cc.monash.edu.au
15 * All rights reserved.
17 * This copyright notice covers the redistribution and use of the
18 * FPU emulator developed by W. Metzenthen. It covers only its use
19 * in the 386BSD, FreeBSD and NetBSD operating systems. Any other
20 * use is not permitted under this copyright.
22 * Redistribution and use in source and binary forms, with or without
23 * modification, are permitted provided that the following conditions
25 * 1. Redistributions of source code must retain the above copyright
26 * notice, this list of conditions and the following disclaimer.
27 * 2. Redistributions in binary form must include information specifying
28 * that source code for the emulator is freely available and include
30 * a) an offer to provide the source code for a nominal distribution
32 * b) list at least two alternative methods whereby the source
33 * can be obtained, e.g. a publically accessible bulletin board
34 * and an anonymous ftp site from which the software can be
36 * 3. All advertising materials specifically mentioning features or use of
37 * this emulator must acknowledge that it was developed by W. Metzenthen.
38 * 4. The name of W. Metzenthen may not be used to endorse or promote
39 * products derived from this software without specific prior written
42 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
43 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
44 * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
45 * W. METZENTHEN BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
46 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
47 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
48 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
49 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
50 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
51 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
54 * The purpose of this copyright, based upon the Berkeley copyright, is to
55 * ensure that the covered software remains freely available to everyone.
57 * The software (with necessary differences) is also available, but under
58 * the terms of the GNU copyleft, for the Linux operating system and for
59 * the djgpp ms-dos extender.
61 * W. Metzenthen June 1994.
64 * $FreeBSD: src/sys/gnu/i386/fpemul/reg_u_sub.s,v 1.9 1999/08/28 00:42:58 peter Exp $
69 | Kernel subtraction routine reg_u_sub(reg *arg1, reg *arg2, reg *answ).
70 | Takes two valid reg f.p. numbers (TW_Valid), which are
71 | treated as unsigned numbers,
72 | and returns their difference as a TW_Valid or TW_Zero f.p.
74 | The first number (arg1) must be the larger.
75 | The returned number is normalized.
76 | Basic checks are performed if PARANOID is defined.
79 #include <gnu/i386/fpemul/fpu_asm.h>
89 movl PARAM1,%esi /* source 1 */
90 movl PARAM2,%edi /* source 2 */
93 cmpl EXP_UNDER,EXP(%esi)
96 call _denormal_operand
101 cmpl EXP_UNDER,EXP(%edi)
104 call _denormal_operand
109 #endif DENORM_OPERAND
113 subl EXP(%edi),%ecx /* exp1 - exp2 */
116 /* source 2 is always smaller than source 1 */
120 testl $0x80000000,SIGH(%edi) /* The args are assumed to be be normalized */
123 testl $0x80000000,SIGH(%esi)
127 /*--------------------------------------+
128 | Form a register holding the |
130 +--------------------------------------*/
131 movl SIGH(%edi),%eax /* register ms word */
132 movl SIGL(%edi),%ebx /* register ls word */
134 movl PARAM3,%edi /* destination */
136 movl %edx,EXP(%edi) /* Copy exponent to destination */
138 movb %dl,SIGN(%edi) /* Copy the sign from the first arg */
140 xorl %edx,%edx /* register extension */
142 /*--------------------------------------+
143 | Shift the temporary register |
144 | right the required number of |
146 +--------------------------------------*/
148 cmpl $32,%ecx /* shrd only works for 0..31 bits */
151 /* less than 32 bits */
167 jz L_more_31_no_low /* none of the lowest bits is set */
169 orl $1,%edx /* record the fact in the extension */
186 /* Shift right by 64 bits */
197 /* Shift right by 65 bits */
198 /* Carry is clear if we get here */
214 movl $1,%edx /* The shifted nr always at least one '1' */
222 /*------------------------------+
223 | Do the subtraction |
224 +------------------------------*/
236 /* We can never get a borrow */
240 /*--------------------------------------+
241 | Normalize the result |
242 +--------------------------------------*/
243 testl $0x80000000,%eax
244 jnz L_round /* no shifting needed */
247 jnz L_shift_1 /* shift left 1 - 31 bits */
250 jnz L_shift_32 /* shift left 32 - 63 bits */
252 /* A rare case, the only one which is non-zero if we got here
253 // is: 1000000 .... 0000
254 // -0111111 .... 1111 1
255 // --------------------
256 // 0000000 .... 0000 1 */
258 cmpl $0x80000000,%edx
261 /* Shift left 64 bits */
272 /* The result is zero */
273 movb TW_Zero,TAG(%edi)
274 movl $0,EXP(%edi) /* exponent */
277 jmp L_exit /* Does not underflow */
283 subl $32,EXP(%edi) /* Can get underflow here */
285 /* We need to shift left by 1 - 31 bits */
287 bsrl %eax,%ecx /* get the required shift in %ecx */
293 subl %ecx,EXP(%edi) /* Can get underflow here */
296 jmp FPU_round /* Round the result */
301 pushl EX_INTERNAL|0x206
307 pushl EX_INTERNAL|0x209
313 pushl EX_INTERNAL|0x210
319 pushl EX_INTERNAL|0x211
325 pushl EX_INTERNAL|0x212
333 /*------------------------------+
335 +------------------------------*/
339 movb TW_Valid,TAG(%edi) /* Set the tags to TW_Valid */
341 cmpl EXP_UNDER,EXP(%edi)
354 call _arith_underflow