From eb319d727a11cc14185d6927344fadf5ffacf4be Mon Sep 17 00:00:00 2001 From: Toni Wilen Date: Sat, 7 Dec 2019 15:14:50 +0200 Subject: [PATCH] Preparation for improved 68010 bus error checks. Odd user stack option added. LINK causing address error due to odd stack: A7->An copy is already done. --- cputest.cpp | 20 ++++++++++++++++++-- gencpu.cpp | 45 +++++++++++++++++++++++++++++++++++++++++---- 2 files changed, 59 insertions(+), 6 deletions(-) diff --git a/cputest.cpp b/cputest.cpp index 05984438..327bc330 100644 --- a/cputest.cpp +++ b/cputest.cpp @@ -66,6 +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 TCHAR *feature_instruction_size = NULL; static uae_u32 feature_addressing_modes[2]; static int ad8r[2], pc8r[2]; @@ -96,6 +97,7 @@ 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_u32 user_stack_memory_use; static uae_u8 *low_memory, *high_memory, *test_memory; static uae_u8 *low_memory_temp, *high_memory_temp, *test_memory_temp; @@ -942,6 +944,7 @@ void exception2_read(uae_u32 opcode, uaecptr addr, int size, int fc) test_exception_3_fc = fc; test_exception_3_size = size; test_exception_3_di = 1; + regs.read_buffer = 0; if (currprefs.cpu_model == 68000) { if (generates_group1_exception(regs.ir)) { @@ -987,6 +990,7 @@ void exception3_read(uae_u32 opcode, uae_u32 addr, int size, int fc) test_exception_3_fc = fc; test_exception_3_size = size; test_exception_3_di = 1; + regs.read_buffer = 0; if (currprefs.cpu_model == 68000) { if (generates_group1_exception(regs.ir)) { @@ -1446,7 +1450,7 @@ 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, user_stack_memory); + pl(data, user_stack_memory_use); fwrite(data, 1, 4, f); pl(data, super_stack_memory); fwrite(data, 1, 4, f); @@ -2501,6 +2505,12 @@ static void execute_ins(uae_u16 opc, uaecptr endpc, uaecptr targetpc, struct ins for (;;) { + // if supervisor stack is odd: exit + if (regs.s && (regs.isp & 1)) { + test_exception = -1; + break; + } + if (cnt <= 0) { wprintf(_T(" Loop mode didn't end!?\n")); abort(); @@ -2921,7 +2931,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] = user_stack_memory; + registers[8 + 7] = user_stack_memory_use; uae_u32 target_address = 0xffffffff; target_ea[0] = 0xffffffff; @@ -4086,6 +4096,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_full_extension_format = 0; if (currprefs.cpu_model >= 68020) { @@ -4226,6 +4238,10 @@ int __cdecl main(int argc, char *argv[]) super_stack_memory = test_memory_start + (2 * RESERVED_SUPERSTACK + RESERVED_USERSTACK_EXTRA); user_stack_memory = test_memory_start + RESERVED_SUPERSTACK; } + user_stack_memory_use = user_stack_memory; + if (feature_odd_usp) { + user_stack_memory_use |= 1; + } low_memory_size = test_low_memory_end; if (low_memory_size < 0x8000) diff --git a/gencpu.cpp b/gencpu.cpp index 38d5892e..3e3c88e0 100644 --- a/gencpu.cpp +++ b/gencpu.cpp @@ -102,6 +102,7 @@ static bool candormw; static bool genastore_done; static char rmw_varname[100]; static struct instr *g_instr; +static char g_srcname[100]; #define GENA_GETV_NO_FETCH 0 #define GENA_GETV_FETCH 1 @@ -1516,6 +1517,11 @@ static void check_bus_error(const char *name, int offset, int write, int size, c fc = 2; } + if (g_instr->mnemo == i_LINK) { + // a7 -> a0 copy done before A7 address error check + printf("\tm68k_areg(regs, srcreg) = olda;\n"); + } + if (cpu_level == 1 && g_instr->mnemo == i_MVSR2 && !write) { printf("\t\topcode |= 0x20000;\n"); // upper byte of SSW is zero -flag. } @@ -2120,6 +2126,7 @@ static void genamode2x (amodes mode, const char *reg, wordsizes size, const char int pc_68000_offset = m68k_pc_offset; int pc_68000_offset_fetch = 0; int pc_68000_offset_store = 0; + bool addr = false; sprintf (namea, "%sa", name); if ((flags & GF_RMW) && using_mmu == 68060) { @@ -2164,6 +2171,7 @@ static void genamode2x (amodes mode, const char *reg, wordsizes size, const char } maybeaddop_ce020 (flags); syncmovepc (getv, flags); + strcpy(g_srcname, name); return; case Areg: if (movem) @@ -2181,6 +2189,7 @@ static void genamode2x (amodes mode, const char *reg, wordsizes size, const char } maybeaddop_ce020 (flags); syncmovepc (getv, flags); + strcpy(g_srcname, name); return; case Aind: // (An) switch (fetchmode) @@ -2198,6 +2207,7 @@ static void genamode2x (amodes mode, const char *reg, wordsizes size, const char printf ("\tuaecptr %sa;\n", name); add_mmu040_movem (movem); printf ("\t%sa = m68k_areg (regs, %s);\n", name, reg); + addr = true; break; case Aipi: // (An)+ switch (fetchmode) @@ -2211,6 +2221,7 @@ static void genamode2x (amodes mode, const char *reg, wordsizes size, const char printf ("\tuaecptr %sa;\n", name); add_mmu040_movem (movem); printf ("\t%sa = m68k_areg (regs, %s);\n", name, reg); + addr = true; break; case Apdi: // -(An) switch (fetchmode) @@ -2246,18 +2257,21 @@ static void genamode2x (amodes mode, const char *reg, wordsizes size, const char if (size == sz_long) pc_68000_offset_fetch -= 2; } + addr = true; break; case Ad16: // (d16,An) printf ("\tuaecptr %sa;\n", name); add_mmu040_movem (movem); printf ("\t%sa = m68k_areg (regs, %s) + (uae_s32)(uae_s16)%s;\n", name, reg, gen_nextiword (flags)); count_read_ea++; + addr = true; break; case PC16: // (d16,PC) printf ("\tuaecptr %sa;\n", name); add_mmu040_movem (movem); printf ("\t%sa = %s + %d;\n", name, getpc, m68k_pc_offset); printf ("\t%sa += (uae_s32)(uae_s16)%s;\n", name, gen_nextiword (flags)); + addr = true; break; case Ad8r: // (d8,An,Xn) switch (fetchmode) @@ -2292,6 +2306,7 @@ static void genamode2x (amodes mode, const char *reg, wordsizes size, const char } count_read_ea++; } + addr = true; break; case PC8r: // (d8,PC,Xn) switch (fetchmode) @@ -2328,19 +2343,21 @@ static void genamode2x (amodes mode, const char *reg, wordsizes size, const char printf ("\t%sa = %s (tmppc, %s);\n", name, disp000, gen_nextiword (flags)); } } - + addr = true; break; case absw: printf ("\tuaecptr %sa;\n", name); add_mmu040_movem (movem); printf ("\t%sa = (uae_s32)(uae_s16)%s;\n", name, gen_nextiword (flags)); pc_68000_offset_fetch += 2; + addr = true; break; case absl: gen_nextilong2 ("uaecptr", namea, flags, movem); count_read_ea += 2; pc_68000_offset_fetch += 4; pc_68000_offset_store += 2; + addr = true; break; case imm: // fetch immediate address @@ -2366,6 +2383,7 @@ static void genamode2x (amodes mode, const char *reg, wordsizes size, const char do_instruction_buserror(); maybeaddop_ce020 (flags); syncmovepc (getv, flags); + strcpy(g_srcname, name); return; case imm0: if (getv != 1) @@ -2374,6 +2392,7 @@ static void genamode2x (amodes mode, const char *reg, wordsizes size, const char count_read_ea++; maybeaddop_ce020 (flags); syncmovepc (getv, flags); + strcpy(g_srcname, name); return; case imm1: if (getv != 1) @@ -2382,6 +2401,7 @@ static void genamode2x (amodes mode, const char *reg, wordsizes size, const char count_read_ea++; maybeaddop_ce020 (flags); syncmovepc (getv, flags); + strcpy(g_srcname, name); return; case imm2: if (getv != 1) @@ -2390,6 +2410,7 @@ static void genamode2x (amodes mode, const char *reg, wordsizes size, const char count_read_ea += 2; maybeaddop_ce020 (flags); syncmovepc (getv, flags); + strcpy(g_srcname, name); return; case immi: if (getv != 1) @@ -2397,15 +2418,24 @@ static void genamode2x (amodes mode, const char *reg, wordsizes size, const char printf ("\tuae_u32 %s = %s;\n", name, reg); maybeaddop_ce020 (flags); syncmovepc (getv, flags); + strcpy(g_srcname, name); return; case am_unknown: // reg = internal variable printf("\tuae_u32 %sa = %s;\n", name, reg); + addr = true; break; default: term (); } + if (g_srcname[0] == 0) { + if (addr) + strcpy(g_srcname, namea); + else + strcpy(g_srcname, name); + } + do_instruction_buserror(); syncmovepc (getv, flags); @@ -2482,13 +2512,14 @@ static void genamode2x (amodes mode, const char *reg, wordsizes size, const char if (g_instr->size == sz_word) { printf("\t\tm68k_areg (regs, %s) = %sa;\n", reg, name); } - } else if (mode == Apdi) { + } else if (mode == Apdi && g_instr->mnemo != i_LINK) { // 68000 decrements register first, then checks for address error // 68010 does not if (cpu_level == 0) setapdiback = 1; } + if (exception_pc_offset) incpc("%d", exception_pc_offset); @@ -2503,6 +2534,10 @@ static void genamode2x (amodes mode, const char *reg, wordsizes size, const char if (cpu_level == 1) { printf("\t\topcode |= 0x20000;\n"); // upper byte of SSW is zero -flag. } + } else if (g_instr->mnemo == i_LINK) { + // a7 -> a0 copy done before A7 address error check + printf("\tm68k_areg(regs, srcreg) = olda;\n"); + setapdiback = 0; } if (setapdiback) { @@ -2514,8 +2549,9 @@ static void genamode2x (amodes mode, const char *reg, wordsizes size, const char printf("\t\t%sa += %d;\n", name, flags & GF_REVERSE2 ? -2 : 2); if (exp3rw) { - printf("\t\texception3_write(opcode, %sa, %d, %s, %d);\n", - name, size, "0", + char *shift = size == sz_long ? " >> 16" : ""; + printf("\t\texception3_write(opcode, %sa, %d, %s%s, %d);\n", + name, size, g_srcname, shift, // PC-relative: FC=2 (getv == 1 && (g_instr->smode == PC16 || g_instr->smode == PC8r) ? 2 : 1) | fcmodeflags); @@ -3968,6 +4004,7 @@ static void gen_opcode (unsigned int opcode) m68k_pc_offset = 2; g_instr = curi; + g_srcname[0] = 0; // do not unnecessarily create useless mmuop030 // functions when CPU is not 68030 -- 2.47.3