From: Toni Wilen Date: Sun, 29 Sep 2019 15:54:34 +0000 (+0300) Subject: CPU tester target ea mode and wip bus error test support. X-Git-Tag: 4300~91 X-Git-Url: https://git.unchartedbackwaters.co.uk/w/?a=commitdiff_plain;h=eb3941d24872207b12ff143bd2e208af9af9a679;p=francis%2Fwinuae.git CPU tester target ea mode and wip bus error test support. --- diff --git a/cputest.cpp b/cputest.cpp index fd08746b..21cfeefb 100644 --- a/cputest.cpp +++ b/cputest.cpp @@ -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++) { diff --git a/cputest/asm.S b/cputest/asm.S index 022dcf3c..9f643087 100644 --- a/cputest/asm.S +++ b/cputest/asm.S @@ -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: diff --git a/cputest/cputest_defines.h b/cputest/cputest_defines.h index d1a1d68e..2efcbee4 100644 --- a/cputest/cputest_defines.h +++ b/cputest/cputest_defines.h @@ -1,5 +1,5 @@ -#define DATA_VERSION 3 +#define DATA_VERSION 4 #define CT_FPREG 0 #define CT_DREG 0 diff --git a/cputest/cputestgen.ini b/cputest/cputestgen.ini index 72256052..d048564d 100644 --- a/cputest/cputestgen.ini +++ b/cputest/cputestgen.ini @@ -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) diff --git a/cputest/main.c b/cputest/main.c index ef806026..8a4e5443 100644 --- a/cputest/main.c +++ b/cputest/main.c @@ -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, ®s, 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; diff --git a/cputest/makefile b/cputest/makefile index 7f364f04..341569ba 100644 --- a/cputest/makefile +++ b/cputest/makefile @@ -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 diff --git a/cputest/makefile.st b/cputest/makefile.st index 3cc45d83..a23373f5 100644 --- a/cputest/makefile.st +++ b/cputest/makefile.st @@ -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