Coverage for /Syzygy/assm/assembler_base_impl.h

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

Coverage information generated Thu Jan 14 17:40:38 2016.