Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/arch/parisc/math-emu/fcnvfu.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/fcnvfu.c $Revision: 1.1 $
13
*
14
* Purpose:
15
* Floating-point to Unsigned Fixed-point Converts
16
*
17
* External Interfaces:
18
* dbl_to_dbl_fcnvfu(srcptr,_nullptr,dstptr,status)
19
* dbl_to_sgl_fcnvfu(srcptr,_nullptr,dstptr,status)
20
* sgl_to_dbl_fcnvfu(srcptr,_nullptr,dstptr,status)
21
* sgl_to_sgl_fcnvfu(srcptr,_nullptr,dstptr,status)
22
*
23
* Internal Interfaces:
24
*
25
* Theory:
26
* <<please update with a overview of the operation of this file>>
27
*
28
* END_DESC
29
*/
30
31
32
#include "float.h"
33
#include "sgl_float.h"
34
#include "dbl_float.h"
35
#include "cnv_float.h"
36
37
/************************************************************************
38
* Floating-point to Unsigned Fixed-point Converts *
39
************************************************************************/
40
41
/*
42
* Single Floating-point to Single Unsigned Fixed
43
*/
44
/*ARGSUSED*/
45
int
46
sgl_to_sgl_fcnvfu(
47
sgl_floating_point *srcptr,
48
unsigned int *_nullptr,
49
unsigned int *dstptr,
50
unsigned int *status)
51
{
52
register unsigned int src, result;
53
register int src_exponent;
54
register boolean inexact = FALSE;
55
56
src = *srcptr;
57
src_exponent = Sgl_exponent(src) - SGL_BIAS;
58
59
/*
60
* Test for overflow
61
*/
62
if (src_exponent > SGL_FX_MAX_EXP + 1) {
63
if (Sgl_isone_sign(src)) {
64
result = 0;
65
} else {
66
result = 0xffffffff;
67
}
68
if (Is_invalidtrap_enabled()) {
69
return(INVALIDEXCEPTION);
70
}
71
Set_invalidflag();
72
*dstptr = result;
73
return(NOEXCEPTION);
74
}
75
/*
76
* Generate result
77
*/
78
if (src_exponent >= 0) {
79
/*
80
* Check sign.
81
* If negative, trap unimplemented.
82
*/
83
if (Sgl_isone_sign(src)) {
84
result = 0;
85
if (Is_invalidtrap_enabled()) {
86
return(INVALIDEXCEPTION);
87
}
88
Set_invalidflag();
89
*dstptr = result;
90
return(NOEXCEPTION);
91
}
92
Sgl_clear_signexponent_set_hidden(src);
93
Suint_from_sgl_mantissa(src,src_exponent,result);
94
95
/* check for inexact */
96
if (Sgl_isinexact_to_unsigned(src,src_exponent)) {
97
inexact = TRUE;
98
/* round result */
99
switch (Rounding_mode()) {
100
case ROUNDPLUS:
101
result++;
102
break;
103
case ROUNDMINUS: /* never negative */
104
break;
105
case ROUNDNEAREST:
106
if (Sgl_isone_roundbit(src,src_exponent) &&
107
(Sgl_isone_stickybit(src,src_exponent) ||
108
(result & 1))) {
109
result++;
110
}
111
break;
112
}
113
}
114
} else {
115
result = 0;
116
117
/* check for inexact */
118
if (Sgl_isnotzero_exponentmantissa(src)) {
119
inexact = TRUE;
120
/* round result */
121
switch (Rounding_mode()) {
122
case ROUNDPLUS:
123
if (Sgl_iszero_sign(src)) {
124
result++;
125
}
126
break;
127
case ROUNDMINUS:
128
if (Sgl_isone_sign(src)) {
129
result = 0;
130
if (Is_invalidtrap_enabled()) {
131
return(INVALIDEXCEPTION);
132
}
133
Set_invalidflag();
134
inexact = FALSE;
135
}
136
break;
137
case ROUNDNEAREST:
138
if (src_exponent == -1 &&
139
Sgl_isnotzero_mantissa(src)) {
140
if (Sgl_isone_sign(src)) {
141
result = 0;
142
if (Is_invalidtrap_enabled()) {
143
return(INVALIDEXCEPTION);
144
}
145
Set_invalidflag();
146
inexact = FALSE;
147
}
148
else result++;
149
}
150
break;
151
}
152
}
153
}
154
*dstptr = result;
155
if (inexact) {
156
if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION);
157
else Set_inexactflag();
158
}
159
return(NOEXCEPTION);
160
}
161
162
/*
163
* Single Floating-point to Double Unsigned Fixed
164
*/
165
/*ARGSUSED*/
166
int
167
sgl_to_dbl_fcnvfu(
168
sgl_floating_point *srcptr,
169
unsigned int *_nullptr,
170
dbl_unsigned *dstptr,
171
unsigned int *status)
172
{
173
register int src_exponent;
174
register unsigned int src, resultp1, resultp2;
175
register boolean inexact = FALSE;
176
177
src = *srcptr;
178
src_exponent = Sgl_exponent(src) - SGL_BIAS;
179
180
/*
181
* Test for overflow
182
*/
183
if (src_exponent > DBL_FX_MAX_EXP + 1) {
184
if (Sgl_isone_sign(src)) {
185
resultp1 = resultp2 = 0;
186
} else {
187
resultp1 = resultp2 = 0xffffffff;
188
}
189
if (Is_invalidtrap_enabled()) {
190
return(INVALIDEXCEPTION);
191
}
192
Set_invalidflag();
193
Duint_copytoptr(resultp1,resultp2,dstptr);
194
return(NOEXCEPTION);
195
}
196
/*
197
* Generate result
198
*/
199
if (src_exponent >= 0) {
200
/*
201
* Check sign.
202
* If negative, trap unimplemented.
203
*/
204
if (Sgl_isone_sign(src)) {
205
resultp1 = resultp2 = 0;
206
if (Is_invalidtrap_enabled()) {
207
return(INVALIDEXCEPTION);
208
}
209
Set_invalidflag();
210
Duint_copytoptr(resultp1,resultp2,dstptr);
211
return(NOEXCEPTION);
212
}
213
Sgl_clear_signexponent_set_hidden(src);
214
Duint_from_sgl_mantissa(src,src_exponent,resultp1,resultp2);
215
216
/* check for inexact */
217
if (Sgl_isinexact_to_unsigned(src,src_exponent)) {
218
inexact = TRUE;
219
/* round result */
220
switch (Rounding_mode()) {
221
case ROUNDPLUS:
222
Duint_increment(resultp1,resultp2);
223
break;
224
case ROUNDMINUS: /* never negative */
225
break;
226
case ROUNDNEAREST:
227
if (Sgl_isone_roundbit(src,src_exponent) &&
228
(Sgl_isone_stickybit(src,src_exponent) ||
229
Duint_isone_lowp2(resultp2))) {
230
Duint_increment(resultp1,resultp2);
231
}
232
break;
233
}
234
}
235
} else {
236
Duint_setzero(resultp1,resultp2);
237
238
/* check for inexact */
239
if (Sgl_isnotzero_exponentmantissa(src)) {
240
inexact = TRUE;
241
/* round result */
242
switch (Rounding_mode()) {
243
case ROUNDPLUS:
244
if (Sgl_iszero_sign(src)) {
245
Duint_increment(resultp1,resultp2);
246
}
247
break;
248
case ROUNDMINUS:
249
if (Sgl_isone_sign(src)) {
250
resultp1 = resultp2 = 0;
251
if (Is_invalidtrap_enabled()) {
252
return(INVALIDEXCEPTION);
253
}
254
Set_invalidflag();
255
inexact = FALSE;
256
}
257
break;
258
case ROUNDNEAREST:
259
if (src_exponent == -1 &&
260
Sgl_isnotzero_mantissa(src)) {
261
if (Sgl_isone_sign(src)) {
262
resultp1 = 0;
263
resultp2 = 0;
264
if (Is_invalidtrap_enabled()) {
265
return(INVALIDEXCEPTION);
266
}
267
Set_invalidflag();
268
inexact = FALSE;
269
}
270
else Duint_increment(resultp1,resultp2);
271
}
272
}
273
}
274
}
275
Duint_copytoptr(resultp1,resultp2,dstptr);
276
if (inexact) {
277
if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION);
278
else Set_inexactflag();
279
}
280
return(NOEXCEPTION);
281
}
282
283
/*
284
* Double Floating-point to Single Unsigned Fixed
285
*/
286
/*ARGSUSED*/
287
int
288
dbl_to_sgl_fcnvfu (dbl_floating_point * srcptr, unsigned int *_nullptr,
289
unsigned int *dstptr, unsigned int *status)
290
{
291
register unsigned int srcp1, srcp2, result;
292
register int src_exponent;
293
register boolean inexact = FALSE;
294
295
Dbl_copyfromptr(srcptr,srcp1,srcp2);
296
src_exponent = Dbl_exponent(srcp1) - DBL_BIAS;
297
298
/*
299
* Test for overflow
300
*/
301
if (src_exponent > SGL_FX_MAX_EXP + 1) {
302
if (Dbl_isone_sign(srcp1)) {
303
result = 0;
304
} else {
305
result = 0xffffffff;
306
}
307
if (Is_invalidtrap_enabled()) {
308
return(INVALIDEXCEPTION);
309
}
310
Set_invalidflag();
311
*dstptr = result;
312
return(NOEXCEPTION);
313
}
314
/*
315
* Generate result
316
*/
317
if (src_exponent >= 0) {
318
/*
319
* Check sign.
320
* If negative, trap unimplemented.
321
*/
322
if (Dbl_isone_sign(srcp1)) {
323
result = 0;
324
if (Is_invalidtrap_enabled()) {
325
return(INVALIDEXCEPTION);
326
}
327
Set_invalidflag();
328
*dstptr = result;
329
return(NOEXCEPTION);
330
}
331
Dbl_clear_signexponent_set_hidden(srcp1);
332
Suint_from_dbl_mantissa(srcp1,srcp2,src_exponent,result);
333
334
/* check for inexact */
335
if (Dbl_isinexact_to_unsigned(srcp1,srcp2,src_exponent)) {
336
inexact = TRUE;
337
/* round result */
338
switch (Rounding_mode()) {
339
case ROUNDPLUS:
340
result++;
341
break;
342
case ROUNDMINUS: /* never negative */
343
break;
344
case ROUNDNEAREST:
345
if(Dbl_isone_roundbit(srcp1,srcp2,src_exponent) &&
346
(Dbl_isone_stickybit(srcp1,srcp2,src_exponent)||
347
result&1))
348
result++;
349
break;
350
}
351
/* check for overflow */
352
if (result == 0) {
353
result = 0xffffffff;
354
if (Is_invalidtrap_enabled()) {
355
return(INVALIDEXCEPTION);
356
}
357
Set_invalidflag();
358
*dstptr = result;
359
return(NOEXCEPTION);
360
}
361
}
362
} else {
363
result = 0;
364
365
/* check for inexact */
366
if (Dbl_isnotzero_exponentmantissa(srcp1,srcp2)) {
367
inexact = TRUE;
368
/* round result */
369
switch (Rounding_mode()) {
370
case ROUNDPLUS:
371
if (Dbl_iszero_sign(srcp1)) result++;
372
break;
373
case ROUNDMINUS:
374
if (Dbl_isone_sign(srcp1)) {
375
result = 0;
376
if (Is_invalidtrap_enabled()) {
377
return(INVALIDEXCEPTION);
378
}
379
Set_invalidflag();
380
inexact = FALSE;
381
}
382
break;
383
case ROUNDNEAREST:
384
if (src_exponent == -1 &&
385
Dbl_isnotzero_mantissa(srcp1,srcp2))
386
if (Dbl_isone_sign(srcp1)) {
387
result = 0;
388
if (Is_invalidtrap_enabled()) {
389
return(INVALIDEXCEPTION);
390
}
391
Set_invalidflag();
392
inexact = FALSE;
393
}
394
else result++;
395
}
396
}
397
}
398
*dstptr = result;
399
if (inexact) {
400
if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION);
401
else Set_inexactflag();
402
}
403
return(NOEXCEPTION);
404
}
405
406
/*
407
* Double Floating-point to Double Unsigned Fixed
408
*/
409
/*ARGSUSED*/
410
int
411
dbl_to_dbl_fcnvfu (dbl_floating_point * srcptr, unsigned int *_nullptr,
412
dbl_unsigned * dstptr, unsigned int *status)
413
{
414
register int src_exponent;
415
register unsigned int srcp1, srcp2, resultp1, resultp2;
416
register boolean inexact = FALSE;
417
418
Dbl_copyfromptr(srcptr,srcp1,srcp2);
419
src_exponent = Dbl_exponent(srcp1) - DBL_BIAS;
420
421
/*
422
* Test for overflow
423
*/
424
if (src_exponent > DBL_FX_MAX_EXP + 1) {
425
if (Dbl_isone_sign(srcp1)) {
426
resultp1 = resultp2 = 0;
427
} else {
428
resultp1 = resultp2 = 0xffffffff;
429
}
430
if (Is_invalidtrap_enabled()) {
431
return(INVALIDEXCEPTION);
432
}
433
Set_invalidflag();
434
Duint_copytoptr(resultp1,resultp2,dstptr);
435
return(NOEXCEPTION);
436
}
437
438
/*
439
* Generate result
440
*/
441
if (src_exponent >= 0) {
442
/*
443
* Check sign.
444
* If negative, trap unimplemented.
445
*/
446
if (Dbl_isone_sign(srcp1)) {
447
resultp1 = resultp2 = 0;
448
if (Is_invalidtrap_enabled()) {
449
return(INVALIDEXCEPTION);
450
}
451
Set_invalidflag();
452
Duint_copytoptr(resultp1,resultp2,dstptr);
453
return(NOEXCEPTION);
454
}
455
Dbl_clear_signexponent_set_hidden(srcp1);
456
Duint_from_dbl_mantissa(srcp1,srcp2,src_exponent,resultp1,
457
resultp2);
458
459
/* check for inexact */
460
if (Dbl_isinexact_to_unsigned(srcp1,srcp2,src_exponent)) {
461
inexact = TRUE;
462
/* round result */
463
switch (Rounding_mode()) {
464
case ROUNDPLUS:
465
Duint_increment(resultp1,resultp2);
466
break;
467
case ROUNDMINUS: /* never negative */
468
break;
469
case ROUNDNEAREST:
470
if(Dbl_isone_roundbit(srcp1,srcp2,src_exponent))
471
if(Dbl_isone_stickybit(srcp1,srcp2,src_exponent) ||
472
Duint_isone_lowp2(resultp2))
473
Duint_increment(resultp1,resultp2);
474
}
475
}
476
} else {
477
Duint_setzero(resultp1,resultp2);
478
479
/* check for inexact */
480
if (Dbl_isnotzero_exponentmantissa(srcp1,srcp2)) {
481
inexact = TRUE;
482
/* round result */
483
switch (Rounding_mode()) {
484
case ROUNDPLUS:
485
if (Dbl_iszero_sign(srcp1)) {
486
Duint_increment(resultp1,resultp2);
487
}
488
break;
489
case ROUNDMINUS:
490
if (Dbl_isone_sign(srcp1)) {
491
resultp1 = resultp2 = 0;
492
if (Is_invalidtrap_enabled()) {
493
return(INVALIDEXCEPTION);
494
}
495
Set_invalidflag();
496
inexact = FALSE;
497
}
498
break;
499
case ROUNDNEAREST:
500
if (src_exponent == -1 &&
501
Dbl_isnotzero_mantissa(srcp1,srcp2))
502
if (Dbl_iszero_sign(srcp1)) {
503
Duint_increment(resultp1,resultp2);
504
} else {
505
resultp1 = 0;
506
resultp2 = 0;
507
if (Is_invalidtrap_enabled()) {
508
return(INVALIDEXCEPTION);
509
}
510
Set_invalidflag();
511
inexact = FALSE;
512
}
513
}
514
}
515
}
516
Duint_copytoptr(resultp1,resultp2,dstptr);
517
if (inexact) {
518
if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION);
519
else Set_inexactflag();
520
}
521
return(NOEXCEPTION);
522
}
523
524
525