]> git.unchartedbackwaters.co.uk Git - francis/winuae.git/commitdiff
Apparently 68030 does post-increment/pre-decrement before MMU bus error is generated.
authorToni Wilen <twilen@winuae.net>
Sat, 4 Jan 2020 20:16:29 +0000 (22:16 +0200)
committerToni Wilen <twilen@winuae.net>
Sat, 4 Jan 2020 20:16:29 +0000 (22:16 +0200)
cpummu30.cpp
gencpu.cpp
newcpu_common.cpp

index 46a73ac341e1ee9a68b411dd083286e1ec9f8f83..59bf12172c206b6bbc2b45817101e5f3e98d1be4 100644 (file)
@@ -1760,6 +1760,22 @@ static void dump_opcode(uae_u16 opcode)
 }
 #endif
 
+// if CPU is 68030 and faulted access' addressing mode was -(an) or (an)+
+// register content is not restored when exception starts.
+static void mmu030fixupreg(int i)
+{
+       struct mmufixup *m = &mmufixup[i];
+       if (m->reg < 0)
+               return;
+       int size = 1 << ((m->reg >> 10) & 3);
+       if (m->reg & 0x100) {
+               m68k_areg(regs, m->reg & 15) += size;
+       }
+       if (m->reg & 0x200) {
+               m68k_areg(regs, m->reg & 15) -= size;
+       }
+}
+
 void mmu030_page_fault(uaecptr addr, bool read, int flags, uae_u32 fc)
 {
        if (flags < 0) {
@@ -1784,6 +1800,10 @@ void mmu030_page_fault(uaecptr addr, bool read, int flags, uae_u32 fc)
                } else {
                        regs.mmu_ssw = MMU030_SSW_FB | MMU030_SSW_RB;
                }
+               if (!(mmu030_state[1] & MMU030_STATEFLAG1_LASTWRITE)) {
+                       mmu030fixupreg(0);
+                       mmu030fixupreg(1);
+               }
        }
        regs.mmu_ssw |= read ? MMU030_SSW_RW : 0;
        regs.mmu_ssw |= flags;
index 60b6afb1209c97bac39d540180af18b1ff80f636..407404fe2ff66257361be15ddd74647ee97d18c5 100644 (file)
@@ -255,11 +255,24 @@ static bool needmmufixup(void)
        return true;
 }
 
