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/fcnvuf.c $Revision: 1.1 $ |
13 | * |
14 | * Purpose: |
15 | * Fixed point to Floating-point Converts |
16 | * |
17 | * External Interfaces: |
18 | * dbl_to_dbl_fcnvuf(srcptr,_nullptr,dstptr,status) |
19 | * dbl_to_sgl_fcnvuf(srcptr,_nullptr,dstptr,status) |
20 | * sgl_to_dbl_fcnvuf(srcptr,_nullptr,dstptr,status) |
21 | * sgl_to_sgl_fcnvuf(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 | * Fixed point to Floating-point Converts * |
39 | ************************************************************************/ |
40 | |
41 | /* |
42 | * Convert Single Unsigned Fixed to Single Floating-point format |
43 | */ |
44 | |
45 | int |
46 | sgl_to_sgl_fcnvuf( |
47 | unsigned int *srcptr, |
48 | unsigned int *_nullptr, |
49 | sgl_floating_point *dstptr, |
50 | unsigned int *status) |
51 | { |
52 | register unsigned int src, result = 0; |
53 | register int dst_exponent; |
54 | |
55 | src = *srcptr; |
56 | |
57 | /* Check for zero */ |
58 | if (src == 0) { |
59 | Sgl_setzero(result); |
60 | *dstptr = result; |
61 | return(NOEXCEPTION); |
62 | } |
63 | /* |
64 | * Generate exponent and normalized mantissa |
65 | */ |
66 | dst_exponent = 16; /* initialize for normalization */ |
67 | /* |
68 | * Check word for most significant bit set. Returns |
69 | * a value in dst_exponent indicating the bit position, |
70 | * between -1 and 30. |
71 | */ |
72 | Find_ms_one_bit(src,dst_exponent); |
73 | /* left justify source, with msb at bit position 0 */ |
74 | src <<= dst_exponent+1; |
75 | Sgl_set_mantissa(result, src >> SGL_EXP_LENGTH); |
76 | Sgl_set_exponent(result, 30+SGL_BIAS - dst_exponent); |
77 | |
78 | /* check for inexact */ |
79 | if (Suint_isinexact_to_sgl(src)) { |
80 | switch (Rounding_mode()) { |
81 | case ROUNDPLUS: |
82 | Sgl_increment(result); |
83 | break; |
84 | case ROUNDMINUS: /* never negative */ |
85 | break; |
86 | case ROUNDNEAREST: |
87 | Sgl_roundnearest_from_suint(src,result); |
88 | break; |
89 | } |
90 | if (Is_inexacttrap_enabled()) { |
91 | *dstptr = result; |
92 | return(INEXACTEXCEPTION); |
93 | } |
94 | else Set_inexactflag(); |
95 | } |
96 | *dstptr = result; |
97 | return(NOEXCEPTION); |
98 | } |
99 | |
100 | /* |
101 | * Single Unsigned Fixed to Double Floating-point |
102 | */ |
103 | |
104 | int |
105 | sgl_to_dbl_fcnvuf( |
106 | unsigned int *srcptr, |
107 | unsigned int *_nullptr, |
108 | dbl_floating_point *dstptr, |
109 | unsigned int *status) |
110 | { |
111 | register int dst_exponent; |
112 | register unsigned int src, resultp1 = 0, resultp2 = 0; |
113 | |
114 | src = *srcptr; |
115 | |
116 | /* Check for zero */ |
117 | if (src == 0) { |
118 | Dbl_setzero(resultp1,resultp2); |
119 | Dbl_copytoptr(resultp1,resultp2,dstptr); |
120 | return(NOEXCEPTION); |
121 | } |
122 | /* |
123 | * Generate exponent and normalized mantissa |
124 | */ |
125 | dst_exponent = 16; /* initialize for normalization */ |
126 | /* |
127 | * Check word for most significant bit set. Returns |
128 | * a value in dst_exponent indicating the bit position, |
129 | * between -1 and 30. |
130 | */ |
131 | Find_ms_one_bit(src,dst_exponent); |
132 | /* left justify source, with msb at bit position 0 */ |
133 | src <<= dst_exponent+1; |
134 | Dbl_set_mantissap1(resultp1, src >> DBL_EXP_LENGTH); |
135 | Dbl_set_mantissap2(resultp2, src << (32-DBL_EXP_LENGTH)); |
136 | Dbl_set_exponent(resultp1, (30+DBL_BIAS) - dst_exponent); |
137 | Dbl_copytoptr(resultp1,resultp2,dstptr); |
138 | return(NOEXCEPTION); |
139 | } |
140 | |
141 | /* |
142 | * Double Unsigned Fixed to Single Floating-point |
143 | */ |
144 | |
145 | int |
146 | dbl_to_sgl_fcnvuf( |
147 | dbl_unsigned *srcptr, |
148 | unsigned int *_nullptr, |
149 | sgl_floating_point *dstptr, |
150 | unsigned int *status) |
151 | { |
152 | int dst_exponent; |
153 | unsigned int srcp1, srcp2, result = 0; |
154 | |
155 | Duint_copyfromptr(srcptr,srcp1,srcp2); |
156 | |
157 | /* Check for zero */ |
158 | if (srcp1 == 0 && srcp2 == 0) { |
159 | Sgl_setzero(result); |
160 | *dstptr = result; |
161 | return(NOEXCEPTION); |
162 | } |
163 | /* |
164 | * Generate exponent and normalized mantissa |
165 | */ |
166 | dst_exponent = 16; /* initialize for normalization */ |
167 | if (srcp1 == 0) { |
168 | /* |
169 | * Check word for most significant bit set. Returns |
170 | * a value in dst_exponent indicating the bit position, |
171 | * between -1 and 30. |
172 | */ |
173 | Find_ms_one_bit(srcp2,dst_exponent); |
174 | /* left justify source, with msb at bit position 0 */ |
175 | srcp1 = srcp2 << dst_exponent+1; |
176 | srcp2 = 0; |
177 | /* |
178 | * since msb set is in second word, need to |
179 | * adjust bit position count |
180 | */ |
181 | dst_exponent += 32; |
182 | } |
183 | else { |
184 | /* |
185 | * Check word for most significant bit set. Returns |
186 | * a value in dst_exponent indicating the bit position, |
187 | * between -1 and 30. |
188 | * |
189 | */ |
190 | Find_ms_one_bit(srcp1,dst_exponent); |
191 | /* left justify source, with msb at bit position 0 */ |
192 | if (dst_exponent >= 0) { |
193 | Variable_shift_double(srcp1,srcp2,(31-dst_exponent), |
194 | srcp1); |
195 | srcp2 <<= dst_exponent+1; |
196 | } |
197 | } |
198 | Sgl_set_mantissa(result, srcp1 >> SGL_EXP_LENGTH); |
199 | Sgl_set_exponent(result, (62+SGL_BIAS) - dst_exponent); |
200 | |
201 | /* check for inexact */ |
202 | if (Duint_isinexact_to_sgl(srcp1,srcp2)) { |
203 | switch (Rounding_mode()) { |
204 | case ROUNDPLUS: |
205 | Sgl_increment(result); |
206 | break; |
207 | case ROUNDMINUS: /* never negative */ |
208 | break; |
209 | case ROUNDNEAREST: |
210 | Sgl_roundnearest_from_duint(srcp1,srcp2,result); |
211 | break; |
212 | } |
213 | if (Is_inexacttrap_enabled()) { |
214 | *dstptr = result; |
215 | return(INEXACTEXCEPTION); |
216 | } |
217 | else Set_inexactflag(); |
218 | } |
219 | *dstptr = result; |
220 | return(NOEXCEPTION); |
221 | } |
222 | |
223 | /* |
224 | * Double Unsigned Fixed to Double Floating-point |
225 | */ |
226 | |
227 | int |
228 | dbl_to_dbl_fcnvuf( |
229 | dbl_unsigned *srcptr, |
230 | unsigned int *_nullptr, |
231 | dbl_floating_point *dstptr, |
232 | unsigned int *status) |
233 | { |
234 | register int dst_exponent; |
235 | register unsigned int srcp1, srcp2, resultp1 = 0, resultp2 = 0; |
236 | |
237 | Duint_copyfromptr(srcptr,srcp1,srcp2); |
238 | |
239 | /* Check for zero */ |
240 | if (srcp1 == 0 && srcp2 ==0) { |
241 | Dbl_setzero(resultp1,resultp2); |
242 | Dbl_copytoptr(resultp1,resultp2,dstptr); |
243 | return(NOEXCEPTION); |
244 | } |
245 | /* |
246 | * Generate exponent and normalized mantissa |
247 | */ |
248 | dst_exponent = 16; /* initialize for normalization */ |
249 | if (srcp1 == 0) { |
250 | /* |
251 | * Check word for most significant bit set. Returns |
252 | * a value in dst_exponent indicating the bit position, |
253 | * between -1 and 30. |
254 | */ |
255 | Find_ms_one_bit(srcp2,dst_exponent); |
256 | /* left justify source, with msb at bit position 0 */ |
257 | srcp1 = srcp2 << dst_exponent+1; |
258 | srcp2 = 0; |
259 | /* |
260 | * since msb set is in second word, need to |
261 | * adjust bit position count |
262 | */ |
263 | dst_exponent += 32; |
264 | } |
265 | else { |
266 | /* |
267 | * Check word for most significant bit set. Returns |
268 | * a value in dst_exponent indicating the bit position, |
269 | * between -1 and 30. |
270 | */ |
271 | Find_ms_one_bit(srcp1,dst_exponent); |
272 | /* left justify source, with msb at bit position 0 */ |
273 | if (dst_exponent >= 0) { |
274 | Variable_shift_double(srcp1,srcp2,(31-dst_exponent), |
275 | srcp1); |
276 | srcp2 <<= dst_exponent+1; |
277 | } |
278 | } |
279 | Dbl_set_mantissap1(resultp1, srcp1 >> DBL_EXP_LENGTH); |
280 | Shiftdouble(srcp1,srcp2,DBL_EXP_LENGTH,resultp2); |
281 | Dbl_set_exponent(resultp1, (62+DBL_BIAS) - dst_exponent); |
282 | |
283 | /* check for inexact */ |
284 | if (Duint_isinexact_to_dbl(srcp2)) { |
285 | switch (Rounding_mode()) { |
286 | case ROUNDPLUS: |
287 | Dbl_increment(resultp1,resultp2); |
288 | break; |
289 | case ROUNDMINUS: /* never negative */ |
290 | break; |
291 | case ROUNDNEAREST: |
292 | Dbl_roundnearest_from_duint(srcp2,resultp1, |
293 | resultp2); |
294 | break; |
295 | } |
296 | if (Is_inexacttrap_enabled()) { |
297 | Dbl_copytoptr(resultp1,resultp2,dstptr); |
298 | return(INEXACTEXCEPTION); |
299 | } |
300 | else Set_inexactflag(); |
301 | } |
302 | Dbl_copytoptr(resultp1,resultp2,dstptr); |
303 | return(NOEXCEPTION); |
304 | } |
305 | |
306 | |