Home | History | Annotate | Download | only in aarch32
      1 // Copyright 2017, VIXL authors
      2 // All rights reserved.
      3 //
      4 // Redistribution and use in source and binary forms, with or without
      5 // modification, are permitted provided that the following conditions are met:
      6 //
      7 //   * Redistributions of source code must retain the above copyright notice,
      8 //     this list of conditions and the following disclaimer.
      9 //   * Redistributions in binary form must reproduce the above copyright notice,
     10 //     this list of conditions and the following disclaimer in the documentation
     11 //     and/or other materials provided with the distribution.
     12 //   * Neither the name of ARM Limited nor the names of its contributors may be
     13 //     used to endorse or promote products derived from this software without
     14 //     specific prior written permission.
     15 //
     16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS CONTRIBUTORS "AS IS" AND
     17 // ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
     18 // WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
     19 // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
     20 // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     21 // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
     22 // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
     23 // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
     24 // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     25 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     26 
     27 #include "location-aarch32.h"
     28 
     29 #include "assembler-aarch32.h"
     30 #include "macro-assembler-aarch32.h"
     31 
     32 namespace vixl {
     33 
     34 namespace aarch32 {
     35 
     36 bool Location::Needs16BitPadding(int32_t location) const {
     37   if (!HasForwardReferences()) return false;
     38   const ForwardRef& last_ref = GetLastForwardReference();
     39   int32_t min_location_last_ref = last_ref.GetMinLocation();
     40   VIXL_ASSERT(min_location_last_ref - location <= 2);
     41   return (min_location_last_ref > location);
     42 }
     43 
     44 void Location::ResolveReferences(internal::AssemblerBase* assembler) {
     45   // Iterate over references and call EncodeLocationFor on each of them.
     46   for (ForwardRefListIterator it(this); !it.Done(); it.Advance()) {
     47     const ForwardRef& reference = *it.Current();
     48     VIXL_ASSERT(reference.LocationIsEncodable(location_));
     49     int32_t from = reference.GetLocation();
     50     EncodeLocationFor(assembler, from, reference.op());
     51   }
     52   forward_.clear();
     53 }
     54 
     55 static bool Is16BitEncoding(uint16_t instr) {
     56   return instr < (kLowestT32_32Opcode >> 16);
     57 }
     58 
     59 void Location::EncodeLocationFor(internal::AssemblerBase* assembler,
     60                                  int32_t from,
     61                                  const Location::EmitOperator* encoder) {
     62   if (encoder->IsUsingT32()) {
     63     uint16_t* instr_ptr =
     64         assembler->GetBuffer()->GetOffsetAddress<uint16_t*>(from);
     65     if (Is16BitEncoding(instr_ptr[0])) {
     66       // The Encode methods always deals with uint32_t types so we need
     67       // to explicitly cast it.
     68       uint32_t instr = static_cast<uint32_t>(instr_ptr[0]);
     69       instr = encoder->Encode(instr, from, this);
     70       // The Encode method should not ever set the top 16 bits.
     71       VIXL_ASSERT((instr & ~0xffff) == 0);
     72       instr_ptr[0] = static_cast<uint16_t>(instr);
     73     } else {
     74       uint32_t instr =
     75           instr_ptr[1] | (static_cast<uint32_t>(instr_ptr[0]) << 16);
     76       instr = encoder->Encode(instr, from, this);
     77       instr_ptr[0] = static_cast<uint16_t>(instr >> 16);
     78       instr_ptr[1] = static_cast<uint16_t>(instr);
     79     }
     80   } else {
     81     uint32_t* instr_ptr =
     82         assembler->GetBuffer()->GetOffsetAddress<uint32_t*>(from);
     83     instr_ptr[0] = encoder->Encode(instr_ptr[0], from, this);
     84   }
     85 }
     86 
     87 void Location::AddForwardRef(int32_t instr_location,
     88                              const EmitOperator& op,
     89                              const ReferenceInfo* info) {
     90   VIXL_ASSERT(referenced_);
     91   int32_t from = instr_location + (op.IsUsingT32() ? kT32PcDelta : kA32PcDelta);
     92   if (info->pc_needs_aligning == ReferenceInfo::kAlignPc)
     93     from = AlignDown(from, 4);
     94   int32_t min_object_location = from + info->min_offset;
     95   int32_t max_object_location = from + info->max_offset;
     96   forward_.insert(ForwardRef(&op,
     97                              instr_location,
     98                              info->size,
     99                              min_object_location,
    100                              max_object_location,
    101                              info->alignment));
    102 }
    103 
    104 int Location::GetMaxAlignment() const {
    105   int max_alignment = GetPoolObjectAlignment();
    106   for (ForwardRefListIterator it(const_cast<Location*>(this)); !it.Done();
    107        it.Advance()) {
    108     const ForwardRef& reference = *it.Current();
    109     if (reference.GetAlignment() > max_alignment)
    110       max_alignment = reference.GetAlignment();
    111   }
    112   return max_alignment;
    113 }
    114 
    115 int Location::GetMinLocation() const {
    116   int32_t min_location = 0;
    117   for (ForwardRefListIterator it(const_cast<Location*>(this)); !it.Done();
    118        it.Advance()) {
    119     const ForwardRef& reference = *it.Current();
    120     if (reference.GetMinLocation() > min_location)
    121       min_location = reference.GetMinLocation();
    122   }
    123   return min_location;
    124 }
    125 
    126 void Label::UpdatePoolObject(PoolObject<int32_t>* object) {
    127   VIXL_ASSERT(forward_.size() == 1);
    128   const ForwardRef& reference = forward_.Front();
    129   object->Update(reference.GetMinLocation(),
    130                  reference.GetMaxLocation(),
    131                  reference.GetAlignment());
    132 }
    133 
    134 void Label::EmitPoolObject(MacroAssemblerInterface* masm) {
    135   MacroAssembler* macro_assembler = static_cast<MacroAssembler*>(masm);
    136 
    137   // Add a new branch to this label.
    138   macro_assembler->GetBuffer()->EnsureSpaceFor(kMaxInstructionSizeInBytes);
    139   ExactAssemblyScopeWithoutPoolsCheck guard(macro_assembler,
    140                                             kMaxInstructionSizeInBytes,
    141                                             ExactAssemblyScope::kMaximumSize);
    142   macro_assembler->b(this);
    143 }
    144 
    145 void RawLiteral::EmitPoolObject(MacroAssemblerInterface* masm) {
    146   Assembler* assembler = static_cast<Assembler*>(masm->AsAssemblerBase());
    147 
    148   assembler->GetBuffer()->EnsureSpaceFor(GetSize());
    149   assembler->GetBuffer()->EmitData(GetDataAddress(), GetSize());
    150 }
    151 }
    152 }
    153