Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/include/math-emu/op-1.h
26282 views
1
/* Software floating-point emulation.
2
Basic one-word fraction declaration and manipulation.
3
Copyright (C) 1997,1998,1999 Free Software Foundation, Inc.
4
This file is part of the GNU C Library.
5
Contributed by Richard Henderson ([email protected]),
6
Jakub Jelinek ([email protected]),
7
David S. Miller ([email protected]) and
8
Peter Maydell ([email protected]).
9
10
The GNU C Library is free software; you can redistribute it and/or
11
modify it under the terms of the GNU Library General Public License as
12
published by the Free Software Foundation; either version 2 of the
13
License, or (at your option) any later version.
14
15
The GNU C Library is distributed in the hope that it will be useful,
16
but WITHOUT ANY WARRANTY; without even the implied warranty of
17
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18
Library General Public License for more details.
19
20
You should have received a copy of the GNU Library General Public
21
License along with the GNU C Library; see the file COPYING.LIB. If
22
not, write to the Free Software Foundation, Inc.,
23
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
24
25
#ifndef __MATH_EMU_OP_1_H__
26
#define __MATH_EMU_OP_1_H__
27
28
#define _FP_FRAC_DECL_1(X) _FP_W_TYPE X##_f=0
29
#define _FP_FRAC_COPY_1(D,S) (D##_f = S##_f)
30
#define _FP_FRAC_SET_1(X,I) (X##_f = I)
31
#define _FP_FRAC_HIGH_1(X) (X##_f)
32
#define _FP_FRAC_LOW_1(X) (X##_f)
33
#define _FP_FRAC_WORD_1(X,w) (X##_f)
34
35
#define _FP_FRAC_ADDI_1(X,I) (X##_f += I)
36
#define _FP_FRAC_SLL_1(X,N) \
37
do { \
38
if (__builtin_constant_p(N) && (N) == 1) \
39
X##_f += X##_f; \
40
else \
41
X##_f <<= (N); \
42
} while (0)
43
#define _FP_FRAC_SRL_1(X,N) (X##_f >>= N)
44
45
/* Right shift with sticky-lsb. */
46
#define _FP_FRAC_SRS_1(X,N,sz) __FP_FRAC_SRS_1(X##_f, N, sz)
47
48
#define __FP_FRAC_SRS_1(X,N,sz) \
49
(X = (X >> (N) | (__builtin_constant_p(N) && (N) == 1 \
50
? X & 1 : (X << (_FP_W_TYPE_SIZE - (N))) != 0)))
51
52
#define _FP_FRAC_ADD_1(R,X,Y) (R##_f = X##_f + Y##_f)
53
#define _FP_FRAC_SUB_1(R,X,Y) (R##_f = X##_f - Y##_f)
54
#define _FP_FRAC_DEC_1(X,Y) (X##_f -= Y##_f)
55
#define _FP_FRAC_CLZ_1(z, X) __FP_CLZ(z, X##_f)
56
57
/* Predicates */
58
#define _FP_FRAC_NEGP_1(X) ((_FP_WS_TYPE)X##_f < 0)
59
#define _FP_FRAC_ZEROP_1(X) (X##_f == 0)
60
#define _FP_FRAC_OVERP_1(fs,X) (X##_f & _FP_OVERFLOW_##fs)
61
#define _FP_FRAC_CLEAR_OVERP_1(fs,X) (X##_f &= ~_FP_OVERFLOW_##fs)
62
#define _FP_FRAC_EQ_1(X, Y) (X##_f == Y##_f)
63
#define _FP_FRAC_GE_1(X, Y) (X##_f >= Y##_f)
64
#define _FP_FRAC_GT_1(X, Y) (X##_f > Y##_f)
65
66
#define _FP_ZEROFRAC_1 0
67
#define _FP_MINFRAC_1 1
68
#define _FP_MAXFRAC_1 (~(_FP_WS_TYPE)0)
69
70
/*
71
* Unpack the raw bits of a native fp value. Do not classify or
72
* normalize the data.
73
*/
74
75
#define _FP_UNPACK_RAW_1(fs, X, val) \
76
do { \
77
union _FP_UNION_##fs _flo; _flo.flt = (val); \
78
\
79
X##_f = _flo.bits.frac; \
80
X##_e = _flo.bits.exp; \
81
X##_s = _flo.bits.sign; \
82
} while (0)
83
84
#define _FP_UNPACK_RAW_1_P(fs, X, val) \
85
do { \
86
union _FP_UNION_##fs *_flo = \
87
(union _FP_UNION_##fs *)(val); \
88
\
89
X##_f = _flo->bits.frac; \
90
X##_e = _flo->bits.exp; \
91
X##_s = _flo->bits.sign; \
92
} while (0)
93
94
/*
95
* Repack the raw bits of a native fp value.
96
*/
97
98
#define _FP_PACK_RAW_1(fs, val, X) \
99
do { \
100
union _FP_UNION_##fs _flo; \
101
\
102
_flo.bits.frac = X##_f; \
103
_flo.bits.exp = X##_e; \
104
_flo.bits.sign = X##_s; \
105
\
106
(val) = _flo.flt; \
107
} while (0)
108
109
#define _FP_PACK_RAW_1_P(fs, val, X) \
110
do { \
111
union _FP_UNION_##fs *_flo = \
112
(union _FP_UNION_##fs *)(val); \
113
\
114
_flo->bits.frac = X##_f; \
115
_flo->bits.exp = X##_e; \
116
_flo->bits.sign = X##_s; \
117
} while (0)
118
119
120
/*
121
* Multiplication algorithms:
122
*/
123
124
/* Basic. Assuming the host word size is >= 2*FRACBITS, we can do the
125
multiplication immediately. */
126
127
#define _FP_MUL_MEAT_1_imm(wfracbits, R, X, Y) \
128
do { \
129
R##_f = X##_f * Y##_f; \
130
/* Normalize since we know where the msb of the multiplicands \
131
were (bit B), we know that the msb of the of the product is \
132
at either 2B or 2B-1. */ \
133
_FP_FRAC_SRS_1(R, wfracbits-1, 2*wfracbits); \
134
} while (0)
135
136
/* Given a 1W * 1W => 2W primitive, do the extended multiplication. */
137
138
#define _FP_MUL_MEAT_1_wide(wfracbits, R, X, Y, doit) \
139
do { \
140
_FP_W_TYPE _Z_f0, _Z_f1; \
141
doit(_Z_f1, _Z_f0, X##_f, Y##_f); \
142
/* Normalize since we know where the msb of the multiplicands \
143
were (bit B), we know that the msb of the of the product is \
144
at either 2B or 2B-1. */ \
145
_FP_FRAC_SRS_2(_Z, wfracbits-1, 2*wfracbits); \
146
R##_f = _Z_f0; \
147
} while (0)
148
149
/* Finally, a simple widening multiply algorithm. What fun! */
150
151
#define _FP_MUL_MEAT_1_hard(wfracbits, R, X, Y) \
152
do { \
153
_FP_W_TYPE _xh, _xl, _yh, _yl, _z_f0, _z_f1, _a_f0, _a_f1; \
154
\
155
/* split the words in half */ \
156
_xh = X##_f >> (_FP_W_TYPE_SIZE/2); \
157
_xl = X##_f & (((_FP_W_TYPE)1 << (_FP_W_TYPE_SIZE/2)) - 1); \
158
_yh = Y##_f >> (_FP_W_TYPE_SIZE/2); \
159
_yl = Y##_f & (((_FP_W_TYPE)1 << (_FP_W_TYPE_SIZE/2)) - 1); \
160
\
161
/* multiply the pieces */ \
162
_z_f0 = _xl * _yl; \
163
_a_f0 = _xh * _yl; \
164
_a_f1 = _xl * _yh; \
165
_z_f1 = _xh * _yh; \
166
\
167
/* reassemble into two full words */ \
168
if ((_a_f0 += _a_f1) < _a_f1) \
169
_z_f1 += (_FP_W_TYPE)1 << (_FP_W_TYPE_SIZE/2); \
170
_a_f1 = _a_f0 >> (_FP_W_TYPE_SIZE/2); \
171
_a_f0 = _a_f0 << (_FP_W_TYPE_SIZE/2); \
172
_FP_FRAC_ADD_2(_z, _z, _a); \
173
\
174
/* normalize */ \
175
_FP_FRAC_SRS_2(_z, wfracbits - 1, 2*wfracbits); \
176
R##_f = _z_f0; \
177
} while (0)
178
179
180
/*
181
* Division algorithms:
182
*/
183
184
/* Basic. Assuming the host word size is >= 2*FRACBITS, we can do the
185
division immediately. Give this macro either _FP_DIV_HELP_imm for
186
C primitives or _FP_DIV_HELP_ldiv for the ISO function. Which you
187
choose will depend on what the compiler does with divrem4. */
188
189
#define _FP_DIV_MEAT_1_imm(fs, R, X, Y, doit) \
190
do { \
191
_FP_W_TYPE _q, _r; \
192
X##_f <<= (X##_f < Y##_f \
193
? R##_e--, _FP_WFRACBITS_##fs \
194
: _FP_WFRACBITS_##fs - 1); \
195
doit(_q, _r, X##_f, Y##_f); \
196
R##_f = _q | (_r != 0); \
197
} while (0)
198
199
/* GCC's longlong.h defines a 2W / 1W => (1W,1W) primitive udiv_qrnnd
200
that may be useful in this situation. This first is for a primitive
201
that requires normalization, the second for one that does not. Look
202
for UDIV_NEEDS_NORMALIZATION to tell which your machine needs. */
203
204
#define _FP_DIV_MEAT_1_udiv_norm(fs, R, X, Y) \
205
do { \
206
_FP_W_TYPE _nh, _nl, _q, _r, _y; \
207
\
208
/* Normalize Y -- i.e. make the most significant bit set. */ \
209
_y = Y##_f << _FP_WFRACXBITS_##fs; \
210
\
211
/* Shift X op correspondingly high, that is, up one full word. */ \
212
if (X##_f < Y##_f) \
213
{ \
214
R##_e--; \
215
_nl = 0; \
216
_nh = X##_f; \
217
} \
218
else \
219
{ \
220
_nl = X##_f << (_FP_W_TYPE_SIZE - 1); \
221
_nh = X##_f >> 1; \
222
} \
223
\
224
udiv_qrnnd(_q, _r, _nh, _nl, _y); \
225
R##_f = _q | (_r != 0); \
226
} while (0)
227
228
#define _FP_DIV_MEAT_1_udiv(fs, R, X, Y) \
229
do { \
230
_FP_W_TYPE _nh, _nl, _q, _r; \
231
if (X##_f < Y##_f) \
232
{ \
233
R##_e--; \
234
_nl = X##_f << _FP_WFRACBITS_##fs; \
235
_nh = X##_f >> _FP_WFRACXBITS_##fs; \
236
} \
237
else \
238
{ \
239
_nl = X##_f << (_FP_WFRACBITS_##fs - 1); \
240
_nh = X##_f >> (_FP_WFRACXBITS_##fs + 1); \
241
} \
242
udiv_qrnnd(_q, _r, _nh, _nl, Y##_f); \
243
R##_f = _q | (_r != 0); \
244
} while (0)
245
246
247
/*
248
* Square root algorithms:
249
* We have just one right now, maybe Newton approximation
250
* should be added for those machines where division is fast.
251
*/
252
253
#define _FP_SQRT_MEAT_1(R, S, T, X, q) \
254
do { \
255
while (q != _FP_WORK_ROUND) \
256
{ \
257
T##_f = S##_f + q; \
258
if (T##_f <= X##_f) \
259
{ \
260
S##_f = T##_f + q; \
261
X##_f -= T##_f; \
262
R##_f += q; \
263
} \
264
_FP_FRAC_SLL_1(X, 1); \
265
q >>= 1; \
266
} \
267
if (X##_f) \
268
{ \
269
if (S##_f < X##_f) \
270
R##_f |= _FP_WORK_ROUND; \
271
R##_f |= _FP_WORK_STICKY; \
272
} \
273
} while (0)
274
275
/*
276
* Assembly/disassembly for converting to/from integral types.
277
* No shifting or overflow handled here.
278
*/
279
280
#define _FP_FRAC_ASSEMBLE_1(r, X, rsize) (r = X##_f)
281
#define _FP_FRAC_DISASSEMBLE_1(X, r, rsize) (X##_f = r)
282
283
284
/*
285
* Convert FP values between word sizes
286
*/
287
288
#define _FP_FRAC_CONV_1_1(dfs, sfs, D, S) \
289
do { \
290
D##_f = S##_f; \
291
if (_FP_WFRACBITS_##sfs > _FP_WFRACBITS_##dfs) \
292
{ \
293
if (S##_c != FP_CLS_NAN) \
294
_FP_FRAC_SRS_1(D, (_FP_WFRACBITS_##sfs-_FP_WFRACBITS_##dfs), \
295
_FP_WFRACBITS_##sfs); \
296
else \
297
_FP_FRAC_SRL_1(D, (_FP_WFRACBITS_##sfs-_FP_WFRACBITS_##dfs)); \
298
} \
299
else \
300
D##_f <<= _FP_WFRACBITS_##dfs - _FP_WFRACBITS_##sfs; \
301
} while (0)
302
303
#endif /* __MATH_EMU_OP_1_H__ */
304
305