-static void addmmufixup(const char *reg)
+static void addmmufixup(const char *reg, int size, int mode)
 {
        if (!needmmufixup())
                return;
-       printf("\tmmufixup[%d].reg = %s;\n", mmufixupcnt, reg);
+       int flags = 0;
+       if (cpu_level == 3 && size >= 0 && mode >= 0) {
+               if (mode == Aipi) {
+                       flags |= 0x100;
+               } else if (mode == Apdi) {
+                       flags |= 0x200;
+               }
+               if (size == sz_long) {
+                       flags |= 0x800;
+               } else if (size == sz_word) {
+                       flags |= 0x400;
+               }
+       }
+       printf("\tmmufixup[%d].reg = %s | 0x%x;\n", mmufixupcnt, reg, flags);
        printf("\tmmufixup[%d].value = m68k_areg(regs, %s);\n", mmufixupcnt, reg);
        mmufixupstate |= 1 << mmufixupcnt;
        mmufixupcnt++;
@@ -3013,6 +3026,10 @@ static void genamode2x (amodes mode, const char *reg, wordsizes size, const char
        else if (flags & GF_IR2IRC)
                irc2ir (true);
 
+       if (!movem && (mode == Aipi || mode == Apdi)) {
+               addmmufixup(reg, size, mode);
+       }
+
        if (getv == 1) {
                const char *srcbx = !(flags & GF_FC) ? srcb : "sfc_nommu_get_byte";
                const char *srcwx = !(flags & GF_FC) ? srcw : "sfc_nommu_get_word";
@@ -3123,10 +3140,9 @@ static void genamode2x (amodes mode, const char *reg, wordsizes size, const char
 
        /* We now might have to fix up the register for pre-dec or post-inc
        * addressing modes. */
-       if (!movem)
+       if (!movem) {
                switch (mode) {
                case Aipi:
-                       addmmufixup (reg);
                        switch (size) {
                        case sz_byte:
                                printf("\tm68k_areg(regs, %s) += areg_byteinc[%s];\n", reg, reg);
@@ -3138,15 +3154,15 @@ static void genamode2x (amodes mode, const char *reg, wordsizes size, const char
                                printf("\tm68k_areg(regs, %s) += 4;\n", reg);
                                break;
                        default:
-                               term ();
+                               term();
                        }
                        break;
                case Apdi:
-                       addmmufixup (reg);
                        printf("\tm68k_areg(regs, %s) = %sa;\n", reg, name);
                        break;
                default:
                        break;
+               }
        }
 
        if (movem == 3) {
@@ -6005,7 +6021,7 @@ static void gen_opcode (unsigned int opcode)
                // ce confirmed
                // 68040 uses different order than other CPU models.
                if (using_mmu) {
-                       addmmufixup("srcreg");
+                       addmmufixup("srcreg", -1, -1);
                        genamode(NULL, curi->dmode, "dstreg", curi->size, "offs", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, 0);
                        if (cpu_level == 4) {
                                genamode(NULL, Apdi, "7", sz_long, "old", GENA_GETV_FETCH_ALIGN, GENA_MOVEM_DO_INC, 0);
@@ -7557,11 +7573,11 @@ bccl_not68020:
                        printf("\tm68k_dreg(regs, dstreg) = (m68k_dreg(regs, dstreg) & 0xffffff00) | ((val >> 4) & 0xf0) | (val & 0xf);\n");
                } else {
                        printf("\tuae_u16 val;\n");
-                       addmmufixup ("srcreg");
+                       addmmufixup("srcreg", curi->size, curi->smode);
                        printf("\tm68k_areg(regs, srcreg) -= 2;\n");
                        printf("\tval = (uae_u16)(%s(m68k_areg(regs, srcreg)));\n", srcw);
                        printf("\tval += %s;\n", gen_nextiword(0));
-                       addmmufixup ("dstreg");
+                       addmmufixup("dstreg", curi->size, curi->dmode);
                        printf("\tm68k_areg(regs, dstreg) -= areg_byteinc[dstreg];\n");
                        gen_set_fault_pc (false, false);
                        printf("\t%s(m68k_areg(regs, dstreg),((val >> 4) & 0xf0) | (val & 0xf));\n", dstb);
@@ -7575,11 +7591,11 @@ bccl_not68020:
                        printf("\tm68k_dreg(regs, dstreg) = (m68k_dreg(regs, dstreg) & 0xffff0000) | (val & 0xffff);\n");
                } else {
                        printf("\tuae_u16 val;\n");
-                       addmmufixup ("srcreg");
+                       addmmufixup ("srcreg", curi->size, curi->smode);
                        printf("\tm68k_areg(regs, srcreg) -= areg_byteinc[srcreg];\n");
                        printf("\tval = (uae_u16)(%s(m68k_areg(regs, srcreg)) & 0xff);\n", srcb);
                        printf("\tval = (((val << 4) & 0xf00) | (val & 0xf)) + %s;\n", gen_nextiword (0));
-                       addmmufixup ("dstreg");
+                       addmmufixup ("dstreg", curi->size, curi->dmode);
                        printf("\tm68k_areg(regs, dstreg) -= 2;\n");
                        gen_set_fault_pc(false, false);
                        printf("\t%s(m68k_areg(regs, dstreg), val);\n", dstw);
index 13c79001bf5e638ea1041c07f045ca085ff11414..2dbb8545a6d9139e36d6d709c9690c8e46917b22 100644 (file)
@@ -1563,11 +1563,11 @@ void Exception_build_68000_address_error_stack_frame(uae_u16 mode, uae_u16 opcod
 void cpu_restore_fixup(void)
 {
        if (mmufixup[0].reg >= 0) {
-               m68k_areg(regs, mmufixup[0].reg) = mmufixup[0].value;
+               m68k_areg(regs, mmufixup[0].reg & 15) = mmufixup[0].value;
                mmufixup[0].reg = -1;
        }
        if (mmufixup[1].reg >= 0) {
-               m68k_areg(regs, mmufixup[1].reg) = mmufixup[1].value;
+               m68k_areg(regs, mmufixup[1].reg & 15) = mmufixup[1].value;
                mmufixup[1].reg = -1;
        }
 }