WIP FPC-III support
[linux/fpc-iii.git] / arch / parisc / math-emu / fcnvxf.c
blob69401797146b906cddee6bb31be45c322ae91011
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3 * Linux/PA-RISC Project (http://www.parisc-linux.org/)
5 * Floating-point emulation code
6 * Copyright (C) 2001 Hewlett-Packard (Paul Bame) <bame@debian.org>
7 */
8 /*
9 * BEGIN_DESC
11 * File:
12 * @(#) pa/spmath/fcnvxf.c $Revision: 1.1 $
14 * Purpose:
15 * Single Fixed-point to Single Floating-point
16 * Single Fixed-point to Double Floating-point
17 * Double Fixed-point to Single Floating-point
18 * Double Fixed-point to Double Floating-point
20 * External Interfaces:
21 * dbl_to_dbl_fcnvxf(srcptr,nullptr,dstptr,status)
22 * dbl_to_sgl_fcnvxf(srcptr,nullptr,dstptr,status)
23 * sgl_to_dbl_fcnvxf(srcptr,nullptr,dstptr,status)
24 * sgl_to_sgl_fcnvxf(srcptr,nullptr,dstptr,status)
26 * Internal Interfaces:
28 * Theory:
29 * <<please update with a overview of the operation of this file>>
31 * END_DESC
35 #include "float.h"
36 #include "sgl_float.h"
37 #include "dbl_float.h"
38 #include "cnv_float.h"
41 * Convert single fixed-point to single floating-point format
44 int
45 sgl_to_sgl_fcnvxf(
46 int *srcptr,
47 unsigned int *nullptr,
48 sgl_floating_point *dstptr,
49 unsigned int *status)
51 register int src, dst_exponent;
52 register unsigned int result = 0;
54 src = *srcptr;
55 /*
56 * set sign bit of result and get magnitude of source
58 if (src < 0) {
59 Sgl_setone_sign(result);
60 Int_negate(src);
62 else {
63 Sgl_setzero_sign(result);
64 /* Check for zero */
65 if (src == 0) {
66 Sgl_setzero(result);
67 *dstptr = result;
68 return(NOEXCEPTION);
72 * Generate exponent and normalized mantissa
74 dst_exponent = 16; /* initialize for normalization */
76 * Check word for most significant bit set. Returns
77 * a value in dst_exponent indicating the bit position,
78 * between -1 and 30.
80 Find_ms_one_bit(src,dst_exponent);
81 /* left justify source, with msb at bit position 1 */
82 if (dst_exponent >= 0) src <<= dst_exponent;
83 else src = 1 << 30;
84 Sgl_set_mantissa(result, src >> (SGL_EXP_LENGTH-1));
85 Sgl_set_exponent(result, 30+SGL_BIAS - dst_exponent);
87 /* check for inexact */
88 if (Int_isinexact_to_sgl(src)) {
89 switch (Rounding_mode()) {
90 case ROUNDPLUS:
91 if (Sgl_iszero_sign(result))
92 Sgl_increment(result);
93 break;
94 case ROUNDMINUS:
95 if (Sgl_isone_sign(result))
96 Sgl_increment(result);
97 break;
98 case ROUNDNEAREST:
99 Sgl_roundnearest_from_int(src,result);
101 if (Is_inexacttrap_enabled()) {
102 *dstptr = result;
103 return(INEXACTEXCEPTION);
105 else Set_inexactflag();
107 *dstptr = result;
108 return(NOEXCEPTION);
112 * Single Fixed-point to Double Floating-point
116 sgl_to_dbl_fcnvxf(
117 int *srcptr,
118 unsigned int *nullptr,
119 dbl_floating_point *dstptr,
120 unsigned int *status)
122 register int src, dst_exponent;
123 register unsigned int resultp1 = 0, resultp2 = 0;
125 src = *srcptr;
127 * set sign bit of result and get magnitude of source
129 if (src < 0) {
130 Dbl_setone_sign(resultp1);
131 Int_negate(src);
133 else {
134 Dbl_setzero_sign(resultp1);
135 /* Check for zero */
136 if (src == 0) {
137 Dbl_setzero(resultp1,resultp2);
138 Dbl_copytoptr(resultp1,resultp2,dstptr);
139 return(NOEXCEPTION);
143 * Generate exponent and normalized mantissa
145 dst_exponent = 16; /* initialize for normalization */
147 * Check word for most significant bit set. Returns
148 * a value in dst_exponent indicating the bit position,
149 * between -1 and 30.
151 Find_ms_one_bit(src,dst_exponent);
152 /* left justify source, with msb at bit position 1 */
153 if (dst_exponent >= 0) src <<= dst_exponent;
154 else src = 1 << 30;
155 Dbl_set_mantissap1(resultp1, src >> DBL_EXP_LENGTH - 1);
156 Dbl_set_mantissap2(resultp2, src << (33-DBL_EXP_LENGTH));
157 Dbl_set_exponent(resultp1, (30+DBL_BIAS) - dst_exponent);
158 Dbl_copytoptr(resultp1,resultp2,dstptr);
159 return(NOEXCEPTION);
163 * Double Fixed-point to Single Floating-point
167 dbl_to_sgl_fcnvxf(
168 dbl_integer *srcptr,
169 unsigned int *nullptr,
170 sgl_floating_point *dstptr,
171 unsigned int *status)
173 int dst_exponent, srcp1;
174 unsigned int result = 0, srcp2;
176 Dint_copyfromptr(srcptr,srcp1,srcp2);
178 * set sign bit of result and get magnitude of source
180 if (srcp1 < 0) {
181 Sgl_setone_sign(result);
182 Dint_negate(srcp1,srcp2);
184 else {
185 Sgl_setzero_sign(result);
186 /* Check for zero */
187 if (srcp1 == 0 && srcp2 == 0) {
188 Sgl_setzero(result);
189 *dstptr = result;
190 return(NOEXCEPTION);
194 * Generate exponent and normalized mantissa
196 dst_exponent = 16; /* initialize for normalization */
197 if (srcp1 == 0) {
199 * Check word for most significant bit set. Returns
200 * a value in dst_exponent indicating the bit position,
201 * between -1 and 30.
203 Find_ms_one_bit(srcp2,dst_exponent);
204 /* left justify source, with msb at bit position 1 */
205 if (dst_exponent >= 0) {
206 srcp1 = srcp2 << dst_exponent;
207 srcp2 = 0;
209 else {
210 srcp1 = srcp2 >> 1;
211 srcp2 <<= 31;
214 * since msb set is in second word, need to
215 * adjust bit position count
217 dst_exponent += 32;
219 else {
221 * Check word for most significant bit set. Returns
222 * a value in dst_exponent indicating the bit position,
223 * between -1 and 30.
226 Find_ms_one_bit(srcp1,dst_exponent);
227 /* left justify source, with msb at bit position 1 */
228 if (dst_exponent > 0) {
229 Variable_shift_double(srcp1,srcp2,(32-dst_exponent),
230 srcp1);
231 srcp2 <<= dst_exponent;
234 * If dst_exponent = 0, we don't need to shift anything.
235 * If dst_exponent = -1, src = - 2**63 so we won't need to
236 * shift srcp2.
238 else srcp1 >>= -(dst_exponent);
240 Sgl_set_mantissa(result, srcp1 >> SGL_EXP_LENGTH - 1);
241 Sgl_set_exponent(result, (62+SGL_BIAS) - dst_exponent);
243 /* check for inexact */
244 if (Dint_isinexact_to_sgl(srcp1,srcp2)) {
245 switch (Rounding_mode()) {
246 case ROUNDPLUS:
247 if (Sgl_iszero_sign(result))
248 Sgl_increment(result);
249 break;
250 case ROUNDMINUS:
251 if (Sgl_isone_sign(result))
252 Sgl_increment(result);
253 break;
254 case ROUNDNEAREST:
255 Sgl_roundnearest_from_dint(srcp1,srcp2,result);
257 if (Is_inexacttrap_enabled()) {
258 *dstptr = result;
259 return(INEXACTEXCEPTION);
261 else Set_inexactflag();
263 *dstptr = result;
264 return(NOEXCEPTION);
268 * Double Fixed-point to Double Floating-point
272 dbl_to_dbl_fcnvxf(
273 dbl_integer *srcptr,
274 unsigned int *nullptr,
275 dbl_floating_point *dstptr,
276 unsigned int *status)
278 register int srcp1, dst_exponent;
279 register unsigned int srcp2, resultp1 = 0, resultp2 = 0;
281 Dint_copyfromptr(srcptr,srcp1,srcp2);
283 * set sign bit of result and get magnitude of source
285 if (srcp1 < 0) {
286 Dbl_setone_sign(resultp1);
287 Dint_negate(srcp1,srcp2);
289 else {
290 Dbl_setzero_sign(resultp1);
291 /* Check for zero */
292 if (srcp1 == 0 && srcp2 ==0) {
293 Dbl_setzero(resultp1,resultp2);
294 Dbl_copytoptr(resultp1,resultp2,dstptr);
295 return(NOEXCEPTION);
299 * Generate exponent and normalized mantissa
301 dst_exponent = 16; /* initialize for normalization */
302 if (srcp1 == 0) {
304 * Check word for most significant bit set. Returns
305 * a value in dst_exponent indicating the bit position,
306 * between -1 and 30.
308 Find_ms_one_bit(srcp2,dst_exponent);
309 /* left justify source, with msb at bit position 1 */
310 if (dst_exponent >= 0) {
311 srcp1 = srcp2 << dst_exponent;
312 srcp2 = 0;
314 else {
315 srcp1 = srcp2 >> 1;
316 srcp2 <<= 31;
319 * since msb set is in second word, need to
320 * adjust bit position count
322 dst_exponent += 32;
324 else {
326 * Check word for most significant bit set. Returns
327 * a value in dst_exponent indicating the bit position,
328 * between -1 and 30.
330 Find_ms_one_bit(srcp1,dst_exponent);
331 /* left justify source, with msb at bit position 1 */
332 if (dst_exponent > 0) {
333 Variable_shift_double(srcp1,srcp2,(32-dst_exponent),
334 srcp1);
335 srcp2 <<= dst_exponent;
338 * If dst_exponent = 0, we don't need to shift anything.
339 * If dst_exponent = -1, src = - 2**63 so we won't need to
340 * shift srcp2.
342 else srcp1 >>= -(dst_exponent);
344 Dbl_set_mantissap1(resultp1, srcp1 >> (DBL_EXP_LENGTH-1));
345 Shiftdouble(srcp1,srcp2,DBL_EXP_LENGTH-1,resultp2);
346 Dbl_set_exponent(resultp1, (62+DBL_BIAS) - dst_exponent);
348 /* check for inexact */
349 if (Dint_isinexact_to_dbl(srcp2)) {
350 switch (Rounding_mode()) {
351 case ROUNDPLUS:
352 if (Dbl_iszero_sign(resultp1)) {
353 Dbl_increment(resultp1,resultp2);
355 break;
356 case ROUNDMINUS:
357 if (Dbl_isone_sign(resultp1)) {
358 Dbl_increment(resultp1,resultp2);
360 break;
361 case ROUNDNEAREST:
362 Dbl_roundnearest_from_dint(srcp2,resultp1,
363 resultp2);
365 if (Is_inexacttrap_enabled()) {
366 Dbl_copytoptr(resultp1,resultp2,dstptr);
367 return(INEXACTEXCEPTION);
369 else Set_inexactflag();
371 Dbl_copytoptr(resultp1,resultp2,dstptr);
372 return(NOEXCEPTION);