Home | History | Annotate | Download | only in ia32
      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 2006-2008 the V8 project authors. All rights reserved.
     34 
     35 // A light-weight IA32 Assembler.
     36 
     37 #ifndef V8_IA32_ASSEMBLER_IA32_H_
     38 #define V8_IA32_ASSEMBLER_IA32_H_
     39 
     40 #include "serialize.h"
     41 
     42 namespace v8 {
     43 namespace internal {
     44 
     45 // CPU Registers.
     46 //
     47 // 1) We would prefer to use an enum, but enum values are assignment-
     48 // compatible with int, which has caused code-generation bugs.
     49 //
     50 // 2) We would prefer to use a class instead of a struct but we don't like
     51 // the register initialization to depend on the particular initialization
     52 // order (which appears to be different on OS X, Linux, and Windows for the
     53 // installed versions of C++ we tried). Using a struct permits C-style
     54 // "initialization". Also, the Register objects cannot be const as this
     55 // forces initialization stubs in MSVC, making us dependent on initialization
     56 // order.
     57 //
     58 // 3) By not using an enum, we are possibly preventing the compiler from
     59 // doing certain constant folds, which may significantly reduce the
     60 // code generated for some assembly instructions (because they boil down
     61 // to a few constants). If this is a problem, we could change the code
     62 // such that we use an enum in optimized mode, and the struct in debug
     63 // mode. This way we get the compile-time error checking in debug mode
     64 // and best performance in optimized code.
     65 //
     66 struct Register {
     67   bool is_valid() const  { return 0 <= code_ && code_ < 8; }
     68   bool is(Register reg) const  { return code_ == reg.code_; }
     69   // eax, ebx, ecx and edx are byte registers, the rest are not.
     70   bool is_byte_register() const  { return code_ <= 3; }
     71   int code() const  {
     72     ASSERT(is_valid());
     73     return code_;
     74   }
     75   int bit() const  {
     76     ASSERT(is_valid());
     77     return 1 << code_;
     78   }
     79 
     80   // Unfortunately we can't make this private in a struct.
     81   int code_;
     82 };
     83 
     84 const Register eax = { 0 };
     85 const Register ecx = { 1 };
     86 const Register edx = { 2 };
     87 const Register ebx = { 3 };
     88 const Register esp = { 4 };
     89 const Register ebp = { 5 };
     90 const Register esi = { 6 };
     91 const Register edi = { 7 };
     92 const Register no_reg = { -1 };
     93 
     94 
     95 struct XMMRegister {
     96   bool is_valid() const  { return 0 <= code_ && code_ < 2; }  // currently
     97   int code() const  {
     98     ASSERT(is_valid());
     99     return code_;
    100   }
    101 
    102   int code_;
    103 };
    104 
    105 const XMMRegister xmm0 = { 0 };
    106 const XMMRegister xmm1 = { 1 };
    107 const XMMRegister xmm2 = { 2 };
    108 const XMMRegister xmm3 = { 3 };
    109 const XMMRegister xmm4 = { 4 };
    110 const XMMRegister xmm5 = { 5 };
    111 const XMMRegister xmm6 = { 6 };
    112 const XMMRegister xmm7 = { 7 };
    113 
    114 enum Condition {
    115   // any value < 0 is considered no_condition
    116   no_condition  = -1,
    117 
    118   overflow      =  0,
    119   no_overflow   =  1,
    120   below         =  2,
    121   above_equal   =  3,
    122   equal         =  4,
    123   not_equal     =  5,
    124   below_equal   =  6,
    125   above         =  7,
    126   negative      =  8,
    127   positive      =  9,
    128   parity_even   = 10,
    129   parity_odd    = 11,
    130   less          = 12,
    131   greater_equal = 13,
    132   less_equal    = 14,
    133   greater       = 15,
    134 
    135   // aliases
    136   carry         = below,
    137   not_carry     = above_equal,
    138   zero          = equal,
    139   not_zero      = not_equal,
    140   sign          = negative,
    141   not_sign      = positive
    142 };
    143 
    144 
    145 // Returns the equivalent of !cc.
    146 // Negation of the default no_condition (-1) results in a non-default
    147 // no_condition value (-2). As long as tests for no_condition check
    148 // for condition < 0, this will work as expected.
    149 inline Condition NegateCondition(Condition cc);
    150 
    151 // Corresponds to transposing the operands of a comparison.
    152 inline Condition ReverseCondition(Condition cc) {
    153   switch (cc) {
    154     case below:
    155       return above;
    156     case above:
    157       return below;
    158     case above_equal:
    159       return below_equal;
    160     case below_equal:
    161       return above_equal;
    162     case less:
    163       return greater;
    164     case greater:
    165       return less;
    166     case greater_equal:
    167       return less_equal;
    168     case less_equal:
    169       return greater_equal;
    170     default:
    171       return cc;
    172   };
    173 }
    174 
    175 enum Hint {
    176   no_hint = 0,
    177   not_taken = 0x2e,
    178   taken = 0x3e
    179 };
    180 
    181 // The result of negating a hint is as if the corresponding condition
    182 // were negated by NegateCondition.  That is, no_hint is mapped to
    183 // itself and not_taken and taken are mapped to each other.
    184 inline Hint NegateHint(Hint hint) {
    185   return (hint == no_hint)
    186       ? no_hint
    187       : ((hint == not_taken) ? taken : not_taken);
    188 }
    189 
    190 
    191 // -----------------------------------------------------------------------------
    192 // Machine instruction Immediates
    193 
    194 class Immediate BASE_EMBEDDED {
    195  public:
    196   inline explicit Immediate(int x);
    197   inline explicit Immediate(const char* s);
    198   inline explicit Immediate(const ExternalReference& ext);
    199   inline explicit Immediate(Handle<Object> handle);
    200   inline explicit Immediate(Smi* value);
    201 
    202   static Immediate CodeRelativeOffset(Label* label) {
    203     return Immediate(label);
    204   }
    205 
    206   bool is_zero() const { return x_ == 0 && rmode_ == RelocInfo::NONE; }
    207   bool is_int8() const {
    208     return -128 <= x_ && x_ < 128 && rmode_ == RelocInfo::NONE;
    209   }
    210   bool is_int16() const {
    211     return -32768 <= x_ && x_ < 32768 && rmode_ == RelocInfo::NONE;
    212   }
    213 
    214  private:
    215   inline explicit Immediate(Label* value);
    216 
    217   int x_;
    218   RelocInfo::Mode rmode_;
    219 
    220   friend class Assembler;
    221 };
    222 
    223 
    224 // -----------------------------------------------------------------------------
    225 // Machine instruction Operands
    226 
    227 enum ScaleFactor {
    228   times_1 = 0,
    229   times_2 = 1,
    230   times_4 = 2,
    231   times_8 = 3,
    232   times_int_size = times_4,
    233   times_half_pointer_size = times_2,
    234   times_pointer_size = times_4,
    235   times_twice_pointer_size = times_8
    236 };
    237 
    238 
    239 class Operand BASE_EMBEDDED {
    240  public:
    241   // reg
    242   INLINE(explicit Operand(Register reg));
    243 
    244   // [disp/r]
    245   INLINE(explicit Operand(int32_t disp, RelocInfo::Mode rmode));
    246   // disp only must always be relocated
    247 
    248   // [base + disp/r]
    249   explicit Operand(Register base, int32_t disp,
    250                    RelocInfo::Mode rmode = RelocInfo::NONE);
    251 
    252   // [base + index*scale + disp/r]
    253   explicit Operand(Register base,
    254                    Register index,
    255                    ScaleFactor scale,
    256                    int32_t disp,
    257                    RelocInfo::Mode rmode = RelocInfo::NONE);
    258 
    259   // [index*scale + disp/r]
    260   explicit Operand(Register index,
    261                    ScaleFactor scale,
    262                    int32_t disp,
    263                    RelocInfo::Mode rmode = RelocInfo::NONE);
    264 
    265   static Operand StaticVariable(const ExternalReference& ext) {
    266     return Operand(reinterpret_cast<int32_t>(ext.address()),
    267                    RelocInfo::EXTERNAL_REFERENCE);
    268   }
    269 
    270   static Operand StaticArray(Register index,
    271                              ScaleFactor scale,
    272                              const ExternalReference& arr) {
    273     return Operand(index, scale, reinterpret_cast<int32_t>(arr.address()),
    274                    RelocInfo::EXTERNAL_REFERENCE);
    275   }
    276 
    277   // Returns true if this Operand is a wrapper for the specified register.
    278   bool is_reg(Register reg) const;
    279 
    280  private:
    281   byte buf_[6];
    282   // The number of bytes in buf_.
    283   unsigned int len_;
    284   // Only valid if len_ > 4.
    285   RelocInfo::Mode rmode_;
    286 
    287   // Set the ModRM byte without an encoded 'reg' register. The
    288   // register is encoded later as part of the emit_operand operation.
    289   inline void set_modrm(int mod, Register rm);
    290 
    291   inline void set_sib(ScaleFactor scale, Register index, Register base);
    292   inline void set_disp8(int8_t disp);
    293   inline void set_dispr(int32_t disp, RelocInfo::Mode rmode);
    294 
    295   friend class Assembler;
    296 };
    297 
    298 
    299 // -----------------------------------------------------------------------------
    300 // A Displacement describes the 32bit immediate field of an instruction which
    301 // may be used together with a Label in order to refer to a yet unknown code
    302 // position. Displacements stored in the instruction stream are used to describe
    303 // the instruction and to chain a list of instructions using the same Label.
    304 // A Displacement contains 2 different fields:
    305 //
    306 // next field: position of next displacement in the chain (0 = end of list)
    307 // type field: instruction type
    308 //
    309 // A next value of null (0) indicates the end of a chain (note that there can
    310 // be no displacement at position zero, because there is always at least one
    311 // instruction byte before the displacement).
    312 //
    313 // Displacement _data field layout
    314 //
    315 // |31.....2|1......0|
    316 // [  next  |  type  |
    317 
    318 class Displacement BASE_EMBEDDED {
    319  public:
    320   enum Type {
    321     UNCONDITIONAL_JUMP,
    322     CODE_RELATIVE,
    323     OTHER
    324   };
    325 
    326   int data() const { return data_; }
    327   Type type() const { return TypeField::decode(data_); }
    328   void next(Label* L) const {
    329     int n = NextField::decode(data_);
    330     n > 0 ? L->link_to(n) : L->Unuse();
    331   }
    332   void link_to(Label* L) { init(L, type()); }
    333 
    334   explicit Displacement(int data) { data_ = data; }
    335 
    336   Displacement(Label* L, Type type) { init(L, type); }
    337 
    338   void print() {
    339     PrintF("%s (%x) ", (type() == UNCONDITIONAL_JUMP ? "jmp" : "[other]"),
    340                        NextField::decode(data_));
    341   }
    342 
    343  private:
    344   int data_;
    345 
    346   class TypeField: public BitField<Type, 0, 2> {};
    347   class NextField: public BitField<int,  2, 32-2> {};
    348 
    349   void init(Label* L, Type type);
    350 };
    351 
    352 
    353 
    354 // CpuFeatures keeps track of which features are supported by the target CPU.
    355 // Supported features must be enabled by a Scope before use.
    356 // Example:
    357 //   if (CpuFeatures::IsSupported(SSE2)) {
    358 //     CpuFeatures::Scope fscope(SSE2);
    359 //     // Generate SSE2 floating point code.
    360 //   } else {
    361 //     // Generate standard x87 floating point code.
    362 //   }
    363 class CpuFeatures : public AllStatic {
    364  public:
    365   // Detect features of the target CPU. Set safe defaults if the serializer
    366   // is enabled (snapshots must be portable).
    367   static void Probe();
    368   // Check whether a feature is supported by the target CPU.
    369   static bool IsSupported(CpuFeature f) {
    370     if (f == SSE2 && !FLAG_enable_sse2) return false;
    371     if (f == SSE3 && !FLAG_enable_sse3) return false;
    372     if (f == CMOV && !FLAG_enable_cmov) return false;
    373     if (f == RDTSC && !FLAG_enable_rdtsc) return false;
    374     return (supported_ & (static_cast<uint64_t>(1) << f)) != 0;
    375   }
    376   // Check whether a feature is currently enabled.
    377   static bool IsEnabled(CpuFeature f) {
    378     return (enabled_ & (static_cast<uint64_t>(1) << f)) != 0;
    379   }
    380   // Enable a specified feature within a scope.
    381   class Scope BASE_EMBEDDED {
    382 #ifdef DEBUG
    383    public:
    384     explicit Scope(CpuFeature f) {
    385       uint64_t mask = static_cast<uint64_t>(1) << f;
    386       ASSERT(CpuFeatures::IsSupported(f));
    387       ASSERT(!Serializer::enabled() || (found_by_runtime_probing_ & mask) == 0);
    388       old_enabled_ = CpuFeatures::enabled_;
    389       CpuFeatures::enabled_ |= mask;
    390     }
    391     ~Scope() { CpuFeatures::enabled_ = old_enabled_; }
    392    private:
    393     uint64_t old_enabled_;
    394 #else
    395    public:
    396     explicit Scope(CpuFeature f) {}
    397 #endif
    398   };
    399  private:
    400   static uint64_t supported_;
    401   static uint64_t enabled_;
    402   static uint64_t found_by_runtime_probing_;
    403 };
    404 
    405 
    406 class Assembler : public Malloced {
    407  private:
    408   // We check before assembling an instruction that there is sufficient
    409   // space to write an instruction and its relocation information.
    410   // The relocation writer's position must be kGap bytes above the end of
    411   // the generated instructions. This leaves enough space for the
    412   // longest possible ia32 instruction, 15 bytes, and the longest possible
    413   // relocation information encoding, RelocInfoWriter::kMaxLength == 16.
    414   // (There is a 15 byte limit on ia32 instruction length that rules out some
    415   // otherwise valid instructions.)
    416   // This allows for a single, fast space check per instruction.
    417   static const int kGap = 32;
    418 
    419  public:
    420   // Create an assembler. Instructions and relocation information are emitted
    421   // into a buffer, with the instructions starting from the beginning and the
    422   // relocation information starting from the end of the buffer. See CodeDesc
    423   // for a detailed comment on the layout (globals.h).
    424   //
    425   // If the provided buffer is NULL, the assembler allocates and grows its own
    426   // buffer, and buffer_size determines the initial buffer size. The buffer is
    427   // owned by the assembler and deallocated upon destruction of the assembler.
    428   //
    429   // If the provided buffer is not NULL, the assembler uses the provided buffer
    430   // for code generation and assumes its size to be buffer_size. If the buffer
    431   // is too small, a fatal error occurs. No deallocation of the buffer is done
    432   // upon destruction of the assembler.
    433   Assembler(void* buffer, int buffer_size);
    434   ~Assembler();
    435 
    436   // GetCode emits any pending (non-emitted) code and fills the descriptor
    437   // desc. GetCode() is idempotent; it returns the same result if no other
    438   // Assembler functions are invoked in between GetCode() calls.
    439   void GetCode(CodeDesc* desc);
    440 
    441   // Read/Modify the code target in the branch/call instruction at pc.
    442   inline static Address target_address_at(Address pc);
    443   inline static void set_target_address_at(Address pc, Address target);
    444 
    445   // This sets the branch destination (which is in the instruction on x86).
    446   // This is for calls and branches within generated code.
    447   inline static void set_target_at(Address instruction_payload,
    448                                    Address target) {
    449     set_target_address_at(instruction_payload, target);
    450   }
    451 
    452   // This sets the branch destination (which is in the instruction on x86).
    453   // This is for calls and branches to runtime code.
    454   inline static void set_external_target_at(Address instruction_payload,
    455                                             Address target) {
    456     set_target_address_at(instruction_payload, target);
    457   }
    458 
    459   static const int kCallTargetSize = kPointerSize;
    460   static const int kExternalTargetSize = kPointerSize;
    461 
    462   // Distance between the address of the code target in the call instruction
    463   // and the return address
    464   static const int kCallTargetAddressOffset = kPointerSize;
    465   // Distance between start of patched return sequence and the emitted address
    466   // to jump to.
    467   static const int kPatchReturnSequenceAddressOffset = 1;  // JMP imm32.
    468 
    469   static const int kCallInstructionLength = 5;
    470   static const int kJSReturnSequenceLength = 6;
    471 
    472   // ---------------------------------------------------------------------------
    473   // Code generation
    474   //
    475   // - function names correspond one-to-one to ia32 instruction mnemonics
    476   // - unless specified otherwise, instructions operate on 32bit operands
    477   // - instructions on 8bit (byte) operands/registers have a trailing '_b'
    478   // - instructions on 16bit (word) operands/registers have a trailing '_w'
    479   // - naming conflicts with C++ keywords are resolved via a trailing '_'
    480 
    481   // NOTE ON INTERFACE: Currently, the interface is not very consistent
    482   // in the sense that some operations (e.g. mov()) can be called in more
    483   // the one way to generate the same instruction: The Register argument
    484   // can in some cases be replaced with an Operand(Register) argument.
    485   // This should be cleaned up and made more orthogonal. The questions
    486   // is: should we always use Operands instead of Registers where an
    487   // Operand is possible, or should we have a Register (overloaded) form
    488   // instead? We must be careful to make sure that the selected instruction
    489   // is obvious from the parameters to avoid hard-to-find code generation
    490   // bugs.
    491 
    492   // Insert the smallest number of nop instructions
    493   // possible to align the pc offset to a multiple
    494   // of m. m must be a power of 2.
    495   void Align(int m);
    496 
    497   // Stack
    498   void pushad();
    499   void popad();
    500 
    501   void pushfd();
    502   void popfd();
    503 
    504   void push(const Immediate& x);
    505   void push(Register src);
    506   void push(const Operand& src);
    507   void push(Label* label, RelocInfo::Mode relocation_mode);
    508 
    509   void pop(Register dst);
    510   void pop(const Operand& dst);
    511 
    512   void enter(const Immediate& size);
    513   void leave();
    514 
    515   // Moves
    516   void mov_b(Register dst, const Operand& src);
    517   void mov_b(const Operand& dst, int8_t imm8);
    518   void mov_b(const Operand& dst, Register src);
    519 
    520   void mov_w(Register dst, const Operand& src);
    521   void mov_w(const Operand& dst, Register src);
    522 
    523   void mov(Register dst, int32_t imm32);
    524   void mov(Register dst, const Immediate& x);
    525   void mov(Register dst, Handle<Object> handle);
    526   void mov(Register dst, const Operand& src);
    527   void mov(Register dst, Register src);
    528   void mov(const Operand& dst, const Immediate& x);
    529   void mov(const Operand& dst, Handle<Object> handle);
    530   void mov(const Operand& dst, Register src);
    531 
    532   void movsx_b(Register dst, const Operand& src);
    533 
    534   void movsx_w(Register dst, const Operand& src);
    535 
    536   void movzx_b(Register dst, const Operand& src);
    537 
    538   void movzx_w(Register dst, const Operand& src);
    539 
    540   // Conditional moves
    541   void cmov(Condition cc, Register dst, int32_t imm32);
    542   void cmov(Condition cc, Register dst, Handle<Object> handle);
    543   void cmov(Condition cc, Register dst, const Operand& src);
    544 
    545   // Repetitive string instructions.
    546   void rep_movs();
    547 
    548   // Exchange two registers
    549   void xchg(Register dst, Register src);
    550 
    551   // Arithmetics
    552   void adc(Register dst, int32_t imm32);
    553   void adc(Register dst, const Operand& src);
    554 
    555   void add(Register dst, const Operand& src);
    556   void add(const Operand& dst, const Immediate& x);
    557 
    558   void and_(Register dst, int32_t imm32);
    559   void and_(Register dst, const Operand& src);
    560   void and_(const Operand& src, Register dst);
    561   void and_(const Operand& dst, const Immediate& x);
    562 
    563   void cmpb(const Operand& op, int8_t imm8);
    564   void cmpb(Register src, const Operand& dst);
    565   void cmpb(const Operand& dst, Register src);
    566   void cmpb_al(const Operand& op);
    567   void cmpw_ax(const Operand& op);
    568   void cmpw(const Operand& op, Immediate imm16);
    569   void cmp(Register reg, int32_t imm32);
    570   void cmp(Register reg, Handle<Object> handle);
    571   void cmp(Register reg, const Operand& op);
    572   void cmp(const Operand& op, const Immediate& imm);
    573   void cmp(const Operand& op, Handle<Object> handle);
    574 
    575   void dec_b(Register dst);
    576 
    577   void dec(Register dst);
    578   void dec(const Operand& dst);
    579 
    580   void cdq();
    581 
    582   void idiv(Register src);
    583 
    584   // Signed multiply instructions.
    585   void imul(Register src);                               // edx:eax = eax * src.
    586   void imul(Register dst, const Operand& src);           // dst = dst * src.
    587   void imul(Register dst, Register src, int32_t imm32);  // dst = src * imm32.
    588 
    589   void inc(Register dst);
    590   void inc(const Operand& dst);
    591 
    592   void lea(Register dst, const Operand& src);
    593 
    594   // Unsigned multiply instruction.
    595   void mul(Register src);                                // edx:eax = eax * reg.
    596 
    597   void neg(Register dst);
    598 
    599   void not_(Register dst);
    600 
    601   void or_(Register dst, int32_t imm32);
    602   void or_(Register dst, const Operand& src);
    603   void or_(const Operand& dst, Register src);
    604   void or_(const Operand& dst, const Immediate& x);
    605 
    606   void rcl(Register dst, uint8_t imm8);
    607 
    608   void sar(Register dst, uint8_t imm8);
    609   void sar_cl(Register dst);
    610 
    611   void sbb(Register dst, const Operand& src);
    612 
    613   void shld(Register dst, const Operand& src);
    614 
    615   void shl(Register dst, uint8_t imm8);
    616   void shl_cl(Register dst);
    617 
    618   void shrd(Register dst, const Operand& src);
    619 
    620   void shr(Register dst, uint8_t imm8);
    621   void shr_cl(Register dst);
    622 
    623   void subb(const Operand& dst, int8_t imm8);
    624   void subb(Register dst, const Operand& src);
    625   void sub(const Operand& dst, const Immediate& x);
    626   void sub(Register dst, const Operand& src);
    627   void sub(const Operand& dst, Register src);
    628 
    629   void test(Register reg, const Immediate& imm);
    630   void test(Register reg, const Operand& op);
    631   void test_b(Register reg, const Operand& op);
    632   void test(const Operand& op, const Immediate& imm);
    633 
    634   void xor_(Register dst, int32_t imm32);
    635   void xor_(Register dst, const Operand& src);
    636   void xor_(const Operand& src, Register dst);
    637   void xor_(const Operand& dst, const Immediate& x);
    638 
    639   // Bit operations.
    640   void bt(const Operand& dst, Register src);
    641   void bts(const Operand& dst, Register src);
    642 
    643   // Miscellaneous
    644   void hlt();
    645   void int3();
    646   void nop();
    647   void rdtsc();
    648   void ret(int imm16);
    649 
    650   // Label operations & relative jumps (PPUM Appendix D)
    651   //
    652   // Takes a branch opcode (cc) and a label (L) and generates
    653   // either a backward branch or a forward branch and links it
    654   // to the label fixup chain. Usage:
    655   //
    656   // Label L;    // unbound label
    657   // j(cc, &L);  // forward branch to unbound label
    658   // bind(&L);   // bind label to the current pc
    659   // j(cc, &L);  // backward branch to bound label
    660   // bind(&L);   // illegal: a label may be bound only once
    661   //
    662   // Note: The same Label can be used for forward and backward branches
    663   // but it may be bound only once.
    664 
    665   void bind(Label* L);  // binds an unbound label L to the current code position
    666 
    667   // Calls
    668   void call(Label* L);
    669   void call(byte* entry, RelocInfo::Mode rmode);
    670   void call(const Operand& adr);
    671   void call(const ExternalReference& target);
    672   void call(Handle<Code> code, RelocInfo::Mode rmode);
    673 
    674   // Jumps
    675   void jmp(Label* L);  // unconditional jump to L
    676   void jmp(byte* entry, RelocInfo::Mode rmode);
    677   void jmp(const Operand& adr);
    678   void jmp(Handle<Code> code, RelocInfo::Mode rmode);
    679 
    680   // Conditional jumps
    681   void j(Condition cc, Label* L, Hint hint = no_hint);
    682   void j(Condition cc, byte* entry, RelocInfo::Mode rmode, Hint hint = no_hint);
    683   void j(Condition cc, Handle<Code> code, Hint hint = no_hint);
    684 
    685   // Floating-point operations
    686   void fld(int i);
    687   void fstp(int i);
    688 
    689   void fld1();
    690   void fldz();
    691   void fldpi();
    692 
    693   void fld_s(const Operand& adr);
    694   void fld_d(const Operand& adr);
    695 
    696   void fstp_s(const Operand& adr);
    697   void fstp_d(const Operand& adr);
    698   void fst_d(const Operand& adr);
    699 
    700   void fild_s(const Operand& adr);
    701   void fild_d(const Operand& adr);
    702 
    703   void fist_s(const Operand& adr);
    704 
    705   void fistp_s(const Operand& adr);
    706   void fistp_d(const Operand& adr);
    707 
    708   void fisttp_s(const Operand& adr);
    709   void fisttp_d(const Operand& adr);
    710 
    711   void fabs();
    712   void fchs();
    713   void fcos();
    714   void fsin();
    715 
    716   void fadd(int i);
    717   void fsub(int i);
    718   void fmul(int i);
    719   void fdiv(int i);
    720 
    721   void fisub_s(const Operand& adr);
    722 
    723   void faddp(int i = 1);
    724   void fsubp(int i = 1);
    725   void fsubrp(int i = 1);
    726   void fmulp(int i = 1);
    727   void fdivp(int i = 1);
    728   void fprem();
    729   void fprem1();
    730 
    731   void fxch(int i = 1);
    732   void fincstp();
    733   void ffree(int i = 0);
    734 
    735   void ftst();
    736   void fucomp(int i);
    737   void fucompp();
    738   void fucomi(int i);
    739   void fucomip();
    740   void fcompp();
    741   void fnstsw_ax();
    742   void fwait();
    743   void fnclex();
    744 
    745   void frndint();
    746 
    747   void sahf();
    748   void setcc(Condition cc, Register reg);
    749 
    750   void cpuid();
    751 
    752   // SSE2 instructions
    753   void cvttss2si(Register dst, const Operand& src);
    754   void cvttsd2si(Register dst, const Operand& src);
    755 
    756   void cvtsi2sd(XMMRegister dst, const Operand& src);
    757 
    758   void addsd(XMMRegister dst, XMMRegister src);
    759   void subsd(XMMRegister dst, XMMRegister src);
    760   void mulsd(XMMRegister dst, XMMRegister src);
    761   void divsd(XMMRegister dst, XMMRegister src);
    762   void xorpd(XMMRegister dst, XMMRegister src);
    763 
    764   void comisd(XMMRegister dst, XMMRegister src);
    765 
    766   void movdqa(XMMRegister dst, const Operand& src);
    767   void movdqa(const Operand& dst, XMMRegister src);
    768   void movdqu(XMMRegister dst, const Operand& src);
    769   void movdqu(const Operand& dst, XMMRegister src);
    770 
    771   // Use either movsd or movlpd.
    772   void movdbl(XMMRegister dst, const Operand& src);
    773   void movdbl(const Operand& dst, XMMRegister src);
    774 
    775   // Debugging
    776   void Print();
    777 
    778   // Check the code size generated from label to here.
    779   int SizeOfCodeGeneratedSince(Label* l) { return pc_offset() - l->pos(); }
    780 
    781   // Mark address of the ExitJSFrame code.
    782   void RecordJSReturn();
    783 
    784   // Record a comment relocation entry that can be used by a disassembler.
    785   // Use --debug_code to enable.
    786   void RecordComment(const char* msg);
    787 
    788   void RecordPosition(int pos);
    789   void RecordStatementPosition(int pos);
    790   void WriteRecordedPositions();
    791 
    792   // Writes a single word of data in the code stream.
    793   // Used for inline tables, e.g., jump-tables.
    794   void dd(uint32_t data, RelocInfo::Mode reloc_info);
    795 
    796   int pc_offset() const  { return pc_ - buffer_; }
    797   int current_statement_position() const { return current_statement_position_; }
    798   int current_position() const  { return current_position_; }
    799 
    800   // Check if there is less than kGap bytes available in the buffer.
    801   // If this is the case, we need to grow the buffer before emitting
    802   // an instruction or relocation information.
    803   inline bool overflow() const { return pc_ >= reloc_info_writer.pos() - kGap; }
    804 
    805   // Get the number of bytes available in the buffer.
    806   inline int available_space() const { return reloc_info_writer.pos() - pc_; }
    807 
    808   // Avoid overflows for displacements etc.
    809   static const int kMaximalBufferSize = 512*MB;
    810   static const int kMinimalBufferSize = 4*KB;
    811 
    812  protected:
    813   void movsd(XMMRegister dst, const Operand& src);
    814   void movsd(const Operand& dst, XMMRegister src);
    815 
    816   void emit_sse_operand(XMMRegister reg, const Operand& adr);
    817   void emit_sse_operand(XMMRegister dst, XMMRegister src);
    818 
    819 
    820  private:
    821   byte* addr_at(int pos)  { return buffer_ + pos; }
    822   byte byte_at(int pos)  { return buffer_[pos]; }
    823   uint32_t long_at(int pos)  {
    824     return *reinterpret_cast<uint32_t*>(addr_at(pos));
    825   }
    826   void long_at_put(int pos, uint32_t x)  {
    827     *reinterpret_cast<uint32_t*>(addr_at(pos)) = x;
    828   }
    829 
    830   // code emission
    831   void GrowBuffer();
    832   inline void emit(uint32_t x);
    833   inline void emit(Handle<Object> handle);
    834   inline void emit(uint32_t x, RelocInfo::Mode rmode);
    835   inline void emit(const Immediate& x);
    836   inline void emit_w(const Immediate& x);
    837 
    838   // Emit the code-object-relative offset of the label's position
    839   inline void emit_code_relative_offset(Label* label);
    840 
    841   // instruction generation
    842   void emit_arith_b(int op1, int op2, Register dst, int imm8);
    843 
    844   // Emit a basic arithmetic instruction (i.e. first byte of the family is 0x81)
    845   // with a given destination expression and an immediate operand.  It attempts
    846   // to use the shortest encoding possible.
    847   // sel specifies the /n in the modrm byte (see the Intel PRM).
    848   void emit_arith(int sel, Operand dst, const Immediate& x);
    849 
    850   void emit_operand(Register reg, const Operand& adr);
    851 
    852   void emit_farith(int b1, int b2, int i);
    853 
    854   // labels
    855   void print(Label* L);
    856   void bind_to(Label* L, int pos);
    857   void link_to(Label* L, Label* appendix);
    858 
    859   // displacements
    860   inline Displacement disp_at(Label* L);
    861   inline void disp_at_put(Label* L, Displacement disp);
    862   inline void emit_disp(Label* L, Displacement::Type type);
    863 
    864   // record reloc info for current pc_
    865   void RecordRelocInfo(RelocInfo::Mode rmode, intptr_t data = 0);
    866 
    867   friend class CodePatcher;
    868   friend class EnsureSpace;
    869 
    870   // Code buffer:
    871   // The buffer into which code and relocation info are generated.
    872   byte* buffer_;
    873   int buffer_size_;
    874   // True if the assembler owns the buffer, false if buffer is external.
    875   bool own_buffer_;
    876   // A previously allocated buffer of kMinimalBufferSize bytes, or NULL.
    877   static byte* spare_buffer_;
    878 
    879   // code generation
    880   byte* pc_;  // the program counter; moves forward
    881   RelocInfoWriter reloc_info_writer;
    882 
    883   // push-pop elimination
    884   byte* last_pc_;
    885 
    886   // source position information
    887   int current_statement_position_;
    888   int current_position_;
    889   int written_statement_position_;
    890   int written_position_;
    891 };
    892 
    893 
    894 // Helper class that ensures that there is enough space for generating
    895 // instructions and relocation information.  The constructor makes
    896 // sure that there is enough space and (in debug mode) the destructor
    897 // checks that we did not generate too much.
    898 class EnsureSpace BASE_EMBEDDED {
    899  public:
    900   explicit EnsureSpace(Assembler* assembler) : assembler_(assembler) {
    901     if (assembler_->overflow()) assembler_->GrowBuffer();
    902 #ifdef DEBUG
    903     space_before_ = assembler_->available_space();
    904 #endif
    905   }
    906 
    907 #ifdef DEBUG
    908   ~EnsureSpace() {
    909     int bytes_generated = space_before_ - assembler_->available_space();
    910     ASSERT(bytes_generated < assembler_->kGap);
    911   }
    912 #endif
    913 
    914  private:
    915   Assembler* assembler_;
    916 #ifdef DEBUG
    917   int space_before_;
    918 #endif
    919 };
    920 
    921 } }  // namespace v8::internal
    922 
    923 #endif  // V8_IA32_ASSEMBLER_IA32_H_
    924