From: Toni Wilen Date: Tue, 18 Jun 2019 17:26:32 +0000 (+0300) Subject: 68000/010 modes didn't check BSR/JSR/RTS odd stack pointer. 68010 incorrectly accepte... X-Git-Tag: 4300~195 X-Git-Url: https://git.unchartedbackwaters.co.uk/w/?a=commitdiff_plain;h=5f8452bac6eca82d4320b8a5105ded75be11a414;p=francis%2Fwinuae.git 68000/010 modes didn't check BSR/JSR/RTS odd stack pointer. 68010 incorrectly accepted 68020+ stack frame types 1 and 2. Partial 68010 bus/address error stack frame support. --- diff --git a/gencpu.cpp b/gencpu.cpp index 5679b9d1..01be24c3 100644 --- a/gencpu.cpp +++ b/gencpu.cpp @@ -3957,6 +3957,7 @@ static void gen_opcode (unsigned int opcode) addop_ce020 (curi, 0); next_level_000 (); if (cpu_level == 0) { + // 68000 genamode (NULL, Aipi, "7", sz_word, "sr", 1, 0, GF_NOREFILL); genamode (NULL, Aipi, "7", sz_long, "pc", 1, 0, GF_NOREFILL); printf("\tuaecptr oldpc = %s;\n", getpc); @@ -3969,7 +3970,8 @@ static void gen_opcode (unsigned int opcode) printf("\tbranch_stack_pop_rte(oldpc);\n"); makefromsr(); } else if (cpu_level == 1 && using_prefetch) { - int old_brace_level = n_braces; + // 68010 + int old_brace_level = n_braces; printf("\tuaecptr oldpc = %s;\n", getpc); printf ("\tuae_u16 newsr; uae_u32 newpc;\n"); printf ("\tfor (;;) {\n"); @@ -3985,7 +3987,7 @@ static void gen_opcode (unsigned int opcode) printf ("\t\tnewsr = sr; newpc = pc;\n"); printf ("\t\tif (frame == 0x0) { m68k_areg (regs, 7) += offset; break; }\n"); printf ("\t\telse if (frame == 0x8) { m68k_areg (regs, 7) += offset + 50; break; }\n"); - printf ("\t\telse { m68k_areg (regs, 7) += offset; Exception_cpu(14); goto %s; }\n", endlabelstr); + printf ("\t\telse { Exception_cpu(14); goto %s; }\n", endlabelstr); printf ("\t\tregs.sr = newsr; MakeFromSR ();\n}\n"); pop_braces (old_brace_level); printf ("\tregs.sr = newsr;\n"); @@ -4015,24 +4017,33 @@ static void gen_opcode (unsigned int opcode) printf ("\t\tnewsr = sr; newpc = pc;\n"); addcycles_ce020 (6); printf ("\t\tif (frame == 0x0) { m68k_areg (regs, 7) += offset; break; }\n"); - printf ("\t\telse if (frame == 0x1) { m68k_areg (regs, 7) += offset; }\n"); - printf ("\t\telse if (frame == 0x2) { m68k_areg (regs, 7) += offset + 4; break; }\n"); + if (cpu_level >= 2) { + // 68020+ + printf ("\t\telse if (frame == 0x1) { m68k_areg (regs, 7) += offset; }\n"); + printf ("\t\telse if (frame == 0x2) { m68k_areg (regs, 7) += offset + 4; break; }\n"); + } if (cpu_level >= 4) { + // 68040+ printf ("\t\telse if (frame == 0x3) { m68k_areg (regs, 7) += offset + 4; break; }\n"); } if (using_mmu == 68060) { printf ("\t\telse if (frame == 0x4) { m68k_do_rte_mmu060 (a); m68k_areg (regs, 7) += offset + 8; break; }\n"); } else if (cpu_level >= 4) { + // 68040+ printf ("\t\telse if (frame == 0x4) { m68k_areg (regs, 7) += offset + 8; break; }\n"); } - if (cpu_level == 1) // 68010 only - printf ("\t\telse if (frame == 0x8) { m68k_areg (regs, 7) += offset + 50; break; }\n"); + if (cpu_level == 1) { + // 68010 only + printf("\t\telse if (frame == 0x8) { m68k_areg (regs, 7) += offset + 50; break; }\n"); + } if (using_mmu == 68040) { printf ("\t\telse if (frame == 0x7) { m68k_do_rte_mmu040 (a); m68k_areg (regs, 7) += offset + 52; break; }\n"); } else if (cpu_level >= 4) { + // 68040+ printf ("\t\telse if (frame == 0x7) { m68k_areg (regs, 7) += offset + 52; break; }\n"); } - if (cpu_level == 2 || cpu_level == 3) { // 68020/68030 only + if (cpu_level == 2 || cpu_level == 3) { + // 68020/68030 only printf ("\t\telse if (frame == 0x9) { m68k_areg (regs, 7) += offset + 12; break; }\n"); if (using_mmu == 68030) { if (using_prefetch_020) { @@ -4047,7 +4058,7 @@ static void gen_opcode (unsigned int opcode) printf ("\t\telse if (frame == 0xb) { m68k_areg (regs, 7) += offset + 84; break; }\n"); } } - printf ("\t\telse { m68k_areg (regs, 7) += offset; Exception_cpu(14); goto %s; }\n", endlabelstr); + printf ("\t\telse { Exception_cpu(14); goto %s; }\n", endlabelstr); printf ("\t\tregs.sr = newsr;\n"); makefromsr_t0(); printf ("}\n"); @@ -4133,6 +4144,12 @@ static void gen_opcode (unsigned int opcode) case i_RTS: addop_ce020 (curi, 0); 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));\n"); + printf("\t\tgoto %s;\n", endlabelstr); + printf("\t}\n"); + } if (using_indirect > 0 && !using_ce020 && !using_prefetch_020 && !using_ce) { printf("\tm68k_do_rtsi_jit ();\n"); } else if (using_mmu) { @@ -4202,10 +4219,10 @@ static void gen_opcode (unsigned int opcode) printf("\tuaecptr oldpc = %s;\n", getpc); printf("\tuaecptr nextpc = oldpc + %d;\n", m68k_pc_offset); if (using_exception_3) { - printf ("\tif (srca & 1) {\n"); - printf ("\t\texception3i (opcode, srca);\n"); - printf ("\t\tgoto %s;\n", endlabelstr); - printf ("\t}\n"); + printf("\tif (srca & 1) {\n"); + printf("\t\texception3i (opcode, srca);\n"); + printf("\t\tgoto %s;\n", endlabelstr); + printf("\t}\n"); need_endlabel = 1; } if (using_mmu) { @@ -4221,10 +4238,16 @@ static void gen_opcode (unsigned int opcode) if (cpu_level <= 1 && using_prefetch) printf ("\tnextpc += 2;\n"); } + 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));\n"); + printf("\t\tgoto %s;\n", endlabelstr); + printf("\t}\n"); + } setpc ("srca"); clear_m68k_offset(); fill_prefetch_1 (0); - printf ("\tm68k_areg (regs, 7) -= 4;\n"); if (using_ce || using_prefetch) { printf ("\t%s (m68k_areg (regs, 7), nextpc >> 16);\n", dstw); printf ("\t%s (m68k_areg (regs, 7) + 2, nextpc);\n", dstw); @@ -4274,10 +4297,17 @@ static void gen_opcode (unsigned int opcode) } printf ("\ts = (uae_s32)src + 2;\n"); if (using_exception_3) { - printf ("\tif (src & 1) {\n"); - printf ("\t\texception3b (opcode, %s + s, 0, 1, %s + s);\n", getpc, getpc); - printf ("\t\tgoto %s;\n", endlabelstr); - printf ("\t}\n"); + printf("\tif (src & 1) {\n"); + printf("\t\texception3b(opcode, %s + s, 0, 1, %s + s);\n", getpc, getpc); + printf("\t\tgoto %s;\n", endlabelstr); + printf("\t}\n"); + if (cpu_level <= 1) { + 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\tgoto %s;\n", endlabelstr); + printf("\t}\n"); + } need_endlabel = 1; } addcycles000 (2); diff --git a/identify.cpp b/identify.cpp index eee9af67..01ccc39d 100644 --- a/identify.cpp +++ b/identify.cpp @@ -28,6 +28,7 @@ const struct mem_labels int_labels[] = { _T("TRACE"), 0x0024 }, { _T("LINEA EMU"), 0x0028 }, { _T("LINEF EMU"), 0x002C }, + { _T("FORMAT ERR"), 0x0038 }, { _T("INT Uninit"), 0x003C }, { _T("INT Unjust"), 0x0060 }, { _T("Lvl 1 Int"), 0x0064 }, diff --git a/newcpu.cpp b/newcpu.cpp index 6d23b310..6c431547 100644 --- a/newcpu.cpp +++ b/newcpu.cpp @@ -3023,6 +3023,7 @@ static void Exception_ce000 (int nr) int sv = regs.s; int start, interrupt; int vector_nr = nr; + int frame_id = 0; start = 6; interrupt = nr >= 24 && nr < 24 + 8; @@ -3052,24 +3053,46 @@ static void Exception_ce000 (int nr) cpu_halt (CPU_HALT_DOUBLE_FAULT); return; } - uae_u16 mode = (sv ? 4 : 0) | (last_instructionaccess_for_exception_3 ? 2 : 1); - mode |= last_writeaccess_for_exception_3 ? 0 : 16; - mode |= last_notinstruction_for_exception_3 ? 8 : 0; - // undocumented bits seem to contain opcode - mode |= last_op_for_exception_3 & ~31; - m68k_areg (regs, 7) -= 14; - exception_in_exception = -1; - x_put_word (m68k_areg (regs, 7) + 12, last_addr_for_exception_3); - x_put_word (m68k_areg (regs, 7) + 8, regs.sr); - x_put_word (m68k_areg (regs, 7) + 10, last_addr_for_exception_3 >> 16); - x_put_word (m68k_areg (regs, 7) + 6, last_op_for_exception_3); - x_put_word (m68k_areg (regs, 7) + 4, last_fault_for_exception_3); - x_put_word (m68k_areg (regs, 7) + 0, mode); - x_put_word (m68k_areg (regs, 7) + 2, last_fault_for_exception_3 >> 16); - x_do_cycles (2 * cpucycleunit); - write_log (_T("Exception %d (%04x %x) at %x -> %x!\n"), - nr, last_op_for_exception_3, last_addr_for_exception_3, currpc, get_long_debug (4 * nr)); - goto kludge_me_do; + write_log(_T("Exception %d (%04x %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) { + uae_u16 mode = (sv ? 4 : 0) | (last_instructionaccess_for_exception_3 ? 2 : 1); + mode |= last_writeaccess_for_exception_3 ? 0 : 16; + mode |= last_notinstruction_for_exception_3 ? 8 : 0; + // undocumented bits seem to contain opcode + mode |= last_op_for_exception_3 & ~31; + m68k_areg(regs, 7) -= 14; + exception_in_exception = -1; + x_put_word(m68k_areg(regs, 7) + 12, last_addr_for_exception_3); + x_put_word(m68k_areg(regs, 7) + 8, regs.sr); + x_put_word(m68k_areg(regs, 7) + 10, last_addr_for_exception_3 >> 16); + x_put_word(m68k_areg(regs, 7) + 6, last_op_for_exception_3); + x_put_word(m68k_areg(regs, 7) + 4, last_fault_for_exception_3); + x_put_word(m68k_areg(regs, 7) + 0, mode); + x_put_word(m68k_areg(regs, 7) + 2, last_fault_for_exception_3 >> 16); + x_do_cycles(2 * cpucycleunit); + goto kludge_me_do; + } else { + // 68010 address error (partially implemented only) + uae_u16 ssw = (sv ? 4 : 0) | (last_instructionaccess_for_exception_3 ? 2 : 1); + ssw |= last_writeaccess_for_exception_3 ? 0 : 0x100; + ssw |= last_instructionaccess_for_exception_3 ? 0 : 0x2000; + 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) + 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 + x_put_word(m68k_areg(regs, 7) + 16, last_op_for_exception_3); // instruction input buffer + x_put_word(m68k_areg(regs, 7) + 18, 0); // version + for (int i = 0; i < 15; i++) { + x_put_word(m68k_areg(regs, 7) + 20 + i * 2, 0); + } + } } if (currprefs.cpu_model == 68010) { // 68010 creates only format 0 and 8 stack frames @@ -3084,7 +3107,7 @@ static void Exception_ce000 (int nr) vector_nr = iack_cycle(nr); x_put_word (m68k_areg (regs, 7) + 0, regs.sr); // write SR x_put_word (m68k_areg (regs, 7) + 2, currpc >> 16); // write high address - x_put_word (m68k_areg (regs, 7) + 6, vector_nr * 4); + x_put_word (m68k_areg (regs, 7) + 6, (frame_id << 12) | (vector_nr * 4)); } else { m68k_areg (regs, 7) -= 6; if (m68k_areg(regs, 7) & 1) { @@ -3322,7 +3345,10 @@ static void Exception_build_stack_frame (uae_u32 oldpc, uae_u32 currpc, uae_u32 static void Exception_build_stack_frame_common (uae_u32 oldpc, uae_u32 currpc, uae_u32 ssw, int nr) { if (nr == 5 || nr == 6 || nr == 7 || nr == 9) { - Exception_build_stack_frame(oldpc, currpc, regs.mmu_ssw, nr, 0x2); + if (currprefs.cpu_model <= 68010) + Exception_build_stack_frame(oldpc, currpc, regs.mmu_ssw, nr, 0x0); + else + Exception_build_stack_frame(oldpc, currpc, regs.mmu_ssw, nr, 0x2); } else if (nr == 60 || nr == 61) { Exception_build_stack_frame(oldpc, regs.instruction_pc, regs.mmu_ssw, nr, 0x0); } else if (nr >= 48 && nr <= 55) { @@ -3664,8 +3690,8 @@ static void Exception_normal (int nr) m68k_areg (regs, 7) -= 2; x_put_word (m68k_areg (regs, 7), 0x2000 + vector_nr * 4); } - } else { - // 68020 address error + } else if (currprefs.cpu_model >= 68020) { + // 68020/030 address error uae_u16 ssw = (sv ? 4 : 0) | (last_instructionaccess_for_exception_3 ? 2 : 1); ssw |= last_writeaccess_for_exception_3 ? 0 : 0x40; ssw |= 0x20; @@ -3685,6 +3711,35 @@ static void Exception_normal (int nr) x_put_word (m68k_areg (regs, 7), ssw); m68k_areg (regs, 7) -= 2; x_put_word (m68k_areg (regs, 7), 0xb000 + vector_nr * 4); + } else { + // 68010 address error (partially implemented only) + uae_u16 ssw = (sv ? 4 : 0) | (last_instructionaccess_for_exception_3 ? 2 : 1); + ssw |= last_writeaccess_for_exception_3 ? 0 : 0x100; + ssw |= last_instructionaccess_for_exception_3 ? 0 : 0x2000; + for (i = 0; i < 15; i++) { + m68k_areg(regs, 7) -= 2; + x_put_word(m68k_areg(regs, 7), 0); + } + m68k_areg(regs, 7) -= 2; + x_put_word(m68k_areg(regs, 7), 0); // version + m68k_areg(regs, 7) -= 2; + x_put_word(m68k_areg(regs, 7), last_op_for_exception_3); // 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 + 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 + m68k_areg(regs, 7) -= 2; + x_put_word(m68k_areg(regs, 7), 0); // unused + m68k_areg(regs, 7) -= 4; + x_put_long(m68k_areg(regs, 7), last_addr_for_exception_3); // fault addr + m68k_areg(regs, 7) -= 2; + x_put_word(m68k_areg(regs, 7), ssw); // ssw + m68k_areg(regs, 7) -= 2; + x_put_word(m68k_areg(regs, 7), 0x8000 + vector_nr * 4); } write_log (_T("Exception %d (%x) at %x -> %x!\n"), nr, regs.instruction_pc, currpc, get_long_debug (regs.vbr + 4 * vector_nr)); } else if (regs.m && interrupt) { /* M + Interrupt */