Home | History | Annotate | Download | only in x87
      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 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 //
    109 struct 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};
    145 GENERAL_REGISTERS(DECLARE_REGISTER)
    146 #undef DECLARE_REGISTER
    147 const Register no_reg = {Register::kCode_no_reg};
    148 
    149 static const bool kSimpleFPAliasing = true;
    150 static const bool kSimdMaskRegisters = false;
    151 
    152 struct 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 
    181 typedef X87Register FloatRegister;
    182 
    183 typedef X87Register DoubleRegister;
    184 
    185 // TODO(x87) Define SIMD registers.
    186 typedef X87Register Simd128Register;
    187 
    188 #define DECLARE_REGISTER(R) \
    189   const DoubleRegister R = {DoubleRegister::kCode_##R};
    190 DOUBLE_REGISTERS(DECLARE_REGISTER)
    191 #undef DECLARE_REGISTER
    192 const DoubleRegister no_double_reg = {DoubleRegister::kCode_no_reg};
    193 
    194 enum 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.
    229 inline 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}.
    235 inline 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 
    259 enum RoundingMode {
    260   kRoundToNearest = 0x0,
    261   kRoundDown = 0x1,
    262   kRoundUp = 0x2,
    263   kRoundToZero = 0x3
    264 };
    265 
    266 
    267 // -----------------------------------------------------------------------------
    268 // Machine instruction Immediates
    269 
    270 class 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 
    312 enum 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 
    324 class 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 
    428 class 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 
    459 class 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.
   1079 class 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