1 // SPDX-License-Identifier: GPL-2.0-or-later
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>
12 * @(#) pa/spmath/sfmpy.c $Revision: 1.1 $
15 * Single Precision Floating-point Multiply
17 * External Interfaces:
18 * sgl_fmpy(srcptr1,srcptr2,dstptr,status)
20 * Internal Interfaces:
23 * <<please update with a overview of the operation of this file>>
30 #include "sgl_float.h"
33 * Single Precision Floating-point Multiply
38 sgl_floating_point
*srcptr1
,
39 sgl_floating_point
*srcptr2
,
40 sgl_floating_point
*dstptr
,
43 register unsigned int opnd1
, opnd2
, opnd3
, result
;
44 register int dest_exponent
, count
;
45 register boolean inexact
= FALSE
, guardbit
= FALSE
, stickybit
= FALSE
;
51 * set sign bit of result
53 if (Sgl_sign(opnd1
) ^ Sgl_sign(opnd2
)) Sgl_setnegativezero(result
);
54 else Sgl_setzero(result
);
56 * check first operand for NaN's or infinity
58 if (Sgl_isinfinity_exponent(opnd1
)) {
59 if (Sgl_iszero_mantissa(opnd1
)) {
60 if (Sgl_isnotnan(opnd2
)) {
61 if (Sgl_iszero_exponentmantissa(opnd2
)) {
63 * invalid since operands are infinity
66 if (Is_invalidtrap_enabled())
67 return(INVALIDEXCEPTION
);
69 Sgl_makequietnan(result
);
76 Sgl_setinfinity_exponentmantissa(result
);
83 * is NaN; signaling or quiet?
85 if (Sgl_isone_signaling(opnd1
)) {
86 /* trap if INVALIDTRAP enabled */
87 if (Is_invalidtrap_enabled())
88 return(INVALIDEXCEPTION
);
94 * is second operand a signaling NaN?
96 else if (Sgl_is_signalingnan(opnd2
)) {
97 /* trap if INVALIDTRAP enabled */
98 if (Is_invalidtrap_enabled())
99 return(INVALIDEXCEPTION
);
102 Sgl_set_quiet(opnd2
);
114 * check second operand for NaN's or infinity
116 if (Sgl_isinfinity_exponent(opnd2
)) {
117 if (Sgl_iszero_mantissa(opnd2
)) {
118 if (Sgl_iszero_exponentmantissa(opnd1
)) {
119 /* invalid since operands are zero & infinity */
120 if (Is_invalidtrap_enabled())
121 return(INVALIDEXCEPTION
);
123 Sgl_makequietnan(opnd2
);
130 Sgl_setinfinity_exponentmantissa(result
);
135 * is NaN; signaling or quiet?
137 if (Sgl_isone_signaling(opnd2
)) {
138 /* trap if INVALIDTRAP enabled */
139 if (Is_invalidtrap_enabled()) return(INVALIDEXCEPTION
);
143 Sgl_set_quiet(opnd2
);
154 dest_exponent
= Sgl_exponent(opnd1
) + Sgl_exponent(opnd2
) - SGL_BIAS
;
159 if (Sgl_isnotzero_exponent(opnd1
)) {
161 Sgl_clear_signexponent_set_hidden(opnd1
);
165 if (Sgl_iszero_mantissa(opnd1
)) {
166 Sgl_setzero_exponentmantissa(result
);
170 /* is denormalized, adjust exponent */
171 Sgl_clear_signexponent(opnd1
);
172 Sgl_leftshiftby1(opnd1
);
173 Sgl_normalize(opnd1
,dest_exponent
);
175 /* opnd2 needs to have hidden bit set with msb in hidden bit */
176 if (Sgl_isnotzero_exponent(opnd2
)) {
177 Sgl_clear_signexponent_set_hidden(opnd2
);
181 if (Sgl_iszero_mantissa(opnd2
)) {
182 Sgl_setzero_exponentmantissa(result
);
186 /* is denormalized; want to normalize */
187 Sgl_clear_signexponent(opnd2
);
188 Sgl_leftshiftby1(opnd2
);
189 Sgl_normalize(opnd2
,dest_exponent
);
192 /* Multiply two source mantissas together */
194 Sgl_leftshiftby4(opnd2
); /* make room for guard bits */
197 * Four bits at a time are inspected in each loop, and a
198 * simple shift and add multiply algorithm is used.
200 for (count
=1;count
<SGL_P
;count
+=4) {
201 stickybit
|= Slow4(opnd3
);
202 Sgl_rightshiftby4(opnd3
);
203 if (Sbit28(opnd1
)) Sall(opnd3
) += (Sall(opnd2
) << 3);
204 if (Sbit29(opnd1
)) Sall(opnd3
) += (Sall(opnd2
) << 2);
205 if (Sbit30(opnd1
)) Sall(opnd3
) += (Sall(opnd2
) << 1);
206 if (Sbit31(opnd1
)) Sall(opnd3
) += Sall(opnd2
);
207 Sgl_rightshiftby4(opnd1
);
209 /* make sure result is left-justified */
210 if (Sgl_iszero_sign(opnd3
)) {
211 Sgl_leftshiftby1(opnd3
);
214 /* result mantissa >= 2. */
217 /* check for denormalized result */
218 while (Sgl_iszero_sign(opnd3
)) {
219 Sgl_leftshiftby1(opnd3
);
223 * check for guard, sticky and inexact bits
225 stickybit
|= Sgl_all(opnd3
) << (SGL_BITLENGTH
- SGL_EXP_LENGTH
+ 1);
226 guardbit
= Sbit24(opnd3
);
227 inexact
= guardbit
| stickybit
;
229 /* re-align mantissa */
230 Sgl_rightshiftby8(opnd3
);
235 if (inexact
&& (dest_exponent
>0 || Is_underflowtrap_enabled())) {
236 Sgl_clear_signexponent(opnd3
);
237 switch (Rounding_mode()) {
239 if (Sgl_iszero_sign(result
))
240 Sgl_increment(opnd3
);
243 if (Sgl_isone_sign(result
))
244 Sgl_increment(opnd3
);
248 if (stickybit
|| Sgl_isone_lowmantissa(opnd3
))
249 Sgl_increment(opnd3
);
252 if (Sgl_isone_hidden(opnd3
)) dest_exponent
++;
254 Sgl_set_mantissa(result
,opnd3
);
259 if (dest_exponent
>= SGL_INFINITY_EXPONENT
) {
260 /* trap if OVERFLOWTRAP enabled */
261 if (Is_overflowtrap_enabled()) {
263 * Adjust bias of result
265 Sgl_setwrapped_exponent(result
,dest_exponent
,ovfl
);
268 if (Is_inexacttrap_enabled())
269 return(OVERFLOWEXCEPTION
| INEXACTEXCEPTION
);
270 else Set_inexactflag();
271 return(OVERFLOWEXCEPTION
);
275 /* set result to infinity or largest number */
276 Sgl_setoverflow(result
);
281 else if (dest_exponent
<= 0) {
282 /* trap if UNDERFLOWTRAP enabled */
283 if (Is_underflowtrap_enabled()) {
285 * Adjust bias of result
287 Sgl_setwrapped_exponent(result
,dest_exponent
,unfl
);
290 if (Is_inexacttrap_enabled())
291 return(UNDERFLOWEXCEPTION
| INEXACTEXCEPTION
);
292 else Set_inexactflag();
293 return(UNDERFLOWEXCEPTION
);
296 /* Determine if should set underflow flag */
298 if (dest_exponent
== 0 && inexact
) {
299 switch (Rounding_mode()) {
301 if (Sgl_iszero_sign(result
)) {
302 Sgl_increment(opnd3
);
303 if (Sgl_isone_hiddenoverflow(opnd3
))
305 Sgl_decrement(opnd3
);
309 if (Sgl_isone_sign(result
)) {
310 Sgl_increment(opnd3
);
311 if (Sgl_isone_hiddenoverflow(opnd3
))
313 Sgl_decrement(opnd3
);
317 if (guardbit
&& (stickybit
||
318 Sgl_isone_lowmantissa(opnd3
))) {
319 Sgl_increment(opnd3
);
320 if (Sgl_isone_hiddenoverflow(opnd3
))
322 Sgl_decrement(opnd3
);
329 * denormalize result or set to signed zero
332 Sgl_denormalize(opnd3
,dest_exponent
,guardbit
,stickybit
,inexact
);
334 /* return zero or smallest number */
336 switch (Rounding_mode()) {
338 if (Sgl_iszero_sign(result
)) {
339 Sgl_increment(opnd3
);
343 if (Sgl_isone_sign(result
)) {
344 Sgl_increment(opnd3
);
348 if (guardbit
&& (stickybit
||
349 Sgl_isone_lowmantissa(opnd3
))) {
350 Sgl_increment(opnd3
);
354 if (is_tiny
) Set_underflowflag();
356 Sgl_set_exponentmantissa(result
,opnd3
);
358 else Sgl_set_exponent(result
,dest_exponent
);
361 /* check for inexact */
363 if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION
);
364 else Set_inexactflag();