Use the thumb2 assembler for the optimizing compiler.
Change-Id: I2b058f4433504dc3299c06f5cb0b5ab12f34aa82
diff --git a/compiler/utils/arm/assembler_arm.cc b/compiler/utils/arm/assembler_arm.cc
index 8a34928..5fe8246 100644
--- a/compiler/utils/arm/assembler_arm.cc
+++ b/compiler/utils/arm/assembler_arm.cc
@@ -169,9 +169,7 @@
return ArmAssembler::ModifiedImmediate(immediate) != kInvalidModifiedImmediate;
case MOV:
- if (immediate < (1 << 12)) { // Less than (or equal to) 12 bits can always be done.
- return true;
- }
+ // TODO: Support less than or equal to 12bits.
return ArmAssembler::ModifiedImmediate(immediate) != kInvalidModifiedImmediate;
case MVN:
default:
diff --git a/compiler/utils/arm/assembler_thumb2.cc b/compiler/utils/arm/assembler_thumb2.cc
index 604f59e..2ce4fd2 100644
--- a/compiler/utils/arm/assembler_thumb2.cc
+++ b/compiler/utils/arm/assembler_thumb2.cc
@@ -877,6 +877,7 @@
rn_shift = 8;
} else {
thumb_opcode = 0b1010;
+ rd = rn;
rn = so.GetRegister();
}
@@ -1470,6 +1471,7 @@
// branch the size may change if it so happens that other branches change size that change
// the distance to the target and that distance puts this branch over the limit for 16 bits.
if (size == Branch::k16Bit) {
+ DCHECK(!force_32bit_branches_);
Emit16(0); // Space for a 16 bit branch.
} else {
Emit32(0); // Space for a 32 bit branch.
@@ -1477,7 +1479,7 @@
} else {
// Branch is to an unbound label. Emit space for it.
uint16_t branch_id = AddBranch(branch_type, pc, cond); // Unresolved branch.
- if (force_32bit_) {
+ if (force_32bit_branches_ || force_32bit_) {
Emit16(static_cast<uint16_t>(label->position_)); // Emit current label link.
Emit16(0); // another 16 bits.
} else {
@@ -2073,6 +2075,7 @@
uint32_t branch_location = branch->GetLocation();
uint16_t next = buffer_.Load<uint16_t>(branch_location); // Get next in chain.
if (changed) {
+ DCHECK(!force_32bit_branches_);
MakeHoleForBranch(branch->GetLocation(), 2);
if (branch->IsCompareAndBranch()) {
// A cbz/cbnz instruction has changed size. There is no valid encoding for
diff --git a/compiler/utils/arm/assembler_thumb2.h b/compiler/utils/arm/assembler_thumb2.h
index 5f24e4e..f1ae3d8 100644
--- a/compiler/utils/arm/assembler_thumb2.h
+++ b/compiler/utils/arm/assembler_thumb2.h
@@ -29,10 +29,13 @@
namespace art {
namespace arm {
-
class Thumb2Assembler FINAL : public ArmAssembler {
public:
- Thumb2Assembler() : force_32bit_(false), it_cond_index_(kNoItCondition), next_condition_(AL) {
+ Thumb2Assembler(bool force_32bit_branches = false)
+ : force_32bit_branches_(force_32bit_branches),
+ force_32bit_(false),
+ it_cond_index_(kNoItCondition),
+ next_condition_(AL) {
}
virtual ~Thumb2Assembler() {
@@ -49,6 +52,10 @@
return force_32bit_;
}
+ bool IsForced32BitBranches() const {
+ return force_32bit_branches_;
+ }
+
void FinalizeInstructions(const MemoryRegion& region) OVERRIDE {
EmitBranches();
Assembler::FinalizeInstructions(region);
@@ -412,7 +419,8 @@
void EmitShift(Register rd, Register rm, Shift shift, uint8_t amount, bool setcc = false);
void EmitShift(Register rd, Register rn, Shift shift, Register rm, bool setcc = false);
- bool force_32bit_; // Force the assembler to use 32 bit thumb2 instructions.
+ bool force_32bit_branches_; // Force the assembler to use 32 bit branch instructions.
+ bool force_32bit_; // Force the assembler to use 32 bit thumb2 instructions.
// IfThen conditions. Used to check that conditional instructions match the preceding IT.
Condition it_conditions_[4];
@@ -605,6 +613,9 @@
private:
// Calculate the size of the branch instruction based on its type and offset.
Size CalculateSize() const {
+ if (assembler_->IsForced32BitBranches()) {
+ return k32Bit;
+ }
if (target_ == kUnresolved) {
if (assembler_->IsForced32Bit() && (type_ == kUnconditional || type_ == kConditional)) {
return k32Bit;