Home | History | Annotate | Download | only in x64
      1 // Copyright 2012 the V8 project authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #ifndef V8_X64_ASSEMBLER_X64_INL_H_
      6 #define V8_X64_ASSEMBLER_X64_INL_H_
      7 
      8 #include "src/x64/assembler-x64.h"
      9 
     10 #include "src/base/cpu.h"
     11 #include "src/debug/debug.h"
     12 #include "src/objects-inl.h"
     13 #include "src/v8memory.h"
     14 
     15 namespace v8 {
     16 namespace internal {
     17 
     18 bool CpuFeatures::SupportsCrankshaft() { return true; }
     19 
     20 bool CpuFeatures::SupportsSimd128() { return true; }
     21 
     22 // -----------------------------------------------------------------------------
     23 // Implementation of Assembler
     24 
     25 
     26 static const byte kCallOpcode = 0xE8;
     27 
     28 
     29 void Assembler::emitl(uint32_t x) {
     30   Memory::uint32_at(pc_) = x;
     31   pc_ += sizeof(uint32_t);
     32 }
     33 
     34 
     35 void Assembler::emitp(void* x, RelocInfo::Mode rmode) {
     36   uintptr_t value = reinterpret_cast<uintptr_t>(x);
     37   Memory::uintptr_at(pc_) = value;
     38   if (!RelocInfo::IsNone(rmode)) {
     39     RecordRelocInfo(rmode, value);
     40   }
     41   pc_ += sizeof(uintptr_t);
     42 }
     43 
     44 
     45 void Assembler::emitq(uint64_t x) {
     46   Memory::uint64_at(pc_) = x;
     47   pc_ += sizeof(uint64_t);
     48 }
     49 
     50 
     51 void Assembler::emitw(uint16_t x) {
     52   Memory::uint16_at(pc_) = x;
     53   pc_ += sizeof(uint16_t);
     54 }
     55 
     56 
     57 void Assembler::emit_code_target(Handle<Code> target,
     58                                  RelocInfo::Mode rmode,
     59                                  TypeFeedbackId ast_id) {
     60   DCHECK(RelocInfo::IsCodeTarget(rmode) ||
     61       rmode == RelocInfo::CODE_AGE_SEQUENCE);
     62   if (rmode == RelocInfo::CODE_TARGET && !ast_id.IsNone()) {
     63     RecordRelocInfo(RelocInfo::CODE_TARGET_WITH_ID, ast_id.ToInt());
     64   } else {
     65     RecordRelocInfo(rmode);
     66   }
     67   int current = code_targets_.length();
     68   if (current > 0 && code_targets_.last().address() == target.address()) {
     69     // Optimization if we keep jumping to the same code target.
     70     emitl(current - 1);
     71   } else {
     72     code_targets_.Add(target);
     73     emitl(current);
     74   }
     75 }
     76 
     77 
     78 void Assembler::emit_runtime_entry(Address entry, RelocInfo::Mode rmode) {
     79   DCHECK(RelocInfo::IsRuntimeEntry(rmode));
     80   RecordRelocInfo(rmode);
     81   emitl(static_cast<uint32_t>(
     82       entry - isolate()->heap()->memory_allocator()->code_range()->start()));
     83 }
     84 
     85 void Assembler::emit(Immediate x) {
     86   if (!RelocInfo::IsNone(x.rmode_)) {
     87     RecordRelocInfo(x.rmode_);
     88   }
     89   emitl(x.value_);
     90 }
     91 
     92 void Assembler::emit_rex_64(Register reg, Register rm_reg) {
     93   emit(0x48 | reg.high_bit() << 2 | rm_reg.high_bit());
     94 }
     95 
     96 
     97 void Assembler::emit_rex_64(XMMRegister reg, Register rm_reg) {
     98   emit(0x48 | (reg.code() & 0x8) >> 1 | rm_reg.code() >> 3);
     99 }
    100 
    101 
    102 void Assembler::emit_rex_64(Register reg, XMMRegister rm_reg) {
    103   emit(0x48 | (reg.code() & 0x8) >> 1 | rm_reg.code() >> 3);
    104 }
    105 
    106 
    107 void Assembler::emit_rex_64(Register reg, const Operand& op) {
    108   emit(0x48 | reg.high_bit() << 2 | op.rex_);
    109 }
    110 
    111 
    112 void Assembler::emit_rex_64(XMMRegister reg, const Operand& op) {
    113   emit(0x48 | (reg.code() & 0x8) >> 1 | op.rex_);
    114 }
    115 
    116 
    117 void Assembler::emit_rex_64(Register rm_reg) {
    118   DCHECK_EQ(rm_reg.code() & 0xf, rm_reg.code());
    119   emit(0x48 | rm_reg.high_bit());
    120 }
    121 
    122 
    123 void Assembler::emit_rex_64(const Operand& op) {
    124   emit(0x48 | op.rex_);
    125 }
    126 
    127 
    128 void Assembler::emit_rex_32(Register reg, Register rm_reg) {
    129   emit(0x40 | reg.high_bit() << 2 | rm_reg.high_bit());
    130 }
    131 
    132 
    133 void Assembler::emit_rex_32(Register reg, const Operand& op) {
    134   emit(0x40 | reg.high_bit() << 2  | op.rex_);
    135 }
    136 
    137 
    138 void Assembler::emit_rex_32(Register rm_reg) {
    139   emit(0x40 | rm_reg.high_bit());
    140 }
    141 
    142 
    143 void Assembler::emit_rex_32(const Operand& op) {
    144   emit(0x40 | op.rex_);
    145 }
    146 
    147 
    148 void Assembler::emit_optional_rex_32(Register reg, Register rm_reg) {
    149   byte rex_bits = reg.high_bit() << 2 | rm_reg.high_bit();
    150   if (rex_bits != 0) emit(0x40 | rex_bits);
    151 }
    152 
    153 
    154 void Assembler::emit_optional_rex_32(Register reg, const Operand& op) {
    155   byte rex_bits =  reg.high_bit() << 2 | op.rex_;
    156   if (rex_bits != 0) emit(0x40 | rex_bits);
    157 }
    158 
    159 
    160 void Assembler::emit_optional_rex_32(XMMRegister reg, const Operand& op) {
    161   byte rex_bits =  (reg.code() & 0x8) >> 1 | op.rex_;
    162   if (rex_bits != 0) emit(0x40 | rex_bits);
    163 }
    164 
    165 
    166 void Assembler::emit_optional_rex_32(XMMRegister reg, XMMRegister base) {
    167   byte rex_bits =  (reg.code() & 0x8) >> 1 | (base.code() & 0x8) >> 3;
    168   if (rex_bits != 0) emit(0x40 | rex_bits);
    169 }
    170 
    171 
    172 void Assembler::emit_optional_rex_32(XMMRegister reg, Register base) {
    173   byte rex_bits =  (reg.code() & 0x8) >> 1 | (base.code() & 0x8) >> 3;
    174   if (rex_bits != 0) emit(0x40 | rex_bits);
    175 }
    176 
    177 
    178 void Assembler::emit_optional_rex_32(Register reg, XMMRegister base) {
    179   byte rex_bits =  (reg.code() & 0x8) >> 1 | (base.code() & 0x8) >> 3;
    180   if (rex_bits != 0) emit(0x40 | rex_bits);
    181 }
    182 
    183 
    184 void Assembler::emit_optional_rex_32(Register rm_reg) {
    185   if (rm_reg.high_bit()) emit(0x41);
    186 }
    187 
    188 void Assembler::emit_optional_rex_32(XMMRegister rm_reg) {
    189   if (rm_reg.high_bit()) emit(0x41);
    190 }
    191 
    192 void Assembler::emit_optional_rex_32(const Operand& op) {
    193   if (op.rex_ != 0) emit(0x40 | op.rex_);
    194 }
    195 
    196 
    197 // byte 1 of 3-byte VEX
    198 void Assembler::emit_vex3_byte1(XMMRegister reg, XMMRegister rm,
    199                                 LeadingOpcode m) {
    200   byte rxb = ~((reg.high_bit() << 2) | rm.high_bit()) << 5;
    201   emit(rxb | m);
    202 }
    203 
    204 
    205 // byte 1 of 3-byte VEX
    206 void Assembler::emit_vex3_byte1(XMMRegister reg, const Operand& rm,
    207                                 LeadingOpcode m) {
    208   byte rxb = ~((reg.high_bit() << 2) | rm.rex_) << 5;
    209   emit(rxb | m);
    210 }
    211 
    212 
    213 // byte 1 of 2-byte VEX
    214 void Assembler::emit_vex2_byte1(XMMRegister reg, XMMRegister v, VectorLength l,
    215                                 SIMDPrefix pp) {
    216   byte rv = ~((reg.high_bit() << 4) | v.code()) << 3;
    217   emit(rv | l | pp);
    218 }
    219 
    220 
    221 // byte 2 of 3-byte VEX
    222 void Assembler::emit_vex3_byte2(VexW w, XMMRegister v, VectorLength l,
    223                                 SIMDPrefix pp) {
    224   emit(w | ((~v.code() & 0xf) << 3) | l | pp);
    225 }
    226 
    227 
    228 void Assembler::emit_vex_prefix(XMMRegister reg, XMMRegister vreg,
    229                                 XMMRegister rm, VectorLength l, SIMDPrefix pp,
    230                                 LeadingOpcode mm, VexW w) {
    231   if (rm.high_bit() || mm != k0F || w != kW0) {
    232     emit_vex3_byte0();
    233     emit_vex3_byte1(reg, rm, mm);
    234     emit_vex3_byte2(w, vreg, l, pp);
    235   } else {
    236     emit_vex2_byte0();
    237     emit_vex2_byte1(reg, vreg, l, pp);
    238   }
    239 }
    240 
    241 
    242 void Assembler::emit_vex_prefix(Register reg, Register vreg, Register rm,
    243                                 VectorLength l, SIMDPrefix pp, LeadingOpcode mm,
    244                                 VexW w) {
    245   XMMRegister ireg = {reg.code()};
    246   XMMRegister ivreg = {vreg.code()};
    247   XMMRegister irm = {rm.code()};
    248   emit_vex_prefix(ireg, ivreg, irm, l, pp, mm, w);
    249 }
    250 
    251 
    252 void Assembler::emit_vex_prefix(XMMRegister reg, XMMRegister vreg,
    253                                 const Operand& rm, VectorLength l,
    254                                 SIMDPrefix pp, LeadingOpcode mm, VexW w) {
    255   if (rm.rex_ || mm != k0F || w != kW0) {
    256     emit_vex3_byte0();
    257     emit_vex3_byte1(reg, rm, mm);
    258     emit_vex3_byte2(w, vreg, l, pp);
    259   } else {
    260     emit_vex2_byte0();
    261     emit_vex2_byte1(reg, vreg, l, pp);
    262   }
    263 }
    264 
    265 
    266 void Assembler::emit_vex_prefix(Register reg, Register vreg, const Operand& rm,
    267                                 VectorLength l, SIMDPrefix pp, LeadingOpcode mm,
    268                                 VexW w) {
    269   XMMRegister ireg = {reg.code()};
    270   XMMRegister ivreg = {vreg.code()};
    271   emit_vex_prefix(ireg, ivreg, rm, l, pp, mm, w);
    272 }
    273 
    274 
    275 Address Assembler::target_address_at(Address pc, Address constant_pool) {
    276   return Memory::int32_at(pc) + pc + 4;
    277 }
    278 
    279 
    280 void Assembler::set_target_address_at(Isolate* isolate, Address pc,
    281                                       Address constant_pool, Address target,
    282                                       ICacheFlushMode icache_flush_mode) {
    283   Memory::int32_at(pc) = static_cast<int32_t>(target - pc - 4);
    284   if (icache_flush_mode != SKIP_ICACHE_FLUSH) {
    285     Assembler::FlushICache(isolate, pc, sizeof(int32_t));
    286   }
    287 }
    288 
    289 Address Assembler::target_address_at(Address pc, Code* code) {
    290   Address constant_pool = code ? code->constant_pool() : NULL;
    291   return target_address_at(pc, constant_pool);
    292 }
    293 
    294 void Assembler::set_target_address_at(Isolate* isolate, Address pc, Code* code,
    295                                       Address target,
    296                                       ICacheFlushMode icache_flush_mode) {
    297   Address constant_pool = code ? code->constant_pool() : NULL;
    298   set_target_address_at(isolate, pc, constant_pool, target, icache_flush_mode);
    299 }
    300 
    301 void Assembler::deserialization_set_target_internal_reference_at(
    302     Isolate* isolate, Address pc, Address target, RelocInfo::Mode mode) {
    303   Memory::Address_at(pc) = target;
    304 }
    305 
    306 
    307 Address Assembler::target_address_from_return_address(Address pc) {
    308   return pc - kCallTargetAddressOffset;
    309 }
    310 
    311 void Assembler::deserialization_set_special_target_at(
    312     Isolate* isolate, Address instruction_payload, Code* code, Address target) {
    313   set_target_address_at(isolate, instruction_payload, code, target);
    314 }
    315 
    316 Handle<Object> Assembler::code_target_object_handle_at(Address pc) {
    317   return code_targets_[Memory::int32_at(pc)];
    318 }
    319 
    320 
    321 Address Assembler::runtime_entry_at(Address pc) {
    322   return Memory::int32_at(pc) +
    323          isolate()->heap()->memory_allocator()->code_range()->start();
    324 }
    325 
    326 // -----------------------------------------------------------------------------
    327 // Implementation of RelocInfo
    328 
    329 // The modes possibly affected by apply must be in kApplyMask.
    330 void RelocInfo::apply(intptr_t delta) {
    331   if (IsCodeTarget(rmode_) || IsRuntimeEntry(rmode_)) {
    332     Memory::int32_at(pc_) -= static_cast<int32_t>(delta);
    333   } else if (IsCodeAgeSequence(rmode_)) {
    334     if (*pc_ == kCallOpcode) {
    335       int32_t* p = reinterpret_cast<int32_t*>(pc_ + 1);
    336       *p -= static_cast<int32_t>(delta);  // Relocate entry.
    337     }
    338   } else if (IsInternalReference(rmode_)) {
    339     // absolute code pointer inside code object moves with the code object.
    340     Memory::Address_at(pc_) += delta;
    341   }
    342 }
    343 
    344 
    345 Address RelocInfo::target_address() {
    346   DCHECK(IsCodeTarget(rmode_) || IsRuntimeEntry(rmode_));
    347   return Assembler::target_address_at(pc_, host_);
    348 }
    349 
    350 Address RelocInfo::target_address_address() {
    351   DCHECK(IsCodeTarget(rmode_) || IsRuntimeEntry(rmode_)
    352                               || rmode_ == EMBEDDED_OBJECT
    353                               || rmode_ == EXTERNAL_REFERENCE);
    354   return reinterpret_cast<Address>(pc_);
    355 }
    356 
    357 
    358 Address RelocInfo::constant_pool_entry_address() {
    359   UNREACHABLE();
    360   return NULL;
    361 }
    362 
    363 
    364 int RelocInfo::target_address_size() {
    365   if (IsCodedSpecially()) {
    366     return Assembler::kSpecialTargetSize;
    367   } else {
    368     return kPointerSize;
    369   }
    370 }
    371 
    372 
    373 Object* RelocInfo::target_object() {
    374   DCHECK(IsCodeTarget(rmode_) || rmode_ == EMBEDDED_OBJECT);
    375   return Memory::Object_at(pc_);
    376 }
    377 
    378 
    379 Handle<Object> RelocInfo::target_object_handle(Assembler* origin) {
    380   DCHECK(IsCodeTarget(rmode_) || rmode_ == EMBEDDED_OBJECT);
    381   if (rmode_ == EMBEDDED_OBJECT) {
    382     return Memory::Object_Handle_at(pc_);
    383   } else {
    384     return origin->code_target_object_handle_at(pc_);
    385   }
    386 }
    387 
    388 
    389 Address RelocInfo::target_external_reference() {
    390   DCHECK(rmode_ == RelocInfo::EXTERNAL_REFERENCE);
    391   return Memory::Address_at(pc_);
    392 }
    393 
    394 
    395 Address RelocInfo::target_internal_reference() {
    396   DCHECK(rmode_ == INTERNAL_REFERENCE);
    397   return Memory::Address_at(pc_);
    398 }
    399 
    400 
    401 Address RelocInfo::target_internal_reference_address() {
    402   DCHECK(rmode_ == INTERNAL_REFERENCE);
    403   return reinterpret_cast<Address>(pc_);
    404 }
    405 
    406 
    407 void RelocInfo::set_target_object(Object* target,
    408                                   WriteBarrierMode write_barrier_mode,
    409                                   ICacheFlushMode icache_flush_mode) {
    410   DCHECK(IsCodeTarget(rmode_) || rmode_ == EMBEDDED_OBJECT);
    411   Memory::Object_at(pc_) = target;
    412   if (icache_flush_mode != SKIP_ICACHE_FLUSH) {
    413     Assembler::FlushICache(isolate_, pc_, sizeof(Address));
    414   }
    415   if (write_barrier_mode == UPDATE_WRITE_BARRIER &&
    416       host() != NULL &&
    417       target->IsHeapObject()) {
    418     host()->GetHeap()->incremental_marking()->RecordWriteIntoCode(
    419         host(), this, HeapObject::cast(target));
    420     host()->GetHeap()->RecordWriteIntoCode(host(), this, target);
    421   }
    422 }
    423 
    424 
    425 Address RelocInfo::target_runtime_entry(Assembler* origin) {
    426   DCHECK(IsRuntimeEntry(rmode_));
    427   return origin->runtime_entry_at(pc_);
    428 }
    429 
    430 
    431 void RelocInfo::set_target_runtime_entry(Address target,
    432                                          WriteBarrierMode write_barrier_mode,
    433                                          ICacheFlushMode icache_flush_mode) {
    434   DCHECK(IsRuntimeEntry(rmode_));
    435   if (target_address() != target) {
    436     set_target_address(target, write_barrier_mode, icache_flush_mode);
    437   }
    438 }
    439 
    440 
    441 Handle<Cell> RelocInfo::target_cell_handle() {
    442   DCHECK(rmode_ == RelocInfo::CELL);
    443   Address address = Memory::Address_at(pc_);
    444   return Handle<Cell>(reinterpret_cast<Cell**>(address));
    445 }
    446 
    447 
    448 Cell* RelocInfo::target_cell() {
    449   DCHECK(rmode_ == RelocInfo::CELL);
    450   return Cell::FromValueAddress(Memory::Address_at(pc_));
    451 }
    452 
    453 
    454 void RelocInfo::set_target_cell(Cell* cell,
    455                                 WriteBarrierMode write_barrier_mode,
    456                                 ICacheFlushMode icache_flush_mode) {
    457   DCHECK(rmode_ == RelocInfo::CELL);
    458   Address address = cell->address() + Cell::kValueOffset;
    459   Memory::Address_at(pc_) = address;
    460   if (icache_flush_mode != SKIP_ICACHE_FLUSH) {
    461     Assembler::FlushICache(isolate_, pc_, sizeof(Address));
    462   }
    463   if (write_barrier_mode == UPDATE_WRITE_BARRIER &&
    464       host() != NULL) {
    465     host()->GetHeap()->incremental_marking()->RecordWriteIntoCode(host(), this,
    466                                                                   cell);
    467   }
    468 }
    469 
    470 
    471 void RelocInfo::WipeOut() {
    472   if (IsEmbeddedObject(rmode_) || IsExternalReference(rmode_) ||
    473       IsInternalReference(rmode_)) {
    474     Memory::Address_at(pc_) = NULL;
    475   } else if (IsCodeTarget(rmode_) || IsRuntimeEntry(rmode_)) {
    476     // Effectively write zero into the relocation.
    477     Assembler::set_target_address_at(isolate_, pc_, host_,
    478                                      pc_ + sizeof(int32_t));
    479   } else {
    480     UNREACHABLE();
    481   }
    482 }
    483 
    484 
    485 Handle<Object> RelocInfo::code_age_stub_handle(Assembler* origin) {
    486   DCHECK(rmode_ == RelocInfo::CODE_AGE_SEQUENCE);
    487   DCHECK(*pc_ == kCallOpcode);
    488   return origin->code_target_object_handle_at(pc_ + 1);
    489 }
    490 
    491 
    492 Code* RelocInfo::code_age_stub() {
    493   DCHECK(rmode_ == RelocInfo::CODE_AGE_SEQUENCE);
    494   DCHECK(*pc_ == kCallOpcode);
    495   return Code::GetCodeFromTargetAddress(
    496       Assembler::target_address_at(pc_ + 1, host_));
    497 }
    498 
    499 
    500 void RelocInfo::set_code_age_stub(Code* stub,
    501                                   ICacheFlushMode icache_flush_mode) {
    502   DCHECK(*pc_ == kCallOpcode);
    503   DCHECK(rmode_ == RelocInfo::CODE_AGE_SEQUENCE);
    504   Assembler::set_target_address_at(
    505       isolate_, pc_ + 1, host_, stub->instruction_start(), icache_flush_mode);
    506 }
    507 
    508 
    509 Address RelocInfo::debug_call_address() {
    510   DCHECK(IsDebugBreakSlot(rmode()) && IsPatchedDebugBreakSlotSequence());
    511   return Memory::Address_at(pc_ + Assembler::kPatchDebugBreakSlotAddressOffset);
    512 }
    513 
    514 
    515 void RelocInfo::set_debug_call_address(Address target) {
    516   DCHECK(IsDebugBreakSlot(rmode()) && IsPatchedDebugBreakSlotSequence());
    517   Memory::Address_at(pc_ + Assembler::kPatchDebugBreakSlotAddressOffset) =
    518       target;
    519   Assembler::FlushICache(isolate_,
    520                          pc_ + Assembler::kPatchDebugBreakSlotAddressOffset,
    521                          sizeof(Address));
    522   if (host() != NULL) {
    523     Object* target_code = Code::GetCodeFromTargetAddress(target);
    524     host()->GetHeap()->incremental_marking()->RecordWriteIntoCode(
    525         host(), this, HeapObject::cast(target_code));
    526   }
    527 }
    528 
    529 template <typename ObjectVisitor>
    530 void RelocInfo::Visit(Isolate* isolate, ObjectVisitor* visitor) {
    531   RelocInfo::Mode mode = rmode();
    532   if (mode == RelocInfo::EMBEDDED_OBJECT) {
    533     visitor->VisitEmbeddedPointer(this);
    534     Assembler::FlushICache(isolate, pc_, sizeof(Address));
    535   } else if (RelocInfo::IsCodeTarget(mode)) {
    536     visitor->VisitCodeTarget(this);
    537   } else if (mode == RelocInfo::CELL) {
    538     visitor->VisitCell(this);
    539   } else if (mode == RelocInfo::EXTERNAL_REFERENCE) {
    540     visitor->VisitExternalReference(this);
    541   } else if (mode == RelocInfo::INTERNAL_REFERENCE) {
    542     visitor->VisitInternalReference(this);
    543   } else if (RelocInfo::IsCodeAgeSequence(mode)) {
    544     visitor->VisitCodeAgeSequence(this);
    545   } else if (RelocInfo::IsDebugBreakSlot(mode) &&
    546              IsPatchedDebugBreakSlotSequence()) {
    547     visitor->VisitDebugTarget(this);
    548   } else if (RelocInfo::IsRuntimeEntry(mode)) {
    549     visitor->VisitRuntimeEntry(this);
    550   }
    551 }
    552 
    553 
    554 template<typename StaticVisitor>
    555 void RelocInfo::Visit(Heap* heap) {
    556   RelocInfo::Mode mode = rmode();
    557   if (mode == RelocInfo::EMBEDDED_OBJECT) {
    558     StaticVisitor::VisitEmbeddedPointer(heap, this);
    559     Assembler::FlushICache(heap->isolate(), pc_, sizeof(Address));
    560   } else if (RelocInfo::IsCodeTarget(mode)) {
    561     StaticVisitor::VisitCodeTarget(heap, this);
    562   } else if (mode == RelocInfo::CELL) {
    563     StaticVisitor::VisitCell(heap, this);
    564   } else if (mode == RelocInfo::EXTERNAL_REFERENCE) {
    565     StaticVisitor::VisitExternalReference(this);
    566   } else if (mode == RelocInfo::INTERNAL_REFERENCE) {
    567     StaticVisitor::VisitInternalReference(this);
    568   } else if (RelocInfo::IsCodeAgeSequence(mode)) {
    569     StaticVisitor::VisitCodeAgeSequence(heap, this);
    570   } else if (RelocInfo::IsDebugBreakSlot(mode) &&
    571              IsPatchedDebugBreakSlotSequence()) {
    572     StaticVisitor::VisitDebugTarget(heap, this);
    573   } else if (RelocInfo::IsRuntimeEntry(mode)) {
    574     StaticVisitor::VisitRuntimeEntry(this);
    575   }
    576 }
    577 
    578 
    579 // -----------------------------------------------------------------------------
    580 // Implementation of Operand
    581 
    582 void Operand::set_modrm(int mod, Register rm_reg) {
    583   DCHECK(is_uint2(mod));
    584   buf_[0] = mod << 6 | rm_reg.low_bits();
    585   // Set REX.B to the high bit of rm.code().
    586   rex_ |= rm_reg.high_bit();
    587 }
    588 
    589 
    590 void Operand::set_sib(ScaleFactor scale, Register index, Register base) {
    591   DCHECK(len_ == 1);
    592   DCHECK(is_uint2(scale));
    593   // Use SIB with no index register only for base rsp or r12. Otherwise we
    594   // would skip the SIB byte entirely.
    595   DCHECK(!index.is(rsp) || base.is(rsp) || base.is(r12));
    596   buf_[1] = (scale << 6) | (index.low_bits() << 3) | base.low_bits();
    597   rex_ |= index.high_bit() << 1 | base.high_bit();
    598   len_ = 2;
    599 }
    600 
    601 void Operand::set_disp8(int disp) {
    602   DCHECK(is_int8(disp));
    603   DCHECK(len_ == 1 || len_ == 2);
    604   int8_t* p = reinterpret_cast<int8_t*>(&buf_[len_]);
    605   *p = disp;
    606   len_ += sizeof(int8_t);
    607 }
    608 
    609 void Operand::set_disp32(int disp) {
    610   DCHECK(len_ == 1 || len_ == 2);
    611   int32_t* p = reinterpret_cast<int32_t*>(&buf_[len_]);
    612   *p = disp;
    613   len_ += sizeof(int32_t);
    614 }
    615 
    616 void Operand::set_disp64(int64_t disp) {
    617   DCHECK_EQ(1, len_);
    618   int64_t* p = reinterpret_cast<int64_t*>(&buf_[len_]);
    619   *p = disp;
    620   len_ += sizeof(disp);
    621 }
    622 }  // namespace internal
    623 }  // namespace v8
    624 
    625 #endif  // V8_X64_ASSEMBLER_X64_INL_H_
    626