From: Toni Wilen Date: Tue, 8 Aug 2017 08:54:58 +0000 (+0300) Subject: FMOVECR undefined offset values are now 100% identical to real 68881/68882. Statesave... X-Git-Tag: 3600~132 X-Git-Url: https://git.unchartedbackwaters.co.uk/w/?a=commitdiff_plain;h=bdaf492f8a6496e4f2fed6a85ae2cc74fc6b0884;p=francis%2Fwinuae.git FMOVECR undefined offset values are now 100% identical to real 68881/68882. Statesave support updated. --- diff --git a/fpp.cpp b/fpp.cpp index a8ded4e6..2048f77c 100644 --- a/fpp.cpp +++ b/fpp.cpp @@ -185,24 +185,24 @@ static const struct fpp_cr_entry fpp_cr[22] = { #define FPP_CR_1E4096 21 struct fpp_cr_entry_undef { - uae_u8 constant; uae_u32 val[3]; }; +#define FPP_CR_NUM_SPECIAL_UNDEFINED 10 + // 68881 and 68882 have identical undefined fields static const struct fpp_cr_entry_undef fpp_cr_undef[] = { - { 0xff, {0x40000000, 0x00000000, 0x00000000} }, - { 0x01, {0x40010000, 0xfe000682, 0x00000000} }, - { 0x02, {0x40010000, 0xffc00503, 0x80000000} }, - { 0x03, {0x20000000, 0x7fffffff, 0x00000000} }, - { 0x04, {0x00000000, 0xffffffff, 0xffffffff} }, - { 0x05, {0x3c000000, 0xffffffff, 0xfffff800} }, - { 0x06, {0x3f800000, 0xffffff00, 0x00000000} }, - { 0x07, {0x00010000, 0xf65d8d9c, 0x00000000} }, - { 0x08, {0x7fff0000, 0x001e0000, 0x00000000} }, - { 0x09, {0x43ff0000, 0x000e0000, 0x00000000} }, - { 0x0a, {0x407f0000, 0x00060000, 0x00000000} }, - { 0x00 } + { {0x40000000, 0x00000000, 0x00000000} }, + { {0x40010000, 0xfe000682, 0x00000000} }, + { {0x40010000, 0xffc00503, 0x80000000} }, + { {0x20000000, 0x7fffffff, 0x00000000} }, + { {0x00000000, 0xffffffff, 0xffffffff} }, + { {0x3c000000, 0xffffffff, 0xfffff800} }, + { {0x3f800000, 0xffffff00, 0x00000000} }, + { {0x00010000, 0xf65d8d9c, 0x00000000} }, + { {0x7fff0000, 0x001e0000, 0x00000000} }, + { {0x43ff0000, 0x000e0000, 0x00000000} }, + { {0x407f0000, 0x00060000, 0x00000000} } }; uae_u32 xhex_nan[] ={0x7fff0000, 0xffffffff, 0xffffffff}; @@ -631,7 +631,7 @@ static void fpsr_get_quotient(uae_u64 *quot, uae_u8 *sign) uae_u32 fpp_get_fpsr (void) { #ifdef JIT - if (currprefs.compfpu) { + if (currprefs.cachesize && currprefs.compfpu) { regs.fpsr &= 0x00fffff8; // clear cc if (fpp_is_nan (®s.fp_result)) { regs.fpsr |= FPSR_CC_NAN; @@ -673,7 +673,7 @@ static void fpp_set_fpsr (uae_u32 val) #ifdef JIT // check comment in fpp_cond - if (currprefs.compfpu) { + if (currprefs.cachesize && currprefs.compfpu) { if (val & 0x01000000) fpnan(®s.fp_result); else if (val & 0x04000000) @@ -688,9 +688,14 @@ static void fpp_set_fpsr (uae_u32 val) bool fpu_get_constant(fpdata *fpd, int cr) { - uae_u32 f[3] = { 0, 0, }; + uae_u32 f[3] = { 0, 0, 0 }; int entry = -1; bool valid = true; + bool round = true; + int f1_adjust = 0; + uae_u32 sr = 0; + int mode = (regs.fpcr >> 4) & 3; + int prec = (regs.fpcr >> 6) & 3; switch (cr & 0x7f) { @@ -762,20 +767,51 @@ bool fpu_get_constant(fpdata *fpd, int cr) break; default: // undefined { + bool check_f1_adjust = false; const struct fpp_cr_entry_undef *fcr = fpp_cr_undef; cr &= 0x7f; - write_log (_T("Undocumented FPU constant access (index %02x)\n"), cr); - // Most undefined fields contain this - f[0] = fcr[0].val[0]; - f[1] = fcr[0].val[1]; - f[2] = fcr[0].val[2]; - // Other undefined fields - for (int i = 1; fcr[i].constant; i++) { - if (fcr[i].constant == cr) { - f[0] = fcr[i].val[0]; - f[1] = fcr[i].val[1]; - f[2] = fcr[i].val[2]; - break; + if (cr > FPP_CR_NUM_SPECIAL_UNDEFINED) { + // Most undefined fields contain this + cr = 0; + // Do not round or normalize + round = false; + // Zero + sr |= FPSR_CC_Z; + } + f[0] = fcr[cr].val[0]; + f[1] = fcr[cr].val[1]; + f[2] = fcr[cr].val[2]; + // Rounding mode and precision works very strangely here.. + switch (cr) + { + case 1: + check_f1_adjust = true; + break; + case 2: + if (prec == 1 && mode == 3) + f1_adjust = -1; + break; + case 3: + if (prec == 1 && (mode == 0 || mode == 3)) + sr |= FPSR_CC_I; + else + sr |= FPSR_CC_NAN; + break; + case 7: + sr |= FPSR_CC_NAN; + check_f1_adjust = true; + break; + case 8: + round = false; + break; + } + if (check_f1_adjust) { + if (prec == 1) { + if (mode == 0) { + f1_adjust = -1; + } else if (mode == 1 || mode == 2) { + f1_adjust = 1; + } } } valid = false; @@ -791,18 +827,27 @@ bool fpu_get_constant(fpdata *fpd, int cr) // note: with valid constants, LSB never wraps if (fpp_cr[entry].inexact) { fpsr_set_exception(FPSR_INEX2); - f[2] += fpp_cr[entry].rndoff[(regs.fpcr >> 4) & 3]; + f[2] += fpp_cr[entry].rndoff[mode]; } } fpp_to_exten_fmovem(fpd, f[0], f[1], f[2]); - if (((regs.fpcr >> 6) & 3) == 1) - fpp_round32(fpd); - if (((regs.fpcr >> 6) & 3) >= 2) - fpp_round64(fpd); + if (round) { + if (((regs.fpcr >> 6) & 3) == 1) + fpp_round32(fpd); + if (((regs.fpcr >> 6) & 3) >= 2) + fpp_round64(fpd); + } + if (f1_adjust) { + fpp_from_exten_fmovem(fpd, &f[0], &f[1], &f[2]); + f[1] += f1_adjust * 0x80; + fpp_to_exten_fmovem(fpd, f[0], f[1], f[2]); + } + fpsr_set_result(fpd); + regs.fpsr |= sr; return valid; } @@ -1690,7 +1735,7 @@ int fpp_cond (int condition) int NotANumber, N, Z; #ifdef JIT - if (currprefs.compfpu) { + if (currprefs.cachesize && currprefs.compfpu) { // JIT reads and writes regs.fpu_result NotANumber = fpp_is_nan(®s.fp_result); N = fpp_is_neg(®s.fp_result); @@ -3102,33 +3147,53 @@ uae_u8 *restore_fpu (uae_u8 *src) restore_u32 (); restore_u32 (); } - if (flags & 0x40000000) { - w1 = restore_u16() << 16; - w2 = restore_u32(); - w3 = restore_u32(); - //fpp_to_exten_fmovem(&fsave_data.src, w1, w2, w3); - w1 = restore_u16() << 16; - w2 = restore_u32(); - w3 = restore_u32(); - //fpp_to_exten_fmovem(&fsave_data.dst, w1, w2, w3); - restore_u32(); // fsave_data.pack[0] = restore_u32(); - restore_u32(); // fsave_data.pack[1] = restore_u32(); - restore_u32(); // fsave_data.pack[2] = restore_u32(); - restore_u16(); // fsave_data.opcode = restore_u16(); - restore_u16(); // fsave_data.extra = restore_u16(); - restore_u16(); //fsave_data.type = restore_u16(); - } - regs.fpu_state = (flags & 1) ? 0 : 1; - regs.fpu_exp_state = (flags & 2) ? 1 : 0; - if (flags & 4) - regs.fpu_exp_state = 2; + if (flags & 0x20000000) { + uae_u32 v = restore_u32(); + regs.fpu_state = (v >> 0) & 15; + regs.fpu_exp_state = (v >> 4) & 15; + regs.fp_unimp_pend = (v >> 8) & 15; + regs.fp_exp_pend = (v >> 16) & 0xff; + regs.fp_opword = restore_u16(); + regs.fp_ea = restore_u32(); + if (currprefs.fpu_model == 68060 || currprefs.fpu_model >= 68881) { + fsave_data.ccr = restore_u32(); + fsave_data.eo[0] = restore_u32(); + fsave_data.eo[1] = restore_u32(); + fsave_data.eo[2] = restore_u32(); + } + if (currprefs.fpu_model == 68060) { + fsave_data.v = restore_u32(); + } + if (currprefs.fpu_model == 68040) { + fsave_data.fpiarcu = restore_u32(); + fsave_data.cmdreg3b = restore_u32(); + fsave_data.cmdreg1b = restore_u32(); + fsave_data.stag = restore_u32(); + fsave_data.dtag = restore_u32(); + fsave_data.e1 = restore_u32(); + fsave_data.e3 = restore_u32(); + fsave_data.t = restore_u32(); + fsave_data.fpt[0] = restore_u32(); + fsave_data.fpt[1] = restore_u32(); + fsave_data.fpt[2] = restore_u32(); + fsave_data.et[0] = restore_u32(); + fsave_data.et[1] = restore_u32(); + fsave_data.et[2] = restore_u32(); + fsave_data.wbt[0] = restore_u32(); + fsave_data.wbt[1] = restore_u32(); + fsave_data.wbt[2] = restore_u32(); + fsave_data.grs = restore_u32(); + fsave_data.wbte15 = restore_u32(); + fsave_data.wbtm66 = restore_u32(); + } + } write_log(_T("FPU: %d\n"), currprefs.fpu_model); return src; } uae_u8 *save_fpu (int *len, uae_u8 *dstptr) { - uae_u32 w1, w2, w3; + uae_u32 w1, w2, w3, v; uae_u8 *dstbak, *dst; int i; @@ -3140,7 +3205,7 @@ uae_u8 *save_fpu (int *len, uae_u8 *dstptr) else dstbak = dst = xmalloc (uae_u8, 4+4+8*10+4+4+4+4+4+2*10+3*(4+2)); save_u32 (currprefs.fpu_model); - save_u32 (0x80000000 | 0x40000000 | (regs.fpu_state == 0 ? 1 : 0) | (regs.fpu_exp_state ? 2 : 0) | (regs.fpu_exp_state > 1 ? 4 : 0)); + save_u32 (0x80000000 | 0x20000000); for (i = 0; i < 8; i++) { fpp_from_exten_fmovem(®s.fp[i], &w1, &w2, &w3); save_u16 (w1 >> 16); @@ -3152,26 +3217,48 @@ uae_u8 *save_fpu (int *len, uae_u8 *dstptr) save_u32 (regs.fpiar); save_u32 (-1); - save_u32 (0); - - w1 = w2 = w3 = 0; - //fpp_from_exten_fmovem(&fsave_data.src, &w1, &w2, &w3); - save_u16(w1 >> 16); - save_u32(w2); - save_u32(w3); - //fpp_from_exten_fmovem(&fsave_data.dst, &w1, &w2, &w3); - save_u16(w1 >> 16); - save_u32(w2); - save_u32(w3); - save_u32(0); // save_u32(fsave_data.pack[0]); - save_u32(0); // save_u32(fsave_data.pack[1]); - save_u32(0); // save_u32(fsave_data.pack[2]); - save_u16(0); // save_u16(fsave_data.opcode); - save_u16(0); // save_u16(fsave_data.extra); - save_u16(0); //fsave_data.exp_type); + save_u32 (1); + + v = regs.fpu_state; + v |= regs.fpu_exp_state << 4; + v |= regs.fp_unimp_pend << 8; + v |= regs.fp_exp_pend << 16; + save_u32(v); + save_u16(regs.fp_opword); + save_u32(regs.fp_ea); + + if (currprefs.fpu_model == 68060 || currprefs.fpu_model >= 68881) { + save_u32(fsave_data.ccr); + save_u32(fsave_data.eo[0]); + save_u32(fsave_data.eo[1]); + save_u32(fsave_data.eo[2]); + } + if (currprefs.fpu_model == 68060) { + save_u32(fsave_data.v); + } + if (currprefs.fpu_model == 68040) { + save_u32(fsave_data.fpiarcu); + save_u32(fsave_data.cmdreg3b); + save_u32(fsave_data.cmdreg1b); + save_u32(fsave_data.stag); + save_u32(fsave_data.dtag); + save_u32(fsave_data.e1); + save_u32(fsave_data.e3); + save_u32(fsave_data.t); + save_u32(fsave_data.fpt[0]); + save_u32(fsave_data.fpt[1]); + save_u32(fsave_data.fpt[2]); + save_u32(fsave_data.et[0]); + save_u32(fsave_data.et[1]); + save_u32(fsave_data.et[2]); + save_u32(fsave_data.wbt[0]); + save_u32(fsave_data.wbt[1]); + save_u32(fsave_data.wbt[2]); + save_u32(fsave_data.grs); + save_u32(fsave_data.wbte15); + save_u32(fsave_data.wbtm66); + } *len = dst - dstbak; return dstbak; } - -