Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
awilliam
GitHub Repository: awilliam/linux-vfio
Path: blob/master/arch/parisc/math-emu/frnd.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
* Purpose:
25
* Single Floating-point Round to Integer
26
* Double Floating-point Round to Integer
27
* Quad Floating-point Round to Integer (returns unimplemented)
28
*
29
* External Interfaces:
30
* dbl_frnd(srcptr,nullptr,dstptr,status)
31
* sgl_frnd(srcptr,nullptr,dstptr,status)
32
*
33
* END_DESC
34
*/
35
36
37
#include "float.h"
38
#include "sgl_float.h"
39
#include "dbl_float.h"
40
#include "cnv_float.h"
41
42
/*
43
* Single Floating-point Round to Integer
44
*/
45
46
/*ARGSUSED*/
47
int
48
sgl_frnd(sgl_floating_point *srcptr,
49
unsigned int *nullptr,
50
sgl_floating_point *dstptr,
51
unsigned int *status)
52
{
53
register unsigned int src, result;
54
register int src_exponent;
55
register boolean inexact = FALSE;
56
57
src = *srcptr;
58
/*
59
* check source operand for NaN or infinity
60
*/
61
if ((src_exponent = Sgl_exponent(src)) == SGL_INFINITY_EXPONENT) {
62
/*
63
* is signaling NaN?
64
*/
65
if (Sgl_isone_signaling(src)) {
66
/* trap if INVALIDTRAP enabled */
67
if (Is_invalidtrap_enabled()) return(INVALIDEXCEPTION);
68
/* make NaN quiet */
69
Set_invalidflag();
70
Sgl_set_quiet(src);
71
}
72
/*
73
* return quiet NaN or infinity
74
*/
75
*dstptr = src;
76
return(NOEXCEPTION);
77
}
78
/*
79
* Need to round?
80
*/
81
if ((src_exponent -= SGL_BIAS) >= SGL_P - 1) {
82
*dstptr = src;
83
return(NOEXCEPTION);
84
}
85
/*
86
* Generate result
87
*/
88
if (src_exponent >= 0) {
89
Sgl_clear_exponent_set_hidden(src);
90
result = src;
91
Sgl_rightshift(result,(SGL_P-1) - (src_exponent));
92
/* check for inexact */
93
if (Sgl_isinexact_to_fix(src,src_exponent)) {
94
inexact = TRUE;
95
/* round result */
96
switch (Rounding_mode()) {
97
case ROUNDPLUS:
98
if (Sgl_iszero_sign(src)) Sgl_increment(result);
99
break;
100
case ROUNDMINUS:
101
if (Sgl_isone_sign(src)) Sgl_increment(result);
102
break;
103
case ROUNDNEAREST:
104
if (Sgl_isone_roundbit(src,src_exponent))
105
if (Sgl_isone_stickybit(src,src_exponent)
106
|| (Sgl_isone_lowmantissa(result)))
107
Sgl_increment(result);
108
}
109
}
110
Sgl_leftshift(result,(SGL_P-1) - (src_exponent));
111
if (Sgl_isone_hiddenoverflow(result))
112
Sgl_set_exponent(result,src_exponent + (SGL_BIAS+1));
113
else Sgl_set_exponent(result,src_exponent + SGL_BIAS);
114
}
115
else {
116
result = src; /* set sign */
117
Sgl_setzero_exponentmantissa(result);
118
/* check for inexact */
119
if (Sgl_isnotzero_exponentmantissa(src)) {
120
inexact = TRUE;
121
/* round result */
122
switch (Rounding_mode()) {
123
case ROUNDPLUS:
124
if (Sgl_iszero_sign(src))
125
Sgl_set_exponent(result,SGL_BIAS);
126
break;
127
case ROUNDMINUS:
128
if (Sgl_isone_sign(src))
129
Sgl_set_exponent(result,SGL_BIAS);
130
break;
131
case ROUNDNEAREST:
132
if (src_exponent == -1)
133
if (Sgl_isnotzero_mantissa(src))
134
Sgl_set_exponent(result,SGL_BIAS);
135
}
136
}
137
}
138
*dstptr = result;
139
if (inexact) {
140
if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION);
141
else Set_inexactflag();
142
}
143
return(NOEXCEPTION);
144
}
145
146
/*
147
* Double Floating-point Round to Integer
148
*/
149
150
/*ARGSUSED*/
151
int
152
dbl_frnd(
153
dbl_floating_point *srcptr,
154
unsigned int *nullptr,
155
dbl_floating_point *dstptr,
156
unsigned int *status)
157
{
158
register unsigned int srcp1, srcp2, resultp1, resultp2;
159
register int src_exponent;
160
register boolean inexact = FALSE;
161
162
Dbl_copyfromptr(srcptr,srcp1,srcp2);
163
/*
164
* check source operand for NaN or infinity
165
*/
166
if ((src_exponent = Dbl_exponent(srcp1)) == DBL_INFINITY_EXPONENT) {
167
/*
168
* is signaling NaN?
169
*/
170
if (Dbl_isone_signaling(srcp1)) {
171
/* trap if INVALIDTRAP enabled */
172
if (Is_invalidtrap_enabled()) return(INVALIDEXCEPTION);
173
/* make NaN quiet */
174
Set_invalidflag();
175
Dbl_set_quiet(srcp1);
176
}
177
/*
178
* return quiet NaN or infinity
179
*/
180
Dbl_copytoptr(srcp1,srcp2,dstptr);
181
return(NOEXCEPTION);
182
}
183
/*
184
* Need to round?
185
*/
186
if ((src_exponent -= DBL_BIAS) >= DBL_P - 1) {
187
Dbl_copytoptr(srcp1,srcp2,dstptr);
188
return(NOEXCEPTION);
189
}
190
/*
191
* Generate result
192
*/
193
if (src_exponent >= 0) {
194
Dbl_clear_exponent_set_hidden(srcp1);
195
resultp1 = srcp1;
196
resultp2 = srcp2;
197
Dbl_rightshift(resultp1,resultp2,(DBL_P-1) - (src_exponent));
198
/* check for inexact */
199
if (Dbl_isinexact_to_fix(srcp1,srcp2,src_exponent)) {
200
inexact = TRUE;
201
/* round result */
202
switch (Rounding_mode()) {
203
case ROUNDPLUS:
204
if (Dbl_iszero_sign(srcp1))
205
Dbl_increment(resultp1,resultp2);
206
break;
207
case ROUNDMINUS:
208
if (Dbl_isone_sign(srcp1))
209
Dbl_increment(resultp1,resultp2);
210
break;
211
case ROUNDNEAREST:
212
if (Dbl_isone_roundbit(srcp1,srcp2,src_exponent))
213
if (Dbl_isone_stickybit(srcp1,srcp2,src_exponent)
214
|| (Dbl_isone_lowmantissap2(resultp2)))
215
Dbl_increment(resultp1,resultp2);
216
}
217
}
218
Dbl_leftshift(resultp1,resultp2,(DBL_P-1) - (src_exponent));
219
if (Dbl_isone_hiddenoverflow(resultp1))
220
Dbl_set_exponent(resultp1,src_exponent + (DBL_BIAS+1));
221
else Dbl_set_exponent(resultp1,src_exponent + DBL_BIAS);
222
}
223
else {
224
resultp1 = srcp1; /* set sign */
225
Dbl_setzero_exponentmantissa(resultp1,resultp2);
226
/* check for inexact */
227
if (Dbl_isnotzero_exponentmantissa(srcp1,srcp2)) {
228
inexact = TRUE;
229
/* round result */
230
switch (Rounding_mode()) {
231
case ROUNDPLUS:
232
if (Dbl_iszero_sign(srcp1))
233
Dbl_set_exponent(resultp1,DBL_BIAS);
234
break;
235
case ROUNDMINUS:
236
if (Dbl_isone_sign(srcp1))
237
Dbl_set_exponent(resultp1,DBL_BIAS);
238
break;
239
case ROUNDNEAREST:
240
if (src_exponent == -1)
241
if (Dbl_isnotzero_mantissa(srcp1,srcp2))
242
Dbl_set_exponent(resultp1,DBL_BIAS);
243
}
244
}
245
}
246
Dbl_copytoptr(resultp1,resultp2,dstptr);
247
if (inexact) {
248
if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION);
249
else Set_inexactflag();
250
}
251
return(NOEXCEPTION);
252
}
253
254