]> git.unchartedbackwaters.co.uk Git - francis/winuae.git/commitdiff
Tester updates, configurable stack and opcode space, CALLM disassembly, cpRESTORE...
authorToni Wilen <twilen@winuae.net>
Fri, 25 Oct 2019 17:41:02 +0000 (20:41 +0300)
committerToni Wilen <twilen@winuae.net>
Fri, 25 Oct 2019 17:41:02 +0000 (20:41 +0300)
cputest.cpp
cputest/cputest_defines.h
cputest/main.c
disasm.cpp
gencpu.cpp
include/newcpu.h
newcpu.cpp
newcpu_common.cpp

index fb27b6d2e4a4c842af6fcc773a2e777ea1f3c99f..e5cfc7369a7197afb29f52d78523ba1ec80c7674 100644 (file)
@@ -81,6 +81,8 @@ static uae_u32 target_ea[2];
 // large enough for RTD
 #define STACK_SIZE (0x8000 + 8)
 #define RESERVED_SUPERSTACK 1024
+// space between superstack and USP
+#define RESERVED_USERSTACK_EXTRA 64
 // space for extra exception, not part of test region
 #define EXTRA_RESERVED_SPACE 1024
 
@@ -92,6 +94,8 @@ static uae_u32 low_memory_size = 32768;
 static uae_u32 high_memory_size = 32768;
 static uae_u32 safe_memory_start;
 static uae_u32 safe_memory_end;
+static int safe_memory_mode;
+static uae_u32 user_stack_memory, super_stack_memory;
 
 static uae_u8 *low_memory, *high_memory, *test_memory;
 static uae_u8 *low_memory_temp, *high_memory_temp, *test_memory_temp;
@@ -193,11 +197,25 @@ static bool valid_address(uaecptr addr, int size, int w)
                high_memory_accessed = w ? -1 : 1;
                return 1;
        }
+       if (addr >= super_stack_memory - RESERVED_SUPERSTACK && addr + size < super_stack_memory) {
+               // allow only instructions that have to access super stack, for example RTE
+               // read-only
+               if (w) {
+                       goto oob;
+               }
+               if (testing_active) {
+                       if (is_superstack_use_required()) {
+                               test_memory_accessed = 1;
+                               return 1;
+                       }
+               }
+               goto oob;
+       }
        if (addr >= test_memory_end && addr + size < test_memory_end + EXTRA_RESERVED_SPACE) {
                if (testing_active < 0)
                        return 1;
        }
-       if (addr >= test_memory_start && addr + size < test_memory_end - RESERVED_SUPERSTACK) {
+       if (addr >= test_memory_start && addr + size < test_memory_end) {
                // make sure we don't modify our test instruction
                if (testing_active && w) {
                        if (addr >= opcode_memory_start && addr + size < opcode_memory_start + OPCODE_AREA)
@@ -206,18 +224,6 @@ static bool valid_address(uaecptr addr, int size, int w)
                test_memory_accessed = w ? -1 : 1;
                return 1;
        }
-       if (addr >= test_memory_end - RESERVED_SUPERSTACK && addr + size < test_memory_end) {
-               // allow only instructions that have to access super stack, for example RTE
-               // read-only
-               if (w)
-                       goto oob;
-               if (testing_active) {
-                       if (is_superstack_use_required()) {
-                               test_memory_accessed = 1;
-                               return 1;
-                       }
-               }
-       }
 oob:
        return 0;
 }
@@ -277,7 +283,10 @@ static void check_bus_error(uaecptr addr, int write, int fc)
        if (safe_memory_start == 0xffffffff && safe_memory_end == 0xffffffff)
                return;
        if (addr >= safe_memory_start && addr < safe_memory_end) {
-               cpu_bus_error = 1;
+               if ((safe_memory_mode & 1) && !write)
+                       cpu_bus_error = 1;
+               if ((safe_memory_mode & 2) && write)
+                       cpu_bus_error = 1;
        }
 }
 
@@ -853,12 +862,25 @@ static void doexcstack(void)
 
 uae_u32 REGPARAM2 op_illg_1(uae_u32 opcode)
 {
-       if ((opcode & 0xf000) == 0xf000)
+       if ((opcode & 0xf000) == 0xf000) {
+               if (currprefs.cpu_model == 68030) {
+                       // mmu instruction extra check
+                       // because mmu checks following word to detect if addressing mode is supported,
+                       // we can't test any MMU opcodes without parsing following word. TODO.
+                       if ((opcode & 0xfe00) == 0xf000) {
+                               test_exception = -1;
+                               return 0;
+                       }
+               }
                test_exception = 11;
-       else if ((opcode & 0xf000) == 0xa000)
+               if (privileged_copro_instruction(opcode)) {
+                       test_exception = 8;
+               }
+       } else if ((opcode & 0xf000) == 0xa000) {
                test_exception = 10;
-       else
+       } else {
                test_exception = 4;
+       }
        doexcstack();
        return 0;
 }
