ah->size = sz_byte;
ah->donotsave = false;
}
- regs.write_buffer = v;
+ regs.write_buffer &= 0xff00;
+ regs.write_buffer |= v & 0xff;
*p = v;
add_memory_cycles(1);
}
check_bus_error(addr, 0, regs.s ? 5 : 1);
uae_u8 *p = get_addr(addr, 1, 0);
read_buffer_prev = regs.read_buffer;
- regs.read_buffer = *p;
+ regs.read_buffer &= 0xff00;
+ regs.read_buffer |= *p;
add_memory_cycles(1);
return *p;
}
} else if (cpu_lvl == 1) {
if (test_exception == 2 || test_exception == 3) {
uae_u16 ssw = (sv ? 4 : 0) | test_exception_3_fc;
- ssw |= test_exception_3_di ? 0x0000 : 0x2000; // IF
+ ssw |= test_exception_3_di > 0 ? 0x0000 : (test_exception_3_di < 0 ? (0x2000 | 0x1000) : 0x2000);
ssw |= (!test_exception_3_w && test_exception_3_di) ? 0x1000 : 0x000; // DF
ssw |= (test_exception_opcode & 0x10000) ? 0x0400 : 0x0000; // HB
ssw |= test_exception_3_size == 0 ? 0x0200 : 0x0000; // BY
ssw |= test_exception_3_w ? 0x0000 : 0x0100; // RW
+ ssw |= (test_exception_opcode & 0x80000) ? 0x0800 : 0x0000; // RM
regs.mmu_fault_addr = test_exception_addr;
Exception_build_stack_frame(regs.instruction_pc, regs.pc, ssw, test_exception, 0x08);
SPCFLAG_DOTRACE = 0;
if (interrupt) {
regs.intmask = original_exception - 24;
regs.ir = original_exception;
- flags |= 0x10000 | 0x20000;
+ if (cpu_lvl == 0) {
+ flags |= 0x10000 | 0x20000;
+ } else {
+ flags |= 0x20000;
+ }
}
// set I/N if original exception was group 1 exception.
flags |= 0x20000;
- if (g1) {
+ if (g1 && cpu_lvl == 0) {
flags |= 0x10000;
}
return op_illg_1(opcode);
}
-void exception2_fetch(uae_u32 opcode, int offset)
+static void exception2_fetch_common(uae_u32 opcode, int offset)
{
test_exception = 2;
test_exception_3_w = 0;
if (opcode & 0x10000)
test_exception_3_fc |= 8;
}
+}
+
+void exception2_fetch(uae_u32 opcode, int offset)
+{
+ exception2_fetch_common(opcode, offset);
+ doexcstack();
+}
+void exception2_fetch_opcode(uae_u32 opcode, int offset)
+{
+ exception2_fetch_common(opcode, offset);
+ if (currprefs.cpu_model == 68010) {
+ test_exception_3_di = -1;
+ }
doexcstack();
}
test_exception_opcode = opcode;
test_exception_3_fc = fc;
test_exception_3_size = size;
- regs.write_buffer = val;
+ if (size == sz_byte) {
+ regs.write_buffer &= 0xff00;
+ regs.write_buffer |= val & 0xff;
+ } else {
+ regs.write_buffer = val;
+ }
test_exception_3_di = 1;
if (currprefs.cpu_model == 68000) {
{
bool vgot = false;
uae_u16 v;
- if (srcdst && dp->mnemo != i_DBcc)
- return -2;
+ if (dp->mnemo == i_MOVES) {
+ v = imm16_cnt << 11;
+ v |= rand16() & 0x07ff;
+ imm16_cnt++;
+ *isconstant = 32;
+ put_word_test(pc, v);
+ return 2;
+ }
+ if (srcdst) {
+ if (dp->mnemo != i_DBcc)
+ return -2;
+ }
if (dp->mnemo == i_DBcc || dp->mnemo == i_BSR || dp->mnemo == i_Bcc) {
uae_u32 pct = pc + 2 - 2;
if (target <= pct + 0x7ffe && target >= pct - 0x8000) {
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 == 0xd196
- //&& opw1 == 0x64fc
+ if (opc == 0x199c
+ && opw1 == 0x2808
//&& opw2 == 0x4afc
)
printf("");
regs.regs[15] = target_usp_address;
}
- if (opc == 0x4a53)
+ if (opc == 0x0e51)
printf("");
if (subtest_count >= 700)
printf("");
pc += o;
}
+ if (dp->mnemo == i_MOVES) {
+ // MOVES is stupid
+ if (!(get_word_test(pc - 2) & 0x0800)) {
+ uae_u32 vv = dstea;
+ dstea = srcea;
+ srcea = vv;
+ }
+ }
+
// requested target address but no EA? skip
if (target_address != 0xffffffff && isbranchinst(dp) != 2 && (feature_usp < 3 || !stackinst(dp))) {
if (srcea != target_address && dstea != target_address) {
out_of_test_space = false;
if ((dflags & 1) && target_ea[0] != 0xffffffff && srcaddr != 0xffffffff && srcaddr != target_ea[0]) {
- wprintf(_T(" Source address mismatch %08x <> %08x\n"), target_ea[0], srcaddr);
+ if (verbose) {
+ wprintf(_T(" Source address mismatch %08x <> %08x\n"), target_ea[0], srcaddr);
+ }
memcpy(opcode_memory, oldcodebytes, sizeof(oldcodebytes));
continue;
}
if ((dflags & 2) && target_ea[1] != 0xffffffff && dstaddr != target_ea[1]) {
- wprintf(_T(" Destination address mismatch %08x <> %08x\n"), target_ea[1], dstaddr);
+ if (verbose) {
+ wprintf(_T(" Destination address mismatch %08x <> %08x\n"), target_ea[1], dstaddr);
+ }
memcpy(opcode_memory, oldcodebytes, sizeof(oldcodebytes));
continue;
}
if ((dflags & 1) && target_ea[0] == 0xffffffff && (srcaddr & addressing_mask) >= safe_memory_start - 4 && (srcaddr & addressing_mask) < safe_memory_end + 4) {
// random generated EA must never be inside safe memory
memcpy(opcode_memory, oldcodebytes, sizeof(oldcodebytes));
+ if (verbose) {
+ wprintf(_T("\n"));
+ }
continue;
}
if ((dflags & 2) && target_ea[1] == 0xffffffff && (dstaddr & addressing_mask) >= safe_memory_start - 4 && (dstaddr & addressing_mask) < safe_memory_end + 4) {
// random generated EA must never be inside safe memory
memcpy(opcode_memory, oldcodebytes, sizeof(oldcodebytes));
+ if (verbose) {
+ wprintf(_T("\n"));
+ }
continue;
}
if (target_ea[1] != 0xffffffff && (target_ea[1] & 1) && target_ea[0] == 0xffffffff && !test_exception_3_w) {
skipped = 1;
}
+ if (safe_memory_mode) {
+ skipped = 1;
+ }
}
if (feature_usp == 2) {
if (i == 2) {
target_ea_opcode_max = cnt;
if (cnt > 0) {
- safe_memory_mode = 7;
+ safe_memory_mode = 1 | 4;
}
} else if (i) {
target_ea_dst_max = cnt;
p += size2;
size -= size2;
}
- if ((safe_memory_mode & 1)) {
- // if reading cause bus error: skip it
+ if ((safe_memory_mode & 2) && (safe_memory_mode & (1 | 4))) {
+ // if writing causes bus error and other bit(s) are also active: skip it
if (size > 0 && p >= safe_memory_start && p < safe_memory_end) {
int size2 = safe_memory_end - p;
if (size2 > size)
TCHAR *p;
pc += 2;
if (!(extra & 0x0800)) {
- pc = ShowEA(NULL, pc, opcode, dp->dreg, dp->dmode, dp->size, instrname, &seaddr2, &actualea_src, safemode);
+ pc = ShowEA(NULL, pc, opcode, dp->dreg, dp->dmode, dp->size, instrname, &deaddr2, &actualea_dst, safemode);
p = instrname + _tcslen(instrname);
_stprintf(p, _T(",%c%d"), (extra & 0x8000) ? 'A' : 'D', (extra >> 12) & 7);
} else {
sprintf(bus_error_text, "exception2_fetch(%s, %d);\n", opcode, offset);
}
+static void check_bus_error_ins_opcode(int offset)
+{
+ const char *opcode;
+ if (bus_error_specials) {
+ opcode = "0";
+ } else {
+ opcode = "opcode";
+ }
+ sprintf(bus_error_text, "exception2_fetch_opcode(%s, %d);\n", opcode, offset);
+}
+
static void check_prefetch_bus_error(int offset, int secondprefetchmode)
{
if (!using_bus_error || using_mmu)
bus_error_specials = 1;
}
}
- check_bus_error_ins(offset);
+ check_bus_error_ins_opcode(offset);
do_instruction_buserror();
}
//out("m68k_areg(regs, %s) = %sa;\n", bus_error_reg, name);
}
-
+ if (g_instr->mnemo == i_MOVES) {
+ out("regs.irc = extra;\n");
+ if (!write) {
+ out("regs.write_buffer = extra;\n");
+ }
+ if (g_instr->size == sz_long) {
+ // moves.l an,-(an)/(an)+ (same registers): write buffer contains modified value.
+ if (g_instr->dmode == Aipi || g_instr->dmode == Apdi) {
+ out("if (dstreg + 8 == ((extra >> 12) & 15)) {\n");
+ out("src += %d;\n", g_instr->dmode == Aipi ? 2 : -2);
+ out("}\n");
+ }
+ if (g_instr->dmode == Apdi) {
+ if (!write) {
+ out("m68k_areg(regs, dstreg) = srca;\n");
+ }
+ } else if (g_instr->dmode == Aipi) {
+ out("m68k_areg(regs, dstreg) += 4;\n");
+ }
+ }
+ } else if (g_instr->mnemo == i_TAS) {
+ if (!write) {
+ out("regs.read_buffer = regs.irc & 0xff00;\n");
+ out("regs.read_buffer |= 0x80;\n");
+ }
+ out("opcode |= 0x80000;\n");
+ } else if (g_instr->mnemo == i_CLR) {
+ if (g_instr->smode < Ad16) {
+ out("regflags.cznv = oldflags;\n");
+ }
+ // (an)+ and -(an) is done later
+ if (g_instr->smode == Aipi || g_instr->smode == Apdi) {
+ if (g_instr->size == sz_byte) {
+ out("m68k_areg(regs, srcreg) %c= areg_byteinc[srcreg];\n", g_instr->smode == Aipi ? '-' : '+');
+ } else {
+ out("m68k_areg(regs, srcreg) %c= %d;\n", g_instr->smode == Aipi ? '-' : '+', 1 << g_instr->size);
+ }
+ }
+ }
}
// write causing bus error and trace: set I/N
out("if (regs.t1) opcode |= 0x10000;\n"); // I/N set
}
- //if (cpu_level == 0 && write) {
- // out("opcode = regs.irc;\n");
- //}
-
if (write) {
out("exception2_write(opcode, %sa + %d, %d, %s, %d);\n",
name, offset, size, writevar,
}
static void genastore_fc (const char *from, amodes mode, const char *reg, wordsizes size, const char *to)
{
- genastore_2 (from, mode, reg, size, to, 1, GF_FC);
+ genastore_2(from, mode, reg, size, to, 0, GF_FC);
}
static void movem_mmu060 (const char *code, int size, bool put, bool aipi, bool apdi)
out("uae_u32 v = (%s(srca) << 16) | (m68k_dreg(regs, movem_index1[dmask]) & 0xffff);\n", srcw);
addcycles000_nonce(4);
check_bus_error("src", 0, 0, 1, NULL, 1);
- out("m68k_dreg(regs, movem_index1[dmask]) = v;\n");
+ if (cpu_level == 0) {
+ // 68010 does not do partial updates
+ out("m68k_dreg(regs, movem_index1[dmask]) = v;\n");
+ }
out("v &= 0xffff0000;\n");
out("v |= %s(srca + 2); \n", srcw);
addcycles000_nonce(4);
out("uae_u32 v = (%s(srca) << 16) | (m68k_areg(regs, movem_index1[amask]) & 0xffff);\n", srcw);
addcycles000_nonce(4);
check_bus_error("src", 0, 0, 1, NULL, 1);
- out("m68k_areg(regs, movem_index1[amask]) = v;\n");
+ if (cpu_level == 0) {
+ out("m68k_areg(regs, movem_index1[amask]) = v;\n");
+ }
out("v &= 0xffff0000;\n");
out("v |= %s(srca + 2);\n", srcw);
addcycles000_nonce(4);
genastore_rev("0", curi->smode, "srcreg", curi->size, "src");
}
} else if (cpu_level == 1) {
+ out("uae_u16 oldflags = regflags.cznv;\n");
genamode(curi, curi->smode, "srcreg", curi->size, "src", 3, 0, GF_CLR68010);
if (isreg(curi->smode) && curi->size == sz_long) {
addcycles000(2);
write_return_cycles(0);
out("}\n");
}
- fill_prefetch_next();
+ fill_prefetch_next_after(0, "CLEAR_CZNV();\nSET_ZFLG(1);\n");
genflags(flag_logical, curi->size, "0", "", "");
genastore_rev("0", curi->smode, "srcreg", curi->size, "src");
} else {
addcycles000(4);
out("if (extra & 0x800) {\n");
{
+ // reg -> memory
int old_m68k_pc_offset = m68k_pc_offset;
int old_m68k_pc_total = m68k_pc_total;
push_ins_cnt();
}
out("} else {\n");
{
+ // memory -> reg
genamode(curi, curi->dmode, "dstreg", curi->size, "src", 1, 0, GF_FC | (cpu_level == 1 ? GF_NOFETCH : 0));
out("if (extra & 0x8000) {\n");
switch (curi->size) {
} else {
genamode(curi, curi->smode, "srcreg", curi->size, "src", 2, 0, GF_LRMW | GF_NOFETCH);
out("uae_u8 src = %s(srca);\n", srcb);
+ check_bus_error("src", 0, 0, 0, "src", 1);
}
genflags(flag_logical, curi->size, "src", "", "");
if (!isreg(curi->smode)) {
extern void exception2_setup(uae_u32 opcode, uaecptr addr, bool read, int size, uae_u32 fc);
extern void exception2_read(uae_u32 opcode, uaecptr addr, int size, int fc);
extern void exception2_write(uae_u32 opcode, uaecptr addr, int size, uae_u32 val, int fc);
+extern void exception2_fetch_opcode(uae_u32 opcode, int offset);
extern void exception2_fetch(uae_u32 opcode, int offset);
extern void m68k_reset (void);
extern void cpureset (void);
uae_u16 in = regs.read_buffer;
uae_u16 out = regs.write_buffer;
uae_u16 ssw = (sv ? 4 : 0) | last_fc_for_exception_3;
- ssw |= last_di_for_exception_3 ? 0x0000 : 0x2000; // IF
+ ssw |= last_di_for_exception_3 > 0 ? 0x0000 : (last_di_for_exception_3 < 0 ? (0x2000 | 0x1000) : 0x2000);
ssw |= (!last_writeaccess_for_exception_3 && last_di_for_exception_3) ? 0x1000 : 0x000; // DF
ssw |= (last_op_for_exception_3 & 0x10000) ? 0x0400 : 0x0000; // HB
ssw |= last_size_for_exception_3 == 0 ? 0x0200 : 0x0000; // BY
} else {
// 68010 bus/address error (partially implemented only)
uae_u16 ssw = (sv ? 4 : 0) | last_fc_for_exception_3;
- ssw |= last_di_for_exception_3 ? 0x0000 : 0x2000; // IF
+ ssw |= last_di_for_exception_3 > 0 ? 0x0000 : (last_di_for_exception_3 < 0 ? (0x2000 | 0x1000) : 0x2000);
ssw |= (!last_writeaccess_for_exception_3 && last_di_for_exception_3) ? 0x1000 : 0x000; // DF
ssw |= (last_op_for_exception_3 & 0x10000) ? 0x0400 : 0x0000; // HB
ssw |= last_size_for_exception_3 == 0 ? 0x0200 : 0x0000; // BY
Exception(2);
}
-void exception2_fetch(uae_u32 opcode, int offset)
+static void exception2_fetch_common(uae_u32 opcode, int offset)
{
last_fault_for_exception_3 = m68k_getpc() + offset;
last_writeaccess_for_exception_3 = 0;
if (opcode & 0x10000)
last_fc_for_exception_3 |= 8;
}
+}
+
+void exception2_fetch_opcode(uae_u32 opcode, int offset)
+{
+ exception2_fetch_common(opcode, offset);
+ if (currprefs.cpu_model == 68010) {
+ last_di_for_exception_3 = -1;
+ }
+ Exception(2);
+}
+void exception2_fetch(uae_u32 opcode, int offset)
+{
+ exception2_fetch_common(opcode, offset);
Exception(2);
}