Linux-libre 5.3.12-gnu
[librecmc/linux-libre.git] / arch / parisc / math-emu / fcnvxf.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/fcnvxf.c              $Revision: 1.1 $
13  *
14  *  Purpose:
15  *      Single Fixed-point to Single Floating-point
16  *      Single Fixed-point to Double Floating-point 
17  *      Double Fixed-point to Single Floating-point 
18  *      Double Fixed-point to Double Floating-point 
19  *
20  *  External Interfaces:
21  *      dbl_to_dbl_fcnvxf(srcptr,nullptr,dstptr,status)
22  *      dbl_to_sgl_fcnvxf(srcptr,nullptr,dstptr,status)
23  *      sgl_to_dbl_fcnvxf(srcptr,nullptr,dstptr,status)
24  *      sgl_to_sgl_fcnvxf(srcptr,nullptr,dstptr,status)
25  *
26  *  Internal Interfaces:
27  *
28  *  Theory:
29  *      <<please update with a overview of the operation of this file>>
30  *
31  * END_DESC
32 */
33
34
35 #include "float.h"
36 #include "sgl_float.h"
37 #include "dbl_float.h"
38 #include "cnv_float.h"
39
40 /*
41  *  Convert single fixed-point to single floating-point format
42  */
43
44 int
45 sgl_to_sgl_fcnvxf(
46                     int *srcptr,
47                     unsigned int *nullptr,
48                     sgl_floating_point *dstptr,
49                     unsigned int *status)
50 {
51         register int src, dst_exponent;
52         register unsigned int result = 0;
53
54         src = *srcptr;
55         /* 
56          * set sign bit of result and get magnitude of source 
57          */
58         if (src < 0) {
59                 Sgl_setone_sign(result);  
60                 Int_negate(src);
61         }
62         else {
63                 Sgl_setzero_sign(result);
64                 /* Check for zero */ 
65                 if (src == 0) { 
66                         Sgl_setzero(result); 
67                         *dstptr = result;
68                         return(NOEXCEPTION); 
69                 } 
70         }
71         /*
72          * Generate exponent and normalized mantissa
73          */
74         dst_exponent = 16;    /* initialize for normalization */
75         /*
76          * Check word for most significant bit set.  Returns
77          * a value in dst_exponent indicating the bit position,
78          * between -1 and 30.
79          */
80         Find_ms_one_bit(src,dst_exponent);
81         /*  left justify source, with msb at bit position 1  */
82         if (dst_exponent >= 0) src <<= dst_exponent;
83         else src = 1 << 30;
84         Sgl_set_mantissa(result, src >> (SGL_EXP_LENGTH-1));
85         Sgl_set_exponent(result, 30+SGL_BIAS - dst_exponent);
86
87         /* check for inexact */
88         if (Int_isinexact_to_sgl(src)) {
89                 switch (Rounding_mode()) {
90                         case ROUNDPLUS: 
91                                 if (Sgl_iszero_sign(result)) 
92                                         Sgl_increment(result);
93                                 break;
94                         case ROUNDMINUS: 
95                                 if (Sgl_isone_sign(result)) 
96                                         Sgl_increment(result);
97                                 break;
98                         case ROUNDNEAREST:
99                                 Sgl_roundnearest_from_int(src,result);
100                 }
101                 if (Is_inexacttrap_enabled()) {
102                         *dstptr = result;
103                         return(INEXACTEXCEPTION);
104                 }
105                 else Set_inexactflag();
106         }
107         *dstptr = result;
108         return(NOEXCEPTION);
109 }
110
111 /*
112  *  Single Fixed-point to Double Floating-point 
113  */
114
115 int
116 sgl_to_dbl_fcnvxf(
117                     int *srcptr,
118                     unsigned int *nullptr,
119                     dbl_floating_point *dstptr,
120                     unsigned int *status)
121 {
122         register int src, dst_exponent;
123         register unsigned int resultp1 = 0, resultp2 = 0;
124
125         src = *srcptr;
126         /* 
127          * set sign bit of result and get magnitude of source 
128          */
129         if (src < 0) {
130                 Dbl_setone_sign(resultp1);  
131                 Int_negate(src);
132         }
133         else {
134                 Dbl_setzero_sign(resultp1);
135                 /* Check for zero */
136                 if (src == 0) {
137                         Dbl_setzero(resultp1,resultp2);
138                         Dbl_copytoptr(resultp1,resultp2,dstptr);
139                         return(NOEXCEPTION);
140                 }
141         }
142         /*
143          * Generate exponent and normalized mantissa
144          */
145         dst_exponent = 16;    /* initialize for normalization */
146         /*
147          * Check word for most significant bit set.  Returns
148          * a value in dst_exponent indicating the bit position,
149          * between -1 and 30.
150          */
151         Find_ms_one_bit(src,dst_exponent);
152         /*  left justify source, with msb at bit position 1  */
153         if (dst_exponent >= 0) src <<= dst_exponent;
154         else src = 1 << 30;
155         Dbl_set_mantissap1(resultp1, src >> DBL_EXP_LENGTH - 1);
156         Dbl_set_mantissap2(resultp2, src << (33-DBL_EXP_LENGTH));
157         Dbl_set_exponent(resultp1, (30+DBL_BIAS) - dst_exponent);
158         Dbl_copytoptr(resultp1,resultp2,dstptr);
159         return(NOEXCEPTION);
160 }
161
162 /*
163  *  Double Fixed-point to Single Floating-point 
164  */
165
166 int
167 dbl_to_sgl_fcnvxf(
168                         dbl_integer *srcptr,
169                         unsigned int *nullptr,
170                         sgl_floating_point *dstptr,
171                         unsigned int *status)
172 {
173         int dst_exponent, srcp1;
174         unsigned int result = 0, srcp2;
175
176         Dint_copyfromptr(srcptr,srcp1,srcp2);
177         /* 
178          * set sign bit of result and get magnitude of source 
179          */
180         if (srcp1 < 0) {
181                 Sgl_setone_sign(result);  
182                 Dint_negate(srcp1,srcp2);
183         }
184         else {
185                 Sgl_setzero_sign(result);
186                 /* Check for zero */
187                 if (srcp1 == 0 && srcp2 == 0) {
188                         Sgl_setzero(result);
189                         *dstptr = result;
190                         return(NOEXCEPTION);
191                 }
192         }
193         /*
194          * Generate exponent and normalized mantissa
195          */
196         dst_exponent = 16;    /* initialize for normalization */
197         if (srcp1 == 0) {
198                 /*
199                  * Check word for most significant bit set.  Returns
200                  * a value in dst_exponent indicating the bit position,
201                  * between -1 and 30.
202                  */
203                 Find_ms_one_bit(srcp2,dst_exponent);
204                 /*  left justify source, with msb at bit position 1  */
205                 if (dst_exponent >= 0) {
206                         srcp1 = srcp2 << dst_exponent;    
207                         srcp2 = 0;
208                 }
209                 else {
210                         srcp1 = srcp2 >> 1;
211                         srcp2 <<= 31; 
212                 }
213                 /*
214                  *  since msb set is in second word, need to 
215                  *  adjust bit position count
216                  */
217                 dst_exponent += 32;
218         }
219         else {
220                 /*
221                  * Check word for most significant bit set.  Returns
222                  * a value in dst_exponent indicating the bit position,
223                  * between -1 and 30.
224                  *
225                  */
226                 Find_ms_one_bit(srcp1,dst_exponent);
227                 /*  left justify source, with msb at bit position 1  */
228                 if (dst_exponent > 0) {
229                         Variable_shift_double(srcp1,srcp2,(32-dst_exponent),
230                          srcp1); 
231                         srcp2 <<= dst_exponent;
232                 }
233                 /*
234                  * If dst_exponent = 0, we don't need to shift anything.
235                  * If dst_exponent = -1, src = - 2**63 so we won't need to 
236                  * shift srcp2.
237                  */
238                 else srcp1 >>= -(dst_exponent);
239         }
240         Sgl_set_mantissa(result, srcp1 >> SGL_EXP_LENGTH - 1);
241         Sgl_set_exponent(result, (62+SGL_BIAS) - dst_exponent);
242
243         /* check for inexact */
244         if (Dint_isinexact_to_sgl(srcp1,srcp2)) {
245                 switch (Rounding_mode()) {
246                         case ROUNDPLUS: 
247                                 if (Sgl_iszero_sign(result)) 
248                                         Sgl_increment(result);
249                                 break;
250                         case ROUNDMINUS: 
251                                 if (Sgl_isone_sign(result)) 
252                                         Sgl_increment(result);
253                                 break;
254                         case ROUNDNEAREST:
255                                 Sgl_roundnearest_from_dint(srcp1,srcp2,result);
256                 }
257                 if (Is_inexacttrap_enabled()) {
258                         *dstptr = result;
259                         return(INEXACTEXCEPTION);
260                 }
261                 else Set_inexactflag();
262         }
263         *dstptr = result;
264         return(NOEXCEPTION);
265 }
266
267 /*
268  *  Double Fixed-point to Double Floating-point 
269  */
270
271 int
272 dbl_to_dbl_fcnvxf(
273                     dbl_integer *srcptr,
274                     unsigned int *nullptr,
275                     dbl_floating_point *dstptr,
276                     unsigned int *status)
277 {
278         register int srcp1, dst_exponent;
279         register unsigned int srcp2, resultp1 = 0, resultp2 = 0;
280
281         Dint_copyfromptr(srcptr,srcp1,srcp2);
282         /* 
283          * set sign bit of result and get magnitude of source 
284          */
285         if (srcp1 < 0) {
286                 Dbl_setone_sign(resultp1);
287                 Dint_negate(srcp1,srcp2);
288         }
289         else {
290                 Dbl_setzero_sign(resultp1);
291                 /* Check for zero */
292                 if (srcp1 == 0 && srcp2 ==0) {
293                         Dbl_setzero(resultp1,resultp2);
294                         Dbl_copytoptr(resultp1,resultp2,dstptr);
295                         return(NOEXCEPTION);
296                 }
297         }
298         /*
299          * Generate exponent and normalized mantissa
300          */
301         dst_exponent = 16;    /* initialize for normalization */
302         if (srcp1 == 0) {
303                 /*
304                  * Check word for most significant bit set.  Returns
305                  * a value in dst_exponent indicating the bit position,
306                  * between -1 and 30.
307                  */
308                 Find_ms_one_bit(srcp2,dst_exponent);
309                 /*  left justify source, with msb at bit position 1  */
310                 if (dst_exponent >= 0) {
311                         srcp1 = srcp2 << dst_exponent;    
312                         srcp2 = 0;
313                 }
314                 else {
315                         srcp1 = srcp2 >> 1;
316                         srcp2 <<= 31;
317                 }
318                 /*
319                  *  since msb set is in second word, need to 
320                  *  adjust bit position count
321                  */
322                 dst_exponent += 32;
323         }
324         else {
325                 /*
326                  * Check word for most significant bit set.  Returns
327                  * a value in dst_exponent indicating the bit position,
328                  * between -1 and 30.
329                  */
330                 Find_ms_one_bit(srcp1,dst_exponent);
331                 /*  left justify source, with msb at bit position 1  */
332                 if (dst_exponent > 0) {
333                         Variable_shift_double(srcp1,srcp2,(32-dst_exponent),
334                          srcp1); 
335                         srcp2 <<= dst_exponent;
336                 }
337                 /*
338                  * If dst_exponent = 0, we don't need to shift anything.
339                  * If dst_exponent = -1, src = - 2**63 so we won't need to 
340                  * shift srcp2.
341                  */
342                 else srcp1 >>= -(dst_exponent);
343         }
344         Dbl_set_mantissap1(resultp1, srcp1 >> (DBL_EXP_LENGTH-1));
345         Shiftdouble(srcp1,srcp2,DBL_EXP_LENGTH-1,resultp2);
346         Dbl_set_exponent(resultp1, (62+DBL_BIAS) - dst_exponent);
347
348         /* check for inexact */
349         if (Dint_isinexact_to_dbl(srcp2)) {
350                 switch (Rounding_mode()) {
351                         case ROUNDPLUS: 
352                                 if (Dbl_iszero_sign(resultp1)) {
353                                         Dbl_increment(resultp1,resultp2);
354                                 }
355                                 break;
356                         case ROUNDMINUS: 
357                                 if (Dbl_isone_sign(resultp1)) {
358                                         Dbl_increment(resultp1,resultp2);
359                                 }
360                                 break;
361                         case ROUNDNEAREST:
362                                 Dbl_roundnearest_from_dint(srcp2,resultp1,
363                                 resultp2);
364                 }
365                 if (Is_inexacttrap_enabled()) {
366                         Dbl_copytoptr(resultp1,resultp2,dstptr);
367                         return(INEXACTEXCEPTION);
368                 }
369                 else Set_inexactflag();
370         }
371         Dbl_copytoptr(resultp1,resultp2,dstptr);
372         return(NOEXCEPTION);
373 }