diff options
-rw-r--r-- | vm/Globals.h | 3 | ||||
-rw-r--r-- | vm/Init.c | 3 | ||||
-rw-r--r-- | vm/compiler/Compiler.c | 6 | ||||
-rw-r--r-- | vm/compiler/CompilerIR.h | 2 | ||||
-rw-r--r-- | vm/compiler/IntermediateRep.c | 14 | ||||
-rw-r--r-- | vm/compiler/Utility.c | 6 | ||||
-rw-r--r-- | vm/compiler/codegen/Optimizer.h | 9 | ||||
-rw-r--r-- | vm/compiler/codegen/arm/ArchUtility.c | 6 | ||||
-rw-r--r-- | vm/compiler/codegen/arm/ArmLIR.h | 128 | ||||
-rw-r--r-- | vm/compiler/codegen/arm/Assemble.c | 350 | ||||
-rw-r--r-- | vm/compiler/codegen/arm/Codegen.c | 94 | ||||
-rw-r--r-- | vm/compiler/codegen/arm/Codegen.h | 1 | ||||
-rw-r--r-- | vm/compiler/codegen/arm/LocalOptimizations.c | 145 | ||||
-rw-r--r-- | vm/compiler/codegen/arm/Thumb2Util.c | 64 | ||||
-rw-r--r-- | vm/compiler/codegen/arm/ThumbUtil.c | 44 |
15 files changed, 600 insertions, 275 deletions
diff --git a/vm/Globals.h b/vm/Globals.h index c94a57814..23b7497b0 100644 --- a/vm/Globals.h +++ b/vm/Globals.h @@ -748,6 +748,9 @@ struct DvmJitGlobals { /* 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; @@ -120,6 +120,7 @@ static void dvmUsage(const char* progName) "(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 @@ static int dvmProcessOptions(int argc, const char* const argv[], 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 203a08020..47881cadd 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 @@ bool dvmCompilerStartup(void) /* 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 948f3e75b..d5f60b684 100644 --- a/vm/compiler/CompilerIR.h +++ b/vm/compiler/CompilerIR.h @@ -152,6 +152,8 @@ void dvmCompilerAppendLIR(CompilationUnit *cUnit, LIR *lir); 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 a8bfda096..018d8907a 100644 --- a/vm/compiler/IntermediateRep.c +++ b/vm/compiler/IntermediateRep.c @@ -90,3 +90,17 @@ void dvmCompilerInsertLIRBefore(LIR *currentLIR, LIR *newLIR) 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 1ad1e27a5..cbfea1672 100644 --- a/vm/compiler/Utility.c +++ b/vm/compiler/Utility.c @@ -203,8 +203,10 @@ void dvmCompilerDumpStats(void) 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 432b36898..0931df3d0 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 ab46b449a..551e1f753 100644 --- a/vm/compiler/codegen/arm/ArchUtility.c +++ b/vm/compiler/codegen/arm/ArchUtility.c @@ -204,6 +204,9 @@ static void dumpLIRInsn(LIR *arg, unsigned char *baseAddr) 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 @@ void dvmCompilerCodegenDump(CompilationUnit *cUnit) 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 be793d693..20fb6bf66 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 @@ typedef enum ArmConditionCode { * 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 @@ typedef enum ArmOpCode { 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 @@ typedef enum ArmOpCode { 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 @@ typedef enum ArmOpCode { 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 @@ typedef enum ArmOpCode { 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 @@ typedef enum ArmOpCode { 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 @@ typedef enum ArmOpCode { [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 @@ typedef enum ArmOpCode { /* 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 @@ extern ArmEncodingMap EncodingMap[ARM_LAST]; /* * 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 @@ typedef struct ArmLIR { 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 6293fb298..4d7dadc36 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 @@ ArmEncodingMap EncodingMap[ARM_LAST] = { 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 @@ ArmEncodingMap EncodingMap[ARM_LAST] = { 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 @@ ArmEncodingMap EncodingMap[ARM_LAST] = { 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 @@ ArmEncodingMap EncodingMap[ARM_LAST] = { "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 @@ ArmEncodingMap EncodingMap[ARM_LAST] = { "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 @@ ArmEncodingMap EncodingMap[ARM_LAST] = { "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 @@ ArmEncodingMap EncodingMap[ARM_LAST] = { "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 3c28c7b08..8ae22af12 100644 --- a/vm/compiler/codegen/arm/Codegen.c +++ b/vm/compiler/codegen/arm/Codegen.c @@ -483,6 +483,91 @@ static void selfVerificationMemOpWrapper(CompilationUnit *cUnit, int regMap, #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 @@ static ArmLIR *newLIR0(CompilationUnit *cUnit, ArmOpCode opCode) 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 @@ static ArmLIR *newLIR1(CompilationUnit *cUnit, ArmOpCode opCode, 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 @@ static ArmLIR *newLIR2(CompilationUnit *cUnit, ArmOpCode opCode, insn->opCode = opCode; insn->operands[0] = dest; insn->operands[1] = src1; + setupResourceMasks(insn); dvmCompilerAppendLIR(cUnit, (LIR *) insn); return insn; } @@ -529,6 +617,7 @@ static ArmLIR *newLIR3(CompilationUnit *cUnit, ArmOpCode opCode, insn->operands[0] = dest; insn->operands[1] = src1; insn->operands[2] = src2; + setupResourceMasks(insn); dvmCompilerAppendLIR(cUnit, (LIR *) insn); return insn; } @@ -544,6 +633,7 @@ static ArmLIR *newLIR4(CompilationUnit *cUnit, ArmOpCode opCode, insn->operands[1] = src1; insn->operands[2] = src2; insn->operands[3] = info; + setupResourceMasks(insn); dvmCompilerAppendLIR(cUnit, (LIR *) insn); return insn; } @@ -3615,11 +3705,13 @@ static void setupLoopEntryBlock(CompilationUnit *cUnit, BasicBlock *entry, 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 @@ void dvmCompilerMIR2LIR(CompilationUnit *cUnit) (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 6da22eb5b..50a94fdd7 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 6f00b9e4c..fbc0e26f1 100644 --- a/vm/compiler/codegen/arm/LocalOptimizations.c +++ b/vm/compiler/codegen/arm/LocalOptimizations.c @@ -85,6 +85,11 @@ static void applyLoadStoreElimination(CompilationUnit *cUnit, 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 @@ static void applyLoadStoreElimination(CompilationUnit *cUnit, 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 @@ static void applyLoadStoreElimination(CompilationUnit *cUnit, 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 applyLoadStoreElimination(CompilationUnit *cUnit, } } +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 806bd02d0..b9d1a239e 100644 --- a/vm/compiler/codegen/arm/Thumb2Util.c +++ b/vm/compiler/codegen/arm/Thumb2Util.c @@ -172,6 +172,16 @@ static inline int selectFirstRegister(CompilationUnit *cUnit, int vSrc, } /* + * 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 @@ static ArmLIR *genIT(CompilationUnit *cUnit, ArmConditionCode code, int mask3 = 0; int mask2 = 0; int mask1 = 0; + //Note: case fallthroughs intentional switch(strlen(guide)) { case 3: @@ -230,6 +241,7 @@ static ArmLIR *fpRegCopy(CompilationUnit *cUnit, int rDest, int rSrc) res->operands[0] = rDest; res->operands[1] = rSrc; } + setupResourceMasks(res); return res; } @@ -249,9 +261,10 @@ ArmLIR* dvmCompilerRegCopy(CompilationUnit *cUnit, int rDest, int rSrc) 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 @@ static ArmLIR *loadConstant(CompilationUnit *cUnit, int rDest, int value) 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 @@ static ArmLIR *opRegRegShift(CompilationUnit *cUnit, OpKind op, int rDestSrc1, 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 @@ static ArmLIR *opRegRegShift(CompilationUnit *cUnit, OpKind op, int rDestSrc1, 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 @@ static ArmLIR *opRegRegShift(CompilationUnit *cUnit, OpKind op, int rDestSrc1, 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 @@ static ArmLIR *opRegRegShift(CompilationUnit *cUnit, OpKind op, int rDestSrc1, 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 @@ static ArmLIR *opRegRegRegShift(CompilationUnit *cUnit, OpKind op, 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 @@ static ArmLIR *opRegRegImm(CompilationUnit *cUnit, OpKind op, int rDest, 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 @@ static void genCmpLong(CompilationUnit *cUnit, MIR *mir, 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 @@ static bool genInlinedMinMaxInt(CompilationUnit *cUnit, MIR *mir, bool isMin) //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 0be162180..ccc75cb2f 100644 --- a/vm/compiler/codegen/arm/ThumbUtil.c +++ b/vm/compiler/codegen/arm/ThumbUtil.c @@ -188,12 +188,11 @@ ArmLIR* dvmCompilerRegCopy(CompilationUnit *cUnit, int rDest, int rSrc) 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 @@ static ArmLIR *loadConstant(CompilationUnit *cUnit, int rDest, int value) 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 @@ static ArmLIR *opRegReg(CompilationUnit *cUnit, OpKind op, int rDestSrc1, 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 @@ static ArmLIR *opRegReg(CompilationUnit *cUnit, OpKind op, int rDestSrc1, 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 @@ static ArmLIR *opRegReg(CompilationUnit *cUnit, OpKind op, int rDestSrc1, 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 @@ static ArmLIR *opRegRegImm(CompilationUnit *cUnit, OpKind op, int rDest, 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 @@ static bool genInlinedAbsInt(CompilationUnit *cUnit, MIR *mir) 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 @@ static bool genInlinedAbsLong(CompilationUnit *cUnit, MIR *mir) 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; |