Thumb/Thumb2 instruction selection rework.

Change-id: I7428278f07f49e675d0271c58b3cbf1f6a4e9da1
diff --git a/vm/compiler/codegen/arm/Assemble.c b/vm/compiler/codegen/arm/Assemble.c
index fc740b6..144a416 100644
--- a/vm/compiler/codegen/arm/Assemble.c
+++ b/vm/compiler/codegen/arm/Assemble.c
@@ -39,9 +39,9 @@
  * fmt: for pretty-prining
  */
 #define ENCODING_MAP(opcode, skeleton, k0, ds, de, k1, s1s, s1e, k2, s2s, s2e, \
-                     operands, name, fmt, size) \
-        {skeleton, {{k0, ds, de}, {k1, s1s, s1e}, {k2, s2s, s2e}}, \
-         opcode, operands, name, fmt, size}
+                     k3, k3s, k3e, operands, name, fmt, size) \
+        {skeleton, {{k0, ds, de}, {k1, s1s, s1e}, {k2, s2s, s2e}, \
+                    {k3, k3s, k3e}}, opcode, operands, name, fmt, size}
 
 /* Instruction dump string format keys: !pf, where "!" is the start
  * of the key, "p" is which numeric operand to use and "f" is the
@@ -51,6 +51,7 @@
  *     0 -> operands[0] (dest)
  *     1 -> operands[1] (src1)
  *     2 -> operands[2] (src2)
+ *     3 -> operands[3] (extra)
  *
  * [f]ormats:
  *     h -> 4-digit hex
@@ -66,6 +67,7 @@
  *     s -> single precision floating point register
  *     S -> double precision floating point register
  *     m -> Thumb2 modified immediate
+ *     n -> complimented Thumb2 modified immediate
  *     M -> Thumb2 16-bit zero-extended immediate
  *
  *  [!] escape.  To insert "!", use "!!"
@@ -73,428 +75,648 @@
 /* NOTE: must be kept in sync with enum ArmOpcode from ArmLIR.h */
 ArmEncodingMap EncodingMap[ARM_LAST] = {
     ENCODING_MAP(ARM_16BIT_DATA,    0x0000,
-                 BITBLT, 15, 0, UNUSED, -1, -1, UNUSED, -1, -1,
+                 BITBLT, 15, 0, UNUSED, -1, -1, UNUSED, -1, -1, UNUSED, -1, -1,
                  IS_UNARY_OP,
                  "data", "0x!0h(!0d)", 1),
     ENCODING_MAP(THUMB_ADC,           0x4140,
-                 BITBLT, 2, 0, BITBLT, 5, 3, UNUSED, -1, -1,
-                 IS_BINARY_OP | CLOBBER_DEST,
-                 "adc", "r!0d, r!1d", 1),
+                 BITBLT, 2, 0, BITBLT, 5, 3, UNUSED, -1, -1, UNUSED, -1, -1,
+                 IS_BINARY_OP | CLOBBER_DEST | SETS_CCODES | USES_CCODES,
+                 "adcs", "r!0d, r!1d", 1),
     ENCODING_MAP(THUMB_ADD_RRI3,      0x1c00,
-                 BITBLT, 2, 0, BITBLT, 5, 3, BITBLT, 8, 6,
-                 IS_TERTIARY_OP | CLOBBER_DEST,
-                 "add", "r!0d, r!1d, #!2d", 1),
+                 BITBLT, 2, 0, BITBLT, 5, 3, BITBLT, 8, 6, UNUSED, -1, -1,
+                 IS_TERTIARY_OP | CLOBBER_DEST | SETS_CCODES,
+                 "adds", "r!0d, r!1d, #!2d", 1),
     ENCODING_MAP(THUMB_ADD_RI8,       0x3000,
-                 BITBLT, 10, 8, BITBLT, 7, 0, UNUSED, -1, -1,
-                 IS_BINARY_OP | CLOBBER_DEST,
-                 "add", "r!0d, r!0d, #!1d", 1),
+                 BITBLT, 10, 8, BITBLT, 7, 0, UNUSED, -1, -1, UNUSED, -1, -1,
+                 IS_BINARY_OP | CLOBBER_DEST | SETS_CCODES,
+                 "adds", "r!0d, r!0d, #!1d", 1),
     ENCODING_MAP(THUMB_ADD_RRR,       0x1800,
-                 BITBLT, 2, 0, BITBLT, 5, 3, BITBLT, 8, 6,
-                 IS_TERTIARY_OP | CLOBBER_DEST,
-                 "add", "r!0d, r!1d, r!2d", 1),
+                 BITBLT, 2, 0, BITBLT, 5, 3, BITBLT, 8, 6, UNUSED, -1, -1,
+                 IS_TERTIARY_OP | CLOBBER_DEST | SETS_CCODES,
+                 "adds", "r!0d, r!1d, r!2d", 1),
     ENCODING_MAP(THUMB_ADD_RR_LH,     0x4440,
-                 BITBLT, 2, 0, BITBLT, 5, 3, UNUSED, -1, -1,
+                 BITBLT, 2, 0, BITBLT, 5, 3, UNUSED, -1, -1, UNUSED, -1, -1,
                  IS_BINARY_OP | CLOBBER_DEST,
-                 "add",
-                 "r!0d, r!1d", 1),
+                 "add", "r!0d, r!1d", 1),
     ENCODING_MAP(THUMB_ADD_RR_HL,     0x4480,
-                 BITBLT, 2, 0, BITBLT, 5, 3, UNUSED, -1, -1,
+                 BITBLT, 2, 0, BITBLT, 5, 3, UNUSED, -1, -1, UNUSED, -1, -1,
                  IS_BINARY_OP | CLOBBER_DEST,
                  "add", "r!0d, r!1d", 1),
     ENCODING_MAP(THUMB_ADD_RR_HH,     0x44c0,
-                 BITBLT, 2, 0, BITBLT, 5, 3, UNUSED, -1, -1,
+                 BITBLT, 2, 0, BITBLT, 5, 3, UNUSED, -1, -1, UNUSED, -1, -1,
                  IS_BINARY_OP | CLOBBER_DEST,
                  "add", "r!0d, r!1d", 1),
     ENCODING_MAP(THUMB_ADD_PC_REL,    0xa000,
-                 BITBLT, 10, 8, BITBLT, 7, 0, UNUSED, -1, -1,
+                 BITBLT, 10, 8, BITBLT, 7, 0, UNUSED, -1, -1, UNUSED, -1, -1,
                  IS_TERTIARY_OP | CLOBBER_DEST,
                  "add", "r!0d, pc, #!1E", 1),
     ENCODING_MAP(THUMB_ADD_SP_REL,    0xa800,
-                 BITBLT, 10, 8, BITBLT, 7, 0, UNUSED, -1, -1,
+                 BITBLT, 10, 8, BITBLT, 7, 0, UNUSED, -1, -1, UNUSED, -1, -1,
                  IS_BINARY_OP | CLOBBER_DEST,
                  "add", "r!0d, sp, #!1E", 1),
     ENCODING_MAP(THUMB_ADD_SPI7,      0xb000,
-                 BITBLT, 6, 0, UNUSED, -1, -1, UNUSED, -1, -1,
+                 BITBLT, 6, 0, UNUSED, -1, -1, UNUSED, -1, -1, UNUSED, -1, -1,
                  IS_UNARY_OP | CLOBBER_DEST,
                  "add", "sp, #!0d*4", 1),
     ENCODING_MAP(THUMB_AND_RR,        0x4000,
-                 BITBLT, 2, 0, BITBLT, 5, 3, UNUSED, -1, -1,
-                 IS_BINARY_OP | CLOBBER_DEST,
-                 "and", "r!0d, r!1d", 1),
+                 BITBLT, 2, 0, BITBLT, 5, 3, UNUSED, -1, -1, UNUSED, -1, -1,
+                 IS_BINARY_OP | CLOBBER_DEST | SETS_CCODES,
+                 "ands", "r!0d, r!1d", 1),
     ENCODING_MAP(THUMB_ASR,           0x1000,
-                 BITBLT, 2, 0, BITBLT, 5, 3, BITBLT, 10, 6,
-                 IS_TERTIARY_OP | CLOBBER_DEST,
-                 "asr", "r!0d, r!1d, #!2d", 1),
+                 BITBLT, 2, 0, BITBLT, 5, 3, BITBLT, 10, 6, UNUSED, -1, -1,
+                 IS_TERTIARY_OP | CLOBBER_DEST | SETS_CCODES,
+                 "asrs", "r!0d, r!1d, #!2d", 1),
     ENCODING_MAP(THUMB_ASRV,          0x4100,
-                 BITBLT, 2, 0, BITBLT, 5, 3, UNUSED, -1, -1,
-                 IS_BINARY_OP | CLOBBER_DEST,
-                 "asr", "r!0d, r!1d", 1),
+                 BITBLT, 2, 0, BITBLT, 5, 3, UNUSED, -1, -1, UNUSED, -1, -1,
+                 IS_BINARY_OP | CLOBBER_DEST | SETS_CCODES,
+                 "asrs", "r!0d, r!1d", 1),
     ENCODING_MAP(THUMB_B_COND,        0xd000,
-                 BITBLT, 7, 0, BITBLT, 11, 8, UNUSED, -1, -1,
-                 IS_BINARY_OP | IS_BRANCH,
+                 BITBLT, 7, 0, BITBLT, 11, 8, UNUSED, -1, -1, UNUSED, -1, -1,
+                 IS_BINARY_OP | IS_BRANCH | USES_CCODES,
                  "!1c", "!0t", 1),
     ENCODING_MAP(THUMB_B_UNCOND,      0xe000,
-                 BITBLT, 10, 0, UNUSED, -1, -1, UNUSED, -1, -1,
+                 BITBLT, 10, 0, UNUSED, -1, -1, UNUSED, -1, -1, UNUSED, -1, -1,
                  NO_OPERAND | IS_BRANCH,
                  "b", "!0t", 1),
     ENCODING_MAP(THUMB_BIC,           0x4380,
-                 BITBLT, 2, 0, BITBLT, 5, 3, UNUSED, -1, -1,
-                 IS_BINARY_OP | CLOBBER_DEST,
-                 "bic", "r!0d, r!1d", 1),
+                 BITBLT, 2, 0, BITBLT, 5, 3, UNUSED, -1, -1, UNUSED, -1, -1,
+                 IS_BINARY_OP | CLOBBER_DEST | SETS_CCODES,
+                 "bics", "r!0d, r!1d", 1),
     ENCODING_MAP(THUMB_BKPT,          0xbe00,
-                 BITBLT, 7, 0, UNUSED, -1, -1, UNUSED, -1, -1,
+                 BITBLT, 7, 0, UNUSED, -1, -1, UNUSED, -1, -1, UNUSED, -1, -1,
                  IS_UNARY_OP | IS_BRANCH,
                  "bkpt", "!0d", 1),
     ENCODING_MAP(THUMB_BLX_1,         0xf000,
-                 BITBLT, 10, 0, UNUSED, -1, -1, UNUSED, -1, -1,
+                 BITBLT, 10, 0, UNUSED, -1, -1, UNUSED, -1, -1, UNUSED, -1, -1,
                  IS_BINARY_OP | IS_BRANCH,
                  "blx_1", "!0u", 1),
     ENCODING_MAP(THUMB_BLX_2,         0xe800,
-                 BITBLT, 10, 0, UNUSED, -1, -1, UNUSED, -1, -1,
+                 BITBLT, 10, 0, UNUSED, -1, -1, UNUSED, -1, -1, UNUSED, -1, -1,
                  IS_BINARY_OP | IS_BRANCH,
                  "blx_2", "!0v", 1),
     ENCODING_MAP(THUMB_BL_1,          0xf000,
-                 BITBLT, 10, 0, UNUSED, -1, -1, UNUSED, -1, -1,
+                 BITBLT, 10, 0, UNUSED, -1, -1, UNUSED, -1, -1, UNUSED, -1, -1,
                  IS_UNARY_OP | IS_BRANCH,
                  "bl_1", "!0u", 1),
     ENCODING_MAP(THUMB_BL_2,          0xf800,
-                 BITBLT, 10, 0, UNUSED, -1, -1, UNUSED, -1, -1,
+                 BITBLT, 10, 0, UNUSED, -1, -1, UNUSED, -1, -1, UNUSED, -1, -1,
                  IS_UNARY_OP | IS_BRANCH,
                  "bl_2", "!0v", 1),
     ENCODING_MAP(THUMB_BLX_R,         0x4780,
-                 BITBLT, 6, 3, UNUSED, -1, -1, UNUSED, -1, -1,
+                 BITBLT, 6, 3, UNUSED, -1, -1, UNUSED, -1, -1, UNUSED, -1, -1,
                  IS_UNARY_OP | IS_BRANCH,
                  "blx", "r!0d", 1),
     ENCODING_MAP(THUMB_BX,            0x4700,
-                 BITBLT, 6, 3, UNUSED, -1, -1, UNUSED, -1, -1,
+                 BITBLT, 6, 3, UNUSED, -1, -1, UNUSED, -1, -1, UNUSED, -1, -1,
                  IS_UNARY_OP | IS_BRANCH,
                  "bx", "r!0d", 1),
     ENCODING_MAP(THUMB_CMN,           0x42c0,
-                 BITBLT, 2, 0, BITBLT, 5, 3, UNUSED, -1, -1,
-                 IS_BINARY_OP,
+                 BITBLT, 2, 0, BITBLT, 5, 3, UNUSED, -1, -1, UNUSED, -1, -1,
+                 IS_BINARY_OP | SETS_CCODES,
                  "cmn", "r!0d, r!1d", 1),
     ENCODING_MAP(THUMB_CMP_RI8,       0x2800,
-                 BITBLT, 10, 8, BITBLT, 7, 0, UNUSED, -1, -1,
-                 IS_BINARY_OP,
+                 BITBLT, 10, 8, BITBLT, 7, 0, UNUSED, -1, -1, UNUSED, -1, -1,
+                 IS_BINARY_OP | SETS_CCODES,
                  "cmp", "r!0d, #!1d", 1),
     ENCODING_MAP(THUMB_CMP_RR,        0x4280,
-                 BITBLT, 2, 0, BITBLT, 5, 3, UNUSED, -1, -1,
-                 IS_BINARY_OP,
+                 BITBLT, 2, 0, BITBLT, 5, 3, UNUSED, -1, -1, UNUSED, -1, -1,
+                 IS_BINARY_OP | SETS_CCODES,
                  "cmp", "r!0d, r!1d", 1),
     ENCODING_MAP(THUMB_CMP_LH,        0x4540,
-                 BITBLT, 2, 0, BITBLT, 5, 3, UNUSED, -1, -1,
-                 IS_BINARY_OP,
+                 BITBLT, 2, 0, BITBLT, 5, 3, UNUSED, -1, -1, UNUSED, -1, -1,
+                 IS_BINARY_OP | SETS_CCODES,
                  "cmp", "r!0d, r!1D", 1),
     ENCODING_MAP(THUMB_CMP_HL,        0x4580,
-                 BITBLT, 2, 0, BITBLT, 5, 3, UNUSED, -1, -1,
-                 IS_BINARY_OP,
+                 BITBLT, 2, 0, BITBLT, 5, 3, UNUSED, -1, -1, UNUSED, -1, -1,
+                 IS_BINARY_OP | SETS_CCODES,
                  "cmp", "r!0D, r!1d", 1),
     ENCODING_MAP(THUMB_CMP_HH,        0x45c0,
-                 BITBLT, 2, 0, BITBLT, 5, 3, UNUSED, -1, -1,
-                 IS_BINARY_OP,
+                 BITBLT, 2, 0, BITBLT, 5, 3, UNUSED, -1, -1, UNUSED, -1, -1,
+                 IS_BINARY_OP | SETS_CCODES,
                  "cmp", "r!0D, r!1D", 1),
     ENCODING_MAP(THUMB_EOR,           0x4040,
-                 BITBLT, 2, 0, BITBLT, 5, 3, UNUSED, -1, -1,
-                 IS_BINARY_OP | CLOBBER_DEST,
-                 "eor", "r!0d, r!1d", 1),
+                 BITBLT, 2, 0, BITBLT, 5, 3, UNUSED, -1, -1, UNUSED, -1, -1,
+                 IS_BINARY_OP | CLOBBER_DEST | SETS_CCODES,
+                 "eors", "r!0d, r!1d", 1),
     ENCODING_MAP(THUMB_LDMIA,         0xc800,
-                 BITBLT, 10, 8, BITBLT, 7, 0, UNUSED, -1, -1,
+                 BITBLT, 10, 8, BITBLT, 7, 0, UNUSED, -1, -1, UNUSED, -1, -1,
                  IS_BINARY_OP | CLOBBER_DEST | CLOBBER_SRC1,
                  "ldmia", "r!0d!!, <!1R>", 1),
     ENCODING_MAP(THUMB_LDR_RRI5,      0x6800,
-                 BITBLT, 2, 0, BITBLT, 5, 3, BITBLT, 10, 6,
+                 BITBLT, 2, 0, BITBLT, 5, 3, BITBLT, 10, 6, UNUSED, -1, -1,
                  IS_TERTIARY_OP | CLOBBER_DEST,
                  "ldr", "r!0d, [r!1d, #!2E]", 1),
     ENCODING_MAP(THUMB_LDR_RRR,       0x5800,
-                 BITBLT, 2, 0, BITBLT, 5, 3, BITBLT, 8, 6,
+                 BITBLT, 2, 0, BITBLT, 5, 3, BITBLT, 8, 6, UNUSED, -1, -1,
                  IS_TERTIARY_OP | CLOBBER_DEST,
                  "ldr", "r!0d, [r!1d, r!2d]", 1),
     ENCODING_MAP(THUMB_LDR_PC_REL,    0x4800,
-                 BITBLT, 10, 8, BITBLT, 7, 0, UNUSED, -1, -1,
+                 BITBLT, 10, 8, BITBLT, 7, 0, UNUSED, -1, -1, UNUSED, -1, -1,
                  IS_TERTIARY_OP | CLOBBER_DEST,
                  "ldr", "r!0d, [pc, #!1E]", 1),
     ENCODING_MAP(THUMB_LDR_SP_REL,    0x9800,
-                 BITBLT, 10, 8, BITBLT, 7, 0, UNUSED, -1, -1,
-                 IS_BINARY_OP | CLOBBER_DEST,
+                 BITBLT, 10, 8, BITBLT, 7, 0, UNUSED, -1, -1, UNUSED, -1, -1,
+                 IS_TERTIARY_OP | CLOBBER_DEST,
                  "ldr", "r!0d, [sp, #!1E]", 1),
     ENCODING_MAP(THUMB_LDRB_RRI5,     0x7800,
-                 BITBLT, 2, 0, BITBLT, 5, 3, BITBLT, 10, 6,
+                 BITBLT, 2, 0, BITBLT, 5, 3, BITBLT, 10, 6, UNUSED, -1, -1,
                  IS_TERTIARY_OP | CLOBBER_DEST,
                  "ldrb", "r!0d, [r!1d, #2d]", 1),
     ENCODING_MAP(THUMB_LDRB_RRR,      0x5c00,
-                 BITBLT, 2, 0, BITBLT, 5, 3, BITBLT, 8, 6,
+                 BITBLT, 2, 0, BITBLT, 5, 3, BITBLT, 8, 6, UNUSED, -1, -1,
                  IS_TERTIARY_OP | CLOBBER_DEST,
                  "ldrb", "r!0d, [r!1d, r!2d]", 1),
     ENCODING_MAP(THUMB_LDRH_RRI5,     0x8800,
-                 BITBLT, 2, 0, BITBLT, 5, 3, BITBLT, 10, 6,
+                 BITBLT, 2, 0, BITBLT, 5, 3, BITBLT, 10, 6, UNUSED, -1, -1,
                  IS_TERTIARY_OP | CLOBBER_DEST,
                  "ldrh", "r!0d, [r!1d, #!2F]", 1),
     ENCODING_MAP(THUMB_LDRH_RRR,      0x5a00,
-                 BITBLT, 2, 0, BITBLT, 5, 3, BITBLT, 8, 6,
+                 BITBLT, 2, 0, BITBLT, 5, 3, BITBLT, 8, 6, UNUSED, -1, -1,
                  IS_TERTIARY_OP | CLOBBER_DEST,
                  "ldrh", "r!0d, [r!1d, r!2d]", 1),
     ENCODING_MAP(THUMB_LDRSB_RRR,     0x5600,
-                 BITBLT, 2, 0, BITBLT, 5, 3, BITBLT, 8, 6,
+                 BITBLT, 2, 0, BITBLT, 5, 3, BITBLT, 8, 6, UNUSED, -1, -1,
                  IS_TERTIARY_OP | CLOBBER_DEST,
                  "ldrsb", "r!0d, [r!1d, r!2d]", 1),
     ENCODING_MAP(THUMB_LDRSH_RRR,     0x5e00,
-                 BITBLT, 2, 0, BITBLT, 5, 3, BITBLT, 8, 6,
+                 BITBLT, 2, 0, BITBLT, 5, 3, BITBLT, 8, 6, UNUSED, -1, -1,
                  IS_TERTIARY_OP | CLOBBER_DEST,
                  "ldrsh", "r!0d, [r!1d, r!2d]", 1),
     ENCODING_MAP(THUMB_LSL,           0x0000,
-                 BITBLT, 2, 0, BITBLT, 5, 3, BITBLT, 10, 6,
-                 IS_TERTIARY_OP | CLOBBER_DEST,
-                 "lsl", "r!0d, r!1d, #!2d", 1),
+                 BITBLT, 2, 0, BITBLT, 5, 3, BITBLT, 10, 6, UNUSED, -1, -1,
+                 IS_TERTIARY_OP | CLOBBER_DEST | SETS_CCODES,
+                 "lsls", "r!0d, r!1d, #!2d", 1),
     ENCODING_MAP(THUMB_LSLV,          0x4080,
-                 BITBLT, 2, 0, BITBLT, 5, 3, UNUSED, -1, -1,
-                 IS_BINARY_OP | CLOBBER_DEST,
-                 "lsl", "r!0d, r!1d", 1),
+                 BITBLT, 2, 0, BITBLT, 5, 3, UNUSED, -1, -1, UNUSED, -1, -1,
+                 IS_BINARY_OP | CLOBBER_DEST | SETS_CCODES,
+                 "lsls", "r!0d, r!1d", 1),
     ENCODING_MAP(THUMB_LSR,           0x0800,
-                 BITBLT, 2, 0, BITBLT, 5, 3, BITBLT, 10, 6,
-                 IS_TERTIARY_OP | CLOBBER_DEST,
-                 "lsr", "r!0d, r!1d, #!2d", 1),
+                 BITBLT, 2, 0, BITBLT, 5, 3, BITBLT, 10, 6, UNUSED, -1, -1,
+                 IS_TERTIARY_OP | CLOBBER_DEST | SETS_CCODES,
+                 "lsrs", "r!0d, r!1d, #!2d", 1),
     ENCODING_MAP(THUMB_LSRV,          0x40c0,
-                 BITBLT, 2, 0, BITBLT, 5, 3, UNUSED, -1, -1,
-                 IS_BINARY_OP | CLOBBER_DEST,
-                 "lsr", "r!0d, r!1d", 1),
+                 BITBLT, 2, 0, BITBLT, 5, 3, UNUSED, -1, -1, UNUSED, -1, -1,
+                 IS_BINARY_OP | CLOBBER_DEST | SETS_CCODES,
+                 "lsrs", "r!0d, r!1d", 1),
     ENCODING_MAP(THUMB_MOV_IMM,       0x2000,
-                 BITBLT, 10, 8, BITBLT, 7, 0, UNUSED, -1, -1,
-                 IS_BINARY_OP | CLOBBER_DEST,
-                 "mov", "r!0d, #!1d", 1),
+                 BITBLT, 10, 8, BITBLT, 7, 0, UNUSED, -1, -1, UNUSED, -1, -1,
+                 IS_BINARY_OP | CLOBBER_DEST | SETS_CCODES,
+                 "movs", "r!0d, #!1d", 1),
     ENCODING_MAP(THUMB_MOV_RR,        0x1c00,
-                 BITBLT, 2, 0, BITBLT, 5, 3, UNUSED, -1, -1,
-                 IS_BINARY_OP | CLOBBER_DEST,
-                 "mov", "r!0d, r!1d", 1),
+                 BITBLT, 2, 0, BITBLT, 5, 3, UNUSED, -1, -1, UNUSED, -1, -1,
+                 IS_BINARY_OP | CLOBBER_DEST | SETS_CCODES,
+                 "movs", "r!0d, r!1d", 1),
     ENCODING_MAP(THUMB_MOV_RR_H2H,    0x46c0,
-                 BITBLT, 2, 0, BITBLT, 5, 3, UNUSED, -1, -1,
+                 BITBLT, 2, 0, BITBLT, 5, 3, UNUSED, -1, -1, UNUSED, -1, -1,
                  IS_BINARY_OP | CLOBBER_DEST,
                  "mov", "r!0D, r!1D", 1),
     ENCODING_MAP(THUMB_MOV_RR_H2L,    0x4640,
-                 BITBLT, 2, 0, BITBLT, 5, 3, UNUSED, -1, -1,
+                 BITBLT, 2, 0, BITBLT, 5, 3, UNUSED, -1, -1, UNUSED, -1, -1,
                  IS_BINARY_OP | CLOBBER_DEST,
                  "mov", "r!0d, r!1D", 1),
     ENCODING_MAP(THUMB_MOV_RR_L2H,    0x4680,
-                 BITBLT, 2, 0, BITBLT, 5, 3, UNUSED, -1, -1,
+                 BITBLT, 2, 0, BITBLT, 5, 3, UNUSED, -1, -1, UNUSED, -1, -1,
                  IS_BINARY_OP | CLOBBER_DEST,
                  "mov", "r!0D, r!1d", 1),
     ENCODING_MAP(THUMB_MUL,           0x4340,
-                 BITBLT, 2, 0, BITBLT, 5, 3, UNUSED, -1, -1,
-                 IS_BINARY_OP | CLOBBER_DEST,
-                 "mul", "r!0d, r!1d", 1),
+                 BITBLT, 2, 0, BITBLT, 5, 3, UNUSED, -1, -1, UNUSED, -1, -1,
+                 IS_BINARY_OP | CLOBBER_DEST | SETS_CCODES,
+                 "muls", "r!0d, r!1d", 1),
     ENCODING_MAP(THUMB_MVN,           0x43c0,
-                 BITBLT, 2, 0, BITBLT, 5, 3, UNUSED, -1, -1,
-                 IS_BINARY_OP | CLOBBER_DEST,
-                 "mvn", "r!0d, r!1d", 1),
+                 BITBLT, 2, 0, BITBLT, 5, 3, UNUSED, -1, -1, UNUSED, -1, -1,
+                 IS_BINARY_OP | CLOBBER_DEST | SETS_CCODES,
+                 "mvns", "r!0d, r!1d", 1),
     ENCODING_MAP(THUMB_NEG,           0x4240,
-                 BITBLT, 2, 0, BITBLT, 5, 3, UNUSED, -1, -1,
-                 IS_BINARY_OP | CLOBBER_DEST,
-                 "neg", "r!0d, r!1d", 1),
+                 BITBLT, 2, 0, BITBLT, 5, 3, UNUSED, -1, -1, UNUSED, -1, -1,
+                 IS_BINARY_OP | CLOBBER_DEST | SETS_CCODES,
+                 "negs", "r!0d, r!1d", 1),
     ENCODING_MAP(THUMB_ORR,           0x4300,
-                 BITBLT, 2, 0, BITBLT, 5, 3, UNUSED, -1, -1,
-                 IS_BINARY_OP | CLOBBER_DEST,
-                 "orr", "r!0d, r!1d", 1),
+                 BITBLT, 2, 0, BITBLT, 5, 3, UNUSED, -1, -1, UNUSED, -1, -1,
+                 IS_BINARY_OP | CLOBBER_DEST | SETS_CCODES,
+                 "orrs", "r!0d, r!1d", 1),
     ENCODING_MAP(THUMB_POP,           0xbc00,
-                 BITBLT, 8, 0, UNUSED, -1, -1, UNUSED, -1, -1,
+                 BITBLT, 8, 0, UNUSED, -1, -1, UNUSED, -1, -1, UNUSED, -1, -1,
                  IS_UNARY_OP,
                  "pop", "<!0R>", 1),
     ENCODING_MAP(THUMB_PUSH,          0xb400,
-                 BITBLT, 8, 0, UNUSED, -1, -1, UNUSED, -1, -1,
+                 BITBLT, 8, 0, UNUSED, -1, -1, UNUSED, -1, -1, UNUSED, -1, -1,
                  IS_UNARY_OP,
                  "push", "<!0R>", 1),
