From: Toni Wilen Date: Fri, 25 Oct 2019 17:41:02 +0000 (+0300) Subject: Tester updates, configurable stack and opcode space, CALLM disassembly, cpRESTORE... X-Git-Tag: 4300~69 X-Git-Url: https://git.unchartedbackwaters.co.uk/w/?a=commitdiff_plain;h=e7f6b2fa45c4e0ea7a87c6239a8d87f8212f27fe;p=francis%2Fwinuae.git Tester updates, configurable stack and opcode space, CALLM disassembly, cpRESTORE/cpSAVE checks for supervisor mode even if co-pro is missing. --- diff --git a/cputest.cpp b/cputest.cpp index fb27b6d2..e5cfc736 100644 --- a/cputest.cpp +++ b/cputest.cpp @@ -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) diff --git a/cputest/cputest_defines.h b/cputest/cputest_defines.h index 2efcbee4..0eaa71f2 100644 --- a/cputest/cputest_defines.h +++ b/cputest/cputest_defines.h @@ -1,5 +1,5 @@ -#define DATA_VERSION 4 +#define DATA_VERSION 5 #define CT_FPREG 0 #define CT_DREG 0 diff --git a/cputest/main.c b/cputest/main.c index 77dfb08a..eae5dc00 100644 --- a/cputest/main.c +++ b/cputest/main.c @@ -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, ®s, 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); diff --git a/disasm.cpp b/disasm.cpp index bd72d41c..6438b2a3 100644 --- a/disasm.cpp +++ b/disasm.cpp @@ -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; diff --git a/gencpu.cpp b/gencpu.cpp index 8a6706ec..2b25e5b3 100644 --- a/gencpu.cpp +++ b/gencpu.cpp @@ -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; diff --git a/include/newcpu.h b/include/newcpu.h index 915e8def..4c8a950f 100644 --- a/include/newcpu.h +++ b/include/newcpu.h @@ -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); diff --git a/newcpu.cpp b/newcpu.cpp index 1365e661..13afd934 100644 --- a/newcpu.cpp +++ b/newcpu.cpp @@ -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; } diff --git a/newcpu_common.cpp b/newcpu_common.cpp index 7f528433..ad1d1f0c 100644 --- a/newcpu_common.cpp +++ b/newcpu_common.cpp @@ -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; +}