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