diexec: Add callback to allow debugger to break into the middle of wait-type instructions whose execution time is normally indefinite. When this happens, a special message may be printed to the debug console stating the location of the last actual instruction executed before the wait (if there was one).

Note that since the callback ignores the current value of the program counter, this special type of debugger break cannot be entered through breakpoints or instruction stepping commands. The callback also leaves no effect on PC history tracking or trace logs.

* cpu/hd61700, cpu/tms32031: Add standard IRQ callback
* cpu/m68000gen.py: Change name of invoked executable to bin/python3
* cpu/m6809: Eliminate PC "massaging" for SYNC and similar instructions
This commit is contained in:
AJR 2024-11-17 08:11:09 -05:00
parent 3c6e66e50f
commit b1181f8602
77 changed files with 337 additions and 171 deletions

View File

@ -1176,6 +1176,7 @@ void adsp21xx_device::execute_run()
{
// Return if CPU is halted
if (current_input_state(INPUT_LINE_HALT)) {
debugger_wait_hook();
m_icount = 0;
return;
}

View File

@ -842,12 +842,14 @@ void apexc_cpu_device::execute_run()
{
do
{
debugger_instruction_hook(m_pc);
if (m_running)
{
debugger_instruction_hook(m_pc);
execute();
}
else
{
debugger_wait_hook();
DELAY(m_icount); /* burn cycles once for all */
}
} while (m_icount > 0);

View File

@ -98,16 +98,18 @@ void arcompact_device::execute_run()
{
while (m_icount > 0)
{
debugger_instruction_hook(m_pc);
if (!m_delayactive)
{
check_interrupts();
}
// make sure CPU isn't in 'SLEEP' mode
if (!debugreg_check_ZZ())
if (debugreg_check_ZZ())
debugger_wait_hook();
else
{
debugger_instruction_hook(m_pc);
if (m_delayactive)
{
uint16_t op = READ16((m_pc + 0));

View File

@ -203,6 +203,7 @@ void ccpu_cpu_device::execute_run()
{
if (m_waiting)
{
debugger_wait_hook();
m_icount = 0;
return;
}

View File

@ -206,14 +206,15 @@ void clipper_device::execute_run()
while (m_icount > 0)
{
debugger_instruction_hook(m_pc);
if (m_wait)
{
debugger_wait_hook();
m_icount = 0;
continue;
}
debugger_instruction_hook(m_pc);
// fetch and decode an instruction
if (decode_instruction())
{

View File

@ -812,11 +812,13 @@ void cosmac_device::execute_run()
break;
case cosmac_mode::RESET:
debugger_wait_hook();
reset_state();
m_icount--;
break;
case cosmac_mode::PAUSE:
debugger_wait_hook();
m_icount--;
break;

View File

@ -563,6 +563,7 @@ void dsp32c_device::execute_run()
// skip if halted
if ((m_pcr & PCR_RESET) == 0)
{
debugger_wait_hook();
m_icount = 0;
return;
}

View File

@ -465,6 +465,7 @@ void dsp56156_device::execute_run()
/* If reset line is asserted, do nothing */
if (m_core.reset_state)
{
debugger_wait_hook();
m_core.icount = 0;
return;
}
@ -472,6 +473,7 @@ void dsp56156_device::execute_run()
/* HACK - if you're in bootstrap mode, simply pretend you ate up all your cycles waiting for data. */
if (m_core.bootstrap_mode != BOOTSTRAP_OFF)
{
debugger_wait_hook();
m_core.icount = 0;
return;
}

View File

@ -199,6 +199,7 @@ void e0c6200_cpu_device::execute_run()
// core cpu not running (peripherals still work)
if (m_halt || m_sleep)
{
debugger_wait_hook();
m_icount = 0;
break;
}

View File

@ -1940,7 +1940,9 @@ TABLE_FUNCTION(int, execute, (int clocks))
// do a check here also in case we're in STOP_WAI mode - this'll clear it when the IRQ happens
g65816i_check_maskable_interrupt();
if (!CPU_STOPPED)
if (CPU_STOPPED)
debugger_wait_hook();
else
{
CLOCKS = clocks;
do

View File

@ -296,6 +296,7 @@ bool hd61700_cpu_device::check_irqs()
{
if (BIT(REG_IB, i) && !BIT(m_irq_status, i))
{
standard_irq_callback(i, m_pc);
m_irq_status |= (1 << i);
push(REG_SS, (uint8_t)(m_pc >> 8));
push(REG_SS, (uint8_t)m_pc);
@ -319,19 +320,19 @@ void hd61700_cpu_device::execute_run()
{
do
{
m_ppc = m_curpc;
debugger_instruction_hook(m_curpc);
// verify that CPU is not in sleep
if (m_state & CPU_SLP)
{
debugger_wait_hook();
m_icount -= 6;
}
else
{
check_irqs();
m_ppc = m_curpc;
debugger_instruction_hook(m_curpc);
// instruction fetch
uint8_t op = read_op();

View File

@ -655,6 +655,7 @@ void hmcs40_cpu_device::execute_run()
// in HLT state, the internal clock is not running
if (m_halt)
{
debugger_wait_hook();
m_icount = 0;
return;
}

View File

@ -877,6 +877,7 @@ void hmcs400_cpu_device::execute_run()
// in stop mode, the internal clock is not running
if (m_stop)
{
debugger_wait_hook();
m_icount = 0;
return;
}

View File

@ -1093,6 +1093,7 @@ void ht1130_device::execute_run()
{
if (m_inhalt)
{
debugger_wait_hook();
m_icount = 0;
return;
}

View File

@ -2778,6 +2778,7 @@ void i386_device::execute_run()
if (m_halted)
{
debugger_wait_hook();
m_tsc += cycles;
m_cycles = 0;
return;

View File

@ -242,6 +242,7 @@ void i80186_cpu_device::execute_run()
if (m_halt)
{
debugger_wait_hook();
m_icount = 0;
return;
}

View File

@ -1078,6 +1078,7 @@ void i80286_cpu_device::execute_run()
if(m_halt || m_shutdown)
{
debugger_wait_hook();
m_icount = 0;
return;
}

View File

@ -211,6 +211,7 @@ void i8086_cpu_device::execute_run()
if(m_halt)
{
debugger_wait_hook();
m_icount = 0;
return;
}

View File

@ -486,6 +486,7 @@ void jaguargpu_cpu_device::execute_run()
if (m_go == false)
{
//device->execute().set_input_line(INPUT_LINE_HALT, ASSERT_LINE);
debugger_wait_hook();
m_icount = 0;
return;
}
@ -521,6 +522,7 @@ void jaguardsp_cpu_device::execute_run()
if (m_go == false)
{
//device->execute().set_input_line(INPUT_LINE_HALT, ASSERT_LINE);
debugger_wait_hook();
m_icount = 0;
return;
}

View File

@ -420,18 +420,20 @@ void lc8670_cpu_device::execute_run()
{
check_irqs();
m_ppc = m_pc;
debugger_instruction_hook(m_pc);
int cycles;
if (REG_PCON & HALT_MODE)
{
debugger_wait_hook();
// in HALT state the timers are still updated
cycles = 1;
}
else
{
m_ppc = m_pc;
debugger_instruction_hook(m_pc);
// instruction fetch
m_op = fetch();
int op_idx = decode_op(m_op);

View File

@ -216,7 +216,10 @@ void lh5801_cpu_device::execute_run()
check_irq();
if (m_idle)
{
debugger_wait_hook();
m_icount = 0;
}
else
{
m_oldpc = P;

View File

@ -357,12 +357,13 @@ void lr35902_cpu_device::execute_run()
/* Fetch and count cycles */
bool was_halted = (m_enable & HALTED);
check_interrupts();
debugger_instruction_hook(m_PC);
if ( m_enable & HALTED ) {
debugger_wait_hook();
cycles_passed(m_has_halt_bug ? 2 : 4);
m_execution_state = 1;
m_entering_halt = false;
} else {
debugger_instruction_hook(m_PC);
if (was_halted) {
m_PC++;
} else {

View File

@ -2534,7 +2534,8 @@ TABLE_FUNCTION(void, set_reg, (int regnum, uint32_t val))
TABLE_FUNCTION(int, execute, (int clocks))
{
if(!CPU_STOPPED)
if(CPU_STOPPED)
debugger_wait_hook();
{
CLOCKS = clocks;
do

View File

@ -85,6 +85,7 @@ def save_opcodes(f, device, opcodes):
for ins in instructions:
line_type = identify_line_type(ins)
if line_type == "EAT":
emit(f, "\tdebugger_wait_hook();")
emit(f, "\ticount = 0;")
emit(f, "\tinst_substate = %d;" % substate)
emit(f, "\treturn;")
@ -114,6 +115,7 @@ def save_opcodes(f, device, opcodes):
for ins in instructions:
line_type = identify_line_type(ins)
if line_type == "EAT":
emit(f, "\tdebugger_wait_hook();")
emit(f, "\ticount = 0;")
emit(f, "\tinst_substate = %d;" % substate)
emit(f, "\treturn;")

View File

@ -612,6 +612,7 @@ void m6800_cpu_device::execute_run()
{
if (m_wai_state & (M6800_WAI | M6800_SLP))
{
debugger_wait_hook();
eat_cycles();
}
else

View File

@ -94497,6 +94497,7 @@ void m68000_device::stop_i16u_df() // 4e72 ffff
m_au = m_au - 2;
m_icount -= 2;
m_inst_state = m_next_state ? m_next_state : m_decode_table[m_ird];
debugger_wait_hook();
return;
}

View File

@ -107590,6 +107590,7 @@ void m68000_device::stop_i16u_dp() // 4e72 ffff
m_icount -= 2;
m_inst_state = m_next_state ? m_next_state : m_decode_table[m_ird];
m_inst_substate = 0;
debugger_wait_hook();
return;
}
}

View File

@ -94497,6 +94497,7 @@ void m68000_device::stop_i16u_if() // 4e72 ffff
m_au = m_au - 2;
m_icount -= 2;
m_inst_state = m_next_state ? m_next_state : m_decode_table[m_ird];
debugger_wait_hook();
return;
}

View File

@ -107590,6 +107590,7 @@ void m68000_device::stop_i16u_ip() // 4e72 ffff
m_icount -= 2;
m_inst_state = m_next_state ? m_next_state : m_decode_table[m_ird];
m_inst_substate = 0;
debugger_wait_hook();
return;
}
}

View File

@ -1,4 +1,4 @@
#!/bin/python
#!/bin/python3
# m68000 emulation code generator
@ -1893,7 +1893,7 @@ def generate_code_from_blocks(blocks, ir, irmask, tvn, priv, group01):
if len(b[3]) == 0:
if cb[-1][0] != "set_trace":
# stop #nnnn case, which loops on itself transparently
cb.append(["next"])
cb.append(["next_stop"])
else:
cb[-1][0] = "next_trace"
elif b[3][0] == ib:
@ -2285,10 +2285,12 @@ def generate_source_from_code(code, gen_mode):
source.append("\tsr_%s();" % aflags)
elif ci[0] == "=t":
source.append("\tm_t = %s;" % ci[1])
elif ci[0] == "next" or ci[0] == "next_trace":
elif ci[0] == "next_stop" or ci[0] == "next_trace":
source.append("\tm_inst_state = m_next_state ? m_next_state : m_decode_table[m_ird];")
if not (gen_mode & GEN.full):
source.append("\tm_inst_substate = 0;")
if ci[0] == "next_stop":
source.append("\tdebugger_wait_hook();")
if ci[0] == "next_trace":
source.append("\tif(m_sr & SR_T)")
source.append("\t\tm_next_state = S_TRACE;")

View File

@ -94497,6 +94497,7 @@ void m68000_mcu_device::stop_i16u_dfm() // 4e72 ffff
m_au = m_au - 2;
m_icount -= 2;
m_inst_state = m_next_state ? m_next_state : m_decode_table[m_ird];
debugger_wait_hook();
return;
}

View File

@ -107590,6 +107590,7 @@ void m68000_mcu_device::stop_i16u_dpm() // 4e72 ffff
m_icount -= 2;
m_inst_state = m_next_state ? m_next_state : m_decode_table[m_ird];
m_inst_substate = 0;
debugger_wait_hook();
return;
}
}

View File

@ -94497,6 +94497,7 @@ void m68000_mcu_device::stop_i16u_ifm() // 4e72 ffff
m_au = m_au - 2;
m_icount -= 2;
m_inst_state = m_next_state ? m_next_state : m_decode_table[m_ird];
debugger_wait_hook();
return;
}

View File

@ -107590,6 +107590,7 @@ void m68000_mcu_device::stop_i16u_ipm() // 4e72 ffff
m_icount -= 2;
m_inst_state = m_next_state ? m_next_state : m_decode_table[m_ird];
m_inst_substate = 0;
debugger_wait_hook();
return;
}
}

View File

@ -124544,6 +124544,7 @@ void m68008_device::stop_i16u_df8() // 4e72 ffff
m_au = m_au - 2;
m_icount -= 2;
m_inst_state = m_next_state ? m_next_state : m_decode_table[m_ird];
debugger_wait_hook();
return;
}

View File

@ -143738,6 +143738,7 @@ void m68008_device::stop_i16u_dp8() // 4e72 ffff
m_icount -= 2;
m_inst_state = m_next_state ? m_next_state : m_decode_table[m_ird];
m_inst_substate = 0;
debugger_wait_hook();
return;
}
}

View File

@ -124544,6 +124544,7 @@ void m68008_device::stop_i16u_if8() // 4e72 ffff
m_au = m_au - 2;
m_icount -= 2;
m_inst_state = m_next_state ? m_next_state : m_decode_table[m_ird];
debugger_wait_hook();
return;
}

View File

@ -143738,6 +143738,7 @@ void m68008_device::stop_i16u_ip8() // 4e72 ffff
m_icount -= 2;
m_inst_state = m_next_state ? m_next_state : m_decode_table[m_ird];
m_inst_substate = 0;
debugger_wait_hook();
return;
}
}

View File

@ -880,6 +880,7 @@ void m68000_musashi_device::execute_run()
}
if(m_stopped)
{
debugger_wait_hook();
if (m_icount > 0)
m_icount = 0;
return;

View File

@ -445,14 +445,8 @@ SYNC:
m_syncack_write_func(1);
while(!m_nmi_asserted && !m_firq_line && !m_irq_line)
{
// massaging the PC this way makes the debugger's behavior more
// intuitive
m_pc.w--;
@eat_remaining();
// unmassage...
m_pc.w++;
;
}
m_syncack_write_func(0);
@eat(1);
@ -595,14 +589,8 @@ CWAI:
while((m_ea.w = get_pending_interrupt()) == 0)
{
// massaging the PC this way makes the debugger's behavior more
// intuitive
m_pc.w -= 2;
@eat_remaining();
// unmassage...
m_pc.w += 2;
;
}
if (m_nmi_asserted)

View File

@ -13,7 +13,6 @@ MAIN:
m_ppc = m_pc;
debugger_instruction_hook(m_pc.w);
DISPATCH01:
// opcode fetch
m_lic_func(ASSERT_LINE);
@m_opcode = read_opcode();
@ -21,6 +20,7 @@ DISPATCH01:
if (m_free_run) goto FREERUN;
DISPATCH01:
// dispatch opcode
switch(m_opcode)
{

View File

@ -243,14 +243,8 @@ inline T m6809_base_device::set_flags(uint8_t mask, T r)
inline void m6809_base_device::eat_remaining()
{
// we do this in order to be nice to people debugging
uint16_t real_pc = m_pc.w;
debugger_wait_hook();
eat(m_icount);
m_pc.w = m_ppc.w;
debugger_instruction_hook(m_pc.w);
m_pc.w = real_pc;
}

View File

@ -4180,28 +4180,14 @@ void HC11OP(tys)()
/* WAI 0x3E */
void HC11OP(wai)()
{
if(m_wait_state == 0)
{
/* TODO: the following is bogus, pushes regs HERE in an instruction that wants an irq to go out? */
PUSH16(m_pc);
PUSH16(m_iy);
PUSH16(m_ix);
PUSH8(REG_A);
PUSH8(REG_B);
PUSH8(m_ccr);
CYCLES(14);
m_wait_state = 1;
}
if(m_wait_state == 1)
{
SET_PC(m_ppc); // wait for an exception
CYCLES(1);
}
if(m_wait_state == 2)
{
m_wait_state = 0;
CYCLES(1);
}
PUSH16(m_pc);
PUSH16(m_iy);
PUSH16(m_ix);
PUSH8(REG_A);
PUSH8(REG_B);
PUSH8(m_ccr);
CYCLES(14);
m_wait_state = 1;
}
/* XGDX 0x8F */

View File

@ -1222,10 +1222,18 @@ void mc68hc11_cpu_device::execute_run()
check_irq_lines();
m_ppc = m_pc;
debugger_instruction_hook(m_pc);
if (m_wait_state != 0)
{
debugger_wait_hook();
m_icount = 0;
}
else
{
m_ppc = m_pc;
debugger_instruction_hook(m_pc);
op = FETCH();
(this->*hc11_optable[op])();
op = FETCH();
(this->*hc11_optable[op])();
}
}
}

View File

@ -2160,6 +2160,7 @@ void mcs51_cpu_device::execute_run()
/* if in powerdown, just return */
if ((m_features & FEATURE_CMOS) && GET_PD)
{
debugger_wait_hook();
m_icount = 0;
return;
}

View File

@ -212,6 +212,7 @@ void minx_cpu_device::execute_run()
if ( m_halted )
{
debugger_wait_hook();
m_icount -= insnminx_cycles_CE[0xAE];
}
else

View File

@ -631,8 +631,8 @@ void nec_common_device::execute_run()
if (m_halted)
{
debugger_wait_hook();
m_icount = 0;
debugger_instruction_hook((Sreg(PS)<<4) + m_ip);
return;
}

View File

@ -784,8 +784,8 @@ void v25_common_device::execute_run()
if (m_halted)
{
debugger_wait_hook();
m_icount = 0;
debugger_instruction_hook((Sreg(PS)<<4) + m_ip);
return;
}

View File

@ -999,6 +999,7 @@ template <int HighBits, int Width> void ns32000_device<HighBits, Width>::execute
{
if (m_wait)
{
debugger_wait_hook();
m_icount = 0;
continue;
}

View File

@ -155,9 +155,9 @@ void patinho_feio_cpu_device::execute_run() {
m_ext = READ_ACC_EXTENSION_REG();
m_idx = READ_INDEX_REG();
m_update_panel_cb(ACC, READ_BYTE_PATINHO(PC), READ_BYTE_PATINHO(m_addr), m_addr, PC, FLAGS, RC, m_mode);
debugger_instruction_hook(PC);
if (!m_run){
debugger_wait_hook();
if (!m_buttons_read_cb.isunset()){
uint16_t buttons = m_buttons_read_cb(0);
if (buttons & BUTTON_PARTIDA){
@ -180,6 +180,7 @@ void patinho_feio_cpu_device::execute_run() {
}
m_icount = 0; /* if processor is stopped, just burn cycles */
} else {
debugger_instruction_hook(PC);
execute_instruction();
m_icount --;
}

View File

@ -775,7 +775,7 @@ void pdp1_device::execute_run()
if ((! m_run) && (! m_rim))
{
debugger_instruction_hook(PC);
debugger_wait_hook();
m_icount = 0; /* if processor is stopped, just burn cycles */
}
else if (m_rim)

View File

@ -899,6 +899,7 @@ void pic17_cpu_device::execute_run()
else
{
// Do nothing until time to wake up
debugger_wait_hook();
m_icount = 0;
m_execphase = exec_phase::Q1;
return;

View File

@ -2110,6 +2110,7 @@ void riscii_series_device::execute_run()
break;
case EXEC_IDLE:
debugger_wait_hook();
m_icount = 0;
return;
}

View File

@ -122,6 +122,7 @@ void romp_device::execute_run()
if (m_branch_state == WAIT)
{
debugger_wait_hook();
m_icount = 0;
return;
}

View File

@ -2840,6 +2840,7 @@ void rsp_device::execute_run()
{
if (m_sr & (RSP_STATUS_HALT | RSP_STATUS_BROKE))
{
debugger_wait_hook();
m_ideduct = 0;
m_scalar_busy = false;
m_vector_busy = false;

View File

@ -337,17 +337,19 @@ void saturn_device::execute_run()
{
do
{
m_oldpc = m_pc;
debugger_instruction_hook(m_pc);
if ( m_sleeping )
{
debugger_wait_hook();
/* advance time when sleeping */
m_icount -= 100;
}
else
{
m_oldpc = m_pc;
debugger_instruction_hook(m_pc);
/* takes irq */
if ( m_pending_irq && (!m_in_irq) )
saturn_take_irq();

View File

@ -287,6 +287,7 @@ void sh2_device::execute_run()
if (m_cpu_off)
{
debugger_wait_hook();
m_sh2_state->icount = 0;
return;
}

View File

@ -1960,6 +1960,7 @@ void sh34_base_device::execute_run()
if (m_sh2_state->m_cpu_off)
{
debugger_wait_hook();
m_sh2_state->icount = 0;
return;
}
@ -2003,6 +2004,7 @@ void sh3be_device::execute_run()
if (m_sh2_state->m_cpu_off)
{
debugger_wait_hook();
m_sh2_state->icount = 0;
return;
}
@ -2043,6 +2045,7 @@ void sh4be_device::execute_run()
if (m_sh2_state->m_cpu_off)
{
debugger_wait_hook();
m_sh2_state->icount = 0;
return;
}

View File

@ -1038,6 +1038,8 @@ void adsp21062_device::execute_run()
if (m_core->idle && m_core->irq_pending == 0)
{
debugger_wait_hook();
int dma_count = m_core->icount;
// run active DMAs even while idling
@ -1052,7 +1054,6 @@ void adsp21062_device::execute_run()
}
m_core->icount = 0;
debugger_instruction_hook(m_core->daddr);
}
if (m_core->irq_pending != 0)
{

View File

@ -291,6 +291,7 @@ void sm510_base_device::execute_run()
else
{
// got nothing to do
debugger_wait_hook();
m_icount = 0;
return;
}

View File

@ -361,10 +361,10 @@ void sm8500_cpu_device::execute_run()
uint32_t d1,d2;
uint32_t res;
debugger_instruction_hook(m_PC);
m_oldpc = m_PC;
process_interrupts();
if ( !m_halted ) {
m_oldpc = m_PC;
debugger_instruction_hook(m_PC);
uint8_t op = mem_readbyte( m_PC++ );
m_SYS = m_program->read_byte(0x19);
m_PS0 = m_program->read_byte(0x1e);
@ -379,6 +379,7 @@ void sm8500_cpu_device::execute_run()
mem_writebyte(0x1e,m_PS0); // need to update debugger
m_program->write_byte(0x1f,m_PS1);
} else {
debugger_wait_hook();
mycycles = 4;
m_dma_func( mycycles );
}

View File

@ -4471,19 +4471,22 @@ void sparc_base_device::run_loop()
continue;
}*/
if (CHECK_DEBUG)
debugger_instruction_hook(PC);
if (MODE == MODE_RESET)
{
if (CHECK_DEBUG)
debugger_wait_hook();
reset_step();
}
else if (MODE == MODE_ERROR)
{
if (CHECK_DEBUG)
debugger_wait_hook();
error_step();
}
else if (MODE == MODE_EXECUTE)
{
if (CHECK_DEBUG)
debugger_instruction_hook(PC);
execute_step();
}

View File

@ -1349,6 +1349,7 @@ void spc700_device::execute_run()
{
if (CPU_STOPPED)
{
debugger_wait_hook();
CLOCKS = 0;
return;
}

View File

@ -790,6 +790,7 @@ void superfx_device::execute_run()
{
if(!(m_sfr & SUPERFX_SFR_G))
{
debugger_wait_hook();
superfx_add_clocks_internal(6);
m_icount = std::min(m_icount, 0);
break;

View File

@ -640,6 +640,7 @@ void t11_device::execute_run()
if (m_wait_state)
{
debugger_wait_hook();
m_icount = 0;
return;
}

View File

@ -1458,7 +1458,10 @@ void tlcs90_device::execute_run()
// when in HALT state, the fetched opcode is not dispatched (aka a NOP) and the PC is not increased
if (m_halt)
{
debugger_wait_hook();
m_op = NOP;
}
else
{
m_prvpc.d = m_pc.d;

View File

@ -277,14 +277,15 @@ void tlcs900_device::execute_run()
m_check_irqs = 0;
}
debugger_instruction_hook( m_pc.d );
if ( m_halted )
{
debugger_wait_hook();
m_cycles += 8;
}
else
{
debugger_instruction_hook( m_pc.d );
m_op = RDOP();
inst = &m_mnemonic[m_op];
prepare_operands( inst );

View File

@ -2000,11 +2000,11 @@ void tms3202x_device::execute_run()
if (m_idle && m_IFR && m_icount > 0)
m_icount -= process_IRQs();
while (m_idle && m_icount > 0)
process_timer(m_icount);
if (m_icount <= 0) debugger_instruction_hook(m_PC);
if (m_idle) {
debugger_wait_hook();
while (m_idle && m_icount > 0)
process_timer(m_icount);
}
while (m_icount > 0)
{

View File

@ -817,6 +817,7 @@ void tms3203x_device::check_irqs()
if (!m_delayed)
{
uint16_t intmask = 1 << (whichtrap - 1);
standard_irq_callback(whichtrap - 1, m_pc);
// bit in IF is cleared when interrupt is taken
IREG(TMR_IF) &= ~intmask;
@ -954,6 +955,7 @@ void tms3203x_device::execute_run()
// if we're idling, just eat the cycles
if (m_is_idling)
{
debugger_wait_hook();
m_icount = 0;
return;
}

View File

@ -863,6 +863,7 @@ void tms340x0_device::execute_run()
/* Get out if CPU is halted. Absolutely no interrupts must be taken!!! */
if (IOREG(REG_HSTCTLH) & 0x8000)
{
debugger_wait_hook();
m_icount = 0;
return;
}

View File

@ -262,7 +262,7 @@ void tx0_64kw_device::execute_run()
if ((! m_run) && (! m_rim))
{
debugger_instruction_hook(PC);
debugger_wait_hook();
m_icount = 0; /* if processor is stopped, just burn cycles */
}
else if (m_rim)
@ -368,7 +368,7 @@ void tx0_8kw_device::execute_run()
if ((! m_run) && (! m_rim))
{
debugger_instruction_hook(PC);
debugger_wait_hook();
m_icount = 0; /* if processor is stopped, just burn cycles */
}
else if (m_rim)

View File

@ -1918,7 +1918,7 @@ again:
if ((m_dstat & Z180_DSTAT_DE0) == Z180_DSTAT_DE0 &&
(m_dmode & Z180_DMODE_MMOD) == Z180_DMODE_MMOD)
{
debugger_instruction_hook(_PCD);
debugger_wait_hook();
/* FIXME z180_dma0 should be handled in handle_io_timers */
curcycles = z180_dma0(m_icount);
@ -1934,18 +1934,21 @@ again:
handle_io_timers(curcycles);
m_after_EI = 0;
_PPC = _PCD;
debugger_instruction_hook(_PCD);
if (!m_HALT)
{
_PPC = _PCD;
debugger_instruction_hook(_PCD);
m_R++;
m_extra_cycles = 0;
curcycles = exec_op(ROP());
curcycles += m_extra_cycles;
}
else
{
debugger_wait_hook();
curcycles = 3;
}
m_icount -= curcycles;
@ -1992,18 +1995,21 @@ again:
handle_io_timers(curcycles);
m_after_EI = 0;
_PPC = _PCD;
debugger_instruction_hook(_PCD);
if (!m_HALT)
{
_PPC = _PCD;
debugger_instruction_hook(_PCD);
m_R++;
m_extra_cycles = 0;
curcycles = exec_op(ROP());
curcycles += m_extra_cycles;
}
else
{
debugger_wait_hook();
curcycles = 3;
}
m_icount -= curcycles;
handle_io_timers(curcycles);

View File

@ -684,14 +684,16 @@ ffff
call check_interrupts
m_after_ei = false;
m_after_ldair = false;
PRVPC = PC;
debugger_instruction_hook(PC);
call rop
if (m_halt) {
debugger_wait_hook();
call rop
PC--;
m_ref = 0xffff00;
return;
} else {
PRVPC = PC;
debugger_instruction_hook(PC);
call rop
m_ref = (0x00 << 16) | (TDAT8 << 8);
return;
}

View File

@ -637,6 +637,7 @@ void z8002_device::execute_run()
if (m_halt)
{
debugger_wait_hook();
m_icount = 0;
}
else

View File

@ -409,6 +409,70 @@ void debugger_cpu::halt_on_next_instruction(device_t *device, util::format_argum
}
}
//-------------------------------------------------
// wait_for_debugger - pause during execution to
// allow debugging
//-------------------------------------------------
void debugger_cpu::wait_for_debugger(device_t &device)
{
assert(is_stopped());
assert(within_instruction_hook());
bool firststop = true;
// load comments if we haven't yet
ensure_comments_loaded();
// reset any transient state
reset_transient_flags();
set_break_cpu(nullptr);
// remember the last visible CPU in the debugger
m_machine.debugger().console().set_visible_cpu(&device);
// update all views
m_machine.debug_view().update_all();
m_machine.debugger().refresh_display();
// wait for the debugger; during this time, disable sound output
m_machine.sound().debugger_mute(true);
while (is_stopped())
{
// flush any pending updates before waiting again
m_machine.debug_view().flush_osd_updates();
emulator_info::periodic_check();
// clear the memory modified flag and wait
set_memory_modified(false);
if (m_machine.debug_flags & DEBUG_FLAG_OSD_ENABLED)
m_machine.osd().wait_for_debugger(device, firststop);
firststop = false;
// if something modified memory, update the screen
if (memory_modified())
{
m_machine.debug_view().update_all(DVT_DISASSEMBLY);
m_machine.debug_view().update_all(DVT_STATE);
m_machine.debugger().refresh_display();
}
// check for commands in the source file
m_machine.debugger().console().process_source_file();
// if an event got scheduled, resume
if (m_machine.scheduled_event_pending())
set_execution_running();
}
m_machine.sound().debugger_mute(false);
// remember the last visible CPU in the debugger
m_machine.debugger().console().set_visible_cpu(&device);
}
//**************************************************************************
// DEVICE DEBUG
//**************************************************************************
@ -435,6 +499,7 @@ device_debug::device_debug(device_t &device)
, m_endexectime(attotime::zero)
, m_total_cycles(0)
, m_last_total_cycles(0)
, m_was_waiting(true)
, m_pc_history_index(0)
, m_pc_history_valid(0)
, m_bplist()
@ -638,6 +703,13 @@ void device_debug::stop_hook()
void device_debug::interrupt_hook(int irqline, offs_t pc)
{
// CPU is presumably no longer waiting if it acknowledges an interrupt
if (m_was_waiting)
{
m_was_waiting = false;
compute_debug_flags();
}
// see if this matches a pending interrupt request
if ((m_flags & DEBUG_FLAG_STOP_INTERRUPT) != 0 && (m_stopirq == -1 || m_stopirq == irqline))
{
@ -772,6 +844,7 @@ void device_debug::privilege_hook()
}
}
//-------------------------------------------------
// instruction_hook - called by the CPU cores
// before executing each instruction
@ -780,7 +853,7 @@ void device_debug::privilege_hook()
void device_debug::instruction_hook(offs_t curpc)
{
running_machine &machine = m_device.machine();
debugger_cpu& debugcpu = machine.debugger().cpu();
debugger_cpu &debugcpu = machine.debugger().cpu();
// note that we are in the debugger code
debugcpu.set_within_instruction(true);
@ -794,6 +867,11 @@ void device_debug::instruction_hook(offs_t curpc)
// update total cycles
m_last_total_cycles = m_total_cycles;
m_total_cycles = m_exec->total_cycles();
if (m_was_waiting)
{
m_was_waiting = false;
compute_debug_flags();
}
// are we tracking our recent pc visits?
if (m_track_pc)
@ -865,7 +943,7 @@ void device_debug::instruction_hook(offs_t curpc)
}
// handle breakpoints
if (!debugcpu.is_stopped() && (m_flags & (DEBUG_FLAG_STOP_TIME | DEBUG_FLAG_STOP_PC | DEBUG_FLAG_LIVE_BP)) != 0)
if (!debugcpu.is_stopped() && (m_flags & (DEBUG_FLAG_STOP_TIME | DEBUG_FLAG_STOP_PC | DEBUG_FLAG_LIVE_BP | DEBUG_FLAG_LIVE_RP)) != 0)
{
// see if we hit a target time
if ((m_flags & DEBUG_FLAG_STOP_TIME) != 0 && machine.time() >= m_stoptime)
@ -885,69 +963,69 @@ void device_debug::instruction_hook(offs_t curpc)
}
// check for execution breakpoints
else if ((m_flags & DEBUG_FLAG_LIVE_BP) != 0)
breakpoint_check(curpc);
else
{
if ((m_flags & DEBUG_FLAG_LIVE_BP) != 0)
breakpoint_check(curpc);
if ((m_flags & DEBUG_FLAG_LIVE_RP) != 0)
registerpoint_check();
}
}
// if we are supposed to halt, do it now
if (debugcpu.is_stopped())
debugcpu.wait_for_debugger(m_device);
// handle step out/over on the instruction we are about to execute
if ((m_flags & (DEBUG_FLAG_STEPPING_OVER | DEBUG_FLAG_STEPPING_OUT | DEBUG_FLAG_STEPPING_BRANCH)) != 0 && (m_flags & (DEBUG_FLAG_CALL_IN_PROGRESS | DEBUG_FLAG_TEST_IN_PROGRESS)) == 0)
prepare_for_step_overout(m_state->pcbase());
// no longer in debugger code
debugcpu.set_within_instruction(false);
}
//-------------------------------------------------
// wait_hook - called by the CPU cores while
// waiting indefinitely for some kind of event
//-------------------------------------------------
void device_debug::wait_hook()
{
running_machine &machine = m_device.machine();
debugger_cpu &debugcpu = machine.debugger().cpu();
// note that we are in the debugger code
debugcpu.set_within_instruction(true);
// update total cycles
m_last_total_cycles = m_total_cycles;
m_total_cycles = m_exec->total_cycles();
// handle registerpoints (but not breakpoints)
if (!debugcpu.is_stopped() && (m_flags & (DEBUG_FLAG_STOP_TIME | DEBUG_FLAG_LIVE_RP)) != 0)
{
// see if we hit a target time
if ((m_flags & DEBUG_FLAG_STOP_TIME) != 0 && machine.time() >= m_stoptime)
{
machine.debugger().console().printf("Stopped at time interval %.1g\n", machine.time().as_double());
debugcpu.set_execution_stopped();
}
else if ((m_flags & DEBUG_FLAG_LIVE_RP) != 0)
registerpoint_check();
}
// if we are supposed to halt, do it now
if (debugcpu.is_stopped())
{
bool firststop = true;
// load comments if we haven't yet
debugcpu.ensure_comments_loaded();
// reset any transient state
debugcpu.reset_transient_flags();
debugcpu.set_break_cpu(nullptr);
// remember the last visible CPU in the debugger
machine.debugger().console().set_visible_cpu(&m_device);
// update all views
machine.debug_view().update_all();
machine.debugger().refresh_display();
// wait for the debugger; during this time, disable sound output
m_device.machine().sound().debugger_mute(true);
while (debugcpu.is_stopped())
if (!m_was_waiting)
{
// flush any pending updates before waiting again
machine.debug_view().flush_osd_updates();
emulator_info::periodic_check();
// clear the memory modified flag and wait
debugcpu.set_memory_modified(false);
if (machine.debug_flags & DEBUG_FLAG_OSD_ENABLED)
machine.osd().wait_for_debugger(m_device, firststop);
firststop = false;
// if something modified memory, update the screen
if (debugcpu.memory_modified())
{
machine.debug_view().update_all(DVT_DISASSEMBLY);
machine.debug_view().update_all(DVT_STATE);
machine.debugger().refresh_display();
}
// check for commands in the source file
machine.debugger().console().process_source_file();
// if an event got scheduled, resume
if (machine.scheduled_event_pending())
debugcpu.set_execution_running();
machine.debugger().console().printf("CPU waiting after PC=%s\n", m_state->state_string(STATE_GENPCBASE));
m_was_waiting = true;
}
machine.sound().debugger_mute(false);
// remember the last visible CPU in the debugger
machine.debugger().console().set_visible_cpu(&m_device);
debugcpu.wait_for_debugger(m_device);
}
// handle step out/over on the instruction we are about to execute
if ((m_flags & (DEBUG_FLAG_STEPPING_OVER | DEBUG_FLAG_STEPPING_OUT | DEBUG_FLAG_STEPPING_BRANCH)) != 0 && (m_flags & (DEBUG_FLAG_CALL_IN_PROGRESS | DEBUG_FLAG_TEST_IN_PROGRESS)) == 0)
prepare_for_step_overout(m_state->pcbase());
// no longer in debugger code
debugcpu.set_within_instruction(false);
}
@ -1753,7 +1831,7 @@ void device_debug::trace(std::unique_ptr<std::ostream> &&file, bool trace_over,
void device_debug::compute_debug_flags()
{
running_machine &machine = m_device.machine();
debugger_cpu& debugcpu = machine.debugger().cpu();
debugger_cpu &debugcpu = machine.debugger().cpu();
// clear out global flags by default, keep DEBUG_FLAG_OSD_ENABLED
machine.debug_flags &= DEBUG_FLAG_OSD_ENABLED;
@ -1769,7 +1847,7 @@ void device_debug::compute_debug_flags()
// if we're tracking history, or we're hooked, or stepping, or stopping at a breakpoint
// make sure we call the hook
if ((m_flags & (DEBUG_FLAG_HISTORY | DEBUG_FLAG_STEPPING_ANY | DEBUG_FLAG_STOP_PC | DEBUG_FLAG_LIVE_BP)) != 0)
if ((m_flags & (DEBUG_FLAG_HISTORY | DEBUG_FLAG_STEPPING_ANY | DEBUG_FLAG_STOP_PC | DEBUG_FLAG_LIVE_BP | DEBUG_FLAG_LIVE_RP)) != 0)
machine.debug_flags |= DEBUG_FLAG_CALL_HOOK;
// also call if we are tracing
@ -1779,6 +1857,10 @@ void device_debug::compute_debug_flags()
// if we are stopping at a particular time and that time is within the current timeslice, we need to be called
if ((m_flags & DEBUG_FLAG_STOP_TIME) && m_endexectime <= m_stoptime)
machine.debug_flags |= DEBUG_FLAG_CALL_HOOK;
// if we were waiting, call if only to clear
if (m_was_waiting)
machine.debug_flags |= DEBUG_FLAG_CALL_HOOK;
}
@ -1859,7 +1941,7 @@ void device_debug::prepare_for_step_overout(offs_t pc)
void device_debug::breakpoint_update_flags()
{
// see if there are any enabled breakpoints
m_flags &= ~DEBUG_FLAG_LIVE_BP;
m_flags &= ~(DEBUG_FLAG_LIVE_BP | DEBUG_FLAG_LIVE_RP);
for (auto &bpp : m_bplist)
if (bpp.second->m_enabled)
{
@ -1867,16 +1949,13 @@ void device_debug::breakpoint_update_flags()
break;
}
if (!(m_flags & DEBUG_FLAG_LIVE_BP))
// see if there are any enabled registerpoints
for (debug_registerpoint &rp : m_rplist)
{
// see if there are any enabled registerpoints
for (debug_registerpoint &rp : m_rplist)
if (rp.m_enabled)
{
if (rp.m_enabled)
{
m_flags |= DEBUG_FLAG_LIVE_BP;
break;
}
m_flags |= DEBUG_FLAG_LIVE_RP;
break;
}
}
@ -1893,8 +1972,6 @@ void device_debug::breakpoint_update_flags()
void device_debug::breakpoint_check(offs_t pc)
{
debugger_cpu& debugcpu = m_device.machine().debugger().cpu();
// see if we match
auto bpitp = m_bplist.equal_range(pc);
for (auto bpit = bpitp.first; bpit != bpitp.second; ++bpit)
@ -1902,6 +1979,8 @@ void device_debug::breakpoint_check(offs_t pc)
debug_breakpoint &bp = *bpit->second;
if (bp.hit(pc))
{
debugger_cpu &debugcpu = m_device.machine().debugger().cpu();
// halt in the debugger by default
debugcpu.set_execution_stopped();
@ -1918,12 +1997,23 @@ void device_debug::breakpoint_check(offs_t pc)
break;
}
}
}
//-------------------------------------------------
// registerpoint_check - check the registerpoints
// for a given device
//-------------------------------------------------
void device_debug::registerpoint_check()
{
// see if we have any matching registerpoints
for (debug_registerpoint &rp : m_rplist)
{
if (rp.hit())
{
debugger_cpu &debugcpu = m_device.machine().debugger().cpu();
// halt in the debugger by default
debugcpu.set_execution_stopped();

View File

@ -55,6 +55,7 @@ public:
void exception_hook(int exception);
void privilege_hook();
void instruction_hook(offs_t curpc);
void wait_hook();
// debugger focus
void ignore(bool ignore = true);
@ -174,6 +175,7 @@ private:
// breakpoint and watchpoint helpers
void breakpoint_update_flags();
void breakpoint_check(offs_t pc);
void registerpoint_check();
void reinstall_all(read_or_write mode);
void reinstall(address_space &space, read_or_write mode);
void write_tracking(address_space &space, offs_t address, u64 data);
@ -204,6 +206,7 @@ private:
attotime m_endexectime; // ending time of the current execution
u64 m_total_cycles; // current total cycles
u64 m_last_total_cycles; // last total cycles
bool m_was_waiting; // true if no instruction executed since last wait
// history
offs_t m_pc_history[HISTORY_SIZE]; // history of recent PCs
@ -328,7 +331,8 @@ private:
static constexpr u32 DEBUG_FLAG_STOP_VBLANK = 0x00001000; // there is a pending stop on the next VBLANK
static constexpr u32 DEBUG_FLAG_STOP_TIME = 0x00002000; // there is a pending stop at cpu->stoptime
static constexpr u32 DEBUG_FLAG_SUSPENDED = 0x00004000; // CPU currently suspended
static constexpr u32 DEBUG_FLAG_LIVE_BP = 0x00010000; // there are live breakpoints for this CPU
static constexpr u32 DEBUG_FLAG_LIVE_BP = 0x00008000; // there are live breakpoints for this CPU
static constexpr u32 DEBUG_FLAG_LIVE_RP = 0x00010000; // there are live registerpoints for this CPU
static constexpr u32 DEBUG_FLAG_STOP_PRIVILEGE = 0x00020000; // run until execution level changes
static constexpr u32 DEBUG_FLAG_STEPPING_BRANCH_TRUE = 0x0040000; // run until true branch
static constexpr u32 DEBUG_FLAG_STEPPING_BRANCH_FALSE = 0x0080000; // run until false branch
@ -409,6 +413,7 @@ public:
void halt_on_next_instruction(device_t *device, util::format_argument_pack<char> &&args);
void ensure_comments_loaded();
void reset_transient_flags();
void wait_for_debugger(device_t &device);
private:
static const size_t NUM_TEMP_VARIABLES;

View File

@ -239,6 +239,12 @@ protected:
device().debug()->privilege_hook();
}
void debugger_wait_hook()
{
if (device().machine().debug_flags & DEBUG_FLAG_CALL_HOOK)
device().debug()->wait_hook();
}
private:
// internal information about the state of inputs
class device_input