defined UNSAFE_OPTIMIZATIONS in Thumbulator

This commit is contained in:
thrust26 2019-02-23 16:09:00 +01:00
parent bac5a86832
commit 486494eb7a
2 changed files with 116 additions and 10 deletions

View File

@ -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

View File

@ -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;