Home | History | Annotate | Download | only in x87
      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 2012 the V8 project authors. All rights reserved.
     34 
     35 // A light-weight IA32 Assembler.
     36 
     37 #ifndef V8_X87_ASSEMBLER_X87_INL_H_
     38 #define V8_X87_ASSEMBLER_X87_INL_H_
     39 
     40 #include "src/x87/assembler-x87.h"
     41 
     42 #include "src/assembler.h"
     43 #include "src/debug.h"
     44 
     45 namespace v8 {
     46 namespace internal {
     47 
     48 bool CpuFeatures::SupportsCrankshaft() { return true; }
     49 
     50 
     51 static const byte kCallOpcode = 0xE8;
     52 static const int kNoCodeAgeSequenceLength = 5;
     53 
     54 
     55 // The modes possibly affected by apply must be in kApplyMask.
     56 void RelocInfo::apply(intptr_t delta, ICacheFlushMode icache_flush_mode) {
     57   bool flush_icache = icache_flush_mode != SKIP_ICACHE_FLUSH;
     58   if (IsRuntimeEntry(rmode_) || IsCodeTarget(rmode_)) {
     59     int32_t* p = reinterpret_cast<int32_t*>(pc_);
     60     *p -= delta;  // Relocate entry.
     61     if (flush_icache) CpuFeatures::FlushICache(p, sizeof(uint32_t));
     62   } else if (rmode_ == CODE_AGE_SEQUENCE) {
     63     if (*pc_ == kCallOpcode) {
     64       int32_t* p = reinterpret_cast<int32_t*>(pc_ + 1);
     65       *p -= delta;  // Relocate entry.
     66       if (flush_icache) CpuFeatures::FlushICache(p, sizeof(uint32_t));
     67     }
     68   } else if (rmode_ == JS_RETURN && IsPatchedReturnSequence()) {
     69     // Special handling of js_return when a break point is set (call
     70     // instruction has been inserted).
     71     int32_t* p = reinterpret_cast<int32_t*>(pc_ + 1);
     72     *p -= delta;  // Relocate entry.
     73     if (flush_icache) CpuFeatures::FlushICache(p, sizeof(uint32_t));
     74   } else if (rmode_ == DEBUG_BREAK_SLOT && IsPatchedDebugBreakSlotSequence()) {
     75     // Special handling of a debug break slot when a break point is set (call
     76     // instruction has been inserted).
     77     int32_t* p = reinterpret_cast<int32_t*>(pc_ + 1);
     78     *p -= delta;  // Relocate entry.
     79     if (flush_icache) CpuFeatures::FlushICache(p, sizeof(uint32_t));
     80   } else if (IsInternalReference(rmode_)) {
     81     // absolute code pointer inside code object moves with the code object.
     82     int32_t* p = reinterpret_cast<int32_t*>(pc_);
     83     *p += delta;  // Relocate entry.
     84     if (flush_icache) CpuFeatures::FlushICache(p, sizeof(uint32_t));
     85   }
     86 }
     87 
     88 
     89 Address RelocInfo::target_address() {
     90   DCHECK(IsCodeTarget(rmode_) || IsRuntimeEntry(rmode_));
     91   return Assembler::target_address_at(pc_, host_);
     92 }
     93 
     94 
     95 Address RelocInfo::target_address_address() {
     96   DCHECK(IsCodeTarget(rmode_) || IsRuntimeEntry(rmode_)
     97                               || rmode_ == EMBEDDED_OBJECT
     98                               || rmode_ == EXTERNAL_REFERENCE);
     99   return reinterpret_cast<Address>(pc_);
    100 }
    101 
    102 
    103 Address RelocInfo::constant_pool_entry_address() {
    104   UNREACHABLE();
    105   return NULL;
    106 }
    107 
    108 
    109 int RelocInfo::target_address_size() {
    110   return Assembler::kSpecialTargetSize;
    111 }
    112 
    113 
    114 void RelocInfo::set_target_address(Address target,
    115                                    WriteBarrierMode write_barrier_mode,
    116                                    ICacheFlushMode icache_flush_mode) {
    117   Assembler::set_target_address_at(pc_, host_, target, icache_flush_mode);
    118   Assembler::set_target_address_at(pc_, host_, target);
    119   DCHECK(IsCodeTarget(rmode_) || IsRuntimeEntry(rmode_));
    120   if (write_barrier_mode == UPDATE_WRITE_BARRIER && host() != NULL &&
    121       IsCodeTarget(rmode_)) {
    122     Object* target_code = Code::GetCodeFromTargetAddress(target);
    123     host()->GetHeap()->incremental_marking()->RecordWriteIntoCode(
    124         host(), this, HeapObject::cast(target_code));
    125   }
    126 }
    127 
    128 
    129 Object* RelocInfo::target_object() {
    130   DCHECK(IsCodeTarget(rmode_) || rmode_ == EMBEDDED_OBJECT);
    131   return Memory::Object_at(pc_);
    132 }
    133 
    134 
    135 Handle<Object> RelocInfo::target_object_handle(Assembler* origin) {
    136   DCHECK(IsCodeTarget(rmode_) || rmode_ == EMBEDDED_OBJECT);
    137   return Memory::Object_Handle_at(pc_);
    138 }
    139 
    140 
    141 void RelocInfo::set_target_object(Object* target,
    142                                   WriteBarrierMode write_barrier_mode,
    143                                   ICacheFlushMode icache_flush_mode) {
    144   DCHECK(IsCodeTarget(rmode_) || rmode_ == EMBEDDED_OBJECT);
    145   Memory::Object_at(pc_) = target;
    146   if (icache_flush_mode != SKIP_ICACHE_FLUSH) {
    147     CpuFeatures::FlushICache(pc_, sizeof(Address));
    148   }
    149   if (write_barrier_mode == UPDATE_WRITE_BARRIER &&
    150       host() != NULL &&
    151       target->IsHeapObject()) {
    152     host()->GetHeap()->incremental_marking()->RecordWrite(
    153         host(), &Memory::Object_at(pc_), HeapObject::cast(target));
    154   }
    155 }
    156 
    157 
    158 Address RelocInfo::target_reference() {
    159   DCHECK(rmode_ == RelocInfo::EXTERNAL_REFERENCE);
    160   return Memory::Address_at(pc_);
    161 }
    162 
    163 
    164 Address RelocInfo::target_runtime_entry(Assembler* origin) {
    165   DCHECK(IsRuntimeEntry(rmode_));
    166   return reinterpret_cast<Address>(*reinterpret_cast<int32_t*>(pc_));
    167 }
    168 
    169 
    170 void RelocInfo::set_target_runtime_entry(Address target,
    171                                          WriteBarrierMode write_barrier_mode,
    172                                          ICacheFlushMode icache_flush_mode) {
    173   DCHECK(IsRuntimeEntry(rmode_));
    174   if (target_address() != target) {
    175     set_target_address(target, write_barrier_mode, icache_flush_mode);
    176   }
    177 }
    178 
    179 
    180 Handle<Cell> RelocInfo::target_cell_handle() {
    181   DCHECK(rmode_ == RelocInfo::CELL);
    182   Address address = Memory::Address_at(pc_);
    183   return Handle<Cell>(reinterpret_cast<Cell**>(address));
    184 }
    185 
    186 
    187 Cell* RelocInfo::target_cell() {
    188   DCHECK(rmode_ == RelocInfo::CELL);
    189   return Cell::FromValueAddress(Memory::Address_at(pc_));
    190 }
    191 
    192 
    193 void RelocInfo::set_target_cell(Cell* cell,
    194                                 WriteBarrierMode write_barrier_mode,
    195                                 ICacheFlushMode icache_flush_mode) {
    196   DCHECK(rmode_ == RelocInfo::CELL);
    197   Address address = cell->address() + Cell::kValueOffset;
    198   Memory::Address_at(pc_) = address;
    199   if (icache_flush_mode != SKIP_ICACHE_FLUSH) {
    200     CpuFeatures::FlushICache(pc_, sizeof(Address));
    201   }
    202   if (write_barrier_mode == UPDATE_WRITE_BARRIER && host() != NULL) {
    203     // TODO(1550) We are passing NULL as a slot because cell can never be on
    204     // evacuation candidate.
    205     host()->GetHeap()->incremental_marking()->RecordWrite(
    206         host(), NULL, cell);
    207   }
    208 }
    209 
    210 
    211 Handle<Object> RelocInfo::code_age_stub_handle(Assembler* origin) {
    212   DCHECK(rmode_ == RelocInfo::CODE_AGE_SEQUENCE);
    213   DCHECK(*pc_ == kCallOpcode);
    214   return Memory::Object_Handle_at(pc_ + 1);
    215 }
    216 
    217 
    218 Code* RelocInfo::code_age_stub() {
    219   DCHECK(rmode_ == RelocInfo::CODE_AGE_SEQUENCE);
    220   DCHECK(*pc_ == kCallOpcode);
    221   return Code::GetCodeFromTargetAddress(
    222       Assembler::target_address_at(pc_ + 1, host_));
    223 }
    224 
    225 
    226 void RelocInfo::set_code_age_stub(Code* stub,
    227                                   ICacheFlushMode icache_flush_mode) {
    228   DCHECK(*pc_ == kCallOpcode);
    229   DCHECK(rmode_ == RelocInfo::CODE_AGE_SEQUENCE);
    230   Assembler::set_target_address_at(pc_ + 1, host_, stub->instruction_start(),
    231                                    icache_flush_mode);
    232 }
    233 
    234 
    235 Address RelocInfo::call_address() {
    236   DCHECK((IsJSReturn(rmode()) && IsPatchedReturnSequence()) ||
    237          (IsDebugBreakSlot(rmode()) && IsPatchedDebugBreakSlotSequence()));
    238   return Assembler::target_address_at(pc_ + 1, host_);
    239 }
    240 
    241 
    242 void RelocInfo::set_call_address(Address target) {
    243   DCHECK((IsJSReturn(rmode()) && IsPatchedReturnSequence()) ||
    244          (IsDebugBreakSlot(rmode()) && IsPatchedDebugBreakSlotSequence()));
    245   Assembler::set_target_address_at(pc_ + 1, host_, target);
    246   if (host() != NULL) {
    247     Object* target_code = Code::GetCodeFromTargetAddress(target);
    248     host()->GetHeap()->incremental_marking()->RecordWriteIntoCode(
    249         host(), this, HeapObject::cast(target_code));
    250   }
    251 }
    252 
    253 
    254 Object* RelocInfo::call_object() {
    255   return *call_object_address();
    256 }
    257 
    258 
    259 void RelocInfo::set_call_object(Object* target) {
    260   *call_object_address() = target;
    261 }
    262 
    263 
    264 Object** RelocInfo::call_object_address() {
    265   DCHECK((IsJSReturn(rmode()) && IsPatchedReturnSequence()) ||
    266          (IsDebugBreakSlot(rmode()) && IsPatchedDebugBreakSlotSequence()));
    267   return reinterpret_cast<Object**>(pc_ + 1);
    268 }
    269 
    270 
    271 void RelocInfo::WipeOut() {
    272   if (IsEmbeddedObject(rmode_) || IsExternalReference(rmode_)) {
    273     Memory::Address_at(pc_) = NULL;
    274   } else if (IsCodeTarget(rmode_) || IsRuntimeEntry(rmode_)) {
    275     // Effectively write zero into the relocation.
    276     Assembler::set_target_address_at(pc_, host_, pc_ + sizeof(int32_t));
    277   } else {
    278     UNREACHABLE();
    279   }
    280 }
    281 
    282 
    283 bool RelocInfo::IsPatchedReturnSequence() {
    284   return *pc_ == kCallOpcode;
    285 }
    286 
    287 
    288 bool RelocInfo::IsPatchedDebugBreakSlotSequence() {
    289   return !Assembler::IsNop(pc());
    290 }
    291 
    292 
    293 void RelocInfo::Visit(Isolate* isolate, ObjectVisitor* visitor) {
    294   RelocInfo::Mode mode = rmode();
    295   if (mode == RelocInfo::EMBEDDED_OBJECT) {
    296     visitor->VisitEmbeddedPointer(this);
    297     CpuFeatures::FlushICache(pc_, sizeof(Address));
    298   } else if (RelocInfo::IsCodeTarget(mode)) {
    299     visitor->VisitCodeTarget(this);
    300   } else if (mode == RelocInfo::CELL) {
    301     visitor->VisitCell(this);
    302   } else if (mode == RelocInfo::EXTERNAL_REFERENCE) {
    303     visitor->VisitExternalReference(this);
    304     CpuFeatures::FlushICache(pc_, sizeof(Address));
    305   } else if (RelocInfo::IsCodeAgeSequence(mode)) {
    306     visitor->VisitCodeAgeSequence(this);
    307   } else if (((RelocInfo::IsJSReturn(mode) &&
    308               IsPatchedReturnSequence()) ||
    309              (RelocInfo::IsDebugBreakSlot(mode) &&
    310               IsPatchedDebugBreakSlotSequence())) &&
    311              isolate->debug()->has_break_points()) {
    312     visitor->VisitDebugTarget(this);
    313   } else if (IsRuntimeEntry(mode)) {
    314     visitor->VisitRuntimeEntry(this);
    315   }
    316 }
    317 
    318 
    319 template<typename StaticVisitor>
    320 void RelocInfo::Visit(Heap* heap) {
    321   RelocInfo::Mode mode = rmode();
    322   if (mode == RelocInfo::EMBEDDED_OBJECT) {
    323     StaticVisitor::VisitEmbeddedPointer(heap, this);
    324     CpuFeatures::FlushICache(pc_, sizeof(Address));
    325   } else if (RelocInfo::IsCodeTarget(mode)) {
    326     StaticVisitor::VisitCodeTarget(heap, this);
    327   } else if (mode == RelocInfo::CELL) {
    328     StaticVisitor::VisitCell(heap, this);
    329   } else if (mode == RelocInfo::EXTERNAL_REFERENCE) {
    330     StaticVisitor::VisitExternalReference(this);
    331     CpuFeatures::FlushICache(pc_, sizeof(Address));
    332   } else if (RelocInfo::IsCodeAgeSequence(mode)) {
    333     StaticVisitor::VisitCodeAgeSequence(heap, this);
    334   } else if (heap->isolate()->debug()->has_break_points() &&
    335              ((RelocInfo::IsJSReturn(mode) &&
    336               IsPatchedReturnSequence()) ||
    337              (RelocInfo::IsDebugBreakSlot(mode) &&
    338               IsPatchedDebugBreakSlotSequence()))) {
    339     StaticVisitor::VisitDebugTarget(heap, this);
    340   } else if (IsRuntimeEntry(mode)) {
    341     StaticVisitor::VisitRuntimeEntry(this);
    342   }
    343 }
    344 
    345 
    346 
    347 Immediate::Immediate(int x)  {
    348   x_ = x;
    349   rmode_ = RelocInfo::NONE32;
    350 }
    351 
    352 
    353 Immediate::Immediate(const ExternalReference& ext) {
    354   x_ = reinterpret_cast<int32_t>(ext.address());
    355   rmode_ = RelocInfo::EXTERNAL_REFERENCE;
    356 }
    357 
    358 
    359 Immediate::Immediate(Label* internal_offset) {
    360   x_ = reinterpret_cast<int32_t>(internal_offset);
    361   rmode_ = RelocInfo::INTERNAL_REFERENCE;
    362 }
    363 
    364 
    365 Immediate::Immediate(Handle<Object> handle) {
    366   AllowDeferredHandleDereference using_raw_address;
    367   // Verify all Objects referred by code are NOT in new space.
    368   Object* obj = *handle;
    369   if (obj->IsHeapObject()) {
    370     DCHECK(!HeapObject::cast(obj)->GetHeap()->InNewSpace(obj));
    371     x_ = reinterpret_cast<intptr_t>(handle.location());
    372     rmode_ = RelocInfo::EMBEDDED_OBJECT;
    373   } else {
    374     // no relocation needed
    375     x_ =  reinterpret_cast<intptr_t>(obj);
    376     rmode_ = RelocInfo::NONE32;
    377   }
    378 }
    379 
    380 
    381 Immediate::Immediate(Smi* value) {
    382   x_ = reinterpret_cast<intptr_t>(value);
    383   rmode_ = RelocInfo::NONE32;
    384 }
    385 
    386 
    387 Immediate::Immediate(Address addr) {
    388   x_ = reinterpret_cast<int32_t>(addr);
    389   rmode_ = RelocInfo::NONE32;
    390 }
    391 
    392 
    393 void Assembler::emit(uint32_t x) {
    394   *reinterpret_cast<uint32_t*>(pc_) = x;
    395   pc_ += sizeof(uint32_t);
    396 }
    397 
    398 
    399 void Assembler::emit(Handle<Object> handle) {
    400   AllowDeferredHandleDereference heap_object_check;
    401   // Verify all Objects referred by code are NOT in new space.
    402   Object* obj = *handle;
    403   DCHECK(!isolate()->heap()->InNewSpace(obj));
    404   if (obj->IsHeapObject()) {
    405     emit(reinterpret_cast<intptr_t>(handle.location()),
    406          RelocInfo::EMBEDDED_OBJECT);
    407   } else {
    408     // no relocation needed
    409     emit(reinterpret_cast<intptr_t>(obj));
    410   }
    411 }
    412 
    413 
    414 void Assembler::emit(uint32_t x, RelocInfo::Mode rmode, TypeFeedbackId id) {
    415   if (rmode == RelocInfo::CODE_TARGET && !id.IsNone()) {
    416     RecordRelocInfo(RelocInfo::CODE_TARGET_WITH_ID, id.ToInt());
    417   } else if (!RelocInfo::IsNone(rmode)
    418       && rmode != RelocInfo::CODE_AGE_SEQUENCE) {
    419     RecordRelocInfo(rmode);
    420   }
    421   emit(x);
    422 }
    423 
    424 
    425 void Assembler::emit(Handle<Code> code,
    426                      RelocInfo::Mode rmode,
    427                      TypeFeedbackId id) {
    428   AllowDeferredHandleDereference embedding_raw_address;
    429   emit(reinterpret_cast<intptr_t>(code.location()), rmode, id);
    430 }
    431 
    432 
    433 void Assembler::emit(const Immediate& x) {
    434   if (x.rmode_ == RelocInfo::INTERNAL_REFERENCE) {
    435     Label* label = reinterpret_cast<Label*>(x.x_);
    436     emit_code_relative_offset(label);
    437     return;
    438   }
    439   if (!RelocInfo::IsNone(x.rmode_)) RecordRelocInfo(x.rmode_);
    440   emit(x.x_);
    441 }
    442 
    443 
    444 void Assembler::emit_code_relative_offset(Label* label) {
    445   if (label->is_bound()) {
    446     int32_t pos;
    447     pos = label->pos() + Code::kHeaderSize - kHeapObjectTag;
    448     emit(pos);
    449   } else {
    450     emit_disp(label, Displacement::CODE_RELATIVE);
    451   }
    452 }
    453 
    454 
    455 void Assembler::emit_w(const Immediate& x) {
    456   DCHECK(RelocInfo::IsNone(x.rmode_));
    457   uint16_t value = static_cast<uint16_t>(x.x_);
    458   reinterpret_cast<uint16_t*>(pc_)[0] = value;
    459   pc_ += sizeof(uint16_t);
    460 }
    461 
    462 
    463 Address Assembler::target_address_at(Address pc,
    464                                      ConstantPoolArray* constant_pool) {
    465   return pc + sizeof(int32_t) + *reinterpret_cast<int32_t*>(pc);
    466 }
    467 
    468 
    469 void Assembler::set_target_address_at(Address pc,
    470                                       ConstantPoolArray* constant_pool,
    471                                       Address target,
    472                                       ICacheFlushMode icache_flush_mode) {
    473   int32_t* p = reinterpret_cast<int32_t*>(pc);
    474   *p = target - (pc + sizeof(int32_t));
    475   if (icache_flush_mode != SKIP_ICACHE_FLUSH) {
    476     CpuFeatures::FlushICache(p, sizeof(int32_t));
    477   }
    478 }
    479 
    480 
    481 Address Assembler::target_address_from_return_address(Address pc) {
    482   return pc - kCallTargetAddressOffset;
    483 }
    484 
    485 
    486 Address Assembler::break_address_from_return_address(Address pc) {
    487   return pc - Assembler::kPatchDebugBreakSlotReturnOffset;
    488 }
    489 
    490 
    491 Displacement Assembler::disp_at(Label* L) {
    492   return Displacement(long_at(L->pos()));
    493 }
    494 
    495 
    496 void Assembler::disp_at_put(Label* L, Displacement disp) {
    497   long_at_put(L->pos(), disp.data());
    498 }
    499 
    500 
    501 void Assembler::emit_disp(Label* L, Displacement::Type type) {
    502   Displacement disp(L, type);
    503   L->link_to(pc_offset());
    504   emit(static_cast<int>(disp.data()));
    505 }
    506 
    507 
    508 void Assembler::emit_near_disp(Label* L) {
    509   byte disp = 0x00;
    510   if (L->is_near_linked()) {
    511     int offset = L->near_link_pos() - pc_offset();
    512     DCHECK(is_int8(offset));
    513     disp = static_cast<byte>(offset & 0xFF);
    514   }
    515   L->link_to(pc_offset(), Label::kNear);
    516   *pc_++ = disp;
    517 }
    518 
    519 
    520 void Operand::set_modrm(int mod, Register rm) {
    521   DCHECK((mod & -4) == 0);
    522   buf_[0] = mod << 6 | rm.code();
    523   len_ = 1;
    524 }
    525 
    526 
    527 void Operand::set_sib(ScaleFactor scale, Register index, Register base) {
    528   DCHECK(len_ == 1);
    529   DCHECK((scale & -4) == 0);
    530   // Use SIB with no index register only for base esp.
    531   DCHECK(!index.is(esp) || base.is(esp));
    532   buf_[1] = scale << 6 | index.code() << 3 | base.code();
    533   len_ = 2;
    534 }
    535 
    536 
    537 void Operand::set_disp8(int8_t disp) {
    538   DCHECK(len_ == 1 || len_ == 2);
    539   *reinterpret_cast<int8_t*>(&buf_[len_++]) = disp;
    540 }
    541 
    542 
    543 void Operand::set_dispr(int32_t disp, RelocInfo::Mode rmode) {
    544   DCHECK(len_ == 1 || len_ == 2);
    545   int32_t* p = reinterpret_cast<int32_t*>(&buf_[len_]);
    546   *p = disp;
    547   len_ += sizeof(int32_t);
    548   rmode_ = rmode;
    549 }
    550 
    551 Operand::Operand(Register reg) {
    552   // reg
    553   set_modrm(3, reg);
    554 }
    555 
    556 
    557 Operand::Operand(int32_t disp, RelocInfo::Mode rmode) {
    558   // [disp/r]
    559   set_modrm(0, ebp);
    560   set_dispr(disp, rmode);
    561 }
    562 
    563 
    564 Operand::Operand(Immediate imm) {
    565   // [disp/r]
    566   set_modrm(0, ebp);
    567   set_dispr(imm.x_, imm.rmode_);
    568 }
    569 } }  // namespace v8::internal
    570 
    571 #endif  // V8_X87_ASSEMBLER_X87_INL_H_
    572