From: Toni Wilen Date: Mon, 11 Jul 2022 08:40:18 +0000 (+0300) Subject: Yet another STOP emulation rewrite. Not yet fully cputester validated. X-Git-Tag: 41000~200 X-Git-Url: https://git.unchartedbackwaters.co.uk/w/?a=commitdiff_plain;h=ab6586585444601f7da57626f41ddb78006bf1bb;p=francis%2Fwinuae.git Yet another STOP emulation rewrite. Not yet fully cputester validated. --- diff --git a/cia.cpp b/cia.cpp index d7236dda..d7efa40e 100644 --- a/cia.cpp +++ b/cia.cpp @@ -2747,7 +2747,7 @@ static void REGPARAM2 clock_bput(uaecptr addr, uae_u32 value) // write_log(_T("W: %x (%x): %x, PC=%08x\n"), addr, (addr & 0xff) >> 2, value & 0xff, M68K_GETPC); if (currprefs.cputester && (addr & 65535) == 0) { - event2_newevent_xx(-1, CYCLE_UNIT * (62 / 2), 0, cputester_event); + event2_newevent_xx(-1, CYCLE_UNIT * (64 / 2 - 1), 0, cputester_event); } if ((addr & 0xffff) >= 0x8000 && currprefs.cs_fatgaryrev >= 0) { diff --git a/cputest.cpp b/cputest.cpp index 18c9442f..7e01e081 100644 --- a/cputest.cpp +++ b/cputest.cpp @@ -126,7 +126,7 @@ static int max_storage_buffer; static bool out_of_test_space; static uaecptr out_of_test_space_addr; static int forced_immediate_mode; -static int test_exception; +static int test_exception, test_exception_orig; static int test_exception_extra; static int exception_stack_frame_size; static uae_u8 exception_extra_frame[100]; @@ -522,7 +522,7 @@ void put_byte_test(uaecptr addr, uae_u32 v) return; if (feature_interrupts >= 2 && addr == IPL_TRIGGER_ADDR) { add_memory_cycles(1); - interrupt_cycle_cnt = INTERRUPT_CYCLES - 2; + interrupt_cycle_cnt = INTERRUPT_CYCLES; return; } check_bus_error(addr, 1, regs.s ? 5 : 1); @@ -830,7 +830,7 @@ bool is_cycle_ce(uaecptr addr) void ipl_fetch(void) { if (regs.ipl_pin) { - regs.ipl = regs.ipl_pin; + regs.ipl[0] = regs.ipl_pin; } } @@ -839,6 +839,11 @@ int intlev(void) return interrupt_level; } +void do_cycles_stop(int c) +{ + do_cycles_test(c); +} + uae_u32(*x_get_long)(uaecptr); uae_u32(*x_get_word)(uaecptr); uae_u32(*x_get_byte)(uaecptr); @@ -905,6 +910,10 @@ static void activate_trace(void) static void do_trace(void) { + if (cpu_stopped) { + m68k_incpci(4); + cpu_stopped = 0; + } regs.trace_pc = regs.pc; if (regs.t0 && !regs.t1 && currprefs.cpu_model >= 68020) { // this is obsolete @@ -1020,13 +1029,7 @@ void cpu_halt(int halt) void m68k_setstopped(void) { - /* A traced STOP instruction drops through immediately without - actually stopping. */ - if (SPCFLAG_DOTRACE == 0) { - cpu_stopped = 1; - } else { - cpu_stopped = 0; - } + cpu_stopped = 1; } void check_t0_trace(void) @@ -1475,13 +1478,15 @@ uae_u16 exception3_word_read(uaecptr addr) void REGPARAM2 Exception(int n) { + if (cpu_stopped) { + m68k_incpci(4); + cpu_stopped = 0; + } + test_exception = n; test_exception_addr = m68k_getpci(); test_exception_opcode = -1; doexcstack(); - if (n >= 24 && n < 24 + 8) { - cpu_stopped = 0; - } } void REGPARAM2 Exception_cpu_oldpc(int n, uaecptr oldpc) { @@ -2085,25 +2090,25 @@ static uae_u8 *store_fpureg(uae_u8 *dst, uae_u8 mode, floatx80 *s, floatx80 d, i } uae_u8 fs[10], fd[10]; fs[0] = s->high >> 8; - fs[1] = s->high; - fs[2] = s->low >> 56; - fs[3] = s->low >> 48; - fs[4] = s->low >> 40; - fs[5] = s->low >> 32; - fs[6] = s->low >> 24; - fs[7] = s->low >> 16; - fs[8] = s->low >> 8; - fs[9] = s->low >> 0; + fs[1] = (uae_u8)s->high; + fs[2] = (uae_u8)(s->low >> 56); + fs[3] = (uae_u8)(s->low >> 48); + fs[4] = (uae_u8)(s->low >> 40); + fs[5] = (uae_u8)(s->low >> 32); + fs[6] = (uae_u8)(s->low >> 24); + fs[7] = (uae_u8)(s->low >> 16); + fs[8] = (uae_u8)(s->low >> 8); + fs[9] = (uae_u8)(s->low >> 0); fd[0] = d.high >> 8; - fd[1] = d.high; - fd[2] = d.low >> 56; - fd[3] = d.low >> 48; - fd[4] = d.low >> 40; - fd[5] = d.low >> 32; - fd[6] = d.low >> 24; - fd[7] = d.low >> 16; - fd[8] = d.low >> 8; - fd[9] = d.low >> 0; + fd[1] = (uae_u8)d.high; + fd[2] = (uae_u8)(d.low >> 56); + fd[3] = (uae_u8)(d.low >> 48); + fd[4] = (uae_u8)(d.low >> 40); + fd[5] = (uae_u8)(d.low >> 32); + fd[6] = (uae_u8)(d.low >> 24); + fd[7] = (uae_u8)(d.low >> 16); + fd[8] = (uae_u8)(d.low >> 8); + fd[9] = (uae_u8)(d.low >> 0); *dst++ = mode | CT_SIZE_FPU; if (fs[4] != fd[4] || fs[5] != fd[5]) { *dst++ = 0xff; @@ -2460,7 +2465,7 @@ static int putfpuimm(uaecptr addr, int opcodesize, int *isconstant) fpu_imm_cnt++; put_long_test(addr + 0, v.high); put_long_test(addr + 4, v.low >> 32); - put_long_test(addr + 8, v.low); + put_long_test(addr + 8, (uae_u32)v.low); addr += 12; break; } @@ -2492,7 +2497,7 @@ static int putfpuimm(uaecptr addr, int opcodesize, int *isconstant) fpu_imm_cnt++; float64 v2 = floatx80_to_float64(v, &fpustatus); put_long_test(addr + 0, v2 >> 32); - put_long_test(addr + 4, v2); + put_long_test(addr + 4, (uae_u32)v2); addr += 8; break; } @@ -3051,7 +3056,11 @@ static int create_ea_random(uae_u16 *opcodep, uaecptr pc, int mode, int reg, str put_word_test(pc, imm16_cnt); if (dp->mnemo == i_STOP && feature_interrupts > 0) { // STOP hack to keep STOP test size smaller. - imm16_cnt += 0x0100; + if (feature_interrupts > 1) { + imm16_cnt += 0x0100; + } else { + imm16_cnt += 0x0001; + } } else { imm16_cnt += 0x0001; } @@ -3907,6 +3916,14 @@ static bool check_interrupts(void) return false; } +static int get_ipl(void) +{ + if (cpu_cycles + 4 > regs.ipl_time) { + return regs.ipl[0]; + } + return regs.ipl[1]; +} + static void execute_ins(uaecptr endpc, uaecptr targetpc, struct instr *dp, bool fpumode) { uae_u16 opc = regs.ir; @@ -3950,13 +3967,16 @@ static void execute_ins(uaecptr endpc, uaecptr targetpc, struct instr *dp, bool cpu_cycles = 0; regs.loop_mode = 0; regs.ipl_pin = 0; - regs.ipl = 0; + regs.ipl[0] = regs.ipl[1] = 0; + regs.ipl_time = 0; interrupt_level = 0; interrupt_cycle_cnt = 0; + test_exception_orig = 0; int cnt = 2; uaecptr first_pc = regs.pc; uae_u32 loop_mode_reg = 0; + int stop_count = 0; if (feature_loop_mode_68010) { // 68010 loop mode @@ -3990,7 +4010,7 @@ static void execute_ins(uaecptr endpc, uaecptr targetpc, struct instr *dp, bool abort(); } - if (SPCFLAG_TRACE && !cpu_stopped) { + if (SPCFLAG_TRACE) { do_trace(); } @@ -4012,24 +4032,14 @@ static void execute_ins(uaecptr endpc, uaecptr targetpc, struct instr *dp, bool } if (cpu_stopped) { - if (feature_interrupts && !interrupt_cycle_cnt) { - test_exception = -1; + stop_count++; + if (stop_count > 256) { break; } - ipl_fetch(); - do_cycles_test(4); - if (!SPCFLAG_DOTRACE && regs.s == 0 && currprefs.cpu_model <= 68010) { - // 68000/68010 undocumented special case: - // if STOP clears S-bit and T was not set: - // cause privilege violation exception, PC pointing to following instruction. - // If T was set before STOP: STOP works as documented. - cpu_stopped = 0; - Exception(8); - } - } else { - (*cpufunctbl[opc])(opc); } + (*cpufunctbl[opc])(opc); + if (fpumode) { // skip result has too large or small exponent for (int i = 0; i < 8; i++) { @@ -4060,6 +4070,7 @@ static void execute_ins(uaecptr endpc, uaecptr targetpc, struct instr *dp, bool if (out_of_test_space) { break; } + // CPU stopped or was reset: skip if (cpu_stopped && feature_interrupts < 2) { break; @@ -4086,17 +4097,18 @@ static void execute_ins(uaecptr endpc, uaecptr targetpc, struct instr *dp, bool break; } - if (!test_exception && regs.ipl > regs.intmask) { - Exception(24 + regs.ipl); + if (get_ipl() > regs.intmask) { + Exception(24 + get_ipl()); break; } - if ((regs.pc == endpc || regs.pc == targetpc) && !cpu_stopped) { + 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 // Trace stacked with other exception is handled later if (SPCFLAG_DOTRACE && !test_exception && trace_store_pc == 0xffffffffff) { Exception(9); } + break; } @@ -4117,11 +4129,6 @@ static void execute_ins(uaecptr endpc, uaecptr targetpc, struct instr *dp, bool trace_store_sr = regs.sr; SPCFLAG_DOTRACE = 0; } - // STOP can only end with exception, fake prefetch here. - if (dp->mnemo == i_STOP) { - regs.ir = get_iword_test(regs.pc + 0); - regs.irc = get_iword_test(regs.pc + 2); - } } if (currprefs.cpu_model >= 68020) { regs.ir = get_iword_test(regs.pc + 0); @@ -4148,12 +4155,20 @@ static void execute_ins(uaecptr endpc, uaecptr targetpc, struct instr *dp, bool opc = regs.ir; } + test_exception_orig = test_exception; + + // if still stopped: skip test + if (cpu_stopped) { + test_exception = -1; + } + if (feature_interrupts >= 2) { - // IPL test must cause some exception - if (!test_exception || test_exception == 8) { + // Skip test if end exception + if (regs.pc == endpc || regs.pc == targetpc) { test_exception = -1; } - if (cpu_stopped) { + // Skip test if no exception + if (!test_exception) { test_exception = -1; } // Interrupt start must be before test instruction, @@ -4198,7 +4213,7 @@ static uae_u8 *save_exception(uae_u8 *p, struct instr *dp) // Separate, non-stacked Trace if (test_exception_extra & 0x80) { *p++ = trace_store_sr >> 8; - *p++ = trace_store_sr; + *p++ = (uae_u8)trace_store_sr; p = store_rel(p, 0, opcode_memory_start, trace_store_pc, 1); } uae_u8 *sf = NULL; @@ -4221,7 +4236,7 @@ static uae_u8 *save_exception(uae_u8 *p, struct instr *dp) *p++ = sf[7]; if (st & 0x20) { *p++ = regs.opcode >> 8; - *p++ = regs.opcode; + *p++ = (uae_u8)regs.opcode; } // access address p = store_rel(p, 0, opcode_memory_start, gl(sf + 2), 1); @@ -4281,7 +4296,7 @@ static uae_u8 *save_exception(uae_u8 *p, struct instr *dp) *p++ = sf[25]; // optional data input (some hardware does real memory fetch when CPU does the dummy fetch, some don't) *p++ = read_buffer_prev >> 8; - *p++ = read_buffer_prev; + *p++ = (uae_u8)read_buffer_prev; break; case 0x0a: // 68020/030 address error. case 0x0b: // Don't save anything extra, too many undefined fields and bits.. @@ -4653,6 +4668,10 @@ static void test_mnemo(const TCHAR *path, const TCHAR *mnemo, const TCHAR *ovrfi int branch_target_swap_mode_old = 0; int doopcodeswap = 1; + if (feature_interrupts >= 2) { + doopcodeswap = 0; + } + if (verbose) { if (target_ea[0] != 0xffffffff) wprintf(_T(" Target EA SRC=%08x\n"), target_ea[0]); @@ -5593,7 +5612,7 @@ static void test_mnemo(const TCHAR *path, const TCHAR *mnemo, const TCHAR *ovrfi if (regs.sr & 0x2000) prev_s_cnt++; - if (subtest_count == 433) + if (subtest_count == 19) printf(""); // execute test instruction(s) @@ -5627,7 +5646,7 @@ static void test_mnemo(const TCHAR *path, const TCHAR *mnemo, const TCHAR *ovrfi } // exception check disabled - if (!exceptionenabletable[test_exception]) { + if (test_exception < 0 || !exceptionenabletable[test_exception]) { skipped = 1; } @@ -5921,8 +5940,10 @@ static void test_mnemo(const TCHAR *path, const TCHAR *mnemo, const TCHAR *ovrfi } } if (verbose) { - wprintf(_T(" OK=%d OB=%d S=%d/%d T=%d STP=%d I=%d/%d %08x"), ok, exception_array[0], - prev_s_cnt, s_cnt, t_cnt, cnt_stopped, interrupt_delay_cnt, interrupt_cycle_cnt, test_exception_addr); + wprintf(_T(" OK=%d OB=%d S=%d/%d T=%d STP=%d I=%d/%d EX=%d %08x %08x"), ok, exception_array[0], + prev_s_cnt, s_cnt, t_cnt, cnt_stopped, interrupt_delay_cnt, interrupt_cycle_cnt, + test_exception_orig, + test_exception_addr, regs.pc); if (!ccr_done) wprintf(_T(" X")); for (int i = 2; i < 128; i++) { diff --git a/cputest/main.c b/cputest/main.c index b608c30f..5e14e98b 100644 --- a/cputest/main.c +++ b/cputest/main.c @@ -128,6 +128,7 @@ static int errors; static int totalerrors; static int testcnt; static short testcntsub, testcntsubmax; +static int invalidcycles; static int fpu_approx, fpu_approxcnt; static short dooutput = 1; static short quit; @@ -1696,7 +1697,6 @@ static uae_u8 *validate_exception(struct registers *regs, uae_u8 *p, short excnu uae_u8 *sp = (uae_u8*)regs->excframe; uae_u32 v; uae_u8 excdatalen = *p++; - int size; int excrwp = 0; int alts = 0; @@ -2172,6 +2172,13 @@ static int check_cycles(int exc, short extratrace, short extrag2w1, struct regis { int gotcycles = 0; + if ((test_regs.cycles >> 16) == 0xffff) { + // cycle counter got exception (interrupt) during exception handling + // -> cycle counter was invalidated. Ignore cycle count. + invalidcycles++; + return 1; + } + if (cyclecounter_addr != 0xffffffff) { gotcycles = (test_regs.cycles & 0xffff) - (test_regs.cycles >> 16); if (gotcycles == 0) { @@ -2257,7 +2264,7 @@ static int check_cycles(int exc, short extratrace, short extrag2w1, struct regis if (0 || abs(gotcycles - expectedcycles) > cycles_range) { addinfo(); - sprintf(outbp, "Got %d cycles (%d + %d) but expected %d (%d + %d) cycles\n", + sprintf(outbp, "Got %d cycles (%d + %d) but expected %d (%d + %d)\n", gotcycles, gotcycles - exceptioncycles, exceptioncycles, expectedcycles, expectedcycles - exceptioncycles, exceptioncycles); outbp += strlen(outbp); @@ -2944,6 +2951,10 @@ static void out_endinfo(void) outbp += strlen(outbp); } } + if (invalidcycles) { + sprintf(outbp, " INVCYC=%d", invalidcycles); + outbp += strlen(outbp); + } strcat(outbp, "\n"); outbp += strlen(outbp); if (fpu_approxcnt) { @@ -3018,6 +3029,10 @@ static void process_test(uae_u8 *p) short doopcodeswap = 1; + if (interrupttest >= 1) { + doopcodeswap = 0; + } + for (;;) { cur_regs.endpc = endpc; @@ -3403,7 +3418,7 @@ static int test_mnemo(const char *opcode) int size; uae_u8 data[4] = { 0 }; uae_u32 v; - char fname[256], tfname[256]; + char tfname[256]; int filecnt = 1; uae_u32 starttimeid; int lvl; diff --git a/debug.cpp b/debug.cpp index 09a66aa6..b32dbf81 100644 --- a/debug.cpp +++ b/debug.cpp @@ -179,6 +179,7 @@ static const TCHAR help[] = { _T(" a
Assembler.\n") _T(" d
[] Disassembly starting at
.\n") _T(" t [instructions] Step one or more instructions.\n") + _T(" tx Break when any exception.\n") _T(" z Step through one instruction - useful for JSR, DBRA etc.\n") _T(" f Step forward until PC in RAM (\"boot block finder\").\n") _T(" f
Add/remove breakpoint.\n") @@ -1401,7 +1402,7 @@ static void set_dbg_color(int index, int extra, uae_u8 r, uae_u8 g, uae_u8 b, in if (extra >= 0) { debug_colors[index].l[extra] = lc((r << 16) | (g << 8) | (b << 0)); } else { - for (int i = 0; i < DMARECORD_SUBITEMS; i++) { + for (int i = 0; i < DMARECORD_MAX; i++) { debug_colors[index].l[i] = lc((r << 16) | (g << 8) | (b << 0)); } } @@ -1417,7 +1418,7 @@ static void set_debug_colors(void) set_dbg_color(DMARECORD_CPU, 0, 0xa2, 0x53, 0x42, 2, _T("CPU")); // code set_dbg_color(DMARECORD_COPPER, 0, 0xee, 0xee, 0x00, 3, _T("Copper")); set_dbg_color(DMARECORD_AUDIO, 0, 0xff, 0x00, 0x00, 4, _T("Audio")); - set_dbg_color(DMARECORD_BLITTER, 0, 0x00, 0x88, 0x88, 2, _T("Blitter")); // blit A + set_dbg_color(DMARECORD_BLITTER, 0, 0x00, 0x88, 0x88, 2, _T("Blitter")); set_dbg_color(DMARECORD_BITPLANE, 0, 0x00, 0x00, 0xff, 8, _T("Bitplane")); set_dbg_color(DMARECORD_SPRITE, 0, 0xff, 0x00, 0xff, 8, _T("Sprite")); set_dbg_color(DMARECORD_DISK, 0, 0xff, 0xff, 0xff, 3, _T("Disk")); @@ -1432,11 +1433,8 @@ static void set_debug_colors(void) set_dbg_color(DMARECORD_CPU, 1, 0xad, 0x98, 0xd6, 0, NULL); // data set_dbg_color(DMARECORD_COPPER, 1, 0xaa, 0xaa, 0x22, 0, NULL); // wait set_dbg_color(DMARECORD_COPPER, 2, 0x66, 0x66, 0x44, 0, NULL); // special - set_dbg_color(DMARECORD_BLITTER, 1, 0x00, 0x88, 0x88, 0, NULL); // blit B - set_dbg_color(DMARECORD_BLITTER, 2, 0x00, 0x88, 0x88, 0, NULL); // blit C - set_dbg_color(DMARECORD_BLITTER, 3, 0x00, 0xaa, 0x88, 0, NULL); // blit D (write) - set_dbg_color(DMARECORD_BLITTER, 4, 0x00, 0x88, 0xff, 0, NULL); // fill A-D - set_dbg_color(DMARECORD_BLITTER, 6, 0x00, 0xff, 0x00, 0, NULL); // line A-D + set_dbg_color(DMARECORD_BLITTER, 1, 0x00, 0x88, 0xff, 0, NULL); // fill + set_dbg_color(DMARECORD_BLITTER, 2, 0x00, 0xff, 0x00, 0, NULL); // line } static int cycles_toggle; @@ -1477,20 +1475,10 @@ static void debug_draw_cycles (uae_u8 *buf, int bpp, int line, int width, int he uae_u32 c = debug_colors[0].l[0]; xx = x * xplus + dx; dr = &dma_record[t][y * NR_DMA_REC_HPOS + x]; - if (dr->reg != 0xffff && debug_colors[dr->type].enabled) { - // General DMA slots - c = debug_colors[dr->type].l[dr->extra & 7]; - - // Special cases + c = debug_colors[dr->type].l[dr->extra]; if (dr->cf_reg != 0xffff && ((cycles_toggle ^ line) & 1)) { c = debug_colors[DMARECORD_CONFLICT].l[0]; - } else if (dr->extra > 0xF) { - // High bits of "extra" contain additional blitter state. - if (dr->extra & 0x10) - c = debug_colors[dr->type].l[4]; // blit fill, channels A-D - else if (dr->extra & 0x20) - c = debug_colors[dr->type].l[6]; // blit line, channels A-D } } if (dr->intlev > intlev) @@ -2103,9 +2091,7 @@ static bool get_record_dma_info(struct dma_rec *dr, int hpos, int vpos, evt_t cy sr = _T(" "); if (dr->type == DMARECORD_COPPER) { - if (br == 2) - sr = _T("COPS"); - else if (br == 1) + if (dr->extra == 3) sr = _T("COPW"); else sr = _T("COP "); @@ -6153,6 +6139,11 @@ static bool debug_line (TCHAR *input) trace_param[1] = debugmem_get_sourceline(M68K_GETPC, NULL, 0); return true; } + } else if (*inptr == 'x') { + trace_mode = TRACE_SKIP_INS; + trace_param[0] = 0xffffffff; + exception_debugging = 1; + return true; } else { if (more_params(&inptr)) trace_param[0] = readint(&inptr); @@ -6561,22 +6552,26 @@ static void debug_1 (void) } } -static void addhistory (void) +static void addhistory(void) { - if (regs.stopped) - return; - uae_u32 pc = currprefs.cpu_model >= 68020 && currprefs.cpu_compatible ? regs.instruction_pc : m68k_getpc(); + int prevhist = lasthist == 0 ? MAX_HIST - 1 : lasthist - 1; + if (history[prevhist].regs.pc == pc) { + return; + } history[lasthist].regs = regs; history[lasthist].regs.pc = pc; history[lasthist].vpos = vpos; history[lasthist].hpos = current_hpos(); history[lasthist].fp = timeframes; - if (++lasthist == MAX_HIST) + if (++lasthist == MAX_HIST) { lasthist = 0; + } if (lasthist == firsthist) { - if (++firsthist == MAX_HIST) firsthist = 0; + if (++firsthist == MAX_HIST) { + firsthist = 0; + } } } @@ -6585,6 +6580,19 @@ static void debug_continue(void) set_special (SPCFLAG_BRK); } +void debug_exception(int nr) +{ + if (debug_illegal) { + if (nr <= 63 && (debug_illegal_mask & ((uae_u64)1 << nr))) { + write_log(_T("Exception %d breakpoint\n"), nr); + activate_debugger(); + } + } + if (trace_param[0] == 0xffffffff && trace_mode == TRACE_SKIP_INS) { + activate_debugger(); + } +} + void debug (void) { int i; @@ -6726,7 +6734,7 @@ void debug (void) } } } else if (trace_mode == TRACE_SKIP_INS) { - if (trace_param[0] != 0) + if (trace_param[0] != 0 && trace_param[0] != 0xffffffff) trace_param[0]--; if (trace_param[0] == 0) { bp = -1; @@ -6783,9 +6791,16 @@ void debug (void) if (trace_cycles && last_frame >= 0) { if (last_frame + 2 >= timeframes || trace_cycles > 1) { + evt_t c = last_cycles2 - last_cycles1; + uae_u32 cc; + if (c >= 0x7fffffff) { + cc = 0x7fffffff; + } else { + cc = (uae_u32)c; + } console_out_f(_T("Cycles: %d Chip, %d CPU. (V=%d H=%d -> V=%d H=%d)\n"), - (last_cycles2 - last_cycles1) / CYCLE_UNIT, - (last_cycles2 - last_cycles1) / cpucycleunit, + cc / CYCLE_UNIT, + cc / cpucycleunit, last_vpos1, last_hpos1, last_vpos2, last_hpos2); } diff --git a/gencpu.cpp b/gencpu.cpp index 3d4c04fb..6e5fef58 100644 --- a/gencpu.cpp +++ b/gencpu.cpp @@ -6657,16 +6657,19 @@ static void gen_opcode (unsigned int opcode) break; case i_STOP: { + const char *reg = cpu_level <= 1 ? "irc" : "ir"; + out("if (!regs.stopped) {\n"); if (using_prefetch) { - out("uae_u16 sr = regs.irc;\n"); - m68k_pc_offset += 2; + out("uae_u16 src = regs.%s;\n", reg); } else { genamode(curi, curi->smode, "srcreg", curi->size, "src", 1, 0, 0); - out("uae_u16 sr = src;\n"); } + out("regs.%s = src;\n", reg); + out("}\n"); + out("uae_u16 sr = regs.%s;\n", reg); // STOP undocumented features: // if new SR S-bit is not set: - // 68000/68010: Update SR, increase PC and then cause privilege violation exception (handled in newcpu) + // 68000/68010: Update SR, increase PC and then cause privilege violation exception // 68000/68010: Traced STOP runs 4 cycles faster. // 68020 68030 68040: STOP works normally // 68060: Immediate privilege violation exception @@ -6676,25 +6679,14 @@ static void gen_opcode (unsigned int opcode) write_return_cycles(0); out("}\n"); } - bool accstop = (cpu_level == 0 || cpu_level == 1) && (using_ce || using_prefetch); - if (accstop) { - // if interrupt is pending before SR change: STOP finishes in 4 cycles - out("bool irq = stop_interrupt_pending();\n"); - } out("regs.sr = sr;\n"); check_ipl_always(); - makefromsr(); - if (accstop) { - out("do_cycles_stop(4);\n"); - out("if (!irq) {\n"); - out("m68k_setstopped();\n"); - out("}\n"); - } else { - out("m68k_setstopped();\n"); - } - sync_m68k_pc(); + out("MakeFromSR();\n"); + out("do_cycles_stop(4);\n"); + out("m68k_setstopped();\n"); // STOP does not prefetch anything did_prefetch = -1; + m68k_pc_offset = 0; next_cpu_level = cpu_level - 1; next_level_000(); break; diff --git a/include/cpu_prefetch.h b/include/cpu_prefetch.h index 6885e164..4d7a6737 100644 --- a/include/cpu_prefetch.h +++ b/include/cpu_prefetch.h @@ -386,7 +386,9 @@ STATIC_INLINE void do_cycles_ce000 (int clocks) STATIC_INLINE void ipl_fetch (void) { - regs.ipl = regs.ipl_pin; + regs.ipl[1] = regs.ipl[0]; + regs.ipl[0] = regs.ipl_pin; + regs.ipl_time = get_cycles(); } uae_u32 mem_access_delay_word_read (uaecptr addr); diff --git a/include/custom.h b/include/custom.h index aae817e8..2ef6a75f 100644 --- a/include/custom.h +++ b/include/custom.h @@ -81,7 +81,6 @@ STATIC_INLINE int dmaen(unsigned int dmamask) return (dmamask & dmacon) && (dmacon & 0x200); } -#define SPCFLAG_STOP 2 #define SPCFLAG_COPPER 4 #define SPCFLAG_INT 8 #define SPCFLAG_BRK 16 diff --git a/include/debug.h b/include/debug.h index 1acbda9c..b881d4bf 100644 --- a/include/debug.h +++ b/include/debug.h @@ -73,6 +73,7 @@ extern int memwatch_access_validator; extern bool debug_sprintf(uaecptr, uae_u32, int); extern bool debug_get_prefetch(int idx, uae_u16 *opword); extern void debug_hsync(void); +extern void debug_exception(int); extern void debug_init_trainer(const TCHAR*); extern void debug_trainer_match(void); diff --git a/include/newcpu.h b/include/newcpu.h index 6a6c59a0..82621185 100644 --- a/include/newcpu.h +++ b/include/newcpu.h @@ -201,7 +201,8 @@ struct regstruct int halted; int exception; int intmask; - int ipl, ipl_pin; + int ipl[2], ipl_pin; + evt_t ipl_time; uae_u32 vbr, sfc, dfc; @@ -689,9 +690,8 @@ extern void REGPARAM3 ExceptionL (int, uaecptr) REGPARAM; extern void NMI (void); extern void IRQ_forced(int, int); extern void prepare_interrupt (uae_u32); -extern void doint (void); +extern void doint(void); extern void intlev_load(void); -extern bool stop_interrupt_pending(void); extern void dump_counts (void); extern int m68k_move2c (int, uae_u32 *); extern int m68k_movec2 (int, uae_u32 *); diff --git a/newcpu.cpp b/newcpu.cpp index 291ea226..8b842876 100644 --- a/newcpu.cpp +++ b/newcpu.cpp @@ -104,6 +104,7 @@ static int cachedsets04060, cachedsets04060mask, cachedtag04060mask; static int cpu_prefs_changed_flag; +int cpuipldelay; int cpucycleunit; int cpu_tracer; @@ -2030,6 +2031,12 @@ static void build_cpufunctbl (void) } write_log(_T("\n")); + if (m68k_interrupt_delay) { + cpuipldelay = 4 * cpucycleunit; + } else { + cpuipldelay = 0; + } + set_cpu_caches (true); target_cpu_speed(); } @@ -2290,7 +2297,6 @@ static void m68k_set_stop(void) if (regs.stopped) return; regs.stopped = 1; - set_special(SPCFLAG_STOP); if (cpu_last_stop_vpos >= 0) { cpu_last_stop_vpos = vpos; } @@ -2299,7 +2305,6 @@ static void m68k_set_stop(void) static void m68k_unset_stop(void) { regs.stopped = 0; - unset_special(SPCFLAG_STOP); if (cpu_last_stop_vpos >= 0) { cpu_stopped_lines += vpos - cpu_last_stop_vpos; cpu_last_stop_vpos = vpos; @@ -3327,12 +3332,10 @@ static void ExceptionX (int nr, uaecptr address, uaecptr oldpc) if (oldpc != 0xffffffff) { regs.instruction_pc = oldpc; } - if (debug_illegal && !in_rom(pc)) { - if (nr <= 63 && (debug_illegal_mask & ((uae_u64)1 << nr))) { - write_log(_T("Exception %d breakpoint\n"), nr); - activate_debugger(); - } - } +#ifdef DEBUGGER + debug_exception(nr); +#endif + m68k_resumestopped(); #ifdef CPUEMU_13 if (currprefs.cpu_cycle_exact && currprefs.cpu_model <= 68010) @@ -3396,6 +3399,14 @@ static void bus_error(void) } ENDTRY } +static int get_ipl(void) +{ + if (get_cycles() - cpuipldelay > regs.ipl_time) { + return regs.ipl[0]; + } + return regs.ipl[1]; +} + static void do_interrupt (int nr) { if (debug_dma) @@ -3408,7 +3419,6 @@ static void do_interrupt (int nr) inprec_playdebug_cpu (2); } - m68k_unset_stop(); assert (nr < 8 && nr >= 0); for (;;) { @@ -3416,7 +3426,7 @@ static void do_interrupt (int nr) if (!currprefs.cpu_compatible || currprefs.cpu_model == 68060) break; if (m68k_interrupt_delay) - nr = regs.ipl; + nr = get_ipl(); else nr = intlev(); if (nr <= 0 || regs.intmask >= nr) @@ -3471,7 +3481,7 @@ static void m68k_reset2(bool hardreset) regs.spcflags = 0; m68k_reset_delay = 0; - regs.ipl = regs.ipl_pin = 0; + regs.ipl[0] = regs.ipl[1] = regs.ipl_pin = 0; for (int i = 0; i < IRQ_SOURCE_MAX; i++) { uae_interrupts2[i] = 0; uae_interrupts6[i] = 0; @@ -4345,9 +4355,10 @@ static bool uae_ppc_poll_check_halt(void) // handle interrupt delay (few cycles) -STATIC_INLINE bool time_for_interrupt (void) +static bool time_for_interrupt(void) { - return regs.ipl > regs.intmask || regs.ipl == 7; + int ipl = get_ipl(); + return ipl > regs.intmask || ipl == 7; } void intlev_load(void) @@ -4355,20 +4366,6 @@ void intlev_load(void) doint(); } -bool stop_interrupt_pending(void) -{ - if (m68k_interrupt_delay) { - int il = intlev(); - regs.ipl_pin = il; - if (regs.ipl_pin > regs.intmask || regs.ipl_pin == 7) { - if (regs.spcflags & SPCFLAG_INT) { - return true; - } - } - } - return false; -} - void doint(void) { #ifdef WITH_PPC @@ -4413,7 +4410,7 @@ static void debug_cpu_stop(void) static int do_specialties (int cycles) { - bool stopped_debug = false; + uaecptr pc = m68k_getpc(); if (regs.spcflags & SPCFLAG_MODE_CHANGE) return 1; @@ -4447,15 +4444,15 @@ static int do_specialties (int cycles) #ifdef ACTION_REPLAY #ifdef ACTION_REPLAY_HRTMON if ((regs.spcflags & SPCFLAG_ACTION_REPLAY) && hrtmon_flag != ACTION_REPLAY_INACTIVE) { - int isinhrt = (m68k_getpc () >= hrtmem_start && m68k_getpc () < hrtmem_start + hrtmem_size); + int isinhrt = pc >= hrtmem_start && pc < hrtmem_start + hrtmem_size; /* exit from HRTMon? */ if (hrtmon_flag == ACTION_REPLAY_ACTIVE && !isinhrt) - hrtmon_hide (); + hrtmon_hide(); /* HRTMon breakpoint? (not via IRQ7) */ if (hrtmon_flag == ACTION_REPLAY_IDLE && isinhrt) - hrtmon_breakenter (); + hrtmon_breakenter(); if (hrtmon_flag == ACTION_REPLAY_ACTIVATE) - hrtmon_enter (); + hrtmon_enter(); } #endif if ((regs.spcflags & SPCFLAG_ACTION_REPLAY) && action_replay_flag != ACTION_REPLAY_INACTIVE) { @@ -4463,14 +4460,14 @@ static int do_specialties (int cycles) /* write_log (_T("PC:%p\n"), m68k_getpc ());*/ if (action_replay_flag == ACTION_REPLAY_ACTIVATE || action_replay_flag == ACTION_REPLAY_DORESET) - action_replay_enter (); - if ((action_replay_flag == ACTION_REPLAY_HIDE || action_replay_flag == ACTION_REPLAY_ACTIVE) && !is_ar_pc_in_rom ()) { - action_replay_hide (); + action_replay_enter(); + if ((action_replay_flag == ACTION_REPLAY_HIDE || action_replay_flag == ACTION_REPLAY_ACTIVE) && !is_ar_pc_in_rom()) { + action_replay_hide(); unset_special (SPCFLAG_ACTION_REPLAY); } if (action_replay_flag == ACTION_REPLAY_WAIT_PC) { /*write_log (_T("Waiting for PC: %p, current PC= %p\n"), wait_for_pc, m68k_getpc ());*/ - if (m68k_getpc () == wait_for_pc) { + if (pc == wait_for_pc) { action_replay_flag = ACTION_REPLAY_ACTIVATE; /* Activate after next instruction. */ } } @@ -4478,14 +4475,14 @@ static int do_specialties (int cycles) #endif if (regs.spcflags & SPCFLAG_COPPER) - do_copper (); + do_copper(); #ifdef JIT - unset_special (SPCFLAG_END_COMPILE); /* has done its job */ + unset_special(SPCFLAG_END_COMPILE); /* has done its job */ #endif while ((regs.spcflags & SPCFLAG_BLTNASTY) && dmaen (DMA_BLITTER) && cycles > 0 && ((currprefs.waiting_blits && currprefs.cpu_model >= 68020) || !currprefs.blitter_cycle_exact)) { - int c = blitnasty (); + int c = blitnasty(); if (c < 0) { break; } else if (c > 0) { @@ -4495,9 +4492,9 @@ static int do_specialties (int cycles) } else { c = 4; } - x_do_cycles (c * CYCLE_UNIT); + x_do_cycles(c * CYCLE_UNIT); if (regs.spcflags & SPCFLAG_COPPER) - do_copper (); + do_copper(); #ifdef WITH_PPC if (ppc_state) { if (uae_ppc_poll_check_halt()) @@ -4508,116 +4505,15 @@ static int do_specialties (int cycles) } if (regs.spcflags & SPCFLAG_DOTRACE) - Exception (9); + Exception(9); if (regs.spcflags & SPCFLAG_TRAP) { unset_special (SPCFLAG_TRAP); - Exception (3); - } - - while (regs.spcflags & SPCFLAG_STOP) { - - if (regs.s == 0 && currprefs.cpu_model <= 68010) { - // 68000/68010 undocumented special case: - // if STOP clears S-bit and T was not set: - // cause privilege violation exception, PC pointing to following instruction. - // If T was set before STOP: STOP works as documented. - m68k_unset_stop(); - Exception(8); - break; - } - - isstopped: - check_uae_int_request(); - { - if (bsd_int_requested) - bsdsock_fake_int_handler (); - } - - if (cpu_tracer > 0) { - cputrace.stopped = regs.stopped; - cputrace.intmask = regs.intmask; - cputrace.sr = regs.sr; - cputrace.state = 1; - cputrace.pc = m68k_getpc (); - cputrace.memoryoffset = 0; - cputrace.cyclecounter = cputrace.cyclecounter_pre = cputrace.cyclecounter_post = 0; - cputrace.readcounter = cputrace.writecounter = 0; - } - - if (m68k_interrupt_delay) { - unset_special(SPCFLAG_INT); - if (time_for_interrupt()) { - // extra STOP "round" - if (debug_dma) { - debug_cpu_stop(); - x_do_cycles(2 * cpucycleunit); - debug_cpu_stop(); - x_do_cycles(2 * cpucycleunit); - } else { - x_do_cycles(4 * cpucycleunit); - } - do_interrupt(regs.ipl); - break; - } - } else { - if (regs.spcflags & (SPCFLAG_INT | SPCFLAG_DOINT)) { - int intr = intlev (); - unset_special (SPCFLAG_INT | SPCFLAG_DOINT); -#ifdef WITH_PPC - bool m68kint = true; - if (ppc_state) { - m68kint = ppc_interrupt(intr); - } - if (m68kint) { -#endif - if (intr > 0 && intr > regs.intmask) { - do_interrupt(intr); - break; - } -#ifdef WITH_PPC - } -#endif - } - } - - ipl_fetch(); - - if (debug_dma) { - debug_cpu_stop(); - x_do_cycles(2 * cpucycleunit); - debug_cpu_stop(); - x_do_cycles(2 * cpucycleunit); - } else { - x_do_cycles(4 * cpucycleunit); - } - - if (regs.spcflags & SPCFLAG_COPPER) { - do_copper(); - } - - if (regs.spcflags & SPCFLAG_MODE_CHANGE) { - m68k_resumestopped(); - fill_prefetch(); - return 1; - } - - if (regs.spcflags & SPCFLAG_BRK) { - stopped_debug = false; - goto dodebug; - } - -#ifdef WITH_PPC - if (ppc_state) { - uae_ppc_execute_check(); - uae_ppc_poll_check_halt(); - } -#endif - + Exception(3); } if (regs.spcflags & SPCFLAG_TRACE) - do_trace (); + do_trace(); if (regs.spcflags & SPCFLAG_UAEINT) { check_uae_int_request(); @@ -4625,44 +4521,29 @@ static int do_specialties (int cycles) } if (m68k_interrupt_delay) { - if (time_for_interrupt ()) { + if (time_for_interrupt()) { unset_special(SPCFLAG_INT); - do_interrupt (regs.ipl); + do_interrupt(get_ipl()); } } else { if (regs.spcflags & SPCFLAG_INT) { - int intr = intlev (); + int intr = intlev(); unset_special (SPCFLAG_INT | SPCFLAG_DOINT); if (intr > 0 && (intr > regs.intmask || intr == 7)) - do_interrupt (intr); + do_interrupt(intr); } } if (regs.spcflags & SPCFLAG_DOINT) { - unset_special (SPCFLAG_DOINT); - set_special (SPCFLAG_INT); + unset_special(SPCFLAG_DOINT); + set_special(SPCFLAG_INT); } - if ((regs.spcflags & SPCFLAG_BRK) || stopped_debug) { -dodebug: + if (regs.spcflags & SPCFLAG_BRK) { unset_special(SPCFLAG_BRK); #ifdef DEBUGGER - if (stopped_debug && !regs.stopped) { - if (debugging) { - debugger_active = 1; - stopped_debug = false; - } - } if (debugging) { - if (!stopped_debug) - debug(); - if (regs.stopped) { - stopped_debug = true; - if (debugging) { - debugger_active = 0; - } - goto isstopped; - } + debug(); } #endif } @@ -4670,6 +4551,12 @@ dodebug: return 0; } + +uaecptr m68kpc(void) +{ + return m68k_getpc(); +} + //static uae_u32 pcs[1000]; #if DEBUG_CD32CDTVIO @@ -4806,7 +4693,7 @@ static void m68k_run_1 (void) if (do_specialties (cpu_cycles)) exit = true; } - regs.ipl = regs.ipl_pin; + regs.ipl[0] = regs.ipl_pin; if (!currprefs.cpu_compatible || (currprefs.cpu_cycle_exact && currprefs.cpu_model <= 68010)) exit = true; } @@ -4816,7 +4703,7 @@ static void m68k_run_1 (void) if (do_specialties(cpu_cycles)) exit = true; } - regs.ipl = regs.ipl_pin; + regs.ipl[0] = regs.ipl[1] = regs.ipl_pin; } ENDTRY } } @@ -4867,8 +4754,6 @@ static void m68k_run_1_ce (void) } else { write_log (_T("CPU TRACE: STOPPED\n")); } - if (r->stopped) - set_special (SPCFLAG_STOP); set_cpu_tracer (false); goto cont; } @@ -5031,10 +4916,7 @@ static int do_specialties_thread(void) do_interrupt(ilvl); } - if (!(regs.spcflags & SPCFLAG_STOP)) - break; - - uae_sem_wait(&cpu_wakeup_sema); + break; } return 0; @@ -5741,7 +5623,7 @@ insretry: } else { regs.instruction_cnt++; - regs.ipl = regs.ipl_pin; + regs.ipl[0] = regs.ipl_pin; if (regs.spcflags || time_for_interrupt ()) { if (do_specialties(0)) { STOPTRY; @@ -5915,8 +5797,6 @@ static void m68k_run_2ce (void) else if (cputrace.state == 1) (*cpufunctbl[cputrace.opcode])(cputrace.opcode); } - if (regs.stopped) - set_special (SPCFLAG_STOP); set_cpu_tracer (false); goto cont; } @@ -5999,7 +5879,7 @@ static void m68k_run_2ce (void) regs.instruction_cnt++; cont: - regs.ipl = regs.ipl_pin; + regs.ipl[0] = regs.ipl_pin; if (r->spcflags || time_for_interrupt ()) { if (do_specialties (0)) exit = true; @@ -6009,7 +5889,7 @@ static void m68k_run_2ce (void) } } CATCH(prb) { bus_error(); - regs.ipl = regs.ipl_pin; + regs.ipl[0] = regs.ipl_pin; if (r->spcflags || time_for_interrupt()) { if (do_specialties(0)) exit = true; @@ -6060,8 +5940,6 @@ static void m68k_run_2p (void) else if (cputrace.state == 1) (*cpufunctbl[cputrace.opcode])(cputrace.opcode); } - if (regs.stopped) - set_special (SPCFLAG_STOP); set_cpu_tracer (false); goto cont; } @@ -6950,8 +6828,6 @@ void restore_cpu_finish (void) fill_prefetch_quick (); set_cycles (start_cycles); events_schedule (); - if (regs.stopped) - set_special (SPCFLAG_STOP); //activate_debugger (); } @@ -7672,32 +7548,31 @@ bool cpureset (void) void do_cycles_stop(int c) { - if (debug_dma) { - while (c >= 2) { - debug_cpu_stop(); - do_cycles_ce000_internal(2); - c -= 2; - } + if (!currprefs.cpu_compatible) { + do_cycles(c); } else { - do_cycles_ce000_internal(c); + if (debug_dma) { + while (c >= 2) { + debug_cpu_stop(); + do_cycles_ce000_internal(2); + c -= 2; + } + } else { + do_cycles_ce000_internal(c); + } } } void m68k_setstopped (void) { - /* A traced STOP instruction drops through immediately without - actually stopping. */ - if ((regs.spcflags & SPCFLAG_DOTRACE) == 0) { - m68k_set_stop(); - } else { - m68k_resumestopped(); - } + m68k_set_stop(); } void m68k_resumestopped(void) { if (!regs.stopped) return; + m68k_incpci(4); m68k_unset_stop(); }