summaryrefslogtreecommitdiff
path: root/compiler
diff options
context:
space:
mode:
Diffstat (limited to 'compiler')
-rw-r--r--compiler/dex/quick/arm/codegen_arm.h2
-rw-r--r--compiler/dex/quick/arm/utility_arm.cc99
2 files changed, 44 insertions, 57 deletions
diff --git a/compiler/dex/quick/arm/codegen_arm.h b/compiler/dex/quick/arm/codegen_arm.h
index 9c801a520b..9921d52e5b 100644
--- a/compiler/dex/quick/arm/codegen_arm.h
+++ b/compiler/dex/quick/arm/codegen_arm.h
@@ -204,6 +204,8 @@ class ArmMir2Lir FINAL : public Mir2Lir {
void GenFusedLongCmpImmBranch(BasicBlock* bb, RegLocation rl_src1, int64_t val,
ConditionCode ccode);
LIR* LoadFPConstantValue(int r_dest, int value);
+ LIR* LoadStoreMaxDisp1020(ArmOpcode opcode, RegStorage r_base, int displacement,
+ RegStorage r_src_dest, RegStorage r_work = RegStorage::InvalidReg());
void ReplaceFixup(LIR* prev_lir, LIR* orig_lir, LIR* new_lir);
void InsertFixupBefore(LIR* prev_lir, LIR* orig_lir, LIR* new_lir);
void AssignDataOffsets();
diff --git a/compiler/dex/quick/arm/utility_arm.cc b/compiler/dex/quick/arm/utility_arm.cc
index 86d32f4d72..6bb0d74187 100644
--- a/compiler/dex/quick/arm/utility_arm.cc
+++ b/compiler/dex/quick/arm/utility_arm.cc
@@ -819,6 +819,30 @@ LIR* ArmMir2Lir::StoreBaseIndexed(RegStorage r_base, RegStorage r_index, RegStor
return store;
}
+// Helper function for LoadBaseDispBody()/StoreBaseDispBody().
+LIR* ArmMir2Lir::LoadStoreMaxDisp1020(ArmOpcode opcode, RegStorage r_base, int displacement,
+ RegStorage r_src_dest, RegStorage r_work) {
+ DCHECK_EQ(displacement & 3, 0);
+ int encoded_disp = (displacement & 1020) >> 2; // Within range of the instruction.
+ RegStorage r_ptr = r_base;
+ if ((displacement & ~1020) != 0) {
+ r_ptr = r_work.Valid() ? r_work : AllocTemp();
+ // Add displacement & ~1020 to base, it's a single instruction for up to +-256KiB.
+ OpRegRegImm(kOpAdd, r_ptr, r_base, displacement & ~1020);
+ }
+ LIR* lir = nullptr;
+ if (!r_src_dest.IsPair()) {
+ lir = NewLIR3(opcode, r_src_dest.GetReg(), r_ptr.GetReg(), encoded_disp);
+ } else {
+ lir = NewLIR4(opcode, r_src_dest.GetLowReg(), r_src_dest.GetHighReg(), r_ptr.GetReg(),
+ encoded_disp);
+ }
+ if ((displacement & ~1020) != 0 && !r_work.Valid()) {
+ FreeTemp(r_ptr);
+ }
+ return lir;
+}
+
/*
* Load value from base + displacement. Optionally perform null check
* on base (which must have an associated s_reg and MIR). If not
@@ -836,40 +860,26 @@ LIR* ArmMir2Lir::LoadBaseDispBody(RegStorage r_base, int displacement, RegStorag
switch (size) {
case kDouble:
// Intentional fall-though.
- case k64: {
- DCHECK_EQ(displacement & 3, 0);
- encoded_disp = (displacement & 1020) >> 2; // Within range of kThumb2Vldrd/kThumb2LdrdI8.
- RegStorage r_ptr = r_base;
- if ((displacement & ~1020) != 0) {
- // For core register load, use the r_dest.GetLow() for the temporary pointer.
- r_ptr = r_dest.IsFloat() ? AllocTemp() : r_dest.GetLow();
- // Add displacement & ~1020 to base, it's a single instruction for up to +-256KiB.
- OpRegRegImm(kOpAdd, r_ptr, r_base, displacement & ~1020);
- }
+ case k64:
if (r_dest.IsFloat()) {
DCHECK(!r_dest.IsPair());
- load = NewLIR3(kThumb2Vldrd, r_dest.GetReg(), r_ptr.GetReg(), encoded_disp);
+ load = LoadStoreMaxDisp1020(kThumb2Vldrd, r_base, displacement, r_dest);
} else {
- load = NewLIR4(kThumb2LdrdI8, r_dest.GetLowReg(), r_dest.GetHighReg(), r_ptr.GetReg(),
- encoded_disp);
- }
- if ((displacement & ~1020) != 0 && r_dest.IsFloat()) {
- FreeTemp(r_ptr);
+ DCHECK(r_dest.IsPair());
+ // Use the r_dest.GetLow() for the temporary pointer if needed.
+ load = LoadStoreMaxDisp1020(kThumb2LdrdI8, r_base, displacement, r_dest, r_dest.GetLow());
}
already_generated = true;
break;
- }
case kSingle:
// Intentional fall-though.
case k32:
// Intentional fall-though.
case kReference:
if (r_dest.IsFloat()) {
- opcode = kThumb2Vldrs;
- if (displacement <= 1020) {
- short_form = true;
- encoded_disp >>= 2;
- }
+ DCHECK(r_dest.IsSingle());
+ load = LoadStoreMaxDisp1020(kThumb2Vldrs, r_base, displacement, r_dest);
+ already_generated = true;
break;
}
if (r_dest.Low8() && (r_base == rs_rARM_PC) && (displacement <= 1020) &&
@@ -934,13 +944,8 @@ LIR* ArmMir2Lir::LoadBaseDispBody(RegStorage r_base, int displacement, RegStorag
} else {
RegStorage reg_offset = AllocTemp();
LoadConstant(reg_offset, encoded_disp);
- if (r_dest.IsFloat()) {
- // No index ops - must use a long sequence. Turn the offset into a direct pointer.
- OpRegReg(kOpAdd, reg_offset, r_base);
- load = LoadBaseDispBody(reg_offset, 0, r_dest, size);
- } else {
- load = LoadBaseIndexed(r_base, reg_offset, r_dest, 0, size);
- }
+ DCHECK(!r_dest.IsFloat());
+ load = LoadBaseIndexed(r_base, reg_offset, r_dest, 0, size);
FreeTemp(reg_offset);
}
}
@@ -992,28 +997,16 @@ LIR* ArmMir2Lir::StoreBaseDispBody(RegStorage r_base, int displacement, RegStora
switch (size) {
case kDouble:
// Intentional fall-though.
- case k64: {
- DCHECK_EQ(displacement & 3, 0);
- encoded_disp = (displacement & 1020) >> 2; // Within range of kThumb2Vstrd/kThumb2StrdI8.
- RegStorage r_ptr = r_base;
- if ((displacement & ~1020) != 0) {
- r_ptr = AllocTemp();
- // Add displacement & ~1020 to base, it's a single instruction for up to +-256KiB.
- OpRegRegImm(kOpAdd, r_ptr, r_base, displacement & ~1020);
- }
+ case k64:
if (r_src.IsFloat()) {
DCHECK(!r_src.IsPair());
- store = NewLIR3(kThumb2Vstrd, r_src.GetReg(), r_ptr.GetReg(), encoded_disp);
+ store = LoadStoreMaxDisp1020(kThumb2Vstrd, r_base, displacement, r_src);
} else {
- store = NewLIR4(kThumb2StrdI8, r_src.GetLowReg(), r_src.GetHighReg(), r_ptr.GetReg(),
- encoded_disp);
- }
- if ((displacement & ~1020) != 0) {
- FreeTemp(r_ptr);
+ DCHECK(r_src.IsPair());
+ store = LoadStoreMaxDisp1020(kThumb2StrdI8, r_base, displacement, r_src);
}
already_generated = true;
break;
- }
case kSingle:
// Intentional fall-through.
case k32:
@@ -1021,11 +1014,8 @@ LIR* ArmMir2Lir::StoreBaseDispBody(RegStorage r_base, int displacement, RegStora
case kReference:
if (r_src.IsFloat()) {
DCHECK(r_src.IsSingle());
- opcode = kThumb2Vstrs;
- if (displacement <= 1020) {
- short_form = true;
- encoded_disp >>= 2;
- }
+ store = LoadStoreMaxDisp1020(kThumb2Vstrs, r_base, displacement, r_src);
+ already_generated = true;
break;
}
if (r_src.Low8() && (r_base == rs_r13sp) && (displacement <= 1020) && (displacement >= 0)) {
@@ -1073,13 +1063,8 @@ LIR* ArmMir2Lir::StoreBaseDispBody(RegStorage r_base, int displacement, RegStora
} else {
RegStorage r_scratch = AllocTemp();
LoadConstant(r_scratch, encoded_disp);
- if (r_src.IsFloat()) {
- // No index ops - must use a long sequence. Turn the offset into a direct pointer.
- OpRegReg(kOpAdd, r_scratch, r_base);
- store = StoreBaseDispBody(r_scratch, 0, r_src, size);
- } else {
- store = StoreBaseIndexed(r_base, r_scratch, r_src, 0, size);
- }
+ DCHECK(!r_src.IsFloat());
+ store = StoreBaseIndexed(r_base, r_scratch, r_src, 0, size);
FreeTemp(r_scratch);
}
}