Coverage for /Syzygy/assm/assembler_base_impl.h

CoverageLines executed / instrumented / missingexe / inst / missLanguageGroup
99.0%6866930.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>::l(LoopCode lc, const Immediate& dst) {
 720  E :    DCHECK_EQ(kSize8Bit, dst.size());
 721  E :    DCHECK_LE(0, lc);
 722  E :    DCHECK_GE(2, lc);
 723  E :    InstructionBuffer instr(this);
 724    :  
 725  E :    instr.EmitOpCodeByte(0xE0 | lc);
 726  E :    instr.Emit8BitPCRelative(location_, dst);
 727  E :  }
 728    :  
 729    :  template <class ReferenceType>
 730  E :  void AssemblerBase<ReferenceType>::ret() {
 731  E :    InstructionBuffer instr(this);
 732    :  
 733  E :    instr.EmitOpCodeByte(0xC3);
 734  E :  }
 735    :  
 736    :  template <class ReferenceType>
 737  E :  void AssemblerBase<ReferenceType>::ret(uint16 n) {
 738  E :    InstructionBuffer instr(this);
 739    :  
 740  E :    instr.EmitOpCodeByte(0xC2);
 741  E :    instr.Emit16BitValue(n);
 742  E :  }
 743    :  
 744    :  template <class ReferenceType>
 745    :  void AssemblerBase<ReferenceType>::set(ConditionCode cc,
 746  E :                                         const Register32& dst) {
 747  E :    DCHECK_LE(kMinConditionCode, cc);
 748  E :    DCHECK_GE(kMaxConditionCode, cc);
 749    :  
 750  E :    InstructionBuffer instr(this);
 751  E :    instr.EmitOpCodeByte(kTwoByteOpCodePrefix);
 752  E :    instr.EmitOpCodeByte(0x90 | cc);
 753    :  
 754    :    // AMD64 Architecture Programmers Manual Volume 3: General-Purpose and System
 755    :    // Instructions: The reg field in the ModR/M byte is unused.
 756  E :    const Register32& unused = eax;
 757  E :    instr.EmitModRMByte(kReg1, unused.id(), dst.id());
 758  E :  }
 759    :  
 760    :  template <class ReferenceType>
 761    :  void AssemblerBase<ReferenceType>::mov_b(const Operand& dst,
 762  E :                                           const Immediate& src) {
 763  E :    InstructionBuffer instr(this);
 764    :  
 765  E :    instr.EmitOpCodeByte(0xC6);
 766  E :    instr.EmitOperand(0, dst);
 767  E :    instr.Emit8BitImmediate(src);
 768  E :  }
 769    :  
 770    :  template <class ReferenceType>
 771    :  void AssemblerBase<ReferenceType>::movzx_b(const Register32& dst,
 772  E :                                             const Operand& src) {
 773  E :    InstructionBuffer instr(this);
 774  E :    instr.EmitOpCodeByte(kTwoByteOpCodePrefix);
 775  E :    instr.EmitOpCodeByte(0xB6);
 776  E :    instr.EmitOperand(dst.code(), src);
 777  E :  }
 778    :  
 779    :  template <class ReferenceType>
 780    :  void AssemblerBase<ReferenceType>::mov(const Register32& dst,
 781  E :                                         const Register32& src) {
 782  E :    InstructionBuffer instr(this);
 783    :  
 784  E :    instr.EmitOpCodeByte(0x8B);
 785  E :    instr.EmitModRMByte(kReg1, dst.id(), src.id());
 786  E :  }
 787    :  
 788    :  template <class ReferenceType>
 789    :  void AssemblerBase<ReferenceType>::mov(const Register32& dst,
 790  E :                                         const Operand& src) {
 791  E :    InstructionBuffer instr(this);
 792    :  
 793  E :    if (dst.id() == kRegisterEax && IsDisplacementOnly(src)) {
 794    :      // Special encoding for indirect displacement only to EAX.
 795  E :      instr.EmitOpCodeByte(0xA1);
 796  E :      instr.Emit32BitDisplacement(src.displacement());
 797  E :    } else {
 798  E :      instr.EmitOpCodeByte(0x8B);
 799  E :      instr.EmitOperand(dst.code(), src);
 800    :    }
 801  E :  }
 802    :  
 803    :  template <class ReferenceType>
 804    :  void AssemblerBase<ReferenceType>::mov(const Operand& dst,
 805  E :                                         const Register32& src) {
 806  E :    InstructionBuffer instr(this);
 807    :  
 808  E :    if (src.id() == kRegisterEax && IsDisplacementOnly(dst)) {
 809    :      // Special encoding for indirect displacement only from EAX.
 810  E :      instr.EmitOpCodeByte(0xA3);
 811  E :      instr.Emit32BitDisplacement(dst.displacement());
 812  E :    } else {
 813  E :      instr.EmitOpCodeByte(0x89);
 814  E :      instr.EmitOperand(src.code(), dst);
 815    :    }
 816  E :  }
 817    :  
 818    :  template <class ReferenceType>
 819    :  void AssemblerBase<ReferenceType>::mov(const Register32& dst,
 820  E :                                         const Immediate& src) {
 821  E :    DCHECK_NE(kSizeNone, src.size());
 822  E :    InstructionBuffer instr(this);
 823    :  
 824  E :    instr.EmitOpCodeByte(0xB8 | dst.code());
 825  E :    instr.Emit32BitImmediate(src);
 826  E :  }
 827    :  
 828    :  template <class ReferenceType>
 829    :  void AssemblerBase<ReferenceType>::mov(const Operand& dst,
 830  E :                                         const Immediate& src) {
 831  E :    InstructionBuffer instr(this);
 832    :  
 833  E :    instr.EmitOpCodeByte(0xC7);
 834  E :    instr.EmitOperand(0, dst);
 835  E :    instr.Emit32BitImmediate(src);
 836  E :  }
 837    :  
 838    :  template <class ReferenceType>
 839    :  void AssemblerBase<ReferenceType>::mov_fs(const Register32& dst,
 840  E :                                            const Operand& src) {
 841  E :    InstructionBuffer instr(this);
 842  E :    instr.EmitOpCodeByte(kFsSegmentPrefix);
 843    :  
 844  E :    if (dst.id() == kRegisterEax && IsDisplacementOnly(src)) {
 845    :      // Special encoding for indirect displacement only to EAX.
 846  i :      instr.EmitOpCodeByte(0xA1);
 847  i :      instr.Emit32BitDisplacement(src.displacement());
 848  i :    } else {
 849  E :      instr.EmitOpCodeByte(0x8B);
 850  E :      instr.EmitOperand(dst.code(), src);
 851    :    }
 852  E :  }
 853    :  
 854    :  template <class ReferenceType>
 855    :  void AssemblerBase<ReferenceType>::mov_fs(const Operand& dst,
 856  E :                                            const Register32& src) {
 857  E :    InstructionBuffer instr(this);
 858  E :    instr.EmitOpCodeByte(kFsSegmentPrefix);
 859    :  
 860  E :    if (src.id() == kRegisterEax && IsDisplacementOnly(dst)) {
 861    :      // Special encoding for indirect displacement only from EAX.
 862  i :      instr.EmitOpCodeByte(0xA3);
 863  i :      instr.Emit32BitDisplacement(dst.displacement());
 864  i :    } 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>::lea(const Register32& dst,
 872  E :                                         const Operand& src) {
 873  E :    InstructionBuffer instr(this);
 874    :  
 875  E :    instr.EmitOpCodeByte(0x8D);
 876  E :    instr.EmitOperand(dst.code(), src);
 877  E :  }
 878    :  
 879    :  template <class ReferenceType>
 880  E :  void AssemblerBase<ReferenceType>::push(const Register32& src) {
 881  E :    InstructionBuffer instr(this);
 882    :  
 883  E :    instr.EmitOpCodeByte(0x50 | src.code());
 884  E :  }
 885    :  
 886    :  template <class ReferenceType>
 887  E :  void AssemblerBase<ReferenceType>::push(const Immediate& src) {
 888  E :    DCHECK_EQ(kSize32Bit, src.size());
 889  E :    InstructionBuffer instr(this);
 890    :  
 891  E :    instr.EmitOpCodeByte(0x68);
 892  E :    instr.Emit32BitImmediate(src);
 893  E :  }
 894    :  
 895    :  template <class ReferenceType>
 896  E :  void AssemblerBase<ReferenceType>::push(const Operand& dst) {
 897  E :    InstructionBuffer instr(this);
 898    :  
 899  E :    instr.EmitOpCodeByte(0xFF);
 900  E :    instr.EmitOperand(0x6, dst);
 901  E :  }
 902    :  
 903    :  template <class ReferenceType>
 904  E :  void AssemblerBase<ReferenceType>::pushad() {
 905  E :    InstructionBuffer instr(this);
 906    :  
 907  E :    instr.EmitOpCodeByte(0x60);
 908  E :  }
 909    :  
 910    :  template <class ReferenceType>
 911  E :  void AssemblerBase<ReferenceType>::pop(const Register32& src) {
 912  E :    InstructionBuffer instr(this);
 913    :  
 914  E :    instr.EmitOpCodeByte(0x58 | src.code());
 915  E :  }
 916    :  
 917    :  template <class ReferenceType>
 918  E :  void AssemblerBase<ReferenceType>::pop(const Operand& dst) {
 919  E :    InstructionBuffer instr(this);
 920    :  
 921  E :    instr.EmitOpCodeByte(0x8F);
 922  E :    instr.EmitOperand(0, dst);
 923  E :  }
 924    :  
 925    :  template <class ReferenceType>
 926  E :  void AssemblerBase<ReferenceType>::popad() {
 927  E :    InstructionBuffer instr(this);
 928    :  
 929  E :    instr.EmitOpCodeByte(0x61);
 930  E :  }
 931    :  
 932    :  template <class ReferenceType>
 933  E :  void AssemblerBase<ReferenceType>::pushfd() {
 934  E :    InstructionBuffer instr(this);
 935  E :    instr.EmitOpCodeByte(0x9C);
 936  E :  }
 937    :  
 938    :  template <class ReferenceType>
 939  E :  void AssemblerBase<ReferenceType>::popfd() {
 940  E :    InstructionBuffer instr(this);
 941  E :    instr.EmitOpCodeByte(0x9D);
 942  E :  }
 943    :  
 944    :  template <class ReferenceType>
 945  E :  void AssemblerBase<ReferenceType>::lahf() {
 946  E :    InstructionBuffer instr(this);
 947  E :    instr.EmitOpCodeByte(0x9F);
 948  E :  }
 949    :  
 950    :  template <class ReferenceType>
 951  E :  void AssemblerBase<ReferenceType>::sahf() {
 952  E :    InstructionBuffer instr(this);
 953  E :    instr.EmitOpCodeByte(0x9E);
 954  E :  }
 955    :  
 956    :  template <class ReferenceType>
 957    :  void AssemblerBase<ReferenceType>::test(const Register8& dst,
 958  E :                                          const Register8& src) {
 959  E :    InstructionBuffer instr(this);
 960  E :    instr.EmitArithmeticInstruction(0x84, dst, src);
 961  E :  }
 962    :  
 963    :  template <class ReferenceType>
 964    :  void AssemblerBase<ReferenceType>::test(const Register8& dst,
 965  E :                                          const Immediate& src) {
 966  E :    InstructionBuffer instr(this);
 967  E :    instr.EmitArithmeticInstructionToRegister8(0xA8, 0xF6, 0, dst, src);
 968  E :  }
 969    :  
 970    :  template <class ReferenceType>
 971    :  void AssemblerBase<ReferenceType>::test(const Register32& dst,
 972  E :                                          const Register32& src) {
 973  E :    InstructionBuffer instr(this);
 974  E :    instr.EmitArithmeticInstruction(0x85, dst, src);
 975  E :  }
 976    :  
 977    :  template <class ReferenceType>
 978    :  void AssemblerBase<ReferenceType>::test(const Register32& dst,
 979  E :                                          const Operand& src) {
 980    :    // Use commutative property for a smaller encoding.
 981  E :    test(src, dst);
 982  E :  }
 983    :  
 984    :  template <class ReferenceType>
 985    :  void AssemblerBase<ReferenceType>::test(const Operand& dst,
 986  E :                                          const Register32& src) {
 987  E :    InstructionBuffer instr(this);
 988  E :    instr.EmitArithmeticInstruction(0x85, dst, src);
 989  E :  }
 990    :  
 991    :  template <class ReferenceType>
 992    :  void AssemblerBase<ReferenceType>::test(const Register32& dst,
 993  E :                                          const Immediate& src) {
 994  E :    if (src.size() == kSize8Bit) {
 995    :      // note: There is no encoding for a 8-bit immediate with 32-bit register.
 996  E :      test(dst, Immediate(src.value(), kSize32Bit));
 997  E :    } else {
 998  E :      InstructionBuffer instr(this);
 999  E :      instr.EmitArithmeticInstructionToRegister32(0xA9, 0xF7, 0xF7, 0, dst, src);
1000  E :    }
1001  E :  }
1002    :  
1003    :  template <class ReferenceType>
1004    :  void AssemblerBase<ReferenceType>::test(const Operand& dst,
1005  E :                                          const Immediate& src) {
1006  E :    if (src.size() == kSize8Bit) {
1007    :      // note: There is no encoding for a 8-bit immediate with 32-bit register.
1008  E :      test(dst, Immediate(src.value(), kSize32Bit));
1009  E :    } else {
1010  E :      InstructionBuffer instr(this);
1011  E :      instr.EmitArithmeticInstructionToOperand(0xF7, 0xF7, 0, dst, src);
1012  E :    }
1013  E :  }
1014    :  
1015    :  template <class ReferenceType>
1016    :  void AssemblerBase<ReferenceType>::cmp(const Register8& dst,
1017  E :                                         const Register8& src) {
1018  E :    InstructionBuffer instr(this);
1019  E :    instr.EmitArithmeticInstruction(0x3A, dst, src);
1020  E :  }
1021    :  
1022    :  template <class ReferenceType>
1023    :  void AssemblerBase<ReferenceType>::cmp(const Register8& dst,
1024  E :                                         const Immediate& src) {
1025  E :    InstructionBuffer instr(this);
1026  E :    instr.EmitArithmeticInstructionToRegister8(0x3C, 0x80, 7, dst, src);
1027  E :  }
1028    :  
1029    :  template <class ReferenceType>
1030    :  void AssemblerBase<ReferenceType>::cmp(const Register32& dst,
1031  E :                                         const Register32& src) {
1032  E :    InstructionBuffer instr(this);
1033  E :    instr.EmitArithmeticInstruction(0x3B, dst, src);
1034  E :  }
1035    :  
1036    :  template <class ReferenceType>
1037    :  void AssemblerBase<ReferenceType>::cmp(const Register32& dst,
1038  E :                                         const Operand& src) {
1039  E :    InstructionBuffer instr(this);
1040  E :    instr.EmitArithmeticInstruction(0x3B, dst, src);
1041  E :  }
1042    :  
1043    :  template <class ReferenceType>
1044    :  void AssemblerBase<ReferenceType>::cmp(const Operand& dst,
1045  E :                                         const Register32& src) {
1046  E :    InstructionBuffer instr(this);
1047  E :    instr.EmitArithmeticInstruction(0x39, dst, src);
1048  E :  }
1049    :  
1050    :  template <class ReferenceType>
1051    :  void AssemblerBase<ReferenceType>::cmp(const Register32& dst,
1052  E :                                         const Immediate& src) {
1053  E :    InstructionBuffer instr(this);
1054  E :    instr.EmitArithmeticInstructionToRegister32(0x3D, 0x83, 0x81, 7, dst, src);
1055  E :  }
1056    :  
1057    :  template <class ReferenceType>
1058    :  void AssemblerBase<ReferenceType>::cmp(const Operand& dst,
1059  E :                                         const Immediate& src) {
1060  E :    InstructionBuffer instr(this);
1061  E :    instr.EmitArithmeticInstructionToOperand(0x83, 0x81, 7, dst, src);
1062  E :  }
1063    :  
1064    :  template <class ReferenceType>
1065    :  void AssemblerBase<ReferenceType>::add(const Register8& dst,
1066  E :                                         const Register8& src) {
1067  E :    InstructionBuffer instr(this);
1068  E :    instr.EmitArithmeticInstruction(0x02, dst, src);
1069  E :  }
1070    :  
1071    :  template <class ReferenceType>
1072    :  void AssemblerBase<ReferenceType>::add(const Register8& dst,
1073  E :                                         const Immediate& src) {
1074  E :    InstructionBuffer instr(this);
1075  E :    instr.EmitArithmeticInstructionToRegister8(0x04, 0x80, 0, dst, src);
1076  E :  }
1077    :  
1078    :  template <class ReferenceType>
1079    :  void AssemblerBase<ReferenceType>::add(const Register32& dst,
1080  E :                                         const Register32& src) {
1081  E :    InstructionBuffer instr(this);
1082  E :    instr.EmitArithmeticInstruction(0x03, dst, src);
1083  E :  }
1084    :  
1085    :  template <class ReferenceType>
1086    :  void AssemblerBase<ReferenceType>::add(const Register32& dst,
1087  E :                                         const Operand& src) {
1088  E :    InstructionBuffer instr(this);
1089  E :    instr.EmitArithmeticInstruction(0x03, dst, src);
1090  E :  }
1091    :  
1092    :  template <class ReferenceType>
1093    :  void AssemblerBase<ReferenceType>::add(const Operand& dst,
1094  E :                                         const Register32& src) {
1095  E :    InstructionBuffer instr(this);
1096  E :    instr.EmitArithmeticInstruction(0x01, dst, src);
1097  E :  }
1098    :  
1099    :  template <class ReferenceType>
1100    :  void AssemblerBase<ReferenceType>::add(const Register32& dst,
1101  E :                                         const Immediate& src) {
1102  E :    InstructionBuffer instr(this);
1103  E :    instr.EmitArithmeticInstructionToRegister32(0x05, 0x83, 0x81, 0, dst, src);
1104  E :  }
1105    :  
1106    :  template <class ReferenceType>
1107    :  void AssemblerBase<ReferenceType>::add(const Operand& dst,
1108  E :                                         const Immediate& src) {
1109  E :    InstructionBuffer instr(this);
1110  E :    instr.EmitArithmeticInstructionToOperand(0x83, 0x81, 0, dst, src);
1111  E :  }
1112    :  
1113    :  template <class ReferenceType>
1114    :  void AssemblerBase<ReferenceType>::sub(const Register8& dst,
1115  E :                                         const Register8& src) {
1116  E :    InstructionBuffer instr(this);
1117  E :    instr.EmitArithmeticInstruction(0x2A, dst, src);
1118  E :  }
1119    :  
1120    :  template <class ReferenceType>
1121    :  void AssemblerBase<ReferenceType>::sub(const Register8& dst,
1122  E :                                         const Immediate& src) {
1123  E :    InstructionBuffer instr(this);
1124  E :    instr.EmitArithmeticInstructionToRegister8(0x2C, 0x80, 5, dst, src);
1125  E :  }
1126    :  
1127    :  template <class ReferenceType>
1128    :  void AssemblerBase<ReferenceType>::sub(const Register32& dst,
1129  E :                                         const Register32& src) {
1130  E :    InstructionBuffer instr(this);
1131  E :    instr.EmitArithmeticInstruction(0x2B, dst, src);
1132  E :  }
1133    :  
1134    :  template <class ReferenceType>
1135    :  void AssemblerBase<ReferenceType>::sub(const Register32& dst,
1136  E :                                         const Operand& src) {
1137  E :    InstructionBuffer instr(this);
1138  E :    instr.EmitArithmeticInstruction(0x2B, dst, src);
1139  E :  }
1140    :  
1141    :  template <class ReferenceType>
1142    :  void AssemblerBase<ReferenceType>::sub(const Operand&  dst,
1143  E :                                         const Register32& src) {
1144  E :    InstructionBuffer instr(this);
1145  E :    instr.EmitArithmeticInstruction(0x29, dst, src);
1146  E :  }
1147    :  
1148    :  template <class ReferenceType>
1149    :  void AssemblerBase<ReferenceType>::sub(const Register32& dst,
1150  E :                                         const Immediate& src) {
1151  E :    InstructionBuffer instr(this);
1152  E :    instr.EmitArithmeticInstructionToRegister32(0x2D, 0x83, 0x81, 5, dst, src);
1153  E :  }
1154    :  
1155    :  template <class ReferenceType>
1156    :  void AssemblerBase<ReferenceType>::sub(const Operand&  dst,
1157  E :                                         const Immediate& src) {
1158  E :    InstructionBuffer instr(this);
1159  E :    instr.EmitArithmeticInstructionToOperand(0x83, 0x81, 5, dst, src);
1160  E :  }
1161    :  
1162    :  template <class ReferenceType>
1163    :  void AssemblerBase<ReferenceType>::shl(const Register32& dst,
1164  E :                                         const Immediate& src) {
1165  E :    InstructionBuffer instr(this);
1166  E :    if (src.value() == 1) {
1167  E :      instr.EmitOpCodeByte(0xD1);
1168  E :      instr.EmitModRMByte(kReg1, 4, dst.id());
1169  E :    } else {
1170  E :      instr.EmitOpCodeByte(0xC1);
1171  E :      instr.EmitModRMByte(kReg1, 4, dst.id());
1172  E :      instr.Emit8BitImmediate(src);
1173    :    }
1174  E :  }
1175    :  
1176    :  template <class ReferenceType>
1177    :  void AssemblerBase<ReferenceType>::shr(const Register32& dst,
1178  E :                                         const Immediate& src) {
1179  E :    InstructionBuffer instr(this);
1180  E :    if (src.value() == 1) {
1181  E :      instr.EmitOpCodeByte(0xD1);
1182  E :      instr.EmitModRMByte(kReg1, 5, dst.id());
1183  E :    } else {
1184  E :      instr.EmitOpCodeByte(0xC1);
1185  E :      instr.EmitModRMByte(kReg1, 5, dst.id());
1186  E :      instr.Emit8BitImmediate(src);
1187    :    }
1188  E :  }
1189    :  
1190    :  template <class ReferenceType>
1191    :  void AssemblerBase<ReferenceType>::xchg(const Register32& dst,
1192  E :                                          const Register32& src) {
1193  E :    InstructionBuffer instr(this);
1194  E :    instr.EmitXchg(kSize32Bit, dst.id(), src.id());
1195  E :  }
1196    :  
1197    :  template <class ReferenceType>
1198    :  void AssemblerBase<ReferenceType>::xchg(const Register16& dst,
1199  E :                                          const Register16& src) {
1200  E :    InstructionBuffer instr(this);
1201  E :    instr.EmitXchg(kSize16Bit, dst.id(), src.id());
1202  E :  }
1203    :  
1204    :  template <class ReferenceType>
1205    :  void AssemblerBase<ReferenceType>::xchg(const Register8& dst,
1206  E :                                          const Register8& src) {
1207  E :    InstructionBuffer instr(this);
1208  E :    instr.EmitXchg(kSize8Bit, dst.id(), src.id());
1209  E :  }
1210    :  
1211    :  template <class ReferenceType>
1212    :  void AssemblerBase<ReferenceType>::xchg(const Register32& dst,
1213  E :                                          const Operand& src) {
1214  E :    InstructionBuffer instr(this);
1215  E :    instr.EmitOpCodeByte(0x87);
1216  E :    instr.EmitOperand(dst.code(), src);
1217  E :  }
1218    :  
1219    :  template <class ReferenceType>
1220  E :  void AssemblerBase<ReferenceType>::nop1(size_t prefix_count) {
1221  E :    InstructionBuffer instr(this);
1222  E :    instr.EmitOperandSizePrefix(prefix_count);
1223  E :    instr.EmitXchg(kSize32Bit, kRegisterEax, kRegisterEax);
1224  E :  }
1225    :  
1226    :  template <class ReferenceType>
1227  E :  void AssemblerBase<ReferenceType>::nop4(size_t prefix_count) {
1228  E :    InstructionBuffer instr(this);
1229  E :    instr.EmitOperandSizePrefix(prefix_count);
1230    :    // 4 bytes: NOP DWORD PTR [EAX + 0] 8-bit offset
1231  E :    instr.EmitOpCodeByte(kTwoByteOpCodePrefix);
1232  E :    instr.EmitOpCodeByte(kNopOpCode);
1233  E :    instr.EmitModRMByte(kReg1ByteDisp, 0, kRegisterEax);
1234  E :    instr.Emit8BitDisplacement(Displacement(0, kSize8Bit));
1235  E :  }
1236    :  
1237    :  template <class ReferenceType>
1238  E :  void AssemblerBase<ReferenceType>::nop5(size_t prefix_count) {
1239  E :    InstructionBuffer instr(this);
1240  E :    instr.EmitOperandSizePrefix(prefix_count);
1241    :    // 5 bytes: NOP DWORD PTR [EAX + EAX * 1 + 0] 8-bit offset
1242  E :    instr.EmitOpCodeByte(kTwoByteOpCodePrefix);
1243  E :    instr.EmitOpCodeByte(kNopOpCode);
1244    :    // esp in the ModR/M byte indicates SIB to follow.
1245  E :    instr.EmitModRMByte(kReg1ByteDisp, 0, kRegisterEsp);
1246  E :    instr.EmitScaleIndexBaseByte(kTimes1, kRegisterEax, kRegisterEax);
1247  E :    instr.Emit8BitDisplacement(Displacement(0, kSize8Bit));
1248  E :  }
1249    :  
1250    :  template <class ReferenceType>
1251  E :  void AssemblerBase<ReferenceType>::nop7(size_t prefix_count) {
1252  E :    InstructionBuffer instr(this);
1253  E :    instr.EmitOperandSizePrefix(prefix_count);
1254    :    // 7 bytes: NOP DWORD PTR [EAX + 0] 32-bit offset
1255  E :    instr.EmitOpCodeByte(kTwoByteOpCodePrefix);
1256  E :    instr.EmitOpCodeByte(kNopOpCode);
1257  E :    instr.EmitModRMByte(kReg1WordDisp, 0, kRegisterEax);
1258  E :    instr.Emit32BitDisplacement(Displacement(0, kSize32Bit));
1259  E :  }
1260    :  
1261    :  template <class ReferenceType>
1262  E :  void AssemblerBase<ReferenceType>::nop8(size_t prefix_count) {
1263  E :    InstructionBuffer instr(this);
1264  E :    instr.EmitOperandSizePrefix(prefix_count);
1265    :    // 8 bytes: NOP DWORD PTR [EAX + EAX * 1 + 0] 32-bit offset
1266  E :    instr.EmitOpCodeByte(kTwoByteOpCodePrefix);
1267  E :    instr.EmitOpCodeByte(kNopOpCode);
1268    :    // esp in the ModR/M byte indicates SIB to follow.
1269  E :    instr.EmitModRMByte(kReg1WordDisp, 0, kRegisterEsp);
1270  E :    instr.EmitScaleIndexBaseByte(kTimes1, kRegisterEax, kRegisterEax);
1271  E :    instr.Emit32BitDisplacement(Displacement(0, kSize32Bit));
1272  E :  }
1273    :  
1274    :  template <class ReferenceType>
1275  E :  void AssemblerBase<ReferenceType>::Output(const InstructionBuffer& instr) {
1276    :    serializer_->AppendInstruction(location_,
1277    :                                   instr.buf(),
1278    :                                   instr.len(),
1279    :                                   instr.reference_infos(),
1280  E :                                   instr.num_reference_infos());
1281    :  
1282  E :    location_ += instr.len();
1283  E :  }
1284    :  
1285    :  template <class ReferenceType>
1286    :  bool AssemblerBase<ReferenceType>::FinalizeLabel(
1287  E :      uint32 location, uint32 destination, RegisterSize size) {
1288  E :    if (size == kSize8Bit) {
1289    :      // Compute the relative value, note that this is computed relative to
1290    :      // the end of the PC-relative constant, e.g. from the start of the next
1291    :      // instruction.
1292  E :      int32 relative_value = destination - (location + 1);
1293    :      if (relative_value < std::numeric_limits<int8>::min() ||
1294  E :          relative_value > std::numeric_limits<int8>::max()) {
1295    :        // Out of bounds...
1296  E :        return false;
1297    :      }
1298  E :      uint8 byte = relative_value & 0xFF;
1299  E :      return serializer_->FinalizeLabel(location, &byte, sizeof(byte));
1300  i :    } else {
1301  E :      DCHECK_EQ(kSize32Bit, size);
1302  E :      int32 relative_value = destination - (location + 4);
1303    :  
1304    :      return serializer_->FinalizeLabel(
1305    :          location,
1306    :          reinterpret_cast<const uint8*>(&relative_value),
1307  E :          sizeof(relative_value));
1308    :    }
1309  E :  }
1310    :  
1311    :  }  // namespace assm
1312    :  
1313    :  #endif  // SYZYGY_ASSM_ASSEMBLER_BASE_IMPL_H_

Coverage information generated Thu Mar 26 16:15:41 2015.