Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | RSS feed

  1. /* Software floating-point emulation.
  2.    Basic four-word fraction declaration and manipulation.
  3.    Copyright (C) 1997-2014 Free Software Foundation, Inc.
  4.    This file is part of the GNU C Library.
  5.    Contributed by Richard Henderson (rth@cygnus.com),
  6.                   Jakub Jelinek (jj@ultra.linux.cz),
  7.                   David S. Miller (davem@redhat.com) and
  8.                   Peter Maydell (pmaydell@chiark.greenend.org.uk).
  9.  
  10.    The GNU C Library is free software; you can redistribute it and/or
  11.    modify it under the terms of the GNU Lesser General Public
  12.    License as published by the Free Software Foundation; either
  13.    version 2.1 of the License, or (at your option) any later version.
  14.  
  15.    In addition to the permissions in the GNU Lesser General Public
  16.    License, the Free Software Foundation gives you unlimited
  17.    permission to link the compiled version of this file into
  18.    combinations with other programs, and to distribute those
  19.    combinations without any restriction coming from the use of this
  20.    file.  (The Lesser General Public License restrictions do apply in
  21.    other respects; for example, they cover modification of the file,
  22.    and distribution when not linked into a combine executable.)
  23.  
  24.    The GNU C Library is distributed in the hope that it will be useful,
  25.    but WITHOUT ANY WARRANTY; without even the implied warranty of
  26.    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  27.    Lesser General Public License for more details.
  28.  
  29.    You should have received a copy of the GNU Lesser General Public
  30.    License along with the GNU C Library; if not, see
  31.    <http://www.gnu.org/licenses/>.  */
  32.  
  33. #define _FP_FRAC_DECL_4(X)      _FP_W_TYPE X##_f[4]
  34. #define _FP_FRAC_COPY_4(D, S)                   \
  35.   (D##_f[0] = S##_f[0], D##_f[1] = S##_f[1],    \
  36.    D##_f[2] = S##_f[2], D##_f[3] = S##_f[3])
  37. #define _FP_FRAC_SET_4(X, I)    __FP_FRAC_SET_4 (X, I)
  38. #define _FP_FRAC_HIGH_4(X)      (X##_f[3])
  39. #define _FP_FRAC_LOW_4(X)       (X##_f[0])
  40. #define _FP_FRAC_WORD_4(X, w)   (X##_f[w])
  41.  
  42. #define _FP_FRAC_SLL_4(X, N)                                            \
  43.   do                                                                    \
  44.     {                                                                   \
  45.       _FP_I_TYPE _FP_FRAC_SLL_4_up, _FP_FRAC_SLL_4_down;                \
  46.       _FP_I_TYPE _FP_FRAC_SLL_4_skip, _FP_FRAC_SLL_4_i;                 \
  47.       _FP_FRAC_SLL_4_skip = (N) / _FP_W_TYPE_SIZE;                      \
  48.       _FP_FRAC_SLL_4_up = (N) % _FP_W_TYPE_SIZE;                        \
  49.       _FP_FRAC_SLL_4_down = _FP_W_TYPE_SIZE - _FP_FRAC_SLL_4_up;        \
  50.       if (!_FP_FRAC_SLL_4_up)                                           \
  51.         for (_FP_FRAC_SLL_4_i = 3;                                      \
  52.              _FP_FRAC_SLL_4_i >= _FP_FRAC_SLL_4_skip;                   \
  53.              --_FP_FRAC_SLL_4_i)                                        \
  54.           X##_f[_FP_FRAC_SLL_4_i]                                       \
  55.             = X##_f[_FP_FRAC_SLL_4_i-_FP_FRAC_SLL_4_skip];              \
  56.       else                                                              \
  57.         {                                                               \
  58.           for (_FP_FRAC_SLL_4_i = 3;                                    \
  59.                _FP_FRAC_SLL_4_i > _FP_FRAC_SLL_4_skip;                  \
  60.                --_FP_FRAC_SLL_4_i)                                      \
  61.             X##_f[_FP_FRAC_SLL_4_i]                                     \
  62.               = ((X##_f[_FP_FRAC_SLL_4_i-_FP_FRAC_SLL_4_skip]           \
  63.                   << _FP_FRAC_SLL_4_up)                                 \
  64.                  | (X##_f[_FP_FRAC_SLL_4_i-_FP_FRAC_SLL_4_skip-1]       \
  65.                     >> _FP_FRAC_SLL_4_down));                           \
  66.           X##_f[_FP_FRAC_SLL_4_i--] = X##_f[0] << _FP_FRAC_SLL_4_up;    \
  67.         }                                                               \
  68.       for (; _FP_FRAC_SLL_4_i >= 0; --_FP_FRAC_SLL_4_i)                 \
  69.         X##_f[_FP_FRAC_SLL_4_i] = 0;                                    \
  70.     }                                                                   \
  71.   while (0)
  72.  
  73. /* This one was broken too.  */
  74. #define _FP_FRAC_SRL_4(X, N)                                            \
  75.   do                                                                    \
  76.     {                                                                   \
  77.       _FP_I_TYPE _FP_FRAC_SRL_4_up, _FP_FRAC_SRL_4_down;                \
  78.       _FP_I_TYPE _FP_FRAC_SRL_4_skip, _FP_FRAC_SRL_4_i;                 \
  79.       _FP_FRAC_SRL_4_skip = (N) / _FP_W_TYPE_SIZE;                      \
  80.       _FP_FRAC_SRL_4_down = (N) % _FP_W_TYPE_SIZE;                      \
  81.       _FP_FRAC_SRL_4_up = _FP_W_TYPE_SIZE - _FP_FRAC_SRL_4_down;        \
  82.       if (!_FP_FRAC_SRL_4_down)                                         \
  83.         for (_FP_FRAC_SRL_4_i = 0;                                      \
  84.              _FP_FRAC_SRL_4_i <= 3-_FP_FRAC_SRL_4_skip;                 \
  85.              ++_FP_FRAC_SRL_4_i)                                        \
  86.           X##_f[_FP_FRAC_SRL_4_i]                                       \
  87.             = X##_f[_FP_FRAC_SRL_4_i+_FP_FRAC_SRL_4_skip];              \
  88.       else                                                              \
  89.         {                                                               \
  90.           for (_FP_FRAC_SRL_4_i = 0;                                    \
  91.                _FP_FRAC_SRL_4_i < 3-_FP_FRAC_SRL_4_skip;                \
  92.                ++_FP_FRAC_SRL_4_i)                                      \
  93.             X##_f[_FP_FRAC_SRL_4_i]                                     \
  94.               = ((X##_f[_FP_FRAC_SRL_4_i+_FP_FRAC_SRL_4_skip]           \
  95.                   >> _FP_FRAC_SRL_4_down)                               \
  96.                  | (X##_f[_FP_FRAC_SRL_4_i+_FP_FRAC_SRL_4_skip+1]       \
  97.                     << _FP_FRAC_SRL_4_up));                             \
  98.           X##_f[_FP_FRAC_SRL_4_i++] = X##_f[3] >> _FP_FRAC_SRL_4_down;  \
  99.         }                                                               \
  100.       for (; _FP_FRAC_SRL_4_i < 4; ++_FP_FRAC_SRL_4_i)                  \
  101.         X##_f[_FP_FRAC_SRL_4_i] = 0;                                    \
  102.     }                                                                   \
  103.   while (0)
  104.  
  105.  
  106. /* Right shift with sticky-lsb.
  107.    What this actually means is that we do a standard right-shift,
  108.    but that if any of the bits that fall off the right hand side
  109.    were one then we always set the LSbit.  */
  110. #define _FP_FRAC_SRST_4(X, S, N, size)                                  \
  111.   do                                                                    \
  112.     {                                                                   \
  113.       _FP_I_TYPE _FP_FRAC_SRST_4_up, _FP_FRAC_SRST_4_down;              \
  114.       _FP_I_TYPE _FP_FRAC_SRST_4_skip, _FP_FRAC_SRST_4_i;               \
  115.       _FP_W_TYPE _FP_FRAC_SRST_4_s;                                     \
  116.       _FP_FRAC_SRST_4_skip = (N) / _FP_W_TYPE_SIZE;                     \
  117.       _FP_FRAC_SRST_4_down = (N) % _FP_W_TYPE_SIZE;                     \
  118.       _FP_FRAC_SRST_4_up = _FP_W_TYPE_SIZE - _FP_FRAC_SRST_4_down;      \
  119.       for (_FP_FRAC_SRST_4_s = _FP_FRAC_SRST_4_i = 0;                   \
  120.            _FP_FRAC_SRST_4_i < _FP_FRAC_SRST_4_skip;                    \
  121.            ++_FP_FRAC_SRST_4_i)                                         \
  122.         _FP_FRAC_SRST_4_s |= X##_f[_FP_FRAC_SRST_4_i];                  \
  123.       if (!_FP_FRAC_SRST_4_down)                                        \
  124.         for (_FP_FRAC_SRST_4_i = 0;                                     \
  125.              _FP_FRAC_SRST_4_i <= 3-_FP_FRAC_SRST_4_skip;               \
  126.              ++_FP_FRAC_SRST_4_i)                                       \
  127.           X##_f[_FP_FRAC_SRST_4_i]                                      \
  128.             = X##_f[_FP_FRAC_SRST_4_i+_FP_FRAC_SRST_4_skip];            \
  129.       else                                                              \
  130.         {                                                               \
  131.           _FP_FRAC_SRST_4_s                                             \
  132.             |= X##_f[_FP_FRAC_SRST_4_i] << _FP_FRAC_SRST_4_up;          \
  133.           for (_FP_FRAC_SRST_4_i = 0;                                   \
  134.                _FP_FRAC_SRST_4_i < 3-_FP_FRAC_SRST_4_skip;              \
  135.                ++_FP_FRAC_SRST_4_i)                                     \
  136.             X##_f[_FP_FRAC_SRST_4_i]                                    \
  137.               = ((X##_f[_FP_FRAC_SRST_4_i+_FP_FRAC_SRST_4_skip]         \
  138.                   >> _FP_FRAC_SRST_4_down)                              \
  139.                  | (X##_f[_FP_FRAC_SRST_4_i+_FP_FRAC_SRST_4_skip+1]     \
  140.                     << _FP_FRAC_SRST_4_up));                            \
  141.           X##_f[_FP_FRAC_SRST_4_i++]                                    \
  142.             = X##_f[3] >> _FP_FRAC_SRST_4_down;                         \
  143.         }                                                               \
  144.       for (; _FP_FRAC_SRST_4_i < 4; ++_FP_FRAC_SRST_4_i)                \
  145.         X##_f[_FP_FRAC_SRST_4_i] = 0;                                   \
  146.       S = (_FP_FRAC_SRST_4_s != 0);                                     \
  147.     }                                                                   \
  148.   while (0)
  149.  
  150. #define _FP_FRAC_SRS_4(X, N, size)                              \
  151.   do                                                            \
  152.     {                                                           \
  153.       int _FP_FRAC_SRS_4_sticky;                                \
  154.       _FP_FRAC_SRST_4 (X, _FP_FRAC_SRS_4_sticky, (N), (size));  \
  155.       X##_f[0] |= _FP_FRAC_SRS_4_sticky;                        \
  156.     }                                                           \
  157.   while (0)
  158.  
  159. #define _FP_FRAC_ADD_4(R, X, Y)                                 \
  160.   __FP_FRAC_ADD_4 (R##_f[3], R##_f[2], R##_f[1], R##_f[0],      \
  161.                    X##_f[3], X##_f[2], X##_f[1], X##_f[0],      \
  162.                    Y##_f[3], Y##_f[2], Y##_f[1], Y##_f[0])
  163.  
  164. #define _FP_FRAC_SUB_4(R, X, Y)                                 \
  165.   __FP_FRAC_SUB_4 (R##_f[3], R##_f[2], R##_f[1], R##_f[0],      \
  166.                    X##_f[3], X##_f[2], X##_f[1], X##_f[0],      \
  167.                    Y##_f[3], Y##_f[2], Y##_f[1], Y##_f[0])
  168.  
  169. #define _FP_FRAC_DEC_4(X, Y)                                    \
  170.   __FP_FRAC_DEC_4 (X##_f[3], X##_f[2], X##_f[1], X##_f[0],      \
  171.                    Y##_f[3], Y##_f[2], Y##_f[1], Y##_f[0])
  172.  
  173. #define _FP_FRAC_ADDI_4(X, I)                                   \
  174.   __FP_FRAC_ADDI_4 (X##_f[3], X##_f[2], X##_f[1], X##_f[0], I)
  175.  
  176. #define _FP_ZEROFRAC_4  0, 0, 0, 0
  177. #define _FP_MINFRAC_4   0, 0, 0, 1
  178. #define _FP_MAXFRAC_4   (~(_FP_WS_TYPE) 0), (~(_FP_WS_TYPE) 0), (~(_FP_WS_TYPE) 0), (~(_FP_WS_TYPE) 0)
  179.  
  180. #define _FP_FRAC_ZEROP_4(X)     ((X##_f[0] | X##_f[1] | X##_f[2] | X##_f[3]) == 0)
  181. #define _FP_FRAC_NEGP_4(X)      ((_FP_WS_TYPE) X##_f[3] < 0)
  182. #define _FP_FRAC_OVERP_4(fs, X)  (_FP_FRAC_HIGH_##fs (X) & _FP_OVERFLOW_##fs)
  183. #define _FP_FRAC_HIGHBIT_DW_4(fs, X)    \
  184.   (_FP_FRAC_HIGH_DW_##fs (X) & _FP_HIGHBIT_DW_##fs)
  185. #define _FP_FRAC_CLEAR_OVERP_4(fs, X)  (_FP_FRAC_HIGH_##fs (X) &= ~_FP_OVERFLOW_##fs)
  186.  
  187. #define _FP_FRAC_EQ_4(X, Y)                             \
  188.   (X##_f[0] == Y##_f[0] && X##_f[1] == Y##_f[1]         \
  189.    && X##_f[2] == Y##_f[2] && X##_f[3] == Y##_f[3])
  190.  
  191. #define _FP_FRAC_GT_4(X, Y)                             \
  192.   (X##_f[3] > Y##_f[3]                                  \
  193.    || (X##_f[3] == Y##_f[3]                             \
  194.        && (X##_f[2] > Y##_f[2]                          \
  195.            || (X##_f[2] == Y##_f[2]                     \
  196.                && (X##_f[1] > Y##_f[1]                  \
  197.                    || (X##_f[1] == Y##_f[1]             \
  198.                        && X##_f[0] > Y##_f[0]))))))
  199.  
  200. #define _FP_FRAC_GE_4(X, Y)                             \
  201.   (X##_f[3] > Y##_f[3]                                  \
  202.    || (X##_f[3] == Y##_f[3]                             \
  203.        && (X##_f[2] > Y##_f[2]                          \
  204.            || (X##_f[2] == Y##_f[2]                     \
  205.                && (X##_f[1] > Y##_f[1]                  \
  206.                    || (X##_f[1] == Y##_f[1]             \
  207.                        && X##_f[0] >= Y##_f[0]))))))
  208.  
  209.  
  210. #define _FP_FRAC_CLZ_4(R, X)                    \
  211.   do                                            \
  212.     {                                           \
  213.       if (X##_f[3])                             \
  214.         __FP_CLZ ((R), X##_f[3]);               \
  215.       else if (X##_f[2])                        \
  216.         {                                       \
  217.           __FP_CLZ ((R), X##_f[2]);             \
  218.           (R) += _FP_W_TYPE_SIZE;               \
  219.         }                                       \
  220.       else if (X##_f[1])                        \
  221.         {                                       \
  222.           __FP_CLZ ((R), X##_f[1]);             \
  223.           (R) += _FP_W_TYPE_SIZE*2;             \
  224.         }                                       \
  225.       else                                      \
  226.         {                                       \
  227.           __FP_CLZ ((R), X##_f[0]);             \
  228.           (R) += _FP_W_TYPE_SIZE*3;             \
  229.         }                                       \
  230.     }                                           \
  231.   while (0)
  232.  
  233.  
  234. #define _FP_UNPACK_RAW_4(fs, X, val)                    \
  235.   do                                                    \
  236.     {                                                   \
  237.       union _FP_UNION_##fs _FP_UNPACK_RAW_4_flo;        \
  238.       _FP_UNPACK_RAW_4_flo.flt = (val);                 \
  239.       X##_f[0] = _FP_UNPACK_RAW_4_flo.bits.frac0;       \
  240.       X##_f[1] = _FP_UNPACK_RAW_4_flo.bits.frac1;       \
  241.       X##_f[2] = _FP_UNPACK_RAW_4_flo.bits.frac2;       \
  242.       X##_f[3] = _FP_UNPACK_RAW_4_flo.bits.frac3;       \
  243.       X##_e  = _FP_UNPACK_RAW_4_flo.bits.exp;           \
  244.       X##_s  = _FP_UNPACK_RAW_4_flo.bits.sign;          \
  245.     }                                                   \
  246.   while (0)
  247.  
  248. #define _FP_UNPACK_RAW_4_P(fs, X, val)                  \
  249.   do                                                    \
  250.     {                                                   \
  251.       union _FP_UNION_##fs *_FP_UNPACK_RAW_4_P_flo      \
  252.         = (union _FP_UNION_##fs *) (val);               \
  253.                                                         \
  254.       X##_f[0] = _FP_UNPACK_RAW_4_P_flo->bits.frac0;    \
  255.       X##_f[1] = _FP_UNPACK_RAW_4_P_flo->bits.frac1;    \
  256.       X##_f[2] = _FP_UNPACK_RAW_4_P_flo->bits.frac2;    \
  257.       X##_f[3] = _FP_UNPACK_RAW_4_P_flo->bits.frac3;    \
  258.       X##_e  = _FP_UNPACK_RAW_4_P_flo->bits.exp;        \
  259.       X##_s  = _FP_UNPACK_RAW_4_P_flo->bits.sign;       \
  260.     }                                                   \
  261.   while (0)
  262.  
  263. #define _FP_PACK_RAW_4(fs, val, X)              \
  264.   do                                            \
  265.     {                                           \
  266.       union _FP_UNION_##fs _FP_PACK_RAW_4_flo;  \
  267.       _FP_PACK_RAW_4_flo.bits.frac0 = X##_f[0]; \
  268.       _FP_PACK_RAW_4_flo.bits.frac1 = X##_f[1]; \
  269.       _FP_PACK_RAW_4_flo.bits.frac2 = X##_f[2]; \
  270.       _FP_PACK_RAW_4_flo.bits.frac3 = X##_f[3]; \
  271.       _FP_PACK_RAW_4_flo.bits.exp   = X##_e;    \
  272.       _FP_PACK_RAW_4_flo.bits.sign  = X##_s;    \
  273.       (val) = _FP_PACK_RAW_4_flo.flt;           \
  274.     }                                           \
  275.   while (0)
  276.  
  277. #define _FP_PACK_RAW_4_P(fs, val, X)                    \
  278.   do                                                    \
  279.     {                                                   \
  280.       union _FP_UNION_##fs *_FP_PACK_RAW_4_P_flo        \
  281.         = (union _FP_UNION_##fs *) (val);               \
  282.                                                         \
  283.       _FP_PACK_RAW_4_P_flo->bits.frac0 = X##_f[0];      \
  284.       _FP_PACK_RAW_4_P_flo->bits.frac1 = X##_f[1];      \
  285.       _FP_PACK_RAW_4_P_flo->bits.frac2 = X##_f[2];      \
  286.       _FP_PACK_RAW_4_P_flo->bits.frac3 = X##_f[3];      \
  287.       _FP_PACK_RAW_4_P_flo->bits.exp   = X##_e;         \
  288.       _FP_PACK_RAW_4_P_flo->bits.sign  = X##_s;         \
  289.     }                                                   \
  290.   while (0)
  291.  
  292. /* Multiplication algorithms: */
  293.  
  294. /* Given a 1W * 1W => 2W primitive, do the extended multiplication.  */
  295.  
  296. #define _FP_MUL_MEAT_DW_4_wide(wfracbits, R, X, Y, doit)                \
  297.   do                                                                    \
  298.     {                                                                   \
  299.       _FP_FRAC_DECL_2 (_FP_MUL_MEAT_DW_4_wide_b);                       \
  300.       _FP_FRAC_DECL_2 (_FP_MUL_MEAT_DW_4_wide_c);                       \
  301.       _FP_FRAC_DECL_2 (_FP_MUL_MEAT_DW_4_wide_d);                       \
  302.       _FP_FRAC_DECL_2 (_FP_MUL_MEAT_DW_4_wide_e);                       \
  303.       _FP_FRAC_DECL_2 (_FP_MUL_MEAT_DW_4_wide_f);                       \
  304.                                                                         \
  305.       doit (_FP_FRAC_WORD_8 (R, 1), _FP_FRAC_WORD_8 (R, 0),             \
  306.             X##_f[0], Y##_f[0]);                                        \
  307.       doit (_FP_MUL_MEAT_DW_4_wide_b_f1, _FP_MUL_MEAT_DW_4_wide_b_f0,   \
  308.             X##_f[0], Y##_f[1]);                                        \
  309.       doit (_FP_MUL_MEAT_DW_4_wide_c_f1, _FP_MUL_MEAT_DW_4_wide_c_f0,   \
  310.             X##_f[1], Y##_f[0]);                                        \
  311.       doit (_FP_MUL_MEAT_DW_4_wide_d_f1, _FP_MUL_MEAT_DW_4_wide_d_f0,   \
  312.             X##_f[1], Y##_f[1]);                                        \
  313.       doit (_FP_MUL_MEAT_DW_4_wide_e_f1, _FP_MUL_MEAT_DW_4_wide_e_f0,   \
  314.             X##_f[0], Y##_f[2]);                                        \
  315.       doit (_FP_MUL_MEAT_DW_4_wide_f_f1, _FP_MUL_MEAT_DW_4_wide_f_f0,   \
  316.             X##_f[2], Y##_f[0]);                                        \
  317.       __FP_FRAC_ADD_3 (_FP_FRAC_WORD_8 (R, 3), _FP_FRAC_WORD_8 (R, 2),  \
  318.                        _FP_FRAC_WORD_8 (R, 1), 0,                       \
  319.                        _FP_MUL_MEAT_DW_4_wide_b_f1,                     \
  320.                        _FP_MUL_MEAT_DW_4_wide_b_f0,                     \
  321.                        0, 0, _FP_FRAC_WORD_8 (R, 1));                   \
  322.       __FP_FRAC_ADD_3 (_FP_FRAC_WORD_8 (R, 3), _FP_FRAC_WORD_8 (R, 2),  \
  323.                        _FP_FRAC_WORD_8 (R, 1), 0,                       \
  324.                        _FP_MUL_MEAT_DW_4_wide_c_f1,                     \
  325.                        _FP_MUL_MEAT_DW_4_wide_c_f0,                     \
  326.                        _FP_FRAC_WORD_8 (R, 3), _FP_FRAC_WORD_8 (R, 2),  \
  327.                        _FP_FRAC_WORD_8 (R, 1));                         \
  328.       __FP_FRAC_ADD_3 (_FP_FRAC_WORD_8 (R, 4), _FP_FRAC_WORD_8 (R, 3),  \
  329.                        _FP_FRAC_WORD_8 (R, 2), 0,                       \
  330.                        _FP_MUL_MEAT_DW_4_wide_d_f1,                     \
  331.                        _FP_MUL_MEAT_DW_4_wide_d_f0,                     \
  332.                        0, _FP_FRAC_WORD_8 (R, 3), _FP_FRAC_WORD_8 (R, 2)); \
  333.       __FP_FRAC_ADD_3 (_FP_FRAC_WORD_8 (R, 4), _FP_FRAC_WORD_8 (R, 3),  \
  334.                        _FP_FRAC_WORD_8 (R, 2), 0,                       \
  335.                        _FP_MUL_MEAT_DW_4_wide_e_f1,                     \
  336.                        _FP_MUL_MEAT_DW_4_wide_e_f0,                     \
  337.                        _FP_FRAC_WORD_8 (R, 4), _FP_FRAC_WORD_8 (R, 3),  \
  338.                        _FP_FRAC_WORD_8 (R, 2));                         \
  339.       __FP_FRAC_ADD_3 (_FP_FRAC_WORD_8 (R, 4), _FP_FRAC_WORD_8 (R, 3),  \
  340.                        _FP_FRAC_WORD_8 (R, 2), 0,                       \
  341.                        _FP_MUL_MEAT_DW_4_wide_f_f1,                     \
  342.                        _FP_MUL_MEAT_DW_4_wide_f_f0,                     \
  343.                        _FP_FRAC_WORD_8 (R, 4), _FP_FRAC_WORD_8 (R, 3),  \
  344.                        _FP_FRAC_WORD_8 (R, 2));                         \
  345.       doit (_FP_MUL_MEAT_DW_4_wide_b_f1,                                \
  346.             _FP_MUL_MEAT_DW_4_wide_b_f0, X##_f[0], Y##_f[3]);           \
  347.       doit (_FP_MUL_MEAT_DW_4_wide_c_f1,                                \
  348.             _FP_MUL_MEAT_DW_4_wide_c_f0, X##_f[3], Y##_f[0]);           \
  349.       doit (_FP_MUL_MEAT_DW_4_wide_d_f1, _FP_MUL_MEAT_DW_4_wide_d_f0,   \
  350.             X##_f[1], Y##_f[2]);                                        \
  351.       doit (_FP_MUL_MEAT_DW_4_wide_e_f1, _FP_MUL_MEAT_DW_4_wide_e_f0,   \
  352.             X##_f[2], Y##_f[1]);                                        \
  353.       __FP_FRAC_ADD_3 (_FP_FRAC_WORD_8 (R, 5), _FP_FRAC_WORD_8 (R, 4),  \
  354.                        _FP_FRAC_WORD_8 (R, 3), 0,                       \
  355.                        _FP_MUL_MEAT_DW_4_wide_b_f1,                     \
  356.                        _FP_MUL_MEAT_DW_4_wide_b_f0,                     \
  357.                        0, _FP_FRAC_WORD_8 (R, 4), _FP_FRAC_WORD_8 (R, 3)); \
  358.       __FP_FRAC_ADD_3 (_FP_FRAC_WORD_8 (R, 5), _FP_FRAC_WORD_8 (R, 4),  \
  359.                        _FP_FRAC_WORD_8 (R, 3), 0,                       \
  360.                        _FP_MUL_MEAT_DW_4_wide_c_f1,                     \
  361.                        _FP_MUL_MEAT_DW_4_wide_c_f0,                     \
  362.                        _FP_FRAC_WORD_8 (R, 5), _FP_FRAC_WORD_8 (R, 4),  \
  363.                        _FP_FRAC_WORD_8 (R, 3));                         \
  364.       __FP_FRAC_ADD_3 (_FP_FRAC_WORD_8 (R, 5), _FP_FRAC_WORD_8 (R, 4),  \
  365.                        _FP_FRAC_WORD_8 (R, 3), 0,                       \
  366.                        _FP_MUL_MEAT_DW_4_wide_d_f1,                     \
  367.                        _FP_MUL_MEAT_DW_4_wide_d_f0,                     \
  368.                        _FP_FRAC_WORD_8 (R, 5), _FP_FRAC_WORD_8 (R, 4),  \
  369.                        _FP_FRAC_WORD_8 (R, 3));                         \
  370.       __FP_FRAC_ADD_3 (_FP_FRAC_WORD_8 (R, 5), _FP_FRAC_WORD_8 (R, 4),  \
  371.                        _FP_FRAC_WORD_8 (R, 3), 0,                       \
  372.                        _FP_MUL_MEAT_DW_4_wide_e_f1,                     \
  373.                        _FP_MUL_MEAT_DW_4_wide_e_f0,                     \
  374.                        _FP_FRAC_WORD_8 (R, 5), _FP_FRAC_WORD_8 (R, 4),  \
  375.                        _FP_FRAC_WORD_8 (R, 3));                         \
  376.       doit (_FP_MUL_MEAT_DW_4_wide_b_f1, _FP_MUL_MEAT_DW_4_wide_b_f0,   \
  377.             X##_f[2], Y##_f[2]);                                        \
  378.       doit (_FP_MUL_MEAT_DW_4_wide_c_f1, _FP_MUL_MEAT_DW_4_wide_c_f0,   \
  379.             X##_f[1], Y##_f[3]);                                        \
  380.       doit (_FP_MUL_MEAT_DW_4_wide_d_f1, _FP_MUL_MEAT_DW_4_wide_d_f0,   \
  381.             X##_f[3], Y##_f[1]);                                        \
  382.       doit (_FP_MUL_MEAT_DW_4_wide_e_f1, _FP_MUL_MEAT_DW_4_wide_e_f0,   \
  383.             X##_f[2], Y##_f[3]);                                        \
  384.       doit (_FP_MUL_MEAT_DW_4_wide_f_f1, _FP_MUL_MEAT_DW_4_wide_f_f0,   \
  385.             X##_f[3], Y##_f[2]);                                        \
  386.       __FP_FRAC_ADD_3 (_FP_FRAC_WORD_8 (R, 6), _FP_FRAC_WORD_8 (R, 5),  \
  387.                        _FP_FRAC_WORD_8 (R, 4), 0,                       \
  388.                        _FP_MUL_MEAT_DW_4_wide_b_f1,                     \
  389.                        _FP_MUL_MEAT_DW_4_wide_b_f0,                     \
  390.                        0, _FP_FRAC_WORD_8 (R, 5), _FP_FRAC_WORD_8 (R, 4)); \
  391.       __FP_FRAC_ADD_3 (_FP_FRAC_WORD_8 (R, 6), _FP_FRAC_WORD_8 (R, 5),  \
  392.                        _FP_FRAC_WORD_8 (R, 4), 0,                       \
  393.                        _FP_MUL_MEAT_DW_4_wide_c_f1,                     \
  394.                        _FP_MUL_MEAT_DW_4_wide_c_f0,                     \
  395.                        _FP_FRAC_WORD_8 (R, 6), _FP_FRAC_WORD_8 (R, 5),  \
  396.                        _FP_FRAC_WORD_8 (R, 4));                         \
  397.       __FP_FRAC_ADD_3 (_FP_FRAC_WORD_8 (R, 6), _FP_FRAC_WORD_8 (R, 5),  \
  398.                        _FP_FRAC_WORD_8 (R, 4), 0,                       \
  399.                        _FP_MUL_MEAT_DW_4_wide_d_f1,                     \
  400.                        _FP_MUL_MEAT_DW_4_wide_d_f0,                     \
  401.                        _FP_FRAC_WORD_8 (R, 6), _FP_FRAC_WORD_8 (R, 5),  \
  402.                        _FP_FRAC_WORD_8 (R, 4));                         \
  403.       __FP_FRAC_ADD_3 (_FP_FRAC_WORD_8 (R, 7), _FP_FRAC_WORD_8 (R, 6),  \
  404.                        _FP_FRAC_WORD_8 (R, 5), 0,                       \
  405.                        _FP_MUL_MEAT_DW_4_wide_e_f1,                     \
  406.                        _FP_MUL_MEAT_DW_4_wide_e_f0,                     \
  407.                        0, _FP_FRAC_WORD_8 (R, 6), _FP_FRAC_WORD_8 (R, 5)); \
  408.       __FP_FRAC_ADD_3 (_FP_FRAC_WORD_8 (R, 7), _FP_FRAC_WORD_8 (R, 6),  \
  409.                        _FP_FRAC_WORD_8 (R, 5), 0,                       \
  410.                        _FP_MUL_MEAT_DW_4_wide_f_f1,                     \
  411.                        _FP_MUL_MEAT_DW_4_wide_f_f0,                     \
  412.                        _FP_FRAC_WORD_8 (R, 7), _FP_FRAC_WORD_8 (R, 6),  \
  413.                        _FP_FRAC_WORD_8 (R, 5));                         \
  414.       doit (_FP_MUL_MEAT_DW_4_wide_b_f1, _FP_MUL_MEAT_DW_4_wide_b_f0,   \
  415.             X##_f[3], Y##_f[3]);                                        \
  416.       __FP_FRAC_ADD_2 (_FP_FRAC_WORD_8 (R, 7), _FP_FRAC_WORD_8 (R, 6),  \
  417.                        _FP_MUL_MEAT_DW_4_wide_b_f1,                     \
  418.                        _FP_MUL_MEAT_DW_4_wide_b_f0,                     \
  419.                        _FP_FRAC_WORD_8 (R, 7), _FP_FRAC_WORD_8 (R, 6)); \
  420.     }                                                                   \
  421.   while (0)
  422.  
  423. #define _FP_MUL_MEAT_4_wide(wfracbits, R, X, Y, doit)                   \
  424.   do                                                                    \
  425.     {                                                                   \
  426.       _FP_FRAC_DECL_8 (_FP_MUL_MEAT_4_wide_z);                          \
  427.                                                                         \
  428.       _FP_MUL_MEAT_DW_4_wide ((wfracbits), _FP_MUL_MEAT_4_wide_z,       \
  429.                               X, Y, doit);                              \
  430.                                                                         \
  431.       /* Normalize since we know where the msb of the multiplicands     \
  432.          were (bit B), we know that the msb of the of the product is    \
  433.          at either 2B or 2B-1.  */                                      \
  434.       _FP_FRAC_SRS_8 (_FP_MUL_MEAT_4_wide_z, (wfracbits)-1,             \
  435.                       2*(wfracbits));                                   \
  436.       __FP_FRAC_SET_4 (R, _FP_FRAC_WORD_8 (_FP_MUL_MEAT_4_wide_z, 3),   \
  437.                        _FP_FRAC_WORD_8 (_FP_MUL_MEAT_4_wide_z, 2),      \
  438.                        _FP_FRAC_WORD_8 (_FP_MUL_MEAT_4_wide_z, 1),      \
  439.                        _FP_FRAC_WORD_8 (_FP_MUL_MEAT_4_wide_z, 0));     \
  440.     }                                                                   \
  441.   while (0)
  442.  
  443. #define _FP_MUL_MEAT_DW_4_gmp(wfracbits, R, X, Y)       \
  444.   do                                                    \
  445.     {                                                   \
  446.       mpn_mul_n (R##_f, _x_f, _y_f, 4);                 \
  447.     }                                                   \
  448.   while (0)
  449.  
  450. #define _FP_MUL_MEAT_4_gmp(wfracbits, R, X, Y)                          \
  451.   do                                                                    \
  452.     {                                                                   \
  453.       _FP_FRAC_DECL_8 (_FP_MUL_MEAT_4_gmp_z);                           \
  454.                                                                         \
  455.       _FP_MUL_MEAT_DW_4_gmp ((wfracbits), _FP_MUL_MEAT_4_gmp_z, X, Y);  \
  456.                                                                         \
  457.       /* Normalize since we know where the msb of the multiplicands     \
  458.          were (bit B), we know that the msb of the of the product is    \
  459.          at either 2B or 2B-1.  */                                      \
  460.       _FP_FRAC_SRS_8 (_FP_MUL_MEAT_4_gmp_z, (wfracbits)-1,              \
  461.                       2*(wfracbits));                                   \
  462.       __FP_FRAC_SET_4 (R, _FP_FRAC_WORD_8 (_FP_MUL_MEAT_4_gmp_z, 3),    \
  463.                        _FP_FRAC_WORD_8 (_FP_MUL_MEAT_4_gmp_z, 2),       \
  464.                        _FP_FRAC_WORD_8 (_FP_MUL_MEAT_4_gmp_z, 1),       \
  465.                        _FP_FRAC_WORD_8 (_FP_MUL_MEAT_4_gmp_z, 0));      \
  466.     }                                                                   \
  467.   while (0)
  468.  
  469. /* Helper utility for _FP_DIV_MEAT_4_udiv:
  470.  * pppp = m * nnn.  */
  471. #define umul_ppppmnnn(p3, p2, p1, p0, m, n2, n1, n0)    \
  472.   do                                                    \
  473.     {                                                   \
  474.       UWtype umul_ppppmnnn_t;                           \
  475.       umul_ppmm (p1, p0, m, n0);                        \
  476.       umul_ppmm (p2, umul_ppppmnnn_t, m, n1);           \
  477.       __FP_FRAC_ADDI_2 (p2, p1, umul_ppppmnnn_t);       \
  478.       umul_ppmm (p3, umul_ppppmnnn_t, m, n2);           \
  479.       __FP_FRAC_ADDI_2 (p3, p2, umul_ppppmnnn_t);       \
  480.     }                                                   \
  481.   while (0)
  482.  
  483. /* Division algorithms: */
  484.  
  485. #define _FP_DIV_MEAT_4_udiv(fs, R, X, Y)                                \
  486.   do                                                                    \
  487.     {                                                                   \
  488.       int _FP_DIV_MEAT_4_udiv_i;                                        \
  489.       _FP_FRAC_DECL_4 (_FP_DIV_MEAT_4_udiv_n);                          \
  490.       _FP_FRAC_DECL_4 (_FP_DIV_MEAT_4_udiv_m);                          \
  491.       _FP_FRAC_SET_4 (_FP_DIV_MEAT_4_udiv_n, _FP_ZEROFRAC_4);           \
  492.       if (_FP_FRAC_GE_4 (X, Y))                                         \
  493.         {                                                               \
  494.           _FP_DIV_MEAT_4_udiv_n_f[3]                                    \
  495.             = X##_f[0] << (_FP_W_TYPE_SIZE - 1);                        \
  496.           _FP_FRAC_SRL_4 (X, 1);                                        \
  497.         }                                                               \
  498.       else                                                              \
  499.         R##_e--;                                                        \
  500.                                                                         \
  501.       /* Normalize, i.e. make the most significant bit of the           \
  502.          denominator set.  */                                           \
  503.       _FP_FRAC_SLL_4 (Y, _FP_WFRACXBITS_##fs);                          \
  504.                                                                         \
  505.       for (_FP_DIV_MEAT_4_udiv_i = 3; ; _FP_DIV_MEAT_4_udiv_i--)        \
  506.         {                                                               \
  507.           if (X##_f[3] == Y##_f[3])                                     \
  508.             {                                                           \
  509.               /* This is a special case, not an optimization            \
  510.                  (X##_f[3]/Y##_f[3] would not fit into UWtype).         \
  511.                  As X## is guaranteed to be < Y,                        \
  512.                  R##_f[_FP_DIV_MEAT_4_udiv_i] can be either             \
  513.                  (UWtype)-1 or (UWtype)-2.  */                          \
  514.               R##_f[_FP_DIV_MEAT_4_udiv_i] = -1;                        \
  515.               if (!_FP_DIV_MEAT_4_udiv_i)                               \
  516.                 break;                                                  \
  517.               __FP_FRAC_SUB_4 (X##_f[3], X##_f[2], X##_f[1], X##_f[0],  \
  518.                                Y##_f[2], Y##_f[1], Y##_f[0], 0,         \
  519.                                X##_f[2], X##_f[1], X##_f[0],            \
  520.                                _FP_DIV_MEAT_4_udiv_n_f[_FP_DIV_MEAT_4_udiv_i]); \
  521.               _FP_FRAC_SUB_4 (X, Y, X);                                 \
  522.               if (X##_f[3] > Y##_f[3])                                  \
  523.                 {                                                       \
  524.                   R##_f[_FP_DIV_MEAT_4_udiv_i] = -2;                    \
  525.                   _FP_FRAC_ADD_4 (X, Y, X);                             \
  526.                 }                                                       \
  527.             }                                                           \
  528.           else                                                          \
  529.             {                                                           \
  530.               udiv_qrnnd (R##_f[_FP_DIV_MEAT_4_udiv_i],                 \
  531.                           X##_f[3], X##_f[3], X##_f[2], Y##_f[3]);      \
  532.               umul_ppppmnnn (_FP_DIV_MEAT_4_udiv_m_f[3],                \
  533.                              _FP_DIV_MEAT_4_udiv_m_f[2],                \
  534.                              _FP_DIV_MEAT_4_udiv_m_f[1],                \
  535.                              _FP_DIV_MEAT_4_udiv_m_f[0],                \
  536.                              R##_f[_FP_DIV_MEAT_4_udiv_i],              \
  537.                              Y##_f[2], Y##_f[1], Y##_f[0]);             \
  538.               X##_f[2] = X##_f[1];                                      \
  539.               X##_f[1] = X##_f[0];                                      \
  540.               X##_f[0]                                                  \
  541.                 = _FP_DIV_MEAT_4_udiv_n_f[_FP_DIV_MEAT_4_udiv_i];       \
  542.               if (_FP_FRAC_GT_4 (_FP_DIV_MEAT_4_udiv_m, X))             \
  543.                 {                                                       \
  544.                   R##_f[_FP_DIV_MEAT_4_udiv_i]--;                       \
  545.                   _FP_FRAC_ADD_4 (X, Y, X);                             \
  546.                   if (_FP_FRAC_GE_4 (X, Y)                              \
  547.                       && _FP_FRAC_GT_4 (_FP_DIV_MEAT_4_udiv_m, X))      \
  548.                     {                                                   \
  549.                       R##_f[_FP_DIV_MEAT_4_udiv_i]--;                   \
  550.                       _FP_FRAC_ADD_4 (X, Y, X);                         \
  551.                     }                                                   \
  552.                 }                                                       \
  553.               _FP_FRAC_DEC_4 (X, _FP_DIV_MEAT_4_udiv_m);                \
  554.               if (!_FP_DIV_MEAT_4_udiv_i)                               \
  555.                 {                                                       \
  556.                   if (!_FP_FRAC_EQ_4 (X, _FP_DIV_MEAT_4_udiv_m))        \
  557.                     R##_f[0] |= _FP_WORK_STICKY;                        \
  558.                   break;                                                \
  559.                 }                                                       \
  560.             }                                                           \
  561.         }                                                               \
  562.     }                                                                   \
  563.   while (0)
  564.  
  565.  
  566. /* Square root algorithms:
  567.    We have just one right now, maybe Newton approximation
  568.    should be added for those machines where division is fast.  */
  569.  
  570. #define _FP_SQRT_MEAT_4(R, S, T, X, q)                                  \
  571.   do                                                                    \
  572.     {                                                                   \
  573.       while (q)                                                         \
  574.         {                                                               \
  575.           T##_f[3] = S##_f[3] + (q);                                    \
  576.           if (T##_f[3] <= X##_f[3])                                     \
  577.             {                                                           \
  578.               S##_f[3] = T##_f[3] + (q);                                \
  579.               X##_f[3] -= T##_f[3];                                     \
  580.               R##_f[3] += (q);                                          \
  581.             }                                                           \
  582.           _FP_FRAC_SLL_4 (X, 1);                                        \
  583.           (q) >>= 1;                                                    \
  584.         }                                                               \
  585.       (q) = (_FP_W_TYPE) 1 << (_FP_W_TYPE_SIZE - 1);                    \
  586.       while (q)                                                         \
  587.         {                                                               \
  588.           T##_f[2] = S##_f[2] + (q);                                    \
  589.           T##_f[3] = S##_f[3];                                          \
  590.           if (T##_f[3] < X##_f[3]                                       \
  591.               || (T##_f[3] == X##_f[3] && T##_f[2] <= X##_f[2]))        \
  592.             {                                                           \
  593.               S##_f[2] = T##_f[2] + (q);                                \
  594.               S##_f[3] += (T##_f[2] > S##_f[2]);                        \
  595.               __FP_FRAC_DEC_2 (X##_f[3], X##_f[2],                      \
  596.                                T##_f[3], T##_f[2]);                     \
  597.               R##_f[2] += (q);                                          \
  598.             }                                                           \
  599.           _FP_FRAC_SLL_4 (X, 1);                                        \
  600.           (q) >>= 1;                                                    \
  601.         }                                                               \
  602.       (q) = (_FP_W_TYPE) 1 << (_FP_W_TYPE_SIZE - 1);                    \
  603.       while (q)                                                         \
  604.         {                                                               \
  605.           T##_f[1] = S##_f[1] + (q);                                    \
  606.           T##_f[2] = S##_f[2];                                          \
  607.           T##_f[3] = S##_f[3];                                          \
  608.           if (T##_f[3] < X##_f[3]                                       \
  609.               || (T##_f[3] == X##_f[3]                                  \
  610.                   && (T##_f[2] < X##_f[2]                               \
  611.                       || (T##_f[2] == X##_f[2]                          \
  612.                           && T##_f[1] <= X##_f[1]))))                   \
  613.             {                                                           \
  614.               S##_f[1] = T##_f[1] + (q);                                \
  615.               S##_f[2] += (T##_f[1] > S##_f[1]);                        \
  616.               S##_f[3] += (T##_f[2] > S##_f[2]);                        \
  617.               __FP_FRAC_DEC_3 (X##_f[3], X##_f[2], X##_f[1],            \
  618.                                T##_f[3], T##_f[2], T##_f[1]);           \
  619.               R##_f[1] += (q);                                          \
  620.             }                                                           \
  621.           _FP_FRAC_SLL_4 (X, 1);                                        \
  622.           (q) >>= 1;                                                    \
  623.         }                                                               \
  624.       (q) = (_FP_W_TYPE) 1 << (_FP_W_TYPE_SIZE - 1);                    \
  625.       while ((q) != _FP_WORK_ROUND)                                     \
  626.         {                                                               \
  627.           T##_f[0] = S##_f[0] + (q);                                    \
  628.           T##_f[1] = S##_f[1];                                          \
  629.           T##_f[2] = S##_f[2];                                          \
  630.           T##_f[3] = S##_f[3];                                          \
  631.           if (_FP_FRAC_GE_4 (X, T))                                     \
  632.             {                                                           \
  633.               S##_f[0] = T##_f[0] + (q);                                \
  634.               S##_f[1] += (T##_f[0] > S##_f[0]);                        \
  635.               S##_f[2] += (T##_f[1] > S##_f[1]);                        \
  636.               S##_f[3] += (T##_f[2] > S##_f[2]);                        \
  637.               _FP_FRAC_DEC_4 (X, T);                                    \
  638.               R##_f[0] += (q);                                          \
  639.             }                                                           \
  640.           _FP_FRAC_SLL_4 (X, 1);                                        \
  641.           (q) >>= 1;                                                    \
  642.         }                                                               \
  643.       if (!_FP_FRAC_ZEROP_4 (X))                                        \
  644.         {                                                               \
  645.           if (_FP_FRAC_GT_4 (X, S))                                     \
  646.             R##_f[0] |= _FP_WORK_ROUND;                                 \
  647.           R##_f[0] |= _FP_WORK_STICKY;                                  \
  648.         }                                                               \
  649.     }                                                                   \
  650.   while (0)
  651.  
  652.  
  653. /* Internals.  */
  654.  
  655. #define __FP_FRAC_SET_4(X, I3, I2, I1, I0)                      \
  656.   (X##_f[3] = I3, X##_f[2] = I2, X##_f[1] = I1, X##_f[0] = I0)
  657.  
  658. #ifndef __FP_FRAC_ADD_3
  659. # define __FP_FRAC_ADD_3(r2, r1, r0, x2, x1, x0, y2, y1, y0)    \
  660.   do                                                            \
  661.     {                                                           \
  662.       _FP_W_TYPE __FP_FRAC_ADD_3_c1, __FP_FRAC_ADD_3_c2;        \
  663.       r0 = x0 + y0;                                             \
  664.       __FP_FRAC_ADD_3_c1 = r0 < x0;                             \
  665.       r1 = x1 + y1;                                             \
  666.       __FP_FRAC_ADD_3_c2 = r1 < x1;                             \
  667.       r1 += __FP_FRAC_ADD_3_c1;                                 \
  668.       __FP_FRAC_ADD_3_c2 |= r1 < __FP_FRAC_ADD_3_c1;            \
  669.       r2 = x2 + y2 + __FP_FRAC_ADD_3_c2;                        \
  670.     }                                                           \
  671.   while (0)
  672. #endif
  673.  
  674. #ifndef __FP_FRAC_ADD_4
  675. # define __FP_FRAC_ADD_4(r3, r2, r1, r0, x3, x2, x1, x0, y3, y2, y1, y0) \
  676.   do                                                                    \
  677.     {                                                                   \
  678.       _FP_W_TYPE __FP_FRAC_ADD_4_c1, __FP_FRAC_ADD_4_c2;                \
  679.       _FP_W_TYPE __FP_FRAC_ADD_4_c3;                                    \
  680.       r0 = x0 + y0;                                                     \
  681.       __FP_FRAC_ADD_4_c1 = r0 < x0;                                     \
  682.       r1 = x1 + y1;                                                     \
  683.       __FP_FRAC_ADD_4_c2 = r1 < x1;                                     \
  684.       r1 += __FP_FRAC_ADD_4_c1;                                         \
  685.       __FP_FRAC_ADD_4_c2 |= r1 < __FP_FRAC_ADD_4_c1;                    \
  686.       r2 = x2 + y2;                                                     \
  687.       __FP_FRAC_ADD_4_c3 = r2 < x2;                                     \
  688.       r2 += __FP_FRAC_ADD_4_c2;                                         \
  689.       __FP_FRAC_ADD_4_c3 |= r2 < __FP_FRAC_ADD_4_c2;                    \
  690.       r3 = x3 + y3 + __FP_FRAC_ADD_4_c3;                                \
  691.     }                                                                   \
  692.   while (0)
  693. #endif
  694.  
  695. #ifndef __FP_FRAC_SUB_3
  696. # define __FP_FRAC_SUB_3(r2, r1, r0, x2, x1, x0, y2, y1, y0)    \
  697.   do                                                            \
  698.     {                                                           \
  699.       _FP_W_TYPE __FP_FRAC_SUB_3_c1, __FP_FRAC_SUB_3_c2;        \
  700.       r0 = x0 - y0;                                             \
  701.       __FP_FRAC_SUB_3_c1 = r0 > x0;                             \
  702.       r1 = x1 - y1;                                             \
  703.       __FP_FRAC_SUB_3_c2 = r1 > x1;                             \
  704.       r1 -= __FP_FRAC_SUB_3_c1;                                 \
  705.       __FP_FRAC_SUB_3_c2 |= __FP_FRAC_SUB_3_c1 && (y1 == x1);   \
  706.       r2 = x2 - y2 - __FP_FRAC_SUB_3_c2;                        \
  707.     }                                                           \
  708.   while (0)
  709. #endif
  710.  
  711. #ifndef __FP_FRAC_SUB_4
  712. # define __FP_FRAC_SUB_4(r3, r2, r1, r0, x3, x2, x1, x0, y3, y2, y1, y0) \
  713.   do                                                                    \
  714.     {                                                                   \
  715.       _FP_W_TYPE __FP_FRAC_SUB_4_c1, __FP_FRAC_SUB_4_c2;                \
  716.       _FP_W_TYPE __FP_FRAC_SUB_4_c3;                                    \
  717.       r0 = x0 - y0;                                                     \
  718.       __FP_FRAC_SUB_4_c1 = r0 > x0;                                     \
  719.       r1 = x1 - y1;                                                     \
  720.       __FP_FRAC_SUB_4_c2 = r1 > x1;                                     \
  721.       r1 -= __FP_FRAC_SUB_4_c1;                                         \
  722.       __FP_FRAC_SUB_4_c2 |= __FP_FRAC_SUB_4_c1 && (y1 == x1);           \
  723.       r2 = x2 - y2;                                                     \
  724.       __FP_FRAC_SUB_4_c3 = r2 > x2;                                     \
  725.       r2 -= __FP_FRAC_SUB_4_c2;                                         \
  726.       __FP_FRAC_SUB_4_c3 |= __FP_FRAC_SUB_4_c2 && (y2 == x2);           \
  727.       r3 = x3 - y3 - __FP_FRAC_SUB_4_c3;                                \
  728.     }                                                                   \
  729.   while (0)
  730. #endif
  731.  
  732. #ifndef __FP_FRAC_DEC_3
  733. # define __FP_FRAC_DEC_3(x2, x1, x0, y2, y1, y0)                \
  734.   do                                                            \
  735.     {                                                           \
  736.       UWtype __FP_FRAC_DEC_3_t0, __FP_FRAC_DEC_3_t1;            \
  737.       UWtype __FP_FRAC_DEC_3_t2;                                \
  738.       __FP_FRAC_DEC_3_t0 = x0;                                  \
  739.       __FP_FRAC_DEC_3_t1 = x1;                                  \
  740.       __FP_FRAC_DEC_3_t2 = x2;                                  \
  741.       __FP_FRAC_SUB_3 (x2, x1, x0, __FP_FRAC_DEC_3_t2,          \
  742.                        __FP_FRAC_DEC_3_t1, __FP_FRAC_DEC_3_t0,  \
  743.                        y2, y1, y0);                             \
  744.     }                                                           \
  745.   while (0)
  746. #endif
  747.  
  748. #ifndef __FP_FRAC_DEC_4
  749. # define __FP_FRAC_DEC_4(x3, x2, x1, x0, y3, y2, y1, y0)        \
  750.   do                                                            \
  751.     {                                                           \
  752.       UWtype __FP_FRAC_DEC_4_t0, __FP_FRAC_DEC_4_t1;            \
  753.       UWtype __FP_FRAC_DEC_4_t2, __FP_FRAC_DEC_4_t3;            \
  754.       __FP_FRAC_DEC_4_t0 = x0;                                  \
  755.       __FP_FRAC_DEC_4_t1 = x1;                                  \
  756.       __FP_FRAC_DEC_4_t2 = x2;                                  \
  757.       __FP_FRAC_DEC_4_t3 = x3;                                  \
  758.       __FP_FRAC_SUB_4 (x3, x2, x1, x0, __FP_FRAC_DEC_4_t3,      \
  759.                        __FP_FRAC_DEC_4_t2, __FP_FRAC_DEC_4_t1,  \
  760.                        __FP_FRAC_DEC_4_t0, y3, y2, y1, y0);     \
  761.     }                                                           \
  762.   while (0)
  763. #endif
  764.  
  765. #ifndef __FP_FRAC_ADDI_4
  766. # define __FP_FRAC_ADDI_4(x3, x2, x1, x0, i)            \
  767.   do                                                    \
  768.     {                                                   \
  769.       UWtype __FP_FRAC_ADDI_4_t;                        \
  770.       __FP_FRAC_ADDI_4_t = ((x0 += i) < i);             \
  771.       x1 += __FP_FRAC_ADDI_4_t;                         \
  772.       __FP_FRAC_ADDI_4_t = (x1 < __FP_FRAC_ADDI_4_t);   \
  773.       x2 += __FP_FRAC_ADDI_4_t;                         \
  774.       __FP_FRAC_ADDI_4_t = (x2 < __FP_FRAC_ADDI_4_t);   \
  775.       x3 += __FP_FRAC_ADDI_4_t;                         \
  776.     }                                                   \
  777.   while (0)
  778. #endif
  779.  
  780. /* Convert FP values between word sizes. This appears to be more
  781.    complicated than I'd have expected it to be, so these might be
  782.    wrong... These macros are in any case somewhat bogus because they
  783.    use information about what various FRAC_n variables look like
  784.    internally [eg, that 2 word vars are X_f0 and x_f1]. But so do
  785.    the ones in op-2.h and op-1.h.  */
  786. #define _FP_FRAC_COPY_1_4(D, S)         (D##_f = S##_f[0])
  787.  
  788. #define _FP_FRAC_COPY_2_4(D, S)                 \
  789.   do                                            \
  790.     {                                           \
  791.       D##_f0 = S##_f[0];                        \
  792.       D##_f1 = S##_f[1];                        \
  793.     }                                           \
  794.   while (0)
  795.  
  796. /* Assembly/disassembly for converting to/from integral types.
  797.    No shifting or overflow handled here.  */
  798. /* Put the FP value X into r, which is an integer of size rsize.  */
  799. #define _FP_FRAC_ASSEMBLE_4(r, X, rsize)                                \
  800.   do                                                                    \
  801.     {                                                                   \
  802.       if ((rsize) <= _FP_W_TYPE_SIZE)                                   \
  803.         (r) = X##_f[0];                                                 \
  804.         else if ((rsize) <= 2*_FP_W_TYPE_SIZE)                          \
  805.         {                                                               \
  806.           (r) = X##_f[1];                                               \
  807.           (r) = ((rsize) <= _FP_W_TYPE_SIZE                             \
  808.                  ? 0                                                    \
  809.                  : (r) << _FP_W_TYPE_SIZE);                             \
  810.           (r) += X##_f[0];                                              \
  811.         }                                                               \
  812.       else                                                              \
  813.         {                                                               \
  814.           /* I'm feeling lazy so we deal with int == 3words             \
  815.              (implausible) and int == 4words as a single case.  */      \
  816.           (r) = X##_f[3];                                               \
  817.           (r) = ((rsize) <= _FP_W_TYPE_SIZE                             \
  818.                  ? 0                                                    \
  819.                  : (r) << _FP_W_TYPE_SIZE);                             \
  820.           (r) += X##_f[2];                                              \
  821.           (r) = ((rsize) <= _FP_W_TYPE_SIZE                             \
  822.                  ? 0                                                    \
  823.                  : (r) << _FP_W_TYPE_SIZE);                             \
  824.           (r) += X##_f[1];                                              \
  825.           (r) = ((rsize) <= _FP_W_TYPE_SIZE                             \
  826.                  ? 0                                                    \
  827.                  : (r) << _FP_W_TYPE_SIZE);                             \
  828.           (r) += X##_f[0];                                              \
  829.         }                                                               \
  830.     }                                                                   \
  831.   while (0)
  832.  
  833. /* "No disassemble Number Five!" */
  834. /* Move an integer of size rsize into X's fractional part. We rely on
  835.    the _f[] array consisting of words of size _FP_W_TYPE_SIZE to avoid
  836.    having to mask the values we store into it.  */
  837. #define _FP_FRAC_DISASSEMBLE_4(X, r, rsize)     \
  838.   do                                            \
  839.     {                                           \
  840.       X##_f[0] = (r);                           \
  841.       X##_f[1] = ((rsize) <= _FP_W_TYPE_SIZE    \
  842.                   ? 0                           \
  843.                   : (r) >> _FP_W_TYPE_SIZE);    \
  844.       X##_f[2] = ((rsize) <= 2*_FP_W_TYPE_SIZE  \
  845.                   ? 0                           \
  846.                   : (r) >> 2*_FP_W_TYPE_SIZE);  \
  847.       X##_f[3] = ((rsize) <= 3*_FP_W_TYPE_SIZE  \
  848.                   ? 0                           \
  849.                   : (r) >> 3*_FP_W_TYPE_SIZE);  \
  850.     }                                           \
  851.   while (0)
  852.  
  853. #define _FP_FRAC_COPY_4_1(D, S)                 \
  854.   do                                            \
  855.     {                                           \
  856.       D##_f[0] = S##_f;                         \
  857.       D##_f[1] = D##_f[2] = D##_f[3] = 0;       \
  858.     }                                           \
  859.   while (0)
  860.  
  861. #define _FP_FRAC_COPY_4_2(D, S)                 \
  862.   do                                            \
  863.     {                                           \
  864.       D##_f[0] = S##_f0;                        \
  865.       D##_f[1] = S##_f1;                        \
  866.       D##_f[2] = D##_f[3] = 0;                  \
  867.     }                                           \
  868.   while (0)
  869.  
  870. #define _FP_FRAC_COPY_4_4(D, S) _FP_FRAC_COPY_4 (D, S)
  871.