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