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
sgl_to_sgl_fcnvxf(int * srcptr,unsigned int * nullptr,sgl_floating_point * dstptr,unsigned int * status)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
sgl_to_dbl_fcnvxf(int * srcptr,unsigned int * nullptr,dbl_floating_point * dstptr,unsigned int * status)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
dbl_to_sgl_fcnvxf(dbl_integer * srcptr,unsigned int * nullptr,sgl_floating_point * dstptr,unsigned int * status)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
dbl_to_dbl_fcnvxf(dbl_integer * srcptr,unsigned int * nullptr,dbl_floating_point * dstptr,unsigned int * status)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 }
374