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