Model resource usage for each Thumb/Thumb2 instrution.

This is an mid-point checkin to avoid future merge nightmare for the register
allocator work.
diff --git a/vm/Globals.h b/vm/Globals.h
index c94a578..23b7497 100644
--- a/vm/Globals.h
+++ b/vm/Globals.h
@@ -748,6 +748,9 @@
     /* Flag to count trace execution */
     bool profile;
 
+    /* Vector to disable selected optimizations */
+    int disableOpt;
+
     /* Table to track the overall and trace statistics of hot methods */
     HashTable*  methodStatsTable;
 
diff --git a/vm/Init.c b/vm/Init.c
index dcbdfb7..0710a55 100644
--- a/vm/Init.c
+++ b/vm/Init.c
@@ -120,6 +120,7 @@
                        "(eg Ljava/lang/String\\;replace)\n");
     dvmFprintf(stderr, "  -Xjitverbose\n");
     dvmFprintf(stderr, "  -Xjitprofile\n");
+    dvmFprintf(stderr, "  -Xjitdisableopt\n");
 #endif
     dvmFprintf(stderr, "\n");
     dvmFprintf(stderr, "Configured with:"
@@ -910,6 +911,8 @@
           gDvmJit.printMe = true;
         } else if (strncmp(argv[i], "-Xjitprofile", 12) == 0) {
           gDvmJit.profile = true;
+        } else if (strncmp(argv[i], "-Xjitdisableopt:", 16) == 0) {
+          sscanf(argv[i] + 16, "%x", &gDvmJit.disableOpt);
 #endif
 
         } else if (strncmp(argv[i], "-Xdeadlockpredict:", 18) == 0) {
diff --git a/vm/compiler/Compiler.c b/vm/compiler/Compiler.c
index 203a080..47881ca 100644
--- a/vm/compiler/Compiler.c
+++ b/vm/compiler/Compiler.c
@@ -21,7 +21,6 @@
 #include "interp/Jit.h"
 #include "CompilerInternals.h"
 
-
 static inline bool workQueueLength(void)
 {
     return gDvmJit.compilerQueueLength;
@@ -228,6 +227,11 @@
     /* Track method-level compilation statistics */
     gDvmJit.methodStatsTable =  dvmHashTableCreate(32, NULL);
 
+    /*
+     * FIXME - temporarily disable optimizations for this intermediate checkin
+     */
+    gDvmJit.disableOpt = 0x3;
+
     dvmUnlockMutex(&gDvmJit.compilerLock);
 
     return true;
diff --git a/vm/compiler/CompilerIR.h b/vm/compiler/CompilerIR.h
index 948f3e7..d5f60b6 100644
--- a/vm/compiler/CompilerIR.h
+++ b/vm/compiler/CompilerIR.h
@@ -152,6 +152,8 @@
 
 void dvmCompilerInsertLIRBefore(LIR *currentLIR, LIR *newLIR);
 
+void dvmCompilerInsertLIRAfter(LIR *currentLIR, LIR *newLIR);
+
 /* Debug Utilities */
 void dvmCompilerDumpCompilationUnit(CompilationUnit *cUnit);
 
diff --git a/vm/compiler/IntermediateRep.c b/vm/compiler/IntermediateRep.c
index a8bfda0..018d890 100644
--- a/vm/compiler/IntermediateRep.c
+++ b/vm/compiler/IntermediateRep.c
@@ -90,3 +90,17 @@
     newLIR->next = currentLIR;
     currentLIR->prev = newLIR;
 }
+
+/*
+ * Insert an LIR instruction after the current instruction, which cannot be the
+ * first instruction.
+ *
+ * currentLIR -> newLIR -> oldNext
+ */
+void dvmCompilerInsertLIRAfter(LIR *currentLIR, LIR *newLIR)
+{
+    newLIR->prev = currentLIR;
+    newLIR->next = currentLIR->next;
+    currentLIR->next = newLIR;
+    newLIR->next->prev = newLIR;
+}
diff --git a/vm/compiler/Utility.c b/vm/compiler/Utility.c
index 1ad1e27..cbfea16 100644
--- a/vm/compiler/Utility.c
+++ b/vm/compiler/Utility.c
@@ -203,8 +203,10 @@
          gDvmJit.compilerMaxQueued);
     dvmJitStats();
     dvmCompilerArchDump();
