First pass at adding a 'dirty page' infrastructure to the System class.

The idea is that all direct-access pokes will set a flag indicating that
the page containing the poked address is set to be dirty.  Devices that
handle their own pokes will have to be updated to set this dirty flag too.
Overall, the point is to enable the debugger to know whether cart space
has been modified, and use that knowledge to selectively do a
re-disassembly.


git-svn-id: svn://svn.code.sf.net/p/stella/code/trunk@1973 8b62c5a3-ac7e-4cc8-8f21-d9a121418aba
This commit is contained in:
stephena 2010-03-26 00:59:56 +00:00
parent 4ca87ba76b
commit 2b384e2353
2 changed files with 66 additions and 3 deletions

View File

@ -44,8 +44,9 @@ System::System(uInt16 n, uInt16 m)
// Create a new random number generator // Create a new random number generator
myRandom = new Random(); myRandom = new Random();
// Allocate page table // Allocate page table and dirty list
myPageAccessTable = new PageAccess[myNumberOfPages]; myPageAccessTable = new PageAccess[myNumberOfPages];
myPageIsDirtyTable = new bool[myNumberOfPages];
// Initialize page access table // Initialize page access table
PageAccess access; PageAccess access;
@ -73,8 +74,9 @@ System::~System()
// Free the M6502 that I own // Free the M6502 that I own
delete myM6502; delete myM6502;
// Free my page access table // Free my page access table and dirty list
delete[] myPageAccessTable; delete[] myPageAccessTable;
delete[] myPageIsDirtyTable;
// Free the random number generator // Free the random number generator
delete myRandom; delete myRandom;
@ -172,6 +174,32 @@ const System::PageAccess& System::getPageAccess(uInt16 page)
return myPageAccessTable[page]; return myPageAccessTable[page];
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void System::setDirtyAddress(uInt16 addr)
{
myPageIsDirtyTable[(addr & myAddressMask) >> myPageShift] = true;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool System::isDirtyRange(uInt16 start_addr, uInt16 end_addr)
{
uInt16 start_page = (start_addr & myAddressMask) >> myPageShift;
uInt16 end_page = (end_addr & myAddressMask) >> myPageShift;
for(uInt16 page = start_page; page <= end_page; ++page)
if(myPageIsDirtyTable[page])
return true;
return false;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void System::clearDirtyAddresses()
{
for(uInt32 i = 0; i < myNumberOfPages; ++i)
myPageIsDirtyTable[i] = false;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
System::System(const System& s) System::System(const System& s)
: myAddressMask(s.myAddressMask), : myAddressMask(s.myAddressMask),
@ -218,15 +246,21 @@ uInt8 System::peek(uInt16 addr)
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void System::poke(uInt16 addr, uInt8 value) void System::poke(uInt16 addr, uInt8 value)
{ {
PageAccess& access = myPageAccessTable[(addr & myAddressMask) >> myPageShift]; uInt16 page = (addr & myAddressMask) >> myPageShift;
PageAccess& access = myPageAccessTable[page];
// See if this page uses direct accessing or not // See if this page uses direct accessing or not
if(access.directPokeBase != 0) if(access.directPokeBase != 0)
{ {
// Since we have direct access to this poke, we can dirty its page
myPageIsDirtyTable[page] = true;
*(access.directPokeBase + (addr & myPageMask)) = value; *(access.directPokeBase + (addr & myPageMask)) = value;
} }
else else
{ {
// The specific device is responsible for setting the dirty flag
// We can't automatically set it, since not all pokes actually
// succeed and modify a page
access.device->poke(addr, value); access.device->poke(addr, value);
} }

View File

@ -269,6 +269,11 @@ class System : public Serializable
No masking of the address occurs before it's sent to the device No masking of the address occurs before it's sent to the device
mapped at the address. mapped at the address.
This method sets the 'page dirty' flag for direct-access pokes.
If the device has taken responsibility for handling the poke,
it must also update the 'page dirty' flag with a call to
System::setDirtyAddress().
@param address The address where the value should be stored @param address The address where the value should be stored
@param value The value to be stored at the address @param value The value to be stored at the address
*/ */
@ -331,6 +336,27 @@ class System : public Serializable
*/ */
const PageAccess& getPageAccess(uInt16 page); const PageAccess& getPageAccess(uInt16 page);
/**
Mark the page containing this address as being dirty.
@param addr Determines the page that is dirty
*/
void setDirtyAddress(uInt16 addr);
/**
Answer whether any pages in given range of addresses have been
marked as dirty.
@param start_addr The start address; determines the start page
@param end_addr The end address; determines the end page
*/
bool isDirtyRange(uInt16 start_addr, uInt16 end_addr);
/**
Mark all pages as clean (ie, turn off the dirty flag).
*/
void clearDirtyAddresses();
/** /**
Save the current state of this system to the given Serializer. Save the current state of this system to the given Serializer.
@ -370,6 +396,9 @@ class System : public Serializable
// Pointer to a dynamically allocated array of PageAccess structures // Pointer to a dynamically allocated array of PageAccess structures
PageAccess* myPageAccessTable; PageAccess* myPageAccessTable;
// Pointer to a dynamically allocated array for dirty pages
bool* myPageIsDirtyTable;
// Array of all the devices attached to the system // Array of all the devices attached to the system
Device* myDevices[100]; Device* myDevices[100];