]> git.unchartedbackwaters.co.uk Git - francis/winuae.git/commitdiff
Optional basic check for exception 2 and 3. Ignores possible register and CCR partial...
authorToni Wilen <twilen@winuae.net>
Mon, 30 Dec 2019 15:24:31 +0000 (17:24 +0200)
committerToni Wilen <twilen@winuae.net>
Mon, 30 Dec 2019 15:24:31 +0000 (17:24 +0200)
cputest.cpp
cputest/cputest_defines.h
cputest/main.c
cputest/readme.txt

index bf13c8f1d488fd5e945c6b60411727ce5790070f..344e9b3b33673dee4c68d09ceb6cb8fce86b3532 100644 (file)
@@ -2357,7 +2357,7 @@ static uaecptr handle_specials_extra(uae_u16 opcode, uaecptr pc, struct instr *d
 static uae_u32 generate_stack_return(int cnt)
 {
        uae_u32 v;
-       // if targer sp mode: generate random return address
+       // if target sp mode: always generate valid address
        if (target_ea[0] != 0xffffffff && feature_usp < 3) {
                v = target_ea[0];
        } else {
@@ -2366,7 +2366,7 @@ static uae_u32 generate_stack_return(int cnt)
                {
                case 0:
                case 3:
-                       v = opcode_memory_start + 128;
+                       v = opcode_memory_start + 32768;
                        break;
                case 1:
                        v &= 0xffff;
@@ -2569,8 +2569,8 @@ static void execute_ins(uaecptr endpc, uaecptr targetpc, struct instr *dp)
                        break;
                }
 
-               // Supervisor mode and A7 was modified: skip this test round.
-               if (s && regs.regs[15] != a7) {
+               // Supervisor mode and A7 was modified and not RTE+stack mode: skip this test round.
+               if (s && regs.regs[15] != a7 && (dp->mnemo != i_RTE || feature_usp < 3)) {
                        // but not if RTE
                        if (!is_superstack_use_required()) {
                                test_exception = -1;
@@ -2754,10 +2754,20 @@ static uae_u8 *save_exception(uae_u8 *p, struct instr *dp)
                if (cpu_lvl == 0) {
                        if (test_exception == 2 || test_exception == 3) {
                                // status
-                               *p++ = sf[1];
+                               uae_u8 st = sf[1];
+                               // save also current opcode if different than stacked opcode
+                               // used by basic exception check
+                               if (((sf[6] << 8) | sf[7]) != regs.opcode) {
+                                       st |= 0x20;
+                               }
+                               *p++ = st;
                                // opcode (which is not necessarily current opcode!)
                                *p++ = sf[6];
                                *p++ = sf[7];
+                               if (st & 0x20) {
+                                       *p++ = regs.opcode >> 8;
+                                       *p++ = regs.opcode;
+                               }
                                // access address
                                p = store_rel(p, 0, opcode_memory_start, gl(sf + 2), 1);
                        }
@@ -3348,7 +3358,14 @@ static void test_mnemo(const TCHAR *path, const TCHAR *mnemo, const TCHAR *ovrfi
 
                                        }
 
-                                       put_word_test(opcode_memory_address, opc);
+                                       // if bus error stack checking and RTE: copy USP to ISP before RTE
+                                       if (dp->mnemo == i_RTE && feature_usp == 3) {
+                                               put_word_test(opcode_memory_address, 0x4e6f); // MOVE USP,A7
+                                               put_word_test(opcode_memory_address + 2, opc);
+                                               pc += 2;
+                                       } else {
+                                               put_word_test(opcode_memory_address, opc);
+                                       }
 
                                        if (extra_or || extra_and) {
                                                uae_u16 ew = get_word_test(opcode_memory_address + 2);
@@ -3479,13 +3496,13 @@ static void test_mnemo(const TCHAR *path, const TCHAR *mnemo, const TCHAR *ovrfi
                                                        srcaddr = get_long_test(regs.regs[15] + stackoffset);
                                                }
                                                // branch target is not accessible? skip.
-                                               if ((srcaddr >= cur_registers[15] - 16 && srcaddr <= cur_registers[15] + 16) || ((srcaddr & 1) && !feature_exception3_instruction && feature_usp < 2)) {
+                                               if (((srcaddr >= cur_registers[15] - 16 && srcaddr <= cur_registers[15] + 16) && dp->mnemo != i_RTE) || ((srcaddr & 1) && !feature_exception3_instruction && feature_usp < 2)) {
                                                        // lets not jump directly to stack..
                                                        if (verbose) {
                                                                if (srcaddr & 1)
-                                                                       wprintf(_T(" Branch target is odd\n"));
+                                                                       wprintf(_T(" Branch target is odd (%08x)\n"), srcaddr);
                                                                else
-                                                                       wprintf(_T(" Branch target is stack\n"));
+                                                                       wprintf(_T(" Branch target is stack (%08x)\n"), srcaddr);
                                                        }
                                                        memcpy(opcode_memory, oldcodebytes, sizeof(oldcodebytes));
                                                        continue;
@@ -3493,7 +3510,7 @@ static void test_mnemo(const TCHAR *path, const TCHAR *mnemo, const TCHAR *ovrfi
                                                testing_active = 1;
                                                if (!valid_address(srcaddr, 2, 1) || srcaddr + 2 == opcode_memory_start) {
                                                        if (verbose) {
-                                                               wprintf(_T(" Branch target inaccessible\n"));
+                                                               wprintf(_T(" Branch target inaccessible (%08x)\n"), srcaddr);
                                                        }
                                                        testing_active = 0;
                                                        memcpy(opcode_memory, oldcodebytes, sizeof(oldcodebytes));
index 33d15780411d9257f83e2b5736bc7a33b87f38e1..539901e0792fe757d7c416af5c4593f9c0a98aa0 100644 (file)
@@ -1,5 +1,5 @@
 
-#define DATA_VERSION 11
+#define DATA_VERSION 12
 
 #define CT_FPREG 0
 #define CT_DREG 0
index 0ee3e55f62fd4283c856ffeee62ec31ad244393b..95b6005b5e1de52adeb7e9cf5c7d50cf66b4be74 100644 (file)
@@ -117,6 +117,7 @@ static uae_u8 ccr_mask;
 static uae_u32 addressing_mask = 0x00ffffff;
 static uae_u32 interrupt_mask;
 static int disasm;
+static int basicexcept;
 
 #define SIZE_STORED_ADDRESS_OFFSET 8
 #define SIZE_STORED_ADDRESS 16
@@ -1061,8 +1062,8 @@ static void addinfo(void)
                uae_u8 *b = (uae_u8 *)regs.branchtarget - SIZE_STORED_ADDRESS_OFFSET;
                addinfo_bytes("B", b, regs.branchtarget, -SIZE_STORED_ADDRESS_OFFSET, SIZE_STORED_ADDRESS);
        }
-       sprintf(outbp, "STARTPC=%08lx ENDPC=%08lx\n", startpc, endpc);
-       outbp += strlen(outbp);
+//     sprintf(outbp, "STARTPC=%08lx ENDPC=%08lx\n", startpc, endpc);
+//     outbp += strlen(outbp);
 }
 
 struct srbit
@@ -1187,6 +1188,9 @@ static void hexdump(uae_u8 *p, int len)
 
 static uae_u8 last_exception[256], last_exception_extra;
 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 *validate_exception(struct registers *regs, uae_u8 *p, int excnum, int *gotexcnum, int *experr)
 {
@@ -1198,6 +1202,7 @@ static uae_u8 *validate_exception(struct registers *regs, uae_u8 *p, int excnum,
        uae_u8 excdatalen = *p++;
        int size;
        int excrwp = 0;
+       int alts = 0;
 
        if (!excdatalen) {
                return p;
@@ -1225,7 +1230,7 @@ static uae_u8 *validate_exception(struct registers *regs, uae_u8 *p, int excnum,
                                }
                                uae_u32 retv = exceptiontableinuse + (excnum - 2) * 2;
                                if (ret != retv) {
-                                       sprintf(outbp, "Trace (%d stacked) PC mismatch: %08lx != %08lx (%ld)\n", excnum, ret, retv);
+                                       sprintf(outbp, "Trace (%d stacked) PC mismatch: %08lx != %08lx\n", excnum, ret, retv);
                                        outbp += strlen(outbp);
                                        errors = 1;
                                        *experr = 1;
@@ -1277,14 +1282,22 @@ static uae_u8 *validate_exception(struct registers *regs, uae_u8 *p, int excnum,
                if (cpu_lvl == 0) {
                        if (excnum == 2 || excnum == 3) {
                                // status (with undocumented opcode part)
+                               uae_u8 status = p[0];
                                uae_u8 opcode0 = p[1];
                                uae_u8 opcode1 = p[2];
+                               p += 1 + 2;
+                               uae_u8 opcode0b = opcode0;
+                               uae_u8 opcode1b = opcode1;
+                               if (status & 0x20) {
+                                       opcode0b = p[0];
+                                       opcode1b = p[1];
+                                       p += 2;
+                               }
                                exc[0] = opcode0;
-                               exc[1] = (opcode1 & ~0x1f) | p[0];
-                               excrwp = ((p[0] & 0x10) == 0) ? 1 : 0;
-                               if (p[0] & 2)
+                               exc[1] = (opcode1 & ~0x1f) | (status & 0x1f);
+                               excrwp = ((status & 0x10) == 0) ? 1 : 0;
+                               if (status & 2)
                                        excrwp = 2;
-                               p += 3;
                                // access address
                                v = opcode_memory_addr;
                                p = restore_rel_ordered(p, &v);
@@ -1298,6 +1311,23 @@ static uae_u8 *validate_exception(struct registers *regs, uae_u8 *p, int excnum,
                                // pc
                                pl(exc + 10, regs->pc);
                                exclen = 14;
+                               if (basicexcept) {
+                                       // I/N field is not always as documented
+                                       memcpy(alternate_exception1, exc, exclen);
+                                       alternate_exception1[1] ^= 0x08; // I/N
+                                       alts = 1;
+                                       if (status & 0x80) {
+                                               // opcode field is not always current opcode
+                                               memcpy(alternate_exception2, exc, exclen);
+                                               alternate_exception2[0] = opcode0b;
+                                               alternate_exception2[1] = (opcode1b & ~0x1f) | (status & 0x1f);
+                                               alternate_exception2[6] = opcode0b;
+                                               alternate_exception2[7] = opcode1b;
+                                               memcpy(alternate_exception3, alternate_exception2, exclen);
+                                               alternate_exception3[1] ^= 0x08; // I/N
+                                               alts += 2;
+                                       }
+                               }
                        }
                } else if (cpu_lvl > 0) {
                        // sr
@@ -1378,7 +1408,7 @@ static uae_u8 *validate_exception(struct registers *regs, uae_u8 *p, int excnum,
                last_exception_len = exclen;
                if (p != op + excdatalen + 1) {
                        end_test();
-                       printf("Exception length mismatch %d != %d\n", excdatalen, p - op - 1);
+                       printf("Exception %d length mismatch %d != %d\n", excnum, excdatalen, p - op - 1);
                        exit(0);
                }
        } else {
@@ -1389,7 +1419,19 @@ 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)) {
+               err = 1;
+               if (err && alts > 0) {
+                       if (alts >= 1 && !memcmp(alternate_exception1, sp, exclen))
+                               err = 0;
+                       if (alts >= 2 && !memcmp(alternate_exception2, sp, exclen))
+                               err = 0;
+                       if (alts >= 3 && !memcmp(alternate_exception3, sp, exclen))
+                               err = 0;
+               }
+       }
+       if (err) {
                sprintf(outbp, "Exception %ld stack frame mismatch:\n", excnum);
                outbp += strlen(outbp);
                strcpy(outbp, "Expected: ");
@@ -1448,6 +1490,10 @@ static uae_u8 *validate_test(uae_u8 *p, int ignore_errors, int ignore_sr)
                return p + 1;
 
        int experr = 0;
+       int errflag = 0;
+       int errflag_orig = 0;
+       uae_u8 *outbp_old = outbp;
+
        for (;;) {
                uae_u8 v = *p;
                if (v & CT_END) {
@@ -1467,7 +1513,7 @@ static uae_u8 *validate_test(uae_u8 *p, int ignore_errors, int ignore_sr)
                                        sprintf(outbp, "Exception: vector number does not match vector offset! (%d <> %d)\n", exc, cpuexc010);
                                        experr = 1;
                                        outbp += strlen(outbp);
-                                       errors++;
+                                       errflag |= 1 << 16;
                                }
                                break;
                        }
@@ -1475,6 +1521,8 @@ static uae_u8 *validate_test(uae_u8 *p, int ignore_errors, int ignore_sr)
                                if (exc) {
                                        p = validate_exception(&test_regs, p, exc, &cpuexc, &experr);
                                }
+                               errflag_orig = errflag;
+                               errflag = 0;
                                break;
                        }
                        if (exc == 0 && cpuexc == 4) {
@@ -1482,12 +1530,17 @@ static uae_u8 *validate_test(uae_u8 *p, int ignore_errors, int ignore_sr)
                                if (last_registers.pc != test_regs.pc && dooutput) {
                                        sprintf(outbp, "PC: expected %08lx but got %08lx\n", last_registers.pc, test_regs.pc);
                                        outbp += strlen(outbp);
-                                       errors++;
+                                       errflag |= 1 << 16;
                                }
                                break;
                        }
                        if (exc) {
                                p = validate_exception(&test_regs, p, exc, &cpuexc, &experr);
+                               if (basicexcept && (cpuexc == 2 || cpuexc == 3)) {
+                                       errflag_orig = errflag;
+                                       errflag &= ~(1 << 0);
+                                       errflag &= ~(1 << 7);
+                               }
                        }
                        if (exc != cpuexc && exc >= 2) {
                                addinfo();
@@ -1502,7 +1555,7 @@ static uae_u8 *validate_test(uae_u8 *p, int ignore_errors, int ignore_sr)
                                        experr = 1;
                                }
                                outbp += strlen(outbp);
-                               errors++;
+                               errflag |= 1 << 16;
                        }
                        break;
                }
@@ -1518,7 +1571,7 @@ static uae_u8 *validate_test(uae_u8 *p, int ignore_errors, int ignore_sr)
                                        sprintf(outbp, "%c%d: expected %08lx but got %08lx\n", mode < CT_AREG ? 'D' : 'A', mode & 7, val, test_regs.regs[mode]);
                                        outbp += strlen(outbp);
                                }
-                               errors++;
+                               errflag |= 1 << 0;
                        }
                        regs_changed[mode] = 0;
                        last_registers.regs[mode] = val;
@@ -1533,7 +1586,7 @@ static uae_u8 *validate_test(uae_u8 *p, int ignore_errors, int ignore_sr)
                                                test_regs.fpuregs[mode].exp, test_regs.fpuregs[mode].m[0], test_regs.fpuregs[mode].m[1]);
                                        outbp += strlen(outbp);
                                }
-                               errors++;
+                               errflag |= 1 << 1;
                        }
                        regs_fpuchanged[mode] = 0;
                        xmemcpy(&last_registers.fpuregs[mode], &val, sizeof(struct fpureg));
@@ -1543,7 +1596,6 @@ static uae_u8 *validate_test(uae_u8 *p, int ignore_errors, int ignore_sr)
                        // High 16 bit: ignore mask, low 16 bit: SR/CCR
                        p = restore_value(p, &val, &size);
                        test_ccrignoremask = ~(val >> 16);
-
                        if ((val & (sr_undefined_mask & test_ccrignoremask)) != (test_regs.sr & (sr_undefined_mask & test_ccrignoremask)) && !ignore_errors && !ignore_sr) {
                                addinfo();
                                if (dooutput) {
@@ -1554,20 +1606,29 @@ static uae_u8 *validate_test(uae_u8 *p, int ignore_errors, int ignore_sr)
                                                outbp += strlen(outbp);
                                        }
                                        *outbp++ = '\n';
+                                       errflag |= 1 << 2;
+                                       errflag |= 1 << 7;
+                               }
+                               uae_u16 mask = test_ccrignoremask & 0xff00;
+                               if ((val & (sr_undefined_mask & mask)) == (test_regs.sr & (sr_undefined_mask & mask))) {
+                                       errflag &= ~(1 << 2);
+                               }
+                               mask = test_ccrignoremask & 0x00ff;
+                               if ((val & (sr_undefined_mask & mask)) == (test_regs.sr & (sr_undefined_mask & mask))) {
+                                       errflag &= ~(1 << 7);
                                }
-                               errors++;
                        }
                        sr_changed = 0;
                        last_registers.sr = val;
                        if (!(test_regs.expsr & 0x2000)) {
                                sprintf(outbp, "SR S-bit is not set at start of exception handler!\n");
                                outbp += strlen(outbp);
-                               errors++;
+                               errflag |= 1 << 16;
                        }
                        if ((test_regs.expsr & 0xff) != (test_regs.sr & 0xff)) {
                                sprintf(outbp, "Exception stacked CCR != CCR at start of exception handler!\n");
                                outbp += strlen(outbp);
-                               errors++;
+                               errflag |= 1 << 16;
                        }
 
                } else if (mode == CT_PC) {
@@ -1585,7 +1646,7 @@ static uae_u8 *validate_test(uae_u8 *p, int ignore_errors, int ignore_sr)
                                        sprintf(outbp, "FPCR: expected %08lx -> %08lx but got %08lx\n", test_fpcr, val, test_regs.fpcr);
                                        outbp += strlen(outbp);
                                }
-                               errors++;
+                               errflag |= 1 << 3;
                        }
                        fpcr_changed = 0;
                        last_registers.fpcr = val;
@@ -1599,7 +1660,7 @@ static uae_u8 *validate_test(uae_u8 *p, int ignore_errors, int ignore_sr)
                                        sprintf(outbp, "FPSR: expected %08lx -> %08lx but got %08lx\n", test_fpsr, val, test_regs.fpsr);
                                        outbp += strlen(outbp);
                                }
-                               errors++;
+                               errflag |= 1 << 4;
                        }
                        fpsr_changed = 0;
                        last_registers.fpsr = val;
@@ -1612,7 +1673,7 @@ static uae_u8 *validate_test(uae_u8 *p, int ignore_errors, int ignore_sr)
                                        sprintf(outbp, "FPIAR: expected %08x but got %08x\n", val, test_regs.fpiar);
                                        outbp += strlen(outbp);
                                }
-                               errors++;
+                               errflag |= 1 << 5;
                        }
                        fpiar_changed = 0;
                        last_registers.fpiar = val;
@@ -1636,7 +1697,7 @@ static uae_u8 *validate_test(uae_u8 *p, int ignore_errors, int ignore_sr)
                                                sprintf(outbp, "Memory byte write: address %08lx, expected %02x but got %02x\n", (uae_u32)addr, val, mval);
                                                outbp += strlen(outbp);
                                        }
-                                       errors++;
+                                       errflag |= 1 << 6;
                                }
                                addr[0] = oldval;
                                break;
@@ -1648,7 +1709,7 @@ static uae_u8 *validate_test(uae_u8 *p, int ignore_errors, int ignore_sr)
                                                sprintf(outbp, "Memory word write: address %08lx, expected %04x but got %04x\n", (uae_u32)addr, val, mval);
                                                outbp += strlen(outbp);
                                        }
-                                       errors++;
+                                       errflag |= 1 << 6;
                                }
                                addr[0] = oldval >> 8;
                                addr[1] = oldval;
@@ -1661,7 +1722,7 @@ static uae_u8 *validate_test(uae_u8 *p, int ignore_errors, int ignore_sr)
                                                sprintf(outbp, "Memory long write: address %08lx, expected %08lx but got %08x\n", (uae_u32)addr, val, mval);
                                                outbp += strlen(outbp);
                                        }
-                                       errors++;
+                                       errflag |= 1 << 6;
                                }
                                pl(addr, oldval);
                                break;
@@ -1681,7 +1742,7 @@ static uae_u8 *validate_test(uae_u8 *p, int ignore_errors, int ignore_sr)
                                                sprintf(outbp, "%c%d: modified %08lx -> %08lx but expected no modifications\n", i < 8 ? 'D' : 'A', i & 7, last_registers.regs[i], test_regs.regs[i]);
                                                outbp += strlen(outbp);
                                        }
