Expand PMF_FN_* macros.
[netbsd-mini2440.git] / sys / arch / hppa / spmath / sfrem.c
blob31d84a1a3f8f19e7bac0b93aa40bf632224e27f7
1 /* $NetBSD: sfrem.c,v 1.3 2005/12/11 12:17:40 christos Exp $ */
3 /* $OpenBSD: sfrem.c,v 1.4 2001/03/29 03:58:19 mickey Exp $ */
5 /*
6 * Copyright 1996 1995 by Open Software Foundation, Inc.
7 * All Rights Reserved
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.
27 * pmk1.1
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: sfrem.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 Remainder
53 int
54 sgl_frem(srcptr1,srcptr2,dstptr,status)
56 sgl_floating_point *srcptr1, *srcptr2, *dstptr;
57 unsigned int *status;
59 register unsigned int opnd1, opnd2, result;
60 register int opnd1_exponent, opnd2_exponent, dest_exponent, stepcount;
61 register int roundup = false;
63 opnd1 = *srcptr1;
64 opnd2 = *srcptr2;
66 * check first operand for NaN's or infinity
68 if ((opnd1_exponent = Sgl_exponent(opnd1)) == SGL_INFINITY_EXPONENT) {
69 if (Sgl_iszero_mantissa(opnd1)) {
70 if (Sgl_isnotnan(opnd2)) {
71 /* invalid since first operand is infinity */
72 if (Is_invalidtrap_enabled())
73 return(INVALIDEXCEPTION);
74 Set_invalidflag();
75 Sgl_makequietnan(result);
76 *dstptr = result;
77 return(NOEXCEPTION);
80 else {
82 * is NaN; signaling or quiet?
84 if (Sgl_isone_signaling(opnd1)) {
85 /* trap if INVALIDTRAP enabled */
86 if (Is_invalidtrap_enabled())
87 return(INVALIDEXCEPTION);
88 /* make NaN quiet */
89 Set_invalidflag();
90 Sgl_set_quiet(opnd1);
93 * is second operand a signaling NaN?
95 else if (Sgl_is_signalingnan(opnd2)) {
96 /* trap if INVALIDTRAP enabled */
97 if (Is_invalidtrap_enabled())
98 return(INVALIDEXCEPTION);
99 /* make NaN quiet */
100 Set_invalidflag();
101 Sgl_set_quiet(opnd2);
102 *dstptr = opnd2;
103 return(NOEXCEPTION);
106 * return quiet NaN
108 *dstptr = opnd1;
109 return(NOEXCEPTION);
113 * check second operand for NaN's or infinity
115 if ((opnd2_exponent = Sgl_exponent(opnd2)) == SGL_INFINITY_EXPONENT) {
116 if (Sgl_iszero_mantissa(opnd2)) {
118 * return first operand
120 *dstptr = opnd1;
121 return(NOEXCEPTION);
124 * is NaN; signaling or quiet?
126 if (Sgl_isone_signaling(opnd2)) {
127 /* trap if INVALIDTRAP enabled */
128 if (Is_invalidtrap_enabled()) return(INVALIDEXCEPTION);
129 /* make NaN quiet */
130 Set_invalidflag();
131 Sgl_set_quiet(opnd2);
134 * return quiet NaN
136 *dstptr = opnd2;
137 return(NOEXCEPTION);
140 * check second operand for zero
142 if (Sgl_iszero_exponentmantissa(opnd2)) {
143 /* invalid since second operand is zero */
144 if (Is_invalidtrap_enabled()) return(INVALIDEXCEPTION);
145 Set_invalidflag();
146 Sgl_makequietnan(result);
147 *dstptr = result;
148 return(NOEXCEPTION);
152 * get sign of result
154 result = opnd1;
157 * check for denormalized operands
159 if (opnd1_exponent == 0) {
160 /* check for zero */
161 if (Sgl_iszero_mantissa(opnd1)) {
162 *dstptr = opnd1;
163 return(NOEXCEPTION);
165 /* normalize, then continue */
166 opnd1_exponent = 1;
167 Sgl_normalize(opnd1,opnd1_exponent);
169 else {
170 Sgl_clear_signexponent_set_hidden(opnd1);
172 if (opnd2_exponent == 0) {
173 /* normalize, then continue */
174 opnd2_exponent = 1;
175 Sgl_normalize(opnd2,opnd2_exponent);
177 else {
178 Sgl_clear_signexponent_set_hidden(opnd2);
181 /* find result exponent and divide step loop count */
182 dest_exponent = opnd2_exponent - 1;
183 stepcount = opnd1_exponent - opnd2_exponent;
186 * check for opnd1/opnd2 < 1
188 if (stepcount < 0) {
190 * check for opnd1/opnd2 > 1/2
192 * In this case n will round to 1, so
193 * r = opnd1 - opnd2
195 if (stepcount == -1 && Sgl_isgreaterthan(opnd1,opnd2)) {
196 Sgl_all(result) = ~Sgl_all(result); /* set sign */
197 /* align opnd2 with opnd1 */
198 Sgl_leftshiftby1(opnd2);
199 Sgl_subtract(opnd2,opnd1,opnd2);
200 /* now normalize */
201 while (Sgl_iszero_hidden(opnd2)) {
202 Sgl_leftshiftby1(opnd2);
203 dest_exponent--;
205 Sgl_set_exponentmantissa(result,opnd2);
206 goto testforunderflow;
209 * opnd1/opnd2 <= 1/2
211 * In this case n will round to zero, so
212 * r = opnd1
214 Sgl_set_exponentmantissa(result,opnd1);
215 dest_exponent = opnd1_exponent;
216 goto testforunderflow;
220 * Generate result
222 * Do iterative subtract until remainder is less than operand 2.
224 while (stepcount-- > 0 && Sgl_all(opnd1)) {
225 if (Sgl_isnotlessthan(opnd1,opnd2))
226 Sgl_subtract(opnd1,opnd2,opnd1);
227 Sgl_leftshiftby1(opnd1);
230 * Do last subtract, then determine which way to round if remainder
231 * is exactly 1/2 of opnd2
233 if (Sgl_isnotlessthan(opnd1,opnd2)) {
234 Sgl_subtract(opnd1,opnd2,opnd1);
235 roundup = true;
237 if (stepcount > 0 || Sgl_iszero(opnd1)) {
238 /* division is exact, remainder is zero */
239 Sgl_setzero_exponentmantissa(result);
240 *dstptr = result;
241 return(NOEXCEPTION);
245 * Check for cases where opnd1/opnd2 < n
247 * In this case the result's sign will be opposite that of
248 * opnd1. The mantissa also needs some correction.
250 Sgl_leftshiftby1(opnd1);
251 if (Sgl_isgreaterthan(opnd1,opnd2)) {
252 Sgl_invert_sign(result);
253 Sgl_subtract((opnd2<<1),opnd1,opnd1);
255 /* check for remainder being exactly 1/2 of opnd2 */
256 else if (Sgl_isequal(opnd1,opnd2) && roundup) {
257 Sgl_invert_sign(result);
260 /* normalize result's mantissa */
261 while (Sgl_iszero_hidden(opnd1)) {
262 dest_exponent--;
263 Sgl_leftshiftby1(opnd1);
265 Sgl_set_exponentmantissa(result,opnd1);
268 * Test for underflow
270 testforunderflow:
271 if (dest_exponent <= 0) {
272 /* trap if UNDERFLOWTRAP enabled */
273 if (Is_underflowtrap_enabled()) {
275 * Adjust bias of result
277 Sgl_setwrapped_exponent(result,dest_exponent,unfl);
278 *dstptr = result;
279 /* frem is always exact */
280 return(UNDERFLOWEXCEPTION);
283 * denormalize result or set to signed zero
285 if (dest_exponent >= (1 - SGL_P)) {
286 Sgl_rightshift_exponentmantissa(result,1-dest_exponent);
287 } else {
288 Sgl_setzero_exponentmantissa(result);
291 else Sgl_set_exponent(result,dest_exponent);
292 *dstptr = result;
293 return(NOEXCEPTION);