--- BasiliskII/src/uae_cpu/fpp.cpp 1999/10/27 16:59:54 1.2 +++ BasiliskII/src/uae_cpu/fpp.cpp 1999/10/31 23:18:38 1.6 @@ -71,6 +71,7 @@ #include "memory.h" #include "readcpu.h" #include "newcpu.h" +#include "main.h" #define DEBUG 0 #include "debug.h" @@ -79,6 +80,14 @@ // Only define if you have IEEE 64 bit doubles. #define HAVE_IEEE_DOUBLE 1 +#ifdef WORDS_BIGENDIAN +#define FLO 1 +#define FHI 0 +#else +#define FLO 0 +#define FHI 1 +#endif + // fpcr rounding modes #define ROUND_TO_NEAREST 0 #define ROUND_TO_ZERO 0x10 @@ -173,9 +182,9 @@ double_flags fl_dest, fl_source; static __inline__ uae_u32 IS_NAN(uae_u32 *p) { - if( (p[1] & 0x7FF00000) == 0x7FF00000 ) { + if( (p[FHI] & 0x7FF00000) == 0x7FF00000 ) { // logical or is faster here. - if( (p[1] & 0x000FFFFF) || p[0] ) { + if( (p[FHI] & 0x000FFFFF) || p[FLO] ) { return(1); } } @@ -184,7 +193,7 @@ static __inline__ uae_u32 IS_NAN(uae_u32 static __inline__ uae_u32 IS_INFINITY(uae_u32 *p) { - if( ((p[1] & 0x7FF00000) == 0x7FF00000) && p[0] == 0 ) { + if( ((p[FHI] & 0x7FF00000) == 0x7FF00000) && p[FLO] == 0 ) { return(1); } return(0); @@ -192,12 +201,12 @@ static __inline__ uae_u32 IS_INFINITY(ua static __inline__ uae_u32 IS_NEGATIVE(uae_u32 *p) { - return( (p[1] & 0x80000000) != 0 ); + return( (p[FHI] & 0x80000000) != 0 ); } static __inline__ uae_u32 IS_ZERO(uae_u32 *p) { - return( ((p[1] & 0x7FF00000) == 0) && p[0] == 0 ); + return( ((p[FHI] & 0x7FF00000) == 0) && p[FLO] == 0 ); } // This should not touch the quotient. @@ -236,67 +245,67 @@ static __inline__ void GET_SOURCE_FLAGS( static __inline__ void MAKE_NAN(uae_u32 *p) { - p[0] = 0xFFFFFFFF; - p[1] = 0x7FFFFFFF; + p[FLO] = 0xFFFFFFFF; + p[FHI] = 0x7FFFFFFF; } static __inline__ void MAKE_ZERO_POSITIVE(uae_u32 *p) { - p[0] = p[1] = 0; + p[FLO] = p[FHI] = 0; } static __inline__ void MAKE_ZERO_NEGATIVE(uae_u32 *p) { - p[0] = 0; - p[1] = 0x80000000; + p[FLO] = 0; + p[FHI] = 0x80000000; } static __inline__ void MAKE_INF_POSITIVE(uae_u32 *p) { - p[0] = 0; - p[1] = 0x7FF00000; + p[FLO] = 0; + p[FHI] = 0x7FF00000; } static __inline__ void MAKE_INF_NEGATIVE(uae_u32 *p) { - p[0] = 0; - p[1] = 0xFFF00000; + p[FLO] = 0; + p[FHI] = 0xFFF00000; } static __inline__ void FAST_SCALE(uae_u32 *p, int add) { int exp; - exp = (p[1] & 0x7FF00000) >> 20; + exp = (p[FHI] & 0x7FF00000) >> 20; // TODO: overflow flags exp += add; if(exp >= 2047) { MAKE_INF_POSITIVE(p); } else if(exp < 0) { // keep sign (+/- 0) - p[1] &= 0x80000000; + p[FHI] &= 0x80000000; } else { - p[1] = (p[1] & 0x800FFFFF) | ((uae_u32)exp << 20); + p[FHI] = (p[FHI] & 0x800FFFFF) | ((uae_u32)exp << 20); } } static __inline__ double FAST_FGETEXP(uae_u32 *p) { - int exp = (p[1] & 0x7FF00000) >> 20; + int exp = (p[FHI] & 0x7FF00000) >> 20; return( exp - 1023 ); } // Normalize to range 1..2 static __inline__ void FAST_REMOVE_EXPONENT(uae_u32 *p) { - p[1] = (p[1] & 0x800FFFFF) | 0x3FF00000; + p[FHI] = (p[FHI] & 0x800FFFFF) | 0x3FF00000; } // The sign of the quotient is the exclusive-OR of the sign bits // of the source and destination operands. static __inline__ uae_u32 GET_QUOTIENT_SIGN(uae_u32 *a, uae_u32 *b) { - return( ((a[1] ^ b[1]) & 0x80000000) ? 0x800000 : 0); + return( ((a[FHI] ^ b[FHI]) & 0x80000000) ? 0x800000 : 0); } // Quotient Byte is loaded with the sign and least significant @@ -319,8 +328,8 @@ static __inline__ double to_single (uae_ uae_u32 sign = (value & 0x80000000); uae_u32 exp = ((value & 0x7F800000) >> 23) + 1023 - 127; - p[0] = value << 29; - p[1] = sign | (exp << 20) | ((value & 0x007FFFFF) >> 3); + p[FLO] = value << 29; + p[FHI] = sign | (exp << 20) | ((value & 0x007FFFFF) >> 3); D(bug("to_single (%X) = %.04f\r\n",value,(float)result)); @@ -334,8 +343,8 @@ static __inline__ uae_u32 from_single (d if (src == 0.0) return 0; - uae_u32 sign = (p[1] & 0x80000000); - uae_u32 exp = (p[1] & 0x7FF00000) >> 20; + uae_u32 sign = (p[FHI] & 0x80000000); + uae_u32 exp = (p[FHI] & 0x7FF00000) >> 20; if(exp + 127 < 1023) { exp = 0; @@ -345,7 +354,7 @@ static __inline__ uae_u32 from_single (d exp = exp + 127 - 1023; } - result = sign | (exp << 23) | ((p[1] & 0x000FFFFF) << 3) | (p[0] >> 29); + result = sign | (exp << 23) | ((p[FHI] & 0x000FFFFF) << 3) | (p[FLO] >> 29); D(bug("from_single (%.04f) = %X\r\n",(float)src,result)); @@ -368,7 +377,7 @@ static __inline__ double to_exten(uae_u3 if( wrd2 | wrd3 ) { // mantissa, not fraction. uae_u64 man = ((uae_u64)wrd2 << 32) | wrd3; - while( (man & 0x8000000000000000LL) == 0 ) { + while( (man & UVAL64(0x8000000000000000)) == 0 ) { man <<= 1; exp--; } @@ -395,8 +404,8 @@ static __inline__ double to_exten(uae_u3 } // drop the explicit integer bit. - p[0] = (wrd2 << 21) | (wrd3 >> 11); - p[1] = sign | (exp << 20) | ((wrd2 & 0x7FFFFFFF) >> 11); + p[FLO] = (wrd2 << 21) | (wrd3 >> 11); + p[FHI] = sign | (exp << 20) | ((wrd2 & 0x7FFFFFFF) >> 11); D(bug("to_exten (%X,%X,%X) = %.04f\r\n",wrd1,wrd2,wrd3,(float)result)); @@ -412,11 +421,11 @@ static __inline__ void from_exten(double return; } - D(bug("from_exten (%X,%X)\r\n",p[0],p[1])); + D(bug("from_exten (%X,%X)\r\n",p[FLO],p[FHI])); - uae_u32 sign = p[1] & 0x80000000; + uae_u32 sign = p[FHI] & 0x80000000; - uae_u32 exp = ((p[1] >> 20) & 0x7ff); + uae_u32 exp = ((p[FHI] >> 20) & 0x7ff); // Check for maximum if(exp == 0x7FF) { exp = 0x7FFF; @@ -426,8 +435,8 @@ static __inline__ void from_exten(double *wrd1 = sign | (exp << 16); // always set the explicit integer bit. - *wrd2 = 0x80000000 | ((p[1] & 0x000FFFFF) << 11) | ((p[0] & 0xFFE00000) >> 21); - *wrd3 = p[0] << 11; + *wrd2 = 0x80000000 | ((p[FHI] & 0x000FFFFF) << 11) | ((p[FLO] & 0xFFE00000) >> 21); + *wrd3 = p[FLO] << 11; D(bug("from_exten (%.04f) = %X,%X,%X\r\n",(float)src,*wrd1,*wrd2,*wrd3)); } @@ -440,8 +449,8 @@ static __inline__ double to_double(uae_u if ((wrd1 & 0x7fffffff) == 0 && wrd2 == 0) return 0.0; p = (uae_u32 *)&result; - p[0] = wrd2; - p[1] = wrd1; + p[FLO] = wrd2; + p[FHI] = wrd1; D(bug("to_double (%X,%X) = %.04f\r\n",wrd1,wrd2,(float)result)); @@ -455,8 +464,8 @@ static __inline__ void from_double(doubl return; } uae_u32 *p = (uae_u32 *)&src; - *wrd2 = p[0]; - *wrd1 = p[1]; + *wrd2 = p[FLO]; + *wrd1 = p[FHI]; D(bug("from_double (%.04f) = %X,%X\r\n",(float)src,*wrd1,*wrd2)); } @@ -1226,31 +1235,40 @@ void fsave_opp(uae_u32 opcode) return; } - // Put 28 byte IDLE frame. - // NOTE!!! IDLE frame is only 4 bytes on a 68040!! - - if (incr < 0) { - D(bug("fsave_opp pre-decrement\r\n")); - ad -= 4; - // What's this? Some BIU flags, or (incorrectly placed) command/condition? - put_long (ad, 0x70000000); - for (i = 0; i < 5; i++) { - ad -= 4; - put_long (ad, 0x00000000); - } - ad -= 4; - put_long (ad, 0x1f180000); // IDLE, vers 1f - } else { - put_long (ad, 0x1f180000); // IDLE, vers 1f - ad += 4; - for (i = 0; i < 5; i++) { - put_long (ad, 0x00000000); - ad += 4; + if (CPUType == 4) { + // Put 4 byte 68040 IDLE frame. + if (incr < 0) { + ad -= 4; + put_long (ad, 0x41000000); + } else { + put_long (ad, 0x41000000); + ad += 4; } - // What's this? Some BIU flags, or (incorrectly placed) command/condition? - put_long (ad, 0x70000000); - ad += 4; - } + } else { + // Put 28 byte 68881 IDLE frame. + if (incr < 0) { + D(bug("fsave_opp pre-decrement\r\n")); + ad -= 4; + // What's this? Some BIU flags, or (incorrectly placed) command/condition? + put_long (ad, 0x70000000); + for (i = 0; i < 5; i++) { + ad -= 4; + put_long (ad, 0x00000000); + } + ad -= 4; + put_long (ad, 0x1f180000); // IDLE, vers 1f + } else { + put_long (ad, 0x1f180000); // IDLE, vers 1f + ad += 4; + for (i = 0; i < 5; i++) { + put_long (ad, 0x00000000); + ad += 4; + } + // What's this? Some BIU flags, or (incorrectly placed) command/condition? + put_long (ad, 0x70000000); + ad += 4; + } + } if ((opcode & 0x38) == 0x18) { m68k_areg (regs, opcode & 7) = ad; // Never executed on a 68881 D(bug("PROBLEM: fsave_opp post-increment\r\n")); @@ -1261,7 +1279,7 @@ void fsave_opp(uae_u32 opcode) } } -// FSAVE has no pre-decrement +// FRESTORE has no pre-decrement void frestore_opp(uae_u32 opcode) { uae_u32 ad; @@ -1276,37 +1294,70 @@ void frestore_opp(uae_u32 opcode) return; } - if (incr < 0) { - - D(bug("PROBLEM: frestore_opp incr < 0\r\n")); - - // this may be wrong, but it's never called. - ad -= 4; - d = get_long (ad); - if ((d & 0xff000000) != 0) { - if ((d & 0x00ff0000) == 0x00180000) - ad -= 6 * 4; - else if ((d & 0x00ff0000) == 0x00380000) - ad -= 14 * 4; - else if ((d & 0x00ff0000) == 0x00b40000) - ad -= 45 * 4; + if (CPUType == 4) { + // 68040 + if (incr < 0) { + D(bug("PROBLEM: frestore_opp incr < 0\r\n")); + // this may be wrong, but it's never called. + ad -= 4; + d = get_long (ad); + if ((d & 0xff000000) != 0) { // Not a NULL frame? + if ((d & 0x00ff0000) == 0) { // IDLE + D(bug("frestore_opp found IDLE frame at %X\r\n",ad-4)); + } else if ((d & 0x00ff0000) == 0x00300000) { // UNIMP + D(bug("PROBLEM: frestore_opp found UNIMP frame at %X\r\n",ad-4)); + ad -= 44; + } else if ((d & 0x00ff0000) == 0x00600000) { // BUSY + D(bug("PROBLEM: frestore_opp found BUSY frame at %X\r\n",ad-4)); + ad -= 92; + } + } + } else { + d = get_long (ad); + D(bug("frestore_opp frame at %X = %X\r\n",ad,d)); + ad += 4; + if ((d & 0xff000000) != 0) { // Not a NULL frame? + if ((d & 0x00ff0000) == 0) { // IDLE + D(bug("frestore_opp found IDLE frame at %X\r\n",ad-4)); + } else if ((d & 0x00ff0000) == 0x00300000) { // UNIMP + D(bug("PROBLEM: frestore_opp found UNIMP frame at %X\r\n",ad-4)); + ad += 44; + } else if ((d & 0x00ff0000) == 0x00600000) { // BUSY + D(bug("PROBLEM: frestore_opp found BUSY frame at %X\r\n",ad-4)); + ad += 92; + } + } } - } else { - d = get_long (ad); - - D(bug("frestore_opp frame at %X = %X\r\n",ad,d)); - - ad += 4; - if ((d & 0xff000000) != 0) { // Not a NULL frame? - if ((d & 0x00ff0000) == 0x00180000) { // IDLE - D(bug("frestore_opp found IDLE frame at %X\r\n",ad-4)); - ad += 6 * 4; - } else if ((d & 0x00ff0000) == 0x00380000) {// UNIMP? shouldn't it be 3C? - ad += 14 * 4; - D(bug("PROBLEM: frestore_opp found UNIMP? frame at %X\r\n",ad-4)); - } else if ((d & 0x00ff0000) == 0x00b40000) {// BUSY - D(bug("PROBLEM: frestore_opp found BUSY frame at %X\r\n",ad-4)); - ad += 45 * 4; + } else { + // 68881 + if (incr < 0) { + D(bug("PROBLEM: frestore_opp incr < 0\r\n")); + // this may be wrong, but it's never called. + ad -= 4; + d = get_long (ad); + if ((d & 0xff000000) != 0) { + if ((d & 0x00ff0000) == 0x00180000) + ad -= 6 * 4; + else if ((d & 0x00ff0000) == 0x00380000) + ad -= 14 * 4; + else if ((d & 0x00ff0000) == 0x00b40000) + ad -= 45 * 4; + } + } else { + d = get_long (ad); + D(bug("frestore_opp frame at %X = %X\r\n",ad,d)); + ad += 4; + if ((d & 0xff000000) != 0) { // Not a NULL frame? + if ((d & 0x00ff0000) == 0x00180000) { // IDLE + D(bug("frestore_opp found IDLE frame at %X\r\n",ad-4)); + ad += 6 * 4; + } else if ((d & 0x00ff0000) == 0x00380000) {// UNIMP? shouldn't it be 3C? + ad += 14 * 4; + D(bug("PROBLEM: frestore_opp found UNIMP? frame at %X\r\n",ad-4)); + } else if ((d & 0x00ff0000) == 0x00b40000) {// BUSY + D(bug("PROBLEM: frestore_opp found BUSY frame at %X\r\n",ad-4)); + ad += 45 * 4; + } } } } @@ -2022,6 +2073,7 @@ void fpp_opp(uae_u32 opcode, uae_u16 ext break; case 0x23: /* FMUL */ D(bug("FMUL %.04f\r\n",(float)src)); +#if HAVE_IEEE_DOUBLE GET_DEST_FLAGS((uae_u32 *)®s.fp[reg]); GET_SOURCE_FLAGS((uae_u32 *)&src); if(fl_dest.in_range && fl_source.in_range) { @@ -2048,6 +2100,10 @@ void fpp_opp(uae_u32 opcode, uae_u16 ext MAKE_INF_POSITIVE((uae_u32 *)®s.fp[reg]); } } +#else + D(bug("FMUL %.04f\r\n",(float)src)); + regs.fp[reg] *= src; +#endif MAKE_FPSR(regs.fpsr,regs.fp[reg]); break; case 0x24: /* FSGLDIV */