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
      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 2012 the V8 project authors. All rights reserved.
     36 
     37 #include "src/v8.h"
     38 
     39 #if V8_TARGET_ARCH_X87
     40 
     41 #include "src/disassembler.h"
     42 #include "src/macro-assembler.h"
     43 #include "src/serialize.h"
     44 
     45 namespace v8 {
     46 namespace internal {
     47 
     48 // -----------------------------------------------------------------------------
     49 // Implementation of CpuFeatures
     50 
     51 void CpuFeatures::ProbeImpl(bool cross_compile) {
     52   CPU cpu;
     53 
     54   // Only use statically determined features for cross compile (snapshot).
     55   if (cross_compile) return;
     56 }
     57 
     58 
     59 void CpuFeatures::PrintTarget() { }
     60 void CpuFeatures::PrintFeatures() { }
     61 
     62 
     63 // -----------------------------------------------------------------------------
     64 // Implementation of Displacement
     65 
     66 void Displacement::init(Label* L, Type type) {
     67   ASSERT(!L->is_bound());
     68   int next = 0;
     69   if (L->is_linked()) {
     70     next = L->pos();
     71     ASSERT(next > 0);  // Displacements must be at positions > 0
     72   }
     73   // Ensure that we _never_ overflow the next field.
     74   ASSERT(NextField::is_valid(Assembler::kMaximalBufferSize));
     75   data_ = NextField::encode(next) | TypeField::encode(type);
     76 }
     77 
     78 
     79 // -----------------------------------------------------------------------------
     80 // Implementation of RelocInfo
     81 
     82 
     83 const int RelocInfo::kApplyMask =
     84   RelocInfo::kCodeTargetMask | 1 << RelocInfo::RUNTIME_ENTRY |
     85     1 << RelocInfo::JS_RETURN | 1 << RelocInfo::INTERNAL_REFERENCE |
     86     1 << RelocInfo::DEBUG_BREAK_SLOT | 1 << RelocInfo::CODE_AGE_SEQUENCE;
     87 
     88 
     89 bool RelocInfo::IsCodedSpecially() {
     90   // The deserializer needs to know whether a pointer is specially coded.  Being
     91   // specially coded on IA32 means that it is a relative address, as used by
     92   // branch instructions.  These are also the ones that need changing when a
     93   // code object moves.
     94   return (1 << rmode_) & kApplyMask;
     95 }
     96 
     97 
     98 bool RelocInfo::IsInConstantPool() {
     99   return false;
    100 }
    101 
    102 
    103 void RelocInfo::PatchCode(byte* instructions, int instruction_count) {
    104   // Patch the code at the current address with the supplied instructions.
    105   for (int i = 0; i < instruction_count; i++) {
    106     *(pc_ + i) = *(instructions + i);
    107   }
    108 
    109   // Indicate that code has changed.
    110   CPU::FlushICache(pc_, instruction_count);
    111 }
    112 
    113 
    114 // Patch the code at the current PC with a call to the target address.
    115 // Additional guard int3 instructions can be added if required.
    116 void RelocInfo::PatchCodeWithCall(Address target, int guard_bytes) {
    117   // Call instruction takes up 5 bytes and int3 takes up one byte.
    118   static const int kCallCodeSize = 5;
    119   int code_size = kCallCodeSize + guard_bytes;
    120 
    121   // Create a code patcher.
    122   CodePatcher patcher(pc_, code_size);
    123 
    124   // Add a label for checking the size of the code used for returning.
    125 #ifdef DEBUG
    126   Label check_codesize;
    127   patcher.masm()->bind(&check_codesize);
    128 #endif
    129 
    130   // Patch the code.
    131   patcher.masm()->call(target, RelocInfo::NONE32);
    132 
    133   // Check that the size of the code generated is as expected.
    134   ASSERT_EQ(kCallCodeSize,
    135             patcher.masm()->SizeOfCodeGeneratedSince(&check_codesize));
    136 
    137   // Add the requested number of int3 instructions after the call.
    138   ASSERT_GE(guard_bytes, 0);
    139   for (int i = 0; i < guard_bytes; i++) {
    140     patcher.masm()->int3();
    141   }
    142 }
    143 
    144 
    145 // -----------------------------------------------------------------------------
    146 // Implementation of Operand
    147 
    148 Operand::Operand(Register base, int32_t disp, RelocInfo::Mode rmode) {
    149   // [base + disp/r]
    150   if (disp == 0 && RelocInfo::IsNone(rmode) && !base.is(ebp)) {
    151     // [base]
    152     set_modrm(0, base);
    153     if (base.is(esp)) set_sib(times_1, esp, base);
    154   } else if (is_int8(disp) && RelocInfo::IsNone(rmode)) {
    155     // [base + disp8]
    156     set_modrm(1, base);
    157     if (base.is(esp)) set_sib(times_1, esp, base);
    158     set_disp8(disp);
    159   } else {
    160     // [base + disp/r]
    161     set_modrm(2, base);
    162     if (base.is(esp)) set_sib(times_1, esp, base);
    163     set_dispr(disp, rmode);
    164   }
    165 }
    166 
    167 
    168 Operand::Operand(Register base,
    169                  Register index,
    170                  ScaleFactor scale,
    171                  int32_t disp,
    172                  RelocInfo::Mode rmode) {
    173   ASSERT(!index.is(esp));  // illegal addressing mode
    174   // [base + index*scale + disp/r]
    175   if (disp == 0 && RelocInfo::IsNone(rmode) && !base.is(ebp)) {
    176     // [base + index*scale]
    177     set_modrm(0, esp);
    178     set_sib(scale, index, base);
    179   } else if (is_int8(disp) && RelocInfo::IsNone(rmode)) {
    180     // [base + index*scale + disp8]
    181     set_modrm(1, esp);
    182     set_sib(scale, index, base);
    183     set_disp8(disp);
    184   } else {
    185     // [base + index*scale + disp/r]
    186     set_modrm(2, esp);
    187     set_sib(scale, index, base);
    188     set_dispr(disp, rmode);
    189   }
    190 }
    191 
    192 
    193 Operand::Operand(Register index,
    194                  ScaleFactor scale,
    195                  int32_t disp,
    196                  RelocInfo::Mode rmode) {
    197   ASSERT(!index.is(esp));  // illegal addressing mode
    198   // [index*scale + disp/r]
    199   set_modrm(0, esp);
    200   set_sib(scale, index, ebp);
    201   set_dispr(disp, rmode);
    202 }
    203 
    204 
    205 bool Operand::is_reg(Register reg) const {
    206   return ((buf_[0] & 0xF8) == 0xC0)  // addressing mode is register only.
    207       && ((buf_[0] & 0x07) == reg.code());  // register codes match.
    208 }
    209 
    210 
    211 bool Operand::is_reg_only() const {
    212   return (buf_[0] & 0xF8) == 0xC0;  // Addressing mode is register only.
    213 }
    214 
    215 
    216 Register Operand::reg() const {
    217   ASSERT(is_reg_only());
    218   return Register::from_code(buf_[0] & 0x07);
    219 }
    220 
    221 
    222 // -----------------------------------------------------------------------------
    223 // Implementation of Assembler.
    224 
    225 // Emit a single byte. Must always be inlined.
    226 #define EMIT(x)                                 \
    227   *pc_++ = (x)
    228 
    229 
    230 #ifdef GENERATED_CODE_COVERAGE
    231 static void InitCoverageLog();
    232 #endif
    233 
    234 Assembler::Assembler(Isolate* isolate, void* buffer, int buffer_size)
    235     : AssemblerBase(isolate, buffer, buffer_size),
    236       positions_recorder_(this) {
    237   // Clear the buffer in debug mode unless it was provided by the
    238   // caller in which case we can't be sure it's okay to overwrite
    239   // existing code in it; see CodePatcher::CodePatcher(...).
    240 #ifdef DEBUG
    241   if (own_buffer_) {
    242     memset(buffer_, 0xCC, buffer_size_);  // int3
    243   }
    244 #endif
    245 
    246   reloc_info_writer.Reposition(buffer_ + buffer_size_, pc_);
    247 
    248 #ifdef GENERATED_CODE_COVERAGE
    249   InitCoverageLog();
    250 #endif
    251 }
    252 
    253 
    254 void Assembler::GetCode(CodeDesc* desc) {
    255   // Finalize code (at this point overflow() may be true, but the gap ensures
    256   // that we are still not overlapping instructions and relocation info).
    257   ASSERT(pc_ <= reloc_info_writer.pos());  // No overlap.
    258   // Set up code descriptor.
    259   desc->buffer = buffer_;
    260   desc->buffer_size = buffer_size_;
    261   desc->instr_size = pc_offset();
    262   desc->reloc_size = (buffer_ + buffer_size_) - reloc_info_writer.pos();
    263   desc->origin = this;
    264 }
    265 
    266 
    267 void Assembler::Align(int m) {
    268   ASSERT(IsPowerOf2(m));
    269   int mask = m - 1;
    270   int addr = pc_offset();
    271   Nop((m - (addr & mask)) & mask);
    272 }
    273 
    274 
    275 bool Assembler::IsNop(Address addr) {
    276   Address a = addr;
    277   while (*a == 0x66) a++;
    278   if (*a == 0x90) return true;
    279   if (a[0] == 0xf && a[1] == 0x1f) return true;
    280   return false;
    281 }
    282 
    283 
    284 void Assembler::Nop(int bytes) {
    285   EnsureSpace ensure_space(this);
    286 
    287   // Older CPUs that do not support SSE2 may not support multibyte NOP
    288   // instructions.
    289   for (; bytes > 0; bytes--) {
    290     EMIT(0x90);
    291   }
    292   return;
    293 }
    294 
    295 
    296 void Assembler::CodeTargetAlign() {
    297   Align(16);  // Preferred alignment of jump targets on ia32.
    298 }
    299 
    300 
    301 void Assembler::cpuid() {
    302   EnsureSpace ensure_space(this);
    303   EMIT(0x0F);
    304   EMIT(0xA2);
    305 }
    306 
    307 
    308 void Assembler::pushad() {
    309   EnsureSpace ensure_space(this);
    310   EMIT(0x60);
    311 }
    312 
    313 
    314 void Assembler::popad() {
    315   EnsureSpace ensure_space(this);
    316   EMIT(0x61);
    317 }
    318 
    319 
    320 void Assembler::pushfd() {
    321   EnsureSpace ensure_space(this);
    322   EMIT(0x9C);
    323 }
    324 
    325 
    326 void Assembler::popfd() {
    327   EnsureSpace ensure_space(this);
    328   EMIT(0x9D);
    329 }
    330 
    331 
    332 void Assembler::push(const Immediate& x) {
    333   EnsureSpace ensure_space(this);
    334   if (x.is_int8()) {
    335     EMIT(0x6a);
    336     EMIT(x.x_);
    337   } else {
    338     EMIT(0x68);
    339     emit(x);
    340   }
    341 }
    342 
    343 
    344 void Assembler::push_imm32(int32_t imm32) {
    345   EnsureSpace ensure_space(this);
    346   EMIT(0x68);
    347   emit(imm32);
    348 }
    349 
    350 
    351 void Assembler::push(Register src) {
    352   EnsureSpace ensure_space(this);
    353   EMIT(0x50 | src.code());
    354 }
    355 
    356 
    357 void Assembler::push(const Operand& src) {
    358   EnsureSpace ensure_space(this);
    359   EMIT(0xFF);
    360   emit_operand(esi, src);
    361 }
    362 
    363 
    364 void Assembler::pop(Register dst) {
    365   ASSERT(reloc_info_writer.last_pc() != NULL);
    366   EnsureSpace ensure_space(this);
    367   EMIT(0x58 | dst.code());
    368 }
    369 
    370 
    371 void Assembler::pop(const Operand& dst) {
    372   EnsureSpace ensure_space(this);
    373   EMIT(0x8F);
    374   emit_operand(eax, dst);
    375 }
    376 
    377 
    378 void Assembler::enter(const Immediate& size) {
    379   EnsureSpace ensure_space(this);
    380   EMIT(0xC8);
    381   emit_w(size);
    382   EMIT(0);
    383 }
    384 
    385 
    386 void Assembler::leave() {
    387   EnsureSpace ensure_space(this);
    388   EMIT(0xC9);
    389 }
    390 
    391 
    392 void Assembler::mov_b(Register dst, const Operand& src) {
    393   CHECK(dst.is_byte_register());
    394   EnsureSpace ensure_space(this);
    395   EMIT(0x8A);
    396   emit_operand(dst, src);
    397 }
    398 
    399 
    400 void Assembler::mov_b(const Operand& dst, int8_t imm8) {
    401   EnsureSpace ensure_space(this);
    402   EMIT(0xC6);
    403   emit_operand(eax, dst);
    404   EMIT(imm8);
    405 }
    406 
    407 
    408 void Assembler::mov_b(const Operand& dst, Register src) {
    409   CHECK(src.is_byte_register());
    410   EnsureSpace ensure_space(this);
    411   EMIT(0x88);
    412   emit_operand(src, dst);
    413 }
    414 
    415 
    416 void Assembler::mov_w(Register dst, const Operand& src) {
    417   EnsureSpace ensure_space(this);
    418   EMIT(0x66);
    419   EMIT(0x8B);
    420   emit_operand(dst, src);
    421 }
    422 
    423 
    424 void Assembler::mov_w(const Operand& dst, Register src) {
    425   EnsureSpace ensure_space(this);
    426   EMIT(0x66);
    427   EMIT(0x89);
    428   emit_operand(src, dst);
    429 }
    430 
    431 
    432 void Assembler::mov_w(const Operand& dst, int16_t imm16) {
    433   EnsureSpace ensure_space(this);
    434   EMIT(0x66);
    435   EMIT(0xC7);
    436   emit_operand(eax, dst);
    437   EMIT(static_cast<int8_t>(imm16 & 0xff));
    438   EMIT(static_cast<int8_t>(imm16 >> 8));
    439 }
    440 
    441 
    442 void Assembler::mov(Register dst, int32_t imm32) {
    443   EnsureSpace ensure_space(this);
    444   EMIT(0xB8 | dst.code());
    445   emit(imm32);
    446 }
    447 
    448 
    449 void Assembler::mov(Register dst, const Immediate& x) {
    450   EnsureSpace ensure_space(this);
    451   EMIT(0xB8 | dst.code());
    452   emit(x);
    453 }
    454 
    455 
    456 void Assembler::mov(Register dst, Handle<Object> handle) {
    457   EnsureSpace ensure_space(this);
    458   EMIT(0xB8 | dst.code());
    459   emit(handle);
    460 }
    461 
    462 
    463 void Assembler::mov(Register dst, const Operand& src) {
    464   EnsureSpace ensure_space(this);
    465   EMIT(0x8B);
    466   emit_operand(dst, src);
    467 }
    468 
    469 
    470 void Assembler::mov(Register dst, Register src) {
    471   EnsureSpace ensure_space(this);
    472   EMIT(0x89);
    473   EMIT(0xC0 | src.code() << 3 | dst.code());
    474 }
    475 
    476 
    477 void Assembler::mov(const Operand& dst, const Immediate& x) {
    478   EnsureSpace ensure_space(this);
    479   EMIT(0xC7);
    480   emit_operand(eax, dst);
    481   emit(x);
    482 }
    483 
    484 
    485 void Assembler::mov(const Operand& dst, Handle<Object> handle) {
    486   EnsureSpace ensure_space(this);
    487   EMIT(0xC7);
    488   emit_operand(eax, dst);
    489   emit(handle);
    490 }
    491 
    492 
    493 void Assembler::mov(const Operand& dst, Register src) {
    494   EnsureSpace ensure_space(this);
    495   EMIT(0x89);
    496   emit_operand(src, dst);
    497 }
    498 
    499 
    500 void Assembler::movsx_b(Register dst, const Operand& src) {
    501   EnsureSpace ensure_space(this);
    502   EMIT(0x0F);
    503   EMIT(0xBE);
    504   emit_operand(dst, src);
    505 }
    506 
    507 
    508 void Assembler::movsx_w(Register dst, const Operand& src) {
    509   EnsureSpace ensure_space(this);
    510   EMIT(0x0F);
    511   EMIT(0xBF);
    512   emit_operand(dst, src);
    513 }
    514 
    515 
    516 void Assembler::movzx_b(Register dst, const Operand& src) {
    517   EnsureSpace ensure_space(this);
    518   EMIT(0x0F);
    519   EMIT(0xB6);
    520   emit_operand(dst, src);
    521 }
    522 
    523 
    524 void Assembler::movzx_w(Register dst, const Operand& src) {
    525   EnsureSpace ensure_space(this);
    526   EMIT(0x0F);
    527   EMIT(0xB7);
    528   emit_operand(dst, src);
    529 }
    530 
    531 
    532 void Assembler::cld() {
    533   EnsureSpace ensure_space(this);
    534   EMIT(0xFC);
    535 }
    536 
    537 
    538 void Assembler::rep_movs() {
    539   EnsureSpace ensure_space(this);
    540   EMIT(0xF3);
    541   EMIT(0xA5);
    542 }
    543 
    544 
    545 void Assembler::rep_stos() {
    546   EnsureSpace ensure_space(this);
    547   EMIT(0xF3);
    548   EMIT(0xAB);
    549 }
    550 
    551 
    552 void Assembler::stos() {
    553   EnsureSpace ensure_space(this);
    554   EMIT(0xAB);
    555 }
    556 
    557 
    558 void Assembler::xchg(Register dst, Register src) {
    559   EnsureSpace ensure_space(this);
    560   if (src.is(eax) || dst.is(eax)) {  // Single-byte encoding.
    561     EMIT(0x90 | (src.is(eax) ? dst.code() : src.code()));
    562   } else {
    563     EMIT(0x87);
    564     EMIT(0xC0 | src.code() << 3 | dst.code());
    565   }
    566 }
    567 
    568 
    569 void Assembler::adc(Register dst, int32_t imm32) {
    570   EnsureSpace ensure_space(this);
    571   emit_arith(2, Operand(dst), Immediate(imm32));
    572 }
    573 
    574 
    575 void Assembler::adc(Register dst, const Operand& src) {
    576   EnsureSpace ensure_space(this);
    577   EMIT(0x13);
    578   emit_operand(dst, src);
    579 }
    580 
    581 
    582 void Assembler::add(Register dst, const Operand& src) {
    583   EnsureSpace ensure_space(this);
    584   EMIT(0x03);
    585   emit_operand(dst, src);
    586 }
    587 
    588 
    589 void Assembler::add(const Operand& dst, Register src) {
    590   EnsureSpace ensure_space(this);
    591   EMIT(0x01);
    592   emit_operand(src, dst);
    593 }
    594 
    595 
    596 void Assembler::add(const Operand& dst, const Immediate& x) {
    597   ASSERT(reloc_info_writer.last_pc() != NULL);
    598   EnsureSpace ensure_space(this);
    599   emit_arith(0, dst, x);
    600 }
    601 
    602 
    603 void Assembler::and_(Register dst, int32_t imm32) {
    604   and_(dst, Immediate(imm32));
    605 }
    606 
    607 
    608 void Assembler::and_(Register dst, const Immediate& x) {
    609   EnsureSpace ensure_space(this);
    610   emit_arith(4, Operand(dst), x);
    611 }
    612 
    613 
    614 void Assembler::and_(Register dst, const Operand& src) {
    615   EnsureSpace ensure_space(this);
    616   EMIT(0x23);
    617   emit_operand(dst, src);
    618 }
    619 
    620 
    621 void Assembler::and_(const Operand& dst, const Immediate& x) {
    622   EnsureSpace ensure_space(this);
    623   emit_arith(4, dst, x);
    624 }
    625 
    626 
    627 void Assembler::and_(const Operand& dst, Register src) {
    628   EnsureSpace ensure_space(this);
    629   EMIT(0x21);
    630   emit_operand(src, dst);
    631 }
    632 
    633 
    634 void Assembler::cmpb(const Operand& op, int8_t imm8) {
    635   EnsureSpace ensure_space(this);
    636   if (op.is_reg(eax)) {
    637     EMIT(0x3C);
    638   } else {
    639     EMIT(0x80);
    640     emit_operand(edi, op);  // edi == 7
    641   }
    642   EMIT(imm8);
    643 }
    644 
    645 
    646 void Assembler::cmpb(const Operand& op, Register reg) {
    647   CHECK(reg.is_byte_register());
    648   EnsureSpace ensure_space(this);
    649   EMIT(0x38);
    650   emit_operand(reg, op);
    651 }
    652 
    653 
    654 void Assembler::cmpb(Register reg, const Operand& op) {
    655   CHECK(reg.is_byte_register());
    656   EnsureSpace ensure_space(this);
    657   EMIT(0x3A);
    658   emit_operand(reg, op);
    659 }
    660 
    661 
    662 void Assembler::cmpw(const Operand& op, Immediate imm16) {
    663   ASSERT(imm16.is_int16());
    664   EnsureSpace ensure_space(this);
    665   EMIT(0x66);
    666   EMIT(0x81);
    667   emit_operand(edi, op);
    668   emit_w(imm16);
    669 }
    670 
    671 
    672 void Assembler::cmp(Register reg, int32_t imm32) {
    673   EnsureSpace ensure_space(this);
    674   emit_arith(7, Operand(reg), Immediate(imm32));
    675 }
    676 
    677 
    678 void Assembler::cmp(Register reg, Handle<Object> handle) {
    679   EnsureSpace ensure_space(this);
    680   emit_arith(7, Operand(reg), Immediate(handle));
    681 }
    682 
    683 
    684 void Assembler::cmp(Register reg, const Operand& op) {
    685   EnsureSpace ensure_space(this);
    686   EMIT(0x3B);
    687   emit_operand(reg, op);
    688 }
    689 
    690 
    691 void Assembler::cmp(const Operand& op, const Immediate& imm) {
    692   EnsureSpace ensure_space(this);
    693   emit_arith(7, op, imm);
    694 }
    695 
    696 
    697 void Assembler::cmp(const Operand& op, Handle<Object> handle) {
    698   EnsureSpace ensure_space(this);
    699   emit_arith(7, op, Immediate(handle));
    700 }
    701 
    702 
    703 void Assembler::cmpb_al(const Operand& op) {
    704   EnsureSpace ensure_space(this);
    705   EMIT(0x38);  // CMP r/m8, r8
    706   emit_operand(eax, op);  // eax has same code as register al.
    707 }
    708 
    709 
    710 void Assembler::cmpw_ax(const Operand& op) {
    711   EnsureSpace ensure_space(this);
    712   EMIT(0x66);
    713   EMIT(0x39);  // CMP r/m16, r16
    714   emit_operand(eax, op);  // eax has same code as register ax.
    715 }
    716 
    717 
    718 void Assembler::dec_b(Register dst) {
    719   CHECK(dst.is_byte_register());
    720   EnsureSpace ensure_space(this);
    721   EMIT(0xFE);
    722   EMIT(0xC8 | dst.code());
    723 }
    724 
    725 
    726 void Assembler::dec_b(const Operand& dst) {
    727   EnsureSpace ensure_space(this);
    728   EMIT(0xFE);
    729   emit_operand(ecx, dst);
    730 }
    731 
    732 
    733 void Assembler::dec(Register dst) {
    734   EnsureSpace ensure_space(this);
    735   EMIT(0x48 | dst.code());
    736 }
    737 
    738 
    739 void Assembler::dec(const Operand& dst) {
    740   EnsureSpace ensure_space(this);
    741   EMIT(0xFF);
    742   emit_operand(ecx, dst);
    743 }
    744 
    745 
    746 void Assembler::cdq() {
    747   EnsureSpace ensure_space(this);
    748   EMIT(0x99);
    749 }
    750 
    751 
    752 void Assembler::idiv(Register src) {
    753   EnsureSpace ensure_space(this);
    754   EMIT(0xF7);
    755   EMIT(0xF8 | src.code());
    756 }
    757 
    758 
    759 void Assembler::imul(Register reg) {
    760   EnsureSpace ensure_space(this);
    761   EMIT(0xF7);
    762   EMIT(0xE8 | reg.code());
    763 }
    764 
    765 
    766 void Assembler::imul(Register dst, const Operand& src) {
    767   EnsureSpace ensure_space(this);
    768   EMIT(0x0F);
    769   EMIT(0xAF);
    770   emit_operand(dst, src);
    771 }
    772 
    773 
    774 void Assembler::imul(Register dst, Register src, int32_t imm32) {
    775   EnsureSpace ensure_space(this);
    776   if (is_int8(imm32)) {
    777     EMIT(0x6B);
    778     EMIT(0xC0 | dst.code() << 3 | src.code());
    779     EMIT(imm32);
    780   } else {
    781     EMIT(0x69);
    782     EMIT(0xC0 | dst.code() << 3 | src.code());
    783     emit(imm32);
    784   }
    785 }
    786 
    787 
    788 void Assembler::inc(Register dst) {
    789   EnsureSpace ensure_space(this);
    790   EMIT(0x40 | dst.code());
    791 }
    792 
    793 
    794 void Assembler::inc(const Operand& dst) {
    795   EnsureSpace ensure_space(this);
    796   EMIT(0xFF);
    797   emit_operand(eax, dst);
    798 }
    799 
    800 
    801 void Assembler::lea(Register dst, const Operand& src) {
    802   EnsureSpace ensure_space(this);
    803   EMIT(0x8D);
    804   emit_operand(dst, src);
    805 }
    806 
    807 
    808 void Assembler::mul(Register src) {
    809   EnsureSpace ensure_space(this);
    810   EMIT(0xF7);
    811   EMIT(0xE0 | src.code());
    812 }
    813 
    814 
    815 void Assembler::neg(Register dst) {
    816   EnsureSpace ensure_space(this);
    817   EMIT(0xF7);
    818   EMIT(0xD8 | dst.code());
    819 }
    820 
    821 
    822 void Assembler::not_(Register dst) {
    823   EnsureSpace ensure_space(this);
    824   EMIT(0xF7);
    825   EMIT(0xD0 | dst.code());
    826 }
    827 
    828 
    829 void Assembler::or_(Register dst, int32_t imm32) {
    830   EnsureSpace ensure_space(this);
    831   emit_arith(1, Operand(dst), Immediate(imm32));
    832 }
    833 
    834 
    835 void Assembler::or_(Register dst, const Operand& src) {
    836   EnsureSpace ensure_space(this);
    837   EMIT(0x0B);
    838   emit_operand(dst, src);
    839 }
    840 
    841 
    842 void Assembler::or_(const Operand& dst, const Immediate& x) {
    843   EnsureSpace ensure_space(this);
    844   emit_arith(1, dst, x);
    845 }
    846 
    847 
    848 void Assembler::or_(const Operand& dst, Register src) {
    849   EnsureSpace ensure_space(this);
    850   EMIT(0x09);
    851   emit_operand(src, dst);
    852 }
    853 
    854 
    855 void Assembler::rcl(Register dst, uint8_t imm8) {
    856   EnsureSpace ensure_space(this);
    857   ASSERT(is_uint5(imm8));  // illegal shift count
    858   if (imm8 == 1) {
    859     EMIT(0xD1);
    860     EMIT(0xD0 | dst.code());
    861   } else {
    862     EMIT(0xC1);
    863     EMIT(0xD0 | dst.code());
    864     EMIT(imm8);
    865   }
    866 }
    867 
    868 
    869 void Assembler::rcr(Register dst, uint8_t imm8) {
    870   EnsureSpace ensure_space(this);
    871   ASSERT(is_uint5(imm8));  // illegal shift count
    872   if (imm8 == 1) {
    873     EMIT(0xD1);
    874     EMIT(0xD8 | dst.code());
    875   } else {
    876     EMIT(0xC1);
    877     EMIT(0xD8 | dst.code());
    878     EMIT(imm8);
    879   }
    880 }
    881 
    882 
    883 void Assembler::ror(Register dst, uint8_t imm8) {
    884   EnsureSpace ensure_space(this);
    885   ASSERT(is_uint5(imm8));  // illegal shift count
    886   if (imm8 == 1) {
    887     EMIT(0xD1);
    888     EMIT(0xC8 | dst.code());
    889   } else {
    890     EMIT(0xC1);
    891     EMIT(0xC8 | dst.code());
    892     EMIT(imm8);
    893   }
    894 }
    895 
    896 
    897 void Assembler::ror_cl(Register dst) {
    898   EnsureSpace ensure_space(this);
    899   EMIT(0xD3);
    900   EMIT(0xC8 | dst.code());
    901 }
    902 
    903 
    904 void Assembler::sar(Register dst, uint8_t imm8) {
    905   EnsureSpace ensure_space(this);
    906   ASSERT(is_uint5(imm8));  // illegal shift count
    907   if (imm8 == 1) {
    908     EMIT(0xD1);
    909     EMIT(0xF8 | dst.code());
    910   } else {
    911     EMIT(0xC1);
    912     EMIT(0xF8 | dst.code());
    913     EMIT(imm8);
    914   }
    915 }
    916 
    917 
    918 void Assembler::sar_cl(Register dst) {
    919   EnsureSpace ensure_space(this);
    920   EMIT(0xD3);
    921   EMIT(0xF8 | dst.code());
    922 }
    923 
    924 
    925 void Assembler::sbb(Register dst, const Operand& src) {
    926   EnsureSpace ensure_space(this);
    927   EMIT(0x1B);
    928   emit_operand(dst, src);
    929 }
    930 
    931 
    932 void Assembler::shld(Register dst, const Operand& src) {
    933   EnsureSpace ensure_space(this);
    934   EMIT(0x0F);
    935   EMIT(0xA5);
    936   emit_operand(dst, src);
    937 }
    938 
    939 
    940 void Assembler::shl(Register dst, uint8_t imm8) {
    941   EnsureSpace ensure_space(this);
    942   ASSERT(is_uint5(imm8));  // illegal shift count
    943   if (imm8 == 1) {
    944     EMIT(0xD1);
    945     EMIT(0xE0 | dst.code());
    946   } else {
    947     EMIT(0xC1);
    948     EMIT(0xE0 | dst.code());
    949     EMIT(imm8);
    950   }
    951 }
    952 
    953 
    954 void Assembler::shl_cl(Register dst) {
    955   EnsureSpace ensure_space(this);
    956   EMIT(0xD3);
    957   EMIT(0xE0 | dst.code());
    958 }
    959 
    960 
    961 void Assembler::shrd(Register dst, const Operand& src) {
    962   EnsureSpace ensure_space(this);
    963   EMIT(0x0F);
    964   EMIT(0xAD);
    965   emit_operand(dst, src);
    966 }
    967 
    968 
    969 void Assembler::shr(Register dst, uint8_t imm8) {
    970   EnsureSpace ensure_space(this);
    971   ASSERT(is_uint5(imm8));  // illegal shift count
    972   if (imm8 == 1) {
    973     EMIT(0xD1);
    974     EMIT(0xE8 | dst.code());
    975   } else {
    976     EMIT(0xC1);
    977     EMIT(0xE8 | dst.code());
    978     EMIT(imm8);
    979   }
    980 }
    981 
    982 
    983 void Assembler::shr_cl(Register dst) {
    984   EnsureSpace ensure_space(this);
    985   EMIT(0xD3);
    986   EMIT(0xE8 | dst.code());
    987 }
    988 
    989 
    990 void Assembler::sub(const Operand& dst, const Immediate& x) {
    991   EnsureSpace ensure_space(this);
    992   emit_arith(5, dst, x);
    993 }
    994 
    995 
    996 void Assembler::sub(Register dst, const Operand& src) {
    997   EnsureSpace ensure_space(this);
    998   EMIT(0x2B);
    999   emit_operand(dst, src);
   1000 }
   1001 
   1002 
   1003 void Assembler::sub(const Operand& dst, Register src) {
   1004   EnsureSpace ensure_space(this);
   1005   EMIT(0x29);
   1006   emit_operand(src, dst);
   1007 }
   1008 
   1009 
   1010 void Assembler::test(Register reg, const Immediate& imm) {
   1011   if (RelocInfo::IsNone(imm.rmode_) && is_uint8(imm.x_)) {
   1012     test_b(reg, imm.x_);
   1013     return;
   1014   }
   1015 
   1016   EnsureSpace ensure_space(this);
   1017   // This is not using emit_arith because test doesn't support
   1018   // sign-extension of 8-bit operands.
   1019   if (reg.is(eax)) {
   1020     EMIT(0xA9);
   1021   } else {
   1022     EMIT(0xF7);
   1023     EMIT(0xC0 | reg.code());
   1024   }
   1025   emit(imm);
   1026 }
   1027 
   1028 
   1029 void Assembler::test(Register reg, const Operand& op) {
   1030   EnsureSpace ensure_space(this);
   1031   EMIT(0x85);
   1032   emit_operand(reg, op);
   1033 }
   1034 
   1035 
   1036 void Assembler::test_b(Register reg, const Operand& op) {
   1037   CHECK(reg.is_byte_register());
   1038   EnsureSpace ensure_space(this);
   1039   EMIT(0x84);
   1040   emit_operand(reg, op);
   1041 }
   1042 
   1043 
   1044 void Assembler::test(const Operand& op, const Immediate& imm) {
   1045   if (op.is_reg_only()) {
   1046     test(op.reg(), imm);
   1047     return;
   1048   }
   1049   if (RelocInfo::IsNone(imm.rmode_) && is_uint8(imm.x_)) {
   1050     return test_b(op, imm.x_);
   1051   }
   1052   EnsureSpace ensure_space(this);
   1053   EMIT(0xF7);
   1054   emit_operand(eax, op);
   1055   emit(imm);
   1056 }
   1057 
   1058 
   1059 void Assembler::test_b(Register reg, uint8_t imm8) {
   1060   EnsureSpace ensure_space(this);
   1061   // Only use test against byte for registers that have a byte
   1062   // variant: eax, ebx, ecx, and edx.
   1063   if (reg.is(eax)) {
   1064     EMIT(0xA8);
   1065     EMIT(imm8);
   1066   } else if (reg.is_byte_register()) {
   1067     emit_arith_b(0xF6, 0xC0, reg, imm8);
   1068   } else {
   1069     EMIT(0xF7);
   1070     EMIT(0xC0 | reg.code());
   1071     emit(imm8);
   1072   }
   1073 }
   1074 
   1075 
   1076 void Assembler::test_b(const Operand& op, uint8_t imm8) {
   1077   if (op.is_reg_only()) {
   1078     test_b(op.reg(), imm8);
   1079     return;
   1080   }
   1081   EnsureSpace ensure_space(this);
   1082   EMIT(0xF6);
   1083   emit_operand(eax, op);
   1084   EMIT(imm8);
   1085 }
   1086 
   1087 
   1088 void Assembler::xor_(Register dst, int32_t imm32) {
   1089   EnsureSpace ensure_space(this);
   1090   emit_arith(6, Operand(dst), Immediate(imm32));
   1091 }
   1092 
   1093 
   1094 void Assembler::xor_(Register dst, const Operand& src) {
   1095   EnsureSpace ensure_space(this);
   1096   EMIT(0x33);
   1097   emit_operand(dst, src);
   1098 }
   1099 
   1100 
   1101 void Assembler::xor_(const Operand& dst, Register src) {
   1102   EnsureSpace ensure_space(this);
   1103   EMIT(0x31);
   1104   emit_operand(src, dst);
   1105 }
   1106 
   1107 
   1108 void Assembler::xor_(const Operand& dst, const Immediate& x) {
   1109   EnsureSpace ensure_space(this);
   1110   emit_arith(6, dst, x);
   1111 }
   1112 
   1113 
   1114 void Assembler::bt(const Operand& dst, Register src) {
   1115   EnsureSpace ensure_space(this);
   1116   EMIT(0x0F);
   1117   EMIT(0xA3);
   1118   emit_operand(src, dst);
   1119 }
   1120 
   1121 
   1122 void Assembler::bts(const Operand& dst, Register src) {
   1123   EnsureSpace ensure_space(this);
   1124   EMIT(0x0F);
   1125   EMIT(0xAB);
   1126   emit_operand(src, dst);
   1127 }
   1128 
   1129 
   1130 void Assembler::bsr(Register dst, const Operand& src) {
   1131   EnsureSpace ensure_space(this);
   1132   EMIT(0x0F);
   1133   EMIT(0xBD);
   1134   emit_operand(dst, src);
   1135 }
   1136 
   1137 
   1138 void Assembler::hlt() {
   1139   EnsureSpace ensure_space(this);
   1140   EMIT(0xF4);
   1141 }
   1142 
   1143 
   1144 void Assembler::int3() {
   1145   EnsureSpace ensure_space(this);
   1146   EMIT(0xCC);
   1147 }
   1148 
   1149 
   1150 void Assembler::nop() {
   1151   EnsureSpace ensure_space(this);
   1152   EMIT(0x90);
   1153 }
   1154 
   1155 
   1156 void Assembler::ret(int imm16) {
   1157   EnsureSpace ensure_space(this);
   1158   ASSERT(is_uint16(imm16));
   1159   if (imm16 == 0) {
   1160     EMIT(0xC3);
   1161   } else {
   1162     EMIT(0xC2);
   1163     EMIT(imm16 & 0xFF);
   1164     EMIT((imm16 >> 8) & 0xFF);
   1165   }
   1166 }
   1167 
   1168 
   1169 // Labels refer to positions in the (to be) generated code.
   1170 // There are bound, linked, and unused labels.
   1171 //
   1172 // Bound labels refer to known positions in the already
   1173 // generated code. pos() is the position the label refers to.
   1174 //
   1175 // Linked labels refer to unknown positions in the code
   1176 // to be generated; pos() is the position of the 32bit
   1177 // Displacement of the last instruction using the label.
   1178 
   1179 
   1180 void Assembler::print(Label* L) {
   1181   if (L->is_unused()) {
   1182     PrintF("unused label\n");
   1183   } else if (L->is_bound()) {
   1184     PrintF("bound label to %d\n", L->pos());
   1185   } else if (L->is_linked()) {
   1186     Label l = *L;
   1187     PrintF("unbound label");
   1188     while (l.is_linked()) {
   1189       Displacement disp = disp_at(&l);
   1190       PrintF("@ %d ", l.pos());
   1191       disp.print();
   1192       PrintF("\n");
   1193       disp.next(&l);
   1194     }
   1195   } else {
   1196     PrintF("label in inconsistent state (pos = %d)\n", L->pos_);
   1197   }
   1198 }
   1199 
   1200 
   1201 void Assembler::bind_to(Label* L, int pos) {
   1202   EnsureSpace ensure_space(this);
   1203   ASSERT(0 <= pos && pos <= pc_offset());  // must have a valid binding position
   1204   while (L->is_linked()) {
   1205     Displacement disp = disp_at(L);
   1206     int fixup_pos = L->pos();
   1207     if (disp.type() == Displacement::CODE_RELATIVE) {
   1208       // Relative to Code* heap object pointer.
   1209       long_at_put(fixup_pos, pos + Code::kHeaderSize - kHeapObjectTag);
   1210     } else {
   1211       if (disp.type() == Displacement::UNCONDITIONAL_JUMP) {
   1212         ASSERT(byte_at(fixup_pos - 1) == 0xE9);  // jmp expected
   1213       }
   1214       // Relative address, relative to point after address.
   1215       int imm32 = pos - (fixup_pos + sizeof(int32_t));
   1216       long_at_put(fixup_pos, imm32);
   1217     }
   1218     disp.next(L);
   1219   }
   1220   while (L->is_near_linked()) {
   1221     int fixup_pos = L->near_link_pos();
   1222     int offset_to_next =
   1223         static_cast<int>(*reinterpret_cast<int8_t*>(addr_at(fixup_pos)));
   1224     ASSERT(offset_to_next <= 0);
   1225     // Relative address, relative to point after address.
   1226     int disp = pos - fixup_pos - sizeof(int8_t);
   1227     CHECK(0 <= disp && disp <= 127);
   1228     set_byte_at(fixup_pos, disp);
   1229     if (offset_to_next < 0) {
   1230       L->link_to(fixup_pos + offset_to_next, Label::kNear);
   1231     } else {
   1232       L->UnuseNear();
   1233     }
   1234   }
   1235   L->bind_to(pos);
   1236 }
   1237 
   1238 
   1239 void Assembler::bind(Label* L) {
   1240   EnsureSpace ensure_space(this);
   1241   ASSERT(!L->is_bound());  // label can only be bound once
   1242   bind_to(L, pc_offset());
   1243 }
   1244 
   1245 
   1246 void Assembler::call(Label* L) {
   1247   positions_recorder()->WriteRecordedPositions();
   1248   EnsureSpace ensure_space(this);
   1249   if (L->is_bound()) {
   1250     const int long_size = 5;
   1251     int offs = L->pos() - pc_offset();
   1252     ASSERT(offs <= 0);
   1253     // 1110 1000 #32-bit disp.
   1254     EMIT(0xE8);
   1255     emit(offs - long_size);
   1256   } else {
   1257     // 1110 1000 #32-bit disp.
   1258     EMIT(0xE8);
   1259     emit_disp(L, Displacement::OTHER);
   1260   }
   1261 }
   1262 
   1263 
   1264 void Assembler::call(byte* entry, RelocInfo::Mode rmode) {
   1265   positions_recorder()->WriteRecordedPositions();
   1266   EnsureSpace ensure_space(this);
   1267   ASSERT(!RelocInfo::IsCodeTarget(rmode));
   1268   EMIT(0xE8);
   1269   if (RelocInfo::IsRuntimeEntry(rmode)) {
   1270     emit(reinterpret_cast<uint32_t>(entry), rmode);
   1271   } else {
   1272     emit(entry - (pc_ + sizeof(int32_t)), rmode);
   1273   }
   1274 }
   1275 
   1276 
   1277 int Assembler::CallSize(const Operand& adr) {
   1278   // Call size is 1 (opcode) + adr.len_ (operand).
   1279   return 1 + adr.len_;
   1280 }
   1281 
   1282 
   1283 void Assembler::call(const Operand& adr) {
   1284   positions_recorder()->WriteRecordedPositions();
   1285   EnsureSpace ensure_space(this);
   1286   EMIT(0xFF);
   1287   emit_operand(edx, adr);
   1288 }
   1289 
   1290 
   1291 int Assembler::CallSize(Handle<Code> code, RelocInfo::Mode rmode) {
   1292   return 1 /* EMIT */ + sizeof(uint32_t) /* emit */;
   1293 }
   1294 
   1295 
   1296 void Assembler::call(Handle<Code> code,
   1297                      RelocInfo::Mode rmode,
   1298                      TypeFeedbackId ast_id) {
   1299   positions_recorder()->WriteRecordedPositions();
   1300   EnsureSpace ensure_space(this);
   1301   ASSERT(RelocInfo::IsCodeTarget(rmode)
   1302       || rmode == RelocInfo::CODE_AGE_SEQUENCE);
   1303   EMIT(0xE8);
   1304   emit(code, rmode, ast_id);
   1305 }
   1306 
   1307 
   1308 void Assembler::jmp(Label* L, Label::Distance distance) {
   1309   EnsureSpace ensure_space(this);
   1310   if (L->is_bound()) {
   1311     const int short_size = 2;
   1312     const int long_size  = 5;
   1313     int offs = L->pos() - pc_offset();
   1314     ASSERT(offs <= 0);
   1315     if (is_int8(offs - short_size)) {
   1316       // 1110 1011 #8-bit disp.
   1317       EMIT(0xEB);
   1318       EMIT((offs - short_size) & 0xFF);
   1319     } else {
   1320       // 1110 1001 #32-bit disp.
   1321       EMIT(0xE9);
   1322       emit(offs - long_size);
   1323     }
   1324   } else if (distance == Label::kNear) {
   1325     EMIT(0xEB);
   1326     emit_near_disp(L);
   1327   } else {
   1328     // 1110 1001 #32-bit disp.
   1329     EMIT(0xE9);
   1330     emit_disp(L, Displacement::UNCONDITIONAL_JUMP);
   1331   }
   1332 }
   1333 
   1334 
   1335 void Assembler::jmp(byte* entry, RelocInfo::Mode rmode) {
   1336   EnsureSpace ensure_space(this);
   1337   ASSERT(!RelocInfo::IsCodeTarget(rmode));
   1338   EMIT(0xE9);
   1339   if (RelocInfo::IsRuntimeEntry(rmode)) {
   1340     emit(reinterpret_cast<uint32_t>(entry), rmode);
   1341   } else {
   1342     emit(entry - (pc_ + sizeof(int32_t)), rmode);
   1343   }
   1344 }
   1345 
   1346 
   1347 void Assembler::jmp(const Operand& adr) {
   1348   EnsureSpace ensure_space(this);
   1349   EMIT(0xFF);
   1350   emit_operand(esp, adr);
   1351 }
   1352 
   1353 
   1354 void Assembler::jmp(Handle<Code> code, RelocInfo::Mode rmode) {
   1355   EnsureSpace ensure_space(this);
   1356   ASSERT(RelocInfo::IsCodeTarget(rmode));
   1357   EMIT(0xE9);
   1358   emit(code, rmode);
   1359 }
   1360 
   1361 
   1362 void Assembler::j(Condition cc, Label* L, Label::Distance distance) {
   1363   EnsureSpace ensure_space(this);
   1364   ASSERT(0 <= cc && static_cast<int>(cc) < 16);
   1365   if (L->is_bound()) {
   1366     const int short_size = 2;
   1367     const int long_size  = 6;
   1368     int offs = L->pos() - pc_offset();
   1369     ASSERT(offs <= 0);
   1370     if (is_int8(offs - short_size)) {
   1371       // 0111 tttn #8-bit disp
   1372       EMIT(0x70 | cc);
   1373       EMIT((offs - short_size) & 0xFF);
   1374     } else {
   1375       // 0000 1111 1000 tttn #32-bit disp
   1376       EMIT(0x0F);
   1377       EMIT(0x80 | cc);
   1378       emit(offs - long_size);
   1379     }
   1380   } else if (distance == Label::kNear) {
   1381     EMIT(0x70 | cc);
   1382     emit_near_disp(L);
   1383   } else {
   1384     // 0000 1111 1000 tttn #32-bit disp
   1385     // Note: could eliminate cond. jumps to this jump if condition
   1386     //       is the same however, seems to be rather unlikely case.
   1387     EMIT(0x0F);
   1388     EMIT(0x80 | cc);
   1389     emit_disp(L, Displacement::OTHER);
   1390   }
   1391 }
   1392 
   1393 
   1394 void Assembler::j(Condition cc, byte* entry, RelocInfo::Mode rmode) {
   1395   EnsureSpace ensure_space(this);
   1396   ASSERT((0 <= cc) && (static_cast<int>(cc) < 16));
   1397   // 0000 1111 1000 tttn #32-bit disp.
   1398   EMIT(0x0F);
   1399   EMIT(0x80 | cc);
   1400   if (RelocInfo::IsRuntimeEntry(rmode)) {
   1401     emit(reinterpret_cast<uint32_t>(entry), rmode);
   1402   } else {
   1403     emit(entry - (pc_ + sizeof(int32_t)), rmode);
   1404   }
   1405 }
   1406 
   1407 
   1408 void Assembler::j(Condition cc, Handle<Code> code) {
   1409   EnsureSpace ensure_space(this);
   1410   // 0000 1111 1000 tttn #32-bit disp
   1411   EMIT(0x0F);
   1412   EMIT(0x80 | cc);
   1413   emit(code, RelocInfo::CODE_TARGET);
   1414 }
   1415 
   1416 
   1417 // FPU instructions.
   1418 
   1419 void Assembler::fld(int i) {
   1420   EnsureSpace ensure_space(this);
   1421   emit_farith(0xD9, 0xC0, i);
   1422 }
   1423 
   1424 
   1425 void Assembler::fstp(int i) {
   1426   EnsureSpace ensure_space(this);
   1427   emit_farith(0xDD, 0xD8, i);
   1428 }
   1429 
   1430 
   1431 void Assembler::fld1() {
   1432   EnsureSpace ensure_space(this);
   1433   EMIT(0xD9);
   1434   EMIT(0xE8);
   1435 }
   1436 
   1437 
   1438 void Assembler::fldpi() {
   1439   EnsureSpace ensure_space(this);
   1440   EMIT(0xD9);
   1441   EMIT(0xEB);
   1442 }
   1443 
   1444 
   1445 void Assembler::fldz() {
   1446   EnsureSpace ensure_space(this);
   1447   EMIT(0xD9);
   1448   EMIT(0xEE);
   1449 }
   1450 
   1451 
   1452 void Assembler::fldln2() {
   1453   EnsureSpace ensure_space(this);
   1454   EMIT(0xD9);
   1455   EMIT(0xED);
   1456 }
   1457 
   1458 
   1459 void Assembler::fld_s(const Operand& adr) {
   1460   EnsureSpace ensure_space(this);
   1461   EMIT(0xD9);
   1462   emit_operand(eax, adr);
   1463 }
   1464 
   1465 
   1466 void Assembler::fld_d(const Operand& adr) {
   1467   EnsureSpace ensure_space(this);
   1468   EMIT(0xDD);
   1469   emit_operand(eax, adr);
   1470 }
   1471 
   1472 
   1473 void Assembler::fstp_s(const Operand& adr) {
   1474   EnsureSpace ensure_space(this);
   1475   EMIT(0xD9);
   1476   emit_operand(ebx, adr);
   1477 }
   1478 
   1479 
   1480 void Assembler::fst_s(const Operand& adr) {
   1481   EnsureSpace ensure_space(this);
   1482   EMIT(0xD9);
   1483   emit_operand(edx, adr);
   1484 }
   1485 
   1486 
   1487 void Assembler::fstp_d(const Operand& adr) {
   1488   EnsureSpace ensure_space(this);
   1489   EMIT(0xDD);
   1490   emit_operand(ebx, adr);
   1491 }
   1492 
   1493 
   1494 void Assembler::fst_d(const Operand& adr) {
   1495   EnsureSpace ensure_space(this);
   1496   EMIT(0xDD);
   1497   emit_operand(edx, adr);
   1498 }
   1499 
   1500 
   1501 void Assembler::fild_s(const Operand& adr) {
   1502   EnsureSpace ensure_space(this);
   1503   EMIT(0xDB);
   1504   emit_operand(eax, adr);
   1505 }
   1506 
   1507 
   1508 void Assembler::fild_d(const Operand& adr) {
   1509   EnsureSpace ensure_space(this);
   1510   EMIT(0xDF);
   1511   emit_operand(ebp, adr);
   1512 }
   1513 
   1514 
   1515 void Assembler::fistp_s(const Operand& adr) {
   1516   EnsureSpace ensure_space(this);
   1517   EMIT(0xDB);
   1518   emit_operand(ebx, adr);
   1519 }
   1520 
   1521 
   1522 void Assembler::fisttp_s(const Operand& adr) {
   1523   ASSERT(IsEnabled(SSE3));
   1524   EnsureSpace ensure_space(this);
   1525   EMIT(0xDB);
   1526   emit_operand(ecx, adr);
   1527 }
   1528 
   1529 
   1530 void Assembler::fisttp_d(const Operand& adr) {
   1531   ASSERT(IsEnabled(SSE3));
   1532   EnsureSpace ensure_space(this);
   1533   EMIT(0xDD);
   1534   emit_operand(ecx, adr);
   1535 }
   1536 
   1537 
   1538 void Assembler::fist_s(const Operand& adr) {
   1539   EnsureSpace ensure_space(this);
   1540   EMIT(0xDB);
   1541   emit_operand(edx, adr);
   1542 }
   1543 
   1544 
   1545 void Assembler::fistp_d(const Operand& adr) {
   1546   EnsureSpace ensure_space(this);
   1547   EMIT(0xDF);
   1548   emit_operand(edi, adr);
   1549 }
   1550 
   1551 
   1552 void Assembler::fabs() {
   1553   EnsureSpace ensure_space(this);
   1554   EMIT(0xD9);
   1555   EMIT(0xE1);
   1556 }
   1557 
   1558 
   1559 void Assembler::fchs() {
   1560   EnsureSpace ensure_space(this);
   1561   EMIT(0xD9);
   1562   EMIT(0xE0);
   1563 }
   1564 
   1565 
   1566 void Assembler::fcos() {
   1567   EnsureSpace ensure_space(this);
   1568   EMIT(0xD9);
   1569   EMIT(0xFF);
   1570 }
   1571 
   1572 
   1573 void Assembler::fsin() {
   1574   EnsureSpace ensure_space(this);
   1575   EMIT(0xD9);
   1576   EMIT(0xFE);
   1577 }
   1578 
   1579 
   1580 void Assembler::fptan() {
   1581   EnsureSpace ensure_space(this);
   1582   EMIT(0xD9);
   1583   EMIT(0xF2);
   1584 }
   1585 
   1586 
   1587 void Assembler::fyl2x() {
   1588   EnsureSpace ensure_space(this);
   1589   EMIT(0xD9);
   1590   EMIT(0xF1);
   1591 }
   1592 
   1593 
   1594 void Assembler::f2xm1() {
   1595   EnsureSpace ensure_space(this);
   1596   EMIT(0xD9);
   1597   EMIT(0xF0);
   1598 }
   1599 
   1600 
   1601 void Assembler::fscale() {
   1602   EnsureSpace ensure_space(this);
   1603   EMIT(0xD9);
   1604   EMIT(0xFD);
   1605 }
   1606 
   1607 
   1608 void Assembler::fninit() {
   1609   EnsureSpace ensure_space(this);
   1610   EMIT(0xDB);
   1611   EMIT(0xE3);
   1612 }
   1613 
   1614 
   1615 void Assembler::fadd(int i) {
   1616   EnsureSpace ensure_space(this);
   1617   emit_farith(0xDC, 0xC0, i);
   1618 }
   1619 
   1620 
   1621 void Assembler::fadd_i(int i) {
   1622   EnsureSpace ensure_space(this);
   1623   emit_farith(0xD8, 0xC0, i);
   1624 }
   1625 
   1626 
   1627 void Assembler::fsub(int i) {
   1628   EnsureSpace ensure_space(this);
   1629   emit_farith(0xDC, 0xE8, i);
   1630 }
   1631 
   1632 
   1633 void Assembler::fsub_i(int i) {
   1634   EnsureSpace ensure_space(this);
   1635   emit_farith(0xD8, 0xE0, i);
   1636 }
   1637 
   1638 
   1639 void Assembler::fisub_s(const Operand& adr) {
   1640   EnsureSpace ensure_space(this);
   1641   EMIT(0xDA);
   1642   emit_operand(esp, adr);
   1643 }
   1644 
   1645 
   1646 void Assembler::fmul_i(int i) {
   1647   EnsureSpace ensure_space(this);
   1648   emit_farith(0xD8, 0xC8, i);
   1649 }
   1650 
   1651 
   1652 void Assembler::fmul(int i) {
   1653   EnsureSpace ensure_space(this);
   1654   emit_farith(0xDC, 0xC8, i);
   1655 }
   1656 
   1657 
   1658 void Assembler::fdiv(int i) {
   1659   EnsureSpace ensure_space(this);
   1660   emit_farith(0xDC, 0xF8, i);
   1661 }
   1662 
   1663 
   1664 void Assembler::fdiv_i(int i) {
   1665   EnsureSpace ensure_space(this);
   1666   emit_farith(0xD8, 0xF0, i);
   1667 }
   1668 
   1669 
   1670 void Assembler::faddp(int i) {
   1671   EnsureSpace ensure_space(this);
   1672   emit_farith(0xDE, 0xC0, i);
   1673 }
   1674 
   1675 
   1676 void Assembler::fsubp(int i) {
   1677   EnsureSpace ensure_space(this);
   1678   emit_farith(0xDE, 0xE8, i);
   1679 }
   1680 
   1681 
   1682 void Assembler::fsubrp(int i) {
   1683   EnsureSpace ensure_space(this);
   1684   emit_farith(0xDE, 0xE0, i);
   1685 }
   1686 
   1687 
   1688 void Assembler::fmulp(int i) {
   1689   EnsureSpace ensure_space(this);
   1690   emit_farith(0xDE, 0xC8, i);
   1691 }
   1692 
   1693 
   1694 void Assembler::fdivp(int i) {
   1695   EnsureSpace ensure_space(this);
   1696   emit_farith(0xDE, 0xF8, i);
   1697 }
   1698 
   1699 
   1700 void Assembler::fprem() {
   1701   EnsureSpace ensure_space(this);
   1702   EMIT(0xD9);
   1703   EMIT(0xF8);
   1704 }
   1705 
   1706 
   1707 void Assembler::fprem1() {
   1708   EnsureSpace ensure_space(this);
   1709   EMIT(0xD9);
   1710   EMIT(0xF5);
   1711 }
   1712 
   1713 
   1714 void Assembler::fxch(int i) {
   1715   EnsureSpace ensure_space(this);
   1716   emit_farith(0xD9, 0xC8, i);
   1717 }
   1718 
   1719 
   1720 void Assembler::fincstp() {
   1721   EnsureSpace ensure_space(this);
   1722   EMIT(0xD9);
   1723   EMIT(0xF7);
   1724 }
   1725 
   1726 
   1727 void Assembler::ffree(int i) {
   1728   EnsureSpace ensure_space(this);
   1729   emit_farith(0xDD, 0xC0, i);
   1730 }
   1731 
   1732 
   1733 void Assembler::ftst() {
   1734   EnsureSpace ensure_space(this);
   1735   EMIT(0xD9);
   1736   EMIT(0xE4);
   1737 }
   1738 
   1739 
   1740 void Assembler::fucomp(int i) {
   1741   EnsureSpace ensure_space(this);
   1742   emit_farith(0xDD, 0xE8, i);
   1743 }
   1744 
   1745 
   1746 void Assembler::fucompp() {
   1747   EnsureSpace ensure_space(this);
   1748   EMIT(0xDA);
   1749   EMIT(0xE9);
   1750 }
   1751 
   1752 
   1753 void Assembler::fucomi(int i) {
   1754   EnsureSpace ensure_space(this);
   1755   EMIT(0xDB);
   1756   EMIT(0xE8 + i);
   1757 }
   1758 
   1759 
   1760 void Assembler::fucomip() {
   1761   EnsureSpace ensure_space(this);
   1762   EMIT(0xDF);
   1763   EMIT(0xE9);
   1764 }
   1765 
   1766 
   1767 void Assembler::fcompp() {
   1768   EnsureSpace ensure_space(this);
   1769   EMIT(0xDE);
   1770   EMIT(0xD9);
   1771 }
   1772 
   1773 
   1774 void Assembler::fnstsw_ax() {
   1775   EnsureSpace ensure_space(this);
   1776   EMIT(0xDF);
   1777   EMIT(0xE0);
   1778 }
   1779 
   1780 
   1781 void Assembler::fwait() {
   1782   EnsureSpace ensure_space(this);
   1783   EMIT(0x9B);
   1784 }
   1785 
   1786 
   1787 void Assembler::frndint() {
   1788   EnsureSpace ensure_space(this);
   1789   EMIT(0xD9);
   1790   EMIT(0xFC);
   1791 }
   1792 
   1793 
   1794 void Assembler::fnclex() {
   1795   EnsureSpace ensure_space(this);
   1796   EMIT(0xDB);
   1797   EMIT(0xE2);
   1798 }
   1799 
   1800 
   1801 void Assembler::sahf() {
   1802   EnsureSpace ensure_space(this);
   1803   EMIT(0x9E);
   1804 }
   1805 
   1806 
   1807 void Assembler::setcc(Condition cc, Register reg) {
   1808   ASSERT(reg.is_byte_register());
   1809   EnsureSpace ensure_space(this);
   1810   EMIT(0x0F);
   1811   EMIT(0x90 | cc);
   1812   EMIT(0xC0 | reg.code());
   1813 }
   1814 
   1815 
   1816 void Assembler::Print() {
   1817   Disassembler::Decode(isolate(), stdout, buffer_, pc_);
   1818 }
   1819 
   1820 
   1821 void Assembler::RecordJSReturn() {
   1822   positions_recorder()->WriteRecordedPositions();
   1823   EnsureSpace ensure_space(this);
   1824   RecordRelocInfo(RelocInfo::JS_RETURN);
   1825 }
   1826 
   1827 
   1828 void Assembler::RecordDebugBreakSlot() {
   1829   positions_recorder()->WriteRecordedPositions();
   1830   EnsureSpace ensure_space(this);
   1831   RecordRelocInfo(RelocInfo::DEBUG_BREAK_SLOT);
   1832 }
   1833 
   1834 
   1835 void Assembler::RecordComment(const char* msg, bool force) {
   1836   if (FLAG_code_comments || force) {
   1837     EnsureSpace ensure_space(this);
   1838     RecordRelocInfo(RelocInfo::COMMENT, reinterpret_cast<intptr_t>(msg));
   1839   }
   1840 }
   1841 
   1842 
   1843 void Assembler::GrowBuffer() {
   1844   ASSERT(buffer_overflow());
   1845   if (!own_buffer_) FATAL("external code buffer is too small");
   1846 
   1847   // Compute new buffer size.
   1848   CodeDesc desc;  // the new buffer
   1849   if (buffer_size_ < 4*KB) {
   1850     desc.buffer_size = 4*KB;
   1851   } else {
   1852     desc.buffer_size = 2*buffer_size_;
   1853   }
   1854   // Some internal data structures overflow for very large buffers,
   1855   // they must ensure that kMaximalBufferSize is not too large.
   1856   if ((desc.buffer_size > kMaximalBufferSize) ||
   1857       (desc.buffer_size > isolate()->heap()->MaxOldGenerationSize())) {
   1858     V8::FatalProcessOutOfMemory("Assembler::GrowBuffer");
   1859   }
   1860 
   1861   // Set up new buffer.
   1862   desc.buffer = NewArray<byte>(desc.buffer_size);
   1863   desc.instr_size = pc_offset();
   1864   desc.reloc_size = (buffer_ + buffer_size_) - (reloc_info_writer.pos());
   1865 
   1866   // Clear the buffer in debug mode. Use 'int3' instructions to make
   1867   // sure to get into problems if we ever run uninitialized code.
   1868 #ifdef DEBUG
   1869   memset(desc.buffer, 0xCC, desc.buffer_size);
   1870 #endif
   1871 
   1872   // Copy the data.
   1873   int pc_delta = desc.buffer - buffer_;
   1874   int rc_delta = (desc.buffer + desc.buffer_size) - (buffer_ + buffer_size_);
   1875   MemMove(desc.buffer, buffer_, desc.instr_size);
   1876   MemMove(rc_delta + reloc_info_writer.pos(), reloc_info_writer.pos(),
   1877           desc.reloc_size);
   1878 
   1879   // Switch buffers.
   1880   if (isolate()->assembler_spare_buffer() == NULL &&
   1881       buffer_size_ == kMinimalBufferSize) {
   1882     isolate()->set_assembler_spare_buffer(buffer_);
   1883   } else {
   1884     DeleteArray(buffer_);
   1885   }
   1886   buffer_ = desc.buffer;
   1887   buffer_size_ = desc.buffer_size;
   1888   pc_ += pc_delta;
   1889   reloc_info_writer.Reposition(reloc_info_writer.pos() + rc_delta,
   1890                                reloc_info_writer.last_pc() + pc_delta);
   1891 
   1892   // Relocate runtime entries.
   1893   for (RelocIterator it(desc); !it.done(); it.next()) {
   1894     RelocInfo::Mode rmode = it.rinfo()->rmode();
   1895     if (rmode == RelocInfo::INTERNAL_REFERENCE) {
   1896       int32_t* p = reinterpret_cast<int32_t*>(it.rinfo()->pc());
   1897       if (*p != 0) {  // 0 means uninitialized.
   1898         *p += pc_delta;
   1899       }
   1900     }
   1901   }
   1902 
   1903   ASSERT(!buffer_overflow());
   1904 }
   1905 
   1906 
   1907 void Assembler::emit_arith_b(int op1, int op2, Register dst, int imm8) {
   1908   ASSERT(is_uint8(op1) && is_uint8(op2));  // wrong opcode
   1909   ASSERT(is_uint8(imm8));
   1910   ASSERT((op1 & 0x01) == 0);  // should be 8bit operation
   1911   EMIT(op1);
   1912   EMIT(op2 | dst.code());
   1913   EMIT(imm8);
   1914 }
   1915 
   1916 
   1917 void Assembler::emit_arith(int sel, Operand dst, const Immediate& x) {
   1918   ASSERT((0 <= sel) && (sel <= 7));
   1919   Register ireg = { sel };
   1920   if (x.is_int8()) {
   1921     EMIT(0x83);  // using a sign-extended 8-bit immediate.
   1922     emit_operand(ireg, dst);
   1923     EMIT(x.x_ & 0xFF);
   1924   } else if (dst.is_reg(eax)) {
   1925     EMIT((sel << 3) | 0x05);  // short form if the destination is eax.
   1926     emit(x);
   1927   } else {
   1928     EMIT(0x81);  // using a literal 32-bit immediate.
   1929     emit_operand(ireg, dst);
   1930     emit(x);
   1931   }
   1932 }
   1933 
   1934 
   1935 void Assembler::emit_operand(Register reg, const Operand& adr) {
   1936   const unsigned length = adr.len_;
   1937   ASSERT(length > 0);
   1938 
   1939   // Emit updated ModRM byte containing the given register.
   1940   pc_[0] = (adr.buf_[0] & ~0x38) | (reg.code() << 3);
   1941 
   1942   // Emit the rest of the encoded operand.
   1943   for (unsigned i = 1; i < length; i++) pc_[i] = adr.buf_[i];
   1944   pc_ += length;
   1945 
   1946   // Emit relocation information if necessary.
   1947   if (length >= sizeof(int32_t) && !RelocInfo::IsNone(adr.rmode_)) {
   1948     pc_ -= sizeof(int32_t);  // pc_ must be *at* disp32
   1949     RecordRelocInfo(adr.rmode_);
   1950     pc_ += sizeof(int32_t);
   1951   }
   1952 }
   1953 
   1954 
   1955 void Assembler::emit_farith(int b1, int b2, int i) {
   1956   ASSERT(is_uint8(b1) && is_uint8(b2));  // wrong opcode
   1957   ASSERT(0 <= i &&  i < 8);  // illegal stack offset
   1958   EMIT(b1);
   1959   EMIT(b2 + i);
   1960 }
   1961 
   1962 
   1963 void Assembler::db(uint8_t data) {
   1964   EnsureSpace ensure_space(this);
   1965   EMIT(data);
   1966 }
   1967 
   1968 
   1969 void Assembler::dd(uint32_t data) {
   1970   EnsureSpace ensure_space(this);
   1971   emit(data);
   1972 }
   1973 
   1974 
   1975 void Assembler::RecordRelocInfo(RelocInfo::Mode rmode, intptr_t data) {
   1976   ASSERT(!RelocInfo::IsNone(rmode));
   1977   // Don't record external references unless the heap will be serialized.
   1978   if (rmode == RelocInfo::EXTERNAL_REFERENCE &&
   1979       !serializer_enabled() && !emit_debug_code()) {
   1980       return;
   1981   }
   1982   RelocInfo rinfo(pc_, rmode, data, NULL);
   1983   reloc_info_writer.Write(&rinfo);
   1984 }
   1985 
   1986 
   1987 Handle<ConstantPoolArray> Assembler::NewConstantPool(Isolate* isolate) {
   1988   // No out-of-line constant pool support.
   1989   ASSERT(!FLAG_enable_ool_constant_pool);
   1990   return isolate->factory()->empty_constant_pool_array();
   1991 }
   1992 
   1993 
   1994 void Assembler::PopulateConstantPool(ConstantPoolArray* constant_pool) {
   1995   // No out-of-line constant pool support.
   1996   ASSERT(!FLAG_enable_ool_constant_pool);
   1997   return;
   1998 }
   1999 
   2000 
   2001 #ifdef GENERATED_CODE_COVERAGE
   2002 static FILE* coverage_log = NULL;
   2003 
   2004 
   2005 static void InitCoverageLog() {
   2006   char* file_name = getenv("V8_GENERATED_CODE_COVERAGE_LOG");
   2007   if (file_name != NULL) {
   2008     coverage_log = fopen(file_name, "aw+");
   2009   }
   2010 }
   2011 
   2012 
   2013 void LogGeneratedCodeCoverage(const char* file_line) {
   2014   const char* return_address = (&file_line)[-1];
   2015   char* push_insn = const_cast<char*>(return_address - 12);
   2016   push_insn[0] = 0xeb;  // Relative branch insn.
   2017   push_insn[1] = 13;    // Skip over coverage insns.
   2018   if (coverage_log != NULL) {
   2019     fprintf(coverage_log, "%s\n", file_line);
   2020     fflush(coverage_log);
   2021   }
   2022 }
   2023 
   2024 #endif
   2025 
   2026 } }  // namespace v8::internal
   2027 
   2028 #endif  // V8_TARGET_ARCH_X87
   2029