melonDS/ARMInterpreter_ALU.cpp

768 lines
17 KiB
C++

#include "ARM.h"
#define CARRY_ADD(a, b) ((0xFFFFFFFF-a) < b)
#define CARRY_SUB(a, b) (a >= b)
#define OVERFLOW_ADD(a, b, res) ((!(((a) ^ (b)) & 0x80000000)) && (((a) ^ (res)) & 0x80000000))
#define OVERFLOW_SUB(a, b, res) ((((a) ^ (b)) & 0x80000000) && (((a) ^ (res)) & 0x80000000))
namespace ARMInterpreter
{
#define LSL_IMM(x, s) \
x <<= s;
#define LSR_IMM(x, s) \
if (s == 0) s = 32; \
x >>= s;
#define ASR_IMM(x, s) \
if (s == 0) s = 32; \
x = ((s32)x) >> s;
#define ROR_IMM(x, s) \
if (s == 0) \
{ \
x = (x >> 1) | ((cpu->CPSR & 0x20000000) << 2); \
} \
else \
{ \
x = ROR(x, s); \
}
#define LSL_IMM_S(x, s) \
if (s > 0) \
{ \
cpu->SetC(x & (1<<(32-s))); \
x <<= s; \
}
#define LSR_IMM_S(x, s) \
if (s == 0) s = 32; \
cpu->SetC(x & (1<<(s-1))); \
x >>= s;
#define ASR_IMM_S(x, s) \
if (s == 0) s = 32; \
cpu->SetC(x & (1<<(s-1))); \
x = ((s32)x) >> s;
#define ROR_IMM_S(x, s) \
if (s == 0) \
{ \
cpu->SetC(x & 1); \
x = (x >> 1) | ((cpu->CPSR & 0x20000000) << 2); \
} \
else \
{ \
cpu->SetC(x & (1<<(s-1))); \
x = ROR(x, s); \
}
#define LSL_REG(x, s) \
x <<= s;
#define LSR_REG(x, s) \
x >>= s;
#define ASR_REG(x, s) \
x = ((s32)x) >> s;
#define ROR_REG(x, s) \
x = ROR(x, s);
#define LSL_REG_S(x, s) \
if (s > 0) cpu->SetC(x & (1<<(32-s))); \
x <<= s;
#define LSR_REG_S(x, s) \
if (s > 0) cpu->SetC(x & (1<<(s-1))); \
x >>= s;
#define ASR_REG_S(x, s) \
if (s > 0) cpu->SetC(x & (1<<(s-1))); \
x = ((s32)x) >> s;
#define ROR_REG_S(x, s) \
if (s > 0) cpu->SetC(x & (1<<(s-1))); \
x = ROR(x, s);
#define A_CALC_OP2_IMM \
u32 b = ROR(cpu->CurInstr&0xFF, (cpu->CurInstr>>7)&0x1E);
#define A_CALC_OP2_REG_SHIFT_IMM(shiftop) \
u32 b = cpu->R[cpu->CurInstr&0xF]; \
u32 s = (cpu->CurInstr>>7)&0x1F; \
shiftop(b, s);
#define A_CALC_OP2_REG_SHIFT_REG(shiftop) \
u32 b = cpu->R[cpu->CurInstr&0xF]; \
shiftop(b, cpu->R[(cpu->CurInstr>>8)&0xF]);
#define A_IMPLEMENT_ALU_OP(x) \
\
s32 A_##x##_IMM(ARM* cpu) \
{ \
A_CALC_OP2_IMM \
A_##x(0) \
} \
s32 A_##x##_REG_LSL_IMM(ARM* cpu) \
{ \
A_CALC_OP2_REG_SHIFT_IMM(LSL_IMM) \
A_##x(0) \
} \
s32 A_##x##_REG_LSR_IMM(ARM* cpu) \
{ \
A_CALC_OP2_REG_SHIFT_IMM(LSR_IMM) \
A_##x(0) \
} \
s32 A_##x##_REG_ASR_IMM(ARM* cpu) \
{ \
A_CALC_OP2_REG_SHIFT_IMM(ASR_IMM) \
A_##x(0) \
} \
s32 A_##x##_REG_ROR_IMM(ARM* cpu) \
{ \
A_CALC_OP2_REG_SHIFT_IMM(ROR_IMM) \
A_##x(0) \
} \
s32 A_##x##_REG_LSL_REG(ARM* cpu) \
{ \
A_CALC_OP2_REG_SHIFT_REG(LSL_REG) \
A_##x(1) \
} \
s32 A_##x##_REG_LSR_REG(ARM* cpu) \
{ \
A_CALC_OP2_REG_SHIFT_REG(LSR_REG) \
A_##x(1) \
} \
s32 A_##x##_REG_ASR_REG(ARM* cpu) \
{ \
A_CALC_OP2_REG_SHIFT_REG(ASR_REG) \
A_##x(1) \
} \
s32 A_##x##_REG_ROR_REG(ARM* cpu) \
{ \
A_CALC_OP2_REG_SHIFT_REG(ROR_REG) \
A_##x(1) \
} \
s32 A_##x##_IMM_S(ARM* cpu) \
{ \
A_CALC_OP2_IMM \
A_##x##_S(0) \
} \
s32 A_##x##_REG_LSL_IMM_S(ARM* cpu) \
{ \
A_CALC_OP2_REG_SHIFT_IMM(LSL_IMM_S) \
A_##x##_S(0) \
} \
s32 A_##x##_REG_LSR_IMM_S(ARM* cpu) \
{ \
A_CALC_OP2_REG_SHIFT_IMM(LSR_IMM_S) \
A_##x##_S(0) \
} \
s32 A_##x##_REG_ASR_IMM_S(ARM* cpu) \
{ \
A_CALC_OP2_REG_SHIFT_IMM(ASR_IMM_S) \
A_##x##_S(0) \
} \
s32 A_##x##_REG_ROR_IMM_S(ARM* cpu) \
{ \
A_CALC_OP2_REG_SHIFT_IMM(ROR_IMM_S) \
A_##x##_S(0) \
} \
s32 A_##x##_REG_LSL_REG_S(ARM* cpu) \
{ \
A_CALC_OP2_REG_SHIFT_REG(LSL_REG_S) \
A_##x##_S(1) \
} \
s32 A_##x##_REG_LSR_REG_S(ARM* cpu) \
{ \
A_CALC_OP2_REG_SHIFT_REG(LSR_REG_S) \
A_##x##_S(1) \
} \
s32 A_##x##_REG_ASR_REG_S(ARM* cpu) \
{ \
A_CALC_OP2_REG_SHIFT_REG(ASR_REG_S) \
A_##x##_S(1) \
} \
s32 A_##x##_REG_ROR_REG_S(ARM* cpu) \
{ \
A_CALC_OP2_REG_SHIFT_REG(ROR_REG_S) \
A_##x##_S(1) \
}
#define A_IMPLEMENT_ALU_TEST(x) \
\
s32 A_##x##_IMM(ARM* cpu) \
{ \
A_CALC_OP2_IMM \
A_##x(0) \
} \
s32 A_##x##_REG_LSL_IMM(ARM* cpu) \
{ \
A_CALC_OP2_REG_SHIFT_IMM(LSL_IMM_S) \
A_##x(0) \
} \
s32 A_##x##_REG_LSR_IMM(ARM* cpu) \
{ \
A_CALC_OP2_REG_SHIFT_IMM(LSR_IMM_S) \
A_##x(0) \
} \
s32 A_##x##_REG_ASR_IMM(ARM* cpu) \
{ \
A_CALC_OP2_REG_SHIFT_IMM(ASR_IMM_S) \
A_##x(0) \
} \
s32 A_##x##_REG_ROR_IMM(ARM* cpu) \
{ \
A_CALC_OP2_REG_SHIFT_IMM(ROR_IMM_S) \
A_##x(0) \
} \
s32 A_##x##_REG_LSL_REG(ARM* cpu) \
{ \
A_CALC_OP2_REG_SHIFT_REG(LSL_REG_S) \
A_##x(1) \
} \
s32 A_##x##_REG_LSR_REG(ARM* cpu) \
{ \
A_CALC_OP2_REG_SHIFT_REG(LSR_REG_S) \
A_##x(1) \
} \
s32 A_##x##_REG_ASR_REG(ARM* cpu) \
{ \
A_CALC_OP2_REG_SHIFT_REG(ASR_REG_S) \
A_##x(1) \
} \
s32 A_##x##_REG_ROR_REG(ARM* cpu) \
{ \
A_CALC_OP2_REG_SHIFT_REG(ROR_REG_S) \
A_##x(1) \
}
#define A_AND(c) \
u32 a = cpu->R[(cpu->CurInstr>>16) & 0xF]; \
u32 res = a & b; \
if (((cpu->CurInstr>>12) & 0xF) == 15) \
{ \
cpu->JumpTo(res); \
return C_S(2) + C_I(c) + C_N(1); \
} \
else \
{ \
cpu->R[(cpu->CurInstr>>12) & 0xF] = res; \
return C_S(1) + C_I(c); \
}
#define A_AND_S(c) \
u32 a = cpu->R[(cpu->CurInstr>>16) & 0xF]; \
u32 res = a & b; \
cpu->SetNZ(res & 0x80000000, \
!res); \
if (((cpu->CurInstr>>12) & 0xF) == 15) \
{ \
cpu->JumpTo(res); \
cpu->RestoreCPSR(); \
return C_S(2) + C_I(c) + C_N(1); \
} \
else \
{ \
cpu->R[(cpu->CurInstr>>12) & 0xF] = res; \
return C_S(1) + C_I(c); \
}
A_IMPLEMENT_ALU_OP(AND)
#define A_EOR(c) \
u32 a = cpu->R[(cpu->CurInstr>>16) & 0xF]; \
u32 res = a | b; \
if (((cpu->CurInstr>>12) & 0xF) == 15) \
{ \
cpu->JumpTo(res); \
return C_S(2) + C_I(c) + C_N(1); \
} \
else \
{ \
cpu->R[(cpu->CurInstr>>12) & 0xF] = res; \
return C_S(1) + C_I(c); \
}
#define A_EOR_S(c) \
u32 a = cpu->R[(cpu->CurInstr>>16) & 0xF]; \
u32 res = a ^ b; \
cpu->SetNZ(res & 0x80000000, \
!res); \
if (((cpu->CurInstr>>12) & 0xF) == 15) \
{ \
cpu->JumpTo(res); \
cpu->RestoreCPSR(); \
return C_S(2) + C_I(c) + C_N(1); \
} \
else \
{ \
cpu->R[(cpu->CurInstr>>12) & 0xF] = res; \
return C_S(1) + C_I(c); \
}
A_IMPLEMENT_ALU_OP(EOR)
#define A_SUB(c) \
u32 a = cpu->R[(cpu->CurInstr>>16) & 0xF]; \
u32 res = a - b; \
if (((cpu->CurInstr>>12) & 0xF) == 15) \
{ \
cpu->JumpTo(res); \
return C_S(2) + C_I(c) + C_N(1); \
} \
else \
{ \
cpu->R[(cpu->CurInstr>>12) & 0xF] = res; \
return C_S(1) + C_I(c); \
}
#define A_SUB_S(c) \
u32 a = cpu->R[(cpu->CurInstr>>16) & 0xF]; \
u32 res = a - b; \
cpu->SetNZCV(res & 0x80000000, \
!res, \
CARRY_SUB(a, b), \
OVERFLOW_SUB(a, b, res)); \
if (((cpu->CurInstr>>12) & 0xF) == 15) \
{ \
cpu->JumpTo(res); \
cpu->RestoreCPSR(); \
return C_S(2) + C_I(c) + C_N(1); \
} \
else \
{ \
cpu->R[(cpu->CurInstr>>12) & 0xF] = res; \
return C_S(1) + C_I(c); \
}
A_IMPLEMENT_ALU_OP(SUB)
#define A_RSB(c) \
u32 a = cpu->R[(cpu->CurInstr>>16) & 0xF]; \
u32 res = b - a; \
if (((cpu->CurInstr>>12) & 0xF) == 15) \
{ \
cpu->JumpTo(res); \
return C_S(2) + C_I(c) + C_N(1); \
} \
else \
{ \
cpu->R[(cpu->CurInstr>>12) & 0xF] = res; \
return C_S(1) + C_I(c); \
}
#define A_RSB_S(c) \
u32 a = cpu->R[(cpu->CurInstr>>16) & 0xF]; \
u32 res = b - a; \
cpu->SetNZCV(res & 0x80000000, \
!res, \
CARRY_SUB(b, a), \
OVERFLOW_SUB(b, a, res)); \
if (((cpu->CurInstr>>12) & 0xF) == 15) \
{ \
cpu->JumpTo(res); \
cpu->RestoreCPSR(); \
return C_S(2) + C_I(c) + C_N(1); \
} \
else \
{ \
cpu->R[(cpu->CurInstr>>12) & 0xF] = res; \
return C_S(1) + C_I(c); \
}
A_IMPLEMENT_ALU_OP(RSB)
#define A_ADD(c) \
u32 a = cpu->R[(cpu->CurInstr>>16) & 0xF]; \
u32 res = a + b; \
if (((cpu->CurInstr>>12) & 0xF) == 15) \
{ \
cpu->JumpTo(res); \
return C_S(2) + C_I(c) + C_N(1); \
} \
else \
{ \
cpu->R[(cpu->CurInstr>>12) & 0xF] = res; \
return C_S(1) + C_I(c); \
}
#define A_ADD_S(c) \
u32 a = cpu->R[(cpu->CurInstr>>16) & 0xF]; \
u32 res = a + b; \
cpu->SetNZCV(res & 0x80000000, \
!res, \
CARRY_ADD(a, b), \
OVERFLOW_ADD(a, b, res)); \
if (((cpu->CurInstr>>12) & 0xF) == 15) \
{ \
cpu->JumpTo(res); \
cpu->RestoreCPSR(); \
return C_S(2) + C_I(c) + C_N(1); \
} \
else \
{ \
cpu->R[(cpu->CurInstr>>12) & 0xF] = res; \
return C_S(1) + C_I(c); \
}
A_IMPLEMENT_ALU_OP(ADD)
#define A_ADC(c) \
u32 a = cpu->R[(cpu->CurInstr>>16) & 0xF]; \
u32 res = a + b + (cpu->CPSR&0x20000000 ? 1:0); \
if (((cpu->CurInstr>>12) & 0xF) == 15) \
{ \
cpu->JumpTo(res); \
return C_S(2) + C_I(c) + C_N(1); \
} \
else \
{ \
cpu->R[(cpu->CurInstr>>12) & 0xF] = res; \
return C_S(1) + C_I(c); \
}
#define A_ADC_S(c) \
u32 a = cpu->R[(cpu->CurInstr>>16) & 0xF]; \
u32 res_tmp = a + b; \
u32 carry = (cpu->CPSR&0x20000000 ? 1:0); \
u32 res = res_tmp + carry; \
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)); \
if (((cpu->CurInstr>>12) & 0xF) == 15) \
{ \
cpu->JumpTo(res); \
cpu->RestoreCPSR(); \
return C_S(2) + C_I(c) + C_N(1); \
} \
else \
{ \
cpu->R[(cpu->CurInstr>>12) & 0xF] = res; \
return C_S(1) + C_I(c); \
}
A_IMPLEMENT_ALU_OP(ADC)
#define A_SBC(c) \
u32 a = cpu->R[(cpu->CurInstr>>16) & 0xF]; \
u32 res = a - b - (cpu->CPSR&0x20000000 ? 0:1); \
if (((cpu->CurInstr>>12) & 0xF) == 15) \
{ \
cpu->JumpTo(res); \
return C_S(2) + C_I(c) + C_N(1); \
} \
else \
{ \
cpu->R[(cpu->CurInstr>>12) & 0xF] = res; \
return C_S(1) + C_I(c); \
}
#define A_SBC_S(c) \
u32 a = cpu->R[(cpu->CurInstr>>16) & 0xF]; \
u32 res_tmp = a - b; \
u32 carry = (cpu->CPSR&0x20000000 ? 0:1); \
u32 res = res_tmp - carry; \
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)); \
if (((cpu->CurInstr>>12) & 0xF) == 15) \
{ \
cpu->JumpTo(res); \
cpu->RestoreCPSR(); \
return C_S(2) + C_I(c) + C_N(1); \
} \
else \
{ \
cpu->R[(cpu->CurInstr>>12) & 0xF] = res; \
return C_S(1) + C_I(c); \
}
A_IMPLEMENT_ALU_OP(SBC)
#define A_RSC(c) \
u32 a = cpu->R[(cpu->CurInstr>>16) & 0xF]; \
u32 res = b - a - (cpu->CPSR&0x20000000 ? 0:1); \
if (((cpu->CurInstr>>12) & 0xF) == 15) \
{ \
cpu->JumpTo(res); \
return C_S(2) + C_I(c) + C_N(1); \
} \
else \
{ \
cpu->R[(cpu->CurInstr>>12) & 0xF] = res; \
return C_S(1) + C_I(c); \
}
#define A_RSC_S(c) \
u32 a = cpu->R[(cpu->CurInstr>>16) & 0xF]; \
u32 res_tmp = b - a; \
u32 carry = (cpu->CPSR&0x20000000 ? 0:1); \
u32 res = res_tmp - carry; \
cpu->SetNZCV(res & 0x80000000, \
!res, \
CARRY_SUB(b, a) | CARRY_SUB(res_tmp, carry), \
OVERFLOW_SUB(b, a, res_tmp) | OVERFLOW_SUB(res_tmp, carry, res)); \
if (((cpu->CurInstr>>12) & 0xF) == 15) \
{ \
cpu->JumpTo(res); \
cpu->RestoreCPSR(); \
return C_S(2) + C_I(c) + C_N(1); \
} \
else \
{ \
cpu->R[(cpu->CurInstr>>12) & 0xF] = res; \
return C_S(1) + C_I(c); \
}
A_IMPLEMENT_ALU_OP(RSC)
#define A_TST(c) \
u32 a = cpu->R[(cpu->CurInstr>>16) & 0xF]; \
u32 res = a & b; \
cpu->SetNZ(res & 0x80000000, \
!res); \
return C_S(1) + C_I(c);
A_IMPLEMENT_ALU_TEST(TST)
#define A_TEQ(c) \
u32 a = cpu->R[(cpu->CurInstr>>16) & 0xF]; \
u32 res = a ^ b; \
cpu->SetNZ(res & 0x80000000, \
!res); \
return C_S(1) + C_I(c);
A_IMPLEMENT_ALU_TEST(TEQ)
#define A_CMP(c) \
u32 a = cpu->R[(cpu->CurInstr>>16) & 0xF]; \
u32 res = a - b; \
cpu->SetNZCV(res & 0x80000000, \
!res, \
CARRY_SUB(a, b), \
OVERFLOW_SUB(a, b, res)); \
return C_S(1) + C_I(c);
A_IMPLEMENT_ALU_TEST(CMP)
#define A_CMN(c) \
u32 a = cpu->R[(cpu->CurInstr>>16) & 0xF]; \
u32 res = a + b; \
cpu->SetNZCV(res & 0x80000000, \
!res, \
CARRY_ADD(a, b), \
OVERFLOW_ADD(a, b, res)); \
return C_S(1) + C_I(c);
A_IMPLEMENT_ALU_TEST(CMN)
#define A_ORR(c) \
u32 a = cpu->R[(cpu->CurInstr>>16) & 0xF]; \
u32 res = a | b; \
if (((cpu->CurInstr>>12) & 0xF) == 15) \
{ \
cpu->JumpTo(res); \
return C_S(2) + C_I(c) + C_N(1); \
} \
else \
{ \
cpu->R[(cpu->CurInstr>>12) & 0xF] = res; \
return C_S(1) + C_I(c); \
}
#define A_ORR_S(c) \
u32 a = cpu->R[(cpu->CurInstr>>16) & 0xF]; \
u32 res = a | b; \
cpu->SetNZ(res & 0x80000000, \
!res); \
if (((cpu->CurInstr>>12) & 0xF) == 15) \
{ \
cpu->JumpTo(res); \
cpu->RestoreCPSR(); \
return C_S(2) + C_I(c) + C_N(1); \
} \
else \
{ \
cpu->R[(cpu->CurInstr>>12) & 0xF] = res; \
return C_S(1) + C_I(c); \
}
A_IMPLEMENT_ALU_OP(ORR)
#define A_MOV(c) \
if (((cpu->CurInstr>>12) & 0xF) == 15) \
{ \
cpu->JumpTo(b); \
return C_S(2) + C_I(c) + C_N(1); \
} \
else \
{ \
cpu->R[(cpu->CurInstr>>12) & 0xF] = b; \
return C_S(1) + C_I(c); \
}
#define A_MOV_S(c) \
cpu->SetNZ(b & 0x80000000, \
!b); \
if (((cpu->CurInstr>>12) & 0xF) == 15) \
{ \
cpu->JumpTo(b); \
cpu->RestoreCPSR(); \
return C_S(2) + C_I(c) + C_N(1); \
} \
else \
{ \
cpu->R[(cpu->CurInstr>>12) & 0xF] = b; \
return C_S(1) + C_I(c); \
}
A_IMPLEMENT_ALU_OP(MOV)
#define A_BIC(c) \
u32 a = cpu->R[(cpu->CurInstr>>16) & 0xF]; \
u32 res = a & ~b; \
if (((cpu->CurInstr>>12) & 0xF) == 15) \
{ \
cpu->JumpTo(res); \
return C_S(2) + C_I(c) + C_N(1); \
} \
else \
{ \
cpu->R[(cpu->CurInstr>>12) & 0xF] = res; \
return C_S(1) + C_I(c); \
}
#define A_BIC_S(c) \
u32 a = cpu->R[(cpu->CurInstr>>16) & 0xF]; \
u32 res = a & ~b; \
cpu->SetNZ(res & 0x80000000, \
!res); \
if (((cpu->CurInstr>>12) & 0xF) == 15) \
{ \
cpu->JumpTo(res); \
cpu->RestoreCPSR(); \
return C_S(2) + C_I(c) + C_N(1); \
} \
else \
{ \
cpu->R[(cpu->CurInstr>>12) & 0xF] = res; \
return C_S(1) + C_I(c); \
}
A_IMPLEMENT_ALU_OP(BIC)
#define A_MVN(c) \
b = ~b; \
if (((cpu->CurInstr>>12) & 0xF) == 15) \
{ \
cpu->JumpTo(b); \
return C_S(2) + C_I(c) + C_N(1); \
} \
else \
{ \
cpu->R[(cpu->CurInstr>>12) & 0xF] = b; \
return C_S(1) + C_I(c); \
}
#define A_MVN_S(c) \
b = ~b; \
cpu->SetNZ(b & 0x80000000, \
!b); \
if (((cpu->CurInstr>>12) & 0xF) == 15) \
{ \
cpu->JumpTo(b); \
cpu->RestoreCPSR(); \
return C_S(2) + C_I(c) + C_N(1); \
} \
else \
{ \
cpu->R[(cpu->CurInstr>>12) & 0xF] = b; \
return C_S(1) + C_I(c); \
}
A_IMPLEMENT_ALU_OP(MVN)
// ---- THUMB ----------------------------------
s32 T_MOV_IMM(ARM* cpu)
{
u32 b = cpu->CurInstr & 0xFF;
cpu->R[(cpu->CurInstr >> 8) & 0x7] = b;
cpu->SetNZ(0,
!b);
return C_S(1);
}
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)); \
return C_S(1);
}
s32 T_ADD_IMM(ARM* cpu)
{
u32 a = cpu->R[(cpu->CurInstr >> 8) & 0x7];
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)); \
return C_S(1);
}
s32 T_SUB_IMM(ARM* cpu)
{
u32 a = cpu->R[(cpu->CurInstr >> 8) & 0x7];
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)); \
return C_S(1);
}
}