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_ = nullptr; 45 slow_path_ = nullptr; 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 != nullptr) { 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 nullptr; 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