]> git.unchartedbackwaters.co.uk Git - francis/winuae.git/commitdiff
Some 68010 cycle count fixes.
authorToni Wilen <twilen@winuae.net>
Sat, 23 May 2020 15:50:44 +0000 (18:50 +0300)
committerToni Wilen <twilen@winuae.net>
Sat, 23 May 2020 15:50:44 +0000 (18:50 +0300)
gencpu.cpp
newcpu.cpp
newcpu_common.cpp

index ee5097a9080a38c17717f3d1a7b5d18a4a7e6f7f..62befa24800ab98e229e534445e204eda15926f4 100644 (file)
@@ -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");
index 82a51c81352ea68eca7a261a4ac6c00b1fb06535..b55fc58fb10827a93fd7c6932e69047136fa9d8b 100644 (file)
@@ -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);
 }
 
index 628d9fea107f457516b17f2dc1cd6521d88e76da..b0d389f436fdc11d7e51710f0d36a58b65bc0851 100644 (file)
@@ -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