static uaecptr test_exception_addr;
static int test_exception_3_w;
static int test_exception_3_fc;
+static int test_exception_3_size;
+static int test_exception_3_value;
+static int test_exception_3_di;
static int test_exception_opcode;
static uae_u8 imm8_cnt;
static int test_memory_accessed;
static uae_u16 extra_or, extra_and;
static uae_u32 cur_registers[MAX_REGISTERS];
+static uae_u32 test_last_read, test_last_write;
struct uae_prefs currprefs;
}
}
+static uae_u8 get_ibyte_test(uaecptr addr)
+{
+ check_bus_error(addr, 0, regs.s ? 5 : 1);
+ uae_u8 *p = get_addr(addr, 1, 0);
+ return *p;
+}
+
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);
+ return (get_ibyte_test(addr + 0) << 8) | (get_ibyte_test(addr + 1) << 0);
} else {
uae_u8 *p = get_addr(addr, 2, 0);
return (p[0] << 8) | (p[1]);
if (cpu_lvl < 2)
o -= 2;
regs.irc = get_iword_test(m68k_getpci() + o + 2);
+ test_last_read = regs.irc;
return get_iword_test(m68k_getpci() + o);
}
ah->oldval = *p;
ah->size = sz_byte;
}
+ test_last_write = v;
*p = v;
}
void put_word_test(uaecptr addr, uae_u32 v)
p[0] = v >> 8;
p[1] = v & 0xff;
}
+ test_last_write = v;
}
void put_long_test(uaecptr addr, uae_u32 v)
{
p[2] = v >> 8;
p[3] = v >> 0;
}
+ test_last_write = v;
}
-
static void undo_memory(struct accesshistory *ahp, int *cntp)
{
out_of_test_space = 0;
}
}
-
uae_u32 get_byte_test(uaecptr addr)
{
check_bus_error(addr, 0, regs.s ? 5 : 1);
uae_u8 *p = get_addr(addr, 1, 0);
+ test_last_read = *p;
return *p;
}
uae_u32 get_word_test(uaecptr addr)
{
+ uae_u16 v;
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);
+ v = (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]);
+ v = (p[0] << 8) | (p[1]);
}
+ test_last_read = v;
+ return v;
}
uae_u32 get_long_test(uaecptr addr)
{
+ uae_u32 v;
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);
uae_u8 v3 = get_byte_test(addr + 3);
- return (v0 << 24) | (v1 << 8) | (v3 << 0);
+ v = (v0 << 24) | (v1 << 8) | (v3 << 0);
} else if (addr & 2) {
uae_u16 v0 = get_word_test(addr + 0);
uae_u16 v1 = get_word_test(addr + 2);
- return (v0 << 16) | (v1 << 0);
+ v = (v0 << 16) | (v1 << 0);
} else {
uae_u8 *p = get_addr(addr, 4, 0);
- return (p[0] << 24) | (p[1] << 16) | (p[2] << 8) | (p[3]);
+ v = (p[0] << 24) | (p[1] << 16) | (p[2] << 8) | (p[3]);
}
+ test_last_read = v;
+ return v;
}
uae_u32 get_byte_debug(uaecptr addr)
Exception_build_68000_address_error_stack_frame(mode, opcode, test_exception_addr, regs.pc);
}
} else if (cpu_lvl == 1) {
- if (test_exception == 3) {
+ if (test_exception == 2 || test_exception == 3) {
uae_u16 ssw = (sv ? 4 : 0) | test_exception_3_fc;
- ssw |= test_exception_3_w ? 0 : 0x100;
- ssw |= (test_exception_3_fc & 2) ? 0 : 0x2000;
+ ssw |= test_exception_3_di ? 0x0000 : 0x2000; // IF
+ 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
regs.mmu_fault_addr = test_exception_addr;
+ regs.mmu_effective_addr = test_exception_3_value;
+ regs.mmu_effective_addr = (test_last_read & 0xffff) | ((test_last_write & 0xffff) << 16);
Exception_build_stack_frame(regs.instruction_pc, regs.pc, ssw, 3, 0x08);
} else {
Exception_build_stack_frame_common(regs.instruction_pc, regs.pc, 0, test_exception);
return op_illg_1(opcode);
}
-void exception2_read(uae_u32 opcode, uaecptr addr, int fc)
+void exception2_fetch(uae_u32 opcode, uaecptr addr)
+{
+ test_exception = 2;
+ test_exception_3_w = 0;
+ test_exception_addr = addr;
+ test_exception_opcode = opcode;
+ test_exception_3_fc = 2;
+ test_exception_3_size = 1;
+ test_exception_3_di = 0;
+ doexcstack();
+}
+
+void exception2_read(uae_u32 opcode, uaecptr addr, int size, int fc)
{
test_exception = 2;
test_exception_3_w = 0;
test_exception_addr = addr;
test_exception_opcode = opcode;
test_exception_3_fc = fc;
+ test_exception_3_size = size;
+ test_exception_3_di = 1;
doexcstack();
}
-void exception2_write(uae_u32 opcode, uaecptr addr, int fc)
+void exception2_write(uae_u32 opcode, uaecptr addr, int size, uae_u32 val, int fc)
{
test_exception = 2;
test_exception_3_w = 1;
test_exception_addr = addr;
test_exception_opcode = opcode;
test_exception_3_fc = fc;
+ test_exception_3_size = size;
+ test_exception_3_value = val;
+ test_exception_3_di = 1;
doexcstack();
}
-
-void exception3_read(uae_u32 opcode, uae_u32 addr, int fc)
+void exception3_read(uae_u32 opcode, uae_u32 addr, int size, int fc)
{
test_exception = 3;
test_exception_3_w = 0;
test_exception_addr = addr;
test_exception_opcode = opcode;
test_exception_3_fc = fc;
+ test_exception_3_size = size;
+ test_exception_3_di = 1;
doexcstack();
}
-void exception3_write(uae_u32 opcode, uae_u32 addr, int fc)
+void exception3_write(uae_u32 opcode, uae_u32 addr, int size, uae_u32 val, int fc)
{
test_exception = 3;
test_exception_3_w = 1;
test_exception_addr = addr;
test_exception_opcode = opcode;
test_exception_3_fc = fc;
+ test_exception_3_size = size;
+ test_exception_3_value = val;
+ test_exception_3_di = 1;
doexcstack();
}
+
void REGPARAM2 Exception(int n)
{
test_exception = n;
testing_active = 1;
testing_active_opcode = opc;
cpu_bus_error = 0;
+ test_last_read = regs.irc;
+ test_last_write = 0xf00d;
int cnt = feature_loop_mode * 2;
if (multi_mode)
// FSLW or PC of faulted instruction
p = store_rel(p, 0, opcode_memory_start, gl(sf + 12), 1);
break;
+ case 8: // 68010 address/bus error
+ // SSW
+ *p++ = sf[8];
+ *p++ = sf[9];
+ // fault address
+ p = store_rel(p, 0, opcode_memory_start, gl(sf + 10), 1);
+ // data output
+ *p++ = sf[16];
+ *p++ = sf[17];
+ // data input
+ *p++ = sf[20];
+ *p++ = sf[21];
+ // instruction
+ *p++ = sf[24];
+ *p++ = sf[25];
+ break;
case 0x0a: // 68020/030 address error.
case 0x0b: // Don't save anything extra, too many undefined fields and bits..
exception_stack_frame_size = 0x08;
if (dp->dmode == Apdi) {
diff = -diff;
}
+ uae_u32 ta = target_address;
target_address -= diff * (1 << dp->size);
- target_ea[1] = target_address;
+ if (target_ea[0] == ta)
+ target_ea[0] = target_address;
+ if (target_ea[1] == ta)
+ target_ea[1] = target_address;
}
}
} else {
opcode = "opcode";
}
- sprintf(bus_error_text, "\t\texception2_read(%s, m68k_getpci() + %d, 2);\n", opcode, offset);
+ sprintf(bus_error_text, "\t\texception2_fetch(%s, m68k_getpci() + %d);\n", opcode, offset);
}
static void check_prefetch_bus_error(int offset)
static char const *bus_error_reg;
static int bus_error_reg_add;
-static void check_bus_error(const char *name, int offset, int write, int fc)
+static void do_bus_error_fixes(const char *name, int offset)
+{
+ switch (bus_error_reg_add)
+ {
+ case 1:
+ if (g_instr->mnemo == i_CMPM && write) {
+ ;
+ } else {
+ printf("\t\tm68k_areg(regs, %s) += areg_byteinc[%s] + %d;\n", bus_error_reg, bus_error_reg, offset);
+ }
+ break;
+ case 2:
+ printf("\t\tm68k_areg(regs, %s) += 2 + %d;\n", bus_error_reg, offset);
+ break;
+ case 3:
+ if (g_instr->mnemo == i_CMPM) {
+ // CMPM.L (an)+,(an)+: increased by 2
+ printf("\t\tm68k_areg(regs, %s) += 2 + %d;\n", bus_error_reg, offset);
+ }
+ break;
+ case 4:
+ if ((g_instr->mnemo == i_ADDX || g_instr->mnemo == i_SUBX) && g_instr->size == sz_long) {
+ // ADDX.L/SUBX.L -(an),-(an) source: stack frame decreased by 2, not 4.
+ offset = 2;
+ } else {
+ printf("\t\tm68k_areg (regs, %s) = %sa;\n", bus_error_reg, name);
+ }
+ break;
+ }
+
+}
+
+static void check_bus_error(const char *name, int offset, int write, int size, const char *writevar, int fc)
{
// check possible bus error (if 68000/010 and enabled)
if (!using_bus_error)
return;
if (!using_prefetch && !using_ce)
return;
+
+ uae_u32 extra = fc & 0xffff0000;
+ fc &= 0xffff;
+
printf("\tif(cpu_bus_error) {\n");
int setapdiback = 0;
if (fc == 2) {
- printf("\t\texception2_read(opcode, m68k_getpci() + %d, 2);\n", offset);
+ printf("\t\texception2_fetch(opcode, m68k_getpci() + %d);\n", offset);
} else {
move_68000_bus_error(offset, g_instr->size, &setapdiback, &fc);
}
- switch (bus_error_reg_add)
- {
- case 1:
- if (g_instr->mnemo == i_CMPM && write) {
- ;
- } else {
- printf("\t\tm68k_areg(regs, %s) += areg_byteinc[%s] + %d;\n", bus_error_reg, bus_error_reg, offset);
- }
- break;
- case 2:
- printf("\t\tm68k_areg(regs, %s) += 2 + %d;\n", bus_error_reg, offset);
- break;
- case 3:
- if (g_instr->mnemo == i_CMPM) {
- // CMPM.L (an)+,(an)+: increased by 2
- printf("\t\tm68k_areg(regs, %s) += 2 + %d;\n", bus_error_reg, offset);
- }
- break;
- case 4:
- if ((g_instr->mnemo == i_ADDX || g_instr->mnemo == i_SUBX) && g_instr->size == sz_long) {
- // ADDX.L/SUBX.L -(an),-(an) source: stack frame decreased by 2, not 4.
- offset = 2;
- } else {
- printf("\t\tm68k_areg (regs, %s) = %sa;\n", bus_error_reg, name);
- }
- break;
- }
+ do_bus_error_fixes(name, offset);
if (g_instr->mnemo == i_BTST && (g_instr->dmode == PC16 || g_instr->dmode == PC8r)) {
// BTST special case where destination is read access
fc = 2;
}
- printf("\t\texception2_%s(opcode, %sa + %d, %d);\n",
- write ? "write" : "read", name, offset,
- (!write && (g_instr->smode == PC16 || g_instr->smode == PC8r)) ||
- (write && (g_instr->dmode == PC16 || g_instr->dmode == PC8r)) ? 2 : fc);
+ // 68010 bus/address error HB bit
+ if (extra && cpu_level == 1)
+ printf("\t\topcode |= 0x%x;\n", extra);
+
+ if (write) {
+ printf("\t\texception2_write(opcode, %sa + %d, %d, %s, %d);\n",
+ name, offset, size, writevar,
+ (!write && (g_instr->smode == PC16 || g_instr->smode == PC8r)) ||
+ (write && (g_instr->dmode == PC16 || g_instr->dmode == PC8r)) ? 2 : fc);
+ } else {
+ printf("\t\texception2_read(opcode, %sa + %d, %d, %d);\n",
+ name, offset, size,
+ (!write && (g_instr->smode == PC16 || g_instr->smode == PC8r)) ||
+ (write && (g_instr->dmode == PC16 || g_instr->dmode == PC8r)) ? 2 : fc);
+ }
}
printf("\t\tgoto %s;\n", endlabelstr);
/* We get here for all non-reg non-immediate addressing modes to
* actually fetch the value. */
+ bus_error_reg_add = 0;
+ bus_error_reg = reg;
+ if (!movem) {
+ if (mode == Aipi) {
+ switch (size)
+ {
+ case sz_byte:
+ bus_error_reg_add = 1;
+ break;
+ case sz_word:
+ bus_error_reg_add = 2;
+ break;
+ case sz_long:
+ bus_error_reg_add = 3;
+ break;
+ default: term();
+ }
+ } else if (mode == Apdi) {
+ bus_error_reg_add = 4;
+ }
+ }
+
exception_pc_offset = 0;
if (getv == 2) {
// store
printf("\tif (%sa & 1) {\n", name);
+ if (cpu_level == 1) {
+ if (bus_error_reg_add == 4)
+ bus_error_reg_add = 0;
+ do_bus_error_fixes(name, 0);
+ // x,-(an): an is modified
+ if (mode == Apdi && g_instr->size == sz_word) {
+ printf("\t\tm68k_areg (regs, %s) = %sa;\n", reg, name);
+ }
+ }
+
if (g_instr->mnemo == i_ADDX || g_instr->mnemo == i_SUBX) {
// ADDX/SUBX special case
if (g_instr->size == sz_word) {
}
} else if (mode == Apdi) {
// 68000 decrements register first, then checks for address error
- setapdiback = 1;
+ // 68010 does not
+ if (cpu_level == 0)
+ setapdiback = 1;
}
if (exception_pc_offset)
if ((flags & (GF_REVERSE | GF_REVERSE2)) && size == sz_long && mode == Apdi)
printf("\t\t%sa += %d;\n", name, flags & GF_REVERSE2 ? -2 : 2);
- printf("\t\texception3_%s(opcode, %sa, %d);\n",
- exp3rw ? "write" : "read", name,
- // PC-relative: FC=2
- (getv == 1 && (g_instr->smode == PC16 || g_instr->smode == PC8r) ? 2 : 1) | fcmodeflags);
+ if (exp3rw) {
+ printf("\t\texception3_write(opcode, %sa, %d, %s, %d);\n",
+ name, size, "0",
+ // PC-relative: FC=2
+ (getv == 1 && (g_instr->smode == PC16 || g_instr->smode == PC8r) ? 2 : 1) | fcmodeflags);
+
+ } else {
+ printf("\t\texception3_read(opcode, %sa, %d, %d);\n",
+ name, size,
+ // PC-relative: FC=2
+ (getv == 1 && (g_instr->smode == PC16 || g_instr->smode == PC8r) ? 2 : 1) | fcmodeflags);
+ }
printf ("\t\tgoto %s;\n", endlabelstr);
printf ("\t}\n");
else if (flags & GF_IR2IRC)
irc2ir (true);
- bus_error_reg_add = 0;
- bus_error_reg = reg;
- if (!movem) {
- if (mode == Aipi) {
- switch (size)
- {
- case sz_byte:
- bus_error_reg_add = 1;
- break;
- case sz_word:
- bus_error_reg_add = 2;
- break;
- case sz_long:
- bus_error_reg_add = 3;
- break;
- default: term();
- }
- } else if (mode == Apdi) {
- bus_error_reg_add = 4;
- }
- }
-
if (getv == 1) {
const char *srcbx = !(flags & GF_FC) ? srcb : "sfc_nommu_get_byte";
const char *srcwx = !(flags & GF_FC) ? srcw : "sfc_nommu_get_word";
{
insn_n_cycles += 4; printf("\tuae_s8 %s = %s (%sa);\n", name, srcbx, name);
count_read++;
- check_bus_error(name, 0, 0, 1);
+ check_bus_error(name, 0, 0, 0, NULL, 1);
break;
}
case sz_word:
{
insn_n_cycles += 4; printf("\tuae_s16 %s = %s (%sa);\n", name, srcwx, name);
count_read++;
- check_bus_error(name, 0, 0, 1);
+ check_bus_error(name, 0, 0, 1, NULL, 1);
break;
}
case sz_long:
insn_n_cycles += 8;
if ((flags & GF_REVERSE) && mode == Apdi) {
printf("\tuae_s32 %s = %s(%sa + 2);\n", name, srcwx, name);
- check_bus_error(name, 0, 0, 1);
+ check_bus_error(name, 0, 0, 1, NULL, 1);
printf("\t%s |= %s(%sa) << 16; \n", name, srcw, name);
- check_bus_error(name, -2, 0, 1);
+ check_bus_error(name, -2, 0, 1, NULL, 1);
} else {
printf("\tuae_s32 %s = %s(%sa) << 16;\n", name, srcwx, name);
- check_bus_error(name, 0, 0, 1);
+ check_bus_error(name, 0, 0, 1, NULL, 1);
printf("\t%s |= %s(%sa + 2); \n", name, srcw, name);
- check_bus_error(name, 2, 0, 1);
+ check_bus_error(name, 2, 0, 1, NULL, 1);
}
count_read += 2;
break;
static void genastore_2 (const char *from, amodes mode, const char *reg, wordsizes size, const char *to, int store_dir, int flags)
{
+ char tmp[100];
+
if (candormw) {
if (strcmp (rmw_varname, to) != 0)
candormw = false;
check_ipl_again();
printf ("\tx_put_byte (%sa, %s);\n", to, from);
count_write++;
- check_bus_error(to, 0, 1, 1);
+ check_bus_error(to, 0, 1, 0, from, 1);
break;
case sz_word:
if (cpu_level < 2 && (mode == PC16 || mode == PC8r))
check_ipl_again();
printf ("\tx_put_word (%sa, %s);\n", to, from);
count_write++;
- check_bus_error(to, 0, 1, 1);
+ check_bus_error(to, 0, 1, 1, from, 1);
break;
case sz_long:
if (cpu_level < 2 && (mode == PC16 || mode == PC8r))
term ();
if (store_dir) {
printf ("\t%s (%sa + 2, %s);\n", dstwx, to, from);
- check_bus_error(to, 2, 1, 1);
+ check_bus_error(to, 2, 1, 1, from, 1);
check_ipl_again();
if (flags & GF_SECONDWORDSETFLAGS) {
genflags(flag_logical, g_instr->size, "src", "", "");
}
printf ("%s (%sa, %s >> 16);\n", dstwx, to, from);
- check_bus_error(to, 0, 1, 1);
+ sprintf(tmp, "%s >> 16", from);
+ check_bus_error(to, 0, 1, 1, tmp, 1);
} else {
printf ("\t%s (%sa, %s >> 16);\n", dstwx, to, from);
- check_bus_error(to, 0, 1, 1);
+ sprintf(tmp, "%s >> 16", from);
+ check_bus_error(to, 0, 1, 1, tmp, 1);
check_ipl_again();
if (flags & GF_SECONDWORDSETFLAGS) {
genflags(flag_logical, g_instr->size, "src", "", "");
}
printf ("\t%s (%sa + 2, %s);\n", dstwx, to, from);
- check_bus_error(to, 2, 1, 1);
+ check_bus_error(to, 2, 1, 1, "from", 1);
}
count_write += 2;
break;
insn_n_cycles += 4;
printf ("\t%s (%sa, %s);\n", dstbx, to, from);
count_write++;
- check_bus_error(to, 0, 1, 1);
+ check_bus_error(to, 0, 1, 0, from, 1);
break;
case sz_word:
insn_n_cycles += 4;
if (cpu_level < 2 && (mode == PC16 || mode == PC8r))
term ();
printf ("\t%s (%sa, %s);\n", dstwx, to, from);
- check_bus_error(to, 0, 1, 1);
+ check_bus_error(to, 0, 1, 1, from, 1);
count_write++;
break;
case sz_long:
term ();
if (store_dir) {
printf("\t%s(%sa + 2, %s);\n", dstwx, to, from);
- check_bus_error(to, 2, 1, 1);
+ check_bus_error(to, 2, 1, 1, from, 1);
if (flags & GF_SECONDWORDSETFLAGS) {
genflags(flag_logical, g_instr->size, "src", "", "");
}
printf("\t%s(%sa, %s >> 16); \n", dstwx, to, from);
- check_bus_error(to, 0, 1, 1);
+ sprintf(tmp, "%s >> 16", from);
+ check_bus_error(to, 0, 1, 1, tmp, 1);
} else {
printf("\t%s (%sa, %s >> 16);\n", dstwx, to, from);
- check_bus_error(to, 0, 1, 1);
+ sprintf(tmp, "%s >> 16", from);
+ check_bus_error(to, 0, 1, 1, tmp, 1);
if (flags & GF_SECONDWORDSETFLAGS) {
genflags(flag_logical, g_instr->size, "src", "", "");
}
printf("\t%s(%sa + 2, %s); \n", dstwx, to, from);
- check_bus_error(to, 2, 1, 1);
+ check_bus_error(to, 2, 1, 1, from, 1);
}
count_write += 2;
break;
printf("\t\topcode |= 0x01020000;\n");
}
}
- printf("\t\texception3_%s(opcode, srca, %d);\n",
- write ? "write" : "read", (g_instr->dmode == PC16 || g_instr->dmode == PC8r) ? 2 : 1);
+ if (write) {
+ printf("\t\texception3_write(opcode, srca, %d, srca, %d);\n",
+ g_instr->size,
+ (g_instr->dmode == PC16 || g_instr->dmode == PC8r) ? 2 : 1);
+ } else {
+ printf("\t\texception3_read(opcode, srca, %d, %d);\n",
+ g_instr->size,
+ (g_instr->dmode == PC16 || g_instr->dmode == PC8r) ? 2 : 1);
+ }
printf("\t\tgoto %s;\n", endlabelstr);
printf("\t}\n");
need_endlabel = 1;
if (table68k[opcode].size == sz_long) {
printf("\twhile (dmask) {\n");
printf("\t\tuae_u32 v = %s (srca) << 16;\n", srcw);
- check_bus_error("src", 0, 0, 1);
+ check_bus_error("src", 0, 0, 1, NULL, 1);
printf("\t\tv |= %s (srca + 2);\n", srcw);
- check_bus_error("src", 2, 0, 1);
+ check_bus_error("src", 2, 0, 1, NULL, 1);
printf("\t\tm68k_dreg (regs, movem_index1[dmask]) = v;\n");
printf("\t\tsrca += %d;\n", size);
printf("\t\tdmask = movem_next[dmask];\n");
printf("\t}\n");
printf("\twhile (amask) {\n");
printf("\t\tuae_u32 v = %s (srca) << 16;\n", srcw);
- check_bus_error("src", 0, 0, 1);
+ check_bus_error("src", 0, 0, 1, NULL, 1);
printf("\t\tv |= %s (srca + 2);\n", srcw);
- check_bus_error("src", 2, 0, 1);
+ check_bus_error("src", 2, 0, 1, NULL, 1);
printf("\t\tm68k_areg (regs, movem_index1[amask]) = v;\n");
printf("\t\tsrca += %d;\n", size);
printf("\t\tamask = movem_next[amask];\n");
} else {
printf("\twhile (dmask) {\n");
printf("\t\tuae_u32 v = (uae_s32)(uae_s16)%s (srca);\n", srcw);
- check_bus_error("src", 0, 0, 1);
+ check_bus_error("src", 0, 0, 1, NULL, 1);
printf("\t\tm68k_dreg (regs, movem_index1[dmask]) = v;\n");
printf("\t\tsrca += %d;\n", size);
printf("\t\tdmask = movem_next[dmask];\n");
printf("\t}\n");
printf("\twhile (amask) {\n");
printf("\t\tuae_u32 v = (uae_s32)(uae_s16)%s (srca);\n", srcw);
- check_bus_error("src", 0, 0, 1);
+ check_bus_error("src", 0, 0, 1, NULL, 1);
printf("\t\tm68k_areg (regs, movem_index1[amask]) = v;\n");
printf("\t\tsrca += %d;\n", size);
printf("\t\tamask = movem_next[amask];\n");
printf("\t}\n");
}
printf("\t%s (srca);\n", srcw); // and final extra word fetch that goes nowhere..
- check_bus_error("src", 0, 0, 1);
+ check_bus_error("src", 0, 0, 1, NULL, 1);
count_read++;
if (table68k[opcode].dmode == Aipi)
printf("\tm68k_areg (regs, dstreg) = srca;\n");
movem_ex3(1);
printf ("\twhile (amask) {\n");
printf ("\t\t%s (srca - 2, m68k_areg (regs, movem_index2[amask]));\n", dstw);
- check_bus_error("src", -2, 1, 1);
- printf ("\t\t%s (srca - 4, m68k_areg (regs, movem_index2[amask]) >> 16);\n", dstw);
- check_bus_error("src", -4, 1, 1);
+ check_bus_error("src", -2, 1, 1, "m68k_areg(regs, movem_index2[amask])", 1);
+ printf ("\t\t%s (srca - 4, m68k_areg(regs, movem_index2[amask]) >> 16);\n", dstw);
+ check_bus_error("src", -4, 1, 1, "m68k_areg(regs, movem_index2[amask]) >> 16", 1);
printf("\t\tsrca -= %d;\n", size);
printf ("\t\tamask = movem_next[amask];\n");
addcycles000_nonce("\t\t", 8);
printf ("\t}\n");
printf ("\twhile (dmask) {\n");
- printf ("\t\t%s (srca - 2, m68k_dreg (regs, movem_index2[dmask]));\n", dstw);
- check_bus_error("src", -2, 1, 1);
- printf ("\t\t%s (srca - 4, m68k_dreg (regs, movem_index2[dmask]) >> 16);\n", dstw);
- check_bus_error("src", -4, 1, 1);
+ printf ("\t\t%s (srca - 2, m68k_dreg(regs, movem_index2[dmask]));\n", dstw);
+ check_bus_error("src", -2, 1, 1, "m68k_dreg(regs, movem_index2[dmask])", 1);
+ printf ("\t\t%s (srca - 4, m68k_dreg(regs, movem_index2[dmask]) >> 16);\n", dstw);
+ check_bus_error("src", -4, 1, 1, "m68k_dreg(regs, movem_index2[dmask]) >> 16", 1);
printf("\t\tsrca -= %d;\n", size);
printf ("\t\tdmask = movem_next[dmask];\n");
addcycles000_nonce("\t\t", 8);
printf ("\tuae_u16 dmask = mask & 0xff, amask = (mask >> 8) & 0xff;\n");
movem_ex3(1);
printf ("\twhile (dmask) {\n");
- printf ("\t\t%s (srca, m68k_dreg (regs, movem_index1[dmask]) >> 16);\n", dstw);
- check_bus_error("src", 0, 1, 1);
- printf ("\t\t%s (srca + 2, m68k_dreg (regs, movem_index1[dmask]));\n", dstw);
- check_bus_error("src", 2, 1, 1);
+ printf ("\t\t%s (srca, m68k_dreg(regs, movem_index1[dmask]) >> 16);\n", dstw);
+ check_bus_error("src", 0, 1, 1, "m68k_dreg(regs, movem_index1[dmask]) >> 16", 1);
+ printf ("\t\t%s (srca + 2, m68k_dreg(regs, movem_index1[dmask]));\n", dstw);
+ check_bus_error("src", 2, 1, 1, "m68k_dreg(regs, movem_index1[dmask])", 1);
printf ("\t\tsrca += %d;\n", size);
printf ("\t\tdmask = movem_next[dmask];\n");
addcycles000_nonce("\t\t", 8);
printf ("\t}\n");
printf ("\twhile (amask) {\n");
- printf ("\t\t%s (srca, m68k_areg (regs, movem_index1[amask]) >> 16);\n", dstw);
- check_bus_error("src", 0, 1, 1);
- printf ("\t\t%s (srca + 2, m68k_areg (regs, movem_index1[amask]));\n", dstw);
- check_bus_error("src", 2, 1, 1);
+ printf ("\t\t%s (srca, m68k_areg(regs, movem_index1[amask]) >> 16);\n", dstw);
+ check_bus_error("src", 0, 1, 1, "m68k_areg(regs, movem_index1[amask]) >> 16", 1);
+ printf ("\t\t%s (srca + 2, m68k_areg(regs, movem_index1[amask]));\n", dstw);
+ check_bus_error("src", 2, 1, 1, "m68k_areg(regs, movem_index1[amask])", 1);
printf ("\t\tsrca += %d;\n", size);
printf ("\t\tamask = movem_next[amask];\n");
addcycles000_nonce("\t\t", 8);
movem_ex3(1);
printf ("\twhile (amask) {\n");
printf ("\t\tsrca -= %d;\n", size);
- printf ("\t\t%s (srca, m68k_areg (regs, movem_index2[amask]));\n", dstw);
- check_bus_error("src", 0, 1, 1);
+ printf ("\t\t%s (srca, m68k_areg(regs, movem_index2[amask]));\n", dstw);
+ check_bus_error("src", 0, 1, 1, "m68k_areg(regs, movem_index2[amask])", 1);
printf ("\tamask = movem_next[amask];\n");
addcycles000_nonce("\t\t", 4);
printf ("\t}\n");
printf ("\twhile (dmask) {\n");
printf ("\t\tsrca -= %d;\n", size);
- printf ("\t\t%s (srca, m68k_dreg (regs, movem_index2[dmask]));\n", dstw);
- check_bus_error("src", 0, 1, 1);
+ printf ("\t\t%s (srca, m68k_dreg(regs, movem_index2[dmask]));\n", dstw);
+ check_bus_error("src", 0, 1, 1, "m68k_dreg(regs, movem_index2[dmask])", 1);
printf ("\t\tdmask = movem_next[dmask];\n");
addcycles000_nonce("\t\t", 4);
printf ("\t}\n");
printf ("\tuae_u16 dmask = mask & 0xff, amask = (mask >> 8) & 0xff;\n");
movem_ex3(1);
printf ("\twhile (dmask) {\n");
- printf ("\t\t%s (srca, m68k_dreg (regs, movem_index1[dmask]));\n", dstw);
- check_bus_error("src", 0, 1, 1);
+ printf ("\t\t%s (srca, m68k_dreg(regs, movem_index1[dmask]));\n", dstw);
+ check_bus_error("src", 0, 1, 1, "m68k_dreg(regs, movem_index1[dmask])", 1);
printf ("\t\tsrca += %d;\n", size);
printf ("\t\tdmask = movem_next[dmask];\n");
addcycles000_nonce("\t\t", 4);
printf ("\t}\n");
printf ("\twhile (amask) {\n");
- printf ("\t\t%s (srca, m68k_areg (regs, movem_index1[amask]));\n", dstw);
- check_bus_error("src", 0, 1, 1);
+ printf ("\t\t%s (srca, m68k_areg(regs, movem_index1[amask]));\n", dstw);
+ check_bus_error("src", 0, 1, 1, "m68k_areg(regs, movem_index1[amask])", 1);
printf ("\t\tsrca += %d;\n", size);
printf ("\t\tamask = movem_next[amask];\n");
addcycles000_nonce("\t\t", 4);
printf ("\tuaecptr mempa = m68k_areg (regs, dstreg) + (uae_s32)(uae_s16)%s;\n", gen_nextiword (0));
if (curi->size == sz_word) {
printf("\t%s(mempa, src >> 8);\n", dstb);
- check_bus_error("memp", 0, 1, 1);
+ check_bus_error("memp", 0, 1, 0, "src >> 8", 1 | 0x10000);
printf("\t%s(mempa + 2, src); \n", dstb);
- check_bus_error("memp", 2, 1, 1);
+ check_bus_error("memp", 2, 1, 0, "src", 1);
count_write += 2;
} else {
printf("\t%s(mempa, src >> 24);\n", dstb);
- check_bus_error("memp", 0, 1, 1);
+ check_bus_error("memp", 0, 1, 0, "src >> 24", 1 | 0x10000);
printf("\t%s(mempa + 2, src >> 16);\n", dstb);
- check_bus_error("memp", 2, 1, 1);
+ check_bus_error("memp", 2, 1, 0, "src >> 16", 1);
printf("\t%s(mempa + 4, src >> 8);\n", dstb);
- check_bus_error("memp", 4, 1, 1);
+ check_bus_error("memp", 4, 1, 0, "src >> 8", 1 | 0x10000);
printf("\t%s(mempa + 6, src); \n", dstb);
- check_bus_error("memp", 6, 1, 1);
+ check_bus_error("memp", 6, 1, 0, "src", 1);
count_write += 4;
}
fill_prefetch_next ();
genamode (curi, curi->dmode, "dstreg", curi->size, "dst", 2, 0, 0);
if (curi->size == sz_word) {
printf ("\tuae_u16 val = (%s (mempa) & 0xff) << 8;\n", srcb);
- check_bus_error("memp", 0, 0, 1);
+ check_bus_error("memp", 0, 0, 0, NULL, 1 | 0x10000);
printf ("\tval |= (%s (mempa + 2) & 0xff);\n", srcb);
- check_bus_error("memp", 2, 0, 1);
+ check_bus_error("memp", 2, 0, 0, NULL, 1);
count_read += 2;
} else {
printf ("\tuae_u32 val = (%s (mempa) & 0xff) << 24;\n", srcb);
- check_bus_error("memp", 0, 0, 1);
+ check_bus_error("memp", 0, 0, 0, NULL, 1 | 0x10000);
printf ("\tval |= (%s (mempa + 2) & 0xff) << 16;\n", srcb);
- check_bus_error("memp", 2, 0, 1);
+ check_bus_error("memp", 2, 0, 0, NULL, 1);
// upper word gets updated after two bytes (makes only difference if bus error is possible)
printf("\tm68k_dreg(regs, dstreg) = (m68k_dreg(regs, dstreg) & 0x0000ffff) | (val & 0xffff0000);\n");
printf("\tval |= (%s (mempa + 4) & 0xff) << 8;\n", srcb);
- check_bus_error("memp", 4, 0, 1);
+ check_bus_error("memp", 4, 0, 0, NULL, 1 | 0x10000);
printf ("\tval |= (%s (mempa + 6) & 0xff);\n", srcb);
- check_bus_error("memp", 6, 0, 1);
+ check_bus_error("memp", 6, 0, 0, NULL, 1);
count_read += 4;
}
fill_prefetch_next ();
// read first and ignore result
if (cpu_level <= 1 && curi->size == sz_word) {
printf("\t%s (srca);\n", srcw);
- check_bus_error("src", 0, 0, 1);
+ check_bus_error("src", 0, 0, 1, NULL, 1);
count_write++;
}
fill_prefetch_next ();
printf ("\tuaecptr pc = %s;\n", getpc);
if (cpu_level <= 1 && using_exception_3) {
printf("\tif (m68k_areg(regs, 7) & 1) {\n");
- printf("\t\texception3_read(opcode, m68k_areg(regs, 7), 1);\n");
+ printf("\t\texception3_read(opcode, m68k_areg(regs, 7), 1, 1);\n");
printf("\t\tgoto %s;\n", endlabelstr);
printf("\t}\n");
}
} else if (using_ce || using_prefetch || (using_test && cpu_level <= 1)) {
printf("\tuaecptr newpc, dsta = m68k_areg(regs, 7);\n");
printf("\tnewpc = %s(dsta) << 16;\n", srcw);
- check_bus_error("dst", 0, 0, 1);
+ check_bus_error("dst", 0, 0, 1, NULL, 1);
printf("\tnewpc |= %s(dsta + 2);\n", srcw);
- check_bus_error("dst", 2, 0, 1);
+ check_bus_error("dst", 2, 0, 1, NULL, 1);
printf("\tm68k_areg(regs, 7) += 4;\n");
setpc("newpc");
} else if (using_prefetch_020 || (using_test && cpu_level >= 2)) {
printf("\tm68k_areg (regs, 7) -= 4;\n");
if (using_exception_3 && cpu_level <= 1) {
printf("\tif (m68k_areg(regs, 7) & 1) {\n");
- printf("\t\texception3_write(opcode, m68k_areg(regs, 7), 1);\n");
+ printf("\t\texception3_write(opcode, m68k_areg(regs, 7), 1, m68k_areg(regs, 7) >> 16, 1);\n");
printf("\t\tgoto %s;\n", endlabelstr);
printf("\t}\n");
need_endlabel = 1;
if (using_ce || using_prefetch) {
printf("\tuaecptr dsta = m68k_areg(regs, 7);\n");
printf("\t%s(dsta, nextpc >> 16);\n", dstw);
- check_bus_error("dst", 0, 1, 1);
+ check_bus_error("dst", 0, 1, 1, "nextpc >> 16", 1);
printf("\t%s(dsta + 2, nextpc);\n", dstw);
- check_bus_error("dst", 2, 1, 1);
+ check_bus_error("dst", 2, 1, 1, "nextpc", 1);
} else {
printf("\t%s(m68k_areg(regs, 7), nextpc);\n", dstl);
}
printf("\tm68k_areg(regs, 7) -= 4;\n");
printf("\tuaecptr dsta = m68k_areg(regs, 7);\n");
printf("\t%s(dsta, nextpc >> 16);\n", dstw);
- check_bus_error("dst", 0, 1, 1);
+ check_bus_error("dst", 0, 1, 1, "nextpc >> 16", 1);
printf("\t%s(dsta + 2, nextpc);\n", dstw);
- check_bus_error("dst", 2, 1, 1);
+ check_bus_error("dst", 2, 1, 1, "nextpc", 1);
incpc("s");
} else if (using_prefetch_020 || (using_test && cpu_level >= 2)) {
printf ("\tm68k_do_bsri (nextpc, s);\n");
static uaecptr last_fault_for_exception_3;
/* read (0) or write (1) access */
static bool last_writeaccess_for_exception_3;
+/* size */
+static bool last_size_for_exception_3;
/* FC */
static int last_fc_for_exception_3;
+/* Data (1) or instruction fetch (0) */
+static int last_di_for_exception_3;
+/* Value */
+static int last_value_for_exception_3;
/* not instruction */
static bool last_notinstruction_for_exception_3;
/* set when writing exception stack frame */
write_log(_T("Exception %d (%08x %x) at %x -> %x!\n"),
nr, last_op_for_exception_3, last_addr_for_exception_3, currpc, get_long_debug(4 * nr));
if (currprefs.cpu_model == 68000) {
+ // 68000 bus/address error
uae_u16 mode = (sv ? 4 : 0) | last_fc_for_exception_3;
mode |= last_writeaccess_for_exception_3 ? 0 : 16;
mode |= last_notinstruction_for_exception_3 ? 8 : 0;
x_do_cycles(2 * cpucycleunit);
goto kludge_me_do;
} else {
- // 68010 address error (partially implemented only)
+ // 68010 bus/address error (partially implemented only)
uae_u16 ssw = (sv ? 4 : 0) | last_fc_for_exception_3;
- ssw |= last_writeaccess_for_exception_3 ? 0 : 0x100;
- ssw |= (last_fc_for_exception_3 & 2) ? 0 : 0x2000;
+ ssw |= last_di_for_exception_3 ? 0x0000 : 0x2000; // IF
+ 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
+ ssw |= last_writeaccess_for_exception_3 ? 0 : 0x0100; // RW
m68k_areg(regs, 7) -= 50;
exception_in_exception = -1;
frame_id = 8;
x_put_word(m68k_areg(regs, 7) + 0, ssw); // ssw
x_put_long(m68k_areg(regs, 7) + 2, last_addr_for_exception_3); // fault addr
x_put_word(m68k_areg(regs, 7) + 6, 0); // unused
- x_put_word(m68k_areg(regs, 7) + 8, 0); // data output buffer
+ x_put_word(m68k_areg(regs, 7) + 8, last_value_for_exception_3); // data output buffer
x_put_word(m68k_areg(regs, 7) + 10, 0); // unused
x_put_word(m68k_areg(regs, 7) + 12, 0); // data input buffer
x_put_word(m68k_areg(regs, 7) + 14, 0); // unused
if (nr == 2 || nr == 3)
cpu_halt (CPU_HALT_DOUBLE_FAULT);
else
- exception3_read(regs.ir, newpc, 1);
+ exception3_read(regs.ir, newpc, 1, 1);
return;
}
if (interrupt)
if (nr == 2 || nr == 3)
cpu_halt (CPU_HALT_DOUBLE_FAULT);
else
- exception3_read(regs.ir, newpc, 1);
+ exception3_read(regs.ir, newpc, 2, 1);
return;
}
if (nr == 2 || nr == 3)
cpu_halt (CPU_HALT_DOUBLE_FAULT);
else
- exception3_read(regs.ir, newpc, 1);
+ exception3_read(regs.ir, newpc, 2, 1);
return;
}
m68k_setpc (newpc);
Exception_build_stack_frame(last_fault_for_exception_3, currpc, ssw, nr, 0x0b);
used_exception_build_stack_frame = true;
} else {
- // 68010 address error (partially implemented only)
+ // 68010 bus/address error (partially implemented only)
uae_u16 ssw = (sv ? 4 : 0) | last_fc_for_exception_3;
- ssw |= last_writeaccess_for_exception_3 ? 0 : 0x100;
- ssw |= (last_fc_for_exception_3 & 2) ? 0 : 0x2000;
+ ssw |= last_di_for_exception_3 ? 0x0000 : 0x2000; // IF
+ 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
+ ssw |= last_writeaccess_for_exception_3 ? 0x0000 : 0x0100; // RW
regs.mmu_fault_addr = last_addr_for_exception_3;
+ regs.mmu_effective_addr = last_value_for_exception_3;
Exception_build_stack_frame(oldpc, currpc, ssw, nr, 0x08);
used_exception_build_stack_frame = true;
}
add_approximate_exception_cycles(nr);
nextpc = m68k_getpc ();
if (nr == 2 || nr == 3) {
- // 68000 bus error/address error
+ // 68000 bus/address error
uae_u16 mode = (sv ? 4 : 0) | last_fc_for_exception_3;
mode |= last_writeaccess_for_exception_3 ? 0 : 16;
mode |= last_notinstruction_for_exception_3 ? 8 : 0;
#endif /* SAVESTATE */
-static void exception3f (uae_u32 opcode, uaecptr addr, bool writeaccess, bool instructionaccess, bool notinstruction, uaecptr pc, bool plus2, int fc)
+static void exception3f (uae_u32 opcode, uaecptr addr, bool writeaccess, bool instructionaccess, bool notinstruction, uaecptr pc, int size, bool plus2, int fc)
{
if (currprefs.cpu_model >= 68040)
addr &= ~1;
last_writeaccess_for_exception_3 = writeaccess;
last_fc_for_exception_3 = fc >= 0 ? fc : (instructionaccess ? 2 : 1);
last_notinstruction_for_exception_3 = notinstruction;
+ last_size_for_exception_3 = size;
Exception (3);
#if EXCEPTION3_DEBUGGER
activate_debugger();
void exception3_notinstruction(uae_u32 opcode, uaecptr addr)
{
- exception3f (opcode, addr, true, false, true, 0xffffffff, false, -1);
+ exception3f (opcode, addr, true, false, true, 0xffffffff, 1, false, -1);
}
-void exception3_read(uae_u32 opcode, uaecptr addr, int fc)
+void exception3_read(uae_u32 opcode, uaecptr addr, int size, int fc)
{
- exception3f (opcode, addr, false, 0, false, 0xffffffff, false, fc);
+ exception3f (opcode, addr, false, 0, false, 0xffffffff, size, false, fc);
}
-void exception3_write(uae_u32 opcode, uaecptr addr, int fc)
+void exception3_write(uae_u32 opcode, uaecptr addr, int size, uae_u32 val, int fc)
{
- exception3f (opcode, addr, true, 0, false, 0xffffffff, false, fc);
+ exception3f (opcode, addr, true, 0, false, 0xffffffff, size, false, fc);
}
void exception3i (uae_u32 opcode, uaecptr addr)
{
- exception3f (opcode, addr, 0, 1, false, 0xffffffff, true, -1);
+ exception3f (opcode, addr, 0, 1, false, 0xffffffff, 1, true, -1);
}
void exception3b (uae_u32 opcode, uaecptr addr, bool w, bool i, uaecptr pc)
{
- exception3f (opcode, addr, w, i, false, pc, true, -1);
+ exception3f (opcode, addr, w, i, false, pc, 1, true, -1);
}
-void exception2_setup(uaecptr addr, bool read, uae_u32 fc)
+void exception2_setup(uaecptr addr, bool read, int size, uae_u32 fc)
{
last_addr_for_exception_3 = m68k_getpc() + bus_error_offset;
last_fault_for_exception_3 = addr;
last_fc_for_exception_3 = fc;
last_op_for_exception_3 = regs.opcode;
last_notinstruction_for_exception_3 = exception_in_exception != 0;
+ last_size_for_exception_3 = size;
+ last_di_for_exception_3 = 1;
cpu_bus_error = 0;
}
mmu_bus_error (addr, 0, fc, read == false, size, 0, true);
}
} else {
- exception2_setup(addr, read, fc);
+ exception2_setup(addr, read, size == 1 ? 0 : (size == 2 ? 1 : 2), fc);
THROW(2);
- activate_debugger();
}
}
-void exception2_read(uae_u32 opcode, uaecptr addr, int fc)
+void exception2_read(uae_u32 opcode, uaecptr addr, int size, int fc)
{
- exception2_setup(addr, true, fc);
+ exception2_setup(addr, true, size, fc);
+ last_op_for_exception_3 = opcode;
+ Exception(2);
+}
+
+void exception2_write(uae_u32 opcode, uaecptr addr, int size, uae_u32 val, int fc)
+{
+ exception2_setup(addr, false, size, fc);
+ last_op_for_exception_3 = opcode;
Exception(2);
}
-void exception2_write(uae_u32 opcode, uaecptr addr, int fc)
+void exception2_fetch(uae_u32 opcode, uaecptr addr)
{
- exception2_setup(addr, false, fc);
+ exception2_setup(addr, true, 1, 2);
+ last_op_for_exception_3 = opcode;
+ last_di_for_exception_3 = 0;
Exception(2);
}
+
void cpureset (void)
{
/* RESET hasn't increased PC yet, 1 word offset */