]> git.unchartedbackwaters.co.uk Git - francis/winuae.git/commitdiff
68010 read bus error support.
authorToni Wilen <twilen@winuae.net>
Sat, 11 Jan 2020 11:03:54 +0000 (13:03 +0200)
committerToni Wilen <twilen@winuae.net>
Sat, 11 Jan 2020 11:03:54 +0000 (13:03 +0200)
cputest.cpp
cputest/main.c
gencpu.cpp

index a76f51079f0c32394507dd1396ce1a5544a25e0f..838fc726cb91982395605a3214a67d954e7b4e00 100644 (file)
@@ -853,7 +853,7 @@ static void doexcstack2(void)
                        ssw |= test_exception_3_size == 0 ? 0x0200 : 0x0000; // BY
                        ssw |= test_exception_3_w ? 0x0000 : 0x0100; // RW
                        regs.mmu_fault_addr = test_exception_addr;
-                       Exception_build_stack_frame(regs.instruction_pc, regs.pc, ssw, 3, 0x08);
+                       Exception_build_stack_frame(regs.instruction_pc, regs.pc, ssw, test_exception, 0x08);
                        SPCFLAG_DOTRACE = 0;
                } else {
                        Exception_build_stack_frame_common(regs.instruction_pc, regs.pc, 0, test_exception);
@@ -863,7 +863,7 @@ static void doexcstack2(void)
                        uae_u16 ssw = (sv ? 4 : 0) | test_exception_3_fc;
                        ssw |= 0x20;
                        regs.mmu_fault_addr = test_exception_addr;
-                       Exception_build_stack_frame(regs.instruction_pc, regs.pc, ssw, 3, 0x0b);
+                       Exception_build_stack_frame(regs.instruction_pc, regs.pc, ssw, test_exception, 0x0b);
                } else {
                        Exception_build_stack_frame_common(regs.instruction_pc, regs.pc, 0, test_exception);
                }
@@ -871,7 +871,7 @@ static void doexcstack2(void)
                if (test_exception == 3) {
                        if (currprefs.cpu_model >= 68040)
                                test_exception_addr &= ~1;
-                       Exception_build_stack_frame(test_exception_addr, regs.pc, 0, 3, 0x02);
+                       Exception_build_stack_frame(test_exception_addr, regs.pc, 0, test_exception, 0x02);
                } else {
                        Exception_build_stack_frame_common(regs.instruction_pc, regs.pc, 0, test_exception);
                }
index c02c4a70c60bacaf21a1e46b675f1db467090b55..6e85a55dc25bd132a9d803a1d79c006c84880a30 100644 (file)
@@ -1314,6 +1314,24 @@ static int last_exception_len;
 static uae_u8 alternate_exception1[256];
 static uae_u8 alternate_exception2[256];
 static uae_u8 alternate_exception3[256];
