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_IA32 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 CHECK(cpu.has_sse2()); // SSE2 support is mandatory. 56 CHECK(cpu.has_cmov()); // CMOV support is mandatory. 57 58 // Only use statically determined features for cross compile (snapshot). 59 if (cross_compile) return; 60 61 if (cpu.has_sse41() && FLAG_enable_sse4_1) supported_ |= 1u << SSE4_1; 62 if (cpu.has_sse3() && FLAG_enable_sse3) supported_ |= 1u << SSE3; 63} 64 65 66void CpuFeatures::PrintTarget() { } 67void CpuFeatures::PrintFeatures() { } 68 69 70// ----------------------------------------------------------------------------- 71// Implementation of Displacement 72 73void Displacement::init(Label* L, Type type) { 74 DCHECK(!L->is_bound()); 75 int next = 0; 76 if (L->is_linked()) { 77 next = L->pos(); 78 DCHECK(next > 0); // Displacements must be at positions > 0 79 } 80 // Ensure that we _never_ overflow the next field. 81 DCHECK(NextField::is_valid(Assembler::kMaximalBufferSize)); 82 data_ = NextField::encode(next) | TypeField::encode(type); 83} 84 85 86// ----------------------------------------------------------------------------- 87// Implementation of RelocInfo 88 89 90const int RelocInfo::kApplyMask = 91 RelocInfo::kCodeTargetMask | 1 << RelocInfo::RUNTIME_ENTRY | 92 1 << RelocInfo::JS_RETURN | 1 << RelocInfo::INTERNAL_REFERENCE | 93 1 << RelocInfo::DEBUG_BREAK_SLOT | 1 << RelocInfo::CODE_AGE_SEQUENCE; 94 95 96bool RelocInfo::IsCodedSpecially() { 97 // The deserializer needs to know whether a pointer is specially coded. Being 98 // specially coded on IA32 means that it is a relative address, as used by 99 // branch instructions. These are also the ones that need changing when a 100 // code object moves. 101 return (1 << rmode_) & kApplyMask; 102} 103 104 105bool RelocInfo::IsInConstantPool() { 106 return false; 107} 108 109 110void RelocInfo::PatchCode(byte* instructions, int instruction_count) { 111 // Patch the code at the current address with the supplied instructions. 112 for (int i = 0; i < instruction_count; i++) { 113 *(pc_ + i) = *(instructions + i); 114 } 115 116 // Indicate that code has changed. 117 CpuFeatures::FlushICache(pc_, instruction_count); 118} 119 120 121// Patch the code at the current PC with a call to the target address. 122// Additional guard int3 instructions can be added if required. 123void RelocInfo::PatchCodeWithCall(Address target, int guard_bytes) { 124 // Call instruction takes up 5 bytes and int3 takes up one byte. 125 static const int kCallCodeSize = 5; 126 int code_size = kCallCodeSize + guard_bytes; 127 128 // Create a code patcher. 129 CodePatcher patcher(pc_, code_size); 130 131 // Add a label for checking the size of the code used for returning. 132#ifdef DEBUG 133 Label check_codesize; 134 patcher.masm()->bind(&check_codesize); 135#endif 136 137 // Patch the code. 138 patcher.masm()->call(target, RelocInfo::NONE32); 139 140 // Check that the size of the code generated is as expected. 141 DCHECK_EQ(kCallCodeSize, 142 patcher.masm()->SizeOfCodeGeneratedSince(&check_codesize)); 143 144 // Add the requested number of int3 instructions after the call. 145 DCHECK_GE(guard_bytes, 0); 146 for (int i = 0; i < guard_bytes; i++) { 147 patcher.masm()->int3(); 148 } 149} 150 151 152// ----------------------------------------------------------------------------- 153// Implementation of Operand 154 155Operand::Operand(Register base, int32_t disp, RelocInfo::Mode rmode) { 156 // [base + disp/r] 157 if (disp == 0 && RelocInfo::IsNone(rmode) && !base.is(ebp)) { 158 // [base] 159 set_modrm(0, base); 160 if (base.is(esp)) set_sib(times_1, esp, base); 161 } else if (is_int8(disp) && RelocInfo::IsNone(rmode)) { 162 // [base + disp8] 163 set_modrm(1, base); 164 if (base.is(esp)) set_sib(times_1, esp, base); 165 set_disp8(disp); 166 } else { 167 // [base + disp/r] 168 set_modrm(2, base); 169 if (base.is(esp)) set_sib(times_1, esp, base); 170 set_dispr(disp, rmode); 171 } 172} 173 174 175Operand::Operand(Register base, 176 Register index, 177 ScaleFactor scale, 178 int32_t disp, 179 RelocInfo::Mode rmode) { 180 DCHECK(!index.is(esp)); // illegal addressing mode 181 // [base + index*scale + disp/r] 182 if (disp == 0 && RelocInfo::IsNone(rmode) && !base.is(ebp)) { 183 // [base + index*scale] 184 set_modrm(0, esp); 185 set_sib(scale, index, base); 186 } else if (is_int8(disp) && RelocInfo::IsNone(rmode)) { 187 // [base + index*scale + disp8] 188 set_modrm(1, esp); 189 set_sib(scale, index, base); 190 set_disp8(disp); 191 } else { 192 // [base + index*scale + disp/r] 193 set_modrm(2, esp); 194 set_sib(scale, index, base); 195 set_dispr(disp, rmode); 196 } 197} 198 199 200Operand::Operand(Register index, 201 ScaleFactor scale, 202 int32_t disp, 203 RelocInfo::Mode rmode) { 204 DCHECK(!index.is(esp)); // illegal addressing mode 205 // [index*scale + disp/r] 206 set_modrm(0, esp); 207 set_sib(scale, index, ebp); 208 set_dispr(disp, rmode); 209} 210 211 212bool Operand::is_reg(Register reg) const { 213 return ((buf_[0] & 0xF8) == 0xC0) // addressing mode is register only. 214 && ((buf_[0] & 0x07) == reg.code()); // register codes match. 215} 216 217 218bool Operand::is_reg_only() const { 219 return (buf_[0] & 0xF8) == 0xC0; // Addressing mode is register only. 220} 221 222 223Register Operand::reg() const { 224 DCHECK(is_reg_only()); 225 return Register::from_code(buf_[0] & 0x07); 226} 227 228 229// ----------------------------------------------------------------------------- 230// Implementation of Assembler. 231 232// Emit a single byte. Must always be inlined. 233#define EMIT(x) \ 234 *pc_++ = (x) 235 236 237#ifdef GENERATED_CODE_COVERAGE 238static void InitCoverageLog(); 239#endif 240 241Assembler::Assembler(Isolate* isolate, void* buffer, int buffer_size) 242 : AssemblerBase(isolate, buffer, buffer_size), 243 positions_recorder_(this) { 244 // Clear the buffer in debug mode unless it was provided by the 245 // caller in which case we can't be sure it's okay to overwrite 246 // existing code in it; see CodePatcher::CodePatcher(...). 247#ifdef DEBUG 248 if (own_buffer_) { 249 memset(buffer_, 0xCC, buffer_size_); // int3 250 } 251#endif 252 253 reloc_info_writer.Reposition(buffer_ + buffer_size_, pc_); 254 255#ifdef GENERATED_CODE_COVERAGE 256 InitCoverageLog(); 257#endif 258} 259 260 261void Assembler::GetCode(CodeDesc* desc) { 262 // Finalize code (at this point overflow() may be true, but the gap ensures 263 // that we are still not overlapping instructions and relocation info). 264 DCHECK(pc_ <= reloc_info_writer.pos()); // No overlap. 265 // Set up code descriptor. 266 desc->buffer = buffer_; 267 desc->buffer_size = buffer_size_; 268 desc->instr_size = pc_offset(); 269 desc->reloc_size = (buffer_ + buffer_size_) - reloc_info_writer.pos(); 270 desc->origin = this; 271} 272 273 274void Assembler::Align(int m) { 275 DCHECK(base::bits::IsPowerOfTwo32(m)); 276 int mask = m - 1; 277 int addr = pc_offset(); 278 Nop((m - (addr & mask)) & mask); 279} 280 281 282bool Assembler::IsNop(Address addr) { 283 Address a = addr; 284 while (*a == 0x66) a++; 285 if (*a == 0x90) return true; 286 if (a[0] == 0xf && a[1] == 0x1f) return true; 287 return false; 288} 289 290 291void Assembler::Nop(int bytes) { 292 EnsureSpace ensure_space(this); 293 294 // Multi byte nops from http://support.amd.com/us/Processor_TechDocs/40546.pdf 295 while (bytes > 0) { 296 switch (bytes) { 297 case 2: 298 EMIT(0x66); 299 case 1: 300 EMIT(0x90); 301 return; 302 case 3: 303 EMIT(0xf); 304 EMIT(0x1f); 305 EMIT(0); 306 return; 307 case 4: 308 EMIT(0xf); 309 EMIT(0x1f); 310 EMIT(0x40); 311 EMIT(0); 312 return; 313 case 6: 314 EMIT(0x66); 315 case 5: 316 EMIT(0xf); 317 EMIT(0x1f); 318 EMIT(0x44); 319 EMIT(0); 320 EMIT(0); 321 return; 322 case 7: 323 EMIT(0xf); 324 EMIT(0x1f); 325 EMIT(0x80); 326 EMIT(0); 327 EMIT(0); 328 EMIT(0); 329 EMIT(0); 330 return; 331 default: 332 case 11: 333 EMIT(0x66); 334 bytes--; 335 case 10: 336 EMIT(0x66); 337 bytes--; 338 case 9: 339 EMIT(0x66); 340 bytes--; 341 case 8: 342 EMIT(0xf); 343 EMIT(0x1f); 344 EMIT(0x84); 345 EMIT(0); 346 EMIT(0); 347 EMIT(0); 348 EMIT(0); 349 EMIT(0); 350 bytes -= 8; 351 } 352 } 353} 354 355 356void Assembler::CodeTargetAlign() { 357 Align(16); // Preferred alignment of jump targets on ia32. 358} 359 360 361void Assembler::cpuid() { 362 EnsureSpace ensure_space(this); 363 EMIT(0x0F); 364 EMIT(0xA2); 365} 366 367 368void Assembler::pushad() { 369 EnsureSpace ensure_space(this); 370 EMIT(0x60); 371} 372 373 374void Assembler::popad() { 375 EnsureSpace ensure_space(this); 376 EMIT(0x61); 377} 378 379 380void Assembler::pushfd() { 381 EnsureSpace ensure_space(this); 382 EMIT(0x9C); 383} 384 385 386void Assembler::popfd() { 387 EnsureSpace ensure_space(this); 388 EMIT(0x9D); 389} 390 391 392void Assembler::push(const Immediate& x) { 393 EnsureSpace ensure_space(this); 394 if (x.is_int8()) { 395 EMIT(0x6a); 396 EMIT(x.x_); 397 } else { 398 EMIT(0x68); 399 emit(x); 400 } 401} 402 403 404void Assembler::push_imm32(int32_t imm32) { 405 EnsureSpace ensure_space(this); 406 EMIT(0x68); 407 emit(imm32); 408} 409 410 411void Assembler::push(Register src) { 412 EnsureSpace ensure_space(this); 413 EMIT(0x50 | src.code()); 414} 415 416 417void Assembler::push(const Operand& src) { 418 EnsureSpace ensure_space(this); 419 EMIT(0xFF); 420 emit_operand(esi, src); 421} 422 423 424void Assembler::pop(Register dst) { 425 DCHECK(reloc_info_writer.last_pc() != NULL); 426 EnsureSpace ensure_space(this); 427 EMIT(0x58 | dst.code()); 428} 429 430 431void Assembler::pop(const Operand& dst) { 432 EnsureSpace ensure_space(this); 433 EMIT(0x8F); 434 emit_operand(eax, dst); 435} 436 437 438void Assembler::enter(const Immediate& size) { 439 EnsureSpace ensure_space(this); 440 EMIT(0xC8); 441 emit_w(size); 442 EMIT(0); 443} 444 445 446void Assembler::leave() { 447 EnsureSpace ensure_space(this); 448 EMIT(0xC9); 449} 450 451 452void Assembler::mov_b(Register dst, const Operand& src) { 453 CHECK(dst.is_byte_register()); 454 EnsureSpace ensure_space(this); 455 EMIT(0x8A); 456 emit_operand(dst, src); 457} 458 459 460void Assembler::mov_b(const Operand& dst, int8_t imm8) { 461 EnsureSpace ensure_space(this); 462 EMIT(0xC6); 463 emit_operand(eax, dst); 464 EMIT(imm8); 465} 466 467 468void Assembler::mov_b(const Operand& dst, Register src) { 469 CHECK(src.is_byte_register()); 470 EnsureSpace ensure_space(this); 471 EMIT(0x88); 472 emit_operand(src, dst); 473} 474 475 476void Assembler::mov_w(Register dst, const Operand& src) { 477 EnsureSpace ensure_space(this); 478 EMIT(0x66); 479 EMIT(0x8B); 480 emit_operand(dst, src); 481} 482 483 484void Assembler::mov_w(const Operand& dst, Register src) { 485 EnsureSpace ensure_space(this); 486 EMIT(0x66); 487 EMIT(0x89); 488 emit_operand(src, dst); 489} 490 491 492void Assembler::mov_w(const Operand& dst, int16_t imm16) { 493 EnsureSpace ensure_space(this); 494 EMIT(0x66); 495 EMIT(0xC7); 496 emit_operand(eax, dst); 497 EMIT(static_cast<int8_t>(imm16 & 0xff)); 498 EMIT(static_cast<int8_t>(imm16 >> 8)); 499} 500 501 502void Assembler::mov(Register dst, int32_t imm32) { 503 EnsureSpace ensure_space(this); 504 EMIT(0xB8 | dst.code()); 505 emit(imm32); 506} 507 508 509void Assembler::mov(Register dst, const Immediate& x) { 510 EnsureSpace ensure_space(this); 511 EMIT(0xB8 | dst.code()); 512 emit(x); 513} 514 515 516void Assembler::mov(Register dst, Handle<Object> handle) { 517 EnsureSpace ensure_space(this); 518 EMIT(0xB8 | dst.code()); 519 emit(handle); 520} 521 522 523void Assembler::mov(Register dst, const Operand& src) { 524 EnsureSpace ensure_space(this); 525 EMIT(0x8B); 526 emit_operand(dst, src); 527} 528 529 530void Assembler::mov(Register dst, Register src) { 531 EnsureSpace ensure_space(this); 532 EMIT(0x89); 533 EMIT(0xC0 | src.code() << 3 | dst.code()); 534} 535 536 537void Assembler::mov(const Operand& dst, const Immediate& x) { 538 EnsureSpace ensure_space(this); 539 EMIT(0xC7); 540 emit_operand(eax, dst); 541 emit(x); 542} 543 544 545void Assembler::mov(const Operand& dst, Handle<Object> handle) { 546 EnsureSpace ensure_space(this); 547 EMIT(0xC7); 548 emit_operand(eax, dst); 549 emit(handle); 550} 551 552 553void Assembler::mov(const Operand& dst, Register src) { 554 EnsureSpace ensure_space(this); 555 EMIT(0x89); 556 emit_operand(src, dst); 557} 558 559 560void Assembler::movsx_b(Register dst, const Operand& src) { 561 EnsureSpace ensure_space(this); 562 EMIT(0x0F); 563 EMIT(0xBE); 564 emit_operand(dst, src); 565} 566 567 568void Assembler::movsx_w(Register dst, const Operand& src) { 569 EnsureSpace ensure_space(this); 570 EMIT(0x0F); 571 EMIT(0xBF); 572 emit_operand(dst, src); 573} 574 575 576void Assembler::movzx_b(Register dst, const Operand& src) { 577 EnsureSpace ensure_space(this); 578 EMIT(0x0F); 579 EMIT(0xB6); 580 emit_operand(dst, src); 581} 582 583 584void Assembler::movzx_w(Register dst, const Operand& src) { 585 EnsureSpace ensure_space(this); 586 EMIT(0x0F); 587 EMIT(0xB7); 588 emit_operand(dst, src); 589} 590 591 592void Assembler::cmov(Condition cc, Register dst, const Operand& src) { 593 EnsureSpace ensure_space(this); 594 // Opcode: 0f 40 + cc /r. 595 EMIT(0x0F); 596 EMIT(0x40 + cc); 597 emit_operand(dst, src); 598} 599 600 601void Assembler::cld() { 602 EnsureSpace ensure_space(this); 603 EMIT(0xFC); 604} 605 606 607void Assembler::rep_movs() { 608 EnsureSpace ensure_space(this); 609 EMIT(0xF3); 610 EMIT(0xA5); 611} 612 613 614void Assembler::rep_stos() { 615 EnsureSpace ensure_space(this); 616 EMIT(0xF3); 617 EMIT(0xAB); 618} 619 620 621void Assembler::stos() { 622 EnsureSpace ensure_space(this); 623 EMIT(0xAB); 624} 625 626 627void Assembler::xchg(Register dst, Register src) { 628 EnsureSpace ensure_space(this); 629 if (src.is(eax) || dst.is(eax)) { // Single-byte encoding. 630 EMIT(0x90 | (src.is(eax) ? dst.code() : src.code())); 631 } else { 632 EMIT(0x87); 633 EMIT(0xC0 | src.code() << 3 | dst.code()); 634 } 635} 636 637 638void Assembler::xchg(Register dst, const Operand& src) { 639 EnsureSpace ensure_space(this); 640 EMIT(0x87); 641 emit_operand(dst, src); 642} 643 644 645void Assembler::adc(Register dst, int32_t imm32) { 646 EnsureSpace ensure_space(this); 647 emit_arith(2, Operand(dst), Immediate(imm32)); 648} 649 650 651void Assembler::adc(Register dst, const Operand& src) { 652 EnsureSpace ensure_space(this); 653 EMIT(0x13); 654 emit_operand(dst, src); 655} 656 657 658void Assembler::add(Register dst, const Operand& src) { 659 EnsureSpace ensure_space(this); 660 EMIT(0x03); 661 emit_operand(dst, src); 662} 663 664 665void Assembler::add(const Operand& dst, Register src) { 666 EnsureSpace ensure_space(this); 667 EMIT(0x01); 668 emit_operand(src, dst); 669} 670 671 672void Assembler::add(const Operand& dst, const Immediate& x) { 673 DCHECK(reloc_info_writer.last_pc() != NULL); 674 EnsureSpace ensure_space(this); 675 emit_arith(0, dst, x); 676} 677 678 679void Assembler::and_(Register dst, int32_t imm32) { 680 and_(dst, Immediate(imm32)); 681} 682 683 684void Assembler::and_(Register dst, const Immediate& x) { 685 EnsureSpace ensure_space(this); 686 emit_arith(4, Operand(dst), x); 687} 688 689 690void Assembler::and_(Register dst, const Operand& src) { 691 EnsureSpace ensure_space(this); 692 EMIT(0x23); 693 emit_operand(dst, src); 694} 695 696 697void Assembler::and_(const Operand& dst, const Immediate& x) { 698 EnsureSpace ensure_space(this); 699 emit_arith(4, dst, x); 700} 701 702 703void Assembler::and_(const Operand& dst, Register src) { 704 EnsureSpace ensure_space(this); 705 EMIT(0x21); 706 emit_operand(src, dst); 707} 708 709 710void Assembler::cmpb(const Operand& op, int8_t imm8) { 711 EnsureSpace ensure_space(this); 712 if (op.is_reg(eax)) { 713 EMIT(0x3C); 714 } else { 715 EMIT(0x80); 716 emit_operand(edi, op); // edi == 7 717 } 718 EMIT(imm8); 719} 720 721 722void Assembler::cmpb(const Operand& op, Register reg) { 723 CHECK(reg.is_byte_register()); 724 EnsureSpace ensure_space(this); 725 EMIT(0x38); 726 emit_operand(reg, op); 727} 728 729 730void Assembler::cmpb(Register reg, const Operand& op) { 731 CHECK(reg.is_byte_register()); 732 EnsureSpace ensure_space(this); 733 EMIT(0x3A); 734 emit_operand(reg, op); 735} 736 737 738void Assembler::cmpw(const Operand& op, Immediate imm16) { 739 DCHECK(imm16.is_int16()); 740 EnsureSpace ensure_space(this); 741 EMIT(0x66); 742 EMIT(0x81); 743 emit_operand(edi, op); 744 emit_w(imm16); 745} 746 747 748void Assembler::cmp(Register reg, int32_t imm32) { 749 EnsureSpace ensure_space(this); 750 emit_arith(7, Operand(reg), Immediate(imm32)); 751} 752 753 754void Assembler::cmp(Register reg, Handle<Object> handle) { 755 EnsureSpace ensure_space(this); 756 emit_arith(7, Operand(reg), Immediate(handle)); 757} 758 759 760void Assembler::cmp(Register reg, const Operand& op) { 761 EnsureSpace ensure_space(this); 762 EMIT(0x3B); 763 emit_operand(reg, op); 764} 765 766 767void Assembler::cmp(const Operand& op, const Immediate& imm) { 768 EnsureSpace ensure_space(this); 769 emit_arith(7, op, imm); 770} 771 772 773void Assembler::cmp(const Operand& op, Handle<Object> handle) { 774 EnsureSpace ensure_space(this); 775 emit_arith(7, op, Immediate(handle)); 776} 777 778 779void Assembler::cmpb_al(const Operand& op) { 780 EnsureSpace ensure_space(this); 781 EMIT(0x38); // CMP r/m8, r8 782 emit_operand(eax, op); // eax has same code as register al. 783} 784 785 786void Assembler::cmpw_ax(const Operand& op) { 787 EnsureSpace ensure_space(this); 788 EMIT(0x66); 789 EMIT(0x39); // CMP r/m16, r16 790 emit_operand(eax, op); // eax has same code as register ax. 791} 792 793 794void Assembler::dec_b(Register dst) { 795 CHECK(dst.is_byte_register()); 796 EnsureSpace ensure_space(this); 797 EMIT(0xFE); 798 EMIT(0xC8 | dst.code()); 799} 800 801 802void Assembler::dec_b(const Operand& dst) { 803 EnsureSpace ensure_space(this); 804 EMIT(0xFE); 805 emit_operand(ecx, dst); 806} 807 808 809void Assembler::dec(Register dst) { 810 EnsureSpace ensure_space(this); 811 EMIT(0x48 | dst.code()); 812} 813 814 815void Assembler::dec(const Operand& dst) { 816 EnsureSpace ensure_space(this); 817 EMIT(0xFF); 818 emit_operand(ecx, dst); 819} 820 821 822void Assembler::cdq() { 823 EnsureSpace ensure_space(this); 824 EMIT(0x99); 825} 826 827 828void Assembler::idiv(const Operand& src) { 829 EnsureSpace ensure_space(this); 830 EMIT(0xF7); 831 emit_operand(edi, src); 832} 833 834 835void Assembler::div(const Operand& src) { 836 EnsureSpace ensure_space(this); 837 EMIT(0xF7); 838 emit_operand(esi, src); 839} 840 841 842void Assembler::imul(Register reg) { 843 EnsureSpace ensure_space(this); 844 EMIT(0xF7); 845 EMIT(0xE8 | reg.code()); 846} 847 848 849void Assembler::imul(Register dst, const Operand& src) { 850 EnsureSpace ensure_space(this); 851 EMIT(0x0F); 852 EMIT(0xAF); 853 emit_operand(dst, src); 854} 855 856 857void Assembler::imul(Register dst, Register src, int32_t imm32) { 858 imul(dst, Operand(src), imm32); 859} 860 861 862void Assembler::imul(Register dst, const Operand& src, int32_t imm32) { 863 EnsureSpace ensure_space(this); 864 if (is_int8(imm32)) { 865 EMIT(0x6B); 866 emit_operand(dst, src); 867 EMIT(imm32); 868 } else { 869 EMIT(0x69); 870 emit_operand(dst, src); 871 emit(imm32); 872 } 873} 874 875 876void Assembler::inc(Register dst) { 877 EnsureSpace ensure_space(this); 878 EMIT(0x40 | dst.code()); 879} 880 881 882void Assembler::inc(const Operand& dst) { 883 EnsureSpace ensure_space(this); 884 EMIT(0xFF); 885 emit_operand(eax, dst); 886} 887 888 889void Assembler::lea(Register dst, const Operand& src) { 890 EnsureSpace ensure_space(this); 891 EMIT(0x8D); 892 emit_operand(dst, src); 893} 894 895 896void Assembler::mul(Register src) { 897 EnsureSpace ensure_space(this); 898 EMIT(0xF7); 899 EMIT(0xE0 | src.code()); 900} 901 902 903void Assembler::neg(Register dst) { 904 EnsureSpace ensure_space(this); 905 EMIT(0xF7); 906 EMIT(0xD8 | dst.code()); 907} 908 909 910void Assembler::neg(const Operand& dst) { 911 EnsureSpace ensure_space(this); 912 EMIT(0xF7); 913 emit_operand(ebx, dst); 914} 915 916 917void Assembler::not_(Register dst) { 918 EnsureSpace ensure_space(this); 919 EMIT(0xF7); 920 EMIT(0xD0 | dst.code()); 921} 922 923 924void Assembler::not_(const Operand& dst) { 925 EnsureSpace ensure_space(this); 926 EMIT(0xF7); 927 emit_operand(edx, dst); 928} 929 930 931void Assembler::or_(Register dst, int32_t imm32) { 932 EnsureSpace ensure_space(this); 933 emit_arith(1, Operand(dst), Immediate(imm32)); 934} 935 936 937void Assembler::or_(Register dst, const Operand& src) { 938 EnsureSpace ensure_space(this); 939 EMIT(0x0B); 940 emit_operand(dst, src); 941} 942 943 944void Assembler::or_(const Operand& dst, const Immediate& x) { 945 EnsureSpace ensure_space(this); 946 emit_arith(1, dst, x); 947} 948 949 950void Assembler::or_(const Operand& dst, Register src) { 951 EnsureSpace ensure_space(this); 952 EMIT(0x09); 953 emit_operand(src, dst); 954} 955 956 957void Assembler::rcl(Register dst, uint8_t imm8) { 958 EnsureSpace ensure_space(this); 959 DCHECK(is_uint5(imm8)); // illegal shift count 960 if (imm8 == 1) { 961 EMIT(0xD1); 962 EMIT(0xD0 | dst.code()); 963 } else { 964 EMIT(0xC1); 965 EMIT(0xD0 | dst.code()); 966 EMIT(imm8); 967 } 968} 969 970 971void Assembler::rcr(Register dst, uint8_t imm8) { 972 EnsureSpace ensure_space(this); 973 DCHECK(is_uint5(imm8)); // illegal shift count 974 if (imm8 == 1) { 975 EMIT(0xD1); 976 EMIT(0xD8 | dst.code()); 977 } else { 978 EMIT(0xC1); 979 EMIT(0xD8 | dst.code()); 980 EMIT(imm8); 981 } 982} 983 984 985void Assembler::ror(Register dst, uint8_t imm8) { 986 EnsureSpace ensure_space(this); 987 DCHECK(is_uint5(imm8)); // illegal shift count 988 if (imm8 == 1) { 989 EMIT(0xD1); 990 EMIT(0xC8 | dst.code()); 991 } else { 992 EMIT(0xC1); 993 EMIT(0xC8 | dst.code()); 994 EMIT(imm8); 995 } 996} 997 998 999void Assembler::ror_cl(Register dst) { 1000 EnsureSpace ensure_space(this); 1001 EMIT(0xD3); 1002 EMIT(0xC8 | dst.code()); 1003} 1004 1005 1006void Assembler::sar(const Operand& dst, uint8_t imm8) { 1007 EnsureSpace ensure_space(this); 1008 DCHECK(is_uint5(imm8)); // illegal shift count 1009 if (imm8 == 1) { 1010 EMIT(0xD1); 1011 emit_operand(edi, dst); 1012 } else { 1013 EMIT(0xC1); 1014 emit_operand(edi, dst); 1015 EMIT(imm8); 1016 } 1017} 1018 1019 1020void Assembler::sar_cl(const Operand& dst) { 1021 EnsureSpace ensure_space(this); 1022 EMIT(0xD3); 1023 emit_operand(edi, dst); 1024} 1025 1026 1027void Assembler::sbb(Register dst, const Operand& src) { 1028 EnsureSpace ensure_space(this); 1029 EMIT(0x1B); 1030 emit_operand(dst, src); 1031} 1032 1033 1034void Assembler::shld(Register dst, const Operand& src) { 1035 EnsureSpace ensure_space(this); 1036 EMIT(0x0F); 1037 EMIT(0xA5); 1038 emit_operand(dst, src); 1039} 1040 1041 1042void Assembler::shl(const Operand& dst, uint8_t imm8) { 1043 EnsureSpace ensure_space(this); 1044 DCHECK(is_uint5(imm8)); // illegal shift count 1045 if (imm8 == 1) { 1046 EMIT(0xD1); 1047 emit_operand(esp, dst); 1048 } else { 1049 EMIT(0xC1); 1050 emit_operand(esp, dst); 1051 EMIT(imm8); 1052 } 1053} 1054 1055 1056void Assembler::shl_cl(const Operand& dst) { 1057 EnsureSpace ensure_space(this); 1058 EMIT(0xD3); 1059 emit_operand(esp, dst); 1060} 1061 1062 1063void Assembler::shrd(Register dst, const Operand& src) { 1064 EnsureSpace ensure_space(this); 1065 EMIT(0x0F); 1066 EMIT(0xAD); 1067 emit_operand(dst, src); 1068} 1069 1070 1071void Assembler::shr(const Operand& dst, uint8_t imm8) { 1072 EnsureSpace ensure_space(this); 1073 DCHECK(is_uint5(imm8)); // illegal shift count 1074 if (imm8 == 1) { 1075 EMIT(0xD1); 1076 emit_operand(ebp, dst); 1077 } else { 1078 EMIT(0xC1); 1079 emit_operand(ebp, dst); 1080 EMIT(imm8); 1081 } 1082} 1083 1084 1085void Assembler::shr_cl(const Operand& dst) { 1086 EnsureSpace ensure_space(this); 1087 EMIT(0xD3); 1088 emit_operand(ebp, dst); 1089} 1090 1091 1092void Assembler::sub(const Operand& dst, const Immediate& x) { 1093 EnsureSpace ensure_space(this); 1094 emit_arith(5, dst, x); 1095} 1096 1097 1098void Assembler::sub(Register dst, const Operand& src) { 1099 EnsureSpace ensure_space(this); 1100 EMIT(0x2B); 1101 emit_operand(dst, src); 1102} 1103 1104 1105void Assembler::sub(const Operand& dst, Register src) { 1106 EnsureSpace ensure_space(this); 1107 EMIT(0x29); 1108 emit_operand(src, dst); 1109} 1110 1111 1112void Assembler::test(Register reg, const Immediate& imm) { 1113 if (RelocInfo::IsNone(imm.rmode_) && is_uint8(imm.x_)) { 1114 test_b(reg, imm.x_); 1115 return; 1116 } 1117 1118 EnsureSpace ensure_space(this); 1119 // This is not using emit_arith because test doesn't support 1120 // sign-extension of 8-bit operands. 1121 if (reg.is(eax)) { 1122 EMIT(0xA9); 1123 } else { 1124 EMIT(0xF7); 1125 EMIT(0xC0 | reg.code()); 1126 } 1127 emit(imm); 1128} 1129 1130 1131void Assembler::test(Register reg, const Operand& op) { 1132 EnsureSpace ensure_space(this); 1133 EMIT(0x85); 1134 emit_operand(reg, op); 1135} 1136 1137 1138void Assembler::test_b(Register reg, const Operand& op) { 1139 CHECK(reg.is_byte_register()); 1140 EnsureSpace ensure_space(this); 1141 EMIT(0x84); 1142 emit_operand(reg, op); 1143} 1144 1145 1146void Assembler::test(const Operand& op, const Immediate& imm) { 1147 if (op.is_reg_only()) { 1148 test(op.reg(), imm); 1149 return; 1150 } 1151 if (RelocInfo::IsNone(imm.rmode_) && is_uint8(imm.x_)) { 1152 return test_b(op, imm.x_); 1153 } 1154 EnsureSpace ensure_space(this); 1155 EMIT(0xF7); 1156 emit_operand(eax, op); 1157 emit(imm); 1158} 1159 1160 1161void Assembler::test_b(Register reg, uint8_t imm8) { 1162 EnsureSpace ensure_space(this); 1163 // Only use test against byte for registers that have a byte 1164 // variant: eax, ebx, ecx, and edx. 1165 if (reg.is(eax)) { 1166 EMIT(0xA8); 1167 EMIT(imm8); 1168 } else if (reg.is_byte_register()) { 1169 emit_arith_b(0xF6, 0xC0, reg, imm8); 1170 } else { 1171 EMIT(0xF7); 1172 EMIT(0xC0 | reg.code()); 1173 emit(imm8); 1174 } 1175} 1176 1177 1178void Assembler::test_b(const Operand& op, uint8_t imm8) { 1179 if (op.is_reg_only()) { 1180 test_b(op.reg(), imm8); 1181 return; 1182 } 1183 EnsureSpace ensure_space(this); 1184 EMIT(0xF6); 1185 emit_operand(eax, op); 1186 EMIT(imm8); 1187} 1188 1189 1190void Assembler::xor_(Register dst, int32_t imm32) { 1191 EnsureSpace ensure_space(this); 1192 emit_arith(6, Operand(dst), Immediate(imm32)); 1193} 1194 1195 1196void Assembler::xor_(Register dst, const Operand& src) { 1197 EnsureSpace ensure_space(this); 1198 EMIT(0x33); 1199 emit_operand(dst, src); 1200} 1201 1202 1203void Assembler::xor_(const Operand& dst, Register src) { 1204 EnsureSpace ensure_space(this); 1205 EMIT(0x31); 1206 emit_operand(src, dst); 1207} 1208 1209 1210void Assembler::xor_(const Operand& dst, const Immediate& x) { 1211 EnsureSpace ensure_space(this); 1212 emit_arith(6, dst, x); 1213} 1214 1215 1216void Assembler::bt(const Operand& dst, Register src) { 1217 EnsureSpace ensure_space(this); 1218 EMIT(0x0F); 1219 EMIT(0xA3); 1220 emit_operand(src, dst); 1221} 1222 1223 1224void Assembler::bts(const Operand& dst, Register src) { 1225 EnsureSpace ensure_space(this); 1226 EMIT(0x0F); 1227 EMIT(0xAB); 1228 emit_operand(src, dst); 1229} 1230 1231 1232void Assembler::bsr(Register dst, const Operand& src) { 1233 EnsureSpace ensure_space(this); 1234 EMIT(0x0F); 1235 EMIT(0xBD); 1236 emit_operand(dst, src); 1237} 1238 1239 1240void Assembler::hlt() { 1241 EnsureSpace ensure_space(this); 1242 EMIT(0xF4); 1243} 1244 1245 1246void Assembler::int3() { 1247 EnsureSpace ensure_space(this); 1248 EMIT(0xCC); 1249} 1250 1251 1252void Assembler::nop() { 1253 EnsureSpace ensure_space(this); 1254 EMIT(0x90); 1255} 1256 1257 1258void Assembler::ret(int imm16) { 1259 EnsureSpace ensure_space(this); 1260 DCHECK(is_uint16(imm16)); 1261 if (imm16 == 0) { 1262 EMIT(0xC3); 1263 } else { 1264 EMIT(0xC2); 1265 EMIT(imm16 & 0xFF); 1266 EMIT((imm16 >> 8) & 0xFF); 1267 } 1268} 1269 1270 1271// Labels refer to positions in the (to be) generated code. 1272// There are bound, linked, and unused labels. 1273// 1274// Bound labels refer to known positions in the already 1275// generated code. pos() is the position the label refers to. 1276// 1277// Linked labels refer to unknown positions in the code 1278// to be generated; pos() is the position of the 32bit 1279// Displacement of the last instruction using the label. 1280 1281 1282void Assembler::print(Label* L) { 1283 if (L->is_unused()) { 1284 PrintF("unused label\n"); 1285 } else if (L->is_bound()) { 1286 PrintF("bound label to %d\n", L->pos()); 1287 } else if (L->is_linked()) { 1288 Label l = *L; 1289 PrintF("unbound label"); 1290 while (l.is_linked()) { 1291 Displacement disp = disp_at(&l); 1292 PrintF("@ %d ", l.pos()); 1293 disp.print(); 1294 PrintF("\n"); 1295 disp.next(&l); 1296 } 1297 } else { 1298 PrintF("label in inconsistent state (pos = %d)\n", L->pos_); 1299 } 1300} 1301 1302 1303void Assembler::bind_to(Label* L, int pos) { 1304 EnsureSpace ensure_space(this); 1305 DCHECK(0 <= pos && pos <= pc_offset()); // must have a valid binding position 1306 while (L->is_linked()) { 1307 Displacement disp = disp_at(L); 1308 int fixup_pos = L->pos(); 1309 if (disp.type() == Displacement::CODE_RELATIVE) { 1310 // Relative to Code* heap object pointer. 1311 long_at_put(fixup_pos, pos + Code::kHeaderSize - kHeapObjectTag); 1312 } else { 1313 if (disp.type() == Displacement::UNCONDITIONAL_JUMP) { 1314 DCHECK(byte_at(fixup_pos - 1) == 0xE9); // jmp expected 1315 } 1316 // Relative address, relative to point after address. 1317 int imm32 = pos - (fixup_pos + sizeof(int32_t)); 1318 long_at_put(fixup_pos, imm32); 1319 } 1320 disp.next(L); 1321 } 1322 while (L->is_near_linked()) { 1323 int fixup_pos = L->near_link_pos(); 1324 int offset_to_next = 1325 static_cast<int>(*reinterpret_cast<int8_t*>(addr_at(fixup_pos))); 1326 DCHECK(offset_to_next <= 0); 1327 // Relative address, relative to point after address. 1328 int disp = pos - fixup_pos - sizeof(int8_t); 1329 CHECK(0 <= disp && disp <= 127); 1330 set_byte_at(fixup_pos, disp); 1331 if (offset_to_next < 0) { 1332 L->link_to(fixup_pos + offset_to_next, Label::kNear); 1333 } else { 1334 L->UnuseNear(); 1335 } 1336 } 1337 L->bind_to(pos); 1338} 1339 1340 1341void Assembler::bind(Label* L) { 1342 EnsureSpace ensure_space(this); 1343 DCHECK(!L->is_bound()); // label can only be bound once 1344 bind_to(L, pc_offset()); 1345} 1346 1347 1348void Assembler::call(Label* L) { 1349 positions_recorder()->WriteRecordedPositions(); 1350 EnsureSpace ensure_space(this); 1351 if (L->is_bound()) { 1352 const int long_size = 5; 1353 int offs = L->pos() - pc_offset(); 1354 DCHECK(offs <= 0); 1355 // 1110 1000 #32-bit disp. 1356 EMIT(0xE8); 1357 emit(offs - long_size); 1358 } else { 1359 // 1110 1000 #32-bit disp. 1360 EMIT(0xE8); 1361 emit_disp(L, Displacement::OTHER); 1362 } 1363} 1364 1365 1366void Assembler::call(byte* entry, RelocInfo::Mode rmode) { 1367 positions_recorder()->WriteRecordedPositions(); 1368 EnsureSpace ensure_space(this); 1369 DCHECK(!RelocInfo::IsCodeTarget(rmode)); 1370 EMIT(0xE8); 1371 if (RelocInfo::IsRuntimeEntry(rmode)) { 1372 emit(reinterpret_cast<uint32_t>(entry), rmode); 1373 } else { 1374 emit(entry - (pc_ + sizeof(int32_t)), rmode); 1375 } 1376} 1377 1378 1379int Assembler::CallSize(const Operand& adr) { 1380 // Call size is 1 (opcode) + adr.len_ (operand). 1381 return 1 + adr.len_; 1382} 1383 1384 1385void Assembler::call(const Operand& adr) { 1386 positions_recorder()->WriteRecordedPositions(); 1387 EnsureSpace ensure_space(this); 1388 EMIT(0xFF); 1389 emit_operand(edx, adr); 1390} 1391 1392 1393int Assembler::CallSize(Handle<Code> code, RelocInfo::Mode rmode) { 1394 return 1 /* EMIT */ + sizeof(uint32_t) /* emit */; 1395} 1396 1397 1398void Assembler::call(Handle<Code> code, 1399 RelocInfo::Mode rmode, 1400 TypeFeedbackId ast_id) { 1401 positions_recorder()->WriteRecordedPositions(); 1402 EnsureSpace ensure_space(this); 1403 DCHECK(RelocInfo::IsCodeTarget(rmode) 1404 || rmode == RelocInfo::CODE_AGE_SEQUENCE); 1405 EMIT(0xE8); 1406 emit(code, rmode, ast_id); 1407} 1408 1409 1410void Assembler::jmp(Label* L, Label::Distance distance) { 1411 EnsureSpace ensure_space(this); 1412 if (L->is_bound()) { 1413 const int short_size = 2; 1414 const int long_size = 5; 1415 int offs = L->pos() - pc_offset(); 1416 DCHECK(offs <= 0); 1417 if (is_int8(offs - short_size)) { 1418 // 1110 1011 #8-bit disp. 1419 EMIT(0xEB); 1420 EMIT((offs - short_size) & 0xFF); 1421 } else { 1422 // 1110 1001 #32-bit disp. 1423 EMIT(0xE9); 1424 emit(offs - long_size); 1425 } 1426 } else if (distance == Label::kNear) { 1427 EMIT(0xEB); 1428 emit_near_disp(L); 1429 } else { 1430 // 1110 1001 #32-bit disp. 1431 EMIT(0xE9); 1432 emit_disp(L, Displacement::UNCONDITIONAL_JUMP); 1433 } 1434} 1435 1436 1437void Assembler::jmp(byte* entry, RelocInfo::Mode rmode) { 1438 EnsureSpace ensure_space(this); 1439 DCHECK(!RelocInfo::IsCodeTarget(rmode)); 1440 EMIT(0xE9); 1441 if (RelocInfo::IsRuntimeEntry(rmode)) { 1442 emit(reinterpret_cast<uint32_t>(entry), rmode); 1443 } else { 1444 emit(entry - (pc_ + sizeof(int32_t)), rmode); 1445 } 1446} 1447 1448 1449void Assembler::jmp(const Operand& adr) { 1450 EnsureSpace ensure_space(this); 1451 EMIT(0xFF); 1452 emit_operand(esp, adr); 1453} 1454 1455 1456void Assembler::jmp(Handle<Code> code, RelocInfo::Mode rmode) { 1457 EnsureSpace ensure_space(this); 1458 DCHECK(RelocInfo::IsCodeTarget(rmode)); 1459 EMIT(0xE9); 1460 emit(code, rmode); 1461} 1462 1463 1464void Assembler::j(Condition cc, Label* L, Label::Distance distance) { 1465 EnsureSpace ensure_space(this); 1466 DCHECK(0 <= cc && static_cast<int>(cc) < 16); 1467 if (L->is_bound()) { 1468 const int short_size = 2; 1469 const int long_size = 6; 1470 int offs = L->pos() - pc_offset(); 1471 DCHECK(offs <= 0); 1472 if (is_int8(offs - short_size)) { 1473 // 0111 tttn #8-bit disp 1474 EMIT(0x70 | cc); 1475 EMIT((offs - short_size) & 0xFF); 1476 } else { 1477 // 0000 1111 1000 tttn #32-bit disp 1478 EMIT(0x0F); 1479 EMIT(0x80 | cc); 1480 emit(offs - long_size); 1481 } 1482 } else if (distance == Label::kNear) { 1483 EMIT(0x70 | cc); 1484 emit_near_disp(L); 1485 } else { 1486 // 0000 1111 1000 tttn #32-bit disp 1487 // Note: could eliminate cond. jumps to this jump if condition 1488 // is the same however, seems to be rather unlikely case. 1489 EMIT(0x0F); 1490 EMIT(0x80 | cc); 1491 emit_disp(L, Displacement::OTHER); 1492 } 1493} 1494 1495 1496void Assembler::j(Condition cc, byte* entry, RelocInfo::Mode rmode) { 1497 EnsureSpace ensure_space(this); 1498 DCHECK((0 <= cc) && (static_cast<int>(cc) < 16)); 1499 // 0000 1111 1000 tttn #32-bit disp. 1500 EMIT(0x0F); 1501 EMIT(0x80 | cc); 1502 if (RelocInfo::IsRuntimeEntry(rmode)) { 1503 emit(reinterpret_cast<uint32_t>(entry), rmode); 1504 } else { 1505 emit(entry - (pc_ + sizeof(int32_t)), rmode); 1506 } 1507} 1508 1509 1510void Assembler::j(Condition cc, Handle<Code> code) { 1511 EnsureSpace ensure_space(this); 1512 // 0000 1111 1000 tttn #32-bit disp 1513 EMIT(0x0F); 1514 EMIT(0x80 | cc); 1515 emit(code, RelocInfo::CODE_TARGET); 1516} 1517 1518 1519// FPU instructions. 1520 1521void Assembler::fld(int i) { 1522 EnsureSpace ensure_space(this); 1523 emit_farith(0xD9, 0xC0, i); 1524} 1525 1526 1527void Assembler::fstp(int i) { 1528 EnsureSpace ensure_space(this); 1529 emit_farith(0xDD, 0xD8, i); 1530} 1531 1532 1533void Assembler::fld1() { 1534 EnsureSpace ensure_space(this); 1535 EMIT(0xD9); 1536 EMIT(0xE8); 1537} 1538 1539 1540void Assembler::fldpi() { 1541 EnsureSpace ensure_space(this); 1542 EMIT(0xD9); 1543 EMIT(0xEB); 1544} 1545 1546 1547void Assembler::fldz() { 1548 EnsureSpace ensure_space(this); 1549 EMIT(0xD9); 1550 EMIT(0xEE); 1551} 1552 1553 1554void Assembler::fldln2() { 1555 EnsureSpace ensure_space(this); 1556 EMIT(0xD9); 1557 EMIT(0xED); 1558} 1559 1560 1561void Assembler::fld_s(const Operand& adr) { 1562 EnsureSpace ensure_space(this); 1563 EMIT(0xD9); 1564 emit_operand(eax, adr); 1565} 1566 1567 1568void Assembler::fld_d(const Operand& adr) { 1569 EnsureSpace ensure_space(this); 1570 EMIT(0xDD); 1571 emit_operand(eax, adr); 1572} 1573 1574 1575void Assembler::fstp_s(const Operand& adr) { 1576 EnsureSpace ensure_space(this); 1577 EMIT(0xD9); 1578 emit_operand(ebx, adr); 1579} 1580 1581 1582void Assembler::fst_s(const Operand& adr) { 1583 EnsureSpace ensure_space(this); 1584 EMIT(0xD9); 1585 emit_operand(edx, adr); 1586} 1587 1588 1589void Assembler::fstp_d(const Operand& adr) { 1590 EnsureSpace ensure_space(this); 1591 EMIT(0xDD); 1592 emit_operand(ebx, adr); 1593} 1594 1595 1596void Assembler::fst_d(const Operand& adr) { 1597 EnsureSpace ensure_space(this); 1598 EMIT(0xDD); 1599 emit_operand(edx, adr); 1600} 1601 1602 1603void Assembler::fild_s(const Operand& adr) { 1604 EnsureSpace ensure_space(this); 1605 EMIT(0xDB); 1606 emit_operand(eax, adr); 1607} 1608 1609 1610void Assembler::fild_d(const Operand& adr) { 1611 EnsureSpace ensure_space(this); 1612 EMIT(0xDF); 1613 emit_operand(ebp, adr); 1614} 1615 1616 1617void Assembler::fistp_s(const Operand& adr) { 1618 EnsureSpace ensure_space(this); 1619 EMIT(0xDB); 1620 emit_operand(ebx, adr); 1621} 1622 1623 1624void Assembler::fisttp_s(const Operand& adr) { 1625 DCHECK(IsEnabled(SSE3)); 1626 EnsureSpace ensure_space(this); 1627 EMIT(0xDB); 1628 emit_operand(ecx, adr); 1629} 1630 1631 1632void Assembler::fisttp_d(const Operand& adr) { 1633 DCHECK(IsEnabled(SSE3)); 1634 EnsureSpace ensure_space(this); 1635 EMIT(0xDD); 1636 emit_operand(ecx, adr); 1637} 1638 1639 1640void Assembler::fist_s(const Operand& adr) { 1641 EnsureSpace ensure_space(this); 1642 EMIT(0xDB); 1643 emit_operand(edx, adr); 1644} 1645 1646 1647void Assembler::fistp_d(const Operand& adr) { 1648 EnsureSpace ensure_space(this); 1649 EMIT(0xDF); 1650 emit_operand(edi, adr); 1651} 1652 1653 1654void Assembler::fabs() { 1655 EnsureSpace ensure_space(this); 1656 EMIT(0xD9); 1657 EMIT(0xE1); 1658} 1659 1660 1661void Assembler::fchs() { 1662 EnsureSpace ensure_space(this); 1663 EMIT(0xD9); 1664 EMIT(0xE0); 1665} 1666 1667 1668void Assembler::fcos() { 1669 EnsureSpace ensure_space(this); 1670 EMIT(0xD9); 1671 EMIT(0xFF); 1672} 1673 1674 1675void Assembler::fsin() { 1676 EnsureSpace ensure_space(this); 1677 EMIT(0xD9); 1678 EMIT(0xFE); 1679} 1680 1681 1682void Assembler::fptan() { 1683 EnsureSpace ensure_space(this); 1684 EMIT(0xD9); 1685 EMIT(0xF2); 1686} 1687 1688 1689void Assembler::fyl2x() { 1690 EnsureSpace ensure_space(this); 1691 EMIT(0xD9); 1692 EMIT(0xF1); 1693} 1694 1695 1696void Assembler::f2xm1() { 1697 EnsureSpace ensure_space(this); 1698 EMIT(0xD9); 1699 EMIT(0xF0); 1700} 1701 1702 1703void Assembler::fscale() { 1704 EnsureSpace ensure_space(this); 1705 EMIT(0xD9); 1706 EMIT(0xFD); 1707} 1708 1709 1710void Assembler::fninit() { 1711 EnsureSpace ensure_space(this); 1712 EMIT(0xDB); 1713 EMIT(0xE3); 1714} 1715 1716 1717void Assembler::fadd(int i) { 1718 EnsureSpace ensure_space(this); 1719 emit_farith(0xDC, 0xC0, i); 1720} 1721 1722 1723void Assembler::fadd_i(int i) { 1724 EnsureSpace ensure_space(this); 1725 emit_farith(0xD8, 0xC0, i); 1726} 1727 1728 1729void Assembler::fsub(int i) { 1730 EnsureSpace ensure_space(this); 1731 emit_farith(0xDC, 0xE8, i); 1732} 1733 1734 1735void Assembler::fsub_i(int i) { 1736 EnsureSpace ensure_space(this); 1737 emit_farith(0xD8, 0xE0, i); 1738} 1739 1740 1741void Assembler::fisub_s(const Operand& adr) { 1742 EnsureSpace ensure_space(this); 1743 EMIT(0xDA); 1744 emit_operand(esp, adr); 1745} 1746 1747 1748void Assembler::fmul_i(int i) { 1749 EnsureSpace ensure_space(this); 1750 emit_farith(0xD8, 0xC8, i); 1751} 1752 1753 1754void Assembler::fmul(int i) { 1755 EnsureSpace ensure_space(this); 1756 emit_farith(0xDC, 0xC8, i); 1757} 1758 1759 1760void Assembler::fdiv(int i) { 1761 EnsureSpace ensure_space(this); 1762 emit_farith(0xDC, 0xF8, i); 1763} 1764 1765 1766void Assembler::fdiv_i(int i) { 1767 EnsureSpace ensure_space(this); 1768 emit_farith(0xD8, 0xF0, i); 1769} 1770 1771 1772void Assembler::faddp(int i) { 1773 EnsureSpace ensure_space(this); 1774 emit_farith(0xDE, 0xC0, i); 1775} 1776 1777 1778void Assembler::fsubp(int i) { 1779 EnsureSpace ensure_space(this); 1780 emit_farith(0xDE, 0xE8, i); 1781} 1782 1783 1784void Assembler::fsubrp(int i) { 1785 EnsureSpace ensure_space(this); 1786 emit_farith(0xDE, 0xE0, i); 1787} 1788 1789 1790void Assembler::fmulp(int i) { 1791 EnsureSpace ensure_space(this); 1792 emit_farith(0xDE, 0xC8, i); 1793} 1794 1795 1796void Assembler::fdivp(int i) { 1797 EnsureSpace ensure_space(this); 1798 emit_farith(0xDE, 0xF8, i); 1799} 1800 1801 1802void Assembler::fprem() { 1803 EnsureSpace ensure_space(this); 1804 EMIT(0xD9); 1805 EMIT(0xF8); 1806} 1807 1808 1809void Assembler::fprem1() { 1810 EnsureSpace ensure_space(this); 1811 EMIT(0xD9); 1812 EMIT(0xF5); 1813} 1814 1815 1816void Assembler::fxch(int i) { 1817 EnsureSpace ensure_space(this); 1818 emit_farith(0xD9, 0xC8, i); 1819} 1820 1821 1822void Assembler::fincstp() { 1823 EnsureSpace ensure_space(this); 1824 EMIT(0xD9); 1825 EMIT(0xF7); 1826} 1827 1828 1829void Assembler::ffree(int i) { 1830 EnsureSpace ensure_space(this); 1831 emit_farith(0xDD, 0xC0, i); 1832} 1833 1834 1835void Assembler::ftst() { 1836 EnsureSpace ensure_space(this); 1837 EMIT(0xD9); 1838 EMIT(0xE4); 1839} 1840 1841 1842void Assembler::fucomp(int i) { 1843 EnsureSpace ensure_space(this); 1844 emit_farith(0xDD, 0xE8, i); 1845} 1846 1847 1848void Assembler::fucompp() { 1849 EnsureSpace ensure_space(this); 1850 EMIT(0xDA); 1851 EMIT(0xE9); 1852} 1853 1854 1855void Assembler::fucomi(int i) { 1856 EnsureSpace ensure_space(this); 1857 EMIT(0xDB); 1858 EMIT(0xE8 + i); 1859} 1860 1861 1862void Assembler::fucomip() { 1863 EnsureSpace ensure_space(this); 1864 EMIT(0xDF); 1865 EMIT(0xE9); 1866} 1867 1868 1869void Assembler::fcompp() { 1870 EnsureSpace ensure_space(this); 1871 EMIT(0xDE); 1872 EMIT(0xD9); 1873} 1874 1875 1876void Assembler::fnstsw_ax() { 1877 EnsureSpace ensure_space(this); 1878 EMIT(0xDF); 1879 EMIT(0xE0); 1880} 1881 1882 1883void Assembler::fwait() { 1884 EnsureSpace ensure_space(this); 1885 EMIT(0x9B); 1886} 1887 1888 1889void Assembler::frndint() { 1890 EnsureSpace ensure_space(this); 1891 EMIT(0xD9); 1892 EMIT(0xFC); 1893} 1894 1895 1896void Assembler::fnclex() { 1897 EnsureSpace ensure_space(this); 1898 EMIT(0xDB); 1899 EMIT(0xE2); 1900} 1901 1902 1903void Assembler::sahf() { 1904 EnsureSpace ensure_space(this); 1905 EMIT(0x9E); 1906} 1907 1908 1909void Assembler::setcc(Condition cc, Register reg) { 1910 DCHECK(reg.is_byte_register()); 1911 EnsureSpace ensure_space(this); 1912 EMIT(0x0F); 1913 EMIT(0x90 | cc); 1914 EMIT(0xC0 | reg.code()); 1915} 1916 1917 1918void Assembler::cvttss2si(Register dst, const Operand& src) { 1919 EnsureSpace ensure_space(this); 1920 EMIT(0xF3); 1921 EMIT(0x0F); 1922 EMIT(0x2C); 1923 emit_operand(dst, src); 1924} 1925 1926 1927void Assembler::cvttsd2si(Register dst, const Operand& src) { 1928 EnsureSpace ensure_space(this); 1929 EMIT(0xF2); 1930 EMIT(0x0F); 1931 EMIT(0x2C); 1932 emit_operand(dst, src); 1933} 1934 1935 1936void Assembler::cvtsd2si(Register dst, XMMRegister src) { 1937 EnsureSpace ensure_space(this); 1938 EMIT(0xF2); 1939 EMIT(0x0F); 1940 EMIT(0x2D); 1941 emit_sse_operand(dst, src); 1942} 1943 1944 1945void Assembler::cvtsi2sd(XMMRegister dst, const Operand& src) { 1946 EnsureSpace ensure_space(this); 1947 EMIT(0xF2); 1948 EMIT(0x0F); 1949 EMIT(0x2A); 1950 emit_sse_operand(dst, src); 1951} 1952 1953 1954void Assembler::cvtss2sd(XMMRegister dst, XMMRegister src) { 1955 EnsureSpace ensure_space(this); 1956 EMIT(0xF3); 1957 EMIT(0x0F); 1958 EMIT(0x5A); 1959 emit_sse_operand(dst, src); 1960} 1961 1962 1963void Assembler::cvtsd2ss(XMMRegister dst, XMMRegister src) { 1964 EnsureSpace ensure_space(this); 1965 EMIT(0xF2); 1966 EMIT(0x0F); 1967 EMIT(0x5A); 1968 emit_sse_operand(dst, src); 1969} 1970 1971 1972void Assembler::addsd(XMMRegister dst, XMMRegister src) { 1973 EnsureSpace ensure_space(this); 1974 EMIT(0xF2); 1975 EMIT(0x0F); 1976 EMIT(0x58); 1977 emit_sse_operand(dst, src); 1978} 1979 1980 1981void Assembler::addsd(XMMRegister dst, const Operand& src) { 1982 EnsureSpace ensure_space(this); 1983 EMIT(0xF2); 1984 EMIT(0x0F); 1985 EMIT(0x58); 1986 emit_sse_operand(dst, src); 1987} 1988 1989 1990void Assembler::mulsd(XMMRegister dst, XMMRegister src) { 1991 EnsureSpace ensure_space(this); 1992 EMIT(0xF2); 1993 EMIT(0x0F); 1994 EMIT(0x59); 1995 emit_sse_operand(dst, src); 1996} 1997 1998 1999void Assembler::mulsd(XMMRegister dst, const Operand& src) { 2000 EnsureSpace ensure_space(this); 2001 EMIT(0xF2); 2002 EMIT(0x0F); 2003 EMIT(0x59); 2004 emit_sse_operand(dst, src); 2005} 2006 2007 2008void Assembler::subsd(XMMRegister dst, XMMRegister src) { 2009 EnsureSpace ensure_space(this); 2010 EMIT(0xF2); 2011 EMIT(0x0F); 2012 EMIT(0x5C); 2013 emit_sse_operand(dst, src); 2014} 2015 2016 2017void Assembler::subsd(XMMRegister dst, const Operand& src) { 2018 EnsureSpace ensure_space(this); 2019 EMIT(0xF2); 2020 EMIT(0x0F); 2021 EMIT(0x5C); 2022 emit_sse_operand(dst, src); 2023} 2024 2025 2026void Assembler::divsd(XMMRegister dst, XMMRegister src) { 2027 EnsureSpace ensure_space(this); 2028 EMIT(0xF2); 2029 EMIT(0x0F); 2030 EMIT(0x5E); 2031 emit_sse_operand(dst, src); 2032} 2033 2034 2035void Assembler::xorpd(XMMRegister dst, XMMRegister src) { 2036 EnsureSpace ensure_space(this); 2037 EMIT(0x66); 2038 EMIT(0x0F); 2039 EMIT(0x57); 2040 emit_sse_operand(dst, src); 2041} 2042 2043 2044void Assembler::andps(XMMRegister dst, const Operand& src) { 2045 EnsureSpace ensure_space(this); 2046 EMIT(0x0F); 2047 EMIT(0x54); 2048 emit_sse_operand(dst, src); 2049} 2050 2051 2052void Assembler::orps(XMMRegister dst, const Operand& src) { 2053 EnsureSpace ensure_space(this); 2054 EMIT(0x0F); 2055 EMIT(0x56); 2056 emit_sse_operand(dst, src); 2057} 2058 2059 2060void Assembler::xorps(XMMRegister dst, const Operand& src) { 2061 EnsureSpace ensure_space(this); 2062 EMIT(0x0F); 2063 EMIT(0x57); 2064 emit_sse_operand(dst, src); 2065} 2066 2067 2068void Assembler::addps(XMMRegister dst, const Operand& src) { 2069 EnsureSpace ensure_space(this); 2070 EMIT(0x0F); 2071 EMIT(0x58); 2072 emit_sse_operand(dst, src); 2073} 2074 2075 2076void Assembler::subps(XMMRegister dst, const Operand& src) { 2077 EnsureSpace ensure_space(this); 2078 EMIT(0x0F); 2079 EMIT(0x5C); 2080 emit_sse_operand(dst, src); 2081} 2082 2083 2084void Assembler::mulps(XMMRegister dst, const Operand& src) { 2085 EnsureSpace ensure_space(this); 2086 EMIT(0x0F); 2087 EMIT(0x59); 2088 emit_sse_operand(dst, src); 2089} 2090 2091 2092void Assembler::divps(XMMRegister dst, const Operand& src) { 2093 EnsureSpace ensure_space(this); 2094 EMIT(0x0F); 2095 EMIT(0x5E); 2096 emit_sse_operand(dst, src); 2097} 2098 2099 2100void Assembler::sqrtsd(XMMRegister dst, XMMRegister src) { 2101 EnsureSpace ensure_space(this); 2102 EMIT(0xF2); 2103 EMIT(0x0F); 2104 EMIT(0x51); 2105 emit_sse_operand(dst, src); 2106} 2107 2108 2109void Assembler::sqrtsd(XMMRegister dst, const Operand& src) { 2110 EnsureSpace ensure_space(this); 2111 EMIT(0xF2); 2112 EMIT(0x0F); 2113 EMIT(0x51); 2114 emit_sse_operand(dst, src); 2115} 2116 2117 2118void Assembler::andpd(XMMRegister dst, XMMRegister src) { 2119 EnsureSpace ensure_space(this); 2120 EMIT(0x66); 2121 EMIT(0x0F); 2122 EMIT(0x54); 2123 emit_sse_operand(dst, src); 2124} 2125 2126 2127void Assembler::orpd(XMMRegister dst, XMMRegister src) { 2128 EnsureSpace ensure_space(this); 2129 EMIT(0x66); 2130 EMIT(0x0F); 2131 EMIT(0x56); 2132 emit_sse_operand(dst, src); 2133} 2134 2135 2136void Assembler::ucomisd(XMMRegister dst, const Operand& src) { 2137 EnsureSpace ensure_space(this); 2138 EMIT(0x66); 2139 EMIT(0x0F); 2140 EMIT(0x2E); 2141 emit_sse_operand(dst, src); 2142} 2143 2144 2145void Assembler::roundsd(XMMRegister dst, XMMRegister src, RoundingMode mode) { 2146 DCHECK(IsEnabled(SSE4_1)); 2147 EnsureSpace ensure_space(this); 2148 EMIT(0x66); 2149 EMIT(0x0F); 2150 EMIT(0x3A); 2151 EMIT(0x0B); 2152 emit_sse_operand(dst, src); 2153 // Mask precision exeption. 2154 EMIT(static_cast<byte>(mode) | 0x8); 2155} 2156 2157 2158void Assembler::movmskpd(Register dst, XMMRegister src) { 2159 EnsureSpace ensure_space(this); 2160 EMIT(0x66); 2161 EMIT(0x0F); 2162 EMIT(0x50); 2163 emit_sse_operand(dst, src); 2164} 2165 2166 2167void Assembler::movmskps(Register dst, XMMRegister src) { 2168 EnsureSpace ensure_space(this); 2169 EMIT(0x0F); 2170 EMIT(0x50); 2171 emit_sse_operand(dst, src); 2172} 2173 2174 2175void Assembler::pcmpeqd(XMMRegister dst, XMMRegister src) { 2176 EnsureSpace ensure_space(this); 2177 EMIT(0x66); 2178 EMIT(0x0F); 2179 EMIT(0x76); 2180 emit_sse_operand(dst, src); 2181} 2182 2183 2184void Assembler::cmpltsd(XMMRegister dst, XMMRegister src) { 2185 EnsureSpace ensure_space(this); 2186 EMIT(0xF2); 2187 EMIT(0x0F); 2188 EMIT(0xC2); 2189 emit_sse_operand(dst, src); 2190 EMIT(1); // LT == 1 2191} 2192 2193 2194void Assembler::movaps(XMMRegister dst, XMMRegister src) { 2195 EnsureSpace ensure_space(this); 2196 EMIT(0x0F); 2197 EMIT(0x28); 2198 emit_sse_operand(dst, src); 2199} 2200 2201 2202void Assembler::shufps(XMMRegister dst, XMMRegister src, byte imm8) { 2203 DCHECK(is_uint8(imm8)); 2204 EnsureSpace ensure_space(this); 2205 EMIT(0x0F); 2206 EMIT(0xC6); 2207 emit_sse_operand(dst, src); 2208 EMIT(imm8); 2209} 2210 2211 2212void Assembler::movdqa(const Operand& dst, XMMRegister src) { 2213 EnsureSpace ensure_space(this); 2214 EMIT(0x66); 2215 EMIT(0x0F); 2216 EMIT(0x7F); 2217 emit_sse_operand(src, dst); 2218} 2219 2220 2221void Assembler::movdqa(XMMRegister dst, const Operand& src) { 2222 EnsureSpace ensure_space(this); 2223 EMIT(0x66); 2224 EMIT(0x0F); 2225 EMIT(0x6F); 2226 emit_sse_operand(dst, src); 2227} 2228 2229 2230void Assembler::movdqu(const Operand& dst, XMMRegister src ) { 2231 EnsureSpace ensure_space(this); 2232 EMIT(0xF3); 2233 EMIT(0x0F); 2234 EMIT(0x7F); 2235 emit_sse_operand(src, dst); 2236} 2237 2238 2239void Assembler::movdqu(XMMRegister dst, const Operand& src) { 2240 EnsureSpace ensure_space(this); 2241 EMIT(0xF3); 2242 EMIT(0x0F); 2243 EMIT(0x6F); 2244 emit_sse_operand(dst, src); 2245} 2246 2247 2248void Assembler::movntdqa(XMMRegister dst, const Operand& src) { 2249 DCHECK(IsEnabled(SSE4_1)); 2250 EnsureSpace ensure_space(this); 2251 EMIT(0x66); 2252 EMIT(0x0F); 2253 EMIT(0x38); 2254 EMIT(0x2A); 2255 emit_sse_operand(dst, src); 2256} 2257 2258 2259void Assembler::movntdq(const Operand& dst, XMMRegister src) { 2260 EnsureSpace ensure_space(this); 2261 EMIT(0x66); 2262 EMIT(0x0F); 2263 EMIT(0xE7); 2264 emit_sse_operand(src, dst); 2265} 2266 2267 2268void Assembler::prefetch(const Operand& src, int level) { 2269 DCHECK(is_uint2(level)); 2270 EnsureSpace ensure_space(this); 2271 EMIT(0x0F); 2272 EMIT(0x18); 2273 // Emit hint number in Reg position of RegR/M. 2274 XMMRegister code = XMMRegister::from_code(level); 2275 emit_sse_operand(code, src); 2276} 2277 2278 2279void Assembler::movsd(const Operand& dst, XMMRegister src ) { 2280 EnsureSpace ensure_space(this); 2281 EMIT(0xF2); // double 2282 EMIT(0x0F); 2283 EMIT(0x11); // store 2284 emit_sse_operand(src, dst); 2285} 2286 2287 2288void Assembler::movsd(XMMRegister dst, const Operand& src) { 2289 EnsureSpace ensure_space(this); 2290 EMIT(0xF2); // double 2291 EMIT(0x0F); 2292 EMIT(0x10); // load 2293 emit_sse_operand(dst, src); 2294} 2295 2296 2297void Assembler::movss(const Operand& dst, XMMRegister src ) { 2298 EnsureSpace ensure_space(this); 2299 EMIT(0xF3); // float 2300 EMIT(0x0F); 2301 EMIT(0x11); // store 2302 emit_sse_operand(src, dst); 2303} 2304 2305 2306void Assembler::movss(XMMRegister dst, const Operand& src) { 2307 EnsureSpace ensure_space(this); 2308 EMIT(0xF3); // float 2309 EMIT(0x0F); 2310 EMIT(0x10); // load 2311 emit_sse_operand(dst, src); 2312} 2313 2314 2315void Assembler::movd(XMMRegister dst, const Operand& src) { 2316 EnsureSpace ensure_space(this); 2317 EMIT(0x66); 2318 EMIT(0x0F); 2319 EMIT(0x6E); 2320 emit_sse_operand(dst, src); 2321} 2322 2323 2324void Assembler::movd(const Operand& dst, XMMRegister src) { 2325 EnsureSpace ensure_space(this); 2326 EMIT(0x66); 2327 EMIT(0x0F); 2328 EMIT(0x7E); 2329 emit_sse_operand(src, dst); 2330} 2331 2332 2333void Assembler::extractps(Register dst, XMMRegister src, byte imm8) { 2334 DCHECK(IsEnabled(SSE4_1)); 2335 DCHECK(is_uint8(imm8)); 2336 EnsureSpace ensure_space(this); 2337 EMIT(0x66); 2338 EMIT(0x0F); 2339 EMIT(0x3A); 2340 EMIT(0x17); 2341 emit_sse_operand(src, dst); 2342 EMIT(imm8); 2343} 2344 2345 2346void Assembler::pand(XMMRegister dst, XMMRegister src) { 2347 EnsureSpace ensure_space(this); 2348 EMIT(0x66); 2349 EMIT(0x0F); 2350 EMIT(0xDB); 2351 emit_sse_operand(dst, src); 2352} 2353 2354 2355void Assembler::pxor(XMMRegister dst, XMMRegister src) { 2356 EnsureSpace ensure_space(this); 2357 EMIT(0x66); 2358 EMIT(0x0F); 2359 EMIT(0xEF); 2360 emit_sse_operand(dst, src); 2361} 2362 2363 2364void Assembler::por(XMMRegister dst, XMMRegister src) { 2365 EnsureSpace ensure_space(this); 2366 EMIT(0x66); 2367 EMIT(0x0F); 2368 EMIT(0xEB); 2369 emit_sse_operand(dst, src); 2370} 2371 2372 2373void Assembler::ptest(XMMRegister dst, XMMRegister src) { 2374 DCHECK(IsEnabled(SSE4_1)); 2375 EnsureSpace ensure_space(this); 2376 EMIT(0x66); 2377 EMIT(0x0F); 2378 EMIT(0x38); 2379 EMIT(0x17); 2380 emit_sse_operand(dst, src); 2381} 2382 2383 2384void Assembler::psllq(XMMRegister reg, int8_t shift) { 2385 EnsureSpace ensure_space(this); 2386 EMIT(0x66); 2387 EMIT(0x0F); 2388 EMIT(0x73); 2389 emit_sse_operand(esi, reg); // esi == 6 2390 EMIT(shift); 2391} 2392 2393 2394void Assembler::psllq(XMMRegister dst, XMMRegister src) { 2395 EnsureSpace ensure_space(this); 2396 EMIT(0x66); 2397 EMIT(0x0F); 2398 EMIT(0xF3); 2399 emit_sse_operand(dst, src); 2400} 2401 2402 2403void Assembler::psrlq(XMMRegister reg, int8_t shift) { 2404 EnsureSpace ensure_space(this); 2405 EMIT(0x66); 2406 EMIT(0x0F); 2407 EMIT(0x73); 2408 emit_sse_operand(edx, reg); // edx == 2 2409 EMIT(shift); 2410} 2411 2412 2413void Assembler::psrlq(XMMRegister dst, XMMRegister src) { 2414 EnsureSpace ensure_space(this); 2415 EMIT(0x66); 2416 EMIT(0x0F); 2417 EMIT(0xD3); 2418 emit_sse_operand(dst, src); 2419} 2420 2421 2422void Assembler::pshufd(XMMRegister dst, XMMRegister src, uint8_t shuffle) { 2423 EnsureSpace ensure_space(this); 2424 EMIT(0x66); 2425 EMIT(0x0F); 2426 EMIT(0x70); 2427 emit_sse_operand(dst, src); 2428 EMIT(shuffle); 2429} 2430 2431 2432void Assembler::pextrd(const Operand& dst, XMMRegister src, int8_t offset) { 2433 DCHECK(IsEnabled(SSE4_1)); 2434 EnsureSpace ensure_space(this); 2435 EMIT(0x66); 2436 EMIT(0x0F); 2437 EMIT(0x3A); 2438 EMIT(0x16); 2439 emit_sse_operand(src, dst); 2440 EMIT(offset); 2441} 2442 2443 2444void Assembler::pinsrd(XMMRegister dst, const Operand& src, int8_t offset) { 2445 DCHECK(IsEnabled(SSE4_1)); 2446 EnsureSpace ensure_space(this); 2447 EMIT(0x66); 2448 EMIT(0x0F); 2449 EMIT(0x3A); 2450 EMIT(0x22); 2451 emit_sse_operand(dst, src); 2452 EMIT(offset); 2453} 2454 2455 2456void Assembler::emit_sse_operand(XMMRegister reg, const Operand& adr) { 2457 Register ireg = { reg.code() }; 2458 emit_operand(ireg, adr); 2459} 2460 2461 2462void Assembler::emit_sse_operand(XMMRegister dst, XMMRegister src) { 2463 EMIT(0xC0 | dst.code() << 3 | src.code()); 2464} 2465 2466 2467void Assembler::emit_sse_operand(Register dst, XMMRegister src) { 2468 EMIT(0xC0 | dst.code() << 3 | src.code()); 2469} 2470 2471 2472void Assembler::emit_sse_operand(XMMRegister dst, Register src) { 2473 EMIT(0xC0 | (dst.code() << 3) | src.code()); 2474} 2475 2476 2477void Assembler::Print() { 2478 Disassembler::Decode(isolate(), stdout, buffer_, pc_); 2479} 2480 2481 2482void Assembler::RecordJSReturn() { 2483 positions_recorder()->WriteRecordedPositions(); 2484 EnsureSpace ensure_space(this); 2485 RecordRelocInfo(RelocInfo::JS_RETURN); 2486} 2487 2488 2489void Assembler::RecordDebugBreakSlot() { 2490 positions_recorder()->WriteRecordedPositions(); 2491 EnsureSpace ensure_space(this); 2492 RecordRelocInfo(RelocInfo::DEBUG_BREAK_SLOT); 2493} 2494 2495 2496void Assembler::RecordComment(const char* msg, bool force) { 2497 if (FLAG_code_comments || force) { 2498 EnsureSpace ensure_space(this); 2499 RecordRelocInfo(RelocInfo::COMMENT, reinterpret_cast<intptr_t>(msg)); 2500 } 2501} 2502 2503 2504void Assembler::GrowBuffer() { 2505 DCHECK(buffer_overflow()); 2506 if (!own_buffer_) FATAL("external code buffer is too small"); 2507 2508 // Compute new buffer size. 2509 CodeDesc desc; // the new buffer 2510 desc.buffer_size = 2 * buffer_size_; 2511 2512 // Some internal data structures overflow for very large buffers, 2513 // they must ensure that kMaximalBufferSize is not too large. 2514 if ((desc.buffer_size > kMaximalBufferSize) || 2515 (desc.buffer_size > isolate()->heap()->MaxOldGenerationSize())) { 2516 V8::FatalProcessOutOfMemory("Assembler::GrowBuffer"); 2517 } 2518 2519 // Set up new buffer. 2520 desc.buffer = NewArray<byte>(desc.buffer_size); 2521 desc.instr_size = pc_offset(); 2522 desc.reloc_size = (buffer_ + buffer_size_) - (reloc_info_writer.pos()); 2523 2524 // Clear the buffer in debug mode. Use 'int3' instructions to make 2525 // sure to get into problems if we ever run uninitialized code. 2526#ifdef DEBUG 2527 memset(desc.buffer, 0xCC, desc.buffer_size); 2528#endif 2529 2530 // Copy the data. 2531 int pc_delta = desc.buffer - buffer_; 2532 int rc_delta = (desc.buffer + desc.buffer_size) - (buffer_ + buffer_size_); 2533 MemMove(desc.buffer, buffer_, desc.instr_size); 2534 MemMove(rc_delta + reloc_info_writer.pos(), reloc_info_writer.pos(), 2535 desc.reloc_size); 2536 2537 // Switch buffers. 2538 DeleteArray(buffer_); 2539 buffer_ = desc.buffer; 2540 buffer_size_ = desc.buffer_size; 2541 pc_ += pc_delta; 2542 reloc_info_writer.Reposition(reloc_info_writer.pos() + rc_delta, 2543 reloc_info_writer.last_pc() + pc_delta); 2544 2545 // Relocate runtime entries. 2546 for (RelocIterator it(desc); !it.done(); it.next()) { 2547 RelocInfo::Mode rmode = it.rinfo()->rmode(); 2548 if (rmode == RelocInfo::INTERNAL_REFERENCE) { 2549 int32_t* p = reinterpret_cast<int32_t*>(it.rinfo()->pc()); 2550 if (*p != 0) { // 0 means uninitialized. 2551 *p += pc_delta; 2552 } 2553 } 2554 } 2555 2556 DCHECK(!buffer_overflow()); 2557} 2558 2559 2560void Assembler::emit_arith_b(int op1, int op2, Register dst, int imm8) { 2561 DCHECK(is_uint8(op1) && is_uint8(op2)); // wrong opcode 2562 DCHECK(is_uint8(imm8)); 2563 DCHECK((op1 & 0x01) == 0); // should be 8bit operation 2564 EMIT(op1); 2565 EMIT(op2 | dst.code()); 2566 EMIT(imm8); 2567} 2568 2569 2570void Assembler::emit_arith(int sel, Operand dst, const Immediate& x) { 2571 DCHECK((0 <= sel) && (sel <= 7)); 2572 Register ireg = { sel }; 2573 if (x.is_int8()) { 2574 EMIT(0x83); // using a sign-extended 8-bit immediate. 2575 emit_operand(ireg, dst); 2576 EMIT(x.x_ & 0xFF); 2577 } else if (dst.is_reg(eax)) { 2578 EMIT((sel << 3) | 0x05); // short form if the destination is eax. 2579 emit(x); 2580 } else { 2581 EMIT(0x81); // using a literal 32-bit immediate. 2582 emit_operand(ireg, dst); 2583 emit(x); 2584 } 2585} 2586 2587 2588void Assembler::emit_operand(Register reg, const Operand& adr) { 2589 const unsigned length = adr.len_; 2590 DCHECK(length > 0); 2591 2592 // Emit updated ModRM byte containing the given register. 2593 pc_[0] = (adr.buf_[0] & ~0x38) | (reg.code() << 3); 2594 2595 // Emit the rest of the encoded operand. 2596 for (unsigned i = 1; i < length; i++) pc_[i] = adr.buf_[i]; 2597 pc_ += length; 2598 2599 // Emit relocation information if necessary. 2600 if (length >= sizeof(int32_t) && !RelocInfo::IsNone(adr.rmode_)) { 2601 pc_ -= sizeof(int32_t); // pc_ must be *at* disp32 2602 RecordRelocInfo(adr.rmode_); 2603 pc_ += sizeof(int32_t); 2604 } 2605} 2606 2607 2608void Assembler::emit_farith(int b1, int b2, int i) { 2609 DCHECK(is_uint8(b1) && is_uint8(b2)); // wrong opcode 2610 DCHECK(0 <= i && i < 8); // illegal stack offset 2611 EMIT(b1); 2612 EMIT(b2 + i); 2613} 2614 2615 2616void Assembler::db(uint8_t data) { 2617 EnsureSpace ensure_space(this); 2618 EMIT(data); 2619} 2620 2621 2622void Assembler::dd(uint32_t data) { 2623 EnsureSpace ensure_space(this); 2624 emit(data); 2625} 2626 2627 2628void Assembler::RecordRelocInfo(RelocInfo::Mode rmode, intptr_t data) { 2629 DCHECK(!RelocInfo::IsNone(rmode)); 2630 // Don't record external references unless the heap will be serialized. 2631 if (rmode == RelocInfo::EXTERNAL_REFERENCE && 2632 !serializer_enabled() && !emit_debug_code()) { 2633 return; 2634 } 2635 RelocInfo rinfo(pc_, rmode, data, NULL); 2636 reloc_info_writer.Write(&rinfo); 2637} 2638 2639 2640Handle<ConstantPoolArray> Assembler::NewConstantPool(Isolate* isolate) { 2641 // No out-of-line constant pool support. 2642 DCHECK(!FLAG_enable_ool_constant_pool); 2643 return isolate->factory()->empty_constant_pool_array(); 2644} 2645 2646 2647void Assembler::PopulateConstantPool(ConstantPoolArray* constant_pool) { 2648 // No out-of-line constant pool support. 2649 DCHECK(!FLAG_enable_ool_constant_pool); 2650 return; 2651} 2652 2653 2654#ifdef GENERATED_CODE_COVERAGE 2655static FILE* coverage_log = NULL; 2656 2657 2658static void InitCoverageLog() { 2659 char* file_name = getenv("V8_GENERATED_CODE_COVERAGE_LOG"); 2660 if (file_name != NULL) { 2661 coverage_log = fopen(file_name, "aw+"); 2662 } 2663} 2664 2665 2666void LogGeneratedCodeCoverage(const char* file_line) { 2667 const char* return_address = (&file_line)[-1]; 2668 char* push_insn = const_cast<char*>(return_address - 12); 2669 push_insn[0] = 0xeb; // Relative branch insn. 2670 push_insn[1] = 13; // Skip over coverage insns. 2671 if (coverage_log != NULL) { 2672 fprintf(coverage_log, "%s\n", file_line); 2673 fflush(coverage_log); 2674 } 2675} 2676 2677#endif 2678 2679} } // namespace v8::internal 2680 2681#endif // V8_TARGET_ARCH_IA32 2682