Path: blob/master/dep/vixl/src/aarch32/location-aarch32.cc
4261 views
// Copyright 2017, VIXL authors1// All rights reserved.2//3// Redistribution and use in source and binary forms, with or without4// modification, are permitted provided that the following conditions are met:5//6// * Redistributions of source code must retain the above copyright notice,7// this list of conditions and the following disclaimer.8// * Redistributions in binary form must reproduce the above copyright notice,9// this list of conditions and the following disclaimer in the documentation10// and/or other materials provided with the distribution.11// * Neither the name of ARM Limited nor the names of its contributors may be12// used to endorse or promote products derived from this software without13// specific prior written permission.14//15// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS CONTRIBUTORS "AS IS" AND16// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED17// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE18// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE19// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL20// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR21// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER22// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,23// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE24// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.2526#include "location-aarch32.h"2728#include "assembler-aarch32.h"29#include "macro-assembler-aarch32.h"3031namespace vixl {3233namespace aarch32 {3435bool Location::Needs16BitPadding(int32_t location) const {36if (!HasForwardReferences()) return false;37const ForwardRef& last_ref = GetLastForwardReference();38int32_t min_location_last_ref = last_ref.GetMinLocation();39VIXL_ASSERT(min_location_last_ref - location <= 2);40return (min_location_last_ref > location);41}4243void Location::ResolveReferences(internal::AssemblerBase* assembler) {44// Iterate over references and call EncodeLocationFor on each of them.45for (ForwardRefListIterator it(this); !it.Done(); it.Advance()) {46const ForwardRef& reference = *it.Current();47VIXL_ASSERT(reference.LocationIsEncodable(location_));48int32_t from = reference.GetLocation();49EncodeLocationFor(assembler, from, reference.op());50}51forward_.clear();52}5354static bool Is16BitEncoding(uint16_t instr) {55return instr < (kLowestT32_32Opcode >> 16);56}5758void Location::EncodeLocationFor(internal::AssemblerBase* assembler,59int32_t from,60const Location::EmitOperator* encoder) {61if (encoder->IsUsingT32()) {62uint16_t* instr_ptr =63assembler->GetBuffer()->GetOffsetAddress<uint16_t*>(from);64if (Is16BitEncoding(instr_ptr[0])) {65// The Encode methods always deals with uint32_t types so we need66// to explicitly cast it.67uint32_t instr = static_cast<uint32_t>(instr_ptr[0]);68instr = encoder->Encode(instr, from, this);69// The Encode method should not ever set the top 16 bits.70VIXL_ASSERT((instr & ~0xffff) == 0);71instr_ptr[0] = static_cast<uint16_t>(instr);72} else {73uint32_t instr =74instr_ptr[1] | (static_cast<uint32_t>(instr_ptr[0]) << 16);75instr = encoder->Encode(instr, from, this);76instr_ptr[0] = static_cast<uint16_t>(instr >> 16);77instr_ptr[1] = static_cast<uint16_t>(instr);78}79} else {80uint32_t* instr_ptr =81assembler->GetBuffer()->GetOffsetAddress<uint32_t*>(from);82instr_ptr[0] = encoder->Encode(instr_ptr[0], from, this);83}84}8586void Location::AddForwardRef(int32_t instr_location,87const EmitOperator& op,88const ReferenceInfo* info) {89VIXL_ASSERT(referenced_);90int32_t from = instr_location + (op.IsUsingT32() ? kT32PcDelta : kA32PcDelta);91if (info->pc_needs_aligning == ReferenceInfo::kAlignPc)92from = AlignDown(from, 4);93int32_t min_object_location = from + info->min_offset;94int32_t max_object_location = from + info->max_offset;95forward_.insert(ForwardRef(&op,96instr_location,97info->size,98min_object_location,99max_object_location,100info->alignment));101}102103int Location::GetMaxAlignment() const {104int max_alignment = GetPoolObjectAlignment();105for (ForwardRefListIterator it(const_cast<Location*>(this)); !it.Done();106it.Advance()) {107const ForwardRef& reference = *it.Current();108if (reference.GetAlignment() > max_alignment)109max_alignment = reference.GetAlignment();110}111return max_alignment;112}113114int Location::GetMinLocation() const {115int32_t min_location = 0;116for (ForwardRefListIterator it(const_cast<Location*>(this)); !it.Done();117it.Advance()) {118const ForwardRef& reference = *it.Current();119if (reference.GetMinLocation() > min_location)120min_location = reference.GetMinLocation();121}122return min_location;123}124125void Label::UpdatePoolObject(PoolObject<int32_t>* object) {126VIXL_ASSERT(forward_.size() == 1);127const ForwardRef& reference = forward_.Front();128object->Update(reference.GetMinLocation(),129reference.GetMaxLocation(),130reference.GetAlignment());131}132133void Label::EmitPoolObject(MacroAssemblerInterface* masm) {134MacroAssembler* macro_assembler = static_cast<MacroAssembler*>(masm);135136// Add a new branch to this label.137VIXL_ASSERT(macro_assembler->GetBuffer()->HasSpaceFor(kMaxInstructionSizeInBytes));138ExactAssemblyScopeWithoutPoolsCheck guard(macro_assembler,139kMaxInstructionSizeInBytes,140ExactAssemblyScope::kMaximumSize);141macro_assembler->b(this);142}143144void RawLiteral::EmitPoolObject(MacroAssemblerInterface* masm) {145Assembler* assembler = static_cast<Assembler*>(masm->AsAssemblerBase());146147VIXL_ASSERT(assembler->GetBuffer()->HasSpaceFor(GetSize()));148assembler->GetBuffer()->EmitData(GetDataAddress(), GetSize());149}150}151}152153154