summaryrefslogtreecommitdiffstats
path: root/compiler/dex/quick/arm
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/dex/quick/arm')
-rw-r--r--compiler/dex/quick/arm/assemble_arm.cc42
-rw-r--r--compiler/dex/quick/arm/codegen_arm.h30
-rw-r--r--compiler/dex/quick/arm/int_arm.cc3
-rw-r--r--compiler/dex/quick/arm/target_arm.cc42
-rw-r--r--compiler/dex/quick/arm/utility_arm.cc19
5 files changed, 107 insertions, 29 deletions
diff --git a/compiler/dex/quick/arm/assemble_arm.cc b/compiler/dex/quick/arm/assemble_arm.cc
index df4a9f2048..57ebca67e8 100644
--- a/compiler/dex/quick/arm/assemble_arm.cc
+++ b/compiler/dex/quick/arm/assemble_arm.cc
@@ -1082,6 +1082,19 @@ void ArmMir2Lir::InsertFixupBefore(LIR* prev_lir, LIR* orig_lir, LIR* new_lir) {
*/
#define PADDING_MOV_R5_R5 0x1C2D
+uint32_t ArmMir2Lir::ProcessMoreEncodings(const ArmEncodingMap* encoder, int i, uint32_t operand) {
+ LOG(FATAL) << "Bad fmt:" << encoder->field_loc[i].kind << " " << operand;
+ uint32_t value=0;
+ return value;
+}
+
+const ArmEncodingMap * ArmMir2Lir::GetEncoder(int opcode) {
+ if (opcode < 0 || opcode >= kArmLast)
+ LOG(FATAL) << "invalid opcode " << opcode;
+ const ArmEncodingMap *encoder = &EncodingMap[opcode];
+ return encoder;
+}
+
uint8_t* ArmMir2Lir::EncodeLIRs(uint8_t* write_pos, LIR* lir) {
uint8_t* const write_buffer = write_pos;
for (; lir != nullptr; lir = NEXT_LIR(lir)) {
@@ -1098,7 +1111,7 @@ uint8_t* ArmMir2Lir::EncodeLIRs(uint8_t* write_pos, LIR* lir) {
}
}
} else if (LIKELY(!lir->flags.is_nop)) {
- const ArmEncodingMap *encoder = &EncodingMap[lir->opcode];
+ const ArmEncodingMap *encoder = GetEncoder(lir->opcode);
uint32_t bits = encoder->skeleton;
for (int i = 0; i < 4; i++) {
uint32_t operand;
@@ -1214,7 +1227,8 @@ uint8_t* ArmMir2Lir::EncodeLIRs(uint8_t* write_pos, LIR* lir) {
}
break;
default:
- LOG(FATAL) << "Bad fmt:" << encoder->field_loc[i].kind;
+ bits |= ProcessMoreEncodings(encoder, i, operand);
+ break;
}
}
}
@@ -1324,7 +1338,7 @@ void ArmMir2Lir::AssembleLIR() {
base_reg, 0, 0, 0, 0, lir->target);
new_adr->offset = lir->offset;
new_adr->flags.fixup = kFixupAdr;
- new_adr->flags.size = EncodingMap[kThumb2Adr].size;
+ new_adr->flags.size = GetEncoder(kThumb2Adr)->size;
InsertLIRBefore(lir, new_adr);
lir->offset += new_adr->flags.size;
offset_adjustment += new_adr->flags.size;
@@ -1339,7 +1353,7 @@ void ArmMir2Lir::AssembleLIR() {
} else if (lir->opcode == kThumb2LdrdPcRel8) {
lir->opcode = kThumb2LdrdI8;
}
- lir->flags.size = EncodingMap[lir->opcode].size;
+ lir->flags.size = GetEncoder(lir->opcode)->size;
offset_adjustment += lir->flags.size;
// Change the load to be relative to the new Adr base.
if (lir->opcode == kThumb2LdrdI8) {
@@ -1389,13 +1403,13 @@ void ArmMir2Lir::AssembleLIR() {
/* operand[0] is src1 in both cb[n]z & CmpRI8 */
lir->operands[1] = 0;
lir->target = 0;
- lir->flags.size = EncodingMap[lir->opcode].size;
+ lir->flags.size = GetEncoder(lir->opcode)->size;
// Add back the new size.
offset_adjustment += lir->flags.size;
// Set up the new following inst.
new_inst->offset = lir->offset + lir->flags.size;
new_inst->flags.fixup = kFixupCondBranch;
- new_inst->flags.size = EncodingMap[new_inst->opcode].size;
+ new_inst->flags.size = GetEncoder(new_inst->opcode)->size;
offset_adjustment += new_inst->flags.size;
// lir no longer pcrel, unlink and link in new_inst.
@@ -1420,7 +1434,7 @@ void ArmMir2Lir::AssembleLIR() {
if ((lir->opcode == kThumbBCond) && (delta > 254 || delta < -256)) {
offset_adjustment -= lir->flags.size;
lir->opcode = kThumb2BCond;
- lir->flags.size = EncodingMap[lir->opcode].size;
+ lir->flags.size = GetEncoder(lir->opcode)->size;
// Fixup kind remains the same.
offset_adjustment += lir->flags.size;
res = kRetryAll;
@@ -1456,7 +1470,7 @@ void ArmMir2Lir::AssembleLIR() {
offset_adjustment -= lir->flags.size;
lir->opcode = kThumb2BUncond;
lir->operands[0] = 0;
- lir->flags.size = EncodingMap[lir->opcode].size;
+ lir->flags.size = GetEncoder(lir->opcode)->size;
lir->flags.fixup = kFixupT2Branch;
offset_adjustment += lir->flags.size;
res = kRetryAll;
@@ -1518,7 +1532,7 @@ void ArmMir2Lir::AssembleLIR() {
LIR *new_mov16L =
RawLIR(lir->dalvik_offset, kThumb2MovImm16LST, lir->operands[0], 0,
WrapPointer(lir), WrapPointer(tab_rec), 0, lir->target);
- new_mov16L->flags.size = EncodingMap[new_mov16L->opcode].size;
+ new_mov16L->flags.size = GetEncoder(new_mov16L->opcode)->size;
new_mov16L->flags.fixup = kFixupMovImmLST;
new_mov16L->offset = lir->offset;
// Link the new instruction, retaining lir.
@@ -1530,7 +1544,7 @@ void ArmMir2Lir::AssembleLIR() {
LIR *new_mov16H =
RawLIR(lir->dalvik_offset, kThumb2MovImm16HST, lir->operands[0], 0,
WrapPointer(lir), WrapPointer(tab_rec), 0, lir->target);
- new_mov16H->flags.size = EncodingMap[new_mov16H->opcode].size;
+ new_mov16H->flags.size = GetEncoder(new_mov16H->opcode)->size;
new_mov16H->flags.fixup = kFixupMovImmHST;
new_mov16H->offset = lir->offset;
// Link the new instruction, retaining lir.
@@ -1547,7 +1561,7 @@ void ArmMir2Lir::AssembleLIR() {
lir->opcode = kThumbAddRRHH;
}
lir->operands[1] = rs_rARM_PC.GetReg();
- lir->flags.size = EncodingMap[lir->opcode].size;
+ lir->flags.size = GetEncoder(lir->opcode)->size;
offset_adjustment += lir->flags.size;
// Must stay in fixup list and have offset updated; will be used by LST/HSP pair.
lir->flags.fixup = kFixupNone;
@@ -1635,7 +1649,7 @@ void ArmMir2Lir::AssembleLIR() {
size_t ArmMir2Lir::GetInsnSize(LIR* lir) {
DCHECK(!IsPseudoLirOp(lir->opcode));
- return EncodingMap[lir->opcode].size;
+ return GetEncoder(lir->opcode)->size;
}
// Encode instruction bit pattern and assign offsets.
@@ -1647,8 +1661,8 @@ uint32_t ArmMir2Lir::LinkFixupInsns(LIR* head_lir, LIR* tail_lir, uint32_t offse
if (!lir->flags.is_nop) {
if (lir->flags.fixup != kFixupNone) {
if (!IsPseudoLirOp(lir->opcode)) {
- lir->flags.size = EncodingMap[lir->opcode].size;
- lir->flags.fixup = EncodingMap[lir->opcode].fixup;
+ lir->flags.size = GetEncoder(lir->opcode)->size;
+ lir->flags.fixup = GetEncoder(lir->opcode)->fixup;
} else if (UNLIKELY(lir->opcode == kPseudoPseudoAlign4)) {
lir->flags.size = (offset & 0x2);
lir->flags.fixup = kFixupAlign4;
diff --git a/compiler/dex/quick/arm/codegen_arm.h b/compiler/dex/quick/arm/codegen_arm.h
index b94e707354..2fee96ddb8 100644
--- a/compiler/dex/quick/arm/codegen_arm.h
+++ b/compiler/dex/quick/arm/codegen_arm.h
@@ -22,10 +22,18 @@
#include "base/logging.h"
#include "dex/quick/mir_to_lir.h"
+#ifdef QC_STRONG
+#define QC_WEAK
+#else
+#define QC_WEAK __attribute__((weak))
+#endif
+
namespace art {
struct CompilationUnit;
+class QCArmMir2Lir;
+
class ArmMir2Lir FINAL : public Mir2Lir {
protected:
// Inherited class for ARM backend.
@@ -57,6 +65,7 @@ class ArmMir2Lir FINAL : public Mir2Lir {
public:
ArmMir2Lir(CompilationUnit* cu, MIRGraph* mir_graph, ArenaAllocator* arena);
+ ~ArmMir2Lir();
// Required for target - codegen helpers.
bool SmallLiteralDivRem(Instruction::Code dalvik_opcode, bool is_div, RegLocation rl_src,
@@ -206,6 +215,7 @@ class ArmMir2Lir FINAL : public Mir2Lir {
LIR* OpMem(OpKind op, RegStorage r_base, int disp);
void OpPcRelLoad(RegStorage reg, LIR* target);
LIR* OpReg(OpKind op, RegStorage r_dest_src);
+ LIR* OpBkpt();
void OpRegCopy(RegStorage r_dest, RegStorage r_src);
LIR* OpRegCopyNoInsert(RegStorage r_dest, RegStorage r_src);
LIR* OpRegImm(OpKind op, RegStorage r_dest_src1, int value);
@@ -271,12 +281,15 @@ class ArmMir2Lir FINAL : public Mir2Lir {
LIR* InvokeTrampoline(OpKind op, RegStorage r_tgt, QuickEntrypointEnum trampoline) OVERRIDE;
size_t GetInstructionOffset(LIR* lir);
+ void GenMoreMachineSpecificExtendedMethodMIR(BasicBlock* bb, MIR* mir) QC_WEAK;
+ //void MachineSpecificPreprocessMIR(BasicBlock* bb, MIR* mir);
void GenMachineSpecificExtendedMethodMIR(BasicBlock* bb, MIR* mir) OVERRIDE;
bool HandleEasyDivRem(Instruction::Code dalvik_opcode, bool is_div,
RegLocation rl_src, RegLocation rl_dest, int lit) OVERRIDE;
+ void CleanupCodeGenData() QC_WEAK;
private:
void GenNegLong(RegLocation rl_dest, RegLocation rl_src);
void GenMulLong(Instruction::Code opcode, RegLocation rl_dest, RegLocation rl_src1,
@@ -301,6 +314,12 @@ class ArmMir2Lir FINAL : public Mir2Lir {
bool GetEasyMultiplyTwoOps(int lit, EasyMultiplyOp* ops);
void GenEasyMultiplyTwoOps(RegStorage r_dest, RegStorage r_src, EasyMultiplyOp* ops);
+
+
+ static uint32_t ProcessMoreEncodings(const ArmEncodingMap* encoder, int i, uint32_t operand) QC_WEAK;
+
+ static const ArmEncodingMap * GetEncoder(int opcode) QC_WEAK;
+
static constexpr ResourceMask GetRegMaskArm(RegStorage reg);
static constexpr ResourceMask EncodeArmRegList(int reg_list);
static constexpr ResourceMask EncodeArmRegFpcsList(int reg_list);
@@ -351,6 +370,17 @@ class ArmMir2Lir FINAL : public Mir2Lir {
InvokeType type);
void OpPcRelDexCacheArrayAddr(const DexFile* dex_file, int offset, RegStorage r_dest);
+
+ virtual void ApplyArchOptimizations(LIR* head_lir, LIR* tail_lir, BasicBlock* bb) QC_WEAK;
+
+ void CompilerPostInitializeRegAlloc() QC_WEAK;
+ void ArmMir2LirPostInit(ArmMir2Lir* mir_to_lir) QC_WEAK;
+
+ friend class QCArmMir2Lir;
+
+ public:
+ QCArmMir2Lir * qcm2l ;
+
};
} // namespace art
diff --git a/compiler/dex/quick/arm/int_arm.cc b/compiler/dex/quick/arm/int_arm.cc
index cf0188456d..4ddf616724 100644
--- a/compiler/dex/quick/arm/int_arm.cc
+++ b/compiler/dex/quick/arm/int_arm.cc
@@ -754,8 +754,7 @@ RegLocation ArmMir2Lir::GenDivRem(RegLocation rl_dest, RegStorage reg1, RegStora
RegStorage temp = AllocTemp();
OpRegRegReg(kOpDiv, temp, reg1, reg2);
- OpRegReg(kOpMul, temp, reg2);
- OpRegRegReg(kOpSub, rl_result.reg, reg1, temp);
+ NewLIR4(kThumb2Mls, rl_result.reg.GetReg(), temp.GetReg(), reg2.GetReg(), reg1.GetReg());
FreeTemp(temp);
}
diff --git a/compiler/dex/quick/arm/target_arm.cc b/compiler/dex/quick/arm/target_arm.cc
index 5f27338e6b..6702f79a33 100644
--- a/compiler/dex/quick/arm/target_arm.cc
+++ b/compiler/dex/quick/arm/target_arm.cc
@@ -140,11 +140,18 @@ ResourceMask ArmMir2Lir::GetRegMaskCommon(const RegStorage& reg) const {
return GetRegMaskArm(reg);
}
+void ArmMir2Lir::CompilerPostInitializeRegAlloc()
+{
+ //nothing here
+}
+
constexpr ResourceMask ArmMir2Lir::GetRegMaskArm(RegStorage reg) {
- return reg.IsDouble()
+ return (reg.IsQuad())
+ ? (ResourceMask::FourBits((reg.GetRegNum() * 4) + kArmFPReg0))
+ : (reg.IsDouble()
/* Each double register is equal to a pair of single-precision FP registers */
? ResourceMask::TwoBits(reg.GetRegNum() * 2 + kArmFPReg0)
- : ResourceMask::Bit(reg.IsSingle() ? reg.GetRegNum() + kArmFPReg0 : reg.GetRegNum());
+ : ResourceMask::Bit(reg.IsSingle() ? reg.GetRegNum() + kArmFPReg0 : reg.GetRegNum()));
}
constexpr ResourceMask ArmMir2Lir::EncodeArmRegList(int reg_list) {
@@ -586,6 +593,20 @@ ArmMir2Lir::ArmMir2Lir(CompilationUnit* cu, MIRGraph* mir_graph, ArenaAllocator*
<< " is wrong: expecting " << i << ", seeing "
<< static_cast<int>(ArmMir2Lir::EncodingMap[i].opcode);
}
+ qcm2l = nullptr;
+ ArmMir2LirPostInit(this);
+}
+
+ArmMir2Lir::~ArmMir2Lir()
+{
+ CleanupCodeGenData();
+}
+
+void ArmMir2Lir::CleanupCodeGenData()
+{
+}
+
+void ArmMir2Lir::ArmMir2LirPostInit(ArmMir2Lir*) {
}
Mir2Lir* ArmCodeGenerator(CompilationUnit* const cu, MIRGraph* const mir_graph,
@@ -633,6 +654,8 @@ void ArmMir2Lir::CompilerInitializeRegAlloc() {
reg_pool_->next_core_reg_ = 2;
reg_pool_->next_sp_reg_ = 0;
reg_pool_->next_dp_reg_ = 0;
+
+ CompilerPostInitializeRegAlloc();
}
/*
@@ -814,17 +837,17 @@ LIR* ArmMir2Lir::CheckSuspendUsingLoad() {
uint64_t ArmMir2Lir::GetTargetInstFlags(int opcode) {
DCHECK(!IsPseudoLirOp(opcode));
- return ArmMir2Lir::EncodingMap[opcode].flags;
+ return GetEncoder(opcode)->flags;
}
const char* ArmMir2Lir::GetTargetInstName(int opcode) {
DCHECK(!IsPseudoLirOp(opcode));
- return ArmMir2Lir::EncodingMap[opcode].name;
+ return GetEncoder(opcode)->name;
}
const char* ArmMir2Lir::GetTargetInstFmt(int opcode) {
DCHECK(!IsPseudoLirOp(opcode));
- return ArmMir2Lir::EncodingMap[opcode].fmt;
+ return GetEncoder(opcode)->fmt;
}
/*
@@ -1009,8 +1032,15 @@ void ArmMir2Lir::GenMachineSpecificExtendedMethodMIR(BasicBlock* bb, MIR* mir) {
GenMaddMsubInt(rl_dest, rl_src[0], rl_src[1], rl_src[2], true);
break;
default:
- LOG(FATAL) << "Unexpected opcode: " << mir->dalvikInsn.opcode;
+ GenMoreMachineSpecificExtendedMethodMIR(bb, mir);
+ // LOG(FATAL) << "Unexpected opcode: " << mir->dalvikInsn.opcode;
}
}
+void ArmMir2Lir::GenMoreMachineSpecificExtendedMethodMIR(BasicBlock*, MIR*){
+ // nothing here
+}
+
+void ArmMir2Lir::ApplyArchOptimizations(LIR*, LIR*, BasicBlock*) {
+}
} // namespace art
diff --git a/compiler/dex/quick/arm/utility_arm.cc b/compiler/dex/quick/arm/utility_arm.cc
index 2ef92f851b..0a2a969374 100644
--- a/compiler/dex/quick/arm/utility_arm.cc
+++ b/compiler/dex/quick/arm/utility_arm.cc
@@ -282,6 +282,11 @@ LIR* ArmMir2Lir::OpReg(OpKind op, RegStorage r_dest_src) {
return NewLIR1(opcode, r_dest_src.GetReg());
}
+LIR* ArmMir2Lir::OpBkpt() {
+ LOG(ERROR) << "Inserting breakpoint";
+ return NewLIR0(kThumbBkpt);
+}
+
LIR* ArmMir2Lir::OpRegRegShift(OpKind op, RegStorage r_dest_src1, RegStorage r_src2,
int shift) {
bool thumb_form =
@@ -399,15 +404,15 @@ LIR* ArmMir2Lir::OpRegRegShift(OpKind op, RegStorage r_dest_src1, RegStorage r_s
break;
}
DCHECK(!IsPseudoLirOp(opcode));
- if (EncodingMap[opcode].flags & IS_BINARY_OP) {
+ if (GetEncoder(opcode)->flags & IS_BINARY_OP) {
return NewLIR2(opcode, r_dest_src1.GetReg(), r_src2.GetReg());
- } else if (EncodingMap[opcode].flags & IS_TERTIARY_OP) {
- if (EncodingMap[opcode].field_loc[2].kind == kFmtShift) {
+ } else if (GetEncoder(opcode)->flags & IS_TERTIARY_OP) {
+ if (GetEncoder(opcode)->field_loc[2].kind == kFmtShift) {
return NewLIR3(opcode, r_dest_src1.GetReg(), r_src2.GetReg(), shift);
} else {
return NewLIR3(opcode, r_dest_src1.GetReg(), r_dest_src1.GetReg(), r_src2.GetReg());
}
- } else if (EncodingMap[opcode].flags & IS_QUAD_OP) {
+ } else if (GetEncoder(opcode)->flags & IS_QUAD_OP) {
return NewLIR4(opcode, r_dest_src1.GetReg(), r_dest_src1.GetReg(), r_src2.GetReg(), shift);
} else {
LOG(FATAL) << "Unexpected encoding operand count";
@@ -498,10 +503,10 @@ LIR* ArmMir2Lir::OpRegRegRegShift(OpKind op, RegStorage r_dest, RegStorage r_src
break;
}
DCHECK(!IsPseudoLirOp(opcode));
- if (EncodingMap[opcode].flags & IS_QUAD_OP) {
+ if (GetEncoder(opcode)->flags & IS_QUAD_OP) {
return NewLIR4(opcode, r_dest.GetReg(), r_src1.GetReg(), r_src2.GetReg(), shift);
} else {
- DCHECK(EncodingMap[opcode].flags & IS_TERTIARY_OP);
+ DCHECK(GetEncoder(opcode)->flags & IS_TERTIARY_OP);
return NewLIR3(opcode, r_dest.GetReg(), r_src1.GetReg(), r_src2.GetReg());
}
}
@@ -643,7 +648,7 @@ LIR* ArmMir2Lir::OpRegRegImm(OpKind op, RegStorage r_dest, RegStorage r_src1, in
RegStorage r_scratch = AllocTemp();
LoadConstant(r_scratch, value);
LIR* res;
- if (EncodingMap[alt_opcode].flags & IS_QUAD_OP)
+ if (GetEncoder(alt_opcode)->flags & IS_QUAD_OP)
res = NewLIR4(alt_opcode, r_dest.GetReg(), r_src1.GetReg(), r_scratch.GetReg(), 0);
else
res = NewLIR3(alt_opcode, r_dest.GetReg(), r_src1.GetReg(), r_scratch.GetReg());