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_X87_ASSEMBLER_X87_H_ 38 #define V8_X87_ASSEMBLER_X87_H_ 39 40 #include "src/isolate.h" 41 #include "src/serialize.h" 42 43 namespace v8 { 44 namespace internal { 45 46 // CPU Registers. 47 // 48 // 1) We would prefer to use an enum, but enum values are assignment- 49 // compatible with int, which has caused code-generation bugs. 50 // 51 // 2) We would prefer to use a class instead of a struct but we don't like 52 // the register initialization to depend on the particular initialization 53 // order (which appears to be different on OS X, Linux, and Windows for the 54 // installed versions of C++ we tried). Using a struct permits C-style 55 // "initialization". Also, the Register objects cannot be const as this 56 // forces initialization stubs in MSVC, making us dependent on initialization 57 // order. 58 // 59 // 3) By not using an enum, we are possibly preventing the compiler from 60 // doing certain constant folds, which may significantly reduce the 61 // code generated for some assembly instructions (because they boil down 62 // to a few constants). If this is a problem, we could change the code 63 // such that we use an enum in optimized mode, and the struct in debug 64 // mode. This way we get the compile-time error checking in debug mode 65 // and best performance in optimized code. 66 // 67 struct Register { 68 static const int kMaxNumAllocatableRegisters = 6; 69 static int NumAllocatableRegisters() { 70 return kMaxNumAllocatableRegisters; 71 } 72 static const int kNumRegisters = 8; 73 74 static inline const char* AllocationIndexToString(int index); 75 76 static inline int ToAllocationIndex(Register reg); 77 78 static inline Register FromAllocationIndex(int index); 79 80 static Register from_code(int code) { 81 ASSERT(code >= 0); 82 ASSERT(code < kNumRegisters); 83 Register r = { code }; 84 return r; 85 } 86 bool is_valid() const { return 0 <= code_ && code_ < kNumRegisters; } 87 bool is(Register reg) const { return code_ == reg.code_; } 88 // eax, ebx, ecx and edx are byte registers, the rest are not. 89 bool is_byte_register() const { return code_ <= 3; } 90 int code() const { 91 ASSERT(is_valid()); 92 return code_; 93 } 94 int bit() const { 95 ASSERT(is_valid()); 96 return 1 << code_; 97 } 98 99 // Unfortunately we can't make this private in a struct. 100 int code_; 101 }; 102 103 const int kRegister_eax_Code = 0; 104 const int kRegister_ecx_Code = 1; 105 const int kRegister_edx_Code = 2; 106 const int kRegister_ebx_Code = 3; 107 const int kRegister_esp_Code = 4; 108 const int kRegister_ebp_Code = 5; 109 const int kRegister_esi_Code = 6; 110 const int kRegister_edi_Code = 7; 111 const int kRegister_no_reg_Code = -1; 112 113 const Register eax = { kRegister_eax_Code }; 114 const Register ecx = { kRegister_ecx_Code }; 115 const Register edx = { kRegister_edx_Code }; 116 const Register ebx = { kRegister_ebx_Code }; 117 const Register esp = { kRegister_esp_Code }; 118 const Register ebp = { kRegister_ebp_Code }; 119 const Register esi = { kRegister_esi_Code }; 120 const Register edi = { kRegister_edi_Code }; 121 const Register no_reg = { kRegister_no_reg_Code }; 122 123 124 inline const char* Register::AllocationIndexToString(int index) { 125 ASSERT(index >= 0 && index < kMaxNumAllocatableRegisters); 126 // This is the mapping of allocation indices to registers. 127 const char* const kNames[] = { "eax", "ecx", "edx", "ebx", "esi", "edi" }; 128 return kNames[index]; 129 } 130 131 132 inline int Register::ToAllocationIndex(Register reg) { 133 ASSERT(reg.is_valid() && !reg.is(esp) && !reg.is(ebp)); 134 return (reg.code() >= 6) ? reg.code() - 2 : reg.code(); 135 } 136 137 138 inline Register Register::FromAllocationIndex(int index) { 139 ASSERT(index >= 0 && index < kMaxNumAllocatableRegisters); 140 return (index >= 4) ? from_code(index + 2) : from_code(index); 141 } 142 143 144 struct X87Register { 145 static const int kMaxNumAllocatableRegisters = 8; 146 static const int kMaxNumRegisters = 8; 147 static int NumAllocatableRegisters() { 148 return kMaxNumAllocatableRegisters; 149 } 150 151 static int ToAllocationIndex(X87Register reg) { 152 return reg.code_; 153 } 154 155 static const char* AllocationIndexToString(int index) { 156 ASSERT(index >= 0 && index < kMaxNumAllocatableRegisters); 157 const char* const names[] = { 158 "stX_0", "stX_1", "stX_2", "stX_3", "stX_4", 159 "stX_5", "stX_6", "stX_7" 160 }; 161 return names[index]; 162 } 163 164 static X87Register FromAllocationIndex(int index) { 165 ASSERT(index >= 0 && index < kMaxNumAllocatableRegisters); 166 X87Register result; 167 result.code_ = index; 168 return result; 169 } 170 171 bool is_valid() const { 172 return 0 <= code_ && code_ < kMaxNumRegisters; 173 } 174 175 int code() const { 176 ASSERT(is_valid()); 177 return code_; 178 } 179 180 bool is(X87Register reg) const { 181 return code_ == reg.code_; 182 } 183 184 int code_; 185 }; 186 187 188 typedef X87Register DoubleRegister; 189 190 191 const X87Register stX_0 = { 0 }; 192 const X87Register stX_1 = { 1 }; 193 const X87Register stX_2 = { 2 }; 194 const X87Register stX_3 = { 3 }; 195 const X87Register stX_4 = { 4 }; 196 const X87Register stX_5 = { 5 }; 197 const X87Register stX_6 = { 6 }; 198 const X87Register stX_7 = { 7 }; 199 200 201 enum Condition { 202 // any value < 0 is considered no_condition 203 no_condition = -1, 204 205 overflow = 0, 206 no_overflow = 1, 207 below = 2, 208 above_equal = 3, 209 equal = 4, 210 not_equal = 5, 211 below_equal = 6, 212 above = 7, 213 negative = 8, 214 positive = 9, 215 parity_even = 10, 216 parity_odd = 11, 217 less = 12, 218 greater_equal = 13, 219 less_equal = 14, 220 greater = 15, 221 222 // aliases 223 carry = below, 224 not_carry = above_equal, 225 zero = equal, 226 not_zero = not_equal, 227 sign = negative, 228 not_sign = positive 229 }; 230 231 232 // Returns the equivalent of !cc. 233 // Negation of the default no_condition (-1) results in a non-default 234 // no_condition value (-2). As long as tests for no_condition check 235 // for condition < 0, this will work as expected. 236 inline Condition NegateCondition(Condition cc) { 237 return static_cast<Condition>(cc ^ 1); 238 } 239 240 241 // Commute a condition such that {a cond b == b cond' a}. 242 inline Condition CommuteCondition(Condition cc) { 243 switch (cc) { 244 case below: 245 return above; 246 case above: 247 return below; 248 case above_equal: 249 return below_equal; 250 case below_equal: 251 return above_equal; 252 case less: 253 return greater; 254 case greater: 255 return less; 256 case greater_equal: 257 return less_equal; 258 case less_equal: 259 return greater_equal; 260 default: 261 return cc; 262 } 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 277 static Immediate CodeRelativeOffset(Label* label) { 278 return Immediate(label); 279 } 280 281 bool is_zero() const { return x_ == 0 && RelocInfo::IsNone(rmode_); } 282 bool is_int8() const { 283 return -128 <= x_ && x_ < 128 && RelocInfo::IsNone(rmode_); 284 } 285 bool is_int16() const { 286 return -32768 <= x_ && x_ < 32768 && RelocInfo::IsNone(rmode_); 287 } 288 289 private: 290 inline explicit Immediate(Label* value); 291 292 int x_; 293 RelocInfo::Mode rmode_; 294 295 friend class Assembler; 296 friend class MacroAssembler; 297 }; 298 299 300 // ----------------------------------------------------------------------------- 301 // Machine instruction Operands 302 303 enum ScaleFactor { 304 times_1 = 0, 305 times_2 = 1, 306 times_4 = 2, 307 times_8 = 3, 308 times_int_size = times_4, 309 times_half_pointer_size = times_2, 310 times_pointer_size = times_4, 311 times_twice_pointer_size = times_8 312 }; 313 314 315 class Operand BASE_EMBEDDED { 316 public: 317 // [disp/r] 318 INLINE(explicit Operand(int32_t disp, RelocInfo::Mode rmode)); 319 // disp only must always be relocated 320 321 // [base + disp/r] 322 explicit Operand(Register base, int32_t disp, 323 RelocInfo::Mode rmode = RelocInfo::NONE32); 324 325 // [base + index*scale + disp/r] 326 explicit Operand(Register base, 327 Register index, 328 ScaleFactor scale, 329 int32_t disp, 330 RelocInfo::Mode rmode = RelocInfo::NONE32); 331 332 // [index*scale + disp/r] 333 explicit Operand(Register index, 334 ScaleFactor scale, 335 int32_t disp, 336 RelocInfo::Mode rmode = RelocInfo::NONE32); 337 338 static Operand StaticVariable(const ExternalReference& ext) { 339 return Operand(reinterpret_cast<int32_t>(ext.address()), 340 RelocInfo::EXTERNAL_REFERENCE); 341 } 342 343 static Operand StaticArray(Register index, 344 ScaleFactor scale, 345 const ExternalReference& arr) { 346 return Operand(index, scale, reinterpret_cast<int32_t>(arr.address()), 347 RelocInfo::EXTERNAL_REFERENCE); 348 } 349 350 static Operand ForCell(Handle<Cell> cell) { 351 AllowDeferredHandleDereference embedding_raw_address; 352 return Operand(reinterpret_cast<int32_t>(cell.location()), 353 RelocInfo::CELL); 354 } 355 356 // Returns true if this Operand is a wrapper for the specified register. 357 bool is_reg(Register reg) const; 358 359 // Returns true if this Operand is a wrapper for one register. 360 bool is_reg_only() const; 361 362 // Asserts that this Operand is a wrapper for one register and returns the 363 // register. 364 Register reg() const; 365 366 private: 367 // reg 368 INLINE(explicit Operand(Register reg)); 369 370 // Set the ModRM byte without an encoded 'reg' register. The 371 // register is encoded later as part of the emit_operand operation. 372 inline void set_modrm(int mod, Register rm); 373 374 inline void set_sib(ScaleFactor scale, Register index, Register base); 375 inline void set_disp8(int8_t disp); 376 inline void set_dispr(int32_t disp, RelocInfo::Mode rmode); 377 378 byte buf_[6]; 379 // The number of bytes in buf_. 380 unsigned int len_; 381 // Only valid if len_ > 4. 382 RelocInfo::Mode rmode_; 383 384 friend class Assembler; 385 friend class MacroAssembler; 386 friend class LCodeGen; 387 }; 388 389 390 // ----------------------------------------------------------------------------- 391 // A Displacement describes the 32bit immediate field of an instruction which 392 // may be used together with a Label in order to refer to a yet unknown code 393 // position. Displacements stored in the instruction stream are used to describe 394 // the instruction and to chain a list of instructions using the same Label. 395 // A Displacement contains 2 different fields: 396 // 397 // next field: position of next displacement in the chain (0 = end of list) 398 // type field: instruction type 399 // 400 // A next value of null (0) indicates the end of a chain (note that there can 401 // be no displacement at position zero, because there is always at least one 402 // instruction byte before the displacement). 403 // 404 // Displacement _data field layout 405 // 406 // |31.....2|1......0| 407 // [ next | type | 408 409 class Displacement BASE_EMBEDDED { 410 public: 411 enum Type { 412 UNCONDITIONAL_JUMP, 413 CODE_RELATIVE, 414 OTHER 415 }; 416 417 int data() const { return data_; } 418 Type type() const { return TypeField::decode(data_); } 419 void next(Label* L) const { 420 int n = NextField::decode(data_); 421 n > 0 ? L->link_to(n) : L->Unuse(); 422 } 423 void link_to(Label* L) { init(L, type()); } 424 425 explicit Displacement(int data) { data_ = data; } 426 427 Displacement(Label* L, Type type) { init(L, type); } 428 429 void print() { 430 PrintF("%s (%x) ", (type() == UNCONDITIONAL_JUMP ? "jmp" : "[other]"), 431 NextField::decode(data_)); 432 } 433 434 private: 435 int data_; 436 437 class TypeField: public BitField<Type, 0, 2> {}; 438 class NextField: public BitField<int, 2, 32-2> {}; 439 440 void init(Label* L, Type type); 441 }; 442 443 444 class Assembler : public AssemblerBase { 445 private: 446 // We check before assembling an instruction that there is sufficient 447 // space to write an instruction and its relocation information. 448 // The relocation writer's position must be kGap bytes above the end of 449 // the generated instructions. This leaves enough space for the 450 // longest possible ia32 instruction, 15 bytes, and the longest possible 451 // relocation information encoding, RelocInfoWriter::kMaxLength == 16. 452 // (There is a 15 byte limit on ia32 instruction length that rules out some 453 // otherwise valid instructions.) 454 // This allows for a single, fast space check per instruction. 455 static const int kGap = 32; 456 457 public: 458 // Create an assembler. Instructions and relocation information are emitted 459 // into a buffer, with the instructions starting from the beginning and the 460 // relocation information starting from the end of the buffer. See CodeDesc 461 // for a detailed comment on the layout (globals.h). 462 // 463 // If the provided buffer is NULL, the assembler allocates and grows its own 464 // buffer, and buffer_size determines the initial buffer size. The buffer is 465 // owned by the assembler and deallocated upon destruction of the assembler. 466 // 467 // If the provided buffer is not NULL, the assembler uses the provided buffer 468 // for code generation and assumes its size to be buffer_size. If the buffer 469 // is too small, a fatal error occurs. No deallocation of the buffer is done 470 // upon destruction of the assembler. 471 // TODO(vitalyr): the assembler does not need an isolate. 472 Assembler(Isolate* isolate, void* buffer, int buffer_size); 473 virtual ~Assembler() { } 474 475 // GetCode emits any pending (non-emitted) code and fills the descriptor 476 // desc. GetCode() is idempotent; it returns the same result if no other 477 // Assembler functions are invoked in between GetCode() calls. 478 void GetCode(CodeDesc* desc); 479 480 // Read/Modify the code target in the branch/call instruction at pc. 481 inline static Address target_address_at(Address pc, 482 ConstantPoolArray* constant_pool); 483 inline static void set_target_address_at(Address pc, 484 ConstantPoolArray* constant_pool, 485 Address target, 486 ICacheFlushMode icache_flush_mode = 487 FLUSH_ICACHE_IF_NEEDED); 488 static inline Address target_address_at(Address pc, Code* code) { 489 ConstantPoolArray* constant_pool = code ? code->constant_pool() : NULL; 490 return target_address_at(pc, constant_pool); 491 } 492 static inline void set_target_address_at(Address pc, 493 Code* code, 494 Address target, 495 ICacheFlushMode icache_flush_mode = 496 FLUSH_ICACHE_IF_NEEDED) { 497 ConstantPoolArray* constant_pool = code ? code->constant_pool() : NULL; 498 set_target_address_at(pc, constant_pool, target); 499 } 500 501 // Return the code target address at a call site from the return address 502 // of that call in the instruction stream. 503 inline static Address target_address_from_return_address(Address pc); 504 505 // This sets the branch destination (which is in the instruction on x86). 506 // This is for calls and branches within generated code. 507 inline static void deserialization_set_special_target_at( 508 Address instruction_payload, Code* code, Address target) { 509 set_target_address_at(instruction_payload, code, target); 510 } 511 512 static const int kSpecialTargetSize = kPointerSize; 513 514 // Distance between the address of the code target in the call instruction 515 // and the return address 516 static const int kCallTargetAddressOffset = kPointerSize; 517 // Distance between start of patched return sequence and the emitted address 518 // to jump to. 519 static const int kPatchReturnSequenceAddressOffset = 1; // JMP imm32. 520 521 // Distance between start of patched debug break slot and the emitted address 522 // to jump to. 523 static const int kPatchDebugBreakSlotAddressOffset = 1; // JMP imm32. 524 525 static const int kCallInstructionLength = 5; 526 static const int kPatchDebugBreakSlotReturnOffset = kPointerSize; 527 static const int kJSReturnSequenceLength = 6; 528 529 // The debug break slot must be able to contain a call instruction. 530 static const int kDebugBreakSlotLength = kCallInstructionLength; 531 532 // One byte opcode for test al, 0xXX. 533 static const byte kTestAlByte = 0xA8; 534 // One byte opcode for nop. 535 static const byte kNopByte = 0x90; 536 537 // One byte opcode for a short unconditional jump. 538 static const byte kJmpShortOpcode = 0xEB; 539 // One byte prefix for a short conditional jump. 540 static const byte kJccShortPrefix = 0x70; 541 static const byte kJncShortOpcode = kJccShortPrefix | not_carry; 542 static const byte kJcShortOpcode = kJccShortPrefix | carry; 543 static const byte kJnzShortOpcode = kJccShortPrefix | not_zero; 544 static const byte kJzShortOpcode = kJccShortPrefix | zero; 545 546 547 // --------------------------------------------------------------------------- 548 // Code generation 549 // 550 // - function names correspond one-to-one to ia32 instruction mnemonics 551 // - unless specified otherwise, instructions operate on 32bit operands 552 // - instructions on 8bit (byte) operands/registers have a trailing '_b' 553 // - instructions on 16bit (word) operands/registers have a trailing '_w' 554 // - naming conflicts with C++ keywords are resolved via a trailing '_' 555 556 // NOTE ON INTERFACE: Currently, the interface is not very consistent 557 // in the sense that some operations (e.g. mov()) can be called in more 558 // the one way to generate the same instruction: The Register argument 559 // can in some cases be replaced with an Operand(Register) argument. 560 // This should be cleaned up and made more orthogonal. The questions 561 // is: should we always use Operands instead of Registers where an 562 // Operand is possible, or should we have a Register (overloaded) form 563 // instead? We must be careful to make sure that the selected instruction 564 // is obvious from the parameters to avoid hard-to-find code generation 565 // bugs. 566 567 // Insert the smallest number of nop instructions 568 // possible to align the pc offset to a multiple 569 // of m. m must be a power of 2. 570 void Align(int m); 571 void Nop(int bytes = 1); 572 // Aligns code to something that's optimal for a jump target for the platform. 573 void CodeTargetAlign(); 574 575 // Stack 576 void pushad(); 577 void popad(); 578 579 void pushfd(); 580 void popfd(); 581 582 void push(const Immediate& x); 583 void push_imm32(int32_t imm32); 584 void push(Register src); 585 void push(const Operand& src); 586 587 void pop(Register dst); 588 void pop(const Operand& dst); 589 590 void enter(const Immediate& size); 591 void leave(); 592 593 // Moves 594 void mov_b(Register dst, Register src) { mov_b(dst, Operand(src)); } 595 void mov_b(Register dst, const Operand& src); 596 void mov_b(Register dst, int8_t imm8) { mov_b(Operand(dst), imm8); } 597 void mov_b(const Operand& dst, int8_t imm8); 598 void mov_b(const Operand& dst, Register src); 599 600 void mov_w(Register dst, const Operand& src); 601 void mov_w(const Operand& dst, Register src); 602 void mov_w(const Operand& dst, int16_t imm16); 603 604 void mov(Register dst, int32_t imm32); 605 void mov(Register dst, const Immediate& x); 606 void mov(Register dst, Handle<Object> handle); 607 void mov(Register dst, const Operand& src); 608 void mov(Register dst, Register src); 609 void mov(const Operand& dst, const Immediate& x); 610 void mov(const Operand& dst, Handle<Object> handle); 611 void mov(const Operand& dst, Register src); 612 613 void movsx_b(Register dst, Register src) { movsx_b(dst, Operand(src)); } 614 void movsx_b(Register dst, const Operand& src); 615 616 void movsx_w(Register dst, Register src) { movsx_w(dst, Operand(src)); } 617 void movsx_w(Register dst, const Operand& src); 618 619 void movzx_b(Register dst, Register src) { movzx_b(dst, Operand(src)); } 620 void movzx_b(Register dst, const Operand& src); 621 622 void movzx_w(Register dst, Register src) { movzx_w(dst, Operand(src)); } 623 void movzx_w(Register dst, const Operand& src); 624 625 // Flag management. 626 void cld(); 627 628 // Repetitive string instructions. 629 void rep_movs(); 630 void rep_stos(); 631 void stos(); 632 633 // Exchange two registers 634 void xchg(Register dst, Register src); 635 636 // Arithmetics 637 void adc(Register dst, int32_t imm32); 638 void adc(Register dst, const Operand& src); 639 640 void add(Register dst, Register src) { add(dst, Operand(src)); } 641 void add(Register dst, const Operand& src); 642 void add(const Operand& dst, Register src); 643 void add(Register dst, const Immediate& imm) { add(Operand(dst), imm); } 644 void add(const Operand& dst, const Immediate& x); 645 646 void and_(Register dst, int32_t imm32); 647 void and_(Register dst, const Immediate& x); 648 void and_(Register dst, Register src) { and_(dst, Operand(src)); } 649 void and_(Register dst, const Operand& src); 650 void and_(const Operand& dst, Register src); 651 void and_(const Operand& dst, const Immediate& x); 652 653 void cmpb(Register reg, int8_t imm8) { cmpb(Operand(reg), imm8); } 654 void cmpb(const Operand& op, int8_t imm8); 655 void cmpb(Register reg, const Operand& op); 656 void cmpb(const Operand& op, Register reg); 657 void cmpb_al(const Operand& op); 658 void cmpw_ax(const Operand& op); 659 void cmpw(const Operand& op, Immediate imm16); 660 void cmp(Register reg, int32_t imm32); 661 void cmp(Register reg, Handle<Object> handle); 662 void cmp(Register reg0, Register reg1) { cmp(reg0, Operand(reg1)); } 663 void cmp(Register reg, const Operand& op); 664 void cmp(Register reg, const Immediate& imm) { cmp(Operand(reg), imm); } 665 void cmp(const Operand& op, const Immediate& imm); 666 void cmp(const Operand& op, Handle<Object> handle); 667 668 void dec_b(Register dst); 669 void dec_b(const Operand& dst); 670 671 void dec(Register dst); 672 void dec(const Operand& dst); 673 674 void cdq(); 675 676 void idiv(Register src); 677 678 // Signed multiply instructions. 679 void imul(Register src); // edx:eax = eax * src. 680 void imul(Register dst, Register src) { imul(dst, Operand(src)); } 681 void imul(Register dst, const Operand& src); // dst = dst * src. 682 void imul(Register dst, Register src, int32_t imm32); // dst = src * imm32. 683 684 void inc(Register dst); 685 void inc(const Operand& dst); 686 687 void lea(Register dst, const Operand& src); 688 689 // Unsigned multiply instruction. 690 void mul(Register src); // edx:eax = eax * reg. 691 692 void neg(Register dst); 693 694 void not_(Register dst); 695 696 void or_(Register dst, int32_t imm32); 697 void or_(Register dst, Register src) { or_(dst, Operand(src)); } 698 void or_(Register dst, const Operand& src); 699 void or_(const Operand& dst, Register src); 700 void or_(Register dst, const Immediate& imm) { or_(Operand(dst), imm); } 701 void or_(const Operand& dst, const Immediate& x); 702 703 void rcl(Register dst, uint8_t imm8); 704 void rcr(Register dst, uint8_t imm8); 705 void ror(Register dst, uint8_t imm8); 706 void ror_cl(Register dst); 707 708 void sar(Register dst, uint8_t imm8); 709 void sar_cl(Register dst); 710 711 void sbb(Register dst, const Operand& src); 712 713 void shld(Register dst, Register src) { shld(dst, Operand(src)); } 714 void shld(Register dst, const Operand& src); 715 716 void shl(Register dst, uint8_t imm8); 717 void shl_cl(Register dst); 718 719 void shrd(Register dst, Register src) { shrd(dst, Operand(src)); } 720 void shrd(Register dst, const Operand& src); 721 722 void shr(Register dst, uint8_t imm8); 723 void shr_cl(Register dst); 724 725 void sub(Register dst, const Immediate& imm) { sub(Operand(dst), imm); } 726 void sub(const Operand& dst, const Immediate& x); 727 void sub(Register dst, Register src) { sub(dst, Operand(src)); } 728 void sub(Register dst, const Operand& src); 729 void sub(const Operand& dst, Register src); 730 731 void test(Register reg, const Immediate& imm); 732 void test(Register reg0, Register reg1) { test(reg0, Operand(reg1)); } 733 void test(Register reg, const Operand& op); 734 void test_b(Register reg, const Operand& op); 735 void test(const Operand& op, const Immediate& imm); 736 void test_b(Register reg, uint8_t imm8); 737 void test_b(const Operand& op, uint8_t imm8); 738 739 void xor_(Register dst, int32_t imm32); 740 void xor_(Register dst, Register src) { xor_(dst, Operand(src)); } 741 void xor_(Register dst, const Operand& src); 742 void xor_(const Operand& dst, Register src); 743 void xor_(Register dst, const Immediate& imm) { xor_(Operand(dst), imm); } 744 void xor_(const Operand& dst, const Immediate& x); 745 746 // Bit operations. 747 void bt(const Operand& dst, Register src); 748 void bts(Register dst, Register src) { bts(Operand(dst), src); } 749 void bts(const Operand& dst, Register src); 750 void bsr(Register dst, Register src) { bsr(dst, Operand(src)); } 751 void bsr(Register dst, const Operand& src); 752 753 // Miscellaneous 754 void hlt(); 755 void int3(); 756 void nop(); 757 void ret(int imm16); 758 759 // Label operations & relative jumps (PPUM Appendix D) 760 // 761 // Takes a branch opcode (cc) and a label (L) and generates 762 // either a backward branch or a forward branch and links it 763 // to the label fixup chain. Usage: 764 // 765 // Label L; // unbound label 766 // j(cc, &L); // forward branch to unbound label 767 // bind(&L); // bind label to the current pc 768 // j(cc, &L); // backward branch to bound label 769 // bind(&L); // illegal: a label may be bound only once 770 // 771 // Note: The same Label can be used for forward and backward branches 772 // but it may be bound only once. 773 774 void bind(Label* L); // binds an unbound label L to the current code position 775 776 // Calls 777 void call(Label* L); 778 void call(byte* entry, RelocInfo::Mode rmode); 779 int CallSize(const Operand& adr); 780 void call(Register reg) { call(Operand(reg)); } 781 void call(const Operand& adr); 782 int CallSize(Handle<Code> code, RelocInfo::Mode mode); 783 void call(Handle<Code> code, 784 RelocInfo::Mode rmode, 785 TypeFeedbackId id = TypeFeedbackId::None()); 786 787 // Jumps 788 // unconditional jump to L 789 void jmp(Label* L, Label::Distance distance = Label::kFar); 790 void jmp(byte* entry, RelocInfo::Mode rmode); 791 void jmp(Register reg) { jmp(Operand(reg)); } 792 void jmp(const Operand& adr); 793 void jmp(Handle<Code> code, RelocInfo::Mode rmode); 794 795 // Conditional jumps 796 void j(Condition cc, 797 Label* L, 798 Label::Distance distance = Label::kFar); 799 void j(Condition cc, byte* entry, RelocInfo::Mode rmode); 800 void j(Condition cc, Handle<Code> code); 801 802 // Floating-point operations 803 void fld(int i); 804 void fstp(int i); 805 806 void fld1(); 807 void fldz(); 808 void fldpi(); 809 void fldln2(); 810 811 void fld_s(const Operand& adr); 812 void fld_d(const Operand& adr); 813 814 void fstp_s(const Operand& adr); 815 void fst_s(const Operand& adr); 816 void fstp_d(const Operand& adr); 817 void fst_d(const Operand& adr); 818 819 void fild_s(const Operand& adr); 820 void fild_d(const Operand& adr); 821 822 void fist_s(const Operand& adr); 823 824 void fistp_s(const Operand& adr); 825 void fistp_d(const Operand& adr); 826 827 // The fisttp instructions require SSE3. 828 void fisttp_s(const Operand& adr); 829 void fisttp_d(const Operand& adr); 830 831 void fabs(); 832 void fchs(); 833 void fcos(); 834 void fsin(); 835 void fptan(); 836 void fyl2x(); 837 void f2xm1(); 838 void fscale(); 839 void fninit(); 840 841 void fadd(int i); 842 void fadd_i(int i); 843 void fsub(int i); 844 void fsub_i(int i); 845 void fmul(int i); 846 void fmul_i(int i); 847 void fdiv(int i); 848 void fdiv_i(int i); 849 850 void fisub_s(const Operand& adr); 851 852 void faddp(int i = 1); 853 void fsubp(int i = 1); 854 void fsubrp(int i = 1); 855 void fmulp(int i = 1); 856 void fdivp(int i = 1); 857 void fprem(); 858 void fprem1(); 859 860 void fxch(int i = 1); 861 void fincstp(); 862 void ffree(int i = 0); 863 864 void ftst(); 865 void fucomp(int i); 866 void fucompp(); 867 void fucomi(int i); 868 void fucomip(); 869 void fcompp(); 870 void fnstsw_ax(); 871 void fwait(); 872 void fnclex(); 873 874 void frndint(); 875 876 void sahf(); 877 void setcc(Condition cc, Register reg); 878 879 void cpuid(); 880 881 // TODO(lrn): Need SFENCE for movnt? 882 883 // Debugging 884 void Print(); 885 886 // Check the code size generated from label to here. 887 int SizeOfCodeGeneratedSince(Label* label) { 888 return pc_offset() - label->pos(); 889 } 890 891 // Mark address of the ExitJSFrame code. 892 void RecordJSReturn(); 893 894 // Mark address of a debug break slot. 895 void RecordDebugBreakSlot(); 896 897 // Record a comment relocation entry that can be used by a disassembler. 898 // Use --code-comments to enable, or provide "force = true" flag to always 899 // write a comment. 900 void RecordComment(const char* msg, bool force = false); 901 902 // Writes a single byte or word of data in the code stream. Used for 903 // inline tables, e.g., jump-tables. 904 void db(uint8_t data); 905 void dd(uint32_t data); 906 907 // Check if there is less than kGap bytes available in the buffer. 908 // If this is the case, we need to grow the buffer before emitting 909 // an instruction or relocation information. 910 inline bool buffer_overflow() const { 911 return pc_ >= reloc_info_writer.pos() - kGap; 912 } 913 914 // Get the number of bytes available in the buffer. 915 inline int available_space() const { return reloc_info_writer.pos() - pc_; } 916 917 static bool IsNop(Address addr); 918 919 PositionsRecorder* positions_recorder() { return &positions_recorder_; } 920 921 int relocation_writer_size() { 922 return (buffer_ + buffer_size_) - reloc_info_writer.pos(); 923 } 924 925 // Avoid overflows for displacements etc. 926 static const int kMaximalBufferSize = 512*MB; 927 928 byte byte_at(int pos) { return buffer_[pos]; } 929 void set_byte_at(int pos, byte value) { buffer_[pos] = value; } 930 931 // Allocate a constant pool of the correct size for the generated code. 932 Handle<ConstantPoolArray> NewConstantPool(Isolate* isolate); 933 934 // Generate the constant pool for the generated code. 935 void PopulateConstantPool(ConstantPoolArray* constant_pool); 936 937 protected: 938 byte* addr_at(int pos) { return buffer_ + pos; } 939 940 941 private: 942 uint32_t long_at(int pos) { 943 return *reinterpret_cast<uint32_t*>(addr_at(pos)); 944 } 945 void long_at_put(int pos, uint32_t x) { 946 *reinterpret_cast<uint32_t*>(addr_at(pos)) = x; 947 } 948 949 // code emission 950 void GrowBuffer(); 951 inline void emit(uint32_t x); 952 inline void emit(Handle<Object> handle); 953 inline void emit(uint32_t x, 954 RelocInfo::Mode rmode, 955 TypeFeedbackId id = TypeFeedbackId::None()); 956 inline void emit(Handle<Code> code, 957 RelocInfo::Mode rmode, 958 TypeFeedbackId id = TypeFeedbackId::None()); 959 inline void emit(const Immediate& x); 960 inline void emit_w(const Immediate& x); 961 962 // Emit the code-object-relative offset of the label's position 963 inline void emit_code_relative_offset(Label* label); 964 965 // instruction generation 966 void emit_arith_b(int op1, int op2, Register dst, int imm8); 967 968 // Emit a basic arithmetic instruction (i.e. first byte of the family is 0x81) 969 // with a given destination expression and an immediate operand. It attempts 970 // to use the shortest encoding possible. 971 // sel specifies the /n in the modrm byte (see the Intel PRM). 972 void emit_arith(int sel, Operand dst, const Immediate& x); 973 974 void emit_operand(Register reg, const Operand& adr); 975 976 void emit_farith(int b1, int b2, int i); 977 978 // labels 979 void print(Label* L); 980 void bind_to(Label* L, int pos); 981 982 // displacements 983 inline Displacement disp_at(Label* L); 984 inline void disp_at_put(Label* L, Displacement disp); 985 inline void emit_disp(Label* L, Displacement::Type type); 986 inline void emit_near_disp(Label* L); 987 988 // record reloc info for current pc_ 989 void RecordRelocInfo(RelocInfo::Mode rmode, intptr_t data = 0); 990 991 friend class CodePatcher; 992 friend class EnsureSpace; 993 994 // code generation 995 RelocInfoWriter reloc_info_writer; 996 997 PositionsRecorder positions_recorder_; 998 friend class PositionsRecorder; 999 }; 1000 1001 1002 // Helper class that ensures that there is enough space for generating 1003 // instructions and relocation information. The constructor makes 1004 // sure that there is enough space and (in debug mode) the destructor 1005 // checks that we did not generate too much. 1006 class EnsureSpace BASE_EMBEDDED { 1007 public: 1008 explicit EnsureSpace(Assembler* assembler) : assembler_(assembler) { 1009 if (assembler_->buffer_overflow()) assembler_->GrowBuffer(); 1010 #ifdef DEBUG 1011 space_before_ = assembler_->available_space(); 1012 #endif 1013 } 1014 1015 #ifdef DEBUG 1016 ~EnsureSpace() { 1017 int bytes_generated = space_before_ - assembler_->available_space(); 1018 ASSERT(bytes_generated < assembler_->kGap); 1019 } 1020 #endif 1021 1022 private: 1023 Assembler* assembler_; 1024 #ifdef DEBUG 1025 int space_before_; 1026 #endif 1027 }; 1028 1029 } } // namespace v8::internal 1030 1031 #endif // V8_X87_ASSEMBLER_X87_H_ 1032