diff --git a/src/debugger/gui/CartARMWidget.cxx b/src/debugger/gui/CartARMWidget.cxx index 33881b0b5..ab6cb38e4 100644 --- a/src/debugger/gui/CartARMWidget.cxx +++ b/src/debugger/gui/CartARMWidget.cxx @@ -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(Thumbulator::ChipType::LPC2103)); - VarList::push_back(items, "LPC2104/5/6", static_cast(Thumbulator::ChipType::LPC2104)); + VarList::push_back(items, "LPC2101" + ELLIPSIS + "3", static_cast(Thumbulator::ChipType::LPC2101)); + VarList::push_back(items, "LPC2104" + ELLIPSIS + "6 OC", static_cast(Thumbulator::ChipType::LPC2104_OC)); + VarList::push_back(items, "LPC2104" + ELLIPSIS + "6", static_cast(Thumbulator::ChipType::LPC2104)); + VarList::push_back(items, "LPC213x", static_cast(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(myChipType->getSelectedTag().toInt())); - myCart.setChipType(static_cast(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()); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/emucore/CartARM.hxx b/src/emucore/CartARM.hxx index 36df98cef..d43b4e17d 100644 --- a/src/emucore/CartARM.hxx +++ b/src/emucore/CartARM.hxx @@ -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(); } diff --git a/src/emucore/Thumbulator.cxx b/src/emucore/Thumbulator.cxx index 92402a6dc..6a6042e30 100644 --- a/src/emucore/Thumbulator.cxx +++ b/src/emucore/Thumbulator.cxx @@ -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(type)]; + _chipType = type; - _MHz = ChipProps[static_cast(_chipType)].MHz; + _MHz = props.MHz; #ifdef THUMB_CYCLE_COUNT - _flashCycles = ChipProps[static_cast(_chipType)].flashCycles; - _flashBanks = ChipProps[static_cast(_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; diff --git a/src/emucore/Thumbulator.hxx b/src/emucore/Thumbulator.hxx index 141879d9a..3d5707a9d 100644 --- a/src/emucore/Thumbulator.hxx +++ b/src/emucore/Thumbulator.hxx @@ -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(mamcr); } @@ -204,6 +205,13 @@ class Thumbulator prefetch, branch, data }; #endif + const std::array 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 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};