From ba3c65ace71aab5e60c8fd9e011c028a0b69abae Mon Sep 17 00:00:00 2001 From: Dimitris Panokostas Date: Mon, 3 Dec 2018 00:52:36 +0100 Subject: [PATCH] Minor FPU improvements --- src/fpp.cpp | 302 ++++++++++++++++++++---------------------- src/fpp_native.cpp | 116 ++++++++-------- src/include/fpp.h | 5 + src/include/newcpu.h | 33 +++-- src/newcpu.cpp | 85 ++++++------ src/newcpu_common.cpp | 6 +- 6 files changed, 280 insertions(+), 267 deletions(-) diff --git a/src/fpp.cpp b/src/fpp.cpp index d94b29b6..dd2d1135 100644 --- a/src/fpp.cpp +++ b/src/fpp.cpp @@ -27,18 +27,10 @@ #include "savestate.h" #include "cpu_prefetch.h" -void fpsr_set_exception(uae_u32 exception); +static void fpsr_set_exception(uae_u32 exception); #include "fpp_native.cpp" -#define DEBUG_FPP 0 -#define EXCEPTION_FPP 0 - -STATIC_INLINE int isinrom (void) -{ - return (munge24 (m68k_getpc ()) & 0xFFF80000) == 0xF80000; -} - struct fpp_cr_entry { uae_u32 val[3]; uae_u8 inexact; @@ -116,6 +108,8 @@ static const struct fpp_cr_entry_undef fpp_cr_undef[] = { uae_u32 xhex_nan[] ={0x7fff0000, 0xffffffff, 0xffffffff}; +static bool fpu_mmu_fixup; + /* Floating Point Control Register (FPCR) * * Exception Enable Byte @@ -266,7 +260,7 @@ static void fp_unimp_instruction_exception_pending(void) } } -void fpsr_set_exception(uae_u32 exception) +static void fpsr_set_exception(uae_u32 exception) { regs.fpsr |= exception; } @@ -360,7 +354,12 @@ static uae_u32 fpp_get_fpsr (void) regs.fpsr |= FPSR_CC_N; } #endif - return regs.fpsr; + return regs.fpsr & 0x0ffffff8; +} + +static uae_u32 fpp_get_fpcr(void) +{ + return regs.fpcr & (currprefs.fpu_model == 68040 ? 0xffff : 0xfff0); } static void fpp_set_fpcr (uae_u32 val) @@ -374,10 +373,6 @@ static void fpnan (fpdata *fpd) fpp_to_exten(fpd, xhex_nan[0], xhex_nan[1], xhex_nan[2]); } -static void fpclear (fpdata *fpd) -{ - fpp_from_int(fpd, 0); -} static void fpset (fpdata *fpd, uae_s32 val) { fpp_from_int(fpd, val); @@ -599,7 +594,6 @@ static void fp_unimp_datatype(uae_u16 opcode, uae_u16 extra, uae_u32 ea, uaecptr uae_u32 size = (extra >> 10) & 7; uae_u32 opclass = (extra >> 13) & 7; - regs.fp_opword = opcode; regs.fp_ea = ea; regs.fp_unimp_pend = packed ? 2 : 1; @@ -661,9 +655,6 @@ static void fpu_op_illg(uae_u16 opcode, uae_u32 ea, uaecptr oldpc) static void fpu_noinst (uae_u16 opcode, uaecptr pc) { -#if EXCEPTION_FPP - write_log (_T("Unknown FPU instruction %04X %08X\n"), opcode, pc); -#endif regs.fp_exception = true; m68k_setpc (pc); op_illg (opcode); @@ -677,9 +668,10 @@ static bool if_no_fpu(void) static bool fault_if_no_fpu (uae_u16 opcode, uae_u16 extra, uaecptr ea, uaecptr oldpc) { if (if_no_fpu()) { -#if EXCEPTION_FPP - write_log (_T("no FPU: %04X-%04X PC=%08X\n"), opcode, extra, oldpc); -#endif + if (fpu_mmu_fixup) { + m68k_areg (regs, mmufixup[0].reg) = mmufixup[0].value; + mmufixup[0].reg = -1; + } fpu_op_illg(opcode, ea, oldpc); return true; } @@ -807,15 +799,14 @@ static bool fault_if_unimplemented_6888x (uae_u16 opcode, uae_u16 extra, uaecptr static bool fault_if_no_fpu_u (uae_u16 opcode, uae_u16 extra, uaecptr ea, uaecptr oldpc) { - return fault_if_no_fpu (opcode, extra, ea, oldpc); + if (fault_if_no_fpu (opcode, extra, ea, oldpc)) + return true; + return false; } static bool fault_if_no_6888x (uae_u16 opcode, uae_u16 extra, uaecptr oldpc) { if (currprefs.cpu_model < 68040 && currprefs.fpu_model <= 0) { -#if EXCEPTION_FPP - write_log (_T("6888x no FPU: %04X-%04X PC=%08X\n"), opcode, extra, oldpc); -#endif m68k_setpc (oldpc); regs.fp_exception = true; op_illg (opcode); @@ -882,7 +873,7 @@ static int get_fp_value (uae_u32 opcode, uae_u16 extra, fpdata *src, uaecptr old size = (extra >> 10) & 7; switch (mode) { - case 0: + case 0: // Dn if ((size == 0 || size == 1 ||size == 4 || size == 6) && fault_if_no_fpu (opcode, extra, 0, oldpc)) return -1; switch (size) @@ -903,23 +894,31 @@ static int get_fp_value (uae_u32 opcode, uae_u16 extra, fpdata *src, uaecptr old return 0; } return 1; - case 1: + case 1: // An return 0; - case 2: + case 2: // (An) ad = m68k_areg (regs, reg); break; - case 3: + case 3: // (An)+ + // Also needed by fault_if_no_fpu + mmufixup[0].reg = reg; + mmufixup[0].value = m68k_areg (regs, reg); + fpu_mmu_fixup = true; ad = m68k_areg (regs, reg); m68k_areg (regs, reg) += reg == 7 ? sz2[size] : sz1[size]; break; - case 4: + case 4: // -(An) + // Also needed by fault_if_no_fpu + mmufixup[0].reg = reg; + mmufixup[0].value = m68k_areg (regs, reg); + fpu_mmu_fixup = true; m68k_areg (regs, reg) -= reg == 7 ? sz2[size] : sz1[size]; ad = m68k_areg (regs, reg); break; - case 5: + case 5: // (d16,An) ad = m68k_areg (regs, reg) + (uae_s32) (uae_s16) x_cp_next_iword (); break; - case 6: + case 6: // (d8,An,Xn)+ ad = x_cp_get_disp_ea_020 (m68k_areg (regs, reg), 0); break; case 7: @@ -977,13 +976,13 @@ static int get_fp_value (uae_u32 opcode, uae_u16 extra, fpdata *src, uaecptr old switch (size) { - case 0: + case 0: // L fpset(src, (uae_s32) (doext ? exts[0] : x_cp_get_long (ad))); break; - case 1: + case 1: // S fpp_to_single (src, (doext ? exts[0] : x_cp_get_long (ad))); break; - case 2: + case 2: // X { uae_u32 wrd1, wrd2, wrd3; wrd1 = (doext ? exts[0] : x_cp_get_long (ad)); @@ -994,7 +993,7 @@ static int get_fp_value (uae_u32 opcode, uae_u16 extra, fpdata *src, uaecptr old fpp_to_exten (src, wrd1, wrd2, wrd3); } break; - case 3: + case 3: // P { uae_u32 wrd[3]; wrd[0] = (doext ? exts[0] : x_cp_get_long (ad)); @@ -1008,10 +1007,10 @@ static int get_fp_value (uae_u32 opcode, uae_u16 extra, fpdata *src, uaecptr old return 1; } break; - case 4: + case 4: // W fpset(src, (uae_s16) (doext ? exts[0] : x_cp_get_word (ad))); break; - case 5: + case 5: // D { uae_u32 wrd1, wrd2; wrd1 = (doext ? exts[0] : x_cp_get_long (ad)); @@ -1020,7 +1019,7 @@ static int get_fp_value (uae_u32 opcode, uae_u16 extra, fpdata *src, uaecptr old fpp_to_double (src, wrd1, wrd2); } break; - case 6: + case 6: // B fpset(src, (uae_s8) (doext ? exts[0] : x_cp_get_byte (ad))); break; default: @@ -1036,74 +1035,72 @@ static int put_fp_value (fpdata *value, uae_u32 opcode, uae_u16 extra, uaecptr o static const int sz1[8] = { 4, 4, 12, 12, 2, 8, 1, 0 }; static const int sz2[8] = { 4, 4, 12, 12, 2, 8, 2, 0 }; -#if DEBUG_FPP - if (!isinrom ()) - write_log (_T("PUTFP: %04X %04X\n"), opcode, extra); -#endif reg = opcode & 7; mode = (opcode >> 3) & 7; size = (extra >> 10) & 7; switch (mode) { - case 0: + case 0: // Dn if ((size == 0 || size == 1 ||size == 4 || size == 6) && fault_if_no_fpu (opcode, extra, 0, oldpc)) return -1; switch (size) { - case 6: + case 6: // B m68k_dreg (regs, reg) = (uae_u32)(((fpp_to_int (value, 0) & 0xff) | (m68k_dreg (regs, reg) & ~0xff))); break; - case 4: + case 4: // W m68k_dreg (regs, reg) = (uae_u32)(((fpp_to_int (value, 1) & 0xffff) | (m68k_dreg (regs, reg) & ~0xffff))); break; - case 0: + case 0: // L m68k_dreg (regs, reg) = (uae_u32)fpp_to_int (value, 2); break; - case 1: + case 1: // S m68k_dreg (regs, reg) = fpp_from_single (value); break; default: return 0; } return 1; - case 1: + case 1: // An return 0; - case 2: + case 2: // (An) ad = m68k_areg (regs, reg); break; - case 3: + case 3: // (An)+ + // Also needed by fault_if_no_fpu + mmufixup[0].reg = reg; + mmufixup[0].value = m68k_areg (regs, reg); + fpu_mmu_fixup = true; ad = m68k_areg (regs, reg); m68k_areg (regs, reg) += reg == 7 ? sz2[size] : sz1[size]; break; - case 4: + case 4: // -(An) + // Also needed by fault_if_no_fpu + mmufixup[0].reg = reg; + mmufixup[0].value = m68k_areg (regs, reg); + fpu_mmu_fixup = true; m68k_areg (regs, reg) -= reg == 7 ? sz2[size] : sz1[size]; ad = m68k_areg (regs, reg); break; - case 5: + case 5: // (d16,An) ad = m68k_areg (regs, reg) + (uae_s32) (uae_s16) x_cp_next_iword (); break; - case 6: + case 6: // (d8,An,Xn)+ ad = x_cp_get_disp_ea_020 (m68k_areg (regs, reg), 0); break; case 7: switch (reg) { - case 0: + case 0: // (xxx).W ad = (uae_s32) (uae_s16) x_cp_next_iword (); break; - case 1: + case 1: // (xxx).L ad = x_cp_next_ilong (); break; - case 2: - ad = m68k_getpc (); - ad += (uae_s32) (uae_s16) x_cp_next_iword (); - break; - case 3: - ad = x_cp_get_disp_ea_020 (m68k_getpc (), 0); - break; + // Immediate and PC-relative modes are not supported default: return 0; } @@ -1116,13 +1113,13 @@ static int put_fp_value (fpdata *value, uae_u32 opcode, uae_u16 extra, uaecptr o switch (size) { - case 0: + case 0: // L x_cp_put_long(ad, (uae_u32)fpp_to_int(value, 2)); break; - case 1: + case 1: // S x_cp_put_long(ad, fpp_from_single(value)); break; - case 2: + case 2: // X { uae_u32 wrd1, wrd2, wrd3; fpp_from_exten(value, &wrd1, &wrd2, &wrd3); @@ -1152,10 +1149,10 @@ static int put_fp_value (fpdata *value, uae_u32 opcode, uae_u16 extra, uaecptr o x_cp_put_long (ad, wrd[2]); } break; - case 4: + case 4: // W x_cp_put_word(ad, (uae_s16)fpp_to_int(value, 1)); break; - case 5: + case 5: // D { uae_u32 wrd1, wrd2; fpp_from_double(value, &wrd1, &wrd2); @@ -1164,7 +1161,7 @@ static int put_fp_value (fpdata *value, uae_u32 opcode, uae_u16 extra, uaecptr o x_cp_put_long (ad, wrd2); } break; - case 6: + case 6: // B x_cp_put_byte(ad, (uae_s8)fpp_to_int(value, 0)); break; default: @@ -1182,38 +1179,38 @@ static int get_fp_ad (uae_u32 opcode, uae_u32 * ad) reg = opcode & 7; switch (mode) { - case 0: - case 1: + case 0: // Dn + case 1: // An return 0; - case 2: + case 2: // (An) *ad = m68k_areg (regs, reg); break; - case 3: + case 3: // (An)+ *ad = m68k_areg (regs, reg); break; - case 4: + case 4: // -(An) *ad = m68k_areg (regs, reg); break; - case 5: + case 5: // (d16,An) *ad = m68k_areg (regs, reg) + (uae_s32) (uae_s16) x_cp_next_iword (); break; - case 6: + case 6: // (d8,An,Xn)+ *ad = x_cp_get_disp_ea_020 (m68k_areg (regs, reg), 0); break; case 7: switch (reg) { - case 0: + case 0: // (xxx).W *ad = (uae_s32) (uae_s16) x_cp_next_iword (); break; - case 1: + case 1: // (xxx).L *ad = x_cp_next_ilong (); break; - case 2: + case 2: // (d16,PC) *ad = m68k_getpc (); *ad += (uae_s32) (uae_s16) x_cp_next_iword (); break; - case 3: + case 3: // (d8,PC,Xn)+ *ad = x_cp_get_disp_ea_020 (m68k_getpc (), 0); break; default: @@ -1223,7 +1220,7 @@ static int get_fp_ad (uae_u32 opcode, uae_u32 * ad) return 1; } -int fpp_cond (int condition) +static int fpp_cond (int condition) { int NotANumber, N, Z; @@ -1334,10 +1331,6 @@ void fpuop_dbcc (uae_u32 opcode, uae_u16 extra) return; regs.fp_exception = false; -#if DEBUG_FPP - if (!isinrom ()) - write_log (_T("fdbcc_opp at %08x\n"), m68k_getpc ()); -#endif if (fault_if_no_6888x (opcode, extra, pc - 4)) return; @@ -1373,10 +1366,6 @@ void fpuop_scc (uae_u32 opcode, uae_u16 extra) return; regs.fp_exception = false; -#if DEBUG_FPP - if (!isinrom ()) - write_log (_T("fscc_opp at %08x\n"), m68k_getpc ()); -#endif if (fault_if_no_6888x (opcode, extra, pc)) return; @@ -1413,10 +1402,6 @@ void fpuop_trapcc (uae_u32 opcode, uaecptr oldpc, uae_u16 extra) return; regs.fp_exception = false; -#if DEBUG_FPP - if (!isinrom ()) - write_log (_T("ftrapcc_opp at %08x\n"), m68k_getpc ()); -#endif if (fault_if_no_fpu_u (opcode, extra, 0, oldpc)) return; @@ -1440,10 +1425,6 @@ void fpuop_bcc (uae_u32 opcode, uaecptr oldpc, uae_u32 extra) return; regs.fp_exception = false; -#if DEBUG_FPP - if (!isinrom ()) - write_log (_T("fbcc_opp at %08x\n"), m68k_getpc ()); -#endif if (fault_if_no_fpu (opcode, extra, 0, oldpc - 2)) return; @@ -1471,10 +1452,6 @@ void fpuop_save (uae_u32 opcode) int i; regs.fp_exception = false; -#if DEBUG_FPP - if (!isinrom ()) - write_log (_T("fsave_opp at %08x\n"), m68k_getpc ()); -#endif if (fault_if_no_6888x (opcode, 0, pc)) return; @@ -1621,11 +1598,6 @@ void fpuop_restore (uae_u32 opcode) regs.fp_exception = false; -#if DEBUG_FPP - if (!isinrom ()) - write_log (_T("frestore_opp at %08x\n"), m68k_getpc ()); -#endif - if (fault_if_no_6888x (opcode, 0, pc)) return; @@ -1694,13 +1666,6 @@ retry: if (opclass == 0 || opclass == 2) { fpp_to_exten(&dst, fsave_data.fpt[0], fsave_data.fpt[1], fsave_data.fpt[2]); fpp_to_exten(&src, fsave_data.et[0], fsave_data.et[1], fsave_data.et[2]); -#if EXCEPTION_FPP - uae_u32 tmpsrc[3], tmpdst[3]; - fpp_from_exten(&src, &tmpsrc[0], &tmpsrc[1], &tmpsrc[2]); - fpp_from_exten(&dst, &tmpdst[0], &tmpdst[1], &tmpdst[2]); - write_log (_T("FRESTORE src = %08X %08X %08X, dst = %08X %08X %08X, extra = %04X\n"), - tmpsrc[0], tmpsrc[1], tmpsrc[2], tmpdst[0], tmpdst[1], tmpdst[2], cmdreg1b); -#endif fpsr_clear_status(); v = fp_arithmetic(&src, &dst, cmdreg1b); @@ -1861,10 +1826,10 @@ static bool fp_arithmetic(fpdata *src, fpdata *dst, int extra) fpp_move(dst, src, fpu_prec); break; case 0x40: /* FSMOVE */ - fpp_move(dst, src, 32); + fpp_move(dst, src, PREC_FLOAT); break; case 0x44: /* FDMOVE */ - fpp_move(dst, src, 64); + fpp_move(dst, src, PREC_DOUBLE); break; case 0x01: /* FINT */ fpp_int(dst, src); @@ -1879,10 +1844,10 @@ static bool fp_arithmetic(fpdata *src, fpdata *dst, int extra) fpp_sqrt(dst, src, fpu_prec); break; case 0x41: /* FSSQRT */ - fpp_sqrt(dst, src, 32); + fpp_sqrt(dst, src, PREC_FLOAT); break; case 0x45: /* FDSQRT */ - fpp_sqrt(dst, src, 64); + fpp_sqrt(dst, src, PREC_DOUBLE); break; case 0x06: /* FLOGNP1 */ fpp_lognp1(dst, src); @@ -1930,10 +1895,10 @@ static bool fp_arithmetic(fpdata *src, fpdata *dst, int extra) fpp_abs(dst, src, fpu_prec); break; case 0x58: /* FSABS */ - fpp_abs(dst, src, 32); + fpp_abs(dst, src, PREC_FLOAT); break; case 0x5c: /* FDABS */ - fpp_abs(dst, src, 64); + fpp_abs(dst, src, PREC_DOUBLE); break; case 0x19: /* FCOSH */ fpp_cosh(dst, src); @@ -1942,10 +1907,10 @@ static bool fp_arithmetic(fpdata *src, fpdata *dst, int extra) fpp_neg(dst, src, fpu_prec); break; case 0x5a: /* FSNEG */ - fpp_neg(dst, src, 32); + fpp_neg(dst, src, PREC_FLOAT); break; case 0x5e: /* FDNEG */ - fpp_neg(dst, src, 64); + fpp_neg(dst, src, PREC_DOUBLE); break; case 0x1c: /* FACOS */ fpp_acos(dst, src); @@ -1963,10 +1928,10 @@ static bool fp_arithmetic(fpdata *src, fpdata *dst, int extra) fpp_div(dst, src, fpu_prec); break; case 0x60: /* FSDIV */ - fpp_div(dst, src, 32); + fpp_div(dst, src, PREC_FLOAT); break; case 0x64: /* FDDIV */ - fpp_div(dst, src, 64); + fpp_div(dst, src, PREC_DOUBLE); break; case 0x21: /* FMOD */ fpsr_get_quotient(&q, &s); @@ -1977,19 +1942,19 @@ static bool fp_arithmetic(fpdata *src, fpdata *dst, int extra) fpp_add(dst, src, fpu_prec); break; case 0x62: /* FSADD */ - fpp_add(dst, src, 32); + fpp_add(dst, src, PREC_FLOAT); break; case 0x66: /* FDADD */ - fpp_add(dst, src, 64); + fpp_add(dst, src, PREC_DOUBLE); break; case 0x23: /* FMUL */ fpp_mul(dst, src, fpu_prec); break; case 0x63: /* FSMUL */ - fpp_mul(dst, src, 32); + fpp_mul(dst, src, PREC_FLOAT); break; case 0x67: /* FDMUL */ - fpp_mul(dst, src, 64); + fpp_mul(dst, src, PREC_DOUBLE); break; case 0x24: /* FSGLDIV */ fpp_sgldiv(dst, src); @@ -2009,10 +1974,10 @@ static bool fp_arithmetic(fpdata *src, fpdata *dst, int extra) fpp_sub(dst, src, fpu_prec); break; case 0x68: /* FSSUB */ - fpp_sub(dst, src, 32); + fpp_sub(dst, src, PREC_FLOAT); break; case 0x6c: /* FDSUB */ - fpp_sub(dst, src, 64); + fpp_sub(dst, src, PREC_DOUBLE); break; case 0x30: /* FSINCOS */ case 0x31: /* FSINCOS */ @@ -2061,16 +2026,13 @@ static void fpuop_arithmetic2 (uae_u32 opcode, uae_u16 extra) uaecptr pc = m68k_getpc () - 4; uaecptr ad = 0; -#if DEBUG_FPP - if (!isinrom ()) - write_log (_T("FPP %04x %04x at %08x\n"), opcode & 0xffff, extra, pc); -#endif if (fault_if_no_6888x (opcode, extra, pc)) return; switch ((extra >> 13) & 0x7) { case 3: + // FMOVE FPP->EA if (fp_exception_pending(true)) return; @@ -2089,41 +2051,49 @@ static void fpuop_arithmetic2 (uae_u32 opcode, uae_u16 extra) case 4: case 5: + // FMOVE Control Register <> Data or Address register if ((opcode & 0x38) == 0) { + // Dn if (fault_if_no_fpu (opcode, extra, 0, pc)) return; + // Only single selected control register is allowed + // All control register bits unset = FPIAR + uae_u16 bits = extra & (0x1000 | 0x0800 | 0x0400); + if (bits && bits != 0x1000 && bits != 0x0800 && bits != 0x400) { + fpu_noinst(opcode, pc); + return; + } if (extra & 0x2000) { if (extra & 0x1000) - m68k_dreg (regs, opcode & 7) = regs.fpcr & 0xffff; + m68k_dreg (regs, opcode & 7) = fpp_get_fpcr(); if (extra & 0x0800) m68k_dreg (regs, opcode & 7) = fpp_get_fpsr (); - if (extra & 0x0400) + if ((extra & 0x0400) || !bits) m68k_dreg (regs, opcode & 7) = regs.fpiar; } else { if (extra & 0x1000) fpp_set_fpcr(m68k_dreg (regs, opcode & 7)); if (extra & 0x0800) fpp_set_fpsr(m68k_dreg (regs, opcode & 7)); - if (extra & 0x0400) + if ((extra & 0x0400) || !bits) regs.fpiar = m68k_dreg (regs, opcode & 7); } } else if ((opcode & 0x38) == 0x08) { + // An if (fault_if_no_fpu (opcode, extra, 0, pc)) return; + // Only FPIAR can be moved to/from address register + // All bits unset = FPIAR + uae_u16 bits = extra & (0x1000 | 0x0800 | 0x0400); + // 68060, An and all bits unset: f-line + if (bits && bits != 0x0400) { + fpu_noinst(opcode, pc); + return; + } if (extra & 0x2000) { - if (extra & 0x1000) - m68k_areg (regs, opcode & 7) = regs.fpcr & 0xffff; - if (extra & 0x0800) - m68k_areg (regs, opcode & 7) = fpp_get_fpsr (); - if (extra & 0x0400) - m68k_areg (regs, opcode & 7) = regs.fpiar; + m68k_areg (regs, opcode & 7) = regs.fpiar; } else { - if (extra & 0x1000) - fpp_set_fpcr(m68k_areg (regs, opcode & 7)); - if (extra & 0x0800) - fpp_set_fpsr(m68k_areg (regs, opcode & 7)); - if (extra & 0x0400) - regs.fpiar = m68k_areg (regs, opcode & 7); + regs.fpiar = m68k_areg (regs, opcode & 7); } } else if ((opcode & 0x3f) == 0x3c) { if ((extra & 0x2000) == 0) { @@ -2150,7 +2120,7 @@ static void fpuop_arithmetic2 (uae_u32 opcode, uae_u16 extra) return; } } else if (extra & 0x2000) { - /* FMOVEM FPP->memory */ + /* FMOVEM Control Register->Memory */ uae_u32 ad; int incr = 0; @@ -2160,6 +2130,11 @@ static void fpuop_arithmetic2 (uae_u32 opcode, uae_u16 extra) } if (fault_if_no_fpu (opcode, extra, ad, pc)) return; + if ((opcode & 0x3f) >= 0x3a) { + // PC relative modes not supported + fpu_noinst(opcode, pc); + return; + } if ((opcode & 0x38) == 0x20) { if (extra & 0x1000) @@ -2171,7 +2146,7 @@ static void fpuop_arithmetic2 (uae_u32 opcode, uae_u16 extra) } ad -= incr; if (extra & 0x1000) { - x_cp_put_long (ad, regs.fpcr & 0xffff); + x_cp_put_long (ad, fpp_get_fpcr()); ad += 4; } if (extra & 0x0800) { @@ -2188,7 +2163,7 @@ static void fpuop_arithmetic2 (uae_u32 opcode, uae_u16 extra) if ((opcode & 0x38) == 0x20) m68k_areg (regs, opcode & 7) = ad; } else { - /* FMOVEM memory->FPP */ + /* FMOVEM Memory->Control Register */ uae_u32 ad; int incr = 0; @@ -2230,6 +2205,7 @@ static void fpuop_arithmetic2 (uae_u32 opcode, uae_u16 extra) case 6: case 7: { + // FMOVEM FPP<>Memory uae_u32 ad, list = 0; int incr = 1; int regdir = 1; @@ -2239,6 +2215,18 @@ static void fpuop_arithmetic2 (uae_u32 opcode, uae_u16 extra) } if (fault_if_no_fpu (opcode, extra, ad, pc)) return; + + if ((extra & 0x2000) && ((opcode & 0x38) == 0x18 || (opcode & 0x3f) >= 0x3a)) { + // FMOVEM FPP->Memory: (An)+ and PC relative modes not supported + fpu_noinst(opcode, pc); + return; + } + if (!(extra & 0x2000) && (opcode & 0x38) == 0x20) { + // FMOVEM Memory->FPP: -(An) not supported + fpu_noinst(opcode, pc); + return; + } + switch ((extra >> 11) & 3) { case 0: /* static pred */ @@ -2261,10 +2249,10 @@ static void fpuop_arithmetic2 (uae_u32 opcode, uae_u16 extra) } } if (extra & 0x2000) { - /* FMOVEM FPP->memory */ + /* FMOVEM FPP->Memory */ ad = fmovem2mem (ad, list, incr, regdir); } else { - /* FMOVEM memory->FPP */ + /* FMOVEM Memory->FPP */ ad = fmovem2fpp (ad, list, incr, regdir); } if ((opcode & 0x38) == 0x18 || (opcode & 0x38) == 0x20) // (an)+ or -(an) @@ -2338,7 +2326,11 @@ void fpuop_arithmetic (uae_u32 opcode, uae_u16 extra) { regs.fpu_state = 1; regs.fp_exception = false; + fpu_mmu_fixup = false; fpuop_arithmetic2 (opcode, extra); + if (fpu_mmu_fixup) { + mmufixup[0].reg = -1; + } } void fpu_reset (void) @@ -2385,7 +2377,6 @@ uae_u8 *restore_fpu (uae_u8 *src) 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 >= 68881) { fsave_data.ccr = restore_u32(); @@ -2453,7 +2444,6 @@ uae_u8 *save_fpu (int *len, uae_u8 *dstptr) 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 >= 68881) { diff --git a/src/fpp_native.cpp b/src/fpp_native.cpp index 17345a26..ad081850 100644 --- a/src/fpp_native.cpp +++ b/src/fpp_native.cpp @@ -55,33 +55,33 @@ static void fpp_set_mode(uae_u32 mode_control) { if (mode_control == fpu_mode_control && !currprefs.compfpu) return; - switch (mode_control & FPCR_ROUNDING_PRECISION) { - case FPCR_PRECISION_EXTENDED: // X - fpu_prec = 80; - break; - case FPCR_PRECISION_SINGLE: // S - fpu_prec = 32; - break; - case FPCR_PRECISION_DOUBLE: // D - default: // undefined - fpu_prec = 64; - break; - } + switch(mode_control & FPCR_ROUNDING_PRECISION) { + case FPCR_PRECISION_EXTENDED: // X + fpu_prec = PREC_EXTENDED; + break; + case FPCR_PRECISION_SINGLE: // S + fpu_prec = PREC_FLOAT; + break; + case FPCR_PRECISION_DOUBLE: // D + default: // undefined + fpu_prec = PREC_DOUBLE; + break; + } #if USE_HOST_ROUNDING if ((mode_control & FPCR_ROUNDING_MODE) != (fpu_mode_control & FPCR_ROUNDING_MODE)) { - switch (mode_control & FPCR_ROUNDING_MODE) { - case FPCR_ROUND_NEAR: // to neareset - fesetround(FE_TONEAREST); - break; - case FPCR_ROUND_ZERO: // to zero - fesetround(FE_TOWARDZERO); - break; - case FPCR_ROUND_MINF: // to minus - fesetround(FE_DOWNWARD); - break; - case FPCR_ROUND_PINF: // to plus - fesetround(FE_UPWARD); - break; + switch(mode_control & FPCR_ROUNDING_MODE) { + case FPCR_ROUND_NEAR: // to neareset + fesetround(FE_TONEAREST); + break; + case FPCR_ROUND_ZERO: // to zero + fesetround(FE_TOWARDZERO); + break; + case FPCR_ROUND_MINF: // to minus + fesetround(FE_DOWNWARD); + break; + case FPCR_ROUND_PINF: // to plus + fesetround(FE_UPWARD); + break; } } #endif @@ -112,32 +112,32 @@ static bool fpp_is_neg(fpdata *fpd) static void fpp_to_native(fptype *fp, fpdata *fpd) { - *fp = fpd->fp; + *fp = fpd->fp; } static void fpp_from_native(fptype fp, fpdata *fpd) { - fpd->fp = fp; + fpd->fp = fp; } static void fpp_to_single(fpdata *fpd, uae_u32 wrd1) { - union { - float f; - uae_u32 u; - } val; - - val.u = wrd1; - fpd->fp = (fptype)val.f; + union { + float f; + uae_u32 u; + } val; + + val.u = wrd1; + fpd->fp = (fptype) val.f; } static uae_u32 fpp_from_single(fpdata *fpd) { - union { - float f; - uae_u32 u; - } val; - - val.f = (float)fpd->fp; - return val.u; + union { + float f; + uae_u32 u; + } val; + + val.f = (float) fpd->fp; + return val.u; } static void fpp_to_double(fpdata *fpd, uae_u32 wrd1, uae_u32 wrd2) @@ -178,9 +178,8 @@ static void fpp_from_exten(fpdata *fpd, uae_u32 *wrd1, uae_u32 *wrd2, uae_u32 *w double frac; fptype v; - v = fpd->fp; - if (v == 0.0) { - *wrd1 = signbit(v) ? 0x80000000 : 0; + if (fpp_is_zero(fpd)) { + *wrd1 = signbit(fpd->fp) ? 0x80000000 : 0; *wrd2 = 0; *wrd3 = 0; return; @@ -189,7 +188,8 @@ static void fpp_from_exten(fpdata *fpd, uae_u32 *wrd1, uae_u32 *wrd2, uae_u32 *w *wrd2 = 0xffffffff; *wrd3 = 0xffffffff; return; - } + } + v = fpd->fp; if (v < 0) { *wrd1 = 0x80000000; v = -v; @@ -307,13 +307,15 @@ static void fpp_round_single(fpdata *fpd) static void fpp_round_prec(fpdata *fpd, int prec) { - if (prec == 32) { + if (prec == PREC_FLOAT) { fpp_round_single(fpd); } } static void fp_round(fpdata *fpd) { + if (!currprefs.fpu_strict) + return; fpp_round_prec(fpd, fpu_prec); } @@ -322,7 +324,7 @@ static void fp_round(fpdata *fpd) static void fpp_move(fpdata *a, fpdata *b, int prec) { a->fp = b->fp; - if (prec == 32) + if (prec == PREC_FLOAT) fpp_round_single(a); } @@ -368,7 +370,7 @@ static void fpp_getman(fpdata *a, fpdata *b) static void fpp_div(fpdata *a, fpdata *b, int prec) { a->fp = a->fp / b->fp; - if (prec == 32) + if (prec == PREC_FLOAT) fpp_round_single(a); } static void fpp_mod(fpdata *a, fpdata *b, uae_u64 *q, uae_u8 *s) @@ -432,7 +434,7 @@ static void fpp_intrz(fpdata *a, fpdata *b) static void fpp_sqrt(fpdata *a, fpdata *b, int prec) { a->fp = sqrtl(b->fp); - if (prec == 32) + if (prec == PREC_FLOAT) fpp_round_single(a); } static void fpp_lognp1(fpdata *a, fpdata *b) @@ -508,7 +510,7 @@ static void fpp_log2(fpdata *a, fpdata *b) static void fpp_abs(fpdata *a, fpdata *b, int prec) { a->fp = b->fp < 0.0 ? -b->fp : b->fp; - if (prec == 32) + if (prec == PREC_FLOAT) fpp_round_single(a); } static void fpp_cosh(fpdata *a, fpdata *b) @@ -519,7 +521,7 @@ static void fpp_cosh(fpdata *a, fpdata *b) static void fpp_neg(fpdata *a, fpdata *b, int prec) { a->fp = -b->fp; - if (prec == 32) + if (prec == PREC_FLOAT) fpp_round_single(a); } static void fpp_acos(fpdata *a, fpdata *b) @@ -535,19 +537,19 @@ static void fpp_cos(fpdata *a, fpdata *b) static void fpp_sub(fpdata *a, fpdata *b, int prec) { a->fp = a->fp - b->fp; - if (prec == 32) + if (prec == PREC_FLOAT) fpp_round_single(a); } static void fpp_add(fpdata *a, fpdata *b, int prec) { a->fp = a->fp + b->fp; - if (prec == 32) + if (prec == PREC_FLOAT) fpp_round_single(a); } static void fpp_mul(fpdata *a, fpdata *b, int prec) { a->fp = a->fp * b->fp; - if (prec == 32) + if (prec == PREC_FLOAT) fpp_round_single(a); } static void fpp_sglmul(fpdata *a, fpdata *b) @@ -577,12 +579,12 @@ static void fpp_cmp(fpdata *a, fpdata *b) fptype v = 1.0; if (currprefs.fpu_strict) { bool a_neg = fpp_is_neg(a); - bool b_neg = fpp_is_neg(b); bool a_inf = fpp_is_infinity(a); - bool b_inf = fpp_is_infinity(b); bool a_zero = fpp_is_zero(a); - bool b_zero = fpp_is_zero(b); bool a_nan = fpp_is_nan(a); + bool b_neg = fpp_is_neg(b); + bool b_inf = fpp_is_infinity(b); + bool b_zero = fpp_is_zero(b); bool b_nan = fpp_is_nan(b); if (a_nan || b_nan) { diff --git a/src/include/fpp.h b/src/include/fpp.h index bcf5b10e..418c6d0d 100644 --- a/src/include/fpp.h +++ b/src/include/fpp.h @@ -20,3 +20,8 @@ #if defined(CPU_i386) || defined(CPU_x86_64) extern void init_fpucw_x87(void); #endif + +#define PREC_NORMAL 0 +#define PREC_FLOAT 1 +#define PREC_DOUBLE 2 +#define PREC_EXTENDED 3 diff --git a/src/include/newcpu.h b/src/include/newcpu.h index db495ed2..bf9a84cf 100644 --- a/src/include/newcpu.h +++ b/src/include/newcpu.h @@ -38,6 +38,7 @@ struct cputbl { }; #ifdef JIT +#define MIN_JIT_CACHE 128 #define MAX_JIT_CACHE 16384 typedef uae_u32 REGPARAM3 compop_func (uae_u32) REGPARAM; @@ -62,9 +63,15 @@ typedef uae_u8 flagtype; #ifdef FPUEMU typedef double fptype; -#define LDPTR qword ptr #endif +struct mmufixup +{ + int reg; + uae_u32 value; +}; +extern struct mmufixup mmufixup[1]; + typedef struct { fptype fp; @@ -105,7 +112,6 @@ struct regstruct uae_u32 fpcr,fpsr, fpiar; uae_u32 fpu_state; uae_u32 fpu_exp_state; - uae_u16 fp_opword; uaecptr fp_ea; uae_u32 fp_exp_pend, fp_unimp_pend; bool fpu_exp_pre; @@ -177,6 +183,11 @@ STATIC_INLINE void m68k_setpc (uaecptr newpc) regs.pc_p = regs.pc_oldp = get_real_address (newpc); regs.instruction_pc = regs.pc = newpc; } +STATIC_INLINE void m68k_setpc_j(uaecptr newpc) +{ + regs.pc_p = regs.pc_oldp = get_real_address(newpc); + regs.pc = newpc; +} STATIC_INLINE uaecptr m68k_getpc (void) { return (uaecptr)(regs.pc + ((uae_u8*)regs.pc_p - (uae_u8*)regs.pc_oldp)); @@ -231,6 +242,10 @@ STATIC_INLINE void m68k_setpci(uaecptr newpc) { regs.instruction_pc = regs.pc = newpc; } +STATIC_INLINE void m68k_setpci_j(uaecptr newpc) +{ + regs.pc = newpc; +} STATIC_INLINE uaecptr m68k_getpci(void) { return regs.pc; @@ -240,20 +255,15 @@ STATIC_INLINE void m68k_incpci(int o) regs.pc += o; } -STATIC_INLINE uae_u32 get_iiword(int o) -{ - return get_wordi(m68k_getpci() + (o)); -} - STATIC_INLINE void m68k_do_bsri(uaecptr oldpc, uae_s32 offset) { m68k_areg(regs, 7) -= 4; - put_long(m68k_areg(regs, 7), oldpc); + x_put_long(m68k_areg(regs, 7), oldpc); m68k_incpci(offset); } STATIC_INLINE void m68k_do_rtsi(void) { - uae_u32 newpc = get_long(m68k_areg(regs, 7)); + uae_u32 newpc = x_get_long(m68k_areg(regs, 7)); m68k_setpci(newpc); m68k_areg(regs, 7) += 4; } @@ -316,7 +326,6 @@ extern void divbyzero_special (bool issigned, uae_s32 dst); extern void setdivuoverflowflags(uae_u32 dividend, uae_u16 divisor); extern void setdivsoverflowflags(uae_s32 dividend, uae_s16 divisor); extern void protect_roms (bool); -extern bool is_hardreset(void); STATIC_INLINE int bitset_count16(uae_u16 data) { @@ -344,7 +353,6 @@ extern void fpuop_bcc(uae_u32, uaecptr, uae_u32); extern void fpuop_save(uae_u32); extern void fpuop_restore(uae_u32); extern void fpu_reset (void); -extern int fpp_cond(int condition); extern void exception3_read(uae_u32 opcode, uaecptr addr); extern void exception3_write(uae_u32 opcode, uaecptr addr); @@ -354,7 +362,7 @@ extern void exception3b (uae_u32 opcode, uaecptr addr, bool w, bool i, uaecptr p extern void exception2 (uaecptr addr, bool read, int size, uae_u32 fc); extern void cpureset (void); extern void cpu_halt (int id); -extern int cpu_sleep_millis(int ms); +extern void cpu_sleep_millis(int ms); extern void fill_prefetch (void); @@ -395,7 +403,6 @@ extern int movec_illg (int regno); #define CPU_HALT_BUS_ERROR_DOUBLE_FAULT 1 #define CPU_HALT_DOUBLE_FAULT 2 #define CPU_HALT_OPCODE_FETCH_FROM_NON_EXISTING_ADDRESS 3 -#define CPU_HALT_FAKE_DMA 6 #define CPU_HALT_AUTOCONFIG_CONFLICT 7 #define CPU_HALT_SSP_IN_NON_EXISTING_ADDRESS 10 #define CPU_HALT_INVALID_START_ADDRESS 11 diff --git a/src/newcpu.cpp b/src/newcpu.cpp index 7a60f6bc..99ddaa1c 100644 --- a/src/newcpu.cpp +++ b/src/newcpu.cpp @@ -74,6 +74,8 @@ struct cputbl_data }; static struct cputbl_data cpudatatbl[65536]; +struct mmufixup mmufixup[1]; + #define COUNT_INSTRS 0 static uae_u64 fake_srp_030, fake_crp_030; @@ -210,7 +212,6 @@ void flush_cpu_caches_040(uae_u16 opcode) if (scope == 3) { // all if (!k) { - // data } else { // instruction flush_cpu_caches(true); @@ -277,7 +278,7 @@ static void build_cpufunctbl (void) m68k_pc_indirect = 0; } lvl = (currprefs.cpu_model - 68000) / 10; - if (lvl >= 4) + if (lvl >= 5) lvl = 4; tbl = cputbls[lvl][mode]; @@ -502,7 +503,7 @@ STATIC_INLINE unsigned long adjust_cycles(unsigned long cycles) return res; } -STATIC_INLINE void m68k_set_stop(void) +static void m68k_set_stop(void) { if (regs.stopped) return; @@ -510,7 +511,7 @@ STATIC_INLINE void m68k_set_stop(void) set_special(SPCFLAG_STOP); } -STATIC_INLINE void m68k_unset_stop(void) +static void m68k_unset_stop(void) { regs.stopped = 0; unset_special(SPCFLAG_STOP); @@ -522,6 +523,14 @@ static void activate_trace(void) set_special (SPCFLAG_DOTRACE); } +// make sure interrupt is checked immediately after current instruction +static void doint_imm(void) +{ + doint(); + if (!currprefs.cachesize && !(regs.spcflags & SPCFLAG_INT) && (regs.spcflags & SPCFLAG_DOINT)) + set_special(SPCFLAG_INT); +} + void REGPARAM2 MakeSR (void) { regs.sr = ((regs.t1 << 15) | (regs.t0 << 14) @@ -588,7 +597,7 @@ STATIC_INLINE void MakeFromSR_x(int t0trace) } } - doint(); + doint_imm(); if (regs.t1 || regs.t0) { set_special (SPCFLAG_TRACE); } else { @@ -626,7 +635,7 @@ static void exception_check_trace (int nr) regs.t1 = regs.t0 = 0; } -STATIC_INLINE int iack_cycle(int nr) +static int iack_cycle(int nr) { int vector; @@ -708,7 +717,6 @@ static void Exception_build_stack_frame (uae_u32 oldpc, uae_u32 currpc, uae_u32 { switch (format) { case 0x0: // four word stack frame - case 0x1: // throwaway four word stack frame break; case 0x2: // six word stack frame m68k_areg (regs, 7) -= 4; @@ -736,12 +744,12 @@ static void Exception_build_stack_frame (uae_u32 oldpc, uae_u32 currpc, uae_u32 x_put_word (m68k_areg (regs, 7), regs.sr); } -static void Exception_build_stack_frame_common (uae_u32 oldpc, uae_u32 currpc, uae_u32 ssw, int nr) +static void Exception_build_stack_frame_common (uae_u32 oldpc, uae_u32 currpc, int nr) { if (nr == 5 || nr == 6 || nr == 7 || nr == 9) { - Exception_build_stack_frame(oldpc, currpc, 0 /*regs.mmu_ssw*/, nr, 0x2); + Exception_build_stack_frame(oldpc, currpc, 0, nr, 0x2); } else if (nr == 60 || nr == 61) { - Exception_build_stack_frame(oldpc, regs.instruction_pc, 0 /*regs.mmu_ssw*/, nr, 0x0); + Exception_build_stack_frame(oldpc, regs.instruction_pc, 0, nr, 0x0); } else if (nr >= 48 && nr <= 55) { if (regs.fpu_exp_pre) { Exception_build_stack_frame(oldpc, regs.instruction_pc, 0, nr, 0x0); @@ -750,13 +758,13 @@ static void Exception_build_stack_frame_common (uae_u32 oldpc, uae_u32 currpc, u } } else if (nr == 11 && regs.fp_unimp_ins) { regs.fp_unimp_ins = false; - if ((currprefs.cpu_model == 68040 && currprefs.fpu_model == 0)) { + if (currprefs.cpu_model == 68040 && currprefs.fpu_model == 0) { Exception_build_stack_frame(regs.fp_ea, currpc, regs.instruction_pc, nr, 0x4); } else { - Exception_build_stack_frame(regs.fp_ea, currpc, 0 /*regs.mmu_ssw*/, nr, 0x2); + Exception_build_stack_frame(regs.fp_ea, currpc, 0, nr, 0x2); } } else { - Exception_build_stack_frame(oldpc, currpc, 0 /*regs.mmu_ssw*/, nr, 0x0); + Exception_build_stack_frame(oldpc, currpc, 0, nr, 0x0); } } @@ -890,7 +898,7 @@ void Exception (int nr) m68k_areg(regs, 7) -= 2; x_put_word (m68k_areg(regs, 7), 0x1000 + vector_nr * 4); } else { - Exception_build_stack_frame_common(oldpc, currpc, 0 /*regs.mmu_ssw*/, nr); + Exception_build_stack_frame_common(oldpc, currpc, nr); used_exception_build_stack_frame = true; } } else { @@ -928,6 +936,8 @@ kludge_me_do: exception3_notinstruction(regs.ir, newpc); return; } + if (interrupt) + regs.intmask = nr - 24; m68k_setpc (newpc); #ifdef JIT set_special(SPCFLAG_END_COMPILE); @@ -961,7 +971,6 @@ static void do_interrupt (int nr) for (;;) { Exception (nr + 24); - regs.intmask = nr; if (!currprefs.cpu_compatible) break; nr = intlev(); @@ -1046,6 +1055,7 @@ static void m68k_reset (bool hardreset) set_cpu_caches (false); } + mmufixup[0].reg = -1; if (currprefs.cpu_model >= 68040) { set_cpu_caches(false); } @@ -1216,7 +1226,6 @@ static bool mmu_op30fake_pmove (uaecptr pc, uae_u32 opcode, uae_u16 next, uaecpt if (!reg) return true; - return false; } @@ -1253,6 +1262,7 @@ static bool mmu_op30fake_pflush (uaecptr pc, uae_u32 opcode, uae_u16 next, uaecp switch (flushmode) { case 0x00: + case 0x02: return mmu_op30fake_pload(pc, opcode, next, extra); case 0x18: if (mmu_op30_invea(opcode)) @@ -1343,7 +1353,7 @@ void mmu_op(uae_u32 opcode, uae_u32 extra) /* PFLUSH */ regs.mmusr = 0; return; - } else if ((opcode & 0x0FD8) == 0x548) { + } else if ((opcode & 0x0FD8) == 0x0548) { /* PTEST */ int regno = opcode & 7; uae_u32 addr = m68k_areg(regs, regno); @@ -1390,16 +1400,15 @@ static void check_uae_int_request(void) if (uae_int_requested & 0xff0000) { atomic_and(&uae_int_requested, ~0x010000); } - if (irq) + if (irq) { doint(); + } } } -int cpu_sleep_millis(int ms) +void cpu_sleep_millis(int ms) { - int ret = 0; - ret = sleep_millis_main(ms); - return ret; + sleep_millis_main(ms); } static bool haltloop(void) @@ -1455,9 +1464,6 @@ static int do_specialties (int cycles) /* exit from HRTMon? */ if (hrtmon_flag == ACTION_REPLAY_ACTIVE && !isinhrt) hrtmon_hide (); - /* HRTMon breakpoint? (not via IRQ7) */ - if (hrtmon_flag == ACTION_REPLAY_IDLE && isinhrt) - hrtmon_breakenter (); if (hrtmon_flag == ACTION_REPLAY_ACTIVATE) hrtmon_enter (); } @@ -1505,6 +1511,15 @@ static int do_specialties (int cycles) if (regs.spcflags & SPCFLAG_DOTRACE) Exception (9); + if ((regs.spcflags & SPCFLAG_STOP) && regs.s == 0 && currprefs.cpu_model <= 68010) { + // 68000/68010 undocumented special case: + // if STOP clears S-bit and T was not set: + // cause privilege violation exception, PC pointing to following instruction. + // If T was set before STOP: STOP works as documented. + m68k_unset_stop(); + Exception(8); + } + bool first = true; while ((regs.spcflags & SPCFLAG_STOP) && !(regs.spcflags & SPCFLAG_BRK)) { check_uae_int_request(); @@ -1609,7 +1624,6 @@ void execute_exception(void) // after leaving this function, we fall back to execute_normal() } - void do_nothing(void) { /* What did you expect this to do? */ @@ -1747,11 +1761,6 @@ static int in_m68k_go = 0; static bool cpu_hardreset; -bool is_hardreset(void) -{ - return cpu_hardreset; -} - #ifdef USE_JIT_FPU static uae_u8 fp_buffer[8 * 8]; #endif @@ -1981,6 +1990,8 @@ static void fill_prefetch_quick (void) void restore_cpu_finish(void) { + if (!currprefs.fpu_model) + fpu_reset(); init_m68k (); m68k_setpc_normal (regs.pc); doint (); @@ -2032,7 +2043,7 @@ uae_u8 *save_cpu_extra (int *len, uae_u8 *dstptr) uae_u8 *save_cpu (int *len, uae_u8 *dstptr) { uae_u8 *dstbak,*dst; - int model, i, khz; + int model, khz; if (dstptr) dstbak = dst = dstptr; @@ -2041,7 +2052,7 @@ uae_u8 *save_cpu (int *len, uae_u8 *dstptr) model = currprefs.cpu_model; save_u32 (model); /* MODEL */ save_u32 (0x80000000 | (currprefs.address_space_24 ? 1 : 0)); /* FLAGS */ - for(i = 0;i < 15; i++) + for(int i = 0;i < 15; i++) save_u32 (regs.regs[i]); /* D0-D7 A0-A6 */ save_u32 (m68k_getpc ()); /* PC */ save_u16 (regs.irc); /* prefetch */ @@ -2221,9 +2232,7 @@ void fill_prefetch (void) return; if (!currprefs.cpu_compatible) return; - if (currprefs.cpu_model <= 68010) { - uaecptr pc = m68k_getpc (); - regs.ir = x_get_word (pc); - regs.irc = x_get_word (pc + 2); - } + uaecptr pc = m68k_getpc (); + regs.ir = x_get_word (pc); + regs.irc = x_get_word (pc + 2); } diff --git a/src/newcpu_common.cpp b/src/newcpu_common.cpp index 320b6bad..06e95d91 100644 --- a/src/newcpu_common.cpp +++ b/src/newcpu_common.cpp @@ -78,9 +78,9 @@ int m68k_move2c (int regno, uae_u32 *regp) case 0x804: regs.isp = *regp; if (regs.m == 0) m68k_areg(regs, 7) = regs.isp; break; /* 68040 only */ case 0x805: regs.mmusr = *regp; break; - /* 68040/060 */ - case 0x806: regs.urp = *regp & 0xfffffe00; break; - case 0x807: regs.srp = *regp & 0xfffffe00; break; + /* 68040 stores all bits, 68060 zeroes low 9 bits */ + case 0x806: regs.urp = *regp; break; + case 0x807: regs.srp = *regp; break; default: op_illg (0x4E7B); return 0;