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