File Index
Files and directories
Sign in
FILE

sfmpy.c

File preview with syntax highlighting.

linux-6.19.14/arch/parisc/math-emu/sfmpy.c C
  1// SPDX-License-Identifier: GPL-2.0-or-later
  2/*
  3 * Linux/PA-RISC Project (http://www.parisc-linux.org/)
  4 *
  5 * Floating-point emulation code
  6 *  Copyright (C) 2001 Hewlett-Packard (Paul Bame) <bame@debian.org>
  7 */
  8/*
  9 * BEGIN_DESC
 10 *
 11 *  File:
 12 *	@(#)	pa/spmath/sfmpy.c		$Revision: 1.1 $
 13 *
 14 *  Purpose:
 15 *	Single Precision Floating-point Multiply
 16 *
 17 *  External Interfaces:
 18 *	sgl_fmpy(srcptr1,srcptr2,dstptr,status)
 19 *
 20 *  Internal Interfaces:
 21 *
 22 *  Theory:
 23 *	<<please update with a overview of the operation of this file>>
 24 *
 25 * END_DESC
 26*/
 27
 28
 29#include "float.h"
 30#include "sgl_float.h"
 31
 32/*
 33 *  Single Precision Floating-point Multiply
 34 */
 35
 36int
 37sgl_fmpy(
 38    sgl_floating_point *srcptr1,
 39    sgl_floating_point *srcptr2,
 40    sgl_floating_point *dstptr,
 41    unsigned int *status)
 42{
 43	register unsigned int opnd1, opnd2, opnd3, result;
 44	register int dest_exponent, count;
 45	register boolean inexact = FALSE, guardbit = FALSE, stickybit = FALSE;
 46	boolean is_tiny;
 47
 48	opnd1 = *srcptr1;
 49	opnd2 = *srcptr2;
 50	/* 
 51	 * set sign bit of result 
 52	 */
 53	if (Sgl_sign(opnd1) ^ Sgl_sign(opnd2)) Sgl_setnegativezero(result);  
 54	else Sgl_setzero(result);
 55	/*
 56	 * check first operand for NaN's or infinity
 57	 */
 58	if (Sgl_isinfinity_exponent(opnd1)) {
 59		if (Sgl_iszero_mantissa(opnd1)) {
 60			if (Sgl_isnotnan(opnd2)) {
 61				if (Sgl_iszero_exponentmantissa(opnd2)) {
 62					/* 
 63					 * invalid since operands are infinity 
 64					 * and zero 
 65					 */
 66					if (Is_invalidtrap_enabled()) 
 67                                		return(INVALIDEXCEPTION);
 68                                	Set_invalidflag();
 69                                	Sgl_makequietnan(result);
 70					*dstptr = result;
 71					return(NOEXCEPTION);
 72				}
 73				/*
 74			 	 * return infinity
 75			 	 */
 76				Sgl_setinfinity_exponentmantissa(result);
 77				*dstptr = result;
 78				return(NOEXCEPTION);
 79			}
 80		}
 81		else {
 82                	/*
 83                 	 * is NaN; signaling or quiet?
 84                 	 */
 85                	if (Sgl_isone_signaling(opnd1)) {
 86                        	/* trap if INVALIDTRAP enabled */
 87                        	if (Is_invalidtrap_enabled()) 
 88                            		return(INVALIDEXCEPTION);
 89                        	/* make NaN quiet */
 90                        	Set_invalidflag();
 91                        	Sgl_set_quiet(opnd1);
 92                	}
 93			/* 
 94			 * is second operand a signaling NaN? 
 95			 */
 96			else if (Sgl_is_signalingnan(opnd2)) {
 97                        	/* trap if INVALIDTRAP enabled */
 98                        	if (Is_invalidtrap_enabled()) 
 99                            		return(INVALIDEXCEPTION);
100                        	/* make NaN quiet */
101                        	Set_invalidflag();
102                        	Sgl_set_quiet(opnd2);
103                		*dstptr = opnd2;
104                		return(NOEXCEPTION);
105			}
106                	/*
107                 	 * return quiet NaN
108                 	 */
109                	*dstptr = opnd1;
110                	return(NOEXCEPTION);
111		}
112	}
113	/*
114	 * check second operand for NaN's or infinity
115	 */
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);
122                                Set_invalidflag();
123                                Sgl_makequietnan(opnd2);
124				*dstptr = opnd2;
125				return(NOEXCEPTION);
126			}
127			/*
128			 * return infinity
129			 */
130			Sgl_setinfinity_exponentmantissa(result);
131			*dstptr = result;
132			return(NOEXCEPTION);
133		}
134                /*
135                 * is NaN; signaling or quiet?
136                 */
137                if (Sgl_isone_signaling(opnd2)) {
138                        /* trap if INVALIDTRAP enabled */
139                        if (Is_invalidtrap_enabled()) return(INVALIDEXCEPTION);
140
141                        /* make NaN quiet */
142                        Set_invalidflag();
143                        Sgl_set_quiet(opnd2);
144                }
145                /*
146                 * return quiet NaN
147                 */
148                *dstptr = opnd2;
149                return(NOEXCEPTION);
150	}
151	/*
152	 * Generate exponent 
153	 */
154	dest_exponent = Sgl_exponent(opnd1) + Sgl_exponent(opnd2) - SGL_BIAS;
155
156	/*
157	 * Generate mantissa
158	 */
159	if (Sgl_isnotzero_exponent(opnd1)) {
160		/* set hidden bit */
161		Sgl_clear_signexponent_set_hidden(opnd1);
162	}
163	else {
164		/* check for zero */
165		if (Sgl_iszero_mantissa(opnd1)) {
166			Sgl_setzero_exponentmantissa(result);
167			*dstptr = result;
168			return(NOEXCEPTION);
169		}
170                /* is denormalized, adjust exponent */
171                Sgl_clear_signexponent(opnd1);
172		Sgl_leftshiftby1(opnd1);
173		Sgl_normalize(opnd1,dest_exponent);
174	}
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);
178	}
179	else {
180		/* check for zero */
181		if (Sgl_iszero_mantissa(opnd2)) {
182			Sgl_setzero_exponentmantissa(result);
183			*dstptr = result;
184			return(NOEXCEPTION);
185		}
186                /* is denormalized; want to normalize */
187                Sgl_clear_signexponent(opnd2);
188                Sgl_leftshiftby1(opnd2);
189		Sgl_normalize(opnd2,dest_exponent);
190	}
191
192	/* Multiply two source mantissas together */
193
194	Sgl_leftshiftby4(opnd2);     /* make room for guard bits */
195	Sgl_setzero(opnd3);
196	/*
197	 * Four bits at a time are inspected in each loop, and a
198	 * simple shift and add multiply algorithm is used.
199	 */
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);
208	}
209	/* make sure result is left-justified */
210	if (Sgl_iszero_sign(opnd3)) {
211		Sgl_leftshiftby1(opnd3);
212	}
213	else {
214		/* result mantissa >= 2. */
215		dest_exponent++;
216	}
217	/* check for denormalized result */
218	while (Sgl_iszero_sign(opnd3)) {
219		Sgl_leftshiftby1(opnd3);
220		dest_exponent--;
221	}
222	/*
223	 * check for guard, sticky and inexact bits
224	 */
225	stickybit |= Sgl_all(opnd3) << (SGL_BITLENGTH - SGL_EXP_LENGTH + 1);
226	guardbit = Sbit24(opnd3);
227	inexact = guardbit | stickybit;
228
229	/* re-align mantissa */
230	Sgl_rightshiftby8(opnd3);
231
232	/* 
233	 * round result 
234	 */
235	if (inexact && (dest_exponent>0 || Is_underflowtrap_enabled())) {
236		Sgl_clear_signexponent(opnd3);
237		switch (Rounding_mode()) {
238			case ROUNDPLUS: 
239				if (Sgl_iszero_sign(result)) 
240					Sgl_increment(opnd3);
241				break;
242			case ROUNDMINUS: 
243				if (Sgl_isone_sign(result)) 
244					Sgl_increment(opnd3);
245				break;
246			case ROUNDNEAREST:
247				if (guardbit) {
248			   	if (stickybit || Sgl_isone_lowmantissa(opnd3))
249			      	Sgl_increment(opnd3);
250				}
251		}
252		if (Sgl_isone_hidden(opnd3)) dest_exponent++;
253	}
254	Sgl_set_mantissa(result,opnd3);
255
256        /* 
257         * Test for overflow
258         */
259	if (dest_exponent >= SGL_INFINITY_EXPONENT) {
260                /* trap if OVERFLOWTRAP enabled */
261                if (Is_overflowtrap_enabled()) {
262                        /*
263                         * Adjust bias of result
264                         */
265			Sgl_setwrapped_exponent(result,dest_exponent,ovfl);
266			*dstptr = result;
267			if (inexact) 
268			    if (Is_inexacttrap_enabled())
269				return(OVERFLOWEXCEPTION | INEXACTEXCEPTION);
270			    else Set_inexactflag();
271			return(OVERFLOWEXCEPTION);
272                }
273		inexact = TRUE;
274		Set_overflowflag();
275                /* set result to infinity or largest number */
276		Sgl_setoverflow(result);
277	}
278        /* 
279         * Test for underflow
280         */
281	else if (dest_exponent <= 0) {
282                /* trap if UNDERFLOWTRAP enabled */
283                if (Is_underflowtrap_enabled()) {
284                        /*
285                         * Adjust bias of result
286                         */
287			Sgl_setwrapped_exponent(result,dest_exponent,unfl);
288			*dstptr = result;
289			if (inexact) 
290			    if (Is_inexacttrap_enabled())
291				return(UNDERFLOWEXCEPTION | INEXACTEXCEPTION);
292			    else Set_inexactflag();
293			return(UNDERFLOWEXCEPTION);
294                }
295
296		/* Determine if should set underflow flag */
297		is_tiny = TRUE;
298		if (dest_exponent == 0 && inexact) {
299			switch (Rounding_mode()) {
300			case ROUNDPLUS: 
301				if (Sgl_iszero_sign(result)) {
302					Sgl_increment(opnd3);
303					if (Sgl_isone_hiddenoverflow(opnd3))
304                			    is_tiny = FALSE;
305					Sgl_decrement(opnd3);
306				}
307				break;
308			case ROUNDMINUS: 
309				if (Sgl_isone_sign(result)) {
310					Sgl_increment(opnd3);
311					if (Sgl_isone_hiddenoverflow(opnd3))
312                			    is_tiny = FALSE;
313					Sgl_decrement(opnd3);
314				}
315				break;
316			case ROUNDNEAREST:
317				if (guardbit && (stickybit || 
318				    Sgl_isone_lowmantissa(opnd3))) {
319				      	Sgl_increment(opnd3);
320					if (Sgl_isone_hiddenoverflow(opnd3))
321                			    is_tiny = FALSE;
322					Sgl_decrement(opnd3);
323				}
324				break;
325			}
326		}
327
328                /*
329                 * denormalize result or set to signed zero
330                 */
331		stickybit = inexact;
332		Sgl_denormalize(opnd3,dest_exponent,guardbit,stickybit,inexact);
333
334		/* return zero or smallest number */
335		if (inexact) {
336			switch (Rounding_mode()) {
337			case ROUNDPLUS: 
338				if (Sgl_iszero_sign(result)) {
339					Sgl_increment(opnd3);
340				}
341				break;
342			case ROUNDMINUS: 
343				if (Sgl_isone_sign(result)) {
344					Sgl_increment(opnd3);
345				}
346				break;
347			case ROUNDNEAREST:
348				if (guardbit && (stickybit || 
349				    Sgl_isone_lowmantissa(opnd3))) {
350			      		Sgl_increment(opnd3);
351				}
352				break;
353			}
354                if (is_tiny) Set_underflowflag();
355		}
356		Sgl_set_exponentmantissa(result,opnd3);
357	}
358	else Sgl_set_exponent(result,dest_exponent);
359	*dstptr = result;
360
361	/* check for inexact */
362	if (inexact) {
363		if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION);
364		else Set_inexactflag();
365	}
366	return(NOEXCEPTION);
367}
~/ Read-only file preview.