From: Toni Wilen Date: Tue, 31 Dec 2019 15:30:06 +0000 (+0200) Subject: 68010 address error updates. X-Git-Tag: 4400~206 X-Git-Url: https://git.unchartedbackwaters.co.uk/w/?a=commitdiff_plain;h=ac713fb452678c5443354c063c3709e7b43e673a;p=francis%2Fwinuae.git 68010 address error updates. --- diff --git a/cputest.cpp b/cputest.cpp index 344e9b3b..da5c5dc4 100644 --- a/cputest.cpp +++ b/cputest.cpp @@ -146,6 +146,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_u16 read_buffer_prev; struct uae_prefs currprefs; @@ -330,6 +331,7 @@ uae_u16 get_word_test_prefetch(int o) if (cpu_lvl < 2) o -= 2; regs.irc = get_iword_test(m68k_getpci() + o + 2); + read_buffer_prev = regs.read_buffer; regs.read_buffer = regs.irc; return get_iword_test(m68k_getpci() + o); } @@ -459,6 +461,7 @@ uae_u32 get_byte_test(uaecptr addr) { check_bus_error(addr, 0, regs.s ? 5 : 1); uae_u8 *p = get_addr(addr, 1, 0); + read_buffer_prev = regs.read_buffer; regs.read_buffer = *p; return *p; } @@ -472,6 +475,7 @@ uae_u32 get_word_test(uaecptr addr) uae_u8 *p = get_addr(addr, 2, 0); v = (p[0] << 8) | (p[1]); } + read_buffer_prev = regs.read_buffer; regs.read_buffer = v; return v; } @@ -492,6 +496,7 @@ uae_u32 get_long_test(uaecptr addr) uae_u8 *p = get_addr(addr, 4, 0); v = (p[0] << 24) | (p[1] << 16) | (p[2] << 8) | (p[3]); } + read_buffer_prev = regs.read_buffer; regs.read_buffer = v; return v; } @@ -946,7 +951,6 @@ void exception2_read(uae_u32 opcode, uaecptr addr, int size, int fc) test_exception_3_fc = fc; test_exception_3_size = size; test_exception_3_di = 1; - regs.read_buffer = 0; if (currprefs.cpu_model == 68000) { if (generates_group1_exception(regs.ir) && !(opcode & 0x20000)) { @@ -994,7 +998,6 @@ void exception3_read(uae_u32 opcode, uae_u32 addr, int size, int fc) test_exception_3_fc = fc; test_exception_3_size = size; test_exception_3_di = 1; - regs.read_buffer = 0; if (currprefs.cpu_model == 68000) { if (generates_group1_exception(regs.ir) && !(opcode & 0x20000)) { @@ -1004,6 +1007,11 @@ void exception3_read(uae_u32 opcode, uae_u32 addr, int size, int fc) test_exception_3_fc |= 8; test_exception_opcode = regs.ir; } + if (currprefs.cpu_model == 68010) { + if (opcode & 0x40000) { + test_exception_3_di = 0; + } + } doexcstack(); } @@ -1057,6 +1065,8 @@ void exception3i(uae_u32 opcode, uaecptr addr) test_exception_3_w = 0; test_exception_addr = addr; test_exception_opcode = opcode; + test_exception_3_di = 0; + test_exception_3_size = sz_word; doexcstack(); } void exception3b(uae_u32 opcode, uaecptr addr, bool w, bool i, uaecptr pc) @@ -1066,6 +1076,8 @@ void exception3b(uae_u32 opcode, uaecptr addr, bool w, bool i, uaecptr pc) test_exception_3_w = w; test_exception_addr = addr; test_exception_opcode = opcode; + test_exception_3_di = 0; + test_exception_3_size = sz_word; doexcstack(); } @@ -2534,6 +2546,7 @@ static void execute_ins(uaecptr endpc, uaecptr targetpc, struct instr *dp) testing_active_opcode = opc; cpu_bus_error = 0; cpu_bus_error_fake = 0; + read_buffer_prev = regs.ir; regs.read_buffer = regs.irc; regs.write_buffer = 0xf00d; @@ -2810,6 +2823,9 @@ static uae_u8 *save_exception(uae_u8 *p, struct instr *dp) // instruction *p++ = sf[24]; *p++ = sf[25]; + // optional data input (some hardware does real memory fetch when CPU does the dummy fetch, some don't) + *p++ = read_buffer_prev >> 8; + *p++ = read_buffer_prev; break; case 0x0a: // 68020/030 address error. case 0x0b: // Don't save anything extra, too many undefined fields and bits.. diff --git a/cputest/cputest_defines.h b/cputest/cputest_defines.h index 539901e0..037dddd7 100644 --- a/cputest/cputest_defines.h +++ b/cputest/cputest_defines.h @@ -1,5 +1,5 @@ -#define DATA_VERSION 12 +#define DATA_VERSION 13 #define CT_FPREG 0 #define CT_DREG 0 diff --git a/cputest/main.c b/cputest/main.c index 973700d7..e7155aab 100644 --- a/cputest/main.c +++ b/cputest/main.c @@ -1362,7 +1362,7 @@ static uae_u8 *validate_exception(struct registers *regs, uae_u8 *p, int excnum, pl(exc + 12, v); exclen = 16; break; - case 8: + case 8: // 68010 bus/address error exc[8] = *p++; exc[9] = *p++; excrwp = ((exc[8] & 1) == 0) ? 1 : 0; @@ -1388,6 +1388,12 @@ static uae_u8 *validate_exception(struct registers *regs, uae_u8 *p, int excnum, sp[22] = sp[23] = 0; // ignore undocumented data exclen = 26; + // read input buffer may contain either actual data read from memory or previous read data + // this depends on hardware, cpu does dummy read cycle and some hardware returns memory data, some ignore it. + memcpy(alternate_exception1, exc, exclen); + alternate_exception1[20] = *p++; + alternate_exception1[21] = *p++; + alts = 1; break; case 0x0a: case 0x0b: diff --git a/cputest_support.cpp b/cputest_support.cpp index b4c653ab..bce2b91d 100644 --- a/cputest_support.cpp +++ b/cputest_support.cpp @@ -9,6 +9,8 @@ #include "mmu_common.h" #include "cpummu030.h" +cpuop_func *loop_mode_table[65536]; + void my_trim(TCHAR *s) { int len; diff --git a/gencpu.cpp b/gencpu.cpp index ae8d4b51..ad23126e 100644 --- a/gencpu.cpp +++ b/gencpu.cpp @@ -2749,6 +2749,8 @@ static void genamode2x (amodes mode, const char *reg, wordsizes size, const char printf("\tif (%sa & 1) {\n", name); if (cpu_level == 1) { + // 68010 does dummy access + printf("\t\tuae_s16 d_%s = %s(%sa & ~1);\n", name, srcw, name); if (abs(bus_error_reg_add) == 4) bus_error_reg_add = 0; // 68010 CLR : pre and post are not added yet @@ -2763,9 +2765,6 @@ static void genamode2x (amodes mode, const char *reg, wordsizes size, const char if (mode == Apdi && g_instr->size == sz_word && g_instr->mnemo != i_CLR) { printf("\t\tm68k_areg(regs, %s) = %sa;\n", reg, name); } - if (mode == Apdi) { - ;// printf("\t\tregs.read_buffer = 0;\n"); - } } if (g_instr->mnemo == i_ADDX || g_instr->mnemo == i_SUBX) { @@ -3511,13 +3510,34 @@ static void movem_mmu030 (const char *code, int size, bool put, bool aipi, bool static void movem_ex3(int write) { if ((using_prefetch || using_ce) && using_exception_3) { + if (write) { // MOVEM write to memory won't generate address error // exception if mask is zero and EA is odd. printf("\tif ((amask || dmask) && (srca & 1)) {\n"); // MOVE.L EA,-(An) causing address error: stacked value is original An - 2, not An - 4. - if (g_instr->dmode == Apdi) + if (g_instr->dmode == Apdi) { printf("\t\tsrca -= 2;\n"); + } + printf("\t\tuaecptr srcav = srca;\n"); + if (cpu_level == 1) { + if (g_instr->dmode == Apdi) { + printf("\t\tif(amask) {\n"); + printf("\t\t\tsrcav = m68k_areg(regs, movem_index2[amask]);\n"); + printf("\t\t} else if (dmask) {\n"); + printf("\t\t\tsrcav = m68k_dreg(regs, movem_index2[dmask]);\n"); + printf("\t\t}\n"); + } else { + printf("\t\tif(dmask) {\n"); + printf("\t\t\tsrcav = m68k_dreg(regs, movem_index1[dmask]);\n"); + printf("\t\t} else if (amask) {\n"); + printf("\t\t\tsrcav = m68k_areg(regs, movem_index1[amask]);\n"); + printf("\t\t}\n"); + } + if (g_instr->dmode == Aind || g_instr->dmode == Apdi || g_instr->dmode == Aipi) { + printf("\t\tregs.read_buffer = mask;\n"); + } + } } else { // MOVEM from memory will generate address error // exception if mask is zero and EA is odd. @@ -3525,9 +3545,13 @@ static void movem_ex3(int write) if (g_instr->dmode == PC16 || g_instr->dmode == PC8r) { printf("\t\topcode |= 0x01020000;\n"); } + printf("\t\tuaecptr srcav = srca;\n"); + if (cpu_level == 1) { + printf("\t\tuae_s16 dummy = %s(srca & ~1);\n", srcw); + } } if (write) { - printf("\t\texception3_write(opcode, srca, %d, srca, %d);\n", + printf("\t\texception3_write(opcode, srca, %d, srcav, %d);\n", g_instr->size, (g_instr->dmode == PC16 || g_instr->dmode == PC8r) ? 2 : 1); } else { @@ -4879,13 +4903,21 @@ static void gen_opcode (unsigned int opcode) addcycles000(2); if (!isreg(curi->smode) && using_exception_3 && curi->size != sz_byte && (using_prefetch || using_ce)) { printf("\tif(srca & 1) {\n"); + if (curi->smode == Aipi) { + printf("\t\tm68k_areg(regs, srcreg) -= %d;\n", 1 << curi->size); + } else if (curi->smode == Apdi) { + printf("\t\tm68k_areg(regs, srcreg) += %d;\n", 1 << curi->size); + } else if (curi->smode >= Ad16) { + printf("\t%s(%d);\n", prefetch_word, m68k_pc_offset + 2); + genflags(flag_logical, curi->size, "0", "", ""); + } printf("\t\texception3_write(opcode, srca, 1, 0, 1);\n"); write_return_cycles("\t\t", 0); printf("\t}\n"); } + fill_prefetch_next(); genflags(flag_logical, curi->size, "0", "", ""); genastore_rev("0", curi->smode, "srcreg", curi->size, "src"); - fill_prefetch_next(); } else { genamode(curi, curi->smode, "srcreg", curi->size, "src", 2, 0, 0); fill_prefetch_next(); @@ -6028,15 +6060,15 @@ static void gen_opcode (unsigned int opcode) } printf("\ts = (uae_s32)src + 2;\n"); if (using_exception_3) { - if (cpu_level <= 1) { + if (cpu_level == 0) { printf("\tif (m68k_areg(regs, 7) & 1) {\n"); printf("\t\tm68k_areg(regs, 7) -= 4;\n"); - printf("\t\texception3b(opcode, m68k_areg(regs, 7), true, false, %s + 2);\n", getpc); + printf("\t\texception3b(opcode, m68k_areg(regs, 7), true, false, %s + 2);\n", getpc); write_return_cycles("\t\t", 0); printf("\t}\n"); - } else if (0) { - printf("\tif (src & 1) {\n"); - printf("\t\texception3b(opcode, %s + s, 0, 1, %s + s);\n", getpc, getpc); + } else if (cpu_level == 1) { + printf("\tif (m68k_areg(regs, 7) & 1) {\n"); + printf("\t\texception3b(opcode, m68k_areg(regs, 7), true, true, %s);\n", getpc); write_return_cycles("\t\t", 0); printf("\t}\n"); } @@ -6044,6 +6076,16 @@ static void gen_opcode (unsigned int opcode) addcycles000 (2); printf("\tuaecptr oldpc = %s;\n", getpc); printf("\tuaecptr 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 + printf("\tif (s & 1) {\n"); + setpc("(oldpc + s) & ~1"); + printf("\t%s(0);\n", prefetch_word); + setpc("oldpc"); + printf("\t\texception3b(opcode, oldpc + s, false, true, %s);\n", getpc); + write_return_cycles("\t\t", 0); + printf("\t}\n"); + } if (using_exception_3 && cpu_level >= 2) { printf("\tif (s & 1) {\n"); if (cpu_level < 4) @@ -6075,9 +6117,9 @@ static void gen_opcode (unsigned int opcode) } else { printf("\tm68k_do_bsr (nextpc, s);\n"); } - if (using_exception_3 && cpu_level <= 1) { + if (using_exception_3 && cpu_level == 0) { printf("\tif (%s & 1) {\n", getpc); - printf("\t\texception3b(opcode, %s, 0, 1, %s);\n", getpc, getpc); + printf("\t\texception3b(opcode, %s, false, true, %s);\n", getpc, getpc); write_return_cycles("\t\t", 0); printf("\t}\n"); } @@ -6100,7 +6142,7 @@ static void gen_opcode (unsigned int opcode) if (cpu_level < 2) { addcycles000 (2); printf("\tif (cctrue(%d)) {\n", curi->cc); - printf("\t\texception3i (opcode, %s + 1);\n", getpc); + printf("\t\texception3i(opcode, %s + 1);\n", getpc); write_return_cycles("\t\t", 0); printf("\t}\n"); sync_m68k_pc (); @@ -6117,14 +6159,20 @@ static void gen_opcode (unsigned int opcode) addcycles000 (2); if (using_exception_3 && cpu_level >= 4) { printf("\tif (src & 1) {\n"); - printf("\t\texception3i (opcode, %s + 2 + (uae_s32)src);\n", getpc); + printf("\t\texception3i(opcode, %s + 2 + (uae_s32)src);\n", getpc); write_return_cycles("\t\t", 0); printf("\t}\n"); } printf("\tif (cctrue(%d)) {\n", curi->cc); if (using_exception_3 && cpu_level < 4) { printf("\t\tif (src & 1) {\n"); - printf("\t\t\texception3i (opcode, %s + 2 + (uae_s32)src);\n", getpc); + if (cpu_level == 1) { + printf("\t\tuaecptr oldpc = %s;\n", getpc); + incpc("((uae_s32)src + 2) & ~1"); + printf("\t%s(0);\n", prefetch_word); + setpc("oldpc"); + } + printf("\t\t\texception3i(opcode, %s + 2 + (uae_s32)src);\n", getpc); write_return_cycles("\t\t\t", 0); printf("\t\t}\n"); } diff --git a/newcpu_common.cpp b/newcpu_common.cpp index 83a3d9dc..8403991a 100644 --- a/newcpu_common.cpp +++ b/newcpu_common.cpp @@ -1364,7 +1364,7 @@ void Exception_build_stack_frame(uae_u32 oldpc, uae_u32 currpc, uae_u32 ssw, int m68k_areg(regs, 7) -= 4; x_put_long(m68k_areg(regs, 7), regs.mmu_effective_addr); break; - case 0x8: // address error (68010) + case 0x8: // bus/address error (68010) { uae_u16 in = regs.read_buffer; uae_u16 out = regs.write_buffer;