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 32 namespace art { 33 34 static uint8_t* NewContents(size_t capacity) { 35 return new uint8_t[capacity]; 36 } 37 38 39 AssemblerBuffer::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 57 AssemblerBuffer::~AssemblerBuffer() { 58 delete[] contents_; 59 } 60 61 62 void 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 71 void 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 83 void 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 108 void DebugFrameOpCodeWriterForAssembler::ImplicitlyAdvancePC() { 109 this->AdvancePC(assembler_->CodeSize()); 110 } 111 112 Assembler* 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 134 void Assembler::StoreImmediateToThread32(ThreadOffset<4> dest ATTRIBUTE_UNUSED, 135 uint32_t imm ATTRIBUTE_UNUSED, 136 ManagedRegister scratch ATTRIBUTE_UNUSED) { 137 UNIMPLEMENTED(FATAL); 138 } 139 140 void Assembler::StoreImmediateToThread64(ThreadOffset<8> dest ATTRIBUTE_UNUSED, 141 uint32_t imm ATTRIBUTE_UNUSED, 142 ManagedRegister scratch ATTRIBUTE_UNUSED) { 143 UNIMPLEMENTED(FATAL); 144 } 145 146 void Assembler::StoreStackOffsetToThread32(ThreadOffset<4> thr_offs ATTRIBUTE_UNUSED, 147 FrameOffset fr_offs ATTRIBUTE_UNUSED, 148 ManagedRegister scratch ATTRIBUTE_UNUSED) { 149 UNIMPLEMENTED(FATAL); 150 } 151 152 void Assembler::StoreStackOffsetToThread64(ThreadOffset<8> thr_offs ATTRIBUTE_UNUSED, 153 FrameOffset fr_offs ATTRIBUTE_UNUSED, 154 ManagedRegister scratch ATTRIBUTE_UNUSED) { 155 UNIMPLEMENTED(FATAL); 156 } 157 158 void Assembler::StoreStackPointerToThread32(ThreadOffset<4> thr_offs ATTRIBUTE_UNUSED) { 159 UNIMPLEMENTED(FATAL); 160 } 161 162 void Assembler::StoreStackPointerToThread64(ThreadOffset<8> thr_offs ATTRIBUTE_UNUSED) { 163 UNIMPLEMENTED(FATAL); 164 } 165 166 void Assembler::LoadFromThread32(ManagedRegister dest ATTRIBUTE_UNUSED, 167 ThreadOffset<4> src ATTRIBUTE_UNUSED, 168 size_t size ATTRIBUTE_UNUSED) { 169 UNIMPLEMENTED(FATAL); 170 } 171 172 void Assembler::LoadFromThread64(ManagedRegister dest ATTRIBUTE_UNUSED, 173 ThreadOffset<8> src ATTRIBUTE_UNUSED, 174 size_t size ATTRIBUTE_UNUSED) { 175 UNIMPLEMENTED(FATAL); 176 } 177 178 void Assembler::LoadRawPtrFromThread32(ManagedRegister dest ATTRIBUTE_UNUSED, 179 ThreadOffset<4> offs ATTRIBUTE_UNUSED) { 180 UNIMPLEMENTED(FATAL); 181 } 182 183 void Assembler::LoadRawPtrFromThread64(ManagedRegister dest ATTRIBUTE_UNUSED, 184 ThreadOffset<8> offs ATTRIBUTE_UNUSED) { 185 UNIMPLEMENTED(FATAL); 186 } 187 188 void Assembler::CopyRawPtrFromThread32(FrameOffset fr_offs ATTRIBUTE_UNUSED, 189 ThreadOffset<4> thr_offs ATTRIBUTE_UNUSED, 190 ManagedRegister scratch ATTRIBUTE_UNUSED) { 191 UNIMPLEMENTED(FATAL); 192 } 193 194 void Assembler::CopyRawPtrFromThread64(FrameOffset fr_offs ATTRIBUTE_UNUSED, 195 ThreadOffset<8> thr_offs ATTRIBUTE_UNUSED, 196 ManagedRegister scratch ATTRIBUTE_UNUSED) { 197 UNIMPLEMENTED(FATAL); 198 } 199 200 void Assembler::CopyRawPtrToThread32(ThreadOffset<4> thr_offs ATTRIBUTE_UNUSED, 201 FrameOffset fr_offs ATTRIBUTE_UNUSED, 202 ManagedRegister scratch ATTRIBUTE_UNUSED) { 203 UNIMPLEMENTED(FATAL); 204 } 205 206 void Assembler::CopyRawPtrToThread64(ThreadOffset<8> thr_offs ATTRIBUTE_UNUSED, 207 FrameOffset fr_offs ATTRIBUTE_UNUSED, 208 ManagedRegister scratch ATTRIBUTE_UNUSED) { 209 UNIMPLEMENTED(FATAL); 210 } 211 212 void Assembler::CallFromThread32(ThreadOffset<4> offset ATTRIBUTE_UNUSED, 213 ManagedRegister scratch ATTRIBUTE_UNUSED) { 214 UNIMPLEMENTED(FATAL); 215 } 216 217 void Assembler::CallFromThread64(ThreadOffset<8> offset ATTRIBUTE_UNUSED, 218 ManagedRegister scratch ATTRIBUTE_UNUSED) { 219 UNIMPLEMENTED(FATAL); 220 } 221 222 } // namespace art 223