1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * Linux/PA-RISC Project (http://www.parisc-linux.org/)
5 * Floating-point emulation code
6 * Copyright (C) 2001 Hewlett-Packard (Paul Bame) <bame@debian.org>
12 * @(#) pa/spmath/dfdiv.c $Revision: 1.1 $
15 * Double Precision Floating-point Divide
17 * External Interfaces:
18 * dbl_fdiv(srcptr1,srcptr2,dstptr,status)
20 * Internal Interfaces:
23 * <<please update with a overview of the operation of this file>>
30 #include "dbl_float.h"
33 * Double Precision Floating-point Divide
37 dbl_fdiv (dbl_floating_point
* srcptr1
, dbl_floating_point
* srcptr2
,
38 dbl_floating_point
* dstptr
, unsigned int *status
)
40 register unsigned int opnd1p1
, opnd1p2
, opnd2p1
, opnd2p2
;
41 register unsigned int opnd3p1
, opnd3p2
, resultp1
, resultp2
;
42 register int dest_exponent
, count
;
43 register boolean inexact
= FALSE
, guardbit
= FALSE
, stickybit
= FALSE
;
46 Dbl_copyfromptr(srcptr1
,opnd1p1
,opnd1p2
);
47 Dbl_copyfromptr(srcptr2
,opnd2p1
,opnd2p2
);
49 * set sign bit of result
51 if (Dbl_sign(opnd1p1
) ^ Dbl_sign(opnd2p1
))
52 Dbl_setnegativezerop1(resultp1
);
53 else Dbl_setzerop1(resultp1
);
55 * check first operand for NaN's or infinity
57 if (Dbl_isinfinity_exponent(opnd1p1
)) {
58 if (Dbl_iszero_mantissa(opnd1p1
,opnd1p2
)) {
59 if (Dbl_isnotnan(opnd2p1
,opnd2p2
)) {
60 if (Dbl_isinfinity(opnd2p1
,opnd2p2
)) {
62 * invalid since both operands
65 if (Is_invalidtrap_enabled())
66 return(INVALIDEXCEPTION
);
68 Dbl_makequietnan(resultp1
,resultp2
);
69 Dbl_copytoptr(resultp1
,resultp2
,dstptr
);
75 Dbl_setinfinity_exponentmantissa(resultp1
,resultp2
);
76 Dbl_copytoptr(resultp1
,resultp2
,dstptr
);
82 * is NaN; signaling or quiet?
84 if (Dbl_isone_signaling(opnd1p1
)) {
85 /* trap if INVALIDTRAP enabled */
86 if (Is_invalidtrap_enabled())
87 return(INVALIDEXCEPTION
);
90 Dbl_set_quiet(opnd1p1
);
93 * is second operand a signaling NaN?
95 else if (Dbl_is_signalingnan(opnd2p1
)) {
96 /* trap if INVALIDTRAP enabled */
97 if (Is_invalidtrap_enabled())
98 return(INVALIDEXCEPTION
);
101 Dbl_set_quiet(opnd2p1
);
102 Dbl_copytoptr(opnd2p1
,opnd2p2
,dstptr
);
108 Dbl_copytoptr(opnd1p1
,opnd1p2
,dstptr
);
113 * check second operand for NaN's or infinity
115 if (Dbl_isinfinity_exponent(opnd2p1
)) {
116 if (Dbl_iszero_mantissa(opnd2p1
,opnd2p2
)) {
120 Dbl_setzero_exponentmantissa(resultp1
,resultp2
);
121 Dbl_copytoptr(resultp1
,resultp2
,dstptr
);
125 * is NaN; signaling or quiet?
127 if (Dbl_isone_signaling(opnd2p1
)) {
128 /* trap if INVALIDTRAP enabled */
129 if (Is_invalidtrap_enabled()) return(INVALIDEXCEPTION
);
132 Dbl_set_quiet(opnd2p1
);
137 Dbl_copytoptr(opnd2p1
,opnd2p2
,dstptr
);
141 * check for division by zero
143 if (Dbl_iszero_exponentmantissa(opnd2p1
,opnd2p2
)) {
144 if (Dbl_iszero_exponentmantissa(opnd1p1
,opnd1p2
)) {
145 /* invalid since both operands are zero */
146 if (Is_invalidtrap_enabled()) return(INVALIDEXCEPTION
);
148 Dbl_makequietnan(resultp1
,resultp2
);
149 Dbl_copytoptr(resultp1
,resultp2
,dstptr
);
152 if (Is_divisionbyzerotrap_enabled())
153 return(DIVISIONBYZEROEXCEPTION
);
154 Set_divisionbyzeroflag();
155 Dbl_setinfinity_exponentmantissa(resultp1
,resultp2
);
156 Dbl_copytoptr(resultp1
,resultp2
,dstptr
);
162 dest_exponent
= Dbl_exponent(opnd1p1
) - Dbl_exponent(opnd2p1
) + DBL_BIAS
;
167 if (Dbl_isnotzero_exponent(opnd1p1
)) {
169 Dbl_clear_signexponent_set_hidden(opnd1p1
);
173 if (Dbl_iszero_mantissa(opnd1p1
,opnd1p2
)) {
174 Dbl_setzero_exponentmantissa(resultp1
,resultp2
);
175 Dbl_copytoptr(resultp1
,resultp2
,dstptr
);
178 /* is denormalized, want to normalize */
179 Dbl_clear_signexponent(opnd1p1
);
180 Dbl_leftshiftby1(opnd1p1
,opnd1p2
);
181 Dbl_normalize(opnd1p1
,opnd1p2
,dest_exponent
);
183 /* opnd2 needs to have hidden bit set with msb in hidden bit */
184 if (Dbl_isnotzero_exponent(opnd2p1
)) {
185 Dbl_clear_signexponent_set_hidden(opnd2p1
);
188 /* is denormalized; want to normalize */
189 Dbl_clear_signexponent(opnd2p1
);
190 Dbl_leftshiftby1(opnd2p1
,opnd2p2
);
191 while (Dbl_iszero_hiddenhigh7mantissa(opnd2p1
)) {
193 Dbl_leftshiftby8(opnd2p1
,opnd2p2
);
195 if (Dbl_iszero_hiddenhigh3mantissa(opnd2p1
)) {
197 Dbl_leftshiftby4(opnd2p1
,opnd2p2
);
199 while (Dbl_iszero_hidden(opnd2p1
)) {
201 Dbl_leftshiftby1(opnd2p1
,opnd2p2
);
205 /* Divide the source mantissas */
208 * A non-restoring divide algorithm is used.
210 Twoword_subtract(opnd1p1
,opnd1p2
,opnd2p1
,opnd2p2
);
211 Dbl_setzero(opnd3p1
,opnd3p2
);
212 for (count
=1; count
<= DBL_P
&& (opnd1p1
|| opnd1p2
); count
++) {
213 Dbl_leftshiftby1(opnd1p1
,opnd1p2
);
214 Dbl_leftshiftby1(opnd3p1
,opnd3p2
);
215 if (Dbl_iszero_sign(opnd1p1
)) {
216 Dbl_setone_lowmantissap2(opnd3p2
);
217 Twoword_subtract(opnd1p1
,opnd1p2
,opnd2p1
,opnd2p2
);
220 Twoword_add(opnd1p1
, opnd1p2
, opnd2p1
, opnd2p2
);
223 if (count
<= DBL_P
) {
224 Dbl_leftshiftby1(opnd3p1
,opnd3p2
);
225 Dbl_setone_lowmantissap2(opnd3p2
);
226 Dbl_leftshift(opnd3p1
,opnd3p2
,(DBL_P
-count
));
227 if (Dbl_iszero_hidden(opnd3p1
)) {
228 Dbl_leftshiftby1(opnd3p1
,opnd3p2
);
233 if (Dbl_iszero_hidden(opnd3p1
)) {
234 /* need to get one more bit of result */
235 Dbl_leftshiftby1(opnd1p1
,opnd1p2
);
236 Dbl_leftshiftby1(opnd3p1
,opnd3p2
);
237 if (Dbl_iszero_sign(opnd1p1
)) {
238 Dbl_setone_lowmantissap2(opnd3p2
);
239 Twoword_subtract(opnd1p1
,opnd1p2
,opnd2p1
,opnd2p2
);
242 Twoword_add(opnd1p1
,opnd1p2
,opnd2p1
,opnd2p2
);
246 if (Dbl_iszero_sign(opnd1p1
)) guardbit
= TRUE
;
247 stickybit
= Dbl_allp1(opnd1p1
) || Dbl_allp2(opnd1p2
);
249 inexact
= guardbit
| stickybit
;
254 if (inexact
&& (dest_exponent
> 0 || Is_underflowtrap_enabled())) {
255 Dbl_clear_signexponent(opnd3p1
);
256 switch (Rounding_mode()) {
258 if (Dbl_iszero_sign(resultp1
))
259 Dbl_increment(opnd3p1
,opnd3p2
);
262 if (Dbl_isone_sign(resultp1
))
263 Dbl_increment(opnd3p1
,opnd3p2
);
266 if (guardbit
&& (stickybit
||
267 Dbl_isone_lowmantissap2(opnd3p2
))) {
268 Dbl_increment(opnd3p1
,opnd3p2
);
271 if (Dbl_isone_hidden(opnd3p1
)) dest_exponent
++;
273 Dbl_set_mantissa(resultp1
,resultp2
,opnd3p1
,opnd3p2
);
278 if (dest_exponent
>= DBL_INFINITY_EXPONENT
) {
279 /* trap if OVERFLOWTRAP enabled */
280 if (Is_overflowtrap_enabled()) {
282 * Adjust bias of result
284 Dbl_setwrapped_exponent(resultp1
,dest_exponent
,ovfl
);
285 Dbl_copytoptr(resultp1
,resultp2
,dstptr
);
287 if (Is_inexacttrap_enabled())
288 return(OVERFLOWEXCEPTION
| INEXACTEXCEPTION
);
289 else Set_inexactflag();
290 return(OVERFLOWEXCEPTION
);
293 /* set result to infinity or largest number */
294 Dbl_setoverflow(resultp1
,resultp2
);
300 else if (dest_exponent
<= 0) {
301 /* trap if UNDERFLOWTRAP enabled */
302 if (Is_underflowtrap_enabled()) {
304 * Adjust bias of result
306 Dbl_setwrapped_exponent(resultp1
,dest_exponent
,unfl
);
307 Dbl_copytoptr(resultp1
,resultp2
,dstptr
);
309 if (Is_inexacttrap_enabled())
310 return(UNDERFLOWEXCEPTION
| INEXACTEXCEPTION
);
311 else Set_inexactflag();
312 return(UNDERFLOWEXCEPTION
);
315 /* Determine if should set underflow flag */
317 if (dest_exponent
== 0 && inexact
) {
318 switch (Rounding_mode()) {
320 if (Dbl_iszero_sign(resultp1
)) {
321 Dbl_increment(opnd3p1
,opnd3p2
);
322 if (Dbl_isone_hiddenoverflow(opnd3p1
))
324 Dbl_decrement(opnd3p1
,opnd3p2
);
328 if (Dbl_isone_sign(resultp1
)) {
329 Dbl_increment(opnd3p1
,opnd3p2
);
330 if (Dbl_isone_hiddenoverflow(opnd3p1
))
332 Dbl_decrement(opnd3p1
,opnd3p2
);
336 if (guardbit
&& (stickybit
||
337 Dbl_isone_lowmantissap2(opnd3p2
))) {
338 Dbl_increment(opnd3p1
,opnd3p2
);
339 if (Dbl_isone_hiddenoverflow(opnd3p1
))
341 Dbl_decrement(opnd3p1
,opnd3p2
);
348 * denormalize result or set to signed zero
351 Dbl_denormalize(opnd3p1
,opnd3p2
,dest_exponent
,guardbit
,
354 /* return rounded number */
356 switch (Rounding_mode()) {
358 if (Dbl_iszero_sign(resultp1
)) {
359 Dbl_increment(opnd3p1
,opnd3p2
);
363 if (Dbl_isone_sign(resultp1
)) {
364 Dbl_increment(opnd3p1
,opnd3p2
);
368 if (guardbit
&& (stickybit
||
369 Dbl_isone_lowmantissap2(opnd3p2
))) {
370 Dbl_increment(opnd3p1
,opnd3p2
);
374 if (is_tiny
) Set_underflowflag();
376 Dbl_set_exponentmantissa(resultp1
,resultp2
,opnd3p1
,opnd3p2
);
378 else Dbl_set_exponent(resultp1
,dest_exponent
);
379 Dbl_copytoptr(resultp1
,resultp2
,dstptr
);
381 /* check for inexact */
383 if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION
);
384 else Set_inexactflag();