From ca9902640d5ae09a3889faadfbee4643f3645c8d Mon Sep 17 00:00:00 2001 From: Toni Wilen Date: Sat, 23 May 2020 18:50:44 +0300 Subject: [PATCH] Some 68010 cycle count fixes. --- gencpu.cpp | 35 +++++++++--------- newcpu.cpp | 21 +++++++---- newcpu_common.cpp | 90 +++++++++++++++++++++++++++++++++-------------- 3 files changed, 96 insertions(+), 50 deletions(-) diff --git a/gencpu.cpp b/gencpu.cpp index ee5097a9..62befa24 100644 --- a/gencpu.cpp +++ b/gencpu.cpp @@ -1454,8 +1454,8 @@ static void loopmode_access(void) } else { addcycles000_nonces("loop_mode & 0xfffe"); } - // CLR.L adds 2 extra cycles when loop exits - if (g_instr->mnemo == i_CLR && g_instr->size == sz_long) { + // CLR.x adds 2 extra cycles when loop exits + if (g_instr->mnemo == i_CLR) { out("loop_mode &= 0xffff0000;\n"); out("loop_mode |= 1;\n"); } else { @@ -2283,23 +2283,12 @@ static void check_bus_error(const char *name, int offset, int write, int size, c if (g_instr->mnemo == i_MVSR2 && !write) { out("opcode |= 0x20000;\n"); } - // read bus error, -(an).w/.l: pre-decrement is done first. - if (!write && g_instr->smode == Apdi && g_instr->size == sz_long) { - - //out("m68k_areg(regs, %s) = %sa;\n", bus_error_reg, name); - } if (g_instr->mnemo == i_MOVES) { out("regs.irc = extra;\n"); if (!write) { out("regs.write_buffer = extra;\n"); } if (g_instr->size == sz_long) { - // moves.l an,-(an)/(an)+ (same registers): write buffer contains modified value. - if (g_instr->dmode == Aipi || g_instr->dmode == Apdi) { - out("if (dstreg + 8 == ((extra >> 12) & 15)) {\n"); - out("src += %d;\n", g_instr->dmode == Aipi ? 2 : -2); - out("}\n"); - } if (g_instr->dmode == Apdi) { if (!write) { out("m68k_areg(regs, dstreg) = srca;\n"); @@ -2342,6 +2331,16 @@ static void check_bus_error(const char *name, int offset, int write, int size, c out("regs.irc = dsta >> 16;\n"); } } + } else if (g_instr->mnemo == i_MVPRM) { + if (write) { + if (g_instr->size == sz_word) { + out("uae_u16 val = src;\n"); + } else { + out("uae_u16 val = src >> %d;\n", offset <= 2 ? 16 : 0); + } + size |= 0x100; + writevar = "val"; + } } } @@ -2356,12 +2355,12 @@ static void check_bus_error(const char *name, int offset, int write, int size, c } if (write) { - out("exception2_write(opcode, %sa + %d, %d, %s, %d);\n", + out("exception2_write(opcode, %sa + %d, 0x%x, %s, %d);\n", name, offset, size, writevar, (!write && (g_instr->smode == PC16 || g_instr->smode == PC8r)) || (write && (g_instr->dmode == PC16 || g_instr->dmode == PC8r)) ? 2 : fc); } else { - out("exception2_read(opcode, %sa + %d, %d, %d);\n", + out("exception2_read(opcode, %sa + %d, 0x%x, %d);\n", name, offset, size, (!write && (g_instr->smode == PC16 || g_instr->smode == PC8r)) || (write && (g_instr->dmode == PC16 || g_instr->dmode == PC8r)) ? 2 : fc); @@ -7574,8 +7573,10 @@ bccl_not68020: int old_m68k_pc_offset = m68k_pc_offset; int old_m68k_pc_total = m68k_pc_total; clear_m68k_offset(); + count_cycles -= 4; get_prefetch_020_continue(); fill_prefetch_full_000_special(1, NULL); + count_cycles += 4; returncycles(8); m68k_pc_offset = old_m68k_pc_offset; m68k_pc_total = old_m68k_pc_total; @@ -7591,7 +7592,7 @@ bccl_not68020: setpc("oldpc"); check_ipl_always(); - returncycles(0); + returncycles(2); out("}\n"); out("regs.loop_mode = 0;\n"); setpc("oldpc + %d", m68k_pc_offset); @@ -8467,7 +8468,7 @@ bccl_not68020: returntail(false); did_prefetch = 0; // Earlier models do -(an)/(an)+ EA calculation first - if (!(cpu_level == 5 || (curi->dmode != Aipi && curi->dmode != Apdi) || (cpu_level == 1 && curi->size == sz_long))) { + if (!(cpu_level == 5 || (curi->dmode != Aipi && curi->dmode != Apdi)) || (cpu_level == 1 && curi->size == sz_long)) { out("src = regs.regs[(extra >> 12) & 15];\n"); } genastore_fc ("src", curi->dmode, "dstreg", curi->size, "dst"); diff --git a/newcpu.cpp b/newcpu.cpp index 82a51c81..b55fc58f 100644 --- a/newcpu.cpp +++ b/newcpu.cpp @@ -7259,7 +7259,7 @@ void exception3_read(uae_u32 opcode, uaecptr addr, int size, int fc) opcode = regs.ir; } last_di_for_exception_3 = 1; - exception3f(opcode, addr, false, ia, ni, 0xffffffff, size, fc); + exception3f(opcode, addr, false, ia, ni, 0xffffffff, size & 15, fc); } void exception3_write(uae_u32 opcode, uaecptr addr, int size, uae_u32 val, int fc) { @@ -7278,7 +7278,7 @@ void exception3_write(uae_u32 opcode, uaecptr addr, int size, uae_u32 val, int f } last_di_for_exception_3 = 1; regs.write_buffer = val; - exception3f(opcode, addr, true, ia, ni, 0xffffffff, size, fc); + exception3f(opcode, addr, true, ia, ni, 0xffffffff, size & 15, fc); } void exception2_setup(uae_u32 opcode, uaecptr addr, bool read, int size, uae_u32 fc) @@ -7289,7 +7289,7 @@ void exception2_setup(uae_u32 opcode, uaecptr addr, bool read, int size, uae_u32 last_op_for_exception_3 = opcode; last_fc_for_exception_3 = fc; last_notinstruction_for_exception_3 = exception_in_exception != 0; - last_size_for_exception_3 = size; + last_size_for_exception_3 = size & 15; last_di_for_exception_3 = 1; hardware_bus_error = 0; @@ -7331,14 +7331,23 @@ void hardware_exception2(uaecptr addr, uae_u32 v, bool read, bool ins, int size) void exception2_read(uae_u32 opcode, uaecptr addr, int size, int fc) { - exception2_setup(opcode, addr, true, size, fc); + exception2_setup(opcode, addr, true, size & 15, fc); Exception(2); } void exception2_write(uae_u32 opcode, uaecptr addr, int size, uae_u32 val, int fc) { - exception2_setup(opcode, addr, false, size, fc); - regs.write_buffer = val; + exception2_setup(opcode, addr, false, size & 15, fc); + if (size & 0x100) { + regs.write_buffer = val; + } else { + if (size == sz_byte) { + regs.write_buffer &= 0xff00; + regs.write_buffer |= val & 0xff; + } else { + regs.write_buffer = val; + } + } Exception(2); } diff --git a/newcpu_common.cpp b/newcpu_common.cpp index 628d9fea..b0d389f4 100644 --- a/newcpu_common.cpp +++ b/newcpu_common.cpp @@ -716,14 +716,19 @@ Best and worst cases for register operand: (Note the difference with the documented range.) -DIVU: +DIVU 68000: Overflow (always): 10 cycles. Worst case: 136 cycles. Best case: 76 cycles. +DIVU 68010: -DIVS: +Overflow (always): 8 cycles. +Wost case: 108 cycles. +Best case: 78 cycles. + +DIVS 68000: Absolute overflow: 16-18 cycles. Signed overflow is not detected prematurely. @@ -732,6 +737,13 @@ Worst case: 156 cycles. Best case without signed overflow: 122 cycles. Best case with signed overflow: 120 cycles +DIVS 68010: + +Absolute overflow: 16 cycles. +Signed overflow is not detected prematurely. + +Worst case: 122 cycles. +Best case: 120 cycles. */ @@ -745,39 +757,64 @@ int getDivu68kCycles (uae_u32 dividend, uae_u16 divisor) return 0; if (currprefs.cpu_model == 68010) { + // Overflow - if ((dividend >> 16) >= divisor) + if ((dividend >> 16) >= divisor) { return 4; - return 104; - } + } - // Overflow - if ((dividend >> 16) >= divisor) - return (mcycles = 5) * 2 - 4; + mcycles = 74; - mcycles = 38; + hdivisor = divisor << 16; - hdivisor = divisor << 16; + for (i = 0; i < 15; i++) { + uae_u32 temp; + temp = dividend; - for (i = 0; i < 15; i++) { - uae_u32 temp; - temp = dividend; + dividend <<= 1; - dividend <<= 1; + // If carry from shift + if ((uae_s32)temp < 0) { + dividend -= hdivisor; + } else { + mcycles += 2; + if (dividend >= hdivisor) { + dividend -= hdivisor; + } + } + } + return mcycles; - // If carry from shift - if ((uae_s32)temp < 0) - dividend -= hdivisor; - else { - mcycles += 2; - if (dividend >= hdivisor) { + } else { + + // Overflow + if ((dividend >> 16) >= divisor) + return (mcycles = 5) * 2 - 4; + + mcycles = 38; + + hdivisor = divisor << 16; + + for (i = 0; i < 15; i++) { + uae_u32 temp; + temp = dividend; + + dividend <<= 1; + + // If carry from shift + if ((uae_s32)temp < 0) dividend -= hdivisor; - mcycles--; + else { + mcycles += 2; + if (dividend >= hdivisor) { + dividend -= hdivisor; + mcycles--; + } } } + // -4 = remove prefetch cycle + return mcycles * 2 - 4; } - // -4 = remove prefetch cycle - return mcycles * 2 - 4; } int getDivs68kCycles (uae_s32 dividend, uae_s16 divisor) @@ -875,7 +912,7 @@ void divbyzero_special (bool issigned, uae_s32 dst) /* DIVU overflow * * 68000: V=1, N=1, C=0, Z=0 - * 68010: V=1, N=divisor<0x8000, C=0, Z=divided upper word == 0xffff and divisor == 0xffff + * 68010: V=1, N=1, C=0, Z=0 * 68020: V=1, C=0, Z=0, N=X * 68040: V=1, C=0, NZ not modified. * 68060: V=1, C=0, NZ not modified. @@ -898,9 +935,8 @@ void setdivuflags(uae_u32 dividend, uae_u16 divisor) SET_NFLG(1); } else if (currprefs.cpu_model == 68010) { SET_VFLG(1); - SET_NFLG(divisor < 0x8000); - // can anyone explain this? - SET_ZFLG((dividend >> 16) == 0xffff && divisor == 0xffff); + SET_NFLG(1); + SET_ZFLG(0); SET_CFLG(0); } else { // 68000 -- 2.47.3