diff options
author | StapleButter <thetotalworm@gmail.com> | 2016-12-03 02:09:04 +0100 |
---|---|---|
committer | StapleButter <thetotalworm@gmail.com> | 2016-12-03 02:09:04 +0100 |
commit | 844ca4505570bef9c6c8b16263a2473f7df9020a (patch) | |
tree | 93afbf2bc11e56217958583863e03aa6df39f8d4 | |
parent | 23d584ca4c86e5e75947ef4edc1f06e1fbedc2e6 (diff) |
add MSR/MRS. also fix misc error with LDR ROR effect.
see shibboleet, I can do it too :>
-rw-r--r-- | ARMInterpreter.cpp | 93 | ||||
-rw-r--r-- | ARMInterpreter.h | 4 | ||||
-rw-r--r-- | ARMInterpreter_LoadStore.cpp | 4 | ||||
-rw-r--r-- | ARM_InstrTable.h | 24 | ||||
-rw-r--r-- | melonDS.depend | 4 |
5 files changed, 113 insertions, 16 deletions
diff --git a/ARMInterpreter.cpp b/ARMInterpreter.cpp index 896919d..36c436c 100644 --- a/ARMInterpreter.cpp +++ b/ARMInterpreter.cpp @@ -27,6 +27,99 @@ s32 T_UNK(ARM* cpu) +s32 A_MSR_IMM(ARM* cpu) +{ + u32* psr; + if (cpu->CurInstr & (1<<22)) + { + switch (cpu->CPSR & 0x1F) + { + 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 0x17: psr = &cpu->R_ABT[2]; break; + case 0x1B: psr = &cpu->R_UND[2]; break; + default: printf("bad CPU mode %08X\n", cpu->CPSR); return 1; + } + } + else + psr = &cpu->CPSR; + + u32 mask = 0; + if (cpu->CurInstr & (1<<16)) mask |= 0x000000DF; + if (cpu->CurInstr & (1<<17)) mask |= 0x0000FF00; + if (cpu->CurInstr & (1<<18)) mask |= 0x00FF0000; + if (cpu->CurInstr & (1<<19)) mask |= 0xFF000000; + + if ((cpu->CPSR & 0x1F) == 0x10) mask &= 0xFFFFFF00; + + u32 val = ROR((cpu->CurInstr & 0xFF), ((cpu->CurInstr >> 7) & 0x1E)); + + *psr &= ~mask; + *psr |= (val & mask); + + return C_S(1); +} + +s32 A_MSR_REG(ARM* cpu) +{ + u32* psr; + if (cpu->CurInstr & (1<<22)) + { + switch (cpu->CPSR & 0x1F) + { + 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 0x17: psr = &cpu->R_ABT[2]; break; + case 0x1B: psr = &cpu->R_UND[2]; break; + default: printf("bad CPU mode %08X\n", cpu->CPSR); return 1; + } + } + else + psr = &cpu->CPSR; + + u32 mask = 0; + if (cpu->CurInstr & (1<<16)) mask |= 0x000000DF; + if (cpu->CurInstr & (1<<17)) mask |= 0x0000FF00; + if (cpu->CurInstr & (1<<18)) mask |= 0x00FF0000; + if (cpu->CurInstr & (1<<19)) mask |= 0xFF000000; + + if ((cpu->CPSR & 0x1F) == 0x10) mask &= 0xFFFFFF00; + + u32 val = cpu->R[cpu->CurInstr & 0xF]; + + *psr &= ~mask; + *psr |= (val & mask); + + return C_S(1); +} + +s32 A_MRS(ARM* cpu) +{ + u32 psr; + if (cpu->CurInstr & (1<<22)) + { + switch (cpu->CPSR & 0x1F) + { + 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 0x17: psr = cpu->R_ABT[2]; break; + case 0x1B: psr = cpu->R_UND[2]; break; + default: printf("bad CPU mode %08X\n", cpu->CPSR); return 1; + } + } + else + psr = cpu->CPSR; + + cpu->R[(cpu->CurInstr>>12) & 0xF] = psr; + + return C_S(1); +} + + + #define INSTRFUNC_PROTO(x) s32 (*x)(ARM* cpu) #include "ARM_InstrTable.h" #undef INSTRFUNC_PROTO diff --git a/ARMInterpreter.h b/ARMInterpreter.h index 08e4be1..00a3f20 100644 --- a/ARMInterpreter.h +++ b/ARMInterpreter.h @@ -8,6 +8,10 @@ namespace ARMInterpreter { +s32 A_MSR_IMM(ARM* cpu); +s32 A_MSR_REG(ARM* cpu); +s32 A_MRS(ARM* cpu); + extern s32 (*ARMInstrTable[4096])(ARM* cpu); extern s32 (*THUMBInstrTable[1024])(ARM* cpu); diff --git a/ARMInterpreter_LoadStore.cpp b/ARMInterpreter_LoadStore.cpp index e319056..b719e35 100644 --- a/ARMInterpreter_LoadStore.cpp +++ b/ARMInterpreter_LoadStore.cpp @@ -67,7 +67,7 @@ namespace ARMInterpreter #define A_LDR \ offset += cpu->R[(cpu->CurInstr>>16) & 0xF]; \ - u32 val = ROR(cpu->Read32(offset), offset&0x3); \ + u32 val = ROR(cpu->Read32(offset), ((offset&0x3)<<3)); \ if (cpu->CurInstr & (1<<21)) cpu->R[(cpu->CurInstr>>16) & 0xF] = offset; \ if (((cpu->CurInstr>>12) & 0xF) == 15) \ { \ @@ -83,7 +83,7 @@ namespace ARMInterpreter #define A_LDR_POST \ u32 addr = cpu->R[(cpu->CurInstr>>16) & 0xF]; \ - u32 val = ROR(cpu->Read32(addr, cpu->CurInstr & (1<<21)), addr&0x3); \ + u32 val = ROR(cpu->Read32(addr, cpu->CurInstr & (1<<21)), ((addr&0x3)<<3)); \ cpu->R[(cpu->CurInstr>>16) & 0xF] += offset; \ if (((cpu->CurInstr>>12) & 0xF) == 15) \ { \ diff --git a/ARM_InstrTable.h b/ARM_InstrTable.h index a39bbf9..9d25670 100644 --- a/ARM_InstrTable.h +++ b/ARM_InstrTable.h @@ -100,7 +100,7 @@ INSTRFUNC_PROTO(ARMInstrTable[4096]) = // 0001 0000 0000 - A_UNK, A_UNK, A_UNK, A_UNK, + A_MRS, 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, @@ -112,7 +112,7 @@ INSTRFUNC_PROTO(ARMInstrTable[4096]) = A_UNK, A_UNK, A_UNK, A_UNK, // 0001 0010 0000 - A_UNK, A_UNK, A_UNK, A_UNK, + A_MSR_REG, 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, @@ -124,7 +124,7 @@ INSTRFUNC_PROTO(ARMInstrTable[4096]) = A_UNK, A_UNK, A_UNK, A_UNK, // 0001 0100 0000 - A_UNK, A_UNK, A_UNK, A_UNK, + A_MRS, 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, @@ -136,7 +136,7 @@ INSTRFUNC_PROTO(ARMInstrTable[4096]) = A_UNK, A_UNK, A_UNK, A_UNK, // 0001 0110 0000 - A_UNK, A_UNK, A_UNK, A_UNK, + A_MSR_REG, 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, @@ -308,10 +308,10 @@ INSTRFUNC_PROTO(ARMInstrTable[4096]) = A_TST_IMM, A_TST_IMM, A_TST_IMM, A_TST_IMM, // 0011 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_MSR_IMM, A_MSR_IMM, A_MSR_IMM, A_MSR_IMM, + A_MSR_IMM, A_MSR_IMM, A_MSR_IMM, A_MSR_IMM, + A_MSR_IMM, A_MSR_IMM, A_MSR_IMM, A_MSR_IMM, + A_MSR_IMM, A_MSR_IMM, A_MSR_IMM, A_MSR_IMM, // 0011 0011 0000 A_TEQ_IMM, A_TEQ_IMM, A_TEQ_IMM, A_TEQ_IMM, @@ -332,10 +332,10 @@ INSTRFUNC_PROTO(ARMInstrTable[4096]) = A_CMP_IMM, A_CMP_IMM, A_CMP_IMM, A_CMP_IMM, // 0011 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_MSR_IMM, A_MSR_IMM, A_MSR_IMM, A_MSR_IMM, + A_MSR_IMM, A_MSR_IMM, A_MSR_IMM, A_MSR_IMM, + A_MSR_IMM, A_MSR_IMM, A_MSR_IMM, A_MSR_IMM, + A_MSR_IMM, A_MSR_IMM, A_MSR_IMM, A_MSR_IMM, // 0011 0111 0000 A_CMN_IMM, A_CMN_IMM, A_CMN_IMM, A_CMN_IMM, diff --git a/melonDS.depend b/melonDS.depend index 0b30f29..7487ff1 100644 --- a/melonDS.depend +++ b/melonDS.depend @@ -13,7 +13,7 @@ "NDS.h" "ARM.h" -1480027981 source:c:\documents\sources\melonds\arm.cpp +1480726419 source:c:\documents\sources\melonds\arm.cpp <stdio.h> "NDS.h" "ARM.h" @@ -25,7 +25,7 @@ 1480724917 c:\documents\sources\melonds\arm_instrtable.h -1480018830 c:\documents\sources\melonds\arminterpreter.h +1480725698 c:\documents\sources\melonds\arminterpreter.h "types.h" "ARM.h" |