added more chips types for ARM cycle count

added missing cycle counts for push and pop
added music update cycles to ARM cycle count for CDFJ
fixed stmia cycle counts
This commit is contained in:
Thomas Jentzsch 2021-06-27 09:44:42 +02:00
parent 287ab8b742
commit 6175176a6a
4 changed files with 123 additions and 53 deletions

View File

@ -89,8 +89,10 @@ void CartridgeARMWidget::addCycleWidgets(int xpos, int ypos)
- PopUpWidget::dropDownWidth(_font);
items.clear();
VarList::push_back(items, "LPC2101/2/3", static_cast<uInt32>(Thumbulator::ChipType::LPC2103));
VarList::push_back(items, "LPC2104/5/6", static_cast<uInt32>(Thumbulator::ChipType::LPC2104));
VarList::push_back(items, "LPC2101" + ELLIPSIS + "3", static_cast<uInt32>(Thumbulator::ChipType::LPC2101));
VarList::push_back(items, "LPC2104" + ELLIPSIS + "6 OC", static_cast<uInt32>(Thumbulator::ChipType::LPC2104_OC));
VarList::push_back(items, "LPC2104" + ELLIPSIS + "6", static_cast<uInt32>(Thumbulator::ChipType::LPC2104));
VarList::push_back(items, "LPC213x", static_cast<uInt32>(Thumbulator::ChipType::LPC213x));
myChipType = new PopUpWidget(_boss, _font, xpos, ypos, pwidth, myLineHeight, items,
"Chip ", 0, kChipChanged);
myChipType->setToolTip("Select emulated ARM chip.");
@ -221,8 +223,19 @@ void CartridgeARMWidget::handleChipType()
}
myChipType->setEnabled(devSettings);
Thumbulator::ChipPropsType chipProps = myCart.setChipType(static_cast<Thumbulator::ChipType>(myChipType->getSelectedTag().toInt()));
myCart.setChipType(static_cast<Thumbulator::ChipType>(myChipType->getSelectedTag().toInt()));
// update tooltip with currently selecte chip's properties
string tip = myChipType->getToolTip(Common::Point(0, 0));
ostringstream buf;
tip = tip.substr(0, 25);
buf << tip << "\nCurrent:\n"
<< chipProps.MHz << " MHz, "
<< chipProps.flashBanks << " flash bank"
<< (chipProps.flashBanks > 1 ? "s" : "") << ", "
<< chipProps.flashCycles - 1 << " wait states";
myChipType->setToolTip(buf.str());
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

View File

@ -78,7 +78,9 @@ class CartridgeARM : public Cartridge
void incCycles(bool enable);
void cycleFactor(double factor);
double cycleFactor() const { return myThumbEmulator->cycleFactor(); }
void setChipType(Thumbulator::ChipType chipType) { myThumbEmulator->setChipType(chipType); }
Thumbulator::ChipPropsType setChipType(Thumbulator::ChipType chipType) {
return myThumbEmulator->setChipType(chipType);
}
void lockMamMode(bool lock) { myThumbEmulator->lockMamMode(lock); }
void setMamMode(Thumbulator::MamModeType mamMode) { myThumbEmulator->setMamMode(mamMode); }
Thumbulator::MamModeType mamMode() const { return myThumbEmulator->mamMode(); }

View File

