Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/arch/mips/math-emu/sp_sub.c
26424 views
1
// SPDX-License-Identifier: GPL-2.0-only
2
/* IEEE754 floating point arithmetic
3
* single precision
4
*/
5
/*
6
* MIPS floating point support
7
* Copyright (C) 1994-2000 Algorithmics Ltd.
8
*/
9
10
#include "ieee754sp.h"
11
12
union ieee754sp ieee754sp_sub(union ieee754sp x, union ieee754sp y)
13
{
14
int s;
15
16
COMPXSP;
17
COMPYSP;
18
19
EXPLODEXSP;
20
EXPLODEYSP;
21
22
ieee754_clearcx();
23
24
FLUSHXSP;
25
FLUSHYSP;
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 ieee754sp_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 ieee754sp_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 ieee754sp_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 ieee754sp_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 ieee754sp_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
SPSIGN(y) ^= 1;
93
return y;
94
95
case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_DNORM):
96
SPDNORMX;
97
fallthrough;
98
case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_DNORM):
99
SPDNORMY;
100
break;
101
102
case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_NORM):
103
SPDNORMX;
104
break;
105
106
case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_NORM):
107
break;
108
}
109
/* flip sign of y and handle as add */
110
ys ^= 1;
111
112
assert(xm & SP_HIDDEN_BIT);
113
assert(ym & SP_HIDDEN_BIT);
114
115
116
/* provide guard,round and stick bit space */
117
xm <<= 3;
118
ym <<= 3;
119
120
if (xe > ye) {
121
/*
122
* have to shift y fraction right to align
123
*/
124
s = xe - ye;
125
ym = XSPSRS(ym, s);
126
ye += s;
127
} else if (ye > xe) {
128
/*
129
* have to shift x fraction right to align
130
*/
131
s = ye - xe;
132
xm = XSPSRS(xm, s);
133
xe += s;
134
}
135
assert(xe == ye);
136
assert(xe <= SP_EMAX);
137
138
if (xs == ys) {
139
/* generate 28 bit result of adding two 27 bit numbers
140
*/
141
xm = xm + ym;
142
143
if (xm >> (SP_FBITS + 1 + 3)) { /* carry out */
144
SPXSRSX1(); /* shift preserving sticky */
145
}
146
} else {
147
if (xm >= ym) {
148
xm = xm - ym;
149
} else {
150
xm = ym - xm;
151
xs = ys;
152
}
153
if (xm == 0) {
154
if (ieee754_csr.rm == FPU_CSR_RD)
155
return ieee754sp_zero(1); /* round negative inf. => sign = -1 */
156
else
157
return ieee754sp_zero(0); /* other round modes => sign = 1 */
158
}
159
/* normalize to rounding precision
160
*/
161
while ((xm >> (SP_FBITS + 3)) == 0) {
162
xm <<= 1;
163
xe--;
164
}
165
}
166
167
return ieee754sp_format(xs, xe, xm);
168
}
169
170