# simple instructions
# ^a means that this operand corresponds to the op2 and will be decoded using 'ARM_Shifts.txt' file
MOV		^1, ^a					; ^1 = ^a;
MVN		^1, ^a					; ^1 = ~(^a);
TST		^1, ^a					;  s = ^1 & (^a);
TEQ		^1, ^a					;  s = ^1 ^ (^a);
AND		^1, ^2, ^a				; ^1 = ^2 & (^a);
EOR		^1, ^2, ^a				; ^1 = ^2 ^ (^a);
ORR		^1, ^2, ^a				; ^1 = ^2 | (^a);
ORN		^1, ^2, ^a				; ^1 = ^2 | (~(^a));
BIC		^1, ^2, ^a				; ^1 = ^2 & (~(^a));
CLZ		^1, ^2					; { int x=^2;    int leadingZeros = 0; while(x != 0) { x = x >> 1; leadingZeros++; } ^1 = 32 - leadingZeros; } 

# shift operators
ASR		^1, ^2, ^3				; ^1 = ^2 >> (^3);
LSL		^1, ^2, ^3				; ^1 = ^2 << (^3);
LSR		^1, ^2, ^3				; ^1 = ((unsigned int)^2) >>> (^3);
ROR		^1, ^2, ^3				; ^1 = (((unsigned int)^2) >>> (^3) ) | (^2 << 31);
RRX		^1, ^2, ^3				; { int tmp = c & 1;  ^1 = ((unsigned int)^2) >>> (^3) | c; c = tmp;}

# arithmetical operations
ADD		^1, ^2, ^a				; ^1 = ^2 + (^a);
SUB		^1, ^2, ^a				; ^1 = ^2 - (^a);
RSB		^1, ^2, ^a				; ^1 = (^a) - ^2;
QADD	^1, ^2, ^3				; { INT64 t = (INT64)^2 + ^3; if (t>0x7fffffff) t=0x7fffffff; if (t<(-((INT64)0x80000000))) t=-(INT64)0x80000000; ^1 = (int) t; }
QSUB	^1, ^2, ^3				; { INT64 t = (INT64)^2 - ^3; if (t>0x7fffffff) t=0x7fffffff; if (t<(-((INT64)0x80000000))) t=-(INT64)0x80000000; ^1 = (int) t; }
QDADD	^1, ^2, ^3				; { INT64 t = (INT64)^3 << 1; if (t>0x7fffffff) t=0x7fffffff; if (t<(-((INT64)0x80000000))) t=-(INT64)0x80000000; t += ^2;    if (t>0x7fffffff) t=0x7fffffff; if (t<(-((INT64)0x80000000))) t=-(INT64)0x80000000; ^1 = (int) t; }
QDSUB	^1, ^2, ^3				; { INT64 t = (INT64)^3 << 1; if (t>0x7fffffff) t=0x7fffffff; if (t<(-((INT64)0x80000000))) t=-(INT64)0x80000000; t = ^2 - t; if (t>0x7fffffff) t=0x7fffffff; if (t<(-((INT64)0x80000000))) t=-(INT64)0x80000000; ^1 = (int) t; }

# multiplications
SMULWB	^1, ^2, ^3				; ^1 = (int)(((INT64)^2 * (short)^3)>>16);
SMULWT	^1, ^2, ^3				; ^1 = (int)(((INT64)^2 * (short)(^3>>16))>>16);
SMLAWB	^1, ^2, ^3, ^4			; ^1 = (int)((((INT64)^2 * (short)^3)>>16) + ^4);
SMLAWT	^1, ^2, ^3, ^4			; ^1 = (int)((((INT64)^2 * (short)(^3>>16))>>16) + ^4);
SMULBB	^1, ^2, ^3				; ^1 = (int)((short)^2) * (short)^3;
SMLABB	^1, ^2, ^3, ^4			; ^1 = (int)((short)^2) * (short)^3 + ^4;
SMULBT	^1, ^2, ^3				; ^1 = (int)((short)^2) * (short)(^3>>16);
SMLABT	^1, ^2, ^3, ^4			; ^1 = (int)((short)^2) * (short)(^3>>16) + ^4;
SMULTB	^1, ^2, ^3				; ^1 = (int)((short)(^2>>16)) * (short)^3;
SMLATB	^1, ^2, ^3, ^4			; ^1 = (int)((short)(^2>>16)) * (short)^3 + ^4;
SMULTT	^1, ^2, ^3				; ^1 = (int)((short)(^2>>16)) * (short)(^3>>16);
SMLATT	^1, ^2, ^3, ^4			; ^1 = (int)((short)(^2>>16)) * (short)(^3>>16) + ^4;
SMULL	^1, ^2, ^3, ^4			; {INT64 t = (INT64)^3 * ^4; ^1 = (int)t; ^2 = (int)(t >> 32) }
SMLAL	^1, ^2, ^3, ^4			; {INT64 t = ^1 + (((INT64)^2)<<32); t += (INT64)^3 * ^4; ^1 = (int)t; ^2 = (int)(t >> 32) }
MUL		^1, ^2, ^3				; ^1 = ^2 * ^3;
MLA		^1, ^2, ^3, ^4			; ^1 = ^4 + ^2 * ^3;
MLS		^1, ^2, ^3, ^4			; ^1 = ^4 - ^2 * ^3;

