aboutsummaryrefslogtreecommitdiffstats
path: root/include/math-emu
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@ppc970.osdl.org>2005-04-16 18:20:36 -0400
committerLinus Torvalds <torvalds@ppc970.osdl.org>2005-04-16 18:20:36 -0400
commit1da177e4c3f41524e886b7f1b8a0c1fc7321cac2 (patch)
tree0bba044c4ce775e45a88a51686b5d9f90697ea9d /include/math-emu
Linux-2.6.12-rc2v2.6.12-rc2
Initial git repository build. I'm not bothering with the full history, even though we have it. We can create a separate "historical" git archive of that later if we want to, and in the meantime it's about 3.2GB when imported into git - space that would just make the early git days unnecessarily complicated, when we don't have a lot of good infrastructure for it. Let it rip!
Diffstat (limited to 'include/math-emu')
-rw-r--r--include/math-emu/double.h205
-rw-r--r--include/math-emu/extended.h396
-rw-r--r--include/math-emu/op-1.h303
-rw-r--r--include/math-emu/op-2.h613
-rw-r--r--include/math-emu/op-4.h692
-rw-r--r--include/math-emu/op-8.h107
-rw-r--r--include/math-emu/op-common.h853
-rw-r--r--include/math-emu/quad.h208
-rw-r--r--include/math-emu/single.h116
-rw-r--r--include/math-emu/soft-fp.h181
10 files changed, 3674 insertions, 0 deletions
diff --git a/include/math-emu/double.h b/include/math-emu/double.h
new file mode 100644
index 000000000000..655ccf1c4739
--- /dev/null
+++ b/include/math-emu/double.h
@@ -0,0 +1,205 @@
1/* Software floating-point emulation.
2 Definitions for IEEE Double Precision
3 Copyright (C) 1997,1998,1999 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 Library General Public License as
12 published by the Free Software Foundation; either version 2 of the
13 License, or (at your option) any later version.
14
15 The GNU C Library is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 Library General Public License for more details.
19
20 You should have received a copy of the GNU Library General Public
21 License along with the GNU C Library; see the file COPYING.LIB. If
22 not, write to the Free Software Foundation, Inc.,
23 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
24
25#ifndef __MATH_EMU_DOUBLE_H__
26#define __MATH_EMU_DOUBLE_H__
27
28#if _FP_W_TYPE_SIZE < 32
29#error "Here's a nickel kid. Go buy yourself a real computer."
30#endif
31
32#if _FP_W_TYPE_SIZE < 64
33#define _FP_FRACTBITS_D (2 * _FP_W_TYPE_SIZE)
34#else
35#define _FP_FRACTBITS_D _FP_W_TYPE_SIZE
36#endif
37
38#define _FP_FRACBITS_D 53
39#define _FP_FRACXBITS_D (_FP_FRACTBITS_D - _FP_FRACBITS_D)
40#define _FP_WFRACBITS_D (_FP_WORKBITS + _FP_FRACBITS_D)
41#define _FP_WFRACXBITS_D (_FP_FRACTBITS_D - _FP_WFRACBITS_D)
42#define _FP_EXPBITS_D 11
43#define _FP_EXPBIAS_D 1023
44#define _FP_EXPMAX_D 2047
45
46#define _FP_QNANBIT_D \
47 ((_FP_W_TYPE)1 << (_FP_FRACBITS_D-2) % _FP_W_TYPE_SIZE)
48#define _FP_IMPLBIT_D \
49 ((_FP_W_TYPE)1 << (_FP_FRACBITS_D-1) % _FP_W_TYPE_SIZE)
50#define _FP_OVERFLOW_D \
51 ((_FP_W_TYPE)1 << _FP_WFRACBITS_D % _FP_W_TYPE_SIZE)
52
53#if _FP_W_TYPE_SIZE < 64
54
55union _FP_UNION_D
56{
57 double flt;
58 struct {
59#if __BYTE_ORDER == __BIG_ENDIAN
60 unsigned sign : 1;
61 unsigned exp : _FP_EXPBITS_D;
62 unsigned frac1 : _FP_FRACBITS_D - (_FP_IMPLBIT_D != 0) - _FP_W_TYPE_SIZE;
63 unsigned frac0 : _FP_W_TYPE_SIZE;
64#else
65 unsigned frac0 : _FP_W_TYPE_SIZE;
66 unsigned frac1 : _FP_FRACBITS_D - (_FP_IMPLBIT_D != 0) - _FP_W_TYPE_SIZE;
67 unsigned exp : _FP_EXPBITS_D;
68 unsigned sign : 1;
69#endif
70 } bits __attribute__((packed));
71};
72
73#define FP_DECL_D(X) _FP_DECL(2,X)
74#define FP_UNPACK_RAW_D(X,val) _FP_UNPACK_RAW_2(D,X,val)
75#define FP_UNPACK_RAW_DP(X,val) _FP_UNPACK_RAW_2_P(D,X,val)
76#define FP_PACK_RAW_D(val,X) _FP_PACK_RAW_2(D,val,X)
77#define FP_PACK_RAW_DP(val,X) \
78 do { \
79 if (!FP_INHIBIT_RESULTS) \
80 _FP_PACK_RAW_2_P(D,val,X); \
81 } while (0)
82
83#define FP_UNPACK_D(X,val) \
84 do { \
85 _FP_UNPACK_RAW_2(D,X,val); \
86 _FP_UNPACK_CANONICAL(D,2,X); \
87 } while (0)
88
89#define FP_UNPACK_DP(X,val) \
90 do { \
91 _FP_UNPACK_RAW_2_P(D,X,val); \
92 _FP_UNPACK_CANONICAL(D,2,X); \
93 } while (0)
94
95#define FP_PACK_D(val,X) \
96 do { \
97 _FP_PACK_CANONICAL(D,2,X); \
98 _FP_PACK_RAW_2(D,val,X); \
99 } while (0)
100
101#define FP_PACK_DP(val,X) \
102 do { \
103 _FP_PACK_CANONICAL(D,2,X); \
104 if (!FP_INHIBIT_RESULTS) \
105 _FP_PACK_RAW_2_P(D,val,X); \
106 } while (0)
107
108#define FP_ISSIGNAN_D(X) _FP_ISSIGNAN(D,2,X)
109#define FP_NEG_D(R,X) _FP_NEG(D,2,R,X)
110#define FP_ADD_D(R,X,Y) _FP_ADD(D,2,R,X,Y)
111#define FP_SUB_D(R,X,Y) _FP_SUB(D,2,R,X,Y)
112#define FP_MUL_D(R,X,Y) _FP_MUL(D,2,R,X,Y)
113#define FP_DIV_D(R,X,Y) _FP_DIV(D,2,R,X,Y)
114#define FP_SQRT_D(R,X) _FP_SQRT(D,2,R,X)
115#define _FP_SQRT_MEAT_D(R,S,T,X,Q) _FP_SQRT_MEAT_2(R,S,T,X,Q)
116
117#define FP_CMP_D(r,X,Y,un) _FP_CMP(D,2,r,X,Y,un)
118#define FP_CMP_EQ_D(r,X,Y) _FP_CMP_EQ(D,2,r,X,Y)
119
120#define FP_TO_INT_D(r,X,rsz,rsg) _FP_TO_INT(D,2,r,X,rsz,rsg)
121#define FP_TO_INT_ROUND_D(r,X,rsz,rsg) _FP_TO_INT_ROUND(D,2,r,X,rsz,rsg)
122#define FP_FROM_INT_D(X,r,rs,rt) _FP_FROM_INT(D,2,X,r,rs,rt)
123
124#define _FP_FRAC_HIGH_D(X) _FP_FRAC_HIGH_2(X)
125#define _FP_FRAC_HIGH_RAW_D(X) _FP_FRAC_HIGH_2(X)
126
127#else
128
129union _FP_UNION_D
130{
131 double flt;
132 struct {
133#if __BYTE_ORDER == __BIG_ENDIAN
134 unsigned sign : 1;
135 unsigned exp : _FP_EXPBITS_D;
136 unsigned long frac : _FP_FRACBITS_D - (_FP_IMPLBIT_D != 0);
137#else
138 unsigned long frac : _FP_FRACBITS_D - (_FP_IMPLBIT_D != 0);
139 unsigned exp : _FP_EXPBITS_D;
140 unsigned sign : 1;
141#endif
142 } bits __attribute__((packed));
143};
144
145#define FP_DECL_D(X) _FP_DECL(1,X)
146#define FP_UNPACK_RAW_D(X,val) _FP_UNPACK_RAW_1(D,X,val)
147#define FP_UNPACK_RAW_DP(X,val) _FP_UNPACK_RAW_1_P(D,X,val)
148#define FP_PACK_RAW_D(val,X) _FP_PACK_RAW_1(D,val,X)
149#define FP_PACK_RAW_DP(val,X) \
150 do { \
151 if (!FP_INHIBIT_RESULTS) \
152 _FP_PACK_RAW_1_P(D,val,X); \
153 } while (0)
154
155#define FP_UNPACK_D(X,val) \
156 do { \
157 _FP_UNPACK_RAW_1(D,X,val); \
158 _FP_UNPACK_CANONICAL(D,1,X); \
159 } while (0)
160
161#define FP_UNPACK_DP(X,val) \
162 do { \
163 _FP_UNPACK_RAW_1_P(D,X,val); \
164 _FP_UNPACK_CANONICAL(D,1,X); \
165 } while (0)
166
167#define FP_PACK_D(val,X) \
168 do { \
169 _FP_PACK_CANONICAL(D,1,X); \
170 _FP_PACK_RAW_1(D,val,X); \
171 } while (0)
172
173#define FP_PACK_DP(val,X) \
174 do { \
175 _FP_PACK_CANONICAL(D,1,X); \
176 if (!FP_INHIBIT_RESULTS) \
177 _FP_PACK_RAW_1_P(D,val,X); \
178 } while (0)
179
180#define FP_ISSIGNAN_D(X) _FP_ISSIGNAN(D,1,X)
181#define FP_NEG_D(R,X) _FP_NEG(D,1,R,X)
182#define FP_ADD_D(R,X,Y) _FP_ADD(D,1,R,X,Y)
183#define FP_SUB_D(R,X,Y) _FP_SUB(D,1,R,X,Y)
184#define FP_MUL_D(R,X,Y) _FP_MUL(D,1,R,X,Y)
185#define FP_DIV_D(R,X,Y) _FP_DIV(D,1,R,X,Y)
186#define FP_SQRT_D(R,X) _FP_SQRT(D,1,R,X)
187#define _FP_SQRT_MEAT_D(R,S,T,X,Q) _FP_SQRT_MEAT_1(R,S,T,X,Q)
188
189/* The implementation of _FP_MUL_D and _FP_DIV_D should be chosen by
190 the target machine. */
191
192#define FP_CMP_D(r,X,Y,un) _FP_CMP(D,1,r,X,Y,un)
193#define FP_CMP_EQ_D(r,X,Y) _FP_CMP_EQ(D,1,r,X,Y)
194
195#define FP_TO_INT_D(r,X,rsz,rsg) _FP_TO_INT(D,1,r,X,rsz,rsg)
196#define FP_TO_INT_ROUND_D(r,X,rsz,rsg) _FP_TO_INT_ROUND(D,1,r,X,rsz,rsg)
197#define FP_FROM_INT_D(X,r,rs,rt) _FP_FROM_INT(D,1,X,r,rs,rt)
198
199#define _FP_FRAC_HIGH_D(X) _FP_FRAC_HIGH_1(X)
200#define _FP_FRAC_HIGH_RAW_D(X) _FP_FRAC_HIGH_1(X)
201
202#endif /* W_TYPE_SIZE < 64 */
203
204
205#endif /* __MATH_EMU_DOUBLE_H__ */
diff --git a/include/math-emu/extended.h b/include/math-emu/extended.h
new file mode 100644
index 000000000000..84770fceb53e
--- /dev/null
+++ b/include/math-emu/extended.h
@@ -0,0 +1,396 @@
1/* Software floating-point emulation.
2 Definitions for IEEE Extended Precision.
3 Copyright (C) 1999 Free Software Foundation, Inc.
4 This file is part of the GNU C Library.
5 Contributed by Jakub Jelinek (jj@ultra.linux.cz).
6
7 The GNU C Library is free software; you can redistribute it and/or
8 modify it under the terms of the GNU Library General Public License as
9 published by the Free Software Foundation; either version 2 of the
10 License, or (at your option) any later version.
11
12 The GNU C Library is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 Library General Public License for more details.
16
17 You should have received a copy of the GNU Library General Public
18 License along with the GNU C Library; see the file COPYING.LIB. If
19 not, write to the Free Software Foundation, Inc.,
20 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
21
22
23#ifndef __MATH_EMU_EXTENDED_H__
24#define __MATH_EMU_EXTENDED_H__
25
26#if _FP_W_TYPE_SIZE < 32
27#error "Here's a nickel, kid. Go buy yourself a real computer."
28#endif
29
30#if _FP_W_TYPE_SIZE < 64
31#define _FP_FRACTBITS_E (4*_FP_W_TYPE_SIZE)
32#else
33#define _FP_FRACTBITS_E (2*_FP_W_TYPE_SIZE)
34#endif
35
36#define _FP_FRACBITS_E 64
37#define _FP_FRACXBITS_E (_FP_FRACTBITS_E - _FP_FRACBITS_E)
38#define _FP_WFRACBITS_E (_FP_WORKBITS + _FP_FRACBITS_E)
39#define _FP_WFRACXBITS_E (_FP_FRACTBITS_E - _FP_WFRACBITS_E)
40#define _FP_EXPBITS_E 15
41#define _FP_EXPBIAS_E 16383
42#define _FP_EXPMAX_E 32767
43
44#define _FP_QNANBIT_E \
45 ((_FP_W_TYPE)1 << (_FP_FRACBITS_E-2) % _FP_W_TYPE_SIZE)
46#define _FP_IMPLBIT_E \
47 ((_FP_W_TYPE)1 << (_FP_FRACBITS_E-1) % _FP_W_TYPE_SIZE)
48#define _FP_OVERFLOW_E \
49 ((_FP_W_TYPE)1 << (_FP_WFRACBITS_E % _FP_W_TYPE_SIZE))
50
51#if _FP_W_TYPE_SIZE < 64
52
53union _FP_UNION_E
54{
55 long double flt;
56 struct
57 {
58#if __BYTE_ORDER == __BIG_ENDIAN
59 unsigned long pad1 : _FP_W_TYPE_SIZE;
60 unsigned long pad2 : (_FP_W_TYPE_SIZE - 1 - _FP_EXPBITS_E);
61 unsigned long sign : 1;
62 unsigned long exp : _FP_EXPBITS_E;
63 unsigned long frac1 : _FP_W_TYPE_SIZE;
64 unsigned long frac0 : _FP_W_TYPE_SIZE;
65#else
66 unsigned long frac0 : _FP_W_TYPE_SIZE;
67 unsigned long frac1 : _FP_W_TYPE_SIZE;
68 unsigned exp : _FP_EXPBITS_E;
69 unsigned sign : 1;
70#endif /* not bigendian */
71 } bits __attribute__((packed));
72};
73
74
75#define FP_DECL_E(X) _FP_DECL(4,X)
76
77#define FP_UNPACK_RAW_E(X, val) \
78 do { \
79 union _FP_UNION_E _flo; _flo.flt = (val); \
80 \
81 X##_f[2] = 0; X##_f[3] = 0; \
82 X##_f[0] = _flo.bits.frac0; \
83 X##_f[1] = _flo.bits.frac1; \
84 X##_e = _flo.bits.exp; \
85 X##_s = _flo.bits.sign; \
86 if (!X##_e && (X##_f[1] || X##_f[0]) \
87 && !(X##_f[1] & _FP_IMPLBIT_E)) \
88 { \
89 X##_e++; \
90 FP_SET_EXCEPTION(FP_EX_DENORM); \
91 } \
92 } while (0)
93
94#define FP_UNPACK_RAW_EP(X, val) \
95 do { \
96 union _FP_UNION_E *_flo = \
97 (union _FP_UNION_E *)(val); \
98 \
99 X##_f[2] = 0; X##_f[3] = 0; \
100 X##_f[0] = _flo->bits.frac0; \
101 X##_f[1] = _flo->bits.frac1; \
102 X##_e = _flo->bits.exp; \
103 X##_s = _flo->bits.sign; \
104 if (!X##_e && (X##_f[1] || X##_f[0]) \
105 && !(X##_f[1] & _FP_IMPLBIT_E)) \
106 { \
107 X##_e++; \
108 FP_SET_EXCEPTION(FP_EX_DENORM); \
109 } \
110 } while (0)
111
112#define FP_PACK_RAW_E(val, X) \
113 do { \
114 union _FP_UNION_E _flo; \
115 \
116 if (X##_e) X##_f[1] |= _FP_IMPLBIT_E; \
117 else X##_f[1] &= ~(_FP_IMPLBIT_E); \
118 _flo.bits.frac0 = X##_f[0]; \
119 _flo.bits.frac1 = X##_f[1]; \
120 _flo.bits.exp = X##_e; \
121 _flo.bits.sign = X##_s; \
122 \
123 (val) = _flo.flt; \
124 } while (0)
125
126#define FP_PACK_RAW_EP(val, X) \
127 do { \
128 if (!FP_INHIBIT_RESULTS) \
129 { \
130 union _FP_UNION_E *_flo = \
131 (union _FP_UNION_E *)(val); \
132 \
133 if (X##_e) X##_f[1] |= _FP_IMPLBIT_E; \
134 else X##_f[1] &= ~(_FP_IMPLBIT_E); \
135 _flo->bits.frac0 = X##_f[0]; \
136 _flo->bits.frac1 = X##_f[1]; \
137 _flo->bits.exp = X##_e; \
138 _flo->bits.sign = X##_s; \
139 } \
140 } while (0)
141
142#define FP_UNPACK_E(X,val) \
143 do { \
144 FP_UNPACK_RAW_E(X,val); \
145 _FP_UNPACK_CANONICAL(E,4,X); \
146 } while (0)
147
148#define FP_UNPACK_EP(X,val) \
149 do { \
150 FP_UNPACK_RAW_2_P(X,val); \
151 _FP_UNPACK_CANONICAL(E,4,X); \
152 } while (0)
153
154#define FP_PACK_E(val,X) \
155 do { \
156 _FP_PACK_CANONICAL(E,4,X); \
157 FP_PACK_RAW_E(val,X); \
158 } while (0)
159
160#define FP_PACK_EP(val,X) \
161 do { \
162 _FP_PACK_CANONICAL(E,4,X); \
163 FP_PACK_RAW_EP(val,X); \
164 } while (0)
165
166#define FP_ISSIGNAN_E(X) _FP_ISSIGNAN(E,4,X)
167#define FP_NEG_E(R,X) _FP_NEG(E,4,R,X)
168#define FP_ADD_E(R,X,Y) _FP_ADD(E,4,R,X,Y)
169#define FP_SUB_E(R,X,Y) _FP_SUB(E,4,R,X,Y)
170#define FP_MUL_E(R,X,Y) _FP_MUL(E,4,R,X,Y)
171#define FP_DIV_E(R,X,Y) _FP_DIV(E,4,R,X,Y)
172#define FP_SQRT_E(R,X) _FP_SQRT(E,4,R,X)
173
174/*
175 * Square root algorithms:
176 * We have just one right now, maybe Newton approximation
177 * should be added for those machines where division is fast.
178 * This has special _E version because standard _4 square
179 * root would not work (it has to start normally with the
180 * second word and not the first), but as we have to do it
181 * anyway, we optimize it by doing most of the calculations
182 * in two UWtype registers instead of four.
183 */
184
185#define _FP_SQRT_MEAT_E(R, S, T, X, q) \
186 do { \
187 q = (_FP_W_TYPE)1 << (_FP_W_TYPE_SIZE - 1); \
188 _FP_FRAC_SRL_4(X, (_FP_WORKBITS)); \
189 while (q) \
190 { \
191 T##_f[1] = S##_f[1] + q; \
192 if (T##_f[1] <= X##_f[1]) \
193 { \
194 S##_f[1] = T##_f[1] + q; \
195 X##_f[1] -= T##_f[1]; \
196 R##_f[1] += q; \
197 } \
198 _FP_FRAC_SLL_2(X, 1); \
199 q >>= 1; \
200 } \
201 q = (_FP_W_TYPE)1 << (_FP_W_TYPE_SIZE - 1); \
202 while (q) \
203 { \
204 T##_f[0] = S##_f[0] + q; \
205 T##_f[1] = S##_f[1]; \
206 if (T##_f[1] < X##_f[1] || \
207 (T##_f[1] == X##_f[1] && \
208 T##_f[0] <= X##_f[0])) \
209 { \
210 S##_f[0] = T##_f[0] + q; \
211 S##_f[1] += (T##_f[0] > S##_f[0]); \
212 _FP_FRAC_DEC_2(X, T); \
213 R##_f[0] += q; \
214 } \
215 _FP_FRAC_SLL_2(X, 1); \
216 q >>= 1; \
217 } \
218 _FP_FRAC_SLL_4(R, (_FP_WORKBITS)); \
219 if (X##_f[0] | X##_f[1]) \
220 { \
221 if (S##_f[1] < X##_f[1] || \
222 (S##_f[1] == X##_f[1] && \
223 S##_f[0] < X##_f[0])) \
224 R##_f[0] |= _FP_WORK_ROUND; \
225 R##_f[0] |= _FP_WORK_STICKY; \
226 } \
227 } while (0)
228
229#define FP_CMP_E(r,X,Y,un) _FP_CMP(E,4,r,X,Y,un)
230#define FP_CMP_EQ_E(r,X,Y) _FP_CMP_EQ(E,4,r,X,Y)
231
232#define FP_TO_INT_E(r,X,rsz,rsg) _FP_TO_INT(E,4,r,X,rsz,rsg)
233#define FP_TO_INT_ROUND_E(r,X,rsz,rsg) _FP_TO_INT_ROUND(E,4,r,X,rsz,rsg)
234#define FP_FROM_INT_E(X,r,rs,rt) _FP_FROM_INT(E,4,X,r,rs,rt)
235
236#define _FP_FRAC_HIGH_E(X) (X##_f[2])
237#define _FP_FRAC_HIGH_RAW_E(X) (X##_f[1])
238
239#else /* not _FP_W_TYPE_SIZE < 64 */
240union _FP_UNION_E
241{
242 long double flt /* __attribute__((mode(TF))) */ ;
243 struct {
244#if __BYTE_ORDER == __BIG_ENDIAN
245 unsigned long pad : (_FP_W_TYPE_SIZE - 1 - _FP_EXPBITS_E);
246 unsigned sign : 1;
247 unsigned exp : _FP_EXPBITS_E;
248 unsigned long frac : _FP_W_TYPE_SIZE;
249#else
250 unsigned long frac : _FP_W_TYPE_SIZE;
251 unsigned exp : _FP_EXPBITS_E;
252 unsigned sign : 1;
253#endif
254 } bits;
255};
256
257#define FP_DECL_E(X) _FP_DECL(2,X)
258
259#define FP_UNPACK_RAW_E(X, val) \
260 do { \
261 union _FP_UNION_E _flo; _flo.flt = (val); \
262 \
263 X##_f0 = _flo.bits.frac; \
264 X##_f1 = 0; \
265 X##_e = _flo.bits.exp; \
266 X##_s = _flo.bits.sign; \
267 if (!X##_e && X##_f0 && !(X##_f0 & _FP_IMPLBIT_E)) \
268 { \
269 X##_e++; \
270 FP_SET_EXCEPTION(FP_EX_DENORM); \
271 } \
272 } while (0)
273
274#define FP_UNPACK_RAW_EP(X, val) \
275 do { \
276 union _FP_UNION_E *_flo = \
277 (union _FP_UNION_E *)(val); \
278 \
279 X##_f0 = _flo->bits.frac; \
280 X##_f1 = 0; \
281 X##_e = _flo->bits.exp; \
282 X##_s = _flo->bits.sign; \
283 if (!X##_e && X##_f0 && !(X##_f0 & _FP_IMPLBIT_E)) \
284 { \
285 X##_e++; \
286 FP_SET_EXCEPTION(FP_EX_DENORM); \
287 } \
288 } while (0)
289
290#define FP_PACK_RAW_E(val, X) \
291 do { \
292 union _FP_UNION_E _flo; \
293 \
294 if (X##_e) X##_f0 |= _FP_IMPLBIT_E; \
295 else X##_f0 &= ~(_FP_IMPLBIT_E); \
296 _flo.bits.frac = X##_f0; \
297 _flo.bits.exp = X##_e; \
298 _flo.bits.sign = X##_s; \
299 \
300 (val) = _flo.flt; \
301 } while (0)
302
303#define FP_PACK_RAW_EP(fs, val, X) \
304 do { \
305 if (!FP_INHIBIT_RESULTS) \
306 { \
307 union _FP_UNION_E *_flo = \
308 (union _FP_UNION_E *)(val); \
309 \
310 if (X##_e) X##_f0 |= _FP_IMPLBIT_E; \
311 else X##_f0 &= ~(_FP_IMPLBIT_E); \
312 _flo->bits.frac = X##_f0; \
313 _flo->bits.exp = X##_e; \
314 _flo->bits.sign = X##_s; \
315 } \
316 } while (0)
317
318
319#define FP_UNPACK_E(X,val) \
320 do { \
321 FP_UNPACK_RAW_E(X,val); \
322 _FP_UNPACK_CANONICAL(E,2,X); \
323 } while (0)
324
325#define FP_UNPACK_EP(X,val) \
326 do { \
327 FP_UNPACK_RAW_EP(X,val); \
328 _FP_UNPACK_CANONICAL(E,2,X); \
329 } while (0)
330
331#define FP_PACK_E(val,X) \
332 do { \
333 _FP_PACK_CANONICAL(E,2,X); \
334 FP_PACK_RAW_E(val,X); \
335 } while (0)
336
337#define FP_PACK_EP(val,X) \
338 do { \
339 _FP_PACK_CANONICAL(E,2,X); \
340 FP_PACK_RAW_EP(val,X); \
341 } while (0)
342
343#define FP_ISSIGNAN_E(X) _FP_ISSIGNAN(E,2,X)
344#define FP_NEG_E(R,X) _FP_NEG(E,2,R,X)
345#define FP_ADD_E(R,X,Y) _FP_ADD(E,2,R,X,Y)
346#define FP_SUB_E(R,X,Y) _FP_SUB(E,2,R,X,Y)
347#define FP_MUL_E(R,X,Y) _FP_MUL(E,2,R,X,Y)
348#define FP_DIV_E(R,X,Y) _FP_DIV(E,2,R,X,Y)
349#define FP_SQRT_E(R,X) _FP_SQRT(E,2,R,X)
350
351/*
352 * Square root algorithms:
353 * We have just one right now, maybe Newton approximation
354 * should be added for those machines where division is fast.
355 * We optimize it by doing most of the calculations
356 * in one UWtype registers instead of two, although we don't
357 * have to.
358 */
359#define _FP_SQRT_MEAT_E(R, S, T, X, q) \
360 do { \
361 q = (_FP_W_TYPE)1 << (_FP_W_TYPE_SIZE - 1); \
362 _FP_FRAC_SRL_2(X, (_FP_WORKBITS)); \
363 while (q) \
364 { \
365 T##_f0 = S##_f0 + q; \
366 if (T##_f0 <= X##_f0) \
367 { \
368 S##_f0 = T##_f0 + q; \
369 X##_f0 -= T##_f0; \
370 R##_f0 += q; \
371 } \
372 _FP_FRAC_SLL_1(X, 1); \
373 q >>= 1; \
374 } \
375 _FP_FRAC_SLL_2(R, (_FP_WORKBITS)); \
376 if (X##_f0) \
377 { \
378 if (S##_f0 < X##_f0) \
379 R##_f0 |= _FP_WORK_ROUND; \
380 R##_f0 |= _FP_WORK_STICKY; \
381 } \
382 } while (0)
383
384#define FP_CMP_E(r,X,Y,un) _FP_CMP(E,2,r,X,Y,un)
385#define FP_CMP_EQ_E(r,X,Y) _FP_CMP_EQ(E,2,r,X,Y)
386
387#define FP_TO_INT_E(r,X,rsz,rsg) _FP_TO_INT(E,2,r,X,rsz,rsg)
388#define FP_TO_INT_ROUND_E(r,X,rsz,rsg) _FP_TO_INT_ROUND(E,2,r,X,rsz,rsg)
389#define FP_FROM_INT_E(X,r,rs,rt) _FP_FROM_INT(E,2,X,r,rs,rt)
390
391#define _FP_FRAC_HIGH_E(X) (X##_f1)
392#define _FP_FRAC_HIGH_RAW_E(X) (X##_f0)
393
394#endif /* not _FP_W_TYPE_SIZE < 64 */
395
396#endif /* __MATH_EMU_EXTENDED_H__ */
diff --git a/include/math-emu/op-1.h b/include/math-emu/op-1.h
new file mode 100644
index 000000000000..3be3bb422cbe
--- /dev/null
+++ b/include/math-emu/op-1.h
@@ -0,0 +1,303 @@
1/* Software floating-point emulation.
2 Basic one-word fraction declaration and manipulation.
3 Copyright (C) 1997,1998,1999 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 Library General Public License as
12 published by the Free Software Foundation; either version 2 of the
13 License, or (at your option) any later version.
14
15 The GNU C Library is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 Library General Public License for more details.
19
20 You should have received a copy of the GNU Library General Public
21 License along with the GNU C Library; see the file COPYING.LIB. If
22 not, write to the Free Software Foundation, Inc.,
23 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
24
25#ifndef __MATH_EMU_OP_1_H__
26#define __MATH_EMU_OP_1_H__
27
28#define _FP_FRAC_DECL_1(X) _FP_W_TYPE X##_f=0
29#define _FP_FRAC_COPY_1(D,S) (D##_f = S##_f)
30#define _FP_FRAC_SET_1(X,I) (X##_f = I)
31#define _FP_FRAC_HIGH_1(X) (X##_f)
32#define _FP_FRAC_LOW_1(X) (X##_f)
33#define _FP_FRAC_WORD_1(X,w) (X##_f)
34
35#define _FP_FRAC_ADDI_1(X,I) (X##_f += I)
36#define _FP_FRAC_SLL_1(X,N) \
37 do { \
38 if (__builtin_constant_p(N) && (N) == 1) \
39 X##_f += X##_f; \
40 else \
41 X##_f <<= (N); \
42 } while (0)
43#define _FP_FRAC_SRL_1(X,N) (X##_f >>= N)
44
45/* Right shift with sticky-lsb. */
46#define _FP_FRAC_SRS_1(X,N,sz) __FP_FRAC_SRS_1(X##_f, N, sz)
47
48#define __FP_FRAC_SRS_1(X,N,sz) \
49 (X = (X >> (N) | (__builtin_constant_p(N) && (N) == 1 \
50 ? X & 1 : (X << (_FP_W_TYPE_SIZE - (N))) != 0)))
51
52#define _FP_FRAC_ADD_1(R,X,Y) (R##_f = X##_f + Y##_f)
53#define _FP_FRAC_SUB_1(R,X,Y) (R##_f = X##_f - Y##_f)
54#define _FP_FRAC_DEC_1(X,Y) (X##_f -= Y##_f)
55#define _FP_FRAC_CLZ_1(z, X) __FP_CLZ(z, X##_f)
56
57/* Predicates */
58#define _FP_FRAC_NEGP_1(X) ((_FP_WS_TYPE)X##_f < 0)
59#define _FP_FRAC_ZEROP_1(X) (X##_f == 0)
60#define _FP_FRAC_OVERP_1(fs,X) (X##_f & _FP_OVERFLOW_##fs)
61#define _FP_FRAC_CLEAR_OVERP_1(fs,X) (X##_f &= ~_FP_OVERFLOW_##fs)
62#define _FP_FRAC_EQ_1(X, Y) (X##_f == Y##_f)
63#define _FP_FRAC_GE_1(X, Y) (X##_f >= Y##_f)
64#define _FP_FRAC_GT_1(X, Y) (X##_f > Y##_f)
65
66#define _FP_ZEROFRAC_1 0
67#define _FP_MINFRAC_1 1
68#define _FP_MAXFRAC_1 (~(_FP_WS_TYPE)0)
69
70/*
71 * Unpack the raw bits of a native fp value. Do not classify or
72 * normalize the data.
73 */
74
75#define _FP_UNPACK_RAW_1(fs, X, val) \
76 do { \
77 union _FP_UNION_##fs _flo; _flo.flt = (val); \
78 \
79 X##_f = _flo.bits.frac; \
80 X##_e = _flo.bits.exp; \
81 X##_s = _flo.bits.sign; \
82 } while (0)
83
84#define _FP_UNPACK_RAW_1_P(fs, X, val) \
85 do { \
86 union _FP_UNION_##fs *_flo = \
87 (union _FP_UNION_##fs *)(val); \
88 \
89 X##_f = _flo->bits.frac; \
90 X##_e = _flo->bits.exp; \
91 X##_s = _flo->bits.sign; \
92 } while (0)
93
94/*
95 * Repack the raw bits of a native fp value.
96 */
97
98#define _FP_PACK_RAW_1(fs, val, X) \
99 do { \
100 union _FP_UNION_##fs _flo; \
101 \
102 _flo.bits.frac = X##_f; \
103 _flo.bits.exp = X##_e; \
104 _flo.bits.sign = X##_s; \
105 \
106 (val) = _flo.flt; \
107 } while (0)
108
109#define _FP_PACK_RAW_1_P(fs, val, X) \
110 do { \
111 union _FP_UNION_##fs *_flo = \
112 (union _FP_UNION_##fs *)(val); \
113 \
114 _flo->bits.frac = X##_f; \
115 _flo->bits.exp = X##_e; \
116 _flo->bits.sign = X##_s; \
117 } while (0)
118
119
120/*
121 * Multiplication algorithms:
122 */
123
124/* Basic. Assuming the host word size is >= 2*FRACBITS, we can do the
125 multiplication immediately. */
126
127#define _FP_MUL_MEAT_1_imm(wfracbits, R, X, Y) \
128 do { \
129 R##_f = X##_f * Y##_f; \
130 /* Normalize since we know where the msb of the multiplicands \
131 were (bit B), we know that the msb of the of the product is \
132 at either 2B or 2B-1. */ \
133 _FP_FRAC_SRS_1(R, wfracbits-1, 2*wfracbits); \
134 } while (0)
135
136/* Given a 1W * 1W => 2W primitive, do the extended multiplication. */
137
138#define _FP_MUL_MEAT_1_wide(wfracbits, R, X, Y, doit) \
139 do { \
140 _FP_W_TYPE _Z_f0, _Z_f1; \
141 doit(_Z_f1, _Z_f0, X##_f, Y##_f); \
142 /* Normalize since we know where the msb of the multiplicands \
143 were (bit B), we know that the msb of the of the product is \
144 at either 2B or 2B-1. */ \
145 _FP_FRAC_SRS_2(_Z, wfracbits-1, 2*wfracbits); \
146 R##_f = _Z_f0; \
147 } while (0)
148
149/* Finally, a simple widening multiply algorithm. What fun! */
150
151#define _FP_MUL_MEAT_1_hard(wfracbits, R, X, Y) \
152 do { \
153 _FP_W_TYPE _xh, _xl, _yh, _yl, _z_f0, _z_f1, _a_f0, _a_f1; \
154 \
155 /* split the words in half */ \
156 _xh = X##_f >> (_FP_W_TYPE_SIZE/2); \
157 _xl = X##_f & (((_FP_W_TYPE)1 << (_FP_W_TYPE_SIZE/2)) - 1); \
158 _yh = Y##_f >> (_FP_W_TYPE_SIZE/2); \
159 _yl = Y##_f & (((_FP_W_TYPE)1 << (_FP_W_TYPE_SIZE/2)) - 1); \
160 \
161 /* multiply the pieces */ \
162 _z_f0 = _xl * _yl; \
163 _a_f0 = _xh * _yl; \
164 _a_f1 = _xl * _yh; \
165 _z_f1 = _xh * _yh; \
166 \
167 /* reassemble into two full words */ \
168 if ((_a_f0 += _a_f1) < _a_f1) \
169 _z_f1 += (_FP_W_TYPE)1 << (_FP_W_TYPE_SIZE/2); \
170 _a_f1 = _a_f0 >> (_FP_W_TYPE_SIZE/2); \
171 _a_f0 = _a_f0 << (_FP_W_TYPE_SIZE/2); \
172 _FP_FRAC_ADD_2(_z, _z, _a); \
173 \
174 /* normalize */ \
175 _FP_FRAC_SRS_2(_z, wfracbits - 1, 2*wfracbits); \
176 R##_f = _z_f0; \
177 } while (0)
178
179
180/*
181 * Division algorithms:
182 */
183
184/* Basic. Assuming the host word size is >= 2*FRACBITS, we can do the
185 division immediately. Give this macro either _FP_DIV_HELP_imm for
186 C primitives or _FP_DIV_HELP_ldiv for the ISO function. Which you
187 choose will depend on what the compiler does with divrem4. */
188
189#define _FP_DIV_MEAT_1_imm(fs, R, X, Y, doit) \
190 do { \
191 _FP_W_TYPE _q, _r; \
192 X##_f <<= (X##_f < Y##_f \
193 ? R##_e--, _FP_WFRACBITS_##fs \
194 : _FP_WFRACBITS_##fs - 1); \
195 doit(_q, _r, X##_f, Y##_f); \
196 R##_f = _q | (_r != 0); \
197 } while (0)
198
199/* GCC's longlong.h defines a 2W / 1W => (1W,1W) primitive udiv_qrnnd
200 that may be useful in this situation. This first is for a primitive
201 that requires normalization, the second for one that does not. Look
202 for UDIV_NEEDS_NORMALIZATION to tell which your machine needs. */
203
204#define _FP_DIV_MEAT_1_udiv_norm(fs, R, X, Y) \
205 do { \
206 _FP_W_TYPE _nh, _nl, _q, _r, _y; \
207 \
208 /* Normalize Y -- i.e. make the most significant bit set. */ \
209 _y = Y##_f << _FP_WFRACXBITS_##fs; \
210 \
211 /* Shift X op correspondingly high, that is, up one full word. */ \
212 if (X##_f < Y##_f) \
213 { \
214 R##_e--; \
215 _nl = 0; \
216 _nh = X##_f; \
217 } \
218 else \
219 { \
220 _nl = X##_f << (_FP_W_TYPE_SIZE - 1); \
221 _nh = X##_f >> 1; \
222 } \
223 \
224 udiv_qrnnd(_q, _r, _nh, _nl, _y); \
225 R##_f = _q | (_r != 0); \
226 } while (0)
227
228#define _FP_DIV_MEAT_1_udiv(fs, R, X, Y) \
229 do { \
230 _FP_W_TYPE _nh, _nl, _q, _r; \
231 if (X##_f < Y##_f) \
232 { \
233 R##_e--; \
234 _nl = X##_f << _FP_WFRACBITS_##fs; \
235 _nh = X##_f >> _FP_WFRACXBITS_##fs; \
236 } \
237 else \
238 { \
239 _nl = X##_f << (_FP_WFRACBITS_##fs - 1); \
240 _nh = X##_f >> (_FP_WFRACXBITS_##fs + 1); \
241 } \
242 udiv_qrnnd(_q, _r, _nh, _nl, Y##_f); \
243 R##_f = _q | (_r != 0); \
244 } while (0)
245
246
247/*
248 * Square root algorithms:
249 * We have just one right now, maybe Newton approximation
250 * should be added for those machines where division is fast.
251 */
252
253#define _FP_SQRT_MEAT_1(R, S, T, X, q) \
254 do { \
255 while (q != _FP_WORK_ROUND) \
256 { \
257 T##_f = S##_f + q; \
258 if (T##_f <= X##_f) \
259 { \
260 S##_f = T##_f + q; \
261 X##_f -= T##_f; \
262 R##_f += q; \
263 } \
264 _FP_FRAC_SLL_1(X, 1); \
265 q >>= 1; \
266 } \
267 if (X##_f) \
268 { \
269 if (S##_f < X##_f) \
270 R##_f |= _FP_WORK_ROUND; \
271 R##_f |= _FP_WORK_STICKY; \
272 } \
273 } while (0)
274
275/*
276 * Assembly/disassembly for converting to/from integral types.
277 * No shifting or overflow handled here.
278 */
279
280#define _FP_FRAC_ASSEMBLE_1(r, X, rsize) (r = X##_f)
281#define _FP_FRAC_DISASSEMBLE_1(X, r, rsize) (X##_f = r)
282
283
284/*
285 * Convert FP values between word sizes
286 */
287
288#define _FP_FRAC_CONV_1_1(dfs, sfs, D, S) \
289 do { \
290 D##_f = S##_f; \
291 if (_FP_WFRACBITS_##sfs > _FP_WFRACBITS_##dfs) \
292 { \
293 if (S##_c != FP_CLS_NAN) \
294 _FP_FRAC_SRS_1(D, (_FP_WFRACBITS_##sfs-_FP_WFRACBITS_##dfs), \
295 _FP_WFRACBITS_##sfs); \
296 else \
297 _FP_FRAC_SRL_1(D, (_FP_WFRACBITS_##sfs-_FP_WFRACBITS_##dfs)); \
298 } \
299 else \
300 D##_f <<= _FP_WFRACBITS_##dfs - _FP_WFRACBITS_##sfs; \
301 } while (0)
302
303#endif /* __MATH_EMU_OP_1_H__ */
diff --git a/include/math-emu/op-2.h b/include/math-emu/op-2.h
new file mode 100644
index 000000000000..e193fb08fd55
--- /dev/null
+++ b/include/math-emu/op-2.h
@@ -0,0 +1,613 @@
1/* Software floating-point emulation.
2 Basic two-word fraction declaration and manipulation.
3 Copyright (C) 1997,1998,1999 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 Library General Public License as
12 published by the Free Software Foundation; either version 2 of the
13 License, or (at your option) any later version.
14
15 The GNU C Library is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 Library General Public License for more details.
19
20 You should have received a copy of the GNU Library General Public
21 License along with the GNU C Library; see the file COPYING.LIB. If
22 not, write to the Free Software Foundation, Inc.,
23 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
24
25#ifndef __MATH_EMU_OP_2_H__
26#define __MATH_EMU_OP_2_H__
27
28#define _FP_FRAC_DECL_2(X) _FP_W_TYPE X##_f0, X##_f1
29#define _FP_FRAC_COPY_2(D,S) (D##_f0 = S##_f0, D##_f1 = S##_f1)
30#define _FP_FRAC_SET_2(X,I) __FP_FRAC_SET_2(X, I)
31#define _FP_FRAC_HIGH_2(X) (X##_f1)
32#define _FP_FRAC_LOW_2(X) (X##_f0)
33#define _FP_FRAC_WORD_2(X,w) (X##_f##w)
34
35#define _FP_FRAC_SLL_2(X,N) \
36 do { \
37 if ((N) < _FP_W_TYPE_SIZE) \
38 { \
39 if (__builtin_constant_p(N) && (N) == 1) \
40 { \
41 X##_f1 = X##_f1 + X##_f1 + (((_FP_WS_TYPE)(X##_f0)) < 0); \
42 X##_f0 += X##_f0; \
43 } \
44 else \
45 { \
46 X##_f1 = X##_f1 << (N) | X##_f0 >> (_FP_W_TYPE_SIZE - (N)); \
47 X##_f0 <<= (N); \
48 } \
49 } \
50 else \
51 { \
52 X##_f1 = X##_f0 << ((N) - _FP_W_TYPE_SIZE); \
53 X##_f0 = 0; \
54 } \
55 } while (0)
56
57#define _FP_FRAC_SRL_2(X,N) \
58 do { \
59 if ((N) < _FP_W_TYPE_SIZE) \
60 { \
61 X##_f0 = X##_f0 >> (N) | X##_f1 << (_FP_W_TYPE_SIZE - (N)); \
62 X##_f1 >>= (N); \
63 } \
64 else \
65 { \
66 X##_f0 = X##_f1 >> ((N) - _FP_W_TYPE_SIZE); \
67 X##_f1 = 0; \
68 } \
69 } while (0)
70
71/* Right shift with sticky-lsb. */
72#define _FP_FRAC_SRS_2(X,N,sz) \
73 do { \
74 if ((N) < _FP_W_TYPE_SIZE) \
75 { \
76 X##_f0 = (X##_f1 << (_FP_W_TYPE_SIZE - (N)) | X##_f0 >> (N) | \
77 (__builtin_constant_p(N) && (N) == 1 \
78 ? X##_f0 & 1 \
79 : (X##_f0 << (_FP_W_TYPE_SIZE - (N))) != 0)); \
80 X##_f1 >>= (N); \
81 } \
82 else \
83 { \
84 X##_f0 = (X##_f1 >> ((N) - _FP_W_TYPE_SIZE) | \
85 (((X##_f1 << (2*_FP_W_TYPE_SIZE - (N))) | X##_f0) != 0)); \
86 X##_f1 = 0; \
87 } \
88 } while (0)
89
90#define _FP_FRAC_ADDI_2(X,I) \
91 __FP_FRAC_ADDI_2(X##_f1, X##_f0, I)
92
93#define _FP_FRAC_ADD_2(R,X,Y) \
94 __FP_FRAC_ADD_2(R##_f1, R##_f0, X##_f1, X##_f0, Y##_f1, Y##_f0)
95
96#define _FP_FRAC_SUB_2(R,X,Y) \
97 __FP_FRAC_SUB_2(R##_f1, R##_f0, X##_f1, X##_f0, Y##_f1, Y##_f0)
98
99#define _FP_FRAC_DEC_2(X,Y) \
100 __FP_FRAC_DEC_2(X##_f1, X##_f0, Y##_f1, Y##_f0)
101
102#define _FP_FRAC_CLZ_2(R,X) \
103 do { \
104 if (X##_f1) \
105 __FP_CLZ(R,X##_f1); \
106 else \
107 { \
108 __FP_CLZ(R,X##_f0); \
109 R += _FP_W_TYPE_SIZE; \
110 } \
111 } while(0)
112
113/* Predicates */
114#define _FP_FRAC_NEGP_2(X) ((_FP_WS_TYPE)X##_f1 < 0)
115#define _FP_FRAC_ZEROP_2(X) ((X##_f1 | X##_f0) == 0)
116#define _FP_FRAC_OVERP_2(fs,X) (_FP_FRAC_HIGH_##fs(X) & _FP_OVERFLOW_##fs)
117#define _FP_FRAC_CLEAR_OVERP_2(fs,X) (_FP_FRAC_HIGH_##fs(X) &= ~_FP_OVERFLOW_##fs)
118#define _FP_FRAC_EQ_2(X, Y) (X##_f1 == Y##_f1 && X##_f0 == Y##_f0)
119#define _FP_FRAC_GT_2(X, Y) \
120 (X##_f1 > Y##_f1 || (X##_f1 == Y##_f1 && X##_f0 > Y##_f0))
121#define _FP_FRAC_GE_2(X, Y) \
122 (X##_f1 > Y##_f1 || (X##_f1 == Y##_f1 && X##_f0 >= Y##_f0))
123
124#define _FP_ZEROFRAC_2 0, 0
125#define _FP_MINFRAC_2 0, 1
126#define _FP_MAXFRAC_2 (~(_FP_WS_TYPE)0), (~(_FP_WS_TYPE)0)
127
128/*
129 * Internals
130 */
131
132#define __FP_FRAC_SET_2(X,I1,I0) (X##_f0 = I0, X##_f1 = I1)
133
134#define __FP_CLZ_2(R, xh, xl) \
135 do { \
136 if (xh) \
137 __FP_CLZ(R,xh); \
138 else \
139 { \
140 __FP_CLZ(R,xl); \
141 R += _FP_W_TYPE_SIZE; \
142 } \
143 } while(0)
144
145#if 0
146
147#ifndef __FP_FRAC_ADDI_2
148#define __FP_FRAC_ADDI_2(xh, xl, i) \
149 (xh += ((xl += i) < i))
150#endif
151#ifndef __FP_FRAC_ADD_2
152#define __FP_FRAC_ADD_2(rh, rl, xh, xl, yh, yl) \
153 (rh = xh + yh + ((rl = xl + yl) < xl))
154#endif
155#ifndef __FP_FRAC_SUB_2
156#define __FP_FRAC_SUB_2(rh, rl, xh, xl, yh, yl) \
157 (rh = xh - yh - ((rl = xl - yl) > xl))
158#endif
159#ifndef __FP_FRAC_DEC_2
160#define __FP_FRAC_DEC_2(xh, xl, yh, yl) \
161 do { \
162 UWtype _t = xl; \
163 xh -= yh + ((xl -= yl) > _t); \
164 } while (0)
165#endif
166
167#else
168
169#undef __FP_FRAC_ADDI_2
170#define __FP_FRAC_ADDI_2(xh, xl, i) add_ssaaaa(xh, xl, xh, xl, 0, i)
171#undef __FP_FRAC_ADD_2
172#define __FP_FRAC_ADD_2 add_ssaaaa
173#undef __FP_FRAC_SUB_2
174#define __FP_FRAC_SUB_2 sub_ddmmss
175#undef __FP_FRAC_DEC_2
176#define __FP_FRAC_DEC_2(xh, xl, yh, yl) sub_ddmmss(xh, xl, xh, xl, yh, yl)
177
178#endif
179
180/*
181 * Unpack the raw bits of a native fp value. Do not classify or
182 * normalize the data.
183 */
184
185#define _FP_UNPACK_RAW_2(fs, X, val) \
186 do { \
187 union _FP_UNION_##fs _flo; _flo.flt = (val); \
188 \
189 X##_f0 = _flo.bits.frac0; \
190 X##_f1 = _flo.bits.frac1; \
191 X##_e = _flo.bits.exp; \
192 X##_s = _flo.bits.sign; \
193 } while (0)
194
195#define _FP_UNPACK_RAW_2_P(fs, X, val) \
196 do { \
197 union _FP_UNION_##fs *_flo = \
198 (union _FP_UNION_##fs *)(val); \
199 \
200 X##_f0 = _flo->bits.frac0; \
201 X##_f1 = _flo->bits.frac1; \
202 X##_e = _flo->bits.exp; \
203 X##_s = _flo->bits.sign; \
204 } while (0)
205
206
207/*
208 * Repack the raw bits of a native fp value.
209 */
210
211#define _FP_PACK_RAW_2(fs, val, X) \
212 do { \
213 union _FP_UNION_##fs _flo; \
214 \
215 _flo.bits.frac0 = X##_f0; \
216 _flo.bits.frac1 = X##_f1; \
217 _flo.bits.exp = X##_e; \
218 _flo.bits.sign = X##_s; \
219 \
220 (val) = _flo.flt; \
221 } while (0)
222
223#define _FP_PACK_RAW_2_P(fs, val, X) \
224 do { \
225 union _FP_UNION_##fs *_flo = \
226 (union _FP_UNION_##fs *)(val); \
227 \
228 _flo->bits.frac0 = X##_f0; \
229 _flo->bits.frac1 = X##_f1; \
230 _flo->bits.exp = X##_e; \
231 _flo->bits.sign = X##_s; \
232 } while (0)
233
234
235/*
236 * Multiplication algorithms:
237 */
238
239/* Given a 1W * 1W => 2W primitive, do the extended multiplication. */
240
241#define _FP_MUL_MEAT_2_wide(wfracbits, R, X, Y, doit) \
242 do { \
243 _FP_FRAC_DECL_4(_z); _FP_FRAC_DECL_2(_b); _FP_FRAC_DECL_2(_c); \
244 \
245 doit(_FP_FRAC_WORD_4(_z,1), _FP_FRAC_WORD_4(_z,0), X##_f0, Y##_f0); \
246 doit(_b_f1, _b_f0, X##_f0, Y##_f1); \
247 doit(_c_f1, _c_f0, X##_f1, Y##_f0); \
248 doit(_FP_FRAC_WORD_4(_z,3), _FP_FRAC_WORD_4(_z,2), X##_f1, Y##_f1); \
249 \
250 __FP_FRAC_ADD_3(_FP_FRAC_WORD_4(_z,3),_FP_FRAC_WORD_4(_z,2), \
251 _FP_FRAC_WORD_4(_z,1), 0, _b_f1, _b_f0, \
252 _FP_FRAC_WORD_4(_z,3),_FP_FRAC_WORD_4(_z,2), \
253 _FP_FRAC_WORD_4(_z,1)); \
254 __FP_FRAC_ADD_3(_FP_FRAC_WORD_4(_z,3),_FP_FRAC_WORD_4(_z,2), \
255 _FP_FRAC_WORD_4(_z,1), 0, _c_f1, _c_f0, \
256 _FP_FRAC_WORD_4(_z,3),_FP_FRAC_WORD_4(_z,2), \
257 _FP_FRAC_WORD_4(_z,1)); \
258 \
259 /* Normalize since we know where the msb of the multiplicands \
260 were (bit B), we know that the msb of the of the product is \
261 at either 2B or 2B-1. */ \
262 _FP_FRAC_SRS_4(_z, wfracbits-1, 2*wfracbits); \
263 R##_f0 = _FP_FRAC_WORD_4(_z,0); \
264 R##_f1 = _FP_FRAC_WORD_4(_z,1); \
265 } while (0)
266
267/* Given a 1W * 1W => 2W primitive, do the extended multiplication.
268 Do only 3 multiplications instead of four. This one is for machines
269 where multiplication is much more expensive than subtraction. */
270
271#define _FP_MUL_MEAT_2_wide_3mul(wfracbits, R, X, Y, doit) \
272 do { \
273 _FP_FRAC_DECL_4(_z); _FP_FRAC_DECL_2(_b); _FP_FRAC_DECL_2(_c); \
274 _FP_W_TYPE _d; \
275 int _c1, _c2; \
276 \
277 _b_f0 = X##_f0 + X##_f1; \
278 _c1 = _b_f0 < X##_f0; \
279 _b_f1 = Y##_f0 + Y##_f1; \
280 _c2 = _b_f1 < Y##_f0; \
281 doit(_d, _FP_FRAC_WORD_4(_z,0), X##_f0, Y##_f0); \
282 doit(_FP_FRAC_WORD_4(_z,2), _FP_FRAC_WORD_4(_z,1), _b_f0, _b_f1); \
283 doit(_c_f1, _c_f0, X##_f1, Y##_f1); \
284 \
285 _b_f0 &= -_c2; \
286 _b_f1 &= -_c1; \
287 __FP_FRAC_ADD_3(_FP_FRAC_WORD_4(_z,3),_FP_FRAC_WORD_4(_z,2), \
288 _FP_FRAC_WORD_4(_z,1), (_c1 & _c2), 0, _d, \
289 0, _FP_FRAC_WORD_4(_z,2), _FP_FRAC_WORD_4(_z,1)); \
290 __FP_FRAC_ADDI_2(_FP_FRAC_WORD_4(_z,3),_FP_FRAC_WORD_4(_z,2), \
291 _b_f0); \
292 __FP_FRAC_ADDI_2(_FP_FRAC_WORD_4(_z,3),_FP_FRAC_WORD_4(_z,2), \
293 _b_f1); \
294 __FP_FRAC_DEC_3(_FP_FRAC_WORD_4(_z,3),_FP_FRAC_WORD_4(_z,2), \
295 _FP_FRAC_WORD_4(_z,1), \
296 0, _d, _FP_FRAC_WORD_4(_z,0)); \
297 __FP_FRAC_DEC_3(_FP_FRAC_WORD_4(_z,3),_FP_FRAC_WORD_4(_z,2), \
298 _FP_FRAC_WORD_4(_z,1), 0, _c_f1, _c_f0); \
299 __FP_FRAC_ADD_2(_FP_FRAC_WORD_4(_z,3), _FP_FRAC_WORD_4(_z,2), \
300 _c_f1, _c_f0, \
301 _FP_FRAC_WORD_4(_z,3), _FP_FRAC_WORD_4(_z,2)); \
302 \
303 /* Normalize since we know where the msb of the multiplicands \
304 were (bit B), we know that the msb of the of the product is \
305 at either 2B or 2B-1. */ \
306 _FP_FRAC_SRS_4(_z, wfracbits-1, 2*wfracbits); \
307 R##_f0 = _FP_FRAC_WORD_4(_z,0); \
308 R##_f1 = _FP_FRAC_WORD_4(_z,1); \
309 } while (0)
310
311#define _FP_MUL_MEAT_2_gmp(wfracbits, R, X, Y) \
312 do { \
313 _FP_FRAC_DECL_4(_z); \
314 _FP_W_TYPE _x[2], _y[2]; \
315 _x[0] = X##_f0; _x[1] = X##_f1; \
316 _y[0] = Y##_f0; _y[1] = Y##_f1; \
317 \
318 mpn_mul_n(_z_f, _x, _y, 2); \
319 \
320 /* Normalize since we know where the msb of the multiplicands \
321 were (bit B), we know that the msb of the of the product is \
322 at either 2B or 2B-1. */ \
323 _FP_FRAC_SRS_4(_z, wfracbits-1, 2*wfracbits); \
324 R##_f0 = _z_f[0]; \
325 R##_f1 = _z_f[1]; \
326 } while (0)
327
328/* Do at most 120x120=240 bits multiplication using double floating
329 point multiplication. This is useful if floating point
330 multiplication has much bigger throughput than integer multiply.
331 It is supposed to work for _FP_W_TYPE_SIZE 64 and wfracbits
332 between 106 and 120 only.
333 Caller guarantees that X and Y has (1LLL << (wfracbits - 1)) set.
334 SETFETZ is a macro which will disable all FPU exceptions and set rounding
335 towards zero, RESETFE should optionally reset it back. */
336
337#define _FP_MUL_MEAT_2_120_240_double(wfracbits, R, X, Y, setfetz, resetfe) \
338 do { \
339 static const double _const[] = { \
340 /* 2^-24 */ 5.9604644775390625e-08, \
341 /* 2^-48 */ 3.5527136788005009e-15, \
342 /* 2^-72 */ 2.1175823681357508e-22, \
343 /* 2^-96 */ 1.2621774483536189e-29, \
344 /* 2^28 */ 2.68435456e+08, \
345 /* 2^4 */ 1.600000e+01, \
346 /* 2^-20 */ 9.5367431640625e-07, \
347 /* 2^-44 */ 5.6843418860808015e-14, \
348 /* 2^-68 */ 3.3881317890172014e-21, \
349 /* 2^-92 */ 2.0194839173657902e-28, \
350 /* 2^-116 */ 1.2037062152420224e-35}; \
351 double _a240, _b240, _c240, _d240, _e240, _f240, \
352 _g240, _h240, _i240, _j240, _k240; \
353 union { double d; UDItype i; } _l240, _m240, _n240, _o240, \
354 _p240, _q240, _r240, _s240; \
355 UDItype _t240, _u240, _v240, _w240, _x240, _y240 = 0; \
356 \
357 if (wfracbits < 106 || wfracbits > 120) \
358 abort(); \
359 \
360 setfetz; \
361 \
362 _e240 = (double)(long)(X##_f0 & 0xffffff); \
363 _j240 = (double)(long)(Y##_f0 & 0xffffff); \
364 _d240 = (double)(long)((X##_f0 >> 24) & 0xffffff); \
365 _i240 = (double)(long)((Y##_f0 >> 24) & 0xffffff); \
366 _c240 = (double)(long)(((X##_f1 << 16) & 0xffffff) | (X##_f0 >> 48)); \
367 _h240 = (double)(long)(((Y##_f1 << 16) & 0xffffff) | (Y##_f0 >> 48)); \
368 _b240 = (double)(long)((X##_f1 >> 8) & 0xffffff); \
369 _g240 = (double)(long)((Y##_f1 >> 8) & 0xffffff); \
370 _a240 = (double)(long)(X##_f1 >> 32); \
371 _f240 = (double)(long)(Y##_f1 >> 32); \
372 _e240 *= _const[3]; \
373 _j240 *= _const[3]; \
374 _d240 *= _const[2]; \
375 _i240 *= _const[2]; \
376 _c240 *= _const[1]; \
377 _h240 *= _const[1]; \
378 _b240 *= _const[0]; \
379 _g240 *= _const[0]; \
380 _s240.d = _e240*_j240;\
381 _r240.d = _d240*_j240 + _e240*_i240;\
382 _q240.d = _c240*_j240 + _d240*_i240 + _e240*_h240;\
383 _p240.d = _b240*_j240 + _c240*_i240 + _d240*_h240 + _e240*_g240;\
384 _o240.d = _a240*_j240 + _b240*_i240 + _c240*_h240 + _d240*_g240 + _e240*_f240;\
385 _n240.d = _a240*_i240 + _b240*_h240 + _c240*_g240 + _d240*_f240; \
386 _m240.d = _a240*_h240 + _b240*_g240 + _c240*_f240; \
387 _l240.d = _a240*_g240 + _b240*_f240; \
388 _k240 = _a240*_f240; \
389 _r240.d += _s240.d; \
390 _q240.d += _r240.d; \
391 _p240.d += _q240.d; \
392 _o240.d += _p240.d; \
393 _n240.d += _o240.d; \
394 _m240.d += _n240.d; \
395 _l240.d += _m240.d; \
396 _k240 += _l240.d; \
397 _s240.d -= ((_const[10]+_s240.d)-_const[10]); \
398 _r240.d -= ((_const[9]+_r240.d)-_const[9]); \
399 _q240.d -= ((_const[8]+_q240.d)-_const[8]); \
400 _p240.d -= ((_const[7]+_p240.d)-_const[7]); \
401 _o240.d += _const[7]; \
402 _n240.d += _const[6]; \
403 _m240.d += _const[5]; \
404 _l240.d += _const[4]; \
405 if (_s240.d != 0.0) _y240 = 1; \
406 if (_r240.d != 0.0) _y240 = 1; \
407 if (_q240.d != 0.0) _y240 = 1; \
408 if (_p240.d != 0.0) _y240 = 1; \
409 _t240 = (DItype)_k240; \
410 _u240 = _l240.i; \
411 _v240 = _m240.i; \
412 _w240 = _n240.i; \
413 _x240 = _o240.i; \
414 R##_f1 = (_t240 << (128 - (wfracbits - 1))) \
415 | ((_u240 & 0xffffff) >> ((wfracbits - 1) - 104)); \
416 R##_f0 = ((_u240 & 0xffffff) << (168 - (wfracbits - 1))) \
417 | ((_v240 & 0xffffff) << (144 - (wfracbits - 1))) \
418 | ((_w240 & 0xffffff) << (120 - (wfracbits - 1))) \
419 | ((_x240 & 0xffffff) >> ((wfracbits - 1) - 96)) \
420 | _y240; \
421 resetfe; \
422 } while (0)
423
424/*
425 * Division algorithms:
426 */
427
428#define _FP_DIV_MEAT_2_udiv(fs, R, X, Y) \
429 do { \
430 _FP_W_TYPE _n_f2, _n_f1, _n_f0, _r_f1, _r_f0, _m_f1, _m_f0; \
431 if (_FP_FRAC_GT_2(X, Y)) \
432 { \
433 _n_f2 = X##_f1 >> 1; \
434 _n_f1 = X##_f1 << (_FP_W_TYPE_SIZE - 1) | X##_f0 >> 1; \
435 _n_f0 = X##_f0 << (_FP_W_TYPE_SIZE - 1); \
436 } \
437 else \
438 { \
439 R##_e--; \
440 _n_f2 = X##_f1; \
441 _n_f1 = X##_f0; \
442 _n_f0 = 0; \
443 } \
444 \
445 /* Normalize, i.e. make the most significant bit of the \
446 denominator set. */ \
447 _FP_FRAC_SLL_2(Y, _FP_WFRACXBITS_##fs); \
448 \
449 udiv_qrnnd(R##_f1, _r_f1, _n_f2, _n_f1, Y##_f1); \
450 umul_ppmm(_m_f1, _m_f0, R##_f1, Y##_f0); \
451 _r_f0 = _n_f0; \
452 if (_FP_FRAC_GT_2(_m, _r)) \
453 { \
454 R##_f1--; \
455 _FP_FRAC_ADD_2(_r, Y, _r); \
456 if (_FP_FRAC_GE_2(_r, Y) && _FP_FRAC_GT_2(_m, _r)) \
457 { \
458 R##_f1--; \
459 _FP_FRAC_ADD_2(_r, Y, _r); \
460 } \
461 } \
462 _FP_FRAC_DEC_2(_r, _m); \
463 \
464 if (_r_f1 == Y##_f1) \
465 { \
466 /* This is a special case, not an optimization \
467 (_r/Y##_f1 would not fit into UWtype). \
468 As _r is guaranteed to be < Y, R##_f0 can be either \
469 (UWtype)-1 or (UWtype)-2. But as we know what kind \
470 of bits it is (sticky, guard, round), we don't care. \
471 We also don't care what the reminder is, because the \
472 guard bit will be set anyway. -jj */ \
473 R##_f0 = -1; \
474 } \
475 else \
476 { \
477 udiv_qrnnd(R##_f0, _r_f1, _r_f1, _r_f0, Y##_f1); \
478 umul_ppmm(_m_f1, _m_f0, R##_f0, Y##_f0); \
479 _r_f0 = 0; \
480 if (_FP_FRAC_GT_2(_m, _r)) \
481 { \
482 R##_f0--; \
483 _FP_FRAC_ADD_2(_r, Y, _r); \
484 if (_FP_FRAC_GE_2(_r, Y) && _FP_FRAC_GT_2(_m, _r)) \
485 { \
486 R##_f0--; \
487 _FP_FRAC_ADD_2(_r, Y, _r); \
488 } \
489 } \
490 if (!_FP_FRAC_EQ_2(_r, _m)) \
491 R##_f0 |= _FP_WORK_STICKY; \
492 } \
493 } while (0)
494
495
496#define _FP_DIV_MEAT_2_gmp(fs, R, X, Y) \
497 do { \
498 _FP_W_TYPE _x[4], _y[2], _z[4]; \
499 _y[0] = Y##_f0; _y[1] = Y##_f1; \
500 _x[0] = _x[3] = 0; \
501 if (_FP_FRAC_GT_2(X, Y)) \
502 { \
503 R##_e++; \
504 _x[1] = (X##_f0 << (_FP_WFRACBITS_##fs-1 - _FP_W_TYPE_SIZE) | \
505 X##_f1 >> (_FP_W_TYPE_SIZE - \
506 (_FP_WFRACBITS_##fs-1 - _FP_W_TYPE_SIZE))); \
507 _x[2] = X##_f1 << (_FP_WFRACBITS_##fs-1 - _FP_W_TYPE_SIZE); \
508 } \
509 else \
510 { \
511 _x[1] = (X##_f0 << (_FP_WFRACBITS_##fs - _FP_W_TYPE_SIZE) | \
512 X##_f1 >> (_FP_W_TYPE_SIZE - \
513 (_FP_WFRACBITS_##fs - _FP_W_TYPE_SIZE))); \
514 _x[2] = X##_f1 << (_FP_WFRACBITS_##fs - _FP_W_TYPE_SIZE); \
515 } \
516 \
517 (void) mpn_divrem (_z, 0, _x, 4, _y, 2); \
518 R##_f1 = _z[1]; \
519 R##_f0 = _z[0] | ((_x[0] | _x[1]) != 0); \
520 } while (0)
521
522
523/*
524 * Square root algorithms:
525 * We have just one right now, maybe Newton approximation
526 * should be added for those machines where division is fast.
527 */
528
529#define _FP_SQRT_MEAT_2(R, S, T, X, q) \
530 do { \
531 while (q) \
532 { \
533 T##_f1 = S##_f1 + q; \
534 if (T##_f1 <= X##_f1) \
535 { \
536 S##_f1 = T##_f1 + q; \
537 X##_f1 -= T##_f1; \
538 R##_f1 += q; \
539 } \
540 _FP_FRAC_SLL_2(X, 1); \
541 q >>= 1; \
542 } \
543 q = (_FP_W_TYPE)1 << (_FP_W_TYPE_SIZE - 1); \
544 while (q != _FP_WORK_ROUND) \
545 { \
546 T##_f0 = S##_f0 + q; \
547 T##_f1 = S##_f1; \
548 if (T##_f1 < X##_f1 || \
549 (T##_f1 == X##_f1 && T##_f0 <= X##_f0)) \
550 { \
551 S##_f0 = T##_f0 + q; \
552 S##_f1 += (T##_f0 > S##_f0); \
553 _FP_FRAC_DEC_2(X, T); \
554 R##_f0 += q; \
555 } \
556 _FP_FRAC_SLL_2(X, 1); \
557 q >>= 1; \
558 } \
559 if (X##_f0 | X##_f1) \
560 { \
561 if (S##_f1 < X##_f1 || \
562 (S##_f1 == X##_f1 && S##_f0 < X##_f0)) \
563 R##_f0 |= _FP_WORK_ROUND; \
564 R##_f0 |= _FP_WORK_STICKY; \
565 } \
566 } while (0)
567
568
569/*
570 * Assembly/disassembly for converting to/from integral types.
571 * No shifting or overflow handled here.
572 */
573
574#define _FP_FRAC_ASSEMBLE_2(r, X, rsize) \
575 do { \
576 if (rsize <= _FP_W_TYPE_SIZE) \
577 r = X##_f0; \
578 else \
579 { \
580 r = X##_f1; \
581 r <<= _FP_W_TYPE_SIZE; \
582 r += X##_f0; \
583 } \
584 } while (0)
585
586#define _FP_FRAC_DISASSEMBLE_2(X, r, rsize) \
587 do { \
588 X##_f0 = r; \
589 X##_f1 = (rsize <= _FP_W_TYPE_SIZE ? 0 : r >> _FP_W_TYPE_SIZE); \
590 } while (0)
591
592/*
593 * Convert FP values between word sizes
594 */
595
596#define _FP_FRAC_CONV_1_2(dfs, sfs, D, S) \
597 do { \
598 if (S##_c != FP_CLS_NAN) \
599 _FP_FRAC_SRS_2(S, (_FP_WFRACBITS_##sfs - _FP_WFRACBITS_##dfs), \
600 _FP_WFRACBITS_##sfs); \
601 else \
602 _FP_FRAC_SRL_2(S, (_FP_WFRACBITS_##sfs - _FP_WFRACBITS_##dfs)); \
603 D##_f = S##_f0; \
604 } while (0)
605
606#define _FP_FRAC_CONV_2_1(dfs, sfs, D, S) \
607 do { \
608 D##_f0 = S##_f; \
609 D##_f1 = 0; \
610 _FP_FRAC_SLL_2(D, (_FP_WFRACBITS_##dfs - _FP_WFRACBITS_##sfs)); \
611 } while (0)
612
613#endif
diff --git a/include/math-emu/op-4.h b/include/math-emu/op-4.h
new file mode 100644
index 000000000000..ba226f8237a6
--- /dev/null
+++ b/include/math-emu/op-4.h
@@ -0,0 +1,692 @@
1/* Software floating-point emulation.
2 Basic four-word fraction declaration and manipulation.
3 Copyright (C) 1997,1998,1999 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 Library General Public License as
12 published by the Free Software Foundation; either version 2 of the
13 License, or (at your option) any later version.
14
15 The GNU C Library is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 Library General Public License for more details.
19
20 You should have received a copy of the GNU Library General Public
21 License along with the GNU C Library; see the file COPYING.LIB. If
22 not, write to the Free Software Foundation, Inc.,
23 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
24
25#ifndef __MATH_EMU_OP_4_H__
26#define __MATH_EMU_OP_4_H__
27
28#define _FP_FRAC_DECL_4(X) _FP_W_TYPE X##_f[4]
29#define _FP_FRAC_COPY_4(D,S) \
30 (D##_f[0] = S##_f[0], D##_f[1] = S##_f[1], \
31 D##_f[2] = S##_f[2], D##_f[3] = S##_f[3])
32#define _FP_FRAC_SET_4(X,I) __FP_FRAC_SET_4(X, I)
33#define _FP_FRAC_HIGH_4(X) (X##_f[3])
34#define _FP_FRAC_LOW_4(X) (X##_f[0])
35#define _FP_FRAC_WORD_4(X,w) (X##_f[w])
36
37#define _FP_FRAC_SLL_4(X,N) \
38 do { \
39 _FP_I_TYPE _up, _down, _skip, _i; \
40 _skip = (N) / _FP_W_TYPE_SIZE; \
41 _up = (N) % _FP_W_TYPE_SIZE; \
42 _down = _FP_W_TYPE_SIZE - _up; \
43 if (!_up) \
44 for (_i = 3; _i >= _skip; --_i) \
45 X##_f[_i] = X##_f[_i-_skip]; \
46 else \
47 { \
48 for (_i = 3; _i > _skip; --_i) \
49 X##_f[_i] = X##_f[_i-_skip] << _up \
50 | X##_f[_i-_skip-1] >> _down; \
51 X##_f[_i--] = X##_f[0] << _up; \
52 } \
53 for (; _i >= 0; --_i) \
54 X##_f[_i] = 0; \
55 } while (0)
56
57/* This one was broken too */
58#define _FP_FRAC_SRL_4(X,N) \
59 do { \
60 _FP_I_TYPE _up, _down, _skip, _i; \
61 _skip = (N) / _FP_W_TYPE_SIZE; \
62 _down = (N) % _FP_W_TYPE_SIZE; \
63 _up = _FP_W_TYPE_SIZE - _down; \
64 if (!_down) \
65 for (_i = 0; _i <= 3-_skip; ++_i) \
66 X##_f[_i] = X##_f[_i+_skip]; \
67 else \
68 { \
69 for (_i = 0; _i < 3-_skip; ++_i) \
70 X##_f[_i] = X##_f[_i+_skip] >> _down \
71 | X##_f[_i+_skip+1] << _up; \
72 X##_f[_i++] = X##_f[3] >> _down; \
73 } \
74 for (; _i < 4; ++_i) \
75 X##_f[_i] = 0; \
76 } while (0)
77
78
79/* Right shift with sticky-lsb.
80 * What this actually means is that we do a standard right-shift,
81 * but that if any of the bits that fall off the right hand side
82 * were one then we always set the LSbit.
83 */
84#define _FP_FRAC_SRS_4(X,N,size) \
85 do { \
86 _FP_I_TYPE _up, _down, _skip, _i; \
87 _FP_W_TYPE _s; \
88 _skip = (N) / _FP_W_TYPE_SIZE; \
89 _down = (N) % _FP_W_TYPE_SIZE; \
90 _up = _FP_W_TYPE_SIZE - _down; \
91 for (_s = _i = 0; _i < _skip; ++_i) \
92 _s |= X##_f[_i]; \
93 _s |= X##_f[_i] << _up; \
94/* s is now != 0 if we want to set the LSbit */ \
95 if (!_down) \
96 for (_i = 0; _i <= 3-_skip; ++_i) \
97 X##_f[_i] = X##_f[_i+_skip]; \
98 else \
99 { \
100 for (_i = 0; _i < 3-_skip; ++_i) \
101 X##_f[_i] = X##_f[_i+_skip] >> _down \
102 | X##_f[_i+_skip+1] << _up; \
103 X##_f[_i++] = X##_f[3] >> _down; \
104 } \
105 for (; _i < 4; ++_i) \
106 X##_f[_i] = 0; \
107 /* don't fix the LSB until the very end when we're sure f[0] is stable */ \
108 X##_f[0] |= (_s != 0); \
109 } while (0)
110
111#define _FP_FRAC_ADD_4(R,X,Y) \
112 __FP_FRAC_ADD_4(R##_f[3], R##_f[2], R##_f[1], R##_f[0], \
113 X##_f[3], X##_f[2], X##_f[1], X##_f[0], \
114 Y##_f[3], Y##_f[2], Y##_f[1], Y##_f[0])
115
116#define _FP_FRAC_SUB_4(R,X,Y) \
117 __FP_FRAC_SUB_4(R##_f[3], R##_f[2], R##_f[1], R##_f[0], \
118 X##_f[3], X##_f[2], X##_f[1], X##_f[0], \
119 Y##_f[3], Y##_f[2], Y##_f[1], Y##_f[0])
120
121#define _FP_FRAC_DEC_4(X,Y) \
122 __FP_FRAC_DEC_4(X##_f[3], X##_f[2], X##_f[1], X##_f[0], \
123 Y##_f[3], Y##_f[2], Y##_f[1], Y##_f[0])
124
125#define _FP_FRAC_ADDI_4(X,I) \
126 __FP_FRAC_ADDI_4(X##_f[3], X##_f[2], X##_f[1], X##_f[0], I)
127
128#define _FP_ZEROFRAC_4 0,0,0,0
129#define _FP_MINFRAC_4 0,0,0,1
130#define _FP_MAXFRAC_4 (~(_FP_WS_TYPE)0), (~(_FP_WS_TYPE)0), (~(_FP_WS_TYPE)0), (~(_FP_WS_TYPE)0)
131
132#define _FP_FRAC_ZEROP_4(X) ((X##_f[0] | X##_f[1] | X##_f[2] | X##_f[3]) == 0)
133#define _FP_FRAC_NEGP_4(X) ((_FP_WS_TYPE)X##_f[3] < 0)
134#define _FP_FRAC_OVERP_4(fs,X) (_FP_FRAC_HIGH_##fs(X) & _FP_OVERFLOW_##fs)
135#define _FP_FRAC_CLEAR_OVERP_4(fs,X) (_FP_FRAC_HIGH_##fs(X) &= ~_FP_OVERFLOW_##fs)
136
137#define _FP_FRAC_EQ_4(X,Y) \
138 (X##_f[0] == Y##_f[0] && X##_f[1] == Y##_f[1] \
139 && X##_f[2] == Y##_f[2] && X##_f[3] == Y##_f[3])
140
141#define _FP_FRAC_GT_4(X,Y) \
142 (X##_f[3] > Y##_f[3] || \
143 (X##_f[3] == Y##_f[3] && (X##_f[2] > Y##_f[2] || \
144 (X##_f[2] == Y##_f[2] && (X##_f[1] > Y##_f[1] || \
145 (X##_f[1] == Y##_f[1] && X##_f[0] > Y##_f[0]) \
146 )) \
147 )) \
148 )
149
150#define _FP_FRAC_GE_4(X,Y) \
151 (X##_f[3] > Y##_f[3] || \
152 (X##_f[3] == Y##_f[3] && (X##_f[2] > Y##_f[2] || \
153 (X##_f[2] == Y##_f[2] && (X##_f[1] > Y##_f[1] || \
154 (X##_f[1] == Y##_f[1] && X##_f[0] >= Y##_f[0]) \
155 )) \
156 )) \
157 )
158
159
160#define _FP_FRAC_CLZ_4(R,X) \
161 do { \
162 if (X##_f[3]) \
163 { \
164 __FP_CLZ(R,X##_f[3]); \
165 } \
166 else if (X##_f[2]) \
167 { \
168 __FP_CLZ(R,X##_f[2]); \
169 R += _FP_W_TYPE_SIZE; \
170 } \
171 else if (X##_f[1]) \
172 { \
173 __FP_CLZ(R,X##_f[2]); \
174 R += _FP_W_TYPE_SIZE*2; \
175 } \
176 else \
177 { \
178 __FP_CLZ(R,X##_f[0]); \
179 R += _FP_W_TYPE_SIZE*3; \
180 } \
181 } while(0)
182
183
184#define _FP_UNPACK_RAW_4(fs, X, val) \
185 do { \
186 union _FP_UNION_##fs _flo; _flo.flt = (val); \
187 X##_f[0] = _flo.bits.frac0; \
188 X##_f[1] = _flo.bits.frac1; \
189 X##_f[2] = _flo.bits.frac2; \
190 X##_f[3] = _flo.bits.frac3; \
191 X##_e = _flo.bits.exp; \
192 X##_s = _flo.bits.sign; \
193 } while (0)
194
195#define _FP_UNPACK_RAW_4_P(fs, X, val) \
196 do { \
197 union _FP_UNION_##fs *_flo = \
198 (union _FP_UNION_##fs *)(val); \
199 \
200 X##_f[0] = _flo->bits.frac0; \
201 X##_f[1] = _flo->bits.frac1; \
202 X##_f[2] = _flo->bits.frac2; \
203 X##_f[3] = _flo->bits.frac3; \
204 X##_e = _flo->bits.exp; \
205 X##_s = _flo->bits.sign; \
206 } while (0)
207
208#define _FP_PACK_RAW_4(fs, val, X) \
209 do { \
210 union _FP_UNION_##fs _flo; \
211 _flo.bits.frac0 = X##_f[0]; \
212 _flo.bits.frac1 = X##_f[1]; \
213 _flo.bits.frac2 = X##_f[2]; \
214 _flo.bits.frac3 = X##_f[3]; \
215 _flo.bits.exp = X##_e; \
216 _flo.bits.sign = X##_s; \
217 (val) = _flo.flt; \
218 } while (0)
219
220#define _FP_PACK_RAW_4_P(fs, val, X) \
221 do { \
222 union _FP_UNION_##fs *_flo = \
223 (union _FP_UNION_##fs *)(val); \
224 \
225 _flo->bits.frac0 = X##_f[0]; \
226 _flo->bits.frac1 = X##_f[1]; \
227 _flo->bits.frac2 = X##_f[2]; \
228 _flo->bits.frac3 = X##_f[3]; \
229 _flo->bits.exp = X##_e; \
230 _flo->bits.sign = X##_s; \
231 } while (0)
232
233/*
234 * Multiplication algorithms:
235 */
236
237/* Given a 1W * 1W => 2W primitive, do the extended multiplication. */
238
239#define _FP_MUL_MEAT_4_wide(wfracbits, R, X, Y, doit) \
240 do { \
241 _FP_FRAC_DECL_8(_z); _FP_FRAC_DECL_2(_b); _FP_FRAC_DECL_2(_c); \
242 _FP_FRAC_DECL_2(_d); _FP_FRAC_DECL_2(_e); _FP_FRAC_DECL_2(_f); \
243 \
244 doit(_FP_FRAC_WORD_8(_z,1), _FP_FRAC_WORD_8(_z,0), X##_f[0], Y##_f[0]); \
245 doit(_b_f1, _b_f0, X##_f[0], Y##_f[1]); \
246 doit(_c_f1, _c_f0, X##_f[1], Y##_f[0]); \
247 doit(_d_f1, _d_f0, X##_f[1], Y##_f[1]); \
248 doit(_e_f1, _e_f0, X##_f[0], Y##_f[2]); \
249 doit(_f_f1, _f_f0, X##_f[2], Y##_f[0]); \
250 __FP_FRAC_ADD_3(_FP_FRAC_WORD_8(_z,3),_FP_FRAC_WORD_8(_z,2), \
251 _FP_FRAC_WORD_8(_z,1), 0,_b_f1,_b_f0, \
252 0,0,_FP_FRAC_WORD_8(_z,1)); \
253 __FP_FRAC_ADD_3(_FP_FRAC_WORD_8(_z,3),_FP_FRAC_WORD_8(_z,2), \
254 _FP_FRAC_WORD_8(_z,1), 0,_c_f1,_c_f0, \
255 _FP_FRAC_WORD_8(_z,3),_FP_FRAC_WORD_8(_z,2), \
256 _FP_FRAC_WORD_8(_z,1)); \
257 __FP_FRAC_ADD_3(_FP_FRAC_WORD_8(_z,4),_FP_FRAC_WORD_8(_z,3), \
258 _FP_FRAC_WORD_8(_z,2), 0,_d_f1,_d_f0, \
259 0,_FP_FRAC_WORD_8(_z,3),_FP_FRAC_WORD_8(_z,2)); \
260 __FP_FRAC_ADD_3(_FP_FRAC_WORD_8(_z,4),_FP_FRAC_WORD_8(_z,3), \
261 _FP_FRAC_WORD_8(_z,2), 0,_e_f1,_e_f0, \
262 _FP_FRAC_WORD_8(_z,4),_FP_FRAC_WORD_8(_z,3), \
263 _FP_FRAC_WORD_8(_z,2)); \
264 __FP_FRAC_ADD_3(_FP_FRAC_WORD_8(_z,4),_FP_FRAC_WORD_8(_z,3), \
265 _FP_FRAC_WORD_8(_z,2), 0,_f_f1,_f_f0, \
266 _FP_FRAC_WORD_8(_z,4),_FP_FRAC_WORD_8(_z,3), \
267 _FP_FRAC_WORD_8(_z,2)); \
268 doit(_b_f1, _b_f0, X##_f[0], Y##_f[3]); \
269 doit(_c_f1, _c_f0, X##_f[3], Y##_f[0]); \
270 doit(_d_f1, _d_f0, X##_f[1], Y##_f[2]); \
271 doit(_e_f1, _e_f0, X##_f[2], Y##_f[1]); \
272 __FP_FRAC_ADD_3(_FP_FRAC_WORD_8(_z,5),_FP_FRAC_WORD_8(_z,4), \
273 _FP_FRAC_WORD_8(_z,3), 0,_b_f1,_b_f0, \
274 0,_FP_FRAC_WORD_8(_z,4),_FP_FRAC_WORD_8(_z,3)); \
275 __FP_FRAC_ADD_3(_FP_FRAC_WORD_8(_z,5),_FP_FRAC_WORD_8(_z,4), \
276 _FP_FRAC_WORD_8(_z,3), 0,_c_f1,_c_f0, \
277 _FP_FRAC_WORD_8(_z,5),_FP_FRAC_WORD_8(_z,4), \
278 _FP_FRAC_WORD_8(_z,3)); \
279 __FP_FRAC_ADD_3(_FP_FRAC_WORD_8(_z,5),_FP_FRAC_WORD_8(_z,4), \
280 _FP_FRAC_WORD_8(_z,3), 0,_d_f1,_d_f0, \
281 _FP_FRAC_WORD_8(_z,5),_FP_FRAC_WORD_8(_z,4), \
282 _FP_FRAC_WORD_8(_z,3)); \
283 __FP_FRAC_ADD_3(_FP_FRAC_WORD_8(_z,5),_FP_FRAC_WORD_8(_z,4), \
284 _FP_FRAC_WORD_8(_z,3), 0,_e_f1,_e_f0, \
285 _FP_FRAC_WORD_8(_z,5),_FP_FRAC_WORD_8(_z,4), \
286 _FP_FRAC_WORD_8(_z,3)); \
287 doit(_b_f1, _b_f0, X##_f[2], Y##_f[2]); \
288 doit(_c_f1, _c_f0, X##_f[1], Y##_f[3]); \
289 doit(_d_f1, _d_f0, X##_f[3], Y##_f[1]); \
290 doit(_e_f1, _e_f0, X##_f[2], Y##_f[3]); \
291 doit(_f_f1, _f_f0, X##_f[3], Y##_f[2]); \
292 __FP_FRAC_ADD_3(_FP_FRAC_WORD_8(_z,6),_FP_FRAC_WORD_8(_z,5), \
293 _FP_FRAC_WORD_8(_z,4), 0,_b_f1,_b_f0, \
294 0,_FP_FRAC_WORD_8(_z,5),_FP_FRAC_WORD_8(_z,4)); \
295 __FP_FRAC_ADD_3(_FP_FRAC_WORD_8(_z,6),_FP_FRAC_WORD_8(_z,5), \
296 _FP_FRAC_WORD_8(_z,4), 0,_c_f1,_c_f0, \
297 _FP_FRAC_WORD_8(_z,6),_FP_FRAC_WORD_8(_z,5), \
298 _FP_FRAC_WORD_8(_z,4)); \
299 __FP_FRAC_ADD_3(_FP_FRAC_WORD_8(_z,6),_FP_FRAC_WORD_8(_z,5), \
300 _FP_FRAC_WORD_8(_z,4), 0,_d_f1,_d_f0, \
301 _FP_FRAC_WORD_8(_z,6),_FP_FRAC_WORD_8(_z,5), \
302 _FP_FRAC_WORD_8(_z,4)); \
303 __FP_FRAC_ADD_3(_FP_FRAC_WORD_8(_z,7),_FP_FRAC_WORD_8(_z,6), \
304 _FP_FRAC_WORD_8(_z,5), 0,_e_f1,_e_f0, \
305 0,_FP_FRAC_WORD_8(_z,6),_FP_FRAC_WORD_8(_z,5)); \
306 __FP_FRAC_ADD_3(_FP_FRAC_WORD_8(_z,7),_FP_FRAC_WORD_8(_z,6), \
307 _FP_FRAC_WORD_8(_z,5), 0,_f_f1,_f_f0, \
308 _FP_FRAC_WORD_8(_z,7),_FP_FRAC_WORD_8(_z,6), \
309 _FP_FRAC_WORD_8(_z,5)); \
310 doit(_b_f1, _b_f0, X##_f[3], Y##_f[3]); \
311 __FP_FRAC_ADD_2(_FP_FRAC_WORD_8(_z,7),_FP_FRAC_WORD_8(_z,6), \
312 _b_f1,_b_f0, \
313 _FP_FRAC_WORD_8(_z,7),_FP_FRAC_WORD_8(_z,6)); \
314 \
315 /* Normalize since we know where the msb of the multiplicands \
316 were (bit B), we know that the msb of the of the product is \
317 at either 2B or 2B-1. */ \
318 _FP_FRAC_SRS_8(_z, wfracbits-1, 2*wfracbits); \
319 __FP_FRAC_SET_4(R, _FP_FRAC_WORD_8(_z,3), _FP_FRAC_WORD_8(_z,2), \
320 _FP_FRAC_WORD_8(_z,1), _FP_FRAC_WORD_8(_z,0)); \
321 } while (0)
322
323#define _FP_MUL_MEAT_4_gmp(wfracbits, R, X, Y) \
324 do { \
325 _FP_FRAC_DECL_8(_z); \
326 \
327 mpn_mul_n(_z_f, _x_f, _y_f, 4); \
328 \
329 /* Normalize since we know where the msb of the multiplicands \
330 were (bit B), we know that the msb of the of the product is \
331 at either 2B or 2B-1. */ \
332 _FP_FRAC_SRS_8(_z, wfracbits-1, 2*wfracbits); \
333 __FP_FRAC_SET_4(R, _FP_FRAC_WORD_8(_z,3), _FP_FRAC_WORD_8(_z,2), \
334 _FP_FRAC_WORD_8(_z,1), _FP_FRAC_WORD_8(_z,0)); \
335 } while (0)
336
337/*
338 * Helper utility for _FP_DIV_MEAT_4_udiv:
339 * pppp = m * nnn
340 */
341#define umul_ppppmnnn(p3,p2,p1,p0,m,n2,n1,n0) \
342 do { \
343 UWtype _t; \
344 umul_ppmm(p1,p0,m,n0); \
345 umul_ppmm(p2,_t,m,n1); \
346 __FP_FRAC_ADDI_2(p2,p1,_t); \
347 umul_ppmm(p3,_t,m,n2); \
348 __FP_FRAC_ADDI_2(p3,p2,_t); \
349 } while (0)
350
351/*
352 * Division algorithms:
353 */
354
355#define _FP_DIV_MEAT_4_udiv(fs, R, X, Y) \
356 do { \
357 int _i; \
358 _FP_FRAC_DECL_4(_n); _FP_FRAC_DECL_4(_m); \
359 _FP_FRAC_SET_4(_n, _FP_ZEROFRAC_4); \
360 if (_FP_FRAC_GT_4(X, Y)) \
361 { \
362 _n_f[3] = X##_f[0] << (_FP_W_TYPE_SIZE - 1); \
363 _FP_FRAC_SRL_4(X, 1); \
364 } \
365 else \
366 R##_e--; \
367 \
368 /* Normalize, i.e. make the most significant bit of the \
369 denominator set. */ \
370 _FP_FRAC_SLL_4(Y, _FP_WFRACXBITS_##fs); \
371 \
372 for (_i = 3; ; _i--) \
373 { \
374 if (X##_f[3] == Y##_f[3]) \
375 { \
376 /* This is a special case, not an optimization \
377 (X##_f[3]/Y##_f[3] would not fit into UWtype). \
378 As X## is guaranteed to be < Y, R##_f[_i] can be either \
379 (UWtype)-1 or (UWtype)-2. */ \
380 R##_f[_i] = -1; \
381 if (!_i) \
382 break; \
383 __FP_FRAC_SUB_4(X##_f[3], X##_f[2], X##_f[1], X##_f[0], \
384 Y##_f[2], Y##_f[1], Y##_f[0], 0, \
385 X##_f[2], X##_f[1], X##_f[0], _n_f[_i]); \
386 _FP_FRAC_SUB_4(X, Y, X); \
387 if (X##_f[3] > Y##_f[3]) \
388 { \
389 R##_f[_i] = -2; \
390 _FP_FRAC_ADD_4(X, Y, X); \
391 } \
392 } \
393 else \
394 { \
395 udiv_qrnnd(R##_f[_i], X##_f[3], X##_f[3], X##_f[2], Y##_f[3]); \
396 umul_ppppmnnn(_m_f[3], _m_f[2], _m_f[1], _m_f[0], \
397 R##_f[_i], Y##_f[2], Y##_f[1], Y##_f[0]); \
398 X##_f[2] = X##_f[1]; \
399 X##_f[1] = X##_f[0]; \
400 X##_f[0] = _n_f[_i]; \
401 if (_FP_FRAC_GT_4(_m, X)) \
402 { \
403 R##_f[_i]--; \
404 _FP_FRAC_ADD_4(X, Y, X); \
405 if (_FP_FRAC_GE_4(X, Y) && _FP_FRAC_GT_4(_m, X)) \
406 { \
407 R##_f[_i]--; \
408 _FP_FRAC_ADD_4(X, Y, X); \
409 } \
410 } \
411 _FP_FRAC_DEC_4(X, _m); \
412 if (!_i) \
413 { \
414 if (!_FP_FRAC_EQ_4(X, _m)) \
415 R##_f[0] |= _FP_WORK_STICKY; \
416 break; \
417 } \
418 } \
419 } \
420 } while (0)
421
422
423/*
424 * Square root algorithms:
425 * We have just one right now, maybe Newton approximation
426 * should be added for those machines where division is fast.
427 */
428
429#define _FP_SQRT_MEAT_4(R, S, T, X, q) \
430 do { \
431 while (q) \
432 { \
433 T##_f[3] = S##_f[3] + q; \
434 if (T##_f[3] <= X##_f[3]) \
435 { \
436 S##_f[3] = T##_f[3] + q; \
437 X##_f[3] -= T##_f[3]; \
438 R##_f[3] += q; \
439 } \
440 _FP_FRAC_SLL_4(X, 1); \
441 q >>= 1; \
442 } \
443 q = (_FP_W_TYPE)1 << (_FP_W_TYPE_SIZE - 1); \
444 while (q) \
445 { \
446 T##_f[2] = S##_f[2] + q; \
447 T##_f[3] = S##_f[3]; \
448 if (T##_f[3] < X##_f[3] || \
449 (T##_f[3] == X##_f[3] && T##_f[2] <= X##_f[2])) \
450 { \
451 S##_f[2] = T##_f[2] + q; \
452 S##_f[3] += (T##_f[2] > S##_f[2]); \
453 __FP_FRAC_DEC_2(X##_f[3], X##_f[2], \
454 T##_f[3], T##_f[2]); \
455 R##_f[2] += q; \
456 } \
457 _FP_FRAC_SLL_4(X, 1); \
458 q >>= 1; \
459 } \
460 q = (_FP_W_TYPE)1 << (_FP_W_TYPE_SIZE - 1); \
461 while (q) \
462 { \
463 T##_f[1] = S##_f[1] + q; \
464 T##_f[2] = S##_f[2]; \
465 T##_f[3] = S##_f[3]; \
466 if (T##_f[3] < X##_f[3] || \
467 (T##_f[3] == X##_f[3] && (T##_f[2] < X##_f[2] || \
468 (T##_f[2] == X##_f[2] && T##_f[1] <= X##_f[1])))) \
469 { \
470 S##_f[1] = T##_f[1] + q; \
471 S##_f[2] += (T##_f[1] > S##_f[1]); \
472 S##_f[3] += (T##_f[2] > S##_f[2]); \
473 __FP_FRAC_DEC_3(X##_f[3], X##_f[2], X##_f[1], \
474 T##_f[3], T##_f[2], T##_f[1]); \
475 R##_f[1] += q; \
476 } \
477 _FP_FRAC_SLL_4(X, 1); \
478 q >>= 1; \
479 } \
480 q = (_FP_W_TYPE)1 << (_FP_W_TYPE_SIZE - 1); \
481 while (q != _FP_WORK_ROUND) \
482 { \
483 T##_f[0] = S##_f[0] + q; \
484 T##_f[1] = S##_f[1]; \
485 T##_f[2] = S##_f[2]; \
486 T##_f[3] = S##_f[3]; \
487 if (_FP_FRAC_GE_4(X,T)) \
488 { \
489 S##_f[0] = T##_f[0] + q; \
490 S##_f[1] += (T##_f[0] > S##_f[0]); \
491 S##_f[2] += (T##_f[1] > S##_f[1]); \
492 S##_f[3] += (T##_f[2] > S##_f[2]); \
493 _FP_FRAC_DEC_4(X, T); \
494 R##_f[0] += q; \
495 } \
496 _FP_FRAC_SLL_4(X, 1); \
497 q >>= 1; \
498 } \
499 if (!_FP_FRAC_ZEROP_4(X)) \
500 { \
501 if (_FP_FRAC_GT_4(X,S)) \
502 R##_f[0] |= _FP_WORK_ROUND; \
503 R##_f[0] |= _FP_WORK_STICKY; \
504 } \
505 } while (0)
506
507
508/*
509 * Internals
510 */
511
512#define __FP_FRAC_SET_4(X,I3,I2,I1,I0) \
513 (X##_f[3] = I3, X##_f[2] = I2, X##_f[1] = I1, X##_f[0] = I0)
514
515#ifndef __FP_FRAC_ADD_3
516#define __FP_FRAC_ADD_3(r2,r1,r0,x2,x1,x0,y2,y1,y0) \
517 do { \
518 int _c1, _c2; \
519 r0 = x0 + y0; \
520 _c1 = r0 < x0; \
521 r1 = x1 + y1; \
522 _c2 = r1 < x1; \
523 r1 += _c1; \
524 _c2 |= r1 < _c1; \
525 r2 = x2 + y2 + _c2; \
526 } while (0)
527#endif
528
529#ifndef __FP_FRAC_ADD_4
530#define __FP_FRAC_ADD_4(r3,r2,r1,r0,x3,x2,x1,x0,y3,y2,y1,y0) \
531 do { \
532 int _c1, _c2, _c3; \
533 r0 = x0 + y0; \
534 _c1 = r0 < x0; \
535 r1 = x1 + y1; \
536 _c2 = r1 < x1; \
537 r1 += _c1; \
538 _c2 |= r1 < _c1; \
539 r2 = x2 + y2; \
540 _c3 = r2 < x2; \
541 r2 += _c2; \
542 _c3 |= r2 < _c2; \
543 r3 = x3 + y3 + _c3; \
544 } while (0)
545#endif
546
547#ifndef __FP_FRAC_SUB_3
548#define __FP_FRAC_SUB_3(r2,r1,r0,x2,x1,x0,y2,y1,y0) \
549 do { \
550 int _c1, _c2; \
551 r0 = x0 - y0; \
552 _c1 = r0 > x0; \
553 r1 = x1 - y1; \
554 _c2 = r1 > x1; \
555 r1 -= _c1; \
556 _c2 |= r1 > _c1; \
557 r2 = x2 - y2 - _c2; \
558 } while (0)
559#endif
560
561#ifndef __FP_FRAC_SUB_4
562#define __FP_FRAC_SUB_4(r3,r2,r1,r0,x3,x2,x1,x0,y3,y2,y1,y0) \
563 do { \
564 int _c1, _c2, _c3; \
565 r0 = x0 - y0; \
566 _c1 = r0 > x0; \
567 r1 = x1 - y1; \
568 _c2 = r1 > x1; \
569 r1 -= _c1; \
570 _c2 |= r1 > _c1; \
571 r2 = x2 - y2; \
572 _c3 = r2 > x2; \
573 r2 -= _c2; \
574 _c3 |= r2 > _c2; \
575 r3 = x3 - y3 - _c3; \
576 } while (0)
577#endif
578
579#ifndef __FP_FRAC_DEC_3
580#define __FP_FRAC_DEC_3(x2,x1,x0,y2,y1,y0) \
581 do { \
582 UWtype _t0, _t1, _t2; \
583 _t0 = x0, _t1 = x1, _t2 = x2; \
584 __FP_FRAC_SUB_3 (x2, x1, x0, _t2, _t1, _t0, y2, y1, y0); \
585 } while (0)
586#endif
587
588#ifndef __FP_FRAC_DEC_4
589#define __FP_FRAC_DEC_4(x3,x2,x1,x0,y3,y2,y1,y0) \
590 do { \
591 UWtype _t0, _t1, _t2, _t3; \
592 _t0 = x0, _t1 = x1, _t2 = x2, _t3 = x3; \
593 __FP_FRAC_SUB_4 (x3,x2,x1,x0,_t3,_t2,_t1,_t0, y3,y2,y1,y0); \
594 } while (0)
595#endif
596
597#ifndef __FP_FRAC_ADDI_4
598#define __FP_FRAC_ADDI_4(x3,x2,x1,x0,i) \
599 do { \
600 UWtype _t; \
601 _t = ((x0 += i) < i); \
602 x1 += _t; _t = (x1 < _t); \
603 x2 += _t; _t = (x2 < _t); \
604 x3 += _t; \
605 } while (0)
606#endif
607
608/* Convert FP values between word sizes. This appears to be more
609 * complicated than I'd have expected it to be, so these might be
610 * wrong... These macros are in any case somewhat bogus because they
611 * use information about what various FRAC_n variables look like
612 * internally [eg, that 2 word vars are X_f0 and x_f1]. But so do
613 * the ones in op-2.h and op-1.h.
614 */
615#define _FP_FRAC_CONV_1_4(dfs, sfs, D, S) \
616 do { \
617 if (S##_c != FP_CLS_NAN) \
618 _FP_FRAC_SRS_4(S, (_FP_WFRACBITS_##sfs - _FP_WFRACBITS_##dfs), \
619 _FP_WFRACBITS_##sfs); \
620 else \
621 _FP_FRAC_SRL_4(S, (_FP_WFRACBITS_##sfs - _FP_WFRACBITS_##dfs)); \
622 D##_f = S##_f[0]; \
623 } while (0)
624
625#define _FP_FRAC_CONV_2_4(dfs, sfs, D, S) \
626 do { \
627 if (S##_c != FP_CLS_NAN) \
628 _FP_FRAC_SRS_4(S, (_FP_WFRACBITS_##sfs - _FP_WFRACBITS_##dfs), \
629 _FP_WFRACBITS_##sfs); \
630 else \
631 _FP_FRAC_SRL_4(S, (_FP_WFRACBITS_##sfs - _FP_WFRACBITS_##dfs)); \
632 D##_f0 = S##_f[0]; \
633 D##_f1 = S##_f[1]; \
634 } while (0)
635
636/* Assembly/disassembly for converting to/from integral types.
637 * No shifting or overflow handled here.
638 */
639/* Put the FP value X into r, which is an integer of size rsize. */
640#define _FP_FRAC_ASSEMBLE_4(r, X, rsize) \
641 do { \
642 if (rsize <= _FP_W_TYPE_SIZE) \
643 r = X##_f[0]; \
644 else if (rsize <= 2*_FP_W_TYPE_SIZE) \
645 { \
646 r = X##_f[1]; \
647 r <<= _FP_W_TYPE_SIZE; \
648 r += X##_f[0]; \
649 } \
650 else \
651 { \
652 /* I'm feeling lazy so we deal with int == 3words (implausible)*/ \
653 /* and int == 4words as a single case. */ \
654 r = X##_f[3]; \
655 r <<= _FP_W_TYPE_SIZE; \
656 r += X##_f[2]; \
657 r <<= _FP_W_TYPE_SIZE; \
658 r += X##_f[1]; \
659 r <<= _FP_W_TYPE_SIZE; \
660 r += X##_f[0]; \
661 } \
662 } while (0)
663
664/* "No disassemble Number Five!" */
665/* move an integer of size rsize into X's fractional part. We rely on
666 * the _f[] array consisting of words of size _FP_W_TYPE_SIZE to avoid
667 * having to mask the values we store into it.
668 */
669#define _FP_FRAC_DISASSEMBLE_4(X, r, rsize) \
670 do { \
671 X##_f[0] = r; \
672 X##_f[1] = (rsize <= _FP_W_TYPE_SIZE ? 0 : r >> _FP_W_TYPE_SIZE); \
673 X##_f[2] = (rsize <= 2*_FP_W_TYPE_SIZE ? 0 : r >> 2*_FP_W_TYPE_SIZE); \
674 X##_f[3] = (rsize <= 3*_FP_W_TYPE_SIZE ? 0 : r >> 3*_FP_W_TYPE_SIZE); \
675 } while (0)
676
677#define _FP_FRAC_CONV_4_1(dfs, sfs, D, S) \
678 do { \
679 D##_f[0] = S##_f; \
680 D##_f[1] = D##_f[2] = D##_f[3] = 0; \
681 _FP_FRAC_SLL_4(D, (_FP_WFRACBITS_##dfs - _FP_WFRACBITS_##sfs)); \
682 } while (0)
683
684#define _FP_FRAC_CONV_4_2(dfs, sfs, D, S) \
685 do { \
686 D##_f[0] = S##_f0; \
687 D##_f[1] = S##_f1; \
688 D##_f[2] = D##_f[3] = 0; \
689 _FP_FRAC_SLL_4(D, (_FP_WFRACBITS_##dfs - _FP_WFRACBITS_##sfs)); \
690 } while (0)
691
692#endif
diff --git a/include/math-emu/op-8.h b/include/math-emu/op-8.h
new file mode 100644
index 000000000000..8b8c05eb8283
--- /dev/null
+++ b/include/math-emu/op-8.h
@@ -0,0 +1,107 @@
1/* Software floating-point emulation.
2 Basic eight-word fraction declaration and manipulation.
3 Copyright (C) 1997,1998,1999 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) and
7 Peter Maydell (pmaydell@chiark.greenend.org.uk).
8
9 The GNU C Library is free software; you can redistribute it and/or
10 modify it under the terms of the GNU Library General Public License as
11 published by the Free Software Foundation; either version 2 of the
12 License, or (at your option) any later version.
13
14 The GNU C Library is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 Library General Public License for more details.
18
19 You should have received a copy of the GNU Library General Public
20 License along with the GNU C Library; see the file COPYING.LIB. If
21 not, write to the Free Software Foundation, Inc.,
22 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
23
24#ifndef __MATH_EMU_OP_8_H__
25#define __MATH_EMU_OP_8_H__
26
27/* We need just a few things from here for op-4, if we ever need some
28 other macros, they can be added. */
29#define _FP_FRAC_DECL_8(X) _FP_W_TYPE X##_f[8]
30#define _FP_FRAC_HIGH_8(X) (X##_f[7])
31#define _FP_FRAC_LOW_8(X) (X##_f[0])
32#define _FP_FRAC_WORD_8(X,w) (X##_f[w])
33
34#define _FP_FRAC_SLL_8(X,N) \
35 do { \
36 _FP_I_TYPE _up, _down, _skip, _i; \
37 _skip = (N) / _FP_W_TYPE_SIZE; \
38 _up = (N) % _FP_W_TYPE_SIZE; \
39 _down = _FP_W_TYPE_SIZE - _up; \
40 if (!_up) \
41 for (_i = 7; _i >= _skip; --_i) \
42 X##_f[_i] = X##_f[_i-_skip]; \
43 else \
44 { \
45 for (_i = 7; _i > _skip; --_i) \
46 X##_f[_i] = X##_f[_i-_skip] << _up \
47 | X##_f[_i-_skip-1] >> _down; \
48 X##_f[_i--] = X##_f[0] << _up; \
49 } \
50 for (; _i >= 0; --_i) \
51 X##_f[_i] = 0; \
52 } while (0)
53
54#define _FP_FRAC_SRL_8(X,N) \
55 do { \
56 _FP_I_TYPE _up, _down, _skip, _i; \
57 _skip = (N) / _FP_W_TYPE_SIZE; \
58 _down = (N) % _FP_W_TYPE_SIZE; \
59 _up = _FP_W_TYPE_SIZE - _down; \
60 if (!_down) \
61 for (_i = 0; _i <= 7-_skip; ++_i) \
62 X##_f[_i] = X##_f[_i+_skip]; \
63 else \
64 { \
65 for (_i = 0; _i < 7-_skip; ++_i) \
66 X##_f[_i] = X##_f[_i+_skip] >> _down \
67 | X##_f[_i+_skip+1] << _up; \
68 X##_f[_i++] = X##_f[7] >> _down; \
69 } \
70 for (; _i < 8; ++_i) \
71 X##_f[_i] = 0; \
72 } while (0)
73
74
75/* Right shift with sticky-lsb.
76 * What this actually means is that we do a standard right-shift,
77 * but that if any of the bits that fall off the right hand side
78 * were one then we always set the LSbit.
79 */
80#define _FP_FRAC_SRS_8(X,N,size) \
81 do { \
82 _FP_I_TYPE _up, _down, _skip, _i; \
83 _FP_W_TYPE _s; \
84 _skip = (N) / _FP_W_TYPE_SIZE; \
85 _down = (N) % _FP_W_TYPE_SIZE; \
86 _up = _FP_W_TYPE_SIZE - _down; \
87 for (_s = _i = 0; _i < _skip; ++_i) \
88 _s |= X##_f[_i]; \
89 _s |= X##_f[_i] << _up; \
90/* s is now != 0 if we want to set the LSbit */ \
91 if (!_down) \
92 for (_i = 0; _i <= 7-_skip; ++_i) \
93 X##_f[_i] = X##_f[_i+_skip]; \
94 else \
95 { \
96 for (_i = 0; _i < 7-_skip; ++_i) \
97 X##_f[_i] = X##_f[_i+_skip] >> _down \
98 | X##_f[_i+_skip+1] << _up; \
99 X##_f[_i++] = X##_f[7] >> _down; \
100 } \
101 for (; _i < 8; ++_i) \
102 X##_f[_i] = 0; \
103 /* don't fix the LSB until the very end when we're sure f[0] is stable */ \
104 X##_f[0] |= (_s != 0); \
105 } while (0)
106
107#endif
diff --git a/include/math-emu/op-common.h b/include/math-emu/op-common.h
new file mode 100644
index 000000000000..93780abd01bc
--- /dev/null
+++ b/include/math-emu/op-common.h
@@ -0,0 +1,853 @@
1/* Software floating-point emulation. Common operations.
2 Copyright (C) 1997,1998,1999 Free Software Foundation, Inc.
3 This file is part of the GNU C Library.
4 Contributed by Richard Henderson (rth@cygnus.com),
5 Jakub Jelinek (jj@ultra.linux.cz),
6 David S. Miller (davem@redhat.com) and
7 Peter Maydell (pmaydell@chiark.greenend.org.uk).
8
9 The GNU C Library is free software; you can redistribute it and/or
10 modify it under the terms of the GNU Library General Public License as
11 published by the Free Software Foundation; either version 2 of the
12 License, or (at your option) any later version.
13
14 The GNU C Library is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 Library General Public License for more details.
18
19 You should have received a copy of the GNU Library General Public
20 License along with the GNU C Library; see the file COPYING.LIB. If
21 not, write to the Free Software Foundation, Inc.,
22 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
23
24#ifndef __MATH_EMU_OP_COMMON_H__
25#define __MATH_EMU_OP_COMMON_H__
26
27#define _FP_DECL(wc, X) \
28 _FP_I_TYPE X##_c=0, X##_s=0, X##_e=0; \
29 _FP_FRAC_DECL_##wc(X)
30
31/*
32 * Finish truely unpacking a native fp value by classifying the kind
33 * of fp value and normalizing both the exponent and the fraction.
34 */
35
36#define _FP_UNPACK_CANONICAL(fs, wc, X) \
37do { \
38 switch (X##_e) \
39 { \
40 default: \
41 _FP_FRAC_HIGH_RAW_##fs(X) |= _FP_IMPLBIT_##fs; \
42 _FP_FRAC_SLL_##wc(X, _FP_WORKBITS); \
43 X##_e -= _FP_EXPBIAS_##fs; \
44 X##_c = FP_CLS_NORMAL; \
45 break; \
46 \
47 case 0: \
48 if (_FP_FRAC_ZEROP_##wc(X)) \
49 X##_c = FP_CLS_ZERO; \
50 else \
51 { \
52 /* a denormalized number */ \
53 _FP_I_TYPE _shift; \
54 _FP_FRAC_CLZ_##wc(_shift, X); \
55 _shift -= _FP_FRACXBITS_##fs; \
56 _FP_FRAC_SLL_##wc(X, (_shift+_FP_WORKBITS)); \
57 X##_e -= _FP_EXPBIAS_##fs - 1 + _shift; \
58 X##_c = FP_CLS_NORMAL; \
59 FP_SET_EXCEPTION(FP_EX_DENORM); \
60 if (FP_DENORM_ZERO) \
61 { \
62 FP_SET_EXCEPTION(FP_EX_INEXACT); \
63 X##_c = FP_CLS_ZERO; \
64 } \
65 } \
66 break; \
67 \
68 case _FP_EXPMAX_##fs: \
69 if (_FP_FRAC_ZEROP_##wc(X)) \
70 X##_c = FP_CLS_INF; \
71 else \
72 { \
73 X##_c = FP_CLS_NAN; \
74 /* Check for signaling NaN */ \
75 if (!(_FP_FRAC_HIGH_RAW_##fs(X) & _FP_QNANBIT_##fs)) \
76 FP_SET_EXCEPTION(FP_EX_INVALID); \
77 } \
78 break; \
79 } \
80} while (0)
81
82/*
83 * Before packing the bits back into the native fp result, take care
84 * of such mundane things as rounding and overflow. Also, for some
85 * kinds of fp values, the original parts may not have been fully
86 * extracted -- but that is ok, we can regenerate them now.
87 */
88
89#define _FP_PACK_CANONICAL(fs, wc, X) \
90do { \
91 switch (X##_c) \
92 { \
93 case FP_CLS_NORMAL: \
94 X##_e += _FP_EXPBIAS_##fs; \
95 if (X##_e > 0) \
96 { \
97 _FP_ROUND(wc, X); \
98 if (_FP_FRAC_OVERP_##wc(fs, X)) \
99 { \
100 _FP_FRAC_CLEAR_OVERP_##wc(fs, X); \
101 X##_e++; \
102 } \
103 _FP_FRAC_SRL_##wc(X, _FP_WORKBITS); \
104 if (X##_e >= _FP_EXPMAX_##fs) \
105 { \
106 /* overflow */ \
107 switch (FP_ROUNDMODE) \
108 { \
109 case FP_RND_NEAREST: \
110 X##_c = FP_CLS_INF; \
111 break; \
112 case FP_RND_PINF: \
113 if (!X##_s) X##_c = FP_CLS_INF; \
114 break; \
115 case FP_RND_MINF: \
116 if (X##_s) X##_c = FP_CLS_INF; \
117 break; \
118 } \
119 if (X##_c == FP_CLS_INF) \
120 { \
121 /* Overflow to infinity */ \
122 X##_e = _FP_EXPMAX_##fs; \
123 _FP_FRAC_SET_##wc(X, _FP_ZEROFRAC_##wc); \
124 } \
125 else \
126 { \
127 /* Overflow to maximum normal */ \
128 X##_e = _FP_EXPMAX_##fs - 1; \
129 _FP_FRAC_SET_##wc(X, _FP_MAXFRAC_##wc); \
130 } \
131 FP_SET_EXCEPTION(FP_EX_OVERFLOW); \
132 FP_SET_EXCEPTION(FP_EX_INEXACT); \
133 } \
134 } \
135 else \
136 { \
137 /* we've got a denormalized number */ \
138 X##_e = -X##_e + 1; \
139 if (X##_e <= _FP_WFRACBITS_##fs) \
140 { \
141 _FP_FRAC_SRS_##wc(X, X##_e, _FP_WFRACBITS_##fs); \
142 _FP_ROUND(wc, X); \
143 if (_FP_FRAC_HIGH_##fs(X) \
144 & (_FP_OVERFLOW_##fs >> 1)) \
145 { \
146 X##_e = 1; \
147 _FP_FRAC_SET_##wc(X, _FP_ZEROFRAC_##wc); \
148 } \
149 else \
150 { \
151 X##_e = 0; \
152 _FP_FRAC_SRL_##wc(X, _FP_WORKBITS); \
153 FP_SET_EXCEPTION(FP_EX_UNDERFLOW); \
154 } \
155 } \
156 else \
157 { \
158 /* underflow to zero */ \
159 X##_e = 0; \
160 if (!_FP_FRAC_ZEROP_##wc(X)) \
161 { \
162 _FP_FRAC_SET_##wc(X, _FP_MINFRAC_##wc); \
163 _FP_ROUND(wc, X); \
164 _FP_FRAC_LOW_##wc(X) >>= (_FP_WORKBITS); \
165 } \
166 FP_SET_EXCEPTION(FP_EX_UNDERFLOW); \
167 } \
168 } \
169 break; \
170 \
171 case FP_CLS_ZERO: \
172 X##_e = 0; \
173 _FP_FRAC_SET_##wc(X, _FP_ZEROFRAC_##wc); \
174 break; \
175 \
176 case FP_CLS_INF: \
177 X##_e = _FP_EXPMAX_##fs; \
178 _FP_FRAC_SET_##wc(X, _FP_ZEROFRAC_##wc); \
179 break; \
180 \
181 case FP_CLS_NAN: \
182 X##_e = _FP_EXPMAX_##fs; \
183 if (!_FP_KEEPNANFRACP) \
184 { \
185 _FP_FRAC_SET_##wc(X, _FP_NANFRAC_##fs); \
186 X##_s = _FP_NANSIGN_##fs; \
187 } \
188 else \
189 _FP_FRAC_HIGH_RAW_##fs(X) |= _FP_QNANBIT_##fs; \
190 break; \
191 } \
192} while (0)
193
194/* This one accepts raw argument and not cooked, returns
195 * 1 if X is a signaling NaN.
196 */
197#define _FP_ISSIGNAN(fs, wc, X) \
198({ \
199 int __ret = 0; \
200 if (X##_e == _FP_EXPMAX_##fs) \
201 { \
202 if (!_FP_FRAC_ZEROP_##wc(X) \
203 && !(_FP_FRAC_HIGH_RAW_##fs(X) & _FP_QNANBIT_##fs)) \
204 __ret = 1; \
205 } \
206 __ret; \
207})
208
209
210
211
212
213/*
214 * Main addition routine. The input values should be cooked.
215 */
216
217#define _FP_ADD_INTERNAL(fs, wc, R, X, Y, OP) \
218do { \
219 switch (_FP_CLS_COMBINE(X##_c, Y##_c)) \
220 { \
221 case _FP_CLS_COMBINE(FP_CLS_NORMAL,FP_CLS_NORMAL): \
222 { \
223 /* shift the smaller number so that its exponent matches the larger */ \
224 _FP_I_TYPE diff = X##_e - Y##_e; \
225 \
226 if (diff < 0) \
227 { \
228 diff = -diff; \
229 if (diff <= _FP_WFRACBITS_##fs) \
230 _FP_FRAC_SRS_##wc(X, diff, _FP_WFRACBITS_##fs); \
231 else if (!_FP_FRAC_ZEROP_##wc(X)) \
232 _FP_FRAC_SET_##wc(X, _FP_MINFRAC_##wc); \
233 R##_e = Y##_e; \
234 } \
235 else \
236 { \
237 if (diff > 0) \
238 { \
239 if (diff <= _FP_WFRACBITS_##fs) \
240 _FP_FRAC_SRS_##wc(Y, diff, _FP_WFRACBITS_##fs); \
241 else if (!_FP_FRAC_ZEROP_##wc(Y)) \
242 _FP_FRAC_SET_##wc(Y, _FP_MINFRAC_##wc); \
243 } \
244 R##_e = X##_e; \
245 } \
246 \
247 R##_c = FP_CLS_NORMAL; \
248 \
249 if (X##_s == Y##_s) \
250 { \
251 R##_s = X##_s; \
252 _FP_FRAC_ADD_##wc(R, X, Y); \
253 if (_FP_FRAC_OVERP_##wc(fs, R)) \
254 { \
255 _FP_FRAC_SRS_##wc(R, 1, _FP_WFRACBITS_##fs); \
256 R##_e++; \
257 } \
258 } \
259 else \
260 { \
261 R##_s = X##_s; \
262 _FP_FRAC_SUB_##wc(R, X, Y); \
263 if (_FP_FRAC_ZEROP_##wc(R)) \
264 { \
265 /* return an exact zero */ \
266 if (FP_ROUNDMODE == FP_RND_MINF) \
267 R##_s |= Y##_s; \
268 else \
269 R##_s &= Y##_s; \
270 R##_c = FP_CLS_ZERO; \
271 } \
272 else \
273 { \
274 if (_FP_FRAC_NEGP_##wc(R)) \
275 { \
276 _FP_FRAC_SUB_##wc(R, Y, X); \
277 R##_s = Y##_s; \
278 } \
279 \
280 /* renormalize after subtraction */ \
281 _FP_FRAC_CLZ_##wc(diff, R); \
282 diff -= _FP_WFRACXBITS_##fs; \
283 if (diff) \
284 { \
285 R##_e -= diff; \
286 _FP_FRAC_SLL_##wc(R, diff); \
287 } \
288 } \
289 } \
290 break; \
291 } \
292 \
293 case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_NAN): \
294 _FP_CHOOSENAN(fs, wc, R, X, Y, OP); \
295 break; \
296 \
297 case _FP_CLS_COMBINE(FP_CLS_NORMAL,FP_CLS_ZERO): \
298 R##_e = X##_e; \
299 case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_NORMAL): \
300 case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_INF): \
301 case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_ZERO): \
302 _FP_FRAC_COPY_##wc(R, X); \
303 R##_s = X##_s; \
304 R##_c = X##_c; \
305 break; \
306 \
307 case _FP_CLS_COMBINE(FP_CLS_ZERO,FP_CLS_NORMAL): \
308 R##_e = Y##_e; \
309 case _FP_CLS_COMBINE(FP_CLS_NORMAL,FP_CLS_NAN): \
310 case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_NAN): \
311 case _FP_CLS_COMBINE(FP_CLS_ZERO,FP_CLS_NAN): \
312 _FP_FRAC_COPY_##wc(R, Y); \
313 R##_s = Y##_s; \
314 R##_c = Y##_c; \
315 break; \
316 \
317 case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_INF): \
318 if (X##_s != Y##_s) \
319 { \
320 /* +INF + -INF => NAN */ \
321 _FP_FRAC_SET_##wc(R, _FP_NANFRAC_##fs); \
322 R##_s = _FP_NANSIGN_##fs; \
323 R##_c = FP_CLS_NAN; \
324 FP_SET_EXCEPTION(FP_EX_INVALID); \
325 break; \
326 } \
327 /* FALLTHRU */ \
328 \
329 case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_NORMAL): \
330 case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_ZERO): \
331 R##_s = X##_s; \
332 R##_c = FP_CLS_INF; \
333 break; \
334 \
335 case _FP_CLS_COMBINE(FP_CLS_NORMAL,FP_CLS_INF): \
336 case _FP_CLS_COMBINE(FP_CLS_ZERO,FP_CLS_INF): \
337 R##_s = Y##_s; \
338 R##_c = FP_CLS_INF; \
339 break; \
340 \
341 case _FP_CLS_COMBINE(FP_CLS_ZERO,FP_CLS_ZERO): \
342 /* make sure the sign is correct */ \
343 if (FP_ROUNDMODE == FP_RND_MINF) \
344 R##_s = X##_s | Y##_s; \
345 else \
346 R##_s = X##_s & Y##_s; \
347 R##_c = FP_CLS_ZERO; \
348 break; \
349 \
350 default: \
351 abort(); \
352 } \
353} while (0)
354
355#define _FP_ADD(fs, wc, R, X, Y) _FP_ADD_INTERNAL(fs, wc, R, X, Y, '+')
356#define _FP_SUB(fs, wc, R, X, Y) \
357 do { \
358 if (Y##_c != FP_CLS_NAN) Y##_s ^= 1; \
359 _FP_ADD_INTERNAL(fs, wc, R, X, Y, '-'); \
360 } while (0)
361
362
363/*
364 * Main negation routine. FIXME -- when we care about setting exception
365 * bits reliably, this will not do. We should examine all of the fp classes.
366 */
367
368#define _FP_NEG(fs, wc, R, X) \
369 do { \
370 _FP_FRAC_COPY_##wc(R, X); \
371 R##_c = X##_c; \
372 R##_e = X##_e; \
373 R##_s = 1 ^ X##_s; \
374 } while (0)
375
376
377/*
378 * Main multiplication routine. The input values should be cooked.
379 */
380
381#define _FP_MUL(fs, wc, R, X, Y) \
382do { \
383 R##_s = X##_s ^ Y##_s; \
384 switch (_FP_CLS_COMBINE(X##_c, Y##_c)) \
385 { \
386 case _FP_CLS_COMBINE(FP_CLS_NORMAL,FP_CLS_NORMAL): \
387 R##_c = FP_CLS_NORMAL; \
388 R##_e = X##_e + Y##_e + 1; \
389 \
390 _FP_MUL_MEAT_##fs(R,X,Y); \
391 \
392 if (_FP_FRAC_OVERP_##wc(fs, R)) \
393 _FP_FRAC_SRS_##wc(R, 1, _FP_WFRACBITS_##fs); \
394 else \
395 R##_e--; \
396 break; \
397 \
398 case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_NAN): \
399 _FP_CHOOSENAN(fs, wc, R, X, Y, '*'); \
400 break; \
401 \
402 case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_NORMAL): \
403 case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_INF): \
404 case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_ZERO): \
405 R##_s = X##_s; \
406 \
407 case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_INF): \
408 case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_NORMAL): \
409 case _FP_CLS_COMBINE(FP_CLS_ZERO,FP_CLS_NORMAL): \
410 case _FP_CLS_COMBINE(FP_CLS_ZERO,FP_CLS_ZERO): \
411 _FP_FRAC_COPY_##wc(R, X); \
412 R##_c = X##_c; \
413 break; \
414 \
415 case _FP_CLS_COMBINE(FP_CLS_NORMAL,FP_CLS_NAN): \
416 case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_NAN): \
417 case _FP_CLS_COMBINE(FP_CLS_ZERO,FP_CLS_NAN): \
418 R##_s = Y##_s; \
419 \
420 case _FP_CLS_COMBINE(FP_CLS_NORMAL,FP_CLS_INF): \
421 case _FP_CLS_COMBINE(FP_CLS_NORMAL,FP_CLS_ZERO): \
422 _FP_FRAC_COPY_##wc(R, Y); \
423 R##_c = Y##_c; \
424 break; \
425 \
426 case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_ZERO): \
427 case _FP_CLS_COMBINE(FP_CLS_ZERO,FP_CLS_INF): \
428 R##_s = _FP_NANSIGN_##fs; \
429 R##_c = FP_CLS_NAN; \
430 _FP_FRAC_SET_##wc(R, _FP_NANFRAC_##fs); \
431 FP_SET_EXCEPTION(FP_EX_INVALID); \
432 break; \
433 \
434 default: \
435 abort(); \
436 } \
437} while (0)
438
439
440/*
441 * Main division routine. The input values should be cooked.
442 */
443
444#define _FP_DIV(fs, wc, R, X, Y) \
445do { \
446 R##_s = X##_s ^ Y##_s; \
447 switch (_FP_CLS_COMBINE(X##_c, Y##_c)) \
448 { \
449 case _FP_CLS_COMBINE(FP_CLS_NORMAL,FP_CLS_NORMAL): \
450 R##_c = FP_CLS_NORMAL; \
451 R##_e = X##_e - Y##_e; \
452 \
453 _FP_DIV_MEAT_##fs(R,X,Y); \
454 break; \
455 \
456 case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_NAN): \
457 _FP_CHOOSENAN(fs, wc, R, X, Y, '/'); \
458 break; \
459 \
460 case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_NORMAL): \
461 case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_INF): \
462 case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_ZERO): \
463 R##_s = X##_s; \
464 _FP_FRAC_COPY_##wc(R, X); \
465 R##_c = X##_c; \
466 break; \
467 \
468 case _FP_CLS_COMBINE(FP_CLS_NORMAL,FP_CLS_NAN): \
469 case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_NAN): \
470 case _FP_CLS_COMBINE(FP_CLS_ZERO,FP_CLS_NAN): \
471 R##_s = Y##_s; \
472 _FP_FRAC_COPY_##wc(R, Y); \
473 R##_c = Y##_c; \
474 break; \
475 \
476 case _FP_CLS_COMBINE(FP_CLS_NORMAL,FP_CLS_INF): \
477 case _FP_CLS_COMBINE(FP_CLS_ZERO,FP_CLS_INF): \
478 case _FP_CLS_COMBINE(FP_CLS_ZERO,FP_CLS_NORMAL): \
479 R##_c = FP_CLS_ZERO; \
480 break; \
481 \
482 case _FP_CLS_COMBINE(FP_CLS_NORMAL,FP_CLS_ZERO): \
483 FP_SET_EXCEPTION(FP_EX_DIVZERO); \
484 case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_ZERO): \
485 case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_NORMAL): \
486 R##_c = FP_CLS_INF; \
487 break; \
488 \
489 case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_INF): \
490 case _FP_CLS_COMBINE(FP_CLS_ZERO,FP_CLS_ZERO): \
491 R##_s = _FP_NANSIGN_##fs; \
492 R##_c = FP_CLS_NAN; \
493 _FP_FRAC_SET_##wc(R, _FP_NANFRAC_##fs); \
494 FP_SET_EXCEPTION(FP_EX_INVALID); \
495 break; \
496 \
497 default: \
498 abort(); \
499 } \
500} while (0)
501
502
503/*
504 * Main differential comparison routine. The inputs should be raw not
505 * cooked. The return is -1,0,1 for normal values, 2 otherwise.
506 */
507
508#define _FP_CMP(fs, wc, ret, X, Y, un) \
509 do { \
510 /* NANs are unordered */ \
511 if ((X##_e == _FP_EXPMAX_##fs && !_FP_FRAC_ZEROP_##wc(X)) \
512 || (Y##_e == _FP_EXPMAX_##fs && !_FP_FRAC_ZEROP_##wc(Y))) \
513 { \
514 ret = un; \
515 } \
516 else \
517 { \
518 int __is_zero_x; \
519 int __is_zero_y; \
520 \
521 __is_zero_x = (!X##_e && _FP_FRAC_ZEROP_##wc(X)) ? 1 : 0; \
522 __is_zero_y = (!Y##_e && _FP_FRAC_ZEROP_##wc(Y)) ? 1 : 0; \
523 \
524 if (__is_zero_x && __is_zero_y) \
525 ret = 0; \
526 else if (__is_zero_x) \
527 ret = Y##_s ? 1 : -1; \
528 else if (__is_zero_y) \
529 ret = X##_s ? -1 : 1; \
530 else if (X##_s != Y##_s) \
531 ret = X##_s ? -1 : 1; \
532 else if (X##_e > Y##_e) \
533 ret = X##_s ? -1 : 1; \
534 else if (X##_e < Y##_e) \
535 ret = X##_s ? 1 : -1; \
536 else if (_FP_FRAC_GT_##wc(X, Y)) \
537 ret = X##_s ? -1 : 1; \
538 else if (_FP_FRAC_GT_##wc(Y, X)) \
539 ret = X##_s ? 1 : -1; \
540 else \
541 ret = 0; \
542 } \
543 } while (0)
544
545
546/* Simplification for strict equality. */
547
548#define _FP_CMP_EQ(fs, wc, ret, X, Y) \
549 do { \
550 /* NANs are unordered */ \
551 if ((X##_e == _FP_EXPMAX_##fs && !_FP_FRAC_ZEROP_##wc(X)) \
552 || (Y##_e == _FP_EXPMAX_##fs && !_FP_FRAC_ZEROP_##wc(Y))) \
553 { \
554 ret = 1; \
555 } \
556 else \
557 { \
558 ret = !(X##_e == Y##_e \
559 && _FP_FRAC_EQ_##wc(X, Y) \
560 && (X##_s == Y##_s || !X##_e && _FP_FRAC_ZEROP_##wc(X))); \
561 } \
562 } while (0)
563
564/*
565 * Main square root routine. The input value should be cooked.
566 */
567
568#define _FP_SQRT(fs, wc, R, X) \
569do { \
570 _FP_FRAC_DECL_##wc(T); _FP_FRAC_DECL_##wc(S); \
571 _FP_W_TYPE q; \
572 switch (X##_c) \
573 { \
574 case FP_CLS_NAN: \
575 _FP_FRAC_COPY_##wc(R, X); \
576 R##_s = X##_s; \
577 R##_c = FP_CLS_NAN; \
578 break; \
579 case FP_CLS_INF: \
580 if (X##_s) \
581 { \
582 R##_s = _FP_NANSIGN_##fs; \
583 R##_c = FP_CLS_NAN; /* NAN */ \
584 _FP_FRAC_SET_##wc(R, _FP_NANFRAC_##fs); \
585 FP_SET_EXCEPTION(FP_EX_INVALID); \
586 } \
587 else \
588 { \
589 R##_s = 0; \
590 R##_c = FP_CLS_INF; /* sqrt(+inf) = +inf */ \
591 } \
592 break; \
593 case FP_CLS_ZERO: \
594 R##_s = X##_s; \
595 R##_c = FP_CLS_ZERO; /* sqrt(+-0) = +-0 */ \
596 break; \
597 case FP_CLS_NORMAL: \
598 R##_s = 0; \
599 if (X##_s) \
600 { \
601 R##_c = FP_CLS_NAN; /* sNAN */ \
602 R##_s = _FP_NANSIGN_##fs; \
603 _FP_FRAC_SET_##wc(R, _FP_NANFRAC_##fs); \
604 FP_SET_EXCEPTION(FP_EX_INVALID); \
605 break; \
606 } \
607 R##_c = FP_CLS_NORMAL; \
608 if (X##_e & 1) \
609 _FP_FRAC_SLL_##wc(X, 1); \
610 R##_e = X##_e >> 1; \
611 _FP_FRAC_SET_##wc(S, _FP_ZEROFRAC_##wc); \
612 _FP_FRAC_SET_##wc(R, _FP_ZEROFRAC_##wc); \
613 q = _FP_OVERFLOW_##fs >> 1; \
614 _FP_SQRT_MEAT_##wc(R, S, T, X, q); \
615 } \
616 } while (0)
617
618/*
619 * Convert from FP to integer
620 */
621
622/* RSIGNED can have following values:
623 * 0: the number is required to be 0..(2^rsize)-1, if not, NV is set plus
624 * the result is either 0 or (2^rsize)-1 depending on the sign in such case.
625 * 1: the number is required to be -(2^(rsize-1))..(2^(rsize-1))-1, if not, NV is
626 * set plus the result is either -(2^(rsize-1)) or (2^(rsize-1))-1 depending
627 * on the sign in such case.
628 * 2: the number is required to be -(2^(rsize-1))..(2^(rsize-1))-1, if not, NV is
629 * set plus the result is truncated to fit into destination.
630 * -1: the number is required to be -(2^(rsize-1))..(2^rsize)-1, if not, NV is
631 * set plus the result is either -(2^(rsize-1)) or (2^(rsize-1))-1 depending
632 * on the sign in such case.
633 */
634#define _FP_TO_INT(fs, wc, r, X, rsize, rsigned) \
635 do { \
636 switch (X##_c) \
637 { \
638 case FP_CLS_NORMAL: \
639 if (X##_e < 0) \
640 { \
641 FP_SET_EXCEPTION(FP_EX_INEXACT); \
642 case FP_CLS_ZERO: \
643 r = 0; \
644 } \
645 else if (X##_e >= rsize - (rsigned > 0 || X##_s) \
646 || (!rsigned && X##_s)) \
647 { /* overflow */ \
648 case FP_CLS_NAN: \
649 case FP_CLS_INF: \
650 if (rsigned == 2) \
651 { \
652 if (X##_c != FP_CLS_NORMAL \
653 || X##_e >= rsize - 1 + _FP_WFRACBITS_##fs) \
654 r = 0; \
655 else \
656 { \
657 _FP_FRAC_SLL_##wc(X, (X##_e - _FP_WFRACBITS_##fs + 1)); \
658 _FP_FRAC_ASSEMBLE_##wc(r, X, rsize); \
659 } \
660 } \
661 else if (rsigned) \
662 { \
663 r = 1; \
664 r <<= rsize - 1; \
665 r -= 1 - X##_s; \
666 } \
667 else \
668 { \
669 r = 0; \
670 if (X##_s) \
671 r = ~r; \
672 } \
673 FP_SET_EXCEPTION(FP_EX_INVALID); \
674 } \
675 else \
676 { \
677 if (_FP_W_TYPE_SIZE*wc < rsize) \
678 { \
679 _FP_FRAC_ASSEMBLE_##wc(r, X, rsize); \
680 r <<= X##_e - _FP_WFRACBITS_##fs; \
681 } \
682 else \
683 { \
684 if (X##_e >= _FP_WFRACBITS_##fs) \
685 _FP_FRAC_SLL_##wc(X, (X##_e - _FP_WFRACBITS_##fs + 1)); \
686 else if (X##_e < _FP_WFRACBITS_##fs - 1) \
687 { \
688 _FP_FRAC_SRS_##wc(X, (_FP_WFRACBITS_##fs - X##_e - 2), \
689 _FP_WFRACBITS_##fs); \
690 if (_FP_FRAC_LOW_##wc(X) & 1) \
691 FP_SET_EXCEPTION(FP_EX_INEXACT); \
692 _FP_FRAC_SRL_##wc(X, 1); \
693 } \
694 _FP_FRAC_ASSEMBLE_##wc(r, X, rsize); \
695 } \
696 if (rsigned && X##_s) \
697 r = -r; \
698 } \
699 break; \
700 } \
701 } while (0)
702
703#define _FP_TO_INT_ROUND(fs, wc, r, X, rsize, rsigned) \
704 do { \
705 r = 0; \
706 switch (X##_c) \
707 { \
708 case FP_CLS_NORMAL: \
709 if (X##_e >= _FP_FRACBITS_##fs - 1) \
710 { \
711 if (X##_e < rsize - 1 + _FP_WFRACBITS_##fs) \
712 { \
713 if (X##_e >= _FP_WFRACBITS_##fs - 1) \
714 { \
715 _FP_FRAC_ASSEMBLE_##wc(r, X, rsize); \
716 r <<= X##_e - _FP_WFRACBITS_##fs + 1; \
717 } \
718 else \
719 { \
720 _FP_FRAC_SRL_##wc(X, _FP_WORKBITS - X##_e \
721 + _FP_FRACBITS_##fs - 1); \
722 _FP_FRAC_ASSEMBLE_##wc(r, X, rsize); \
723 } \
724 } \
725 } \
726 else \
727 { \
728 if (X##_e <= -_FP_WORKBITS - 1) \
729 _FP_FRAC_SET_##wc(X, _FP_MINFRAC_##wc); \
730 else \
731 _FP_FRAC_SRS_##wc(X, _FP_FRACBITS_##fs - 1 - X##_e, \
732 _FP_WFRACBITS_##fs); \
733 _FP_ROUND(wc, X); \
734 _FP_FRAC_SRL_##wc(X, _FP_WORKBITS); \
735 _FP_FRAC_ASSEMBLE_##wc(r, X, rsize); \
736 } \
737 if (rsigned && X##_s) \
738 r = -r; \
739 if (X##_e >= rsize - (rsigned > 0 || X##_s) \
740 || (!rsigned && X##_s)) \
741 { /* overflow */ \
742 case FP_CLS_NAN: \
743 case FP_CLS_INF: \
744 if (!rsigned) \
745 { \
746 r = 0; \
747 if (X##_s) \
748 r = ~r; \
749 } \
750 else if (rsigned != 2) \
751 { \
752 r = 1; \
753 r <<= rsize - 1; \
754 r -= 1 - X##_s; \
755 } \
756 FP_SET_EXCEPTION(FP_EX_INVALID); \
757 } \
758 break; \
759 case FP_CLS_ZERO: \
760 break; \
761 } \
762 } while (0)
763
764#define _FP_FROM_INT(fs, wc, X, r, rsize, rtype) \
765 do { \
766 if (r) \
767 { \
768 unsigned rtype ur_; \
769 X##_c = FP_CLS_NORMAL; \
770 \
771 if ((X##_s = (r < 0))) \
772 ur_ = (unsigned rtype) -r; \
773 else \
774 ur_ = (unsigned rtype) r; \
775 if (rsize <= _FP_W_TYPE_SIZE) \
776 __FP_CLZ(X##_e, ur_); \
777 else \
778 __FP_CLZ_2(X##_e, (_FP_W_TYPE)(ur_ >> _FP_W_TYPE_SIZE), \
779 (_FP_W_TYPE)ur_); \
780 if (rsize < _FP_W_TYPE_SIZE) \
781 X##_e -= (_FP_W_TYPE_SIZE - rsize); \
782 X##_e = rsize - X##_e - 1; \
783 \
784 if (_FP_FRACBITS_##fs < rsize && _FP_WFRACBITS_##fs < X##_e) \
785 __FP_FRAC_SRS_1(ur_, (X##_e - _FP_WFRACBITS_##fs + 1), rsize);\
786 _FP_FRAC_DISASSEMBLE_##wc(X, ur_, rsize); \
787 if ((_FP_WFRACBITS_##fs - X##_e - 1) > 0) \
788 _FP_FRAC_SLL_##wc(X, (_FP_WFRACBITS_##fs - X##_e - 1)); \
789 } \
790 else \
791 { \
792 X##_c = FP_CLS_ZERO, X##_s = 0; \
793 } \
794 } while (0)
795
796
797#define FP_CONV(dfs,sfs,dwc,swc,D,S) \
798 do { \
799 _FP_FRAC_CONV_##dwc##_##swc(dfs, sfs, D, S); \
800 D##_e = S##_e; \
801 D##_c = S##_c; \
802 D##_s = S##_s; \
803 } while (0)
804
805/*
806 * Helper primitives.
807 */
808
809/* Count leading zeros in a word. */
810
811#ifndef __FP_CLZ
812#if _FP_W_TYPE_SIZE < 64
813/* this is just to shut the compiler up about shifts > word length -- PMM 02/1998 */
814#define __FP_CLZ(r, x) \
815 do { \
816 _FP_W_TYPE _t = (x); \
817 r = _FP_W_TYPE_SIZE - 1; \
818 if (_t > 0xffff) r -= 16; \
819 if (_t > 0xffff) _t >>= 16; \
820 if (_t > 0xff) r -= 8; \
821 if (_t > 0xff) _t >>= 8; \
822 if (_t & 0xf0) r -= 4; \
823 if (_t & 0xf0) _t >>= 4; \
824 if (_t & 0xc) r -= 2; \
825 if (_t & 0xc) _t >>= 2; \
826 if (_t & 0x2) r -= 1; \
827 } while (0)
828#else /* not _FP_W_TYPE_SIZE < 64 */
829#define __FP_CLZ(r, x) \
830 do { \
831 _FP_W_TYPE _t = (x); \
832 r = _FP_W_TYPE_SIZE - 1; \
833 if (_t > 0xffffffff) r -= 32; \
834 if (_t > 0xffffffff) _t >>= 32; \
835 if (_t > 0xffff) r -= 16; \
836 if (_t > 0xffff) _t >>= 16; \
837 if (_t > 0xff) r -= 8; \
838 if (_t > 0xff) _t >>= 8; \
839 if (_t & 0xf0) r -= 4; \
840 if (_t & 0xf0) _t >>= 4; \
841 if (_t & 0xc) r -= 2; \
842 if (_t & 0xc) _t >>= 2; \
843 if (_t & 0x2) r -= 1; \
844 } while (0)
845#endif /* not _FP_W_TYPE_SIZE < 64 */
846#endif /* ndef __FP_CLZ */
847
848#define _FP_DIV_HELP_imm(q, r, n, d) \
849 do { \
850 q = n / d, r = n % d; \
851 } while (0)
852
853#endif /* __MATH_EMU_OP_COMMON_H__ */
diff --git a/include/math-emu/quad.h b/include/math-emu/quad.h
new file mode 100644
index 000000000000..616113626d09
--- /dev/null
+++ b/include/math-emu/quad.h
@@ -0,0 +1,208 @@
1/* Software floating-point emulation.
2 Definitions for IEEE Quad Precision.
3 Copyright (C) 1997,1998,1999 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 Library General Public License as
12 published by the Free Software Foundation; either version 2 of the
13 License, or (at your option) any later version.
14
15 The GNU C Library is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 Library General Public License for more details.
19
20 You should have received a copy of the GNU Library General Public
21 License along with the GNU C Library; see the file COPYING.LIB. If
22 not, write to the Free Software Foundation, Inc.,
23 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
24
25#ifndef __MATH_EMU_QUAD_H__
26#define __MATH_EMU_QUAD_H__
27
28#if _FP_W_TYPE_SIZE < 32
29#error "Here's a nickel, kid. Go buy yourself a real computer."
30#endif
31
32#if _FP_W_TYPE_SIZE < 64
33#define _FP_FRACTBITS_Q (4*_FP_W_TYPE_SIZE)
34#else
35#define _FP_FRACTBITS_Q (2*_FP_W_TYPE_SIZE)
36#endif
37
38#define _FP_FRACBITS_Q 113
39#define _FP_FRACXBITS_Q (_FP_FRACTBITS_Q - _FP_FRACBITS_Q)
40#define _FP_WFRACBITS_Q (_FP_WORKBITS + _FP_FRACBITS_Q)
41#define _FP_WFRACXBITS_Q (_FP_FRACTBITS_Q - _FP_WFRACBITS_Q)
42#define _FP_EXPBITS_Q 15
43#define _FP_EXPBIAS_Q 16383
44#define _FP_EXPMAX_Q 32767
45
46#define _FP_QNANBIT_Q \
47 ((_FP_W_TYPE)1 << (_FP_FRACBITS_Q-2) % _FP_W_TYPE_SIZE)
48#define _FP_IMPLBIT_Q \
49 ((_FP_W_TYPE)1 << (_FP_FRACBITS_Q-1) % _FP_W_TYPE_SIZE)
50#define _FP_OVERFLOW_Q \
51 ((_FP_W_TYPE)1 << (_FP_WFRACBITS_Q % _FP_W_TYPE_SIZE))
52
53#if _FP_W_TYPE_SIZE < 64
54
55union _FP_UNION_Q
56{
57 long double flt;
58 struct
59 {
60#if __BYTE_ORDER == __BIG_ENDIAN
61 unsigned sign : 1;
62 unsigned exp : _FP_EXPBITS_Q;
63 unsigned long frac3 : _FP_FRACBITS_Q - (_FP_IMPLBIT_Q != 0)-(_FP_W_TYPE_SIZE * 3);
64 unsigned long frac2 : _FP_W_TYPE_SIZE;
65 unsigned long frac1 : _FP_W_TYPE_SIZE;
66 unsigned long frac0 : _FP_W_TYPE_SIZE;
67#else
68 unsigned long frac0 : _FP_W_TYPE_SIZE;
69 unsigned long frac1 : _FP_W_TYPE_SIZE;
70 unsigned long frac2 : _FP_W_TYPE_SIZE;
71 unsigned long frac3 : _FP_FRACBITS_Q - (_FP_IMPLBIT_Q != 0)-(_FP_W_TYPE_SIZE * 3);
72 unsigned exp : _FP_EXPBITS_Q;
73 unsigned sign : 1;
74#endif /* not bigendian */
75 } bits __attribute__((packed));
76};
77
78
79#define FP_DECL_Q(X) _FP_DECL(4,X)
80#define FP_UNPACK_RAW_Q(X,val) _FP_UNPACK_RAW_4(Q,X,val)
81#define FP_UNPACK_RAW_QP(X,val) _FP_UNPACK_RAW_4_P(Q,X,val)
82#define FP_PACK_RAW_Q(val,X) _FP_PACK_RAW_4(Q,val,X)
83#define FP_PACK_RAW_QP(val,X) \
84 do { \
85 if (!FP_INHIBIT_RESULTS) \
86 _FP_PACK_RAW_4_P(Q,val,X); \
87 } while (0)
88
89#define FP_UNPACK_Q(X,val) \
90 do { \
91 _FP_UNPACK_RAW_4(Q,X,val); \
92 _FP_UNPACK_CANONICAL(Q,4,X); \
93 } while (0)
94
95#define FP_UNPACK_QP(X,val) \
96 do { \
97 _FP_UNPACK_RAW_4_P(Q,X,val); \
98 _FP_UNPACK_CANONICAL(Q,4,X); \
99 } while (0)
100
101#define FP_PACK_Q(val,X) \
102 do { \
103 _FP_PACK_CANONICAL(Q,4,X); \
104 _FP_PACK_RAW_4(Q,val,X); \
105 } while (0)
106
107#define FP_PACK_QP(val,X) \
108 do { \
109 _FP_PACK_CANONICAL(Q,4,X); \
110 if (!FP_INHIBIT_RESULTS) \
111 _FP_PACK_RAW_4_P(Q,val,X); \
112 } while (0)
113
114#define FP_ISSIGNAN_Q(X) _FP_ISSIGNAN(Q,4,X)
115#define FP_NEG_Q(R,X) _FP_NEG(Q,4,R,X)
116#define FP_ADD_Q(R,X,Y) _FP_ADD(Q,4,R,X,Y)
117#define FP_SUB_Q(R,X,Y) _FP_SUB(Q,4,R,X,Y)
118#define FP_MUL_Q(R,X,Y) _FP_MUL(Q,4,R,X,Y)
119#define FP_DIV_Q(R,X,Y) _FP_DIV(Q,4,R,X,Y)
120#define FP_SQRT_Q(R,X) _FP_SQRT(Q,4,R,X)
121#define _FP_SQRT_MEAT_Q(R,S,T,X,Q) _FP_SQRT_MEAT_4(R,S,T,X,Q)
122
123#define FP_CMP_Q(r,X,Y,un) _FP_CMP(Q,4,r,X,Y,un)
124#define FP_CMP_EQ_Q(r,X,Y) _FP_CMP_EQ(Q,4,r,X,Y)
125
126#define FP_TO_INT_Q(r,X,rsz,rsg) _FP_TO_INT(Q,4,r,X,rsz,rsg)
127#define FP_TO_INT_ROUND_Q(r,X,rsz,rsg) _FP_TO_INT_ROUND(Q,4,r,X,rsz,rsg)
128#define FP_FROM_INT_Q(X,r,rs,rt) _FP_FROM_INT(Q,4,X,r,rs,rt)
129
130#define _FP_FRAC_HIGH_Q(X) _FP_FRAC_HIGH_4(X)
131#define _FP_FRAC_HIGH_RAW_Q(X) _FP_FRAC_HIGH_4(X)
132
133#else /* not _FP_W_TYPE_SIZE < 64 */
134union _FP_UNION_Q
135{
136 long double flt /* __attribute__((mode(TF))) */ ;
137 struct {
138#if __BYTE_ORDER == __BIG_ENDIAN
139 unsigned sign : 1;
140 unsigned exp : _FP_EXPBITS_Q;
141 unsigned long frac1 : _FP_FRACBITS_Q-(_FP_IMPLBIT_Q != 0)-_FP_W_TYPE_SIZE;
142 unsigned long frac0 : _FP_W_TYPE_SIZE;
143#else
144 unsigned long frac0 : _FP_W_TYPE_SIZE;
145 unsigned long frac1 : _FP_FRACBITS_Q-(_FP_IMPLBIT_Q != 0)-_FP_W_TYPE_SIZE;
146 unsigned exp : _FP_EXPBITS_Q;
147 unsigned sign : 1;
148#endif
149 } bits;
150};
151
152#define FP_DECL_Q(X) _FP_DECL(2,X)
153#define FP_UNPACK_RAW_Q(X,val) _FP_UNPACK_RAW_2(Q,X,val)
154#define FP_UNPACK_RAW_QP(X,val) _FP_UNPACK_RAW_2_P(Q,X,val)
155#define FP_PACK_RAW_Q(val,X) _FP_PACK_RAW_2(Q,val,X)
156#define FP_PACK_RAW_QP(val,X) \
157 do { \
158 if (!FP_INHIBIT_RESULTS) \
159 _FP_PACK_RAW_2_P(Q,val,X); \
160 } while (0)
161
162#define FP_UNPACK_Q(X,val) \
163 do { \
164 _FP_UNPACK_RAW_2(Q,X,val); \
165 _FP_UNPACK_CANONICAL(Q,2,X); \
166 } while (0)
167
168#define FP_UNPACK_QP(X,val) \
169 do { \
170 _FP_UNPACK_RAW_2_P(Q,X,val); \
171 _FP_UNPACK_CANONICAL(Q,2,X); \
172 } while (0)
173
174#define FP_PACK_Q(val,X) \
175 do { \
176 _FP_PACK_CANONICAL(Q,2,X); \
177 _FP_PACK_RAW_2(Q,val,X); \
178 } while (0)
179
180#define FP_PACK_QP(val,X) \
181 do { \
182 _FP_PACK_CANONICAL(Q,2,X); \
183 if (!FP_INHIBIT_RESULTS) \
184 _FP_PACK_RAW_2_P(Q,val,X); \
185 } while (0)
186
187#define FP_ISSIGNAN_Q(X) _FP_ISSIGNAN(Q,2,X)
188#define FP_NEG_Q(R,X) _FP_NEG(Q,2,R,X)
189#define FP_ADD_Q(R,X,Y) _FP_ADD(Q,2,R,X,Y)
190#define FP_SUB_Q(R,X,Y) _FP_SUB(Q,2,R,X,Y)
191#define FP_MUL_Q(R,X,Y) _FP_MUL(Q,2,R,X,Y)
192#define FP_DIV_Q(R,X,Y) _FP_DIV(Q,2,R,X,Y)
193#define FP_SQRT_Q(R,X) _FP_SQRT(Q,2,R,X)
194#define _FP_SQRT_MEAT_Q(R,S,T,X,Q) _FP_SQRT_MEAT_2(R,S,T,X,Q)
195
196#define FP_CMP_Q(r,X,Y,un) _FP_CMP(Q,2,r,X,Y,un)
197#define FP_CMP_EQ_Q(r,X,Y) _FP_CMP_EQ(Q,2,r,X,Y)
198
199#define FP_TO_INT_Q(r,X,rsz,rsg) _FP_TO_INT(Q,2,r,X,rsz,rsg)
200#define FP_TO_INT_ROUND_Q(r,X,rsz,rsg) _FP_TO_INT_ROUND(Q,2,r,X,rsz,rsg)
201#define FP_FROM_INT_Q(X,r,rs,rt) _FP_FROM_INT(Q,2,X,r,rs,rt)
202
203#define _FP_FRAC_HIGH_Q(X) _FP_FRAC_HIGH_2(X)
204#define _FP_FRAC_HIGH_RAW_Q(X) _FP_FRAC_HIGH_2(X)
205
206#endif /* not _FP_W_TYPE_SIZE < 64 */
207
208#endif /* __MATH_EMU_QUAD_H__ */
diff --git a/include/math-emu/single.h b/include/math-emu/single.h
new file mode 100644
index 000000000000..87f90b0f9e5d
--- /dev/null
+++ b/include/math-emu/single.h
@@ -0,0 +1,116 @@
1/* Software floating-point emulation.
2 Definitions for IEEE Single Precision.
3 Copyright (C) 1997,1998,1999 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 Library General Public License as
12 published by the Free Software Foundation; either version 2 of the
13 License, or (at your option) any later version.
14
15 The GNU C Library is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 Library General Public License for more details.
19
20 You should have received a copy of the GNU Library General Public
21 License along with the GNU C Library; see the file COPYING.LIB. If
22 not, write to the Free Software Foundation, Inc.,
23 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
24
25#ifndef __MATH_EMU_SINGLE_H__
26#define __MATH_EMU_SINGLE_H__
27
28#if _FP_W_TYPE_SIZE < 32
29#error "Here's a nickel kid. Go buy yourself a real computer."
30#endif
31
32#define _FP_FRACBITS_S 24
33#define _FP_FRACXBITS_S (_FP_W_TYPE_SIZE - _FP_FRACBITS_S)
34#define _FP_WFRACBITS_S (_FP_WORKBITS + _FP_FRACBITS_S)
35#define _FP_WFRACXBITS_S (_FP_W_TYPE_SIZE - _FP_WFRACBITS_S)
36#define _FP_EXPBITS_S 8
37#define _FP_EXPBIAS_S 127
38#define _FP_EXPMAX_S 255
39#define _FP_QNANBIT_S ((_FP_W_TYPE)1 << (_FP_FRACBITS_S-2))
40#define _FP_IMPLBIT_S ((_FP_W_TYPE)1 << (_FP_FRACBITS_S-1))
41#define _FP_OVERFLOW_S ((_FP_W_TYPE)1 << (_FP_WFRACBITS_S))
42
43/* The implementation of _FP_MUL_MEAT_S and _FP_DIV_MEAT_S should be
44 chosen by the target machine. */
45
46union _FP_UNION_S
47{
48 float flt;
49 struct {
50#if __BYTE_ORDER == __BIG_ENDIAN
51 unsigned sign : 1;
52 unsigned exp : _FP_EXPBITS_S;
53 unsigned frac : _FP_FRACBITS_S - (_FP_IMPLBIT_S != 0);
54#else
55 unsigned frac : _FP_FRACBITS_S - (_FP_IMPLBIT_S != 0);
56 unsigned exp : _FP_EXPBITS_S;
57 unsigned sign : 1;
58#endif
59 } bits __attribute__((packed));
60};
61
62#define FP_DECL_S(X) _FP_DECL(1,X)
63#define FP_UNPACK_RAW_S(X,val) _FP_UNPACK_RAW_1(S,X,val)
64#define FP_UNPACK_RAW_SP(X,val) _FP_UNPACK_RAW_1_P(S,X,val)
65#define FP_PACK_RAW_S(val,X) _FP_PACK_RAW_1(S,val,X)
66#define FP_PACK_RAW_SP(val,X) \
67 do { \
68 if (!FP_INHIBIT_RESULTS) \
69 _FP_PACK_RAW_1_P(S,val,X); \
70 } while (0)
71
72#define FP_UNPACK_S(X,val) \
73 do { \
74 _FP_UNPACK_RAW_1(S,X,val); \
75 _FP_UNPACK_CANONICAL(S,1,X); \
76 } while (0)
77
78#define FP_UNPACK_SP(X,val) \
79 do { \
80 _FP_UNPACK_RAW_1_P(S,X,val); \
81 _FP_UNPACK_CANONICAL(S,1,X); \
82 } while (0)
83
84#define FP_PACK_S(val,X) \
85 do { \
86 _FP_PACK_CANONICAL(S,1,X); \
87 _FP_PACK_RAW_1(S,val,X); \
88 } while (0)
89
90#define FP_PACK_SP(val,X) \
91 do { \
92 _FP_PACK_CANONICAL(S,1,X); \
93 if (!FP_INHIBIT_RESULTS) \
94 _FP_PACK_RAW_1_P(S,val,X); \
95 } while (0)
96
97#define FP_ISSIGNAN_S(X) _FP_ISSIGNAN(S,1,X)
98#define FP_NEG_S(R,X) _FP_NEG(S,1,R,X)
99#define FP_ADD_S(R,X,Y) _FP_ADD(S,1,R,X,Y)
100#define FP_SUB_S(R,X,Y) _FP_SUB(S,1,R,X,Y)
101#define FP_MUL_S(R,X,Y) _FP_MUL(S,1,R,X,Y)
102#define FP_DIV_S(R,X,Y) _FP_DIV(S,1,R,X,Y)
103#define FP_SQRT_S(R,X) _FP_SQRT(S,1,R,X)
104#define _FP_SQRT_MEAT_S(R,S,T,X,Q) _FP_SQRT_MEAT_1(R,S,T,X,Q)
105
106#define FP_CMP_S(r,X,Y,un) _FP_CMP(S,1,r,X,Y,un)
107#define FP_CMP_EQ_S(r,X,Y) _FP_CMP_EQ(S,1,r,X,Y)
108
109#define FP_TO_INT_S(r,X,rsz,rsg) _FP_TO_INT(S,1,r,X,rsz,rsg)
110#define FP_TO_INT_ROUND_S(r,X,rsz,rsg) _FP_TO_INT_ROUND(S,1,r,X,rsz,rsg)
111#define FP_FROM_INT_S(X,r,rs,rt) _FP_FROM_INT(S,1,X,r,rs,rt)
112
113#define _FP_FRAC_HIGH_S(X) _FP_FRAC_HIGH_1(X)
114#define _FP_FRAC_HIGH_RAW_S(X) _FP_FRAC_HIGH_1(X)
115
116#endif /* __MATH_EMU_SINGLE_H__ */
diff --git a/include/math-emu/soft-fp.h b/include/math-emu/soft-fp.h
new file mode 100644
index 000000000000..d02eb64a865b
--- /dev/null
+++ b/include/math-emu/soft-fp.h
@@ -0,0 +1,181 @@
1/* Software floating-point emulation.
2 Copyright (C) 1997,1998,1999 Free Software Foundation, Inc.
3 This file is part of the GNU C Library.
4 Contributed by Richard Henderson (rth@cygnus.com),
5 Jakub Jelinek (jj@ultra.linux.cz),
6 David S. Miller (davem@redhat.com) and
7 Peter Maydell (pmaydell@chiark.greenend.org.uk).
8
9 The GNU C Library is free software; you can redistribute it and/or
10 modify it under the terms of the GNU Library General Public License as
11 published by the Free Software Foundation; either version 2 of the
12 License, or (at your option) any later version.
13
14 The GNU C Library is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 Library General Public License for more details.
18
19 You should have received a copy of the GNU Library General Public
20 License along with the GNU C Library; see the file COPYING.LIB. If
21 not, write to the Free Software Foundation, Inc.,
22 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
23
24#ifndef __MATH_EMU_SOFT_FP_H__
25#define __MATH_EMU_SOFT_FP_H__
26
27#include <asm/sfp-machine.h>
28
29/* Allow sfp-machine to have its own byte order definitions. */
30#ifndef __BYTE_ORDER
31#include <endian.h>
32#endif
33
34#define _FP_WORKBITS 3
35#define _FP_WORK_LSB ((_FP_W_TYPE)1 << 3)
36#define _FP_WORK_ROUND ((_FP_W_TYPE)1 << 2)
37#define _FP_WORK_GUARD ((_FP_W_TYPE)1 << 1)
38#define _FP_WORK_STICKY ((_FP_W_TYPE)1 << 0)
39
40#ifndef FP_RND_NEAREST
41# define FP_RND_NEAREST 0
42# define FP_RND_ZERO 1
43# define FP_RND_PINF 2
44# define FP_RND_MINF 3
45#ifndef FP_ROUNDMODE
46# define FP_ROUNDMODE FP_RND_NEAREST
47#endif
48#endif
49
50/* By default don't care about exceptions. */
51#ifndef FP_EX_INVALID
52#define FP_EX_INVALID 0
53#endif
54#ifndef FP_EX_OVERFLOW
55#define FP_EX_OVERFLOW 0
56#endif
57#ifndef FP_EX_UNDERFLOW
58#define FP_EX_UNDERFLOW
59#endif
60#ifndef FP_EX_DIVZERO
61#define FP_EX_DIVZERO 0
62#endif
63#ifndef FP_EX_INEXACT
64#define FP_EX_INEXACT 0
65#endif
66#ifndef FP_EX_DENORM
67#define FP_EX_DENORM 0
68#endif
69
70#ifdef _FP_DECL_EX
71#define FP_DECL_EX \
72 int _fex = 0; \
73 _FP_DECL_EX
74#else
75#define FP_DECL_EX int _fex = 0
76#endif
77
78#ifndef FP_INIT_ROUNDMODE
79#define FP_INIT_ROUNDMODE do {} while (0)
80#endif
81
82#ifndef FP_HANDLE_EXCEPTIONS
83#define FP_HANDLE_EXCEPTIONS do {} while (0)
84#endif
85
86/* By default we never flush denormal input operands to signed zero. */
87#ifndef FP_DENORM_ZERO
88#define FP_DENORM_ZERO 0
89#endif
90
91#ifndef FP_INHIBIT_RESULTS
92/* By default we write the results always.
93 * sfp-machine may override this and e.g.
94 * check if some exceptions are unmasked
95 * and inhibit it in such a case.
96 */
97#define FP_INHIBIT_RESULTS 0
98#endif
99
100#define FP_SET_EXCEPTION(ex) \
101 _fex |= (ex)
102
103#define FP_UNSET_EXCEPTION(ex) \
104 _fex &= ~(ex)
105
106#define FP_CLEAR_EXCEPTIONS \
107 _fex = 0
108
109#define _FP_ROUND_NEAREST(wc, X) \
110do { \
111 if ((_FP_FRAC_LOW_##wc(X) & 15) != _FP_WORK_ROUND) \
112 _FP_FRAC_ADDI_##wc(X, _FP_WORK_ROUND); \
113} while (0)
114
115#define _FP_ROUND_ZERO(wc, X) 0
116
117#define _FP_ROUND_PINF(wc, X) \
118do { \
119 if (!X##_s && (_FP_FRAC_LOW_##wc(X) & 7)) \
120 _FP_FRAC_ADDI_##wc(X, _FP_WORK_LSB); \
121} while (0)
122
123#define _FP_ROUND_MINF(wc, X) \
124do { \
125 if (X##_s && (_FP_FRAC_LOW_##wc(X) & 7)) \
126 _FP_FRAC_ADDI_##wc(X, _FP_WORK_LSB); \
127} while (0)
128
129#define _FP_ROUND(wc, X) \
130do { \
131 if (_FP_FRAC_LOW_##wc(X) & 7) \
132 FP_SET_EXCEPTION(FP_EX_INEXACT); \
133 switch (FP_ROUNDMODE) \
134 { \
135 case FP_RND_NEAREST: \
136 _FP_ROUND_NEAREST(wc,X); \
137 break; \
138 case FP_RND_ZERO: \
139 _FP_ROUND_ZERO(wc,X); \
140 break; \
141 case FP_RND_PINF: \
142 _FP_ROUND_PINF(wc,X); \
143 break; \
144 case FP_RND_MINF: \
145 _FP_ROUND_MINF(wc,X); \
146 break; \
147 } \
148} while (0)
149
150#define FP_CLS_NORMAL 0
151#define FP_CLS_ZERO 1
152#define FP_CLS_INF 2
153#define FP_CLS_NAN 3
154
155#define _FP_CLS_COMBINE(x,y) (((x) << 2) | (y))
156
157#include <math-emu/op-1.h>
158#include <math-emu/op-2.h>
159#include <math-emu/op-4.h>
160#include <math-emu/op-8.h>
161#include <math-emu/op-common.h>
162
163/* Sigh. Silly things longlong.h needs. */
164#define UWtype _FP_W_TYPE
165#define W_TYPE_SIZE _FP_W_TYPE_SIZE
166
167typedef int SItype __attribute__((mode(SI)));
168typedef int DItype __attribute__((mode(DI)));
169typedef unsigned int USItype __attribute__((mode(SI)));
170typedef unsigned int UDItype __attribute__((mode(DI)));
171#if _FP_W_TYPE_SIZE == 32
172typedef unsigned int UHWtype __attribute__((mode(HI)));
173#elif _FP_W_TYPE_SIZE == 64
174typedef USItype UHWtype;
175#endif
176
177#ifndef umul_ppmm
178#include <stdlib/longlong.h>
179#endif
180
181#endif /* __MATH_EMU_SOFT_FP_H__ */