static int ad8r[2], pc8r[2];
static int multi_mode;
#define MAX_TARGET_EA 20
-static uae_u32 feature_target_ea[MAX_TARGET_EA][2];
-static int target_ea_src_cnt, target_ea_dst_cnt;
-static int target_ea_src_max, target_ea_dst_max;
-static uae_u32 target_ea[2];
+static uae_u32 feature_target_ea[MAX_TARGET_EA][3];
+static int target_ea_src_cnt, target_ea_dst_cnt, target_ea_opcode_cnt;
+static int target_ea_src_max, target_ea_dst_max, target_ea_opcode_max;
+static uae_u32 target_ea[3];
#define HIGH_MEMORY_START (addressing_mask == 0xffffffff ? 0xffff8000 : 0x00ff8000)
if (safe_memory_start == 0xffffffff && safe_memory_end == 0xffffffff)
return;
if (addr >= safe_memory_start && addr < safe_memory_end) {
- cpu_bus_error_fake = 1;
- if ((safe_memory_mode & 1) && !write)
- cpu_bus_error = 1;
- if ((safe_memory_mode & 2) && write)
+ cpu_bus_error_fake = -1;
+ if ((safe_memory_mode & 1) && !write) {
cpu_bus_error = 1;
+ cpu_bus_error_fake = 1;
+ }
+ if ((safe_memory_mode & 2) && write) {
+ cpu_bus_error = 2;
+ cpu_bus_error_fake = 2;
+ }
}
}
regs.read_buffer = 0;
if (currprefs.cpu_model == 68000) {
- if (generates_group1_exception(regs.ir)) {
+ if (generates_group1_exception(regs.ir) && !(opcode & 0x20000)) {
test_exception_3_fc |= 8; // set N/I
}
if (opcode & 0x10000)
test_exception_3_fc |= 8;
- test_exception_opcode = regs.ir;
+ if (!(opcode & 0x20000))
+ test_exception_opcode = regs.ir;
}
doexcstack();
test_exception_3_di = 1;
if (currprefs.cpu_model == 68000) {
- if (generates_group1_exception(regs.ir)) {
+ if (generates_group1_exception(regs.ir) && !(opcode & 0x20000)) {
test_exception_3_fc |= 8; // set N/I
}
if (opcode & 0x10000)
test_exception_3_fc |= 8;
- test_exception_opcode = regs.ir;
+ if (!(opcode & 0x20000))
+ test_exception_opcode = regs.ir;
}
doexcstack();
uaecptr oldstart = start;
uae_u8 offset = 0;
// start
- for (int i = 0; i < len; i++) {
- uae_u8 v = get_byte_test(start);
- if (v != *old)
- break;
- start++;
- old++;
+ if (old) {
+ for (int i = 0; i < len; i++) {
+ uae_u8 v = get_byte_test(start);
+ if (v != *old)
+ break;
+ start++;
+ old++;
+ }
}
// end
offset = start - oldstart;
offset = 7;
}
len -= offset;
- for (int i = len - 1; i >= 0; i--) {
- uae_u8 v = get_byte_test(start + i);
- if (v != old[i])
- break;
- len--;
+ if (old) {
+ for (int i = len - 1; i >= 0; i--) {
+ uae_u8 v = get_byte_test(start + i);
+ if (v != old[i])
+ break;
+ len--;
+ }
}
if (!len)
return dst;
fwrite(data, 1, 4, f);
pl(data, opcode_memory_start);
fwrite(data, 1, 4, f);
- pl(data, (cpu_lvl << 16) | sr_undefined_mask | (addressing_mask == 0xffffffff ? 0x80000000 : 0) | (feature_min_interrupt_mask << 20));
+ pl(data, (cpu_lvl << 16) | sr_undefined_mask | (addressing_mask == 0xffffffff ? 0x80000000 : 0) | (feature_min_interrupt_mask << 20) | (safe_memory_mode << 23));
fwrite(data, 1, 4, f);
pl(data, currprefs.fpu_model);
fwrite(data, 1, 4, f);
out_of_test_space = false;
return 0;
}
- if (ea_state_found[0] >= 2 && ea_state_found[1] >= 2 && ea_state_found[2] >= 2)
- return 1;
+ if (ea_state_found[0] >= 2 && ea_state_found[1] >= 2 && ea_state_found[2] >= 2) {
+ ea_state_found[0] = ea_state_found[1] = ea_state_found[2] = 0;
+ }
// zero
if (v == 0) {
if (ea_state_found[0] >= 2 && (ea_state_found[1] < 2 || ea_state_found[2] < 2))
uae_u32 target_address = 0xffffffff;
target_ea[0] = 0xffffffff;
target_ea[1] = 0xffffffff;
+ target_ea[2] = 0xffffffff;
if (feature_target_ea[0][0] != 0xffffffff) {
target_address = feature_target_ea[0][0];
target_ea[0] = target_address;
}
target_ea_src_cnt = 0;
target_ea_dst_cnt = 0;
+ target_ea_opcode_cnt = 0;
// 1.0
fpuregisters[0].high = 0x3fff;
int sr_override = 0;
- uae_u32 target_ea_bak[2], target_address_bak;
+ uae_u32 target_ea_bak[3], target_address_bak;
for (;;) {
target_ea_bak[0] = target_ea[0];
target_ea_bak[1] = target_ea[1];
+ target_ea_bak[2] = target_ea[2];
target_address_bak = target_address;
if (quick)
if (verbose) {
if (target_ea[0] != 0xffffffff)
- wprintf(_T("Targeat EA SRC=%08x\n"), target_ea[0]);
+ wprintf(_T(" Target EA SRC=%08x\n"), target_ea[0]);
if (target_ea[1] != 0xffffffff)
- wprintf(_T("Targeat EA DST=%08x\n"), target_ea[1]);
+ wprintf(_T(" Target EA DST=%08x\n"), target_ea[1]);
+ if (target_ea[2] != 0xffffffff)
+ wprintf(_T(" Target EA OPCODE=%08x\n"), target_ea[2]);
}
for (int opcode = 0; opcode < 65536; opcode++) {
target_ea[0] = target_ea_bak[0];
target_ea[1] = target_ea_bak[1];
+ target_ea[2] = target_ea_bak[2];
target_address = target_address_bak;
int extra_loops = 3;
target_ea[0] = target_ea_bak[0];
target_ea[1] = target_ea_bak[1];
+ target_ea[2] = target_ea_bak[1];
target_address = target_address_bak;
reset_ea_state();
target_ea[0] = target_ea_bak[0];
target_ea[1] = target_ea_bak[1];
+ target_ea[2] = target_ea_bak[2];
target_address = target_address_bak;
if (opc == 0x4ed0)
uae_u8 *bo = opcode_memory + 2;
uae_u16 bopw1 = (bo[0] << 8) | (bo[1] << 0);
uae_u16 bopw2 = (bo[2] << 8) | (bo[3] << 0);
- if (opc == 0xf228
- && bopw1 == 0x003a
+ if (opc == 0x0662
+ && bopw1 == 0x3dec
//&& bopw2 == 0x2770
)
printf("");
abort();
}
- dst = store_mem_bytes(dst, opcode_memory_start, pc - opcode_memory_start, oldbytes);
+ dst = store_mem_bytes(dst, opcode_memory_start, pc - opcode_memory_start, subtest_count > 0 ? oldbytes : NULL);
ahcnt = 0;
uae_u8 *pcaddr = get_addr(regs.pc, 2, 0);
// examine results
+
+ // if only testing read bus errors, skip tests that generated only writes and vice-versa
+ // skip also all tests don't generate any bus errors
+ if ((cpu_bus_error == 0 && safe_memory_mode) ||
+ (cpu_bus_error == 1 && !(safe_memory_mode & 1)) ||
+ (cpu_bus_error == 2 && !(safe_memory_mode & 2))) {
+ skipped = 1;
+ }
if (cpu_stopped) {
cnt_stopped++;
// CPU stopped, skip test
if (SPCFLAG_DOTRACE || test_exception == 9) {
t_cnt++;
}
- } else {
+ } else if (!skipped) {
// instruction executed successfully
ok++;
// validate branch instructions
if (isbranchinst(dp)) {
- if ((regs.pc != branch_target_pc && regs.pc != pc - endopcodesize) || ((pcaddr[0] != 0x4a && pcaddr[1] != 0xfc) && (pcaddr[0] != 0x4e && pcaddr[1] != 0x71))) {
+ if ((regs.pc != branch_target_pc && regs.pc != pc - endopcodesize)) {
wprintf(_T(" Branch instruction target fault\n"));
abort();
}
+ if (branch_target_pc < safe_memory_start || branch_target_pc >= safe_memory_end) {
+ if ((pcaddr[0] != 0x4a && pcaddr[1] != 0xfc) && (pcaddr[0] != 0x4e && pcaddr[1] != 0x71)) {
+ wprintf(_T(" Branch instruction target fault\n"));
+ abort();
+ }
+ }
}
}
for (int i = 0; i < MAX_TARGET_EA; i++) {
feature_target_ea[i][0] = 0xffffffff;
feature_target_ea[i][1] = 0xffffffff;
+ feature_target_ea[i][2] = 0xffffffff;
}
- for (int i = 0; i < 2; i++) {
- if (ini_getstring(ini, INISECTION, i ? _T("feature_target_dst_ea") : _T("feature_target_src_ea"), &vs)) {
+ for (int i = 0; i < 3; i++) {
+ if (ini_getstring(ini, INISECTION, i == 2 ? _T("feature_target_opcode") : (i ? _T("feature_target_dst_ea") : _T("feature_target_src_ea")), &vs)) {
int cnt = 0;
TCHAR *p = vs;
while (p && *p) {
p = pp;
cnt++;
}
- if (i) {
+ if (i == 2) {
+ target_ea_opcode_max = cnt;
+ } else if (i) {
target_ea_dst_max = cnt;
} else {
target_ea_src_max = cnt;
static uae_u32 test_memory_size;
static uae_u8 *test_data;
static uae_u8 *safe_memory_start, *safe_memory_end;
+static int safe_memory_mode;
static uae_u32 user_stack_memory, super_stack_memory;
static int test_data_size;
static uae_u32 oldvbr;
static int high_memory_offset;
static uae_u32 vbr[256];
-static int exceptioncount[128];
+static int exceptioncount[2][128];
static int supercnt;
static char inst_name[16+1];
#define MAX_ACCESSHIST 48
static struct accesshistory ahist[MAX_ACCESSHIST];
+static int is_valid_test_addr_read(uae_u32 a)
+{
+ if ((uae_u8 *)a >= safe_memory_start && (uae_u8 *)a < safe_memory_end && (safe_memory_mode & 1))
+ 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);
+}
+
static void endinfo(void)
{
printf("Last test: %lu\n", testcnt);
uae_u8 *p = opcode_memory;
- for (int i = 0; i < 32 * 2; i += 2) {
+ for (int i = 0; i < 4 * 2; i += 2) {
+ if (!is_valid_test_addr_read((uae_u32)(&p[i])))
+ break;
uae_u16 v = (p[i] << 8) | (p[i + 1]);
- printf(" %04x", v);
+ printf("%08lx %04x\n", &p[i], v);
if (v == 0x4afc && i > 0)
break;
}
p += size2;
size -= size2;
}
- if (size > 0 && p >= safe_memory_start && p < safe_memory_end) {
- int size2 = safe_memory_end - p;
- if (size2 > size)
- size2 = size;
- fseek(f, size2, SEEK_CUR);
- p += size2;
- size -= size2;
+ if ((safe_memory_mode & 1)) {
+ // if reading cause bus error: skip it
+ if (size > 0 && p >= safe_memory_start && p < safe_memory_end) {
+ int size2 = safe_memory_end - p;
+ if (size2 > size)
+ size2 = size;
+ fseek(f, size2, SEEK_CUR);
+ p += size2;
+ size -= size2;
+ }
+ } else if (safe_memory_mode == 2) {
+ // if only writes generate bus error: load data if different
+ if (size > 0 && p >= safe_memory_start && p < safe_memory_end) {
+ int size2 = safe_memory_end - p;
+ if (size2 > size)
+ size2 = size;
+ uae_u8 *tmp = malloc(size2);
+ if (!tmp) {
+ printf("Couldn't allocate safe tmp memory (%ld bytes)\n", size2);
+ exit(0);
+ }
+ fread(tmp, 1, size2, f);
+ if (memcmp(tmp, p, size2)) {
+ printf("Disable write bus error mode and press any key (SPACE=skip,ESC=abort)\n");
+ int ch = getchar();
+ if (ch == 27) {
+ exit(0);
+ } else if (ch == 32) {
+ fseek(f, size2, SEEK_CUR);
+ p += size2;
+ size -= size2;
+ } else {
+ memcpy(p, tmp, size2);
+ p += size2;
+ size -= size2;
+ printf("Re-enable write bus error mode and press any key (ESC=abort)\n");
+ if (getchar() == 27) {
+ exit(0);
+ }
+ }
+ } else {
+ printf("Write-only bus error mode, data already correct\n");
+ fseek(f, size2, SEEK_CUR);
+ p += size2;
+ size -= size2;
+ }
+ free(tmp);
+ }
}
if (size > 0) {
if (fread(p, 1, size, f) != size)
static uae_u16 test_sr, test_ccrignoremask;
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);
-}
-
static int addr_diff(uae_u8 *ap, uae_u8 *bp, int size)
{
for (int i = 0; i < size; i++) {
- if (is_valid_test_addr((uae_u32)bp)) {
+ if (is_valid_test_addr_read((uae_u32)bp)) {
if (*ap != *bp)
return 1;
}
*outbp++ = '*';
else if (cnt > 0)
*outbp++ = '.';
- if ((uae_u8*)address >= safe_memory_start && (uae_u8*)address < safe_memory_end) {
+ if ((uae_u8*)address >= safe_memory_start && (uae_u8*)address < safe_memory_end && (safe_memory_mode & 1)) {
outbp[0] = '?';
outbp[1] = '?';
} else {
int lines = 0;
while (lines++ < 5) {
int v = 0;
- if (!is_valid_test_addr((uae_u32)p) || !is_valid_test_addr((uae_u32)p + 1))
+ if (!is_valid_test_addr_read((uae_u32)p) || !is_valid_test_addr_read((uae_u32)p + 1))
break;
tmpbuffer[0] = 0;
if (!(((uae_u32)code) & 1)) {
uae_u32 v;
uae_u8 excdatalen = *p++;
int size;
+ int excrw = 0;
if (!excdatalen) {
return p;
// check possible extra trace
last_exception_extra = *p++;
if ((last_exception_extra & 0x7f) == 9) {
- exceptioncount[last_exception_extra & 0x7f]++;
+ exceptioncount[0][last_exception_extra & 0x7f]++;
uae_u32 ret = (regs->tracedata[1] << 16) | regs->tracedata[2];
uae_u16 sr = regs->tracedata[0];
if (regs->tracecnt == 0) {
}
}
- exceptioncount[*gotexcnum]++;
-
exc = last_exception;
if (excdatalen != 0xff) {
if (cpu_lvl == 0) {
uae_u8 opcode1 = p[2];
exc[0] = opcode0;
exc[1] = (opcode1 & ~0x1f) | p[0];
+ excrw = (p[0] & 0x10) == 0;
p += 3;
// access address
v = opcode_memory_addr;
case 8:
exc[8] = *p++;
exc[9] = *p++;
+ excrw = (exc[8] & 1) == 0;
v = opcode_memory_addr;
p = restore_rel_ordered(p, &v);
pl(exc + 10, v);
} else {
exclen = last_exception_len;
}
+
+ exceptioncount[excrw][*gotexcnum]++;
+
if (exclen == 0 || *gotexcnum != excnum)
return p;
if (memcmp(exc, sp, exclen)) {
return;
for (int i = 0; i < SIZE_STORED_ADDRESS; i++) {
uae_u32 ss = s + (i - SIZE_STORED_ADDRESS_OFFSET);
- if (is_valid_test_addr(ss)) {
+ if (is_valid_test_addr_read(ss)) {
*d++ = *((uae_u8 *)ss);
} else {
*d++ = 0;
if (opcode_memory_end > (uae_u8*)pc + 32) {
end_test();
printf("Corrupted opcode memory\n");
+ endinfo();
exit(0);
}
}
interrupt_mask = (lvl_mask >> 20) & 7;
addressing_mask = (lvl_mask & 0x80000000) ? 0xffffffff : 0x00ffffff;
sr_undefined_mask = lvl_mask & 0xffff;
+ safe_memory_mode = (lvl_mask >> 23) & 3;
fpu_model = read_u32(f);
test_low_memory_start = read_u32(f);
test_low_memory_end = read_u32(f);
printf("%lu ", testcnt);
printf("S=%ld", supercnt);
for (int i = 0; i < 128; i++) {
- if (exceptioncount[i]) {
- printf(" E%02d=%ld", i, exceptioncount[i]);
+ if (exceptioncount[0][i] || exceptioncount[1][i]) {
+ if (i == 2 || i == 3) {
+ printf(" E%02d=%ld/%ld", i, exceptioncount[0][i], exceptioncount[1][i]);
+ } else {
+ printf(" E%02d=%ld", i, exceptioncount[0][i]);
+ }
}
}
printf("\n");
// }
}
+static void fill_prefetch_next_skipopcode(void)
+{
+ if (using_prefetch) {
+ irc2ir();
+ if (using_bus_error) {
+ printf("\topcode |= 0x20000;\n");
+ }
+ fill_prefetch_1(m68k_pc_offset + 2);
+ }
+ // if (using_prefetch_020) {
+ // printf ("\t%s (%d);\n", prefetch_word, m68k_pc_offset);
+ // did_prefetch = 1;
+ // }
+}
+
+
static void fill_prefetch_next_empty(void)
{
if (using_prefetch) {
if (dmode == Apdi) {
- // this is buggy, bus error stack frame opcode field contains next
- // instruction opcode and Instruction/Not field is one!
- printf("\t\topcode = regs.ir;\n");
- *fcmodeflags |= 0x08; // "Not instruction" = 1
+ printf("\t\tif (regs.t1) opcode |= 0x10000;\n"); // I/N set
} else if (dmode == Aipi) {
} else if (size == sz_word) {
if (dmode == Apdi) {
- // this is buggy, bus error stack frame opcode field contains next
- // instruction opcode and Instruction/Not field is one!
- printf("\t\topcode = regs.ir;\n");
- *fcmodeflags |= 0x08; // "Not instruction" = 1
-
+
+ printf("\t\tif (regs.t1) opcode |= 0x10000;\n"); // I/N set
+
} else if (dmode == Aipi) {
// move.w x,(an)+: an is not increased
static void check_bus_error(const char *name, int offset, int write, int size, const char *writevar, int fc)
{
+ int mnemo = g_instr->mnemo;
+
// check possible bus error (if 68000/010 and enabled)
if (!using_bus_error)
return;
offset = do_bus_error_fixes(name, offset, write);
- if (g_instr->mnemo == i_BTST && (g_instr->dmode == PC16 || g_instr->dmode == PC8r)) {
+ if (mnemo == i_BTST && (g_instr->dmode == PC16 || g_instr->dmode == PC8r)) {
// BTST special case where destination is read access
fc = 2;
}
- if (g_instr->mnemo == i_MVMEL && (g_instr->dmode == PC16 || g_instr->dmode == PC8r)) {
+ if (mnemo == i_MVMEL && (g_instr->dmode == PC16 || g_instr->dmode == PC8r)) {
// MOVEM to registers
fc = 2;
}
- if (g_instr->mnemo == i_LINK) {
+ if (mnemo == i_LINK) {
// a7 -> a0 copy done before A7 address error check
printf("\tm68k_areg(regs, srcreg) = olda;\n");
}
printf("\t\topcode |= 0x%x;\n", extra);
}
+ // write causing bus error and trace: set I/N
+ if (write && g_instr->size <= sz_word &&
+ mnemo != i_MOVE &&
+ mnemo != i_MVMEL && mnemo != i_MVMLE &&
+ mnemo != i_MVPRM && mnemo != i_MVPMR) {
+ printf("\t\tif (regs.t1) opcode |= 0x10000;\n"); // I/N set
+ }
+
//if (cpu_level == 0 && write) {
// printf("\t\topcode = regs.irc;\n");
//}
if (curi->mnemo == i_MOVEA && curi->size == sz_word)
printf ("\tsrc = (uae_s32)(uae_s16)src;\n");
if (curi->dmode == Apdi) {
- fill_prefetch_next ();
+ if (curi->size == sz_long)
+ fill_prefetch_next_skipopcode();
+ else
+ fill_prefetch_next();
prefetch_done = 1;
}