Reverted TIA changes that affect late NUSIZx changes. More work is needed

in this area.

Added commandline argument 'thumb.trapfatal', which causes fatal errors in
the Thumb ARM emulation to really be treated as fatal (ie, the emulation stops
and throws an exception).  This is enabled by default (as it always should be).
When disabled, fatal errors simply log the error and continue with emulation.
This was added because the current HarmonyCart ARM code isn't always exactly
compatible with the emulation in Stella, and there is a lagtime from when
Harmony implements something to when the same functionality is added to Stella.


git-svn-id: svn://svn.code.sf.net/p/stella/code/trunk@2279 8b62c5a3-ac7e-4cc8-8f21-d9a121418aba
This commit is contained in:
stephena 2011-11-07 22:50:23 +00:00
parent 1d5ea6a9eb
commit bb63ea3dd1
6 changed files with 54 additions and 38 deletions

View File

@ -22,7 +22,7 @@
#include <cstdlib>
#define STELLA_VERSION "3.5_svn_test1"
#define STELLA_VERSION "3.5_svn_test2"
#define STELLA_BUILD atoi("$Rev$" + 6)
#endif

View File

@ -68,7 +68,8 @@ CartridgeDPCPlus::CartridgeDPCPlus(const uInt8* image, uInt32 size,
#ifdef THUMB_SUPPORT
// Create Thumbulator ARM emulator
myThumbEmulator = new Thumbulator((uInt16*)(myProgramImage-0xC00),
(uInt16*)myDPCRAM);
(uInt16*)myDPCRAM,
settings.getBool("thumb.trapfatal"));
#endif
// Copy DPC display data to Harmony RAM

View File

@ -137,6 +137,9 @@ Settings::Settings(OSystem* osystem)
setInternal("resolvedata", "auto");
setInternal("gfxformat", "2");
setInternal("showaddr", "true");
// Thumb ARM emulation options
setInternal("thumb.trapfatal", "true");
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

View File

