Stage 3 of Thumb2 support. armv7-a now generates vfp code inline.
diff --git a/vm/compiler/codegen/arm/Assemble.c b/vm/compiler/codegen/arm/Assemble.c
index f9961ce..5a87014 100644
--- a/vm/compiler/codegen/arm/Assemble.c
+++ b/vm/compiler/codegen/arm/Assemble.c
@@ -25,20 +25,23 @@
 /*
  * opcode: ArmOpCode enum
  * skeleton: pre-designated bit-pattern for this opcode
+ * k0: key to applying ds/de
  * ds: dest start bit position
  * de: dest end bit position
+ * k1: key to applying s1s/s1e
  * s1s: src1 start bit position
  * s1e: src1 end bit position
+ * k2: key to applying s2s/s2e
  * s2s: src2 start bit position
  * s2e: src2 end bit position
  * operands: number of operands (for sanity check purposes)
  * name: mnemonic name
  * fmt: for pretty-prining
  */
-#define ENCODING_MAP(opcode, skeleton, ds, de, s1s, s1e, s2s, s2e, operands, \
-                     name, fmt, size) \
-        {skeleton, {{ds, de}, {s1s, s1e}, {s2s, s2e}}, opcode, operands, name, \
-         fmt, size}
+#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}
 
 /* Instruction dump string format keys: !pf, where "!" is the start
  * of the key, "p" is which numeric operand to use and "f" is the
@@ -65,226 +68,371 @@
  */
 /* NOTE: must be kept in sync with enum ArmOpcode from ArmLIR.h */
 ArmEncodingMap EncodingMap[ARM_LAST] = {
-    ENCODING_MAP(ARM_16BIT_DATA,    0x0000, 15, 0, -1, -1, -1, -1,
+    ENCODING_MAP(ARM_16BIT_DATA,    0x0000,
+                 BITBLT, 15, 0, UNUSED, -1, -1, UNUSED, -1, -1,
                  IS_UNARY_OP,
                  "data", "0x!0h(!0d)", 1),
-    ENCODING_MAP(THUMB_ADC,           0x4140, 2, 0, 5, 3, -1, -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),
-    ENCODING_MAP(THUMB_ADD_RRI3,      0x1c00, 2, 0, 5, 3, 8, 6,
+    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),
-    ENCODING_MAP(THUMB_ADD_RI8,       0x3000, 10, 8, 7, 0, -1, -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),
-    ENCODING_MAP(THUMB_ADD_RRR,       0x1800, 2, 0, 5, 3, 8, 6,
+    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),
-    ENCODING_MAP(THUMB_ADD_RR_LH,     0x4440, 2, 0, 5, 3, -1, -1,
+    ENCODING_MAP(THUMB_ADD_RR_LH,     0x4440,
+                 BITBLT, 2, 0, BITBLT, 5, 3, UNUSED, -1, -1,
                  IS_BINARY_OP | CLOBBER_DEST,
                  "add",
                  "r!0d, r!1d", 1),
-    ENCODING_MAP(THUMB_ADD_RR_HL,     0x4480, 2, 0, 5, 3, -1, -1,
+    ENCODING_MAP(THUMB_ADD_RR_HL,     0x4480,
+                 BITBLT, 2, 0, BITBLT, 5, 3, UNUSED, -1, -1,
                  IS_BINARY_OP | CLOBBER_DEST,
                  "add", "r!0d, r!1d", 1),
-    ENCODING_MAP(THUMB_ADD_RR_HH,     0x44c0, 2, 0, 5, 3, -1, -1,
+    ENCODING_MAP(THUMB_ADD_RR_HH,     0x44c0,
+                 BITBLT, 2, 0, BITBLT, 5, 3, UNUSED, -1, -1,
                  IS_BINARY_OP | CLOBBER_DEST,
                  "add", "r!0d, r!1d", 1),
-    ENCODING_MAP(THUMB_ADD_PC_REL,    0xa000, 10, 8, 7, 0, -1, -1,
+    ENCODING_MAP(THUMB_ADD_PC_REL,    0xa000,
+                 BITBLT, 10, 8, BITBLT, 7, 0, UNUSED, -1, -1,
                  IS_TERTIARY_OP | CLOBBER_DEST,
                  "add", "r!0d, pc, #!1E", 1),
-    ENCODING_MAP(THUMB_ADD_SP_REL,    0xa800, 10, 8, 7, 0, -1, -1,
+    ENCODING_MAP(THUMB_ADD_SP_REL,    0xa800,
+                 BITBLT, 10, 8, BITBLT, 7, 0, UNUSED, -1, -1,
                  IS_BINARY_OP | CLOBBER_DEST,
                  "add", "r!0d, sp, #!1E", 1),
-    ENCODING_MAP(THUMB_ADD_SPI7,      0xb000, 6, 0, -1, -1, -1, -1,
+    ENCODING_MAP(THUMB_ADD_SPI7,      0xb000,
+                 BITBLT, 6, 0, UNUSED, -1, -1, UNUSED, -1, -1,
                  IS_UNARY_OP | CLOBBER_DEST,
                  "add", "sp, #!0d*4", 1),
-    ENCODING_MAP(THUMB_AND_RR,        0x4000, 2, 0, 5, 3, -1, -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),
-    ENCODING_MAP(THUMB_ASR,           0x1000, 2, 0, 5, 3, 10, 6,
+    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),
-    ENCODING_MAP(THUMB_ASRV,          0x4100, 2, 0, 5, 3, -1, -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),
-    ENCODING_MAP(THUMB_B_COND,        0xd000, 7, 0, 11, 8, -1, -1,
+    ENCODING_MAP(THUMB_B_COND,        0xd000,
+                 BITBLT, 7, 0, BITBLT, 11, 8, UNUSED, -1, -1,
                  IS_BINARY_OP | IS_BRANCH,
                  "!1c", "!0t", 1),
-    ENCODING_MAP(THUMB_B_UNCOND,      0xe000, 10, 0, -1, -1, -1, -1,
+    ENCODING_MAP(THUMB_B_UNCOND,      0xe000,
+                 BITBLT, 10, 0, UNUSED, -1, -1, UNUSED, -1, -1,
                  NO_OPERAND | IS_BRANCH,
                  "b", "!0t", 1),
-    ENCODING_MAP(THUMB_BIC,           0x4380, 2, 0, 5, 3, -1, -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),
-    ENCODING_MAP(THUMB_BKPT,          0xbe00, 7, 0, -1, -1, -1, -1,
+    ENCODING_MAP(THUMB_BKPT,          0xbe00,
+                 BITBLT, 7, 0, UNUSED, -1, -1, UNUSED, -1, -1,
                  IS_UNARY_OP | IS_BRANCH,
                  "bkpt", "!0d", 1),
-    ENCODING_MAP(THUMB_BLX_1,         0xf000, 10, 0, -1, -1, -1, -1,
+    ENCODING_MAP(THUMB_BLX_1,         0xf000,
+                 BITBLT, 10, 0, UNUSED, -1, -1, UNUSED, -1, -1,
                  IS_BINARY_OP | IS_BRANCH,
                  "blx_1", "!0u", 1),
-    ENCODING_MAP(THUMB_BLX_2,         0xe800, 10, 0, -1, -1, -1, -1,
+    ENCODING_MAP(THUMB_BLX_2,         0xe800,
+                 BITBLT, 10, 0, UNUSED, -1, -1, UNUSED, -1, -1,
                  IS_BINARY_OP | IS_BRANCH,
                  "blx_2", "!0v", 1),
-    ENCODING_MAP(THUMB_BL_1,          0xf000, 10, 0, -1, -1, -1, -1,
+    ENCODING_MAP(THUMB_BL_1,          0xf000,
+                 BITBLT, 10, 0, UNUSED, -1, -1, UNUSED, -1, -1,
                  IS_UNARY_OP | IS_BRANCH,
                  "bl_1", "!0u", 1),
-    ENCODING_MAP(THUMB_BL_2,          0xf800, 10, 0, -1, -1, -1, -1,
+    ENCODING_MAP(THUMB_BL_2,          0xf800,
+                 BITBLT, 10, 0, UNUSED, -1, -1, UNUSED, -1, -1,
                  IS_UNARY_OP | IS_BRANCH,
                  "bl_2", "!0v", 1),
-    ENCODING_MAP(THUMB_BLX_R,         0x4780, 6, 3, -1, -1, -1, -1,
+    ENCODING_MAP(THUMB_BLX_R,         0x4780,
+                 BITBLT, 6, 3, UNUSED, -1, -1, UNUSED, -1, -1,
                  IS_UNARY_OP | IS_BRANCH,
                  "blx", "r!0d", 1),
-    ENCODING_MAP(THUMB_BX,            0x4700, 6, 3, -1, -1, -1, -1,
+    ENCODING_MAP(THUMB_BX,            0x4700,
+                 BITBLT, 6, 3, UNUSED, -1, -1, UNUSED, -1, -1,
                  IS_UNARY_OP | IS_BRANCH,
                  "bx", "r!0d", 1),
-    ENCODING_MAP(THUMB_CMN,           0x42c0, 2, 0, 5, 3, -1, -1,
+    ENCODING_MAP(THUMB_CMN,           0x42c0,
+                 BITBLT, 2, 0, BITBLT, 5, 3, UNUSED, -1, -1,
                  IS_BINARY_OP,
                  "cmn", "r!0d, r!1d", 1),
-    ENCODING_MAP(THUMB_CMP_RI8,       0x2800, 10, 8, 7, 0, -1, -1,
+    ENCODING_MAP(THUMB_CMP_RI8,       0x2800,
+                 BITBLT, 10, 8, BITBLT, 7, 0, UNUSED, -1, -1,
                  IS_BINARY_OP,
                  "cmp", "r!0d, #!1d", 1),
-    ENCODING_MAP(THUMB_CMP_RR,        0x4280, 2, 0, 5, 3, -1, -1,
+    ENCODING_MAP(THUMB_CMP_RR,        0x4280,
+                 BITBLT, 2, 0, BITBLT, 5, 3, UNUSED, -1, -1,
                  IS_BINARY_OP,
                  "cmp", "r!0d, r!1d", 1),
-    ENCODING_MAP(THUMB_CMP_LH,        0x4540, 2, 0, 5, 3, -1, -1,
+    ENCODING_MAP(THUMB_CMP_LH,        0x4540,
+                 BITBLT, 2, 0, BITBLT, 5, 3, UNUSED, -1, -1,
                  IS_BINARY_OP,
                  "cmp", "r!0d, r!1D", 1),
-    ENCODING_MAP(THUMB_CMP_HL,        0x4580, 2, 0, 5, 3, -1, -1,
+    ENCODING_MAP(THUMB_CMP_HL,        0x4580,
+                 BITBLT, 2, 0, BITBLT, 5, 3, UNUSED, -1, -1,
                  IS_BINARY_OP,
                  "cmp", "r!0D, r!1d", 1),
-    ENCODING_MAP(THUMB_CMP_HH,        0x45c0, 2, 0, 5, 3, -1, -1,
+    ENCODING_MAP(THUMB_CMP_HH,        0x45c0,
+                 BITBLT, 2, 0, BITBLT, 5, 3, UNUSED, -1, -1,
                  IS_BINARY_OP,
                  "cmp", "r!0D, r!1D", 1),
-    ENCODING_MAP(THUMB_EOR,           0x4040, 2, 0, 5, 3, -1, -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),
-    ENCODING_MAP(THUMB_LDMIA,         0xc800, 10, 8, 7, 0, -1, -1,
+    ENCODING_MAP(THUMB_LDMIA,         0xc800,
+                 BITBLT, 10, 8, BITBLT, 7, 0, UNUSED, -1, -1,
                  IS_BINARY_OP | CLOBBER_DEST | CLOBBER_SRC1,
                  "ldmia", "r!0d!!, <!1R>", 1),
-    ENCODING_MAP(THUMB_LDR_RRI5,      0x6800, 2, 0, 5, 3, 10, 6,
+    ENCODING_MAP(THUMB_LDR_RRI5,      0x6800,
+                 BITBLT, 2, 0, BITBLT, 5, 3, BITBLT, 10, 6,
                  IS_TERTIARY_OP | CLOBBER_DEST,
                  "ldr", "r!0d, [r!1d, #!2E]", 1),
-    ENCODING_MAP(THUMB_LDR_RRR,       0x5800, 2, 0, 5, 3, 8, 6,
+    ENCODING_MAP(THUMB_LDR_RRR,       0x5800,
+                 BITBLT, 2, 0, BITBLT, 5, 3, BITBLT, 8, 6,
                  IS_TERTIARY_OP | CLOBBER_DEST,
                  "ldr", "r!0d, [r!1d, r!2d]", 1),
-    ENCODING_MAP(THUMB_LDR_PC_REL,    0x4800, 10, 8, 7, 0, -1, -1,
+    ENCODING_MAP(THUMB_LDR_PC_REL,    0x4800,
+                 BITBLT, 10, 8, BITBLT, 7, 0, UNUSED, -1, -1,
                  IS_TERTIARY_OP | CLOBBER_DEST,
                  "ldr", "r!0d, [pc, #!1E]", 1),
-    ENCODING_MAP(THUMB_LDR_SP_REL,    0x9800, 10, 8, 7, 0, -1, -1,
+    ENCODING_MAP(THUMB_LDR_SP_REL,    0x9800,
+                 BITBLT, 10, 8, BITBLT, 7, 0, UNUSED, -1, -1,
                  IS_BINARY_OP | CLOBBER_DEST,
                  "ldr", "r!0d, [sp, #!1E]", 1),
-    ENCODING_MAP(THUMB_LDRB_RRI5,     0x7800, 2, 0, 5, 3, 10, 6,
+    ENCODING_MAP(THUMB_LDRB_RRI5,     0x7800,
+                 BITBLT, 2, 0, BITBLT, 5, 3, BITBLT, 10, 6,
                  IS_TERTIARY_OP | CLOBBER_DEST,
                  "ldrb", "r!0d, [r!1d, #2d]", 1),
-    ENCODING_MAP(THUMB_LDRB_RRR,      0x5c00, 2, 0, 5, 3, 8, 6,
+    ENCODING_MAP(THUMB_LDRB_RRR,      0x5c00,
+                 BITBLT, 2, 0, BITBLT, 5, 3, BITBLT, 8, 6,
                  IS_TERTIARY_OP | CLOBBER_DEST,
                  "ldrb", "r!0d, [r!1d, r!2d]", 1),
-    ENCODING_MAP(THUMB_LDRH_RRI5,     0x8800, 2, 0, 5, 3, 10, 6,
+    ENCODING_MAP(THUMB_LDRH_RRI5,     0x8800,
+                 BITBLT, 2, 0, BITBLT, 5, 3, BITBLT, 10, 6,
                  IS_TERTIARY_OP | CLOBBER_DEST,
                  "ldrh", "r!0d, [r!1d, #!2F]", 1),
-    ENCODING_MAP(THUMB_LDRH_RRR,      0x5a00, 2, 0, 5, 3, 8, 6,
+    ENCODING_MAP(THUMB_LDRH_RRR,      0x5a00,
+                 BITBLT, 2, 0, BITBLT, 5, 3, BITBLT, 8, 6,
                  IS_TERTIARY_OP | CLOBBER_DEST,
                  "ldrh", "r!0d, [r!1d, r!2d]", 1),
-    ENCODING_MAP(THUMB_LDRSB_RRR,     0x5600, 2, 0, 5, 3, 8, 6,
+    ENCODING_MAP(THUMB_LDRSB_RRR,     0x5600,
+                 BITBLT, 2, 0, BITBLT, 5, 3, BITBLT, 8, 6,
                  IS_TERTIARY_OP | CLOBBER_DEST,
                  "ldrsb", "r!0d, [r!1d, r!2d]", 1),
-    ENCODING_MAP(THUMB_LDRSH_RRR,     0x5e00, 2, 0, 5, 3, 8, 6,
+    ENCODING_MAP(THUMB_LDRSH_RRR,     0x5e00,
+                 BITBLT, 2, 0, BITBLT, 5, 3, BITBLT, 8, 6,
                  IS_TERTIARY_OP | CLOBBER_DEST,
                  "ldrsh", "r!0d, [r!1d, r!2d]", 1),
-    ENCODING_MAP(THUMB_LSL,           0x0000, 2, 0, 5, 3, 10, 6,
+    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),
-    ENCODING_MAP(THUMB_LSLV,          0x4080, 2, 0, 5, 3, -1, -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),
-    ENCODING_MAP(THUMB_LSR,           0x0800, 2, 0, 5, 3, 10, 6,
+    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),
-    ENCODING_MAP(THUMB_LSRV,          0x40c0, 2, 0, 5, 3, -1, -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),
-    ENCODING_MAP(THUMB_MOV_IMM,       0x2000, 10, 8, 7, 0, -1, -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),
-    ENCODING_MAP(THUMB_MOV_RR,        0x1c00, 2, 0, 5, 3, -1, -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),
-    ENCODING_MAP(THUMB_MOV_RR_H2H,    0x46c0, 2, 0, 5, 3, -1, -1,
+    ENCODING_MAP(THUMB_MOV_RR_H2H,    0x46c0,
+                 BITBLT, 2, 0, BITBLT, 5, 3, UNUSED, -1, -1,
                  IS_BINARY_OP | CLOBBER_DEST,
                  "mov", "r!0D, r!1D", 1),
-    ENCODING_MAP(THUMB_MOV_RR_H2L,    0x4640, 2, 0, 5, 3, -1, -1,
+    ENCODING_MAP(THUMB_MOV_RR_H2L,    0x4640,
+                 BITBLT, 2, 0, BITBLT, 5, 3, UNUSED, -1, -1,
                  IS_BINARY_OP | CLOBBER_DEST,
                  "mov", "r!0d, r!1D", 1),
-    ENCODING_MAP(THUMB_MOV_RR_L2H,    0x4680, 2, 0, 5, 3, -1, -1,
+    ENCODING_MAP(THUMB_MOV_RR_L2H,    0x4680,
+                 BITBLT, 2, 0, BITBLT, 5, 3, UNUSED, -1, -1,
                  IS_BINARY_OP | CLOBBER_DEST,
                  "mov", "r!0D, r!1d", 1),
-    ENCODING_MAP(THUMB_MUL,           0x4340, 2, 0, 5, 3, -1, -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),
-    ENCODING_MAP(THUMB_MVN,           0x43c0, 2, 0, 5, 3, -1, -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),
-    ENCODING_MAP(THUMB_NEG,           0x4240, 2, 0, 5, 3, -1, -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),
-    ENCODING_MAP(THUMB_ORR,           0x4300, 2, 0, 5, 3, -1, -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),
-    ENCODING_MAP(THUMB_POP,           0xbc00, 8, 0, -1, -1, -1, -1,
+    ENCODING_MAP(THUMB_POP,           0xbc00,
+                 BITBLT, 8, 0, UNUSED, -1, -1, UNUSED, -1, -1,
                  IS_UNARY_OP,
                  "pop", "<!0R>", 1),
-    ENCODING_MAP(THUMB_PUSH,          0xb400, 8, 0, -1, -1, -1, -1,
+    ENCODING_MAP(THUMB_PUSH,          0xb400,
+                 BITBLT, 8, 0, UNUSED, -1, -1, UNUSED, -1, -1,
                  IS_UNARY_OP,
                  "push", "<!0R>", 1),
-    ENCODING_MAP(THUMB_ROR,           0x41c0, 2, 0, 5, 3, -1, -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_SBC,           0x4180, 2, 0, 5, 3, -1, -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),
-    ENCODING_MAP(THUMB_STMIA,         0xc000, 10, 8, 7, 0, -1, -1,
+    ENCODING_MAP(THUMB_STMIA,         0xc000,
+                 BITBLT, 10, 8, BITBLT, 7, 0, UNUSED, -1, -1,
                  IS_BINARY_OP | CLOBBER_SRC1,
                  "stmia", "r!0d!!, <!1R>", 1),
-    ENCODING_MAP(THUMB_STR_RRI5,      0x6000, 2, 0, 5, 3, 10, 6,
+    ENCODING_MAP(THUMB_STR_RRI5,      0x6000,
+                 BITBLT, 2, 0, BITBLT, 5, 3, BITBLT, 10, 6,
                  IS_TERTIARY_OP,
                  "str", "r!0d, [r!1d, #!2E]", 1),
-    ENCODING_MAP(THUMB_STR_RRR,       0x5000, 2, 0, 5, 3, 8, 6,
+    ENCODING_MAP(THUMB_STR_RRR,       0x5000,
+                 BITBLT, 2, 0, BITBLT, 5, 3, BITBLT, 8, 6,
                  IS_TERTIARY_OP,
                  "str", "r!0d, [r!1d, r!2d]", 1),
-    ENCODING_MAP(THUMB_STR_SP_REL,    0x9000, 10, 8, 7, 0, -1, -1,
+    ENCODING_MAP(THUMB_STR_SP_REL,    0x9000,
+                 BITBLT, 10, 8, BITBLT, 7, 0, UNUSED, -1, -1,
                  IS_BINARY_OP,
                  "str", "r!0d, [sp, #!1E]", 1),
-    ENCODING_MAP(THUMB_STRB_RRI5,     0x7000, 2, 0, 5, 3, 10, 6,
+    ENCODING_MAP(THUMB_STRB_RRI5,     0x7000,
+                 BITBLT, 2, 0, BITBLT, 5, 3, BITBLT, 10, 6,
                  IS_TERTIARY_OP,
                  "strb", "r!0d, [r!1d, #!2d]", 1),
-    ENCODING_MAP(THUMB_STRB_RRR,      0x5400, 2, 0, 5, 3, 8, 6,
+    ENCODING_MAP(THUMB_STRB_RRR,      0x5400,
+                 BITBLT, 2, 0, BITBLT, 5, 3, BITBLT, 8, 6,
                  IS_TERTIARY_OP,
                  "strb", "r!0d, [r!1d, r!2d]", 1),
-    ENCODING_MAP(THUMB_STRH_RRI5,     0x8000, 2, 0, 5, 3, 10, 6,
+    ENCODING_MAP(THUMB_STRH_RRI5,     0x8000,
+                 BITBLT, 2, 0, BITBLT, 5, 3, BITBLT, 10, 6,
                  IS_TERTIARY_OP,
                  "strh", "r!0d, [r!1d, #!2F]", 1),
-    ENCODING_MAP(THUMB_STRH_RRR,      0x5200, 2, 0, 5, 3, 8, 6,
+    ENCODING_MAP(THUMB_STRH_RRR,      0x5200,
+                 BITBLT, 2, 0, BITBLT, 5, 3, BITBLT, 8, 6,
                  IS_TERTIARY_OP,
                  "strh", "r!0d, [r!1d, r!2d]", 1),
-    ENCODING_MAP(THUMB_SUB_RRI3,      0x1e00, 2, 0, 5, 3, 8, 6,
+    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),
-    ENCODING_MAP(THUMB_SUB_RI8,       0x3800, 10, 8, 7, 0, -1, -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),
-    ENCODING_MAP(THUMB_SUB_RRR,       0x1a00, 2, 0, 5, 3, 8, 6,
+    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),
-    ENCODING_MAP(THUMB_SUB_SPI7,      0xb080, 6, 0, -1, -1, -1, -1,
+    ENCODING_MAP(THUMB_SUB_SPI7,      0xb080,
+                 BITBLT, 6, 0, UNUSED, -1, -1, UNUSED, -1, -1,
                  IS_UNARY_OP | CLOBBER_DEST,
                  "sub", "sp, #!0d", 1),
-    ENCODING_MAP(THUMB_SWI,           0xdf00, 7, 0, -1, -1, -1, -1,
+    ENCODING_MAP(THUMB_SWI,           0xdf00,
+                 BITBLT, 7, 0, UNUSED, -1, -1, UNUSED, -1, -1,
                  IS_UNARY_OP | IS_BRANCH,
                  "swi", "!0d", 1),
-    ENCODING_MAP(THUMB_TST,           0x4200, 2, 0, 5, 3, -1, -1,
+    ENCODING_MAP(THUMB_TST,           0x4200,
+                 BITBLT, 2, 0, BITBLT, 5, 3, UNUSED, -1, -1,
                  IS_UNARY_OP,
                  "tst", "r!0d, r!1d", 1),
+    ENCODING_MAP(THUMB2_VLDRS,       0xed900a00,
+                 SFP, 22, 12, BITBLT, 19, 16, BITBLT, 7, 0,
+                 IS_TERTIARY_OP,
+                 "vldr", "s!0d, [r!1d, #!2E]", 2),
+    ENCODING_MAP(THUMB2_VLDRD,       0xed900b00,
+                 DFP, 22, 12, BITBLT, 19, 16, BITBLT, 7, 0,
+                 IS_TERTIARY_OP,
+                 "vldr", "d!0d, [r!1d, #!2E]", 2),
+    ENCODING_MAP(THUMB2_VMULS,        0xee200a00,
+                 SFP, 22, 12, SFP, 7, 16, SFP, 5, 0,
+                 IS_TERTIARY_OP,
+                 "vmuls", "s!0d, s!1d, s!2d", 2),
+    ENCODING_MAP(THUMB2_VMULD,        0xee200b00,
+                 DFP, 22, 12, DFP, 7, 16, DFP, 5, 0,
+                 IS_TERTIARY_OP,
+                 "vmuld", "d!0d, d!1d, d!2d", 2),
+    ENCODING_MAP(THUMB2_VSTRS,       0xed800a00,
+                 SFP, 22, 12, BITBLT, 19, 16, BITBLT, 7, 0,
+                 IS_TERTIARY_OP,
+                 "vstr", "s!0d, [r!1d, #!2E]", 2),
+    ENCODING_MAP(THUMB2_VSTRD,       0xed800b00,
+                 DFP, 22, 12, BITBLT, 19, 16, BITBLT, 7, 0,
+                 IS_TERTIARY_OP,
+                 "vstr", "d!0d, [r!1d, #!2E]", 2),
+    ENCODING_MAP(THUMB2_VSUBS,        0xee300a40,
+                 SFP, 22, 12, SFP, 7, 16, SFP, 5, 0,
+                 IS_TERTIARY_OP,
+                 "vsub", "s!0d, s!1d, s!2d", 2),
+    ENCODING_MAP(THUMB2_VSUBD,        0xee300b40,
+                 DFP, 22, 12, DFP, 7, 16, DFP, 5, 0,
+                 IS_TERTIARY_OP,
+                 "vsub", "d!0d, s!1d, s!2d", 2),
+    ENCODING_MAP(THUMB2_VADDS,        0xee300a00,
+                 SFP, 22, 12, SFP, 7, 16, SFP, 5, 0,
+                 IS_TERTIARY_OP,
+                 "vadd", "s!0d, s!1d, s!2d", 2),
+    ENCODING_MAP(THUMB2_VADDD,        0xee300b00,
+                 DFP, 22, 12, DFP, 7, 16, DFP, 5, 0,
+                 IS_TERTIARY_OP,
+                 "vadd", "d!0d, s!1d, s!2d", 2),
+    ENCODING_MAP(THUMB2_VDIVS,        0xee800a00,
+                 SFP, 22, 12, SFP, 7, 16, SFP, 5, 0,
+                 IS_TERTIARY_OP,
+                 "vdivs", "s!0d, s!1d, s!2d", 2),
+    ENCODING_MAP(THUMB2_VDIVD,        0xee800b00,
+                 DFP, 22, 12, DFP, 7, 16, DFP, 5, 0,
+                 IS_TERTIARY_OP,
+                 "vdivs", "s!0d, s!1d, s!2d", 2),
+    ENCODING_MAP(THUMB2_VCVTIF,       0xeeb80ac0,
+                 SFP, 22, 12, SFP, 5, 0, UNUSED, -1, -1,
+                 IS_BINARY_OP,
+                 "vcvf.f32", "s!0d, s!1d", 2),
+    ENCODING_MAP(THUMB2_VCVTID,       0xeeb80bc0,
+                 DFP, 22, 12, SFP, 5, 0, UNUSED, -1, -1,
+                 IS_BINARY_OP,
+                 "vcvf.f64", "s!0d, s!1d", 2),
+    ENCODING_MAP(THUMB2_VCVTFI,       0xeebd0ac0,
+                 SFP, 22, 12, SFP, 5, 0, UNUSED, -1, -1,
+                 IS_BINARY_OP,
+                 "vcvf.s32.f32", "s!0d, s!1d", 2),
+    ENCODING_MAP(THUMB2_VCVTDI,       0xeebd0bc0,
+                 SFP, 22, 12, DFP, 5, 0, UNUSED, -1, -1,
+                 IS_BINARY_OP,
+                 "vcvf.s32.f64", "s!0d, s!1d", 2),
+    ENCODING_MAP(THUMB2_VCVTFD,       0xeeb70ac0,
+                 DFP, 22, 12, SFP, 5, 0, UNUSED, -1, -1,
+                 IS_BINARY_OP,
+                 "vcvf.f64.f32", "s!0d, s!1d", 2),
+    ENCODING_MAP(THUMB2_VCVTDF,       0xeeb70bc0,
+                 SFP, 22, 12, DFP, 5, 0, UNUSED, -1, -1,
+                 IS_BINARY_OP,
+                 "vcvf.f32.f64", "s!0d, s!1d", 2),
 };
 
 #define PADDING_MOV_R0_R0               0x1C00
@@ -387,18 +535,50 @@
         }
 
         ArmEncodingMap *encoder = &EncodingMap[lir->opCode];
-        short bits = encoder->skeleton;
+        u4 bits = encoder->skeleton;
         int i;
         for (i = 0; i < 3; i++) {
-            short value;
-            if (encoder->fieldLoc[i].end != -1) {
-                value = (lir->operands[i] << encoder->fieldLoc[i].start) &
-                        ((1 << (encoder->fieldLoc[i].end + 1)) - 1);
-                bits |= value;
-
+            u4 value;
+            switch(encoder->fieldLoc[i].kind) {
+                case UNUSED:
+                    break;
+                case BITBLT:
+                    value = (lir->operands[i] << encoder->fieldLoc[i].start) &
+                            ((1 << (encoder->fieldLoc[i].end + 1)) - 1);
+                    bits |= value;
+                    break;
+                case DFP:
+                    /* Snag the 1-bit slice and position it */
+                    value = ((lir->operands[i] & 0x10) >> 4) <<
+                            encoder->fieldLoc[i].end;
+                    /* Extract and position the 4-bit slice */
+                    value |= (lir->operands[i] & 0x0f) <<
+                            encoder->fieldLoc[i].start;
+                    bits |= value;
+                    break;
+                case SFP:
+                    /* Snag the 1-bit slice and position it */
+                    value = (lir->operands[i] & 0x1) <<
+                            encoder->fieldLoc[i].end;
+                    /* Extract and position the 4-bit slice */
+                    value |= ((lir->operands[i] & 0x1e) >> 1) <<
+                            encoder->fieldLoc[i].start;
+                    bits |= value;
+                    break;
+                case IMMSHIFT8:
+                case IMM12:
+                    value = ((lir->operands[i] & 0x800) >> 11) << 26;
+                    value |= ((lir->operands[i] & 0x700) >> 8) << 12;
+                    value |= lir->operands[i] & 0x0ff;
+                    break;
+                default:
+                    assert(0);
             }
         }
-        *bufferAddr++ = bits;
+        if (encoder->size == 2) {
+            *bufferAddr++ = (bits >> 16) & 0xffff;
+        }
+        *bufferAddr++ = bits & 0xffff;
     }
     return false;
 }
@@ -459,7 +639,8 @@
          armLIR = NEXT_LIR(armLIR)) {
         armLIR->generic.offset = offset;
         if (armLIR->opCode >= 0 && !armLIR->isNop) {
-            offset += 2;
+            armLIR->size = EncodingMap[armLIR->opCode].size * 2;
+            offset += armLIR->size;
         } else if (armLIR->opCode == ARM_PSEUDO_ALIGN4) {
             if (offset & 0x2) {
                 offset += 2;