mirror of https://github.com/stella-emu/stella.git
defined UNSAFE_OPTIMIZATIONS in Thumbulator
This commit is contained in:
parent
bac5a86832
commit
486494eb7a
|
@ -68,7 +68,9 @@ Thumbulator::Thumbulator(const uInt16* rom_ptr, uInt16* ram_ptr, uInt32 romSize,
|
|||
decodedRom[i] = decodeInstructionWord(CONV_RAMROM(rom[i]));
|
||||
|
||||
setConsoleTiming(ConsoleTiming::ntsc);
|
||||
#ifndef UNSAFE_OPTIMIZATIONS
|
||||
trapFatalErrors(traponfatal);
|
||||
#endif
|
||||
reset();
|
||||
}
|
||||
|
||||
|
@ -79,8 +81,10 @@ string Thumbulator::run()
|
|||
for(;;)
|
||||
{
|
||||
if(execute()) break;
|
||||
#ifndef UNSAFE_OPTIMIZATIONS
|
||||
if(instructions > 500000) // way more than would otherwise be possible
|
||||
throw runtime_error("instructions > 500000");
|
||||
#endif
|
||||
}
|
||||
#if defined(THUMB_DISS) || defined(THUMB_DBUG)
|
||||
dump_counters();
|
||||
|
@ -105,6 +109,7 @@ void Thumbulator::setConsoleTiming(ConsoleTiming timing)
|
|||
case ConsoleTiming::pal: timing_factor = PAL; break;
|
||||
}
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void Thumbulator::updateTimer(uInt32 cycles)
|
||||
{
|
||||
|
@ -119,6 +124,7 @@ string Thumbulator::run(uInt32 cycles)
|
|||
return run();
|
||||
}
|
||||
|
||||
#ifndef UNSAFE_OPTIMIZATIONS
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
inline int Thumbulator::fatalError(const char* opcode, uInt32 v1, const char* msg)
|
||||
{
|
||||
|
@ -150,8 +156,7 @@ void Thumbulator::dump_counters()
|
|||
<< "fetches " << fetches << endl
|
||||
<< "reads " << reads << endl
|
||||
<< "writes " << writes << endl
|
||||
<< "memcycles " << (fetches+reads+writes) << endl
|
||||
<< "systick_ints " << systick_ints << endl;
|
||||
<< "memcycles " << (fetches+reads+writes) << endl;
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
@ -168,33 +173,42 @@ void Thumbulator::dump_regs()
|
|||
<< "PC = " << Base::HEX8 << reg_norm[15] << " "
|
||||
<< endl;
|
||||
}
|
||||
#endif
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
uInt32 Thumbulator::fetch16(uInt32 addr)
|
||||
{
|
||||
#ifndef NO_THUMB_STATS
|
||||
++fetches;
|
||||
#endif
|
||||
|
||||
uInt32 data;
|
||||
switch(addr & 0xF0000000)
|
||||
{
|
||||
case 0x00000000: //ROM
|
||||
addr &= ROMADDMASK;
|
||||
#ifndef UNSAFE_OPTIMIZATIONS
|
||||
if(addr < 0x50)
|
||||
fatalError("fetch16", addr, "abort");
|
||||
|
||||
#endif
|
||||
addr >>= 1;
|
||||
data = CONV_RAMROM(rom[addr]);
|
||||
DO_DBUG(statusMsg << "fetch16(" << Base::HEX8 << addr << ")=" << Base::HEX4 << data << endl);
|
||||
return data;
|
||||
|
||||
#ifndef UNSAFE_OPTIMIZATIONS
|
||||
case 0x40000000: //RAM
|
||||
#else
|
||||
default:
|
||||
#endif
|
||||
addr &= RAMADDMASK;
|
||||
addr >>= 1;
|
||||
data=CONV_RAMROM(ram[addr]);
|
||||
DO_DBUG(statusMsg << "fetch16(" << Base::HEX8 << addr << ")=" << Base::HEX4 << data << endl);
|
||||
return data;
|
||||
}
|
||||
#ifndef UNSAFE_OPTIMIZATIONS
|
||||
return fatalError("fetch16", addr, "abort");
|
||||
#endif
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
@ -210,22 +224,33 @@ uInt32 Thumbulator::fetch32(uInt32 addr)
|
|||
DO_DBUG(statusMsg << "fetch32(" << Base::HEX8 << addr << ")=" << Base::HEX8 << data << endl);
|
||||
if(addr == 0x00000000) return data;
|
||||
if(addr == 0x00000004) return data;
|
||||
#ifndef UNSAFE_OPTIMIZATIONS
|
||||
if(addr == 0x0000003C) return data;
|
||||
fatalError("fetch32", addr, "abort");
|
||||
#else
|
||||
return data;
|
||||
#endif
|
||||
}
|
||||
[[fallthrough]];
|
||||
|
||||
#ifndef UNSAFE_OPTIMIZATIONS
|
||||
case 0x40000000: //RAM
|
||||
#else
|
||||
default:
|
||||
#endif
|
||||
data = read32(addr);
|
||||
DO_DBUG(statusMsg << "fetch32(" << Base::HEX8 << addr << ")=" << Base::HEX8 << data << endl);
|
||||
return data;
|
||||
}
|
||||
#ifndef UNSAFE_OPTIMIZATIONS
|
||||
return fatalError("fetch32", addr, "abort");
|
||||
#endif
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void Thumbulator::write16(uInt32 addr, uInt32 data)
|
||||
{
|
||||
#ifndef UNSAFE_OPTIMIZATIONS
|
||||
if((addr > 0x40001fff) && (addr < 0x50000000))
|
||||
fatalError("write16", addr, "abort - out of range");
|
||||
|
||||
|
@ -233,8 +258,10 @@ void Thumbulator::write16(uInt32 addr, uInt32 data)
|
|||
|
||||
if(addr & 1)
|
||||
fatalError("write16", addr, "abort - misaligned");
|
||||
|
||||
#endif
|
||||
#ifndef NO_THUMB_STATS
|
||||
++writes;
|
||||
#endif
|
||||
|
||||
DO_DBUG(statusMsg << "write16(" << Base::HEX8 << addr << "," << Base::HEX8 << data << ")" << endl);
|
||||
|
||||
|
@ -246,7 +273,11 @@ void Thumbulator::write16(uInt32 addr, uInt32 data)
|
|||
ram[addr] = CONV_DATA(data);
|
||||
return;
|
||||
|
||||
#ifndef UNSAFE_OPTIMIZATIONS
|
||||
case 0xE0000000: //MAMCR
|
||||
#else
|
||||
default:
|
||||
#endif
|
||||
if(addr == 0xE01FC000)
|
||||
{
|
||||
DO_DBUG(statusMsg << "write16(" << Base::HEX8 << "MAMCR" << "," << Base::HEX8 << data << ") *" << endl);
|
||||
|
@ -254,23 +285,29 @@ void Thumbulator::write16(uInt32 addr, uInt32 data)
|
|||
return;
|
||||
}
|
||||
}
|
||||
#ifndef UNSAFE_OPTIMIZATIONS
|
||||
fatalError("write16", addr, data, "abort");
|
||||
#endif
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void Thumbulator::write32(uInt32 addr, uInt32 data)
|
||||
{
|
||||
#ifndef UNSAFE_OPTIMIZATIONS
|
||||
if(addr & 3)
|
||||
fatalError("write32", addr, "abort - misaligned");
|
||||
|
||||
if (isProtected(addr)) fatalError("write32", addr, "to driver area");
|
||||
#endif
|
||||
DO_DBUG(statusMsg << "write32(" << Base::HEX8 << addr << "," << Base::HEX8 << data << ")" << endl);
|
||||
|
||||
switch(addr & 0xF0000000)
|
||||
{
|
||||
#ifndef UNSAFE_OPTIMIZATIONS
|
||||
case 0xF0000000: //halt
|
||||
dump_counters();
|
||||
throw runtime_error("HALT");
|
||||
#endif
|
||||
|
||||
case 0xE0000000: //periph
|
||||
switch(addr)
|
||||
|
@ -314,6 +351,7 @@ void Thumbulator::write32(uInt32 addr, uInt32 data)
|
|||
return;
|
||||
|
||||
case 0xD0000000: //debug
|
||||
#ifndef UNSAFE_OPTIMIZATIONS
|
||||
switch(addr & 0xFF)
|
||||
{
|
||||
case 0x00:
|
||||
|
@ -329,16 +367,24 @@ void Thumbulator::write32(uInt32 addr, uInt32 data)
|
|||
statusMsg << Base::HEX8 << data << endl;
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
return;
|
||||
|
||||
#ifndef UNSAFE_OPTIMIZATIONS
|
||||
case 0x40000000: //RAM
|
||||
#else
|
||||
default:
|
||||
#endif
|
||||
write16(addr+0, (data >> 0) & 0xFFFF);
|
||||
write16(addr+2, (data >> 16) & 0xFFFF);
|
||||
return;
|
||||
}
|
||||
#ifndef UNSAFE_OPTIMIZATIONS
|
||||
fatalError("write32", addr, data, "abort");
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifndef UNSAFE_OPTIMIZATIONS
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
bool Thumbulator::isProtected(uInt32 addr)
|
||||
{
|
||||
|
@ -361,20 +407,23 @@ bool Thumbulator::isProtected(uInt32 addr)
|
|||
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
uInt32 Thumbulator::read16(uInt32 addr)
|
||||
{
|
||||
uInt32 data;
|
||||
|
||||
#ifndef UNSAFE_OPTIMIZATIONS
|
||||
if((addr > 0x40001fff) && (addr < 0x50000000))
|
||||
fatalError("read16", addr, "abort - out of range");
|
||||
else if((addr > 0x7fff) && (addr < 0x10000000))
|
||||
fatalError("read16", addr, "abort - out of range");
|
||||
if(addr & 1)
|
||||
fatalError("read16", addr, "abort - misaligned");
|
||||
|
||||
#endif
|
||||
#ifndef NO_THUMB_STATS
|
||||
++reads;
|
||||
#endif
|
||||
|
||||
switch(addr & 0xF0000000)
|
||||
{
|
||||
|
@ -392,21 +441,29 @@ uInt32 Thumbulator::read16(uInt32 addr)
|
|||
DO_DBUG(statusMsg << "read16(" << Base::HEX8 << addr << ")=" << Base::HEX4 << data << endl);
|
||||
return data;
|
||||
|
||||
#ifndef UNSAFE_OPTIMIZATIONS
|
||||
case 0xE0000000: //MAMCR
|
||||
if(addr == 0xE01FC000)
|
||||
#else
|
||||
default:
|
||||
#endif
|
||||
{
|
||||
DO_DBUG(statusMsg << "read16(" << "MAMCR" << addr << ")=" << mamcr << " *");
|
||||
return mamcr;
|
||||
}
|
||||
}
|
||||
#ifndef UNSAFE_OPTIMIZATIONS
|
||||
return fatalError("read16", addr, "abort");
|
||||
#endif
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
uInt32 Thumbulator::read32(uInt32 addr)
|
||||
{
|
||||
#ifndef UNSAFE_OPTIMIZATIONS
|
||||
if(addr & 3)
|
||||
fatalError("read32", addr, "abort - misaligned");
|
||||
#endif
|
||||
|
||||
uInt32 data;
|
||||
switch(addr & 0xF0000000)
|
||||
|
@ -418,7 +475,11 @@ uInt32 Thumbulator::read32(uInt32 addr)
|
|||
DO_DBUG(statusMsg << "read32(" << Base::HEX8 << addr << ")=" << Base::HEX8 << data << endl);
|
||||
return data;
|
||||
|
||||
#ifndef UNSAFE_OPTIMIZATIONS
|
||||
case 0xE0000000:
|
||||
#else
|
||||
default:
|
||||
#endif
|
||||
{
|
||||
switch(addr)
|
||||
{
|
||||
|
@ -443,13 +504,19 @@ uInt32 Thumbulator::read32(uInt32 addr)
|
|||
data = systick_count;
|
||||
return data;
|
||||
|
||||
#ifndef UNSAFE_OPTIMIZATIONS
|
||||
case 0xE000E01C:
|
||||
#else
|
||||
default:
|
||||
#endif
|
||||
data = systick_calibrate;
|
||||
return data;
|
||||
}
|
||||
}
|
||||
}
|
||||
#ifndef UNSAFE_OPTIMIZATIONS
|
||||
return fatalError("read32", addr, "abort");
|
||||
#endif
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
@ -771,7 +838,9 @@ int Thumbulator::execute()
|
|||
write_register(15, pc);
|
||||
DO_DISS(statusMsg << Base::HEX8 << (pc-5) << ": " << Base::HEX4 << inst << " ");
|
||||
|
||||
#ifndef UNSAFE_OPTIMIZATIONS
|
||||
++instructions;
|
||||
#endif
|
||||
|
||||
Op decodedOp;
|
||||
if ((instructionPtr & 0xF0000000) == 0 && instructionPtr < romSize)
|
||||
|
@ -872,9 +941,10 @@ int Thumbulator::execute()
|
|||
rc = ra + rb;
|
||||
if(rd == 15)
|
||||
{
|
||||
#ifndef UNSAFE_OPTIMIZATIONS
|
||||
if((rc & 1) == 0)
|
||||
fatalError("add pc", pc, rc, " produced an arm address");
|
||||
|
||||
#endif
|
||||
//rc &= ~1; //write_register may do this as well
|
||||
rc += 2; //The program counter is special
|
||||
}
|
||||
|
@ -1148,12 +1218,14 @@ int Thumbulator::execute()
|
|||
return 0;
|
||||
}
|
||||
|
||||
#ifndef UNSAFE_OPTIMIZATIONS
|
||||
//BKPT
|
||||
case Op::bkpt: {
|
||||
rb = (inst >> 0) & 0xFF;
|
||||
statusMsg << "bkpt 0x" << Base::HEX2 << rb << endl;
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
//BL/BLX(1)
|
||||
case Op::blx1: {
|
||||
|
@ -1514,11 +1586,13 @@ int Thumbulator::execute()
|
|||
return 0;
|
||||
}
|
||||
|
||||
#ifndef UNSAFE_OPTIMIZATIONS
|
||||
//CPS
|
||||
case Op::cps: {
|
||||
DO_DISS(statusMsg << "cps TODO" << endl);
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
//CPY copy high register
|
||||
case Op::cpy: {
|
||||
|
@ -2142,11 +2216,13 @@ int Thumbulator::execute()
|
|||
return 0;
|
||||
}
|
||||
|
||||
#ifndef UNSAFE_OPTIMIZATIONS
|
||||
//SETEND
|
||||
case Op::setend: {
|
||||
statusMsg << "setend not implemented" << endl;
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
//STMIA
|
||||
case Op::stmia: {
|
||||
|
@ -2424,11 +2500,15 @@ int Thumbulator::execute()
|
|||
return 0;
|
||||
}
|
||||
|
||||
#ifndef UNSAFE_OPTIMIZATIONS
|
||||
case Op::invalid:
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifndef UNSAFE_OPTIMIZATIONS
|
||||
statusMsg << "invalid instruction " << Base::HEX8 << pc << " " << Base::HEX4 << inst << endl;
|
||||
#endif
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@ -2464,12 +2544,19 @@ int Thumbulator::reset()
|
|||
systick_calibrate = 0x00ABCDEF;
|
||||
|
||||
// fxq: don't care about below so much (maybe to guess timing???)
|
||||
instructions = fetches = reads = writes = systick_ints = 0;
|
||||
#ifndef UNSAFE_OPTIMIZATIONS
|
||||
instructions = 0;
|
||||
#endif
|
||||
#ifndef NO_THUMB_STATS
|
||||
fetches = reads = writes = 0;
|
||||
#endif
|
||||
|
||||
statusMsg.str("");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifndef UNSAFE_OPTIMIZATIONS
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
bool Thumbulator::trapOnFatal = true;
|
||||
#endif
|
||||
|
|
|
@ -30,6 +30,12 @@ class Cartridge;
|
|||
#include "bspf.hxx"
|
||||
#include "Console.hxx"
|
||||
|
||||
#define RETRON77
|
||||
#ifdef RETRON77
|
||||
#define UNSAFE_OPTIMIZATIONS
|
||||
#define NO_THUMB_STATS
|
||||
#endif
|
||||
|
||||
#define ROMADDMASK 0x7FFF
|
||||
#define RAMADDMASK 0x1FFF
|
||||
|
||||
|
@ -67,6 +73,7 @@ class Thumbulator
|
|||
string run();
|
||||
string run(uInt32 cycles);
|
||||
|
||||
#ifndef UNSAFE_OPTIMIZATIONS
|
||||
/**
|
||||
Normally when a fatal error is encountered, the ARM emulation
|
||||
immediately throws an exception and exits. This method allows execution
|
||||
|
@ -80,6 +87,7 @@ class Thumbulator
|
|||
@param enable Enable (the default) or disable exceptions on fatal errors
|
||||
*/
|
||||
static void trapFatalErrors(bool enable) { trapOnFatal = enable; }
|
||||
#endif
|
||||
|
||||
/**
|
||||
Inform the Thumbulator class about the console currently in use,
|
||||
|
@ -147,7 +155,9 @@ class Thumbulator
|
|||
uInt32 fetch32(uInt32 addr);
|
||||
uInt32 read16(uInt32 addr);
|
||||
uInt32 read32(uInt32 addr);
|
||||
#ifndef UNSAFE_OPTIMIZATIONS
|
||||
bool isProtected(uInt32 addr);
|
||||
#endif
|
||||
void write16(uInt32 addr, uInt32 data);
|
||||
void write32(uInt32 addr, uInt32 data);
|
||||
void updateTimer(uInt32 cycles);
|
||||
|
@ -161,6 +171,7 @@ class Thumbulator
|
|||
void do_cflag_bit(uInt32 x);
|
||||
void do_vflag_bit(uInt32 x);
|
||||
|
||||
#ifndef UNSAFE_OPTIMIZATIONS
|
||||
// Throw a runtime_error exception containing an error referencing the
|
||||
// given message and variables
|
||||
// Note that the return value is never used in these methods
|
||||
|
@ -169,6 +180,7 @@ class Thumbulator
|
|||
|
||||
void dump_counters();
|
||||
void dump_regs();
|
||||
#endif
|
||||
int execute();
|
||||
int reset();
|
||||
|
||||
|
@ -182,7 +194,12 @@ class Thumbulator
|
|||
uInt32 cpsr, mamcr;
|
||||
bool handler_mode;
|
||||
uInt32 systick_ctrl, systick_reload, systick_count, systick_calibrate;
|
||||
uInt64 instructions, fetches, reads, writes, systick_ints;
|
||||
#ifndef UNSAFE_OPTIMIZATIONS
|
||||
uInt64 instructions;
|
||||
#endif
|
||||
#ifndef NO_THUMB_STATS
|
||||
uInt64 fetches, reads, writes;
|
||||
#endif
|
||||
|
||||
// For emulation of LPC2103's timer 1, used for NTSC/PAL/SECAM detection.
|
||||
// Register names from documentation:
|
||||
|
@ -193,7 +210,9 @@ class Thumbulator
|
|||
|
||||
ostringstream statusMsg;
|
||||
|
||||
#ifndef UNSAFE_OPTIMIZATIONS
|
||||
static bool trapOnFatal;
|
||||
#endif
|
||||
|
||||
ConfigureFor configuration;
|
||||
|
||||
|
|
Loading…
Reference in New Issue