Coverage for /Syzygy/core/assembler.h

CoverageLines executed / instrumented / missingexe / inst / missLanguageGroup
100.0%22220.C++source

Line-by-line coverage:

   1    :  // Copyright 2012 Google Inc.
   2    :  //
   3    :  // Licensed under the Apache License, Version 2.0 (the "License");
   4    :  // you may not use this file except in compliance with the License.
   5    :  // You may obtain a copy of the License at
   6    :  //
   7    :  //     http://www.apache.org/licenses/LICENSE-2.0
   8    :  //
   9    :  // Unless required by applicable law or agreed to in writing, software
  10    :  // distributed under the License is distributed on an "AS IS" BASIS,
  11    :  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12    :  // See the License for the specific language governing permissions and
  13    :  // limitations under the License.
  14    :  //
  15    :  // This file declares implementation classes to generate assembly code.
  16    :  // The API to the assembler is intentionally very close to the API exposed
  17    :  // by the V8 assembler.
  18    :  
  19    :  #ifndef SYZYGY_CORE_ASSEMBLER_H_
  20    :  #define SYZYGY_CORE_ASSEMBLER_H_
  21    :  
  22    :  #include "base/basictypes.h"
  23    :  #include "base/logging.h"
  24    :  
  25    :  namespace core {
  26    :  
  27    :  enum RegisterCode {
  28    :    kRegisterNone = -1,
  29    :    kRegisterEax = 0,
  30    :    kRegisterEcx = 1,
  31    :    kRegisterEdx = 2,
  32    :    kRegisterEbx = 3,
  33    :    kRegisterEsp = 4,
  34    :    kRegisterEbp = 5,
  35    :    kRegisterEsi = 6,
  36    :    kRegisterEdi = 7,
  37    :  };
  38    :  
  39    :  // The condition codes by which conditional branches are determined. This enum
  40    :  // is taken from the V8 project, and has the property that the conditions are
  41    :  // defined to be bit-wise ORed into the base conditional branch opcode, and
  42    :  // they can be easily negated/inverted.
  43    :  //
  44    :  // See:
  45    :  //     http://code.google.com/p/v8/source/browse/trunk/src/ia32/assembler-ia32.h
  46    :  enum ConditionCode {
  47    :    // Any value < 0 is considered no_condition
  48    :    kNoCondition  = -1,
  49    :  
  50    :    kOverflow =  0,
  51    :    kNoOverflow =  1,
  52    :    kBelow =  2,
  53    :    kAboveEqual =  3,
  54    :    kEqual =  4,
  55    :    kNotEqual =  5,
  56    :    kBelowEqual =  6,
  57    :    kAbove =  7,
  58    :    kNegative =  8,
  59    :    kPositive =  9,
  60    :    kParityEven = 10,
  61    :    kParityOdd = 11,
  62    :    kLess = 12,
  63    :    kGreaterEqual = 13,
  64    :    kLessEqual = 14,
  65    :    kGreater = 15,
  66    :  
  67    :    // Aliases.
  68    :    kCarry = kBelow,
  69    :    kNotCarry = kAboveEqual,
  70    :    kZero = kEqual,
  71    :    kNotZero = kNotEqual,
  72    :    kSign = kNegative,
  73    :    kNotSign = kPositive,
  74    :  
  75    :    // Extents.
  76    :    kMinConditionCode = 0,
  77    :    kMaxConditionCode = 15
  78    :  };
  79    :  
  80    :  // The conditions on which a loop instruction should branch. These are modeled
  81    :  // in the same manner as ConditionCode (above).
  82    :  enum LoopCode {
  83    :    kLoopOnCounterAndNotZeroFlag = 0,  // LOOPNE and LOOPNZ
  84    :    kLoopOnCounterAndZeroFlag = 1,  // LOOPE and NOOPZ.
  85    :    kLoopOnCounter = 2,  // LOOP.
  86    :  };
  87    :  
  88  E :  inline ConditionCode NegateConditionCode(ConditionCode cc) {
  89  E :    DCHECK_GT(16, cc);
  90  E :    return static_cast<ConditionCode>(cc ^ 1);
  91  E :  }
  92    :  
  93    :  // Each instance of this class names a register.
  94    :  class Register {
  95    :   public:
  96  E :    explicit Register(RegisterCode code) : code_(code) {
  97  E :      DCHECK(code != kRegisterNone);
  98  E :    }
  99    :  
 100  E :    RegisterCode code() const { return code_; }
 101    :    void set_code(RegisterCode code) { code_ = code; }
 102    :  
 103    :   private:
 104    :    RegisterCode code_;
 105    :  };
 106    :  
 107    :  // Convenience constants for the x86 registers.
 108    :  extern const Register eax;
 109    :  extern const Register ecx;
 110    :  extern const Register edx;
 111    :  extern const Register ebx;
 112    :  extern const Register esp;
 113    :  extern const Register ebp;
 114    :  extern const Register esi;
 115    :  extern const Register edi;
 116    :  
 117    :  // Selects a scale for the Operand addressing modes.
 118    :  // The values match the encoding in the x86 SIB bytes.
 119    :  enum ScaleFactor {
 120    :    kTimes1 = 0,
 121    :    kTimes2 = 1,
 122    :    kTimes4 = 2,
 123    :    kTimes8 = 3,
 124    :  };
 125    :  
 126    :  // Size for immediate and displacement operands.
 127    :  enum ValueSize {
 128    :    kSizeNone,
 129    :    kSize8Bit,
 130    :    kSize32Bit,
 131    :  };
 132    :  
 133    :  // An instance of this class is an explicit value, which is either
 134    :  // an immediate or a displacement.
 135    :  class ValueImpl  {
 136    :   public:
 137    :    ValueImpl();
 138    :    ValueImpl(uint32 value, ValueSize size);
 139    :    ValueImpl(uint32 value, ValueSize size, const void* imm_ref);
 140    :  
 141    :    // @name Accessors.
 142    :    // @{
 143  E :    uint32 value() const { return value_; }
 144  E :    const void* reference() const { return reference_; }
 145  E :    ValueSize size() const { return size_; }
 146    :    // @}
 147    :  
 148    :   private:
 149    :    uint32 value_;
 150    :    const void* reference_;
 151    :    ValueSize size_;
 152    :  };
 153    :  
 154    :  // Displacements and immediates behave near-identically, but are semantically
 155    :  // slightly different.
 156    :  typedef ValueImpl ImmediateImpl;
 157    :  typedef ValueImpl DisplacementImpl;
 158    :  
 159    :  // An operand implies indirection to memory through one of the myriad
 160    :  // modes supported by IA32.
 161    :  class OperandImpl {
 162    :   public:
 163    :    // A register-indirect mode.
 164    :    explicit OperandImpl(Register base);
 165    :  
 166    :    // A register-indirect with displacement mode.
 167    :    OperandImpl(Register base, const DisplacementImpl& displ);
 168    :  
 169    :    // A displacement-only mode.
 170    :    explicit OperandImpl(const DisplacementImpl& displ);
 171    :  
 172    :    // The full [base + index * scale + displ32] mode.
 173    :    // @note esp cannot be used as an index register.
 174    :    OperandImpl(Register base,
 175    :                Register index,
 176    :                ScaleFactor scale,
 177    :                const DisplacementImpl& displ);
 178    :  
 179    :    // The [base + index * scale] mode.
 180    :    // @note esp cannot be used as an index register.
 181    :    OperandImpl(Register base,
 182    :                Register index,
 183    :                ScaleFactor scale);
 184    :  
 185    :    // The [index * scale + displ32] mode - e.g. no base.
 186    :    // @note esp cannot be used as an index register.
 187    :    OperandImpl(Register index,
 188    :                ScaleFactor scale,
 189    :                const DisplacementImpl& displ);
 190    :  
 191    :    // Low-level constructor, none of the parameters are checked.
 192    :    OperandImpl(RegisterCode base,
 193    :                RegisterCode index,
 194    :                ScaleFactor scale,
 195    :                const DisplacementImpl& displacement);
 196    :  
 197    :    // @name Accessors.
 198    :    // @{
 199  E :    RegisterCode base() const { return base_; }
 200  E :    RegisterCode index() const { return index_; }
 201  E :    ScaleFactor scale() const { return scale_; }
 202  E :    const DisplacementImpl& displacement() const { return displacement_; }
 203    :    // @}
 204    :  
 205    :   private:
 206    :    // The base register involved, or none.
 207    :    RegisterCode base_;
 208    :    // The index register involved, or none.
 209    :    RegisterCode index_;
 210    :    // The scaling factor, must be kTimes1 if no index register.
 211    :    ScaleFactor scale_;
 212    :    // The displacement, if any.
 213    :    DisplacementImpl displacement_;
 214    :  };
 215    :  
 216    :  // The assembler takes care of maintaining an output location (address), and
 217    :  // generating a stream of bytes and references as instructions are assembled.
 218    :  class AssemblerImpl {
 219    :   public:
 220    :    // The assembler pushes instructions and references to
 221    :    // one of these for serialization.
 222    :    class InstructionSerializer {
 223    :     public:
 224    :      virtual void AppendInstruction(uint32 location,
 225    :                                     const uint8* bytes,
 226    :                                     size_t num_bytes,
 227    :                                     const size_t *ref_locations,
 228    :                                     const void* const* refs,
 229    :                                     size_t num_refs) = 0;
 230    :    };
 231    :  
 232    :    // Constructs an assembler that assembles to @p delegate
 233    :    // starting at @p location.
 234    :    AssemblerImpl(uint32 location, InstructionSerializer* serializer);
 235    :  
 236    :    // @name Accessors.
 237    :    // @{
 238  E :    uint32 location() const { return location_; }
 239  E :    void set_location(uint32 location) { location_ = location; }
 240    :    // @}
 241    :  
 242    :    // @name Call instructions.
 243    :    // @{
 244    :    void call(const ImmediateImpl& dst);
 245    :    void call(const OperandImpl& dst);
 246    :    // @}
 247    :  
 248    :    // @name Control flow instructions.
 249    :    // @{
 250    :    void j(ConditionCode cc, const ImmediateImpl& dst);
 251    :    void jecxz(const ImmediateImpl& dst);
 252    :    void jmp(const ImmediateImpl& dst);
 253    :    void jmp(const OperandImpl& dst);
 254    :    void l(LoopCode lc, const ImmediateImpl& dst);
 255    :    void ret();
 256    :    void ret(uint16 n);
 257    :    // @}
 258    :  
 259    :    // @name byte mov varieties.
 260    :    // @{
 261    :    void mov_b(const OperandImpl& dst, const ImmediateImpl& src);
 262    :    // @}
 263    :  
 264    :    // @name Double-word mov varieties.
 265    :    // @{
 266    :    void mov(Register dst, Register src);
 267    :    void mov(Register dst, const OperandImpl& src);
 268    :    void mov(const OperandImpl& dst, Register src);
 269    :    void mov(Register dst, const ImmediateImpl& src);
 270    :    void mov(const OperandImpl& dst, const ImmediateImpl& src);
 271    :    // @}
 272    :  
 273    :    // @name load effective address.
 274    :    void lea(Register dst, const OperandImpl& src);
 275    :  
 276    :    // @name stack manipulation.
 277    :    // @{
 278    :    void push(Register src);
 279    :    void push(const ImmediateImpl& src);
 280    :    void push(const OperandImpl& src);
 281    :  
 282    :    void pop(Register dst);
 283    :    void pop(const OperandImpl& src);
 284    :    // @}
 285    :  
 286    :    // @name Aliases
 287    :    // @{
 288  E :    void loop(const ImmediateImpl& dst) { l(kLoopOnCounter, dst); }
 289  E :    void loope(const ImmediateImpl& dst) { l(kLoopOnCounterAndZeroFlag, dst); }
 290  E :    void loopne(const ImmediateImpl& dst) {
 291  E :      l(kLoopOnCounterAndNotZeroFlag, dst);
 292  E :    }
 293    :    // @}
 294    :  
 295    :    // The maximum length a single instruction will assemble to.
 296    :    static const size_t kMaxInstructionLength;
 297    :  
 298    :   private:
 299    :    class InstructionBuffer;
 300    :    // Output the instruction data in @p instr to our delegate.
 301    :    void Output(const InstructionBuffer& instr);
 302    :  
 303    :    // Stores the current location of assembly.
 304    :    uint32 location_;
 305    :  
 306    :    // The delegate we push instructions at.
 307    :    InstructionSerializer* serializer_;
 308    :  };
 309    :  
 310    :  }  // namespace core
 311    :  
 312    :  #endif  // SYZYGY_CORE_ASSEMBLER_H_

Coverage information generated Thu Sep 06 11:30:46 2012.