static int test_exception_3_fc;
static int test_exception_3_size;
static int test_exception_3_di;
+static uae_u16 test_exception_3_sr;
static int test_exception_opcode;
static uae_u32 trace_store_pc;
static uae_u16 trace_store_sr;
if (addr < test_low_memory_start || test_low_memory_start == 0xffffffff)
goto oob;
// exception vectors needed during tests
- if ((addr + size >= 0x08 && addr < 0x30 || (addr + size >= 0x80 && addr < 0xc0)) && currprefs.cpu_model == 68000)
- goto oob;
+ if (currprefs.cpu_model == 68000) {
+ if ((addr + size >= 0x08 && addr < 0x30 || (addr + size >= 0x80 && addr < 0xc0)))
+ goto oob;
+ if (feature_interrupts && (addr + size >= 0x64 && addr < 0x7c))
+ goto oob;
+ }
if (addr + size >= test_low_memory_end)
goto oob;
if (w && lmem_rom)
return get_iword_test(m68k_getpci() + o);
}
-static void previoussame(uaecptr addr, int size)
+static void previoussame(uaecptr addr, int size, uae_u32 *old)
{
if (!ahcnt_current || ahcnt_current == ahcnt_written)
return;
// Move from SR does two writes to same address.
// Loop mode can write different values to same address.
// Mark old values as do not save.
+ // Also loop mode test can do multi writes and it needs original value.
+ bool gotold = false;
for (int i = ahcnt_written; i < ahcnt_current; i++) {
struct accesshistory *ah = &ahist[i];
if (ah->size == size && ah->addr == addr) {
ah->donotsave = true;
- }
- if (size == sz_long) {
- if (ah->size == sz_word && ah->addr == addr) {
- ah->donotsave = true;
+ if (!gotold) {
+ *old = ah->oldval;
+ gotold = true;
}
- if (ah->size == sz_word && ah->addr == addr + 2) {
- ah->donotsave = true;
+ }
+ if (cpu_lvl < 2) {
+ if (size == sz_long) {
+ if (ah->size == sz_word && ah->addr == addr) {
+ ah->donotsave = true;
+ }
+ if (ah->size == sz_word && ah->addr == addr + 2) {
+ ah->donotsave = true;
+ }
}
}
}
check_bus_error(addr, 1, regs.s ? 5 : 1);
uae_u8 *p = get_addr(addr, 1, 2);
if (!out_of_test_space && !noaccesshistory && !hardware_bus_error_fake) {
- previoussame(addr, sz_byte);
+ uae_u32 old = p[0];
+ previoussame(addr, sz_byte, &old);
if (ahcnt_current >= MAX_ACCESSHIST) {
wprintf(_T(" ahist overflow!"));
abort();
struct accesshistory *ah = &ahist[ahcnt_current++];
ah->addr = addr;
ah->val = v & 0xff;
- ah->oldval = *p;
+ ah->oldval = old & 0xff;
ah->size = sz_byte;
ah->donotsave = false;
}
} else {
uae_u8 *p = get_addr(addr, 2, 2);
if (!out_of_test_space && !noaccesshistory && !hardware_bus_error_fake) {
- previoussame(addr, sz_word);
+ uae_u32 old = (p[0] << 8) | p[1];
+ previoussame(addr, sz_word, &old);
if (ahcnt_current >= MAX_ACCESSHIST) {
wprintf(_T(" ahist overflow!"));
abort();
struct accesshistory *ah = &ahist[ahcnt_current++];
ah->addr = addr;
ah->val = v & 0xffff;
- ah->oldval = (p[0] << 8) | p[1];
+ ah->oldval = old & 0xffff;
ah->size = sz_word;
ah->donotsave = false;
}
} else {
uae_u8 *p = get_addr(addr, 4, 2);
if (!out_of_test_space && !noaccesshistory && !hardware_bus_error_fake) {
- previoussame(addr, sz_long);
+ uae_u32 old = (p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3];
+ previoussame(addr, sz_long, &old);
if (ahcnt_current >= MAX_ACCESSHIST) {
wprintf(_T(" ahist overflow!"));
abort();
struct accesshistory *ah = &ahist[ahcnt_current++];
ah->addr = addr;
ah->val = v;
- ah->oldval = (p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3];
+ ah->oldval = old;
ah->size = sz_long;
ah->donotsave = false;
}
// Always trace if Tx bits were already set, even if this SR modification cleared them.
activate_trace();
}
-
}
void REGPARAM2 MakeFromSR_T0(void)
MakeSR();
regs.sr |= 0x2000;
- regs.sr &= ~0x8000;
+ regs.sr &= ~(0x8000 | 0x4000);
MakeFromSR();
regs.pc = original_exception * 4;
} else {
flags |= 0x20000;
}
+ if (cpu_lvl < 5) {
+ regs.m = 0;
+ }
}
// set I/N if original exception was group 1 exception.
}
uae_u32 REGPARAM2 op_unimpl_1(uae_u32 opcode)
{
- if ((opcode & 0xf000) == 0xf000 || currprefs.cpu_model < 68060)
+ if ((opcode & 0xf000) == 0xf000 || currprefs.cpu_model < 68060) {
op_illg(opcode);
- else
+ } else {
op_unimpl(opcode);
+ }
return 0;
}
uae_u32 REGPARAM2 op_illg(uae_u32 opcode)
test_exception_addr = addr;
test_exception_opcode = opcode;
test_exception_3_fc = fc;
- test_exception_3_size = size;
+ test_exception_3_size = size & 15;
test_exception_3_di = 1;
if (currprefs.cpu_model == 68000) {
test_exception_addr = addr;
test_exception_opcode = opcode;
test_exception_3_fc = fc;
- test_exception_3_size = size;
- if (size == sz_byte) {
- regs.write_buffer &= 0xff00;
- regs.write_buffer |= val & 0xff;
- } else {
+ test_exception_3_size = size & 15;
+ if (size & 0x100) {
regs.write_buffer = val;
+ } else {
+ if (size == sz_byte) {
+ regs.write_buffer &= 0xff00;
+ regs.write_buffer |= val & 0xff;
+ } else {
+ regs.write_buffer = val;
+ }
}
test_exception_3_di = 1;
test_exception_addr = addr;
test_exception_opcode = opcode;
test_exception_3_fc = fc;
- test_exception_3_size = size;
+ test_exception_3_size = size & 15;
test_exception_3_di = 1;
if (currprefs.cpu_model == 68000) {
test_exception_addr = addr;
test_exception_opcode = opcode;
test_exception_3_fc = fc;
- test_exception_3_size = size;
+ test_exception_3_size = size & 15;
regs.write_buffer = val;
test_exception_3_di = 1;
doexcstack();
}
+void exception3_read_prefetch_68040bug(uae_u32 opcode, uae_u32 addr, uae_u16 secondarysr)
+{
+ if (cpu_lvl == 1) {
+ get_word_test(addr & ~1);
+ } else {
+ add_memory_cycles(1);
+ }
+ exception3_pc_inc();
+
+ test_exception = 3;
+ test_exception_3_w = 0;
+ test_exception_addr = addr;
+ test_exception_opcode = opcode | 0x10000;
+ test_exception_3_fc = 2;
+ test_exception_3_size = sz_word;
+ test_exception_3_di = 0;
+ test_exception_3_sr = secondarysr;
+
+ doexcstack();
+}
+
+
void exception3_read_access2(uae_u32 opcode, uae_u32 addr, int size, int fc)
{
get_word_test(addr & ~1);
test_exception_opcode = -1;
bool t0 = currprefs.cpu_model >= 68020 && regs.t0 && !regs.t1;
- // check T0 trace
- if (t0) {
- activate_trace();
+ if (n != 14) {
+ // check T0 trace
+ if (t0) {
+ activate_trace();
+ }
}
doexcstack();
}
if (generate_address_mode && reg >= 8)
return false;
+ if (feature_loop_mode_register == reg)
+ return false;
// don't unnecessarily modify static forced register
for (int i = 0; i < regdatacnt; i++) {
}
break;
case 11:
+ if (feature_loop_mode && !feature_loop_mode_68010) {
+ return false;
+ }
v ^= 0x8000;
break;
case 12:
{
if (!len)
return dst;
- if (len > 32) {
+ if (len > 256) {
wprintf(_T(" too long byte count!\n"));
abort();
}
if (header) {
*dst++ = CT_MEMWRITES | CT_PC_BYTES;
}
- *dst++ = (offset << 5) | (uae_u8)(len == 32 ? 0 : len);
+ if (len > 32) {
+ *dst++ = (offset << 5) | 31;
+ *dst++ = len;
+ } else {
+ *dst++ = (offset << 5) | (uae_u8)(len == 32 ? 0 : len);
+ }
for (int i = 0; i < len; i++) {
*dst++ = get_byte_test(start);
start++;
}
}
-static void save_data(uae_u8 *dst, const TCHAR *dir)
+static void save_data(uae_u8 *dst, const TCHAR *dir, int size)
{
TCHAR path[1000];
fwrite(data, 1, 2, f);
fclose(f);
filecount++;
- save_data(dst, dir);
+ save_data(dst, dir, size);
} else {
uae_u8 data[4];
pl(data, DATA_VERSION);
fwrite(data, 1, 4, f);
pl(data, (uae_u32)starttime);
fwrite(data, 1, 4, f);
- pl(data, 0);
+ pl(data, (size & 3));
fwrite(data, 1, 4, f);
+ pl(data, 0);
fwrite(data, 1, 4, f);
*dst++ = CT_END_FINISH;
*dst++ = filecount;
} else {
if (opcodecnt == 1) {
// STOP #xxxx: test all combinations
- // (also includes RTD)
if (dp->mnemo == i_LPSTOP) {
uae_u16 lp = 0x01c0;
if (imm16_cnt & (0x40 | 0x80)) {
else
*isconstant = -1;
} else if (dp->mnemo == i_BSR || dp->mnemo == i_DBcc || dp->mnemo == i_Bcc ||
- dp->mnemo == i_ORSR || dp->mnemo == i_ANDSR || dp->mnemo == i_EORSR) {
+ dp->mnemo == i_ORSR || dp->mnemo == i_ANDSR || dp->mnemo == i_EORSR ||
+ dp->mnemo == i_RTD) {
// don't try to test all 65536 possibilies..
uae_u16 i16 = imm16_cnt;
put_word_test(pc, imm16_cnt);
static const int interrupt_levels[] =
{
- 1, 1, 1, 2, 3, 3, 3, 4, 4, 4, 4, 5, 5, 6, 6, 0
+ 0, 1, 1, 1, 2, 3, 3, 3, 4, 4, 4, 4, 5, 5, 6, 6
};
+static bool check_interrupts(void)
+{
+ if (feature_interrupts) {
+ int ic = interrupt_count & 15;
+ int lvl = interrupt_levels[ic];
+ if (lvl > 0 && lvl > feature_min_interrupt_mask) {
+ Exception(lvl + 24);
+ return true;
+ }
+ }
+ return false;
+}
+
static void execute_ins(uaecptr endpc, uaecptr targetpc, struct instr *dp)
{
uae_u16 opc = regs.ir;
uae_u16 opw1 = (opcode_memory[2] << 8) | (opcode_memory[3] << 0);
uae_u16 opw2 = (opcode_memory[4] << 8) | (opcode_memory[5] << 0);
- if (opc == 0xf202
- && opw1 == 0x5225
+ if (opc == 0x4ed6
+ //&& opw1 == 0x5225
//&& opw2 == 0x4afc
)
printf("");
cpu_cycles = 0;
regs.loop_mode = 0;
- int cnt = (feature_loop_mode + 1) * 2;
+ int cnt = 2;
+ if (feature_loop_mode_68010) {
+ cnt = (feature_loop_mode + 1) * 2;
+ } else if (feature_loop_mode) {
+ cnt = (feature_loop_mode + 1) * 20;
+ }
if (multi_mode)
cnt = 100;
do_trace();
}
- if (feature_interrupts) {
- int ic = interrupt_count;
- interrupt_count++;
- interrupt_count &= 15;
- int lvl = interrupt_levels[ic];
- if (lvl > 0 && lvl > feature_min_interrupt_mask) {
- Exception(lvl + 24);
+ if (cpu_lvl <= 1) {
+ if (check_interrupts())
break;
- }
}
regs.instruction_pc = regs.pc;
break;
}
+ if (cpu_lvl >= 2) {
+ if (check_interrupts())
+ break;
+ }
+
if (regs.pc == endpc || regs.pc == targetpc) {
// Trace is only added as an exception if there was no other exceptions
// Trace stacked with other exception is handled later
- if (SPCFLAG_DOTRACE && !test_exception) {
+ if (SPCFLAG_DOTRACE && !test_exception && trace_store_pc == 0xffffffffff) {
Exception(9);
}
break;
cnt--;
- if (!feature_loop_mode && !multi_mode && opc != 0x4e71) {
+ if (!feature_loop_mode && !multi_mode && opc != NOP_OPCODE) {
wprintf(_T(" Test instruction didn't finish in single step in non-loop mode!?\n"));
abort();
}
int count = 0;
+ if (feature_loop_mode && !feature_loop_mode_68010) {
+ registers[8 + 3] = 0;
+ }
+
registers[8 + 6] = opcode_memory_start - 0x100;
registers[15] = user_stack_memory_use;
dst = storage_buffer;
- if (low_memory) {
+ if (low_memory && low_memory_size != 0xffffffff) {
memcpy(low_memory, low_memory_temp, low_memory_size);
}
- if (high_memory) {
+ if (high_memory && high_memory_size != 0xffffffff) {
memcpy(high_memory, high_memory_temp, high_memory_size);
}
memcpy(test_memory, test_memory_temp, test_memory_size);
uae_u32 target_ea_bak[3], target_address_bak, target_opcode_address_bak;
for (;;) {
+ int got_something = 0;
target_ea_bak[0] = target_ea[0];
target_ea_bak[1] = target_ea[1];
if (feature_loop_mode) {
cur_regs.regs[feature_loop_mode_register] &= 0xffff0000;
- cur_regs.regs[feature_loop_mode_register] |= feature_loop_mode - 1;
+ if (feature_loop_mode_68010) {
+ cur_regs.regs[feature_loop_mode_register] |= feature_loop_mode - 1;
+ } else {
+ // loop register is used as index in some addressing modes but
+ // we don't handle situation where multiple memory writes access same
+ // memory location using different access sizes.
+ cur_regs.regs[feature_loop_mode_register] |= feature_loop_mode * 64 - 1;
+ }
}
for (int i = 0; i < MAX_REGISTERS; i++) {
continue;
}
+ got_something = 1;
+
target_ea[0] = target_ea_bak[0];
target_ea[1] = target_ea_bak[1];
target_ea[2] = target_ea_bak[2];
uae_u32 branch_target_swap_address = 0;
int branch_target_swap_mode = 0;
- uae_u32 branch_target_data_original = 0x4afc4e71;
+ uae_u32 branch_target_data_original = (ILLG_OPCODE << 16) | NOP_OPCODE;
uae_u32 branch_target_data = branch_target_data_original;
int srcregused = -1;
pc -= 2;
int cnt = 0;
while (pc - 2 != opcode_memory_address) {
- put_word_test(pc, 0x4e71);
+ put_word_test(pc, NOP_OPCODE);
pc += 2;
cnt++;
if (cnt >= 16) {
uae_u8 *bo = opcode_memory_ptr + 2;
uae_u16 bopw1 = (bo[0] << 8) | (bo[1] << 0);
uae_u16 bopw2 = (bo[2] << 8) | (bo[3] << 0);
- if (opc == 0x4e96
- //&& bopw1 == 0x3dec
- //&& bopw2 == 0x2770
+ if (opc == 0x0ab3
+ && bopw1 == 0x5aa9
+ && bopw2 == 0xe5cc
)
printf("");
// loop mode
if (feature_loop_mode) {
// dbf dn, opcode_memory_start
+ if (!feature_loop_mode_68010) {
+ for (int i = 0; i < 4; i++) {
+ // bcc, bne, bvc, bpl
+ put_word(pc, 0x6400 + (i * 0x0200) + 4);
+ pc += 2;
+ // adda.w #x,a3
+ put_long(pc, 0xd6fc0000 | (1 << (i * 3)));
+ pc += 4;
+ }
+ // negx.b d0 ; add.w d0,d0
+ put_long(pc, 0x4000d040);
+ pc += 4;
+ // sub.w #63,dn
+ put_long(pc, ((0x0440 | feature_loop_mode_register) << 16) | 63);
+ pc += 4;
+ }
+ // dbf dn,label
put_long_test(pc, ((0x51c8 | feature_loop_mode_register) << 16) | ((opcode_memory_address - pc - 2) & 0xffff));
pc += 4;
}
// end word, needed to detect if instruction finished normally when
// running on real hardware.
- uae_u32 originalendopcode = 0x4afc4e71;
+ uae_u32 originalendopcode = (ILLG_OPCODE << 16) | NOP_OPCODE;
uae_u32 endopcode = originalendopcode;
uae_u32 actualendpc = pc;
if (dstaddr != 0xffffffff && srcaddr != dstaddr) {
outbytes(_T("D"), dstaddr);
}
+ if (feature_loop_mode) {
+ wprintf(_T("\n"));
+ for (int i = 0; i < 20; i++) {
+ out_of_test_space = false;
+ if (get_word_test(nextpc) == ILLG_OPCODE)
+ break;
+ m68k_disasm_2(out, sizeof(out) / sizeof(TCHAR), nextpc, &nextpc, 1, NULL, NULL, 0xffffffff, 0);
+ my_trim(out);
+ wprintf(_T("%08u %s\n"), subtest_count, out);
+ }
+ }
}
// disassembler may set this
uae_u32 branchtarget_old_prev = branchtarget_old;
uae_u32 srcaddr_old_prev = srcaddr_old;
uae_u32 dstaddr_old_prev = dstaddr_old;
+ int interrupt_count_old_prev = interrupt_count;
if (startpc != startpc_old) {
dst = store_reg(dst, CT_PC, startpc_old, startpc, -1);
ahcnt_current = ahcnt_written;
int ahcnt_start = ahcnt_current;
+ if (feature_interrupts) {
+ *dst++ = (uae_u8)interrupt_count;
+ interrupt_count++;
+ interrupt_count &= 15;
+ }
+
memset(®s, 0, sizeof(regs));
// swap end opcode illegal/nop
noaccesshistory++;
endopcode = (endopcode >> 16) | (endopcode << 16);
- int extraopcodeendsize = ((endopcode >> 16) == 0x4e71) ? 2 : 0;
+ int extraopcodeendsize = ((endopcode >> 16) == NOP_OPCODE) ? 2 : 0;
int endopcodesize = 0;
if (!is_nowrite_address(pc - 4, 4)) {
put_long_test(pc - 4, endopcode);
- endopcodesize = (endopcode >> 16) == 0x4e71 ? 2 : 4;
+ endopcodesize = (endopcode >> 16) == NOP_OPCODE ? 2 : 4;
} else if (!is_nowrite_address(pc - 4, 2)) {
put_word_test(pc - 4, endopcode >> 16);
endopcodesize = 2;
if (!(branch_target_swap_address & 1)) {
branch_target_data = (branch_target_data >> 16) | (branch_target_data << 16);
put_long_test(branch_target_swap_address, branch_target_data);
- if ((branch_target_data >> 16) == 0x4e71)
+ if ((branch_target_data >> 16) == NOP_OPCODE)
branch_target_pc = branch_target + 2;
else
branch_target_pc = branch_target;
regs.ir = get_word_test(regs.pc + 0);
regs.irc = get_word_test(regs.pc + 2);
- if (regs.ir == 0x4afc && dp->mnemo != i_ILLG) {
+ if (regs.ir == ILLG_OPCODE && dp->mnemo != i_ILLG) {
wprintf(_T(" Illegal as starting opcode!?\n"));
abort();
}
// did we have trace also active?
if (SPCFLAG_DOTRACE) {
- if ((regs.t1 || regs.t0) && (test_exception == 5 || test_exception == 6 || test_exception == 7 || (test_exception >= 32 && test_exception <= 47) || (cpu_lvl == 1 && test_exception == 14))) {
- test_exception_extra = 9;
- } else {
- test_exception_extra = 0;
+ test_exception_extra = 0;
+ if (regs.t1 || regs.t0) {
+ if ((cpu_lvl < 4 && (test_exception == 5 || test_exception == 6 || test_exception == 7 || (test_exception >= 32 && test_exception <= 47)))
+ ||
+ (cpu_lvl == 1 && test_exception == 14)) {
+ test_exception_extra = 9;
+ }
}
}
if (trace_store_pc != 0xffffffff) {
branchtarget_old = branchtarget_old_prev;
instructionendpc_old = instructionendpc_old_prev;
startpc_old = startpc_old_prev;
+ interrupt_count = interrupt_count_old_prev;
} else {
full_format_cnt++;
data_saved = 1;
// save to file and create new file if watermark reached
if (dst - storage_buffer >= storage_buffer_watermark) {
if (subtest_count > 0) {
- save_data(dst, dir);
+ save_data(dst, dir, size);
branchtarget_old = 0xffffffff;
srcaddr_old = 0xffffffff;
}
if (data_saved) {
- save_data(dst, dir);
+ save_data(dst, dir, size);
data_saved = 0;
}
dst = storage_buffer;
if (nextround) {
rounds--;
if (rounds < 0) {
- if (subtest_count >= feature_test_rounds_opcode)
+ if (subtest_count >= feature_test_rounds_opcode || !got_something)
break;
rounds = 1;
}
if (currprefs.fpu_model < 0) {
currprefs.fpu_model = currprefs.cpu_model;
if (currprefs.fpu_model == 68020 || currprefs.fpu_model == 68030) {
- currprefs.fpu_model == 68882;
+ currprefs.fpu_model = 68882;
}
} else if (currprefs.cpu_model >= 68040) {
currprefs.fpu_model = currprefs.cpu_model;
; main test memory start and size (real hardware must have RAM in this address space)
test_memory_start=0x860000
;test_memory_start=0x68800000
+;test_memory_start=0x43800000
;test_memory_start=0x07800000
-;test_memory_start=0x340000
-test_memory_size=0x40000
+test_memory_size=0xa0000
; address where test instructions are located
; if not defined: mid point of test memory
; test word or long odd data access address errors (68000/010 only)
; 0 = do not generate address errors
; 1 = include address errors
-; 2 = only generate test instructions that generate address errors
+; 2 = only generate test instructions that generate address errors (trace is allowed)
feature_exception3_data=0
; test branches to odd addresses
; generate loop test: label: <test instruction> dbf dn,label
; value: 0 = disabled, >0 = number of loops
-feature_loop_mode=0
-feature_loop_mode_register=7
+; feature_loop_mode=0
+; feature_loop_mode_register=7
; only generate 68010 loop mode compatible instructions
-feature_loop_mode_68010=0
+: feature_loop_mode_68010=0
+; reload changed address register(s) (-(an) or (an)+) after each round
+; feature_loop_mode_reload=1
; 68020+ addressing modes (this makes test files much larger if other addressing modes are also enabled)
; currently does not generate any reserved mode bit combinations.
[test=IRQ]
enabled=0
cpu=68000-68010
-mode=nop,ext,swap
+feature_sr_mask=0x8000
feature_interrupts=1
+mode=jsr,jmp,bsr,bcc,dbcc,nop,exg,swap,stop,mvsr2,mv2sr,andsr,eorsr,orsr
+min_opcode_test_rounds=100
; source EA address error
[test=AE_SRC]
feature_target_opcode_offset=2,4,6,8,10,12,14,16
opcode_memory_start=0x87ffee
test_memory_size=0xa0000
+test_memory_size=0x100000
+opcode_memory_start=0x87ffa0
mode=all
; source EA read bus error (requires extra hardware)
feature_safe_memory_mode=R
feature_target_src_ea=0x87fffc,0x87fffd,0x87fffe,0x87ffff,0x880000,0x880001,0x880002,0x880003,0x880004
feature_target_dst_ea=
-test_memory_size=0xa0000
+test_memory_start=0x860000
+test_memory_size=0x100000
+opcode_memory_start=0x87ffa0
mode=all
; destination EA read bus error (requires extra hardware)
feature_safe_memory_mode=R
feature_target_src_ea=
feature_target_dst_ea=0x87fffc,0x87fffd,0x87fffe,0x87ffff,0x880000,0x880001,0x880002,0x880003,0x880004
-test_memory_size=0xa0000
+test_memory_start=0x860000
+test_memory_size=0x100000
+opcode_memory_start=0x87ffa0
mode=all
; source EA (=RMW instructions like NOT have only source EA) write bus error (requires extra hardware)
opcode_memory_start=0x8fffa0
test_memory_start=0x880000
test_memory_size=0x100000
-mode=all
+mode=moves
+;mode=all
; destination EA write bus error (requires extra hardware)
[test=BE_DSTW]
test_memory_size=0x100000
mode=all
+
; 68010 loop mode compatible instructions
-[test=loopmode]
+[test=LM]
enabled=0
cpu=68010
feature_loop_mode_68010=1
+feature_loop_mode=3
+feature_loop_mode_register=7
+min_opcode_test_rounds=100
mode=all
; **************
[test=Basic]
enabled=0
cpu=68020-68060
-feature_sr_mask=0xd000
+feature_sr_mask=0xf000
mode=all
+; interrupt exception
+[test=IRQ]
+enabled=0
+cpu=68020-68060
+mode=jsr,jmp,bsr,bcc,dbcc,nop,exg,swap,stop,mvsr2,mv2sr,andsr,eorsr,orsr
+min_opcode_test_rounds=100
+feature_interrupts=1
+
; 68020+ addressing mode tests
[test=FFEXT_SRC]
enabled=0
[test=AE]
enabled=0
cpu=68020-68060
+feature_sr_mask=0xd000
feature_exception3_instruction=2
mode=all
[test=ODD_STK]
enabled=0
cpu=68020-68060
+feature_sr_mask=0xd000
feature_usp=2
mode=rts,rtd,rtr,jsr,bsr,link,unlk,pea
[test=ODD_EXC]
enabled=0
cpu=68020-68060
+feature_sr_mask=0xd000
feature_exception_vectors=0x000123
mode=mv2sr.w,mvsr2.w,mvusp2r,mvr2usp,illegal,chk,trap,trapv,orsr.w,eorsr.w,andsr.w,divu,divs,divul,divsl
[test=ODD_IRQ]
enabled=0
cpu=68020-68060
-mode=nop,ext,swap
+feature_sr_mask=0xd000
+mode=ext,swap
feature_interrupts=1
feature_exception_vectors=0x000123
exceptions=11,55,60,61
feature_flags_mode=2
mode=fillegal
+
+; ******************
+; JIT loop mode test
+; ******************
+
+[test=JITLM]
+enabled=0
+cpu=68020-68060
+cpu_address_space=68020
+feature_loop_mode=10
+feature_loop_mode_reload=1
+feature_loop_mode_register=7
+mode=eor
+feature_instruction_size=W
+verbose=0
static uae_u8 ccr_mask;
static uae_u32 addressing_mask = 0x00ffffff;
static uae_u32 interrupt_mask;
+static short instructionsize;
static short disasm;
static short basicexcept;
static short excskipccr;
static uae_u8 branchtarget[SIZE_STORED_ADDRESS];
static uae_u8 stackaddr[SIZE_STORED_ADDRESS];
static uae_u32 stackaddr_ptr;
+static uae_u8 *opcode_memory_end;
static char opcode[32], group[32], cpustr[10];
break;
uae_u16 v = (p[i] << 8) | (p[i + 1]);
printf("%08x %04x\n", (uae_u32)&p[i], v);
- if (v == 0x4afc && i > 0)
+ if (v == ILLG_OPCODE && i > 0)
break;
}
printf("\n");
static uae_u8 *restore_bytes(uae_u8 *mem, uae_u8 *p)
{
uae_u8 *addr = mem;
- uae_u8 v = *p++;
+ uae_u16 v = *p++;
addr += v >> 5;
v &= 31;
- if (v == 0)
+ if (v == 31) {
+ v = *p++;
+ if (v == 0) {
+ v = 256;
+ }
+ } else if (v == 0) {
v = 32;
+ }
#ifndef _MSC_VER
xmemcpy(addr, p, v);
#endif
uae_u8 *p = mem;
int offset = 0;
int lines = 0;
- while (lines++ < 7) {
+ while (lines++ < 15) {
int v = 0;
if (!is_valid_word(p)) {
sprintf(outbp, "%08x -- INACCESSIBLE --\n", (uae_u32)p);
}
sprintf(outbp, "%04x ", v);
outbp += strlen(outbp);
- if (v == 0x4e71)
+ if (v == NOP_OPCODE)
lines--;
}
sprintf(outbp, " %s\n", tmpbuffer);
outbp += strlen(outbp);
if (!is_valid_word((uae_u8*)(code + offset)))
break;
- if (v <= 0 || code[offset] == 0x4afc)
+ if (v <= 0 || code[offset] == ILLG_OPCODE)
break;
while (v > 0) {
offset++;
} else if ((i % 8) != 0) {
strcat(outbp, " ");
}
+ uae_u32 v1 = r1->regs[i];
+ uae_u32 v2 = r2->regs[i];
+ uae_u32 sv = sreg->regs[i];
outbp += strlen(outbp);
- sprintf(outbp, "%c%d:%c%08x", i < 8 ? 'D' : 'A', i & 7, r1->regs[i] != r2->regs[i] ? '*' : ' ', r->regs[i]);
+ sprintf(outbp, "%c%d:%c%08x", i < 8 ? 'D' : 'A', i & 7, v1 == v2 && v1 != sv ? '*' : (v1 != v2 ? '!' : ' '), r->regs[i]);
outbp += strlen(outbp);
}
*outbp++ = '\n';
- sprintf(outbp, "SR:%c%04x PC: %08x ISP: %08x B: %d", r1->sr != r2->sr ? '*' : ' ', r->sr, r->pc, r->ssp, branched);
+ sprintf(outbp, "SR:%c%04x PC: %08x ISP: %08x", r1->sr == r2->sr && r1->sr != sreg->sr ? '*' : (r1->sr != r2->sr ? '!' : ' '), r->sr, r->pc, r->ssp);
} else {
// output only lines that have at least one modified register to save screen space
for (int i = 0; i < 4; i++) {
int diff = 0;
for (int j = 0; j < 4; j++) {
int idx = i * 4 + j;
- if (r1->regs[idx] != r2->regs[idx]) {
+ if (r1->regs[idx] != sreg->regs[idx]) {
diff = 1;
}
}
int idx = i * 4 + j;
if (j > 0)
*outbp++ = ' ';
- sprintf(outbp, "%c%d:%c%08x", idx < 8 ? 'D' : 'A', idx & 7, r->regs[idx] != r2->regs[idx] ? '*' : ' ', r->regs[idx]);
+ uae_u32 v1 = r1->regs[idx];
+ uae_u32 v2 = r2->regs[idx];
+ uae_u32 sv = sreg->regs[idx];
+ sprintf(outbp, "%c%d:%c%08x", idx < 8 ? 'D' : 'A', idx & 7, v1 == v2 && v1 != sv ? '*' : ((v1 != v2) ? '!' : ' '), r->regs[idx]);
outbp += strlen(outbp);
}
*outbp++ = '\n';
}
}
- sprintf(outbp, "SR:%c%04x/%04x PC: %08x ISP: %08x B: %d", r->sr != r2->sr ? '*' : ' ', r->sr, r->expsr, r->pc, r->ssp, branched);
+ sprintf(outbp, "SR:%c%04x/%04x PC: %08x ISP: %08x", r1->sr == r2->sr && r1->sr != sreg->sr ? '*' : (r1->sr != r2->sr ? '!' : ' '), r->sr, r->expsr, r->pc, r->ssp);
}
outbp += strlen(outbp);
if (cpu_lvl >= 2 && cpu_lvl <= 4) {
sprintf(outbp, " MSP: %08x", r->msp);
outbp += strlen(outbp);
}
+ if (branched) {
+ sprintf(outbp, " B: %d", branched);
+ outbp += strlen(outbp);
+ }
*outbp++ = '\n';
*outbp = 0;
last_exception_extra = *p++;
if (last_exception_extra & 0x40) {
*group2with1 = *p++;
+ exceptioncount[0][*group2with1]++;
last_exception_extra &= ~0x40;
}
if ((last_exception_extra & 0x3f) == 9) {
uae_u32 ret = (regs->tracedata[1] << 16) | regs->tracedata[2];
uae_u16 sr = regs->tracedata[0];
if (regs->tracecnt == 0) {
- sprintf(outbp, "Expected trace exception but got none\n");
+ uae_u32 pc;
+ if (!(last_exception_extra & 0x80)) {
+ pc = exceptiontableinuse + (excnum - 2) * 2;
+ } else {
+ pc = opcode_memory_addr;
+ p = restore_rel_ordered(p + 2, &pc);
+ }
+ sprintf(outbp, "Expected trace exception (PC=%08x) but got none.\n", pc);
outbp += strlen(outbp);
*experr = 1;
} else if (!(last_exception_extra & 0x80)) {
}
alts = 3;
}
+ if (instructionsize == 0) {
+ // if byte wide bus error, ignore high byte of input and output buffer
+ // contents of high byte depends on used alu operation and instruction type and more..
+ masked_exception[16] = 0;
+ masked_exception[20] = 0;
+ }
p += 2;
}
break;
int gotcycles = (endcycle - startcycle) * 2;
return gotcycles;
}
+
+static uae_u16 test_intena, test_intreq;
+
+static void set_interrupt(void)
+{
+ if (interrupt_count < 15) {
+ volatile uae_u16 *intena = (uae_u16 *)0xdff09a;
+ volatile uae_u16 *intreq = (uae_u16 *)0xdff09c;
+ uae_u16 mask = 1 << interrupt_count;
+ test_intena = mask | 0x8000 | 0x4000;
+ test_intreq = mask | 0x8000;
+ *intena = test_intena;
+ *intreq = test_intreq;
+ }
+}
+
+static void clear_interrupt(void)
+{
+ volatile uae_u16 *intena = (uae_u16 *)0xdff09a;
+ volatile uae_u16 *intreq = (uae_u16 *)0xdff09c;
+ *intena = 0x7fff;
+ *intreq = 0x7fff;
+}
+
#endif
static int check_cycles(int exc, short extratrace, short extrag2w1, struct registers *lregs)
// interrupt
expectedcycles += 2 + 4 + 4;
}
- exceptioncount[0][extrag2w1]++;
}
if (0 || abs(gotcycles - expectedcycles) > cycles_range) {
errflag |= 1 << 16;
}
if ((tregs->expsr & 0xff) != (tregs->sr & 0xff)) {
- sprintf(outbp, "Exception stacked CCR != CCR at start of exception handler!\n");
+ sprintf(outbp, "Exception stacked CCR (%04x) != CCR (%04x) at start of exception handler!\n", tregs->sr, tregs->expsr);
outbp += strlen(outbp);
errflag |= 1 << 16;
}
lregs->sr = val;
} else if (mode == CT_PC) {
uae_u32 val = lregs->pc;
- p = restore_rel(p, &val, 0);
+ p = restore_rel(p, &val, 1);
pc_changed = 0;
lregs->pc = val;
} else if (mode == CT_CYCLES) {
strcat(outbp, "Registers after:\n");
outbp += strlen(outbp);
out_regs(tregs, tregs, lregs, sregs, 0, branched2);
+#ifdef AMIGA
+ if (interrupttest) {
+ sprintf(outbp, "INTREQ: %04x INTENA: %04x\n", test_intreq, test_intena);
+ outbp += strlen(outbp);
+ }
+#endif
if (exc > 1) {
if (!experr) {
sprintf(outbp, "OK: exception %d ", exc);
}
}
-#ifdef AMIGA
-static const int interrupt_levels[] =
-{
- 0, 1, 1, 1, 2, 3, 3, 3, 4, 4, 4, 4, 5, 5, 6, 6, -1
-};
-
-static void set_interrupt(void)
-{
- if (interrupt_count < 15) {
- volatile uae_u16 *intena = (uae_u16*)0xdff09a;
- volatile uae_u16 *intreq = (uae_u16*)0xdff09c;
- uae_u16 mask = 1 << interrupt_count;
- *intena = mask | 0x8000 | 0x4000;
- *intreq = mask | 0x8000;
- }
- interrupt_count++;
- interrupt_count &= 15;
-}
-
-static void clear_interrupt(void)
-{
- volatile uae_u16 *intena = (uae_u16*)0xdff09a;
- volatile uae_u16 *intreq = (uae_u16*)0xdff09c;
- *intena = 0x7fff;
- *intreq = 0x7fff;
-}
-#endif
-
static uae_u32 xorshiftstate;
static uae_u32 xorshift32(void)
{
store_addr(cur_regs.branchtarget, branchtarget);
startpc = cur_regs.pc;
endpc = cur_regs.endpc;
- uae_u8 *opcode_memory_end = (uae_u8*)endpc;
+ opcode_memory_end = (uae_u8*)endpc;
int fpumode = fpu_model && (opcode_memory[0] & 0xf0) == 0xf0;
copyregs(&last_regs, &cur_regs, fpumode);
- uae_u32 originalopcodeend = 0x4afc4e71;
+ uae_u32 originalopcodeend = (ILLG_OPCODE << 16) | NOP_OPCODE;
short opcodeendsizeextra = 0;
uae_u32 opcodeend = originalopcodeend;
int extraccr = 0;
testcntsub = 0;
for (short ccr = 0; ccr < maxccr; ccr++, testcntsub++) {
- copyregs(&test_regs, &cur_regs, fpumode);
fpu_approx = 0;
opcodeend = (opcodeend >> 16) | (opcodeend << 16);
pl((uae_u8*)cur_regs.branchtarget, bv);
} else if (cur_regs.branchtarget_mode == 2) {
uae_u16 bv = gw((uae_u8 *)cur_regs.branchtarget);
- if (bv == 0x4e71)
- bv = 0x4afc;
+ if (bv == NOP_OPCODE)
+ bv = ILLG_OPCODE;
else
- bv = 0x4e71;
+ bv = NOP_OPCODE;
pw((uae_u8 *)cur_regs.branchtarget, bv);
}
}
- test_regs.ssp = super_stack_memory - 0x80;
- test_regs.msp = super_stack_memory;
+ cur_regs.ssp = super_stack_memory - 0x80;
+ cur_regs.msp = super_stack_memory;
+
+ copyregs(&test_regs, &cur_regs, fpumode);
+
test_regs.pc = startpc;
test_regs.fpiar = startpc;
test_regs.cyclest = 0xffffffff;
}
}
+#ifdef AMIGA
+ if (interrupttest) {
+ interrupt_count = *p++;
+ }
+#endif
+
while ((*p) == CT_OVERRIDE_REG) {
p++;
uae_u8 v = *p++;
int headoffset = 0;
v = read_u32(headerfile, &headoffset);
if (v != DATA_VERSION) {
- printf("Invalid test data file (header)\n");
+ printf("Invalid test data file (header %08x<>%08x)\n", v, DATA_VERSION);
exit(0);
}
break;
}
if (gl(test_data) != DATA_VERSION) {
- printf("Invalid test data file (header)\n");
+ printf("Invalid test data file (header, %08x<>%08x)\n", gl(test_data), DATA_VERSION);
exit(0);
}
if (gl(test_data + 4) != starttimeid) {
free(test_data);
exit(0);
}
+ uae_u32 flags = gl(test_data + 8);
+ instructionsize = flags & 3;
// last file?
int last = test_data[test_data_size - 1] == CT_END_FINISH;