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., 675 Mass Ave, Cambridge, MA 02139, USA.
20 */
21 /*
22 * BEGIN_DESC
23 *
24 * File:
25 * @(#) pa/spmath/fcnvxf.c $Revision: $
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
sgl_to_sgl_fcnvxf(int * srcptr,unsigned int * nullptr,sgl_floating_point * dstptr,unsigned int * status)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
sgl_to_dbl_fcnvxf(int * srcptr,unsigned int * nullptr,dbl_floating_point * dstptr,unsigned int * status)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
dbl_to_sgl_fcnvxf(dbl_integer * srcptr,unsigned int * nullptr,sgl_floating_point * dstptr,unsigned int * status)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
dbl_to_dbl_fcnvxf(dbl_integer * srcptr,unsigned int * nullptr,dbl_floating_point * dstptr,unsigned int * status)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 }
387