@@ -1347,7 +1369,7 @@ static void save_data(uae_u8 *dst, const TCHAR *dir)
                fwrite(data, 1, 4, f);
                pl(data, test_memory_size);
                fwrite(data, 1, 4, f);
-               pl(data, opcode_memory_start - test_memory_start);
+               pl(data, opcode_memory_start);
                fwrite(data, 1, 4, f);
                pl(data, (cpu_lvl << 16) | sr_undefined_mask | (addressing_mask == 0xffffffff ? 0x80000000 : 0) | ((feature_flag_mode & 1) << 30) | (feature_min_interrupt_mask << 20));
                fwrite(data, 1, 4, f);
@@ -1365,9 +1387,9 @@ static void save_data(uae_u8 *dst, const TCHAR *dir)
                fwrite(data, 1, 4, f);
                pl(data, safe_memory_end);
                fwrite(data, 1, 4, f);
-               pl(data, 0);
+               pl(data, user_stack_memory);
                fwrite(data, 1, 4, f);
-               pl(data, 0);
+               pl(data, super_stack_memory);
                fwrite(data, 1, 4, f);
                fwrite(inst_name, 1, sizeof(inst_name) - 1, f);
                fclose(f);
@@ -1433,6 +1455,60 @@ static uaecptr putfpuimm(uaecptr pc, int opcodesize, int *isconstant)
        return pc;
 }
 
