diff options
| author | 2015-05-20 12:31:08 +0100 | |
|---|---|---|
| committer | 2015-05-20 18:44:51 +0100 | |
| commit | db0bbab279534974dca507946c66cff2d05dc9f9 (patch) | |
| tree | 190c7ace8cfb404202a342bef51aa967592c8d6b | |
| parent | 099d3750d59719cecffdf49284f2633308b9c221 (diff) | |
Introduce a NearLabel in thumb2.
This tells the assembler that the user knows the encoding
can be in 16bits.
Change-Id: Idf36c38beb1e07a69862c972484aeb08326a0499
| -rw-r--r-- | compiler/optimizing/code_generator_arm.cc | 16 | ||||
| -rw-r--r-- | compiler/utils/arm/assembler_arm.h | 16 | ||||
| -rw-r--r-- | compiler/utils/arm/assembler_arm32.h | 4 | ||||
| -rw-r--r-- | compiler/utils/arm/assembler_thumb2.cc | 17 | ||||
| -rw-r--r-- | compiler/utils/arm/assembler_thumb2.h | 28 |
5 files changed, 62 insertions, 19 deletions
diff --git a/compiler/optimizing/code_generator_arm.cc b/compiler/optimizing/code_generator_arm.cc index 1c76630efe..7a0c9c1d31 100644 --- a/compiler/optimizing/code_generator_arm.cc +++ b/compiler/optimizing/code_generator_arm.cc @@ -2883,7 +2883,7 @@ void InstructionCodeGeneratorARM::VisitCompare(HCompare* compare) { Location left = locations->InAt(0); Location right = locations->InAt(1); - Label less, greater, done; + NearLabel less, greater, done; Primitive::Type type = compare->InputAt(0)->GetType(); switch (type) { case Primitive::kPrimLong: { @@ -2979,7 +2979,7 @@ void InstructionCodeGeneratorARM::GenerateWideAtomicStore(Register addr, Register temp1, Register temp2, HInstruction* instruction) { - Label fail; + NearLabel fail; if (offset != 0) { __ LoadImmediate(temp1, offset); __ add(IP, addr, ShifterOperand(temp1)); @@ -3659,7 +3659,7 @@ void CodeGeneratorARM::MarkGCCard(Register temp, Register object, Register value, bool can_be_null) { - Label is_null; + NearLabel is_null; if (can_be_null) { __ CompareAndBranchIfZero(value, &is_null); } @@ -4081,14 +4081,13 @@ void InstructionCodeGeneratorARM::VisitInstanceOf(HInstanceOf* instruction) { Register cls = locations->InAt(1).AsRegister<Register>(); Register out = locations->Out().AsRegister<Register>(); uint32_t class_offset = mirror::Object::ClassOffset().Int32Value(); - Label done, zero; + NearLabel done, zero; SlowPathCodeARM* slow_path = nullptr; // Return 0 if `obj` is null. // avoid null check if we know obj is not null. if (instruction->MustDoNullCheck()) { - __ cmp(obj, ShifterOperand(0)); - __ b(&zero, EQ); + __ CompareAndBranchIfZero(obj, &zero); } // Compare the class of `obj` with `cls`. __ LoadFromOffset(kLoadWord, out, obj, class_offset); @@ -4139,16 +4138,17 @@ void InstructionCodeGeneratorARM::VisitCheckCast(HCheckCast* instruction) { instruction, locations->InAt(1), locations->GetTemp(0), instruction->GetDexPc()); codegen_->AddSlowPath(slow_path); + NearLabel done; // avoid null check if we know obj is not null. if (instruction->MustDoNullCheck()) { - __ cmp(obj, ShifterOperand(0)); - __ b(slow_path->GetExitLabel(), EQ); + __ CompareAndBranchIfZero(obj, &done); } // Compare the class of `obj` with `cls`. __ LoadFromOffset(kLoadWord, temp, obj, class_offset); __ cmp(temp, ShifterOperand(cls)); __ b(slow_path->GetEntryLabel(), NE); __ Bind(slow_path->GetExitLabel()); + __ Bind(&done); } void LocationsBuilderARM::VisitMonitorOperation(HMonitorOperation* instruction) { diff --git a/compiler/utils/arm/assembler_arm.h b/compiler/utils/arm/assembler_arm.h index dee8287e67..a19a7645c2 100644 --- a/compiler/utils/arm/assembler_arm.h +++ b/compiler/utils/arm/assembler_arm.h @@ -33,6 +33,16 @@ namespace arm { class Arm32Assembler; class Thumb2Assembler; +// This class indicates that the label and its uses +// will fall into a range that is encodable in 16bits on thumb2. +class NearLabel : public Label { + public: + NearLabel() {} + + private: + DISALLOW_COPY_AND_ASSIGN(NearLabel); +}; + class ShifterOperand { public: ShifterOperand() : type_(kUnknown), rm_(kNoRegister), rs_(kNoRegister), @@ -519,6 +529,9 @@ class ArmAssembler : public Assembler { // Branch instructions. virtual void b(Label* label, Condition cond = AL) = 0; + virtual void b(NearLabel* label, Condition cond = AL) { + b(reinterpret_cast<Label*>(label), cond); + } virtual void bl(Label* label, Condition cond = AL) = 0; virtual void blx(Register rm, Condition cond = AL) = 0; virtual void bx(Register rm, Condition cond = AL) = 0; @@ -654,6 +667,9 @@ class ArmAssembler : public Assembler { virtual void Bind(Label* label) = 0; virtual void CompareAndBranchIfZero(Register r, Label* label) = 0; + virtual void CompareAndBranchIfZero(Register r, NearLabel* label) { + CompareAndBranchIfZero(r, reinterpret_cast<Label*>(label)); + } virtual void CompareAndBranchIfNonZero(Register r, Label* label) = 0; // diff --git a/compiler/utils/arm/assembler_arm32.h b/compiler/utils/arm/assembler_arm32.h index 55ec7b46d8..45647675e8 100644 --- a/compiler/utils/arm/assembler_arm32.h +++ b/compiler/utils/arm/assembler_arm32.h @@ -201,8 +201,8 @@ class Arm32Assembler FINAL : public ArmAssembler { void vpopd(DRegister reg, int nregs, Condition cond = AL) OVERRIDE; // Branch instructions. - void b(Label* label, Condition cond = AL); - void bl(Label* label, Condition cond = AL); + void b(Label* label, Condition cond = AL) OVERRIDE; + void bl(Label* label, Condition cond = AL) OVERRIDE; void blx(Register rm, Condition cond = AL) OVERRIDE; void bx(Register rm, Condition cond = AL) OVERRIDE; void Lsl(Register rd, Register rm, uint32_t shift_imm, bool setcc = false, diff --git a/compiler/utils/arm/assembler_thumb2.cc b/compiler/utils/arm/assembler_thumb2.cc index 75f2b77c96..c3b19da498 100644 --- a/compiler/utils/arm/assembler_thumb2.cc +++ b/compiler/utils/arm/assembler_thumb2.cc @@ -671,11 +671,17 @@ void Thumb2Assembler::vcmpdz(DRegister dd, Condition cond) { EmitVFPddd(cond, B23 | B21 | B20 | B18 | B16 | B6, dd, D0, D0); } + void Thumb2Assembler::b(Label* label, Condition cond) { EmitBranch(cond, label, false, false); } +void Thumb2Assembler::b(NearLabel* label, Condition cond) { + EmitBranch(cond, label, false, false, true /* is_near */); +} + + void Thumb2Assembler::bl(Label* label, Condition cond) { CheckCondition(cond); EmitBranch(cond, label, true, false); @@ -1613,7 +1619,7 @@ void Thumb2Assembler::EmitMultiMemOp(Condition cond, } -void Thumb2Assembler::EmitBranch(Condition cond, Label* label, bool link, bool x) { +void Thumb2Assembler::EmitBranch(Condition cond, Label* label, bool link, bool x, bool is_near) { uint32_t pc = buffer_.Size(); Branch::Type branch_type; if (cond == AL) { @@ -1644,8 +1650,8 @@ void Thumb2Assembler::EmitBranch(Condition cond, Label* label, bool link, bool x } } else { // Branch is to an unbound label. Emit space for it. - uint16_t branch_id = AddBranch(branch_type, pc, cond); // Unresolved branch. - if (!CanRelocateBranches() || force_32bit_) { + uint16_t branch_id = AddBranch(branch_type, pc, cond, is_near); // Unresolved branch. + if (force_32bit_ || (!CanRelocateBranches() && !is_near)) { Emit16(static_cast<uint16_t>(label->position_)); // Emit current label link. Emit16(0); // another 16 bits. } else { @@ -2750,6 +2756,11 @@ void Thumb2Assembler::CompareAndBranchIfZero(Register r, Label* label) { } +void Thumb2Assembler::CompareAndBranchIfZero(Register r, NearLabel* label) { + cbz(r, label); +} + + void Thumb2Assembler::CompareAndBranchIfNonZero(Register r, Label* label) { if (CanRelocateBranches()) { cbnz(r, label); diff --git a/compiler/utils/arm/assembler_thumb2.h b/compiler/utils/arm/assembler_thumb2.h index 90d489fb02..e8def73609 100644 --- a/compiler/utils/arm/assembler_thumb2.h +++ b/compiler/utils/arm/assembler_thumb2.h @@ -239,6 +239,7 @@ class Thumb2Assembler FINAL : public ArmAssembler { // Branch instructions. void b(Label* label, Condition cond = AL); + void b(NearLabel* label, Condition cond = AL); void bl(Label* label, Condition cond = AL); void blx(Label* label); void blx(Register rm, Condition cond = AL) OVERRIDE; @@ -273,6 +274,7 @@ class Thumb2Assembler FINAL : public ArmAssembler { void Mov(Register rd, Register rm, Condition cond = AL) OVERRIDE; void CompareAndBranchIfZero(Register r, Label* label) OVERRIDE; + void CompareAndBranchIfZero(Register r, NearLabel* label) OVERRIDE; void CompareAndBranchIfNonZero(Register r, Label* label) OVERRIDE; // Memory barriers. @@ -431,7 +433,7 @@ class Thumb2Assembler FINAL : public ArmAssembler { void EmitVPushPop(uint32_t reg, int nregs, bool push, bool dbl, Condition cond); - void EmitBranch(Condition cond, Label* label, bool link, bool x); + void EmitBranch(Condition cond, Label* label, bool link, bool x, bool is_near = false); static int32_t EncodeBranchOffset(int32_t offset, int32_t inst); static int DecodeBranchOffset(int32_t inst); int32_t EncodeTstOffset(int offset, int32_t inst); @@ -559,6 +561,7 @@ class Thumb2Assembler FINAL : public ArmAssembler { // Resolve a branch when the target is known. If this causes the // size of the branch to change return true. Otherwise return false. bool Resolve(uint32_t target) { + uint32_t old_target = target_; target_ = target; if (assembler_->CanRelocateBranches()) { Size new_size = CalculateSize(); @@ -569,9 +572,11 @@ class Thumb2Assembler FINAL : public ArmAssembler { return false; } else { if (kIsDebugBuild) { - Size new_size = CalculateSize(); - // Check that the size has not increased. - DCHECK(!(new_size == k32Bit && size_ == k16Bit)); + if (old_target == kUnresolved) { + DCHECK(!(CalculateSize() == k32Bit && size_ == k16Bit)); + } else { + DCHECK(CalculateSize() == size_); + } } return false; } @@ -651,6 +656,10 @@ class Thumb2Assembler FINAL : public ArmAssembler { if (assembler_->IsForced32Bit() && (type_ == kUnconditional || type_ == kConditional)) { return k32Bit; } + if (IsCompareAndBranch()) { + // Compare and branch instructions can only be encoded on 16 bits. + return k16Bit; + } return assembler_->CanRelocateBranches() ? k16Bit : k32Bit; } // When the target is resolved, we know the best encoding for it. @@ -714,8 +723,15 @@ class Thumb2Assembler FINAL : public ArmAssembler { } // Add an unresolved branch and return its id. - uint16_t AddBranch(Branch::Type type, uint32_t location, Condition cond = AL) { - branches_.push_back(new Branch(this, type, location, cond)); + uint16_t AddBranch(Branch::Type type, + uint32_t location, + Condition cond = AL, + bool is_near = false) { + Branch* branch = new Branch(this, type, location, cond); + if (is_near) { + branch->ResetSize(Branch::k16Bit); + } + branches_.push_back(branch); return branches_.size() - 1; } |