No empty .Rs/.Re
[netbsd-mini2440.git] / sys / arch / hppa / spmath / sfmpy.c
blob5f4739575ff8aeb652e68d6dd43ca52322e54e2f
1 /* $NetBSD: sfmpy.c,v 1.3 2005/12/11 12:17:40 christos Exp $ */
3 /* $OpenBSD: sfmpy.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: sfmpy.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 Multiply
53 int
54 sgl_fmpy(srcptr1,srcptr2,dstptr,status)
56 sgl_floating_point *srcptr1, *srcptr2, *dstptr;
57 unsigned int *status;
59 register unsigned int opnd1, opnd2, opnd3, result;
60 register int dest_exponent, count;
61 register int inexact = false, guardbit = false, stickybit = false;
62 int is_tiny;
64 opnd1 = *srcptr1;
65 opnd2 = *srcptr2;
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_iszero_exponentmantissa(opnd2)) {
79 * invalid since operands are infinity
80 * and zero
82 if (Is_invalidtrap_enabled())
83 return(INVALIDEXCEPTION);
84 Set_invalidflag();
85 Sgl_makequietnan(result);
86 *dstptr = result;
87 return(NOEXCEPTION);
90 * return infinity
92 Sgl_setinfinity_exponentmantissa(result);
93 *dstptr = result;
94 return(NOEXCEPTION);
97 else {
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);
105 /* make NaN quiet */
106 Set_invalidflag();
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);
116 /* make NaN quiet */
117 Set_invalidflag();
118 Sgl_set_quiet(opnd2);
119 *dstptr = opnd2;
120 return(NOEXCEPTION);
123 * return quiet NaN
125 *dstptr = opnd1;
126 return(NOEXCEPTION);
130 * check second operand for NaN's or infinity
132 if (Sgl_isinfinity_exponent(opnd2)) {
133 if (Sgl_iszero_mantissa(opnd2)) {
134 if (Sgl_iszero_exponentmantissa(opnd1)) {
135 /* invalid since operands are zero & infinity */
136 if (Is_invalidtrap_enabled())
137 return(INVALIDEXCEPTION);
138 Set_invalidflag();
139 Sgl_makequietnan(opnd2);
140 *dstptr = opnd2;
141 return(NOEXCEPTION);
144 * return infinity
146 Sgl_setinfinity_exponentmantissa(result);
147 *dstptr = result;
148 return(NOEXCEPTION);
151 * is NaN; signaling or quiet?
153 if (Sgl_isone_signaling(opnd2)) {
154 /* trap if INVALIDTRAP enabled */
155 if (Is_invalidtrap_enabled()) return(INVALIDEXCEPTION);
157 /* make NaN quiet */
158 Set_invalidflag();
159 Sgl_set_quiet(opnd2);
162 * return quiet NaN
164 *dstptr = opnd2;
165 return(NOEXCEPTION);
168 * Generate exponent
170 dest_exponent = Sgl_exponent(opnd1) + Sgl_exponent(opnd2) - SGL_BIAS;
173 * Generate mantissa
175 if (Sgl_isnotzero_exponent(opnd1)) {
176 /* set hidden bit */
177 Sgl_clear_signexponent_set_hidden(opnd1);
179 else {
180 /* check for zero */
181 if (Sgl_iszero_mantissa(opnd1)) {
182 Sgl_setzero_exponentmantissa(result);
183 *dstptr = result;
184 return(NOEXCEPTION);
186 /* is denormalized, adjust exponent */
187 Sgl_clear_signexponent(opnd1);
188 Sgl_leftshiftby1(opnd1);
189 Sgl_normalize(opnd1,dest_exponent);
191 /* opnd2 needs to have hidden bit set with msb in hidden bit */
192 if (Sgl_isnotzero_exponent(opnd2)) {
193 Sgl_clear_signexponent_set_hidden(opnd2);
195 else {
196 /* check for zero */
197 if (Sgl_iszero_mantissa(opnd2)) {
198 Sgl_setzero_exponentmantissa(result);
199 *dstptr = result;
200 return(NOEXCEPTION);
202 /* is denormalized; want to normalize */
203 Sgl_clear_signexponent(opnd2);
204 Sgl_leftshiftby1(opnd2);
205 Sgl_normalize(opnd2,dest_exponent);
208 /* Multiply two source mantissas together */
210 Sgl_leftshiftby4(opnd2); /* make room for guard bits */
211 Sgl_setzero(opnd3);
213 * Four bits at a time are inspected in each loop, and a
214 * simple shift and add multiply algorithm is used.
216 for (count=1;count<SGL_P;count+=4) {
217 stickybit |= Slow4(opnd3);
218 Sgl_rightshiftby4(opnd3);
219 if (Sbit28(opnd1)) Sall(opnd3) += (Sall(opnd2) << 3);
220 if (Sbit29(opnd1)) Sall(opnd3) += (Sall(opnd2) << 2);
221 if (Sbit30(opnd1)) Sall(opnd3) += (Sall(opnd2) << 1);
222 if (Sbit31(opnd1)) Sall(opnd3) += Sall(opnd2);
223 Sgl_rightshiftby4(opnd1);
225 /* make sure result is left-justified */
226 if (Sgl_iszero_sign(opnd3)) {
227 Sgl_leftshiftby1(opnd3);
229 else {
230 /* result mantissa >= 2. */
231 dest_exponent++;
233 /* check for denormalized result */
234 while (Sgl_iszero_sign(opnd3)) {
235 Sgl_leftshiftby1(opnd3);
236 dest_exponent--;
239 * check for guard, sticky and inexact bits
241 stickybit |= Sgl_all(opnd3) << (SGL_BITLENGTH - SGL_EXP_LENGTH + 1);
242 guardbit = Sbit24(opnd3);
243 inexact = guardbit | stickybit;
245 /* re-align mantissa */
246 Sgl_rightshiftby8(opnd3);
249 * round result
251 if (inexact && (dest_exponent>0 || Is_underflowtrap_enabled())) {
252 Sgl_clear_signexponent(opnd3);
253 switch (Rounding_mode()) {
254 case ROUNDPLUS:
255 if (Sgl_iszero_sign(result))
256 Sgl_increment(opnd3);
257 break;
258 case ROUNDMINUS:
259 if (Sgl_isone_sign(result))
260 Sgl_increment(opnd3);
261 break;
262 case ROUNDNEAREST:
263 if (guardbit &&
264 (stickybit || Sgl_isone_lowmantissa(opnd3)))
265 Sgl_increment(opnd3);
266 break;
268 if (Sgl_isone_hidden(opnd3)) dest_exponent++;
270 Sgl_set_mantissa(result,opnd3);
273 * Test for overflow
275 if (dest_exponent >= SGL_INFINITY_EXPONENT) {
276 /* trap if OVERFLOWTRAP enabled */
277 if (Is_overflowtrap_enabled()) {
279 * Adjust bias of result
281 Sgl_setwrapped_exponent(result,dest_exponent,ovfl);
282 *dstptr = result;
283 if (inexact) {
284 if (Is_inexacttrap_enabled())
285 return(OVERFLOWEXCEPTION | INEXACTEXCEPTION);
286 else Set_inexactflag();
288 return(OVERFLOWEXCEPTION);
290 inexact = true;
291 Set_overflowflag();
292 /* set result to infinity or largest number */
293 Sgl_setoverflow(result);
296 * Test for underflow
298 else if (dest_exponent <= 0) {
299 /* trap if UNDERFLOWTRAP enabled */
300 if (Is_underflowtrap_enabled()) {
302 * Adjust bias of result
304 Sgl_setwrapped_exponent(result,dest_exponent,unfl);
305 *dstptr = result;
306 if (inexact) {
307 if (Is_inexacttrap_enabled())
308 return(UNDERFLOWEXCEPTION | INEXACTEXCEPTION);
309 else Set_inexactflag();
311 return(UNDERFLOWEXCEPTION);
314 /* Determine if should set underflow flag */
315 is_tiny = true;
316 if (dest_exponent == 0 && inexact) {
317 switch (Rounding_mode()) {
318 case ROUNDPLUS:
319 if (Sgl_iszero_sign(result)) {
320 Sgl_increment(opnd3);
321 if (Sgl_isone_hiddenoverflow(opnd3))
322 is_tiny = false;
323 Sgl_decrement(opnd3);
325 break;
326 case ROUNDMINUS:
327 if (Sgl_isone_sign(result)) {
328 Sgl_increment(opnd3);
329 if (Sgl_isone_hiddenoverflow(opnd3))
330 is_tiny = false;
331 Sgl_decrement(opnd3);
333 break;
334 case ROUNDNEAREST:
335 if (guardbit && (stickybit ||
336 Sgl_isone_lowmantissa(opnd3))) {
337 Sgl_increment(opnd3);
338 if (Sgl_isone_hiddenoverflow(opnd3))
339 is_tiny = false;
340 Sgl_decrement(opnd3);
342 break;
347 * denormalize result or set to signed zero
349 stickybit = inexact;
350 Sgl_denormalize(opnd3,dest_exponent,guardbit,stickybit,inexact);
352 /* return zero or smallest number */
353 if (inexact) {
354 switch (Rounding_mode()) {
355 case ROUNDPLUS:
356 if (Sgl_iszero_sign(result))
357 Sgl_increment(opnd3);
358 break;
359 case ROUNDMINUS:
360 if (Sgl_isone_sign(result))
361 Sgl_increment(opnd3);
362 break;
363 case ROUNDNEAREST:
364 if (guardbit && (stickybit ||
365 Sgl_isone_lowmantissa(opnd3)))
366 Sgl_increment(opnd3);
367 break;
369 if (is_tiny) Set_underflowflag();
371 Sgl_set_exponentmantissa(result,opnd3);
373 else Sgl_set_exponent(result,dest_exponent);
374 *dstptr = result;
376 /* check for inexact */
377 if (inexact) {
378 if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION);
379 else Set_inexactflag();
381 return(NOEXCEPTION);