Remove UNSAFE_OPTIMIZATIONS from Thumbulator.

This commit is contained in:
Stephen Anthony 2025-06-01 17:34:09 -02:30
parent 3efa52d2c4
commit f198be5d2f
3 changed files with 13 additions and 135 deletions

View File

@ -2250,12 +2250,10 @@ CortexM0::err_t CortexM0::execute(uInt16 inst, uInt8 op)
return ERR_NONE; return ERR_NONE;
} }
#ifndef UNSAFE_OPTIMIZATIONS
//SETEND //SETEND
case Op::setend: { case Op::setend: {
return errIntrinsic(ERR_UNIMPLEMENTED_INST, read_register(15) - 4); return errIntrinsic(ERR_UNIMPLEMENTED_INST, read_register(15) - 4);
} }
#endif
//STMIA //STMIA
case Op::stmia: { case Op::stmia: {

View File

@ -154,9 +154,7 @@ Thumbulator::Thumbulator(const uInt16* rom_ptr, uInt16* ram_ptr, uInt32 rom_size
decodedRom[i] = decodeInstructionWord(CONV_RAMROM(rom[i]), i * 2); decodedRom[i] = decodeInstructionWord(CONV_RAMROM(rom[i]), i * 2);
setConsoleTiming(ConsoleTiming::ntsc); setConsoleTiming(ConsoleTiming::ntsc);
#ifndef UNSAFE_OPTIMIZATIONS
trapFatalErrors(traponfatal); trapFatalErrors(traponfatal);
#endif
#ifdef DEBUGGER_SUPPORT #ifdef DEBUGGER_SUPPORT
cycleFactor(cyclefactor); cycleFactor(cyclefactor);
#endif #endif
@ -171,10 +169,8 @@ string Thumbulator::doRun(uInt32& cycles, bool irqDrivenAudio)
for(;;) for(;;)
{ {
if(execute()) break; if(execute()) break;
#ifndef UNSAFE_OPTIMIZATIONS
if(_stats.instructions > 500000) // way more than would otherwise be possible if(_stats.instructions > 500000) // way more than would otherwise be possible
throw runtime_error("instructions > 500000"); throw runtime_error("instructions > 500000");
#endif
} }
#ifdef THUMB_CYCLE_COUNT #ifdef THUMB_CYCLE_COUNT
_totalCycles *= _armCyclesFactor; _totalCycles *= _armCyclesFactor;
@ -241,7 +237,6 @@ string Thumbulator::run(uInt32& cycles, bool irqDrivenAudio)
return doRun(cycles, irqDrivenAudio); return doRun(cycles, irqDrivenAudio);
} }
#ifndef UNSAFE_OPTIMIZATIONS
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
int Thumbulator::fatalError(string_view opcode, uInt32 v1, string_view msg) int Thumbulator::fatalError(string_view opcode, uInt32 v1, string_view msg)
{ {
@ -293,12 +288,10 @@ void Thumbulator::dump_regs()
<< "LR = " << Base::HEX8 << reg_norm[14] << " " << "LR = " << Base::HEX8 << reg_norm[14] << " "
<< "PC = " << Base::HEX8 << reg_norm[15] << '\n'; << "PC = " << Base::HEX8 << reg_norm[15] << '\n';
} }
#endif
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
FORCE_INLINE uInt32 Thumbulator::fetch16(uInt32 addr) FORCE_INLINE uInt32 Thumbulator::fetch16(uInt32 addr)
{ {
#ifndef UNSAFE_OPTIMIZATIONS
uInt32 data = 0; uInt32 data = 0;
#ifdef THUMB_CYCLE_COUNT #ifdef THUMB_CYCLE_COUNT
@ -355,42 +348,32 @@ FORCE_INLINE uInt32 Thumbulator::fetch16(uInt32 addr)
break; break;
} }
return fatalError("fetch16", addr, "abort"); return fatalError("fetch16", addr, "abort");
#else
addr &= ROMADDMASK;
addr >>= 1;
return CONV_RAMROM(rom[addr]);
#endif
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void Thumbulator::write16(uInt32 addr, uInt32 data) void Thumbulator::write16(uInt32 addr, uInt32 data)
{ {
#ifndef UNSAFE_OPTIMIZATIONS
if(addr & 1) if(addr & 1)
fatalError("write16", addr, "abort - misaligned"); fatalError("write16", addr, "abort - misaligned");
#endif
THUMB_STAT(_stats.writes) THUMB_STAT(_stats.writes)
DO_DBUG(statusMsg << "write16(" << Base::HEX8 << addr << "," << Base::HEX8 << data << ")\n"); DO_DBUG(statusMsg << "write16(" << Base::HEX8 << addr << "," << Base::HEX8 << data << ")\n");
switch(addr & 0xF0000000) // NOLINT (missing default for UNSAFE_OPTIMIZATIONS) switch(addr & 0xF0000000)
{ {
case 0x40000000: //RAM case 0x40000000: //RAM
#ifndef UNSAFE_OPTIMIZATIONS
if(isInvalidRAM(addr)) if(isInvalidRAM(addr))
fatalError("write16", addr, "abort - out of range"); fatalError("write16", addr, "abort - out of range");
if(isProtectedRAM(addr)) if(isProtectedRAM(addr))
fatalError("write16", addr, "to driver area"); fatalError("write16", addr, "to driver area");
#endif
addr &= RAMADDMASK; addr &= RAMADDMASK;
addr >>= 1; addr >>= 1;
ram[addr] = CONV_DATA(data); ram[addr] = CONV_DATA(data);
return; return;
#ifndef UNSAFE_OPTIMIZATIONS
case 0xE0000000: //MAMCR case 0xE0000000: //MAMCR
#else
default: default:
#endif
if(addr == 0xE01FC000) if(addr == 0xE01FC000)
{ {
DO_DBUG(statusMsg << "write16(" << Base::HEX8 << "MAMCR" << "," << Base::HEX8 << data << ") *\n"); DO_DBUG(statusMsg << "write16(" << Base::HEX8 << "MAMCR" << "," << Base::HEX8 << data << ") *\n");
@ -399,36 +382,29 @@ void Thumbulator::write16(uInt32 addr, uInt32 data)
return; return;
} }
} }
#ifndef UNSAFE_OPTIMIZATIONS
fatalError("write16", addr, data, "abort"); fatalError("write16", addr, data, "abort");
#endif
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void Thumbulator::write32(uInt32 addr, uInt32 data) void Thumbulator::write32(uInt32 addr, uInt32 data)
{ {
#ifndef UNSAFE_OPTIMIZATIONS
if(addr & 3) if(addr & 3)
fatalError("write32", addr, "abort - misaligned"); fatalError("write32", addr, "abort - misaligned");
#endif
DO_DBUG(statusMsg << "write32(" << Base::HEX8 << addr << "," << Base::HEX8 << data << ")\n"); DO_DBUG(statusMsg << "write32(" << Base::HEX8 << addr << "," << Base::HEX8 << data << ")\n");
switch(addr & 0xF0000000) // NOLINT (missing default for UNSAFE_OPTIMIZATIONS) switch(addr & 0xF0000000)
{ {
#ifndef UNSAFE_OPTIMIZATIONS
case 0xF0000000: //halt case 0xF0000000: //halt
dump_counters(); dump_counters();
throw runtime_error("HALT"); throw runtime_error("HALT");
#endif
case 0xE0000000: //periph case 0xE0000000: //periph
switch(addr) switch(addr)
{ {
#ifndef UNSAFE_OPTIMIZATIONS
case 0xE0000000: case 0xE0000000:
DO_DISS(statusMsg << "uart: [" << char(data&0xFF) << "]\n"); DO_DISS(statusMsg << "uart: [" << char(data&0xFF) << "]\n");
break; break;
#endif
#ifdef TIMER_0 #ifdef TIMER_0
case 0xE0004004: // T0TCR - Timer 0 Control Register case 0xE0004004: // T0TCR - Timer 0 Control Register
#ifdef THUMB_CYCLE_COUNT #ifdef THUMB_CYCLE_COUNT
@ -516,7 +492,6 @@ void Thumbulator::write32(uInt32 addr, uInt32 data)
return; return;
case 0xD0000000: //debug case 0xD0000000: //debug
#ifndef UNSAFE_OPTIMIZATIONS
switch(addr & 0xFF) switch(addr & 0xFF)
{ {
case 0x00: case 0x00:
@ -535,24 +510,17 @@ void Thumbulator::write32(uInt32 addr, uInt32 data)
default: default:
break; break;
} }
#endif
return; return;
#ifndef UNSAFE_OPTIMIZATIONS
case 0x40000000: //RAM case 0x40000000: //RAM
#else
default: default:
#endif
write16(addr+0, (data >> 0) & 0xFFFF); write16(addr+0, (data >> 0) & 0xFFFF);
write16(addr+2, (data >> 16) & 0xFFFF); write16(addr+2, (data >> 16) & 0xFFFF);
return; return;
} }
#ifndef UNSAFE_OPTIMIZATIONS
fatalError("write32", addr, data, "abort"); fatalError("write32", addr, data, "abort");
#endif
} }
#ifndef UNSAFE_OPTIMIZATIONS
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
FORCE_INLINE bool Thumbulator::isInvalidROM(uInt32 addr) const FORCE_INLINE bool Thumbulator::isInvalidROM(uInt32 addr) const
{ {
@ -613,25 +581,21 @@ FORCE_INLINE bool Thumbulator::isProtectedRAM(uInt32 addr)
return false; return false;
} }
#endif
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
uInt32 Thumbulator::read16(uInt32 addr) uInt32 Thumbulator::read16(uInt32 addr)
{ {
uInt32 data = 0; uInt32 data = 0;
#ifndef UNSAFE_OPTIMIZATIONS
if(addr & 1) if(addr & 1)
fatalError("read16", addr, "abort - misaligned"); fatalError("read16", addr, "abort - misaligned");
#endif
THUMB_STAT(_stats.reads) THUMB_STAT(_stats.reads)
switch(addr & 0xF0000000) // NOLINT (missing default for UNSAFE_OPTIMIZATIONS) switch(addr & 0xF0000000)
{ {
case 0x00000000: //ROM case 0x00000000: //ROM
#ifndef UNSAFE_OPTIMIZATIONS
if(isInvalidROM(addr)) if(isInvalidROM(addr))
fatalError("read16", addr, "abort - out of range"); fatalError("read16", addr, "abort - out of range");
#endif
addr &= ROMADDMASK; addr &= ROMADDMASK;
addr >>= 1; addr >>= 1;
data = CONV_RAMROM(rom[addr]); data = CONV_RAMROM(rom[addr]);
@ -639,10 +603,9 @@ uInt32 Thumbulator::read16(uInt32 addr)
return data; return data;
case 0x40000000: //RAM case 0x40000000: //RAM
#ifndef UNSAFE_OPTIMIZATIONS
if(isInvalidRAM(addr)) if(isInvalidRAM(addr))
fatalError("read16", addr, "abort - out of range"); fatalError("read16", addr, "abort - out of range");
#endif
addr &= RAMADDMASK; addr &= RAMADDMASK;
addr >>= 1; addr >>= 1;
data = CONV_RAMROM(ram[addr]); data = CONV_RAMROM(ram[addr]);
@ -661,49 +624,40 @@ uInt32 Thumbulator::read16(uInt32 addr)
return data; return data;
} }
} }
#ifndef UNSAFE_OPTIMIZATIONS
return fatalError("read16", addr, "abort"); return fatalError("read16", addr, "abort");
#endif
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
uInt32 Thumbulator::read32(uInt32 addr) uInt32 Thumbulator::read32(uInt32 addr)
{ {
#ifndef UNSAFE_OPTIMIZATIONS
if(addr & 3) if(addr & 3)
fatalError("read32", addr, "abort - misaligned"); fatalError("read32", addr, "abort - misaligned");
#endif
uInt32 data = 0; uInt32 data = 0;
switch(addr & 0xF0000000) // NOLINT (missing default for UNSAFE_OPTIMIZATIONS) switch(addr & 0xF0000000)
{ {
case 0x00000000: //ROM case 0x00000000: //ROM
#ifndef UNSAFE_OPTIMIZATIONS
if(isInvalidROM(addr)) if(isInvalidROM(addr))
fatalError("read32", addr, "abort - out of range"); fatalError("read32", addr, "abort - out of range");
#endif
data = read16(addr+0); data = read16(addr+0);
data |= read16(addr+2) << 16; data |= read16(addr+2) << 16;
DO_DBUG(statusMsg << "read32(" << Base::HEX8 << addr << ")=" << Base::HEX8 << data << '\n'); DO_DBUG(statusMsg << "read32(" << Base::HEX8 << addr << ")=" << Base::HEX8 << data << '\n');
return data; return data;
case 0x40000000: //RAM case 0x40000000: //RAM
#ifndef UNSAFE_OPTIMIZATIONS
if(isInvalidRAM(addr)) if(isInvalidRAM(addr))
fatalError("read32", addr, "abort - out of range"); fatalError("read32", addr, "abort - out of range");
#endif
data = read16(addr+0); data = read16(addr+0);
data |= read16(addr+2) << 16; data |= read16(addr+2) << 16;
DO_DBUG(statusMsg << "read32(" << Base::HEX8 << addr << ")=" << Base::HEX8 << data << '\n'); DO_DBUG(statusMsg << "read32(" << Base::HEX8 << addr << ")=" << Base::HEX8 << data << '\n');
return data; return data;
#ifndef UNSAFE_OPTIMIZATIONS
case 0xE0000000: case 0xE0000000:
#else
default: default:
#endif
{ {
switch(addr) // NOLINT (FIXME: missing default) switch(addr)
{ {
#ifdef THUMB_CYCLE_COUNT #ifdef THUMB_CYCLE_COUNT
case 0xE01FC000: //MAMCR case 0xE01FC000: //MAMCR
@ -765,22 +719,16 @@ uInt32 Thumbulator::read32(uInt32 addr)
return 1; // random value return 1; // random value
#endif #endif
#ifndef UNSAFE_OPTIMIZATIONS
case 0xE000E01C: case 0xE000E01C:
#else
default: default:
#endif
data = systick_calibrate; data = systick_calibrate;
return data; return data;
} }
} }
} }
#ifndef UNSAFE_OPTIMIZATIONS
return fatalError("read32", addr, "abort"); return fatalError("read32", addr, "abort");
#endif
} }
#ifndef UNSAFE_OPTIMIZATIONS
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
FORCE_INLINE uInt32 Thumbulator::read_register(uInt32 reg) FORCE_INLINE uInt32 Thumbulator::read_register(uInt32 reg)
{ {
@ -818,10 +766,6 @@ FORCE_INLINE void Thumbulator::write_register(uInt32 reg, uInt32 data, bool isFl
} }
reg_norm[reg] = data; reg_norm[reg] = data;
} }
#else
#define read_register(reg) reg_norm[reg]
#define write_register(reg, data) reg_norm[reg]=(data)
#endif
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void Thumbulator::do_cvflag(uInt32 a, uInt32 b, uInt32 c) void Thumbulator::do_cvflag(uInt32 a, uInt32 b, uInt32 c)
@ -1145,37 +1089,23 @@ FORCE_INLINE int Thumbulator::execute() // NOLINT (readability-function-size)
{ {
uInt32 sp, inst, ra, rb, rc, rm, rd, rn, rs; // NOLINT uInt32 sp, inst, ra, rb, rc, rm, rd, rn, rs; // NOLINT
#ifndef UNSAFE_OPTIMIZATIONS
uInt32 pc = read_register(15); uInt32 pc = read_register(15);
#else
uInt32 pc = read_register(15) & ~1; // not checked and corrected in read_register
#endif
const uInt32 instructionPtr = pc - 2; const uInt32 instructionPtr = pc - 2;
const uInt32 instructionPtr2 = instructionPtr >> 1; const uInt32 instructionPtr2 = instructionPtr >> 1;
inst = fetch16(instructionPtr); inst = fetch16(instructionPtr);
pc += 2; pc += 2;
#ifndef UNSAFE_OPTIMIZATIONS
write_register(15, pc, false); write_register(15, pc, false);
#else
write_register(15, pc);
#endif
DO_DISS(statusMsg << Base::HEX8 << (pc-5) << ": " << Base::HEX4 << inst << " "); DO_DISS(statusMsg << Base::HEX8 << (pc-5) << ": " << Base::HEX4 << inst << " ");
#ifndef UNSAFE_OPTIMIZATIONS
++_stats.instructions; ++_stats.instructions;
#endif
Op decodedOp{}; Op decodedOp{};
#ifndef UNSAFE_OPTIMIZATIONS
if ((instructionPtr & 0xF0000000) == 0 && instructionPtr < romSize) if ((instructionPtr & 0xF0000000) == 0 && instructionPtr < romSize)
decodedOp = decodedRom[instructionPtr2]; decodedOp = decodedRom[instructionPtr2];
else else
decodedOp = decodeInstructionWord(CONV_RAMROM(rom[instructionPtr2]), instructionPtr); decodedOp = decodeInstructionWord(CONV_RAMROM(rom[instructionPtr2]), instructionPtr);
#else
decodedOp = decodedRom[(instructionPtr & ROMADDMASK) >> 1];
#endif
#ifdef COUNT_OPS #ifdef COUNT_OPS
++opCount[static_cast<int>(decodedOp)]; ++opCount[static_cast<int>(decodedOp)];
@ -1265,10 +1195,9 @@ FORCE_INLINE int Thumbulator::execute() // NOLINT (readability-function-size)
rc = ra + rb; rc = ra + rb;
if(rd == 15) if(rd == 15)
{ {
#ifndef UNSAFE_OPTIMIZATIONS
if((rc & 1) == 0) if((rc & 1) == 0)
fatalError("add pc", pc, rc, " produced an arm address"); fatalError("add pc", pc, rc, " produced an arm address");
#endif
//rc &= ~1; //write_register may f this as well //rc &= ~1; //write_register may f this as well
rc += 2; //The program counter is special rc += 2; //The program counter is special
} }
@ -1526,14 +1455,12 @@ FORCE_INLINE int Thumbulator::execute() // NOLINT (readability-function-size)
return 0; return 0;
} }
#ifndef UNSAFE_OPTIMIZATIONS
//BKPT //BKPT
case Op::bkpt: { case Op::bkpt: {
rb = (inst >> 0) & 0xFF; rb = (inst >> 0) & 0xFF;
statusMsg << "bkpt 0x" << Base::HEX2 << rb << '\n'; statusMsg << "bkpt 0x" << Base::HEX2 << rb << '\n';
return 1; return 1;
} }
#endif
//BL/BLX(1) variants //BL/BLX(1) variants
// (bl, blx_thumb, blx_arm) // (bl, blx_thumb, blx_arm)
@ -1584,9 +1511,6 @@ FORCE_INLINE int Thumbulator::execute() // NOLINT (readability-function-size)
if(rc & 1) if(rc & 1)
{ {
write_register(14, (pc-2) | 1); write_register(14, (pc-2) | 1);
#ifdef UNSAFE_OPTIMIZATIONS
rc &= ~1; // not checked and corrected in write_register
#endif
write_register(15, rc); write_register(15, rc);
return 0; return 0;
} }
@ -1906,13 +1830,11 @@ FORCE_INLINE int Thumbulator::execute() // NOLINT (readability-function-size)
return 0; return 0;
} }
#ifndef UNSAFE_OPTIMIZATIONS
//CPS //CPS
case Op::cps: { case Op::cps: {
DO_DISS(statusMsg << "cps TODO\n"); DO_DISS(statusMsg << "cps TODO\n");
return 1; return 1;
} }
#endif
//CPY copy high register //CPY copy high register
case Op::cpy: { case Op::cpy: {
@ -2047,11 +1969,7 @@ FORCE_INLINE int Thumbulator::execute() // NOLINT (readability-function-size)
rb = (inst >> 6) & 0x1F; rb = (inst >> 6) & 0x1F;
DO_DISS(statusMsg << "ldrb r" << dec << rd << ",[r" << dec << rn << ",#0x" << Base::HEX2 << rb << "]\n"); DO_DISS(statusMsg << "ldrb r" << dec << rd << ",[r" << dec << rn << ",#0x" << Base::HEX2 << rb << "]\n");
rb = read_register(rn) + rb; rb = read_register(rn) + rb;
#ifndef UNSAFE_OPTIMIZATIONS
rc = read16(rb & (~1U)); rc = read16(rb & (~1U));
#else
rc = read16(rb);
#endif
if(rb & 1) if(rb & 1)
{ {
rc >>= 8; rc >>= 8;
@ -2071,11 +1989,7 @@ FORCE_INLINE int Thumbulator::execute() // NOLINT (readability-function-size)
rm = (inst >> 6) & 0x7; rm = (inst >> 6) & 0x7;
DO_DISS(statusMsg << "ldrb r" << dec << rd << ",[r" << dec << rn << ",r" << dec << rm << "]\n"); DO_DISS(statusMsg << "ldrb r" << dec << rd << ",[r" << dec << rn << ",r" << dec << rm << "]\n");
rb = read_register(rn) + read_register(rm); rb = read_register(rn) + read_register(rm);
#ifndef UNSAFE_OPTIMIZATIONS
rc = read16(rb & (~1U)); rc = read16(rb & (~1U));
#else
rc = read16(rb);
#endif
if(rb & 1) if(rb & 1)
{ {
rc >>= 8; rc >>= 8;
@ -2119,11 +2033,7 @@ FORCE_INLINE int Thumbulator::execute() // NOLINT (readability-function-size)
rm = (inst >> 6) & 0x7; rm = (inst >> 6) & 0x7;
DO_DISS(statusMsg << "ldrsb r" << dec << rd << ",[r" << dec << rn << ",r" << dec << rm << "]\n"); DO_DISS(statusMsg << "ldrsb r" << dec << rd << ",[r" << dec << rn << ",r" << dec << rm << "]\n");
rb = read_register(rn) + read_register(rm); rb = read_register(rn) + read_register(rm);
#ifndef UNSAFE_OPTIMIZATIONS
rc = read16(rb & (~1U)); rc = read16(rb & (~1U));
#else
rc = read16(rb);
#endif
if(rb & 1) if(rb & 1)
{ {
rc >>= 8; rc >>= 8;
@ -2603,13 +2513,11 @@ FORCE_INLINE int Thumbulator::execute() // NOLINT (readability-function-size)
return 0; return 0;
} }
#ifndef UNSAFE_OPTIMIZATIONS
//SETEND //SETEND
case Op::setend: { case Op::setend: {
statusMsg << "setend not implemented\n"; statusMsg << "setend not implemented\n";
return 1; return 1;
} }
#endif
//STMIA //STMIA
case Op::stmia: { case Op::stmia: {
@ -2701,11 +2609,7 @@ FORCE_INLINE int Thumbulator::execute() // NOLINT (readability-function-size)
DO_DISS(statusMsg << "strb r" << dec << rd << ",[r" << dec << rn << ",#0x" << Base::HEX8 << rb << "]\n"); DO_DISS(statusMsg << "strb r" << dec << rd << ",[r" << dec << rn << ",#0x" << Base::HEX8 << rb << "]\n");
rb = read_register(rn) + rb; rb = read_register(rn) + rb;
rc = read_register(rd); rc = read_register(rd);
#ifndef UNSAFE_OPTIMIZATIONS
ra = read16(rb & (~1U)); ra = read16(rb & (~1U));
#else
ra = read16(rb);
#endif
if(rb & 1) if(rb & 1)
{ {
ra &= 0x00FF; ra &= 0x00FF;
@ -2729,11 +2633,7 @@ FORCE_INLINE int Thumbulator::execute() // NOLINT (readability-function-size)
DO_DISS(statusMsg << "strb r" << dec << rd << ",[r" << dec << rn << ",r" << rm << "]\n"); DO_DISS(statusMsg << "strb r" << dec << rd << ",[r" << dec << rn << ",r" << rm << "]\n");
rb = read_register(rn) + read_register(rm); rb = read_register(rn) + read_register(rm);
rc = read_register(rd); rc = read_register(rd);
#ifndef UNSAFE_OPTIMIZATIONS
ra = read16(rb & (~1U)); ra = read16(rb & (~1U));
#else
ra = read16(rb);
#endif
if(rb & 1) if(rb & 1)
{ {
ra &= 0x00FF; ra &= 0x00FF;
@ -2912,19 +2812,13 @@ FORCE_INLINE int Thumbulator::execute() // NOLINT (readability-function-size)
case Op::numOps: case Op::numOps:
break; break;
#ifndef UNSAFE_OPTIMIZATIONS
case Op::invalid: case Op::invalid:
break;
#else
default: default:
break; break;
#endif
} }
#ifndef UNSAFE_OPTIMIZATIONS
statusMsg << "invalid instruction " << Base::HEX8 << pc << " " statusMsg << "invalid instruction " << Base::HEX8 << pc << " "
<< Base::HEX4 << inst << '\n'; << Base::HEX4 << inst << '\n';
#endif
return 1; return 1;
} }
@ -2946,10 +2840,8 @@ int Thumbulator::reset()
systick_calibrate = 0x00ABCDEF; systick_calibrate = 0x00ABCDEF;
// fxq: don't care about below so much (maybe to guess timing???) // fxq: don't care about below so much (maybe to guess timing???)
#ifndef UNSAFE_OPTIMIZATIONS
_stats.instructions = 0; _stats.instructions = 0;
statusMsg.str(""); statusMsg.str("");
#endif
#ifdef THUMB_STATS #ifdef THUMB_STATS
_stats.reads = _stats.writes _stats.reads = _stats.writes
= _stats.nCycles = _stats.nCycles = _stats.iCycles = _stats.nCycles = _stats.nCycles = _stats.iCycles

View File

@ -30,8 +30,6 @@ class Cartridge;
#include "bspf.hxx" #include "bspf.hxx"
#include "Console.hxx" #include "Console.hxx"
//#define UNSAFE_OPTIMIZATIONS
#ifdef DEBUGGER_SUPPORT #ifdef DEBUGGER_SUPPORT
#define THUMB_CYCLE_COUNT #define THUMB_CYCLE_COUNT
//#define COUNT_OPS //#define COUNT_OPS
@ -117,7 +115,6 @@ class Thumbulator
double cycleFactor() const { return 1.0; } double cycleFactor() const { return 1.0; }
#endif #endif
#ifndef UNSAFE_OPTIMIZATIONS
/** /**
Normally when a fatal error is encountered, the ARM emulation Normally when a fatal error is encountered, the ARM emulation
immediately throws an exception and exits. This method allows execution immediately throws an exception and exits. This method allows execution
@ -131,7 +128,6 @@ class Thumbulator
@param enable Enable (the default) or disable exceptions on fatal errors @param enable Enable (the default) or disable exceptions on fatal errors
*/ */
void trapFatalErrors(bool enable) { trapOnFatal = enable; } void trapFatalErrors(bool enable) { trapOnFatal = enable; }
#endif
/** /**
Inform the Thumbulator class about the console currently in use, Inform the Thumbulator class about the console currently in use,
@ -215,18 +211,14 @@ class Thumbulator
private: private:
string doRun(uInt32& cycles, bool irqDrivenAudio); string doRun(uInt32& cycles, bool irqDrivenAudio);
#ifndef UNSAFE_OPTIMIZATIONS
uInt32 read_register(uInt32 reg); uInt32 read_register(uInt32 reg);
void write_register(uInt32 reg, uInt32 data, bool isFlowBreak = true); void write_register(uInt32 reg, uInt32 data, bool isFlowBreak = true);
#endif
uInt32 fetch16(uInt32 addr); uInt32 fetch16(uInt32 addr);
uInt32 read16(uInt32 addr); uInt32 read16(uInt32 addr);
uInt32 read32(uInt32 addr); uInt32 read32(uInt32 addr);
#ifndef UNSAFE_OPTIMIZATIONS
bool isInvalidROM(uInt32 addr) const; bool isInvalidROM(uInt32 addr) const;
bool isInvalidRAM(uInt32 addr) const; bool isInvalidRAM(uInt32 addr) const;
bool isProtectedRAM(uInt32 addr); bool isProtectedRAM(uInt32 addr);
#endif
void write16(uInt32 addr, uInt32 data); void write16(uInt32 addr, uInt32 data);
void write32(uInt32 addr, uInt32 data); void write32(uInt32 addr, uInt32 data);
void updateTimer(uInt32 cycles); void updateTimer(uInt32 cycles);
@ -235,7 +227,6 @@ class Thumbulator
void do_cvflag(uInt32 a, uInt32 b, uInt32 c); void do_cvflag(uInt32 a, uInt32 b, uInt32 c);
#ifndef UNSAFE_OPTIMIZATIONS
// Throw a runtime_error exception containing an error referencing the // Throw a runtime_error exception containing an error referencing the
// given message and variables // given message and variables
// Note that the return value is never used in these methods // Note that the return value is never used in these methods
@ -244,7 +235,6 @@ class Thumbulator
void dump_counters() const; void dump_counters() const;
void dump_regs(); void dump_regs();
#endif
int execute(); int execute();
int reset(); int reset();
@ -299,10 +289,8 @@ class Thumbulator
uInt32 tim1Total{0}; // total cycles of Timer 1 uInt32 tim1Total{0}; // total cycles of Timer 1
double timing_factor{0.0}; double timing_factor{0.0};
#ifndef UNSAFE_OPTIMIZATIONS
ostringstream statusMsg; ostringstream statusMsg;
bool trapOnFatal{true}; bool trapOnFatal{true};
#endif
bool _countCycles{false}; bool _countCycles{false};
bool _lockMamcr{false}; bool _lockMamcr{false};