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