-                                       errors++;
+                                       errflag |= 1 << 0;
                                }
                        }
                        if (sr_changed) {
@@ -1690,7 +1751,7 @@ static uae_u8 *validate_test(uae_u8 *p, int ignore_errors, int ignore_sr)
                                        sprintf(outbp, "SR: modified %04x -> %04x but expected no modifications\n", last_registers.sr & 0xffff, test_regs.sr & 0xffff);
                                        outbp += strlen(outbp);
                                }
-                               errors++;
+                               errflag |= 1 << 2;
                        }
                }
                for (int i = 0; i < 8; i++) {
@@ -1702,7 +1763,7 @@ static uae_u8 *validate_test(uae_u8 *p, int ignore_errors, int ignore_sr)
                                                test_regs.fpuregs[i].exp, test_regs.fpuregs[i].m[0], test_regs.fpuregs[i].m[1]);
                                        outbp += strlen(outbp);
                                }
-                               errors++;
+                               errflag |= 1 << 1;
                        }
                }
                if (fpsr_changed) {
@@ -1711,7 +1772,7 @@ static uae_u8 *validate_test(uae_u8 *p, int ignore_errors, int ignore_sr)
                                sprintf(outbp, "FPSR: modified %08x -> %08x but expected no modifications\n", last_registers.fpsr, test_regs.fpsr);
                                outbp += strlen(outbp);
                        }
