OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-dev/] [or1k-gcc/] [libgcc/] [soft-fp/] [op-common.h] - Blame information for rev 734

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 734 jeremybenn
/* Software floating-point emulation. Common operations.
2
   Copyright (C) 1997,1998,1999,2006,2007 Free Software Foundation, Inc.
3
   This file is part of the GNU C Library.
4
   Contributed by Richard Henderson (rth@cygnus.com),
5
                  Jakub Jelinek (jj@ultra.linux.cz),
6
                  David S. Miller (davem@redhat.com) and
7
                  Peter Maydell (pmaydell@chiark.greenend.org.uk).
8
 
9
   The GNU C Library is free software; you can redistribute it and/or
10
   modify it under the terms of the GNU Lesser General Public
11
   License as published by the Free Software Foundation; either
12
   version 2.1 of the License, or (at your option) any later version.
13
 
14
   In addition to the permissions in the GNU Lesser General Public
15
   License, the Free Software Foundation gives you unlimited
16
   permission to link the compiled version of this file into
17
   combinations with other programs, and to distribute those
18
   combinations without any restriction coming from the use of this
19
   file.  (The Lesser General Public License restrictions do apply in
20
   other respects; for example, they cover modification of the file,
21
   and distribution when not linked into a combine executable.)
22
 
23
   The GNU C Library is distributed in the hope that it will be useful,
24
   but WITHOUT ANY WARRANTY; without even the implied warranty of
25
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
26
   Lesser General Public License for more details.
27
 
28
   You should have received a copy of the GNU Lesser General Public
29
   License along with the GNU C Library; if not, write to the Free
30
   Software Foundation, 51 Franklin Street, Fifth Floor, Boston,
31
   MA 02110-1301, USA.  */
32
 
33
#define _FP_DECL(wc, X)                                         \
34
  _FP_I_TYPE X##_c __attribute__((unused)), X##_s, X##_e;       \
35
  _FP_FRAC_DECL_##wc(X)
36
 
37
/*
38
 * Finish truely unpacking a native fp value by classifying the kind
39
 * of fp value and normalizing both the exponent and the fraction.
40
 */
41
 
