Get LINT to build.
[dragonfly.git] / sys / platform / pc32 / gnu / fpemul / reg_div.s
1         .file   "reg_div.S"
2 /*
3  *  reg_div.S
4  *
5  * Divide one FPU_REG by another and put the result in a destination FPU_REG.
6  *
7  * Call from C as:
8  *   void reg_div(FPU_REG *a, FPU_REG *b, FPU_REG *dest,
9  *
10  *
11  * Copyright (C) 1992,1993,1994
12  *                       W. Metzenthen, 22 Parker St, Ormond, Vic 3163,
13  *                       Australia.  E-mail   billm@vaxc.cc.monash.edu.au
14  * All rights reserved.
15  *
16  * This copyright notice covers the redistribution and use of the
17  * FPU emulator developed by W. Metzenthen. It covers only its use
18  * in the 386BSD, FreeBSD and NetBSD operating systems. Any other
19  * use is not permitted under this copyright.
20  *
21  * Redistribution and use in source and binary forms, with or without
22  * modification, are permitted provided that the following conditions
23  * are met:
24  * 1. Redistributions of source code must retain the above copyright
25  *    notice, this list of conditions and the following disclaimer.
26  * 2. Redistributions in binary form must include information specifying
27  *    that source code for the emulator is freely available and include
28  *    either:
29  *      a) an offer to provide the source code for a nominal distribution
30  *         fee, or
31  *      b) list at least two alternative methods whereby the source
32  *         can be obtained, e.g. a publically accessible bulletin board
33  *         and an anonymous ftp site from which the software can be
34  *         downloaded.
35  * 3. All advertising materials specifically mentioning features or use of
36  *    this emulator must acknowledge that it was developed by W. Metzenthen.
37  * 4. The name of W. Metzenthen may not be used to endorse or promote
38  *    products derived from this software without specific prior written
39  *    permission.
40  *
41  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
42  * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
43  * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL
44  * W. METZENTHEN BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
45  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
46  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
47  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
48  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
49  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
50  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
51  *
52  *
53  * The purpose of this copyright, based upon the Berkeley copyright, is to
54  * ensure that the covered software remains freely available to everyone.
55  *
56  * The software (with necessary differences) is also available, but under
57  * the terms of the GNU copyleft, for the Linux operating system and for
58  * the djgpp ms-dos extender.
59  *
60  * W. Metzenthen   June 1994.
61  *
62  * 
63  * $FreeBSD: src/sys/gnu/i386/fpemul/reg_div.s,v 1.9.2.1 2000/07/07 00:38:42 obrien Exp $
64  * $DragonFly: src/sys/platform/pc32/gnu/fpemul/Attic/reg_div.s,v 1.3 2003/07/31 12:37:39 hmp Exp $
65  *
66  */
67
68 #include <gnu/i386/fpemul/fpu_asm.h>
69
70 .text
71 ENTRY(reg_div)
72         pushl   %ebp
73         movl    %esp,%ebp
74
75         pushl   %esi
76         pushl   %edi
77         pushl   %ebx
78
79         movl    PARAM1,%esi
80         movl    PARAM2,%ebx
81         movl    PARAM3,%edi
82
83         movb    TAG(%esi),%al
84         orb     TAG(%ebx),%al
85
86         jne     L_div_special           /* Not (both numbers TW_Valid) */
87
88 #ifdef DENORM_OPERAND
89 /* Check for denormals */
90         cmpl    EXP_UNDER,EXP(%esi)
91         jg      xL_arg1_not_denormal
92
93         call    denormal_operand
94         orl     %eax,%eax
95         jnz     FPU_Arith_exit
96
97 xL_arg1_not_denormal:
98         cmpl    EXP_UNDER,EXP(%ebx)
99         jg      xL_arg2_not_denormal
100
101         call    denormal_operand
102         orl     %eax,%eax
103         jnz     FPU_Arith_exit
104
105 xL_arg2_not_denormal:
106 #endif DENORM_OPERAND
107
108 /* Both arguments are TW_Valid */
109         movb    TW_Valid,TAG(%edi)
110
111         movb    SIGN(%esi),%cl
112         cmpb    %cl,SIGN(%ebx)
113         setne   (%edi)     /* Set the sign, requires SIGN_NEG=1, SIGN_POS=0 */
114
115         movl    EXP(%esi),%edx
116         movl    EXP(%ebx),%eax
117         subl    %eax,%edx
118         addl    EXP_BIAS,%edx
119         movl    %edx,EXP(%edi)
120
121         jmp     _divide_kernel
122
123
124 /*-----------------------------------------------------------------------*/
125 L_div_special:
126         cmpb    TW_NaN,TAG(%esi)        /* A NaN with anything to give NaN */
127         je      L_arg1_NaN
128
129         cmpb    TW_NaN,TAG(%ebx)        /* A NaN with anything to give NaN */
130         jne     L_no_NaN_arg
131
132 /*  Operations on NaNs */
133 L_arg1_NaN:
134 L_arg2_NaN:
135         pushl   %edi                    /* Destination */
136         pushl   %ebx
137         pushl   %esi
138         call    real_2op_NaN
139         jmp     LDiv_exit
140
141 /* Invalid operations */
142 L_zero_zero:
143 L_inf_inf:
144         pushl   %edi                    /* Destination */
145         call    arith_invalid           /* 0/0 or Infinity/Infinity */
146         jmp     LDiv_exit
147
148 L_no_NaN_arg:
149         cmpb    TW_Infinity,TAG(%esi)
150         jne     L_arg1_not_inf
151
152         cmpb    TW_Infinity,TAG(%ebx)
153         je      L_inf_inf               /* invalid operation */
154
155         cmpb    TW_Valid,TAG(%ebx)
156         je      L_inf_valid
157
158 #ifdef PARANOID
159         /* arg2 must be zero or valid */
160         cmpb    TW_Zero,TAG(%ebx)
161         ja      L_unknown_tags
162 #endif PARANOID
163
164         /* Note that p16-9 says that infinity/0 returns infinity */
165         jmp     L_copy_arg1             /* Answer is Inf */
166
167 L_inf_valid:
168 #ifdef DENORM_OPERAND
169         cmpl    EXP_UNDER,EXP(%ebx)
170         jg      L_copy_arg1             /* Answer is Inf */
171
172         call    denormal_operand
173         orl     %eax,%eax
174         jnz     FPU_Arith_exit
175 #endif DENORM_OPERAND
176
177         jmp     L_copy_arg1             /* Answer is Inf */
178
179 L_arg1_not_inf:
180         cmpb    TW_Zero,TAG(%ebx)       /* Priority to div-by-zero error */
181         jne     L_arg2_not_zero
182
183         cmpb    TW_Zero,TAG(%esi)
184         je      L_zero_zero             /* invalid operation */
185
186 #ifdef PARANOID
187         /* arg1 must be valid */
188         cmpb    TW_Valid,TAG(%esi)
189         ja      L_unknown_tags
190 #endif PARANOID
191
192 /* Division by zero error */
193         pushl   %edi                    /* destination */
194         movb    SIGN(%esi),%al
195         xorb    SIGN(%ebx),%al
196         pushl   %eax                    /* lower 8 bits have the sign */
197         call    divide_by_zero
198         jmp     LDiv_exit
199
200 L_arg2_not_zero:
201         cmpb    TW_Infinity,TAG(%ebx)
202         jne     L_arg2_not_inf
203
204 #ifdef DENORM_OPERAND
205         cmpb    TW_Valid,TAG(%esi)
206         jne     L_return_zero
207
208         cmpl    EXP_UNDER,EXP(%esi)
209         jg      L_return_zero           /* Answer is zero */
210
211         call    denormal_operand
212         orl     %eax,%eax
213         jnz     FPU_Arith_exit
214 #endif DENORM_OPERAND
215
216         jmp     L_return_zero           /* Answer is zero */
217
218 L_arg2_not_inf:
219
220 #ifdef PARANOID
221         cmpb    TW_Zero,TAG(%esi)
222         jne     L_unknown_tags
223 #endif PARANOID
224
225         /* arg1 is zero, arg2 is not Infinity or a NaN */
226
227 #ifdef DENORM_OPERAND
228         cmpl    EXP_UNDER,EXP(%ebx)
229         jg      L_copy_arg1             /* Answer is zero */
230
231         call    denormal_operand
232         orl     %eax,%eax
233         jnz     FPU_Arith_exit
234 #endif DENORM_OPERAND
235
236 L_copy_arg1:
237         movb    TAG(%esi),%al
238         movb    %al,TAG(%edi)
239         movl    EXP(%esi),%eax
240         movl    %eax,EXP(%edi)
241         movl    SIGL(%esi),%eax
242         movl    %eax,SIGL(%edi)
243         movl    SIGH(%esi),%eax
244         movl    %eax,SIGH(%edi)
245
246         movb    SIGN(%esi),%cl
247         cmpb    %cl,SIGN(%ebx)
248         jne     LDiv_negative_result
249
250         movb    SIGN_POS,SIGN(%edi)
251         jmp     LDiv_exit
252
253 LDiv_set_result_sign:
254         movb    SIGN(%esi),%cl
255         cmpb    %cl,SIGN(%edi)
256         jne     LDiv_negative_result
257
258         movb    SIGN_POS,SIGN(%ebx)
259         jmp     LDiv_exit
260
261 LDiv_negative_result:
262         movb    SIGN_NEG,SIGN(%edi)
263
264 LDiv_exit:
265         leal    -12(%ebp),%esp
266
267         popl    %ebx
268         popl    %edi
269         popl    %esi
270         leave
271         ret
272
273
274 L_return_zero:
275         movb    TW_Zero,TAG(%edi)
276         jmp     LDiv_set_result_sign
277
278 #ifdef PARANOID
279 L_unknown_tags:
280         push    EX_INTERNAL | 0x208
281         call    EXCEPTION
282
283         /* Generate a NaN for unknown tags */
284         movl    _CONST_QNaN,%eax
285         movl    %eax,(%edi)
286         movl    _CONST_QNaN+4,%eax
287         movl    %eax,SIGL(%edi)
288         movl    _CONST_QNaN+8,%eax
289         movl    %eax,SIGH(%edi)
290         jmp     LDiv_exit
291 #endif PARANOID