#include "disasm.h"
#include "ini.h"
#include "fpp.h"
+#include "mmu_common.h"
#include "options.h"
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
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)
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;
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;
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;
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;
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:
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);
}
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);
}
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);
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 {
}
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);
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);
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++;
}
// 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)
{
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:
}
*isconstant = 32;
}
+ *eap = 1;
break;
}
case absw:
put_word_test(pc, rand16());
*isconstant = 16;
pc += 2;
+ *eap = 1;
break;
case absl:
{
*isconstant = 32;
pc += 4;
}
+ *eap = 1;
break;
case imm:
if (fpuopcode >= 0 && opcodesize < 8) {
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)
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) {
}
+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)
}
}
- xorshiftstate ^= 0x12;
-
int pathlen = _tcslen(path);
_stprintf(dir, _T("%s%s"), path, mns);
if (fpuopcode < 0) {
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;
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];
}
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);
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) {
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)
// 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
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) {
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;
}
}
}
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);
nextopcode:;
}
- save_data(dst, dir);
+ if (subtest_count > 0) {
+ save_data(dst, dir);
+ }
dst = storage_buffer;
if (opcodecnt == 1)
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]--;
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) {
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);
}
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++) {
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;
#else
static char outbuffer[4000];
#endif
-static char tmpbuffer[256];
+static char tmpbuffer[1024];
static char *outbp;
static int infoadded;
static int errors;
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;
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);
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);
printf("Couldn't open '%s'\n", fname);
exit(0);
}
- return NULL;
+ return NULL;
}
int size = *sizep;
if (size < 0) {
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);
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 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) {
*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';
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);
}
p++;
store_addr(regs.srcaddr, srcaddr);
- store_addr(regs.srcaddr, dstaddr);
+ store_addr(regs.dstaddr, dstaddr);
xmemcpy(&last_registers, ®s, sizeof(struct registers));
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) {
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;
}
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;