1b78f13911bfe6eda303e91ef215c87a165aae8aeAlexandre Rames// Copyright 2015, VIXL authors
288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois// All rights reserved.
388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois//
488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois// Redistribution and use in source and binary forms, with or without
588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois// modification, are permitted provided that the following conditions are met:
688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois//
788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois//   * Redistributions of source code must retain the above copyright notice,
888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois//     this list of conditions and the following disclaimer.
988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois//   * Redistributions in binary form must reproduce the above copyright notice,
1088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois//     this list of conditions and the following disclaimer in the documentation
1188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois//     and/or other materials provided with the distribution.
1288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois//   * Neither the name of ARM Limited nor the names of its contributors may be
1388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois//     used to endorse or promote products derived from this software without
1488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois//     specific prior written permission.
1588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois//
1688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS CONTRIBUTORS "AS IS" AND
1788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
1888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
1988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
2088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
2288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
2388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
2488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
2588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
27d3832965c62a8ad461b9ea9eb0994ca6b0a3da2cAlexandre Rames#ifndef VIXL_AARCH32_LABEL_AARCH32_H_
28d3832965c62a8ad461b9ea9eb0994ca6b0a3da2cAlexandre Rames#define VIXL_AARCH32_LABEL_AARCH32_H_
2988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
3078973f258039f6e96eba85f1b5ecdb14b3c51dbbPierre Langloisextern "C" {
3188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois#include <stdint.h>
3278973f258039f6e96eba85f1b5ecdb14b3c51dbbPierre Langlois}
3378973f258039f6e96eba85f1b5ecdb14b3c51dbbPierre Langlois
34bf01e787b9ca4ff28b8c4d4355fd575c4ac81dfaAnton Kirilov#include <algorithm>
3578973f258039f6e96eba85f1b5ecdb14b3c51dbbPierre Langlois#include <cstddef>
3688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois#include <iomanip>
3778973f258039f6e96eba85f1b5ecdb14b3c51dbbPierre Langlois#include <list>
3888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
39bf01e787b9ca4ff28b8c4d4355fd575c4ac81dfaAnton Kirilov#include "utils-vixl.h"
40bf01e787b9ca4ff28b8c4d4355fd575c4ac81dfaAnton Kirilov
418d191abf32edf41421f68f35585e4fce8da4d50cAlexandre Rames#include "constants-aarch32.h"
428d191abf32edf41421f68f35585e4fce8da4d50cAlexandre Rames
4388c46b84df005638546de5e4e965bdcc31352f48Pierre Langloisnamespace vixl {
4488c46b84df005638546de5e4e965bdcc31352f48Pierre Langloisnamespace aarch32 {
4588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
467827144797ee5ebfa0b574f45ad8ff235f919304Vincent Belliardclass VeneerPoolManager;
477827144797ee5ebfa0b574f45ad8ff235f919304Vincent Belliardclass MacroAssembler;
487827144797ee5ebfa0b574f45ad8ff235f919304Vincent Belliard
4988c46b84df005638546de5e4e965bdcc31352f48Pierre Langloisclass Label {
5088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois public:
5188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  typedef int32_t Offset;
5288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  static const Offset kMaxOffset = 0x7fffffff;
5388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
5488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  class LabelEmitOperator {
5588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    Label::Offset max_backward_;
5688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    Label::Offset max_forward_;
5788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
5888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois   public:
5988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    LabelEmitOperator(Label::Offset max_backward, Label::Offset max_forward)
6088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois        : max_backward_(max_backward), max_forward_(max_forward) {}
6188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    virtual ~LabelEmitOperator() {}
6288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    virtual uint32_t Encode(uint32_t /*instr*/,
6388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois                            Label::Offset /*pc*/,
6488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois                            const Label* /*label*/) const {
6588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois      return 0;
6688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    }
6788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    Label::Offset GetMaxForwardDistance() const { return max_forward_; }
6888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    Label::Offset GetMaxBackwardDistance() const { return max_backward_; }
6988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  };
7088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
7188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  class ForwardReference {
7288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois   public:
739a9331faeba996d6c85e6e2a6355ccfc22c6cab6Rodolph Perfetta    ForwardReference(int32_t location,
749a9331faeba996d6c85e6e2a6355ccfc22c6cab6Rodolph Perfetta                     const LabelEmitOperator& op,
759a9331faeba996d6c85e6e2a6355ccfc22c6cab6Rodolph Perfetta                     InstructionSet isa)
769a9331faeba996d6c85e6e2a6355ccfc22c6cab6Rodolph Perfetta        : location_(location), op_(op), isa_(isa), is_branch_(false) {
779a9331faeba996d6c85e6e2a6355ccfc22c6cab6Rodolph Perfetta#if defined(VIXL_INCLUDE_TARGET_A32_ONLY)
789a9331faeba996d6c85e6e2a6355ccfc22c6cab6Rodolph Perfetta      USE(isa_);
799a9331faeba996d6c85e6e2a6355ccfc22c6cab6Rodolph Perfetta      VIXL_ASSERT(isa_ == A32);
809a9331faeba996d6c85e6e2a6355ccfc22c6cab6Rodolph Perfetta#elif defined(VIXL_INCLUDE_TARGET_T32_ONLY)
819a9331faeba996d6c85e6e2a6355ccfc22c6cab6Rodolph Perfetta      USE(isa_);
829a9331faeba996d6c85e6e2a6355ccfc22c6cab6Rodolph Perfetta      VIXL_ASSERT(isa == T32);
839a9331faeba996d6c85e6e2a6355ccfc22c6cab6Rodolph Perfetta#endif
849a9331faeba996d6c85e6e2a6355ccfc22c6cab6Rodolph Perfetta    }
8588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    Offset GetMaxForwardDistance() const { return op_.GetMaxForwardDistance(); }
86f5348cedd702124c90fc75e75d0195e2e485c620Pierre Langlois    int32_t GetLocation() const { return location_; }
8788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    uint32_t GetStatePCOffset() const {
889a9331faeba996d6c85e6e2a6355ccfc22c6cab6Rodolph Perfetta      return IsUsingT32() ? kT32PcDelta : kA32PcDelta;
8988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    }
909a9331faeba996d6c85e6e2a6355ccfc22c6cab6Rodolph Perfetta
919a9331faeba996d6c85e6e2a6355ccfc22c6cab6Rodolph Perfetta#if defined(VIXL_INCLUDE_TARGET_A32_ONLY)
929a9331faeba996d6c85e6e2a6355ccfc22c6cab6Rodolph Perfetta    bool IsUsingT32() const { return false; }
939a9331faeba996d6c85e6e2a6355ccfc22c6cab6Rodolph Perfetta#elif defined(VIXL_INCLUDE_TARGET_T32_ONLY)
949a9331faeba996d6c85e6e2a6355ccfc22c6cab6Rodolph Perfetta    bool IsUsingT32() const { return true; }
959a9331faeba996d6c85e6e2a6355ccfc22c6cab6Rodolph Perfetta#else
969a9331faeba996d6c85e6e2a6355ccfc22c6cab6Rodolph Perfetta    bool IsUsingT32() const { return isa_ == T32; }
979a9331faeba996d6c85e6e2a6355ccfc22c6cab6Rodolph Perfetta#endif
989a9331faeba996d6c85e6e2a6355ccfc22c6cab6Rodolph Perfetta
9988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    bool IsBranch() const { return is_branch_; }
10088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    void SetIsBranch() { is_branch_ = true; }
10188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    const LabelEmitOperator& GetEmitOperator() const { return op_; }
10288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    Offset GetCheckpoint() const {
10340b7e470e71b158158ef6ce8a1a3f701857ce0e2Vincent Belliard      // The load instructions align down PC before adding the offset.
10440b7e470e71b158158ef6ce8a1a3f701857ce0e2Vincent Belliard      // The alignment is only needed for T32 as A32 instructions are always
10540b7e470e71b158158ef6ce8a1a3f701857ce0e2Vincent Belliard      // 4 byte aligned.
10640b7e470e71b158158ef6ce8a1a3f701857ce0e2Vincent Belliard      int32_t pc = GetLocation() + GetStatePCOffset();
10740b7e470e71b158158ef6ce8a1a3f701857ce0e2Vincent Belliard      return GetMaxForwardDistance() +
10840b7e470e71b158158ef6ce8a1a3f701857ce0e2Vincent Belliard             ((IsUsingT32() && !IsBranch()) ? AlignDown(pc, 4) : pc);
10988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    }
11088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
11188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois   private:
112f5348cedd702124c90fc75e75d0195e2e485c620Pierre Langlois    int32_t location_;
11388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    const LabelEmitOperator& op_;
1149a9331faeba996d6c85e6e2a6355ccfc22c6cab6Rodolph Perfetta    InstructionSet isa_;
11588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    bool is_branch_;
11688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  };
11788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
11888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  typedef std::list<ForwardReference> ForwardRefList;
11988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
12088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  enum UpdateCheckpointOption { kNoUpdateNecessary, kRecomputeCheckpoint };
12188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
12288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  static bool CompareCheckpoints(const ForwardReference& a,
12388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois                                 const ForwardReference& b) {
12488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    return a.GetCheckpoint() < b.GetCheckpoint();
12588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  }
12688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
12788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  Offset GetNextCheckpoint() {
128b323da089731b39a34ad0a77d20f0a96c1c1a1bcVincent Belliard    if (HasForwardReference()) {
12988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois      ForwardRefList::iterator min_checkpoint =
13088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois          std::min_element(forward_.begin(),
13188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois                           forward_.end(),
13288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois                           CompareCheckpoints);
13388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois      return (*min_checkpoint).GetCheckpoint();
13488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    }
13588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    return kMaxOffset;
13688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  }
13788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
13888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois public:
13988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  Label()
14088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois      : imm_offset_(kMaxOffset),
14188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois        pc_offset_(0),
14288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois        is_bound_(false),
14388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois        minus_zero_(false),
1449a9331faeba996d6c85e6e2a6355ccfc22c6cab6Rodolph Perfetta        isa_(kDefaultISA),
145b323da089731b39a34ad0a77d20f0a96c1c1a1bcVincent Belliard        referenced_(false),
1467827144797ee5ebfa0b574f45ad8ff235f919304Vincent Belliard        veneer_pool_manager_(NULL),
14715985a2fcc72ce0ec5e19c410b444ceec899c11fVincent Belliard        is_near_(false),
14888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois        checkpoint_(kMaxOffset) {}
14988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  explicit Label(Offset offset, uint32_t pc_offset, bool minus_zero = false)
15088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois      : imm_offset_(offset),
15188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois        pc_offset_(pc_offset),
15288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois        is_bound_(true),
15388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois        minus_zero_(minus_zero),
1549a9331faeba996d6c85e6e2a6355ccfc22c6cab6Rodolph Perfetta        isa_(kDefaultISA),
155b323da089731b39a34ad0a77d20f0a96c1c1a1bcVincent Belliard        referenced_(false),
1567827144797ee5ebfa0b574f45ad8ff235f919304Vincent Belliard        veneer_pool_manager_(NULL),
15715985a2fcc72ce0ec5e19c410b444ceec899c11fVincent Belliard        is_near_(false),
15888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois        checkpoint_(kMaxOffset) {}
159b323da089731b39a34ad0a77d20f0a96c1c1a1bcVincent Belliard  ~Label() VIXL_THROW_IN_NEGATIVE_TESTING_MODE(std::runtime_error) {
160b323da089731b39a34ad0a77d20f0a96c1c1a1bcVincent Belliard#ifdef VIXL_DEBUG
161b323da089731b39a34ad0a77d20f0a96c1c1a1bcVincent Belliard    if (referenced_ && !is_bound_) {
162b323da089731b39a34ad0a77d20f0a96c1c1a1bcVincent Belliard      VIXL_ABORT_WITH_MSG("Label used but not bound.\n");
163b323da089731b39a34ad0a77d20f0a96c1c1a1bcVincent Belliard    }
164b323da089731b39a34ad0a77d20f0a96c1c1a1bcVincent Belliard#endif
165b323da089731b39a34ad0a77d20f0a96c1c1a1bcVincent Belliard  }
1669a9331faeba996d6c85e6e2a6355ccfc22c6cab6Rodolph Perfetta
1679a9331faeba996d6c85e6e2a6355ccfc22c6cab6Rodolph Perfetta#undef DEFAULT_IS_T32
1689a9331faeba996d6c85e6e2a6355ccfc22c6cab6Rodolph Perfetta
16988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  bool IsBound() const { return is_bound_; }
170b323da089731b39a34ad0a77d20f0a96c1c1a1bcVincent Belliard  bool HasForwardReference() const { return !forward_.empty(); }
1719a9331faeba996d6c85e6e2a6355ccfc22c6cab6Rodolph Perfetta  void Bind(Offset offset, InstructionSet isa) {
17288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    VIXL_ASSERT(!IsBound());
1739a9331faeba996d6c85e6e2a6355ccfc22c6cab6Rodolph Perfetta    USE(isa);
1749a9331faeba996d6c85e6e2a6355ccfc22c6cab6Rodolph Perfetta    USE(isa_);
17588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    imm_offset_ = offset;
17688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    is_bound_ = true;
1779a9331faeba996d6c85e6e2a6355ccfc22c6cab6Rodolph Perfetta#if defined(VIXL_INCLUDE_TARGET_A32_ONLY)
1789a9331faeba996d6c85e6e2a6355ccfc22c6cab6Rodolph Perfetta    VIXL_ASSERT(isa == A32);
1799a9331faeba996d6c85e6e2a6355ccfc22c6cab6Rodolph Perfetta#elif defined(VIXL_INCLUDE_TARGET_T32_ONLY)
1809a9331faeba996d6c85e6e2a6355ccfc22c6cab6Rodolph Perfetta    VIXL_ASSERT(isa == T32);
1819a9331faeba996d6c85e6e2a6355ccfc22c6cab6Rodolph Perfetta#else
1829a9331faeba996d6c85e6e2a6355ccfc22c6cab6Rodolph Perfetta    isa_ = isa;
1839a9331faeba996d6c85e6e2a6355ccfc22c6cab6Rodolph Perfetta#endif
18488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  }
18574e3ecd9dc3ecf92604e37c4ec9b9ced5048dedfVincent Belliard  uint32_t GetPcOffset() const { return pc_offset_; }
18688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  Offset GetLocation() const {
18788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    VIXL_ASSERT(IsBound());
18888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    return imm_offset_ + static_cast<Offset>(pc_offset_);
18988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  }
19010dae1a549308bddc1931f29754d6a4459f70c9bJacob Bramley  bool IsUsingT32() const {
1919a9331faeba996d6c85e6e2a6355ccfc22c6cab6Rodolph Perfetta    VIXL_ASSERT(IsBound());  // Must be bound to know its ISA.
1929a9331faeba996d6c85e6e2a6355ccfc22c6cab6Rodolph Perfetta#if defined(VIXL_INCLUDE_TARGET_A32_ONLY)
1939a9331faeba996d6c85e6e2a6355ccfc22c6cab6Rodolph Perfetta    return false;
1949a9331faeba996d6c85e6e2a6355ccfc22c6cab6Rodolph Perfetta#elif defined(VIXL_INCLUDE_TARGET_T32_ONLY)
1959a9331faeba996d6c85e6e2a6355ccfc22c6cab6Rodolph Perfetta    return true;
1969a9331faeba996d6c85e6e2a6355ccfc22c6cab6Rodolph Perfetta#else
1979a9331faeba996d6c85e6e2a6355ccfc22c6cab6Rodolph Perfetta    return isa_ == T32;
1989a9331faeba996d6c85e6e2a6355ccfc22c6cab6Rodolph Perfetta#endif
19988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  }
20088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  bool IsMinusZero() const {
20188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    VIXL_ASSERT(IsBound());
20288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    return minus_zero_;
20388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  }
204b323da089731b39a34ad0a77d20f0a96c1c1a1bcVincent Belliard  void SetReferenced() { referenced_ = true; }
205b323da089731b39a34ad0a77d20f0a96c1c1a1bcVincent Belliard  bool IsReferenced() const { return referenced_; }
2067827144797ee5ebfa0b574f45ad8ff235f919304Vincent Belliard  bool IsInVeneerPool() const { return veneer_pool_manager_ != NULL; }
2077827144797ee5ebfa0b574f45ad8ff235f919304Vincent Belliard  VeneerPoolManager* GetVeneerPoolManager() const {
2087827144797ee5ebfa0b574f45ad8ff235f919304Vincent Belliard    return veneer_pool_manager_;
2097827144797ee5ebfa0b574f45ad8ff235f919304Vincent Belliard  }
21015985a2fcc72ce0ec5e19c410b444ceec899c11fVincent Belliard  void SetVeneerPoolManager(VeneerPoolManager* veneer_pool_manager,
21115985a2fcc72ce0ec5e19c410b444ceec899c11fVincent Belliard                            bool is_near) {
2127827144797ee5ebfa0b574f45ad8ff235f919304Vincent Belliard    veneer_pool_manager_ = veneer_pool_manager;
21315985a2fcc72ce0ec5e19c410b444ceec899c11fVincent Belliard    is_near_ = is_near;
2147827144797ee5ebfa0b574f45ad8ff235f919304Vincent Belliard  }
2157827144797ee5ebfa0b574f45ad8ff235f919304Vincent Belliard  void ClearVeneerPoolManager() { veneer_pool_manager_ = NULL; }
21615985a2fcc72ce0ec5e19c410b444ceec899c11fVincent Belliard  bool IsNear() const { return is_near_; }
21788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  void SetCheckpoint(Offset checkpoint) { checkpoint_ = checkpoint; }
21888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  Offset GetCheckpoint() const { return checkpoint_; }
21988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  Offset GetAlignedCheckpoint(int byte_align) const {
22088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    return AlignDown(GetCheckpoint(), byte_align);
22188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  }
222f5348cedd702124c90fc75e75d0195e2e485c620Pierre Langlois  void AddForwardRef(int32_t instr_location,
2239a9331faeba996d6c85e6e2a6355ccfc22c6cab6Rodolph Perfetta                     InstructionSet isa,
22488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois                     const LabelEmitOperator& op) {
225b323da089731b39a34ad0a77d20f0a96c1c1a1bcVincent Belliard    VIXL_ASSERT(referenced_);
2269a9331faeba996d6c85e6e2a6355ccfc22c6cab6Rodolph Perfetta    forward_.push_back(ForwardReference(instr_location, op, isa));
22788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  }
22888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
22988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  ForwardRefList::iterator GetFirstForwardRef() { return forward_.begin(); }
23088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  ForwardRefList::iterator GetEndForwardRef() { return forward_.end(); }
231f8833fa525b25cb1d72beb4f2d033d5ad9a3eb80Vincent Belliard  const ForwardReference* GetForwardRefBack() const {
232f8833fa525b25cb1d72beb4f2d033d5ad9a3eb80Vincent Belliard    if (forward_.empty()) return NULL;
233f8833fa525b25cb1d72beb4f2d033d5ad9a3eb80Vincent Belliard    return &forward_.back();
234f8833fa525b25cb1d72beb4f2d033d5ad9a3eb80Vincent Belliard  }
23588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  // Erase an item in the list. We don't have to recompute the checkpoint as
23688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  // the caller does it.
23788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  ForwardRefList::iterator Erase(ForwardRefList::iterator ref) {
23888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    return forward_.erase(ref);
23988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  }
24088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  ForwardReference& GetBackForwardRef() { return forward_.back(); }
24188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
24288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  void ClearForwardRef() { forward_.clear(); }
24388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
24488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  // Only used by the literal pool.
24588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  // Removes the last forward reference, in particular because of a rewind.
24688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  // TODO(all): This is hard to test as the checkpoint could be affected only
24788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  //   if the literal has multiple forward references. So, the literal has to be
24888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  //   shared between multiple instructions and part of the literal pool which
24988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  //   is not yet supperted.
25088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  void InvalidateLastForwardReference(
25188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois      UpdateCheckpointOption update_checkpoint = kRecomputeCheckpoint) {
25288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    if (!IsBound()) {
253b323da089731b39a34ad0a77d20f0a96c1c1a1bcVincent Belliard      VIXL_ASSERT(HasForwardReference());
25488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois      forward_.pop_back();
25588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    }
25688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    VIXL_ASSERT((update_checkpoint == kNoUpdateNecessary) &&
25788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois                ((checkpoint_ == GetNextCheckpoint()) ||
25888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois                 ((checkpoint_ == Label::kMaxOffset) && forward_.empty())));
25988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    if (update_checkpoint == kRecomputeCheckpoint) {
26088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois      checkpoint_ = GetNextCheckpoint();
26188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    }
26288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  }
26388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
26488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  // Only used by the literal pool.
26588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  // Update the checkpoint as the shorter distance from the last
26688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  // literal in the pool's reference location to the point
26788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  // where the forward reference will fail.
26888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  // The last forward reference is assumed to be the one freshly
26988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  // added regarding this literal.
27088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  void UpdateCheckpoint() {
271b323da089731b39a34ad0a77d20f0a96c1c1a1bcVincent Belliard    if (HasForwardReference()) {
27288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois      const ForwardReference& ref = forward_.back();
27388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois      checkpoint_ = std::min(checkpoint_, ref.GetCheckpoint());
27488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    }
27588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    VIXL_ASSERT(GetNextCheckpoint() == checkpoint_);
27688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  }
27788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
27888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  static bool CompareLabels(Label* a, Label* b) {
27988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    return a->GetCheckpoint() < b->GetCheckpoint();
28088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  }
28188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
28288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois private:
28388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  // Once bound, location of this label in the code buffer.
28488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  Offset imm_offset_;
28588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  uint32_t pc_offset_;
28688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  // Is the label bound.
28788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  bool is_bound_;
28888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  // Special flag for 'pc - 0'.
28988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  bool minus_zero_;
2909a9331faeba996d6c85e6e2a6355ccfc22c6cab6Rodolph Perfetta  // Which ISA is the label in.
2919a9331faeba996d6c85e6e2a6355ccfc22c6cab6Rodolph Perfetta  InstructionSet isa_;
292b323da089731b39a34ad0a77d20f0a96c1c1a1bcVincent Belliard  // True if the label has been used at least once.
293b323da089731b39a34ad0a77d20f0a96c1c1a1bcVincent Belliard  bool referenced_;
2947827144797ee5ebfa0b574f45ad8ff235f919304Vincent Belliard  // Not null if the label is currently inserted in the veneer pool.
2957827144797ee5ebfa0b574f45ad8ff235f919304Vincent Belliard  VeneerPoolManager* veneer_pool_manager_;
29615985a2fcc72ce0ec5e19c410b444ceec899c11fVincent Belliard  // True if the label is inserted in the near_labels_ list.
29715985a2fcc72ce0ec5e19c410b444ceec899c11fVincent Belliard  bool is_near_;
29888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  // Contains the references to the unbound label
29988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  ForwardRefList forward_;
30088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  // Max offset in the code buffer. Must be emitted before this checkpoint.
30188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  Offset checkpoint_;
30288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois};
30388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
3047827144797ee5ebfa0b574f45ad8ff235f919304Vincent Belliardclass VeneerPoolManager {
3057827144797ee5ebfa0b574f45ad8ff235f919304Vincent Belliard public:
3067827144797ee5ebfa0b574f45ad8ff235f919304Vincent Belliard  explicit VeneerPoolManager(MacroAssembler* masm)
30715985a2fcc72ce0ec5e19c410b444ceec899c11fVincent Belliard      : masm_(masm),
30815985a2fcc72ce0ec5e19c410b444ceec899c11fVincent Belliard        near_checkpoint_(Label::kMaxOffset),
30915985a2fcc72ce0ec5e19c410b444ceec899c11fVincent Belliard        far_checkpoint_(Label::kMaxOffset),
3102272afbda5f15c4bfb25c3c9bf95d960c9df39d6Vincent Belliard        max_near_checkpoint_(0),
3112272afbda5f15c4bfb25c3c9bf95d960c9df39d6Vincent Belliard        near_checkpoint_margin_(0),
31215985a2fcc72ce0ec5e19c410b444ceec899c11fVincent Belliard        last_label_reference_offset_(0),
31315985a2fcc72ce0ec5e19c410b444ceec899c11fVincent Belliard        monitor_(0) {}
31415985a2fcc72ce0ec5e19c410b444ceec899c11fVincent Belliard  bool IsEmpty() const {
31515985a2fcc72ce0ec5e19c410b444ceec899c11fVincent Belliard    return (near_labels_.size() + far_labels_.size()) == 0;
31615985a2fcc72ce0ec5e19c410b444ceec899c11fVincent Belliard  }
3177827144797ee5ebfa0b574f45ad8ff235f919304Vincent Belliard  Label::Offset GetCheckpoint() const {
31815985a2fcc72ce0ec5e19c410b444ceec899c11fVincent Belliard    // For the far labels, we subtract the veneer size. This way avoids problems
31915985a2fcc72ce0ec5e19c410b444ceec899c11fVincent Belliard    // when two label have the same checkpoint. In the usual case, we lose some
32015985a2fcc72ce0ec5e19c410b444ceec899c11fVincent Belliard    // range but, as the minimum range for far labels is 1 mega byte, it's not
32115985a2fcc72ce0ec5e19c410b444ceec899c11fVincent Belliard    // very important.
32215985a2fcc72ce0ec5e19c410b444ceec899c11fVincent Belliard    size_t veneer_max_size = GetMaxSize();
32315985a2fcc72ce0ec5e19c410b444ceec899c11fVincent Belliard    VIXL_ASSERT(IsInt32(veneer_max_size));
32415985a2fcc72ce0ec5e19c410b444ceec899c11fVincent Belliard    Label::Offset tmp =
32515985a2fcc72ce0ec5e19c410b444ceec899c11fVincent Belliard        far_checkpoint_ - static_cast<Label::Offset>(veneer_max_size);
3267827144797ee5ebfa0b574f45ad8ff235f919304Vincent Belliard    // Make room for a branch over the pools.
3272272afbda5f15c4bfb25c3c9bf95d960c9df39d6Vincent Belliard    return std::min(near_checkpoint_, tmp) - kMaxInstructionSizeInBytes -
3282272afbda5f15c4bfb25c3c9bf95d960c9df39d6Vincent Belliard           near_checkpoint_margin_;
3297827144797ee5ebfa0b574f45ad8ff235f919304Vincent Belliard  }
3307827144797ee5ebfa0b574f45ad8ff235f919304Vincent Belliard  size_t GetMaxSize() const {
33115985a2fcc72ce0ec5e19c410b444ceec899c11fVincent Belliard    return (near_labels_.size() + far_labels_.size()) *
33215985a2fcc72ce0ec5e19c410b444ceec899c11fVincent Belliard           kMaxInstructionSizeInBytes;
3337827144797ee5ebfa0b574f45ad8ff235f919304Vincent Belliard  }
3347827144797ee5ebfa0b574f45ad8ff235f919304Vincent Belliard  void AddLabel(Label* label);
3357827144797ee5ebfa0b574f45ad8ff235f919304Vincent Belliard  void RemoveLabel(Label* label);
33615985a2fcc72ce0ec5e19c410b444ceec899c11fVincent Belliard  void EmitLabel(Label* label, Label::Offset emitted_target);
3377827144797ee5ebfa0b574f45ad8ff235f919304Vincent Belliard  void Emit(Label::Offset target);
3387827144797ee5ebfa0b574f45ad8ff235f919304Vincent Belliard
3398d191abf32edf41421f68f35585e4fce8da4d50cAlexandre Rames  void Block() { monitor_++; }
3408d191abf32edf41421f68f35585e4fce8da4d50cAlexandre Rames  void Release();
3418d191abf32edf41421f68f35585e4fce8da4d50cAlexandre Rames  bool IsBlocked() const { return monitor_ != 0; }
3428d191abf32edf41421f68f35585e4fce8da4d50cAlexandre Rames
3437827144797ee5ebfa0b574f45ad8ff235f919304Vincent Belliard private:
3447827144797ee5ebfa0b574f45ad8ff235f919304Vincent Belliard  MacroAssembler* masm_;
34515985a2fcc72ce0ec5e19c410b444ceec899c11fVincent Belliard  // Lists of all unbound labels which are used by a branch instruction.
34615985a2fcc72ce0ec5e19c410b444ceec899c11fVincent Belliard  std::list<Label*> near_labels_;
34715985a2fcc72ce0ec5e19c410b444ceec899c11fVincent Belliard  std::list<Label*> far_labels_;
3482272afbda5f15c4bfb25c3c9bf95d960c9df39d6Vincent Belliard  // Offset in the code buffer after which the veneer needs to be emitted.
3492272afbda5f15c4bfb25c3c9bf95d960c9df39d6Vincent Belliard  // It's the lowest checkpoint value in the associated list.
3507827144797ee5ebfa0b574f45ad8ff235f919304Vincent Belliard  // A default value of Label::kMaxOffset means that the checkpoint is
3512272afbda5f15c4bfb25c3c9bf95d960c9df39d6Vincent Belliard  // invalid (no entry in the list).
35215985a2fcc72ce0ec5e19c410b444ceec899c11fVincent Belliard  Label::Offset near_checkpoint_;
35315985a2fcc72ce0ec5e19c410b444ceec899c11fVincent Belliard  Label::Offset far_checkpoint_;
3542272afbda5f15c4bfb25c3c9bf95d960c9df39d6Vincent Belliard  // Highest checkpoint value for the near list.
3552272afbda5f15c4bfb25c3c9bf95d960c9df39d6Vincent Belliard  Label::Offset max_near_checkpoint_;
3562272afbda5f15c4bfb25c3c9bf95d960c9df39d6Vincent Belliard  // Margin we have to take to ensure that 16 bit branch instructions will be
3572272afbda5f15c4bfb25c3c9bf95d960c9df39d6Vincent Belliard  // able to generate 32 bit veneers.
3582272afbda5f15c4bfb25c3c9bf95d960c9df39d6Vincent Belliard  uint32_t near_checkpoint_margin_;
35915985a2fcc72ce0ec5e19c410b444ceec899c11fVincent Belliard  // Offset where the last reference to a label has been added to the pool.
36015985a2fcc72ce0ec5e19c410b444ceec899c11fVincent Belliard  Label::Offset last_label_reference_offset_;
3618d191abf32edf41421f68f35585e4fce8da4d50cAlexandre Rames  // Indicates whether the emission of this pool is blocked.
3628d191abf32edf41421f68f35585e4fce8da4d50cAlexandre Rames  int monitor_;
3637827144797ee5ebfa0b574f45ad8ff235f919304Vincent Belliard};
36488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
36588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois}  // namespace aarch32
36688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois}  // namespace vixl
36788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois
368d3832965c62a8ad461b9ea9eb0994ca6b0a3da2cAlexandre Rames#endif  // VIXL_AARCH32_LABEL_AARCH32_H_
369