1 /* $NetBSD: sfdiv.c,v 1.3 2005/12/11 12:17:40 christos Exp $ */
3 /* $OpenBSD: sfdiv.c,v 1.4 2001/03/29 03:58:19 mickey Exp $ */
6 * Copyright 1996 1995 by Open Software Foundation, Inc.
9 * Permission to use, copy, modify, and distribute this software and
10 * its documentation for any purpose and without fee is hereby granted,
11 * provided that the above copyright notice appears in all copies and
12 * that both the copyright notice and this permission notice appear in
13 * supporting documentation.
15 * OSF DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE
16 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
17 * FOR A PARTICULAR PURPOSE.
19 * IN NO EVENT SHALL OSF BE LIABLE FOR ANY SPECIAL, INDIRECT, OR
20 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
21 * LOSS OF USE, DATA OR PROFITS, WHETHER IN ACTION OF CONTRACT,
22 * NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
23 * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
30 * (c) Copyright 1986 HEWLETT-PACKARD COMPANY
32 * To anyone who acknowledges that this file is provided "AS IS"
33 * without any express or implied warranty:
34 * permission to use, copy, modify, and distribute this file
35 * for any purpose is hereby granted without fee, provided that
36 * the above copyright notice and this notice appears in all
37 * copies, and that the name of Hewlett-Packard Company not be
38 * used in advertising or publicity pertaining to distribution
39 * of the software without specific, written prior permission.
40 * Hewlett-Packard Company makes no representations about the
41 * suitability of this software for any purpose.
44 #include <sys/cdefs.h>
45 __KERNEL_RCSID(0, "$NetBSD: sfdiv.c,v 1.3 2005/12/11 12:17:40 christos Exp $");
47 #include "../spmath/float.h"
48 #include "../spmath/sgl_float.h"
51 * Single Precision Floating-point Divide
54 sgl_fdiv(srcptr1
,srcptr2
,dstptr
,status
)
56 sgl_floating_point
*srcptr1
, *srcptr2
, *dstptr
;
59 register unsigned int opnd1
, opnd2
, opnd3
, result
;
60 register int dest_exponent
, count
;
61 register int inexact
= false, guardbit
= false, stickybit
= false;
67 * set sign bit of result
69 if (Sgl_sign(opnd1
) ^ Sgl_sign(opnd2
)) Sgl_setnegativezero(result
);
70 else Sgl_setzero(result
);
72 * check first operand for NaN's or infinity
74 if (Sgl_isinfinity_exponent(opnd1
)) {
75 if (Sgl_iszero_mantissa(opnd1
)) {
76 if (Sgl_isnotnan(opnd2
)) {
77 if (Sgl_isinfinity(opnd2
)) {
79 * invalid since both operands
82 if (Is_invalidtrap_enabled())
83 return(INVALIDEXCEPTION
);
85 Sgl_makequietnan(result
);
92 Sgl_setinfinity_exponentmantissa(result
);
99 * is NaN; signaling or quiet?
101 if (Sgl_isone_signaling(opnd1
)) {
102 /* trap if INVALIDTRAP enabled */
103 if (Is_invalidtrap_enabled())
104 return(INVALIDEXCEPTION
);
107 Sgl_set_quiet(opnd1
);
110 * is second operand a signaling NaN?
112 else if (Sgl_is_signalingnan(opnd2
)) {
113 /* trap if INVALIDTRAP enabled */
114 if (Is_invalidtrap_enabled())
115 return(INVALIDEXCEPTION
);
118 Sgl_set_quiet(opnd2
);
130 * check second operand for NaN's or infinity
132 if (Sgl_isinfinity_exponent(opnd2
)) {
133 if (Sgl_iszero_mantissa(opnd2
)) {
137 Sgl_setzero_exponentmantissa(result
);
142 * is NaN; signaling or quiet?
144 if (Sgl_isone_signaling(opnd2
)) {
145 /* trap if INVALIDTRAP enabled */
146 if (Is_invalidtrap_enabled()) return(INVALIDEXCEPTION
);
149 Sgl_set_quiet(opnd2
);
158 * check for division by zero
160 if (Sgl_iszero_exponentmantissa(opnd2
)) {
161 if (Sgl_iszero_exponentmantissa(opnd1
)) {
162 /* invalid since both operands are zero */
163 if (Is_invalidtrap_enabled()) return(INVALIDEXCEPTION
);
165 Sgl_makequietnan(result
);
169 if (Is_divisionbyzerotrap_enabled())
170 return(DIVISIONBYZEROEXCEPTION
);
171 Set_divisionbyzeroflag();
172 Sgl_setinfinity_exponentmantissa(result
);
179 dest_exponent
= Sgl_exponent(opnd1
) - Sgl_exponent(opnd2
) + SGL_BIAS
;
184 if (Sgl_isnotzero_exponent(opnd1
)) {
186 Sgl_clear_signexponent_set_hidden(opnd1
);
190 if (Sgl_iszero_mantissa(opnd1
)) {
191 Sgl_setzero_exponentmantissa(result
);
195 /* is denormalized; want to normalize */
196 Sgl_clear_signexponent(opnd1
);
197 Sgl_leftshiftby1(opnd1
);
198 Sgl_normalize(opnd1
,dest_exponent
);
200 /* opnd2 needs to have hidden bit set with msb in hidden bit */
201 if (Sgl_isnotzero_exponent(opnd2
)) {
202 Sgl_clear_signexponent_set_hidden(opnd2
);
205 /* is denormalized; want to normalize */
206 Sgl_clear_signexponent(opnd2
);
207 Sgl_leftshiftby1(opnd2
);
208 while(Sgl_iszero_hiddenhigh7mantissa(opnd2
)) {
209 Sgl_leftshiftby8(opnd2
);
212 if(Sgl_iszero_hiddenhigh3mantissa(opnd2
)) {
213 Sgl_leftshiftby4(opnd2
);
216 while(Sgl_iszero_hidden(opnd2
)) {
217 Sgl_leftshiftby1(opnd2
);
222 /* Divide the source mantissas */
225 * A non_restoring divide algorithm is used.
227 Sgl_subtract(opnd1
,opnd2
,opnd1
);
229 for (count
=1;count
<=SGL_P
&& Sgl_all(opnd1
);count
++) {
230 Sgl_leftshiftby1(opnd1
);
231 Sgl_leftshiftby1(opnd3
);
232 if (Sgl_iszero_sign(opnd1
)) {
233 Sgl_setone_lowmantissa(opnd3
);
234 Sgl_subtract(opnd1
,opnd2
,opnd1
);
236 else Sgl_addition(opnd1
,opnd2
,opnd1
);
238 if (count
<= SGL_P
) {
239 Sgl_leftshiftby1(opnd3
);
240 Sgl_setone_lowmantissa(opnd3
);
241 Sgl_leftshift(opnd3
,SGL_P
-count
);
242 if (Sgl_iszero_hidden(opnd3
)) {
243 Sgl_leftshiftby1(opnd3
);
248 if (Sgl_iszero_hidden(opnd3
)) {
249 /* need to get one more bit of result */
250 Sgl_leftshiftby1(opnd1
);
251 Sgl_leftshiftby1(opnd3
);
252 if (Sgl_iszero_sign(opnd1
)) {
253 Sgl_setone_lowmantissa(opnd3
);
254 Sgl_subtract(opnd1
,opnd2
,opnd1
);
256 else Sgl_addition(opnd1
,opnd2
,opnd1
);
259 if (Sgl_iszero_sign(opnd1
)) guardbit
= true;
260 stickybit
= Sgl_all(opnd1
);
262 inexact
= guardbit
| stickybit
;
267 if (inexact
&& (dest_exponent
> 0 || Is_underflowtrap_enabled())) {
268 Sgl_clear_signexponent(opnd3
);
269 switch (Rounding_mode()) {
271 if (Sgl_iszero_sign(result
))
272 Sgl_increment_mantissa(opnd3
);
275 if (Sgl_isone_sign(result
))
276 Sgl_increment_mantissa(opnd3
);
280 (stickybit
|| Sgl_isone_lowmantissa(opnd3
)))
281 Sgl_increment_mantissa(opnd3
);
283 if (Sgl_isone_hidden(opnd3
)) dest_exponent
++;
285 Sgl_set_mantissa(result
,opnd3
);
290 if (dest_exponent
>= SGL_INFINITY_EXPONENT
) {
291 /* trap if OVERFLOWTRAP enabled */
292 if (Is_overflowtrap_enabled()) {
294 * Adjust bias of result
296 Sgl_setwrapped_exponent(result
,dest_exponent
,ovfl
);
299 if (Is_inexacttrap_enabled())
300 return(OVERFLOWEXCEPTION
| INEXACTEXCEPTION
);
301 else Set_inexactflag();
303 return(OVERFLOWEXCEPTION
);
306 /* set result to infinity or largest number */
307 Sgl_setoverflow(result
);
313 else if (dest_exponent
<= 0) {
314 /* trap if UNDERFLOWTRAP enabled */
315 if (Is_underflowtrap_enabled()) {
317 * Adjust bias of result
319 Sgl_setwrapped_exponent(result
,dest_exponent
,unfl
);
322 if (Is_inexacttrap_enabled())
323 return(UNDERFLOWEXCEPTION
| INEXACTEXCEPTION
);
324 else Set_inexactflag();
326 return(UNDERFLOWEXCEPTION
);
329 /* Determine if should set underflow flag */
331 if (dest_exponent
== 0 && inexact
) {
332 switch (Rounding_mode()) {
334 if (Sgl_iszero_sign(result
)) {
335 Sgl_increment(opnd3
);
336 if (Sgl_isone_hiddenoverflow(opnd3
))
338 Sgl_decrement(opnd3
);
342 if (Sgl_isone_sign(result
)) {
343 Sgl_increment(opnd3
);
344 if (Sgl_isone_hiddenoverflow(opnd3
))
346 Sgl_decrement(opnd3
);
350 if (guardbit
&& (stickybit
||
351 Sgl_isone_lowmantissa(opnd3
))) {
352 Sgl_increment(opnd3
);
353 if (Sgl_isone_hiddenoverflow(opnd3
))
355 Sgl_decrement(opnd3
);
362 * denormalize result or set to signed zero
365 Sgl_denormalize(opnd3
,dest_exponent
,guardbit
,stickybit
,inexact
);
367 /* return rounded number */
369 switch (Rounding_mode()) {
371 if (Sgl_iszero_sign(result
)) {
372 Sgl_increment(opnd3
);
376 if (Sgl_isone_sign(result
)) {
377 Sgl_increment(opnd3
);
381 if (guardbit
&& (stickybit
||
382 Sgl_isone_lowmantissa(opnd3
))) {
383 Sgl_increment(opnd3
);
387 if (is_tiny
) Set_underflowflag();
389 Sgl_set_exponentmantissa(result
,opnd3
);
391 else Sgl_set_exponent(result
,dest_exponent
);
393 /* check for inexact */
395 if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION
);
396 else Set_inexactflag();