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