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