42
#define _FP_UNPACK_CANONICAL(fs, wc, X)                                 \
43
do {                                                                    \
44
  switch (X##_e)                                                        \
45
  {                                                                     \
46
  default:                                                              \
47
    _FP_FRAC_HIGH_RAW_##fs(X) |= _FP_IMPLBIT_##fs;                      \
48
    _FP_FRAC_SLL_##wc(X, _FP_WORKBITS);                                 \
49
    X##_e -= _FP_EXPBIAS_##fs;                                          \
50
    X##_c = FP_CLS_NORMAL;                                              \
51
    break;                                                              \
52
                                                                        \
53
  case 0:                                                                \
54
    if (_FP_FRAC_ZEROP_##wc(X))                                         \
55
      X##_c = FP_CLS_ZERO;                                              \
56
    else                                                                \
57
      {                                                                 \
58
        /* a denormalized number */                                     \
59
        _FP_I_TYPE _shift;                                              \
60
        _FP_FRAC_CLZ_##wc(_shift, X);                                   \
61
        _shift -= _FP_FRACXBITS_##fs;                                   \
62
        _FP_FRAC_SLL_##wc(X, (_shift+_FP_WORKBITS));                    \
63
        X##_e -= _FP_EXPBIAS_##fs - 1 + _shift;                         \
64
        X##_c = FP_CLS_NORMAL;                                          \
65
        FP_SET_EXCEPTION(FP_EX_DENORM);                                 \
66
      }                                                                 \
67
    break;                                                              \
68
                                                                        \
69
  case _FP_EXPMAX_##fs:                                                 \
70
    if (_FP_FRAC_ZEROP_##wc(X))                                         \
71
      X##_c = FP_CLS_INF;                                               \
72
    else                                                                \
73
      {                                                                 \
74
        X##_c = FP_CLS_NAN;                                             \
75
        /* Check for signaling NaN */                                   \
76
        if (!(_FP_FRAC_HIGH_RAW_##fs(X) & _FP_QNANBIT_##fs))            \
77
          FP_SET_EXCEPTION(FP_EX_INVALID);                              \
78
      }                                                                 \
79
    break;                                                              \
80
  }                                                                     \
81
} while (0)
82
 
83
/* Finish unpacking an fp value in semi-raw mode: the mantissa is
84
   shifted by _FP_WORKBITS but the implicit MSB is not inserted and
85
   other classification is not done.  */
86
#define _FP_UNPACK_SEMIRAW(fs, wc, X)   _FP_FRAC_SLL_##wc(X, _FP_WORKBITS)
87
 
88
/* A semi-raw value has overflowed to infinity.  Adjust the mantissa
89
   and exponent appropriately.  */
90
#define _FP_OVERFLOW_SEMIRAW(fs, wc, X)                 \
91
do {                                                    \
92
  if (FP_ROUNDMODE == FP_RND_NEAREST                    \
93
      || (FP_ROUNDMODE == FP_RND_PINF && !X##_s)        \
94
      || (FP_ROUNDMODE == FP_RND_MINF && X##_s))        \
95
    {                                                   \
96
      X##_e = _FP_EXPMAX_##fs;                          \
97
      _FP_FRAC_SET_##wc(X, _FP_ZEROFRAC_##wc);          \
98
    }                                                   \
99
  else                                                  \
100
    {                                                   \
101
      X##_e = _FP_EXPMAX_##fs - 1;                      \
102
      _FP_FRAC_SET_##wc(X, _FP_MAXFRAC_##wc);           \
103
    }                                                   \
104
    FP_SET_EXCEPTION(FP_EX_INEXACT);                    \
105
    FP_SET_EXCEPTION(FP_EX_OVERFLOW);                   \
106
} while (0)
107
 
108
/* Check for a semi-raw value being a signaling NaN and raise the
109
   invalid exception if so.  */
110
#define _FP_CHECK_SIGNAN_SEMIRAW(fs, wc, X)                     \
111
do {                                                            \
112
  if (X##_e == _FP_EXPMAX_##fs                                  \
113
      && !_FP_FRAC_ZEROP_##wc(X)                                \
114
      && !(_FP_FRAC_HIGH_##fs(X) & _FP_QNANBIT_SH_##fs))        \
115
    FP_SET_EXCEPTION(FP_EX_INVALID);                            \
116
} while (0)
117
 
118
/* Choose a NaN result from an operation on two semi-raw NaN
119
   values.  */
120
#define _FP_CHOOSENAN_SEMIRAW(fs, wc, R, X, Y, OP)                      \
121
do {                                                                    \
122
  /* _FP_CHOOSENAN expects raw values, so shift as required.  */        \
123
  _FP_FRAC_SRL_##wc(X, _FP_WORKBITS);                                   \
124
  _FP_FRAC_SRL_##wc(Y, _FP_WORKBITS);                                   \
125
  _FP_CHOOSENAN(fs, wc, R, X, Y, OP);                                   \
126
  _FP_FRAC_SLL_##wc(R, _FP_WORKBITS);                                   \
127
} while (0)
128
 
129
/* Test whether a biased exponent is normal (not zero or maximum).  */
130
#define _FP_EXP_NORMAL(fs, wc, X)       (((X##_e + 1) & _FP_EXPMAX_##fs) > 1)
131
 
132
/* Prepare to pack an fp value in semi-raw mode: the mantissa is
133
   rounded and shifted right, with the rounding possibly increasing
134
   the exponent (including changing a finite value to infinity).  */
135
#define _FP_PACK_SEMIRAW(fs, wc, X)                             \
136
do {                                                            \
137
  _FP_ROUND(wc, X);                                             \
138
  if (_FP_FRAC_HIGH_##fs(X)                                     \
139
      & (_FP_OVERFLOW_##fs >> 1))                               \
140
    {                                                           \
141
      _FP_FRAC_HIGH_##fs(X) &= ~(_FP_OVERFLOW_##fs >> 1);       \
142
      X##_e++;                                                  \
143
      if (X##_e == _FP_EXPMAX_##fs)                             \
144
        _FP_OVERFLOW_SEMIRAW(fs, wc, X);                        \
145
    }                                                           \
146
  _FP_FRAC_SRL_##wc(X, _FP_WORKBITS);                           \
147
  if (!_FP_EXP_NORMAL(fs, wc, X) && !_FP_FRAC_ZEROP_##wc(X))    \
148
    {                                                           \
149
      if (X##_e == 0)                                           \
150
        FP_SET_EXCEPTION(FP_EX_UNDERFLOW);                      \
151
      else                                                      \
152
        {                                                       \
153
          if (!_FP_KEEPNANFRACP)                                \
154
            {                                                   \
155
              _FP_FRAC_SET_##wc(X, _FP_NANFRAC_##fs);           \
156
              X##_s = _FP_NANSIGN_##fs;                         \
157
            }                                                   \
158
          else                                                  \
159
            _FP_FRAC_HIGH_RAW_##fs(X) |= _FP_QNANBIT_##fs;      \
160
        }                                                       \
161
    }                                                           \
162
} while (0)
163
 
164
/*
165
 * Before packing the bits back into the native fp result, take care
166
 * of such mundane things as rounding and overflow.  Also, for some
167
 * kinds of fp values, the original parts may not have been fully
168
 * extracted -- but that is ok, we can regenerate them now.
169
 */
170
 
171
#define _FP_PACK_CANONICAL(fs, wc, X)                           \
172
do {                                                            \
173
  switch (X##_c)                                                \
174
  {                                                             \
175
  case FP_CLS_NORMAL:                                           \
176
    X##_e += _FP_EXPBIAS_##fs;                                  \
177
    if (X##_e > 0)                                              \
178
      {                                                         \
179
        _FP_ROUND(wc, X);                                       \
180
        if (_FP_FRAC_OVERP_##wc(fs, X))                         \
181
          {                                                     \
182
            _FP_FRAC_CLEAR_OVERP_##wc(fs, X);                   \
183
            X##_e++;                                            \
184
          }                                                     \
185
        _FP_FRAC_SRL_##wc(X, _FP_WORKBITS);                     \
186
        if (X##_e >= _FP_EXPMAX_##fs)                           \
187
          {                                                     \
188
            /* overflow */                                      \
189
            switch (FP_ROUNDMODE)                               \
190
              {                                                 \
191
              case FP_RND_NEAREST:                              \
192
                X##_c = FP_CLS_INF;                             \
193
                break;                                          \
194
              case FP_RND_PINF:                                 \
195
                if (!X##_s) X##_c = FP_CLS_INF;                 \
196
                break;                                          \
197
              case FP_RND_MINF:                                 \
198
                if (X##_s) X##_c = FP_CLS_INF;                  \
199
                break;                                          \
200
              }                                                 \
201
            if (X##_c == FP_CLS_INF)                            \
202
              {                                                 \
203
                /* Overflow to infinity */                      \
204
                X##_e = _FP_EXPMAX_##fs;                        \
205
                _FP_FRAC_SET_##wc(X, _FP_ZEROFRAC_##wc);        \
206
              }                                                 \
207
            else                                                \
208
              {                                                 \
209
                /* Overflow to maximum normal */                \
210
                X##_e = _FP_EXPMAX_##fs - 1;                    \
211
                _FP_FRAC_SET_##wc(X, _FP_MAXFRAC_##wc);         \
212
              }                                                 \
213
            FP_SET_EXCEPTION(FP_EX_OVERFLOW);                   \
214
            FP_SET_EXCEPTION(FP_EX_INEXACT);                    \
215
          }                                                     \
216
      }                                                         \
217
    else                                                        \
218
      {                                                         \
219
        /* we've got a denormalized number */                   \
220
        X##_e = -X##_e + 1;                                     \
221
        if (X##_e <= _FP_WFRACBITS_##fs)                        \
222
          {                                                     \
223
            _FP_FRAC_SRS_##wc(X, X##_e, _FP_WFRACBITS_##fs);    \
224
            _FP_ROUND(wc, X);                                   \
225
            if (_FP_FRAC_HIGH_##fs(X)                           \
226
                & (_FP_OVERFLOW_##fs >> 1))                     \
227
              {                                                 \
228
                X##_e = 1;                                      \
229
                _FP_FRAC_SET_##wc(X, _FP_ZEROFRAC_##wc);        \
230
              }                                                 \
231
            else                                                \
232
              {                                                 \
233
                X##_e = 0;                                      \
234
                _FP_FRAC_SRL_##wc(X, _FP_WORKBITS);             \
235
                FP_SET_EXCEPTION(FP_EX_UNDERFLOW);              \
236
              }                                                 \
237
          }                                                     \
238
        else                                                    \
239
          {                                                     \
240
            /* underflow to zero */                             \
241
            X##_e = 0;                                          \
242
            if (!_FP_FRAC_ZEROP_##wc(X))                        \
243
              {                                                 \
244
                _FP_FRAC_SET_##wc(X, _FP_MINFRAC_##wc);         \
245
                _FP_ROUND(wc, X);                               \
246
                _FP_FRAC_LOW_##wc(X) >>= (_FP_WORKBITS);        \
247
              }                                                 \
248
            FP_SET_EXCEPTION(FP_EX_UNDERFLOW);                  \
249
          }                                                     \
250
      }                                                         \
251
    break;                                                      \
252
                                                                \
253
  case FP_CLS_ZERO:                                             \
254
    X##_e = 0;                                                  \
255
    _FP_FRAC_SET_##wc(X, _FP_ZEROFRAC_##wc);                    \
256
    break;                                                      \
257
                                                                \
258
  case FP_CLS_INF:                                              \
259
    X##_e = _FP_EXPMAX_##fs;                                    \
260
    _FP_FRAC_SET_##wc(X, _FP_ZEROFRAC_##wc);                    \
261
    break;                                                      \
262
                                                                \
263
  case FP_CLS_NAN:                                              \
264
    X##_e = _FP_EXPMAX_##fs;                                    \
265
    if (!_FP_KEEPNANFRACP)                                      \
266
      {                                                         \
267
        _FP_FRAC_SET_##wc(X, _FP_NANFRAC_##fs);                 \
268
        X##_s = _FP_NANSIGN_##fs;                               \
269
      }                                                         \
270
    else                                                        \
271
      _FP_FRAC_HIGH_RAW_##fs(X) |= _FP_QNANBIT_##fs;            \
272
    break;                                                      \
273
  }                                                             \
274
} while (0)
275
 
276
/* This one accepts raw argument and not cooked,  returns
277
 * 1 if X is a signaling NaN.
278
 */
279
#define _FP_ISSIGNAN(fs, wc, X)                                 \
280
({                                                              \
281
  int __ret = 0;                                         \
282
  if (X##_e == _FP_EXPMAX_##fs)                                 \
283
    {                                                           \
284
      if (!_FP_FRAC_ZEROP_##wc(X)                               \
285
          && !(_FP_FRAC_HIGH_RAW_##fs(X) & _FP_QNANBIT_##fs))   \
286
        __ret = 1;                                              \
287
    }                                                           \
288
  __ret;                                                        \
289
})
290
 
291
 
292
 
293
 
294
 
295
/* Addition on semi-raw values.  */
296
#define _FP_ADD_INTERNAL(fs, wc, R, X, Y, OP)                            \
297
do {                                                                     \
298
  if (X##_s == Y##_s)                                                    \
299
    {                                                                    \
300
      /* Addition.  */                                                   \
301
      R##_s = X##_s;                                                     \
302
      int ediff = X##_e - Y##_e;                                         \
303
      if (ediff > 0)                                                      \
304
        {                                                                \
305
          R##_e = X##_e;                                                 \
306
          if (Y##_e == 0)                                                \
307
            {                                                            \
308
              /* Y is zero or denormalized.  */                          \
309
              if (_FP_FRAC_ZEROP_##wc(Y))                                \
310
                {                                                        \
311
                  _FP_CHECK_SIGNAN_SEMIRAW(fs, wc, X);                   \
312
                  _FP_FRAC_COPY_##wc(R, X);                              \
313
                  goto add_done;                                         \
314
                }                                                        \
315
              else                                                       \
316
                {                                                        \
317
                  FP_SET_EXCEPTION(FP_EX_DENORM);                        \
318
                  ediff--;                                               \
319
                  if (ediff == 0)                                         \
320
                    {                                                    \
321
                      _FP_FRAC_ADD_##wc(R, X, Y);                        \
322
                      goto add3;                                         \
323
                    }                                                    \
324
                  if (X##_e == _FP_EXPMAX_##fs)                          \
325
                    {                                                    \
326
                      _FP_CHECK_SIGNAN_SEMIRAW(fs, wc, X);               \
327
                      _FP_FRAC_COPY_##wc(R, X);                          \
328
                      goto add_done;                                     \
329
                    }                                                    \
330
                  goto add1;                                             \
331
                }                                                        \
332
            }                                                            \
333
          else if (X##_e == _FP_EXPMAX_##fs)                             \
334
            {                                                            \
335
              /* X is NaN or Inf, Y is normal.  */                       \
336
              _FP_CHECK_SIGNAN_SEMIRAW(fs, wc, X);                       \
337
              _FP_FRAC_COPY_##wc(R, X);                                  \
338
              goto add_done;                                             \
339
            }                                                            \
340
                                                                         \
341
          /* Insert implicit MSB of Y.  */                               \
342
          _FP_FRAC_HIGH_##fs(Y) |= _FP_IMPLBIT_SH_##fs;                  \
343
                                                                         \
344
        add1:                                                            \
345
          /* Shift the mantissa of Y to the right EDIFF steps;           \
346
             remember to account later for the implicit MSB of X.  */    \
347
          if (ediff <= _FP_WFRACBITS_##fs)                               \
348
            _FP_FRAC_SRS_##wc(Y, ediff, _FP_WFRACBITS_##fs);             \
349
          else if (!_FP_FRAC_ZEROP_##wc(Y))                              \
350
            _FP_FRAC_SET_##wc(Y, _FP_MINFRAC_##wc);                      \
351
          _FP_FRAC_ADD_##wc(R, X, Y);                                    \
352
        }                                                                \
353
      else if (ediff < 0)                                                 \
354
        {                                                                \
355
          ediff = -ediff;                                                \
356
          R##_e = Y##_e;                                                 \
357
          if (X##_e == 0)                                                \
358
            {                                                            \
359
              /* X is zero or denormalized.  */                          \
360
              if (_FP_FRAC_ZEROP_##wc(X))                                \
361
                {                                                        \
362
                  _FP_CHECK_SIGNAN_SEMIRAW(fs, wc, Y);                   \
363
                  _FP_FRAC_COPY_##wc(R, Y);                              \
364
                  goto add_done;                                         \
365
                }                                                        \
366
              else                                                       \
367
                {                                                        \
368
                  FP_SET_EXCEPTION(FP_EX_DENORM);                        \
369
                  ediff--;                                               \
370
                  if (ediff == 0)                                         \
371
                    {                                                    \
372
                      _FP_FRAC_ADD_##wc(R, Y, X);                        \
373
                      goto add3;                                         \
374
                    }                                                    \
375
                  if (Y##_e == _FP_EXPMAX_##fs)                          \
376
                    {                                                    \
377
                      _FP_CHECK_SIGNAN_SEMIRAW(fs, wc, Y);               \
378
                      _FP_FRAC_COPY_##wc(R, Y);                          \
379
                      goto add_done;                                     \
380
                    }                                                    \
381
                  goto add2;                                             \
382
                }                                                        \
383
            }                                                            \
384
          else if (Y##_e == _FP_EXPMAX_##fs)                             \
385
            {                                                            \
386
              /* Y is NaN or Inf, X is normal.  */                       \
387
              _FP_CHECK_SIGNAN_SEMIRAW(fs, wc, Y);                       \
388
              _FP_FRAC_COPY_##wc(R, Y);                                  \
389
              goto add_done;                                             \
390
            }                                                            \
391
                                                                         \
392
          /* Insert implicit MSB of X.  */                               \
393
          _FP_FRAC_HIGH_##fs(X) |= _FP_IMPLBIT_SH_##fs;                  \
394
                                                                         \
395
        add2:                                                            \
396
          /* Shift the mantissa of X to the right EDIFF steps;           \
397
             remember to account later for the implicit MSB of Y.  */    \
398
          if (ediff <= _FP_WFRACBITS_##fs)                               \
399
            _FP_FRAC_SRS_##wc(X, ediff, _FP_WFRACBITS_##fs);             \
400
          else if (!_FP_FRAC_ZEROP_##wc(X))                              \
401
            _FP_FRAC_SET_##wc(X, _FP_MINFRAC_##wc);                      \
402
          _FP_FRAC_ADD_##wc(R, Y, X);                                    \
403
        }                                                                \
404
      else                                                               \
405
        {                                                                \
406
          /* ediff == 0.  */                                             \
407
          if (!_FP_EXP_NORMAL(fs, wc, X))                                \
408
            {                                                            \
409
              if (X##_e == 0)                                            \
410
                {                                                        \
411
                  /* X and Y are zero or denormalized.  */               \
412
                  R##_e = 0;                                             \
413
                  if (_FP_FRAC_ZEROP_##wc(X))                            \
414
                    {                                                    \
415
                      if (!_FP_FRAC_ZEROP_##wc(Y))                       \
416
                        FP_SET_EXCEPTION(FP_EX_DENORM);                  \
417
                      _FP_FRAC_COPY_##wc(R, Y);                          \
418
                      goto add_done;                                     \
419
                    }                                                    \
420
                  else if (_FP_FRAC_ZEROP_##wc(Y))                       \
421
                    {                                                    \
422
                      FP_SET_EXCEPTION(FP_EX_DENORM);                    \
423
                      _FP_FRAC_COPY_##wc(R, X);                          \
424
                      goto add_done;                                     \
425
                    }                                                    \
426
                  else                                                   \
427
                    {                                                    \
428
                      FP_SET_EXCEPTION(FP_EX_DENORM);                    \
429
                      _FP_FRAC_ADD_##wc(R, X, Y);                        \
430
                      if (_FP_FRAC_HIGH_##fs(R) & _FP_IMPLBIT_SH_##fs)   \
431
                        {                                                \
432
                          /* Normalized result.  */                      \
433
                          _FP_FRAC_HIGH_##fs(R)                          \
434
                            &= ~(_FP_W_TYPE)_FP_IMPLBIT_SH_##fs;         \
435
                          R##_e = 1;                                     \
436
                        }                                                \
437
                      goto add_done;                                     \
438
                    }                                                    \
439
                }                                                        \
440
              else                                                       \
441
                {                                                        \
442
                  /* X and Y are NaN or Inf.  */                         \
443
                  _FP_CHECK_SIGNAN_SEMIRAW(fs, wc, X);                   \
444
                  _FP_CHECK_SIGNAN_SEMIRAW(fs, wc, Y);                   \
445
                  R##_e = _FP_EXPMAX_##fs;                               \
446
                  if (_FP_FRAC_ZEROP_##wc(X))                            \
447
                    _FP_FRAC_COPY_##wc(R, Y);                            \
448
                  else if (_FP_FRAC_ZEROP_##wc(Y))                       \
449
                    _FP_FRAC_COPY_##wc(R, X);                            \
450
                  else                                                   \
451
                    _FP_CHOOSENAN_SEMIRAW(fs, wc, R, X, Y, OP);          \
452
                  goto add_done;                                         \
453
                }                                                        \
454
            }                                                            \
455
          /* The exponents of X and Y, both normal, are equal.  The      \
456
             implicit MSBs will always add to increase the               \
457
             exponent.  */                                               \
458
          _FP_FRAC_ADD_##wc(R, X, Y);                                    \
459
          R##_e = X##_e + 1;                                             \
460
          _FP_FRAC_SRS_##wc(R, 1, _FP_WFRACBITS_##fs);                   \
461
          if (R##_e == _FP_EXPMAX_##fs)                                  \
462
            /* Overflow to infinity (depending on rounding mode).  */    \
463
            _FP_OVERFLOW_SEMIRAW(fs, wc, R);                             \
464
          goto add_done;                                                 \
465
        }                                                                \
466
    add3:                                                                \
467
      if (_FP_FRAC_HIGH_##fs(R) & _FP_IMPLBIT_SH_##fs)                   \
468
        {                                                                \
469
          /* Overflow.  */                                               \
470
          _FP_FRAC_HIGH_##fs(R) &= ~(_FP_W_TYPE)_FP_IMPLBIT_SH_##fs;     \
471
          R##_e++;                                                       \
472
          _FP_FRAC_SRS_##wc(R, 1, _FP_WFRACBITS_##fs);                   \
473
          if (R##_e == _FP_EXPMAX_##fs)                                  \
474
            /* Overflow to infinity (depending on rounding mode).  */    \
475
            _FP_OVERFLOW_SEMIRAW(fs, wc, R);                             \
476
        }                                                                \
477
    add_done: ;                                                          \
478
    }                                                                    \
479
  else                                                                   \
480
    {                                                                    \
481
      /* Subtraction.  */                                                \
482
      int ediff = X##_e - Y##_e;                                         \
483
      if (ediff > 0)                                                      \
484
        {                                                                \
485
          R##_e = X##_e;                                                 \
486
          R##_s = X##_s;                                                 \
487
          if (Y##_e == 0)                                                \
488
            {                                                            \
489
              /* Y is zero or denormalized.  */                          \
490
              if (_FP_FRAC_ZEROP_##wc(Y))                                \
491
                {                                                        \
492
                  _FP_CHECK_SIGNAN_SEMIRAW(fs, wc, X);                   \
493
                  _FP_FRAC_COPY_##wc(R, X);                              \
494
                  goto sub_done;                                         \
495
                }                                                        \
496
              else                                                       \
497
                {                                                        \
498
                  FP_SET_EXCEPTION(FP_EX_DENORM);                        \
499
                  ediff--;                                               \
500
                  if (ediff == 0)                                         \
501
                    {                                                    \
502
                      _FP_FRAC_SUB_##wc(R, X, Y);                        \
503
                      goto sub3;                                         \
504
                    }                                                    \
505
                  if (X##_e == _FP_EXPMAX_##fs)                          \
506
                    {                                                    \
507
                      _FP_CHECK_SIGNAN_SEMIRAW(fs, wc, X);               \
508
                      _FP_FRAC_COPY_##wc(R, X);                          \
509
                      goto sub_done;                                     \
510
                    }                                                    \
511
                  goto sub1;                                             \
512
                }                                                        \
513
            }                                                            \
514
          else if (X##_e == _FP_EXPMAX_##fs)                             \
515
            {                                                            \
516
              /* X is NaN or Inf, Y is normal.  */                       \
517
              _FP_CHECK_SIGNAN_SEMIRAW(fs, wc, X);                       \
518
              _FP_FRAC_COPY_##wc(R, X);                                  \
519
              goto sub_done;                                             \
520
            }                                                            \
521
                                                                         \
522
          /* Insert implicit MSB of Y.  */                               \
523
          _FP_FRAC_HIGH_##fs(Y) |= _FP_IMPLBIT_SH_##fs;                  \
524
                                                                         \
525
        sub1:                                                            \
526
          /* Shift the mantissa of Y to the right EDIFF steps;           \
527
             remember to account later for the implicit MSB of X.  */    \
528
          if (ediff <= _FP_WFRACBITS_##fs)                               \
529
            _FP_FRAC_SRS_##wc(Y, ediff, _FP_WFRACBITS_##fs);             \
530
          else if (!_FP_FRAC_ZEROP_##wc(Y))                              \
531
            _FP_FRAC_SET_##wc(Y, _FP_MINFRAC_##wc);                      \
532
          _FP_FRAC_SUB_##wc(R, X, Y);                                    \
533
        }                                                                \
534
      else if (ediff < 0)                                                 \
535
        {                                                                \
536
          ediff = -ediff;                                                \
537
          R##_e = Y##_e;                                                 \
538
          R##_s = Y##_s;                                                 \
539
          if (X##_e == 0)                                                \
540
            {                                                            \
541
              /* X is zero or denormalized.  */                          \
542
              if (_FP_FRAC_ZEROP_##wc(X))                                \
543
                {                                                        \
544
                  _FP_CHECK_SIGNAN_SEMIRAW(fs, wc, Y);                   \
545
                  _FP_FRAC_COPY_##wc(R, Y);                              \
546
                  goto sub_done;                                         \
547
                }                                                        \
548
              else                                                       \
549
                {                                                        \
550
                  FP_SET_EXCEPTION(FP_EX_DENORM);                        \
551
                  ediff--;                                               \
552
                  if (ediff == 0)                                         \
553
                    {                                                    \
554
                      _FP_FRAC_SUB_##wc(R, Y, X);                        \
555
                      goto sub3;                                         \
556
                    }                                                    \
557
                  if (Y##_e == _FP_EXPMAX_##fs)                          \
558
                    {                                                    \
559
                      _FP_CHECK_SIGNAN_SEMIRAW(fs, wc, Y);               \
560
                      _FP_FRAC_COPY_##wc(R, Y);                          \
561
                      goto sub_done;                                     \
562
                    }                                                    \
563
                  goto sub2;                                             \
564
                }                                                        \
565
            }                                                            \
566
          else if (Y##_e == _FP_EXPMAX_##fs)                             \
567
            {                                                            \
568
              /* Y is NaN or Inf, X is normal.  */                       \
569
              _FP_CHECK_SIGNAN_SEMIRAW(fs, wc, Y);                       \
570
              _FP_FRAC_COPY_##wc(R, Y);                                  \
571
              goto sub_done;                                             \
572
            }                                                            \
573
                                                                         \
574
          /* Insert implicit MSB of X.  */                               \
575
          _FP_FRAC_HIGH_##fs(X) |= _FP_IMPLBIT_SH_##fs;                  \
576
                                                                         \
577
        sub2:                                                            \
578
          /* Shift the mantissa of X to the right EDIFF steps;           \
579
             remember to account later for the implicit MSB of Y.  */    \
580
          if (ediff <= _FP_WFRACBITS_##fs)                               \
581
            _FP_FRAC_SRS_##wc(X, ediff, _FP_WFRACBITS_##fs);             \
582
          else if (!_FP_FRAC_ZEROP_##wc(X))                              \
583
            _FP_FRAC_SET_##wc(X, _FP_MINFRAC_##wc);                      \
584
          _FP_FRAC_SUB_##wc(R, Y, X);                                    \
585
        }                                                                \
586
      else                                                               \
587
        {                                                                \
588
          /* ediff == 0.  */                                             \
589
          if (!_FP_EXP_NORMAL(fs, wc, X))                                \
590
            {                                                            \
591
              if (X##_e == 0)                                            \
592
                {                                                        \
593
                  /* X and Y are zero or denormalized.  */               \
594
                  R##_e = 0;                                             \
595
                  if (_FP_FRAC_ZEROP_##wc(X))                            \
596
                    {                                                    \
597
                      _FP_FRAC_COPY_##wc(R, Y);                          \
598
                      if (_FP_FRAC_ZEROP_##wc(Y))                        \
599
                        R##_s = (FP_ROUNDMODE == FP_RND_MINF);           \
600
                      else                                               \
601
                        {                                                \
602
                          FP_SET_EXCEPTION(FP_EX_DENORM);                \
603
                          R##_s = Y##_s;                                 \
604
                        }                                                \
605
                      goto sub_done;                                     \
606
                    }                                                    \
607
                  else if (_FP_FRAC_ZEROP_##wc(Y))                       \
608
                    {                                                    \
609
                      FP_SET_EXCEPTION(FP_EX_DENORM);                    \
610
                      _FP_FRAC_COPY_##wc(R, X);                          \
611
                      R##_s = X##_s;                                     \
612
                      goto sub_done;                                     \
613
                    }                                                    \
614
                  else                                                   \
615
                    {                                                    \
616
                      FP_SET_EXCEPTION(FP_EX_DENORM);                    \
617
                      _FP_FRAC_SUB_##wc(R, X, Y);                        \
618
                      R##_s = X##_s;                                     \
619
                      if (_FP_FRAC_HIGH_##fs(R) & _FP_IMPLBIT_SH_##fs)   \
620
                        {                                                \
621
                          /* |X| < |Y|, negate result.  */               \
622
                          _FP_FRAC_SUB_##wc(R, Y, X);                    \
623
                          R##_s = Y##_s;                                 \
624
                        }                                                \
625
                      else if (_FP_FRAC_ZEROP_##wc(R))                   \
626
                        R##_s = (FP_ROUNDMODE == FP_RND_MINF);           \
627
                      goto sub_done;                                     \
628
                    }                                                    \
629
                }                                                        \
630
              else                                                       \
631
                {                                                        \
632
                  /* X and Y are NaN or Inf, of opposite signs.  */      \
633
                  _FP_CHECK_SIGNAN_SEMIRAW(fs, wc, X);                   \
634
                  _FP_CHECK_SIGNAN_SEMIRAW(fs, wc, Y);                   \
635
                  R##_e = _FP_EXPMAX_##fs;                               \
636
                  if (_FP_FRAC_ZEROP_##wc(X))                            \
637
                    {                                                    \
638
                      if (_FP_FRAC_ZEROP_##wc(Y))                        \
639
                        {                                                \
640
                          /* Inf - Inf.  */                              \
641
                          R##_s = _FP_NANSIGN_##fs;                      \
642
                          _FP_FRAC_SET_##wc(R, _FP_NANFRAC_##fs);        \
643
                          _FP_FRAC_SLL_##wc(R, _FP_WORKBITS);            \
644
                          FP_SET_EXCEPTION(FP_EX_INVALID);               \
645
                        }                                                \
646
                      else                                               \
647
                        {                                                \
648
                          /* Inf - NaN.  */                              \
649
                          R##_s = Y##_s;                                 \
650
                          _FP_FRAC_COPY_##wc(R, Y);                      \
651
                        }                                                \
652
                    }                                                    \
653
                  else                                                   \
654
                    {                                                    \
655
                      if (_FP_FRAC_ZEROP_##wc(Y))                        \
656
                        {                                                \
657
                          /* NaN - Inf.  */                              \
658
                          R##_s = X##_s;                                 \
659
                          _FP_FRAC_COPY_##wc(R, X);                      \
660
                        }                                                \
661
                      else                                               \
662
                        {                                                \
663
                          /* NaN - NaN.  */                              \
664
                          _FP_CHOOSENAN_SEMIRAW(fs, wc, R, X, Y, OP);    \
665
                        }                                                \
666
                    }                                                    \
667
                  goto sub_done;                                         \
668
                }                                                        \
669
            }                                                            \
670
          /* The exponents of X and Y, both normal, are equal.  The      \
671
             implicit MSBs cancel.  */                                   \
672
          R##_e = X##_e;                                                 \
673
          _FP_FRAC_SUB_##wc(R, X, Y);                                    \
674
          R##_s = X##_s;                                                 \
675
          if (_FP_FRAC_HIGH_##fs(R) & _FP_IMPLBIT_SH_##fs)               \
676
            {                                                            \
677
              /* |X| < |Y|, negate result.  */                           \
678
              _FP_FRAC_SUB_##wc(R, Y, X);                                \
679
              R##_s = Y##_s;                                             \
680
            }                                                            \
681
          else if (_FP_FRAC_ZEROP_##wc(R))                               \
682
            {                                                            \
683
              R##_e = 0;                                                 \
684
              R##_s = (FP_ROUNDMODE == FP_RND_MINF);                     \
685
              goto sub_done;                                             \
686
            }                                                            \
687
          goto norm;                                                     \
688
        }                                                                \
689
    sub3:                                                                \
690
      if (_FP_FRAC_HIGH_##fs(R) & _FP_IMPLBIT_SH_##fs)                   \
691
        {                                                                \
692
          int diff;                                                      \
693
          /* Carry into most significant bit of larger one of X and Y,   \
694
             canceling it; renormalize.  */                              \
695
          _FP_FRAC_HIGH_##fs(R) &= _FP_IMPLBIT_SH_##fs - 1;              \
696
        norm:                                                            \
697
          _FP_FRAC_CLZ_##wc(diff, R);                                    \
698
          diff -= _FP_WFRACXBITS_##fs;                                   \
699
          _FP_FRAC_SLL_##wc(R, diff);                                    \
700
          if (R##_e <= diff)                                             \
701
            {                                                            \
702
              /* R is denormalized.  */                                  \
703
              diff = diff - R##_e + 1;                                   \
704
              _FP_FRAC_SRS_##wc(R, diff, _FP_WFRACBITS_##fs);            \
705
              R##_e = 0;                                                 \
706
            }                                                            \
707
          else                                                           \
708
            {                                                            \
709
              R##_e -= diff;                                             \
710
              _FP_FRAC_HIGH_##fs(R) &= ~(_FP_W_TYPE)_FP_IMPLBIT_SH_##fs; \
711
            }                                                            \
712
        }                                                                \
713
    sub_done: ;                                                          \
714
    }                                                                    \
715
} while (0)
716
 
717
#define _FP_ADD(fs, wc, R, X, Y) _FP_ADD_INTERNAL(fs, wc, R, X, Y, '+')
718
#define _FP_SUB(fs, wc, R, X, Y)                                            \
719
  do {                                                                      \
720
    if (!(Y##_e == _FP_EXPMAX_##fs && !_FP_FRAC_ZEROP_##wc(Y))) Y##_s ^= 1; \
721
    _FP_ADD_INTERNAL(fs, wc, R, X, Y, '-');                                 \
722
  } while (0)
723
 
724
 
725
/*
726
 * Main negation routine.  FIXME -- when we care about setting exception
727
 * bits reliably, this will not do.  We should examine all of the fp classes.
728
 */
729
 
730
#define _FP_NEG(fs, wc, R, X)           \
731
  do {                                  \
732
    _FP_FRAC_COPY_##wc(R, X);           \
733
    R##_c = X##_c;                      \
734
    R##_e = X##_e;                      \
735
    R##_s = 1 ^ X##_s;                  \
736
  } while (0)
737
 
738
 
739
/*
740
 * Main multiplication routine.  The input values should be cooked.
741
 */
742
 
743
#define _FP_MUL(fs, wc, R, X, Y)                        \
744
do {                                                    \
745
  R##_s = X##_s ^ Y##_s;                                \
746
  switch (_FP_CLS_COMBINE(X##_c, Y##_c))                \
747
  {                                                     \
748
  case _FP_CLS_COMBINE(FP_CLS_NORMAL,FP_CLS_NORMAL):    \
749
    R##_c = FP_CLS_NORMAL;                              \
750
    R##_e = X##_e + Y##_e + 1;                          \
751
                                                        \
752
    _FP_MUL_MEAT_##fs(R,X,Y);                           \
753
                                                        \
754
    if (_FP_FRAC_OVERP_##wc(fs, R))                     \
755
      _FP_FRAC_SRS_##wc(R, 1, _FP_WFRACBITS_##fs);      \
756
    else                                                \
757
      R##_e--;                                          \
758
    break;                                              \
759
                                                        \
760
  case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_NAN):          \
761
    _FP_CHOOSENAN(fs, wc, R, X, Y, '*');                \
762
    break;                                              \
763
                                                        \
764
  case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_NORMAL):       \
765
  case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_INF):          \
766
  case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_ZERO):         \
767
    R##_s = X##_s;                                      \
768
                                                        \
769
  case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_INF):          \
770
  case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_NORMAL):       \
771
  case _FP_CLS_COMBINE(FP_CLS_ZERO,FP_CLS_NORMAL):      \
772
  case _FP_CLS_COMBINE(FP_CLS_ZERO,FP_CLS_ZERO):        \
773
    _FP_FRAC_COPY_##wc(R, X);                           \
774
    R##_c = X##_c;                                      \
775
    break;                                              \
776
                                                        \
777
  case _FP_CLS_COMBINE(FP_CLS_NORMAL,FP_CLS_NAN):       \
778
  case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_NAN):          \
779
  case _FP_CLS_COMBINE(FP_CLS_ZERO,FP_CLS_NAN):         \
780
    R##_s = Y##_s;                                      \
781
                                                        \
782
  case _FP_CLS_COMBINE(FP_CLS_NORMAL,FP_CLS_INF):       \
783
  case _FP_CLS_COMBINE(FP_CLS_NORMAL,FP_CLS_ZERO):      \
784
    _FP_FRAC_COPY_##wc(R, Y);                           \
785
    R##_c = Y##_c;                                      \
786
    break;                                              \
787
                                                        \
788
  case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_ZERO):         \
789
  case _FP_CLS_COMBINE(FP_CLS_ZERO,FP_CLS_INF):         \
790
    R##_s = _FP_NANSIGN_##fs;                           \
791
    R##_c = FP_CLS_NAN;                                 \
792
    _FP_FRAC_SET_##wc(R, _FP_NANFRAC_##fs);             \
793
    FP_SET_EXCEPTION(FP_EX_INVALID);                    \
794
    break;                                              \
795
                                                        \
796
  default:                                              \
797
    abort();                                            \
798
  }                                                     \
799
} while (0)
800
 
801
 
802
/*
803
 * Main division routine.  The input values should be cooked.
804
 */
805
 
806
#define _FP_DIV(fs, wc, R, X, Y)                        \
807
do {                                                    \
808
  R##_s = X##_s ^ Y##_s;                                \
809
  switch (_FP_CLS_COMBINE(X##_c, Y##_c))                \
810
  {                                                     \
811
  case _FP_CLS_COMBINE(FP_CLS_NORMAL,FP_CLS_NORMAL):    \
812
    R##_c = FP_CLS_NORMAL;                              \
813
    R##_e = X##_e - Y##_e;                              \
814
                                                        \
815
    _FP_DIV_MEAT_##fs(R,X,Y);                           \
816
    break;                                              \
817
                                                        \
818
  case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_NAN):          \
819
    _FP_CHOOSENAN(fs, wc, R, X, Y, '/');                \
820
    break;                                              \
821
                                                        \
822
  case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_NORMAL):       \
823
  case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_INF):          \
824
  case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_ZERO):         \
825
    R##_s = X##_s;                                      \
826
    _FP_FRAC_COPY_##wc(R, X);                           \
827
    R##_c = X##_c;                                      \
828
    break;                                              \
829
                                                        \
830
  case _FP_CLS_COMBINE(FP_CLS_NORMAL,FP_CLS_NAN):       \
831
  case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_NAN):          \
832
  case _FP_CLS_COMBINE(FP_CLS_ZERO,FP_CLS_NAN):         \
833
    R##_s = Y##_s;                                      \
834
    _FP_FRAC_COPY_##wc(R, Y);                           \
835
    R##_c = Y##_c;                                      \
836
    break;                                              \
837
                                                        \
838
  case _FP_CLS_COMBINE(FP_CLS_NORMAL,FP_CLS_INF):       \
839
  case _FP_CLS_COMBINE(FP_CLS_ZERO,FP_CLS_INF):         \
840
  case _FP_CLS_COMBINE(FP_CLS_ZERO,FP_CLS_NORMAL):      \
841
    R##_c = FP_CLS_ZERO;                                \
842
    break;                                              \
843
                                                        \
844
  case _FP_CLS_COMBINE(FP_CLS_NORMAL,FP_CLS_ZERO):      \
845
    FP_SET_EXCEPTION(FP_EX_DIVZERO);                    \
846
  case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_ZERO):         \
847
  case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_NORMAL):       \
848
    R##_c = FP_CLS_INF;                                 \
849
    break;                                              \
850
                                                        \
851
  case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_INF):          \
852
  case _FP_CLS_COMBINE(FP_CLS_ZERO,FP_CLS_ZERO):        \
853
    R##_s = _FP_NANSIGN_##fs;                           \
854
    R##_c = FP_CLS_NAN;                                 \
855
    _FP_FRAC_SET_##wc(R, _FP_NANFRAC_##fs);             \
856
    FP_SET_EXCEPTION(FP_EX_INVALID);                    \
857
    break;                                              \
858
                                                        \
859
  default:                                              \
860
    abort();                                            \
861
  }                                                     \
862
} while (0)
863
 
864
 
865
/*
866
 * Main differential comparison routine.  The inputs should be raw not
867
 * cooked.  The return is -1,0,1 for normal values, 2 otherwise.
868
 */
869
 
870
#define _FP_CMP(fs, wc, ret, X, Y, un)                                  \
871
  do {                                                                  \
872
    /* NANs are unordered */                                            \
873
    if ((X##_e == _FP_EXPMAX_##fs && !_FP_FRAC_ZEROP_##wc(X))           \
874
        || (Y##_e == _FP_EXPMAX_##fs && !_FP_FRAC_ZEROP_##wc(Y)))       \
875
      {                                                                 \
876
        ret = un;                                                       \
877
      }                                                                 \
878
    else                                                                \
879
      {                                                                 \
880
        int __is_zero_x;                                                \
881
        int __is_zero_y;                                                \
882
                                                                        \
883
        __is_zero_x = (!X##_e && _FP_FRAC_ZEROP_##wc(X)) ? 1 : 0;       \
884
        __is_zero_y = (!Y##_e && _FP_FRAC_ZEROP_##wc(Y)) ? 1 : 0;       \
885
                                                                        \
886
        if (__is_zero_x && __is_zero_y)                                 \
887
                ret = 0;                                         \
888
        else if (__is_zero_x)                                           \
889
                ret = Y##_s ? 1 : -1;                                   \
890
        else if (__is_zero_y)                                           \
891
                ret = X##_s ? -1 : 1;                                   \
892
        else if (X##_s != Y##_s)                                        \
893
          ret = X##_s ? -1 : 1;                                         \
894
        else if (X##_e > Y##_e)                                         \
895
          ret = X##_s ? -1 : 1;                                         \
896
        else if (X##_e < Y##_e)                                         \
897
          ret = X##_s ? 1 : -1;                                         \
898
        else if (_FP_FRAC_GT_##wc(X, Y))                                \
899
          ret = X##_s ? -1 : 1;                                         \
900
        else if (_FP_FRAC_GT_##wc(Y, X))                                \
901
          ret = X##_s ? 1 : -1;                                         \
902
        else                                                            \
903
          ret = 0;                                                       \
904
      }                                                                 \
905
  } while (0)
906
 
907
 
908
/* Simplification for strict equality.  */
909
 
910
#define _FP_CMP_EQ(fs, wc, ret, X, Y)                                       \
911
  do {                                                                      \
912
    /* NANs are unordered */                                                \
913
    if ((X##_e == _FP_EXPMAX_##fs && !_FP_FRAC_ZEROP_##wc(X))               \
914
        || (Y##_e == _FP_EXPMAX_##fs && !_FP_FRAC_ZEROP_##wc(Y)))           \
915
      {                                                                     \
916
        ret = 1;                                                            \
917
      }                                                                     \
918
    else                                                                    \
919
      {                                                                     \
920
        ret = !(X##_e == Y##_e                                              \
921
                && _FP_FRAC_EQ_##wc(X, Y)                                   \
922
                && (X##_s == Y##_s || (!X##_e && _FP_FRAC_ZEROP_##wc(X)))); \
923
      }                                                                     \
924
  } while (0)
925
 
926
/* Version to test unordered.  */
927
 
928
#define _FP_CMP_UNORD(fs, wc, ret, X, Y)                                \
929
  do {                                                                  \
930
    ret = ((X##_e == _FP_EXPMAX_##fs && !_FP_FRAC_ZEROP_##wc(X))        \
931
           || (Y##_e == _FP_EXPMAX_##fs && !_FP_FRAC_ZEROP_##wc(Y)));   \
932
  } while (0)
933
 
934
/*
935
 * Main square root routine.  The input value should be cooked.
936
 */
937
 
938
#define _FP_SQRT(fs, wc, R, X)                                          \
939
do {                                                                    \
940
    _FP_FRAC_DECL_##wc(T); _FP_FRAC_DECL_##wc(S);                       \
941
    _FP_W_TYPE q;                                                       \
942
    switch (X##_c)                                                      \
943
    {                                                                   \
944
    case FP_CLS_NAN:                                                    \
945
        _FP_FRAC_COPY_##wc(R, X);                                       \
946
        R##_s = X##_s;                                                  \
947
        R##_c = FP_CLS_NAN;                                             \
948
        break;                                                          \
949
    case FP_CLS_INF:                                                    \
950
        if (X##_s)                                                      \
951
          {                                                             \
952
            R##_s = _FP_NANSIGN_##fs;                                   \
953
            R##_c = FP_CLS_NAN; /* NAN */                               \
954
            _FP_FRAC_SET_##wc(R, _FP_NANFRAC_##fs);                     \
955
            FP_SET_EXCEPTION(FP_EX_INVALID);                            \
956
          }                                                             \
957
        else                                                            \
958
          {                                                             \
959
            R##_s = 0;                                                  \
960
            R##_c = FP_CLS_INF; /* sqrt(+inf) = +inf */                 \
961
          }                                                             \
962
        break;                                                          \
963
    case FP_CLS_ZERO:                                                   \
964
        R##_s = X##_s;                                                  \
965
        R##_c = FP_CLS_ZERO; /* sqrt(+-0) = +-0 */                      \
966
        break;                                                          \
967
    case FP_CLS_NORMAL:                                                 \
968
        R##_s = 0;                                                      \
969
        if (X##_s)                                                      \
970
          {                                                             \
971
            R##_c = FP_CLS_NAN; /* sNAN */                              \
972
            R##_s = _FP_NANSIGN_##fs;                                   \
973
            _FP_FRAC_SET_##wc(R, _FP_NANFRAC_##fs);                     \
974
            FP_SET_EXCEPTION(FP_EX_INVALID);                            \
975
            break;                                                      \
976
          }                                                             \
977
        R##_c = FP_CLS_NORMAL;                                          \
978
        if (X##_e & 1)                                                  \
979
          _FP_FRAC_SLL_##wc(X, 1);                                      \
980
        R##_e = X##_e >> 1;                                             \
981
        _FP_FRAC_SET_##wc(S, _FP_ZEROFRAC_##wc);                        \
982
        _FP_FRAC_SET_##wc(R, _FP_ZEROFRAC_##wc);                        \
983
        q = _FP_OVERFLOW_##fs >> 1;                                     \
984
        _FP_SQRT_MEAT_##wc(R, S, T, X, q);                              \
985
    }                                                                   \
986
  } while (0)
987
 
988
/*
989
 * Convert from FP to integer.  Input is raw.
990
 */
991
 
992
/* RSIGNED can have following values:
993
 * 0:  the number is required to be 0..(2^rsize)-1, if not, NV is set plus
994
 *     the result is either 0 or (2^rsize)-1 depending on the sign in such
995
 *     case.
996
 * 1:  the number is required to be -(2^(rsize-1))..(2^(rsize-1))-1, if not,
997
 *     NV is set plus the result is either -(2^(rsize-1)) or (2^(rsize-1))-1
998
 *     depending on the sign in such case.
999
 * -1: the number is required to be -(2^(rsize-1))..(2^rsize)-1, if not, NV is
1000
 *     set plus the result is either -(2^(rsize-1)) or (2^(rsize-1))-1
1001
 *     depending on the sign in such case.
1002
 */
1003
#define _FP_TO_INT(fs, wc, r, X, rsize, rsigned)                        \
1004
do {                                                                    \
1005
  if (X##_e < _FP_EXPBIAS_##fs)                                         \
1006
    {                                                                   \
1007
      r = 0;                                                             \
1008
      if (X##_e == 0)                                                   \
1009
        {                                                               \
1010
          if (!_FP_FRAC_ZEROP_##wc(X))                                  \
1011
            {                                                           \
1012
              FP_SET_EXCEPTION(FP_EX_INEXACT);                          \
1013
              FP_SET_EXCEPTION(FP_EX_DENORM);                           \
1014
            }                                                           \
1015
        }                                                               \
1016
      else                                                              \
1017
        FP_SET_EXCEPTION(FP_EX_INEXACT);                                \
1018
    }                                                                   \
1019
  else if (X##_e >= _FP_EXPBIAS_##fs + rsize - (rsigned > 0 || X##_s)   \
1020
           || (!rsigned && X##_s))                                      \
1021
    {                                                                   \
1022
      /* Overflow or converting to the most negative integer.  */       \
1023
      if (rsigned)                                                      \
1024
        {                                                               \
1025
          r = 1;                                                        \
1026
          r <<= rsize - 1;                                              \
1027
          r -= 1 - X##_s;                                               \
1028
        } else {                                                        \
1029
          r = 0;                                                 \
1030
          if (X##_s)                                                    \
1031
            r = ~r;                                                     \
1032
        }                                                               \
1033
                                                                        \
1034
      if (rsigned && X##_s && X##_e == _FP_EXPBIAS_##fs + rsize - 1)    \
1035
        {                                                               \
1036
          /* Possibly converting to most negative integer; check the    \
1037
             mantissa.  */                                              \
1038
          int inexact = 0;                                               \
1039
          (void)((_FP_FRACBITS_##fs > rsize)                            \
1040
                 ? ({ _FP_FRAC_SRST_##wc(X, inexact,                    \
1041
                                         _FP_FRACBITS_##fs - rsize,     \
1042
                                         _FP_FRACBITS_##fs); 0; })      \
1043
                 : 0);                                                   \
1044
          if (!_FP_FRAC_ZEROP_##wc(X))                                  \
1045
            FP_SET_EXCEPTION(FP_EX_INVALID);                            \
1046
          else if (inexact)                                             \
1047
            FP_SET_EXCEPTION(FP_EX_INEXACT);                            \
1048
        }                                                               \
1049
      else                                                              \
1050
        FP_SET_EXCEPTION(FP_EX_INVALID);                                \
1051
    }                                                                   \
1052
  else                                                                  \
1053
    {                                                                   \
1054
      _FP_FRAC_HIGH_RAW_##fs(X) |= _FP_IMPLBIT_##fs;                    \
1055
      if (X##_e >= _FP_EXPBIAS_##fs + _FP_FRACBITS_##fs - 1)            \
1056
        {                                                               \
1057
          _FP_FRAC_ASSEMBLE_##wc(r, X, rsize);                          \
1058
          r <<= X##_e - _FP_EXPBIAS_##fs - _FP_FRACBITS_##fs + 1;       \
1059
        }                                                               \
1060
      else                                                              \
1061
        {                                                               \
1062
          int inexact;                                                  \
1063
          _FP_FRAC_SRST_##wc(X, inexact,                                \
1064
                            (_FP_FRACBITS_##fs + _FP_EXPBIAS_##fs - 1   \
1065
                             - X##_e),                                  \
1066
                            _FP_FRACBITS_##fs);                         \
1067
          if (inexact)                                                  \
1068
            FP_SET_EXCEPTION(FP_EX_INEXACT);                            \
1069
          _FP_FRAC_ASSEMBLE_##wc(r, X, rsize);                          \
1070
        }                                                               \
1071
      if (rsigned && X##_s)                                             \
1072
        r = -r;                                                         \
1073
    }                                                                   \
1074
} while (0)
1075
 
1076
/* Convert integer to fp.  Output is raw.  RTYPE is unsigned even if
1077
   input is signed.  */
1078
#define _FP_FROM_INT(fs, wc, X, r, rsize, rtype)                             \
1079
  do {                                                                       \
1080
    if (r)                                                                   \
1081
      {                                                                      \
1082
        rtype ur_;                                                           \
1083
                                                                             \
1084
        if ((X##_s = (r < 0)))                                               \
1085
          r = -(rtype)r;                                                     \
1086
                                                                             \
1087
        ur_ = (rtype) r;                                                     \
1088
        (void)((rsize <= _FP_W_TYPE_SIZE)                                    \
1089
               ? ({                                                          \
1090
                    int lz_;                                                 \
1091
                    __FP_CLZ(lz_, (_FP_W_TYPE)ur_);                          \
1092
                    X##_e = _FP_EXPBIAS_##fs + _FP_W_TYPE_SIZE - 1 - lz_;    \
1093
                  })                                                         \
1094
               : ((rsize <= 2 * _FP_W_TYPE_SIZE)                             \
1095
                  ? ({                                                       \
1096
                       int lz_;                                              \
1097
                       __FP_CLZ_2(lz_, (_FP_W_TYPE)(ur_ >> _FP_W_TYPE_SIZE), \
1098
                                  (_FP_W_TYPE)ur_);                          \
1099
                       X##_e = (_FP_EXPBIAS_##fs + 2 * _FP_W_TYPE_SIZE - 1   \
1100
                                - lz_);                                      \
1101
                     })                                                      \
1102
                  : (abort(), 0)));                                           \
1103
                                                                             \
1104
        if (rsize - 1 + _FP_EXPBIAS_##fs >= _FP_EXPMAX_##fs                  \
1105
            && X##_e >= _FP_EXPMAX_##fs)                                     \
1106
          {                                                                  \
1107
            /* Exponent too big; overflow to infinity.  (May also            \
1108
               happen after rounding below.)  */                             \
1109
            _FP_OVERFLOW_SEMIRAW(fs, wc, X);                                 \
1110
            goto pack_semiraw;                                               \
1111
          }                                                                  \
1112
                                                                             \
1113
        if (rsize <= _FP_FRACBITS_##fs                                       \
1114
            || X##_e < _FP_EXPBIAS_##fs + _FP_FRACBITS_##fs)                 \
1115
          {                                                                  \
1116
            /* Exactly representable; shift left.  */                        \
1117
            _FP_FRAC_DISASSEMBLE_##wc(X, ur_, rsize);                        \
1118
            _FP_FRAC_SLL_##wc(X, (_FP_EXPBIAS_##fs                           \
1119
                                  + _FP_FRACBITS_##fs - 1 - X##_e));         \
1120
          }                                                                  \
1121
        else                                                                 \
1122
          {                                                                  \
1123
            /* More bits in integer than in floating type; need to           \
1124
               round.  */                                                    \
1125
            if (_FP_EXPBIAS_##fs + _FP_WFRACBITS_##fs - 1 < X##_e)           \
1126
              ur_ = ((ur_ >> (X##_e - _FP_EXPBIAS_##fs                       \
1127
                              - _FP_WFRACBITS_##fs + 1))                     \
1128
                     | ((ur_ << (rsize - (X##_e - _FP_EXPBIAS_##fs           \
1129
                                          - _FP_WFRACBITS_##fs + 1)))        \
1130
                        != 0));                                               \
1131
            _FP_FRAC_DISASSEMBLE_##wc(X, ur_, rsize);                        \
1132
            if ((_FP_EXPBIAS_##fs + _FP_WFRACBITS_##fs - 1 - X##_e) > 0)     \
1133
              _FP_FRAC_SLL_##wc(X, (_FP_EXPBIAS_##fs                         \
1134
                                    + _FP_WFRACBITS_##fs - 1 - X##_e));      \
1135
            _FP_FRAC_HIGH_##fs(X) &= ~(_FP_W_TYPE)_FP_IMPLBIT_SH_##fs;       \
1136
          pack_semiraw:                                                      \
1137
            _FP_PACK_SEMIRAW(fs, wc, X);                                     \
1138
          }                                                                  \
1139
      }                                                                      \
1140
    else                                                                     \
1141
      {                                                                      \
1142
        X##_s = 0;                                                           \
1143
        X##_e = 0;                                                           \
1144
        _FP_FRAC_SET_##wc(X, _FP_ZEROFRAC_##wc);                             \
1145
      }                                                                      \
1146
  } while (0)
1147
 
1148
 
1149
/* Extend from a narrower floating-point format to a wider one.  Input
1150
   and output are raw.  */
1151
#define FP_EXTEND(dfs,sfs,dwc,swc,D,S)                                   \
1152
do {                                                                     \
1153
  if (_FP_FRACBITS_##dfs < _FP_FRACBITS_##sfs                            \
1154
      || (_FP_EXPMAX_##dfs - _FP_EXPBIAS_##dfs                           \
1155
          < _FP_EXPMAX_##sfs - _FP_EXPBIAS_##sfs)                        \
1156
      || (_FP_EXPBIAS_##dfs < _FP_EXPBIAS_##sfs + _FP_FRACBITS_##sfs - 1 \
1157
          && _FP_EXPBIAS_##dfs != _FP_EXPBIAS_##sfs))                    \
1158
    abort();                                                             \
1159
  D##_s = S##_s;                                                         \
1160
  _FP_FRAC_COPY_##dwc##_##swc(D, S);                                     \
1161
  if (_FP_EXP_NORMAL(sfs, swc, S))                                       \
1162
    {                                                                    \
1163
      D##_e = S##_e + _FP_EXPBIAS_##dfs - _FP_EXPBIAS_##sfs;             \
1164
      _FP_FRAC_SLL_##dwc(D, (_FP_FRACBITS_##dfs - _FP_FRACBITS_##sfs));  \
1165
    }                                                                    \
1166
  else                                                                   \
1167
    {                                                                    \
1168
      if (S##_e == 0)                                                    \
1169
        {                                                                \
1170
          if (_FP_FRAC_ZEROP_##swc(S))                                   \
1171
            D##_e = 0;                                                   \
1172
          else if (_FP_EXPBIAS_##dfs                                     \
1173
                   < _FP_EXPBIAS_##sfs + _FP_FRACBITS_##sfs - 1)         \
1174
            {                                                            \
1175
              FP_SET_EXCEPTION(FP_EX_DENORM);                            \
1176
              _FP_FRAC_SLL_##dwc(D, (_FP_FRACBITS_##dfs                  \
1177
                                     - _FP_FRACBITS_##sfs));             \
1178
              D##_e = 0;                                                 \
1179
            }                                                            \
1180
          else                                                           \
1181
            {                                                            \
1182
              int _lz;                                                   \
1183
              FP_SET_EXCEPTION(FP_EX_DENORM);                            \
1184
              _FP_FRAC_CLZ_##swc(_lz, S);                                \
1185
              _FP_FRAC_SLL_##dwc(D,                                      \
1186
                                 _lz + _FP_FRACBITS_##dfs                \
1187
                                 - _FP_FRACTBITS_##sfs);                 \
1188
              D##_e = (_FP_EXPBIAS_##dfs - _FP_EXPBIAS_##sfs + 1         \
1189
                       + _FP_FRACXBITS_##sfs - _lz);                     \
1190
            }                                                            \
1191
        }                                                                \
1192
      else                                                               \
1193
        {                                                                \
1194
          D##_e = _FP_EXPMAX_##dfs;                                      \
1195
          if (!_FP_FRAC_ZEROP_##swc(S))                                  \
1196
            {                                                            \
1197
              if (!(_FP_FRAC_HIGH_RAW_##sfs(S) & _FP_QNANBIT_##sfs))     \
1198
                FP_SET_EXCEPTION(FP_EX_INVALID);                         \
1199
              _FP_FRAC_SLL_##dwc(D, (_FP_FRACBITS_##dfs                  \
1200
                                     - _FP_FRACBITS_##sfs));             \
1201
            }                                                            \
1202
        }                                                                \
1203
    }                                                                    \
1204
} while (0)
1205
 
1206
/* Truncate from a wider floating-point format to a narrower one.
1207
   Input and output are semi-raw.  */
1208
#define FP_TRUNC(dfs,sfs,dwc,swc,D,S)                                        \
1209
do {                                                                         \
1210
  if (_FP_FRACBITS_##sfs < _FP_FRACBITS_##dfs                                \
1211
      || (_FP_EXPBIAS_##sfs < _FP_EXPBIAS_##dfs + _FP_FRACBITS_##dfs - 1     \
1212
          && _FP_EXPBIAS_##sfs != _FP_EXPBIAS_##dfs))                        \
1213
    abort();                                                                 \
1214
  D##_s = S##_s;                                                             \
1215
  if (_FP_EXP_NORMAL(sfs, swc, S))                                           \
1216
    {                                                                        \
1217
      D##_e = S##_e + _FP_EXPBIAS_##dfs - _FP_EXPBIAS_##sfs;                 \
1218
      if (D##_e >= _FP_EXPMAX_##dfs)                                         \
1219
        _FP_OVERFLOW_SEMIRAW(dfs, dwc, D);                                   \
1220
      else                                                                   \
1221
        {                                                                    \
1222
          if (D##_e <= 0)                                                    \
1223
            {                                                                \
1224
              if (D##_e < 1 - _FP_FRACBITS_##dfs)                            \
1225
                {                                                            \
1226
                  _FP_FRAC_SET_##swc(S, _FP_ZEROFRAC_##swc);                 \
1227
                  _FP_FRAC_LOW_##swc(S) |= 1;                                \
1228
                }                                                            \
1229
              else                                                           \
1230
                {                                                            \
1231
                  _FP_FRAC_HIGH_##sfs(S) |= _FP_IMPLBIT_SH_##sfs;            \
1232
                  _FP_FRAC_SRS_##swc(S, (_FP_WFRACBITS_##sfs                 \
1233
                                         - _FP_WFRACBITS_##dfs + 1 - D##_e), \
1234
                                     _FP_WFRACBITS_##sfs);                   \
1235
                }                                                            \
1236
              D##_e = 0;                                                     \
1237
            }                                                                \
1238
          else                                                               \
1239
            _FP_FRAC_SRS_##swc(S, (_FP_WFRACBITS_##sfs                       \
1240
                                   - _FP_WFRACBITS_##dfs),                   \
1241
                               _FP_WFRACBITS_##sfs);                         \
1242
          _FP_FRAC_COPY_##dwc##_##swc(D, S);                                 \
1243
        }                                                                    \
1244
    }                                                                        \
1245
  else                                                                       \
1246
    {                                                                        \
1247
      if (S##_e == 0)                                                        \
1248
        {                                                                    \
1249
          D##_e = 0;                                                         \
1250
          if (_FP_FRAC_ZEROP_##swc(S))                                       \
1251
            _FP_FRAC_SET_##dwc(D, _FP_ZEROFRAC_##dwc);                       \
1252
          else                                                               \
1253
            {                                                                \
1254
              FP_SET_EXCEPTION(FP_EX_DENORM);                                \
1255
              if (_FP_EXPBIAS_##sfs                                          \
1256
                  < _FP_EXPBIAS_##dfs + _FP_FRACBITS_##dfs - 1)              \
1257
                {                                                            \
1258
                  _FP_FRAC_SRS_##swc(S, (_FP_WFRACBITS_##sfs                 \
1259
                                         - _FP_WFRACBITS_##dfs),             \
1260
                                     _FP_WFRACBITS_##sfs);                   \
1261
                  _FP_FRAC_COPY_##dwc##_##swc(D, S);                         \
1262
                }                                                            \
1263
              else                                                           \
1264
                {                                                            \
1265
                  _FP_FRAC_SET_##dwc(D, _FP_ZEROFRAC_##dwc);                 \
1266
                  _FP_FRAC_LOW_##dwc(D) |= 1;                                \
1267
                }                                                            \
1268
            }                                                                \
1269
        }                                                                    \
1270
      else                                                                   \
1271
        {                                                                    \
1272
          D##_e = _FP_EXPMAX_##dfs;                                          \
1273
          if (_FP_FRAC_ZEROP_##swc(S))                                       \
1274
            _FP_FRAC_SET_##dwc(D, _FP_ZEROFRAC_##dwc);                       \
1275
          else                                                               \
1276
            {                                                                \
1277
              _FP_CHECK_SIGNAN_SEMIRAW(sfs, swc, S);                         \
1278
              _FP_FRAC_SRL_##swc(S, (_FP_WFRACBITS_##sfs                     \
1279
                                     - _FP_WFRACBITS_##dfs));                \
1280
              _FP_FRAC_COPY_##dwc##_##swc(D, S);                             \
1281
              /* Semi-raw NaN must have all workbits cleared.  */            \
1282
              _FP_FRAC_LOW_##dwc(D)                                          \
1283
                &= ~(_FP_W_TYPE) ((1 << _FP_WORKBITS) - 1);                  \
1284
              _FP_FRAC_HIGH_##dfs(D) |= _FP_QNANBIT_SH_##dfs;                \
1285
            }                                                                \
1286
        }                                                                    \
1287
    }                                                                        \
1288
} while (0)
1289
 
1290
/*
1291
 * Helper primitives.
1292
 */
1293
 
1294
/* Count leading zeros in a word.  */
1295
 
1296
#ifndef __FP_CLZ
1297
/* GCC 3.4 and later provide the builtins for us.  */
1298
#define __FP_CLZ(r, x)                                                        \
1299
  do {                                                                        \
1300
    if (sizeof (_FP_W_TYPE) == sizeof (unsigned int))                         \
1301
      r = __builtin_clz (x);                                                  \
1302
    else if (sizeof (_FP_W_TYPE) == sizeof (unsigned long))                   \
1303
      r = __builtin_clzl (x);                                                 \
1304
    else if (sizeof (_FP_W_TYPE) == sizeof (unsigned long long))              \
1305
      r = __builtin_clzll (x);                                                \
1306
    else                                                                      \
1307
      abort ();                                                               \
1308
  } while (0)
1309
#endif /* ndef __FP_CLZ */
1310
 
1311
#define _FP_DIV_HELP_imm(q, r, n, d)            \
1312
  do {                                          \
1313
    q = n / d, r = n % d;                       \
1314
  } while (0)
1315
 
1316
 
1317
/* A restoring bit-by-bit division primitive.  */
1318
 
1319
#define _FP_DIV_MEAT_N_loop(fs, wc, R, X, Y)                            \
1320
  do {                                                                  \
1321
    int count = _FP_WFRACBITS_##fs;                                     \
1322
    _FP_FRAC_DECL_##wc (u);                                             \
1323
    _FP_FRAC_DECL_##wc (v);                                             \
1324
    _FP_FRAC_COPY_##wc (u, X);                                          \
1325
    _FP_FRAC_COPY_##wc (v, Y);                                          \
1326
    _FP_FRAC_SET_##wc (R, _FP_ZEROFRAC_##wc);                           \
1327
    /* Normalize U and V.  */                                           \
1328
    _FP_FRAC_SLL_##wc (u, _FP_WFRACXBITS_##fs);                         \
1329
    _FP_FRAC_SLL_##wc (v, _FP_WFRACXBITS_##fs);                         \
1330
    /* First round.  Since the operands are normalized, either the      \
1331
       first or second bit will be set in the fraction.  Produce a      \
1332
       normalized result by checking which and adjusting the loop       \
1333
       count and exponent accordingly.  */                              \
1334
    if (_FP_FRAC_GE_1 (u, v))                                           \
1335
      {                                                                 \
1336
        _FP_FRAC_SUB_##wc (u, u, v);                                    \
1337
        _FP_FRAC_LOW_##wc (R) |= 1;                                     \
1338
        count--;                                                        \
1339
      }                                                                 \
1340
    else                                                                \
1341
      R##_e--;                                                          \
1342
    /* Subsequent rounds.  */                                           \
1343
    do {                                                                \
1344
      int msb = (_FP_WS_TYPE) _FP_FRAC_HIGH_##wc (u) < 0;               \
1345
      _FP_FRAC_SLL_##wc (u, 1);                                         \
1346
      _FP_FRAC_SLL_##wc (R, 1);                                         \
1347
      if (msb || _FP_FRAC_GE_1 (u, v))                                  \
1348
        {                                                               \
1349
          _FP_FRAC_SUB_##wc (u, u, v);                                  \
1350
          _FP_FRAC_LOW_##wc (R) |= 1;                                   \
1351
        }                                                               \
1352
    } while (--count > 0);                                               \
1353
    /* If there's anything left in U, the result is inexact.  */        \
1354
    _FP_FRAC_LOW_##wc (R) |= !_FP_FRAC_ZEROP_##wc (u);                  \
1355
  } while (0)
1356
 
1357
#define _FP_DIV_MEAT_1_loop(fs, R, X, Y)  _FP_DIV_MEAT_N_loop (fs, 1, R, X, Y)
1358
#define _FP_DIV_MEAT_2_loop(fs, R, X, Y)  _FP_DIV_MEAT_N_loop (fs, 2, R, X, Y)
1359
#define _FP_DIV_MEAT_4_loop(fs, R, X, Y)  _FP_DIV_MEAT_N_loop (fs, 4, R, X, Y)

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.