aboutsummaryrefslogtreecommitdiff
path: root/ARMInterpreter.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'ARMInterpreter.cpp')
-rw-r--r--ARMInterpreter.cpp93
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