@ -620,8 +620,8 @@ const Int16 TIATables::PokeDelay[64] = {
1, // VBLANK (0) / 1
0, // WSYNC
0, // RSYNC
0, // NUSIZ0 (0) / 8 TODO - calculate this instead of hardcoding
0, // NUSIZ1 (0) / 8 TODO - calculate this instead of hardcoding
8, // NUSIZ0 (0) / 8 TODO - calculate this instead of hardcoding
8, // NUSIZ1 (0) / 8 TODO - calculate this instead of hardcoding
0, // COLUP0
0, // COLUP1
0, // COLUPF

View File

@ -31,13 +31,14 @@
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Thumbulator::Thumbulator(uInt16* rom_ptr, uInt16* ram_ptr)
Thumbulator::Thumbulator(uInt16* rom_ptr, uInt16* ram_ptr, bool traponfatal)
: rom(rom_ptr),
ram(ram_ptr),
copydata(0),
DBUG(0), // dump detailed execution trace
DISS(0) // dump Thumb instruction trace
{
trapFatalErrors(traponfatal);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -74,7 +75,9 @@ inline int Thumbulator::fatalError(const char* opcode, uInt32 v1, const char* ms
statusMsg << "Thumb ARM emulation fatal error: " << endl
<< opcode << "(" << HEX8 << v1 << "), " << msg << endl;
dump_regs();
if(trapOnFatal)
throw statusMsg.str();
return 0;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -84,7 +87,9 @@ inline int Thumbulator::fatalError(const char* opcode, uInt32 v1, uInt32 v2,
statusMsg << "Thumb ARM emulation fatal error: " << endl
<< opcode << "(" << HEX8 << v1 << "," << v2 << "), " << msg << endl;
dump_regs();
if(trapOnFatal)
throw statusMsg.str();
return 0;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -116,13 +121,9 @@ void Thumbulator::dump_regs( void )
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
uInt32 Thumbulator::fetch16 ( uInt32 addr )
{
uInt32 data;
fetches++;
if(DBUG)
statusMsg << "fetch16(" << HEX8 << addr << ")=";
uInt32 data;
switch(addr&0xF0000000)
{
case 0x00000000: //ROM
@ -137,7 +138,7 @@ uInt32 Thumbulator::fetch16 ( uInt32 addr )
data=rom[addr];
#endif
if(DBUG)
statusMsg << HEX4 << data << endl;
statusMsg << "fetch16(" << HEX8 << addr << ")=" << HEX4 << data << endl;
return(data);
case 0x40000000: //RAM
@ -149,7 +150,7 @@ uInt32 Thumbulator::fetch16 ( uInt32 addr )
data=ram[addr];
#endif
if(DBUG)
statusMsg << HEX4 << data << endl;
statusMsg << "fetch16(" << HEX8 << addr << ")=" << HEX4 << data << endl;
return(data);
}
return fatalError("fetch16", addr, "abort");
@ -159,10 +160,6 @@ uInt32 Thumbulator::fetch16 ( uInt32 addr )
uInt32 Thumbulator::fetch32 ( uInt32 addr )
{
uInt32 data;
if(DBUG)
statusMsg << "fetch32(" << HEX8 << addr << ")=";
switch(addr&0xF0000000)
{
case 0x00000000: //ROM
@ -170,7 +167,7 @@ uInt32 Thumbulator::fetch32 ( uInt32 addr )
{
data=read32(addr);
if(DBUG)
statusMsg << HEX8 << data << endl;
statusMsg << "fetch32(" << HEX8 << addr << ")=" << HEX8 << data << endl;
if(addr==0x00000000) return(data);
if(addr==0x00000004) return(data);
fatalError("fetch32", addr, "abort");
@ -181,7 +178,7 @@ uInt32 Thumbulator::fetch32 ( uInt32 addr )
data<<=16;
data|=fetch16(addr+0);
if(DBUG)
statusMsg << HEX8 << data << endl;;
statusMsg << "fetch32(" << HEX8 << addr << ")=" << HEX8 << data << endl;;
return(data);
}
return fatalError("fetch32", addr, "abort");
@ -217,6 +214,8 @@ void Thumbulator::write16 ( uInt32 addr, uInt32 data )
case 0xE0000000: //MAMCR
if(addr == 0xE01FC000)
{
if(DBUG)
statusMsg << "write16(" << HEX8 << "MAMCR" << "," << HEX8 << data << ") *" << endl;
mamcr = data;
return;
}
@ -277,9 +276,6 @@ uInt32 Thumbulator::read16 ( uInt32 addr )
reads++;
if(DBUG)
statusMsg << "read16(" << HEX8 << addr << ")=";
switch(addr&0xF0000000)
{
case 0x00000000: //ROM
@ -291,7 +287,7 @@ uInt32 Thumbulator::read16 ( uInt32 addr )
data=rom[addr];
#endif
if(DBUG)
statusMsg << HEX4 << data << endl;
statusMsg << "read16(" << HEX8 << addr << ")=" << HEX4 << data << endl;
return(data);
case 0x40000000: //RAM
@ -303,13 +299,17 @@ uInt32 Thumbulator::read16 ( uInt32 addr )
data=ram[addr];
#endif
if(DBUG)
statusMsg << HEX4 << data << endl;
statusMsg << "read16(" << HEX8 << addr << ")=" << HEX4 << data << endl;
return(data);
case 0xE0000000: //MAMCR
if(addr == 0xE01FC000)
{
if(DBUG)
statusMsg << "read16(" << "MAMCR" << addr << ")=" << mamcr << " *";
return mamcr;
}
}
return fatalError("read16", addr, "abort");
}
@ -319,9 +319,6 @@ uInt32 Thumbulator::read32 ( uInt32 addr )
if(addr&3)
fatalError("read32", addr, "abort - misaligned");
if(DBUG)
statusMsg << "read32(" << HEX8 << addr << ")=";
uInt32 data;
switch(addr&0xF0000000)
{
@ -331,7 +328,7 @@ uInt32 Thumbulator::read32 ( uInt32 addr )
data<<=16;
data|=read16(addr+0);
if(DBUG)
statusMsg << HEX8 << data << endl;
statusMsg << "read32(" << HEX8 << addr << ")=" << HEX8 << data << endl;
return(data);
}
return fatalError("read32", addr, "abort");
@ -340,12 +337,9 @@ uInt32 Thumbulator::read32 ( uInt32 addr )
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
uInt32 Thumbulator::read_register ( uInt32 reg )
{
uInt32 data;
reg&=0xF;
if(DBUG)
statusMsg << "read_register(" << dec << reg << ")=";
uInt32 data;
switch(cpsr&0x1F)
{
case MODE_SVC:
@ -355,7 +349,7 @@ uInt32 Thumbulator::read_register ( uInt32 reg )
case 13: case 14: data=reg_svc[reg]; break;
}
if(DBUG)
statusMsg << HEX8 << data << endl;
statusMsg << "read_register(" << dec << reg << ")=" << HEX8 << data << endl;
return(data);
}
return fatalError("read_register", cpsr, "invalid cpsr mode");
@ -369,7 +363,6 @@ uInt32 Thumbulator::write_register ( uInt32 reg, uInt32 data )
if(DBUG)
statusMsg << "write_register(" << dec << reg << ","
<< HEX8 << data << ")" << endl;
switch(cpsr&0x1F)
{
case MODE_SVC:
@ -2096,4 +2089,7 @@ int Thumbulator::reset ( void )
return(0);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool Thumbulator::trapOnFatal = true;
#endif

View File

@ -62,19 +62,33 @@
class Thumbulator
{
public:
Thumbulator(uInt16* rom, uInt16* ram);
Thumbulator(uInt16* rom, uInt16* ram, bool traponfatal);
~Thumbulator();
/**
Run the ARM code, and return when finished. A string exception is
thrown in case of any fatal errors/aborts, containing the actual error,
and the contents of the registers at that point in time.
thrown in case of any fatal errors/aborts (if enabled), containing the
actual error, and the contents of the registers at that point in time.
@return The results of any debugging output (if enabled),
otherwise an empty string
*/
string run();
/**
Normally when a fatal error is encountered, the ARM emulation
immediately throws an exception and exits. This method allows execution
to continue, and simply log the error.
Note that this is meant for developers only, and should normally be
always enabled. It can be used to temporarily ignore illegal reads
and writes, but a ROM which consistently performs these operations
should be fixed, as it can cause crashes on real hardware.
@param enable Enable (the default) or disable exceptions on fatal errors
*/
static void trapFatalErrors(bool enable) { trapOnFatal = enable; }
private:
uInt32 read_register ( uInt32 reg );
uInt32 write_register ( uInt32 reg, uInt32 data );
@ -128,6 +142,8 @@ class Thumbulator
Int32 DBUG; // dump detailed execution trace
Int32 DISS; // dump Thumb instruction trace
ostringstream statusMsg;
static bool trapOnFatal;
};
#endif