Merge tag 'reset-for-v5.3' of git://git.pengutronix.de/git/pza/linux into arm/drivers
[sfrench/cifs-2.6.git] / arch / parisc / math-emu / fcnvfu.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/fcnvfu.c              $Revision: 1.1 $
13  *
14  *  Purpose:
15  *      Floating-point to Unsigned Fixed-point Converts
16  *
17  *  External Interfaces:
18  *      dbl_to_dbl_fcnvfu(srcptr,nullptr,dstptr,status)
19  *      dbl_to_sgl_fcnvfu(srcptr,nullptr,dstptr,status)
20  *      sgl_to_dbl_fcnvfu(srcptr,nullptr,dstptr,status)
21  *      sgl_to_sgl_fcnvfu(srcptr,nullptr,dstptr,status)
22  *
23  *  Internal Interfaces:
24  *
25  *  Theory:
26  *      <<please update with a overview of the operation of this file>>
27  *
28  * END_DESC
29 */
30
31
32 #include "float.h"
33 #include "sgl_float.h"
34 #include "dbl_float.h"
35 #include "cnv_float.h"
36
37 /************************************************************************
38  *  Floating-point to Unsigned Fixed-point Converts                     *
39  ************************************************************************/
40
41 /*
42  *  Single Floating-point to Single Unsigned Fixed 
43  */
44 /*ARGSUSED*/
45 int
46 sgl_to_sgl_fcnvfu(
47                         sgl_floating_point *srcptr,
48                         unsigned int *nullptr,
49                         unsigned int *dstptr,
50                         unsigned int *status)
51 {
52         register unsigned int src, result;
53         register int src_exponent;
54         register boolean inexact = FALSE;
55
56         src = *srcptr;
57         src_exponent = Sgl_exponent(src) - SGL_BIAS;
58
59         /* 
60          * Test for overflow
61          */
62         if (src_exponent > SGL_FX_MAX_EXP + 1) {
63                 if (Sgl_isone_sign(src)) {
64                         result = 0;
65                 } else {
66                         result = 0xffffffff;
67                 }
68                 if (Is_invalidtrap_enabled()) {
69                         return(INVALIDEXCEPTION);
70                 }
71                 Set_invalidflag();
72                 *dstptr = result;
73                 return(NOEXCEPTION);
74         }
75         /*
76          * Generate result
77          */
78         if (src_exponent >= 0) {
79                 /* 
80                  * Check sign.
81                  * If negative, trap unimplemented.
82                  */
83                 if (Sgl_isone_sign(src)) {
84                         result = 0;
85                         if (Is_invalidtrap_enabled()) {
86                                 return(INVALIDEXCEPTION);
87                         }
88                         Set_invalidflag();
89                         *dstptr = result;
90                         return(NOEXCEPTION);
91                 }
92                 Sgl_clear_signexponent_set_hidden(src);
93                 Suint_from_sgl_mantissa(src,src_exponent,result);
94
95                 /* check for inexact */
96                 if (Sgl_isinexact_to_unsigned(src,src_exponent)) {
97                         inexact = TRUE;
98                         /*  round result  */
99                         switch (Rounding_mode()) {
100                         case ROUNDPLUS:
101                                 result++;
102                                 break;
103                         case ROUNDMINUS: /* never negative */
104                                 break;
105                         case ROUNDNEAREST:
106                                 if (Sgl_isone_roundbit(src,src_exponent) &&
107                                     (Sgl_isone_stickybit(src,src_exponent) ||
108                                      (result & 1))) {
109                                         result++;
110                                 }
111                                 break;
112                         }
113                 }
114         } else {
115                 result = 0;
116
117                 /* check for inexact */
118                 if (Sgl_isnotzero_exponentmantissa(src)) {
119                         inexact = TRUE;
120                         /*  round result  */
121                         switch (Rounding_mode()) {
122                         case ROUNDPLUS:
123                                 if (Sgl_iszero_sign(src)) {
124                                         result++;
125                                 }
126                                 break;
127                         case ROUNDMINUS:
128                                 if (Sgl_isone_sign(src)) {
129                                         result = 0;
130                                         if (Is_invalidtrap_enabled()) {
131                                                 return(INVALIDEXCEPTION);
132                                         }
133                                         Set_invalidflag();
134                                         inexact = FALSE;
135                                 }
136                                 break;
137                         case ROUNDNEAREST:
138                                 if (src_exponent == -1 &&
139                                     Sgl_isnotzero_mantissa(src)) {
140                                         if (Sgl_isone_sign(src)) {
141                                                 result = 0;
142                                                 if (Is_invalidtrap_enabled()) {
143                                                         return(INVALIDEXCEPTION);
144                                                 }
145                                                 Set_invalidflag();
146                                                 inexact = FALSE;
147                                         }
148                                         else result++;
149                                 }
150                                 break;
151                         }
152                 }
153         }
154         *dstptr = result;
155         if (inexact) {
156                 if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION);
157                 else Set_inexactflag();
158         }
159         return(NOEXCEPTION);
160 }
161
162 /*
163  *  Single Floating-point to Double Unsigned Fixed 
164  */
165 /*ARGSUSED*/
166 int
167 sgl_to_dbl_fcnvfu(
168                     sgl_floating_point *srcptr,
169                     unsigned int *nullptr,
170                     dbl_unsigned *dstptr,
171                     unsigned int *status)
172 {
173         register int src_exponent;
174         register unsigned int src, resultp1, resultp2;
175         register boolean inexact = FALSE;
176
177         src = *srcptr;
178         src_exponent = Sgl_exponent(src) - SGL_BIAS;
179
180         /* 
181          * Test for overflow
182          */
183         if (src_exponent > DBL_FX_MAX_EXP + 1) {
184                 if (Sgl_isone_sign(src)) {
185                         resultp1 = resultp2 = 0;
186                 } else {
187                         resultp1 = resultp2 = 0xffffffff;
188                 }
189                 if (Is_invalidtrap_enabled()) {
190                         return(INVALIDEXCEPTION);
191                 }
192                 Set_invalidflag();
193                 Duint_copytoptr(resultp1,resultp2,dstptr);
194                 return(NOEXCEPTION);
195         }
196         /*
197          * Generate result
198          */
199         if (src_exponent >= 0) {
200                 /* 
201                  * Check sign.
202                  * If negative, trap unimplemented.
203                  */
204                 if (Sgl_isone_sign(src)) {
205                         resultp1 = resultp2 = 0;
206                         if (Is_invalidtrap_enabled()) {
207                                 return(INVALIDEXCEPTION);
208                         }
209                         Set_invalidflag();
210                         Duint_copytoptr(resultp1,resultp2,dstptr);
211                         return(NOEXCEPTION);
212                 }
213                 Sgl_clear_signexponent_set_hidden(src);
214                 Duint_from_sgl_mantissa(src,src_exponent,resultp1,resultp2);
215
216                 /* check for inexact */
217                 if (Sgl_isinexact_to_unsigned(src,src_exponent)) {
218                         inexact = TRUE;
219                         /*  round result  */
220                         switch (Rounding_mode()) {
221                         case ROUNDPLUS:
222                                 Duint_increment(resultp1,resultp2);
223                                 break;
224                         case ROUNDMINUS: /* never negative */
225                                 break;
226                         case ROUNDNEAREST:
227                                 if (Sgl_isone_roundbit(src,src_exponent) &&
228                                     (Sgl_isone_stickybit(src,src_exponent) || 
229                                      Duint_isone_lowp2(resultp2))) {
230                                         Duint_increment(resultp1,resultp2);
231                                 }
232                                 break;
233                         }
234                 }
235         } else {
236                 Duint_setzero(resultp1,resultp2);
237
238                 /* check for inexact */
239                 if (Sgl_isnotzero_exponentmantissa(src)) {
240                         inexact = TRUE;
241                         /*  round result  */
242                         switch (Rounding_mode()) {
243                         case ROUNDPLUS:
244                                 if (Sgl_iszero_sign(src)) {
245                                         Duint_increment(resultp1,resultp2);
246                                 }
247                                 break;
248                         case ROUNDMINUS:
249                                 if (Sgl_isone_sign(src)) {
250                                         resultp1 = resultp2 = 0;
251                                         if (Is_invalidtrap_enabled()) {
252                                                 return(INVALIDEXCEPTION);
253                                         }
254                                         Set_invalidflag();
255                                         inexact = FALSE;
256                                 }
257                                 break;
258                         case ROUNDNEAREST:
259                                 if (src_exponent == -1 &&
260                                     Sgl_isnotzero_mantissa(src)) {
261                                         if (Sgl_isone_sign(src)) {
262                                                 resultp1 = 0;
263                                                 resultp2 = 0;
264                                                 if (Is_invalidtrap_enabled()) {
265                                                         return(INVALIDEXCEPTION);
266                                                 }
267                                                 Set_invalidflag();
268                                                 inexact = FALSE;
269                                         }
270                                         else Duint_increment(resultp1,resultp2);
271                                 }
272                         }
273                 }
274         }
275         Duint_copytoptr(resultp1,resultp2,dstptr);
276         if (inexact) {
277                 if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION);
278                 else Set_inexactflag();
279         }
280         return(NOEXCEPTION);
281 }
282
283 /*
284  *  Double Floating-point to Single Unsigned Fixed 
285  */
286 /*ARGSUSED*/
287 int
288 dbl_to_sgl_fcnvfu (dbl_floating_point * srcptr, unsigned int *nullptr,
289                    unsigned int *dstptr, unsigned int *status)
290 {
291         register unsigned int srcp1, srcp2, result;
292         register int src_exponent;
293         register boolean inexact = FALSE;
294
295         Dbl_copyfromptr(srcptr,srcp1,srcp2);
296         src_exponent = Dbl_exponent(srcp1) - DBL_BIAS;
297
298         /* 
299          * Test for overflow
300          */
301         if (src_exponent > SGL_FX_MAX_EXP + 1) {
302                 if (Dbl_isone_sign(srcp1)) {
303                         result = 0;
304                 } else {
305                         result = 0xffffffff;
306                 }
307                 if (Is_invalidtrap_enabled()) {
308                         return(INVALIDEXCEPTION);
309                 }
310                 Set_invalidflag();
311                 *dstptr = result;
312                 return(NOEXCEPTION);
313         }
314         /*
315          * Generate result
316          */
317         if (src_exponent >= 0) {
318                 /* 
319                  * Check sign.
320                  * If negative, trap unimplemented.
321                  */
322                 if (Dbl_isone_sign(srcp1)) {
323                         result = 0;
324                         if (Is_invalidtrap_enabled()) {
325                                 return(INVALIDEXCEPTION);
326                         }
327                         Set_invalidflag();
328                         *dstptr = result;
329                         return(NOEXCEPTION);
330                 }
331                 Dbl_clear_signexponent_set_hidden(srcp1);
332                 Suint_from_dbl_mantissa(srcp1,srcp2,src_exponent,result);
333
334                 /* check for inexact */
335                 if (Dbl_isinexact_to_unsigned(srcp1,srcp2,src_exponent)) {
336                         inexact = TRUE;
337                         /*  round result  */
338                         switch (Rounding_mode()) {
339                         case ROUNDPLUS:
340                              result++;
341                              break;
342                         case ROUNDMINUS: /* never negative */
343                              break;
344                         case ROUNDNEAREST:
345                              if(Dbl_isone_roundbit(srcp1,srcp2,src_exponent) &&
346                                 (Dbl_isone_stickybit(srcp1,srcp2,src_exponent)||
347                                  result&1))
348                                    result++;
349                              break;
350                         }
351                         /* check for overflow */
352                         if (result == 0) {
353                                 result = 0xffffffff;
354                                 if (Is_invalidtrap_enabled()) {
355                                         return(INVALIDEXCEPTION);
356                                 }
357                                 Set_invalidflag();
358                                 *dstptr = result;
359                                 return(NOEXCEPTION);
360                         }
361                 }
362         } else {
363                 result = 0;
364
365                 /* check for inexact */
366                 if (Dbl_isnotzero_exponentmantissa(srcp1,srcp2)) {
367                         inexact = TRUE;
368                         /*  round result  */
369                         switch (Rounding_mode()) {
370                         case ROUNDPLUS:
371                                 if (Dbl_iszero_sign(srcp1)) result++;
372                                 break;
373                         case ROUNDMINUS:
374                                 if (Dbl_isone_sign(srcp1)) {
375                                         result = 0;
376                                         if (Is_invalidtrap_enabled()) {
377                                                 return(INVALIDEXCEPTION);
378                                         }
379                                         Set_invalidflag();
380                                         inexact = FALSE;
381                                 }
382                                 break;
383                         case ROUNDNEAREST:
384                                 if (src_exponent == -1 &&
385                                     Dbl_isnotzero_mantissa(srcp1,srcp2))
386                                         if (Dbl_isone_sign(srcp1)) {
387                                                 result = 0;
388                                                 if (Is_invalidtrap_enabled()) {
389                                                         return(INVALIDEXCEPTION);
390                                                 }
391                                                 Set_invalidflag();
392                                                 inexact = FALSE;
393                                         }
394                                         else result++;
395                         }
396                 }
397         }
398         *dstptr = result;
399         if (inexact) {
400                 if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION);
401                 else Set_inexactflag();
402         }
403         return(NOEXCEPTION);
404 }
405
406 /*
407  *  Double Floating-point to Double Unsigned Fixed 
408  */
409 /*ARGSUSED*/
410 int
411 dbl_to_dbl_fcnvfu (dbl_floating_point * srcptr, unsigned int *nullptr,
412                    dbl_unsigned * dstptr, unsigned int *status)
413 {
414         register int src_exponent;
415         register unsigned int srcp1, srcp2, resultp1, resultp2;
416         register boolean inexact = FALSE;
417
418         Dbl_copyfromptr(srcptr,srcp1,srcp2);
419         src_exponent = Dbl_exponent(srcp1) - DBL_BIAS;
420
421         /* 
422          * Test for overflow
423          */
424         if (src_exponent > DBL_FX_MAX_EXP + 1) {
425                 if (Dbl_isone_sign(srcp1)) {
426                         resultp1 = resultp2 = 0;
427                 } else {
428                         resultp1 = resultp2 = 0xffffffff;
429                 }
430                 if (Is_invalidtrap_enabled()) {
431                         return(INVALIDEXCEPTION);
432                 }
433                 Set_invalidflag();
434                 Duint_copytoptr(resultp1,resultp2,dstptr);
435                 return(NOEXCEPTION);
436         }
437  
438         /*
439          * Generate result
440          */
441         if (src_exponent >= 0) {
442                 /* 
443                  * Check sign.
444                  * If negative, trap unimplemented.
445                  */
446                 if (Dbl_isone_sign(srcp1)) {
447                         resultp1 = resultp2 = 0;
448                         if (Is_invalidtrap_enabled()) {
449                                 return(INVALIDEXCEPTION);
450                         }
451                         Set_invalidflag();
452                         Duint_copytoptr(resultp1,resultp2,dstptr);
453                         return(NOEXCEPTION);
454                 }
455                 Dbl_clear_signexponent_set_hidden(srcp1);
456                 Duint_from_dbl_mantissa(srcp1,srcp2,src_exponent,resultp1,
457                   resultp2);
458
459                 /* check for inexact */
460                 if (Dbl_isinexact_to_unsigned(srcp1,srcp2,src_exponent)) {
461                         inexact = TRUE;
462                         /*  round result  */
463                         switch (Rounding_mode()) {
464                         case ROUNDPLUS:
465                                 Duint_increment(resultp1,resultp2);
466                                 break;
467                         case ROUNDMINUS: /* never negative */
468                                 break;
469                         case ROUNDNEAREST:
470                                 if(Dbl_isone_roundbit(srcp1,srcp2,src_exponent))
471                                   if(Dbl_isone_stickybit(srcp1,srcp2,src_exponent) || 
472                                      Duint_isone_lowp2(resultp2))
473                                         Duint_increment(resultp1,resultp2);
474                         } 
475                 }
476         } else {
477                 Duint_setzero(resultp1,resultp2);
478
479                 /* check for inexact */
480                 if (Dbl_isnotzero_exponentmantissa(srcp1,srcp2)) {
481                         inexact = TRUE;
482                         /*  round result  */
483                         switch (Rounding_mode()) {
484                         case ROUNDPLUS:
485                                 if (Dbl_iszero_sign(srcp1)) {
486                                         Duint_increment(resultp1,resultp2);
487                                 }
488                                 break;
489                         case ROUNDMINUS:
490                                 if (Dbl_isone_sign(srcp1)) {
491                                         resultp1 = resultp2 = 0;
492                                         if (Is_invalidtrap_enabled()) {
493                                                 return(INVALIDEXCEPTION);
494                                         }
495                                         Set_invalidflag();
496                                         inexact = FALSE;
497                                 }
498                                 break;
499                         case ROUNDNEAREST:
500                                 if (src_exponent == -1 &&
501                                     Dbl_isnotzero_mantissa(srcp1,srcp2))
502                                         if (Dbl_iszero_sign(srcp1)) {
503                                                 Duint_increment(resultp1,resultp2);
504                                         } else {
505                                                 resultp1 = 0;
506                                                 resultp2 = 0;
507                                                 if (Is_invalidtrap_enabled()) {
508                                                         return(INVALIDEXCEPTION);
509                                                 }
510                                                 Set_invalidflag();
511                                                 inexact = FALSE;
512                                         }
513                         }
514                 }
515         }
516         Duint_copytoptr(resultp1,resultp2,dstptr);
517         if (inexact) {
518                 if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION);
519                 else Set_inexactflag();
520         }
521         return(NOEXCEPTION);
522 }
523