# compare
CMP		^1, ^a					; s = ^1 - (^a);
CMN		^1, ^a					; s = ^1 + (^a);

# load and store instructions
LDR		^1, [^2]				; ^1 = *((int*)(^2));
LDR		^1, ^2				; ^1 = *((int*)(^2));
LDR		^1, [^2,^a]				; ^1 = *((int*)(^2+(^a)));
LDR		^1, [^2,^a]!			; ^2+=^a; ^1 = *((int*)(^2));
LDR		^1, [^2], ^a			; ^1 = *((int*)^2); ^2+=^a;
LDRB	^1, [^2]				; ^1 = (unsigned int)(*((char*)(^2)));
LDRB	^1, [^2,^a]				; ^1 = (unsigned int)(*((char*)(^2+(^a))));
LDRB	^1, [^2,^a]!			; ^2+=^a; ^1 = (unsigned int)(*((char*)(^2+(^a))));
LDRB	^1, [^2], ^a			; ^1 = (unsigned int)(*((char*)^2)); ^2+=^a;
LDRH	^1, [^2]				; ^1 = (unsigned int)(*((unsigned short*)(^2)));
LDRH	^1, [^2,^a]				; ^1 = (unsigned int)(*((unsigned short*)(^2+(^a))));
LDRH	^1, [^2,^a]!			; ^2+=^a; ^1 = (unsigned int)(*((unsigned short*)(^2+(^a))));
LDRH	^1, [^2], ^a			; ^1 = (unsigned int)(*((unsigned short*)^2)); ^2+=^a;
LDRSH	^1, [^2]				; ^1 = (int)(*((short*)(^2)));
LDRSH	^1, [^2,^a]				; ^1 = (int)(*((short*)(^2+(^a))));
LDRSH	^1, [^2,^a]!			; ^2+=^a; ^1 = (int)(*((short*)(^2+(^a))));
LDRSH	^1, [^2], ^a			; ^1 = (int)(*((short*)^2)); ^2+=^a;
LDRD	^1, ^2, [^3]				; { int* p=(int*)^3; ^1 = *p; ^2 = *(p+1); }
LDRD	^1, ^2, [^3,^a]				; { int* p=(int*)(^3+(^a)); ^1 = *p; ^2 = *(p+1); }
LDRD	^1, ^2, [^3,^a]!			; { int* p=(int*)(^3+(^a)); ^1 = *p; ^2 = *(p+1); ^3=(int)p; }
LDRD	^1, ^2, [^3], ^a			; { ^1 = *((int*)(^3)); ^2 = *((int*)(^3)+1); ^3 += ^a;}
STR		^1, [^2]				; *((int*)(^2)) = ^1;
STR		^1, ^2				; *((int*)(^2)) = ^1;
STR		^1, [^2,^a]				; *((int*)(^2+(^a))) = ^1;
STR		^1, [^2,^a]!			; ^2+=^a; *((int*)(^2+(^a))) = ^1;
STR		^1, [^2], ^a			; *((int*)^2) = ^1; ^2+=^a;
STRB	^1, [^2]				; (*((char*)(^2))) = (char)^1;
STRB	^1, [^2,^a]				; (*((char*)(^2+(^a)))) = (char)^1;
STRB	^1, [^2,^a]!			; ^2+=^a; (*((char*)(^2+(^a)))) = (char)^1;
STRB	^1, [^2], ^a			; (*((char*)^2)) = (char)^1; ^2+=^a;
STRH	^1, [^2]				; (*((unsigned short*)(^2))) = (unsigned short)^1;
STRH	^1, [^2,^a]				; (*((unsigned short*)(^2+(^a)))) = (unsigned short)^1;
STRH	^1, [^2,^a]!			; ^2+=^a; (*((unsigned short*)(^2+(^a)))) = (unsigned short)^1;
STRH	^1, [^2], ^a			; (*((unsigned short*)^2)) = (unsigned short)^1; ^2+=^a;
STRSH	^1, [^2]				; (*((short*)(^2))) = (short)^1;
STRSH	^1, [^2,^a]				; (*((short*)(^2+(^a)))) = (short)^1;
STRSH	^1, [^2,^a]!			; ^2+=^a; (*((short*)(^2+(^a)))) = (short)^1;
STRSH	^1, [^2], ^a			; (*((short*)^2)) = (short)^1; ^2+=^a;
STRD	^1, ^2, [^3]				; { int* p=(int*)^3; *p = ^1; *(p+1) = ^2; }
STRD	^1, ^2, [^3,^a]				; { int* p=(int*)(^3+(^a)); *p = ^1; *(p+1) = ^2; }
STRD	^1, ^2, [^3,^a]!			; { int* p=(int*)(^3+(^a)); *p = ^1; *(p+1) = ^2; ^3=(int)p; }
STRD	^1, ^2, [^3], ^a			; { *((int*)(^3)) = ^1; *((int*)(^3)+1) = ^2; ^3 += ^a;}

