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 <deque> 41 42 #include "src/assembler.h" 43 #include "src/isolate.h" 44 #include "src/utils.h" 45 46 namespace v8 { 47 namespace internal { 48 49 #define GENERAL_REGISTERS(V) \ 50 V(eax) \ 51 V(ecx) \ 52 V(edx) \ 53 V(ebx) \ 54 V(esp) \ 55 V(ebp) \ 56 V(esi) \ 57 V(edi) 58 59 #define ALLOCATABLE_GENERAL_REGISTERS(V) \ 60 V(eax) \ 61 V(ecx) \ 62 V(edx) \ 63 V(ebx) \ 64 V(esi) \ 65 V(edi) 66 67 #define DOUBLE_REGISTERS(V) \ 68 V(xmm0) \ 69 V(xmm1) \ 70 V(xmm2) \ 71 V(xmm3) \ 72 V(xmm4) \ 73 V(xmm5) \ 74 V(xmm6) \ 75 V(xmm7) 76 77 #define FLOAT_REGISTERS DOUBLE_REGISTERS 78 #define SIMD128_REGISTERS DOUBLE_REGISTERS 79 80 #define ALLOCATABLE_DOUBLE_REGISTERS(V) \ 81 V(xmm1) \ 82 V(xmm2) \ 83 V(xmm3) \ 84 V(xmm4) \ 85 V(xmm5) \ 86 V(xmm6) \ 87 V(xmm7) 88 89 // CPU Registers. 90 // 91 // 1) We would prefer to use an enum, but enum values are assignment- 92 // compatible with int, which has caused code-generation bugs. 93 // 94 // 2) We would prefer to use a class instead of a struct but we don't like 95 // the register initialization to depend on the particular initialization 96 // order (which appears to be different on OS X, Linux, and Windows for the 97 // installed versions of C++ we tried). Using a struct permits C-style 98 // "initialization". Also, the Register objects cannot be const as this 99 // forces initialization stubs in MSVC, making us dependent on initialization 100 // order. 101 // 102 // 3) By not using an enum, we are possibly preventing the compiler from 103 // doing certain constant folds, which may significantly reduce the 104 // code generated for some assembly instructions (because they boil down 105 // to a few constants). If this is a problem, we could change the code 106 // such that we use an enum in optimized mode, and the struct in debug 107 // mode. This way we get the compile-time error checking in debug mode 108 // and best performance in optimized code. 109 // 110 struct Register { 111 enum Code { 112 #define REGISTER_CODE(R) kCode_##R, 113 GENERAL_REGISTERS(REGISTER_CODE) 114 #undef REGISTER_CODE 115 kAfterLast, 116 kCode_no_reg = -1 117 }; 118 119 static const int kNumRegisters = Code::kAfterLast; 120 121 static Register from_code(int code) { 122 DCHECK(code >= 0); 123 DCHECK(code < kNumRegisters); 124 Register r = {code}; 125 return r; 126 } 127 bool is_valid() const { return 0 <= reg_code && reg_code < kNumRegisters; } 128 bool is(Register reg) const { return reg_code == reg.reg_code; } 129 int code() const { 130 DCHECK(is_valid()); 131 return reg_code; 132 } 133 int bit() const { 134 DCHECK(is_valid()); 135 return 1 << reg_code; 136 } 137 138 bool is_byte_register() const { return reg_code <= 3; } 139 140 // Unfortunately we can't make this private in a struct. 141 int reg_code; 142 }; 143 144 145 #define DECLARE_REGISTER(R) const Register R = {Register::kCode_##R}; 146 GENERAL_REGISTERS(DECLARE_REGISTER) 147 #undef DECLARE_REGISTER 148 const Register no_reg = {Register::kCode_no_reg}; 149 150 static const bool kSimpleFPAliasing = true; 151 static const bool kSimdMaskRegisters = false; 152 153 struct XMMRegister { 154 enum Code { 155 #define REGISTER_CODE(R) kCode_##R, 156 DOUBLE_REGISTERS(REGISTER_CODE) 157 #undef REGISTER_CODE 158 kAfterLast, 159 kCode_no_reg = -1 160 }; 161 162 static const int kMaxNumRegisters = Code::kAfterLast; 163 164 static XMMRegister from_code(int code) { 165 XMMRegister result = {code}; 166 return result; 167 } 168 169 bool is_valid() const { return 0 <= reg_code && reg_code < kMaxNumRegisters; } 170 171 int code() const { 172 DCHECK(is_valid()); 173 return reg_code; 174 } 175 176 bool is(XMMRegister reg) const { return reg_code == reg.reg_code; } 177 178 int reg_code; 179 }; 180 181 typedef XMMRegister FloatRegister; 182 183 typedef XMMRegister DoubleRegister; 184 185 typedef XMMRegister Simd128Register; 186 187 #define DECLARE_REGISTER(R) \ 188 const DoubleRegister R = {DoubleRegister::kCode_##R}; 189 DOUBLE_REGISTERS(DECLARE_REGISTER) 190 #undef DECLARE_REGISTER 191 const DoubleRegister no_double_reg = {DoubleRegister::kCode_no_reg}; 192 193 enum Condition { 194 // any value < 0 is considered no_condition 195 no_condition = -1, 196 197 overflow = 0, 198 no_overflow = 1, 199 below = 2, 200 above_equal = 3, 201 equal = 4, 202 not_equal = 5, 203 below_equal = 6, 204 above = 7, 205 negative = 8, 206 positive = 9, 207 parity_even = 10, 208 parity_odd = 11, 209 less = 12, 210 greater_equal = 13, 211 less_equal = 14, 212 greater = 15, 213 214 // aliases 215 carry = below, 216 not_carry = above_equal, 217 zero = equal, 218 not_zero = not_equal, 219 sign = negative, 220 not_sign = positive 221 }; 222 223 224 // Returns the equivalent of !cc. 225 // Negation of the default no_condition (-1) results in a non-default 226 // no_condition value (-2). As long as tests for no_condition check 227 // for condition < 0, this will work as expected. 228 inline Condition NegateCondition(Condition cc) { 229 return static_cast<Condition>(cc ^ 1); 230 } 231 232 233 // Commute a condition such that {a cond b == b cond' a}. 234 inline Condition CommuteCondition(Condition cc) { 235 switch (cc) { 236 case below: 237 return above; 238 case above: 239 return below; 240 case above_equal: 241 return below_equal; 242 case below_equal: 243 return above_equal; 244 case less: 245 return greater; 246 case greater: 247 return less; 248 case greater_equal: 249 return less_equal; 250 case less_equal: 251 return greater_equal; 252 default: 253 return cc; 254 } 255 } 256 257 258 enum RoundingMode { 259 kRoundToNearest = 0x0, 260 kRoundDown = 0x1, 261 kRoundUp = 0x2, 262 kRoundToZero = 0x3 263 }; 264 265 266 // ----------------------------------------------------------------------------- 267 // Machine instruction Immediates 268 269 class Immediate BASE_EMBEDDED { 270 public: 271 inline explicit Immediate(int x); 272 inline explicit Immediate(const ExternalReference& ext); 273 inline explicit Immediate(Handle<Object> handle); 274 inline explicit Immediate(Smi* value); 275 inline explicit Immediate(Address addr); 276 inline explicit Immediate(Address x, RelocInfo::Mode rmode); 277 278 static Immediate CodeRelativeOffset(Label* label) { 279 return Immediate(label); 280 } 281 282 bool is_zero() const { return x_ == 0 && RelocInfo::IsNone(rmode_); } 283 bool is_int8() const { 284 return -128 <= x_ && x_ < 128 && RelocInfo::IsNone(rmode_); 285 } 286 bool is_uint8() const { 287 return v8::internal::is_uint8(x_) && RelocInfo::IsNone(rmode_); 288 } 289 bool is_int16() const { 290 return -32768 <= x_ && x_ < 32768 && RelocInfo::IsNone(rmode_); 291 } 292 bool is_uint16() const { 293 return v8::internal::is_uint16(x_) && RelocInfo::IsNone(rmode_); 294 } 295 296 private: 297 inline explicit Immediate(Label* value); 298 299 int x_; 300 RelocInfo::Mode rmode_; 301 302 friend class Operand; 303 friend class Assembler; 304 friend class MacroAssembler; 305 }; 306 307 308 // ----------------------------------------------------------------------------- 309 // Machine instruction Operands 310 311 enum ScaleFactor { 312 times_1 = 0, 313 times_2 = 1, 314 times_4 = 2, 315 times_8 = 3, 316 times_int_size = times_4, 317 times_half_pointer_size = times_2, 318 times_pointer_size = times_4, 319 times_twice_pointer_size = times_8 320 }; 321 322 323 class Operand BASE_EMBEDDED { 324 public: 325 // reg 326 INLINE(explicit Operand(Register reg)); 327 328 // XMM reg 329 INLINE(explicit Operand(XMMRegister xmm_reg)); 330 331 // [disp/r] 332 INLINE(explicit Operand(int32_t disp, RelocInfo::Mode rmode)); 333 334 // [disp/r] 335 INLINE(explicit Operand(Immediate imm)); 336 337 // [base + disp/r] 338 explicit Operand(Register base, int32_t disp, 339 RelocInfo::Mode rmode = RelocInfo::NONE32); 340 341 // [base + index*scale + disp/r] 342 explicit Operand(Register base, 343 Register index, 344 ScaleFactor scale, 345 int32_t disp, 346 RelocInfo::Mode rmode = RelocInfo::NONE32); 347 348 // [index*scale + disp/r] 349 explicit Operand(Register index, 350 ScaleFactor scale, 351 int32_t disp, 352 RelocInfo::Mode rmode = RelocInfo::NONE32); 353 354 static Operand JumpTable(Register index, ScaleFactor scale, Label* table) { 355 return Operand(index, scale, reinterpret_cast<int32_t>(table), 356 RelocInfo::INTERNAL_REFERENCE); 357 } 358 359 static Operand StaticVariable(const ExternalReference& ext) { 360 return Operand(reinterpret_cast<int32_t>(ext.address()), 361 RelocInfo::EXTERNAL_REFERENCE); 362 } 363 364 static Operand StaticArray(Register index, 365 ScaleFactor scale, 366 const ExternalReference& arr) { 367 return Operand(index, scale, reinterpret_cast<int32_t>(arr.address()), 368 RelocInfo::EXTERNAL_REFERENCE); 369 } 370 371 static Operand ForCell(Handle<Cell> cell) { 372 AllowDeferredHandleDereference embedding_raw_address; 373 return Operand(reinterpret_cast<int32_t>(cell.location()), 374 RelocInfo::CELL); 375 } 376 377 static Operand ForRegisterPlusImmediate(Register base, Immediate imm) { 378 return Operand(base, imm.x_, imm.rmode_); 379 } 380 381 // Returns true if this Operand is a wrapper for the specified register. 382 bool is_reg(Register reg) const; 383 384 // Returns true if this Operand is a wrapper for one register. 385 bool is_reg_only() const; 386 387 // Asserts that this Operand is a wrapper for one register and returns the 388 // register. 389 Register reg() const; 390 391 private: 392 // Set the ModRM byte without an encoded 'reg' register. The 393 // register is encoded later as part of the emit_operand operation. 394 inline void set_modrm(int mod, Register rm); 395 396 inline void set_sib(ScaleFactor scale, Register index, Register base); 397 inline void set_disp8(int8_t disp); 398 inline void set_dispr(int32_t disp, RelocInfo::Mode rmode); 399 400 byte buf_[6]; 401 // The number of bytes in buf_. 402 unsigned int len_; 403 // Only valid if len_ > 4. 404 RelocInfo::Mode rmode_; 405 406 friend class Assembler; 407 friend class MacroAssembler; 408 }; 409 410 411 // ----------------------------------------------------------------------------- 412 // A Displacement describes the 32bit immediate field of an instruction which 413 // may be used together with a Label in order to refer to a yet unknown code 414 // position. Displacements stored in the instruction stream are used to describe 415 // the instruction and to chain a list of instructions using the same Label. 416 // A Displacement contains 2 different fields: 417 // 418 // next field: position of next displacement in the chain (0 = end of list) 419 // type field: instruction type 420 // 421 // A next value of null (0) indicates the end of a chain (note that there can 422 // be no displacement at position zero, because there is always at least one 423 // instruction byte before the displacement). 424 // 425 // Displacement _data field layout 426 // 427 // |31.....2|1......0| 428 // [ next | type | 429 430 class Displacement BASE_EMBEDDED { 431 public: 432 enum Type { UNCONDITIONAL_JUMP, CODE_RELATIVE, OTHER, CODE_ABSOLUTE }; 433 434 int data() const { return data_; } 435 Type type() const { return TypeField::decode(data_); } 436 void next(Label* L) const { 437 int n = NextField::decode(data_); 438 n > 0 ? L->link_to(n) : L->Unuse(); 439 } 440 void link_to(Label* L) { init(L, type()); } 441 442 explicit Displacement(int data) { data_ = data; } 443 444 Displacement(Label* L, Type type) { init(L, type); } 445 446 void print() { 447 PrintF("%s (%x) ", (type() == UNCONDITIONAL_JUMP ? "jmp" : "[other]"), 448 NextField::decode(data_)); 449 } 450 451 private: 452 int data_; 453 454 class TypeField: public BitField<Type, 0, 2> {}; 455 class NextField: public BitField<int, 2, 32-2> {}; 456 457 void init(Label* L, Type type); 458 }; 459 460 461 class Assembler : public AssemblerBase { 462 private: 463 // We check before assembling an instruction that there is sufficient 464 // space to write an instruction and its relocation information. 465 // The relocation writer's position must be kGap bytes above the end of 466 // the generated instructions. This leaves enough space for the 467 // longest possible ia32 instruction, 15 bytes, and the longest possible 468 // relocation information encoding, RelocInfoWriter::kMaxLength == 16. 469 // (There is a 15 byte limit on ia32 instruction length that rules out some 470 // otherwise valid instructions.) 471 // This allows for a single, fast space check per instruction. 472 static const int kGap = 32; 473 474 public: 475 // Create an assembler. Instructions and relocation information are emitted 476 // into a buffer, with the instructions starting from the beginning and the 477 // relocation information starting from the end of the buffer. See CodeDesc 478 // for a detailed comment on the layout (globals.h). 479 // 480 // If the provided buffer is NULL, the assembler allocates and grows its own 481 // buffer, and buffer_size determines the initial buffer size. The buffer is 482 // owned by the assembler and deallocated upon destruction of the assembler. 483 // 484 // If the provided buffer is not NULL, the assembler uses the provided buffer 485 // for code generation and assumes its size to be buffer_size. If the buffer 486 // is too small, a fatal error occurs. No deallocation of the buffer is done 487 // upon destruction of the assembler. 488 // TODO(vitalyr): the assembler does not need an isolate. 489 Assembler(Isolate* isolate, void* buffer, int buffer_size); 490 virtual ~Assembler() { } 491 492 // GetCode emits any pending (non-emitted) code and fills the descriptor 493 // desc. GetCode() is idempotent; it returns the same result if no other 494 // Assembler functions are invoked in between GetCode() calls. 495 void GetCode(CodeDesc* desc); 496 497 // Read/Modify the code target in the branch/call instruction at pc. 498 inline static Address target_address_at(Address pc, Address constant_pool); 499 inline static void set_target_address_at( 500 Isolate* isolate, Address pc, Address constant_pool, Address target, 501 ICacheFlushMode icache_flush_mode = FLUSH_ICACHE_IF_NEEDED); 502 static inline Address target_address_at(Address pc, Code* code); 503 static inline void set_target_address_at( 504 Isolate* isolate, Address pc, Code* code, Address target, 505 ICacheFlushMode icache_flush_mode = FLUSH_ICACHE_IF_NEEDED); 506 507 // Return the code target address at a call site from the return address 508 // of that call in the instruction stream. 509 inline static Address target_address_from_return_address(Address pc); 510 511 // This sets the branch destination (which is in the instruction on x86). 512 // This is for calls and branches within generated code. 513 inline static void deserialization_set_special_target_at( 514 Isolate* isolate, Address instruction_payload, Code* code, 515 Address target) { 516 set_target_address_at(isolate, instruction_payload, code, target); 517 } 518 519 // This sets the internal reference at the pc. 520 inline static void deserialization_set_target_internal_reference_at( 521 Isolate* isolate, Address pc, Address target, 522 RelocInfo::Mode mode = RelocInfo::INTERNAL_REFERENCE); 523 524 static const int kSpecialTargetSize = kPointerSize; 525 526 // Distance between the address of the code target in the call instruction 527 // and the return address 528 static const int kCallTargetAddressOffset = kPointerSize; 529 530 static const int kCallInstructionLength = 5; 531 532 // The debug break slot must be able to contain a call instruction. 533 static const int kDebugBreakSlotLength = kCallInstructionLength; 534 535 // Distance between start of patched debug break slot and the emitted address 536 // to jump to. 537 static const int kPatchDebugBreakSlotAddressOffset = 1; // JMP imm32. 538 539 // One byte opcode for test al, 0xXX. 540 static const byte kTestAlByte = 0xA8; 541 // One byte opcode for nop. 542 static const byte kNopByte = 0x90; 543 544 // One byte opcode for a short unconditional jump. 545 static const byte kJmpShortOpcode = 0xEB; 546 // One byte prefix for a short conditional jump. 547 static const byte kJccShortPrefix = 0x70; 548 static const byte kJncShortOpcode = kJccShortPrefix | not_carry; 549 static const byte kJcShortOpcode = kJccShortPrefix | carry; 550 static const byte kJnzShortOpcode = kJccShortPrefix | not_zero; 551 static const byte kJzShortOpcode = kJccShortPrefix | zero; 552 553 554 // --------------------------------------------------------------------------- 555 // Code generation 556 // 557 // - function names correspond one-to-one to ia32 instruction mnemonics 558 // - unless specified otherwise, instructions operate on 32bit operands 559 // - instructions on 8bit (byte) operands/registers have a trailing '_b' 560 // - instructions on 16bit (word) operands/registers have a trailing '_w' 561 // - naming conflicts with C++ keywords are resolved via a trailing '_' 562 563 // NOTE ON INTERFACE: Currently, the interface is not very consistent 564 // in the sense that some operations (e.g. mov()) can be called in more 565 // the one way to generate the same instruction: The Register argument 566 // can in some cases be replaced with an Operand(Register) argument. 567 // This should be cleaned up and made more orthogonal. The questions 568 // is: should we always use Operands instead of Registers where an 569 // Operand is possible, or should we have a Register (overloaded) form 570 // instead? We must be careful to make sure that the selected instruction 571 // is obvious from the parameters to avoid hard-to-find code generation 572 // bugs. 573 574 // Insert the smallest number of nop instructions 575 // possible to align the pc offset to a multiple 576 // of m. m must be a power of 2. 577 void Align(int m); 578 // Insert the smallest number of zero bytes possible to align the pc offset 579 // to a mulitple of m. m must be a power of 2 (>= 2). 580 void DataAlign(int m); 581 void Nop(int bytes = 1); 582 // Aligns code to something that's optimal for a jump target for the platform. 583 void CodeTargetAlign(); 584 585 // Stack 586 void pushad(); 587 void popad(); 588 589 void pushfd(); 590 void popfd(); 591 592 void push(const Immediate& x); 593 void push_imm32(int32_t imm32); 594 void push(Register src); 595 void push(const Operand& src); 596 597 void pop(Register dst); 598 void pop(const Operand& dst); 599 600 void enter(const Immediate& size); 601 void leave(); 602 603 // Moves 604 void mov_b(Register dst, Register src) { mov_b(dst, Operand(src)); } 605 void mov_b(Register dst, const Operand& src); 606 void mov_b(Register dst, int8_t imm8) { mov_b(Operand(dst), imm8); } 607 void mov_b(const Operand& dst, int8_t src) { mov_b(dst, Immediate(src)); } 608 void mov_b(const Operand& dst, const Immediate& src); 609 void mov_b(const Operand& dst, Register src); 610 611 void mov_w(Register dst, const Operand& src); 612 void mov_w(const Operand& dst, int16_t src) { mov_w(dst, Immediate(src)); } 613 void mov_w(const Operand& dst, const Immediate& src); 614 void mov_w(const Operand& dst, Register src); 615 616 void mov(Register dst, int32_t imm32); 617 void mov(Register dst, const Immediate& x); 618 void mov(Register dst, Handle<Object> handle); 619 void mov(Register dst, const Operand& src); 620 void mov(Register dst, Register src); 621 void mov(const Operand& dst, const Immediate& x); 622 void mov(const Operand& dst, Handle<Object> handle); 623 void mov(const Operand& dst, Register src); 624 625 void movsx_b(Register dst, Register src) { movsx_b(dst, Operand(src)); } 626 void movsx_b(Register dst, const Operand& src); 627 628 void movsx_w(Register dst, Register src) { movsx_w(dst, Operand(src)); } 629 void movsx_w(Register dst, const Operand& src); 630 631 void movzx_b(Register dst, Register src) { movzx_b(dst, Operand(src)); } 632 void movzx_b(Register dst, const Operand& src); 633 634 void movzx_w(Register dst, Register src) { movzx_w(dst, Operand(src)); } 635 void movzx_w(Register dst, const Operand& src); 636 637 // Conditional moves 638 void cmov(Condition cc, Register dst, Register src) { 639 cmov(cc, dst, Operand(src)); 640 } 641 void cmov(Condition cc, Register dst, const Operand& src); 642 643 // Flag management. 644 void cld(); 645 646 // Repetitive string instructions. 647 void rep_movs(); 648 void rep_stos(); 649 void stos(); 650 651 // Exchange 652 void xchg(Register dst, Register src); 653 void xchg(Register dst, const Operand& src); 654 void xchg_b(Register reg, const Operand& op); 655 void xchg_w(Register reg, const Operand& op); 656 657 // Lock prefix 658 void lock(); 659 660 // CompareExchange 661 void cmpxchg(const Operand& dst, Register src); 662 void cmpxchg_b(const Operand& dst, Register src); 663 void cmpxchg_w(const Operand& dst, Register src); 664 665 // Arithmetics 666 void adc(Register dst, int32_t imm32); 667 void adc(Register dst, const Operand& src); 668 669 void add(Register dst, Register src) { add(dst, Operand(src)); } 670 void add(Register dst, const Operand& src); 671 void add(const Operand& dst, Register src); 672 void add(Register dst, const Immediate& imm) { add(Operand(dst), imm); } 673 void add(const Operand& dst, const Immediate& x); 674 675 void and_(Register dst, int32_t imm32); 676 void and_(Register dst, const Immediate& x); 677 void and_(Register dst, Register src) { and_(dst, Operand(src)); } 678 void and_(Register dst, const Operand& src); 679 void and_(const Operand& dst, Register src); 680 void and_(const Operand& dst, const Immediate& x); 681 682 void cmpb(Register reg, Immediate imm8) { cmpb(Operand(reg), imm8); } 683 void cmpb(const Operand& op, Immediate imm8); 684 void cmpb(Register reg, const Operand& op); 685 void cmpb(const Operand& op, Register reg); 686 void cmpb(Register dst, Register src) { cmpb(Operand(dst), src); } 687 void cmpb_al(const Operand& op); 688 void cmpw_ax(const Operand& op); 689 void cmpw(const Operand& dst, Immediate src); 690 void cmpw(Register dst, Immediate src) { cmpw(Operand(dst), src); } 691 void cmpw(Register dst, const Operand& src); 692 void cmpw(Register dst, Register src) { cmpw(Operand(dst), src); } 693 void cmpw(const Operand& dst, Register src); 694 void cmp(Register reg, int32_t imm32); 695 void cmp(Register reg, Handle<Object> handle); 696 void cmp(Register reg0, Register reg1) { cmp(reg0, Operand(reg1)); } 697 void cmp(Register reg, const Operand& op); 698 void cmp(Register reg, const Immediate& imm) { cmp(Operand(reg), imm); } 699 void cmp(const Operand& op, Register reg); 700 void cmp(const Operand& op, const Immediate& imm); 701 void cmp(const Operand& op, Handle<Object> handle); 702 703 void dec_b(Register dst); 704 void dec_b(const Operand& dst); 705 706 void dec(Register dst); 707 void dec(const Operand& dst); 708 709 void cdq(); 710 711 void idiv(Register src) { idiv(Operand(src)); } 712 void idiv(const Operand& src); 713 void div(Register src) { div(Operand(src)); } 714 void div(const Operand& src); 715 716 // Signed multiply instructions. 717 void imul(Register src); // edx:eax = eax * src. 718 void imul(Register dst, Register src) { imul(dst, Operand(src)); } 719 void imul(Register dst, const Operand& src); // dst = dst * src. 720 void imul(Register dst, Register src, int32_t imm32); // dst = src * imm32. 721 void imul(Register dst, const Operand& src, int32_t imm32); 722 723 void inc(Register dst); 724 void inc(const Operand& dst); 725 726 void lea(Register dst, const Operand& src); 727 728 // Unsigned multiply instruction. 729 void mul(Register src); // edx:eax = eax * reg. 730 731 void neg(Register dst); 732 void neg(const Operand& dst); 733 734 void not_(Register dst); 735 void not_(const Operand& dst); 736 737 void or_(Register dst, int32_t imm32); 738 void or_(Register dst, Register src) { or_(dst, Operand(src)); } 739 void or_(Register dst, const Operand& src); 740 void or_(const Operand& dst, Register src); 741 void or_(Register dst, const Immediate& imm) { or_(Operand(dst), imm); } 742 void or_(const Operand& dst, const Immediate& x); 743 744 void rcl(Register dst, uint8_t imm8); 745 void rcr(Register dst, uint8_t imm8); 746 747 void ror(Register dst, uint8_t imm8) { ror(Operand(dst), imm8); } 748 void ror(const Operand& dst, uint8_t imm8); 749 void ror_cl(Register dst) { ror_cl(Operand(dst)); } 750 void ror_cl(const Operand& dst); 751 752 void sar(Register dst, uint8_t imm8) { sar(Operand(dst), imm8); } 753 void sar(const Operand& dst, uint8_t imm8); 754 void sar_cl(Register dst) { sar_cl(Operand(dst)); } 755 void sar_cl(const Operand& dst); 756 757 void sbb(Register dst, const Operand& src); 758 759 void shl(Register dst, uint8_t imm8) { shl(Operand(dst), imm8); } 760 void shl(const Operand& dst, uint8_t imm8); 761 void shl_cl(Register dst) { shl_cl(Operand(dst)); } 762 void shl_cl(const Operand& dst); 763 void shld(Register dst, Register src, uint8_t shift); 764 void shld_cl(Register dst, Register src); 765 766 void shr(Register dst, uint8_t imm8) { shr(Operand(dst), imm8); } 767 void shr(const Operand& dst, uint8_t imm8); 768 void shr_cl(Register dst) { shr_cl(Operand(dst)); } 769 void shr_cl(const Operand& dst); 770 void shrd(Register dst, Register src, uint8_t shift); 771 void shrd_cl(Register dst, Register src) { shrd_cl(Operand(dst), src); } 772 void shrd_cl(const Operand& dst, Register src); 773 774 void sub(Register dst, const Immediate& imm) { sub(Operand(dst), imm); } 775 void sub(const Operand& dst, const Immediate& x); 776 void sub(Register dst, Register src) { sub(dst, Operand(src)); } 777 void sub(Register dst, const Operand& src); 778 void sub(const Operand& dst, Register src); 779 780 void test(Register reg, const Immediate& imm); 781 void test(Register reg0, Register reg1) { test(reg0, Operand(reg1)); } 782 void test(Register reg, const Operand& op); 783 void test(const Operand& op, const Immediate& imm); 784 void test(const Operand& op, Register reg) { test(reg, op); } 785 void test_b(Register reg, const Operand& op); 786 void test_b(Register reg, Immediate imm8); 787 void test_b(const Operand& op, Immediate imm8); 788 void test_b(const Operand& op, Register reg) { test_b(reg, op); } 789 void test_b(Register dst, Register src) { test_b(dst, Operand(src)); } 790 void test_w(Register reg, const Operand& op); 791 void test_w(Register reg, Immediate imm16); 792 void test_w(const Operand& op, Immediate imm16); 793 void test_w(const Operand& op, Register reg) { test_w(reg, op); } 794 void test_w(Register dst, Register src) { test_w(dst, Operand(src)); } 795 796 void xor_(Register dst, int32_t imm32); 797 void xor_(Register dst, Register src) { xor_(dst, Operand(src)); } 798 void xor_(Register dst, const Operand& src); 799 void xor_(const Operand& dst, Register src); 800 void xor_(Register dst, const Immediate& imm) { xor_(Operand(dst), imm); } 801 void xor_(const Operand& dst, const Immediate& x); 802 803 // Bit operations. 804 void bt(const Operand& dst, Register src); 805 void bts(Register dst, Register src) { bts(Operand(dst), src); } 806 void bts(const Operand& dst, Register src); 807 void bsr(Register dst, Register src) { bsr(dst, Operand(src)); } 808 void bsr(Register dst, const Operand& src); 809 void bsf(Register dst, Register src) { bsf(dst, Operand(src)); } 810 void bsf(Register dst, const Operand& src); 811 812 // Miscellaneous 813 void hlt(); 814 void int3(); 815 void nop(); 816 void ret(int imm16); 817 void ud2(); 818 819 // Label operations & relative jumps (PPUM Appendix D) 820 // 821 // Takes a branch opcode (cc) and a label (L) and generates 822 // either a backward branch or a forward branch and links it 823 // to the label fixup chain. Usage: 824 // 825 // Label L; // unbound label 826 // j(cc, &L); // forward branch to unbound label 827 // bind(&L); // bind label to the current pc 828 // j(cc, &L); // backward branch to bound label 829 // bind(&L); // illegal: a label may be bound only once 830 // 831 // Note: The same Label can be used for forward and backward branches 832 // but it may be bound only once. 833 834 void bind(Label* L); // binds an unbound label L to the current code position 835 836 // Calls 837 void call(Label* L); 838 void call(byte* entry, RelocInfo::Mode rmode); 839 int CallSize(const Operand& adr); 840 void call(Register reg) { call(Operand(reg)); } 841 void call(const Operand& adr); 842 int CallSize(Handle<Code> code, RelocInfo::Mode mode); 843 void call(Handle<Code> code, 844 RelocInfo::Mode rmode, 845 TypeFeedbackId id = TypeFeedbackId::None()); 846 847 // Jumps 848 // unconditional jump to L 849 void jmp(Label* L, Label::Distance distance = Label::kFar); 850 void jmp(byte* entry, RelocInfo::Mode rmode); 851 void jmp(Register reg) { jmp(Operand(reg)); } 852 void jmp(const Operand& adr); 853 void jmp(Handle<Code> code, RelocInfo::Mode rmode); 854 855 // Conditional jumps 856 void j(Condition cc, 857 Label* L, 858 Label::Distance distance = Label::kFar); 859 void j(Condition cc, byte* entry, RelocInfo::Mode rmode); 860 void j(Condition cc, Handle<Code> code, 861 RelocInfo::Mode rmode = RelocInfo::CODE_TARGET); 862 863 // Floating-point operations 864 void fld(int i); 865 void fstp(int i); 866 867 void fld1(); 868 void fldz(); 869 void fldpi(); 870 void fldln2(); 871 872 void fld_s(const Operand& adr); 873 void fld_d(const Operand& adr); 874 875 void fstp_s(const Operand& adr); 876 void fst_s(const Operand& adr); 877 void fstp_d(const Operand& adr); 878 void fst_d(const Operand& adr); 879 880 void fild_s(const Operand& adr); 881 void fild_d(const Operand& adr); 882 883 void fist_s(const Operand& adr); 884 885 void fistp_s(const Operand& adr); 886 void fistp_d(const Operand& adr); 887 888 // The fisttp instructions require SSE3. 889 void fisttp_s(const Operand& adr); 890 void fisttp_d(const Operand& adr); 891 892 void fabs(); 893 void fchs(); 894 void fcos(); 895 void fsin(); 896 void fptan(); 897 void fyl2x(); 898 void f2xm1(); 899 void fscale(); 900 void fninit(); 901 902 void fadd(int i); 903 void fadd_i(int i); 904 void fsub(int i); 905 void fsub_i(int i); 906 void fmul(int i); 907 void fmul_i(int i); 908 void fdiv(int i); 909 void fdiv_i(int i); 910 911 void fisub_s(const Operand& adr); 912 913 void faddp(int i = 1); 914 void fsubp(int i = 1); 915 void fsubrp(int i = 1); 916 void fmulp(int i = 1); 917 void fdivp(int i = 1); 918 void fprem(); 919 void fprem1(); 920 921 void fxch(int i = 1); 922 void fincstp(); 923 void ffree(int i = 0); 924 925 void ftst(); 926 void fucomp(int i); 927 void fucompp(); 928 void fucomi(int i); 929 void fucomip(); 930 void fcompp(); 931 void fnstsw_ax(); 932 void fwait(); 933 void fnclex(); 934 935 void frndint(); 936 937 void sahf(); 938 void setcc(Condition cc, Register reg); 939 940 void cpuid(); 941 942 // SSE instructions 943 void addss(XMMRegister dst, XMMRegister src) { addss(dst, Operand(src)); } 944 void addss(XMMRegister dst, const Operand& src); 945 void subss(XMMRegister dst, XMMRegister src) { subss(dst, Operand(src)); } 946 void subss(XMMRegister dst, const Operand& src); 947 void mulss(XMMRegister dst, XMMRegister src) { mulss(dst, Operand(src)); } 948 void mulss(XMMRegister dst, const Operand& src); 949 void divss(XMMRegister dst, XMMRegister src) { divss(dst, Operand(src)); } 950 void divss(XMMRegister dst, const Operand& src); 951 void sqrtss(XMMRegister dst, XMMRegister src) { sqrtss(dst, Operand(src)); } 952 void sqrtss(XMMRegister dst, const Operand& src); 953 954 void ucomiss(XMMRegister dst, XMMRegister src) { ucomiss(dst, Operand(src)); } 955 void ucomiss(XMMRegister dst, const Operand& src); 956 void movaps(XMMRegister dst, XMMRegister src); 957 void movups(XMMRegister dst, XMMRegister src); 958 void movups(XMMRegister dst, const Operand& src); 959 void movups(const Operand& dst, XMMRegister src); 960 void shufps(XMMRegister dst, XMMRegister src, byte imm8); 961 962 void maxss(XMMRegister dst, XMMRegister src) { maxss(dst, Operand(src)); } 963 void maxss(XMMRegister dst, const Operand& src); 964 void minss(XMMRegister dst, XMMRegister src) { minss(dst, Operand(src)); } 965 void minss(XMMRegister dst, const Operand& src); 966 967 void andps(XMMRegister dst, const Operand& src); 968 void andps(XMMRegister dst, XMMRegister src) { andps(dst, Operand(src)); } 969 void xorps(XMMRegister dst, const Operand& src); 970 void xorps(XMMRegister dst, XMMRegister src) { xorps(dst, Operand(src)); } 971 void orps(XMMRegister dst, const Operand& src); 972 void orps(XMMRegister dst, XMMRegister src) { orps(dst, Operand(src)); } 973 974 void addps(XMMRegister dst, const Operand& src); 975 void addps(XMMRegister dst, XMMRegister src) { addps(dst, Operand(src)); } 976 void subps(XMMRegister dst, const Operand& src); 977 void subps(XMMRegister dst, XMMRegister src) { subps(dst, Operand(src)); } 978 void mulps(XMMRegister dst, const Operand& src); 979 void mulps(XMMRegister dst, XMMRegister src) { mulps(dst, Operand(src)); } 980 void divps(XMMRegister dst, const Operand& src); 981 void divps(XMMRegister dst, XMMRegister src) { divps(dst, Operand(src)); } 982 983 // SSE2 instructions 984 void cvttss2si(Register dst, const Operand& src); 985 void cvttss2si(Register dst, XMMRegister src) { 986 cvttss2si(dst, Operand(src)); 987 } 988 void cvttsd2si(Register dst, const Operand& src); 989 void cvttsd2si(Register dst, XMMRegister src) { 990 cvttsd2si(dst, Operand(src)); 991 } 992 void cvtsd2si(Register dst, XMMRegister src); 993 994 void cvtsi2ss(XMMRegister dst, Register src) { cvtsi2ss(dst, Operand(src)); } 995 void cvtsi2ss(XMMRegister dst, const Operand& src); 996 void cvtsi2sd(XMMRegister dst, Register src) { cvtsi2sd(dst, Operand(src)); } 997 void cvtsi2sd(XMMRegister dst, const Operand& src); 998 void cvtss2sd(XMMRegister dst, const Operand& src); 999 void cvtss2sd(XMMRegister dst, XMMRegister src) { 1000 cvtss2sd(dst, Operand(src)); 1001 } 1002 void cvtsd2ss(XMMRegister dst, const Operand& src); 1003 void cvtsd2ss(XMMRegister dst, XMMRegister src) { 1004 cvtsd2ss(dst, Operand(src)); 1005 } 1006 void addsd(XMMRegister dst, XMMRegister src) { addsd(dst, Operand(src)); } 1007 void addsd(XMMRegister dst, const Operand& src); 1008 void subsd(XMMRegister dst, XMMRegister src) { subsd(dst, Operand(src)); } 1009 void subsd(XMMRegister dst, const Operand& src); 1010 void mulsd(XMMRegister dst, XMMRegister src) { mulsd(dst, Operand(src)); } 1011 void mulsd(XMMRegister dst, const Operand& src); 1012 void divsd(XMMRegister dst, XMMRegister src) { divsd(dst, Operand(src)); } 1013 void divsd(XMMRegister dst, const Operand& src); 1014 void xorpd(XMMRegister dst, XMMRegister src); 1015 void sqrtsd(XMMRegister dst, XMMRegister src) { sqrtsd(dst, Operand(src)); } 1016 void sqrtsd(XMMRegister dst, const Operand& src); 1017 1018 void andpd(XMMRegister dst, XMMRegister src); 1019 void orpd(XMMRegister dst, XMMRegister src); 1020 1021 void ucomisd(XMMRegister dst, XMMRegister src) { ucomisd(dst, Operand(src)); } 1022 void ucomisd(XMMRegister dst, const Operand& src); 1023 1024 void roundss(XMMRegister dst, XMMRegister src, RoundingMode mode); 1025 void roundsd(XMMRegister dst, XMMRegister src, RoundingMode mode); 1026 1027 void movmskpd(Register dst, XMMRegister src); 1028 void movmskps(Register dst, XMMRegister src); 1029 1030 void cmpltsd(XMMRegister dst, XMMRegister src); 1031 void pcmpeqd(XMMRegister dst, XMMRegister src); 1032 1033 void punpckldq(XMMRegister dst, XMMRegister src); 1034 void punpckhdq(XMMRegister dst, XMMRegister src); 1035 1036 void maxsd(XMMRegister dst, XMMRegister src) { maxsd(dst, Operand(src)); } 1037 void maxsd(XMMRegister dst, const Operand& src); 1038 void minsd(XMMRegister dst, XMMRegister src) { minsd(dst, Operand(src)); } 1039 void minsd(XMMRegister dst, const Operand& src); 1040 1041 void movdqa(XMMRegister dst, const Operand& src); 1042 void movdqa(const Operand& dst, XMMRegister src); 1043 void movdqu(XMMRegister dst, const Operand& src); 1044 void movdqu(const Operand& dst, XMMRegister src); 1045 void movdq(bool aligned, XMMRegister dst, const Operand& src) { 1046 if (aligned) { 1047 movdqa(dst, src); 1048 } else { 1049 movdqu(dst, src); 1050 } 1051 } 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) { movsd(dst, Operand(src)); } 1058 void movsd(XMMRegister dst, const Operand& src); 1059 void movsd(const Operand& dst, XMMRegister src); 1060 1061 1062 void movss(XMMRegister dst, const Operand& src); 1063 void movss(const Operand& dst, XMMRegister src); 1064 void movss(XMMRegister dst, XMMRegister src) { movss(dst, Operand(src)); } 1065 void extractps(Register dst, XMMRegister src, byte imm8); 1066 1067 void pand(XMMRegister dst, XMMRegister src); 1068 void pxor(XMMRegister dst, XMMRegister src); 1069 void por(XMMRegister dst, XMMRegister src); 1070 void ptest(XMMRegister dst, XMMRegister src); 1071 1072 void pslld(XMMRegister reg, int8_t shift); 1073 void psrld(XMMRegister reg, int8_t shift); 1074 void psllq(XMMRegister reg, int8_t shift); 1075 void psllq(XMMRegister dst, XMMRegister src); 1076 void psrlq(XMMRegister reg, int8_t shift); 1077 void psrlq(XMMRegister dst, XMMRegister src); 1078 void pshufd(XMMRegister dst, XMMRegister src, uint8_t shuffle); 1079 void pextrd(Register dst, XMMRegister src, int8_t offset) { 1080 pextrd(Operand(dst), src, offset); 1081 } 1082 void pextrd(const Operand& dst, XMMRegister src, int8_t offset); 1083 void pinsrd(XMMRegister dst, Register src, int8_t offset) { 1084 pinsrd(dst, Operand(src), offset); 1085 } 1086 void pinsrd(XMMRegister dst, const Operand& src, int8_t offset); 1087 1088 // AVX instructions 1089 void vfmadd132sd(XMMRegister dst, XMMRegister src1, XMMRegister src2) { 1090 vfmadd132sd(dst, src1, Operand(src2)); 1091 } 1092 void vfmadd213sd(XMMRegister dst, XMMRegister src1, XMMRegister src2) { 1093 vfmadd213sd(dst, src1, Operand(src2)); 1094 } 1095 void vfmadd231sd(XMMRegister dst, XMMRegister src1, XMMRegister src2) { 1096 vfmadd231sd(dst, src1, Operand(src2)); 1097 } 1098 void vfmadd132sd(XMMRegister dst, XMMRegister src1, const Operand& src2) { 1099 vfmasd(0x99, dst, src1, src2); 1100 } 1101 void vfmadd213sd(XMMRegister dst, XMMRegister src1, const Operand& src2) { 1102 vfmasd(0xa9, dst, src1, src2); 1103 } 1104 void vfmadd231sd(XMMRegister dst, XMMRegister src1, const Operand& src2) { 1105 vfmasd(0xb9, dst, src1, src2); 1106 } 1107 void vfmsub132sd(XMMRegister dst, XMMRegister src1, XMMRegister src2) { 1108 vfmsub132sd(dst, src1, Operand(src2)); 1109 } 1110 void vfmsub213sd(XMMRegister dst, XMMRegister src1, XMMRegister src2) { 1111 vfmsub213sd(dst, src1, Operand(src2)); 1112 } 1113 void vfmsub231sd(XMMRegister dst, XMMRegister src1, XMMRegister src2) { 1114 vfmsub231sd(dst, src1, Operand(src2)); 1115 } 1116 void vfmsub132sd(XMMRegister dst, XMMRegister src1, const Operand& src2) { 1117 vfmasd(0x9b, dst, src1, src2); 1118 } 1119 void vfmsub213sd(XMMRegister dst, XMMRegister src1, const Operand& src2) { 1120 vfmasd(0xab, dst, src1, src2); 1121 } 1122 void vfmsub231sd(XMMRegister dst, XMMRegister src1, const Operand& src2) { 1123 vfmasd(0xbb, dst, src1, src2); 1124 } 1125 void vfnmadd132sd(XMMRegister dst, XMMRegister src1, XMMRegister src2) { 1126 vfnmadd132sd(dst, src1, Operand(src2)); 1127 } 1128 void vfnmadd213sd(XMMRegister dst, XMMRegister src1, XMMRegister src2) { 1129 vfnmadd213sd(dst, src1, Operand(src2)); 1130 } 1131 void vfnmadd231sd(XMMRegister dst, XMMRegister src1, XMMRegister src2) { 1132 vfnmadd231sd(dst, src1, Operand(src2)); 1133 } 1134 void vfnmadd132sd(XMMRegister dst, XMMRegister src1, const Operand& src2) { 1135 vfmasd(0x9d, dst, src1, src2); 1136 } 1137 void vfnmadd213sd(XMMRegister dst, XMMRegister src1, const Operand& src2) { 1138 vfmasd(0xad, dst, src1, src2); 1139 } 1140 void vfnmadd231sd(XMMRegister dst, XMMRegister src1, const Operand& src2) { 1141 vfmasd(0xbd, dst, src1, src2); 1142 } 1143 void vfnmsub132sd(XMMRegister dst, XMMRegister src1, XMMRegister src2) { 1144 vfnmsub132sd(dst, src1, Operand(src2)); 1145 } 1146 void vfnmsub213sd(XMMRegister dst, XMMRegister src1, XMMRegister src2) { 1147 vfnmsub213sd(dst, src1, Operand(src2)); 1148 } 1149 void vfnmsub231sd(XMMRegister dst, XMMRegister src1, XMMRegister src2) { 1150 vfnmsub231sd(dst, src1, Operand(src2)); 1151 } 1152 void vfnmsub132sd(XMMRegister dst, XMMRegister src1, const Operand& src2) { 1153 vfmasd(0x9f, dst, src1, src2); 1154 } 1155 void vfnmsub213sd(XMMRegister dst, XMMRegister src1, const Operand& src2) { 1156 vfmasd(0xaf, dst, src1, src2); 1157 } 1158 void vfnmsub231sd(XMMRegister dst, XMMRegister src1, const Operand& src2) { 1159 vfmasd(0xbf, dst, src1, src2); 1160 } 1161 void vfmasd(byte op, XMMRegister dst, XMMRegister src1, const Operand& src2); 1162 1163 void vfmadd132ss(XMMRegister dst, XMMRegister src1, XMMRegister src2) { 1164 vfmadd132ss(dst, src1, Operand(src2)); 1165 } 1166 void vfmadd213ss(XMMRegister dst, XMMRegister src1, XMMRegister src2) { 1167 vfmadd213ss(dst, src1, Operand(src2)); 1168 } 1169 void vfmadd231ss(XMMRegister dst, XMMRegister src1, XMMRegister src2) { 1170 vfmadd231ss(dst, src1, Operand(src2)); 1171 } 1172 void vfmadd132ss(XMMRegister dst, XMMRegister src1, const Operand& src2) { 1173 vfmass(0x99, dst, src1, src2); 1174 } 1175 void vfmadd213ss(XMMRegister dst, XMMRegister src1, const Operand& src2) { 1176 vfmass(0xa9, dst, src1, src2); 1177 } 1178 void vfmadd231ss(XMMRegister dst, XMMRegister src1, const Operand& src2) { 1179 vfmass(0xb9, dst, src1, src2); 1180 } 1181 void vfmsub132ss(XMMRegister dst, XMMRegister src1, XMMRegister src2) { 1182 vfmsub132ss(dst, src1, Operand(src2)); 1183 } 1184 void vfmsub213ss(XMMRegister dst, XMMRegister src1, XMMRegister src2) { 1185 vfmsub213ss(dst, src1, Operand(src2)); 1186 } 1187 void vfmsub231ss(XMMRegister dst, XMMRegister src1, XMMRegister src2) { 1188 vfmsub231ss(dst, src1, Operand(src2)); 1189 } 1190 void vfmsub132ss(XMMRegister dst, XMMRegister src1, const Operand& src2) { 1191 vfmass(0x9b, dst, src1, src2); 1192 } 1193 void vfmsub213ss(XMMRegister dst, XMMRegister src1, const Operand& src2) { 1194 vfmass(0xab, dst, src1, src2); 1195 } 1196 void vfmsub231ss(XMMRegister dst, XMMRegister src1, const Operand& src2) { 1197 vfmass(0xbb, dst, src1, src2); 1198 } 1199 void vfnmadd132ss(XMMRegister dst, XMMRegister src1, XMMRegister src2) { 1200 vfnmadd132ss(dst, src1, Operand(src2)); 1201 } 1202 void vfnmadd213ss(XMMRegister dst, XMMRegister src1, XMMRegister src2) { 1203 vfnmadd213ss(dst, src1, Operand(src2)); 1204 } 1205 void vfnmadd231ss(XMMRegister dst, XMMRegister src1, XMMRegister src2) { 1206 vfnmadd231ss(dst, src1, Operand(src2)); 1207 } 1208 void vfnmadd132ss(XMMRegister dst, XMMRegister src1, const Operand& src2) { 1209 vfmass(0x9d, dst, src1, src2); 1210 } 1211 void vfnmadd213ss(XMMRegister dst, XMMRegister src1, const Operand& src2) { 1212 vfmass(0xad, dst, src1, src2); 1213 } 1214 void vfnmadd231ss(XMMRegister dst, XMMRegister src1, const Operand& src2) { 1215 vfmass(0xbd, dst, src1, src2); 1216 } 1217 void vfnmsub132ss(XMMRegister dst, XMMRegister src1, XMMRegister src2) { 1218 vfnmsub132ss(dst, src1, Operand(src2)); 1219 } 1220 void vfnmsub213ss(XMMRegister dst, XMMRegister src1, XMMRegister src2) { 1221 vfnmsub213ss(dst, src1, Operand(src2)); 1222 } 1223 void vfnmsub231ss(XMMRegister dst, XMMRegister src1, XMMRegister src2) { 1224 vfnmsub231ss(dst, src1, Operand(src2)); 1225 } 1226 void vfnmsub132ss(XMMRegister dst, XMMRegister src1, const Operand& src2) { 1227 vfmass(0x9f, dst, src1, src2); 1228 } 1229 void vfnmsub213ss(XMMRegister dst, XMMRegister src1, const Operand& src2) { 1230 vfmass(0xaf, dst, src1, src2); 1231 } 1232 void vfnmsub231ss(XMMRegister dst, XMMRegister src1, const Operand& src2) { 1233 vfmass(0xbf, dst, src1, src2); 1234 } 1235 void vfmass(byte op, XMMRegister dst, XMMRegister src1, const Operand& src2); 1236 1237 void vaddsd(XMMRegister dst, XMMRegister src1, XMMRegister src2) { 1238 vaddsd(dst, src1, Operand(src2)); 1239 } 1240 void vaddsd(XMMRegister dst, XMMRegister src1, const Operand& src2) { 1241 vsd(0x58, dst, src1, src2); 1242 } 1243 void vsubsd(XMMRegister dst, XMMRegister src1, XMMRegister src2) { 1244 vsubsd(dst, src1, Operand(src2)); 1245 } 1246 void vsubsd(XMMRegister dst, XMMRegister src1, const Operand& src2) { 1247 vsd(0x5c, dst, src1, src2); 1248 } 1249 void vmulsd(XMMRegister dst, XMMRegister src1, XMMRegister src2) { 1250 vmulsd(dst, src1, Operand(src2)); 1251 } 1252 void vmulsd(XMMRegister dst, XMMRegister src1, const Operand& src2) { 1253 vsd(0x59, dst, src1, src2); 1254 } 1255 void vdivsd(XMMRegister dst, XMMRegister src1, XMMRegister src2) { 1256 vdivsd(dst, src1, Operand(src2)); 1257 } 1258 void vdivsd(XMMRegister dst, XMMRegister src1, const Operand& src2) { 1259 vsd(0x5e, dst, src1, src2); 1260 } 1261 void vmaxsd(XMMRegister dst, XMMRegister src1, XMMRegister src2) { 1262 vmaxsd(dst, src1, Operand(src2)); 1263 } 1264 void vmaxsd(XMMRegister dst, XMMRegister src1, const Operand& src2) { 1265 vsd(0x5f, dst, src1, src2); 1266 } 1267 void vminsd(XMMRegister dst, XMMRegister src1, XMMRegister src2) { 1268 vminsd(dst, src1, Operand(src2)); 1269 } 1270 void vminsd(XMMRegister dst, XMMRegister src1, const Operand& src2) { 1271 vsd(0x5d, dst, src1, src2); 1272 } 1273 void vsd(byte op, XMMRegister dst, XMMRegister src1, const Operand& src2); 1274 1275 void vaddss(XMMRegister dst, XMMRegister src1, XMMRegister src2) { 1276 vaddss(dst, src1, Operand(src2)); 1277 } 1278 void vaddss(XMMRegister dst, XMMRegister src1, const Operand& src2) { 1279 vss(0x58, dst, src1, src2); 1280 } 1281 void vsubss(XMMRegister dst, XMMRegister src1, XMMRegister src2) { 1282 vsubss(dst, src1, Operand(src2)); 1283 } 1284 void vsubss(XMMRegister dst, XMMRegister src1, const Operand& src2) { 1285 vss(0x5c, dst, src1, src2); 1286 } 1287 void vmulss(XMMRegister dst, XMMRegister src1, XMMRegister src2) { 1288 vmulss(dst, src1, Operand(src2)); 1289 } 1290 void vmulss(XMMRegister dst, XMMRegister src1, const Operand& src2) { 1291 vss(0x59, dst, src1, src2); 1292 } 1293 void vdivss(XMMRegister dst, XMMRegister src1, XMMRegister src2) { 1294 vdivss(dst, src1, Operand(src2)); 1295 } 1296 void vdivss(XMMRegister dst, XMMRegister src1, const Operand& src2) { 1297 vss(0x5e, dst, src1, src2); 1298 } 1299 void vmaxss(XMMRegister dst, XMMRegister src1, XMMRegister src2) { 1300 vmaxss(dst, src1, Operand(src2)); 1301 } 1302 void vmaxss(XMMRegister dst, XMMRegister src1, const Operand& src2) { 1303 vss(0x5f, dst, src1, src2); 1304 } 1305 void vminss(XMMRegister dst, XMMRegister src1, XMMRegister src2) { 1306 vminss(dst, src1, Operand(src2)); 1307 } 1308 void vminss(XMMRegister dst, XMMRegister src1, const Operand& src2) { 1309 vss(0x5d, dst, src1, src2); 1310 } 1311 void vss(byte op, XMMRegister dst, XMMRegister src1, const Operand& src2); 1312 1313 // BMI instruction 1314 void andn(Register dst, Register src1, Register src2) { 1315 andn(dst, src1, Operand(src2)); 1316 } 1317 void andn(Register dst, Register src1, const Operand& src2) { 1318 bmi1(0xf2, dst, src1, src2); 1319 } 1320 void bextr(Register dst, Register src1, Register src2) { 1321 bextr(dst, Operand(src1), src2); 1322 } 1323 void bextr(Register dst, const Operand& src1, Register src2) { 1324 bmi1(0xf7, dst, src2, src1); 1325 } 1326 void blsi(Register dst, Register src) { blsi(dst, Operand(src)); } 1327 void blsi(Register dst, const Operand& src) { 1328 Register ireg = {3}; 1329 bmi1(0xf3, ireg, dst, src); 1330 } 1331 void blsmsk(Register dst, Register src) { blsmsk(dst, Operand(src)); } 1332 void blsmsk(Register dst, const Operand& src) { 1333 Register ireg = {2}; 1334 bmi1(0xf3, ireg, dst, src); 1335 } 1336 void blsr(Register dst, Register src) { blsr(dst, Operand(src)); } 1337 void blsr(Register dst, const Operand& src) { 1338 Register ireg = {1}; 1339 bmi1(0xf3, ireg, dst, src); 1340 } 1341 void tzcnt(Register dst, Register src) { tzcnt(dst, Operand(src)); } 1342 void tzcnt(Register dst, const Operand& src); 1343 1344 void lzcnt(Register dst, Register src) { lzcnt(dst, Operand(src)); } 1345 void lzcnt(Register dst, const Operand& src); 1346 1347 void popcnt(Register dst, Register src) { popcnt(dst, Operand(src)); } 1348 void popcnt(Register dst, const Operand& src); 1349 1350 void bzhi(Register dst, Register src1, Register src2) { 1351 bzhi(dst, Operand(src1), src2); 1352 } 1353 void bzhi(Register dst, const Operand& src1, Register src2) { 1354 bmi2(kNone, 0xf5, dst, src2, src1); 1355 } 1356 void mulx(Register dst1, Register dst2, Register src) { 1357 mulx(dst1, dst2, Operand(src)); 1358 } 1359 void mulx(Register dst1, Register dst2, const Operand& src) { 1360 bmi2(kF2, 0xf6, dst1, dst2, src); 1361 } 1362 void pdep(Register dst, Register src1, Register src2) { 1363 pdep(dst, src1, Operand(src2)); 1364 } 1365 void pdep(Register dst, Register src1, const Operand& src2) { 1366 bmi2(kF2, 0xf5, dst, src1, src2); 1367 } 1368 void pext(Register dst, Register src1, Register src2) { 1369 pext(dst, src1, Operand(src2)); 1370 } 1371 void pext(Register dst, Register src1, const Operand& src2) { 1372 bmi2(kF3, 0xf5, dst, src1, src2); 1373 } 1374 void sarx(Register dst, Register src1, Register src2) { 1375 sarx(dst, Operand(src1), src2); 1376 } 1377 void sarx(Register dst, const Operand& src1, Register src2) { 1378 bmi2(kF3, 0xf7, dst, src2, src1); 1379 } 1380 void shlx(Register dst, Register src1, Register src2) { 1381 shlx(dst, Operand(src1), src2); 1382 } 1383 void shlx(Register dst, const Operand& src1, Register src2) { 1384 bmi2(k66, 0xf7, dst, src2, src1); 1385 } 1386 void shrx(Register dst, Register src1, Register src2) { 1387 shrx(dst, Operand(src1), src2); 1388 } 1389 void shrx(Register dst, const Operand& src1, Register src2) { 1390 bmi2(kF2, 0xf7, dst, src2, src1); 1391 } 1392 void rorx(Register dst, Register src, byte imm8) { 1393 rorx(dst, Operand(src), imm8); 1394 } 1395 void rorx(Register dst, const Operand& src, byte imm8); 1396 1397 #define PACKED_OP_LIST(V) \ 1398 V(and, 0x54) \ 1399 V(xor, 0x57) 1400 1401 #define AVX_PACKED_OP_DECLARE(name, opcode) \ 1402 void v##name##ps(XMMRegister dst, XMMRegister src1, XMMRegister src2) { \ 1403 vps(opcode, dst, src1, Operand(src2)); \ 1404 } \ 1405 void v##name##ps(XMMRegister dst, XMMRegister src1, const Operand& src2) { \ 1406 vps(opcode, dst, src1, src2); \ 1407 } \ 1408 void v##name##pd(XMMRegister dst, XMMRegister src1, XMMRegister src2) { \ 1409 vpd(opcode, dst, src1, Operand(src2)); \ 1410 } \ 1411 void v##name##pd(XMMRegister dst, XMMRegister src1, const Operand& src2) { \ 1412 vpd(opcode, dst, src1, src2); \ 1413 } 1414 1415 PACKED_OP_LIST(AVX_PACKED_OP_DECLARE); 1416 void vps(byte op, XMMRegister dst, XMMRegister src1, XMMRegister src2); 1417 void vps(byte op, XMMRegister dst, XMMRegister src1, const Operand& src2); 1418 void vpd(byte op, XMMRegister dst, XMMRegister src1, XMMRegister src2); 1419 void vpd(byte op, XMMRegister dst, XMMRegister src1, const Operand& src2); 1420 1421 // Prefetch src position into cache level. 1422 // Level 1, 2 or 3 specifies CPU cache level. Level 0 specifies a 1423 // non-temporal 1424 void prefetch(const Operand& src, int level); 1425 // TODO(lrn): Need SFENCE for movnt? 1426 1427 // Check the code size generated from label to here. 1428 int SizeOfCodeGeneratedSince(Label* label) { 1429 return pc_offset() - label->pos(); 1430 } 1431 1432 // Mark address of a debug break slot. 1433 void RecordDebugBreakSlot(RelocInfo::Mode mode); 1434 1435 // Record a comment relocation entry that can be used by a disassembler. 1436 // Use --code-comments to enable. 1437 void RecordComment(const char* msg); 1438 1439 // Record a deoptimization reason that can be used by a log or cpu profiler. 1440 // Use --trace-deopt to enable. 1441 void RecordDeoptReason(DeoptimizeReason reason, SourcePosition position, 1442 int id); 1443 1444 // Writes a single byte or word of data in the code stream. Used for 1445 // inline tables, e.g., jump-tables. 1446 void db(uint8_t data); 1447 void dd(uint32_t data); 1448 void dq(uint64_t data); 1449 void dp(uintptr_t data) { dd(data); } 1450 void dd(Label* label); 1451 1452 // Check if there is less than kGap bytes available in the buffer. 1453 // If this is the case, we need to grow the buffer before emitting 1454 // an instruction or relocation information. 1455 inline bool buffer_overflow() const { 1456 return pc_ >= reloc_info_writer.pos() - kGap; 1457 } 1458 1459 // Get the number of bytes available in the buffer. 1460 inline int available_space() const { return reloc_info_writer.pos() - pc_; } 1461 1462 static bool IsNop(Address addr); 1463 1464 int relocation_writer_size() { 1465 return (buffer_ + buffer_size_) - reloc_info_writer.pos(); 1466 } 1467 1468 // Avoid overflows for displacements etc. 1469 static const int kMaximalBufferSize = 512*MB; 1470 1471 byte byte_at(int pos) { return buffer_[pos]; } 1472 void set_byte_at(int pos, byte value) { buffer_[pos] = value; } 1473 1474 void PatchConstantPoolAccessInstruction(int pc_offset, int offset, 1475 ConstantPoolEntry::Access access, 1476 ConstantPoolEntry::Type type) { 1477 // No embedded constant pool support. 1478 UNREACHABLE(); 1479 } 1480 1481 protected: 1482 void emit_sse_operand(XMMRegister reg, const Operand& adr); 1483 void emit_sse_operand(XMMRegister dst, XMMRegister src); 1484 void emit_sse_operand(Register dst, XMMRegister src); 1485 void emit_sse_operand(XMMRegister dst, Register src); 1486 1487 byte* addr_at(int pos) { return buffer_ + pos; } 1488 1489 1490 private: 1491 uint32_t long_at(int pos) { 1492 return *reinterpret_cast<uint32_t*>(addr_at(pos)); 1493 } 1494 void long_at_put(int pos, uint32_t x) { 1495 *reinterpret_cast<uint32_t*>(addr_at(pos)) = x; 1496 } 1497 1498 // code emission 1499 void GrowBuffer(); 1500 inline void emit(uint32_t x); 1501 inline void emit(Handle<Object> handle); 1502 inline void emit(uint32_t x, 1503 RelocInfo::Mode rmode, 1504 TypeFeedbackId id = TypeFeedbackId::None()); 1505 inline void emit(Handle<Code> code, 1506 RelocInfo::Mode rmode, 1507 TypeFeedbackId id = TypeFeedbackId::None()); 1508 inline void emit(const Immediate& x); 1509 inline void emit_b(Immediate x); 1510 inline void emit_w(const Immediate& x); 1511 inline void emit_q(uint64_t x); 1512 1513 // Emit the code-object-relative offset of the label's position 1514 inline void emit_code_relative_offset(Label* label); 1515 1516 // instruction generation 1517 void emit_arith_b(int op1, int op2, Register dst, int imm8); 1518 1519 // Emit a basic arithmetic instruction (i.e. first byte of the family is 0x81) 1520 // with a given destination expression and an immediate operand. It attempts 1521 // to use the shortest encoding possible. 1522 // sel specifies the /n in the modrm byte (see the Intel PRM). 1523 void emit_arith(int sel, Operand dst, const Immediate& x); 1524 1525 void emit_operand(Register reg, const Operand& adr); 1526 1527 void emit_label(Label* label); 1528 1529 void emit_farith(int b1, int b2, int i); 1530 1531 // Emit vex prefix 1532 enum SIMDPrefix { kNone = 0x0, k66 = 0x1, kF3 = 0x2, kF2 = 0x3 }; 1533 enum VectorLength { kL128 = 0x0, kL256 = 0x4, kLIG = kL128, kLZ = kL128 }; 1534 enum VexW { kW0 = 0x0, kW1 = 0x80, kWIG = kW0 }; 1535 enum LeadingOpcode { k0F = 0x1, k0F38 = 0x2, k0F3A = 0x3 }; 1536 inline void emit_vex_prefix(XMMRegister v, VectorLength l, SIMDPrefix pp, 1537 LeadingOpcode m, VexW w); 1538 inline void emit_vex_prefix(Register v, VectorLength l, SIMDPrefix pp, 1539 LeadingOpcode m, VexW w); 1540 1541 // labels 1542 void print(Label* L); 1543 void bind_to(Label* L, int pos); 1544 1545 // displacements 1546 inline Displacement disp_at(Label* L); 1547 inline void disp_at_put(Label* L, Displacement disp); 1548 inline void emit_disp(Label* L, Displacement::Type type); 1549 inline void emit_near_disp(Label* L); 1550 1551 // Most BMI instructions are similiar. 1552 void bmi1(byte op, Register reg, Register vreg, const Operand& rm); 1553 void bmi2(SIMDPrefix pp, byte op, Register reg, Register vreg, 1554 const Operand& rm); 1555 1556 // record reloc info for current pc_ 1557 void RecordRelocInfo(RelocInfo::Mode rmode, intptr_t data = 0); 1558 1559 friend class CodePatcher; 1560 friend class EnsureSpace; 1561 1562 // Internal reference positions, required for (potential) patching in 1563 // GrowBuffer(); contains only those internal references whose labels 1564 // are already bound. 1565 std::deque<int> internal_reference_positions_; 1566 1567 // code generation 1568 RelocInfoWriter reloc_info_writer; 1569 }; 1570 1571 1572 // Helper class that ensures that there is enough space for generating 1573 // instructions and relocation information. The constructor makes 1574 // sure that there is enough space and (in debug mode) the destructor 1575 // checks that we did not generate too much. 1576 class EnsureSpace BASE_EMBEDDED { 1577 public: 1578 explicit EnsureSpace(Assembler* assembler) : assembler_(assembler) { 1579 if (assembler_->buffer_overflow()) assembler_->GrowBuffer(); 1580 #ifdef DEBUG 1581 space_before_ = assembler_->available_space(); 1582 #endif 1583 } 1584 1585 #ifdef DEBUG 1586 ~EnsureSpace() { 1587 int bytes_generated = space_before_ - assembler_->available_space(); 1588 DCHECK(bytes_generated < assembler_->kGap); 1589 } 1590 #endif 1591 1592 private: 1593 Assembler* assembler_; 1594 #ifdef DEBUG 1595 int space_before_; 1596 #endif 1597 }; 1598 1599 } // namespace internal 1600 } // namespace v8 1601 1602 #endif // V8_IA32_ASSEMBLER_IA32_H_ 1603