• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
Needs16BitPadding(int32_t location) const36 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 
ResolveReferences(internal::AssemblerBase * assembler)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 
Is16BitEncoding(uint16_t instr)55 static bool Is16BitEncoding(uint16_t instr) {
56   return instr < (kLowestT32_32Opcode >> 16);
57 }
58 
EncodeLocationFor(internal::AssemblerBase * assembler,int32_t from,const Location::EmitOperator * encoder)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 
AddForwardRef(int32_t instr_location,const EmitOperator & op,const ReferenceInfo * info)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 
GetMaxAlignment() const104 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 
GetMinLocation() const115 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 
UpdatePoolObject(PoolObject<int32_t> * object)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 
EmitPoolObject(MacroAssemblerInterface * masm)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 
EmitPoolObject(MacroAssemblerInterface * masm)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