aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorStapleButter <thetotalworm@gmail.com>2016-12-03 02:09:04 +0100
committerStapleButter <thetotalworm@gmail.com>2016-12-03 02:09:04 +0100
commit844ca4505570bef9c6c8b16263a2473f7df9020a (patch)
tree93afbf2bc11e56217958583863e03aa6df39f8d4
parent23d584ca4c86e5e75947ef4edc1f06e1fbedc2e6 (diff)
add MSR/MRS. also fix misc error with LDR ROR effect.
see shibboleet, I can do it too :>
-rw-r--r--ARMInterpreter.cpp93
-rw-r--r--ARMInterpreter.h4
-rw-r--r--ARMInterpreter_LoadStore.cpp4
-rw-r--r--ARM_InstrTable.h24
-rw-r--r--melonDS.depend4
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"