+static int ea_state_found[3];
+
+static void reset_ea_state(void)
+{
+       ea_state_found[0] = 0;
+       ea_state_found[1] = 0;
+       ea_state_found[2] = 0;
+}
+
+// attempt to find at least one zero, positive and negative source value
+static int analyze_address(struct instr *dp, int srcdst, uae_u32 addr)
+{
+       uae_u32 v;
+       uae_u32 mask;
+
+       if (srcdst)
+               return 1;
+       if (dp->size == sz_byte) {
+               v = get_byte_test(addr);
+               mask = 0x80;
+       } else if (dp->size == sz_word) {
+               v = get_word_test(addr);
+               mask = 0x8000;
+       } else {
+               v = get_long_test(addr);
+               mask = 0x80000000;
+       }
+       if (out_of_test_space) {
+               out_of_test_space = false;
+               return 0;
+       }
+       if (ea_state_found[0] >= 2 && ea_state_found[1] >= 2 && ea_state_found[2] >= 2)
+               return 1;
+       // zero
+       if (v == 0) {
+               if (ea_state_found[0] >= 2 && (ea_state_found[1] < 2 || ea_state_found[2] < 2))
+                       return 0;
+               ea_state_found[0]++;
+       }
+       // negative value
+       if (v & mask) {
+               if (ea_state_found[1] >= 2 && (ea_state_found[0] < 2 || ea_state_found[2] < 2))
+                       return 0;
+               ea_state_found[1]++;
+       }
+       // positive value
+       if (v < mask && v > 0) {
+               if (ea_state_found[2] >= 2 && (ea_state_found[0] < 2 || ea_state_found[1] < 2))
+                       return 0;
+               ea_state_found[2]++;
+       }
+       return 1;
+}
+
 // generate mostly random EA.
 static int create_ea_random(uae_u16 *opcodep, uaecptr pc, int mode, int reg, struct instr *dp, int *isconstant, int srcdst, int fpuopcode, int opcodesize, uae_u32 *eap)
 {
@@ -1453,20 +1529,56 @@ static int create_ea_random(uae_u16 *opcodep, uaecptr pc, int mode, int reg, str
        case Areg:
        case Aind:
        case Aipi:
+               *eap = cur_registers[reg + 8];
+               break;
        case Apdi:
-               *eap = 1;
+               *eap = cur_registers[reg + 8] - (1 << dp->size);
                break;
        case Ad16:
+       {
+               uae_u16 v;
+               uae_u32 addr;
+               int maxcnt = 1000;
+               for (;;) {
+                       v = rand16();
+                       addr = cur_registers[reg + 8] + (uae_s16)v;
+                       if (analyze_address(dp, srcdst, addr))
+                               break;
+                       maxcnt--;
+                       if (maxcnt < 0)
+                               break;
+               }
+               put_word_test(pc, v);
+               *isconstant = 16;
+               pc += 2;
+               *eap = addr;
+               break;
+       }
        case PC16:
-               put_word_test(pc, rand16());
+       {
+               uae_u32 pct = pc + 2 - 2;
+               uae_u16 v;
+               uae_u32 addr;
+               int maxcnt = 1000;
+               for (;;) {
+                       v = rand16();
+                       addr = pct + (uae_s16)v;
+                       if (analyze_address(dp, srcdst, addr))
+                               break;
+                       maxcnt--;
+                       if (maxcnt < 0)
+                               break;
+               }
                *isconstant = 16;
                pc += 2;
                *eap = 1;
                break;
+       }
        case Ad8r:
        case PC8r:
        {
-               uae_u16 v = rand16();
+               uae_u32 addr;
+               uae_u16 v = rand16() & 0x0100;
                if (!feature_full_extension_format)
                        v &= ~0x100;
                if (mode == Ad8r) {
@@ -1481,13 +1593,41 @@ static int create_ea_random(uae_u16 *opcodep, uaecptr pc, int mode, int reg, str
                                v |= 0x100;
                }
                if (currprefs.cpu_model < 68020 || (v & 0x100) == 0) {
+                       // brief format extension
+                       uae_u32 add = 0;
+                       int maxcnt = 1000;
+                       for (;;) {
+                               v = rand16();
+                               if (currprefs.cpu_model >= 68020)
+                                       v &= ~0x100;
+                               addr = mode == PC8r ? pc + 2 - 2 : cur_registers[reg + 8];
+                               add = cur_registers[v >> 12];
+                               if (v & 0x0800) {
+                                       // L
+                                       addr += add;
+                               } else {
+                                       // W
+                                       addr += (uae_s16)add;
+                               }
+                               if (currprefs.cpu_model >= 68020) {
+                                       add <<= (v >> 9) & 3; // SCALE
+                               }
+                               addr += (uae_s8)(v & 0xff); // DISPLACEMENT
+                               if (analyze_address(dp, srcdst, addr))
+                                       break;
+                               maxcnt--;
+                               if (maxcnt < 0)
+                                       break;
+                       }
                        *isconstant = 16;
                        put_word_test(pc, v);
                        pc += 2;
+                       *eap = addr;
                } else {
                        // full format extension
                        // attempt to generate every possible combination,
                        // one by one.
+                       v |= rand16() & ~0x100;
                        for (;;) {
                                v &= 0xff00;
                                v |= full_format_cnt & 0xff;
@@ -1513,22 +1653,35 @@ static int create_ea_random(uae_u16 *opcodep, uaecptr pc, int mode, int reg, str
                                pc += 2;
                        }
                        *isconstant = 32;
+                       *eap = 1;
                }
-               *eap = 1;
                break;
        }
        case absw:
-               put_word_test(pc, rand16());
+       {
+               uae_u16 v;
+               for (;;) {
+                       v = rand16();
+                       if (analyze_address(dp, srcdst, v))
+                               break;
+               }
+               put_word_test(pc, v);
                *isconstant = 16;
                pc += 2;
-               *eap = 1;
+               *eap = v >= 0x8000 ? (0xffff0000 | v) : v;
                break;
+       }
        case absl:
-               {
-                       uae_u32 v = rand32();
+       {
+               uae_u32 v;
+               for (;;) {
+                       v = rand32();
                        if ((immabsl_cnt & 7) == 0) {
-                               v &= 0x0000ffff;
-                       } else if ((immabsl_cnt & 7) >= 4) {
+                               v &= 0x00007fff;
+                       } else if ((immabsl_cnt & 7) == 1) {
+                               v &= 0x00007fff;
+                               v = 0xffff8000 | v;
+                       } else if ((immabsl_cnt & 7) >= 5) {
                                int offset = 0;
                                for (;;) {
                                        offset = (uae_s16)rand16();
@@ -1538,12 +1691,15 @@ static int create_ea_random(uae_u16 *opcodep, uaecptr pc, int mode, int reg, str
                                v = opcode_memory_start + offset;
                        }
                        immabsl_cnt++;
-                       put_long_test(pc, v);
-                       *isconstant = 32;
-                       pc += 4;
+                       if (analyze_address(dp, srcdst, v))
+                               break;
                }
-               *eap = 1;
+               put_long_test(pc, v);
+               *isconstant = 32;
+               pc += 4;
+               *eap = v;
                break;
+       }
        case imm:
                if (fpuopcode >= 0 && opcodesize < 8) {
                        pc = putfpuimm(pc, opcodesize, isconstant);
@@ -1564,8 +1720,11 @@ static int create_ea_random(uae_u16 *opcodep, uaecptr pc, int mode, int reg, str
        {
                // byte immediate but randomly fill also upper byte
                uae_u16 v = rand16();
-               if ((imm8_cnt & 3) == 0)
+               if ((imm8_cnt & 15) == 0) {
+                       v = 0;
+               } else if ((imm8_cnt & 3) == 0) {
                        v &= 0xff;
+               }
                imm8_cnt++;
                put_word_test(pc, v);
                *isconstant = 16;
@@ -1687,10 +1846,11 @@ static int create_ea_random(uae_u16 *opcodep, uaecptr pc, int mode, int reg, str
                                }
                        } else {
                                uae_u16 v = rand16();
-                               if ((imm16_cnt & 7) == 0)
+                               if ((imm16_cnt & 7) == 0) {
                                        v &= 0x00ff;
-                               if ((imm16_cnt & 15) == 0)
-                                       v &= 0x000f;
+                               } else if ((imm16_cnt & 15) == 0) {
+                                       v = 0;
+                               }
                                imm16_cnt++;
                                put_word_test(pc, v);
                                *isconstant = 16;
@@ -1703,7 +1863,9 @@ static int create_ea_random(uae_u16 *opcodep, uaecptr pc, int mode, int reg, str
        {
                // long immediate
                uae_u32 v = rand32();
-               if ((imm32_cnt & 7) == 0) {
+               if ((imm32_cnt & 63) == 0) {
+                       v = 0;
+               } else if ((imm32_cnt & 7) == 0) {
                        v &= 0x0000ffff;
                }
                imm32_cnt++;
@@ -1951,7 +2113,7 @@ static int handle_specials_branch(uae_u16 opcode, uaecptr pc, struct instr *dp,
        return 0;
 }
 
-static int handle_specials_pack(uae_u16 opcode, uaecptr pc, struct instr *dp, int *isconstant)
+static int handle_specials_misc(uae_u16 opcode, uaecptr pc, struct instr *dp, int *isconstant)
 {
        // PACK and UNPK has third parameter
        if (dp->mnemo == i_PACK || dp->mnemo == i_UNPK) {
@@ -1959,6 +2121,12 @@ static int handle_specials_pack(uae_u16 opcode, uaecptr pc, struct instr *dp, in
                put_word_test(pc, v);
                *isconstant = 16;
                return 2;
+       } else if (dp->mnemo == i_CALLM) {
+               // CALLM has extra parameter
+               uae_u16 v = rand16();
+               put_word_test(pc, v);
+               *isconstant = 16;
+               return 2;
        }
        return 0;
 }
@@ -2177,8 +2345,8 @@ static void execute_ins(uae_u16 opc, uaecptr endpc, uaecptr targetpc, struct ins
 {
        uae_u16 opw1 = (opcode_memory[2] << 8) | (opcode_memory[3] << 0);
        uae_u16 opw2 = (opcode_memory[4] << 8) | (opcode_memory[5] << 0);
-       if (opc == 0x89c2
-               //&& opw1 == 0xcf19
+       if (opc == 0xf23d
+               //&& opw1 == 0xee38
                //&& opw2 == 0x504e
                )
                printf("");
@@ -2262,7 +2430,7 @@ static void execute_ins(uae_u16 opc, uaecptr endpc, uaecptr targetpc, struct ins
                        break;
 
                if (!feature_loop_mode && !multi_mode) {
-                       wprintf(_T("Test instruction didn't finish in single step in non-loop mode!?\n"));
+                       wprintf(_T(" Test instruction didn't finish in single step in non-loop mode!?\n"));
                        abort();
                }
 
@@ -2274,7 +2442,7 @@ static void execute_ins(uae_u16 opc, uaecptr endpc, uaecptr targetpc, struct ins
 
                cnt--;
                if (cnt <= 0) {
-                       wprintf(_T("Loop mode didn't end!?\n"));
+                       wprintf(_T(" Loop mode didn't end!?\n"));
                        abort();
                }
        }
@@ -2345,6 +2513,8 @@ static int isunsupported(struct instr *dp)
        case i_CINVP:
        case i_PLPAR:
        case i_PLPAW:
+       case i_CALLM:
+       case i_RTM:
                return 1;
        }
        return 0;
@@ -2568,13 +2738,15 @@ static void test_mnemo(const TCHAR *path, const TCHAR *mnemo, const TCHAR *ovrfi
                if (size == 3 && !dp->unsized)
                        continue;
                // skip all unsupported instructions if not specifically testing i_ILLG
-               if (dp->clev > cpu_lvl && lookup->mnemo != i_ILLG)
-                       continue;
+               if (lookup->mnemo != i_ILLG) {
+                       if (dp->clev > cpu_lvl)
+                               continue;
+                       if (isunsupported(dp))
+                               return;
+                       if (isfpp(lookup->mnemo) && !currprefs.fpu_model)
+                               return;
+               }
                opcodecnt++;
-               if (isunsupported(dp))
-                       return;
-               if (isfpp(lookup->mnemo) && !currprefs.fpu_model)
-                       return;
                fpumode = currprefs.fpu_model && isfpp(lookup->mnemo);
        }
 
@@ -2590,7 +2762,7 @@ 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] = test_memory_end - STACK_SIZE;
+       registers[8 + 7] = user_stack_memory;
 
        uae_u32 target_address = 0xffffffff;
        target_ea[0] = 0xffffffff;
@@ -2734,6 +2906,7 @@ static void test_mnemo(const TCHAR *path, const TCHAR *mnemo, const TCHAR *ovrfi
                                target_ea[1] = target_ea_bak[1];
                                target_address = target_address_bak;
 
+                               reset_ea_state();
                                // retry few times if out of bounds access
                                int oob_retries = 10;
                                // if instruction has immediate(s), repeat instruction test multiple times
@@ -2787,9 +2960,9 @@ static void test_mnemo(const TCHAR *path, const TCHAR *mnemo, const TCHAR *ovrfi
                                        uae_u8 *ao = opcode_memory + 2;
                                        uae_u16 apw1 = (ao[0] << 8) | (ao[1] << 0);
                                        uae_u16 apw2 = (ao[2] << 8) | (ao[3] << 0);
-                                       if (opc == 0x48a8
-                                               && apw1 == 0x0000
-                                               //&& apw2 == 0xfff0
+                                       if (opc == 0x4eb1
+                                               && apw1 == 0xee38
+                                               //&& apw2 == 0x7479
                                                )
                                                printf("");
 
@@ -2856,8 +3029,8 @@ static void test_mnemo(const TCHAR *path, const TCHAR *mnemo, const TCHAR *ovrfi
 
                                        // bcc.x
                                        pc += handle_specials_branch(opc, pc, dp, &isconstant_src);
-                                       // pack
-                                       pc += handle_specials_pack(opc, pc, dp, &isconstant_src);
+                                       // misc
+                                       pc += handle_specials_misc(opc, pc, dp, &isconstant_src);
 
                                        put_word_test(opcode_memory_start, opc);
 
@@ -3095,10 +3268,10 @@ static void test_mnemo(const TCHAR *path, const TCHAR *mnemo, const TCHAR *ovrfi
                                                        }
                                                        regs.sr |= feature_min_interrupt_mask << 8;
                                                        regs.usp = regs.regs[8 + 7];
-                                                       regs.isp = test_memory_end - 0x80;
+                                                       regs.isp = super_stack_memory - 0x80;
                                                        // copy user stack to super stack, for RTE etc support
-                                                       memcpy(regs.isp - test_memory_start + test_memory, regs.usp - test_memory_start + test_memory, 0x20);
-                                                       regs.msp = test_memory_end;
+                                                       memcpy(test_memory + (regs.isp - test_memory_start), test_memory + (regs.usp - test_memory_start), 0x20);
+                                                       regs.msp = super_stack_memory;
 
                                                        // data size optimization, only store data
                                                        // if it is different than in previous round
@@ -3614,6 +3787,15 @@ int __cdecl main(int argc, char *argv[])
        safe_memory_end = 0xffffffff;
        if (ini_getval(ini, INISECTION, _T("feature_safe_memory_size"), &v))
                safe_memory_end = safe_memory_start + v;
+       safe_memory_mode = 3;
+       if (ini_getstring(ini, INISECTION, _T("feature_safe_memory_mode"), &vs)) {
+               safe_memory_mode = 0;
+               if (_totupper(vs[0]) == 'R')
+                       safe_memory_mode |= 1;
+               if (_totupper(vs[0]) == 'W')
+                       safe_memory_mode |= 2;
+               xfree(vs);
+       }
 
        feature_sr_mask = 0;
        ini_getval(ini, INISECTION, _T("feature_sr_mask"), &feature_sr_mask);
@@ -3748,8 +3930,25 @@ int __cdecl main(int argc, char *argv[])
                return 0;
        }
 
-       opcode_memory = test_memory + test_memory_size / 2;
-       opcode_memory_start = test_memory_start + test_memory_size / 2;
+       v = 0;
+       if (ini_getval(ini, INISECTION, _T("feature_opcode_memory"), &v)) {
+               opcode_memory_start = v;
+               opcode_memory = test_memory + (opcode_memory_start - test_memory_start);
+       } else {
+               opcode_memory = test_memory + test_memory_size / 2;
+               opcode_memory_start = test_memory_start + test_memory_size / 2;
+       }
+       if (opcode_memory_start < opcode_memory_start || opcode_memory_start > test_memory_start + test_memory_size - 256) {
+               wprintf(_T("Opcode memory out of bounds\n"));
+               return 0;
+       }
+       if (ini_getval(ini, INISECTION, _T("feature_stack_memory"), &v)) {
+               super_stack_memory = v;
+               user_stack_memory = super_stack_memory - (RESERVED_SUPERSTACK + RESERVED_USERSTACK_EXTRA);
+       } else {
+               super_stack_memory = test_memory_end;
+               user_stack_memory = test_memory_end - (RESERVED_SUPERSTACK + RESERVED_USERSTACK_EXTRA);
+       }
 
        low_memory_size = test_low_memory_end;
        if (low_memory_size < 0x8000)
index 2efcbee498a3e8e88c88ff2ff58dc9edf7f35096..0eaa71f20bdee9e3de2dc6129c10cd3242316bb6 100644 (file)
@@ -1,5 +1,5 @@
 
-#define DATA_VERSION 4
+#define DATA_VERSION 5
 
 #define CT_FPREG 0
 #define CT_DREG 0
index 77dfb08a605197cda46e5745e9d848d4057afaf7..eae5dc002223a96d6eda47b4a0d663741ebec9be 100644 (file)
@@ -64,6 +64,7 @@ static uae_u32 test_memory_addr, test_memory_end;
 static uae_u32 test_memory_size;
 static uae_u8 *test_data;
 static uae_u8 *safe_memory_start, *safe_memory_end;
+static uae_u32 user_stack_memory, super_stack_memory;
 static int test_data_size;
 static uae_u32 oldvbr;
 static uae_u8 *vbr_zero = 0;
@@ -218,22 +219,22 @@ static void endinfo(void)
 static void safe_memcpy(uae_u8 *d, uae_u8 *s, int size)
 {
        if (safe_memory_start == (uae_u8*)0xffffffff && safe_memory_end == (uae_u8*)0xffffffff) {
-               memcpy(d, s, size);
+               xmemcpy(d, s, size);
                return;
        }
        if (safe_memory_end <= d || safe_memory_start >= d + size) {
                if (safe_memory_end <= s || safe_memory_start >= s + size) {
-                       memcpy(d, s, size);
+                       xmemcpy(d, s, size);
                        return;
                }
        }
        while (size > 0) {
                int size2 = size > sizeof(tmpbuffer) ? sizeof(tmpbuffer) : size;
                if ((d + size2 > safe_memory_start && d < safe_memory_end) ||
-                       (s + size2 > safe_memory_start && d < safe_memory_end)) {
+                       (s + size2 > safe_memory_start && s < safe_memory_end)) {
                        for (int i = 0; i < size2; i++) {
                                if ((d >= safe_memory_start && d < safe_memory_end) ||
-                                       (s >= safe_memory_start && d < safe_memory_end)) {
+                                       (s >= safe_memory_start && s < safe_memory_end)) {
                                        s++;
                                        d++;
                                        continue;
@@ -241,7 +242,7 @@ static void safe_memcpy(uae_u8 *d, uae_u8 *s, int size)
                                *d++ = *s++;
                        }
                } else {
-                       memcpy(d, s, size2);
+                       xmemcpy(d, s, size2);
                        d += size2;
                        s += size2;
                }
@@ -730,7 +731,7 @@ static uae_u8 *restore_memory(uae_u8 *p, int storedata)
                                v &= 31;
                                if (v == 0)
                                        v = 32;
-                               memcpy(addr, p, v);
+                               xmemcpy(addr, p, v);
                                p += v;
                                break;
                        }
@@ -995,7 +996,7 @@ static void out_regs(struct registers *r, int before)
        sprintf(outbp, "SR:%c%04x   PC: %08lx ISP: %08lx", test_sr != last_registers.sr ? '*' : ' ', before ? test_sr : test_regs.sr, r->pc, r->ssp);
        outbp += strlen(outbp);
        if (cpu_lvl >= 2 && cpu_lvl <= 4) {
-               sprintf(outbp, " MSP: %08lx\n", r->msp);
+               sprintf(outbp, " MSP: %08lx", r->msp);
                outbp += strlen(outbp);
        }
        *outbp++ = '\n';
@@ -1013,13 +1014,11 @@ static void out_regs(struct registers *r, int before)
                                (s2 & mask) != (s3 & mask) ? '!' : ((s1 & mask) != (s2 & mask) ? '*' : '='), (s & mask) != 0);
                        outbp += strlen(outbp);
                }
+               *outbp++ = '\n';
        }
 
-       if (!fpu_model) {
-               strcat(outbp, "\n");
-               outbp += strlen(outbp);
+       if (!fpu_model)
                return;
-       }
 
        for (int i = 0; i < 8; i++) {
                if ((i % 2) == 0) {
@@ -1322,7 +1321,7 @@ static uae_u8 *validate_test(uae_u8 *p, int ignore_errors, int ignore_sr)
                                errors++;
                        }
                        regs_fpuchanged[mode] = 0;
-                       memcpy(&last_registers.fpuregs[mode], &val, sizeof(struct fpureg));
+                       xmemcpy(&last_registers.fpuregs[mode], &val, sizeof(struct fpureg));
                } else if (mode == CT_SR) {
                        uae_u32 val = last_registers.sr;
                        int size;
@@ -1615,13 +1614,13 @@ static void process_test(uae_u8 *p)
                        }
                        for (int ccr = 0;  ccr < maxccr; ccr++) {
 
-                               regs.ssp = test_memory_addr + test_memory_size - 0x80;
-                               regs.msp = test_memory_addr + test_memory_size;
+                               regs.ssp = super_stack_memory - 0x80;
+                               regs.msp = super_stack_memory;
                                regs.pc = opcode_memory_addr;
                                regs.fpiar = opcode_memory_addr;
 
 #ifdef M68K
-                               memcpy((void*)regs.ssp, (void*)regs.regs[15], 0x20);
+                               xmemcpy((void*)regs.ssp, (void*)regs.regs[15], 0x20);
 #endif
                                xmemcpy(&test_regs, &regs, sizeof(struct registers));
 
@@ -1788,7 +1787,8 @@ static int test_mnemo(const char *path, const char *opcode)
        test_memory_size = gl(data);
        test_memory_end = test_memory_addr + test_memory_size;
        fread(data, 1, 4, f);
-       opcode_memory_addr = gl(data) + test_memory_addr;
+       opcode_memory_addr = gl(data);
+       opcode_memory = (uae_u8*)opcode_memory_addr;
        fread(data, 1, 4, f);
        lvl = (gl(data) >> 16) & 15;
        interrupt_mask = (gl(data) >> 20) & 7;
@@ -1810,7 +1810,9 @@ static int test_mnemo(const char *path, const char *opcode)
        fread(data, 1, 4, f);
        safe_memory_end = (uae_u8*)gl(data);
        fread(data, 1, 4, f);
+       user_stack_memory = gl(data);
        fread(data, 1, 4, f);
+       super_stack_memory = gl(data);
        fread(inst_name, 1, sizeof(inst_name) - 1, f);
        inst_name[sizeof(inst_name) - 1] = 0;
 
@@ -1859,8 +1861,6 @@ static int test_mnemo(const char *path, const char *opcode)
                exit(0);
        }
 
-       opcode_memory = test_memory + (opcode_memory_addr - test_memory_addr);
-
        size = test_memory_size;
        load_file(path, "tmem.dat", test_memory, &size, 1);
        if (size != test_memory_size) {
@@ -1868,7 +1868,9 @@ static int test_mnemo(const char *path, const char *opcode)
                exit(0);
        }
 
-       printf("CPUlvl=%d, Mask=%08lx Code=%08lx\n", cpu_lvl, addressing_mask, opcode_memory);
+       printf("CPUlvl=%d, Mask=%08lx Code=%08lx SP=%08lx ISP=%08lx\n",
+               cpu_lvl, addressing_mask, opcode_memory,
+               user_stack_memory, super_stack_memory);
        printf(" Low: %08lx-%08lx High: %08lx-%08lx\n",
                test_low_memory_start, test_low_memory_end,
                test_high_memory_start, test_high_memory_end);
index bd72d41cc291a1ab514fe221b8132d9e30379972..6438b2a3b6704beb78c6d5de243ea4ee57c84363 100644 (file)
@@ -182,6 +182,10 @@ uaecptr ShowEA_disp(uaecptr *pcp, uaecptr base, TCHAR *buffer, const TCHAR *name
                _stprintf(mult, _T("*%d"), m);
        }
 
+       if (currprefs.cpu_model >= 68020) {
+               dispreg <<= (dp >> 9) & 3; // SCALE
+       }
+
        if (buffer)
                buffer[0] = 0;
        if ((dp & 0x100) && currprefs.cpu_model >= 68020) {
@@ -190,7 +194,6 @@ uaecptr ShowEA_disp(uaecptr *pcp, uaecptr base, TCHAR *buffer, const TCHAR *name
 
                // Full format extension (68020+)
 
-               dispreg <<= (dp >> 9) & 3; // SCALE
                if (dp & 0x80) { // BS (base register suppress)
                        base = 0;
                        if (buffer)
@@ -1850,6 +1853,11 @@ uae_u32 m68k_disasm_2 (TCHAR *buf, int bufsize, uaecptr pc, uaecptr *nextpc, int
                                _stprintf(instrname, _T("ILLG #$%04x"), extra);
                                pc += 2;
                        }
+               } else if (lookup->mnemo == i_CALLM) {
+                       TCHAR *p = instrname + _tcslen(instrname);
+                       _stprintf(p, _T("#%d,"), extra & 255);
+                       pc = ShowEA(NULL, pc, opcode, dp->sreg, dp->smode, dp->size, instrname, &seaddr2, &actualea_src, safemode);
+                       pc += 2;
                } else if (lookup->mnemo == i_FDBcc) {
                        pc = ShowEA(NULL, pc, opcode, dp->dreg, dp->dmode, dp->size, instrname, &seaddr2, &actualea_src, safemode);
                        pc += 2;
index 8a6706ec740f4ef22d796e7899b15a9a12c55b06..2b25e5b3b1dc72b8d2e9a29cc0b23eac53d85a90 100644 (file)
@@ -1395,7 +1395,7 @@ static void move_68000_bus_error(int offset, int size, int *setapdi, int *fcmode
 static char const *bus_error_reg;
 static int bus_error_reg_add;
 
-static void do_bus_error_fixes(const char *name, int offset)
+static void do_bus_error_fixes(const char *name, int offset, int write)
 {
        switch (bus_error_reg_add)
        {
@@ -1456,7 +1456,7 @@ static void check_bus_error(const char *name, int offset, int write, int size, c
                        move_68000_bus_error(offset, g_instr->size, &setapdiback, &fc);
                }
 
-               do_bus_error_fixes(name, offset);
+               do_bus_error_fixes(name, offset, write);
 
                if (g_instr->mnemo == i_BTST && (g_instr->dmode == PC16 || g_instr->dmode == PC8r)) {
                        // BTST special case where destination is read access
@@ -1472,8 +1472,13 @@ static void check_bus_error(const char *name, int offset, int write, int size, c
                }
 
                // 68010 bus/address error HB bit
-               if (extra && cpu_level == 1)
+               if (extra && cpu_level == 1) {
                        printf("\t\topcode |= 0x%x;\n", extra);
+               }
+
+               if (cpu_level == 0 && write) {
+                       printf("\t\topcode = regs.irc;\n");
+               }
 
                if (write) {
                        printf("\t\texception2_write(opcode, %sa + %d, %d, %s, %d);\n",
@@ -2425,7 +2430,7 @@ static void genamode2x (amodes mode, const char *reg, wordsizes size, const char
                                if (mode == Apdi)
                                        bus_error_reg_add = 0;
                        }
-                       do_bus_error_fixes(name, 0);
+                       do_bus_error_fixes(name, 0, getv == 2);
                        // x,-(an): an is modified
                        if (mode == Apdi && g_instr->size == sz_word && g_instr->mnemo != i_CLR) {
                                printf("\t\tm68k_areg (regs, %s) = %sa;\n", reg, name);
@@ -2831,7 +2836,7 @@ static void genastore_2 (const char *from, amodes mode, const char *reg, wordsiz
                                                genflags(flag_logical, g_instr->size, "src", "", "");
                                        }
                                        printf ("\t%s (%sa + 2, %s);\n", dstwx, to, from);
-                                       check_bus_error(to, 2, 1, 1, "from", 1);
+                                       check_bus_error(to, 2, 1, 1, from, 1);
                                }
                                count_write += 2;
                                break;
index 915e8def0c86ec81225204ec0d6afbf64e024b59..4c8a950f5c0940ecbb0d248f8b10218fc3923c09 100644 (file)
@@ -694,6 +694,7 @@ extern void Exception_build_stack_frame(uae_u32 oldpc, uae_u32 currpc, uae_u32 s
 extern void Exception_build_68000_address_error_stack_frame(uae_u16 mode, uae_u16 opcode, uaecptr fault_addr, uaecptr pc);
 extern uae_u32 exception_pc(int nr);
 extern void cpu_restore_fixup(void);
+extern bool privileged_copro_instruction(uae_u16 opcode);
 
 void ccr_68000_long_move_ae_LZN(uae_s32 src);
 void ccr_68000_long_move_ae_LN(uae_s32 src);
index 1365e6611fea31478634368fb6d114bf64a1d685..13afd9342adb5622485ec5bd425efa6ff3496a0b 100644 (file)
@@ -3390,11 +3390,16 @@ uae_u32 REGPARAM2 op_illg (uae_u32 opcode)
 #endif
 
        if ((opcode & 0xF000) == 0xF000) {
-               if (warned < 20) {
-                       write_log(_T("B-Trap %04X at %08X -> %08X\n"), opcode, pc, get_long_debug(regs.vbr + 0x2c));
-                       warned++;
+               // 68020 MMU or 020/030 FPU cpSAVE/cpRESTORE privilege check
+               if (privileged_copro_instruction(opcode)) {
+                       Exception(8);
+               } else {
+                       if (warned < 20) {
+                               write_log(_T("B-Trap %04X at %08X -> %08X\n"), opcode, pc, get_long_debug(regs.vbr + 0x2c));
+                               warned++;
+                       }
+                       Exception(0xB);
                }
-               Exception (0xB);
                //activate_debugger_new();
                return 4;
        }
index 7f528433d51be2350137da4be2dc07a78755050c..ad1d1f0ca49ebcba1eae5aa9ec7160a39682b418 100644 (file)
@@ -1618,4 +1618,26 @@ void ccr_68000_word_move_ae_normal(uae_s16 src)
        SET_NFLG(src < 0);
 }
 
-
+bool privileged_copro_instruction(uae_u16 opcode)
+{
+       if ((currprefs.cpu_model == 68020 || currprefs.cpu_model == 68030) && !regs.s) {
+               int reg = opcode & 7;
+               int mode = (opcode >> 3) & 7;
+               int id = (opcode >> 9) & 7;
+               // cpSAVE and cpRESTORE: privilege violation if user mode.
+               if ((opcode & 0xf1c0) == 0xf100) {
+                       // cpSAVE
+                       if (mode == 2 || (mode >= 4 && mode <= 6) || (mode == 7 && (reg == 0 || reg == 1))) {
+                               if (currprefs.cpu_model == 68020 || (currprefs.cpu_model == 68030 && id >= 2))
+                                       return true;
+                       }
+               } else if ((opcode & 0xf1c0) == 0xf140) {
+                       // cpRESTORE
+                       if (mode == 2 || mode == 3 || (mode >= 5 && mode <= 6) || (mode == 7 && reg <= 3)) {
+                               if (currprefs.cpu_model == 68020 || (currprefs.cpu_model == 68030 && id >= 2))
+                                       return true;
+                       }
+               }
+       }
+       return false;
+}