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