| Index: src/a64/macro-assembler-a64.h
|
| diff --git a/src/a64/macro-assembler-a64.h b/src/a64/macro-assembler-a64.h
|
| index 8bd24d3033f6eb9d945e5363359b37b6087de2af..7b8dd3f806734d3f4dfed8b984998b39da58b402 100644
|
| --- a/src/a64/macro-assembler-a64.h
|
| +++ b/src/a64/macro-assembler-a64.h
|
| @@ -212,7 +212,7 @@ class MacroAssembler : public Assembler {
|
| inline void Asr(const Register& rd, const Register& rn, const Register& rm);
|
| inline void B(Label* label);
|
| inline void B(Condition cond, Label* label);
|
| - inline void B(Label* label, Condition cond);
|
| + void B(Label* label, Condition cond);
|
| inline void Bfi(const Register& rd,
|
| const Register& rn,
|
| unsigned lsb,
|
| @@ -226,8 +226,8 @@ class MacroAssembler : public Assembler {
|
| inline void Blr(const Register& xn);
|
| inline void Br(const Register& xn);
|
| inline void Brk(int code);
|
| - inline void Cbnz(const Register& rt, Label* label);
|
| - inline void Cbz(const Register& rt, Label* label);
|
| + void Cbnz(const Register& rt, Label* label);
|
| + void Cbz(const Register& rt, Label* label);
|
| inline void Cinc(const Register& rd, const Register& rn, Condition cond);
|
| inline void Cinv(const Register& rd, const Register& rn, Condition cond);
|
| inline void Cls(const Register& rd, const Register& rn);
|
| @@ -400,8 +400,8 @@ class MacroAssembler : public Assembler {
|
| inline void Sxtb(const Register& rd, const Register& rn);
|
| inline void Sxth(const Register& rd, const Register& rn);
|
| inline void Sxtw(const Register& rd, const Register& rn);
|
| - inline void Tbnz(const Register& rt, unsigned bit_pos, Label* label);
|
| - inline void Tbz(const Register& rt, unsigned bit_pos, Label* label);
|
| + void Tbnz(const Register& rt, unsigned bit_pos, Label* label);
|
| + void Tbz(const Register& rt, unsigned bit_pos, Label* label);
|
| inline void Ubfiz(const Register& rd,
|
| const Register& rn,
|
| unsigned lsb,
|
| @@ -422,7 +422,6 @@ class MacroAssembler : public Assembler {
|
| const Register& rn,
|
| const Register& rm,
|
| const Register& ra);
|
| - inline void Unreachable();
|
| inline void Uxtb(const Register& rd, const Register& rn);
|
| inline void Uxth(const Register& rd, const Register& rn);
|
| inline void Uxtw(const Register& rd, const Register& rn);
|
| @@ -2074,6 +2073,58 @@ class MacroAssembler : public Assembler {
|
| Heap::RootListIndex map_index,
|
| Register scratch1,
|
| Register scratch2);
|
| +
|
| + public:
|
| + // Far branches resolving.
|
| + //
|
| + // The various classes of branch instructions with immediate offsets have
|
| + // different ranges. While the Assembler will fail to assemble a branch
|
| + // exceeding its range, the MacroAssembler offers a mechanism to resolve
|
| + // branches to too distant targets, either by tweaking the generated code to
|
| + // use branch instructions with wider ranges or generating veneers.
|
| + //
|
| + // Currently branches to distant targets are resolved using unconditional
|
| + // branch isntructions with a range of +-128MB. If that becomes too little
|
| + // (!), the mechanism can be extended to generate special veneers for really
|
| + // far targets.
|
| +
|
| + // Returns true if we should emit a veneer as soon as possible for a branch
|
| + // which can at most reach to specified pc.
|
| + bool ShouldEmitVeneer(int max_reachable_pc,
|
| + int margin = kVeneerDistanceMargin);
|
| +
|
| + // The maximum code size generated for a veneer. Currently one branch
|
| + // instruction. This is for code size checking purposes, and can be extended
|
| + // in the future for example if we decide to add nops between the veneers.
|
| + static const int kMaxVeneerCodeSize = 1 * kInstructionSize;
|
| +
|
| + // Emits veneers for branches that are approaching their maximum range.
|
| + // If need_protection is true, the veneers are protected by a branch jumping
|
| + // over the code.
|
| + void EmitVeneers(bool need_protection);
|
| + void EmitVeneersGuard();
|
| + // Checks wether veneers need to be emitted at this point.
|
| + void CheckVeneers(bool need_protection);
|
| +
|
| + // Helps resolve branching to labels potentially out of range.
|
| + // If the label is not bound, it registers the information necessary to later
|
| + // be able to emit a veneer for this branch if necessary.
|
| + // If the label is bound, it returns true if the label (or the previous link
|
| + // in the label chain) is out of range. In that case the caller is responsible
|
| + // for generating appropriate code.
|
| + // Otherwise it returns false.
|
| + // This function also checks wether veneers need to be emitted.
|
| + bool NeedExtraInstructionsOrRegisterBranch(Label *label,
|
| + ImmBranchType branch_type);
|
| +
|
| + private:
|
| + // We generate a veneer for a branch if we reach within this distance of the
|
| + // limit of the range.
|
| + static const int kVeneerDistanceMargin = 2 * KB;
|
| + int unresolved_branches_first_limit() const {
|
| + ASSERT(!unresolved_branches_.empty());
|
| + return unresolved_branches_.begin()->first;
|
| + }
|
| };
|
|
|
|
|
| @@ -2083,20 +2134,13 @@ class MacroAssembler : public Assembler {
|
| // emitted is what you specified when creating the scope.
|
| class InstructionAccurateScope BASE_EMBEDDED {
|
| public:
|
| - explicit InstructionAccurateScope(MacroAssembler* masm)
|
| - : masm_(masm), size_(0) {
|
| - masm_->StartBlockConstPool();
|
| -#ifdef DEBUG
|
| - previous_allow_macro_instructions_ = masm_->allow_macro_instructions();
|
| - masm_->set_allow_macro_instructions(false);
|
| -#endif
|
| - }
|
| -
|
| - InstructionAccurateScope(MacroAssembler* masm, size_t count)
|
| + InstructionAccurateScope(MacroAssembler* masm, size_t count = 0)
|
| : masm_(masm), size_(count * kInstructionSize) {
|
| masm_->StartBlockConstPool();
|
| #ifdef DEBUG
|
| - masm_->bind(&start_);
|
| + if (count != 0) {
|
| + masm_->bind(&start_);
|
| + }
|
| previous_allow_macro_instructions_ = masm_->allow_macro_instructions();
|
| masm_->set_allow_macro_instructions(false);
|
| #endif
|
|
|