aboutsummaryrefslogtreecommitdiff
path: root/ARMInterpreter_ALU.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'ARMInterpreter_ALU.cpp')
-rw-r--r--ARMInterpreter_ALU.cpp257
1 files changed, 245 insertions, 12 deletions
diff --git a/ARMInterpreter_ALU.cpp b/ARMInterpreter_ALU.cpp
index 6ad7ebf..46f8107 100644
--- a/ARMInterpreter_ALU.cpp
+++ b/ARMInterpreter_ALU.cpp
@@ -716,6 +716,41 @@ A_IMPLEMENT_ALU_OP(MVN)
+s32 T_LSL_IMM(ARM* cpu)
+{
+ u32 op = cpu->R[(cpu->CurInstr >> 3) & 0x7];
+ u32 s = (cpu->CurInstr >> 6) & 0x1F;
+ LSL_IMM_S(op, s);
+ cpu->R[cpu->CurInstr & 0x7] = op;
+ cpu->SetNZ(op & 0x80000000,
+ !op);
+ return C_S(1);
+}
+
+s32 T_LSR_IMM(ARM* cpu)
+{
+ u32 op = cpu->R[(cpu->CurInstr >> 3) & 0x7];
+ u32 s = (cpu->CurInstr >> 6) & 0x1F;
+ LSR_IMM_S(op, s);
+ cpu->R[cpu->CurInstr & 0x7] = op;
+ cpu->SetNZ(op & 0x80000000,
+ !op);
+ return C_S(1);
+}
+
+s32 T_ASR_IMM(ARM* cpu)
+{
+ u32 op = cpu->R[(cpu->CurInstr >> 3) & 0x7];
+ u32 s = (cpu->CurInstr >> 6) & 0x1F;
+ ASR_IMM_S(op, s);
+ cpu->R[cpu->CurInstr & 0x7] = op;
+ cpu->SetNZ(op & 0x80000000,
+ !op);
+ return C_S(1);
+}
+
+//
+
s32 T_MOV_IMM(ARM* cpu)
{
u32 b = cpu->CurInstr & 0xFF;
@@ -730,10 +765,10 @@ s32 T_CMP_IMM(ARM* cpu)
u32 a = cpu->R[(cpu->CurInstr >> 8) & 0x7];
u32 b = cpu->CurInstr & 0xFF;
u32 res = a - b;
- cpu->SetNZCV(res & 0x80000000, \
- !res, \
- CARRY_SUB(a, b), \
- OVERFLOW_SUB(a, b, res)); \
+ cpu->SetNZCV(res & 0x80000000,
+ !res,
+ CARRY_SUB(a, b),
+ OVERFLOW_SUB(a, b, res));
return C_S(1);
}
@@ -743,10 +778,10 @@ s32 T_ADD_IMM(ARM* cpu)
u32 b = cpu->CurInstr & 0xFF;
u32 res = a + b;
cpu->R[(cpu->CurInstr >> 8) & 0x7] = res;
- cpu->SetNZCV(res & 0x80000000, \
- !res, \
- CARRY_ADD(a, b), \
- OVERFLOW_ADD(a, b, res)); \
+ cpu->SetNZCV(res & 0x80000000,
+ !res,
+ CARRY_ADD(a, b),
+ OVERFLOW_ADD(a, b, res));
return C_S(1);
}
@@ -756,10 +791,208 @@ s32 T_SUB_IMM(ARM* cpu)
u32 b = cpu->CurInstr & 0xFF;
u32 res = a - b;
cpu->R[(cpu->CurInstr >> 8) & 0x7] = res;
- cpu->SetNZCV(res & 0x80000000, \
- !res, \
- CARRY_SUB(a, b), \
- OVERFLOW_SUB(a, b, res)); \
+ cpu->SetNZCV(res & 0x80000000,
+ !res,
+ CARRY_SUB(a, b),
+ OVERFLOW_SUB(a, b, res));
+ return C_S(1);
+}
+
+
+s32 T_AND_REG(ARM* cpu)
+{
+ u32 a = cpu->R[cpu->CurInstr & 0x7];
+ u32 b = cpu->R[(cpu->CurInstr >> 3) & 0x7];
+ u32 res = a & b;
+ cpu->R[cpu->CurInstr & 0x7] = res;
+ cpu->SetNZ(res & 0x80000000,
+ !res);
+ return C_S(1);
+}
+
+s32 T_EOR_REG(ARM* cpu)
+{
+ u32 a = cpu->R[cpu->CurInstr & 0x7];
+ u32 b = cpu->R[(cpu->CurInstr >> 3) & 0x7];
+ u32 res = a ^ b;
+ cpu->R[cpu->CurInstr & 0x7] = res;
+ cpu->SetNZ(res & 0x80000000,
+ !res);
+ return C_S(1);
+}
+
+s32 T_LSL_REG(ARM* cpu)
+{
+ u32 a = cpu->R[cpu->CurInstr & 0x7];
+ u32 b = cpu->R[(cpu->CurInstr >> 3) & 0x7] & 0xFF;
+ LSL_REG_S(a, b);
+ cpu->R[cpu->CurInstr & 0x7] = a;
+ cpu->SetNZ(a & 0x80000000,
+ !a);
+ return C_S(1) + C_I(1);
+}
+
+s32 T_LSR_REG(ARM* cpu)
+{
+ u32 a = cpu->R[cpu->CurInstr & 0x7];
+ u32 b = cpu->R[(cpu->CurInstr >> 3) & 0x7] & 0xFF;
+ LSR_REG_S(a, b);
+ cpu->R[cpu->CurInstr & 0x7] = a;
+ cpu->SetNZ(a & 0x80000000,
+ !a);
+ return C_S(1) + C_I(1);
+}
+
+s32 T_ASR_REG(ARM* cpu)
+{
+ u32 a = cpu->R[cpu->CurInstr & 0x7];
+ u32 b = cpu->R[(cpu->CurInstr >> 3) & 0x7] & 0xFF;
+ ASR_REG_S(a, b);
+ cpu->R[cpu->CurInstr & 0x7] = a;
+ cpu->SetNZ(a & 0x80000000,
+ !a);
+ return C_S(1) + C_I(1);
+}
+
+s32 T_ADC_REG(ARM* cpu)
+{
+ u32 a = cpu->R[cpu->CurInstr & 0x7];
+ u32 b = cpu->R[(cpu->CurInstr >> 3) & 0x7];
+ u32 res_tmp = a + b;
+ u32 carry = (cpu->CPSR&0x20000000 ? 1:0);
+ u32 res = res_tmp + carry;
+ cpu->R[cpu->CurInstr & 0x7] = res;
+ cpu->SetNZCV(res & 0x80000000,
+ !res,
+ CARRY_ADD(a, b) | CARRY_ADD(res_tmp, carry),
+ OVERFLOW_ADD(a, b, res_tmp) | OVERFLOW_ADD(res_tmp, carry, res));
+ return C_S(1);
+}
+
+s32 T_SBC_REG(ARM* cpu)
+{
+ u32 a = cpu->R[cpu->CurInstr & 0x7];
+ u32 b = cpu->R[(cpu->CurInstr >> 3) & 0x7];
+ u32 res_tmp = a - b;
+ u32 carry = (cpu->CPSR&0x20000000 ? 0:1);
+ u32 res = res_tmp - carry;
+ cpu->R[cpu->CurInstr & 0x7] = res;
+ cpu->SetNZCV(res & 0x80000000,
+ !res,
+ CARRY_SUB(a, b) | CARRY_SUB(res_tmp, carry),
+ OVERFLOW_SUB(a, b, res_tmp) | OVERFLOW_SUB(res_tmp, carry, res));
+ return C_S(1);
+}
+
+s32 T_ROR_REG(ARM* cpu)
+{
+ u32 a = cpu->R[cpu->CurInstr & 0x7];
+ u32 b = cpu->R[(cpu->CurInstr >> 3) & 0x7] & 0xFF;
+ ROR_REG_S(a, b);
+ cpu->R[cpu->CurInstr & 0x7] = a;
+ cpu->SetNZ(a & 0x80000000,
+ !a);
+ return C_S(1) + C_I(1);
+}
+
+s32 T_TST_REG(ARM* cpu)
+{
+ u32 a = cpu->R[cpu->CurInstr & 0x7];
+ u32 b = cpu->R[(cpu->CurInstr >> 3) & 0x7];
+ u32 res = a & b;
+ cpu->SetNZ(res & 0x80000000,
+ !res);
+ return C_S(1);
+}
+
+s32 T_NEG_REG(ARM* cpu)
+{
+ u32 b = cpu->R[(cpu->CurInstr >> 3) & 0x7];
+ u32 res = -b;
+ cpu->R[cpu->CurInstr & 0x7] = res;
+ cpu->SetNZ(res & 0x80000000,
+ !res);
+ return C_S(1);
+}
+
+s32 T_CMP_REG(ARM* cpu)
+{
+ u32 a = cpu->R[cpu->CurInstr & 0x7];
+ u32 b = cpu->R[(cpu->CurInstr >> 3) & 0x7];
+ u32 res = a - b;
+ cpu->SetNZCV(res & 0x80000000,
+ !res,
+ CARRY_SUB(a, b),
+ OVERFLOW_SUB(a, b, res));
+ return C_S(1);
+}
+
+s32 T_CMN_REG(ARM* cpu)
+{
+ u32 a = cpu->R[cpu->CurInstr & 0x7];
+ u32 b = cpu->R[(cpu->CurInstr >> 3) & 0x7];
+ u32 res = a + b;
+ cpu->SetNZCV(res & 0x80000000,
+ !res,
+ CARRY_ADD(a, b),
+ OVERFLOW_ADD(a, b, res));
+ return C_S(1);
+}
+
+s32 T_ORR_REG(ARM* cpu)
+{
+ u32 a = cpu->R[cpu->CurInstr & 0x7];
+ u32 b = cpu->R[(cpu->CurInstr >> 3) & 0x7];
+ u32 res = a | b;
+ cpu->R[cpu->CurInstr & 0x7] = res;
+ cpu->SetNZ(res & 0x80000000,
+ !res);
+ return C_S(1);
+}
+
+s32 T_MUL_REG(ARM* cpu)
+{
+ u32 a = cpu->R[cpu->CurInstr & 0x7];
+ u32 b = cpu->R[(cpu->CurInstr >> 3) & 0x7];
+ u32 res = a * b;
+ cpu->R[cpu->CurInstr & 0x7] = res;
+ cpu->SetNZ(res & 0x80000000,
+ !res);
+
+ s32 cycles = C_S(1);
+ if (cpu->Num == 0)
+ {
+ cycles += C_I(3);
+ }
+ else
+ {
+ cpu->SetC(0); // carry flag destroyed, they say. whatever that means...
+ if (a & 0xFF000000) cycles += C_I(4);
+ else if (a & 0x00FF0000) cycles += C_I(3);
+ else if (a & 0x0000FF00) cycles += C_I(2);
+ else cycles += C_I(1);
+ }
+ return cycles;
+}
+
+s32 T_BIC_REG(ARM* cpu)
+{
+ u32 a = cpu->R[cpu->CurInstr & 0x7];
+ u32 b = cpu->R[(cpu->CurInstr >> 3) & 0x7];
+ u32 res = a & ~b;
+ cpu->R[cpu->CurInstr & 0x7] = res;
+ cpu->SetNZ(res & 0x80000000,
+ !res);
+ return C_S(1);
+}
+
+s32 T_MVN_REG(ARM* cpu)
+{
+ u32 b = cpu->R[(cpu->CurInstr >> 3) & 0x7];
+ u32 res = ~b;
+ cpu->R[cpu->CurInstr & 0x7] = res;
+ cpu->SetNZ(res & 0x80000000,
+ !res);
return C_S(1);
}