-                       errors++;
+                       errflag |= 1 << 3;
                }
                if (fpcr_changed) {
                        addinfo();
@@ -1719,7 +1780,7 @@ static uae_u8 *validate_test(uae_u8 *p, int ignore_errors, int ignore_sr)
                                sprintf(outbp, "FPCR: modified %08x -> %08x but expected no modifications\n", last_registers.fpcr, test_regs.fpcr);
                                outbp += strlen(outbp);
                        }
-                       errors++;
+                       errflag |= 1 << 4;
                }
                if (fpiar_changed) {
                        addinfo();
@@ -1727,10 +1788,10 @@ static uae_u8 *validate_test(uae_u8 *p, int ignore_errors, int ignore_sr)
                                sprintf(outbp, "FPIAR: modified %08x -> %08x but expected no modifications\n", last_registers.fpiar, test_regs.fpiar);
                                outbp += strlen(outbp);
                        }
-                       errors++;
+                       errflag |= 1 << 5;
                }
        }
-       if (errors && dooutput) {
+       if (errflag && dooutput) {
                addinfo();
                if (!fpu_model) {
                        strcat(outbp, "Registers before:\n");
@@ -1758,6 +1819,12 @@ static uae_u8 *validate_test(uae_u8 *p, int ignore_errors, int ignore_sr)
                        sprintf(outbp, "OK: No exception generated\n");
                        outbp += strlen(outbp);
                }
+               errors++;
+       }
+       if (!errflag && errflag_orig && dooutput) {
+               outbp = outbp_old;
+               *outbp = 0;
+               infoadded = 0;
        }
        return p;
 }
