]> git.unchartedbackwaters.co.uk Git - francis/winuae.git/commitdiff
CPU tester target ea mode and wip bus error test support.
authorToni Wilen <twilen@winuae.net>
Sun, 29 Sep 2019 15:54:34 +0000 (18:54 +0300)
committerToni Wilen <twilen@winuae.net>
Sun, 29 Sep 2019 15:54:34 +0000 (18:54 +0300)
cputest.cpp
cputest/asm.S
cputest/cputest_defines.h
cputest/cputestgen.ini
cputest/main.c
cputest/makefile
cputest/makefile.st

index fd08746b87420aae10200c06d628f07686cc451d..21cfeefb8dff5b37889a73bfb7bebc39a25f16af 100644 (file)
@@ -5,6 +5,7 @@
 #include "disasm.h"
 #include "ini.h"
 #include "fpp.h"
+#include "mmu_common.h"
 
 #include "options.h"
 
@@ -40,6 +41,8 @@ const int imm8_table[] = { 8, 1, 2, 3, 4, 5, 6, 7 };
 int movem_index1[256];
 int movem_index2[256];
 int movem_next[256];
+int bus_error_offset;
+
 struct mmufixup mmufixup[2];
 cpuop_func *cpufunctbl[65536];
 struct cputbl_data
@@ -66,6 +69,7 @@ static int feature_flag_mode = 0;
 static uae_u32 feature_addressing_modes[2];
 static int ad8r[2], pc8r[2];
 static int multi_mode;
+static uae_u32 feature_target_ea[2];
 
 #define HIGH_MEMORY_START (addressing_mask == 0xffffffff ? 0xffff8000 : 0x00ff8000)
 
@@ -81,6 +85,8 @@ static uae_u32 test_high_memory_start;
 static uae_u32 test_high_memory_end;
 static uae_u32 low_memory_size = 32768;
 static uae_u32 high_memory_size = 32768;
+static uae_u32 safe_memory_start;
+static uae_u32 safe_memory_end;
 
 static uae_u8 *low_memory, *high_memory, *test_memory;
 static uae_u8 *low_memory_temp, *high_memory_temp, *test_memory_temp;
@@ -103,6 +109,7 @@ static uaecptr test_exception_addr;
 static int test_exception_3_w;
 static int test_exception_3_fc;
 static int test_exception_opcode;
+
 static uae_u8 imm8_cnt;
 static uae_u16 imm16_cnt;
 static uae_u32 imm32_cnt;
@@ -122,6 +129,7 @@ static int low_memory_accessed;
 static int high_memory_accessed;
 static int test_memory_accessed;
 static uae_u16 extra_or, extra_and;
+static uae_u32 cur_registers[MAX_REGISTERS];
 
 struct uae_prefs currprefs;
 
@@ -159,7 +167,7 @@ static bool valid_address(uaecptr addr, int size, int w)
                if (addr < test_low_memory_start || test_low_memory_start == 0xffffffff)
                        goto oob;
                // exception vectors needed during tests
-               if ((addr + size >= 0x0c && addr < 0x30 || (addr + size >= 0x80 && addr < 0xc0)) && regs.vbr == 0)
+               if ((addr + size >= 0x08 && addr < 0x30 || (addr + size >= 0x80 && addr < 0xc0)) && regs.vbr == 0)
                        goto oob;
                if (addr + size >= test_low_memory_end)
                        goto oob;
@@ -250,13 +258,39 @@ oob:
        return dummy_memory;
 }
 
+static void check_bus_error(uaecptr addr, int write, int fc)
+{
+       if (!testing_active)
+               return;
+       if (safe_memory_start == 0xffffffff && safe_memory_end == 0xffffffff)
+               return;
+       if (addr >= safe_memory_start && addr < safe_memory_end) {
+               test_exception = 2;
+               test_exception_3_w = write;
+               test_exception_addr = addr;
+               test_exception_3_fc = fc;
+               THROW(2);
+       }
+}
+
+static uae_u16 get_iword_test(uaecptr addr)
+{
+       check_bus_error(addr, 0, regs.s ? 6 : 2);
+       if (addr & 1) {
+               return (get_byte_test(addr + 0) << 8) | (get_byte_test(addr + 1) << 0);
+       } else {
+               uae_u8 *p = get_addr(addr, 2, 0);
+               return (p[0] << 8) | (p[1]);
+       }
+}
+
 uae_u16 get_word_test_prefetch(int o)
 {
        // no real prefetch
        if (cpu_lvl < 2)
                o -= 2;
-       regs.irc = get_word_test(m68k_getpci() + o + 2);
-       return get_word_test(m68k_getpci() + o);
+       regs.irc = get_iword_test(m68k_getpci() + o + 2);
+       return get_iword_test(m68k_getpci() + o);
 }
 
 // Move from SR does two writes to same address:
