]> git.unchartedbackwaters.co.uk Git - francis/winuae.git/commitdiff
68000/010 modes didn't check BSR/JSR/RTS odd stack pointer. 68010 incorrectly accepte...
authorToni Wilen <twilen@winuae.net>
Tue, 18 Jun 2019 17:26:32 +0000 (20:26 +0300)
committerToni Wilen <twilen@winuae.net>
Tue, 18 Jun 2019 17:26:32 +0000 (20:26 +0300)
gencpu.cpp
identify.cpp
newcpu.cpp

index 5679b9d10283c8a15332c69952f3dfae62e6938f..01be24c33b97f06300ee75a8de4ae2f65a47f973 100644 (file)
@@ -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);
index eee9af670bd5cf3a6d4baaa77db65a5878168690..01ccc39d341df781c7ae909dca56f65ee8feaf3b 100644 (file)
@@ -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 },
index 6d23b310d24672f3bb9088ce9c2c798293e05ac4..6c4315476d64dc43ccd39b4a087e719c14145efc 100644 (file)
@@ -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 */