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*/
40int
41sgl_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*/
127int
128dbl_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

source code of linux/arch/parisc/math-emu/fcnvff.c