+static uae_u8 masked_exception[256];
+static int mask_exception;
+static int exception_stored;
+
+static int compare_exception(uae_u8 *s1, uae_u8 *s2, int len, int domask, uae_u8 *mask)
+{
+       if (!domask) {
+               return memcmp(s1, s2, len);
+       } else {
+               for (int i = 0; i < len; i++) {
+                       if (mask[i])
+                               continue;
+                       if (s1[i] != s2[i])
+                               return 1;
+               }
+               return 0;
+       }
+}
 
 static uae_u8 *validate_exception(struct registers *regs, uae_u8 *p, int excnum, int *gotexcnum, int *experr)
 {
@@ -1327,6 +1345,7 @@ static uae_u8 *validate_exception(struct registers *regs, uae_u8 *p, int excnum,
        int excrwp = 0;
        int alts = 0;
 
+       mask_exception = 0;
        if (!excdatalen) {
                return p;
        }
@@ -1491,45 +1510,59 @@ static uae_u8 *validate_exception(struct registers *regs, uae_u8 *p, int excnum,
                                exclen = 16;
                                break;
                        case 8: // 68010 bus/address error
-                               exc[8] = *p++;
-                               exc[9] = *p++;
-                               excrwp = ((exc[8] & 1) == 0) ? 1 : 0;
-                               if (exc[9] & 2)
-                                       excrwp = 2;
-                               v = opcode_memory_addr;
-                               p = restore_rel_ordered(p, &v);
-                               pl(exc + 10, v);
-                               // data out
-                               exc[16] = *p++;
-                               exc[17] = *p++;
-                               // data in
-                               exc[20] = *p++;
-                               exc[21] = *p++;
-                               // inst
-                               exc[24] = *p++;
-                               exc[25] = *p++;
-                               exc[14] = exc[15] = 0;
-                               sp[14] = sp[15] = 0;
-                               exc[18] = exc[19] = 0;
-                               sp[18] = sp[19] = 0;
-                               exc[22] = exc[23] = 0;
-                               sp[22] = sp[23] = 0;
-                               // ignore undocumented data
-                               exclen = 26;
-                               // read input buffer may contain either actual data read from memory or previous read data
-                               // this depends on hardware, cpu does dummy read cycle and some hardware returns memory data, some ignore it.
-                               memcpy(alternate_exception1, exc, exclen);
-                               memcpy(alternate_exception2, exc, exclen);
-                               alternate_exception1[20] = p[0];
-                               alternate_exception1[21] = p[1];
-                               memcpy(alternate_exception3, alternate_exception1, exclen);
-                               // same with instruction input buffer if branch instruction generates address error
-                               alternate_exception2[24] = p[0];
-                               alternate_exception2[25] = p[1];
-                               alternate_exception3[24] = p[0];
-                               alternate_exception3[25] = p[1];
-                               p += 2;
-                               alts = 3;
+                               {
+                                       exc[8] = *p++;
+                                       exc[9] = *p++;
+                                       excrwp = ((exc[8] & 1) == 0) ? 1 : 0;
+                                       if (exc[9] & 2)
+                                               excrwp = 2;
+                                       uae_u32 fault_addr = opcode_memory_addr;
+                                       p = restore_rel_ordered(p, &fault_addr);
+                                       pl(exc + 10, fault_addr);
+                                       // data out
+                                       exc[16] = *p++;
+                                       exc[17] = *p++;
+                                       // data in
+                                       exc[20] = *p++;
+                                       exc[21] = *p++;
+                                       // inst
+                                       exc[24] = *p++;
+                                       exc[25] = *p++;
+                                       exc[14] = exc[15] = 0;
+                                       sp[14] = sp[15] = 0;
+                                       exc[18] = exc[19] = 0;
+                                       sp[18] = sp[19] = 0;
+                                       exc[22] = exc[23] = 0;
+                                       sp[22] = sp[23] = 0;
+                                       if (basicexcept) {
+                                               exclen = 14;
+                                       } else {
+                                               // ignore undocumented data
+                                               exclen = 26;
+                                               // read input buffer may contain either actual data read from memory or previous read data
+                                               // this depends on hardware, cpu does dummy read cycle and some hardware returns memory data, some ignore it.
+                                               memcpy(alternate_exception1, exc, exclen);
+                                               memcpy(alternate_exception2, exc, exclen);
+                                               alternate_exception1[20] = p[0];
+                                               alternate_exception1[21] = p[1];
+                                               memcpy(alternate_exception3, alternate_exception1, exclen);
+                                               // same with instruction input buffer if branch instruction generates address error
+                                               alternate_exception2[24] = p[0];
+                                               alternate_exception2[25] = p[1];
+                                               alternate_exception3[24] = p[0];
+                                               alternate_exception3[25] = p[1];
+                                               if (excnum == 2 || !is_valid_test_addr_readwrite(fault_addr - 4) || !is_valid_test_addr_readwrite(fault_addr + 4)) {
+                                                       // bus error read: cpu may still the data, depends on hardware.
+                                                       // ignore input buffer contents
+                                                       mask_exception = 1;
+                                                       memset(masked_exception, 0, sizeof(masked_exception));
+                                                       masked_exception[20] = 1;
+                                                       masked_exception[21] = 1;
+                                               }
+                                               alts = 3;
+                                       }
+                                       p += 2;
+                               }
                                break;
                        case 0x0a:
                        case 0x0b:
@@ -1557,14 +1590,14 @@ static uae_u8 *validate_exception(struct registers *regs, uae_u8 *p, int excnum,
        if (exclen == 0 || *gotexcnum != excnum)
                return p;
        int err = 0;
-       if (memcmp(exc, sp, exclen)) {
+       if (compare_exception(exc, sp, exclen, mask_exception, masked_exception)) {
                err = 1;
                if (err && alts > 0) {
-                       if (alts >= 1 && !memcmp(alternate_exception1, sp, exclen))
+                       if (alts >= 1 && !compare_exception(alternate_exception1, sp, exclen, mask_exception, masked_exception))
                                err = 0;
-                       if (alts >= 2 && !memcmp(alternate_exception2, sp, exclen))
+                       if (alts >= 2 && !compare_exception(alternate_exception2, sp, exclen, mask_exception, masked_exception))
                                err = 0;
-                       if (alts >= 3 && !memcmp(alternate_exception3, sp, exclen))
+                       if (alts >= 3 && !compare_exception(alternate_exception3, sp, exclen, mask_exception, masked_exception))
                                err = 0;
                }
        }
@@ -1579,9 +1612,11 @@ static uae_u8 *validate_exception(struct registers *regs, uae_u8 *p, int excnum,
                hexdump(sp, exclen);
                *experr = 1;
        }
+       exception_stored = exclen;
        return p;
 }
 
+
 // regs: registers before execution of test code
 // test_reg: registers used during execution of test code, also modified by test code.
 // last_registers: registers after modifications from data files. Test ok if test_reg == last_registers.
@@ -1629,6 +1664,7 @@ static uae_u8 *validate_test(uae_u8 *p, int ignore_errors, int ignore_sr)
        int errflag = 0;
        int errflag_orig = 0;
        uae_u8 *outbp_old = outbp;
+       exception_stored = 0;
 
        for (;;) {
                uae_u8 v = *p;
@@ -1944,8 +1980,11 @@ static uae_u8 *validate_test(uae_u8 *p, int ignore_errors, int ignore_sr)
                out_regs(&test_regs, 0);
                if (exc > 1) {
                        if (!experr) {
-                               sprintf(outbp, "OK: Generated exception %d\n", exc);
+                               sprintf(outbp, "OK: exception %d ", exc);
                                outbp += strlen(outbp);
+                               if (exception_stored) {
+                                       hexdump(last_exception, exception_stored);
+                               }
                        }
                        if ((exc == 3 || exc == 2) && cpu_lvl == 0) {
                                sprintf(outbp, "RW=%d IN=%d FC=%d\n",
index e5729c876a50601519be44affc417294850a4a5b..e72f92703857a170e9eb55d352b68cd7a523d04f 100644 (file)
@@ -1739,6 +1739,12 @@ static int do_bus_error_fixes(const char *name, int offset, int write)
                                printf("\t\tregs.sr = sr;\n");
                                printf("\t\tMakeFromSR();\n");
                        }
+               } else if (cpu_level == 1) {
+                       // -(an).l where first word causes bus error: An is not modified
+                       // -(an).l where second word causes bus error: An is modified
+                       if (g_instr->size != sz_long || (g_instr->size == sz_long && offset)) {
+                               printf("\t\tm68k_areg(regs, %s) = %sa;\n", bus_error_reg, name);
+                       }
                } else {
                        printf("\t\tm68k_areg(regs, %s) = %sa;\n", bus_error_reg, name);
                }
@@ -1848,13 +1854,21 @@ static void check_bus_error(const char *name, int offset, int write, int size, c
                        }
                }
 
-               if (cpu_level == 1 && g_instr->mnemo == i_MVSR2 && !write) {
-                       printf("\t\topcode |= 0x20000;\n"); // upper byte of SSW is zero -flag.
-               }
+               if (cpu_level == 1) {
+                       // 68010 bus/address error HB bit
+                       if (extra) {
+                               printf("\t\topcode |= 0x%x;\n", extra);
+                       }
+                       // upper byte of SSW is zero -flag.
+                       if (g_instr->mnemo == i_MVSR2 && !write) {
+                               printf("\t\topcode |= 0x20000;\n");
+                       }
+                       // read bus error, -(an).w/.l: pre-decrement is done first.
+                       if (!write && g_instr->smode == Apdi && g_instr->size == sz_long) {
+
+                               //printf("\t\tm68k_areg(regs, %s) = %sa;\n", bus_error_reg, name);
+                       }
 
-               // 68010 bus/address error HB bit
-               if (extra && cpu_level == 1) {
-                       printf("\t\topcode |= 0x%x;\n", extra);
                }
 
                // write causing bus error and trace: set I/N
@@ -2933,6 +2947,7 @@ static void genamode2x (amodes mode, const char *reg, wordsizes size, const char
                printf("\tif (%sa & 1) {\n", name);
 
                if (cpu_level == 1) {
+                       int bus_error_reg_add_old = bus_error_reg_add;
                        // 68010 does dummy access
                        if (getv != 2) {
                                if ((flags & GF_REVERSE) && size == sz_long) {
@@ -2957,10 +2972,11 @@ static void genamode2x (amodes mode, const char *reg, wordsizes size, const char
                        } else {
                                do_bus_error_fixes(name, 0, getv == 2);
                        }
-                       // x,-(an): an is modified
-                       if (mode == Apdi && g_instr->size == sz_word && g_instr->mnemo != i_CLR) {
+                       // x,-(an): an is modified (MOVE to CCR counts as word sized)
+                       if (mode == Apdi && (g_instr->size == sz_word || g_instr->size == i_MV2SR) && g_instr->mnemo != i_CLR) {
                                printf("\t\tm68k_areg(regs, %s) = %sa;\n", reg, name);
                        }
+                       bus_error_reg_add = bus_error_reg_add_old;
                }
 
                if (g_instr->mnemo == i_ADDX || g_instr->mnemo == i_SUBX) {