diff options
author | StapleButter <thetotalworm@gmail.com> | 2016-12-03 04:41:10 +0100 |
---|---|---|
committer | StapleButter <thetotalworm@gmail.com> | 2016-12-03 04:41:10 +0100 |
commit | 30f85e3400d0cd69001976b70ed2d79b6b3cfdd9 (patch) | |
tree | 1d0731da240da16069bddb77411600c322f9f8e3 | |
parent | 6213245f3a49a3aa23aae7d53ad78c28a22f65ed (diff) |
more instructions. some handling of CPU mode switching.
-rw-r--r-- | ARM.cpp | 76 | ||||
-rw-r--r-- | ARM.h | 2 | ||||
-rw-r--r-- | ARMInterpreter.cpp | 51 | ||||
-rw-r--r-- | ARM_InstrTable.h | 128 | ||||
-rw-r--r-- | melonDS.depend | 10 |
5 files changed, 198 insertions, 69 deletions
@@ -74,6 +74,82 @@ void ARM::RestoreCPSR() printf("TODO: restore CPSR\n"); } +void ARM::UpdateMode(u32 oldmode, u32 newmode) +{ + u32 temp; + #define SWAP(a, b) temp = a; a = b; b = temp; + + if ((oldmode & 0x1F) == (newmode & 0x1F)) return; + + switch (oldmode & 0x1F) + { + case 0x11: + SWAP(R[8], R_FIQ[0]); + SWAP(R[9], R_FIQ[1]); + SWAP(R[10], R_FIQ[2]); + SWAP(R[11], R_FIQ[3]); + SWAP(R[12], R_FIQ[4]); + SWAP(R[13], R_FIQ[5]); + SWAP(R[14], R_FIQ[6]); + break; + + case 0x12: + SWAP(R[13], R_IRQ[0]); + SWAP(R[14], R_IRQ[1]); + break; + + case 0x13: + SWAP(R[13], R_SVC[0]); + SWAP(R[14], R_SVC[1]); + break; + + case 0x17: + SWAP(R[13], R_ABT[0]); + SWAP(R[14], R_ABT[1]); + break; + + case 0x1B: + SWAP(R[13], R_UND[0]); + SWAP(R[14], R_UND[1]); + break; + } + + switch (newmode & 0x1F) + { + case 0x11: + SWAP(R[8], R_FIQ[0]); + SWAP(R[9], R_FIQ[1]); + SWAP(R[10], R_FIQ[2]); + SWAP(R[11], R_FIQ[3]); + SWAP(R[12], R_FIQ[4]); + SWAP(R[13], R_FIQ[5]); + SWAP(R[14], R_FIQ[6]); + break; + + case 0x12: + SWAP(R[13], R_IRQ[0]); + SWAP(R[14], R_IRQ[1]); + break; + + case 0x13: + SWAP(R[13], R_SVC[0]); + SWAP(R[14], R_SVC[1]); + break; + + case 0x17: + SWAP(R[13], R_ABT[0]); + SWAP(R[14], R_ABT[1]); + break; + + case 0x1B: + SWAP(R[13], R_UND[0]); + SWAP(R[14], R_UND[1]); + break; + } + + #undef SWAP +} + s32 ARM::Execute(s32 cycles) { while (cycles > 0) @@ -55,6 +55,8 @@ public: if (v) CPSR |= 0x10000000; } + void UpdateMode(u32 oldmode, u32 newmode); + u8 Read8(u32 addr, u32 forceuser=0) { diff --git a/ARMInterpreter.cpp b/ARMInterpreter.cpp index 36c436c..9fd89d7 100644 --- a/ARMInterpreter.cpp +++ b/ARMInterpreter.cpp @@ -45,6 +45,8 @@ s32 A_MSR_IMM(ARM* cpu) else psr = &cpu->CPSR; + u32 oldpsr = *psr; + u32 mask = 0; if (cpu->CurInstr & (1<<16)) mask |= 0x000000DF; if (cpu->CurInstr & (1<<17)) mask |= 0x0000FF00; @@ -58,6 +60,9 @@ s32 A_MSR_IMM(ARM* cpu) *psr &= ~mask; *psr |= (val & mask); + if (!(cpu->CurInstr & (1<<22))) + cpu->UpdateMode(oldpsr, cpu->CPSR); + return C_S(1); } @@ -79,6 +84,8 @@ s32 A_MSR_REG(ARM* cpu) else psr = &cpu->CPSR; + u32 oldpsr = *psr; + u32 mask = 0; if (cpu->CurInstr & (1<<16)) mask |= 0x000000DF; if (cpu->CurInstr & (1<<17)) mask |= 0x0000FF00; @@ -92,6 +99,9 @@ s32 A_MSR_REG(ARM* cpu) *psr &= ~mask; *psr |= (val & mask); + if (!(cpu->CurInstr & (1<<22))) + cpu->UpdateMode(oldpsr, cpu->CPSR); + return C_S(1); } @@ -119,6 +129,47 @@ s32 A_MRS(ARM* cpu) } +s32 A_MCR(ARM* cpu) +{ + u32 cp = (cpu->CurInstr >> 8) & 0xF; + u32 op = (cpu->CurInstr >> 21) & 0x7; + u32 cn = (cpu->CurInstr >> 16) & 0xF; + u32 cm = cpu->CurInstr & 0xF; + u32 cpinfo = (cpu->CurInstr >> 5) & 0x7; + + if (cpu->Num==0 && cp==15) + { + printf("CP15: R%d -> %d,%d,%d\n", (cpu->CurInstr>>12)&0xF, cn, cm, cpinfo); + } + else + { + printf("bad MCR opcode p%d,%d,%d,%d on ARM%d\n", cp, cn, cm, cpinfo, cpu->Num?7:9); + } + + return C_S(1) + 1; // TODO: checkme +} + +s32 A_MRC(ARM* cpu) +{ + u32 cp = (cpu->CurInstr >> 8) & 0xF; + u32 op = (cpu->CurInstr >> 21) & 0x7; + u32 cn = (cpu->CurInstr >> 16) & 0xF; + u32 cm = cpu->CurInstr & 0xF; + u32 cpinfo = (cpu->CurInstr >> 5) & 0x7; + + if (cpu->Num==0 && cp==15) + { + printf("CP15: R%d <- %d,%d,%d\n", (cpu->CurInstr>>12)&0xF, cn, cm, cpinfo); + } + else + { + printf("bad MRC opcode p%d,%d,%d,%d on ARM%d\n", cp, cn, cm, cpinfo, cpu->Num?7:9); + } + + return C_S(1) + 1 + C_I(1); // TODO: checkme +} + + #define INSTRFUNC_PROTO(x) s32 (*x)(ARM* cpu) #include "ARM_InstrTable.h" diff --git a/ARM_InstrTable.h b/ARM_InstrTable.h index 6731803..f00ddaa 100644 --- a/ARM_InstrTable.h +++ b/ARM_InstrTable.h @@ -1374,100 +1374,100 @@ INSTRFUNC_PROTO(ARMInstrTable[4096]) = // 1110 0000 0000 - A_UNK, A_UNK, A_UNK, A_UNK, - A_UNK, A_UNK, A_UNK, A_UNK, - A_UNK, A_UNK, A_UNK, A_UNK, - A_UNK, A_UNK, A_UNK, A_UNK, + A_UNK, A_MCR, A_UNK, A_MCR, + A_UNK, A_MCR, A_UNK, A_MCR, + A_UNK, A_MCR, A_UNK, A_MCR, + A_UNK, A_MCR, A_UNK, A_MCR, // 1110 0001 0000 - A_UNK, A_UNK, A_UNK, A_UNK, - A_UNK, A_UNK, A_UNK, A_UNK, - A_UNK, A_UNK, A_UNK, A_UNK, - A_UNK, A_UNK, A_UNK, A_UNK, + A_UNK, A_MRC, A_UNK, A_MRC, + A_UNK, A_MRC, A_UNK, A_MRC, + A_UNK, A_MRC, A_UNK, A_MRC, + A_UNK, A_MRC, A_UNK, A_MRC, // 1110 0010 0000 - A_UNK, A_UNK, A_UNK, A_UNK, - A_UNK, A_UNK, A_UNK, A_UNK, - A_UNK, A_UNK, A_UNK, A_UNK, - A_UNK, A_UNK, A_UNK, A_UNK, + A_UNK, A_MCR, A_UNK, A_MCR, + A_UNK, A_MCR, A_UNK, A_MCR, + A_UNK, A_MCR, A_UNK, A_MCR, + A_UNK, A_MCR, A_UNK, A_MCR, // 1110 0011 0000 - A_UNK, A_UNK, A_UNK, A_UNK, - A_UNK, A_UNK, A_UNK, A_UNK, - A_UNK, A_UNK, A_UNK, A_UNK, - A_UNK, A_UNK, A_UNK, A_UNK, + A_UNK, A_MRC, A_UNK, A_MRC, + A_UNK, A_MRC, A_UNK, A_MRC, + A_UNK, A_MRC, A_UNK, A_MRC, + A_UNK, A_MRC, A_UNK, A_MRC, // 1110 0100 0000 - A_UNK, A_UNK, A_UNK, A_UNK, - A_UNK, A_UNK, A_UNK, A_UNK, - A_UNK, A_UNK, A_UNK, A_UNK, - A_UNK, A_UNK, A_UNK, A_UNK, + A_UNK, A_MCR, A_UNK, A_MCR, + A_UNK, A_MCR, A_UNK, A_MCR, + A_UNK, A_MCR, A_UNK, A_MCR, + A_UNK, A_MCR, A_UNK, A_MCR, // 1110 0101 0000 - A_UNK, A_UNK, A_UNK, A_UNK, - A_UNK, A_UNK, A_UNK, A_UNK, - A_UNK, A_UNK, A_UNK, A_UNK, - A_UNK, A_UNK, A_UNK, A_UNK, + A_UNK, A_MRC, A_UNK, A_MRC, + A_UNK, A_MRC, A_UNK, A_MRC, + A_UNK, A_MRC, A_UNK, A_MRC, + A_UNK, A_MRC, A_UNK, A_MRC, // 1110 0110 0000 - A_UNK, A_UNK, A_UNK, A_UNK, - A_UNK, A_UNK, A_UNK, A_UNK, - A_UNK, A_UNK, A_UNK, A_UNK, - A_UNK, A_UNK, A_UNK, A_UNK, + A_UNK, A_MCR, A_UNK, A_MCR, + A_UNK, A_MCR, A_UNK, A_MCR, + A_UNK, A_MCR, A_UNK, A_MCR, + A_UNK, A_MCR, A_UNK, A_MCR, // 1110 0111 0000 - A_UNK, A_UNK, A_UNK, A_UNK, - A_UNK, A_UNK, A_UNK, A_UNK, - A_UNK, A_UNK, A_UNK, A_UNK, - A_UNK, A_UNK, A_UNK, A_UNK, + A_UNK, A_MRC, A_UNK, A_MRC, + A_UNK, A_MRC, A_UNK, A_MRC, + A_UNK, A_MRC, A_UNK, A_MRC, + A_UNK, A_MRC, A_UNK, A_MRC, // 1110 1000 0000 - A_UNK, A_UNK, A_UNK, A_UNK, - A_UNK, A_UNK, A_UNK, A_UNK, - A_UNK, A_UNK, A_UNK, A_UNK, - A_UNK, A_UNK, A_UNK, A_UNK, + A_UNK, A_MCR, A_UNK, A_MCR, + A_UNK, A_MCR, A_UNK, A_MCR, + A_UNK, A_MCR, A_UNK, A_MCR, + A_UNK, A_MCR, A_UNK, A_MCR, // 1110 1001 0000 - A_UNK, A_UNK, A_UNK, A_UNK, - A_UNK, A_UNK, A_UNK, A_UNK, - A_UNK, A_UNK, A_UNK, A_UNK, - A_UNK, A_UNK, A_UNK, A_UNK, + A_UNK, A_MRC, A_UNK, A_MRC, + A_UNK, A_MRC, A_UNK, A_MRC, + A_UNK, A_MRC, A_UNK, A_MRC, + A_UNK, A_MRC, A_UNK, A_MRC, // 1110 1010 0000 - A_UNK, A_UNK, A_UNK, A_UNK, - A_UNK, A_UNK, A_UNK, A_UNK, - A_UNK, A_UNK, A_UNK, A_UNK, - A_UNK, A_UNK, A_UNK, A_UNK, + A_UNK, A_MCR, A_UNK, A_MCR, + A_UNK, A_MCR, A_UNK, A_MCR, + A_UNK, A_MCR, A_UNK, A_MCR, + A_UNK, A_MCR, A_UNK, A_MCR, // 1110 1011 0000 - A_UNK, A_UNK, A_UNK, A_UNK, - A_UNK, A_UNK, A_UNK, A_UNK, - A_UNK, A_UNK, A_UNK, A_UNK, - A_UNK, A_UNK, A_UNK, A_UNK, + A_UNK, A_MRC, A_UNK, A_MRC, + A_UNK, A_MRC, A_UNK, A_MRC, + A_UNK, A_MRC, A_UNK, A_MRC, + A_UNK, A_MRC, A_UNK, A_MRC, // 1110 1100 0000 - A_UNK, A_UNK, A_UNK, A_UNK, - A_UNK, A_UNK, A_UNK, A_UNK, - A_UNK, A_UNK, A_UNK, A_UNK, - A_UNK, A_UNK, A_UNK, A_UNK, + A_UNK, A_MCR, A_UNK, A_MCR, + A_UNK, A_MCR, A_UNK, A_MCR, + A_UNK, A_MCR, A_UNK, A_MCR, + A_UNK, A_MCR, A_UNK, A_MCR, // 1110 1101 0000 - A_UNK, A_UNK, A_UNK, A_UNK, - A_UNK, A_UNK, A_UNK, A_UNK, - A_UNK, A_UNK, A_UNK, A_UNK, - A_UNK, A_UNK, A_UNK, A_UNK, + A_UNK, A_MRC, A_UNK, A_MRC, + A_UNK, A_MRC, A_UNK, A_MRC, + A_UNK, A_MRC, A_UNK, A_MRC, + A_UNK, A_MRC, A_UNK, A_MRC, // 1110 1110 0000 - A_UNK, A_UNK, A_UNK, A_UNK, - A_UNK, A_UNK, A_UNK, A_UNK, - A_UNK, A_UNK, A_UNK, A_UNK, - A_UNK, A_UNK, A_UNK, A_UNK, + A_UNK, A_MCR, A_UNK, A_MCR, + A_UNK, A_MCR, A_UNK, A_MCR, + A_UNK, A_MCR, A_UNK, A_MCR, + A_UNK, A_MCR, A_UNK, A_MCR, // 1110 1111 0000 - A_UNK, A_UNK, A_UNK, A_UNK, - A_UNK, A_UNK, A_UNK, A_UNK, - A_UNK, A_UNK, A_UNK, A_UNK, - A_UNK, A_UNK, A_UNK, A_UNK, + A_UNK, A_MRC, A_UNK, A_MRC, + A_UNK, A_MRC, A_UNK, A_MRC, + A_UNK, A_MRC, A_UNK, A_MRC, + A_UNK, A_MRC, A_UNK, A_MRC, diff --git a/melonDS.depend b/melonDS.depend index cb9e396..5692d42 100644 --- a/melonDS.depend +++ b/melonDS.depend @@ -13,23 +13,23 @@ "NDS.h" "ARM.h" -1480729196 source:c:\documents\sources\melonds\arm.cpp +1480736240 source:c:\documents\sources\melonds\arm.cpp <stdio.h> "NDS.h" "ARM.h" "ARMInterpreter.h" -1480722720 c:\documents\sources\melonds\arm.h +1480735953 c:\documents\sources\melonds\arm.h "types.h" "NDS.h" -1480734093 c:\documents\sources\melonds\arm_instrtable.h +1480735162 c:\documents\sources\melonds\arm_instrtable.h 1480725698 c:\documents\sources\melonds\arminterpreter.h "types.h" "ARM.h" -1480727235 source:c:\documents\sources\melonds\arminterpreter.cpp +1480736379 source:c:\documents\sources\melonds\arminterpreter.cpp <stdio.h> "NDS.h" "ARMInterpreter.h" @@ -51,6 +51,6 @@ 1480734113 c:\documents\sources\melonds\arminterpreter_loadstore.h -1480731825 source:c:\documents\sources\melonds\arminterpreter_loadstore.cpp +1480734224 source:c:\documents\sources\melonds\arminterpreter_loadstore.cpp "ARM.h" |