From: Toni Wilen Date: Sat, 19 Oct 2019 09:53:57 +0000 (+0300) Subject: 68010 bus error/address error stack frame partial tester support. X-Git-Tag: 4300~79 X-Git-Url: https://git.unchartedbackwaters.co.uk/w/?a=commitdiff_plain;h=55cbc706b752bb09f404e703d0cee869b1503e93;p=francis%2Fwinuae.git 68010 bus error/address error stack frame partial tester support. --- diff --git a/cputest.cpp b/cputest.cpp index 96d46479..3878f636 100644 --- a/cputest.cpp +++ b/cputest.cpp @@ -113,6 +113,9 @@ static int exception_stack_frame_size; 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; @@ -135,6 +138,7 @@ static int high_memory_accessed; 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; @@ -279,11 +283,18 @@ static void check_bus_error(uaecptr addr, int write, int fc) } } +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]); @@ -296,6 +307,7 @@ uae_u16 get_word_test_prefetch(int o) 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); } @@ -327,6 +339,7 @@ void put_byte_test(uaecptr addr, uae_u32 v) ah->oldval = *p; ah->size = sz_byte; } + test_last_write = v; *p = v; } void put_word_test(uaecptr addr, uae_u32 v) @@ -352,6 +365,7 @@ 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) { @@ -382,9 +396,9 @@ 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; @@ -412,39 +426,45 @@ static void undo_memory(struct accesshistory *ahp, int *cntp) } } - 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) @@ -794,11 +814,16 @@ static void doexcstack(void) 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); @@ -857,45 +882,67 @@ uae_u32 REGPARAM2 op_illg(uae_u32 opcode) 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; @@ -2154,6 +2201,8 @@ static void execute_ins(uae_u16 opc, uaecptr endpc, uaecptr targetpc, struct ins 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) @@ -2352,6 +2401,22 @@ static uae_u8 *save_exception(uae_u8 *p, struct instr *dp) // 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; @@ -2744,8 +2809,12 @@ static void test_mnemo(const TCHAR *path, const TCHAR *mnemo, const TCHAR *ovrfi 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; } } diff --git a/cputest/asm.S b/cputest/asm.S index 85ee63e5..d1833eb6 100644 --- a/cputest/asm.S +++ b/cputest/asm.S @@ -147,6 +147,9 @@ _execute_test010: move.l S_AREG+7*4(a0),a1 move.l a1,USP movem.l (a0),d0-d7/a0-a6 + | clear data output buffer. + | we don't want random DOB contents in bus/address error frame + move.w #0xf00d,dummy rte | 68020+ test entrypoint @@ -392,3 +395,5 @@ datapointer: dc.l 0 superstack: dc.l 0 +dummy: + dc.l 0 diff --git a/cputest/main.c b/cputest/main.c index ab1de087..77dfb08a 100644 --- a/cputest/main.c +++ b/cputest/main.c @@ -1134,6 +1134,30 @@ static uae_u8 *validate_exception(struct registers *regs, uae_u8 *p, int excnum, pl(exc + 12, v); exclen = 16; break; + case 8: + exc[8] = *p++; + exc[9] = *p++; + v = opcode_memory_addr; + p = restore_rel_ordered(p, &v); + pl(exc + 10, v); + // data out + exc[16] = *p++; + exc[17] = *p++; + // data in + exc[20] = *p++; + exc[21] = *p++; + // inst + exc[24] = *p++; + exc[25] = *p++; + exc[14] = exc[15] = 0; + sp[14] = sp[15] = 0; + exc[18] = exc[19] = 0; + sp[18] = sp[19] = 0; + exc[22] = exc[23] = 0; + sp[22] = sp[23] = 0; + // ignore undocumented data + exclen = 26; + break; case 0x0a: case 0x0b: exclen = 8; diff --git a/gencpu.cpp b/gencpu.cpp index 14a51e12..bab5f139 100644 --- a/gencpu.cpp +++ b/gencpu.cpp @@ -515,7 +515,7 @@ static void check_bus_error_ins(int offset) } 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) @@ -1393,20 +1393,56 @@ static void move_68000_bus_error(int offset, int size, int *setapdi, int *fcmode 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 { @@ -1418,33 +1454,7 @@ static void check_bus_error(const char *name, int offset, int write, int fc) 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 @@ -1455,10 +1465,21 @@ static void check_bus_error(const char *name, int offset, int write, int fc) 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); @@ -2345,6 +2366,28 @@ static void genamode2x (amodes mode, const char *reg, wordsizes size, const char /* 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 @@ -2364,6 +2407,16 @@ static void genamode2x (amodes mode, const char *reg, wordsizes size, const char 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) { @@ -2371,7 +2424,9 @@ static void genamode2x (amodes mode, const char *reg, wordsizes size, const char } } 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) @@ -2395,10 +2450,18 @@ static void genamode2x (amodes mode, const char *reg, wordsizes size, const char 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"); @@ -2411,28 +2474,6 @@ static void genamode2x (amodes mode, const char *reg, wordsizes size, const char 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"; @@ -2467,14 +2508,14 @@ static void genamode2x (amodes mode, const char *reg, wordsizes size, const char { 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: @@ -2482,14 +2523,14 @@ static void genamode2x (amodes mode, const char *reg, wordsizes size, const char 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; @@ -2629,6 +2670,8 @@ static void genamodedual (instr *curi, amodes smode, const char *sreg, wordsizes 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; @@ -2738,7 +2781,7 @@ static void genastore_2 (const char *from, amodes mode, const char *reg, wordsiz 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)) @@ -2746,29 +2789,31 @@ static void genastore_2 (const char *from, amodes mode, const char *reg, wordsiz 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; @@ -2781,14 +2826,14 @@ static void genastore_2 (const char *from, amodes mode, const char *reg, wordsiz 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: @@ -2797,20 +2842,22 @@ static void genastore_2 (const char *from, amodes mode, const char *reg, wordsiz 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; @@ -3106,8 +3153,15 @@ static void movem_ex3(int write) 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; @@ -3170,9 +3224,9 @@ static void genmovemel_ce (uae_u16 opcode) 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"); @@ -3180,9 +3234,9 @@ static void genmovemel_ce (uae_u16 opcode) 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"); @@ -3191,7 +3245,7 @@ static void genmovemel_ce (uae_u16 opcode) } 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"); @@ -3199,7 +3253,7 @@ static void genmovemel_ce (uae_u16 opcode) 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"); @@ -3207,7 +3261,7 @@ static void genmovemel_ce (uae_u16 opcode) 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"); @@ -3292,18 +3346,18 @@ static void genmovemle_ce (uae_u16 opcode) 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); @@ -3313,19 +3367,19 @@ static void genmovemle_ce (uae_u16 opcode) 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); @@ -3337,15 +3391,15 @@ static void genmovemle_ce (uae_u16 opcode) 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"); @@ -3354,15 +3408,15 @@ static void genmovemle_ce (uae_u16 opcode) 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); @@ -4291,19 +4345,19 @@ static void gen_opcode (unsigned int opcode) 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 (); @@ -4313,23 +4367,23 @@ static void gen_opcode (unsigned int opcode) 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 (); @@ -4489,7 +4543,7 @@ static void gen_opcode (unsigned int opcode) // 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 (); @@ -4894,7 +4948,7 @@ static void gen_opcode (unsigned int opcode) 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"); } @@ -4911,9 +4965,9 @@ static void gen_opcode (unsigned int opcode) } 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)) { @@ -5022,7 +5076,7 @@ static void gen_opcode (unsigned int opcode) 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; @@ -5030,9 +5084,9 @@ static void gen_opcode (unsigned int opcode) 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); } @@ -5124,9 +5178,9 @@ static void gen_opcode (unsigned int opcode) 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"); diff --git a/include/newcpu.h b/include/newcpu.h index 1f69cf54..fac8105c 100644 --- a/include/newcpu.h +++ b/include/newcpu.h @@ -717,15 +717,16 @@ extern void fpux_restore (int*); extern bool fpu_get_constant(fpdata *fp, int cr); extern int fpp_cond(int condition); -extern void exception3_read(uae_u32 opcode, uaecptr addr, int fc); -extern void exception3_write(uae_u32 opcode, uaecptr addr, int fc); +extern void exception3_read(uae_u32 opcode, uaecptr addr, int size, int fc); +extern void exception3_write(uae_u32 opcode, uaecptr addr, int size, uae_u32 val, int fc); extern void exception3_notinstruction(uae_u32 opcode, uaecptr addr); extern void exception3i (uae_u32 opcode, uaecptr addr); extern void exception3b (uae_u32 opcode, uaecptr addr, bool w, bool i, uaecptr pc); extern void exception2 (uaecptr addr, bool read, int size, uae_u32 fc); -extern void exception2_setup(uaecptr addr, bool read, uae_u32 fc); -extern void exception2_read(uae_u32 opcode, uaecptr addr, int fc); -extern void exception2_write(uae_u32 opcode, uaecptr addr, int fc); +extern void exception2_setup(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(uae_u32 opcode, uaecptr addr); extern void m68k_reset (void); extern void cpureset (void); extern void cpu_halt (int id); diff --git a/jit/exception_handler.cpp b/jit/exception_handler.cpp index efc4e04a..9f4698b0 100644 --- a/jit/exception_handler.cpp +++ b/jit/exception_handler.cpp @@ -507,7 +507,7 @@ LONG WINAPI EvalException(LPEXCEPTION_POINTERS info) } if (currprefs.comp_catchfault) { // setup fake exception - exception2_setup(uae_p32(address) - uae_p32(NATMEM_OFFSET), info->ExceptionRecord->ExceptionInformation[0] == 0, regs.s ? 4 : 0); + exception2_setup(uae_p32(address) - uae_p32(NATMEM_OFFSET), info->ExceptionRecord->ExceptionInformation[0] == 0, 1, regs.s ? 4 : 0); return EXCEPTION_EXECUTE_HANDLER; } return EXCEPTION_CONTINUE_SEARCH; diff --git a/newcpu.cpp b/newcpu.cpp index e89fe279..5778764e 100644 --- a/newcpu.cpp +++ b/newcpu.cpp @@ -69,8 +69,14 @@ static uaecptr last_addr_for_exception_3; 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 */ @@ -2492,6 +2498,7 @@ static void Exception_ce000 (int nr) 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; @@ -2509,17 +2516,20 @@ static void Exception_ce000 (int nr) 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 @@ -2641,7 +2651,7 @@ static void Exception_mmu030 (int nr, uaecptr oldpc) 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) @@ -2707,7 +2717,7 @@ static void Exception_mmu (int nr, uaecptr oldpc) 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; } @@ -2851,7 +2861,7 @@ static void Exception_normal (int nr) 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); @@ -2906,11 +2916,15 @@ static void Exception_normal (int nr) 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; } @@ -2938,7 +2952,7 @@ static void Exception_normal (int nr) 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; @@ -6805,7 +6819,7 @@ uae_u8 *restore_mmu (uae_u8 *src) #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; @@ -6826,6 +6840,7 @@ static void exception3f (uae_u32 opcode, uaecptr addr, bool writeaccess, bool in 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(); @@ -6834,26 +6849,26 @@ static void exception3f (uae_u32 opcode, uaecptr addr, bool writeaccess, bool in 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; @@ -6861,6 +6876,8 @@ void exception2_setup(uaecptr addr, bool read, uae_u32 fc) 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; } @@ -6874,24 +6891,34 @@ void exception2(uaecptr addr, bool read, int size, uae_u32 fc) 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 */ diff --git a/newcpu_common.cpp b/newcpu_common.cpp index ecb4f97f..b801929f 100644 --- a/newcpu_common.cpp +++ b/newcpu_common.cpp @@ -818,7 +818,7 @@ void divbyzero_special (bool issigned, uae_s32 dst) /* DIVU overflow * * 68000: V=1, N=1, C=0, Z=0 - * 68010: V=1, N=1, C=0, Z=0 + * 68010: V=1, N=divisor<0x8000, C=0, Z=divided upper word == 0xffff and divisor == 0xffff * 68020: V=1, C=0, Z=0, N=X * 68040: V=1, C=0, NZ not modified. * 68060: V=1, C=0, NZ not modified. @@ -841,8 +841,9 @@ void setdivuflags(uae_u32 dividend, uae_u16 divisor) SET_NFLG(1); } else if (currprefs.cpu_model == 68010) { SET_VFLG(1); - SET_NFLG(1); - SET_ZFLG(0); + SET_NFLG(divisor < 0x8000); + // can anyone explain this? + SET_ZFLG((dividend >> 16) == 0xffff && divisor == 0xffff); SET_CFLG(0); } else { // 68000 @@ -1369,17 +1370,17 @@ void Exception_build_stack_frame(uae_u32 oldpc, uae_u32 currpc, uae_u32 ssw, int x_put_word(m68k_areg(regs, 7), 0); } m68k_areg(regs, 7) -= 2; - x_put_word(m68k_areg(regs, 7), 0); // version + x_put_word(m68k_areg(regs, 7), 0x0000); // version (probably bits 12 to 15 only because other bits change) m68k_areg(regs, 7) -= 2; - x_put_word(m68k_areg(regs, 7), regs.opcode); // instruction input buffer + x_put_word(m68k_areg(regs, 7), regs.irc); // instruction input buffer m68k_areg(regs, 7) -= 2; x_put_word(m68k_areg(regs, 7), 0); // unused m68k_areg(regs, 7) -= 2; - x_put_word(m68k_areg(regs, 7), 0); // data input buffer + x_put_word(m68k_areg(regs, 7), regs.mmu_effective_addr); // data input buffer m68k_areg(regs, 7) -= 2; x_put_word(m68k_areg(regs, 7), 0); // unused m68k_areg(regs, 7) -= 2; - x_put_word(m68k_areg(regs, 7), 0); // data output buffer + x_put_word(m68k_areg(regs, 7), regs.mmu_effective_addr >> 16); // data output buffer m68k_areg(regs, 7) -= 2; x_put_word(m68k_areg(regs, 7), 0); // unused m68k_areg(regs, 7) -= 4;