// 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) {
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];
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);
void ipl_fetch(void)
{
if (regs.ipl_pin) {
- regs.ipl = regs.ipl_pin;
+ regs.ipl[0] = regs.ipl_pin;
}
}
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);
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
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)
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)
{
}
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;
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;
}
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;
}
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;
}
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;
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
abort();
}
- if (SPCFLAG_TRACE && !cpu_stopped) {
+ if (SPCFLAG_TRACE) {
do_trace();
}
}
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++) {
if (out_of_test_space) {
break;
}
+
// CPU stopped or was reset: skip
if (cpu_stopped && feature_interrupts < 2) {
break;
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;
}
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);
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,
// 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;
*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);
*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..
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]);
if (regs.sr & 0x2000)
prev_s_cnt++;
- if (subtest_count == 433)
+ if (subtest_count == 19)
printf("");
// execute test instruction(s)
}
// exception check disabled
- if (!exceptionenabletable[test_exception]) {
+ if (test_exception < 0 || !exceptionenabletable[test_exception]) {
skipped = 1;
}
}
}
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++) {
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;
uae_u8 *sp = (uae_u8*)regs->excframe;
uae_u32 v;
uae_u8 excdatalen = *p++;
- int size;
int excrwp = 0;
int alts = 0;
{
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) {
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);
outbp += strlen(outbp);
}
}
+ if (invalidcycles) {
+ sprintf(outbp, " INVCYC=%d", invalidcycles);
+ outbp += strlen(outbp);
+ }
strcat(outbp, "\n");
outbp += strlen(outbp);
if (fpu_approxcnt) {
short doopcodeswap = 1;
+ if (interrupttest >= 1) {
+ doopcodeswap = 0;
+ }
+
for (;;) {
cur_regs.endpc = endpc;
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;
_T(" a <address> Assembler.\n")
_T(" d <address> [<lines>] Disassembly starting at <address>.\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 <address> Add/remove breakpoint.\n")
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));
}
}
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"));
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;
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)
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 ");
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);
}
}
-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;
+ }
}
}
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;
}
}
} 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;
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);
}
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
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;
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);
return (dmamask & dmacon) && (dmacon & 0x200);
}
-#define SPCFLAG_STOP 2
#define SPCFLAG_COPPER 4
#define SPCFLAG_INT 8
#define SPCFLAG_BRK 16
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);
int halted;
int exception;
int intmask;
- int ipl, ipl_pin;
+ int ipl[2], ipl_pin;
+ evt_t ipl_time;
uae_u32 vbr, sfc, dfc;
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 *);
static int cpu_prefs_changed_flag;
+int cpuipldelay;
int cpucycleunit;
int cpu_tracer;
}
write_log(_T("\n"));
+ if (m68k_interrupt_delay) {
+ cpuipldelay = 4 * cpucycleunit;
+ } else {
+ cpuipldelay = 0;
+ }
+
set_cpu_caches (true);
target_cpu_speed();
}
if (regs.stopped)
return;
regs.stopped = 1;
- set_special(SPCFLAG_STOP);
if (cpu_last_stop_vpos >= 0) {
cpu_last_stop_vpos = vpos;
}
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;
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)
} 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)
inprec_playdebug_cpu (2);
}
- m68k_unset_stop();
assert (nr < 8 && nr >= 0);
for (;;) {
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)
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;
// 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)
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
static int do_specialties (int cycles)
{
- bool stopped_debug = false;
+ uaecptr pc = m68k_getpc();
if (regs.spcflags & SPCFLAG_MODE_CHANGE)
return 1;
#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) {
/* 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. */
}
}
#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) {
} 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())
}
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();
}
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
}
return 0;
}
+
+uaecptr m68kpc(void)
+{
+ return m68k_getpc();
+}
+
//static uae_u32 pcs[1000];
#if DEBUG_CD32CDTVIO
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;
}
if (do_specialties(cpu_cycles))
exit = true;
}
- regs.ipl = regs.ipl_pin;
+ regs.ipl[0] = regs.ipl[1] = regs.ipl_pin;
} ENDTRY
}
}
} else {
write_log (_T("CPU TRACE: STOPPED\n"));
}
- if (r->stopped)
- set_special (SPCFLAG_STOP);
set_cpu_tracer (false);
goto cont;
}
do_interrupt(ilvl);
}
- if (!(regs.spcflags & SPCFLAG_STOP))
- break;
-
- uae_sem_wait(&cpu_wakeup_sema);
+ break;
}
return 0;
} 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;
else if (cputrace.state == 1)
(*cpufunctbl[cputrace.opcode])(cputrace.opcode);
}
- if (regs.stopped)
- set_special (SPCFLAG_STOP);
set_cpu_tracer (false);
goto cont;
}
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;
}
} 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;
else if (cputrace.state == 1)
(*cpufunctbl[cputrace.opcode])(cputrace.opcode);
}
- if (regs.stopped)
- set_special (SPCFLAG_STOP);
set_cpu_tracer (false);
goto cont;
}
fill_prefetch_quick ();
set_cycles (start_cycles);
events_schedule ();
- if (regs.stopped)
- set_special (SPCFLAG_STOP);
//activate_debugger ();
}
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();
}