-    ENCODING_MAP(THUMB_ROR,           0x41c0,
-                 BITBLT, 2, 0, BITBLT, 5, 3, UNUSED, -1, -1,
-                 IS_BINARY_OP | CLOBBER_DEST,
-                 "ror", "r!0d, r!1d", 1),
+    ENCODING_MAP(THUMB_RORV,           0x41c0,
+                 BITBLT, 2, 0, BITBLT, 5, 3, UNUSED, -1, -1, UNUSED, -1, -1,
+                 IS_BINARY_OP | CLOBBER_DEST | SETS_CCODES,
+                 "rors", "r!0d, r!1d", 1),
     ENCODING_MAP(THUMB_SBC,           0x4180,
-                 BITBLT, 2, 0, BITBLT, 5, 3, UNUSED, -1, -1,
-                 IS_BINARY_OP | CLOBBER_DEST,
-                 "sbc", "r!0d, r!1d", 1),
+                 BITBLT, 2, 0, BITBLT, 5, 3, UNUSED, -1, -1, UNUSED, -1, -1,
+                 IS_BINARY_OP | CLOBBER_DEST | USES_CCODES | SETS_CCODES,
+                 "sbcs", "r!0d, r!1d", 1),
     ENCODING_MAP(THUMB_STMIA,         0xc000,
-                 BITBLT, 10, 8, BITBLT, 7, 0, UNUSED, -1, -1,
+                 BITBLT, 10, 8, BITBLT, 7, 0, UNUSED, -1, -1, UNUSED, -1, -1,
                  IS_BINARY_OP | CLOBBER_SRC1,
                  "stmia", "r!0d!!, <!1R>", 1),
     ENCODING_MAP(THUMB_STR_RRI5,      0x6000,
-                 BITBLT, 2, 0, BITBLT, 5, 3, BITBLT, 10, 6,
+                 BITBLT, 2, 0, BITBLT, 5, 3, BITBLT, 10, 6, UNUSED, -1, -1,
                  IS_TERTIARY_OP,
                  "str", "r!0d, [r!1d, #!2E]", 1),
     ENCODING_MAP(THUMB_STR_RRR,       0x5000,
-                 BITBLT, 2, 0, BITBLT, 5, 3, BITBLT, 8, 6,
+                 BITBLT, 2, 0, BITBLT, 5, 3, BITBLT, 8, 6, UNUSED, -1, -1,
                  IS_TERTIARY_OP,
                  "str", "r!0d, [r!1d, r!2d]", 1),
     ENCODING_MAP(THUMB_STR_SP_REL,    0x9000,
-                 BITBLT, 10, 8, BITBLT, 7, 0, UNUSED, -1, -1,
+                 BITBLT, 10, 8, BITBLT, 7, 0, UNUSED, -1, -1, UNUSED, -1, -1,
                  IS_BINARY_OP,
                  "str", "r!0d, [sp, #!1E]", 1),
     ENCODING_MAP(THUMB_STRB_RRI5,     0x7000,
-                 BITBLT, 2, 0, BITBLT, 5, 3, BITBLT, 10, 6,
+                 BITBLT, 2, 0, BITBLT, 5, 3, BITBLT, 10, 6, UNUSED, -1, -1,
                  IS_TERTIARY_OP,
                  "strb", "r!0d, [r!1d, #!2d]", 1),
     ENCODING_MAP(THUMB_STRB_RRR,      0x5400,
-                 BITBLT, 2, 0, BITBLT, 5, 3, BITBLT, 8, 6,
+                 BITBLT, 2, 0, BITBLT, 5, 3, BITBLT, 8, 6, UNUSED, -1, -1,
                  IS_TERTIARY_OP,
                  "strb", "r!0d, [r!1d, r!2d]", 1),
     ENCODING_MAP(THUMB_STRH_RRI5,     0x8000,
-                 BITBLT, 2, 0, BITBLT, 5, 3, BITBLT, 10, 6,
+                 BITBLT, 2, 0, BITBLT, 5, 3, BITBLT, 10, 6, UNUSED, -1, -1,
                  IS_TERTIARY_OP,
                  "strh", "r!0d, [r!1d, #!2F]", 1),
     ENCODING_MAP(THUMB_STRH_RRR,      0x5200,
-                 BITBLT, 2, 0, BITBLT, 5, 3, BITBLT, 8, 6,
+                 BITBLT, 2, 0, BITBLT, 5, 3, BITBLT, 8, 6, UNUSED, -1, -1,
                  IS_TERTIARY_OP,
                  "strh", "r!0d, [r!1d, r!2d]", 1),
     ENCODING_MAP(THUMB_SUB_RRI3,      0x1e00,
-                 BITBLT, 2, 0, BITBLT, 5, 3, BITBLT, 8, 6,
-                 IS_TERTIARY_OP | CLOBBER_DEST,
-                 "sub", "r!0d, r!1d, #!2d]", 1),
+                 BITBLT, 2, 0, BITBLT, 5, 3, BITBLT, 8, 6, UNUSED, -1, -1,
+                 IS_TERTIARY_OP | CLOBBER_DEST | SETS_CCODES,
+                 "subs", "r!0d, r!1d, #!2d]", 1),
     ENCODING_MAP(THUMB_SUB_RI8,       0x3800,
-                 BITBLT, 10, 8, BITBLT, 7, 0, UNUSED, -1, -1,
-                 IS_BINARY_OP | CLOBBER_DEST,
-                 "sub", "r!0d, #!1d", 1),
+                 BITBLT, 10, 8, BITBLT, 7, 0, UNUSED, -1, -1, UNUSED, -1, -1,
+                 IS_BINARY_OP | CLOBBER_DEST | SETS_CCODES,
+                 "subs", "r!0d, #!1d", 1),
     ENCODING_MAP(THUMB_SUB_RRR,       0x1a00,
-                 BITBLT, 2, 0, BITBLT, 5, 3, BITBLT, 8, 6,
-                 IS_TERTIARY_OP | CLOBBER_DEST,
-                 "sub", "r!0d, r!1d, r!2d", 1),
+                 BITBLT, 2, 0, BITBLT, 5, 3, BITBLT, 8, 6, UNUSED, -1, -1,
+                 IS_TERTIARY_OP | CLOBBER_DEST | SETS_CCODES,
+                 "subs", "r!0d, r!1d, r!2d", 1),
     ENCODING_MAP(THUMB_SUB_SPI7,      0xb080,
-                 BITBLT, 6, 0, UNUSED, -1, -1, UNUSED, -1, -1,
+                 BITBLT, 6, 0, UNUSED, -1, -1, UNUSED, -1, -1, UNUSED, -1, -1,
                  IS_UNARY_OP | CLOBBER_DEST,
                  "sub", "sp, #!0d", 1),
     ENCODING_MAP(THUMB_SWI,           0xdf00,
-                 BITBLT, 7, 0, UNUSED, -1, -1, UNUSED, -1, -1,
+                 BITBLT, 7, 0, UNUSED, -1, -1, UNUSED, -1, -1, UNUSED, -1, -1,
                  IS_UNARY_OP | IS_BRANCH,
                  "swi", "!0d", 1),
     ENCODING_MAP(THUMB_TST,           0x4200,
-                 BITBLT, 2, 0, BITBLT, 5, 3, UNUSED, -1, -1,
-                 IS_UNARY_OP,
+                 BITBLT, 2, 0, BITBLT, 5, 3, UNUSED, -1, -1, UNUSED, -1, -1,
+                 IS_UNARY_OP | SETS_CCODES,
                  "tst", "r!0d, r!1d", 1),
     ENCODING_MAP(THUMB2_VLDRS,       0xed900a00,
-                 SFP, 22, 12, BITBLT, 19, 16, BITBLT, 7, 0,
+                 SFP, 22, 12, BITBLT, 19, 16, BITBLT, 7, 0, UNUSED, -1, -1,
                  IS_TERTIARY_OP | CLOBBER_DEST,
                  "vldr", "!0s, [r!1d, #!2E]", 2),
     ENCODING_MAP(THUMB2_VLDRD,       0xed900b00,
-                 DFP, 22, 12, BITBLT, 19, 16, BITBLT, 7, 0,
+                 DFP, 22, 12, BITBLT, 19, 16, BITBLT, 7, 0, UNUSED, -1, -1,
                  IS_TERTIARY_OP | CLOBBER_DEST,
                  "vldr", "!0S, [r!1d, #!2E]", 2),
     ENCODING_MAP(THUMB2_VMULS,        0xee200a00,
-                 SFP, 22, 12, SFP, 7, 16, SFP, 5, 0,
+                 SFP, 22, 12, SFP, 7, 16, SFP, 5, 0, UNUSED, -1, -1,
                  IS_TERTIARY_OP | CLOBBER_DEST,
                  "vmuls", "!0s, !1s, !2s", 2),
     ENCODING_MAP(THUMB2_VMULD,        0xee200b00,
-                 DFP, 22, 12, DFP, 7, 16, DFP, 5, 0,
+                 DFP, 22, 12, DFP, 7, 16, DFP, 5, 0, UNUSED, -1, -1,
                  IS_TERTIARY_OP | CLOBBER_DEST,
                  "vmuld", "!0S, !1S, !2S", 2),
     ENCODING_MAP(THUMB2_VSTRS,       0xed800a00,
-                 SFP, 22, 12, BITBLT, 19, 16, BITBLT, 7, 0,
+                 SFP, 22, 12, BITBLT, 19, 16, BITBLT, 7, 0, UNUSED, -1, -1,
                  IS_TERTIARY_OP,
                  "vstr", "!0s, [r!1d, #!2E]", 2),
     ENCODING_MAP(THUMB2_VSTRD,       0xed800b00,
-                 DFP, 22, 12, BITBLT, 19, 16, BITBLT, 7, 0,
+                 DFP, 22, 12, BITBLT, 19, 16, BITBLT, 7, 0, UNUSED, -1, -1,
                  IS_TERTIARY_OP,
                  "vstr", "!0S, [r!1d, #!2E]", 2),
     ENCODING_MAP(THUMB2_VSUBS,        0xee300a40,
-                 SFP, 22, 12, SFP, 7, 16, SFP, 5, 0,
+                 SFP, 22, 12, SFP, 7, 16, SFP, 5, 0, UNUSED, -1, -1,
                  IS_TERTIARY_OP | CLOBBER_DEST,
                  "vsub", "!0s, !1s, !2s", 2),
     ENCODING_MAP(THUMB2_VSUBD,        0xee300b40,
-                 DFP, 22, 12, DFP, 7, 16, DFP, 5, 0,
+                 DFP, 22, 12, DFP, 7, 16, DFP, 5, 0, UNUSED, -1, -1,
                  IS_TERTIARY_OP | CLOBBER_DEST,
                  "vsub", "!0S, !1S, !2S", 2),
     ENCODING_MAP(THUMB2_VADDS,        0xee300a00,
-                 SFP, 22, 12, SFP, 7, 16, SFP, 5, 0,
+                 SFP, 22, 12, SFP, 7, 16, SFP, 5, 0, UNUSED, -1, -1,
                  IS_TERTIARY_OP | CLOBBER_DEST,
                  "vadd", "!0s, !1s, !2s", 2),
     ENCODING_MAP(THUMB2_VADDD,        0xee300b00,
-                 DFP, 22, 12, DFP, 7, 16, DFP, 5, 0,
+                 DFP, 22, 12, DFP, 7, 16, DFP, 5, 0, UNUSED, -1, -1,
                  IS_TERTIARY_OP | CLOBBER_DEST,
                  "vadd", "!0S, !1S, !2S", 2),
     ENCODING_MAP(THUMB2_VDIVS,        0xee800a00,
-                 SFP, 22, 12, SFP, 7, 16, SFP, 5, 0,
+                 SFP, 22, 12, SFP, 7, 16, SFP, 5, 0, UNUSED, -1, -1,
                  IS_TERTIARY_OP | CLOBBER_DEST,
                  "vdivs", "!0s, !1s, !2s", 2),
     ENCODING_MAP(THUMB2_VDIVD,        0xee800b00,
-                 DFP, 22, 12, DFP, 7, 16, DFP, 5, 0,
+                 DFP, 22, 12, DFP, 7, 16, DFP, 5, 0, UNUSED, -1, -1,
                  IS_TERTIARY_OP | CLOBBER_DEST,
                  "vdivs", "!0S, !1S, !2S", 2),
     ENCODING_MAP(THUMB2_VCVTIF,       0xeeb80ac0,
-                 SFP, 22, 12, SFP, 5, 0, UNUSED, -1, -1,
+                 SFP, 22, 12, SFP, 5, 0, UNUSED, -1, -1, UNUSED, -1, -1,
                  IS_BINARY_OP | CLOBBER_DEST,
                  "vcvt.f32", "!0s, !1s", 2),
     ENCODING_MAP(THUMB2_VCVTID,       0xeeb80bc0,
-                 DFP, 22, 12, SFP, 5, 0, UNUSED, -1, -1,
+                 DFP, 22, 12, SFP, 5, 0, UNUSED, -1, -1, UNUSED, -1, -1,
                  IS_BINARY_OP | CLOBBER_DEST,
                  "vcvt.f64", "!0S, !1s", 2),
     ENCODING_MAP(THUMB2_VCVTFI,       0xeebd0ac0,
-                 SFP, 22, 12, SFP, 5, 0, UNUSED, -1, -1,
+                 SFP, 22, 12, SFP, 5, 0, UNUSED, -1, -1, UNUSED, -1, -1,
                  IS_BINARY_OP | CLOBBER_DEST,
                  "vcvt.s32.f32 ", "!0s, !1s", 2),
     ENCODING_MAP(THUMB2_VCVTDI,       0xeebd0bc0,
-                 SFP, 22, 12, DFP, 5, 0, UNUSED, -1, -1,
+                 SFP, 22, 12, DFP, 5, 0, UNUSED, -1, -1, UNUSED, -1, -1,
                  IS_BINARY_OP | CLOBBER_DEST,
                  "vcvt.s32.f64 ", "!0s, !1S", 2),
     ENCODING_MAP(THUMB2_VCVTFD,       0xeeb70ac0,
-                 DFP, 22, 12, SFP, 5, 0, UNUSED, -1, -1,
+                 DFP, 22, 12, SFP, 5, 0, UNUSED, -1, -1, UNUSED, -1, -1,
                  IS_BINARY_OP | CLOBBER_DEST,
                  "vcvt.f64.f32 ", "!0S, !1s", 2),
     ENCODING_MAP(THUMB2_VCVTDF,       0xeeb70bc0,
-                 SFP, 22, 12, DFP, 5, 0, UNUSED, -1, -1,
+                 SFP, 22, 12, DFP, 5, 0, UNUSED, -1, -1, UNUSED, -1, -1,
                  IS_BINARY_OP | CLOBBER_DEST,
                  "vcvt.f32.f64 ", "!0s, !1S", 2),
     ENCODING_MAP(THUMB2_VSQRTS,       0xeeb10ac0,
-                 SFP, 22, 12, SFP, 5, 0, UNUSED, -1, -1,
+                 SFP, 22, 12, SFP, 5, 0, UNUSED, -1, -1, UNUSED, -1, -1,
                  IS_BINARY_OP | CLOBBER_DEST,
                  "vsqrt.f32 ", "!0s, !1s", 2),
     ENCODING_MAP(THUMB2_VSQRTD,       0xeeb10bc0,
-                 DFP, 22, 12, DFP, 5, 0, UNUSED, -1, -1,
+                 DFP, 22, 12, DFP, 5, 0, UNUSED, -1, -1, UNUSED, -1, -1,
                  IS_BINARY_OP | CLOBBER_DEST,
                  "vsqrt.f64 ", "!0S, !1S", 2),
