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