Commit | Line | Data |
---|---|---|
1da177e4 LT |
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 | ||
53 | union _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 */ | |
240 | union _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__ */ |