Supermodel/Src/Debugger/CPU/Turbo68KDebug.h
Nik Henson e8e02ba685 Changes to debugger classes:
- updated debugger classes to compile again with all recent changes.
- improved debugger classes to allow them to work in multi-threaded emulator and be able to handle CPUs on different threads.
- added debug classes for new Z80 and Musashi 68K CPU cores.
- added logging of cycle counts and frames.
- moved all Supermodel specific code & configuration to CSupermodelDebugger.
- added all Model 3 CPUs (PPC, sound board 68K, DSB 68K/Z80 and drive board Z80) to CSupermodelDebugger.
- added persisting of custom entry points in saved debug state to CCodeAnalyser.
- fixed bug with listing I/O ports in CConsoleDebugger and added displaying of cycle counts and CPU speeds when listing CPUs.
2011-09-18 21:59:23 +00:00

316 lines
9.4 KiB
C++

#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 TBO68K_REG_SP 0
#define TBO68K_REG_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];
UINT32 m_resetAddr;
protected:
UINT32 GetSP();
public:
CTurbo68KDebug(const char *name);
virtual ~CTurbo68KDebug();
// 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);
};
//
// 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