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) {
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -21,8 +21,6 @@ typedef optional<uint32_t> 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<void(const char *)> newLogger) { logger = newLogger; }
|
||||
uint32_t lastPcExecuted() const { return pcHistory[(pcHistoryIndex - 1) % PcHistoryCount].addr; }
|
||||
protected:
|
||||
void log(const char *format, ...);
|
||||
void logPcHistory();
|
||||
private:
|
||||
std::function<void(const char *)> logger;
|
||||
|
||||
enum { PcHistoryCount = 10 };
|
||||
struct { uint32_t addr, insn; } pcHistory[PcHistoryCount];
|
||||
uint32_t pcHistoryIndex = 0;
|
||||
|
||||
enum { Nop = 0xE1A00000 };
|
||||
|
||||
enum Mode : uint8_t {
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in New Issue