]> git.unchartedbackwaters.co.uk Git - francis/winuae.git/commitdiff
Stack read/write bus error support.
authorToni Wilen <twilen@winuae.net>
Fri, 27 Dec 2019 20:49:20 +0000 (22:49 +0200)
committerToni Wilen <twilen@winuae.net>
Fri, 27 Dec 2019 20:49:20 +0000 (22:49 +0200)
cputest.cpp
cputest/cputestgen.ini
cputest/main.c
gencpu.cpp

index d65603b8209b6d367ef02bbf0e399e5b66291540..bf13c8f1d488fd5e945c6b60411727ce5790070f 100644 (file)
@@ -66,7 +66,7 @@ static int feature_loop_mode_register = -1;
 static int feature_full_extension_format = 0;
 static int feature_test_rounds = 2;
 static int feature_flag_mode = 0;
-static int feature_odd_usp = 0;
+static int feature_usp = 0;
 static TCHAR *feature_instruction_size = NULL;
 static uae_u32 feature_addressing_modes[2];
 static int ad8r[2], pc8r[2];
@@ -299,6 +299,10 @@ static void check_bus_error(uaecptr addr, int write, int fc)
                        cpu_bus_error |= 2;
                        cpu_bus_error_fake |= 2;
                }
+               if (!write && (fc & 2) && feature_usp == 3) {
+                       out_of_test_space = true;
+                       out_of_test_space_addr = addr;
+               }
        }
 }
 
