Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/include/math-emu/op-common.h
26278 views
1
/* Software floating-point emulation. Common operations.
2
Copyright (C) 1997,1998,1999 Free Software Foundation, Inc.
3
This file is part of the GNU C Library.
4
Contributed by Richard Henderson ([email protected]),
5
Jakub Jelinek ([email protected]),
6
David S. Miller ([email protected]) and
7
Peter Maydell ([email protected]).
8
9
The GNU C Library is free software; you can redistribute it and/or
10
modify it under the terms of the GNU Library General Public License as
11
published by the Free Software Foundation; either version 2 of the
12
License, or (at your option) any later version.
13
14
The GNU C Library is distributed in the hope that it will be useful,
15
but WITHOUT ANY WARRANTY; without even the implied warranty of
16
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17
Library General Public License for more details.
18
19
You should have received a copy of the GNU Library General Public
20
License along with the GNU C Library; see the file COPYING.LIB. If
21
not, write to the Free Software Foundation, Inc.,
22
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
23
24
#ifndef __MATH_EMU_OP_COMMON_H__
25
#define __MATH_EMU_OP_COMMON_H__
26
27
#define _FP_DECL(wc, X) \
28
_FP_I_TYPE X##_c=0, X##_s=0, X##_e=0; \
29
_FP_FRAC_DECL_##wc(X)
30
31
/*
32
* Finish truly unpacking a native fp value by classifying the kind
33
* of fp value and normalizing both the exponent and the fraction.
34
*/
35
36
#define _FP_UNPACK_CANONICAL(fs, wc, X) \
37
do { \
38
switch (X##_e) \
39
{ \
40
default: \
41
_FP_FRAC_HIGH_RAW_##fs(X) |= _FP_IMPLBIT_##fs; \
42
_FP_FRAC_SLL_##wc(X, _FP_WORKBITS); \
43
X##_e -= _FP_EXPBIAS_##fs; \
44
X##_c = FP_CLS_NORMAL; \
45
break; \
46
\
47
case 0: \
48
if (_FP_FRAC_ZEROP_##wc(X)) \
49
X##_c = FP_CLS_ZERO; \
50
else \
51
{ \
52
/* a denormalized number */ \
53
_FP_I_TYPE _shift; \
54
_FP_FRAC_CLZ_##wc(_shift, X); \
55
_shift -= _FP_FRACXBITS_##fs; \
56
_FP_FRAC_SLL_##wc(X, (_shift+_FP_WORKBITS)); \
57
X##_e -= _FP_EXPBIAS_##fs - 1 + _shift; \
58
X##_c = FP_CLS_NORMAL; \
59
FP_SET_EXCEPTION(FP_EX_DENORM); \
60
if (FP_DENORM_ZERO) \
61
{ \
62
FP_SET_EXCEPTION(FP_EX_INEXACT); \
63
X##_c = FP_CLS_ZERO; \
64
} \
65
} \
66
break; \
67
\
68
case _FP_EXPMAX_##fs: \
69
if (_FP_FRAC_ZEROP_##wc(X)) \
70
X##_c = FP_CLS_INF; \
71
else \
72
{ \
73
X##_c = FP_CLS_NAN; \
74
/* Check for signaling NaN */ \
75
if (!(_FP_FRAC_HIGH_RAW_##fs(X) & _FP_QNANBIT_##fs)) \
76
FP_SET_EXCEPTION(FP_EX_INVALID | FP_EX_INVALID_SNAN); \
77
} \
78
break; \
79
} \
80
} while (0)
81
82
/*
83
* Before packing the bits back into the native fp result, take care
84
* of such mundane things as rounding and overflow. Also, for some
85
* kinds of fp values, the original parts may not have been fully
86
* extracted -- but that is ok, we can regenerate them now.
87
*/
88
89
#define _FP_PACK_CANONICAL(fs, wc, X) \
90
do { \
91
switch (X##_c) \
92
{ \
93
case FP_CLS_NORMAL: \
94
X##_e += _FP_EXPBIAS_##fs; \
95
if (X##_e > 0) \
96
{ \
97
_FP_ROUND(wc, X); \
98
if (_FP_FRAC_OVERP_##wc(fs, X)) \
99
{ \
100
_FP_FRAC_CLEAR_OVERP_##wc(fs, X); \
101
X##_e++; \
102
} \
103
_FP_FRAC_SRL_##wc(X, _FP_WORKBITS); \
104
if (X##_e >= _FP_EXPMAX_##fs) \
105
{ \
106
/* overflow */ \
107
switch (FP_ROUNDMODE) \
108
{ \
109
case FP_RND_NEAREST: \
110
X##_c = FP_CLS_INF; \
111
break; \
112
case FP_RND_PINF: \
113
if (!X##_s) X##_c = FP_CLS_INF; \
114
break; \
115
case FP_RND_MINF: \
116
if (X##_s) X##_c = FP_CLS_INF; \
117
break; \
118
} \
119
if (X##_c == FP_CLS_INF) \
120
{ \
121
/* Overflow to infinity */ \
122
X##_e = _FP_EXPMAX_##fs; \
123
_FP_FRAC_SET_##wc(X, _FP_ZEROFRAC_##wc); \
124
} \
125
else \
126
{ \
127
/* Overflow to maximum normal */ \
128
X##_e = _FP_EXPMAX_##fs - 1; \
129
_FP_FRAC_SET_##wc(X, _FP_MAXFRAC_##wc); \
130
} \
131
FP_SET_EXCEPTION(FP_EX_OVERFLOW); \
132
FP_SET_EXCEPTION(FP_EX_INEXACT); \
133
} \
134
} \
135
else \
136
{ \
137
/* we've got a denormalized number */ \
138
X##_e = -X##_e + 1; \
139
if (X##_e <= _FP_WFRACBITS_##fs) \
140
{ \
141
_FP_FRAC_SRS_##wc(X, X##_e, _FP_WFRACBITS_##fs); \
142
if (_FP_FRAC_HIGH_##fs(X) \
143
& (_FP_OVERFLOW_##fs >> 1)) \
144
{ \
145
X##_e = 1; \
146
_FP_FRAC_SET_##wc(X, _FP_ZEROFRAC_##wc); \
147
} \
148
else \
149
{ \
150
_FP_ROUND(wc, X); \
151
if (_FP_FRAC_HIGH_##fs(X) \
152
& (_FP_OVERFLOW_##fs >> 1)) \
153
{ \
154
X##_e = 1; \
155
_FP_FRAC_SET_##wc(X, _FP_ZEROFRAC_##wc); \
156
FP_SET_EXCEPTION(FP_EX_INEXACT); \
157
} \
158
else \
159
{ \
160
X##_e = 0; \
161
_FP_FRAC_SRL_##wc(X, _FP_WORKBITS); \
162
} \
163
} \
164
if ((FP_CUR_EXCEPTIONS & FP_EX_INEXACT) || \
165
(FP_TRAPPING_EXCEPTIONS & FP_EX_UNDERFLOW)) \
166
FP_SET_EXCEPTION(FP_EX_UNDERFLOW); \
167
} \
168
else \
169
{ \
170
/* underflow to zero */ \
171
X##_e = 0; \
172
if (!_FP_FRAC_ZEROP_##wc(X)) \
173
{ \
174
_FP_FRAC_SET_##wc(X, _FP_MINFRAC_##wc); \
175
_FP_ROUND(wc, X); \
176
_FP_FRAC_LOW_##wc(X) >>= (_FP_WORKBITS); \
177
} \
178
FP_SET_EXCEPTION(FP_EX_UNDERFLOW); \
179
} \
180
} \
181
break; \
182
\
183
case FP_CLS_ZERO: \
184
X##_e = 0; \
185
_FP_FRAC_SET_##wc(X, _FP_ZEROFRAC_##wc); \
186
break; \
187
\
188
case FP_CLS_INF: \
189
X##_e = _FP_EXPMAX_##fs; \
190
_FP_FRAC_SET_##wc(X, _FP_ZEROFRAC_##wc); \
191
break; \
192
\
193
case FP_CLS_NAN: \
194
X##_e = _FP_EXPMAX_##fs; \
195
if (!_FP_KEEPNANFRACP) \
196
{ \
197
_FP_FRAC_SET_##wc(X, _FP_NANFRAC_##fs); \
198
X##_s = _FP_NANSIGN_##fs; \
199
} \
200
else \
201
_FP_FRAC_HIGH_RAW_##fs(X) |= _FP_QNANBIT_##fs; \
202
break; \
203
} \
204
} while (0)
205
206
/* This one accepts raw argument and not cooked, returns
207
* 1 if X is a signaling NaN.
208
*/
209
#define _FP_ISSIGNAN(fs, wc, X) \
210
({ \
211
int __ret = 0; \
212
if (X##_e == _FP_EXPMAX_##fs) \
213
{ \
214
if (!_FP_FRAC_ZEROP_##wc(X) \
215
&& !(_FP_FRAC_HIGH_RAW_##fs(X) & _FP_QNANBIT_##fs)) \
216
__ret = 1; \
217
} \
218
__ret; \
219
})
220
221
222
223
224
225
/*
226
* Main addition routine. The input values should be cooked.
227
*/
228
229
#define _FP_ADD_INTERNAL(fs, wc, R, X, Y, OP) \
230
do { \
231
switch (_FP_CLS_COMBINE(X##_c, Y##_c)) \
232
{ \
233
case _FP_CLS_COMBINE(FP_CLS_NORMAL,FP_CLS_NORMAL): \
234
{ \
235
/* shift the smaller number so that its exponent matches the larger */ \
236
_FP_I_TYPE diff = X##_e - Y##_e; \
237
\
238
if (diff < 0) \
239
{ \
240
diff = -diff; \
241
if (diff <= _FP_WFRACBITS_##fs) \
242
_FP_FRAC_SRS_##wc(X, diff, _FP_WFRACBITS_##fs); \
243
else if (!_FP_FRAC_ZEROP_##wc(X)) \
244
_FP_FRAC_SET_##wc(X, _FP_MINFRAC_##wc); \
245
R##_e = Y##_e; \
246
} \
247
else \
248
{ \
249
if (diff > 0) \
250
{ \
251
if (diff <= _FP_WFRACBITS_##fs) \
252
_FP_FRAC_SRS_##wc(Y, diff, _FP_WFRACBITS_##fs); \
253
else if (!_FP_FRAC_ZEROP_##wc(Y)) \
254
_FP_FRAC_SET_##wc(Y, _FP_MINFRAC_##wc); \
255
} \
256
R##_e = X##_e; \
257
} \
258
\
259
R##_c = FP_CLS_NORMAL; \
260
\
261
if (X##_s == Y##_s) \
262
{ \
263
R##_s = X##_s; \
264
_FP_FRAC_ADD_##wc(R, X, Y); \
265
if (_FP_FRAC_OVERP_##wc(fs, R)) \
266
{ \
267
_FP_FRAC_SRS_##wc(R, 1, _FP_WFRACBITS_##fs); \
268
R##_e++; \
269
} \
270
} \
271
else \
272
{ \
273
R##_s = X##_s; \
274
_FP_FRAC_SUB_##wc(R, X, Y); \
275
if (_FP_FRAC_ZEROP_##wc(R)) \
276
{ \
277
/* return an exact zero */ \
278
if (FP_ROUNDMODE == FP_RND_MINF) \
279
R##_s |= Y##_s; \
280
else \
281
R##_s &= Y##_s; \
282
R##_c = FP_CLS_ZERO; \
283
} \
284
else \
285
{ \
286
if (_FP_FRAC_NEGP_##wc(R)) \
287
{ \
288
_FP_FRAC_SUB_##wc(R, Y, X); \
289
R##_s = Y##_s; \
290
} \
291
\
292
/* renormalize after subtraction */ \
293
_FP_FRAC_CLZ_##wc(diff, R); \
294
diff -= _FP_WFRACXBITS_##fs; \
295
if (diff) \
296
{ \
297
R##_e -= diff; \
298
_FP_FRAC_SLL_##wc(R, diff); \
299
} \
300
} \
301
} \
302
break; \
303
} \
304
\
305
case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_NAN): \
306
_FP_CHOOSENAN(fs, wc, R, X, Y, OP); \
307
break; \
308
\
309
case _FP_CLS_COMBINE(FP_CLS_NORMAL,FP_CLS_ZERO): \
310
R##_e = X##_e; \
311
fallthrough; \
312
case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_NORMAL): \
313
case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_INF): \
314
case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_ZERO): \
315
_FP_FRAC_COPY_##wc(R, X); \
316
R##_s = X##_s; \
317
R##_c = X##_c; \
318
break; \
319
\
320
case _FP_CLS_COMBINE(FP_CLS_ZERO,FP_CLS_NORMAL): \
321
R##_e = Y##_e; \
322
fallthrough; \
323
case _FP_CLS_COMBINE(FP_CLS_NORMAL,FP_CLS_NAN): \
324
case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_NAN): \
325
case _FP_CLS_COMBINE(FP_CLS_ZERO,FP_CLS_NAN): \
326
_FP_FRAC_COPY_##wc(R, Y); \
327
R##_s = Y##_s; \
328
R##_c = Y##_c; \
329
break; \
330
\
331
case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_INF): \
332
if (X##_s != Y##_s) \
333
{ \
334
/* +INF + -INF => NAN */ \
335
_FP_FRAC_SET_##wc(R, _FP_NANFRAC_##fs); \
336
R##_s = _FP_NANSIGN_##fs; \
337
R##_c = FP_CLS_NAN; \
338
FP_SET_EXCEPTION(FP_EX_INVALID | FP_EX_INVALID_ISI); \
339
break; \
340
} \
341
fallthrough; \
342
\
343
case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_NORMAL): \
344
case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_ZERO): \
345
R##_s = X##_s; \
346
R##_c = FP_CLS_INF; \
347
break; \
348
\
349
case _FP_CLS_COMBINE(FP_CLS_NORMAL,FP_CLS_INF): \
350
case _FP_CLS_COMBINE(FP_CLS_ZERO,FP_CLS_INF): \
351
R##_s = Y##_s; \
352
R##_c = FP_CLS_INF; \
353
break; \
354
\
355
case _FP_CLS_COMBINE(FP_CLS_ZERO,FP_CLS_ZERO): \
356
/* make sure the sign is correct */ \
357
if (FP_ROUNDMODE == FP_RND_MINF) \
358
R##_s = X##_s | Y##_s; \
359
else \
360
R##_s = X##_s & Y##_s; \
361
R##_c = FP_CLS_ZERO; \
362
break; \
363
\
364
default: \
365
abort(); \
366
} \
367
} while (0)
368
369
#define _FP_ADD(fs, wc, R, X, Y) _FP_ADD_INTERNAL(fs, wc, R, X, Y, '+')
370
#define _FP_SUB(fs, wc, R, X, Y) \
371
do { \
372
if (Y##_c != FP_CLS_NAN) Y##_s ^= 1; \
373
_FP_ADD_INTERNAL(fs, wc, R, X, Y, '-'); \
374
} while (0)
375
376
377
/*
378
* Main negation routine. FIXME -- when we care about setting exception
379
* bits reliably, this will not do. We should examine all of the fp classes.
380
*/
381
382
#define _FP_NEG(fs, wc, R, X) \
383
do { \
384
_FP_FRAC_COPY_##wc(R, X); \
385
R##_c = X##_c; \
386
R##_e = X##_e; \
387
R##_s = 1 ^ X##_s; \
388
} while (0)
389
390
391
/*
392
* Main multiplication routine. The input values should be cooked.
393
*/
394
395
#define _FP_MUL(fs, wc, R, X, Y) \
396
do { \
397
R##_s = X##_s ^ Y##_s; \
398
switch (_FP_CLS_COMBINE(X##_c, Y##_c)) \
399
{ \
400
case _FP_CLS_COMBINE(FP_CLS_NORMAL,FP_CLS_NORMAL): \
401
R##_c = FP_CLS_NORMAL; \
402
R##_e = X##_e + Y##_e + 1; \
403
\
404
_FP_MUL_MEAT_##fs(R,X,Y); \
405
\
406
if (_FP_FRAC_OVERP_##wc(fs, R)) \
407
_FP_FRAC_SRS_##wc(R, 1, _FP_WFRACBITS_##fs); \
408
else \
409
R##_e--; \
410
break; \
411
\
412
case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_NAN): \
413
_FP_CHOOSENAN(fs, wc, R, X, Y, '*'); \
414
break; \
415
\
416
case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_NORMAL): \
417
case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_INF): \
418
case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_ZERO): \
419
R##_s = X##_s; \
420
fallthrough; \
421
\
422
case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_INF): \
423
case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_NORMAL): \
424
case _FP_CLS_COMBINE(FP_CLS_ZERO,FP_CLS_NORMAL): \
425
case _FP_CLS_COMBINE(FP_CLS_ZERO,FP_CLS_ZERO): \
426
_FP_FRAC_COPY_##wc(R, X); \
427
R##_c = X##_c; \
428
break; \
429
\
430
case _FP_CLS_COMBINE(FP_CLS_NORMAL,FP_CLS_NAN): \
431
case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_NAN): \
432
case _FP_CLS_COMBINE(FP_CLS_ZERO,FP_CLS_NAN): \
433
R##_s = Y##_s; \
434
fallthrough; \
435
\
436
case _FP_CLS_COMBINE(FP_CLS_NORMAL,FP_CLS_INF): \
437
case _FP_CLS_COMBINE(FP_CLS_NORMAL,FP_CLS_ZERO): \
438
_FP_FRAC_COPY_##wc(R, Y); \
439
R##_c = Y##_c; \
440
break; \
441
\
442
case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_ZERO): \
443
case _FP_CLS_COMBINE(FP_CLS_ZERO,FP_CLS_INF): \
444
R##_s = _FP_NANSIGN_##fs; \
445
R##_c = FP_CLS_NAN; \
446
_FP_FRAC_SET_##wc(R, _FP_NANFRAC_##fs); \
447
FP_SET_EXCEPTION(FP_EX_INVALID | FP_EX_INVALID_IMZ);\
448
break; \
449
\
450
default: \
451
abort(); \
452
} \
453
} while (0)
454
455
456
/*
457
* Main division routine. The input values should be cooked.
458
*/
459
460
#define _FP_DIV(fs, wc, R, X, Y) \
461
do { \
462
R##_s = X##_s ^ Y##_s; \
463
switch (_FP_CLS_COMBINE(X##_c, Y##_c)) \
464
{ \
465
case _FP_CLS_COMBINE(FP_CLS_NORMAL,FP_CLS_NORMAL): \
466
R##_c = FP_CLS_NORMAL; \
467
R##_e = X##_e - Y##_e; \
468
\
469
_FP_DIV_MEAT_##fs(R,X,Y); \
470
break; \
471
\
472
case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_NAN): \
473
_FP_CHOOSENAN(fs, wc, R, X, Y, '/'); \
474
break; \
475
\
476
case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_NORMAL): \
477
case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_INF): \
478
case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_ZERO): \
479
R##_s = X##_s; \
480
_FP_FRAC_COPY_##wc(R, X); \
481
R##_c = X##_c; \
482
break; \
483
\
484
case _FP_CLS_COMBINE(FP_CLS_NORMAL,FP_CLS_NAN): \
485
case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_NAN): \
486
case _FP_CLS_COMBINE(FP_CLS_ZERO,FP_CLS_NAN): \
487
R##_s = Y##_s; \
488
_FP_FRAC_COPY_##wc(R, Y); \
489
R##_c = Y##_c; \
490
break; \
491
\
492
case _FP_CLS_COMBINE(FP_CLS_NORMAL,FP_CLS_INF): \
493
case _FP_CLS_COMBINE(FP_CLS_ZERO,FP_CLS_INF): \
494
case _FP_CLS_COMBINE(FP_CLS_ZERO,FP_CLS_NORMAL): \
495
R##_c = FP_CLS_ZERO; \
496
break; \
497
\
498
case _FP_CLS_COMBINE(FP_CLS_NORMAL,FP_CLS_ZERO): \
499
FP_SET_EXCEPTION(FP_EX_DIVZERO); \
500
fallthrough; \
501
case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_ZERO): \
502
case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_NORMAL): \
503
R##_c = FP_CLS_INF; \
504
break; \
505
\
506
case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_INF): \
507
R##_s = _FP_NANSIGN_##fs; \
508
R##_c = FP_CLS_NAN; \
509
_FP_FRAC_SET_##wc(R, _FP_NANFRAC_##fs); \
510
FP_SET_EXCEPTION(FP_EX_INVALID | FP_EX_INVALID_IDI);\
511
break; \
512
\
513
case _FP_CLS_COMBINE(FP_CLS_ZERO,FP_CLS_ZERO): \
514
R##_s = _FP_NANSIGN_##fs; \
515
R##_c = FP_CLS_NAN; \
516
_FP_FRAC_SET_##wc(R, _FP_NANFRAC_##fs); \
517
FP_SET_EXCEPTION(FP_EX_INVALID | FP_EX_INVALID_ZDZ);\
518
break; \
519
\
520
default: \
521
abort(); \
522
} \
523
} while (0)
524
525
526
/*
527
* Main differential comparison routine. The inputs should be raw not
528
* cooked. The return is -1,0,1 for normal values, 2 otherwise.
529
*/
530
531
#define _FP_CMP(fs, wc, ret, X, Y, un) \
532
do { \
533
/* NANs are unordered */ \
534
if ((X##_e == _FP_EXPMAX_##fs && !_FP_FRAC_ZEROP_##wc(X)) \
535
|| (Y##_e == _FP_EXPMAX_##fs && !_FP_FRAC_ZEROP_##wc(Y))) \
536
{ \
537
ret = un; \
538
} \
539
else \
540
{ \
541
int __is_zero_x; \
542
int __is_zero_y; \
543
\
544
__is_zero_x = (!X##_e && _FP_FRAC_ZEROP_##wc(X)) ? 1 : 0; \
545
__is_zero_y = (!Y##_e && _FP_FRAC_ZEROP_##wc(Y)) ? 1 : 0; \
546
\
547
if (__is_zero_x && __is_zero_y) \
548
ret = 0; \
549
else if (__is_zero_x) \
550
ret = Y##_s ? 1 : -1; \
551
else if (__is_zero_y) \
552
ret = X##_s ? -1 : 1; \
553
else if (X##_s != Y##_s) \
554
ret = X##_s ? -1 : 1; \
555
else if (X##_e > Y##_e) \
556
ret = X##_s ? -1 : 1; \
557
else if (X##_e < Y##_e) \
558
ret = X##_s ? 1 : -1; \
559
else if (_FP_FRAC_GT_##wc(X, Y)) \
560
ret = X##_s ? -1 : 1; \
561
else if (_FP_FRAC_GT_##wc(Y, X)) \
562
ret = X##_s ? 1 : -1; \
563
else \
564
ret = 0; \
565
} \
566
} while (0)
567
568
569
/* Simplification for strict equality. */
570
571
#define _FP_CMP_EQ(fs, wc, ret, X, Y) \
572
do { \
573
/* NANs are unordered */ \
574
if ((X##_e == _FP_EXPMAX_##fs && !_FP_FRAC_ZEROP_##wc(X)) \
575
|| (Y##_e == _FP_EXPMAX_##fs && !_FP_FRAC_ZEROP_##wc(Y))) \
576
{ \
577
ret = 1; \
578
} \
579
else \
580
{ \
581
ret = !(X##_e == Y##_e \
582
&& _FP_FRAC_EQ_##wc(X, Y) \
583
&& (X##_s == Y##_s || !X##_e && _FP_FRAC_ZEROP_##wc(X))); \
584
} \
585
} while (0)
586
587
/*
588
* Main square root routine. The input value should be cooked.
589
*/
590
591
#define _FP_SQRT(fs, wc, R, X) \
592
do { \
593
_FP_FRAC_DECL_##wc(T); _FP_FRAC_DECL_##wc(S); \
594
_FP_W_TYPE q; \
595
switch (X##_c) \
596
{ \
597
case FP_CLS_NAN: \
598
_FP_FRAC_COPY_##wc(R, X); \
599
R##_s = X##_s; \
600
R##_c = FP_CLS_NAN; \
601
break; \
602
case FP_CLS_INF: \
603
if (X##_s) \
604
{ \
605
R##_s = _FP_NANSIGN_##fs; \
606
R##_c = FP_CLS_NAN; /* NAN */ \
607
_FP_FRAC_SET_##wc(R, _FP_NANFRAC_##fs); \
608
FP_SET_EXCEPTION(FP_EX_INVALID); \
609
} \
610
else \
611
{ \
612
R##_s = 0; \
613
R##_c = FP_CLS_INF; /* sqrt(+inf) = +inf */ \
614
} \
615
break; \
616
case FP_CLS_ZERO: \
617
R##_s = X##_s; \
618
R##_c = FP_CLS_ZERO; /* sqrt(+-0) = +-0 */ \
619
break; \
620
case FP_CLS_NORMAL: \
621
R##_s = 0; \
622
if (X##_s) \
623
{ \
624
R##_c = FP_CLS_NAN; /* sNAN */ \
625
R##_s = _FP_NANSIGN_##fs; \
626
_FP_FRAC_SET_##wc(R, _FP_NANFRAC_##fs); \
627
FP_SET_EXCEPTION(FP_EX_INVALID); \
628
break; \
629
} \
630
R##_c = FP_CLS_NORMAL; \
631
if (X##_e & 1) \
632
_FP_FRAC_SLL_##wc(X, 1); \
633
R##_e = X##_e >> 1; \
634
_FP_FRAC_SET_##wc(S, _FP_ZEROFRAC_##wc); \
635
_FP_FRAC_SET_##wc(R, _FP_ZEROFRAC_##wc); \
636
q = _FP_OVERFLOW_##fs >> 1; \
637
_FP_SQRT_MEAT_##wc(R, S, T, X, q); \
638
} \
639
} while (0)
640
641
/*
642
* Convert from FP to integer
643
*/
644
645
/* RSIGNED can have following values:
646
* 0: the number is required to be 0..(2^rsize)-1, if not, NV is set plus
647
* the result is either 0 or (2^rsize)-1 depending on the sign in such case.
648
* 1: the number is required to be -(2^(rsize-1))..(2^(rsize-1))-1, if not, NV is
649
* set plus the result is either -(2^(rsize-1)) or (2^(rsize-1))-1 depending
650
* on the sign in such case.
651
* 2: the number is required to be -(2^(rsize-1))..(2^(rsize-1))-1, if not, NV is
652
* set plus the result is truncated to fit into destination.
653
* -1: the number is required to be -(2^(rsize-1))..(2^rsize)-1, if not, NV is
654
* set plus the result is either -(2^(rsize-1)) or (2^(rsize-1))-1 depending
655
* on the sign in such case.
656
*/
657
#define _FP_TO_INT(fs, wc, r, X, rsize, rsigned) \
658
do { \
659
switch (X##_c) \
660
{ \
661
case FP_CLS_NORMAL: \
662
if (X##_e < 0) \
663
{ \
664
FP_SET_EXCEPTION(FP_EX_INEXACT); \
665
fallthrough; \
666
case FP_CLS_ZERO: \
667
r = 0; \
668
} \
669
else if (X##_e >= rsize - (rsigned > 0 || X##_s) \
670
|| (!rsigned && X##_s)) \
671
{ /* overflow */ \
672
fallthrough; \
673
case FP_CLS_NAN: \
674
case FP_CLS_INF: \
675
if (rsigned == 2) \
676
{ \
677
if (X##_c != FP_CLS_NORMAL \
678
|| X##_e >= rsize - 1 + _FP_WFRACBITS_##fs) \
679
r = 0; \
680
else \
681
{ \
682
_FP_FRAC_SLL_##wc(X, (X##_e - _FP_WFRACBITS_##fs + 1)); \
683
_FP_FRAC_ASSEMBLE_##wc(r, X, rsize); \
684
} \
685
} \
686
else if (rsigned) \
687
{ \
688
r = 1; \
689
r <<= rsize - 1; \
690
r -= 1 - X##_s; \
691
} \
692
else \
693
{ \
694
r = 0; \
695
if (!X##_s) \
696
r = ~r; \
697
} \
698
FP_SET_EXCEPTION(FP_EX_INVALID); \
699
} \
700
else \
701
{ \
702
if (_FP_W_TYPE_SIZE*wc < rsize) \
703
{ \
704
_FP_FRAC_ASSEMBLE_##wc(r, X, rsize); \
705
r <<= X##_e - _FP_WFRACBITS_##fs; \
706
} \
707
else \
708
{ \
709
if (X##_e >= _FP_WFRACBITS_##fs) \
710
_FP_FRAC_SLL_##wc(X, (X##_e - _FP_WFRACBITS_##fs + 1)); \
711
else if (X##_e < _FP_WFRACBITS_##fs - 1) \
712
{ \
713
_FP_FRAC_SRS_##wc(X, (_FP_WFRACBITS_##fs - X##_e - 2), \
714
_FP_WFRACBITS_##fs); \
715
if (_FP_FRAC_LOW_##wc(X) & 1) \
716
FP_SET_EXCEPTION(FP_EX_INEXACT); \
717
_FP_FRAC_SRL_##wc(X, 1); \
718
} \
719
_FP_FRAC_ASSEMBLE_##wc(r, X, rsize); \
720
} \
721
if (rsigned && X##_s) \
722
r = -r; \
723
} \
724
break; \
725
} \
726
} while (0)
727
728
#define _FP_TO_INT_ROUND(fs, wc, r, X, rsize, rsigned) \
729
do { \
730
r = 0; \
731
switch (X##_c) \
732
{ \
733
case FP_CLS_NORMAL: \
734
if (X##_e >= _FP_FRACBITS_##fs - 1) \
735
{ \
736
if (X##_e < rsize - 1 + _FP_WFRACBITS_##fs) \
737
{ \
738
if (X##_e >= _FP_WFRACBITS_##fs - 1) \
739
{ \
740
_FP_FRAC_ASSEMBLE_##wc(r, X, rsize); \
741
r <<= X##_e - _FP_WFRACBITS_##fs + 1; \
742
} \
743
else \
744
{ \
745
_FP_FRAC_SRL_##wc(X, _FP_WORKBITS - X##_e \
746
+ _FP_FRACBITS_##fs - 1); \
747
_FP_FRAC_ASSEMBLE_##wc(r, X, rsize); \
748
} \
749
} \
750
} \
751
else \
752
{ \
753
int _lz0, _lz1; \
754
if (X##_e <= -_FP_WORKBITS - 1) \
755
_FP_FRAC_SET_##wc(X, _FP_MINFRAC_##wc); \
756
else \
757
_FP_FRAC_SRS_##wc(X, _FP_FRACBITS_##fs - 1 - X##_e, \
758
_FP_WFRACBITS_##fs); \
759
_FP_FRAC_CLZ_##wc(_lz0, X); \
760
_FP_ROUND(wc, X); \
761
_FP_FRAC_CLZ_##wc(_lz1, X); \
762
if (_lz1 < _lz0) \
763
X##_e++; /* For overflow detection. */ \
764
_FP_FRAC_SRL_##wc(X, _FP_WORKBITS); \
765
_FP_FRAC_ASSEMBLE_##wc(r, X, rsize); \
766
} \
767
if (rsigned && X##_s) \
768
r = -r; \
769
if (X##_e >= rsize - (rsigned > 0 || X##_s) \
770
|| (!rsigned && X##_s)) \
771
{ /* overflow */ \
772
fallthrough; \
773
case FP_CLS_NAN: \
774
case FP_CLS_INF: \
775
if (!rsigned) \
776
{ \
777
r = 0; \
778
if (!X##_s) \
779
r = ~r; \
780
} \
781
else if (rsigned != 2) \
782
{ \
783
r = 1; \
784
r <<= rsize - 1; \
785
r -= 1 - X##_s; \
786
} \
787
FP_SET_EXCEPTION(FP_EX_INVALID); \
788
} \
789
break; \
790
case FP_CLS_ZERO: \
791
break; \
792
} \
793
} while (0)
794
795
#define _FP_FROM_INT(fs, wc, X, r, rsize, rtype) \
796
do { \
797
if (r) \
798
{ \
799
unsigned rtype ur_; \
800
X##_c = FP_CLS_NORMAL; \
801
\
802
if ((X##_s = (r < 0))) \
803
ur_ = (unsigned rtype) -r; \
804
else \
805
ur_ = (unsigned rtype) r; \
806
(void) (((rsize) <= _FP_W_TYPE_SIZE) \
807
? ({ __FP_CLZ(X##_e, ur_); }) \
808
: ({ \
809
__FP_CLZ_2(X##_e, (_FP_W_TYPE)(ur_ >> _FP_W_TYPE_SIZE), \
810
(_FP_W_TYPE)ur_); \
811
})); \
812
if (rsize < _FP_W_TYPE_SIZE) \
813
X##_e -= (_FP_W_TYPE_SIZE - rsize); \
814
X##_e = rsize - X##_e - 1; \
815
\
816
if (_FP_FRACBITS_##fs < rsize && _FP_WFRACBITS_##fs <= X##_e) \
817
__FP_FRAC_SRS_1(ur_, (X##_e - _FP_WFRACBITS_##fs + 1), rsize);\
818
_FP_FRAC_DISASSEMBLE_##wc(X, ur_, rsize); \
819
if ((_FP_WFRACBITS_##fs - X##_e - 1) > 0) \
820
_FP_FRAC_SLL_##wc(X, (_FP_WFRACBITS_##fs - X##_e - 1)); \
821
} \
822
else \
823
{ \
824
X##_c = FP_CLS_ZERO, X##_s = 0; \
825
} \
826
} while (0)
827
828
829
#define FP_CONV(dfs,sfs,dwc,swc,D,S) \
830
do { \
831
_FP_FRAC_CONV_##dwc##_##swc(dfs, sfs, D, S); \
832
D##_e = S##_e; \
833
D##_c = S##_c; \
834
D##_s = S##_s; \
835
} while (0)
836
837
/*
838
* Helper primitives.
839
*/
840
841
/* Count leading zeros in a word. */
842
843
#ifndef __FP_CLZ
844
#if _FP_W_TYPE_SIZE < 64
845
/* this is just to shut the compiler up about shifts > word length -- PMM 02/1998 */
846
#define __FP_CLZ(r, x) \
847
do { \
848
_FP_W_TYPE _t = (x); \
849
r = _FP_W_TYPE_SIZE - 1; \
850
if (_t > 0xffff) r -= 16; \
851
if (_t > 0xffff) _t >>= 16; \
852
if (_t > 0xff) r -= 8; \
853
if (_t > 0xff) _t >>= 8; \
854
if (_t & 0xf0) r -= 4; \
855
if (_t & 0xf0) _t >>= 4; \
856
if (_t & 0xc) r -= 2; \
857
if (_t & 0xc) _t >>= 2; \
858
if (_t & 0x2) r -= 1; \
859
} while (0)
860
#else /* not _FP_W_TYPE_SIZE < 64 */
861
#define __FP_CLZ(r, x) \
862
do { \
863
_FP_W_TYPE _t = (x); \
864
r = _FP_W_TYPE_SIZE - 1; \
865
if (_t > 0xffffffff) r -= 32; \
866
if (_t > 0xffffffff) _t >>= 32; \
867
if (_t > 0xffff) r -= 16; \
868
if (_t > 0xffff) _t >>= 16; \
869
if (_t > 0xff) r -= 8; \
870
if (_t > 0xff) _t >>= 8; \
871
if (_t & 0xf0) r -= 4; \
872
if (_t & 0xf0) _t >>= 4; \
873
if (_t & 0xc) r -= 2; \
874
if (_t & 0xc) _t >>= 2; \
875
if (_t & 0x2) r -= 1; \
876
} while (0)
877
#endif /* not _FP_W_TYPE_SIZE < 64 */
878
#endif /* ndef __FP_CLZ */
879
880
#define _FP_DIV_HELP_imm(q, r, n, d) \
881
do { \
882
q = n / d, r = n % d; \
883
} while (0)
884
885
#endif /* __MATH_EMU_OP_COMMON_H__ */
886
887