Linux-libre 5.7.5-gnu
[librecmc/linux-libre.git] / arch / parisc / math-emu / sfmpy.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
36 int
37 sgl_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 }