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)
SRCS = \
IceAssembler.cpp \
IceAssemblerX8632.cpp \
IceAssemblerX8664.cpp \
IceBrowserCompileServer.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
// for details. All rights reserved. Use of this source code is governed by a
......@@ -23,906 +23,34 @@
#define SUBZERO_SRC_ICEASSEMBLERX8632_H
#include "IceAssembler.h"
#include "IceConditionCodesX8632.h"
#include "IceAssemblerX86Base.h"
#include "IceDefs.h"
#include "IceOperand.h"
#include "IceRegistersX8632.h"
#include "IceTargetLoweringX8632Traits.h"
#include "IceTypes.h"
#include "IceUtils.h"
namespace Ice {
using RegX8632::GPRRegister;
using RegX8632::XmmRegister;
using RegX8632::ByteRegister;
using RegX8632::X87STRegister;
class TargetX8632;
namespace X8632 {
const int MAX_NOP_SIZE = 8;
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 {
class AssemblerX8632 : public X86Internal::AssemblerX86Base<TargetX8632> {
AssemblerX8632(const AssemblerX8632 &) = delete;
AssemblerX8632 &operator=(const AssemblerX8632 &) = delete;
public:
explicit AssemblerX8632(bool use_far_branches = false)
: Assembler(Asm_X8632) {
// This mode is only needed and implemented for MIPS and ARM.
assert(!use_far_branches);
(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;
}
: X86Internal::AssemblerX86Base<TargetX8632>(Asm_X8632,
use_far_branches) {}
~AssemblerX8632() override = default;
static bool classof(const Assembler *Asm) {
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 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 @@
namespace Ice {
namespace CondX8664 {
// An enum of condition codes used for branches and cmov. The enum value
// should match the value used to encode operands in binary instructions.
enum BrCond {
class CondX8664 {
// An enum of condition codes used for branches and cmov. The enum value
// should match the value used to encode operands in binary instructions.
enum BrCond {
#define X(tag, encode, opp, dump, emit) tag encode,
ICEINSTX8664BR_TABLE
ICEINSTX8664BR_TABLE
#undef X
Br_None
};
Br_None
};
// An enum of condition codes relevant to the CMPPS instruction. The enum
// value should match the value used to encode operands in binary
// instructions.
enum CmppsCond {
// An enum of condition codes relevant to the CMPPS instruction. The enum
// value should match the value used to encode operands in binary
// instructions.
enum CmppsCond {
#define X(tag, emit) tag,
ICEINSTX8664CMPPS_TABLE
ICEINSTX8664CMPPS_TABLE
#undef X
Cmpps_Invalid
Cmpps_Invalid
};
};
} // end of namespace CondX8664
} // end of namespace Ice
#endif // SUBZERO_SRC_ICECONDITIONCODESX8664_H
......@@ -28,12 +28,12 @@ namespace Ice {
namespace {
const struct InstX8632BrAttributes_ {
CondX86::BrCond Opposite;
X8632::Traits::Cond::BrCond Opposite;
const char *DisplayString;
const char *EmitString;
} InstX8632BrAttributes[] = {
#define X(tag, encode, opp, dump, emit) \
{ CondX86::opp, dump, emit } \
{ X8632::Traits::Cond::opp, dump, emit } \
,
ICEINSTX8632BR_TABLE
#undef X
......@@ -85,7 +85,8 @@ const char *InstX8632::getFldString(Type Ty) {
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;
}
......@@ -159,7 +160,8 @@ IceString InstX8632Label::getName(const Cfg *Func) const {
InstX8632Br::InstX8632Br(Cfg *Func, const CfgNode *TargetTrue,
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),
TargetTrue(TargetTrue), TargetFalse(TargetFalse), Label(Label) {}
......@@ -178,7 +180,8 @@ bool InstX8632Br::optimizeBranch(const CfgNode *NextNode) {
return false;
// 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);
setDeleted();
return true;
......@@ -193,7 +196,7 @@ bool InstX8632Br::optimizeBranch(const CfgNode *NextNode) {
// (which was already tested above), then invert the branch
// condition, swap the targets, and set new fallthrough to nullptr.
if (getTargetTrue() == NextNode) {
assert(Condition != CondX86::Br_None);
assert(Condition != X8632::Traits::Cond::Br_None);
Condition = getOppositeCondition(Condition);
TargetTrue = getTargetFalse();
TargetFalse = nullptr;
......@@ -225,7 +228,7 @@ InstX8632Call::InstX8632Call(Cfg *Func, Variable *Dest, Operand *CallTarget)
}
InstX8632Cmov::InstX8632Cmov(Cfg *Func, Variable *Dest, Operand *Source,
CondX86::BrCond Condition)
X8632::Traits::Cond::BrCond Condition)
: InstX8632(Func, InstX8632::Cmov, 2, Dest), Condition(Condition) {
// The final result is either the original Dest, or Source, so mark
// both as sources.
......@@ -234,7 +237,7 @@ InstX8632Cmov::InstX8632Cmov(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) {
addSource(Dest);
addSource(Source);
......@@ -352,7 +355,8 @@ InstX8632Ret::InstX8632Ret(Cfg *Func, Variable *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) {}
InstX8632Xadd::InstX8632Xadd(Cfg *Func, Operand *Dest, Variable *Source,
......@@ -417,7 +421,7 @@ void InstX8632Br::emit(const Cfg *Func) const {
Ostream &Str = Func->getContext()->getStrEmit();
Str << "\t";
if (Condition == CondX86::Br_None) {
if (Condition == X8632::Traits::Cond::Br_None) {
Str << "jmp";
} else {
Str << InstX8632BrAttributes[Condition].EmitString;
......@@ -426,7 +430,7 @@ void InstX8632Br::emit(const Cfg *Func) const {
if (Label) {
Str << "\t" << Label->getName(Func);
} else {
if (Condition == CondX86::Br_None) {
if (Condition == X8632::Traits::Cond::Br_None) {
Str << "\t" << getTargetFalse()->getAsmName();
} else {
Str << "\t" << getTargetTrue()->getAsmName();
......@@ -443,7 +447,7 @@ void InstX8632Br::emitIAS(const Cfg *Func) const {
X8632::Label *L = Asm->GetOrCreateLocalLabel(Label->getNumber());
// In all these cases, local Labels should only be used for Near.
const bool Near = true;
if (Condition == CondX86::Br_None) {
if (Condition == X8632::Traits::Cond::Br_None) {
Asm->jmp(L, Near);
} else {
Asm->j(Condition, L, Near);
......@@ -452,7 +456,7 @@ void InstX8632Br::emitIAS(const Cfg *Func) const {
// Pessimistically assume it's far. This only affects Labels that
// are not Bound.
const bool Near = false;
if (Condition == CondX86::Br_None) {
if (Condition == X8632::Traits::Cond::Br_None) {
X8632::Label *L =
Asm->GetOrCreateCfgNodeLabel(getTargetFalse()->getIndex());
assert(!getTargetTrue());
......@@ -476,7 +480,7 @@ void InstX8632Br::dump(const Cfg *Func) const {
Ostream &Str = Func->getContext()->getStrDump();
Str << "br ";
if (Condition == CondX86::Br_None) {
if (Condition == X8632::Traits::Cond::Br_None) {
Str << "label %"
<< (Label ? Label->getName(Func) : getTargetFalse()->getName());
return;
......@@ -636,8 +640,9 @@ void emitIASOpTyGPR(const Cfg *Func, Type Ty, const Operand *Op,
RegX8632::getEncodedByteRegOrGPR(Ty, Var->getRegNum());
(Asm->*(Emitter.Reg))(Ty, VarReg);
} else {
X8632::Address StackAddr(static_cast<TargetX8632 *>(Func->getTarget())
->stackVarToAsmOperand(Var));
X8632::Traits::Address StackAddr(
static_cast<TargetX8632 *>(Func->getTarget())
->stackVarToAsmOperand(Var));
(Asm->*(Emitter.Addr))(Ty, StackAddr);
}
} else if (const auto Mem = llvm::dyn_cast<OperandX8632Mem>(Op)) {
......@@ -666,7 +671,7 @@ void emitIASRegOpTyGPR(const Cfg *Func, Type Ty, const Variable *Var,
: RegX8632::getEncodedGPR(SrcVar->getRegNum());
(Asm->*(Emitter.GPRGPR))(Ty, VarReg, SrcReg);
} else {
X8632::Address SrcStackAddr =
X8632::Traits::Address SrcStackAddr =
static_cast<TargetX8632 *>(Func->getTarget())
->stackVarToAsmOperand(SrcVar);
(Asm->*(Emitter.GPRAddr))(Ty, VarReg, SrcStackAddr);
......@@ -688,7 +693,8 @@ void emitIASRegOpTyGPR(const Cfg *Func, Type Ty, const Variable *Var,
}
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) {
X8632::AssemblerX8632 *Asm = Func->getAssembler<X8632::AssemblerX8632>();
// Src can only be Reg or Immediate.
......@@ -713,8 +719,9 @@ void emitIASAsAddrOpTyGPR(
const X8632::AssemblerX8632::GPREmitterAddrOp &Emitter) {
if (const auto Op0Var = llvm::dyn_cast<Variable>(Op0)) {
assert(!Op0Var->hasReg());
X8632::Address StackAddr(static_cast<TargetX8632 *>(Func->getTarget())
->stackVarToAsmOperand(Op0Var));
X8632::Traits::Address StackAddr(
static_cast<TargetX8632 *>(Func->getTarget())
->stackVarToAsmOperand(Op0Var));
emitIASAddrOpTyGPR(Func, Ty, StackAddr, Op1, Emitter);
} else if (const auto Op0Mem = llvm::dyn_cast<OperandX8632Mem>(Op0)) {
X8632::AssemblerX8632 *Asm = Func->getAssembler<X8632::AssemblerX8632>();
......@@ -786,7 +793,7 @@ void emitIASXmmShift(const Cfg *Func, Type Ty, const Variable *Var,
RegX8632::getEncodedXmm(SrcVar->getRegNum());
(Asm->*(Emitter.XmmXmm))(Ty, VarReg, SrcReg);
} else {
X8632::Address SrcStackAddr =
X8632::Traits::Address SrcStackAddr =
static_cast<TargetX8632 *>(Func->getTarget())
->stackVarToAsmOperand(SrcVar);
(Asm->*(Emitter.XmmAddr))(Ty, VarReg, SrcStackAddr);
......@@ -813,7 +820,7 @@ void emitIASRegOpTyXMM(const Cfg *Func, Type Ty, const Variable *Var,
RegX8632::getEncodedXmm(SrcVar->getRegNum());
(Asm->*(Emitter.XmmXmm))(Ty, VarReg, SrcReg);
} else {
X8632::Address SrcStackAddr =
X8632::Traits::Address SrcStackAddr =
static_cast<TargetX8632 *>(Func->getTarget())
->stackVarToAsmOperand(SrcVar);
(Asm->*(Emitter.XmmAddr))(Ty, VarReg, SrcStackAddr);
......@@ -823,7 +830,7 @@ void emitIASRegOpTyXMM(const Cfg *Func, Type Ty, const Variable *Var,
(Asm->*(Emitter.XmmAddr))(Ty, VarReg, Mem->toAsmAddress(Asm));
} else if (const auto Imm = llvm::dyn_cast<Constant>(Src)) {
(Asm->*(Emitter.XmmAddr))(Ty, VarReg,
X8632::Address::ofConstPool(Asm, Imm));
X8632::Traits::Address::ofConstPool(Asm, Imm));
} else {
llvm_unreachable("Unexpected operand type");
}
......@@ -842,7 +849,7 @@ void emitIASCastRegOp(
SReg_t SrcReg = srcEnc(SrcVar->getRegNum());
(Asm->*(Emitter.RegReg))(DispatchTy, DestReg, SrcReg);
} else {
X8632::Address SrcStackAddr =
X8632::Traits::Address SrcStackAddr =
static_cast<TargetX8632 *>(Func->getTarget())
->stackVarToAsmOperand(SrcVar);
(Asm->*(Emitter.RegAddr))(DispatchTy, DestReg, SrcStackAddr);
......@@ -871,7 +878,7 @@ void emitIASThreeOpImmOps(
SReg_t SrcReg = srcEnc(SrcVar->getRegNum());
(Asm->*(Emitter.RegRegImm))(DispatchTy, DestReg, SrcReg, Imm);
} else {
X8632::Address SrcStackAddr =
X8632::Traits::Address SrcStackAddr =
static_cast<TargetX8632 *>(Func->getTarget())
->stackVarToAsmOperand(SrcVar);
(Asm->*(Emitter.RegAddrImm))(DispatchTy, DestReg, SrcStackAddr, Imm);
......@@ -896,8 +903,9 @@ void emitIASMovlikeXMM(const Cfg *Func, const Variable *Dest,
(Asm->*(Emitter.XmmXmm))(DestReg,
RegX8632::getEncodedXmm(SrcVar->getRegNum()));
} else {
X8632::Address StackAddr(static_cast<TargetX8632 *>(Func->getTarget())
->stackVarToAsmOperand(SrcVar));
X8632::Traits::Address StackAddr(
static_cast<TargetX8632 *>(Func->getTarget())
->stackVarToAsmOperand(SrcVar));
(Asm->*(Emitter.XmmAddr))(DestReg, StackAddr);
}
} else if (const auto SrcMem = llvm::dyn_cast<OperandX8632Mem>(Src)) {
......@@ -907,8 +915,9 @@ void emitIASMovlikeXMM(const Cfg *Func, const Variable *Dest,
llvm_unreachable("Unexpected operand type");
}
} else {
X8632::Address StackAddr(static_cast<TargetX8632 *>(Func->getTarget())
->stackVarToAsmOperand(Dest));
X8632::Traits::Address StackAddr(
static_cast<TargetX8632 *>(Func->getTarget())
->stackVarToAsmOperand(Dest));
// Src must be a register in this case.
const auto SrcVar = llvm::cast<Variable>(Src);
assert(SrcVar->hasReg());
......@@ -1194,7 +1203,7 @@ template <> void InstX8632Pmull::emit(const Cfg *Func) const {
bool InstructionSetIsValid =
getDest()->getType() == IceType_v8i16 ||
static_cast<TargetX8632 *>(Func->getTarget())->getInstructionSet() >=
TargetX8632::SSE4_1;
X8632::Traits::SSE4_1;
(void)TypesAreValid;
(void)InstructionSetIsValid;
assert(TypesAreValid);
......@@ -1210,7 +1219,7 @@ template <> void InstX8632Pmull::emitIAS(const Cfg *Func) const {
bool InstructionSetIsValid =
Ty == IceType_v8i16 ||
static_cast<TargetX8632 *>(Func->getTarget())->getInstructionSet() >=
TargetX8632::SSE4_1;
X8632::Traits::SSE4_1;
(void)TypesAreValid;
(void)InstructionSetIsValid;
assert(TypesAreValid);
......@@ -1336,13 +1345,13 @@ template <> void InstX8632Blendvps::emit(const Cfg *Func) const {
if (!BuildDefs::dump())
return;
assert(static_cast<TargetX8632 *>(Func->getTarget())->getInstructionSet() >=
TargetX8632::SSE4_1);
X8632::Traits::SSE4_1);
emitVariableBlendInst(Opcode, this, Func);
}
template <> void InstX8632Blendvps::emitIAS(const Cfg *Func) const {
assert(static_cast<TargetX8632 *>(Func->getTarget())->getInstructionSet() >=
TargetX8632::SSE4_1);
X8632::Traits::SSE4_1);
static const X8632::AssemblerX8632::XmmEmitterRegOp Emitter = {
&X8632::AssemblerX8632::blendvps, &X8632::AssemblerX8632::blendvps};
emitIASVariableBlendInst(this, Func, Emitter);
......@@ -1352,13 +1361,13 @@ template <> void InstX8632Pblendvb::emit(const Cfg *Func) const {
if (!BuildDefs::dump())
return;
assert(static_cast<TargetX8632 *>(Func->getTarget())->getInstructionSet() >=
TargetX8632::SSE4_1);
X8632::Traits::SSE4_1);
emitVariableBlendInst(Opcode, this, Func);
}
template <> void InstX8632Pblendvb::emitIAS(const Cfg *Func) const {
assert(static_cast<TargetX8632 *>(Func->getTarget())->getInstructionSet() >=
TargetX8632::SSE4_1);
X8632::Traits::SSE4_1);
static const X8632::AssemblerX8632::XmmEmitterRegOp Emitter = {
&X8632::AssemblerX8632::pblendvb, &X8632::AssemblerX8632::pblendvb};
emitIASVariableBlendInst(this, Func, Emitter);
......@@ -1416,7 +1425,7 @@ template <> void InstX8632Imul::emitIAS(const Cfg *Func) const {
template <> void InstX8632Insertps::emitIAS(const Cfg *Func) const {
assert(getSrcSize() == 3);
assert(static_cast<TargetX8632 *>(Func->getTarget())->getInstructionSet() >=
TargetX8632::SSE4_1);
X8632::Traits::SSE4_1);
const Variable *Dest = getDest();
assert(Dest == getSrc(0));
Type Ty = Dest->getType();
......@@ -1601,7 +1610,7 @@ void InstX8632Cmov::emit(const Cfg *Func) const {
Ostream &Str = Func->getContext()->getStrEmit();
Variable *Dest = getDest();
Str << "\t";
assert(Condition != CondX86::Br_None);
assert(Condition != X8632::Traits::Cond::Br_None);
assert(getDest()->hasReg());
Str << "cmov" << InstX8632BrAttributes[Condition].DisplayString
<< getWidthString(Dest->getType()) << "\t";
......@@ -1611,7 +1620,7 @@ void InstX8632Cmov::emit(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(getSrcSize() == 2);
Operand *Src = getSrc(1);
......@@ -1654,7 +1663,7 @@ void InstX8632Cmpps::emit(const Cfg *Func) const {
return;
Ostream &Str = Func->getContext()->getStrEmit();
assert(getSrcSize() == 2);
assert(Condition < CondX86::Cmpps_Invalid);
assert(Condition < X8632::Traits::Cond::Cmpps_Invalid);
Str << "\t";
Str << "cmp" << InstX8632CmppsAttributes[Condition].EmitString << "ps"
<< "\t";
......@@ -1666,7 +1675,7 @@ void InstX8632Cmpps::emit(const Cfg *Func) const {
void InstX8632Cmpps::emitIAS(const Cfg *Func) const {
X8632::AssemblerX8632 *Asm = Func->getAssembler<X8632::AssemblerX8632>();
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
// are not allowed in PNaCl.
assert(llvm::isa<Variable>(getSrc(1)));
......@@ -1675,8 +1684,9 @@ void InstX8632Cmpps::emitIAS(const Cfg *Func) const {
Asm->cmpps(RegX8632::getEncodedXmm(getDest()->getRegNum()),
RegX8632::getEncodedXmm(SrcVar->getRegNum()), Condition);
} else {
X8632::Address SrcStackAddr = static_cast<TargetX8632 *>(Func->getTarget())
->stackVarToAsmOperand(SrcVar);
X8632::Traits::Address SrcStackAddr =
static_cast<TargetX8632 *>(Func->getTarget())
->stackVarToAsmOperand(SrcVar);
Asm->cmpps(RegX8632::getEncodedXmm(getDest()->getRegNum()), SrcStackAddr,
Condition);
}
......@@ -1686,7 +1696,7 @@ void InstX8632Cmpps::dump(const Cfg *Func) const {
if (!BuildDefs::dump())
return;
Ostream &Str = Func->getContext()->getStrDump();
assert(Condition < CondX86::Cmpps_Invalid);
assert(Condition < X8632::Traits::Cond::Cmpps_Invalid);
dumpDest(Func);
Str << " = cmp" << InstX8632CmppsAttributes[Condition].EmitString << "ps"
<< "\t";
......@@ -1713,7 +1723,7 @@ void InstX8632Cmpxchg::emitIAS(const Cfg *Func) const {
Type Ty = getSrc(0)->getType();
const auto Mem = llvm::cast<OperandX8632Mem>(getSrc(0));
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));
assert(VarReg->hasReg());
const RegX8632::GPRRegister Reg =
......@@ -1749,7 +1759,7 @@ void InstX8632Cmpxchg8b::emitIAS(const Cfg *Func) const {
X8632::AssemblerX8632 *Asm = Func->getAssembler<X8632::AssemblerX8632>();
const auto Mem = llvm::cast<OperandX8632Mem>(getSrc(0));
assert(Mem->getSegmentRegister() == OperandX8632Mem::DefaultSegment);
const X8632::Address Addr = Mem->toAsmAddress(Asm);
const X8632::Traits::Address Addr = Mem->toAsmAddress(Asm);
Asm->cmpxchg8b(Addr, Locked);
}
......@@ -2027,8 +2037,9 @@ void InstX8632Store::emitIAS(const Cfg *Func) const {
X8632::AssemblerX8632 *Asm = Func->getAssembler<X8632::AssemblerX8632>();
if (const auto DestVar = llvm::dyn_cast<Variable>(Dest)) {
assert(!DestVar->hasReg());
X8632::Address StackAddr(static_cast<TargetX8632 *>(Func->getTarget())
->stackVarToAsmOperand(DestVar));
X8632::Traits::Address StackAddr(
static_cast<TargetX8632 *>(Func->getTarget())
->stackVarToAsmOperand(DestVar));
Asm->movss(DestTy, StackAddr, SrcReg);
} else {
const auto DestMem = llvm::cast<OperandX8632Mem>(Dest);
......@@ -2217,8 +2228,9 @@ template <> void InstX8632Mov::emitIAS(const Cfg *Func) const {
} else {
// Dest must be Stack and Src *could* be a register. Use Src's type
// to decide on the emitters.
X8632::Address StackAddr(static_cast<TargetX8632 *>(Func->getTarget())
->stackVarToAsmOperand(Dest));
X8632::Traits::Address StackAddr(
static_cast<TargetX8632 *>(Func->getTarget())
->stackVarToAsmOperand(Dest));
if (isScalarFloatingType(SrcTy)) {
// Src must be a register.
const auto SrcVar = llvm::cast<Variable>(Src);
......@@ -2251,8 +2263,9 @@ template <> void InstX8632Movd::emitIAS(const Cfg *Func) const {
if (SrcVar->hasReg()) {
Asm->movd(DestReg, RegX8632::getEncodedGPR(SrcVar->getRegNum()));
} else {
X8632::Address StackAddr(static_cast<TargetX8632 *>(Func->getTarget())
->stackVarToAsmOperand(SrcVar));
X8632::Traits::Address StackAddr(
static_cast<TargetX8632 *>(Func->getTarget())
->stackVarToAsmOperand(SrcVar));
Asm->movd(DestReg, StackAddr);
}
} else {
......@@ -2263,8 +2276,9 @@ template <> void InstX8632Movd::emitIAS(const Cfg *Func) const {
if (Dest->hasReg()) {
Asm->movd(RegX8632::getEncodedGPR(Dest->getRegNum()), SrcReg);
} else {
X8632::Address StackAddr(static_cast<TargetX8632 *>(Func->getTarget())
->stackVarToAsmOperand(Dest));
X8632::Traits::Address StackAddr(
static_cast<TargetX8632 *>(Func->getTarget())
->stackVarToAsmOperand(Dest));
Asm->movd(StackAddr, SrcReg);
}
}
......@@ -2414,20 +2428,22 @@ void InstX8632Fld::emitIAS(const Cfg *Func) const {
// temporary stack slot.
X8632::Immediate Width(typeWidthInBytes(Ty));
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->fld(Ty, StackSlot);
Asm->add(IceType_i32, RegX8632::Encoded_Reg_esp, Width);
} else {
X8632::Address StackAddr(static_cast<TargetX8632 *>(Func->getTarget())
->stackVarToAsmOperand(Var));
X8632::Traits::Address StackAddr(
static_cast<TargetX8632 *>(Func->getTarget())
->stackVarToAsmOperand(Var));
Asm->fld(Ty, StackAddr);
}
} else if (const auto Mem = llvm::dyn_cast<OperandX8632Mem>(Src)) {
assert(Mem->getSegmentRegister() == OperandX8632Mem::DefaultSegment);
Asm->fld(Ty, Mem->toAsmAddress(Asm));
} 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 {
llvm_unreachable("Unexpected operand type");
}
......@@ -2489,8 +2505,9 @@ void InstX8632Fstp::emitIAS(const Cfg *Func) const {
}
Type Ty = Dest->getType();
if (!Dest->hasReg()) {
X8632::Address StackAddr(static_cast<TargetX8632 *>(Func->getTarget())
->stackVarToAsmOperand(Dest));
X8632::Traits::Address StackAddr(
static_cast<TargetX8632 *>(Func->getTarget())
->stackVarToAsmOperand(Dest));
Asm->fstp(Ty, StackAddr);
} else {
// Dest is a physical (xmm) register, so st(0) needs to go through
......@@ -2499,7 +2516,8 @@ void InstX8632Fstp::emitIAS(const Cfg *Func) const {
// the stack slot.
X8632::Immediate Width(typeWidthInBytes(Ty));
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->movss(Ty, RegX8632::getEncodedXmm(Dest->getRegNum()), StackSlot);
Asm->add(IceType_i32, RegX8632::Encoded_Reg_esp, Width);
......@@ -2541,7 +2559,7 @@ template <> void InstX8632Pextr::emit(const Cfg *Func) const {
assert(getSrc(0)->getType() == IceType_v8i16 ||
getSrc(0)->getType() == IceType_v8i1 ||
static_cast<TargetX8632 *>(Func->getTarget())->getInstructionSet() >=
TargetX8632::SSE4_1);
X8632::Traits::SSE4_1);
Str << "\t" << Opcode << TypeX8632Attributes[getSrc(0)->getType()].PackString
<< "\t";
getSrc(1)->emit(Func);
......@@ -2563,7 +2581,7 @@ template <> void InstX8632Pextr::emitIAS(const Cfg *Func) const {
Type DispatchTy = Dest->getType();
assert(DispatchTy == IceType_i16 ||
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
// a memory dest, but we aren't using it. For uniformity, just restrict
// them all to have a register dest for now.
......@@ -2587,7 +2605,7 @@ template <> void InstX8632Pinsr::emit(const Cfg *Func) const {
assert(getDest()->getType() == IceType_v8i16 ||
getDest()->getType() == IceType_v8i1 ||
static_cast<TargetX8632 *>(Func->getTarget())->getInstructionSet() >=
TargetX8632::SSE4_1);
X8632::Traits::SSE4_1);
Str << "\t" << Opcode << TypeX8632Attributes[getDest()->getType()].PackString
<< "\t";
getSrc(2)->emit(Func);
......@@ -2615,7 +2633,7 @@ template <> void InstX8632Pinsr::emitIAS(const Cfg *Func) const {
Type DispatchTy = Src0->getType();
assert(DispatchTy == IceType_i16 ||
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
// from the encodings for ByteRegs overlapping the encodings for r32),
// but we have to trust the regalloc to not choose "ah", where it
......@@ -2796,7 +2814,7 @@ void InstX8632Setcc::emit(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(getSrcSize() == 0);
X8632::AssemblerX8632 *Asm = Func->getAssembler<X8632::AssemblerX8632>();
......@@ -2835,7 +2853,7 @@ void InstX8632Xadd::emitIAS(const Cfg *Func) const {
Type Ty = getSrc(0)->getType();
const auto Mem = llvm::cast<OperandX8632Mem>(getSrc(0));
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));
assert(VarReg->hasReg());
const RegX8632::GPRRegister Reg =
......@@ -2871,7 +2889,7 @@ void InstX8632Xchg::emitIAS(const Cfg *Func) const {
Type Ty = getSrc(0)->getType();
const auto Mem = llvm::cast<OperandX8632Mem>(getSrc(0));
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));
assert(VarReg->hasReg());
const RegX8632::GPRRegister Reg =
......@@ -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;
AssemblerFixup *Fixup = nullptr;
// Determine the offset (is it relocatable?)
......@@ -3000,29 +3018,31 @@ X8632::Address OperandX8632Mem::toAsmAddress(Assembler *Asm) const {
// Now convert to the various possible forms.
if (getBase() && getIndex()) {
return X8632::Address(RegX8632::getEncodedGPR(getBase()->getRegNum()),
RegX8632::getEncodedGPR(getIndex()->getRegNum()),
X8632::ScaleFactor(getShift()), Disp);
return X8632::Traits::Address(
RegX8632::getEncodedGPR(getBase()->getRegNum()),
RegX8632::getEncodedGPR(getIndex()->getRegNum()),
X8632::Traits::ScaleFactor(getShift()), Disp);
} else if (getBase()) {
return X8632::Address(RegX8632::getEncodedGPR(getBase()->getRegNum()),
Disp);
return X8632::Traits::Address(
RegX8632::getEncodedGPR(getBase()->getRegNum()), Disp);
} else if (getIndex()) {
return X8632::Address(RegX8632::getEncodedGPR(getIndex()->getRegNum()),
X8632::ScaleFactor(getShift()), Disp);
return X8632::Traits::Address(
RegX8632::getEncodedGPR(getIndex()->getRegNum()),
X8632::Traits::ScaleFactor(getShift()), Disp);
} else if (Fixup) {
return X8632::Address::Absolute(Disp, Fixup);
return X8632::Traits::Address::Absolute(Disp, Fixup);
} 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());
const TargetLowering *Target = Func->getTarget();
int32_t Offset =
Var->getStackOffset() + Target->getStackAdjustment() + getOffset();
return X8632::Address(RegX8632::getEncodedGPR(Target->getFrameOrStackReg()),
Offset);
return X8632::Traits::Address(
RegX8632::getEncodedGPR(Target->getFrameOrStackReg()), Offset);
}
void VariableSplit::emit(const Cfg *Func) const {
......
......@@ -22,6 +22,7 @@
#include "IceInst.h"
#include "IceInstX8632.def"
#include "IceOperand.h"
#include "IceTargetLoweringX8632Traits.h"
namespace Ice {
......@@ -76,7 +77,7 @@ public:
uint16_t getShift() const { return Shift; }
SegmentRegisters getSegmentRegister() const { return SegmentReg; }
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;
using OperandX8632::dump;
void dump(const Cfg *Func, Ostream &Str) const override;
......@@ -122,7 +123,7 @@ public:
}
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;
using OperandX8632::dump;
void dump(const Cfg *Func, Ostream &Str) const override;
......@@ -279,7 +280,8 @@ public:
static const char *getWidthString(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;
// Shared emit routines for common forms of instructions.
......@@ -428,8 +430,9 @@ class InstX8632Br : public InstX8632 {
public:
// Create a conditional branch to a node.
static InstX8632Br *create(Cfg *Func, CfgNode *TargetTrue,
CfgNode *TargetFalse, CondX86::BrCond Condition) {
assert(Condition != CondX86::Br_None);
CfgNode *TargetFalse,
X8632::Traits::Cond::BrCond Condition) {
assert(Condition != X8632::Traits::Cond::Br_None);
const InstX8632Label *NoLabel = nullptr;
return new (Func->allocate<InstX8632Br>())
InstX8632Br(Func, TargetTrue, TargetFalse, NoLabel, Condition);
......@@ -438,15 +441,15 @@ public:
static InstX8632Br *create(Cfg *Func, CfgNode *Target) {
const CfgNode *NoCondTarget = nullptr;
const InstX8632Label *NoLabel = nullptr;
return new (Func->allocate<InstX8632Br>())
InstX8632Br(Func, NoCondTarget, Target, NoLabel, CondX86::Br_None);
return new (Func->allocate<InstX8632Br>()) InstX8632Br(
Func, NoCondTarget, Target, NoLabel, X8632::Traits::Cond::Br_None);
}
// Create a non-terminator conditional branch to a node, with a
// fallthrough to the next instruction in the current node. This is
// used for switch lowering.
static InstX8632Br *create(Cfg *Func, CfgNode *Target,
CondX86::BrCond Condition) {
assert(Condition != CondX86::Br_None);
X8632::Traits::Cond::BrCond Condition) {
assert(Condition != X8632::Traits::Cond::Br_None);
const CfgNode *NoUncondTarget = nullptr;
const InstX8632Label *NoLabel = nullptr;
return new (Func->allocate<InstX8632Br>())
......@@ -455,7 +458,7 @@ public:
// Create a conditional intra-block branch (or unconditional, if
// Condition==Br_None) to a label in the current block.
static InstX8632Br *create(Cfg *Func, InstX8632Label *Label,
CondX86::BrCond Condition) {
X8632::Traits::Cond::BrCond Condition) {
const CfgNode *NoCondTarget = nullptr;
const CfgNode *NoUncondTarget = nullptr;
return new (Func->allocate<InstX8632Br>())
......@@ -475,7 +478,7 @@ public:
return Sum;
}
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;
void emit(const Cfg *Func) const override;
......@@ -485,9 +488,10 @@ public:
private:
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 *TargetFalse;
const InstX8632Label *Label; // Intra-block branch target
......@@ -1256,7 +1260,7 @@ class InstX8632Cmov : public InstX8632 {
public:
static InstX8632Cmov *create(Cfg *Func, Variable *Dest, Operand *Source,
CondX86::BrCond Cond) {
X8632::Traits::Cond::BrCond Cond) {
return new (Func->allocate<InstX8632Cmov>())
InstX8632Cmov(Func, Dest, Source, Cond);
}
......@@ -1267,9 +1271,9 @@ public:
private:
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
......@@ -1281,7 +1285,7 @@ class InstX8632Cmpps : public InstX8632 {
public:
static InstX8632Cmpps *create(Cfg *Func, Variable *Dest, Operand *Source,
CondX86::CmppsCond Condition) {
X8632::Traits::Cond::CmppsCond Condition) {
return new (Func->allocate<InstX8632Cmpps>())
InstX8632Cmpps(Func, Dest, Source, Condition);
}
......@@ -1292,9 +1296,9 @@ public:
private:
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>
......@@ -1670,7 +1674,7 @@ class InstX8632Setcc : public InstX8632 {
public:
static InstX8632Setcc *create(Cfg *Func, Variable *Dest,
CondX86::BrCond Cond) {
X8632::Traits::Cond::BrCond Cond) {
return new (Func->allocate<InstX8632Setcc>())
InstX8632Setcc(Func, Dest, Cond);
}
......@@ -1680,9 +1684,9 @@ public:
static bool classof(const Inst *Inst) { return isClassof(Inst, Setcc); }
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
......
......@@ -20,93 +20,92 @@
namespace Ice {
namespace RegX8632 {
// An enum of every register. The enum value may not match the encoding
// used to binary encode register operands in instructions.
enum AllRegisters {
class RegX8632 {
public:
// An enum of every register. The enum value may not match the encoding
// used to binary encode register operands in instructions.
enum AllRegisters {
#define X(val, encode, name, name16, name8, scratch, preserved, stackptr, \
frameptr, isI8, isInt, isFP) \
val,
REGX8632_TABLE
REGX8632_TABLE
#undef X
Reg_NUM,
Reg_NUM,
#define X(val, init) val init,
REGX8632_TABLE_BOUNDS
REGX8632_TABLE_BOUNDS
#undef X
};
};
// An enum of GPR Registers. The enum value does match the encoding used
// to binary encode register operands in instructions.
enum GPRRegister {
// An enum of GPR Registers. The enum value does match the encoding used
// to binary encode register operands in instructions.
enum GPRRegister {
#define X(val, encode, name, name16, name8, scratch, preserved, stackptr, \
frameptr, isI8, isInt, isFP) \
Encoded_##val encode,
REGX8632_GPR_TABLE
REGX8632_GPR_TABLE
#undef X
Encoded_Not_GPR = -1
};
Encoded_Not_GPR = -1
};
// An enum of XMM Registers. The enum value does match the encoding used
// to binary encode register operands in instructions.
enum XmmRegister {
// An enum of XMM Registers. The enum value does match the encoding used
// to binary encode register operands in instructions.
enum XmmRegister {
#define X(val, encode, name, name16, name8, scratch, preserved, stackptr, \
frameptr, isI8, isInt, isFP) \
Encoded_##val encode,
REGX8632_XMM_TABLE
REGX8632_XMM_TABLE
#undef X
Encoded_Not_Xmm = -1
};
Encoded_Not_Xmm = -1
};
// An enum of Byte Registers. The enum value does match the encoding used
// to binary encode register operands in instructions.
enum ByteRegister {
// An enum of Byte Registers. The enum value does match the encoding used
// to binary encode register operands in instructions.
enum ByteRegister {
#define X(val, encode) Encoded_##val encode,
REGX8632_BYTEREG_TABLE
REGX8632_BYTEREG_TABLE
#undef X
Encoded_Not_ByteReg = -1
};
Encoded_Not_ByteReg = -1
};
// An enum of X87 Stack Registers. The enum value does match the encoding used
// to binary encode register operands in instructions.
enum X87STRegister {
// An enum of X87 Stack Registers. The enum value does match the encoding used
// to binary encode register operands in instructions.
enum X87STRegister {
#define X(val, encode, name) Encoded_##val encode,
X87ST_REGX8632_TABLE
X87ST_REGX8632_TABLE
#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
#endif // SUBZERO_SRC_ICEREGISTERSX8632_H
......@@ -20,79 +20,78 @@
namespace Ice {
namespace RegX8664 {
// An enum of every register. The enum value may not match the encoding
// used to binary encode register operands in instructions.
enum AllRegisters {
class RegX8664 {
public:
// An enum of every register. The enum value may not match the encoding
// used to binary encode register operands in instructions.
enum AllRegisters {
#define X(val, encode, name64, name, name16, name8, scratch, preserved, \
stackptr, frameptr, isInt, isFP) \
val,
REGX8664_TABLE
REGX8664_TABLE
#undef X
Reg_NUM,
Reg_NUM,
#define X(val, init) val init,
REGX8664_TABLE_BOUNDS
REGX8664_TABLE_BOUNDS
#undef X
};
};
// An enum of GPR Registers. The enum value does match the encoding used
// to binary encode register operands in instructions.
enum GPRRegister {
// An enum of GPR Registers. The enum value does match the encoding used
// to binary encode register operands in instructions.
enum GPRRegister {
#define X(val, encode, name64, name, name16, name8, scratch, preserved, \
stackptr, frameptr, isInt, isFP) \
Encoded_##val encode,
REGX8664_GPR_TABLE
REGX8664_GPR_TABLE
#undef X
Encoded_Not_GPR = -1
};
Encoded_Not_GPR = -1
};
// An enum of XMM Registers. The enum value does match the encoding used
// to binary encode register operands in instructions.
enum XmmRegister {
// An enum of XMM Registers. The enum value does match the encoding used
// to binary encode register operands in instructions.
enum XmmRegister {
#define X(val, encode, name64, name, name16, name8, scratch, preserved, \
stackptr, frameptr, isInt, isFP) \
Encoded_##val encode,
REGX8664_XMM_TABLE
REGX8664_XMM_TABLE
#undef X
Encoded_Not_Xmm = -1
};
Encoded_Not_Xmm = -1
};
// An enum of Byte Registers. The enum value does match the encoding used
// to binary encode register operands in instructions.
enum ByteRegister {
// An enum of Byte Registers. The enum value does match the encoding used
// to binary encode register operands in instructions.
enum ByteRegister {
#define X(val, encode) Encoded_##val encode,
REGX8664_BYTEREG_TABLE
REGX8664_BYTEREG_TABLE
#undef X
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);
}
Encoded_Not_ByteReg = -1
};
static inline XmmRegister getEncodedXmm(int32_t RegNum) {
assert(Reg_XMM_First <= RegNum && RegNum <= Reg_XMM_Last);
return XmmRegister(RegNum - Reg_XMM_First);
}
static inline GPRRegister getEncodedGPR(int32_t RegNum) {
assert(Reg_GPR_First <= RegNum && RegNum <= Reg_GPR_Last);
return GPRRegister(RegNum - Reg_GPR_First);
}
static inline ByteRegister getEncodedByteReg(int32_t RegNum) {
// In x86-64, AH is not encodable when the REX prefix is used; the same
// encoding is used for spl. Therefore, ah needs special handling.
if (RegNum == Reg_ah)
return Encoded_Reg_spl;
return ByteRegister(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 GPRRegister getEncodedByteRegOrGPR(Type Ty, int32_t RegNum) {
if (isByteSizedType(Ty))
return GPRRegister(getEncodedByteReg(RegNum));
else
return getEncodedGPR(RegNum);
}
static inline ByteRegister getEncodedByteReg(int32_t RegNum) {
// In x86-64, AH is not encodable when the REX prefix is used; the same
// encoding is used for spl. Therefore, ah needs special handling.
if (RegNum == Reg_ah)
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
......
......@@ -2,6 +2,9 @@
//
// 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
......@@ -12,100 +15,19 @@
#include "IceTargetLoweringX8632.h"
#include "IceTargetLoweringX8632Traits.h"
#include "IceTargetLoweringX86Base.h"
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
MachineTraits<TargetX8632>::TableFcmp[] = {
#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
#undef X
......@@ -117,7 +39,7 @@ const size_t MachineTraits<TargetX8632>::TableFcmpSize =
const MachineTraits<TargetX8632>::TableIcmp32Type
MachineTraits<TargetX8632>::TableIcmp32[] = {
#define X(val, C_32, C1_64, C2_64, C3_64) \
{ CondX86::C_32 } \
{ X8632::Traits::Cond::C_32 } \
,
ICMPX8632_TABLE
#undef X
......@@ -129,7 +51,10 @@ const size_t MachineTraits<TargetX8632>::TableIcmp32Size =
const MachineTraits<TargetX8632>::TableIcmp64Type
MachineTraits<TargetX8632>::TableIcmp64[] = {
#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
#undef X
......@@ -151,6 +76,7 @@ const size_t MachineTraits<TargetX8632>::TableTypeX8632AttributesSize =
llvm::array_lengthof(TableTypeX8632Attributes);
const uint32_t MachineTraits<TargetX8632>::X86_STACK_ALIGNMENT_BYTES = 16;
} // end of namespace X86Internal
TargetX8632 *TargetX8632::create(Cfg *Func) {
......
......@@ -21,6 +21,7 @@
#include "IceInstX8632.h"
#include "IceRegistersX8632.h"
#include "IceTargetLowering.h"
#include "IceTargetLoweringX8632Traits.h"
namespace Ice {
......@@ -30,16 +31,11 @@ class TargetX8632 : public TargetLowering {
TargetX8632 &operator=(const TargetX8632 &) = delete;
public:
enum X86InstructionSet {
Begin,
// SSE2 is the PNaCl baseline instruction set.
SSE2 = Begin,
SSE4_1,
End
};
using X86InstructionSet = X8632::Traits::InstructionSet;
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;
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:
void doLoadOpt();
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;
IceString getRegName(SizeT RegNum, Type Ty) const override;
llvm::SmallBitVector getRegisterSet(RegSetMask Include,
......@@ -117,7 +119,8 @@ public:
}
bool hasFramePointer() const override { return IsEbpBasedFrame; }
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 {
// Round up to the next multiple of 4 bytes. In particular, i1,
......@@ -148,7 +151,8 @@ public:
Operand *hiOperand(Operand *Operand);
void finishArgumentLowering(Variable *Arg, Variable *FramePtr,
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 {
return InstructionSet;
......@@ -255,6 +259,7 @@ protected:
llvm::SmallVectorImpl<int32_t> &Permutation,
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
// with minimal syntactic overhead, so that the lowering code can
// look as close to assembly as practical.
......@@ -272,7 +277,7 @@ protected:
}
void _adjust_stack(int32_t Amount) {
Context.insert(InstX8632AdjustStack::create(
Func, Amount, getPhysicalRegister(RegX8632::Reg_esp)));
Func, Amount, getPhysicalRegister(Traits::RegisterSet::Reg_esp)));
}
void _addps(Variable *Dest, Operand *Src0) {
Context.insert(InstX8632Addps::create(Func, Dest, Src0));
......@@ -289,7 +294,7 @@ protected:
void _blendvps(Variable *Dest, Operand *Src0, Operand *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) {
Context.insert(
InstX8632Br::create(Func, TargetTrue, TargetFalse, Condition));
......@@ -297,10 +302,10 @@ protected:
void _br(CfgNode *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));
}
void _br(CondX86::BrCond Condition, InstX8632Label *Label) {
void _br(typename Traits::Cond::BrCond Condition, InstX8632Label *Label) {
Context.insert(InstX8632Br::create(Func, Label, Condition));
}
void _bsf(Variable *Dest, Operand *Src0) {
......@@ -315,13 +320,15 @@ protected:
void _cbwdq(Variable *Dest, Operand *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));
}
void _cmp(Operand *Src0, Operand *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));
}
void _cmpxchg(Operand *DestOrAddr, Variable *Eax, Variable *Desired,
......@@ -503,7 +510,7 @@ protected:
void _sbb_rmw(OperandX8632Mem *DestSrc0, Operand *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));
}
void _shl(Variable *Dest, Operand *Src0) {
......
......@@ -177,7 +177,7 @@ bool BoolFolding<MachineTraits>::hasComplexLowering(const Inst *Instr) {
return true;
case PK_Fcmp:
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)
// TODO: Don't initialize IntegerRegisters and friends every time.
// Instead, initialize in some sort of static initializer for the
// class.
llvm::SmallBitVector IntegerRegisters(RegX8632::Reg_NUM);
llvm::SmallBitVector IntegerRegistersI8(RegX8632::Reg_NUM);
llvm::SmallBitVector FloatRegisters(RegX8632::Reg_NUM);
llvm::SmallBitVector VectorRegisters(RegX8632::Reg_NUM);
llvm::SmallBitVector InvalidRegisters(RegX8632::Reg_NUM);
ScratchRegs.resize(RegX8632::Reg_NUM);
llvm::SmallBitVector IntegerRegisters(Traits::RegisterSet::Reg_NUM);
llvm::SmallBitVector IntegerRegistersI8(Traits::RegisterSet::Reg_NUM);
llvm::SmallBitVector FloatRegisters(Traits::RegisterSet::Reg_NUM);
llvm::SmallBitVector VectorRegisters(Traits::RegisterSet::Reg_NUM);
llvm::SmallBitVector InvalidRegisters(Traits::RegisterSet::Reg_NUM);
ScratchRegs.resize(Traits::RegisterSet::Reg_NUM);
#define X(val, encode, name, name16, name8, scratch, preserved, stackptr, \
frameptr, isI8, isInt, isFP) \
IntegerRegisters[RegX8632::val] = isInt; \
IntegerRegistersI8[RegX8632::val] = isI8; \
FloatRegisters[RegX8632::val] = isFP; \
VectorRegisters[RegX8632::val] = isFP; \
ScratchRegs[RegX8632::val] = scratch;
IntegerRegisters[Traits::RegisterSet::val] = isInt; \
IntegerRegistersI8[Traits::RegisterSet::val] = isI8; \
FloatRegisters[Traits::RegisterSet::val] = isFP; \
VectorRegisters[Traits::RegisterSet::val] = isFP; \
ScratchRegs[Traits::RegisterSet::val] = scratch;
REGX8632_TABLE;
#undef X
TypeToRegisterSet[IceType_void] = InvalidRegisters;
......@@ -740,7 +740,7 @@ Variable *TargetX86Base<Machine>::getPhysicalRegister(SizeT RegNum, Type Ty) {
if (Ty == IceType_void)
Ty = IceType_i32;
if (PhysicalRegisters[Ty].empty())
PhysicalRegisters[Ty].resize(RegX8632::Reg_NUM);
PhysicalRegisters[Ty].resize(Traits::RegisterSet::Reg_NUM);
assert(RegNum < PhysicalRegisters[Ty].size());
Variable *Reg = PhysicalRegisters[Ty][RegNum];
if (Reg == nullptr) {
......@@ -749,7 +749,7 @@ Variable *TargetX86Base<Machine>::getPhysicalRegister(SizeT RegNum, Type Ty) {
PhysicalRegisters[Ty][RegNum] = Reg;
// Specially mark esp as an "argument" so that it is considered
// live upon function entry.
if (RegNum == RegX8632::Reg_esp) {
if (RegNum == Traits::RegisterSet::Reg_esp) {
Func->addImplicitArg(Reg);
Reg->setIgnoreLiveness();
}
......@@ -759,7 +759,7 @@ Variable *TargetX86Base<Machine>::getPhysicalRegister(SizeT RegNum, Type Ty) {
template <class Machine>
IceString TargetX86Base<Machine>::getRegName(SizeT RegNum, Type Ty) const {
assert(RegNum < RegX8632::Reg_NUM);
assert(RegNum < Traits::RegisterSet::Reg_NUM);
static IceString RegNames8[] = {
#define X(val, encode, name, name16, name8, scratch, preserved, stackptr, \
frameptr, isI8, isInt, isFP) \
......@@ -805,7 +805,7 @@ void TargetX86Base<Machine>::emitVariable(const Variable *Var) const {
}
template <class Machine>
X8632::Address
typename TargetX86Base<Machine>::Traits::Address
TargetX86Base<Machine>::stackVarToAsmOperand(const Variable *Var) const {
if (Var->hasReg())
llvm_unreachable("Stack Variable has a register assigned");
......@@ -815,7 +815,8 @@ TargetX86Base<Machine>::stackVarToAsmOperand(const Variable *Var) const {
int32_t Offset = Var->getStackOffset();
if (!hasFramePointer())
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() {
......@@ -837,7 +838,7 @@ template <class Machine> void TargetX86Base<Machine>::lowerArguments() {
// Replace Arg in the argument list with the home register. Then
// generate an instruction in the prolog to copy the home register
// to the assigned location of Arg.
int32_t RegNum = RegX8632::Reg_xmm0 + NumXmmArgs;
int32_t RegNum = Traits::RegisterSet::Reg_xmm0 + NumXmmArgs;
++NumXmmArgs;
Variable *RegisterArg = Func->template makeVariable(Ty);
if (BuildDefs::dump())
......@@ -997,8 +998,8 @@ template <class Machine> void TargetX86Base<Machine>::addProlog(CfgNode *Node) {
assert((RegsUsed & getRegisterSet(RegSet_FramePointer, RegSet_None))
.count() == 0);
PreservedRegsSizeBytes += 4;
Variable *ebp = getPhysicalRegister(RegX8632::Reg_ebp);
Variable *esp = getPhysicalRegister(RegX8632::Reg_esp);
Variable *ebp = getPhysicalRegister(Traits::RegisterSet::Reg_ebp);
Variable *esp = getPhysicalRegister(Traits::RegisterSet::Reg_esp);
_push(ebp);
_mov(ebp, esp);
// Keep ebp live for late-stage liveness analysis
......@@ -1033,7 +1034,7 @@ template <class Machine> void TargetX86Base<Machine>::addProlog(CfgNode *Node) {
// Generate "sub esp, SpillAreaSizeBytes"
if (SpillAreaSizeBytes)
_sub(getPhysicalRegister(RegX8632::Reg_esp),
_sub(getPhysicalRegister(Traits::RegisterSet::Reg_esp),
Ctx->getConstantInt32(SpillAreaSizeBytes));
Ctx->statsUpdateFrameBytes(SpillAreaSizeBytes);
......@@ -1117,9 +1118,9 @@ template <class Machine> void TargetX86Base<Machine>::addEpilog(CfgNode *Node) {
Context.init(Node);
Context.setInsertPoint(InsertPoint);
Variable *esp = getPhysicalRegister(RegX8632::Reg_esp);
Variable *esp = getPhysicalRegister(Traits::RegisterSet::Reg_esp);
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),
// adding a fake use of esp before the assignment of esp=ebp keeps
// previous esp adjustments from being dead-code eliminated.
......@@ -1137,7 +1138,7 @@ template <class Machine> void TargetX86Base<Machine>::addEpilog(CfgNode *Node) {
getRegisterSet(RegSet_CalleeSave, RegSet_None);
for (SizeT i = 0; i < CalleeSaves.size(); ++i) {
SizeT j = CalleeSaves.size() - i - 1;
if (j == RegX8632::Reg_ebp && IsEbpBasedFrame)
if (j == Traits::RegisterSet::Reg_ebp && IsEbpBasedFrame)
continue;
if (CalleeSaves[j] && RegsUsed[j]) {
_pop(getPhysicalRegister(j));
......@@ -1155,7 +1156,7 @@ template <class Machine> void TargetX86Base<Machine>::addEpilog(CfgNode *Node) {
// FakeUse <original_ret_operand>
const SizeT BundleSize =
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);
_bundle_lock();
_and(T_ecx, Ctx->getConstantInt32(~(BundleSize - 1)));
......@@ -1273,26 +1274,26 @@ template <class Machine>
llvm::SmallBitVector
TargetX86Base<Machine>::getRegisterSet(RegSetMask Include,
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, \
frameptr, isI8, isInt, isFP) \
if (scratch && (Include & RegSet_CallerSave)) \
Registers[RegX8632::val] = true; \
Registers[Traits::RegisterSet::val] = true; \
if (preserved && (Include & RegSet_CalleeSave)) \
Registers[RegX8632::val] = true; \
Registers[Traits::RegisterSet::val] = true; \
if (stackptr && (Include & RegSet_StackPointer)) \
Registers[RegX8632::val] = true; \
Registers[Traits::RegisterSet::val] = true; \
if (frameptr && (Include & RegSet_FramePointer)) \
Registers[RegX8632::val] = true; \
Registers[Traits::RegisterSet::val] = true; \
if (scratch && (Exclude & RegSet_CallerSave)) \
Registers[RegX8632::val] = false; \
Registers[Traits::RegisterSet::val] = false; \
if (preserved && (Exclude & RegSet_CalleeSave)) \
Registers[RegX8632::val] = false; \
Registers[Traits::RegisterSet::val] = false; \
if (stackptr && (Exclude & RegSet_StackPointer)) \
Registers[RegX8632::val] = false; \
Registers[Traits::RegisterSet::val] = false; \
if (frameptr && (Exclude & RegSet_FramePointer)) \
Registers[RegX8632::val] = false;
Registers[Traits::RegisterSet::val] = false;
REGX8632_TABLE
......@@ -1312,7 +1313,7 @@ void TargetX86Base<Machine>::lowerAlloca(const InstAlloca *Inst) {
NeedsStackAlignment = true;
// 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());
Variable *Dest = Inst->getDest();
uint32_t AlignmentParam = Inst->getAlignInBytes();
......@@ -1551,8 +1552,8 @@ void TargetX86Base<Machine>::lowerArithmetic(const InstArithmetic *Inst) {
break;
case InstArithmetic::Mul: {
Variable *T_1 = nullptr, *T_2 = nullptr, *T_3 = nullptr;
Variable *T_4Lo = makeReg(IceType_i32, RegX8632::Reg_eax);
Variable *T_4Hi = makeReg(IceType_i32, RegX8632::Reg_edx);
Variable *T_4Lo = makeReg(IceType_i32, Traits::RegisterSet::Reg_eax);
Variable *T_4Hi = makeReg(IceType_i32, Traits::RegisterSet::Reg_edx);
// gcc does the following:
// a=b*c ==>
// t1 = b.hi; t1 *=(imul) c.lo
......@@ -1569,7 +1570,7 @@ void TargetX86Base<Machine>::lowerArithmetic(const InstArithmetic *Inst) {
_imul(T_1, Src1Lo);
_mov(T_2, Src1Hi);
_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);
// The mul instruction produces two dest variables, edx:eax. We
// create a fake definition of edx to account for this.
......@@ -1600,13 +1601,13 @@ void TargetX86Base<Machine>::lowerArithmetic(const InstArithmetic *Inst) {
Constant *BitTest = Ctx->getConstantInt32(0x20);
Constant *Zero = Ctx->getConstantZero(IceType_i32);
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_3, Src0Hi);
_shld(T_3, T_2, T_1);
_shl(T_2, T_1);
_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
// intra-block control flow, so we need the _mov_nonkillable
// variant to avoid liveness problems.
......@@ -1635,13 +1636,13 @@ void TargetX86Base<Machine>::lowerArithmetic(const InstArithmetic *Inst) {
Constant *BitTest = Ctx->getConstantInt32(0x20);
Constant *Zero = Ctx->getConstantZero(IceType_i32);
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_3, Src0Hi);
_shrd(T_2, T_3, T_1);
_shr(T_3, T_1);
_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
// intra-block control flow, so we need the _mov_nonkillable
// variant to avoid liveness problems.
......@@ -1670,13 +1671,13 @@ void TargetX86Base<Machine>::lowerArithmetic(const InstArithmetic *Inst) {
Constant *BitTest = Ctx->getConstantInt32(0x20);
Constant *SignExtend = Ctx->getConstantInt32(0x1f);
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_3, Src0Hi);
_shrd(T_2, T_3, T_1);
_sar(T_3, T_1);
_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
// intra-block control flow, so T_2 needs the _mov_nonkillable
// variant to avoid liveness problems. T_3 doesn't need special
......@@ -1747,7 +1748,7 @@ void TargetX86Base<Machine>::lowerArithmetic(const InstArithmetic *Inst) {
bool TypesAreValidForPmull =
Dest->getType() == IceType_v4i32 || Dest->getType() == IceType_v8i16;
bool InstructionSetIsValidForPmull =
Dest->getType() == IceType_v8i16 || InstructionSet >= Machine::SSE4_1;
Dest->getType() == IceType_v8i16 || InstructionSet >= Traits::SSE4_1;
if (TypesAreValidForPmull && InstructionSetIsValidForPmull) {
Variable *T = makeReg(Dest->getType());
_movp(T, Src0);
......@@ -1874,7 +1875,7 @@ void TargetX86Base<Machine>::lowerArithmetic(const InstArithmetic *Inst) {
// The 8-bit version of imul only allows the form "imul r/m8"
// where T must be in eax.
if (isByteSizedArithType(Dest->getType())) {
_mov(T, Src0, RegX8632::Reg_eax);
_mov(T, Src0, Traits::RegisterSet::Reg_eax);
Src1 = legalize(Src1, Legal_Reg | Legal_Mem);
} else {
_mov(T, Src0);
......@@ -1885,21 +1886,21 @@ void TargetX86Base<Machine>::lowerArithmetic(const InstArithmetic *Inst) {
case InstArithmetic::Shl:
_mov(T, Src0);
if (!llvm::isa<Constant>(Src1))
Src1 = legalizeToVar(Src1, RegX8632::Reg_ecx);
Src1 = legalizeToVar(Src1, Traits::RegisterSet::Reg_ecx);
_shl(T, Src1);
_mov(Dest, T);
break;
case InstArithmetic::Lshr:
_mov(T, Src0);
if (!llvm::isa<Constant>(Src1))
Src1 = legalizeToVar(Src1, RegX8632::Reg_ecx);
Src1 = legalizeToVar(Src1, Traits::RegisterSet::Reg_ecx);
_shr(T, Src1);
_mov(Dest, T);
break;
case InstArithmetic::Ashr:
_mov(T, Src0);
if (!llvm::isa<Constant>(Src1))
Src1 = legalizeToVar(Src1, RegX8632::Reg_ecx);
Src1 = legalizeToVar(Src1, Traits::RegisterSet::Reg_ecx);
_sar(T, Src1);
_mov(Dest, T);
break;
......@@ -1910,14 +1911,14 @@ void TargetX86Base<Machine>::lowerArithmetic(const InstArithmetic *Inst) {
if (isByteSizedArithType(Dest->getType())) {
Variable *T_ah = nullptr;
Constant *Zero = Ctx->getConstantZero(IceType_i8);
_mov(T, Src0, RegX8632::Reg_eax);
_mov(T_ah, Zero, RegX8632::Reg_ah);
_mov(T, Src0, Traits::RegisterSet::Reg_eax);
_mov(T_ah, Zero, Traits::RegisterSet::Reg_ah);
_div(T, Src1, T_ah);
_mov(Dest, T);
} else {
Constant *Zero = Ctx->getConstantZero(IceType_i32);
_mov(T, Src0, RegX8632::Reg_eax);
_mov(T_edx, Zero, RegX8632::Reg_edx);
_mov(T, Src0, Traits::RegisterSet::Reg_eax);
_mov(T_edx, Zero, Traits::RegisterSet::Reg_edx);
_div(T, Src1, T_edx);
_mov(Dest, T);
}
......@@ -1960,13 +1961,13 @@ void TargetX86Base<Machine>::lowerArithmetic(const InstArithmetic *Inst) {
}
Src1 = legalize(Src1, Legal_Reg | Legal_Mem);
if (isByteSizedArithType(Dest->getType())) {
_mov(T, Src0, RegX8632::Reg_eax);
_mov(T, Src0, Traits::RegisterSet::Reg_eax);
_cbwdq(T, T);
_idiv(T, Src1, T);
_mov(Dest, T);
} else {
T_edx = makeReg(IceType_i32, RegX8632::Reg_edx);
_mov(T, Src0, RegX8632::Reg_eax);
T_edx = makeReg(IceType_i32, Traits::RegisterSet::Reg_edx);
_mov(T, Src0, Traits::RegisterSet::Reg_eax);
_cbwdq(T_edx, T);
_idiv(T, Src1, T_edx);
_mov(Dest, T);
......@@ -1977,14 +1978,14 @@ void TargetX86Base<Machine>::lowerArithmetic(const InstArithmetic *Inst) {
if (isByteSizedArithType(Dest->getType())) {
Variable *T_ah = nullptr;
Constant *Zero = Ctx->getConstantZero(IceType_i8);
_mov(T, Src0, RegX8632::Reg_eax);
_mov(T_ah, Zero, RegX8632::Reg_ah);
_mov(T, Src0, Traits::RegisterSet::Reg_eax);
_mov(T_ah, Zero, Traits::RegisterSet::Reg_ah);
_div(T_ah, Src1, T);
_mov(Dest, T_ah);
} else {
Constant *Zero = Ctx->getConstantZero(IceType_i32);
_mov(T_edx, Zero, RegX8632::Reg_edx);
_mov(T, Src0, RegX8632::Reg_eax);
_mov(T_edx, Zero, Traits::RegisterSet::Reg_edx);
_mov(T, Src0, Traits::RegisterSet::Reg_eax);
_div(T_edx, Src1, T);
_mov(Dest, T_edx);
}
......@@ -2032,15 +2033,15 @@ void TargetX86Base<Machine>::lowerArithmetic(const InstArithmetic *Inst) {
}
Src1 = legalize(Src1, Legal_Reg | Legal_Mem);
if (isByteSizedArithType(Dest->getType())) {
Variable *T_ah = makeReg(IceType_i8, RegX8632::Reg_ah);
_mov(T, Src0, RegX8632::Reg_eax);
Variable *T_ah = makeReg(IceType_i8, Traits::RegisterSet::Reg_ah);
_mov(T, Src0, Traits::RegisterSet::Reg_eax);
_cbwdq(T, T);
Context.insert(InstFakeDef::create(Func, T_ah));
_idiv(T_ah, Src1, T);
_mov(Dest, T_ah);
} else {
T_edx = makeReg(IceType_i32, RegX8632::Reg_edx);
_mov(T, Src0, RegX8632::Reg_eax);
T_edx = makeReg(IceType_i32, Traits::RegisterSet::Reg_edx);
_mov(T, Src0, Traits::RegisterSet::Reg_eax);
_cbwdq(T_edx, T);
_idiv(T_edx, Src1, T);
_mov(Dest, T_edx);
......@@ -2156,7 +2157,7 @@ void TargetX86Base<Machine>::lowerBr(const InstBr *Inst) {
Operand *Src0 = legalize(Cond, Legal_Reg | Legal_Mem);
Constant *Zero = Ctx->getConstantZero(IceType_i32);
_cmp(Src0, Zero);
_br(CondX86::Br_ne, Inst->getTargetTrue(), Inst->getTargetFalse());
_br(Traits::Cond::Br_ne, Inst->getTargetTrue(), Inst->getTargetFalse());
}
template <class Machine>
......@@ -2203,7 +2204,8 @@ void TargetX86Base<Machine>::lowerCall(const InstCall *Instr) {
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);
StackArgLocations.push_back(OperandX8632Mem::create(Func, Ty, esp, Loc));
ParameterAreaSizeBytes += typeWidthInBytesOnStack(Arg->getType());
......@@ -2241,7 +2243,8 @@ void TargetX86Base<Machine>::lowerCall(const InstCall *Instr) {
// code, as the memory operand displacements may end up being smaller
// before any stack adjustment is done.
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
// dead code eliminated as a result of the FakeKill of scratch
// registers after the call.
......@@ -2264,11 +2267,11 @@ void TargetX86Base<Machine>::lowerCall(const InstCall *Instr) {
case IceType_i8:
case IceType_i16:
case IceType_i32:
ReturnReg = makeReg(Dest->getType(), RegX8632::Reg_eax);
ReturnReg = makeReg(Dest->getType(), Traits::RegisterSet::Reg_eax);
break;
case IceType_i64:
ReturnReg = makeReg(IceType_i32, RegX8632::Reg_eax);
ReturnRegHi = makeReg(IceType_i32, RegX8632::Reg_edx);
ReturnReg = makeReg(IceType_i32, Traits::RegisterSet::Reg_eax);
ReturnRegHi = makeReg(IceType_i32, Traits::RegisterSet::Reg_edx);
break;
case IceType_f32:
case IceType_f64:
......@@ -2282,7 +2285,7 @@ void TargetX86Base<Machine>::lowerCall(const InstCall *Instr) {
case IceType_v8i16:
case IceType_v4i32:
case IceType_v4f32:
ReturnReg = makeReg(Dest->getType(), RegX8632::Reg_xmm0);
ReturnReg = makeReg(Dest->getType(), Traits::RegisterSet::Reg_xmm0);
break;
}
}
......@@ -2311,7 +2314,8 @@ void TargetX86Base<Machine>::lowerCall(const InstCall *Instr) {
// Add the appropriate offset to esp. The call instruction takes care
// of resetting the stack offset during emission.
if (ParameterAreaSizeBytes) {
Variable *esp = Func->getTarget()->getPhysicalRegister(RegX8632::Reg_esp);
Variable *esp =
Func->getTarget()->getPhysicalRegister(Traits::RegisterSet::Reg_esp);
_add(esp, Ctx->getConstantInt32(ParameterAreaSizeBytes));
}
......@@ -2850,7 +2854,7 @@ void TargetX86Base<Machine>::lowerExtractElement(
// TODO(wala): Determine the best lowering sequences for each type.
bool CanUsePextr = Ty == IceType_v8i16 || Ty == IceType_v8i1 ||
InstructionSet >= Machine::SSE4_1;
InstructionSet >= Traits::SSE4_1;
if (CanUsePextr && Ty != IceType_v4f32) {
// Use pextrb, pextrw, or pextrd.
Constant *Mask = Ctx->getConstantInt32(Index);
......@@ -2943,8 +2947,9 @@ void TargetX86Base<Machine>::lowerFcmp(const InstFcmp *Inst) {
switch (Condition) {
default: {
CondX86::CmppsCond Predicate = Traits::TableFcmp[Index].Predicate;
assert(Predicate != CondX86::Cmpps_Invalid);
typename Traits::Cond::CmppsCond Predicate =
Traits::TableFcmp[Index].Predicate;
assert(Predicate != Traits::Cond::Cmpps_Invalid);
T = makeReg(Src0RM->getType());
_movp(T, Src0RM);
_cmpps(T, Src1RM, Predicate);
......@@ -2954,9 +2959,9 @@ void TargetX86Base<Machine>::lowerFcmp(const InstFcmp *Inst) {
T = makeReg(Src0RM->getType());
Variable *T2 = makeReg(Src0RM->getType());
_movp(T, Src0RM);
_cmpps(T, Src1RM, CondX86::Cmpps_neq);
_cmpps(T, Src1RM, Traits::Cond::Cmpps_neq);
_movp(T2, Src0RM);
_cmpps(T2, Src1RM, CondX86::Cmpps_ord);
_cmpps(T2, Src1RM, Traits::Cond::Cmpps_ord);
_pand(T, T2);
} break;
case InstFcmp::Ueq: {
......@@ -2964,9 +2969,9 @@ void TargetX86Base<Machine>::lowerFcmp(const InstFcmp *Inst) {
T = makeReg(Src0RM->getType());
Variable *T2 = makeReg(Src0RM->getType());
_movp(T, Src0RM);
_cmpps(T, Src1RM, CondX86::Cmpps_eq);
_cmpps(T, Src1RM, Traits::Cond::Cmpps_eq);
_movp(T2, Src0RM);
_cmpps(T2, Src1RM, CondX86::Cmpps_unord);
_cmpps(T2, Src1RM, Traits::Cond::Cmpps_unord);
_por(T, T2);
} break;
}
......@@ -2995,8 +3000,8 @@ void TargetX86Base<Machine>::lowerFcmp(const InstFcmp *Inst) {
assert(Index < Traits::TableFcmpSize);
if (Traits::TableFcmp[Index].SwapScalarOperands)
std::swap(Src0, Src1);
bool HasC1 = (Traits::TableFcmp[Index].C1 != CondX86::Br_None);
bool HasC2 = (Traits::TableFcmp[Index].C2 != CondX86::Br_None);
bool HasC1 = (Traits::TableFcmp[Index].C1 != Traits::Cond::Br_None);
bool HasC2 = (Traits::TableFcmp[Index].C2 != Traits::Cond::Br_None);
if (HasC1) {
Src0 = legalize(Src0);
Operand *Src1RM = legalize(Src1, Legal_Reg | Legal_Mem);
......@@ -3154,9 +3159,9 @@ void TargetX86Base<Machine>::lowerIcmp(const InstIcmp *Inst) {
InstX8632Label *LabelTrue = InstX8632Label::create(Func, this);
_mov(Dest, One);
_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);
if (Traits::TableIcmp64[Index].C2 != CondX86::Br_None)
if (Traits::TableIcmp64[Index].C2 != Traits::Cond::Br_None)
_br(Traits::TableIcmp64[Index].C2, LabelFalse);
_cmp(Src0LoRM, Src1LoRI);
_br(Traits::TableIcmp64[Index].C3, LabelTrue);
......@@ -3198,7 +3203,7 @@ void TargetX86Base<Machine>::lowerInsertElement(const InstInsertElement *Inst) {
}
if (Ty == IceType_v8i16 || Ty == IceType_v8i1 ||
InstructionSet >= Machine::SSE4_1) {
InstructionSet >= Traits::SSE4_1) {
// Use insertps, pinsrb, pinsrw, or pinsrd.
Operand *ElementRM =
legalize(ElementToInsertNotLegalized, Legal_Reg | Legal_Mem);
......@@ -3612,13 +3617,15 @@ void TargetX86Base<Machine>::lowerIntrinsicCall(
return;
}
case Intrinsics::Stacksave: {
Variable *esp = Func->getTarget()->getPhysicalRegister(RegX8632::Reg_esp);
Variable *esp =
Func->getTarget()->getPhysicalRegister(Traits::RegisterSet::Reg_esp);
Variable *Dest = Instr->getDest();
_mov(Dest, esp);
return;
}
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));
return;
}
......@@ -3639,10 +3646,10 @@ void TargetX86Base<Machine>::lowerAtomicCmpxchg(Variable *DestPrev,
if (Expected->getType() == IceType_i64) {
// Reserve the pre-colored registers first, before adding any more
// infinite-weight variables from formMemoryOperand's legalization.
Variable *T_edx = makeReg(IceType_i32, RegX8632::Reg_edx);
Variable *T_eax = makeReg(IceType_i32, RegX8632::Reg_eax);
Variable *T_ecx = makeReg(IceType_i32, RegX8632::Reg_ecx);
Variable *T_ebx = makeReg(IceType_i32, RegX8632::Reg_ebx);
Variable *T_edx = makeReg(IceType_i32, Traits::RegisterSet::Reg_edx);
Variable *T_eax = makeReg(IceType_i32, Traits::RegisterSet::Reg_eax);
Variable *T_ecx = makeReg(IceType_i32, Traits::RegisterSet::Reg_ecx);
Variable *T_ebx = makeReg(IceType_i32, Traits::RegisterSet::Reg_ebx);
_mov(T_eax, loOperand(Expected));
_mov(T_edx, hiOperand(Expected));
_mov(T_ebx, loOperand(Desired));
......@@ -3656,7 +3663,7 @@ void TargetX86Base<Machine>::lowerAtomicCmpxchg(Variable *DestPrev,
_mov(DestHi, T_edx);
return;
}
Variable *T_eax = makeReg(Expected->getType(), RegX8632::Reg_eax);
Variable *T_eax = makeReg(Expected->getType(), Traits::RegisterSet::Reg_eax);
_mov(T_eax, Expected);
OperandX8632Mem *Addr = formMemoryOperand(Ptr, Expected->getType());
Variable *DesiredReg = legalizeToVar(Desired);
......@@ -3727,7 +3734,8 @@ bool TargetX86Base<Machine>::tryOptimizedCmpxchgCmpBr(Variable *Dest,
lowerAssign(PhiAssign);
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.
NextCmp->setDeleted();
NextBr->setDeleted();
......@@ -3858,13 +3866,13 @@ void TargetX86Base<Machine>::expandAtomicRMWAsCmpxchg(LowerBinOp Op_Lo,
Val = legalize(Val);
Type Ty = Val->getType();
if (Ty == IceType_i64) {
Variable *T_edx = makeReg(IceType_i32, RegX8632::Reg_edx);
Variable *T_eax = makeReg(IceType_i32, RegX8632::Reg_eax);
Variable *T_edx = makeReg(IceType_i32, Traits::RegisterSet::Reg_edx);
Variable *T_eax = makeReg(IceType_i32, Traits::RegisterSet::Reg_eax);
OperandX8632Mem *Addr = formMemoryOperand(Ptr, Ty);
_mov(T_eax, loOperand(Addr));
_mov(T_edx, hiOperand(Addr));
Variable *T_ecx = makeReg(IceType_i32, RegX8632::Reg_ecx);
Variable *T_ebx = makeReg(IceType_i32, RegX8632::Reg_ebx);
Variable *T_ecx = makeReg(IceType_i32, Traits::RegisterSet::Reg_ecx);
Variable *T_ebx = makeReg(IceType_i32, Traits::RegisterSet::Reg_ebx);
InstX8632Label *Label = InstX8632Label::create(Func, this);
const bool IsXchg8b = Op_Lo == nullptr && Op_Hi == nullptr;
if (!IsXchg8b) {
......@@ -3883,7 +3891,7 @@ void TargetX86Base<Machine>::expandAtomicRMWAsCmpxchg(LowerBinOp Op_Lo,
}
const bool Locked = true;
_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 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.
......@@ -3908,7 +3916,7 @@ void TargetX86Base<Machine>::expandAtomicRMWAsCmpxchg(LowerBinOp Op_Lo,
return;
}
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);
InstX8632Label *Label = InstX8632Label::create(Func, this);
Context.insert(Label);
......@@ -3919,7 +3927,7 @@ void TargetX86Base<Machine>::expandAtomicRMWAsCmpxchg(LowerBinOp Op_Lo,
(this->*Op_Lo)(T, Val);
const bool Locked = true;
_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
// the end of the loop, since it will be re-used by the loop.
if (Variable *ValVar = llvm::dyn_cast<Variable>(Val)) {
......@@ -3983,7 +3991,7 @@ void TargetX86Base<Machine>::lowerCountZeros(bool Cttz, Type Ty, Variable *Dest,
Constant *SixtyThree = Ctx->getConstantInt32(63);
_mov(T_Dest, SixtyThree);
}
_cmov(T_Dest, T, CondX86::Br_ne);
_cmov(T_Dest, T, Traits::Cond::Br_ne);
if (!Cttz) {
_xor(T_Dest, ThirtyOne);
}
......@@ -4004,7 +4012,7 @@ void TargetX86Base<Machine>::lowerCountZeros(bool Cttz, Type Ty, Variable *Dest,
_xor(T_Dest2, ThirtyOne);
}
_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(DestHi, Ctx->getConstantZero(IceType_i32));
}
......@@ -4306,16 +4314,18 @@ void TargetX86Base<Machine>::lowerRet(const InstRet *Inst) {
if (Inst->hasRetValue()) {
Operand *Src0 = legalize(Inst->getRetValue());
if (Src0->getType() == IceType_i64) {
Variable *eax = legalizeToVar(loOperand(Src0), RegX8632::Reg_eax);
Variable *edx = legalizeToVar(hiOperand(Src0), RegX8632::Reg_edx);
Variable *eax =
legalizeToVar(loOperand(Src0), Traits::RegisterSet::Reg_eax);
Variable *edx =
legalizeToVar(hiOperand(Src0), Traits::RegisterSet::Reg_edx);
Reg = eax;
Context.insert(InstFakeUse::create(Func, edx));
} else if (isScalarFloatingType(Src0->getType())) {
_fld(Src0);
} else if (isVectorType(Src0->getType())) {
Reg = legalizeToVar(Src0, RegX8632::Reg_xmm0);
Reg = legalizeToVar(Src0, Traits::RegisterSet::Reg_xmm0);
} else {
_mov(Reg, Src0, RegX8632::Reg_eax);
_mov(Reg, Src0, Traits::RegisterSet::Reg_eax);
}
}
// Add a ret instruction even if sandboxing is enabled, because
......@@ -4327,7 +4337,8 @@ void TargetX86Base<Machine>::lowerRet(const InstRet *Inst) {
// 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
// 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));
}
......@@ -4344,7 +4355,7 @@ void TargetX86Base<Machine>::lowerSelect(const InstSelect *Inst) {
Variable *T = makeReg(SrcTy);
Operand *SrcTRM = legalize(SrcT, 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
// or pblendw.
//
......@@ -4352,7 +4363,7 @@ void TargetX86Base<Machine>::lowerSelect(const InstSelect *Inst) {
if (SrcTy == IceType_v4i1 || SrcTy == IceType_v4i32 ||
SrcTy == IceType_v4f32) {
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);
_psll(xmm0, Ctx->getConstantInt8(31));
_movp(T, SrcFRM);
......@@ -4362,7 +4373,7 @@ void TargetX86Base<Machine>::lowerSelect(const InstSelect *Inst) {
assert(typeNumElements(SrcTy) == 8 || typeNumElements(SrcTy) == 16);
Type SignExtTy = Condition->getType() == IceType_v8i1 ? IceType_v8i16
: 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));
_movp(T, SrcFRM);
_pblendvb(T, SrcTRM, xmm0);
......@@ -4370,7 +4381,7 @@ void TargetX86Base<Machine>::lowerSelect(const InstSelect *Inst) {
}
return;
}
// Lower select without Machine::SSE4.1:
// Lower select without Traits::SSE4.1:
// a=d?b:c ==>
// if elementtype(d) != i1:
// d=sext(d);
......@@ -4397,7 +4408,7 @@ void TargetX86Base<Machine>::lowerSelect(const InstSelect *Inst) {
return;
}
CondX86::BrCond Cond = CondX86::Br_ne;
typename Traits::Cond::BrCond Cond = Traits::Cond::Br_ne;
Operand *CmpOpnd0 = nullptr;
Operand *CmpOpnd1 = nullptr;
// Handle folding opportunities.
......@@ -4542,9 +4553,9 @@ void TargetX86Base<Machine>::lowerSwitch(const InstSwitch *Inst) {
Constant *ValueHi = Ctx->getConstantInt32(Inst->getValue(I) >> 32);
InstX8632Label *Label = InstX8632Label::create(Func, this);
_cmp(Src0Lo, ValueLo);
_br(CondX86::Br_ne, Label);
_br(Traits::Cond::Br_ne, Label);
_cmp(Src0Hi, ValueHi);
_br(CondX86::Br_e, Inst->getLabel(I));
_br(Traits::Cond::Br_e, Inst->getLabel(I));
Context.insert(Label);
}
_br(Inst->getLabelDefault());
......@@ -4559,7 +4570,7 @@ void TargetX86Base<Machine>::lowerSwitch(const InstSwitch *Inst) {
for (SizeT I = 0; I < NumCases; ++I) {
Constant *Value = Ctx->getConstantInt32(Inst->getValue(I));
_cmp(Src0, Value);
_br(CondX86::Br_e, Inst->getLabel(I));
_br(Traits::Cond::Br_e, Inst->getLabel(I));
}
_br(Inst->getLabelDefault());
......@@ -5208,7 +5219,7 @@ void TargetX86Base<Machine>::makeRandomRegisterPermutation(
const llvm::SmallBitVector &ExcludeRegisters) const {
// TODO(stichnot): Declaring Permutation this way loses type/size
// 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
// equivalence class. For x86-32, this would comprise the 8 XMM
// registers. This is for performance, not correctness.
......@@ -5223,15 +5234,15 @@ void TargetX86Base<Machine>::makeRandomRegisterPermutation(
// explicitly excluded from shuffling.
#define X(val, encode, name, name16, name8, scratch, preserved, stackptr, \
frameptr, isI8, isInt, isFP) \
if (ExcludeRegisters[RegX8632::val]) { \
if (ExcludeRegisters[Traits::RegisterSet::val]) { \
/* val stays the same in the resulting permutation. */ \
Permutation[RegX8632::val] = RegX8632::val; \
Permutation[Traits::RegisterSet::val] = Traits::RegisterSet::val; \
++NumPreserved; \
} else { \
const uint32_t Index = (scratch << 0) | (preserved << 1) | (isI8 << 2) | \
(isInt << 3) | (isFP << 4); \
/* 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
#undef X
......@@ -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)) {
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