mirror of
https://github.com/RetroDECK/Supermodel.git
synced 2025-04-10 19:15:14 +00:00
- Updated debugger classes to get them to compile with latest changes
- Moved CPU debugger for Turbo68K into separate class CTurbo68KDebug and made C68KDebug base class for later addition of Musashi core - Fixed typos in ConsoleDebugger
This commit is contained in:
parent
03fa9532eb
commit
45dd662dee
|
@ -1,5 +1,4 @@
|
||||||
#ifdef SUPERMODEL_DEBUGGER
|
#ifdef SUPERMODEL_DEBUGGER
|
||||||
#ifdef SUPERMODEL_SOUND
|
|
||||||
|
|
||||||
#include "68KDebug.h"
|
#include "68KDebug.h"
|
||||||
|
|
||||||
|
@ -8,73 +7,8 @@
|
||||||
|
|
||||||
namespace Debugger
|
namespace Debugger
|
||||||
{
|
{
|
||||||
UINT32 GetSpecialReg(CCPUDebug *cpu, unsigned id)
|
C68KDebug::C68KDebug() : CCPUDebug("68K", 2, 10, true, 24, 7)
|
||||||
{
|
{
|
||||||
switch (id)
|
|
||||||
{
|
|
||||||
case M68KSPECIAL_SP: return (UINT32)turbo68kcontext_68000.a[7];
|
|
||||||
case M68KSPECIAL_SR: return (UINT32)turbo68kcontext_68000.sr;
|
|
||||||
default: return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool SetSpecialReg(CCPUDebug *cpu, unsigned id, UINT32 data)
|
|
||||||
{
|
|
||||||
switch (id)
|
|
||||||
{
|
|
||||||
case M68KSPECIAL_SP: turbo68kcontext_68000.a[7] = data; return true;
|
|
||||||
case M68KSPECIAL_SR: turbo68kcontext_68000.sr = data; return true;
|
|
||||||
default: return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
UINT32 GetDataReg(CCPUDebug *cpu, unsigned id)
|
|
||||||
{
|
|
||||||
return (UINT32)turbo68kcontext_68000.d[id];
|
|
||||||
}
|
|
||||||
|
|
||||||
bool SetDataReg(CCPUDebug *cpu, unsigned id, UINT32 data)
|
|
||||||
{
|
|
||||||
turbo68kcontext_68000.d[id] = data;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
UINT32 GetAddressReg(CCPUDebug *cpu, unsigned id)
|
|
||||||
{
|
|
||||||
return (UINT32)turbo68kcontext_68000.a[id];
|
|
||||||
}
|
|
||||||
|
|
||||||
bool SetAddressReg(CCPUDebug *cpu, unsigned id, UINT32 data)
|
|
||||||
{
|
|
||||||
turbo68kcontext_68000.a[id] = data;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
static const char *srGroup = "Special Registers";
|
|
||||||
static const char *drGroup = "Data Registers";
|
|
||||||
static const char *arGroup = "Address Regsters";
|
|
||||||
|
|
||||||
C68KDebug::C68KDebug() : CCPUDebug("68K", 2, 10, true, 24, 7), m_resetAddr(0)
|
|
||||||
{
|
|
||||||
// Special registers
|
|
||||||
AddPCRegister ("PC", srGroup);
|
|
||||||
AddAddrRegister ("SP", srGroup, M68KSPECIAL_SP, GetSpecialReg, SetSpecialReg);
|
|
||||||
AddStatus32Register("SR", srGroup, M68KSPECIAL_SR, "TtSM.210...XNZVC", GetSpecialReg, SetSpecialReg);
|
|
||||||
|
|
||||||
// Data registers
|
|
||||||
for (unsigned id = 0; id < 8; id++)
|
|
||||||
{
|
|
||||||
sprintf(m_drNames[id], "D%u", id);
|
|
||||||
AddInt32Register(m_drNames[id], drGroup, id, GetDataReg, SetDataReg);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Address registers
|
|
||||||
for (unsigned id = 0; id < 8; id++)
|
|
||||||
{
|
|
||||||
sprintf(m_arNames[id], "A%u", id);
|
|
||||||
AddInt32Register(m_arNames[id], arGroup, id, GetAddressReg, SetAddressReg);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Exceptions
|
// Exceptions
|
||||||
AddException("BUS", 2, "Bus Error");
|
AddException("BUS", 2, "Bus Error");
|
||||||
AddException("ADDRESS", 3, "Address Error");
|
AddException("ADDRESS", 3, "Address Error");
|
||||||
|
@ -148,180 +82,6 @@ namespace Debugger
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
C68KDebug::~C68KDebug()
|
|
||||||
{
|
|
||||||
DetachFromCPU();
|
|
||||||
}
|
|
||||||
|
|
||||||
BOOL __cdecl DebugHandler(TURBO68K_INT32 pc, TURBO68K_INT32 opcode)
|
|
||||||
{
|
|
||||||
// Return true to let Turbo68K know if PC was changed by user
|
|
||||||
return debug->CheckExecution((UINT32)pc, (UINT32)opcode);
|
|
||||||
}
|
|
||||||
|
|
||||||
void __cdecl InterruptHandler(TURBO68K_UINT32 intVec)
|
|
||||||
{
|
|
||||||
// TODO - is following correct handling of interrupts? - need to check readme file
|
|
||||||
if (intVec > 47)
|
|
||||||
return;
|
|
||||||
else if (intVec >= 25 || intVec < 32)
|
|
||||||
{
|
|
||||||
debug->CheckException(25);
|
|
||||||
debug->CheckInterrupt((UINT16)intVec - 25);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
debug->CheckException((UINT16)intVec);
|
|
||||||
|
|
||||||
if (origIntAckPtr != NULL)
|
|
||||||
origIntAckPtr(intVec);
|
|
||||||
}
|
|
||||||
|
|
||||||
void C68KDebug::AttachToCPU()
|
|
||||||
{
|
|
||||||
if (debug != NULL)
|
|
||||||
DetachFromCPU();
|
|
||||||
|
|
||||||
debug = this;
|
|
||||||
|
|
||||||
origDebugPtr = (DebugPtr)turbo68kcontext_68000.Debug;
|
|
||||||
origIntAckPtr = (IntAckPtr)turbo68kcontext_68000.InterruptAcknowledge;
|
|
||||||
|
|
||||||
origRead8Regions = (TURBO68K_DATAREGION*)Turbo68KGetReadByte(TURBO68K_NULL);
|
|
||||||
origRead16Regions = (TURBO68K_DATAREGION*)Turbo68KGetReadWord(TURBO68K_NULL);
|
|
||||||
origRead32Regions = (TURBO68K_DATAREGION*)Turbo68KGetReadLong(TURBO68K_NULL);
|
|
||||||
origWrite8Regions = (TURBO68K_DATAREGION*)Turbo68KGetWriteByte(TURBO68K_NULL);
|
|
||||||
origWrite16Regions = (TURBO68K_DATAREGION*)Turbo68KGetWriteWord(TURBO68K_NULL);
|
|
||||||
origWrite32Regions = (TURBO68K_DATAREGION*)Turbo68KGetWriteLong(TURBO68K_NULL);
|
|
||||||
|
|
||||||
turbo68kcontext_68000.Debug = DebugHandler;
|
|
||||||
turbo68kcontext_68000.InterruptAcknowledge = InterruptHandler;
|
|
||||||
|
|
||||||
debugRead8Regions[0].handler = ReadByteDebug;
|
|
||||||
debugRead16Regions[0].handler = ReadWordDebug;
|
|
||||||
debugRead32Regions[0].handler = ReadLongDebug;
|
|
||||||
debugWrite8Regions[0].handler = WriteByteDebug;
|
|
||||||
debugWrite16Regions[0].handler = WriteWordDebug;
|
|
||||||
debugWrite32Regions[0].handler = WriteLongDebug;
|
|
||||||
|
|
||||||
Turbo68KSetReadByte(debugRead8Regions, TURBO68K_NULL);
|
|
||||||
Turbo68KSetReadWord(debugRead16Regions, TURBO68K_NULL);
|
|
||||||
Turbo68KSetReadLong(debugRead32Regions, TURBO68K_NULL);
|
|
||||||
Turbo68KSetWriteByte(debugWrite8Regions, TURBO68K_NULL);
|
|
||||||
Turbo68KSetWriteWord(debugWrite16Regions, TURBO68K_NULL);
|
|
||||||
Turbo68KSetWriteLong(debugWrite32Regions, TURBO68K_NULL);
|
|
||||||
|
|
||||||
// Reset address is held at 0x000004
|
|
||||||
m_resetAddr = ReadLongDirect(0x000004);
|
|
||||||
}
|
|
||||||
|
|
||||||
void C68KDebug::DetachFromCPU()
|
|
||||||
{
|
|
||||||
if (debug == NULL)
|
|
||||||
return;
|
|
||||||
|
|
||||||
turbo68kcontext_68000.Debug = origDebugPtr;
|
|
||||||
turbo68kcontext_68000.InterruptAcknowledge = origIntAckPtr;
|
|
||||||
|
|
||||||
Turbo68KSetReadByte(origRead8Regions, TURBO68K_NULL);
|
|
||||||
Turbo68KSetReadWord(origRead16Regions, TURBO68K_NULL);
|
|
||||||
Turbo68KSetReadLong(origRead32Regions, TURBO68K_NULL);
|
|
||||||
Turbo68KSetWriteByte(origWrite8Regions, TURBO68K_NULL);
|
|
||||||
Turbo68KSetWriteWord(origWrite16Regions, TURBO68K_NULL);
|
|
||||||
Turbo68KSetWriteLong(origWrite32Regions, TURBO68K_NULL);
|
|
||||||
|
|
||||||
debug = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
UINT32 C68KDebug::GetResetAddr()
|
|
||||||
{
|
|
||||||
return m_resetAddr;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool C68KDebug::UpdatePC(UINT32 newPC)
|
|
||||||
{
|
|
||||||
turbo68kcontext_68000.pc = newPC;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool C68KDebug::ForceException(CException *ex)
|
|
||||||
{
|
|
||||||
//switch (ex->code)
|
|
||||||
//{
|
|
||||||
// TODO
|
|
||||||
//}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool C68KDebug::ForceInterrupt(CInterrupt *in)
|
|
||||||
{
|
|
||||||
if (in->code > 6)
|
|
||||||
return false;
|
|
||||||
//Turbo68KInterrupt(in->code, TURBO64K_AUTOVECTOR);
|
|
||||||
//Turbo68KProcessInterrupts(); TODO - call this?
|
|
||||||
return false; // TODO
|
|
||||||
}
|
|
||||||
|
|
||||||
UINT64 C68KDebug::ReadMem(UINT32 addr, unsigned dataSize)
|
|
||||||
{
|
|
||||||
switch (dataSize)
|
|
||||||
{
|
|
||||||
case 1: return ReadByteDirect(addr);
|
|
||||||
case 2: return ReadWordDirect(addr);
|
|
||||||
case 4: return ReadLongDirect(addr);
|
|
||||||
default: return CCPUDebug::ReadMem(addr, dataSize);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool C68KDebug::WriteMem(UINT32 addr, unsigned dataSize, UINT64 data)
|
|
||||||
{
|
|
||||||
switch (dataSize)
|
|
||||||
{
|
|
||||||
case 1: WriteByteDirect(addr, (TURBO68K_UINT8)data); return true;
|
|
||||||
case 2: WriteWordDirect(addr, (TURBO68K_UINT16)data); return true;
|
|
||||||
case 4: WriteLongDirect(addr, (TURBO68K_UINT32)data); return true;
|
|
||||||
default: return CCPUDebug::WriteMem(addr, dataSize, data);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
TURBO68K_UINT8 __cdecl ReadByteDebug(TURBO68K_UINT32 addr)
|
|
||||||
{
|
|
||||||
TURBO68K_UINT8 data = ReadByteDirect(addr);
|
|
||||||
debug->CheckRead8((UINT32)addr, (UINT8)data);
|
|
||||||
return data;
|
|
||||||
}
|
|
||||||
|
|
||||||
TURBO68K_UINT16 __cdecl ReadWordDebug(TURBO68K_UINT32 addr)
|
|
||||||
{
|
|
||||||
TURBO68K_UINT16 data = ReadWordDirect(addr);
|
|
||||||
debug->CheckRead16((UINT32)addr, (UINT16)data);
|
|
||||||
return data;
|
|
||||||
}
|
|
||||||
|
|
||||||
TURBO68K_UINT32 __cdecl ReadLongDebug(TURBO68K_UINT32 addr)
|
|
||||||
{
|
|
||||||
TURBO68K_UINT32 data = ReadLongDirect(addr);
|
|
||||||
debug->CheckRead32((UINT32)addr, (UINT32)data);
|
|
||||||
return data;
|
|
||||||
}
|
|
||||||
|
|
||||||
void __cdecl WriteByteDebug(TURBO68K_UINT32 addr, TURBO68K_UINT8 data)
|
|
||||||
{
|
|
||||||
WriteByteDirect(addr, data);
|
|
||||||
debug->CheckWrite8((UINT32)addr, (UINT8)data);
|
|
||||||
}
|
|
||||||
|
|
||||||
void __cdecl WriteWordDebug(TURBO68K_UINT32 addr, TURBO68K_UINT16 data)
|
|
||||||
{
|
|
||||||
WriteWordDirect(addr, data);
|
|
||||||
debug->CheckWrite16((UINT32)addr, (UINT16)data);
|
|
||||||
}
|
|
||||||
|
|
||||||
void __cdecl WriteLongDebug(TURBO68K_UINT32 addr, TURBO68K_UINT32 data)
|
|
||||||
{
|
|
||||||
WriteLongDirect(addr, data);
|
|
||||||
debug->CheckWrite32((UINT32)addr, (UINT32)data);
|
|
||||||
}
|
|
||||||
|
|
||||||
static const char *opATable0004[] = { "movep.w [DW3](A0),D0","movep.w [DW3](A1),D0","movep.w [DW3](A2),D0",
|
static const char *opATable0004[] = { "movep.w [DW3](A0),D0","movep.w [DW3](A1),D0","movep.w [DW3](A2),D0",
|
||||||
"movep.w [DW3](A3),D0","movep.w [DW3](A4),D0","movep.w [DW3](A5),D0","movep.w [DW3](A6),D0",
|
"movep.w [DW3](A3),D0","movep.w [DW3](A4),D0","movep.w [DW3](A5),D0","movep.w [DW3](A6),D0",
|
||||||
"movep.w [DW3](A7),D0" };
|
"movep.w [DW3](A7),D0" };
|
||||||
|
@ -1485,7 +1245,7 @@ namespace Debugger
|
||||||
int C68KDebug::Disassemble(UINT32 addr, char *mnemonic, char *operands)
|
int C68KDebug::Disassemble(UINT32 addr, char *mnemonic, char *operands)
|
||||||
{
|
{
|
||||||
// Read opcode head word
|
// Read opcode head word
|
||||||
UINT16 opcode = ReadWordDirect(addr);
|
UINT16 opcode = (UINT16)ReadMem(addr, 16);
|
||||||
int offset = 2;
|
int offset = 2;
|
||||||
|
|
||||||
const char *instr;
|
const char *instr;
|
||||||
|
@ -1537,7 +1297,7 @@ namespace Debugger
|
||||||
if ((opcode&0x0B80) == 0x0880)
|
if ((opcode&0x0B80) == 0x0880)
|
||||||
{
|
{
|
||||||
// movem.z reg-list,a or movem.z a,reg-list
|
// movem.z reg-list,a or movem.z a,reg-list
|
||||||
u16 = ReadWordDirect(addr + offset);
|
u16 = (UINT16)ReadMem(addr + offset, 2);
|
||||||
offset += 2;
|
offset += 2;
|
||||||
char sizeC = (opcode&0x40 ? 'l' : 'w');
|
char sizeC = (opcode&0x40 ? 'l' : 'w');
|
||||||
char regList[50];
|
char regList[50];
|
||||||
|
@ -1923,14 +1683,14 @@ namespace Debugger
|
||||||
if (p[2] == 'N')
|
if (p[2] == 'N')
|
||||||
{
|
{
|
||||||
// Check first byte is zero
|
// Check first byte is zero
|
||||||
u8 = ReadByteDirect(addr + offset++);
|
u8 = (UINT8)ReadMem(addr + offset++, 1);
|
||||||
if (u8 != 0)
|
if (u8 != 0)
|
||||||
{
|
{
|
||||||
offset++;
|
offset++;
|
||||||
goto invalid;
|
goto invalid;
|
||||||
}
|
}
|
||||||
// Get data byte
|
// Get data byte
|
||||||
u8 = ReadByteDirect(addr + offset++);
|
u8 = (UINT8)ReadMem(addr + offset++, 1);
|
||||||
// Check top 3 bits are zero
|
// Check top 3 bits are zero
|
||||||
if (u8&0xE0)
|
if (u8&0xE0)
|
||||||
goto invalid;
|
goto invalid;
|
||||||
|
@ -1940,16 +1700,16 @@ namespace Debugger
|
||||||
else if (p[2] == 'B')
|
else if (p[2] == 'B')
|
||||||
{
|
{
|
||||||
// Check first byte is zero
|
// Check first byte is zero
|
||||||
u8 = ReadByteDirect(addr + offset++);
|
u8 = (UINT8)ReadMem(addr + offset++, 1);
|
||||||
if (u8 != 0)
|
if (u8 != 0)
|
||||||
{
|
{
|
||||||
offset++;
|
offset++;
|
||||||
goto invalid;
|
goto invalid;
|
||||||
}
|
}
|
||||||
// Get data byte
|
// Get data byte
|
||||||
u8 = ReadByteDirect(addr + offset++);
|
u8 = (UINT8)ReadMem(addr + offset++, 1);
|
||||||
FormatData(r, 1, u8);
|
FormatData(r, 1, u8);
|
||||||
//i8 = (INT8)ReadByteDirect(addr + offset++);
|
//i8 = (INT8)ReadMem(addr + offset++, 1);
|
||||||
//if (i8 < 0)
|
//if (i8 < 0)
|
||||||
//{
|
//{
|
||||||
// *r++ = '-';
|
// *r++ = '-';
|
||||||
|
@ -1964,10 +1724,10 @@ namespace Debugger
|
||||||
}
|
}
|
||||||
else if (p[2] == 'W')
|
else if (p[2] == 'W')
|
||||||
{
|
{
|
||||||
u16 = ReadWordDirect(addr + offset);
|
u16 = (UINT16)ReadMem(addr + offset, 2);
|
||||||
offset += 2;
|
offset += 2;
|
||||||
FormatData(r, 2, u16);
|
FormatData(r, 2, u16);
|
||||||
//i16 = (INT16)ReadWordDirect(addr + offset);
|
//i16 = (INT16)ReadMem(addr + offset, 2);
|
||||||
//offset += 2;
|
//offset += 2;
|
||||||
//if (i16 < 0)
|
//if (i16 < 0)
|
||||||
//{
|
//{
|
||||||
|
@ -1983,10 +1743,10 @@ namespace Debugger
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
u32 = ReadLongDirect(addr + offset);
|
u32 = (UINT32)ReadMem(addr + offset, 4);
|
||||||
offset += 4;
|
offset += 4;
|
||||||
FormatData(r, 4, u32);
|
FormatData(r, 4, u32);
|
||||||
//i32 = (INT32)ReadLongDirect(addr + offset);
|
//i32 = (INT32)ReadMem(addr + offset, 4);
|
||||||
//offset += 4;
|
//offset += 4;
|
||||||
//if (i32 < 0)
|
//if (i32 < 0)
|
||||||
//{
|
//{
|
||||||
|
@ -2006,7 +1766,7 @@ namespace Debugger
|
||||||
else if (sscanf(p, "[LL%d]", &part) == 1) // TODO - this should be LW
|
else if (sscanf(p, "[LL%d]", &part) == 1) // TODO - this should be LW
|
||||||
{
|
{
|
||||||
// Fixed width label offset
|
// Fixed width label offset
|
||||||
i16 = (INT16)ReadWordDirect(addr + offset);
|
i16 = (INT16)ReadMem(addr + offset, 2);
|
||||||
offset += 2;
|
offset += 2;
|
||||||
// Offset is from PC + 2
|
// Offset is from PC + 2
|
||||||
opFlags = GetOpFlags(addr, opcode);
|
opFlags = GetOpFlags(addr, opcode);
|
||||||
|
@ -2022,14 +1782,14 @@ namespace Debugger
|
||||||
INT32 labOffset;
|
INT32 labOffset;
|
||||||
if (i8 == 0x00)
|
if (i8 == 0x00)
|
||||||
{
|
{
|
||||||
i16 = (INT16)ReadWordDirect(addr + offset);
|
i16 = (INT16)ReadMem(addr + offset, 2);
|
||||||
offset += 2;
|
offset += 2;
|
||||||
labOffset = i16;
|
labOffset = i16;
|
||||||
}
|
}
|
||||||
// Following 68020+ only
|
// Following 68020+ only
|
||||||
//else if (i8 == 0xFF)
|
//else if (i8 == 0xFF)
|
||||||
//{
|
//{
|
||||||
// i32 = (INT32)ReadLongDirect(addr + offset);
|
// i32 = (INT32)ReadMem(addr + offset, 4);
|
||||||
// offset += 4;
|
// offset += 4;
|
||||||
// labOffset = i32;
|
// labOffset = i32;
|
||||||
//*/
|
//*/
|
||||||
|
@ -2138,7 +1898,7 @@ namespace Debugger
|
||||||
sprintf(dest, "-(A%u)", reg);
|
sprintf(dest, "-(A%u)", reg);
|
||||||
break;
|
break;
|
||||||
case 0x05: // (d16,An)
|
case 0x05: // (d16,An)
|
||||||
i16 = (INT16)ReadWordDirect(addr + offset);
|
i16 = (INT16)ReadMem(addr + offset, 2);
|
||||||
offset += 2;
|
offset += 2;
|
||||||
if (i16 < 0)
|
if (i16 < 0)
|
||||||
{
|
{
|
||||||
|
@ -2154,7 +1914,7 @@ namespace Debugger
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 0x06: // (d8,An,Ri.z)
|
case 0x06: // (d8,An,Ri.z)
|
||||||
u8 = ReadByteDirect(addr + offset++);
|
u8 = (UINT8)ReadMem(addr + offset++, 1);
|
||||||
// Check first 3-bits of first byte are zero
|
// Check first 3-bits of first byte are zero
|
||||||
if (u8&0x7)
|
if (u8&0x7)
|
||||||
{
|
{
|
||||||
|
@ -2171,7 +1931,7 @@ namespace Debugger
|
||||||
ofsReg -= 8;
|
ofsReg -= 8;
|
||||||
}
|
}
|
||||||
ofsSizeC = (u8&0x8 ? 'l' : 'w');
|
ofsSizeC = (u8&0x8 ? 'l' : 'w');
|
||||||
i8 = (INT8)ReadByteDirect(addr + offset++);
|
i8 = (INT8)ReadMem(addr + offset++, 1);
|
||||||
if (i8 < 0)
|
if (i8 < 0)
|
||||||
{
|
{
|
||||||
FormatData(dataStr, 1, -i8);
|
FormatData(dataStr, 1, -i8);
|
||||||
|
@ -2189,21 +1949,21 @@ namespace Debugger
|
||||||
switch (reg)
|
switch (reg)
|
||||||
{
|
{
|
||||||
case 0x00: // addr16
|
case 0x00: // addr16
|
||||||
u16 = ReadWordDirect(addr + offset);
|
u16 = (UINT16)ReadMem(addr + offset, 2);
|
||||||
offset += 2;
|
offset += 2;
|
||||||
opFlags = GetOpFlags(addr, opcode);
|
opFlags = GetOpFlags(addr, opcode);
|
||||||
FormatJumpAddress(dest, u16, opFlags);
|
FormatJumpAddress(dest, u16, opFlags);
|
||||||
//sprintf(dest, "0x%06X", u16); // Format this way as memory bus width is 24-bits
|
//sprintf(dest, "0x%06X", u16); // Format this way as memory bus width is 24-bits
|
||||||
break;
|
break;
|
||||||
case 0x01: // addr32
|
case 0x01: // addr32
|
||||||
u32 = ReadLongDirect(addr + offset);
|
u32 = (UINT32)ReadMem(addr + offset, 4);
|
||||||
offset += 4;
|
offset += 4;
|
||||||
opFlags = GetOpFlags(addr, opcode);
|
opFlags = GetOpFlags(addr, opcode);
|
||||||
FormatJumpAddress(dest, u32, opFlags);
|
FormatJumpAddress(dest, u32, opFlags);
|
||||||
//sprintf(dest, "0x%06X", u32); // Format this way as memory bus width is only 24-bits
|
//sprintf(dest, "0x%06X", u32); // Format this way as memory bus width is only 24-bits
|
||||||
break;
|
break;
|
||||||
case 0x02: // d16(PC)
|
case 0x02: // d16(PC)
|
||||||
i16 = (INT16)ReadWordDirect(addr + offset);
|
i16 = (INT16)ReadMem(addr + offset, 2);
|
||||||
offset += 2;
|
offset += 2;
|
||||||
if (i16 < 0)
|
if (i16 < 0)
|
||||||
{
|
{
|
||||||
|
@ -2219,7 +1979,7 @@ namespace Debugger
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 0x03: // u8(PC,Ri.x)
|
case 0x03: // u8(PC,Ri.x)
|
||||||
u8 = ReadByteDirect(addr + offset++);
|
u8 = (UINT8)ReadMem(addr + offset++, 1);
|
||||||
// Check first 3-bits of first byte are zero
|
// Check first 3-bits of first byte are zero
|
||||||
if (u8&0x7)
|
if (u8&0x7)
|
||||||
{
|
{
|
||||||
|
@ -2236,7 +1996,7 @@ namespace Debugger
|
||||||
ofsReg -= 8;
|
ofsReg -= 8;
|
||||||
}
|
}
|
||||||
ofsSizeC = (u8&0x8 ? 'l' : 'w');
|
ofsSizeC = (u8&0x8 ? 'l' : 'w');
|
||||||
i8 = (INT8)ReadByteDirect(addr + offset++);
|
i8 = (INT8)ReadMem(addr + offset++, 1);
|
||||||
if (i8 < 0)
|
if (i8 < 0)
|
||||||
{
|
{
|
||||||
FormatData(dataStr, 1, -i8);
|
FormatData(dataStr, 1, -i8);
|
||||||
|
@ -2254,17 +2014,17 @@ namespace Debugger
|
||||||
if (sizeC == 'b')
|
if (sizeC == 'b')
|
||||||
{
|
{
|
||||||
// Check first byte is zero
|
// Check first byte is zero
|
||||||
u8 = ReadByteDirect(addr + offset++);
|
u8 = (UINT8)ReadMem(addr + offset++, 1);
|
||||||
if (u8 != 0)
|
if (u8 != 0)
|
||||||
{
|
{
|
||||||
offset++;
|
offset++;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
// Get data byte
|
// Get data byte
|
||||||
u8 = ReadByteDirect(addr + offset++);
|
u8 = (UINT8)ReadMem(addr + offset++, 1);
|
||||||
FormatData(dataStr, 1, u8);
|
FormatData(dataStr, 1, u8);
|
||||||
sprintf(dest, "#%s", dataStr);
|
sprintf(dest, "#%s", dataStr);
|
||||||
//i8 = (INT8)ReadByteDirect(addr + offset++);
|
//i8 = (INT8)ReadMem(addr + offset++, 1);
|
||||||
//if (i8 < 0)
|
//if (i8 < 0)
|
||||||
//{
|
//{
|
||||||
// FormatData(dataStr, 1, -i8);
|
// FormatData(dataStr, 1, -i8);
|
||||||
|
@ -2280,11 +2040,11 @@ namespace Debugger
|
||||||
}
|
}
|
||||||
else if (sizeC == 'w')
|
else if (sizeC == 'w')
|
||||||
{
|
{
|
||||||
u16 = ReadWordDirect(addr + offset);
|
u16 = (UINT16)ReadMem(addr + offset, 2);
|
||||||
offset += 2;
|
offset += 2;
|
||||||
FormatData(dataStr, 2, u16);
|
FormatData(dataStr, 2, u16);
|
||||||
sprintf(dest, "#%s", dataStr);
|
sprintf(dest, "#%s", dataStr);
|
||||||
//i16 = (INT16)ReadWordDirect(addr + offset);
|
//i16 = (INT16)ReadMem(addr + offset, 2);
|
||||||
//offset += 2;
|
//offset += 2;
|
||||||
//if (i16 < 0)
|
//if (i16 < 0)
|
||||||
//{
|
//{
|
||||||
|
@ -2301,11 +2061,11 @@ namespace Debugger
|
||||||
}
|
}
|
||||||
else if (sizeC == 'l')
|
else if (sizeC == 'l')
|
||||||
{
|
{
|
||||||
u32 = ReadLongDirect(addr + offset);
|
u32 = (UINT32)ReadMem(addr + offset, 4);
|
||||||
offset += 4;
|
offset += 4;
|
||||||
FormatData(dataStr, 4, u32);
|
FormatData(dataStr, 4, u32);
|
||||||
sprintf(dest, "#%s", dataStr);
|
sprintf(dest, "#%s", dataStr);
|
||||||
//i32 = (INT32)ReadLongDirect(addr + offset);
|
//i32 = (INT32)ReadMem(addr + offset, 4);
|
||||||
//offset += 4;
|
//offset += 4;
|
||||||
//if (i32 < 0)
|
//if (i32 < 0)
|
||||||
//{
|
//{
|
||||||
|
@ -2372,12 +2132,12 @@ namespace Debugger
|
||||||
{
|
{
|
||||||
if (reg == 0x00)
|
if (reg == 0x00)
|
||||||
{
|
{
|
||||||
jumpAddr = ReadWordDirect(addr + 2);
|
jumpAddr = (UINT32)ReadMem(addr + 2, 4);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
else if (reg == 0x01)
|
else if (reg == 0x01)
|
||||||
{
|
{
|
||||||
jumpAddr = ReadLongDirect(addr + 2);
|
jumpAddr = (UINT32)ReadMem(addr + 2, 4);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2388,7 +2148,7 @@ namespace Debugger
|
||||||
// Instruction is bra, bsr or bCC
|
// Instruction is bra, bsr or bCC
|
||||||
INT8 i8 = (INT8)(opcode&0xFF);
|
INT8 i8 = (INT8)(opcode&0xFF);
|
||||||
if (i8 == 0x00)
|
if (i8 == 0x00)
|
||||||
jumpAddr = addr + 2 + (INT16)ReadWordDirect(addr + 2);
|
jumpAddr = addr + 2 + (INT16)ReadMem(addr + 2, 2);
|
||||||
else
|
else
|
||||||
jumpAddr = addr + 2 + i8;
|
jumpAddr = addr + 2 + i8;
|
||||||
return true;
|
return true;
|
||||||
|
@ -2396,7 +2156,7 @@ namespace Debugger
|
||||||
else if ((opcode&0xF0F8) == 0x50C8)
|
else if ((opcode&0xF0F8) == 0x50C8)
|
||||||
{
|
{
|
||||||
// Instruction is dbCC
|
// Instruction is dbCC
|
||||||
jumpAddr = addr + 2 + (INT16)ReadWordDirect(addr + 2);
|
jumpAddr = addr + 2 + (INT16)ReadMem(addr + 2, 2);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -2444,28 +2204,27 @@ namespace Debugger
|
||||||
if (opcode != 0x4E74 && opcode != 0x4E75 && opcode != 0x4E73)
|
if (opcode != 0x4E74 && opcode != 0x4E75 && opcode != 0x4E73)
|
||||||
return false;
|
return false;
|
||||||
// Return address will be at top of stack for rts and stack + 2 for rtr or rte
|
// Return address will be at top of stack for rts and stack + 2 for rtr or rte
|
||||||
UINT32 sp = (UINT32)turbo68kcontext_68000.a[7];
|
UINT32 sp = 0; // TODO GetSP(); //(UINT32)turbo68kcontext_68000.a[7];
|
||||||
if (opcode == 0x4E75)
|
if (opcode == 0x4E75)
|
||||||
retAddr = ReadLongDirect(sp);
|
retAddr = (UINT32)ReadMem(sp, 4);
|
||||||
else
|
else
|
||||||
retAddr = ReadLongDirect(sp + 2);
|
retAddr = (UINT32)ReadMem(sp + 2, 4);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool C68KDebug::GetHandlerAddr(CException *ex, UINT32 &handlerAddr)
|
bool C68KDebug::GetHandlerAddr(CException *ex, UINT32 &handlerAddr)
|
||||||
{
|
{
|
||||||
UINT32 vecAddr = ex->code * 4;
|
UINT32 vecAddr = ex->code * 4;
|
||||||
handlerAddr = (UINT32)ReadLongDirect(vecAddr);
|
handlerAddr = (UINT32)ReadMem(vecAddr, 4);
|
||||||
return !!handlerAddr;
|
return !!handlerAddr;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool C68KDebug::GetHandlerAddr(CInterrupt *in, UINT32 &handlerAddr)
|
bool C68KDebug::GetHandlerAddr(CInterrupt *in, UINT32 &handlerAddr)
|
||||||
{
|
{
|
||||||
UINT32 vecAddr = (in->code + 25) * 4;
|
UINT32 vecAddr = (in->code + 25) * 4;
|
||||||
handlerAddr = (UINT32)ReadLongDirect(vecAddr);
|
handlerAddr = (UINT32)ReadMem(vecAddr, 4);
|
||||||
return !!handlerAddr;
|
return !!handlerAddr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // SUPERMODEL_SOUND
|
|
||||||
#endif // SUPERMODEL_DEBUGGER
|
#endif // SUPERMODEL_DEBUGGER
|
|
@ -1,12 +1,11 @@
|
||||||
#ifdef SUPERMODEL_DEBUGGER
|
#ifdef SUPERMODEL_DEBUGGER
|
||||||
#ifdef SUPERMODEL_SOUND
|
|
||||||
#ifndef INCLUDED_68KDEBUG_H
|
#ifndef INCLUDED_68KDEBUG_H
|
||||||
#define INCLUDED_68KDEBUG_H
|
#define INCLUDED_68KDEBUG_H
|
||||||
|
|
||||||
#include "Debugger/CPUDebug.h"
|
#include "Debugger/CPUDebug.h"
|
||||||
#include "Types.h"
|
#include "Types.h"
|
||||||
|
|
||||||
#include "CPU/68K/Turbo68K.h"
|
#include "CPU/68K/Turbo68K/Turbo68K.h"
|
||||||
|
|
||||||
#define M68KSPECIAL_SP 0
|
#define M68KSPECIAL_SP 0
|
||||||
#define M68KSPECIAL_SR 1
|
#define M68KSPECIAL_SR 1
|
||||||
|
@ -16,77 +15,8 @@
|
||||||
|
|
||||||
namespace Debugger
|
namespace Debugger
|
||||||
{
|
{
|
||||||
class C68KDebug;
|
|
||||||
|
|
||||||
static C68KDebug *debug = NULL;
|
|
||||||
|
|
||||||
typedef bool (*DebugPtr)(TURBO68K_INT32 pc, TURBO68K_INT32 opcode);
|
|
||||||
typedef void (*IntAckPtr)(TURBO68K_UINT32 intVec);
|
|
||||||
|
|
||||||
static DebugPtr origDebugPtr = NULL;
|
|
||||||
static IntAckPtr origIntAckPtr = NULL;
|
|
||||||
|
|
||||||
static TURBO68K_DATAREGION *origRead8Regions;
|
|
||||||
static TURBO68K_DATAREGION *origRead16Regions;
|
|
||||||
static TURBO68K_DATAREGION *origRead32Regions;
|
|
||||||
static TURBO68K_DATAREGION *origWrite8Regions;
|
|
||||||
static TURBO68K_DATAREGION *origWrite16Regions;
|
|
||||||
static TURBO68K_DATAREGION *origWrite32Regions;
|
|
||||||
|
|
||||||
static TURBO68K_DATAREGION debugRead8Regions[] =
|
|
||||||
{
|
|
||||||
{ 0x000000, 0xFFFFFF, TURBO68K_NULL, TURBO68K_NULL },
|
|
||||||
{ -1, -1, TURBO68K_NULL, TURBO68K_NULL }
|
|
||||||
};
|
|
||||||
static TURBO68K_DATAREGION debugRead16Regions[] =
|
|
||||||
{
|
|
||||||
{ 0x000000, 0xFFFFFF, TURBO68K_NULL, TURBO68K_NULL },
|
|
||||||
{ -1, -1, TURBO68K_NULL, TURBO68K_NULL }
|
|
||||||
};
|
|
||||||
static TURBO68K_DATAREGION debugRead32Regions[] =
|
|
||||||
{
|
|
||||||
{ 0x000000, 0xFFFFFF, TURBO68K_NULL, TURBO68K_NULL },
|
|
||||||
{ -1, -1, TURBO68K_NULL, TURBO68K_NULL }
|
|
||||||
};
|
|
||||||
static TURBO68K_DATAREGION debugWrite8Regions[] =
|
|
||||||
{
|
|
||||||
{ 0x000000, 0xFFFFFF, TURBO68K_NULL, TURBO68K_NULL },
|
|
||||||
{ -1, -1, TURBO68K_NULL, TURBO68K_NULL }
|
|
||||||
};
|
|
||||||
static TURBO68K_DATAREGION debugWrite16Regions[] =
|
|
||||||
{
|
|
||||||
{ 0x000000, 0xFFFFFF, TURBO68K_NULL, TURBO68K_NULL },
|
|
||||||
{ -1, -1, TURBO68K_NULL, TURBO68K_NULL }
|
|
||||||
};
|
|
||||||
static TURBO68K_DATAREGION debugWrite32Regions[] =
|
|
||||||
{
|
|
||||||
{ 0x000000, 0xFFFFFF, TURBO68K_NULL, TURBO68K_NULL },
|
|
||||||
{ -1, -1, TURBO68K_NULL, TURBO68K_NULL }
|
|
||||||
};
|
|
||||||
|
|
||||||
static UINT32 GetSpecialReg(CCPUDebug *cpu, unsigned id);
|
|
||||||
static bool SetSpecialReg(CCPUDebug *cpu, unsigned id, UINT32 data);
|
|
||||||
static UINT32 GetDataReg(CCPUDebug *cpu, unsigned id);
|
|
||||||
static bool SetDataReg(CCPUDebug *cpu, unsigned id, UINT32 data) ;
|
|
||||||
static UINT32 GetAddressReg(CCPUDebug *cpu, unsigned id);
|
|
||||||
static bool SetAddressReg(CCPUDebug *cpu, unsigned id, UINT32 data);
|
|
||||||
|
|
||||||
static TURBO68K_UINT8 ReadByteDebug(TURBO68K_UINT32 addr);
|
|
||||||
static TURBO68K_UINT16 ReadWordDebug(TURBO68K_UINT32 addr);
|
|
||||||
static TURBO68K_UINT32 ReadLongDebug(TURBO68K_UINT32 addr);
|
|
||||||
static void WriteByteDebug(TURBO68K_UINT32 addr, TURBO68K_UINT8 data);
|
|
||||||
static void WriteWordDebug(TURBO68K_UINT32 addr, TURBO68K_UINT16 data);
|
|
||||||
static void WriteLongDebug(TURBO68K_UINT32 addr, TURBO68K_UINT32 data);
|
|
||||||
|
|
||||||
static TURBO68K_UINT8 ReadByteDirect(TURBO68K_UINT32 addr);
|
|
||||||
static TURBO68K_UINT16 ReadWordDirect(TURBO68K_UINT32 addr);
|
|
||||||
static TURBO68K_UINT32 ReadLongDirect(TURBO68K_UINT32 addr);
|
|
||||||
static void WriteByteDirect(TURBO68K_UINT32 addr, TURBO68K_UINT8 data);
|
|
||||||
static void WriteWordDirect(TURBO68K_UINT32 addr, TURBO68K_UINT16 data);
|
|
||||||
static void WriteLongDirect(TURBO68K_UINT32 addr, TURBO68K_UINT32 data);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* CCPUDebug implementation for the Turbo68K Motorola 68000 emulator.
|
* Base class CCPUDebug implementation for Motorola 68000 CPUs.
|
||||||
*/
|
*/
|
||||||
class C68KDebug : public CCPUDebug
|
class C68KDebug : public CCPUDebug
|
||||||
{
|
{
|
||||||
|
@ -98,33 +28,16 @@ namespace Debugger
|
||||||
char m_sSlotStr[32][20];
|
char m_sSlotStr[32][20];
|
||||||
char m_regStr[16][12];
|
char m_regStr[16][12];
|
||||||
|
|
||||||
UINT32 m_resetAddr;
|
|
||||||
|
|
||||||
bool FormatAddrMode(UINT32 addr, UINT32 opcode, int &offset, UINT8 addrMode, char sizeC, char *dest);
|
bool FormatAddrMode(UINT32 addr, UINT32 opcode, int &offset, UINT8 addrMode, char sizeC, char *dest);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
virtual UINT32 GetSP() = 0;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
C68KDebug();
|
C68KDebug();
|
||||||
|
|
||||||
virtual ~C68KDebug();
|
|
||||||
|
|
||||||
// CCPUDebug methods
|
// CCPUDebug methods
|
||||||
|
|
||||||
void AttachToCPU();
|
|
||||||
|
|
||||||
void DetachFromCPU();
|
|
||||||
|
|
||||||
UINT32 GetResetAddr();
|
|
||||||
|
|
||||||
bool UpdatePC(UINT32 pc);
|
|
||||||
|
|
||||||
bool ForceException(CException *ex);
|
|
||||||
|
|
||||||
bool ForceInterrupt(CInterrupt *in);
|
|
||||||
|
|
||||||
UINT64 ReadMem(UINT32 addr, unsigned dataSize);
|
|
||||||
|
|
||||||
bool WriteMem(UINT32 addr, unsigned dataSize, UINT64 data);
|
|
||||||
|
|
||||||
int Disassemble(UINT32 addr, char *mnemonic, char *operands);
|
int Disassemble(UINT32 addr, char *mnemonic, char *operands);
|
||||||
|
|
||||||
EOpFlags GetOpFlags(UINT32 addr, UINT32 opcode);
|
EOpFlags GetOpFlags(UINT32 addr, UINT32 opcode);
|
||||||
|
@ -139,197 +52,7 @@ namespace Debugger
|
||||||
|
|
||||||
bool GetHandlerAddr(CInterrupt *in, UINT32 &handlerAddr);
|
bool GetHandlerAddr(CInterrupt *in, UINT32 &handlerAddr);
|
||||||
};
|
};
|
||||||
|
|
||||||
//
|
|
||||||
// Inlined functions
|
|
||||||
//
|
|
||||||
|
|
||||||
typedef TURBO68K_UINT8 (*ReadByteFPtr)(TURBO68K_UINT32);
|
|
||||||
typedef TURBO68K_UINT16 (*ReadWordFPtr)(TURBO68K_UINT32);
|
|
||||||
typedef TURBO68K_UINT32 (*ReadLongFPtr)(TURBO68K_UINT32);
|
|
||||||
typedef void (*WriteByteFPtr)(TURBO68K_UINT32, TURBO68K_UINT8);
|
|
||||||
typedef void (*WriteWordFPtr)(TURBO68K_UINT32, TURBO68K_UINT16);
|
|
||||||
typedef void (*WriteLongFPtr)(TURBO68K_UINT32, TURBO68K_UINT32);
|
|
||||||
|
|
||||||
inline TURBO68K_UINT8 ReadByteDirect(TURBO68K_UINT32 addr)
|
|
||||||
{
|
|
||||||
#if USE_NATIVE_READ
|
|
||||||
Turbo68KSetReadByte(origRead8Regions, TURBO68K_NULL);
|
|
||||||
TURBO68K_UINT8 data = Turbo68KReadByte(addr);
|
|
||||||
Turbo68KSetReadByte(debugRead8Regions, TURBO68K_NULL);
|
|
||||||
return data;
|
|
||||||
#else
|
|
||||||
for (TURBO68K_DATAREGION *region = origRead8Regions; region->ptr != TURBO68K_NULL || region->handler != TURBO68K_NULL; region++)
|
|
||||||
{
|
|
||||||
if (region->base <= addr && addr <= region->limit)
|
|
||||||
{
|
|
||||||
if (region->ptr != TURBO68K_NULL)
|
|
||||||
{
|
|
||||||
// Turbo68K requires native memory to be byte swapped, so must reverse this when reading bytes
|
|
||||||
TURBO68K_UINT8 *dataP = (TURBO68K_UINT8*)(region->ptr + (addr^1));
|
|
||||||
return *dataP;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
ReadByteFPtr fPtr = (ReadByteFPtr)region->handler;
|
|
||||||
return fPtr(addr);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
inline TURBO68K_UINT16 ReadWordDirect(TURBO68K_UINT32 addr)
|
|
||||||
{
|
|
||||||
#if USE_NATIVE_READ
|
|
||||||
Turbo68KSetReadWord(origRead16Regions, TURBO68K_NULL);
|
|
||||||
TURBO68K_UINT16 data = Turbo68KReadWord(addr);
|
|
||||||
Turbo68KSetReadWord(debugRead16Regions, TURBO68K_NULL);
|
|
||||||
return data;
|
|
||||||
#else
|
|
||||||
for (TURBO68K_DATAREGION *region = origRead16Regions; region->ptr != TURBO68K_NULL || region->handler != TURBO68K_NULL; region++)
|
|
||||||
{
|
|
||||||
if (region->base <= addr && addr <= region->limit)
|
|
||||||
{
|
|
||||||
if (region->ptr != TURBO68K_NULL)
|
|
||||||
{
|
|
||||||
// Turbo68K requires native memory to be byte swapped, so must reverse this when reading bytes
|
|
||||||
TURBO68K_UINT16 *dataP = (TURBO68K_UINT16*)(region->ptr + addr);
|
|
||||||
return *dataP;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
ReadWordFPtr fPtr = (ReadWordFPtr)region->handler;
|
|
||||||
return fPtr(addr);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
inline TURBO68K_UINT32 ReadLongDirect(TURBO68K_UINT32 addr)
|
|
||||||
{
|
|
||||||
#if USE_NATIVE_READ
|
|
||||||
Turbo68KSetReadLong(origRead32Regions, TURBO68K_NULL);
|
|
||||||
TURBO68K_UINT32 data = Turbo68KReadLong(addr);
|
|
||||||
Turbo68KSetReadLong(debugRead32Regions, TURBO68K_NULL);
|
|
||||||
return data;
|
|
||||||
#else
|
|
||||||
for (TURBO68K_DATAREGION *region = origRead32Regions; region->ptr != TURBO68K_NULL || region->handler != TURBO68K_NULL; region++)
|
|
||||||
{
|
|
||||||
if (region->base <= addr && addr <= region->limit)
|
|
||||||
{
|
|
||||||
if (region->ptr != TURBO68K_NULL)
|
|
||||||
{
|
|
||||||
// Turbo68K requires native memory to be byte swapped, so must reverse this when reading bytes
|
|
||||||
TURBO68K_UINT16 *dataP = (TURBO68K_UINT16*)(region->ptr + addr);
|
|
||||||
return (TURBO68K_UINT32)dataP[1] | ((TURBO68K_UINT32)dataP[0])<<16;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
ReadLongFPtr fPtr = (ReadLongFPtr)region->handler;
|
|
||||||
return fPtr(addr);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
inline void WriteByteDirect(TURBO68K_UINT32 addr, TURBO68K_UINT8 data)
|
|
||||||
{
|
|
||||||
#if USE_NATIVE_WRITE
|
|
||||||
Turbo68KSetWriteByte(origWrite8Regions, TURBO68K_NULL);
|
|
||||||
Turbo68KWriteByte(addr, data);
|
|
||||||
Turbo68KSetWriteByte(debugWrite8Regions, TURBO68K_NULL);
|
|
||||||
#else
|
|
||||||
for (TURBO68K_DATAREGION *region = origWrite8Regions; region->ptr != TURBO68K_NULL || region->handler != TURBO68K_NULL; region++)
|
|
||||||
{
|
|
||||||
if (region->base <= addr && addr <= region->limit)
|
|
||||||
{
|
|
||||||
if (region->ptr != TURBO68K_NULL)
|
|
||||||
{
|
|
||||||
// Turbo68K requires native memory to be byte swapped, so must reverse this when writing bytes
|
|
||||||
TURBO68K_UINT8 *dataP = (TURBO68K_UINT8*)(region->ptr + (addr^1));
|
|
||||||
*dataP = data;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
WriteByteFPtr fPtr = (WriteByteFPtr)region->handler;
|
|
||||||
fPtr(addr, data);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
inline void WriteWordDirect(TURBO68K_UINT32 addr, TURBO68K_UINT16 data)
|
|
||||||
{
|
|
||||||
#if USE_NATIVE_WRITE
|
|
||||||
Turbo68KSetWriteWord(origWrite16Regions, TURBO68K_NULL);
|
|
||||||
Turbo68KWriteWord(addr, data);
|
|
||||||
Turbo68KSetWriteWord(debugWrite16Regions, TURBO68K_NULL);
|
|
||||||
#else
|
|
||||||
for (TURBO68K_DATAREGION *region = origWrite16Regions; region->ptr != TURBO68K_NULL || region->handler != TURBO68K_NULL; region++)
|
|
||||||
{
|
|
||||||
if (region->base <= addr && addr <= region->limit)
|
|
||||||
{
|
|
||||||
if (region->ptr != TURBO68K_NULL)
|
|
||||||
{
|
|
||||||
// Turbo68K requires native memory to be byte swapped, so must reverse this when writing bytes
|
|
||||||
TURBO68K_UINT16 *dataP = (TURBO68K_UINT16*)(region->ptr + addr);
|
|
||||||
*dataP = data;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
WriteWordFPtr fPtr = (WriteWordFPtr)region->handler;
|
|
||||||
fPtr(addr, data);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
inline void WriteLongDirect(TURBO68K_UINT32 addr, TURBO68K_UINT32 data)
|
|
||||||
{
|
|
||||||
#if USE_NATIVE_WRITE
|
|
||||||
Turbo68KSetWriteLong(origWrite32Regions, TURBO68K_NULL);
|
|
||||||
Turbo68KWriteLong(addr, data);
|
|
||||||
Turbo68KSetWriteLong(debugWrite32Regions, TURBO68K_NULL);
|
|
||||||
#else
|
|
||||||
for (TURBO68K_DATAREGION *region = origWrite32Regions; region->ptr != TURBO68K_NULL || region->handler != TURBO68K_NULL; region++)
|
|
||||||
{
|
|
||||||
if (region->base <= addr && addr <= region->limit)
|
|
||||||
{
|
|
||||||
if (region->ptr != TURBO68K_NULL)
|
|
||||||
{
|
|
||||||
// Turbo68K requires native memory to be byte swapped, so must reverse this when writing bytes
|
|
||||||
TURBO68K_UINT16 *dataP = (TURBO68K_UINT16*)(region->ptr + addr);
|
|
||||||
dataP[0] = data>>16;
|
|
||||||
dataP[1] = data&0xFFFF;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
WriteLongFPtr fPtr = (WriteLongFPtr)region->handler;
|
|
||||||
fPtr(addr, data);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // INCLUDED_68KDEBUG_H
|
#endif // INCLUDED_68KDEBUG_H
|
||||||
#endif // SUPERMODEL_SOUND
|
|
||||||
#endif // SUPERMODEL_DEBUGGER
|
#endif // SUPERMODEL_DEBUGGER
|
|
@ -3,7 +3,7 @@
|
||||||
#define INCLUDED_PPCDEBUG_H
|
#define INCLUDED_PPCDEBUG_H
|
||||||
|
|
||||||
#include "Debugger/CPUDebug.h"
|
#include "Debugger/CPUDebug.h"
|
||||||
#include "Model3/Bus.h"
|
#include "CPU/Bus.h"
|
||||||
#include "Types.h"
|
#include "Types.h"
|
||||||
|
|
||||||
#define PPCSPECIAL_LR 0
|
#define PPCSPECIAL_LR 0
|
||||||
|
|
291
Src/Debugger/CPU/Turbo68KDebug.cpp
Normal file
291
Src/Debugger/CPU/Turbo68KDebug.cpp
Normal file
|
@ -0,0 +1,291 @@
|
||||||
|
#ifdef SUPERMODEL_DEBUGGER
|
||||||
|
|
||||||
|
#include "Turbo68KDebug.h"
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
#include <ctype.h>
|
||||||
|
|
||||||
|
namespace Debugger
|
||||||
|
{
|
||||||
|
UINT32 GetSpecialReg(CCPUDebug *cpu, unsigned id)
|
||||||
|
{
|
||||||
|
switch (id)
|
||||||
|
{
|
||||||
|
case M68KSPECIAL_SP: return (UINT32)turbo68kcontext_68000.a[7];
|
||||||
|
case M68KSPECIAL_SR: return (UINT32)turbo68kcontext_68000.sr;
|
||||||
|
default: return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SetSpecialReg(CCPUDebug *cpu, unsigned id, UINT32 data)
|
||||||
|
{
|
||||||
|
switch (id)
|
||||||
|
{
|
||||||
|
case M68KSPECIAL_SP: turbo68kcontext_68000.a[7] = data; return true;
|
||||||
|
case M68KSPECIAL_SR: turbo68kcontext_68000.sr = data; return true;
|
||||||
|
default: return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
UINT32 GetDataReg(CCPUDebug *cpu, unsigned id)
|
||||||
|
{
|
||||||
|
return (UINT32)turbo68kcontext_68000.d[id];
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SetDataReg(CCPUDebug *cpu, unsigned id, UINT32 data)
|
||||||
|
{
|
||||||
|
turbo68kcontext_68000.d[id] = data;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
UINT32 GetAddressReg(CCPUDebug *cpu, unsigned id)
|
||||||
|
{
|
||||||
|
return (UINT32)turbo68kcontext_68000.a[id];
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SetAddressReg(CCPUDebug *cpu, unsigned id, UINT32 data)
|
||||||
|
{
|
||||||
|
turbo68kcontext_68000.a[id] = data;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const char *srGroup = "Special Registers";
|
||||||
|
static const char *drGroup = "Data Registers";
|
||||||
|
static const char *arGroup = "Address Regsters";
|
||||||
|
|
||||||
|
CTurbo68KDebug::CTurbo68KDebug() : C68KDebug(), m_resetAddr(0)
|
||||||
|
{
|
||||||
|
// Special registers
|
||||||
|
AddPCRegister ("PC", srGroup);
|
||||||
|
AddAddrRegister ("SP", srGroup, M68KSPECIAL_SP, GetSpecialReg, SetSpecialReg);
|
||||||
|
AddStatus32Register("SR", srGroup, M68KSPECIAL_SR, "TtSM.210...XNZVC", GetSpecialReg, SetSpecialReg);
|
||||||
|
|
||||||
|
// Data registers
|
||||||
|
for (unsigned id = 0; id < 8; id++)
|
||||||
|
{
|
||||||
|
sprintf(m_drNames[id], "D%u", id);
|
||||||
|
AddInt32Register(m_drNames[id], drGroup, id, GetDataReg, SetDataReg);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Address registers
|
||||||
|
for (unsigned id = 0; id < 8; id++)
|
||||||
|
{
|
||||||
|
sprintf(m_arNames[id], "A%u", id);
|
||||||
|
AddInt32Register(m_arNames[id], arGroup, id, GetAddressReg, SetAddressReg);
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO - following Model3-specific stuff should be moved to SupermodelDebugger
|
||||||
|
|
||||||
|
// Regions
|
||||||
|
AddRegion(0x000000, 0x0FFFFF, true, false, "SCSP1 RAM");
|
||||||
|
AddRegion(0x200000, 0x2FFFFF, true, false, "SCSP2 RAM");
|
||||||
|
AddRegion(0x600000, 0x67FFFF, true, true, "Program ROM");
|
||||||
|
AddRegion(0x800000, 0x9FFFFF, false, true, "Sample ROM (low 2 MB)");
|
||||||
|
AddRegion(0xA00000, 0xDFFFFF, false, true, "Sample ROM (bank)");
|
||||||
|
AddRegion(0xE00000, 0xFFFFFF, false, true, "Sample ROM (bank)");
|
||||||
|
AddRegion(0x100000, 0x10FFFF, false, false, "SCSP Master");
|
||||||
|
AddRegion(0x300000, 0x30FFFF, false, false, "SCSP Slave");
|
||||||
|
|
||||||
|
// Mapped I/O
|
||||||
|
for (unsigned slot = 0; slot < 32; slot++)
|
||||||
|
{
|
||||||
|
sprintf(m_mSlotStr[slot], "SCSP Master Slot %02X", slot);
|
||||||
|
for (unsigned reg = 0; reg < 16; reg++)
|
||||||
|
{
|
||||||
|
UINT32 addr = 0x100000 + slot * 0x20 + reg * 0x02;
|
||||||
|
sprintf(m_regStr[reg], "Register %u", reg);
|
||||||
|
AddMappedIO(addr, 2, m_regStr[reg], m_mSlotStr[slot]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (unsigned slot = 0; slot < 32; slot++)
|
||||||
|
{
|
||||||
|
sprintf(m_sSlotStr[slot], "SCSP Slave Slot %02X", slot);
|
||||||
|
for (unsigned reg = 0; reg < 16; reg++)
|
||||||
|
{
|
||||||
|
UINT32 addr = 0x300000 + slot * 0x20 + reg * 0x02;
|
||||||
|
AddMappedIO(addr, 2, m_regStr[reg], m_sSlotStr[slot]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
CTurbo68KDebug::~CTurbo68KDebug()
|
||||||
|
{
|
||||||
|
DetachFromCPU();
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOL __cdecl DebugHandler(TURBO68K_INT32 pc, TURBO68K_INT32 opcode)
|
||||||
|
{
|
||||||
|
// Return true to let Turbo68K know if PC was changed by user
|
||||||
|
return debug->CheckExecution((UINT32)pc, (UINT32)opcode);
|
||||||
|
}
|
||||||
|
|
||||||
|
void __cdecl InterruptHandler(TURBO68K_UINT32 intVec)
|
||||||
|
{
|
||||||
|
// TODO - is following correct handling of interrupts? - need to check readme file
|
||||||
|
if (intVec > 47)
|
||||||
|
return;
|
||||||
|
else if (intVec >= 25 || intVec < 32)
|
||||||
|
{
|
||||||
|
debug->CheckException(25);
|
||||||
|
debug->CheckInterrupt((UINT16)intVec - 25);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
debug->CheckException((UINT16)intVec);
|
||||||
|
|
||||||
|
if (origIntAckPtr != NULL)
|
||||||
|
origIntAckPtr(intVec);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CTurbo68KDebug::AttachToCPU()
|
||||||
|
{
|
||||||
|
if (debug != NULL)
|
||||||
|
DetachFromCPU();
|
||||||
|
|
||||||
|
debug = this;
|
||||||
|
|
||||||
|
origDebugPtr = (DebugPtr)turbo68kcontext_68000.Debug;
|
||||||
|
origIntAckPtr = (IntAckPtr)turbo68kcontext_68000.InterruptAcknowledge;
|
||||||
|
|
||||||
|
origRead8Regions = (TURBO68K_DATAREGION*)Turbo68KGetReadByte(TURBO68K_NULL);
|
||||||
|
origRead16Regions = (TURBO68K_DATAREGION*)Turbo68KGetReadWord(TURBO68K_NULL);
|
||||||
|
origRead32Regions = (TURBO68K_DATAREGION*)Turbo68KGetReadLong(TURBO68K_NULL);
|
||||||
|
origWrite8Regions = (TURBO68K_DATAREGION*)Turbo68KGetWriteByte(TURBO68K_NULL);
|
||||||
|
origWrite16Regions = (TURBO68K_DATAREGION*)Turbo68KGetWriteWord(TURBO68K_NULL);
|
||||||
|
origWrite32Regions = (TURBO68K_DATAREGION*)Turbo68KGetWriteLong(TURBO68K_NULL);
|
||||||
|
|
||||||
|
turbo68kcontext_68000.Debug = DebugHandler;
|
||||||
|
turbo68kcontext_68000.InterruptAcknowledge = InterruptHandler;
|
||||||
|
|
||||||
|
debugRead8Regions[0].handler = ReadByteDebug;
|
||||||
|
debugRead16Regions[0].handler = ReadWordDebug;
|
||||||
|
debugRead32Regions[0].handler = ReadLongDebug;
|
||||||
|
debugWrite8Regions[0].handler = WriteByteDebug;
|
||||||
|
debugWrite16Regions[0].handler = WriteWordDebug;
|
||||||
|
debugWrite32Regions[0].handler = WriteLongDebug;
|
||||||
|
|
||||||
|
Turbo68KSetReadByte(debugRead8Regions, TURBO68K_NULL);
|
||||||
|
Turbo68KSetReadWord(debugRead16Regions, TURBO68K_NULL);
|
||||||
|
Turbo68KSetReadLong(debugRead32Regions, TURBO68K_NULL);
|
||||||
|
Turbo68KSetWriteByte(debugWrite8Regions, TURBO68K_NULL);
|
||||||
|
Turbo68KSetWriteWord(debugWrite16Regions, TURBO68K_NULL);
|
||||||
|
Turbo68KSetWriteLong(debugWrite32Regions, TURBO68K_NULL);
|
||||||
|
|
||||||
|
// Reset address is held at 0x000004
|
||||||
|
m_resetAddr = ReadLongDirect(0x000004);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CTurbo68KDebug::DetachFromCPU()
|
||||||
|
{
|
||||||
|
if (debug == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
turbo68kcontext_68000.Debug = origDebugPtr;
|
||||||
|
turbo68kcontext_68000.InterruptAcknowledge = origIntAckPtr;
|
||||||
|
|
||||||
|
Turbo68KSetReadByte(origRead8Regions, TURBO68K_NULL);
|
||||||
|
Turbo68KSetReadWord(origRead16Regions, TURBO68K_NULL);
|
||||||
|
Turbo68KSetReadLong(origRead32Regions, TURBO68K_NULL);
|
||||||
|
Turbo68KSetWriteByte(origWrite8Regions, TURBO68K_NULL);
|
||||||
|
Turbo68KSetWriteWord(origWrite16Regions, TURBO68K_NULL);
|
||||||
|
Turbo68KSetWriteLong(origWrite32Regions, TURBO68K_NULL);
|
||||||
|
|
||||||
|
debug = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
UINT32 CTurbo68KDebug::GetResetAddr()
|
||||||
|
{
|
||||||
|
return m_resetAddr;
|
||||||
|
}
|
||||||
|
|
||||||
|
UINT32 CTurbo68KDebug::GetSP()
|
||||||
|
{
|
||||||
|
return (UINT32)turbo68kcontext_68000.a[7];
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CTurbo68KDebug::UpdatePC(UINT32 newPC)
|
||||||
|
{
|
||||||
|
turbo68kcontext_68000.pc = newPC;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CTurbo68KDebug::ForceException(CException *ex)
|
||||||
|
{
|
||||||
|
//switch (ex->code)
|
||||||
|
//{
|
||||||
|
// TODO
|
||||||
|
//}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CTurbo68KDebug::ForceInterrupt(CInterrupt *in)
|
||||||
|
{
|
||||||
|
if (in->code > 6)
|
||||||
|
return false;
|
||||||
|
//Turbo68KInterrupt(in->code, TURBO64K_AUTOVECTOR);
|
||||||
|
//Turbo68KProcessInterrupts(); TODO - call this?
|
||||||
|
return false; // TODO
|
||||||
|
}
|
||||||
|
|
||||||
|
UINT64 CTurbo68KDebug::ReadMem(UINT32 addr, unsigned dataSize)
|
||||||
|
{
|
||||||
|
switch (dataSize)
|
||||||
|
{
|
||||||
|
case 1: return ReadByteDirect(addr);
|
||||||
|
case 2: return ReadWordDirect(addr);
|
||||||
|
case 4: return ReadLongDirect(addr);
|
||||||
|
default: return CCPUDebug::ReadMem(addr, dataSize);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CTurbo68KDebug::WriteMem(UINT32 addr, unsigned dataSize, UINT64 data)
|
||||||
|
{
|
||||||
|
switch (dataSize)
|
||||||
|
{
|
||||||
|
case 1: WriteByteDirect(addr, (TURBO68K_UINT8)data); return true;
|
||||||
|
case 2: WriteWordDirect(addr, (TURBO68K_UINT16)data); return true;
|
||||||
|
case 4: WriteLongDirect(addr, (TURBO68K_UINT32)data); return true;
|
||||||
|
default: return CCPUDebug::WriteMem(addr, dataSize, data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TURBO68K_UINT8 __cdecl ReadByteDebug(TURBO68K_UINT32 addr)
|
||||||
|
{
|
||||||
|
TURBO68K_UINT8 data = ReadByteDirect(addr);
|
||||||
|
debug->CheckRead8((UINT32)addr, (UINT8)data);
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
TURBO68K_UINT16 __cdecl ReadWordDebug(TURBO68K_UINT32 addr)
|
||||||
|
{
|
||||||
|
TURBO68K_UINT16 data = ReadWordDirect(addr);
|
||||||
|
debug->CheckRead16((UINT32)addr, (UINT16)data);
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
TURBO68K_UINT32 __cdecl ReadLongDebug(TURBO68K_UINT32 addr)
|
||||||
|
{
|
||||||
|
TURBO68K_UINT32 data = ReadLongDirect(addr);
|
||||||
|
debug->CheckRead32((UINT32)addr, (UINT32)data);
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
void __cdecl WriteByteDebug(TURBO68K_UINT32 addr, TURBO68K_UINT8 data)
|
||||||
|
{
|
||||||
|
WriteByteDirect(addr, data);
|
||||||
|
debug->CheckWrite8((UINT32)addr, (UINT8)data);
|
||||||
|
}
|
||||||
|
|
||||||
|
void __cdecl WriteWordDebug(TURBO68K_UINT32 addr, TURBO68K_UINT16 data)
|
||||||
|
{
|
||||||
|
WriteWordDirect(addr, data);
|
||||||
|
debug->CheckWrite16((UINT32)addr, (UINT16)data);
|
||||||
|
}
|
||||||
|
|
||||||
|
void __cdecl WriteLongDebug(TURBO68K_UINT32 addr, TURBO68K_UINT32 data)
|
||||||
|
{
|
||||||
|
WriteLongDirect(addr, data);
|
||||||
|
debug->CheckWrite32((UINT32)addr, (UINT32)data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // SUPERMODEL_DEBUGGER
|
319
Src/Debugger/CPU/Turbo68KDebug.h
Normal file
319
Src/Debugger/CPU/Turbo68KDebug.h
Normal file
|
@ -0,0 +1,319 @@
|
||||||
|
#ifdef SUPERMODEL_DEBUGGER
|
||||||
|
#ifndef INCLUDED_TURBO68KDEBUG_H
|
||||||
|
#define INCLUDED_TURBO68KDEBUG_H
|
||||||
|
|
||||||
|
#include "Debugger/CPU/68KDebug.h"
|
||||||
|
#include "Types.h"
|
||||||
|
|
||||||
|
#include "CPU/68K/Turbo68K/Turbo68K.h"
|
||||||
|
|
||||||
|
#define M68KSPECIAL_SP 0
|
||||||
|
#define M68KSPECIAL_SR 1
|
||||||
|
|
||||||
|
#define USE_NATIVE_READ 0
|
||||||
|
#define USE_NATIVE_WRITE 0
|
||||||
|
|
||||||
|
namespace Debugger
|
||||||
|
{
|
||||||
|
class CTurbo68KDebug;
|
||||||
|
|
||||||
|
static CTurbo68KDebug *debug = NULL;
|
||||||
|
|
||||||
|
typedef bool (*DebugPtr)(TURBO68K_INT32 pc, TURBO68K_INT32 opcode);
|
||||||
|
typedef void (*IntAckPtr)(TURBO68K_UINT32 intVec);
|
||||||
|
|
||||||
|
static DebugPtr origDebugPtr = NULL;
|
||||||
|
static IntAckPtr origIntAckPtr = NULL;
|
||||||
|
|
||||||
|
static TURBO68K_DATAREGION *origRead8Regions;
|
||||||
|
static TURBO68K_DATAREGION *origRead16Regions;
|
||||||
|
static TURBO68K_DATAREGION *origRead32Regions;
|
||||||
|
static TURBO68K_DATAREGION *origWrite8Regions;
|
||||||
|
static TURBO68K_DATAREGION *origWrite16Regions;
|
||||||
|
static TURBO68K_DATAREGION *origWrite32Regions;
|
||||||
|
|
||||||
|
static TURBO68K_DATAREGION debugRead8Regions[] =
|
||||||
|
{
|
||||||
|
{ 0x000000, 0xFFFFFF, TURBO68K_NULL, TURBO68K_NULL },
|
||||||
|
{ -1, -1, TURBO68K_NULL, TURBO68K_NULL }
|
||||||
|
};
|
||||||
|
static TURBO68K_DATAREGION debugRead16Regions[] =
|
||||||
|
{
|
||||||
|
{ 0x000000, 0xFFFFFF, TURBO68K_NULL, TURBO68K_NULL },
|
||||||
|
{ -1, -1, TURBO68K_NULL, TURBO68K_NULL }
|
||||||
|
};
|
||||||
|
static TURBO68K_DATAREGION debugRead32Regions[] =
|
||||||
|
{
|
||||||
|
{ 0x000000, 0xFFFFFF, TURBO68K_NULL, TURBO68K_NULL },
|
||||||
|
{ -1, -1, TURBO68K_NULL, TURBO68K_NULL }
|
||||||
|
};
|
||||||
|
static TURBO68K_DATAREGION debugWrite8Regions[] =
|
||||||
|
{
|
||||||
|
{ 0x000000, 0xFFFFFF, TURBO68K_NULL, TURBO68K_NULL },
|
||||||
|
{ -1, -1, TURBO68K_NULL, TURBO68K_NULL }
|
||||||
|
};
|
||||||
|
static TURBO68K_DATAREGION debugWrite16Regions[] =
|
||||||
|
{
|
||||||
|
{ 0x000000, 0xFFFFFF, TURBO68K_NULL, TURBO68K_NULL },
|
||||||
|
{ -1, -1, TURBO68K_NULL, TURBO68K_NULL }
|
||||||
|
};
|
||||||
|
static TURBO68K_DATAREGION debugWrite32Regions[] =
|
||||||
|
{
|
||||||
|
{ 0x000000, 0xFFFFFF, TURBO68K_NULL, TURBO68K_NULL },
|
||||||
|
{ -1, -1, TURBO68K_NULL, TURBO68K_NULL }
|
||||||
|
};
|
||||||
|
|
||||||
|
static UINT32 GetSpecialReg(CCPUDebug *cpu, unsigned id);
|
||||||
|
static bool SetSpecialReg(CCPUDebug *cpu, unsigned id, UINT32 data);
|
||||||
|
static UINT32 GetDataReg(CCPUDebug *cpu, unsigned id);
|
||||||
|
static bool SetDataReg(CCPUDebug *cpu, unsigned id, UINT32 data) ;
|
||||||
|
static UINT32 GetAddressReg(CCPUDebug *cpu, unsigned id);
|
||||||
|
static bool SetAddressReg(CCPUDebug *cpu, unsigned id, UINT32 data);
|
||||||
|
|
||||||
|
static TURBO68K_UINT8 ReadByteDebug(TURBO68K_UINT32 addr);
|
||||||
|
static TURBO68K_UINT16 ReadWordDebug(TURBO68K_UINT32 addr);
|
||||||
|
static TURBO68K_UINT32 ReadLongDebug(TURBO68K_UINT32 addr);
|
||||||
|
static void WriteByteDebug(TURBO68K_UINT32 addr, TURBO68K_UINT8 data);
|
||||||
|
static void WriteWordDebug(TURBO68K_UINT32 addr, TURBO68K_UINT16 data);
|
||||||
|
static void WriteLongDebug(TURBO68K_UINT32 addr, TURBO68K_UINT32 data);
|
||||||
|
|
||||||
|
static TURBO68K_UINT8 ReadByteDirect(TURBO68K_UINT32 addr);
|
||||||
|
static TURBO68K_UINT16 ReadWordDirect(TURBO68K_UINT32 addr);
|
||||||
|
static TURBO68K_UINT32 ReadLongDirect(TURBO68K_UINT32 addr);
|
||||||
|
static void WriteByteDirect(TURBO68K_UINT32 addr, TURBO68K_UINT8 data);
|
||||||
|
static void WriteWordDirect(TURBO68K_UINT32 addr, TURBO68K_UINT16 data);
|
||||||
|
static void WriteLongDirect(TURBO68K_UINT32 addr, TURBO68K_UINT32 data);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* CCPUDebug implementation for the Turbo68K Motorola 68000 emulator.
|
||||||
|
*/
|
||||||
|
class CTurbo68KDebug : public C68KDebug
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
char m_drNames[8][3];
|
||||||
|
char m_arNames[8][3];
|
||||||
|
|
||||||
|
char m_mSlotStr[32][20];
|
||||||
|
char m_sSlotStr[32][20];
|
||||||
|
char m_regStr[16][12];
|
||||||
|
|
||||||
|
UINT32 m_resetAddr;
|
||||||
|
|
||||||
|
public:
|
||||||
|
CTurbo68KDebug();
|
||||||
|
|
||||||
|
virtual ~CTurbo68KDebug();
|
||||||
|
|
||||||
|
// CCPUDebug methods
|
||||||
|
|
||||||
|
void AttachToCPU();
|
||||||
|
|
||||||
|
void DetachFromCPU();
|
||||||
|
|
||||||
|
UINT32 GetResetAddr();
|
||||||
|
|
||||||
|
UINT32 GetSP();
|
||||||
|
|
||||||
|
bool UpdatePC(UINT32 pc);
|
||||||
|
|
||||||
|
bool ForceException(CException *ex);
|
||||||
|
|
||||||
|
bool ForceInterrupt(CInterrupt *in);
|
||||||
|
|
||||||
|
UINT64 ReadMem(UINT32 addr, unsigned dataSize);
|
||||||
|
|
||||||
|
bool WriteMem(UINT32 addr, unsigned dataSize, UINT64 data);
|
||||||
|
};
|
||||||
|
|
||||||
|
//
|
||||||
|
// Inlined functions
|
||||||
|
//
|
||||||
|
|
||||||
|
typedef TURBO68K_UINT8 (*ReadByteFPtr)(TURBO68K_UINT32);
|
||||||
|
typedef TURBO68K_UINT16 (*ReadWordFPtr)(TURBO68K_UINT32);
|
||||||
|
typedef TURBO68K_UINT32 (*ReadLongFPtr)(TURBO68K_UINT32);
|
||||||
|
typedef void (*WriteByteFPtr)(TURBO68K_UINT32, TURBO68K_UINT8);
|
||||||
|
typedef void (*WriteWordFPtr)(TURBO68K_UINT32, TURBO68K_UINT16);
|
||||||
|
typedef void (*WriteLongFPtr)(TURBO68K_UINT32, TURBO68K_UINT32);
|
||||||
|
|
||||||
|
inline TURBO68K_UINT8 ReadByteDirect(TURBO68K_UINT32 addr)
|
||||||
|
{
|
||||||
|
#if USE_NATIVE_READ
|
||||||
|
Turbo68KSetReadByte(origRead8Regions, TURBO68K_NULL);
|
||||||
|
TURBO68K_UINT8 data = Turbo68KReadByte(addr);
|
||||||
|
Turbo68KSetReadByte(debugRead8Regions, TURBO68K_NULL);
|
||||||
|
return data;
|
||||||
|
#else
|
||||||
|
for (TURBO68K_DATAREGION *region = origRead8Regions; region->ptr != TURBO68K_NULL || region->handler != TURBO68K_NULL; region++)
|
||||||
|
{
|
||||||
|
if (region->base <= addr && addr <= region->limit)
|
||||||
|
{
|
||||||
|
if (region->ptr != TURBO68K_NULL)
|
||||||
|
{
|
||||||
|
// Turbo68K requires native memory to be byte swapped, so must reverse this when reading bytes
|
||||||
|
TURBO68K_UINT8 *dataP = (TURBO68K_UINT8*)(region->ptr + (addr^1));
|
||||||
|
return *dataP;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ReadByteFPtr fPtr = (ReadByteFPtr)region->handler;
|
||||||
|
return fPtr(addr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
inline TURBO68K_UINT16 ReadWordDirect(TURBO68K_UINT32 addr)
|
||||||
|
{
|
||||||
|
#if USE_NATIVE_READ
|
||||||
|
Turbo68KSetReadWord(origRead16Regions, TURBO68K_NULL);
|
||||||
|
TURBO68K_UINT16 data = Turbo68KReadWord(addr);
|
||||||
|
Turbo68KSetReadWord(debugRead16Regions, TURBO68K_NULL);
|
||||||
|
return data;
|
||||||
|
#else
|
||||||
|
for (TURBO68K_DATAREGION *region = origRead16Regions; region->ptr != TURBO68K_NULL || region->handler != TURBO68K_NULL; region++)
|
||||||
|
{
|
||||||
|
if (region->base <= addr && addr <= region->limit)
|
||||||
|
{
|
||||||
|
if (region->ptr != TURBO68K_NULL)
|
||||||
|
{
|
||||||
|
// Turbo68K requires native memory to be byte swapped, so must reverse this when reading bytes
|
||||||
|
TURBO68K_UINT16 *dataP = (TURBO68K_UINT16*)(region->ptr + addr);
|
||||||
|
return *dataP;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ReadWordFPtr fPtr = (ReadWordFPtr)region->handler;
|
||||||
|
return fPtr(addr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
inline TURBO68K_UINT32 ReadLongDirect(TURBO68K_UINT32 addr)
|
||||||
|
{
|
||||||
|
#if USE_NATIVE_READ
|
||||||
|
Turbo68KSetReadLong(origRead32Regions, TURBO68K_NULL);
|
||||||
|
TURBO68K_UINT32 data = Turbo68KReadLong(addr);
|
||||||
|
Turbo68KSetReadLong(debugRead32Regions, TURBO68K_NULL);
|
||||||
|
return data;
|
||||||
|
#else
|
||||||
|
for (TURBO68K_DATAREGION *region = origRead32Regions; region->ptr != TURBO68K_NULL || region->handler != TURBO68K_NULL; region++)
|
||||||
|
{
|
||||||
|
if (region->base <= addr && addr <= region->limit)
|
||||||
|
{
|
||||||
|
if (region->ptr != TURBO68K_NULL)
|
||||||
|
{
|
||||||
|
// Turbo68K requires native memory to be byte swapped, so must reverse this when reading bytes
|
||||||
|
TURBO68K_UINT16 *dataP = (TURBO68K_UINT16*)(region->ptr + addr);
|
||||||
|
return (TURBO68K_UINT32)dataP[1] | ((TURBO68K_UINT32)dataP[0])<<16;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ReadLongFPtr fPtr = (ReadLongFPtr)region->handler;
|
||||||
|
return fPtr(addr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void WriteByteDirect(TURBO68K_UINT32 addr, TURBO68K_UINT8 data)
|
||||||
|
{
|
||||||
|
#if USE_NATIVE_WRITE
|
||||||
|
Turbo68KSetWriteByte(origWrite8Regions, TURBO68K_NULL);
|
||||||
|
Turbo68KWriteByte(addr, data);
|
||||||
|
Turbo68KSetWriteByte(debugWrite8Regions, TURBO68K_NULL);
|
||||||
|
#else
|
||||||
|
for (TURBO68K_DATAREGION *region = origWrite8Regions; region->ptr != TURBO68K_NULL || region->handler != TURBO68K_NULL; region++)
|
||||||
|
{
|
||||||
|
if (region->base <= addr && addr <= region->limit)
|
||||||
|
{
|
||||||
|
if (region->ptr != TURBO68K_NULL)
|
||||||
|
{
|
||||||
|
// Turbo68K requires native memory to be byte swapped, so must reverse this when writing bytes
|
||||||
|
TURBO68K_UINT8 *dataP = (TURBO68K_UINT8*)(region->ptr + (addr^1));
|
||||||
|
*dataP = data;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
WriteByteFPtr fPtr = (WriteByteFPtr)region->handler;
|
||||||
|
fPtr(addr, data);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void WriteWordDirect(TURBO68K_UINT32 addr, TURBO68K_UINT16 data)
|
||||||
|
{
|
||||||
|
#if USE_NATIVE_WRITE
|
||||||
|
Turbo68KSetWriteWord(origWrite16Regions, TURBO68K_NULL);
|
||||||
|
Turbo68KWriteWord(addr, data);
|
||||||
|
Turbo68KSetWriteWord(debugWrite16Regions, TURBO68K_NULL);
|
||||||
|
#else
|
||||||
|
for (TURBO68K_DATAREGION *region = origWrite16Regions; region->ptr != TURBO68K_NULL || region->handler != TURBO68K_NULL; region++)
|
||||||
|
{
|
||||||
|
if (region->base <= addr && addr <= region->limit)
|
||||||
|
{
|
||||||
|
if (region->ptr != TURBO68K_NULL)
|
||||||
|
{
|
||||||
|
// Turbo68K requires native memory to be byte swapped, so must reverse this when writing bytes
|
||||||
|
TURBO68K_UINT16 *dataP = (TURBO68K_UINT16*)(region->ptr + addr);
|
||||||
|
*dataP = data;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
WriteWordFPtr fPtr = (WriteWordFPtr)region->handler;
|
||||||
|
fPtr(addr, data);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void WriteLongDirect(TURBO68K_UINT32 addr, TURBO68K_UINT32 data)
|
||||||
|
{
|
||||||
|
#if USE_NATIVE_WRITE
|
||||||
|
Turbo68KSetWriteLong(origWrite32Regions, TURBO68K_NULL);
|
||||||
|
Turbo68KWriteLong(addr, data);
|
||||||
|
Turbo68KSetWriteLong(debugWrite32Regions, TURBO68K_NULL);
|
||||||
|
#else
|
||||||
|
for (TURBO68K_DATAREGION *region = origWrite32Regions; region->ptr != TURBO68K_NULL || region->handler != TURBO68K_NULL; region++)
|
||||||
|
{
|
||||||
|
if (region->base <= addr && addr <= region->limit)
|
||||||
|
{
|
||||||
|
if (region->ptr != TURBO68K_NULL)
|
||||||
|
{
|
||||||
|
// Turbo68K requires native memory to be byte swapped, so must reverse this when writing bytes
|
||||||
|
TURBO68K_UINT16 *dataP = (TURBO68K_UINT16*)(region->ptr + addr);
|
||||||
|
dataP[0] = data>>16;
|
||||||
|
dataP[1] = data&0xFFFF;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
WriteLongFPtr fPtr = (WriteLongFPtr)region->handler;
|
||||||
|
fPtr(addr, data);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // INCLUDED_TURBO68KDEBUG_H
|
||||||
|
#endif // SUPERMODEL_DEBUGGER
|
|
@ -18,7 +18,7 @@ namespace Debugger
|
||||||
//
|
//
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO - tidy upf this function, ie do some proper parsing of commands - it is a mess!
|
// TODO - tidy up this function, ie do some proper parsing of commands - it is a mess!
|
||||||
void CConsoleDebugger::WaitCommand(CCPUDebug *cpu)
|
void CConsoleDebugger::WaitCommand(CCPUDebug *cpu)
|
||||||
{
|
{
|
||||||
m_cpu = cpu;
|
m_cpu = cpu;
|
||||||
|
@ -485,7 +485,7 @@ namespace Debugger
|
||||||
}
|
}
|
||||||
|
|
||||||
ex->trap = false;
|
ex->trap = false;
|
||||||
Print("Trap for exception %s removed.\n", ex->name);
|
Print("Trap for exceptions of type %s removed.\n", ex->id);
|
||||||
}
|
}
|
||||||
else if (CheckToken(token, "i", "interrupt"))
|
else if (CheckToken(token, "i", "interrupt"))
|
||||||
{
|
{
|
||||||
|
@ -503,7 +503,7 @@ namespace Debugger
|
||||||
}
|
}
|
||||||
|
|
||||||
in->trap = false;
|
in->trap = false;
|
||||||
Print("Trap for interrupt %s removed.\n", in->name);
|
Print("Trap for interrupts ot type %s removed.\n", in->id);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -725,7 +725,7 @@ namespace Debugger
|
||||||
else if (CheckToken(token, "ral", "removealllabels")) // removealllabels
|
else if (CheckToken(token, "ral", "removealllabels")) // removealllabels
|
||||||
{
|
{
|
||||||
m_cpu->RemoveAllLabels();
|
m_cpu->RemoveAllLabels();
|
||||||
Print("All custom labels removed.\m");
|
Print("All custom labels removed.\n");
|
||||||
}
|
}
|
||||||
else if (CheckToken(token, "ac", "addcomment")) // addcomment <addr> <text...>
|
else if (CheckToken(token, "ac", "addcomment")) // addcomment <addr> <text...>
|
||||||
{
|
{
|
||||||
|
|
|
@ -16,9 +16,6 @@ namespace Debugger
|
||||||
m_loadEmuState(false), m_saveEmuState(false), m_resetEmu(false)
|
m_loadEmuState(false), m_saveEmuState(false), m_resetEmu(false)
|
||||||
{
|
{
|
||||||
AddCPU(new CPPCDebug());
|
AddCPU(new CPPCDebug());
|
||||||
#ifdef SUPERMODEL_SOUND
|
|
||||||
AddCPU(new C68KDebug());
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void CSupermodelDebugger::WaitCommand(CCPUDebug *cpu)
|
void CSupermodelDebugger::WaitCommand(CCPUDebug *cpu)
|
||||||
|
|
Loading…
Reference in a new issue