From 580b3f2dadb06f2bf0a701740d3120f6319ebda7 Mon Sep 17 00:00:00 2001 From: Toni Wilen Date: Sat, 16 May 2020 22:16:10 +0300 Subject: [PATCH] 68000 write bus error stack frame PC field fix. --- cputest.cpp | 6 ++-- gencpu.cpp | 98 ++++++++++++++++++++++++++++++----------------------- 2 files changed, 60 insertions(+), 44 deletions(-) diff --git a/cputest.cpp b/cputest.cpp index e087fe5b..5db67705 100644 --- a/cputest.cpp +++ b/cputest.cpp @@ -1188,20 +1188,22 @@ static void exception2_fetch_common(uae_u32 opcode, int offset) } } -void exception2_fetch(uae_u32 opcode, int offset) +void exception2_fetch(uae_u32 opcode, int offset, int pcoffset) { exception2_fetch_common(opcode, offset); regs.pc = test_exception_addr; + regs.pc += pcoffset; doexcstack(); } -void exception2_fetch_opcode(uae_u32 opcode, int offset) +void exception2_fetch_opcode(uae_u32 opcode, int offset, int pcoffset) { exception2_fetch_common(opcode, offset); if (currprefs.cpu_model == 68010) { test_exception_3_di = -1; } regs.pc = test_exception_addr; + regs.pc += pcoffset; doexcstack(); } diff --git a/gencpu.cpp b/gencpu.cpp index 67a6f8c8..5531df2c 100644 --- a/gencpu.cpp +++ b/gencpu.cpp @@ -2208,7 +2208,7 @@ static void check_bus_error(const char *name, int offset, int write, int size, c bus_error_cycles = 0; } - if (pcoffset < 0) { + if (pcoffset == -1) { incpc("%d", m68k_pc_offset + 2); } else if (exception_pc_offset + exception_pc_offset_extra + pcoffset) { incpc("%d", exception_pc_offset + exception_pc_offset_extra + pcoffset); @@ -3777,6 +3777,13 @@ static void genamodedual(struct instr *curi, amodes smode, const char *sreg, wor 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]; + int pcoffset = (flags & GF_MOVE) ? 0 : 2; + + if (flags & GF_PCM2) { + pcoffset -= 2; + } else if (flags & GF_PCP2) { + pcoffset += 2; + } exception_pc_offset = m68k_pc_offset; @@ -3874,21 +3881,21 @@ static void genastore_2 (const char *from, amodes mode, const char *reg, wordsiz case sz_byte: out("%s(%sa, %s);\n", dstbx, to, from); count_writew++; - check_bus_error(to, 0, 1, 0, from, 1, 0); + check_bus_error(to, 0, 1, 0, from, 1, pcoffset); break; case sz_word: if (cpu_level < 2 && (mode == PC16 || mode == PC8r)) term(); out("%s(%sa, %s);\n", dstwx, to, from); count_writew++; - check_bus_error(to, 0, 1, 1, from, 1, 0); + check_bus_error(to, 0, 1, 1, from, 1, pcoffset); break; case sz_long: if (cpu_level < 2 && (mode == PC16 || mode == PC8r)) term(); out("%s(%sa, %s);\n", dstlx, to, from); count_writel++; - check_bus_error(to, 0, 1, 2, from, 1, 0); + check_bus_error(to, 0, 1, 2, from, 1, pcoffset); break; default: term(); @@ -3899,7 +3906,7 @@ static void genastore_2 (const char *from, amodes mode, const char *reg, wordsiz set_last_access(); out("%s(%sa, %s);\n", dstbx, to, from); count_writew++; - check_bus_error(to, 0, 1, 0, from, 1, 0); + check_bus_error(to, 0, 1, 0, from, 1, pcoffset); break; case sz_word: if (cpu_level < 2 && (mode == PC16 || mode == PC8r)) @@ -3907,7 +3914,7 @@ static void genastore_2 (const char *from, amodes mode, const char *reg, wordsiz set_last_access(); out("%s(%sa, %s);\n", dstwx, to, from); count_writew++; - check_bus_error(to, 0, 1, 1, from, 1, 0); + check_bus_error(to, 0, 1, 1, from, 1, pcoffset); break; case sz_long: if (cpu_level < 2 && (mode == PC16 || mode == PC8r)) @@ -3915,7 +3922,7 @@ static void genastore_2 (const char *from, amodes mode, const char *reg, wordsiz if (store_dir) { out("%s(%sa + 2, %s);\n", dstwx, to, from); count_writew++; - check_bus_error(to, 2, 1, 1, from, 1, 0); + check_bus_error(to, 2, 1, 1, from, 1, pcoffset); if (flags & GF_SECONDWORDSETFLAGS) { genflags(flag_logical, g_instr->size, "src", "", ""); } @@ -3928,19 +3935,19 @@ static void genastore_2 (const char *from, amodes mode, const char *reg, wordsiz out("%s(%sa, %s >> 16);\n", dstwx, to, from); sprintf(tmp, "%s >> 16", from); count_writew++; - check_bus_error(to, 0, 1, 1, tmp, 1, 0); + check_bus_error(to, 0, 1, 1, tmp, 1, pcoffset); } else { out("%s(%sa, %s >> 16);\n", dstwx, to, from); sprintf(tmp, "%s >> 16", from); count_writew++; - check_bus_error(to, 0, 1, 1, tmp, 1, 0); + check_bus_error(to, 0, 1, 1, tmp, 1, pcoffset); if (flags & GF_SECONDWORDSETFLAGS) { genflags(flag_logical, g_instr->size, "src", "", ""); } set_last_access(); out("%s(%sa + 2, %s);\n", dstwx, to, from); count_writew++; - check_bus_error(to, 2, 1, 1, from, 1, 0); + check_bus_error(to, 2, 1, 1, from, 1, pcoffset); } break; default: @@ -3952,7 +3959,7 @@ static void genastore_2 (const char *from, amodes mode, const char *reg, wordsiz set_last_access(); out("%s(%sa, %s);\n", dstbx, to, from); count_writew++; - check_bus_error(to, 0, 1, 0, from, 1, 0); + check_bus_error(to, 0, 1, 0, from, 1, pcoffset); break; case sz_word: if (cpu_level < 2 && (mode == PC16 || mode == PC8r)) @@ -3960,7 +3967,7 @@ static void genastore_2 (const char *from, amodes mode, const char *reg, wordsiz set_last_access(); out("%s(%sa, %s);\n", dstwx, to, from); count_writew++; - check_bus_error(to, 0, 1, 1, from, 1, 0); + check_bus_error(to, 0, 1, 1, from, 1, pcoffset); break; case sz_long: if (cpu_level < 2 && (mode == PC16 || mode == PC8r)) @@ -3968,7 +3975,7 @@ static void genastore_2 (const char *from, amodes mode, const char *reg, wordsiz if (store_dir) { out("%s(%sa + 2, %s);\n", dstwx, to, from); count_writew++; - check_bus_error(to, 2, 1, 1, from, 1, 0); + check_bus_error(to, 2, 1, 1, from, 1, pcoffset); if (flags & GF_SECONDWORDSETFLAGS) { genflags(flag_logical, g_instr->size, "src", "", ""); } @@ -3980,19 +3987,19 @@ static void genastore_2 (const char *from, amodes mode, const char *reg, wordsiz out("%s(%sa, %s >> 16); \n", dstwx, to, from); sprintf(tmp, "%s >> 16", from); count_writew++; - check_bus_error(to, 0, 1, 1, tmp, 1, 0); + check_bus_error(to, 0, 1, 1, tmp, 1, pcoffset); } else { out("%s(%sa, %s >> 16);\n", dstwx, to, from); sprintf(tmp, "%s >> 16", from); count_writew++; - check_bus_error(to, 0, 1, 1, tmp, 1, 0); + check_bus_error(to, 0, 1, 1, tmp, 1, pcoffset); if (flags & GF_SECONDWORDSETFLAGS) { genflags(flag_logical, g_instr->size, "src", "", ""); } set_last_access(); out("%s(%sa + 2, %s); \n", dstwx, to, from); count_writew++; - check_bus_error(to, 2, 1, 1, from, 1, 0); + check_bus_error(to, 2, 1, 1, from, 1, pcoffset); } break; default: @@ -4003,14 +4010,14 @@ static void genastore_2 (const char *from, amodes mode, const char *reg, wordsiz case sz_byte: out("%s(%sa, %s);\n", dstbx, to, from); count_writew++; - check_bus_error(to, 0, 1, 0, from, 1, 0); + check_bus_error(to, 0, 1, 0, from, 1, pcoffset); break; case sz_word: if (cpu_level < 2 && (mode == PC16 || mode == PC8r)) term(); out("%s(%sa, %s);\n", dstwx, to, from); count_writew++; - check_bus_error(to, 0, 1, 1, from, 1, 0); + check_bus_error(to, 0, 1, 1, from, 1, pcoffset); break; case sz_long: if (cpu_level < 2 && (mode == PC16 || mode == PC8r)) @@ -4021,7 +4028,7 @@ static void genastore_2 (const char *from, amodes mode, const char *reg, wordsiz } out("%s(%sa, %s);\n", dstlx, to, from); count_writel++; - check_bus_error(to, 0, 1, 2, from, 1, 0); + check_bus_error(to, 0, 1, 2, from, 1, pcoffset); break; default: term(); @@ -4581,6 +4588,7 @@ static void genmovemle_ce (uae_u16 opcode) { int size = table68k[opcode].size == sz_long ? 4 : 2; amodes mode = table68k[opcode].dmode; + int pcoffset = 0; out("uae_u16 mask = %s;\n", gen_nextiword(mode >= Ad8r && mode != absw && mode != absl ? GF_PCM2 : ((mode == Ad16 || mode == PC16 || mode == absw || mode == absl) ? 0 : GF_PCP2))); do_instruction_buserror(); @@ -4589,6 +4597,9 @@ static void genmovemle_ce (uae_u16 opcode) } strcpy(bus_error_code2, "pcoffset += 2;\n"); genamode(NULL, mode, "dstreg", table68k[opcode].size, "src", 2, 1, GF_AA | GF_MOVE | GF_REVERSE | GF_REVERSE2 | (mode == absl ? GF_PCM2 : GF_PCP2)); + if (mode >= Ad16) { + pcoffset = 2; + } if (table68k[opcode].size == sz_long) { if (mode == Apdi) { out("uae_u16 amask = mask & 0xff, dmask = (mask >> 8) & 0xff;\n"); @@ -4596,20 +4607,20 @@ static void genmovemle_ce (uae_u16 opcode) out("while (amask) {\n"); out("%s(srca - 2, m68k_areg(regs, movem_index2[amask]));\n", dstw); addcycles000_nonce(4); - check_bus_error("src", -2, 1, 1, "m68k_areg(regs, movem_index2[amask])", 1, 0); + check_bus_error("src", -2, 1, 1, "m68k_areg(regs, movem_index2[amask])", 1, pcoffset); out("%s(srca - 4, m68k_areg(regs, movem_index2[amask]) >> 16);\n", dstw); addcycles000_nonce(4); - check_bus_error("src", -4, 1, 1, "m68k_areg(regs, movem_index2[amask]) >> 16", 1, 0); + check_bus_error("src", -4, 1, 1, "m68k_areg(regs, movem_index2[amask]) >> 16", 1, pcoffset); out("srca -= %d;\n", size); out("amask = movem_next[amask];\n"); out("}\n"); out("while (dmask) {\n"); out("%s(srca - 2, m68k_dreg(regs, movem_index2[dmask]));\n", dstw); addcycles000_nonce(4); - check_bus_error("src", -2, 1, 1, "m68k_dreg(regs, movem_index2[dmask])", 1, 0); + check_bus_error("src", -2, 1, 1, "m68k_dreg(regs, movem_index2[dmask])", 1, pcoffset); out("%s(srca - 4, m68k_dreg(regs, movem_index2[dmask]) >> 16);\n", dstw); addcycles000_nonce(4); - check_bus_error("src", -4, 1, 1, "m68k_dreg(regs, movem_index2[dmask]) >> 16", 1, 0); + check_bus_error("src", -4, 1, 1, "m68k_dreg(regs, movem_index2[dmask]) >> 16", 1, pcoffset); out("srca -= %d;\n", size); out("dmask = movem_next[dmask];\n"); out("}\n"); @@ -4620,20 +4631,20 @@ static void genmovemle_ce (uae_u16 opcode) out("while (dmask) {\n"); out("%s(srca, m68k_dreg(regs, movem_index1[dmask]) >> 16);\n", dstw); addcycles000_nonce(4); - check_bus_error("src", 0, 1, 1, "m68k_dreg(regs, movem_index1[dmask]) >> 16", 1, 0); + check_bus_error("src", 0, 1, 1, "m68k_dreg(regs, movem_index1[dmask]) >> 16", 1, pcoffset); out("%s(srca + 2, m68k_dreg(regs, movem_index1[dmask]));\n", dstw); addcycles000_nonce(4); - check_bus_error("src", 2, 1, 1, "m68k_dreg(regs, movem_index1[dmask])", 1, 0); + check_bus_error("src", 2, 1, 1, "m68k_dreg(regs, movem_index1[dmask])", 1, pcoffset); out("srca += %d;\n", size); out("dmask = movem_next[dmask];\n"); out("}\n"); out("while (amask) {\n"); out("%s(srca, m68k_areg(regs, movem_index1[amask]) >> 16);\n", dstw); addcycles000_nonce(4); - check_bus_error("src", 0, 1, 1, "m68k_areg(regs, movem_index1[amask]) >> 16", 1, 0); + check_bus_error("src", 0, 1, 1, "m68k_areg(regs, movem_index1[amask]) >> 16", 1, pcoffset); out("%s(srca + 2, m68k_areg(regs, movem_index1[amask]));\n", dstw); addcycles000_nonce(4); - check_bus_error("src", 2, 1, 1, "m68k_areg(regs, movem_index1[amask])", 1, 0); + check_bus_error("src", 2, 1, 1, "m68k_areg(regs, movem_index1[amask])", 1, pcoffset); out("srca += %d;\n", size); out("amask = movem_next[amask];\n"); out("}\n"); @@ -4646,14 +4657,14 @@ static void genmovemle_ce (uae_u16 opcode) out("srca -= %d;\n", size); out("%s(srca, m68k_areg(regs, movem_index2[amask]));\n", dstw); addcycles000_nonce(4); - check_bus_error("src", 0, 1, 1, "m68k_areg(regs, movem_index2[amask])", 1, 0); + check_bus_error("src", 0, 1, 1, "m68k_areg(regs, movem_index2[amask])", 1, pcoffset); out("amask = movem_next[amask];\n"); out("}\n"); out("while (dmask) {\n"); out("srca -= %d;\n", size); out("%s(srca, m68k_dreg(regs, movem_index2[dmask]));\n", dstw); addcycles000_nonce(4); - check_bus_error("src", 0, 1, 1, "m68k_dreg(regs, movem_index2[dmask])", 1, 0); + check_bus_error("src", 0, 1, 1, "m68k_dreg(regs, movem_index2[dmask])", 1, pcoffset); out("dmask = movem_next[dmask];\n"); out("}\n"); out("m68k_areg(regs, dstreg) = srca;\n"); @@ -4663,14 +4674,14 @@ static void genmovemle_ce (uae_u16 opcode) out("while (dmask) {\n"); out("%s(srca, m68k_dreg(regs, movem_index1[dmask]));\n", dstw); addcycles000_nonce(4); - check_bus_error("src", 0, 1, 1, "m68k_dreg(regs, movem_index1[dmask])", 1, 0); + check_bus_error("src", 0, 1, 1, "m68k_dreg(regs, movem_index1[dmask])", 1, pcoffset); out("srca += %d;\n", size); out("dmask = movem_next[dmask];\n"); out("}\n"); out("while (amask) {\n"); out("%s(srca, m68k_areg(regs, movem_index1[amask]));\n", dstw); addcycles000_nonce(4); - check_bus_error("src", 0, 1, 1, "m68k_areg(regs, movem_index1[amask])", 1, 0); + check_bus_error("src", 0, 1, 1, "m68k_areg(regs, movem_index1[amask])", 1, pcoffset); out("srca += %d;\n", size); out("amask = movem_next[amask];\n"); out("}\n"); @@ -5449,6 +5460,7 @@ static void gen_opcode (unsigned int opcode) addcycles000(2); next_level_000(); } + exception_pc_offset_extra = 0; if (curi->size == sz_long && !isreg(curi->dmode)) { // write addr + 2 // prefetch @@ -5494,6 +5506,7 @@ static void gen_opcode (unsigned int opcode) if (isreg (curi->smode)) { addcycles000(2); } + exception_pc_offset_extra = 0; genastore("newv", curi->dmode, "dstreg", curi->size, "dst"); break; case i_ADD: @@ -5644,6 +5657,7 @@ static void gen_opcode (unsigned int opcode) addcycles000(2); next_level_000(); } + exception_pc_offset_extra = 0; if (curi->size == sz_long && !isreg(curi->dmode)) { // write addr + 2 // prefetch @@ -5690,6 +5704,7 @@ static void gen_opcode (unsigned int opcode) if (isreg (curi->smode)) { addcycles000(2); } + exception_pc_offset_extra = 0; genastore("newv", curi->dmode, "dstreg", curi->size, "dst"); break; case i_NEG: @@ -6024,16 +6039,16 @@ static void gen_opcode (unsigned int opcode) } else { out("%s(mempa, src >> 24);\n", dstb); count_writew++; - check_bus_error("memp", 0, 1, 0, "src >> 24", 1 | 0x10000, 0); + check_bus_error("memp", 0, 1, 0, "src >> 24", 1 | 0x10000, 2); out("%s(mempa + 2, src >> 16);\n", dstb); count_writew++; - check_bus_error("memp", 2, 1, 0, "src >> 16", 1, 0); + check_bus_error("memp", 2, 1, 0, "src >> 16", 1, 2); out("%s(mempa + 4, src >> 8);\n", dstb); count_writew++; - check_bus_error("memp", 4, 1, 0, "src >> 8", 1 | 0x10000, 0); + check_bus_error("memp", 4, 1, 0, "src >> 8", 1 | 0x10000, 2); out("%s(mempa + 6, src); \n", dstb); count_writew++; - check_bus_error("memp", 6, 1, 0, "src", 1, 0); + check_bus_error("memp", 6, 1, 0, "src", 1, 2); } fill_prefetch_next_t(); next_level_000(); @@ -6295,19 +6310,18 @@ static void gen_opcode (unsigned int opcode) bus_error_code[0] = 0; bus_error_code2[0] = 0; - int pcoffset = 0; + storeflags &= ~(GF_PCM2 | GF_PCP2); if (curi->smode >= Aind && curi->smode < imm && curi->dmode == absl) { - // address/bus error stacked PC is 2 less - pcoffset -= 2; + storeflags |= GF_PCM2; + } else if (curi->dmode == Apdi) { + storeflags |= GF_PCP2; } - exception_pc_offset += pcoffset; // MOVE EA,-(An) long writes are always reversed. Reads are normal. if (curi->dmode == Apdi && curi->size == sz_long) { - genastore_2("src", curi->dmode, "dstreg", curi->size, "dst", 1, storeflags | GF_EXC3); + genastore_2("src", curi->dmode, "dstreg", curi->size, "dst", 1, storeflags | GF_EXC3 | GF_MOVE); } else { - genastore_2("src", curi->dmode, "dstreg", curi->size, "dst", 0, storeflags | GF_EXC3); + genastore_2("src", curi->dmode, "dstreg", curi->size, "dst", 0, storeflags | GF_EXC3 | GF_MOVE); } - exception_pc_offset -= pcoffset; sync_m68k_pc(); if (dualprefetch) { fill_prefetch_full_000(curi->mnemo == i_MOVE ? 2 : 1); -- 2.47.3