@@ -273,6 +307,7 @@ static void previoussame(uaecptr addr, int size)
 
 void put_byte_test(uaecptr addr, uae_u32 v)
 {
+       check_bus_error(addr, 1, regs.s ? 5 : 1);
        uae_u8 *p = get_addr(addr, 1, 1);
        if (!out_of_test_space && !noaccesshistory) {
                previoussame(addr, sz_byte);
@@ -290,6 +325,7 @@ void put_byte_test(uaecptr addr, uae_u32 v)
 }
 void put_word_test(uaecptr addr, uae_u32 v)
 {
+       check_bus_error(addr, 1, regs.s ? 5 : 1);
        if (addr & 1) {
                put_byte_test(addr + 0, v >> 8);
                put_byte_test(addr + 1, v >> 0);
@@ -313,6 +349,7 @@ void put_word_test(uaecptr addr, uae_u32 v)
 }
 void put_long_test(uaecptr addr, uae_u32 v)
 {
+       check_bus_error(addr, 1, regs.s ? 5 : 1);
        if (addr & 1) {
                put_byte_test(addr + 0, v >> 24);
                put_word_test(addr + 1, v >> 8);
@@ -372,11 +409,13 @@ static void undo_memory(struct accesshistory *ahp, int  *cntp)
 
 uae_u32 get_byte_test(uaecptr addr)
 {
+       check_bus_error(addr, 0, regs.s ? 5 : 1);
        uae_u8 *p = get_addr(addr, 1, 0);
        return *p;
 }
 uae_u32 get_word_test(uaecptr addr)
 {
+       check_bus_error(addr, 0, regs.s ? 5 : 1);
        if (addr & 1) {
                return (get_byte_test(addr + 0) << 8) | (get_byte_test(addr + 1) << 0);
        } else {
@@ -386,6 +425,7 @@ uae_u32 get_word_test(uaecptr addr)
 }
 uae_u32 get_long_test(uaecptr addr)
 {
+       check_bus_error(addr, 0, regs.s ? 5 : 1);
        if (addr & 1) {
                uae_u8 v0 = get_byte_test(addr + 0);
                uae_u16 v1 = get_word_test(addr + 1);
@@ -742,7 +782,7 @@ static void doexcstack(void)
        uaecptr tmp = m68k_areg(regs, 7);
        m68k_areg(regs, 7) = test_memory_end + EXTRA_RESERVED_SPACE;
        if (cpu_lvl == 0) {
-               if (test_exception == 3) {
+               if (test_exception == 2 || test_exception == 3) {
                        uae_u16 mode = (sv ? 4 : 0) | test_exception_3_fc;
                        mode |= test_exception_3_w ? 0 : 16;
                        Exception_build_68000_address_error_stack_frame(mode, opcode, test_exception_addr, regs.pc);
@@ -1249,6 +1289,14 @@ static void save_data(uae_u8 *dst, const TCHAR *dir)
                fwrite(data, 1, 4, f);
                pl(data, test_high_memory_end);
                fwrite(data, 1, 4, f);
+               pl(data, safe_memory_start);
+               fwrite(data, 1, 4, f);
+               pl(data, safe_memory_end);
+               fwrite(data, 1, 4, f);
+               pl(data, 0);
+               fwrite(data, 1, 4, f);
+               pl(data, 0);
+               fwrite(data, 1, 4, f);
                fwrite(inst_name, 1, sizeof(inst_name) - 1, f);
                fclose(f);
                filecount++;
@@ -1314,14 +1362,10 @@ static uaecptr putfpuimm(uaecptr pc, int opcodesize, int *isconstant)
 }
 
 // generate mostly random EA.
-static int create_ea(uae_u16 *opcodep, uaecptr pc, int mode, int reg, struct instr *dp, int *isconstant, int srcdst, int fpuopcode, int opcodesize)
+static int create_ea_random(uae_u16 *opcodep, uaecptr pc, int mode, int reg, struct instr *dp, int *isconstant, int srcdst, int fpuopcode, int opcodesize, uae_u32 *eap)
 {
        uaecptr old_pc = pc;
        uae_u16 opcode = *opcodep;
-       int am = mode >= imm ? imm : mode;
-
-       if (!((1 << am) & feature_addressing_modes[srcdst]))
-               return -1;
 
        switch (mode)
        {
@@ -1338,12 +1382,14 @@ static int create_ea(uae_u16 *opcodep, uaecptr pc, int mode, int reg, struct ins
        case Aind:
        case Aipi:
        case Apdi:
+               *eap = 1;
                break;
        case Ad16:
        case PC16:
                put_word_test(pc, rand16());
                *isconstant = 16;
                pc += 2;
+               *eap = 1;
                break;
        case Ad8r:
        case PC8r:
@@ -1396,12 +1442,14 @@ static int create_ea(uae_u16 *opcodep, uaecptr pc, int mode, int reg, struct ins
                        }
                        *isconstant = 32;
                }
+               *eap = 1;
                break;
        }
        case absw:
                put_word_test(pc, rand16());
                *isconstant = 16;
                pc += 2;
+               *eap = 1;
                break;
        case absl:
                {
@@ -1422,6 +1470,7 @@ static int create_ea(uae_u16 *opcodep, uaecptr pc, int mode, int reg, struct ins
                        *isconstant = 32;
                        pc += 4;
                }
+               *eap = 1;
                break;
        case imm:
                if (fpuopcode >= 0 && opcodesize < 8) {
@@ -1599,6 +1648,195 @@ static int create_ea(uae_u16 *opcodep, uaecptr pc, int mode, int reg, struct ins
        return pc - old_pc;
 }
 
+static int ea_exact_cnt;
+
+// generate exact EA (for bus error test)
+static int create_ea_exact(uae_u16 *opcodep, uaecptr pc, int mode, int reg, struct instr *dp, int *isconstant, int srcdst, int fpuopcode, int opcodesize, uae_u32 *eap)
+{
+       uae_u32 target = feature_target_ea[srcdst];
+       ea_exact_cnt++;
+
+       switch (mode)
+       {
+               // always allow modes that don't have EA
+       case Areg:
+       case Dreg:
+               return 0;
+       case Aind:
+       case Aipi:
+       {
+               if (cur_registers[reg + 8] == target) {
+                       *eap = target;
+                       return  0;
+               }
+               return -2;
+       }
+       case Apdi:
+       {
+               if (cur_registers[reg + 8] == target + (1 << dp->size)) {
+                       *eap = target;
+                       return  0;
+               }
+               return -2;
+       }
+       case Ad16:
+       {
+               uae_u32 v = cur_registers[reg + 8];
+               if (target <= v + 0x7ffe && (target >= v - 0x8000 || v < 0x8000)) {
+                       put_word_test(pc, target - v);
+                       *eap = target;
+                       return 2;
+               }
+               return -2;
+       }
+       case PC16:
+       {
+               uae_u32 pct = opcode_memory_start + 2;
+               if (target <= pct + 0x7ffe && target >= pct - 0x8000) {
+                       put_word_test(pc, target - pct);
+                       *eap = target;
+                       return 2;
+               }
+               return -2;
+       }
+       case Ad8r:
+       {
+               for (int r = 0; r < 16; r++) {
+                       uae_u32 aval = cur_registers[reg + 8];
+                       int rn = ((ea_exact_cnt >> 1) + r) & 15;
+                       for (int i = 0; i < 2; i++) {
+                               if ((ea_exact_cnt & 1) == 0 || i == 1) {
+                                       uae_s32 val32 = cur_registers[rn];
+                                       uae_u32 addr = aval + val32;
+                                       if (target <= addr + 0x7f && target >= addr - 0x80) {
+                                               put_word_test(pc, (rn << 12) | 0x0800 | ((target - addr) & 0xff));
+                                               *eap = target;
+                                               return 2;
+                                       }
+                               } else {
+                                       uae_s16 val16 = (uae_s16)cur_registers[rn];
+                                       uae_u32 addr = aval + val16;
+                                       if (target <= addr + 0x7f && target >= addr - 0x80) {
+                                               put_word_test(pc, (rn << 12) | 0x0000 | ((target - addr) & 0xff));
+                                               *eap = target;
+                                               return 2;
+                                       }
+                               }
+                       }
+               }
+               return -2;
+       }
+       case PC8r:
+       {
+               for (int r = 0; r < 16; r++) {
+                       uae_u32 aval = opcode_memory_start + 2;
+                       int rn = ((ea_exact_cnt >> 1) + r) & 15;
+                       for (int i = 0; i < 2; i++) {
+                               if ((ea_exact_cnt & 1) == 0 || i == 1) {
+                                       uae_s32 val32 = cur_registers[rn];
+                                       uae_u32 addr = aval + val32;
+                                       if (target <= addr + 0x7f && target >= addr - 0x80) {
+                                               put_word_test(pc, (rn << 12) | 0x0800 | ((target - addr) & 0xff));
+                                               *eap = target;
+                                               return 2;
+                                       }
+                               } else {
+                                       uae_s16 val16 = (uae_s16)cur_registers[rn];
+                                       uae_u32 addr = aval + val16;
+                                       if (target <= addr + 0x7f && target >= addr - 0x80) {
+                                               put_word_test(pc, (rn << 12) | 0x0000 | ((target - addr) & 0xff));
+                                               *eap = target;
+                                               return 2;
+                                       }
+                               }
+                       }
+               }
+               return -2;
+       }
+       case absw:
+       {
+               if (target >= test_low_memory_start && target < test_low_memory_end) {
+                       put_word_test(pc, target);
+                       *eap = target;
+                       return 2;
+               }
+               return -2;
+       }
+       case absl:
+       {
+               if (target >= test_low_memory_start && target < test_low_memory_end) {
+                       put_long_test(pc, target);
+                       *eap = target;
+                       return 4;
+               }
+               if (target >= test_high_memory_start && target < test_high_memory_end) {
+                       put_long_test(pc, target);
+                       *eap = target;
+                       return 4;
+               }
+               if (target >= test_memory_start && target < test_memory_end) {
+                       put_long_test(pc, target);
+                       *eap = target;
+                       return 4;
+               }
+               return -2;
+       }
+       case imm:
+               if (srcdst)
+                       return -2;
+               if (dp->size == sz_long) {
+                       put_long_test(pc, rand32());
+                       return 4;
+               } else {
+                       put_word_test(pc, rand16());
+                       return 2;
+               }
+               break;
+       case imm0:
+       {
+               if (srcdst)
+                       return -2;
+               uae_u16 v = rand16();
+               if ((imm8_cnt & 3) == 0)
+                       v &= 0xff;
+               imm8_cnt++;
+               put_word_test(pc, v);
+               return 2;
+       }
+       case imm1:
+       {
+               if (srcdst)
+                       return -2;
+               uae_u16 v = rand16();
+               put_word_test(pc, v);
+               return 2;
+       }
+       case imm2:
+       {
+               if (srcdst)
+                       return -2;
+               uae_u32 v = rand32();
+               put_long_test(pc, v);
+               return 4;
+       }
+       }
+       return -2;
+}
+
+static int create_ea(uae_u16 *opcodep, uaecptr pc, int mode, int reg, struct instr *dp, int *isconstant, int srcdst, int fpuopcode, int opcodesize, uae_u32 *ea)
+{
+       int am = mode >= imm ? imm : mode;
+
+       if (!((1 << am) & feature_addressing_modes[srcdst]))
+               return -1;
+
+       if (feature_target_ea[srcdst] == 0xffffffff) {
+               return create_ea_random(opcodep, pc, mode, reg, dp, isconstant, srcdst, fpuopcode, opcodesize, ea);
+       } else {
+               return create_ea_exact(opcodep, pc, mode, reg, dp, isconstant, srcdst, fpuopcode, opcodesize, ea);
+       }
+}
+
 static int imm_special;
 
 static int handle_specials_preea(uae_u16 opcode, uaecptr pc, struct instr *dp)
@@ -1902,7 +2140,12 @@ static void execute_ins(uae_u16 opc, uaecptr endpc, uaecptr targetpc, struct ins
                uaecptr a7 = regs.regs[15];
                int s = regs.s;
 
-               (*cpufunctbl[opc])(opc);
+               TRY (ex) {
+                       (*cpufunctbl[opc])(opc);
+               } CATCH(ex) {
+                       // got bus error
+                       Exception(2);
+               } ENDTRY
 
                // Supervisor mode and A7 was modified: skip this test round.
                if (s && regs.regs[15] != a7) {
@@ -2137,6 +2380,21 @@ static int isfpp(int mnemo)
 }
 
 
+static void generate_target_registers(uae_u32 target_address, uae_u32 *out)
+{
+       uae_u32 *a = out + 8;
+       a[0] = target_address;
+       a[1] = target_address + 1;
+       a[2] = target_address + 2;
+       a[3] = target_address + 4;
+       a[4] = target_address - 6;
+       a[5] = target_address + 6;
+       for (int i = 0; i < 7; i++) {
+               out[i] = i - 4;
+       }
+       out[7] = target_address - opcode_memory_start;
+}
+
 static const TCHAR *sizes[] = { _T("B"), _T("W"), _T("L") };
 
 static void test_mnemo(const TCHAR *path, const TCHAR *mnemo, const TCHAR *ovrfilename, int opcodesize, int fpuopcode)
@@ -2198,8 +2456,6 @@ static void test_mnemo(const TCHAR *path, const TCHAR *mnemo, const TCHAR *ovrfi
                }
        }
 
-       xorshiftstate ^= 0x12;
-
        int pathlen = _tcslen(path);
        _stprintf(dir, _T("%s%s"), path, mns);
        if (fpuopcode < 0) {
@@ -2250,6 +2506,12 @@ static void test_mnemo(const TCHAR *path, const TCHAR *mnemo, const TCHAR *ovrfi
        registers[8 + 6] = opcode_memory_start - 0x100;
        registers[8 + 7] = test_memory_end - STACK_SIZE;
 
+       uae_u32 target_address = 0xffffffff;
+       if (feature_target_ea[0] != 0xffffffff)
+               target_address = feature_target_ea[0];
+       else if (feature_target_ea[1] != 0xffffffff)
+               target_address = feature_target_ea[1];
+
        // 1.0
        fpuregisters[0].high = 0x3fff;
        fpuregisters[0].low = 0x8000000000000000;
@@ -2274,7 +2536,6 @@ static void test_mnemo(const TCHAR *path, const TCHAR *mnemo, const TCHAR *ovrfi
                fpuregisters[i].low = (((uae_u64)rand32()) << 32) | (rand32());
        }
 
-       uae_u32 cur_registers[MAX_REGISTERS];
        for (int i = 0; i < MAX_REGISTERS; i++) {
                cur_registers[i] = registers[i];
        }
@@ -2283,6 +2544,10 @@ static void test_mnemo(const TCHAR *path, const TCHAR *mnemo, const TCHAR *ovrfi
                cur_fpuregisters[i] = fpuregisters[i];
        }
 
+       if (target_address != 0xffffffff) {
+               generate_target_registers(target_address, cur_registers);
+       }
+
        dst = storage_buffer;
 
        memcpy(low_memory, low_memory_temp, low_memory_size);
@@ -2336,6 +2601,12 @@ static void test_mnemo(const TCHAR *path, const TCHAR *mnemo, const TCHAR *ovrfi
                        if (dp->clev > cpu_lvl && lookup->mnemo != i_ILLG)
                                continue;
 
+                       // not supported yet in target mode
+                       if (target_address != 0xffffffff) {
+                               if (dp->mnemo == i_MVMEL || dp->mnemo == i_MVMLE)
+                                       continue;
+                       }
+
                        int extra_loops = 3;
                        while (extra_loops-- > 0) {
 
@@ -2392,9 +2663,13 @@ static void test_mnemo(const TCHAR *path, const TCHAR *mnemo, const TCHAR *ovrfi
 
                                        pc += handle_specials_preea(opc, pc, dp);
 
+
+                                       uae_u32 srcea = 0xffffffff;
+                                       uae_u32 dstea = 0xffffffff;
+
                                        // create source addressing mode
                                        if (dp->suse) {
-                                               int o = create_ea(&opc, pc, dp->smode, dp->sreg, dp, &isconstant_src, 0, fpuopcode, opcodesize);
+                                               int o = create_ea(&opc, pc, dp->smode, dp->sreg, dp, &isconstant_src, 0, fpuopcode, opcodesize, &srcea);
                                                if (o < 0) {
                                                        memcpy(opcode_memory, oldbytes, sizeof(oldbytes));
                                                        if (o == -1)
@@ -2418,17 +2693,23 @@ static void test_mnemo(const TCHAR *path, const TCHAR *mnemo, const TCHAR *ovrfi
 
                                        // create destination addressing mode
                                        if (dp->duse) {
-                                               int o = create_ea(&opc, pc, dp->dmode, dp->dreg, dp, &isconstant_dst, 1, fpuopcode, opcodesize);
+                                               int o = create_ea(&opc, pc, dp->dmode, dp->dreg, dp, &isconstant_dst, 1, fpuopcode, opcodesize, &dstea);
                                                if (o < 0) {
                                                        memcpy(opcode_memory, oldbytes, sizeof(oldbytes));
                                                        if (o == -1)
                                                                goto nextopcode;
                                                        continue;
-                                                       goto nextopcode;
                                                }
                                                pc += o;
                                        }
 
+                                       // requested target address but no EA? skip
+                                       if (target_address != 0xffffffff && srcea == 0xffffffff && dstea == 0xffffffff) {
+                                               memcpy(opcode_memory, oldbytes, sizeof(oldbytes));
+                                               continue;
+                                       }
+
+
                                        pc = handle_specials_extra(opc, pc, dp);
 
                                        // if destination EA modified opcode
@@ -2504,11 +2785,21 @@ static void test_mnemo(const TCHAR *path, const TCHAR *mnemo, const TCHAR *ovrfi
                                        uaecptr nextpc;
                                        srcaddr = 0xffffffff;
                                        dstaddr = 0xffffffff;
-                                       m68k_disasm_2(out, sizeof(out) / sizeof(TCHAR), opcode_memory_start, &nextpc, 1, &srcaddr, &dstaddr, 0xffffffff, 0);
+                                       uae_u32 dflags = m68k_disasm_2(out, sizeof(out) / sizeof(TCHAR), opcode_memory_start, &nextpc, 1, &srcaddr, &dstaddr, 0xffffffff, 0);
                                        if (verbose) {
                                                my_trim(out);
                                                wprintf(_T("%08u %s"), subtest_count, out);
                                        }
+
+                                       if ((dflags & 1) && feature_target_ea[0] != 0xffffffff && srcaddr != 0xffffffff && srcaddr != feature_target_ea[0]) {
+                                               wprintf(_T("\nSource address mismatch %08x <> %08x\n"), feature_target_ea[0], srcaddr);
+                                               abort();
+                                       }
+                                       if ((dflags & 2) && feature_target_ea[1] != 0xffffffff && dstaddr != feature_target_ea[1]) {
+                                               wprintf(_T("\nDestination address mismatch %08x <> %08x\n"), feature_target_ea[1], dstaddr);
+                                               abort();
+                                       }
+
 #if 0
                                        // can't test because dp may be empty if instruction is invalid
                                        if (nextpc != pc - 2) {
@@ -2562,11 +2853,11 @@ static void test_mnemo(const TCHAR *path, const TCHAR *mnemo, const TCHAR *ovrfi
                                                testing_active = 0;
                                        }
 
-                                       if (srcaddr != srcaddr_old) {
+                                       if (srcaddr != srcaddr_old && (dflags & 1)) {
                                                dst = store_reg(dst, CT_SRCADDR, srcaddr_old, srcaddr, -1);
                                                srcaddr_old = srcaddr;
                                        }
-                                       if (dstaddr != dstaddr_old) {
+                                       if (dstaddr != dstaddr_old && (dflags & 2)) {
                                                dst = store_reg(dst, CT_DSTADDR, dstaddr_old, dstaddr, -1);
                                                dstaddr_old = dstaddr;
                                        }
@@ -2840,7 +3131,9 @@ static void test_mnemo(const TCHAR *path, const TCHAR *mnemo, const TCHAR *ovrfi
                                                }
                                        }
                                        if (dst - storage_buffer >= storage_buffer_watermark) {
-                                               save_data(dst, dir);
+                                               if (subtest_count > 0) {
+                                                       save_data(dst, dir);
+                                               }
                                                dst = storage_buffer;
                                                for (int i = 0; i < MAX_REGISTERS; i++) {
                                                        dst = store_reg(dst, CT_DREG + i, 0, cur_registers[i], -1);
@@ -2869,7 +3162,9 @@ static void test_mnemo(const TCHAR *path, const TCHAR *mnemo, const TCHAR *ovrfi
                nextopcode:;
                }
 
-               save_data(dst, dir);
+               if (subtest_count > 0) {
+                       save_data(dst, dir);
+               }
                dst = storage_buffer;
 
                if (opcodecnt == 1)
@@ -2881,10 +3176,15 @@ static void test_mnemo(const TCHAR *path, const TCHAR *mnemo, const TCHAR *ovrfi
                if (rounds < 0)
                        break;
 
-               // randomize registers
-               for (int i = 0; i < 16 - 2; i++) {
-                       cur_registers[i] = rand32();
+               if (target_address != 0xffffffff) {
+                       generate_target_registers(target_address, cur_registers);
+               } else {
+                       // randomize registers
+                       for (int i = 0; i < 16 - 2; i++) {
+                               cur_registers[i] = rand32();
+                       }
                }
+
                cur_registers[0] &= 0xffff;
                cur_registers[8] &= 0xffff;
                cur_registers[8 + 6]--;
@@ -3099,10 +3399,36 @@ int __cdecl main(int argc, char *argv[])
        ini_getval(ini, INISECTION, _T("feature_exception3_data"), &feature_exception3_data);
        feature_exception3_instruction = 0;
        ini_getval(ini, INISECTION, _T("feature_exception3_instruction"), &feature_exception3_instruction);
+
+       v = -1;
+       ini_getval(ini, INISECTION, _T("feature_target_src_ea"), &v);
+       feature_target_ea[0] = v;
+       v = -1;
+       ini_getval(ini, INISECTION, _T("feature_target_dst_ea"), &v);
+       feature_target_ea[1] = v;
+       if (feature_target_ea[0] != 0xffffffff || feature_target_ea[1] != 0xffffffff) {
+               if (feature_target_ea[0] & 1) {
+                       feature_exception3_data = 3;
+                       feature_exception3_instruction = 3;
+               }
+               if (feature_target_ea[1] & 1) {
+                       feature_exception3_data = 3;
+                       feature_exception3_instruction = 3;
+               }
+       }
+
+       safe_memory_start = 0xffffffff;
+       if (ini_getval(ini, INISECTION, _T("feature_safe_memory_start"), &v))
+               safe_memory_start = v;
+       safe_memory_end = 0xffffffff;
+       if (ini_getval(ini, INISECTION, _T("feature_safe_memory_size"), &v))
+               safe_memory_end = safe_memory_start + v;
+
        feature_sr_mask = 0;
        ini_getval(ini, INISECTION, _T("feature_sr_mask"), &feature_sr_mask);
        feature_min_interrupt_mask = 0;
        ini_getval(ini, INISECTION, _T("feature_min_interrupt_mask"), &feature_min_interrupt_mask);
+
        feature_loop_mode = 0;
        ini_getval(ini, INISECTION, _T("feature_loop_mode"), &feature_loop_mode);
        if (feature_loop_mode) {
@@ -3410,7 +3736,8 @@ int __cdecl main(int argc, char *argv[])
 
                if (!_tcsicmp(mode, _T("all"))) {
 
-                       verbose = 0;
+                       if (verbose == 1)
+                               verbose = 0;
                        for (int j = 1; lookuptab[j].name; j++) {
                                test_mnemo_text(path, lookuptab[j].name);
                        }
@@ -3422,7 +3749,8 @@ int __cdecl main(int argc, char *argv[])
 
                if (!_tcsicmp(mode, _T("fall"))) {
 
-                       verbose = 0;
+                       if (verbose == 1)
+                               verbose = 0;
                        test_mnemo_text(path, _T("FMOVECR"));
                        const TCHAR *prev = _T("");
                        for (int j = 0; j < 64; j++) {
index 022dcf3cd979be435a22518e955037eba2d48616..9f6430870a183ac829099f662a07fadf1ed17add 100644 (file)
@@ -209,6 +209,7 @@ _msp_address2:
 
 
 _exceptiontable000:
+       bsr.s exception | 2
        bsr.s exception | 3
        bsr.s exception | 4
        bsr.s exception | 5
@@ -264,12 +265,15 @@ exception:
        lea _exceptiontable000(pc),a1
        sub.l a1,d0
        lsr.w #1,d0
-       addq.w #2,d0
+       addq.w #1,d0
        move.w d0,S_EXC+2(a0)
 
        move.l sp,S_EXCFRAME(a0)
+       cmp.w #2,d0
+       beq.s .isbuserror
        cmp.w #3,d0
        bne.s .noaddresserror
+.isbuserror:
        move.w (sp),S_EXC+0(a0)
        addq.w #8,sp
 .noaddresserror:
index d1a1d68e84250c585f984312414c16e358a67766..2efcbee498a3e8e88c88ff2ff58dc9edf7f35096 100644 (file)
@@ -1,5 +1,5 @@
 
-#define DATA_VERSION 3
+#define DATA_VERSION 4
 
 #define CT_FPREG 0
 #define CT_DREG 0
index 72256052135d3bfc56044160cc6b73fd1b0f75e7..d048564d580a4389fdadf196c3c877968deb7317 100644 (file)
@@ -39,7 +39,8 @@ test_memory_start=0x780000
 ;test_memory_start=0x340000
 test_memory_size=0x080000
 
-; number of test rounds (registers are re-randomized after each round)
+; number of test rounds
+; registers are re-randomized after each round if not in target ea mode.
 test_rounds=2
 
 ; test word or long odd data access address errors (68000/010 only)
@@ -52,6 +53,20 @@ feature_exception3_data=0
 ; same options as above
 feature_exception3_instruction=0
 
+; Use static effective address instead of random EA.
+; Useful for bus error and address error testing
+; Disables above exception3 modes.
+; Supports 68000 addressing modes only.
+; If instruction only has destination EA, source Areg, Dreg or immediate is generated.
+feature_target_src_ea=
+feature_target_dst_ea=
+
+; Memory region that generates bus error (both read and write).
+; Must be inside any test memory region.
+; Can be used to verify bus errors if ea above is inside this memory region.
+feature_safe_memory_start=
+feature_safe_memory_size=
+
 ; CCR/FPU status flags mode
 ; 0 = all combinations (32 CCR loops, 256 FPU loops)
 ; 1 = all zeros and all ones only (2 CCR loops, 32 FPU loops)
index ef8060262c80c342b47d756dd4d78ad6c19f790e..8a4e5443c7d042411f4c1ce36b46ce103333071f 100644 (file)
@@ -63,6 +63,7 @@ static uae_u8 *test_memory;
 static uae_u32 test_memory_addr, test_memory_end;
 static uae_u32 test_memory_size;
 static uae_u8 *test_data;
+static uae_u8 *safe_memory_start, *safe_memory_end;
 static int test_data_size;
 static uae_u32 oldvbr;
 static uae_u8 *vbr_zero = 0;
@@ -96,7 +97,7 @@ static char outbuffer[40000];
 #else
 static char outbuffer[4000];
 #endif
-static char tmpbuffer[256];
+static char tmpbuffer[1024];
 static char *outbp;
 static int infoadded;
 static int errors;
@@ -211,6 +212,40 @@ static void endinfo(void)
        printf("\n");
 }
 
+static void safe_memcpy(uae_u8 *d, uae_u8 *s, int size)
+{
+       if (safe_memory_start == (uae_u8*)0xffffffff && safe_memory_end == (uae_u8*)0xffffffff) {
+               memcpy(d, s, size);
+               return;
+       }
+       if (safe_memory_end <= d || safe_memory_start >= d + size) {
+               if (safe_memory_end <= s || safe_memory_start >= s + size) {
+                       memcpy(d, s, size);
+                       return;
+               }
+       }
+       while (size > 0) {
+               int size2 = size > sizeof(tmpbuffer) ? sizeof(tmpbuffer) : size;
+               if ((d + size2 > safe_memory_start && d < safe_memory_end) ||
+                       (s + size2 > safe_memory_start && d < safe_memory_end)) {
+                       for (int i = 0; i < size2; i++) {
+                               if ((d >= safe_memory_start && d < safe_memory_end) ||
+                                       (s >= safe_memory_start && d < safe_memory_end)) {
+                                       s++;
+                                       d++;
+                                       continue;
+                               }
+                               *d++ = *s++;
+                       }
+               } else {
+                       memcpy(d, s, size2);
+                       d += size2;
+                       s += size2;
+               }
+               size -= size2;
+       }
+}
+
 static int test_active;
 static uae_u32 enable_data;
 
@@ -238,28 +273,28 @@ static void start_test(void)
 
        enable_data = tosuper(0);
 
-       memcpy(low_memory_back + low_memory_offset, low_memory + low_memory_offset, low_memory_size - low_memory_offset);
+       safe_memcpy(low_memory_back + low_memory_offset, low_memory + low_memory_offset, low_memory_size - low_memory_offset);
        // always copy exception vectors if 68000
        if (cpu_lvl == 0 && low_memory_offset > 0x08)
-               memcpy(low_memory_back + 8, low_memory + 8, (192 - 2) * 4);
+               safe_memcpy(low_memory_back + 8, low_memory + 8, (192 - 2) * 4);
 
        if (!hmem_rom)
-               memcpy(high_memory_back, high_memory + high_memory_offset, high_memory_size - high_memory_offset);
+               safe_memcpy(high_memory_back, high_memory + high_memory_offset, high_memory_size - high_memory_offset);
 
-       memcpy(low_memory + low_memory_offset, low_memory_temp + low_memory_offset, low_memory_size - low_memory_offset);
+       safe_memcpy(low_memory + low_memory_offset, low_memory_temp + low_memory_offset, low_memory_size - low_memory_offset);
        if (cpu_lvl == 0 && low_memory_offset > 0x08)
-               memcpy(low_memory + 8, low_memory_temp + 8, (192 - 2) * 4);
+               safe_memcpy(low_memory + 8, low_memory_temp + 8, (192 - 2) * 4);
 
        if (!hmem_rom)
-               memcpy(high_memory + high_memory_offset, high_memory_temp, high_memory_size - high_memory_offset);
+               safe_memcpy(high_memory + high_memory_offset, high_memory_temp, high_memory_size - high_memory_offset);
 
        if (cpu_lvl == 0) {
                uae_u32 *p = (uae_u32 *)vbr_zero;
-               for (int i = 3; i < 12; i++) {
-                       p[i] = (uae_u32)(((uae_u32)&exceptiontable000) + (i - 3) * 2);
+               for (int i = 2; i < 12; i++) {
+                       p[i] = (uae_u32)(((uae_u32)&exceptiontable000) + (i - 2) * 2);
                }
                for (int i = 32; i < 48; i++) {
-                       p[i] = (uae_u32)(((uae_u32)&exceptiontable000) + (i - 3) * 2);
+                       p[i] = (uae_u32)(((uae_u32)&exceptiontable000) + (i - 2) * 2);
                }
        } else {
                oldvbr = setvbr((uae_u32)vbr);
@@ -276,12 +311,12 @@ static void end_test(void)
                return;
        test_active = 0;
 
-       memcpy(low_memory + low_memory_offset, low_memory_back + low_memory_offset, low_memory_size - low_memory_offset);
+       safe_memcpy(low_memory + low_memory_offset, low_memory_back + low_memory_offset, low_memory_size - low_memory_offset);
        if (cpu_lvl == 0 && low_memory_offset > 0x08)
-               memcpy(low_memory + 8, low_memory_back + 8, (192 - 2) * 4);
+               safe_memcpy(low_memory + 8, low_memory_back + 8, (192 - 2) * 4);
 
        if (!hmem_rom)
-               memcpy(high_memory + high_memory_offset, high_memory_back, high_memory_size - high_memory_offset);
+               safe_memcpy(high_memory + high_memory_offset, high_memory_back, high_memory_size - high_memory_offset);
 
        if (cpu_lvl > 0) {
                setvbr(oldvbr);
@@ -301,7 +336,7 @@ static uae_u8 *load_file(const char *path, const char *file, uae_u8 *p, int *siz
                        printf("Couldn't open '%s'\n", fname);
                        exit(0);
                }
-               return NULL; 
+               return NULL;
        }
        int size = *sizep;
        if (size < 0) {
@@ -316,7 +351,39 @@ static uae_u8 *load_file(const char *path, const char *file, uae_u8 *p, int *siz
                        exit(0);
                }
        }
-       *sizep = fread(p, 1, size, f);
+       if (safe_memory_start == (uae_u8*)0xffffffff && safe_memory_end == (uae_u8*)0xffffffff) {
+               *sizep = fread(p, 1, size, f);
+       } else if (safe_memory_end < p || safe_memory_start >= p + size) {
+               *sizep = fread(p, 1, size, f);
+       } else {
+               *sizep = size;
+               uae_u8 *pp = p;
+               while (size > 0) {
+                       int size2 = size > sizeof(tmpbuffer) ? sizeof(tmpbuffer) : size;
+                       if (p + size2 > safe_memory_start && p < safe_memory_end) {
+                               if (fread(tmpbuffer, 1, size2, f) != size2) {
+                                       printf("Couldn't read file '%s' %ld\n", fname, size2);
+                                       exit(0);
+                               }
+                               uae_u8 *sp = tmpbuffer;
+                               for (int i = 0; i < size2; i++) {
+                                       if (pp < safe_memory_start || pp >= safe_memory_end) {
+                                               *pp = *sp;
+                                       }
+                                       pp++;
+                                       sp++;
+                               }
+                       } else {
+                               if (fread(p, 1, size2, f) != size2) {
+                                       printf("Couldn't read file '%s'\n", fname);
+                                       exit(0);
+                               }
+                               p += size2;
+                       }
+                       size -= size2;
+               }
+               size = *sizep;
+       }
        if (*sizep != size) {
                printf("Couldn't read file '%s'\n", fname);
                exit(0);
@@ -722,6 +789,8 @@ static uae_u32 test_fpsr, test_fpcr;
 
 static int is_valid_test_addr(uae_u32 a)
 {
+       if ((uae_u8 *)a >= safe_memory_start && (uae_u8 *)a < safe_memory_end)
+               return 0;
        return (a >= test_low_memory_start && a < test_low_memory_end && test_low_memory_start != 0xffffffff) ||
                (a >= test_high_memory_start && a < test_high_memory_end && test_high_memory_start != 0xffffffff) ||
                (a >= test_memory_addr && a < test_memory_end);
@@ -743,6 +812,7 @@ static int addr_diff(uae_u8 *ap, uae_u8 *bp, int size)
 static void addinfo_bytes(char *name, uae_u8 *src, uae_u32 address, int offset, int len)
 {
        sprintf(outbp, "%s: %08lx ", name, address);
+       address += offset;
        outbp += strlen(outbp);
        int cnt = 0;
        while (len-- > 0) {
@@ -750,9 +820,15 @@ static void addinfo_bytes(char *name, uae_u8 *src, uae_u32 address, int offset,
                        *outbp++ = '*';
                else if (cnt > 0)
                        *outbp++ = '.';
-               sprintf(outbp, "%02x", src[cnt]);
+               if ((uae_u8*)address >= safe_memory_start && (uae_u8*)address < safe_memory_end) {
+                       outbp[0] = '?';
+                       outbp[1] = '?';
+               } else {
+                       sprintf(outbp, "%02x", src[cnt]);
+               }
                outbp += 2;
                offset++;
+               address++;
                cnt++;
        }
        *outbp++ = '\n';
@@ -1164,6 +1240,8 @@ static uae_u8 *validate_test(uae_u8 *p, int ignore_errors, int ignore_sr)
                                if (dooutput) {
                                        if (cpuexc == 4 && last_registers.pc == test_regs.pc) {
                                                sprintf(outbp, "Exception ID: expected %d but got no exception.\n", exc);
+                                       } else if (cpuexc == 4) {
+                                               sprintf(outbp, "Exception ID: expected %d but got %d (or no exception)\n", exc, cpuexc);
                                        } else {
                                                sprintf(outbp, "Exception ID: expected %d but got %d\n", exc, cpuexc);
                                        }
@@ -1462,7 +1540,7 @@ static void process_test(uae_u8 *p)
                p++;
 
                store_addr(regs.srcaddr, srcaddr);
-               store_addr(regs.srcaddr, dstaddr);
+               store_addr(regs.dstaddr, dstaddr);
 
                xmemcpy(&last_registers, &regs, sizeof(struct registers));
 
@@ -1649,7 +1727,6 @@ static int test_mnemo(const char *path, const char *opcode)
                printf("Couldn't open '%s'\n", tfname);
                exit(0);
        }
-       int header_size = 32;
        fread(data, 1, 4, f);
        v = gl(data);
        if (v != DATA_VERSION) {
@@ -1684,6 +1761,12 @@ static int test_mnemo(const char *path, const char *opcode)
        test_high_memory_start = gl(data);
        fread(data, 1, 4, f);
        test_high_memory_end = gl(data);
+       fread(data, 1, 4, f);
+       safe_memory_start = (uae_u8*)gl(data);
+       fread(data, 1, 4, f);
+       safe_memory_end = (uae_u8*)gl(data);
+       fread(data, 1, 4, f);
+       fread(data, 1, 4, f);
        fread(inst_name, 1, sizeof(inst_name) - 1, f);
        inst_name[sizeof(inst_name) - 1] = 0;
 
@@ -1742,6 +1825,12 @@ static int test_mnemo(const char *path, const char *opcode)
        }
 
        printf("CPUlvl=%d, Mask=%08lx Code=%08lx\n", cpu_lvl, addressing_mask, opcode_memory);
+       printf(" Low: %08lx-%08lx High: %08lx-%08lx\n",
+               test_low_memory_start, test_low_memory_end,
+               test_high_memory_start, test_high_memory_end);
+       printf("Test: %08lx-%08lx Safe: %08lx-%08lx\n",
+               test_memory_addr, test_memory_end,
+               safe_memory_start, safe_memory_end);
        printf("%s:\n", inst_name);
 
        testcnt = 0;
index 7f364f04c998f7175321fbf21f04217dfece4e54..341569baccdeabd5cefa9c7be44293fbfd680c9c 100644 (file)
@@ -48,5 +48,5 @@ util.o: adis/util.c
 asm040.o: asm040.S
        $(AS) -m68020  -o $@ asm040.S
 
-amiga.o: amiga.S
+amiga.o: amiga.S asm.S
        $(AS) -m68020  -o $@ amiga.S
index 3cc45d83bc8a0024bf4f1c5f8869106155c0f32d..a23373f55617109c9a52163ff57d3a9919cb3c54 100644 (file)
@@ -48,5 +48,5 @@ util.o: adis/util.c
 asm040.o: asm040.S
        $(AS) -m68020  -o $@ asm040.S
 
-atari.o: atari.S
+atari.o: atari.S asm.S
        $(AS) -m68020  -o $@ atari.S