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