diff options
Diffstat (limited to 'ARMInterpreter.cpp')
-rw-r--r-- | ARMInterpreter.cpp | 93 |
1 files changed, 93 insertions, 0 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 |