mirror of https://github.com/Treeki/WindEmu.git
make enough things work to boot EPOC32 successfully
This commit is contained in:
parent
e21911ff4b
commit
63e74b1513
|
@ -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);
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
|
|
Loading…
Reference in New Issue