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 $ */
6 * Copyright 1996 1995 by Open Software Foundation, Inc.
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.
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
54 sgl_fmpy(srcptr1
,srcptr2
,dstptr
,status
)
56 sgl_floating_point
*srcptr1
, *srcptr2
, *dstptr
;
59 register unsigned int opnd1
, opnd2
, opnd3
, result
;
60 register int dest_exponent
, count
;
61 register int inexact
= false, guardbit
= false, stickybit
= false;
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
82 if (Is_invalidtrap_enabled())
83 return(INVALIDEXCEPTION
);
85 Sgl_makequietnan(result
);
92 Sgl_setinfinity_exponentmantissa(result
);
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
);
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
);
118 Sgl_set_quiet(opnd2
);
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
);
139 Sgl_makequietnan(opnd2
);
146 Sgl_setinfinity_exponentmantissa(result
);
151 * is NaN; signaling or quiet?
153 if (Sgl_isone_signaling(opnd2
)) {
154 /* trap if INVALIDTRAP enabled */
155 if (Is_invalidtrap_enabled()) return(INVALIDEXCEPTION
);
159 Sgl_set_quiet(opnd2
);
170 dest_exponent
= Sgl_exponent(opnd1
) + Sgl_exponent(opnd2
) - SGL_BIAS
;
175 if (Sgl_isnotzero_exponent(opnd1
)) {
177 Sgl_clear_signexponent_set_hidden(opnd1
);
181 if (Sgl_iszero_mantissa(opnd1
)) {
182 Sgl_setzero_exponentmantissa(result
);
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
);
197 if (Sgl_iszero_mantissa(opnd2
)) {
198 Sgl_setzero_exponentmantissa(result
);
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 */
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
);
230 /* result mantissa >= 2. */
233 /* check for denormalized result */
234 while (Sgl_iszero_sign(opnd3
)) {
235 Sgl_leftshiftby1(opnd3
);
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
);
251 if (inexact
&& (dest_exponent
>0 || Is_underflowtrap_enabled())) {
252 Sgl_clear_signexponent(opnd3
);
253 switch (Rounding_mode()) {
255 if (Sgl_iszero_sign(result
))
256 Sgl_increment(opnd3
);
259 if (Sgl_isone_sign(result
))
260 Sgl_increment(opnd3
);
264 (stickybit
|| Sgl_isone_lowmantissa(opnd3
)))
265 Sgl_increment(opnd3
);
268 if (Sgl_isone_hidden(opnd3
)) dest_exponent
++;
270 Sgl_set_mantissa(result
,opnd3
);
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
);
284 if (Is_inexacttrap_enabled())
285 return(OVERFLOWEXCEPTION
| INEXACTEXCEPTION
);
286 else Set_inexactflag();
288 return(OVERFLOWEXCEPTION
);
292 /* set result to infinity or largest number */
293 Sgl_setoverflow(result
);
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
);
307 if (Is_inexacttrap_enabled())
308 return(UNDERFLOWEXCEPTION
| INEXACTEXCEPTION
);
309 else Set_inexactflag();
311 return(UNDERFLOWEXCEPTION
);
314 /* Determine if should set underflow flag */
316 if (dest_exponent
== 0 && inexact
) {
317 switch (Rounding_mode()) {
319 if (Sgl_iszero_sign(result
)) {
320 Sgl_increment(opnd3
);
321 if (Sgl_isone_hiddenoverflow(opnd3
))
323 Sgl_decrement(opnd3
);
327 if (Sgl_isone_sign(result
)) {
328 Sgl_increment(opnd3
);
329 if (Sgl_isone_hiddenoverflow(opnd3
))
331 Sgl_decrement(opnd3
);
335 if (guardbit
&& (stickybit
||
336 Sgl_isone_lowmantissa(opnd3
))) {
337 Sgl_increment(opnd3
);
338 if (Sgl_isone_hiddenoverflow(opnd3
))
340 Sgl_decrement(opnd3
);
347 * denormalize result or set to signed zero
350 Sgl_denormalize(opnd3
,dest_exponent
,guardbit
,stickybit
,inexact
);
352 /* return zero or smallest number */
354 switch (Rounding_mode()) {
356 if (Sgl_iszero_sign(result
))
357 Sgl_increment(opnd3
);
360 if (Sgl_isone_sign(result
))
361 Sgl_increment(opnd3
);
364 if (guardbit
&& (stickybit
||
365 Sgl_isone_lowmantissa(opnd3
)))
366 Sgl_increment(opnd3
);
369 if (is_tiny
) Set_underflowflag();
371 Sgl_set_exponentmantissa(result
,opnd3
);
373 else Sgl_set_exponent(result
,dest_exponent
);
376 /* check for inexact */
378 if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION
);
379 else Set_inexactflag();