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 are 6// 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 distribution. 14// 15// - Neither the name of Sun Microsystems or the names of contributors may 16// be used to endorse or promote products derived from this software without 17// specific prior written permission. 18// 19// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS 20// IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 21// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 23// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 24// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 25// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 26// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 27// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 28// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 29// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 31// The original source code covered by the above license above has been 32// modified significantly by Google Inc. 33// Copyright 2006-2008 the V8 project authors. All rights reserved. 34 35// A light-weight IA32 Assembler. 36 37#ifndef V8_IA32_ASSEMBLER_IA32_INL_H_ 38#define V8_IA32_ASSEMBLER_IA32_INL_H_ 39 40#include "cpu.h" 41 42namespace v8 { 43namespace internal { 44 45Condition NegateCondition(Condition cc) { 46 return static_cast<Condition>(cc ^ 1); 47} 48 49 50// The modes possibly affected by apply must be in kApplyMask. 51void RelocInfo::apply(intptr_t delta) { 52 if (rmode_ == RUNTIME_ENTRY || IsCodeTarget(rmode_)) { 53 int32_t* p = reinterpret_cast<int32_t*>(pc_); 54 *p -= delta; // relocate entry 55 } else if (rmode_ == JS_RETURN && IsPatchedReturnSequence()) { 56 // Special handling of js_return when a break point is set (call 57 // instruction has been inserted). 58 int32_t* p = reinterpret_cast<int32_t*>(pc_ + 1); 59 *p -= delta; // relocate entry 60 } else if (IsInternalReference(rmode_)) { 61 // absolute code pointer inside code object moves with the code object. 62 int32_t* p = reinterpret_cast<int32_t*>(pc_); 63 *p += delta; // relocate entry 64 } 65} 66 67 68Address RelocInfo::target_address() { 69 ASSERT(IsCodeTarget(rmode_) || rmode_ == RUNTIME_ENTRY); 70 return Assembler::target_address_at(pc_); 71} 72 73 74Address RelocInfo::target_address_address() { 75 ASSERT(IsCodeTarget(rmode_) || rmode_ == RUNTIME_ENTRY); 76 return reinterpret_cast<Address>(pc_); 77} 78 79 80void RelocInfo::set_target_address(Address target) { 81 ASSERT(IsCodeTarget(rmode_) || rmode_ == RUNTIME_ENTRY); 82 Assembler::set_target_address_at(pc_, target); 83} 84 85 86Object* RelocInfo::target_object() { 87 ASSERT(IsCodeTarget(rmode_) || rmode_ == EMBEDDED_OBJECT); 88 return Memory::Object_at(pc_); 89} 90 91 92Handle<Object> RelocInfo::target_object_handle(Assembler* origin) { 93 ASSERT(IsCodeTarget(rmode_) || rmode_ == EMBEDDED_OBJECT); 94 return Memory::Object_Handle_at(pc_); 95} 96 97 98Object** RelocInfo::target_object_address() { 99 ASSERT(IsCodeTarget(rmode_) || rmode_ == EMBEDDED_OBJECT); 100 return &Memory::Object_at(pc_); 101} 102 103 104void RelocInfo::set_target_object(Object* target) { 105 ASSERT(IsCodeTarget(rmode_) || rmode_ == EMBEDDED_OBJECT); 106 Memory::Object_at(pc_) = target; 107} 108 109 110Address* RelocInfo::target_reference_address() { 111 ASSERT(rmode_ == RelocInfo::EXTERNAL_REFERENCE); 112 return reinterpret_cast<Address*>(pc_); 113} 114 115 116Address RelocInfo::call_address() { 117 ASSERT(IsPatchedReturnSequence()); 118 return Assembler::target_address_at(pc_ + 1); 119} 120 121 122void RelocInfo::set_call_address(Address target) { 123 ASSERT(IsPatchedReturnSequence()); 124 Assembler::set_target_address_at(pc_ + 1, target); 125} 126 127 128Object* RelocInfo::call_object() { 129 ASSERT(IsPatchedReturnSequence()); 130 return *call_object_address(); 131} 132 133 134Object** RelocInfo::call_object_address() { 135 ASSERT(IsPatchedReturnSequence()); 136 return reinterpret_cast<Object**>(pc_ + 1); 137} 138 139 140void RelocInfo::set_call_object(Object* target) { 141 ASSERT(IsPatchedReturnSequence()); 142 *call_object_address() = target; 143} 144 145 146bool RelocInfo::IsPatchedReturnSequence() { 147 return *pc_ == 0xE8; 148} 149 150 151Immediate::Immediate(int x) { 152 x_ = x; 153 rmode_ = RelocInfo::NONE; 154} 155 156 157Immediate::Immediate(const ExternalReference& ext) { 158 x_ = reinterpret_cast<int32_t>(ext.address()); 159 rmode_ = RelocInfo::EXTERNAL_REFERENCE; 160} 161 162Immediate::Immediate(const char* s) { 163 x_ = reinterpret_cast<int32_t>(s); 164 rmode_ = RelocInfo::EMBEDDED_STRING; 165} 166 167 168Immediate::Immediate(Label* internal_offset) { 169 x_ = reinterpret_cast<int32_t>(internal_offset); 170 rmode_ = RelocInfo::INTERNAL_REFERENCE; 171} 172 173 174Immediate::Immediate(Handle<Object> handle) { 175 // Verify all Objects referred by code are NOT in new space. 176 Object* obj = *handle; 177 ASSERT(!Heap::InNewSpace(obj)); 178 if (obj->IsHeapObject()) { 179 x_ = reinterpret_cast<intptr_t>(handle.location()); 180 rmode_ = RelocInfo::EMBEDDED_OBJECT; 181 } else { 182 // no relocation needed 183 x_ = reinterpret_cast<intptr_t>(obj); 184 rmode_ = RelocInfo::NONE; 185 } 186} 187 188 189Immediate::Immediate(Smi* value) { 190 x_ = reinterpret_cast<intptr_t>(value); 191 rmode_ = RelocInfo::NONE; 192} 193 194 195void Assembler::emit(uint32_t x) { 196 *reinterpret_cast<uint32_t*>(pc_) = x; 197 pc_ += sizeof(uint32_t); 198} 199 200 201void Assembler::emit(Handle<Object> handle) { 202 // Verify all Objects referred by code are NOT in new space. 203 Object* obj = *handle; 204 ASSERT(!Heap::InNewSpace(obj)); 205 if (obj->IsHeapObject()) { 206 emit(reinterpret_cast<intptr_t>(handle.location()), 207 RelocInfo::EMBEDDED_OBJECT); 208 } else { 209 // no relocation needed 210 emit(reinterpret_cast<intptr_t>(obj)); 211 } 212} 213 214 215void Assembler::emit(uint32_t x, RelocInfo::Mode rmode) { 216 if (rmode != RelocInfo::NONE) RecordRelocInfo(rmode); 217 emit(x); 218} 219 220 221void Assembler::emit(const Immediate& x) { 222 if (x.rmode_ == RelocInfo::INTERNAL_REFERENCE) { 223 Label* label = reinterpret_cast<Label*>(x.x_); 224 emit_code_relative_offset(label); 225 return; 226 } 227 if (x.rmode_ != RelocInfo::NONE) RecordRelocInfo(x.rmode_); 228 emit(x.x_); 229} 230 231 232void Assembler::emit_code_relative_offset(Label* label) { 233 if (label->is_bound()) { 234 int32_t pos; 235 pos = label->pos() + Code::kHeaderSize - kHeapObjectTag; 236 emit(pos); 237 } else { 238 emit_disp(label, Displacement::CODE_RELATIVE); 239 } 240} 241 242 243void Assembler::emit_w(const Immediate& x) { 244 ASSERT(x.rmode_ == RelocInfo::NONE); 245 uint16_t value = static_cast<uint16_t>(x.x_); 246 reinterpret_cast<uint16_t*>(pc_)[0] = value; 247 pc_ += sizeof(uint16_t); 248} 249 250 251Address Assembler::target_address_at(Address pc) { 252 return pc + sizeof(int32_t) + *reinterpret_cast<int32_t*>(pc); 253} 254 255 256void Assembler::set_target_address_at(Address pc, Address target) { 257 int32_t* p = reinterpret_cast<int32_t*>(pc); 258 *p = target - (pc + sizeof(int32_t)); 259 CPU::FlushICache(p, sizeof(int32_t)); 260} 261 262 263Displacement Assembler::disp_at(Label* L) { 264 return Displacement(long_at(L->pos())); 265} 266 267 268void Assembler::disp_at_put(Label* L, Displacement disp) { 269 long_at_put(L->pos(), disp.data()); 270} 271 272 273void Assembler::emit_disp(Label* L, Displacement::Type type) { 274 Displacement disp(L, type); 275 L->link_to(pc_offset()); 276 emit(static_cast<int>(disp.data())); 277} 278 279 280void Operand::set_modrm(int mod, Register rm) { 281 ASSERT((mod & -4) == 0); 282 buf_[0] = mod << 6 | rm.code(); 283 len_ = 1; 284} 285 286 287void Operand::set_sib(ScaleFactor scale, Register index, Register base) { 288 ASSERT(len_ == 1); 289 ASSERT((scale & -4) == 0); 290 // Use SIB with no index register only for base esp. 291 ASSERT(!index.is(esp) || base.is(esp)); 292 buf_[1] = scale << 6 | index.code() << 3 | base.code(); 293 len_ = 2; 294} 295 296 297void Operand::set_disp8(int8_t disp) { 298 ASSERT(len_ == 1 || len_ == 2); 299 *reinterpret_cast<int8_t*>(&buf_[len_++]) = disp; 300} 301 302 303void Operand::set_dispr(int32_t disp, RelocInfo::Mode rmode) { 304 ASSERT(len_ == 1 || len_ == 2); 305 int32_t* p = reinterpret_cast<int32_t*>(&buf_[len_]); 306 *p = disp; 307 len_ += sizeof(int32_t); 308 rmode_ = rmode; 309} 310 311Operand::Operand(Register reg) { 312 // reg 313 set_modrm(3, reg); 314} 315 316 317Operand::Operand(int32_t disp, RelocInfo::Mode rmode) { 318 // [disp/r] 319 set_modrm(0, ebp); 320 set_dispr(disp, rmode); 321} 322 323} } // namespace v8::internal 324 325#endif // V8_IA32_ASSEMBLER_IA32_INL_H_ 326