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 | } |
374 | |