Coverage for /Syzygy/assm/assembler_base_impl.h

CoverageLines executed / instrumented / missingexe / inst / missLanguageGroup
99.1%7497560.C++source

Line-by-line coverage:

   1    :  // Copyright 2014 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    :  #ifndef SYZYGY_ASSM_ASSEMBLER_BASE_IMPL_H_
  16    :  #define SYZYGY_ASSM_ASSEMBLER_BASE_IMPL_H_
  17    :  
  18    :  #ifndef SYZYGY_ASSM_ASSEMBLER_BASE_H_
  19    :  #error Do not include this file directly.
  20    :  #endif  // SYZYGY_ASSM_ASSEMBLER_BASE_H_
  21    :  
  22    :  #include <stdint.h>
  23    :  #include <limits>
  24    :  
  25    :  #include "syzygy/assm/const.h"
  26    :  
  27    :  namespace assm {
  28    :  
  29    :  // This class is used to buffer a single instruction during its creation.
  30    :  // TODO(siggi): Add a small state machine in debug mode to ensure the
  31    :  //     correct order of invocation to opcode/modrm etc.
  32    :  // @note @p ReferenceType must either be a pointer type, or else have
  33    :  //     a method bool IsValid() const.
  34    :  template <class ReferenceType>
  35    :  class AssemblerBase<ReferenceType>::InstructionBuffer {
  36    :   public:
  37    :    explicit InstructionBuffer(AssemblerBase* assm);
  38    :    ~InstructionBuffer();
  39    :  
  40    :    // @name Accessors.
  41    :    // @{
  42  E :    size_t len() const { return len_; }
  43  E :    const uint8_t* buf() const { return buf_; }
  44  E :    size_t num_reference_infos() const { return num_reference_infos_; }
  45  E :    const ReferenceInfo* reference_infos() const { return reference_infos_; }
  46    :    // @}
  47    :  
  48    :    // Emits operand size prefix (0x66) bytes.
  49    :    // @param count The number of operand size prefix bytes to emit.
  50    :    void EmitOperandSizePrefix(size_t count);
  51    :    // Emit an opcode byte.
  52    :    void EmitOpCodeByte(uint8_t opcode);
  53    :    // Emit a ModR/M byte with an opcode extension.
  54    :    void EmitModRMByte(Mod mod, uint8_t op, RegisterId reg1);
  55    :    // Emit a ModR/M byte with a destination register.
  56    :    void EmitModRMByte(Mod mod, RegisterId reg2, RegisterId reg1);
  57    :    // Emit a SIB byte.
  58    :    void EmitScaleIndexBaseByte(ScaleFactor scale,
  59    :                                RegisterId index,
  60    :                                RegisterId base);
  61    :    // Emit an operand.
  62    :    void EmitOperand(uint8_t reg_op, const Operand& op);
  63    :  
  64    :    // Emit an 8-bit displacement, with optional reference info.
  65    :    void Emit8BitDisplacement(const Displacement& disp);
  66    :    // Emit an 8-bit immediate, with optional reference info.
  67    :    void Emit8BitImmediate(const Immediate& disp);
  68    :  
  69    :    // Emit a 32-bit displacement with optional reference info.
  70    :    void Emit32BitDisplacement(const Displacement& disp);
  71    :  
  72    :    // Emit a 32-bit immediate with optional reference info.
  73    :    void Emit32BitImmediate(const Immediate& disp);
  74    :  
  75    :    // Emit an 8-bit PC-relative value.
  76    :    void Emit8BitPCRelative(uint32_t location, const Immediate& imm);
  77    :  
  78    :    // Emit a 32-bit PC-relative value.
  79    :    void Emit32BitPCRelative(uint32_t location, const Immediate& imm);
  80    :  
  81    :    // Emit a 16-bit immediate value.
  82    :    void Emit16BitValue(uint16_t value);
  83    :  
  84    :    // Emit an arithmetic instruction with various encoding.
  85    :    void EmitArithmeticInstruction(uint8_t op,
  86    :                                   const Register& dst,
  87    :                                   const Register& src);
  88    :    void EmitArithmeticInstruction(uint8_t op,
  89    :                                   const Register& dst,
  90    :                                   const Operand& src);
  91    :    void EmitArithmeticInstruction(uint8_t op,
  92    :                                   const Operand& dst,
  93    :                                   const Register32& src);
  94    :    void EmitArithmeticInstructionToRegister32(uint8_t op_eax,
  95    :                                               uint8_t op_8,
  96    :                                               uint8_t op_32,
  97    :                                               uint8_t sub_op,
  98    :                                               const Register32& dst,
  99    :                                               const Immediate& src);
 100    :    void EmitArithmeticInstructionToRegister8(uint8_t op_eax,
 101    :                                              uint8_t op_8,
 102    :                                              uint8_t sub_op,
 103    :                                              const Register8& dst,
 104    :                                              const Immediate& src);
 105    :    void EmitArithmeticInstructionToOperand(uint8_t op_8,
 106    :                                            uint8_t op_32,
 107    :                                            uint8_t sub_op,
 108    :                                            const Operand& dst,
 109    :                                            const Immediate& src);
 110    :  
 111    :    // Emit an arithmetic instruction with 3 operands.
 112    :    void EmitThreeOperandArithmeticInstructionToRegister32(
 113    :        uint8_t op,
 114    :        const Register32& dst,
 115    :        const Register32& src,
 116    :        const Immediate& index);
 117    :  
 118    :    // Emit an XCHG instruction.
 119    :    void EmitXchg(ValueSize size, RegisterId dst, RegisterId src);
 120    :  
 121    :    // Add reference at current location.
 122    :    void AddReference(const ReferenceType& reference,
 123    :                      RegisterSize size,
 124    :                      bool pc_relative);
 125    :  
 126    :   protected:
 127    :    void EmitByte(uint8_t byte);
 128    :  
 129    :    AssemblerBase* asm_;
 130    :    size_t num_reference_infos_;
 131    :    ReferenceInfo reference_infos_[2];
 132    :    size_t len_;
 133    :    uint8_t buf_[kMaxInstructionLength];
 134    :  };
 135    :  
 136    :  namespace details {
 137    :  
 138    :  template <class ReferenceType>
 139  E :  bool IsValidReference(const ReferenceType* ref) {
 140  E :    return ref != NULL;
 141  E :  }
 142    :  
 143    :  template <class ReferenceType>
 144  E :  bool IsValidReference(const ReferenceType& ref) {
 145  E :    return ref.IsValid();
 146  E :  }
 147    :  
 148    :  }  // namespace details
 149    :  
 150    :  // Returns true if @p operand is a displacement only - e.g.
 151    :  // specifies neither a base, nor an index register.
 152    :  template <class ReferenceType>
 153  E :  bool IsDisplacementOnly(const OperandBase<ReferenceType>& operand) {
 154  E :    return operand.displacement().size() != kSizeNone &&
 155    :        operand.base() == kRegisterNone &&
 156    :        operand.index() == kRegisterNone;
 157  E :  }
 158    :  
 159    :  template <class ReferenceType>
 160    :  AssemblerBase<ReferenceType>::InstructionBuffer::InstructionBuffer(
 161  E :      AssemblerBase* assm) : asm_(assm), len_(0), num_reference_infos_(0) {
 162  E :    DCHECK(assm != NULL);
 163    :  #ifndef NDEBUG
 164    :    // Initialize the buffer in debug mode for easier debugging.
 165  E :    ::memset(buf_, 0xCC, sizeof(buf_));
 166    :  #endif
 167  E :  }
 168    :  
 169    :  template <class ReferenceType>
 170  E :  AssemblerBase<ReferenceType>::InstructionBuffer::~InstructionBuffer() {
 171  E :    asm_->Output(*this);
 172  E :  }
 173    :  
 174    :  template <class ReferenceType>
 175    :  void AssemblerBase<ReferenceType>::InstructionBuffer::EmitOperandSizePrefix(
 176  E :      size_t count) {
 177  E :    for (size_t i = 0; i < count; ++i)
 178  E :      EmitByte(kOperandSizePrefix);
 179  E :  }
 180    :  
 181    :  template <class ReferenceType>
 182    :  void AssemblerBase<ReferenceType>::InstructionBuffer::EmitOpCodeByte(
 183  E :      uint8_t opcode) {
 184  E :    EmitByte(opcode);
 185  E :  }
 186    :  
 187    :  template <class ReferenceType>
 188    :  void AssemblerBase<ReferenceType>::InstructionBuffer::EmitModRMByte(
 189    :      Mod mod,
 190    :      uint8_t reg_op,
 191  E :      RegisterId reg1) {
 192  E :    DCHECK_LE(reg_op, 8);
 193  E :    DCHECK_NE(kRegisterNone, reg1);
 194  E :    EmitByte((mod << 6) | (reg_op << 3) | Register::Code(reg1));
 195  E :  }
 196    :  
 197    :  template <class ReferenceType>
 198    :  void AssemblerBase<ReferenceType>::InstructionBuffer::EmitModRMByte(
 199  E :      Mod mod, RegisterId reg2, RegisterId reg1) {
 200  E :    DCHECK_NE(kRegisterNone, reg2);
 201  E :    DCHECK_NE(kRegisterNone, reg1);
 202  E :    EmitModRMByte(mod, Register::Code(reg2), reg1);
 203  E :  }
 204    :  
 205    :  template <class ReferenceType>
 206    :  void AssemblerBase<ReferenceType>::InstructionBuffer::EmitScaleIndexBaseByte(
 207  E :      ScaleFactor scale, RegisterId index, RegisterId base) {
 208  E :    DCHECK_NE(kRegisterNone, index);
 209  E :    DCHECK_NE(kRegisterNone, base);
 210    :  
 211  E :    EmitByte((scale << 6) | (Register::Code(index) << 3) | Register::Code(base));
 212  E :  }
 213    :  
 214    :  template <class ReferenceType>
 215    :  void AssemblerBase<ReferenceType>::InstructionBuffer::EmitOperand(
 216    :      uint8_t reg_op,
 217  E :      const Operand& op) {
 218  E :    DCHECK_GE(8, reg_op);
 219    :  
 220    :    // The op operand can encode any one of the following things:
 221    :    // An indirect register access [EAX].
 222    :    // An indirect 32-bit displacement only [0xDEADBEEF].
 223    :    // An indirect base register + 32/8-bit displacement [EAX+0xDEADBEEF].
 224    :    // An indirect base + index register*scale [EAX+ECX*4].
 225    :    // An indirect base + index register*scale + 32/8-bit displacement
 226    :    //   [EAX+ECX*4+0xDEADBEEF].
 227    :    // To complicate things, there are certain combinations that can't be encoded
 228    :    // canonically. The mode [ESP] or [ESP+disp] can never be encoded in a
 229    :    // ModR/M byte alone, as ESP in the ModR/M byte for any of the indirect modes
 230    :    // is overloaded to select the SIB representation.
 231    :    // Likewise [EBP] is overloaded to encode the [disp32] case.
 232    :    // See e.g. http://ref.x86asm.net/geek32-abc.html#modrm_byte_32 for a nice
 233    :    // overview table of the ModR/M byte encoding.
 234    :  
 235    :    // ESP can never be used as an index register on X86.
 236  E :    DCHECK_NE(kRegisterEsp, op.index());
 237    :  
 238    :    // Is there an index register?
 239  E :    if (op.index() == kRegisterNone) {
 240  E :      DCHECK_EQ(kTimes1, op.scale());
 241    :  
 242    :      // No index register, is there a base register?
 243  E :      if (op.base() == kRegisterNone) {
 244    :        // No base register, this is a displacement only.
 245  E :        DCHECK_NE(kSizeNone, op.displacement().size());
 246  E :        DCHECK_EQ(kTimes1, op.scale());
 247    :  
 248    :        // The [disp32] mode is encoded by overloading [EBP].
 249  E :        EmitModRMByte(kReg1Ind, reg_op, kRegisterEbp);
 250  E :        Emit32BitDisplacement(op.displacement());
 251  E :      } else {
 252    :        // Base register only, is it ESP?
 253  E :        if (op.base() == kRegisterEsp) {
 254    :          // The [ESP] and [ESP+disp] cases cannot be encoded without a SIB byte.
 255  E :          if (op.displacement().size() == kSizeNone) {
 256  E :            EmitModRMByte(kReg1Ind, reg_op, kRegisterEsp);
 257  E :            EmitScaleIndexBaseByte(kTimes1, kRegisterEsp, kRegisterEsp);
 258  E :          } else if (op.displacement().size() == kSize8Bit) {
 259  E :            EmitModRMByte(kReg1ByteDisp, reg_op, kRegisterEsp);
 260  E :            EmitScaleIndexBaseByte(kTimes1, kRegisterEsp, kRegisterEsp);
 261  E :            Emit8BitDisplacement(op.displacement());
 262  E :          } else {
 263  E :            DCHECK_EQ(kSize32Bit, op.displacement().size());
 264  E :            EmitModRMByte(kReg1WordDisp, reg_op, kRegisterEsp);
 265  E :            EmitScaleIndexBaseByte(kTimes1, kRegisterEsp, kRegisterEsp);
 266  E :            Emit32BitDisplacement(op.displacement());
 267  E :          }
 268  E :        } else if (op.displacement().size() == kSizeNone) {
 269  E :          if (op.base() == kRegisterEbp) {
 270    :            // The [EBP] case cannot be encoded canonically, there always must
 271    :            // be a (zero) displacement.
 272  E :            EmitModRMByte(kReg1ByteDisp, reg_op, op.base());
 273  E :            Emit8BitDisplacement(
 274    :                Displacement(0, kSize8Bit, ReferenceType()));
 275  E :          } else {
 276  E :            EmitModRMByte(kReg1Ind, reg_op, op.base());
 277  E :          }
 278  E :        } else if (op.displacement().size() == kSize8Bit) {
 279    :          // It's [base+disp8], or possibly [EBP].
 280  E :          EmitModRMByte(kReg1ByteDisp, reg_op, op.base());
 281  E :          Emit8BitDisplacement(op.displacement());
 282  E :        } else {
 283  E :          DCHECK_EQ(kSize32Bit, op.displacement().size());
 284    :          // It's [base+disp32].
 285  E :          EmitModRMByte(kReg1WordDisp, reg_op, op.base());
 286  E :          Emit32BitDisplacement(op.displacement());
 287    :        }
 288  E :      }
 289  E :    } else if (op.base() == kRegisterNone) {
 290    :      // Index, no base.
 291  E :      DCHECK_NE(kRegisterNone, op.index());
 292  E :      DCHECK_EQ(kRegisterNone, op.base());
 293    :  
 294    :      // This mode always has a 32 bit displacement.
 295  E :      EmitModRMByte(kReg1Ind, reg_op, kRegisterEsp);
 296  E :      EmitScaleIndexBaseByte(op.scale(), op.index(), kRegisterEbp);
 297  E :      Emit32BitDisplacement(op.displacement());
 298  E :    } else {
 299    :      // Index and base case.
 300  E :      DCHECK_NE(kRegisterNone, op.index());
 301  E :      DCHECK_NE(kRegisterNone, op.base());
 302    :  
 303    :      // Is there a displacement?
 304  E :      if (op.displacement().size() == kSizeNone) {
 305  E :        EmitModRMByte(kReg1Ind, reg_op, kRegisterEsp);
 306  E :        EmitScaleIndexBaseByte(op.scale(), op.index(), op.base());
 307  E :      } else if (op.displacement().size() == kSize8Bit) {
 308  E :        EmitModRMByte(kReg1ByteDisp, reg_op, kRegisterEsp);
 309  E :        EmitScaleIndexBaseByte(op.scale(), op.index(), op.base());
 310  E :        Emit8BitDisplacement(op.displacement());
 311  E :      } else {
 312  E :        DCHECK_EQ(kSize32Bit, op.displacement().size());
 313  E :        EmitModRMByte(kReg1WordDisp, reg_op, kRegisterEsp);
 314  E :        EmitScaleIndexBaseByte(op.scale(), op.index(), op.base());
 315  E :        Emit32BitDisplacement(op.displacement());
 316    :      }
 317    :    }
 318  E :  }
 319    :  
 320    :  template <class ReferenceType>
 321    :  void AssemblerBase<ReferenceType>::InstructionBuffer::Emit8BitDisplacement(
 322  E :      const Displacement& disp) {
 323  E :    DCHECK(disp.size() == kSize8Bit);
 324    :  
 325  E :    AddReference(disp.reference(), kSize8Bit, false);
 326    :  
 327  E :    EmitByte(disp.value());
 328  E :  }
 329    :  
 330    :  template <class ReferenceType>
 331    :  void AssemblerBase<ReferenceType>::InstructionBuffer::Emit8BitImmediate(
 332  E :      const Immediate& imm) {
 333  E :    DCHECK(imm.size() == kSize8Bit);
 334    :  
 335  E :    AddReference(imm.reference(), kSize8Bit, false);
 336    :  
 337  E :    EmitByte(imm.value());
 338  E :  }
 339    :  
 340    :  template <class ReferenceType>
 341    :  void AssemblerBase<ReferenceType>::InstructionBuffer::Emit32BitDisplacement(
 342  E :      const Displacement& disp) {
 343  E :    AddReference(disp.reference(), kSize32Bit, false);
 344    :  
 345  E :    uint32_t 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    :  template <class ReferenceType>
 353    :  void AssemblerBase<ReferenceType>::InstructionBuffer::Emit32BitImmediate(
 354  E :      const Immediate& imm) {
 355  E :    AddReference(imm.reference(), kSize32Bit, false);
 356    :  
 357  E :    uint32_t value = imm.value();
 358  E :    EmitByte(value);
 359  E :    EmitByte(value >> 8);
 360  E :    EmitByte(value >> 16);
 361  E :    EmitByte(value >> 24);
 362  E :  }
 363    :  
 364    :  template <class ReferenceType>
 365    :  void AssemblerBase<ReferenceType>::InstructionBuffer::Emit8BitPCRelative(
 366    :      uint32_t location,
 367  E :      const Immediate& imm) {
 368  E :    DCHECK_EQ(kSize8Bit, imm.size());
 369    :  
 370  E :    AddReference(imm.reference(), kSize8Bit, true);
 371    :  
 372    :    // Turn the absolute imm into a imm relative to the address of
 373    :    // the end of the emitted constant.
 374  E :    int32_t relative_value = imm.value() - (location + len_ + 1);
 375  E :    DCHECK_LE(std::numeric_limits<int8_t>::min(), relative_value);
 376  E :    DCHECK_GE(std::numeric_limits<int8_t>::max(), relative_value);
 377  E :    EmitByte(relative_value);
 378  E :  }
 379    :  
 380    :  template <class ReferenceType>
 381    :  void AssemblerBase<ReferenceType>::InstructionBuffer::Emit32BitPCRelative(
 382    :      uint32_t location,
 383  E :      const Immediate& imm) {
 384  E :    DCHECK_EQ(kSize32Bit, imm.size());
 385    :  
 386  E :    AddReference(imm.reference(), kSize32Bit, true);
 387    :  
 388    :    // Turn the absolute imm into a imm relative to the address of
 389    :    // the end of the emitted constant.
 390  E :    uint32_t relative_value = imm.value() - (location + len_ + 4);
 391  E :    EmitByte(relative_value);
 392  E :    EmitByte(relative_value >> 8);
 393  E :    EmitByte(relative_value >> 16);
 394  E :    EmitByte(relative_value >> 24);
 395  E :  }
 396    :  
 397    :  template <class ReferenceType>
 398    :  void AssemblerBase<ReferenceType>::InstructionBuffer::Emit16BitValue(
 399  E :      uint16_t value) {
 400  E :    EmitByte(value);
 401  E :    EmitByte(value >> 8);
 402  E :  }
 403    :  
 404    :  template <class ReferenceType>
 405    :  void AssemblerBase<ReferenceType>::InstructionBuffer::EmitArithmeticInstruction(
 406    :      uint8_t op,
 407    :      const Register& dst,
 408  E :      const Register& src) {
 409  E :    DCHECK_EQ(dst.size(), src.size());
 410  E :    EmitOpCodeByte(op);
 411  E :    EmitModRMByte(kReg1, dst.id(), src.id());
 412  E :  }
 413    :  
 414    :  template <class ReferenceType>
 415    :  void AssemblerBase<ReferenceType>::InstructionBuffer::EmitArithmeticInstruction(
 416    :      uint8_t op,
 417    :      const Register& dst,
 418  E :      const Operand& src) {
 419  E :    EmitOpCodeByte(op);
 420  E :    EmitOperand(dst.code(), src);
 421  E :  }
 422    :  
 423    :  template <class ReferenceType>
 424    :  void AssemblerBase<ReferenceType>::InstructionBuffer::EmitArithmeticInstruction(
 425    :      uint8_t op,
 426    :      const Operand& dst,
 427  E :      const Register32& src) {
 428  E :    EmitOpCodeByte(op);
 429  E :    EmitOperand(src.code(), dst);
 430  E :  }
 431    :  
 432    :  template <class ReferenceType>
 433    :  void AssemblerBase<ReferenceType>::InstructionBuffer::
 434    :      EmitArithmeticInstructionToRegister32(uint8_t op_eax,
 435    :                                            uint8_t op_8,
 436    :                                            uint8_t op_32,
 437    :                                            uint8_t sub_op,
 438    :                                            const Register32& dst,
 439  E :                                            const Immediate& src) {
 440  E :    if (dst.id() == kRegisterEax && src.size() == kSize32Bit) {
 441    :      // Special encoding for EAX.
 442  E :      EmitOpCodeByte(op_eax);
 443  E :      Emit32BitImmediate(src);
 444  E :    } else if (src.size() == kSize8Bit) {
 445  E :      EmitOpCodeByte(op_8);
 446  E :      EmitModRMByte(kReg1, sub_op, dst.id());
 447  E :      Emit8BitImmediate(src);
 448  E :    } else {
 449  E :      EmitOpCodeByte(op_32);
 450  E :      EmitModRMByte(kReg1, sub_op, dst.id());
 451  E :      Emit32BitImmediate(src);
 452    :    }
 453  E :  }
 454    :  
 455    :  template <class ReferenceType>
 456    :  void AssemblerBase<ReferenceType>::InstructionBuffer::
 457    :      EmitArithmeticInstructionToRegister8(uint8_t op_eax,
 458    :                                           uint8_t op_8,
 459    :                                           uint8_t sub_op,
 460    :                                           const Register8& dst,
 461  E :                                           const Immediate& src) {
 462  E :    DCHECK(src.size() == kSize8Bit);
 463  E :    if (dst.code() == kAccumulatorCode) {
 464    :      // Special encoding for AL/AX/EAX.
 465  E :      EmitOpCodeByte(op_eax);
 466  E :    } else {
 467  E :      EmitOpCodeByte(op_8);
 468  E :      EmitModRMByte(kReg1, sub_op, dst.id());
 469    :    }
 470  E :    Emit8BitImmediate(src);
 471  E :  }
 472    :  
 473    :  template <class ReferenceType>
 474    :  void AssemblerBase<ReferenceType>::InstructionBuffer::
 475    :      EmitArithmeticInstructionToOperand(uint8_t op_8,
 476    :                                         uint8_t op_32,
 477    :                                         uint8_t sub_op,
 478    :                                         const Operand& dst,
 479  E :                                         const Immediate& src) {
 480  E :    if (src.size() == kSize8Bit) {
 481  E :      EmitOpCodeByte(op_8);
 482  E :      EmitOperand(sub_op, dst);
 483  E :      Emit8BitImmediate(src);
 484  E :    } else {
 485  E :      EmitOpCodeByte(op_32);
 486  E :      EmitOperand(sub_op, dst);
 487  E :      Emit32BitImmediate(src);
 488    :    }
 489  E :  }
 490    :  
 491    :  template <class ReferenceType>
 492    :  void AssemblerBase<ReferenceType>::InstructionBuffer::
 493    :      EmitThreeOperandArithmeticInstructionToRegister32(uint8_t op,
 494    :                                                        const Register32& dst,
 495    :                                                        const Register32& src,
 496  E :                                                        const Immediate& index) {
 497  E :    EmitArithmeticInstruction(op, dst, src);
 498  E :    Emit32BitImmediate(index);
 499  E :  }
 500    :  
 501    :  template <class ReferenceType>
 502    :  void AssemblerBase<ReferenceType>::InstructionBuffer::EmitXchg(
 503  E :      ValueSize size, RegisterId dst, RegisterId src) {
 504    :    // Encoding for 8-bit registers.
 505  E :    if (size == kSize8Bit) {
 506  E :      EmitOpCodeByte(0x86);
 507  E :      EmitModRMByte(kReg1, src, dst);
 508  E :    } else {
 509    :      // 16-bit encodings are identical to 32-bit encodings, simply with
 510    :      // a operand size override prefix.
 511  E :      if (size == kSize16Bit)
 512  E :        EmitOperandSizePrefix(1);
 513    :  
 514    :      // If either register is EAX/AX there's a 1-byte encoding.
 515  E :      RegisterCode dst_code = Register::Code(dst);
 516  E :      RegisterCode src_code = Register::Code(src);
 517  E :      if (src_code == kAccumulatorCode || dst_code == kAccumulatorCode) {
 518  E :        RegisterCode other_register = dst_code;
 519  E :        if (dst_code == kAccumulatorCode)
 520  E :          other_register = src_code;
 521  E :        EmitOpCodeByte(0x90 | other_register);
 522  E :      } else {
 523    :        // Otherwise we use a 2-byte encoding with a ModR/M byte.
 524  E :        EmitOpCodeByte(0x87);
 525  E :        EmitModRMByte(kReg1, src, dst);
 526    :      }
 527    :    }
 528  E :  }
 529    :  
 530    :  template <class ReferenceType>
 531    :  void AssemblerBase<ReferenceType>::InstructionBuffer::AddReference(
 532  E :      const ReferenceType& reference, RegisterSize size, bool pc_relative) {
 533  E :    if (!details::IsValidReference(reference))
 534  E :      return;
 535    :  
 536  E :    DCHECK_GT(arraysize(reference_infos_), num_reference_infos_);
 537  E :    ReferenceInfo& info = reference_infos_[num_reference_infos_];
 538  E :    info.offset = len();
 539  E :    info.reference = reference;
 540  E :    info.size = size;
 541  E :    info.pc_relative = pc_relative;
 542  E :    ++num_reference_infos_;
 543  E :  }
 544    :  
 545    :  template <class ReferenceType>
 546  E :  void AssemblerBase<ReferenceType>::InstructionBuffer::EmitByte(uint8_t byte) {
 547  E :    DCHECK_GT(sizeof(buf_), len_);
 548  E :    buf_[len_++] = byte;
 549  E :  }
 550    :  
 551    :  template <class ReferenceType>
 552    :  AssemblerBase<ReferenceType>::AssemblerBase(uint32_t location,
 553    :                                              InstructionSerializer* serializer)
 554  E :      : location_(location), serializer_(serializer) {
 555  E :    DCHECK(serializer != NULL);
 556  E :  }
 557    :  
 558    :  template <class ReferenceType>
 559  E :  void AssemblerBase<ReferenceType>::nop(size_t size) {
 560    :    // These are NOP sequences suggested by the Intel Architecture
 561    :    // Software Developer's manual, page 4-8.
 562    :    //
 563    :    //  1: 0x90
 564    :    //  2: 0x66 0x90
 565    :    //  3: 0x66 0x66 0x90
 566    :    //  4: 0x0F 0x1F 0x40 0x00
 567    :    //  5: 0x0F 0x1F 0x44 0x00 0x00
 568    :    //  6: 0x66 0x0F 0x1F 0x44 0x00 0x00
 569    :    //  7: 0x0F 0x1F 0x80 0x00 0x00 0x00 0x00
 570    :    //  8: 0x0F 0x1F 0x84 0x00 0x00 0x00 0x00 0x00
 571    :    //  9: 0x66 0x0F 0x1F 0x84 0x00 0x00 0x00 0x00 0x00
 572    :    // 10: 0x66 0x66 0x0F 0x1F 0x84 0x00 0x00 0x00 0x00 0x00
 573    :    // 11: 0x66 0x66 0x66 0x0F 0x1F 0x84 0x00 0x00 0x00 0x00 0x00
 574    :    //
 575    :    // It is further suggested not to put consecutive XCHG NOPs with prefixes,
 576    :    // but rather to mix them with 0x1F NOPs or XCHG NOPs without prefixes. The
 577    :    // basic nops without any operand prefixes (0x66) have been implemented as
 578    :    // helper functions nop1, nop4, nop5, nop7 and nop8. This implementation of
 579    :    // NOP sequences has been inspired by Oracle's HotSpot JVM JIT assembler
 580    :    // (http://openjdk.java.net/groups/hotspot/).
 581    :  
 582    :    // Eat up the NOPs in chunks of 15 bytes.
 583  E :    while (size >= 15) {
 584  E :      nop8(3);  // 11-byte non-XCHG NOP.
 585  E :      nop1(3);  // 4-byte prefixed XCHG NOP.
 586  E :      size -= 15;
 587  E :    }
 588  E :    DCHECK_GE(14u, size);
 589    :  
 590    :    // Handle the last chunk of bytes.
 591  E :    size_t prefix_count = 0;
 592  E :    switch (size) {
 593    :      // Handle 12- to 14-byte NOPs.
 594    :      case 14:
 595  E :        ++prefix_count;
 596    :      case 13:
 597  E :        ++prefix_count;
 598    :      case 12:
 599  E :        nop8(prefix_count);  // 8- to 10-byte non-XCHG NOP.
 600  E :        nop1(3);  // 4-byte prefixed XCHG NOP.
 601  E :        return;
 602    :  
 603    :      // Handle 8- to 11-byte NOPs.
 604    :      case 11:
 605  E :        ++prefix_count;
 606    :      case 10:
 607  E :        ++prefix_count;
 608    :      case 9:
 609  E :        ++prefix_count;
 610    :      case 8:
 611  E :        nop8(prefix_count);  // 8- to 11-byte non-XCHG NOP.
 612  E :        return;
 613    :  
 614    :      // Handle 7-byte NOPs.
 615    :      case 7:
 616  E :        nop7(prefix_count);  // 7-byte non-XCHG NOP.
 617  E :        return;
 618    :  
 619    :      // Handle 5- to 6-byte NOPs.
 620    :      case 6:
 621  E :        ++prefix_count;
 622    :      case 5:
 623  E :        nop5(prefix_count);  // 5- to 6-byte non-XCHG NOP.
 624  E :        return;
 625    :  
 626    :      // Handle 4-byte NOPs.
 627    :      case 4:
 628  E :        nop4(prefix_count);  // 4-byte non-XCHG NOP.
 629  E :        return;
 630    :  
 631    :      // Handle 1- to 3-byte NOPs.
 632    :      case 3:
 633  E :        ++prefix_count;
 634    :      case 2:
 635  E :        ++prefix_count;
 636    :      case 1:
 637  E :        nop1(prefix_count);  // 1- to 3-byte XCHG NOP.
 638    :        return;
 639    :  
 640    :      case 0:
 641    :        // Nothing to do!
 642    :        break;
 643    :    }
 644    :    return;
 645  E :  }
 646    :  
 647    :  template <class ReferenceType>
 648  E :  void AssemblerBase<ReferenceType>::call(const Immediate& dst) {
 649  E :    InstructionBuffer instr(this);
 650    :  
 651  E :    instr.EmitOpCodeByte(0xE8);
 652  E :    instr.Emit32BitPCRelative(location_, dst);
 653  E :  }
 654    :  
 655    :  template <class ReferenceType>
 656  E :  void AssemblerBase<ReferenceType>::call(const Operand& dst) {
 657  E :    InstructionBuffer instr(this);
 658    :  
 659  E :    instr.EmitOpCodeByte(0xFF);
 660  E :    instr.EmitOperand(0x2, dst);
 661  E :  }
 662    :  
 663    :  template <class ReferenceType>
 664  E :  void AssemblerBase<ReferenceType>::j(ConditionCode cc, const Immediate& dst) {
 665  E :    DCHECK_LE(kMinConditionCode, cc);
 666  E :    DCHECK_GE(kMaxConditionCode, cc);
 667    :  
 668  E :    InstructionBuffer instr(this);
 669  E :    if (dst.size() == kSize32Bit) {
 670  E :      instr.EmitOpCodeByte(kTwoByteOpCodePrefix);
 671  E :      instr.EmitOpCodeByte(0x80 | cc);
 672  E :      instr.Emit32BitPCRelative(location_, dst);
 673  E :    } else {
 674  E :      DCHECK_EQ(kSize8Bit, dst.size());
 675  E :      instr.EmitOpCodeByte(0x70 | cc);
 676  E :      instr.Emit8BitPCRelative(location_, dst);
 677    :    }
 678  E :  }
 679    :  
 680    :  template <class ReferenceType>
 681    :  bool AssemblerBase<ReferenceType>::j(ConditionCode cc,
 682    :                                       Label* label,
 683  E :                                       RegisterSize size) {
 684  E :    DCHECK(label != NULL);
 685  E :    DCHECK_LE(kMinConditionCode, cc);
 686  E :    DCHECK_GE(kMaxConditionCode, cc);
 687  E :    DCHECK(size == kSize8Bit || size == kSize32Bit || size == kSizeNone);
 688    :  
 689  E :    Immediate dst;
 690  E :    if (label->bound()) {
 691    :      // Check whether the short reach is in range.
 692    :      // TODO(siggi): Utility function for this.
 693  E :      int32_t offs = label->location() - (location() + kShortBranchSize);
 694  E :      if (offs > std::numeric_limits<int8_t>::max() ||
 695    :          offs < std::numeric_limits<int8_t>::min()) {
 696    :        // Short is out of range, fail if that's requested.
 697  E :        if (size == kSize8Bit)
 698  E :          return false;
 699    :        // Short is out of range, go long.
 700  E :        size = kSize32Bit;
 701  E :      } else {
 702    :        // Short is in range, pick short if there's a choice.
 703  E :        if (size == kSizeNone)
 704  E :          size = kSize8Bit;
 705    :      }
 706    :  
 707  E :      dst = Immediate(label->location(), size);
 708  E :    } else {
 709  E :      if (size == kSizeNone)
 710  E :        size = kSize32Bit;
 711    :  
 712  E :      size_t opcode_size = kShortBranchOpcodeSize;
 713  E :      if (size == kSize32Bit)
 714  E :        opcode_size = kLongBranchOpcodeSize;
 715    :  
 716    :      // The label is not yet bound, declare our use.
 717  E :      label->Use(location() + opcode_size, size);
 718    :      // Point the destination to our own instruction as a debugging aid.
 719  E :      dst = Immediate(location(), size);
 720    :    }
 721    :  
 722  E :    j(cc, dst);
 723    :  
 724  E :    return true;
 725  E :  }
 726    :  
 727    :  template <class ReferenceType>
 728  E :  bool AssemblerBase<ReferenceType>::j(ConditionCode cc, Label* label) {
 729  E :    return j(cc, label, kSizeNone);
 730  E :  }
 731    :  
 732    :  template <class ReferenceType>
 733  E :  void AssemblerBase<ReferenceType>::jecxz(const Immediate& dst) {
 734  E :    DCHECK_EQ(kSize8Bit, dst.size());
 735  E :    InstructionBuffer instr(this);
 736  E :    instr.EmitOpCodeByte(0xE3);
 737  E :    instr.Emit8BitPCRelative(location_, dst);
 738  E :  }
 739    :  
 740    :  template <class ReferenceType>
 741  E :  void AssemblerBase<ReferenceType>::jmp(const Immediate& dst) {
 742  E :    InstructionBuffer instr(this);
 743    :  
 744  E :    if (dst.size() == kSize32Bit) {
 745  E :      instr.EmitOpCodeByte(0xE9);
 746  E :      instr.Emit32BitPCRelative(location_, dst);
 747  E :    } else {
 748  E :      DCHECK_EQ(kSize8Bit, dst.size());
 749  E :      instr.EmitOpCodeByte(0xEB);
 750  E :      instr.Emit8BitPCRelative(location_, dst);
 751    :    }
 752  E :  }
 753    :  
 754    :  template <class ReferenceType>
 755  E :  void AssemblerBase<ReferenceType>::jmp(const Operand& dst) {
 756  E :    InstructionBuffer instr(this);
 757    :  
 758  E :    instr.EmitOpCodeByte(0xFF);
 759  E :    instr.EmitOperand(0x4, dst);
 760  E :  }
 761    :  
 762    :  template <class ReferenceType>
 763  E :  void AssemblerBase<ReferenceType>::jmp(const Register32& dst) {
 764  E :    InstructionBuffer instr(this);
 765    :  
 766  E :    instr.EmitOpCodeByte(0xFF);
 767  E :    instr.EmitOpCodeByte(0xE0 | dst.code());
 768  E :  }
 769    :  
 770    :  template <class ReferenceType>
 771  E :  void AssemblerBase<ReferenceType>::l(LoopCode lc, const Immediate& dst) {
 772  E :    DCHECK_EQ(kSize8Bit, dst.size());
 773  E :    DCHECK_LE(0, lc);
 774  E :    DCHECK_GE(2, lc);
 775  E :    InstructionBuffer instr(this);
 776    :  
 777  E :    instr.EmitOpCodeByte(0xE0 | lc);
 778  E :    instr.Emit8BitPCRelative(location_, dst);
 779  E :  }
 780    :  
 781    :  template <class ReferenceType>
 782  E :  void AssemblerBase<ReferenceType>::ret() {
 783  E :    InstructionBuffer instr(this);
 784    :  
 785  E :    instr.EmitOpCodeByte(0xC3);
 786  E :  }
 787    :  
 788    :  template <class ReferenceType>
 789  E :  void AssemblerBase<ReferenceType>::ret(uint16_t n) {
 790  E :    InstructionBuffer instr(this);
 791    :  
 792  E :    instr.EmitOpCodeByte(0xC2);
 793  E :    instr.Emit16BitValue(n);
 794  E :  }
 795    :  
 796    :  template <class ReferenceType>
 797    :  void AssemblerBase<ReferenceType>::set(ConditionCode cc,
 798  E :                                         const Register32& dst) {
 799  E :    DCHECK_LE(kMinConditionCode, cc);
 800  E :    DCHECK_GE(kMaxConditionCode, cc);
 801    :  
 802  E :    InstructionBuffer instr(this);
 803  E :    instr.EmitOpCodeByte(kTwoByteOpCodePrefix);
 804  E :    instr.EmitOpCodeByte(0x90 | cc);
 805    :  
 806    :    // AMD64 Architecture Programmers Manual Volume 3: General-Purpose and System
 807    :    // Instructions: The reg field in the ModR/M byte is unused.
 808  E :    const Register32& unused = eax;
 809  E :    instr.EmitModRMByte(kReg1, unused.id(), dst.id());
 810  E :  }
 811    :  
 812    :  template <class ReferenceType>
 813    :  void AssemblerBase<ReferenceType>::mov_b(const Operand& dst,
 814  E :                                           const Immediate& src) {
 815  E :    InstructionBuffer instr(this);
 816    :  
 817  E :    instr.EmitOpCodeByte(0xC6);
 818  E :    instr.EmitOperand(0, dst);
 819  E :    instr.Emit8BitImmediate(src);
 820  E :  }
 821    :  
 822    :  template <class ReferenceType>
 823    :  void AssemblerBase<ReferenceType>::movzx_b(const Register32& dst,
 824  E :                                             const Operand& src) {
 825  E :    InstructionBuffer instr(this);
 826  E :    instr.EmitOpCodeByte(kTwoByteOpCodePrefix);
 827  E :    instr.EmitOpCodeByte(0xB6);
 828  E :    instr.EmitOperand(dst.code(), src);
 829  E :  }
 830    :  
 831    :  template <class ReferenceType>
 832    :  void AssemblerBase<ReferenceType>::mov(const Register32& dst,
 833  E :                                         const Register32& src) {
 834  E :    InstructionBuffer instr(this);
 835    :  
 836  E :    instr.EmitOpCodeByte(0x8B);
 837  E :    instr.EmitModRMByte(kReg1, dst.id(), src.id());
 838  E :  }
 839    :  
 840    :  template <class ReferenceType>
 841    :  void AssemblerBase<ReferenceType>::mov(const Register32& dst,
 842  E :                                         const Operand& src) {
 843  E :    InstructionBuffer instr(this);
 844    :  
 845  E :    if (dst.id() == kRegisterEax && IsDisplacementOnly(src)) {
 846    :      // Special encoding for indirect displacement only to EAX.
 847  E :      instr.EmitOpCodeByte(0xA1);
 848  E :      instr.Emit32BitDisplacement(src.displacement());
 849  E :    } else {
 850  E :      instr.EmitOpCodeByte(0x8B);
 851  E :      instr.EmitOperand(dst.code(), src);
 852    :    }
 853  E :  }
 854    :  
 855    :  template <class ReferenceType>
 856    :  void AssemblerBase<ReferenceType>::mov(const Operand& dst,
 857  E :                                         const Register32& src) {
 858  E :    InstructionBuffer instr(this);
 859    :  
 860  E :    if (src.id() == kRegisterEax && IsDisplacementOnly(dst)) {
 861    :      // Special encoding for indirect displacement only from EAX.
 862  E :      instr.EmitOpCodeByte(0xA3);
 863  E :      instr.Emit32BitDisplacement(dst.displacement());
 864  E :    } else {
 865  E :      instr.EmitOpCodeByte(0x89);
 866  E :      instr.EmitOperand(src.code(), dst);
 867    :    }
 868  E :  }
 869    :  
 870    :  template <class ReferenceType>
 871    :  void AssemblerBase<ReferenceType>::mov(const Register32& dst,
 872  E :                                         const Immediate& src) {
 873  E :    DCHECK_NE(kSizeNone, src.size());
 874  E :    InstructionBuffer instr(this);
 875    :  
 876  E :    instr.EmitOpCodeByte(0xB8 | dst.code());
 877  E :    instr.Emit32BitImmediate(src);
 878  E :  }
 879    :  
 880    :  template <class ReferenceType>
 881    :  void AssemblerBase<ReferenceType>::mov(const Operand& dst,
 882  E :                                         const Immediate& src) {
 883  E :    InstructionBuffer instr(this);
 884    :  
 885  E :    instr.EmitOpCodeByte(0xC7);
 886  E :    instr.EmitOperand(0, dst);
 887  E :    instr.Emit32BitImmediate(src);
 888  E :  }
 889    :  
 890    :  template <class ReferenceType>
 891    :  void AssemblerBase<ReferenceType>::mov_fs(const Register32& dst,
 892  E :                                            const Operand& src) {
 893  E :    InstructionBuffer instr(this);
 894  E :    instr.EmitOpCodeByte(kFsSegmentPrefix);
 895    :  
 896  E :    if (dst.id() == kRegisterEax && IsDisplacementOnly(src)) {
 897    :      // Special encoding for indirect displacement only to EAX.
 898  i :      instr.EmitOpCodeByte(0xA1);
 899  i :      instr.Emit32BitDisplacement(src.displacement());
 900  i :    } else {
 901  E :      instr.EmitOpCodeByte(0x8B);
 902  E :      instr.EmitOperand(dst.code(), src);
 903    :    }
 904  E :  }
 905    :  
 906    :  template <class ReferenceType>
 907    :  void AssemblerBase<ReferenceType>::mov_fs(const Operand& dst,
 908  E :                                            const Register32& src) {
 909  E :    InstructionBuffer instr(this);
 910  E :    instr.EmitOpCodeByte(kFsSegmentPrefix);
 911    :  
 912  E :    if (src.id() == kRegisterEax && IsDisplacementOnly(dst)) {
 913    :      // Special encoding for indirect displacement only from EAX.
 914  i :      instr.EmitOpCodeByte(0xA3);
 915  i :      instr.Emit32BitDisplacement(dst.displacement());
 916  i :    } else {
 917  E :      instr.EmitOpCodeByte(0x89);
 918  E :      instr.EmitOperand(src.code(), dst);
 919    :    }
 920  E :  }
 921    :  
 922    :  template <class ReferenceType>
 923    :  void AssemblerBase<ReferenceType>::lea(const Register32& dst,
 924  E :                                         const Operand& src) {
 925  E :    InstructionBuffer instr(this);
 926    :  
 927  E :    instr.EmitOpCodeByte(0x8D);
 928  E :    instr.EmitOperand(dst.code(), src);
 929  E :  }
 930    :  
 931    :  template <class ReferenceType>
 932  E :  void AssemblerBase<ReferenceType>::push(const Register32& src) {
 933  E :    InstructionBuffer instr(this);
 934    :  
 935  E :    instr.EmitOpCodeByte(0x50 | src.code());
 936  E :  }
 937    :  
 938    :  template <class ReferenceType>
 939  E :  void AssemblerBase<ReferenceType>::push(const Immediate& src) {
 940  E :    DCHECK_EQ(kSize32Bit, src.size());
 941  E :    InstructionBuffer instr(this);
 942    :  
 943  E :    instr.EmitOpCodeByte(0x68);
 944  E :    instr.Emit32BitImmediate(src);
 945  E :  }
 946    :  
 947    :  template <class ReferenceType>
 948  E :  void AssemblerBase<ReferenceType>::push(const Operand& dst) {
 949  E :    InstructionBuffer instr(this);
 950    :  
 951  E :    instr.EmitOpCodeByte(0xFF);
 952  E :    instr.EmitOperand(0x6, dst);
 953  E :  }
 954    :  
 955    :  template <class ReferenceType>
 956  E :  void AssemblerBase<ReferenceType>::pushad() {
 957  E :    InstructionBuffer instr(this);
 958    :  
 959  E :    instr.EmitOpCodeByte(0x60);
 960  E :  }
 961    :  
 962    :  template <class ReferenceType>
 963  E :  void AssemblerBase<ReferenceType>::pop(const Register32& src) {
 964  E :    InstructionBuffer instr(this);
 965    :  
 966  E :    instr.EmitOpCodeByte(0x58 | src.code());
 967  E :  }
 968    :  
 969    :  template <class ReferenceType>
 970  E :  void AssemblerBase<ReferenceType>::pop(const Operand& dst) {
 971  E :    InstructionBuffer instr(this);
 972    :  
 973  E :    instr.EmitOpCodeByte(0x8F);
 974  E :    instr.EmitOperand(0, dst);
 975  E :  }
 976    :  
 977    :  template <class ReferenceType>
 978  E :  void AssemblerBase<ReferenceType>::popad() {
 979  E :    InstructionBuffer instr(this);
 980    :  
 981  E :    instr.EmitOpCodeByte(0x61);
 982  E :  }
 983    :  
 984    :  template <class ReferenceType>
 985  E :  void AssemblerBase<ReferenceType>::pushfd() {
 986  E :    InstructionBuffer instr(this);
 987  E :    instr.EmitOpCodeByte(0x9C);
 988  E :  }
 989    :  
 990    :  template <class ReferenceType>
 991  E :  void AssemblerBase<ReferenceType>::popfd() {
 992  E :    InstructionBuffer instr(this);
 993  E :    instr.EmitOpCodeByte(0x9D);
 994  E :  }
 995    :  
 996    :  template <class ReferenceType>
 997  E :  void AssemblerBase<ReferenceType>::lahf() {
 998  E :    InstructionBuffer instr(this);
 999  E :    instr.EmitOpCodeByte(0x9F);
1000  E :  }
1001    :  
1002    :  template <class ReferenceType>
1003  E :  void AssemblerBase<ReferenceType>::sahf() {
1004  E :    InstructionBuffer instr(this);
1005  E :    instr.EmitOpCodeByte(0x9E);
1006  E :  }
1007    :  
1008    :  template <class ReferenceType>
1009    :  void AssemblerBase<ReferenceType>::test(const Register8& dst,
1010  E :                                          const Register8& src) {
1011  E :    InstructionBuffer instr(this);
1012  E :    instr.EmitArithmeticInstruction(0x84, dst, src);
1013  E :  }
1014    :  
1015    :  template <class ReferenceType>
1016    :  void AssemblerBase<ReferenceType>::test(const Register8& dst,
1017  E :                                          const Immediate& src) {
1018  E :    InstructionBuffer instr(this);
1019  E :    instr.EmitArithmeticInstructionToRegister8(0xA8, 0xF6, 0, dst, src);
1020  E :  }
1021    :  
1022    :  template <class ReferenceType>
1023    :  void AssemblerBase<ReferenceType>::test(const Register32& dst,
1024  E :                                          const Register32& src) {
1025  E :    InstructionBuffer instr(this);
1026  E :    instr.EmitArithmeticInstruction(0x85, dst, src);
1027  E :  }
1028    :  
1029    :  template <class ReferenceType>
1030    :  void AssemblerBase<ReferenceType>::test(const Register32& dst,
1031  E :                                          const Operand& src) {
1032    :    // Use commutative property for a smaller encoding.
1033  E :    test(src, dst);
1034  E :  }
1035    :  
1036    :  template <class ReferenceType>
1037    :  void AssemblerBase<ReferenceType>::test(const Operand& dst,
1038  E :                                          const Register32& src) {
1039  E :    InstructionBuffer instr(this);
1040  E :    instr.EmitArithmeticInstruction(0x85, dst, src);
1041  E :  }
1042    :  
1043    :  template <class ReferenceType>
1044    :  void AssemblerBase<ReferenceType>::test(const Register32& dst,
1045  E :                                          const Immediate& src) {
1046  E :    if (src.size() == kSize8Bit) {
1047    :      // note: There is no encoding for a 8-bit immediate with 32-bit register.
1048  E :      test(dst, Immediate(src.value(), kSize32Bit));
1049  E :    } else {
1050  E :      InstructionBuffer instr(this);
1051  E :      instr.EmitArithmeticInstructionToRegister32(0xA9, 0xF7, 0xF7, 0, dst, src);
1052  E :    }
1053  E :  }
1054    :  
1055    :  template <class ReferenceType>
1056    :  void AssemblerBase<ReferenceType>::test(const Operand& dst,
1057  E :                                          const Immediate& src) {
1058  E :    if (src.size() == kSize8Bit) {
1059    :      // note: There is no encoding for a 8-bit immediate with 32-bit register.
1060  E :      test(dst, Immediate(src.value(), kSize32Bit));
1061  E :    } else {
1062  E :      InstructionBuffer instr(this);
1063  E :      instr.EmitArithmeticInstructionToOperand(0xF7, 0xF7, 0, dst, src);
1064  E :    }
1065  E :  }
1066    :  
1067    :  template <class ReferenceType>
1068    :  void AssemblerBase<ReferenceType>::cmp(const Register8& dst,
1069  E :                                         const Register8& src) {
1070  E :    InstructionBuffer instr(this);
1071  E :    instr.EmitArithmeticInstruction(0x3A, dst, src);
1072  E :  }
1073    :  
1074    :  template <class ReferenceType>
1075    :  void AssemblerBase<ReferenceType>::cmp(const Register8& dst,
1076  E :                                         const Immediate& src) {
1077  E :    InstructionBuffer instr(this);
1078  E :    instr.EmitArithmeticInstructionToRegister8(0x3C, 0x80, 7, dst, src);
1079  E :  }
1080    :  
1081    :  template <class ReferenceType>
1082    :  void AssemblerBase<ReferenceType>::cmp(const Register32& dst,
1083  E :                                         const Register32& src) {
1084  E :    InstructionBuffer instr(this);
1085  E :    instr.EmitArithmeticInstruction(0x3B, dst, src);
1086  E :  }
1087    :  
1088    :  template <class ReferenceType>
1089    :  void AssemblerBase<ReferenceType>::cmp(const Register32& dst,
1090  E :                                         const Operand& src) {
1091  E :    InstructionBuffer instr(this);
1092  E :    instr.EmitArithmeticInstruction(0x3B, dst, src);
1093  E :  }
1094    :  
1095    :  template <class ReferenceType>
1096    :  void AssemblerBase<ReferenceType>::cmp(const Operand& dst,
1097  E :                                         const Register32& src) {
1098  E :    InstructionBuffer instr(this);
1099  E :    instr.EmitArithmeticInstruction(0x39, dst, src);
1100  E :  }
1101    :  
1102    :  template <class ReferenceType>
1103    :  void AssemblerBase<ReferenceType>::cmp(const Register32& dst,
1104  E :                                         const Immediate& src) {
1105  E :    InstructionBuffer instr(this);
1106  E :    instr.EmitArithmeticInstructionToRegister32(0x3D, 0x83, 0x81, 7, dst, src);
1107  E :  }
1108    :  
1109    :  template <class ReferenceType>
1110    :  void AssemblerBase<ReferenceType>::cmp(const Operand& dst,
1111  E :                                         const Immediate& src) {
1112  E :    InstructionBuffer instr(this);
1113  E :    instr.EmitArithmeticInstructionToOperand(0x83, 0x81, 7, dst, src);
1114  E :  }
1115    :  
1116    :  template <class ReferenceType>
1117    :  void AssemblerBase<ReferenceType>::add(const Register8& dst,
1118  E :                                         const Register8& src) {
1119  E :    InstructionBuffer instr(this);
1120  E :    instr.EmitArithmeticInstruction(0x02, dst, src);
1121  E :  }
1122    :  
1123    :  template <class ReferenceType>
1124    :  void AssemblerBase<ReferenceType>::add(const Register8& dst,
1125  E :                                         const Immediate& src) {
1126  E :    InstructionBuffer instr(this);
1127  E :    instr.EmitArithmeticInstructionToRegister8(0x04, 0x80, 0, dst, src);
1128  E :  }
1129    :  
1130    :  template <class ReferenceType>
1131    :  void AssemblerBase<ReferenceType>::add(const Register32& dst,
1132  E :                                         const Register32& src) {
1133  E :    InstructionBuffer instr(this);
1134  E :    instr.EmitArithmeticInstruction(0x03, dst, src);
1135  E :  }
1136    :  
1137    :  template <class ReferenceType>
1138    :  void AssemblerBase<ReferenceType>::add(const Register32& dst,
1139  E :                                         const Operand& src) {
1140  E :    InstructionBuffer instr(this);
1141  E :    instr.EmitArithmeticInstruction(0x03, dst, src);
1142  E :  }
1143    :  
1144    :  template <class ReferenceType>
1145    :  void AssemblerBase<ReferenceType>::add(const Operand& dst,
1146  E :                                         const Register32& src) {
1147  E :    InstructionBuffer instr(this);
1148  E :    instr.EmitArithmeticInstruction(0x01, dst, src);
1149  E :  }
1150    :  
1151    :  template <class ReferenceType>
1152    :  void AssemblerBase<ReferenceType>::add(const Register32& dst,
1153  E :                                         const Immediate& src) {
1154  E :    InstructionBuffer instr(this);
1155  E :    instr.EmitArithmeticInstructionToRegister32(0x05, 0x83, 0x81, 0, dst, src);
1156  E :  }
1157    :  
1158    :  template <class ReferenceType>
1159    :  void AssemblerBase<ReferenceType>::add(const Operand& dst,
1160  E :                                         const Immediate& src) {
1161  E :    InstructionBuffer instr(this);
1162  E :    instr.EmitArithmeticInstructionToOperand(0x83, 0x81, 0, dst, src);
1163  E :  }
1164    :  
1165    :  template <class ReferenceType>
1166    :  void AssemblerBase<ReferenceType>::sub(const Register8& dst,
1167  E :                                         const Register8& src) {
1168  E :    InstructionBuffer instr(this);
1169  E :    instr.EmitArithmeticInstruction(0x2A, dst, src);
1170  E :  }
1171    :  
1172    :  template <class ReferenceType>
1173    :  void AssemblerBase<ReferenceType>::sub(const Register8& dst,
1174  E :                                         const Immediate& src) {
1175  E :    InstructionBuffer instr(this);
1176  E :    instr.EmitArithmeticInstructionToRegister8(0x2C, 0x80, 5, dst, src);
1177  E :  }
1178    :  
1179    :  template <class ReferenceType>
1180    :  void AssemblerBase<ReferenceType>::sub(const Register32& dst,
1181  E :                                         const Register32& src) {
1182  E :    InstructionBuffer instr(this);
1183  E :    instr.EmitArithmeticInstruction(0x2B, dst, src);
1184  E :  }
1185    :  
1186    :  template <class ReferenceType>
1187    :  void AssemblerBase<ReferenceType>::sub(const Register32& dst,
1188  E :                                         const Operand& src) {
1189  E :    InstructionBuffer instr(this);
1190  E :    instr.EmitArithmeticInstruction(0x2B, dst, src);
1191  E :  }
1192    :  
1193    :  template <class ReferenceType>
1194    :  void AssemblerBase<ReferenceType>::sub(const Operand&  dst,
1195  E :                                         const Register32& src) {
1196  E :    InstructionBuffer instr(this);
1197  E :    instr.EmitArithmeticInstruction(0x29, dst, src);
1198  E :  }
1199    :  
1200    :  template <class ReferenceType>
1201    :  void AssemblerBase<ReferenceType>::sub(const Register32& dst,
1202  E :                                         const Immediate& src) {
1203  E :    InstructionBuffer instr(this);
1204  E :    instr.EmitArithmeticInstructionToRegister32(0x2D, 0x83, 0x81, 5, dst, src);
1205  E :  }
1206    :  
1207    :  template <class ReferenceType>
1208    :  void AssemblerBase<ReferenceType>::sub(const Operand&  dst,
1209  E :                                         const Immediate& src) {
1210  E :    InstructionBuffer instr(this);
1211  E :    instr.EmitArithmeticInstructionToOperand(0x83, 0x81, 5, dst, src);
1212  E :  }
1213    :  
1214    :  template <class ReferenceType>
1215    :  void AssemblerBase<ReferenceType>::imul(const Register32& dst,
1216  E :                                          const Register32& src) {
1217  E :    InstructionBuffer instr(this);
1218  E :    instr.EmitOpCodeByte(0x0F);
1219  E :    instr.EmitArithmeticInstruction(0xAF, dst, src);
1220  E :  }
1221    :  
1222    :  template <class ReferenceType>
1223    :  void AssemblerBase<ReferenceType>::imul(const Register32& dst,
1224  E :                                          const Operand& src) {
1225  E :    InstructionBuffer instr(this);
1226  E :    instr.EmitOpCodeByte(0x0F);
1227  E :    instr.EmitArithmeticInstruction(0xAF, dst, src);
1228  E :  }
1229    :  
1230    :  template <class ReferenceType>
1231    :  void AssemblerBase<ReferenceType>::imul(const Register32& dst,
1232    :                                          const Register32& base,
1233  E :                                          const Immediate& disp) {
1234  E :    InstructionBuffer instr(this);
1235  E :    instr.EmitThreeOperandArithmeticInstructionToRegister32(0x69, dst, base,
1236    :                                                            disp);
1237  E :  }
1238    :  
1239    :  template <class ReferenceType>
1240    :  void AssemblerBase<ReferenceType>::and(const Register8& dst,
1241    :                                         const Register8& src) {
1242    :    InstructionBuffer instr(this);
1243    :    instr.EmitArithmeticInstruction(0x20, src, dst);
1244    :  }
1245    :  
1246    :  template <class ReferenceType>
1247    :  void AssemblerBase<ReferenceType>::and(const Register8& dst,
1248    :                                         const Immediate& src) {
1249    :    InstructionBuffer instr(this);
1250    :    instr.EmitArithmeticInstructionToRegister8(0x24, 0x80, 4, dst, src);
1251    :  }
1252    :  
1253    :  template <class ReferenceType>
1254    :  void AssemblerBase<ReferenceType>::and(const Register32& dst,
1255  E :                                         const Register32& src) {
1256  E :    InstructionBuffer instr(this);
1257  E :    instr.EmitArithmeticInstruction(0x21, src, dst);
1258  E :  }
1259    :  
1260    :  template <class ReferenceType>
1261    :  void AssemblerBase<ReferenceType>::and(const Register32& dst,
1262  E :                                         const Operand& src) {
1263  E :    InstructionBuffer instr(this);
1264  E :    instr.EmitArithmeticInstruction(0x23, dst, src);
1265  E :  }
1266    :  
1267    :  template <class ReferenceType>
1268    :  void AssemblerBase<ReferenceType>::and(const Operand& dst,
1269  E :                                         const Register32& src) {
1270  E :    InstructionBuffer instr(this);
1271  E :    instr.EmitArithmeticInstruction(0x21, dst, src);
1272  E :  }
1273    :  
1274    :  template <class ReferenceType>
1275    :  void AssemblerBase<ReferenceType>::and(const Register32& dst,
1276  E :                                         const Immediate& src) {
1277  E :    InstructionBuffer instr(this);
1278  E :    instr.EmitArithmeticInstructionToRegister32(0x25, 0x83, 0x81, 4, dst, src);
1279  E :  }
1280    :  
1281    :  template <class ReferenceType>
1282    :  void AssemblerBase<ReferenceType>::and(const Operand& dst,
1283  E :                                         const Immediate& src) {
1284  E :    InstructionBuffer instr(this);
1285  E :    instr.EmitArithmeticInstructionToOperand(0x83, 0x81, 4, dst, src);
1286  E :  }
1287    :  
1288    :  template <class ReferenceType>
1289    :  void AssemblerBase<ReferenceType>::xor(const Register8& dst,
1290    :                                         const Register8& src) {
1291    :    InstructionBuffer instr(this);
1292    :    instr.EmitArithmeticInstruction(0x30, src, dst);
1293    :  }
1294    :  
1295    :  template <class ReferenceType>
1296    :  void AssemblerBase<ReferenceType>::xor(const Register8& dst,
1297    :                                         const Immediate& src) {
1298    :    InstructionBuffer instr(this);
1299    :    instr.EmitArithmeticInstructionToRegister8(0x34, 0x80, 6, dst, src);
1300    :  }
1301    :  
1302    :  template <class ReferenceType>
1303    :  void AssemblerBase<ReferenceType>::xor(const Register32& dst,
1304  E :                                         const Register32& src) {
1305  E :    InstructionBuffer instr(this);
1306  E :    instr.EmitArithmeticInstruction(0x31, src, dst);
1307  E :  }
1308    :  
1309    :  template <class ReferenceType>
1310    :  void AssemblerBase<ReferenceType>::xor(const Register32& dst,
1311  E :                                         const Operand& src) {
1312  E :    InstructionBuffer instr(this);
1313  E :    instr.EmitArithmeticInstruction(0x33, dst, src);
1314  E :  }
1315    :  
1316    :  template <class ReferenceType>
1317    :  void AssemblerBase<ReferenceType>::xor(const Operand& dst,
1318  E :                                         const Register32& src) {
1319  E :    InstructionBuffer instr(this);
1320  E :    instr.EmitArithmeticInstruction(0x31, dst, src);
1321  E :  }
1322    :  
1323    :  template <class ReferenceType>
1324    :  void AssemblerBase<ReferenceType>::xor(const Register32& dst,
1325  E :                                         const Immediate& src) {
1326  E :    InstructionBuffer instr(this);
1327  E :    instr.EmitArithmeticInstructionToRegister32(0x35, 0x83, 0x81, 6, dst, src);
1328  E :  }
1329    :  
1330    :  template <class ReferenceType>
1331    :  void AssemblerBase<ReferenceType>::xor(const Operand& dst,
1332  E :                                         const Immediate& src) {
1333  E :    InstructionBuffer instr(this);
1334  E :    instr.EmitArithmeticInstructionToOperand(0x83, 0x81, 6, dst, src);
1335  E :  }
1336    :  
1337    :  template <class ReferenceType>
1338    :  void AssemblerBase<ReferenceType>::shl(const Register32& dst,
1339  E :                                         const Immediate& src) {
1340  E :    InstructionBuffer instr(this);
1341  E :    if (src.value() == 1) {
1342  E :      instr.EmitOpCodeByte(0xD1);
1343  E :      instr.EmitModRMByte(kReg1, 4, dst.id());
1344  E :    } else {
1345  E :      instr.EmitOpCodeByte(0xC1);
1346  E :      instr.EmitModRMByte(kReg1, 4, dst.id());
1347  E :      instr.Emit8BitImmediate(src);
1348    :    }
1349  E :  }
1350    :  
1351    :  template <class ReferenceType>
1352    :  void AssemblerBase<ReferenceType>::shr(const Register32& dst,
1353  E :                                         const Immediate& src) {
1354  E :    InstructionBuffer instr(this);
1355  E :    if (src.value() == 1) {
1356  E :      instr.EmitOpCodeByte(0xD1);
1357  E :      instr.EmitModRMByte(kReg1, 5, dst.id());
1358  E :    } else {
1359  E :      instr.EmitOpCodeByte(0xC1);
1360  E :      instr.EmitModRMByte(kReg1, 5, dst.id());
1361  E :      instr.Emit8BitImmediate(src);
1362    :    }
1363  E :  }
1364    :  
1365    :  template <class ReferenceType>
1366    :  void AssemblerBase<ReferenceType>::xchg(const Register32& dst,
1367  E :                                          const Register32& src) {
1368  E :    InstructionBuffer instr(this);
1369  E :    instr.EmitXchg(kSize32Bit, dst.id(), src.id());
1370  E :  }
1371    :  
1372    :  template <class ReferenceType>
1373    :  void AssemblerBase<ReferenceType>::xchg(const Register16& dst,
1374  E :                                          const Register16& src) {
1375  E :    InstructionBuffer instr(this);
1376  E :    instr.EmitXchg(kSize16Bit, dst.id(), src.id());
1377  E :  }
1378    :  
1379    :  template <class ReferenceType>
1380    :  void AssemblerBase<ReferenceType>::xchg(const Register8& dst,
1381  E :                                          const Register8& src) {
1382  E :    InstructionBuffer instr(this);
1383  E :    instr.EmitXchg(kSize8Bit, dst.id(), src.id());
1384  E :  }
1385    :  
1386    :  template <class ReferenceType>
1387    :  void AssemblerBase<ReferenceType>::xchg(const Register32& dst,
1388  E :                                          const Operand& src) {
1389  E :    InstructionBuffer instr(this);
1390  E :    instr.EmitOpCodeByte(0x87);
1391  E :    instr.EmitOperand(dst.code(), src);
1392  E :  }
1393    :  
1394    :  template <class ReferenceType>
1395  E :  void AssemblerBase<ReferenceType>::nop1(size_t prefix_count) {
1396  E :    InstructionBuffer instr(this);
1397  E :    instr.EmitOperandSizePrefix(prefix_count);
1398  E :    instr.EmitXchg(kSize32Bit, kRegisterEax, kRegisterEax);
1399  E :  }
1400    :  
1401    :  template <class ReferenceType>
1402  E :  void AssemblerBase<ReferenceType>::nop4(size_t prefix_count) {
1403  E :    InstructionBuffer instr(this);
1404  E :    instr.EmitOperandSizePrefix(prefix_count);
1405    :    // 4 bytes: NOP DWORD PTR [EAX + 0] 8-bit offset
1406  E :    instr.EmitOpCodeByte(kTwoByteOpCodePrefix);
1407  E :    instr.EmitOpCodeByte(kNopOpCode);
1408  E :    instr.EmitModRMByte(kReg1ByteDisp, 0, kRegisterEax);
1409  E :    instr.Emit8BitDisplacement(Displacement(0, kSize8Bit));
1410  E :  }
1411    :  
1412    :  template <class ReferenceType>
1413  E :  void AssemblerBase<ReferenceType>::nop5(size_t prefix_count) {
1414  E :    InstructionBuffer instr(this);
1415  E :    instr.EmitOperandSizePrefix(prefix_count);
1416    :    // 5 bytes: NOP DWORD PTR [EAX + EAX * 1 + 0] 8-bit offset
1417  E :    instr.EmitOpCodeByte(kTwoByteOpCodePrefix);
1418  E :    instr.EmitOpCodeByte(kNopOpCode);
1419    :    // esp in the ModR/M byte indicates SIB to follow.
1420  E :    instr.EmitModRMByte(kReg1ByteDisp, 0, kRegisterEsp);
1421  E :    instr.EmitScaleIndexBaseByte(kTimes1, kRegisterEax, kRegisterEax);
1422  E :    instr.Emit8BitDisplacement(Displacement(0, kSize8Bit));
1423  E :  }
1424    :  
1425    :  template <class ReferenceType>
1426  E :  void AssemblerBase<ReferenceType>::nop7(size_t prefix_count) {
1427  E :    InstructionBuffer instr(this);
1428  E :    instr.EmitOperandSizePrefix(prefix_count);
1429    :    // 7 bytes: NOP DWORD PTR [EAX + 0] 32-bit offset
1430  E :    instr.EmitOpCodeByte(kTwoByteOpCodePrefix);
1431  E :    instr.EmitOpCodeByte(kNopOpCode);
1432  E :    instr.EmitModRMByte(kReg1WordDisp, 0, kRegisterEax);
1433  E :    instr.Emit32BitDisplacement(Displacement(0, kSize32Bit));
1434  E :  }
1435    :  
1436    :  template <class ReferenceType>
1437  E :  void AssemblerBase<ReferenceType>::nop8(size_t prefix_count) {
1438  E :    InstructionBuffer instr(this);
1439  E :    instr.EmitOperandSizePrefix(prefix_count);
1440    :    // 8 bytes: NOP DWORD PTR [EAX + EAX * 1 + 0] 32-bit offset
1441  E :    instr.EmitOpCodeByte(kTwoByteOpCodePrefix);
1442  E :    instr.EmitOpCodeByte(kNopOpCode);
1443    :    // esp in the ModR/M byte indicates SIB to follow.
1444  E :    instr.EmitModRMByte(kReg1WordDisp, 0, kRegisterEsp);
1445  E :    instr.EmitScaleIndexBaseByte(kTimes1, kRegisterEax, kRegisterEax);
1446  E :    instr.Emit32BitDisplacement(Displacement(0, kSize32Bit));
1447  E :  }
1448    :  
1449    :  template <class ReferenceType>
1450    :  void AssemblerBase<ReferenceType>::data(const uint8_t b) {
1451    :    InstructionBuffer instr(this);
1452    :    instr.EmitOpCodeByte(b);
1453    :  }
1454    :  
1455    :  template <class ReferenceType>
1456  E :  void AssemblerBase<ReferenceType>::Output(const InstructionBuffer& instr) {
1457  E :    serializer_->AppendInstruction(location_,
1458    :                                   instr.buf(),
1459    :                                   instr.len(),
1460    :                                   instr.reference_infos(),
1461    :                                   instr.num_reference_infos());
1462    :  
1463  E :    location_ += instr.len();
1464  E :  }
1465    :  
1466    :  template <class ReferenceType>
1467    :  bool AssemblerBase<ReferenceType>::FinalizeLabel(uint32_t location,
1468    :                                                   uint32_t destination,
1469  E :                                                   RegisterSize size) {
1470  E :    if (size == kSize8Bit) {
1471    :      // Compute the relative value, note that this is computed relative to
1472    :      // the end of the PC-relative constant, e.g. from the start of the next
1473    :      // instruction.
1474  E :      int32_t relative_value = destination - (location + 1);
1475  E :      if (relative_value < std::numeric_limits<int8_t>::min() ||
1476    :          relative_value > std::numeric_limits<int8_t>::max()) {
1477    :        // Out of bounds...
1478  E :        return false;
1479    :      }
1480  E :      uint8_t byte = relative_value & 0xFF;
1481  E :      return serializer_->FinalizeLabel(location, &byte, sizeof(byte));
1482  i :    } else {
1483  E :      DCHECK_EQ(kSize32Bit, size);
1484  E :      int32_t relative_value = destination - (location + 4);
1485    :  
1486  E :      return serializer_->FinalizeLabel(
1487    :          location, reinterpret_cast<const uint8_t*>(&relative_value),
1488    :          sizeof(relative_value));
1489    :    }
1490  E :  }
1491    :  
1492    :  }  // namespace assm
1493    :  
1494    :  #endif  // SYZYGY_ASSM_ASSEMBLER_BASE_IMPL_H_

Coverage information generated Fri Jul 29 11:00:21 2016.