From ed24e2a08e7e374c71578894dfcd347f2466cb94 Mon Sep 17 00:00:00 2001 From: Toni Wilen Date: Tue, 21 Jul 2020 21:53:56 +0300 Subject: [PATCH] JIT loop mode improved CCR error checking and reporting. --- cputest.cpp | 116 ++++++++++++++++++++++++++++++----------- cputest/cputestgen.ini | 3 +- cputest/main.c | 68 ++++++++++++++++++++++-- 3 files changed, 153 insertions(+), 34 deletions(-) diff --git a/cputest.cpp b/cputest.cpp index 8db40d67..30db6f02 100644 --- a/cputest.cpp +++ b/cputest.cpp @@ -68,7 +68,6 @@ static int feature_flag_mode = 0; static int feature_usp = 0; static int feature_exception_vectors = 0; static int feature_interrupts = 0; -static int feature_randomize = 0; static int feature_instruction_size = 0; static TCHAR *feature_instruction_size_text = NULL; static uae_u32 feature_addressing_modes[2]; @@ -166,7 +165,7 @@ static uae_u16 extra_or, extra_and; static struct regstruct cur_regs; static uae_u16 read_buffer_prev; static int interrupt_count; -static int interrupt_cycle_cnt; +static int interrupt_cycle_cnt, interrupt_delay_cnt; static int interrupt_level; static uaecptr test_instruction_end_pc; @@ -450,7 +449,7 @@ uae_u32 get_ilong_test(uaecptr addr) uae_u16 v1 = get_iword_test(addr + 2); v = (v0 << 16) | (v1 << 0); } else { - uae_u8 *p = get_addr(addr, 4, 1); + uae_u8 *p = get_addr(addr, 4, 4); v = (p[0] << 24) | (p[1] << 16) | (p[2] << 8) | (p[3]); add_memory_cycles(2); } @@ -1786,6 +1785,9 @@ static bool regchange(int reg, uae_u32 *regs) v ^= 0x8000; break; case 12: + if (feature_loop_mode && !feature_loop_mode_68010) { + return false; + } v ^= 0x80000000; v = (v & 0xffffff00) | ((v + 0x14) & 0xff); break; @@ -2289,7 +2291,8 @@ static void save_data(uae_u8 *dst, const TCHAR *dir, int size) pl(data, opcode_memory_start); fwrite(data, 1, 4, f); pl(data, (cpu_lvl << 16) | sr_undefined_mask | (addressing_mask == 0xffffffff ? 0x80000000 : 0) | - (feature_min_interrupt_mask << 20) | (safe_memory_mode << 23) | (feature_interrupts << 26) | (feature_randomize << 28)); + (feature_min_interrupt_mask << 20) | (safe_memory_mode << 23) | (feature_interrupts << 26) | + ((feature_loop_mode ? 1 : 0) << 28) | ((feature_loop_mode_68010 ? 1 : 0) << 29)); fwrite(data, 1, 4, f); pl(data, currprefs.fpu_model); fwrite(data, 1, 4, f); @@ -2311,10 +2314,11 @@ static void save_data(uae_u8 *dst, const TCHAR *dir, int size) fwrite(data, 1, 4, f); pl(data, feature_exception_vectors); fwrite(data, 1, 4, f); - data[0] = data[1] = data[2] = data[3] = 0; - fwrite(data, 1, 4, f); - fwrite(data, 1, 4, f); - fwrite(data, 1, 4, f); + data[0] = data[1] = data[2] = 0; + pl(data, feature_loop_mode); + fwrite(&data[0], 1, 4, f); + fwrite(&data[1], 1, 4, f); + fwrite(&data[2], 1, 4, f); fwrite(inst_name, 1, sizeof(inst_name) - 1, f); data[0] = CT_END_FINISH; data[1] = 0; @@ -2515,7 +2519,7 @@ static int create_ea_random(uae_u16 *opcodep, uaecptr pc, int mode, int reg, str return -1; if (feature_loop_mode) { - // loop mode JMP or JSR: skip if A3 or A7 is used in EA calculation + // loop mode JMP or JSR: skip if A3, A4 or A7 is used in EA calculation if (dp->mnemo == i_JMP || dp->mnemo == i_JSR) { if (mode == Areg || mode == Aind || mode == Aipi || mode == Apdi || mode == Ad16 || mode == Ad8r) { if (reg == 3 || reg == 7) { @@ -2645,7 +2649,7 @@ static int create_ea_random(uae_u16 *opcodep, uaecptr pc, int mode, int reg, str if (currprefs.cpu_model >= 68020) v &= ~0x100; ereg = v >> 12; - if (loopmodelimit && (ereg == 0 || ereg == 8 + 3 || ereg == 8 + 7 || ereg == feature_loop_mode_register)) { + if (loopmodelimit && (ereg == 0 || ereg == 8 + 3 || ereg == 8 + 4 || ereg == 8 + 7 || ereg == feature_loop_mode_register)) { continue; } break; @@ -2700,7 +2704,7 @@ static int create_ea_random(uae_u16 *opcodep, uaecptr pc, int mode, int reg, str break; } int ereg = v >> 12; - if (loopmodelimit && (ereg == 0 || ereg == 8 + 3 || ereg == 8 + 7 || ereg == feature_loop_mode_register)) { + if (loopmodelimit && (ereg == 0 || ereg == 8 + 3 || ereg == 8 + 4 || ereg == 8 + 7 || ereg == feature_loop_mode_register)) { return -1; } *regused = ereg; @@ -4346,7 +4350,8 @@ static void test_mnemo(const TCHAR *path, const TCHAR *mnemo, const TCHAR *ovrfi int count = 0; if (feature_loop_mode && !feature_loop_mode_68010) { - registers[8 + 3] = 0; + registers[8 + 3] = 0; // A3 = 0 + registers[8 + 4] = 0; // A4 = 0 } registers[8 + 6] = opcode_memory_start - 0x100; @@ -4636,6 +4641,7 @@ static void test_mnemo(const TCHAR *path, const TCHAR *mnemo, const TCHAR *ovrfi uaecptr startpc = opcode_memory_start; uaecptr pc = startpc + 2; + // target opcode mode if (target_opcode_address != 0xffffffff) { pc -= 2; int cnt = 0; @@ -4651,6 +4657,17 @@ static void test_mnemo(const TCHAR *path, const TCHAR *mnemo, const TCHAR *ovrfi startpc = opcode_memory_address; } + // interrupt timing test mode + if (feature_interrupts == 2) { + pc -= 2; + put_word_test(pc + 0, 0x7000 | interrupt_delay_cnt); // moveq #x,d0 (4 cycles) + put_word_test(pc + 2, 0xe0b9); // ror.l d0,d1 (4 + 4 + d0 * 2 cycles) + put_word_test(pc + 4, NOP_OPCODE); + pc += 6; + opcode_memory_address = startpc = pc; + pc += 2; + } + // Start address to start address + 3 must be accessible or // jump prefetch would cause early bus error which we don't want if (is_nowrite_address(startpc, 4)) { @@ -4801,7 +4818,7 @@ static void test_mnemo(const TCHAR *path, const TCHAR *mnemo, const TCHAR *ovrfi test_instruction_end_pc = pc; // loop mode - if (feature_loop_mode) { + if (feature_loop_mode) { // dbf dn, opcode_memory_start if (!feature_loop_mode_68010) { uae_u16 ccrmaskt = get_ccr_ignore(dp, extraword, true); @@ -4810,25 +4827,52 @@ static void test_mnemo(const TCHAR *path, const TCHAR *mnemo, const TCHAR *ovrfi ccrmask |= 0x02; if (ccrmaskt & 0x02) ccrmask |= 0x04; + // add.l a3,a3 + put_word(pc, 0xd7cb); + pc += 2; + // add.l a4,a4 + put_word(pc, 0xd9cc); + pc += 2; for (int i = 0; i < 4; i++) { // bcc, bne, bvc, bpl - put_word(pc, 0x6400 + (i * 0x0200) + 4); + uaecptr bcc = pc; pc += 2; + uae_u32 add = 0; if (!(ccrmask & (1 << i))) { - // adda.w #x,a3 - put_long(pc, 0xd6fc0000 | (1 << (i * 3))); + add = 1 << (i * 8); + } + if (add >= 1 && add <= 8) { + if (add == 8) { + add = 0; + } + // addq.w #x,a3 + put_word(pc, 0x5048 | 3 | (add << 9)); + pc += 2; + } else if (add < 65536) { + // add.w #x,a3 + put_long(pc, (0xd6fc << 16) | add); + pc += 4; } else { - // adda.w #0,a3 - put_long(pc, 0xd6fc0000); + // add.l #x,a3 + put_word(pc, 0xd7fc); + pc += 2; + put_long(pc, add); + pc += 4; } - pc += 4; + put_word(bcc, 0x6400 + (i * 0x0200) + (pc - bcc) - 2); } - // adda.l a3,a3 - put_word(pc, 0xd7cb); + // sub.l d0,a4 + put_word(pc, 0x99c0); + pc += 2; + // negx.w d0 + put_word(pc, 0x4080); + pc += 2; + // neg.w d0 + put_word(pc, 0x4480); + pc += 2; + // add.l d0,a4 + put_word(pc, 0xd9c0); pc += 2; - // negx.b d0 ; add.w d0,d0 - put_long(pc, 0x4000d040); - pc += 4; } // dbf dn,label put_long_test(pc, ((0x51c8 | feature_loop_mode_register) << 16) | ((opcode_memory_address - pc - 2) & 0xffff)); @@ -5715,6 +5759,15 @@ static void test_mnemo(const TCHAR *path, const TCHAR *mnemo, const TCHAR *ovrfi nextround = true; } + if (feature_interrupts == 2) { + interrupt_delay_cnt++; + if (interrupt_delay_cnt >= 64) { + nextround = false; + } else { + nextround = true; + } + } + if (target_opcode_address != 0xffffffff || target_usp_address != 0xffffffff) { nextround = false; target_ea_opcode_cnt++; @@ -6343,8 +6396,6 @@ static int test(struct ini_data *ini, const TCHAR *sections, const TCHAR *testna ini_getvalx(ini, sections, _T("feature_exception_vectors"), &feature_exception_vectors); feature_interrupts = 0; ini_getvalx(ini, sections, _T("feature_interrupts"), &feature_interrupts); - feature_randomize = 0; - ini_getvalx(ini, sections, _T("feature_randomize"), &feature_randomize); feature_full_extension_format = 0; if (currprefs.cpu_model >= 68020) { @@ -6510,12 +6561,17 @@ static int test(struct ini_data *ini, const TCHAR *sections, const TCHAR *testna v = 0; if (ini_getvalx(ini, sections, _T("opcode_memory_start"), &v)) { - opcode_memory_start = v; - opcode_memory = test_memory + (opcode_memory_start - test_memory_start); - if (opcode_memory_start < test_memory_start || opcode_memory_start + OPCODE_AREA >= test_memory_end) { - wprintf(_T("Opcode memory out of bounds, using default location.\n")); + if (v == -1) { opcode_memory = test_memory + test_memory_size / 2; opcode_memory_start = test_memory_start + test_memory_size / 2; + } else { + opcode_memory_start = v; + opcode_memory = test_memory + (opcode_memory_start - test_memory_start); + if (opcode_memory_start < test_memory_start || opcode_memory_start + OPCODE_AREA >= test_memory_end) { + wprintf(_T("Opcode memory out of bounds, using default location.\n")); + opcode_memory = test_memory + test_memory_size / 2; + opcode_memory_start = test_memory_start + test_memory_size / 2; + } } } else { opcode_memory = test_memory + test_memory_size / 2; diff --git a/cputest/cputestgen.ini b/cputest/cputestgen.ini index dbf9b608..d26f6e96 100644 --- a/cputest/cputestgen.ini +++ b/cputest/cputestgen.ini @@ -487,8 +487,9 @@ mode=fillegal enabled=0 cpu=68020-68060 cpu_address_space=68020 -feature_loop_mode=10 +feature_loop_mode=8 feature_loop_mode_reload=1 feature_loop_mode_register=7 +opcode_memory_start=-1 mode=all verbose=0 diff --git a/cputest/main.c b/cputest/main.c index ab158462..6c764e95 100644 --- a/cputest/main.c +++ b/cputest/main.c @@ -133,6 +133,7 @@ static short quit; static uae_u8 ccr_mask; static uae_u32 addressing_mask = 0x00ffffff; static uae_u32 interrupt_mask; +static short loop_mode, loop_mode_68010, loop_mode_cnt; static short instructionsize; static short disasm; static short basicexcept; @@ -146,7 +147,6 @@ static int exitcnt; static short cycles, cycles_range, cycles_adjust; static short gotcycles; static short interrupttest; -static short randomizetest; static uae_u32 cyclecounter_addr; static int errorcnt; static short uaemode; @@ -2313,6 +2313,49 @@ static short fpucheckextra(struct fpureg *f1, struct fpureg *f2) return 1; } +static void loop_mode_error(uae_u32 ov, uae_u32 nv) +{ + strcpy(outbp, " expected "); + outbp += strlen(outbp); + for (short i = loop_mode_cnt - 1; i >= 0; i--) { + if ((ov >> i) & 1) { + *outbp++ = '1'; + } else { + *outbp++ = '0'; + } + } + strcpy(outbp, " got "); + outbp += strlen(outbp); + for (short i = loop_mode_cnt - 1; i >= 0; i--) { + if ((nv >> i) & 1) { + *outbp++ = '1'; + } else { + *outbp++ = '0'; + } + } + *outbp++ = '\n'; +} + +static const char cvzn[] = { "CVZN" }; +static void loop_mode_error_CVZN(uae_u32 ov, uae_u32 nv) +{ + for (short i = 0; i < 4; i++) { + if ((ov & 0xff) != (nv & 0xff)) { + sprintf(outbp, "Loop mode %c:", cvzn[i]); + outbp += strlen(outbp); + loop_mode_error(ov, nv); + } + ov >>= 8; + nv >>= 8; + } +} +static void loop_mode_error_X(uae_u32 ov, uae_u32 nv) +{ + sprintf(outbp, "Loop mode X:"); + outbp += strlen(outbp); + loop_mode_error(ov, nv); +} + // sregs: registers before execution of test code // tregs: registers used during execution of test code, also modified by test code. // lregs: registers after modifications from data files. Test ok if tregs == lregs. @@ -2459,6 +2502,13 @@ static uae_u8 *validate_test(uae_u8 *p, short ignore_errors, short ignore_sr, st sprintf(outbp, "%c%d: expected %08x but got %08x\n", mode < CT_AREG ? 'D' : 'A', mode & 7, val, tregs->regs[mode]); } outbp += strlen(outbp); + if (loop_mode && !loop_mode_68010) { + if (mode == CT_AREG + 3) { + loop_mode_error_CVZN(val, tregs->regs[mode]); + } else if (mode == CT_AREG + 4) { + loop_mode_error_X(val, tregs->regs[mode]); + } + } } errflag |= 1 << 0; } @@ -2656,6 +2706,14 @@ static uae_u8 *validate_test(uae_u8 *p, short ignore_errors, short ignore_sr, st if (dooutput) { uae_u32 val = lregs->regs[mode]; sprintf(outbp, "%c%d: expected %08x but got %08x\n", mode < CT_AREG ? 'D' : 'A', mode & 7, val, tregs->regs[mode]); + outbp += strlen(outbp); + if (loop_mode && !loop_mode_68010) { + if (mode == CT_AREG + 3) { + loop_mode_error_CVZN(val, tregs->regs[mode]); + } else if (mode == CT_AREG + 4) { + loop_mode_error_X(val, tregs->regs[mode]); + } + } } errflag |= 1 << 0; } @@ -3296,9 +3354,10 @@ static int test_mnemo(const char *opcode) interrupt_mask = (lvl_mask >> 20) & 7; addressing_mask = (lvl_mask & 0x80000000) ? 0xffffffff : 0x00ffffff; interrupttest = (lvl_mask >> 26) & 1; - randomizetest = (lvl_mask >> 28) & 1; sr_undefined_mask = lvl_mask & 0xffff; safe_memory_mode = (lvl_mask >> 23) & 7; + loop_mode = (lvl_mask >> 28) & 1; + loop_mode_68010 = (lvl_mask >> 29) & 1; fpu_model = read_u32(headerfile, &headoffset); test_low_memory_start = read_u32(headerfile, &headoffset); test_low_memory_end = read_u32(headerfile, &headoffset); @@ -3309,7 +3368,10 @@ static int test_mnemo(const char *opcode) user_stack_memory = read_u32(headerfile, &headoffset); super_stack_memory = read_u32(headerfile, &headoffset); exception_vectors = read_u32(headerfile, &headoffset); - read_u32(headerfile, &headoffset); + v = read_u32(headerfile, &headoffset); + if (loop_mode) { + loop_mode_cnt = v & 0xff; + } read_u32(headerfile, &headoffset); read_u32(headerfile, &headoffset); memcpy(inst_name, headerfile + headoffset, sizeof(inst_name) - 1); -- 2.47.3