diff options
author | Arisotura <thetotalworm@gmail.com> | 2021-10-28 19:45:32 +0200 |
---|---|---|
committer | Arisotura <thetotalworm@gmail.com> | 2021-10-28 19:45:32 +0200 |
commit | 9d82826cdb84aa5e261d6a55e42812652e6ab13f (patch) | |
tree | 4174270113508614abb2968b2ce91159e3bffaa2 | |
parent | ae489d9e033ae22b56bb99bd44d23423320ab874 (diff) |
fix some gaps in CPU modes
* non-defined CPU modes are actually possible
* bit4 of all PSRs is forced to one (modes 00-0F aren't possible)
* modes 14/15/16 and 18/19/1A share a SPSR with modes 17 and 1B respectively (but they don't share the register banks)
* modes 10 and 1C/1D/1E don't have a SPSR (MRS returns the CPSR always)
-rw-r--r-- | src/ARM.cpp | 24 | ||||
-rw-r--r-- | src/ARMInterpreter.cpp | 34 |
2 files changed, 55 insertions, 3 deletions
diff --git a/src/ARM.cpp b/src/ARM.cpp index 03844b6..bdb10bf 100644 --- a/src/ARM.cpp +++ b/src/ARM.cpp @@ -109,6 +109,22 @@ void ARM::Reset() CPSR = 0x000000D3; + for (int i = 0; i < 7; i++) + R_FIQ[i] = 0; + for (int i = 0; i < 2; i++) + { + R_SVC[i] = 0; + R_ABT[i] = 0; + R_IRQ[i] = 0; + R_UND[i] = 0; + } + + R_FIQ[7] = 0x00000010; + R_SVC[2] = 0x00000010; + R_ABT[2] = 0x00000010; + R_IRQ[2] = 0x00000010; + R_UND[2] = 0x00000010; + ExceptionBase = Num ? 0x00000000 : 0xFFFF0000; CodeMem.Mem = NULL; @@ -375,10 +391,16 @@ void ARM::RestoreCPSR() CPSR = R_SVC[2]; break; + case 0x14: + case 0x15: + case 0x16: case 0x17: CPSR = R_ABT[2]; break; + case 0x18: + case 0x19: + case 0x1A: case 0x1B: CPSR = R_UND[2]; break; @@ -388,6 +410,8 @@ void ARM::RestoreCPSR() break; } + CPSR |= 0x00000010; + UpdateMode(oldcpsr, CPSR); } diff --git a/src/ARMInterpreter.cpp b/src/ARMInterpreter.cpp index db2c925..3b8408a 100644 --- a/src/ARMInterpreter.cpp +++ b/src/ARMInterpreter.cpp @@ -69,9 +69,17 @@ void A_MSR_IMM(ARM* cpu) case 0x11: psr = &cpu->R_FIQ[7]; break; case 0x12: psr = &cpu->R_IRQ[2]; break; case 0x13: psr = &cpu->R_SVC[2]; break; + case 0x14: + case 0x15: + case 0x16: case 0x17: psr = &cpu->R_ABT[2]; break; + case 0x18: + case 0x19: + case 0x1A: case 0x1B: psr = &cpu->R_UND[2]; break; - default: printf("bad CPU mode %08X\n", cpu->CPSR); return; + default: + cpu->AddCycles_C(); + return; } } else @@ -92,6 +100,9 @@ void A_MSR_IMM(ARM* cpu) u32 val = ROR((cpu->CurInstr & 0xFF), ((cpu->CurInstr >> 7) & 0x1E)); + // bit4 is forced to 1 + val |= 0x00000010; + *psr &= ~mask; *psr |= (val & mask); @@ -111,9 +122,17 @@ void A_MSR_REG(ARM* cpu) case 0x11: psr = &cpu->R_FIQ[7]; break; case 0x12: psr = &cpu->R_IRQ[2]; break; case 0x13: psr = &cpu->R_SVC[2]; break; + case 0x14: + case 0x15: + case 0x16: case 0x17: psr = &cpu->R_ABT[2]; break; + case 0x18: + case 0x19: + case 0x1A: case 0x1B: psr = &cpu->R_UND[2]; break; - default: printf("bad CPU mode %08X\n", cpu->CPSR); return; + default: + cpu->AddCycles_C(); + return; } } else @@ -134,6 +153,9 @@ void A_MSR_REG(ARM* cpu) u32 val = cpu->R[cpu->CurInstr & 0xF]; + // bit4 is forced to 1 + val |= 0x00000010; + *psr &= ~mask; *psr |= (val & mask); @@ -153,9 +175,15 @@ void A_MRS(ARM* cpu) case 0x11: psr = cpu->R_FIQ[7]; break; case 0x12: psr = cpu->R_IRQ[2]; break; case 0x13: psr = cpu->R_SVC[2]; break; + case 0x14: + case 0x15: + case 0x16: case 0x17: psr = cpu->R_ABT[2]; break; + case 0x18: + case 0x19: + case 0x1A: case 0x1B: psr = cpu->R_UND[2]; break; - default: printf("bad CPU mode %08X\n", cpu->CPSR); return; + default: psr = cpu->CPSR; break; } } else |