#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;