# branch instructions
B		^1						; goto ^1;
BX		^1						; pc = ^1;

# multiple load and store
# part in internal curves will be iterated by operand ^b
LDMIA	^1, {^b}				; { int* p=(int*)^1; { ^b = *p; p+=1; } }
LDMIA	^1!, {^b}				; { ^b = *((int*)(^1)); ^1+=4; }
LDMIB	^1, {^b}				; { int* p=(int*)^1; { p+=1; ^b = *p; } }
LDMIB	^1!, {^b}				; { ^1+=4; ^b = *((int*)(^1)); }
LDMDA	^1, {^b}				; { int* p=(int*)^1; { ^b = *p; p-=1; } }
LDMDA	^1!, {^b}				; { ^b = *((int*)(^1)); ^1-=4; }
LDMDB	^1, {^b}				; { int* p=(int*)^1; { p-=1; ^b = *p; } }
LDMDB	^1!, {^b}				; { ^1-=4; ^b = *((int*)(^1)); }
LDMFD	^1, {^b}				; { int* p=(int*)^1; { ^b = *p; p+=1; } }
LDMFD	^1!, {^b}				; { ^b = *((int*)(^1)); ^1+=4; }
STMIA	^1, {^b}				; { int* p=(int*)^1; { *p = ^b; p+=1; } }
STMIA	^1!, {^b}				; { *((int*)(^1)) = ^b; ^1+=4; }
STMIB	^1, {^b}				; { int* p=(int*)^1; { p+=1; *p = ^b; } }
STMIB	^1!, {^b}				; { ^1+=4; *((int*)(^1)) = ^b; }
STMDA	^1, {^b}				; { int* p=(int*)^1; { *p = ^b; p-=1; } }
STMDA	^1!, {^b}				; { *((int*)(^1)) = ^b; ^1-=4; }
STMDB	^1, {^b}				; { int* p=(int*)^1; { p-=1; *p = ^b; } }
STMDB	^1!, {^b}				; { ^1-=4; *((int*)(^1)) = ^b; }
STMFD	^1, {^b}				; { int* p=(int*)^1; { p-=1; *p = ^b; } }
STMFD	^1!, {^b}				; { ^1-=4; *((int*)(^1)) = ^b; }
# additional load multiple
# LDM = LDMIA
LDM		^1, {^b}				; { int* p=(int*)^1; { ^b = *p; p+=1; } }
LDM		^1!, {^b}				; { ^b = *((int*)(^1)); ^1+=4; }
# STM = STMIA
STM		^1, {^b}				; { int* p=(int*)^1; { *p = ^b; p+=1; } }
STM		^1!, {^b}				; { *((int*)(^1)) = ^b; ^1+=4; }
# PUSH = STMFD
PUSH	{^b}					; { sp-=4; *((int*)(sp)) = ^b; }
# POP = LDMFD
POP		{^b}					; { ^b = *((int*)(sp)); sp+=4; }