Commit 5d0acff3 by John Porto

Move X8632-specific Assembler stuff to Machine Traits.

As part of the refactoring moves the MachineTraits<TargetX8632> to a separate header. BUG= https://code.google.com/p/nativeclient/issues/detail?id=4077 R=jvoung@chromium.org Review URL: https://codereview.chromium.org/1216033004.
parent 7b60eb77
...@@ -175,7 +175,6 @@ SB_LDFLAGS := $(LINKOPTLEVEL) $(LD_EXTRA) ...@@ -175,7 +175,6 @@ SB_LDFLAGS := $(LINKOPTLEVEL) $(LD_EXTRA)
SRCS = \ SRCS = \
IceAssembler.cpp \ IceAssembler.cpp \
IceAssemblerX8632.cpp \
IceAssemblerX8664.cpp \ IceAssemblerX8664.cpp \
IceBrowserCompileServer.cpp \ IceBrowserCompileServer.cpp \
IceCfg.cpp \ IceCfg.cpp \
......
//===- subzero/src/assembler_ia32.h - Assembler for x86-32 ------*- C++ -*-===// //===- subzero/src/IceAssemblerX8632.h - Assembler for x86-32 ---*- C++ -*-===//
// //
// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file // 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 // for details. All rights reserved. Use of this source code is governed by a
...@@ -23,906 +23,34 @@ ...@@ -23,906 +23,34 @@
#define SUBZERO_SRC_ICEASSEMBLERX8632_H #define SUBZERO_SRC_ICEASSEMBLERX8632_H
#include "IceAssembler.h" #include "IceAssembler.h"
#include "IceConditionCodesX8632.h" #include "IceAssemblerX86Base.h"
#include "IceDefs.h" #include "IceDefs.h"
#include "IceOperand.h" #include "IceOperand.h"
#include "IceRegistersX8632.h" #include "IceTargetLoweringX8632Traits.h"
#include "IceTypes.h" #include "IceTypes.h"
#include "IceUtils.h" #include "IceUtils.h"
namespace Ice { namespace Ice {
using RegX8632::GPRRegister; class TargetX8632;
using RegX8632::XmmRegister;
using RegX8632::ByteRegister;
using RegX8632::X87STRegister;
namespace X8632 { namespace X8632 {
const int MAX_NOP_SIZE = 8; class AssemblerX8632 : public X86Internal::AssemblerX86Base<TargetX8632> {
enum ScaleFactor { TIMES_1 = 0, TIMES_2 = 1, TIMES_4 = 2, TIMES_8 = 3 };
class Immediate {
Immediate(const Immediate &) = delete;
Immediate &operator=(const Immediate &) = delete;
public:
explicit Immediate(int32_t value) : value_(value) {}
Immediate(RelocOffsetT offset, AssemblerFixup *fixup)
: value_(offset), fixup_(fixup) {
// Use the Offset in the "value" for now. If we decide to process fixups,
// we'll need to patch that offset with the true value.
}
int32_t value() const { return value_; }
AssemblerFixup *fixup() const { return fixup_; }
bool is_int8() const {
// We currently only allow 32-bit fixups, and they usually have value = 0,
// so if fixup_ != nullptr, it shouldn't be classified as int8/16.
return fixup_ == nullptr && Utils::IsInt(8, value_);
}
bool is_uint8() const {
return fixup_ == nullptr && Utils::IsUint(8, value_);
}
bool is_uint16() const {
return fixup_ == nullptr && Utils::IsUint(16, value_);
}
private:
const int32_t value_;
AssemblerFixup *fixup_ = nullptr;
};
class Operand {
public:
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;
}
uint8_t mod() const { return (encoding_at(0) >> 6) & 3; }
GPRRegister rm() const {
return static_cast<GPRRegister>(encoding_at(0) & 7);
}
ScaleFactor scale() const {
return static_cast<ScaleFactor>((encoding_at(1) >> 6) & 3);
}
GPRRegister index() const {
return static_cast<GPRRegister>((encoding_at(1) >> 3) & 7);
}
GPRRegister base() const {
return static_cast<GPRRegister>(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_; }
protected:
Operand() : length_(0), fixup_(nullptr) {} // Needed by subclass Address.
void SetModRM(int mod, GPRRegister rm) {
assert((mod & ~3) == 0);
encoding_[0] = (mod << 6) | rm;
length_ = 1;
}
void SetSIB(ScaleFactor scale, GPRRegister index, GPRRegister 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];
AssemblerFixup *fixup_;
explicit Operand(GPRRegister reg) : fixup_(nullptr) { 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(GPRRegister reg) const {
return ((encoding_[0] & 0xF8) == 0xC0) // Addressing mode is register only.
&& ((encoding_[0] & 0x07) == reg); // Register codes match.
}
friend class AssemblerX8632;
};
class Address : public Operand {
public:
Address(const Address &other) : Operand(other) {}
Address &operator=(const Address &other) {
Operand::operator=(other);
return *this;
}
Address(GPRRegister base, int32_t disp) {
if (disp == 0 && base != RegX8632::Encoded_Reg_ebp) {
SetModRM(0, base);
if (base == RegX8632::Encoded_Reg_esp)
SetSIB(TIMES_1, RegX8632::Encoded_Reg_esp, base);
} else if (Utils::IsInt(8, disp)) {
SetModRM(1, base);
if (base == RegX8632::Encoded_Reg_esp)
SetSIB(TIMES_1, RegX8632::Encoded_Reg_esp, base);
SetDisp8(disp);
} else {
SetModRM(2, base);
if (base == RegX8632::Encoded_Reg_esp)
SetSIB(TIMES_1, RegX8632::Encoded_Reg_esp, base);
SetDisp32(disp);
}
}
Address(GPRRegister index, ScaleFactor scale, int32_t disp) {
assert(index != RegX8632::Encoded_Reg_esp); // Illegal addressing mode.
SetModRM(0, RegX8632::Encoded_Reg_esp);
SetSIB(scale, index, RegX8632::Encoded_Reg_ebp);
SetDisp32(disp);
}
Address(GPRRegister base, GPRRegister index, ScaleFactor scale,
int32_t disp) {
assert(index != RegX8632::Encoded_Reg_esp); // Illegal addressing mode.
if (disp == 0 && base != RegX8632::Encoded_Reg_ebp) {
SetModRM(0, RegX8632::Encoded_Reg_esp);
SetSIB(scale, index, base);
} else if (Utils::IsInt(8, disp)) {
SetModRM(1, RegX8632::Encoded_Reg_esp);
SetSIB(scale, index, base);
SetDisp8(disp);
} else {
SetModRM(2, RegX8632::Encoded_Reg_esp);
SetSIB(scale, index, base);
SetDisp32(disp);
}
}
static Address Absolute(const uintptr_t addr) {
Address result;
result.SetModRM(0, RegX8632::Encoded_Reg_ebp);
result.SetDisp32(addr);
return result;
}
static Address Absolute(RelocOffsetT Offset, AssemblerFixup *fixup) {
Address result;
result.SetModRM(0, RegX8632::Encoded_Reg_ebp);
// Use the Offset in the displacement for now. If we decide to process
// fixups later, we'll need to patch up the emitted displacement.
result.SetDisp32(Offset);
result.SetFixup(fixup);
return result;
}
static Address ofConstPool(Assembler *Asm, const Constant *Imm);
private:
Address() = default; // Needed by Address::Absolute.
};
class Label {
Label(const Label &) = delete;
Label &operator=(const Label &) = delete;
public:
Label() {
if (BuildDefs::asserts()) {
for (int i = 0; i < kMaxUnresolvedBranches; i++) {
unresolved_near_positions_[i] = -1;
}
}
}
~Label() = default;
void FinalCheck() const {
// 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 constexpr int kMaxUnresolvedBranches = 20;
intptr_t position_ = 0;
intptr_t num_unresolved_ = 0;
// TODO(stichnot,jvoung): Can this instead be
// llvm::SmallVector<intptr_t, kMaxUnresolvedBranches> ?
intptr_t unresolved_near_positions_[kMaxUnresolvedBranches];
friend class AssemblerX8632;
};
class AssemblerX8632 : public Assembler {
AssemblerX8632(const AssemblerX8632 &) = delete; AssemblerX8632(const AssemblerX8632 &) = delete;
AssemblerX8632 &operator=(const AssemblerX8632 &) = delete; AssemblerX8632 &operator=(const AssemblerX8632 &) = delete;
public: public:
explicit AssemblerX8632(bool use_far_branches = false) explicit AssemblerX8632(bool use_far_branches = false)
: Assembler(Asm_X8632) { : X86Internal::AssemblerX86Base<TargetX8632>(Asm_X8632,
// This mode is only needed and implemented for MIPS and ARM. use_far_branches) {}
assert(!use_far_branches); ~AssemblerX8632() override = default;
(void)use_far_branches;
}
~AssemblerX8632() override;
static const bool kNearJump = true;
static const bool kFarJump = false;
void alignFunction() override;
SizeT getBundleAlignLog2Bytes() const override { return 5; }
const char *getNonExecPadDirective() const override { return ".p2align"; }
llvm::ArrayRef<uint8_t> getNonExecBundlePadding() const override {
static const uint8_t Padding[] = {0xF4};
return llvm::ArrayRef<uint8_t>(Padding, 1);
}
void padWithNop(intptr_t Padding) override {
while (Padding > MAX_NOP_SIZE) {
nop(MAX_NOP_SIZE);
Padding -= MAX_NOP_SIZE;
}
if (Padding)
nop(Padding);
}
Label *GetOrCreateCfgNodeLabel(SizeT NodeNumber);
void bindCfgNodeLabel(SizeT NodeNumber) override;
Label *GetOrCreateLocalLabel(SizeT Number);
void BindLocalLabel(SizeT Number);
bool fixupIsPCRel(FixupKind Kind) const override {
// Currently assuming this is the only PC-rel relocation type used.
return Kind == llvm::ELF::R_386_PC32;
}
static bool classof(const Assembler *Asm) { static bool classof(const Assembler *Asm) {
return Asm->getKind() == Asm_X8632; return Asm->getKind() == Asm_X8632;
} }
// Operations to emit GPR instructions (and dispatch on operand type).
typedef void (AssemblerX8632::*TypedEmitGPR)(Type, GPRRegister);
typedef void (AssemblerX8632::*TypedEmitAddr)(Type, const Address &);
struct GPREmitterOneOp {
TypedEmitGPR Reg;
TypedEmitAddr Addr;
};
typedef void (AssemblerX8632::*TypedEmitGPRGPR)(Type, GPRRegister,
GPRRegister);
typedef void (AssemblerX8632::*TypedEmitGPRAddr)(Type, GPRRegister,
const Address &);
typedef void (AssemblerX8632::*TypedEmitGPRImm)(Type, GPRRegister,
const Immediate &);
struct GPREmitterRegOp {
TypedEmitGPRGPR GPRGPR;
TypedEmitGPRAddr GPRAddr;
TypedEmitGPRImm GPRImm;
};
struct GPREmitterShiftOp {
// Technically, Addr/GPR and Addr/Imm are also allowed, but */Addr are not.
// In practice, we always normalize the Dest to a Register first.
TypedEmitGPRGPR GPRGPR;
TypedEmitGPRImm GPRImm;
};
typedef void (AssemblerX8632::*TypedEmitGPRGPRImm)(Type, GPRRegister,
GPRRegister,
const Immediate &);
struct GPREmitterShiftD {
// Technically AddrGPR and AddrGPRImm are also allowed, but in practice
// we always normalize Dest to a Register first.
TypedEmitGPRGPR GPRGPR;
TypedEmitGPRGPRImm GPRGPRImm;
};
typedef void (AssemblerX8632::*TypedEmitAddrGPR)(Type, const Address &,
GPRRegister);
typedef void (AssemblerX8632::*TypedEmitAddrImm)(Type, const Address &,
const Immediate &);
struct GPREmitterAddrOp {
TypedEmitAddrGPR AddrGPR;
TypedEmitAddrImm AddrImm;
};
// Operations to emit XMM instructions (and dispatch on operand type).
typedef void (AssemblerX8632::*TypedEmitXmmXmm)(Type, XmmRegister,
XmmRegister);
typedef void (AssemblerX8632::*TypedEmitXmmAddr)(Type, XmmRegister,
const Address &);
struct XmmEmitterRegOp {
TypedEmitXmmXmm XmmXmm;
TypedEmitXmmAddr XmmAddr;
};
typedef void (AssemblerX8632::*EmitXmmXmm)(XmmRegister, XmmRegister);
typedef void (AssemblerX8632::*EmitXmmAddr)(XmmRegister, const Address &);
typedef void (AssemblerX8632::*EmitAddrXmm)(const Address &, XmmRegister);
struct XmmEmitterMovOps {
EmitXmmXmm XmmXmm;
EmitXmmAddr XmmAddr;
EmitAddrXmm AddrXmm;
};
typedef void (AssemblerX8632::*TypedEmitXmmImm)(Type, XmmRegister,
const Immediate &);
struct XmmEmitterShiftOp {
TypedEmitXmmXmm XmmXmm;
TypedEmitXmmAddr XmmAddr;
TypedEmitXmmImm XmmImm;
};
// Cross Xmm/GPR cast instructions.
template <typename DReg_t, typename SReg_t> struct CastEmitterRegOp {
typedef void (AssemblerX8632::*TypedEmitRegs)(Type, DReg_t, SReg_t);
typedef void (AssemblerX8632::*TypedEmitAddr)(Type, DReg_t,
const Address &);
TypedEmitRegs RegReg;
TypedEmitAddr RegAddr;
};
// Three operand (potentially) cross Xmm/GPR instructions.
// The last operand must be an immediate.
template <typename DReg_t, typename SReg_t> struct ThreeOpImmEmitter {
typedef void (AssemblerX8632::*TypedEmitRegRegImm)(Type, DReg_t, SReg_t,
const Immediate &);
typedef void (AssemblerX8632::*TypedEmitRegAddrImm)(Type, DReg_t,
const Address &,
const Immediate &);
TypedEmitRegRegImm RegRegImm;
TypedEmitRegAddrImm RegAddrImm;
};
/*
* Emit Machine Instructions.
*/
void call(GPRRegister reg);
void call(const Address &address);
void call(const ConstantRelocatable *label);
void call(const Immediate &abs_address);
static const intptr_t kCallExternalLabelSize = 5;
void pushl(GPRRegister reg);
void popl(GPRRegister reg);
void popl(const Address &address);
void pushal();
void popal();
void setcc(CondX86::BrCond condition, ByteRegister dst);
void setcc(CondX86::BrCond condition, const Address &address);
void mov(Type Ty, GPRRegister dst, const Immediate &src);
void mov(Type Ty, GPRRegister dst, GPRRegister src);
void mov(Type Ty, GPRRegister dst, const Address &src);
void mov(Type Ty, const Address &dst, GPRRegister src);
void mov(Type Ty, const Address &dst, const Immediate &imm);
void movzx(Type Ty, GPRRegister dst, GPRRegister src);
void movzx(Type Ty, GPRRegister dst, const Address &src);
void movsx(Type Ty, GPRRegister dst, GPRRegister src);
void movsx(Type Ty, GPRRegister dst, const Address &src);
void lea(Type Ty, GPRRegister dst, const Address &src);
void cmov(Type Ty, CondX86::BrCond cond, GPRRegister dst, GPRRegister src);
void cmov(Type Ty, CondX86::BrCond cond, GPRRegister dst, const Address &src);
void rep_movsb();
void movss(Type Ty, XmmRegister dst, const Address &src);
void movss(Type Ty, const Address &dst, XmmRegister src);
void movss(Type Ty, XmmRegister dst, XmmRegister src);
void movd(XmmRegister dst, GPRRegister src);
void movd(XmmRegister dst, const Address &src);
void movd(GPRRegister dst, XmmRegister src);
void movd(const Address &dst, XmmRegister src);
void movq(XmmRegister dst, XmmRegister src);
void movq(const Address &dst, XmmRegister src);
void movq(XmmRegister dst, const Address &src);
void addss(Type Ty, XmmRegister dst, XmmRegister src);
void addss(Type Ty, XmmRegister dst, const Address &src);
void subss(Type Ty, XmmRegister dst, XmmRegister src);
void subss(Type Ty, XmmRegister dst, const Address &src);
void mulss(Type Ty, XmmRegister dst, XmmRegister src);
void mulss(Type Ty, XmmRegister dst, const Address &src);
void divss(Type Ty, XmmRegister dst, XmmRegister src);
void divss(Type Ty, XmmRegister dst, const Address &src);
void movaps(XmmRegister dst, XmmRegister src);
void movups(XmmRegister dst, XmmRegister src);
void movups(XmmRegister dst, const Address &src);
void movups(const Address &dst, XmmRegister src);
void padd(Type Ty, XmmRegister dst, XmmRegister src);
void padd(Type Ty, XmmRegister dst, const Address &src);
void pand(Type Ty, XmmRegister dst, XmmRegister src);
void pand(Type Ty, XmmRegister dst, const Address &src);
void pandn(Type Ty, XmmRegister dst, XmmRegister src);
void pandn(Type Ty, XmmRegister dst, const Address &src);
void pmull(Type Ty, XmmRegister dst, XmmRegister src);
void pmull(Type Ty, XmmRegister dst, const Address &src);
void pmuludq(Type Ty, XmmRegister dst, XmmRegister src);
void pmuludq(Type Ty, XmmRegister dst, const Address &src);
void por(Type Ty, XmmRegister dst, XmmRegister src);
void por(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 pxor(Type Ty, XmmRegister dst, XmmRegister src);
void pxor(Type Ty, XmmRegister dst, const Address &src);
void psll(Type Ty, XmmRegister dst, XmmRegister src);
void psll(Type Ty, XmmRegister dst, const Address &src);
void psll(Type Ty, XmmRegister dst, const Immediate &src);
void psra(Type Ty, XmmRegister dst, XmmRegister src);
void psra(Type Ty, XmmRegister dst, const Address &src);
void psra(Type Ty, XmmRegister dst, const Immediate &src);
void psrl(Type Ty, XmmRegister dst, XmmRegister src);
void psrl(Type Ty, XmmRegister dst, const Address &src);
void psrl(Type Ty, XmmRegister dst, const Immediate &src);
void addps(Type Ty, XmmRegister dst, XmmRegister src);
void addps(Type Ty, XmmRegister dst, const Address &src);
void subps(Type Ty, XmmRegister dst, XmmRegister src);
void subps(Type Ty, XmmRegister dst, const Address &src);
void divps(Type Ty, XmmRegister dst, XmmRegister src);
void divps(Type Ty, XmmRegister dst, const Address &src);
void mulps(Type Ty, XmmRegister dst, XmmRegister src);
void mulps(Type Ty, 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);
void blendvps(Type Ty, XmmRegister dst, XmmRegister src);
void blendvps(Type Ty, XmmRegister dst, const Address &src);
void pblendvb(Type Ty, XmmRegister dst, XmmRegister src);
void pblendvb(Type Ty, XmmRegister dst, const Address &src);
void cmpps(XmmRegister dst, XmmRegister src, CondX86::CmppsCond CmpCondition);
void cmpps(XmmRegister dst, const Address &src,
CondX86::CmppsCond 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, GPRRegister tmp, const Immediate &imm);
void shufps(XmmRegister dst, XmmRegister src, const Immediate &mask);
void minpd(XmmRegister dst, XmmRegister src);
void maxpd(XmmRegister dst, XmmRegister src);
void sqrtpd(XmmRegister dst);
void shufpd(XmmRegister dst, XmmRegister src, const Immediate &mask);
void pshufd(Type Ty, XmmRegister dst, XmmRegister src, const Immediate &mask);
void pshufd(Type Ty, XmmRegister dst, const Address &src,
const Immediate &mask);
void shufps(Type Ty, XmmRegister dst, XmmRegister src, const Immediate &mask);
void shufps(Type Ty, XmmRegister dst, const Address &src,
const Immediate &mask);
void cvtdq2ps(Type, XmmRegister dst, XmmRegister src);
void cvtdq2ps(Type, XmmRegister dst, const Address &src);
void cvttps2dq(Type, XmmRegister dst, XmmRegister src);
void cvttps2dq(Type, XmmRegister dst, const Address &src);
void cvtsi2ss(Type DestTy, XmmRegister dst, GPRRegister src);
void cvtsi2ss(Type DestTy, XmmRegister dst, const Address &src);
void cvtfloat2float(Type SrcTy, XmmRegister dst, XmmRegister src);
void cvtfloat2float(Type SrcTy, XmmRegister dst, const Address &src);
void cvttss2si(Type SrcTy, GPRRegister dst, XmmRegister src);
void cvttss2si(Type SrcTy, GPRRegister dst, const Address &src);
void ucomiss(Type Ty, XmmRegister a, XmmRegister b);
void ucomiss(Type Ty, XmmRegister a, const Address &b);
void movmskpd(GPRRegister dst, XmmRegister src);
void movmskps(GPRRegister dst, XmmRegister src);
void sqrtss(Type Ty, XmmRegister dst, const Address &src);
void sqrtss(Type Ty, 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 insertps(Type Ty, XmmRegister dst, XmmRegister src,
const Immediate &imm);
void insertps(Type Ty, XmmRegister dst, const Address &src,
const Immediate &imm);
void pinsr(Type Ty, XmmRegister dst, GPRRegister src, const Immediate &imm);
void pinsr(Type Ty, XmmRegister dst, const Address &src,
const Immediate &imm);
void pextr(Type Ty, GPRRegister dst, XmmRegister src, const Immediate &imm);
void pextr(Type Ty, GPRRegister dst, const Address &src,
const Immediate &imm);
void pmovsxdq(XmmRegister dst, XmmRegister src);
void pcmpeq(Type Ty, XmmRegister dst, XmmRegister src);
void pcmpeq(Type Ty, XmmRegister dst, const Address &src);
void pcmpgt(Type Ty, XmmRegister dst, XmmRegister src);
void pcmpgt(Type Ty, XmmRegister dst, const Address &src);
enum RoundingMode {
kRoundToNearest = 0x0,
kRoundDown = 0x1,
kRoundUp = 0x2,
kRoundToZero = 0x3
};
void roundsd(XmmRegister dst, XmmRegister src, RoundingMode mode);
void fld(Type Ty, const Address &src);
void fstp(Type Ty, const Address &dst);
void fstp(X87STRegister st);
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 cmp(Type Ty, GPRRegister reg0, GPRRegister reg1);
void cmp(Type Ty, GPRRegister reg, const Address &address);
void cmp(Type Ty, GPRRegister reg, const Immediate &imm);
void cmp(Type Ty, const Address &address, GPRRegister reg);
void cmp(Type Ty, const Address &address, const Immediate &imm);
void test(Type Ty, GPRRegister reg0, GPRRegister reg1);
void test(Type Ty, GPRRegister reg, const Immediate &imm);
void test(Type Ty, const Address &address, GPRRegister reg);
void test(Type Ty, const Address &address, const Immediate &imm);
void And(Type Ty, GPRRegister dst, GPRRegister src);
void And(Type Ty, GPRRegister dst, const Address &address);
void And(Type Ty, GPRRegister dst, const Immediate &imm);
void And(Type Ty, const Address &address, GPRRegister reg);
void And(Type Ty, const Address &address, const Immediate &imm);
void Or(Type Ty, GPRRegister dst, GPRRegister src);
void Or(Type Ty, GPRRegister dst, const Address &address);
void Or(Type Ty, GPRRegister dst, const Immediate &imm);
void Or(Type Ty, const Address &address, GPRRegister reg);
void Or(Type Ty, const Address &address, const Immediate &imm);
void Xor(Type Ty, GPRRegister dst, GPRRegister src);
void Xor(Type Ty, GPRRegister dst, const Address &address);
void Xor(Type Ty, GPRRegister dst, const Immediate &imm);
void Xor(Type Ty, const Address &address, GPRRegister reg);
void Xor(Type Ty, const Address &address, const Immediate &imm);
void add(Type Ty, GPRRegister dst, GPRRegister src);
void add(Type Ty, GPRRegister reg, const Address &address);
void add(Type Ty, GPRRegister reg, const Immediate &imm);
void add(Type Ty, const Address &address, GPRRegister reg);
void add(Type Ty, const Address &address, const Immediate &imm);
void adc(Type Ty, GPRRegister dst, GPRRegister src);
void adc(Type Ty, GPRRegister dst, const Address &address);
void adc(Type Ty, GPRRegister reg, const Immediate &imm);
void adc(Type Ty, const Address &address, GPRRegister reg);
void adc(Type Ty, const Address &address, const Immediate &imm);
void sub(Type Ty, GPRRegister dst, GPRRegister src);
void sub(Type Ty, GPRRegister reg, const Address &address);
void sub(Type Ty, GPRRegister reg, const Immediate &imm);
void sub(Type Ty, const Address &address, GPRRegister reg);
void sub(Type Ty, const Address &address, const Immediate &imm);
void sbb(Type Ty, GPRRegister dst, GPRRegister src);
void sbb(Type Ty, GPRRegister reg, const Address &address);
void sbb(Type Ty, GPRRegister reg, const Immediate &imm);
void sbb(Type Ty, const Address &address, GPRRegister reg);
void sbb(Type Ty, const Address &address, const Immediate &imm);
void cbw();
void cwd();
void cdq();
void div(Type Ty, GPRRegister reg);
void div(Type Ty, const Address &address);
void idiv(Type Ty, GPRRegister reg);
void idiv(Type Ty, const Address &address);
void imul(Type Ty, GPRRegister dst, GPRRegister src);
void imul(Type Ty, GPRRegister reg, const Immediate &imm);
void imul(Type Ty, GPRRegister reg, const Address &address);
void imul(Type Ty, GPRRegister reg);
void imul(Type Ty, const Address &address);
void mul(Type Ty, GPRRegister reg);
void mul(Type Ty, const Address &address);
void incl(GPRRegister reg);
void incl(const Address &address);
void decl(GPRRegister reg);
void decl(const Address &address);
void rol(Type Ty, GPRRegister reg, const Immediate &imm);
void rol(Type Ty, GPRRegister operand, GPRRegister shifter);
void rol(Type Ty, const Address &operand, GPRRegister shifter);
void shl(Type Ty, GPRRegister reg, const Immediate &imm);
void shl(Type Ty, GPRRegister operand, GPRRegister shifter);
void shl(Type Ty, const Address &operand, GPRRegister shifter);
void shr(Type Ty, GPRRegister reg, const Immediate &imm);
void shr(Type Ty, GPRRegister operand, GPRRegister shifter);
void shr(Type Ty, const Address &operand, GPRRegister shifter);
void sar(Type Ty, GPRRegister reg, const Immediate &imm);
void sar(Type Ty, GPRRegister operand, GPRRegister shifter);
void sar(Type Ty, const Address &address, GPRRegister shifter);
void shld(Type Ty, GPRRegister dst, GPRRegister src);
void shld(Type Ty, GPRRegister dst, GPRRegister src, const Immediate &imm);
void shld(Type Ty, const Address &operand, GPRRegister src);
void shrd(Type Ty, GPRRegister dst, GPRRegister src);
void shrd(Type Ty, GPRRegister dst, GPRRegister src, const Immediate &imm);
void shrd(Type Ty, const Address &dst, GPRRegister src);
void neg(Type Ty, GPRRegister reg);
void neg(Type Ty, const Address &addr);
void notl(GPRRegister reg);
void bsf(Type Ty, GPRRegister dst, GPRRegister src);
void bsf(Type Ty, GPRRegister dst, const Address &src);
void bsr(Type Ty, GPRRegister dst, GPRRegister src);
void bsr(Type Ty, GPRRegister dst, const Address &src);
void bswap(Type Ty, GPRRegister reg);
void bt(GPRRegister base, GPRRegister offset);
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();
void hlt();
void ud2();
void j(CondX86::BrCond condition, Label *label, bool near = kFarJump);
void j(CondX86::BrCond condition, const ConstantRelocatable *label);
void jmp(GPRRegister reg);
void jmp(Label *label, bool near = kFarJump);
void jmp(const ConstantRelocatable *label);
void mfence();
void lock();
void cmpxchg(Type Ty, const Address &address, GPRRegister reg, bool Locked);
void cmpxchg8b(const Address &address, bool Locked);
void xadd(Type Ty, const Address &address, GPRRegister reg, bool Locked);
void xchg(Type Ty, const Address &address, GPRRegister reg);
void emitSegmentOverride(uint8_t prefix);
intptr_t preferredLoopAlignment() { return 16; }
void align(intptr_t alignment, intptr_t offset);
void bind(Label *label);
intptr_t CodeSize() const { return Buffer.size(); }
private:
inline void emitUint8(uint8_t value);
inline void emitInt16(int16_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(Type ty, const Immediate &imm);
void emitComplexI8(int rm, const Operand &operand,
const Immediate &immediate);
void emitComplex(Type Ty, 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, Type Ty, GPRRegister reg, const Immediate &imm);
void emitGenericShift(int rm, Type Ty, const Operand &operand,
GPRRegister shifter);
typedef std::vector<Label *> LabelVector;
// A vector of pool-allocated x86 labels for CFG nodes.
LabelVector CfgNodeLabels;
// A vector of pool-allocated x86 labels for Local labels.
LabelVector LocalLabels;
Label *GetOrCreateLabel(SizeT Number, LabelVector &Labels);
// The arith_int() methods factor out the commonality between the encodings of
// add(), Or(), adc(), sbb(), And(), sub(), Xor(), and cmp(). The Tag
// parameter is statically asserted to be less than 8.
template <uint32_t Tag>
void arith_int(Type Ty, GPRRegister reg, const Immediate &imm);
template <uint32_t Tag>
void arith_int(Type Ty, GPRRegister reg0, GPRRegister reg1);
template <uint32_t Tag>
void arith_int(Type Ty, GPRRegister reg, const Address &address);
template <uint32_t Tag>
void arith_int(Type Ty, const Address &address, GPRRegister reg);
template <uint32_t Tag>
void arith_int(Type Ty, const Address &address, const Immediate &imm);
}; };
inline void AssemblerX8632::emitUint8(uint8_t value) {
Buffer.emit<uint8_t>(value);
}
inline void AssemblerX8632::emitInt16(int16_t value) {
Buffer.emit<int16_t>(value);
}
inline void AssemblerX8632::emitInt32(int32_t value) {
Buffer.emit<int32_t>(value);
}
inline void AssemblerX8632::emitRegisterOperand(int rm, int reg) {
assert(rm >= 0 && rm < 8);
Buffer.emit<uint8_t>(0xC0 + (rm << 3) + reg);
}
inline void AssemblerX8632::emitXmmRegisterOperand(int rm, XmmRegister reg) {
emitRegisterOperand(rm, static_cast<GPRRegister>(reg));
}
inline void AssemblerX8632::emitFixup(AssemblerFixup *fixup) {
Buffer.emitFixup(fixup);
}
inline void AssemblerX8632::emitOperandSizeOverride() { emitUint8(0x66); }
} // end of namespace X8632 } // end of namespace X8632
} // end of namespace Ice } // end of namespace Ice
......
//===- subzero/src/IceAssemblerX86Base.h - base x86 assembler -*- C++ -*---===//
//
// 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.
//
//===----------------------------------------------------------------------===//
//
// The Subzero Code Generator
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file defines the AssemblerX86 template class for x86, the base of all
// X86 assemblers.
//
//===----------------------------------------------------------------------===//
#ifndef SUBZERO_SRC_ICEASSEMBLERX86BASE_H
#define SUBZERO_SRC_ICEASSEMBLERX86BASE_H
#include "IceAssembler.h"
#include "IceDefs.h"
#include "IceOperand.h"
#include "IceTypes.h"
#include "IceUtils.h"
namespace Ice {
namespace X86Internal {
template <class Machine> class AssemblerX86Base;
template <class Machine> struct MachineTraits;
constexpr int MAX_NOP_SIZE = 8;
class Immediate {
Immediate(const Immediate &) = delete;
Immediate &operator=(const Immediate &) = delete;
public:
explicit Immediate(int32_t value) : value_(value) {}
Immediate(RelocOffsetT offset, AssemblerFixup *fixup)
: value_(offset), fixup_(fixup) {
// Use the Offset in the "value" for now. If we decide to process fixups,
// we'll need to patch that offset with the true value.
}
int32_t value() const { return value_; }
AssemblerFixup *fixup() const { return fixup_; }
bool is_int8() const {
// We currently only allow 32-bit fixups, and they usually have value = 0,
// so if fixup_ != nullptr, it shouldn't be classified as int8/16.
return fixup_ == nullptr && Utils::IsInt(8, value_);
}
bool is_uint8() const {
return fixup_ == nullptr && Utils::IsUint(8, value_);
}
bool is_uint16() const {
return fixup_ == nullptr && Utils::IsUint(16, value_);
}
private:
const int32_t value_;
AssemblerFixup *fixup_ = nullptr;
};
class Label {
Label(const Label &) = delete;
Label &operator=(const Label &) = delete;
public:
Label() {
if (BuildDefs::asserts()) {
for (int i = 0; i < kMaxUnresolvedBranches; i++) {
unresolved_near_positions_[i] = -1;
}
}
}
~Label() = default;
void FinalCheck() const {
// 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 constexpr int kMaxUnresolvedBranches = 20;
intptr_t position_ = 0;
intptr_t num_unresolved_ = 0;
// TODO(stichnot,jvoung): Can this instead be
// llvm::SmallVector<intptr_t, kMaxUnresolvedBranches> ?
intptr_t unresolved_near_positions_[kMaxUnresolvedBranches];
template <class> friend class AssemblerX86Base;
};
template <class Machine> class AssemblerX86Base : public Assembler {
AssemblerX86Base(const AssemblerX86Base &) = delete;
AssemblerX86Base &operator=(const AssemblerX86Base &) = delete;
protected:
AssemblerX86Base(AssemblerKind Kind, bool use_far_branches)
: Assembler(Kind) {
// This mode is only needed and implemented for MIPS and ARM.
assert(!use_far_branches);
(void)use_far_branches;
}
public:
using Traits = MachineTraits<Machine>;
~AssemblerX86Base() override;
static const bool kNearJump = true;
static const bool kFarJump = false;
void alignFunction() override;
SizeT getBundleAlignLog2Bytes() const override { return 5; }
const char *getNonExecPadDirective() const override { return ".p2align"; }
llvm::ArrayRef<uint8_t> getNonExecBundlePadding() const override {
static const uint8_t Padding[] = {0xF4};
return llvm::ArrayRef<uint8_t>(Padding, 1);
}
void padWithNop(intptr_t Padding) override {
while (Padding > MAX_NOP_SIZE) {
nop(MAX_NOP_SIZE);
Padding -= MAX_NOP_SIZE;
}
if (Padding)
nop(Padding);
}
Label *GetOrCreateCfgNodeLabel(SizeT NodeNumber);
void bindCfgNodeLabel(SizeT NodeNumber) override;
Label *GetOrCreateLocalLabel(SizeT Number);
void BindLocalLabel(SizeT Number);
bool fixupIsPCRel(FixupKind Kind) const override {
// Currently assuming this is the only PC-rel relocation type used.
// TODO(jpp): Traits.PcRelTypes.count(Kind) != 0
return Kind == Traits::PcRelFixup;
}
// Operations to emit GPR instructions (and dispatch on operand type).
typedef void (AssemblerX86Base::*TypedEmitGPR)(Type,
typename Traits::GPRRegister);
typedef void (AssemblerX86Base::*TypedEmitAddr)(
Type, const typename Traits::Address &);
struct GPREmitterOneOp {
TypedEmitGPR Reg;
TypedEmitAddr Addr;
};
typedef void (AssemblerX86Base::*TypedEmitGPRGPR)(
Type, typename Traits::GPRRegister, typename Traits::GPRRegister);
typedef void (AssemblerX86Base::*TypedEmitGPRAddr)(
Type, typename Traits::GPRRegister, const typename Traits::Address &);
typedef void (AssemblerX86Base::*TypedEmitGPRImm)(
Type, typename Traits::GPRRegister, const Immediate &);
struct GPREmitterRegOp {
TypedEmitGPRGPR GPRGPR;
TypedEmitGPRAddr GPRAddr;
TypedEmitGPRImm GPRImm;
};
struct GPREmitterShiftOp {
// Technically, Addr/GPR and Addr/Imm are also allowed, but */Addr are not.
// In practice, we always normalize the Dest to a Register first.
TypedEmitGPRGPR GPRGPR;
TypedEmitGPRImm GPRImm;
};
typedef void (AssemblerX86Base::*TypedEmitGPRGPRImm)(
Type, typename Traits::GPRRegister, typename Traits::GPRRegister,
const Immediate &);
struct GPREmitterShiftD {
// Technically AddrGPR and AddrGPRImm are also allowed, but in practice
// we always normalize Dest to a Register first.
TypedEmitGPRGPR GPRGPR;
TypedEmitGPRGPRImm GPRGPRImm;
};
typedef void (AssemblerX86Base::*TypedEmitAddrGPR)(
Type, const typename Traits::Address &, typename Traits::GPRRegister);
typedef void (AssemblerX86Base::*TypedEmitAddrImm)(
Type, const typename Traits::Address &, const Immediate &);
struct GPREmitterAddrOp {
TypedEmitAddrGPR AddrGPR;
TypedEmitAddrImm AddrImm;
};
// Operations to emit XMM instructions (and dispatch on operand type).
typedef void (AssemblerX86Base::*TypedEmitXmmXmm)(
Type, typename Traits::XmmRegister, typename Traits::XmmRegister);
typedef void (AssemblerX86Base::*TypedEmitXmmAddr)(
Type, typename Traits::XmmRegister, const typename Traits::Address &);
struct XmmEmitterRegOp {
TypedEmitXmmXmm XmmXmm;
TypedEmitXmmAddr XmmAddr;
};
typedef void (AssemblerX86Base::*EmitXmmXmm)(typename Traits::XmmRegister,
typename Traits::XmmRegister);
typedef void (AssemblerX86Base::*EmitXmmAddr)(
typename Traits::XmmRegister, const typename Traits::Address &);
typedef void (AssemblerX86Base::*EmitAddrXmm)(
const typename Traits::Address &, typename Traits::XmmRegister);
struct XmmEmitterMovOps {
EmitXmmXmm XmmXmm;
EmitXmmAddr XmmAddr;
EmitAddrXmm AddrXmm;
};
typedef void (AssemblerX86Base::*TypedEmitXmmImm)(
Type, typename Traits::XmmRegister, const Immediate &);
struct XmmEmitterShiftOp {
TypedEmitXmmXmm XmmXmm;
TypedEmitXmmAddr XmmAddr;
TypedEmitXmmImm XmmImm;
};
// Cross Xmm/GPR cast instructions.
template <typename DReg_t, typename SReg_t> struct CastEmitterRegOp {
typedef void (AssemblerX86Base::*TypedEmitRegs)(Type, DReg_t, SReg_t);
typedef void (AssemblerX86Base::*TypedEmitAddr)(
Type, DReg_t, const typename Traits::Address &);
TypedEmitRegs RegReg;
TypedEmitAddr RegAddr;
};
// Three operand (potentially) cross Xmm/GPR instructions.
// The last operand must be an immediate.
template <typename DReg_t, typename SReg_t> struct ThreeOpImmEmitter {
typedef void (AssemblerX86Base::*TypedEmitRegRegImm)(Type, DReg_t, SReg_t,
const Immediate &);
typedef void (AssemblerX86Base::*TypedEmitRegAddrImm)(
Type, DReg_t, const typename Traits::Address &, const Immediate &);
TypedEmitRegRegImm RegRegImm;
TypedEmitRegAddrImm RegAddrImm;
};
/*
* Emit Machine Instructions.
*/
void call(typename Traits::GPRRegister reg);
void call(const typename Traits::Address &address);
void call(const ConstantRelocatable *label);
void call(const Immediate &abs_address);
static const intptr_t kCallExternalLabelSize = 5;
void pushl(typename Traits::GPRRegister reg);
void popl(typename Traits::GPRRegister reg);
void popl(const typename Traits::Address &address);
void pushal();
void popal();
void setcc(typename Traits::Cond::BrCond condition,
typename Traits::ByteRegister dst);
void setcc(typename Traits::Cond::BrCond condition,
const typename Traits::Address &address);
void mov(Type Ty, typename Traits::GPRRegister dst, const Immediate &src);
void mov(Type Ty, typename Traits::GPRRegister dst,
typename Traits::GPRRegister src);
void mov(Type Ty, typename Traits::GPRRegister dst,
const typename Traits::Address &src);
void mov(Type Ty, const typename Traits::Address &dst,
typename Traits::GPRRegister src);
void mov(Type Ty, const typename Traits::Address &dst, const Immediate &imm);
void movzx(Type Ty, typename Traits::GPRRegister dst,
typename Traits::GPRRegister src);
void movzx(Type Ty, typename Traits::GPRRegister dst,
const typename Traits::Address &src);
void movsx(Type Ty, typename Traits::GPRRegister dst,
typename Traits::GPRRegister src);
void movsx(Type Ty, typename Traits::GPRRegister dst,
const typename Traits::Address &src);
void lea(Type Ty, typename Traits::GPRRegister dst,
const typename Traits::Address &src);
void cmov(Type Ty, typename Traits::Cond::BrCond cond,
typename Traits::GPRRegister dst, typename Traits::GPRRegister src);
void cmov(Type Ty, typename Traits::Cond::BrCond cond,
typename Traits::GPRRegister dst,
const typename Traits::Address &src);
void rep_movsb();
void movss(Type Ty, typename Traits::XmmRegister dst,
const typename Traits::Address &src);
void movss(Type Ty, const typename Traits::Address &dst,
typename Traits::XmmRegister src);
void movss(Type Ty, typename Traits::XmmRegister dst,
typename Traits::XmmRegister src);
void movd(typename Traits::XmmRegister dst, typename Traits::GPRRegister src);
void movd(typename Traits::XmmRegister dst,
const typename Traits::Address &src);
void movd(typename Traits::GPRRegister dst, typename Traits::XmmRegister src);
void movd(const typename Traits::Address &dst,
typename Traits::XmmRegister src);
void movq(typename Traits::XmmRegister dst, typename Traits::XmmRegister src);
void movq(const typename Traits::Address &dst,
typename Traits::XmmRegister src);
void movq(typename Traits::XmmRegister dst,
const typename Traits::Address &src);
void addss(Type Ty, typename Traits::XmmRegister dst,
typename Traits::XmmRegister src);
void addss(Type Ty, typename Traits::XmmRegister dst,
const typename Traits::Address &src);
void subss(Type Ty, typename Traits::XmmRegister dst,
typename Traits::XmmRegister src);
void subss(Type Ty, typename Traits::XmmRegister dst,
const typename Traits::Address &src);
void mulss(Type Ty, typename Traits::XmmRegister dst,
typename Traits::XmmRegister src);
void mulss(Type Ty, typename Traits::XmmRegister dst,
const typename Traits::Address &src);
void divss(Type Ty, typename Traits::XmmRegister dst,
typename Traits::XmmRegister src);
void divss(Type Ty, typename Traits::XmmRegister dst,
const typename Traits::Address &src);
void movaps(typename Traits::XmmRegister dst,
typename Traits::XmmRegister src);
void movups(typename Traits::XmmRegister dst,
typename Traits::XmmRegister src);
void movups(typename Traits::XmmRegister dst,
const typename Traits::Address &src);
void movups(const typename Traits::Address &dst,
typename Traits::XmmRegister src);
void padd(Type Ty, typename Traits::XmmRegister dst,
typename Traits::XmmRegister src);
void padd(Type Ty, typename Traits::XmmRegister dst,
const typename Traits::Address &src);
void pand(Type Ty, typename Traits::XmmRegister dst,
typename Traits::XmmRegister src);
void pand(Type Ty, typename Traits::XmmRegister dst,
const typename Traits::Address &src);
void pandn(Type Ty, typename Traits::XmmRegister dst,
typename Traits::XmmRegister src);
void pandn(Type Ty, typename Traits::XmmRegister dst,
const typename Traits::Address &src);
void pmull(Type Ty, typename Traits::XmmRegister dst,
typename Traits::XmmRegister src);
void pmull(Type Ty, typename Traits::XmmRegister dst,
const typename Traits::Address &src);
void pmuludq(Type Ty, typename Traits::XmmRegister dst,
typename Traits::XmmRegister src);
void pmuludq(Type Ty, typename Traits::XmmRegister dst,
const typename Traits::Address &src);
void por(Type Ty, typename Traits::XmmRegister dst,
typename Traits::XmmRegister src);
void por(Type Ty, typename Traits::XmmRegister dst,
const typename Traits::Address &src);
void psub(Type Ty, typename Traits::XmmRegister dst,
typename Traits::XmmRegister src);
void psub(Type Ty, typename Traits::XmmRegister dst,
const typename Traits::Address &src);
void pxor(Type Ty, typename Traits::XmmRegister dst,
typename Traits::XmmRegister src);
void pxor(Type Ty, typename Traits::XmmRegister dst,
const typename Traits::Address &src);
void psll(Type Ty, typename Traits::XmmRegister dst,
typename Traits::XmmRegister src);
void psll(Type Ty, typename Traits::XmmRegister dst,
const typename Traits::Address &src);
void psll(Type Ty, typename Traits::XmmRegister dst, const Immediate &src);
void psra(Type Ty, typename Traits::XmmRegister dst,
typename Traits::XmmRegister src);
void psra(Type Ty, typename Traits::XmmRegister dst,
const typename Traits::Address &src);
void psra(Type Ty, typename Traits::XmmRegister dst, const Immediate &src);
void psrl(Type Ty, typename Traits::XmmRegister dst,
typename Traits::XmmRegister src);
void psrl(Type Ty, typename Traits::XmmRegister dst,
const typename Traits::Address &src);
void psrl(Type Ty, typename Traits::XmmRegister dst, const Immediate &src);
void addps(Type Ty, typename Traits::XmmRegister dst,
typename Traits::XmmRegister src);
void addps(Type Ty, typename Traits::XmmRegister dst,
const typename Traits::Address &src);
void subps(Type Ty, typename Traits::XmmRegister dst,
typename Traits::XmmRegister src);
void subps(Type Ty, typename Traits::XmmRegister dst,
const typename Traits::Address &src);
void divps(Type Ty, typename Traits::XmmRegister dst,
typename Traits::XmmRegister src);
void divps(Type Ty, typename Traits::XmmRegister dst,
const typename Traits::Address &src);
void mulps(Type Ty, typename Traits::XmmRegister dst,
typename Traits::XmmRegister src);
void mulps(Type Ty, typename Traits::XmmRegister dst,
const typename Traits::Address &src);
void minps(typename Traits::XmmRegister dst,
typename Traits::XmmRegister src);
void maxps(typename Traits::XmmRegister dst,
typename Traits::XmmRegister src);
void andps(typename Traits::XmmRegister dst,
typename Traits::XmmRegister src);
void andps(typename Traits::XmmRegister dst,
const typename Traits::Address &src);
void orps(typename Traits::XmmRegister dst, typename Traits::XmmRegister src);
void blendvps(Type Ty, typename Traits::XmmRegister dst,
typename Traits::XmmRegister src);
void blendvps(Type Ty, typename Traits::XmmRegister dst,
const typename Traits::Address &src);
void pblendvb(Type Ty, typename Traits::XmmRegister dst,
typename Traits::XmmRegister src);
void pblendvb(Type Ty, typename Traits::XmmRegister dst,
const typename Traits::Address &src);
void cmpps(typename Traits::XmmRegister dst, typename Traits::XmmRegister src,
typename Traits::Cond::CmppsCond CmpCondition);
void cmpps(typename Traits::XmmRegister dst,
const typename Traits::Address &src,
typename Traits::Cond::CmppsCond CmpCondition);
void sqrtps(typename Traits::XmmRegister dst);
void rsqrtps(typename Traits::XmmRegister dst);
void reciprocalps(typename Traits::XmmRegister dst);
void movhlps(typename Traits::XmmRegister dst,
typename Traits::XmmRegister src);
void movlhps(typename Traits::XmmRegister dst,
typename Traits::XmmRegister src);
void unpcklps(typename Traits::XmmRegister dst,
typename Traits::XmmRegister src);
void unpckhps(typename Traits::XmmRegister dst,
typename Traits::XmmRegister src);
void unpcklpd(typename Traits::XmmRegister dst,
typename Traits::XmmRegister src);
void unpckhpd(typename Traits::XmmRegister dst,
typename Traits::XmmRegister src);
void set1ps(typename Traits::XmmRegister dst,
typename Traits::GPRRegister tmp, const Immediate &imm);
void shufps(typename Traits::XmmRegister dst,
typename Traits::XmmRegister src, const Immediate &mask);
void minpd(typename Traits::XmmRegister dst,
typename Traits::XmmRegister src);
void maxpd(typename Traits::XmmRegister dst,
typename Traits::XmmRegister src);
void sqrtpd(typename Traits::XmmRegister dst);
void shufpd(typename Traits::XmmRegister dst,
typename Traits::XmmRegister src, const Immediate &mask);
void pshufd(Type Ty, typename Traits::XmmRegister dst,
typename Traits::XmmRegister src, const Immediate &mask);
void pshufd(Type Ty, typename Traits::XmmRegister dst,
const typename Traits::Address &src, const Immediate &mask);
void shufps(Type Ty, typename Traits::XmmRegister dst,
typename Traits::XmmRegister src, const Immediate &mask);
void shufps(Type Ty, typename Traits::XmmRegister dst,
const typename Traits::Address &src, const Immediate &mask);
void cvtdq2ps(Type, typename Traits::XmmRegister dst,
typename Traits::XmmRegister src);
void cvtdq2ps(Type, typename Traits::XmmRegister dst,
const typename Traits::Address &src);
void cvttps2dq(Type, typename Traits::XmmRegister dst,
typename Traits::XmmRegister src);
void cvttps2dq(Type, typename Traits::XmmRegister dst,
const typename Traits::Address &src);
void cvtsi2ss(Type DestTy, typename Traits::XmmRegister dst,
typename Traits::GPRRegister src);
void cvtsi2ss(Type DestTy, typename Traits::XmmRegister dst,
const typename Traits::Address &src);
void cvtfloat2float(Type SrcTy, typename Traits::XmmRegister dst,
typename Traits::XmmRegister src);
void cvtfloat2float(Type SrcTy, typename Traits::XmmRegister dst,
const typename Traits::Address &src);
void cvttss2si(Type SrcTy, typename Traits::GPRRegister dst,
typename Traits::XmmRegister src);
void cvttss2si(Type SrcTy, typename Traits::GPRRegister dst,
const typename Traits::Address &src);
void ucomiss(Type Ty, typename Traits::XmmRegister a,
typename Traits::XmmRegister b);
void ucomiss(Type Ty, typename Traits::XmmRegister a,
const typename Traits::Address &b);
void movmskpd(typename Traits::GPRRegister dst,
typename Traits::XmmRegister src);
void movmskps(typename Traits::GPRRegister dst,
typename Traits::XmmRegister src);
void sqrtss(Type Ty, typename Traits::XmmRegister dst,
const typename Traits::Address &src);
void sqrtss(Type Ty, typename Traits::XmmRegister dst,
typename Traits::XmmRegister src);
void xorpd(typename Traits::XmmRegister dst,
const typename Traits::Address &src);
void xorpd(typename Traits::XmmRegister dst,
typename Traits::XmmRegister src);
void xorps(typename Traits::XmmRegister dst,
const typename Traits::Address &src);
void xorps(typename Traits::XmmRegister dst,
typename Traits::XmmRegister src);
void andpd(typename Traits::XmmRegister dst,
const typename Traits::Address &src);
void andpd(typename Traits::XmmRegister dst,
typename Traits::XmmRegister src);
void orpd(typename Traits::XmmRegister dst, typename Traits::XmmRegister src);
void insertps(Type Ty, typename Traits::XmmRegister dst,
typename Traits::XmmRegister src, const Immediate &imm);
void insertps(Type Ty, typename Traits::XmmRegister dst,
const typename Traits::Address &src, const Immediate &imm);
void pinsr(Type Ty, typename Traits::XmmRegister dst,
typename Traits::GPRRegister src, const Immediate &imm);
void pinsr(Type Ty, typename Traits::XmmRegister dst,
const typename Traits::Address &src, const Immediate &imm);
void pextr(Type Ty, typename Traits::GPRRegister dst,
typename Traits::XmmRegister src, const Immediate &imm);
void pextr(Type Ty, typename Traits::GPRRegister dst,
const typename Traits::Address &src, const Immediate &imm);
void pmovsxdq(typename Traits::XmmRegister dst,
typename Traits::XmmRegister src);
void pcmpeq(Type Ty, typename Traits::XmmRegister dst,
typename Traits::XmmRegister src);
void pcmpeq(Type Ty, typename Traits::XmmRegister dst,
const typename Traits::Address &src);
void pcmpgt(Type Ty, typename Traits::XmmRegister dst,
typename Traits::XmmRegister src);
void pcmpgt(Type Ty, typename Traits::XmmRegister dst,
const typename Traits::Address &src);
enum RoundingMode {
kRoundToNearest = 0x0,
kRoundDown = 0x1,
kRoundUp = 0x2,
kRoundToZero = 0x3
};
void roundsd(typename Traits::XmmRegister dst,
typename Traits::XmmRegister src, RoundingMode mode);
void fld(Type Ty, const typename Traits::Address &src);
void fstp(Type Ty, const typename Traits::Address &dst);
void fstp(typename Traits::X87STRegister st);
void fnstcw(const typename Traits::Address &dst);
void fldcw(const typename Traits::Address &src);
void fistpl(const typename Traits::Address &dst);
void fistps(const typename Traits::Address &dst);
void fildl(const typename Traits::Address &src);
void filds(const typename Traits::Address &src);
void fincstp();
void cmp(Type Ty, typename Traits::GPRRegister reg0,
typename Traits::GPRRegister reg1);
void cmp(Type Ty, typename Traits::GPRRegister reg,
const typename Traits::Address &address);
void cmp(Type Ty, typename Traits::GPRRegister reg, const Immediate &imm);
void cmp(Type Ty, const typename Traits::Address &address,
typename Traits::GPRRegister reg);
void cmp(Type Ty, const typename Traits::Address &address,
const Immediate &imm);
void test(Type Ty, typename Traits::GPRRegister reg0,
typename Traits::GPRRegister reg1);
void test(Type Ty, typename Traits::GPRRegister reg, const Immediate &imm);
void test(Type Ty, const typename Traits::Address &address,
typename Traits::GPRRegister reg);
void test(Type Ty, const typename Traits::Address &address,
const Immediate &imm);
void And(Type Ty, typename Traits::GPRRegister dst,
typename Traits::GPRRegister src);
void And(Type Ty, typename Traits::GPRRegister dst,
const typename Traits::Address &address);
void And(Type Ty, typename Traits::GPRRegister dst, const Immediate &imm);
void And(Type Ty, const typename Traits::Address &address,
typename Traits::GPRRegister reg);
void And(Type Ty, const typename Traits::Address &address,
const Immediate &imm);
void Or(Type Ty, typename Traits::GPRRegister dst,
typename Traits::GPRRegister src);
void Or(Type Ty, typename Traits::GPRRegister dst,
const typename Traits::Address &address);
void Or(Type Ty, typename Traits::GPRRegister dst, const Immediate &imm);
void Or(Type Ty, const typename Traits::Address &address,
typename Traits::GPRRegister reg);
void Or(Type Ty, const typename Traits::Address &address,
const Immediate &imm);
void Xor(Type Ty, typename Traits::GPRRegister dst,
typename Traits::GPRRegister src);
void Xor(Type Ty, typename Traits::GPRRegister dst,
const typename Traits::Address &address);
void Xor(Type Ty, typename Traits::GPRRegister dst, const Immediate &imm);
void Xor(Type Ty, const typename Traits::Address &address,
typename Traits::GPRRegister reg);
void Xor(Type Ty, const typename Traits::Address &address,
const Immediate &imm);
void add(Type Ty, typename Traits::GPRRegister dst,
typename Traits::GPRRegister src);
void add(Type Ty, typename Traits::GPRRegister reg,
const typename Traits::Address &address);
void add(Type Ty, typename Traits::GPRRegister reg, const Immediate &imm);
void add(Type Ty, const typename Traits::Address &address,
typename Traits::GPRRegister reg);
void add(Type Ty, const typename Traits::Address &address,
const Immediate &imm);
void adc(Type Ty, typename Traits::GPRRegister dst,
typename Traits::GPRRegister src);
void adc(Type Ty, typename Traits::GPRRegister dst,
const typename Traits::Address &address);
void adc(Type Ty, typename Traits::GPRRegister reg, const Immediate &imm);
void adc(Type Ty, const typename Traits::Address &address,
typename Traits::GPRRegister reg);
void adc(Type Ty, const typename Traits::Address &address,
const Immediate &imm);
void sub(Type Ty, typename Traits::GPRRegister dst,
typename Traits::GPRRegister src);
void sub(Type Ty, typename Traits::GPRRegister reg,
const typename Traits::Address &address);
void sub(Type Ty, typename Traits::GPRRegister reg, const Immediate &imm);
void sub(Type Ty, const typename Traits::Address &address,
typename Traits::GPRRegister reg);
void sub(Type Ty, const typename Traits::Address &address,
const Immediate &imm);
void sbb(Type Ty, typename Traits::GPRRegister dst,
typename Traits::GPRRegister src);
void sbb(Type Ty, typename Traits::GPRRegister reg,
const typename Traits::Address &address);
void sbb(Type Ty, typename Traits::GPRRegister reg, const Immediate &imm);
void sbb(Type Ty, const typename Traits::Address &address,
typename Traits::GPRRegister reg);
void sbb(Type Ty, const typename Traits::Address &address,
const Immediate &imm);
void cbw();
void cwd();
void cdq();
void div(Type Ty, typename Traits::GPRRegister reg);
void div(Type Ty, const typename Traits::Address &address);
void idiv(Type Ty, typename Traits::GPRRegister reg);
void idiv(Type Ty, const typename Traits::Address &address);
void imul(Type Ty, typename Traits::GPRRegister dst,
typename Traits::GPRRegister src);
void imul(Type Ty, typename Traits::GPRRegister reg, const Immediate &imm);
void imul(Type Ty, typename Traits::GPRRegister reg,
const typename Traits::Address &address);
void imul(Type Ty, typename Traits::GPRRegister reg);
void imul(Type Ty, const typename Traits::Address &address);
void mul(Type Ty, typename Traits::GPRRegister reg);
void mul(Type Ty, const typename Traits::Address &address);
void incl(typename Traits::GPRRegister reg);
void incl(const typename Traits::Address &address);
void decl(typename Traits::GPRRegister reg);
void decl(const typename Traits::Address &address);
void rol(Type Ty, typename Traits::GPRRegister reg, const Immediate &imm);
void rol(Type Ty, typename Traits::GPRRegister operand,
typename Traits::GPRRegister shifter);
void rol(Type Ty, const typename Traits::Address &operand,
typename Traits::GPRRegister shifter);
void shl(Type Ty, typename Traits::GPRRegister reg, const Immediate &imm);
void shl(Type Ty, typename Traits::GPRRegister operand,
typename Traits::GPRRegister shifter);
void shl(Type Ty, const typename Traits::Address &operand,
typename Traits::GPRRegister shifter);
void shr(Type Ty, typename Traits::GPRRegister reg, const Immediate &imm);
void shr(Type Ty, typename Traits::GPRRegister operand,
typename Traits::GPRRegister shifter);
void shr(Type Ty, const typename Traits::Address &operand,
typename Traits::GPRRegister shifter);
void sar(Type Ty, typename Traits::GPRRegister reg, const Immediate &imm);
void sar(Type Ty, typename Traits::GPRRegister operand,
typename Traits::GPRRegister shifter);
void sar(Type Ty, const typename Traits::Address &address,
typename Traits::GPRRegister shifter);
void shld(Type Ty, typename Traits::GPRRegister dst,
typename Traits::GPRRegister src);
void shld(Type Ty, typename Traits::GPRRegister dst,
typename Traits::GPRRegister src, const Immediate &imm);
void shld(Type Ty, const typename Traits::Address &operand,
typename Traits::GPRRegister src);
void shrd(Type Ty, typename Traits::GPRRegister dst,
typename Traits::GPRRegister src);
void shrd(Type Ty, typename Traits::GPRRegister dst,
typename Traits::GPRRegister src, const Immediate &imm);
void shrd(Type Ty, const typename Traits::Address &dst,
typename Traits::GPRRegister src);
void neg(Type Ty, typename Traits::GPRRegister reg);
void neg(Type Ty, const typename Traits::Address &addr);
void notl(typename Traits::GPRRegister reg);
void bsf(Type Ty, typename Traits::GPRRegister dst,
typename Traits::GPRRegister src);
void bsf(Type Ty, typename Traits::GPRRegister dst,
const typename Traits::Address &src);
void bsr(Type Ty, typename Traits::GPRRegister dst,
typename Traits::GPRRegister src);
void bsr(Type Ty, typename Traits::GPRRegister dst,
const typename Traits::Address &src);
void bswap(Type Ty, typename Traits::GPRRegister reg);
void bt(typename Traits::GPRRegister base,
typename Traits::GPRRegister offset);
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();
void hlt();
void ud2();
void j(typename Traits::Cond::BrCond condition, Label *label,
bool near = kFarJump);
void j(typename Traits::Cond::BrCond condition,
const ConstantRelocatable *label);
void jmp(typename Traits::GPRRegister reg);
void jmp(Label *label, bool near = kFarJump);
void jmp(const ConstantRelocatable *label);
void mfence();
void lock();
void cmpxchg(Type Ty, const typename Traits::Address &address,
typename Traits::GPRRegister reg, bool Locked);
void cmpxchg8b(const typename Traits::Address &address, bool Locked);
void xadd(Type Ty, const typename Traits::Address &address,
typename Traits::GPRRegister reg, bool Locked);
void xchg(Type Ty, const typename Traits::Address &address,
typename Traits::GPRRegister reg);
void emitSegmentOverride(uint8_t prefix);
intptr_t preferredLoopAlignment() { return 16; }
void align(intptr_t alignment, intptr_t offset);
void bind(Label *label);
intptr_t CodeSize() const { return Buffer.size(); }
private:
inline void emitUint8(uint8_t value);
inline void emitInt16(int16_t value);
inline void emitInt32(int32_t value);
inline void emitRegisterOperand(int rm, int reg);
inline void emitXmmRegisterOperand(int rm, typename Traits::XmmRegister reg);
inline void emitFixup(AssemblerFixup *fixup);
inline void emitOperandSizeOverride();
void emitOperand(int rm, const typename Traits::Operand &operand);
void emitImmediate(Type ty, const Immediate &imm);
void emitComplexI8(int rm, const typename Traits::Operand &operand,
const Immediate &immediate);
void emitComplex(Type Ty, int rm, const typename Traits::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, Type Ty, typename Traits::GPRRegister reg,
const Immediate &imm);
void emitGenericShift(int rm, Type Ty,
const typename Traits::Operand &operand,
typename Traits::GPRRegister shifter);
typedef std::vector<Label *> LabelVector;
// A vector of pool-allocated x86 labels for CFG nodes.
LabelVector CfgNodeLabels;
// A vector of pool-allocated x86 labels for Local labels.
LabelVector LocalLabels;
Label *GetOrCreateLabel(SizeT Number, LabelVector &Labels);
// The arith_int() methods factor out the commonality between the encodings of
// add(), Or(), adc(), sbb(), And(), sub(), Xor(), and cmp(). The Tag
// parameter is statically asserted to be less than 8.
template <uint32_t Tag>
void arith_int(Type Ty, typename Traits::GPRRegister reg,
const Immediate &imm);
template <uint32_t Tag>
void arith_int(Type Ty, typename Traits::GPRRegister reg0,
typename Traits::GPRRegister reg1);
template <uint32_t Tag>
void arith_int(Type Ty, typename Traits::GPRRegister reg,
const typename Traits::Address &address);
template <uint32_t Tag>
void arith_int(Type Ty, const typename Traits::Address &address,
typename Traits::GPRRegister reg);
template <uint32_t Tag>
void arith_int(Type Ty, const typename Traits::Address &address,
const Immediate &imm);
};
template <class Machine>
inline void AssemblerX86Base<Machine>::emitUint8(uint8_t value) {
Buffer.emit<uint8_t>(value);
}
template <class Machine>
inline void AssemblerX86Base<Machine>::emitInt16(int16_t value) {
Buffer.emit<int16_t>(value);
}
template <class Machine>
inline void AssemblerX86Base<Machine>::emitInt32(int32_t value) {
Buffer.emit<int32_t>(value);
}
template <class Machine>
inline void AssemblerX86Base<Machine>::emitRegisterOperand(int rm, int reg) {
assert(rm >= 0 && rm < 8);
Buffer.emit<uint8_t>(0xC0 + (rm << 3) + reg);
}
template <class Machine>
inline void AssemblerX86Base<Machine>::emitXmmRegisterOperand(
int rm, typename Traits::XmmRegister reg) {
emitRegisterOperand(rm, static_cast<typename Traits::GPRRegister>(reg));
}
template <class Machine>
inline void AssemblerX86Base<Machine>::emitFixup(AssemblerFixup *fixup) {
Buffer.emitFixup(fixup);
}
template <class Machine>
inline void AssemblerX86Base<Machine>::emitOperandSizeOverride() {
emitUint8(0x66);
}
} // end of namespace X86Internal
namespace X8632 {
using Immediate = ::Ice::X86Internal::Immediate;
using Label = ::Ice::X86Internal::Label;
} // end of namespace X8632
} // end of namespace Ice
#include "IceAssemblerX86BaseImpl.h"
#endif // SUBZERO_SRC_ICEASSEMBLERX86BASE_H
This source diff could not be displayed because it is too large. You can view the blob instead.
...@@ -19,28 +19,27 @@ ...@@ -19,28 +19,27 @@
namespace Ice { namespace Ice {
namespace CondX8664 { class CondX8664 {
// An enum of condition codes used for branches and cmov. The enum value // An enum of condition codes used for branches and cmov. The enum value
// should match the value used to encode operands in binary instructions. // should match the value used to encode operands in binary instructions.
enum BrCond { enum BrCond {
#define X(tag, encode, opp, dump, emit) tag encode, #define X(tag, encode, opp, dump, emit) tag encode,
ICEINSTX8664BR_TABLE ICEINSTX8664BR_TABLE
#undef X #undef X
Br_None Br_None
}; };
// An enum of condition codes relevant to the CMPPS instruction. The enum // An enum of condition codes relevant to the CMPPS instruction. The enum
// value should match the value used to encode operands in binary // value should match the value used to encode operands in binary
// instructions. // instructions.
enum CmppsCond { enum CmppsCond {
#define X(tag, emit) tag, #define X(tag, emit) tag,
ICEINSTX8664CMPPS_TABLE ICEINSTX8664CMPPS_TABLE
#undef X #undef X
Cmpps_Invalid Cmpps_Invalid
};
}; };
} // end of namespace CondX8664
} // end of namespace Ice } // end of namespace Ice
#endif // SUBZERO_SRC_ICECONDITIONCODESX8664_H #endif // SUBZERO_SRC_ICECONDITIONCODESX8664_H
...@@ -28,12 +28,12 @@ namespace Ice { ...@@ -28,12 +28,12 @@ namespace Ice {
namespace { namespace {
const struct InstX8632BrAttributes_ { const struct InstX8632BrAttributes_ {
CondX86::BrCond Opposite; X8632::Traits::Cond::BrCond Opposite;
const char *DisplayString; const char *DisplayString;
const char *EmitString; const char *EmitString;
} InstX8632BrAttributes[] = { } InstX8632BrAttributes[] = {
#define X(tag, encode, opp, dump, emit) \ #define X(tag, encode, opp, dump, emit) \
{ CondX86::opp, dump, emit } \ { X8632::Traits::Cond::opp, dump, emit } \
, ,
ICEINSTX8632BR_TABLE ICEINSTX8632BR_TABLE
#undef X #undef X
...@@ -85,7 +85,8 @@ const char *InstX8632::getFldString(Type Ty) { ...@@ -85,7 +85,8 @@ const char *InstX8632::getFldString(Type Ty) {
return TypeX8632Attributes[Ty].FldString; return TypeX8632Attributes[Ty].FldString;
} }
CondX86::BrCond InstX8632::getOppositeCondition(CondX86::BrCond Cond) { X8632::Traits::Cond::BrCond
InstX8632::getOppositeCondition(X8632::Traits::Cond::BrCond Cond) {
return InstX8632BrAttributes[Cond].Opposite; return InstX8632BrAttributes[Cond].Opposite;
} }
...@@ -159,7 +160,8 @@ IceString InstX8632Label::getName(const Cfg *Func) const { ...@@ -159,7 +160,8 @@ IceString InstX8632Label::getName(const Cfg *Func) const {
InstX8632Br::InstX8632Br(Cfg *Func, const CfgNode *TargetTrue, InstX8632Br::InstX8632Br(Cfg *Func, const CfgNode *TargetTrue,
const CfgNode *TargetFalse, const CfgNode *TargetFalse,
const InstX8632Label *Label, CondX86::BrCond Condition) const InstX8632Label *Label,
X8632::Traits::Cond::BrCond Condition)
: InstX8632(Func, InstX8632::Br, 0, nullptr), Condition(Condition), : InstX8632(Func, InstX8632::Br, 0, nullptr), Condition(Condition),
TargetTrue(TargetTrue), TargetFalse(TargetFalse), Label(Label) {} TargetTrue(TargetTrue), TargetFalse(TargetFalse), Label(Label) {}
...@@ -178,7 +180,8 @@ bool InstX8632Br::optimizeBranch(const CfgNode *NextNode) { ...@@ -178,7 +180,8 @@ bool InstX8632Br::optimizeBranch(const CfgNode *NextNode) {
return false; return false;
// Unconditional branch to the next node can be removed. // Unconditional branch to the next node can be removed.
if (Condition == CondX86::Br_None && getTargetFalse() == NextNode) { if (Condition == X8632::Traits::Cond::Br_None &&
getTargetFalse() == NextNode) {
assert(getTargetTrue() == nullptr); assert(getTargetTrue() == nullptr);
setDeleted(); setDeleted();
return true; return true;
...@@ -193,7 +196,7 @@ bool InstX8632Br::optimizeBranch(const CfgNode *NextNode) { ...@@ -193,7 +196,7 @@ bool InstX8632Br::optimizeBranch(const CfgNode *NextNode) {
// (which was already tested above), then invert the branch // (which was already tested above), then invert the branch
// condition, swap the targets, and set new fallthrough to nullptr. // condition, swap the targets, and set new fallthrough to nullptr.
if (getTargetTrue() == NextNode) { if (getTargetTrue() == NextNode) {
assert(Condition != CondX86::Br_None); assert(Condition != X8632::Traits::Cond::Br_None);
Condition = getOppositeCondition(Condition); Condition = getOppositeCondition(Condition);
TargetTrue = getTargetFalse(); TargetTrue = getTargetFalse();
TargetFalse = nullptr; TargetFalse = nullptr;
...@@ -225,7 +228,7 @@ InstX8632Call::InstX8632Call(Cfg *Func, Variable *Dest, Operand *CallTarget) ...@@ -225,7 +228,7 @@ InstX8632Call::InstX8632Call(Cfg *Func, Variable *Dest, Operand *CallTarget)
} }
InstX8632Cmov::InstX8632Cmov(Cfg *Func, Variable *Dest, Operand *Source, InstX8632Cmov::InstX8632Cmov(Cfg *Func, Variable *Dest, Operand *Source,
CondX86::BrCond Condition) X8632::Traits::Cond::BrCond Condition)
: InstX8632(Func, InstX8632::Cmov, 2, Dest), Condition(Condition) { : InstX8632(Func, InstX8632::Cmov, 2, Dest), Condition(Condition) {
// The final result is either the original Dest, or Source, so mark // The final result is either the original Dest, or Source, so mark
// both as sources. // both as sources.
...@@ -234,7 +237,7 @@ InstX8632Cmov::InstX8632Cmov(Cfg *Func, Variable *Dest, Operand *Source, ...@@ -234,7 +237,7 @@ InstX8632Cmov::InstX8632Cmov(Cfg *Func, Variable *Dest, Operand *Source,
} }
InstX8632Cmpps::InstX8632Cmpps(Cfg *Func, Variable *Dest, Operand *Source, InstX8632Cmpps::InstX8632Cmpps(Cfg *Func, Variable *Dest, Operand *Source,
CondX86::CmppsCond Condition) X8632::Traits::Cond::CmppsCond Condition)
: InstX8632(Func, InstX8632::Cmpps, 2, Dest), Condition(Condition) { : InstX8632(Func, InstX8632::Cmpps, 2, Dest), Condition(Condition) {
addSource(Dest); addSource(Dest);
addSource(Source); addSource(Source);
...@@ -352,7 +355,8 @@ InstX8632Ret::InstX8632Ret(Cfg *Func, Variable *Source) ...@@ -352,7 +355,8 @@ InstX8632Ret::InstX8632Ret(Cfg *Func, Variable *Source)
addSource(Source); addSource(Source);
} }
InstX8632Setcc::InstX8632Setcc(Cfg *Func, Variable *Dest, CondX86::BrCond Cond) InstX8632Setcc::InstX8632Setcc(Cfg *Func, Variable *Dest,
X8632::Traits::Cond::BrCond Cond)
: InstX8632(Func, InstX8632::Setcc, 0, Dest), Condition(Cond) {} : InstX8632(Func, InstX8632::Setcc, 0, Dest), Condition(Cond) {}
InstX8632Xadd::InstX8632Xadd(Cfg *Func, Operand *Dest, Variable *Source, InstX8632Xadd::InstX8632Xadd(Cfg *Func, Operand *Dest, Variable *Source,
...@@ -417,7 +421,7 @@ void InstX8632Br::emit(const Cfg *Func) const { ...@@ -417,7 +421,7 @@ void InstX8632Br::emit(const Cfg *Func) const {
Ostream &Str = Func->getContext()->getStrEmit(); Ostream &Str = Func->getContext()->getStrEmit();
Str << "\t"; Str << "\t";
if (Condition == CondX86::Br_None) { if (Condition == X8632::Traits::Cond::Br_None) {
Str << "jmp"; Str << "jmp";
} else { } else {
Str << InstX8632BrAttributes[Condition].EmitString; Str << InstX8632BrAttributes[Condition].EmitString;
...@@ -426,7 +430,7 @@ void InstX8632Br::emit(const Cfg *Func) const { ...@@ -426,7 +430,7 @@ void InstX8632Br::emit(const Cfg *Func) const {
if (Label) { if (Label) {
Str << "\t" << Label->getName(Func); Str << "\t" << Label->getName(Func);
} else { } else {
if (Condition == CondX86::Br_None) { if (Condition == X8632::Traits::Cond::Br_None) {
Str << "\t" << getTargetFalse()->getAsmName(); Str << "\t" << getTargetFalse()->getAsmName();
} else { } else {
Str << "\t" << getTargetTrue()->getAsmName(); Str << "\t" << getTargetTrue()->getAsmName();
...@@ -443,7 +447,7 @@ void InstX8632Br::emitIAS(const Cfg *Func) const { ...@@ -443,7 +447,7 @@ void InstX8632Br::emitIAS(const Cfg *Func) const {
X8632::Label *L = Asm->GetOrCreateLocalLabel(Label->getNumber()); X8632::Label *L = Asm->GetOrCreateLocalLabel(Label->getNumber());
// In all these cases, local Labels should only be used for Near. // In all these cases, local Labels should only be used for Near.
const bool Near = true; const bool Near = true;
if (Condition == CondX86::Br_None) { if (Condition == X8632::Traits::Cond::Br_None) {
Asm->jmp(L, Near); Asm->jmp(L, Near);
} else { } else {
Asm->j(Condition, L, Near); Asm->j(Condition, L, Near);
...@@ -452,7 +456,7 @@ void InstX8632Br::emitIAS(const Cfg *Func) const { ...@@ -452,7 +456,7 @@ void InstX8632Br::emitIAS(const Cfg *Func) const {
// Pessimistically assume it's far. This only affects Labels that // Pessimistically assume it's far. This only affects Labels that
// are not Bound. // are not Bound.
const bool Near = false; const bool Near = false;
if (Condition == CondX86::Br_None) { if (Condition == X8632::Traits::Cond::Br_None) {
X8632::Label *L = X8632::Label *L =
Asm->GetOrCreateCfgNodeLabel(getTargetFalse()->getIndex()); Asm->GetOrCreateCfgNodeLabel(getTargetFalse()->getIndex());
assert(!getTargetTrue()); assert(!getTargetTrue());
...@@ -476,7 +480,7 @@ void InstX8632Br::dump(const Cfg *Func) const { ...@@ -476,7 +480,7 @@ void InstX8632Br::dump(const Cfg *Func) const {
Ostream &Str = Func->getContext()->getStrDump(); Ostream &Str = Func->getContext()->getStrDump();
Str << "br "; Str << "br ";
if (Condition == CondX86::Br_None) { if (Condition == X8632::Traits::Cond::Br_None) {
Str << "label %" Str << "label %"
<< (Label ? Label->getName(Func) : getTargetFalse()->getName()); << (Label ? Label->getName(Func) : getTargetFalse()->getName());
return; return;
...@@ -636,8 +640,9 @@ void emitIASOpTyGPR(const Cfg *Func, Type Ty, const Operand *Op, ...@@ -636,8 +640,9 @@ void emitIASOpTyGPR(const Cfg *Func, Type Ty, const Operand *Op,
RegX8632::getEncodedByteRegOrGPR(Ty, Var->getRegNum()); RegX8632::getEncodedByteRegOrGPR(Ty, Var->getRegNum());
(Asm->*(Emitter.Reg))(Ty, VarReg); (Asm->*(Emitter.Reg))(Ty, VarReg);
} else { } else {
X8632::Address StackAddr(static_cast<TargetX8632 *>(Func->getTarget()) X8632::Traits::Address StackAddr(
->stackVarToAsmOperand(Var)); static_cast<TargetX8632 *>(Func->getTarget())
->stackVarToAsmOperand(Var));
(Asm->*(Emitter.Addr))(Ty, StackAddr); (Asm->*(Emitter.Addr))(Ty, StackAddr);
} }
} else if (const auto Mem = llvm::dyn_cast<OperandX8632Mem>(Op)) { } else if (const auto Mem = llvm::dyn_cast<OperandX8632Mem>(Op)) {
...@@ -666,7 +671,7 @@ void emitIASRegOpTyGPR(const Cfg *Func, Type Ty, const Variable *Var, ...@@ -666,7 +671,7 @@ void emitIASRegOpTyGPR(const Cfg *Func, Type Ty, const Variable *Var,
: RegX8632::getEncodedGPR(SrcVar->getRegNum()); : RegX8632::getEncodedGPR(SrcVar->getRegNum());
(Asm->*(Emitter.GPRGPR))(Ty, VarReg, SrcReg); (Asm->*(Emitter.GPRGPR))(Ty, VarReg, SrcReg);
} else { } else {
X8632::Address SrcStackAddr = X8632::Traits::Address SrcStackAddr =
static_cast<TargetX8632 *>(Func->getTarget()) static_cast<TargetX8632 *>(Func->getTarget())
->stackVarToAsmOperand(SrcVar); ->stackVarToAsmOperand(SrcVar);
(Asm->*(Emitter.GPRAddr))(Ty, VarReg, SrcStackAddr); (Asm->*(Emitter.GPRAddr))(Ty, VarReg, SrcStackAddr);
...@@ -688,7 +693,8 @@ void emitIASRegOpTyGPR(const Cfg *Func, Type Ty, const Variable *Var, ...@@ -688,7 +693,8 @@ void emitIASRegOpTyGPR(const Cfg *Func, Type Ty, const Variable *Var,
} }
void emitIASAddrOpTyGPR( void emitIASAddrOpTyGPR(
const Cfg *Func, Type Ty, const X8632::Address &Addr, const Operand *Src, const Cfg *Func, Type Ty, const X8632::Traits::Address &Addr,
const Operand *Src,
const X8632::AssemblerX8632::GPREmitterAddrOp &Emitter) { const X8632::AssemblerX8632::GPREmitterAddrOp &Emitter) {
X8632::AssemblerX8632 *Asm = Func->getAssembler<X8632::AssemblerX8632>(); X8632::AssemblerX8632 *Asm = Func->getAssembler<X8632::AssemblerX8632>();
// Src can only be Reg or Immediate. // Src can only be Reg or Immediate.
...@@ -713,8 +719,9 @@ void emitIASAsAddrOpTyGPR( ...@@ -713,8 +719,9 @@ void emitIASAsAddrOpTyGPR(
const X8632::AssemblerX8632::GPREmitterAddrOp &Emitter) { const X8632::AssemblerX8632::GPREmitterAddrOp &Emitter) {
if (const auto Op0Var = llvm::dyn_cast<Variable>(Op0)) { if (const auto Op0Var = llvm::dyn_cast<Variable>(Op0)) {
assert(!Op0Var->hasReg()); assert(!Op0Var->hasReg());
X8632::Address StackAddr(static_cast<TargetX8632 *>(Func->getTarget()) X8632::Traits::Address StackAddr(
->stackVarToAsmOperand(Op0Var)); static_cast<TargetX8632 *>(Func->getTarget())
->stackVarToAsmOperand(Op0Var));
emitIASAddrOpTyGPR(Func, Ty, StackAddr, Op1, Emitter); emitIASAddrOpTyGPR(Func, Ty, StackAddr, Op1, Emitter);
} else if (const auto Op0Mem = llvm::dyn_cast<OperandX8632Mem>(Op0)) { } else if (const auto Op0Mem = llvm::dyn_cast<OperandX8632Mem>(Op0)) {
X8632::AssemblerX8632 *Asm = Func->getAssembler<X8632::AssemblerX8632>(); X8632::AssemblerX8632 *Asm = Func->getAssembler<X8632::AssemblerX8632>();
...@@ -786,7 +793,7 @@ void emitIASXmmShift(const Cfg *Func, Type Ty, const Variable *Var, ...@@ -786,7 +793,7 @@ void emitIASXmmShift(const Cfg *Func, Type Ty, const Variable *Var,
RegX8632::getEncodedXmm(SrcVar->getRegNum()); RegX8632::getEncodedXmm(SrcVar->getRegNum());
(Asm->*(Emitter.XmmXmm))(Ty, VarReg, SrcReg); (Asm->*(Emitter.XmmXmm))(Ty, VarReg, SrcReg);
} else { } else {
X8632::Address SrcStackAddr = X8632::Traits::Address SrcStackAddr =
static_cast<TargetX8632 *>(Func->getTarget()) static_cast<TargetX8632 *>(Func->getTarget())
->stackVarToAsmOperand(SrcVar); ->stackVarToAsmOperand(SrcVar);
(Asm->*(Emitter.XmmAddr))(Ty, VarReg, SrcStackAddr); (Asm->*(Emitter.XmmAddr))(Ty, VarReg, SrcStackAddr);
...@@ -813,7 +820,7 @@ void emitIASRegOpTyXMM(const Cfg *Func, Type Ty, const Variable *Var, ...@@ -813,7 +820,7 @@ void emitIASRegOpTyXMM(const Cfg *Func, Type Ty, const Variable *Var,
RegX8632::getEncodedXmm(SrcVar->getRegNum()); RegX8632::getEncodedXmm(SrcVar->getRegNum());
(Asm->*(Emitter.XmmXmm))(Ty, VarReg, SrcReg); (Asm->*(Emitter.XmmXmm))(Ty, VarReg, SrcReg);
} else { } else {
X8632::Address SrcStackAddr = X8632::Traits::Address SrcStackAddr =
static_cast<TargetX8632 *>(Func->getTarget()) static_cast<TargetX8632 *>(Func->getTarget())
->stackVarToAsmOperand(SrcVar); ->stackVarToAsmOperand(SrcVar);
(Asm->*(Emitter.XmmAddr))(Ty, VarReg, SrcStackAddr); (Asm->*(Emitter.XmmAddr))(Ty, VarReg, SrcStackAddr);
...@@ -823,7 +830,7 @@ void emitIASRegOpTyXMM(const Cfg *Func, Type Ty, const Variable *Var, ...@@ -823,7 +830,7 @@ void emitIASRegOpTyXMM(const Cfg *Func, Type Ty, const Variable *Var,
(Asm->*(Emitter.XmmAddr))(Ty, VarReg, Mem->toAsmAddress(Asm)); (Asm->*(Emitter.XmmAddr))(Ty, VarReg, Mem->toAsmAddress(Asm));
} else if (const auto Imm = llvm::dyn_cast<Constant>(Src)) { } else if (const auto Imm = llvm::dyn_cast<Constant>(Src)) {
(Asm->*(Emitter.XmmAddr))(Ty, VarReg, (Asm->*(Emitter.XmmAddr))(Ty, VarReg,
X8632::Address::ofConstPool(Asm, Imm)); X8632::Traits::Address::ofConstPool(Asm, Imm));
} else { } else {
llvm_unreachable("Unexpected operand type"); llvm_unreachable("Unexpected operand type");
} }
...@@ -842,7 +849,7 @@ void emitIASCastRegOp( ...@@ -842,7 +849,7 @@ void emitIASCastRegOp(
SReg_t SrcReg = srcEnc(SrcVar->getRegNum()); SReg_t SrcReg = srcEnc(SrcVar->getRegNum());
(Asm->*(Emitter.RegReg))(DispatchTy, DestReg, SrcReg); (Asm->*(Emitter.RegReg))(DispatchTy, DestReg, SrcReg);
} else { } else {
X8632::Address SrcStackAddr = X8632::Traits::Address SrcStackAddr =
static_cast<TargetX8632 *>(Func->getTarget()) static_cast<TargetX8632 *>(Func->getTarget())
->stackVarToAsmOperand(SrcVar); ->stackVarToAsmOperand(SrcVar);
(Asm->*(Emitter.RegAddr))(DispatchTy, DestReg, SrcStackAddr); (Asm->*(Emitter.RegAddr))(DispatchTy, DestReg, SrcStackAddr);
...@@ -871,7 +878,7 @@ void emitIASThreeOpImmOps( ...@@ -871,7 +878,7 @@ void emitIASThreeOpImmOps(
SReg_t SrcReg = srcEnc(SrcVar->getRegNum()); SReg_t SrcReg = srcEnc(SrcVar->getRegNum());
(Asm->*(Emitter.RegRegImm))(DispatchTy, DestReg, SrcReg, Imm); (Asm->*(Emitter.RegRegImm))(DispatchTy, DestReg, SrcReg, Imm);
} else { } else {
X8632::Address SrcStackAddr = X8632::Traits::Address SrcStackAddr =
static_cast<TargetX8632 *>(Func->getTarget()) static_cast<TargetX8632 *>(Func->getTarget())
->stackVarToAsmOperand(SrcVar); ->stackVarToAsmOperand(SrcVar);
(Asm->*(Emitter.RegAddrImm))(DispatchTy, DestReg, SrcStackAddr, Imm); (Asm->*(Emitter.RegAddrImm))(DispatchTy, DestReg, SrcStackAddr, Imm);
...@@ -896,8 +903,9 @@ void emitIASMovlikeXMM(const Cfg *Func, const Variable *Dest, ...@@ -896,8 +903,9 @@ void emitIASMovlikeXMM(const Cfg *Func, const Variable *Dest,
(Asm->*(Emitter.XmmXmm))(DestReg, (Asm->*(Emitter.XmmXmm))(DestReg,
RegX8632::getEncodedXmm(SrcVar->getRegNum())); RegX8632::getEncodedXmm(SrcVar->getRegNum()));
} else { } else {
X8632::Address StackAddr(static_cast<TargetX8632 *>(Func->getTarget()) X8632::Traits::Address StackAddr(
->stackVarToAsmOperand(SrcVar)); static_cast<TargetX8632 *>(Func->getTarget())
->stackVarToAsmOperand(SrcVar));
(Asm->*(Emitter.XmmAddr))(DestReg, StackAddr); (Asm->*(Emitter.XmmAddr))(DestReg, StackAddr);
} }
} else if (const auto SrcMem = llvm::dyn_cast<OperandX8632Mem>(Src)) { } else if (const auto SrcMem = llvm::dyn_cast<OperandX8632Mem>(Src)) {
...@@ -907,8 +915,9 @@ void emitIASMovlikeXMM(const Cfg *Func, const Variable *Dest, ...@@ -907,8 +915,9 @@ void emitIASMovlikeXMM(const Cfg *Func, const Variable *Dest,
llvm_unreachable("Unexpected operand type"); llvm_unreachable("Unexpected operand type");
} }
} else { } else {
X8632::Address StackAddr(static_cast<TargetX8632 *>(Func->getTarget()) X8632::Traits::Address StackAddr(
->stackVarToAsmOperand(Dest)); static_cast<TargetX8632 *>(Func->getTarget())
->stackVarToAsmOperand(Dest));
// Src must be a register in this case. // Src must be a register in this case.
const auto SrcVar = llvm::cast<Variable>(Src); const auto SrcVar = llvm::cast<Variable>(Src);
assert(SrcVar->hasReg()); assert(SrcVar->hasReg());
...@@ -1194,7 +1203,7 @@ template <> void InstX8632Pmull::emit(const Cfg *Func) const { ...@@ -1194,7 +1203,7 @@ template <> void InstX8632Pmull::emit(const Cfg *Func) const {
bool InstructionSetIsValid = bool InstructionSetIsValid =
getDest()->getType() == IceType_v8i16 || getDest()->getType() == IceType_v8i16 ||
static_cast<TargetX8632 *>(Func->getTarget())->getInstructionSet() >= static_cast<TargetX8632 *>(Func->getTarget())->getInstructionSet() >=
TargetX8632::SSE4_1; X8632::Traits::SSE4_1;
(void)TypesAreValid; (void)TypesAreValid;
(void)InstructionSetIsValid; (void)InstructionSetIsValid;
assert(TypesAreValid); assert(TypesAreValid);
...@@ -1210,7 +1219,7 @@ template <> void InstX8632Pmull::emitIAS(const Cfg *Func) const { ...@@ -1210,7 +1219,7 @@ template <> void InstX8632Pmull::emitIAS(const Cfg *Func) const {
bool InstructionSetIsValid = bool InstructionSetIsValid =
Ty == IceType_v8i16 || Ty == IceType_v8i16 ||
static_cast<TargetX8632 *>(Func->getTarget())->getInstructionSet() >= static_cast<TargetX8632 *>(Func->getTarget())->getInstructionSet() >=
TargetX8632::SSE4_1; X8632::Traits::SSE4_1;
(void)TypesAreValid; (void)TypesAreValid;
(void)InstructionSetIsValid; (void)InstructionSetIsValid;
assert(TypesAreValid); assert(TypesAreValid);
...@@ -1336,13 +1345,13 @@ template <> void InstX8632Blendvps::emit(const Cfg *Func) const { ...@@ -1336,13 +1345,13 @@ template <> void InstX8632Blendvps::emit(const Cfg *Func) const {
if (!BuildDefs::dump()) if (!BuildDefs::dump())
return; return;
assert(static_cast<TargetX8632 *>(Func->getTarget())->getInstructionSet() >= assert(static_cast<TargetX8632 *>(Func->getTarget())->getInstructionSet() >=
TargetX8632::SSE4_1); X8632::Traits::SSE4_1);
emitVariableBlendInst(Opcode, this, Func); emitVariableBlendInst(Opcode, this, Func);
} }
template <> void InstX8632Blendvps::emitIAS(const Cfg *Func) const { template <> void InstX8632Blendvps::emitIAS(const Cfg *Func) const {
assert(static_cast<TargetX8632 *>(Func->getTarget())->getInstructionSet() >= assert(static_cast<TargetX8632 *>(Func->getTarget())->getInstructionSet() >=
TargetX8632::SSE4_1); X8632::Traits::SSE4_1);
static const X8632::AssemblerX8632::XmmEmitterRegOp Emitter = { static const X8632::AssemblerX8632::XmmEmitterRegOp Emitter = {
&X8632::AssemblerX8632::blendvps, &X8632::AssemblerX8632::blendvps}; &X8632::AssemblerX8632::blendvps, &X8632::AssemblerX8632::blendvps};
emitIASVariableBlendInst(this, Func, Emitter); emitIASVariableBlendInst(this, Func, Emitter);
...@@ -1352,13 +1361,13 @@ template <> void InstX8632Pblendvb::emit(const Cfg *Func) const { ...@@ -1352,13 +1361,13 @@ template <> void InstX8632Pblendvb::emit(const Cfg *Func) const {
if (!BuildDefs::dump()) if (!BuildDefs::dump())
return; return;
assert(static_cast<TargetX8632 *>(Func->getTarget())->getInstructionSet() >= assert(static_cast<TargetX8632 *>(Func->getTarget())->getInstructionSet() >=
TargetX8632::SSE4_1); X8632::Traits::SSE4_1);
emitVariableBlendInst(Opcode, this, Func); emitVariableBlendInst(Opcode, this, Func);
} }
template <> void InstX8632Pblendvb::emitIAS(const Cfg *Func) const { template <> void InstX8632Pblendvb::emitIAS(const Cfg *Func) const {
assert(static_cast<TargetX8632 *>(Func->getTarget())->getInstructionSet() >= assert(static_cast<TargetX8632 *>(Func->getTarget())->getInstructionSet() >=
TargetX8632::SSE4_1); X8632::Traits::SSE4_1);
static const X8632::AssemblerX8632::XmmEmitterRegOp Emitter = { static const X8632::AssemblerX8632::XmmEmitterRegOp Emitter = {
&X8632::AssemblerX8632::pblendvb, &X8632::AssemblerX8632::pblendvb}; &X8632::AssemblerX8632::pblendvb, &X8632::AssemblerX8632::pblendvb};
emitIASVariableBlendInst(this, Func, Emitter); emitIASVariableBlendInst(this, Func, Emitter);
...@@ -1416,7 +1425,7 @@ template <> void InstX8632Imul::emitIAS(const Cfg *Func) const { ...@@ -1416,7 +1425,7 @@ template <> void InstX8632Imul::emitIAS(const Cfg *Func) const {
template <> void InstX8632Insertps::emitIAS(const Cfg *Func) const { template <> void InstX8632Insertps::emitIAS(const Cfg *Func) const {
assert(getSrcSize() == 3); assert(getSrcSize() == 3);
assert(static_cast<TargetX8632 *>(Func->getTarget())->getInstructionSet() >= assert(static_cast<TargetX8632 *>(Func->getTarget())->getInstructionSet() >=
TargetX8632::SSE4_1); X8632::Traits::SSE4_1);
const Variable *Dest = getDest(); const Variable *Dest = getDest();
assert(Dest == getSrc(0)); assert(Dest == getSrc(0));
Type Ty = Dest->getType(); Type Ty = Dest->getType();
...@@ -1601,7 +1610,7 @@ void InstX8632Cmov::emit(const Cfg *Func) const { ...@@ -1601,7 +1610,7 @@ void InstX8632Cmov::emit(const Cfg *Func) const {
Ostream &Str = Func->getContext()->getStrEmit(); Ostream &Str = Func->getContext()->getStrEmit();
Variable *Dest = getDest(); Variable *Dest = getDest();
Str << "\t"; Str << "\t";
assert(Condition != CondX86::Br_None); assert(Condition != X8632::Traits::Cond::Br_None);
assert(getDest()->hasReg()); assert(getDest()->hasReg());
Str << "cmov" << InstX8632BrAttributes[Condition].DisplayString Str << "cmov" << InstX8632BrAttributes[Condition].DisplayString
<< getWidthString(Dest->getType()) << "\t"; << getWidthString(Dest->getType()) << "\t";
...@@ -1611,7 +1620,7 @@ void InstX8632Cmov::emit(const Cfg *Func) const { ...@@ -1611,7 +1620,7 @@ void InstX8632Cmov::emit(const Cfg *Func) const {
} }
void InstX8632Cmov::emitIAS(const Cfg *Func) const { void InstX8632Cmov::emitIAS(const Cfg *Func) const {
assert(Condition != CondX86::Br_None); assert(Condition != X8632::Traits::Cond::Br_None);
assert(getDest()->hasReg()); assert(getDest()->hasReg());
assert(getSrcSize() == 2); assert(getSrcSize() == 2);
Operand *Src = getSrc(1); Operand *Src = getSrc(1);
...@@ -1654,7 +1663,7 @@ void InstX8632Cmpps::emit(const Cfg *Func) const { ...@@ -1654,7 +1663,7 @@ void InstX8632Cmpps::emit(const Cfg *Func) const {
return; return;
Ostream &Str = Func->getContext()->getStrEmit(); Ostream &Str = Func->getContext()->getStrEmit();
assert(getSrcSize() == 2); assert(getSrcSize() == 2);
assert(Condition < CondX86::Cmpps_Invalid); assert(Condition < X8632::Traits::Cond::Cmpps_Invalid);
Str << "\t"; Str << "\t";
Str << "cmp" << InstX8632CmppsAttributes[Condition].EmitString << "ps" Str << "cmp" << InstX8632CmppsAttributes[Condition].EmitString << "ps"
<< "\t"; << "\t";
...@@ -1666,7 +1675,7 @@ void InstX8632Cmpps::emit(const Cfg *Func) const { ...@@ -1666,7 +1675,7 @@ void InstX8632Cmpps::emit(const Cfg *Func) const {
void InstX8632Cmpps::emitIAS(const Cfg *Func) const { void InstX8632Cmpps::emitIAS(const Cfg *Func) const {
X8632::AssemblerX8632 *Asm = Func->getAssembler<X8632::AssemblerX8632>(); X8632::AssemblerX8632 *Asm = Func->getAssembler<X8632::AssemblerX8632>();
assert(getSrcSize() == 2); assert(getSrcSize() == 2);
assert(Condition < CondX86::Cmpps_Invalid); assert(Condition < X8632::Traits::Cond::Cmpps_Invalid);
// Assuming there isn't any load folding for cmpps, and vector constants // Assuming there isn't any load folding for cmpps, and vector constants
// are not allowed in PNaCl. // are not allowed in PNaCl.
assert(llvm::isa<Variable>(getSrc(1))); assert(llvm::isa<Variable>(getSrc(1)));
...@@ -1675,8 +1684,9 @@ void InstX8632Cmpps::emitIAS(const Cfg *Func) const { ...@@ -1675,8 +1684,9 @@ void InstX8632Cmpps::emitIAS(const Cfg *Func) const {
Asm->cmpps(RegX8632::getEncodedXmm(getDest()->getRegNum()), Asm->cmpps(RegX8632::getEncodedXmm(getDest()->getRegNum()),
RegX8632::getEncodedXmm(SrcVar->getRegNum()), Condition); RegX8632::getEncodedXmm(SrcVar->getRegNum()), Condition);
} else { } else {
X8632::Address SrcStackAddr = static_cast<TargetX8632 *>(Func->getTarget()) X8632::Traits::Address SrcStackAddr =
->stackVarToAsmOperand(SrcVar); static_cast<TargetX8632 *>(Func->getTarget())
->stackVarToAsmOperand(SrcVar);
Asm->cmpps(RegX8632::getEncodedXmm(getDest()->getRegNum()), SrcStackAddr, Asm->cmpps(RegX8632::getEncodedXmm(getDest()->getRegNum()), SrcStackAddr,
Condition); Condition);
} }
...@@ -1686,7 +1696,7 @@ void InstX8632Cmpps::dump(const Cfg *Func) const { ...@@ -1686,7 +1696,7 @@ void InstX8632Cmpps::dump(const Cfg *Func) const {
if (!BuildDefs::dump()) if (!BuildDefs::dump())
return; return;
Ostream &Str = Func->getContext()->getStrDump(); Ostream &Str = Func->getContext()->getStrDump();
assert(Condition < CondX86::Cmpps_Invalid); assert(Condition < X8632::Traits::Cond::Cmpps_Invalid);
dumpDest(Func); dumpDest(Func);
Str << " = cmp" << InstX8632CmppsAttributes[Condition].EmitString << "ps" Str << " = cmp" << InstX8632CmppsAttributes[Condition].EmitString << "ps"
<< "\t"; << "\t";
...@@ -1713,7 +1723,7 @@ void InstX8632Cmpxchg::emitIAS(const Cfg *Func) const { ...@@ -1713,7 +1723,7 @@ void InstX8632Cmpxchg::emitIAS(const Cfg *Func) const {
Type Ty = getSrc(0)->getType(); Type Ty = getSrc(0)->getType();
const auto Mem = llvm::cast<OperandX8632Mem>(getSrc(0)); const auto Mem = llvm::cast<OperandX8632Mem>(getSrc(0));
assert(Mem->getSegmentRegister() == OperandX8632Mem::DefaultSegment); assert(Mem->getSegmentRegister() == OperandX8632Mem::DefaultSegment);
const X8632::Address Addr = Mem->toAsmAddress(Asm); const X8632::Traits::Address Addr = Mem->toAsmAddress(Asm);
const auto VarReg = llvm::cast<Variable>(getSrc(2)); const auto VarReg = llvm::cast<Variable>(getSrc(2));
assert(VarReg->hasReg()); assert(VarReg->hasReg());
const RegX8632::GPRRegister Reg = const RegX8632::GPRRegister Reg =
...@@ -1749,7 +1759,7 @@ void InstX8632Cmpxchg8b::emitIAS(const Cfg *Func) const { ...@@ -1749,7 +1759,7 @@ void InstX8632Cmpxchg8b::emitIAS(const Cfg *Func) const {
X8632::AssemblerX8632 *Asm = Func->getAssembler<X8632::AssemblerX8632>(); X8632::AssemblerX8632 *Asm = Func->getAssembler<X8632::AssemblerX8632>();
const auto Mem = llvm::cast<OperandX8632Mem>(getSrc(0)); const auto Mem = llvm::cast<OperandX8632Mem>(getSrc(0));
assert(Mem->getSegmentRegister() == OperandX8632Mem::DefaultSegment); assert(Mem->getSegmentRegister() == OperandX8632Mem::DefaultSegment);
const X8632::Address Addr = Mem->toAsmAddress(Asm); const X8632::Traits::Address Addr = Mem->toAsmAddress(Asm);
Asm->cmpxchg8b(Addr, Locked); Asm->cmpxchg8b(Addr, Locked);
} }
...@@ -2027,8 +2037,9 @@ void InstX8632Store::emitIAS(const Cfg *Func) const { ...@@ -2027,8 +2037,9 @@ void InstX8632Store::emitIAS(const Cfg *Func) const {
X8632::AssemblerX8632 *Asm = Func->getAssembler<X8632::AssemblerX8632>(); X8632::AssemblerX8632 *Asm = Func->getAssembler<X8632::AssemblerX8632>();
if (const auto DestVar = llvm::dyn_cast<Variable>(Dest)) { if (const auto DestVar = llvm::dyn_cast<Variable>(Dest)) {
assert(!DestVar->hasReg()); assert(!DestVar->hasReg());
X8632::Address StackAddr(static_cast<TargetX8632 *>(Func->getTarget()) X8632::Traits::Address StackAddr(
->stackVarToAsmOperand(DestVar)); static_cast<TargetX8632 *>(Func->getTarget())
->stackVarToAsmOperand(DestVar));
Asm->movss(DestTy, StackAddr, SrcReg); Asm->movss(DestTy, StackAddr, SrcReg);
} else { } else {
const auto DestMem = llvm::cast<OperandX8632Mem>(Dest); const auto DestMem = llvm::cast<OperandX8632Mem>(Dest);
...@@ -2217,8 +2228,9 @@ template <> void InstX8632Mov::emitIAS(const Cfg *Func) const { ...@@ -2217,8 +2228,9 @@ template <> void InstX8632Mov::emitIAS(const Cfg *Func) const {
} else { } else {
// Dest must be Stack and Src *could* be a register. Use Src's type // Dest must be Stack and Src *could* be a register. Use Src's type
// to decide on the emitters. // to decide on the emitters.
X8632::Address StackAddr(static_cast<TargetX8632 *>(Func->getTarget()) X8632::Traits::Address StackAddr(
->stackVarToAsmOperand(Dest)); static_cast<TargetX8632 *>(Func->getTarget())
->stackVarToAsmOperand(Dest));
if (isScalarFloatingType(SrcTy)) { if (isScalarFloatingType(SrcTy)) {
// Src must be a register. // Src must be a register.
const auto SrcVar = llvm::cast<Variable>(Src); const auto SrcVar = llvm::cast<Variable>(Src);
...@@ -2251,8 +2263,9 @@ template <> void InstX8632Movd::emitIAS(const Cfg *Func) const { ...@@ -2251,8 +2263,9 @@ template <> void InstX8632Movd::emitIAS(const Cfg *Func) const {
if (SrcVar->hasReg()) { if (SrcVar->hasReg()) {
Asm->movd(DestReg, RegX8632::getEncodedGPR(SrcVar->getRegNum())); Asm->movd(DestReg, RegX8632::getEncodedGPR(SrcVar->getRegNum()));
} else { } else {
X8632::Address StackAddr(static_cast<TargetX8632 *>(Func->getTarget()) X8632::Traits::Address StackAddr(
->stackVarToAsmOperand(SrcVar)); static_cast<TargetX8632 *>(Func->getTarget())
->stackVarToAsmOperand(SrcVar));
Asm->movd(DestReg, StackAddr); Asm->movd(DestReg, StackAddr);
} }
} else { } else {
...@@ -2263,8 +2276,9 @@ template <> void InstX8632Movd::emitIAS(const Cfg *Func) const { ...@@ -2263,8 +2276,9 @@ template <> void InstX8632Movd::emitIAS(const Cfg *Func) const {
if (Dest->hasReg()) { if (Dest->hasReg()) {
Asm->movd(RegX8632::getEncodedGPR(Dest->getRegNum()), SrcReg); Asm->movd(RegX8632::getEncodedGPR(Dest->getRegNum()), SrcReg);
} else { } else {
X8632::Address StackAddr(static_cast<TargetX8632 *>(Func->getTarget()) X8632::Traits::Address StackAddr(
->stackVarToAsmOperand(Dest)); static_cast<TargetX8632 *>(Func->getTarget())
->stackVarToAsmOperand(Dest));
Asm->movd(StackAddr, SrcReg); Asm->movd(StackAddr, SrcReg);
} }
} }
...@@ -2414,20 +2428,22 @@ void InstX8632Fld::emitIAS(const Cfg *Func) const { ...@@ -2414,20 +2428,22 @@ void InstX8632Fld::emitIAS(const Cfg *Func) const {
// temporary stack slot. // temporary stack slot.
X8632::Immediate Width(typeWidthInBytes(Ty)); X8632::Immediate Width(typeWidthInBytes(Ty));
Asm->sub(IceType_i32, RegX8632::Encoded_Reg_esp, Width); Asm->sub(IceType_i32, RegX8632::Encoded_Reg_esp, Width);
X8632::Address StackSlot = X8632::Address(RegX8632::Encoded_Reg_esp, 0); X8632::Traits::Address StackSlot =
X8632::Traits::Address(RegX8632::Encoded_Reg_esp, 0);
Asm->movss(Ty, StackSlot, RegX8632::getEncodedXmm(Var->getRegNum())); Asm->movss(Ty, StackSlot, RegX8632::getEncodedXmm(Var->getRegNum()));
Asm->fld(Ty, StackSlot); Asm->fld(Ty, StackSlot);
Asm->add(IceType_i32, RegX8632::Encoded_Reg_esp, Width); Asm->add(IceType_i32, RegX8632::Encoded_Reg_esp, Width);
} else { } else {
X8632::Address StackAddr(static_cast<TargetX8632 *>(Func->getTarget()) X8632::Traits::Address StackAddr(
->stackVarToAsmOperand(Var)); static_cast<TargetX8632 *>(Func->getTarget())
->stackVarToAsmOperand(Var));
Asm->fld(Ty, StackAddr); Asm->fld(Ty, StackAddr);
} }
} else if (const auto Mem = llvm::dyn_cast<OperandX8632Mem>(Src)) { } else if (const auto Mem = llvm::dyn_cast<OperandX8632Mem>(Src)) {
assert(Mem->getSegmentRegister() == OperandX8632Mem::DefaultSegment); assert(Mem->getSegmentRegister() == OperandX8632Mem::DefaultSegment);
Asm->fld(Ty, Mem->toAsmAddress(Asm)); Asm->fld(Ty, Mem->toAsmAddress(Asm));
} else if (const auto Imm = llvm::dyn_cast<Constant>(Src)) { } else if (const auto Imm = llvm::dyn_cast<Constant>(Src)) {
Asm->fld(Ty, X8632::Address::ofConstPool(Asm, Imm)); Asm->fld(Ty, X8632::Traits::Address::ofConstPool(Asm, Imm));
} else { } else {
llvm_unreachable("Unexpected operand type"); llvm_unreachable("Unexpected operand type");
} }
...@@ -2489,8 +2505,9 @@ void InstX8632Fstp::emitIAS(const Cfg *Func) const { ...@@ -2489,8 +2505,9 @@ void InstX8632Fstp::emitIAS(const Cfg *Func) const {
} }
Type Ty = Dest->getType(); Type Ty = Dest->getType();
if (!Dest->hasReg()) { if (!Dest->hasReg()) {
X8632::Address StackAddr(static_cast<TargetX8632 *>(Func->getTarget()) X8632::Traits::Address StackAddr(
->stackVarToAsmOperand(Dest)); static_cast<TargetX8632 *>(Func->getTarget())
->stackVarToAsmOperand(Dest));
Asm->fstp(Ty, StackAddr); Asm->fstp(Ty, StackAddr);
} else { } else {
// Dest is a physical (xmm) register, so st(0) needs to go through // Dest is a physical (xmm) register, so st(0) needs to go through
...@@ -2499,7 +2516,8 @@ void InstX8632Fstp::emitIAS(const Cfg *Func) const { ...@@ -2499,7 +2516,8 @@ void InstX8632Fstp::emitIAS(const Cfg *Func) const {
// the stack slot. // the stack slot.
X8632::Immediate Width(typeWidthInBytes(Ty)); X8632::Immediate Width(typeWidthInBytes(Ty));
Asm->sub(IceType_i32, RegX8632::Encoded_Reg_esp, Width); Asm->sub(IceType_i32, RegX8632::Encoded_Reg_esp, Width);
X8632::Address StackSlot = X8632::Address(RegX8632::Encoded_Reg_esp, 0); X8632::Traits::Address StackSlot =
X8632::Traits::Address(RegX8632::Encoded_Reg_esp, 0);
Asm->fstp(Ty, StackSlot); Asm->fstp(Ty, StackSlot);
Asm->movss(Ty, RegX8632::getEncodedXmm(Dest->getRegNum()), StackSlot); Asm->movss(Ty, RegX8632::getEncodedXmm(Dest->getRegNum()), StackSlot);
Asm->add(IceType_i32, RegX8632::Encoded_Reg_esp, Width); Asm->add(IceType_i32, RegX8632::Encoded_Reg_esp, Width);
...@@ -2541,7 +2559,7 @@ template <> void InstX8632Pextr::emit(const Cfg *Func) const { ...@@ -2541,7 +2559,7 @@ template <> void InstX8632Pextr::emit(const Cfg *Func) const {
assert(getSrc(0)->getType() == IceType_v8i16 || assert(getSrc(0)->getType() == IceType_v8i16 ||
getSrc(0)->getType() == IceType_v8i1 || getSrc(0)->getType() == IceType_v8i1 ||
static_cast<TargetX8632 *>(Func->getTarget())->getInstructionSet() >= static_cast<TargetX8632 *>(Func->getTarget())->getInstructionSet() >=
TargetX8632::SSE4_1); X8632::Traits::SSE4_1);
Str << "\t" << Opcode << TypeX8632Attributes[getSrc(0)->getType()].PackString Str << "\t" << Opcode << TypeX8632Attributes[getSrc(0)->getType()].PackString
<< "\t"; << "\t";
getSrc(1)->emit(Func); getSrc(1)->emit(Func);
...@@ -2563,7 +2581,7 @@ template <> void InstX8632Pextr::emitIAS(const Cfg *Func) const { ...@@ -2563,7 +2581,7 @@ template <> void InstX8632Pextr::emitIAS(const Cfg *Func) const {
Type DispatchTy = Dest->getType(); Type DispatchTy = Dest->getType();
assert(DispatchTy == IceType_i16 || assert(DispatchTy == IceType_i16 ||
static_cast<TargetX8632 *>(Func->getTarget())->getInstructionSet() >= static_cast<TargetX8632 *>(Func->getTarget())->getInstructionSet() >=
TargetX8632::SSE4_1); X8632::Traits::SSE4_1);
// pextrw must take a register dest. There is an SSE4.1 version that takes // pextrw must take a register dest. There is an SSE4.1 version that takes
// a memory dest, but we aren't using it. For uniformity, just restrict // a memory dest, but we aren't using it. For uniformity, just restrict
// them all to have a register dest for now. // them all to have a register dest for now.
...@@ -2587,7 +2605,7 @@ template <> void InstX8632Pinsr::emit(const Cfg *Func) const { ...@@ -2587,7 +2605,7 @@ template <> void InstX8632Pinsr::emit(const Cfg *Func) const {
assert(getDest()->getType() == IceType_v8i16 || assert(getDest()->getType() == IceType_v8i16 ||
getDest()->getType() == IceType_v8i1 || getDest()->getType() == IceType_v8i1 ||
static_cast<TargetX8632 *>(Func->getTarget())->getInstructionSet() >= static_cast<TargetX8632 *>(Func->getTarget())->getInstructionSet() >=
TargetX8632::SSE4_1); X8632::Traits::SSE4_1);
Str << "\t" << Opcode << TypeX8632Attributes[getDest()->getType()].PackString Str << "\t" << Opcode << TypeX8632Attributes[getDest()->getType()].PackString
<< "\t"; << "\t";
getSrc(2)->emit(Func); getSrc(2)->emit(Func);
...@@ -2615,7 +2633,7 @@ template <> void InstX8632Pinsr::emitIAS(const Cfg *Func) const { ...@@ -2615,7 +2633,7 @@ template <> void InstX8632Pinsr::emitIAS(const Cfg *Func) const {
Type DispatchTy = Src0->getType(); Type DispatchTy = Src0->getType();
assert(DispatchTy == IceType_i16 || assert(DispatchTy == IceType_i16 ||
static_cast<TargetX8632 *>(Func->getTarget())->getInstructionSet() >= static_cast<TargetX8632 *>(Func->getTarget())->getInstructionSet() >=
TargetX8632::SSE4_1); X8632::Traits::SSE4_1);
// If src1 is a register, it should always be r32 (this should fall out // If src1 is a register, it should always be r32 (this should fall out
// from the encodings for ByteRegs overlapping the encodings for r32), // from the encodings for ByteRegs overlapping the encodings for r32),
// but we have to trust the regalloc to not choose "ah", where it // but we have to trust the regalloc to not choose "ah", where it
...@@ -2796,7 +2814,7 @@ void InstX8632Setcc::emit(const Cfg *Func) const { ...@@ -2796,7 +2814,7 @@ void InstX8632Setcc::emit(const Cfg *Func) const {
} }
void InstX8632Setcc::emitIAS(const Cfg *Func) const { void InstX8632Setcc::emitIAS(const Cfg *Func) const {
assert(Condition != CondX86::Br_None); assert(Condition != X8632::Traits::Cond::Br_None);
assert(getDest()->getType() == IceType_i1); assert(getDest()->getType() == IceType_i1);
assert(getSrcSize() == 0); assert(getSrcSize() == 0);
X8632::AssemblerX8632 *Asm = Func->getAssembler<X8632::AssemblerX8632>(); X8632::AssemblerX8632 *Asm = Func->getAssembler<X8632::AssemblerX8632>();
...@@ -2835,7 +2853,7 @@ void InstX8632Xadd::emitIAS(const Cfg *Func) const { ...@@ -2835,7 +2853,7 @@ void InstX8632Xadd::emitIAS(const Cfg *Func) const {
Type Ty = getSrc(0)->getType(); Type Ty = getSrc(0)->getType();
const auto Mem = llvm::cast<OperandX8632Mem>(getSrc(0)); const auto Mem = llvm::cast<OperandX8632Mem>(getSrc(0));
assert(Mem->getSegmentRegister() == OperandX8632Mem::DefaultSegment); assert(Mem->getSegmentRegister() == OperandX8632Mem::DefaultSegment);
const X8632::Address Addr = Mem->toAsmAddress(Asm); const X8632::Traits::Address Addr = Mem->toAsmAddress(Asm);
const auto VarReg = llvm::cast<Variable>(getSrc(1)); const auto VarReg = llvm::cast<Variable>(getSrc(1));
assert(VarReg->hasReg()); assert(VarReg->hasReg());
const RegX8632::GPRRegister Reg = const RegX8632::GPRRegister Reg =
...@@ -2871,7 +2889,7 @@ void InstX8632Xchg::emitIAS(const Cfg *Func) const { ...@@ -2871,7 +2889,7 @@ void InstX8632Xchg::emitIAS(const Cfg *Func) const {
Type Ty = getSrc(0)->getType(); Type Ty = getSrc(0)->getType();
const auto Mem = llvm::cast<OperandX8632Mem>(getSrc(0)); const auto Mem = llvm::cast<OperandX8632Mem>(getSrc(0));
assert(Mem->getSegmentRegister() == OperandX8632Mem::DefaultSegment); assert(Mem->getSegmentRegister() == OperandX8632Mem::DefaultSegment);
const X8632::Address Addr = Mem->toAsmAddress(Asm); const X8632::Traits::Address Addr = Mem->toAsmAddress(Asm);
const auto VarReg = llvm::cast<Variable>(getSrc(1)); const auto VarReg = llvm::cast<Variable>(getSrc(1));
assert(VarReg->hasReg()); assert(VarReg->hasReg());
const RegX8632::GPRRegister Reg = const RegX8632::GPRRegister Reg =
...@@ -2982,7 +3000,7 @@ void OperandX8632Mem::emitSegmentOverride(X8632::AssemblerX8632 *Asm) const { ...@@ -2982,7 +3000,7 @@ void OperandX8632Mem::emitSegmentOverride(X8632::AssemblerX8632 *Asm) const {
} }
} }
X8632::Address OperandX8632Mem::toAsmAddress(Assembler *Asm) const { X8632::Traits::Address OperandX8632Mem::toAsmAddress(Assembler *Asm) const {
int32_t Disp = 0; int32_t Disp = 0;
AssemblerFixup *Fixup = nullptr; AssemblerFixup *Fixup = nullptr;
// Determine the offset (is it relocatable?) // Determine the offset (is it relocatable?)
...@@ -3000,29 +3018,31 @@ X8632::Address OperandX8632Mem::toAsmAddress(Assembler *Asm) const { ...@@ -3000,29 +3018,31 @@ X8632::Address OperandX8632Mem::toAsmAddress(Assembler *Asm) const {
// Now convert to the various possible forms. // Now convert to the various possible forms.
if (getBase() && getIndex()) { if (getBase() && getIndex()) {
return X8632::Address(RegX8632::getEncodedGPR(getBase()->getRegNum()), return X8632::Traits::Address(
RegX8632::getEncodedGPR(getIndex()->getRegNum()), RegX8632::getEncodedGPR(getBase()->getRegNum()),
X8632::ScaleFactor(getShift()), Disp); RegX8632::getEncodedGPR(getIndex()->getRegNum()),
X8632::Traits::ScaleFactor(getShift()), Disp);
} else if (getBase()) { } else if (getBase()) {
return X8632::Address(RegX8632::getEncodedGPR(getBase()->getRegNum()), return X8632::Traits::Address(
Disp); RegX8632::getEncodedGPR(getBase()->getRegNum()), Disp);
} else if (getIndex()) { } else if (getIndex()) {
return X8632::Address(RegX8632::getEncodedGPR(getIndex()->getRegNum()), return X8632::Traits::Address(
X8632::ScaleFactor(getShift()), Disp); RegX8632::getEncodedGPR(getIndex()->getRegNum()),
X8632::Traits::ScaleFactor(getShift()), Disp);
} else if (Fixup) { } else if (Fixup) {
return X8632::Address::Absolute(Disp, Fixup); return X8632::Traits::Address::Absolute(Disp, Fixup);
} else { } else {
return X8632::Address::Absolute(Disp); return X8632::Traits::Address::Absolute(Disp);
} }
} }
X8632::Address VariableSplit::toAsmAddress(const Cfg *Func) const { X8632::Traits::Address VariableSplit::toAsmAddress(const Cfg *Func) const {
assert(!Var->hasReg()); assert(!Var->hasReg());
const TargetLowering *Target = Func->getTarget(); const TargetLowering *Target = Func->getTarget();
int32_t Offset = int32_t Offset =
Var->getStackOffset() + Target->getStackAdjustment() + getOffset(); Var->getStackOffset() + Target->getStackAdjustment() + getOffset();
return X8632::Address(RegX8632::getEncodedGPR(Target->getFrameOrStackReg()), return X8632::Traits::Address(
Offset); RegX8632::getEncodedGPR(Target->getFrameOrStackReg()), Offset);
} }
void VariableSplit::emit(const Cfg *Func) const { void VariableSplit::emit(const Cfg *Func) const {
......
...@@ -22,6 +22,7 @@ ...@@ -22,6 +22,7 @@
#include "IceInst.h" #include "IceInst.h"
#include "IceInstX8632.def" #include "IceInstX8632.def"
#include "IceOperand.h" #include "IceOperand.h"
#include "IceTargetLoweringX8632Traits.h"
namespace Ice { namespace Ice {
...@@ -76,7 +77,7 @@ public: ...@@ -76,7 +77,7 @@ public:
uint16_t getShift() const { return Shift; } uint16_t getShift() const { return Shift; }
SegmentRegisters getSegmentRegister() const { return SegmentReg; } SegmentRegisters getSegmentRegister() const { return SegmentReg; }
void emitSegmentOverride(X8632::AssemblerX8632 *Asm) const; void emitSegmentOverride(X8632::AssemblerX8632 *Asm) const;
X8632::Address toAsmAddress(Assembler *Asm) const; X8632::Traits::Address toAsmAddress(Assembler *Asm) const;
void emit(const Cfg *Func) const override; void emit(const Cfg *Func) const override;
using OperandX8632::dump; using OperandX8632::dump;
void dump(const Cfg *Func, Ostream &Str) const override; void dump(const Cfg *Func, Ostream &Str) const override;
...@@ -122,7 +123,7 @@ public: ...@@ -122,7 +123,7 @@ public:
} }
int32_t getOffset() const { return Part == High ? 4 : 0; } int32_t getOffset() const { return Part == High ? 4 : 0; }
X8632::Address toAsmAddress(const Cfg *Func) const; X8632::Traits::Address toAsmAddress(const Cfg *Func) const;
void emit(const Cfg *Func) const override; void emit(const Cfg *Func) const override;
using OperandX8632::dump; using OperandX8632::dump;
void dump(const Cfg *Func, Ostream &Str) const override; void dump(const Cfg *Func, Ostream &Str) const override;
...@@ -279,7 +280,8 @@ public: ...@@ -279,7 +280,8 @@ public:
static const char *getWidthString(Type Ty); static const char *getWidthString(Type Ty);
static const char *getFldString(Type Ty); static const char *getFldString(Type Ty);
static CondX86::BrCond getOppositeCondition(CondX86::BrCond Cond); static X8632::Traits::Cond::BrCond
getOppositeCondition(X8632::Traits::Cond::BrCond Cond);
void dump(const Cfg *Func) const override; void dump(const Cfg *Func) const override;
// Shared emit routines for common forms of instructions. // Shared emit routines for common forms of instructions.
...@@ -428,8 +430,9 @@ class InstX8632Br : public InstX8632 { ...@@ -428,8 +430,9 @@ class InstX8632Br : public InstX8632 {
public: public:
// Create a conditional branch to a node. // Create a conditional branch to a node.
static InstX8632Br *create(Cfg *Func, CfgNode *TargetTrue, static InstX8632Br *create(Cfg *Func, CfgNode *TargetTrue,
CfgNode *TargetFalse, CondX86::BrCond Condition) { CfgNode *TargetFalse,
assert(Condition != CondX86::Br_None); X8632::Traits::Cond::BrCond Condition) {
assert(Condition != X8632::Traits::Cond::Br_None);
const InstX8632Label *NoLabel = nullptr; const InstX8632Label *NoLabel = nullptr;
return new (Func->allocate<InstX8632Br>()) return new (Func->allocate<InstX8632Br>())
InstX8632Br(Func, TargetTrue, TargetFalse, NoLabel, Condition); InstX8632Br(Func, TargetTrue, TargetFalse, NoLabel, Condition);
...@@ -438,15 +441,15 @@ public: ...@@ -438,15 +441,15 @@ public:
static InstX8632Br *create(Cfg *Func, CfgNode *Target) { static InstX8632Br *create(Cfg *Func, CfgNode *Target) {
const CfgNode *NoCondTarget = nullptr; const CfgNode *NoCondTarget = nullptr;
const InstX8632Label *NoLabel = nullptr; const InstX8632Label *NoLabel = nullptr;
return new (Func->allocate<InstX8632Br>()) return new (Func->allocate<InstX8632Br>()) InstX8632Br(
InstX8632Br(Func, NoCondTarget, Target, NoLabel, CondX86::Br_None); Func, NoCondTarget, Target, NoLabel, X8632::Traits::Cond::Br_None);
} }
// Create a non-terminator conditional branch to a node, with a // Create a non-terminator conditional branch to a node, with a
// fallthrough to the next instruction in the current node. This is // fallthrough to the next instruction in the current node. This is
// used for switch lowering. // used for switch lowering.
static InstX8632Br *create(Cfg *Func, CfgNode *Target, static InstX8632Br *create(Cfg *Func, CfgNode *Target,
CondX86::BrCond Condition) { X8632::Traits::Cond::BrCond Condition) {
assert(Condition != CondX86::Br_None); assert(Condition != X8632::Traits::Cond::Br_None);
const CfgNode *NoUncondTarget = nullptr; const CfgNode *NoUncondTarget = nullptr;
const InstX8632Label *NoLabel = nullptr; const InstX8632Label *NoLabel = nullptr;
return new (Func->allocate<InstX8632Br>()) return new (Func->allocate<InstX8632Br>())
...@@ -455,7 +458,7 @@ public: ...@@ -455,7 +458,7 @@ public:
// Create a conditional intra-block branch (or unconditional, if // Create a conditional intra-block branch (or unconditional, if
// Condition==Br_None) to a label in the current block. // Condition==Br_None) to a label in the current block.
static InstX8632Br *create(Cfg *Func, InstX8632Label *Label, static InstX8632Br *create(Cfg *Func, InstX8632Label *Label,
CondX86::BrCond Condition) { X8632::Traits::Cond::BrCond Condition) {
const CfgNode *NoCondTarget = nullptr; const CfgNode *NoCondTarget = nullptr;
const CfgNode *NoUncondTarget = nullptr; const CfgNode *NoUncondTarget = nullptr;
return new (Func->allocate<InstX8632Br>()) return new (Func->allocate<InstX8632Br>())
...@@ -475,7 +478,7 @@ public: ...@@ -475,7 +478,7 @@ public:
return Sum; return Sum;
} }
bool isUnconditionalBranch() const override { bool isUnconditionalBranch() const override {
return !Label && Condition == CondX86::Br_None; return !Label && Condition == X8632::Traits::Cond::Br_None;
} }
bool repointEdge(CfgNode *OldNode, CfgNode *NewNode) override; bool repointEdge(CfgNode *OldNode, CfgNode *NewNode) override;
void emit(const Cfg *Func) const override; void emit(const Cfg *Func) const override;
...@@ -485,9 +488,10 @@ public: ...@@ -485,9 +488,10 @@ public:
private: private:
InstX8632Br(Cfg *Func, const CfgNode *TargetTrue, const CfgNode *TargetFalse, InstX8632Br(Cfg *Func, const CfgNode *TargetTrue, const CfgNode *TargetFalse,
const InstX8632Label *Label, CondX86::BrCond Condition); const InstX8632Label *Label,
X8632::Traits::Cond::BrCond Condition);
CondX86::BrCond Condition; X8632::Traits::Cond::BrCond Condition;
const CfgNode *TargetTrue; const CfgNode *TargetTrue;
const CfgNode *TargetFalse; const CfgNode *TargetFalse;
const InstX8632Label *Label; // Intra-block branch target const InstX8632Label *Label; // Intra-block branch target
...@@ -1256,7 +1260,7 @@ class InstX8632Cmov : public InstX8632 { ...@@ -1256,7 +1260,7 @@ class InstX8632Cmov : public InstX8632 {
public: public:
static InstX8632Cmov *create(Cfg *Func, Variable *Dest, Operand *Source, static InstX8632Cmov *create(Cfg *Func, Variable *Dest, Operand *Source,
CondX86::BrCond Cond) { X8632::Traits::Cond::BrCond Cond) {
return new (Func->allocate<InstX8632Cmov>()) return new (Func->allocate<InstX8632Cmov>())
InstX8632Cmov(Func, Dest, Source, Cond); InstX8632Cmov(Func, Dest, Source, Cond);
} }
...@@ -1267,9 +1271,9 @@ public: ...@@ -1267,9 +1271,9 @@ public:
private: private:
InstX8632Cmov(Cfg *Func, Variable *Dest, Operand *Source, InstX8632Cmov(Cfg *Func, Variable *Dest, Operand *Source,
CondX86::BrCond Cond); X8632::Traits::Cond::BrCond Cond);
CondX86::BrCond Condition; X8632::Traits::Cond::BrCond Condition;
}; };
// Cmpps instruction - compare packed singled-precision floating point // Cmpps instruction - compare packed singled-precision floating point
...@@ -1281,7 +1285,7 @@ class InstX8632Cmpps : public InstX8632 { ...@@ -1281,7 +1285,7 @@ class InstX8632Cmpps : public InstX8632 {
public: public:
static InstX8632Cmpps *create(Cfg *Func, Variable *Dest, Operand *Source, static InstX8632Cmpps *create(Cfg *Func, Variable *Dest, Operand *Source,
CondX86::CmppsCond Condition) { X8632::Traits::Cond::CmppsCond Condition) {
return new (Func->allocate<InstX8632Cmpps>()) return new (Func->allocate<InstX8632Cmpps>())
InstX8632Cmpps(Func, Dest, Source, Condition); InstX8632Cmpps(Func, Dest, Source, Condition);
} }
...@@ -1292,9 +1296,9 @@ public: ...@@ -1292,9 +1296,9 @@ public:
private: private:
InstX8632Cmpps(Cfg *Func, Variable *Dest, Operand *Source, InstX8632Cmpps(Cfg *Func, Variable *Dest, Operand *Source,
CondX86::CmppsCond Cond); X8632::Traits::Cond::CmppsCond Cond);
CondX86::CmppsCond Condition; X8632::Traits::Cond::CmppsCond Condition;
}; };
// Cmpxchg instruction - cmpxchg <dest>, <desired> will compare if <dest> // Cmpxchg instruction - cmpxchg <dest>, <desired> will compare if <dest>
...@@ -1670,7 +1674,7 @@ class InstX8632Setcc : public InstX8632 { ...@@ -1670,7 +1674,7 @@ class InstX8632Setcc : public InstX8632 {
public: public:
static InstX8632Setcc *create(Cfg *Func, Variable *Dest, static InstX8632Setcc *create(Cfg *Func, Variable *Dest,
CondX86::BrCond Cond) { X8632::Traits::Cond::BrCond Cond) {
return new (Func->allocate<InstX8632Setcc>()) return new (Func->allocate<InstX8632Setcc>())
InstX8632Setcc(Func, Dest, Cond); InstX8632Setcc(Func, Dest, Cond);
} }
...@@ -1680,9 +1684,9 @@ public: ...@@ -1680,9 +1684,9 @@ public:
static bool classof(const Inst *Inst) { return isClassof(Inst, Setcc); } static bool classof(const Inst *Inst) { return isClassof(Inst, Setcc); }
private: private:
InstX8632Setcc(Cfg *Func, Variable *Dest, CondX86::BrCond Cond); InstX8632Setcc(Cfg *Func, Variable *Dest, X8632::Traits::Cond::BrCond Cond);
const CondX86::BrCond Condition; const X8632::Traits::Cond::BrCond Condition;
}; };
// Exchanging Add instruction. Exchanges the first operand (destination // Exchanging Add instruction. Exchanges the first operand (destination
......
...@@ -20,93 +20,92 @@ ...@@ -20,93 +20,92 @@
namespace Ice { namespace Ice {
namespace RegX8632 { class RegX8632 {
public:
// An enum of every register. The enum value may not match the encoding // An enum of every register. The enum value may not match the encoding
// used to binary encode register operands in instructions. // used to binary encode register operands in instructions.
enum AllRegisters { enum AllRegisters {
#define X(val, encode, name, name16, name8, scratch, preserved, stackptr, \ #define X(val, encode, name, name16, name8, scratch, preserved, stackptr, \
frameptr, isI8, isInt, isFP) \ frameptr, isI8, isInt, isFP) \
val, val,
REGX8632_TABLE REGX8632_TABLE
#undef X #undef X
Reg_NUM, Reg_NUM,
#define X(val, init) val init, #define X(val, init) val init,
REGX8632_TABLE_BOUNDS REGX8632_TABLE_BOUNDS
#undef X #undef X
}; };
// An enum of GPR Registers. The enum value does match the encoding used // An enum of GPR Registers. The enum value does match the encoding used
// to binary encode register operands in instructions. // to binary encode register operands in instructions.
enum GPRRegister { enum GPRRegister {
#define X(val, encode, name, name16, name8, scratch, preserved, stackptr, \ #define X(val, encode, name, name16, name8, scratch, preserved, stackptr, \
frameptr, isI8, isInt, isFP) \ frameptr, isI8, isInt, isFP) \
Encoded_##val encode, Encoded_##val encode,
REGX8632_GPR_TABLE REGX8632_GPR_TABLE
#undef X #undef X
Encoded_Not_GPR = -1 Encoded_Not_GPR = -1
}; };
// An enum of XMM Registers. The enum value does match the encoding used // An enum of XMM Registers. The enum value does match the encoding used
// to binary encode register operands in instructions. // to binary encode register operands in instructions.
enum XmmRegister { enum XmmRegister {
#define X(val, encode, name, name16, name8, scratch, preserved, stackptr, \ #define X(val, encode, name, name16, name8, scratch, preserved, stackptr, \
frameptr, isI8, isInt, isFP) \ frameptr, isI8, isInt, isFP) \
Encoded_##val encode, Encoded_##val encode,
REGX8632_XMM_TABLE REGX8632_XMM_TABLE
#undef X #undef X
Encoded_Not_Xmm = -1 Encoded_Not_Xmm = -1
}; };
// An enum of Byte Registers. The enum value does match the encoding used // An enum of Byte Registers. The enum value does match the encoding used
// to binary encode register operands in instructions. // to binary encode register operands in instructions.
enum ByteRegister { enum ByteRegister {
#define X(val, encode) Encoded_##val encode, #define X(val, encode) Encoded_##val encode,
REGX8632_BYTEREG_TABLE REGX8632_BYTEREG_TABLE
#undef X #undef X
Encoded_Not_ByteReg = -1 Encoded_Not_ByteReg = -1
}; };
// An enum of X87 Stack Registers. The enum value does match the encoding used // An enum of X87 Stack Registers. The enum value does match the encoding used
// to binary encode register operands in instructions. // to binary encode register operands in instructions.
enum X87STRegister { enum X87STRegister {
#define X(val, encode, name) Encoded_##val encode, #define X(val, encode, name) Encoded_##val encode,
X87ST_REGX8632_TABLE X87ST_REGX8632_TABLE
#undef X #undef X
Encoded_Not_X87STReg = -1 Encoded_Not_X87STReg = -1
};
static inline GPRRegister getEncodedGPR(int32_t RegNum) {
assert(Reg_GPR_First <= RegNum && RegNum <= Reg_GPR_Last);
return GPRRegister(RegNum - Reg_GPR_First);
}
static inline XmmRegister getEncodedXmm(int32_t RegNum) {
assert(Reg_XMM_First <= RegNum && RegNum <= Reg_XMM_Last);
return XmmRegister(RegNum - Reg_XMM_First);
}
static inline ByteRegister getEncodedByteReg(int32_t RegNum) {
assert(RegNum == Reg_ah || (Reg_GPR_First <= RegNum && RegNum <= Reg_ebx));
if (RegNum == Reg_ah)
return Encoded_Reg_ah;
return ByteRegister(RegNum - Reg_GPR_First);
}
static inline GPRRegister getEncodedByteRegOrGPR(Type Ty, int32_t RegNum) {
if (isByteSizedType(Ty))
return GPRRegister(getEncodedByteReg(RegNum));
else
return getEncodedGPR(RegNum);
}
static inline X87STRegister getEncodedSTReg(int32_t RegNum) {
assert(Encoded_X87ST_First <= RegNum && RegNum <= Encoded_X87ST_Last);
return X87STRegister(RegNum);
}
}; };
static inline GPRRegister getEncodedGPR(int32_t RegNum) {
assert(Reg_GPR_First <= RegNum && RegNum <= Reg_GPR_Last);
return GPRRegister(RegNum - Reg_GPR_First);
}
static inline XmmRegister getEncodedXmm(int32_t RegNum) {
assert(Reg_XMM_First <= RegNum && RegNum <= Reg_XMM_Last);
return XmmRegister(RegNum - Reg_XMM_First);
}
static inline ByteRegister getEncodedByteReg(int32_t RegNum) {
assert(RegNum == Reg_ah || (Reg_GPR_First <= RegNum && RegNum <= Reg_ebx));
if (RegNum == Reg_ah)
return Encoded_Reg_ah;
return ByteRegister(RegNum - Reg_GPR_First);
}
static inline GPRRegister getEncodedByteRegOrGPR(Type Ty, int32_t RegNum) {
if (isByteSizedType(Ty))
return GPRRegister(getEncodedByteReg(RegNum));
else
return getEncodedGPR(RegNum);
}
static inline X87STRegister getEncodedSTReg(int32_t RegNum) {
assert(Encoded_X87ST_First <= RegNum && RegNum <= Encoded_X87ST_Last);
return X87STRegister(RegNum);
}
} // end of namespace RegX8632
} // end of namespace Ice } // end of namespace Ice
#endif // SUBZERO_SRC_ICEREGISTERSX8632_H #endif // SUBZERO_SRC_ICEREGISTERSX8632_H
...@@ -20,79 +20,78 @@ ...@@ -20,79 +20,78 @@
namespace Ice { namespace Ice {
namespace RegX8664 { class RegX8664 {
public:
// An enum of every register. The enum value may not match the encoding // An enum of every register. The enum value may not match the encoding
// used to binary encode register operands in instructions. // used to binary encode register operands in instructions.
enum AllRegisters { enum AllRegisters {
#define X(val, encode, name64, name, name16, name8, scratch, preserved, \ #define X(val, encode, name64, name, name16, name8, scratch, preserved, \
stackptr, frameptr, isInt, isFP) \ stackptr, frameptr, isInt, isFP) \
val, val,
REGX8664_TABLE REGX8664_TABLE
#undef X #undef X
Reg_NUM, Reg_NUM,
#define X(val, init) val init, #define X(val, init) val init,
REGX8664_TABLE_BOUNDS REGX8664_TABLE_BOUNDS
#undef X #undef X
}; };
// An enum of GPR Registers. The enum value does match the encoding used // An enum of GPR Registers. The enum value does match the encoding used
// to binary encode register operands in instructions. // to binary encode register operands in instructions.
enum GPRRegister { enum GPRRegister {
#define X(val, encode, name64, name, name16, name8, scratch, preserved, \ #define X(val, encode, name64, name, name16, name8, scratch, preserved, \
stackptr, frameptr, isInt, isFP) \ stackptr, frameptr, isInt, isFP) \
Encoded_##val encode, Encoded_##val encode,
REGX8664_GPR_TABLE REGX8664_GPR_TABLE
#undef X #undef X
Encoded_Not_GPR = -1 Encoded_Not_GPR = -1
}; };
// An enum of XMM Registers. The enum value does match the encoding used // An enum of XMM Registers. The enum value does match the encoding used
// to binary encode register operands in instructions. // to binary encode register operands in instructions.
enum XmmRegister { enum XmmRegister {
#define X(val, encode, name64, name, name16, name8, scratch, preserved, \ #define X(val, encode, name64, name, name16, name8, scratch, preserved, \
stackptr, frameptr, isInt, isFP) \ stackptr, frameptr, isInt, isFP) \
Encoded_##val encode, Encoded_##val encode,
REGX8664_XMM_TABLE REGX8664_XMM_TABLE
#undef X #undef X
Encoded_Not_Xmm = -1 Encoded_Not_Xmm = -1
}; };
// An enum of Byte Registers. The enum value does match the encoding used // An enum of Byte Registers. The enum value does match the encoding used
// to binary encode register operands in instructions. // to binary encode register operands in instructions.
enum ByteRegister { enum ByteRegister {
#define X(val, encode) Encoded_##val encode, #define X(val, encode) Encoded_##val encode,
REGX8664_BYTEREG_TABLE REGX8664_BYTEREG_TABLE
#undef X #undef X
Encoded_Not_ByteReg = -1 Encoded_Not_ByteReg = -1
}; };
static inline GPRRegister getEncodedGPR(int32_t RegNum) {
assert(Reg_GPR_First <= RegNum && RegNum <= Reg_GPR_Last);
return GPRRegister(RegNum - Reg_GPR_First);
}
static inline XmmRegister getEncodedXmm(int32_t RegNum) { static inline GPRRegister getEncodedGPR(int32_t RegNum) {
assert(Reg_XMM_First <= RegNum && RegNum <= Reg_XMM_Last); assert(Reg_GPR_First <= RegNum && RegNum <= Reg_GPR_Last);
return XmmRegister(RegNum - Reg_XMM_First); return GPRRegister(RegNum - Reg_GPR_First);
} }
static inline ByteRegister getEncodedByteReg(int32_t RegNum) { static inline XmmRegister getEncodedXmm(int32_t RegNum) {
// In x86-64, AH is not encodable when the REX prefix is used; the same assert(Reg_XMM_First <= RegNum && RegNum <= Reg_XMM_Last);
// encoding is used for spl. Therefore, ah needs special handling. return XmmRegister(RegNum - Reg_XMM_First);
if (RegNum == Reg_ah) }
return Encoded_Reg_spl;
return ByteRegister(RegNum - Reg_GPR_First);
}
static inline GPRRegister getEncodedByteRegOrGPR(Type Ty, int32_t RegNum) { static inline ByteRegister getEncodedByteReg(int32_t RegNum) {
if (isByteSizedType(Ty)) // In x86-64, AH is not encodable when the REX prefix is used; the same
return GPRRegister(getEncodedByteReg(RegNum)); // encoding is used for spl. Therefore, ah needs special handling.
else if (RegNum == Reg_ah)
return getEncodedGPR(RegNum); return Encoded_Reg_spl;
} return ByteRegister(RegNum - Reg_GPR_First);
}
} // end of namespace RegX8664 static inline GPRRegister getEncodedByteRegOrGPR(Type Ty, int32_t RegNum) {
if (isByteSizedType(Ty))
return GPRRegister(getEncodedByteReg(RegNum));
else
return getEncodedGPR(RegNum);
}
};
} // end of namespace Ice } // end of namespace Ice
......
...@@ -2,6 +2,9 @@ ...@@ -2,6 +2,9 @@
// //
// The Subzero Code Generator // 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 TargetLoweringX8632 class, which // This file implements the TargetLoweringX8632 class, which
...@@ -12,100 +15,19 @@ ...@@ -12,100 +15,19 @@
#include "IceTargetLoweringX8632.h" #include "IceTargetLoweringX8632.h"
#include "IceTargetLoweringX8632Traits.h"
#include "IceTargetLoweringX86Base.h" #include "IceTargetLoweringX86Base.h"
namespace Ice { namespace Ice {
namespace X86Internal {
template <> struct MachineTraits<TargetX8632> {
using InstructionSet = TargetX8632::X86InstructionSet;
// The following table summarizes the logic for lowering the fcmp
// instruction. There is one table entry for each of the 16 conditions.
//
// The first four columns describe the case when the operands are
// floating point scalar values. A comment in lowerFcmp() describes the
// lowering template. In the most general case, there is a compare
// followed by two conditional branches, because some fcmp conditions
// don't map to a single x86 conditional branch. However, in many cases
// it is possible to swap the operands in the comparison and have a
// single conditional branch. Since it's quite tedious to validate the
// table by hand, good execution tests are helpful.
//
// The last two columns describe the case when the operands are vectors
// of floating point values. For most fcmp conditions, there is a clear
// mapping to a single x86 cmpps instruction variant. Some fcmp
// conditions require special code to handle and these are marked in the
// table with a Cmpps_Invalid predicate.
static const struct TableFcmpType {
uint32_t Default;
bool SwapScalarOperands;
CondX86::BrCond C1, C2;
bool SwapVectorOperands;
CondX86::CmppsCond Predicate;
} TableFcmp[];
static const size_t TableFcmpSize;
// The following table summarizes the logic for lowering the icmp instruction
// for i32 and narrower types. Each icmp condition has a clear mapping to an
// x86 conditional branch instruction.
static const struct TableIcmp32Type {
CondX86::BrCond Mapping;
} TableIcmp32[];
static const size_t TableIcmp32Size;
// The following table summarizes the logic for lowering the icmp instruction
// for the i64 type. For Eq and Ne, two separate 32-bit comparisons and
// conditional branches are needed. For the other conditions, three separate
// conditional branches are needed.
static const struct TableIcmp64Type {
CondX86::BrCond C1, C2, C3;
} TableIcmp64[];
static const size_t TableIcmp64Size;
static CondX86::BrCond getIcmp32Mapping(InstIcmp::ICond Cond) {
size_t Index = static_cast<size_t>(Cond);
assert(Index < TableIcmp32Size);
return TableIcmp32[Index].Mapping;
}
static const struct TableTypeX8632AttributesType {
Type InVectorElementType;
} TableTypeX8632Attributes[];
static const size_t TableTypeX8632AttributesSize;
// Return the type which the elements of the vector have in the X86
// representation of the vector.
static Type getInVectorElementType(Type Ty) {
assert(isVectorType(Ty));
size_t Index = static_cast<size_t>(Ty);
(void)Index;
assert(Index < TableTypeX8632AttributesSize);
return TableTypeX8632Attributes[Ty].InVectorElementType;
}
// The maximum number of arguments to pass in XMM registers
static const uint32_t X86_MAX_XMM_ARGS = 4;
// The number of bits in a byte
static const uint32_t X86_CHAR_BIT = 8;
// Stack alignment
static const uint32_t X86_STACK_ALIGNMENT_BYTES;
// Size of the return address on the stack
static const uint32_t X86_RET_IP_SIZE_BYTES = 4;
// The number of different NOP instructions
static const uint32_t X86_NUM_NOP_VARIANTS = 5;
// Value is in bytes. Return Value adjusted to the next highest multiple
// of the stack alignment.
static uint32_t applyStackAlignment(uint32_t Value) {
return Utils::applyAlignment(Value, X86_STACK_ALIGNMENT_BYTES);
}
};
namespace X86Internal {
const MachineTraits<TargetX8632>::TableFcmpType const MachineTraits<TargetX8632>::TableFcmpType
MachineTraits<TargetX8632>::TableFcmp[] = { MachineTraits<TargetX8632>::TableFcmp[] = {
#define X(val, dflt, swapS, C1, C2, swapV, pred) \ #define X(val, dflt, swapS, C1, C2, swapV, pred) \
{ dflt, swapS, CondX86::C1, CondX86::C2, swapV, CondX86::pred } \ { \
dflt, swapS, X8632::Traits::Cond::C1, X8632::Traits::Cond::C2, swapV, \
X8632::Traits::Cond::pred \
} \
, ,
FCMPX8632_TABLE FCMPX8632_TABLE
#undef X #undef X
...@@ -117,7 +39,7 @@ const size_t MachineTraits<TargetX8632>::TableFcmpSize = ...@@ -117,7 +39,7 @@ const size_t MachineTraits<TargetX8632>::TableFcmpSize =
const MachineTraits<TargetX8632>::TableIcmp32Type const MachineTraits<TargetX8632>::TableIcmp32Type
MachineTraits<TargetX8632>::TableIcmp32[] = { MachineTraits<TargetX8632>::TableIcmp32[] = {
#define X(val, C_32, C1_64, C2_64, C3_64) \ #define X(val, C_32, C1_64, C2_64, C3_64) \
{ CondX86::C_32 } \ { X8632::Traits::Cond::C_32 } \
, ,
ICMPX8632_TABLE ICMPX8632_TABLE
#undef X #undef X
...@@ -129,7 +51,10 @@ const size_t MachineTraits<TargetX8632>::TableIcmp32Size = ...@@ -129,7 +51,10 @@ const size_t MachineTraits<TargetX8632>::TableIcmp32Size =
const MachineTraits<TargetX8632>::TableIcmp64Type const MachineTraits<TargetX8632>::TableIcmp64Type
MachineTraits<TargetX8632>::TableIcmp64[] = { MachineTraits<TargetX8632>::TableIcmp64[] = {
#define X(val, C_32, C1_64, C2_64, C3_64) \ #define X(val, C_32, C1_64, C2_64, C3_64) \
{ CondX86::C1_64, CondX86::C2_64, CondX86::C3_64 } \ { \
X8632::Traits::Cond::C1_64, X8632::Traits::Cond::C2_64, \
X8632::Traits::Cond::C3_64 \
} \
, ,
ICMPX8632_TABLE ICMPX8632_TABLE
#undef X #undef X
...@@ -151,6 +76,7 @@ const size_t MachineTraits<TargetX8632>::TableTypeX8632AttributesSize = ...@@ -151,6 +76,7 @@ const size_t MachineTraits<TargetX8632>::TableTypeX8632AttributesSize =
llvm::array_lengthof(TableTypeX8632Attributes); llvm::array_lengthof(TableTypeX8632Attributes);
const uint32_t MachineTraits<TargetX8632>::X86_STACK_ALIGNMENT_BYTES = 16; const uint32_t MachineTraits<TargetX8632>::X86_STACK_ALIGNMENT_BYTES = 16;
} // end of namespace X86Internal } // end of namespace X86Internal
TargetX8632 *TargetX8632::create(Cfg *Func) { TargetX8632 *TargetX8632::create(Cfg *Func) {
......
...@@ -21,6 +21,7 @@ ...@@ -21,6 +21,7 @@
#include "IceInstX8632.h" #include "IceInstX8632.h"
#include "IceRegistersX8632.h" #include "IceRegistersX8632.h"
#include "IceTargetLowering.h" #include "IceTargetLowering.h"
#include "IceTargetLoweringX8632Traits.h"
namespace Ice { namespace Ice {
...@@ -30,16 +31,11 @@ class TargetX8632 : public TargetLowering { ...@@ -30,16 +31,11 @@ class TargetX8632 : public TargetLowering {
TargetX8632 &operator=(const TargetX8632 &) = delete; TargetX8632 &operator=(const TargetX8632 &) = delete;
public: public:
enum X86InstructionSet { using X86InstructionSet = X8632::Traits::InstructionSet;
Begin,
// SSE2 is the PNaCl baseline instruction set.
SSE2 = Begin,
SSE4_1,
End
};
static TargetX8632 *create(Cfg *Func); static TargetX8632 *create(Cfg *Func);
virtual X8632::Address stackVarToAsmOperand(const Variable *Var) const = 0; virtual X8632::Traits::Address
stackVarToAsmOperand(const Variable *Var) const = 0;
virtual X86InstructionSet getInstructionSet() const = 0; virtual X86InstructionSet getInstructionSet() const = 0;
protected: protected:
......
//===- subzero/src/IceTargetLoweringX8632Traits.h - x86-32 traits -*- C++ -*-=//
//
// The Subzero Code Generator
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file defines the X8632 Target Lowering Traits.
//
//===----------------------------------------------------------------------===//
#ifndef SUBZERO_SRC_ICETARGETLOWERINGX8632TRAITS_H
#define SUBZERO_SRC_ICETARGETLOWERINGX8632TRAITS_H
#include "IceAssembler.h"
#include "IceConditionCodesX8632.h"
#include "IceDefs.h"
#include "IceInst.h"
#include "IceInstX8632.def"
#include "IceRegistersX8632.h"
#include "IceTargetLoweringX8632.def"
namespace Ice {
class TargetX8632;
namespace X86Internal {
template <class Machine> struct MachineTraits;
template <> struct MachineTraits<TargetX8632> {
//----------------------------------------------------------------------------
// ______ ______ __ __
// /\ __ \/\ ___\/\ "-./ \
// \ \ __ \ \___ \ \ \-./\ \
// \ \_\ \_\/\_____\ \_\ \ \_\
// \/_/\/_/\/_____/\/_/ \/_/
//
//----------------------------------------------------------------------------
enum ScaleFactor { TIMES_1 = 0, TIMES_2 = 1, TIMES_4 = 2, TIMES_8 = 3 };
using GPRRegister = ::Ice::RegX8632::GPRRegister;
using XmmRegister = ::Ice::RegX8632::XmmRegister;
using ByteRegister = ::Ice::RegX8632::ByteRegister;
using X87STRegister = ::Ice::RegX8632::X87STRegister;
using Cond = ::Ice::CondX86;
using RegisterSet = ::Ice::RegX8632;
static const GPRRegister Encoded_Reg_Accumulator = RegX8632::Encoded_Reg_eax;
static const GPRRegister Encoded_Reg_Counter = RegX8632::Encoded_Reg_ecx;
static const FixupKind PcRelFixup = llvm::ELF::R_386_PC32;
class Operand {
public:
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;
}
uint8_t mod() const { return (encoding_at(0) >> 6) & 3; }
GPRRegister rm() const {
return static_cast<GPRRegister>(encoding_at(0) & 7);
}
ScaleFactor scale() const {
return static_cast<ScaleFactor>((encoding_at(1) >> 6) & 3);
}
GPRRegister index() const {
return static_cast<GPRRegister>((encoding_at(1) >> 3) & 7);
}
GPRRegister base() const {
return static_cast<GPRRegister>(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_; }
protected:
Operand() : length_(0), fixup_(nullptr) {} // Needed by subclass Address.
void SetModRM(int mod, GPRRegister rm) {
assert((mod & ~3) == 0);
encoding_[0] = (mod << 6) | rm;
length_ = 1;
}
void SetSIB(ScaleFactor scale, GPRRegister index, GPRRegister 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];
AssemblerFixup *fixup_;
explicit Operand(GPRRegister reg) : fixup_(nullptr) { 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(GPRRegister reg) const {
return ((encoding_[0] & 0xF8) ==
0xC0) // Addressing mode is register only.
&&
((encoding_[0] & 0x07) == reg); // Register codes match.
}
template <class> friend class AssemblerX86Base;
};
class Address : public Operand {
Address() = delete;
public:
Address(const Address &other) : Operand(other) {}
Address &operator=(const Address &other) {
Operand::operator=(other);
return *this;
}
Address(GPRRegister base, int32_t disp) {
if (disp == 0 && base != RegX8632::Encoded_Reg_ebp) {
SetModRM(0, base);
if (base == RegX8632::Encoded_Reg_esp)
SetSIB(TIMES_1, RegX8632::Encoded_Reg_esp, base);
} else if (Utils::IsInt(8, disp)) {
SetModRM(1, base);
if (base == RegX8632::Encoded_Reg_esp)
SetSIB(TIMES_1, RegX8632::Encoded_Reg_esp, base);
SetDisp8(disp);
} else {
SetModRM(2, base);
if (base == RegX8632::Encoded_Reg_esp)
SetSIB(TIMES_1, RegX8632::Encoded_Reg_esp, base);
SetDisp32(disp);
}
}
Address(GPRRegister index, ScaleFactor scale, int32_t disp) {
assert(index != RegX8632::Encoded_Reg_esp); // Illegal addressing mode.
SetModRM(0, RegX8632::Encoded_Reg_esp);
SetSIB(scale, index, RegX8632::Encoded_Reg_ebp);
SetDisp32(disp);
}
Address(GPRRegister base, GPRRegister index, ScaleFactor scale,
int32_t disp) {
assert(index != RegX8632::Encoded_Reg_esp); // Illegal addressing mode.
if (disp == 0 && base != RegX8632::Encoded_Reg_ebp) {
SetModRM(0, RegX8632::Encoded_Reg_esp);
SetSIB(scale, index, base);
} else if (Utils::IsInt(8, disp)) {
SetModRM(1, RegX8632::Encoded_Reg_esp);
SetSIB(scale, index, base);
SetDisp8(disp);
} else {
SetModRM(2, RegX8632::Encoded_Reg_esp);
SetSIB(scale, index, base);
SetDisp32(disp);
}
}
// AbsoluteTag is a special tag used by clients to create an absolute
// Address.
enum AbsoluteTag { ABSOLUTE };
Address(AbsoluteTag, const uintptr_t Addr) {
SetModRM(0, RegX8632::Encoded_Reg_ebp);
SetDisp32(Addr);
}
// TODO(jpp): remove this.
static Address Absolute(const uintptr_t Addr) {
return Address(ABSOLUTE, Addr);
}
Address(AbsoluteTag, RelocOffsetT Offset, AssemblerFixup *Fixup) {
SetModRM(0, RegX8632::Encoded_Reg_ebp);
// Use the Offset in the displacement for now. If we decide to process
// fixups later, we'll need to patch up the emitted displacement.
SetDisp32(Offset);
SetFixup(Fixup);
}
// TODO(jpp): remove this.
static Address Absolute(RelocOffsetT Offset, AssemblerFixup *Fixup) {
return Address(ABSOLUTE, Offset, Fixup);
}
static Address ofConstPool(Assembler *Asm, const Constant *Imm) {
AssemblerFixup *Fixup = Asm->createFixup(llvm::ELF::R_386_32, Imm);
const RelocOffsetT Offset = 0;
return Address(ABSOLUTE, Offset, Fixup);
}
};
//----------------------------------------------------------------------------
// __ ______ __ __ ______ ______ __ __ __ ______
// /\ \ /\ __ \/\ \ _ \ \/\ ___\/\ == \/\ \/\ "-.\ \/\ ___\
// \ \ \___\ \ \/\ \ \ \/ ".\ \ \ __\\ \ __<\ \ \ \ \-. \ \ \__ \
// \ \_____\ \_____\ \__/".~\_\ \_____\ \_\ \_\ \_\ \_\\"\_\ \_____\
// \/_____/\/_____/\/_/ \/_/\/_____/\/_/ /_/\/_/\/_/ \/_/\/_____/
//
//----------------------------------------------------------------------------
enum InstructionSet {
Begin,
// SSE2 is the PNaCl baseline instruction set.
SSE2 = Begin,
SSE4_1,
End
};
// The maximum number of arguments to pass in XMM registers
static const uint32_t X86_MAX_XMM_ARGS = 4;
// The number of bits in a byte
static const uint32_t X86_CHAR_BIT = 8;
// Stack alignment. This is defined in IceTargetLoweringX8632.cpp because it
// is used as an argument to std::max(), and the default std::less<T> has an
// operator(T const&, T const&) which requires this member to have an address.
static const uint32_t X86_STACK_ALIGNMENT_BYTES;
// Size of the return address on the stack
static const uint32_t X86_RET_IP_SIZE_BYTES = 4;
// The number of different NOP instructions
static const uint32_t X86_NUM_NOP_VARIANTS = 5;
// Value is in bytes. Return Value adjusted to the next highest multiple
// of the stack alignment.
static uint32_t applyStackAlignment(uint32_t Value) {
return Utils::applyAlignment(Value, X86_STACK_ALIGNMENT_BYTES);
}
// Return the type which the elements of the vector have in the X86
// representation of the vector.
static Type getInVectorElementType(Type Ty) {
assert(isVectorType(Ty));
size_t Index = static_cast<size_t>(Ty);
(void)Index;
assert(Index < TableTypeX8632AttributesSize);
return TableTypeX8632Attributes[Ty].InVectorElementType;
}
// Note: The following data structures are defined in
// IceTargetLoweringX8632.cpp.
// The following table summarizes the logic for lowering the fcmp
// instruction. There is one table entry for each of the 16 conditions.
//
// The first four columns describe the case when the operands are
// floating point scalar values. A comment in lowerFcmp() describes the
// lowering template. In the most general case, there is a compare
// followed by two conditional branches, because some fcmp conditions
// don't map to a single x86 conditional branch. However, in many cases
// it is possible to swap the operands in the comparison and have a
// single conditional branch. Since it's quite tedious to validate the
// table by hand, good execution tests are helpful.
//
// The last two columns describe the case when the operands are vectors
// of floating point values. For most fcmp conditions, there is a clear
// mapping to a single x86 cmpps instruction variant. Some fcmp
// conditions require special code to handle and these are marked in the
// table with a Cmpps_Invalid predicate.
static const struct TableFcmpType {
uint32_t Default;
bool SwapScalarOperands;
CondX86::BrCond C1, C2;
bool SwapVectorOperands;
CondX86::CmppsCond Predicate;
} TableFcmp[];
static const size_t TableFcmpSize;
// The following table summarizes the logic for lowering the icmp instruction
// for i32 and narrower types. Each icmp condition has a clear mapping to an
// x86 conditional branch instruction.
static const struct TableIcmp32Type {
CondX86::BrCond Mapping;
} TableIcmp32[];
static const size_t TableIcmp32Size;
// The following table summarizes the logic for lowering the icmp instruction
// for the i64 type. For Eq and Ne, two separate 32-bit comparisons and
// conditional branches are needed. For the other conditions, three separate
// conditional branches are needed.
static const struct TableIcmp64Type {
CondX86::BrCond C1, C2, C3;
} TableIcmp64[];
static const size_t TableIcmp64Size;
static CondX86::BrCond getIcmp32Mapping(InstIcmp::ICond Cond) {
size_t Index = static_cast<size_t>(Cond);
assert(Index < TableIcmp32Size);
return TableIcmp32[Index].Mapping;
}
static const struct TableTypeX8632AttributesType {
Type InVectorElementType;
} TableTypeX8632Attributes[];
static const size_t TableTypeX8632AttributesSize;
};
} // end of namespace X86Internal
namespace X8632 {
using Traits = ::Ice::X86Internal::MachineTraits<TargetX8632>;
} // end of namespace X8632
} // end of namespace Ice
#endif // SUBZERO_SRC_ICETARGETLOWERINGX8632TRAITS_H
...@@ -107,7 +107,9 @@ public: ...@@ -107,7 +107,9 @@ public:
void doLoadOpt(); void doLoadOpt();
bool doBranchOpt(Inst *I, const CfgNode *NextNode) override; bool doBranchOpt(Inst *I, const CfgNode *NextNode) override;
SizeT getNumRegisters() const override { return RegX8632::Reg_NUM; } SizeT getNumRegisters() const override {
return Traits::RegisterSet::Reg_NUM;
}
Variable *getPhysicalRegister(SizeT RegNum, Type Ty = IceType_void) override; Variable *getPhysicalRegister(SizeT RegNum, Type Ty = IceType_void) override;
IceString getRegName(SizeT RegNum, Type Ty) const override; IceString getRegName(SizeT RegNum, Type Ty) const override;
llvm::SmallBitVector getRegisterSet(RegSetMask Include, llvm::SmallBitVector getRegisterSet(RegSetMask Include,
...@@ -117,7 +119,8 @@ public: ...@@ -117,7 +119,8 @@ public:
} }
bool hasFramePointer() const override { return IsEbpBasedFrame; } bool hasFramePointer() const override { return IsEbpBasedFrame; }
SizeT getFrameOrStackReg() const override { SizeT getFrameOrStackReg() const override {
return IsEbpBasedFrame ? RegX8632::Reg_ebp : RegX8632::Reg_esp; return IsEbpBasedFrame ? Traits::RegisterSet::Reg_ebp
: Traits::RegisterSet::Reg_esp;
} }
size_t typeWidthInBytesOnStack(Type Ty) const override { size_t typeWidthInBytesOnStack(Type Ty) const override {
// Round up to the next multiple of 4 bytes. In particular, i1, // Round up to the next multiple of 4 bytes. In particular, i1,
...@@ -148,7 +151,8 @@ public: ...@@ -148,7 +151,8 @@ public:
Operand *hiOperand(Operand *Operand); Operand *hiOperand(Operand *Operand);
void finishArgumentLowering(Variable *Arg, Variable *FramePtr, void finishArgumentLowering(Variable *Arg, Variable *FramePtr,
size_t BasicFrameOffset, size_t &InArgsSizeBytes); size_t BasicFrameOffset, size_t &InArgsSizeBytes);
X8632::Address stackVarToAsmOperand(const Variable *Var) const final; typename Traits::Address
stackVarToAsmOperand(const Variable *Var) const final;
typename Traits::InstructionSet getInstructionSet() const final { typename Traits::InstructionSet getInstructionSet() const final {
return InstructionSet; return InstructionSet;
...@@ -255,6 +259,7 @@ protected: ...@@ -255,6 +259,7 @@ protected:
llvm::SmallVectorImpl<int32_t> &Permutation, llvm::SmallVectorImpl<int32_t> &Permutation,
const llvm::SmallBitVector &ExcludeRegisters) const override; const llvm::SmallBitVector &ExcludeRegisters) const override;
// TODO(jpp): move the helper methods below to the MachineTraits.
// The following are helpers that insert lowered x86 instructions // The following are helpers that insert lowered x86 instructions
// with minimal syntactic overhead, so that the lowering code can // with minimal syntactic overhead, so that the lowering code can
// look as close to assembly as practical. // look as close to assembly as practical.
...@@ -272,7 +277,7 @@ protected: ...@@ -272,7 +277,7 @@ protected:
} }
void _adjust_stack(int32_t Amount) { void _adjust_stack(int32_t Amount) {
Context.insert(InstX8632AdjustStack::create( Context.insert(InstX8632AdjustStack::create(
Func, Amount, getPhysicalRegister(RegX8632::Reg_esp))); Func, Amount, getPhysicalRegister(Traits::RegisterSet::Reg_esp)));
} }
void _addps(Variable *Dest, Operand *Src0) { void _addps(Variable *Dest, Operand *Src0) {
Context.insert(InstX8632Addps::create(Func, Dest, Src0)); Context.insert(InstX8632Addps::create(Func, Dest, Src0));
...@@ -289,7 +294,7 @@ protected: ...@@ -289,7 +294,7 @@ protected:
void _blendvps(Variable *Dest, Operand *Src0, Operand *Src1) { void _blendvps(Variable *Dest, Operand *Src0, Operand *Src1) {
Context.insert(InstX8632Blendvps::create(Func, Dest, Src0, Src1)); Context.insert(InstX8632Blendvps::create(Func, Dest, Src0, Src1));
} }
void _br(CondX86::BrCond Condition, CfgNode *TargetTrue, void _br(typename Traits::Cond::BrCond Condition, CfgNode *TargetTrue,
CfgNode *TargetFalse) { CfgNode *TargetFalse) {
Context.insert( Context.insert(
InstX8632Br::create(Func, TargetTrue, TargetFalse, Condition)); InstX8632Br::create(Func, TargetTrue, TargetFalse, Condition));
...@@ -297,10 +302,10 @@ protected: ...@@ -297,10 +302,10 @@ protected:
void _br(CfgNode *Target) { void _br(CfgNode *Target) {
Context.insert(InstX8632Br::create(Func, Target)); Context.insert(InstX8632Br::create(Func, Target));
} }
void _br(CondX86::BrCond Condition, CfgNode *Target) { void _br(typename Traits::Cond::BrCond Condition, CfgNode *Target) {
Context.insert(InstX8632Br::create(Func, Target, Condition)); Context.insert(InstX8632Br::create(Func, Target, Condition));
} }
void _br(CondX86::BrCond Condition, InstX8632Label *Label) { void _br(typename Traits::Cond::BrCond Condition, InstX8632Label *Label) {
Context.insert(InstX8632Br::create(Func, Label, Condition)); Context.insert(InstX8632Br::create(Func, Label, Condition));
} }
void _bsf(Variable *Dest, Operand *Src0) { void _bsf(Variable *Dest, Operand *Src0) {
...@@ -315,13 +320,15 @@ protected: ...@@ -315,13 +320,15 @@ protected:
void _cbwdq(Variable *Dest, Operand *Src0) { void _cbwdq(Variable *Dest, Operand *Src0) {
Context.insert(InstX8632Cbwdq::create(Func, Dest, Src0)); Context.insert(InstX8632Cbwdq::create(Func, Dest, Src0));
} }
void _cmov(Variable *Dest, Operand *Src0, CondX86::BrCond Condition) { void _cmov(Variable *Dest, Operand *Src0,
typename Traits::Cond::BrCond Condition) {
Context.insert(InstX8632Cmov::create(Func, Dest, Src0, Condition)); Context.insert(InstX8632Cmov::create(Func, Dest, Src0, Condition));
} }
void _cmp(Operand *Src0, Operand *Src1) { void _cmp(Operand *Src0, Operand *Src1) {
Context.insert(InstX8632Icmp::create(Func, Src0, Src1)); Context.insert(InstX8632Icmp::create(Func, Src0, Src1));
} }
void _cmpps(Variable *Dest, Operand *Src0, CondX86::CmppsCond Condition) { void _cmpps(Variable *Dest, Operand *Src0,
typename Traits::Cond::CmppsCond Condition) {
Context.insert(InstX8632Cmpps::create(Func, Dest, Src0, Condition)); Context.insert(InstX8632Cmpps::create(Func, Dest, Src0, Condition));
} }
void _cmpxchg(Operand *DestOrAddr, Variable *Eax, Variable *Desired, void _cmpxchg(Operand *DestOrAddr, Variable *Eax, Variable *Desired,
...@@ -503,7 +510,7 @@ protected: ...@@ -503,7 +510,7 @@ protected:
void _sbb_rmw(OperandX8632Mem *DestSrc0, Operand *Src1) { void _sbb_rmw(OperandX8632Mem *DestSrc0, Operand *Src1) {
Context.insert(InstX8632SbbRMW::create(Func, DestSrc0, Src1)); Context.insert(InstX8632SbbRMW::create(Func, DestSrc0, Src1));
} }
void _setcc(Variable *Dest, CondX86::BrCond Condition) { void _setcc(Variable *Dest, typename Traits::Cond::BrCond Condition) {
Context.insert(InstX8632Setcc::create(Func, Dest, Condition)); Context.insert(InstX8632Setcc::create(Func, Dest, Condition));
} }
void _shl(Variable *Dest, Operand *Src0) { void _shl(Variable *Dest, Operand *Src0) {
......
...@@ -177,7 +177,7 @@ bool BoolFolding<MachineTraits>::hasComplexLowering(const Inst *Instr) { ...@@ -177,7 +177,7 @@ bool BoolFolding<MachineTraits>::hasComplexLowering(const Inst *Instr) {
return true; return true;
case PK_Fcmp: case PK_Fcmp:
return MachineTraits::TableFcmp[llvm::cast<InstFcmp>(Instr)->getCondition()] return MachineTraits::TableFcmp[llvm::cast<InstFcmp>(Instr)->getCondition()]
.C2 != CondX86::Br_None; .C2 != MachineTraits::Cond::Br_None;
} }
} }
...@@ -285,19 +285,19 @@ TargetX86Base<Machine>::TargetX86Base(Cfg *Func) ...@@ -285,19 +285,19 @@ TargetX86Base<Machine>::TargetX86Base(Cfg *Func)
// TODO: Don't initialize IntegerRegisters and friends every time. // TODO: Don't initialize IntegerRegisters and friends every time.
// Instead, initialize in some sort of static initializer for the // Instead, initialize in some sort of static initializer for the
// class. // class.
llvm::SmallBitVector IntegerRegisters(RegX8632::Reg_NUM); llvm::SmallBitVector IntegerRegisters(Traits::RegisterSet::Reg_NUM);
llvm::SmallBitVector IntegerRegistersI8(RegX8632::Reg_NUM); llvm::SmallBitVector IntegerRegistersI8(Traits::RegisterSet::Reg_NUM);
llvm::SmallBitVector FloatRegisters(RegX8632::Reg_NUM); llvm::SmallBitVector FloatRegisters(Traits::RegisterSet::Reg_NUM);
llvm::SmallBitVector VectorRegisters(RegX8632::Reg_NUM); llvm::SmallBitVector VectorRegisters(Traits::RegisterSet::Reg_NUM);
llvm::SmallBitVector InvalidRegisters(RegX8632::Reg_NUM); llvm::SmallBitVector InvalidRegisters(Traits::RegisterSet::Reg_NUM);
ScratchRegs.resize(RegX8632::Reg_NUM); ScratchRegs.resize(Traits::RegisterSet::Reg_NUM);
#define X(val, encode, name, name16, name8, scratch, preserved, stackptr, \ #define X(val, encode, name, name16, name8, scratch, preserved, stackptr, \
frameptr, isI8, isInt, isFP) \ frameptr, isI8, isInt, isFP) \
IntegerRegisters[RegX8632::val] = isInt; \ IntegerRegisters[Traits::RegisterSet::val] = isInt; \
IntegerRegistersI8[RegX8632::val] = isI8; \ IntegerRegistersI8[Traits::RegisterSet::val] = isI8; \
FloatRegisters[RegX8632::val] = isFP; \ FloatRegisters[Traits::RegisterSet::val] = isFP; \
VectorRegisters[RegX8632::val] = isFP; \ VectorRegisters[Traits::RegisterSet::val] = isFP; \
ScratchRegs[RegX8632::val] = scratch; ScratchRegs[Traits::RegisterSet::val] = scratch;
REGX8632_TABLE; REGX8632_TABLE;
#undef X #undef X
TypeToRegisterSet[IceType_void] = InvalidRegisters; TypeToRegisterSet[IceType_void] = InvalidRegisters;
...@@ -740,7 +740,7 @@ Variable *TargetX86Base<Machine>::getPhysicalRegister(SizeT RegNum, Type Ty) { ...@@ -740,7 +740,7 @@ Variable *TargetX86Base<Machine>::getPhysicalRegister(SizeT RegNum, Type Ty) {
if (Ty == IceType_void) if (Ty == IceType_void)
Ty = IceType_i32; Ty = IceType_i32;
if (PhysicalRegisters[Ty].empty()) if (PhysicalRegisters[Ty].empty())
PhysicalRegisters[Ty].resize(RegX8632::Reg_NUM); PhysicalRegisters[Ty].resize(Traits::RegisterSet::Reg_NUM);
assert(RegNum < PhysicalRegisters[Ty].size()); assert(RegNum < PhysicalRegisters[Ty].size());
Variable *Reg = PhysicalRegisters[Ty][RegNum]; Variable *Reg = PhysicalRegisters[Ty][RegNum];
if (Reg == nullptr) { if (Reg == nullptr) {
...@@ -749,7 +749,7 @@ Variable *TargetX86Base<Machine>::getPhysicalRegister(SizeT RegNum, Type Ty) { ...@@ -749,7 +749,7 @@ Variable *TargetX86Base<Machine>::getPhysicalRegister(SizeT RegNum, Type Ty) {
PhysicalRegisters[Ty][RegNum] = Reg; PhysicalRegisters[Ty][RegNum] = Reg;
// Specially mark esp as an "argument" so that it is considered // Specially mark esp as an "argument" so that it is considered
// live upon function entry. // live upon function entry.
if (RegNum == RegX8632::Reg_esp) { if (RegNum == Traits::RegisterSet::Reg_esp) {
Func->addImplicitArg(Reg); Func->addImplicitArg(Reg);
Reg->setIgnoreLiveness(); Reg->setIgnoreLiveness();
} }
...@@ -759,7 +759,7 @@ Variable *TargetX86Base<Machine>::getPhysicalRegister(SizeT RegNum, Type Ty) { ...@@ -759,7 +759,7 @@ Variable *TargetX86Base<Machine>::getPhysicalRegister(SizeT RegNum, Type Ty) {
template <class Machine> template <class Machine>
IceString TargetX86Base<Machine>::getRegName(SizeT RegNum, Type Ty) const { IceString TargetX86Base<Machine>::getRegName(SizeT RegNum, Type Ty) const {
assert(RegNum < RegX8632::Reg_NUM); assert(RegNum < Traits::RegisterSet::Reg_NUM);
static IceString RegNames8[] = { static IceString RegNames8[] = {
#define X(val, encode, name, name16, name8, scratch, preserved, stackptr, \ #define X(val, encode, name, name16, name8, scratch, preserved, stackptr, \
frameptr, isI8, isInt, isFP) \ frameptr, isI8, isInt, isFP) \
...@@ -805,7 +805,7 @@ void TargetX86Base<Machine>::emitVariable(const Variable *Var) const { ...@@ -805,7 +805,7 @@ void TargetX86Base<Machine>::emitVariable(const Variable *Var) const {
} }
template <class Machine> template <class Machine>
X8632::Address typename TargetX86Base<Machine>::Traits::Address
TargetX86Base<Machine>::stackVarToAsmOperand(const Variable *Var) const { TargetX86Base<Machine>::stackVarToAsmOperand(const Variable *Var) const {
if (Var->hasReg()) if (Var->hasReg())
llvm_unreachable("Stack Variable has a register assigned"); llvm_unreachable("Stack Variable has a register assigned");
...@@ -815,7 +815,8 @@ TargetX86Base<Machine>::stackVarToAsmOperand(const Variable *Var) const { ...@@ -815,7 +815,8 @@ TargetX86Base<Machine>::stackVarToAsmOperand(const Variable *Var) const {
int32_t Offset = Var->getStackOffset(); int32_t Offset = Var->getStackOffset();
if (!hasFramePointer()) if (!hasFramePointer())
Offset += getStackAdjustment(); Offset += getStackAdjustment();
return X8632::Address(RegX8632::getEncodedGPR(getFrameOrStackReg()), Offset); return typename Traits::Address(
Traits::RegisterSet::getEncodedGPR(getFrameOrStackReg()), Offset);
} }
template <class Machine> void TargetX86Base<Machine>::lowerArguments() { template <class Machine> void TargetX86Base<Machine>::lowerArguments() {
...@@ -837,7 +838,7 @@ template <class Machine> void TargetX86Base<Machine>::lowerArguments() { ...@@ -837,7 +838,7 @@ template <class Machine> void TargetX86Base<Machine>::lowerArguments() {
// Replace Arg in the argument list with the home register. Then // Replace Arg in the argument list with the home register. Then
// generate an instruction in the prolog to copy the home register // generate an instruction in the prolog to copy the home register
// to the assigned location of Arg. // to the assigned location of Arg.
int32_t RegNum = RegX8632::Reg_xmm0 + NumXmmArgs; int32_t RegNum = Traits::RegisterSet::Reg_xmm0 + NumXmmArgs;
++NumXmmArgs; ++NumXmmArgs;
Variable *RegisterArg = Func->template makeVariable(Ty); Variable *RegisterArg = Func->template makeVariable(Ty);
if (BuildDefs::dump()) if (BuildDefs::dump())
...@@ -997,8 +998,8 @@ template <class Machine> void TargetX86Base<Machine>::addProlog(CfgNode *Node) { ...@@ -997,8 +998,8 @@ template <class Machine> void TargetX86Base<Machine>::addProlog(CfgNode *Node) {
assert((RegsUsed & getRegisterSet(RegSet_FramePointer, RegSet_None)) assert((RegsUsed & getRegisterSet(RegSet_FramePointer, RegSet_None))
.count() == 0); .count() == 0);
PreservedRegsSizeBytes += 4; PreservedRegsSizeBytes += 4;
Variable *ebp = getPhysicalRegister(RegX8632::Reg_ebp); Variable *ebp = getPhysicalRegister(Traits::RegisterSet::Reg_ebp);
Variable *esp = getPhysicalRegister(RegX8632::Reg_esp); Variable *esp = getPhysicalRegister(Traits::RegisterSet::Reg_esp);
_push(ebp); _push(ebp);
_mov(ebp, esp); _mov(ebp, esp);
// Keep ebp live for late-stage liveness analysis // Keep ebp live for late-stage liveness analysis
...@@ -1033,7 +1034,7 @@ template <class Machine> void TargetX86Base<Machine>::addProlog(CfgNode *Node) { ...@@ -1033,7 +1034,7 @@ template <class Machine> void TargetX86Base<Machine>::addProlog(CfgNode *Node) {
// Generate "sub esp, SpillAreaSizeBytes" // Generate "sub esp, SpillAreaSizeBytes"
if (SpillAreaSizeBytes) if (SpillAreaSizeBytes)
_sub(getPhysicalRegister(RegX8632::Reg_esp), _sub(getPhysicalRegister(Traits::RegisterSet::Reg_esp),
Ctx->getConstantInt32(SpillAreaSizeBytes)); Ctx->getConstantInt32(SpillAreaSizeBytes));
Ctx->statsUpdateFrameBytes(SpillAreaSizeBytes); Ctx->statsUpdateFrameBytes(SpillAreaSizeBytes);
...@@ -1117,9 +1118,9 @@ template <class Machine> void TargetX86Base<Machine>::addEpilog(CfgNode *Node) { ...@@ -1117,9 +1118,9 @@ template <class Machine> void TargetX86Base<Machine>::addEpilog(CfgNode *Node) {
Context.init(Node); Context.init(Node);
Context.setInsertPoint(InsertPoint); Context.setInsertPoint(InsertPoint);
Variable *esp = getPhysicalRegister(RegX8632::Reg_esp); Variable *esp = getPhysicalRegister(Traits::RegisterSet::Reg_esp);
if (IsEbpBasedFrame) { if (IsEbpBasedFrame) {
Variable *ebp = getPhysicalRegister(RegX8632::Reg_ebp); Variable *ebp = getPhysicalRegister(Traits::RegisterSet::Reg_ebp);
// For late-stage liveness analysis (e.g. asm-verbose mode), // For late-stage liveness analysis (e.g. asm-verbose mode),
// adding a fake use of esp before the assignment of esp=ebp keeps // adding a fake use of esp before the assignment of esp=ebp keeps
// previous esp adjustments from being dead-code eliminated. // previous esp adjustments from being dead-code eliminated.
...@@ -1137,7 +1138,7 @@ template <class Machine> void TargetX86Base<Machine>::addEpilog(CfgNode *Node) { ...@@ -1137,7 +1138,7 @@ template <class Machine> void TargetX86Base<Machine>::addEpilog(CfgNode *Node) {
getRegisterSet(RegSet_CalleeSave, RegSet_None); getRegisterSet(RegSet_CalleeSave, RegSet_None);
for (SizeT i = 0; i < CalleeSaves.size(); ++i) { for (SizeT i = 0; i < CalleeSaves.size(); ++i) {
SizeT j = CalleeSaves.size() - i - 1; SizeT j = CalleeSaves.size() - i - 1;
if (j == RegX8632::Reg_ebp && IsEbpBasedFrame) if (j == Traits::RegisterSet::Reg_ebp && IsEbpBasedFrame)
continue; continue;
if (CalleeSaves[j] && RegsUsed[j]) { if (CalleeSaves[j] && RegsUsed[j]) {
_pop(getPhysicalRegister(j)); _pop(getPhysicalRegister(j));
...@@ -1155,7 +1156,7 @@ template <class Machine> void TargetX86Base<Machine>::addEpilog(CfgNode *Node) { ...@@ -1155,7 +1156,7 @@ template <class Machine> void TargetX86Base<Machine>::addEpilog(CfgNode *Node) {
// FakeUse <original_ret_operand> // FakeUse <original_ret_operand>
const SizeT BundleSize = const SizeT BundleSize =
1 << Func->template getAssembler<>()->getBundleAlignLog2Bytes(); 1 << Func->template getAssembler<>()->getBundleAlignLog2Bytes();
Variable *T_ecx = makeReg(IceType_i32, RegX8632::Reg_ecx); Variable *T_ecx = makeReg(IceType_i32, Traits::RegisterSet::Reg_ecx);
_pop(T_ecx); _pop(T_ecx);
_bundle_lock(); _bundle_lock();
_and(T_ecx, Ctx->getConstantInt32(~(BundleSize - 1))); _and(T_ecx, Ctx->getConstantInt32(~(BundleSize - 1)));
...@@ -1273,26 +1274,26 @@ template <class Machine> ...@@ -1273,26 +1274,26 @@ template <class Machine>
llvm::SmallBitVector llvm::SmallBitVector
TargetX86Base<Machine>::getRegisterSet(RegSetMask Include, TargetX86Base<Machine>::getRegisterSet(RegSetMask Include,
RegSetMask Exclude) const { RegSetMask Exclude) const {
llvm::SmallBitVector Registers(RegX8632::Reg_NUM); llvm::SmallBitVector Registers(Traits::RegisterSet::Reg_NUM);
#define X(val, encode, name, name16, name8, scratch, preserved, stackptr, \ #define X(val, encode, name, name16, name8, scratch, preserved, stackptr, \
frameptr, isI8, isInt, isFP) \ frameptr, isI8, isInt, isFP) \
if (scratch && (Include & RegSet_CallerSave)) \ if (scratch && (Include & RegSet_CallerSave)) \
Registers[RegX8632::val] = true; \ Registers[Traits::RegisterSet::val] = true; \
if (preserved && (Include & RegSet_CalleeSave)) \ if (preserved && (Include & RegSet_CalleeSave)) \
Registers[RegX8632::val] = true; \ Registers[Traits::RegisterSet::val] = true; \
if (stackptr && (Include & RegSet_StackPointer)) \ if (stackptr && (Include & RegSet_StackPointer)) \
Registers[RegX8632::val] = true; \ Registers[Traits::RegisterSet::val] = true; \
if (frameptr && (Include & RegSet_FramePointer)) \ if (frameptr && (Include & RegSet_FramePointer)) \
Registers[RegX8632::val] = true; \ Registers[Traits::RegisterSet::val] = true; \
if (scratch && (Exclude & RegSet_CallerSave)) \ if (scratch && (Exclude & RegSet_CallerSave)) \
Registers[RegX8632::val] = false; \ Registers[Traits::RegisterSet::val] = false; \
if (preserved && (Exclude & RegSet_CalleeSave)) \ if (preserved && (Exclude & RegSet_CalleeSave)) \
Registers[RegX8632::val] = false; \ Registers[Traits::RegisterSet::val] = false; \
if (stackptr && (Exclude & RegSet_StackPointer)) \ if (stackptr && (Exclude & RegSet_StackPointer)) \
Registers[RegX8632::val] = false; \ Registers[Traits::RegisterSet::val] = false; \
if (frameptr && (Exclude & RegSet_FramePointer)) \ if (frameptr && (Exclude & RegSet_FramePointer)) \
Registers[RegX8632::val] = false; Registers[Traits::RegisterSet::val] = false;
REGX8632_TABLE REGX8632_TABLE
...@@ -1312,7 +1313,7 @@ void TargetX86Base<Machine>::lowerAlloca(const InstAlloca *Inst) { ...@@ -1312,7 +1313,7 @@ void TargetX86Base<Machine>::lowerAlloca(const InstAlloca *Inst) {
NeedsStackAlignment = true; NeedsStackAlignment = true;
// TODO(stichnot): minimize the number of adjustments of esp, etc. // TODO(stichnot): minimize the number of adjustments of esp, etc.
Variable *esp = getPhysicalRegister(RegX8632::Reg_esp); Variable *esp = getPhysicalRegister(Traits::RegisterSet::Reg_esp);
Operand *TotalSize = legalize(Inst->getSizeInBytes()); Operand *TotalSize = legalize(Inst->getSizeInBytes());
Variable *Dest = Inst->getDest(); Variable *Dest = Inst->getDest();
uint32_t AlignmentParam = Inst->getAlignInBytes(); uint32_t AlignmentParam = Inst->getAlignInBytes();
...@@ -1551,8 +1552,8 @@ void TargetX86Base<Machine>::lowerArithmetic(const InstArithmetic *Inst) { ...@@ -1551,8 +1552,8 @@ void TargetX86Base<Machine>::lowerArithmetic(const InstArithmetic *Inst) {
break; break;
case InstArithmetic::Mul: { case InstArithmetic::Mul: {
Variable *T_1 = nullptr, *T_2 = nullptr, *T_3 = nullptr; Variable *T_1 = nullptr, *T_2 = nullptr, *T_3 = nullptr;
Variable *T_4Lo = makeReg(IceType_i32, RegX8632::Reg_eax); Variable *T_4Lo = makeReg(IceType_i32, Traits::RegisterSet::Reg_eax);
Variable *T_4Hi = makeReg(IceType_i32, RegX8632::Reg_edx); Variable *T_4Hi = makeReg(IceType_i32, Traits::RegisterSet::Reg_edx);
// gcc does the following: // gcc does the following:
// a=b*c ==> // a=b*c ==>
// t1 = b.hi; t1 *=(imul) c.lo // t1 = b.hi; t1 *=(imul) c.lo
...@@ -1569,7 +1570,7 @@ void TargetX86Base<Machine>::lowerArithmetic(const InstArithmetic *Inst) { ...@@ -1569,7 +1570,7 @@ void TargetX86Base<Machine>::lowerArithmetic(const InstArithmetic *Inst) {
_imul(T_1, Src1Lo); _imul(T_1, Src1Lo);
_mov(T_2, Src1Hi); _mov(T_2, Src1Hi);
_imul(T_2, Src0Lo); _imul(T_2, Src0Lo);
_mov(T_3, Src0Lo, RegX8632::Reg_eax); _mov(T_3, Src0Lo, Traits::RegisterSet::Reg_eax);
_mul(T_4Lo, T_3, Src1Lo); _mul(T_4Lo, T_3, Src1Lo);
// The mul instruction produces two dest variables, edx:eax. We // The mul instruction produces two dest variables, edx:eax. We
// create a fake definition of edx to account for this. // create a fake definition of edx to account for this.
...@@ -1600,13 +1601,13 @@ void TargetX86Base<Machine>::lowerArithmetic(const InstArithmetic *Inst) { ...@@ -1600,13 +1601,13 @@ void TargetX86Base<Machine>::lowerArithmetic(const InstArithmetic *Inst) {
Constant *BitTest = Ctx->getConstantInt32(0x20); Constant *BitTest = Ctx->getConstantInt32(0x20);
Constant *Zero = Ctx->getConstantZero(IceType_i32); Constant *Zero = Ctx->getConstantZero(IceType_i32);
InstX8632Label *Label = InstX8632Label::create(Func, this); InstX8632Label *Label = InstX8632Label::create(Func, this);
_mov(T_1, Src1Lo, RegX8632::Reg_ecx); _mov(T_1, Src1Lo, Traits::RegisterSet::Reg_ecx);
_mov(T_2, Src0Lo); _mov(T_2, Src0Lo);
_mov(T_3, Src0Hi); _mov(T_3, Src0Hi);
_shld(T_3, T_2, T_1); _shld(T_3, T_2, T_1);
_shl(T_2, T_1); _shl(T_2, T_1);
_test(T_1, BitTest); _test(T_1, BitTest);
_br(CondX86::Br_e, Label); _br(Traits::Cond::Br_e, Label);
// T_2 and T_3 are being assigned again because of the // T_2 and T_3 are being assigned again because of the
// intra-block control flow, so we need the _mov_nonkillable // intra-block control flow, so we need the _mov_nonkillable
// variant to avoid liveness problems. // variant to avoid liveness problems.
...@@ -1635,13 +1636,13 @@ void TargetX86Base<Machine>::lowerArithmetic(const InstArithmetic *Inst) { ...@@ -1635,13 +1636,13 @@ void TargetX86Base<Machine>::lowerArithmetic(const InstArithmetic *Inst) {
Constant *BitTest = Ctx->getConstantInt32(0x20); Constant *BitTest = Ctx->getConstantInt32(0x20);
Constant *Zero = Ctx->getConstantZero(IceType_i32); Constant *Zero = Ctx->getConstantZero(IceType_i32);
InstX8632Label *Label = InstX8632Label::create(Func, this); InstX8632Label *Label = InstX8632Label::create(Func, this);
_mov(T_1, Src1Lo, RegX8632::Reg_ecx); _mov(T_1, Src1Lo, Traits::RegisterSet::Reg_ecx);
_mov(T_2, Src0Lo); _mov(T_2, Src0Lo);
_mov(T_3, Src0Hi); _mov(T_3, Src0Hi);
_shrd(T_2, T_3, T_1); _shrd(T_2, T_3, T_1);
_shr(T_3, T_1); _shr(T_3, T_1);
_test(T_1, BitTest); _test(T_1, BitTest);
_br(CondX86::Br_e, Label); _br(Traits::Cond::Br_e, Label);
// T_2 and T_3 are being assigned again because of the // T_2 and T_3 are being assigned again because of the
// intra-block control flow, so we need the _mov_nonkillable // intra-block control flow, so we need the _mov_nonkillable
// variant to avoid liveness problems. // variant to avoid liveness problems.
...@@ -1670,13 +1671,13 @@ void TargetX86Base<Machine>::lowerArithmetic(const InstArithmetic *Inst) { ...@@ -1670,13 +1671,13 @@ void TargetX86Base<Machine>::lowerArithmetic(const InstArithmetic *Inst) {
Constant *BitTest = Ctx->getConstantInt32(0x20); Constant *BitTest = Ctx->getConstantInt32(0x20);
Constant *SignExtend = Ctx->getConstantInt32(0x1f); Constant *SignExtend = Ctx->getConstantInt32(0x1f);
InstX8632Label *Label = InstX8632Label::create(Func, this); InstX8632Label *Label = InstX8632Label::create(Func, this);
_mov(T_1, Src1Lo, RegX8632::Reg_ecx); _mov(T_1, Src1Lo, Traits::RegisterSet::Reg_ecx);
_mov(T_2, Src0Lo); _mov(T_2, Src0Lo);
_mov(T_3, Src0Hi); _mov(T_3, Src0Hi);
_shrd(T_2, T_3, T_1); _shrd(T_2, T_3, T_1);
_sar(T_3, T_1); _sar(T_3, T_1);
_test(T_1, BitTest); _test(T_1, BitTest);
_br(CondX86::Br_e, Label); _br(Traits::Cond::Br_e, Label);
// T_2 and T_3 are being assigned again because of the // T_2 and T_3 are being assigned again because of the
// intra-block control flow, so T_2 needs the _mov_nonkillable // intra-block control flow, so T_2 needs the _mov_nonkillable
// variant to avoid liveness problems. T_3 doesn't need special // variant to avoid liveness problems. T_3 doesn't need special
...@@ -1747,7 +1748,7 @@ void TargetX86Base<Machine>::lowerArithmetic(const InstArithmetic *Inst) { ...@@ -1747,7 +1748,7 @@ void TargetX86Base<Machine>::lowerArithmetic(const InstArithmetic *Inst) {
bool TypesAreValidForPmull = bool TypesAreValidForPmull =
Dest->getType() == IceType_v4i32 || Dest->getType() == IceType_v8i16; Dest->getType() == IceType_v4i32 || Dest->getType() == IceType_v8i16;
bool InstructionSetIsValidForPmull = bool InstructionSetIsValidForPmull =
Dest->getType() == IceType_v8i16 || InstructionSet >= Machine::SSE4_1; Dest->getType() == IceType_v8i16 || InstructionSet >= Traits::SSE4_1;
if (TypesAreValidForPmull && InstructionSetIsValidForPmull) { if (TypesAreValidForPmull && InstructionSetIsValidForPmull) {
Variable *T = makeReg(Dest->getType()); Variable *T = makeReg(Dest->getType());
_movp(T, Src0); _movp(T, Src0);
...@@ -1874,7 +1875,7 @@ void TargetX86Base<Machine>::lowerArithmetic(const InstArithmetic *Inst) { ...@@ -1874,7 +1875,7 @@ void TargetX86Base<Machine>::lowerArithmetic(const InstArithmetic *Inst) {
// The 8-bit version of imul only allows the form "imul r/m8" // The 8-bit version of imul only allows the form "imul r/m8"
// where T must be in eax. // where T must be in eax.
if (isByteSizedArithType(Dest->getType())) { if (isByteSizedArithType(Dest->getType())) {
_mov(T, Src0, RegX8632::Reg_eax); _mov(T, Src0, Traits::RegisterSet::Reg_eax);
Src1 = legalize(Src1, Legal_Reg | Legal_Mem); Src1 = legalize(Src1, Legal_Reg | Legal_Mem);
} else { } else {
_mov(T, Src0); _mov(T, Src0);
...@@ -1885,21 +1886,21 @@ void TargetX86Base<Machine>::lowerArithmetic(const InstArithmetic *Inst) { ...@@ -1885,21 +1886,21 @@ void TargetX86Base<Machine>::lowerArithmetic(const InstArithmetic *Inst) {
case InstArithmetic::Shl: case InstArithmetic::Shl:
_mov(T, Src0); _mov(T, Src0);
if (!llvm::isa<Constant>(Src1)) if (!llvm::isa<Constant>(Src1))
Src1 = legalizeToVar(Src1, RegX8632::Reg_ecx); Src1 = legalizeToVar(Src1, Traits::RegisterSet::Reg_ecx);
_shl(T, Src1); _shl(T, Src1);
_mov(Dest, T); _mov(Dest, T);
break; break;
case InstArithmetic::Lshr: case InstArithmetic::Lshr:
_mov(T, Src0); _mov(T, Src0);
if (!llvm::isa<Constant>(Src1)) if (!llvm::isa<Constant>(Src1))
Src1 = legalizeToVar(Src1, RegX8632::Reg_ecx); Src1 = legalizeToVar(Src1, Traits::RegisterSet::Reg_ecx);
_shr(T, Src1); _shr(T, Src1);
_mov(Dest, T); _mov(Dest, T);
break; break;
case InstArithmetic::Ashr: case InstArithmetic::Ashr:
_mov(T, Src0); _mov(T, Src0);
if (!llvm::isa<Constant>(Src1)) if (!llvm::isa<Constant>(Src1))
Src1 = legalizeToVar(Src1, RegX8632::Reg_ecx); Src1 = legalizeToVar(Src1, Traits::RegisterSet::Reg_ecx);
_sar(T, Src1); _sar(T, Src1);
_mov(Dest, T); _mov(Dest, T);
break; break;
...@@ -1910,14 +1911,14 @@ void TargetX86Base<Machine>::lowerArithmetic(const InstArithmetic *Inst) { ...@@ -1910,14 +1911,14 @@ void TargetX86Base<Machine>::lowerArithmetic(const InstArithmetic *Inst) {
if (isByteSizedArithType(Dest->getType())) { if (isByteSizedArithType(Dest->getType())) {
Variable *T_ah = nullptr; Variable *T_ah = nullptr;
Constant *Zero = Ctx->getConstantZero(IceType_i8); Constant *Zero = Ctx->getConstantZero(IceType_i8);
_mov(T, Src0, RegX8632::Reg_eax); _mov(T, Src0, Traits::RegisterSet::Reg_eax);
_mov(T_ah, Zero, RegX8632::Reg_ah); _mov(T_ah, Zero, Traits::RegisterSet::Reg_ah);
_div(T, Src1, T_ah); _div(T, Src1, T_ah);
_mov(Dest, T); _mov(Dest, T);
} else { } else {
Constant *Zero = Ctx->getConstantZero(IceType_i32); Constant *Zero = Ctx->getConstantZero(IceType_i32);
_mov(T, Src0, RegX8632::Reg_eax); _mov(T, Src0, Traits::RegisterSet::Reg_eax);
_mov(T_edx, Zero, RegX8632::Reg_edx); _mov(T_edx, Zero, Traits::RegisterSet::Reg_edx);
_div(T, Src1, T_edx); _div(T, Src1, T_edx);
_mov(Dest, T); _mov(Dest, T);
} }
...@@ -1960,13 +1961,13 @@ void TargetX86Base<Machine>::lowerArithmetic(const InstArithmetic *Inst) { ...@@ -1960,13 +1961,13 @@ void TargetX86Base<Machine>::lowerArithmetic(const InstArithmetic *Inst) {
} }
Src1 = legalize(Src1, Legal_Reg | Legal_Mem); Src1 = legalize(Src1, Legal_Reg | Legal_Mem);
if (isByteSizedArithType(Dest->getType())) { if (isByteSizedArithType(Dest->getType())) {
_mov(T, Src0, RegX8632::Reg_eax); _mov(T, Src0, Traits::RegisterSet::Reg_eax);
_cbwdq(T, T); _cbwdq(T, T);
_idiv(T, Src1, T); _idiv(T, Src1, T);
_mov(Dest, T); _mov(Dest, T);
} else { } else {
T_edx = makeReg(IceType_i32, RegX8632::Reg_edx); T_edx = makeReg(IceType_i32, Traits::RegisterSet::Reg_edx);
_mov(T, Src0, RegX8632::Reg_eax); _mov(T, Src0, Traits::RegisterSet::Reg_eax);
_cbwdq(T_edx, T); _cbwdq(T_edx, T);
_idiv(T, Src1, T_edx); _idiv(T, Src1, T_edx);
_mov(Dest, T); _mov(Dest, T);
...@@ -1977,14 +1978,14 @@ void TargetX86Base<Machine>::lowerArithmetic(const InstArithmetic *Inst) { ...@@ -1977,14 +1978,14 @@ void TargetX86Base<Machine>::lowerArithmetic(const InstArithmetic *Inst) {
if (isByteSizedArithType(Dest->getType())) { if (isByteSizedArithType(Dest->getType())) {
Variable *T_ah = nullptr; Variable *T_ah = nullptr;
Constant *Zero = Ctx->getConstantZero(IceType_i8); Constant *Zero = Ctx->getConstantZero(IceType_i8);
_mov(T, Src0, RegX8632::Reg_eax); _mov(T, Src0, Traits::RegisterSet::Reg_eax);
_mov(T_ah, Zero, RegX8632::Reg_ah); _mov(T_ah, Zero, Traits::RegisterSet::Reg_ah);
_div(T_ah, Src1, T); _div(T_ah, Src1, T);
_mov(Dest, T_ah); _mov(Dest, T_ah);
} else { } else {
Constant *Zero = Ctx->getConstantZero(IceType_i32); Constant *Zero = Ctx->getConstantZero(IceType_i32);
_mov(T_edx, Zero, RegX8632::Reg_edx); _mov(T_edx, Zero, Traits::RegisterSet::Reg_edx);
_mov(T, Src0, RegX8632::Reg_eax); _mov(T, Src0, Traits::RegisterSet::Reg_eax);
_div(T_edx, Src1, T); _div(T_edx, Src1, T);
_mov(Dest, T_edx); _mov(Dest, T_edx);
} }
...@@ -2032,15 +2033,15 @@ void TargetX86Base<Machine>::lowerArithmetic(const InstArithmetic *Inst) { ...@@ -2032,15 +2033,15 @@ void TargetX86Base<Machine>::lowerArithmetic(const InstArithmetic *Inst) {
} }
Src1 = legalize(Src1, Legal_Reg | Legal_Mem); Src1 = legalize(Src1, Legal_Reg | Legal_Mem);
if (isByteSizedArithType(Dest->getType())) { if (isByteSizedArithType(Dest->getType())) {
Variable *T_ah = makeReg(IceType_i8, RegX8632::Reg_ah); Variable *T_ah = makeReg(IceType_i8, Traits::RegisterSet::Reg_ah);
_mov(T, Src0, RegX8632::Reg_eax); _mov(T, Src0, Traits::RegisterSet::Reg_eax);
_cbwdq(T, T); _cbwdq(T, T);
Context.insert(InstFakeDef::create(Func, T_ah)); Context.insert(InstFakeDef::create(Func, T_ah));
_idiv(T_ah, Src1, T); _idiv(T_ah, Src1, T);
_mov(Dest, T_ah); _mov(Dest, T_ah);
} else { } else {
T_edx = makeReg(IceType_i32, RegX8632::Reg_edx); T_edx = makeReg(IceType_i32, Traits::RegisterSet::Reg_edx);
_mov(T, Src0, RegX8632::Reg_eax); _mov(T, Src0, Traits::RegisterSet::Reg_eax);
_cbwdq(T_edx, T); _cbwdq(T_edx, T);
_idiv(T_edx, Src1, T); _idiv(T_edx, Src1, T);
_mov(Dest, T_edx); _mov(Dest, T_edx);
...@@ -2156,7 +2157,7 @@ void TargetX86Base<Machine>::lowerBr(const InstBr *Inst) { ...@@ -2156,7 +2157,7 @@ void TargetX86Base<Machine>::lowerBr(const InstBr *Inst) {
Operand *Src0 = legalize(Cond, Legal_Reg | Legal_Mem); Operand *Src0 = legalize(Cond, Legal_Reg | Legal_Mem);
Constant *Zero = Ctx->getConstantZero(IceType_i32); Constant *Zero = Ctx->getConstantZero(IceType_i32);
_cmp(Src0, Zero); _cmp(Src0, Zero);
_br(CondX86::Br_ne, Inst->getTargetTrue(), Inst->getTargetFalse()); _br(Traits::Cond::Br_ne, Inst->getTargetTrue(), Inst->getTargetFalse());
} }
template <class Machine> template <class Machine>
...@@ -2203,7 +2204,8 @@ void TargetX86Base<Machine>::lowerCall(const InstCall *Instr) { ...@@ -2203,7 +2204,8 @@ void TargetX86Base<Machine>::lowerCall(const InstCall *Instr) {
ParameterAreaSizeBytes = ParameterAreaSizeBytes =
Traits::applyStackAlignment(ParameterAreaSizeBytes); Traits::applyStackAlignment(ParameterAreaSizeBytes);
} }
Variable *esp = Func->getTarget()->getPhysicalRegister(RegX8632::Reg_esp); Variable *esp =
Func->getTarget()->getPhysicalRegister(Traits::RegisterSet::Reg_esp);
Constant *Loc = Ctx->getConstantInt32(ParameterAreaSizeBytes); Constant *Loc = Ctx->getConstantInt32(ParameterAreaSizeBytes);
StackArgLocations.push_back(OperandX8632Mem::create(Func, Ty, esp, Loc)); StackArgLocations.push_back(OperandX8632Mem::create(Func, Ty, esp, Loc));
ParameterAreaSizeBytes += typeWidthInBytesOnStack(Arg->getType()); ParameterAreaSizeBytes += typeWidthInBytesOnStack(Arg->getType());
...@@ -2241,7 +2243,8 @@ void TargetX86Base<Machine>::lowerCall(const InstCall *Instr) { ...@@ -2241,7 +2243,8 @@ void TargetX86Base<Machine>::lowerCall(const InstCall *Instr) {
// code, as the memory operand displacements may end up being smaller // code, as the memory operand displacements may end up being smaller
// before any stack adjustment is done. // before any stack adjustment is done.
for (SizeT i = 0, NumXmmArgs = XmmArgs.size(); i < NumXmmArgs; ++i) { for (SizeT i = 0, NumXmmArgs = XmmArgs.size(); i < NumXmmArgs; ++i) {
Variable *Reg = legalizeToVar(XmmArgs[i], RegX8632::Reg_xmm0 + i); Variable *Reg =
legalizeToVar(XmmArgs[i], Traits::RegisterSet::Reg_xmm0 + i);
// Generate a FakeUse of register arguments so that they do not get // Generate a FakeUse of register arguments so that they do not get
// dead code eliminated as a result of the FakeKill of scratch // dead code eliminated as a result of the FakeKill of scratch
// registers after the call. // registers after the call.
...@@ -2264,11 +2267,11 @@ void TargetX86Base<Machine>::lowerCall(const InstCall *Instr) { ...@@ -2264,11 +2267,11 @@ void TargetX86Base<Machine>::lowerCall(const InstCall *Instr) {
case IceType_i8: case IceType_i8:
case IceType_i16: case IceType_i16:
case IceType_i32: case IceType_i32:
ReturnReg = makeReg(Dest->getType(), RegX8632::Reg_eax); ReturnReg = makeReg(Dest->getType(), Traits::RegisterSet::Reg_eax);
break; break;
case IceType_i64: case IceType_i64:
ReturnReg = makeReg(IceType_i32, RegX8632::Reg_eax); ReturnReg = makeReg(IceType_i32, Traits::RegisterSet::Reg_eax);
ReturnRegHi = makeReg(IceType_i32, RegX8632::Reg_edx); ReturnRegHi = makeReg(IceType_i32, Traits::RegisterSet::Reg_edx);
break; break;
case IceType_f32: case IceType_f32:
case IceType_f64: case IceType_f64:
...@@ -2282,7 +2285,7 @@ void TargetX86Base<Machine>::lowerCall(const InstCall *Instr) { ...@@ -2282,7 +2285,7 @@ void TargetX86Base<Machine>::lowerCall(const InstCall *Instr) {
case IceType_v8i16: case IceType_v8i16:
case IceType_v4i32: case IceType_v4i32:
case IceType_v4f32: case IceType_v4f32:
ReturnReg = makeReg(Dest->getType(), RegX8632::Reg_xmm0); ReturnReg = makeReg(Dest->getType(), Traits::RegisterSet::Reg_xmm0);
break; break;
} }
} }
...@@ -2311,7 +2314,8 @@ void TargetX86Base<Machine>::lowerCall(const InstCall *Instr) { ...@@ -2311,7 +2314,8 @@ void TargetX86Base<Machine>::lowerCall(const InstCall *Instr) {
// Add the appropriate offset to esp. The call instruction takes care // Add the appropriate offset to esp. The call instruction takes care
// of resetting the stack offset during emission. // of resetting the stack offset during emission.
if (ParameterAreaSizeBytes) { if (ParameterAreaSizeBytes) {
Variable *esp = Func->getTarget()->getPhysicalRegister(RegX8632::Reg_esp); Variable *esp =
Func->getTarget()->getPhysicalRegister(Traits::RegisterSet::Reg_esp);
_add(esp, Ctx->getConstantInt32(ParameterAreaSizeBytes)); _add(esp, Ctx->getConstantInt32(ParameterAreaSizeBytes));
} }
...@@ -2850,7 +2854,7 @@ void TargetX86Base<Machine>::lowerExtractElement( ...@@ -2850,7 +2854,7 @@ void TargetX86Base<Machine>::lowerExtractElement(
// TODO(wala): Determine the best lowering sequences for each type. // TODO(wala): Determine the best lowering sequences for each type.
bool CanUsePextr = Ty == IceType_v8i16 || Ty == IceType_v8i1 || bool CanUsePextr = Ty == IceType_v8i16 || Ty == IceType_v8i1 ||
InstructionSet >= Machine::SSE4_1; InstructionSet >= Traits::SSE4_1;
if (CanUsePextr && Ty != IceType_v4f32) { if (CanUsePextr && Ty != IceType_v4f32) {
// Use pextrb, pextrw, or pextrd. // Use pextrb, pextrw, or pextrd.
Constant *Mask = Ctx->getConstantInt32(Index); Constant *Mask = Ctx->getConstantInt32(Index);
...@@ -2943,8 +2947,9 @@ void TargetX86Base<Machine>::lowerFcmp(const InstFcmp *Inst) { ...@@ -2943,8 +2947,9 @@ void TargetX86Base<Machine>::lowerFcmp(const InstFcmp *Inst) {
switch (Condition) { switch (Condition) {
default: { default: {
CondX86::CmppsCond Predicate = Traits::TableFcmp[Index].Predicate; typename Traits::Cond::CmppsCond Predicate =
assert(Predicate != CondX86::Cmpps_Invalid); Traits::TableFcmp[Index].Predicate;
assert(Predicate != Traits::Cond::Cmpps_Invalid);
T = makeReg(Src0RM->getType()); T = makeReg(Src0RM->getType());
_movp(T, Src0RM); _movp(T, Src0RM);
_cmpps(T, Src1RM, Predicate); _cmpps(T, Src1RM, Predicate);
...@@ -2954,9 +2959,9 @@ void TargetX86Base<Machine>::lowerFcmp(const InstFcmp *Inst) { ...@@ -2954,9 +2959,9 @@ void TargetX86Base<Machine>::lowerFcmp(const InstFcmp *Inst) {
T = makeReg(Src0RM->getType()); T = makeReg(Src0RM->getType());
Variable *T2 = makeReg(Src0RM->getType()); Variable *T2 = makeReg(Src0RM->getType());
_movp(T, Src0RM); _movp(T, Src0RM);
_cmpps(T, Src1RM, CondX86::Cmpps_neq); _cmpps(T, Src1RM, Traits::Cond::Cmpps_neq);
_movp(T2, Src0RM); _movp(T2, Src0RM);
_cmpps(T2, Src1RM, CondX86::Cmpps_ord); _cmpps(T2, Src1RM, Traits::Cond::Cmpps_ord);
_pand(T, T2); _pand(T, T2);
} break; } break;
case InstFcmp::Ueq: { case InstFcmp::Ueq: {
...@@ -2964,9 +2969,9 @@ void TargetX86Base<Machine>::lowerFcmp(const InstFcmp *Inst) { ...@@ -2964,9 +2969,9 @@ void TargetX86Base<Machine>::lowerFcmp(const InstFcmp *Inst) {
T = makeReg(Src0RM->getType()); T = makeReg(Src0RM->getType());
Variable *T2 = makeReg(Src0RM->getType()); Variable *T2 = makeReg(Src0RM->getType());
_movp(T, Src0RM); _movp(T, Src0RM);
_cmpps(T, Src1RM, CondX86::Cmpps_eq); _cmpps(T, Src1RM, Traits::Cond::Cmpps_eq);
_movp(T2, Src0RM); _movp(T2, Src0RM);
_cmpps(T2, Src1RM, CondX86::Cmpps_unord); _cmpps(T2, Src1RM, Traits::Cond::Cmpps_unord);
_por(T, T2); _por(T, T2);
} break; } break;
} }
...@@ -2995,8 +3000,8 @@ void TargetX86Base<Machine>::lowerFcmp(const InstFcmp *Inst) { ...@@ -2995,8 +3000,8 @@ void TargetX86Base<Machine>::lowerFcmp(const InstFcmp *Inst) {
assert(Index < Traits::TableFcmpSize); assert(Index < Traits::TableFcmpSize);
if (Traits::TableFcmp[Index].SwapScalarOperands) if (Traits::TableFcmp[Index].SwapScalarOperands)
std::swap(Src0, Src1); std::swap(Src0, Src1);
bool HasC1 = (Traits::TableFcmp[Index].C1 != CondX86::Br_None); bool HasC1 = (Traits::TableFcmp[Index].C1 != Traits::Cond::Br_None);
bool HasC2 = (Traits::TableFcmp[Index].C2 != CondX86::Br_None); bool HasC2 = (Traits::TableFcmp[Index].C2 != Traits::Cond::Br_None);
if (HasC1) { if (HasC1) {
Src0 = legalize(Src0); Src0 = legalize(Src0);
Operand *Src1RM = legalize(Src1, Legal_Reg | Legal_Mem); Operand *Src1RM = legalize(Src1, Legal_Reg | Legal_Mem);
...@@ -3154,9 +3159,9 @@ void TargetX86Base<Machine>::lowerIcmp(const InstIcmp *Inst) { ...@@ -3154,9 +3159,9 @@ void TargetX86Base<Machine>::lowerIcmp(const InstIcmp *Inst) {
InstX8632Label *LabelTrue = InstX8632Label::create(Func, this); InstX8632Label *LabelTrue = InstX8632Label::create(Func, this);
_mov(Dest, One); _mov(Dest, One);
_cmp(Src0HiRM, Src1HiRI); _cmp(Src0HiRM, Src1HiRI);
if (Traits::TableIcmp64[Index].C1 != CondX86::Br_None) if (Traits::TableIcmp64[Index].C1 != Traits::Cond::Br_None)
_br(Traits::TableIcmp64[Index].C1, LabelTrue); _br(Traits::TableIcmp64[Index].C1, LabelTrue);
if (Traits::TableIcmp64[Index].C2 != CondX86::Br_None) if (Traits::TableIcmp64[Index].C2 != Traits::Cond::Br_None)
_br(Traits::TableIcmp64[Index].C2, LabelFalse); _br(Traits::TableIcmp64[Index].C2, LabelFalse);
_cmp(Src0LoRM, Src1LoRI); _cmp(Src0LoRM, Src1LoRI);
_br(Traits::TableIcmp64[Index].C3, LabelTrue); _br(Traits::TableIcmp64[Index].C3, LabelTrue);
...@@ -3198,7 +3203,7 @@ void TargetX86Base<Machine>::lowerInsertElement(const InstInsertElement *Inst) { ...@@ -3198,7 +3203,7 @@ void TargetX86Base<Machine>::lowerInsertElement(const InstInsertElement *Inst) {
} }
if (Ty == IceType_v8i16 || Ty == IceType_v8i1 || if (Ty == IceType_v8i16 || Ty == IceType_v8i1 ||
InstructionSet >= Machine::SSE4_1) { InstructionSet >= Traits::SSE4_1) {
// Use insertps, pinsrb, pinsrw, or pinsrd. // Use insertps, pinsrb, pinsrw, or pinsrd.
Operand *ElementRM = Operand *ElementRM =
legalize(ElementToInsertNotLegalized, Legal_Reg | Legal_Mem); legalize(ElementToInsertNotLegalized, Legal_Reg | Legal_Mem);
...@@ -3612,13 +3617,15 @@ void TargetX86Base<Machine>::lowerIntrinsicCall( ...@@ -3612,13 +3617,15 @@ void TargetX86Base<Machine>::lowerIntrinsicCall(
return; return;
} }
case Intrinsics::Stacksave: { case Intrinsics::Stacksave: {
Variable *esp = Func->getTarget()->getPhysicalRegister(RegX8632::Reg_esp); Variable *esp =
Func->getTarget()->getPhysicalRegister(Traits::RegisterSet::Reg_esp);
Variable *Dest = Instr->getDest(); Variable *Dest = Instr->getDest();
_mov(Dest, esp); _mov(Dest, esp);
return; return;
} }
case Intrinsics::Stackrestore: { case Intrinsics::Stackrestore: {
Variable *esp = Func->getTarget()->getPhysicalRegister(RegX8632::Reg_esp); Variable *esp =
Func->getTarget()->getPhysicalRegister(Traits::RegisterSet::Reg_esp);
_mov_nonkillable(esp, Instr->getArg(0)); _mov_nonkillable(esp, Instr->getArg(0));
return; return;
} }
...@@ -3639,10 +3646,10 @@ void TargetX86Base<Machine>::lowerAtomicCmpxchg(Variable *DestPrev, ...@@ -3639,10 +3646,10 @@ void TargetX86Base<Machine>::lowerAtomicCmpxchg(Variable *DestPrev,
if (Expected->getType() == IceType_i64) { if (Expected->getType() == IceType_i64) {
// Reserve the pre-colored registers first, before adding any more // Reserve the pre-colored registers first, before adding any more
// infinite-weight variables from formMemoryOperand's legalization. // infinite-weight variables from formMemoryOperand's legalization.
Variable *T_edx = makeReg(IceType_i32, RegX8632::Reg_edx); Variable *T_edx = makeReg(IceType_i32, Traits::RegisterSet::Reg_edx);
Variable *T_eax = makeReg(IceType_i32, RegX8632::Reg_eax); Variable *T_eax = makeReg(IceType_i32, Traits::RegisterSet::Reg_eax);
Variable *T_ecx = makeReg(IceType_i32, RegX8632::Reg_ecx); Variable *T_ecx = makeReg(IceType_i32, Traits::RegisterSet::Reg_ecx);
Variable *T_ebx = makeReg(IceType_i32, RegX8632::Reg_ebx); Variable *T_ebx = makeReg(IceType_i32, Traits::RegisterSet::Reg_ebx);
_mov(T_eax, loOperand(Expected)); _mov(T_eax, loOperand(Expected));
_mov(T_edx, hiOperand(Expected)); _mov(T_edx, hiOperand(Expected));
_mov(T_ebx, loOperand(Desired)); _mov(T_ebx, loOperand(Desired));
...@@ -3656,7 +3663,7 @@ void TargetX86Base<Machine>::lowerAtomicCmpxchg(Variable *DestPrev, ...@@ -3656,7 +3663,7 @@ void TargetX86Base<Machine>::lowerAtomicCmpxchg(Variable *DestPrev,
_mov(DestHi, T_edx); _mov(DestHi, T_edx);
return; return;
} }
Variable *T_eax = makeReg(Expected->getType(), RegX8632::Reg_eax); Variable *T_eax = makeReg(Expected->getType(), Traits::RegisterSet::Reg_eax);
_mov(T_eax, Expected); _mov(T_eax, Expected);
OperandX8632Mem *Addr = formMemoryOperand(Ptr, Expected->getType()); OperandX8632Mem *Addr = formMemoryOperand(Ptr, Expected->getType());
Variable *DesiredReg = legalizeToVar(Desired); Variable *DesiredReg = legalizeToVar(Desired);
...@@ -3727,7 +3734,8 @@ bool TargetX86Base<Machine>::tryOptimizedCmpxchgCmpBr(Variable *Dest, ...@@ -3727,7 +3734,8 @@ bool TargetX86Base<Machine>::tryOptimizedCmpxchgCmpBr(Variable *Dest,
lowerAssign(PhiAssign); lowerAssign(PhiAssign);
Context.advanceNext(); Context.advanceNext();
} }
_br(CondX86::Br_e, NextBr->getTargetTrue(), NextBr->getTargetFalse()); _br(Traits::Cond::Br_e, NextBr->getTargetTrue(),
NextBr->getTargetFalse());
// Skip over the old compare and branch, by deleting them. // Skip over the old compare and branch, by deleting them.
NextCmp->setDeleted(); NextCmp->setDeleted();
NextBr->setDeleted(); NextBr->setDeleted();
...@@ -3858,13 +3866,13 @@ void TargetX86Base<Machine>::expandAtomicRMWAsCmpxchg(LowerBinOp Op_Lo, ...@@ -3858,13 +3866,13 @@ void TargetX86Base<Machine>::expandAtomicRMWAsCmpxchg(LowerBinOp Op_Lo,
Val = legalize(Val); Val = legalize(Val);
Type Ty = Val->getType(); Type Ty = Val->getType();
if (Ty == IceType_i64) { if (Ty == IceType_i64) {
Variable *T_edx = makeReg(IceType_i32, RegX8632::Reg_edx); Variable *T_edx = makeReg(IceType_i32, Traits::RegisterSet::Reg_edx);
Variable *T_eax = makeReg(IceType_i32, RegX8632::Reg_eax); Variable *T_eax = makeReg(IceType_i32, Traits::RegisterSet::Reg_eax);
OperandX8632Mem *Addr = formMemoryOperand(Ptr, Ty); OperandX8632Mem *Addr = formMemoryOperand(Ptr, Ty);
_mov(T_eax, loOperand(Addr)); _mov(T_eax, loOperand(Addr));
_mov(T_edx, hiOperand(Addr)); _mov(T_edx, hiOperand(Addr));
Variable *T_ecx = makeReg(IceType_i32, RegX8632::Reg_ecx); Variable *T_ecx = makeReg(IceType_i32, Traits::RegisterSet::Reg_ecx);
Variable *T_ebx = makeReg(IceType_i32, RegX8632::Reg_ebx); Variable *T_ebx = makeReg(IceType_i32, Traits::RegisterSet::Reg_ebx);
InstX8632Label *Label = InstX8632Label::create(Func, this); InstX8632Label *Label = InstX8632Label::create(Func, this);
const bool IsXchg8b = Op_Lo == nullptr && Op_Hi == nullptr; const bool IsXchg8b = Op_Lo == nullptr && Op_Hi == nullptr;
if (!IsXchg8b) { if (!IsXchg8b) {
...@@ -3883,7 +3891,7 @@ void TargetX86Base<Machine>::expandAtomicRMWAsCmpxchg(LowerBinOp Op_Lo, ...@@ -3883,7 +3891,7 @@ void TargetX86Base<Machine>::expandAtomicRMWAsCmpxchg(LowerBinOp Op_Lo,
} }
const bool Locked = true; const bool Locked = true;
_cmpxchg8b(Addr, T_edx, T_eax, T_ecx, T_ebx, Locked); _cmpxchg8b(Addr, T_edx, T_eax, T_ecx, T_ebx, Locked);
_br(CondX86::Br_ne, Label); _br(Traits::Cond::Br_ne, Label);
if (!IsXchg8b) { if (!IsXchg8b) {
// If Val is a variable, model the extended live range of Val through // If Val is a variable, model the extended live range of Val through
// the end of the loop, since it will be re-used by the loop. // the end of the loop, since it will be re-used by the loop.
...@@ -3908,7 +3916,7 @@ void TargetX86Base<Machine>::expandAtomicRMWAsCmpxchg(LowerBinOp Op_Lo, ...@@ -3908,7 +3916,7 @@ void TargetX86Base<Machine>::expandAtomicRMWAsCmpxchg(LowerBinOp Op_Lo,
return; return;
} }
OperandX8632Mem *Addr = formMemoryOperand(Ptr, Ty); OperandX8632Mem *Addr = formMemoryOperand(Ptr, Ty);
Variable *T_eax = makeReg(Ty, RegX8632::Reg_eax); Variable *T_eax = makeReg(Ty, Traits::RegisterSet::Reg_eax);
_mov(T_eax, Addr); _mov(T_eax, Addr);
InstX8632Label *Label = InstX8632Label::create(Func, this); InstX8632Label *Label = InstX8632Label::create(Func, this);
Context.insert(Label); Context.insert(Label);
...@@ -3919,7 +3927,7 @@ void TargetX86Base<Machine>::expandAtomicRMWAsCmpxchg(LowerBinOp Op_Lo, ...@@ -3919,7 +3927,7 @@ void TargetX86Base<Machine>::expandAtomicRMWAsCmpxchg(LowerBinOp Op_Lo,
(this->*Op_Lo)(T, Val); (this->*Op_Lo)(T, Val);
const bool Locked = true; const bool Locked = true;
_cmpxchg(Addr, T_eax, T, Locked); _cmpxchg(Addr, T_eax, T, Locked);
_br(CondX86::Br_ne, Label); _br(Traits::Cond::Br_ne, Label);
// If Val is a variable, model the extended live range of Val through // If Val is a variable, model the extended live range of Val through
// the end of the loop, since it will be re-used by the loop. // the end of the loop, since it will be re-used by the loop.
if (Variable *ValVar = llvm::dyn_cast<Variable>(Val)) { if (Variable *ValVar = llvm::dyn_cast<Variable>(Val)) {
...@@ -3983,7 +3991,7 @@ void TargetX86Base<Machine>::lowerCountZeros(bool Cttz, Type Ty, Variable *Dest, ...@@ -3983,7 +3991,7 @@ void TargetX86Base<Machine>::lowerCountZeros(bool Cttz, Type Ty, Variable *Dest,
Constant *SixtyThree = Ctx->getConstantInt32(63); Constant *SixtyThree = Ctx->getConstantInt32(63);
_mov(T_Dest, SixtyThree); _mov(T_Dest, SixtyThree);
} }
_cmov(T_Dest, T, CondX86::Br_ne); _cmov(T_Dest, T, Traits::Cond::Br_ne);
if (!Cttz) { if (!Cttz) {
_xor(T_Dest, ThirtyOne); _xor(T_Dest, ThirtyOne);
} }
...@@ -4004,7 +4012,7 @@ void TargetX86Base<Machine>::lowerCountZeros(bool Cttz, Type Ty, Variable *Dest, ...@@ -4004,7 +4012,7 @@ void TargetX86Base<Machine>::lowerCountZeros(bool Cttz, Type Ty, Variable *Dest,
_xor(T_Dest2, ThirtyOne); _xor(T_Dest2, ThirtyOne);
} }
_test(SecondVar, SecondVar); _test(SecondVar, SecondVar);
_cmov(T_Dest2, T_Dest, CondX86::Br_e); _cmov(T_Dest2, T_Dest, Traits::Cond::Br_e);
_mov(DestLo, T_Dest2); _mov(DestLo, T_Dest2);
_mov(DestHi, Ctx->getConstantZero(IceType_i32)); _mov(DestHi, Ctx->getConstantZero(IceType_i32));
} }
...@@ -4306,16 +4314,18 @@ void TargetX86Base<Machine>::lowerRet(const InstRet *Inst) { ...@@ -4306,16 +4314,18 @@ void TargetX86Base<Machine>::lowerRet(const InstRet *Inst) {
if (Inst->hasRetValue()) { if (Inst->hasRetValue()) {
Operand *Src0 = legalize(Inst->getRetValue()); Operand *Src0 = legalize(Inst->getRetValue());
if (Src0->getType() == IceType_i64) { if (Src0->getType() == IceType_i64) {
Variable *eax = legalizeToVar(loOperand(Src0), RegX8632::Reg_eax); Variable *eax =
Variable *edx = legalizeToVar(hiOperand(Src0), RegX8632::Reg_edx); legalizeToVar(loOperand(Src0), Traits::RegisterSet::Reg_eax);
Variable *edx =
legalizeToVar(hiOperand(Src0), Traits::RegisterSet::Reg_edx);
Reg = eax; Reg = eax;
Context.insert(InstFakeUse::create(Func, edx)); Context.insert(InstFakeUse::create(Func, edx));
} else if (isScalarFloatingType(Src0->getType())) { } else if (isScalarFloatingType(Src0->getType())) {
_fld(Src0); _fld(Src0);
} else if (isVectorType(Src0->getType())) { } else if (isVectorType(Src0->getType())) {
Reg = legalizeToVar(Src0, RegX8632::Reg_xmm0); Reg = legalizeToVar(Src0, Traits::RegisterSet::Reg_xmm0);
} else { } else {
_mov(Reg, Src0, RegX8632::Reg_eax); _mov(Reg, Src0, Traits::RegisterSet::Reg_eax);
} }
} }
// Add a ret instruction even if sandboxing is enabled, because // Add a ret instruction even if sandboxing is enabled, because
...@@ -4327,7 +4337,8 @@ void TargetX86Base<Machine>::lowerRet(const InstRet *Inst) { ...@@ -4327,7 +4337,8 @@ void TargetX86Base<Machine>::lowerRet(const InstRet *Inst) {
// eliminated. TODO: Are there more places where the fake use // eliminated. TODO: Are there more places where the fake use
// should be inserted? E.g. "void f(int n){while(1) g(n);}" may not // should be inserted? E.g. "void f(int n){while(1) g(n);}" may not
// have a ret instruction. // have a ret instruction.
Variable *esp = Func->getTarget()->getPhysicalRegister(RegX8632::Reg_esp); Variable *esp =
Func->getTarget()->getPhysicalRegister(Traits::RegisterSet::Reg_esp);
Context.insert(InstFakeUse::create(Func, esp)); Context.insert(InstFakeUse::create(Func, esp));
} }
...@@ -4344,7 +4355,7 @@ void TargetX86Base<Machine>::lowerSelect(const InstSelect *Inst) { ...@@ -4344,7 +4355,7 @@ void TargetX86Base<Machine>::lowerSelect(const InstSelect *Inst) {
Variable *T = makeReg(SrcTy); Variable *T = makeReg(SrcTy);
Operand *SrcTRM = legalize(SrcT, Legal_Reg | Legal_Mem); Operand *SrcTRM = legalize(SrcT, Legal_Reg | Legal_Mem);
Operand *SrcFRM = legalize(SrcF, Legal_Reg | Legal_Mem); Operand *SrcFRM = legalize(SrcF, Legal_Reg | Legal_Mem);
if (InstructionSet >= Machine::SSE4_1) { if (InstructionSet >= Traits::SSE4_1) {
// TODO(wala): If the condition operand is a constant, use blendps // TODO(wala): If the condition operand is a constant, use blendps
// or pblendw. // or pblendw.
// //
...@@ -4352,7 +4363,7 @@ void TargetX86Base<Machine>::lowerSelect(const InstSelect *Inst) { ...@@ -4352,7 +4363,7 @@ void TargetX86Base<Machine>::lowerSelect(const InstSelect *Inst) {
if (SrcTy == IceType_v4i1 || SrcTy == IceType_v4i32 || if (SrcTy == IceType_v4i1 || SrcTy == IceType_v4i32 ||
SrcTy == IceType_v4f32) { SrcTy == IceType_v4f32) {
Operand *ConditionRM = legalize(Condition, Legal_Reg | Legal_Mem); Operand *ConditionRM = legalize(Condition, Legal_Reg | Legal_Mem);
Variable *xmm0 = makeReg(IceType_v4i32, RegX8632::Reg_xmm0); Variable *xmm0 = makeReg(IceType_v4i32, Traits::RegisterSet::Reg_xmm0);
_movp(xmm0, ConditionRM); _movp(xmm0, ConditionRM);
_psll(xmm0, Ctx->getConstantInt8(31)); _psll(xmm0, Ctx->getConstantInt8(31));
_movp(T, SrcFRM); _movp(T, SrcFRM);
...@@ -4362,7 +4373,7 @@ void TargetX86Base<Machine>::lowerSelect(const InstSelect *Inst) { ...@@ -4362,7 +4373,7 @@ void TargetX86Base<Machine>::lowerSelect(const InstSelect *Inst) {
assert(typeNumElements(SrcTy) == 8 || typeNumElements(SrcTy) == 16); assert(typeNumElements(SrcTy) == 8 || typeNumElements(SrcTy) == 16);
Type SignExtTy = Condition->getType() == IceType_v8i1 ? IceType_v8i16 Type SignExtTy = Condition->getType() == IceType_v8i1 ? IceType_v8i16
: IceType_v16i8; : IceType_v16i8;
Variable *xmm0 = makeReg(SignExtTy, RegX8632::Reg_xmm0); Variable *xmm0 = makeReg(SignExtTy, Traits::RegisterSet::Reg_xmm0);
lowerCast(InstCast::create(Func, InstCast::Sext, xmm0, Condition)); lowerCast(InstCast::create(Func, InstCast::Sext, xmm0, Condition));
_movp(T, SrcFRM); _movp(T, SrcFRM);
_pblendvb(T, SrcTRM, xmm0); _pblendvb(T, SrcTRM, xmm0);
...@@ -4370,7 +4381,7 @@ void TargetX86Base<Machine>::lowerSelect(const InstSelect *Inst) { ...@@ -4370,7 +4381,7 @@ void TargetX86Base<Machine>::lowerSelect(const InstSelect *Inst) {
} }
return; return;
} }
// Lower select without Machine::SSE4.1: // Lower select without Traits::SSE4.1:
// a=d?b:c ==> // a=d?b:c ==>
// if elementtype(d) != i1: // if elementtype(d) != i1:
// d=sext(d); // d=sext(d);
...@@ -4397,7 +4408,7 @@ void TargetX86Base<Machine>::lowerSelect(const InstSelect *Inst) { ...@@ -4397,7 +4408,7 @@ void TargetX86Base<Machine>::lowerSelect(const InstSelect *Inst) {
return; return;
} }
CondX86::BrCond Cond = CondX86::Br_ne; typename Traits::Cond::BrCond Cond = Traits::Cond::Br_ne;
Operand *CmpOpnd0 = nullptr; Operand *CmpOpnd0 = nullptr;
Operand *CmpOpnd1 = nullptr; Operand *CmpOpnd1 = nullptr;
// Handle folding opportunities. // Handle folding opportunities.
...@@ -4542,9 +4553,9 @@ void TargetX86Base<Machine>::lowerSwitch(const InstSwitch *Inst) { ...@@ -4542,9 +4553,9 @@ void TargetX86Base<Machine>::lowerSwitch(const InstSwitch *Inst) {
Constant *ValueHi = Ctx->getConstantInt32(Inst->getValue(I) >> 32); Constant *ValueHi = Ctx->getConstantInt32(Inst->getValue(I) >> 32);
InstX8632Label *Label = InstX8632Label::create(Func, this); InstX8632Label *Label = InstX8632Label::create(Func, this);
_cmp(Src0Lo, ValueLo); _cmp(Src0Lo, ValueLo);
_br(CondX86::Br_ne, Label); _br(Traits::Cond::Br_ne, Label);
_cmp(Src0Hi, ValueHi); _cmp(Src0Hi, ValueHi);
_br(CondX86::Br_e, Inst->getLabel(I)); _br(Traits::Cond::Br_e, Inst->getLabel(I));
Context.insert(Label); Context.insert(Label);
} }
_br(Inst->getLabelDefault()); _br(Inst->getLabelDefault());
...@@ -4559,7 +4570,7 @@ void TargetX86Base<Machine>::lowerSwitch(const InstSwitch *Inst) { ...@@ -4559,7 +4570,7 @@ void TargetX86Base<Machine>::lowerSwitch(const InstSwitch *Inst) {
for (SizeT I = 0; I < NumCases; ++I) { for (SizeT I = 0; I < NumCases; ++I) {
Constant *Value = Ctx->getConstantInt32(Inst->getValue(I)); Constant *Value = Ctx->getConstantInt32(Inst->getValue(I));
_cmp(Src0, Value); _cmp(Src0, Value);
_br(CondX86::Br_e, Inst->getLabel(I)); _br(Traits::Cond::Br_e, Inst->getLabel(I));
} }
_br(Inst->getLabelDefault()); _br(Inst->getLabelDefault());
...@@ -5208,7 +5219,7 @@ void TargetX86Base<Machine>::makeRandomRegisterPermutation( ...@@ -5208,7 +5219,7 @@ void TargetX86Base<Machine>::makeRandomRegisterPermutation(
const llvm::SmallBitVector &ExcludeRegisters) const { const llvm::SmallBitVector &ExcludeRegisters) const {
// TODO(stichnot): Declaring Permutation this way loses type/size // TODO(stichnot): Declaring Permutation this way loses type/size
// information. Fix this in conjunction with the caller-side TODO. // information. Fix this in conjunction with the caller-side TODO.
assert(Permutation.size() >= RegX8632::Reg_NUM); assert(Permutation.size() >= Traits::RegisterSet::Reg_NUM);
// Expected upper bound on the number of registers in a single // Expected upper bound on the number of registers in a single
// equivalence class. For x86-32, this would comprise the 8 XMM // equivalence class. For x86-32, this would comprise the 8 XMM
// registers. This is for performance, not correctness. // registers. This is for performance, not correctness.
...@@ -5223,15 +5234,15 @@ void TargetX86Base<Machine>::makeRandomRegisterPermutation( ...@@ -5223,15 +5234,15 @@ void TargetX86Base<Machine>::makeRandomRegisterPermutation(
// explicitly excluded from shuffling. // explicitly excluded from shuffling.
#define X(val, encode, name, name16, name8, scratch, preserved, stackptr, \ #define X(val, encode, name, name16, name8, scratch, preserved, stackptr, \
frameptr, isI8, isInt, isFP) \ frameptr, isI8, isInt, isFP) \
if (ExcludeRegisters[RegX8632::val]) { \ if (ExcludeRegisters[Traits::RegisterSet::val]) { \
/* val stays the same in the resulting permutation. */ \ /* val stays the same in the resulting permutation. */ \
Permutation[RegX8632::val] = RegX8632::val; \ Permutation[Traits::RegisterSet::val] = Traits::RegisterSet::val; \
++NumPreserved; \ ++NumPreserved; \
} else { \ } else { \
const uint32_t Index = (scratch << 0) | (preserved << 1) | (isI8 << 2) | \ const uint32_t Index = (scratch << 0) | (preserved << 1) | (isI8 << 2) | \
(isInt << 3) | (isFP << 4); \ (isInt << 3) | (isFP << 4); \
/* val is assigned to an equivalence class based on its properties. */ \ /* val is assigned to an equivalence class based on its properties. */ \
EquivalenceClasses[Index].push_back(RegX8632::val); \ EquivalenceClasses[Index].push_back(Traits::RegisterSet::val); \
} }
REGX8632_TABLE REGX8632_TABLE
#undef X #undef X
...@@ -5249,7 +5260,7 @@ void TargetX86Base<Machine>::makeRandomRegisterPermutation( ...@@ -5249,7 +5260,7 @@ void TargetX86Base<Machine>::makeRandomRegisterPermutation(
} }
} }
assert(NumShuffled + NumPreserved == RegX8632::Reg_NUM); assert(NumShuffled + NumPreserved == Traits::RegisterSet::Reg_NUM);
if (Func->isVerbose(IceV_Random)) { if (Func->isVerbose(IceV_Random)) {
OstreamLocker L(Func->getContext()); OstreamLocker L(Func->getContext());
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment