From 621d21abe7d3ef5c587efa001a0a646d50b6e308 Mon Sep 17 00:00:00 2001 From: Ash Wolf Date: Thu, 26 Dec 2019 00:19:37 +0000 Subject: [PATCH] make some things a bit more optimised for web usage --- WindCore/arm710.cpp | 16 +++++++++++++++- WindCore/arm710.h | 13 ++++++++++--- WindCore/clps7111.cpp | 16 ++++++++++------ WindCore/emubase.h | 4 ++++ WindCore/hardware.h | 11 ++++++++--- WindCore/windermere.cpp | 21 +++++++++++++-------- WindWasm/build.sh | 2 +- WindWasm/main.cpp | 11 ++--------- 8 files changed, 63 insertions(+), 31 deletions(-) diff --git a/WindCore/arm710.cpp b/WindCore/arm710.cpp index c9fc626..5d804d3 100644 --- a/WindCore/arm710.cpp +++ b/WindCore/arm710.cpp @@ -664,15 +664,19 @@ uint32_t ARM710::execCP15RegisterTransfer(uint32_t CPOpc, bool L, uint32_t CRn, case 5: if (isTVersion) cp15_faultStatus = what; +#ifdef ARM710T_TLB else flushTlb(); +#endif break; case 6: if (isTVersion) cp15_faultAddress = what; +#ifdef ARM710T_TLB else flushTlb(what); break; +#endif case 7: #ifdef ARM710T_CACHE clearCache(); @@ -680,12 +684,14 @@ uint32_t ARM710::execCP15RegisterTransfer(uint32_t CPOpc, bool L, uint32_t CRn, #endif break; case 8: { +#ifdef ARM710T_TLB if (isTVersion) { if (CPOpc == 1) flushTlb(what); else flushTlb(); } +#endif break; } } @@ -900,6 +906,7 @@ ARM710::MMUFault ARM710::writeVirtual(uint32_t value, uint32_t virtAddr, ValueSi // TLB +#ifdef ARM710T_TLB void ARM710::flushTlb() { for (TlbEntry &e : tlb) e = {0, 0, 0, 0}; @@ -912,21 +919,28 @@ void ARM710::flushTlb(uint32_t virtAddr) { } } } +#endif ARM710::TlbEntry *ARM710::_allocateTlbEntry(uint32_t addrMask, uint32_t addr) { +#ifdef ARM710T_TLB TlbEntry *entry = &tlb[nextTlbIndex]; + nextTlbIndex = (nextTlbIndex + 1) % TlbSize; +#else + TlbEntry *entry = &singleTlbEntry; +#endif entry->addrMask = addrMask; entry->addr = addr & addrMask; - nextTlbIndex = (nextTlbIndex + 1) % TlbSize; return entry; } variant ARM710::translateAddressUsingTlb(uint32_t virtAddr, TlbEntry *useMe) { +#ifdef ARM710T_TLB // first things first, do we have a matching entry in the TLB? for (TlbEntry &e : tlb) { if (e.addrMask && (virtAddr & e.addrMask) == e.addr) return &e; } +#endif // no, so do a page table walk TlbEntry *entry; diff --git a/WindCore/arm710.h b/WindCore/arm710.h index c6cf91f..cb85566 100644 --- a/WindCore/arm710.h +++ b/WindCore/arm710.h @@ -18,6 +18,7 @@ using namespace std; // Speedhacks: //#define ARM710T_CACHE +//#define ARM710T_TLB typedef optional MaybeU32; @@ -87,7 +88,9 @@ public: #ifdef ARM710T_CACHE clearCache(); #endif +#ifdef ARM710T_TLB flushTlb(); +#endif } void setProcessorID(uint32_t v) { cp15_id = v; } @@ -239,16 +242,20 @@ private: return (MMUFault)(baseFault | (isPage ? 2 : 0) | (domain << 4) | ((uint64_t)virtAddr << 32)); } - enum { TlbSize = 64 }; struct TlbEntry { uint32_t addrMask, addr, lv1Entry, lv2Entry; }; +#ifdef ARM710T_TLB + enum { TlbSize = 64 }; TlbEntry tlb[TlbSize]; int nextTlbIndex = 0; void flushTlb(); void flushTlb(uint32_t virtAddr); - variant translateAddressUsingTlb(uint32_t virtAddr, TlbEntry *useMe=nullptr); - TlbEntry *_allocateTlbEntry(uint32_t addrMask, uint32_t addr); +#else + TlbEntry singleTlbEntry; +#endif + TlbEntry *_allocateTlbEntry(uint32_t addrMask, uint32_t addr); + variant translateAddressUsingTlb(uint32_t virtAddr, TlbEntry *useMe=nullptr); static uint32_t physAddrFromTlbEntry(TlbEntry *tlbEntry, uint32_t virtAddr); MMUFault checkAccessPermissions(TlbEntry *entry, uint32_t virtAddr, bool isWrite) const; diff --git a/WindCore/clps7111.cpp b/WindCore/clps7111.cpp index af98d79..618e546 100644 --- a/WindCore/clps7111.cpp +++ b/WindCore/clps7111.cpp @@ -147,12 +147,14 @@ void Emulator::writeReg8(uint32_t reg, uint8_t value) { void Emulator::writeReg32(uint32_t reg, uint32_t value) { if (reg == SYSCON1) { kScan = value & 0xF; - tc1.config = Timer::ENABLED; // always on with PS-7111! - if (value & 0x10) tc1.config |= Timer::PERIODIC; - if (value & 0x20) tc1.config |= Timer::MODE_512KHZ; - tc2.config = Timer::ENABLED; - if (value & 0x40) tc2.config |= Timer::PERIODIC; - if (value & 0x80) tc2.config |= Timer::MODE_512KHZ; + uint8_t tc1cfg = Timer::ENABLED; // always on with PS-7111! + if (value & 0x10) tc1cfg |= Timer::PERIODIC; + if (value & 0x20) tc1cfg |= Timer::MODE_512KHZ; + uint8_t tc2cfg = Timer::ENABLED; + if (value & 0x40) tc2cfg |= Timer::PERIODIC; + if (value & 0x80) tc2cfg |= Timer::MODE_512KHZ; + tc1.setConfig(tc1cfg); + tc2.setConfig(tc2cfg); } else if (reg == INTMR1) { interruptMask &= 0xFFFF0000;; interruptMask |= (value & 0xFFFF); @@ -277,6 +279,8 @@ void Emulator::configure() { tc2.clockSpeed = CLOCK_SPEED; nextTickAt = TICK_INTERVAL; + tc1.nextTickAt = tc1.tickInterval(); + tc2.nextTickAt = tc2.tickInterval(); rtc = getRTC(); reset(); diff --git a/WindCore/emubase.h b/WindCore/emubase.h index a5a6f70..ae35d9d 100644 --- a/WindCore/emubase.h +++ b/WindCore/emubase.h @@ -103,7 +103,9 @@ enum EpocKey { class EmuBase : public ARM710 { protected: +#ifndef __EMSCRIPTEN__ std::unordered_set _breakpoints; +#endif int64_t passedCycles = 0; int64_t nextTickAt = 0; uint8_t readKeyboard(int kScan); @@ -127,7 +129,9 @@ public: virtual void setKeyboardKey(EpocKey key, bool value) = 0; virtual void updateTouchInput(int32_t x, int32_t y, bool down) = 0; +#ifndef __EMSCRIPTEN__ std::unordered_set &breakpoints() { return _breakpoints; } +#endif uint64_t currentCycles() const { return passedCycles; } }; diff --git a/WindCore/hardware.h b/WindCore/hardware.h index c1857ae..02ac948 100644 --- a/WindCore/hardware.h +++ b/WindCore/hardware.h @@ -10,7 +10,7 @@ struct Timer { PERIODIC = 1<<6, ENABLED = 1<<7 }; - int64_t lastTicked; + int64_t nextTickAt; uint8_t config; uint32_t interval; int32_t value; @@ -23,9 +23,14 @@ struct Timer { interval = lval; value = lval; } + void setConfig(uint8_t cval) { + nextTickAt -= tickInterval(); + config = cval; + nextTickAt += tickInterval(); + } bool tick(int64_t cycles) { - if (cycles >= (lastTicked + tickInterval())) { - lastTicked += tickInterval(); + if (cycles >= nextTickAt) { + nextTickAt += tickInterval(); if (config & ENABLED) { --value; diff --git a/WindCore/windermere.cpp b/WindCore/windermere.cpp index 7ca6a8c..41bbe70 100644 --- a/WindCore/windermere.cpp +++ b/WindCore/windermere.cpp @@ -115,9 +115,9 @@ void Emulator::writeReg8(uint32_t reg, uint8_t value) { } else if ((reg & 0xF00) == 0x700) { uart2.writeReg8(reg & 0xFF, value); } else if (reg == TC1CTRL) { - tc1.config = value; + tc1.setConfig(value); } else if (reg == TC2CTRL) { - tc2.config = value; + tc2.setConfig(value); } else if (reg == PADR) { uint32_t oldPorts = portValues; portValues &= 0x00FFFFFF; @@ -364,6 +364,8 @@ void Emulator::configure() { tc2.clockSpeed = CLOCK_SPEED; nextTickAt = TICK_INTERVAL; + tc1.nextTickAt = tc1.tickInterval(); + tc2.nextTickAt = tc2.tickInterval(); rtc = getRTC(); reset(); @@ -413,22 +415,25 @@ void Emulator::executeUntil(int64_t cycles) { // what's running? if (halted) { // keep the clock moving - passedCycles++; + // when does the next earliest thing happen? + // this stops us from spinning needlessly + int64_t nextEvent = nextTickAt; + if (tc1.nextTickAt < nextEvent) nextEvent = tc1.nextTickAt; + if (tc2.nextTickAt < nextEvent) nextEvent = tc2.nextTickAt; + if (cycles < nextEvent) nextEvent = cycles; + passedCycles = nextEvent; } else { if (auto v = virtToPhys(getGPR(15) - 0xC); v.has_value() && instructionReady()) debugPC(v.value()); passedCycles += tick(); +#ifndef __EMSCRIPTEN__ uint32_t new_pc = getGPR(15) - 0xC; if (_breakpoints.find(new_pc) != _breakpoints.end()) { log("⚠️ Breakpoint triggered at %08x!", new_pc); return; } - if (new_pc >= 0x80000000 && new_pc <= 0x90000000) { - log("BAD PC %08x!!", new_pc); - logPcHistory(); - return; - } +#endif } } } diff --git a/WindWasm/build.sh b/WindWasm/build.sh index fb52887..00aa9d8 100755 --- a/WindWasm/build.sh +++ b/WindWasm/build.sh @@ -1,6 +1,6 @@ #!/bin/sh -FLAGS="-O3 --profiling -s WASM_OBJECT_FILES=0 -std=c++17" +FLAGS="-O3 --profiling -g -s WASM_OBJECT_FILES=0 -std=c++17" mkdir -p obj for i in arm710 emubase etna windermere; do emcc -c $FLAGS -o obj/$i.o ../WindCore/$i.cpp; done diff --git a/WindWasm/main.cpp b/WindWasm/main.cpp index b785226..c05ba67 100644 --- a/WindWasm/main.cpp +++ b/WindWasm/main.cpp @@ -120,15 +120,8 @@ int main(int argc, char **argv) { printf("SDL_SetVideoMode failed: %s\n", SDL_GetError()); return 1; } - // window = SDL_CreateWindow( - // "WindEmu", - // SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, - // emu->getDigitiserWidth(), emu->getDigitiserHeight(), - // 0); - // if (window == NULL) { - // printf("SDL_CreateWindow failed: %s\n", SDL_GetError()); - // return 1; - // } + + EM_ASM("SDL.defaults.copyOnLock = false; SDL.defaults.discardOnLock = true; SDL.defaults.opaqueFrontBuffer = false;"); emscripten_set_main_loop(&emuEventLoop, 64, 1);