Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
awilliam
GitHub Repository: awilliam/linux-vfio
Path: blob/master/arch/parisc/math-emu/dfrem.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/dfrem.c $Revision: 1.1 $
26
*
27
* Purpose:
28
* Double Precision Floating-point Remainder
29
*
30
* External Interfaces:
31
* dbl_frem(srcptr1,srcptr2,dstptr,status)
32
*
33
* Internal Interfaces:
34
*
35
* Theory:
36
* <<please update with a overview of the operation of this file>>
37
*
38
* END_DESC
39
*/
40
41
42
43
#include "float.h"
44
#include "dbl_float.h"
45
46
/*
47
* Double Precision Floating-point Remainder
48
*/
49
50
int
51
dbl_frem (dbl_floating_point * srcptr1, dbl_floating_point * srcptr2,
52
dbl_floating_point * dstptr, unsigned int *status)
53
{
54
register unsigned int opnd1p1, opnd1p2, opnd2p1, opnd2p2;
55
register unsigned int resultp1, resultp2;
56
register int opnd1_exponent, opnd2_exponent, dest_exponent, stepcount;
57
register boolean roundup = FALSE;
58
59
Dbl_copyfromptr(srcptr1,opnd1p1,opnd1p2);
60
Dbl_copyfromptr(srcptr2,opnd2p1,opnd2p2);
61
/*
62
* check first operand for NaN's or infinity
63
*/
64
if ((opnd1_exponent = Dbl_exponent(opnd1p1)) == DBL_INFINITY_EXPONENT) {
65
if (Dbl_iszero_mantissa(opnd1p1,opnd1p2)) {
66
if (Dbl_isnotnan(opnd2p1,opnd2p2)) {
67
/* invalid since first operand is infinity */
68
if (Is_invalidtrap_enabled())
69
return(INVALIDEXCEPTION);
70
Set_invalidflag();
71
Dbl_makequietnan(resultp1,resultp2);
72
Dbl_copytoptr(resultp1,resultp2,dstptr);
73
return(NOEXCEPTION);
74
}
75
}
76
else {
77
/*
78
* is NaN; signaling or quiet?
79
*/
80
if (Dbl_isone_signaling(opnd1p1)) {
81
/* trap if INVALIDTRAP enabled */
82
if (Is_invalidtrap_enabled())
83
return(INVALIDEXCEPTION);
84
/* make NaN quiet */
85
Set_invalidflag();
86
Dbl_set_quiet(opnd1p1);
87
}
88
/*
89
* is second operand a signaling NaN?
90
*/
91
else if (Dbl_is_signalingnan(opnd2p1)) {
92
/* trap if INVALIDTRAP enabled */
93
if (Is_invalidtrap_enabled())
94
return(INVALIDEXCEPTION);
95
/* make NaN quiet */
96
Set_invalidflag();
97
Dbl_set_quiet(opnd2p1);
98
Dbl_copytoptr(opnd2p1,opnd2p2,dstptr);
99
return(NOEXCEPTION);
100
}
101
/*
102
* return quiet NaN
103
*/
104
Dbl_copytoptr(opnd1p1,opnd1p2,dstptr);
105
return(NOEXCEPTION);
106
}
107
}
108
/*
109
* check second operand for NaN's or infinity
110
*/
111
if ((opnd2_exponent = Dbl_exponent(opnd2p1)) == DBL_INFINITY_EXPONENT) {
112
if (Dbl_iszero_mantissa(opnd2p1,opnd2p2)) {
113
/*
114
* return first operand
115
*/
116
Dbl_copytoptr(opnd1p1,opnd1p2,dstptr);
117
return(NOEXCEPTION);
118
}
119
/*
120
* is NaN; signaling or quiet?
121
*/
122
if (Dbl_isone_signaling(opnd2p1)) {
123
/* trap if INVALIDTRAP enabled */
124
if (Is_invalidtrap_enabled()) return(INVALIDEXCEPTION);
125
/* make NaN quiet */
126
Set_invalidflag();
127
Dbl_set_quiet(opnd2p1);
128
}
129
/*
130
* return quiet NaN
131
*/
132
Dbl_copytoptr(opnd2p1,opnd2p2,dstptr);
133
return(NOEXCEPTION);
134
}
135
/*
136
* check second operand for zero
137
*/
138
if (Dbl_iszero_exponentmantissa(opnd2p1,opnd2p2)) {
139
/* invalid since second operand is zero */
140
if (Is_invalidtrap_enabled()) return(INVALIDEXCEPTION);
141
Set_invalidflag();
142
Dbl_makequietnan(resultp1,resultp2);
143
Dbl_copytoptr(resultp1,resultp2,dstptr);
144
return(NOEXCEPTION);
145
}
146
147
/*
148
* get sign of result
149
*/
150
resultp1 = opnd1p1;
151
152
/*
153
* check for denormalized operands
154
*/
155
if (opnd1_exponent == 0) {
156
/* check for zero */
157
if (Dbl_iszero_mantissa(opnd1p1,opnd1p2)) {
158
Dbl_copytoptr(opnd1p1,opnd1p2,dstptr);
159
return(NOEXCEPTION);
160
}
161
/* normalize, then continue */
162
opnd1_exponent = 1;
163
Dbl_normalize(opnd1p1,opnd1p2,opnd1_exponent);
164
}
165
else {
166
Dbl_clear_signexponent_set_hidden(opnd1p1);
167
}
168
if (opnd2_exponent == 0) {
169
/* normalize, then continue */
170
opnd2_exponent = 1;
171
Dbl_normalize(opnd2p1,opnd2p2,opnd2_exponent);
172
}
173
else {
174
Dbl_clear_signexponent_set_hidden(opnd2p1);
175
}
176
177
/* find result exponent and divide step loop count */
178
dest_exponent = opnd2_exponent - 1;
179
stepcount = opnd1_exponent - opnd2_exponent;
180
181
/*
182
* check for opnd1/opnd2 < 1
183
*/
184
if (stepcount < 0) {
185
/*
186
* check for opnd1/opnd2 > 1/2
187
*
188
* In this case n will round to 1, so
189
* r = opnd1 - opnd2
190
*/
191
if (stepcount == -1 &&
192
Dbl_isgreaterthan(opnd1p1,opnd1p2,opnd2p1,opnd2p2)) {
193
/* set sign */
194
Dbl_allp1(resultp1) = ~Dbl_allp1(resultp1);
195
/* align opnd2 with opnd1 */
196
Dbl_leftshiftby1(opnd2p1,opnd2p2);
197
Dbl_subtract(opnd2p1,opnd2p2,opnd1p1,opnd1p2,
198
opnd2p1,opnd2p2);
199
/* now normalize */
200
while (Dbl_iszero_hidden(opnd2p1)) {
201
Dbl_leftshiftby1(opnd2p1,opnd2p2);
202
dest_exponent--;
203
}
204
Dbl_set_exponentmantissa(resultp1,resultp2,opnd2p1,opnd2p2);
205
goto testforunderflow;
206
}
207
/*
208
* opnd1/opnd2 <= 1/2
209
*
210
* In this case n will round to zero, so
211
* r = opnd1
212
*/
213
Dbl_set_exponentmantissa(resultp1,resultp2,opnd1p1,opnd1p2);
214
dest_exponent = opnd1_exponent;
215
goto testforunderflow;
216
}
217
218
/*
219
* Generate result
220
*
221
* Do iterative subtract until remainder is less than operand 2.
222
*/
223
while (stepcount-- > 0 && (Dbl_allp1(opnd1p1) || Dbl_allp2(opnd1p2))) {
224
if (Dbl_isnotlessthan(opnd1p1,opnd1p2,opnd2p1,opnd2p2)) {
225
Dbl_subtract(opnd1p1,opnd1p2,opnd2p1,opnd2p2,opnd1p1,opnd1p2);
226
}
227
Dbl_leftshiftby1(opnd1p1,opnd1p2);
228
}
229
/*
230
* Do last subtract, then determine which way to round if remainder
231
* is exactly 1/2 of opnd2
232
*/
233
if (Dbl_isnotlessthan(opnd1p1,opnd1p2,opnd2p1,opnd2p2)) {
234
Dbl_subtract(opnd1p1,opnd1p2,opnd2p1,opnd2p2,opnd1p1,opnd1p2);
235
roundup = TRUE;
236
}
237
if (stepcount > 0 || Dbl_iszero(opnd1p1,opnd1p2)) {
238
/* division is exact, remainder is zero */
239
Dbl_setzero_exponentmantissa(resultp1,resultp2);
240
Dbl_copytoptr(resultp1,resultp2,dstptr);
241
return(NOEXCEPTION);
242
}
243
244
/*
245
* Check for cases where opnd1/opnd2 < n
246
*
247
* In this case the result's sign will be opposite that of
248
* opnd1. The mantissa also needs some correction.
249
*/
250
Dbl_leftshiftby1(opnd1p1,opnd1p2);
251
if (Dbl_isgreaterthan(opnd1p1,opnd1p2,opnd2p1,opnd2p2)) {
252
Dbl_invert_sign(resultp1);
253
Dbl_leftshiftby1(opnd2p1,opnd2p2);
254
Dbl_subtract(opnd2p1,opnd2p2,opnd1p1,opnd1p2,opnd1p1,opnd1p2);
255
}
256
/* check for remainder being exactly 1/2 of opnd2 */
257
else if (Dbl_isequal(opnd1p1,opnd1p2,opnd2p1,opnd2p2) && roundup) {
258
Dbl_invert_sign(resultp1);
259
}
260
261
/* normalize result's mantissa */
262
while (Dbl_iszero_hidden(opnd1p1)) {
263
dest_exponent--;
264
Dbl_leftshiftby1(opnd1p1,opnd1p2);
265
}
266
Dbl_set_exponentmantissa(resultp1,resultp2,opnd1p1,opnd1p2);
267
268
/*
269
* Test for underflow
270
*/
271
testforunderflow:
272
if (dest_exponent <= 0) {
273
/* trap if UNDERFLOWTRAP enabled */
274
if (Is_underflowtrap_enabled()) {
275
/*
276
* Adjust bias of result
277
*/
278
Dbl_setwrapped_exponent(resultp1,dest_exponent,unfl);
279
/* frem is always exact */
280
Dbl_copytoptr(resultp1,resultp2,dstptr);
281
return(UNDERFLOWEXCEPTION);
282
}
283
/*
284
* denormalize result or set to signed zero
285
*/
286
if (dest_exponent >= (1 - DBL_P)) {
287
Dbl_rightshift_exponentmantissa(resultp1,resultp2,
288
1-dest_exponent);
289
}
290
else {
291
Dbl_setzero_exponentmantissa(resultp1,resultp2);
292
}
293
}
294
else Dbl_set_exponent(resultp1,dest_exponent);
295
Dbl_copytoptr(resultp1,resultp2,dstptr);
296
return(NOEXCEPTION);
297
}
298
299