mirror of https://github.com/stella-emu/stella.git
slightly optimized Thumb emulation for R77
This commit is contained in:
parent
f677acf273
commit
e9efdbc3a1
|
@ -38,7 +38,8 @@ void CartridgeARMWidget::addCycleWidgets(int xpos, int ypos)
|
||||||
constexpr int INDENT = 20, VGAP = 4;
|
constexpr int INDENT = 20, VGAP = 4;
|
||||||
VariantList items;
|
VariantList items;
|
||||||
|
|
||||||
new StaticTextWidget(_boss, _font, xpos, ypos + 1, "ARM emulation cycles:");
|
auto* s = new StaticTextWidget(_boss, _font, xpos, ypos + 1, "ARM emulation cycles:");
|
||||||
|
s->setToolTip("Cycle count enabled by developer settings.");
|
||||||
xpos += INDENT; ypos += myLineHeight + VGAP;
|
xpos += INDENT; ypos += myLineHeight + VGAP;
|
||||||
myIncCycles = new CheckboxWidget(_boss, _font, xpos, ypos + 1, "Increase 6507 cycles",
|
myIncCycles = new CheckboxWidget(_boss, _font, xpos, ypos + 1, "Increase 6507 cycles",
|
||||||
kIncCyclesChanged);
|
kIncCyclesChanged);
|
||||||
|
@ -68,7 +69,7 @@ void CartridgeARMWidget::addCycleWidgets(int xpos, int ypos)
|
||||||
myThumbCycles->setEditable(false);
|
myThumbCycles->setEditable(false);
|
||||||
myThumbCycles->setToolTip("Approximated CPU cycles of last ARM run.\n");
|
myThumbCycles->setToolTip("Approximated CPU cycles of last ARM run.\n");
|
||||||
|
|
||||||
auto* s = new StaticTextWidget(_boss, _font, myCycleFactor->getLeft(), ypos + 1,
|
s = new StaticTextWidget(_boss, _font, myCycleFactor->getLeft(), ypos + 1,
|
||||||
"Instructions #");
|
"Instructions #");
|
||||||
|
|
||||||
myPrevThumbInstructions = new DataGridWidget(_boss, _font, s->getRight(), ypos - 1,
|
myPrevThumbInstructions = new DataGridWidget(_boss, _font, s->getRight(), ypos - 1,
|
||||||
|
|
|
@ -777,14 +777,13 @@ uInt32 Thumbulator::read32(uInt32 addr)
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifndef UNSAFE_OPTIMIZATIONS
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
FORCE_INLINE uInt32 Thumbulator::read_register(uInt32 reg)
|
FORCE_INLINE uInt32 Thumbulator::read_register(uInt32 reg)
|
||||||
{
|
{
|
||||||
reg &= 0xF;
|
reg &= 0xF;
|
||||||
|
|
||||||
uInt32 data = reg_norm[reg];
|
uInt32 data = reg_norm[reg];
|
||||||
DO_DBUG(statusMsg << "read_register(" << dec << reg << ")=" << Base::HEX8 << data << endl);
|
DO_DBUG(statusMsg << "read_register(" << dec << reg << ")=" << Base::HEX8 << data << endl);
|
||||||
#ifndef UNSAFE_OPTIMIZATIONS
|
|
||||||
if(reg == 15)
|
if(reg == 15)
|
||||||
{
|
{
|
||||||
if(data & 1)
|
if(data & 1)
|
||||||
|
@ -793,7 +792,6 @@ FORCE_INLINE uInt32 Thumbulator::read_register(uInt32 reg)
|
||||||
data &= ~1;
|
data &= ~1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -801,9 +799,7 @@ FORCE_INLINE uInt32 Thumbulator::read_register(uInt32 reg)
|
||||||
FORCE_INLINE void Thumbulator::write_register(uInt32 reg, uInt32 data, bool isFlowBreak)
|
FORCE_INLINE void Thumbulator::write_register(uInt32 reg, uInt32 data, bool isFlowBreak)
|
||||||
{
|
{
|
||||||
reg &= 0xF;
|
reg &= 0xF;
|
||||||
|
|
||||||
DO_DBUG(statusMsg << "write_register(" << dec << reg << "," << Base::HEX8 << data << ")" << endl);
|
DO_DBUG(statusMsg << "write_register(" << dec << reg << "," << Base::HEX8 << data << ")" << endl);
|
||||||
//#ifndef UNSAFE_OPTIMIZATIONS // this fails when combined with read_register UNSAFE_OPTIMIZATIONS
|
|
||||||
if(reg == 15)
|
if(reg == 15)
|
||||||
{
|
{
|
||||||
data &= ~1;
|
data &= ~1;
|
||||||
|
@ -817,9 +813,12 @@ FORCE_INLINE void Thumbulator::write_register(uInt32 reg, uInt32 data, bool isFl
|
||||||
INC_S_CYCLES(data, AccessType::branch);
|
INC_S_CYCLES(data, AccessType::branch);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//#endif
|
|
||||||
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)
|
||||||
|
@ -1143,14 +1142,22 @@ 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
|
#ifndef UNSAFE_OPTIMIZATIONS
|
||||||
|
@ -1574,7 +1581,9 @@ 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);
|
||||||
//rc &= ~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;
|
||||||
}
|
}
|
||||||
|
@ -1596,7 +1605,7 @@ FORCE_INLINE int Thumbulator::execute() // NOLINT (readability-function-size)
|
||||||
if(rc & 1)
|
if(rc & 1)
|
||||||
{
|
{
|
||||||
// branch to odd address denotes 16 bit ARM code
|
// branch to odd address denotes 16 bit ARM code
|
||||||
//rc &= ~1;
|
rc &= ~1;
|
||||||
write_register(15, rc);
|
write_register(15, rc);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -215,8 +215,10 @@ 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);
|
||||||
|
|
Loading…
Reference in New Issue