Commit aa0b1a17 by David Sehr

Enhance address mode recovery

This adds some more patterns to address mode recovery to recover ConstantRelocatables as displacements, and a few more generalizations that catch indexed addressing. BUG= R=stichnot@chromium.org Review URL: https://codereview.chromium.org/1428443002 .
parent 6a3b5154
...@@ -36,7 +36,6 @@ static uintptr_t NewContents(Assembler &Assemblr, intptr_t Capacity) { ...@@ -36,7 +36,6 @@ static uintptr_t NewContents(Assembler &Assemblr, intptr_t Capacity) {
} }
void AssemblerBuffer::installFixup(AssemblerFixup *F) { void AssemblerBuffer::installFixup(AssemblerFixup *F) {
F->set_position(0);
if (!Assemblr.getPreliminary()) if (!Assemblr.getPreliminary())
Fixups.push_back(F); Fixups.push_back(F);
} }
......
...@@ -3313,14 +3313,23 @@ void AssemblerX86Base<Machine>::emitOperand( ...@@ -3313,14 +3313,23 @@ void AssemblerX86Base<Machine>::emitOperand(
assert(rm >= 0 && rm < 8); assert(rm >= 0 && rm < 8);
const intptr_t length = operand.length_; const intptr_t length = operand.length_;
assert(length > 0); assert(length > 0);
intptr_t displacement_start = 1;
// Emit the ModRM byte updated with the given RM value. // Emit the ModRM byte updated with the given RM value.
assert((operand.encoding_[0] & 0x38) == 0); assert((operand.encoding_[0] & 0x38) == 0);
emitUint8(operand.encoding_[0] + (rm << 3)); emitUint8(operand.encoding_[0] + (rm << 3));
// Whenever the addressing mode is not register indirect, using esp == 0x4
// as the register operation indicates an SIB byte follows.
if (((operand.encoding_[0] & 0xc0) != 0xc0) &&
((operand.encoding_[0] & 0x07) == 0x04)) {
emitUint8(operand.encoding_[1]);
displacement_start = 2;
}
// Emit the displacement and the fixup that affects it, if any.
if (operand.fixup()) { if (operand.fixup()) {
emitFixup(operand.fixup()); emitFixup(operand.fixup());
assert(length - displacement_start == 4);
} }
// Emit the rest of the encoded operand. for (intptr_t i = displacement_start; i < length; i++) {
for (intptr_t i = 1; i < length; i++) {
emitUint8(operand.encoding_[i]); emitUint8(operand.encoding_[i]);
} }
} }
......
...@@ -31,8 +31,14 @@ struct AssemblerFixup { ...@@ -31,8 +31,14 @@ struct AssemblerFixup {
public: public:
AssemblerFixup() = default; AssemblerFixup() = default;
AssemblerFixup(const AssemblerFixup &) = default; AssemblerFixup(const AssemblerFixup &) = default;
intptr_t position() const { return position_; } intptr_t position() const {
void set_position(intptr_t Position) { position_ = Position; } assert(position_was_set_);
return position_;
}
void set_position(intptr_t Position) {
position_ = Position;
position_was_set_ = true;
}
FixupKind kind() const { return kind_; } FixupKind kind() const { return kind_; }
void set_kind(FixupKind Kind) { kind_ = Kind; } void set_kind(FixupKind Kind) { kind_ = Kind; }
...@@ -43,12 +49,15 @@ public: ...@@ -43,12 +49,15 @@ public:
static const Constant *NullSymbol; static const Constant *NullSymbol;
bool isNullSymbol() const { return value_ == NullSymbol; } bool isNullSymbol() const { return value_ == NullSymbol; }
static constexpr AssemblerFixup *NoFixup = nullptr;
void set_value(const Constant *Value) { value_ = Value; } void set_value(const Constant *Value) { value_ = Value; }
/// Emits fixup, then returns the number of bytes to skip. /// Emits fixup, then returns the number of bytes to skip.
virtual size_t emit(GlobalContext *Ctx, const Assembler &Asm) const; virtual size_t emit(GlobalContext *Ctx, const Assembler &Asm) const;
private: private:
bool position_was_set_ = false;
intptr_t position_ = 0; intptr_t position_ = 0;
FixupKind kind_ = 0; FixupKind kind_ = 0;
const Constant *value_ = nullptr; const Constant *value_ = nullptr;
......
...@@ -120,9 +120,10 @@ void MachineTraits<TargetX8632>::X86OperandMem::emit(const Cfg *Func) const { ...@@ -120,9 +120,10 @@ void MachineTraits<TargetX8632>::X86OperandMem::emit(const Cfg *Func) const {
llvm_unreachable("Invalid offset type for x86 mem operand"); llvm_unreachable("Invalid offset type for x86 mem operand");
} }
if (Base) { if (Base || Index) {
Str << "("; Str << "(";
Base->emit(Func); if (Base)
Base->emit(Func);
if (Index) { if (Index) {
Str << ","; Str << ",";
Index->emit(Func); Index->emit(Func);
...@@ -151,8 +152,8 @@ void MachineTraits<TargetX8632>::X86OperandMem::dump(const Cfg *Func, ...@@ -151,8 +152,8 @@ void MachineTraits<TargetX8632>::X86OperandMem::dump(const Cfg *Func,
Dumped = true; Dumped = true;
} }
if (Index) { if (Index) {
assert(Base); if (Base)
Str << "+"; Str << "+";
if (Shift > 0) if (Shift > 0)
Str << (1u << Shift) << "*"; Str << (1u << Shift) << "*";
if (Func) if (Func)
...@@ -216,18 +217,16 @@ MachineTraits<TargetX8632>::X86OperandMem::toAsmAddress( ...@@ -216,18 +217,16 @@ MachineTraits<TargetX8632>::X86OperandMem::toAsmAddress(
return X8632::Traits::Address( return X8632::Traits::Address(
RegX8632::getEncodedGPR(getBase()->getRegNum()), RegX8632::getEncodedGPR(getBase()->getRegNum()),
RegX8632::getEncodedGPR(getIndex()->getRegNum()), RegX8632::getEncodedGPR(getIndex()->getRegNum()),
X8632::Traits::ScaleFactor(getShift()), Disp); X8632::Traits::ScaleFactor(getShift()), Disp, Fixup);
} else if (getBase()) { } else if (getBase()) {
return X8632::Traits::Address( return X8632::Traits::Address(
RegX8632::getEncodedGPR(getBase()->getRegNum()), Disp); RegX8632::getEncodedGPR(getBase()->getRegNum()), Disp, Fixup);
} else if (getIndex()) { } else if (getIndex()) {
return X8632::Traits::Address( return X8632::Traits::Address(
RegX8632::getEncodedGPR(getIndex()->getRegNum()), RegX8632::getEncodedGPR(getIndex()->getRegNum()),
X8632::Traits::ScaleFactor(getShift()), Disp); X8632::Traits::ScaleFactor(getShift()), Disp, Fixup);
} else if (Fixup) {
return X8632::Traits::Address::Absolute(Disp, Fixup);
} else { } else {
return X8632::Traits::Address::Absolute(Disp); return X8632::Traits::Address(Disp, Fixup);
} }
} }
...@@ -238,7 +237,8 @@ MachineTraits<TargetX8632>::VariableSplit::toAsmAddress(const Cfg *Func) const { ...@@ -238,7 +237,8 @@ MachineTraits<TargetX8632>::VariableSplit::toAsmAddress(const Cfg *Func) const {
int32_t Offset = int32_t Offset =
Var->getStackOffset() + Target->getStackAdjustment() + getOffset(); Var->getStackOffset() + Target->getStackAdjustment() + getOffset();
return X8632::Traits::Address( return X8632::Traits::Address(
RegX8632::getEncodedGPR(Target->getFrameOrStackReg()), Offset); RegX8632::getEncodedGPR(Target->getFrameOrStackReg()), Offset,
AssemblerFixup::NoFixup);
} }
void MachineTraits<TargetX8632>::VariableSplit::emit(const Cfg *Func) const { void MachineTraits<TargetX8632>::VariableSplit::emit(const Cfg *Func) const {
......
...@@ -106,9 +106,10 @@ void MachineTraits<TargetX8664>::X86OperandMem::emit(const Cfg *Func) const { ...@@ -106,9 +106,10 @@ void MachineTraits<TargetX8664>::X86OperandMem::emit(const Cfg *Func) const {
llvm_unreachable("Invalid offset type for x86 mem operand"); llvm_unreachable("Invalid offset type for x86 mem operand");
} }
if (Base) { if (Base || Index) {
Str << "("; Str << "(";
Base->emit(Func); if (Base)
Base->emit(Func);
if (Index) { if (Index) {
Str << ","; Str << ",";
Index->emit(Func); Index->emit(Func);
...@@ -133,8 +134,8 @@ void MachineTraits<TargetX8664>::X86OperandMem::dump(const Cfg *Func, ...@@ -133,8 +134,8 @@ void MachineTraits<TargetX8664>::X86OperandMem::dump(const Cfg *Func,
Dumped = true; Dumped = true;
} }
if (Index) { if (Index) {
assert(Base); if (Base)
Str << "+"; Str << "+";
if (Shift > 0) if (Shift > 0)
Str << (1u << Shift) << "*"; Str << (1u << Shift) << "*";
if (Func) if (Func)
...@@ -190,18 +191,16 @@ MachineTraits<TargetX8664>::X86OperandMem::toAsmAddress( ...@@ -190,18 +191,16 @@ MachineTraits<TargetX8664>::X86OperandMem::toAsmAddress(
return X8664::Traits::Address( return X8664::Traits::Address(
RegX8664::getEncodedGPR(getBase()->getRegNum()), RegX8664::getEncodedGPR(getBase()->getRegNum()),
RegX8664::getEncodedGPR(getIndex()->getRegNum()), RegX8664::getEncodedGPR(getIndex()->getRegNum()),
X8664::Traits::ScaleFactor(getShift()), Disp); X8664::Traits::ScaleFactor(getShift()), Disp, Fixup);
} else if (getBase()) { } else if (getBase()) {
return X8664::Traits::Address( return X8664::Traits::Address(
RegX8664::getEncodedGPR(getBase()->getRegNum()), Disp); RegX8664::getEncodedGPR(getBase()->getRegNum()), Disp, Fixup);
} else if (getIndex()) { } else if (getIndex()) {
return X8664::Traits::Address( return X8664::Traits::Address(
RegX8664::getEncodedGPR(getIndex()->getRegNum()), RegX8664::getEncodedGPR(getIndex()->getRegNum()),
X8664::Traits::ScaleFactor(getShift()), Disp); X8664::Traits::ScaleFactor(getShift()), Disp, Fixup);
} else if (Fixup) {
return X8664::Traits::Address::Absolute(Disp, Fixup);
} else { } else {
return X8664::Traits::Address::Absolute(Disp); return X8664::Traits::Address(Disp, Fixup);
} }
} }
...@@ -212,7 +211,8 @@ MachineTraits<TargetX8664>::VariableSplit::toAsmAddress(const Cfg *Func) const { ...@@ -212,7 +211,8 @@ MachineTraits<TargetX8664>::VariableSplit::toAsmAddress(const Cfg *Func) const {
int32_t Offset = int32_t Offset =
Var->getStackOffset() + Target->getStackAdjustment() + getOffset(); Var->getStackOffset() + Target->getStackAdjustment() + getOffset();
return X8664::Traits::Address( return X8664::Traits::Address(
RegX8664::getEncodedGPR(Target->getFrameOrStackReg()), Offset); RegX8664::getEncodedGPR(Target->getFrameOrStackReg()), Offset,
AssemblerFixup::NoFixup);
} }
void MachineTraits<TargetX8664>::VariableSplit::emit(const Cfg *Func) const { void MachineTraits<TargetX8664>::VariableSplit::emit(const Cfg *Func) const {
......
...@@ -2657,7 +2657,8 @@ void InstX86Fld<Machine>::emitIAS(const Cfg *Func) const { ...@@ -2657,7 +2657,8 @@ void InstX86Fld<Machine>::emitIAS(const Cfg *Func) const {
Width); Width);
typename InstX86Base<Machine>::Traits::Address StackSlot = typename InstX86Base<Machine>::Traits::Address StackSlot =
typename InstX86Base<Machine>::Traits::Address( typename InstX86Base<Machine>::Traits::Address(
InstX86Base<Machine>::Traits::RegisterSet::Encoded_Reg_esp, 0); InstX86Base<Machine>::Traits::RegisterSet::Encoded_Reg_esp, 0,
AssemblerFixup::NoFixup);
Asm->movss(Ty, StackSlot, Asm->movss(Ty, StackSlot,
InstX86Base<Machine>::Traits::RegisterSet::getEncodedXmm( InstX86Base<Machine>::Traits::RegisterSet::getEncodedXmm(
Var->getRegNum())); Var->getRegNum()));
...@@ -2755,7 +2756,8 @@ void InstX86Fstp<Machine>::emitIAS(const Cfg *Func) const { ...@@ -2755,7 +2756,8 @@ void InstX86Fstp<Machine>::emitIAS(const Cfg *Func) const {
InstX86Base<Machine>::Traits::RegisterSet::Encoded_Reg_esp, Width); InstX86Base<Machine>::Traits::RegisterSet::Encoded_Reg_esp, Width);
typename InstX86Base<Machine>::Traits::Address StackSlot = typename InstX86Base<Machine>::Traits::Address StackSlot =
typename InstX86Base<Machine>::Traits::Address( typename InstX86Base<Machine>::Traits::Address(
InstX86Base<Machine>::Traits::RegisterSet::Encoded_Reg_esp, 0); InstX86Base<Machine>::Traits::RegisterSet::Encoded_Reg_esp, 0,
AssemblerFixup::NoFixup);
Asm->fstp(Ty, StackSlot); Asm->fstp(Ty, StackSlot);
Asm->movss(Ty, InstX86Base<Machine>::Traits::RegisterSet::getEncodedXmm( Asm->movss(Ty, InstX86Base<Machine>::Traits::RegisterSet::getEncodedXmm(
Dest->getRegNum()), Dest->getRegNum()),
......
...@@ -182,79 +182,69 @@ template <> struct MachineTraits<TargetX8632> { ...@@ -182,79 +182,69 @@ template <> struct MachineTraits<TargetX8632> {
return *this; return *this;
} }
Address(GPRRegister base, int32_t disp) { Address(GPRRegister Base, int32_t Disp, AssemblerFixup *Fixup) {
if (disp == 0 && base != RegX8632::Encoded_Reg_ebp) { if (Fixup == nullptr && Disp == 0 && Base != RegX8632::Encoded_Reg_ebp) {
SetModRM(0, base); SetModRM(0, Base);
if (base == RegX8632::Encoded_Reg_esp) if (Base == RegX8632::Encoded_Reg_esp)
SetSIB(TIMES_1, RegX8632::Encoded_Reg_esp, base); SetSIB(TIMES_1, RegX8632::Encoded_Reg_esp, Base);
} else if (Utils::IsInt(8, disp)) { } else if (Fixup == nullptr && Utils::IsInt(8, Disp)) {
SetModRM(1, base); SetModRM(1, Base);
if (base == RegX8632::Encoded_Reg_esp) if (Base == RegX8632::Encoded_Reg_esp)
SetSIB(TIMES_1, RegX8632::Encoded_Reg_esp, base); SetSIB(TIMES_1, RegX8632::Encoded_Reg_esp, Base);
SetDisp8(disp); SetDisp8(Disp);
} else { } else {
SetModRM(2, base); SetModRM(2, Base);
if (base == RegX8632::Encoded_Reg_esp) if (Base == RegX8632::Encoded_Reg_esp)
SetSIB(TIMES_1, RegX8632::Encoded_Reg_esp, base); SetSIB(TIMES_1, RegX8632::Encoded_Reg_esp, Base);
SetDisp32(disp); SetDisp32(Disp);
if (Fixup)
SetFixup(Fixup);
} }
} }
Address(GPRRegister index, ScaleFactor scale, int32_t disp) { Address(GPRRegister Index, ScaleFactor Scale, int32_t Disp,
assert(index != RegX8632::Encoded_Reg_esp); // Illegal addressing mode. AssemblerFixup *Fixup) {
assert(Index != RegX8632::Encoded_Reg_esp); // Illegal addressing mode.
SetModRM(0, RegX8632::Encoded_Reg_esp); SetModRM(0, RegX8632::Encoded_Reg_esp);
SetSIB(scale, index, RegX8632::Encoded_Reg_ebp); SetSIB(Scale, Index, RegX8632::Encoded_Reg_ebp);
SetDisp32(disp); SetDisp32(Disp);
if (Fixup)
SetFixup(Fixup);
} }
Address(GPRRegister base, GPRRegister index, ScaleFactor scale, Address(GPRRegister Base, GPRRegister Index, ScaleFactor Scale,
int32_t disp) { int32_t Disp, AssemblerFixup *Fixup) {
assert(index != RegX8632::Encoded_Reg_esp); // Illegal addressing mode. assert(Index != RegX8632::Encoded_Reg_esp); // Illegal addressing mode.
if (disp == 0 && base != RegX8632::Encoded_Reg_ebp) { if (Fixup == nullptr && Disp == 0 && Base != RegX8632::Encoded_Reg_ebp) {
SetModRM(0, RegX8632::Encoded_Reg_esp); SetModRM(0, RegX8632::Encoded_Reg_esp);
SetSIB(scale, index, base); SetSIB(Scale, Index, Base);
} else if (Utils::IsInt(8, disp)) { } else if (Fixup == nullptr && Utils::IsInt(8, Disp)) {
SetModRM(1, RegX8632::Encoded_Reg_esp); SetModRM(1, RegX8632::Encoded_Reg_esp);
SetSIB(scale, index, base); SetSIB(Scale, Index, Base);
SetDisp8(disp); SetDisp8(Disp);
} else { } else {
SetModRM(2, RegX8632::Encoded_Reg_esp); SetModRM(2, RegX8632::Encoded_Reg_esp);
SetSIB(scale, index, base); SetSIB(Scale, Index, Base);
SetDisp32(disp); SetDisp32(Disp);
if (Fixup)
SetFixup(Fixup);
} }
} }
/// AbsoluteTag is a special tag used by clients to create an absolute /// Generate an absolute address expression on x86-32.
/// Address. Address(RelocOffsetT Offset, AssemblerFixup *Fixup) {
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); SetModRM(0, RegX8632::Encoded_Reg_ebp);
// Use the Offset in the displacement for now. If we decide to process // Use the Offset in the displacement for now. If we decide to process
// fixups later, we'll need to patch up the emitted displacement. // fixups later, we'll need to patch up the emitted displacement.
SetDisp32(Offset); SetDisp32(Offset);
SetFixup(Fixup); if (Fixup)
} 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) { static Address ofConstPool(Assembler *Asm, const Constant *Imm) {
AssemblerFixup *Fixup = Asm->createFixup(llvm::ELF::R_386_32, Imm); AssemblerFixup *Fixup = Asm->createFixup(llvm::ELF::R_386_32, Imm);
const RelocOffsetT Offset = 0; const RelocOffsetT Offset = 0;
return Address(ABSOLUTE, Offset, Fixup); return Address(Offset, Fixup);
} }
}; };
......
...@@ -201,81 +201,72 @@ template <> struct MachineTraits<TargetX8664> { ...@@ -201,81 +201,72 @@ template <> struct MachineTraits<TargetX8664> {
return *this; return *this;
} }
Address(GPRRegister base, int32_t disp) { Address(GPRRegister Base, int32_t Disp, AssemblerFixup *Fixup) {
if (disp == 0 && (base & 7) != RegX8664::Encoded_Reg_ebp) { if (Fixup == nullptr && Disp == 0 &&
SetModRM(0, base); (Base & 7) != RegX8664::Encoded_Reg_ebp) {
if ((base & 7) == RegX8664::Encoded_Reg_esp) SetModRM(0, Base);
SetSIB(TIMES_1, RegX8664::Encoded_Reg_esp, base); if ((Base & 7) == RegX8664::Encoded_Reg_esp)
} else if (Utils::IsInt(8, disp)) { SetSIB(TIMES_1, RegX8664::Encoded_Reg_esp, Base);
SetModRM(1, base); } else if (Fixup == nullptr && Utils::IsInt(8, Disp)) {
if ((base & 7) == RegX8664::Encoded_Reg_esp) SetModRM(1, Base);
SetSIB(TIMES_1, RegX8664::Encoded_Reg_esp, base); if ((Base & 7) == RegX8664::Encoded_Reg_esp)
SetDisp8(disp); SetSIB(TIMES_1, RegX8664::Encoded_Reg_esp, Base);
SetDisp8(Disp);
} else { } else {
SetModRM(2, base); SetModRM(2, Base);
if ((base & 7) == RegX8664::Encoded_Reg_esp) if ((Base & 7) == RegX8664::Encoded_Reg_esp)
SetSIB(TIMES_1, RegX8664::Encoded_Reg_esp, base); SetSIB(TIMES_1, RegX8664::Encoded_Reg_esp, Base);
SetDisp32(disp); SetDisp32(Disp);
if (Fixup)
SetFixup(Fixup);
} }
} }
Address(GPRRegister index, ScaleFactor scale, int32_t disp) { Address(GPRRegister Index, ScaleFactor Scale, int32_t Disp,
assert(index != RegX8664::Encoded_Reg_esp); // Illegal addressing mode. AssemblerFixup *Fixup) {
assert(Index != RegX8664::Encoded_Reg_esp); // Illegal addressing mode.
SetModRM(0, RegX8664::Encoded_Reg_esp); SetModRM(0, RegX8664::Encoded_Reg_esp);
SetSIB(scale, index, RegX8664::Encoded_Reg_ebp); SetSIB(Scale, Index, RegX8664::Encoded_Reg_ebp);
SetDisp32(disp); SetDisp32(Disp);
if (Fixup)
SetFixup(Fixup);
} }
Address(GPRRegister base, GPRRegister index, ScaleFactor scale, Address(GPRRegister Base, GPRRegister Index, ScaleFactor Scale,
int32_t disp) { int32_t Disp, AssemblerFixup *Fixup) {
assert(index != RegX8664::Encoded_Reg_esp); // Illegal addressing mode. assert(Index != RegX8664::Encoded_Reg_esp); // Illegal addressing mode.
if (disp == 0 && (base & 7) != RegX8664::Encoded_Reg_ebp) { if (Fixup == nullptr && Disp == 0 &&
(Base & 7) != RegX8664::Encoded_Reg_ebp) {
SetModRM(0, RegX8664::Encoded_Reg_esp); SetModRM(0, RegX8664::Encoded_Reg_esp);
SetSIB(scale, index, base); SetSIB(Scale, Index, Base);
} else if (Utils::IsInt(8, disp)) { } else if (Fixup == nullptr && Utils::IsInt(8, Disp)) {
SetModRM(1, RegX8664::Encoded_Reg_esp); SetModRM(1, RegX8664::Encoded_Reg_esp);
SetSIB(scale, index, base); SetSIB(Scale, Index, Base);
SetDisp8(disp); SetDisp8(Disp);
} else { } else {
SetModRM(2, RegX8664::Encoded_Reg_esp); SetModRM(2, RegX8664::Encoded_Reg_esp);
SetSIB(scale, index, base); SetSIB(Scale, Index, Base);
SetDisp32(disp); SetDisp32(Disp);
if (Fixup)
SetFixup(Fixup);
} }
} }
// PcRelTag is a special tag for requesting rip-relative addressing in /// Generate a RIP-relative address expression on x86-64.
// X86-64. Address(RelocOffsetT Offset, AssemblerFixup *Fixup) {
// TODO(jpp): this is bogus. remove.
enum AbsoluteTag { ABSOLUTE };
Address(AbsoluteTag, const uintptr_t Addr) {
SetModRM(0, RegX8664::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, RegX8664::Encoded_Reg_ebp); SetModRM(0, RegX8664::Encoded_Reg_ebp);
// Use the Offset in the displacement for now. If we decide to process // Use the Offset in the displacement for now. If we decide to process
// fixups later, we'll need to patch up the emitted displacement. // fixups later, we'll need to patch up the emitted displacement.
SetDisp32(Offset); SetDisp32(Offset);
SetFixup(Fixup); if (Fixup)
} 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) { static Address ofConstPool(Assembler *Asm, const Constant *Imm) {
// TODO(jpp): ??? // TODO(jpp): ???
AssemblerFixup *Fixup = Asm->createFixup(RelFixup, Imm); AssemblerFixup *Fixup = Asm->createFixup(RelFixup, Imm);
const RelocOffsetT Offset = 4; const RelocOffsetT Offset = 4;
return Address(ABSOLUTE, Offset, Fixup); return Address(Offset, Fixup);
} }
}; };
......
...@@ -798,7 +798,8 @@ TargetX86Base<Machine>::stackVarToAsmOperand(const Variable *Var) const { ...@@ -798,7 +798,8 @@ TargetX86Base<Machine>::stackVarToAsmOperand(const Variable *Var) const {
Offset += getStackAdjustment(); Offset += getStackAdjustment();
} }
return typename Traits::Address( return typename Traits::Address(
Traits::RegisterSet::getEncodedGPR(BaseRegNum), Offset); Traits::RegisterSet::getEncodedGPR(BaseRegNum), Offset,
AssemblerFixup::NoFixup);
} }
/// Helper function for addProlog(). /// Helper function for addProlog().
...@@ -2851,15 +2852,19 @@ TargetX86Base<Machine>::lowerIcmp64(const InstIcmp *Icmp, const InstBr *Br) { ...@@ -2851,15 +2852,19 @@ TargetX86Base<Machine>::lowerIcmp64(const InstIcmp *Icmp, const InstBr *Br) {
break; break;
case InstIcmp::Eq: case InstIcmp::Eq:
case InstIcmp::Ule: case InstIcmp::Ule:
_mov(Temp, Src0LoRM); // Mov Src0HiRM first, because it was legalized most recently, and will
_or(Temp, Src0HiRM); // sometimes avoid a move before the OR.
_mov(Temp, Src0HiRM);
_or(Temp, Src0LoRM);
Context.insert(InstFakeUse::create(Func, Temp)); Context.insert(InstFakeUse::create(Func, Temp));
setccOrBr(Traits::Cond::Br_e, Dest, Br); setccOrBr(Traits::Cond::Br_e, Dest, Br);
return; return;
case InstIcmp::Ne: case InstIcmp::Ne:
case InstIcmp::Ugt: case InstIcmp::Ugt:
_mov(Temp, Src0LoRM); // Mov Src0HiRM first, because it was legalized most recently, and will
_or(Temp, Src0HiRM); // sometimes avoid a move before the OR.
_mov(Temp, Src0HiRM);
_or(Temp, Src0LoRM);
Context.insert(InstFakeUse::create(Func, Temp)); Context.insert(InstFakeUse::create(Func, Temp));
setccOrBr(Traits::Cond::Br_ne, Dest, Br); setccOrBr(Traits::Cond::Br_ne, Dest, Br);
return; return;
...@@ -4094,16 +4099,17 @@ void TargetX86Base<Machine>::lowerIndirectJump(Variable *Target) { ...@@ -4094,16 +4099,17 @@ void TargetX86Base<Machine>::lowerIndirectJump(Variable *Target) {
} }
inline bool isAdd(const Inst *Inst) { inline bool isAdd(const Inst *Inst) {
if (const InstArithmetic *Arith = if (auto *Arith = llvm::dyn_cast_or_null<const InstArithmetic>(Inst)) {
llvm::dyn_cast_or_null<const InstArithmetic>(Inst)) {
return (Arith->getOp() == InstArithmetic::Add); return (Arith->getOp() == InstArithmetic::Add);
} }
return false; return false;
} }
inline void dumpAddressOpt(const Cfg *Func, const Variable *Base, inline void dumpAddressOpt(const Cfg *Func,
const ConstantRelocatable *Relocatable,
int32_t Offset, const Variable *Base,
const Variable *Index, uint16_t Shift, const Variable *Index, uint16_t Shift,
int32_t Offset, const Inst *Reason) { const Inst *Reason) {
if (!BuildDefs::dump()) if (!BuildDefs::dump())
return; return;
if (!Func->isVerbose(IceV_AddrOpt)) if (!Func->isVerbose(IceV_AddrOpt))
...@@ -4122,11 +4128,13 @@ inline void dumpAddressOpt(const Cfg *Func, const Variable *Base, ...@@ -4122,11 +4128,13 @@ inline void dumpAddressOpt(const Cfg *Func, const Variable *Base,
Index->dump(Func); Index->dump(Func);
else else
Str << "<null>"; Str << "<null>";
Str << ", Shift=" << Shift << ", Offset=" << Offset << "\n"; Str << ", Shift=" << Shift << ", Offset=" << Offset
<< ", Relocatable=" << Relocatable << "\n";
} }
inline bool matchTransitiveAssign(const VariablesMetadata *VMetadata, inline bool matchAssign(const VariablesMetadata *VMetadata, Variable *&Var,
Variable *&Var, const Inst *&Reason) { ConstantRelocatable *&Relocatable, int32_t &Offset,
const Inst *&Reason) {
// Var originates from Var=SrcVar ==> set Var:=SrcVar // Var originates from Var=SrcVar ==> set Var:=SrcVar
if (Var == nullptr) if (Var == nullptr)
return false; return false;
...@@ -4135,7 +4143,7 @@ inline bool matchTransitiveAssign(const VariablesMetadata *VMetadata, ...@@ -4135,7 +4143,7 @@ inline bool matchTransitiveAssign(const VariablesMetadata *VMetadata,
if (llvm::isa<InstAssign>(VarAssign)) { if (llvm::isa<InstAssign>(VarAssign)) {
Operand *SrcOp = VarAssign->getSrc(0); Operand *SrcOp = VarAssign->getSrc(0);
assert(SrcOp); assert(SrcOp);
if (Variable *SrcVar = llvm::dyn_cast<Variable>(SrcOp)) { if (auto *SrcVar = llvm::dyn_cast<Variable>(SrcOp)) {
if (!VMetadata->isMultiDef(SrcVar) && if (!VMetadata->isMultiDef(SrcVar) &&
// TODO: ensure SrcVar stays single-BB // TODO: ensure SrcVar stays single-BB
true) { true) {
...@@ -4143,6 +4151,21 @@ inline bool matchTransitiveAssign(const VariablesMetadata *VMetadata, ...@@ -4143,6 +4151,21 @@ inline bool matchTransitiveAssign(const VariablesMetadata *VMetadata,
Reason = VarAssign; Reason = VarAssign;
return true; return true;
} }
} else if (auto *Const = llvm::dyn_cast<ConstantInteger32>(SrcOp)) {
int32_t MoreOffset = Const->getValue();
if (Utils::WouldOverflowAdd(Offset, MoreOffset))
return false;
Var = nullptr;
Offset += MoreOffset;
Reason = VarAssign;
return true;
} else if (auto *AddReloc = llvm::dyn_cast<ConstantRelocatable>(SrcOp)) {
if (Relocatable == nullptr) {
Var = nullptr;
Relocatable = AddReloc;
Reason = VarAssign;
return true;
}
} }
} }
} }
...@@ -4158,16 +4181,16 @@ inline bool matchCombinedBaseIndex(const VariablesMetadata *VMetadata, ...@@ -4158,16 +4181,16 @@ inline bool matchCombinedBaseIndex(const VariablesMetadata *VMetadata,
return false; return false;
if (Index != nullptr) if (Index != nullptr)
return false; return false;
const Inst *BaseInst = VMetadata->getSingleDefinition(Base); auto *BaseInst = VMetadata->getSingleDefinition(Base);
if (BaseInst == nullptr) if (BaseInst == nullptr)
return false; return false;
assert(!VMetadata->isMultiDef(Base)); assert(!VMetadata->isMultiDef(Base));
if (BaseInst->getSrcSize() < 2) if (BaseInst->getSrcSize() < 2)
return false; return false;
if (Variable *Var1 = llvm::dyn_cast<Variable>(BaseInst->getSrc(0))) { if (auto *Var1 = llvm::dyn_cast<Variable>(BaseInst->getSrc(0))) {
if (VMetadata->isMultiDef(Var1)) if (VMetadata->isMultiDef(Var1))
return false; return false;
if (Variable *Var2 = llvm::dyn_cast<Variable>(BaseInst->getSrc(1))) { if (auto *Var2 = llvm::dyn_cast<Variable>(BaseInst->getSrc(1))) {
if (VMetadata->isMultiDef(Var2)) if (VMetadata->isMultiDef(Var2))
return false; return false;
if (isAdd(BaseInst) && if (isAdd(BaseInst) &&
...@@ -4191,20 +4214,23 @@ inline bool matchShiftedIndex(const VariablesMetadata *VMetadata, ...@@ -4191,20 +4214,23 @@ inline bool matchShiftedIndex(const VariablesMetadata *VMetadata,
// Index=Var, Shift+=log2(Const) // Index=Var, Shift+=log2(Const)
if (Index == nullptr) if (Index == nullptr)
return false; return false;
const Inst *IndexInst = VMetadata->getSingleDefinition(Index); auto *IndexInst = VMetadata->getSingleDefinition(Index);
if (IndexInst == nullptr) if (IndexInst == nullptr)
return false; return false;
assert(!VMetadata->isMultiDef(Index)); assert(!VMetadata->isMultiDef(Index));
if (IndexInst->getSrcSize() < 2) if (IndexInst->getSrcSize() < 2)
return false; return false;
if (const InstArithmetic *ArithInst = if (auto *ArithInst = llvm::dyn_cast<InstArithmetic>(IndexInst)) {
llvm::dyn_cast<InstArithmetic>(IndexInst)) { if (auto *Var = llvm::dyn_cast<Variable>(ArithInst->getSrc(0))) {
if (Variable *Var = llvm::dyn_cast<Variable>(ArithInst->getSrc(0))) { if (auto *Const =
if (ConstantInteger32 *Const =
llvm::dyn_cast<ConstantInteger32>(ArithInst->getSrc(1))) { llvm::dyn_cast<ConstantInteger32>(ArithInst->getSrc(1))) {
if (ArithInst->getOp() == InstArithmetic::Mul && if (VMetadata->isMultiDef(Var) || Const->getType() != IceType_i32)
!VMetadata->isMultiDef(Var) && Const->getType() == IceType_i32) { return false;
uint64_t Mult = Const->getValue(); switch (ArithInst->getOp()) {
default:
return false;
case InstArithmetic::Mul: {
uint32_t Mult = Const->getValue();
uint32_t LogMult; uint32_t LogMult;
switch (Mult) { switch (Mult) {
case 1: case 1:
...@@ -4229,6 +4255,25 @@ inline bool matchShiftedIndex(const VariablesMetadata *VMetadata, ...@@ -4229,6 +4255,25 @@ inline bool matchShiftedIndex(const VariablesMetadata *VMetadata,
return true; return true;
} }
} }
case InstArithmetic::Shl: {
uint32_t ShiftAmount = Const->getValue();
switch (ShiftAmount) {
case 0:
case 1:
case 2:
case 3:
break;
default:
return false;
}
if (Shift + ShiftAmount <= 3) {
Index = Var;
Shift += ShiftAmount;
Reason = IndexInst;
return true;
}
}
}
} }
} }
} }
...@@ -4236,49 +4281,93 @@ inline bool matchShiftedIndex(const VariablesMetadata *VMetadata, ...@@ -4236,49 +4281,93 @@ inline bool matchShiftedIndex(const VariablesMetadata *VMetadata,
} }
inline bool matchOffsetBase(const VariablesMetadata *VMetadata, Variable *&Base, inline bool matchOffsetBase(const VariablesMetadata *VMetadata, Variable *&Base,
int32_t &Offset, const Inst *&Reason) { ConstantRelocatable *&Relocatable, int32_t &Offset,
const Inst *&Reason) {
// Base is Base=Var+Const || Base is Base=Const+Var ==> // Base is Base=Var+Const || Base is Base=Const+Var ==>
// set Base=Var, Offset+=Const // set Base=Var, Offset+=Const
// Base is Base=Var-Const ==> // Base is Base=Var-Const ==>
// set Base=Var, Offset-=Const // set Base=Var, Offset-=Const
if (Base == nullptr) if (Base == nullptr) {
return false; return false;
}
const Inst *BaseInst = VMetadata->getSingleDefinition(Base); const Inst *BaseInst = VMetadata->getSingleDefinition(Base);
if (BaseInst == nullptr) if (BaseInst == nullptr) {
return false; return false;
}
assert(!VMetadata->isMultiDef(Base)); assert(!VMetadata->isMultiDef(Base));
if (const InstArithmetic *ArithInst = if (auto *ArithInst = llvm::dyn_cast<const InstArithmetic>(BaseInst)) {
llvm::dyn_cast<const InstArithmetic>(BaseInst)) {
if (ArithInst->getOp() != InstArithmetic::Add && if (ArithInst->getOp() != InstArithmetic::Add &&
ArithInst->getOp() != InstArithmetic::Sub) ArithInst->getOp() != InstArithmetic::Sub)
return false; return false;
bool IsAdd = ArithInst->getOp() == InstArithmetic::Add; bool IsAdd = ArithInst->getOp() == InstArithmetic::Add;
Variable *Var = nullptr; Operand *Src0 = ArithInst->getSrc(0);
ConstantInteger32 *Const = nullptr; Operand *Src1 = ArithInst->getSrc(1);
if (Variable *VariableOperand = auto *Var0 = llvm::dyn_cast<Variable>(Src0);
llvm::dyn_cast<Variable>(ArithInst->getSrc(0))) { auto *Var1 = llvm::dyn_cast<Variable>(Src1);
Var = VariableOperand; auto *Const0 = llvm::dyn_cast<ConstantInteger32>(Src0);
Const = llvm::dyn_cast<ConstantInteger32>(ArithInst->getSrc(1)); auto *Const1 = llvm::dyn_cast<ConstantInteger32>(Src1);
} else if (IsAdd) { auto *Reloc0 = llvm::dyn_cast<ConstantRelocatable>(Src0);
Const = llvm::dyn_cast<ConstantInteger32>(ArithInst->getSrc(0)); auto *Reloc1 = llvm::dyn_cast<ConstantRelocatable>(Src1);
Var = llvm::dyn_cast<Variable>(ArithInst->getSrc(1)); Variable *NewBase = nullptr;
} int32_t NewOffset = Offset;
if (Var == nullptr || Const == nullptr || VMetadata->isMultiDef(Var)) ConstantRelocatable *NewRelocatable = Relocatable;
if (Var0 && Var1)
// TODO(sehr): merge base/index splitting into here.
return false; return false;
int32_t MoreOffset = IsAdd ? Const->getValue() : -Const->getValue(); if (!IsAdd && Var1)
if (Utils::WouldOverflowAdd(Offset, MoreOffset))
return false; return false;
Base = Var; if (Var0)
Offset += MoreOffset; NewBase = Var0;
else if (Var1)
NewBase = Var1;
// Don't know how to add/subtract two relocatables.
if ((Relocatable && (Reloc0 || Reloc1)) || (Reloc0 && Reloc1))
return false;
// Don't know how to subtract a relocatable.
if (!IsAdd && Reloc1)
return false;
// Incorporate ConstantRelocatables.
if (Reloc0)
NewRelocatable = Reloc0;
else if (Reloc1)
NewRelocatable = Reloc1;
// Compute the updated constant offset.
if (Const0) {
int32_t MoreOffset = IsAdd ? Const0->getValue() : -Const0->getValue();
if (Utils::WouldOverflowAdd(NewOffset, MoreOffset))
return false;
NewOffset += MoreOffset;
}
if (Const1) {
int32_t MoreOffset = IsAdd ? Const1->getValue() : -Const1->getValue();
if (Utils::WouldOverflowAdd(NewOffset, MoreOffset))
return false;
NewOffset += MoreOffset;
}
// Update the computed address parameters once we are sure optimization
// is valid.
Base = NewBase;
Offset = NewOffset;
Relocatable = NewRelocatable;
Reason = BaseInst; Reason = BaseInst;
return true; return true;
} }
return false; return false;
} }
inline void computeAddressOpt(Cfg *Func, const Inst *Instr, Variable *&Base, // Builds information for a canonical address expresion:
Variable *&Index, uint16_t &Shift, // <Relocatable + Offset>(Base, Index, Shift)
int32_t &Offset) { // On entry:
// Relocatable == null,
// Offset == 0,
// Base is a Variable,
// Index == nullptr,
// Shift == 0
inline bool computeAddressOpt(Cfg *Func, const Inst *Instr,
ConstantRelocatable *&Relocatable,
int32_t &Offset, Variable *&Base,
Variable *&Index, uint16_t &Shift) {
bool AddressWasOptimized = false;
Func->resetCurrentNode(); Func->resetCurrentNode();
if (Func->isVerbose(IceV_AddrOpt)) { if (Func->isVerbose(IceV_AddrOpt)) {
OstreamLocker L(Func->getContext()); OstreamLocker L(Func->getContext());
...@@ -4286,54 +4375,75 @@ inline void computeAddressOpt(Cfg *Func, const Inst *Instr, Variable *&Base, ...@@ -4286,54 +4375,75 @@ inline void computeAddressOpt(Cfg *Func, const Inst *Instr, Variable *&Base,
Str << "\nStarting computeAddressOpt for instruction:\n "; Str << "\nStarting computeAddressOpt for instruction:\n ";
Instr->dumpDecorated(Func); Instr->dumpDecorated(Func);
} }
(void)Offset; // TODO: pattern-match for non-zero offsets.
if (Base == nullptr) if (Base == nullptr)
return; return AddressWasOptimized;
// If the Base has more than one use or is live across multiple blocks, then // If the Base has more than one use or is live across multiple blocks, then
// don't go further. Alternatively (?), never consider a transformation that // don't go further. Alternatively (?), never consider a transformation that
// would change a variable that is currently *not* live across basic block // would change a variable that is currently *not* live across basic block
// boundaries into one that *is*. // boundaries into one that *is*.
if (Func->getVMetadata()->isMultiBlock(Base) /* || Base->getUseCount() > 1*/) if (Func->getVMetadata()->isMultiBlock(Base) /* || Base->getUseCount() > 1*/)
return; return AddressWasOptimized;
const bool MockBounds = Func->getContext()->getFlags().getMockBoundsCheck(); const bool MockBounds = Func->getContext()->getFlags().getMockBoundsCheck();
const VariablesMetadata *VMetadata = Func->getVMetadata(); const VariablesMetadata *VMetadata = Func->getVMetadata();
bool Continue = true; const Inst *Reason = nullptr;
while (Continue) { do {
const Inst *Reason = nullptr; if (Reason) {
if (matchTransitiveAssign(VMetadata, Base, Reason) || dumpAddressOpt(Func, Relocatable, Offset, Base, Index, Shift, Reason);
matchTransitiveAssign(VMetadata, Index, Reason) || AddressWasOptimized = true;
(!MockBounds && Reason = nullptr;
matchCombinedBaseIndex(VMetadata, Base, Index, Shift, Reason)) ||
(!MockBounds && matchShiftedIndex(VMetadata, Index, Shift, Reason)) ||
matchOffsetBase(VMetadata, Base, Offset, Reason)) {
dumpAddressOpt(Func, Base, Index, Shift, Offset, Reason);
} else {
Continue = false;
} }
// Update Base and Index to follow through assignments to definitions.
if (matchAssign(VMetadata, Base, Relocatable, Offset, Reason)) {
// Assignments of Base from a Relocatable or ConstantInt32 can result
// in Base becoming nullptr. To avoid code duplication in this loop we
// prefer that Base be non-nullptr if possible.
if ((Base == nullptr) && (Index != nullptr) && (Shift == 0))
std::swap(Base, Index);
continue;
}
if (matchAssign(VMetadata, Index, Relocatable, Offset, Reason))
continue;
// Index is Index=Var<<Const && Const+Shift<=3 ==> if (!MockBounds) {
// Index=Var, Shift+=Const // Transition from:
// <Relocatable + Offset>(Base) to
// Index is Index=Const*Var && log2(Const)+Shift<=3 ==> // <Relocatable + Offset>(Base, Index)
// Index=Var, Shift+=log2(Const) if (matchCombinedBaseIndex(VMetadata, Base, Index, Shift, Reason))
continue;
// Index && Shift==0 && Base is Base=Var*Const && log2(Const)+Shift<=3 ==> // Recognize multiply/shift and update Shift amount.
// swap(Index,Base) // Index becomes Index=Var<<Const && Const+Shift<=3 ==>
// Similar for Base=Const*Var and Base=Var<<Const // Index=Var, Shift+=Const
// Index becomes Index=Const*Var && log2(Const)+Shift<=3 ==>
// Index=Var, Shift+=log2(Const)
if (matchShiftedIndex(VMetadata, Index, Shift, Reason))
continue;
// If Shift is zero, the choice of Base and Index was purely arbitrary.
// Recognize multiply/shift and set Shift amount.
// Shift==0 && Base is Base=Var*Const && log2(Const)+Shift<=3 ==>
// swap(Index,Base)
// Similar for Base=Const*Var and Base=Var<<Const
if ((Shift == 0) && matchShiftedIndex(VMetadata, Base, Shift, Reason)) {
std::swap(Base, Index);
continue;
}
}
// Update Offset to reflect additions/subtractions with constants and
// relocatables.
// TODO: consider overflow issues with respect to Offset.
// TODO: handle symbolic constants.
if (matchOffsetBase(VMetadata, Base, Relocatable, Offset, Reason))
continue;
// TODO(sehr, stichnot): Handle updates of Index with Shift != 0.
// Index is Index=Var+Const ==> // Index is Index=Var+Const ==>
// set Index=Var, Offset+=(Const<<Shift) // set Index=Var, Offset+=(Const<<Shift)
// Index is Index=Const+Var ==> // Index is Index=Const+Var ==>
// set Index=Var, Offset+=(Const<<Shift) // set Index=Var, Offset+=(Const<<Shift)
// Index is Index=Var-Const ==> // Index is Index=Var-Const ==>
// set Index=Var, Offset-=(Const<<Shift) // set Index=Var, Offset-=(Const<<Shift)
break;
// TODO: consider overflow issues with respect to Offset. } while (Reason);
// TODO: handle symbolic constants. return AddressWasOptimized;
}
} }
/// Add a mock bounds check on the memory address before using it as a load or /// Add a mock bounds check on the memory address before using it as a load or
...@@ -4415,19 +4525,26 @@ template <class Machine> void TargetX86Base<Machine>::doAddressOptLoad() { ...@@ -4415,19 +4525,26 @@ template <class Machine> void TargetX86Base<Machine>::doAddressOptLoad() {
Variable *Dest = Inst->getDest(); Variable *Dest = Inst->getDest();
Operand *Addr = Inst->getSrc(0); Operand *Addr = Inst->getSrc(0);
Variable *Index = nullptr; Variable *Index = nullptr;
ConstantRelocatable *Relocatable = nullptr;
uint16_t Shift = 0; uint16_t Shift = 0;
int32_t Offset = 0; // TODO: make Constant int32_t Offset = 0;
// Vanilla ICE load instructions should not use the segment registers, and // Vanilla ICE load instructions should not use the segment registers, and
// computeAddressOpt only works at the level of Variables and Constants, not // computeAddressOpt only works at the level of Variables and Constants, not
// other Traits::X86OperandMem, so there should be no mention of segment // other Traits::X86OperandMem, so there should be no mention of segment
// registers there either. // registers there either.
const typename Traits::X86OperandMem::SegmentRegisters SegmentReg = const typename Traits::X86OperandMem::SegmentRegisters SegmentReg =
Traits::X86OperandMem::DefaultSegment; Traits::X86OperandMem::DefaultSegment;
Variable *Base = llvm::dyn_cast<Variable>(Addr); auto *Base = llvm::dyn_cast<Variable>(Addr);
computeAddressOpt(Func, Inst, Base, Index, Shift, Offset); if (computeAddressOpt(Func, Inst, Relocatable, Offset, Base, Index, Shift)) {
if (Base && Addr != Base) {
Inst->setDeleted(); Inst->setDeleted();
Constant *OffsetOp = Ctx->getConstantInt32(Offset); Constant *OffsetOp = nullptr;
if (Relocatable == nullptr) {
OffsetOp = Ctx->getConstantInt32(Offset);
} else {
OffsetOp = Ctx->getConstantSym(Relocatable->getOffset() + Offset,
Relocatable->getName(),
Relocatable->getSuppressMangling());
}
Addr = Traits::X86OperandMem::create(Func, Dest->getType(), Base, OffsetOp, Addr = Traits::X86OperandMem::create(Func, Dest->getType(), Base, OffsetOp,
Index, Shift, SegmentReg); Index, Shift, SegmentReg);
Context.insert(InstLoad::create(Func, Dest, Addr)); Context.insert(InstLoad::create(Func, Dest, Addr));
...@@ -4623,19 +4740,26 @@ template <class Machine> void TargetX86Base<Machine>::doAddressOptStore() { ...@@ -4623,19 +4740,26 @@ template <class Machine> void TargetX86Base<Machine>::doAddressOptStore() {
Operand *Data = Inst->getData(); Operand *Data = Inst->getData();
Operand *Addr = Inst->getAddr(); Operand *Addr = Inst->getAddr();
Variable *Index = nullptr; Variable *Index = nullptr;
ConstantRelocatable *Relocatable = nullptr;
uint16_t Shift = 0; uint16_t Shift = 0;
int32_t Offset = 0; // TODO: make Constant int32_t Offset = 0;
Variable *Base = llvm::dyn_cast<Variable>(Addr); auto *Base = llvm::dyn_cast<Variable>(Addr);
// Vanilla ICE store instructions should not use the segment registers, and // Vanilla ICE store instructions should not use the segment registers, and
// computeAddressOpt only works at the level of Variables and Constants, not // computeAddressOpt only works at the level of Variables and Constants, not
// other Traits::X86OperandMem, so there should be no mention of segment // other Traits::X86OperandMem, so there should be no mention of segment
// registers there either. // registers there either.
const typename Traits::X86OperandMem::SegmentRegisters SegmentReg = const typename Traits::X86OperandMem::SegmentRegisters SegmentReg =
Traits::X86OperandMem::DefaultSegment; Traits::X86OperandMem::DefaultSegment;
computeAddressOpt(Func, Inst, Base, Index, Shift, Offset); if (computeAddressOpt(Func, Inst, Relocatable, Offset, Base, Index, Shift)) {
if (Base && Addr != Base) {
Inst->setDeleted(); Inst->setDeleted();
Constant *OffsetOp = Ctx->getConstantInt32(Offset); Constant *OffsetOp = nullptr;
if (Relocatable == nullptr) {
OffsetOp = Ctx->getConstantInt32(Offset);
} else {
OffsetOp = Ctx->getConstantSym(Relocatable->getOffset() + Offset,
Relocatable->getName(),
Relocatable->getSuppressMangling());
}
Addr = Traits::X86OperandMem::create(Func, Data->getType(), Base, OffsetOp, Addr = Traits::X86OperandMem::create(Func, Data->getType(), Base, OffsetOp,
Index, Shift, SegmentReg); Index, Shift, SegmentReg);
InstStore *NewStore = InstStore::create(Func, Data, Addr); InstStore *NewStore = InstStore::create(Func, Data, Addr);
......
; This file checks support for address mode optimization.
; RUN: %p2i --filetype=obj --disassemble -i %s --args -O2 \
; RUN: -allow-externally-defined-symbols | FileCheck %s
@bytes = internal global [1024 x i8] zeroinitializer
define internal i32 @load_global_direct() {
entry:
%base = ptrtoint [1024 x i8]* @bytes to i32
%addr_lo.int = add i32 0, %base
%addr_hi.int = add i32 4, %base
%addr_lo.ptr = inttoptr i32 %addr_lo.int to i32*
%addr_hi.ptr = inttoptr i32 %addr_hi.int to i32*
%addr_lo.load = load i32, i32* %addr_lo.ptr, align 1
%addr_hi.load = load i32, i32* %addr_hi.ptr, align 1
%result = add i32 %addr_lo.load, %addr_hi.load
ret i32 %result
; CHECK-LABEL: load_global_direct
; CHECK-NEXT: mov eax,DWORD PTR ds:0x0{{.*}}bytes
; CHECK-NEXT: add eax,DWORD PTR ds:0x4{{.*}}bytes
}
define internal i32 @load_global_indexed(i32 %arg) {
entry:
%offset = shl i32 %arg, 3
%base = ptrtoint [1024 x i8]* @bytes to i32
%addr.int = add i32 %offset, %base
%addr.ptr = inttoptr i32 %addr.int to i32*
%addr.load = load i32, i32* %addr.ptr, align 1
ret i32 %addr.load
; CHECK-LABEL: load_global_indexed
; CHECK-NEXT: mov eax,DWORD PTR [esp+0x4]
; CHECK-NEXT: mov eax,DWORD PTR [eax*8+0x0]
}
...@@ -133,7 +133,7 @@ TEST_F(AssemblerX8632Test, CallAddr) { ...@@ -133,7 +133,7 @@ TEST_F(AssemblerX8632Test, CallAddr) {
__ hlt(); __ hlt();
__ hlt(); __ hlt();
__ mov(IceType_i32, GPRRegister::Encoded_Reg_eax, Immediate(0xf1f2f300)); __ mov(IceType_i32, GPRRegister::Encoded_Reg_eax, Immediate(0xf1f2f300));
__ call(Address(GPRRegister::Encoded_Reg_esp, 0)); __ call(Address(GPRRegister::Encoded_Reg_esp, 0, AssemblerFixup::NoFixup));
__ popl(GPRRegister::Encoded_Reg_edx); __ popl(GPRRegister::Encoded_Reg_edx);
AssembledTest test = assemble(); AssembledTest test = assemble();
......
...@@ -132,7 +132,8 @@ TEST_F(AssemblerX8632Test, Lea) { ...@@ -132,7 +132,8 @@ TEST_F(AssemblerX8632Test, Lea) {
Immediate(BaseValue)); \ Immediate(BaseValue)); \
} \ } \
__ lea(IceType_i32, GPRRegister::Encoded_Reg_##Dst, \ __ lea(IceType_i32, GPRRegister::Encoded_Reg_##Dst, \
Address(GPRRegister::Encoded_Reg_##Base, Disp)); \ Address(GPRRegister::Encoded_Reg_##Base, Disp, \
AssemblerFixup::NoFixup)); \
AssembledTest test = assemble(); \ AssembledTest test = assemble(); \
test.run(); \ test.run(); \
ASSERT_EQ(test.Base() + (Disp), test.Dst()) << TestString << " with Disp " \ ASSERT_EQ(test.Base() + (Disp), test.Dst()) << TestString << " with Disp " \
...@@ -148,13 +149,17 @@ TEST_F(AssemblerX8632Test, Lea) { ...@@ -148,13 +149,17 @@ TEST_F(AssemblerX8632Test, Lea) {
__ mov(IceType_i32, GPRRegister::Encoded_Reg_##Index, \ __ mov(IceType_i32, GPRRegister::Encoded_Reg_##Index, \
Immediate(IndexValue)); \ Immediate(IndexValue)); \
__ lea(IceType_i32, GPRRegister::Encoded_Reg_##Dst0, \ __ lea(IceType_i32, GPRRegister::Encoded_Reg_##Dst0, \
Address(GPRRegister::Encoded_Reg_##Index, Traits::TIMES_1, Disp)); \ Address(GPRRegister::Encoded_Reg_##Index, Traits::TIMES_1, Disp, \
AssemblerFixup::NoFixup)); \
__ lea(IceType_i32, GPRRegister::Encoded_Reg_##Dst1, \ __ lea(IceType_i32, GPRRegister::Encoded_Reg_##Dst1, \
Address(GPRRegister::Encoded_Reg_##Index, Traits::TIMES_2, Disp)); \ Address(GPRRegister::Encoded_Reg_##Index, Traits::TIMES_2, Disp, \
AssemblerFixup::NoFixup)); \
__ lea(IceType_i32, GPRRegister::Encoded_Reg_##Dst2, \ __ lea(IceType_i32, GPRRegister::Encoded_Reg_##Dst2, \
Address(GPRRegister::Encoded_Reg_##Index, Traits::TIMES_4, Disp)); \ Address(GPRRegister::Encoded_Reg_##Index, Traits::TIMES_4, Disp, \
AssemblerFixup::NoFixup)); \
__ lea(IceType_i32, GPRRegister::Encoded_Reg_##Dst3, \ __ lea(IceType_i32, GPRRegister::Encoded_Reg_##Dst3, \
Address(GPRRegister::Encoded_Reg_##Index, Traits::TIMES_8, Disp)); \ Address(GPRRegister::Encoded_Reg_##Index, Traits::TIMES_8, Disp, \
AssemblerFixup::NoFixup)); \
AssembledTest test = assemble(); \ AssembledTest test = assemble(); \
test.run(); \ test.run(); \
ASSERT_EQ((test.Index() << Traits::TIMES_1) + (Disp), test.Dst0()) \ ASSERT_EQ((test.Index() << Traits::TIMES_1) + (Disp), test.Dst0()) \
...@@ -186,16 +191,20 @@ TEST_F(AssemblerX8632Test, Lea) { ...@@ -186,16 +191,20 @@ TEST_F(AssemblerX8632Test, Lea) {
} \ } \
__ lea(IceType_i32, GPRRegister::Encoded_Reg_##Dst0, \ __ lea(IceType_i32, GPRRegister::Encoded_Reg_##Dst0, \
Address(GPRRegister::Encoded_Reg_##Base, \ Address(GPRRegister::Encoded_Reg_##Base, \
GPRRegister::Encoded_Reg_##Index, Traits::TIMES_1, Disp)); \ GPRRegister::Encoded_Reg_##Index, Traits::TIMES_1, Disp, \
AssemblerFixup::NoFixup)); \
__ lea(IceType_i32, GPRRegister::Encoded_Reg_##Dst1, \ __ lea(IceType_i32, GPRRegister::Encoded_Reg_##Dst1, \
Address(GPRRegister::Encoded_Reg_##Base, \ Address(GPRRegister::Encoded_Reg_##Base, \
GPRRegister::Encoded_Reg_##Index, Traits::TIMES_2, Disp)); \ GPRRegister::Encoded_Reg_##Index, Traits::TIMES_2, Disp, \
AssemblerFixup::NoFixup)); \
__ lea(IceType_i32, GPRRegister::Encoded_Reg_##Dst2, \ __ lea(IceType_i32, GPRRegister::Encoded_Reg_##Dst2, \
Address(GPRRegister::Encoded_Reg_##Base, \ Address(GPRRegister::Encoded_Reg_##Base, \
GPRRegister::Encoded_Reg_##Index, Traits::TIMES_4, Disp)); \ GPRRegister::Encoded_Reg_##Index, Traits::TIMES_4, Disp, \
AssemblerFixup::NoFixup)); \
__ lea(IceType_i32, GPRRegister::Encoded_Reg_##Dst3, \ __ lea(IceType_i32, GPRRegister::Encoded_Reg_##Dst3, \
Address(GPRRegister::Encoded_Reg_##Base, \ Address(GPRRegister::Encoded_Reg_##Base, \
GPRRegister::Encoded_Reg_##Index, Traits::TIMES_8, Disp)); \ GPRRegister::Encoded_Reg_##Index, Traits::TIMES_8, Disp, \
AssemblerFixup::NoFixup)); \
AssembledTest test = assemble(); \ AssembledTest test = assemble(); \
test.run(); \ test.run(); \
uint32_t ExpectedIndexValue = test.Index(); \ uint32_t ExpectedIndexValue = test.Index(); \
...@@ -287,7 +296,7 @@ TEST_F(AssemblerX8632LowLevelTest, LeaAbsolute) { ...@@ -287,7 +296,7 @@ TEST_F(AssemblerX8632LowLevelTest, LeaAbsolute) {
do { \ do { \
static constexpr char TestString[] = "(" #Dst ", " #Value ")"; \ static constexpr char TestString[] = "(" #Dst ", " #Value ")"; \
__ lea(IceType_i32, GPRRegister::Encoded_Reg_##Dst, \ __ lea(IceType_i32, GPRRegister::Encoded_Reg_##Dst, \
Address(Address::ABSOLUTE, Value)); \ Address(Value, AssemblerFixup::NoFixup)); \
static constexpr uint32_t ByteCount = 6; \ static constexpr uint32_t ByteCount = 6; \
ASSERT_EQ(ByteCount, codeBytesSize()) << TestString; \ ASSERT_EQ(ByteCount, codeBytesSize()) << TestString; \
static constexpr uint8_t Opcode = 0x8D; \ static constexpr uint8_t Opcode = 0x8D; \
......
...@@ -200,7 +200,7 @@ TEST_F(AssemblerX8632LowLevelTest, Xadd) { ...@@ -200,7 +200,7 @@ TEST_F(AssemblerX8632LowLevelTest, Xadd) {
// Ensures that xadd emits a lock prefix accordingly. // Ensures that xadd emits a lock prefix accordingly.
{ {
__ xadd(IceType_i8, Address::Absolute(0x1FF00), __ xadd(IceType_i8, Address(0x1FF00, AssemblerFixup::NoFixup),
GPRRegister::Encoded_Reg_esi, NotLocked); GPRRegister::Encoded_Reg_esi, NotLocked);
static constexpr uint8_t ByteCountNotLocked8 = 7; static constexpr uint8_t ByteCountNotLocked8 = 7;
ASSERT_EQ(ByteCountNotLocked8, codeBytesSize()); ASSERT_EQ(ByteCountNotLocked8, codeBytesSize());
...@@ -208,7 +208,7 @@ TEST_F(AssemblerX8632LowLevelTest, Xadd) { ...@@ -208,7 +208,7 @@ TEST_F(AssemblerX8632LowLevelTest, Xadd) {
0x01, 0x00); 0x01, 0x00);
reset(); reset();
__ xadd(IceType_i8, Address::Absolute(0x1FF00), __ xadd(IceType_i8, Address(0x1FF00, AssemblerFixup::NoFixup),
GPRRegister::Encoded_Reg_esi, Locked); GPRRegister::Encoded_Reg_esi, Locked);
static constexpr uint8_t ByteCountLocked8 = 1 + ByteCountNotLocked8; static constexpr uint8_t ByteCountLocked8 = 1 + ByteCountNotLocked8;
ASSERT_EQ(ByteCountLocked8, codeBytesSize()); ASSERT_EQ(ByteCountLocked8, codeBytesSize());
...@@ -218,7 +218,7 @@ TEST_F(AssemblerX8632LowLevelTest, Xadd) { ...@@ -218,7 +218,7 @@ TEST_F(AssemblerX8632LowLevelTest, Xadd) {
} }
{ {
__ xadd(IceType_i16, Address::Absolute(0x1FF00), __ xadd(IceType_i16, Address(0x1FF00, AssemblerFixup::NoFixup),
GPRRegister::Encoded_Reg_esi, NotLocked); GPRRegister::Encoded_Reg_esi, NotLocked);
static constexpr uint8_t ByteCountNotLocked16 = 8; static constexpr uint8_t ByteCountNotLocked16 = 8;
ASSERT_EQ(ByteCountNotLocked16, codeBytesSize()); ASSERT_EQ(ByteCountNotLocked16, codeBytesSize());
...@@ -226,7 +226,7 @@ TEST_F(AssemblerX8632LowLevelTest, Xadd) { ...@@ -226,7 +226,7 @@ TEST_F(AssemblerX8632LowLevelTest, Xadd) {
0xFF, 0x01, 0x00); 0xFF, 0x01, 0x00);
reset(); reset();
__ xadd(IceType_i16, Address::Absolute(0x1FF00), __ xadd(IceType_i16, Address(0x1FF00, AssemblerFixup::NoFixup),
GPRRegister::Encoded_Reg_esi, Locked); GPRRegister::Encoded_Reg_esi, Locked);
static constexpr uint8_t ByteCountLocked16 = 1 + ByteCountNotLocked16; static constexpr uint8_t ByteCountLocked16 = 1 + ByteCountNotLocked16;
ASSERT_EQ(ByteCountLocked16, codeBytesSize()); ASSERT_EQ(ByteCountLocked16, codeBytesSize());
...@@ -236,7 +236,7 @@ TEST_F(AssemblerX8632LowLevelTest, Xadd) { ...@@ -236,7 +236,7 @@ TEST_F(AssemblerX8632LowLevelTest, Xadd) {
} }
{ {
__ xadd(IceType_i32, Address::Absolute(0x1FF00), __ xadd(IceType_i32, Address(0x1FF00, AssemblerFixup::NoFixup),
GPRRegister::Encoded_Reg_esi, NotLocked); GPRRegister::Encoded_Reg_esi, NotLocked);
static constexpr uint8_t ByteCountNotLocked32 = 7; static constexpr uint8_t ByteCountNotLocked32 = 7;
ASSERT_EQ(ByteCountNotLocked32, codeBytesSize()); ASSERT_EQ(ByteCountNotLocked32, codeBytesSize());
...@@ -244,7 +244,7 @@ TEST_F(AssemblerX8632LowLevelTest, Xadd) { ...@@ -244,7 +244,7 @@ TEST_F(AssemblerX8632LowLevelTest, Xadd) {
0x01, 0x00); 0x01, 0x00);
reset(); reset();
__ xadd(IceType_i32, Address::Absolute(0x1FF00), __ xadd(IceType_i32, Address(0x1FF00, AssemblerFixup::NoFixup),
GPRRegister::Encoded_Reg_esi, Locked); GPRRegister::Encoded_Reg_esi, Locked);
static constexpr uint8_t ByteCountLocked32 = 1 + ByteCountNotLocked32; static constexpr uint8_t ByteCountLocked32 = 1 + ByteCountNotLocked32;
ASSERT_EQ(ByteCountLocked32, codeBytesSize()); ASSERT_EQ(ByteCountLocked32, codeBytesSize());
...@@ -307,14 +307,14 @@ TEST_F(AssemblerX8632LowLevelTest, Cmpxchg8b) { ...@@ -307,14 +307,14 @@ TEST_F(AssemblerX8632LowLevelTest, Cmpxchg8b) {
static constexpr bool Locked = true; static constexpr bool Locked = true;
// Ensures that cmpxchg8b emits a lock prefix accordingly. // Ensures that cmpxchg8b emits a lock prefix accordingly.
__ cmpxchg8b(Address::Absolute(0x1FF00), NotLocked); __ cmpxchg8b(Address(0x1FF00, AssemblerFixup::NoFixup), NotLocked);
static constexpr uint8_t ByteCountNotLocked = 7; static constexpr uint8_t ByteCountNotLocked = 7;
ASSERT_EQ(ByteCountNotLocked, codeBytesSize()); ASSERT_EQ(ByteCountNotLocked, codeBytesSize());
verifyBytes<ByteCountNotLocked>(codeBytes(), 0x0F, 0xC7, 0x0D, 0x00, 0xFF, verifyBytes<ByteCountNotLocked>(codeBytes(), 0x0F, 0xC7, 0x0D, 0x00, 0xFF,
0x01, 0x00); 0x01, 0x00);
reset(); reset();
__ cmpxchg8b(Address::Absolute(0x1FF00), Locked); __ cmpxchg8b(Address(0x1FF00, AssemblerFixup::NoFixup), Locked);
static constexpr uint8_t ByteCountLocked = 1 + ByteCountNotLocked; static constexpr uint8_t ByteCountLocked = 1 + ByteCountNotLocked;
ASSERT_EQ(ByteCountLocked, codeBytesSize()); ASSERT_EQ(ByteCountLocked, codeBytesSize());
verifyBytes<ByteCountLocked>(codeBytes(), 0xF0, 0x0F, 0xC7, 0x0D, 0x00, 0xFF, verifyBytes<ByteCountLocked>(codeBytes(), 0xF0, 0x0F, 0xC7, 0x0D, 0x00, 0xFF,
...@@ -400,7 +400,7 @@ TEST_F(AssemblerX8632LowLevelTest, Cmpxchg) { ...@@ -400,7 +400,7 @@ TEST_F(AssemblerX8632LowLevelTest, Cmpxchg) {
// Ensures that cmpxchg emits a lock prefix accordingly. // Ensures that cmpxchg emits a lock prefix accordingly.
{ {
__ cmpxchg(IceType_i8, Address::Absolute(0x1FF00), __ cmpxchg(IceType_i8, Address(0x1FF00, AssemblerFixup::NoFixup),
GPRRegister::Encoded_Reg_esi, NotLocked); GPRRegister::Encoded_Reg_esi, NotLocked);
static constexpr uint8_t ByteCountNotLocked8 = 7; static constexpr uint8_t ByteCountNotLocked8 = 7;
ASSERT_EQ(ByteCountNotLocked8, codeBytesSize()); ASSERT_EQ(ByteCountNotLocked8, codeBytesSize());
...@@ -408,7 +408,7 @@ TEST_F(AssemblerX8632LowLevelTest, Cmpxchg) { ...@@ -408,7 +408,7 @@ TEST_F(AssemblerX8632LowLevelTest, Cmpxchg) {
0x01, 0x00); 0x01, 0x00);
reset(); reset();
__ cmpxchg(IceType_i8, Address::Absolute(0x1FF00), __ cmpxchg(IceType_i8, Address(0x1FF00, AssemblerFixup::NoFixup),
GPRRegister::Encoded_Reg_esi, Locked); GPRRegister::Encoded_Reg_esi, Locked);
static constexpr uint8_t ByteCountLocked8 = 1 + ByteCountNotLocked8; static constexpr uint8_t ByteCountLocked8 = 1 + ByteCountNotLocked8;
ASSERT_EQ(ByteCountLocked8, codeBytesSize()); ASSERT_EQ(ByteCountLocked8, codeBytesSize());
...@@ -418,7 +418,7 @@ TEST_F(AssemblerX8632LowLevelTest, Cmpxchg) { ...@@ -418,7 +418,7 @@ TEST_F(AssemblerX8632LowLevelTest, Cmpxchg) {
} }
{ {
__ cmpxchg(IceType_i16, Address::Absolute(0x1FF00), __ cmpxchg(IceType_i16, Address(0x1FF00, AssemblerFixup::NoFixup),
GPRRegister::Encoded_Reg_esi, NotLocked); GPRRegister::Encoded_Reg_esi, NotLocked);
static constexpr uint8_t ByteCountNotLocked16 = 8; static constexpr uint8_t ByteCountNotLocked16 = 8;
ASSERT_EQ(ByteCountNotLocked16, codeBytesSize()); ASSERT_EQ(ByteCountNotLocked16, codeBytesSize());
...@@ -426,7 +426,7 @@ TEST_F(AssemblerX8632LowLevelTest, Cmpxchg) { ...@@ -426,7 +426,7 @@ TEST_F(AssemblerX8632LowLevelTest, Cmpxchg) {
0xFF, 0x01, 0x00); 0xFF, 0x01, 0x00);
reset(); reset();
__ cmpxchg(IceType_i16, Address::Absolute(0x1FF00), __ cmpxchg(IceType_i16, Address(0x1FF00, AssemblerFixup::NoFixup),
GPRRegister::Encoded_Reg_esi, Locked); GPRRegister::Encoded_Reg_esi, Locked);
static constexpr uint8_t ByteCountLocked16 = 1 + ByteCountNotLocked16; static constexpr uint8_t ByteCountLocked16 = 1 + ByteCountNotLocked16;
ASSERT_EQ(ByteCountLocked16, codeBytesSize()); ASSERT_EQ(ByteCountLocked16, codeBytesSize());
...@@ -436,7 +436,7 @@ TEST_F(AssemblerX8632LowLevelTest, Cmpxchg) { ...@@ -436,7 +436,7 @@ TEST_F(AssemblerX8632LowLevelTest, Cmpxchg) {
} }
{ {
__ cmpxchg(IceType_i32, Address::Absolute(0x1FF00), __ cmpxchg(IceType_i32, Address(0x1FF00, AssemblerFixup::NoFixup),
GPRRegister::Encoded_Reg_esi, NotLocked); GPRRegister::Encoded_Reg_esi, NotLocked);
static constexpr uint8_t ByteCountNotLocked32 = 7; static constexpr uint8_t ByteCountNotLocked32 = 7;
ASSERT_EQ(ByteCountNotLocked32, codeBytesSize()); ASSERT_EQ(ByteCountNotLocked32, codeBytesSize());
...@@ -444,7 +444,7 @@ TEST_F(AssemblerX8632LowLevelTest, Cmpxchg) { ...@@ -444,7 +444,7 @@ TEST_F(AssemblerX8632LowLevelTest, Cmpxchg) {
0x01, 0x00); 0x01, 0x00);
reset(); reset();
__ cmpxchg(IceType_i32, Address::Absolute(0x1FF00), __ cmpxchg(IceType_i32, Address(0x1FF00, AssemblerFixup::NoFixup),
GPRRegister::Encoded_Reg_esi, Locked); GPRRegister::Encoded_Reg_esi, Locked);
static constexpr uint8_t ByteCountLocked32 = 1 + ByteCountNotLocked32; static constexpr uint8_t ByteCountLocked32 = 1 + ByteCountNotLocked32;
ASSERT_EQ(ByteCountLocked32, codeBytesSize()); ASSERT_EQ(ByteCountLocked32, codeBytesSize());
......
...@@ -141,7 +141,7 @@ TEST_F(AssemblerX8632LowLevelTest, Cmp) { ...@@ -141,7 +141,7 @@ TEST_F(AssemblerX8632LowLevelTest, Cmp) {
", " #__VA_ARGS__ ")"; \ ", " #__VA_ARGS__ ")"; \
static constexpr uint8_t ByteCount = ByteCountUntyped; \ static constexpr uint8_t ByteCount = ByteCountUntyped; \
__ Inst(IceType_##OpType, GPRRegister::Encoded_Reg_##Dst, \ __ Inst(IceType_##OpType, GPRRegister::Encoded_Reg_##Dst, \
Address(Address::ABSOLUTE, Disp)); \ Address(Disp, AssemblerFixup::NoFixup)); \
ASSERT_EQ(ByteCount, codeBytesSize()) << TestString; \ ASSERT_EQ(ByteCount, codeBytesSize()) << TestString; \
ASSERT_TRUE(verifyBytes<ByteCount>(codeBytes(), __VA_ARGS__)) \ ASSERT_TRUE(verifyBytes<ByteCount>(codeBytes(), __VA_ARGS__)) \
<< TestString; \ << TestString; \
...@@ -155,7 +155,8 @@ TEST_F(AssemblerX8632LowLevelTest, Cmp) { ...@@ -155,7 +155,8 @@ TEST_F(AssemblerX8632LowLevelTest, Cmp) {
", " #ByteCountUntyped ", " #__VA_ARGS__ ")"; \ ", " #ByteCountUntyped ", " #__VA_ARGS__ ")"; \
static constexpr uint8_t ByteCount = ByteCountUntyped; \ static constexpr uint8_t ByteCount = ByteCountUntyped; \
__ Inst(IceType_##OpType, GPRRegister::Encoded_Reg_##Dst, \ __ Inst(IceType_##OpType, GPRRegister::Encoded_Reg_##Dst, \
Address(GPRRegister::Encoded_Reg_##Base, Disp)); \ Address(GPRRegister::Encoded_Reg_##Base, Disp, \
AssemblerFixup::NoFixup)); \
ASSERT_EQ(ByteCount, codeBytesSize()) << TestString; \ ASSERT_EQ(ByteCount, codeBytesSize()) << TestString; \
ASSERT_TRUE(verifyBytes<ByteCount>(codeBytes(), __VA_ARGS__)) \ ASSERT_TRUE(verifyBytes<ByteCount>(codeBytes(), __VA_ARGS__)) \
<< TestString; \ << TestString; \
...@@ -171,7 +172,7 @@ TEST_F(AssemblerX8632LowLevelTest, Cmp) { ...@@ -171,7 +172,7 @@ TEST_F(AssemblerX8632LowLevelTest, Cmp) {
static constexpr uint8_t ByteCount = ByteCountUntyped; \ static constexpr uint8_t ByteCount = ByteCountUntyped; \
__ Inst(IceType_##OpType, GPRRegister::Encoded_Reg_##Dst, \ __ Inst(IceType_##OpType, GPRRegister::Encoded_Reg_##Dst, \
Address(GPRRegister::Encoded_Reg_##Index, Traits::TIMES_##Scale, \ Address(GPRRegister::Encoded_Reg_##Index, Traits::TIMES_##Scale, \
Disp)); \ Disp, AssemblerFixup::NoFixup)); \
ASSERT_EQ(ByteCount, codeBytesSize()) << TestString; \ ASSERT_EQ(ByteCount, codeBytesSize()) << TestString; \
ASSERT_TRUE(verifyBytes<ByteCount>(codeBytes(), __VA_ARGS__)) \ ASSERT_TRUE(verifyBytes<ByteCount>(codeBytes(), __VA_ARGS__)) \
<< TestString; \ << TestString; \
...@@ -188,7 +189,7 @@ TEST_F(AssemblerX8632LowLevelTest, Cmp) { ...@@ -188,7 +189,7 @@ TEST_F(AssemblerX8632LowLevelTest, Cmp) {
__ Inst(IceType_##OpType, GPRRegister::Encoded_Reg_##Dst, \ __ Inst(IceType_##OpType, GPRRegister::Encoded_Reg_##Dst, \
Address(GPRRegister::Encoded_Reg_##Base, \ Address(GPRRegister::Encoded_Reg_##Base, \
GPRRegister::Encoded_Reg_##Index, Traits::TIMES_##Scale, \ GPRRegister::Encoded_Reg_##Index, Traits::TIMES_##Scale, \
Disp)); \ Disp, AssemblerFixup::NoFixup)); \
ASSERT_EQ(ByteCount, codeBytesSize()) << TestString; \ ASSERT_EQ(ByteCount, codeBytesSize()) << TestString; \
ASSERT_TRUE(verifyBytes<ByteCount>(codeBytes(), __VA_ARGS__)) \ ASSERT_TRUE(verifyBytes<ByteCount>(codeBytes(), __VA_ARGS__)) \
<< TestString; \ << TestString; \
...@@ -204,7 +205,8 @@ TEST_F(AssemblerX8632LowLevelTest, Cmp) { ...@@ -204,7 +205,8 @@ TEST_F(AssemblerX8632LowLevelTest, Cmp) {
static constexpr uint8_t ByteCount = ByteCountUntyped; \ static constexpr uint8_t ByteCount = ByteCountUntyped; \
__ Inst(IceType_##OpType, Address(GPRRegister::Encoded_Reg_##Base, \ __ Inst(IceType_##OpType, Address(GPRRegister::Encoded_Reg_##Base, \
GPRRegister::Encoded_Reg_##Index, \ GPRRegister::Encoded_Reg_##Index, \
Traits::TIMES_##Scale, Disp), \ Traits::TIMES_##Scale, Disp, \
AssemblerFixup::NoFixup), \
Immediate(Imm)); \ Immediate(Imm)); \
ASSERT_EQ(ByteCount, codeBytesSize()) << TestString; \ ASSERT_EQ(ByteCount, codeBytesSize()) << TestString; \
ASSERT_TRUE(verifyBytes<ByteCount>(codeBytes(), __VA_ARGS__)) \ ASSERT_TRUE(verifyBytes<ByteCount>(codeBytes(), __VA_ARGS__)) \
...@@ -221,7 +223,8 @@ TEST_F(AssemblerX8632LowLevelTest, Cmp) { ...@@ -221,7 +223,8 @@ TEST_F(AssemblerX8632LowLevelTest, Cmp) {
static constexpr uint8_t ByteCount = ByteCountUntyped; \ static constexpr uint8_t ByteCount = ByteCountUntyped; \
__ Inst(IceType_##OpType, Address(GPRRegister::Encoded_Reg_##Base, \ __ Inst(IceType_##OpType, Address(GPRRegister::Encoded_Reg_##Base, \
GPRRegister::Encoded_Reg_##Index, \ GPRRegister::Encoded_Reg_##Index, \
Traits::TIMES_##Scale, Disp), \ Traits::TIMES_##Scale, Disp, \
AssemblerFixup::NoFixup), \
GPRRegister::Encoded_Reg_##Src); \ GPRRegister::Encoded_Reg_##Src); \
ASSERT_EQ(ByteCount, codeBytesSize()) << TestString; \ ASSERT_EQ(ByteCount, codeBytesSize()) << TestString; \
ASSERT_TRUE(verifyBytes<ByteCount>(codeBytes(), __VA_ARGS__)) \ ASSERT_TRUE(verifyBytes<ByteCount>(codeBytes(), __VA_ARGS__)) \
......
...@@ -751,7 +751,7 @@ protected: ...@@ -751,7 +751,7 @@ protected:
} }
Address dwordAddress(uint32_t Dword) { Address dwordAddress(uint32_t Dword) {
return Address(GPRRegister::Encoded_Reg_ebp, dwordDisp(Dword)); return Address(GPRRegister::Encoded_Reg_ebp, dwordDisp(Dword), nullptr);
} }
private: private:
......
...@@ -14,8 +14,10 @@ namespace Test { ...@@ -14,8 +14,10 @@ namespace Test {
namespace { namespace {
TEST_F(AssemblerX8632LowLevelTest, Fld) { TEST_F(AssemblerX8632LowLevelTest, Fld) {
__ fld(IceType_f32, Address(GPRRegister::Encoded_Reg_ebp, 1)); __ fld(IceType_f32, Address(GPRRegister::Encoded_Reg_ebp, 1,
__ fld(IceType_f64, Address(GPRRegister::Encoded_Reg_ebp, 0x10000)); AssemblerFixup::NoFixup));
__ fld(IceType_f64, Address(GPRRegister::Encoded_Reg_ebp, 0x10000,
AssemblerFixup::NoFixup));
constexpr size_t ByteCount = 9; constexpr size_t ByteCount = 9;
ASSERT_EQ(ByteCount, codeBytesSize()); ASSERT_EQ(ByteCount, codeBytesSize());
...@@ -31,8 +33,10 @@ TEST_F(AssemblerX8632LowLevelTest, Fld) { ...@@ -31,8 +33,10 @@ TEST_F(AssemblerX8632LowLevelTest, Fld) {
} }
TEST_F(AssemblerX8632LowLevelTest, FstpAddr) { TEST_F(AssemblerX8632LowLevelTest, FstpAddr) {
__ fstp(IceType_f32, Address(GPRRegister::Encoded_Reg_ebp, 1)); __ fstp(IceType_f32, Address(GPRRegister::Encoded_Reg_ebp, 1,
__ fstp(IceType_f64, Address(GPRRegister::Encoded_Reg_ebp, 0x10000)); AssemblerFixup::NoFixup));
__ fstp(IceType_f64, Address(GPRRegister::Encoded_Reg_ebp, 0x10000,
AssemblerFixup::NoFixup));
constexpr size_t ByteCount = 9; constexpr size_t ByteCount = 9;
ASSERT_EQ(ByteCount, codeBytesSize()); ASSERT_EQ(ByteCount, codeBytesSize());
...@@ -57,7 +61,8 @@ TEST_F(AssemblerX8632LowLevelTest, Fincstp) { ...@@ -57,7 +61,8 @@ TEST_F(AssemblerX8632LowLevelTest, Fincstp) {
} }
TEST_F(AssemblerX8632LowLevelTest, FnstcwAddr) { TEST_F(AssemblerX8632LowLevelTest, FnstcwAddr) {
__ fnstcw(Address(GPRRegister::Encoded_Reg_ebp, 0x12345)); __ fnstcw(Address(GPRRegister::Encoded_Reg_ebp, 0x12345,
AssemblerFixup::NoFixup));
constexpr size_t ByteCount = 6; constexpr size_t ByteCount = 6;
ASSERT_EQ(ByteCount, codeBytesSize()); ASSERT_EQ(ByteCount, codeBytesSize());
...@@ -69,7 +74,8 @@ TEST_F(AssemblerX8632LowLevelTest, FnstcwAddr) { ...@@ -69,7 +74,8 @@ TEST_F(AssemblerX8632LowLevelTest, FnstcwAddr) {
} }
TEST_F(AssemblerX8632LowLevelTest, FldcwAddr) { TEST_F(AssemblerX8632LowLevelTest, FldcwAddr) {
__ fldcw(Address(GPRRegister::Encoded_Reg_ebp, 0x12345)); __ fldcw(Address(GPRRegister::Encoded_Reg_ebp, 0x12345,
AssemblerFixup::NoFixup));
constexpr size_t ByteCount = 6; constexpr size_t ByteCount = 6;
ASSERT_EQ(ByteCount, codeBytesSize()); ASSERT_EQ(ByteCount, codeBytesSize());
......
...@@ -169,7 +169,7 @@ TEST_F(AssemblerX8664Test, CallAddr) { ...@@ -169,7 +169,7 @@ TEST_F(AssemblerX8664Test, CallAddr) {
} \ } \
__ mov(IceType_i64, Encoded_GPR_##Dst##q(), dwordAddress(T0)); \ __ mov(IceType_i64, Encoded_GPR_##Dst##q(), dwordAddress(T0)); \
__ mov(IceType_i64, Encoded_GPR_##Src##q(), Encoded_GPR_rsp()); \ __ mov(IceType_i64, Encoded_GPR_##Src##q(), Encoded_GPR_rsp()); \
__ call(Address(Encoded_GPR_##Src##q(), 0)); \ __ call(Address(Encoded_GPR_##Src##q(), 0, AssemblerFixup::NoFixup)); \
__ popl(Encoded_GPR_##Src##q()); \ __ popl(Encoded_GPR_##Src##q()); \
\ \
AssembledTest test = assemble(); \ AssembledTest test = assemble(); \
......
...@@ -117,7 +117,7 @@ TEST_F(AssemblerX8664Test, Lea) { ...@@ -117,7 +117,7 @@ TEST_F(AssemblerX8664Test, Lea) {
__ mov(IceType_i32, Encoded_GPR_##Base(), Immediate(BaseValue)); \ __ mov(IceType_i32, Encoded_GPR_##Base(), Immediate(BaseValue)); \
} \ } \
__ lea(IceType_i32, Encoded_GPR_##Dst(), \ __ lea(IceType_i32, Encoded_GPR_##Dst(), \
Address(Encoded_GPR_##Base(), Disp)); \ Address(Encoded_GPR_##Base(), Disp, AssemblerFixup::NoFixup)); \
AssembledTest test = assemble(); \ AssembledTest test = assemble(); \
test.run(); \ test.run(); \
ASSERT_EQ(test.Base##d() + (Disp), test.Dst##d()) \ ASSERT_EQ(test.Base##d() + (Disp), test.Dst##d()) \
...@@ -134,13 +134,17 @@ TEST_F(AssemblerX8664Test, Lea) { ...@@ -134,13 +134,17 @@ TEST_F(AssemblerX8664Test, Lea) {
__ mov(IceType_i32, Encoded_GPR_##Index(), Immediate(IndexValue)); \ __ mov(IceType_i32, Encoded_GPR_##Index(), Immediate(IndexValue)); \
} \ } \
__ lea(IceType_i32, Encoded_GPR_##Dst0(), \ __ lea(IceType_i32, Encoded_GPR_##Dst0(), \
Address(Encoded_GPR_##Index(), Traits::TIMES_1, Disp)); \ Address(Encoded_GPR_##Index(), Traits::TIMES_1, Disp, \
AssemblerFixup::NoFixup)); \
__ lea(IceType_i32, Encoded_GPR_##Dst1(), \ __ lea(IceType_i32, Encoded_GPR_##Dst1(), \
Address(Encoded_GPR_##Index(), Traits::TIMES_2, Disp)); \ Address(Encoded_GPR_##Index(), Traits::TIMES_2, Disp, \
AssemblerFixup::NoFixup)); \
__ lea(IceType_i32, Encoded_GPR_##Dst2(), \ __ lea(IceType_i32, Encoded_GPR_##Dst2(), \
Address(Encoded_GPR_##Index(), Traits::TIMES_4, Disp)); \ Address(Encoded_GPR_##Index(), Traits::TIMES_4, Disp, \
AssemblerFixup::NoFixup)); \
__ lea(IceType_i32, Encoded_GPR_##Dst3(), \ __ lea(IceType_i32, Encoded_GPR_##Dst3(), \
Address(Encoded_GPR_##Index(), Traits::TIMES_8, Disp)); \ Address(Encoded_GPR_##Index(), Traits::TIMES_8, Disp, \
AssemblerFixup::NoFixup)); \
AssembledTest test = assemble(); \ AssembledTest test = assemble(); \
test.run(); \ test.run(); \
ASSERT_EQ((test.Index##d() << Traits::TIMES_1) + (Disp), test.Dst0##d()) \ ASSERT_EQ((test.Index##d() << Traits::TIMES_1) + (Disp), test.Dst0##d()) \
...@@ -171,16 +175,16 @@ TEST_F(AssemblerX8664Test, Lea) { ...@@ -171,16 +175,16 @@ TEST_F(AssemblerX8664Test, Lea) {
\ \
__ lea(IceType_i32, Encoded_GPR_##Dst0(), \ __ lea(IceType_i32, Encoded_GPR_##Dst0(), \
Address(Encoded_GPR_##Base(), Encoded_GPR_##Index(), \ Address(Encoded_GPR_##Base(), Encoded_GPR_##Index(), \
Traits::TIMES_1, Disp)); \ Traits::TIMES_1, Disp, AssemblerFixup::NoFixup)); \
__ lea(IceType_i32, Encoded_GPR_##Dst1(), \ __ lea(IceType_i32, Encoded_GPR_##Dst1(), \
Address(Encoded_GPR_##Base(), Encoded_GPR_##Index(), \ Address(Encoded_GPR_##Base(), Encoded_GPR_##Index(), \
Traits::TIMES_2, Disp)); \ Traits::TIMES_2, Disp, AssemblerFixup::NoFixup)); \
__ lea(IceType_i32, Encoded_GPR_##Dst2(), \ __ lea(IceType_i32, Encoded_GPR_##Dst2(), \
Address(Encoded_GPR_##Base(), Encoded_GPR_##Index(), \ Address(Encoded_GPR_##Base(), Encoded_GPR_##Index(), \
Traits::TIMES_4, Disp)); \ Traits::TIMES_4, Disp, AssemblerFixup::NoFixup)); \
__ lea(IceType_i32, Encoded_GPR_##Dst3(), \ __ lea(IceType_i32, Encoded_GPR_##Dst3(), \
Address(Encoded_GPR_##Base(), Encoded_GPR_##Index(), \ Address(Encoded_GPR_##Base(), Encoded_GPR_##Index(), \
Traits::TIMES_8, Disp)); \ Traits::TIMES_8, Disp, AssemblerFixup::NoFixup)); \
AssembledTest test = assemble(); \ AssembledTest test = assemble(); \
test.run(); \ test.run(); \
uint32_t ExpectedIndexValue = test.Index(); \ uint32_t ExpectedIndexValue = test.Index(); \
...@@ -323,7 +327,7 @@ TEST_F(AssemblerX8664LowLevelTest, LeaAbsolute) { ...@@ -323,7 +327,7 @@ TEST_F(AssemblerX8664LowLevelTest, LeaAbsolute) {
do { \ do { \
static constexpr char TestString[] = "(" #Dst ", " #Value ")"; \ static constexpr char TestString[] = "(" #Dst ", " #Value ")"; \
__ lea(IceType_i32, GPRRegister::Encoded_Reg_##Dst, \ __ lea(IceType_i32, GPRRegister::Encoded_Reg_##Dst, \
Address(Address::ABSOLUTE, Value)); \ Address(Value, AssemblerFixup::NoFixup)); \
static constexpr uint32_t ByteCount = 6; \ static constexpr uint32_t ByteCount = 6; \
ASSERT_EQ(ByteCount, codeBytesSize()) << TestString; \ ASSERT_EQ(ByteCount, codeBytesSize()) << TestString; \
static constexpr uint8_t Opcode = 0x8D; \ static constexpr uint8_t Opcode = 0x8D; \
......
...@@ -204,15 +204,16 @@ TEST_F(AssemblerX8664LowLevelTest, Xadd) { ...@@ -204,15 +204,16 @@ TEST_F(AssemblerX8664LowLevelTest, Xadd) {
// Ensures that xadd emits a lock prefix accordingly. // Ensures that xadd emits a lock prefix accordingly.
{ {
__ xadd(IceType_i8, Address::Absolute(0x1FF00), Encoded_GPR_r14(), __ xadd(IceType_i8, Address(0x1FF00, AssemblerFixup::NoFixup),
NotLocked); Encoded_GPR_r14(), NotLocked);
static constexpr uint8_t ByteCountNotLocked8 = 8; static constexpr uint8_t ByteCountNotLocked8 = 8;
ASSERT_EQ(ByteCountNotLocked8, codeBytesSize()); ASSERT_EQ(ByteCountNotLocked8, codeBytesSize());
ASSERT_TRUE(verifyBytes<ByteCountNotLocked8>(codeBytes(), 0x44, 0x0F, 0xC0, ASSERT_TRUE(verifyBytes<ByteCountNotLocked8>(codeBytes(), 0x44, 0x0F, 0xC0,
0x35, 0x00, 0xFF, 0x01, 0x00)); 0x35, 0x00, 0xFF, 0x01, 0x00));
reset(); reset();
__ xadd(IceType_i8, Address::Absolute(0x1FF00), Encoded_GPR_r14(), Locked); __ xadd(IceType_i8, Address(0x1FF00, AssemblerFixup::NoFixup),
Encoded_GPR_r14(), Locked);
static constexpr uint8_t ByteCountLocked8 = 1 + ByteCountNotLocked8; static constexpr uint8_t ByteCountLocked8 = 1 + ByteCountNotLocked8;
ASSERT_EQ(ByteCountLocked8, codeBytesSize()); ASSERT_EQ(ByteCountLocked8, codeBytesSize());
ASSERT_TRUE(verifyBytes<ByteCountLocked8>( ASSERT_TRUE(verifyBytes<ByteCountLocked8>(
...@@ -221,15 +222,16 @@ TEST_F(AssemblerX8664LowLevelTest, Xadd) { ...@@ -221,15 +222,16 @@ TEST_F(AssemblerX8664LowLevelTest, Xadd) {
} }
{ {
__ xadd(IceType_i16, Address::Absolute(0x1FF00), Encoded_GPR_r14(), __ xadd(IceType_i16, Address(0x1FF00, AssemblerFixup::NoFixup),
NotLocked); Encoded_GPR_r14(), NotLocked);
static constexpr uint8_t ByteCountNotLocked16 = 9; static constexpr uint8_t ByteCountNotLocked16 = 9;
ASSERT_EQ(ByteCountNotLocked16, codeBytesSize()); ASSERT_EQ(ByteCountNotLocked16, codeBytesSize());
ASSERT_TRUE(verifyBytes<ByteCountNotLocked16>( ASSERT_TRUE(verifyBytes<ByteCountNotLocked16>(
codeBytes(), 0x66, 0x44, 0x0F, 0xC1, 0x35, 0x00, 0xFF, 0x01, 0x00)); codeBytes(), 0x66, 0x44, 0x0F, 0xC1, 0x35, 0x00, 0xFF, 0x01, 0x00));
reset(); reset();
__ xadd(IceType_i16, Address::Absolute(0x1FF00), Encoded_GPR_r14(), Locked); __ xadd(IceType_i16, Address(0x1FF00, AssemblerFixup::NoFixup),
Encoded_GPR_r14(), Locked);
static constexpr uint8_t ByteCountLocked16 = 1 + ByteCountNotLocked16; static constexpr uint8_t ByteCountLocked16 = 1 + ByteCountNotLocked16;
ASSERT_EQ(ByteCountLocked16, codeBytesSize()); ASSERT_EQ(ByteCountLocked16, codeBytesSize());
ASSERT_TRUE(verifyBytes<ByteCountLocked16>(codeBytes(), 0x66, 0xF0, 0x44, ASSERT_TRUE(verifyBytes<ByteCountLocked16>(codeBytes(), 0x66, 0xF0, 0x44,
...@@ -239,15 +241,16 @@ TEST_F(AssemblerX8664LowLevelTest, Xadd) { ...@@ -239,15 +241,16 @@ TEST_F(AssemblerX8664LowLevelTest, Xadd) {
} }
{ {
__ xadd(IceType_i32, Address::Absolute(0x1FF00), Encoded_GPR_r14(), __ xadd(IceType_i32, Address(0x1FF00, AssemblerFixup::NoFixup),
NotLocked); Encoded_GPR_r14(), NotLocked);
static constexpr uint8_t ByteCountNotLocked32 = 8; static constexpr uint8_t ByteCountNotLocked32 = 8;
ASSERT_EQ(ByteCountNotLocked32, codeBytesSize()); ASSERT_EQ(ByteCountNotLocked32, codeBytesSize());
ASSERT_TRUE(verifyBytes<ByteCountNotLocked32>( ASSERT_TRUE(verifyBytes<ByteCountNotLocked32>(
codeBytes(), 0x44, 0x0F, 0xC1, 0x35, 0x00, 0xFF, 0x01, 0x00)); codeBytes(), 0x44, 0x0F, 0xC1, 0x35, 0x00, 0xFF, 0x01, 0x00));
reset(); reset();
__ xadd(IceType_i32, Address::Absolute(0x1FF00), Encoded_GPR_r14(), Locked); __ xadd(IceType_i32, Address(0x1FF00, AssemblerFixup::NoFixup),
Encoded_GPR_r14(), Locked);
static constexpr uint8_t ByteCountLocked32 = 1 + ByteCountNotLocked32; static constexpr uint8_t ByteCountLocked32 = 1 + ByteCountNotLocked32;
ASSERT_EQ(ByteCountLocked32, codeBytesSize()); ASSERT_EQ(ByteCountLocked32, codeBytesSize());
ASSERT_TRUE(verifyBytes<ByteCountLocked32>( ASSERT_TRUE(verifyBytes<ByteCountLocked32>(
...@@ -329,14 +332,14 @@ TEST_F(AssemblerX8664LowLevelTest, Cmpxchg8b) { ...@@ -329,14 +332,14 @@ TEST_F(AssemblerX8664LowLevelTest, Cmpxchg8b) {
static constexpr bool Locked = true; static constexpr bool Locked = true;
// Ensures that cmpxchg8b emits a lock prefix accordingly. // Ensures that cmpxchg8b emits a lock prefix accordingly.
__ cmpxchg8b(Address::Absolute(0x1FF00), NotLocked); __ cmpxchg8b(Address(0x1FF00, AssemblerFixup::NoFixup), NotLocked);
static constexpr uint8_t ByteCountNotLocked = 7; static constexpr uint8_t ByteCountNotLocked = 7;
ASSERT_EQ(ByteCountNotLocked, codeBytesSize()); ASSERT_EQ(ByteCountNotLocked, codeBytesSize());
ASSERT_TRUE(verifyBytes<ByteCountNotLocked>(codeBytes(), 0x0F, 0xC7, 0x0D, ASSERT_TRUE(verifyBytes<ByteCountNotLocked>(codeBytes(), 0x0F, 0xC7, 0x0D,
0x00, 0xFF, 0x01, 0x00)); 0x00, 0xFF, 0x01, 0x00));
reset(); reset();
__ cmpxchg8b(Address::Absolute(0x1FF00), Locked); __ cmpxchg8b(Address(0x1FF00, AssemblerFixup::NoFixup), Locked);
static constexpr uint8_t ByteCountLocked = 1 + ByteCountNotLocked; static constexpr uint8_t ByteCountLocked = 1 + ByteCountNotLocked;
ASSERT_EQ(ByteCountLocked, codeBytesSize()); ASSERT_EQ(ByteCountLocked, codeBytesSize());
ASSERT_TRUE(verifyBytes<ByteCountLocked>(codeBytes(), 0xF0, 0x0F, 0xC7, 0x0D, ASSERT_TRUE(verifyBytes<ByteCountLocked>(codeBytes(), 0xF0, 0x0F, 0xC7, 0x0D,
...@@ -436,16 +439,16 @@ TEST_F(AssemblerX8664LowLevelTest, Cmpxchg) { ...@@ -436,16 +439,16 @@ TEST_F(AssemblerX8664LowLevelTest, Cmpxchg) {
// Ensures that cmpxchg emits a lock prefix accordingly. // Ensures that cmpxchg emits a lock prefix accordingly.
{ {
__ cmpxchg(IceType_i8, Address::Absolute(0x1FF00), Encoded_GPR_r14(), __ cmpxchg(IceType_i8, Address(0x1FF00, AssemblerFixup::NoFixup),
NotLocked); Encoded_GPR_r14(), NotLocked);
static constexpr uint8_t ByteCountNotLocked8 = 8; static constexpr uint8_t ByteCountNotLocked8 = 8;
ASSERT_EQ(ByteCountNotLocked8, codeBytesSize()); ASSERT_EQ(ByteCountNotLocked8, codeBytesSize());
ASSERT_TRUE(verifyBytes<ByteCountNotLocked8>(codeBytes(), 0x44, 0x0F, 0xB0, ASSERT_TRUE(verifyBytes<ByteCountNotLocked8>(codeBytes(), 0x44, 0x0F, 0xB0,
0x35, 0x00, 0xFF, 0x01, 0x00)); 0x35, 0x00, 0xFF, 0x01, 0x00));
reset(); reset();
__ cmpxchg(IceType_i8, Address::Absolute(0x1FF00), Encoded_GPR_r14(), __ cmpxchg(IceType_i8, Address(0x1FF00, AssemblerFixup::NoFixup),
Locked); Encoded_GPR_r14(), Locked);
static constexpr uint8_t ByteCountLocked8 = 1 + ByteCountNotLocked8; static constexpr uint8_t ByteCountLocked8 = 1 + ByteCountNotLocked8;
ASSERT_EQ(ByteCountLocked8, codeBytesSize()); ASSERT_EQ(ByteCountLocked8, codeBytesSize());
ASSERT_TRUE(verifyBytes<ByteCountLocked8>( ASSERT_TRUE(verifyBytes<ByteCountLocked8>(
...@@ -454,16 +457,16 @@ TEST_F(AssemblerX8664LowLevelTest, Cmpxchg) { ...@@ -454,16 +457,16 @@ TEST_F(AssemblerX8664LowLevelTest, Cmpxchg) {
} }
{ {
__ cmpxchg(IceType_i16, Address::Absolute(0x1FF00), Encoded_GPR_r14(), __ cmpxchg(IceType_i16, Address(0x1FF00, AssemblerFixup::NoFixup),
NotLocked); Encoded_GPR_r14(), NotLocked);
static constexpr uint8_t ByteCountNotLocked16 = 9; static constexpr uint8_t ByteCountNotLocked16 = 9;
ASSERT_EQ(ByteCountNotLocked16, codeBytesSize()); ASSERT_EQ(ByteCountNotLocked16, codeBytesSize());
ASSERT_TRUE(verifyBytes<ByteCountNotLocked16>( ASSERT_TRUE(verifyBytes<ByteCountNotLocked16>(
codeBytes(), 0x66, 0x44, 0x0F, 0xB1, 0x35, 0x00, 0xFF, 0x01, 0x00)); codeBytes(), 0x66, 0x44, 0x0F, 0xB1, 0x35, 0x00, 0xFF, 0x01, 0x00));
reset(); reset();
__ cmpxchg(IceType_i16, Address::Absolute(0x1FF00), Encoded_GPR_r14(), __ cmpxchg(IceType_i16, Address(0x1FF00, AssemblerFixup::NoFixup),
Locked); Encoded_GPR_r14(), Locked);
static constexpr uint8_t ByteCountLocked16 = 1 + ByteCountNotLocked16; static constexpr uint8_t ByteCountLocked16 = 1 + ByteCountNotLocked16;
ASSERT_EQ(ByteCountLocked16, codeBytesSize()); ASSERT_EQ(ByteCountLocked16, codeBytesSize());
ASSERT_TRUE(verifyBytes<ByteCountLocked16>(codeBytes(), 0x66, 0xF0, 0x44, ASSERT_TRUE(verifyBytes<ByteCountLocked16>(codeBytes(), 0x66, 0xF0, 0x44,
...@@ -473,16 +476,16 @@ TEST_F(AssemblerX8664LowLevelTest, Cmpxchg) { ...@@ -473,16 +476,16 @@ TEST_F(AssemblerX8664LowLevelTest, Cmpxchg) {
} }
{ {
__ cmpxchg(IceType_i32, Address::Absolute(0x1FF00), Encoded_GPR_r14(), __ cmpxchg(IceType_i32, Address(0x1FF00, AssemblerFixup::NoFixup),
NotLocked); Encoded_GPR_r14(), NotLocked);
static constexpr uint8_t ByteCountNotLocked32 = 8; static constexpr uint8_t ByteCountNotLocked32 = 8;
ASSERT_EQ(ByteCountNotLocked32, codeBytesSize()); ASSERT_EQ(ByteCountNotLocked32, codeBytesSize());
ASSERT_TRUE(verifyBytes<ByteCountNotLocked32>( ASSERT_TRUE(verifyBytes<ByteCountNotLocked32>(
codeBytes(), 0x44, 0x0F, 0xB1, 0x35, 0x00, 0xFF, 0x01, 0x00)); codeBytes(), 0x44, 0x0F, 0xB1, 0x35, 0x00, 0xFF, 0x01, 0x00));
reset(); reset();
__ cmpxchg(IceType_i32, Address::Absolute(0x1FF00), Encoded_GPR_r14(), __ cmpxchg(IceType_i32, Address(0x1FF00, AssemblerFixup::NoFixup),
Locked); Encoded_GPR_r14(), Locked);
static constexpr uint8_t ByteCountLocked32 = 1 + ByteCountNotLocked32; static constexpr uint8_t ByteCountLocked32 = 1 + ByteCountNotLocked32;
ASSERT_EQ(ByteCountLocked32, codeBytesSize()); ASSERT_EQ(ByteCountLocked32, codeBytesSize());
ASSERT_TRUE(verifyBytes<ByteCountLocked32>( ASSERT_TRUE(verifyBytes<ByteCountLocked32>(
......
...@@ -187,7 +187,7 @@ TEST_F(AssemblerX8664LowLevelTest, Cmp) { ...@@ -187,7 +187,7 @@ TEST_F(AssemblerX8664LowLevelTest, Cmp) {
", " #__VA_ARGS__ ")"; \ ", " #__VA_ARGS__ ")"; \
static constexpr uint8_t ByteCount = ByteCountUntyped; \ static constexpr uint8_t ByteCount = ByteCountUntyped; \
__ Inst(IceType_##OpType, Encoded_GPR_##Dst(), \ __ Inst(IceType_##OpType, Encoded_GPR_##Dst(), \
Address(Address::ABSOLUTE, Disp)); \ Address(Disp, AssemblerFixup::NoFixup)); \
ASSERT_EQ(ByteCount, codeBytesSize()) << TestString; \ ASSERT_EQ(ByteCount, codeBytesSize()) << TestString; \
ASSERT_TRUE(verifyBytes<ByteCount>(codeBytes(), __VA_ARGS__)) \ ASSERT_TRUE(verifyBytes<ByteCount>(codeBytes(), __VA_ARGS__)) \
<< TestString; \ << TestString; \
...@@ -201,7 +201,7 @@ TEST_F(AssemblerX8664LowLevelTest, Cmp) { ...@@ -201,7 +201,7 @@ TEST_F(AssemblerX8664LowLevelTest, Cmp) {
", " #ByteCountUntyped ", " #__VA_ARGS__ ")"; \ ", " #ByteCountUntyped ", " #__VA_ARGS__ ")"; \
static constexpr uint8_t ByteCount = ByteCountUntyped; \ static constexpr uint8_t ByteCount = ByteCountUntyped; \
__ Inst(IceType_##OpType, Encoded_GPR_##Dst(), \ __ Inst(IceType_##OpType, Encoded_GPR_##Dst(), \
Address(Encoded_GPR_##Base(), Disp)); \ Address(Encoded_GPR_##Base(), Disp, AssemblerFixup::NoFixup)); \
ASSERT_EQ(ByteCount, codeBytesSize()) << TestString; \ ASSERT_EQ(ByteCount, codeBytesSize()) << TestString; \
ASSERT_TRUE(verifyBytes<ByteCount>(codeBytes(), __VA_ARGS__)) \ ASSERT_TRUE(verifyBytes<ByteCount>(codeBytes(), __VA_ARGS__)) \
<< TestString; \ << TestString; \
...@@ -215,8 +215,10 @@ TEST_F(AssemblerX8664LowLevelTest, Cmp) { ...@@ -215,8 +215,10 @@ TEST_F(AssemblerX8664LowLevelTest, Cmp) {
"(" #Inst ", " #Dst ", " #Index ", " #Scale ", " #Disp ", " #OpType \ "(" #Inst ", " #Dst ", " #Index ", " #Scale ", " #Disp ", " #OpType \
", " #ByteCountUntyped ", " #__VA_ARGS__ ")"; \ ", " #ByteCountUntyped ", " #__VA_ARGS__ ")"; \
static constexpr uint8_t ByteCount = ByteCountUntyped; \ static constexpr uint8_t ByteCount = ByteCountUntyped; \
__ Inst(IceType_##OpType, Encoded_GPR_##Dst(), \ __ Inst( \
Address(Encoded_GPR_##Index(), Traits::TIMES_##Scale, Disp)); \ IceType_##OpType, Encoded_GPR_##Dst(), \
Address(Encoded_GPR_##Index(), Traits::TIMES_##Scale, Disp, \
AssemblerFixup::NoFixup)); \
ASSERT_EQ(ByteCount, codeBytesSize()) << TestString; \ ASSERT_EQ(ByteCount, codeBytesSize()) << TestString; \
ASSERT_TRUE(verifyBytes<ByteCount>(codeBytes(), __VA_ARGS__)) \ ASSERT_TRUE(verifyBytes<ByteCount>(codeBytes(), __VA_ARGS__)) \
<< TestString; \ << TestString; \
...@@ -232,7 +234,7 @@ TEST_F(AssemblerX8664LowLevelTest, Cmp) { ...@@ -232,7 +234,7 @@ TEST_F(AssemblerX8664LowLevelTest, Cmp) {
static constexpr uint8_t ByteCount = ByteCountUntyped; \ static constexpr uint8_t ByteCount = ByteCountUntyped; \
__ Inst(IceType_##OpType, Encoded_GPR_##Dst(), \ __ Inst(IceType_##OpType, Encoded_GPR_##Dst(), \
Address(Encoded_GPR_##Base(), Encoded_GPR_##Index(), \ Address(Encoded_GPR_##Base(), Encoded_GPR_##Index(), \
Traits::TIMES_##Scale, Disp)); \ Traits::TIMES_##Scale, Disp, AssemblerFixup::NoFixup)); \
ASSERT_EQ(ByteCount, codeBytesSize()) << TestString; \ ASSERT_EQ(ByteCount, codeBytesSize()) << TestString; \
ASSERT_TRUE(verifyBytes<ByteCount>(codeBytes(), __VA_ARGS__)) \ ASSERT_TRUE(verifyBytes<ByteCount>(codeBytes(), __VA_ARGS__)) \
<< TestString; \ << TestString; \
...@@ -248,7 +250,7 @@ TEST_F(AssemblerX8664LowLevelTest, Cmp) { ...@@ -248,7 +250,7 @@ TEST_F(AssemblerX8664LowLevelTest, Cmp) {
static constexpr uint8_t ByteCount = ByteCountUntyped; \ static constexpr uint8_t ByteCount = ByteCountUntyped; \
__ Inst(IceType_##OpType, \ __ Inst(IceType_##OpType, \
Address(Encoded_GPR_##Base(), Encoded_GPR_##Index(), \ Address(Encoded_GPR_##Base(), Encoded_GPR_##Index(), \
Traits::TIMES_##Scale, Disp), \ Traits::TIMES_##Scale, Disp, AssemblerFixup::NoFixup), \
Immediate(Imm)); \ Immediate(Imm)); \
ASSERT_EQ(ByteCount, codeBytesSize()) << TestString; \ ASSERT_EQ(ByteCount, codeBytesSize()) << TestString; \
ASSERT_TRUE(verifyBytes<ByteCount>(codeBytes(), __VA_ARGS__)) \ ASSERT_TRUE(verifyBytes<ByteCount>(codeBytes(), __VA_ARGS__)) \
...@@ -265,7 +267,7 @@ TEST_F(AssemblerX8664LowLevelTest, Cmp) { ...@@ -265,7 +267,7 @@ TEST_F(AssemblerX8664LowLevelTest, Cmp) {
static constexpr uint8_t ByteCount = ByteCountUntyped; \ static constexpr uint8_t ByteCount = ByteCountUntyped; \
__ Inst(IceType_##OpType, \ __ Inst(IceType_##OpType, \
Address(Encoded_GPR_##Base(), Encoded_GPR_##Index(), \ Address(Encoded_GPR_##Base(), Encoded_GPR_##Index(), \
Traits::TIMES_##Scale, Disp), \ Traits::TIMES_##Scale, Disp, AssemblerFixup::NoFixup), \
Encoded_GPR_##Src()); \ Encoded_GPR_##Src()); \
ASSERT_EQ(ByteCount, codeBytesSize()) << TestString; \ ASSERT_EQ(ByteCount, codeBytesSize()) << TestString; \
ASSERT_TRUE(verifyBytes<ByteCount>(codeBytes(), __VA_ARGS__)) \ ASSERT_TRUE(verifyBytes<ByteCount>(codeBytes(), __VA_ARGS__)) \
......
...@@ -930,7 +930,7 @@ protected: ...@@ -930,7 +930,7 @@ protected:
} }
Address dwordAddress(uint32_t Dword) { Address dwordAddress(uint32_t Dword) {
return Address(Encoded_GPR_r9(), dwordDisp(Dword)); return Address(Encoded_GPR_r9(), dwordDisp(Dword), nullptr);
} }
private: private:
......
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