1 /* Software floating-point emulation.
2    Basic four-word fraction declaration and manipulation.
3    Copyright (C) 1997-2022 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 */
879