Initial import from FreeBSD RELENG_4:
[dragonfly.git] / sys / platform / pc32 / gnu / fpemul / reg_u_add.s
1         .file   "reg_u_add.S"
2 /*
3  *  reg_u_add.S
4  *
5  * Add two valid (TW_Valid) FPU_REG numbers, of the same sign, and put the
6  *   result in a destination FPU_REG.
7  *
8  * Call from C as:
9  *   void reg_u_add(FPU_REG *arg1, FPU_REG *arg2, FPU_REG *answ,
10  *                                                int control_w)
11  *
12  *
13  * Copyright (C) 1992,1993,1994
14  *                       W. Metzenthen, 22 Parker St, Ormond, Vic 3163,
15  *                       Australia.  E-mail   billm@vaxc.cc.monash.edu.au
16  * All rights reserved.
17  *
18  * This copyright notice covers the redistribution and use of the
19  * FPU emulator developed by W. Metzenthen. It covers only its use
20  * in the 386BSD, FreeBSD and NetBSD operating systems. Any other
21  * use is not permitted under this copyright.
22  *
23  * Redistribution and use in source and binary forms, with or without
24  * modification, are permitted provided that the following conditions
25  * are met:
26  * 1. Redistributions of source code must retain the above copyright
27  *    notice, this list of conditions and the following disclaimer.
28  * 2. Redistributions in binary form must include information specifying
29  *    that source code for the emulator is freely available and include
30  *    either:
31  *      a) an offer to provide the source code for a nominal distribution
32  *         fee, or
33  *      b) list at least two alternative methods whereby the source
34  *         can be obtained, e.g. a publically accessible bulletin board
35  *         and an anonymous ftp site from which the software can be
36  *         downloaded.
37  * 3. All advertising materials specifically mentioning features or use of
38  *    this emulator must acknowledge that it was developed by W. Metzenthen.
39  * 4. The name of W. Metzenthen may not be used to endorse or promote
40  *    products derived from this software without specific prior written
41  *    permission.
42  *
43  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
44  * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
45  * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL
46  * W. METZENTHEN BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
47  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
48  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
49  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
50  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
51  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
52  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
53  *
54  *
55  * The purpose of this copyright, based upon the Berkeley copyright, is to
56  * ensure that the covered software remains freely available to everyone.
57  *
58  * The software (with necessary differences) is also available, but under
59  * the terms of the GNU copyleft, for the Linux operating system and for
60  * the djgpp ms-dos extender.
61  *
62  * W. Metzenthen   June 1994.
63  *
64  *
65  * $FreeBSD: src/sys/gnu/i386/fpemul/reg_u_add.s,v 1.9 1999/08/28 00:42:57 peter Exp $
66  *
67  */
68
69
70 /*
71  |    Kernel addition routine reg_u_add(reg *arg1, reg *arg2, reg *answ).
72  |    Takes two valid reg f.p. numbers (TW_Valid), which are
73  |    treated as unsigned numbers,
74  |    and returns their sum as a TW_Valid or TW_S f.p. number.
75  |    The returned number is normalized.
76  |    Basic checks are performed if PARANOID is defined.
77  */
78
79 #include <gnu/i386/fpemul/fpu_asm.h>
80
81 .text
82 ENTRY(reg_u_add)
83         pushl   %ebp
84         movl    %esp,%ebp
85 /*      subl    $16,%esp*/
86         pushl   %esi
87         pushl   %edi
88         pushl   %ebx
89
90         movl    PARAM1,%esi             /* source 1 */
91         movl    PARAM2,%edi             /* source 2 */
92
93 #ifdef DENORM_OPERAND
94         cmpl    EXP_UNDER,EXP(%esi)
95         jg      xOp1_not_denorm
96
97         call    _denormal_operand
98         orl     %eax,%eax
99         jnz     FPU_Arith_exit
100
101 xOp1_not_denorm:
102         cmpl    EXP_UNDER,EXP(%edi)
103         jg      xOp2_not_denorm
104
105         call    _denormal_operand
106         orl     %eax,%eax
107         jnz     FPU_Arith_exit
108
109 xOp2_not_denorm:
110 #endif DENORM_OPERAND
111
112 /*      xorl    %ecx,%ecx*/
113         movl    EXP(%esi),%ecx
114         subl    EXP(%edi),%ecx          /* exp1 - exp2 */
115 /*      jnc     L_arg1_larger*/
116         jge     L_arg1_larger
117
118         /* num1 is smaller */
119         movl    SIGL(%esi),%ebx
120         movl    SIGH(%esi),%eax
121
122         movl    %edi,%esi
123         negw    %cx
124         jmp     L_accum_loaded
125
126 L_arg1_larger:
127         /* num1 has larger or equal exponent */
128         movl    SIGL(%edi),%ebx
129         movl    SIGH(%edi),%eax
130
131 L_accum_loaded:
132         movl    PARAM3,%edi             /* destination */
133         movb    SIGN(%esi),%dl
134         movb    %dl,SIGN(%edi)          /* Copy the sign from the first arg */
135
136
137         movl    EXP(%esi),%edx
138         movl    %edx,EXP(%edi)  /* Copy exponent to destination */
139
140         xorl    %edx,%edx               /* clear the extension */
141
142 #ifdef PARANOID
143         testl   $0x80000000,%eax
144         je      L_bugged
145
146         testl   $0x80000000,SIGH(%esi)
147         je      L_bugged
148 #endif PARANOID
149
150 /* The number to be shifted is in %eax:%ebx:%edx*/
151         cmpw    $32,%cx         /* shrd only works for 0..31 bits */
152         jnc     L_more_than_31
153
154 /* less than 32 bits */
155         shrd    %cl,%ebx,%edx
156         shrd    %cl,%eax,%ebx
157         shr     %cl,%eax
158         jmp     L_shift_done
159
160 L_more_than_31:
161         cmpw    $64,%cx
162         jnc     L_more_than_63
163
164         subb    $32,%cl
165         jz      L_exactly_32
166
167         shrd    %cl,%eax,%edx
168         shr     %cl,%eax
169         orl     %ebx,%ebx
170         jz      L_more_31_no_low        /* none of the lowest bits is set*/
171
172         orl     $1,%edx                 /* record the fact in the extension*/
173
174 L_more_31_no_low:
175         movl    %eax,%ebx
176         xorl    %eax,%eax
177         jmp     L_shift_done
178
179 L_exactly_32:
180         movl    %ebx,%edx
181         movl    %eax,%ebx
182         xorl    %eax,%eax
183         jmp     L_shift_done
184
185 L_more_than_63:
186         cmpw    $65,%cx
187         jnc     L_more_than_64
188
189         movl    %eax,%edx
190         orl     %ebx,%ebx
191         jz      L_more_63_no_low
192
193         orl     $1,%edx
194         jmp     L_more_63_no_low
195
196 L_more_than_64:
197         movl    $1,%edx         /* The shifted nr always at least one '1'*/
198
199 L_more_63_no_low:
200         xorl    %ebx,%ebx
201         xorl    %eax,%eax
202
203 L_shift_done:
204         /* Now do the addition */
205         addl    SIGL(%esi),%ebx
206         adcl    SIGH(%esi),%eax
207         jnc     L_round_the_result
208
209         /* Overflow, adjust the result */
210         rcrl    $1,%eax
211         rcrl    $1,%ebx
212         rcrl    $1,%edx
213         jnc     L_no_bit_lost
214
215         orl     $1,%edx
216
217 L_no_bit_lost:
218         incl    EXP(%edi)
219
220 L_round_the_result:
221         jmp     FPU_round       /* Round the result*/
222
223
224
225 #ifdef PARANOID
226 /* If we ever get here then we have problems! */
227 L_bugged:
228         pushl   EX_INTERNAL|0x201
229         call    EXCEPTION
230         pop     %ebx
231         jmp     L_exit
232 #endif PARANOID
233
234
235 L_exit:
236         popl    %ebx
237         popl    %edi
238         popl    %esi
239         leave
240         ret