Coverage for /Syzygy/core/assembler.cc

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

Line-by-line coverage:

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

Coverage information generated Thu Mar 14 11:53:36 2013.