@ -65,13 +65,16 @@ using Common::Base;
#define INC_I_CYCLES_M(m) \
if(_countCycles) \
incICycles(m)
#define FETCH_TYPE_N \
_fetchCycleType = CycleType::N
#define INC_CYCLES(m) \
_totalCycles += m
#define FETCH_TYPE_N \
_fetchCycleType = CycleType::N
#else
#define INC_S_CYCLES(addr, accessType)
#define INC_N_CYCLES(addr, accessType)
#define INC_I_CYCLES
#define INC_I_CYCLES_M(m)
#define INC_CYCLES(m)
#define FETCH_TYPE_N
#endif
@ -1516,7 +1519,7 @@ int Thumbulator::execute()
}
else if (pc == 0x0000083a)
{
// exiting Custom ARM code, returning to BUS Driver control
// exiting Custom ARM code, returning to CDF Driver control
}
else
{
@ -1560,26 +1563,42 @@ int Thumbulator::execute()
if (pc == CDF1_SetNote)
{
myCartridge->thumbCallback(0, read_register(2), read_register(3));
// approximated cycles
INC_CYCLES(_flashCycles + 1); // this instruction
INC_CYCLES(6); // ARM code NoteStore
INC_CYCLES(2 + _flashCycles + 2); // ARM code ReturnC
handled = true;
}
else if (pc == CDF1_ResetWave)
{
myCartridge->thumbCallback(1, read_register(2), 0);
// approximated cycles
INC_CYCLES(_flashCycles + 1); // this instruction
INC_CYCLES(6 + _flashCycles + 2); // ARM code ResetWaveStore
INC_CYCLES(2 + _flashCycles + 2); // ARM code ReturnC
handled = true;
}
else if (pc == CDF1_GetWavePtr)
{
write_register(2, myCartridge->thumbCallback(2, read_register(2), 0));
// approximated cycles
INC_CYCLES(_flashCycles + 1); // this instruction
INC_CYCLES(6 + _flashCycles + 2); // ARM code WavePtrFetch
INC_CYCLES(2 + _flashCycles + 2); // ARM code ReturnC
handled = true;
}
else if (pc == CDF1_SetWaveSize)
{
myCartridge->thumbCallback(3, read_register(2), read_register(3));
// approximated cycles
INC_CYCLES(_flashCycles + 1); // this instruction
INC_CYCLES(18 + _flashCycles * 3 + 2); // ARM code WaveSizeStore
INC_CYCLES(2 + _flashCycles + 2); // ARM code ReturnC
handled = true;
}
else if (pc == 0x0000083a)
{
// exiting Custom ARM code, returning to BUS Driver control
// exiting Custom ARM code, returning to CDFJ Driver control
}
else
{
@ -2195,6 +2214,7 @@ int Thumbulator::execute()
}
statusMsg << "}" << endl;
#endif
bool first = true;
sp = read_register(13);
for(ra = 0, rb = 0x01; rb; rb = (rb << 1) & 0xFF, ++ra)
@ -2202,19 +2222,29 @@ int Thumbulator::execute()
if(inst & rb)
{
write_register(ra, read32(sp));
//INC_S_CYCLES(sp, AccessType::data); // TODO
if(first)
{
INC_N_CYCLES(sp, AccessType::data);
first = false;
}
else
INC_S_CYCLES(sp, AccessType::data);
sp += 4;
}
}
if(inst & 0x100)
{
rc = read32(sp);
if(first)
INC_N_CYCLES(sp, AccessType::data);
else
INC_S_CYCLES(sp, AccessType::data);
rc += 2;
write_register(15, rc);
//INC_S_CYCLES(sp, AccessType::data); // TODO
sp += 4;
}
write_register(13, sp);
INC_I_CYCLES; // ??? (copied from stmia)
return 0;
}
@ -2251,13 +2281,21 @@ int Thumbulator::execute()
if(inst & 0x100) ++rc;
rc <<= 2;
sp -= rc;
bool first = true;
rd = sp;
for(ra = 0, rb = 0x01; rb; rb = (rb << 1) & 0xFF, ++ra)
{
if(inst & rb)
{
write32(rd, read_register(ra));
//INC_S_CYCLES(rd, AccessType::data); // TODO
if(first)
{
INC_N_CYCLES(rd, AccessType::data);
first = false;
}
else
INC_S_CYCLES(rd, AccessType::data);
rd += 4;
}
}
@ -2265,13 +2303,18 @@ int Thumbulator::execute()
{
rc = read_register(14);
write32(rd, rc);
//INC_S_CYCLES(rd, AccessType::data); // TODO
if(first)
INC_N_CYCLES(rd, AccessType::data);
else
INC_S_CYCLES(rd, AccessType::data);
if((rc & 1) == 0)
{
// FIXME fprintf(stderr,"push {lr} with an ARM address pc 0x%08X popped 0x%08X\n",pc,rc);
}
}
write_register(13, sp);
INC_I_CYCLES; // ??? (copied from ldmia)
FETCH_TYPE_N; // ??? (copied from ldmia)
return 0;
}
@ -2409,11 +2452,11 @@ int Thumbulator::execute()
write32(sp, read_register(ra));
if(first)
{
INC_N_CYCLES(rb, AccessType::data);
INC_N_CYCLES(sp, AccessType::data);
first = false;
}
else
INC_S_CYCLES(rb, AccessType::data);
INC_S_CYCLES(sp, AccessType::data);
sp += 4;
}
}
@ -2750,16 +2793,20 @@ int Thumbulator::reset()
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void Thumbulator::setChipType(ChipType type)
Thumbulator::ChipPropsType Thumbulator::setChipType(ChipType type)
{
ChipPropsType props = ChipProps[static_cast<uInt32>(type)];
_chipType = type;
_MHz = ChipProps[static_cast<uInt32>(_chipType)].MHz;
_MHz = props.MHz;
#ifdef THUMB_CYCLE_COUNT
_flashCycles = ChipProps[static_cast<uInt32>(_chipType)].flashCycles;
_flashBanks = ChipProps[static_cast<uInt32>(_chipType)].flashBanks;
_flashCycles = props.flashCycles;
_flashBanks = props.flashBanks;
#endif
setConsoleTiming(_consoleTiming);
return props;
}
#ifdef THUMB_CYCLE_COUNT
@ -2866,12 +2913,11 @@ void Thumbulator::incCycles(AccessType accessType, uInt32 cycles)
{
#ifdef EMULATE_PIPELINE
// simulate the pipeline effects
if(_memory0Pipeline)
{
--_memory0Pipeline; // == 0
++_fetchPipeline;
}
//if(_memory0Pipeline)
//{
// --_memory0Pipeline; // == 0
// ++_fetchPipeline;
//}
if(_memory1Pipeline)
{
--_memory1Pipeline;
@ -2896,20 +2942,26 @@ void Thumbulator::incCycles(AccessType accessType, uInt32 cycles)
// Reduce cycles by pipelined cycles
// Cart (Turbo start sequence): 1F0AC
// None: 1FF2E @ 90% (22989 @ 100%)
#if 0
// Version 1: 1ECFC @ 90% (223C3 @ 100%)
uInt32 newCycles = std::max(1, Int32(cycles - _fetchPipeline));
_fetchPipeline -= (cycles - newCycles);
cycles = newCycles;
#endif
#if 1
// Version 1: 1ECFC @ 90% (223C3 @ 100%)
if(cycles == _flashCycles)
{
if(!_memory1Pipeline) // there must be no pending memory access
{
uInt32 newCycles = std::max(1, Int32(cycles - _fetchPipeline));
_fetchPipeline -= (cycles - newCycles);
cycles = newCycles;
}
}
#endif
#if 0
// Version 2: 1ED23 @ 90% (223EF @ 100%)
// considers that partial fetches are not allowed
if(cycles == _flashCycles)
{
_memory0Pipeline = _memory1Pipeline = 0;
if(_fetchPipeline >= _flashCycles)
//_memory0Pipeline = _memory1Pipeline = 0;
if(!_memory1Pipeline && _fetchPipeline >= _flashCycles)
{
_fetchPipeline -= (_flashCycles - 1);
cycles = 1;
@ -2935,7 +2987,7 @@ void Thumbulator::incSCycles(uInt32 addr, AccessType accessType)
else // Flash
{
if(mamcr == MamModeType::mode0)
cycles = _flashCycles; // 4
cycles = _flashCycles; // 3|4
else
{
if(isMamBuffered(addr, accessType) || mamcr == MamModeType::modeX)
@ -2957,7 +3009,7 @@ void Thumbulator::incNCycles(uInt32 addr, AccessType accessType)
else // Flash
{
if(mamcr < MamModeType::mode2)
cycles = _flashCycles; // 4
cycles = _flashCycles; // 3|4
else
if(isMamBuffered(addr, accessType) || mamcr == MamModeType::modeX)
cycles = 1;
@ -2972,11 +3024,13 @@ void Thumbulator::incICycles(uInt32 m)
{
#ifdef EMULATE_PIPELINE
_fetchPipeline += m;
if(_memory0Pipeline)
{
--_memory0Pipeline; // == 0
++_fetchPipeline;
}
//if(_memory0Pipeline)
//{
// --_memory0Pipeline; // == 0
// ++_fetchPipeline;
//}
// TODO: m!
if(_memory1Pipeline)
{
--_memory1Pipeline;

View File

@ -52,7 +52,7 @@ class Cartridge;
#endif
#ifdef THUMB_CYCLE_COUNT
//#define EMULATE_PIPELINE // enable coarse ARM pipeline emulation
//#define EMULATE_PIPELINE // enable coarse ARM pipeline emulation (TODO)
#define TIMER_0 // enable timer 0 support (e.g. for measuring cycle count)
#endif
@ -70,9 +70,10 @@ class Thumbulator
DPCplus // cartridges of type DPC+
};
enum class ChipType {
LPC2103, // Harmony
LPC2104, // Encore (includes LPC2105)
LPC2132, // future use
LPC2101, // Harmony (includes LPC2103)
LPC2104_OC, // Dev cart overclocked (includes LPC2105)
LPC2104, // Dev cart (includes LPC2105)
LPC213x, // future use (includes LPC2132)
numTypes
};
enum class MamModeType {
@ -108,7 +109,7 @@ class Thumbulator
void enableCycleCount(bool enable) { _countCycles = enable; }
const Stats& stats() const { return _stats; }
uInt32 cycles() const { return _totalCycles; }
void setChipType(ChipType type);
ChipPropsType setChipType(ChipType type);
void setMamMode(MamModeType mode) { mamcr = mode; }
void lockMamMode(bool lock) { _lockMamcr = lock; }
MamModeType mamMode() const { return static_cast<MamModeType>(mamcr); }
@ -204,6 +205,13 @@ class Thumbulator
prefetch, branch, data
};
#endif
const std::array<ChipPropsType, uInt32(ChipType::numTypes)> ChipProps =
{{
{ 70.0, 4, 1 }, // LPC2101_02_03
{ 70.0, 4, 2 }, // LPC2104_05_06 Overclocked
{ 60.0, 3, 2 }, // LPC2104_05_06
{ 60.0, 3, 1 }, // LPC2132..
}};
private:
string doRun(uInt32& cycles, bool irqDrivenAudio);
@ -262,7 +270,7 @@ class Thumbulator
MamModeType mamcr{MamModeType::mode0};
bool handler_mode{false};
uInt32 systick_ctrl{0}, systick_reload{0}, systick_count{0}, systick_calibrate{0};
ChipType _chipType{ChipType::LPC2103};
ChipType _chipType{ChipType::LPC2101};
ConsoleTiming _consoleTiming{ConsoleTiming::ntsc};
double _MHz{70.0};
uInt32 _flashCycles{4};
@ -288,13 +296,6 @@ class Thumbulator
ostringstream statusMsg;
bool trapOnFatal{true};
#endif
const std::array<ChipPropsType, uInt32(ChipType::numTypes)> ChipProps =
{{
{ 70.0, 4, 1 }, // LPC2101_02_03
{ 60.0, 3, 2 }, // LPC2104_05_06
{ 60.0, 3, 1 }, // LPC2132..
}};
bool _countCycles{false};
bool _lockMamcr{false};