From: Toni Wilen Date: Thu, 25 Aug 2022 19:14:31 +0000 (+0300) Subject: CPU tester IPL timing rewrite. Merged test files (multiple small dat files -> single... X-Git-Tag: 41000~150 X-Git-Url: https://git.unchartedbackwaters.co.uk/w/?a=commitdiff_plain;h=530a076160b6c44e149c37efe7895bc2a6664d2a;p=francis%2Fwinuae.git CPU tester IPL timing rewrite. Merged test files (multiple small dat files -> single file) --- diff --git a/cputest.cpp b/cputest.cpp index 7e01e081..3bb42a75 100644 --- a/cputest.cpp +++ b/cputest.cpp @@ -71,7 +71,8 @@ static int feature_exception_vectors = 0; static int feature_interrupts = 0; static int feature_instruction_size = 0; static int fpu_min_exponent, fpu_max_exponent; -static int rnd_seed; +static int max_file_size; +static int rnd_seed, rnd_seed_prev; static TCHAR *feature_instruction_size_text = NULL; static uae_u32 feature_addressing_modes[2]; static int feature_gzip = 0; @@ -87,6 +88,7 @@ static uae_u8 exceptionenabletable[256]; #define MAX_REGDATAS 32 static int regdatacnt; static struct regdata regdatas[MAX_REGDATAS]; +static uae_u32 ignore_register_mask; #define HIGH_MEMORY_START (addressing_mask == 0xffffffff ? 0xffff8000 : 0x00ff8000) @@ -143,6 +145,8 @@ static uae_u16 trace_store_sr; static int generate_address_mode; static int test_memory_access_mask; static uae_u32 opcode_memory_address; +static uaecptr branch_target; +static uaecptr branch_target_pc; static uae_u8 imm8_cnt; static uae_u16 imm16_cnt; @@ -522,7 +526,9 @@ void put_byte_test(uaecptr addr, uae_u32 v) return; if (feature_interrupts >= 2 && addr == IPL_TRIGGER_ADDR) { add_memory_cycles(1); +#if IPL_TRIGGER_ADDR_SIZE == 1 interrupt_cycle_cnt = INTERRUPT_CYCLES; +#endif return; } check_bus_error(addr, 1, regs.s ? 5 : 1); @@ -550,6 +556,13 @@ void put_word_test(uaecptr addr, uae_u32 v) { if (!testing_active && is_nowrite_address(addr, 1)) return; + if (feature_interrupts >= 2 && addr == IPL_TRIGGER_ADDR) { + add_memory_cycles(1); +#if IPL_TRIGGER_ADDR_SIZE == 2 + interrupt_cycle_cnt = INTERRUPT_CYCLES; +#endif + return; + } check_bus_error(addr, 1, regs.s ? 5 : 1); if (addr & 1) { put_byte_test(addr + 0, v >> 8); @@ -827,10 +840,19 @@ bool is_cycle_ce(uaecptr addr) return 0; } -void ipl_fetch(void) +// ipl check was early enough, interrupt possible after current instruction +void ipl_fetch_now(void) { - if (regs.ipl_pin) { + if (regs.ipl[0] != regs.ipl_pin) { regs.ipl[0] = regs.ipl_pin; + regs.ipl[1] = 0; + } +} +// ipl check was too late, interrupt possible after following instruction +void ipl_fetch_next(void) +{ + if (regs.ipl[1] != regs.ipl_pin) { + regs.ipl[1] = regs.ipl_pin; } } @@ -899,7 +921,7 @@ uae_u32 get_disp_ea_test(uae_u32 base, uae_u32 dp) uae_s32 regd = regs.regs[reg]; if ((dp & 0x800) == 0) regd = (uae_s32)(uae_s16)regd; - return base + (uae_s8)dp + regd; + return base + (uae_s32)((uae_s8)(dp)) + regd; } static void activate_trace(void) @@ -1014,6 +1036,11 @@ void REGPARAM2 MakeFromSR(void) MakeFromSR_x(0); } +void REGPARAM2 MakeFromSR_STOP(void) +{ + MakeFromSR_x(-1); +} + void REGPARAM2 MakeFromSR_intmask(uae_u16 oldsr, uae_u16 newsr) { } @@ -1022,6 +1049,10 @@ void intlev_load(void) { } +void checkint(void) +{ +} + void cpu_halt(int halt) { cpu_halted = halt; @@ -1590,7 +1621,7 @@ int cctrue(int cc) return 0; } -static uae_u32 xorshiftstate; +static uae_u32 xorshiftstate, xorshiftstate_prev; static uae_u32 xorshift32(void) { uae_u32 x = xorshiftstate; @@ -1601,7 +1632,7 @@ static uae_u32 xorshift32(void) return xorshiftstate; } -static int rand16_cnt; +static int rand16_cnt, rand16_cnt_prev; static uae_u16 rand16(void) { int cnt = rand16_cnt & 15; @@ -1620,7 +1651,7 @@ static uae_u16 rand16(void) v |= 1; return v; } -static int rand32_cnt; +static int rand32_cnt, rand32_cnt_prev; static uae_u32 rand32(void) { int cnt = rand32_cnt & 31; @@ -1643,7 +1674,7 @@ static uae_u32 rand32(void) // first 3 values: positive // next 4 values: negative // last: zero -static int rand8_cnt; +static int rand8_cnt, rand8_cnt_prev; static uae_u8 rand8(void) { int cnt = rand8_cnt & 7; @@ -1777,6 +1808,8 @@ static bool regchange(int reg, uae_u32 *regs) return false; if (feature_loop_mode_register == reg) return false; + if ((1 << reg) & ignore_register_mask) + return false; // don't unnecessarily modify static forced register for (int i = 0; i < regdatacnt; i++) { @@ -1931,13 +1964,84 @@ static void compressfile(TCHAR *path, int flags) static void compressfiles(const TCHAR *dir) { - for (int i = 1; i < filecount; i++) { + for (int i = 0; i < filecount; i++) { TCHAR path[1000]; _stprintf(path, _T("%s/%04d.dat"), dir, i); compressfile(path, 1); } } +static void mergefiles(const TCHAR *dir) +{ + int tsize = 0; + FILE *of = NULL; + int oi = -1; + unsigned char zero[4] = { 0, 0, 0, 0 }; + unsigned char head[4] = { 0xff, 0xff, 0xff, 0xff }; + TCHAR opath[1000]; + for (int i = 0; i < filecount; i++) { + TCHAR path[1000]; + _stprintf(path, _T("%s/%04d.dat"), dir, i); + if (feature_gzip & 1) { + if (_tcschr(path, '.')) { + path[_tcslen(path) - 1] = 'z'; + } else { + _tcscat(path, _T(".gz")); + } + } + FILE *f = _tfopen(path, _T("rb")); + fseek(f, 0, SEEK_END); + int size = ftell(f); + fseek(f, 0, SEEK_SET); + if (tsize > 0 && max_file_size > 0 && tsize + size >= max_file_size * 1024) { + fwrite(head, 1, 4, of); + fwrite(zero, 1, 4, of); + fclose(of); + of = NULL; + tsize = 0; + } + uae_u8 *mem = (uae_u8 *)malloc(size); + fread(mem, 1, size, f); + fclose(f); + if (!of) { + oi++; + _stprintf(opath, _T("%s/%04d.dat"), dir, oi); + if (feature_gzip & 1) { + if (_tcschr(opath, '.')) { + opath[_tcslen(opath) - 1] = 'z'; + } else { + _tcscat(opath, _T(".gz")); + } + } + of = _tfopen(opath, _T("wb")); + if (!of) { + wprintf(_T("Couldn't open '%s'\n"), opath); + abort(); + } + } + if (oi != i) { + _tunlink(path); + } + unsigned char b; + fwrite(head, 1, 4, of); + b = size >> 24; + fwrite(&b, 1, 1, of); + b = size >> 16; + fwrite(&b, 1, 1, of); + b = size >> 8; + fwrite(&b, 1, 1, of); + b = size >> 0; + fwrite(&b, 1, 1, of); + fwrite(mem, 1, size, of); + tsize += size; + free(mem); + } + if (of) { + fwrite(zero, 1, 4, of); + fclose(of); + } +} + static void save_memory(const TCHAR *path, const TCHAR *name, uae_u8 *p, int size) { TCHAR fname[1000]; @@ -2615,6 +2719,8 @@ static int create_ea_random(uae_u16 *opcodep, uaecptr pc, int mode, int reg, str } else { break; } + } else if (((1 << reg) & ignore_register_mask)) { + return -1; } else { break; } @@ -2726,7 +2832,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 + 7 || ((1 << ereg) & ignore_register_mask))) { continue; } break; @@ -2781,7 +2887,10 @@ 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 + 7)) { + return -1; + } + if ((1 << ereg) & ignore_register_mask) { return -1; } *regused = ereg; @@ -3918,10 +4027,7 @@ static bool check_interrupts(void) static int get_ipl(void) { - if (cpu_cycles + 4 > regs.ipl_time) { - return regs.ipl[0]; - } - return regs.ipl[1]; + return regs.ipl[0]; } static void execute_ins(uaecptr endpc, uaecptr targetpc, struct instr *dp, bool fpumode) @@ -3968,7 +4074,6 @@ static void execute_ins(uaecptr endpc, uaecptr targetpc, struct instr *dp, bool regs.loop_mode = 0; regs.ipl_pin = 0; regs.ipl[0] = regs.ipl[1] = 0; - regs.ipl_time = 0; interrupt_level = 0; interrupt_cycle_cnt = 0; test_exception_orig = 0; @@ -4097,10 +4202,16 @@ static void execute_ins(uaecptr endpc, uaecptr targetpc, struct instr *dp, bool break; } + if (test_exception) { + break; + } + if (get_ipl() > regs.intmask) { Exception(24 + get_ipl()); break; } + regs.ipl[0] = regs.ipl[1]; + regs.ipl[1] = 0; if ((regs.pc == endpc || regs.pc == targetpc) && !cpu_stopped && feature_interrupts < 2) { // Trace is only added as an exception if there was no other exceptions @@ -4177,8 +4288,8 @@ static void execute_ins(uaecptr endpc, uaecptr targetpc, struct instr *dp, bool if (test_exception >= 24 && test_exception <= 24 + 8) { if (test_exception_addr != opcode_memory_address && test_exception_addr != opcode_memory_address - 2 && - test_exception_addr != test_instruction_end_pc) - { + test_exception_addr != test_instruction_end_pc && + test_exception_addr != branch_target) { test_exception = -1; } } @@ -4529,6 +4640,16 @@ static void test_mnemo(const TCHAR *path, const TCHAR *mnemo, const TCHAR *ovrfi registers[8 + 3] = test_memory_start; // A3 = start of test memory } + ignore_register_mask = 0; + if (feature_loop_mode_register >= 0) { + ignore_register_mask |= 1 << feature_loop_mode_register; + } + if (feature_interrupts >= 2) { + // D0 and D7 is modified by delay code + ignore_register_mask |= 1 << 0; + ignore_register_mask |= 1 << 7; + } + registers[8 + 6] = opcode_memory_start - 0x100; registers[15] = user_stack_memory_use; @@ -4613,9 +4734,23 @@ static void test_mnemo(const TCHAR *path, const TCHAR *mnemo, const TCHAR *ovrfi uae_u32 target_ea_bak[3], target_address_bak, target_opcode_address_bak; + rnd_seed_prev = rnd_seed; + rand8_cnt_prev = rand8_cnt; + rand16_cnt_prev = rand16_cnt_prev; + rand32_cnt_prev = rand32_cnt_prev; + xorshiftstate_prev = xorshiftstate; + for (;;) { int got_something = 0; + if (feature_interrupts >= 2) { + rnd_seed = rnd_seed; + rand8_cnt = rand8_cnt; + rand16_cnt = rand16_cnt_prev; + rand32_cnt = rand32_cnt_prev; + xorshiftstate = xorshiftstate_prev; + } + target_ea_bak[0] = target_ea[0]; target_ea_bak[1] = target_ea[1]; target_ea_bak[2] = target_ea[2]; @@ -4855,18 +4990,50 @@ static void test_mnemo(const TCHAR *path, const TCHAR *mnemo, const TCHAR *ovrfi // move ccr,d7 put_word_test(pc + 0, 0x42c7); // 4 cycles } + pc += 2; +#if IPL_TRIGGER_ADDR_SIZE == 1 + // move.b #x,xxx.L (4 * 4 + 4) + put_long_test(pc, (0x13fc << 16) | IPL_TRIGGER_DATA); +#else + // move.w #x,xxx.L (4 * 4 + 4) + put_long_test(pc, (0x33fc << 16) | IPL_TRIGGER_DATA); +#endif + pc += 4; + put_long_test(pc, IPL_TRIGGER_ADDR); + pc += 4; // moveq #x,d0 (4 cycles) - put_word_test(pc + 2, 0x7000 | interrupt_delay_cnt); - // move.b d0,0xdc0000 (RTCW) (8 + 4 + 4) - put_word_test(pc + 4, 0x13c0); - put_long_test(pc + 6, IPL_TRIGGER_ADDR); + int shift = interrupt_delay_cnt; + int ashift; + if (shift > 63) { + shift -= 63; + ashift = 63; + } else { + ashift = 0; + } + if (shift > 63 || ashift > 63) { + wprintf(_T("IPL delay count too large!\n")); + abort(); + } + + put_word_test(pc, 0x7000 | (ashift & 63)); + pc += 2; // ror.l d0,d0 (4 + 4 + d0 * 2 cycles) - put_word_test(pc + 10, 0xe0b8); + put_word_test(pc, 0xe0b8); + pc += 2; + // moveq #x,d0 (4 cycles) + put_word_test(pc, 0x7000 | (shift & 63)); + pc += 2; + // ror.l d0,d0 (4 + 4 + d0 * 2 cycles) + put_word_test(pc, 0xe0b8); + pc += 2; // restore CCR // move d7,ccr - put_word_test(pc + 12, 0x44c7); // 12 cycles - put_word_test(pc + 14, NOP_OPCODE); // 4 cycles - pc += 16; + put_word_test(pc, 0x44c7); // 12 cycles + pc += 2; + put_word_test(pc, NOP_OPCODE); // 4 cycles + pc += 2; + put_word_test(pc, NOP_OPCODE); // 4 cycles + pc += 2; if (feature_interrupts >= 3) { // or #$8000,sr put_long_test(pc, 0x007c8000); @@ -5004,7 +5171,7 @@ static void test_mnemo(const TCHAR *path, const TCHAR *mnemo, const TCHAR *ovrfi pc += handle_specials_misc(opc, pc, dp, &isconstant_src); if (fpumode) { - // append fnop so that we detect pending FPU exceptions immediately + // append FNOP so that we detect pending FPU exceptions immediately put_long_test(pc, 0xf2800000); pc += 4; } @@ -5180,6 +5347,10 @@ static void test_mnemo(const TCHAR *path, const TCHAR *mnemo, const TCHAR *ovrfi uaecptr nextpc; srcaddr = 0xffffffff; dstaddr = 0xffffffff; + + if (opc == 0x4efb && get_word_debug(opcode_memory_address + 2) == 0x06d4) + printf(""); + uae_u32 dflags = m68k_disasm_2(out, sizeof(out) / sizeof(TCHAR), opcode_memory_address, NULL, 0, &nextpc, 1, &srcaddr, &dstaddr, 0xffffffff, 0); if (verbose) { my_trim(out); @@ -5203,6 +5374,10 @@ static void test_mnemo(const TCHAR *path, const TCHAR *mnemo, const TCHAR *ovrfi } } } + + + if (srcaddr == 0x006b022e) + printf(""); // disassembler may set this out_of_test_space = false; @@ -5247,8 +5422,8 @@ static void test_mnemo(const TCHAR *path, const TCHAR *mnemo, const TCHAR *ovrfi } #endif - uaecptr branch_target = 0xffffffff; - uaecptr branch_target_pc = 0xffffffff; + branch_target = 0xffffffff; + branch_target_pc = 0xffffffff; int bc = isbranchinst(dp); if (bc) { if (bc < 0) { @@ -5612,7 +5787,7 @@ static void test_mnemo(const TCHAR *path, const TCHAR *mnemo, const TCHAR *ovrfi if (regs.sr & 0x2000) prev_s_cnt++; - if (subtest_count == 19) + if (subtest_count == 77171) printf(""); // execute test instruction(s) @@ -5693,7 +5868,7 @@ static void test_mnemo(const TCHAR *path, const TCHAR *mnemo, const TCHAR *ovrfi } if (safe_memory_mode) { skipped = 1; - } + } } // skip exceptions if loop mode and not CC instruction @@ -5855,7 +6030,7 @@ static void test_mnemo(const TCHAR *path, const TCHAR *mnemo, const TCHAR *ovrfi } } if (cpu_lvl <= 1 && (last_cpu_cycles != cpu_cycles || first_cycles)) { - dst = store_reg(dst, CT_CYCLES, last_cpu_cycles, cpu_cycles, first_cycles ? 0 : -1); + dst = store_reg(dst, CT_CYCLES, last_cpu_cycles, cpu_cycles, first_cycles ? sz_word : -1); last_cpu_cycles = cpu_cycles; first_cycles = 0; } @@ -6007,19 +6182,19 @@ static void test_mnemo(const TCHAR *path, const TCHAR *mnemo, const TCHAR *ovrfi if (lookup->mnemo == i_ILLG || fpuopcode == FPUOPP_ILLEGAL) break; - bool nextround = false; + int nextround = 0; if (target_address != 0xffffffff) { target_ea_src_cnt++; if (target_ea_src_cnt >= target_ea_src_max) { target_ea_src_cnt = 0; if (target_ea_src_max > 0) - nextround = true; + nextround = 1; } target_ea_dst_cnt++; if (target_ea_dst_cnt >= target_ea_dst_max) { target_ea_dst_cnt = 0; if (target_ea_dst_max > 0) - nextround = true; + nextround = 1; } target_ea[0] = 0xffffffff; target_ea[1] = 0xffffffff; @@ -6032,28 +6207,28 @@ static void test_mnemo(const TCHAR *path, const TCHAR *mnemo, const TCHAR *ovrfi } generate_target_registers(target_address, cur_regs.regs); } else { - nextround = true; + nextround = 1; } // interrupt delay test if (feature_interrupts >= 2) { interrupt_delay_cnt++; - if (interrupt_delay_cnt >= MAX_INTERRUPT_DELAY) { + if (interrupt_delay_cnt > 2 * 63) { break; } else { - nextround = true; + nextround = -1; rounds = 1; quick = 0; } } if (target_opcode_address != 0xffffffff || target_usp_address != 0xffffffff) { - nextround = false; + nextround = 0; target_ea_opcode_cnt++; if (target_ea_opcode_cnt >= target_ea_opcode_max) { target_ea_opcode_cnt = 0; if (target_ea_opcode_max > 0) - nextround = true; + nextround = 1; } else { quick = 0; } @@ -6076,16 +6251,25 @@ static void test_mnemo(const TCHAR *path, const TCHAR *mnemo, const TCHAR *ovrfi } } - cur_regs.regs[0] &= 0xffff; - cur_regs.regs[8] &= 0xffff; - cur_regs.regs[8 + 6]--; - cur_regs.regs[15] -= 2; + if (nextround >= 0) { + cur_regs.regs[0] &= 0xffff; + cur_regs.regs[8] &= 0xffff; + cur_regs.regs[8 + 6]--; + cur_regs.regs[15] -= 2; + rnd_seed_prev = rnd_seed; + rand8_cnt_prev = rand8_cnt; + rand16_cnt_prev = rand16_cnt; + rand32_cnt_prev = rand32_cnt; + xorshiftstate_prev = xorshiftstate; + } } markfile(dir); compressfiles(dir); + mergefiles(dir); + wprintf(_T("- %d tests\n"), subtest_count); } @@ -6793,6 +6977,9 @@ static int test(struct ini_data *ini, const TCHAR *sections, const TCHAR *testna feature_test_rounds_opcode = 0; ini_getvalx(ini, sections, _T("min_opcode_test_rounds"), &feature_test_rounds_opcode); + max_file_size = 200; + ini_getvalx(ini, sections, _T("max_file_size"), &max_file_size); + ini_getstringx(ini, sections, _T("feature_instruction_size"), &feature_instruction_size_text); for (int i = 0; i < _tcslen(feature_instruction_size_text); i++) { TCHAR c = _totupper(feature_instruction_size_text[i]); diff --git a/cputest/asm.S b/cputest/asm.S index 40faacaf..0d2616e5 100644 --- a/cputest/asm.S +++ b/cputest/asm.S @@ -357,6 +357,7 @@ exception: move.w sr,-(sp) _cyclereg_address4: move.w CYCLEREG,cycles+2 + move.w #0x2700,sr move.w #0,ACTIVITYREG | exception start inside this assembly code? cmp.l #asm_start,2+4+2(sp) @@ -369,7 +370,11 @@ _cyclereg_address4: cmp.l #_exceptiontable000+(24+8)*2,2(sp) bcc.s .okpc | possibly IPL tester spurious interrupt - | ignore it + | ignore it. Mark cycle count as invalid. +#ifdef AMIGA + move.w #0x0800,0xdff09c +#endif + move.l #0xffffffff,cycles addq.l #2+4,sp rte .okpc: @@ -398,12 +403,9 @@ _cyclereg_address4: bcs.s .nointerrupt cmp.w #24+8,d0 bcc.s .nointerrupt - | possible IPL test run, delay a bit - | to make sure tester hardware is not pulling - | IPL line down anymore - moveq #16-1,d1 -.delay1: - dbf d1,.delay1 +#ifdef AMIGA + move.w #0x0800,0xdff09c +#endif .nointerrupt: move.w (sp)+,S_SR+2(a0) diff --git a/cputest/cputest_defines.h b/cputest/cputest_defines.h index 5aaeb9b1..8c79a2e5 100644 --- a/cputest/cputest_defines.h +++ b/cputest/cputest_defines.h @@ -1,5 +1,5 @@ -#define DATA_VERSION 22 +#define DATA_VERSION 23 #define CT_FPREG 0 #define CT_DREG 0 @@ -58,7 +58,10 @@ #define ILLG_OPCODE 0x4afc #define LM_OPCODE 0x42db -#define INTERRUPT_CYCLES 64 -#define MAX_INTERRUPT_DELAY 64 -#define IPL_TRIGGER_ADDR 0xdc0000 -#define IPL_TEST_IPL_LEVEL 4 +#define IPL_TRIGGER_ADDR 0xdff030 +#define IPL_TRIGGER_ADDR_SIZE 2 +#define IPL_TRIGGER_DATA 0x100 +#define IPL_TRIGGER_SERPER 10 +#define INTERRUPT_CYCLES ((((IPL_TRIGGER_SERPER + 1) * 9) + (((IPL_TRIGGER_SERPER + 1) - 1) / 2) + 1 + 3 + 9) * 2) +#define IPL_TRIGGER_INTMASK 0x0800 +#define IPL_TEST_IPL_LEVEL 5 diff --git a/cputest/cputestgen.ini b/cputest/cputestgen.ini index 802919bc..6d8bcbe6 100644 --- a/cputest/cputestgen.ini +++ b/cputest/cputestgen.ini @@ -36,7 +36,11 @@ path=data/ ; 1 = compress only test data files ; 2 = compress only main data files ; 3 = compress all data files -feature_gzip=0 +feature_gzip=1 + +; data file max size in kilobytes (split size) +; 0 = no split +max_file_size=0 ; Low address space limits. Real hardware must have RAM in this space. Comment out to disable. ; Start should be zero if Amiga, set to 0x0800 if Atari ST. diff --git a/cputest/main.c b/cputest/main.c index 5e14e98b..3caf07f5 100644 --- a/cputest/main.c +++ b/cputest/main.c @@ -173,6 +173,10 @@ static uae_u8 stackaddr[SIZE_STORED_ADDRESS]; static uae_u32 stackaddr_ptr; static uae_u8 *opcode_memory_end; +#define MAX_IPL_PC_VALUES 4 +static uae_u32 ipl_pc[MAX_IPL_PC_VALUES]; +static int ipl_pc_cnt[MAX_IPL_PC_VALUES]; + static char opcode[32], group[32], cpustr[10]; #ifndef M68K @@ -608,25 +612,63 @@ static int set_berr(int mask, int ask) return getchar(); } -static uae_u8 *load_file(const char *path, const char *file, uae_u8 *p, int *sizep, int exiterror, int candirect) +static int load_file_offset(FILE *f, int *foffsetp) +{ + int size = -1; + unsigned char buf[4] = { 0 }; + fseek(f, *foffsetp, SEEK_SET); + fread(buf, 1, sizeof(buf), f); + if (buf[0] == 0xff && buf[1] == 0xff && buf[2] == 0xff && buf[3] == 0xff) { + fread(buf, 1, sizeof(buf), f); + size = (buf[0] << 24) | (buf[1] << 16) | (buf[2] << 8) | (buf[3] << 0); + if (size == 0) { + *foffsetp = -1; + return 0; + } + *foffsetp = *foffsetp + size + 8; + return size; + } + *foffsetp = -1; + return -1; +} + +static uae_u8 *load_file(const char *path, const char *file, uae_u8 *p, int *sizep, int *foffsetp, int exiterror, int candirect) { char fname[256]; uae_u8 *unpack = NULL; int unpackoffset = 0; int size = 0; + int foffset = foffsetp ? *foffsetp : 0; - strcpy(fname, path); - strcat(fname, file); - if (strchr(file, '.')) { - fname[strlen(fname) - 1] = 'z'; + if (path) { + strcpy(fname, path); + strcat(fname, file); + if (strchr(file, '.')) { + fname[strlen(fname) - 1] = 'z'; + } else { + strcat(fname, ".gz"); + } } else { - strcat(fname, ".gz"); + strcpy(fname, file); } FILE *f = fopen(fname, "rb"); if (f) { - fseek(f, 0, SEEK_END); - int gsize = ftell(f); - fseek(f, 0, SEEK_SET); + int gsize; + if (foffsetp) { + gsize = load_file_offset(f, foffsetp); + if (gsize == 0) { + return NULL; + } + if (gsize > 0) { + *sizep = gsize; + } + } + if (*sizep <= 0) { + fseek(f, 0, SEEK_END); + gsize = ftell(f); + fseek(f, 0, SEEK_SET); + } + uae_u8 *gzbuf = NULL; if (prealloc) { if (!prealloc_gzip) { @@ -698,7 +740,11 @@ static uae_u8 *load_file(const char *path, const char *file, uae_u8 *p, int *siz } } if (!unpack) { - sprintf(fname, "%s%s", path, file); + if (path) { + sprintf(fname, "%s%s", path, file); + } else { + strcpy(fname, file); + } f = fopen(fname, "rb"); if (!f) { if (exiterror) { @@ -707,8 +753,17 @@ static uae_u8 *load_file(const char *path, const char *file, uae_u8 *p, int *siz } return NULL; } + if (foffsetp) { + size = load_file_offset(f, foffsetp); + if (size == 0) { + return NULL; + } + if (size > 0) { + *sizep = size; + } + } size = *sizep; - if (size < 0) { + if (size <= 0) { fseek(f, 0, SEEK_END); size = ftell(f); fseek(f, 0, SEEK_SET); @@ -2147,21 +2202,31 @@ static uae_u16 test_intena, test_intreq; static void set_interrupt(void) { - if (interrupt_count < 15) { - volatile uae_u16 *intena = (uae_u16 *)0xdff09a; - volatile uae_u16 *intreq = (uae_u16 *)0xdff09c; - uae_u16 mask = 1 << interrupt_count; - test_intena = mask | 0x8000 | 0x4000; - test_intreq = mask | 0x8000; - *intena = test_intena; - *intreq = test_intreq; + if (interrupttest == 1) { + if (interrupt_count < 15) { + volatile uae_u16 *intena = (uae_u16*)0xdff09a; + volatile uae_u16 *intreq = (uae_u16*)0xdff09c; + uae_u16 mask = 1 << interrupt_count; + test_intena = mask | 0x8000 | 0x4000; + test_intreq = mask | 0x8000; + *intena = test_intena; + *intreq = test_intreq; + } + } + if (interrupttest == 2) { + volatile uae_u16 *intena = (uae_u16*)0xdff09a; + volatile uae_u16 *intreq = (uae_u16*)0xdff09c; + volatile uae_u16 *serper = (uae_u16*)0xdff032; + *serper = IPL_TRIGGER_SERPER; + *intena = 0x8000 | 0x4000 | IPL_TRIGGER_INTMASK; + *intreq = IPL_TRIGGER_INTMASK; } } static void clear_interrupt(void) { - volatile uae_u16 *intena = (uae_u16 *)0xdff09a; - volatile uae_u16 *intreq = (uae_u16 *)0xdff09c; + volatile uae_u16 *intena = (uae_u16*)0xdff09a; + volatile uae_u16 *intreq = (uae_u16*)0xdff09c; *intena = 0x7fff; *intreq = 0x7fff; } @@ -2941,7 +3006,7 @@ static void out_endinfo(void) outbp += strlen(outbp); sprintf(outbp, "S=%d", supercnt); outbp += strlen(outbp); - for (int i = 0; i < 128; i++) { + for (short i = 0; i < 128; i++) { if (exceptioncount[0][i] || exceptioncount[1][i] || exceptioncount[2][i]) { if (i == 2 || i == 3) { sprintf(outbp, " E%02d=%d/%d/%d", i, exceptioncount[0][i], exceptioncount[1][i], exceptioncount[2][i]); @@ -2957,6 +3022,16 @@ static void out_endinfo(void) } strcat(outbp, "\n"); outbp += strlen(outbp); + if (interrupttest == 2) { + for (short i = 0; i < MAX_IPL_PC_VALUES; i++) { + if (ipl_pc[i]) { + sprintf(outbp, "%08x:%d ", ipl_pc[i], ipl_pc_cnt[i]); + outbp += strlen(outbp); + } + } + strcat(outbp, "\n"); + outbp += strlen(outbp); + } if (fpu_approxcnt) { sprintf(outbp, "FPU approximate matches: %d\n", fpu_approxcnt); } @@ -3272,10 +3347,11 @@ static void process_test(uae_u8 *p) #ifdef AMIGA - if (interrupttest == 1) { + if (interrupttest) { set_interrupt(); } #endif + if (cpu_lvl == 1) { execute_test010(&test_regs); } else if (cpu_lvl >= 2) { @@ -3322,6 +3398,26 @@ static void process_test(uae_u8 *p) p = validate_test(p, ignore_errors, ignore_sr, &cur_regs, &test_regs, &last_regs, opcodeendsizeextra); + if (interrupttest == 2) { + short found = 0; + for (short i = 0; i < MAX_IPL_PC_VALUES; i++) { + if (ipl_pc[i] == test_regs.pc) { + ipl_pc_cnt[i]++; + found = 1; + + } + } + if (!found) { + for (short i = 0; i < MAX_IPL_PC_VALUES; i++) { + if (ipl_pc[i] == 0) { + ipl_pc[i] = test_regs.pc; + ipl_pc_cnt[i] = 1; + break; + } + } + } + } + testcnt++; if (super) supercnt++; @@ -3419,7 +3515,7 @@ static int test_mnemo(const char *opcode) uae_u8 data[4] = { 0 }; uae_u32 v; char tfname[256]; - int filecnt = 1; + int filecnt = 0; uae_u32 starttimeid; int lvl; @@ -3429,8 +3525,10 @@ static int test_mnemo(const char *opcode) sprintf(tfname, "%s/0000.dat", opcode); size = -1; - uae_u8 *headerfile = load_file(path, tfname, NULL, &size, 1, 1); + int foffset = 0; + uae_u8 *headerfile = load_file(path, tfname, NULL, &size, &foffset, 1, 1); if (!headerfile) { + printf("Data file failed to open\n"); exit(0); } int headoffset = 0; @@ -3536,7 +3634,7 @@ static int test_mnemo(const char *opcode) } size = test_memory_size; - load_file(path, "tmem.dat", test_memory, &size, 1, 0); + load_file(path, "tmem.dat", test_memory, &size, NULL, 1, 0); if (size != test_memory_size) { printf("tmem.dat size mismatch\n"); exit(0); @@ -3569,14 +3667,27 @@ static int test_mnemo(const char *opcode) } } + int otestcnt = -1; + printf("offset = %d\n", foffset); for (;;) { - printf("%s (%s). %u...\n", tfname, group, testcnt); + if (otestcnt != testcnt) { + printf("%s (%s). %u...\n", tfname, group, testcnt); + otestcnt = testcnt; + } sprintf(tfname, "%s/%04d.dat", opcode, filecnt); - test_data_size = -1; - test_data = load_file(path, tfname, test_data_prealloc, &test_data_size, 0, 1); + test_data_size = 0; + test_data = load_file(path, tfname, test_data_prealloc, &test_data_size, &foffset, 0, 1); + + printf("%p %d\n", test_data, foffset); + if (!test_data) { + if (foffset < 0) { + filecnt++; + foffset = 0; + continue; + } if (askifmissing) { printf("Couldn't open '%s%s'. Type new path and press enter.\n", path, tfname); path[0] = 0; @@ -3627,7 +3738,9 @@ static int test_mnemo(const char *opcode) break; } - filecnt++; + if (foffset <= 0) { + filecnt++; + } } if (errorcnt == 0) { @@ -3929,9 +4042,9 @@ int main(int argc, char *argv[]) } low_memory_size = -1; - low_memory_temp = load_file(path, "lmem.dat", NULL, &low_memory_size, 0, 1); + low_memory_temp = load_file(path, "lmem.dat", NULL, &low_memory_size, NULL, 0, 1); high_memory_size = -1; - high_memory_temp = load_file(path, "hmem.dat", NULL, &high_memory_size, 0, 1); + high_memory_temp = load_file(path, "hmem.dat", NULL, &high_memory_size, NULL, 0, 1); #ifndef M68K low_memory = calloc(1, 32768);