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