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