Commit d1bd1d33 by John Porto

Subzero. X8664. Enables RIP-based addressing mode.

parent c64448fb
......@@ -729,7 +729,7 @@ private:
inline void emitXmmRegisterOperand(RegType reg, RmType rm);
inline void emitOperandSizeOverride();
void emitOperand(int rm, const Operand &operand);
void emitOperand(int rm, const Operand &operand, RelocOffsetT Addend = 0);
void emitImmediate(Type ty, const Immediate &imm);
void emitComplexI8(int rm, const Operand &operand,
const Immediate &immediate);
......
......@@ -299,11 +299,13 @@ void AssemblerX86Base<TraitsType>::mov(Type Ty, const Address &dst,
emitRex(Ty, dst, RexRegIrrelevant);
if (isByteSizedType(Ty)) {
emitUint8(0xC6);
emitOperand(0, dst);
static constexpr RelocOffsetT OffsetFromNextInstruction = 1;
emitOperand(0, dst, OffsetFromNextInstruction);
emitUint8(imm.value() & 0xFF);
} else {
emitUint8(0xC7);
emitOperand(0, dst);
const uint8_t OffsetFromNextInstruction = Ty == IceType_i16 ? 2 : 4;
emitOperand(0, dst, OffsetFromNextInstruction);
emitImmediate(Ty, imm);
}
}
......@@ -1429,7 +1431,8 @@ void AssemblerX86Base<TraitsType>::cmpps(Type Ty, XmmRegister dst,
emitRex(RexTypeIrrelevant, src, dst);
emitUint8(0x0F);
emitUint8(0xC2);
emitOperand(gprEncoding(dst), src);
static constexpr RelocOffsetT OffsetFromNextInstruction = 1;
emitOperand(gprEncoding(dst), src, OffsetFromNextInstruction);
emitUint8(CmpCondition);
}
......@@ -1551,7 +1554,8 @@ void AssemblerX86Base<TraitsType>::pshufd(Type /* Ty */, XmmRegister dst,
emitRex(RexTypeIrrelevant, src, dst);
emitUint8(0x0F);
emitUint8(0x70);
emitOperand(gprEncoding(dst), src);
static constexpr RelocOffsetT OffsetFromNextInstruction = 1;
emitOperand(gprEncoding(dst), src, OffsetFromNextInstruction);
assert(imm.is_uint8());
emitUint8(imm.value());
}
......@@ -1578,7 +1582,8 @@ void AssemblerX86Base<TraitsType>::shufps(Type /* Ty */, XmmRegister dst,
emitRex(RexTypeIrrelevant, src, dst);
emitUint8(0x0F);
emitUint8(0xC6);
emitOperand(gprEncoding(dst), src);
static constexpr RelocOffsetT OffsetFromNextInstruction = 1;
emitOperand(gprEncoding(dst), src, OffsetFromNextInstruction);
assert(imm.is_uint8());
emitUint8(imm.value());
}
......@@ -1830,7 +1835,8 @@ void AssemblerX86Base<TraitsType>::insertps(Type Ty, XmmRegister dst,
emitUint8(0x0F);
emitUint8(0x3A);
emitUint8(0x21);
emitOperand(gprEncoding(dst), src);
static constexpr RelocOffsetT OffsetFromNextInstruction = 1;
emitOperand(gprEncoding(dst), src, OffsetFromNextInstruction);
emitUint8(imm.value());
}
......@@ -1869,7 +1875,8 @@ void AssemblerX86Base<TraitsType>::pinsr(Type Ty, XmmRegister dst,
emitUint8(0x3A);
emitUint8(isByteSizedType(Ty) ? 0x20 : 0x22);
}
emitOperand(gprEncoding(dst), src);
static constexpr RelocOffsetT OffsetFromNextInstruction = 1;
emitOperand(gprEncoding(dst), src, OffsetFromNextInstruction);
emitUint8(imm.value());
}
......@@ -2244,7 +2251,8 @@ void AssemblerX86Base<TraitsType>::test(Type Ty, const Address &addr,
emitAddrSizeOverridePrefix();
emitRex(Ty, addr, RexRegIrrelevant);
emitUint8(0xF6);
emitOperand(0, addr);
static constexpr RelocOffsetT OffsetFromNextInstruction = 1;
emitOperand(0, addr, OffsetFromNextInstruction);
emitUint8(immediate.value() & 0xFF);
} else {
if (Ty == IceType_i16)
......@@ -2252,7 +2260,8 @@ void AssemblerX86Base<TraitsType>::test(Type Ty, const Address &addr,
emitAddrSizeOverridePrefix();
emitRex(Ty, addr, RexRegIrrelevant);
emitUint8(0xF7);
emitOperand(0, addr);
const uint8_t OffsetFromNextInstruction = Ty == IceType_i16 ? 2 : 4;
emitOperand(0, addr, OffsetFromNextInstruction);
emitImmediate(Ty, immediate);
}
}
......@@ -2653,11 +2662,13 @@ void AssemblerX86Base<TraitsType>::imul(Type Ty, GPRRegister dst,
emitRex(Ty, address, dst);
if (imm.is_int8()) {
emitUint8(0x6B);
emitOperand(gprEncoding(dst), address);
static constexpr RelocOffsetT OffsetFromNextInstruction = 1;
emitOperand(gprEncoding(dst), address, OffsetFromNextInstruction);
emitUint8(imm.value() & 0xFF);
} else {
emitUint8(0x69);
emitOperand(gprEncoding(dst), address);
const uint8_t OffsetFromNextInstruction = Ty == IceType_i16 ? 2 : 4;
emitOperand(gprEncoding(dst), address, OffsetFromNextInstruction);
emitImmediate(Ty, imm);
}
}
......@@ -3346,7 +3357,8 @@ void AssemblerX86Base<TraitsType>::bind(Label *L) {
}
template <typename TraitsType>
void AssemblerX86Base<TraitsType>::emitOperand(int rm, const Operand &operand) {
void AssemblerX86Base<TraitsType>::emitOperand(int rm, const Operand &operand,
RelocOffsetT Addend) {
assert(rm >= 0 && rm < 8);
const intptr_t length = operand.length_;
assert(length > 0);
......@@ -3362,9 +3374,18 @@ void AssemblerX86Base<TraitsType>::emitOperand(int rm, const Operand &operand) {
displacement_start = 2;
}
// Emit the displacement and the fixup that affects it, if any.
if (operand.fixup()) {
emitFixup(operand.fixup());
AssemblerFixup *Fixup = operand.fixup();
if (Fixup != nullptr) {
emitFixup(Fixup);
assert(length - displacement_start == 4);
if (fixupIsPCRel(Fixup->kind())) {
Fixup->set_addend(-Addend);
int32_t Offset;
memmove(&Offset, &operand.encoding_[displacement_start], sizeof(Offset));
Offset -= Addend;
emitInt32(Offset);
return;
}
}
for (intptr_t i = displacement_start; i < length; i++) {
emitUint8(operand.encoding_[i]);
......@@ -3374,15 +3395,17 @@ void AssemblerX86Base<TraitsType>::emitOperand(int rm, const Operand &operand) {
template <typename TraitsType>
void AssemblerX86Base<TraitsType>::emitImmediate(Type Ty,
const Immediate &imm) {
auto *const Fixup = imm.fixup();
if (Ty == IceType_i16) {
assert(!imm.fixup());
assert(Fixup == nullptr);
emitInt16(imm.value());
} else {
if (imm.fixup()) {
emitFixup(imm.fixup());
return;
}
emitInt32(imm.value());
if (Fixup != nullptr) {
emitFixup(Fixup);
}
emitInt32(imm.value());
}
template <typename TraitsType>
......@@ -3397,7 +3420,8 @@ void AssemblerX86Base<TraitsType>::emitComplexI8(int rm, const Operand &operand,
} else {
// Use sign-extended 8-bit immediate.
emitUint8(0x80);
emitOperand(rm, operand);
static constexpr RelocOffsetT OffsetFromNextInstruction = 1;
emitOperand(rm, operand, OffsetFromNextInstruction);
emitUint8(immediate.value() & 0xFF);
}
}
......@@ -3410,7 +3434,8 @@ void AssemblerX86Base<TraitsType>::emitComplex(Type Ty, int rm,
if (immediate.is_int8()) {
// Use sign-extended 8-bit immediate.
emitUint8(0x83);
emitOperand(rm, operand);
static constexpr RelocOffsetT OffsetFromNextInstruction = 1;
emitOperand(rm, operand, OffsetFromNextInstruction);
emitUint8(immediate.value() & 0xFF);
} else if (operand.IsRegister(Traits::Encoded_Reg_Accumulator)) {
// Use short form if the destination is eax.
......@@ -3418,7 +3443,8 @@ void AssemblerX86Base<TraitsType>::emitComplex(Type Ty, int rm,
emitImmediate(Ty, immediate);
} else {
emitUint8(0x81);
emitOperand(rm, operand);
const uint8_t OffsetFromNextInstruction = Ty == IceType_i16 ? 2 : 4;
emitOperand(rm, operand, OffsetFromNextInstruction);
emitImmediate(Ty, immediate);
}
}
......@@ -3468,7 +3494,8 @@ void AssemblerX86Base<TraitsType>::emitGenericShift(int rm, Type Ty,
emitOperand(rm, Operand(reg));
} else {
emitUint8(isByteSizedArithType(Ty) ? 0xC0 : 0xC1);
emitOperand(rm, Operand(reg));
static constexpr RelocOffsetT OffsetFromNextInstruction = 1;
emitOperand(rm, Operand(reg), OffsetFromNextInstruction);
emitUint8(imm.value() & 0xFF);
}
}
......
......@@ -23,10 +23,10 @@ const Constant *AssemblerFixup::NullSymbol = nullptr;
RelocOffsetT AssemblerFixup::offset() const {
if (isNullSymbol())
return 0;
return addend_;
if (const auto *CR = llvm::dyn_cast<ConstantRelocatable>(value_))
return CR->getOffset();
return 0;
return CR->getOffset() + addend_;
return addend_;
}
IceString AssemblerFixup::symbol(const GlobalContext *Ctx,
......
......@@ -25,7 +25,7 @@ using FixupKind = uint32_t;
/// Assembler fixups are positions in generated code/data that hold relocation
/// information that needs to be processed before finalizing the code/data.
struct AssemblerFixup {
class AssemblerFixup {
AssemblerFixup &operator=(const AssemblerFixup &) = delete;
public:
......@@ -53,6 +53,8 @@ public:
void set_value(const Constant *Value) { value_ = Value; }
void set_addend(RelocOffsetT Addend) { addend_ = Addend; }
/// Emits fixup, then returns the number of bytes to skip.
virtual size_t emit(GlobalContext *Ctx, const Assembler &Asm) const;
......@@ -61,6 +63,9 @@ private:
intptr_t position_ = 0;
FixupKind kind_ = 0;
const Constant *value_ = nullptr;
// An offset addend to the fixup offset (as returned by offset()), in case the
// assembler needs to adjust it.
RelocOffsetT addend_ = 0;
};
/// Extends a fixup to be textual. That is, it emits text instead of a sequence
......
......@@ -136,7 +136,17 @@ void TargetX8664Traits::X86OperandMem::emit(const Cfg *Func) const {
// rematerializable base/index and Disp.
assert(Disp == 0);
const bool UseNonsfi = Func->getContext()->getFlags().getUseNonsfi();
CR->emitWithoutPrefix(Func->getTarget(), UseNonsfi ? "@GOTOFF" : "");
CR->emitWithoutPrefix(Target, UseNonsfi ? "@GOTOFF" : "");
assert(!UseNonsfi);
if (Base == nullptr && Index == nullptr) {
if (CR->getName() != "") { // rip-relative addressing.
if (NeedSandboxing) {
Str << "(%rip)";
} else {
Str << "(%eip)";
}
}
}
} else {
llvm_unreachable("Invalid offset type for x86 mem operand");
}
......@@ -256,10 +266,16 @@ TargetX8664Traits::Address TargetX8664Traits::X86OperandMem::toAsmAddress(
if (getOffset() != nullptr) {
if (const auto *CI = llvm::dyn_cast<ConstantInteger32>(getOffset())) {
Disp += static_cast<int32_t>(CI->getValue());
} else if (const auto CR =
} else if (const auto *CR =
llvm::dyn_cast<ConstantRelocatable>(getOffset())) {
Disp = CR->getOffset();
Fixup = Asm->createFixup(FK_Abs, CR);
RelocOffsetT DispAdjustment = 0;
if (CR->getName() != "") {
const auto FixupKind =
(getBase() != nullptr || getIndex() != nullptr) ? FK_Abs : FK_PcRel;
DispAdjustment = FixupKind == FK_PcRel ? 4 : 0;
Fixup = Asm->createFixup(FixupKind, CR);
}
Disp = CR->getOffset() - DispAdjustment;
} else {
llvm_unreachable("Unexpected offset type");
}
......@@ -290,7 +306,15 @@ TargetX8664Traits::Address TargetX8664Traits::X86OperandMem::toAsmAddress(
Fixup);
}
return X8664::Traits::Address(Disp, Fixup);
if (Fixup == nullptr) {
// Absolute addresses are not allowed in Nexes -- they must be rebased
// w.r.t. %r15.
// Exception: LEAs are fine because they do not touch memory.
assert(!Target->needSandboxing() || IsLeaAddr);
return X8664::Traits::Address::Absolute(Disp);
}
return X8664::Traits::Address::RipRelative(Disp, Fixup);
}
TargetX8664Traits::Address
......
......@@ -294,10 +294,31 @@ void TargetX8664::emitGetIP(CfgNode *Node) {
(void)Node;
}
namespace {
bool isAssignedToRspOrRbp(const Variable *Var) {
if (Var == nullptr) {
return false;
}
if (Var->isRematerializable()) {
return true;
}
if (!Var->hasReg()) {
return false;
}
const int32_t RegNum = Var->getRegNum();
if ((RegNum == Traits::RegisterSet::Reg_rsp) ||
(RegNum == Traits::RegisterSet::Reg_rbp)) {
return true;
}
return false;
}
} // end of anonymous namespace
Traits::X86OperandMem *TargetX8664::_sandbox_mem_reference(X86OperandMem *Mem) {
// In x86_64-nacl, all memory references are relative to %r15 (i.e., %rzp.)
// NaCl sandboxing also requires that any registers that are not %rsp and
// %rbp to be 'truncated' to 32-bit before memory access.
if (SandboxingType == ST_None) {
return Mem;
}
......@@ -307,25 +328,49 @@ Traits::X86OperandMem *TargetX8664::_sandbox_mem_reference(X86OperandMem *Mem) {
"_sandbox_mem_reference not implemented for nonsfi");
}
// In x86_64-nacl, all memory references are relative to a base register
// (%r15, %rsp, %rbp, or %rip).
Variable *Base = Mem->getBase();
Variable *Index = Mem->getIndex();
uint16_t Shift = 0;
Variable *ZeroReg =
getPhysicalRegister(Traits::RegisterSet::Reg_r15, IceType_i64);
Variable *ZeroReg = RebasePtr;
Constant *Offset = Mem->getOffset();
Variable *T = nullptr;
bool AbsoluteAddress = false;
if (Base == nullptr && Index == nullptr) {
if (const auto *CR = llvm::dyn_cast<ConstantRelocatable>(Offset)) {
if (CR->getName() != "") {
// Mem is RIP-relative. There's no need to rebase it.
return Mem;
}
}
// Offset is an absolute address, so we need to emit
// Offset(%r15)
AbsoluteAddress = true;
}
if (Mem->getIsRebased()) {
// If Mem.IsRebased, then we don't need to update Mem to contain a reference
// to a valid base register (%r15, %rsp, or %rbp), but we still need to
// truncate Mem.Index (if any) to 32-bit.
assert(ZeroReg == Base || Base->isRematerializable());
// If Mem.IsRebased, then we don't need to update Mem, as it's already been
// updated to contain a reference to one of %rsp, %rbp, or %r15.
// We don't return early because we still need to zero extend Index.
assert(ZeroReg == Base || AbsoluteAddress || isAssignedToRspOrRbp(Base));
if (!AbsoluteAddress) {
// If Mem is an absolute address, no need to update ZeroReg (which is
// already set to %r15.)
ZeroReg = Base;
}
if (Index != nullptr) {
T = makeReg(IceType_i32);
_mov(T, Index);
Shift = Mem->getShift();
}
} else {
if (Base != nullptr) {
if (Base->isRematerializable()) {
// If Base is a valid base pointer we don't need to use the RebasePtr. By
// doing this we might save us the need to zero extend the memory operand.
if (isAssignedToRspOrRbp(Base)) {
ZeroReg = Base;
} else {
T = Base;
......@@ -334,13 +379,25 @@ Traits::X86OperandMem *TargetX8664::_sandbox_mem_reference(X86OperandMem *Mem) {
if (Index != nullptr) {
assert(!Index->isRematerializable());
// If Index is not nullptr, it is mandatory that T is a nullptr.
// Otherwise, the lowering generated a memory operand with two registers.
// Note that Base might still be non-nullptr, but it must be a valid
// base register.
if (T != nullptr) {
llvm::report_fatal_error("memory reference contains base and index.");
}
// If the Index is not shifted, and it is a Valid Base, and the ZeroReg is
// still RebasePtr, then we do ZeroReg = Index, and hopefully prevent the
// need to zero-extend the memory operand (which may still happen -- see
// NeedLea below.)
if (Shift == 0 && isAssignedToRspOrRbp(Index) && ZeroReg == RebasePtr) {
ZeroReg = Index;
} else {
T = Index;
Shift = Mem->getShift();
}
}
}
// NeedsLea is a flags indicating whether Mem needs to be materialized to a
// GPR prior to being used. A LEA is needed if Mem.Offset is a constant
......@@ -348,11 +405,13 @@ Traits::X86OperandMem *TargetX8664::_sandbox_mem_reference(X86OperandMem *Mem) {
// needed to ensure the sandboxed memory operand will only use the lower
// 32-bits of T+Offset.
bool NeedsLea = false;
if (const auto *Offset = Mem->getOffset()) {
if (llvm::isa<ConstantRelocatable>(Offset)) {
NeedsLea = true;
if (Offset != nullptr) {
if (const auto *CR = llvm::dyn_cast<ConstantRelocatable>(Offset)) {
NeedsLea = CR->getName() != "" || CR->getOffset() < 0;
} else if (const auto *Imm = llvm::cast<ConstantInteger32>(Offset)) {
NeedsLea = Imm->getValue() < 0;
} else {
llvm::report_fatal_error("Unexpected Offset type.");
}
}
......@@ -362,21 +421,20 @@ Traits::X86OperandMem *TargetX8664::_sandbox_mem_reference(X86OperandMem *Mem) {
if (T->hasReg()) {
RegNum = Traits::getGprForType(IceType_i64, T->getRegNum());
RegNum32 = Traits::getGprForType(IceType_i32, RegNum);
switch (RegNum) {
case Traits::RegisterSet::Reg_rsp:
case Traits::RegisterSet::Reg_rbp:
// Memory operands referencing rsp/rbp do not need to be sandboxed.
return Mem;
}
// At this point, if T was assigned to rsp/rbp, then we would have already
// made this the ZeroReg.
assert(RegNum != Traits::RegisterSet::Reg_rsp);
assert(RegNum != Traits::RegisterSet::Reg_rbp);
}
switch (T->getType()) {
default:
llvm::report_fatal_error("Mem pointer should be a 32-bit GPR.");
case IceType_i64:
// Even though "default:" would also catch T.Type == IceType_i64, an
// explicit 'case IceType_i64' shows that memory operands are always
// supposed to be 32-bits.
llvm::report_fatal_error("Mem pointer should be 32-bit.");
llvm::report_fatal_error("Mem pointer should not be a 64-bit GPR.");
case IceType_i32: {
Variable *T64 = makeReg(IceType_i64, RegNum);
auto *Movzx = _movzx(T64, T);
......
......@@ -89,18 +89,15 @@ struct TargetX8664Traits {
RexB = RexBase | (1 << 0),
};
Operand(const Operand &other)
: fixup_(other.fixup_), rex_(other.rex_), length_(other.length_) {
memmove(&encoding_[0], &other.encoding_[0], other.length_);
}
protected:
// Needed by subclass Address.
Operand() = default;
Operand &operator=(const Operand &other) {
length_ = other.length_;
fixup_ = other.fixup_;
rex_ = other.rex_;
memmove(&encoding_[0], &other.encoding_[0], other.length_);
return *this;
}
public:
Operand(const Operand &) = default;
Operand(Operand &&) = default;
Operand &operator=(const Operand &) = default;
Operand &operator=(Operand &&) = default;
uint8_t mod() const { return (encoding_at(0) >> 6) & 3; }
......@@ -131,19 +128,9 @@ struct TargetX8664Traits {
return static_cast<int8_t>(encoding_[length_ - 1]);
}
int32_t disp32() const {
assert(length_ >= 5);
// TODO(stichnot): This method is not currently used. Delete it along
// with other unused methods, or use a safe version of bitCopy().
llvm::report_fatal_error("Unexpected call to disp32()");
// return Utils::bitCopy<int32_t>(encoding_[length_ - 4]);
}
AssemblerFixup *fixup() const { return fixup_; }
protected:
Operand() : fixup_(nullptr), length_(0) {} // Needed by subclass Address.
void SetModRM(int mod, GPRRegister rm) {
assert((mod & ~3) == 0);
encoding_[0] = (mod << 6) | (rm & 0x07);
......@@ -175,10 +162,10 @@ struct TargetX8664Traits {
void SetFixup(AssemblerFixup *fixup) { fixup_ = fixup; }
private:
AssemblerFixup *fixup_;
AssemblerFixup *fixup_ = nullptr;
uint8_t rex_ = 0;
uint8_t encoding_[6];
uint8_t length_;
uint8_t length_ = 0;
explicit Operand(GPRRegister reg) : fixup_(nullptr) { SetModRM(3, reg); }
......@@ -201,31 +188,29 @@ struct TargetX8664Traits {
};
class Address : public Operand {
Address() = delete;
Address() = default;
public:
Address(const Address &other) : Operand(other) {}
Address &operator=(const Address &other) {
Operand::operator=(other);
return *this;
}
Address(const Address &) = default;
Address(Address &&) = default;
Address &operator=(const Address &) = default;
Address &operator=(Address &&) = default;
Address(GPRRegister Base, int32_t Disp, AssemblerFixup *Fixup) {
if (Fixup == nullptr && Disp == 0 &&
(Base & 7) != RegX8664::Encoded_Reg_ebp) {
(Base & 7) != RegX8664::Encoded_Reg_rbp) {
SetModRM(0, Base);
if ((Base & 7) == RegX8664::Encoded_Reg_esp)
SetSIB(TIMES_1, RegX8664::Encoded_Reg_esp, Base);
if ((Base & 7) == RegX8664::Encoded_Reg_rsp)
SetSIB(TIMES_1, RegX8664::Encoded_Reg_rsp, Base);
} else if (Fixup == nullptr && Utils::IsInt(8, Disp)) {
SetModRM(1, Base);
if ((Base & 7) == RegX8664::Encoded_Reg_esp)
SetSIB(TIMES_1, RegX8664::Encoded_Reg_esp, Base);
if ((Base & 7) == RegX8664::Encoded_Reg_rsp)
SetSIB(TIMES_1, RegX8664::Encoded_Reg_rsp, Base);
SetDisp8(Disp);
} else {
SetModRM(2, Base);
if ((Base & 7) == RegX8664::Encoded_Reg_esp)
SetSIB(TIMES_1, RegX8664::Encoded_Reg_esp, Base);
if ((Base & 7) == RegX8664::Encoded_Reg_rsp)
SetSIB(TIMES_1, RegX8664::Encoded_Reg_rsp, Base);
SetDisp32(Disp);
if (Fixup)
SetFixup(Fixup);
......@@ -234,9 +219,9 @@ struct TargetX8664Traits {
Address(GPRRegister Index, ScaleFactor Scale, int32_t Disp,
AssemblerFixup *Fixup) {
assert(Index != RegX8664::Encoded_Reg_esp); // Illegal addressing mode.
SetModRM(0, RegX8664::Encoded_Reg_esp);
SetSIB(Scale, Index, RegX8664::Encoded_Reg_ebp);
assert(Index != RegX8664::Encoded_Reg_rsp); // Illegal addressing mode.
SetModRM(0, RegX8664::Encoded_Reg_rsp);
SetSIB(Scale, Index, RegX8664::Encoded_Reg_rbp);
SetDisp32(Disp);
if (Fixup)
SetFixup(Fixup);
......@@ -244,17 +229,17 @@ struct TargetX8664Traits {
Address(GPRRegister Base, GPRRegister Index, ScaleFactor Scale,
int32_t Disp, AssemblerFixup *Fixup) {
assert(Index != RegX8664::Encoded_Reg_esp); // Illegal addressing mode.
assert(Index != RegX8664::Encoded_Reg_rsp); // Illegal addressing mode.
if (Fixup == nullptr && Disp == 0 &&
(Base & 7) != RegX8664::Encoded_Reg_ebp) {
SetModRM(0, RegX8664::Encoded_Reg_esp);
(Base & 7) != RegX8664::Encoded_Reg_rbp) {
SetModRM(0, RegX8664::Encoded_Reg_rsp);
SetSIB(Scale, Index, Base);
} else if (Fixup == nullptr && Utils::IsInt(8, Disp)) {
SetModRM(1, RegX8664::Encoded_Reg_esp);
SetModRM(1, RegX8664::Encoded_Reg_rsp);
SetSIB(Scale, Index, Base);
SetDisp8(Disp);
} else {
SetModRM(2, RegX8664::Encoded_Reg_esp);
SetModRM(2, RegX8664::Encoded_Reg_rsp);
SetSIB(Scale, Index, Base);
SetDisp32(Disp);
if (Fixup)
......@@ -263,23 +248,37 @@ struct TargetX8664Traits {
}
/// Generate a RIP-relative address expression on x86-64.
Address(RelocOffsetT Offset, AssemblerFixup *Fixup) {
SetModRM(0x0, RegX8664::Encoded_Reg_esp);
static Address RipRelative(RelocOffsetT Offset, AssemblerFixup *Fixup) {
assert(Fixup != nullptr);
assert(Fixup->kind() == FK_PcRel);
Address NewAddress;
NewAddress.SetModRM(0x0, RegX8664::Encoded_Reg_rbp);
static constexpr ScaleFactor Scale = TIMES_1;
SetSIB(Scale, RegX8664::Encoded_Reg_esp, RegX8664::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);
NewAddress.SetDisp32(Offset);
if (Fixup)
SetFixup(Fixup);
NewAddress.SetFixup(Fixup);
return NewAddress;
}
/// Generate an absolute address.
static Address Absolute(RelocOffsetT Addr) {
Address NewAddress;
NewAddress.SetModRM(0x0, RegX8664::Encoded_Reg_rsp);
static constexpr ScaleFactor NoScale = TIMES_1;
NewAddress.SetSIB(NoScale, RegX8664::Encoded_Reg_rsp,
RegX8664::Encoded_Reg_rbp);
NewAddress.SetDisp32(Addr);
return NewAddress;
}
static Address ofConstPool(Assembler *Asm, const Constant *Imm) {
// TODO(jpp): ???
AssemblerFixup *Fixup = Asm->createFixup(FK_Abs, Imm);
const RelocOffsetT Offset = 4;
return Address(Offset, Fixup);
return Address::RipRelative(Offset, Fixup);
}
};
......
......@@ -328,7 +328,7 @@ TEST_F(AssemblerX8664LowLevelTest, LeaAbsolute) {
do { \
static constexpr char TestString[] = "(" #Dst ", " #Value ")"; \
__ lea(IceType_i32, GPRRegister::Encoded_Reg_##Dst, \
Address(Value, AssemblerFixup::NoFixup)); \
Address::Absolute(Value)); \
static constexpr uint32_t ByteCount = 8; \
ASSERT_EQ(ByteCount, codeBytesSize()) << TestString; \
static constexpr uint8_t Opcode = 0x8D; \
......
......@@ -204,8 +204,8 @@ TEST_F(AssemblerX8664LowLevelTest, Xadd) {
// Ensures that xadd emits a lock prefix accordingly.
{
__ xadd(IceType_i8, Address(0x1FF00, AssemblerFixup::NoFixup),
Encoded_GPR_r14(), NotLocked);
__ xadd(IceType_i8, Address::Absolute(0x1FF00), Encoded_GPR_r14(),
NotLocked);
static constexpr uint8_t ByteCountNotLocked8 = 10;
ASSERT_EQ(ByteCountNotLocked8, codeBytesSize());
ASSERT_TRUE(verifyBytes<ByteCountNotLocked8>(codeBytes(), 0x67, 0x44, 0x0F,
......@@ -213,8 +213,7 @@ TEST_F(AssemblerX8664LowLevelTest, Xadd) {
0x01, 0x00));
reset();
__ xadd(IceType_i8, Address(0x1FF00, AssemblerFixup::NoFixup),
Encoded_GPR_r14(), Locked);
__ xadd(IceType_i8, Address::Absolute(0x1FF00), Encoded_GPR_r14(), Locked);
static constexpr uint8_t ByteCountLocked8 = 1 + ByteCountNotLocked8;
ASSERT_EQ(ByteCountLocked8, codeBytesSize());
ASSERT_TRUE(verifyBytes<ByteCountLocked8>(codeBytes(), 0xF0, 0x67, 0x44,
......@@ -224,8 +223,8 @@ TEST_F(AssemblerX8664LowLevelTest, Xadd) {
}
{
__ xadd(IceType_i16, Address(0x1FF00, AssemblerFixup::NoFixup),
Encoded_GPR_r14(), NotLocked);
__ xadd(IceType_i16, Address::Absolute(0x1FF00), Encoded_GPR_r14(),
NotLocked);
static constexpr uint8_t ByteCountNotLocked16 = 11;
ASSERT_EQ(ByteCountNotLocked16, codeBytesSize());
ASSERT_TRUE(verifyBytes<ByteCountNotLocked16>(codeBytes(), 0x66, 0x67, 0x44,
......@@ -233,8 +232,7 @@ TEST_F(AssemblerX8664LowLevelTest, Xadd) {
0xFF, 0x01, 0x00));
reset();
__ xadd(IceType_i16, Address(0x1FF00, AssemblerFixup::NoFixup),
Encoded_GPR_r14(), Locked);
__ xadd(IceType_i16, Address::Absolute(0x1FF00), Encoded_GPR_r14(), Locked);
static constexpr uint8_t ByteCountLocked16 = 1 + ByteCountNotLocked16;
ASSERT_EQ(ByteCountLocked16, codeBytesSize());
ASSERT_TRUE(verifyBytes<ByteCountLocked16>(codeBytes(), 0x66, 0xF0, 0x67,
......@@ -244,8 +242,8 @@ TEST_F(AssemblerX8664LowLevelTest, Xadd) {
}
{
__ xadd(IceType_i32, Address(0x1FF00, AssemblerFixup::NoFixup),
Encoded_GPR_r14(), NotLocked);
__ xadd(IceType_i32, Address::Absolute(0x1FF00), Encoded_GPR_r14(),
NotLocked);
static constexpr uint8_t ByteCountNotLocked32 = 10;
ASSERT_EQ(ByteCountNotLocked32, codeBytesSize());
ASSERT_TRUE(verifyBytes<ByteCountNotLocked32>(codeBytes(), 0x67, 0x44, 0x0F,
......@@ -253,8 +251,7 @@ TEST_F(AssemblerX8664LowLevelTest, Xadd) {
0x01, 0x00));
reset();
__ xadd(IceType_i32, Address(0x1FF00, AssemblerFixup::NoFixup),
Encoded_GPR_r14(), Locked);
__ xadd(IceType_i32, Address::Absolute(0x1FF00), Encoded_GPR_r14(), Locked);
static constexpr uint8_t ByteCountLocked32 = 1 + ByteCountNotLocked32;
ASSERT_EQ(ByteCountLocked32, codeBytesSize());
ASSERT_TRUE(verifyBytes<ByteCountLocked32>(codeBytes(), 0xF0, 0x67, 0x44,
......@@ -337,14 +334,14 @@ TEST_F(AssemblerX8664LowLevelTest, Cmpxchg8b) {
static constexpr bool Locked = true;
// Ensures that cmpxchg8b emits a lock prefix accordingly.
__ cmpxchg8b(Address(0x1FF00, AssemblerFixup::NoFixup), NotLocked);
__ cmpxchg8b(Address::Absolute(0x1FF00), NotLocked);
static constexpr uint8_t ByteCountNotLocked = 9;
ASSERT_EQ(ByteCountNotLocked, codeBytesSize());
ASSERT_TRUE(verifyBytes<ByteCountNotLocked>(
codeBytes(), 0x67, 0x0F, 0xC7, 0x0C, 0x25, 0x00, 0xFF, 0x01, 0x00));
reset();
__ cmpxchg8b(Address(0x1FF00, AssemblerFixup::NoFixup), Locked);
__ cmpxchg8b(Address::Absolute(0x1FF00), Locked);
static constexpr uint8_t ByteCountLocked = 1 + ByteCountNotLocked;
ASSERT_EQ(ByteCountLocked, codeBytesSize());
ASSERT_TRUE(verifyBytes<ByteCountLocked>(codeBytes(), 0xF0, 0x67, 0x0F, 0xC7,
......@@ -444,8 +441,8 @@ TEST_F(AssemblerX8664LowLevelTest, Cmpxchg) {
// Ensures that cmpxchg emits a lock prefix accordingly.
{
__ cmpxchg(IceType_i8, Address(0x1FF00, AssemblerFixup::NoFixup),
Encoded_GPR_r14(), NotLocked);
__ cmpxchg(IceType_i8, Address::Absolute(0x1FF00), Encoded_GPR_r14(),
NotLocked);
static constexpr uint8_t ByteCountNotLocked8 = 10;
ASSERT_EQ(ByteCountNotLocked8, codeBytesSize());
ASSERT_TRUE(verifyBytes<ByteCountNotLocked8>(codeBytes(), 0x67, 0x44, 0x0F,
......@@ -453,8 +450,8 @@ TEST_F(AssemblerX8664LowLevelTest, Cmpxchg) {
0x01, 0x00));
reset();
__ cmpxchg(IceType_i8, Address(0x1FF00, AssemblerFixup::NoFixup),
Encoded_GPR_r14(), Locked);
__ cmpxchg(IceType_i8, Address::Absolute(0x1FF00), Encoded_GPR_r14(),
Locked);
static constexpr uint8_t ByteCountLocked8 = 1 + ByteCountNotLocked8;
ASSERT_EQ(ByteCountLocked8, codeBytesSize());
ASSERT_TRUE(verifyBytes<ByteCountLocked8>(codeBytes(), 0xF0, 0x67, 0x44,
......@@ -464,8 +461,8 @@ TEST_F(AssemblerX8664LowLevelTest, Cmpxchg) {
}
{
__ cmpxchg(IceType_i16, Address(0x1FF00, AssemblerFixup::NoFixup),
Encoded_GPR_r14(), NotLocked);
__ cmpxchg(IceType_i16, Address::Absolute(0x1FF00), Encoded_GPR_r14(),
NotLocked);
static constexpr uint8_t ByteCountNotLocked16 = 11;
ASSERT_EQ(ByteCountNotLocked16, codeBytesSize());
ASSERT_TRUE(verifyBytes<ByteCountNotLocked16>(codeBytes(), 0x66, 0x67, 0x44,
......@@ -473,8 +470,8 @@ TEST_F(AssemblerX8664LowLevelTest, Cmpxchg) {
0xFF, 0x01, 0x00));
reset();
__ cmpxchg(IceType_i16, Address(0x1FF00, AssemblerFixup::NoFixup),
Encoded_GPR_r14(), Locked);
__ cmpxchg(IceType_i16, Address::Absolute(0x1FF00), Encoded_GPR_r14(),
Locked);
static constexpr uint8_t ByteCountLocked16 = 1 + ByteCountNotLocked16;
ASSERT_EQ(ByteCountLocked16, codeBytesSize());
ASSERT_TRUE(verifyBytes<ByteCountLocked16>(codeBytes(), 0x66, 0xF0, 0x67,
......@@ -484,8 +481,8 @@ TEST_F(AssemblerX8664LowLevelTest, Cmpxchg) {
}
{
__ cmpxchg(IceType_i32, Address(0x1FF00, AssemblerFixup::NoFixup),
Encoded_GPR_r14(), NotLocked);
__ cmpxchg(IceType_i32, Address::Absolute(0x1FF00), Encoded_GPR_r14(),
NotLocked);
static constexpr uint8_t ByteCountNotLocked32 = 10;
ASSERT_EQ(ByteCountNotLocked32, codeBytesSize());
ASSERT_TRUE(verifyBytes<ByteCountNotLocked32>(codeBytes(), 0x67, 0x44, 0x0F,
......@@ -493,8 +490,8 @@ TEST_F(AssemblerX8664LowLevelTest, Cmpxchg) {
0x01, 0x00));
reset();
__ cmpxchg(IceType_i32, Address(0x1FF00, AssemblerFixup::NoFixup),
Encoded_GPR_r14(), Locked);
__ cmpxchg(IceType_i32, Address::Absolute(0x1FF00), Encoded_GPR_r14(),
Locked);
static constexpr uint8_t ByteCountLocked32 = 1 + ByteCountNotLocked32;
ASSERT_EQ(ByteCountLocked32, codeBytesSize());
ASSERT_TRUE(verifyBytes<ByteCountLocked32>(codeBytes(), 0xF0, 0x67, 0x44,
......
......@@ -186,8 +186,7 @@ TEST_F(AssemblerX8664LowLevelTest, Cmp) {
"(" #Inst ", " #Dst ", " #Disp ", " #OpType ", " #ByteCountUntyped \
", " #__VA_ARGS__ ")"; \
static constexpr uint8_t ByteCount = ByteCountUntyped; \
__ Inst(IceType_##OpType, Encoded_GPR_##Dst(), \
Address(Disp, AssemblerFixup::NoFixup)); \
__ Inst(IceType_##OpType, Encoded_GPR_##Dst(), Address::Absolute(Disp)); \
ASSERT_EQ(ByteCount, codeBytesSize()) << TestString; \
ASSERT_TRUE(verifyBytes<ByteCount>(codeBytes(), __VA_ARGS__)) \
<< TestString; \
......
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