@@ -2353,7 +2357,8 @@ static uaecptr handle_specials_extra(uae_u16 opcode, uaecptr pc, struct instr *d
 static uae_u32 generate_stack_return(int cnt)
 {
        uae_u32 v;
-       if (target_ea[0] != 0xffffffff) {
+       // if targer sp mode: generate random return address
+       if (target_ea[0] != 0xffffffff && feature_usp < 3) {
                v = target_ea[0];
        } else {
                v = rand32();
@@ -2446,9 +2451,9 @@ static int handle_specials_stack(uae_u16 opcode, uaecptr pc, struct instr *dp, i
        int offset = 0;
        if (dp->mnemo == i_RTE || dp->mnemo == i_RTD || dp->mnemo == i_RTS || dp->mnemo == i_RTR || dp->mnemo == i_UNLK) {
                uae_u32 v;
-               uaecptr addr = regs.regs[8 + 7];
+               uaecptr addr = regs.regs[15];
                // RTE, RTD, RTS and RTR
-               if (dp->mnemo == i_RTR) {
+               if (dp->mnemo == i_RTR) {
                        // RTR
                        v = imm_special++;
                        uae_u16 ccr = v & 31;
@@ -2649,6 +2654,26 @@ static void execute_ins(uaecptr endpc, uaecptr targetpc, struct instr *dp)
        }
 }
 
+// instruction that reads or writes stack
+static int stackinst(struct instr *dp)
+{
+       switch (dp->mnemo)
+       {
+       case i_RTS:
+       case i_RTR:
+       case i_RTD:
+       case i_RTE:
+       case i_UNLK:
+               return 1;
+       case i_BSR:
+       case i_JSR:
+       case i_LINK:
+       case i_PEA:
+               return 2;
+       }
+       return 0;
+}
+
 // any instruction that can branch execution
 static int isbranchinst(struct instr *dp)
 {
@@ -2958,16 +2983,23 @@ static void test_mnemo(const TCHAR *path, const TCHAR *mnemo, const TCHAR *ovrfi
        int count = 0;
 
        registers[8 + 6] = opcode_memory_start - 0x100;
-       registers[8 + 7] = user_stack_memory_use;
+       registers[15] = user_stack_memory_use;
 
        uae_u32 target_address = 0xffffffff;
        uae_u32 target_opcode_address = 0xffffffff;
+       uae_u32 target_usp_address = 0xffffffff;
        target_ea[0] = 0xffffffff;
        target_ea[1] = 0xffffffff;
        target_ea[2] = 0xffffffff;
        if (feature_target_ea[0][2] && feature_target_ea[0][2] != 0xffffffff) {
-               target_opcode_address = feature_target_ea[0][2];
-               target_ea[2] = target_opcode_address;
+               if (feature_usp == 3) {
+                       target_usp_address = feature_target_ea[0][2];
+                       target_ea[2] = target_usp_address;
+                       target_usp_address += opcode_memory_start;
+               } else {
+                       target_opcode_address = feature_target_ea[0][2];
+                       target_ea[2] = target_opcode_address;
+               }
        }
        if (feature_target_ea[0][0] != 0xffffffff) {
                target_address = feature_target_ea[0][0];
@@ -3185,6 +3217,11 @@ static void test_mnemo(const TCHAR *path, const TCHAR *mnemo, const TCHAR *ovrfi
                                        target_address = target_address_bak;
                                        target_opcode_address = target_opcode_address_bak;
 
+                                       if (target_usp_address != 0xffffffff) {
+                                               cur_registers[15] = target_usp_address;
+                                               regs.regs[15] = target_usp_address;
+                                       }
+
                                        if (opc == 0x4a53)
                                                printf("");
                                        if (subtest_count >= 700)
@@ -3282,7 +3319,7 @@ static void test_mnemo(const TCHAR *path, const TCHAR *mnemo, const TCHAR *ovrfi
                                                }
 
                                                // requested target address but no EA? skip
-                                               if (target_address != 0xffffffff && isbranchinst(dp) != 2) {
+                                               if (target_address != 0xffffffff && isbranchinst(dp) != 2 && (feature_usp < 3 || !stackinst(dp))) {
                                                        if (srcea != target_address && dstea != target_address) {
                                                                memcpy(opcode_memory, oldcodebytes, sizeof(oldcodebytes));
                                                                continue;
@@ -3383,6 +3420,7 @@ static void test_mnemo(const TCHAR *path, const TCHAR *mnemo, const TCHAR *ovrfi
                                        for (int i = 0; i < 8; i++) {
                                                regs.fp[i].fpx = cur_fpuregisters[i];
                                        }
+
                                        uaecptr nextpc;
                                        srcaddr = 0xffffffff;
                                        dstaddr = 0xffffffff;
@@ -3438,10 +3476,10 @@ static void test_mnemo(const TCHAR *path, const TCHAR *mnemo, const TCHAR *ovrfi
                                                                constant_loops++;
                                                                quick = 0;
                                                        }
-                                                       srcaddr = get_long_test(regs.regs[8 + 7] + stackoffset);
+                                                       srcaddr = get_long_test(regs.regs[15] + stackoffset);
                                                }
                                                // branch target is not accessible? skip.
-                                               if ((srcaddr >= cur_registers[15] - 16 && srcaddr <= cur_registers[15] + 16) || ((srcaddr & 1) && !feature_exception3_instruction && feature_odd_usp < 2)) {
+                                               if ((srcaddr >= cur_registers[15] - 16 && srcaddr <= cur_registers[15] + 16) || ((srcaddr & 1) && !feature_exception3_instruction && feature_usp < 2)) {
                                                        // lets not jump directly to stack..
                                                        if (verbose) {
                                                                if (srcaddr & 1)
@@ -3527,6 +3565,10 @@ static void test_mnemo(const TCHAR *path, const TCHAR *mnemo, const TCHAR *ovrfi
                                                *dst++ = branch_target_swap_mode;
                                        }
 
+                                       if (feature_usp >= 3) {
+                                               dst = store_reg(dst, CT_AREG + 7, 0, target_usp_address, sz_long);
+                                       }
+
                                        // pre-test data end
                                        *dst++ = CT_END_INIT;
 
@@ -3669,7 +3711,7 @@ static void test_mnemo(const TCHAR *path, const TCHAR *mnemo, const TCHAR *ovrfi
                                                                regs.sr = ((ccr & 1) ? 31 : 0) | sr_mask;
                                                        }
                                                        regs.sr |= feature_min_interrupt_mask << 8;
-                                                       regs.usp = regs.regs[8 + 7];
+                                                       regs.usp = regs.regs[15];
                                                        regs.isp = super_stack_memory - 0x80;
                                                        // copy user stack to super stack, for RTE etc support
                                                        memcpy(test_memory + (regs.isp - test_memory_start), test_memory + (regs.usp - test_memory_start), 0x20);
@@ -3716,6 +3758,7 @@ static void test_mnemo(const TCHAR *path, const TCHAR *mnemo, const TCHAR *ovrfi
                                                                ((cpu_bus_error & 2) && !(safe_memory_mode & 2))) {
                                                                skipped = 1;
                                                        }
+
                                                        // skip if feature_target_opcode_offset mode and non-prefetch bus error
                                                        if (target_opcode_address != 0xffffffff && (cpu_bus_error & 3)) {
                                                                skipped = 1;
@@ -3729,7 +3772,7 @@ static void test_mnemo(const TCHAR *path, const TCHAR *mnemo, const TCHAR *ovrfi
                                                                if (feature_exception3_instruction == 2) {
                                                                        skipped = 1;
                                                                }
-                                                               if (feature_odd_usp > 1) {
+                                                               if (feature_usp == 2) {
                                                                        skipped = 1;
                                                                }
                                                        }
@@ -3759,10 +3802,10 @@ static void test_mnemo(const TCHAR *path, const TCHAR *mnemo, const TCHAR *ovrfi
                                                                }
                                                                // got exception 3 but didn't want them?
                                                                if (test_exception == 3) {
-                                                                       if (!feature_odd_usp && !feature_exception3_data && !(test_exception_3_fc & 2)) {
+                                                                       if ((feature_usp != 1 && feature_usp != 2) && !feature_exception3_data && !(test_exception_3_fc & 2)) {
                                                                                skipped = 1;
                                                                        }
-                                                                       if (!feature_odd_usp && !feature_exception3_instruction && (test_exception_3_fc & 2)) {
+                                                                       if ((feature_usp != 1 && feature_usp != 2) && !feature_exception3_instruction && (test_exception_3_fc & 2)) {
                                                                                skipped = 1;
                                                                        }
                                                                }
@@ -3976,7 +4019,7 @@ static void test_mnemo(const TCHAR *path, const TCHAR *mnemo, const TCHAR *ovrfi
                }
                dst = storage_buffer;
 
-               if (opcodecnt == 1 && target_address == 0xffffffff && target_opcode_address == 0xffffffff)
+               if (opcodecnt == 1 && target_address == 0xffffffff && target_opcode_address == 0xffffffff && target_usp_address == 0xffffffff)
                        break;
                if (lookup->mnemo == i_ILLG)
                        break;
@@ -4013,7 +4056,7 @@ static void test_mnemo(const TCHAR *path, const TCHAR *mnemo, const TCHAR *ovrfi
                        nextround = true;
                }
 
-               if (target_opcode_address != 0xffffffff) {
+               if (target_opcode_address != 0xffffffff || target_usp_address != 0xffffffff) {
                        nextround = false;
                        target_ea_opcode_cnt++;
                        if (target_ea_opcode_cnt >= target_ea_opcode_max) {
@@ -4023,8 +4066,14 @@ static void test_mnemo(const TCHAR *path, const TCHAR *mnemo, const TCHAR *ovrfi
                        } else {
                                quick = 0;
                        }
-                       target_opcode_address = feature_target_ea[target_ea_opcode_cnt][2];
-                       target_ea[2] = opcode_memory_address + target_opcode_address;
+                       if (feature_usp == 3) {
+                               target_usp_address = feature_target_ea[target_ea_opcode_cnt][2];
+                               target_usp_address += opcode_memory_start;
+                               target_ea[2] =  target_usp_address;
+                       } else {
+                               target_opcode_address = feature_target_ea[target_ea_opcode_cnt][2];
+                               target_ea[2] = opcode_memory_address + target_opcode_address;
+                       }
                }
 
                if (nextround) {
@@ -4036,7 +4085,7 @@ static void test_mnemo(const TCHAR *path, const TCHAR *mnemo, const TCHAR *ovrfi
                cur_registers[0] &= 0xffff;
                cur_registers[8] &= 0xffff;
                cur_registers[8 + 6]--;
-               cur_registers[8 + 7] -= 2;
+               cur_registers[15] -= 2;
 
                if (fpumode) {
                        for (int i = 0; i < 8; i++) {
@@ -4345,8 +4394,8 @@ int __cdecl main(int argc, char *argv[])
        }
        feature_flag_mode = 0;
        ini_getval(ini, INISECTION, _T("feature_flags_mode"), &feature_flag_mode);
-       feature_odd_usp = 0;
-       ini_getval(ini, INISECTION, _T("feature_odd_usp"), &feature_odd_usp);
+       feature_usp = 0;
+       ini_getval(ini, INISECTION, _T("feature_usp"), &feature_usp);
 
        feature_full_extension_format = 0;
        if (currprefs.cpu_model >= 68020) {
@@ -4493,7 +4542,7 @@ int __cdecl main(int argc, char *argv[])
                user_stack_memory = test_memory_start + RESERVED_SUPERSTACK;
        }
        user_stack_memory_use = user_stack_memory;
-       if (feature_odd_usp) {
+       if (feature_usp == 1 || feature_usp == 2) {
                user_stack_memory_use |= 1;
        }
 
index 0353df5c9f48eb3950f172eb99b5dfb0511ee786..97ef082daf7173a27c02dd32605c09390acd0492 100644 (file)
@@ -78,11 +78,12 @@ feature_safe_memory_size=0x80000
 ; if enabled, all tests that don't generate matching bus error are skipped.
 feature_safe_memory_mode=R
 
-; force odd user stack
-; 0 = even stack
+; user stack modes
+; 0 = normal even stack
 ; 1 = odd stack (original stack + 1)
 ; 2 = odd stack and skip all tests that didn't generate address error exception
-feature_odd_usp=0
+; 3 = take stack from feature_target_opcode_offset
+feature_usp=0
 
 ; CCR/FPU status flags mode
 ; 0 = all combinations (32 CCR loops, 256 FPU loops)
index 7cda24f51194321cfeb3a7d4a88b7962d54c30bf..0ee3e55f62fd4283c856ffeee62ec31ad244393b 100644 (file)
@@ -1816,6 +1816,13 @@ static void process_test(uae_u8 *p)
                        break;
                p++;
 
+               int stackcopysize = 0;
+               for (int i = 0; i < 32; i += 2) {
+                       if (!is_valid_test_addr_readwrite(regs.regs[15] + i))
+                               break;
+                       stackcopysize += 2;
+               }
+
                store_addr(regs.srcaddr, srcaddr);
                store_addr(regs.dstaddr, dstaddr);
                store_addr(regs.branchtarget, branchtarget);
@@ -1884,7 +1891,8 @@ static void process_test(uae_u8 *p)
                                regs.fpiar = startpc;
 
 #ifdef M68K
-                               xmemcpy((void*)regs.ssp, (void*)regs.regs[15], 0x20);
+                               if (stackcopysize > 0)
+                                       xmemcpy((void*)regs.ssp, (void*)regs.regs[15], stackcopysize);
 #endif
                                xmemcpy(&test_regs, &regs, sizeof(struct registers));
 
index 568be11e0d315f1a85a3bac957d6eece8d67ec84..241eac40b6e111a63319aaeb8699a91f7c9f2961 100644 (file)
@@ -1016,7 +1016,7 @@ static void fill_prefetch_next_t(void)
        if (using_prefetch) {
                irc2ir();
                if (using_bus_error) {
-                       printf("\topcode = regs.ir;\n");
+                       copy_opcode();
                        strcat(bus_error_code, "\t\tif (regs.t1) opcode |= 0x10000;\n");
                }
                fill_prefetch_1(m68k_pc_offset + 2);
@@ -1031,7 +1031,7 @@ static void fill_prefetch_next_extra(const char *cond, const char *format, ...)
                if (using_bus_error) {
                        if (cond)
                                printf("\t%s\n\t", cond);
-                       printf("\topcode = regs.ir;\n");
+                       copy_opcode();
                        bus_error_code[0] = 0;
                        if (format) {
                                va_list parms;
@@ -1598,7 +1598,11 @@ static int do_bus_error_fixes(const char *name, int offset, int write)
                break;
        case 2:
        case -2:
-               printf("\t\tm68k_areg(regs, %s) += 2 + %d;\n", bus_error_reg, offset);
+               if (g_instr->mnemo == i_RTR) {
+                       ;
+               } else {
+                       printf("\t\tm68k_areg(regs, %s) += 2 + %d;\n", bus_error_reg, offset);
+               }
                break;
        case 3:
        case -3:
@@ -1611,6 +1615,15 @@ static int do_bus_error_fixes(const char *name, int offset, int write)
                if ((g_instr->mnemo == i_ADDX || g_instr->mnemo == i_SUBX) && g_instr->size == sz_long) {
                        // ADDX.L/SUBX.L -(an),-(an) source: stack frame decreased by 2, not 4.
                        offset += 2;
+               } else if (g_instr->mnemo == i_RTR) {
+                       if (offset) {
+                               printf("\t\tm68k_areg(regs, %s) += 4;\n", bus_error_reg);
+                               printf("\t\tregs.sr &= 0xFF00; sr &= 0xFF;\n");
+                               printf("\t\tregs.sr |= sr;\n");
+                               printf("\t\tMakeFromSR();\n");
+                       } else {
+                               printf("\t\tm68k_areg(regs, %s) -= 2;\n", bus_error_reg);
+                       }
                } else {
                        printf("\t\tm68k_areg(regs, %s) = %sa;\n", bus_error_reg, name);
                }
@@ -1685,7 +1698,13 @@ static void check_bus_error(const char *name, int offset, int write, int size, c
 
                if (mnemo == i_LINK) {
                        // a7 -> a0 copy done before A7 address error check
-                       printf("\tm68k_areg(regs, srcreg) = olda;\n");
+                       if (write) {
+                               printf("\t\tm68k_areg(regs, 7) += 4;\n");
+                       }
+                       printf("\t\tm68k_areg(regs, srcreg) = olda;\n");
+               }
+               if (mnemo == i_PEA && write && offset && g_instr->smode != absw && g_instr->smode != absl) {
+                       printf("\t\tif (regs.t1) opcode |= 0x10000;\n"); // I/N set
                }
 
                if (cpu_level == 1 && g_instr->mnemo == i_MVSR2 && !write) {
@@ -1700,8 +1719,10 @@ static void check_bus_error(const char *name, int offset, int write, int size, c
                // write causing bus error and trace: set I/N
                if (write && g_instr->size <= sz_word &&
                        mnemo != i_MOVE &&
+                       mnemo != i_BSR &&
+                       mnemo != i_LINK &&
                        mnemo != i_MVMEL && mnemo != i_MVMLE &&
-                       mnemo != i_MVPRM && mnemo != i_MVPMR) {         
+                       mnemo != i_MVPRM && mnemo != i_MVPMR) {
                        printf("\t\tif (regs.t1) opcode |= 0x10000;\n"); // I/N set
                }
 
@@ -5679,7 +5700,7 @@ static void gen_opcode (unsigned int opcode)
                printf("\tuaecptr oldpc = %s;\n", getpc);
                printf("\tMakeSR();\n");
                genamode (NULL, Aipi, "7", sz_word, "sr", 1, 0, 0);
-               genamode (NULL, Aipi, "7", sz_long, "pc", 1, 0, 0);
+               genamode(NULL, Aipi, "7", sz_long, "pc", 1, 0, 0);
                if (cpu_level >= 4) {
                        printf("\tif (pc & 1) {\n");
                        printf("\t\tm68k_areg(regs, 7) -= 6;\n");
@@ -5689,8 +5710,8 @@ static void gen_opcode (unsigned int opcode)
                }
                printf("\tregs.sr &= 0xFF00; sr &= 0xFF;\n");
                printf("\tregs.sr |= sr;\n");
-               setpc ("pc");
                makefromsr();
+               setpc ("pc");
                if (cpu_level < 4) {
                        printf("\tif (%s & 1) {\n", getpc);
                        printf("\t\tuaecptr faultpc = %s;\n", getpc);
@@ -5783,7 +5804,7 @@ static void gen_opcode (unsigned int opcode)
                        if (using_prefetch || using_ce) {
                                int sp = (curi->smode == Ad16 || curi->smode == absw || curi->smode == absl || curi->smode == PC16 || curi->smode == Ad8r || curi->smode == PC8r) ? -1 : 0;
                                irc2ir();
-                               printf("\topcode = regs.ir;\n");
+                               copy_opcode();
                                if (sp < 0)
                                        printf("\tif(regs.t1) opcode |= 0x10000;\n");
                                printf("\t%s(%d);\n", prefetch_word, 2);
@@ -5821,7 +5842,7 @@ static void gen_opcode (unsigned int opcode)
                        irc2ir();
                        printf("\t%s(%d);\n", prefetch_word, 2);
                        int sp = (curi->smode == Ad16 || curi->smode == absw || curi->smode == absl || curi->smode == PC16 || curi->smode == Ad8r || curi->smode == PC8r) ? -1 : 0;
-                       printf("\topcode = regs.ir;\n");
+                       copy_opcode();
                        if (sp < 0)
                                printf("\tif(regs.t1) opcode |= 0x10000;\n");
                        check_prefetch_bus_error(-2, sp);
@@ -6015,7 +6036,7 @@ bccl_not68020:
                genamode (curi, curi->smode, "srcreg", curi->size, "src", 0, 0, GF_AA);
                genamode (NULL, Apdi, "7", sz_long, "dst", 2, 0, GF_AA);
                if (!(curi->smode == absw || curi->smode == absl))
-                       fill_prefetch_next_after(1, "m68k_areg(regs, 7) += 4;\n");
+                       fill_prefetch_next_after(0, "m68k_areg(regs, 7) += 4;\n");
                if (curi->smode == Ad8r || curi->smode == PC8r)
                        addcycles000 (2);
                genastore ("srca", Apdi, "7", sz_long, "dst");
@@ -6063,7 +6084,7 @@ bccl_not68020:
                add_head_cycs (6);
 
                if (using_prefetch || using_ce) {
-                       printf("\topcode = regs.ir;\n");
+                       copy_opcode();
                        printf("\tif(regs.t1) opcode |= 0x10000;\n");
                        printf("\t%s(%d);\n", prefetch_word, 2);
                        check_prefetch_bus_error(-2, -1);