make enough things work to boot EPOC32 successfully

This commit is contained in:
Ash Wolf 2019-12-24 14:17:14 +00:00
parent e21911ff4b
commit 63e74b1513
4 changed files with 41 additions and 27 deletions

View File

@ -37,6 +37,7 @@ void ARM710T::switchBank(BankIndex newBank) {
void ARM710T::switchMode(Mode newMode) { void ARM710T::switchMode(Mode newMode) {
auto oldMode = currentMode(); auto oldMode = currentMode();
if (newMode != oldMode) { if (newMode != oldMode) {
// log("Switching mode! %x", newMode);
switchBank(modeToBank[newMode & 0xF]); switchBank(modeToBank[newMode & 0xF]);
CPSR &= ~CPSR_ModeMask; CPSR &= ~CPSR_ModeMask;
@ -46,6 +47,7 @@ void ARM710T::switchMode(Mode newMode) {
void ARM710T::raiseException(Mode mode, uint32_t savedPC, uint32_t newPC) { void ARM710T::raiseException(Mode mode, uint32_t savedPC, uint32_t newPC) {
auto bankIndex = modeToBank[mode & 0xF]; auto bankIndex = modeToBank[mode & 0xF];
// log("Raising exception mode %x, saving PC %08x, CPSR %08x", mode, savedPC, CPSR);
SPSRs[bankIndex] = CPSR; SPSRs[bankIndex] = CPSR;
switchMode(mode); switchMode(mode);
@ -56,13 +58,14 @@ void ARM710T::raiseException(Mode mode, uint32_t savedPC, uint32_t newPC) {
} }
void ARM710T::requestFIQ() { void ARM710T::requestFIQ() {
raiseException(FIQ32, GPRs[15], 0x1C); raiseException(FIQ32, getRealPC() + 4, 0x1C);
CPSR |= CPSR_FIQDisable; CPSR |= CPSR_FIQDisable;
CPSR |= CPSR_IRQDisable; CPSR |= CPSR_IRQDisable;
} }
void ARM710T::requestIRQ() { 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; CPSR |= CPSR_IRQDisable;
} }
@ -92,14 +95,6 @@ uint32_t ARM710T::tick() {
// fetch a new instruction // fetch a new instruction
auto newInsn = readVirtual(GPRs[15], V32); 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; GPRs[15] += 4;
prefetch[0] = newInsn.first.value_or(0); prefetch[0] = newInsn.first.value_or(0);
prefetchFaults[0] = newInsn.second; prefetchFaults[0] = newInsn.second;
@ -109,10 +104,13 @@ uint32_t ARM710T::tick() {
// now deal with the one we popped // now deal with the one we popped
uint32_t clocks = 1; uint32_t clocks = 1;
if (haveInsn) { if (haveInsn) {
pcHistory[pcHistoryIndex] = {GPRs[15] - 0xC, insn};
pcHistoryIndex = (pcHistoryIndex + 1) % PcHistoryCount;
if (insnFault != NoFault) { if (insnFault != NoFault) {
// Raise a prefetch error // Raise a prefetch error
// These do not set FSR or FAR // These do not set FSR or FAR
log("prefetch error! %08x", insnFault >> MMUFaultAddressShift); log("prefetch error! %08x", insnFault >> MMUFaultAddressShift);
logPcHistory();
raiseException(Abort32, GPRs[15] - 8, 0xC); raiseException(Abort32, GPRs[15] - 8, 0xC);
} else { } else {
clocks += executeInstruction(insn); 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()]; auto saved = SPSRs[currentBank()];
switchMode(modeFromCPSR(saved)); switchMode(modeFromCPSR(saved));
CPSR = saved; CPSR = saved;
// log("dataproc restore CPSR: %08x", CPSR); // log("dataproc restore CPSR: %08x", saved);
} }
} else if (S) { } else if (S) {
CPSR = (CPSR & ~CPSR_FlagMask) | flags; 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 // datasheet specifies that base register must be
// restored if an error occurs during LDM // restored if an error occurs during LDM
if (load && fault != NoFault) if (load && fault != NoFault)
GPRs[Rn] = writeback ? updatedBase : base; GPRs[Rn] = writeback ? updatedBase : base;
if (psrForceUser && (!load || !(registerList & 0x8000))) if (psrForceUser && (store || !(registerList & 0x8000)))
switchBank(saveBank); 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) if (fault != NoFault)
reportFault(fault); reportFault(fault);
@ -1046,13 +1051,9 @@ void ARM710T::log(const char *format, ...) {
} }
} }
void ARM710T::logPcHistory() {
void ARM710T::test() { for (int i = 0; i < PcHistoryCount; i++) {
uint64_t result; pcHistoryIndex = (pcHistoryIndex + 1) % PcHistoryCount;
uint32_t flags = 0; log("%03d: %08x %08x", i, pcHistory[pcHistoryIndex].addr, pcHistory[pcHistoryIndex].insn);
uint32_t v = 0x10000000; }
SUB_OP(v, v, 1);
log("RESULT:%llx FLAGS:%08x", result, flags);
} }

View File

@ -21,8 +21,6 @@ typedef optional<uint32_t> MaybeU32;
class ARM710T class ARM710T
{ {
public: public:
void test();
enum ValueSize { V8 = 0, V32 = 1 }; enum ValueSize { V8 = 0, V32 = 1 };
enum MMUFault : uint64_t { enum MMUFault : uint64_t {
@ -106,13 +104,22 @@ public:
uint32_t getGPR(int index) const { return GPRs[index]; } uint32_t getGPR(int index) const { return GPRs[index]; }
uint32_t getCPSR() const { return CPSR; } uint32_t getCPSR() const { return CPSR; }
uint32_t getRealPC() const {
return GPRs[15] - (4 * prefetchCount);
}
void setLogger(std::function<void(const char *)> newLogger) { logger = newLogger; } void setLogger(std::function<void(const char *)> newLogger) { logger = newLogger; }
uint32_t lastPcExecuted() const { return pcHistory[(pcHistoryIndex - 1) % PcHistoryCount].addr; }
protected: protected:
void log(const char *format, ...); void log(const char *format, ...);
void logPcHistory();
private: private:
std::function<void(const char *)> logger; std::function<void(const char *)> logger;
enum { PcHistoryCount = 10 };
struct { uint32_t addr, insn; } pcHistory[PcHistoryCount];
uint32_t pcHistoryIndex = 0;
enum { Nop = 0xE1A00000 }; enum { Nop = 0xE1A00000 };
enum Mode : uint8_t { enum Mode : uint8_t {

View File

@ -315,6 +315,8 @@ void Emu::configure() {
if (configured) return; if (configured) return;
configured = true; configured = true;
srand(1000);
uart1.cpu = this; uart1.cpu = this;
uart2.cpu = this; uart2.cpu = this;
memset(&tc1, 0, sizeof(tc1)); memset(&tc1, 0, sizeof(tc1));
@ -377,6 +379,11 @@ void Emu::executeUntil(int64_t cycles) {
log("⚠️ Breakpoint triggered at %08x!", new_pc); log("⚠️ Breakpoint triggered at %08x!", new_pc);
return; return;
} }
if (new_pc >= 0x80000000 && new_pc <= 0x90000000) {
log("BAD PC %08x!!", new_pc);
logPcHistory();
return;
}
} }
} }
} }

View File

@ -17,7 +17,6 @@ MainWindow::MainWindow(QWidget *parent) :
emu->setLogger([&](const char *str) { emu->setLogger([&](const char *str) {
ui->logView->appendPlainText(str); ui->logView->appendPlainText(str);
}); });
emu->test();
timer = new QTimer(this); timer = new QTimer(this);
timer->setInterval(1000/64); timer->setInterval(1000/64);