|
|
1.1 root 1: /*
2: * UAE - The Un*x Amiga Emulator
3: *
4: * MC68881 emulation
5: *
6: * Conversion routines for hosts knowing floating point format.
7: *
8: * Copyright 1996 Herman ten Brugge
9: * Modified 2005 Peter Keunecke
10: */
11:
12: #ifndef FPP_H
13: #define FPP_H
14:
15: #include <softfloat.h>
16:
1.1.1.2 ! root 17: float_ctrl fp_ctrl;
1.1 root 18:
19: #define FPCR_ROUNDING_MODE 0x00000030
20: #define FPCR_ROUND_NEAR 0x00000000
21: #define FPCR_ROUND_ZERO 0x00000010
22: #define FPCR_ROUND_MINF 0x00000020
23: #define FPCR_ROUND_PINF 0x00000030
24:
25: #define FPCR_ROUNDING_PRECISION 0x000000c0
26: #define FPCR_PRECISION_SINGLE 0x00000040
27: #define FPCR_PRECISION_DOUBLE 0x00000080
28: #define FPCR_PRECISION_EXTENDED 0x00000000
29:
30: extern uae_u32 fpp_get_fpsr (void);
31:
32:
33: /* Functions for setting host/library modes and getting status */
1.1.1.2 ! root 34: STATIC_INLINE void init_fp_mode(void)
! 35: {
! 36: float_init(&fp_ctrl);
! 37: }
1.1 root 38: STATIC_INLINE void set_fp_mode(uae_u32 mode_control)
39: {
1.1.1.2 ! root 40: set_float_detect_tininess(float_tininess_before_rounding, &fp_ctrl);
1.1 root 41:
42: switch(mode_control & FPCR_ROUNDING_PRECISION) {
43: case FPCR_PRECISION_SINGLE: // single
1.1.1.2 ! root 44: set_float_rounding_precision(32, &fp_ctrl);
1.1 root 45: break;
46: case FPCR_PRECISION_DOUBLE: // double
1.1.1.2 ! root 47: set_float_rounding_precision(64, &fp_ctrl);
1.1 root 48: break;
49: case FPCR_PRECISION_EXTENDED: // extended
1.1.1.2 ! root 50: set_float_rounding_precision(80, &fp_ctrl);
1.1 root 51: break;
52: default: // double
1.1.1.2 ! root 53: set_float_rounding_precision(64, &fp_ctrl);
1.1 root 54: break;
55: }
56:
57: switch(mode_control & FPCR_ROUNDING_MODE) {
58: case FPCR_ROUND_NEAR: // to neareset
1.1.1.2 ! root 59: set_float_rounding_mode(float_round_nearest_even, &fp_ctrl);
1.1 root 60: break;
61: case FPCR_ROUND_ZERO: // to zero
1.1.1.2 ! root 62: set_float_rounding_mode(float_round_to_zero, &fp_ctrl);
1.1 root 63: break;
64: case FPCR_ROUND_MINF: // to minus
1.1.1.2 ! root 65: set_float_rounding_mode(float_round_down, &fp_ctrl);
1.1 root 66: break;
67: case FPCR_ROUND_PINF: // to plus
1.1.1.2 ! root 68: set_float_rounding_mode(float_round_up, &fp_ctrl);
1.1 root 69: break;
70: }
71: }
72: STATIC_INLINE void get_fp_status(uae_u32 *status)
73: {
1.1.1.2 ! root 74: int8 flags = get_float_exception_flags(&fp_ctrl);
! 75:
! 76: if (flags & float_flag_signaling)
1.1 root 77: *status |= 0x4000;
1.1.1.2 ! root 78: if (flags & float_flag_invalid)
1.1 root 79: *status |= 0x2000;
1.1.1.2 ! root 80: if (flags & float_flag_overflow)
1.1 root 81: *status |= 0x1000;
1.1.1.2 ! root 82: if (flags & float_flag_underflow)
1.1 root 83: *status |= 0x0800;
1.1.1.2 ! root 84: if (flags & float_flag_divbyzero)
1.1 root 85: *status |= 0x0400;
1.1.1.2 ! root 86: if (flags & float_flag_inexact)
1.1 root 87: *status |= 0x0200;
1.1.1.2 ! root 88: if (flags & float_flag_decimal)
1.1 root 89: *status |= 0x0100;
90: }
91: STATIC_INLINE void clear_fp_status(void)
92: {
1.1.1.2 ! root 93: set_float_exception_flags(0, &fp_ctrl);
1.1 root 94: }
95:
96: /* Helper functions */
97: STATIC_INLINE const char *fp_print(fptype *fx)
98: {
99: static char fs[32];
100: bool n, u, d;
101: fptype x;
102: int32 len;
103: int8 save_exception_flags;
104:
105: n = floatx80_is_negative(*fx);
106: u = floatx80_is_unnormal(*fx);
107: d = floatx80_is_denormal(*fx);
108:
109: if (floatx80_is_infinity(*fx)) {
110: sprintf(fs, "%c%s", n?'-':'+', "inf");
111: } else if (floatx80_is_signaling_nan(*fx)) {
112: sprintf(fs, "%c%s", n?'-':'+', "snan");
113: } else if (floatx80_is_nan(*fx)) {
114: sprintf(fs, "%c%s", n?'-':'+', "nan");
115: } else {
116: len = 17;
1.1.1.2 ! root 117: save_exception_flags = get_float_exception_flags(&fp_ctrl);
! 118: set_float_exception_flags(0, &fp_ctrl);
! 119: x = floatx80_to_floatdecimal(*fx, &len, &fp_ctrl);
1.1 root 120:
121: sprintf(fs, "%c%01lld.%016llde%c%04d%s%s", n?'-':'+',
122: x.low/LIT64(10000000000000000), x.low%LIT64(10000000000000000),
123: (x.high&0x4000)?'-':'+', x.high&0x3FFF, d?"D":u?"U":"",
1.1.1.2 ! root 124: (get_float_exception_flags(&fp_ctrl)&float_flag_inexact)?"~":"");
1.1 root 125:
1.1.1.2 ! root 126: set_float_exception_flags(save_exception_flags, &fp_ctrl);
1.1 root 127: }
128:
129: return fs;
130: }
131:
132: /* Functions for detecting float type */
133: STATIC_INLINE bool fp_is_snan(fptype *fp)
134: {
135: return floatx80_is_signaling_nan(*fp) != 0;
136: }
137: STATIC_INLINE void fp_unset_snan(fptype *fp)
138: {
139: fp->low |= LIT64(0x4000000000000000);
140: }
141: STATIC_INLINE bool fp_is_nan (fptype *fp)
142: {
143: return floatx80_is_nan(*fp) != 0;
144: }
145: STATIC_INLINE bool fp_is_infinity (fptype *fp)
146: {
147: return floatx80_is_infinity(*fp) != 0;
148: }
149: STATIC_INLINE bool fp_is_zero(fptype *fp)
150: {
151: return floatx80_is_zero(*fp) != 0;
152: }
153: STATIC_INLINE bool fp_is_neg(fptype *fp)
154: {
155: return floatx80_is_negative(*fp) != 0;
156: }
157: STATIC_INLINE bool fp_is_denormal(fptype *fp)
158: {
159: return floatx80_is_denormal(*fp) != 0;
160: }
161: STATIC_INLINE bool fp_is_unnormal(fptype *fp)
162: {
163: return floatx80_is_unnormal(*fp) != 0;
164: }
165:
166: /* Function for normalizing unnormals */
167: STATIC_INLINE void fp_normalize(fptype *fp)
168: {
169: *fp = floatx80_normalize(*fp);
170: }
171:
172: /* Functions for converting between float formats */
173: STATIC_INLINE void to_single(fptype *fp, uae_u32 wrd1)
174: {
175: float32 f = wrd1;
176: *fp = float32_to_floatx80_allowunnormal(f);
177: }
178: STATIC_INLINE uae_u32 from_single(fptype *fp)
179: {
1.1.1.2 ! root 180: float32 f = floatx80_to_float32(*fp, &fp_ctrl);
1.1 root 181: return f;
182: }
183:
184: STATIC_INLINE void to_double(fptype *fp, uae_u32 wrd1, uae_u32 wrd2)
185: {
186: float64 f = ((float64)wrd1 << 32) | wrd2;
187: *fp = float64_to_floatx80_allowunnormal(f);
188: }
189: STATIC_INLINE void from_double(fptype *fp, uae_u32 *wrd1, uae_u32 *wrd2)
190: {
1.1.1.2 ! root 191: float64 f = floatx80_to_float64(*fp, &fp_ctrl);
1.1 root 192: *wrd1 = f >> 32;
193: *wrd2 = (uae_u32)f;
194: }
195:
196: STATIC_INLINE void to_exten(fptype *fp, uae_u32 wrd1, uae_u32 wrd2, uae_u32 wrd3)
197: {
198: fp->high = (uae_u16)(wrd1 >> 16);
199: fp->low = ((uae_u64)wrd2 << 32) | wrd3;
200: }
201: STATIC_INLINE void from_exten(fptype *fp, uae_u32 *wrd1, uae_u32 *wrd2, uae_u32 *wrd3)
202: {
1.1.1.2 ! root 203: floatx80 f = floatx80_to_floatx80(*fp, &fp_ctrl);
1.1 root 204: *wrd1 = (uae_u32)(f.high << 16);
205: *wrd2 = f.low >> 32;
206: *wrd3 = (uae_u32)f.low;
207: }
208: STATIC_INLINE void to_exten_fmovem(fptype *fp, uae_u32 wrd1, uae_u32 wrd2, uae_u32 wrd3)
209: {
210: fp->high = (uae_u16)(wrd1 >> 16);
211: fp->low = ((uae_u64)wrd2 << 32) | wrd3;
212: }
213: STATIC_INLINE void from_exten_fmovem(fptype *fp, uae_u32 *wrd1, uae_u32 *wrd2, uae_u32 *wrd3)
214: {
215: *wrd1 = (uae_u32)(fp->high << 16);
216: *wrd2 = fp->low >> 32;
217: *wrd3 = (uae_u32)fp->low;
218: }
219:
220: STATIC_INLINE uae_s64 to_int(fptype *src, int size)
221: {
222: switch (size) {
1.1.1.2 ! root 223: case 0: return floatx80_to_int8(*src, &fp_ctrl);
! 224: case 1: return floatx80_to_int16(*src, &fp_ctrl);
! 225: case 2: return floatx80_to_int32(*src, &fp_ctrl);
1.1 root 226: default: return 0;
227: }
228: }
229: STATIC_INLINE fptype from_int(uae_s32 src)
230: {
231: return int32_to_floatx80(src);
232: }
233:
234: STATIC_INLINE void to_pack(fptype *fp, uae_u32 *wrd)
235: {
236: floatx80 f;
237: int i;
238: uae_s32 exp;
239: uae_s64 mant;
240: uae_u32 pack_exp, pack_int, pack_se, pack_sm;
241: uae_u64 pack_frac;
242:
243: if (((wrd[0] >> 16) & 0x7fff) == 0x7fff) {
244: // infinity has extended exponent and all 0 packed fraction
245: // nans are copies bit by bit
246: to_exten(fp, wrd[0], wrd[1], wrd[2]);
247: return;
248: }
249: if (!(wrd[0] & 0xf) && !wrd[1] && !wrd[2]) {
250: // exponent is not cared about, if mantissa is zero
251: wrd[0] &= 0x80000000;
252: to_exten(fp, wrd[0], wrd[1], wrd[2]);
253: return;
254: }
255:
256: pack_exp = (wrd[0] >> 16) & 0xFFF; // packed exponent
257: pack_int = wrd[0] & 0xF; // packed integer part
258: pack_frac = ((uae_u64)wrd[1] << 32) | wrd[2]; // packed fraction
259: pack_se = (wrd[0] >> 30) & 1; // sign of packed exponent
260: pack_sm = (wrd[0] >> 31) & 1; // sign of packed significand
261:
262: exp = 0;
263:
264: for (i = 0; i < 3; i++) {
265: exp *= 10;
266: exp += (pack_exp >> (8 - i * 4)) & 0xF;
267: }
268:
269: if (pack_se) {
270: exp = -exp;
271: }
272:
273: exp -= 16;
274:
275: if (exp < 0) {
276: exp = -exp;
277: pack_se = 1;
278: }
279:
280: mant = pack_int;
281:
282: for (i = 0; i < 16; i++) {
283: mant *= 10;
284: mant += (pack_frac >> (60 - i * 4)) & 0xF;
285: }
286:
287: f.high = exp & 0x3FFF;
288: f.high |= pack_se ? 0x4000 : 0;
289: f.high |= pack_sm ? 0x8000 : 0;
290: f.low = mant;
291:
1.1.1.2 ! root 292: *fp = floatdecimal_to_floatx80(f, &fp_ctrl);
1.1 root 293: }
294: STATIC_INLINE void from_pack(fptype *fp, uae_u32 *wrd, uae_s32 kfactor)
295: {
1.1.1.2 ! root 296: floatx80 f = floatx80_to_floatdecimal(*fp, &kfactor, &fp_ctrl);
1.1 root 297:
298: uae_u32 pack_exp, pack_exp4, pack_int, pack_se, pack_sm;
299: uae_u64 pack_frac;
300:
301: uae_u32 exponent;
302: uae_u64 significand;
303:
304: uae_s32 len;
305: uae_u64 digit;
306:
307: if ((f.high & 0x7FFF) == 0x7FFF) {
308: wrd[0] = (uae_u32)(f.high << 16);
309: wrd[1] = f.low >> 32;
310: wrd[2] = (uae_u32)f.low;
311: } else {
312: exponent = f.high & 0x3FFF;
313: significand = f.low;
314:
315: pack_int = 0;
316: pack_frac = 0;
317: len = kfactor; // SoftFloat saved len to kfactor variable
318: while (len > 0) {
319: len--;
320: digit = significand % 10;
321: significand /= 10;
322: if (len == 0) {
323: pack_int = digit;
324: } else {
325: pack_frac |= digit << (64 - len * 4);
326: }
327: }
328:
329: pack_exp = 0;
330: pack_exp4 = 0;
331: len = 4;
332: while (len > 0) {
333: len--;
334: digit = exponent % 10;
335: exponent /= 10;
336: if (len == 0) {
337: pack_exp4 = digit;
338: } else {
339: pack_exp |= digit << (12 - len * 4);
340: }
341: }
342:
343: pack_se = f.high & 0x4000;
344: pack_sm = f.high & 0x8000;
345:
346: wrd[0] = pack_exp << 16;
347: wrd[0] |= pack_exp4 << 12;
348: wrd[0] |= pack_int;
349: wrd[0] |= pack_se ? 0x40000000 : 0;
350: wrd[0] |= pack_sm ? 0x80000000 : 0;
351:
352: wrd[1] = pack_frac >> 32;
353: wrd[2] = pack_frac & 0xffffffff;
354: }
355: }
356:
357: /* Functions for returning exception state data */
358: STATIC_INLINE fptype fp_get_internal_overflow(void)
359: {
1.1.1.2 ! root 360: return getFloatInternalOverflow(&fp_ctrl);
1.1 root 361: }
362: STATIC_INLINE fptype fp_get_internal_underflow(void)
363: {
1.1.1.2 ! root 364: return getFloatInternalUnderflow(&fp_ctrl);
1.1 root 365: }
366: STATIC_INLINE fptype fp_get_internal_round_all(void)
367: {
1.1.1.2 ! root 368: return getFloatInternalRoundedAll(&fp_ctrl);
1.1 root 369: }
370: STATIC_INLINE fptype fp_get_internal_round(void)
371: {
1.1.1.2 ! root 372: return getFloatInternalRoundedSome(&fp_ctrl);
1.1 root 373: }
374: STATIC_INLINE fptype fp_get_internal_round_exten(void)
375: {
1.1.1.2 ! root 376: return getFloatInternalFloatx80(&fp_ctrl);
1.1 root 377: }
378: STATIC_INLINE fptype fp_get_internal(void)
379: {
1.1.1.2 ! root 380: return getFloatInternalUnrounded(&fp_ctrl);
1.1 root 381: }
382: STATIC_INLINE uae_u32 fp_get_internal_grs(void)
383: {
1.1.1.2 ! root 384: return (uae_u32)getFloatInternalGRS(&fp_ctrl);
1.1 root 385: }
386:
387: /* Function for denormalizing */
388: STATIC_INLINE void fp_denormalize(fptype *fp, int esign)
389: {
390: *fp = floatx80_denormalize(*fp, esign);
391: }
392:
393: /* Functions for rounding */
394:
395: // round to float with extended precision exponent
396: STATIC_INLINE void fp_round32(fptype *fp)
397: {
1.1.1.2 ! root 398: *fp = floatx80_round32(*fp, &fp_ctrl);
1.1 root 399: }
400:
401: // round to double with extended precision exponent
402: STATIC_INLINE void fp_round64(fptype *fp)
403: {
1.1.1.2 ! root 404: *fp = floatx80_round64(*fp, &fp_ctrl);
1.1 root 405: }
406:
407: // round to float
408: STATIC_INLINE void fp_round_single(fptype *fp)
409: {
1.1.1.2 ! root 410: *fp = floatx80_round_to_float32(*fp, &fp_ctrl);
1.1 root 411: }
412:
413: // round to double
414: STATIC_INLINE void fp_round_double(fptype *fp)
415: {
1.1.1.2 ! root 416: *fp = floatx80_round_to_float64(*fp, &fp_ctrl);
1.1 root 417: }
418:
419: // round to selected precision
420: STATIC_INLINE void fp_round(fptype *a)
421: {
1.1.1.2 ! root 422: switch(get_float_rounding_precision(&fp_ctrl)) {
1.1 root 423: case 32:
1.1.1.2 ! root 424: *a = floatx80_round_to_float32(*a, &fp_ctrl);
1.1 root 425: break;
426: case 64:
1.1.1.2 ! root 427: *a = floatx80_round_to_float64(*a, &fp_ctrl);
1.1 root 428: break;
429: default:
430: break;
431: }
432: }
433:
434: /* Arithmetic functions */
435: STATIC_INLINE void fp_move(fptype *a, fptype *b)
436: {
1.1.1.2 ! root 437: *a = floatx80_move(*b, &fp_ctrl);
1.1 root 438: }
439: STATIC_INLINE void fp_int(fptype *a, fptype *b)
440: {
1.1.1.2 ! root 441: *a = floatx80_round_to_int(*b, &fp_ctrl);
1.1 root 442: }
443: STATIC_INLINE void fp_intrz(fptype *a, fptype *b)
444: {
1.1.1.2 ! root 445: *a = floatx80_round_to_int_toward_zero(*b, &fp_ctrl);
1.1 root 446: }
447: STATIC_INLINE void fp_sqrt(fptype *a, fptype *b)
448: {
1.1.1.2 ! root 449: *a = floatx80_sqrt(*b, &fp_ctrl);
1.1 root 450: }
451: STATIC_INLINE void fp_abs(fptype *a, fptype *b)
452: {
1.1.1.2 ! root 453: *a = floatx80_abs(*b, &fp_ctrl);
1.1 root 454: }
455: STATIC_INLINE void fp_neg(fptype *a, fptype *b)
456: {
1.1.1.2 ! root 457: *a = floatx80_neg(*b, &fp_ctrl);
1.1 root 458: }
459: STATIC_INLINE void fp_getexp(fptype *a, fptype *b)
460: {
1.1.1.2 ! root 461: *a = floatx80_getexp(*b, &fp_ctrl);
1.1 root 462: }
463: STATIC_INLINE void fp_getman(fptype *a, fptype *b)
464: {
1.1.1.2 ! root 465: *a = floatx80_getman(*b, &fp_ctrl);
1.1 root 466: }
467: STATIC_INLINE void fp_div(fptype *a, fptype *b)
468: {
1.1.1.2 ! root 469: *a = floatx80_div(*a, *b, &fp_ctrl);
1.1 root 470: }
471: STATIC_INLINE void fp_mod(fptype *a, fptype *b, uae_u64 *q, uae_s8 *s)
472: {
1.1.1.2 ! root 473: *a = floatx80_mod(*a, *b, q, s, &fp_ctrl);
1.1 root 474: }
475: STATIC_INLINE void fp_add(fptype *a, fptype *b)
476: {
1.1.1.2 ! root 477: *a = floatx80_add(*a, *b, &fp_ctrl);
1.1 root 478: }
479: STATIC_INLINE void fp_mul(fptype *a, fptype *b)
480: {
1.1.1.2 ! root 481: *a = floatx80_mul(*a, *b, &fp_ctrl);
1.1 root 482: }
483: STATIC_INLINE void fp_sgldiv(fptype *a, fptype *b)
484: {
1.1.1.2 ! root 485: *a = floatx80_sgldiv(*a, *b, &fp_ctrl);
1.1 root 486: }
487: STATIC_INLINE void fp_rem(fptype *a, fptype *b, uae_u64 *q, uae_s8 *s)
488: {
1.1.1.2 ! root 489: *a = floatx80_rem(*a, *b, q, s, &fp_ctrl);
1.1 root 490: }
491: STATIC_INLINE void fp_scale(fptype *a, fptype *b)
492: {
1.1.1.2 ! root 493: *a = floatx80_scale(*a, *b, &fp_ctrl);
1.1 root 494: }
495: STATIC_INLINE void fp_sglmul(fptype *a, fptype *b)
496: {
1.1.1.2 ! root 497: *a = floatx80_sglmul(*a, *b, &fp_ctrl);
1.1 root 498: }
499: STATIC_INLINE void fp_sub(fptype *a, fptype *b)
500: {
1.1.1.2 ! root 501: *a = floatx80_sub(*a, *b, &fp_ctrl);
1.1 root 502: }
503: STATIC_INLINE void fp_cmp(fptype *a, fptype *b)
504: {
1.1.1.2 ! root 505: *a = floatx80_cmp(*a, *b, &fp_ctrl);
1.1 root 506: }
507: STATIC_INLINE void fp_tst(fptype *a, fptype *b)
508: {
1.1.1.2 ! root 509: *a = floatx80_tst(*b, &fp_ctrl);
1.1 root 510: }
511:
512: STATIC_INLINE void fp_sinh(fptype *a, fptype *b)
513: {
1.1.1.2 ! root 514: *a = floatx80_sinh(*b, &fp_ctrl);
1.1 root 515: }
516: STATIC_INLINE void fp_lognp1(fptype *a, fptype *b)
517: {
1.1.1.2 ! root 518: *a = floatx80_lognp1(*b, &fp_ctrl);
1.1 root 519: }
520: STATIC_INLINE void fp_etoxm1(fptype *a, fptype *b)
521: {
1.1.1.2 ! root 522: *a = floatx80_etoxm1(*b, &fp_ctrl);
1.1 root 523: }
524: STATIC_INLINE void fp_tanh(fptype *a, fptype *b)
525: {
1.1.1.2 ! root 526: *a = floatx80_tanh(*b, &fp_ctrl);
1.1 root 527: }
528: STATIC_INLINE void fp_atan(fptype *a, fptype *b)
529: {
1.1.1.2 ! root 530: *a = floatx80_atan(*b, &fp_ctrl);
1.1 root 531: }
532: STATIC_INLINE void fp_asin(fptype *a, fptype *b)
533: {
1.1.1.2 ! root 534: *a = floatx80_asin(*b, &fp_ctrl);
1.1 root 535: }
536: STATIC_INLINE void fp_atanh(fptype *a, fptype *b)
537: {
1.1.1.2 ! root 538: *a = floatx80_atanh(*b, &fp_ctrl);
1.1 root 539: }
540: STATIC_INLINE void fp_sin(fptype *a, fptype *b)
541: {
1.1.1.2 ! root 542: *a = floatx80_sin(*b, &fp_ctrl);
1.1 root 543: }
544: STATIC_INLINE void fp_tan(fptype *a, fptype *b)
545: {
1.1.1.2 ! root 546: *a = floatx80_tan(*b, &fp_ctrl);
1.1 root 547: }
548: STATIC_INLINE void fp_etox(fptype *a, fptype *b)
549: {
1.1.1.2 ! root 550: *a = floatx80_etox(*b, &fp_ctrl);
1.1 root 551: }
552: STATIC_INLINE void fp_twotox(fptype *a, fptype *b)
553: {
1.1.1.2 ! root 554: *a = floatx80_twotox(*b, &fp_ctrl);
1.1 root 555: }
556: STATIC_INLINE void fp_tentox(fptype *a, fptype *b)
557: {
1.1.1.2 ! root 558: *a = floatx80_tentox(*b, &fp_ctrl);
1.1 root 559: }
560: STATIC_INLINE void fp_logn(fptype *a, fptype *b)
561: {
1.1.1.2 ! root 562: *a = floatx80_logn(*b, &fp_ctrl);
1.1 root 563: }
564: STATIC_INLINE void fp_log10(fptype *a, fptype *b)
565: {
1.1.1.2 ! root 566: *a = floatx80_log10(*b, &fp_ctrl);
1.1 root 567: }
568: STATIC_INLINE void fp_log2(fptype *a, fptype *b)
569: {
1.1.1.2 ! root 570: *a = floatx80_log2(*b, &fp_ctrl);
1.1 root 571: }
572: STATIC_INLINE void fp_cosh(fptype *a, fptype *b)
573: {
1.1.1.2 ! root 574: *a = floatx80_cosh(*b, &fp_ctrl);
1.1 root 575: }
576: STATIC_INLINE void fp_acos(fptype *a, fptype *b)
577: {
1.1.1.2 ! root 578: *a = floatx80_acos(*b, &fp_ctrl);
1.1 root 579: }
580: STATIC_INLINE void fp_cos(fptype *a, fptype *b)
581: {
1.1.1.2 ! root 582: *a = floatx80_cos(*b, &fp_ctrl);
1.1 root 583: }
584:
585: /* Functions with fixed precision */
586: STATIC_INLINE void fp_move_single(fptype *a, fptype *b)
587: {
1.1.1.2 ! root 588: int8 oldprec = get_float_rounding_precision(&fp_ctrl);
! 589: set_float_rounding_precision(32, &fp_ctrl);
! 590: *a = floatx80_move(*b, &fp_ctrl);
! 591: set_float_rounding_precision(oldprec, &fp_ctrl);
1.1 root 592: }
593: STATIC_INLINE void fp_abs_single(fptype *a, fptype *b)
594: {
1.1.1.2 ! root 595: int8 oldprec = get_float_rounding_precision(&fp_ctrl);
! 596: set_float_rounding_precision(32, &fp_ctrl);
! 597: *a = floatx80_abs(*b, &fp_ctrl);
! 598: set_float_rounding_precision(oldprec, &fp_ctrl);
1.1 root 599: }
600: STATIC_INLINE void fp_neg_single(fptype *a, fptype *b)
601: {
1.1.1.2 ! root 602: int8 oldprec = get_float_rounding_precision(&fp_ctrl);
! 603: set_float_rounding_precision(32, &fp_ctrl);
! 604: *a = floatx80_neg(*b, &fp_ctrl);
! 605: set_float_rounding_precision(oldprec, &fp_ctrl);
1.1 root 606: }
607: STATIC_INLINE void fp_add_single(fptype *a, fptype *b)
608: {
1.1.1.2 ! root 609: int8 oldprec = get_float_rounding_precision(&fp_ctrl);
! 610: set_float_rounding_precision(32, &fp_ctrl);
! 611: *a = floatx80_add(*a, *b, &fp_ctrl);
! 612: set_float_rounding_precision(oldprec, &fp_ctrl);
1.1 root 613: }
614: STATIC_INLINE void fp_sub_single(fptype *a, fptype *b)
615: {
1.1.1.2 ! root 616: int8 oldprec = get_float_rounding_precision(&fp_ctrl);
! 617: set_float_rounding_precision(32, &fp_ctrl);
! 618: *a = floatx80_sub(*a, *b, &fp_ctrl);
! 619: set_float_rounding_precision(oldprec, &fp_ctrl);
1.1 root 620: }
621: STATIC_INLINE void fp_mul_single(fptype *a, fptype *b)
622: {
1.1.1.2 ! root 623: int8 oldprec = get_float_rounding_precision(&fp_ctrl);
! 624: set_float_rounding_precision(32, &fp_ctrl);
! 625: *a = floatx80_mul(*a, *b, &fp_ctrl);
! 626: set_float_rounding_precision(oldprec, &fp_ctrl);
1.1 root 627: }
628: STATIC_INLINE void fp_div_single(fptype *a, fptype *b)
629: {
1.1.1.2 ! root 630: int8 oldprec = get_float_rounding_precision(&fp_ctrl);
! 631: set_float_rounding_precision(32, &fp_ctrl);
! 632: *a = floatx80_div(*a, *b, &fp_ctrl);
! 633: set_float_rounding_precision(oldprec, &fp_ctrl);
1.1 root 634: }
635: STATIC_INLINE void fp_sqrt_single(fptype *a, fptype *b)
636: {
1.1.1.2 ! root 637: int8 oldprec = get_float_rounding_precision(&fp_ctrl);
! 638: set_float_rounding_precision(32, &fp_ctrl);
! 639: *a = floatx80_sqrt(*b, &fp_ctrl);
! 640: set_float_rounding_precision(oldprec, &fp_ctrl);
1.1 root 641: }
642: STATIC_INLINE void fp_move_double(fptype *a, fptype *b)
643: {
1.1.1.2 ! root 644: int8 oldprec = get_float_rounding_precision(&fp_ctrl);
! 645: set_float_rounding_precision(64, &fp_ctrl);
! 646: *a = floatx80_move(*b, &fp_ctrl);
! 647: set_float_rounding_precision(oldprec, &fp_ctrl);
1.1 root 648: }
649: STATIC_INLINE void fp_abs_double(fptype *a, fptype *b)
650: {
1.1.1.2 ! root 651: int8 oldprec = get_float_rounding_precision(&fp_ctrl);
! 652: set_float_rounding_precision(64, &fp_ctrl);
! 653: *a = floatx80_abs(*b, &fp_ctrl);
! 654: set_float_rounding_precision(oldprec, &fp_ctrl);
1.1 root 655: }
656: STATIC_INLINE void fp_neg_double(fptype *a, fptype *b)
657: {
1.1.1.2 ! root 658: int8 oldprec = get_float_rounding_precision(&fp_ctrl);
! 659: set_float_rounding_precision(64, &fp_ctrl);
! 660: *a = floatx80_neg(*b, &fp_ctrl);
! 661: set_float_rounding_precision(oldprec, &fp_ctrl);
1.1 root 662: }
663: STATIC_INLINE void fp_add_double(fptype *a, fptype *b)
664: {
1.1.1.2 ! root 665: int8 oldprec = get_float_rounding_precision(&fp_ctrl);
! 666: set_float_rounding_precision(64, &fp_ctrl);
! 667: *a = floatx80_add(*a, *b, &fp_ctrl);
! 668: set_float_rounding_precision(oldprec, &fp_ctrl);
1.1 root 669: }
670: STATIC_INLINE void fp_sub_double(fptype *a, fptype *b)
671: {
1.1.1.2 ! root 672: int8 oldprec = get_float_rounding_precision(&fp_ctrl);
! 673: set_float_rounding_precision(64, &fp_ctrl);
! 674: *a = floatx80_sub(*a, *b, &fp_ctrl);
! 675: set_float_rounding_precision(oldprec, &fp_ctrl);
1.1 root 676: }
677: STATIC_INLINE void fp_mul_double(fptype *a, fptype *b)
678: {
1.1.1.2 ! root 679: int8 oldprec = get_float_rounding_precision(&fp_ctrl);
! 680: set_float_rounding_precision(64, &fp_ctrl);
! 681: *a = floatx80_mul(*a, *b, &fp_ctrl);
! 682: set_float_rounding_precision(oldprec, &fp_ctrl);
1.1 root 683: }
684: STATIC_INLINE void fp_div_double(fptype *a, fptype *b)
685: {
1.1.1.2 ! root 686: int8 oldprec = get_float_rounding_precision(&fp_ctrl);
! 687: set_float_rounding_precision(64, &fp_ctrl);
! 688: *a = floatx80_div(*a, *b, &fp_ctrl);
! 689: set_float_rounding_precision(oldprec, &fp_ctrl);
1.1 root 690: }
691: STATIC_INLINE void fp_sqrt_double(fptype *a, fptype *b)
692: {
1.1.1.2 ! root 693: int8 oldprec = get_float_rounding_precision(&fp_ctrl);
! 694: set_float_rounding_precision(64, &fp_ctrl);
! 695: *a = floatx80_sqrt(*b, &fp_ctrl);
! 696: set_float_rounding_precision(oldprec, &fp_ctrl);
1.1 root 697: }
698:
699:
700:
701: #if 0 /* Old fallback functions disabled */
702: static const long double twoto32 = 4294967296.0;
703:
704: STATIC_INLINE void to_native(long double *fp, fptype fpx)
705: {
706: int expon;
707: long double frac;
708:
709: expon = fpx.high & 0x7fff;
710:
711: if (floatx80_is_zero(fpx)) {
712: *fp = floatx80_is_negative(fpx) ? -0.0 : +0.0;
713: return;
714: }
715: if (floatx80_is_nan(fpx)) {
716: *fp = sqrtl(-1);
717: return;
718: }
719: if (floatx80_is_infinity(fpx)) {
720: *fp = floatx80_is_negative(fpx) ? logl(0.0) : (1.0/0.0);
721: return;
722: }
723:
724: frac = (long double)fpx.low / (long double)(twoto32 * 2147483648.0);
725: if (floatx80_is_negative(fpx))
726: frac = -frac;
727: *fp = ldexpl (frac, expon - 16383);
728: }
729: STATIC_INLINE void from_native(long double fp, fptype *fpx)
730: {
731: int expon;
732: long double frac;
733:
734: if (signbit(fp))
735: fpx->high = 0x8000;
736: else
737: fpx->high = 0x0000;
738:
739: if (isnan(fp)) {
740: fpx->high |= 0x7fff;
741: fpx->low = LIT64(0xffffffffffffffff);
742: return;
743: }
744: if (isinf(fp)) {
745: fpx->high |= 0x7fff;
746: fpx->low = LIT64(0x0000000000000000);
747: return;
748: }
749: if (fp == 0.0) {
750: fpx->low = LIT64(0x0000000000000000);
751: return;
752: }
753: if (fp < 0.0)
754: fp = -fp;
755:
756: frac = frexpl (fp, &expon);
757: frac += 0.5 / (twoto32 * twoto32);
758: if (frac >= 1.0) {
759: frac /= 2.0;
760: expon++;
761: }
762: fpx->high |= (expon + 16383 - 1) & 0x7fff;
763: fpx->low = (bits64)(frac * (long double)(twoto32 * twoto32));
764:
765: while (!(fpx->low & LIT64( 0x8000000000000000))) {
766: if (fpx->high == 0) {
767: break;
768: }
769: fpx->low <<= 1;
770: fpx->high--;
771: }
772: }
773:
774: STATIC_INLINE void fp_sinhf(fptype *a, fptype *b)
775: {
776: flag e = 0;
777: floatx80_sinh_check(*a, &e);
778: if (e) return;
779: long double fp;
780: to_native(&fp, *b);
781: fp = sinhl(fp);
782: from_native(fp, a);
783: fp_round(a);
784: }
785: STATIC_INLINE void fp_lognp1f(fptype *a, fptype *b)
786: {
787: flag e = 0;
788: floatx80_lognp1_check(*a, &e);
789: if (e) return;
790: long double fp;
791: to_native(&fp, *b);
792: fp = log1pl(fp);
793: from_native(fp, a);
794: fp_round(a);
795: }
796: STATIC_INLINE void fp_etoxm1f(fptype *a, fptype *b)
797: {
798: flag e = 0;
799: floatx80_etoxm1_check(*a, &e);
800: if (e) return;
801: long double fp;
802: to_native(&fp, *b);
803: fp = expm1l(fp);
804: from_native(fp, a);
805: fp_round(a);
806: }
807: STATIC_INLINE void fp_tanhf(fptype *a, fptype *b)
808: {
809: flag e = 0;
810: floatx80_tanh_check(*a, &e);
811: if (e) return;
812: long double fp;
813: to_native(&fp, *b);
814: fp = tanhl(fp);
815: from_native(fp, a);
816: fp_round(a);
817: }
818: STATIC_INLINE void fp_atanf(fptype *a, fptype *b)
819: {
820: flag e = 0;
821: floatx80_atan_check(*a, &e);
822: if (e) return;
823: long double fp;
824: to_native(&fp, *b);
825: fp = atanl(fp);
826: from_native(fp, a);
827: fp_round(a);
828: }
829: STATIC_INLINE void fp_asinf(fptype *a, fptype *b)
830: {
831: flag e = 0;
832: floatx80_asin_check(*a, &e);
833: if (e) return;
834: long double fp;
835: to_native(&fp, *b);
836: fp = asinl(fp);
837: from_native(fp, a);
838: fp_round(a);
839: }
840: STATIC_INLINE void fp_atanhf(fptype *a, fptype *b)
841: {
842: flag e = 0;
843: floatx80_atanh_check(*a, &e);
844: if (e) return;
845: long double fp;
846: to_native(&fp, *b);
847: fp = atanhl(fp);
848: from_native(fp, a);
849: fp_round(a);
850: }
851: STATIC_INLINE void fp_sinf(fptype *a, fptype *b)
852: {
853: flag e = 0;
854: floatx80_sin_check(*a, &e);
855: if (e) return;
856: long double fp;
857: to_native(&fp, *b);
858: fp = sinl(fp);
859: from_native(fp, a);
860: fp_round(a);
861: }
862: STATIC_INLINE void fp_tanf(fptype *a, fptype *b)
863: {
864: flag e = 0;
865: floatx80_tan_check(*a, &e);
866: if (e) return;
867: long double fp;
868: to_native(&fp, *b);
869: fp = tanl(fp);
870: from_native(fp, a);
871: fp_round(a);
872: }
873: STATIC_INLINE void fp_etoxf(fptype *a, fptype *b)
874: {
875: flag e = 0;
876: floatx80_etox_check(*a, &e);
877: if (e) return;
878: long double fp;
879: to_native(&fp, *b);
880: fp = expl(fp);
881: from_native(fp, a);
882: fp_round(a);
883: }
884: STATIC_INLINE void fp_twotoxf(fptype *a, fptype *b)
885: {
886: flag e = 0;
887: floatx80_twotox_check(*a, &e);
888: if (e) return;
889: long double fp;
890: to_native(&fp, *b);
891: fp = powl(2.0, fp);
892: from_native(fp, a);
893: fp_round(a);
894: }
895: STATIC_INLINE void fp_tentoxf(fptype *a, fptype *b)
896: {
897: flag e = 0;
898: floatx80_tentox_check(*a, &e);
899: if (e) return;
900: long double fp;
901: to_native(&fp, *b);
902: fp = powl(10.0, fp);
903: from_native(fp, a);
904: fp_round(a);
905: }
906: STATIC_INLINE void fp_lognf(fptype *a, fptype *b)
907: {
908: flag e = 0;
909: floatx80_logn_check(*a, &e);
910: if (e) return;
911: long double fp;
912: to_native(&fp, *b);
913: fp = logl(fp);
914: from_native(fp, a);
915: fp_round(a);
916: }
917: STATIC_INLINE void fp_log10f(fptype *a, fptype *b)
918: {
919: flag e = 0;
920: floatx80_log10_check(*a, &e);
921: if (e) return;
922: long double fp;
923: to_native(&fp, *b);
924: fp = log10l(fp);
925: from_native(fp, a);
926: fp_round(a);
927: }
928: STATIC_INLINE void fp_log2f(fptype *a, fptype *b)
929: {
930: flag e = 0;
931: floatx80_log2_check(*a, &e);
932: if (e) return;
933: long double fp;
934: to_native(&fp, *b);
935: fp = log2l(fp);
936: from_native(fp, a);
937: fp_round(a);
938: }
939: STATIC_INLINE void fp_coshf(fptype *a, fptype *b)
940: {
941: flag e = 0;
942: floatx80_cosh_check(*a, &e);
943: if (e) return;
944: long double fp;
945: to_native(&fp, *b);
946: fp = coshl(fp);
947: from_native(fp, a);
948: fp_round(a);
949: }
950: STATIC_INLINE void fp_acosf(fptype *a, fptype *b)
951: {
952: flag e = 0;
953: floatx80_acos_check(*a, &e);
954: if (e) return;
955: long double fp;
956: to_native(&fp, *b);
957: fp = acosl(fp);
958: from_native(fp, a);
959: fp_round(a);
960: }
961: STATIC_INLINE void fp_cosf(fptype *a, fptype *b)
962: {
963: flag e = 0;
964: floatx80_cos_check(*a, &e);
965: if (e) return;
966: long double fp;
967: to_native(&fp, *b);
968: fp = cosl(fp);
969: from_native(fp, a);
970: fp_round(a);
971: }
972: #endif
973:
974: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.