refined access tracking for ZP, Stack and IO addresses

improved RIOT RAM output in Distella
This commit is contained in:
thrust26 2017-09-16 17:38:37 +02:00
parent 03c1ab17fd
commit 3bf809a137
6 changed files with 104 additions and 36 deletions

View File

@ -1111,26 +1111,34 @@ string CartDebug::saveDisassembly()
addrUsed = false; addrUsed = false;
for(uInt16 addr = 0x80; addr <= 0xFF; ++addr) for(uInt16 addr = 0x80; addr <= 0xFF; ++addr)
addrUsed = addrUsed || myReserved.ZPRAM[addr-0x80]; addrUsed = addrUsed || myReserved.ZPRAM[addr-0x80]
|| (mySystem.getAccessFlags(addr) & (DATA | WRITE))
|| (mySystem.getAccessFlags(addr|0x100) & (DATA | WRITE));
if(addrUsed) if(addrUsed)
{ {
bool addLine = false; bool addLine = false;
out << "\n\n;-----------------------------------------------------------\n" out << "\n\n;-----------------------------------------------------------\n"
<< "; RIOT RAM (zero-page) labels\n" << "; RIOT RAM (zero-page) labels\n"
<< ";-----------------------------------------------------------\n\n"; << ";-----------------------------------------------------------\n\n";
for (uInt16 addr = 0x80; addr <= 0xFF; ++addr) { for (uInt16 addr = 0x80; addr <= 0xFF; ++addr) {
bool ramUsed = (mySystem.getAccessFlags(addr) & (DATA | WRITE));
bool stackUsed = (mySystem.getAccessFlags(addr|0x100) & (DATA | WRITE));
if (myReserved.ZPRAM[addr - 0x80] && if (myReserved.ZPRAM[addr - 0x80] &&
myUserLabels.find(addr) == myUserLabels.end()) { myUserLabels.find(addr) == myUserLabels.end()) {
if (addLine) if (addLine)
out << "\n"; out << "\n";
out << ALIGN(16) << ourZPMnemonic[addr - 0x80] << "= $" out << ALIGN(16) << ourZPMnemonic[addr - 0x80] << "= $"
<< Base::HEX2 << right << (addr) << "\n"; << Base::HEX2 << right << (addr)
<< (stackUsed ? " ; (s)" : "") << "\n";
addLine = false; addLine = false;
} else if (mySystem.getAccessFlags(addr) & DATA) { } else if (ramUsed|stackUsed) {
if (addLine) if (addLine)
out << "\n"; out << "\n";
out << ALIGN(18) << ";" << "$" out << ALIGN(18) << ";" << "$"
<< Base::HEX2 << right << (addr) << " (i)\n"; << Base::HEX2 << right << (addr)
<< " (" << (ramUsed ? "i" : "") << (stackUsed ? "s" : "") << ")\n";
addLine = false; addLine = false;
} else } else
addLine = true; addLine = true;

View File

@ -598,6 +598,7 @@ void DiStella::disasmPass1(CartDebug::AddressList& debuggerAddresses)
CartDebug::CODE)) { CartDebug::CODE)) {
//if (Debugger::debugger().getAccessFlags(k) & //if (Debugger::debugger().getAccessFlags(k) &
// (CartDebug::DATA | CartDebug::GFX | CartDebug::PGFX)) { // (CartDebug::DATA | CartDebug::GFX | CartDebug::PGFX)) {
// TODO: this should never happen, remove when we are sure
Uint8 flags = Debugger::debugger().getAccessFlags(k); Uint8 flags = Debugger::debugger().getAccessFlags(k);
myPCEnd = k - 1; myPCEnd = k - 1;
break; break;

View File

@ -3044,7 +3044,7 @@ case 0x68:
// TODO - add tracking for this opcode // TODO - add tracking for this opcode
{ {
peek(0x0100 + SP++, DISASM_NONE); peek(0x0100 + SP++, DISASM_NONE);
A = peek(0x0100 + SP, DISASM_NONE); A = peek(0x0100 + SP, DISASM_DATA);
notZ = A; notZ = A;
N = A & 0x80; N = A & 0x80;
} }
@ -3059,7 +3059,7 @@ case 0x28:
// TODO - add tracking for this opcode // TODO - add tracking for this opcode
{ {
peek(0x0100 + SP++, DISASM_NONE); peek(0x0100 + SP++, DISASM_NONE);
PS(peek(0x0100 + SP, DISASM_NONE)); PS(peek(0x0100 + SP, DISASM_DATA));
} }
break; break;

View File

@ -736,14 +736,14 @@ define(M6502_PHP, `{
define(M6502_PLA, `{ define(M6502_PLA, `{
peek(0x0100 + SP++, DISASM_NONE); peek(0x0100 + SP++, DISASM_NONE);
A = peek(0x0100 + SP, DISASM_NONE); A = peek(0x0100 + SP, DISASM_DATA);
notZ = A; notZ = A;
N = A & 0x80; N = A & 0x80;
}') }')
define(M6502_PLP, `{ define(M6502_PLP, `{
peek(0x0100 + SP++, DISASM_NONE); peek(0x0100 + SP++, DISASM_NONE);
PS(peek(0x0100 + SP, DISASM_NONE)); PS(peek(0x0100 + SP, DISASM_DATA));
}') }')
define(M6502_RLA, `{ define(M6502_RLA, `{

View File

@ -24,6 +24,7 @@
#include "Switches.hxx" #include "Switches.hxx"
#include "System.hxx" #include "System.hxx"
#ifdef DEBUGGER_SUPPORT #ifdef DEBUGGER_SUPPORT
//#include "Debugger.hxx"
#include "CartDebug.hxx" #include "CartDebug.hxx"
#endif #endif
@ -38,13 +39,9 @@ M6532::M6532(const Console& console, const Settings& settings)
mySetTimerCycle(0), myLastCycle(0), mySetTimerCycle(0), myLastCycle(0),
myDDRA(0), myDDRB(0), myOutA(0), myOutB(0), myDDRA(0), myDDRB(0), myOutA(0), myOutB(0),
myInterruptFlag(false), myInterruptFlag(false),
myEdgeDetectPositive(false) myEdgeDetectPositive(false),
{ myRAMAccessBase(nullptr)
#ifdef DEBUGGER_SUPPORT {
constexpr uInt32 size = 0x80 + 0x1F; // first 0x80 bytes are for ZP, rest is for IO
myAccessBase = make_unique<uInt8[]>(size);
memset(myAccessBase.get(), CartDebug::NONE, size);
#endif
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -57,7 +54,7 @@ void M6532::reset()
else else
memset(myRAM, 0, 128); memset(myRAM, 0, 128);
myTimer = mySystem->randGenerator().next() & 0xFF; myTimer = mySystem->randGenerator().next() & 0xff;
myDivider = 1024; myDivider = 1024;
mySubTimer = 0; mySubTimer = 0;
myTimerWrapped = false; myTimerWrapped = false;
@ -80,6 +77,8 @@ void M6532::reset()
// Let the controllers know about the reset // Let the controllers know about the reset
myConsole.leftController().reset(); myConsole.leftController().reset();
myConsole.rightController().reset(); myConsole.rightController().reset();
createAccessBases();
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -162,21 +161,14 @@ void M6532::installDelegate(System& system, Device& device)
// That is, all mirrors of ZP RAM ($80 - $FF) and IO ($280 - $29F) in the // That is, all mirrors of ZP RAM ($80 - $FF) and IO ($280 - $29F) in the
// lower 4K of the 2600 address space are mapped here // lower 4K of the 2600 address space are mapped here
// The two types of addresses are differentiated in peek/poke as follows: // The two types of addresses are differentiated in peek/poke as follows:
// (addr & 0x0200) == 0x0000 is ZP RAM (A9 is 0) // (addr & 0x0200) == 0x0200 is IO (A9 is 1)
// (addr & 0x0200) != 0x0000 is IO (A9 is 1) // (addr & 0x0300) == 0x0100 is Stack (A8 is 1, A9 is 0)
for(uInt16 addr = 0; addr < 0x1000; addr += System::PAGE_SIZE) // (addr & 0x0300) == 0x0000 is ZP RAM (A8 is 0, A9 is 0)
{ for (uInt16 addr = 0; addr < 0x1000; addr += System::PAGE_SIZE)
if((addr & 0x0080) == 0x0080) // RIOT addresses if ((addr & 0x0080) == 0x0080) {
{ //access.codeAccessBase = &myRAMAccessBase[addr & 0x7f];
#ifdef DEBUGGER_SUPPORT
if((addr & 0x0200) == 0x0000) // ZP RAM addresses
access.codeAccessBase = &myAccessBase[addr & 0x7F];
else // IO addresses
access.codeAccessBase = &myAccessBase[0x80 + (addr & 0x1F)];
#endif
mySystem->setPageAccess(addr, access); mySystem->setPageAccess(addr, access);
} }
}
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -188,7 +180,7 @@ uInt8 M6532::peek(uInt16 addr)
// A9 = 1 is read from I/O // A9 = 1 is read from I/O
// A9 = 0 is read from RAM // A9 = 0 is read from RAM
if((addr & 0x0200) == 0x0000) if((addr & 0x0200) == 0x0000)
return myRAM[addr & 0x7F]; return myRAM[addr & 0x007f];
switch(addr & 0x07) switch(addr & 0x07)
{ {
@ -257,18 +249,18 @@ bool M6532::poke(uInt16 addr, uInt8 value)
// A9 = 0 is write to RAM // A9 = 0 is write to RAM
if((addr & 0x0200) == 0x0000) if((addr & 0x0200) == 0x0000)
{ {
myRAM[addr & 0x7F] = value; myRAM[addr & 0x007f] = value;
return true; return true;
} }
// A2 distinguishes I/O registers from the timer // A2 distinguishes I/O registers from the timer
// A2 = 1 is write to timer // A2 = 1 is write to timer
// A2 = 0 is write to I/O // A2 = 0 is write to I/O
if(addr & 0x04) if((addr & 0x04) != 0)
{ {
// A4 = 1 is write to TIMxT (x = 1, 8, 64, 1024) // A4 = 1 is write to TIMxT (x = 1, 8, 64, 1024)
// A4 = 0 is write to edge detect control // A4 = 0 is write to edge detect control
if(addr & 0x10) if((addr & 0x10) != 0)
setTimerRegister(value, addr & 0x03); // A1A0 determines interval setTimerRegister(value, addr & 0x03); // A1A0 determines interval
else else
myEdgeDetectPositive = addr & 0x01; // A0 determines direction myEdgeDetectPositive = addr & 0x01; // A0 determines direction
@ -463,3 +455,52 @@ uInt32 M6532::timerClocks() const
{ {
return uInt32(mySystem->cycles() - mySetTimerCycle); return uInt32(mySystem->cycles() - mySetTimerCycle);
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void M6532::createAccessBases()
{
#ifdef DEBUGGER_SUPPORT
myRAMAccessBase = make_unique<uInt8[]>(RAM_SIZE);
memset(myRAMAccessBase.get(), CartDebug::NONE, RAM_SIZE);
myStackAccessBase = make_unique<uInt8[]>(STACK_SIZE);
memset(myStackAccessBase.get(), CartDebug::NONE, STACK_SIZE);
myIOAccessBase = make_unique<uInt8[]>(IO_SIZE);
memset(myIOAccessBase.get(), CartDebug::NONE, IO_SIZE);
#else
myRAMAccessBase = myStackAccessBase = myIOAccessBase = nullptr;
#endif
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
uInt8 M6532::getAccessFlags(uInt16 address) const
{
if (address & IO_BIT)
return myIOAccessBase[address & IO_MASK];
else if (address & STACK_BIT)
return myStackAccessBase[address & STACK_MASK];
else
return myRAMAccessBase[address & RAM_MASK];
return 0;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void M6532::setAccessFlags(uInt16 address, uInt8 flags)
{
// ignore none flag
if (flags != CartDebug::NONE) {
if (address & IO_BIT)
myIOAccessBase[address & IO_MASK] |= flags;
else if (address & STACK_BIT)
// the first access is assumed as initialization
if (!(myStackAccessBase[address & STACK_MASK] & CartDebug::ROW))
myStackAccessBase[address & STACK_MASK] |= CartDebug::ROW;
else
myStackAccessBase[address & STACK_MASK] |= flags;
else
// the first access is assumed as initialization
if (!(myRAMAccessBase[address & RAM_MASK] & CartDebug::ROW))
myRAMAccessBase[address & RAM_MASK] |= CartDebug::ROW;
else
myRAMAccessBase[address & RAM_MASK] |= flags;
}
}

View File

@ -139,6 +139,17 @@ class M6532 : public Device
uInt8 timint(); uInt8 timint();
Int32 intimClocks(); Int32 intimClocks();
uInt32 timerClocks() const; uInt32 timerClocks() const;
#ifdef DEBUGGER_SUPPORT
void createAccessBases();
/**
Query/change the given address type to use the given disassembly flags
@param address The address to modify
@param flags A bitfield of DisasmType directives for the given address
*/
uInt8 getAccessFlags(uInt16 address) const override;
void setAccessFlags(uInt16 address, uInt8 flags) override;
#endif // DEBUGGER_SUPPORT
private: private:
// Accessible bits in the interrupt flag register // Accessible bits in the interrupt flag register
@ -198,9 +209,16 @@ class M6532 : public Device
// Last value written to the timer registers // Last value written to the timer registers
uInt8 myOutTimer[4]; uInt8 myOutTimer[4];
// The array containing information about every address of ZP RAM // The arrays containing information about every byte of RIOT
// and IO space, and how/whether it is accessed. // indicating whether and how (RW) it is used.
BytePtr myAccessBase; BytePtr myRAMAccessBase;
BytePtr myStackAccessBase;
BytePtr myIOAccessBase;
static constexpr uInt16
RAM_SIZE = 0x80, RAM_MASK = RAM_SIZE - 1,
STACK_SIZE = 0x80, STACK_MASK = STACK_SIZE - 1, STACK_BIT = 0x100,
IO_SIZE = 0x20, IO_MASK = IO_SIZE - 1, IO_BIT = 0x200;
private: private:
// Following constructors and assignment operators not supported // Following constructors and assignment operators not supported