From: Toni Wilen Date: Sat, 4 Jan 2020 13:42:41 +0000 (+0200) Subject: Basic bus error support added to non-prefetch CPU modes. X-Git-Tag: 4400~197 X-Git-Url: https://git.unchartedbackwaters.co.uk/w/?a=commitdiff_plain;h=dbf04db95de7640b8bdaf4ea2773d40b5dfc11d6;p=francis%2Fwinuae.git Basic bus error support added to non-prefetch CPU modes. --- diff --git a/gencpu.cpp b/gencpu.cpp index df055899..60b6afb1 100644 --- a/gencpu.cpp +++ b/gencpu.cpp @@ -580,6 +580,7 @@ static void do_instruction_buserror(void) { if (!using_bus_error) return; + if (bus_error_text[0]) { printf("\tif(cpu_bus_error) {\n"); if (bus_error_code[0]) @@ -600,13 +601,14 @@ static void check_bus_error_ins(int offset) } else { opcode = "opcode"; } - sprintf(bus_error_text, "\t\texception2_fetch(%s, m68k_getpci() + %d);\n", opcode, offset); + sprintf(bus_error_text, "\t\texception2_fetch(%s, %d);\n", opcode, offset); } static void check_prefetch_bus_error(int offset, int secondprefetchmode) { if (!using_bus_error) return; + if (offset < 0) { if (offset == -1) offset = 0; @@ -849,12 +851,14 @@ static void fill_prefetch_bcc(void) { if (!using_prefetch) return; + if (using_bus_error) { copy_opcode(); if (cpu_level == 0) { printf("\tif(regs.t1) opcode |= 0x10000;\n"); } } + printf("\t%s(%d);\n", prefetch_word, m68k_pc_offset + 2); count_read++; insn_n_cycles += 4; @@ -984,6 +988,7 @@ static void fill_prefetch_full_000_special(void) { if (!using_prefetch) return; + printf("\t%s(%d);\n", prefetch_word, 0); count_read++; insn_n_cycles += 2; @@ -1733,9 +1738,33 @@ static void check_bus_error(const char *name, int offset, int write, int size, c { int mnemo = g_instr->mnemo; - // check possible bus error (if 68000/010 and enabled) if (!using_bus_error) return; + + // basic support + if ((!using_prefetch && !using_ce) || cpu_level >= 2) { + + fc &= 7; + printf("\tif(cpu_bus_error) {\n"); + 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); + } + write_return_cycles("\t\t", 0); + printf("\t}\n"); + return; + } + + // 68000/68010 bus error + if (cpu_level >= 2) + return; if (!using_prefetch && !using_ce) return; @@ -1750,7 +1779,7 @@ static void check_bus_error(const char *name, int offset, int write, int size, c if (fc == 2) { - printf("\t\texception2_fetch(opcode, m68k_getpci() + %d);\n", offset); + printf("\t\texception2_fetch(opcode, %d);\n", offset); } else { @@ -3007,9 +3036,24 @@ static void genamode2x (amodes mode, const char *reg, wordsizes size, const char } } else if (using_ce020 || using_prefetch_020) { switch (size) { - case sz_byte: insn_n_cycles += 4; printf("\tuae_s8 %s = %s(%sa);\n", name, srcbx, name); count_read++; break; - case sz_word: insn_n_cycles += 4; printf("\tuae_s16 %s = %s(%sa);\n", name, srcwx, name); count_read++; break; - case sz_long: insn_n_cycles += 8; printf("\tuae_s32 %s = %s(%sa);\n", name, srclx, name); count_read += 2; break; + case sz_byte: + insn_n_cycles += 4; + printf("\tuae_s8 %s = %s(%sa);\n", name, srcbx, name); + count_read++; + 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, NULL, 1); + break; + case sz_long: + insn_n_cycles += 8; + printf("\tuae_s32 %s = %s(%sa);\n", name, srclx, name); + count_read += 2; + check_bus_error(name, 0, 0, 2, NULL, 1); + break; default: term (); } } else if (using_ce || using_prefetch) { @@ -3052,9 +3096,24 @@ static void genamode2x (amodes mode, const char *reg, wordsizes size, const char } } else { switch (size) { - case sz_byte: insn_n_cycles += 4; printf("\tuae_s8 %s = %s(%sa);\n", name, srcbx, name); count_read++; break; - case sz_word: insn_n_cycles += 4; printf("\tuae_s16 %s = %s(%sa);\n", name, srcwx, name); count_read++; break; - case sz_long: insn_n_cycles += 8; printf("\tuae_s32 %s = %s(%sa);\n", name, srclx, name); count_read += 2; break; + case sz_byte: + insn_n_cycles += 4; + printf("\tuae_s8 %s = %s(%sa);\n", name, srcbx, name); + count_read++; + 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, NULL, 1); + break; + case sz_long: + insn_n_cycles += 8; + printf("\tuae_s32 %s = %s(%sa);\n", name, srclx, name); + count_read += 2; + check_bus_error(name, 0, 0, 2, NULL, 1); + break; default: term (); } } @@ -3272,18 +3331,21 @@ static void genastore_2 (const char *from, amodes mode, const char *reg, wordsiz case sz_byte: printf("\t%s(%sa, %s);\n", dstbx, to, from); count_write++; + check_bus_error(to, 0, 1, 0, from, 1); break; case sz_word: if (cpu_level < 2 && (mode == PC16 || mode == PC8r)) term (); printf("\t%s(%sa, %s);\n", dstwx, to, from); count_write++; + check_bus_error(to, 0, 1, 1, from, 1); break; case sz_long: if (cpu_level < 2 && (mode == PC16 || mode == PC8r)) term (); printf("\t%s(%sa, %s);\n", dstlx, to, from); count_write += 2; + check_bus_error(to, 0, 1, 2, from, 1); break; default: term (); @@ -3395,6 +3457,7 @@ 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, 0, from, 1); break; case sz_word: insn_n_cycles += 4; @@ -3402,6 +3465,7 @@ static void genastore_2 (const char *from, amodes mode, const char *reg, wordsiz term (); printf("\t%s(%sa, %s);\n", dstwx, to, from); count_write++; + check_bus_error(to, 0, 1, 1, from, 1); break; case sz_long: insn_n_cycles += 8; @@ -3409,6 +3473,7 @@ static void genastore_2 (const char *from, amodes mode, const char *reg, wordsiz term (); printf("\t%s(%sa, %s);\n", dstlx, to, from); count_write += 2; + check_bus_error(to, 0, 1, 2, from, 1); break; default: term (); @@ -3744,12 +3809,16 @@ static void genmovemel (uae_u16 opcode) movem_mmu040 (getcode, size, false, table68k[opcode].dmode == Aipi, false, opcode); } else { printf("\twhile (dmask) {\n"); - printf("\t\tm68k_dreg(regs, movem_index1[dmask]) = %s; srca += %d; dmask = movem_next[dmask];\n", getcode, size); - //addcycles_ce020 (1); + printf("\t\tm68k_dreg(regs, movem_index1[dmask]) = %s;\n", getcode); + check_bus_error("src", 0, 0, table68k[opcode].size, NULL, 1); + printf("\t\tsrca += %d;\n", size); + printf("\t\tdmask = movem_next[dmask];\n"); printf("\t}\n"); printf("\twhile (amask) {\n"); - printf("\t\tm68k_areg(regs, movem_index1[amask]) = %s; srca += %d; amask = movem_next[amask];\n", getcode, size); - //addcycles_ce020 (1); + printf("\t\tm68k_areg(regs, movem_index1[amask]) = %s;\n", getcode); + check_bus_error("src", 0, 0, table68k[opcode].size, NULL, 1); + printf("\t\tsrca += %d;\n", size); + printf("\t\tamask = movem_next[amask];\n"); printf("\t}\n"); if (table68k[opcode].dmode == Aipi) { printf("\tm68k_areg(regs, dstreg) = srca;\n"); @@ -3863,22 +3932,40 @@ static void genmovemle (uae_u16 opcode) printf("\twhile (amask) {\n"); printf("\t\tsrca -= %d;\n", size); - printf("\t\tif (!type || movem_index2[amask] != dstreg)\n"); + printf("\t\tif (!type || movem_index2[amask] != dstreg) {\n"); printf("\t\t\t%s, m68k_areg(regs, movem_index2[amask]));\n", putcode); - printf("\t\telse\n"); + check_bus_error("src", 0, 1, table68k[opcode].size, "m68k_areg(regs, movem_index2[amask])", 1); + printf("\t\t} else {\n"); printf("\t\t\t%s, m68k_areg(regs, movem_index2[amask]) - %d);\n", putcode, size); - + if (size == 4) { + check_bus_error("src", 0, 1, table68k[opcode].size, "m68k_areg(regs, movem_index2[amask]) - 4", 1); + } else { + check_bus_error("src", 0, 1, table68k[opcode].size, "m68k_areg(regs, movem_index2[amask]) - 2", 1); + } + printf("\t\t}\n"); printf("\t\tamask = movem_next[amask];\n"); printf("\t}\n"); - printf("\twhile (dmask) { srca -= %d; %s, m68k_dreg(regs, movem_index2[dmask])); dmask = movem_next[dmask]; }\n", - size, putcode); + printf("\twhile (dmask) {\n"); + printf("\t\tsrca -= %d;\n", size); + printf("\t\t%s, m68k_dreg(regs, movem_index2[dmask]));\n", putcode); + check_bus_error("src", 0, 1, table68k[opcode].size, "m68k_dreg(regs, movem_index2[dmask])", 1); + printf("\t\tdmask = movem_next[dmask];\n"); + printf("\t}\n"); printf("\tm68k_areg(regs, dstreg) = srca;\n"); } else { printf("\tuae_u16 dmask = mask & 0xff, amask = (mask >> 8) & 0xff;\n"); - printf("\twhile (dmask) { %s, m68k_dreg(regs, movem_index1[dmask])); srca += %d; dmask = movem_next[dmask]; }\n", - putcode, size); - printf("\twhile (amask) { %s, m68k_areg(regs, movem_index1[amask])); srca += %d; amask = movem_next[amask]; }\n", - putcode, size); + printf("\twhile (dmask) {\n"); + printf("\t\t%s, m68k_dreg(regs, movem_index1[dmask]));\n", putcode); + check_bus_error("src", 0, 1, table68k[opcode].size, "m68k_dreg(regs, movem_index1[dmask])", 1); + printf("\t\tsrca += %d;\n", size); + printf("\t\tdmask = movem_next[dmask];\n"); + printf("\t}\n"); + printf("\twhile (amask) {\n"); + printf("\t\t%s, m68k_areg(regs, movem_index1[amask]));\n", putcode); + check_bus_error("src", 0, 1, table68k[opcode].size, "m68k_areg(regs, movem_index1[amask])", 1); + printf("\t\tsrca += %d;\n", size); + printf("\t\tamask = movem_next[amask];\n"); + printf("\t}\n"); } } count_ncycles++; @@ -6525,7 +6612,7 @@ bccl_not68020: printf("\tint val = cctrue(%d) ? 0xff : 0x00;\n", curi->cc); if (using_ce) printf("\tint cycles = val ? 2 : 0;\n"); - if (using_bus_error) { + if (using_bus_error && cpu_level <= 1) { printf("\tif (!val) {\n"); genastore("val", curi->smode, "srcreg", curi->size, "src"); printf("\t}\n"); diff --git a/include/newcpu.h b/include/newcpu.h index 4fef3385..d81739fc 100644 --- a/include/newcpu.h +++ b/include/newcpu.h @@ -735,7 +735,7 @@ 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); 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 exception2_fetch(uae_u32 opcode, int offset); extern void m68k_reset (void); extern void cpureset (void); extern void cpu_halt (int id); diff --git a/newcpu.cpp b/newcpu.cpp index 7ec25511..5cca4eb6 100644 --- a/newcpu.cpp +++ b/newcpu.cpp @@ -2584,10 +2584,11 @@ kludge_me_do: newpc |= x_get_word (regs.vbr + 4 * vector_nr + 2); // read low address exception_in_exception = 0; if (newpc & 1) { - if (nr == 2 || nr == 3) - cpu_halt (CPU_HALT_DOUBLE_FAULT); - else - exception3_notinstruction(regs.ir, newpc); + if (nr == 2 || nr == 3) { + cpu_halt(CPU_HALT_DOUBLE_FAULT); + return; + } + exception3_notinstruction(regs.ir, newpc); return; } m68k_setpc (newpc); @@ -2595,11 +2596,31 @@ kludge_me_do: regs.intmask = nr - 24; branch_stack_push(currpc, currpc); regs.ir = x_get_word (m68k_getpc ()); // prefetch 1 +#if BUS_ERROR_EMULATION + if (cpu_bus_error) { + if (nr == 2 || nr == 3) { + cpu_halt(CPU_HALT_DOUBLE_FAULT); + return; + } + exception2_fetch(regs.irc, 0); + return; + } +#endif regs.ird = regs.ir; x_do_cycles (2 * cpucycleunit); regs.ipl_pin = intlev(); ipl_fetch(); regs.irc = x_get_word (m68k_getpc () + 2); // prefetch 2 +#if BUS_ERROR_EMULATION + if (cpu_bus_error) { + if (nr == 2 || nr == 3) { + cpu_halt(CPU_HALT_DOUBLE_FAULT); + return; + } + exception2_fetch(regs.ir, 2); + return; + } +#endif #ifdef JIT set_special (SPCFLAG_END_COMPILE); #endif @@ -7004,8 +7025,9 @@ void exception2_write(uae_u32 opcode, uaecptr addr, int size, uae_u32 val, int f Exception(2); } -void exception2_fetch(uae_u32 opcode, uaecptr addr) +void exception2_fetch(uae_u32 opcode, int offset) { + uaecptr addr = m68k_getpc() + offset; exception2_setup(opcode, addr, true, 1, 2); last_di_for_exception_3 = 0; Exception(2);