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