Oh GACK! src-clean doesn't quite work that easily since cleandist rebuilds the
[unix-history] / contrib / FAQ / programs / fp-emu / fpemul / reg_u_sub.s
CommitLineData
f24c459c
JH
1 .file "reg_u_sub.S"
2/*
3 * reg_u_sub.S
4 *
5 * Core floating point subtraction routine.
6 *
7 * Call from C as:
8 * void reg_u_sub(FPU_REG *arg1, FPU_REG *arg2, FPU_REG *answ,
9 * int control_w)
10 *
11 *
12 * Copyright (C) 1992, 1993 W. Metzenthen, 22 Parker St, Ormond,
13 * Vic 3163, Australia.
14 * E-mail apm233m@vaxc.cc.monash.edu.au
15 * All rights reserved.
16 *
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 operating system. Any other use is not permitted
20 * under this copyright.
21 *
22 * Redistribution and use in source and binary forms, with or without
23 * modification, are permitted provided that the following conditions
24 * are met:
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
29 * either:
30 * a) an offer to provide the source code for a nominal distribution
31 * fee, or
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
35 * downloaded.
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
40 * permission.
41 *
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.
52 *
53 */
54
55/*
56 | Kernel subtraction routine reg_u_sub(reg *arg1, reg *arg2, reg *answ).
57 | Takes two valid reg f.p. numbers (TW_Valid), which are
58 | treated as unsigned numbers,
59 | and returns their difference as a TW_Valid or TW_Zero f.p.
60 | number.
61 | The first number (arg1) must be the larger.
62 | The returned number is normalized.
63 | Basic checks are performed if PARANOID is defined.
64 */
65
66#include "exception.h"
67#include "fpu_asm.h"
68#include "control_w.h"
69
70.text
71 .align 2,144
72.globl _reg_u_sub
73_reg_u_sub:
74 pushl %ebp
75 movl %esp,%ebp
76 pushl %esi
77 pushl %edi
78 pushl %ebx
79
80 movl PARAM1,%esi /* source 1 */
81 movl PARAM2,%edi /* source 2 */
82
83#ifdef DENORM_OPERAND
84 cmpl EXP_UNDER,EXP(%esi)
85 jg xOp1_not_denorm
86
87 call _denormal_operand
88 orl %eax,%eax
89 jnz FPU_Arith_exit
90
91xOp1_not_denorm:
92 cmpl EXP_UNDER,EXP(%edi)
93 jg xOp2_not_denorm
94
95 call _denormal_operand
96 orl %eax,%eax
97 jnz FPU_Arith_exit
98
99xOp2_not_denorm:
100#endif DENORM_OPERAND
101
102/* xorl %ecx,%ecx */
103 movl EXP(%esi),%ecx
104 subl EXP(%edi),%ecx /* exp1 - exp2 */
105
106#ifdef PARANOID
107 /* source 2 is always smaller than source 1 */
108/* jc L_bugged */
109 js L_bugged_1
110
111 testl $0x80000000,SIGH(%edi) /* The args are assumed to be be normalized */
112 je L_bugged_2
113
114 testl $0x80000000,SIGH(%esi)
115 je L_bugged_2
116#endif PARANOID
117
118/*--------------------------------------+
119 | Form a register holding the |
120 | smaller number |
121 +--------------------------------------*/
122 movl SIGH(%edi),%eax /* register ms word */
123 movl SIGL(%edi),%ebx /* register ls word */
124
125 movl PARAM3,%edi /* destination */
126 movl EXP(%esi),%edx
127 movl %edx,EXP(%edi) /* Copy exponent to destination */
128 movb SIGN(%esi),%dl
129 movb %dl,SIGN(%edi) /* Copy the sign from the first arg */
130
131 xorl %edx,%edx /* register extension */
132
133/*--------------------------------------+
134 | Shift the temporary register |
135 | right the required number of |
136 | places. |
137 +--------------------------------------*/
138L_shift_r:
139 cmpl $32,%ecx /* shrd only works for 0..31 bits */
140 jnc L_more_than_31
141
142/* less than 32 bits */
143 shrd %cl,%ebx,%edx
144 shrd %cl,%eax,%ebx
145 shr %cl,%eax
146 jmp L_shift_done
147
148L_more_than_31:
149 cmpl $64,%ecx
150 jnc L_more_than_63
151
152 subb $32,%cl
153 jz L_exactly_32
154
155 shrd %cl,%eax,%edx
156 shr %cl,%eax
157 orl %ebx,%ebx
158 jz L_more_31_no_low /* none of the lowest bits is set */
159
160 orl $1,%edx /* record the fact in the extension */
161
162L_more_31_no_low:
163 movl %eax,%ebx
164 xorl %eax,%eax
165 jmp L_shift_done
166
167L_exactly_32:
168 movl %ebx,%edx
169 movl %eax,%ebx
170 xorl %eax,%eax
171 jmp L_shift_done
172
173L_more_than_63:
174 cmpw $65,%cx
175 jnc L_more_than_64
176
177 /* Shift right by 64 bits */
178 movl %eax,%edx
179 orl %ebx,%ebx
180 jz L_more_63_no_low
181
182 orl $1,%edx
183 jmp L_more_63_no_low
184
185L_more_than_64:
186 jne L_more_than_65
187
188 /* Shift right by 65 bits */
189 /* Carry is clear if we get here */
190 movl %eax,%edx
191 rcrl %edx
192 jnc L_shift_65_nc
193
194 orl $1,%edx
195 jmp L_more_63_no_low
196
197L_shift_65_nc:
198 orl %ebx,%ebx
199 jz L_more_63_no_low
200
201 orl $1,%edx
202 jmp L_more_63_no_low
203
204L_more_than_65:
205 movl $1,%edx /* The shifted nr always at least one '1' */
206
207L_more_63_no_low:
208 xorl %ebx,%ebx
209 xorl %eax,%eax
210
211L_shift_done:
212L_subtr:
213/*------------------------------+
214 | Do the subtraction |
215 +------------------------------*/
216 xorl %ecx,%ecx
217 subl %edx,%ecx
218 movl %ecx,%edx
219 movl SIGL(%esi),%ecx
220 sbbl %ebx,%ecx
221 movl %ecx,%ebx
222 movl SIGH(%esi),%ecx
223 sbbl %eax,%ecx
224 movl %ecx,%eax
225
226#ifdef PARANOID
227 /* We can never get a borrow */
228 jc L_bugged
229#endif PARANOID
230
231/*--------------------------------------+
232 | Normalize the result |
233 +--------------------------------------*/
234 testl $0x80000000,%eax
235 jnz L_round /* no shifting needed */
236
237 orl %eax,%eax
238 jnz L_shift_1 /* shift left 1 - 31 bits */
239
240 orl %ebx,%ebx
241 jnz L_shift_32 /* shift left 32 - 63 bits */
242
243/* A rare case, the only one which is non-zero if we got here
244// is: 1000000 .... 0000
245// -0111111 .... 1111 1
246// --------------------
247// 0000000 .... 0000 1 */
248
249 cmpl $0x80000000,%edx
250 jnz L_must_be_zero
251
252 /* Shift left 64 bits */
253 subl $64,EXP(%edi)
254 movl %edx,%eax
255 jmp L_store
256
257L_must_be_zero:
258#ifdef PARANOID
259 orl %edx,%edx
260 jnz L_bugged_3
261#endif PARANOID
262
263 /* The result is zero */
264 movb TW_Zero,TAG(%edi)
265 movl $0,EXP(%edi) /* exponent */
266 movl $0,SIGL(%edi)
267 movl $0,SIGH(%edi)
268 jmp L_exit /* Does not underflow */
269
270L_shift_32:
271 movl %ebx,%eax
272 movl %edx,%ebx
273 movl $0,%edx
274 subl $32,EXP(%edi) /* Can get underflow here */
275
276/* We need to shift left by 1 - 31 bits */
277L_shift_1:
278 bsrl %eax,%ecx /* get the required shift in %ecx */
279 subl $31,%ecx
280 negl %ecx
281 shld %cl,%ebx,%eax
282 shld %cl,%edx,%ebx
283 shl %cl,%edx
284 subl %ecx,EXP(%edi) /* Can get underflow here */
285
286L_round:
287 jmp FPU_round /* Round the result */
288
289
290#ifdef PARANOID
291L_bugged_1:
292 pushl EX_INTERNAL|0x206
293 call EXCEPTION
294 pop %ebx
295 jmp L_exit
296
297L_bugged_2:
298 pushl EX_INTERNAL|0x209
299 call EXCEPTION
300 pop %ebx
301 jmp L_exit
302
303L_bugged_3:
304 pushl EX_INTERNAL|0x210
305 call EXCEPTION
306 pop %ebx
307 jmp L_exit
308
309L_bugged_4:
310 pushl EX_INTERNAL|0x211
311 call EXCEPTION
312 pop %ebx
313 jmp L_exit
314
315L_bugged:
316 pushl EX_INTERNAL|0x212
317 call EXCEPTION
318 pop %ebx
319 jmp L_exit
320#endif PARANOID
321
322
323L_store:
324/*------------------------------+
325 | Store the result |
326 +------------------------------*/
327 movl %eax,SIGH(%edi)
328 movl %ebx,SIGL(%edi)
329
330 movb TW_Valid,TAG(%edi) /* Set the tags to TW_Valid */
331
332 cmpl EXP_UNDER,EXP(%edi)
333 jle L_underflow
334
335L_exit:
336 popl %ebx
337 popl %edi
338 popl %esi
339 leave
340 ret
341
342
343L_underflow:
344 push %edi
345 call _arith_underflow
346 pop %ebx
347 jmp L_exit
348