Linux 5.8-rc4
[linux/fpc-iii.git] / arch / parisc / math-emu / dfdiv.c
blob239150dbe088ccf40a546c750e890d121f57ccee
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
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>
7 */
8 /*
9 * BEGIN_DESC
11 * File:
12 * @(#) pa/spmath/dfdiv.c $Revision: 1.1 $
14 * Purpose:
15 * Double Precision Floating-point Divide
17 * External Interfaces:
18 * dbl_fdiv(srcptr1,srcptr2,dstptr,status)
20 * Internal Interfaces:
22 * Theory:
23 * <<please update with a overview of the operation of this file>>
25 * END_DESC
29 #include "float.h"
30 #include "dbl_float.h"
33 * Double Precision Floating-point Divide
36 int
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;
44 boolean is_tiny;
46 Dbl_copyfromptr(srcptr1,opnd1p1,opnd1p2);
47 Dbl_copyfromptr(srcptr2,opnd2p1,opnd2p2);
48 /*
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)) {
61 /*
62 * invalid since both operands
63 * are infinity
65 if (Is_invalidtrap_enabled())
66 return(INVALIDEXCEPTION);
67 Set_invalidflag();
68 Dbl_makequietnan(resultp1,resultp2);
69 Dbl_copytoptr(resultp1,resultp2,dstptr);
70 return(NOEXCEPTION);
73 * return infinity
75 Dbl_setinfinity_exponentmantissa(resultp1,resultp2);
76 Dbl_copytoptr(resultp1,resultp2,dstptr);
77 return(NOEXCEPTION);
80 else {
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);
88 /* make NaN quiet */
89 Set_invalidflag();
90 Dbl_set_quiet(opnd1p1);
92 /*
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);
99 /* make NaN quiet */
100 Set_invalidflag();
101 Dbl_set_quiet(opnd2p1);
102 Dbl_copytoptr(opnd2p1,opnd2p2,dstptr);
103 return(NOEXCEPTION);
106 * return quiet NaN
108 Dbl_copytoptr(opnd1p1,opnd1p2,dstptr);
109 return(NOEXCEPTION);
113 * check second operand for NaN's or infinity
115 if (Dbl_isinfinity_exponent(opnd2p1)) {
116 if (Dbl_iszero_mantissa(opnd2p1,opnd2p2)) {
118 * return zero
120 Dbl_setzero_exponentmantissa(resultp1,resultp2);
121 Dbl_copytoptr(resultp1,resultp2,dstptr);
122 return(NOEXCEPTION);
125 * is NaN; signaling or quiet?
127 if (Dbl_isone_signaling(opnd2p1)) {
128 /* trap if INVALIDTRAP enabled */
129 if (Is_invalidtrap_enabled()) return(INVALIDEXCEPTION);
130 /* make NaN quiet */
131 Set_invalidflag();
132 Dbl_set_quiet(opnd2p1);
135 * return quiet NaN
137 Dbl_copytoptr(opnd2p1,opnd2p2,dstptr);
138 return(NOEXCEPTION);
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);
147 Set_invalidflag();
148 Dbl_makequietnan(resultp1,resultp2);
149 Dbl_copytoptr(resultp1,resultp2,dstptr);
150 return(NOEXCEPTION);
152 if (Is_divisionbyzerotrap_enabled())
153 return(DIVISIONBYZEROEXCEPTION);
154 Set_divisionbyzeroflag();
155 Dbl_setinfinity_exponentmantissa(resultp1,resultp2);
156 Dbl_copytoptr(resultp1,resultp2,dstptr);
157 return(NOEXCEPTION);
160 * Generate exponent
162 dest_exponent = Dbl_exponent(opnd1p1) - Dbl_exponent(opnd2p1) + DBL_BIAS;
165 * Generate mantissa
167 if (Dbl_isnotzero_exponent(opnd1p1)) {
168 /* set hidden bit */
169 Dbl_clear_signexponent_set_hidden(opnd1p1);
171 else {
172 /* check for zero */
173 if (Dbl_iszero_mantissa(opnd1p1,opnd1p2)) {
174 Dbl_setzero_exponentmantissa(resultp1,resultp2);
175 Dbl_copytoptr(resultp1,resultp2,dstptr);
176 return(NOEXCEPTION);
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);
187 else {
188 /* is denormalized; want to normalize */
189 Dbl_clear_signexponent(opnd2p1);
190 Dbl_leftshiftby1(opnd2p1,opnd2p2);
191 while (Dbl_iszero_hiddenhigh7mantissa(opnd2p1)) {
192 dest_exponent+=8;
193 Dbl_leftshiftby8(opnd2p1,opnd2p2);
195 if (Dbl_iszero_hiddenhigh3mantissa(opnd2p1)) {
196 dest_exponent+=4;
197 Dbl_leftshiftby4(opnd2p1,opnd2p2);
199 while (Dbl_iszero_hidden(opnd2p1)) {
200 dest_exponent++;
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);
219 else {
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);
229 dest_exponent--;
232 else {
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);
241 else {
242 Twoword_add(opnd1p1,opnd1p2,opnd2p1,opnd2p2);
244 dest_exponent--;
246 if (Dbl_iszero_sign(opnd1p1)) guardbit = TRUE;
247 stickybit = Dbl_allp1(opnd1p1) || Dbl_allp2(opnd1p2);
249 inexact = guardbit | stickybit;
252 * round result
254 if (inexact && (dest_exponent > 0 || Is_underflowtrap_enabled())) {
255 Dbl_clear_signexponent(opnd3p1);
256 switch (Rounding_mode()) {
257 case ROUNDPLUS:
258 if (Dbl_iszero_sign(resultp1))
259 Dbl_increment(opnd3p1,opnd3p2);
260 break;
261 case ROUNDMINUS:
262 if (Dbl_isone_sign(resultp1))
263 Dbl_increment(opnd3p1,opnd3p2);
264 break;
265 case ROUNDNEAREST:
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);
276 * Test for overflow
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);
286 if (inexact)
287 if (Is_inexacttrap_enabled())
288 return(OVERFLOWEXCEPTION | INEXACTEXCEPTION);
289 else Set_inexactflag();
290 return(OVERFLOWEXCEPTION);
292 Set_overflowflag();
293 /* set result to infinity or largest number */
294 Dbl_setoverflow(resultp1,resultp2);
295 inexact = TRUE;
298 * Test for underflow
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);
308 if (inexact)
309 if (Is_inexacttrap_enabled())
310 return(UNDERFLOWEXCEPTION | INEXACTEXCEPTION);
311 else Set_inexactflag();
312 return(UNDERFLOWEXCEPTION);
315 /* Determine if should set underflow flag */
316 is_tiny = TRUE;
317 if (dest_exponent == 0 && inexact) {
318 switch (Rounding_mode()) {
319 case ROUNDPLUS:
320 if (Dbl_iszero_sign(resultp1)) {
321 Dbl_increment(opnd3p1,opnd3p2);
322 if (Dbl_isone_hiddenoverflow(opnd3p1))
323 is_tiny = FALSE;
324 Dbl_decrement(opnd3p1,opnd3p2);
326 break;
327 case ROUNDMINUS:
328 if (Dbl_isone_sign(resultp1)) {
329 Dbl_increment(opnd3p1,opnd3p2);
330 if (Dbl_isone_hiddenoverflow(opnd3p1))
331 is_tiny = FALSE;
332 Dbl_decrement(opnd3p1,opnd3p2);
334 break;
335 case ROUNDNEAREST:
336 if (guardbit && (stickybit ||
337 Dbl_isone_lowmantissap2(opnd3p2))) {
338 Dbl_increment(opnd3p1,opnd3p2);
339 if (Dbl_isone_hiddenoverflow(opnd3p1))
340 is_tiny = FALSE;
341 Dbl_decrement(opnd3p1,opnd3p2);
343 break;
348 * denormalize result or set to signed zero
350 stickybit = inexact;
351 Dbl_denormalize(opnd3p1,opnd3p2,dest_exponent,guardbit,
352 stickybit,inexact);
354 /* return rounded number */
355 if (inexact) {
356 switch (Rounding_mode()) {
357 case ROUNDPLUS:
358 if (Dbl_iszero_sign(resultp1)) {
359 Dbl_increment(opnd3p1,opnd3p2);
361 break;
362 case ROUNDMINUS:
363 if (Dbl_isone_sign(resultp1)) {
364 Dbl_increment(opnd3p1,opnd3p2);
366 break;
367 case ROUNDNEAREST:
368 if (guardbit && (stickybit ||
369 Dbl_isone_lowmantissap2(opnd3p2))) {
370 Dbl_increment(opnd3p1,opnd3p2);
372 break;
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 */
382 if (inexact) {
383 if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION);
384 else Set_inexactflag();
386 return(NOEXCEPTION);