}
if (dr->evt & DMA_EVENT_CPUIRQ)
l3[cl2++] = 'I';
+ if (dr->evt & DMA_EVENT_CPUSTOP)
+ l3[cl2++] = '|';
+ if (dr->evt & DMA_EVENT_CPUSTOPIPL)
+ l3[cl2++] = '+';
if (dr->evt & DMA_EVENT_INTREQ)
l3[cl2++] = 'i';
if (dr->evt & DMA_EVENT_SPECIAL)
lastframes = history[temp].fp;
lastvpos = history[temp].vpos;
lasthpos = history[temp].hpos;
- console_out_f(_T("%2d "), regs.intmask ? regs.intmask : (regs.s ? -1 : 0));
+ console_out_f(_T("%2d %03d/%03d "), regs.intmask ? regs.intmask : (regs.s ? -1 : 0), lasthpos, lastvpos);
m68k_disasm (regs.pc, NULL, 0xffffffff, 1);
}
if (addr && regs.pc == addr)
static void addhistory (void)
{
+ if (regs.stopped)
+ return;
+
uae_u32 pc = currprefs.cpu_model >= 68020 && currprefs.cpu_compatible ? regs.instruction_pc : m68k_getpc();
history[lasthist].regs = regs;
history[lasthist].regs.pc = pc;
trace_t0_68040_only();
break;
case i_STOP:
+ {
if (using_prefetch) {
out("uae_u16 sr = regs.irc;\n");
m68k_pc_offset += 2;
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();
- out("m68k_setstopped();\n");
- if ((cpu_level == 0 || cpu_level == 1) && (using_ce || using_prefetch)) {
- out("%s(4);\n", do_cycles);
+ 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();
// STOP does not prefetch anything
next_cpu_level = cpu_level - 1;
next_level_000();
break;
+ }
case i_LPSTOP: /* 68060 */
out("uae_u16 sw = %s;\n", gen_nextiword(0));
out("if (sw != 0x01c0) {\n");
#define DMA_EVENT_HSE 0x04000000
#define DMA_EVENT_CIAA_IRQ 0x08000000
#define DMA_EVENT_CIAB_IRQ 0x10000000
+#define DMA_EVENT_CPUSTOP 0x20000000
+#define DMA_EVENT_CPUSTOPIPL 0x40000000
+
#define DMARECORD_REFRESH 1
#define DMARECORD_CPU 2
extern void m68k_setstopped(void);
extern void m68k_resumestopped(void);
extern void m68k_cancel_idle(void);
+extern void do_cycles_stop(int);
extern uae_u32 REGPARAM3 get_disp_ea_020 (uae_u32 base, int idx) REGPARAM;
extern uae_u32 REGPARAM3 get_bitfield (uae_u32 src, uae_u32 bdata[2], uae_s32 offset, int width) REGPARAM;
extern void prepare_interrupt (uae_u32);
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 *);
bool check_prefs_changed_comp (bool checkonly) { return false; }
#endif
/* For faster JIT cycles handling */
-uae_s32 pissoff = 0;
+int pissoff = 0;
/* Opcode of faulting instruction */
static uae_u32 last_op_for_exception_3;
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 void debug_cpu_stop(void)
+{
+ record_dma_event(DMA_EVENT_CPUSTOP, current_hpos(), vpos);
+ if (time_for_interrupt()) {
+ record_dma_event(DMA_EVENT_CPUSTOPIPL, current_hpos(), vpos);
+ }
+}
+
static int do_specialties (int cycles)
{
bool stopped_debug = false;
Exception (3);
}
- bool first = true;
while (regs.spcflags & SPCFLAG_STOP) {
if (regs.s == 0 && currprefs.cpu_model <= 68010) {
if (m68k_interrupt_delay) {
unset_special(SPCFLAG_INT);
if (time_for_interrupt()) {
- if (!first) {
- // extra loop because even after higher ipl detection,
- // stop needs to do one more loop before it exits.
+ // 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);
}
}
- first = false;
ipl_fetch();
- x_do_cycles(4 * cpucycleunit);
- if (regs.spcflags & SPCFLAG_COPPER)
+ 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();
return false;
}
+void do_cycles_stop(int 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)
{