@@ -2303,6 +2370,8 @@ int main(int argc, char *argv[])
                printf("all <mnemonic> = test all, starting from <mnemonic>\n");
                printf("continue = don't stop on error (all mode only)\n");
                printf("ccrmask = ignore CCR bits that are not set.\n");
+               printf("nodisasm = do not disassemble failed test.\n");
+               printf("basicexc = do only basic checks when exception is 2 or 3.\n");
                return 0;
        }
 
@@ -2343,6 +2412,8 @@ int main(int argc, char *argv[])
                        cpu_lvl = 5;
                } else if (!_stricmp(s, "nodisasm")) {
                        disasm = 0;
+               } else if (!_stricmp(s, "basicexc")) {
+                       basicexcept = 1;
                }
        }
 
index 48517c69adbf3890fa71d4b32172987783f29d2c..9baedfa03a46992538dfefbfc93768d97361cda6 100644 (file)
@@ -11,14 +11,14 @@ Verifies:
 - Generated exception and stack frame contents (if any)
 - Memory writes, including stack modifications (if any)
 - Loop mode for JIT testing. (generates <test instruction>, dbf dn,loop)
-- Supports 68000, 68020, 68030 (only difference between 020 and 030 seems to be data cache and MMU), 68040 and 68060. (I don't currently have real 68010)
+- Supports 68000, 68010, 68020, 68030 (only difference between 020 and 030 seems to be data cache and MMU), 68040 and 68060.
 
 Tests executed for each tested instruction:
 
-- Every CCR combination (32 tests)
+- Every CCR combination or optionally only all zeros, all ones CCR (32 or 2 tests)
 - Every FPU condition combination (4 bits) + 2 precision bits + 2 rounding bits (256 tests)
 - Every addressing mode, including optionally 68020+ addressing modes.
-- If instruction generated privilege violation exception, extra test round is run in supervisor mode (Total 64 tests).
+- If instruction generated privilege violation exception, extra test round is run in supervisor mode.
 - Optionally can do any combination of T0, T1, S and M -bit SR register extra test rounds.
 - Every opcode value is tested. Total number of tests per opcode depends on available addressing modes etc. It can be hundreds of thousands or even millions..
 
@@ -29,20 +29,19 @@ If 68000/68010 and address error testing is enabled: 2 extra test rounds are gen
 
 Notes and limitations:
 
-- Test generator is very brute force based, it should be more intelligent..
-- Address error testing is optional, if disabled, generated tests never cause address errors.
+- Test generator is very brute force based, it should be more intelligent.. Now has optional target src/dst/opcode modes for better bus/address error testing.
+- Bus and address error testing is optional, if disabled, generated tests never cause bus/address errors.
 - RTE test only tests stack frame types 0 and 2 (if 68020+)
 - All tests that would halt or reset the CPU are skipped (RESET in supervisor mode, STOP parameter that would stop the CPU etc)
 - Single instruction test set will take long time to run on real 68000. Few minutes to much longer...
-- Undefined flags (for example DIV and CHK) are also verified. It probably would be good idea to optionally filter them out.
+- Undefined flags (for example DIV and CHK or 68000/010 bus address error) are also verified. It probably would be good idea to optionally filter them out.
 - Instruction cycle order or timing is ignored. It is not possible without extra hardware.
-- 68000 bus errors are not tested but there are some plans for future version with custom hardware. (Hatari also uses UAE CPU core)
 - FPU testing is not yet fully implemented.
 - Sometimes reported old and new condition code state does not match error report..
 
 Tester compatibility (integer instructions only):
 
-68000: Complete. Bus errors are only supported partially.
+68000: Complete. Including bus and address error stack frame/register/CCR modification undocumented behavior.
 68010: Partially supported.
 68020: Almost complete (DIV undocumented behavior is not yet known)
 68030: Same as 68020.
@@ -76,7 +75,7 @@ Build instructions:
 
 Test generator quick instructions:
 
-Update cputestgen.ini to match your CPU model, memory settings etc...
+Update cputestgen.ini to match your CPU model, memory settings etc.
 
 "Low memory" = memory accessible using absolute word addressing mode, positive value (0x0000 to 0x7fff). Can be larger.
 "High memory" = memory accessible using absolute word addressing mode, negative value (0xFFF8000 to 0xFFFFFFFF)