mirror of
https://github.com/RetroDECK/Supermodel.git
synced 2025-04-10 19:15:14 +00:00
Changes to allow debugging of Musashi 68K core:
- added methods to attach/debug debugger. - added instruction hook & callback to m68kconf.h and added hooks into CMusashi68KDebug to allow debugger to control execution. - added methods to allow reading/writing of 68K registers (for all registers and for a given context, rather than just current one).
This commit is contained in:
parent
c155ae7503
commit
5a0f038171
|
@ -48,6 +48,11 @@
|
||||||
// Bus
|
// Bus
|
||||||
static CBus *Bus = NULL;
|
static CBus *Bus = NULL;
|
||||||
|
|
||||||
|
#ifdef SUPERMODEL_DEBUGGER
|
||||||
|
// Debugger
|
||||||
|
static CMusashi68KDebug *Debug = NULL;
|
||||||
|
#endif
|
||||||
|
|
||||||
// IRQ callback
|
// IRQ callback
|
||||||
static int (*IRQAck)(int nIRQ) = NULL;
|
static int (*IRQAck)(int nIRQ) = NULL;
|
||||||
|
|
||||||
|
@ -221,12 +226,30 @@ void M68KSetIRQ(int irqLevel)
|
||||||
|
|
||||||
int M68KRun(int numCycles)
|
int M68KRun(int numCycles)
|
||||||
{
|
{
|
||||||
return m68k_execute(numCycles);
|
#ifdef SUPERMODEL_DEBUGGER
|
||||||
|
if (Debug != NULL)
|
||||||
|
{
|
||||||
|
Debug->CPUActive();
|
||||||
|
lastCycles += numCycles;
|
||||||
|
}
|
||||||
|
#endif // SUPERMODEL_DEBUGGER
|
||||||
|
int doneCycles = m68k_execute(numCycles);
|
||||||
|
#ifdef SUPERMODEL_DEBUGGER
|
||||||
|
if (Debug != NULL)
|
||||||
|
{
|
||||||
|
Debug->CPUInactive();
|
||||||
|
lastCycles -= m68k_cycles_remaining();
|
||||||
|
}
|
||||||
|
#endif // SUPERMODEL_DEBUGGER
|
||||||
|
return doneCycles;
|
||||||
}
|
}
|
||||||
|
|
||||||
void M68KReset(void)
|
void M68KReset(void)
|
||||||
{
|
{
|
||||||
m68k_pulse_reset();
|
m68k_pulse_reset();
|
||||||
|
#ifdef SUPERMODEL_DEBUGGER
|
||||||
|
lastCycles = 0;
|
||||||
|
#endif
|
||||||
DebugLog("68K reset\n");
|
DebugLog("68K reset\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -249,6 +272,9 @@ void M68KGetContext(M68KCtx *Dest)
|
||||||
{
|
{
|
||||||
Dest->IRQAck = IRQAck;
|
Dest->IRQAck = IRQAck;
|
||||||
Dest->Bus = Bus;
|
Dest->Bus = Bus;
|
||||||
|
#ifdef SUPERMODEL_DEBUGGER
|
||||||
|
Dest->Debug = Debug;
|
||||||
|
#endif // SUPERMODEL_DEBUGGER
|
||||||
m68k_get_context(&(Dest->musashiCtx));
|
m68k_get_context(&(Dest->musashiCtx));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -256,6 +282,9 @@ void M68KSetContext(M68KCtx *Src)
|
||||||
{
|
{
|
||||||
IRQAck = Src->IRQAck;
|
IRQAck = Src->IRQAck;
|
||||||
Bus = Src->Bus;
|
Bus = Src->Bus;
|
||||||
|
#ifdef SUPERMODEL_DEBUGGER
|
||||||
|
Debug = Src->Debug;
|
||||||
|
#endif // SUPERMODEL_DEBUGGER
|
||||||
m68k_set_context(&(Src->musashiCtx));
|
m68k_set_context(&(Src->musashiCtx));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -267,11 +296,68 @@ bool M68KInit(void)
|
||||||
m68k_set_cpu_type(M68K_CPU_TYPE_68000);
|
m68k_set_cpu_type(M68K_CPU_TYPE_68000);
|
||||||
m68k_set_int_ack_callback(M68KIRQCallback);
|
m68k_set_int_ack_callback(M68KIRQCallback);
|
||||||
Bus = NULL;
|
Bus = NULL;
|
||||||
|
#ifdef SUPERMODEL_DEBUGGER
|
||||||
|
Debug = NULL;
|
||||||
|
#endif // SUPERMODEL_DEBUGGER
|
||||||
DebugLog("Initialized 68K\n");
|
DebugLog("Initialized 68K\n");
|
||||||
return OKAY;
|
return OKAY;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef SUPERMODEL_DEBUGGER
|
||||||
|
UINT32 M68KGetRegister(M68KCtx *Src, unsigned reg)
|
||||||
|
{
|
||||||
|
switch (reg)
|
||||||
|
{
|
||||||
|
case DBG68K_REG_PC: return m68k_get_reg(&(Src->musashiCtx), M68K_REG_PC);
|
||||||
|
case DBG68K_REG_SR: return m68k_get_reg(&(Src->musashiCtx), M68K_REG_SR);
|
||||||
|
case DBG68K_REG_SP: return m68k_get_reg(&(Src->musashiCtx), M68K_REG_SP);
|
||||||
|
case DBG68K_REG_D0: return m68k_get_reg(&(Src->musashiCtx), M68K_REG_D0);
|
||||||
|
case DBG68K_REG_D1: return m68k_get_reg(&(Src->musashiCtx), M68K_REG_D1);
|
||||||
|
case DBG68K_REG_D2: return m68k_get_reg(&(Src->musashiCtx), M68K_REG_D2);
|
||||||
|
case DBG68K_REG_D3: return m68k_get_reg(&(Src->musashiCtx), M68K_REG_D3);
|
||||||
|
case DBG68K_REG_D4: return m68k_get_reg(&(Src->musashiCtx), M68K_REG_D4);
|
||||||
|
case DBG68K_REG_D5: return m68k_get_reg(&(Src->musashiCtx), M68K_REG_D5);
|
||||||
|
case DBG68K_REG_D6: return m68k_get_reg(&(Src->musashiCtx), M68K_REG_D6);
|
||||||
|
case DBG68K_REG_D7: return m68k_get_reg(&(Src->musashiCtx), M68K_REG_D7);
|
||||||
|
case DBG68K_REG_A0: return m68k_get_reg(&(Src->musashiCtx), M68K_REG_A0);
|
||||||
|
case DBG68K_REG_A1: return m68k_get_reg(&(Src->musashiCtx), M68K_REG_A1);
|
||||||
|
case DBG68K_REG_A2: return m68k_get_reg(&(Src->musashiCtx), M68K_REG_A2);
|
||||||
|
case DBG68K_REG_A3: return m68k_get_reg(&(Src->musashiCtx), M68K_REG_A3);
|
||||||
|
case DBG68K_REG_A4: return m68k_get_reg(&(Src->musashiCtx), M68K_REG_A4);
|
||||||
|
case DBG68K_REG_A5: return m68k_get_reg(&(Src->musashiCtx), M68K_REG_A5);
|
||||||
|
case DBG68K_REG_A6: return m68k_get_reg(&(Src->musashiCtx), M68K_REG_A6);
|
||||||
|
case DBG68K_REG_A7: return m68k_get_reg(&(Src->musashiCtx), M68K_REG_A7);
|
||||||
|
default: return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
UINT32 M68KSetRegister(M68KCtx *Src, unsigned reg, UINT32 val)
|
||||||
|
{
|
||||||
|
switch (reg)
|
||||||
|
{
|
||||||
|
case DBG68K_REG_PC: m68k_set_reg(M68K_REG_PC, val); return true;
|
||||||
|
case DBG68K_REG_SR: m68k_set_reg(M68K_REG_SR, val); return true;
|
||||||
|
case DBG68K_REG_SP: m68k_set_reg(M68K_REG_SP, val); return true;
|
||||||
|
case DBG68K_REG_D0: m68k_set_reg(M68K_REG_D0, val); return true;
|
||||||
|
case DBG68K_REG_D1: m68k_set_reg(M68K_REG_D1, val); return true;
|
||||||
|
case DBG68K_REG_D2: m68k_set_reg(M68K_REG_D2, val); return true;
|
||||||
|
case DBG68K_REG_D3: m68k_set_reg(M68K_REG_D3, val); return true;
|
||||||
|
case DBG68K_REG_D4: m68k_set_reg(M68K_REG_D4, val); return true;
|
||||||
|
case DBG68K_REG_D5: m68k_set_reg(M68K_REG_D5, val); return true;
|
||||||
|
case DBG68K_REG_D6: m68k_set_reg(M68K_REG_D6, val); return true;
|
||||||
|
case DBG68K_REG_D7: m68k_set_reg(M68K_REG_D7, val); return true;
|
||||||
|
case DBG68K_REG_A0: m68k_set_reg(M68K_REG_A0, val); return true;
|
||||||
|
case DBG68K_REG_A1: m68k_set_reg(M68K_REG_A1, val); return true;
|
||||||
|
case DBG68K_REG_A2: m68k_set_reg(M68K_REG_A2, val); return true;
|
||||||
|
case DBG68K_REG_A3: m68k_set_reg(M68K_REG_A3, val); return true;
|
||||||
|
case DBG68K_REG_A4: m68k_set_reg(M68K_REG_A4, val); return true;
|
||||||
|
case DBG68K_REG_A5: m68k_set_reg(M68K_REG_A5, val); return true;
|
||||||
|
case DBG68K_REG_A6: m68k_set_reg(M68K_REG_A6, val); return true;
|
||||||
|
case DBG68K_REG_A7: m68k_set_reg(M68K_REG_A7, val); return true;
|
||||||
|
default: return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif // SUPERMODEL_DEBUGGER
|
||||||
|
|
||||||
/******************************************************************************
|
/******************************************************************************
|
||||||
Musashi 68K Handlers
|
Musashi 68K Handlers
|
||||||
|
@ -280,9 +366,29 @@ bool M68KInit(void)
|
||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
|
|
||||||
|
#ifdef SUPERMODEL_DEBUGGER
|
||||||
|
void M68KDebugCallback()
|
||||||
|
{
|
||||||
|
if (Debug != NULL)
|
||||||
|
{
|
||||||
|
UINT32 pc = m68k_get_reg(NULL, M68K_REG_PC);
|
||||||
|
UINT32 opcode = Bus->Read16(pc);
|
||||||
|
Debug->CPUExecute(pc, opcode, lastCycles - m68k_cycles_remaining());
|
||||||
|
lastCycles = m68k_cycles_remaining();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif // SUPERMODEL_DEBUGGER
|
||||||
|
|
||||||
int M68KIRQCallback(int nIRQ)
|
int M68KIRQCallback(int nIRQ)
|
||||||
{
|
{
|
||||||
|
#ifdef SUPERMODEL_DEBUGGER
|
||||||
|
if (Debug != NULL)
|
||||||
|
{
|
||||||
|
Debug->CPUException(25);
|
||||||
|
Debug->CPUInterrupt(nIRQ - 1);
|
||||||
|
}
|
||||||
|
#endif // SUPERMODEL_DEBUGGER
|
||||||
if (NULL == IRQAck) // no handler, use default behavior
|
if (NULL == IRQAck) // no handler, use default behavior
|
||||||
{
|
{
|
||||||
m68k_set_irq(0); // clear line
|
m68k_set_irq(0); // clear line
|
||||||
|
|
|
@ -44,6 +44,9 @@
|
||||||
#define FASTCALL
|
#define FASTCALL
|
||||||
//#endif
|
//#endif
|
||||||
|
|
||||||
|
#ifdef SUPERMODEL_DEBUGGER
|
||||||
|
class CMusashi68KDebug;
|
||||||
|
#endif // SUPERMODEL_DEBUGGER
|
||||||
|
|
||||||
/******************************************************************************
|
/******************************************************************************
|
||||||
Definitions
|
Definitions
|
||||||
|
@ -71,12 +74,18 @@ public:
|
||||||
m68ki_cpu_core musashiCtx; // CPU context
|
m68ki_cpu_core musashiCtx; // CPU context
|
||||||
CBus *Bus; // memory handlers
|
CBus *Bus; // memory handlers
|
||||||
int (*IRQAck)(int); // IRQ acknowledge callback
|
int (*IRQAck)(int); // IRQ acknowledge callback
|
||||||
|
#ifdef SUPERMODEL_DEBUGGER
|
||||||
|
CMusashi68KDebug *Debug; // holds debugger (if attached)
|
||||||
|
#endif // SUPERMODEL_DEBUGGER
|
||||||
|
|
||||||
SM68KCtx(void)
|
SM68KCtx(void)
|
||||||
{
|
{
|
||||||
Bus = NULL;
|
Bus = NULL;
|
||||||
IRQAck = NULL;
|
IRQAck = NULL;
|
||||||
memset(&musashiCtx, 0, sizeof(musashiCtx)); // very important! garbage in context at reset can cause very strange bugs
|
memset(&musashiCtx, 0, sizeof(musashiCtx)); // very important! garbage in context at reset can cause very strange bugs
|
||||||
|
#ifdef SUPERMODEL_DEBUGGER
|
||||||
|
Debug = NULL;
|
||||||
|
#endif // SUPERMODEL_DEBUGGER
|
||||||
}
|
}
|
||||||
|
|
||||||
~SM68KCtx(void)
|
~SM68KCtx(void)
|
||||||
|
@ -92,9 +101,9 @@ public:
|
||||||
|
|
||||||
Unless otherwise noted, all functions operate on the active context.
|
Unless otherwise noted, all functions operate on the active context.
|
||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* M68KGetDRegister(int n):
|
* M68KGetARegister(int n):
|
||||||
*
|
*
|
||||||
* Parameters:
|
* Parameters:
|
||||||
* n Register number (0-7).
|
* n Register number (0-7).
|
||||||
|
@ -104,6 +113,15 @@ public:
|
||||||
*/
|
*/
|
||||||
extern UINT32 M68KGetARegister(int n);
|
extern UINT32 M68KGetARegister(int n);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* M68KSetARegister(int n, UINT32 v):
|
||||||
|
*
|
||||||
|
* Parameters:
|
||||||
|
* n Register number (0-7).
|
||||||
|
* v Value to set register An to.
|
||||||
|
*/
|
||||||
|
extern void M68KSetARegister(int n, UINT32 v);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* M68KGetDRegister(int n):
|
* M68KGetDRegister(int n):
|
||||||
*
|
*
|
||||||
|
@ -113,7 +131,16 @@ extern UINT32 M68KGetARegister(int n);
|
||||||
* Returns:
|
* Returns:
|
||||||
* Register Dn.
|
* Register Dn.
|
||||||
*/
|
*/
|
||||||
extern UINT32 M68KGetDRegister(int reg);
|
extern UINT32 M68KGetDRegister(int n);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* M68KGetDRegister(int n, UINT32 v):
|
||||||
|
*
|
||||||
|
* Parameters:
|
||||||
|
* n Register number (0-7).
|
||||||
|
* v Value to set register Dn to.
|
||||||
|
*/
|
||||||
|
extern void M68KSetDRegister(int n, UINT32 v);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* M68KGetPC():
|
* M68KGetPC():
|
||||||
|
@ -232,6 +259,33 @@ extern void M68KGetContext(M68KCtx *Dest);
|
||||||
*/
|
*/
|
||||||
extern void M68KSetContext(M68KCtx *Src);
|
extern void M68KSetContext(M68KCtx *Src);
|
||||||
|
|
||||||
|
#ifdef SUPERMODEL_DEBUGGER
|
||||||
|
#define DBG68K_REG_PC 0
|
||||||
|
#define DBG68K_REG_SR 1
|
||||||
|
#define DBG68K_REG_SP 2
|
||||||
|
#define DBG68K_REG_D0 3
|
||||||
|
#define DBG68K_REG_D1 4
|
||||||
|
#define DBG68K_REG_D2 5
|
||||||
|
#define DBG68K_REG_D3 6
|
||||||
|
#define DBG68K_REG_D4 7
|
||||||
|
#define DBG68K_REG_D5 8
|
||||||
|
#define DBG68K_REG_D6 9
|
||||||
|
#define DBG68K_REG_D7 10
|
||||||
|
#define DBG68K_REG_A0 11
|
||||||
|
#define DBG68K_REG_A1 12
|
||||||
|
#define DBG68K_REG_A2 13
|
||||||
|
#define DBG68K_REG_A3 14
|
||||||
|
#define DBG68K_REG_A4 15
|
||||||
|
#define DBG68K_REG_A5 16
|
||||||
|
#define DBG68K_REG_A6 17
|
||||||
|
#define DBG68K_REG_A7 18
|
||||||
|
|
||||||
|
static int lastCycles = 0;
|
||||||
|
|
||||||
|
UINT32 M68KGetRegister(SM68KCtx *ctx, unsigned reg);
|
||||||
|
|
||||||
|
UINT32 M68KSetRegister(SM68KCtx *ctx, unsigned reg, UINT32 val);
|
||||||
|
#endif // SUPERMODEL_DEBUGGER
|
||||||
|
|
||||||
/******************************************************************************
|
/******************************************************************************
|
||||||
68K Handlers
|
68K Handlers
|
||||||
|
@ -239,7 +293,12 @@ extern void M68KSetContext(M68KCtx *Src);
|
||||||
Intended for use directly by the 68K core.
|
Intended for use directly by the 68K core.
|
||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
|
|
||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
|
|
||||||
|
#ifdef SUPERMODEL_DEBUGGER
|
||||||
|
extern void M68KDebugCallback();
|
||||||
|
#endif // SUPERMODEL_DEBUGGER
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* M68KIRQCallback(nIRQ):
|
* M68KIRQCallback(nIRQ):
|
||||||
|
|
|
@ -153,9 +153,13 @@
|
||||||
/* If ON, CPU will call the instruction hook callback before every
|
/* If ON, CPU will call the instruction hook callback before every
|
||||||
* instruction.
|
* instruction.
|
||||||
*/
|
*/
|
||||||
|
#ifdef SUPERMODEL_DEBUGGER
|
||||||
|
#define M68K_INSTRUCTION_HOOK OPT_SPECIFY_HANDLER
|
||||||
|
#define M68K_INSTRUCTION_CALLBACK() M68KDebugCallback()
|
||||||
|
#else
|
||||||
#define M68K_INSTRUCTION_HOOK OPT_OFF
|
#define M68K_INSTRUCTION_HOOK OPT_OFF
|
||||||
#define M68K_INSTRUCTION_CALLBACK() your_instruction_hook_function()
|
#define M68K_INSTRUCTION_CALLBACK() your_instruction_hook_function()
|
||||||
|
#endif // SUPERMODEL_DEBUGGER
|
||||||
|
|
||||||
/* If ON, the CPU will emulate the 4-byte prefetch queue of a real 68000 */
|
/* If ON, the CPU will emulate the 4-byte prefetch queue of a real 68000 */
|
||||||
#define M68K_EMULATE_PREFETCH OPT_OFF
|
#define M68K_EMULATE_PREFETCH OPT_OFF
|
||||||
|
|
Loading…
Reference in a new issue