From: Toni Wilen Date: Sat, 8 Feb 2020 19:30:58 +0000 (+0200) Subject: 68000 prefetch bus error updates and fixes. All prefetch bus error tests pass. X-Git-Tag: 4400~137 X-Git-Url: https://git.unchartedbackwaters.co.uk/w/?a=commitdiff_plain;h=00656f979d8672211979f0edb9f5ac14e15087a5;p=francis%2Fwinuae.git 68000 prefetch bus error updates and fixes. All prefetch bus error tests pass. --- diff --git a/cpummu30.cpp b/cpummu30.cpp index 6d6eaf02..43ed4d42 100644 --- a/cpummu30.cpp +++ b/cpummu30.cpp @@ -3028,7 +3028,7 @@ void m68k_do_rte_mmu030 (uaecptr a7) regs.sr = sr; MakeFromSR_T0(); if (pc & 1) { - exception3i(0x4E73, pc); + exception3_read_prefetch(0x4E73, pc); return; } m68k_setpci(pc); @@ -3483,7 +3483,7 @@ void m68k_do_rte_mmu030c (uaecptr a7) regs.sr = sr; MakeFromSR_T0(); if (pc & 1) { - exception3i (0x4E73, pc); + exception3_read_prefetch(0x4E73, pc); return; } m68k_setpci (pc); diff --git a/cputest.cpp b/cputest.cpp index e324a661..6a583432 100644 --- a/cputest.cpp +++ b/cputest.cpp @@ -42,7 +42,6 @@ const int imm8_table[] = { 8, 1, 2, 3, 4, 5, 6, 7 }; int movem_index1[256]; int movem_index2[256]; int movem_next[256]; -int bus_error_offset; int hardware_bus_error, hardware_bus_error_fake; struct mmufixup mmufixup[2]; @@ -1074,7 +1073,7 @@ void exception2_fetch(uae_u32 opcode, int offset) test_exception_addr = m68k_getpci() + offset; test_exception_opcode = opcode; test_exception_3_fc = 2; - test_exception_3_size = 1; + test_exception_3_size = sz_word; test_exception_3_di = 0; if (currprefs.cpu_model == 68000) { @@ -1184,6 +1183,21 @@ void exception3_write(uae_u32 opcode, uae_u32 addr, int size, uae_u32 val, int f doexcstack(); } +void exception3_read_prefetch(uae_u32 opcode, uae_u32 addr) +{ + add_memory_cycles(1); + + test_exception = 3; + test_exception_3_w = 0; + test_exception_addr = addr; + test_exception_opcode = opcode; + test_exception_3_fc = 2; + test_exception_3_size = sz_word; + test_exception_3_di = 0; + + doexcstack(); +} + void exception3_read_opcode(uae_u32 opcode, uae_u32 addr, int size, int fc) { add_memory_cycles(1); @@ -4103,6 +4117,15 @@ static void test_mnemo(const TCHAR *path, const TCHAR *mnemo, const TCHAR *ovrfi if (feature_exception_vectors) { skipped = 1; } + } else { + // wanted read address error but got write + if (target_ea[0] != 0xffffffff && (target_ea[0] & 1) && target_ea[1] == 0xffffffff && test_exception_3_w) { + skipped = 1; + } + // wanted write address error but got read + if (target_ea[1] != 0xffffffff && (target_ea[1] & 1) && target_ea[0] == 0xffffffff && !test_exception_3_w) { + skipped = 1; + } } if (feature_usp == 2) { diff --git a/cputest/cputestgen.ini b/cputest/cputestgen.ini index 29d29d91..b7137416 100644 --- a/cputest/cputestgen.ini +++ b/cputest/cputestgen.ini @@ -75,7 +75,7 @@ feature_target_dst_ea= ; addresses where test instruction is located, use for bus error prefetch testing ; automatically enables RP bus error mode, data read bus errors are skipped. -;feature_target_opcode_offset=90,92,94,96,98,100,102,104 +feature_target_opcode_offset= ; Memory region that generates bus error (both read and write). ; Must be inside any test memory region. @@ -99,7 +99,8 @@ feature_usp=0 ; exception vector bus error/address error test ; 0: normal ; non-zero: replace exception vectors with this value (except vectors 2 and 3) -;feature_exception_vectors=0x0007321 +; skips all tests that didn't generate address error +feature_exception_vectors= ; CCR/FPU status flags mode ; 0 = all combinations (32 CCR loops, 256 FPU loops) @@ -184,7 +185,7 @@ feature_target_src_ea=0x87fff1,0x7111 feature_target_dst_ea= mode=all -; destination EA address error +; destination EA address error (MOVE, MOVEM) [test=AE_DST] enabled=0 feature_target_src_ea= @@ -195,7 +196,7 @@ mode=all [test=ODD_STK] enabled=0 feature_usp=2 -mode=branchs +mode=rts,rtd,rtr,jsr,bsr,link,unlk,pea ; exception vector address error [test=ODD_EXC] @@ -205,7 +206,7 @@ mode=chk,trap,trapv,divu,divs,orsr ; interrupt exception with odd interrupt vectors [test=ODD_IRQ] -enabled=1 +enabled=0 mode=nop,ext,swap feature_interrupts=1 feature_exception_vectors=0x000123 @@ -216,8 +217,9 @@ enabled=0 feature_safe_memory_start=0x880000 feature_safe_memory_size=0x80000 feature_safe_memory_mode=P -feature_target_opcode_offset=90,92,94,96,98,100,102,104 -opcode_memory_start=0x87ff98 +feature_target_opcode_offset=2,4,6,8,10,12,14,16 +opcode_memory_start=0x87ffee +test_memory_size=0xa0000 mode=all ; source EA read bus error (requires extra hardware) diff --git a/cputest/main.c b/cputest/main.c index 7317501e..b36af176 100644 --- a/cputest/main.c +++ b/cputest/main.c @@ -139,7 +139,7 @@ static short gotcycles; static short interrupttest; static short randomizetest; static uae_u32 cyclecounter_addr; -static short uae; +static short uaemode; #ifdef AMIGA static short interrupt_count; static uae_u16 main_intena; @@ -527,11 +527,11 @@ extern void uae_command(char*); static int set_berr(int mask, int ask) { #ifdef AMIGA - if (uae) { + if (uaemode) { if (!mask) { sprintf(tmpbuffer, "dbg \"w 0\""); } else { - sprintf(tmpbuffer, "dbg \"w 0 %08x %08x BE%s%s%s\"", (uae_u32)safe_memory_start, safe_memory_end - safe_memory_start, (mask & 1) ? "R" : "", (mask & 2) ? "W" : "", (mask & 4) ? "P" : ""); + sprintf(tmpbuffer, "dbg \"w 0 %08x %08x B%s%s%s\"", (uae_u32)safe_memory_start, safe_memory_end - safe_memory_start, (mask & 1) ? "R" : "", (mask & 2) ? "W" : "", (mask & 4) ? "P" : ""); } uae_command(tmpbuffer); return 0; @@ -1715,7 +1715,7 @@ static int getexceptioncycles(int exc) { case 2: case 3: - return 60; + return 56; case 4: case 5: case 6: @@ -2738,7 +2738,7 @@ static int test_mnemo(const char *opcode) interrupttest = (lvl_mask >> 26) & 1; randomizetest = (lvl_mask >> 28) & 1; sr_undefined_mask = lvl_mask & 0xffff; - safe_memory_mode = (lvl_mask >> 23) & 3; + safe_memory_mode = (lvl_mask >> 23) & 7; fpu_model = read_u32(headerfile, &headoffset); test_low_memory_start = read_u32(headerfile, &headoffset); test_low_memory_end = read_u32(headerfile, &headoffset); @@ -2987,6 +2987,9 @@ int main(int argc, char *argv[]) printf("-exit n = exit after n tests.\n"); printf("-cycles [range adjust] = check cycle counts.\n"); printf("-cyclecnt
. Use custom hardware cycle counter.\n"); +#ifdef AMIGA + printf("-uae = running in UAE, automatic bus error enable/disable.\n"); +#endif return 0; } @@ -3068,7 +3071,7 @@ int main(int argc, char *argv[]) cycles = 1; } } else if (!_stricmp(s, "-uae")) { - uae = 1; + uaemode = 1; } } diff --git a/custom.cpp b/custom.cpp index cad7516e..00431de9 100644 --- a/custom.cpp +++ b/custom.cpp @@ -11845,8 +11845,9 @@ void do_cycles_ce020 (unsigned long cycles) bool is_cycle_ce(uaecptr addr) { + addr &= currprefs.address_space_24 ? 0x00ffffff : 0xffffffff; addrbank *ab = get_mem_bank_real(addr); - if ((ab->flags & ABFLAG_CHIPRAM) || ab == &custom_bank) { + if (!ab || (ab->flags & ABFLAG_CHIPRAM) || ab == &custom_bank) { int hpos = current_hpos(); return (cycle_line[hpos] & CYCLE_MASK) != 0; } diff --git a/debug.cpp b/debug.cpp index 7c61607d..4f60cbd9 100644 --- a/debug.cpp +++ b/debug.cpp @@ -50,6 +50,7 @@ #include "ini.h" #include "readcpu.h" #include "cputbl.h" +#include "keybuf.h" #define TRACE_SKIP_INS 1 #define TRACE_MATCH_PC 2 @@ -114,6 +115,7 @@ void deactivate_debugger (void) processname = NULL; debugmem_enable(); debug_pc = 0xffffffff; + keybuf_ignore_next_release(); } void activate_debugger (void) @@ -3598,12 +3600,11 @@ void memwatch_dump2 (TCHAR *buf, int bufsize, int num) buf = buf_out(buf, &bufsize, _T(" L")); if (mwn->nobreak) buf = buf_out(buf, &bufsize, _T(" N")); - if ((mwn->bus_error & (1 | 4)) && (mwn->bus_error & 2)) { - buf = buf_out(buf, &bufsize, _T(" BER")); - } else if (mwn->bus_error & (1 | 4)) { - buf = buf_out(buf, &bufsize, _T(" BERR")); - } else if (mwn->bus_error & 2) { - buf = buf_out(buf, &bufsize, _T(" BERW")); + if (mwn->bus_error) { + buf = buf_out(buf, &bufsize, _T(" BER%s%s%s"), + (mwn->bus_error & 1) ? _T("R") : _T(""), + (mwn->bus_error & 2) ? _T("W") : _T(""), + (mwn->bus_error & 4) ? _T("P") : _T("")); } for (int j = 0; memwatch_access_masks[j].mask; j++) { uae_u32 mask = memwatch_access_masks[j].mask; @@ -3738,7 +3739,7 @@ static void memwatch (TCHAR **c) if (more_params(c)) { for (;;) { TCHAR ncc = _totupper(peek_next_char(c)); - TCHAR nc = _totupper (next_char (c)); + TCHAR nc = _totupper(next_char(c)); if (mwn->rwi == 7) mwn->rwi = 0; if (nc == 'F') @@ -3750,21 +3751,30 @@ static void memwatch (TCHAR **c) if (nc == 'R') mwn->rwi |= 1; if (nc == 'B') { - mwn->bus_error = 7; - if (ncc == 'R') { - mwn->bus_error = 1 | 4; - mwn->rwi |= 1 | 4; - next_char(c); - } - if (ncc == 'W') { - mwn->bus_error = 2; - mwn->rwi |= 2; - next_char(c); + mwn->bus_error = 0; + for (;;) { + ncc = next_char2(c); + if (ncc == ' ' || ncc == 0) + break; + if (ncc == 'R') { + mwn->bus_error |= 1; + mwn->rwi |= 1; + } else if (ncc == 'W') { + mwn->bus_error |= 2; + mwn->rwi |= 2; + } else if (ncc == 'P') { + mwn->bus_error |= 4; + mwn->rwi |= 4; + } else { + break; + } } if (!mwn->rwi) mwn->rwi = 7; + if (!mwn->bus_error) + mwn->bus_error = 7; } - if (ncc == ' ') + if (ncc == ' ' || ncc == 0) break; if (nc == 'P' && ncc == 'C') { next_char(c); diff --git a/gencpu.cpp b/gencpu.cpp index 600694b5..3bafb2e7 100644 --- a/gencpu.cpp +++ b/gencpu.cpp @@ -78,6 +78,7 @@ static int optimized_flags; #define GF_SECONDEA 0x08000 #define GF_NOFETCH 0x10000 // 68010 #define GF_CLR68010 0x20000 // 68010 +#define GF_NOEXC 0x40000 typedef enum { @@ -761,6 +762,11 @@ static void gen_nextilong2 (const char *type, const char *name, int flags, int m out("%s = %s(%d) << 16;\n", name, prefetch_word, r + 2); count_read++; out("%s |= regs.irc;\n", name); + check_bus_error_ins(r + 2); + do_instruction_buserror(); + strcpy(bus_error_code, bus_error_code2); + bus_error_code2[0] = 0; + bus_error_text[0] = 0; } else { out("%s = %s(%d) << 16;\n", name, prefetch_word, r + 2); count_read++; @@ -778,8 +784,12 @@ static void gen_nextilong2 (const char *type, const char *name, int flags, int m out("%s = %s(%d) << 16;\n", name, prefetch_word, r + 2); count_read++; insn_n_cycles += 4; - check_bus_error_ins(r + 2); out("%s |= regs.irc;\n", name); + check_bus_error_ins(r + 2); + do_instruction_buserror(); + strcpy(bus_error_code, bus_error_code2); + bus_error_code2[0] = 0; + bus_error_text[0] = 0; } else { out("%s = %s(%d) << 16;\n", name, prefetch_word, r + 2); count_read++; @@ -969,6 +979,7 @@ static void fill_prefetch_bcc(void) if (cpu_level == 0) { out("if(regs.t1) opcode |= 0x10000;\n"); } + next_level_000(); } out("%s(%d);\n", prefetch_word, m68k_pc_offset + 2); @@ -1039,6 +1050,7 @@ static void fill_prefetch_full_ntx(int beopcode) if (beopcode == 3) out("if(t1) opcode |= 0x10000;\n"); } + next_level_000(); fill_prefetch_1(2); } else { fill_prefetch_1_empty(2); @@ -1083,6 +1095,7 @@ static void fill_prefetch_full(int beopcode) if (beopcode > 1 && cpu_level == 0) { out("if(regs.t1) opcode |= 0x10000;\n"); } + next_level_000(); fill_prefetch_1(2); } else { fill_prefetch_1_empty(2); @@ -1100,7 +1113,7 @@ static void fill_prefetch_full(int beopcode) } } -static void fill_prefetch_full_000_special(void) +static void fill_prefetch_full_000_special(const char *format, ...) { if (!using_prefetch) return; @@ -1119,6 +1132,15 @@ static void fill_prefetch_full_000_special(void) out("if(regs.t1) opcode |= 0x10000;\n"); } } + next_level_000(); + } + if (format) { + char outbuf[256]; + va_list parms; + va_start(parms, format); + _vsnprintf(outbuf, sizeof(outbuf) - 1, format, parms); + va_end(parms); + out(outbuf); } out("%s(%d);\n", prefetch_word, 2); count_read++; @@ -1285,6 +1307,7 @@ static void fill_prefetch_next_noopcodecopy(const char *format, ...) if (cpu_level == 0) { out("opcode |= 0x20000;\n"); } + next_level_000(); } fill_prefetch_1(m68k_pc_offset + 2); if (using_bus_error) { @@ -1317,6 +1340,7 @@ static void fill_prefetch_next_t(void) if (cpu_level == 0) { strcat(bus_error_code, "if (regs.t1) opcode |= 0x10000;\n"); } + next_level_000(); } fill_prefetch_1(m68k_pc_offset + 2); loopmode_end(); @@ -1346,7 +1370,6 @@ static void fill_prefetch_next_extra(const char *cond, const char *format, ...) } } - static void fill_prefetch_next_after(int copy, const char *format, ...) { if (using_prefetch) { @@ -1355,6 +1378,7 @@ static void fill_prefetch_next_after(int copy, const char *format, ...) if (cpu_level == 0) { out("opcode |= 0x20000;\n"); } + next_level_000(); bus_error_code[0] = 0; if (format) { va_list parms; @@ -1375,7 +1399,6 @@ static void fill_prefetch_next_after(int copy, const char *format, ...) } } - static void fill_prefetch_next_skipopcode(void) { if (using_prefetch) { @@ -2544,6 +2567,11 @@ static void move_68000_address_error(int size, int *setapdi, int *fcmodeflags) int smode = g_instr->smode; int dmode = g_instr->dmode; + if (dmode == Apdi) { + addcycles000_onlyce(2); + addcycles000_nonce(2); + } + if (size == sz_word) { // Word MOVE is relatively simply int set_ccr = 0; @@ -3144,7 +3172,7 @@ static void genamode2x (amodes mode, const char *reg, wordsizes size, const char } // check possible address error (if 68000/010 and enabled) - if ((using_prefetch || using_ce) && using_exception_3 && getv != 0 && getv != 3 && size != sz_byte && !movem) { + if ((using_prefetch || using_ce) && using_exception_3 && getv != 0 && getv != 3 && size != sz_byte && !movem && !(flags & GF_NOEXC)) { int setapdiback = 0; int fcmodeflags = 0; int exp3rw = getv == 2; @@ -3613,6 +3641,7 @@ static void genastore_2 (const char *from, amodes mode, const char *reg, wordsiz if (flags & GF_SECONDWORDSETFLAGS) { genflags(flag_logical, g_instr->size, "src", "", ""); } + // ADDX.L/SUBX.L -(an),-(an) only if (store_dir > 1) { fill_prefetch_next_after(0, NULL); } @@ -3664,6 +3693,7 @@ static void genastore_2 (const char *from, amodes mode, const char *reg, wordsiz if (flags & GF_SECONDWORDSETFLAGS) { genflags(flag_logical, g_instr->size, "src", "", ""); } + // ADDX.L/SUBX.L -(an),-(an) only if (store_dir > 1) { fill_prefetch_next_after(0, NULL); } @@ -5018,6 +5048,8 @@ static void gen_opcode (unsigned int opcode) if (curi->size != sz_long) { genflags(flag_subx, curi->size, "newv", "src", "dst"); genflags(flag_zn, curi->size, "newv", "", ""); + } else { + out("int oldz = GET_ZFLG();\n"); } if (isreg(curi->smode) && curi->size != sz_long) { genastore("newv", curi->dmode, "dstreg", curi->size, "dst"); @@ -5036,6 +5068,7 @@ static void gen_opcode (unsigned int opcode) "SET_VFLG((bflgs ^ bflgo) & (bflgo ^ bflgn));\n" "SET_CFLG(bflgs ^ ((bflgs ^ bflgn) & (bflgo ^ bflgn)));\n" "SET_XFLG(GET_CFLG());\n" + "SET_ZFLG(oldz);\n" "if (newv & 0xffff) SET_ZFLG(0);\n" "SET_NFLG(newv & 0x8000); \n" "dreg_68000_long_replace_low(dstreg, newv);\n"); @@ -5208,6 +5241,8 @@ static void gen_opcode (unsigned int opcode) if (curi->size != sz_long) { genflags(flag_addx, curi->size, "newv", "src", "dst"); genflags(flag_zn, curi->size, "newv", "", ""); + } else { + out("int oldz = GET_ZFLG();\n"); } if (isreg(curi->smode) && curi->size != sz_long) { genastore("newv", curi->dmode, "dstreg", curi->size, "dst"); @@ -5226,6 +5261,7 @@ static void gen_opcode (unsigned int opcode) "SET_VFLG((bflgs ^ bflgn) & (bflgo ^ bflgn));\n" "SET_CFLG(bflgs ^ ((bflgs ^ bflgo) & (bflgo ^ bflgn)));\n" "SET_XFLG(GET_CFLG());\n" + "SET_ZFLG(oldz);\n" "if (newv & 0xffff) SET_ZFLG(0);\n" "SET_NFLG(newv & 0x8000); \n" "dreg_68000_long_replace_low(dstreg, newv);\n"); @@ -5299,17 +5335,7 @@ static void gen_opcode (unsigned int opcode) if (curi->smode == Dreg) { if (curi->size == sz_long) { // prefetch bus error and long register: only low word is updated - // N flag from high word. Z both. - fill_prefetch_next_after(1, - "dreg_68000_long_replace_low(srcreg, dst);\n" - "int bflgs = ((uae_s16)(src)) < 0;\n" - "int bflgo = ((uae_s16)(0)) < 0;\n" - "int bflgn = ((uae_s16)(dst)) < 0;\n" - "SET_ZFLG(((uae_s16)(dst)) == 0);\n" - "SET_VFLG((bflgs ^ bflgo) & (bflgn ^ bflgo));\n" - "SET_CFLG(((uae_u16)(src)) > ((uae_u16)(0)));\n" - "SET_NFLG(dst & 0x80000000);\n" - "SET_XFLG(GET_CFLG());\n"); + fill_prefetch_next_after(1, "dreg_68000_long_replace_low(srcreg, dst);\n"); genastore_rev("dst", curi->smode, "srcreg", curi->size, "src"); } else { genastore_rev("dst", curi->smode, "srcreg", curi->size, "src"); @@ -5343,17 +5369,7 @@ static void gen_opcode (unsigned int opcode) if (curi->smode == Dreg) { if (curi->size == sz_long) { // prefetch bus error and long register: only low word is updated - // N flag from high word. Z both. - fill_prefetch_next_after(1, - "dreg_68000_long_replace_low(srcreg, newv);\n" - "int bflgs = ((uae_s16)(src)) < 0;\n" - "int bflgo = ((uae_s16)(0)) < 0;\n" - "int bflgn = ((uae_s16)(newv)) < 0;\n" - "SET_VFLG((bflgs ^ bflgo) & (bflgo ^ bflgn));\n" - "SET_CFLG(bflgs ^ ((bflgs ^ bflgn) & (bflgo ^ bflgn)));\n" - "SET_ZFLG(GET_ZFLG() & (((uae_s16)(newv)) == 0));\n" - "SET_NFLG(((uae_s32)(newv)) < 0);\n" - "SET_XFLG(GET_CFLG());\n"); + fill_prefetch_next_after(1, "dreg_68000_long_replace_low(srcreg, newv);\n"); genastore_rev("newv", curi->smode, "srcreg", curi->size, "src"); } else { genastore_rev("newv", curi->smode, "srcreg", curi->size, "src"); @@ -6131,7 +6147,7 @@ static void gen_opcode (unsigned int opcode) next_level_000(); if (cpu_level <= 1 && using_exception_3) { out("if (m68k_areg(regs, 7) & 1) {\n"); - out("exception3_read(opcode, m68k_areg(regs, 7), 1, 1);\n"); + out("exception3_read_opcode(opcode, m68k_areg(regs, 7), 1, 1);\n"); write_return_cycles_noadd(0); out("}\n"); } @@ -6157,7 +6173,7 @@ static void gen_opcode (unsigned int opcode) out("regs.sr = sr;\n"); makefromsr(); out("if (pc & 1) {\n"); - out("exception3_read(opcode | 0x20000, pc, 1, 2);\n"); + out("exception3_read_opcode(opcode | 0x20000, pc, 1, 2);\n"); write_return_cycles(0); out("}\n"); setpc ("pc"); @@ -6205,7 +6221,7 @@ static void gen_opcode (unsigned int opcode) makefromsr(); out("if (pc & 1) {\n"); dummy_prefetch("pc", "oldpc"); - out("exception3i(opcode, pc);\n"); + out("exception3_read_prefetch(opcode, pc);\n"); write_return_cycles(0); out("}\n"); out("newsr = sr; newpc = pc;\n"); @@ -6302,7 +6318,7 @@ static void gen_opcode (unsigned int opcode) addcycles_ce020 (4); makefromsr_t0(); out("if (newpc & 1) {\n"); - out("exception3i(opcode, newpc);\n"); + out("exception3_read_prefetch(opcode, newpc);\n"); write_return_cycles(0); out("}\n"); setpc ("newpc"); @@ -6315,7 +6331,7 @@ static void gen_opcode (unsigned int opcode) clear_m68k_offset(); tail_ce020_done = true; if (using_ce || using_prefetch) { - fill_prefetch_full_000_special(); + fill_prefetch_full_000_special(NULL); } else { fill_prefetch_full_ntx(0); } @@ -6337,7 +6353,7 @@ static void gen_opcode (unsigned int opcode) if (cpu_level >= 4) { out("m68k_areg(regs, 7) -= 4 + offs;\n"); } - out("exception3i(0x%04X, pc);\n", opcode); + out("exception3_read_prefetch(opcode, pc);\n"); write_return_cycles(0); out("}\n"); setpc ("pc"); @@ -6345,7 +6361,7 @@ static void gen_opcode (unsigned int opcode) clear_m68k_offset(); tail_ce020_done = true; if (using_prefetch || using_ce) { - fill_prefetch_full_000_special(); + fill_prefetch_full_000_special(NULL); } else { fill_prefetch_full(0); } @@ -6373,14 +6389,22 @@ static void gen_opcode (unsigned int opcode) addop_ce020(curi, 0, 0); // smode must be first in case it is A7. Except if 68040! if (cpu_level == 4) { - genamode(NULL, Apdi, "7", sz_long, "old", 2, 0, GF_AA); + genamode(NULL, Apdi, "7", sz_long, "old", 2, 0, GF_AA | GF_NOEXC); genamode(NULL, curi->smode, "srcreg", sz_long, "src", 1, 0, GF_AA); } else { genamode(NULL, curi->smode, "srcreg", sz_long, "src", 1, 0, GF_AA); - genamode(NULL, Apdi, "7", sz_long, "old", 2, 0, GF_AA); + genamode(NULL, Apdi, "7", sz_long, "old", 2, 0, GF_AA | GF_NOEXC); } strcpy(bus_error_code, "m68k_areg(regs, 7) += 4;\n"); genamode(NULL, curi->dmode, "dstreg", curi->size, "offs", 1, 0, 0); + if (cpu_level <= 1 && using_exception_3) { + out("if (olda & 1) {\n"); + out("m68k_areg(regs, 7) += 4;\n"); + out("m68k_areg(regs, srcreg) = olda;\n"); + out("exception3_write_opcode(opcode, olda, sz_word, src >> 16, 1);\n"); + write_return_cycles(0); + out("}\n"); + } genastore("src", Apdi, "7", sz_long, "old"); genastore("m68k_areg(regs, 7)", curi->smode, "srcreg", sz_long, "src"); out("m68k_areg(regs, 7) += offs;\n"); @@ -6411,7 +6435,7 @@ static void gen_opcode (unsigned int opcode) out("uaecptr pc = %s;\n", getpc); if (cpu_level <= 1 && using_exception_3) { out("if (m68k_areg(regs, 7) & 1) {\n"); - out("exception3_read(opcode, m68k_areg(regs, 7), 1, 1);\n"); + out("exception3_read_opcode(opcode, m68k_areg(regs, 7), 1, 1);\n"); write_return_cycles(0); out("}\n"); } @@ -6460,12 +6484,12 @@ static void gen_opcode (unsigned int opcode) if (cpu_level >= 4) { out("m68k_areg(regs, 7) -= 4;\n"); } - out("exception3i(0x%04X, faultpc);\n", opcode); + out("exception3_read_prefetch(opcode, faultpc);\n"); write_return_cycles(0); out("}\n"); clear_m68k_offset(); if (using_prefetch || using_ce) { - fill_prefetch_full_000_special(); + fill_prefetch_full_000_special(NULL); } else { fill_prefetch_full(0); } @@ -6520,9 +6544,8 @@ static void gen_opcode (unsigned int opcode) break; case i_RTR: if (cpu_level <= 1 && using_exception_3) { - // RTR (and RTS) exception3 does not have normal 4 cycle delay out("if (m68k_areg(regs, 7) & 1) {\n"); - out("exception3_read(opcode, m68k_areg(regs, 7), 1, 1);\n"); + out("exception3_read_opcode(opcode, m68k_areg(regs, 7), 1, 1);\n"); write_return_cycles(0); out("}\n"); } @@ -6533,7 +6556,7 @@ static void gen_opcode (unsigned int opcode) if (cpu_level >= 4) { out("if (pc & 1) {\n"); out("m68k_areg(regs, 7) -= 6;\n"); - out("exception3i(0x%04X, pc);\n", opcode); + out("exception3_read_prefetch(opcode, pc);\n"); write_return_cycles(0); out("}\n"); } @@ -6548,13 +6571,13 @@ static void gen_opcode (unsigned int opcode) dummy_prefetch(NULL, NULL); } setpc("oldpc"); - out("exception3i(0x%04X, faultpc);\n", opcode); + out("exception3_read_prefetch(opcode, faultpc);\n"); write_return_cycles(0); out("}\n"); } clear_m68k_offset(); if (using_prefetch || using_ce) { - fill_prefetch_full_000_special(); + fill_prefetch_full_000_special(NULL); } else { fill_prefetch_full(0); } @@ -6572,9 +6595,6 @@ static void gen_opcode (unsigned int opcode) if (using_exception_3 && cpu_level <= 1) { push_ins_cnt(); out("if (srca & 1) {\n"); - if (curi->smode >= Ad16 && cpu_level == 1 && using_prefetch) { - dummy_prefetch("srca", NULL); - } if (curi->smode == Ad16 || curi->smode == absw || curi->smode == PC16) { addcycles000_onlyce(2); addcycles000_nonce(2); @@ -6583,7 +6603,7 @@ static void gen_opcode (unsigned int opcode) addcycles000_onlyce(6); addcycles000_nonce(6); } - out("exception3i(opcode, srca);\n"); + out("exception3_read_prefetch(opcode, srca);\n"); write_return_cycles_noadd(0); out("}\n"); pop_ins_cnt(); @@ -6607,7 +6627,7 @@ static void gen_opcode (unsigned int opcode) out("m68k_areg(regs, 7) -= 4;\n"); if (using_exception_3 && cpu_level >= 2) { out("if (%s & 1) {\n", getpc); - out("exception3i(opcode, %s);\n", getpc); + out("exception3_read_prefetch(opcode, %s);\n", getpc); write_return_cycles(0); out("}\n"); } @@ -6616,7 +6636,7 @@ static void gen_opcode (unsigned int opcode) out("m68k_areg(regs, 7) -= 4;\n"); if (using_exception_3 && cpu_level <= 1) { out("if (m68k_areg(regs, 7) & 1) {\n"); - out("exception3_write(opcode, m68k_areg(regs, 7), 1, m68k_areg(regs, 7) >> 16, 1);\n"); + out("exception3_write_opcode(opcode, m68k_areg(regs, 7), 1, m68k_areg(regs, 7) >> 16, 1);\n"); write_return_cycles(0); out("}\n"); } @@ -6681,7 +6701,7 @@ static void gen_opcode (unsigned int opcode) addcycles000_onlyce(6); addcycles000_nonce(6); } - out("exception3i(opcode, srca);\n"); + out("exception3_read_prefetch(opcode, srca);\n"); write_return_cycles_noadd(0); out("}\n"); pop_ins_cnt(); @@ -6728,28 +6748,28 @@ static void gen_opcode (unsigned int opcode) genamode(curi, curi->smode, "srcreg", curi->size, "src", 1, 0, GF_AA|GF_NOREFILL); } out("s = (uae_s32)src + 2;\n"); + addcycles000(2); + out("uaecptr oldpc = %s;\n", getpc); + out("uaecptr nextpc = oldpc + %d;\n", m68k_pc_offset); if (using_exception_3) { if (cpu_level == 0) { out("if (m68k_areg(regs, 7) & 1) {\n"); out("m68k_areg(regs, 7) -= 4;\n"); - out("exception3b(opcode, m68k_areg(regs, 7), true, false, %s + 2);\n", getpc); + incpc("2"); + out("exception3_write_opcode(opcode, m68k_areg(regs, 7), sz_word, oldpc, 1);\n"); write_return_cycles(0); out("}\n"); } else if (cpu_level == 1) { out("if (m68k_areg(regs, 7) & 1) {\n"); - out("exception3b(opcode, m68k_areg(regs, 7), true, true, %s);\n", getpc); + out("exception3_write_opcode(opcode, m68k_areg(regs, 7), sz_word, oldpc, 1);\n"); write_return_cycles(0); out("}\n"); } } - addcycles000(2); - out("uaecptr oldpc = %s;\n", getpc); - out("uaecptr nextpc = oldpc + %d;\n", m68k_pc_offset); if (using_exception_3 && cpu_level == 1) { // 68010 TODO: looks like prefetches are done first and stack writes last out("if (s & 1) {\n"); - dummy_prefetch("(oldpc + s) & ~1", "oldpc"); - out("exception3b(opcode, oldpc + s, false, true, %s);\n", getpc); + out("exception3_read_prefetch(opcode, s);\n"); write_return_cycles(0); out("}\n"); } @@ -6757,7 +6777,7 @@ static void gen_opcode (unsigned int opcode) out("if (s & 1) {\n"); if (cpu_level < 4) out("m68k_areg(regs, 7) -= 4;\n"); - out("exception3b(opcode, %s + s, 0, 1, %s + s);\n", getpc, getpc); + out("exception3_read_prefetch(opcode, s);\n"); write_return_cycles(0); out("}\n"); } @@ -6769,9 +6789,7 @@ static void gen_opcode (unsigned int opcode) out("m68k_do_bsr_ce020(nextpc, s);\n"); } else if (using_ce020 == 2) { out("m68k_do_bsr_ce030(nextpc, s);\n"); - } else if (using_ce) { - out("m68k_do_bsr_ce(nextpc, s);\n"); - } else if (using_prefetch || (using_test && cpu_level <= 1)) { + } else if (using_ce || using_prefetch || (using_test && cpu_level <= 1)) { out("m68k_areg(regs, 7) -= 4;\n"); out("uaecptr dsta = m68k_areg(regs, 7);\n"); out("%s(dsta, nextpc >> 16);\n", dstw); @@ -6780,14 +6798,14 @@ static void gen_opcode (unsigned int opcode) check_bus_error("dst", 2, 1, 1, "nextpc", 1); incpc("s"); } else if (using_prefetch_020 || (using_test && cpu_level >= 2)) { - out("m68k_do_bsri (nextpc, s);\n"); + out("m68k_do_bsri(nextpc, s);\n"); } else { - out("m68k_do_bsr (nextpc, s);\n"); + out("m68k_do_bsr(nextpc, s);\n"); } count_write += 2; if (using_exception_3 && cpu_level == 0) { out("if (%s & 1) {\n", getpc); - out("exception3b(opcode, %s, false, true, %s);\n", getpc, getpc); + out("exception3_read_prefetch(opcode, %s);\n", getpc); write_return_cycles(0); out("}\n"); } @@ -6798,7 +6816,7 @@ static void gen_opcode (unsigned int opcode) } clear_m68k_offset(); if (using_prefetch || using_ce) { - fill_prefetch_full_000_special(); + fill_prefetch_full_000_special(NULL); } else { fill_prefetch_full(0); } @@ -6811,7 +6829,7 @@ static void gen_opcode (unsigned int opcode) if (cpu_level < 2) { addcycles000(2); out("if (cctrue(%d)) {\n", curi->cc); - out("exception3i(opcode, %s + 1);\n", getpc); + out("exception3_read_prefetch(opcode, %s + 1);\n", getpc); write_return_cycles(0); out("}\n"); sync_m68k_pc(); @@ -6828,7 +6846,7 @@ static void gen_opcode (unsigned int opcode) addcycles000(2); if (using_exception_3 && cpu_level >= 4) { out("if (src & 1) {\n"); - out("exception3i(opcode, %s + 2 + (uae_s32)src);\n", getpc); + out("exception3_read_prefetch(opcode, %s + 2 + (uae_s32)src);\n", getpc); write_return_cycles(0); out("}\n"); } @@ -6840,14 +6858,14 @@ static void gen_opcode (unsigned int opcode) incpc("((uae_s32)src + 2) & ~1"); dummy_prefetch(NULL, "oldpc"); } - out("exception3i(opcode, %s + 2 + (uae_s32)src);\n", getpc); + out("exception3_read_prefetch(opcode, %s + 2 + (uae_s32)src);\n", getpc); write_return_cycles(0); out("}\n"); } push_ins_cnt(); if (using_prefetch) { incpc ("(uae_s32)src + 2"); - fill_prefetch_full_000_special(); + fill_prefetch_full_000_special(NULL); if (using_ce) out("return;\n"); else @@ -6874,10 +6892,10 @@ static void gen_opcode (unsigned int opcode) fill_prefetch_bcc(); } else if (curi->size == sz_word) { add_head_cycs (6); - fill_prefetch_full_000_special(); + fill_prefetch_full_000_special(NULL); } else { add_head_cycs (6); - fill_prefetch_full_000_special(); + fill_prefetch_full_000_special(NULL); } insn_n_cycles = curi->size == sz_byte ? 8 : 12; branch_inst = 1; @@ -6905,12 +6923,22 @@ bccl_not68020: case i_PEA: if (curi->smode == Ad8r || curi->smode == PC8r) addcycles000(2); + if (cpu_level <= 1 && using_exception_3) { + out("uae_u16 old_opcode = opcode;\n"); + } genamode(curi, curi->smode, "srcreg", curi->size, "src", 0, 0, GF_AA); - genamode(NULL, Apdi, "7", sz_long, "dst", 2, 0, GF_AA); - if (!(curi->smode == absw || curi->smode == absl)) - fill_prefetch_next_after(0, "m68k_areg(regs, 7) += 4;\n"); + genamode(NULL, Apdi, "7", sz_long, "dst", 2, 0, GF_AA | GF_NOEXC); if (curi->smode == Ad8r || curi->smode == PC8r) addcycles000(2); + if (!(curi->smode == absw || curi->smode == absl)) + fill_prefetch_next_after(0, "m68k_areg(regs, 7) += 4;\n"); + if (cpu_level <= 1 && using_exception_3) { + out("if (dsta & 1) {\n"); + out("regs.ir = old_opcode;\n"); + out("exception3_write_opcode(old_opcode, dsta, sz_word, srca >> 16, 1);\n"); + write_return_cycles(0); + out("}\n"); + } genastore("srca", Apdi, "7", sz_long, "dst"); if ((curi->smode == absw || curi->smode == absl)) fill_prefetch_next_t(); @@ -6932,7 +6960,7 @@ bccl_not68020: addcycles000_nonce(2); if (using_exception_3 && cpu_level >= 4) { out("if (offs & 1) {\n"); - out("exception3i(opcode, oldpc + (uae_s32)offs + 2);\n"); + out("exception3_read_prefetch(opcode, oldpc + (uae_s32)offs + 2);\n"); write_return_cycles(0); out("}\n"); } @@ -6947,7 +6975,7 @@ bccl_not68020: if (cpu_level == 1) { out("%s(%d);\n", prefetch_word, -1); } - out("exception3i(opcode, %s);\n", getpc); + out("exception3_read_prefetch(opcode, %s);\n", getpc); write_return_cycles(0); out("}\n"); @@ -6991,7 +7019,7 @@ bccl_not68020: int old_m68k_pc_total = m68k_pc_total; clear_m68k_offset(); get_prefetch_020_continue(); - fill_prefetch_full_000_special(); + fill_prefetch_full_000_special(NULL); returncycles(8); m68k_pc_offset = old_m68k_pc_offset; m68k_pc_total = old_m68k_pc_total; @@ -7011,16 +7039,19 @@ bccl_not68020: out("}\n"); out("regs.loop_mode = 0;\n"); setpc("oldpc + %d", m68k_pc_offset); - fill_prefetch_full_000_special(); + fill_prefetch_full_000_special(NULL); returncycles(8); out("}\n"); } fill_prefetch_1(0); - if (cpu_level < 2 || cpu_level >= 4) { + if (cpu_level >= 4) { genastore("(src - 1)", curi->smode, "srcreg", curi->size, "src"); } out("if (src) {\n"); + if (cpu_level < 2) { + genastore("(src - 1)", curi->smode, "srcreg", curi->size, "src"); + } irc2ir(); add_head_cycs (6); @@ -7058,7 +7089,7 @@ bccl_not68020: setpc ("oldpc + %d", m68k_pc_offset); clear_m68k_offset(); get_prefetch_020_continue(); - fill_prefetch_full_000_special(); + fill_prefetch_full_000_special("if (!cctrue(%d)) {\nm68k_dreg(regs, srcreg) = (m68k_dreg(regs, srcreg) & ~0xffff) | (((src - 1)) & 0xffff);\n}\n", curi->cc); insn_n_cycles = 12; branch_inst = 1; next_level_040_to_030(); diff --git a/include/cpu_prefetch.h b/include/cpu_prefetch.h index 8bb6be7e..f30b95fe 100644 --- a/include/cpu_prefetch.h +++ b/include/cpu_prefetch.h @@ -427,31 +427,6 @@ STATIC_INLINE void put_byte_ce000 (uaecptr addr, uae_u32 v) mem_access_delay_byte_write (addr, v); } -STATIC_INLINE void m68k_do_rts_ce (void) -{ - uaecptr pc; - pc = x_get_word (m68k_areg (regs, 7)) << 16; - pc |= x_get_word (m68k_areg (regs, 7) + 2); - m68k_areg (regs, 7) += 4; - m68k_setpci (pc); -} - -STATIC_INLINE void m68k_do_bsr_ce (uaecptr oldpc, uae_s32 offset) -{ - m68k_areg (regs, 7) -= 4; - x_put_word (m68k_areg (regs, 7), oldpc >> 16); - x_put_word (m68k_areg (regs, 7) + 2, oldpc); - m68k_incpci (offset); -} - -STATIC_INLINE void m68k_do_jsr_ce (uaecptr oldpc, uaecptr dest) -{ - m68k_areg (regs, 7) -= 4; - x_put_word (m68k_areg (regs, 7), oldpc >> 16); - x_put_word (m68k_areg (regs, 7) + 2, oldpc); - m68k_setpci (dest); -} - #endif STATIC_INLINE uae_u32 get_disp_ea_000 (uae_u32 base, uae_u32 dp) diff --git a/include/newcpu.h b/include/newcpu.h index 74f2d9b7..ca5823eb 100644 --- a/include/newcpu.h +++ b/include/newcpu.h @@ -52,7 +52,6 @@ extern int fpp_movem_index2[256]; extern int fpp_movem_next[256]; #endif -extern int bus_error_offset; extern int hardware_bus_error; typedef uae_u32 REGPARAM3 cpuop_func (uae_u32) REGPARAM; @@ -732,9 +731,8 @@ 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_read_opcode(uae_u32 opcode, uaecptr addr, int size, int fc); extern void exception3_write_opcode(uae_u32 opcode, uaecptr addr, int size, uae_u32 val, int fc); +extern void exception3_read_prefetch(uae_u32 opcode, uaecptr addr); 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(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); diff --git a/newcpu.cpp b/newcpu.cpp index 20dabbab..3a64de3a 100644 --- a/newcpu.cpp +++ b/newcpu.cpp @@ -84,7 +84,6 @@ static void exception3_read_special(uae_u32 opcode, uaecptr addr, int size, int int mmu_enabled, mmu_triggered; int cpu_cycles; -int bus_error_offset; int hardware_bus_error; static int baseclock; int m68k_pc_indirect; @@ -2615,9 +2614,9 @@ kludge_me_do: m68k_setpc(regs.vbr + 4 * vector_nr); if (interrupt) { regs.ir = nr; - exception3_read(regs.ir | 0x20000 | 0x10000, newpc, 1, 2); + exception3_read(regs.ir | 0x20000 | 0x10000, newpc, sz_word, 2); } else { - exception3_read(regs.ir | 0x40000, newpc, 1, 2); + exception3_read(regs.ir | 0x40000, newpc, sz_word, 2); } } else if (currprefs.cpu_model == 68010) { // offset, not vbr + offset @@ -2626,7 +2625,7 @@ kludge_me_do: regs.write_buffer = 4 * vector_nr; regs.read_buffer = newpc; regs.irc = regs.read_buffer; - exception3b(regs.opcode, newpc, false, true, newpc); + exception3_read(regs.opcode, newpc, sz_word, 2); } else { exception3_notinstruction(regs.ir, newpc); } @@ -3093,9 +3092,9 @@ kludge_me_do: m68k_setpc(regs.vbr + 4 * vector_nr); if (interrupt) { regs.ir = nr; - exception3_read(regs.ir | 0x20000 | 0x10000, newpc, 1, 2); + exception3_read(regs.ir | 0x20000 | 0x10000, newpc, sz_word, 2); } else { - exception3_read(regs.ir | 0x40000, newpc, 1, 2); + exception3_read(regs.ir | 0x40000, newpc, sz_word, 2); } } else if (currprefs.cpu_model == 68010) { regs.t1 = 0; @@ -3103,7 +3102,7 @@ kludge_me_do: regs.write_buffer = 4 * vector_nr; regs.read_buffer = newpc; regs.irc = regs.read_buffer; - exception3b(regs.ir, newpc, false, true, newpc); + exception3_read(regs.ir, newpc, sz_word, 2); } else { exception3_notinstruction(regs.ir, newpc); } @@ -7030,6 +7029,12 @@ static void exception3_read_special(uae_u32 opcode, uaecptr addr, int size, int } // Some hardware accepts address error aborted reads or writes as normal reads/writes. +void exception3_read_prefetch(uae_u32 opcode, uaecptr addr) +{ + x_do_cycles(4 * cpucycleunit); + last_di_for_exception_3 = 0; + exception3f(opcode, addr, false, true, false, m68k_getpc(), sz_word, false, -1); +} void exception3_read_opcode(uae_u32 opcode, uaecptr addr, int size, int fc) { x_do_cycles(4 * cpucycleunit); @@ -7078,20 +7083,10 @@ void exception3_write(uae_u32 opcode, uaecptr addr, int size, uae_u32 val, int f exception3f(opcode, addr, true, ia, ni, 0xffffffff, size, false, fc); regs.write_buffer = val; } -void exception3i(uae_u32 opcode, uaecptr addr) -{ - last_di_for_exception_3 = 0; - exception3f (opcode, addr, 0, 1, false, 0xffffffff, 1, true, -1); -} -void exception3b(uae_u32 opcode, uaecptr addr, bool w, bool i, uaecptr pc) -{ - last_di_for_exception_3 = 0; - exception3f (opcode, addr, w, i, false, pc, 1, true, -1); -} void exception2_setup(uae_u32 opcode, uaecptr addr, bool read, int size, uae_u32 fc) { - last_addr_for_exception_3 = m68k_getpc() + bus_error_offset; + last_addr_for_exception_3 = m68k_getpc(); last_fault_for_exception_3 = addr; last_writeaccess_for_exception_3 = read == 0; last_op_for_exception_3 = opcode; @@ -7143,9 +7138,23 @@ void exception2_write(uae_u32 opcode, uaecptr addr, int size, uae_u32 val, int f void exception2_fetch(uae_u32 opcode, int offset) { - uaecptr addr = m68k_getpc() + offset; - exception2_setup(opcode, addr, true, 1, 2); + last_fault_for_exception_3 = m68k_getpc() + offset; + last_writeaccess_for_exception_3 = 0; + last_op_for_exception_3 = opcode; + last_fc_for_exception_3 = 2; + last_notinstruction_for_exception_3 = exception_in_exception != 0; + last_size_for_exception_3 = sz_word; last_di_for_exception_3 = 0; + hardware_bus_error = 0; + + if (currprefs.cpu_model == 68000 && currprefs.cpu_compatible) { + if (generates_group1_exception(regs.ir) && !(opcode & 0x20000)) { + last_fc_for_exception_3 |= 8; // set N/I + } + if (opcode & 0x10000) + last_fc_for_exception_3 |= 8; + } + Exception(2); }