#define OP_AND asm("and %0, %1, %2\n": "=r" (reg[dest].I):"r" (reg[(opcode>>16)&15].I), "r" (value) : "r0","r1","r2","r3" );
#define OP_ANDS asm("and %0, %1, %2\n": "=r" (reg[dest].I):"r" (reg[(opcode>>16)&15].I), "r" (value) : "r0","r1","r2","r3" );\
N_FLAG = (reg[dest].I & 0x80000000) ? true : false;\
Z_FLAG = (reg[dest].I) ? false : true;\
C_FLAG = C_OUT;
#define OP_EOR asm("eor %0, %1, %2\n": "=r" (reg[dest].I):"r" (reg[(opcode>>16)&15].I), "r" (value) : "r0","r1","r2","r3" );
#define OP_EORS \
asm("eor %0, %1, %2\n": "=r" (reg[dest].I):"r" (reg[(opcode>>16)&15].I), "r" (value) : "r0","r1","r2","r3" ); \
N_FLAG = (reg[dest].I & 0x80000000) ? true : false;\
Z_FLAG = (reg[dest].I) ? false : true;\
C_FLAG = C_OUT;
#define NEG(i) ((i) >> 31)
#define POS(i) ((~(i)) >> 31)
#define ADDCARRY(a, b, c) \
C_FLAG = ((NEG(a) & NEG(b)) |\
(NEG(a) & POS(c)) |\
(NEG(b) & POS(c))) ? true : false;
#define ADDOVERFLOW(a, b, c) \
V_FLAG = ((NEG(a) & NEG(b) & POS(c)) |\
(POS(a) & POS(b) & NEG(c))) ? true : false;
#define SUBCARRY(a, b, c) \
C_FLAG = ((NEG(a) & POS(b)) |\
(NEG(a) & POS(c)) |\
(POS(b) & POS(c))) ? true : false;
#define SUBOVERFLOW(a, b, c)\
V_FLAG = ((NEG(a) & POS(b) & POS(c)) |\
(POS(a) & NEG(b) & NEG(c))) ? true : false;
#define OP_SUB {asm("sub %0, %1, %2\n": "=r" (reg[dest].I):"r" (reg[base].I), "r" (value) : "r0","r1","r2","r3" );}
#define OP_SUBS \
{\
asm("subs %0, %5, %6\n" \
"mrs r0,cpsr\n"\
"mov r1,r0,lsr#30\n"\
"and %1,r1,#1\n"\
"mov r1,r0,lsr#31\n"\
"and %2,r1,#1\n"\
"mov r1,r0,lsr#29\n"\
"and %3,r1,#1\n"\
"mov r1,r0,lsr#28\n"\
"and %4,r1,#1\n"\
:"=r" (reg[dest].I),"=r" (Z_FLAG),"=r"(N_FLAG), "=r"(C_FLAG),"=r" (V_FLAG)\
:"r" (reg[base].I), "r" (value) : "r0","r1","r2","r3" );}
#define OP_RSB {asm("rsb %0, %1, %2\n": "=r" (reg[dest].I):"r" (reg[base].I), "r" (value) : "r0","r1","r2","r3" );}
#define OP_RSBS \
{\
asm("rsbs %0, %5, %6\n" \
"mrs r0,cpsr\n"\
"mov r1,r0,lsr#30\n"\
"and %1,r1,#1\n"\
"mov r1,r0,lsr#31\n"\
"and %2,r1,#1\n"\
"mov r1,r0,lsr#29\n"\
"and %3,r1,#1\n"\
"mov r1,r0,lsr#28\n"\
"and %4,r1,#1\n"\
:"=r" (reg[dest].I),"=r" (Z_FLAG),"=r"(N_FLAG), "=r"(C_FLAG),"=r" (V_FLAG)\
:"r" (reg[base].I), "r" (value) : "r0","r1","r2","r3" );}
#define OP_ADD {asm("add %0, %1, %2\n": "=r" (reg[dest].I):"r" (reg[base].I), "r" (value) : "r0","r1","r2","r3" );}
#define OP_ADDS \
{\
asm("adds %0, %5, %6\n" \
"mrs r0,cpsr\n"\
"mov r1,r0,lsr#30\n"\
"and %1,r1,#1\n"\
"mov r1,r0,lsr#31\n"\
"and %2,r1,#1\n"\
"mov r1,r0,lsr#29\n"\
"and %3,r1,#1\n"\
"mov r1,r0,lsr#28\n"\
"and %4,r1,#1\n"\
:"=r" (reg[dest].I),"=r" (Z_FLAG),"=r"(N_FLAG), "=r"(C_FLAG),"=r" (V_FLAG)\
:"r" (reg[base].I), "r" (value) : "r0","r1","r2","r3" );}
#define OP_ADC {reg[dest].I = reg[base].I + value + (u32)C_FLAG;}
#define OP_ADCS \
{\
u32 lhs = reg[base].I;\
u32 rhs = value;\
u32 res = lhs + rhs + (u32)C_FLAG;\
reg[dest].I = res;\
Z_FLAG = (res == 0) ? true : false;\
N_FLAG = NEG(res) ? true : false;\
ADDCARRY(lhs, rhs, res);\
ADDOVERFLOW(lhs, rhs, res);\
}
#define OP_SBC {reg[dest].I = reg[base].I - value - !((u32)C_FLAG);}
#define OP_SBCS {\
u32 lhs = reg[base].I;\
u32 rhs = value;\
u32 res = lhs - rhs - !((u32)C_FLAG);\
reg[dest].I = res;\
Z_FLAG = (res == 0) ? true : false;\
N_FLAG = NEG(res) ? true : false;\
SUBCARRY(lhs, rhs, res);\
SUBOVERFLOW(lhs, rhs, res);\
}
#define OP_RSC {reg[dest].I = value - reg[base].I - !((u32)C_FLAG);}
#define OP_RSCS \
{\
u32 lhs = reg[base].I;\
u32 rhs = value;\
u32 res = rhs - lhs - !((u32)C_FLAG);\
reg[dest].I = res;\
Z_FLAG = (res == 0) ? true : false;\
N_FLAG = NEG(res) ? true : false;\
SUBCARRY(rhs, lhs, res);\
SUBOVERFLOW(rhs, lhs, res);\
}
#define OP_CMP \
{\
asm("cmp %4, %5\n" \
"mrs r0,cpsr\n"\
"mov r1,r0,lsr#30\n"\
"and %0,r1,#1\n"\
"mov r1,r0,lsr#31\n"\
"and %1,r1,#1\n"\
"mov r1,r0,lsr#29\n"\
"and %2,r1,#1\n"\
"mov r1,r0,lsr#28\n"\
"and %3,r1,#1\n"\
:"=r" (Z_FLAG),"=r"(N_FLAG), "=r"(C_FLAG),"=r" (V_FLAG)\
:"r" (reg[base].I), "r" (value) : "r0","r1","r2","r3" );}
#define OP_CMN \
{\
asm("cmn %4, %5\n" \
"mrs r0,cpsr\n"\
"mov r1,r0,lsr#30\n"\
"and %0,r1,#1\n"\
"mov r1,r0,lsr#31\n"\
"and %1,r1,#1\n"\
"mov r1,r0,lsr#29\n"\
"and %2,r1,#1\n"\
"mov r1,r0,lsr#28\n"\
"and %3,r1,#1\n"\
:"=r" (reg[dest].I),"=r" (Z_FLAG),"=r"(N_FLAG), "=r"(C_FLAG),"=r" (V_FLAG)\
:"r" (reg[base].I), "r" (value) : "r0","r1","r2","r3" );}
#define LOGICAL_LSL_REG \
{\
u32 v = reg[opcode & 0x0f].I;\
C_OUT = (v >> (32 - shift)) & 1 ? true : false;\
value = v << shift;\
}
#define LOGICAL_LSR_REG \
{\
u32 v = reg[opcode & 0x0f].I;\
C_OUT = (v >> (shift - 1)) & 1 ? true : false;\
value = v >> shift;\
}
#define LOGICAL_ASR_REG \
{\
u32 v = reg[opcode & 0x0f].I;\
C_OUT = ((s32)v >> (int)(shift - 1)) & 1 ? true : false;\
value = (s32)v >> (int)shift;\
}
#define LOGICAL_ROR_REG \
{\
u32 v = reg[opcode & 0x0f].I;\
C_OUT = (v >> (shift - 1)) & 1 ? true : false;\
value = ((v << (32 - shift)) | (v >> shift));\
}
#define LOGICAL_RRX_REG \
{\
u32 v = reg[opcode & 0x0f].I;\
shift = (int)C_FLAG;\
C_OUT = (v & 1) ? true : false;\
value = ((v >> 1) |\
(shift << 31));\
}
#define LOGICAL_ROR_IMM \
{\
u32 v = opcode & 0xff;\
C_OUT = (v >> (shift - 1)) & 1 ? true : false;\
value = ((v << (32 - shift)) |\
(v >> shift));\
}
#define ARITHMETIC_LSL_REG \
{\
u32 v = reg[opcode & 0x0f].I;\
value = v << shift;\
}
#define ARITHMETIC_LSR_REG \
{\
u32 v = reg[opcode & 0x0f].I;\
value = v >> shift;\
}
#define ARITHMETIC_ASR_REG \
{\
u32 v = reg[opcode & 0x0f].I;\
value = (s32)v >> (int)shift;\
}
#define ARITHMETIC_ROR_REG \
{\
u32 v = reg[opcode & 0x0f].I;\
value = ((v << (32 - shift)) |(v >> shift));\
}
#define ARITHMETIC_RRX_REG \
{\
u32 v = reg[opcode & 0x0f].I;\
shift = (int)C_FLAG;\
value = ((v >> 1) |\
(shift << 31));\
}
#define ARITHMETIC_ROR_IMM \
{\
u32 v = opcode & 0xff;\
value = ((v << (32 - shift)) |\
(v >> shift));\
}
#define ROR_IMM_MSR \
{\
u32 v = opcode & 0xff;\
value = ((v << (32 - shift)) |\
(v >> shift));\
}
#define ROR_VALUE {value = ((value << (32 - shift)) | (value >> shift));}
#define RCR_VALUE \
{\
shift = (int)C_FLAG;\
value = ((value >> 1) |\
(shift << 31));\
}
#define OP_TST \
u32 res = reg[base].I & value;\
N_FLAG = (res & 0x80000000) ? true : false;\
Z_FLAG = (res) ? false : true;\
C_FLAG = C_OUT;
#define OP_TEQ \
u32 res = reg[base].I ^ value;\
N_FLAG = (res & 0x80000000) ? true : false;\
Z_FLAG = (res) ? false : true;\
C_FLAG = C_OUT;
#define OP_ORR {asm("orr %0, %1, %2\n": "=r" (reg[dest].I):"r" (reg[base].I), "r" (value) :"r0","r1","r2","r3");}
#define OP_ORRS {asm("orr %0, %1, %2\n": "=r" (reg[dest].I):"r" (reg[base].I), "r" (value) :"r0","r1","r2","r3");}\
N_FLAG = (reg[dest].I & 0x80000000) ? true : false;\
Z_FLAG = (reg[dest].I) ? false : true;\
C_FLAG = C_OUT;
#define OP_MOV asm("mov %0, %1\n":"=r" (reg[dest].I): "r" (value) : "r0","r1","r2","r3");
#define OP_MOVS asm("mov %0, %1\n":"=r" (reg[dest].I): "r" (value) : "r0","r1","r2","r3"); \
N_FLAG = (reg[dest].I & 0x80000000) ? true : false;\
Z_FLAG = (reg[dest].I) ? false : true;\
C_FLAG = C_OUT;
#define OP_BIC {asm("bic %0, %1, %2\n": "=r" (reg[dest].I):"r" (reg[base].I), "r" (value) : "r0","r1","r2","r3" );}
#define OP_BICS {asm("bic %0, %1, %2\n": "=r" (reg[dest].I):"r" (reg[base].I), "r" (value) : "r0","r1","r2","r3" );} \
N_FLAG = (reg[dest].I & 0x80000000) ? true : false;\
Z_FLAG = (reg[dest].I) ? false : true;\
C_FLAG = C_OUT;
#define OP_MVN {asm("mvn %0, %1\n":"=r" (reg[dest].I): "r" (value) : "r0","r1","r2","r3" );}
#define OP_MVNS {asm("mvn %0, %1\n":"=r" (reg[dest].I): "r" (value) : "r0","r1","r2","r3" );}\
N_FLAG = (reg[dest].I & 0x80000000) ? true : false;\
Z_FLAG = (reg[dest].I) ? false : true;\
C_FLAG = C_OUT;