diff options
| author | 2012-05-03 15:00:40 -0700 | |
|---|---|---|
| committer | 2012-05-03 18:57:47 -0700 | |
| commit | a114add0300b95eeaae7465493f39144e07324e8 (patch) | |
| tree | 19b119195c00bd4688bb085eadbe142851f75e0e /src/compiler/codegen/arm/Thumb2 | |
| parent | 1ecce9487a1b3aac6b656f5704cf86a961ab0481 (diff) | |
[Compiler] use Art indentation standard
First of several CLs to bring code closer to alignment with Art and LLVM
standards. Move to 2-space indenting. Sticking with 80-col line
length (which LLVM apparently also wants). LLVM also prefers camel
case names, so keeping Dalvik convention there as well (for now).
Change-Id: I351ab234e640678d97747377cccdd6df0a770f4a
Diffstat (limited to 'src/compiler/codegen/arm/Thumb2')
| -rw-r--r-- | src/compiler/codegen/arm/Thumb2/Factory.cc | 1625 | ||||
| -rw-r--r-- | src/compiler/codegen/arm/Thumb2/Gen.cc | 1196 | ||||
| -rw-r--r-- | src/compiler/codegen/arm/Thumb2/Ralloc.cc | 144 |
3 files changed, 1477 insertions, 1488 deletions
diff --git a/src/compiler/codegen/arm/Thumb2/Factory.cc b/src/compiler/codegen/arm/Thumb2/Factory.cc index 0fe937ad98..533f8b4bcf 100644 --- a/src/compiler/codegen/arm/Thumb2/Factory.cc +++ b/src/compiler/codegen/arm/Thumb2/Factory.cc @@ -37,62 +37,62 @@ static int fpTemps[] = {fr0, fr1, fr2, fr3, fr4, fr5, fr6, fr7, int encodeImmSingle(int value) { - int res; - int bitA = (value & 0x80000000) >> 31; - int notBitB = (value & 0x40000000) >> 30; - int bitB = (value & 0x20000000) >> 29; - int bSmear = (value & 0x3e000000) >> 25; - int slice = (value & 0x01f80000) >> 19; - int zeroes = (value & 0x0007ffff); - if (zeroes != 0) - return -1; - if (bitB) { - if ((notBitB != 0) || (bSmear != 0x1f)) - return -1; - } else { - if ((notBitB != 1) || (bSmear != 0x0)) - return -1; - } - res = (bitA << 7) | (bitB << 6) | slice; - return res; + int res; + int bitA = (value & 0x80000000) >> 31; + int notBitB = (value & 0x40000000) >> 30; + int bitB = (value & 0x20000000) >> 29; + int bSmear = (value & 0x3e000000) >> 25; + int slice = (value & 0x01f80000) >> 19; + int zeroes = (value & 0x0007ffff); + if (zeroes != 0) + return -1; + if (bitB) { + if ((notBitB != 0) || (bSmear != 0x1f)) + return -1; + } else { + if ((notBitB != 1) || (bSmear != 0x0)) + return -1; + } + res = (bitA << 7) | (bitB << 6) | slice; + return res; } LIR* loadFPConstantValue(CompilationUnit* cUnit, int rDest, int value) { - int encodedImm = encodeImmSingle(value); - DCHECK(SINGLEREG(rDest)); - if (encodedImm >= 0) { - return newLIR2(cUnit, kThumb2Vmovs_IMM8, rDest, encodedImm); - } - LIR* dataTarget = scanLiteralPool(cUnit->literalList, value, 0); - if (dataTarget == NULL) { - dataTarget = addWordData(cUnit, &cUnit->literalList, value); - } - LIR* loadPcRel = rawLIR(cUnit, cUnit->currentDalvikOffset, kThumb2Vldrs, - rDest, r15pc, 0, 0, 0, dataTarget); - setMemRefType(loadPcRel, true, kLiteral); - loadPcRel->aliasInfo = (intptr_t)dataTarget; - oatAppendLIR(cUnit, (LIR* ) loadPcRel); - return loadPcRel; + int encodedImm = encodeImmSingle(value); + DCHECK(SINGLEREG(rDest)); + if (encodedImm >= 0) { + return newLIR2(cUnit, kThumb2Vmovs_IMM8, rDest, encodedImm); + } + LIR* dataTarget = scanLiteralPool(cUnit->literalList, value, 0); + if (dataTarget == NULL) { + dataTarget = addWordData(cUnit, &cUnit->literalList, value); + } + LIR* loadPcRel = rawLIR(cUnit, cUnit->currentDalvikOffset, kThumb2Vldrs, + rDest, r15pc, 0, 0, 0, dataTarget); + setMemRefType(loadPcRel, true, kLiteral); + loadPcRel->aliasInfo = (intptr_t)dataTarget; + oatAppendLIR(cUnit, (LIR* ) loadPcRel); + return loadPcRel; } int leadingZeros(u4 val) { - u4 alt; - int n; - int count; + u4 alt; + int n; + int count; - count = 16; - n = 32; - do { - alt = val >> count; - if (alt != 0) { - n = n - count; - val = alt; - } - count >>= 1; - } while (count); - return n - val; + count = 16; + n = 32; + do { + alt = val >> count; + if (alt != 0) { + n = n - count; + val = alt; + } + count >>= 1; + } while (count); + return n - val; } /* @@ -107,20 +107,20 @@ int modifiedImmediate(u4 value) /* Note: case of value==0 must use 0:000:0:0000000 encoding */ if (value <= 0xFF) - return b0; // 0:000:a:bcdefgh + return b0; // 0:000:a:bcdefgh if (value == ((b0 << 16) | b0)) - return (0x1 << 8) | b0; /* 0:001:a:bcdefgh */ + return (0x1 << 8) | b0; /* 0:001:a:bcdefgh */ if (value == ((b0 << 24) | (b0 << 16) | (b0 << 8) | b0)) - return (0x3 << 8) | b0; /* 0:011:a:bcdefgh */ + return (0x3 << 8) | b0; /* 0:011:a:bcdefgh */ b0 = (value >> 8) & 0xff; if (value == ((b0 << 24) | (b0 << 8))) - return (0x2 << 8) | b0; /* 0:010:a:bcdefgh */ + return (0x2 << 8) | b0; /* 0:010:a:bcdefgh */ /* Can we do it with rotation? */ zLeading = leadingZeros(value); zTrailing = 32 - leadingZeros(~value & (value - 1)); /* A run of eight or fewer active bits? */ if ((zLeading + zTrailing) < 24) - return -1; /* No - bail */ + return -1; /* No - bail */ /* left-justify the constant, discarding msb (known to be 1) */ value <<= zLeading + 1; /* Create bcdefgh */ @@ -139,443 +139,441 @@ int modifiedImmediate(u4 value) */ LIR* loadConstantNoClobber(CompilationUnit* cUnit, int rDest, int value) { - LIR* res; - int modImm; + LIR* res; + int modImm; - if (FPREG(rDest)) { - return loadFPConstantValue(cUnit, rDest, value); - } + if (FPREG(rDest)) { + return loadFPConstantValue(cUnit, rDest, value); + } - /* See if the value can be constructed cheaply */ - if (LOWREG(rDest) && (value >= 0) && (value <= 255)) { - return newLIR2(cUnit, kThumbMovImm, rDest, value); - } - /* Check Modified immediate special cases */ - modImm = modifiedImmediate(value); - if (modImm >= 0) { - res = newLIR2(cUnit, kThumb2MovImmShift, rDest, modImm); - return res; - } - modImm = modifiedImmediate(~value); - if (modImm >= 0) { - res = newLIR2(cUnit, kThumb2MvnImm12, rDest, modImm); - return res; - } - /* 16-bit immediate? */ - if ((value & 0xffff) == value) { - res = newLIR2(cUnit, kThumb2MovImm16, rDest, value); - return res; - } - /* No shortcut - go ahead and use literal pool */ - LIR* dataTarget = scanLiteralPool(cUnit->literalList, value, 0); - if (dataTarget == NULL) { - dataTarget = addWordData(cUnit, &cUnit->literalList, value); - } - LIR* loadPcRel = rawLIR(cUnit, cUnit->currentDalvikOffset, - kThumb2LdrPcRel12, rDest, 0, 0, 0, 0, dataTarget); - setMemRefType(loadPcRel, true, kLiteral); - loadPcRel->aliasInfo = (intptr_t)dataTarget; - res = loadPcRel; - oatAppendLIR(cUnit, (LIR* ) loadPcRel); - - /* - * To save space in the constant pool, we use the ADD_RRI8 instruction to - * add up to 255 to an existing constant value. - */ - if (dataTarget->operands[0] != value) { - opRegImm(cUnit, kOpAdd, rDest, value - dataTarget->operands[0]); - } + /* See if the value can be constructed cheaply */ + if (LOWREG(rDest) && (value >= 0) && (value <= 255)) { + return newLIR2(cUnit, kThumbMovImm, rDest, value); + } + /* Check Modified immediate special cases */ + modImm = modifiedImmediate(value); + if (modImm >= 0) { + res = newLIR2(cUnit, kThumb2MovImmShift, rDest, modImm); return res; + } + modImm = modifiedImmediate(~value); + if (modImm >= 0) { + res = newLIR2(cUnit, kThumb2MvnImm12, rDest, modImm); + return res; + } + /* 16-bit immediate? */ + if ((value & 0xffff) == value) { + res = newLIR2(cUnit, kThumb2MovImm16, rDest, value); + return res; + } + /* No shortcut - go ahead and use literal pool */ + LIR* dataTarget = scanLiteralPool(cUnit->literalList, value, 0); + if (dataTarget == NULL) { + dataTarget = addWordData(cUnit, &cUnit->literalList, value); + } + LIR* loadPcRel = rawLIR(cUnit, cUnit->currentDalvikOffset, + kThumb2LdrPcRel12, rDest, 0, 0, 0, 0, dataTarget); + setMemRefType(loadPcRel, true, kLiteral); + loadPcRel->aliasInfo = (intptr_t)dataTarget; + res = loadPcRel; + oatAppendLIR(cUnit, (LIR* ) loadPcRel); + + /* + * To save space in the constant pool, we use the ADD_RRI8 instruction to + * add up to 255 to an existing constant value. + */ + if (dataTarget->operands[0] != value) { + opRegImm(cUnit, kOpAdd, rDest, value - dataTarget->operands[0]); + } + return res; } LIR* opBranchUnconditional(CompilationUnit* cUnit, OpKind op) { - DCHECK_EQ(op, kOpUncondBr); - return newLIR1(cUnit, kThumbBUncond, 0 /* offset to be patched */); + DCHECK_EQ(op, kOpUncondBr); + return newLIR1(cUnit, kThumbBUncond, 0 /* offset to be patched */); } LIR* opCondBranch(CompilationUnit* cUnit, ConditionCode cc, LIR* target) { - LIR* branch = newLIR2(cUnit, kThumb2BCond, 0 /* offset to be patched */, - oatArmConditionEncoding(cc)); - branch->target = target; - return branch; + LIR* branch = newLIR2(cUnit, kThumb2BCond, 0 /* offset to be patched */, + oatArmConditionEncoding(cc)); + branch->target = target; + return branch; } LIR* opReg(CompilationUnit* cUnit, OpKind op, int rDestSrc) { - ArmOpcode opcode = kThumbBkpt; - switch (op) { - case kOpBlx: - opcode = kThumbBlxR; - break; - default: - LOG(FATAL) << "Bad opcode " << (int)op; - } - return newLIR1(cUnit, opcode, rDestSrc); + ArmOpcode opcode = kThumbBkpt; + switch (op) { + case kOpBlx: + opcode = kThumbBlxR; + break; + default: + LOG(FATAL) << "Bad opcode " << (int)op; + } + return newLIR1(cUnit, opcode, rDestSrc); } LIR* opRegRegShift(CompilationUnit* cUnit, OpKind op, int rDestSrc1, int rSrc2, int shift) { - bool thumbForm = ((shift == 0) && LOWREG(rDestSrc1) && LOWREG(rSrc2)); - ArmOpcode opcode = kThumbBkpt; - switch (op) { - case kOpAdc: - opcode = (thumbForm) ? kThumbAdcRR : kThumb2AdcRRR; - break; - case kOpAnd: - opcode = (thumbForm) ? kThumbAndRR : kThumb2AndRRR; - break; - case kOpBic: - opcode = (thumbForm) ? kThumbBicRR : kThumb2BicRRR; - break; - case kOpCmn: - DCHECK_EQ(shift, 0); - opcode = (thumbForm) ? kThumbCmnRR : kThumb2CmnRR; - break; - case kOpCmp: - if (thumbForm) - opcode = kThumbCmpRR; - else if ((shift == 0) && !LOWREG(rDestSrc1) && !LOWREG(rSrc2)) - opcode = kThumbCmpHH; - else if ((shift == 0) && LOWREG(rDestSrc1)) - opcode = kThumbCmpLH; - else if (shift == 0) - opcode = kThumbCmpHL; - else - opcode = kThumb2CmpRR; - break; - case kOpXor: - opcode = (thumbForm) ? kThumbEorRR : kThumb2EorRRR; - break; - case kOpMov: - DCHECK_EQ(shift, 0); - if (LOWREG(rDestSrc1) && LOWREG(rSrc2)) - opcode = kThumbMovRR; - else if (!LOWREG(rDestSrc1) && !LOWREG(rSrc2)) - opcode = kThumbMovRR_H2H; - else if (LOWREG(rDestSrc1)) - opcode = kThumbMovRR_H2L; - else - opcode = kThumbMovRR_L2H; - break; - case kOpMul: - DCHECK_EQ(shift, 0); - opcode = (thumbForm) ? kThumbMul : kThumb2MulRRR; - break; - case kOpMvn: - opcode = (thumbForm) ? kThumbMvn : kThumb2MnvRR; - break; - case kOpNeg: - DCHECK_EQ(shift, 0); - opcode = (thumbForm) ? kThumbNeg : kThumb2NegRR; - break; - case kOpOr: - opcode = (thumbForm) ? kThumbOrr : kThumb2OrrRRR; - break; - case kOpSbc: - opcode = (thumbForm) ? kThumbSbc : kThumb2SbcRRR; - break; - case kOpTst: - opcode = (thumbForm) ? kThumbTst : kThumb2TstRR; - break; - case kOpLsl: - DCHECK_EQ(shift, 0); - opcode = (thumbForm) ? kThumbLslRR : kThumb2LslRRR; - break; - case kOpLsr: - DCHECK_EQ(shift, 0); - opcode = (thumbForm) ? kThumbLsrRR : kThumb2LsrRRR; - break; - case kOpAsr: - DCHECK_EQ(shift, 0); - opcode = (thumbForm) ? kThumbAsrRR : kThumb2AsrRRR; - break; - case kOpRor: - DCHECK_EQ(shift, 0); - opcode = (thumbForm) ? kThumbRorRR : kThumb2RorRRR; - break; - case kOpAdd: - opcode = (thumbForm) ? kThumbAddRRR : kThumb2AddRRR; - break; - case kOpSub: - opcode = (thumbForm) ? kThumbSubRRR : kThumb2SubRRR; - break; - case kOp2Byte: - DCHECK_EQ(shift, 0); - return newLIR4(cUnit, kThumb2Sbfx, rDestSrc1, rSrc2, 0, 8); - case kOp2Short: - DCHECK_EQ(shift, 0); - return newLIR4(cUnit, kThumb2Sbfx, rDestSrc1, rSrc2, 0, 16); - case kOp2Char: - DCHECK_EQ(shift, 0); - return newLIR4(cUnit, kThumb2Ubfx, rDestSrc1, rSrc2, 0, 16); - default: - LOG(FATAL) << "Bad opcode: " << (int)op; - break; - } - DCHECK_GE(static_cast<int>(opcode), 0); - if (EncodingMap[opcode].flags & IS_BINARY_OP) - return newLIR2(cUnit, opcode, rDestSrc1, rSrc2); - else if (EncodingMap[opcode].flags & IS_TERTIARY_OP) { - if (EncodingMap[opcode].fieldLoc[2].kind == kFmtShift) - return newLIR3(cUnit, opcode, rDestSrc1, rSrc2, shift); - else - return newLIR3(cUnit, opcode, rDestSrc1, rDestSrc1, rSrc2); - } else if (EncodingMap[opcode].flags & IS_QUAD_OP) - return newLIR4(cUnit, opcode, rDestSrc1, rDestSrc1, rSrc2, shift); - else { - LOG(FATAL) << "Unexpected encoding operand count"; - return NULL; - } + bool thumbForm = ((shift == 0) && LOWREG(rDestSrc1) && LOWREG(rSrc2)); + ArmOpcode opcode = kThumbBkpt; + switch (op) { + case kOpAdc: + opcode = (thumbForm) ? kThumbAdcRR : kThumb2AdcRRR; + break; + case kOpAnd: + opcode = (thumbForm) ? kThumbAndRR : kThumb2AndRRR; + break; + case kOpBic: + opcode = (thumbForm) ? kThumbBicRR : kThumb2BicRRR; + break; + case kOpCmn: + DCHECK_EQ(shift, 0); + opcode = (thumbForm) ? kThumbCmnRR : kThumb2CmnRR; + break; + case kOpCmp: + if (thumbForm) + opcode = kThumbCmpRR; + else if ((shift == 0) && !LOWREG(rDestSrc1) && !LOWREG(rSrc2)) + opcode = kThumbCmpHH; + else if ((shift == 0) && LOWREG(rDestSrc1)) + opcode = kThumbCmpLH; + else if (shift == 0) + opcode = kThumbCmpHL; + else + opcode = kThumb2CmpRR; + break; + case kOpXor: + opcode = (thumbForm) ? kThumbEorRR : kThumb2EorRRR; + break; + case kOpMov: + DCHECK_EQ(shift, 0); + if (LOWREG(rDestSrc1) && LOWREG(rSrc2)) + opcode = kThumbMovRR; + else if (!LOWREG(rDestSrc1) && !LOWREG(rSrc2)) + opcode = kThumbMovRR_H2H; + else if (LOWREG(rDestSrc1)) + opcode = kThumbMovRR_H2L; + else + opcode = kThumbMovRR_L2H; + break; + case kOpMul: + DCHECK_EQ(shift, 0); + opcode = (thumbForm) ? kThumbMul : kThumb2MulRRR; + break; + case kOpMvn: + opcode = (thumbForm) ? kThumbMvn : kThumb2MnvRR; + break; + case kOpNeg: + DCHECK_EQ(shift, 0); + opcode = (thumbForm) ? kThumbNeg : kThumb2NegRR; + break; + case kOpOr: + opcode = (thumbForm) ? kThumbOrr : kThumb2OrrRRR; + break; + case kOpSbc: + opcode = (thumbForm) ? kThumbSbc : kThumb2SbcRRR; + break; + case kOpTst: + opcode = (thumbForm) ? kThumbTst : kThumb2TstRR; + break; + case kOpLsl: + DCHECK_EQ(shift, 0); + opcode = (thumbForm) ? kThumbLslRR : kThumb2LslRRR; + break; + case kOpLsr: + DCHECK_EQ(shift, 0); + opcode = (thumbForm) ? kThumbLsrRR : kThumb2LsrRRR; + break; + case kOpAsr: + DCHECK_EQ(shift, 0); + opcode = (thumbForm) ? kThumbAsrRR : kThumb2AsrRRR; + break; + case kOpRor: + DCHECK_EQ(shift, 0); + opcode = (thumbForm) ? kThumbRorRR : kThumb2RorRRR; + break; + case kOpAdd: + opcode = (thumbForm) ? kThumbAddRRR : kThumb2AddRRR; + break; + case kOpSub: + opcode = (thumbForm) ? kThumbSubRRR : kThumb2SubRRR; + break; + case kOp2Byte: + DCHECK_EQ(shift, 0); + return newLIR4(cUnit, kThumb2Sbfx, rDestSrc1, rSrc2, 0, 8); + case kOp2Short: + DCHECK_EQ(shift, 0); + return newLIR4(cUnit, kThumb2Sbfx, rDestSrc1, rSrc2, 0, 16); + case kOp2Char: + DCHECK_EQ(shift, 0); + return newLIR4(cUnit, kThumb2Ubfx, rDestSrc1, rSrc2, 0, 16); + default: + LOG(FATAL) << "Bad opcode: " << (int)op; + break; + } + DCHECK_GE(static_cast<int>(opcode), 0); + if (EncodingMap[opcode].flags & IS_BINARY_OP) + return newLIR2(cUnit, opcode, rDestSrc1, rSrc2); + else if (EncodingMap[opcode].flags & IS_TERTIARY_OP) { + if (EncodingMap[opcode].fieldLoc[2].kind == kFmtShift) + return newLIR3(cUnit, opcode, rDestSrc1, rSrc2, shift); + else + return newLIR3(cUnit, opcode, rDestSrc1, rDestSrc1, rSrc2); + } else if (EncodingMap[opcode].flags & IS_QUAD_OP) + return newLIR4(cUnit, opcode, rDestSrc1, rDestSrc1, rSrc2, shift); + else { + LOG(FATAL) << "Unexpected encoding operand count"; + return NULL; + } } LIR* opRegReg(CompilationUnit* cUnit, OpKind op, int rDestSrc1, int rSrc2) { - return opRegRegShift(cUnit, op, rDestSrc1, rSrc2, 0); + return opRegRegShift(cUnit, op, rDestSrc1, rSrc2, 0); } LIR* opRegRegRegShift(CompilationUnit* cUnit, OpKind op, int rDest, int rSrc1, - int rSrc2, int shift) + int rSrc2, int shift) { - ArmOpcode opcode = kThumbBkpt; - bool thumbForm = (shift == 0) && LOWREG(rDest) && LOWREG(rSrc1) && - LOWREG(rSrc2); - switch (op) { - case kOpAdd: - opcode = (thumbForm) ? kThumbAddRRR : kThumb2AddRRR; - break; - case kOpSub: - opcode = (thumbForm) ? kThumbSubRRR : kThumb2SubRRR; - break; - case kOpRsub: - opcode = kThumb2RsubRRR; - break; - case kOpAdc: - opcode = kThumb2AdcRRR; - break; - case kOpAnd: - opcode = kThumb2AndRRR; - break; - case kOpBic: - opcode = kThumb2BicRRR; - break; - case kOpXor: - opcode = kThumb2EorRRR; - break; - case kOpMul: - DCHECK_EQ(shift, 0); - opcode = kThumb2MulRRR; - break; - case kOpOr: - opcode = kThumb2OrrRRR; - break; - case kOpSbc: - opcode = kThumb2SbcRRR; - break; - case kOpLsl: - DCHECK_EQ(shift, 0); - opcode = kThumb2LslRRR; - break; - case kOpLsr: - DCHECK_EQ(shift, 0); - opcode = kThumb2LsrRRR; - break; - case kOpAsr: - DCHECK_EQ(shift, 0); - opcode = kThumb2AsrRRR; - break; - case kOpRor: - DCHECK_EQ(shift, 0); - opcode = kThumb2RorRRR; - break; - default: - LOG(FATAL) << "Bad opcode: " << (int)op; - break; - } - DCHECK_GE(static_cast<int>(opcode), 0); - if (EncodingMap[opcode].flags & IS_QUAD_OP) - return newLIR4(cUnit, opcode, rDest, rSrc1, rSrc2, shift); - else { - DCHECK(EncodingMap[opcode].flags & IS_TERTIARY_OP); - return newLIR3(cUnit, opcode, rDest, rSrc1, rSrc2); - } + ArmOpcode opcode = kThumbBkpt; + bool thumbForm = (shift == 0) && LOWREG(rDest) && LOWREG(rSrc1) && + LOWREG(rSrc2); + switch (op) { + case kOpAdd: + opcode = (thumbForm) ? kThumbAddRRR : kThumb2AddRRR; + break; + case kOpSub: + opcode = (thumbForm) ? kThumbSubRRR : kThumb2SubRRR; + break; + case kOpRsub: + opcode = kThumb2RsubRRR; + break; + case kOpAdc: + opcode = kThumb2AdcRRR; + break; + case kOpAnd: + opcode = kThumb2AndRRR; + break; + case kOpBic: + opcode = kThumb2BicRRR; + break; + case kOpXor: + opcode = kThumb2EorRRR; + break; + case kOpMul: + DCHECK_EQ(shift, 0); + opcode = kThumb2MulRRR; + break; + case kOpOr: + opcode = kThumb2OrrRRR; + break; + case kOpSbc: + opcode = kThumb2SbcRRR; + break; + case kOpLsl: + DCHECK_EQ(shift, 0); + opcode = kThumb2LslRRR; + break; + case kOpLsr: + DCHECK_EQ(shift, 0); + opcode = kThumb2LsrRRR; + break; + case kOpAsr: + DCHECK_EQ(shift, 0); + opcode = kThumb2AsrRRR; + break; + case kOpRor: + DCHECK_EQ(shift, 0); + opcode = kThumb2RorRRR; + break; + default: + LOG(FATAL) << "Bad opcode: " << (int)op; + break; + } + DCHECK_GE(static_cast<int>(opcode), 0); + if (EncodingMap[opcode].flags & IS_QUAD_OP) + return newLIR4(cUnit, opcode, rDest, rSrc1, rSrc2, shift); + else { + DCHECK(EncodingMap[opcode].flags & IS_TERTIARY_OP); + return newLIR3(cUnit, opcode, rDest, rSrc1, rSrc2); + } } LIR* opRegRegReg(CompilationUnit* cUnit, OpKind op, int rDest, int rSrc1, int rSrc2) { - return opRegRegRegShift(cUnit, op, rDest, rSrc1, rSrc2, 0); + return opRegRegRegShift(cUnit, op, rDest, rSrc1, rSrc2, 0); } LIR* opRegRegImm(CompilationUnit* cUnit, OpKind op, int rDest, int rSrc1, int value) { - LIR* res; - bool neg = (value < 0); - int absValue = (neg) ? -value : value; - ArmOpcode opcode = kThumbBkpt; - ArmOpcode altOpcode = kThumbBkpt; - bool allLowRegs = (LOWREG(rDest) && LOWREG(rSrc1)); - int modImm = modifiedImmediate(value); - int modImmNeg = modifiedImmediate(-value); + LIR* res; + bool neg = (value < 0); + int absValue = (neg) ? -value : value; + ArmOpcode opcode = kThumbBkpt; + ArmOpcode altOpcode = kThumbBkpt; + bool allLowRegs = (LOWREG(rDest) && LOWREG(rSrc1)); + int modImm = modifiedImmediate(value); + int modImmNeg = modifiedImmediate(-value); - switch (op) { - case kOpLsl: - if (allLowRegs) - return newLIR3(cUnit, kThumbLslRRI5, rDest, rSrc1, value); - else - return newLIR3(cUnit, kThumb2LslRRI5, rDest, rSrc1, value); - case kOpLsr: - if (allLowRegs) - return newLIR3(cUnit, kThumbLsrRRI5, rDest, rSrc1, value); - else - return newLIR3(cUnit, kThumb2LsrRRI5, rDest, rSrc1, value); - case kOpAsr: - if (allLowRegs) - return newLIR3(cUnit, kThumbAsrRRI5, rDest, rSrc1, value); - else - return newLIR3(cUnit, kThumb2AsrRRI5, rDest, rSrc1, value); - case kOpRor: - return newLIR3(cUnit, kThumb2RorRRI5, rDest, rSrc1, value); - case kOpAdd: - if (LOWREG(rDest) && (rSrc1 == r13sp) && - (value <= 1020) && ((value & 0x3)==0)) { - return newLIR3(cUnit, kThumbAddSpRel, rDest, rSrc1, - value >> 2); - } else if (LOWREG(rDest) && (rSrc1 == r15pc) && - (value <= 1020) && ((value & 0x3)==0)) { - return newLIR3(cUnit, kThumbAddPcRel, rDest, rSrc1, - value >> 2); - } - // Note: intentional fallthrough - case kOpSub: - if (allLowRegs && ((absValue & 0x7) == absValue)) { - if (op == kOpAdd) - opcode = (neg) ? kThumbSubRRI3 : kThumbAddRRI3; - else - opcode = (neg) ? kThumbAddRRI3 : kThumbSubRRI3; - return newLIR3(cUnit, opcode, rDest, rSrc1, absValue); - } else if ((absValue & 0xff) == absValue) { - if (op == kOpAdd) - opcode = (neg) ? kThumb2SubRRI12 : kThumb2AddRRI12; - else - opcode = (neg) ? kThumb2AddRRI12 : kThumb2SubRRI12; - return newLIR3(cUnit, opcode, rDest, rSrc1, absValue); - } - if (modImmNeg >= 0) { - op = (op == kOpAdd) ? kOpSub : kOpAdd; - modImm = modImmNeg; - } - if (op == kOpSub) { - opcode = kThumb2SubRRI8; - altOpcode = kThumb2SubRRR; - } else { - opcode = kThumb2AddRRI8; - altOpcode = kThumb2AddRRR; - } - break; - case kOpAdc: - opcode = kThumb2AdcRRI8; - altOpcode = kThumb2AdcRRR; - break; - case kOpSbc: - opcode = kThumb2SbcRRI8; - altOpcode = kThumb2SbcRRR; - break; - case kOpOr: - opcode = kThumb2OrrRRI8; - altOpcode = kThumb2OrrRRR; - break; - case kOpAnd: - opcode = kThumb2AndRRI8; - altOpcode = kThumb2AndRRR; - break; - case kOpXor: - opcode = kThumb2EorRRI8; - altOpcode = kThumb2EorRRR; - break; - case kOpMul: - //TUNING: power of 2, shift & add - modImm = -1; - altOpcode = kThumb2MulRRR; - break; - case kOpCmp: { - int modImm = modifiedImmediate(value); - LIR* res; - if (modImm >= 0) { - res = newLIR2(cUnit, kThumb2CmpRI8, rSrc1, modImm); - } else { - int rTmp = oatAllocTemp(cUnit); - res = loadConstant(cUnit, rTmp, value); - opRegReg(cUnit, kOpCmp, rSrc1, rTmp); - oatFreeTemp(cUnit, rTmp); - } - return res; - } - default: - LOG(FATAL) << "Bad opcode: " << (int)op; - } - - if (modImm >= 0) { - return newLIR3(cUnit, opcode, rDest, rSrc1, modImm); - } else { - int rScratch = oatAllocTemp(cUnit); - loadConstant(cUnit, rScratch, value); - if (EncodingMap[altOpcode].flags & IS_QUAD_OP) - res = newLIR4(cUnit, altOpcode, rDest, rSrc1, rScratch, 0); + switch (op) { + case kOpLsl: + if (allLowRegs) + return newLIR3(cUnit, kThumbLslRRI5, rDest, rSrc1, value); + else + return newLIR3(cUnit, kThumb2LslRRI5, rDest, rSrc1, value); + case kOpLsr: + if (allLowRegs) + return newLIR3(cUnit, kThumbLsrRRI5, rDest, rSrc1, value); + else + return newLIR3(cUnit, kThumb2LsrRRI5, rDest, rSrc1, value); + case kOpAsr: + if (allLowRegs) + return newLIR3(cUnit, kThumbAsrRRI5, rDest, rSrc1, value); + else + return newLIR3(cUnit, kThumb2AsrRRI5, rDest, rSrc1, value); + case kOpRor: + return newLIR3(cUnit, kThumb2RorRRI5, rDest, rSrc1, value); + case kOpAdd: + if (LOWREG(rDest) && (rSrc1 == r13sp) && + (value <= 1020) && ((value & 0x3)==0)) { + return newLIR3(cUnit, kThumbAddSpRel, rDest, rSrc1, value >> 2); + } else if (LOWREG(rDest) && (rSrc1 == r15pc) && + (value <= 1020) && ((value & 0x3)==0)) { + return newLIR3(cUnit, kThumbAddPcRel, rDest, rSrc1, value >> 2); + } + // Note: intentional fallthrough + case kOpSub: + if (allLowRegs && ((absValue & 0x7) == absValue)) { + if (op == kOpAdd) + opcode = (neg) ? kThumbSubRRI3 : kThumbAddRRI3; else - res = newLIR3(cUnit, altOpcode, rDest, rSrc1, rScratch); - oatFreeTemp(cUnit, rScratch); - return res; + opcode = (neg) ? kThumbAddRRI3 : kThumbSubRRI3; + return newLIR3(cUnit, opcode, rDest, rSrc1, absValue); + } else if ((absValue & 0xff) == absValue) { + if (op == kOpAdd) + opcode = (neg) ? kThumb2SubRRI12 : kThumb2AddRRI12; + else + opcode = (neg) ? kThumb2AddRRI12 : kThumb2SubRRI12; + return newLIR3(cUnit, opcode, rDest, rSrc1, absValue); + } + if (modImmNeg >= 0) { + op = (op == kOpAdd) ? kOpSub : kOpAdd; + modImm = modImmNeg; + } + if (op == kOpSub) { + opcode = kThumb2SubRRI8; + altOpcode = kThumb2SubRRR; + } else { + opcode = kThumb2AddRRI8; + altOpcode = kThumb2AddRRR; + } + break; + case kOpAdc: + opcode = kThumb2AdcRRI8; + altOpcode = kThumb2AdcRRR; + break; + case kOpSbc: + opcode = kThumb2SbcRRI8; + altOpcode = kThumb2SbcRRR; + break; + case kOpOr: + opcode = kThumb2OrrRRI8; + altOpcode = kThumb2OrrRRR; + break; + case kOpAnd: + opcode = kThumb2AndRRI8; + altOpcode = kThumb2AndRRR; + break; + case kOpXor: + opcode = kThumb2EorRRI8; + altOpcode = kThumb2EorRRR; + break; + case kOpMul: + //TUNING: power of 2, shift & add + modImm = -1; + altOpcode = kThumb2MulRRR; + break; + case kOpCmp: { + int modImm = modifiedImmediate(value); + LIR* res; + if (modImm >= 0) { + res = newLIR2(cUnit, kThumb2CmpRI8, rSrc1, modImm); + } else { + int rTmp = oatAllocTemp(cUnit); + res = loadConstant(cUnit, rTmp, value); + opRegReg(cUnit, kOpCmp, rSrc1, rTmp); + oatFreeTemp(cUnit, rTmp); + } + return res; } + default: + LOG(FATAL) << "Bad opcode: " << (int)op; + } + + if (modImm >= 0) { + return newLIR3(cUnit, opcode, rDest, rSrc1, modImm); + } else { + int rScratch = oatAllocTemp(cUnit); + loadConstant(cUnit, rScratch, value); + if (EncodingMap[altOpcode].flags & IS_QUAD_OP) + res = newLIR4(cUnit, altOpcode, rDest, rSrc1, rScratch, 0); + else + res = newLIR3(cUnit, altOpcode, rDest, rSrc1, rScratch); + oatFreeTemp(cUnit, rScratch); + return res; + } } /* Handle Thumb-only variants here - otherwise punt to opRegRegImm */ LIR* opRegImm(CompilationUnit* cUnit, OpKind op, int rDestSrc1, int value) { - bool neg = (value < 0); - int absValue = (neg) ? -value : value; - bool shortForm = (((absValue & 0xff) == absValue) && LOWREG(rDestSrc1)); - ArmOpcode opcode = kThumbBkpt; - switch (op) { - case kOpAdd: - if ( !neg && (rDestSrc1 == r13sp) && (value <= 508)) { /* sp */ - DCHECK_EQ((value & 0x3), 0); - return newLIR1(cUnit, kThumbAddSpI7, value >> 2); - } else if (shortForm) { - opcode = (neg) ? kThumbSubRI8 : kThumbAddRI8; - } - break; - case kOpSub: - if (!neg && (rDestSrc1 == r13sp) && (value <= 508)) { /* sp */ - DCHECK_EQ((value & 0x3), 0); - return newLIR1(cUnit, kThumbSubSpI7, value >> 2); - } else if (shortForm) { - opcode = (neg) ? kThumbAddRI8 : kThumbSubRI8; - } - break; - case kOpCmp: - if (LOWREG(rDestSrc1) && shortForm) - opcode = (shortForm) ? kThumbCmpRI8 : kThumbCmpRR; - else if (LOWREG(rDestSrc1)) - opcode = kThumbCmpRR; - else { - shortForm = false; - opcode = kThumbCmpHL; - } - break; - default: - /* Punt to opRegRegImm - if bad case catch it there */ - shortForm = false; - break; - } - if (shortForm) - return newLIR2(cUnit, opcode, rDestSrc1, absValue); - else { - return opRegRegImm(cUnit, op, rDestSrc1, rDestSrc1, value); - } + bool neg = (value < 0); + int absValue = (neg) ? -value : value; + bool shortForm = (((absValue & 0xff) == absValue) && LOWREG(rDestSrc1)); + ArmOpcode opcode = kThumbBkpt; + switch (op) { + case kOpAdd: + if ( !neg && (rDestSrc1 == r13sp) && (value <= 508)) { /* sp */ + DCHECK_EQ((value & 0x3), 0); + return newLIR1(cUnit, kThumbAddSpI7, value >> 2); + } else if (shortForm) { + opcode = (neg) ? kThumbSubRI8 : kThumbAddRI8; + } + break; + case kOpSub: + if (!neg && (rDestSrc1 == r13sp) && (value <= 508)) { /* sp */ + DCHECK_EQ((value & 0x3), 0); + return newLIR1(cUnit, kThumbSubSpI7, value >> 2); + } else if (shortForm) { + opcode = (neg) ? kThumbAddRI8 : kThumbSubRI8; + } + break; + case kOpCmp: + if (LOWREG(rDestSrc1) && shortForm) + opcode = (shortForm) ? kThumbCmpRI8 : kThumbCmpRR; + else if (LOWREG(rDestSrc1)) + opcode = kThumbCmpRR; + else { + shortForm = false; + opcode = kThumbCmpHL; + } + break; + default: + /* Punt to opRegRegImm - if bad case catch it there */ + shortForm = false; + break; + } + if (shortForm) + return newLIR2(cUnit, opcode, rDestSrc1, absValue); + else { + return opRegRegImm(cUnit, op, rDestSrc1, rDestSrc1, value); + } } /* @@ -584,193 +582,191 @@ LIR* opRegImm(CompilationUnit* cUnit, OpKind op, int rDestSrc1, int value) */ int encodeImmDoubleHigh(int value) { - int res; - int bitA = (value & 0x80000000) >> 31; - int notBitB = (value & 0x40000000) >> 30; - int bitB = (value & 0x20000000) >> 29; - int bSmear = (value & 0x3fc00000) >> 22; - int slice = (value & 0x003f0000) >> 16; - int zeroes = (value & 0x0000ffff); - if (zeroes != 0) - return -1; - if (bitB) { - if ((notBitB != 0) || (bSmear != 0xff)) - return -1; - } else { - if ((notBitB != 1) || (bSmear != 0x0)) - return -1; - } - res = (bitA << 7) | (bitB << 6) | slice; - return res; + int res; + int bitA = (value & 0x80000000) >> 31; + int notBitB = (value & 0x40000000) >> 30; + int bitB = (value & 0x20000000) >> 29; + int bSmear = (value & 0x3fc00000) >> 22; + int slice = (value & 0x003f0000) >> 16; + int zeroes = (value & 0x0000ffff); + if (zeroes != 0) + return -1; + if (bitB) { + if ((notBitB != 0) || (bSmear != 0xff)) + return -1; + } else { + if ((notBitB != 1) || (bSmear != 0x0)) + return -1; + } + res = (bitA << 7) | (bitB << 6) | slice; + return res; } int encodeImmDouble(int valLo, int valHi) { - int res = -1; - if (valLo == 0) - res = encodeImmDoubleHigh(valHi); - return res; + int res = -1; + if (valLo == 0) + res = encodeImmDoubleHigh(valHi); + return res; } LIR* loadConstantValueWide(CompilationUnit* cUnit, int rDestLo, int rDestHi, - int valLo, int valHi) + int valLo, int valHi) { - int encodedImm = encodeImmDouble(valLo, valHi); - LIR* res; - if (FPREG(rDestLo)) { - if (encodedImm >= 0) { - res = newLIR2(cUnit, kThumb2Vmovd_IMM8, S2D(rDestLo, rDestHi), - encodedImm); - } else { - LIR* dataTarget = scanLiteralPoolWide(cUnit->literalList, valLo, - valHi); - if (dataTarget == NULL) { - dataTarget = addWideData(cUnit, &cUnit->literalList, valLo, - valHi); - } - LIR* loadPcRel = rawLIR(cUnit, cUnit->currentDalvikOffset, - kThumb2Vldrd, S2D(rDestLo, rDestHi), - r15pc, 0, 0, 0, dataTarget); - setMemRefType(loadPcRel, true, kLiteral); - loadPcRel->aliasInfo = (intptr_t)dataTarget; - oatAppendLIR(cUnit, (LIR* ) loadPcRel); - res = loadPcRel; - } + int encodedImm = encodeImmDouble(valLo, valHi); + LIR* res; + if (FPREG(rDestLo)) { + if (encodedImm >= 0) { + res = newLIR2(cUnit, kThumb2Vmovd_IMM8, S2D(rDestLo, rDestHi), + encodedImm); } else { - res = loadConstantNoClobber(cUnit, rDestLo, valLo); - loadConstantNoClobber(cUnit, rDestHi, valHi); + LIR* dataTarget = scanLiteralPoolWide(cUnit->literalList, valLo, valHi); + if (dataTarget == NULL) { + dataTarget = addWideData(cUnit, &cUnit->literalList, valLo, valHi); + } + LIR* loadPcRel = + rawLIR(cUnit, cUnit->currentDalvikOffset, kThumb2Vldrd, + S2D(rDestLo, rDestHi), r15pc, 0, 0, 0, dataTarget); + setMemRefType(loadPcRel, true, kLiteral); + loadPcRel->aliasInfo = (intptr_t)dataTarget; + oatAppendLIR(cUnit, (LIR* ) loadPcRel); + res = loadPcRel; } - return res; + } else { + res = loadConstantNoClobber(cUnit, rDestLo, valLo); + loadConstantNoClobber(cUnit, rDestHi, valHi); + } + return res; } int encodeShift(int code, int amount) { - return ((amount & 0x1f) << 2) | code; + return ((amount & 0x1f) << 2) | code; } LIR* loadBaseIndexed(CompilationUnit* cUnit, int rBase, int rIndex, int rDest, int scale, OpSize size) { - bool allLowRegs = LOWREG(rBase) && LOWREG(rIndex) && LOWREG(rDest); - LIR* load; - ArmOpcode opcode = kThumbBkpt; - bool thumbForm = (allLowRegs && (scale == 0)); - int regPtr; + bool allLowRegs = LOWREG(rBase) && LOWREG(rIndex) && LOWREG(rDest); + LIR* load; + ArmOpcode opcode = kThumbBkpt; + bool thumbForm = (allLowRegs && (scale == 0)); + int regPtr; - if (FPREG(rDest)) { - if (SINGLEREG(rDest)) { - DCHECK((size == kWord) || (size == kSingle)); - opcode = kThumb2Vldrs; - size = kSingle; - } else { - DCHECK(DOUBLEREG(rDest)); - DCHECK((size == kLong) || (size == kDouble)); - DCHECK((rDest & 0x1) == 0); - opcode = kThumb2Vldrd; - size = kDouble; - } + if (FPREG(rDest)) { + if (SINGLEREG(rDest)) { + DCHECK((size == kWord) || (size == kSingle)); + opcode = kThumb2Vldrs; + size = kSingle; } else { - if (size == kSingle) - size = kWord; + DCHECK(DOUBLEREG(rDest)); + DCHECK((size == kLong) || (size == kDouble)); + DCHECK((rDest & 0x1) == 0); + opcode = kThumb2Vldrd; + size = kDouble; } + } else { + if (size == kSingle) + size = kWord; + } - switch (size) { - case kDouble: // fall-through - case kSingle: - regPtr = oatAllocTemp(cUnit); - if (scale) { - newLIR4(cUnit, kThumb2AddRRR, regPtr, rBase, rIndex, - encodeShift(kArmLsl, scale)); - } else { - opRegRegReg(cUnit, kOpAdd, regPtr, rBase, rIndex); - } - load = newLIR3(cUnit, opcode, rDest, regPtr, 0); - oatFreeTemp(cUnit, regPtr); - return load; - case kWord: - opcode = (thumbForm) ? kThumbLdrRRR : kThumb2LdrRRR; - break; - case kUnsignedHalf: - opcode = (thumbForm) ? kThumbLdrhRRR : kThumb2LdrhRRR; - break; - case kSignedHalf: - opcode = (thumbForm) ? kThumbLdrshRRR : kThumb2LdrshRRR; - break; - case kUnsignedByte: - opcode = (thumbForm) ? kThumbLdrbRRR : kThumb2LdrbRRR; - break; - case kSignedByte: - opcode = (thumbForm) ? kThumbLdrsbRRR : kThumb2LdrsbRRR; - break; - default: - LOG(FATAL) << "Bad size: " << (int)size; - } - if (thumbForm) - load = newLIR3(cUnit, opcode, rDest, rBase, rIndex); - else - load = newLIR4(cUnit, opcode, rDest, rBase, rIndex, scale); + switch (size) { + case kDouble: // fall-through + case kSingle: + regPtr = oatAllocTemp(cUnit); + if (scale) { + newLIR4(cUnit, kThumb2AddRRR, regPtr, rBase, rIndex, + encodeShift(kArmLsl, scale)); + } else { + opRegRegReg(cUnit, kOpAdd, regPtr, rBase, rIndex); + } + load = newLIR3(cUnit, opcode, rDest, regPtr, 0); + oatFreeTemp(cUnit, regPtr); + return load; + case kWord: + opcode = (thumbForm) ? kThumbLdrRRR : kThumb2LdrRRR; + break; + case kUnsignedHalf: + opcode = (thumbForm) ? kThumbLdrhRRR : kThumb2LdrhRRR; + break; + case kSignedHalf: + opcode = (thumbForm) ? kThumbLdrshRRR : kThumb2LdrshRRR; + break; + case kUnsignedByte: + opcode = (thumbForm) ? kThumbLdrbRRR : kThumb2LdrbRRR; + break; + case kSignedByte: + opcode = (thumbForm) ? kThumbLdrsbRRR : kThumb2LdrsbRRR; + break; + default: + LOG(FATAL) << "Bad size: " << (int)size; + } + if (thumbForm) + load = newLIR3(cUnit, opcode, rDest, rBase, rIndex); + else + load = newLIR4(cUnit, opcode, rDest, rBase, rIndex, scale); - return load; + return load; } LIR* storeBaseIndexed(CompilationUnit* cUnit, int rBase, int rIndex, int rSrc, int scale, OpSize size) { - bool allLowRegs = LOWREG(rBase) && LOWREG(rIndex) && LOWREG(rSrc); - LIR* store; - ArmOpcode opcode = kThumbBkpt; - bool thumbForm = (allLowRegs && (scale == 0)); - int regPtr; + bool allLowRegs = LOWREG(rBase) && LOWREG(rIndex) && LOWREG(rSrc); + LIR* store; + ArmOpcode opcode = kThumbBkpt; + bool thumbForm = (allLowRegs && (scale == 0)); + int regPtr; - if (FPREG(rSrc)) { - if (SINGLEREG(rSrc)) { - DCHECK((size == kWord) || (size == kSingle)); - opcode = kThumb2Vstrs; - size = kSingle; - } else { - DCHECK(DOUBLEREG(rSrc)); - DCHECK((size == kLong) || (size == kDouble)); - DCHECK((rSrc & 0x1) == 0); - opcode = kThumb2Vstrd; - size = kDouble; - } + if (FPREG(rSrc)) { + if (SINGLEREG(rSrc)) { + DCHECK((size == kWord) || (size == kSingle)); + opcode = kThumb2Vstrs; + size = kSingle; } else { - if (size == kSingle) - size = kWord; + DCHECK(DOUBLEREG(rSrc)); + DCHECK((size == kLong) || (size == kDouble)); + DCHECK((rSrc & 0x1) == 0); + opcode = kThumb2Vstrd; + size = kDouble; } + } else { + if (size == kSingle) + size = kWord; + } - switch (size) { - case kDouble: // fall-through - case kSingle: - regPtr = oatAllocTemp(cUnit); - if (scale) { - newLIR4(cUnit, kThumb2AddRRR, regPtr, rBase, rIndex, - encodeShift(kArmLsl, scale)); - } else { - opRegRegReg(cUnit, kOpAdd, regPtr, rBase, rIndex); - } - store = newLIR3(cUnit, opcode, rSrc, regPtr, 0); - oatFreeTemp(cUnit, regPtr); - return store; - case kWord: - opcode = (thumbForm) ? kThumbStrRRR : kThumb2StrRRR; - break; - case kUnsignedHalf: - case kSignedHalf: - opcode = (thumbForm) ? kThumbStrhRRR : kThumb2StrhRRR; - break; - case kUnsignedByte: - case kSignedByte: - opcode = (thumbForm) ? kThumbStrbRRR : kThumb2StrbRRR; - break; - default: - LOG(FATAL) << "Bad size: " << (int)size; - } - if (thumbForm) - store = newLIR3(cUnit, opcode, rSrc, rBase, rIndex); - else - store = newLIR4(cUnit, opcode, rSrc, rBase, rIndex, scale); + switch (size) { + case kDouble: // fall-through + case kSingle: + regPtr = oatAllocTemp(cUnit); + if (scale) { + newLIR4(cUnit, kThumb2AddRRR, regPtr, rBase, rIndex, + encodeShift(kArmLsl, scale)); + } else { + opRegRegReg(cUnit, kOpAdd, regPtr, rBase, rIndex); + } + store = newLIR3(cUnit, opcode, rSrc, regPtr, 0); + oatFreeTemp(cUnit, regPtr); + return store; + case kWord: + opcode = (thumbForm) ? kThumbStrRRR : kThumb2StrRRR; + break; + case kUnsignedHalf: + case kSignedHalf: + opcode = (thumbForm) ? kThumbStrhRRR : kThumb2StrhRRR; + break; + case kUnsignedByte: + case kSignedByte: + opcode = (thumbForm) ? kThumbStrbRRR : kThumb2StrbRRR; + break; + default: + LOG(FATAL) << "Bad size: " << (int)size; + } + if (thumbForm) + store = newLIR3(cUnit, opcode, rSrc, rBase, rIndex); + else + store = newLIR4(cUnit, opcode, rSrc, rBase, rIndex, scale); - return store; + return store; } /* @@ -782,267 +778,266 @@ LIR* loadBaseDispBody(CompilationUnit* cUnit, MIR* mir, int rBase, int displacement, int rDest, int rDestHi, OpSize size, int sReg) { - LIR* res; - LIR* load; - ArmOpcode opcode = kThumbBkpt; - bool shortForm = false; - bool thumb2Form = (displacement < 4092 && displacement >= 0); - bool allLowRegs = (LOWREG(rBase) && LOWREG(rDest)); - int encodedDisp = displacement; - bool is64bit = false; - switch (size) { - case kDouble: - case kLong: - is64bit = true; - if (FPREG(rDest)) { - if (SINGLEREG(rDest)) { - DCHECK(FPREG(rDestHi)); - rDest = S2D(rDest, rDestHi); - } - opcode = kThumb2Vldrd; - if (displacement <= 1020) { - shortForm = true; - encodedDisp >>= 2; - } - break; - } else { - res = loadBaseDispBody(cUnit, mir, rBase, displacement, rDest, - -1, kWord, sReg); - loadBaseDispBody(cUnit, NULL, rBase, displacement + 4, rDestHi, - -1, kWord, INVALID_SREG); - return res; - } - case kSingle: - case kWord: - if (FPREG(rDest)) { - opcode = kThumb2Vldrs; - if (displacement <= 1020) { - shortForm = true; - encodedDisp >>= 2; - } - break; - } - if (LOWREG(rDest) && (rBase == r15pc) && - (displacement <= 1020) && (displacement >= 0)) { - shortForm = true; - encodedDisp >>= 2; - opcode = kThumbLdrPcRel; - } else if (LOWREG(rDest) && (rBase == r13sp) && - (displacement <= 1020) && (displacement >= 0)) { - shortForm = true; - encodedDisp >>= 2; - opcode = kThumbLdrSpRel; - } else if (allLowRegs && displacement < 128 && displacement >= 0) { - DCHECK_EQ((displacement & 0x3), 0); - shortForm = true; - encodedDisp >>= 2; - opcode = kThumbLdrRRI5; - } else if (thumb2Form) { - shortForm = true; - opcode = kThumb2LdrRRI12; - } - break; - case kUnsignedHalf: - if (allLowRegs && displacement < 64 && displacement >= 0) { - DCHECK_EQ((displacement & 0x1), 0); - shortForm = true; - encodedDisp >>= 1; - opcode = kThumbLdrhRRI5; - } else if (displacement < 4092 && displacement >= 0) { - shortForm = true; - opcode = kThumb2LdrhRRI12; - } - break; - case kSignedHalf: - if (thumb2Form) { - shortForm = true; - opcode = kThumb2LdrshRRI12; - } - break; - case kUnsignedByte: - if (allLowRegs && displacement < 32 && displacement >= 0) { - shortForm = true; - opcode = kThumbLdrbRRI5; - } else if (thumb2Form) { - shortForm = true; - opcode = kThumb2LdrbRRI12; - } - break; - case kSignedByte: - if (thumb2Form) { - shortForm = true; - opcode = kThumb2LdrsbRRI12; - } - break; - default: - LOG(FATAL) << "Bad size: " << (int)size; - } + LIR* res; + LIR* load; + ArmOpcode opcode = kThumbBkpt; + bool shortForm = false; + bool thumb2Form = (displacement < 4092 && displacement >= 0); + bool allLowRegs = (LOWREG(rBase) && LOWREG(rDest)); + int encodedDisp = displacement; + bool is64bit = false; + switch (size) { + case kDouble: + case kLong: + is64bit = true; + if (FPREG(rDest)) { + if (SINGLEREG(rDest)) { + DCHECK(FPREG(rDestHi)); + rDest = S2D(rDest, rDestHi); + } + opcode = kThumb2Vldrd; + if (displacement <= 1020) { + shortForm = true; + encodedDisp >>= 2; + } + break; + } else { + res = loadBaseDispBody(cUnit, mir, rBase, displacement, rDest, + -1, kWord, sReg); + loadBaseDispBody(cUnit, NULL, rBase, displacement + 4, rDestHi, + -1, kWord, INVALID_SREG); + return res; + } + case kSingle: + case kWord: + if (FPREG(rDest)) { + opcode = kThumb2Vldrs; + if (displacement <= 1020) { + shortForm = true; + encodedDisp >>= 2; + } + break; + } + if (LOWREG(rDest) && (rBase == r15pc) && + (displacement <= 1020) && (displacement >= 0)) { + shortForm = true; + encodedDisp >>= 2; + opcode = kThumbLdrPcRel; + } else if (LOWREG(rDest) && (rBase == r13sp) && + (displacement <= 1020) && (displacement >= 0)) { + shortForm = true; + encodedDisp >>= 2; + opcode = kThumbLdrSpRel; + } else if (allLowRegs && displacement < 128 && displacement >= 0) { + DCHECK_EQ((displacement & 0x3), 0); + shortForm = true; + encodedDisp >>= 2; + opcode = kThumbLdrRRI5; + } else if (thumb2Form) { + shortForm = true; + opcode = kThumb2LdrRRI12; + } + break; + case kUnsignedHalf: + if (allLowRegs && displacement < 64 && displacement >= 0) { + DCHECK_EQ((displacement & 0x1), 0); + shortForm = true; + encodedDisp >>= 1; + opcode = kThumbLdrhRRI5; + } else if (displacement < 4092 && displacement >= 0) { + shortForm = true; + opcode = kThumb2LdrhRRI12; + } + break; + case kSignedHalf: + if (thumb2Form) { + shortForm = true; + opcode = kThumb2LdrshRRI12; + } + break; + case kUnsignedByte: + if (allLowRegs && displacement < 32 && displacement >= 0) { + shortForm = true; + opcode = kThumbLdrbRRI5; + } else if (thumb2Form) { + shortForm = true; + opcode = kThumb2LdrbRRI12; + } + break; + case kSignedByte: + if (thumb2Form) { + shortForm = true; + opcode = kThumb2LdrsbRRI12; + } + break; + default: + LOG(FATAL) << "Bad size: " << (int)size; + } - if (shortForm) { - load = res = newLIR3(cUnit, opcode, rDest, rBase, encodedDisp); - } else { - int regOffset = oatAllocTemp(cUnit); - res = loadConstant(cUnit, regOffset, encodedDisp); - load = loadBaseIndexed(cUnit, rBase, regOffset, rDest, 0, size); - oatFreeTemp(cUnit, regOffset); - } + if (shortForm) { + load = res = newLIR3(cUnit, opcode, rDest, rBase, encodedDisp); + } else { + int regOffset = oatAllocTemp(cUnit); + res = loadConstant(cUnit, regOffset, encodedDisp); + load = loadBaseIndexed(cUnit, rBase, regOffset, rDest, 0, size); + oatFreeTemp(cUnit, regOffset); + } - // TODO: in future may need to differentiate Dalvik accesses w/ spills - if (rBase == rSP) { - annotateDalvikRegAccess(load, displacement >> 2, true /* isLoad */, is64bit); - } - return load; + // TODO: in future may need to differentiate Dalvik accesses w/ spills + if (rBase == rSP) { + annotateDalvikRegAccess(load, displacement >> 2, true /* isLoad */, is64bit); + } + return load; } LIR* loadBaseDisp(CompilationUnit* cUnit, MIR* mir, int rBase, int displacement, int rDest, OpSize size, int sReg) { - return loadBaseDispBody(cUnit, mir, rBase, displacement, rDest, -1, - size, sReg); + return loadBaseDispBody(cUnit, mir, rBase, displacement, rDest, -1, size, + sReg); } LIR* loadBaseDispWide(CompilationUnit* cUnit, MIR* mir, int rBase, int displacement, int rDestLo, int rDestHi, int sReg) { - return loadBaseDispBody(cUnit, mir, rBase, displacement, rDestLo, rDestHi, - kLong, sReg); + return loadBaseDispBody(cUnit, mir, rBase, displacement, rDestLo, rDestHi, + kLong, sReg); } LIR* storeBaseDispBody(CompilationUnit* cUnit, int rBase, int displacement, int rSrc, int rSrcHi, OpSize size) { - LIR* res, *store; - ArmOpcode opcode = kThumbBkpt; - bool shortForm = false; - bool thumb2Form = (displacement < 4092 && displacement >= 0); - bool allLowRegs = (LOWREG(rBase) && LOWREG(rSrc)); - int encodedDisp = displacement; - bool is64bit = false; - switch (size) { - case kLong: - case kDouble: - is64bit = true; - if (!FPREG(rSrc)) { - res = storeBaseDispBody(cUnit, rBase, displacement, rSrc, - -1, kWord); - storeBaseDispBody(cUnit, rBase, displacement + 4, rSrcHi, - -1, kWord); - return res; - } - if (SINGLEREG(rSrc)) { - DCHECK(FPREG(rSrcHi)); - rSrc = S2D(rSrc, rSrcHi); - } - opcode = kThumb2Vstrd; - if (displacement <= 1020) { - shortForm = true; - encodedDisp >>= 2; - } - break; - case kSingle: - case kWord: - if (FPREG(rSrc)) { - DCHECK(SINGLEREG(rSrc)); - opcode = kThumb2Vstrs; - if (displacement <= 1020) { - shortForm = true; - encodedDisp >>= 2; - } - break; - } - if (allLowRegs && displacement < 128 && displacement >= 0) { - DCHECK_EQ((displacement & 0x3), 0); - shortForm = true; - encodedDisp >>= 2; - opcode = kThumbStrRRI5; - } else if (thumb2Form) { - shortForm = true; - opcode = kThumb2StrRRI12; - } - break; - case kUnsignedHalf: - case kSignedHalf: - if (allLowRegs && displacement < 64 && displacement >= 0) { - DCHECK_EQ((displacement & 0x1), 0); - shortForm = true; - encodedDisp >>= 1; - opcode = kThumbStrhRRI5; - } else if (thumb2Form) { - shortForm = true; - opcode = kThumb2StrhRRI12; - } - break; - case kUnsignedByte: - case kSignedByte: - if (allLowRegs && displacement < 32 && displacement >= 0) { - shortForm = true; - opcode = kThumbStrbRRI5; - } else if (thumb2Form) { - shortForm = true; - opcode = kThumb2StrbRRI12; - } - break; - default: - LOG(FATAL) << "Bad size: " << (int)size; - } - if (shortForm) { - store = res = newLIR3(cUnit, opcode, rSrc, rBase, encodedDisp); - } else { - int rScratch = oatAllocTemp(cUnit); - res = loadConstant(cUnit, rScratch, encodedDisp); - store = storeBaseIndexed(cUnit, rBase, rScratch, rSrc, 0, size); - oatFreeTemp(cUnit, rScratch); - } + LIR* res, *store; + ArmOpcode opcode = kThumbBkpt; + bool shortForm = false; + bool thumb2Form = (displacement < 4092 && displacement >= 0); + bool allLowRegs = (LOWREG(rBase) && LOWREG(rSrc)); + int encodedDisp = displacement; + bool is64bit = false; + switch (size) { + case kLong: + case kDouble: + is64bit = true; + if (!FPREG(rSrc)) { + res = storeBaseDispBody(cUnit, rBase, displacement, rSrc, -1, kWord); + storeBaseDispBody(cUnit, rBase, displacement + 4, rSrcHi, -1, kWord); + return res; + } + if (SINGLEREG(rSrc)) { + DCHECK(FPREG(rSrcHi)); + rSrc = S2D(rSrc, rSrcHi); + } + opcode = kThumb2Vstrd; + if (displacement <= 1020) { + shortForm = true; + encodedDisp >>= 2; + } + break; + case kSingle: + case kWord: + if (FPREG(rSrc)) { + DCHECK(SINGLEREG(rSrc)); + opcode = kThumb2Vstrs; + if (displacement <= 1020) { + shortForm = true; + encodedDisp >>= 2; + } + break; + } + if (allLowRegs && displacement < 128 && displacement >= 0) { + DCHECK_EQ((displacement & 0x3), 0); + shortForm = true; + encodedDisp >>= 2; + opcode = kThumbStrRRI5; + } else if (thumb2Form) { + shortForm = true; + opcode = kThumb2StrRRI12; + } + break; + case kUnsignedHalf: + case kSignedHalf: + if (allLowRegs && displacement < 64 && displacement >= 0) { + DCHECK_EQ((displacement & 0x1), 0); + shortForm = true; + encodedDisp >>= 1; + opcode = kThumbStrhRRI5; + } else if (thumb2Form) { + shortForm = true; + opcode = kThumb2StrhRRI12; + } + break; + case kUnsignedByte: + case kSignedByte: + if (allLowRegs && displacement < 32 && displacement >= 0) { + shortForm = true; + opcode = kThumbStrbRRI5; + } else if (thumb2Form) { + shortForm = true; + opcode = kThumb2StrbRRI12; + } + break; + default: + LOG(FATAL) << "Bad size: " << (int)size; + } + if (shortForm) { + store = res = newLIR3(cUnit, opcode, rSrc, rBase, encodedDisp); + } else { + int rScratch = oatAllocTemp(cUnit); + res = loadConstant(cUnit, rScratch, encodedDisp); + store = storeBaseIndexed(cUnit, rBase, rScratch, rSrc, 0, size); + oatFreeTemp(cUnit, rScratch); + } - // TODO: In future, may need to differentiate Dalvik & spill accesses - if (rBase == rSP) { - annotateDalvikRegAccess(store, displacement >> 2, false /* isLoad */, is64bit); - } - return res; + // TODO: In future, may need to differentiate Dalvik & spill accesses + if (rBase == rSP) { + annotateDalvikRegAccess(store, displacement >> 2, false /* isLoad */, + is64bit); + } + return res; } LIR* storeBaseDisp(CompilationUnit* cUnit, int rBase, int displacement, int rSrc, OpSize size) { - return storeBaseDispBody(cUnit, rBase, displacement, rSrc, -1, size); + return storeBaseDispBody(cUnit, rBase, displacement, rSrc, -1, size); } LIR* storeBaseDispWide(CompilationUnit* cUnit, int rBase, int displacement, int rSrcLo, int rSrcHi) { - return storeBaseDispBody(cUnit, rBase, displacement, rSrcLo, rSrcHi, kLong); + return storeBaseDispBody(cUnit, rBase, displacement, rSrcLo, rSrcHi, kLong); } void storePair(CompilationUnit* cUnit, int base, int lowReg, int highReg) { - storeBaseDispWide(cUnit, base, 0, lowReg, highReg); + storeBaseDispWide(cUnit, base, 0, lowReg, highReg); } void loadPair(CompilationUnit* cUnit, int base, int lowReg, int highReg) { - loadBaseDispWide(cUnit, NULL, base, 0, lowReg, highReg, INVALID_SREG); + loadBaseDispWide(cUnit, NULL, base, 0, lowReg, highReg, INVALID_SREG); } LIR* fpRegCopy(CompilationUnit* cUnit, int rDest, int rSrc) { - int opcode; - DCHECK_EQ(DOUBLEREG(rDest), DOUBLEREG(rSrc)); - if (DOUBLEREG(rDest)) { - opcode = kThumb2Vmovd; + int opcode; + DCHECK_EQ(DOUBLEREG(rDest), DOUBLEREG(rSrc)); + if (DOUBLEREG(rDest)) { + opcode = kThumb2Vmovd; + } else { + if (SINGLEREG(rDest)) { + opcode = SINGLEREG(rSrc) ? kThumb2Vmovs : kThumb2Fmsr; } else { - if (SINGLEREG(rDest)) { - opcode = SINGLEREG(rSrc) ? kThumb2Vmovs : kThumb2Fmsr; - } else { - DCHECK(SINGLEREG(rSrc)); - opcode = kThumb2Fmrs; - } + DCHECK(SINGLEREG(rSrc)); + opcode = kThumb2Fmrs; } - LIR* res = rawLIR(cUnit, cUnit->currentDalvikOffset, opcode, rDest, rSrc); - if (!(cUnit->disableOpt & (1 << kSafeOptimizations)) && rDest == rSrc) { - res->flags.isNop = true; - } - return res; + } + LIR* res = rawLIR(cUnit, cUnit->currentDalvikOffset, opcode, rDest, rSrc); + if (!(cUnit->disableOpt & (1 << kSafeOptimizations)) && rDest == rSrc) { + res->flags.isNop = true; + } + return res; } diff --git a/src/compiler/codegen/arm/Thumb2/Gen.cc b/src/compiler/codegen/arm/Thumb2/Gen.cc index 5451d57e02..5252b495c1 100644 --- a/src/compiler/codegen/arm/Thumb2/Gen.cc +++ b/src/compiler/codegen/arm/Thumb2/Gen.cc @@ -31,8 +31,8 @@ namespace art { /* Return the position of an ssa name within the argument list */ int inPosition(CompilationUnit* cUnit, int sReg) { - int vReg = SRegToVReg(cUnit, sReg); - return vReg - cUnit->numRegs; + int vReg = SRegToVReg(cUnit, sReg); + return vReg - cUnit->numRegs; } /* @@ -42,27 +42,27 @@ int inPosition(CompilationUnit* cUnit, int sReg) */ RegLocation argLoc(CompilationUnit* cUnit, RegLocation loc) { - int argNum = inPosition(cUnit, loc.sRegLow); - if (loc.wide) { - if (argNum == 2) { - // Bad case - half in register, half in frame. Just punt - loc.location = kLocInvalid; - } else if (argNum < 2) { - loc.lowReg = rARG1 + argNum; - loc.highReg = loc.lowReg + 1; - loc.location = kLocPhysReg; - } else { - loc.location = kLocDalvikFrame; - } + int argNum = inPosition(cUnit, loc.sRegLow); + if (loc.wide) { + if (argNum == 2) { + // Bad case - half in register, half in frame. Just punt + loc.location = kLocInvalid; + } else if (argNum < 2) { + loc.lowReg = rARG1 + argNum; + loc.highReg = loc.lowReg + 1; + loc.location = kLocPhysReg; + } else { + loc.location = kLocDalvikFrame; + } + } else { + if (argNum < 3) { + loc.lowReg = rARG1 + argNum; + loc.location = kLocPhysReg; } else { - if (argNum < 3) { - loc.lowReg = rARG1 + argNum; - loc.location = kLocPhysReg; - } else { - loc.location = kLocDalvikFrame; - } + loc.location = kLocDalvikFrame; } - return loc; + } + return loc; } /* @@ -72,243 +72,241 @@ RegLocation argLoc(CompilationUnit* cUnit, RegLocation loc) */ RegLocation loadArg(CompilationUnit* cUnit, RegLocation loc) { - if (loc.location == kLocDalvikFrame) { - int start = (inPosition(cUnit, loc.sRegLow) + 1) * sizeof(uint32_t); - loc.lowReg = oatAllocTemp(cUnit); - loadWordDisp(cUnit, rSP, start, loc.lowReg); - if (loc.wide) { - loc.highReg = oatAllocTemp(cUnit); - loadWordDisp(cUnit, rSP, start + sizeof(uint32_t), loc.highReg); - } - loc.location = kLocPhysReg; + if (loc.location == kLocDalvikFrame) { + int start = (inPosition(cUnit, loc.sRegLow) + 1) * sizeof(uint32_t); + loc.lowReg = oatAllocTemp(cUnit); + loadWordDisp(cUnit, rSP, start, loc.lowReg); + if (loc.wide) { + loc.highReg = oatAllocTemp(cUnit); + loadWordDisp(cUnit, rSP, start + sizeof(uint32_t), loc.highReg); } - return loc; + loc.location = kLocPhysReg; + } + return loc; } /* Lock any referenced arguments that arrive in registers */ void lockLiveArgs(CompilationUnit* cUnit, MIR* mir) { - int firstIn = cUnit->numRegs; - const int numArgRegs = 3; // TODO: generalize & move to RegUtil.cc - for (int i = 0; i < mir->ssaRep->numUses; i++) { - int vReg = SRegToVReg(cUnit, mir->ssaRep->uses[i]); - int inPosition = vReg - firstIn; - if (inPosition < numArgRegs) { - oatLockTemp(cUnit, rARG1 + inPosition); - } + int firstIn = cUnit->numRegs; + const int numArgRegs = 3; // TODO: generalize & move to RegUtil.cc + for (int i = 0; i < mir->ssaRep->numUses; i++) { + int vReg = SRegToVReg(cUnit, mir->ssaRep->uses[i]); + int inPosition = vReg - firstIn; + if (inPosition < numArgRegs) { + oatLockTemp(cUnit, rARG1 + inPosition); } + } } /* Find the next MIR, which may be in a following basic block */ MIR* getNextMir(CompilationUnit* cUnit, BasicBlock** pBb, MIR* mir) { - BasicBlock* bb = *pBb; - MIR* origMir = mir; - while (bb != NULL) { - if (mir != NULL) { - mir = mir->next; - } - if (mir != NULL) { - return mir; - } else { - bb = bb->fallThrough; - *pBb = bb; - if (bb) { - mir = bb->firstMIRInsn; - if (mir != NULL) { - return mir; - } - } - } + BasicBlock* bb = *pBb; + MIR* origMir = mir; + while (bb != NULL) { + if (mir != NULL) { + mir = mir->next; + } + if (mir != NULL) { + return mir; + } else { + bb = bb->fallThrough; + *pBb = bb; + if (bb) { + mir = bb->firstMIRInsn; + if (mir != NULL) { + return mir; + } + } } - return origMir; + } + return origMir; } /* Used for the "printMe" listing */ void genPrintLabel(CompilationUnit *cUnit, MIR* mir) { - LIR* boundaryLIR; - /* Mark the beginning of a Dalvik instruction for line tracking */ - char* instStr = cUnit->printMe ? - oatGetDalvikDisassembly(cUnit, mir->dalvikInsn, "") : NULL; - boundaryLIR = newLIR1(cUnit, kPseudoDalvikByteCodeBoundary, - (intptr_t) instStr); - cUnit->boundaryMap.Put(mir->offset, boundaryLIR); - /* Don't generate the SSA annotation unless verbose mode is on */ - if (cUnit->printMe && mir->ssaRep) { - char* ssaString = oatGetSSAString(cUnit, mir->ssaRep); - newLIR1(cUnit, kPseudoSSARep, (int) ssaString); - } + LIR* boundaryLIR; + /* Mark the beginning of a Dalvik instruction for line tracking */ + char* instStr = cUnit->printMe ? + oatGetDalvikDisassembly(cUnit, mir->dalvikInsn, "") : NULL; + boundaryLIR = newLIR1(cUnit, kPseudoDalvikByteCodeBoundary, + (intptr_t) instStr); + cUnit->boundaryMap.Put(mir->offset, boundaryLIR); + /* Don't generate the SSA annotation unless verbose mode is on */ + if (cUnit->printMe && mir->ssaRep) { + char* ssaString = oatGetSSAString(cUnit, mir->ssaRep); + newLIR1(cUnit, kPseudoSSARep, (int) ssaString); + } } MIR* specialIGet(CompilationUnit* cUnit, BasicBlock** bb, MIR* mir, OpSize size, bool longOrDouble, bool isObject) { - int fieldOffset; - bool isVolatile; - uint32_t fieldIdx = mir->dalvikInsn.vC; - bool fastPath = fastInstance(cUnit, fieldIdx, fieldOffset, isVolatile, - false); - if (!fastPath || !(mir->optimizationFlags & MIR_IGNORE_NULL_CHECK)) { - return NULL; - } - RegLocation rlObj = oatGetSrc(cUnit, mir, 0); - lockLiveArgs(cUnit, mir); - rlObj = argLoc(cUnit, rlObj); - RegLocation rlDest; - if (longOrDouble) { - rlDest = oatGetReturnWide(cUnit, false); - } else { - rlDest = oatGetReturn(cUnit, false); - } - // Point of no return - no aborts after this - genPrintLabel(cUnit, mir); - rlObj = loadArg(cUnit, rlObj); - genIGet(cUnit, mir, size, rlDest, rlObj, longOrDouble, isObject); - return getNextMir(cUnit, bb, mir); + int fieldOffset; + bool isVolatile; + uint32_t fieldIdx = mir->dalvikInsn.vC; + bool fastPath = fastInstance(cUnit, fieldIdx, fieldOffset, isVolatile, false); + if (!fastPath || !(mir->optimizationFlags & MIR_IGNORE_NULL_CHECK)) { + return NULL; + } + RegLocation rlObj = oatGetSrc(cUnit, mir, 0); + lockLiveArgs(cUnit, mir); + rlObj = argLoc(cUnit, rlObj); + RegLocation rlDest; + if (longOrDouble) { + rlDest = oatGetReturnWide(cUnit, false); + } else { + rlDest = oatGetReturn(cUnit, false); + } + // Point of no return - no aborts after this + genPrintLabel(cUnit, mir); + rlObj = loadArg(cUnit, rlObj); + genIGet(cUnit, mir, size, rlDest, rlObj, longOrDouble, isObject); + return getNextMir(cUnit, bb, mir); } MIR* specialIPut(CompilationUnit* cUnit, BasicBlock** bb, MIR* mir, OpSize size, bool longOrDouble, bool isObject) { - int fieldOffset; - bool isVolatile; - uint32_t fieldIdx = mir->dalvikInsn.vC; - bool fastPath = fastInstance(cUnit, fieldIdx, fieldOffset, isVolatile, - false); - if (!fastPath || !(mir->optimizationFlags & MIR_IGNORE_NULL_CHECK)) { - return NULL; - } - RegLocation rlSrc; - RegLocation rlObj; - lockLiveArgs(cUnit, mir); - if (longOrDouble) { - rlSrc = oatGetSrcWide(cUnit, mir, 0, 1); - rlObj = oatGetSrc(cUnit, mir, 2); - } else { - rlSrc = oatGetSrc(cUnit, mir, 0); - rlObj = oatGetSrc(cUnit, mir, 1); - } - rlSrc = argLoc(cUnit, rlSrc); - rlObj = argLoc(cUnit, rlObj); - // Reject if source is split across registers & frame - if (rlObj.location == kLocInvalid) { - oatResetRegPool(cUnit); - return NULL; - } - // Point of no return - no aborts after this - genPrintLabel(cUnit, mir); - rlObj = loadArg(cUnit, rlObj); - rlSrc = loadArg(cUnit, rlSrc); - genIPut(cUnit, mir, size, rlSrc, rlObj, longOrDouble, isObject); - return getNextMir(cUnit, bb, mir); + int fieldOffset; + bool isVolatile; + uint32_t fieldIdx = mir->dalvikInsn.vC; + bool fastPath = fastInstance(cUnit, fieldIdx, fieldOffset, isVolatile, false); + if (!fastPath || !(mir->optimizationFlags & MIR_IGNORE_NULL_CHECK)) { + return NULL; + } + RegLocation rlSrc; + RegLocation rlObj; + lockLiveArgs(cUnit, mir); + if (longOrDouble) { + rlSrc = oatGetSrcWide(cUnit, mir, 0, 1); + rlObj = oatGetSrc(cUnit, mir, 2); + } else { + rlSrc = oatGetSrc(cUnit, mir, 0); + rlObj = oatGetSrc(cUnit, mir, 1); + } + rlSrc = argLoc(cUnit, rlSrc); + rlObj = argLoc(cUnit, rlObj); + // Reject if source is split across registers & frame + if (rlObj.location == kLocInvalid) { + oatResetRegPool(cUnit); + return NULL; + } + // Point of no return - no aborts after this + genPrintLabel(cUnit, mir); + rlObj = loadArg(cUnit, rlObj); + rlSrc = loadArg(cUnit, rlSrc); + genIPut(cUnit, mir, size, rlSrc, rlObj, longOrDouble, isObject); + return getNextMir(cUnit, bb, mir); } MIR* specialIdentity(CompilationUnit* cUnit, MIR* mir) { - RegLocation rlSrc; - RegLocation rlDest; - bool wide = (mir->ssaRep->numUses == 2); - if (wide) { - rlSrc = oatGetSrcWide(cUnit, mir, 0, 1); - rlDest = oatGetReturnWide(cUnit, false); - } else { - rlSrc = oatGetSrc(cUnit, mir, 0); - rlDest = oatGetReturn(cUnit, false); - } - lockLiveArgs(cUnit, mir); - rlSrc = argLoc(cUnit, rlSrc); - if (rlSrc.location == kLocInvalid) { - oatResetRegPool(cUnit); - return NULL; - } - // Point of no return - no aborts after this - genPrintLabel(cUnit, mir); - rlSrc = loadArg(cUnit, rlSrc); - if (wide) { - storeValueWide(cUnit, rlDest, rlSrc); - } else { - storeValue(cUnit, rlDest, rlSrc); - } - return mir; + RegLocation rlSrc; + RegLocation rlDest; + bool wide = (mir->ssaRep->numUses == 2); + if (wide) { + rlSrc = oatGetSrcWide(cUnit, mir, 0, 1); + rlDest = oatGetReturnWide(cUnit, false); + } else { + rlSrc = oatGetSrc(cUnit, mir, 0); + rlDest = oatGetReturn(cUnit, false); + } + lockLiveArgs(cUnit, mir); + rlSrc = argLoc(cUnit, rlSrc); + if (rlSrc.location == kLocInvalid) { + oatResetRegPool(cUnit); + return NULL; + } + // Point of no return - no aborts after this + genPrintLabel(cUnit, mir); + rlSrc = loadArg(cUnit, rlSrc); + if (wide) { + storeValueWide(cUnit, rlDest, rlSrc); + } else { + storeValue(cUnit, rlDest, rlSrc); + } + return mir; } /* * Special-case code genration for simple non-throwing leaf methods. */ void genSpecialCase(CompilationUnit* cUnit, BasicBlock* bb, MIR* mir, - SpecialCaseHandler specialCase) + SpecialCaseHandler specialCase) { cUnit->currentDalvikOffset = mir->offset; MIR* nextMir = NULL; switch (specialCase) { - case kNullMethod: - DCHECK(mir->dalvikInsn.opcode == Instruction::RETURN_VOID); - nextMir = mir; - break; - case kConstFunction: - genPrintLabel(cUnit, mir); - loadConstant(cUnit, rRET0, mir->dalvikInsn.vB); - nextMir = getNextMir(cUnit, &bb, mir); - break; - case kIGet: - nextMir = specialIGet(cUnit, &bb, mir, kWord, false, false); - break; - case kIGetBoolean: - case kIGetByte: - nextMir = specialIGet(cUnit, &bb, mir, kUnsignedByte, false, false); - break; - case kIGetObject: - nextMir = specialIGet(cUnit, &bb, mir, kWord, false, true); - break; - case kIGetChar: - nextMir = specialIGet(cUnit, &bb, mir, kUnsignedHalf, false, false); - break; - case kIGetShort: - nextMir = specialIGet(cUnit, &bb, mir, kSignedHalf, false, false); - break; - case kIGetWide: - nextMir = specialIGet(cUnit, &bb, mir, kLong, true, false); - break; - case kIPut: - nextMir = specialIPut(cUnit, &bb, mir, kWord, false, false); - break; - case kIPutBoolean: - case kIPutByte: - nextMir = specialIPut(cUnit, &bb, mir, kUnsignedByte, false, false); - break; - case kIPutObject: - nextMir = specialIPut(cUnit, &bb, mir, kWord, false, true); - break; - case kIPutChar: - nextMir = specialIPut(cUnit, &bb, mir, kUnsignedHalf, false, false); - break; - case kIPutShort: - nextMir = specialIPut(cUnit, &bb, mir, kSignedHalf, false, false); - break; - case kIPutWide: - nextMir = specialIPut(cUnit, &bb, mir, kLong, true, false); - break; - case kIdentity: - nextMir = specialIdentity(cUnit, mir); - break; - default: - return; + case kNullMethod: + DCHECK(mir->dalvikInsn.opcode == Instruction::RETURN_VOID); + nextMir = mir; + break; + case kConstFunction: + genPrintLabel(cUnit, mir); + loadConstant(cUnit, rRET0, mir->dalvikInsn.vB); + nextMir = getNextMir(cUnit, &bb, mir); + break; + case kIGet: + nextMir = specialIGet(cUnit, &bb, mir, kWord, false, false); + break; + case kIGetBoolean: + case kIGetByte: + nextMir = specialIGet(cUnit, &bb, mir, kUnsignedByte, false, false); + break; + case kIGetObject: + nextMir = specialIGet(cUnit, &bb, mir, kWord, false, true); + break; + case kIGetChar: + nextMir = specialIGet(cUnit, &bb, mir, kUnsignedHalf, false, false); + break; + case kIGetShort: + nextMir = specialIGet(cUnit, &bb, mir, kSignedHalf, false, false); + break; + case kIGetWide: + nextMir = specialIGet(cUnit, &bb, mir, kLong, true, false); + break; + case kIPut: + nextMir = specialIPut(cUnit, &bb, mir, kWord, false, false); + break; + case kIPutBoolean: + case kIPutByte: + nextMir = specialIPut(cUnit, &bb, mir, kUnsignedByte, false, false); + break; + case kIPutObject: + nextMir = specialIPut(cUnit, &bb, mir, kWord, false, true); + break; + case kIPutChar: + nextMir = specialIPut(cUnit, &bb, mir, kUnsignedHalf, false, false); + break; + case kIPutShort: + nextMir = specialIPut(cUnit, &bb, mir, kSignedHalf, false, false); + break; + case kIPutWide: + nextMir = specialIPut(cUnit, &bb, mir, kLong, true, false); + break; + case kIdentity: + nextMir = specialIdentity(cUnit, mir); + break; + default: + return; } if (nextMir != NULL) { - cUnit->currentDalvikOffset = nextMir->offset; - if (specialCase != kIdentity) { - genPrintLabel(cUnit, nextMir); - } - newLIR1(cUnit, kThumbBx, rLR); - cUnit->coreSpillMask = 0; - cUnit->numCoreSpills = 0; - cUnit->fpSpillMask = 0; - cUnit->numFPSpills = 0; - cUnit->frameSize = 0; - cUnit->coreVmapTable.clear(); - cUnit->fpVmapTable.clear(); + cUnit->currentDalvikOffset = nextMir->offset; + if (specialCase != kIdentity) { + genPrintLabel(cUnit, nextMir); } + newLIR1(cUnit, kThumbBx, rLR); + cUnit->coreSpillMask = 0; + cUnit->numCoreSpills = 0; + cUnit->fpSpillMask = 0; + cUnit->numFPSpills = 0; + cUnit->frameSize = 0; + cUnit->coreVmapTable.clear(); + cUnit->fpVmapTable.clear(); + } } /* @@ -323,30 +321,30 @@ void genSpecialCase(CompilationUnit* cUnit, BasicBlock* bb, MIR* mir, */ LIR* opIT(CompilationUnit* cUnit, ArmConditionCode code, const char* guide) { - int mask; - int condBit = code & 1; - int altBit = condBit ^ 1; - int mask3 = 0; - int mask2 = 0; - int mask1 = 0; - - //Note: case fallthroughs intentional - switch (strlen(guide)) { - case 3: - mask1 = (guide[2] == 'T') ? condBit : altBit; - case 2: - mask2 = (guide[1] == 'T') ? condBit : altBit; - case 1: - mask3 = (guide[0] == 'T') ? condBit : altBit; - break; - case 0: - break; - default: - LOG(FATAL) << "OAT: bad case in opIT"; - } - mask = (mask3 << 3) | (mask2 << 2) | (mask1 << 1) | - (1 << (3 - strlen(guide))); - return newLIR2(cUnit, kThumb2It, code, mask); + int mask; + int condBit = code & 1; + int altBit = condBit ^ 1; + int mask3 = 0; + int mask2 = 0; + int mask1 = 0; + + //Note: case fallthroughs intentional + switch (strlen(guide)) { + case 3: + mask1 = (guide[2] == 'T') ? condBit : altBit; + case 2: + mask2 = (guide[1] == 'T') ? condBit : altBit; + case 1: + mask3 = (guide[0] == 'T') ? condBit : altBit; + break; + case 0: + break; + default: + LOG(FATAL) << "OAT: bad case in opIT"; + } + mask = (mask3 << 3) | (mask2 << 2) | (mask1 << 1) | + (1 << (3 - strlen(guide))); + return newLIR2(cUnit, kThumb2It, code, mask); } /* @@ -371,97 +369,95 @@ LIR* opIT(CompilationUnit* cUnit, ArmConditionCode code, const char* guide) void genSparseSwitch(CompilationUnit* cUnit, MIR* mir, RegLocation rlSrc, LIR* labelList) { - const u2* table = cUnit->insns + mir->offset + mir->dalvikInsn.vB; - if (cUnit->printMe) { - dumpSparseSwitchTable(table); - } - // Add the table to the list - we'll process it later - SwitchTable *tabRec = (SwitchTable *)oatNew(cUnit, sizeof(SwitchTable), - true, kAllocData); - tabRec->table = table; - tabRec->vaddr = mir->offset; - int size = table[1]; - tabRec->targets = (LIR* *)oatNew(cUnit, size * sizeof(LIR*), true, - kAllocLIR); - oatInsertGrowableList(cUnit, &cUnit->switchTables, (intptr_t)tabRec); - - // Get the switch value - rlSrc = loadValue(cUnit, rlSrc, kCoreReg); - int rBase = oatAllocTemp(cUnit); - /* Allocate key and disp temps */ - int rKey = oatAllocTemp(cUnit); - int rDisp = oatAllocTemp(cUnit); - // Make sure rKey's register number is less than rDisp's number for ldmia - if (rKey > rDisp) { - int tmp = rDisp; - rDisp = rKey; - rKey = tmp; - } - // Materialize a pointer to the switch table - newLIR3(cUnit, kThumb2Adr, rBase, 0, (intptr_t)tabRec); - // Set up rIdx - int rIdx = oatAllocTemp(cUnit); - loadConstant(cUnit, rIdx, size); - // Establish loop branch target - LIR* target = newLIR0(cUnit, kPseudoTargetLabel); - // Load next key/disp - newLIR2(cUnit, kThumb2LdmiaWB, rBase, (1 << rKey) | (1 << rDisp)); - opRegReg(cUnit, kOpCmp, rKey, rlSrc.lowReg); - // Go if match. NOTE: No instruction set switch here - must stay Thumb2 - opIT(cUnit, kArmCondEq, ""); - LIR* switchBranch = newLIR1(cUnit, kThumb2AddPCR, rDisp); - tabRec->anchor = switchBranch; - // Needs to use setflags encoding here - newLIR3(cUnit, kThumb2SubsRRI12, rIdx, rIdx, 1); - opCondBranch(cUnit, kCondNe, target); + const u2* table = cUnit->insns + mir->offset + mir->dalvikInsn.vB; + if (cUnit->printMe) { + dumpSparseSwitchTable(table); + } + // Add the table to the list - we'll process it later + SwitchTable *tabRec = (SwitchTable *)oatNew(cUnit, sizeof(SwitchTable), + true, kAllocData); + tabRec->table = table; + tabRec->vaddr = mir->offset; + int size = table[1]; + tabRec->targets = (LIR* *)oatNew(cUnit, size * sizeof(LIR*), true, kAllocLIR); + oatInsertGrowableList(cUnit, &cUnit->switchTables, (intptr_t)tabRec); + + // Get the switch value + rlSrc = loadValue(cUnit, rlSrc, kCoreReg); + int rBase = oatAllocTemp(cUnit); + /* Allocate key and disp temps */ + int rKey = oatAllocTemp(cUnit); + int rDisp = oatAllocTemp(cUnit); + // Make sure rKey's register number is less than rDisp's number for ldmia + if (rKey > rDisp) { + int tmp = rDisp; + rDisp = rKey; + rKey = tmp; + } + // Materialize a pointer to the switch table + newLIR3(cUnit, kThumb2Adr, rBase, 0, (intptr_t)tabRec); + // Set up rIdx + int rIdx = oatAllocTemp(cUnit); + loadConstant(cUnit, rIdx, size); + // Establish loop branch target + LIR* target = newLIR0(cUnit, kPseudoTargetLabel); + // Load next key/disp + newLIR2(cUnit, kThumb2LdmiaWB, rBase, (1 << rKey) | (1 << rDisp)); + opRegReg(cUnit, kOpCmp, rKey, rlSrc.lowReg); + // Go if match. NOTE: No instruction set switch here - must stay Thumb2 + opIT(cUnit, kArmCondEq, ""); + LIR* switchBranch = newLIR1(cUnit, kThumb2AddPCR, rDisp); + tabRec->anchor = switchBranch; + // Needs to use setflags encoding here + newLIR3(cUnit, kThumb2SubsRRI12, rIdx, rIdx, 1); + opCondBranch(cUnit, kCondNe, target); } void genPackedSwitch(CompilationUnit* cUnit, MIR* mir, RegLocation rlSrc) { - const u2* table = cUnit->insns + mir->offset + mir->dalvikInsn.vB; - if (cUnit->printMe) { - dumpPackedSwitchTable(table); - } - // Add the table to the list - we'll process it later - SwitchTable *tabRec = (SwitchTable *)oatNew(cUnit, sizeof(SwitchTable), - true, kAllocData); - tabRec->table = table; - tabRec->vaddr = mir->offset; - int size = table[1]; - tabRec->targets = (LIR* *)oatNew(cUnit, size * sizeof(LIR*), true, - kAllocLIR); - oatInsertGrowableList(cUnit, &cUnit->switchTables, (intptr_t)tabRec); - - // Get the switch value - rlSrc = loadValue(cUnit, rlSrc, kCoreReg); - int tableBase = oatAllocTemp(cUnit); - // Materialize a pointer to the switch table - newLIR3(cUnit, kThumb2Adr, tableBase, 0, (intptr_t)tabRec); - int lowKey = s4FromSwitchData(&table[2]); - int keyReg; - // Remove the bias, if necessary - if (lowKey == 0) { - keyReg = rlSrc.lowReg; - } else { - keyReg = oatAllocTemp(cUnit); - opRegRegImm(cUnit, kOpSub, keyReg, rlSrc.lowReg, lowKey); - } - // Bounds check - if < 0 or >= size continue following switch - opRegImm(cUnit, kOpCmp, keyReg, size-1); - LIR* branchOver = opCondBranch(cUnit, kCondHi, NULL); - - // Load the displacement from the switch table - int dispReg = oatAllocTemp(cUnit); - loadBaseIndexed(cUnit, tableBase, keyReg, dispReg, 2, kWord); - - // ..and go! NOTE: No instruction set switch here - must stay Thumb2 - LIR* switchBranch = newLIR1(cUnit, kThumb2AddPCR, dispReg); - tabRec->anchor = switchBranch; - - /* branchOver target here */ - LIR* target = newLIR0(cUnit, kPseudoTargetLabel); - branchOver->target = (LIR*)target; + const u2* table = cUnit->insns + mir->offset + mir->dalvikInsn.vB; + if (cUnit->printMe) { + dumpPackedSwitchTable(table); + } + // Add the table to the list - we'll process it later + SwitchTable *tabRec = (SwitchTable *)oatNew(cUnit, sizeof(SwitchTable), + true, kAllocData); + tabRec->table = table; + tabRec->vaddr = mir->offset; + int size = table[1]; + tabRec->targets = (LIR* *)oatNew(cUnit, size * sizeof(LIR*), true, kAllocLIR); + oatInsertGrowableList(cUnit, &cUnit->switchTables, (intptr_t)tabRec); + + // Get the switch value + rlSrc = loadValue(cUnit, rlSrc, kCoreReg); + int tableBase = oatAllocTemp(cUnit); + // Materialize a pointer to the switch table + newLIR3(cUnit, kThumb2Adr, tableBase, 0, (intptr_t)tabRec); + int lowKey = s4FromSwitchData(&table[2]); + int keyReg; + // Remove the bias, if necessary + if (lowKey == 0) { + keyReg = rlSrc.lowReg; + } else { + keyReg = oatAllocTemp(cUnit); + opRegRegImm(cUnit, kOpSub, keyReg, rlSrc.lowReg, lowKey); + } + // Bounds check - if < 0 or >= size continue following switch + opRegImm(cUnit, kOpCmp, keyReg, size-1); + LIR* branchOver = opCondBranch(cUnit, kCondHi, NULL); + + // Load the displacement from the switch table + int dispReg = oatAllocTemp(cUnit); + loadBaseIndexed(cUnit, tableBase, keyReg, dispReg, 2, kWord); + + // ..and go! NOTE: No instruction set switch here - must stay Thumb2 + LIR* switchBranch = newLIR1(cUnit, kThumb2AddPCR, dispReg); + tabRec->anchor = switchBranch; + + /* branchOver target here */ + LIR* target = newLIR0(cUnit, kPseudoTargetLabel); + branchOver->target = (LIR*)target; } /* @@ -476,46 +472,46 @@ void genPackedSwitch(CompilationUnit* cUnit, MIR* mir, RegLocation rlSrc) */ void genFillArrayData(CompilationUnit* cUnit, MIR* mir, RegLocation rlSrc) { - const u2* table = cUnit->insns + mir->offset + mir->dalvikInsn.vB; - // Add the table to the list - we'll process it later - FillArrayData *tabRec = (FillArrayData *) - oatNew(cUnit, sizeof(FillArrayData), true, kAllocData); - tabRec->table = table; - tabRec->vaddr = mir->offset; - u2 width = tabRec->table[1]; - u4 size = tabRec->table[2] | (((u4)tabRec->table[3]) << 16); - tabRec->size = (size * width) + 8; - - oatInsertGrowableList(cUnit, &cUnit->fillArrayData, (intptr_t)tabRec); - - // Making a call - use explicit registers - oatFlushAllRegs(cUnit); /* Everything to home location */ - loadValueDirectFixed(cUnit, rlSrc, r0); - loadWordDisp(cUnit, rSELF, - ENTRYPOINT_OFFSET(pHandleFillArrayDataFromCode), rLR); - // Materialize a pointer to the fill data image - newLIR3(cUnit, kThumb2Adr, r1, 0, (intptr_t)tabRec); - oatClobberCalleeSave(cUnit); - opReg(cUnit, kOpBlx, rLR); + const u2* table = cUnit->insns + mir->offset + mir->dalvikInsn.vB; + // Add the table to the list - we'll process it later + FillArrayData *tabRec = (FillArrayData *) + oatNew(cUnit, sizeof(FillArrayData), true, kAllocData); + tabRec->table = table; + tabRec->vaddr = mir->offset; + u2 width = tabRec->table[1]; + u4 size = tabRec->table[2] | (((u4)tabRec->table[3]) << 16); + tabRec->size = (size * width) + 8; + + oatInsertGrowableList(cUnit, &cUnit->fillArrayData, (intptr_t)tabRec); + + // Making a call - use explicit registers + oatFlushAllRegs(cUnit); /* Everything to home location */ + loadValueDirectFixed(cUnit, rlSrc, r0); + loadWordDisp(cUnit, rSELF, ENTRYPOINT_OFFSET(pHandleFillArrayDataFromCode), + rLR); + // Materialize a pointer to the fill data image + newLIR3(cUnit, kThumb2Adr, r1, 0, (intptr_t)tabRec); + oatClobberCalleeSave(cUnit); + opReg(cUnit, kOpBlx, rLR); } void genNegFloat(CompilationUnit* cUnit, RegLocation rlDest, RegLocation rlSrc) { - RegLocation rlResult; - rlSrc = loadValue(cUnit, rlSrc, kFPReg); - rlResult = oatEvalLoc(cUnit, rlDest, kFPReg, true); - newLIR2(cUnit, kThumb2Vnegs, rlResult.lowReg, rlSrc.lowReg); - storeValue(cUnit, rlDest, rlResult); + RegLocation rlResult; + rlSrc = loadValue(cUnit, rlSrc, kFPReg); + rlResult = oatEvalLoc(cUnit, rlDest, kFPReg, true); + newLIR2(cUnit, kThumb2Vnegs, rlResult.lowReg, rlSrc.lowReg); + storeValue(cUnit, rlDest, rlResult); } void genNegDouble(CompilationUnit* cUnit, RegLocation rlDest, RegLocation rlSrc) { - RegLocation rlResult; - rlSrc = loadValueWide(cUnit, rlSrc, kFPReg); - rlResult = oatEvalLoc(cUnit, rlDest, kFPReg, true); - newLIR2(cUnit, kThumb2Vnegd, S2D(rlResult.lowReg, rlResult.highReg), - S2D(rlSrc.lowReg, rlSrc.highReg)); - storeValueWide(cUnit, rlDest, rlResult); + RegLocation rlResult; + rlSrc = loadValueWide(cUnit, rlSrc, kFPReg); + rlResult = oatEvalLoc(cUnit, rlDest, kFPReg, true); + newLIR2(cUnit, kThumb2Vnegd, S2D(rlResult.lowReg, rlResult.highReg), + S2D(rlSrc.lowReg, rlSrc.highReg)); + storeValueWide(cUnit, rlDest, rlResult); } /* @@ -546,31 +542,30 @@ void genNegDouble(CompilationUnit* cUnit, RegLocation rlDest, RegLocation rlSrc) */ void genMonitorEnter(CompilationUnit* cUnit, MIR* mir, RegLocation rlSrc) { - oatFlushAllRegs(cUnit); - DCHECK_EQ(LW_SHAPE_THIN, 0); - loadValueDirectFixed(cUnit, rlSrc, r0); // Get obj - oatLockCallTemps(cUnit); // Prepare for explicit register usage - genNullCheck(cUnit, rlSrc.sRegLow, r0, mir); - loadWordDisp(cUnit, rSELF, Thread::ThinLockIdOffset().Int32Value(), r2); - newLIR3(cUnit, kThumb2Ldrex, r1, r0, - Object::MonitorOffset().Int32Value() >> 2); // Get object->lock - // Align owner - opRegImm(cUnit, kOpLsl, r2, LW_LOCK_OWNER_SHIFT); - // Is lock unheld on lock or held by us (==threadId) on unlock? - newLIR4(cUnit, kThumb2Bfi, r2, r1, 0, LW_LOCK_OWNER_SHIFT - 1); - newLIR3(cUnit, kThumb2Bfc, r1, LW_HASH_STATE_SHIFT, LW_LOCK_OWNER_SHIFT - 1); - opRegImm(cUnit, kOpCmp, r1, 0); - opIT(cUnit, kArmCondEq, ""); - newLIR4(cUnit, kThumb2Strex, r1, r2, r0, - Object::MonitorOffset().Int32Value() >> 2); - opRegImm(cUnit, kOpCmp, r1, 0); - opIT(cUnit, kArmCondNe, "T"); - // Go expensive route - artLockObjectFromCode(self, obj); - loadWordDisp(cUnit, rSELF, ENTRYPOINT_OFFSET(pLockObjectFromCode), - rLR); - oatClobberCalleeSave(cUnit); - opReg(cUnit, kOpBlx, rLR); - oatGenMemBarrier(cUnit, kSY); + oatFlushAllRegs(cUnit); + DCHECK_EQ(LW_SHAPE_THIN, 0); + loadValueDirectFixed(cUnit, rlSrc, r0); // Get obj + oatLockCallTemps(cUnit); // Prepare for explicit register usage + genNullCheck(cUnit, rlSrc.sRegLow, r0, mir); + loadWordDisp(cUnit, rSELF, Thread::ThinLockIdOffset().Int32Value(), r2); + newLIR3(cUnit, kThumb2Ldrex, r1, r0, + Object::MonitorOffset().Int32Value() >> 2); // Get object->lock + // Align owner + opRegImm(cUnit, kOpLsl, r2, LW_LOCK_OWNER_SHIFT); + // Is lock unheld on lock or held by us (==threadId) on unlock? + newLIR4(cUnit, kThumb2Bfi, r2, r1, 0, LW_LOCK_OWNER_SHIFT - 1); + newLIR3(cUnit, kThumb2Bfc, r1, LW_HASH_STATE_SHIFT, LW_LOCK_OWNER_SHIFT - 1); + opRegImm(cUnit, kOpCmp, r1, 0); + opIT(cUnit, kArmCondEq, ""); + newLIR4(cUnit, kThumb2Strex, r1, r2, r0, + Object::MonitorOffset().Int32Value() >> 2); + opRegImm(cUnit, kOpCmp, r1, 0); + opIT(cUnit, kArmCondNe, "T"); + // Go expensive route - artLockObjectFromCode(self, obj); + loadWordDisp(cUnit, rSELF, ENTRYPOINT_OFFSET(pLockObjectFromCode), rLR); + oatClobberCalleeSave(cUnit); + opReg(cUnit, kOpBlx, rLR); + oatGenMemBarrier(cUnit, kSY); } /* @@ -581,27 +576,27 @@ void genMonitorEnter(CompilationUnit* cUnit, MIR* mir, RegLocation rlSrc) */ void genMonitorExit(CompilationUnit* cUnit, MIR* mir, RegLocation rlSrc) { - DCHECK_EQ(LW_SHAPE_THIN, 0); - oatFlushAllRegs(cUnit); - loadValueDirectFixed(cUnit, rlSrc, r0); // Get obj - oatLockCallTemps(cUnit); // Prepare for explicit register usage - genNullCheck(cUnit, rlSrc.sRegLow, r0, mir); - loadWordDisp(cUnit, r0, Object::MonitorOffset().Int32Value(), r1); // Get lock - loadWordDisp(cUnit, rSELF, Thread::ThinLockIdOffset().Int32Value(), r2); - // Is lock unheld on lock or held by us (==threadId) on unlock? - opRegRegImm(cUnit, kOpAnd, r3, r1, (LW_HASH_STATE_MASK << LW_HASH_STATE_SHIFT)); - // Align owner - opRegImm(cUnit, kOpLsl, r2, LW_LOCK_OWNER_SHIFT); - newLIR3(cUnit, kThumb2Bfc, r1, LW_HASH_STATE_SHIFT, LW_LOCK_OWNER_SHIFT - 1); - opRegReg(cUnit, kOpSub, r1, r2); - opIT(cUnit, kArmCondEq, "EE"); - storeWordDisp(cUnit, r0, Object::MonitorOffset().Int32Value(), r3); - // Go expensive route - UnlockObjectFromCode(obj); - loadWordDisp(cUnit, rSELF, ENTRYPOINT_OFFSET(pUnlockObjectFromCode), - rLR); - oatClobberCalleeSave(cUnit); - opReg(cUnit, kOpBlx, rLR); - oatGenMemBarrier(cUnit, kSY); + DCHECK_EQ(LW_SHAPE_THIN, 0); + oatFlushAllRegs(cUnit); + loadValueDirectFixed(cUnit, rlSrc, r0); // Get obj + oatLockCallTemps(cUnit); // Prepare for explicit register usage + genNullCheck(cUnit, rlSrc.sRegLow, r0, mir); + loadWordDisp(cUnit, r0, Object::MonitorOffset().Int32Value(), r1); // Get lock + loadWordDisp(cUnit, rSELF, Thread::ThinLockIdOffset().Int32Value(), r2); + // Is lock unheld on lock or held by us (==threadId) on unlock? + opRegRegImm(cUnit, kOpAnd, r3, r1, + (LW_HASH_STATE_MASK << LW_HASH_STATE_SHIFT)); + // Align owner + opRegImm(cUnit, kOpLsl, r2, LW_LOCK_OWNER_SHIFT); + newLIR3(cUnit, kThumb2Bfc, r1, LW_HASH_STATE_SHIFT, LW_LOCK_OWNER_SHIFT - 1); + opRegReg(cUnit, kOpSub, r1, r2); + opIT(cUnit, kArmCondEq, "EE"); + storeWordDisp(cUnit, r0, Object::MonitorOffset().Int32Value(), r3); + // Go expensive route - UnlockObjectFromCode(obj); + loadWordDisp(cUnit, rSELF, ENTRYPOINT_OFFSET(pUnlockObjectFromCode), rLR); + oatClobberCalleeSave(cUnit); + opReg(cUnit, kOpBlx, rLR); + oatGenMemBarrier(cUnit, kSY); } /* @@ -620,83 +615,83 @@ void genMonitorExit(CompilationUnit* cUnit, MIR* mir, RegLocation rlSrc) * done: */ void genCmpLong(CompilationUnit* cUnit, MIR* mir, RegLocation rlDest, - RegLocation rlSrc1, RegLocation rlSrc2) + RegLocation rlSrc1, RegLocation rlSrc2) { - LIR* target1; - LIR* target2; - rlSrc1 = loadValueWide(cUnit, rlSrc1, kCoreReg); - rlSrc2 = loadValueWide(cUnit, rlSrc2, kCoreReg); - int tReg = oatAllocTemp(cUnit); - loadConstant(cUnit, tReg, -1); - opRegReg(cUnit, kOpCmp, rlSrc1.highReg, rlSrc2.highReg); - LIR* branch1 = opCondBranch(cUnit, kCondLt, NULL); - LIR* branch2 = opCondBranch(cUnit, kCondGt, NULL); - opRegRegReg(cUnit, kOpSub, tReg, rlSrc1.lowReg, rlSrc2.lowReg); - LIR* branch3 = opCondBranch(cUnit, kCondEq, NULL); - - opIT(cUnit, kArmCondHi, "E"); - newLIR2(cUnit, kThumb2MovImmShift, tReg, modifiedImmediate(-1)); - loadConstant(cUnit, tReg, 1); - genBarrier(cUnit); - - target2 = newLIR0(cUnit, kPseudoTargetLabel); - opRegReg(cUnit, kOpNeg, tReg, tReg); - - target1 = newLIR0(cUnit, kPseudoTargetLabel); - - RegLocation rlTemp = LOC_C_RETURN; // Just using as template, will change - rlTemp.lowReg = tReg; - storeValue(cUnit, rlDest, rlTemp); - oatFreeTemp(cUnit, tReg); - - branch1->target = (LIR*)target1; - branch2->target = (LIR*)target2; - branch3->target = branch1->target; + LIR* target1; + LIR* target2; + rlSrc1 = loadValueWide(cUnit, rlSrc1, kCoreReg); + rlSrc2 = loadValueWide(cUnit, rlSrc2, kCoreReg); + int tReg = oatAllocTemp(cUnit); + loadConstant(cUnit, tReg, -1); + opRegReg(cUnit, kOpCmp, rlSrc1.highReg, rlSrc2.highReg); + LIR* branch1 = opCondBranch(cUnit, kCondLt, NULL); + LIR* branch2 = opCondBranch(cUnit, kCondGt, NULL); + opRegRegReg(cUnit, kOpSub, tReg, rlSrc1.lowReg, rlSrc2.lowReg); + LIR* branch3 = opCondBranch(cUnit, kCondEq, NULL); + + opIT(cUnit, kArmCondHi, "E"); + newLIR2(cUnit, kThumb2MovImmShift, tReg, modifiedImmediate(-1)); + loadConstant(cUnit, tReg, 1); + genBarrier(cUnit); + + target2 = newLIR0(cUnit, kPseudoTargetLabel); + opRegReg(cUnit, kOpNeg, tReg, tReg); + + target1 = newLIR0(cUnit, kPseudoTargetLabel); + + RegLocation rlTemp = LOC_C_RETURN; // Just using as template, will change + rlTemp.lowReg = tReg; + storeValue(cUnit, rlDest, rlTemp); + oatFreeTemp(cUnit, tReg); + + branch1->target = (LIR*)target1; + branch2->target = (LIR*)target2; + branch3->target = branch1->target; } void genFusedLongCmpBranch(CompilationUnit* cUnit, BasicBlock* bb, MIR* mir) { - LIR* labelList = (LIR*)cUnit->blockLabelList; - LIR* taken = &labelList[bb->taken->id]; - LIR* notTaken = &labelList[bb->fallThrough->id]; - RegLocation rlSrc1 = oatGetSrcWide(cUnit, mir, 0, 1); - RegLocation rlSrc2 = oatGetSrcWide(cUnit, mir, 2, 3); - rlSrc1 = loadValueWide(cUnit, rlSrc1, kCoreReg); - rlSrc2 = loadValueWide(cUnit, rlSrc2, kCoreReg); - ConditionCode ccode = static_cast<ConditionCode>(mir->dalvikInsn.arg[0]); - opRegReg(cUnit, kOpCmp, rlSrc1.highReg, rlSrc2.highReg); - switch(ccode) { - case kCondEq: - opCondBranch(cUnit, kCondNe, notTaken); - break; - case kCondNe: - opCondBranch(cUnit, kCondNe, taken); - break; - case kCondLt: - opCondBranch(cUnit, kCondLt, taken); - opCondBranch(cUnit, kCondGt, notTaken); - ccode = kCondCc; - break; - case kCondLe: - opCondBranch(cUnit, kCondLt, taken); - opCondBranch(cUnit, kCondGt, notTaken); - ccode = kCondLs; - break; - case kCondGt: - opCondBranch(cUnit, kCondGt, taken); - opCondBranch(cUnit, kCondLt, notTaken); - ccode = kCondHi; - break; - case kCondGe: - opCondBranch(cUnit, kCondGt, taken); - opCondBranch(cUnit, kCondLt, notTaken); - ccode = kCondCs; - break; - default: - LOG(FATAL) << "Unexpected ccode: " << (int)ccode; - } - opRegReg(cUnit, kOpCmp, rlSrc1.lowReg, rlSrc2.lowReg); - opCondBranch(cUnit, ccode, taken); + LIR* labelList = (LIR*)cUnit->blockLabelList; + LIR* taken = &labelList[bb->taken->id]; + LIR* notTaken = &labelList[bb->fallThrough->id]; + RegLocation rlSrc1 = oatGetSrcWide(cUnit, mir, 0, 1); + RegLocation rlSrc2 = oatGetSrcWide(cUnit, mir, 2, 3); + rlSrc1 = loadValueWide(cUnit, rlSrc1, kCoreReg); + rlSrc2 = loadValueWide(cUnit, rlSrc2, kCoreReg); + ConditionCode ccode = static_cast<ConditionCode>(mir->dalvikInsn.arg[0]); + opRegReg(cUnit, kOpCmp, rlSrc1.highReg, rlSrc2.highReg); + switch(ccode) { + case kCondEq: + opCondBranch(cUnit, kCondNe, notTaken); + break; + case kCondNe: + opCondBranch(cUnit, kCondNe, taken); + break; + case kCondLt: + opCondBranch(cUnit, kCondLt, taken); + opCondBranch(cUnit, kCondGt, notTaken); + ccode = kCondCc; + break; + case kCondLe: + opCondBranch(cUnit, kCondLt, taken); + opCondBranch(cUnit, kCondGt, notTaken); + ccode = kCondLs; + break; + case kCondGt: + opCondBranch(cUnit, kCondGt, taken); + opCondBranch(cUnit, kCondLt, notTaken); + ccode = kCondHi; + break; + case kCondGe: + opCondBranch(cUnit, kCondGt, taken); + opCondBranch(cUnit, kCondLt, notTaken); + ccode = kCondCs; + break; + default: + LOG(FATAL) << "Unexpected ccode: " << (int)ccode; + } + opRegReg(cUnit, kOpCmp, rlSrc1.lowReg, rlSrc2.lowReg); + opCondBranch(cUnit, ccode, taken); } /* @@ -704,166 +699,165 @@ void genFusedLongCmpBranch(CompilationUnit* cUnit, BasicBlock* bb, MIR* mir) * is responsible for setting branch target field. */ LIR* opCmpImmBranch(CompilationUnit* cUnit, ConditionCode cond, int reg, - int checkValue, LIR* target) + int checkValue, LIR* target) { - LIR* branch; - int modImm; - ArmConditionCode armCond = oatArmConditionEncoding(cond); - if ((LOWREG(reg)) && (checkValue == 0) && - ((armCond == kArmCondEq) || (armCond == kArmCondNe))) { - branch = newLIR2(cUnit, - (armCond == kArmCondEq) ? kThumb2Cbz : kThumb2Cbnz, - reg, 0); + LIR* branch; + int modImm; + ArmConditionCode armCond = oatArmConditionEncoding(cond); + if ((LOWREG(reg)) && (checkValue == 0) && + ((armCond == kArmCondEq) || (armCond == kArmCondNe))) { + branch = newLIR2(cUnit, (armCond == kArmCondEq) ? kThumb2Cbz : kThumb2Cbnz, + reg, 0); + } else { + modImm = modifiedImmediate(checkValue); + if (LOWREG(reg) && ((checkValue & 0xff) == checkValue)) { + newLIR2(cUnit, kThumbCmpRI8, reg, checkValue); + } else if (modImm >= 0) { + newLIR2(cUnit, kThumb2CmpRI8, reg, modImm); } else { - modImm = modifiedImmediate(checkValue); - if (LOWREG(reg) && ((checkValue & 0xff) == checkValue)) { - newLIR2(cUnit, kThumbCmpRI8, reg, checkValue); - } else if (modImm >= 0) { - newLIR2(cUnit, kThumb2CmpRI8, reg, modImm); - } else { - int tReg = oatAllocTemp(cUnit); - loadConstant(cUnit, tReg, checkValue); - opRegReg(cUnit, kOpCmp, reg, tReg); - } - branch = newLIR2(cUnit, kThumbBCond, 0, armCond); + int tReg = oatAllocTemp(cUnit); + loadConstant(cUnit, tReg, checkValue); + opRegReg(cUnit, kOpCmp, reg, tReg); } - branch->target = target; - return branch; + branch = newLIR2(cUnit, kThumbBCond, 0, armCond); + } + branch->target = target; + return branch; } LIR* opRegCopyNoInsert(CompilationUnit* cUnit, int rDest, int rSrc) { - LIR* res; - ArmOpcode opcode; - if (FPREG(rDest) || FPREG(rSrc)) - return fpRegCopy(cUnit, rDest, rSrc); - if (LOWREG(rDest) && LOWREG(rSrc)) - opcode = kThumbMovRR; - else if (!LOWREG(rDest) && !LOWREG(rSrc)) - opcode = kThumbMovRR_H2H; - else if (LOWREG(rDest)) - opcode = kThumbMovRR_H2L; - else - opcode = kThumbMovRR_L2H; - res = rawLIR(cUnit, cUnit->currentDalvikOffset, opcode, rDest, rSrc); - if (!(cUnit->disableOpt & (1 << kSafeOptimizations)) && rDest == rSrc) { - res->flags.isNop = true; - } - return res; + LIR* res; + ArmOpcode opcode; + if (FPREG(rDest) || FPREG(rSrc)) + return fpRegCopy(cUnit, rDest, rSrc); + if (LOWREG(rDest) && LOWREG(rSrc)) + opcode = kThumbMovRR; + else if (!LOWREG(rDest) && !LOWREG(rSrc)) + opcode = kThumbMovRR_H2H; + else if (LOWREG(rDest)) + opcode = kThumbMovRR_H2L; + else + opcode = kThumbMovRR_L2H; + res = rawLIR(cUnit, cUnit->currentDalvikOffset, opcode, rDest, rSrc); + if (!(cUnit->disableOpt & (1 << kSafeOptimizations)) && rDest == rSrc) { + res->flags.isNop = true; + } + return res; } LIR* opRegCopy(CompilationUnit* cUnit, int rDest, int rSrc) { - LIR* res = opRegCopyNoInsert(cUnit, rDest, rSrc); - oatAppendLIR(cUnit, (LIR*)res); - return res; + LIR* res = opRegCopyNoInsert(cUnit, rDest, rSrc); + oatAppendLIR(cUnit, (LIR*)res); + return res; } void opRegCopyWide(CompilationUnit* cUnit, int destLo, int destHi, - int srcLo, int srcHi) + int srcLo, int srcHi) { - bool destFP = FPREG(destLo) && FPREG(destHi); - bool srcFP = FPREG(srcLo) && FPREG(srcHi); - DCHECK_EQ(FPREG(srcLo), FPREG(srcHi)); - DCHECK_EQ(FPREG(destLo), FPREG(destHi)); - if (destFP) { - if (srcFP) { - opRegCopy(cUnit, S2D(destLo, destHi), S2D(srcLo, srcHi)); - } else { - newLIR3(cUnit, kThumb2Fmdrr, S2D(destLo, destHi), srcLo, srcHi); - } + bool destFP = FPREG(destLo) && FPREG(destHi); + bool srcFP = FPREG(srcLo) && FPREG(srcHi); + DCHECK_EQ(FPREG(srcLo), FPREG(srcHi)); + DCHECK_EQ(FPREG(destLo), FPREG(destHi)); + if (destFP) { + if (srcFP) { + opRegCopy(cUnit, S2D(destLo, destHi), S2D(srcLo, srcHi)); } else { - if (srcFP) { - newLIR3(cUnit, kThumb2Fmrrd, destLo, destHi, S2D(srcLo, srcHi)); - } else { - // Handle overlap - if (srcHi == destLo) { - opRegCopy(cUnit, destHi, srcHi); - opRegCopy(cUnit, destLo, srcLo); - } else { - opRegCopy(cUnit, destLo, srcLo); - opRegCopy(cUnit, destHi, srcHi); - } - } + newLIR3(cUnit, kThumb2Fmdrr, S2D(destLo, destHi), srcLo, srcHi); } + } else { + if (srcFP) { + newLIR3(cUnit, kThumb2Fmrrd, destLo, destHi, S2D(srcLo, srcHi)); + } else { + // Handle overlap + if (srcHi == destLo) { + opRegCopy(cUnit, destHi, srcHi); + opRegCopy(cUnit, destLo, srcLo); + } else { + opRegCopy(cUnit, destLo, srcLo); + opRegCopy(cUnit, destHi, srcHi); + } + } + } } // Table of magic divisors enum DividePattern { - DivideNone, - Divide3, - Divide5, - Divide7, + DivideNone, + Divide3, + Divide5, + Divide7, }; struct MagicTable { - uint32_t magic; - uint32_t shift; - DividePattern pattern; + uint32_t magic; + uint32_t shift; + DividePattern pattern; }; static const MagicTable magicTable[] = { - {0, 0, DivideNone}, // 0 - {0, 0, DivideNone}, // 1 - {0, 0, DivideNone}, // 2 - {0x55555556, 0, Divide3}, // 3 - {0, 0, DivideNone}, // 4 - {0x66666667, 1, Divide5}, // 5 - {0x2AAAAAAB, 0, Divide3}, // 6 - {0x92492493, 2, Divide7}, // 7 - {0, 0, DivideNone}, // 8 - {0x38E38E39, 1, Divide5}, // 9 - {0x66666667, 2, Divide5}, // 10 - {0x2E8BA2E9, 1, Divide5}, // 11 - {0x2AAAAAAB, 1, Divide5}, // 12 - {0x4EC4EC4F, 2, Divide5}, // 13 - {0x92492493, 3, Divide7}, // 14 - {0x88888889, 3, Divide7}, // 15 + {0, 0, DivideNone}, // 0 + {0, 0, DivideNone}, // 1 + {0, 0, DivideNone}, // 2 + {0x55555556, 0, Divide3}, // 3 + {0, 0, DivideNone}, // 4 + {0x66666667, 1, Divide5}, // 5 + {0x2AAAAAAB, 0, Divide3}, // 6 + {0x92492493, 2, Divide7}, // 7 + {0, 0, DivideNone}, // 8 + {0x38E38E39, 1, Divide5}, // 9 + {0x66666667, 2, Divide5}, // 10 + {0x2E8BA2E9, 1, Divide5}, // 11 + {0x2AAAAAAB, 1, Divide5}, // 12 + {0x4EC4EC4F, 2, Divide5}, // 13 + {0x92492493, 3, Divide7}, // 14 + {0x88888889, 3, Divide7}, // 15 }; // Integer division by constant via reciprocal multiply (Hacker's Delight, 10-4) bool smallLiteralDivide(CompilationUnit* cUnit, Instruction::Code dalvikOpcode, RegLocation rlSrc, RegLocation rlDest, int lit) { - if ((lit < 0) || (lit >= (int)(sizeof(magicTable)/sizeof(magicTable[0])))) { - return false; - } - DividePattern pattern = magicTable[lit].pattern; - if (pattern == DivideNone) { - return false; - } - // Tuning: add rem patterns - if (dalvikOpcode != Instruction::DIV_INT_LIT8) { - return false; - } - - int rMagic = oatAllocTemp(cUnit); - loadConstant(cUnit, rMagic, magicTable[lit].magic); - rlSrc = loadValue(cUnit, rlSrc, kCoreReg); - RegLocation rlResult = oatEvalLoc(cUnit, rlDest, kCoreReg, true); - int rHi = oatAllocTemp(cUnit); - int rLo = oatAllocTemp(cUnit); - newLIR4(cUnit, kThumb2Smull, rLo, rHi, rMagic, rlSrc.lowReg); - switch(pattern) { - case Divide3: - opRegRegRegShift(cUnit, kOpSub, rlResult.lowReg, rHi, - rlSrc.lowReg, encodeShift(kArmAsr, 31)); - break; - case Divide5: - opRegRegImm(cUnit, kOpAsr, rLo, rlSrc.lowReg, 31); - opRegRegRegShift(cUnit, kOpRsub, rlResult.lowReg, rLo, rHi, - encodeShift(kArmAsr, magicTable[lit].shift)); - break; - case Divide7: - opRegReg(cUnit, kOpAdd, rHi, rlSrc.lowReg); - opRegRegImm(cUnit, kOpAsr, rLo, rlSrc.lowReg, 31); - opRegRegRegShift(cUnit, kOpRsub, rlResult.lowReg, rLo, rHi, - encodeShift(kArmAsr, magicTable[lit].shift)); - break; - default: - LOG(FATAL) << "Unexpected pattern: " << (int)pattern; - } - storeValue(cUnit, rlDest, rlResult); - return true; + if ((lit < 0) || (lit >= (int)(sizeof(magicTable)/sizeof(magicTable[0])))) { + return false; + } + DividePattern pattern = magicTable[lit].pattern; + if (pattern == DivideNone) { + return false; + } + // Tuning: add rem patterns + if (dalvikOpcode != Instruction::DIV_INT_LIT8) { + return false; + } + + int rMagic = oatAllocTemp(cUnit); + loadConstant(cUnit, rMagic, magicTable[lit].magic); + rlSrc = loadValue(cUnit, rlSrc, kCoreReg); + RegLocation rlResult = oatEvalLoc(cUnit, rlDest, kCoreReg, true); + int rHi = oatAllocTemp(cUnit); + int rLo = oatAllocTemp(cUnit); + newLIR4(cUnit, kThumb2Smull, rLo, rHi, rMagic, rlSrc.lowReg); + switch(pattern) { + case Divide3: + opRegRegRegShift(cUnit, kOpSub, rlResult.lowReg, rHi, + rlSrc.lowReg, encodeShift(kArmAsr, 31)); + break; + case Divide5: + opRegRegImm(cUnit, kOpAsr, rLo, rlSrc.lowReg, 31); + opRegRegRegShift(cUnit, kOpRsub, rlResult.lowReg, rLo, rHi, + encodeShift(kArmAsr, magicTable[lit].shift)); + break; + case Divide7: + opRegReg(cUnit, kOpAdd, rHi, rlSrc.lowReg); + opRegRegImm(cUnit, kOpAsr, rLo, rlSrc.lowReg, 31); + opRegRegRegShift(cUnit, kOpRsub, rlResult.lowReg, rLo, rHi, + encodeShift(kArmAsr, magicTable[lit].shift)); + break; + default: + LOG(FATAL) << "Unexpected pattern: " << (int)pattern; + } + storeValue(cUnit, rlDest, rlResult); + return true; } } // namespace art diff --git a/src/compiler/codegen/arm/Thumb2/Ralloc.cc b/src/compiler/codegen/arm/Thumb2/Ralloc.cc index 7858318001..98a110cb2b 100644 --- a/src/compiler/codegen/arm/Thumb2/Ralloc.cc +++ b/src/compiler/codegen/arm/Thumb2/Ralloc.cc @@ -30,96 +30,96 @@ namespace art { */ int oatAllocTypedTempPair(CompilationUnit* cUnit, bool fpHint, int regClass) { - int highReg; - int lowReg; - int res = 0; + int highReg; + int lowReg; + int res = 0; - if (((regClass == kAnyReg) && fpHint) || (regClass == kFPReg)) { - lowReg = oatAllocTempDouble(cUnit); - highReg = lowReg + 1; - } else { - lowReg = oatAllocTemp(cUnit); - highReg = oatAllocTemp(cUnit); - } - res = (lowReg & 0xff) | ((highReg & 0xff) << 8); - return res; + if (((regClass == kAnyReg) && fpHint) || (regClass == kFPReg)) { + lowReg = oatAllocTempDouble(cUnit); + highReg = lowReg + 1; + } else { + lowReg = oatAllocTemp(cUnit); + highReg = oatAllocTemp(cUnit); + } + res = (lowReg & 0xff) | ((highReg & 0xff) << 8); + return res; } int oatAllocTypedTemp(CompilationUnit* cUnit, bool fpHint, int regClass) { - if (((regClass == kAnyReg) && fpHint) || (regClass == kFPReg)) - return oatAllocTempFloat(cUnit); - return oatAllocTemp(cUnit); + if (((regClass == kAnyReg) && fpHint) || (regClass == kFPReg)) + return oatAllocTempFloat(cUnit); + return oatAllocTemp(cUnit); } void oatInitializeRegAlloc(CompilationUnit* cUnit) { - int numRegs = sizeof(coreRegs)/sizeof(*coreRegs); - int numReserved = sizeof(reservedRegs)/sizeof(*reservedRegs); - int numTemps = sizeof(coreTemps)/sizeof(*coreTemps); - int numFPRegs = sizeof(fpRegs)/sizeof(*fpRegs); - int numFPTemps = sizeof(fpTemps)/sizeof(*fpTemps); - RegisterPool *pool = (RegisterPool *)oatNew(cUnit, sizeof(*pool), true, - kAllocRegAlloc); - cUnit->regPool = pool; - pool->numCoreRegs = numRegs; - pool->coreRegs = (RegisterInfo *) - oatNew(cUnit, numRegs * sizeof(*cUnit->regPool->coreRegs), - true, kAllocRegAlloc); - pool->numFPRegs = numFPRegs; - pool->FPRegs = (RegisterInfo *) - oatNew(cUnit, numFPRegs * sizeof(*cUnit->regPool->FPRegs), true, - kAllocRegAlloc); - oatInitPool(pool->coreRegs, coreRegs, pool->numCoreRegs); - oatInitPool(pool->FPRegs, fpRegs, pool->numFPRegs); - // Keep special registers from being allocated - for (int i = 0; i < numReserved; i++) { - if (NO_SUSPEND && !cUnit->genDebugger && - (reservedRegs[i] == rSUSPEND)) { - //To measure cost of suspend check - continue; - } - oatMarkInUse(cUnit, reservedRegs[i]); - } - // Mark temp regs - all others not in use can be used for promotion - for (int i = 0; i < numTemps; i++) { - oatMarkTemp(cUnit, coreTemps[i]); - } - for (int i = 0; i < numFPTemps; i++) { - oatMarkTemp(cUnit, fpTemps[i]); + int numRegs = sizeof(coreRegs)/sizeof(*coreRegs); + int numReserved = sizeof(reservedRegs)/sizeof(*reservedRegs); + int numTemps = sizeof(coreTemps)/sizeof(*coreTemps); + int numFPRegs = sizeof(fpRegs)/sizeof(*fpRegs); + int numFPTemps = sizeof(fpTemps)/sizeof(*fpTemps); + RegisterPool *pool = (RegisterPool *)oatNew(cUnit, sizeof(*pool), true, + kAllocRegAlloc); + cUnit->regPool = pool; + pool->numCoreRegs = numRegs; + pool->coreRegs = (RegisterInfo *) + oatNew(cUnit, numRegs * sizeof(*cUnit->regPool->coreRegs), + true, kAllocRegAlloc); + pool->numFPRegs = numFPRegs; + pool->FPRegs = (RegisterInfo *) + oatNew(cUnit, numFPRegs * sizeof(*cUnit->regPool->FPRegs), true, + kAllocRegAlloc); + oatInitPool(pool->coreRegs, coreRegs, pool->numCoreRegs); + oatInitPool(pool->FPRegs, fpRegs, pool->numFPRegs); + // Keep special registers from being allocated + for (int i = 0; i < numReserved; i++) { + if (NO_SUSPEND && !cUnit->genDebugger && + (reservedRegs[i] == rSUSPEND)) { + //To measure cost of suspend check + continue; } + oatMarkInUse(cUnit, reservedRegs[i]); + } + // Mark temp regs - all others not in use can be used for promotion + for (int i = 0; i < numTemps; i++) { + oatMarkTemp(cUnit, coreTemps[i]); + } + for (int i = 0; i < numFPTemps; i++) { + oatMarkTemp(cUnit, fpTemps[i]); + } - // Start allocation at r2 in an attempt to avoid clobbering return values - pool->nextCoreReg = r2; + // Start allocation at r2 in an attempt to avoid clobbering return values + pool->nextCoreReg = r2; - // Construct the alias map. - cUnit->phiAliasMap = (int*)oatNew(cUnit, cUnit->numSSARegs * - sizeof(cUnit->phiAliasMap[0]), false, - kAllocDFInfo); - for (int i = 0; i < cUnit->numSSARegs; i++) { - cUnit->phiAliasMap[i] = i; - } - for (MIR* phi = cUnit->phiList; phi; phi = phi->meta.phiNext) { - int defReg = phi->ssaRep->defs[0]; - for (int i = 0; i < phi->ssaRep->numUses; i++) { - for (int j = 0; j < cUnit->numSSARegs; j++) { - if (cUnit->phiAliasMap[j] == phi->ssaRep->uses[i]) { - cUnit->phiAliasMap[j] = defReg; - } - } - } + // Construct the alias map. + cUnit->phiAliasMap = (int*)oatNew(cUnit, cUnit->numSSARegs * + sizeof(cUnit->phiAliasMap[0]), false, + kAllocDFInfo); + for (int i = 0; i < cUnit->numSSARegs; i++) { + cUnit->phiAliasMap[i] = i; + } + for (MIR* phi = cUnit->phiList; phi; phi = phi->meta.phiNext) { + int defReg = phi->ssaRep->defs[0]; + for (int i = 0; i < phi->ssaRep->numUses; i++) { + for (int j = 0; j < cUnit->numSSARegs; j++) { + if (cUnit->phiAliasMap[j] == phi->ssaRep->uses[i]) { + cUnit->phiAliasMap[j] = defReg; + } + } } + } } void freeRegLocTemps(CompilationUnit* cUnit, RegLocation rlKeep, RegLocation rlFree) { - if ((rlFree.lowReg != rlKeep.lowReg) && (rlFree.lowReg != rlKeep.highReg) && - (rlFree.highReg != rlKeep.lowReg) && (rlFree.highReg != rlKeep.highReg)) { - // No overlap, free both - oatFreeTemp(cUnit, rlFree.lowReg); - oatFreeTemp(cUnit, rlFree.highReg); - } + if ((rlFree.lowReg != rlKeep.lowReg) && (rlFree.lowReg != rlKeep.highReg) && + (rlFree.highReg != rlKeep.lowReg) && (rlFree.highReg != rlKeep.highReg)) { + // No overlap, free both + oatFreeTemp(cUnit, rlFree.lowReg); + oatFreeTemp(cUnit, rlFree.highReg); + } } |