Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
awilliam
GitHub Repository: awilliam/linux-vfio
Path: blob/master/include/math-emu/op-common.h
10817 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
case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_NORMAL): \
312
case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_INF): \
313
case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_ZERO): \
314
_FP_FRAC_COPY_##wc(R, X); \
315
R##_s = X##_s; \
316
R##_c = X##_c; \
317
break; \
318
\
319
case _FP_CLS_COMBINE(FP_CLS_ZERO,FP_CLS_NORMAL): \
320
R##_e = Y##_e; \
321
case _FP_CLS_COMBINE(FP_CLS_NORMAL,FP_CLS_NAN): \
322
case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_NAN): \
323
case _FP_CLS_COMBINE(FP_CLS_ZERO,FP_CLS_NAN): \
324
_FP_FRAC_COPY_##wc(R, Y); \
325
R##_s = Y##_s; \
326
R##_c = Y##_c; \
327
break; \
328
\
329
case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_INF): \
330
if (X##_s != Y##_s) \
331
{ \
332
/* +INF + -INF => NAN */ \
333
_FP_FRAC_SET_##wc(R, _FP_NANFRAC_##fs); \
334
R##_s = _FP_NANSIGN_##fs; \
335
R##_c = FP_CLS_NAN; \
336
FP_SET_EXCEPTION(FP_EX_INVALID | FP_EX_INVALID_ISI); \
337
break; \
338
} \
339
/* FALLTHRU */ \
340
\
341
case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_NORMAL): \
342
case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_ZERO): \
343
R##_s = X##_s; \
344
R##_c = FP_CLS_INF; \
345
break; \
346
\
347
case _FP_CLS_COMBINE(FP_CLS_NORMAL,FP_CLS_INF): \
348
case _FP_CLS_COMBINE(FP_CLS_ZERO,FP_CLS_INF): \
349
R##_s = Y##_s; \
350
R##_c = FP_CLS_INF; \
351
break; \
352
\
353
case _FP_CLS_COMBINE(FP_CLS_ZERO,FP_CLS_ZERO): \
354
/* make sure the sign is correct */ \
355
if (FP_ROUNDMODE == FP_RND_MINF) \
356
R##_s = X##_s | Y##_s; \
357
else \
358
R##_s = X##_s & Y##_s; \
359
R##_c = FP_CLS_ZERO; \
360
break; \
361
\
362
default: \
363
abort(); \
364
} \
365
} while (0)
366
367
#define _FP_ADD(fs, wc, R, X, Y) _FP_ADD_INTERNAL(fs, wc, R, X, Y, '+')
368
#define _FP_SUB(fs, wc, R, X, Y) \
369
do { \
370
if (Y##_c != FP_CLS_NAN) Y##_s ^= 1; \
371
_FP_ADD_INTERNAL(fs, wc, R, X, Y, '-'); \
372
} while (0)
373
374
375
/*
376
* Main negation routine. FIXME -- when we care about setting exception
377
* bits reliably, this will not do. We should examine all of the fp classes.
378
*/
379
380
#define _FP_NEG(fs, wc, R, X) \
381
do { \
382
_FP_FRAC_COPY_##wc(R, X); \
383
R##_c = X##_c; \
384
R##_e = X##_e; \
385
R##_s = 1 ^ X##_s; \
386
} while (0)
387
388
389
/*
390
* Main multiplication routine. The input values should be cooked.
391
*/
392
393
#define _FP_MUL(fs, wc, R, X, Y) \
394
do { \
395
R##_s = X##_s ^ Y##_s; \
396
switch (_FP_CLS_COMBINE(X##_c, Y##_c)) \
397
{ \
398
case _FP_CLS_COMBINE(FP_CLS_NORMAL,FP_CLS_NORMAL): \
399
R##_c = FP_CLS_NORMAL; \
400
R##_e = X##_e + Y##_e + 1; \
401
\
402
_FP_MUL_MEAT_##fs(R,X,Y); \
403
\
404
if (_FP_FRAC_OVERP_##wc(fs, R)) \
405
_FP_FRAC_SRS_##wc(R, 1, _FP_WFRACBITS_##fs); \
406
else \
407
R##_e--; \
408
break; \
409
\
410
case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_NAN): \
411
_FP_CHOOSENAN(fs, wc, R, X, Y, '*'); \
412
break; \
413
\
414
case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_NORMAL): \
415
case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_INF): \
416
case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_ZERO): \
417
R##_s = X##_s; \
418
\
419
case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_INF): \
420
case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_NORMAL): \
421
case _FP_CLS_COMBINE(FP_CLS_ZERO,FP_CLS_NORMAL): \
422
case _FP_CLS_COMBINE(FP_CLS_ZERO,FP_CLS_ZERO): \
423
_FP_FRAC_COPY_##wc(R, X); \
424
R##_c = X##_c; \
425
break; \
426
\
427
case _FP_CLS_COMBINE(FP_CLS_NORMAL,FP_CLS_NAN): \
428
case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_NAN): \
429
case _FP_CLS_COMBINE(FP_CLS_ZERO,FP_CLS_NAN): \
430
R##_s = Y##_s; \
431
\
432
case _FP_CLS_COMBINE(FP_CLS_NORMAL,FP_CLS_INF): \
433
case _FP_CLS_COMBINE(FP_CLS_NORMAL,FP_CLS_ZERO): \
434
_FP_FRAC_COPY_##wc(R, Y); \
435
R##_c = Y##_c; \
436
break; \
437
\
438
case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_ZERO): \
439
case _FP_CLS_COMBINE(FP_CLS_ZERO,FP_CLS_INF): \
440
R##_s = _FP_NANSIGN_##fs; \
441
R##_c = FP_CLS_NAN; \
442
_FP_FRAC_SET_##wc(R, _FP_NANFRAC_##fs); \
443
FP_SET_EXCEPTION(FP_EX_INVALID | FP_EX_INVALID_IMZ);\
444
break; \
445
\
446
default: \
447
abort(); \
448
} \
449
} while (0)
450
451
452
/*
453
* Main division routine. The input values should be cooked.
454
*/
455
456
#define _FP_DIV(fs, wc, R, X, Y) \
457
do { \
458
R##_s = X##_s ^ Y##_s; \
459
switch (_FP_CLS_COMBINE(X##_c, Y##_c)) \
460
{ \
461
case _FP_CLS_COMBINE(FP_CLS_NORMAL,FP_CLS_NORMAL): \
462
R##_c = FP_CLS_NORMAL; \
463
R##_e = X##_e - Y##_e; \
464
\
465
_FP_DIV_MEAT_##fs(R,X,Y); \
466
break; \
467
\
468
case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_NAN): \
469
_FP_CHOOSENAN(fs, wc, R, X, Y, '/'); \
470
break; \
471
\
472
case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_NORMAL): \
473
case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_INF): \
474
case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_ZERO): \
475
R##_s = X##_s; \
476
_FP_FRAC_COPY_##wc(R, X); \
477
R##_c = X##_c; \
478
break; \
479
\
480
case _FP_CLS_COMBINE(FP_CLS_NORMAL,FP_CLS_NAN): \
481
case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_NAN): \
482
case _FP_CLS_COMBINE(FP_CLS_ZERO,FP_CLS_NAN): \
483
R##_s = Y##_s; \
484
_FP_FRAC_COPY_##wc(R, Y); \
485
R##_c = Y##_c; \
486
break; \
487
\
488
case _FP_CLS_COMBINE(FP_CLS_NORMAL,FP_CLS_INF): \
489
case _FP_CLS_COMBINE(FP_CLS_ZERO,FP_CLS_INF): \
490
case _FP_CLS_COMBINE(FP_CLS_ZERO,FP_CLS_NORMAL): \
491
R##_c = FP_CLS_ZERO; \
492
break; \
493
\
494
case _FP_CLS_COMBINE(FP_CLS_NORMAL,FP_CLS_ZERO): \
495
FP_SET_EXCEPTION(FP_EX_DIVZERO); \
496
case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_ZERO): \
497
case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_NORMAL): \
498
R##_c = FP_CLS_INF; \
499
break; \
500
\
501
case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_INF): \
502
R##_s = _FP_NANSIGN_##fs; \
503
R##_c = FP_CLS_NAN; \
504
_FP_FRAC_SET_##wc(R, _FP_NANFRAC_##fs); \
505
FP_SET_EXCEPTION(FP_EX_INVALID | FP_EX_INVALID_IDI);\
506
break; \
507
\
508
case _FP_CLS_COMBINE(FP_CLS_ZERO,FP_CLS_ZERO): \
509
R##_s = _FP_NANSIGN_##fs; \
510
R##_c = FP_CLS_NAN; \
511
_FP_FRAC_SET_##wc(R, _FP_NANFRAC_##fs); \
512
FP_SET_EXCEPTION(FP_EX_INVALID | FP_EX_INVALID_ZDZ);\
513
break; \
514
\
515
default: \
516
abort(); \
517
} \
518
} while (0)
519
520
521
/*
522
* Main differential comparison routine. The inputs should be raw not
523
* cooked. The return is -1,0,1 for normal values, 2 otherwise.
524
*/
525
526
#define _FP_CMP(fs, wc, ret, X, Y, un) \
527
do { \
528
/* NANs are unordered */ \
529
if ((X##_e == _FP_EXPMAX_##fs && !_FP_FRAC_ZEROP_##wc(X)) \
530
|| (Y##_e == _FP_EXPMAX_##fs && !_FP_FRAC_ZEROP_##wc(Y))) \
531
{ \
532
ret = un; \
533
} \
534
else \
535
{ \
536
int __is_zero_x; \
537
int __is_zero_y; \
538
\
539
__is_zero_x = (!X##_e && _FP_FRAC_ZEROP_##wc(X)) ? 1 : 0; \
540
__is_zero_y = (!Y##_e && _FP_FRAC_ZEROP_##wc(Y)) ? 1 : 0; \
541
\
542
if (__is_zero_x && __is_zero_y) \
543
ret = 0; \
544
else if (__is_zero_x) \
545
ret = Y##_s ? 1 : -1; \
546
else if (__is_zero_y) \
547
ret = X##_s ? -1 : 1; \
548
else if (X##_s != Y##_s) \
549
ret = X##_s ? -1 : 1; \
550
else if (X##_e > Y##_e) \
551
ret = X##_s ? -1 : 1; \
552
else if (X##_e < Y##_e) \
553
ret = X##_s ? 1 : -1; \
554
else if (_FP_FRAC_GT_##wc(X, Y)) \
555
ret = X##_s ? -1 : 1; \
556
else if (_FP_FRAC_GT_##wc(Y, X)) \
557
ret = X##_s ? 1 : -1; \
558
else \
559
ret = 0; \
560
} \
561
} while (0)
562
563
564
/* Simplification for strict equality. */
565
566
#define _FP_CMP_EQ(fs, wc, ret, X, Y) \
567
do { \
568
/* NANs are unordered */ \
569
if ((X##_e == _FP_EXPMAX_##fs && !_FP_FRAC_ZEROP_##wc(X)) \
570
|| (Y##_e == _FP_EXPMAX_##fs && !_FP_FRAC_ZEROP_##wc(Y))) \
571
{ \
572
ret = 1; \
573
} \
574
else \
575
{ \
576
ret = !(X##_e == Y##_e \
577
&& _FP_FRAC_EQ_##wc(X, Y) \
578
&& (X##_s == Y##_s || !X##_e && _FP_FRAC_ZEROP_##wc(X))); \
579
} \
580
} while (0)
581
582
/*
583
* Main square root routine. The input value should be cooked.
584
*/
585
586
#define _FP_SQRT(fs, wc, R, X) \
587
do { \
588
_FP_FRAC_DECL_##wc(T); _FP_FRAC_DECL_##wc(S); \
589
_FP_W_TYPE q; \
590
switch (X##_c) \
591
{ \
592
case FP_CLS_NAN: \
593
_FP_FRAC_COPY_##wc(R, X); \
594
R##_s = X##_s; \
595
R##_c = FP_CLS_NAN; \
596
break; \
597
case FP_CLS_INF: \
598
if (X##_s) \
599
{ \
600
R##_s = _FP_NANSIGN_##fs; \
601
R##_c = FP_CLS_NAN; /* NAN */ \
602
_FP_FRAC_SET_##wc(R, _FP_NANFRAC_##fs); \
603
FP_SET_EXCEPTION(FP_EX_INVALID); \
604
} \
605
else \
606
{ \
607
R##_s = 0; \
608
R##_c = FP_CLS_INF; /* sqrt(+inf) = +inf */ \
609
} \
610
break; \
611
case FP_CLS_ZERO: \
612
R##_s = X##_s; \
613
R##_c = FP_CLS_ZERO; /* sqrt(+-0) = +-0 */ \
614
break; \
615
case FP_CLS_NORMAL: \
616
R##_s = 0; \
617
if (X##_s) \
618
{ \
619
R##_c = FP_CLS_NAN; /* sNAN */ \
620
R##_s = _FP_NANSIGN_##fs; \
621
_FP_FRAC_SET_##wc(R, _FP_NANFRAC_##fs); \
622
FP_SET_EXCEPTION(FP_EX_INVALID); \
623
break; \
624
} \
625
R##_c = FP_CLS_NORMAL; \
626
if (X##_e & 1) \
627
_FP_FRAC_SLL_##wc(X, 1); \
628
R##_e = X##_e >> 1; \
629
_FP_FRAC_SET_##wc(S, _FP_ZEROFRAC_##wc); \
630
_FP_FRAC_SET_##wc(R, _FP_ZEROFRAC_##wc); \
631
q = _FP_OVERFLOW_##fs >> 1; \
632
_FP_SQRT_MEAT_##wc(R, S, T, X, q); \
633
} \
634
} while (0)
635
636
/*
637
* Convert from FP to integer
638
*/
639
640
/* RSIGNED can have following values:
641
* 0: the number is required to be 0..(2^rsize)-1, if not, NV is set plus
642
* the result is either 0 or (2^rsize)-1 depending on the sign in such case.
643
* 1: the number is required to be -(2^(rsize-1))..(2^(rsize-1))-1, if not, NV is
644
* set plus the result is either -(2^(rsize-1)) or (2^(rsize-1))-1 depending
645
* on the sign in such case.
646
* 2: the number is required to be -(2^(rsize-1))..(2^(rsize-1))-1, if not, NV is
647
* set plus the result is truncated to fit into destination.
648
* -1: the number is required to be -(2^(rsize-1))..(2^rsize)-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
*/
652
#define _FP_TO_INT(fs, wc, r, X, rsize, rsigned) \
653
do { \
654
switch (X##_c) \
655
{ \
656
case FP_CLS_NORMAL: \
657
if (X##_e < 0) \
658
{ \
659
FP_SET_EXCEPTION(FP_EX_INEXACT); \
660
case FP_CLS_ZERO: \
661
r = 0; \
662
} \
663
else if (X##_e >= rsize - (rsigned > 0 || X##_s) \
664
|| (!rsigned && X##_s)) \
665
{ /* overflow */ \
666
case FP_CLS_NAN: \
667
case FP_CLS_INF: \
668
if (rsigned == 2) \
669
{ \
670
if (X##_c != FP_CLS_NORMAL \
671
|| X##_e >= rsize - 1 + _FP_WFRACBITS_##fs) \
672
r = 0; \
673
else \
674
{ \
675
_FP_FRAC_SLL_##wc(X, (X##_e - _FP_WFRACBITS_##fs + 1)); \
676
_FP_FRAC_ASSEMBLE_##wc(r, X, rsize); \
677
} \
678
} \
679
else if (rsigned) \
680
{ \
681
r = 1; \
682
r <<= rsize - 1; \
683
r -= 1 - X##_s; \
684
} \
685
else \
686
{ \
687
r = 0; \
688
if (X##_s) \
689
r = ~r; \
690
} \
691
FP_SET_EXCEPTION(FP_EX_INVALID); \
692
} \
693
else \
694
{ \
695
if (_FP_W_TYPE_SIZE*wc < rsize) \
696
{ \
697
_FP_FRAC_ASSEMBLE_##wc(r, X, rsize); \
698
r <<= X##_e - _FP_WFRACBITS_##fs; \
699
} \
700
else \
701
{ \
702
if (X##_e >= _FP_WFRACBITS_##fs) \
703
_FP_FRAC_SLL_##wc(X, (X##_e - _FP_WFRACBITS_##fs + 1)); \
704
else if (X##_e < _FP_WFRACBITS_##fs - 1) \
705
{ \
706
_FP_FRAC_SRS_##wc(X, (_FP_WFRACBITS_##fs - X##_e - 2), \
707
_FP_WFRACBITS_##fs); \
708
if (_FP_FRAC_LOW_##wc(X) & 1) \
709
FP_SET_EXCEPTION(FP_EX_INEXACT); \
710
_FP_FRAC_SRL_##wc(X, 1); \
711
} \
712
_FP_FRAC_ASSEMBLE_##wc(r, X, rsize); \
713
} \
714
if (rsigned && X##_s) \
715
r = -r; \
716
} \
717
break; \
718
} \
719
} while (0)
720
721
#define _FP_TO_INT_ROUND(fs, wc, r, X, rsize, rsigned) \
722
do { \
723
r = 0; \
724
switch (X##_c) \
725
{ \
726
case FP_CLS_NORMAL: \
727
if (X##_e >= _FP_FRACBITS_##fs - 1) \
728
{ \
729
if (X##_e < rsize - 1 + _FP_WFRACBITS_##fs) \
730
{ \
731
if (X##_e >= _FP_WFRACBITS_##fs - 1) \
732
{ \
733
_FP_FRAC_ASSEMBLE_##wc(r, X, rsize); \
734
r <<= X##_e - _FP_WFRACBITS_##fs + 1; \
735
} \
736
else \
737
{ \
738
_FP_FRAC_SRL_##wc(X, _FP_WORKBITS - X##_e \
739
+ _FP_FRACBITS_##fs - 1); \
740
_FP_FRAC_ASSEMBLE_##wc(r, X, rsize); \
741
} \
742
} \
743
} \
744
else \
745
{ \
746
if (X##_e <= -_FP_WORKBITS - 1) \
747
_FP_FRAC_SET_##wc(X, _FP_MINFRAC_##wc); \
748
else \
749
_FP_FRAC_SRS_##wc(X, _FP_FRACBITS_##fs - 1 - X##_e, \
750
_FP_WFRACBITS_##fs); \
751
_FP_ROUND(wc, X); \
752
_FP_FRAC_SRL_##wc(X, _FP_WORKBITS); \
753
_FP_FRAC_ASSEMBLE_##wc(r, X, rsize); \
754
} \
755
if (rsigned && X##_s) \
756
r = -r; \
757
if (X##_e >= rsize - (rsigned > 0 || X##_s) \
758
|| (!rsigned && X##_s)) \
759
{ /* overflow */ \
760
case FP_CLS_NAN: \
761
case FP_CLS_INF: \
762
if (!rsigned) \
763
{ \
764
r = 0; \
765
if (X##_s) \
766
r = ~r; \
767
} \
768
else if (rsigned != 2) \
769
{ \
770
r = 1; \
771
r <<= rsize - 1; \
772
r -= 1 - X##_s; \
773
} \
774
FP_SET_EXCEPTION(FP_EX_INVALID); \
775
} \
776
break; \
777
case FP_CLS_ZERO: \
778
break; \
779
} \
780
} while (0)
781
782
#define _FP_FROM_INT(fs, wc, X, r, rsize, rtype) \
783
do { \
784
if (r) \
785
{ \
786
unsigned rtype ur_; \
787
X##_c = FP_CLS_NORMAL; \
788
\
789
if ((X##_s = (r < 0))) \
790
ur_ = (unsigned rtype) -r; \
791
else \
792
ur_ = (unsigned rtype) r; \
793
if (rsize <= _FP_W_TYPE_SIZE) \
794
__FP_CLZ(X##_e, ur_); \
795
else \
796
__FP_CLZ_2(X##_e, (_FP_W_TYPE)(ur_ >> _FP_W_TYPE_SIZE), \
797
(_FP_W_TYPE)ur_); \
798
if (rsize < _FP_W_TYPE_SIZE) \
799
X##_e -= (_FP_W_TYPE_SIZE - rsize); \
800
X##_e = rsize - X##_e - 1; \
801
\
802
if (_FP_FRACBITS_##fs < rsize && _FP_WFRACBITS_##fs <= X##_e) \
803
__FP_FRAC_SRS_1(ur_, (X##_e - _FP_WFRACBITS_##fs + 1), rsize);\
804
_FP_FRAC_DISASSEMBLE_##wc(X, ur_, rsize); \
805
if ((_FP_WFRACBITS_##fs - X##_e - 1) > 0) \
806
_FP_FRAC_SLL_##wc(X, (_FP_WFRACBITS_##fs - X##_e - 1)); \
807
} \
808
else \
809
{ \
810
X##_c = FP_CLS_ZERO, X##_s = 0; \
811
} \
812
} while (0)
813
814
815
#define FP_CONV(dfs,sfs,dwc,swc,D,S) \
816
do { \
817
_FP_FRAC_CONV_##dwc##_##swc(dfs, sfs, D, S); \
818
D##_e = S##_e; \
819
D##_c = S##_c; \
820
D##_s = S##_s; \
821
} while (0)
822
823
/*
824
* Helper primitives.
825
*/
826
827
/* Count leading zeros in a word. */
828
829
#ifndef __FP_CLZ
830
#if _FP_W_TYPE_SIZE < 64
831
/* this is just to shut the compiler up about shifts > word length -- PMM 02/1998 */
832
#define __FP_CLZ(r, x) \
833
do { \
834
_FP_W_TYPE _t = (x); \
835
r = _FP_W_TYPE_SIZE - 1; \
836
if (_t > 0xffff) r -= 16; \
837
if (_t > 0xffff) _t >>= 16; \
838
if (_t > 0xff) r -= 8; \
839
if (_t > 0xff) _t >>= 8; \
840
if (_t & 0xf0) r -= 4; \
841
if (_t & 0xf0) _t >>= 4; \
842
if (_t & 0xc) r -= 2; \
843
if (_t & 0xc) _t >>= 2; \
844
if (_t & 0x2) r -= 1; \
845
} while (0)
846
#else /* not _FP_W_TYPE_SIZE < 64 */
847
#define __FP_CLZ(r, x) \
848
do { \
849
_FP_W_TYPE _t = (x); \
850
r = _FP_W_TYPE_SIZE - 1; \
851
if (_t > 0xffffffff) r -= 32; \
852
if (_t > 0xffffffff) _t >>= 32; \
853
if (_t > 0xffff) r -= 16; \
854
if (_t > 0xffff) _t >>= 16; \
855
if (_t > 0xff) r -= 8; \
856
if (_t > 0xff) _t >>= 8; \
857
if (_t & 0xf0) r -= 4; \
858
if (_t & 0xf0) _t >>= 4; \
859
if (_t & 0xc) r -= 2; \
860
if (_t & 0xc) _t >>= 2; \
861
if (_t & 0x2) r -= 1; \
862
} while (0)
863
#endif /* not _FP_W_TYPE_SIZE < 64 */
864
#endif /* ndef __FP_CLZ */
865
866
#define _FP_DIV_HELP_imm(q, r, n, d) \
867
do { \
868
q = n / d, r = n % d; \
869
} while (0)
870
871
#endif /* __MATH_EMU_OP_COMMON_H__ */
872
873