~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/arch/parisc/math-emu/dfdiv.c

Version: ~ [ linux-6.11.5 ] ~ [ linux-6.10.14 ] ~ [ linux-6.9.12 ] ~ [ linux-6.8.12 ] ~ [ linux-6.7.12 ] ~ [ linux-6.6.58 ] ~ [ linux-6.5.13 ] ~ [ linux-6.4.16 ] ~ [ linux-6.3.13 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.114 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.169 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.228 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.284 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.322 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.336 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.337 ] ~ [ linux-4.4.302 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.9 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  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/dfdiv.c               $Revision: 1.1 $
 13  *
 14  *  Purpose:
 15  *      Double Precision Floating-point Divide
 16  *
 17  *  External Interfaces:
 18  *      dbl_fdiv(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 "dbl_float.h"
 31 
 32 /*
 33  *  Double Precision Floating-point Divide
 34  */
 35 
 36 int
 37 dbl_fdiv (dbl_floating_point * srcptr1, dbl_floating_point * srcptr2,
 38           dbl_floating_point * dstptr, unsigned int *status)
 39 {
 40         register unsigned int opnd1p1, opnd1p2, opnd2p1, opnd2p2;
 41         register unsigned int opnd3p1, opnd3p2, resultp1, resultp2;
 42         register int dest_exponent, count;
 43         register boolean inexact = FALSE, guardbit = FALSE, stickybit = FALSE;
 44         boolean is_tiny;
 45 
 46         Dbl_copyfromptr(srcptr1,opnd1p1,opnd1p2);
 47         Dbl_copyfromptr(srcptr2,opnd2p1,opnd2p2);
 48         /* 
 49          * set sign bit of result 
 50          */
 51         if (Dbl_sign(opnd1p1) ^ Dbl_sign(opnd2p1)) 
 52                 Dbl_setnegativezerop1(resultp1);  
 53         else Dbl_setzerop1(resultp1);
 54         /*
 55          * check first operand for NaN's or infinity
 56          */
 57         if (Dbl_isinfinity_exponent(opnd1p1)) {
 58                 if (Dbl_iszero_mantissa(opnd1p1,opnd1p2)) {
 59                         if (Dbl_isnotnan(opnd2p1,opnd2p2)) {
 60                                 if (Dbl_isinfinity(opnd2p1,opnd2p2)) {
 61                                         /* 
 62                                          * invalid since both operands 
 63                                          * are infinity 
 64                                          */
 65                                         if (Is_invalidtrap_enabled())
 66                                                 return(INVALIDEXCEPTION);
 67                                         Set_invalidflag();
 68                                         Dbl_makequietnan(resultp1,resultp2);
 69                                         Dbl_copytoptr(resultp1,resultp2,dstptr);
 70                                         return(NOEXCEPTION);
 71                                 }
 72                                 /*
 73                                  * return infinity
 74                                  */
 75                                 Dbl_setinfinity_exponentmantissa(resultp1,resultp2);
 76                                 Dbl_copytoptr(resultp1,resultp2,dstptr);
 77                                 return(NOEXCEPTION);
 78                         }
 79                 }
 80                 else {
 81                         /*
 82                          * is NaN; signaling or quiet?
 83                          */
 84                         if (Dbl_isone_signaling(opnd1p1)) {
 85                                 /* trap if INVALIDTRAP enabled */
 86                                 if (Is_invalidtrap_enabled())
 87                                         return(INVALIDEXCEPTION);
 88                                 /* make NaN quiet */
 89                                 Set_invalidflag();
 90                                 Dbl_set_quiet(opnd1p1);
 91                         }
 92                         /* 
 93                          * is second operand a signaling NaN? 
 94                          */
 95                         else if (Dbl_is_signalingnan(opnd2p1)) {
 96                                 /* trap if INVALIDTRAP enabled */
 97                                 if (Is_invalidtrap_enabled())
 98                                         return(INVALIDEXCEPTION);
 99                                 /* make NaN quiet */
100                                 Set_invalidflag();
101                                 Dbl_set_quiet(opnd2p1);
102                                 Dbl_copytoptr(opnd2p1,opnd2p2,dstptr);
103                                 return(NOEXCEPTION);
104                         }
105                         /*
106                          * return quiet NaN
107                          */
108                         Dbl_copytoptr(opnd1p1,opnd1p2,dstptr);
109                         return(NOEXCEPTION);
110                 }
111         }
112         /*
113          * check second operand for NaN's or infinity
114          */
115         if (Dbl_isinfinity_exponent(opnd2p1)) {
116                 if (Dbl_iszero_mantissa(opnd2p1,opnd2p2)) {
117                         /*
118                          * return zero
119                          */
120                         Dbl_setzero_exponentmantissa(resultp1,resultp2);
121                         Dbl_copytoptr(resultp1,resultp2,dstptr);
122                         return(NOEXCEPTION);
123                 }
124                 /*
125                  * is NaN; signaling or quiet?
126                  */
127                 if (Dbl_isone_signaling(opnd2p1)) {
128                         /* trap if INVALIDTRAP enabled */
129                         if (Is_invalidtrap_enabled()) return(INVALIDEXCEPTION);
130                         /* make NaN quiet */
131                         Set_invalidflag();
132                         Dbl_set_quiet(opnd2p1);
133                 }
134                 /*
135                  * return quiet NaN
136                  */
137                 Dbl_copytoptr(opnd2p1,opnd2p2,dstptr);
138                 return(NOEXCEPTION);
139         }
140         /*
141          * check for division by zero
142          */
143         if (Dbl_iszero_exponentmantissa(opnd2p1,opnd2p2)) {
144                 if (Dbl_iszero_exponentmantissa(opnd1p1,opnd1p2)) {
145                         /* invalid since both operands are zero */
146                         if (Is_invalidtrap_enabled()) return(INVALIDEXCEPTION);
147                         Set_invalidflag();
148                         Dbl_makequietnan(resultp1,resultp2);
149                         Dbl_copytoptr(resultp1,resultp2,dstptr);
150                         return(NOEXCEPTION);
151                 }
152                 if (Is_divisionbyzerotrap_enabled())
153                         return(DIVISIONBYZEROEXCEPTION);
154                 Set_divisionbyzeroflag();
155                 Dbl_setinfinity_exponentmantissa(resultp1,resultp2);
156                 Dbl_copytoptr(resultp1,resultp2,dstptr);
157                 return(NOEXCEPTION);
158         }
159         /*
160          * Generate exponent 
161          */
162         dest_exponent = Dbl_exponent(opnd1p1) - Dbl_exponent(opnd2p1) + DBL_BIAS;
163 
164         /*
165          * Generate mantissa
166          */
167         if (Dbl_isnotzero_exponent(opnd1p1)) {
168                 /* set hidden bit */
169                 Dbl_clear_signexponent_set_hidden(opnd1p1);
170         }
171         else {
172                 /* check for zero */
173                 if (Dbl_iszero_mantissa(opnd1p1,opnd1p2)) {
174                         Dbl_setzero_exponentmantissa(resultp1,resultp2);
175                         Dbl_copytoptr(resultp1,resultp2,dstptr);
176                         return(NOEXCEPTION);
177                 }
178                 /* is denormalized, want to normalize */
179                 Dbl_clear_signexponent(opnd1p1);
180                 Dbl_leftshiftby1(opnd1p1,opnd1p2);
181                 Dbl_normalize(opnd1p1,opnd1p2,dest_exponent);
182         }
183         /* opnd2 needs to have hidden bit set with msb in hidden bit */
184         if (Dbl_isnotzero_exponent(opnd2p1)) {
185                 Dbl_clear_signexponent_set_hidden(opnd2p1);
186         }
187         else {
188                 /* is denormalized; want to normalize */
189                 Dbl_clear_signexponent(opnd2p1);
190                 Dbl_leftshiftby1(opnd2p1,opnd2p2);
191                 while (Dbl_iszero_hiddenhigh7mantissa(opnd2p1)) {
192                         dest_exponent+=8;
193                         Dbl_leftshiftby8(opnd2p1,opnd2p2);
194                 }
195                 if (Dbl_iszero_hiddenhigh3mantissa(opnd2p1)) {
196                         dest_exponent+=4;
197                         Dbl_leftshiftby4(opnd2p1,opnd2p2);
198                 }
199                 while (Dbl_iszero_hidden(opnd2p1)) {
200                         dest_exponent++;
201                         Dbl_leftshiftby1(opnd2p1,opnd2p2);
202                 }
203         }
204 
205         /* Divide the source mantissas */
206 
207         /* 
208          * A non-restoring divide algorithm is used.
209          */
210         Twoword_subtract(opnd1p1,opnd1p2,opnd2p1,opnd2p2);
211         Dbl_setzero(opnd3p1,opnd3p2);
212         for (count=1; count <= DBL_P && (opnd1p1 || opnd1p2); count++) {
213                 Dbl_leftshiftby1(opnd1p1,opnd1p2);
214                 Dbl_leftshiftby1(opnd3p1,opnd3p2);
215                 if (Dbl_iszero_sign(opnd1p1)) {
216                         Dbl_setone_lowmantissap2(opnd3p2);
217                         Twoword_subtract(opnd1p1,opnd1p2,opnd2p1,opnd2p2);
218                 }
219                 else {
220                         Twoword_add(opnd1p1, opnd1p2, opnd2p1, opnd2p2);
221                 }
222         }
223         if (count <= DBL_P) {
224                 Dbl_leftshiftby1(opnd3p1,opnd3p2);
225                 Dbl_setone_lowmantissap2(opnd3p2);
226                 Dbl_leftshift(opnd3p1,opnd3p2,(DBL_P-count));
227                 if (Dbl_iszero_hidden(opnd3p1)) {
228                         Dbl_leftshiftby1(opnd3p1,opnd3p2);
229                         dest_exponent--;
230                 }
231         }
232         else {
233                 if (Dbl_iszero_hidden(opnd3p1)) {
234                         /* need to get one more bit of result */
235                         Dbl_leftshiftby1(opnd1p1,opnd1p2);
236                         Dbl_leftshiftby1(opnd3p1,opnd3p2);
237                         if (Dbl_iszero_sign(opnd1p1)) {
238                                 Dbl_setone_lowmantissap2(opnd3p2);
239                                 Twoword_subtract(opnd1p1,opnd1p2,opnd2p1,opnd2p2);
240                         }
241                         else {
242                                 Twoword_add(opnd1p1,opnd1p2,opnd2p1,opnd2p2);
243                         }
244                         dest_exponent--;
245                 }
246                 if (Dbl_iszero_sign(opnd1p1)) guardbit = TRUE;
247                 stickybit = Dbl_allp1(opnd1p1) || Dbl_allp2(opnd1p2);
248         }
249         inexact = guardbit | stickybit;
250 
251         /* 
252          * round result 
253          */
254         if (inexact && (dest_exponent > 0 || Is_underflowtrap_enabled())) {
255                 Dbl_clear_signexponent(opnd3p1);
256                 switch (Rounding_mode()) {
257                         case ROUNDPLUS: 
258                                 if (Dbl_iszero_sign(resultp1)) 
259                                         Dbl_increment(opnd3p1,opnd3p2);
260                                 break;
261                         case ROUNDMINUS: 
262                                 if (Dbl_isone_sign(resultp1)) 
263                                         Dbl_increment(opnd3p1,opnd3p2);
264                                 break;
265                         case ROUNDNEAREST:
266                                 if (guardbit && (stickybit || 
267                                     Dbl_isone_lowmantissap2(opnd3p2))) {
268                                         Dbl_increment(opnd3p1,opnd3p2);
269                                 }
270                 }
271                 if (Dbl_isone_hidden(opnd3p1)) dest_exponent++;
272         }
273         Dbl_set_mantissa(resultp1,resultp2,opnd3p1,opnd3p2);
274 
275         /* 
276          * Test for overflow
277          */
278         if (dest_exponent >= DBL_INFINITY_EXPONENT) {
279                 /* trap if OVERFLOWTRAP enabled */
280                 if (Is_overflowtrap_enabled()) {
281                         /*
282                          * Adjust bias of result
283                          */
284                         Dbl_setwrapped_exponent(resultp1,dest_exponent,ovfl);
285                         Dbl_copytoptr(resultp1,resultp2,dstptr);
286                         if (inexact) 
287                             if (Is_inexacttrap_enabled())
288                                 return(OVERFLOWEXCEPTION | INEXACTEXCEPTION);
289                             else Set_inexactflag();
290                         return(OVERFLOWEXCEPTION);
291                 }
292                 Set_overflowflag();
293                 /* set result to infinity or largest number */
294                 Dbl_setoverflow(resultp1,resultp2);
295                 inexact = TRUE;
296         }
297         /* 
298          * Test for underflow
299          */
300         else if (dest_exponent <= 0) {
301                 /* trap if UNDERFLOWTRAP enabled */
302                 if (Is_underflowtrap_enabled()) {
303                         /*
304                          * Adjust bias of result
305                          */
306                         Dbl_setwrapped_exponent(resultp1,dest_exponent,unfl);
307                         Dbl_copytoptr(resultp1,resultp2,dstptr);
308                         if (inexact) 
309                             if (Is_inexacttrap_enabled())
310                                 return(UNDERFLOWEXCEPTION | INEXACTEXCEPTION);
311                             else Set_inexactflag();
312                         return(UNDERFLOWEXCEPTION);
313                 }
314 
315                 /* Determine if should set underflow flag */
316                 is_tiny = TRUE;
317                 if (dest_exponent == 0 && inexact) {
318                         switch (Rounding_mode()) {
319                         case ROUNDPLUS: 
320                                 if (Dbl_iszero_sign(resultp1)) {
321                                         Dbl_increment(opnd3p1,opnd3p2);
322                                         if (Dbl_isone_hiddenoverflow(opnd3p1))
323                                             is_tiny = FALSE;
324                                         Dbl_decrement(opnd3p1,opnd3p2);
325                                 }
326                                 break;
327                         case ROUNDMINUS: 
328                                 if (Dbl_isone_sign(resultp1)) {
329                                         Dbl_increment(opnd3p1,opnd3p2);
330                                         if (Dbl_isone_hiddenoverflow(opnd3p1))
331                                             is_tiny = FALSE;
332                                         Dbl_decrement(opnd3p1,opnd3p2);
333                                 }
334                                 break;
335                         case ROUNDNEAREST:
336                                 if (guardbit && (stickybit || 
337                                     Dbl_isone_lowmantissap2(opnd3p2))) {
338                                         Dbl_increment(opnd3p1,opnd3p2);
339                                         if (Dbl_isone_hiddenoverflow(opnd3p1))
340                                             is_tiny = FALSE;
341                                         Dbl_decrement(opnd3p1,opnd3p2);
342                                 }
343                                 break;
344                         }
345                 }
346 
347                 /*
348                  * denormalize result or set to signed zero
349                  */
350                 stickybit = inexact;
351                 Dbl_denormalize(opnd3p1,opnd3p2,dest_exponent,guardbit,
352                  stickybit,inexact);
353 
354                 /* return rounded number */ 
355                 if (inexact) {
356                         switch (Rounding_mode()) {
357                         case ROUNDPLUS:
358                                 if (Dbl_iszero_sign(resultp1)) {
359                                         Dbl_increment(opnd3p1,opnd3p2);
360                                 }
361                                 break;
362                         case ROUNDMINUS: 
363                                 if (Dbl_isone_sign(resultp1)) {
364                                         Dbl_increment(opnd3p1,opnd3p2);
365                                 }
366                                 break;
367                         case ROUNDNEAREST:
368                                 if (guardbit && (stickybit || 
369                                     Dbl_isone_lowmantissap2(opnd3p2))) {
370                                         Dbl_increment(opnd3p1,opnd3p2);
371                                 }
372                                 break;
373                         }
374                         if (is_tiny) Set_underflowflag();
375                 }
376                 Dbl_set_exponentmantissa(resultp1,resultp2,opnd3p1,opnd3p2);
377         }
378         else Dbl_set_exponent(resultp1,dest_exponent);
379         Dbl_copytoptr(resultp1,resultp2,dstptr);
380 
381         /* check for inexact */
382         if (inexact) {
383                 if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION);
384                 else Set_inexactflag();
385         }
386         return(NOEXCEPTION);
387 }
388 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

sflogo.php