assembler.cc revision dd97393aca1a3ff2abec4dc4f78d7724300971bc
1/*
2 * Copyright (C) 2011 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include "assembler.h"
18
19#include <algorithm>
20#include <vector>
21
22#include "arm/assembler_arm32.h"
23#include "arm/assembler_thumb2.h"
24#include "arm64/assembler_arm64.h"
25#include "mips/assembler_mips.h"
26#include "mips64/assembler_mips64.h"
27#include "x86/assembler_x86.h"
28#include "x86_64/assembler_x86_64.h"
29#include "globals.h"
30#include "memory_region.h"
31
32namespace art {
33
34static uint8_t* NewContents(size_t capacity) {
35  return new uint8_t[capacity];
36}
37
38
39AssemblerBuffer::AssemblerBuffer() {
40  static const size_t kInitialBufferCapacity = 4 * KB;
41  contents_ = NewContents(kInitialBufferCapacity);
42  cursor_ = contents_;
43  limit_ = ComputeLimit(contents_, kInitialBufferCapacity);
44  fixup_ = NULL;
45  slow_path_ = NULL;
46#ifndef NDEBUG
47  has_ensured_capacity_ = false;
48  fixups_processed_ = false;
49#endif
50
51  // Verify internal state.
52  CHECK_EQ(Capacity(), kInitialBufferCapacity);
53  CHECK_EQ(Size(), 0U);
54}
55
56
57AssemblerBuffer::~AssemblerBuffer() {
58  delete[] contents_;
59}
60
61
62void AssemblerBuffer::ProcessFixups(const MemoryRegion& region) {
63  AssemblerFixup* fixup = fixup_;
64  while (fixup != NULL) {
65    fixup->Process(region, fixup->position());
66    fixup = fixup->previous();
67  }
68}
69
70
71void AssemblerBuffer::FinalizeInstructions(const MemoryRegion& instructions) {
72  // Copy the instructions from the buffer.
73  MemoryRegion from(reinterpret_cast<void*>(contents()), Size());
74  instructions.CopyFrom(0, from);
75  // Process fixups in the instructions.
76  ProcessFixups(instructions);
77#ifndef NDEBUG
78  fixups_processed_ = true;
79#endif
80}
81
82
83void AssemblerBuffer::ExtendCapacity() {
84  size_t old_size = Size();
85  size_t old_capacity = Capacity();
86  size_t new_capacity = std::min(old_capacity * 2, old_capacity + 1 * MB);
87
88  // Allocate the new data area and copy contents of the old one to it.
89  uint8_t* new_contents = NewContents(new_capacity);
90  memmove(reinterpret_cast<void*>(new_contents),
91          reinterpret_cast<void*>(contents_),
92          old_size);
93
94  // Compute the relocation delta and switch to the new contents area.
95  ptrdiff_t delta = new_contents - contents_;
96  delete[] contents_;
97  contents_ = new_contents;
98
99  // Update the cursor and recompute the limit.
100  cursor_ += delta;
101  limit_ = ComputeLimit(new_contents, new_capacity);
102
103  // Verify internal state.
104  CHECK_EQ(Capacity(), new_capacity);
105  CHECK_EQ(Size(), old_size);
106}
107
108void DebugFrameOpCodeWriterForAssembler::ImplicitlyAdvancePC() {
109  this->AdvancePC(assembler_->CodeSize());
110}
111
112Assembler* Assembler::Create(InstructionSet instruction_set) {
113  switch (instruction_set) {
114    case kArm:
115      return new arm::Arm32Assembler();
116    case kThumb2:
117      return new arm::Thumb2Assembler();
118    case kArm64:
119      return new arm64::Arm64Assembler();
120    case kMips:
121      return new mips::MipsAssembler();
122    case kMips64:
123      return new mips64::Mips64Assembler();
124    case kX86:
125      return new x86::X86Assembler();
126    case kX86_64:
127      return new x86_64::X86_64Assembler();
128    default:
129      LOG(FATAL) << "Unknown InstructionSet: " << instruction_set;
130      return NULL;
131  }
132}
133
134void Assembler::StoreImmediateToThread32(ThreadOffset<4> dest ATTRIBUTE_UNUSED,
135                                         uint32_t imm ATTRIBUTE_UNUSED,
136                                         ManagedRegister scratch ATTRIBUTE_UNUSED) {
137  UNIMPLEMENTED(FATAL);
138}
139
140void Assembler::StoreImmediateToThread64(ThreadOffset<8> dest ATTRIBUTE_UNUSED,
141                                         uint32_t imm ATTRIBUTE_UNUSED,
142                                         ManagedRegister scratch ATTRIBUTE_UNUSED) {
143  UNIMPLEMENTED(FATAL);
144}
145
146void Assembler::StoreStackOffsetToThread32(ThreadOffset<4> thr_offs ATTRIBUTE_UNUSED,
147                                           FrameOffset fr_offs ATTRIBUTE_UNUSED,
148                                           ManagedRegister scratch ATTRIBUTE_UNUSED) {
149  UNIMPLEMENTED(FATAL);
150}
151
152void Assembler::StoreStackOffsetToThread64(ThreadOffset<8> thr_offs ATTRIBUTE_UNUSED,
153                                           FrameOffset fr_offs ATTRIBUTE_UNUSED,
154                                           ManagedRegister scratch ATTRIBUTE_UNUSED) {
155  UNIMPLEMENTED(FATAL);
156}
157
158void Assembler::StoreStackPointerToThread32(ThreadOffset<4> thr_offs ATTRIBUTE_UNUSED) {
159  UNIMPLEMENTED(FATAL);
160}
161
162void Assembler::StoreStackPointerToThread64(ThreadOffset<8> thr_offs ATTRIBUTE_UNUSED) {
163  UNIMPLEMENTED(FATAL);
164}
165
166void Assembler::LoadFromThread32(ManagedRegister dest ATTRIBUTE_UNUSED,
167                                 ThreadOffset<4> src ATTRIBUTE_UNUSED,
168                                 size_t size ATTRIBUTE_UNUSED) {
169  UNIMPLEMENTED(FATAL);
170}
171
172void Assembler::LoadFromThread64(ManagedRegister dest ATTRIBUTE_UNUSED,
173                                 ThreadOffset<8> src ATTRIBUTE_UNUSED,
174                                 size_t size ATTRIBUTE_UNUSED) {
175  UNIMPLEMENTED(FATAL);
176}
177
178void Assembler::LoadRawPtrFromThread32(ManagedRegister dest ATTRIBUTE_UNUSED,
179                                       ThreadOffset<4> offs ATTRIBUTE_UNUSED) {
180  UNIMPLEMENTED(FATAL);
181}
182
183void Assembler::LoadRawPtrFromThread64(ManagedRegister dest ATTRIBUTE_UNUSED,
184                                       ThreadOffset<8> offs ATTRIBUTE_UNUSED) {
185  UNIMPLEMENTED(FATAL);
186}
187
188void Assembler::CopyRawPtrFromThread32(FrameOffset fr_offs ATTRIBUTE_UNUSED,
189                                       ThreadOffset<4> thr_offs ATTRIBUTE_UNUSED,
190                                       ManagedRegister scratch ATTRIBUTE_UNUSED) {
191  UNIMPLEMENTED(FATAL);
192}
193
194void Assembler::CopyRawPtrFromThread64(FrameOffset fr_offs ATTRIBUTE_UNUSED,
195                                       ThreadOffset<8> thr_offs ATTRIBUTE_UNUSED,
196                                       ManagedRegister scratch ATTRIBUTE_UNUSED) {
197  UNIMPLEMENTED(FATAL);
198}
199
200void Assembler::CopyRawPtrToThread32(ThreadOffset<4> thr_offs ATTRIBUTE_UNUSED,
201                                     FrameOffset fr_offs ATTRIBUTE_UNUSED,
202                                     ManagedRegister scratch ATTRIBUTE_UNUSED) {
203  UNIMPLEMENTED(FATAL);
204}
205
206void Assembler::CopyRawPtrToThread64(ThreadOffset<8> thr_offs ATTRIBUTE_UNUSED,
207                                     FrameOffset fr_offs ATTRIBUTE_UNUSED,
208                                     ManagedRegister scratch ATTRIBUTE_UNUSED) {
209  UNIMPLEMENTED(FATAL);
210}
211
212void Assembler::CallFromThread32(ThreadOffset<4> offset ATTRIBUTE_UNUSED,
213                                 ManagedRegister scratch ATTRIBUTE_UNUSED) {
214  UNIMPLEMENTED(FATAL);
215}
216
217void Assembler::CallFromThread64(ThreadOffset<8> offset ATTRIBUTE_UNUSED,
218                                 ManagedRegister scratch ATTRIBUTE_UNUSED) {
219  UNIMPLEMENTED(FATAL);
220}
221
222}  // namespace art
223