-    dvmHashForeach(gDvmJit.methodStatsTable, dumpMethodStats,
-                   &totalMethodStats);
+    if (gDvmJit.methodStatsTable) {
+        dvmHashForeach(gDvmJit.methodStatsTable, dumpMethodStats,
+                       &totalMethodStats);
+    }
     LOGD("Code size stats: %d/%d (compiled/total Dalvik), %d (native)",
          totalMethodStats.compiledDalvikSize,
          totalMethodStats.dalvikSize,
diff --git a/vm/compiler/codegen/Optimizer.h b/vm/compiler/codegen/Optimizer.h
index 432b368..0931df3 100644
--- a/vm/compiler/codegen/Optimizer.h
+++ b/vm/compiler/codegen/Optimizer.h
@@ -19,6 +19,15 @@
 
 #include "Dalvik.h"
 
+/*
+ * If the corresponding bit is set in gDvmJit.disableOpt, the selected
+ * optimization will be suppressed.
+ */
+typedef enum optControlVector {
+    kLoadStoreElimination = 0,
+    kLoadHoisting,
+} optControlVector;
+
 /* Forward declarations */
 struct CompilationUnit;
 struct LIR;
diff --git a/vm/compiler/codegen/arm/ArchUtility.c b/vm/compiler/codegen/arm/ArchUtility.c
index ab46b44..551e1f7 100644
--- a/vm/compiler/codegen/arm/ArchUtility.c
+++ b/vm/compiler/codegen/arm/ArchUtility.c
@@ -204,6 +204,9 @@
     u2 *cPtr = (u2*)baseAddr;
     /* Handle pseudo-ops individually, and all regular insns as a group */
     switch(lir->opCode) {
+        case ARM_PSEUDO_IT_BOTTOM:
+            LOGD("-------- IT_Bottom");
+            break;
         case ARM_PSEUDO_EXTENDED_MIR:
             /* intentional fallthrough */
         case ARM_PSEUDO_SSA_REP:
@@ -283,7 +286,8 @@
     for (lirInsn = cUnit->wordList; lirInsn; lirInsn = lirInsn->next) {
         armLIR = (ArmLIR *) lirInsn;
         LOGD("%p (%04x): .word (0x%x)\n",
-             (char*)cUnit->baseAddr + armLIR->generic.offset, armLIR->generic.offset,
+             (char*)cUnit->baseAddr + armLIR->generic.offset,
+             armLIR->generic.offset,
              armLIR->operands[0]);
     }
 }
diff --git a/vm/compiler/codegen/arm/ArmLIR.h b/vm/compiler/codegen/arm/ArmLIR.h
index be793d6..20fb6bf 100644
--- a/vm/compiler/codegen/arm/ArmLIR.h
+++ b/vm/compiler/codegen/arm/ArmLIR.h
@@ -72,13 +72,33 @@
 #define SINGLEREG(x) (FPREG(x) && !DOUBLEREG(x))
 /* Mask to strip off fp flags */
 #define FP_REG_MASK (FP_REG_OFFSET-1)
-/* Mask to convert high reg to low for Thumb */
-#define THUMB_REG_MASK 0x7
 /* non-existent Dalvik register */
 #define vNone   (-1)
 /* non-existant physical register */
 #define rNone   (-1)
 
+typedef enum ResourceEncodingPos {
+    kGPReg0     = 0,
+    kRegSP      = 13,
+    kRegLR      = 14,
+    kRegPC      = 15,
+    kFPReg0     = 16,
+    kITBlock    = 48,
+    kCCode      = 49,
+    kFPStatus   = 50,
+} ResourceEncodingPos;
+
+#define ENCODE_GP_REG(N)        (1ULL << N)
+#define ENCODE_REG_LIST(N)      ((u8) N)
+#define ENCODE_REG_SP           (1ULL << kRegSP)
+#define ENCODE_REG_LR           (1ULL << kRegLR)
+#define ENCODE_REG_PC           (1ULL << kRegPC)
+#define ENCODE_SFP_REG(N)       (1ULL << (N - FP_REG_OFFSET + kFPReg0))
+#define ENCODE_DFP_REG(N)       (3ULL << (((N - FP_DOUBLE) << 1) + kFPReg0))
+#define ENCODE_IT_BLOCK         (1ULL << kITBlock)
+#define ENCODE_CCODE            (1ULL << kCCode)
+#define ENCODE_FP_STATUS        (1ULL << kFPStatus)
+
 typedef enum OpSize {
     WORD,
     LONG,
@@ -220,6 +240,7 @@
  * Assemble.c.
  */
 typedef enum ArmOpCode {
+    ARM_PSEUDO_IT_BOTTOM = -17,
     ARM_PSEUDO_EXTENDED_MIR = -16,
     ARM_PSEUDO_SSA_REP = -15,
     ARM_PSEUDO_ENTRY_BLOCK = -14,
@@ -238,7 +259,7 @@
     ARM_PSEUDO_NORMAL_BLOCK_LABEL = -1,
     /************************************************************************/
     ARM_16BIT_DATA,       /* DATA   [0] rd[15..0] */
-    THUMB_ADC,            /* adc     [0100000101] rm[5..3] rd[2..0] */
+    THUMB_ADC_RR,         /* adc     [0100000101] rm[5..3] rd[2..0] */
     THUMB_ADD_RRI3,       /* add(1)  [0001110] imm_3[8..6] rn[5..3] rd[2..0]*/
     THUMB_ADD_RI8,        /* add(2)  [00110] rd[10..8] imm_8[7..0] */
     THUMB_ADD_RRR,        /* add(3)  [0001100] rm[8..6] rn[5..3] rd[2..0] */
@@ -249,11 +270,11 @@
     THUMB_ADD_SP_REL,     /* add(6)  [10101] rd[10..8] imm_8[7..0] */
     THUMB_ADD_SPI7,       /* add(7)  [101100000] imm_7[6..0] */
     THUMB_AND_RR,         /* and     [0100000000] rm[5..3] rd[2..0] */
-    THUMB_ASR,            /* asr(1)  [00010] imm_5[10..6] rm[5..3] rd[2..0] */
-    THUMB_ASRV,           /* asr(2)  [0100000100] rs[5..3] rd[2..0] */
+    THUMB_ASR_RRI5,       /* asr(1)  [00010] imm_5[10..6] rm[5..3] rd[2..0] */
+    THUMB_ASR_RR,         /* asr(2)  [0100000100] rs[5..3] rd[2..0] */
     THUMB_B_COND,         /* b(1)    [1101] cond[11..8] offset_8[7..0] */
     THUMB_B_UNCOND,       /* b(2)    [11100] offset_11[10..0] */
-    THUMB_BIC,            /* bic     [0100001110] rm[5..3] rd[2..0] */
+    THUMB_BIC_RR,         /* bic     [0100001110] rm[5..3] rd[2..0] */
     THUMB_BKPT,           /* bkpt    [10111110] imm_8[7..0] */
     THUMB_BLX_1,          /* blx(1)  [111] H[10] offset_11[10..0] */
     THUMB_BLX_2,          /* blx(1)  [111] H[01] offset_11[10..0] */
@@ -261,13 +282,13 @@
     THUMB_BL_2,           /* blx(1)  [111] H[11] offset_11[10..0] */
     THUMB_BLX_R,          /* blx(2)  [010001111] rm[6..3] [000] */
     THUMB_BX,             /* bx      [010001110] H2[6..6] rm[5..3] SBZ[000] */
-    THUMB_CMN,            /* cmn     [0100001011] rm[5..3] rd[2..0] */
+    THUMB_CMN_RR,         /* cmn     [0100001011] rm[5..3] rd[2..0] */
     THUMB_CMP_RI8,        /* cmp(1)  [00101] rn[10..8] imm_8[7..0] */
     THUMB_CMP_RR,         /* cmp(2)  [0100001010] rm[5..3] rd[2..0] */
     THUMB_CMP_LH,         /* cmp(3)  [01000101] H12[01] rm[5..3] rd[2..0] */
     THUMB_CMP_HL,         /* cmp(3)  [01000110] H12[10] rm[5..3] rd[2..0] */
     THUMB_CMP_HH,         /* cmp(3)  [01000111] H12[11] rm[5..3] rd[2..0] */
-    THUMB_EOR,            /* eor     [0100000001] rm[5..3] rd[2..0] */
+    THUMB_EOR_RR,         /* eor     [0100000001] rm[5..3] rd[2..0] */
     THUMB_LDMIA,          /* ldmia   [11001] rn[10..8] reglist [7..0] */
     THUMB_LDR_RRI5,       /* ldr(1)  [01101] imm_5[10..6] rn[5..3] rd[2..0] */
     THUMB_LDR_RRR,        /* ldr(2)  [0101100] rm[8..6] rn[5..3] rd[2..0] */
@@ -279,10 +300,10 @@
     THUMB_LDRH_RRR,       /* ldrh(2) [0101101] rm[8..6] rn[5..3] rd[2..0] */
     THUMB_LDRSB_RRR,      /* ldrsb   [0101011] rm[8..6] rn[5..3] rd[2..0] */
     THUMB_LDRSH_RRR,      /* ldrsh   [0101111] rm[8..6] rn[5..3] rd[2..0] */
-    THUMB_LSL,            /* lsl(1)  [00000] imm_5[10..6] rm[5..3] rd[2..0] */
-    THUMB_LSLV,           /* lsl(2)  [0100000010] rs[5..3] rd[2..0] */
-    THUMB_LSR,            /* lsr(1)  [00001] imm_5[10..6] rm[5..3] rd[2..0] */
-    THUMB_LSRV,           /* lsr(2)  [0100000011] rs[5..3] rd[2..0] */
+    THUMB_LSL_RRI5,       /* lsl(1)  [00000] imm_5[10..6] rm[5..3] rd[2..0] */
+    THUMB_LSL_RR,         /* lsl(2)  [0100000010] rs[5..3] rd[2..0] */
+    THUMB_LSR_RRI5,       /* lsr(1)  [00001] imm_5[10..6] rm[5..3] rd[2..0] */
+    THUMB_LSR_RR,         /* lsr(2)  [0100000011] rs[5..3] rd[2..0] */
     THUMB_MOV_IMM,        /* mov(1)  [00100] rd[10..8] imm_8[7..0] */
     THUMB_MOV_RR,         /* mov(2)  [0001110000] rn[5..3] rd[2..0] */
     THUMB_MOV_RR_H2H,     /* mov(3)  [01000111] H12[11] rm[5..3] rd[2..0] */
@@ -294,7 +315,7 @@
     THUMB_ORR,            /* orr     [0100001100] rm[5..3] rd[2..0] */
     THUMB_POP,            /* pop     [1011110] r[8..8] rl[7..0] */
     THUMB_PUSH,           /* push    [1011010] r[8..8] rl[7..0] */
-    THUMB_RORV,           /* ror     [0100000111] rs[5..3] rd[2..0] */
+    THUMB_ROR_RR,         /* ror     [0100000111] rs[5..3] rd[2..0] */
     THUMB_SBC,            /* sbc     [0100000110] rm[5..3] rd[2..0] */
     THUMB_STMIA,          /* stmia   [11000] rn[10..8] reglist [7.. 0] */
     THUMB_STR_RRI5,       /* str(1)  [01100] imm_5[10..6] rn[5..3] rd[2..0] */
@@ -447,13 +468,13 @@
                                    [0000] rm[3..0] */
     THUMB2_TST_RR,        /* tst [111010100001] rn[19..16] [0000] [1111]
                                    [0000] rm[3..0] */
-    THUMB2_LSLV_RRR,      /* lsl [111110100000] rn[19..16] [1111] rd[11..8]
+    THUMB2_LSL_RRR,       /* lsl [111110100000] rn[19..16] [1111] rd[11..8]
                                    [0000] rm[3..0] */
-    THUMB2_LSRV_RRR,      /* lsr [111110100010] rn[19..16] [1111] rd[11..8]
+    THUMB2_LSR_RRR,       /* lsr [111110100010] rn[19..16] [1111] rd[11..8]
                                    [0000] rm[3..0] */
-    THUMB2_ASRV_RRR,      /* asr [111110100100] rn[19..16] [1111] rd[11..8]
+    THUMB2_ASR_RRR,       /* asr [111110100100] rn[19..16] [1111] rd[11..8]
                                    [0000] rm[3..0] */
-    THUMB2_RORV_RRR,      /* ror [111110100110] rn[19..16] [1111] rd[11..8]
+    THUMB2_ROR_RRR,       /* ror [111110100110] rn[19..16] [1111] rd[11..8]
                                    [0000] rm[3..0] */
     THUMB2_LSL_RRI5,      /* lsl [11101010010011110] imm[14.12] rd[11..8]
                                    [00] rm[3..0] */
@@ -507,18 +528,58 @@
 
 /* Bit flags describing the behavior of each native opcode */
 typedef enum ArmOpFeatureFlags {
-    IS_BRANCH =           1 << 1,
-    CLOBBER_DEST =        1 << 2,
-    CLOBBER_SRC1 =        1 << 3,
-    NO_OPERAND =          1 << 4,
-    IS_UNARY_OP =         1 << 5,
-    IS_BINARY_OP =        1 << 6,
-    IS_TERTIARY_OP =      1 << 7,
-    IS_QUAD_OP =          1 << 8,
-    SETS_CCODES =         1 << 9,
-    USES_CCODES =         1 << 10,
+    kIsBranch = 0,
+    kRegDef0,
+    kRegDef1,
+    kRegDefSP,
+    kRegDefList0,
+    kRegDefList1,
+    kRegUse0,
+    kRegUse1,
+    kRegUse2,
+    kRegUseSP,
+    kRegUsePC,
+    kRegUseList0,
+    kRegUseList1,
+    kNoOperand,
+    kIsUnaryOp,
+    kIsBinaryOp,
+    kIsTertiaryOp,
+    kIsQuadOp,
+    kIsIT,
+    kSetsCCodes,
+    kUsesCCodes,
 } ArmOpFeatureFlags;
 
+#define IS_BRANCH       (1 << kIsBranch)
+#define REG_DEF0        (1 << kRegDef0)
+#define REG_DEF1        (1 << kRegDef1)
+#define REG_DEF_SP      (1 << kRegDefSP)
+#define REG_DEF_LIST0   (1 << kRegDefList0)
+#define REG_DEF_LIST1   (1 << kRegDefList1)
+#define REG_USE0        (1 << kRegUse0)
+#define REG_USE1        (1 << kRegUse1)
+#define REG_USE2        (1 << kRegUse2)
+#define REG_USE_PC      (1 << kRegUsePC)
+#define REG_USE_SP      (1 << kRegUseSP)
+#define REG_USE_LIST0   (1 << kRegUseList0)
+#define REG_USE_LIST1   (1 << kRegUseList1)
+#define NO_OPERAND      (1 << kNoOperand)
+#define IS_UNARY_OP     (1 << kIsUnaryOp)
+#define IS_BINARY_OP    (1 << kIsBinaryOp)
+#define IS_TERTIARY_OP  (1 << kIsTertiaryOp)
+#define IS_QUAD_OP      (1 << kIsQuadOp)
+#define IS_IT           (1 << kIsIT)
+#define SETS_CCODES     (1 << kSetsCCodes)
+#define USES_CCODES     (1 << kUsesCCodes)
+
+/* Common combo register usage patterns */
+#define REG_DEF0_USE1   (REG_DEF0 | REG_USE1)
+#define REG_DEF0_USE01  (REG_DEF0 | REG_USE0 | REG_USE1)
+#define REG_DEF0_USE12  (REG_DEF0 | REG_USE1 | REG_USE2)
+#define REG_USE01       (REG_USE0 | REG_USE1)
+#define REG_USE012      (REG_USE0 | REG_USE1 | REG_USE2)
+
 /* Instruction assembly fieldLoc kind */
 typedef enum ArmEncodingKind {
     UNUSED,
@@ -556,7 +617,16 @@
 /*
  * Each instance of this struct holds a pseudo or real LIR instruction:
  * - pesudo ones (eg labels and marks) and will be discarded by the assembler.
- * - real ones will e assembled into Thumb instructions.
+ * - real ones will be assembled into Thumb instructions.
+ *
+ * Machine resources are encoded into a 64-bit vector, where the encodings are
+ * as following:
+ * - [ 0..15]: general purpose registers including PC, SP, and LR
+ * - [16..47]: floating-point registers where d0 is expanded to s[01] and s0
+ *   starts at bit 16
+ * - [48]: IT block
+ * - [49]: integer condition code
+ * - [50]: floatint-point status word
  */
 typedef struct ArmLIR {
     LIR generic;
@@ -565,6 +635,8 @@
     bool isNop;         // LIR is optimized away
     int age;            // default is 0, set lazily by the optimizer
     int size;           // 16-bit unit size (1 for thumb, 1 or 2 for thumb2)
+    u8 useMask;         // Resource mask for use
+    u8 defMask;         // Resource mask for def
 } ArmLIR;
 
 /* Chain cell for predicted method invocation */
diff --git a/vm/compiler/codegen/arm/Assemble.c b/vm/compiler/codegen/arm/Assemble.c
index 6293fb2..4d7dadc 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, \
-                     k3, k3s, k3e, operands, name, fmt, size) \
+                     k3, k3s, k3e, flags, name, fmt, size) \
         {skeleton, {{k0, ds, de}, {k1, s1s, s1e}, {k2, s2s, s2e}, \
-                    {k3, k3s, k3e}}, opcode, operands, name, fmt, size}
+                    {k3, k3s, k3e}}, opcode, flags, 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
@@ -79,57 +79,57 @@
                  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,
+    ENCODING_MAP(THUMB_ADC_RR,        0x4140,
                  BITBLT, 2, 0, BITBLT, 5, 3, UNUSED, -1, -1, UNUSED, -1, -1,
-                 IS_BINARY_OP | CLOBBER_DEST | SETS_CCODES | USES_CCODES,
+                 IS_BINARY_OP | REG_DEF0_USE01 | 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, UNUSED, -1, -1,
-                 IS_TERTIARY_OP | CLOBBER_DEST | SETS_CCODES,
+                 IS_TERTIARY_OP | REG_DEF0_USE1 | SETS_CCODES,
                  "adds", "r!0d, r!1d, #!2d", 1),
     ENCODING_MAP(THUMB_ADD_RI8,       0x3000,
                  BITBLT, 10, 8, BITBLT, 7, 0, UNUSED, -1, -1, UNUSED, -1, -1,
-                 IS_BINARY_OP | CLOBBER_DEST | SETS_CCODES,
+                 IS_BINARY_OP | REG_DEF0 | REG_USE0 | SETS_CCODES,
                  "adds", "r!0d, r!0d, #!1d", 1),
     ENCODING_MAP(THUMB_ADD_RRR,       0x1800,
                  BITBLT, 2, 0, BITBLT, 5, 3, BITBLT, 8, 6, UNUSED, -1, -1,
-                 IS_TERTIARY_OP | CLOBBER_DEST | SETS_CCODES,
+                 IS_TERTIARY_OP | REG_DEF0_USE12 | 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, UNUSED, -1, -1,
-                 IS_BINARY_OP | CLOBBER_DEST,
+                 IS_BINARY_OP | REG_DEF0_USE01,
                  "add", "r!0d, r!1d", 1),
     ENCODING_MAP(THUMB_ADD_RR_HL,     0x4480,
                  BITBLT, 2, 0, BITBLT, 5, 3, UNUSED, -1, -1, UNUSED, -1, -1,
-                 IS_BINARY_OP | CLOBBER_DEST,
+                 IS_BINARY_OP | REG_DEF0_USE01,
                  "add", "r!0d, r!1d", 1),
     ENCODING_MAP(THUMB_ADD_RR_HH,     0x44c0,
                  BITBLT, 2, 0, BITBLT, 5, 3, UNUSED, -1, -1, UNUSED, -1, -1,
-                 IS_BINARY_OP | CLOBBER_DEST,
+                 IS_BINARY_OP | REG_DEF0_USE01,
                  "add", "r!0d, r!1d", 1),
     ENCODING_MAP(THUMB_ADD_PC_REL,    0xa000,
                  BITBLT, 10, 8, BITBLT, 7, 0, UNUSED, -1, -1, UNUSED, -1, -1,
-                 IS_TERTIARY_OP | CLOBBER_DEST,
+                 IS_TERTIARY_OP | IS_BRANCH,
                  "add", "r!0d, pc, #!1E", 1),
     ENCODING_MAP(THUMB_ADD_SP_REL,    0xa800,
                  BITBLT, 10, 8, UNUSED, -1, -1, BITBLT, 7, 0, UNUSED, -1, -1,
-                 IS_TERTIARY_OP | CLOBBER_DEST,
+                 IS_TERTIARY_OP | REG_DEF_SP | REG_USE_SP,
                  "add", "r!0d, sp, #!2E", 1),
     ENCODING_MAP(THUMB_ADD_SPI7,      0xb000,
                  BITBLT, 6, 0, UNUSED, -1, -1, UNUSED, -1, -1, UNUSED, -1, -1,
-                 IS_UNARY_OP | CLOBBER_DEST,
+                 IS_UNARY_OP | REG_DEF_SP | REG_USE_SP,
                  "add", "sp, #!0d*4", 1),
     ENCODING_MAP(THUMB_AND_RR,        0x4000,
                  BITBLT, 2, 0, BITBLT, 5, 3, UNUSED, -1, -1, UNUSED, -1, -1,
-                 IS_BINARY_OP | CLOBBER_DEST | SETS_CCODES,
+                 IS_BINARY_OP | REG_DEF0_USE01 | SETS_CCODES,
                  "ands", "r!0d, r!1d", 1),
-    ENCODING_MAP(THUMB_ASR,           0x1000,
+    ENCODING_MAP(THUMB_ASR_RRI5,      0x1000,
                  BITBLT, 2, 0, BITBLT, 5, 3, BITBLT, 10, 6, UNUSED, -1, -1,
-                 IS_TERTIARY_OP | CLOBBER_DEST | SETS_CCODES,
+                 IS_TERTIARY_OP | REG_DEF0_USE1 | SETS_CCODES,
                  "asrs", "r!0d, r!1d, #!2d", 1),
-    ENCODING_MAP(THUMB_ASRV,          0x4100,
+    ENCODING_MAP(THUMB_ASR_RR,        0x4100,
                  BITBLT, 2, 0, BITBLT, 5, 3, UNUSED, -1, -1, UNUSED, -1, -1,
-                 IS_BINARY_OP | CLOBBER_DEST | SETS_CCODES,
+                 IS_BINARY_OP | REG_DEF0_USE01 | SETS_CCODES,
                  "asrs", "r!0d, r!1d", 1),
     ENCODING_MAP(THUMB_B_COND,        0xd000,
                  BITBLT, 7, 0, BITBLT, 11, 8, UNUSED, -1, -1, UNUSED, -1, -1,
@@ -139,9 +139,9 @@
                  BITBLT, 10, 0, UNUSED, -1, -1, UNUSED, -1, -1, UNUSED, -1, -1,
                  NO_OPERAND | IS_BRANCH,
                  "b", "!0t", 1),
-    ENCODING_MAP(THUMB_BIC,           0x4380,
+    ENCODING_MAP(THUMB_BIC_RR,        0x4380,
                  BITBLT, 2, 0, BITBLT, 5, 3, UNUSED, -1, -1, UNUSED, -1, -1,
-                 IS_BINARY_OP | CLOBBER_DEST | SETS_CCODES,
+                 IS_BINARY_OP | REG_DEF0_USE01 | SETS_CCODES,
                  "bics", "r!0d, r!1d", 1),
     ENCODING_MAP(THUMB_BKPT,          0xbe00,
                  BITBLT, 7, 0, UNUSED, -1, -1, UNUSED, -1, -1, UNUSED, -1, -1,
@@ -171,193 +171,193 @@
                  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,
+    ENCODING_MAP(THUMB_CMN_RR,        0x42c0,
                  BITBLT, 2, 0, BITBLT, 5, 3, UNUSED, -1, -1, UNUSED, -1, -1,
-                 IS_BINARY_OP | SETS_CCODES,
+                 IS_BINARY_OP | REG_USE01 | SETS_CCODES,
                  "cmn", "r!0d, r!1d", 1),
     ENCODING_MAP(THUMB_CMP_RI8,       0x2800,
                  BITBLT, 10, 8, BITBLT, 7, 0, UNUSED, -1, -1, UNUSED, -1, -1,
-                 IS_BINARY_OP | SETS_CCODES,
+                 IS_BINARY_OP | REG_USE0 | SETS_CCODES,
                  "cmp", "r!0d, #!1d", 1),
     ENCODING_MAP(THUMB_CMP_RR,        0x4280,
                  BITBLT, 2, 0, BITBLT, 5, 3, UNUSED, -1, -1, UNUSED, -1, -1,
-                 IS_BINARY_OP | SETS_CCODES,
+                 IS_BINARY_OP | REG_USE01 | SETS_CCODES,
                  "cmp", "r!0d, r!1d", 1),
     ENCODING_MAP(THUMB_CMP_LH,        0x4540,
                  BITBLT, 2, 0, BITBLT, 5, 3, UNUSED, -1, -1, UNUSED, -1, -1,
-                 IS_BINARY_OP | SETS_CCODES,
+                 IS_BINARY_OP | REG_USE01 | SETS_CCODES,
                  "cmp", "r!0d, r!1D", 1),
     ENCODING_MAP(THUMB_CMP_HL,        0x4580,
                  BITBLT, 2, 0, BITBLT, 5, 3, UNUSED, -1, -1, UNUSED, -1, -1,
-                 IS_BINARY_OP | SETS_CCODES,
+                 IS_BINARY_OP | REG_USE01 | SETS_CCODES,
                  "cmp", "r!0D, r!1d", 1),
     ENCODING_MAP(THUMB_CMP_HH,        0x45c0,
                  BITBLT, 2, 0, BITBLT, 5, 3, UNUSED, -1, -1, UNUSED, -1, -1,
-                 IS_BINARY_OP | SETS_CCODES,
+                 IS_BINARY_OP | REG_USE01 | SETS_CCODES,
                  "cmp", "r!0D, r!1D", 1),
-    ENCODING_MAP(THUMB_EOR,           0x4040,
+    ENCODING_MAP(THUMB_EOR_RR,        0x4040,
                  BITBLT, 2, 0, BITBLT, 5, 3, UNUSED, -1, -1, UNUSED, -1, -1,
-                 IS_BINARY_OP | CLOBBER_DEST | SETS_CCODES,
+                 IS_BINARY_OP | REG_DEF0_USE01 | SETS_CCODES,
                  "eors", "r!0d, r!1d", 1),
     ENCODING_MAP(THUMB_LDMIA,         0xc800,
                  BITBLT, 10, 8, BITBLT, 7, 0, UNUSED, -1, -1, UNUSED, -1, -1,
-                 IS_BINARY_OP | CLOBBER_DEST | CLOBBER_SRC1,
+                 IS_BINARY_OP | REG_DEF0 | REG_USE0 | REG_DEF_LIST1,
                  "ldmia", "r!0d!!, <!1R>", 1),
     ENCODING_MAP(THUMB_LDR_RRI5,      0x6800,
                  BITBLT, 2, 0, BITBLT, 5, 3, BITBLT, 10, 6, UNUSED, -1, -1,
-                 IS_TERTIARY_OP | CLOBBER_DEST,
+                 IS_TERTIARY_OP | REG_DEF0_USE1,
                  "ldr", "r!0d, [r!1d, #!2E]", 1),
     ENCODING_MAP(THUMB_LDR_RRR,       0x5800,
                  BITBLT, 2, 0, BITBLT, 5, 3, BITBLT, 8, 6, UNUSED, -1, -1,
-                 IS_TERTIARY_OP | CLOBBER_DEST,
+                 IS_TERTIARY_OP | REG_DEF0_USE12,
                  "ldr", "r!0d, [r!1d, r!2d]", 1),
     ENCODING_MAP(THUMB_LDR_PC_REL,    0x4800,
                  BITBLT, 10, 8, BITBLT, 7, 0, UNUSED, -1, -1, UNUSED, -1, -1,
-                 IS_TERTIARY_OP | CLOBBER_DEST,
+                 IS_TERTIARY_OP | REG_DEF0 | REG_USE_PC,
                  "ldr", "r!0d, [pc, #!1E]", 1),
     ENCODING_MAP(THUMB_LDR_SP_REL,    0x9800,
                  BITBLT, 10, 8, UNUSED, -1, -1, BITBLT, 7, 0, UNUSED, -1, -1,
-                 IS_TERTIARY_OP | CLOBBER_DEST,
+                 IS_TERTIARY_OP | REG_DEF0 | REG_USE_SP,
                  "ldr", "r!0d, [sp, #!2E]", 1),
     ENCODING_MAP(THUMB_LDRB_RRI5,     0x7800,
                  BITBLT, 2, 0, BITBLT, 5, 3, BITBLT, 10, 6, UNUSED, -1, -1,
-                 IS_TERTIARY_OP | CLOBBER_DEST,
+                 IS_TERTIARY_OP | REG_DEF0_USE1,
                  "ldrb", "r!0d, [r!1d, #2d]", 1),
     ENCODING_MAP(THUMB_LDRB_RRR,      0x5c00,
                  BITBLT, 2, 0, BITBLT, 5, 3, BITBLT, 8, 6, UNUSED, -1, -1,
-                 IS_TERTIARY_OP | CLOBBER_DEST,
+                 IS_TERTIARY_OP | REG_DEF0_USE12,
                  "ldrb", "r!0d, [r!1d, r!2d]", 1),
     ENCODING_MAP(THUMB_LDRH_RRI5,     0x8800,
                  BITBLT, 2, 0, BITBLT, 5, 3, BITBLT, 10, 6, UNUSED, -1, -1,
-                 IS_TERTIARY_OP | CLOBBER_DEST,
+                 IS_TERTIARY_OP | REG_DEF0_USE1,
                  "ldrh", "r!0d, [r!1d, #!2F]", 1),
     ENCODING_MAP(THUMB_LDRH_RRR,      0x5a00,
                  BITBLT, 2, 0, BITBLT, 5, 3, BITBLT, 8, 6, UNUSED, -1, -1,
-                 IS_TERTIARY_OP | CLOBBER_DEST,
+                 IS_TERTIARY_OP | REG_DEF0_USE12,
                  "ldrh", "r!0d, [r!1d, r!2d]", 1),
     ENCODING_MAP(THUMB_LDRSB_RRR,     0x5600,
                  BITBLT, 2, 0, BITBLT, 5, 3, BITBLT, 8, 6, UNUSED, -1, -1,
-                 IS_TERTIARY_OP | CLOBBER_DEST,
+                 IS_TERTIARY_OP | REG_DEF0_USE12,
                  "ldrsb", "r!0d, [r!1d, r!2d]", 1),
     ENCODING_MAP(THUMB_LDRSH_RRR,     0x5e00,
                  BITBLT, 2, 0, BITBLT, 5, 3, BITBLT, 8, 6, UNUSED, -1, -1,
-                 IS_TERTIARY_OP | CLOBBER_DEST,
+                 IS_TERTIARY_OP | REG_DEF0_USE12,
                  "ldrsh", "r!0d, [r!1d, r!2d]", 1),
-    ENCODING_MAP(THUMB_LSL,           0x0000,
+    ENCODING_MAP(THUMB_LSL_RRI5,      0x0000,
                  BITBLT, 2, 0, BITBLT, 5, 3, BITBLT, 10, 6, UNUSED, -1, -1,
-                 IS_TERTIARY_OP | CLOBBER_DEST | SETS_CCODES,
+                 IS_TERTIARY_OP | REG_DEF0_USE1 | SETS_CCODES,
                  "lsls", "r!0d, r!1d, #!2d", 1),
-    ENCODING_MAP(THUMB_LSLV,          0x4080,
+    ENCODING_MAP(THUMB_LSL_RR,        0x4080,
                  BITBLT, 2, 0, BITBLT, 5, 3, UNUSED, -1, -1, UNUSED, -1, -1,
-                 IS_BINARY_OP | CLOBBER_DEST | SETS_CCODES,
+                 IS_BINARY_OP | REG_DEF0_USE01 | SETS_CCODES,
                  "lsls", "r!0d, r!1d", 1),
-    ENCODING_MAP(THUMB_LSR,           0x0800,
+    ENCODING_MAP(THUMB_LSR_RRI5,      0x0800,
                  BITBLT, 2, 0, BITBLT, 5, 3, BITBLT, 10, 6, UNUSED, -1, -1,
-                 IS_TERTIARY_OP | CLOBBER_DEST | SETS_CCODES,
+                 IS_TERTIARY_OP | REG_DEF0_USE1 | SETS_CCODES,
                  "lsrs", "r!0d, r!1d, #!2d", 1),
-    ENCODING_MAP(THUMB_LSRV,          0x40c0,
+    ENCODING_MAP(THUMB_LSR_RR,        0x40c0,
                  BITBLT, 2, 0, BITBLT, 5, 3, UNUSED, -1, -1, UNUSED, -1, -1,
-                 IS_BINARY_OP | CLOBBER_DEST | SETS_CCODES,
+                 IS_BINARY_OP | REG_DEF0_USE01 | SETS_CCODES,
                  "lsrs", "r!0d, r!1d", 1),
     ENCODING_MAP(THUMB_MOV_IMM,       0x2000,
                  BITBLT, 10, 8, BITBLT, 7, 0, UNUSED, -1, -1, UNUSED, -1, -1,
-                 IS_BINARY_OP | CLOBBER_DEST | SETS_CCODES,
+                 IS_BINARY_OP | REG_DEF0 | SETS_CCODES,
                  "movs", "r!0d, #!1d", 1),
     ENCODING_MAP(THUMB_MOV_RR,        0x1c00,
                  BITBLT, 2, 0, BITBLT, 5, 3, UNUSED, -1, -1, UNUSED, -1, -1,
-                 IS_BINARY_OP | CLOBBER_DEST | SETS_CCODES,
+                 IS_BINARY_OP | REG_DEF0_USE1 | SETS_CCODES,
                  "movs", "r!0d, r!1d", 1),
     ENCODING_MAP(THUMB_MOV_RR_H2H,    0x46c0,
                  BITBLT, 2, 0, BITBLT, 5, 3, UNUSED, -1, -1, UNUSED, -1, -1,
-                 IS_BINARY_OP | CLOBBER_DEST,
+                 IS_BINARY_OP | REG_DEF0_USE1,
                  "mov", "r!0D, r!1D", 1),
     ENCODING_MAP(THUMB_MOV_RR_H2L,    0x4640,
                  BITBLT, 2, 0, BITBLT, 5, 3, UNUSED, -1, -1, UNUSED, -1, -1,
-                 IS_BINARY_OP | CLOBBER_DEST,
+                 IS_BINARY_OP | REG_DEF0_USE1,
                  "mov", "r!0d, r!1D", 1),
     ENCODING_MAP(THUMB_MOV_RR_L2H,    0x4680,
                  BITBLT, 2, 0, BITBLT, 5, 3, UNUSED, -1, -1, UNUSED, -1, -1,
-                 IS_BINARY_OP | CLOBBER_DEST,
+                 IS_BINARY_OP | REG_DEF0_USE1,
                  "mov", "r!0D, r!1d", 1),
     ENCODING_MAP(THUMB_MUL,           0x4340,
                  BITBLT, 2, 0, BITBLT, 5, 3, UNUSED, -1, -1, UNUSED, -1, -1,
-                 IS_BINARY_OP | CLOBBER_DEST | SETS_CCODES,
+                 IS_BINARY_OP | REG_DEF0_USE01 | SETS_CCODES,
                  "muls", "r!0d, r!1d", 1),
     ENCODING_MAP(THUMB_MVN,           0x43c0,
                  BITBLT, 2, 0, BITBLT, 5, 3, UNUSED, -1, -1, UNUSED, -1, -1,
-                 IS_BINARY_OP | CLOBBER_DEST | SETS_CCODES,
+                 IS_BINARY_OP | REG_DEF0_USE1 | SETS_CCODES,
                  "mvns", "r!0d, r!1d", 1),
     ENCODING_MAP(THUMB_NEG,           0x4240,
                  BITBLT, 2, 0, BITBLT, 5, 3, UNUSED, -1, -1, UNUSED, -1, -1,
-                 IS_BINARY_OP | CLOBBER_DEST | SETS_CCODES,
+                 IS_BINARY_OP | REG_DEF0_USE1 | SETS_CCODES,
                  "negs", "r!0d, r!1d", 1),
     ENCODING_MAP(THUMB_ORR,           0x4300,
                  BITBLT, 2, 0, BITBLT, 5, 3, UNUSED, -1, -1, UNUSED, -1, -1,
-                 IS_BINARY_OP | CLOBBER_DEST | SETS_CCODES,
+                 IS_BINARY_OP | REG_DEF0_USE01 | SETS_CCODES,
                  "orrs", "r!0d, r!1d", 1),
     ENCODING_MAP(THUMB_POP,           0xbc00,
                  BITBLT, 8, 0, UNUSED, -1, -1, UNUSED, -1, -1, UNUSED, -1, -1,
-                 IS_UNARY_OP,
+                 IS_UNARY_OP | REG_DEF_SP | REG_USE_SP | REG_DEF_LIST0,
                  "pop", "<!0R>", 1),
     ENCODING_MAP(THUMB_PUSH,          0xb400,
                  BITBLT, 8, 0, UNUSED, -1, -1, UNUSED, -1, -1, UNUSED, -1, -1,
-                 IS_UNARY_OP,
+                 IS_UNARY_OP | REG_DEF_SP | REG_USE_SP | REG_USE_LIST0,
                  "push", "<!0R>", 1),
-    ENCODING_MAP(THUMB_RORV,           0x41c0,
+    ENCODING_MAP(THUMB_ROR_RR,        0x41c0,
                  BITBLT, 2, 0, BITBLT, 5, 3, UNUSED, -1, -1, UNUSED, -1, -1,
-                 IS_BINARY_OP | CLOBBER_DEST | SETS_CCODES,
+                 IS_BINARY_OP | REG_DEF0_USE01 | SETS_CCODES,
                  "rors", "r!0d, r!1d", 1),
     ENCODING_MAP(THUMB_SBC,           0x4180,
                  BITBLT, 2, 0, BITBLT, 5, 3, UNUSED, -1, -1, UNUSED, -1, -1,
-                 IS_BINARY_OP | CLOBBER_DEST | USES_CCODES | SETS_CCODES,
+                 IS_BINARY_OP | REG_DEF0_USE01 | USES_CCODES | SETS_CCODES,
                  "sbcs", "r!0d, r!1d", 1),
     ENCODING_MAP(THUMB_STMIA,         0xc000,
                  BITBLT, 10, 8, BITBLT, 7, 0, UNUSED, -1, -1, UNUSED, -1, -1,
-                 IS_BINARY_OP | CLOBBER_SRC1,
+                 IS_BINARY_OP | REG_DEF0 | REG_USE0 | REG_USE_LIST1,
                  "stmia", "r!0d!!, <!1R>", 1),
     ENCODING_MAP(THUMB_STR_RRI5,      0x6000,
                  BITBLT, 2, 0, BITBLT, 5, 3, BITBLT, 10, 6, UNUSED, -1, -1,
-                 IS_TERTIARY_OP,
+                 IS_TERTIARY_OP | REG_USE01,
                  "str", "r!0d, [r!1d, #!2E]", 1),
     ENCODING_MAP(THUMB_STR_RRR,       0x5000,
                  BITBLT, 2, 0, BITBLT, 5, 3, BITBLT, 8, 6, UNUSED, -1, -1,
-                 IS_TERTIARY_OP,
+                 IS_TERTIARY_OP | REG_USE012,
                  "str", "r!0d, [r!1d, r!2d]", 1),
     ENCODING_MAP(THUMB_STR_SP_REL,    0x9000,
                  BITBLT, 10, 8, UNUSED, -1, -1, BITBLT, 7, 0, UNUSED, -1, -1,
-                 IS_TERTIARY_OP,
+                 IS_TERTIARY_OP | REG_USE0 | REG_USE_SP,
                  "str", "r!0d, [sp, #!2E]", 1),
     ENCODING_MAP(THUMB_STRB_RRI5,     0x7000,
                  BITBLT, 2, 0, BITBLT, 5, 3, BITBLT, 10, 6, UNUSED, -1, -1,
-                 IS_TERTIARY_OP,
+                 IS_TERTIARY_OP | REG_USE01,
                  "strb", "r!0d, [r!1d, #!2d]", 1),
     ENCODING_MAP(THUMB_STRB_RRR,      0x5400,
                  BITBLT, 2, 0, BITBLT, 5, 3, BITBLT, 8, 6, UNUSED, -1, -1,
-                 IS_TERTIARY_OP,
+                 IS_TERTIARY_OP | REG_USE012,
                  "strb", "r!0d, [r!1d, r!2d]", 1),
     ENCODING_MAP(THUMB_STRH_RRI5,     0x8000,
                  BITBLT, 2, 0, BITBLT, 5, 3, BITBLT, 10, 6, UNUSED, -1, -1,
-                 IS_TERTIARY_OP,
+                 IS_TERTIARY_OP | REG_USE01,
                  "strh", "r!0d, [r!1d, #!2F]", 1),
     ENCODING_MAP(THUMB_STRH_RRR,      0x5200,
                  BITBLT, 2, 0, BITBLT, 5, 3, BITBLT, 8, 6, UNUSED, -1, -1,
-                 IS_TERTIARY_OP,
+                 IS_TERTIARY_OP | REG_USE012,
                  "strh", "r!0d, [r!1d, r!2d]", 1),
     ENCODING_MAP(THUMB_SUB_RRI3,      0x1e00,
                  BITBLT, 2, 0, BITBLT, 5, 3, BITBLT, 8, 6, UNUSED, -1, -1,
-                 IS_TERTIARY_OP | CLOBBER_DEST | SETS_CCODES,
+                 IS_TERTIARY_OP | REG_DEF0_USE1 | SETS_CCODES,
                  "subs", "r!0d, r!1d, #!2d]", 1),
     ENCODING_MAP(THUMB_SUB_RI8,       0x3800,
                  BITBLT, 10, 8, BITBLT, 7, 0, UNUSED, -1, -1, UNUSED, -1, -1,
-                 IS_BINARY_OP | CLOBBER_DEST | SETS_CCODES,
+                 IS_BINARY_OP | REG_DEF0 | REG_USE0 | SETS_CCODES,
                  "subs", "r!0d, #!1d", 1),
     ENCODING_MAP(THUMB_SUB_RRR,       0x1a00,
                  BITBLT, 2, 0, BITBLT, 5, 3, BITBLT, 8, 6, UNUSED, -1, -1,
-                 IS_TERTIARY_OP | CLOBBER_DEST | SETS_CCODES,
+                 IS_TERTIARY_OP | REG_DEF0_USE12 | 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, UNUSED, -1, -1,
-                 IS_UNARY_OP | CLOBBER_DEST,
+                 IS_UNARY_OP | REG_DEF_SP | REG_USE_SP,
                  "sub", "sp, #!0d", 1),
     ENCODING_MAP(THUMB_SWI,           0xdf00,
                  BITBLT, 7, 0, UNUSED, -1, -1, UNUSED, -1, -1, UNUSED, -1, -1,
@@ -365,111 +365,111 @@
                  "swi", "!0d", 1),
     ENCODING_MAP(THUMB_TST,           0x4200,
                  BITBLT, 2, 0, BITBLT, 5, 3, UNUSED, -1, -1, UNUSED, -1, -1,
-                 IS_UNARY_OP | SETS_CCODES,
+                 IS_UNARY_OP | REG_USE01 | SETS_CCODES,
                  "tst", "r!0d, r!1d", 1),
     ENCODING_MAP(THUMB2_VLDRS,       0xed900a00,
                  SFP, 22, 12, BITBLT, 19, 16, BITBLT, 7, 0, UNUSED, -1, -1,
-                 IS_TERTIARY_OP | CLOBBER_DEST,
+                 IS_TERTIARY_OP | REG_DEF0_USE1,
                  "vldr", "!0s, [r!1d, #!2E]", 2),
     ENCODING_MAP(THUMB2_VLDRD,       0xed900b00,
                  DFP, 22, 12, BITBLT, 19, 16, BITBLT, 7, 0, UNUSED, -1, -1,
-                 IS_TERTIARY_OP | CLOBBER_DEST,
+                 IS_TERTIARY_OP | REG_DEF0_USE1,
                  "vldr", "!0S, [r!1d, #!2E]", 2),
     ENCODING_MAP(THUMB2_VMULS,        0xee200a00,
                  SFP, 22, 12, SFP, 7, 16, SFP, 5, 0, UNUSED, -1, -1,
-                 IS_TERTIARY_OP | CLOBBER_DEST,
+                 IS_TERTIARY_OP | REG_DEF0_USE12,
                  "vmuls", "!0s, !1s, !2s", 2),
     ENCODING_MAP(THUMB2_VMULD,        0xee200b00,
                  DFP, 22, 12, DFP, 7, 16, DFP, 5, 0, UNUSED, -1, -1,
-                 IS_TERTIARY_OP | CLOBBER_DEST,
+                 IS_TERTIARY_OP | REG_DEF0_USE12,
                  "vmuld", "!0S, !1S, !2S", 2),
     ENCODING_MAP(THUMB2_VSTRS,       0xed800a00,
                  SFP, 22, 12, BITBLT, 19, 16, BITBLT, 7, 0, UNUSED, -1, -1,
-                 IS_TERTIARY_OP,
+                 IS_TERTIARY_OP | REG_USE01,
                  "vstr", "!0s, [r!1d, #!2E]", 2),
     ENCODING_MAP(THUMB2_VSTRD,       0xed800b00,
                  DFP, 22, 12, BITBLT, 19, 16, BITBLT, 7, 0, UNUSED, -1, -1,
-                 IS_TERTIARY_OP,
+                 IS_TERTIARY_OP | REG_USE01,
                  "vstr", "!0S, [r!1d, #!2E]", 2),
     ENCODING_MAP(THUMB2_VSUBS,        0xee300a40,
                  SFP, 22, 12, SFP, 7, 16, SFP, 5, 0, UNUSED, -1, -1,
-                 IS_TERTIARY_OP | CLOBBER_DEST,
+                 IS_TERTIARY_OP | REG_DEF0_USE12,
                  "vsub", "!0s, !1s, !2s", 2),
     ENCODING_MAP(THUMB2_VSUBD,        0xee300b40,
                  DFP, 22, 12, DFP, 7, 16, DFP, 5, 0, UNUSED, -1, -1,
-                 IS_TERTIARY_OP | CLOBBER_DEST,
+                 IS_TERTIARY_OP | REG_DEF0_USE12,
                  "vsub", "!0S, !1S, !2S", 2),
     ENCODING_MAP(THUMB2_VADDS,        0xee300a00,
                  SFP, 22, 12, SFP, 7, 16, SFP, 5, 0, UNUSED, -1, -1,
-                 IS_TERTIARY_OP | CLOBBER_DEST,
+                 IS_TERTIARY_OP | REG_DEF0_USE12,
                  "vadd", "!0s, !1s, !2s", 2),
     ENCODING_MAP(THUMB2_VADDD,        0xee300b00,
                  DFP, 22, 12, DFP, 7, 16, DFP, 5, 0, UNUSED, -1, -1,
-                 IS_TERTIARY_OP | CLOBBER_DEST,
+                 IS_TERTIARY_OP | REG_DEF0_USE12,
                  "vadd", "!0S, !1S, !2S", 2),
     ENCODING_MAP(THUMB2_VDIVS,        0xee800a00,
                  SFP, 22, 12, SFP, 7, 16, SFP, 5, 0, UNUSED, -1, -1,
-                 IS_TERTIARY_OP | CLOBBER_DEST,
+                 IS_TERTIARY_OP | REG_DEF0_USE12,
                  "vdivs", "!0s, !1s, !2s", 2),
     ENCODING_MAP(THUMB2_VDIVD,        0xee800b00,
                  DFP, 22, 12, DFP, 7, 16, DFP, 5, 0, UNUSED, -1, -1,
-                 IS_TERTIARY_OP | CLOBBER_DEST,
+                 IS_TERTIARY_OP | REG_DEF0_USE12,
                  "vdivd", "!0S, !1S, !2S", 2),
     ENCODING_MAP(THUMB2_VCVTIF,       0xeeb80ac0,
                  SFP, 22, 12, SFP, 5, 0, UNUSED, -1, -1, UNUSED, -1, -1,
-                 IS_BINARY_OP | CLOBBER_DEST,
+                 IS_BINARY_OP | REG_DEF0_USE1,
                  "vcvt.f32", "!0s, !1s", 2),
     ENCODING_MAP(THUMB2_VCVTID,       0xeeb80bc0,
                  DFP, 22, 12, SFP, 5, 0, UNUSED, -1, -1, UNUSED, -1, -1,
-                 IS_BINARY_OP | CLOBBER_DEST,
+                 IS_BINARY_OP | REG_DEF0_USE1,
                  "vcvt.f64", "!0S, !1s", 2),
     ENCODING_MAP(THUMB2_VCVTFI,       0xeebd0ac0,
                  SFP, 22, 12, SFP, 5, 0, UNUSED, -1, -1, UNUSED, -1, -1,
-                 IS_BINARY_OP | CLOBBER_DEST,
+                 IS_BINARY_OP | REG_DEF0_USE1,
                  "vcvt.s32.f32 ", "!0s, !1s", 2),
     ENCODING_MAP(THUMB2_VCVTDI,       0xeebd0bc0,
                  SFP, 22, 12, DFP, 5, 0, UNUSED, -1, -1, UNUSED, -1, -1,
-                 IS_BINARY_OP | CLOBBER_DEST,
+                 IS_BINARY_OP | REG_DEF0_USE1,
                  "vcvt.s32.f64 ", "!0s, !1S", 2),
     ENCODING_MAP(THUMB2_VCVTFD,       0xeeb70ac0,
                  DFP, 22, 12, SFP, 5, 0, UNUSED, -1, -1, UNUSED, -1, -1,
-                 IS_BINARY_OP | CLOBBER_DEST,
+                 IS_BINARY_OP | REG_DEF0_USE1,
                  "vcvt.f64.f32 ", "!0S, !1s", 2),
     ENCODING_MAP(THUMB2_VCVTDF,       0xeeb70bc0,
                  SFP, 22, 12, DFP, 5, 0, UNUSED, -1, -1, UNUSED, -1, -1,
-                 IS_BINARY_OP | CLOBBER_DEST,
+                 IS_BINARY_OP | REG_DEF0_USE1,
                  "vcvt.f32.f64 ", "!0s, !1S", 2),
     ENCODING_MAP(THUMB2_VSQRTS,       0xeeb10ac0,
                  SFP, 22, 12, SFP, 5, 0, UNUSED, -1, -1, UNUSED, -1, -1,
-                 IS_BINARY_OP | CLOBBER_DEST,
+                 IS_BINARY_OP | REG_DEF0_USE1,
                  "vsqrt.f32 ", "!0s, !1s", 2),
     ENCODING_MAP(THUMB2_VSQRTD,       0xeeb10bc0,
                  DFP, 22, 12, DFP, 5, 0, UNUSED, -1, -1, UNUSED, -1, -1,
-                 IS_BINARY_OP | CLOBBER_DEST,
+                 IS_BINARY_OP | REG_DEF0_USE1,
                  "vsqrt.f64 ", "!0S, !1S", 2),
     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,
+                 IS_BINARY_OP | REG_DEF0,
                  "mov", "r!0d, #!1m", 2),
     ENCODING_MAP(THUMB2_MOV_IMM16,       0xf2400000,
                  BITBLT, 11, 8, IMM16, -1, -1, UNUSED, -1, -1, UNUSED, -1, -1,
-                 IS_BINARY_OP | CLOBBER_DEST,
+                 IS_BINARY_OP | REG_DEF0,
                  "mov", "r!0d, #!1M", 2),
     ENCODING_MAP(THUMB2_STR_RRI12,       0xf8c00000,
                  BITBLT, 15, 12, BITBLT, 19, 16, BITBLT, 11, 0, UNUSED, -1, -1,
-                 IS_TERTIARY_OP,
+                 IS_TERTIARY_OP | REG_USE01,
                  "str", "r!0d,[r!1d, #!2d", 2),
     ENCODING_MAP(THUMB2_LDR_RRI12,       0xf8d00000,
                  BITBLT, 15, 12, BITBLT, 19, 16, BITBLT, 11, 0, UNUSED, -1, -1,
-                 IS_TERTIARY_OP | CLOBBER_DEST,
+                 IS_TERTIARY_OP | REG_DEF0_USE1,
                  "ldr", "r!0d,[r!1d, #!2d", 2),
     ENCODING_MAP(THUMB2_STR_RRI8_PREDEC,       0xf8400c00,
                  BITBLT, 15, 12, BITBLT, 19, 16, BITBLT, 8, 0, UNUSED, -1, -1,
-                 IS_TERTIARY_OP,
+                 IS_TERTIARY_OP | REG_USE01,
                  "str", "r!0d,[r!1d, #-!2d]", 2),
     ENCODING_MAP(THUMB2_LDR_RRI8_PREDEC,       0xf8500c00,
                  BITBLT, 15, 12, BITBLT, 19, 16, BITBLT, 8, 0, UNUSED, -1, -1,
-                 IS_TERTIARY_OP | CLOBBER_DEST,
+                 IS_TERTIARY_OP | REG_DEF0_USE1,
                  "ldr", "r!0d,[r!1d, #-!2d]", 2),
     ENCODING_MAP(THUMB2_CBNZ,       0xb900,
                  BITBLT, 2, 0, IMM6, -1, -1, UNUSED, -1, -1, UNUSED, -1, -1,
@@ -481,243 +481,243 @@
                  "cbz", "r!0d,!1t", 1),
     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 */
+                 IS_TERTIARY_OP | REG_DEF0_USE1,/* Note: doesn't affect flags */
                  "add", "r!0d,r!1d,#!2d", 2),
     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,
+                 IS_BINARY_OP | REG_DEF0_USE1,
                  "mov", "r!0d, r!1d", 2),
     ENCODING_MAP(THUMB2_VMOVS,       0xeeb00a40,
                  SFP, 22, 12, SFP, 5, 0, UNUSED, -1, -1, UNUSED, -1, -1,
-                 IS_BINARY_OP | CLOBBER_DEST,
+                 IS_BINARY_OP | REG_DEF0_USE1,
                  "vmov.f32 ", " !0s, !1s", 2),
     ENCODING_MAP(THUMB2_VMOVD,       0xeeb00b40,
                  DFP, 22, 12, DFP, 5, 0, UNUSED, -1, -1, UNUSED, -1, -1,
-                 IS_BINARY_OP | CLOBBER_DEST,
+                 IS_BINARY_OP | REG_DEF0_USE1,
                  "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,
+                 IS_BINARY_OP | REG_DEF0 | REG_USE0 | REG_DEF_LIST1,
                  "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,
+                 IS_BINARY_OP | REG_DEF0 | REG_USE0 | REG_USE_LIST1,
                  "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,
+                 IS_QUAD_OP | REG_DEF0_USE12 | 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,
+                 IS_QUAD_OP | REG_DEF0_USE12 | 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,
+                 IS_QUAD_OP | REG_DEF0_USE12 | 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,
+                 IS_TERTIARY_OP | REG_USE01 | 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 */
+                 IS_TERTIARY_OP | REG_DEF0_USE1,/* 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,
+                 IS_BINARY_OP | REG_DEF0,
                  "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,
+                 IS_TERTIARY_OP | REG_DEF0_USE12 | 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,
+                 IS_QUAD_OP | REG_DEF0_USE1,
                  "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,
+                 IS_QUAD_OP | REG_DEF0_USE1,
                  "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,
+                 IS_QUAD_OP | REG_DEF0_USE12,
                  "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,
+                 IS_QUAD_OP | REG_DEF0_USE12,
                  "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,
+                 IS_QUAD_OP | REG_DEF0_USE12,
                  "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,
+                 IS_QUAD_OP | REG_DEF0_USE12,
                  "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,
+                 IS_QUAD_OP | REG_DEF0_USE12,
                  "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,
+                 IS_QUAD_OP | REG_USE012,
                  "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,
+                 IS_QUAD_OP | REG_USE012,
                  "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,
+                 IS_QUAD_OP | REG_USE012,
                  "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,
+                 IS_TERTIARY_OP | REG_DEF0_USE1,
                  "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,
+                 IS_TERTIARY_OP | REG_DEF0_USE1,
                  "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,
+                 IS_TERTIARY_OP | REG_DEF0_USE1,
                  "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,
+                 IS_TERTIARY_OP | REG_DEF0_USE1,
                  "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,
+                 IS_TERTIARY_OP | REG_USE01,
                  "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,
+                 IS_TERTIARY_OP | REG_USE01,
                  "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,
+                 IS_UNARY_OP | REG_DEF_SP | REG_USE_SP | REG_DEF_LIST0,
                  "pop", "<!0R>", 2),
     ENCODING_MAP(THUMB2_PUSH,          0xe8ad0000,
                  BITBLT, 15, 0, UNUSED, -1, -1, UNUSED, -1, -1, UNUSED, -1, -1,
-                 IS_UNARY_OP,
+                 IS_UNARY_OP | REG_DEF_SP | REG_USE_SP | REG_USE_LIST0,
                  "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,
+                 IS_BINARY_OP | REG_USE0 | 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,
+                 IS_QUAD_OP | REG_DEF0_USE12 | 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,
+                 IS_QUAD_OP | REG_DEF0_USE12,
                  "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,
+                 IS_QUAD_OP | REG_DEF0_USE12,
                  "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,
+                 IS_TERTIARY_OP | REG_DEF0_USE1 | 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,
+                 IS_QUAD_OP | REG_DEF0_USE12,
                  "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,
+                 IS_TERTIARY_OP | REG_DEF0_USE12,
                  "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,
+                 IS_TERTIARY_OP | REG_DEF0_USE1,
                  "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,
+                 IS_TERTIARY_OP | REG_DEF0_USE1 | 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,
+                 IS_BINARY_OP | REG_DEF0_USE1 | 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,
+                 IS_QUAD_OP | REG_DEF0_USE12,
                  "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,
+                 IS_TERTIARY_OP | REG_USE01 | SETS_CCODES,
                  "tst", "r!0d, r!1d, shift !2d", 2),
-    ENCODING_MAP(THUMB2_LSLV_RRR,  0xfa00f000,
+    ENCODING_MAP(THUMB2_LSL_RRR,  0xfa00f000,
                  BITBLT, 11, 8, BITBLT, 19, 16, BITBLT, 3, 0, UNUSED, -1, -1,
-                 IS_TERTIARY_OP | CLOBBER_DEST,
+                 IS_TERTIARY_OP | REG_DEF0_USE12,
                  "lsl", "r!0d, r!1d, r!2d", 2),
-    ENCODING_MAP(THUMB2_LSRV_RRR,  0xfa20f000,
+    ENCODING_MAP(THUMB2_LSR_RRR,  0xfa20f000,
                  BITBLT, 11, 8, BITBLT, 19, 16, BITBLT, 3, 0, UNUSED, -1, -1,
-                 IS_TERTIARY_OP | CLOBBER_DEST,
+                 IS_TERTIARY_OP | REG_DEF0_USE12,
                  "lsr", "r!0d, r!1d, r!2d", 2),
-    ENCODING_MAP(THUMB2_ASRV_RRR,  0xfa40f000,
+    ENCODING_MAP(THUMB2_ASR_RRR,  0xfa40f000,
                  BITBLT, 11, 8, BITBLT, 19, 16, BITBLT, 3, 0, UNUSED, -1, -1,
-                 IS_TERTIARY_OP | CLOBBER_DEST,
+                 IS_TERTIARY_OP | REG_DEF0_USE12,
                  "asr", "r!0d, r!1d, r!2d", 2),
-    ENCODING_MAP(THUMB2_RORV_RRR,  0xfa60f000,
+    ENCODING_MAP(THUMB2_ROR_RRR,  0xfa60f000,
                  BITBLT, 11, 8, BITBLT, 19, 16, BITBLT, 3, 0, UNUSED, -1, -1,
-                 IS_TERTIARY_OP | CLOBBER_DEST,
+                 IS_TERTIARY_OP | REG_DEF0_USE12,
                  "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,
+                 IS_TERTIARY_OP | REG_DEF0_USE1,
                  "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,
+                 IS_TERTIARY_OP | REG_DEF0_USE1,
                  "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,
+                 IS_TERTIARY_OP | REG_DEF0_USE1,
                  "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,
+                 IS_TERTIARY_OP | REG_DEF0_USE1,
                  "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,
+                 IS_TERTIARY_OP | REG_DEF0_USE1,
                  "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,
+                 IS_TERTIARY_OP | REG_DEF0_USE1,
                  "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,
+                 IS_TERTIARY_OP | REG_DEF0_USE1,
                  "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,
+                 IS_TERTIARY_OP | REG_DEF0_USE1,
                  "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,
+                 IS_TERTIARY_OP | REG_DEF0_USE1 | 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,
+                 IS_TERTIARY_OP | REG_DEF0_USE1 | 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,
+                 IS_TERTIARY_OP | REG_DEF0_USE1 | 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,
+                 IS_TERTIARY_OP | REG_DEF0_USE1 | SETS_CCODES | USES_CCODES,
                  "sbcs", "r!0d, r!1d, #!2m", 2),
     ENCODING_MAP(THUMB2_IT,  0xbf00,
                  BITBLT, 7, 4, BITBLT, 3, 0, MODIMM, -1, -1, UNUSED, -1, -1,
-                 IS_BINARY_OP | USES_CCODES,
+                 IS_BINARY_OP | IS_IT | USES_CCODES,
                  "it:!1b", "!0c", 1),
     ENCODING_MAP(THUMB2_FMSTAT,  0xeef1fa10,
                  UNUSED, -1, -1, UNUSED, -1, -1, UNUSED, -1, -1, UNUSED, -1, -1,
@@ -725,15 +725,15 @@
                  "fmstat", "", 2),
     ENCODING_MAP(THUMB2_VCMPD,        0xeeb40b40,
                  DFP, 22, 12, DFP, 5, 0, UNUSED, -1, -1, UNUSED, -1, -1,
-                 IS_BINARY_OP,
+                 IS_BINARY_OP | REG_USE01,
                  "vcmp.f64", "!0S, !1S", 2),
     ENCODING_MAP(THUMB2_VCMPS,        0xeeb40a40,
                  SFP, 22, 12, SFP, 5, 0, UNUSED, -1, -1, UNUSED, -1, -1,
-                 IS_BINARY_OP,
+                 IS_BINARY_OP | REG_USE01,
                  "vcmp.f32", "!0s, !1s", 2),
     ENCODING_MAP(THUMB2_LDR_PC_REL12,       0xf8df0000,
                  BITBLT, 15, 12, BITBLT, 11, 0, UNUSED, -1, -1, UNUSED, -1, -1,
-                 IS_TERTIARY_OP | CLOBBER_DEST,
+                 IS_TERTIARY_OP | REG_DEF0 | REG_USE_PC,
                  "ldr", "r!0d,[rpc, #!1d", 2),
     ENCODING_MAP(THUMB2_B_COND,        0xf0008000,
                  BROFFSET, -1, -1, BITBLT, 25, 22, UNUSED, -1, -1,
@@ -742,27 +742,27 @@
                  "b!1c", "!0t", 2),
     ENCODING_MAP(THUMB2_VMOVD_RR,       0xeeb00b40,
                  DFP, 22, 12, DFP, 5, 0, UNUSED, -1, -1, UNUSED, -1, -1,
-                 IS_BINARY_OP | CLOBBER_DEST,
+                 IS_BINARY_OP | REG_DEF0_USE1,
                  "vmov.f64", "!0S, !1S", 2),
-    ENCODING_MAP(THUMB2_VMOVD_RR,       0xeeb00a40,
+    ENCODING_MAP(THUMB2_VMOVS_RR,       0xeeb00a40,
                  SFP, 22, 12, SFP, 5, 0, UNUSED, -1, -1, UNUSED, -1, -1,
-                 IS_BINARY_OP | CLOBBER_DEST,
+                 IS_BINARY_OP | REG_DEF0_USE1,
                  "vmov.f32", "!0S, !1S", 2),
     ENCODING_MAP(THUMB2_FMRS,       0xee100a10,
                  BITBLT, 15, 12, SFP, 8, 16, UNUSED, -1, -1, UNUSED, -1, -1,
-                 IS_BINARY_OP | CLOBBER_DEST,
+                 IS_BINARY_OP | REG_DEF0_USE1,
                  "fmrs", "r!0d, !1s", 2),
     ENCODING_MAP(THUMB2_FMSR,       0xee000a10,
                  SFP, 8, 16, BITBLT, 15, 12, UNUSED, -1, -1, UNUSED, -1, -1,
-                 IS_BINARY_OP | CLOBBER_DEST,
+                 IS_BINARY_OP | REG_DEF0_USE1,
                  "fmsr", "!0s, r!1d", 2),
     ENCODING_MAP(THUMB2_FMRRD,       0xec500b10,
                  BITBLT, 15, 12, BITBLT, 19, 16, DFP, 5, 0, UNUSED, -1, -1,
-                 IS_TERTIARY_OP | CLOBBER_DEST | CLOBBER_SRC1,
+                 IS_TERTIARY_OP | REG_DEF0 | REG_DEF1 | REG_USE2,
                  "fmrrd", "r!0d, r!1d, !2S", 2),
     ENCODING_MAP(THUMB2_FMDRR,       0xec400b10,
                  DFP, 5, 0, BITBLT, 15, 12, BITBLT, 19, 16, UNUSED, -1, -1,
-                 IS_TERTIARY_OP | CLOBBER_DEST,
+                 IS_TERTIARY_OP | REG_DEF0_USE12,
                  "fmdrr", "!0S, r!1d, r!2d", 2),
 };
 
diff --git a/vm/compiler/codegen/arm/Codegen.c b/vm/compiler/codegen/arm/Codegen.c
index 3c28c7b..8ae22af 100644
--- a/vm/compiler/codegen/arm/Codegen.c
+++ b/vm/compiler/codegen/arm/Codegen.c
@@ -483,6 +483,91 @@
 #endif
 
 /*
+ * Set up the proper fields in the resource mask
+ */
+static void setupResourceMasks(ArmLIR *lir)
+{
+    int opCode = lir->opCode;
+    int flags;
+
+    if (opCode <= 0) {
+        lir->useMask = lir->defMask = 0;
+        return;
+    }
+
+    flags = EncodingMap[lir->opCode].flags;
+
+    /* Set up the mask for resources that are updated */
+    if (flags & IS_BRANCH) {
+        lir->defMask |= ENCODE_REG_PC;
+    }
+
+    if (flags & REG_DEF0) {
+        lir->defMask |= ENCODE_GP_REG(lir->operands[0]);
+    }
+
+    if (flags & REG_DEF1) {
+        lir->defMask |= ENCODE_GP_REG(lir->operands[1]);
+    }
+
+    if (flags & REG_DEF_SP) {
+        lir->defMask |= ENCODE_REG_SP;
+    }
+
+    if (flags & REG_DEF_LIST0) {
+        lir->defMask |= ENCODE_REG_LIST(lir->operands[0]);
+    }
+
+    if (flags & REG_DEF_LIST1) {
+        lir->defMask |= ENCODE_REG_LIST(lir->operands[1]);
+    }
+
+    if (flags & SETS_CCODES) {
+        lir->defMask |= ENCODE_CCODE;
+    }
+
+    /* Conservatively treat the IT block */
+    if (flags & IS_IT) {
+        lir->defMask = -1;
+    }
+
+    /* Set up the mask for resources that are used */
+    if (flags & IS_BRANCH) {
+        lir->useMask |= ENCODE_REG_PC;
+    }
+
+    if (flags & (REG_USE0 | REG_USE1 | REG_USE2)) {
+        int i;
+
+        for (i = 0; i < 3; i++) {
+            if (flags & (1 << (kRegUse0 + i))) {
+                lir->useMask |= ENCODE_GP_REG(lir->operands[i]);
+            }
+        }
+    }
+
+    if (flags & REG_USE_PC) {
+        lir->useMask |= ENCODE_REG_PC;
+    }
+
+    if (flags & REG_USE_SP) {
+        lir->useMask |= ENCODE_REG_SP;
+    }
+
+    if (flags & REG_USE_LIST0) {
+        lir->useMask |= ENCODE_REG_LIST(lir->operands[0]);
+    }
+
+    if (flags & REG_USE_LIST1) {
+        lir->useMask |= ENCODE_REG_LIST(lir->operands[1]);
+    }
+
+    if (flags & USES_CCODES) {
+        lir->useMask |= ENCODE_CCODE;
+    }
+}
+
+/*
  * The following are building blocks to construct low-level IRs with 0 - 4
  * operands.
  */
@@ -491,6 +576,7 @@
     ArmLIR *insn = dvmCompilerNew(sizeof(ArmLIR), true);
     assert(isPseudoOpCode(opCode) || (EncodingMap[opCode].flags & NO_OPERAND));
     insn->opCode = opCode;
+    setupResourceMasks(insn);
     dvmCompilerAppendLIR(cUnit, (LIR *) insn);
     return insn;
 }
@@ -502,6 +588,7 @@
     assert(isPseudoOpCode(opCode) || (EncodingMap[opCode].flags & IS_UNARY_OP));
     insn->opCode = opCode;
     insn->operands[0] = dest;
+    setupResourceMasks(insn);
     dvmCompilerAppendLIR(cUnit, (LIR *) insn);
     return insn;
 }
@@ -515,6 +602,7 @@
     insn->opCode = opCode;
     insn->operands[0] = dest;
     insn->operands[1] = src1;
+    setupResourceMasks(insn);
     dvmCompilerAppendLIR(cUnit, (LIR *) insn);
     return insn;
 }
@@ -529,6 +617,7 @@
     insn->operands[0] = dest;
     insn->operands[1] = src1;
     insn->operands[2] = src2;
+    setupResourceMasks(insn);
     dvmCompilerAppendLIR(cUnit, (LIR *) insn);
     return insn;
 }
@@ -544,6 +633,7 @@
     insn->operands[1] = src1;
     insn->operands[2] = src2;
     insn->operands[3] = info;
+    setupResourceMasks(insn);
     dvmCompilerAppendLIR(cUnit, (LIR *) insn);
     return insn;
 }
@@ -3615,11 +3705,13 @@
     ArmLIR *branchToBody = dvmCompilerNew(sizeof(ArmLIR), true);
     branchToBody->opCode = THUMB_B_UNCOND;
     branchToBody->generic.target = (LIR *) bodyLabel;
+    setupResourceMasks(branchToBody);
     cUnit->loopAnalysis->branchToBody = (LIR *) branchToBody;
 
     ArmLIR *branchToPCR = dvmCompilerNew(sizeof(ArmLIR), true);
     branchToPCR->opCode = THUMB_B_UNCOND;
     branchToPCR->generic.target = (LIR *) pcrLabel;
+    setupResourceMasks(branchToPCR);
     cUnit->loopAnalysis->branchToPCR = (LIR *) branchToPCR;
 }
 
@@ -3662,7 +3754,7 @@
             (LIR *) newLIR1(cUnit, ARM_16BIT_DATA, CHAIN_CELL_OFFSET_TAG);
         cUnit->headerSize = 6;
         /* Thumb instruction used directly here to ensure correct size */
-        newLIR2(cUnit, THUMB_MOV_RR_H2L, r0, rpc & THUMB_REG_MASK);
+        newLIR2(cUnit, THUMB_MOV_RR_H2L, r0, rpc);
         newLIR2(cUnit, THUMB_SUB_RI8, r0, 10);
         newLIR3(cUnit, THUMB_LDR_RRI5, r1, r0, 0);
         newLIR2(cUnit, THUMB_ADD_RI8, r1, 1);
diff --git a/vm/compiler/codegen/arm/Codegen.h b/vm/compiler/codegen/arm/Codegen.h
index 6da22eb..50a94fd 100644
--- a/vm/compiler/codegen/arm/Codegen.h
+++ b/vm/compiler/codegen/arm/Codegen.h
@@ -22,6 +22,7 @@
  * variant code such as ThumbUtilty.c
  */
 
+static void setupResourceMasks(ArmLIR *lir);
 static ArmLIR *newLIR0(CompilationUnit *cUnit, ArmOpCode opCode);
 static ArmLIR *newLIR1(CompilationUnit *cUnit, ArmOpCode opCode,
                            int dest);
diff --git a/vm/compiler/codegen/arm/LocalOptimizations.c b/vm/compiler/codegen/arm/LocalOptimizations.c
index 6f00b9e..fbc0e26 100644
--- a/vm/compiler/codegen/arm/LocalOptimizations.c
+++ b/vm/compiler/codegen/arm/LocalOptimizations.c
@@ -85,6 +85,11 @@
             int nativeRegId = thisLIR->operands[0];
             ArmLIR *checkLIR;
             int sinkDistance = 0;
+            /*
+             * Add r15 (pc) to the mask to prevent this instruction
+             * from sinking past branch instructions.
+             */
+            u8 stopMask = ENCODE_GP_REG(rpc) | thisLIR->useMask;
 
             for (checkLIR = NEXT_LIR(thisLIR);
                  checkLIR != tailLIR;
@@ -122,7 +127,7 @@
                     bool stopHere = false;
 
                     /* Last instruction reached */
-                    stopHere |= checkLIR->generic.next == NULL;
+                    stopHere |= NEXT_LIR(checkLIR) == tailLIR;
 
                     /*
                      * Conservatively assume there is a memory dependency
@@ -139,24 +144,12 @@
                                 checkLIR->opCode == THUMB2_VLDRD ||
                                 checkLIR->opCode == THUMB2_VSTRD;
 
-                    /* Don't migrate into an IF region */
-                    stopHere |= checkLIR->opCode == THUMB2_IT;
 
-                    if (!isPseudoOpCode(checkLIR->opCode)) {
-
-                        /* Store data is clobbered */
-                        stopHere |= (EncodingMap[checkLIR->opCode].flags &
-                                     CLOBBER_DEST) != 0 &&
-                                     regClobber(checkLIR->operands[0],
-                                               nativeRegId);
-
-                        stopHere |= (EncodingMap[checkLIR->opCode].flags &
-                                     IS_BRANCH) != 0;
-                    }
+                    /* Store data is clobbered */
+                    stopHere |= (stopMask & checkLIR->defMask) != 0;
 
                     /* Found a new place to put the store - move it here */
                     if (stopHere == true) {
-
                         /* The store can be sunk for at least one cycle */
                         if (sinkDistance != 0) {
                             ArmLIR *newStoreLIR =
@@ -186,10 +179,126 @@
     }
 }
 
+static void applyLoadHoisting(CompilationUnit *cUnit,
+                              ArmLIR *headLIR,
+                              ArmLIR *tailLIR)
+{
+    ArmLIR *thisLIR;
+
+    cUnit->optRound++;
+    for (thisLIR = headLIR;
+         thisLIR != tailLIR;
+         thisLIR = NEXT_LIR(thisLIR)) {
+        /* Skip newly added instructions */
+        if (thisLIR->age >= cUnit->optRound ||
+            thisLIR->isNop == true) {
+            continue;
+        }
+        if (isDalvikLoad(thisLIR)) {
+            int dRegId = thisLIR->operands[2];
+            int nativeRegId = thisLIR->operands[0];
+            ArmLIR *checkLIR;
+            int hoistDistance = 0;
+            u8 stopUseMask = ENCODE_GP_REG(rpc) | thisLIR->useMask;
+            u8 stopDefMask = thisLIR->defMask;
+
+            for (checkLIR = PREV_LIR(thisLIR);
+                 checkLIR != headLIR;
+                 checkLIR = PREV_LIR(checkLIR)) {
+
+                if (checkLIR->isNop) continue;
+
+                /* Check if the current load is redundant */
+                if ((isDalvikLoad(checkLIR) || isDalvikStore(checkLIR)) &&
+                    checkLIR->operands[2] == dRegId ) {
+                    if (FPREG(nativeRegId) != FPREG(checkLIR->operands[0])) {
+                        break;  // TODO: handle gen<=>float copies
+                    }
+                    /* Insert a move to replace the load */
+                    if (checkLIR->operands[0] != nativeRegId) {
+                        ArmLIR *moveLIR;
+                        moveLIR = dvmCompilerRegCopy(cUnit,
+                                                    nativeRegId,
+                                                    checkLIR->operands[0]);
+                        /*
+                         * Convert *thisLIR* load into a move
+                         */
+                        dvmCompilerInsertLIRAfter((LIR *) checkLIR,
+                                                  (LIR *) moveLIR);
+                    }
+                    cUnit->printMe = true;
+                    thisLIR->isNop = true;
+                    break;
+
+                /* Find out if the load can be yanked past the checkLIR */
+                } else {
+                    bool stopHere = false;
+
+                    /* Last instruction reached */
+                    stopHere |= PREV_LIR(checkLIR) == headLIR;
+
+                    /*
+                     * Conservatively assume there is a memory dependency
+                     * for st/ld multiples and reg+reg address mode
+                     */
+                    stopHere |= checkLIR->opCode == THUMB_STMIA ||
+                                checkLIR->opCode == THUMB_LDMIA ||
+                                checkLIR->opCode == THUMB_STR_RRR ||
+                                checkLIR->opCode == THUMB_LDR_RRR ||
+                                checkLIR->opCode == THUMB2_STR_RRR ||
+                                checkLIR->opCode == THUMB2_LDR_RRR ||
+                                checkLIR->opCode == THUMB2_STMIA ||
+                                checkLIR->opCode == THUMB2_LDMIA ||
+                                checkLIR->opCode == THUMB2_VLDRD ||
+                                checkLIR->opCode == THUMB2_VSTRD;
+
+                    /* Base address is clobbered by checkLIR */
+                    stopHere |= (stopUseMask & checkLIR->defMask) != 0;
+
+                    /* Load target clobbers use/def in checkLIR */
+                    stopHere |= (stopDefMask &
+                                 (checkLIR->useMask | checkLIR->defMask)) != 0;
+
+                    /* Found a new place to put the load - move it here */
+                    if (stopHere == true) {
+                        /* The store can be hoisted for at least one cycle */
+                        if (hoistDistance != 0) {
+                            ArmLIR *newLoadLIR =
+                                dvmCompilerNew(sizeof(ArmLIR), true);
+                            *newLoadLIR = *thisLIR;
+                            newLoadLIR->age = cUnit->optRound;
+                            /*
+                             * Insertion is guaranteed to succeed since checkLIR
+                             * is never the first LIR on the list
+                             */
+                            dvmCompilerInsertLIRAfter((LIR *) checkLIR,
+                                                      (LIR *) newLoadLIR);
+                            thisLIR->isNop = true;
+                            cUnit->printMe = true;
+                        }
+                        break;
+                    }
+
+                    /*
+                     * Saw a real instruction that the store can be sunk after
+                     */
+                    if (!isPseudoOpCode(checkLIR->opCode)) {
+                        hoistDistance++;
+                    }
+                }
+            }
+        }
+    }
+}
+
 void dvmCompilerApplyLocalOptimizations(CompilationUnit *cUnit, LIR *headLIR,
                                         LIR *tailLIR)
 {
-    applyLoadStoreElimination(cUnit,
-                              (ArmLIR *) headLIR,
-                              (ArmLIR *) tailLIR);
+    if (!(gDvmJit.disableOpt & (1 << kLoadStoreElimination))) {
+        applyLoadStoreElimination(cUnit, (ArmLIR *) headLIR,
+                                  (ArmLIR *) tailLIR);
+    }
+    if (!(gDvmJit.disableOpt & (1 << kLoadHoisting))) {
+        applyLoadHoisting(cUnit, (ArmLIR *) headLIR, (ArmLIR *) tailLIR);
+    }
 }
diff --git a/vm/compiler/codegen/arm/Thumb2Util.c b/vm/compiler/codegen/arm/Thumb2Util.c
index 806bd02..b9d1a23 100644
--- a/vm/compiler/codegen/arm/Thumb2Util.c
+++ b/vm/compiler/codegen/arm/Thumb2Util.c
@@ -172,6 +172,16 @@
 }
 
 /*
+ * Generate a ARM_PSEUDO_IT_BOTTOM marker to indicate the end of an IT block
+ */
+static void genITBottom(CompilationUnit *cUnit)
+{
+    ArmLIR *itBottom = newLIR0(cUnit, ARM_PSEUDO_IT_BOTTOM);
+    /* Mark all resources as being clobbered */
+    itBottom->defMask = -1;
+}
+
+/*
  * Generate a Thumb2 IT instruction, which can nullify up to
  * four subsequent instructions based on a condition and its
  * inverse.  The condition applies to the first instruction, which
@@ -190,6 +200,7 @@
     int mask3 = 0;
     int mask2 = 0;
     int mask1 = 0;
+
     //Note: case fallthroughs intentional
     switch(strlen(guide)) {
         case 3:
@@ -230,6 +241,7 @@
         res->operands[0] = rDest;
         res->operands[1] = rSrc;
     }
+    setupResourceMasks(res);
     return res;
 }
 
@@ -249,9 +261,10 @@
     else
          opCode = THUMB_MOV_RR_L2H;
 
-    res->operands[0] = rDest & THUMB_REG_MASK;
-    res->operands[1] = rSrc & THUMB_REG_MASK;
+    res->operands[0] = rDest;
+    res->operands[1] = rSrc;
     res->opCode = opCode;
+    setupResourceMasks(res);
     if (rDest == rSrc) {
         res->isNop = true;
     }
@@ -348,6 +361,7 @@
     loadPcRel->opCode = THUMB_LDR_PC_REL;
     loadPcRel->generic.target = (LIR *) dataTarget;
     loadPcRel->operands[0] = rDest;
+    setupResourceMasks(loadPcRel);
     res = loadPcRel;
     dvmCompilerAppendLIR(cUnit, (LIR *) loadPcRel);
 
@@ -751,17 +765,17 @@
     ArmOpCode opCode = THUMB_BKPT;
     switch (op) {
         case OP_ADC:
-            opCode = (thumbForm) ? THUMB_ADC : THUMB2_ADC_RRR;
+            opCode = (thumbForm) ? THUMB_ADC_RR : THUMB2_ADC_RRR;
             break;
         case OP_AND:
             opCode = (thumbForm) ? THUMB_AND_RR : THUMB2_AND_RRR;
             break;
         case OP_BIC:
-            opCode = (thumbForm) ? THUMB_BIC : THUMB2_BIC_RRR;
+            opCode = (thumbForm) ? THUMB_BIC_RR : THUMB2_BIC_RRR;
             break;
         case OP_CMN:
             assert(shift == 0);
-            opCode = (thumbForm) ? THUMB_CMN : THUMB2_CMN_RR;
+            opCode = (thumbForm) ? THUMB_CMN_RR : THUMB2_CMN_RR;
             break;
         case OP_CMP:
             if (thumbForm)
@@ -772,15 +786,11 @@
                 opCode = THUMB_CMP_LH;
             else if (shift == 0)
                 opCode = THUMB_CMP_HL;
-            if (shift == 0) {
-                rDestSrc1 &= THUMB_REG_MASK;
-                rSrc2 &= THUMB_REG_MASK;
-            } else {
+            else
                 opCode = THUMB2_CMP_RR;
-            }
             break;
         case OP_XOR:
-            opCode = (thumbForm) ? THUMB_EOR : THUMB2_EOR_RRR;
+            opCode = (thumbForm) ? THUMB_EOR_RR : THUMB2_EOR_RRR;
             break;
         case OP_MOV:
             assert(shift == 0);
@@ -792,8 +802,6 @@
                 opCode = THUMB_MOV_RR_H2L;
             else
                 opCode = THUMB_MOV_RR_L2H;
-            rDestSrc1 &= THUMB_REG_MASK;
-            rSrc2 &= THUMB_REG_MASK;
             break;
         case OP_MUL:
             assert(shift == 0);
@@ -817,19 +825,19 @@
             break;
         case OP_LSL:
             assert(shift == 0);
-            opCode = (thumbForm) ? THUMB_LSLV : THUMB2_LSLV_RRR;
+            opCode = (thumbForm) ? THUMB_LSL_RR : THUMB2_LSL_RRR;
             break;
         case OP_LSR:
             assert(shift == 0);
-            opCode = (thumbForm) ? THUMB_LSRV : THUMB2_LSRV_RRR;
+            opCode = (thumbForm) ? THUMB_LSR_RR : THUMB2_LSR_RRR;
             break;
         case OP_ASR:
             assert(shift == 0);
-            opCode = (thumbForm) ? THUMB_ASRV : THUMB2_ASRV_RRR;
+            opCode = (thumbForm) ? THUMB_ASR_RR : THUMB2_ASR_RRR;
             break;
         case OP_ROR:
             assert(shift == 0);
-            opCode = (thumbForm) ? THUMB_RORV : THUMB2_RORV_RRR;
+            opCode = (thumbForm) ? THUMB_ROR_RR : THUMB2_ROR_RRR;
             break;
         case OP_ADD:
             opCode = (thumbForm) ? THUMB_ADD_RRR : THUMB2_ADD_RRR;
@@ -956,19 +964,19 @@
             break;
         case OP_LSL:
             assert(shift == 0);
-            opCode = THUMB2_LSLV_RRR;
+            opCode = THUMB2_LSL_RRR;
             break;
         case OP_LSR:
             assert(shift == 0);
-            opCode = THUMB2_LSRV_RRR;
+            opCode = THUMB2_LSR_RRR;
             break;
         case OP_ASR:
             assert(shift == 0);
-            opCode = THUMB2_ASRV_RRR;
+            opCode = THUMB2_ASR_RRR;
             break;
         case OP_ROR:
             assert(shift == 0);
-            opCode = THUMB2_RORV_RRR;
+            opCode = THUMB2_ROR_RRR;
             break;
         default:
             assert(0);
@@ -1004,26 +1012,28 @@
     switch(op) {
         case OP_LSL:
             if (allLowRegs)
-                return newLIR3(cUnit, THUMB_LSL, rDest, rSrc1, value);
+                return newLIR3(cUnit, THUMB_LSL_RRI5, rDest, rSrc1, value);
             else
                 return newLIR3(cUnit, THUMB2_LSL_RRI5, rDest, rSrc1, value);
         case OP_LSR:
             if (allLowRegs)
-                return newLIR3(cUnit, THUMB_LSR, rDest, rSrc1, value);
+                return newLIR3(cUnit, THUMB_LSR_RRI5, rDest, rSrc1, value);
             else
                 return newLIR3(cUnit, THUMB2_LSR_RRI5, rDest, rSrc1, value);
         case OP_ASR:
             if (allLowRegs)
-                return newLIR3(cUnit, THUMB_ASR, rDest, rSrc1, value);
+                return newLIR3(cUnit, THUMB_ASR_RRI5, rDest, rSrc1, value);
             else
                 return newLIR3(cUnit, THUMB2_ASR_RRI5, rDest, rSrc1, value);
         case OP_ROR:
             return newLIR3(cUnit, THUMB2_ROR_RRI5, rDest, rSrc1, value);
         case OP_ADD:
-            if (LOWREG(rDest) && (rSrc1 == 13) && (value <= 1020) && ((value & 0x3)==0)) {
+            if (LOWREG(rDest) && (rSrc1 == 13) &&
+                (value <= 1020) && ((value & 0x3)==0)) {
                 return newLIR3(cUnit, THUMB_ADD_SP_REL, rDest, rSrc1,
                                value >> 2);
-            } else if (LOWREG(rDest) && (rSrc1 == rpc) && (value <= 1020) && ((value & 0x3)==0)) {
+            } else if (LOWREG(rDest) && (rSrc1 == rpc) &&
+                       (value <= 1020) && ((value & 0x3)==0)) {
                 return newLIR3(cUnit, THUMB_ADD_PC_REL, rDest, rSrc1,
                                value >> 2);
             }
@@ -1129,6 +1139,7 @@
     branch1->generic.target = (LIR *) genIT(cUnit, ARM_COND_HI, "E");
     newLIR2(cUnit, THUMB2_MOV_IMM_SHIFT, r7, modifiedImmediate(-1));
     newLIR2(cUnit, THUMB_MOV_IMM, r7, 1);
+    genITBottom(cUnit);
 
     branch2->generic.target = (LIR *) opRegReg(cUnit, OP_NEG, r7, r7);
     branch1->generic.target = (LIR *) storeValue(cUnit, r7, vDest, r4PC);
@@ -1268,6 +1279,7 @@
     //TODO: need assertion mechanism to validate IT region size
     genIT(cUnit, (isMin) ? ARM_COND_GT : ARM_COND_LT, "");
     opRegReg(cUnit, OP_MOV, reg0, reg1);
+    genITBottom(cUnit);
     if (vDest >= 0)
         storeValue(cUnit, reg0, vDest, reg1);
     else
diff --git a/vm/compiler/codegen/arm/ThumbUtil.c b/vm/compiler/codegen/arm/ThumbUtil.c
index 0be1621..ccc75cb 100644
--- a/vm/compiler/codegen/arm/ThumbUtil.c
+++ b/vm/compiler/codegen/arm/ThumbUtil.c
@@ -188,12 +188,11 @@
          opCode = THUMB_MOV_RR_H2L;
     else
          opCode = THUMB_MOV_RR_L2H;
-    rDest &= THUMB_REG_MASK;
-    rSrc &= THUMB_REG_MASK;
 
-    res->operands[0] = rDest & THUMB_REG_MASK;
-    res->operands[1] = rSrc & THUMB_REG_MASK;
+    res->operands[0] = rDest;
+    res->operands[1] = rSrc;
     res->opCode = opCode;
+    setupResourceMasks(res);
     if (rDest == rSrc) {
         res->isNop = true;
     }
@@ -224,6 +223,7 @@
     loadPcRel->opCode = THUMB_LDR_PC_REL;
     loadPcRel->generic.target = (LIR *) dataTarget;
     loadPcRel->operands[0] = rDest;
+    setupResourceMasks(loadPcRel);
     res = loadPcRel;
     dvmCompilerAppendLIR(cUnit, (LIR *) loadPcRel);
 
@@ -530,22 +530,22 @@
     ArmOpCode opCode = THUMB_BKPT;
     switch (op) {
         case OP_ADC:
-            opCode = THUMB_ADC;
+            opCode = THUMB_ADC_RR;
             break;
         case OP_AND:
             opCode = THUMB_AND_RR;
             break;
         case OP_BIC:
-            opCode = THUMB_BIC;
+            opCode = THUMB_BIC_RR;
             break;
         case OP_CMN:
-            opCode = THUMB_CMN;
+            opCode = THUMB_CMN_RR;
             break;
         case OP_CMP:
             opCode = THUMB_CMP_RR;
             break;
         case OP_XOR:
-            opCode = THUMB_EOR;
+            opCode = THUMB_EOR_RR;
             break;
         case OP_MOV:
             if (LOWREG(rDestSrc1) && LOWREG(rSrc2))
@@ -556,8 +556,6 @@
                 opCode = THUMB_MOV_RR_H2L;
             else
                 opCode = THUMB_MOV_RR_L2H;
-            rDestSrc1 &= THUMB_REG_MASK;
-            rSrc2 &= THUMB_REG_MASK;
             break;
         case OP_MUL:
             opCode = THUMB_MUL;
@@ -578,16 +576,16 @@
             opCode = THUMB_TST;
             break;
         case OP_LSL:
-            opCode = THUMB_LSLV;
+            opCode = THUMB_LSL_RR;
             break;
         case OP_LSR:
-            opCode = THUMB_LSRV;
+            opCode = THUMB_LSR_RRR;
             break;
         case OP_ASR:
-            opCode = THUMB_ASRV;
+            opCode = THUMB_ASR_RR;
             break;
         case OP_ROR:
-            opCode = THUMB_RORV;
+            opCode = THUMB_ROR_RR;
         case OP_ADD:
         case OP_SUB:
             return opRegRegReg(cUnit, op, rDestSrc1, rDestSrc1, rSrc2);
@@ -727,15 +725,15 @@
             break;
         case OP_LSL:
                 shortForm = (!neg && value <= 31);
-                opCode = THUMB_LSL;
+                opCode = THUMB_LSL_RRI5;
                 break;
         case OP_LSR:
                 shortForm = (!neg && value <= 31);
-                opCode = THUMB_LSR;
+                opCode = THUMB_LSR_RRI5;
                 break;
         case OP_ASR:
                 shortForm = (!neg && value <= 31);
-                opCode = THUMB_ASR;
+                opCode = THUMB_ASR_RRI5;
                 break;
         case OP_MUL:
         case OP_AND:
@@ -824,9 +822,9 @@
     int sign = NEXT_REG(reg0);
     /* abs(x) = y<=x>>31, (x+y)^y.  Shorter in ARM/THUMB2, no skip in THUMB */
     loadValue(cUnit, dInsn->arg[0], reg0);
-    newLIR3(cUnit, THUMB_ASR, sign, reg0, 31);
+    newLIR3(cUnit, THUMB_ASR_RRI5, sign, reg0, 31);
     newLIR3(cUnit, THUMB_ADD_RRR, reg0, reg0, sign);
-    newLIR2(cUnit, THUMB_EOR, reg0, sign);
+    newLIR2(cUnit, THUMB_EOR_RR, reg0, sign);
     storeWordDisp(cUnit, rGLUE, offset, reg0, sign);
     return false;
 }
@@ -887,11 +885,11 @@
     int sign = NEXT_REG(ophi);
     /* abs(x) = y<=x>>31, (x+y)^y.  Shorter in ARM/THUMB2, no skip in THUMB */
     loadValuePair(cUnit, dInsn->arg[0], oplo, ophi);
-    newLIR3(cUnit, THUMB_ASR, sign, ophi, 31);
+    newLIR3(cUnit, THUMB_ASR_RRI5, sign, ophi, 31);
     newLIR3(cUnit, THUMB_ADD_RRR, oplo, oplo, sign);
-    newLIR2(cUnit, THUMB_ADC, ophi, sign);
-    newLIR2(cUnit, THUMB_EOR, oplo, sign);
-    newLIR2(cUnit, THUMB_EOR, ophi, sign);
+    newLIR2(cUnit, THUMB_ADC_RR, ophi, sign);
+    newLIR2(cUnit, THUMB_EOR_RR, oplo, sign);
+    newLIR2(cUnit, THUMB_EOR_RR, ophi, sign);
     storeWordDisp(cUnit, rGLUE, offset, oplo, sign);
     storeWordDisp(cUnit, rGLUE, offset + 4, ophi, sign);
     return false;