⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 assembler-ia32.h.svn-base

📁 Google浏览器V8内核代码
💻 SVN-BASE
📖 第 1 页 / 共 2 页
字号:
// Copyright (c) 1994-2006 Sun Microsystems Inc.// All Rights Reserved.//// Redistribution and use in source and binary forms, with or without// modification, are permitted provided that the following conditions are// met://// - Redistributions of source code must retain the above copyright notice,// this list of conditions and the following disclaimer.//// - Redistribution in binary form must reproduce the above copyright// notice, this list of conditions and the following disclaimer in the// documentation and/or other materials provided with the distribution.//// - Neither the name of Sun Microsystems or the names of contributors may// be used to endorse or promote products derived from this software without// specific prior written permission.//// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS// IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.// The original source code covered by the above license above has been// modified significantly by Google Inc.// Copyright 2006-2008 the V8 project authors. All rights reserved.// A light-weight IA32 Assembler.#ifndef V8_ASSEMBLER_IA32_H_#define V8_ASSEMBLER_IA32_H_namespace v8 { namespace internal {// CPU Registers.//// 1) We would prefer to use an enum, but enum values are assignment-// compatible with int, which has caused code-generation bugs.//// 2) We would prefer to use a class instead of a struct but we don't like// the register initialization to depend on the particular initialization// order (which appears to be different on OS X, Linux, and Windows for the// installed versions of C++ we tried). Using a struct permits C-style// "initialization". Also, the Register objects cannot be const as this// forces initialization stubs in MSVC, making us dependent on initialization// order.//// 3) By not using an enum, we are possibly preventing the compiler from// doing certain constant folds, which may significantly reduce the// code generated for some assembly instructions (because they boil down// to a few constants). If this is a problem, we could change the code// such that we use an enum in optimized mode, and the struct in debug// mode. This way we get the compile-time error checking in debug mode// and best performance in optimized code.//struct Register {  bool is_valid() const  { return 0 <= code_ && code_ < 8; }  bool is(Register reg) const  { return code_ == reg.code_; }  int code() const  {    ASSERT(is_valid());    return code_;  }  int bit() const  {    ASSERT(is_valid());    return 1 << code_;  }  // (unfortunately we can't make this private in a struct)  int code_;};extern Register eax;extern Register ecx;extern Register edx;extern Register ebx;extern Register esp;extern Register ebp;extern Register esi;extern Register edi;extern Register no_reg;struct XMMRegister {  bool is_valid() const  { return 0 <= code_ && code_ < 2; }  // currently  int code() const  {    ASSERT(is_valid());    return code_;  }  int code_;};extern XMMRegister xmm0;extern XMMRegister xmm1;extern XMMRegister xmm2;extern XMMRegister xmm3;extern XMMRegister xmm4;extern XMMRegister xmm5;extern XMMRegister xmm6;extern XMMRegister xmm7;enum Condition {  // any value < 0 is considered no_condition  no_condition  = -1,  overflow      =  0,  no_overflow   =  1,  below         =  2,  above_equal   =  3,  equal         =  4,  not_equal     =  5,  below_equal   =  6,  above         =  7,  sign          =  8,  not_sign      =  9,  parity_even   = 10,  parity_odd    = 11,  less          = 12,  greater_equal = 13,  less_equal    = 14,  greater       = 15,  // aliases  zero          = equal,  not_zero      = not_equal,  negative      = sign,  positive      = not_sign};// Returns the equivalent of !cc.// Negation of the default no_condition (-1) results in a non-default// no_condition value (-2). As long as tests for no_condition check// for condition < 0, this will work as expected.inline Condition NegateCondition(Condition cc);// Corresponds to transposing the operands of a comparison.inline Condition ReverseCondition(Condition cc) {  switch (cc) {    case below:      return above;    case above:      return below;    case above_equal:      return below_equal;    case below_equal:      return above_equal;    case less:      return greater;    case greater:      return less;    case greater_equal:      return less_equal;    case less_equal:      return greater_equal;    default:      return cc;  };}enum Hint {  no_hint = 0,  not_taken = 0x2e,  taken = 0x3e};// -----------------------------------------------------------------------------// Machine instruction Immediatesclass Immediate BASE_EMBEDDED { public:  inline explicit Immediate(int x);  inline explicit Immediate(const char* s);  inline explicit Immediate(const ExternalReference& ext);  inline explicit Immediate(Handle<Object> handle);  inline explicit Immediate(Smi* value);  bool is_zero() const { return x_ == 0 && rmode_ == RelocInfo::NONE; }  bool is_int8() const {    return -128 <= x_ && x_ < 128 && rmode_ == RelocInfo::NONE;  } private:  int x_;  RelocInfo::Mode rmode_;  friend class Assembler;};// -----------------------------------------------------------------------------// Machine instruction Operandsenum ScaleFactor {  times_1 = 0,  times_2 = 1,  times_4 = 2,  times_8 = 3};class Operand BASE_EMBEDDED { public:  // reg  INLINE(explicit Operand(Register reg));  // [disp/r]  INLINE(explicit Operand(int32_t disp, RelocInfo::Mode rmode));  // disp only must always be relocated  // [base + disp/r]  explicit Operand(Register base, int32_t disp,                   RelocInfo::Mode rmode = RelocInfo::NONE);  // [base + index*scale + disp/r]  explicit Operand(Register base,                   Register index,                   ScaleFactor scale,                   int32_t disp,                   RelocInfo::Mode rmode = RelocInfo::NONE);  // [index*scale + disp/r]  explicit Operand(Register index,                   ScaleFactor scale,                   int32_t disp,                   RelocInfo::Mode rmode = RelocInfo::NONE);  static Operand StaticVariable(const ExternalReference& ext) {    return Operand(reinterpret_cast<int32_t>(ext.address()),                   RelocInfo::EXTERNAL_REFERENCE);  }  static Operand StaticArray(Register index,                             ScaleFactor scale,                             const ExternalReference& arr) {    return Operand(index, scale, reinterpret_cast<int32_t>(arr.address()),                   RelocInfo::EXTERNAL_REFERENCE);  }  // Returns true if this Operand is a wrapper for the specified register.  bool is_reg(Register reg) const; private:  // Mutable because reg in ModR/M byte is set by Assembler via set_reg().  mutable byte buf_[6];  // The number of bytes in buf_.  unsigned int len_;  // Only valid if len_ > 4.  RelocInfo::Mode rmode_;  inline void set_modrm(int mod,  // reg == 0                        Register rm);  inline void set_sib(ScaleFactor scale, Register index, Register base);  inline void set_disp8(int8_t disp);  inline void set_dispr(int32_t disp, RelocInfo::Mode rmode);  inline void set_reg(Register reg) const;  friend class Assembler;};// -----------------------------------------------------------------------------// A Displacement describes the 32bit immediate field of an instruction which// may be used together with a Label in order to refer to a yet unknown code// position. Displacements stored in the instruction stream are used to describe// the instruction and to chain a list of instructions using the same Label.// A Displacement contains 2 different fields://// next field: position of next displacement in the chain (0 = end of list)// type field: instruction type//// A next value of null (0) indicates the end of a chain (note that there can// be no displacement at position zero, because there is always at least one// instruction byte before the displacement).//// Displacement _data field layout//// |31.....1| ......0|// [  next  |  type  |class Displacement BASE_EMBEDDED { public:  enum Type {    UNCONDITIONAL_JUMP,    OTHER  };  int data() const { return data_; }  Type type() const { return TypeField::decode(data_); }  void next(Label* L) const {    int n = NextField::decode(data_);    n > 0 ? L->link_to(n) : L->Unuse();  }  void link_to(Label* L) { init(L, type()); }  explicit Displacement(int data) { data_ = data; }  Displacement(Label* L, Type type) { init(L, type); }  void print() {    PrintF("%s (%x) ", (type() == UNCONDITIONAL_JUMP ? "jmp" : "[other]"),                       NextField::decode(data_));  } private:  int data_;  class TypeField: public BitField<Type, 0, 1> {};  class NextField: public BitField<int,  1, 32-1> {};  void init(Label* L, Type type);};// CpuFeatures keeps track of which features are supported by the target CPU.// Supported features must be enabled by a Scope before use.// Example://   if (CpuFeatures::IsSupported(SSE2)) {//     CpuFeatures::Scope fscope(SSE2);//     // Generate SSE2 floating point code.//   } else {//     // Generate standard x87 floating point code.//   }class CpuFeatures : public AllStatic { public:  // Feature flags bit positions. They are mostly based on the CPUID spec.  // (We assign CPUID itself to one of the currently reserved bits --  // feel free to change this if needed.)  enum Feature { SSE2 = 26, CMOV = 15, RDTSC = 4, CPUID = 10 };  // Detect features of the target CPU. Set safe defaults if the serializer  // is enabled (snapshots must be portable).  static void Probe();  // Check whether a feature is supported by the target CPU.  static bool IsSupported(Feature f) { return supported_ & (1 << f); }  // Check whether a feature is currently enabled.  static bool IsEnabled(Feature f) { return enabled_ & (1 << f); }  // Enable a specified feature within a scope.  class Scope BASE_EMBEDDED {#ifdef DEBUG   public:    explicit Scope(Feature f) {      ASSERT(CpuFeatures::IsSupported(f));      old_enabled_ = CpuFeatures::enabled_;      CpuFeatures::enabled_ |= (1 << f);    }    ~Scope() { CpuFeatures::enabled_ = old_enabled_; }   private:    uint32_t old_enabled_;#else   public:    explicit Scope(Feature f) {}#endif  }; private:  static uint32_t supported_;  static uint32_t enabled_;};class Assembler : public Malloced { private:  // The relocation writer's position is kGap bytes below the end of  // the generated instructions. This leaves enough space for the  // longest possible ia32 instruction (17 bytes as of 9/26/06) and  // allows for a single, fast space check per instruction.  static const int kGap = 32; public:  // Create an assembler. Instructions and relocation information are emitted  // into a buffer, with the instructions starting from the beginning and the  // relocation information starting from the end of the buffer. See CodeDesc  // for a detailed comment on the layout (globals.h).  //  // If the provided buffer is NULL, the assembler allocates and grows its own  // buffer, and buffer_size determines the initial buffer size. The buffer is  // owned by the assembler and deallocated upon destruction of the assembler.  //  // If the provided buffer is not NULL, the assembler uses the provided buffer  // for code generation and assumes its size to be buffer_size. If the buffer  // is too small, a fatal error occurs. No deallocation of the buffer is done  // upon destruction of the assembler.  Assembler(void* buffer, int buffer_size);  ~Assembler();  // GetCode emits any pending (non-emitted) code and fills the descriptor  // desc. GetCode() is idempotent; it returns the same result if no other  // Assembler functions are invoked inbetween GetCode() calls.  void GetCode(CodeDesc* desc);  // Read/Modify the code target in the branch/call instruction at pc.  inline static Address target_address_at(Address pc);  inline static void set_target_address_at(Address pc, Address target);  // Distance between the address of the code target in the call instruction  // and the return address  static const int kTargetAddrToReturnAddrDist = kPointerSize;  // ---------------------------------------------------------------------------  // Code generation  //

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -