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;
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)
{
bool addLine = false;
out << "\n\n;-----------------------------------------------------------\n"
<< "; RIOT RAM (zero-page) labels\n"
<< ";-----------------------------------------------------------\n\n";
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] &&
myUserLabels.find(addr) == myUserLabels.end()) {
if (addLine)
out << "\n";
out << ALIGN(16) << ourZPMnemonic[addr - 0x80] << "= $"
<< Base::HEX2 << right << (addr) << "\n";
<< Base::HEX2 << right << (addr)
<< (stackUsed ? " ; (s)" : "") << "\n";
addLine = false;
} else if (mySystem.getAccessFlags(addr) & DATA) {
} else if (ramUsed|stackUsed) {
if (addLine)
out << "\n";
out << ALIGN(18) << ";" << "$"
<< Base::HEX2 << right << (addr) << " (i)\n";
<< Base::HEX2 << right << (addr)
<< " (" << (ramUsed ? "i" : "") << (stackUsed ? "s" : "") << ")\n";
addLine = false;
} else
addLine = true;

View File

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

View File

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

View File

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

View File

@ -24,6 +24,7 @@
#include "Switches.hxx"
#include "System.hxx"
#ifdef DEBUGGER_SUPPORT
//#include "Debugger.hxx"
#include "CartDebug.hxx"
#endif
@ -38,13 +39,9 @@ M6532::M6532(const Console& console, const Settings& settings)
mySetTimerCycle(0), myLastCycle(0),
myDDRA(0), myDDRB(0), myOutA(0), myOutB(0),
myInterruptFlag(false),
myEdgeDetectPositive(false)
{
#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
myEdgeDetectPositive(false),
myRAMAccessBase(nullptr)
{
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -57,7 +54,7 @@ void M6532::reset()
else
memset(myRAM, 0, 128);
myTimer = mySystem->randGenerator().next() & 0xFF;
myTimer = mySystem->randGenerator().next() & 0xff;
myDivider = 1024;
mySubTimer = 0;
myTimerWrapped = false;
@ -80,6 +77,8 @@ void M6532::reset()
// Let the controllers know about the reset
myConsole.leftController().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
// lower 4K of the 2600 address space are mapped here
// The two types of addresses are differentiated in peek/poke as follows:
// (addr & 0x0200) == 0x0000 is ZP RAM (A9 is 0)
// (addr & 0x0200) != 0x0000 is IO (A9 is 1)
for(uInt16 addr = 0; addr < 0x1000; addr += System::PAGE_SIZE)
{
if((addr & 0x0080) == 0x0080) // RIOT addresses
{
#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
// (addr & 0x0200) == 0x0200 is IO (A9 is 1)
// (addr & 0x0300) == 0x0100 is Stack (A8 is 1, A9 is 0)
// (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) {
//access.codeAccessBase = &myRAMAccessBase[addr & 0x7f];
mySystem->setPageAccess(addr, access);
}
}
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -188,7 +180,7 @@ uInt8 M6532::peek(uInt16 addr)
// A9 = 1 is read from I/O
// A9 = 0 is read from RAM
if((addr & 0x0200) == 0x0000)
return myRAM[addr & 0x7F];
return myRAM[addr & 0x007f];
switch(addr & 0x07)
{
@ -257,18 +249,18 @@ bool M6532::poke(uInt16 addr, uInt8 value)
// A9 = 0 is write to RAM
if((addr & 0x0200) == 0x0000)
{
myRAM[addr & 0x7F] = value;
myRAM[addr & 0x007f] = value;
return true;
}
// A2 distinguishes I/O registers from the timer
// A2 = 1 is write to timer
// 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 = 0 is write to edge detect control
if(addr & 0x10)
if((addr & 0x10) != 0)
setTimerRegister(value, addr & 0x03); // A1A0 determines interval
else
myEdgeDetectPositive = addr & 0x01; // A0 determines direction
@ -463,3 +455,52 @@ uInt32 M6532::timerClocks() const
{
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();
Int32 intimClocks();
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:
// Accessible bits in the interrupt flag register
@ -198,9 +209,16 @@ class M6532 : public Device
// Last value written to the timer registers
uInt8 myOutTimer[4];
// The array containing information about every address of ZP RAM
// and IO space, and how/whether it is accessed.
BytePtr myAccessBase;
// The arrays containing information about every byte of RIOT
// indicating whether and how (RW) it is used.
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:
// Following constructors and assignment operators not supported