diff --git a/WindCore/arm710t.cpp b/WindCore/arm710t.cpp index db0c8f2..324bb00 100644 --- a/WindCore/arm710t.cpp +++ b/WindCore/arm710t.cpp @@ -37,6 +37,7 @@ void ARM710T::switchBank(BankIndex newBank) { void ARM710T::switchMode(Mode newMode) { auto oldMode = currentMode(); if (newMode != oldMode) { +// log("Switching mode! %x", newMode); switchBank(modeToBank[newMode & 0xF]); CPSR &= ~CPSR_ModeMask; @@ -46,6 +47,7 @@ void ARM710T::switchMode(Mode newMode) { void ARM710T::raiseException(Mode mode, uint32_t savedPC, uint32_t newPC) { auto bankIndex = modeToBank[mode & 0xF]; +// log("Raising exception mode %x, saving PC %08x, CPSR %08x", mode, savedPC, CPSR); SPSRs[bankIndex] = CPSR; switchMode(mode); @@ -56,13 +58,14 @@ void ARM710T::raiseException(Mode mode, uint32_t savedPC, uint32_t newPC) { } void ARM710T::requestFIQ() { - raiseException(FIQ32, GPRs[15], 0x1C); + raiseException(FIQ32, getRealPC() + 4, 0x1C); CPSR |= CPSR_FIQDisable; CPSR |= CPSR_IRQDisable; } void ARM710T::requestIRQ() { - raiseException(FIQ32, GPRs[15], 0x18); +// log("Requesting IRQ: Last exec = %08x, setting LR = %08x", lastPcExecuted(), getRealPC() + 4); + raiseException(IRQ32, getRealPC() + 4, 0x18); CPSR |= CPSR_IRQDisable; } @@ -92,14 +95,6 @@ uint32_t ARM710T::tick() { // fetch a new instruction auto newInsn = readVirtual(GPRs[15], V32); - if (GPRs[15] < 0x10 || GPRs[15] > 0xA0000000) { - log("HACK HACK HACK 2"); - log("PC=%08x LR=%08x", GPRs[15], GPRs[14]); - } -// if (GPRs[15] == 0x50100000) { -// log("HACK HACK HACK"); -// log("LR=%08x", GPRs[14]); -// } GPRs[15] += 4; prefetch[0] = newInsn.first.value_or(0); prefetchFaults[0] = newInsn.second; @@ -109,10 +104,13 @@ uint32_t ARM710T::tick() { // now deal with the one we popped uint32_t clocks = 1; if (haveInsn) { + pcHistory[pcHistoryIndex] = {GPRs[15] - 0xC, insn}; + pcHistoryIndex = (pcHistoryIndex + 1) % PcHistoryCount; if (insnFault != NoFault) { // Raise a prefetch error // These do not set FSR or FAR log("prefetch error! %08x", insnFault >> MMUFaultAddressShift); + logPcHistory(); raiseException(Abort32, GPRs[15] - 8, 0xC); } else { clocks += executeInstruction(insn); @@ -370,7 +368,7 @@ uint32_t ARM710T::execDataProcessing(bool I, uint32_t Opcode, bool S, uint32_t R auto saved = SPSRs[currentBank()]; switchMode(modeFromCPSR(saved)); CPSR = saved; -// log("dataproc restore CPSR: %08x", CPSR); +// log("dataproc restore CPSR: %08x", saved); } } else if (S) { CPSR = (CPSR & ~CPSR_FlagMask) | flags; @@ -562,17 +560,24 @@ uint32_t ARM710T::execBlockDataTransfer(uint32_t PUSWL, uint32_t Rn, uint32_t re } } - if (registerList & 0x8000) - prefetchCount = 0; - // datasheet specifies that base register must be // restored if an error occurs during LDM if (load && fault != NoFault) GPRs[Rn] = writeback ? updatedBase : base; - if (psrForceUser && (!load || !(registerList & 0x8000))) + if (psrForceUser && (store || !(registerList & 0x8000))) switchBank(saveBank); + if (load && (registerList & 0x8000)) { + prefetchCount = 0; + if (psrForceUser && isPrivileged() && fault == NoFault) { + auto saved = SPSRs[currentBank()]; + switchMode(modeFromCPSR(saved)); + CPSR = saved; +// log("reloading saved SPSR: %08x", saved); + } + } + if (fault != NoFault) reportFault(fault); @@ -1046,13 +1051,9 @@ void ARM710T::log(const char *format, ...) { } } - -void ARM710T::test() { - uint64_t result; - uint32_t flags = 0; - uint32_t v = 0x10000000; - - SUB_OP(v, v, 1); - - log("RESULT:%llx FLAGS:%08x", result, flags); +void ARM710T::logPcHistory() { + for (int i = 0; i < PcHistoryCount; i++) { + pcHistoryIndex = (pcHistoryIndex + 1) % PcHistoryCount; + log("%03d: %08x %08x", i, pcHistory[pcHistoryIndex].addr, pcHistory[pcHistoryIndex].insn); + } } diff --git a/WindCore/arm710t.h b/WindCore/arm710t.h index 2ce7f25..009cdbd 100644 --- a/WindCore/arm710t.h +++ b/WindCore/arm710t.h @@ -21,8 +21,6 @@ typedef optional MaybeU32; class ARM710T { public: - void test(); - enum ValueSize { V8 = 0, V32 = 1 }; enum MMUFault : uint64_t { @@ -106,13 +104,22 @@ public: uint32_t getGPR(int index) const { return GPRs[index]; } uint32_t getCPSR() const { return CPSR; } + uint32_t getRealPC() const { + return GPRs[15] - (4 * prefetchCount); + } void setLogger(std::function newLogger) { logger = newLogger; } + uint32_t lastPcExecuted() const { return pcHistory[(pcHistoryIndex - 1) % PcHistoryCount].addr; } protected: void log(const char *format, ...); + void logPcHistory(); private: std::function logger; + enum { PcHistoryCount = 10 }; + struct { uint32_t addr, insn; } pcHistory[PcHistoryCount]; + uint32_t pcHistoryIndex = 0; + enum { Nop = 0xE1A00000 }; enum Mode : uint8_t { diff --git a/WindCore/emu.cpp b/WindCore/emu.cpp index fbac14f..7fb0583 100644 --- a/WindCore/emu.cpp +++ b/WindCore/emu.cpp @@ -315,6 +315,8 @@ void Emu::configure() { if (configured) return; configured = true; + srand(1000); + uart1.cpu = this; uart2.cpu = this; memset(&tc1, 0, sizeof(tc1)); @@ -377,6 +379,11 @@ void Emu::executeUntil(int64_t cycles) { log("⚠️ Breakpoint triggered at %08x!", new_pc); return; } + if (new_pc >= 0x80000000 && new_pc <= 0x90000000) { + log("BAD PC %08x!!", new_pc); + logPcHistory(); + return; + } } } } diff --git a/WindQt/mainwindow.cpp b/WindQt/mainwindow.cpp index 4472194..b9c4fe3 100644 --- a/WindQt/mainwindow.cpp +++ b/WindQt/mainwindow.cpp @@ -17,7 +17,6 @@ MainWindow::MainWindow(QWidget *parent) : emu->setLogger([&](const char *str) { ui->logView->appendPlainText(str); }); - emu->test(); timer = new QTimer(this); timer->setInterval(1000/64);