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/fcnvff.c $Revision: 1.1 $ |
13 | * |
14 | * Purpose: |
15 | * Single Floating-point to Double Floating-point |
16 | * Double Floating-point to Single Floating-point |
17 | * |
18 | * External Interfaces: |
19 | * dbl_to_sgl_fcnvff(srcptr,_nullptr,dstptr,status) |
20 | * sgl_to_dbl_fcnvff(srcptr,_nullptr,dstptr,status) |
21 | * |
22 | * Internal Interfaces: |
23 | * |
24 | * Theory: |
25 | * <<please update with a overview of the operation of this file>> |
26 | * |
27 | * END_DESC |
28 | */ |
29 | |
30 | |
31 | #include "float.h" |
32 | #include "sgl_float.h" |
33 | #include "dbl_float.h" |
34 | #include "cnv_float.h" |
35 | |
36 | /* |
37 | * Single Floating-point to Double Floating-point |
38 | */ |
39 | /*ARGSUSED*/ |
40 | int |
41 | sgl_to_dbl_fcnvff( |
42 | sgl_floating_point *srcptr, |
43 | unsigned int *_nullptr, |
44 | dbl_floating_point *dstptr, |
45 | unsigned int *status) |
46 | { |
47 | register unsigned int src, resultp1, resultp2; |
48 | register int src_exponent; |
49 | |
50 | src = *srcptr; |
51 | src_exponent = Sgl_exponent(src); |
52 | Dbl_allp1(resultp1) = Sgl_all(src); /* set sign of result */ |
53 | /* |
54 | * Test for NaN or infinity |
55 | */ |
56 | if (src_exponent == SGL_INFINITY_EXPONENT) { |
57 | /* |
58 | * determine if NaN or infinity |
59 | */ |
60 | if (Sgl_iszero_mantissa(src)) { |
61 | /* |
62 | * is infinity; want to return double infinity |
63 | */ |
64 | Dbl_setinfinity_exponentmantissa(resultp1,resultp2); |
65 | Dbl_copytoptr(resultp1,resultp2,dstptr); |
66 | return(NOEXCEPTION); |
67 | } |
68 | else { |
69 | /* |
70 | * is NaN; signaling or quiet? |
71 | */ |
72 | if (Sgl_isone_signaling(src)) { |
73 | /* trap if INVALIDTRAP enabled */ |
74 | if (Is_invalidtrap_enabled()) |
75 | return(INVALIDEXCEPTION); |
76 | /* make NaN quiet */ |
77 | else { |
78 | Set_invalidflag(); |
79 | Sgl_set_quiet(src); |
80 | } |
81 | } |
82 | /* |
83 | * NaN is quiet, return as double NaN |
84 | */ |
85 | Dbl_setinfinity_exponent(resultp1); |
86 | Sgl_to_dbl_mantissa(src,resultp1,resultp2); |
87 | Dbl_copytoptr(resultp1,resultp2,dstptr); |
88 | return(NOEXCEPTION); |
89 | } |
90 | } |
91 | /* |
92 | * Test for zero or denormalized |
93 | */ |
94 | if (src_exponent == 0) { |
95 | /* |
96 | * determine if zero or denormalized |
97 | */ |
98 | if (Sgl_isnotzero_mantissa(src)) { |
99 | /* |
100 | * is denormalized; want to normalize |
101 | */ |
102 | Sgl_clear_signexponent(src); |
103 | Sgl_leftshiftby1(src); |
104 | Sgl_normalize(src,src_exponent); |
105 | Sgl_to_dbl_exponent(src_exponent,resultp1); |
106 | Sgl_to_dbl_mantissa(src,resultp1,resultp2); |
107 | } |
108 | else { |
109 | Dbl_setzero_exponentmantissa(resultp1,resultp2); |
110 | } |
111 | Dbl_copytoptr(resultp1,resultp2,dstptr); |
112 | return(NOEXCEPTION); |
113 | } |
114 | /* |
115 | * No special cases, just complete the conversion |
116 | */ |
117 | Sgl_to_dbl_exponent(src_exponent, resultp1); |
118 | Sgl_to_dbl_mantissa(Sgl_mantissa(src), resultp1,resultp2); |
119 | Dbl_copytoptr(resultp1,resultp2,dstptr); |
120 | return(NOEXCEPTION); |
121 | } |
122 | |
123 | /* |
124 | * Double Floating-point to Single Floating-point |
125 | */ |
126 | /*ARGSUSED*/ |
127 | int |
128 | dbl_to_sgl_fcnvff( |
129 | dbl_floating_point *srcptr, |
130 | unsigned int *_nullptr, |
131 | sgl_floating_point *dstptr, |
132 | unsigned int *status) |
133 | { |
134 | register unsigned int srcp1, srcp2, result; |
135 | register int src_exponent, dest_exponent, dest_mantissa; |
136 | register boolean inexact = FALSE, guardbit = FALSE, stickybit = FALSE; |
137 | register boolean lsb_odd = FALSE; |
138 | boolean is_tiny = FALSE; |
139 | |
140 | Dbl_copyfromptr(srcptr,srcp1,srcp2); |
141 | src_exponent = Dbl_exponent(srcp1); |
142 | Sgl_all(result) = Dbl_allp1(srcp1); /* set sign of result */ |
143 | /* |
144 | * Test for NaN or infinity |
145 | */ |
146 | if (src_exponent == DBL_INFINITY_EXPONENT) { |
147 | /* |
148 | * determine if NaN or infinity |
149 | */ |
150 | if (Dbl_iszero_mantissa(srcp1,srcp2)) { |
151 | /* |
152 | * is infinity; want to return single infinity |
153 | */ |
154 | Sgl_setinfinity_exponentmantissa(result); |
155 | *dstptr = result; |
156 | return(NOEXCEPTION); |
157 | } |
158 | /* |
159 | * is NaN; signaling or quiet? |
160 | */ |
161 | if (Dbl_isone_signaling(srcp1)) { |
162 | /* trap if INVALIDTRAP enabled */ |
163 | if (Is_invalidtrap_enabled()) return(INVALIDEXCEPTION); |
164 | else { |
165 | Set_invalidflag(); |
166 | /* make NaN quiet */ |
167 | Dbl_set_quiet(srcp1); |
168 | } |
169 | } |
170 | /* |
171 | * NaN is quiet, return as single NaN |
172 | */ |
173 | Sgl_setinfinity_exponent(result); |
174 | Sgl_set_mantissa(result,Dallp1(srcp1)<<3 | Dallp2(srcp2)>>29); |
175 | if (Sgl_iszero_mantissa(result)) Sgl_set_quiet(result); |
176 | *dstptr = result; |
177 | return(NOEXCEPTION); |
178 | } |
179 | /* |
180 | * Generate result |
181 | */ |
182 | Dbl_to_sgl_exponent(src_exponent,dest_exponent); |
183 | if (dest_exponent > 0) { |
184 | Dbl_to_sgl_mantissa(srcp1,srcp2,dest_mantissa,inexact,guardbit, |
185 | stickybit,lsb_odd); |
186 | } |
187 | else { |
188 | if (Dbl_iszero_exponentmantissa(srcp1,srcp2)){ |
189 | Sgl_setzero_exponentmantissa(result); |
190 | *dstptr = result; |
191 | return(NOEXCEPTION); |
192 | } |
193 | if (Is_underflowtrap_enabled()) { |
194 | Dbl_to_sgl_mantissa(srcp1,srcp2,dest_mantissa,inexact, |
195 | guardbit,stickybit,lsb_odd); |
196 | } |
197 | else { |
198 | /* compute result, determine inexact info, |
199 | * and set Underflowflag if appropriate |
200 | */ |
201 | Dbl_to_sgl_denormalized(srcp1,srcp2,dest_exponent, |
202 | dest_mantissa,inexact,guardbit,stickybit,lsb_odd, |
203 | is_tiny); |
204 | } |
205 | } |
206 | /* |
207 | * Now round result if not exact |
208 | */ |
209 | if (inexact) { |
210 | switch (Rounding_mode()) { |
211 | case ROUNDPLUS: |
212 | if (Sgl_iszero_sign(result)) dest_mantissa++; |
213 | break; |
214 | case ROUNDMINUS: |
215 | if (Sgl_isone_sign(result)) dest_mantissa++; |
216 | break; |
217 | case ROUNDNEAREST: |
218 | if (guardbit) { |
219 | if (stickybit || lsb_odd) dest_mantissa++; |
220 | } |
221 | } |
222 | } |
223 | Sgl_set_exponentmantissa(result,dest_mantissa); |
224 | |
225 | /* |
226 | * check for mantissa overflow after rounding |
227 | */ |
228 | if ((dest_exponent>0 || Is_underflowtrap_enabled()) && |
229 | Sgl_isone_hidden(result)) dest_exponent++; |
230 | |
231 | /* |
232 | * Test for overflow |
233 | */ |
234 | if (dest_exponent >= SGL_INFINITY_EXPONENT) { |
235 | /* trap if OVERFLOWTRAP enabled */ |
236 | if (Is_overflowtrap_enabled()) { |
237 | /* |
238 | * Check for gross overflow |
239 | */ |
240 | if (dest_exponent >= SGL_INFINITY_EXPONENT+SGL_WRAP) |
241 | return(UNIMPLEMENTEDEXCEPTION); |
242 | |
243 | /* |
244 | * Adjust bias of result |
245 | */ |
246 | Sgl_setwrapped_exponent(result,dest_exponent,ovfl); |
247 | *dstptr = result; |
248 | if (inexact) |
249 | if (Is_inexacttrap_enabled()) |
250 | return(OVERFLOWEXCEPTION|INEXACTEXCEPTION); |
251 | else Set_inexactflag(); |
252 | return(OVERFLOWEXCEPTION); |
253 | } |
254 | Set_overflowflag(); |
255 | inexact = TRUE; |
256 | /* set result to infinity or largest number */ |
257 | Sgl_setoverflow(result); |
258 | } |
259 | /* |
260 | * Test for underflow |
261 | */ |
262 | else if (dest_exponent <= 0) { |
263 | /* trap if UNDERFLOWTRAP enabled */ |
264 | if (Is_underflowtrap_enabled()) { |
265 | /* |
266 | * Check for gross underflow |
267 | */ |
268 | if (dest_exponent <= -(SGL_WRAP)) |
269 | return(UNIMPLEMENTEDEXCEPTION); |
270 | /* |
271 | * Adjust bias of result |
272 | */ |
273 | Sgl_setwrapped_exponent(result,dest_exponent,unfl); |
274 | *dstptr = result; |
275 | if (inexact) |
276 | if (Is_inexacttrap_enabled()) |
277 | return(UNDERFLOWEXCEPTION|INEXACTEXCEPTION); |
278 | else Set_inexactflag(); |
279 | return(UNDERFLOWEXCEPTION); |
280 | } |
281 | /* |
282 | * result is denormalized or signed zero |
283 | */ |
284 | if (inexact && is_tiny) Set_underflowflag(); |
285 | |
286 | } |
287 | else Sgl_set_exponent(result,dest_exponent); |
288 | *dstptr = result; |
289 | /* |
290 | * Trap if inexact trap is enabled |
291 | */ |
292 | if (inexact) |
293 | if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION); |
294 | else Set_inexactflag(); |
295 | return(NOEXCEPTION); |
296 | } |
297 | |