mirror of
https://github.com/holub/mame
synced 2025-10-05 08:41:31 +03:00
debugger: add 'gp' command
gp 'go privilege' starts execution until the privilege mode changes. This can be used to break on task switches. I.e on m68k, one could do: gp { ~sr & 0x2000 && crp_aptr == 0x1234567 } which would execute until the privilege mode changes to user mode and the CPU root pointer is 0x1234567. for cpu code, all that is needed to make this work is calling debugger_privilege_hook() when the execution level changes.
This commit is contained in:
parent
25987a5fdc
commit
12f43029dc
@ -1009,12 +1009,17 @@ inline void m68ki_branch_32(uint32_t offset)
|
||||
*/
|
||||
inline void m68ki_set_s_flag(uint32_t value)
|
||||
{
|
||||
uint32_t old_s_flag = m_s_flag;
|
||||
/* Backup the old stack pointer */
|
||||
REG_SP_BASE()[m_s_flag | ((m_s_flag>>1) & m_m_flag)] = REG_SP();
|
||||
/* Set the S flag */
|
||||
m_s_flag = value;
|
||||
/* Set the new stack pointer */
|
||||
REG_SP() = REG_SP_BASE()[m_s_flag | ((m_s_flag>>1) & m_m_flag)];
|
||||
if ((old_s_flag ^ m_s_flag) & SFLAG_SET)
|
||||
{
|
||||
debugger_privilege_hook();
|
||||
}
|
||||
}
|
||||
|
||||
/* Set the S and M flags and change the active stack pointer.
|
||||
@ -1022,6 +1027,7 @@ inline void m68ki_set_s_flag(uint32_t value)
|
||||
*/
|
||||
inline void m68ki_set_sm_flag(uint32_t value)
|
||||
{
|
||||
uint32_t old_s_flag = m_s_flag;
|
||||
/* Backup the old stack pointer */
|
||||
REG_SP_BASE()[m_s_flag | ((m_s_flag >> 1) & m_m_flag)] = REG_SP();
|
||||
/* Set the S and M flags */
|
||||
@ -1029,14 +1035,23 @@ inline void m68ki_set_sm_flag(uint32_t value)
|
||||
m_m_flag = value & MFLAG_SET;
|
||||
/* Set the new stack pointer */
|
||||
REG_SP() = REG_SP_BASE()[m_s_flag | ((m_s_flag>>1) & m_m_flag)];
|
||||
if ((old_s_flag ^ m_s_flag) & SFLAG_SET)
|
||||
{
|
||||
debugger_privilege_hook();
|
||||
}
|
||||
}
|
||||
|
||||
/* Set the S and M flags. Don't touch the stack pointer. */
|
||||
inline void m68ki_set_sm_flag_nosp(uint32_t value)
|
||||
{
|
||||
uint32_t old_s_flag = m_s_flag;
|
||||
/* Set the S and M flags */
|
||||
m_s_flag = value & SFLAG_SET;
|
||||
m_m_flag = value & MFLAG_SET;
|
||||
if ((old_s_flag ^ m_s_flag) & SFLAG_SET)
|
||||
{
|
||||
debugger_privilege_hook();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -160,6 +160,7 @@ debugger_commands::debugger_commands(running_machine& machine, debugger_cpu& cpu
|
||||
m_console.register_command("ge", CMDFLAG_NONE, 0, 0, 1, std::bind(&debugger_commands::execute_go_exception, this, _1, _2));
|
||||
m_console.register_command("gtime", CMDFLAG_NONE, 0, 0, 1, std::bind(&debugger_commands::execute_go_time, this, _1, _2));
|
||||
m_console.register_command("gt", CMDFLAG_NONE, 0, 0, 1, std::bind(&debugger_commands::execute_go_time, this, _1, _2));
|
||||
m_console.register_command("gp", CMDFLAG_NONE, 0, 0, 1, std::bind(&debugger_commands::execute_go_privilege, this, _1, _2));
|
||||
m_console.register_command("next", CMDFLAG_NONE, 0, 0, 0, std::bind(&debugger_commands::execute_next, this, _1, _2));
|
||||
m_console.register_command("n", CMDFLAG_NONE, 0, 0, 0, std::bind(&debugger_commands::execute_next, this, _1, _2));
|
||||
m_console.register_command("focus", CMDFLAG_NONE, 0, 1, 1, std::bind(&debugger_commands::execute_focus, this, _1, _2));
|
||||
@ -899,6 +900,19 @@ void debugger_commands::execute_go_time(int ref, const std::vector<std::string>
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*-------------------------------------------------
|
||||
execute_go_privilege - execute the gp command
|
||||
-------------------------------------------------*/
|
||||
void debugger_commands::execute_go_privilege(int ref, const std::vector<std::string> ¶ms)
|
||||
{
|
||||
parsed_expression condition(&m_cpu.get_visible_cpu()->debug()->symtable());
|
||||
if (params.size() > 0 && !debug_command_parameter_expression(params[0], condition))
|
||||
return;
|
||||
|
||||
m_cpu.get_visible_cpu()->debug()->go_privilege((condition.is_empty()) ? "1" : condition.original_string());
|
||||
}
|
||||
|
||||
/*-------------------------------------------------
|
||||
execute_next - execute the next command
|
||||
-------------------------------------------------*/
|
||||
|
@ -108,6 +108,7 @@ private:
|
||||
void execute_go_interrupt(int ref, const std::vector<std::string> ¶ms);
|
||||
void execute_go_exception(int ref, const std::vector<std::string> ¶ms);
|
||||
void execute_go_time(int ref, const std::vector<std::string> ¶ms);
|
||||
void execute_go_privilege(int ref, const std::vector<std::string> ¶ms);
|
||||
void execute_focus(int ref, const std::vector<std::string> ¶ms);
|
||||
void execute_ignore(int ref, const std::vector<std::string> ¶ms);
|
||||
void execute_observe(int ref, const std::vector<std::string> ¶ms);
|
||||
|
@ -1513,7 +1513,7 @@ void device_debug::interrupt_hook(int irqline)
|
||||
|
||||
void device_debug::exception_hook(int exception)
|
||||
{
|
||||
// see if this matches a pending interrupt request
|
||||
// see if this matches an exception breakpoint
|
||||
if ((m_flags & DEBUG_FLAG_STOP_EXCEPTION) != 0 && (m_stopexception == -1 || m_stopexception == exception))
|
||||
{
|
||||
m_device.machine().debugger().cpu().set_execution_stopped();
|
||||
@ -1523,6 +1523,37 @@ void device_debug::exception_hook(int exception)
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------
|
||||
// privilege_hook - called when privilege level is
|
||||
// changed
|
||||
//-------------------------------------------------
|
||||
|
||||
void device_debug::privilege_hook()
|
||||
{
|
||||
bool matched = 1;
|
||||
|
||||
if ((m_flags & DEBUG_FLAG_STOP_PRIVILEGE) != 0)
|
||||
{
|
||||
if (m_privilege_condition && !m_privilege_condition->is_empty())
|
||||
{
|
||||
try
|
||||
{
|
||||
matched = m_privilege_condition->execute();
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
if (matched)
|
||||
{
|
||||
m_device.machine().debugger().cpu().set_execution_stopped();
|
||||
m_device.machine().debugger().console().printf("Stopped due to privilege change\n", m_device.tag());
|
||||
compute_debug_flags();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//-------------------------------------------------
|
||||
// instruction_hook - called by the CPU cores
|
||||
// before executing each instruction
|
||||
@ -1860,6 +1891,21 @@ void device_debug::go_milliseconds(u64 milliseconds)
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------
|
||||
// go_privilege - execute until execution
|
||||
// level changes
|
||||
//-------------------------------------------------
|
||||
|
||||
void device_debug::go_privilege(const char *condition)
|
||||
{
|
||||
assert(m_exec != nullptr);
|
||||
m_device.machine().rewind_invalidate();
|
||||
m_privilege_condition = std::make_unique<parsed_expression>(&m_symtable, condition);
|
||||
m_flags |= DEBUG_FLAG_STOP_PRIVILEGE;
|
||||
m_device.machine().debugger().cpu().set_execution_running();
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------
|
||||
// halt_on_next_instruction_impl - halt in the
|
||||
// debugger on the next instruction, internal
|
||||
|
@ -181,6 +181,7 @@ public:
|
||||
void stop_hook();
|
||||
void interrupt_hook(int irqline);
|
||||
void exception_hook(int exception);
|
||||
void privilege_hook();
|
||||
void instruction_hook(offs_t curpc);
|
||||
|
||||
// hooks into our operations
|
||||
@ -205,6 +206,7 @@ public:
|
||||
void go_interrupt(int irqline = -1);
|
||||
void go_exception(int exception);
|
||||
void go_milliseconds(u64 milliseconds);
|
||||
void go_privilege(const char *condition);
|
||||
void go_next_device();
|
||||
|
||||
template <typename Format, typename... Params>
|
||||
@ -324,6 +326,7 @@ private:
|
||||
attotime m_stoptime; // stop time for DEBUG_FLAG_STOP_TIME
|
||||
int m_stopirq; // stop IRQ number for DEBUG_FLAG_STOP_INTERRUPT
|
||||
int m_stopexception; // stop exception number for DEBUG_FLAG_STOP_EXCEPTION
|
||||
std::unique_ptr<parsed_expression> m_privilege_condition; // expression to evaluate on privilege change
|
||||
attotime m_endexectime; // ending time of the current execution
|
||||
u64 m_total_cycles; // current total cycles
|
||||
u64 m_last_total_cycles; // last total cycles
|
||||
@ -459,11 +462,13 @@ private:
|
||||
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_STOP_PRIVILEGE = 0x00020000; // run until execution level changes
|
||||
|
||||
static constexpr u32 DEBUG_FLAG_STEPPING_ANY = DEBUG_FLAG_STEPPING | DEBUG_FLAG_STEPPING_OVER | DEBUG_FLAG_STEPPING_OUT;
|
||||
static constexpr u32 DEBUG_FLAG_TRACING_ANY = DEBUG_FLAG_TRACING | DEBUG_FLAG_TRACING_OVER;
|
||||
static constexpr u32 DEBUG_FLAG_TRANSIENT = DEBUG_FLAG_STEPPING_ANY | DEBUG_FLAG_STOP_PC |
|
||||
DEBUG_FLAG_STOP_INTERRUPT | DEBUG_FLAG_STOP_EXCEPTION | DEBUG_FLAG_STOP_VBLANK | DEBUG_FLAG_STOP_TIME;
|
||||
DEBUG_FLAG_STOP_INTERRUPT | DEBUG_FLAG_STOP_EXCEPTION | DEBUG_FLAG_STOP_VBLANK |
|
||||
DEBUG_FLAG_STOP_TIME | DEBUG_FLAG_STOP_PRIVILEGE;
|
||||
};
|
||||
|
||||
//**************************************************************************
|
||||
|
@ -275,6 +275,12 @@ protected:
|
||||
device().debug()->exception_hook(exception);
|
||||
}
|
||||
|
||||
void debugger_privilege_hook()
|
||||
{
|
||||
if (device().machine().debug_flags & DEBUG_FLAG_ENABLED)
|
||||
device().debug()->privilege_hook();
|
||||
}
|
||||
|
||||
private:
|
||||
// internal information about the state of inputs
|
||||
class device_input
|
||||
|
Loading…
Reference in New Issue
Block a user