assembler-arm-inl.h revision a7e24c173cf37484693b9abb38e494fa7bd7baeb
1// Copyright (c) 1994-2006 Sun Microsystems Inc. 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 6// are met: 7// 8// - Redistributions of source code must retain the above copyright notice, 9// this list of conditions and the following disclaimer. 10// 11// - Redistribution in binary form must reproduce the above copyright 12// notice, this list of conditions and the following disclaimer in the 13// documentation and/or other materials provided with the 14// distribution. 15// 16// - Neither the name of Sun Microsystems or the names of contributors may 17// be used to endorse or promote products derived from this software without 18// specific prior written permission. 19// 20// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 21// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 22// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 23// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 24// COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 25// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 26// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 27// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 29// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 30// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 31// OF THE POSSIBILITY OF SUCH DAMAGE. 32 33// The original source code covered by the above license above has been modified 34// significantly by Google Inc. 35// Copyright 2006-2008 the V8 project authors. All rights reserved. 36 37#ifndef V8_ARM_ASSEMBLER_ARM_INL_H_ 38#define V8_ARM_ASSEMBLER_ARM_INL_H_ 39 40#include "arm/assembler-arm.h" 41#include "cpu.h" 42 43 44namespace v8 { 45namespace internal { 46 47Condition NegateCondition(Condition cc) { 48 ASSERT(cc != al); 49 return static_cast<Condition>(cc ^ ne); 50} 51 52 53void RelocInfo::apply(intptr_t delta) { 54 if (RelocInfo::IsInternalReference(rmode_)) { 55 // absolute code pointer inside code object moves with the code object. 56 int32_t* p = reinterpret_cast<int32_t*>(pc_); 57 *p += delta; // relocate entry 58 } 59 // We do not use pc relative addressing on ARM, so there is 60 // nothing else to do. 61} 62 63 64Address RelocInfo::target_address() { 65 ASSERT(IsCodeTarget(rmode_) || rmode_ == RUNTIME_ENTRY); 66 return Assembler::target_address_at(pc_); 67} 68 69 70Address RelocInfo::target_address_address() { 71 ASSERT(IsCodeTarget(rmode_) || rmode_ == RUNTIME_ENTRY); 72 return reinterpret_cast<Address>(Assembler::target_address_address_at(pc_)); 73} 74 75 76void RelocInfo::set_target_address(Address target) { 77 ASSERT(IsCodeTarget(rmode_) || rmode_ == RUNTIME_ENTRY); 78 Assembler::set_target_address_at(pc_, target); 79} 80 81 82Object* RelocInfo::target_object() { 83 ASSERT(IsCodeTarget(rmode_) || rmode_ == EMBEDDED_OBJECT); 84 return reinterpret_cast<Object*>(Assembler::target_address_at(pc_)); 85} 86 87 88Object** RelocInfo::target_object_address() { 89 ASSERT(IsCodeTarget(rmode_) || rmode_ == EMBEDDED_OBJECT); 90 return reinterpret_cast<Object**>(Assembler::target_address_address_at(pc_)); 91} 92 93 94void RelocInfo::set_target_object(Object* target) { 95 ASSERT(IsCodeTarget(rmode_) || rmode_ == EMBEDDED_OBJECT); 96 Assembler::set_target_address_at(pc_, reinterpret_cast<Address>(target)); 97} 98 99 100Address* RelocInfo::target_reference_address() { 101 ASSERT(rmode_ == EXTERNAL_REFERENCE); 102 return reinterpret_cast<Address*>(Assembler::target_address_address_at(pc_)); 103} 104 105 106Address RelocInfo::call_address() { 107 ASSERT(IsCallInstruction()); 108 // The 2 instructions offset assumes patched return sequence. 109 ASSERT(IsJSReturn(rmode())); 110 return Memory::Address_at(pc_ + 2 * Assembler::kInstrSize); 111} 112 113 114void RelocInfo::set_call_address(Address target) { 115 ASSERT(IsCallInstruction()); 116 // The 2 instructions offset assumes patched return sequence. 117 ASSERT(IsJSReturn(rmode())); 118 Memory::Address_at(pc_ + 2 * Assembler::kInstrSize) = target; 119} 120 121 122Object* RelocInfo::call_object() { 123 return *call_object_address(); 124} 125 126 127Object** RelocInfo::call_object_address() { 128 ASSERT(IsCallInstruction()); 129 // The 2 instructions offset assumes patched return sequence. 130 ASSERT(IsJSReturn(rmode())); 131 return reinterpret_cast<Object**>(pc_ + 2 * Assembler::kInstrSize); 132} 133 134 135void RelocInfo::set_call_object(Object* target) { 136 *call_object_address() = target; 137} 138 139 140bool RelocInfo::IsCallInstruction() { 141 // On ARM a "call instruction" is actually two instructions. 142 // mov lr, pc 143 // ldr pc, [pc, #XXX] 144 return (Assembler::instr_at(pc_) == kMovLrPc) 145 && ((Assembler::instr_at(pc_ + Assembler::kInstrSize) & kLdrPCPattern) 146 == kLdrPCPattern); 147} 148 149 150Operand::Operand(int32_t immediate, RelocInfo::Mode rmode) { 151 rm_ = no_reg; 152 imm32_ = immediate; 153 rmode_ = rmode; 154} 155 156 157Operand::Operand(const char* s) { 158 rm_ = no_reg; 159 imm32_ = reinterpret_cast<int32_t>(s); 160 rmode_ = RelocInfo::EMBEDDED_STRING; 161} 162 163 164Operand::Operand(const ExternalReference& f) { 165 rm_ = no_reg; 166 imm32_ = reinterpret_cast<int32_t>(f.address()); 167 rmode_ = RelocInfo::EXTERNAL_REFERENCE; 168} 169 170 171Operand::Operand(Object** opp) { 172 rm_ = no_reg; 173 imm32_ = reinterpret_cast<int32_t>(opp); 174 rmode_ = RelocInfo::NONE; 175} 176 177 178Operand::Operand(Context** cpp) { 179 rm_ = no_reg; 180 imm32_ = reinterpret_cast<int32_t>(cpp); 181 rmode_ = RelocInfo::NONE; 182} 183 184 185Operand::Operand(Smi* value) { 186 rm_ = no_reg; 187 imm32_ = reinterpret_cast<intptr_t>(value); 188 rmode_ = RelocInfo::NONE; 189} 190 191 192Operand::Operand(Register rm) { 193 rm_ = rm; 194 rs_ = no_reg; 195 shift_op_ = LSL; 196 shift_imm_ = 0; 197} 198 199 200bool Operand::is_reg() const { 201 return rm_.is_valid() && 202 rs_.is(no_reg) && 203 shift_op_ == LSL && 204 shift_imm_ == 0; 205} 206 207 208void Assembler::CheckBuffer() { 209 if (buffer_space() <= kGap) { 210 GrowBuffer(); 211 } 212 if (pc_offset() >= next_buffer_check_) { 213 CheckConstPool(false, true); 214 } 215} 216 217 218void Assembler::emit(Instr x) { 219 CheckBuffer(); 220 *reinterpret_cast<Instr*>(pc_) = x; 221 pc_ += kInstrSize; 222} 223 224 225Address Assembler::target_address_address_at(Address pc) { 226 Instr instr = Memory::int32_at(pc); 227 // Verify that the instruction at pc is a ldr<cond> <Rd>, [pc +/- offset_12]. 228 ASSERT((instr & 0x0f7f0000) == 0x051f0000); 229 int offset = instr & 0xfff; // offset_12 is unsigned 230 if ((instr & (1 << 23)) == 0) offset = -offset; // U bit defines offset sign 231 // Verify that the constant pool comes after the instruction referencing it. 232 ASSERT(offset >= -4); 233 return pc + offset + 8; 234} 235 236 237Address Assembler::target_address_at(Address pc) { 238 return Memory::Address_at(target_address_address_at(pc)); 239} 240 241 242void Assembler::set_target_address_at(Address pc, Address target) { 243 Memory::Address_at(target_address_address_at(pc)) = target; 244 // Intuitively, we would think it is necessary to flush the instruction cache 245 // after patching a target address in the code as follows: 246 // CPU::FlushICache(pc, sizeof(target)); 247 // However, on ARM, no instruction was actually patched by the assignment 248 // above; the target address is not part of an instruction, it is patched in 249 // the constant pool and is read via a data access; the instruction accessing 250 // this address in the constant pool remains unchanged. 251} 252 253} } // namespace v8::internal 254 255#endif // V8_ARM_ASSEMBLER_ARM_INL_H_ 256