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