From: Toni Wilen Date: Sun, 18 Aug 2019 17:47:41 +0000 (+0300) Subject: CPU tester updates (68040/060 support). 68020/030 address error fixes. MOVE16 disasse... X-Git-Tag: 4300~145 X-Git-Url: https://git.unchartedbackwaters.co.uk/w/?a=commitdiff_plain;h=48c54e8ef4f725bab4a040eca1768697ab693e99;p=francis%2Fwinuae.git CPU tester updates (68040/060 support). 68020/030 address error fixes. MOVE16 disassembler fix. CAS2.W fix. --- diff --git a/cputest.cpp b/cputest.cpp index c63ede85..2e4d28fe 100644 --- a/cputest.cpp +++ b/cputest.cpp @@ -102,6 +102,7 @@ static int test_exception_opcode; static uae_u8 imm8_cnt; static uae_u16 imm16_cnt; static uae_u32 imm32_cnt; +static uae_u32 immabsl_cnt; static uae_u32 addressing_mask; static int opcodecnt; static int cpu_stopped; @@ -111,6 +112,9 @@ static int testing_active; static time_t starttime; static int filecount; static uae_u16 sr_undefined_mask; +static int low_memory_accessed; +static int high_memory_accessed; +static int test_memory_accessed; struct uae_prefs currprefs; @@ -144,6 +148,7 @@ static bool valid_address(uaecptr addr, int size, int w) goto oob; if (w && lmem_rom) goto oob; + low_memory_accessed = w ? -1 : 1; return 1; } if (addr >= HIGH_MEMORY_START && addr < HIGH_MEMORY_START + 0x8000) { @@ -153,6 +158,7 @@ static bool valid_address(uaecptr addr, int size, int w) goto oob; if (w && hmem_rom) goto oob; + high_memory_accessed = w ? -1 : 1; return 1; } if (addr >= test_memory_end && addr + size < test_memory_end + EXTRA_RESERVED_SPACE) { @@ -165,6 +171,7 @@ static bool valid_address(uaecptr addr, int size, int w) if (addr >= opcode_memory_start && addr + size < opcode_memory_start + OPCODE_AREA) goto oob; } + test_memory_accessed = w ? -1 : 1; return 1; } oob: @@ -695,10 +702,9 @@ static void doexcstack(void) } else if (cpu_lvl == 2) { if (test_exception == 3) { uae_u16 ssw = (sv ? 4 : 0) | test_exception_3_fc; - ssw |= test_exception_3_w ? 0 : 0x40; ssw |= 0x20; regs.mmu_fault_addr = test_exception_addr; - Exception_build_stack_frame(regs.instruction_pc, regs.pc, ssw, 3, 0x0a); + Exception_build_stack_frame(regs.instruction_pc, regs.pc, ssw, 3, 0x0b); } else { Exception_build_stack_frame_common(regs.instruction_pc, regs.pc, 0, test_exception); } @@ -1194,7 +1200,7 @@ static int full_format_cnt; static uaecptr putfpuimm(uaecptr pc, int opcodesize, int *isconstant) { - // TODO: generate FPU immediates + // TODO: generate sane FPU immediates switch (opcodesize) { case 0: // L @@ -1210,24 +1216,24 @@ static uaecptr putfpuimm(uaecptr pc, int opcodesize, int *isconstant) pc += 2; break; case 1: // S - put_long(pc, 0); + put_long(pc, rand32()); pc += 4; break; case 2: // X - put_long(pc, 0); - put_long(pc + 4, 0); - put_long(pc + 8, 0); + put_long(pc, rand32()); + put_long(pc + 4, rand32()); + put_long(pc + 8, rand32()); pc += 12; break; case 3: // P - put_long(pc, 0); - put_long(pc + 4, 0); - put_long(pc + 8, 0); + put_long(pc, rand32()); + put_long(pc + 4, rand32()); + put_long(pc + 8, rand32()); pc += 12; break; case 5: // D - put_long(pc, 0); - put_long(pc + 4, 0); + put_long(pc, rand32()); + put_long(pc + 4, rand32()); pc += 8; break; } @@ -1325,9 +1331,24 @@ static int create_ea(uae_u16 *opcodep, uaecptr pc, int mode, int reg, struct ins pc += 2; break; case absl: - put_long_test(pc, rand32()); - *isconstant = 32; - pc += 4; + { + uae_u32 v = rand32(); + if ((immabsl_cnt & 7) == 0) { + v &= 0x0000ffff; + } else if ((immabsl_cnt & 7) >= 4) { + int offset = 0; + for (;;) { + offset = (uae_s16)rand16(); + if (offset < -OPCODE_AREA || offset > OPCODE_AREA) + break; + } + v = opcode_memory_start + offset; + } + immabsl_cnt++; + put_long_test(pc, v); + *isconstant = 32; + pc += 4; + } break; case imm: if (fpuopcode >= 0 && opcodesize < 8) { @@ -1432,8 +1453,9 @@ static int create_ea(uae_u16 *opcodep, uaecptr pc, int mode, int reg, struct ins { // long immediate uae_u32 v = rand32(); - if ((imm32_cnt & 7) == 0) + if ((imm32_cnt & 7) == 0) { v &= 0x0000ffff; + } imm32_cnt++; put_long_test(pc, v); if (imm32_cnt < 256) @@ -1460,6 +1482,15 @@ static int handle_specials_preea(uae_u16 opcode, uaecptr pc, struct instr *dp) imm_special++; return 2; } + if (dp->mnemo == i_MOVE16) { + if (opcode & 0x20) { + uae_u16 v = 0; + v |= imm_special << 12; + put_word_test(pc, v); + imm_special++; + return 2; + } + } return 0; } @@ -1519,7 +1550,6 @@ static void handle_specials_extra(uae_u16 opcode, uaecptr pc, struct instr *dp) if (extra != extra2) { put_word_test(opcode_memory_start + 4, extra); } - } if (dp->mnemo == i_CHK2) { uae_u16 extra = get_word_test(opcode_memory_start + 2); @@ -1528,7 +1558,6 @@ static void handle_specials_extra(uae_u16 opcode, uaecptr pc, struct instr *dp) if (extra != extra2) { put_word_test(opcode_memory_start + 2, extra); } - } } @@ -1549,13 +1578,6 @@ static int handle_specials_stack(uae_u16 opcode, uaecptr pc, struct instr *dp, i addr += 2; offset += 2; *isconstant = imm_special >= (1 << (0 + 5)) * 4 ? 0 : -1; - } else if (dp->mnemo == i_RTD) { - // RTD - v = imm_special >> 2; - uae_u16 sr = v & 31; - sr |= (v >> 5) << 12; - put_word_test(addr + 4, sr); - *isconstant = imm_special >= (1 << (4 + 5)) * 4 ? 0 : -1; } else if (dp->mnemo == i_RTE) { // RTE if (currprefs.cpu_model == 68000) { @@ -1596,13 +1618,13 @@ static int handle_specials_stack(uae_u16 opcode, uaecptr pc, struct instr *dp, i return offset; } -static void execute_ins(uae_u16 opc, uaecptr endpc, uaecptr targetpc) +static void execute_ins(uae_u16 opc, uaecptr endpc, uaecptr targetpc, struct instr *dp) { uae_u16 opw1 = (opcode_memory[2] << 8) | (opcode_memory[3] << 0); uae_u16 opw2 = (opcode_memory[4] << 8) | (opcode_memory[5] << 0); - if (opc == 0x61ff - && opw1 == 0x0000 - && opw2 == 0x9908 + if (opc == 0xf601 +// && opw1 == 0x0000 +// && opw2 == 0x9908 ) printf(""); if (regs.sr & 0x2000) @@ -1614,6 +1636,9 @@ static void execute_ins(uae_u16 opc, uaecptr endpc, uaecptr targetpc) MakeFromSR(); + low_memory_accessed = 0; + high_memory_accessed = 0; + test_memory_accessed = 0; testing_active = 1; int cnt = feature_loop_mode * 2; @@ -1648,6 +1673,11 @@ static void execute_ins(uae_u16 opc, uaecptr endpc, uaecptr targetpc) } } + if (dp->mnemo == i_TAS && low_memory_accessed) { + test_exception = -1; + break; + } + if (regs.pc == endpc || regs.pc == targetpc) break; @@ -1784,12 +1814,9 @@ static uae_u8 *save_exception(uae_u8 *p, struct instr *dp) // FSLW or PC of faulted instruction p = store_rel(p, 0, opcode_memory_start, gl(sf + 12), 1); break; - case 0x0a: // 68020/030 address error. Only check SSW. - // SSW - p = store_reg(p, 0, 0, gw(sf + 0x0a), sz_word); - exception_stack_frame_size = 0x0c; - sf[8] = sf[9] = 0; - last_exception[8] = last_exception[9] = 0; + case 0x0a: // 68020/030 address error. + case 0x0b: // Don't save anything extra, too many undefined fields and bits.. + exception_stack_frame_size = 0x08; break; default: wprintf(_T("Unknown frame %04x!\n"), frame); @@ -1819,6 +1846,22 @@ static uae_u16 get_ccr_ignore(struct instr *dp) return ccrignoremask; } +static int isfpp(int mnemo) +{ + switch (mnemo) + { + case i_FPP: + case i_FBcc: + case i_FDBcc: + case i_FTRAPcc: + case i_FScc: + case i_FRESTORE: + case i_FSAVE: + return 1; + } + return 0; +} + static const TCHAR *sizes[] = { _T("B"), _T("W"), _T("L") }; @@ -1905,9 +1948,9 @@ static void test_mnemo(const TCHAR *path, const TCHAR *mnemo, int opcodesize, in opcodecnt++; if (isunsupported(dp)) return; - if ((opcode & 0xf000) == 0xf000 && !currprefs.fpu_model) + if (isfpp(lookup->mnemo) && !currprefs.fpu_model) return; - fpumode = currprefs.fpu_model && (opcode & 0xf000) == 0xf000; + fpumode = currprefs.fpu_model && isfpp(lookup->mnemo); } if (!opcodecnt) @@ -2028,6 +2071,7 @@ static void test_mnemo(const TCHAR *path, const TCHAR *mnemo, int opcodesize, in imm8_cnt = 0; imm16_cnt = 0; imm32_cnt = 0; + immabsl_cnt = 0; imm_special = 0; // retry few times if out of bounds access @@ -2048,7 +2092,7 @@ static void test_mnemo(const TCHAR *path, const TCHAR *mnemo, int opcodesize, in out_of_test_space = 0; ahcnt = 0; - if (opc == 0xf228) + if (opc == 0xf620) printf(""); if (subtest_count == 1537) printf(""); @@ -2319,7 +2363,7 @@ static void test_mnemo(const TCHAR *path, const TCHAR *mnemo, int opcodesize, in if (subtest_count == 353) printf(""); - execute_ins(opc, pc - 2, branch_target); + execute_ins(opc, pc - 2, branch_target, dp); if (regs.s) s_cnt++; @@ -2635,7 +2679,7 @@ int __cdecl main(int argc, char *argv[]) currprefs.cpu_model = 68000; ini_getval(ini, INISECTION, _T("cpu"), &currprefs.cpu_model); - if (currprefs.cpu_model != 68000 && currprefs.cpu_model != 68010 && currprefs.cpu_model != 68020) { + if (currprefs.cpu_model != 68000 && currprefs.cpu_model != 68010 && currprefs.cpu_model != 68020 && currprefs.cpu_model != 68040) { wprintf(_T("Unsupported CPU model.\n")); return 0; } @@ -2644,7 +2688,7 @@ int __cdecl main(int argc, char *argv[]) addressing_mask = 0x00ffffff; v = 24; ini_getval(ini, INISECTION, _T("cpu_address_space"), &v); - if (v == 32) { + if (v == 32 || currprefs.cpu_model >= 68030) { currprefs.address_space_24 = 0; addressing_mask = 0xffffffff; } @@ -2653,7 +2697,7 @@ int __cdecl main(int argc, char *argv[]) currprefs.fpu_mode = 1; ini_getval(ini, INISECTION, _T("fpu"), &currprefs.fpu_model); if (currprefs.fpu_model && currprefs.cpu_model < 68020) { - wprintf(_T("FPU requires 68020 CPU.\n")); + wprintf(_T("FPU requires 68020 or 68040 CPU.\n")); return 0; } if (currprefs.fpu_model != 0 && currprefs.fpu_model != 68881 && currprefs.fpu_model != 68882 && currprefs.fpu_model != 68040 && currprefs.fpu_model != 68060) { @@ -2751,6 +2795,9 @@ int __cdecl main(int argc, char *argv[]) xorshiftstate = 1; + feature_test_rounds = 2; + ini_getval(ini, INISECTION, _T("test_rounds"), &feature_test_rounds); + v = 0; ini_getval(ini, INISECTION, _T("test_memory_start"), &v); if (!v) { @@ -2861,6 +2908,9 @@ int __cdecl main(int argc, char *argv[]) } else if (currprefs.cpu_model == 68020) { tbl = op_smalltbl_92_test_ff; cpu_lvl = 2; + } else if (currprefs.cpu_model == 68040) { + tbl = op_smalltbl_94_test_ff; + cpu_lvl = 4; } else { wprintf(_T("Unsupported CPU model.\n")); abort(); @@ -2890,8 +2940,10 @@ int __cdecl main(int argc, char *argv[]) continue; } - if (!currprefs.fpu_model && (opcode & 0xf000) == 0xf000) { - continue; + if (!currprefs.fpu_model) { + int fppskip = isfpp(table->mnemo); + if (fppskip) + continue; } if (table->handler != -1) { diff --git a/cputest/amiga.S b/cputest/amiga.S index 263662a6..81cbc205 100644 --- a/cputest/amiga.S +++ b/cputest/amiga.S @@ -58,17 +58,20 @@ _allocate_absolute: move.l (sp)+,a6 rts - | return CPU model (68000=0, 68010=1, 68020=2) + | return CPU model (68000=0, 68010=1, 68020=2, 68030=3, 68040=4, 68060=5) _get_cpu_model: move.l 4.w,a0 - moveq #0,d0 move.w 0x128(a0),d1 - and.w #3,d1 - beq.s .cpudone - moveq #2,d0 - btst #1,d1 + moveq #5,d0 + tst.b d1 + bmi.s .cpudone2 + moveq #3,d0 +.cpucheck: + btst d0,d1 bne.s .cpudone - moveq #1,d0 + dbf d0,.cpucheck .cpudone: + addq.l #1,d0 +.cpudone2: rts diff --git a/cputest/asm.S b/cputest/asm.S index 70a59add..72d07f07 100644 --- a/cputest/asm.S +++ b/cputest/asm.S @@ -12,6 +12,10 @@ .globl _setvbr .globl _setcpu .globl _flushcache + .globl _msp_address1 + .globl _msp_address2 + .globl _msp_address3 + .globl _msp_address4 | must match main.c S_DREG = 0 @@ -44,9 +48,17 @@ _setcpu: bcs.s .scend1 movec cacr,d0 move.l d0,(a0)+ + moveq #0,d0 + cmp.w #4,d1 + bcc.s .scend1b movec caar,d0 +.scend1b: move.l d0,(a0)+ + moveq #0,d0 + cmp.w #5,d1 + bcc.s .scend1c movec msp,d0 +.scend1c: move.l d0,(a0)+ .scend1: move.l a1,d0 @@ -62,17 +74,30 @@ _setcpu: move.l (a1)+,d0 movec d0,cacr move.l (a1)+,d0 + cmp.w #4,d1 + bcc.s .scend2b movec d0,caar +.scend2b: move.l (a1)+,d0 + cmp.w #5,d1 + bcc.s .scend2 move.c d0,msp .scend2: rts _flushcache: + move.l 4(sp),d1 | cpu_lvl + cmp.w #4,d1 + bcc.s .fc040 movec cacr,d0 bset #3,d0 movec d0,cacr rts +.fc040: + .arch 68040 + cpusha bc + .arch 68020 + rts | set and return old VBR _setvbr: @@ -130,7 +155,7 @@ _execute_test010: movem.l (a0),d0-d7/a0-a6 rte - | 68020 test entrypoint + | 68020+ test entrypoint _execute_test020: movem.l d1-d7/a0-a6,-(sp) move.l 14*4+4(sp),a0 | register struct @@ -149,8 +174,11 @@ _execute_test020: move.w S_SR+2(a0),-(sp) move.l S_AREG+7*4(a0),a1 move.l a1,USP + move.l S_MSP(a0),a1 +_msp_address1: movec a1,MSP + movem.l (a0),d0-d7/a0-a6 rte @@ -173,8 +201,11 @@ _execute_testfpu: move.w S_SR+2(a0),-(sp) move.l S_AREG+7*4(a0),a1 move.l a1,USP + move.l S_MSP(a0),a1 +_msp_address2: movec a1,MSP + fmovem.x S_FPU(a0),fp0-fp7 lea S_FPIAR(a0),a1 fmove.l (a1)+,fpiar @@ -296,8 +327,10 @@ _exception020: lsr.w #2,d0 move.w d0,S_EXC+2(a0) +_msp_address3: movec MSP,a1 move.l a1,S_MSP(a0) + move.l USP,a1 move.l a1,S_AREG+7*4(a0) @@ -323,8 +356,10 @@ _exceptionfpu: lsr.w #2,d0 move.w d0,S_EXC+2(a0) +_msp_address4: movec MSP,a1 move.l a1,S_MSP(a0) + move.l USP,a1 move.l a1,S_AREG+7*4(a0) diff --git a/cputest/cputestgen.ini b/cputest/cputestgen.ini index 8c9b758f..b0dce4c3 100644 --- a/cputest/cputestgen.ini +++ b/cputest/cputestgen.ini @@ -1,7 +1,7 @@ [cputest] -; CPU model (68000, 68020). +; CPU model (68000, 68020 or 68040). ; Always select 68020 when testing FPU instructions, even if test hardware CPU is 68040 or 68060. cpu=68020 @@ -31,8 +31,12 @@ high_rom=D:\amiga\roms\Kickstart v3.1 rev 40.63 (1993)(Commodore)(A500-A600-A200 ; main test memory start and size (real hardware must have RAM in this address space) test_memory_start=0x780000 +;test_memory_start=0x68800000 test_memory_size=0x080000 +; number of test rounds (registers are re-randomized after each round) +test_rounds=2 + ; test word or long odd data access address errors (68000/010 only) ; 0 = do not generate address errors ; 1 = include address errors @@ -41,7 +45,7 @@ feature_exception3_data=0 ; test branches to odd addresses ; same options as above -feature_exception3_instruction=0 +feature_exception3_instruction=1 ; SR extra mask. ; 0x8000 = T1 @@ -72,4 +76,4 @@ feature_addressing_modes_dst= ; mnemonics separated by comma or all/fall. ; all = generate all CPU tests. tst = generate tst.b, tst.w and tst.l. tst.l = generate only tst.l ; fall = generate all FPU tests. -mode=chk2.b +mode=all diff --git a/cputest/main.c b/cputest/main.c index 4a256cf4..cb71ce5c 100644 --- a/cputest/main.c +++ b/cputest/main.c @@ -145,7 +145,7 @@ static uae_u32 get_cpu_model(void) static void setcpu(uae_u32 v, uae_u32 *s, uae_u32 *d) { } -static void flushcache(void) +static void flushcache(uae_u32 v) { } #else @@ -168,7 +168,7 @@ extern uae_u32 testexit(void); extern uae_u32 setvbr(uae_u32); extern uae_u32 get_cpu_model(void); extern void setcpu(uae_u32, uae_u32*, uae_u32*); -extern void flushcache(void); +extern void flushcache(uae_u32); #endif @@ -900,10 +900,8 @@ static uae_u8 *validate_exception(struct registers *regs, uae_u8 *p, int excnum, exclen = 16; break; case 0x0a: - v = 0; - p = restore_value(p, &v, &size); - pw(exc + 0x0a, v); - exclen = 0x0c; + case 0x0b: + exclen = 8; break; default: end_test(); @@ -1299,7 +1297,7 @@ static void process_test(uae_u8 *p) int fpumode = fpu_model && (opcode_memory[0] & 0xf0) == 0xf0; if (cpu_lvl >= 2) - flushcache(); + flushcache(cpu_lvl); uae_u32 pc = opcode_memory_addr; @@ -1435,6 +1433,7 @@ static int test_mnemo(const char *path, const char *opcode) char fname[256], tfname[256]; int filecnt = 1; uae_u32 starttimeid; + int lvl; errors = 0; quit = 0; @@ -1464,13 +1463,22 @@ static int test_mnemo(const char *path, const char *opcode) fread(data, 1, 4, f); opcode_memory_addr = gl(data) + test_memory_addr; fread(data, 1, 4, f); - cpu_lvl = gl(data) >> 16; + lvl = gl(data) >> 16; sr_undefined_mask = gl(data); fread(data, 1, 4, f); fpu_model = gl(data); fread(inst_name, 1, sizeof(inst_name) - 1, f); inst_name[sizeof(inst_name) - 1] = 0; + int lvl2 = cpu_lvl; + if (lvl2 == 5 && lvl2 != lvl) + lvl2 = 4; + + if (lvl != lvl2) { + printf("Mismatched CPU model: %lu <> %lu\n", 68000 + 10 * cpu_lvl, 68000 + lvl * 10); + exit(0); + } + if (!check_undefined_sr) { sr_undefined_mask = ~sr_undefined_mask; } else { @@ -1614,6 +1622,25 @@ int main(int argc, char *argv[]) #endif + int lvl = cpu_lvl; + if (lvl == 3) { + lvl = 2; + } else if (lvl == 5) { + lvl = 4; +#ifdef M68K + // Overwrite MOVEC to/from MSP + // with NOP if 68060 + extern void *msp_address1; + extern void *msp_address2; + extern void *msp_address3; + extern void *msp_address4; + *((uae_u32*)&msp_address1) = 0x4e714e71; + *((uae_u32*)&msp_address2) = 0x4e714e71; + *((uae_u32*)&msp_address3) = 0x4e714e71; + *((uae_u32*)&msp_address4) = 0x4e714e71; +#endif + } + if (argc < 2) { printf("cputest () (continue)\n"); printf("mnemonic = test single mnemonic\n"); @@ -1624,7 +1651,7 @@ int main(int argc, char *argv[]) return 0; } - sprintf(path + strlen(path), "%lu/", 68000 + cpu_lvl * 10); + sprintf(path + strlen(path), "%lu/", 68000 + lvl * 10); strcpy(opcode, argv[1]); diff --git a/cputest_support.cpp b/cputest_support.cpp index 5b03799c..b4c653ab 100644 --- a/cputest_support.cpp +++ b/cputest_support.cpp @@ -92,6 +92,10 @@ void flush_icache(int v) { } +void flush_cpu_caches_040(uae_u16 opcode) +{ +} + void mmu_tt_modified(void) { } @@ -101,6 +105,10 @@ uae_u16 REGPARAM2 mmu_set_tc(uae_u16 tc) return 0; } +void mmu_op(uae_u32 opcode, uae_u32 extra) +{ +} + uae_u16 mmu030_state[3]; int mmu030_opcode; int mmu030_idx; diff --git a/disasm.cpp b/disasm.cpp index af73887c..b173ced6 100644 --- a/disasm.cpp +++ b/disasm.cpp @@ -1791,7 +1791,7 @@ void m68k_disasm_2 (TCHAR *buf, int bufsize, uaecptr pc, uaecptr *nextpc, int cn _stprintf(p, _T("(A%d)+,(A%d)+"), opcode & 7, (extra >> 12) & 7); pc += 2; } else { - uae_u32 addr = get_long_debug(pc + 2); + uae_u32 addr = get_long_debug(pc); int ay = opcode & 7; pc += 4; switch ((opcode >> 3) & 3) diff --git a/gencpu.cpp b/gencpu.cpp index fc9b9bbe..e7ef2a1d 100644 --- a/gencpu.cpp +++ b/gencpu.cpp @@ -1809,7 +1809,7 @@ static void genamode2x (amodes mode, const char *reg, wordsizes size, const char } } else if (g_instr->mnemo == i_MVSR2) { // If MOVE from SR generates address error exception, - // RW field is set to Read! + // Change it to read because it does dummy read first. exp3rw = 0; } @@ -4023,9 +4023,9 @@ static void gen_opcode (unsigned int opcode) fill_prefetch_next (); addcycles000 (2); } else { - // write to memory, dummy write to same address, X-flag seems to be always set + // read first and ignore result if (cpu_level <= 1 && curi->size == sz_word) { - printf ("\t%s (srca, regs.sr | 0x0010);\n", dstw); + printf ("\t%s (srca);\n", srcw); count_write++; } fill_prefetch_next (); @@ -4455,7 +4455,7 @@ static void gen_opcode (unsigned int opcode) start_brace (); printf("\tuaecptr oldpc = %s;\n", getpc); printf("\tuaecptr nextpc = oldpc + %d;\n", m68k_pc_offset); - if (using_exception_3) { + if (using_exception_3 && cpu_level <= 1) { printf("\tif (srca & 1) {\n"); printf("\t\texception3i (opcode, srca);\n"); printf("\t\tgoto %s;\n", endlabelstr); @@ -4481,8 +4481,16 @@ static void gen_opcode (unsigned int opcode) printf("\t\texception3_write(opcode, m68k_areg(regs, 7), 1);\n"); printf("\t\tgoto %s;\n", endlabelstr); printf("\t}\n"); + need_endlabel = 1; } setpc ("srca"); + if (using_exception_3 && cpu_level >= 2) { + printf("\tif (%s & 1) {\n", getpc); + printf("\t\texception3i (opcode, %s);\n", getpc); + printf("\t\tgoto %s;\n", endlabelstr); + printf("\t}\n"); + need_endlabel = 1; + } clear_m68k_offset(); fill_prefetch_1 (0); if (using_ce || using_prefetch) { @@ -4542,7 +4550,7 @@ static void gen_opcode (unsigned int opcode) printf("\t\texception3b(opcode, m68k_areg(regs, 7), true, false, %s + 2);\n", getpc); printf("\t\tgoto %s;\n", endlabelstr); printf("\t}\n"); - } else { + } else if (0) { printf("\tif (src & 1) {\n"); printf("\t\texception3b(opcode, %s + s, 0, 1, %s + s);\n", getpc, getpc); printf("\t\tgoto %s;\n", endlabelstr); @@ -4553,6 +4561,14 @@ static void gen_opcode (unsigned int opcode) addcycles000 (2); printf("\tuaecptr oldpc = %s;\n", getpc); printf("\tuaecptr nextpc = oldpc + %d;\n", m68k_pc_offset); + if (using_exception_3 && cpu_level >= 2) { + printf("\tif (s & 1) {\n"); + printf("\t\tm68k_areg(regs, 7) -= 4;\n"); + printf("\t\texception3b(opcode, %s + s, 0, 1, %s + s);\n", getpc, getpc); + printf("\t\tgoto %s;\n", endlabelstr); + printf("\t}\n"); + need_endlabel = 1; + } if (using_indirect > 0 && !using_ce020 && !using_prefetch_020 && !using_ce && !using_test) { printf("\tm68k_do_bsri_jit (nextpc, s);\n"); } else if (using_mmu) { @@ -4573,6 +4589,7 @@ static void gen_opcode (unsigned int opcode) printf("\t\texception3b(opcode, %s, 0, 1, %s);\n", getpc, getpc); printf("\t\tgoto %s;\n", endlabelstr); printf("\t}\n"); + need_endlabel = 1; } if (using_debugmem) { printf("\tif (debugmem_trace)\n"); @@ -5435,8 +5452,8 @@ bccl_not68020: printf ("\t}}\n"); pop_braces (old_brace_level); printf ("\tif (! GET_ZFLG ()) {\n"); - printf ("\tm68k_dreg (regs, (extra >> 0) & 7) = (m68k_dreg (regs, (extra >> 6) & 7) & ~0xffff) | (dst2 & 0xffff);\n"); - printf ("\tm68k_dreg (regs, (extra >> 16) & 7) = (m68k_dreg (regs, (extra >> 22) & 7) & ~0xffff) | (dst1 & 0xffff);\n"); + printf ("\tm68k_dreg (regs, (extra >> 0) & 7) = (m68k_dreg (regs, (extra >> 0) & 7) & ~0xffff) | (dst2 & 0xffff);\n"); + printf ("\tm68k_dreg (regs, (extra >> 16) & 7) = (m68k_dreg (regs, (extra >> 16) & 7) & ~0xffff) | (dst1 & 0xffff);\n"); printf ("\t}\n"); } else { int old_brace_level = n_braces; @@ -6308,9 +6325,12 @@ static void generate_cpu_test(int mode) cpu_level = 2; using_prefetch = 0; using_simple_cycles = 0; + } else if (mode == 4) { + cpu_level = 4; + using_prefetch = 0; + using_simple_cycles = 0; } - read_counts(); for (rp = 0; rp < nr_cpuop_funcs; rp++) opcode_next_clev[rp] = cpu_level; @@ -6539,6 +6559,7 @@ int main(int argc, char *argv[]) generate_cpu_test(0); generate_cpu_test(1); generate_cpu_test(2); + generate_cpu_test(4); #else diff --git a/include/cputest.h b/include/cputest.h index 29cdcdab..0fdb5a01 100644 --- a/include/cputest.h +++ b/include/cputest.h @@ -28,6 +28,7 @@ extern const int imm8_table[]; extern const struct cputbl op_smalltbl_90_test_ff[]; extern const struct cputbl op_smalltbl_91_test_ff[]; extern const struct cputbl op_smalltbl_92_test_ff[]; +extern const struct cputbl op_smalltbl_94_test_ff[]; extern struct flag_struct regflags; diff --git a/newcpu.cpp b/newcpu.cpp index a116f0ae..c8015cdf 100644 --- a/newcpu.cpp +++ b/newcpu.cpp @@ -2631,7 +2631,7 @@ static void Exception_mmu030 (int nr, uaecptr oldpc) regs.mmu_fault_addr = last_fault_for_exception_3; mmu030_state[0] = mmu030_state[1] = 0; mmu030_data_buffer_out = 0; - Exception_build_stack_frame (last_fault_for_exception_3, currpc, MMU030_SSW_RW | MMU030_SSW_SIZE_W | (regs.s ? 6 : 2), nr, 0xA); + Exception_build_stack_frame (last_fault_for_exception_3, currpc, MMU030_SSW_RW | MMU030_SSW_SIZE_W | (regs.s ? 6 : 2), nr, 0xB); } else { Exception_build_stack_frame_common(oldpc, currpc, regs.mmu_ssw, nr); } @@ -2896,11 +2896,13 @@ static void Exception_normal (int nr) } } else if (currprefs.cpu_model >= 68020) { // 68020/030 odd PC address error (partially implemented only) + // annoyingly this generates frame B, not A. uae_u16 ssw = (sv ? 4 : 0) | last_fc_for_exception_3; - ssw |= last_writeaccess_for_exception_3 ? 0 : 0x40; - ssw |= 0x20; + ssw |= MMU030_SSW_RW | MMU030_SSW_SIZE_W; regs.mmu_fault_addr = last_fault_for_exception_3; - Exception_build_stack_frame(oldpc, currpc, ssw, nr, 0x0a); + mmu030_state[0] = mmu030_state[1] = 0; + mmu030_data_buffer_out = 0; + Exception_build_stack_frame(last_fault_for_exception_3, currpc, ssw, nr, 0x0b); used_exception_build_stack_frame = true; } else { // 68010 address error (partially implemented only)