mirror of https://github.com/stella-emu/stella.git
Remove UNSAFE_OPTIMIZATIONS from Thumbulator.
This commit is contained in:
parent
3efa52d2c4
commit
f198be5d2f
|
@ -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: {
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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};
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue