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