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;