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