Coverage for /Syzygy/core/assembler.cc

CoverageLines executed / instrumented / missingexe / inst / missLanguageGroup
100.0%3063060.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    :  #include "syzygy/core/assembler.h"
  16    :  
  17    :  #include <limits>
  18    :  
  19    :  #include "base/logging.h"
  20    :  
  21    :  namespace core {
  22    :  
  23  E :  const Register eax(kRegisterEax);
  24  E :  const Register ecx(kRegisterEcx);
  25  E :  const Register edx(kRegisterEdx);
  26  E :  const Register ebx(kRegisterEbx);
  27  E :  const Register esp(kRegisterEsp);
  28  E :  const Register ebp(kRegisterEbp);
  29  E :  const Register esi(kRegisterEsi);
  30  E :  const Register edi(kRegisterEdi);
  31    :  
  32    :  namespace {
  33    :  
  34    :  enum Mod {
  35    :    Reg1Ind = 0,  // Register indirect mode.
  36    :    Reg1ByteDisp = 1,  // Register + byte displacement.
  37    :    Reg1WordDisp = 2,  // Register + word displacement.
  38    :    Reg1 = 3,  // Register + word displacement.
  39    :  };
  40    :  
  41    :  // Returns true if @p operand is a displacment only - e.g.
  42    :  // specifies neither a base, nor an index register.
  43  E :  bool IsDisplacementOnly(const OperandImpl& operand) {
  44    :    return operand.displacement().size() != kSizeNone &&
  45    :        operand.base() == kRegisterNone &&
  46  E :        operand.index() == kRegisterNone;
  47  E :  }
  48    :  
  49    :  }  // namespace
  50    :  
  51    :  // No instruction on x86 can exceed 15 bytes, per specs.
  52    :  const size_t AssemblerImpl::kMaxInstructionLength = 15;
  53    :  
  54    :  OperandImpl::OperandImpl(Register base)
  55    :      : base_(base.code()),
  56    :        index_(kRegisterNone),
  57  E :        scale_(kTimes1) {
  58  E :  }
  59    :  
  60    :  OperandImpl::OperandImpl(Register base,
  61    :                           const DisplacementImpl& displacement)
  62    :      : base_(base.code()),
  63    :        index_(kRegisterNone),
  64    :        scale_(kTimes1),
  65  E :        displacement_(displacement) {
  66    :    // There must be a base register.
  67  E :    DCHECK_NE(kRegisterNone, base_);
  68  E :  }
  69    :  
  70    :  OperandImpl::OperandImpl(const DisplacementImpl& displacement)
  71    :      : base_(kRegisterNone),
  72    :        index_(kRegisterNone),
  73    :        scale_(kTimes1),
  74  E :        displacement_(displacement) {
  75  E :    DCHECK_NE(kSizeNone, displacement.size());
  76  E :  }
  77    :  
  78    :  OperandImpl::OperandImpl(Register base,
  79    :                           Register index,
  80    :                           ScaleFactor scale,
  81    :                           const DisplacementImpl& displacement)
  82    :      : base_(base.code()),
  83    :        index_(index.code()),
  84    :        scale_(scale),
  85  E :        displacement_(displacement) {
  86    :    // ESP cannot be used as an index register.
  87  E :    DCHECK_NE(kRegisterEsp, index.code());
  88  E :    DCHECK_NE(kSizeNone, displacement.size());
  89  E :  }
  90    :  
  91    :  OperandImpl::OperandImpl(Register base,
  92    :                           Register index,
  93    :                           ScaleFactor scale)
  94    :      : base_(base.code()),
  95    :        index_(index.code()),
  96  E :        scale_(scale) {
  97    :    // ESP cannot be used as an index register.
  98  E :    DCHECK_NE(kRegisterEsp, index.code());
  99  E :    DCHECK_EQ(kSizeNone, displacement_.size());
 100  E :  }
 101    :  
 102    :  OperandImpl::OperandImpl(Register index,
 103    :                           ScaleFactor scale,
 104    :                           const DisplacementImpl& displacement)
 105    :      : base_(kRegisterNone),
 106    :        index_(index.code()),
 107    :        scale_(scale),
 108  E :        displacement_(displacement) {
 109    :    // ESP cannot be used as an index register.
 110  E :    DCHECK_NE(kRegisterEsp, index.code());
 111  E :    DCHECK_NE(kSizeNone, displacement.size());
 112  E :  }
 113    :  
 114    :  OperandImpl::OperandImpl(RegisterCode base,
 115    :                           RegisterCode index,
 116    :                           ScaleFactor scale,
 117    :                           const DisplacementImpl& displacement)
 118    :      : base_(base),
 119    :        index_(index),
 120    :        scale_(scale),
 121  E :        displacement_(displacement) {
 122  E :  }
 123    :  
 124    :  ValueImpl::ValueImpl()
 125  E :      : value_(0), reference_(NULL), size_(kSizeNone) {
 126  E :  }
 127    :  
 128    :  ValueImpl::ValueImpl(uint32 value, ValueSize size)
 129  E :      : value_(value), reference_(NULL), size_(size) {
 130  E :  }
 131    :  
 132    :  ValueImpl::ValueImpl(uint32 value,
 133    :                       ValueSize size,
 134    :                       const void* value_ref)
 135  E :      : value_(value), reference_(value_ref), size_(size) {
 136  E :  }
 137    :  
 138    :  // This class is used to buffer a single instruction during it's creation.
 139    :  // TODO(siggi): Add a small state machine in debug mode to ensure the
 140    :  //     correct order of invocation to opcode/modrm etc.
 141    :  class AssemblerImpl::InstructionBuffer {
 142    :   public:
 143    :    explicit InstructionBuffer(AssemblerImpl* assm);
 144    :    ~InstructionBuffer();
 145    :  
 146    :    // @name Accessors.
 147    :    // @{
 148  E :    size_t len() const { return len_; }
 149  E :    const uint8* buf() const { return buf_; }
 150  E :    size_t num_references() const { return num_references_; }
 151  E :    const size_t *reference_offsets() const { return reference_offsets_; }
 152  E :    const void*const* references() const { return references_; }
 153    :    // @}
 154    :  
 155    :    // Emit an opcode byte.
 156    :    void EmitOpCodeByte(uint8 opcode);
 157    :    // Emit a ModR/M byte, reg_op is either a register or an opcode
 158    :    // extension, as fits the instruction being generated.
 159    :    void EmitModRMByte(Mod mod, uint8 reg_op, RegisterCode reg1);
 160    :    // Emit a SIB byte.
 161    :    void EmitScaleIndexBaseByte(ScaleFactor scale,
 162    :                                RegisterCode index,
 163    :                                RegisterCode base);
 164    :    // Emit an operand.
 165    :    void EmitOperand(uint8 reg_op, const OperandImpl& op);
 166    :  
 167    :    // Emit an 8-bit displacement, with optional reference info.
 168    :    void Emit8BitDisplacement(const DisplacementImpl& disp);
 169    :  
 170    :    // Emit a 32-bit displacement with optional reference info.
 171    :    void Emit32BitDisplacement(const DisplacementImpl& disp);
 172    :  
 173    :    // Emit an 8-bit PC-relative value.
 174    :    void Emit8BitPCRelative(uint32 location, const ValueImpl& disp);
 175    :  
 176    :    // Emit a 32-bit PC-relative value.
 177    :    void Emit32BitPCRelative(uint32 location, const ValueImpl& disp);
 178    :  
 179    :    // Emit a 16-bit immediate value.
 180    :    void Emit16BitValue(uint16 value);
 181    :  
 182    :    // Add reference at current location.
 183    :    void AddReference(const void* reference);
 184    :  
 185    :   protected:
 186    :    void EmitByte(uint8 byte);
 187    :  
 188    :    AssemblerImpl* asm_;
 189    :    size_t num_references_;
 190    :    const void* (references_)[2];
 191    :    size_t reference_offsets_[2];
 192    :    size_t len_;
 193    :    uint8 buf_[kMaxInstructionLength];
 194    :  };
 195    :  
 196    :  AssemblerImpl::InstructionBuffer::InstructionBuffer(AssemblerImpl* assm)
 197  E :      : asm_(assm), len_(0), num_references_(0) {
 198  E :    DCHECK(assm != NULL);
 199    :  #ifndef NDEBUG
 200    :    // Initialize the buffer in debug mode for easier debugging.
 201  E :    ::memset(buf_, 0xCC, sizeof(buf_));
 202    :  #endif
 203  E :  }
 204    :  
 205  E :  AssemblerImpl::InstructionBuffer::~InstructionBuffer() {
 206  E :    asm_->Output(*this);
 207  E :  }
 208    :  
 209  E :  void AssemblerImpl::InstructionBuffer::EmitOpCodeByte(uint8 opcode) {
 210  E :    EmitByte(opcode);
 211  E :  }
 212    :  
 213    :  void AssemblerImpl::InstructionBuffer::EmitModRMByte(
 214  E :      Mod mod, uint8 reg_op, RegisterCode reg1) {
 215  E :    DCHECK_LE(reg_op, 8);
 216  E :    DCHECK_NE(kRegisterNone, reg1);
 217    :  
 218  E :    EmitByte((mod << 6) | (reg_op << 3) | reg1);
 219  E :  }
 220    :  
 221    :  void AssemblerImpl::InstructionBuffer::EmitScaleIndexBaseByte(
 222  E :      ScaleFactor scale, RegisterCode index, RegisterCode base) {
 223  E :    DCHECK_NE(kRegisterNone, index);
 224  E :    DCHECK_NE(kRegisterNone, base);
 225    :  
 226  E :    EmitByte((scale << 6) | (index << 3) | base);
 227  E :  }
 228    :  
 229    :  void AssemblerImpl::InstructionBuffer::EmitOperand(
 230  E :      uint8 reg_op, const OperandImpl& op) {
 231  E :    DCHECK_GE(8, reg_op);
 232    :  
 233    :    // The op operand can encode any one of the following things:
 234    :    // An indirect register access [EAX].
 235    :    // An indirect 32-bit displacement only [0xDEADBEEF].
 236    :    // An indirect base register + 32/8-bit displacement [EAX+0xDEADBEEF].
 237    :    // An indirect base + index register*scale [EAX+ECX*4].
 238    :    // An indirect base + index register*scale + 32/8-bit displacement
 239    :    //   [EAX+ECX*4+0xDEADBEEF].
 240    :    // To complicate things, there are certain combinations that can't be encoded
 241    :    // canonically. The mode [ESP] or [ESP+disp] can never be encoded in a
 242    :    // ModR/M byte alone, as ESP in the ModR/M byte for any of the indirect modes
 243    :    // is overloaded to select the SIB representation.
 244    :    // Likewise [EBP] is overloaded to encode the [disp32] case.
 245    :    // See e.g. http://ref.x86asm.net/geek32-abc.html#modrm_byte_32 for a nice
 246    :    // overview table of the ModR/M byte encoding.
 247    :  
 248    :    // ESP can never be used as an index register on X86.
 249  E :    DCHECK_NE(kRegisterEsp, op.index());
 250    :  
 251    :    // Is there an index register?
 252  E :    if (op.index() == kRegisterNone) {
 253  E :      DCHECK_EQ(kTimes1, op.scale());
 254    :  
 255    :      // No index register, is there a base register?
 256  E :      if (op.base() == kRegisterNone) {
 257    :        // No base register, this is a displacement only.
 258  E :        DCHECK_NE(kSizeNone, op.displacement().size());
 259  E :        DCHECK_EQ(kTimes1, op.scale());
 260    :  
 261    :        // The [disp32] mode is encoded by overloading [EBP].
 262  E :        EmitModRMByte(Reg1Ind, reg_op, kRegisterEbp);
 263  E :        Emit32BitDisplacement(op.displacement());
 264  E :      } else {
 265    :        // Base register only, is it ESP?
 266  E :        if (op.base() == kRegisterEsp) {
 267    :          // The [ESP] and [ESP+disp] cases cannot be encoded without a SIB byte.
 268  E :          if (op.displacement().size() == kSizeNone) {
 269  E :            EmitModRMByte(Reg1Ind, reg_op, kRegisterEsp);
 270  E :            EmitScaleIndexBaseByte(kTimes1, kRegisterEsp, kRegisterEsp);
 271  E :          } else if (op.displacement().size() == kSize8Bit) {
 272  E :            EmitModRMByte(Reg1ByteDisp, reg_op, kRegisterEsp);
 273  E :            EmitScaleIndexBaseByte(kTimes1, kRegisterEsp, kRegisterEsp);
 274  E :            Emit8BitDisplacement(op.displacement());
 275  E :          } else {
 276  E :            DCHECK_EQ(kSize32Bit, op.displacement().size());
 277  E :            EmitModRMByte(Reg1WordDisp, reg_op, kRegisterEsp);
 278  E :            EmitScaleIndexBaseByte(kTimes1, kRegisterEsp, kRegisterEsp);
 279  E :            Emit32BitDisplacement(op.displacement());
 280  E :          }
 281  E :        } else if (op.displacement().size() == kSizeNone) {
 282  E :          if (op.base() == kRegisterEbp) {
 283    :            // The [EBP] case cannot be encoded canonically, there always must
 284    :            // be a (zero) displacement.
 285  E :            EmitModRMByte(Reg1ByteDisp, reg_op, op.base());
 286  E :            Emit8BitDisplacement(DisplacementImpl(0, kSize8Bit, NULL));
 287  E :          } else {
 288  E :            EmitModRMByte(Reg1Ind, reg_op, op.base());
 289  E :          }
 290  E :        } else if (op.displacement().size() == kSize8Bit) {
 291    :          // It's [base+disp8], or possibly [EBP].
 292  E :          EmitModRMByte(Reg1ByteDisp, reg_op, op.base());
 293  E :          Emit8BitDisplacement(op.displacement());
 294  E :        } else {
 295  E :          DCHECK_EQ(kSize32Bit, op.displacement().size());
 296    :          // It's [base+disp32].
 297  E :          EmitModRMByte(Reg1WordDisp, reg_op, op.base());
 298  E :          Emit32BitDisplacement(op.displacement());
 299    :        }
 300  E :      }
 301  E :    } else if (op.base() == kRegisterNone) {
 302    :      // Index, no base.
 303  E :      DCHECK_NE(kRegisterNone, op.index());
 304  E :      DCHECK_EQ(kRegisterNone, op.base());
 305    :  
 306    :      // This mode always has a 32 bit displacement.
 307  E :      EmitModRMByte(Reg1Ind, reg_op, kRegisterEsp);
 308  E :      EmitScaleIndexBaseByte(op.scale(), op.index(), kRegisterEbp);
 309  E :      Emit32BitDisplacement(op.displacement());
 310  E :    } else {
 311    :      // Index and base case.
 312  E :      DCHECK_NE(kRegisterNone, op.index());
 313  E :      DCHECK_NE(kRegisterNone, op.base());
 314    :  
 315    :      // Is there a displacement?
 316  E :      if (op.displacement().size() == kSizeNone) {
 317  E :        EmitModRMByte(Reg1Ind, reg_op, kRegisterEsp);
 318  E :        EmitScaleIndexBaseByte(op.scale(), op.index(), op.base());
 319  E :      } else if (op.displacement().size() == kSize8Bit) {
 320  E :        EmitModRMByte(Reg1ByteDisp, reg_op, kRegisterEsp);
 321  E :        EmitScaleIndexBaseByte(op.scale(), op.index(), op.base());
 322  E :        Emit8BitDisplacement(op.displacement());
 323  E :      } else {
 324  E :        DCHECK_EQ(kSize32Bit, op.displacement().size());
 325  E :        EmitModRMByte(Reg1WordDisp, reg_op, kRegisterEsp);
 326  E :        EmitScaleIndexBaseByte(op.scale(), op.index(), op.base());
 327  E :        Emit32BitDisplacement(op.displacement());
 328    :      }
 329    :    }
 330  E :  }
 331    :  
 332    :  void AssemblerImpl::InstructionBuffer::Emit8BitDisplacement(
 333  E :      const DisplacementImpl& disp) {
 334  E :    DCHECK(disp.size() == kSize8Bit);
 335    :  
 336  E :    AddReference(disp.reference());
 337    :  
 338  E :    EmitByte(disp.value());
 339  E :  }
 340    :  
 341    :  void AssemblerImpl::InstructionBuffer::Emit32BitDisplacement(
 342  E :      const DisplacementImpl& disp) {
 343  E :    AddReference(disp.reference());
 344    :  
 345  E :    uint32 value = disp.value();
 346  E :    EmitByte(value);
 347  E :    EmitByte(value >> 8);
 348  E :    EmitByte(value >> 16);
 349  E :    EmitByte(value >> 24);
 350  E :  }
 351    :  
 352    :  void AssemblerImpl::InstructionBuffer::Emit8BitPCRelative(
 353  E :      uint32 location, const ValueImpl& value) {
 354  E :    DCHECK_EQ(kSize8Bit, value.size());
 355    :  
 356  E :    AddReference(value.reference());
 357    :  
 358    :    // Turn the absolute value into a value relative to the address of
 359    :    // the end of the emitted constant.
 360  E :    int32 relative_value = value.value() - (location + len_ + 1);
 361  E :    DCHECK_LE(std::numeric_limits<int8>::min(), relative_value);
 362  E :    DCHECK_GE(std::numeric_limits<int8>::max(), relative_value);
 363  E :    EmitByte(relative_value);
 364  E :  }
 365    :  
 366    :  void AssemblerImpl::InstructionBuffer::Emit32BitPCRelative(
 367  E :      uint32 location, const ValueImpl& value) {
 368  E :    DCHECK_EQ(kSize32Bit, value.size());
 369    :  
 370  E :    AddReference(value.reference());
 371    :  
 372    :    // Turn the absolute value into a value relative to the address of
 373    :    // the end of the emitted constant.
 374  E :    uint32 relative_value = value.value() - (location + len_ + 4);
 375  E :    EmitByte(relative_value);
 376  E :    EmitByte(relative_value >> 8);
 377  E :    EmitByte(relative_value >> 16);
 378  E :    EmitByte(relative_value >> 24);
 379  E :  }
 380    :  
 381  E :  void AssemblerImpl::InstructionBuffer::Emit16BitValue(uint16 value) {
 382  E :    EmitByte(value);
 383  E :    EmitByte(value >> 8);
 384  E :  }
 385    :  
 386  E :  void AssemblerImpl::InstructionBuffer::AddReference(const void* reference) {
 387  E :    if (reference == NULL)
 388  E :      return;
 389    :  
 390  E :    DCHECK_GT(arraysize(references_), num_references_);
 391  E :    reference_offsets_[num_references_] = len();
 392  E :    references_[num_references_] = reference;
 393  E :    ++num_references_;
 394  E :  }
 395    :  
 396  E :  void AssemblerImpl::InstructionBuffer::EmitByte(uint8 byte) {
 397  E :    DCHECK_GT(sizeof(buf_), len_);
 398  E :    buf_[len_++] = byte;
 399  E :  }
 400    :  
 401    :  AssemblerImpl::AssemblerImpl(uint32 location, InstructionSerializer* serializer)
 402  E :      : location_(location), serializer_(serializer) {
 403  E :    DCHECK(serializer != NULL);
 404  E :  }
 405    :  
 406  E :  void AssemblerImpl::call(const ImmediateImpl& dst) {
 407  E :    InstructionBuffer instr(this);
 408    :  
 409  E :    instr.EmitOpCodeByte(0xE8);
 410  E :    instr.Emit32BitPCRelative(location_, dst);
 411  E :  }
 412    :  
 413  E :  void AssemblerImpl::call(const OperandImpl& dst) {
 414  E :    InstructionBuffer instr(this);
 415    :  
 416  E :    instr.EmitOpCodeByte(0xFF);
 417  E :    instr.EmitOperand(0x2, dst);
 418  E :  }
 419    :  
 420  E :  void AssemblerImpl::j(ConditionCode cc, const ImmediateImpl& dst) {
 421  E :    DCHECK_LE(0, cc);
 422  E :    DCHECK_GE(15, cc);
 423    :  
 424  E :    InstructionBuffer instr(this);
 425  E :    if (dst.size() == kSize32Bit) {
 426  E :      instr.EmitOpCodeByte(0x0F);
 427  E :      instr.EmitOpCodeByte(0x80 | cc);
 428  E :      instr.Emit32BitPCRelative(location_, dst);
 429  E :    } else {
 430  E :      DCHECK_EQ(kSize8Bit, dst.size());
 431  E :      instr.EmitOpCodeByte(0x70 | cc);
 432  E :      instr.Emit8BitPCRelative(location_, dst);
 433    :    }
 434  E :  }
 435    :  
 436  E :  void AssemblerImpl::jecxz(const ImmediateImpl& dst) {
 437  E :    DCHECK_EQ(kSize8Bit, dst.size());
 438  E :    InstructionBuffer instr(this);
 439  E :    instr.EmitOpCodeByte(0xE3);
 440  E :    instr.Emit8BitPCRelative(location_, dst);
 441  E :  }
 442    :  
 443  E :  void AssemblerImpl::jmp(const ImmediateImpl& dst) {
 444  E :    DCHECK_EQ(kSize32Bit, dst.size());
 445  E :    InstructionBuffer instr(this);
 446    :  
 447  E :    instr.EmitOpCodeByte(0xE9);
 448  E :    instr.Emit32BitPCRelative(location_, dst);
 449  E :  }
 450    :  
 451  E :  void AssemblerImpl::jmp(const OperandImpl& dst) {
 452  E :    InstructionBuffer instr(this);
 453    :  
 454  E :    instr.EmitOpCodeByte(0xFF);
 455  E :    instr.EmitOperand(0x4, dst);
 456  E :  }
 457    :  
 458  E :  void AssemblerImpl::l(LoopCode lc, const ImmediateImpl& dst) {
 459  E :    DCHECK_EQ(kSize8Bit, dst.size());
 460  E :    DCHECK_LE(0, lc);
 461  E :    DCHECK_GE(2, lc);
 462  E :    InstructionBuffer instr(this);
 463    :  
 464  E :    instr.EmitOpCodeByte(0xE0 | lc);
 465  E :    instr.Emit8BitPCRelative(location_, dst);
 466  E :  }
 467    :  
 468  E :  void AssemblerImpl::ret() {
 469  E :    InstructionBuffer instr(this);
 470    :  
 471  E :    instr.EmitOpCodeByte(0xC3);
 472  E :  }
 473    :  
 474  E :  void AssemblerImpl::ret(uint16 n) {
 475  E :    InstructionBuffer instr(this);
 476    :  
 477  E :    instr.EmitOpCodeByte(0xC2);
 478  E :    instr.Emit16BitValue(n);
 479  E :  }
 480    :  
 481  E :  void AssemblerImpl::mov_b(const OperandImpl& dst, const ImmediateImpl& src) {
 482  E :    InstructionBuffer instr(this);
 483    :  
 484  E :    instr.EmitOpCodeByte(0xC6);
 485  E :    instr.EmitOperand(0, dst);
 486  E :    instr.Emit8BitDisplacement(src);
 487  E :  }
 488    :  
 489  E :  void AssemblerImpl::mov(Register dst, Register src) {
 490  E :    InstructionBuffer instr(this);
 491    :  
 492  E :    instr.EmitOpCodeByte(0x8B);
 493  E :    instr.EmitModRMByte(Reg1, dst.code(), src.code());
 494  E :  }
 495    :  
 496  E :  void AssemblerImpl::mov(Register dst, const OperandImpl& src) {
 497  E :    InstructionBuffer instr(this);
 498    :  
 499  E :    if (dst.code() == kRegisterEax && IsDisplacementOnly(src)) {
 500    :      // Special encoding for indirect displacement only to EAX.
 501  E :      instr.EmitOpCodeByte(0xA1);
 502  E :      instr.Emit32BitDisplacement(src.displacement());
 503  E :    } else {
 504  E :      instr.EmitOpCodeByte(0x8B);
 505  E :      instr.EmitOperand(dst.code(), src);
 506    :    }
 507  E :  }
 508    :  
 509  E :  void AssemblerImpl::mov(const OperandImpl& dst, Register src) {
 510  E :    InstructionBuffer instr(this);
 511    :  
 512  E :    if (src.code() == kRegisterEax && IsDisplacementOnly(dst)) {
 513    :      // Special encoding for indirect displacement only from EAX.
 514  E :      instr.EmitOpCodeByte(0xA3);
 515  E :      instr.Emit32BitDisplacement(dst.displacement());
 516  E :    } else {
 517  E :      instr.EmitOpCodeByte(0x89);
 518  E :      instr.EmitOperand(src.code(), dst);
 519    :    }
 520  E :  }
 521    :  
 522  E :  void AssemblerImpl::mov(Register dst, const ValueImpl& src) {
 523  E :    DCHECK_NE(kSizeNone, src.size());
 524  E :    InstructionBuffer instr(this);
 525    :  
 526  E :    instr.EmitOpCodeByte(0xB8 | dst.code());
 527  E :    instr.Emit32BitDisplacement(src);
 528  E :  }
 529    :  
 530  E :  void AssemblerImpl::mov(const OperandImpl& dst, const ImmediateImpl& src) {
 531  E :    InstructionBuffer instr(this);
 532    :  
 533  E :    instr.EmitOpCodeByte(0xC7);
 534  E :    instr.EmitOperand(0, dst);
 535  E :    instr.Emit32BitDisplacement(src);
 536  E :  }
 537    :  
 538  E :  void AssemblerImpl::lea(Register dst, const OperandImpl& src) {
 539  E :    InstructionBuffer instr(this);
 540    :  
 541  E :    instr.EmitOpCodeByte(0x8D);
 542  E :    instr.EmitOperand(dst.code(), src);
 543  E :  }
 544    :  
 545  E :  void AssemblerImpl::push(Register src) {
 546  E :    InstructionBuffer instr(this);
 547    :  
 548  E :    instr.EmitOpCodeByte(0x50 | src.code());
 549  E :  }
 550    :  
 551  E :  void AssemblerImpl::push(const ImmediateImpl& src) {
 552  E :    DCHECK_EQ(kSize32Bit, src.size());
 553  E :    InstructionBuffer instr(this);
 554    :  
 555  E :    instr.EmitOpCodeByte(0x68);
 556  E :    instr.Emit32BitDisplacement(src);
 557  E :  }
 558    :  
 559  E :  void AssemblerImpl::push(const OperandImpl& dst) {
 560  E :    InstructionBuffer instr(this);
 561    :  
 562  E :    instr.EmitOpCodeByte(0xFF);
 563  E :    instr.EmitOperand(0x6, dst);
 564  E :  }
 565    :  
 566  E :  void AssemblerImpl::pop(Register src) {
 567  E :    InstructionBuffer instr(this);
 568    :  
 569  E :    instr.EmitOpCodeByte(0x58 | src.code());
 570  E :  }
 571    :  
 572  E :  void AssemblerImpl::pop(const OperandImpl& dst) {
 573  E :    InstructionBuffer instr(this);
 574    :  
 575  E :    instr.EmitOpCodeByte(0x8F);
 576  E :    instr.EmitOperand(0, dst);
 577  E :  }
 578    :  
 579    :  
 580  E :  void AssemblerImpl::Output(const InstructionBuffer& instr) {
 581    :    serializer_->AppendInstruction(location_,
 582    :                                   instr.buf(),
 583    :                                   instr.len(),
 584    :                                   instr.reference_offsets(),
 585    :                                   instr.references(),
 586  E :                                   instr.num_references());
 587    :  
 588  E :    location_ += instr.len();
 589  E :  }
 590    :  }  // namespace core

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