1 /* $NetBSD: dfmpy.c,v 1.3 2005/12/11 12:17:40 christos Exp $ */
3 /* $OpenBSD: dfmpy.c,v 1.4 2001/03/29 03:58:17 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: dfmpy.c,v 1.3 2005/12/11 12:17:40 christos Exp $");
47 #include "../spmath/float.h"
48 #include "../spmath/dbl_float.h"
51 * Double Precision Floating-point Multiply
55 dbl_fmpy(srcptr1
,srcptr2
,dstptr
,status
)
57 dbl_floating_point
*srcptr1
, *srcptr2
, *dstptr
;
60 register unsigned int opnd1p1
, opnd1p2
, opnd2p1
, opnd2p2
;
61 register unsigned int opnd3p1
, opnd3p2
, resultp1
, resultp2
;
62 register int dest_exponent
, count
;
63 register int inexact
= false, guardbit
= false, stickybit
= false;
66 Dbl_copyfromptr(srcptr1
,opnd1p1
,opnd1p2
);
67 Dbl_copyfromptr(srcptr2
,opnd2p1
,opnd2p2
);
70 * set sign bit of result
72 if (Dbl_sign(opnd1p1
) ^ Dbl_sign(opnd2p1
))
73 Dbl_setnegativezerop1(resultp1
);
74 else Dbl_setzerop1(resultp1
);
76 * check first operand for NaN's or infinity
78 if (Dbl_isinfinity_exponent(opnd1p1
)) {
79 if (Dbl_iszero_mantissa(opnd1p1
,opnd1p2
)) {
80 if (Dbl_isnotnan(opnd2p1
,opnd2p2
)) {
81 if (Dbl_iszero_exponentmantissa(opnd2p1
,opnd2p2
)) {
83 * invalid since operands are infinity
86 if (Is_invalidtrap_enabled())
87 return(INVALIDEXCEPTION
);
89 Dbl_makequietnan(resultp1
,resultp2
);
90 Dbl_copytoptr(resultp1
,resultp2
,dstptr
);
96 Dbl_setinfinity_exponentmantissa(resultp1
,resultp2
);
97 Dbl_copytoptr(resultp1
,resultp2
,dstptr
);
103 * is NaN; signaling or quiet?
105 if (Dbl_isone_signaling(opnd1p1
)) {
106 /* trap if INVALIDTRAP enabled */
107 if (Is_invalidtrap_enabled())
108 return(INVALIDEXCEPTION
);
111 Dbl_set_quiet(opnd1p1
);
114 * is second operand a signaling NaN?
116 else if (Dbl_is_signalingnan(opnd2p1
)) {
117 /* trap if INVALIDTRAP enabled */
118 if (Is_invalidtrap_enabled())
119 return(INVALIDEXCEPTION
);
122 Dbl_set_quiet(opnd2p1
);
123 Dbl_copytoptr(opnd2p1
,opnd2p2
,dstptr
);
129 Dbl_copytoptr(opnd1p1
,opnd1p2
,dstptr
);
134 * check second operand for NaN's or infinity
136 if (Dbl_isinfinity_exponent(opnd2p1
)) {
137 if (Dbl_iszero_mantissa(opnd2p1
,opnd2p2
)) {
138 if (Dbl_iszero_exponentmantissa(opnd1p1
,opnd1p2
)) {
139 /* invalid since operands are zero & infinity */
140 if (Is_invalidtrap_enabled())
141 return(INVALIDEXCEPTION
);
143 Dbl_makequietnan(opnd2p1
,opnd2p2
);
144 Dbl_copytoptr(opnd2p1
,opnd2p2
,dstptr
);
150 Dbl_setinfinity_exponentmantissa(resultp1
,resultp2
);
151 Dbl_copytoptr(resultp1
,resultp2
,dstptr
);
155 * is NaN; signaling or quiet?
157 if (Dbl_isone_signaling(opnd2p1
)) {
158 /* trap if INVALIDTRAP enabled */
159 if (Is_invalidtrap_enabled()) return(INVALIDEXCEPTION
);
162 Dbl_set_quiet(opnd2p1
);
167 Dbl_copytoptr(opnd2p1
,opnd2p2
,dstptr
);
173 dest_exponent
= Dbl_exponent(opnd1p1
) + Dbl_exponent(opnd2p1
) -DBL_BIAS
;
178 if (Dbl_isnotzero_exponent(opnd1p1
)) {
180 Dbl_clear_signexponent_set_hidden(opnd1p1
);
184 if (Dbl_iszero_mantissa(opnd1p1
,opnd1p2
)) {
185 Dbl_setzero_exponentmantissa(resultp1
,resultp2
);
186 Dbl_copytoptr(resultp1
,resultp2
,dstptr
);
189 /* is denormalized, adjust exponent */
190 Dbl_clear_signexponent(opnd1p1
);
191 Dbl_leftshiftby1(opnd1p1
,opnd1p2
);
192 Dbl_normalize(opnd1p1
,opnd1p2
,dest_exponent
);
194 /* opnd2 needs to have hidden bit set with msb in hidden bit */
195 if (Dbl_isnotzero_exponent(opnd2p1
)) {
196 Dbl_clear_signexponent_set_hidden(opnd2p1
);
200 if (Dbl_iszero_mantissa(opnd2p1
,opnd2p2
)) {
201 Dbl_setzero_exponentmantissa(resultp1
,resultp2
);
202 Dbl_copytoptr(resultp1
,resultp2
,dstptr
);
205 /* is denormalized; want to normalize */
206 Dbl_clear_signexponent(opnd2p1
);
207 Dbl_leftshiftby1(opnd2p1
,opnd2p2
);
208 Dbl_normalize(opnd2p1
,opnd2p2
,dest_exponent
);
211 /* Multiply two source mantissas together */
213 /* make room for guard bits */
214 Dbl_leftshiftby7(opnd2p1
,opnd2p2
);
215 Dbl_setzero(opnd3p1
,opnd3p2
);
217 * Four bits at a time are inspected in each loop, and a
218 * simple shift and add multiply algorithm is used.
220 for (count
=1;count
<=DBL_P
;count
+=4) {
221 stickybit
|= Dlow4p2(opnd3p2
);
222 Dbl_rightshiftby4(opnd3p1
,opnd3p2
);
223 if (Dbit28p2(opnd1p2
)) {
224 /* Twoword_add should be an ADDC followed by an ADD. */
225 Twoword_add(opnd3p1
, opnd3p2
, opnd2p1
<<3 | opnd2p2
>>29,
228 if (Dbit29p2(opnd1p2
)) {
229 Twoword_add(opnd3p1
, opnd3p2
, opnd2p1
<<2 | opnd2p2
>>30,
232 if (Dbit30p2(opnd1p2
)) {
233 Twoword_add(opnd3p1
, opnd3p2
, opnd2p1
<<1 | opnd2p2
>>31,
236 if (Dbit31p2(opnd1p2
)) {
237 Twoword_add(opnd3p1
, opnd3p2
, opnd2p1
, opnd2p2
);
239 Dbl_rightshiftby4(opnd1p1
,opnd1p2
);
241 if (Dbit3p1(opnd3p1
)==0) {
242 Dbl_leftshiftby1(opnd3p1
,opnd3p2
);
245 /* result mantissa >= 2. */
248 /* check for denormalized result */
249 while (Dbit3p1(opnd3p1
)==0) {
250 Dbl_leftshiftby1(opnd3p1
,opnd3p2
);
254 * check for guard, sticky and inexact bits
256 stickybit
|= Dallp2(opnd3p2
) << 25;
257 guardbit
= (Dallp2(opnd3p2
) << 24) >> 31;
258 inexact
= guardbit
| stickybit
;
260 /* align result mantissa */
261 Dbl_rightshiftby8(opnd3p1
,opnd3p2
);
266 if (inexact
&& (dest_exponent
>0 || Is_underflowtrap_enabled())) {
267 Dbl_clear_signexponent(opnd3p1
);
268 switch (Rounding_mode()) {
270 if (Dbl_iszero_sign(resultp1
))
271 Dbl_increment(opnd3p1
,opnd3p2
);
274 if (Dbl_isone_sign(resultp1
))
275 Dbl_increment(opnd3p1
,opnd3p2
);
279 (stickybit
|| Dbl_isone_lowmantissap2(opnd3p2
)))
280 Dbl_increment(opnd3p1
,opnd3p2
);
283 if (Dbl_isone_hidden(opnd3p1
)) dest_exponent
++;
285 Dbl_set_mantissa(resultp1
,resultp2
,opnd3p1
,opnd3p2
);
290 if (dest_exponent
>= DBL_INFINITY_EXPONENT
) {
291 /* trap if OVERFLOWTRAP enabled */
292 if (Is_overflowtrap_enabled()) {
294 * Adjust bias of result
296 Dbl_setwrapped_exponent(resultp1
,dest_exponent
,ovfl
);
297 Dbl_copytoptr(resultp1
,resultp2
,dstptr
);
299 if (Is_inexacttrap_enabled())
300 return (OVERFLOWEXCEPTION
| INEXACTEXCEPTION
);
304 return (OVERFLOWEXCEPTION
);
308 /* set result to infinity or largest number */
309 Dbl_setoverflow(resultp1
,resultp2
);
314 else if (dest_exponent
<= 0) {
315 /* trap if UNDERFLOWTRAP enabled */
316 if (Is_underflowtrap_enabled()) {
318 * Adjust bias of result
320 Dbl_setwrapped_exponent(resultp1
,dest_exponent
,unfl
);
321 Dbl_copytoptr(resultp1
,resultp2
,dstptr
);
323 if (Is_inexacttrap_enabled())
324 return (UNDERFLOWEXCEPTION
| INEXACTEXCEPTION
);
328 return (UNDERFLOWEXCEPTION
);
331 /* Determine if should set underflow flag */
333 if (dest_exponent
== 0 && inexact
) {
334 switch (Rounding_mode()) {
336 if (Dbl_iszero_sign(resultp1
)) {
337 Dbl_increment(opnd3p1
,opnd3p2
);
338 if (Dbl_isone_hiddenoverflow(opnd3p1
))
340 Dbl_decrement(opnd3p1
,opnd3p2
);
344 if (Dbl_isone_sign(resultp1
)) {
345 Dbl_increment(opnd3p1
,opnd3p2
);
346 if (Dbl_isone_hiddenoverflow(opnd3p1
))
348 Dbl_decrement(opnd3p1
,opnd3p2
);
352 if (guardbit
&& (stickybit
||
353 Dbl_isone_lowmantissap2(opnd3p2
))) {
354 Dbl_increment(opnd3p1
,opnd3p2
);
355 if (Dbl_isone_hiddenoverflow(opnd3p1
))
357 Dbl_decrement(opnd3p1
,opnd3p2
);
364 * denormalize result or set to signed zero
367 Dbl_denormalize(opnd3p1
,opnd3p2
,dest_exponent
,guardbit
,
370 /* return zero or smallest number */
372 switch (Rounding_mode()) {
374 if (Dbl_iszero_sign(resultp1
)) {
375 Dbl_increment(opnd3p1
,opnd3p2
);
379 if (Dbl_isone_sign(resultp1
)) {
380 Dbl_increment(opnd3p1
,opnd3p2
);
384 if (guardbit
&& (stickybit
||
385 Dbl_isone_lowmantissap2(opnd3p2
))) {
386 Dbl_increment(opnd3p1
,opnd3p2
);
390 if (is_tiny
) Set_underflowflag();
392 Dbl_set_exponentmantissa(resultp1
,resultp2
,opnd3p1
,opnd3p2
);
394 else Dbl_set_exponent(resultp1
,dest_exponent
);
395 /* check for inexact */
396 Dbl_copytoptr(resultp1
,resultp2
,dstptr
);
398 if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION
);
399 else Set_inexactflag();