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/fcnvfxt.c $Revision: $
26 *
27 * Purpose:
28 * Single Floating-point to Single Fixed-point /w truncated result
29 * Single Floating-point to Double Fixed-point /w truncated result
30 * Double Floating-point to Single Fixed-point /w truncated result
31 * Double Floating-point to Double Fixed-point /w truncated result
32 *
33 * External Interfaces:
34 * dbl_to_dbl_fcnvfxt(srcptr,nullptr,dstptr,status)
35 * dbl_to_sgl_fcnvfxt(srcptr,nullptr,dstptr,status)
36 * sgl_to_dbl_fcnvfxt(srcptr,nullptr,dstptr,status)
37 * sgl_to_sgl_fcnvfxt(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 floating-point to single fixed-point format
55 * with truncated result
56 */
57 /*ARGSUSED*/
58 int
sgl_to_sgl_fcnvfxt(sgl_floating_point * srcptr,unsigned int * nullptr,int * dstptr,unsigned int * status)59 sgl_to_sgl_fcnvfxt(
60 sgl_floating_point *srcptr,
61 unsigned int *nullptr,
62 int *dstptr,
63 unsigned int *status)
64 {
65 register unsigned int src, temp;
66 register int src_exponent, result;
67
68 src = *srcptr;
69 src_exponent = Sgl_exponent(src) - SGL_BIAS;
70
71 /*
72 * Test for overflow
73 */
74 if (src_exponent > SGL_FX_MAX_EXP) {
75 /* check for MININT */
76 if ((src_exponent > SGL_FX_MAX_EXP + 1) ||
77 Sgl_isnotzero_mantissa(src) || Sgl_iszero_sign(src)) {
78 if (Sgl_iszero_sign(src)) result = 0x7fffffff;
79 else result = 0x80000000;
80
81 if (Is_invalidtrap_enabled()) {
82 return(INVALIDEXCEPTION);
83 }
84 Set_invalidflag();
85 *dstptr = result;
86 return(NOEXCEPTION);
87 }
88 }
89 /*
90 * Generate result
91 */
92 if (src_exponent >= 0) {
93 temp = src;
94 Sgl_clear_signexponent_set_hidden(temp);
95 Int_from_sgl_mantissa(temp,src_exponent);
96 if (Sgl_isone_sign(src)) result = -Sgl_all(temp);
97 else result = Sgl_all(temp);
98 *dstptr = result;
99
100 /* check for inexact */
101 if (Sgl_isinexact_to_fix(src,src_exponent)) {
102 if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION);
103 else Set_inexactflag();
104 }
105 }
106 else {
107 *dstptr = 0;
108
109 /* check for inexact */
110 if (Sgl_isnotzero_exponentmantissa(src)) {
111 if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION);
112 else Set_inexactflag();
113 }
114 }
115 return(NOEXCEPTION);
116 }
117
118 /*
119 * Single Floating-point to Double Fixed-point
120 */
121 /*ARGSUSED*/
122 int
sgl_to_dbl_fcnvfxt(sgl_floating_point * srcptr,unsigned int * nullptr,dbl_integer * dstptr,unsigned int * status)123 sgl_to_dbl_fcnvfxt(
124 sgl_floating_point *srcptr,
125 unsigned int *nullptr,
126 dbl_integer *dstptr,
127 unsigned int *status)
128 {
129 register int src_exponent, resultp1;
130 register unsigned int src, temp, resultp2;
131
132 src = *srcptr;
133 src_exponent = Sgl_exponent(src) - SGL_BIAS;
134
135 /*
136 * Test for overflow
137 */
138 if (src_exponent > DBL_FX_MAX_EXP) {
139 /* check for MININT */
140 if ((src_exponent > DBL_FX_MAX_EXP + 1) ||
141 Sgl_isnotzero_mantissa(src) || Sgl_iszero_sign(src)) {
142 if (Sgl_iszero_sign(src)) {
143 resultp1 = 0x7fffffff;
144 resultp2 = 0xffffffff;
145 }
146 else {
147 resultp1 = 0x80000000;
148 resultp2 = 0;
149 }
150 if (Is_invalidtrap_enabled()) {
151 return(INVALIDEXCEPTION);
152 }
153 Set_invalidflag();
154 Dint_copytoptr(resultp1,resultp2,dstptr);
155 return(NOEXCEPTION);
156 }
157 Dint_set_minint(resultp1,resultp2);
158 Dint_copytoptr(resultp1,resultp2,dstptr);
159 return(NOEXCEPTION);
160 }
161 /*
162 * Generate result
163 */
164 if (src_exponent >= 0) {
165 temp = src;
166 Sgl_clear_signexponent_set_hidden(temp);
167 Dint_from_sgl_mantissa(temp,src_exponent,resultp1,resultp2);
168 if (Sgl_isone_sign(src)) {
169 Dint_setone_sign(resultp1,resultp2);
170 }
171 Dint_copytoptr(resultp1,resultp2,dstptr);
172
173 /* check for inexact */
174 if (Sgl_isinexact_to_fix(src,src_exponent)) {
175 if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION);
176 else Set_inexactflag();
177 }
178 }
179 else {
180 Dint_setzero(resultp1,resultp2);
181 Dint_copytoptr(resultp1,resultp2,dstptr);
182
183 /* check for inexact */
184 if (Sgl_isnotzero_exponentmantissa(src)) {
185 if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION);
186 else Set_inexactflag();
187 }
188 }
189 return(NOEXCEPTION);
190 }
191
192 /*
193 * Double Floating-point to Single Fixed-point
194 */
195 /*ARGSUSED*/
196 int
dbl_to_sgl_fcnvfxt(dbl_floating_point * srcptr,unsigned int * nullptr,int * dstptr,unsigned int * status)197 dbl_to_sgl_fcnvfxt(
198 dbl_floating_point *srcptr,
199 unsigned int *nullptr,
200 int *dstptr,
201 unsigned int *status)
202 {
203 register unsigned int srcp1, srcp2, tempp1, tempp2;
204 register int src_exponent, result;
205
206 Dbl_copyfromptr(srcptr,srcp1,srcp2);
207 src_exponent = Dbl_exponent(srcp1) - DBL_BIAS;
208
209 /*
210 * Test for overflow
211 */
212 if (src_exponent > SGL_FX_MAX_EXP) {
213 /* check for MININT */
214 if (Dbl_isoverflow_to_int(src_exponent,srcp1,srcp2)) {
215 if (Dbl_iszero_sign(srcp1)) result = 0x7fffffff;
216 else result = 0x80000000;
217
218 if (Is_invalidtrap_enabled()) {
219 return(INVALIDEXCEPTION);
220 }
221 Set_invalidflag();
222 *dstptr = result;
223 return(NOEXCEPTION);
224 }
225 }
226 /*
227 * Generate result
228 */
229 if (src_exponent >= 0) {
230 tempp1 = srcp1;
231 tempp2 = srcp2;
232 Dbl_clear_signexponent_set_hidden(tempp1);
233 Int_from_dbl_mantissa(tempp1,tempp2,src_exponent);
234 if (Dbl_isone_sign(srcp1) && (src_exponent <= SGL_FX_MAX_EXP))
235 result = -Dbl_allp1(tempp1);
236 else result = Dbl_allp1(tempp1);
237 *dstptr = result;
238
239 /* check for inexact */
240 if (Dbl_isinexact_to_fix(srcp1,srcp2,src_exponent)) {
241 if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION);
242 else Set_inexactflag();
243 }
244 }
245 else {
246 *dstptr = 0;
247
248 /* check for inexact */
249 if (Dbl_isnotzero_exponentmantissa(srcp1,srcp2)) {
250 if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION);
251 else Set_inexactflag();
252 }
253 }
254 return(NOEXCEPTION);
255 }
256
257 /*
258 * Double Floating-point to Double Fixed-point
259 */
260 /*ARGSUSED*/
261 int
dbl_to_dbl_fcnvfxt(dbl_floating_point * srcptr,unsigned int * nullptr,dbl_integer * dstptr,unsigned int * status)262 dbl_to_dbl_fcnvfxt(
263 dbl_floating_point *srcptr,
264 unsigned int *nullptr,
265 dbl_integer *dstptr,
266 unsigned int *status)
267 {
268 register int src_exponent, resultp1;
269 register unsigned int srcp1, srcp2, tempp1, tempp2, resultp2;
270
271 Dbl_copyfromptr(srcptr,srcp1,srcp2);
272 src_exponent = Dbl_exponent(srcp1) - DBL_BIAS;
273
274 /*
275 * Test for overflow
276 */
277 if (src_exponent > DBL_FX_MAX_EXP) {
278 /* check for MININT */
279 if ((src_exponent > DBL_FX_MAX_EXP + 1) ||
280 Dbl_isnotzero_mantissa(srcp1,srcp2) || Dbl_iszero_sign(srcp1)) {
281 if (Dbl_iszero_sign(srcp1)) {
282 resultp1 = 0x7fffffff;
283 resultp2 = 0xffffffff;
284 }
285 else {
286 resultp1 = 0x80000000;
287 resultp2 = 0;
288 }
289 if (Is_invalidtrap_enabled()) {
290 return(INVALIDEXCEPTION);
291 }
292 Set_invalidflag();
293 Dint_copytoptr(resultp1,resultp2,dstptr);
294 return(NOEXCEPTION);
295 }
296 }
297 /*
298 * Generate result
299 */
300 if (src_exponent >= 0) {
301 tempp1 = srcp1;
302 tempp2 = srcp2;
303 Dbl_clear_signexponent_set_hidden(tempp1);
304 Dint_from_dbl_mantissa(tempp1,tempp2,src_exponent,
305 resultp1,resultp2);
306 if (Dbl_isone_sign(srcp1)) {
307 Dint_setone_sign(resultp1,resultp2);
308 }
309 Dint_copytoptr(resultp1,resultp2,dstptr);
310
311 /* check for inexact */
312 if (Dbl_isinexact_to_fix(srcp1,srcp2,src_exponent)) {
313 if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION);
314 else Set_inexactflag();
315 }
316 }
317 else {
318 Dint_setzero(resultp1,resultp2);
319 Dint_copytoptr(resultp1,resultp2,dstptr);
320
321 /* check for inexact */
322 if (Dbl_isnotzero_exponentmantissa(srcp1,srcp2)) {
323 if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION);
324 else Set_inexactflag();
325 }
326 }
327 return(NOEXCEPTION);
328 }
329