| Index: src/assembler_ia32.h
 | 
| diff --git a/src/assembler_ia32.h b/src/assembler_ia32.h
 | 
| new file mode 100644
 | 
| index 0000000000000000000000000000000000000000..4038ad64c3ed7f180e6ed776d26c8b9c75c986cc
 | 
| --- /dev/null
 | 
| +++ b/src/assembler_ia32.h
 | 
| @@ -0,0 +1,739 @@
 | 
| +// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
 | 
| +// for details. All rights reserved. Use of this source code is governed by a
 | 
| +// BSD-style license that can be found in the LICENSE file.
 | 
| +//
 | 
| +// Modified by the Subzero authors.
 | 
| +//
 | 
| +//===- subzero/src/assembler_ia32.h - Assembler for x86-32 ----------------===//
 | 
| +//
 | 
| +//                        The Subzero Code Generator
 | 
| +//
 | 
| +// This file is distributed under the University of Illinois Open Source
 | 
| +// License. See LICENSE.TXT for details.
 | 
| +//
 | 
| +//===----------------------------------------------------------------------===//
 | 
| +//
 | 
| +// This file implements the Assembler class for x86-32.
 | 
| +//
 | 
| +//===----------------------------------------------------------------------===//
 | 
| +
 | 
| +#ifndef SUBZERO_SRC_ASSEMBLER_IA32_H_
 | 
| +#define SUBZERO_SRC_ASSEMBLER_IA32_H_
 | 
| +
 | 
| +#include "IceDefs.h"
 | 
| +#include "IceTypes.h"
 | 
| +#include "IceUtils.h"
 | 
| +
 | 
| +#include "assembler.h"
 | 
| +#include "assembler_constants_ia32.h"
 | 
| +// Hmm, assembler_ia32.h includes IceInstX8632.h, but IceInstX8632.cpp includes
 | 
| +// assembler_ia32.h. Or we can move the BrCond out to, or some other
 | 
| +// common group of enums assembler_constants_ia32.h.
 | 
| +
 | 
