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