Home | History | Annotate | Download | only in ia32
      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 
     42 namespace v8 {
     43 namespace internal {
     44 
     45 Condition NegateCondition(Condition cc) {
     46   return static_cast<Condition>(cc ^ 1);
     47 }
     48 
     49 
     50 // The modes possibly affected by apply must be in kApplyMask.
     51 void 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 
     68 Address RelocInfo::target_address() {
     69   ASSERT(IsCodeTarget(rmode_) || rmode_ == RUNTIME_ENTRY);
     70   return Assembler::target_address_at(pc_);
     71 }
     72 
     73 
     74 Address RelocInfo::target_address_address() {
     75   ASSERT(IsCodeTarget(rmode_) || rmode_ == RUNTIME_ENTRY);
     76   return reinterpret_cast<Address>(pc_);
     77 }
     78 
     79 
     80 void RelocInfo::set_target_address(Address target) {
     81   ASSERT(IsCodeTarget(rmode_) || rmode_ == RUNTIME_ENTRY);
     82   Assembler::set_target_address_at(pc_, target);
     83 }
     84 
     85 
     86 Object* RelocInfo::target_object() {
     87   ASSERT(IsCodeTarget(rmode_) || rmode_ == EMBEDDED_OBJECT);
     88   return Memory::Object_at(pc_);
     89 }
     90 
     91 
     92 Handle<Object> RelocInfo::target_object_handle(Assembler* origin) {
     93   ASSERT(IsCodeTarget(rmode_) || rmode_ == EMBEDDED_OBJECT);
     94   return Memory::Object_Handle_at(pc_);
     95 }
     96 
     97 
     98 Object** RelocInfo::target_object_address() {
     99   ASSERT(IsCodeTarget(rmode_) || rmode_ == EMBEDDED_OBJECT);
    100   return &Memory::Object_at(pc_);
    101 }
    102 
    103 
    104 void RelocInfo::set_target_object(Object* target) {
    105   ASSERT(IsCodeTarget(rmode_) || rmode_ == EMBEDDED_OBJECT);
    106   Memory::Object_at(pc_) = target;
    107 }
    108 
    109 
    110 Address* RelocInfo::target_reference_address() {
    111   ASSERT(rmode_ == RelocInfo::EXTERNAL_REFERENCE);
    112   return reinterpret_cast<Address*>(pc_);
    113 }
    114 
    115 
    116 Address RelocInfo::call_address() {
    117   ASSERT(IsPatchedReturnSequence());
    118   return Assembler::target_address_at(pc_ + 1);
    119 }
    120 
    121 
    122 void RelocInfo::set_call_address(Address target) {
    123   ASSERT(IsPatchedReturnSequence());
    124   Assembler::set_target_address_at(pc_ + 1, target);
    125 }
    126 
    127 
    128 Object* RelocInfo::call_object() {
    129   ASSERT(IsPatchedReturnSequence());
    130   return *call_object_address();
    131 }
    132 
    133 
    134 Object** RelocInfo::call_object_address() {
    135   ASSERT(IsPatchedReturnSequence());
    136   return reinterpret_cast<Object**>(pc_ + 1);
    137 }
    138 
    139 
    140 void RelocInfo::set_call_object(Object* target) {
    141   ASSERT(IsPatchedReturnSequence());
    142   *call_object_address() = target;
    143 }
    144 
    145 
    146 bool RelocInfo::IsPatchedReturnSequence() {
    147   return *pc_ == 0xE8;
    148 }
    149 
    150 
    151 Immediate::Immediate(int x)  {
    152   x_ = x;
    153   rmode_ = RelocInfo::NONE;
    154 }
    155 
    156 
    157 Immediate::Immediate(const ExternalReference& ext) {
    158   x_ = reinterpret_cast<int32_t>(ext.address());
    159   rmode_ = RelocInfo::EXTERNAL_REFERENCE;
    160 }
    161 
    162 Immediate::Immediate(const char* s) {
    163   x_ = reinterpret_cast<int32_t>(s);
    164   rmode_ = RelocInfo::EMBEDDED_STRING;
    165 }
    166 
    167 
    168 Immediate::Immediate(Label* internal_offset) {
    169   x_ = reinterpret_cast<int32_t>(internal_offset);
    170   rmode_ = RelocInfo::INTERNAL_REFERENCE;
    171 }
    172 
    173 
    174 Immediate::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 
    189 Immediate::Immediate(Smi* value) {
    190   x_ = reinterpret_cast<intptr_t>(value);
    191   rmode_ = RelocInfo::NONE;
    192 }
    193 
    194 
    195 void Assembler::emit(uint32_t x) {
    196   *reinterpret_cast<uint32_t*>(pc_) = x;
    197   pc_ += sizeof(uint32_t);
    198 }
    199 
    200 
    201 void 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 
    215 void Assembler::emit(uint32_t x, RelocInfo::Mode rmode) {
    216   if (rmode != RelocInfo::NONE) RecordRelocInfo(rmode);
    217   emit(x);
    218 }
    219 
    220 
    221 void 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 
    232 void 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 
    243 void 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 
    251 Address Assembler::target_address_at(Address pc) {
    252   return pc + sizeof(int32_t) + *reinterpret_cast<int32_t*>(pc);
    253 }
    254 
    255 
    256 void 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 
    263 Displacement Assembler::disp_at(Label* L) {
    264   return Displacement(long_at(L->pos()));
    265 }
    266 
    267 
    268 void Assembler::disp_at_put(Label* L, Displacement disp) {
    269   long_at_put(L->pos(), disp.data());
    270 }
    271 
    272 
    273 void 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 
    280 void 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 
    287 void 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 
    297 void Operand::set_disp8(int8_t disp) {
    298   ASSERT(len_ == 1 || len_ == 2);
    299   *reinterpret_cast<int8_t*>(&buf_[len_++]) = disp;
    300 }
    301 
    302 
    303 void 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 
    311 Operand::Operand(Register reg) {
    312   // reg
    313   set_modrm(3, reg);
    314 }
    315 
    316 
    317 Operand::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