Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/arch/mips/math-emu/dp_sub.c
26439 views
1
// SPDX-License-Identifier: GPL-2.0-only
2
/* IEEE754 floating point arithmetic
3
* double precision: common utilities
4
*/
5
/*
6
* MIPS floating point support
7
* Copyright (C) 1994-2000 Algorithmics Ltd.
8
*/
9
10
#include "ieee754dp.h"
11
12
union ieee754dp ieee754dp_sub(union ieee754dp x, union ieee754dp y)
13
{
14
int s;
15
16
COMPXDP;
17
COMPYDP;
18
19
EXPLODEXDP;
20
EXPLODEYDP;
21
22
ieee754_clearcx();
23
24
FLUSHXDP;
25
FLUSHYDP;
26
27
switch (CLPAIR(xc, yc)) {
28
case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_SNAN):
29
case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_SNAN):
30
case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_SNAN):
31
case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_SNAN):
32
case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_SNAN):
33
return ieee754dp_nanxcpt(y);
34
35
case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_SNAN):
36
case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_QNAN):
37
case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_ZERO):
38
case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_NORM):
39
case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_DNORM):
40
case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_INF):
41
return ieee754dp_nanxcpt(x);
42
43
case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_QNAN):
44
case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_QNAN):
45
case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_QNAN):
46
case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_QNAN):
47
return y;
48
49
case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_QNAN):
50
case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_ZERO):
51
case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_NORM):
52
case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_DNORM):
53
case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_INF):
54
return x;
55
56
57
/*
58
* Infinity handling
59
*/
60
case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_INF):
61
if (xs != ys)
62
return x;
63
ieee754_setcx(IEEE754_INVALID_OPERATION);
64
return ieee754dp_indef();
65
66
case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_INF):
67
case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_INF):
68
case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_INF):
69
return ieee754dp_inf(ys ^ 1);
70
71
case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_ZERO):
72
case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_NORM):
73
case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_DNORM):
74
return x;
75
76
/*
77
* Zero handling
78
*/
79
case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_ZERO):
80
if (xs != ys)
81
return x;
82
else
83
return ieee754dp_zero(ieee754_csr.rm == FPU_CSR_RD);
84
85
case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_ZERO):
86
case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_ZERO):
87
return x;
88
89
case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_NORM):
90
case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_DNORM):
91
/* quick fix up */
92
DPSIGN(y) ^= 1;
93
return y;
94
95
case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_DNORM):
96
DPDNORMX;
97
fallthrough;
98
case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_DNORM):
99
/* normalize ym,ye */
100
DPDNORMY;
101
break;
102
103
case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_NORM):
104
/* normalize xm,xe */
105
DPDNORMX;
106
break;
107
108
case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_NORM):
109
break;
110
}
111
/* flip sign of y and handle as add */
112
ys ^= 1;
113
114
assert(xm & DP_HIDDEN_BIT);
115
assert(ym & DP_HIDDEN_BIT);
116
117
118
/* provide guard,round and stick bit dpace */
119
xm <<= 3;
120
ym <<= 3;
121
122
if (xe > ye) {
123
/*
124
* Have to shift y fraction right to align
125
*/
126
s = xe - ye;
127
ym = XDPSRS(ym, s);
128
ye += s;
129
} else if (ye > xe) {
130
/*
131
* Have to shift x fraction right to align
132
*/
133
s = ye - xe;
134
xm = XDPSRS(xm, s);
135
xe += s;
136
}
137
assert(xe == ye);
138
assert(xe <= DP_EMAX);
139
140
if (xs == ys) {
141
/* generate 28 bit result of adding two 27 bit numbers
142
*/
143
xm = xm + ym;
144
145
if (xm >> (DP_FBITS + 1 + 3)) { /* carry out */
146
xm = XDPSRS1(xm); /* shift preserving sticky */
147
xe++;
148
}
149
} else {
150
if (xm >= ym) {
151
xm = xm - ym;
152
} else {
153
xm = ym - xm;
154
xs = ys;
155
}
156
if (xm == 0) {
157
if (ieee754_csr.rm == FPU_CSR_RD)
158
return ieee754dp_zero(1); /* round negative inf. => sign = -1 */
159
else
160
return ieee754dp_zero(0); /* other round modes => sign = 1 */
161
}
162
163
/* normalize to rounding precision
164
*/
165
while ((xm >> (DP_FBITS + 3)) == 0) {
166
xm <<= 1;
167
xe--;
168
}
169
}
170
171
return ieee754dp_format(xs, xe, xm);
172
}
173
174