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 are 6 // 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 distribution. 14 // 15 // - Neither the name of Sun Microsystems or the names of contributors may 16 // be used to endorse or promote products derived from this software without 17 // specific prior written permission. 18 // 19 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS 20 // IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 21 // THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22 // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 23 // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 24 // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 25 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 26 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 27 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 28 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 29 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 31 // The original source code covered by the above license above has been 32 // modified significantly by Google Inc. 33 // Copyright 2011 the V8 project authors. All rights reserved. 34 35 // A light-weight IA32 Assembler. 36 37 #ifndef V8_IA32_ASSEMBLER_IA32_H_ 38 #define V8_IA32_ASSEMBLER_IA32_H_ 39 40 #include "isolate.h" 41 #include "serialize.h" 42 43 namespace v8 { 44 namespace internal { 45 46 // CPU Registers. 47 // 48 // 1) We would prefer to use an enum, but enum values are assignment- 49 // compatible with int, which has caused code-generation bugs. 50 // 51 // 2) We would prefer to use a class instead of a struct but we don't like 52 // the register initialization to depend on the particular initialization 53 // order (which appears to be different on OS X, Linux, and Windows for the 54 // installed versions of C++ we tried). Using a struct permits C-style 55 // "initialization". Also, the Register objects cannot be const as this 56 // forces initialization stubs in MSVC, making us dependent on initialization 57 // order. 58 // 59 // 3) By not using an enum, we are possibly preventing the compiler from 60 // doing certain constant folds, which may significantly reduce the 61 // code generated for some assembly instructions (because they boil down 62 // to a few constants). If this is a problem, we could change the code 63 // such that we use an enum in optimized mode, and the struct in debug 64 // mode. This way we get the compile-time error checking in debug mode 65 // and best performance in optimized code. 66 // 67 struct Register { 68 static const int kNumAllocatableRegisters = 6; 69 static const int kNumRegisters = 8; 70 71 static inline const char* AllocationIndexToString(int index); 72 73 static inline int ToAllocationIndex(Register reg); 74 75 static inline Register FromAllocationIndex(int index); 76 77 static Register from_code(int code) { 78 Register r = { code }; 79 return r; 80 } 81 bool is_valid() const { return 0 <= code_ && code_ < kNumRegisters; } 82 bool is(Register reg) const { return code_ == reg.code_; } 83 // eax, ebx, ecx and edx are byte registers, the rest are not. 84 bool is_byte_register() const { return code_ <= 3; } 85 int code() const { 86 ASSERT(is_valid()); 87 return code_; 88 } 89 int bit() const { 90 ASSERT(is_valid()); 91 return 1 << code_; 92 } 93 94 // Unfortunately we can't make this private in a struct. 95 int code_; 96 }; 97 98 99 const Register eax = { 0 }; 100 const Register ecx = { 1 }; 101 const Register edx = { 2 }; 102 const Register ebx = { 3 }; 103 const Register esp = { 4 }; 104 const Register ebp = { 5 }; 105 const Register esi = { 6 }; 106 const Register edi = { 7 }; 107 const Register no_reg = { -1 }; 108 109 110 inline const char* Register::AllocationIndexToString(int index) { 111 ASSERT(index >= 0 && index < kNumAllocatableRegisters); 112 // This is the mapping of allocation indices to registers. 113 const char* const kNames[] = { "eax", "ecx", "edx", "ebx", "esi", "edi" }; 114 return kNames[index]; 115 } 116 117 118 inline int Register::ToAllocationIndex(Register reg) { 119 ASSERT(reg.is_valid() && !reg.is(esp) && !reg.is(ebp)); 120 return (reg.code() >= 6) ? reg.code() - 2 : reg.code(); 121 } 122 123 124 inline Register Register::FromAllocationIndex(int index) { 125 ASSERT(index >= 0 && index < kNumAllocatableRegisters); 126 return (index >= 4) ? from_code(index + 2) : from_code(index); 127 } 128 129 130 struct XMMRegister { 131 static const int kNumAllocatableRegisters = 7; 132 static const int kNumRegisters = 8; 133 134 static int ToAllocationIndex(XMMRegister reg) { 135 ASSERT(reg.code() != 0); 136 return reg.code() - 1; 137 } 138 139 static XMMRegister FromAllocationIndex(int index) { 140 ASSERT(index >= 0 && index < kNumAllocatableRegisters); 141 return from_code(index + 1); 142 } 143 144 static const char* AllocationIndexToString(int index) { 145 ASSERT(index >= 0 && index < kNumAllocatableRegisters); 146 const char* const names[] = { 147 "xmm1", 148 "xmm2", 149 "xmm3", 150 "xmm4", 151 "xmm5", 152 "xmm6", 153 "xmm7" 154 }; 155 return names[index]; 156 } 157 158 static XMMRegister from_code(int code) { 159 XMMRegister r = { code }; 160 return r; 161 } 162 163 bool is_valid() const { return 0 <= code_ && code_ < kNumRegisters; } 164 bool is(XMMRegister reg) const { return code_ == reg.code_; } 165 int code() const { 166 ASSERT(is_valid()); 167 return code_; 168 } 169 170 int code_; 171 }; 172 173 174 const XMMRegister xmm0 = { 0 }; 175 const XMMRegister xmm1 = { 1 }; 176 const XMMRegister xmm2 = { 2 }; 177 const XMMRegister xmm3 = { 3 }; 178 const XMMRegister xmm4 = { 4 }; 179 const XMMRegister xmm5 = { 5 }; 180 const XMMRegister xmm6 = { 6 }; 181 const XMMRegister xmm7 = { 7 }; 182 183 184 typedef XMMRegister DoubleRegister; 185 186 187 enum Condition { 188 // any value < 0 is considered no_condition 189 no_condition = -1, 190 191 overflow = 0, 192 no_overflow = 1, 193 below = 2, 194 above_equal = 3, 195 equal = 4, 196 not_equal = 5, 197 below_equal = 6, 198 above = 7, 199 negative = 8, 200 positive = 9, 201 parity_even = 10, 202 parity_odd = 11, 203 less = 12, 204 greater_equal = 13, 205 less_equal = 14, 206 greater = 15, 207 208 // aliases 209 carry = below, 210 not_carry = above_equal, 211 zero = equal, 212 not_zero = not_equal, 213 sign = negative, 214 not_sign = positive 215 }; 216 217 218 // Returns the equivalent of !cc. 219 // Negation of the default no_condition (-1) results in a non-default 220 // no_condition value (-2). As long as tests for no_condition check 221 // for condition < 0, this will work as expected. 222 inline Condition NegateCondition(Condition cc) { 223 return static_cast<Condition>(cc ^ 1); 224 } 225 226 227 // Corresponds to transposing the operands of a comparison. 228 inline Condition ReverseCondition(Condition cc) { 229 switch (cc) { 230 case below: 231 return above; 232 case above: 233 return below; 234 case above_equal: 235 return below_equal; 236 case below_equal: 237 return above_equal; 238 case less: 239 return greater; 240 case greater: 241 return less; 242 case greater_equal: 243 return less_equal; 244 case less_equal: 245 return greater_equal; 246 default: 247 return cc; 248 }; 249 } 250 251 252 enum Hint { 253 no_hint = 0, 254 not_taken = 0x2e, 255 taken = 0x3e 256 }; 257 258 259 // The result of negating a hint is as if the corresponding condition 260 // were negated by NegateCondition. That is, no_hint is mapped to 261 // itself and not_taken and taken are mapped to each other. 262 inline Hint NegateHint(Hint hint) { 263 return (hint == no_hint) 264 ? no_hint 265 : ((hint == not_taken) ? taken : not_taken); 266 } 267 268 269 // ----------------------------------------------------------------------------- 270 // Machine instruction Immediates 271 272 class Immediate BASE_EMBEDDED { 273 public: 274 inline explicit Immediate(int x); 275 inline explicit Immediate(const ExternalReference& ext); 276 inline explicit Immediate(Handle<Object> handle); 277 inline explicit Immediate(Smi* value); 278 inline explicit Immediate(Address addr); 279 280 static Immediate CodeRelativeOffset(Label* label) { 281 return Immediate(label); 282 } 283 284 bool is_zero() const { return x_ == 0 && rmode_ == RelocInfo::NONE; } 285 bool is_int8() const { 286 return -128 <= x_ && x_ < 128 && rmode_ == RelocInfo::NONE; 287 } 288 bool is_int16() const { 289 return -32768 <= x_ && x_ < 32768 && rmode_ == RelocInfo::NONE; 290 } 291 292 private: 293 inline explicit Immediate(Label* value); 294 295 int x_; 296 RelocInfo::Mode rmode_; 297 298 friend class Assembler; 299 friend class MacroAssembler; 300 }; 301 302 303 // ----------------------------------------------------------------------------- 304 // Machine instruction Operands 305 306 enum ScaleFactor { 307 times_1 = 0, 308 times_2 = 1, 309 times_4 = 2, 310 times_8 = 3, 311 times_int_size = times_4, 312 times_half_pointer_size = times_2, 313 times_pointer_size = times_4, 314 times_twice_pointer_size = times_8 315 }; 316 317 318 class Operand BASE_EMBEDDED { 319 public: 320 // reg 321 INLINE(explicit Operand(Register reg)); 322 323 // XMM reg 324 INLINE(explicit Operand(XMMRegister xmm_reg)); 325 326 // [disp/r] 327 INLINE(explicit Operand(int32_t disp, RelocInfo::Mode rmode)); 328 // disp only must always be relocated 329 330 // [base + disp/r] 331 explicit Operand(Register base, int32_t disp, 332 RelocInfo::Mode rmode = RelocInfo::NONE); 333 334 // [base + index*scale + disp/r] 335 explicit Operand(Register base, 336 Register index, 337 ScaleFactor scale, 338 int32_t disp, 339 RelocInfo::Mode rmode = RelocInfo::NONE); 340 341 // [index*scale + disp/r] 342 explicit Operand(Register index, 343 ScaleFactor scale, 344 int32_t disp, 345 RelocInfo::Mode rmode = RelocInfo::NONE); 346 347 static Operand StaticVariable(const ExternalReference& ext) { 348 return Operand(reinterpret_cast<int32_t>(ext.address()), 349 RelocInfo::EXTERNAL_REFERENCE); 350 } 351 352 static Operand StaticArray(Register index, 353 ScaleFactor scale, 354 const ExternalReference& arr) { 355 return Operand(index, scale, reinterpret_cast<int32_t>(arr.address()), 356 RelocInfo::EXTERNAL_REFERENCE); 357 } 358 359 static Operand Cell(Handle<JSGlobalPropertyCell> cell) { 360 return Operand(reinterpret_cast<int32_t>(cell.location()), 361 RelocInfo::GLOBAL_PROPERTY_CELL); 362 } 363 364 // Returns true if this Operand is a wrapper for the specified register. 365 bool is_reg(Register reg) const; 366 367 private: 368 byte buf_[6]; 369 // The number of bytes in buf_. 370 unsigned int len_; 371 // Only valid if len_ > 4. 372 RelocInfo::Mode rmode_; 373 374 // Set the ModRM byte without an encoded 'reg' register. The 375 // register is encoded later as part of the emit_operand operation. 376 inline void set_modrm(int mod, Register rm); 377 378 inline void set_sib(ScaleFactor scale, Register index, Register base); 379 inline void set_disp8(int8_t disp); 380 inline void set_dispr(int32_t disp, RelocInfo::Mode rmode); 381 382 friend class Assembler; 383 }; 384 385 386 // ----------------------------------------------------------------------------- 387 // A Displacement describes the 32bit immediate field of an instruction which 388 // may be used together with a Label in order to refer to a yet unknown code 389 // position. Displacements stored in the instruction stream are used to describe 390 // the instruction and to chain a list of instructions using the same Label. 391 // A Displacement contains 2 different fields: 392 // 393 // next field: position of next displacement in the chain (0 = end of list) 394 // type field: instruction type 395 // 396 // A next value of null (0) indicates the end of a chain (note that there can 397 // be no displacement at position zero, because there is always at least one 398 // instruction byte before the displacement). 399 // 400 // Displacement _data field layout 401 // 402 // |31.....2|1......0| 403 // [ next | type | 404 405 class Displacement BASE_EMBEDDED { 406 public: 407 enum Type { 408 UNCONDITIONAL_JUMP, 409 CODE_RELATIVE, 410 OTHER 411 }; 412 413 int data() const { return data_; } 414 Type type() const { return TypeField::decode(data_); } 415 void next(Label* L) const { 416 int n = NextField::decode(data_); 417 n > 0 ? L->link_to(n) : L->Unuse(); 418 } 419 void link_to(Label* L) { init(L, type()); } 420 421 explicit Displacement(int data) { data_ = data; } 422 423 Displacement(Label* L, Type type) { init(L, type); } 424 425 void print() { 426 PrintF("%s (%x) ", (type() == UNCONDITIONAL_JUMP ? "jmp" : "[other]"), 427 NextField::decode(data_)); 428 } 429 430 private: 431 int data_; 432 433 class TypeField: public BitField<Type, 0, 2> {}; 434 class NextField: public BitField<int, 2, 32-2> {}; 435 436 void init(Label* L, Type type); 437 }; 438 439 440 441 // CpuFeatures keeps track of which features are supported by the target CPU. 442 // Supported features must be enabled by a Scope before use. 443 // Example: 444 // if (CpuFeatures::IsSupported(SSE2)) { 445 // CpuFeatures::Scope fscope(SSE2); 446 // // Generate SSE2 floating point code. 447 // } else { 448 // // Generate standard x87 floating point code. 449 // } 450 class CpuFeatures : public AllStatic { 451 public: 452 // Detect features of the target CPU. Set safe defaults if the serializer 453 // is enabled (snapshots must be portable). 454 static void Probe(); 455 456 // Check whether a feature is supported by the target CPU. 457 static bool IsSupported(CpuFeature f) { 458 ASSERT(initialized_); 459 if (f == SSE2 && !FLAG_enable_sse2) return false; 460 if (f == SSE3 && !FLAG_enable_sse3) return false; 461 if (f == SSE4_1 && !FLAG_enable_sse4_1) return false; 462 if (f == CMOV && !FLAG_enable_cmov) return false; 463 if (f == RDTSC && !FLAG_enable_rdtsc) return false; 464 return (supported_ & (static_cast<uint64_t>(1) << f)) != 0; 465 } 466 467 #ifdef DEBUG 468 // Check whether a feature is currently enabled. 469 static bool IsEnabled(CpuFeature f) { 470 ASSERT(initialized_); 471 Isolate* isolate = Isolate::UncheckedCurrent(); 472 if (isolate == NULL) { 473 // When no isolate is available, work as if we're running in 474 // release mode. 475 return IsSupported(f); 476 } 477 uint64_t enabled = isolate->enabled_cpu_features(); 478 return (enabled & (static_cast<uint64_t>(1) << f)) != 0; 479 } 480 #endif 481 482 // Enable a specified feature within a scope. 483 class Scope BASE_EMBEDDED { 484 #ifdef DEBUG 485 public: 486 explicit Scope(CpuFeature f) { 487 uint64_t mask = static_cast<uint64_t>(1) << f; 488 ASSERT(CpuFeatures::IsSupported(f)); 489 ASSERT(!Serializer::enabled() || 490 (CpuFeatures::found_by_runtime_probing_ & mask) == 0); 491 isolate_ = Isolate::UncheckedCurrent(); 492 old_enabled_ = 0; 493 if (isolate_ != NULL) { 494 old_enabled_ = isolate_->enabled_cpu_features(); 495 isolate_->set_enabled_cpu_features(old_enabled_ | mask); 496 } 497 } 498 ~Scope() { 499 ASSERT_EQ(Isolate::UncheckedCurrent(), isolate_); 500 if (isolate_ != NULL) { 501 isolate_->set_enabled_cpu_features(old_enabled_); 502 } 503 } 504 private: 505 Isolate* isolate_; 506 uint64_t old_enabled_; 507 #else 508 public: 509 explicit Scope(CpuFeature f) {} 510 #endif 511 }; 512 513 class TryForceFeatureScope BASE_EMBEDDED { 514 public: 515 explicit TryForceFeatureScope(CpuFeature f) 516 : old_supported_(CpuFeatures::supported_) { 517 if (CanForce()) { 518 CpuFeatures::supported_ |= (static_cast<uint64_t>(1) << f); 519 } 520 } 521 522 ~TryForceFeatureScope() { 523 if (CanForce()) { 524 CpuFeatures::supported_ = old_supported_; 525 } 526 } 527 528 private: 529 static bool CanForce() { 530 // It's only safe to temporarily force support of CPU features 531 // when there's only a single isolate, which is guaranteed when 532 // the serializer is enabled. 533 return Serializer::enabled(); 534 } 535 536 const uint64_t old_supported_; 537 }; 538 539 private: 540 #ifdef DEBUG 541 static bool initialized_; 542 #endif 543 static uint64_t supported_; 544 static uint64_t found_by_runtime_probing_; 545 546 DISALLOW_COPY_AND_ASSIGN(CpuFeatures); 547 }; 548 549 550 class Assembler : public AssemblerBase { 551 private: 552 // We check before assembling an instruction that there is sufficient 553 // space to write an instruction and its relocation information. 554 // The relocation writer's position must be kGap bytes above the end of 555 // the generated instructions. This leaves enough space for the 556 // longest possible ia32 instruction, 15 bytes, and the longest possible 557 // relocation information encoding, RelocInfoWriter::kMaxLength == 16. 558 // (There is a 15 byte limit on ia32 instruction length that rules out some 559 // otherwise valid instructions.) 560 // This allows for a single, fast space check per instruction. 561 static const int kGap = 32; 562 563 public: 564 // Create an assembler. Instructions and relocation information are emitted 565 // into a buffer, with the instructions starting from the beginning and the 566 // relocation information starting from the end of the buffer. See CodeDesc 567 // for a detailed comment on the layout (globals.h). 568 // 569 // If the provided buffer is NULL, the assembler allocates and grows its own 570 // buffer, and buffer_size determines the initial buffer size. The buffer is 571 // owned by the assembler and deallocated upon destruction of the assembler. 572 // 573 // If the provided buffer is not NULL, the assembler uses the provided buffer 574 // for code generation and assumes its size to be buffer_size. If the buffer 575 // is too small, a fatal error occurs. No deallocation of the buffer is done 576 // upon destruction of the assembler. 577 // TODO(vitalyr): the assembler does not need an isolate. 578 Assembler(Isolate* isolate, void* buffer, int buffer_size); 579 ~Assembler(); 580 581 // Overrides the default provided by FLAG_debug_code. 582 void set_emit_debug_code(bool value) { emit_debug_code_ = value; } 583 584 // GetCode emits any pending (non-emitted) code and fills the descriptor 585 // desc. GetCode() is idempotent; it returns the same result if no other 586 // Assembler functions are invoked in between GetCode() calls. 587 void GetCode(CodeDesc* desc); 588 589 // Read/Modify the code target in the branch/call instruction at pc. 590 inline static Address target_address_at(Address pc); 591 inline static void set_target_address_at(Address pc, Address target); 592 593 // This sets the branch destination (which is in the instruction on x86). 594 // This is for calls and branches within generated code. 595 inline static void set_target_at(Address instruction_payload, 596 Address target) { 597 set_target_address_at(instruction_payload, target); 598 } 599 600 // This sets the branch destination (which is in the instruction on x86). 601 // This is for calls and branches to runtime code. 602 inline static void set_external_target_at(Address instruction_payload, 603 Address target) { 604 set_target_address_at(instruction_payload, target); 605 } 606 607 static const int kCallTargetSize = kPointerSize; 608 static const int kExternalTargetSize = kPointerSize; 609 610 // Distance between the address of the code target in the call instruction 611 // and the return address 612 static const int kCallTargetAddressOffset = kPointerSize; 613 // Distance between start of patched return sequence and the emitted address 614 // to jump to. 615 static const int kPatchReturnSequenceAddressOffset = 1; // JMP imm32. 616 617 // Distance between start of patched debug break slot and the emitted address 618 // to jump to. 619 static const int kPatchDebugBreakSlotAddressOffset = 1; // JMP imm32. 620 621 static const int kCallInstructionLength = 5; 622 static const int kJSReturnSequenceLength = 6; 623 624 // The debug break slot must be able to contain a call instruction. 625 static const int kDebugBreakSlotLength = kCallInstructionLength; 626 627 // One byte opcode for test eax,0xXXXXXXXX. 628 static const byte kTestEaxByte = 0xA9; 629 // One byte opcode for test al, 0xXX. 630 static const byte kTestAlByte = 0xA8; 631 // One byte opcode for nop. 632 static const byte kNopByte = 0x90; 633 634 // One byte opcode for a short unconditional jump. 635 static const byte kJmpShortOpcode = 0xEB; 636 // One byte prefix for a short conditional jump. 637 static const byte kJccShortPrefix = 0x70; 638 static const byte kJncShortOpcode = kJccShortPrefix | not_carry; 639 static const byte kJcShortOpcode = kJccShortPrefix | carry; 640 641 // --------------------------------------------------------------------------- 642 // Code generation 643 // 644 // - function names correspond one-to-one to ia32 instruction mnemonics 645 // - unless specified otherwise, instructions operate on 32bit operands 646 // - instructions on 8bit (byte) operands/registers have a trailing '_b' 647 // - instructions on 16bit (word) operands/registers have a trailing '_w' 648 // - naming conflicts with C++ keywords are resolved via a trailing '_' 649 650 // NOTE ON INTERFACE: Currently, the interface is not very consistent 651 // in the sense that some operations (e.g. mov()) can be called in more 652 // the one way to generate the same instruction: The Register argument 653 // can in some cases be replaced with an Operand(Register) argument. 654 // This should be cleaned up and made more orthogonal. The questions 655 // is: should we always use Operands instead of Registers where an 656 // Operand is possible, or should we have a Register (overloaded) form 657 // instead? We must be careful to make sure that the selected instruction 658 // is obvious from the parameters to avoid hard-to-find code generation 659 // bugs. 660 661 // Insert the smallest number of nop instructions 662 // possible to align the pc offset to a multiple 663 // of m. m must be a power of 2. 664 void Align(int m); 665 // Aligns code to something that's optimal for a jump target for the platform. 666 void CodeTargetAlign(); 667 668 // Stack 669 void pushad(); 670 void popad(); 671 672 void pushfd(); 673 void popfd(); 674 675 void push(const Immediate& x); 676 void push_imm32(int32_t imm32); 677 void push(Register src); 678 void push(const Operand& src); 679 680 void pop(Register dst); 681 void pop(const Operand& dst); 682 683 void enter(const Immediate& size); 684 void leave(); 685 686 // Moves 687 void mov_b(Register dst, const Operand& src); 688 void mov_b(const Operand& dst, int8_t imm8); 689 void mov_b(const Operand& dst, Register src); 690 691 void mov_w(Register dst, const Operand& src); 692 void mov_w(const Operand& dst, Register src); 693 694 void mov(Register dst, int32_t imm32); 695 void mov(Register dst, const Immediate& x); 696 void mov(Register dst, Handle<Object> handle); 697 void mov(Register dst, const Operand& src); 698 void mov(Register dst, Register src); 699 void mov(const Operand& dst, const Immediate& x); 700 void mov(const Operand& dst, Handle<Object> handle); 701 void mov(const Operand& dst, Register src); 702 703 void movsx_b(Register dst, const Operand& src); 704 705 void movsx_w(Register dst, const Operand& src); 706 707 void movzx_b(Register dst, const Operand& src); 708 709 void movzx_w(Register dst, const Operand& src); 710 711 // Conditional moves 712 void cmov(Condition cc, Register dst, int32_t imm32); 713 void cmov(Condition cc, Register dst, Handle<Object> handle); 714 void cmov(Condition cc, Register dst, const Operand& src); 715 716 // Flag management. 717 void cld(); 718 719 // Repetitive string instructions. 720 void rep_movs(); 721 void rep_stos(); 722 void stos(); 723 724 // Exchange two registers 725 void xchg(Register dst, Register src); 726 727 // Arithmetics 728 void adc(Register dst, int32_t imm32); 729 void adc(Register dst, const Operand& src); 730 731 void add(Register dst, const Operand& src); 732 void add(const Operand& dst, const Immediate& x); 733 734 void and_(Register dst, int32_t imm32); 735 void and_(Register dst, const Immediate& x); 736 void and_(Register dst, const Operand& src); 737 void and_(const Operand& src, Register dst); 738 void and_(const Operand& dst, const Immediate& x); 739 740 void cmpb(const Operand& op, int8_t imm8); 741 void cmpb(Register src, const Operand& dst); 742 void cmpb(const Operand& dst, Register src); 743 void cmpb_al(const Operand& op); 744 void cmpw_ax(const Operand& op); 745 void cmpw(const Operand& op, Immediate imm16); 746 void cmp(Register reg, int32_t imm32); 747 void cmp(Register reg, Handle<Object> handle); 748 void cmp(Register reg, const Operand& op); 749 void cmp(const Operand& op, const Immediate& imm); 750 void cmp(const Operand& op, Handle<Object> handle); 751 752 void dec_b(Register dst); 753 void dec_b(const Operand& dst); 754 755 void dec(Register dst); 756 void dec(const Operand& dst); 757 758 void cdq(); 759 760 void idiv(Register src); 761 762 // Signed multiply instructions. 763 void imul(Register src); // edx:eax = eax * src. 764 void imul(Register dst, const Operand& src); // dst = dst * src. 765 void imul(Register dst, Register src, int32_t imm32); // dst = src * imm32. 766 767 void inc(Register dst); 768 void inc(const Operand& dst); 769 770 void lea(Register dst, const Operand& src); 771 772 // Unsigned multiply instruction. 773 void mul(Register src); // edx:eax = eax * reg. 774 775 void neg(Register dst); 776 777 void not_(Register dst); 778 779 void or_(Register dst, int32_t imm32); 780 void or_(Register dst, const Operand& src); 781 void or_(const Operand& dst, Register src); 782 void or_(const Operand& dst, const Immediate& x); 783 784 void rcl(Register dst, uint8_t imm8); 785 void rcr(Register dst, uint8_t imm8); 786 787 void sar(Register dst, uint8_t imm8); 788 void sar_cl(Register dst); 789 790 void sbb(Register dst, const Operand& src); 791 792 void shld(Register dst, const Operand& src); 793 794 void shl(Register dst, uint8_t imm8); 795 void shl_cl(Register dst); 796 797 void shrd(Register dst, const Operand& src); 798 799 void shr(Register dst, uint8_t imm8); 800 void shr_cl(Register dst); 801 802 void subb(const Operand& dst, int8_t imm8); 803 void subb(Register dst, const Operand& src); 804 void sub(const Operand& dst, const Immediate& x); 805 void sub(Register dst, const Operand& src); 806 void sub(const Operand& dst, Register src); 807 808 void test(Register reg, const Immediate& imm); 809 void test(Register reg, const Operand& op); 810 void test_b(Register reg, const Operand& op); 811 void test(const Operand& op, const Immediate& imm); 812 void test_b(const Operand& op, uint8_t imm8); 813 814 void xor_(Register dst, int32_t imm32); 815 void xor_(Register dst, const Operand& src); 816 void xor_(const Operand& src, Register dst); 817 void xor_(const Operand& dst, const Immediate& x); 818 819 // Bit operations. 820 void bt(const Operand& dst, Register src); 821 void bts(const Operand& dst, Register src); 822 823 // Miscellaneous 824 void hlt(); 825 void int3(); 826 void nop(); 827 void rdtsc(); 828 void ret(int imm16); 829 830 // Label operations & relative jumps (PPUM Appendix D) 831 // 832 // Takes a branch opcode (cc) and a label (L) and generates 833 // either a backward branch or a forward branch and links it 834 // to the label fixup chain. Usage: 835 // 836 // Label L; // unbound label 837 // j(cc, &L); // forward branch to unbound label 838 // bind(&L); // bind label to the current pc 839 // j(cc, &L); // backward branch to bound label 840 // bind(&L); // illegal: a label may be bound only once 841 // 842 // Note: The same Label can be used for forward and backward branches 843 // but it may be bound only once. 844 845 void bind(Label* L); // binds an unbound label L to the current code position 846 void bind(NearLabel* L); 847 848 // Calls 849 void call(Label* L); 850 void call(byte* entry, RelocInfo::Mode rmode); 851 void call(const Operand& adr); 852 void call(Handle<Code> code, RelocInfo::Mode rmode); 853 854 // Jumps 855 void jmp(Label* L); // unconditional jump to L 856 void jmp(byte* entry, RelocInfo::Mode rmode); 857 void jmp(const Operand& adr); 858 void jmp(Handle<Code> code, RelocInfo::Mode rmode); 859 860 // Short jump 861 void jmp(NearLabel* L); 862 863 // Conditional jumps 864 void j(Condition cc, Label* L, Hint hint = no_hint); 865 void j(Condition cc, byte* entry, RelocInfo::Mode rmode, Hint hint = no_hint); 866 void j(Condition cc, Handle<Code> code, Hint hint = no_hint); 867 868 // Conditional short jump 869 void j(Condition cc, NearLabel* L, Hint hint = no_hint); 870 871 // Floating-point operations 872 void fld(int i); 873 void fstp(int i); 874 875 void fld1(); 876 void fldz(); 877 void fldpi(); 878 void fldln2(); 879 880 void fld_s(const Operand& adr); 881 void fld_d(const Operand& adr); 882 883 void fstp_s(const Operand& adr); 884 void fstp_d(const Operand& adr); 885 void fst_d(const Operand& adr); 886 887 void fild_s(const Operand& adr); 888 void fild_d(const Operand& adr); 889 890 void fist_s(const Operand& adr); 891 892 void fistp_s(const Operand& adr); 893 void fistp_d(const Operand& adr); 894 895 // The fisttp instructions require SSE3. 896 void fisttp_s(const Operand& adr); 897 void fisttp_d(const Operand& adr); 898 899 void fabs(); 900 void fchs(); 901 void fcos(); 902 void fsin(); 903 void fyl2x(); 904 905 void fadd(int i); 906 void fsub(int i); 907 void fmul(int i); 908 void fdiv(int i); 909 910 void fisub_s(const Operand& adr); 911 912 void faddp(int i = 1); 913 void fsubp(int i = 1); 914 void fsubrp(int i = 1); 915 void fmulp(int i = 1); 916 void fdivp(int i = 1); 917 void fprem(); 918 void fprem1(); 919 920 void fxch(int i = 1); 921 void fincstp(); 922 void ffree(int i = 0); 923 924 void ftst(); 925 void fucomp(int i); 926 void fucompp(); 927 void fucomi(int i); 928 void fucomip(); 929 void fcompp(); 930 void fnstsw_ax(); 931 void fwait(); 932 void fnclex(); 933 934 void frndint(); 935 936 void sahf(); 937 void setcc(Condition cc, Register reg); 938 939 void cpuid(); 940 941 // SSE2 instructions 942 void cvttss2si(Register dst, const Operand& src); 943 void cvttsd2si(Register dst, const Operand& src); 944 945 void cvtsi2sd(XMMRegister dst, const Operand& src); 946 void cvtss2sd(XMMRegister dst, XMMRegister src); 947 void cvtsd2ss(XMMRegister dst, XMMRegister src); 948 949 void addsd(XMMRegister dst, XMMRegister src); 950 void subsd(XMMRegister dst, XMMRegister src); 951 void mulsd(XMMRegister dst, XMMRegister src); 952 void divsd(XMMRegister dst, XMMRegister src); 953 void xorpd(XMMRegister dst, XMMRegister src); 954 void sqrtsd(XMMRegister dst, XMMRegister src); 955 956 void andpd(XMMRegister dst, XMMRegister src); 957 958 void ucomisd(XMMRegister dst, XMMRegister src); 959 void movmskpd(Register dst, XMMRegister src); 960 961 void cmpltsd(XMMRegister dst, XMMRegister src); 962 963 void movaps(XMMRegister dst, XMMRegister src); 964 965 void movdqa(XMMRegister dst, const Operand& src); 966 void movdqa(const Operand& dst, XMMRegister src); 967 void movdqu(XMMRegister dst, const Operand& src); 968 void movdqu(const Operand& dst, XMMRegister src); 969 970 // Use either movsd or movlpd. 971 void movdbl(XMMRegister dst, const Operand& src); 972 void movdbl(const Operand& dst, XMMRegister src); 973 974 void movd(XMMRegister dst, const Operand& src); 975 void movd(const Operand& src, XMMRegister dst); 976 void movsd(XMMRegister dst, XMMRegister src); 977 978 void movss(XMMRegister dst, const Operand& src); 979 void movss(const Operand& src, XMMRegister dst); 980 void movss(XMMRegister dst, XMMRegister src); 981 982 void pand(XMMRegister dst, XMMRegister src); 983 void pxor(XMMRegister dst, XMMRegister src); 984 void por(XMMRegister dst, XMMRegister src); 985 void ptest(XMMRegister dst, XMMRegister src); 986 987 void psllq(XMMRegister reg, int8_t shift); 988 void psllq(XMMRegister dst, XMMRegister src); 989 void psrlq(XMMRegister reg, int8_t shift); 990 void psrlq(XMMRegister dst, XMMRegister src); 991 void pshufd(XMMRegister dst, XMMRegister src, int8_t shuffle); 992 void pextrd(const Operand& dst, XMMRegister src, int8_t offset); 993 void pinsrd(XMMRegister dst, const Operand& src, int8_t offset); 994 995 // Parallel XMM operations. 996 void movntdqa(XMMRegister src, const Operand& dst); 997 void movntdq(const Operand& dst, XMMRegister src); 998 // Prefetch src position into cache level. 999 // Level 1, 2 or 3 specifies CPU cache level. Level 0 specifies a 1000 // non-temporal 1001 void prefetch(const Operand& src, int level); 1002 // TODO(lrn): Need SFENCE for movnt? 1003 1004 // Debugging 1005 void Print(); 1006 1007 // Check the code size generated from label to here. 1008 int SizeOfCodeGeneratedSince(Label* l) { return pc_offset() - l->pos(); } 1009 1010 // Mark address of the ExitJSFrame code. 1011 void RecordJSReturn(); 1012 1013 // Mark address of a debug break slot. 1014 void RecordDebugBreakSlot(); 1015 1016 // Record a comment relocation entry that can be used by a disassembler. 1017 // Use --code-comments to enable, or provide "force = true" flag to always 1018 // write a comment. 1019 void RecordComment(const char* msg, bool force = false); 1020 1021 // Writes a single byte or word of data in the code stream. Used for 1022 // inline tables, e.g., jump-tables. 1023 void db(uint8_t data); 1024 void dd(uint32_t data); 1025 1026 int pc_offset() const { return pc_ - buffer_; } 1027 1028 // Check if there is less than kGap bytes available in the buffer. 1029 // If this is the case, we need to grow the buffer before emitting 1030 // an instruction or relocation information. 1031 inline bool overflow() const { return pc_ >= reloc_info_writer.pos() - kGap; } 1032 1033 // Get the number of bytes available in the buffer. 1034 inline int available_space() const { return reloc_info_writer.pos() - pc_; } 1035 1036 static bool IsNop(Address addr) { return *addr == 0x90; } 1037 1038 PositionsRecorder* positions_recorder() { return &positions_recorder_; } 1039 1040 int relocation_writer_size() { 1041 return (buffer_ + buffer_size_) - reloc_info_writer.pos(); 1042 } 1043 1044 // Avoid overflows for displacements etc. 1045 static const int kMaximalBufferSize = 512*MB; 1046 static const int kMinimalBufferSize = 4*KB; 1047 1048 protected: 1049 bool emit_debug_code() const { return emit_debug_code_; } 1050 1051 void movsd(XMMRegister dst, const Operand& src); 1052 void movsd(const Operand& dst, XMMRegister src); 1053 1054 void emit_sse_operand(XMMRegister reg, const Operand& adr); 1055 void emit_sse_operand(XMMRegister dst, XMMRegister src); 1056 void emit_sse_operand(Register dst, XMMRegister src); 1057 1058 byte* addr_at(int pos) { return buffer_ + pos; } 1059 1060 private: 1061 byte byte_at(int pos) { return buffer_[pos]; } 1062 void set_byte_at(int pos, byte value) { buffer_[pos] = value; } 1063 uint32_t long_at(int pos) { 1064 return *reinterpret_cast<uint32_t*>(addr_at(pos)); 1065 } 1066 void long_at_put(int pos, uint32_t x) { 1067 *reinterpret_cast<uint32_t*>(addr_at(pos)) = x; 1068 } 1069 1070 // code emission 1071 void GrowBuffer(); 1072 inline void emit(uint32_t x); 1073 inline void emit(Handle<Object> handle); 1074 inline void emit(uint32_t x, RelocInfo::Mode rmode); 1075 inline void emit(const Immediate& x); 1076 inline void emit_w(const Immediate& x); 1077 1078 // Emit the code-object-relative offset of the label's position 1079 inline void emit_code_relative_offset(Label* label); 1080 1081 // instruction generation 1082 void emit_arith_b(int op1, int op2, Register dst, int imm8); 1083 1084 // Emit a basic arithmetic instruction (i.e. first byte of the family is 0x81) 1085 // with a given destination expression and an immediate operand. It attempts 1086 // to use the shortest encoding possible. 1087 // sel specifies the /n in the modrm byte (see the Intel PRM). 1088 void emit_arith(int sel, Operand dst, const Immediate& x); 1089 1090 void emit_operand(Register reg, const Operand& adr); 1091 1092 void emit_farith(int b1, int b2, int i); 1093 1094 // labels 1095 void print(Label* L); 1096 void bind_to(Label* L, int pos); 1097 1098 // displacements 1099 inline Displacement disp_at(Label* L); 1100 inline void disp_at_put(Label* L, Displacement disp); 1101 inline void emit_disp(Label* L, Displacement::Type type); 1102 1103 // record reloc info for current pc_ 1104 void RecordRelocInfo(RelocInfo::Mode rmode, intptr_t data = 0); 1105 1106 friend class CodePatcher; 1107 friend class EnsureSpace; 1108 1109 // Code buffer: 1110 // The buffer into which code and relocation info are generated. 1111 byte* buffer_; 1112 int buffer_size_; 1113 // True if the assembler owns the buffer, false if buffer is external. 1114 bool own_buffer_; 1115 1116 // code generation 1117 byte* pc_; // the program counter; moves forward 1118 RelocInfoWriter reloc_info_writer; 1119 1120 // push-pop elimination 1121 byte* last_pc_; 1122 1123 PositionsRecorder positions_recorder_; 1124 1125 bool emit_debug_code_; 1126 1127 friend class PositionsRecorder; 1128 }; 1129 1130 1131 // Helper class that ensures that there is enough space for generating 1132 // instructions and relocation information. The constructor makes 1133 // sure that there is enough space and (in debug mode) the destructor 1134 // checks that we did not generate too much. 1135 class EnsureSpace BASE_EMBEDDED { 1136 public: 1137 explicit EnsureSpace(Assembler* assembler) : assembler_(assembler) { 1138 if (assembler_->overflow()) assembler_->GrowBuffer(); 1139 #ifdef DEBUG 1140 space_before_ = assembler_->available_space(); 1141 #endif 1142 } 1143 1144 #ifdef DEBUG 1145 ~EnsureSpace() { 1146 int bytes_generated = space_before_ - assembler_->available_space(); 1147 ASSERT(bytes_generated < assembler_->kGap); 1148 } 1149 #endif 1150 1151 private: 1152 Assembler* assembler_; 1153 #ifdef DEBUG 1154 int space_before_; 1155 #endif 1156 }; 1157 1158 } } // namespace v8::internal 1159 1160 #endif // V8_IA32_ASSEMBLER_IA32_H_ 1161