Linux 5.8-rc4
[linux/fpc-iii.git] / arch / parisc / math-emu / dfrem.c
blob9243a5954d08b43b080350d09941300662d5857e
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/dfrem.c $Revision: 1.1 $
14 * Purpose:
15 * Double Precision Floating-point Remainder
17 * External Interfaces:
18 * dbl_frem(srcptr1,srcptr2,dstptr,status)
20 * Internal Interfaces:
22 * Theory:
23 * <<please update with a overview of the operation of this file>>
25 * END_DESC
30 #include "float.h"
31 #include "dbl_float.h"
34 * Double Precision Floating-point Remainder
37 int
38 dbl_frem (dbl_floating_point * srcptr1, dbl_floating_point * srcptr2,
39 dbl_floating_point * dstptr, unsigned int *status)
41 register unsigned int opnd1p1, opnd1p2, opnd2p1, opnd2p2;
42 register unsigned int resultp1, resultp2;
43 register int opnd1_exponent, opnd2_exponent, dest_exponent, stepcount;
44 register boolean roundup = FALSE;
46 Dbl_copyfromptr(srcptr1,opnd1p1,opnd1p2);
47 Dbl_copyfromptr(srcptr2,opnd2p1,opnd2p2);
49 * check first operand for NaN's or infinity
51 if ((opnd1_exponent = Dbl_exponent(opnd1p1)) == DBL_INFINITY_EXPONENT) {
52 if (Dbl_iszero_mantissa(opnd1p1,opnd1p2)) {
53 if (Dbl_isnotnan(opnd2p1,opnd2p2)) {
54 /* invalid since first operand is infinity */
55 if (Is_invalidtrap_enabled())
56 return(INVALIDEXCEPTION);
57 Set_invalidflag();
58 Dbl_makequietnan(resultp1,resultp2);
59 Dbl_copytoptr(resultp1,resultp2,dstptr);
60 return(NOEXCEPTION);
63 else {
65 * is NaN; signaling or quiet?
67 if (Dbl_isone_signaling(opnd1p1)) {
68 /* trap if INVALIDTRAP enabled */
69 if (Is_invalidtrap_enabled())
70 return(INVALIDEXCEPTION);
71 /* make NaN quiet */
72 Set_invalidflag();
73 Dbl_set_quiet(opnd1p1);
75 /*
76 * is second operand a signaling NaN?
78 else if (Dbl_is_signalingnan(opnd2p1)) {
79 /* trap if INVALIDTRAP enabled */
80 if (Is_invalidtrap_enabled())
81 return(INVALIDEXCEPTION);
82 /* make NaN quiet */
83 Set_invalidflag();
84 Dbl_set_quiet(opnd2p1);
85 Dbl_copytoptr(opnd2p1,opnd2p2,dstptr);
86 return(NOEXCEPTION);
89 * return quiet NaN
91 Dbl_copytoptr(opnd1p1,opnd1p2,dstptr);
92 return(NOEXCEPTION);
96 * check second operand for NaN's or infinity
98 if ((opnd2_exponent = Dbl_exponent(opnd2p1)) == DBL_INFINITY_EXPONENT) {
99 if (Dbl_iszero_mantissa(opnd2p1,opnd2p2)) {
101 * return first operand
103 Dbl_copytoptr(opnd1p1,opnd1p2,dstptr);
104 return(NOEXCEPTION);
107 * is NaN; signaling or quiet?
109 if (Dbl_isone_signaling(opnd2p1)) {
110 /* trap if INVALIDTRAP enabled */
111 if (Is_invalidtrap_enabled()) return(INVALIDEXCEPTION);
112 /* make NaN quiet */
113 Set_invalidflag();
114 Dbl_set_quiet(opnd2p1);
117 * return quiet NaN
119 Dbl_copytoptr(opnd2p1,opnd2p2,dstptr);
120 return(NOEXCEPTION);
123 * check second operand for zero
125 if (Dbl_iszero_exponentmantissa(opnd2p1,opnd2p2)) {
126 /* invalid since second operand is zero */
127 if (Is_invalidtrap_enabled()) return(INVALIDEXCEPTION);
128 Set_invalidflag();
129 Dbl_makequietnan(resultp1,resultp2);
130 Dbl_copytoptr(resultp1,resultp2,dstptr);
131 return(NOEXCEPTION);
135 * get sign of result
137 resultp1 = opnd1p1;
140 * check for denormalized operands
142 if (opnd1_exponent == 0) {
143 /* check for zero */
144 if (Dbl_iszero_mantissa(opnd1p1,opnd1p2)) {
145 Dbl_copytoptr(opnd1p1,opnd1p2,dstptr);
146 return(NOEXCEPTION);
148 /* normalize, then continue */
149 opnd1_exponent = 1;
150 Dbl_normalize(opnd1p1,opnd1p2,opnd1_exponent);
152 else {
153 Dbl_clear_signexponent_set_hidden(opnd1p1);
155 if (opnd2_exponent == 0) {
156 /* normalize, then continue */
157 opnd2_exponent = 1;
158 Dbl_normalize(opnd2p1,opnd2p2,opnd2_exponent);
160 else {
161 Dbl_clear_signexponent_set_hidden(opnd2p1);
164 /* find result exponent and divide step loop count */
165 dest_exponent = opnd2_exponent - 1;
166 stepcount = opnd1_exponent - opnd2_exponent;
169 * check for opnd1/opnd2 < 1
171 if (stepcount < 0) {
173 * check for opnd1/opnd2 > 1/2
175 * In this case n will round to 1, so
176 * r = opnd1 - opnd2
178 if (stepcount == -1 &&
179 Dbl_isgreaterthan(opnd1p1,opnd1p2,opnd2p1,opnd2p2)) {
180 /* set sign */
181 Dbl_allp1(resultp1) = ~Dbl_allp1(resultp1);
182 /* align opnd2 with opnd1 */
183 Dbl_leftshiftby1(opnd2p1,opnd2p2);
184 Dbl_subtract(opnd2p1,opnd2p2,opnd1p1,opnd1p2,
185 opnd2p1,opnd2p2);
186 /* now normalize */
187 while (Dbl_iszero_hidden(opnd2p1)) {
188 Dbl_leftshiftby1(opnd2p1,opnd2p2);
189 dest_exponent--;
191 Dbl_set_exponentmantissa(resultp1,resultp2,opnd2p1,opnd2p2);
192 goto testforunderflow;
195 * opnd1/opnd2 <= 1/2
197 * In this case n will round to zero, so
198 * r = opnd1
200 Dbl_set_exponentmantissa(resultp1,resultp2,opnd1p1,opnd1p2);
201 dest_exponent = opnd1_exponent;
202 goto testforunderflow;
206 * Generate result
208 * Do iterative subtract until remainder is less than operand 2.
210 while (stepcount-- > 0 && (Dbl_allp1(opnd1p1) || Dbl_allp2(opnd1p2))) {
211 if (Dbl_isnotlessthan(opnd1p1,opnd1p2,opnd2p1,opnd2p2)) {
212 Dbl_subtract(opnd1p1,opnd1p2,opnd2p1,opnd2p2,opnd1p1,opnd1p2);
214 Dbl_leftshiftby1(opnd1p1,opnd1p2);
217 * Do last subtract, then determine which way to round if remainder
218 * is exactly 1/2 of opnd2
220 if (Dbl_isnotlessthan(opnd1p1,opnd1p2,opnd2p1,opnd2p2)) {
221 Dbl_subtract(opnd1p1,opnd1p2,opnd2p1,opnd2p2,opnd1p1,opnd1p2);
222 roundup = TRUE;
224 if (stepcount > 0 || Dbl_iszero(opnd1p1,opnd1p2)) {
225 /* division is exact, remainder is zero */
226 Dbl_setzero_exponentmantissa(resultp1,resultp2);
227 Dbl_copytoptr(resultp1,resultp2,dstptr);
228 return(NOEXCEPTION);
232 * Check for cases where opnd1/opnd2 < n
234 * In this case the result's sign will be opposite that of
235 * opnd1. The mantissa also needs some correction.
237 Dbl_leftshiftby1(opnd1p1,opnd1p2);
238 if (Dbl_isgreaterthan(opnd1p1,opnd1p2,opnd2p1,opnd2p2)) {
239 Dbl_invert_sign(resultp1);
240 Dbl_leftshiftby1(opnd2p1,opnd2p2);
241 Dbl_subtract(opnd2p1,opnd2p2,opnd1p1,opnd1p2,opnd1p1,opnd1p2);
243 /* check for remainder being exactly 1/2 of opnd2 */
244 else if (Dbl_isequal(opnd1p1,opnd1p2,opnd2p1,opnd2p2) && roundup) {
245 Dbl_invert_sign(resultp1);
248 /* normalize result's mantissa */
249 while (Dbl_iszero_hidden(opnd1p1)) {
250 dest_exponent--;
251 Dbl_leftshiftby1(opnd1p1,opnd1p2);
253 Dbl_set_exponentmantissa(resultp1,resultp2,opnd1p1,opnd1p2);
256 * Test for underflow
258 testforunderflow:
259 if (dest_exponent <= 0) {
260 /* trap if UNDERFLOWTRAP enabled */
261 if (Is_underflowtrap_enabled()) {
263 * Adjust bias of result
265 Dbl_setwrapped_exponent(resultp1,dest_exponent,unfl);
266 /* frem is always exact */
267 Dbl_copytoptr(resultp1,resultp2,dstptr);
268 return(UNDERFLOWEXCEPTION);
271 * denormalize result or set to signed zero
273 if (dest_exponent >= (1 - DBL_P)) {
274 Dbl_rightshift_exponentmantissa(resultp1,resultp2,
275 1-dest_exponent);
277 else {
278 Dbl_setzero_exponentmantissa(resultp1,resultp2);
281 else Dbl_set_exponent(resultp1,dest_exponent);
282 Dbl_copytoptr(resultp1,resultp2,dstptr);
283 return(NOEXCEPTION);