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