Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/arch/parisc/math-emu/fcnvfx.c
26288 views
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) <[email protected]>
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*/
44
int
45
sgl_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*/
141
int
142
sgl_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*/
262
int
263
dbl_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*/
373
int
374
dbl_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
490