-    ENCODING_MAP(THUMB2_MOV_IMM_SHIFT,       0xf04f0000,
-                 BITBLT, 11, 8, MODIMM, -1, -1, UNUSED, -1, -1,
+    ENCODING_MAP(THUMB2_MOV_IMM_SHIFT, 0xf04f0000, /* no setflags encoding */
+                 BITBLT, 11, 8, MODIMM, -1, -1, UNUSED, -1, -1, UNUSED, -1, -1,
                  IS_BINARY_OP | CLOBBER_DEST,
                  "mov", "r!0d, #!1m", 2),
     ENCODING_MAP(THUMB2_MOV_IMM16,       0xf2400000,
-                 BITBLT, 11, 8, IMM16, -1, -1, UNUSED, -1, -1,
+                 BITBLT, 11, 8, IMM16, -1, -1, UNUSED, -1, -1, UNUSED, -1, -1,
                  IS_BINARY_OP | CLOBBER_DEST,
                  "mov", "r!0d, #!1M", 2),
     ENCODING_MAP(THUMB2_STR_RRI12,       0xf8c00000,
-                 BITBLT, 15, 12, BITBLT, 19, 16, BITBLT, 11, 0,
+                 BITBLT, 15, 12, BITBLT, 19, 16, BITBLT, 11, 0, UNUSED, -1, -1,
                  IS_TERTIARY_OP,
                  "str", "r!0d,[r!1d, #!2d", 2),
     ENCODING_MAP(THUMB2_LDR_RRI12,       0xf8d00000,
-                 BITBLT, 15, 12, BITBLT, 19, 16, BITBLT, 11, 0,
+                 BITBLT, 15, 12, BITBLT, 19, 16, BITBLT, 11, 0, UNUSED, -1, -1,
                  IS_TERTIARY_OP | CLOBBER_DEST,
                  "ldr", "r!0d,[r!1d, #!2d", 2),
     ENCODING_MAP(THUMB2_STR_RRI8_PREDEC,       0xf8400c00,
-                 BITBLT, 15, 12, BITBLT, 19, 16, BITBLT, 8, 0,
+                 BITBLT, 15, 12, BITBLT, 19, 16, BITBLT, 8, 0, UNUSED, -1, -1,
                  IS_TERTIARY_OP,
                  "str", "r!0d,[r!1d, #-!2d]", 2),
     ENCODING_MAP(THUMB2_LDR_RRI8_PREDEC,       0xf8500c00,
-                 BITBLT, 15, 12, BITBLT, 19, 16, BITBLT, 8, 0,
+                 BITBLT, 15, 12, BITBLT, 19, 16, BITBLT, 8, 0, UNUSED, -1, -1,
                  IS_TERTIARY_OP | CLOBBER_DEST,
                  "ldr", "r!0d,[r!1d, #-!2d]", 2),
     ENCODING_MAP(THUMB2_CBNZ,       0xb900,
-                 BITBLT, 2, 0, IMM6, -1, -1, UNUSED, -1, -1,
-                 IS_BINARY_OP,
+                 BITBLT, 2, 0, IMM6, -1, -1, UNUSED, -1, -1, UNUSED, -1, -1,
+                 IS_BINARY_OP,  /* Note: does not affect flags */
                  "cbnz", "r!0d,!1t", 1),
     ENCODING_MAP(THUMB2_CBZ,       0xb100,
-                 BITBLT, 2, 0, IMM6, -1, -1, UNUSED, -1, -1,
-                 IS_BINARY_OP,
+                 BITBLT, 2, 0, IMM6, -1, -1, UNUSED, -1, -1, UNUSED, -1, -1,
+                 IS_BINARY_OP, /* Note: does not affect flags */
                  "cbz", "r!0d,!1t", 1),
-    ENCODING_MAP(THUMB2_ADD_RRI12,       0xf1000000,
-                 BITBLT, 11, 8, BITBLT, 19, 16, IMM12, -1, -1,
-                 IS_TERTIARY_OP | CLOBBER_DEST,
+    ENCODING_MAP(THUMB2_ADD_RRI12,       0xf2000000,
+                 BITBLT, 11, 8, BITBLT, 19, 16, IMM12, -1, -1, UNUSED, -1, -1,
+                 IS_TERTIARY_OP | CLOBBER_DEST,/* Note: doesn't affect flags */
                  "add", "r!0d,r!1d,#!2d", 2),
-    ENCODING_MAP(THUMB2_MOV_RR,       0xea4f0000,
-                 BITBLT, 11, 8, BITBLT, 3, 0, UNUSED, -1, -1,
+    ENCODING_MAP(THUMB2_MOV_RR,       0xea4f0000, /* no setflags encoding */
+                 BITBLT, 11, 8, BITBLT, 3, 0, UNUSED, -1, -1, UNUSED, -1, -1,
                  IS_BINARY_OP | CLOBBER_DEST,
                  "mov", "r!0d, r!1d", 2),
     ENCODING_MAP(THUMB2_VMOVS,       0xeeb00a40,
-                 SFP, 22, 12, SFP, 5, 0, UNUSED, -1, -1,
+                 SFP, 22, 12, SFP, 5, 0, UNUSED, -1, -1, UNUSED, -1, -1,
                  IS_BINARY_OP | CLOBBER_DEST,
                  "vmov.f32 ", "!0s, !1s", 2),
     ENCODING_MAP(THUMB2_VMOVD,       0xeeb00b40,
-                 DFP, 22, 12, DFP, 5, 0, UNUSED, -1, -1,
+                 DFP, 22, 12, DFP, 5, 0, UNUSED, -1, -1, UNUSED, -1, -1,
                  IS_BINARY_OP | CLOBBER_DEST,
                  "vmov.f64 ", "!0s, !1s", 2),
+    ENCODING_MAP(THUMB2_LDMIA,         0xe8900000,
+                 BITBLT, 19, 16, BITBLT, 15, 0, UNUSED, -1, -1, UNUSED, -1, -1,
+                 IS_BINARY_OP | CLOBBER_DEST | CLOBBER_SRC1,
+                 "ldmia", "r!0d!!, <!1R>", 2),
+    ENCODING_MAP(THUMB2_STMIA,         0xe8800000,
+                 BITBLT, 19, 16, BITBLT, 15, 0, UNUSED, -1, -1, UNUSED, -1, -1,
+                 IS_BINARY_OP | CLOBBER_SRC1,
+                 "stmia", "r!0d!!, <!1R>", 2),
+    ENCODING_MAP(THUMB2_ADD_RRR,  0xeb100000, /* setflags encoding */
+                 BITBLT, 11, 8, BITBLT, 19, 16, BITBLT, 3, 0, SHIFT, -1, -1,
+                 IS_QUAD_OP | CLOBBER_DEST | SETS_CCODES,
+                 "adds", "r!0d, r!1d, r!2d", 2),
+    ENCODING_MAP(THUMB2_SUB_RRR,       0xebb00000, /* setflags enconding */
+                 BITBLT, 11, 8, BITBLT, 19, 16, BITBLT, 3, 0, SHIFT, -1, -1,
+                 IS_QUAD_OP | CLOBBER_DEST | SETS_CCODES,
+                 "subs", "r!0d, r!1d, r!2d", 2),
+    ENCODING_MAP(THUMB2_SBC_RRR,       0xeb700000, /* setflags encoding */
+                 BITBLT, 11, 8, BITBLT, 19, 16, BITBLT, 3, 0, SHIFT, -1, -1,
+                 IS_QUAD_OP | CLOBBER_DEST | USES_CCODES | SETS_CCODES,
+                 "sbcs", "r!0d, r!1d, r!2d", 2),
+    ENCODING_MAP(THUMB2_CMP_RR,       0xebb00f00,
+                 BITBLT, 19, 16, BITBLT, 3, 0, SHIFT, -1, -1, UNUSED, -1, -1,
+                 IS_TERTIARY_OP | SETS_CCODES,
+                 "cmp", "r!0d, r!1d", 2),
+    ENCODING_MAP(THUMB2_SUB_RRI12,       0xf2a00000,
+                 BITBLT, 11, 8, BITBLT, 19, 16, IMM12, -1, -1, UNUSED, -1, -1,
+                 IS_TERTIARY_OP | CLOBBER_DEST,/* Note: doesn't affect flags */
+                 "sub", "r!0d,r!1d,#!2d", 2),
+    ENCODING_MAP(THUMB2_MVN_IMM_SHIFT,  0xf06f0000, /* no setflags encoding */
+                 BITBLT, 11, 8, MODIMM, -1, -1, UNUSED, -1, -1, UNUSED, -1, -1,
+                 IS_BINARY_OP | CLOBBER_DEST,
+                 "mvn", "r!0d, #!1n", 2),
+    ENCODING_MAP(THUMB2_SEL,       0xfaa0f080,
+                 BITBLT, 11, 8, BITBLT, 19, 16, BITBLT, 3, 0, UNUSED, -1, -1,
+                 IS_TERTIARY_OP | CLOBBER_DEST | USES_CCODES,
+                 "sel", "r!0d, r!1d, r!2d", 2),
+    ENCODING_MAP(THUMB2_UBFX,       0xf3c00000,
+                 BITBLT, 11, 8, BITBLT, 19, 16, LSB, -1, -1, BWIDTH, 4, 0,
+                 IS_QUAD_OP | CLOBBER_DEST,
+                 "ubfx", "r!0d, r!1d, #!2d, #!3d", 2),
+    ENCODING_MAP(THUMB2_SBFX,       0xf3400000,
+                 BITBLT, 11, 8, BITBLT, 19, 16, LSB, -1, -1, BWIDTH, 4, 0,
+                 IS_QUAD_OP | CLOBBER_DEST,
+                 "sbfx", "r!0d, r!1d, #!2d, #!3d", 2),
+    ENCODING_MAP(THUMB2_LDR_RRR,    0xf8500000,
+                 BITBLT, 15, 12, BITBLT, 19, 16, BITBLT, 3, 0, BITBLT, 5, 4,
+                 IS_QUAD_OP | CLOBBER_DEST,
+                 "ldr", "r!0d,[r!1d, r!2d, LSL #!3d]", 2),
+    ENCODING_MAP(THUMB2_LDRH_RRR,    0xf8300000,
+                 BITBLT, 15, 12, BITBLT, 19, 16, BITBLT, 3, 0, BITBLT, 5, 4,
+                 IS_QUAD_OP | CLOBBER_DEST,
+                 "ldrh", "r!0d,[r!1d, r!2d, LSL #!3d]", 2),
+    ENCODING_MAP(THUMB2_LDRSH_RRR,    0xf9300000,
+                 BITBLT, 15, 12, BITBLT, 19, 16, BITBLT, 3, 0, BITBLT, 5, 4,
+                 IS_QUAD_OP | CLOBBER_DEST,
+                 "ldrsh", "r!0d,[r!1d, r!2d, LSL #!3d]", 2),
+    ENCODING_MAP(THUMB2_LDRB_RRR,    0xf8100000,
+                 BITBLT, 15, 12, BITBLT, 19, 16, BITBLT, 3, 0, BITBLT, 5, 4,
+                 IS_QUAD_OP | CLOBBER_DEST,
+                 "ldrb", "r!0d,[r!1d, r!2d, LSL #!3d]", 2),
+    ENCODING_MAP(THUMB2_LDRSB_RRR,    0xf9100000,
+                 BITBLT, 15, 12, BITBLT, 19, 16, BITBLT, 3, 0, BITBLT, 5, 4,
+                 IS_QUAD_OP | CLOBBER_DEST,
+                 "ldrsb", "r!0d,[r!1d, r!2d, LSL #!3d]", 2),
+    ENCODING_MAP(THUMB2_STR_RRR,    0xf8400000,
+                 BITBLT, 15, 12, BITBLT, 19, 16, BITBLT, 3, 0, BITBLT, 5, 4,
+                 IS_QUAD_OP | CLOBBER_DEST,
+                 "str", "r!0d,[r!1d, r!2d, LSL #!3d]", 2),
+    ENCODING_MAP(THUMB2_STRH_RRR,    0xf8200000,
+                 BITBLT, 15, 12, BITBLT, 19, 16, BITBLT, 3, 0, BITBLT, 5, 4,
+                 IS_QUAD_OP | CLOBBER_DEST,
+                 "strh", "r!0d,[r!1d, r!2d, LSL #!3d]", 2),
+    ENCODING_MAP(THUMB2_STRB_RRR,    0xf8000000,
+                 BITBLT, 15, 12, BITBLT, 19, 16, BITBLT, 3, 0, BITBLT, 5, 4,
+                 IS_QUAD_OP | CLOBBER_DEST,
+                 "strb", "r!0d,[r!1d, r!2d, LSL #!3d]", 2),
+    ENCODING_MAP(THUMB2_LDRH_RRI12,       0xf8b00000,
+                 BITBLT, 15, 12, BITBLT, 19, 16, BITBLT, 11, 0, UNUSED, -1, -1,
+                 IS_TERTIARY_OP | CLOBBER_DEST,
+                 "ldrh", "r!0d,[r!1d, #!2d", 2),
+    ENCODING_MAP(THUMB2_LDRSH_RRI12,       0xf9b00000,
+                 BITBLT, 15, 12, BITBLT, 19, 16, BITBLT, 11, 0, UNUSED, -1, -1,
+                 IS_TERTIARY_OP | CLOBBER_DEST,
+                 "ldrsh", "r!0d,[r!1d, #!2d", 2),
+    ENCODING_MAP(THUMB2_LDRB_RRI12,       0xf8900000,
+                 BITBLT, 15, 12, BITBLT, 19, 16, BITBLT, 11, 0, UNUSED, -1, -1,
+                 IS_TERTIARY_OP | CLOBBER_DEST,
+                 "ldrb", "r!0d,[r!1d, #!2d", 2),
+    ENCODING_MAP(THUMB2_LDRSB_RRI12,       0xf9900000,
+                 BITBLT, 15, 12, BITBLT, 19, 16, BITBLT, 11, 0, UNUSED, -1, -1,
+                 IS_TERTIARY_OP | CLOBBER_DEST,
+                 "ldrsb", "r!0d,[r!1d, #!2d", 2),
+    ENCODING_MAP(THUMB2_STRH_RRI12,       0xf8a00000,
+                 BITBLT, 15, 12, BITBLT, 19, 16, BITBLT, 11, 0, UNUSED, -1, -1,
+                 IS_TERTIARY_OP | CLOBBER_DEST,
+                 "strh", "r!0d,[r!1d, #!2d", 2),
+    ENCODING_MAP(THUMB2_STRB_RRI12,       0xf8800000,
+                 BITBLT, 15, 12, BITBLT, 19, 16, BITBLT, 11, 0, UNUSED, -1, -1,
+                 IS_TERTIARY_OP | CLOBBER_DEST,
+                 "strb", "r!0d,[r!1d, #!2d", 2),
+    ENCODING_MAP(THUMB2_POP,           0xe8bd0000,
+                 BITBLT, 15, 0, UNUSED, -1, -1, UNUSED, -1, -1, UNUSED, -1, -1,
+                 IS_UNARY_OP,
+                 "pop", "<!0R>", 2),
+    ENCODING_MAP(THUMB2_PUSH,          0xe8ad0000,
+                 BITBLT, 15, 0, UNUSED, -1, -1, UNUSED, -1, -1, UNUSED, -1, -1,
+                 IS_UNARY_OP,
+                 "push", "<!0R>", 2),
+    ENCODING_MAP(THUMB2_CMP_RI8, 0xf1b00f00,
+                 BITBLT, 19, 16, MODIMM, -1, -1, UNUSED, -1, -1, UNUSED, -1, -1,
+                 IS_BINARY_OP | CLOBBER_DEST | SETS_CCODES,
+                 "cmp", "r!0d, #!1m", 2),
+    ENCODING_MAP(THUMB2_ADC_RRR,  0xeb500000, /* setflags encoding */
+                 BITBLT, 11, 8, BITBLT, 19, 16, BITBLT, 3, 0, SHIFT, -1, -1,
+                 IS_QUAD_OP | CLOBBER_DEST | SETS_CCODES,
+                 "acds", "r!0d, r!1d, r!2d, shift !3d", 2),
+    ENCODING_MAP(THUMB2_AND_RRR,  0xea000000,
+                 BITBLT, 11, 8, BITBLT, 19, 16, BITBLT, 3, 0, SHIFT, -1, -1,
+                 IS_QUAD_OP | CLOBBER_DEST,
+                 "and", "r!0d, r!1d, r!2d, shift !3d", 2),
+    ENCODING_MAP(THUMB2_BIC_RRR,  0xea200000,
+                 BITBLT, 11, 8, BITBLT, 19, 16, BITBLT, 3, 0, SHIFT, -1, -1,
+                 IS_QUAD_OP | CLOBBER_DEST,
+                 "bic", "r!0d, r!1d, r!2d, shift !3d", 2),
+    ENCODING_MAP(THUMB2_CMN_RR,  0xeb000000,
+                 BITBLT, 19, 16, BITBLT, 3, 0, SHIFT, -1, -1, UNUSED, -1, -1,
+                 IS_TERTIARY_OP | CLOBBER_DEST | SETS_CCODES,
+                 "cmn", "r!0d, r!1d, shift !2d", 2),
+    ENCODING_MAP(THUMB2_EOR_RRR,  0xea800000,
+                 BITBLT, 11, 8, BITBLT, 19, 16, BITBLT, 3, 0, SHIFT, -1, -1,
+                 IS_QUAD_OP | CLOBBER_DEST,
+                 "eor", "r!0d, r!1d, r!2d, shift !3d", 2),
+    ENCODING_MAP(THUMB2_MUL_RRR,  0xfb00f000,
+                 BITBLT, 11, 8, BITBLT, 19, 16, BITBLT, 3, 0, UNUSED, -1, -1,
+                 IS_TERTIARY_OP | CLOBBER_DEST,
+                 "mul", "r!0d, r!1d, r!2d", 2),
+    ENCODING_MAP(THUMB2_MVN_RR,  0xea6f0000,
+                 BITBLT, 11, 8, BITBLT, 3, 0, SHIFT, -1, -1, UNUSED, -1, -1,
+                 IS_TERTIARY_OP | CLOBBER_DEST,
+                 "mvn", "r!0d, r!1d, shift !2d", 2),
+    ENCODING_MAP(THUMB2_RSUB_RRI8,       0xf1d00000,
+                 BITBLT, 11, 8, BITBLT, 19, 16, MODIMM, -1, -1, UNUSED, -1, -1,
+                 IS_TERTIARY_OP | CLOBBER_DEST | SETS_CCODES,
+                 "rsb", "r!0d,r!1d,#!2m", 2),
+    ENCODING_MAP(THUMB2_NEG_RR,       0xf1d00000, /* instance of rsub */
+                 BITBLT, 11, 8, BITBLT, 19, 16, UNUSED, -1, -1, UNUSED, -1, -1,
+                 IS_BINARY_OP | CLOBBER_DEST | SETS_CCODES,
+                 "neg", "r!0d,r!1d", 2),
+    ENCODING_MAP(THUMB2_ORR_RRR,  0xea400000,
+                 BITBLT, 11, 8, BITBLT, 19, 16, BITBLT, 3, 0, SHIFT, -1, -1,
+                 IS_QUAD_OP | CLOBBER_DEST,
+                 "orr", "r!0d, r!1d, r!2d, shift !3d", 2),
+    ENCODING_MAP(THUMB2_TST_RR,       0xea100f00,
+                 BITBLT, 19, 16, BITBLT, 3, 0, SHIFT, -1, -1, UNUSED, -1, -1,
+                 IS_TERTIARY_OP | SETS_CCODES,
+                 "tst", "r!0d, r!1d, shift !2d", 2),
+    ENCODING_MAP(THUMB2_LSLV_RRR,  0xfa00f000,
+                 BITBLT, 11, 8, BITBLT, 19, 16, BITBLT, 3, 0, UNUSED, -1, -1,
+                 IS_TERTIARY_OP | CLOBBER_DEST,
+                 "lsl", "r!0d, r!1d, r!2d", 2),
+    ENCODING_MAP(THUMB2_LSRV_RRR,  0xfa20f000,
+                 BITBLT, 11, 8, BITBLT, 19, 16, BITBLT, 3, 0, UNUSED, -1, -1,
+                 IS_TERTIARY_OP | CLOBBER_DEST,
+                 "lsr", "r!0d, r!1d, r!2d", 2),
+    ENCODING_MAP(THUMB2_ASRV_RRR,  0xfa40f000,
+                 BITBLT, 11, 8, BITBLT, 19, 16, BITBLT, 3, 0, UNUSED, -1, -1,
+                 IS_TERTIARY_OP | CLOBBER_DEST,
+                 "asr", "r!0d, r!1d, r!2d", 2),
+    ENCODING_MAP(THUMB2_RORV_RRR,  0xfa60f000,
+                 BITBLT, 11, 8, BITBLT, 19, 16, BITBLT, 3, 0, UNUSED, -1, -1,
+                 IS_TERTIARY_OP | CLOBBER_DEST,
+                 "ror", "r!0d, r!1d, r!2d", 2),
+    ENCODING_MAP(THUMB2_LSL_RRI5,  0xea4f0000,
+                 BITBLT, 11, 8, BITBLT, 3, 0, SHIFT5, -1, -1, UNUSED, -1, -1,
+                 IS_TERTIARY_OP | CLOBBER_DEST,
+                 "lsl", "r!0d, r!1d, #!2d", 2),
+    ENCODING_MAP(THUMB2_LSR_RRI5,  0xea4f0010,
+                 BITBLT, 11, 8, BITBLT, 3, 0, SHIFT5, -1, -1, UNUSED, -1, -1,
+                 IS_TERTIARY_OP | CLOBBER_DEST,
+                 "lsr", "r!0d, r!1d, #!2d", 2),
+    ENCODING_MAP(THUMB2_ASR_RRI5,  0xea4f0020,
+                 BITBLT, 11, 8, BITBLT, 3, 0, SHIFT5, -1, -1, UNUSED, -1, -1,
+                 IS_TERTIARY_OP | CLOBBER_DEST,
+                 "asr", "r!0d, r!1d, #!2d", 2),
+    ENCODING_MAP(THUMB2_ROR_RRI5,  0xea4f0030,
+                 BITBLT, 11, 8, BITBLT, 3, 0, SHIFT5, -1, -1, UNUSED, -1, -1,
+                 IS_TERTIARY_OP | CLOBBER_DEST,
+                 "ror", "r!0d, r!1d, #!2d", 2),
+    ENCODING_MAP(THUMB2_BIC_RRI8,  0xf0200000,
+                 BITBLT, 11, 8, BITBLT, 19, 16, MODIMM, -1, -1, UNUSED, -1, -1,
+                 IS_TERTIARY_OP | CLOBBER_DEST,
+                 "bic", "r!0d, r!1d, #!2m", 2),
+    ENCODING_MAP(THUMB2_AND_RRI8,  0xf0000000,
+                 BITBLT, 11, 8, BITBLT, 19, 16, MODIMM, -1, -1, UNUSED, -1, -1,
+                 IS_TERTIARY_OP | CLOBBER_DEST,
+                 "and", "r!0d, r!1d, #!2m", 2),
+    ENCODING_MAP(THUMB2_ORR_RRI8,  0xf0400000,
+                 BITBLT, 11, 8, BITBLT, 19, 16, MODIMM, -1, -1, UNUSED, -1, -1,
+                 IS_TERTIARY_OP | CLOBBER_DEST,
+                 "orr", "r!0d, r!1d, #!2m", 2),
+    ENCODING_MAP(THUMB2_EOR_RRI8,  0xf0800000,
+                 BITBLT, 11, 8, BITBLT, 19, 16, MODIMM, -1, -1, UNUSED, -1, -1,
+                 IS_TERTIARY_OP | CLOBBER_DEST,
+                 "eor", "r!0d, r!1d, #!2m", 2),
+    ENCODING_MAP(THUMB2_ADD_RRI8,  0xf1100000,
+                 BITBLT, 11, 8, BITBLT, 19, 16, MODIMM, -1, -1, UNUSED, -1, -1,
+                 IS_TERTIARY_OP | CLOBBER_DEST | SETS_CCODES,
+                 "adds", "r!0d, r!1d, #!2m", 2),
+    ENCODING_MAP(THUMB2_ADC_RRI8,  0xf1500000,
+                 BITBLT, 11, 8, BITBLT, 19, 16, MODIMM, -1, -1, UNUSED, -1, -1,
+                 IS_TERTIARY_OP | CLOBBER_DEST | SETS_CCODES | USES_CCODES,
+                 "adcs", "r!0d, r!1d, #!2m", 2),
+    ENCODING_MAP(THUMB2_SUB_RRI8,  0xf1b00000,
+                 BITBLT, 11, 8, BITBLT, 19, 16, MODIMM, -1, -1, UNUSED, -1, -1,
+                 IS_TERTIARY_OP | CLOBBER_DEST | SETS_CCODES,
+                 "subs", "r!0d, r!1d, #!2m", 2),
+    ENCODING_MAP(THUMB2_SBC_RRI8,  0xf1700000,
+                 BITBLT, 11, 8, BITBLT, 19, 16, MODIMM, -1, -1, UNUSED, -1, -1,
+                 IS_TERTIARY_OP | CLOBBER_DEST | SETS_CCODES | USES_CCODES,
+                 "sbcs", "r!0d, r!1d, #!2m", 2),
 };
 
+
 #define PADDING_MOV_R0_R0               0x1C00
 
 /* Write the numbers in the literal pool to the codegen stream */
@@ -606,11 +828,30 @@
         ArmEncodingMap *encoder = &EncodingMap[lir->opCode];
         u4 bits = encoder->skeleton;
         int i;
-        for (i = 0; i < 3; i++) {
+        for (i = 0; i < 4; i++) {
             u4 value;
             switch(encoder->fieldLoc[i].kind) {
                 case UNUSED:
                     break;
+                case SHIFT5:
+                    value = ((lir->operands[i] & 0x1c) >> 2) << 12;
+                    value |= (lir->operands[i] & 0x03) << 6;
+                    bits |= value;
+                    break;
+                case SHIFT:
+                    value = ((lir->operands[i] & 0x70) >> 4) << 12;
+                    value |= (lir->operands[i] & 0x0f) << 4;
+                    bits |= value;
+                    break;
+                case BWIDTH:
+                    value = lir->operands[i] - 1;
+                    bits |= value;
+                    break;
+                case LSB:
+                    value = ((lir->operands[i] & 0x1c) >> 2) << 12;
+                    value |= (lir->operands[i] & 0x03) << 6;
+                    bits |= value;
+                    break;
                 case IMM6:
                     value = ((lir->operands[i] & 0x20) >> 5) << 9;
                     value |= (lir->operands[i] & 0x1f) << 3;