| +namespace Ice {
 | 
| +
 | 
| +class Assembler;
 | 
| +class ConstantRelocatable;
 | 
| +
 | 
| +namespace x86 {
 | 
| +
 | 
| +class DisplacementRelocation : public AssemblerFixup {
 | 
| +public:
 | 
| +  static DisplacementRelocation *create(Assembler *Asm, FixupKind Kind,
 | 
| +                                        const ConstantRelocatable *Sym) {
 | 
| +    return new (Asm->Allocate<DisplacementRelocation>())
 | 
| +        DisplacementRelocation(Kind, Sym);
 | 
| +  }
 | 
| +
 | 
| +  void Process(const MemoryRegion ®ion, intptr_t position) {
 | 
| +    (void)region;
 | 
| +    (void)position;
 | 
| +    llvm_unreachable("We might not be using this Process() method later.");
 | 
| +  }
 | 
| +
 | 
| +private:
 | 
| +  DisplacementRelocation(FixupKind Kind, const ConstantRelocatable *Sym)
 | 
| +      : AssemblerFixup(Kind, Sym) {}
 | 
| +};
 | 
| +
 | 
| +class Immediate {
 | 
| +public:
 | 
| +  explicit Immediate(int32_t value) : value_(value) {}
 | 
| +
 | 
| +  Immediate(const Immediate &other) : value_(other.value_) {}
 | 
| +
 | 
| +  int32_t value() const { return value_; }
 | 
| +
 | 
| +  bool is_int8() const { return Utils::IsInt(8, value_); }
 | 
| +  bool is_uint8() const { return Utils::IsUint(8, value_); }
 | 
| +  bool is_uint16() const { return Utils::IsUint(16, value_); }
 | 
| +
 | 
| +private:
 | 
| +  const int32_t value_;
 | 
| +
 | 
| +  // TODO(5411081): Add DISALLOW_COPY_AND_ASSIGN(Immediate) once the mac
 | 
| +  // build issue is resolved.
 | 
| +  // And remove the unnecessary copy constructor.
 | 
| +};
 | 
| +
 | 
| +class Operand {
 | 
| +public:
 | 
| +  uint8_t mod() const { return (encoding_at(0) >> 6) & 3; }
 | 
| +
 | 
| +  Register rm() const { return static_cast<Register>(encoding_at(0) & 7); }
 | 
| +
 | 
| +  ScaleFactor scale() const {
 | 
| +    return static_cast<ScaleFactor>((encoding_at(1) >> 6) & 3);
 | 
| +  }
 | 
| +
 | 
| +  Register index() const {
 | 
| +    return static_cast<Register>((encoding_at(1) >> 3) & 7);
 | 
| +  }
 | 
| +
 | 
| +  Register base() const { return static_cast<Register>(encoding_at(1) & 7); }
 | 
| +
 | 
| +  int8_t disp8() const {
 | 
| +    assert(length_ >= 2);
 | 
| +    return static_cast<int8_t>(encoding_[length_ - 1]);
 | 
| +  }
 | 
| +
 | 
| +  int32_t disp32() const {
 | 
| +    assert(length_ >= 5);
 | 
| +    return bit_copy<int32_t>(encoding_[length_ - 4]);
 | 
| +  }
 | 
| +
 | 
| +  AssemblerFixup *fixup() const { return fixup_; }
 | 
| +
 | 
| +  Operand(const Operand &other) : length_(other.length_), fixup_(other.fixup_) {
 | 
| +    memmove(&encoding_[0], &other.encoding_[0], other.length_);
 | 
| +  }
 | 
| +
 | 
| +  Operand &operator=(const Operand &other) {
 | 
| +    length_ = other.length_;
 | 
| +    fixup_ = other.fixup_;
 | 
| +    memmove(&encoding_[0], &other.encoding_[0], other.length_);
 | 
| +    return *this;
 | 
| +  }
 | 
| +
 | 
| +protected:
 | 
| +  Operand() : length_(0), fixup_(NULL) {} // Needed by subclass Address.
 | 
| +
 | 
| +  void SetModRM(int mod, Register rm) {
 | 
| +    assert((mod & ~3) == 0);
 | 
| +    encoding_[0] = (mod << 6) | rm;
 | 
| +    length_ = 1;
 | 
| +  }
 | 
| +
 | 
| +  void SetSIB(ScaleFactor scale, Register index, Register base) {
 | 
| +    assert(length_ == 1);
 | 
| +    assert((scale & ~3) == 0);
 | 
| +    encoding_[1] = (scale << 6) | (index << 3) | base;
 | 
| +    length_ = 2;
 | 
| +  }
 | 
| +
 | 
| +  void SetDisp8(int8_t disp) {
 | 
| +    assert(length_ == 1 || length_ == 2);
 | 
| +    encoding_[length_++] = static_cast<uint8_t>(disp);
 | 
| +  }
 | 
| +
 | 
| +  void SetDisp32(int32_t disp) {
 | 
| +    assert(length_ == 1 || length_ == 2);
 | 
| +    intptr_t disp_size = sizeof(disp);
 | 
| +    memmove(&encoding_[length_], &disp, disp_size);
 | 
| +    length_ += disp_size;
 | 
| +  }
 | 
| +
 | 
| +  void SetFixup(AssemblerFixup *fixup) { fixup_ = fixup; }
 | 
| +
 | 
| +private:
 | 
| +  uint8_t length_;
 | 
| +  uint8_t encoding_[6];
 | 
| +  uint8_t padding_;
 | 
| +  AssemblerFixup *fixup_;
 | 
| +
 | 
| +  explicit Operand(Register reg) : fixup_(NULL) { SetModRM(3, reg); }
 | 
| +
 | 
| +  // Get the operand encoding byte at the given index.
 | 
| +  uint8_t encoding_at(intptr_t index) const {
 | 
| +    assert(index >= 0 && index < length_);
 | 
| +    return encoding_[index];
 | 
| +  }
 | 
| +
 | 
| +  // Returns whether or not this operand is really the given register in
 | 
| +  // disguise. Used from the assembler to generate better encodings.
 | 
| +  bool IsRegister(Register reg) const {
 | 
| +    return ((encoding_[0] & 0xF8) == 0xC0) // Addressing mode is register only.
 | 
| +           && ((encoding_[0] & 0x07) == reg); // Register codes match.
 | 
| +  }
 | 
| +
 | 
| +  friend class AssemblerX86;
 | 
| +};
 | 
| +
 | 
| +class Address : public Operand {
 | 
| +public:
 | 
| +  Address(Register base, int32_t disp) {
 | 
| +    if (disp == 0 && base != EBP) {
 | 
| +      SetModRM(0, base);
 | 
| +      if (base == ESP)
 | 
| +        SetSIB(TIMES_1, ESP, base);
 | 
| +    } else if (Utils::IsInt(8, disp)) {
 | 
| +      SetModRM(1, base);
 | 
| +      if (base == ESP)
 | 
| +        SetSIB(TIMES_1, ESP, base);
 | 
| +      SetDisp8(disp);
 | 
| +    } else {
 | 
| +      SetModRM(2, base);
 | 
| +      if (base == ESP)
 | 
| +        SetSIB(TIMES_1, ESP, base);
 | 
| +      SetDisp32(disp);
 | 
| +    }
 | 
| +  }
 | 
| +
 | 
| +  Address(Register index, ScaleFactor scale, int32_t disp) {
 | 
| +    assert(index != ESP); // Illegal addressing mode.
 | 
| +    SetModRM(0, ESP);
 | 
| +    SetSIB(scale, index, EBP);
 | 
| +    SetDisp32(disp);
 | 
| +  }
 | 
| +
 | 
| +  Address(Register base, Register index, ScaleFactor scale, int32_t disp) {
 | 
| +    assert(index != ESP); // Illegal addressing mode.
 | 
| +    if (disp == 0 && base != EBP) {
 | 
| +      SetModRM(0, ESP);
 | 
| +      SetSIB(scale, index, base);
 | 
| +    } else if (Utils::IsInt(8, disp)) {
 | 
| +      SetModRM(1, ESP);
 | 
| +      SetSIB(scale, index, base);
 | 
| +      SetDisp8(disp);
 | 
| +    } else {
 | 
| +      SetModRM(2, ESP);
 | 
| +      SetSIB(scale, index, base);
 | 
| +      SetDisp32(disp);
 | 
| +    }
 | 
| +  }
 | 
| +
 | 
| +  Address(const Address &other) : Operand(other) {}
 | 
| +
 | 
| +  Address &operator=(const Address &other) {
 | 
| +    Operand::operator=(other);
 | 
| +    return *this;
 | 
| +  }
 | 
| +
 | 
| +  static Address Absolute(const uintptr_t addr, AssemblerFixup *fixup) {
 | 
| +    Address result;
 | 
| +    result.SetModRM(0, EBP);
 | 
| +    result.SetDisp32(addr);
 | 
| +    result.SetFixup(fixup);
 | 
| +    return result;
 | 
| +  }
 | 
| +
 | 
| +private:
 | 
| +  Address() {} // Needed by Address::Absolute.
 | 
| +};
 | 
| +
 | 
| +class Label {
 | 
| +public:
 | 
| +  Label() : position_(0), num_unresolved_(0) {
 | 
| +#ifdef DEBUG
 | 
| +    for (int i = 0; i < kMaxUnresolvedBranches; i++) {
 | 
| +      unresolved_near_positions_[i] = -1;
 | 
| +    }
 | 
| +#endif // DEBUG
 | 
| +  }
 | 
| +
 | 
| +  ~Label() {
 | 
| +    // Assert if label is being destroyed with unresolved branches pending.
 | 
| +    assert(!IsLinked());
 | 
| +    assert(!HasNear());
 | 
| +  }
 | 
| +
 | 
| +  // TODO(jvoung): why are labels offset by this?
 | 
| +  static const uint32_t kWordSize = sizeof(uint32_t);
 | 
| +
 | 
| +  // Returns the position for bound labels (branches that come after this
 | 
| +  // are considered backward branches). Cannot be used for unused or linked
 | 
| +  // labels.
 | 
| +  intptr_t Position() const {
 | 
| +    assert(IsBound());
 | 
| +    return -position_ - kWordSize;
 | 
| +  }
 | 
| +
 | 
| +  // Returns the position of an earlier branch instruction that was linked
 | 
| +  // to this label (branches that use this are considered forward branches).
 | 
| +  // The linked instructions form a linked list, of sorts, using the
 | 
| +  // instruction's displacement field for the location of the next
 | 
| +  // instruction that is also linked to this label.
 | 
| +  intptr_t LinkPosition() const {
 | 
| +    assert(IsLinked());
 | 
| +    return position_ - kWordSize;
 | 
| +  }
 | 
| +
 | 
| +  // Returns the position of an earlier branch instruction which
 | 
| +  // assumes that this label is "near", and bumps iterator to the
 | 
| +  // next near position.
 | 
| +  intptr_t NearPosition() {
 | 
| +    assert(HasNear());
 | 
| +    return unresolved_near_positions_[--num_unresolved_];
 | 
| +  }
 | 
| +
 | 
| +  bool IsBound() const { return position_ < 0; }
 | 
| +  bool IsLinked() const { return position_ > 0; }
 | 
| +  bool IsUnused() const { return (position_ == 0) && (num_unresolved_ == 0); }
 | 
| +  bool HasNear() const { return num_unresolved_ != 0; }
 | 
| +
 | 
| +private:
 | 
| +  void BindTo(intptr_t position) {
 | 
| +    assert(!IsBound());
 | 
| +    assert(!HasNear());
 | 
| +    position_ = -position - kWordSize;
 | 
| +    assert(IsBound());
 | 
| +  }
 | 
| +
 | 
| +  void LinkTo(intptr_t position) {
 | 
| +    assert(!IsBound());
 | 
| +    position_ = position + kWordSize;
 | 
| +    assert(IsLinked());
 | 
| +  }
 | 
| +
 | 
| +  void NearLinkTo(intptr_t position) {
 | 
| +    assert(!IsBound());
 | 
| +    assert(num_unresolved_ < kMaxUnresolvedBranches);
 | 
| +    unresolved_near_positions_[num_unresolved_++] = position;
 | 
| +  }
 | 
| +
 | 
| +  static const int kMaxUnresolvedBranches = 20;
 | 
| +
 | 
| +  intptr_t position_;
 | 
| +  intptr_t num_unresolved_;
 | 
| +  intptr_t unresolved_near_positions_[kMaxUnresolvedBranches];
 | 
| +
 | 
| +  friend class AssemblerX86;
 | 
| +  Label(const Label &) LLVM_DELETED_FUNCTION;
 | 
| +  Label &operator=(const Label &) LLVM_DELETED_FUNCTION;
 | 
| +};
 | 
| +
 | 
| +class AssemblerX86 : public Assembler {
 | 
| +public:
 | 
| +  explicit AssemblerX86(bool use_far_branches = false) : buffer_(*this) {
 | 
| +    // This mode is only needed and implemented for MIPS and ARM.
 | 
| +    assert(!use_far_branches);
 | 
| +  }
 | 
| +  ~AssemblerX86() {}
 | 
| +
 | 
| +  static const bool kNearJump = true;
 | 
| +  static const bool kFarJump = false;
 | 
| +
 | 
| +  // For integer operations that are strict on type.
 | 
| +  typedef void (AssemblerX86::*EmitRegByteR)(Register, ByteRegister);
 | 
| +  typedef void (AssemblerX86::*EmitRegReg)(Register, Register);
 | 
| +  typedef void (AssemblerX86::*EmitRegAddr)(Register, const Address &);
 | 
| +
 | 
| +  // For the integer operations that are less strict on type.
 | 
| +  // Make a version that is independent of the type and fudge a little
 | 
| +  // and consider ByteRegister the same as Register.
 | 
| +  typedef void (AssemblerX86::*EmitTyRegReg)(Type, Register, Register);
 | 
| +  typedef void (AssemblerX86::*EmitTyRegImm)(Type, Register, const Immediate &);
 | 
| +  typedef void (AssemblerX86::*EmitTyRegAddr)(Type, Register, const Address &);
 | 
| +  typedef void (AssemblerX86::*EmitTyAddrReg)(Type, const Address &, Register);
 | 
| +  typedef void (AssemblerX86::*EmitTyAddrImm)(Type, const Address &,
 | 
| +                                              const Immediate &);
 | 
| +
 | 
| +  // For XMM operations.
 | 
| +  typedef void (AssemblerX86::*EmitXmmXmm)(XmmRegister, XmmRegister);
 | 
| +  typedef void (AssemblerX86::*EmitXmmAddr)(XmmRegister, const Address &);
 | 
| +  typedef void (AssemblerX86::*EmitAddrXmm)(const Address &, XmmRegister);
 | 
| +
 | 
| +  typedef void (AssemblerX86::*EmitTyXmmXmm)(Type, XmmRegister, XmmRegister);
 | 
| +  typedef void (AssemblerX86::*EmitTyXmmAddr)(Type, XmmRegister,
 | 
| +                                              const Address &);
 | 
| +  typedef void (AssemblerX86::*EmitTyAddrXmm)(Type, const Address &,
 | 
| +                                              XmmRegister);
 | 
| +
 | 
| +  /*
 | 
| +   * Emit Machine Instructions.
 | 
| +   */
 | 
| +  void call(Register reg);
 | 
| +  void call(const Address &address);
 | 
| +  void call(Label *label);
 | 
| +  void call(const ConstantRelocatable *label);
 | 
| +
 | 
| +  static const intptr_t kCallExternalLabelSize = 5;
 | 
| +
 | 
| +  void pushl(Register reg);
 | 
| +  void pushl(const Address &address);
 | 
| +  void pushl(const Immediate &imm);
 | 
| +
 | 
| +  void popl(Register reg);
 | 
| +  void popl(const Address &address);
 | 
| +
 | 
| +  void pushal();
 | 
| +  void popal();
 | 
| +
 | 
| +  void setcc(Condition condition, ByteRegister dst);
 | 
| +
 | 
| +  void movl(Register dst, const Immediate &src);
 | 
| +  void movl(Register dst, Register src);
 | 
| +
 | 
| +  void movl(Register dst, const Address &src);
 | 
| +  void movl(const Address &dst, Register src);
 | 
| +  void movl(const Address &dst, const Immediate &imm);
 | 
| +
 | 
| +  void movzxb(Register dst, ByteRegister src);
 | 
| +  void movzxb(Register dst, const Address &src);
 | 
| +  void movsxb(Register dst, ByteRegister src);
 | 
| +  void movsxb(Register dst, const Address &src);
 | 
| +
 | 
| +  void movb(ByteRegister dst, const Address &src);
 | 
| +  void movb(const Address &dst, ByteRegister src);
 | 
| +  void movb(const Address &dst, const Immediate &imm);
 | 
| +
 | 
| +  void movzxw(Register dst, Register src);
 | 
| +  void movzxw(Register dst, const Address &src);
 | 
| +  void movsxw(Register dst, Register src);
 | 
| +  void movsxw(Register dst, const Address &src);
 | 
| +  void movw(Register dst, const Address &src);
 | 
| +  void movw(const Address &dst, Register src);
 | 
| +
 | 
| +  void leal(Register dst, const Address &src);
 | 
| +
 | 
| +  void cmov(Condition cond, Register dst, Register src);
 | 
| +
 | 
| +  void rep_movsb();
 | 
| +
 | 
| +  void movss(XmmRegister dst, const Address &src);
 | 
| +  void movss(const Address &dst, XmmRegister src);
 | 
| +  void movss(XmmRegister dst, XmmRegister src);
 | 
| +
 | 
| +  void movd(XmmRegister dst, Register src);
 | 
| +  void movd(Register dst, XmmRegister src);
 | 
| +
 | 
| +  void movq(const Address &dst, XmmRegister src);
 | 
| +  void movq(XmmRegister dst, const Address &src);
 | 
| +
 | 
| +  void addss(XmmRegister dst, XmmRegister src);
 | 
| +  void addss(XmmRegister dst, const Address &src);
 | 
| +  void subss(XmmRegister dst, XmmRegister src);
 | 
| +  void subss(XmmRegister dst, const Address &src);
 | 
| +  void mulss(XmmRegister dst, XmmRegister src);
 | 
| +  void mulss(XmmRegister dst, const Address &src);
 | 
| +  void divss(XmmRegister dst, XmmRegister src);
 | 
| +  void divss(XmmRegister dst, const Address &src);
 | 
| +
 | 
| +  void movsd(XmmRegister dst, const Address &src);
 | 
| +  void movsd(const Address &dst, XmmRegister src);
 | 
| +  void movsd(XmmRegister dst, XmmRegister src);
 | 
| +
 | 
| +  void movaps(XmmRegister dst, XmmRegister src);
 | 
| +
 | 
| +  void movups(XmmRegister dst, const Address &src);
 | 
| +  void movups(const Address &dst, XmmRegister src);
 | 
| +
 | 
| +  void addsd(XmmRegister dst, XmmRegister src);
 | 
| +  void addsd(XmmRegister dst, const Address &src);
 | 
| +  void subsd(XmmRegister dst, XmmRegister src);
 | 
| +  void subsd(XmmRegister dst, const Address &src);
 | 
| +  void mulsd(XmmRegister dst, XmmRegister src);
 | 
| +  void mulsd(XmmRegister dst, const Address &src);
 | 
| +  void divsd(XmmRegister dst, XmmRegister src);
 | 
| +  void divsd(XmmRegister dst, const Address &src);
 | 
| +
 | 
| +  void padd(Type Ty, XmmRegister dst, XmmRegister src);
 | 
| +  void padd(Type Ty, XmmRegister dst, const Address &src);
 | 
| +  void psub(Type Ty, XmmRegister dst, XmmRegister src);
 | 
| +  void psub(Type Ty, XmmRegister dst, const Address &src);
 | 
| +
 | 
| +  void addps(XmmRegister dst, XmmRegister src);
 | 
| +  void addps(XmmRegister dst, const Address &src);
 | 
| +  void subps(XmmRegister dst, XmmRegister src);
 | 
| +  void subps(XmmRegister dst, const Address &src);
 | 
| +  void divps(XmmRegister dst, XmmRegister src);
 | 
| +  void divps(XmmRegister dst, const Address &src);
 | 
| +  void mulps(XmmRegister dst, XmmRegister src);
 | 
| +  void mulps(XmmRegister dst, const Address &src);
 | 
| +  void minps(XmmRegister dst, XmmRegister src);
 | 
| +  void maxps(XmmRegister dst, XmmRegister src);
 | 
| +  void andps(XmmRegister dst, XmmRegister src);
 | 
| +  void andps(XmmRegister dst, const Address &src);
 | 
| +  void orps(XmmRegister dst, XmmRegister src);
 | 
| +
 | 
| +  // TODO(jvoung): Use the enum type instead of uint8_t.
 | 
| +  void cmpps(XmmRegister dst, XmmRegister src, uint8_t CmpCondition);
 | 
| +  void cmpps(XmmRegister dst, const Address &src, uint8_t CmpCondition);
 | 
| +
 | 
| +  void sqrtps(XmmRegister dst);
 | 
| +  void rsqrtps(XmmRegister dst);
 | 
| +  void reciprocalps(XmmRegister dst);
 | 
| +  void movhlps(XmmRegister dst, XmmRegister src);
 | 
| +  void movlhps(XmmRegister dst, XmmRegister src);
 | 
| +  void unpcklps(XmmRegister dst, XmmRegister src);
 | 
| +  void unpckhps(XmmRegister dst, XmmRegister src);
 | 
| +  void unpcklpd(XmmRegister dst, XmmRegister src);
 | 
| +  void unpckhpd(XmmRegister dst, XmmRegister src);
 | 
| +
 | 
| +  void set1ps(XmmRegister dst, Register tmp, const Immediate &imm);
 | 
| +  void shufps(XmmRegister dst, XmmRegister src, const Immediate &mask);
 | 
| +
 | 
| +  void addpd(XmmRegister dst, XmmRegister src);
 | 
| +  void subpd(XmmRegister dst, XmmRegister src);
 | 
| +  void mulpd(XmmRegister dst, XmmRegister src);
 | 
| +  void divpd(XmmRegister dst, XmmRegister src);
 | 
| +  void minpd(XmmRegister dst, XmmRegister src);
 | 
| +  void maxpd(XmmRegister dst, XmmRegister src);
 | 
| +  void sqrtpd(XmmRegister dst);
 | 
| +  void cvtps2pd(XmmRegister dst, XmmRegister src);
 | 
| +  void cvtpd2ps(XmmRegister dst, XmmRegister src);
 | 
| +  void shufpd(XmmRegister dst, XmmRegister src, const Immediate &mask);
 | 
| +
 | 
| +  void cvtsi2ss(XmmRegister dst, Register src);
 | 
| +  void cvtsi2sd(XmmRegister dst, Register src);
 | 
| +
 | 
| +  void cvtss2si(Register dst, XmmRegister src);
 | 
| +  void cvtss2sd(XmmRegister dst, XmmRegister src);
 | 
| +
 | 
| +  void cvtsd2si(Register dst, XmmRegister src);
 | 
| +  void cvtsd2ss(XmmRegister dst, XmmRegister src);
 | 
| +
 | 
| +  void cvttss2si(Register dst, XmmRegister src);
 | 
| +  void cvttsd2si(Register dst, XmmRegister src);
 | 
| +
 | 
| +  void cvtdq2pd(XmmRegister dst, XmmRegister src);
 | 
| +
 | 
| +  void ucomiss(XmmRegister a, XmmRegister b);
 | 
| +  void ucomiss(XmmRegister a, const Address &b);
 | 
| +  void ucomisd(XmmRegister a, XmmRegister b);
 | 
| +  void ucomisd(XmmRegister a, const Address &b);
 | 
| +
 | 
| +  void movmskpd(Register dst, XmmRegister src);
 | 
| +  void movmskps(Register dst, XmmRegister src);
 | 
| +
 | 
| +  void sqrtsd(XmmRegister dst, const Address &src);
 | 
| +  void sqrtsd(XmmRegister dst, XmmRegister src);
 | 
| +  void sqrtss(XmmRegister dst, const Address &src);
 | 
| +  void sqrtss(XmmRegister dst, XmmRegister src);
 | 
| +
 | 
| +  void xorpd(XmmRegister dst, const Address &src);
 | 
| +  void xorpd(XmmRegister dst, XmmRegister src);
 | 
| +  void xorps(XmmRegister dst, const Address &src);
 | 
| +  void xorps(XmmRegister dst, XmmRegister src);
 | 
| +
 | 
| +  void andpd(XmmRegister dst, const Address &src);
 | 
| +  void andpd(XmmRegister dst, XmmRegister src);
 | 
| +
 | 
| +  void orpd(XmmRegister dst, XmmRegister src);
 | 
| +
 | 
| +  void pextrd(Register dst, XmmRegister src, const Immediate &imm);
 | 
| +  void pmovsxdq(XmmRegister dst, XmmRegister src);
 | 
| +  void pcmpeqq(XmmRegister dst, XmmRegister src);
 | 
| +
 | 
| +  void pxor(XmmRegister dst, XmmRegister src);
 | 
| +
 | 
| +  enum RoundingMode {
 | 
| +    kRoundToNearest = 0x0,
 | 
| +    kRoundDown = 0x1,
 | 
| +    kRoundUp = 0x2,
 | 
| +    kRoundToZero = 0x3
 | 
| +  };
 | 
| +  void roundsd(XmmRegister dst, XmmRegister src, RoundingMode mode);
 | 
| +
 | 
| +  void flds(const Address &src);
 | 
| +  void fstps(const Address &dst);
 | 
| +
 | 
| +  void fldl(const Address &src);
 | 
| +  void fstpl(const Address &dst);
 | 
| +
 | 
| +  void fnstcw(const Address &dst);
 | 
| +  void fldcw(const Address &src);
 | 
| +
 | 
| +  void fistpl(const Address &dst);
 | 
| +  void fistps(const Address &dst);
 | 
| +  void fildl(const Address &src);
 | 
| +  void filds(const Address &src);
 | 
| +
 | 
| +  void fincstp();
 | 
| +
 | 
| +  void xchgl(Register dst, Register src);
 | 
| +
 | 
| +  void cmp(Type Ty, Register reg, const Immediate &imm);
 | 
| +  void cmp(Type Ty, Register reg0, Register reg1);
 | 
| +  void cmp(Type Ty, Register reg, const Address &address);
 | 
| +
 | 
| +  void cmp(Type Ty, const Address &address, Register reg);
 | 
| +  void cmp(Type Ty, const Address &address, const Immediate &imm);
 | 
| +
 | 
| +  void testl(Register reg1, Register reg2);
 | 
| +  void testl(Register reg, const Immediate &imm);
 | 
| +
 | 
| +  void _and(Type Ty, Register dst, const Immediate &imm);
 | 
| +  void _and(Type Ty, Register dst, Register src);
 | 
| +  void _and(Type Ty, Register dst, const Address &address);
 | 
| +
 | 
| +  void _or(Type Ty, Register dst, const Immediate &imm);
 | 
| +  void _or(Type Ty, Register dst, Register src);
 | 
| +  void _or(Type Ty, Register dst, const Address &address);
 | 
| +
 | 
| +  void _xor(Type Ty, Register dst, const Immediate &imm);
 | 
| +  void _xor(Type Ty, Register dst, Register src);
 | 
| +  void _xor(Type Ty, Register dst, const Address &address);
 | 
| +
 | 
| +  // We fudge a little, and use Register for ByteRegister as well.
 | 
| +  void add(Type Ty, Register dst, Register src);
 | 
| +  void add(Type Ty, Register reg, const Immediate &imm);
 | 
| +  void add(Type Ty, Register reg, const Address &address);
 | 
| +
 | 
| +  void add(Type Ty, const Address &address, Register reg);
 | 
| +  void add(Type Ty, const Address &address, const Immediate &imm);
 | 
| +
 | 
| +  void adc(Type Ty, Register dst, Register src);
 | 
| +  void adc(Type Ty, Register reg, const Immediate &imm);
 | 
| +  void adc(Type Ty, Register dst, const Address &address);
 | 
| +
 | 
| +  void sub(Type Ty, Register dst, Register src);
 | 
| +  void sub(Type Ty, Register reg, const Immediate &imm);
 | 
| +  void sub(Type Ty, Register reg, const Address &address);
 | 
| +
 | 
| +  void cbw();
 | 
| +  void cwd();
 | 
| +  void cdq();
 | 
| +
 | 
| +  void idivl(Register reg);
 | 
| +
 | 
| +  void imull(Register dst, Register src);
 | 
| +  void imull(Register reg, const Immediate &imm);
 | 
| +  void imull(Register reg, const Address &address);
 | 
| +
 | 
| +  void imull(Register reg);
 | 
| +  void imull(const Address &address);
 | 
| +
 | 
| +  void mull(Register reg);
 | 
| +  void mull(const Address &address);
 | 
| +
 | 
| +  void sbb(Type Ty, Register dst, Register src);
 | 
| +  void sbb(Type Ty, Register reg, const Immediate &imm);
 | 
| +  void sbb(Type Ty, Register reg, const Address &address);
 | 
| +
 | 
| +  void incl(Register reg);
 | 
| +  void incl(const Address &address);
 | 
| +
 | 
| +  void decl(Register reg);
 | 
| +  void decl(const Address &address);
 | 
| +
 | 
| +  void shll(Register reg, const Immediate &imm);
 | 
| +  void shll(Register operand, Register shifter);
 | 
| +  void shll(const Address &operand, Register shifter);
 | 
| +  void shrl(Register reg, const Immediate &imm);
 | 
| +  void shrl(Register operand, Register shifter);
 | 
| +  void sarl(Register reg, const Immediate &imm);
 | 
| +  void sarl(Register operand, Register shifter);
 | 
| +  void sarl(const Address &address, Register shifter);
 | 
| +  void shld(Register dst, Register src);
 | 
| +  void shld(Register dst, Register src, const Immediate &imm);
 | 
| +  void shld(const Address &operand, Register src);
 | 
| +  void shrd(Register dst, Register src);
 | 
| +  void shrd(Register dst, Register src, const Immediate &imm);
 | 
| +  void shrd(const Address &dst, Register src);
 | 
| +
 | 
| +  void negl(Register reg);
 | 
| +  void notl(Register reg);
 | 
| +
 | 
| +  void bsrl(Register dst, Register src);
 | 
| +
 | 
| +  void bt(Register base, Register offset);
 | 
| +
 | 
| +  void enter(const Immediate &imm);
 | 
| +  void leave();
 | 
| +
 | 
| +  void ret();
 | 
| +  void ret(const Immediate &imm);
 | 
| +
 | 
| +  // 'size' indicates size in bytes and must be in the range 1..8.
 | 
| +  void nop(int size = 1);
 | 
| +  void int3();
 | 
| +  // TODO(jvoung): should Subzero just use hlt instead of ud2?
 | 
| +  void hlt();
 | 
| +
 | 
| +  void j(Condition condition, Label *label, bool near = kFarJump);
 | 
| +  void j(Condition condition, const ConstantRelocatable *label);
 | 
| +
 | 
| +  void jmp(Register reg);
 | 
| +  void jmp(Label *label, bool near = kFarJump);
 | 
| +  void jmp(const ConstantRelocatable *label);
 | 
| +
 | 
| +  void lock();
 | 
| +  void cmpxchgl(const Address &address, Register reg);
 | 
| +
 | 
| +  void LockCmpxchgl(const Address &address, Register reg) {
 | 
| +    lock();
 | 
| +    cmpxchgl(address, reg);
 | 
| +  }
 | 
| +
 | 
| +  intptr_t PreferredLoopAlignment() { return 16; }
 | 
| +  void Align(intptr_t alignment, intptr_t offset);
 | 
| +  void Bind(Label *label);
 | 
| +
 | 
| +  intptr_t CodeSize() const { return buffer_.Size(); }
 | 
| +
 | 
| +  void FinalizeInstructions(const MemoryRegion ®ion) {
 | 
| +    buffer_.FinalizeInstructions(region);
 | 
| +  }
 | 
| +
 | 
| +  // Expose the buffer, for bringup...
 | 
| +  intptr_t GetPosition() const { return buffer_.GetPosition(); }
 | 
| +  template <typename T> T LoadBuffer(intptr_t position) const {
 | 
| +    return buffer_.Load<T>(position);
 | 
| +  }
 | 
| +  AssemblerFixup *GetLatestFixup() const { return buffer_.GetLatestFixup(); }
 | 
| +
 | 
| +private:
 | 
| +  inline void EmitUint8(uint8_t value);
 | 
| +  inline void EmitInt32(int32_t value);
 | 
| +  inline void EmitRegisterOperand(int rm, int reg);
 | 
| +  inline void EmitXmmRegisterOperand(int rm, XmmRegister reg);
 | 
| +  inline void EmitFixup(AssemblerFixup *fixup);
 | 
| +  inline void EmitOperandSizeOverride();
 | 
| +
 | 
| +  void EmitOperand(int rm, const Operand &operand);
 | 
| +  void EmitImmediate(const Immediate &imm);
 | 
| +  void EmitComplexI8(int rm, const Operand &operand,
 | 
| +                     const Immediate &immediate);
 | 
| +  void EmitComplex(int rm, const Operand &operand, const Immediate &immediate);
 | 
| +  void EmitLabel(Label *label, intptr_t instruction_size);
 | 
| +  void EmitLabelLink(Label *label);
 | 
| +  void EmitNearLabelLink(Label *label);
 | 
| +
 | 
| +  void EmitGenericShift(int rm, Register reg, const Immediate &imm);
 | 
| +  void EmitGenericShift(int rm, const Operand &operand, Register shifter);
 | 
| +
 | 
| +  AssemblerBuffer buffer_;
 | 
| +
 | 
| +  //  DISALLOW_ALLOCATION(); // disables operator new.
 | 
| +  AssemblerX86(const AssemblerX86 &) LLVM_DELETED_FUNCTION;
 | 
| +  AssemblerX86 &operator=(const AssemblerX86 &) LLVM_DELETED_FUNCTION;
 | 
| +};
 | 
| +
 | 
| +inline void AssemblerX86::EmitUint8(uint8_t value) {
 | 
| +  buffer_.Emit<uint8_t>(value);
 | 
| +}
 | 
| +
 | 
| +inline void AssemblerX86::EmitInt32(int32_t value) {
 | 
| +  buffer_.Emit<int32_t>(value);
 | 
| +}
 | 
| +
 | 
| +inline void AssemblerX86::EmitRegisterOperand(int rm, int reg) {
 | 
| +  assert(rm >= 0 && rm < 8);
 | 
| +  buffer_.Emit<uint8_t>(0xC0 + (rm << 3) + reg);
 | 
| +}
 | 
| +
 | 
| +inline void AssemblerX86::EmitXmmRegisterOperand(int rm, XmmRegister reg) {
 | 
| +  EmitRegisterOperand(rm, static_cast<Register>(reg));
 | 
| +}
 | 
| +
 | 
| +inline void AssemblerX86::EmitFixup(AssemblerFixup *fixup) {
 | 
| +  buffer_.EmitFixup(fixup);
 | 
| +}
 | 
| +
 | 
| +inline void AssemblerX86::EmitOperandSizeOverride() { EmitUint8(0x66); }
 | 
| +
 | 
| +} // end of namespace x86
 | 
| +} // end of namespace Ice
 | 
| +
 | 
| +#endif // SUBZERO_SRC_ASSEMBLER_IA32_H_
 | 
| 
 |