--- BasiliskII/src/uae_cpu/fpu/fpu_ieee.cpp 2002/09/15 18:21:13 1.3 +++ BasiliskII/src/uae_cpu/fpu/fpu_ieee.cpp 2003/05/28 10:17:43 1.9 @@ -80,24 +80,6 @@ fpu_t fpu; /* -------------------------------------------------------------------------- */ -/* --- Endianness --- */ -/* -------------------------------------------------------------------------- */ - -// Taken from glibc 2.1.x: endian.h -#define UAE_LITTLE_ENDIAN 1234 -#define UAE_BIG_ENDIAN 4321 - -#if WORDS_BIGENDIAN -#define UAE_BYTE_ORDER UAE_BIG_ENDIAN -#else -#define UAE_BYTE_ORDER UAE_LITTLE_ENDIAN -#endif - -// Some machines may need to use a different endianness for floating point values -// e.g. ARM in which case it is big endian -#define UAE_FLOAT_WORD_ORDER UAE_BYTE_ORDER - -/* -------------------------------------------------------------------------- */ /* --- Scopes Definition --- */ /* -------------------------------------------------------------------------- */ @@ -198,7 +180,7 @@ PRIVATE inline fpu_register FFPU make_si #if 1 // Use a single, otherwise some checks for NaN, Inf, Zero would have to // be performed - fpu_single result; + fpu_single result = 0; // = 0 to workaround a compiler bug on SPARC fp_declare_init_shape(srp, result, single); srp->ieee.negative = (value >> 31) & 1; srp->ieee.exponent = (value >> 23) & FP_SINGLE_EXP_MAX; @@ -269,7 +251,34 @@ PRIVATE inline fpu_register FFPU make_ex return 0.0; fpu_register result; -#ifndef USE_LONG_DOUBLE +#if USE_QUAD_DOUBLE + // is it NaN? + if ((wrd1 & 0x7fff0000) == 0x7fff0000 && wrd2 != 0 && wrd3 != 0) { + make_nan(result); + return result; + } + // is it inf? + if ((wrd1 & 0x7ffff000) == 0x7fff0000 && wrd2 == 0 && wrd3 == 0) { + if ((wrd1 & 0x80000000) == 0) + make_inf_positive(result); + else + make_inf_negative(result); + return result; + } + fp_declare_init_shape(srp, result, extended); + srp->ieee.negative = (wrd1 >> 31) & 1; + srp->ieee.exponent = (wrd1 >> 16) & FP_EXTENDED_EXP_MAX; + srp->ieee.mantissa0 = (wrd2 >> 16) & 0xffff; + srp->ieee.mantissa1 = ((wrd2 & 0xffff) << 16) | ((wrd3 >> 16) & 0xffff); + srp->ieee.mantissa2 = (wrd3 & 0xffff) << 16; + srp->ieee.mantissa3 = 0; +#elif USE_LONG_DOUBLE + fp_declare_init_shape(srp, result, extended); + srp->ieee.negative = (wrd1 >> 31) & 1; + srp->ieee.exponent = (wrd1 >> 16) & FP_EXTENDED_EXP_MAX; + srp->ieee.mantissa0 = wrd2; + srp->ieee.mantissa1 = wrd3; +#else uae_u32 sgn = (wrd1 >> 31) & 1; uae_u32 exp = (wrd1 >> 16) & 0x7fff; @@ -303,19 +312,6 @@ PRIVATE inline fpu_register FFPU make_ex // drop the explicit integer bit srp->ieee.mantissa0 = (wrd2 & 0x7fffffff) >> 11; srp->ieee.mantissa1 = (wrd2 << 21) | (wrd3 >> 11); -#elif USE_QUAD_DOUBLE - fp_declare_init_shape(srp, result, extended); - srp->ieee.negative = (wrd1 >> 31) & 1; - srp->ieee.exponent = (wrd1 >> 16) & FP_EXTENDED_EXP_MAX; - srp->ieee.mantissa0 = (wrd2 >> 16) & 0xffff; - srp->ieee.mantissa1 = ((wrd2 & 0xffff) << 16) | ((wrd3 >> 16) & 0xffff); - srp->ieee.mantissa2 = (wrd3 & 0xffff) << 16; -#else - fp_declare_init_shape(srp, result, extended); - srp->ieee.negative = (wrd1 >> 31) & 1; - srp->ieee.exponent = (wrd1 >> 16) & FP_EXTENDED_EXP_MAX; - srp->ieee.mantissa0 = wrd2; - srp->ieee.mantissa1 = wrd3; #endif fpu_debug(("make_extended (%X,%X,%X) = %.04f\n",wrd1,wrd2,wrd3,(double)result)); return result; @@ -340,7 +336,29 @@ PRIVATE inline void FFPU make_extended_n make_nan(result); return; } -#ifndef USE_LONG_DOUBLE +#if USE_QUAD_DOUBLE + // is it inf? + if ((wrd1 & 0x7ffff000) == 0x7fff0000 && wrd2 == 0 && wrd3 == 0) { + if ((wrd1 & 0x80000000) == 0) + make_inf_positive(result); + else + make_inf_negative(result); + return; + } + fp_declare_init_shape(srp, result, extended); + srp->ieee.negative = (wrd1 >> 31) & 1; + srp->ieee.exponent = (wrd1 >> 16) & FP_EXTENDED_EXP_MAX; + srp->ieee.mantissa0 = (wrd2 >> 16) & 0xffff; + srp->ieee.mantissa1 = ((wrd2 & 0xffff) << 16) | ((wrd3 >> 16) & 0xffff); + srp->ieee.mantissa2 = (wrd3 & 0xffff) << 16; + srp->ieee.mantissa3 = 0; +#elif USE_LONG_DOUBLE + fp_declare_init_shape(srp, result, extended); + srp->ieee.negative = (wrd1 >> 31) & 1; + srp->ieee.exponent = (wrd1 >> 16) & FP_EXTENDED_EXP_MAX; + srp->ieee.mantissa0 = wrd2; + srp->ieee.mantissa1 = wrd3; +#else uae_u32 exp = (wrd1 >> 16) & 0x7fff; if (exp < FP_EXTENDED_EXP_BIAS - FP_DOUBLE_EXP_BIAS) exp = 0; @@ -355,13 +373,6 @@ PRIVATE inline void FFPU make_extended_n // drop the explicit integer bit srp->ieee.mantissa0 = (wrd2 & 0x7fffffff) >> 11; srp->ieee.mantissa1 = (wrd2 << 21) | (wrd3 >> 11); -#else - // FIXME: USE_QUAD_DOUBLE - fp_declare_init_shape(srp, result, extended); - srp->ieee.negative = (wrd1 & 0x80000000) != 0; - srp->ieee.exponent = (wrd1 >> 16) & 0x7fff; - srp->ieee.mantissa0 = wrd2; - srp->ieee.mantissa1 = wrd3; #endif fpu_debug(("make_extended (%X,%X,%X) = %.04f\n",wrd1,wrd2,wrd3,(double)result)); } @@ -375,7 +386,25 @@ PRIVATE inline void FFPU extract_extende *wrd1 = *wrd2 = *wrd3 = 0; return; } -#ifndef USE_LONG_DOUBLE +#if USE_QUAD_DOUBLE + // FIXME: deal with denormals? + fp_declare_init_shape(srp, src, extended); + *wrd1 = (srp->ieee.negative << 31) | (srp->ieee.exponent << 16); + // always set the explicit integer bit. + *wrd2 = 0x80000000 | (srp->ieee.mantissa0 << 15) | ((srp->ieee.mantissa1 & 0xfffe0000) >> 17); + *wrd3 = (srp->ieee.mantissa1 << 15) | ((srp->ieee.mantissa2 & 0xfffe0000) >> 17); +#elif USE_LONG_DOUBLE + uae_u32 *p = (uae_u32 *)&src; +#ifdef WORDS_BIGENDIAN + *wrd1 = p[0]; + *wrd2 = p[1]; + *wrd3 = p[2]; +#else + *wrd3 = p[0]; + *wrd2 = p[1]; + *wrd1 = ( (uae_u32)*((uae_u16 *)&p[2]) ) << 16; +#endif +#else fp_declare_init_shape(srp, src, double); fpu_debug(("extract_extended (%d,%d,%X,%X)\n", srp->ieee.negative , srp->ieee.exponent, @@ -392,17 +421,6 @@ PRIVATE inline void FFPU extract_extende // always set the explicit integer bit. *wrd2 = 0x80000000 | (srp->ieee.mantissa0 << 11) | ((srp->ieee.mantissa1 & 0xffe00000) >> 21); *wrd3 = srp->ieee.mantissa1 << 11; -#else - // FIXME: USE_QUAD_DOUBLE -#ifdef WORDS_BIGENDIAN - *wrd1 = p[0]; - *wrd2 = p[1]; - *wrd3 = p[2]; -#else - *wrd3 = p[0]; - *wrd2 = p[1]; - *wrd1 = ( (uae_u32)*((uae_u16 *)&p[2]) ) << 16; -#endif #endif fpu_debug(("extract_extended (%.04f) = %X,%X,%X\n",(double)src,*wrd1,*wrd2,*wrd3)); } @@ -1608,21 +1626,21 @@ void FFPU fpuop_arithmetic(uae_u32 opcod FPU registers[reg] = 1.0e256; fpu_debug(("FP const: 1.0e256\n")); break; -#if USE_LONG_DOUBLE +#if USE_LONG_DOUBLE || USE_QUAD_DOUBLE case 0x3c: - FPU registers[reg] = 1.0e512; + FPU registers[reg] = 1.0e512L; fpu_debug(("FP const: 1.0e512\n")); break; case 0x3d: - FPU registers[reg] = 1.0e1024; + FPU registers[reg] = 1.0e1024L; fpu_debug(("FP const: 1.0e1024\n")); break; case 0x3e: - FPU registers[reg] = 1.0e2048; + FPU registers[reg] = 1.0e2048L; fpu_debug(("FP const: 1.0e2048\n")); break; case 0x3f: - FPU registers[reg] = 1.0e4096; + FPU registers[reg] = 1.0e4096L; fpu_debug(("FP const: 1.0e4096\n")); #endif break; @@ -1984,7 +2002,10 @@ void FFPU fpuop_arithmetic(uae_u32 opcod // an overflow or underflow always results. // Here (int) cast is okay. int scale_factor = (int)fp_round_to_zero(src); -#ifndef USE_LONG_DOUBLE +#if USE_LONG_DOUBLE || USE_QUAD_DOUBLE + fp_declare_init_shape(sxp, FPU registers[reg], extended); + sxp->ieee.exponent += scale_factor; +#else fp_declare_init_shape(sxp, FPU registers[reg], double); uae_u32 exp = sxp->ieee.exponent + scale_factor; if (exp < FP_EXTENDED_EXP_BIAS - FP_DOUBLE_EXP_BIAS) @@ -1994,9 +2015,6 @@ void FFPU fpuop_arithmetic(uae_u32 opcod else exp += FP_DOUBLE_EXP_BIAS - FP_EXTENDED_EXP_BIAS; sxp->ieee.exponent = exp; -#else - fp_declare_init_shape(sxp, FPU registers[reg], extended); - sxp->ieee.exponent += scale_factor; #endif } else if (fl_source.infinity) { @@ -2087,7 +2105,7 @@ PUBLIC void FFPU fpu_init (bool integral #if defined(FPU_USE_X86_ROUNDING) // Initial state after boot, reset and frestore(null frame) x86_control_word = CW_INITIAL; -#elif defined(__i386__) && defined(X86_ASSEMBLY) +#elif defined(USE_X87_ASSEMBLY) volatile unsigned short int cw; __asm__ __volatile__("fnstcw %0" : "=m" (cw)); cw &= ~0x0300; cw |= 0x0300; // CW_PC_EXTENDED