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