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