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/fcnvfx.c $Revision: 1.1 $
13 *
14 * Purpose:
15 * Single Floating-point to Single Fixed-point
16 * Single Floating-point to Double Fixed-point
17 * Double Floating-point to Single Fixed-point
18 * Double Floating-point to Double Fixed-point
19 *
20 * External Interfaces:
21 * dbl_to_dbl_fcnvfx(srcptr,_nullptr,dstptr,status)
22 * dbl_to_sgl_fcnvfx(srcptr,_nullptr,dstptr,status)
23 * sgl_to_dbl_fcnvfx(srcptr,_nullptr,dstptr,status)
24 * sgl_to_sgl_fcnvfx(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 * Single Floating-point to Single Fixed-point
42 */
43/*ARGSUSED*/
44int
45sgl_to_sgl_fcnvfx(
46 sgl_floating_point *srcptr,
47 sgl_floating_point *_nullptr,
48 int *dstptr,
49 sgl_floating_point *status)
50{
51 register unsigned int src, temp;
52 register int src_exponent, result;
53 register boolean inexact = FALSE;
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
86 /* check for inexact */
87 if (Sgl_isinexact_to_fix(src,src_exponent)) {
88 inexact = TRUE;
89 /* round result */
90 switch (Rounding_mode()) {
91 case ROUNDPLUS:
92 if (Sgl_iszero_sign(src)) result++;
93 break;
94 case ROUNDMINUS:
95 if (Sgl_isone_sign(src)) result--;
96 break;
97 case ROUNDNEAREST:
98 if (Sgl_isone_roundbit(src,src_exponent)) {
99 if (Sgl_isone_stickybit(src,src_exponent)
100 || (Sgl_isone_lowmantissa(temp)))
101 if (Sgl_iszero_sign(src)) result++;
102 else result--;
103 }
104 }
105 }
106 }
107 else {
108 result = 0;
109
110 /* check for inexact */
111 if (Sgl_isnotzero_exponentmantissa(src)) {
112 inexact = TRUE;
113 /* round result */
114 switch (Rounding_mode()) {
115 case ROUNDPLUS:
116 if (Sgl_iszero_sign(src)) result++;
117 break;
118 case ROUNDMINUS:
119 if (Sgl_isone_sign(src)) result--;
120 break;
121 case ROUNDNEAREST:
122 if (src_exponent == -1)
123 if (Sgl_isnotzero_mantissa(src))
124 if (Sgl_iszero_sign(src)) result++;
125 else result--;
126 }
127 }
128 }
129 *dstptr = result;
130 if (inexact) {
131 if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION);
132 else Set_inexactflag();
133 }
134 return(NOEXCEPTION);
135}
136
137/*
138 * Single Floating-point to Double Fixed-point
139 */
140/*ARGSUSED*/
141int
142sgl_to_dbl_fcnvfx(
143 sgl_floating_point *srcptr,
144 unsigned int *_nullptr,
145 dbl_integer *dstptr,
146 unsigned int *status)
147{
148 register int src_exponent, resultp1;
149 register unsigned int src, temp, resultp2;
150 register boolean inexact = FALSE;
151
152 src = *srcptr;
153 src_exponent = Sgl_exponent(src) - SGL_BIAS;
154
155 /*
156 * Test for overflow
157 */
158 if (src_exponent > DBL_FX_MAX_EXP) {
159 /* check for MININT */
160 if ((src_exponent > DBL_FX_MAX_EXP + 1) ||
161 Sgl_isnotzero_mantissa(src) || Sgl_iszero_sign(src)) {
162 if (Sgl_iszero_sign(src)) {
163 resultp1 = 0x7fffffff;
164 resultp2 = 0xffffffff;
165 }
166 else {
167 resultp1 = 0x80000000;
168 resultp2 = 0;
169 }
170 if (Is_invalidtrap_enabled()) {
171 return(INVALIDEXCEPTION);
172 }
173 Set_invalidflag();
174 Dint_copytoptr(resultp1,resultp2,dstptr);
175 return(NOEXCEPTION);
176 }
177 Dint_set_minint(resultp1,resultp2);
178 Dint_copytoptr(resultp1,resultp2,dstptr);
179 return(NOEXCEPTION);
180 }
181 /*
182 * Generate result
183 */
184 if (src_exponent >= 0) {
185 temp = src;
186 Sgl_clear_signexponent_set_hidden(temp);
187 Dint_from_sgl_mantissa(temp,src_exponent,resultp1,resultp2);
188 if (Sgl_isone_sign(src)) {
189 Dint_setone_sign(resultp1,resultp2);
190 }
191
192 /* check for inexact */
193 if (Sgl_isinexact_to_fix(src,src_exponent)) {
194 inexact = TRUE;
195 /* round result */
196 switch (Rounding_mode()) {
197 case ROUNDPLUS:
198 if (Sgl_iszero_sign(src)) {
199 Dint_increment(resultp1,resultp2);
200 }
201 break;
202 case ROUNDMINUS:
203 if (Sgl_isone_sign(src)) {
204 Dint_decrement(resultp1,resultp2);
205 }
206 break;
207 case ROUNDNEAREST:
208 if (Sgl_isone_roundbit(src,src_exponent))
209 if (Sgl_isone_stickybit(src,src_exponent) ||
210 (Dint_isone_lowp2(resultp2)))
211 if (Sgl_iszero_sign(src)) {
212 Dint_increment(resultp1,resultp2);
213 }
214 else {
215 Dint_decrement(resultp1,resultp2);
216 }
217 }
218 }
219 }
220 else {
221 Dint_setzero(resultp1,resultp2);
222
223 /* check for inexact */
224 if (Sgl_isnotzero_exponentmantissa(src)) {
225 inexact = TRUE;
226 /* round result */
227 switch (Rounding_mode()) {
228 case ROUNDPLUS:
229 if (Sgl_iszero_sign(src)) {
230 Dint_increment(resultp1,resultp2);
231 }
232 break;
233 case ROUNDMINUS:
234 if (Sgl_isone_sign(src)) {
235 Dint_decrement(resultp1,resultp2);
236 }
237 break;
238 case ROUNDNEAREST:
239 if (src_exponent == -1)
240 if (Sgl_isnotzero_mantissa(src))
241 if (Sgl_iszero_sign(src)) {
242 Dint_increment(resultp1,resultp2);
243 }
244 else {
245 Dint_decrement(resultp1,resultp2);
246 }
247 }
248 }
249 }
250 Dint_copytoptr(resultp1,resultp2,dstptr);
251 if (inexact) {
252 if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION);
253 else Set_inexactflag();
254 }
255 return(NOEXCEPTION);
256}
257
258/*
259 * Double Floating-point to Single Fixed-point
260 */
261/*ARGSUSED*/
262int
263dbl_to_sgl_fcnvfx(
264 dbl_floating_point *srcptr,
265 unsigned int *_nullptr,
266 int *dstptr,
267 unsigned int *status)
268{
269 register unsigned int srcp1,srcp2, tempp1,tempp2;
270 register int src_exponent, result;
271 register boolean inexact = FALSE;
272
273 Dbl_copyfromptr(srcptr,srcp1,srcp2);
274 src_exponent = Dbl_exponent(srcp1) - DBL_BIAS;
275
276 /*
277 * Test for overflow
278 */
279 if (src_exponent > SGL_FX_MAX_EXP) {
280 /* check for MININT */
281 if (Dbl_isoverflow_to_int(src_exponent,srcp1,srcp2)) {
282 if (Dbl_iszero_sign(srcp1)) result = 0x7fffffff;
283 else result = 0x80000000;
284
285 if (Is_invalidtrap_enabled()) {
286 return(INVALIDEXCEPTION);
287 }
288 Set_invalidflag();
289 *dstptr = result;
290 return(NOEXCEPTION);
291 }
292 }
293 /*
294 * Generate result
295 */
296 if (src_exponent >= 0) {
297 tempp1 = srcp1;
298 tempp2 = srcp2;
299 Dbl_clear_signexponent_set_hidden(tempp1);
300 Int_from_dbl_mantissa(tempp1,tempp2,src_exponent);
301 if (Dbl_isone_sign(srcp1) && (src_exponent <= SGL_FX_MAX_EXP))
302 result = -Dbl_allp1(tempp1);
303 else result = Dbl_allp1(tempp1);
304
305 /* check for inexact */
306 if (Dbl_isinexact_to_fix(srcp1,srcp2,src_exponent)) {
307 inexact = TRUE;
308 /* round result */
309 switch (Rounding_mode()) {
310 case ROUNDPLUS:
311 if (Dbl_iszero_sign(srcp1)) result++;
312 break;
313 case ROUNDMINUS:
314 if (Dbl_isone_sign(srcp1)) result--;
315 break;
316 case ROUNDNEAREST:
317 if (Dbl_isone_roundbit(srcp1,srcp2,src_exponent))
318 if (Dbl_isone_stickybit(srcp1,srcp2,src_exponent) ||
319 (Dbl_isone_lowmantissap1(tempp1)))
320 if (Dbl_iszero_sign(srcp1)) result++;
321 else result--;
322 }
323 /* check for overflow */
324 if ((Dbl_iszero_sign(srcp1) && result < 0) ||
325 (Dbl_isone_sign(srcp1) && result > 0)) {
326
327 if (Dbl_iszero_sign(srcp1)) result = 0x7fffffff;
328 else result = 0x80000000;
329
330 if (Is_invalidtrap_enabled()) {
331 return(INVALIDEXCEPTION);
332 }
333 Set_invalidflag();
334 *dstptr = result;
335 return(NOEXCEPTION);
336 }
337 }
338 }
339 else {
340 result = 0;
341
342 /* check for inexact */
343 if (Dbl_isnotzero_exponentmantissa(srcp1,srcp2)) {
344 inexact = TRUE;
345 /* round result */
346 switch (Rounding_mode()) {
347 case ROUNDPLUS:
348 if (Dbl_iszero_sign(srcp1)) result++;
349 break;
350 case ROUNDMINUS:
351 if (Dbl_isone_sign(srcp1)) result--;
352 break;
353 case ROUNDNEAREST:
354 if (src_exponent == -1)
355 if (Dbl_isnotzero_mantissa(srcp1,srcp2))
356 if (Dbl_iszero_sign(srcp1)) result++;
357 else result--;
358 }
359 }
360 }
361 *dstptr = result;
362 if (inexact) {
363 if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION);
364 else Set_inexactflag();
365 }
366 return(NOEXCEPTION);
367}
368
369/*
370 * Double Floating-point to Double Fixed-point
371 */
372/*ARGSUSED*/
373int
374dbl_to_dbl_fcnvfx(
375 dbl_floating_point *srcptr,
376 unsigned int *_nullptr,
377 dbl_integer *dstptr,
378 unsigned int *status)
379{
380 register int src_exponent, resultp1;
381 register unsigned int srcp1, srcp2, tempp1, tempp2, resultp2;
382 register boolean inexact = FALSE;
383
384 Dbl_copyfromptr(srcptr,srcp1,srcp2);
385 src_exponent = Dbl_exponent(srcp1) - DBL_BIAS;
386
387 /*
388 * Test for overflow
389 */
390 if (src_exponent > DBL_FX_MAX_EXP) {
391 /* check for MININT */
392 if ((src_exponent > DBL_FX_MAX_EXP + 1) ||
393 Dbl_isnotzero_mantissa(srcp1,srcp2) || Dbl_iszero_sign(srcp1)) {
394 if (Dbl_iszero_sign(srcp1)) {
395 resultp1 = 0x7fffffff;
396 resultp2 = 0xffffffff;
397 }
398 else {
399 resultp1 = 0x80000000;
400 resultp2 = 0;
401 }
402 if (Is_invalidtrap_enabled()) {
403 return(INVALIDEXCEPTION);
404 }
405 Set_invalidflag();
406 Dint_copytoptr(resultp1,resultp2,dstptr);
407 return(NOEXCEPTION);
408 }
409 }
410
411 /*
412 * Generate result
413 */
414 if (src_exponent >= 0) {
415 tempp1 = srcp1;
416 tempp2 = srcp2;
417 Dbl_clear_signexponent_set_hidden(tempp1);
418 Dint_from_dbl_mantissa(tempp1,tempp2,src_exponent,resultp1,
419 resultp2);
420 if (Dbl_isone_sign(srcp1)) {
421 Dint_setone_sign(resultp1,resultp2);
422 }
423
424 /* check for inexact */
425 if (Dbl_isinexact_to_fix(srcp1,srcp2,src_exponent)) {
426 inexact = TRUE;
427 /* round result */
428 switch (Rounding_mode()) {
429 case ROUNDPLUS:
430 if (Dbl_iszero_sign(srcp1)) {
431 Dint_increment(resultp1,resultp2);
432 }
433 break;
434 case ROUNDMINUS:
435 if (Dbl_isone_sign(srcp1)) {
436 Dint_decrement(resultp1,resultp2);
437 }
438 break;
439 case ROUNDNEAREST:
440 if (Dbl_isone_roundbit(srcp1,srcp2,src_exponent))
441 if (Dbl_isone_stickybit(srcp1,srcp2,src_exponent) ||
442 (Dint_isone_lowp2(resultp2)))
443 if (Dbl_iszero_sign(srcp1)) {
444 Dint_increment(resultp1,resultp2);
445 }
446 else {
447 Dint_decrement(resultp1,resultp2);
448 }
449 }
450 }
451 }
452 else {
453 Dint_setzero(resultp1,resultp2);
454
455 /* check for inexact */
456 if (Dbl_isnotzero_exponentmantissa(srcp1,srcp2)) {
457 inexact = TRUE;
458 /* round result */
459 switch (Rounding_mode()) {
460 case ROUNDPLUS:
461 if (Dbl_iszero_sign(srcp1)) {
462 Dint_increment(resultp1,resultp2);
463 }
464 break;
465 case ROUNDMINUS:
466 if (Dbl_isone_sign(srcp1)) {
467 Dint_decrement(resultp1,resultp2);
468 }
469 break;
470 case ROUNDNEAREST:
471 if (src_exponent == -1)
472 if (Dbl_isnotzero_mantissa(srcp1,srcp2))
473 if (Dbl_iszero_sign(srcp1)) {
474 Dint_increment(resultp1,resultp2);
475 }
476 else {
477 Dint_decrement(resultp1,resultp2);
478 }
479 }
480 }
481 }
482 Dint_copytoptr(resultp1,resultp2,dstptr);
483 if (inexact) {
484 if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION);
485 else Set_inexactflag();
486 }
487 return(NOEXCEPTION);
488}
489

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