Commit fe14fb8e by Jan Voung

Handle "Mov" which is mov, movss, movsd, and used for nacl.read.tp.

Currently, this only checks and emits the segment override only for GPR instructions, assuming it's mostly only used for nacl.read.tp. The code will assert when used in other situations. The lea hack is still tested in some files, but it's not emitted with emitIAS, and instead the "immediate" operand now has a fixup. There is a more compact encoding for "mov eax, moffs32", etc., but that isn't used right now. BUG=none R=stichnot@chromium.org Review URL: https://codereview.chromium.org/649463002
parent 9d98d791
...@@ -74,6 +74,9 @@ typedef int32_t InstNumberT; ...@@ -74,6 +74,9 @@ typedef int32_t InstNumberT;
typedef uint32_t TimerStackIdT; typedef uint32_t TimerStackIdT;
typedef uint32_t TimerIdT; typedef uint32_t TimerIdT;
// PNaCl is ILP32, so theoretically we should only need 32-bit offsets.
typedef int32_t RelocOffsetT;
enum LivenessMode { enum LivenessMode {
// Basic version of live-range-end calculation. Marks the last uses // Basic version of live-range-end calculation. Marks the last uses
// of variables based on dataflow analysis. Records the set of // of variables based on dataflow analysis. Records the set of
......
...@@ -313,7 +313,7 @@ Constant *GlobalContext::getConstantDouble(double ConstantDouble) { ...@@ -313,7 +313,7 @@ Constant *GlobalContext::getConstantDouble(double ConstantDouble) {
return ConstPool->Doubles.getOrAdd(this, IceType_f64, ConstantDouble); return ConstPool->Doubles.getOrAdd(this, IceType_f64, ConstantDouble);
} }
Constant *GlobalContext::getConstantSym(Type Ty, int64_t Offset, Constant *GlobalContext::getConstantSym(Type Ty, RelocOffsetT Offset,
const IceString &Name, const IceString &Name,
bool SuppressMangling) { bool SuppressMangling) {
return ConstPool->Relocatables.getOrAdd( return ConstPool->Relocatables.getOrAdd(
......
...@@ -110,7 +110,8 @@ public: ...@@ -110,7 +110,8 @@ public:
Constant *getConstantFloat(float Value); Constant *getConstantFloat(float Value);
Constant *getConstantDouble(double Value); Constant *getConstantDouble(double Value);
// Returns a symbolic constant. // Returns a symbolic constant.
Constant *getConstantSym(Type Ty, int64_t Offset, const IceString &Name = "", Constant *getConstantSym(Type Ty, RelocOffsetT Offset,
const IceString &Name = "",
bool SuppressMangling = false); bool SuppressMangling = false);
// Returns an undef. // Returns an undef.
Constant *getConstantUndef(Type Ty); Constant *getConstantUndef(Type Ty);
......
...@@ -79,14 +79,14 @@ ...@@ -79,14 +79,14 @@
// X86 segment registers. // X86 segment registers.
#define SEG_REGX8632_TABLE \ #define SEG_REGX8632_TABLE \
/* enum value, name */ \ /* enum value, name, prefix */ \
X(SegReg_CS, "cs") \ X(SegReg_CS, "cs", 0x2E) \
X(SegReg_DS, "ds") \ X(SegReg_DS, "ds", 0x3E) \
X(SegReg_ES, "es") \ X(SegReg_ES, "es", 0x26) \
X(SegReg_SS, "ss") \ X(SegReg_SS, "ss", 0x36) \
X(SegReg_FS, "fs") \ X(SegReg_FS, "fs", 0x64) \
X(SegReg_GS, "gs") \ X(SegReg_GS, "gs", 0x65) \
//#define X(val, name) //#define X(val, name, prefix)
// X87 ST(n) registers. // X87 ST(n) registers.
#define X87ST_REGX8632_TABLE \ #define X87ST_REGX8632_TABLE \
......
...@@ -58,7 +58,7 @@ class OperandX8632Mem : public OperandX8632 { ...@@ -58,7 +58,7 @@ class OperandX8632Mem : public OperandX8632 {
public: public:
enum SegmentRegisters { enum SegmentRegisters {
DefaultSegment = -1, DefaultSegment = -1,
#define X(val, name) val, #define X(val, name, prefix) val,
SEG_REGX8632_TABLE SEG_REGX8632_TABLE
#undef X #undef X
SegReg_NUM SegReg_NUM
...@@ -75,6 +75,7 @@ public: ...@@ -75,6 +75,7 @@ public:
Variable *getIndex() const { return Index; } Variable *getIndex() const { return Index; }
uint16_t getShift() const { return Shift; } uint16_t getShift() const { return Shift; }
SegmentRegisters getSegmentRegister() const { return SegmentReg; } SegmentRegisters getSegmentRegister() const { return SegmentReg; }
void emitSegmentOverride(x86::AssemblerX86 *Asm) const;
x86::Address toAsmAddress(Assembler *Asm) const; x86::Address toAsmAddress(Assembler *Asm) const;
void emit(const Cfg *Func) const override; void emit(const Cfg *Func) const override;
using OperandX8632::dump; using OperandX8632::dump;
...@@ -112,6 +113,9 @@ public: ...@@ -112,6 +113,9 @@ public:
static VariableSplit *create(Cfg *Func, Variable *Var, Portion Part) { static VariableSplit *create(Cfg *Func, Variable *Var, Portion Part) {
return new (Func->allocate<VariableSplit>()) VariableSplit(Func, Var, Part); return new (Func->allocate<VariableSplit>()) VariableSplit(Func, Var, Part);
} }
int32_t getOffset() const { return Part == High ? 4 : 0; }
x86::Address toAsmAddress(const Cfg *Func) const;
void emit(const Cfg *Func) const override; void emit(const Cfg *Func) const override;
using OperandX8632::dump; using OperandX8632::dump;
void dump(const Cfg *Func, Ostream &Str) const override; void dump(const Cfg *Func, Ostream &Str) const override;
...@@ -835,7 +839,7 @@ public: ...@@ -835,7 +839,7 @@ public:
} }
bool isSimpleAssign() const override { return true; } bool isSimpleAssign() const override { return true; }
void emit(const Cfg *Func) const override; void emit(const Cfg *Func) const override;
void emitIAS(const Cfg *Func) const override { emit(Func); } void emitIAS(const Cfg *Func) const override;
void dump(const Cfg *Func) const override { void dump(const Cfg *Func) const override {
Ostream &Str = Func->getContext()->getStrDump(); Ostream &Str = Func->getContext()->getStrDump();
Str << Opcode << "." << getDest()->getType() << " "; Str << Opcode << "." << getDest()->getType() << " ";
...@@ -1519,8 +1523,6 @@ template <> void InstX8632Idiv::emitIAS(const Cfg *Func) const; ...@@ -1519,8 +1523,6 @@ template <> void InstX8632Idiv::emitIAS(const Cfg *Func) const;
template <> void InstX8632Imul::emitIAS(const Cfg *Func) const; template <> void InstX8632Imul::emitIAS(const Cfg *Func) const;
template <> void InstX8632Cbwdq::emitIAS(const Cfg *Func) const; template <> void InstX8632Cbwdq::emitIAS(const Cfg *Func) const;
template <> void InstX8632Movd::emitIAS(const Cfg *Func) const; template <> void InstX8632Movd::emitIAS(const Cfg *Func) const;
template <> void InstX8632Movp::emitIAS(const Cfg *Func) const;
template <> void InstX8632Movq::emitIAS(const Cfg *Func) const;
template <> void InstX8632MovssRegs::emitIAS(const Cfg *Func) const; template <> void InstX8632MovssRegs::emitIAS(const Cfg *Func) const;
template <> void InstX8632Pblendvb::emitIAS(const Cfg *Func) const; template <> void InstX8632Pblendvb::emitIAS(const Cfg *Func) const;
template <> void InstX8632Pmull::emitIAS(const Cfg *Func) const; template <> void InstX8632Pmull::emitIAS(const Cfg *Func) const;
......
...@@ -18,7 +18,9 @@ ...@@ -18,7 +18,9 @@
#ifndef SUBZERO_SRC_ICEOPERAND_H #ifndef SUBZERO_SRC_ICEOPERAND_H
#define SUBZERO_SRC_ICEOPERAND_H #define SUBZERO_SRC_ICEOPERAND_H
#include "IceCfg.h"
#include "IceDefs.h" #include "IceDefs.h"
#include "IceGlobalContext.h"
#include "IceTypes.h" #include "IceTypes.h"
namespace Ice { namespace Ice {
...@@ -183,14 +185,14 @@ class RelocatableTuple { ...@@ -183,14 +185,14 @@ class RelocatableTuple {
RelocatableTuple &operator=(const RelocatableTuple &) = delete; RelocatableTuple &operator=(const RelocatableTuple &) = delete;
public: public:
RelocatableTuple(const int64_t Offset, const IceString &Name, RelocatableTuple(const RelocOffsetT Offset, const IceString &Name,
bool SuppressMangling) bool SuppressMangling)
: Offset(Offset), Name(Name), SuppressMangling(SuppressMangling) {} : Offset(Offset), Name(Name), SuppressMangling(SuppressMangling) {}
RelocatableTuple(const RelocatableTuple &Other) RelocatableTuple(const RelocatableTuple &Other)
: Offset(Other.Offset), Name(Other.Name), : Offset(Other.Offset), Name(Other.Name),
SuppressMangling(Other.SuppressMangling) {} SuppressMangling(Other.SuppressMangling) {}
const int64_t Offset; const RelocOffsetT Offset;
const IceString Name; const IceString Name;
bool SuppressMangling; bool SuppressMangling;
}; };
...@@ -207,7 +209,8 @@ public: ...@@ -207,7 +209,8 @@ public:
return new (Ctx->allocate<ConstantRelocatable>()) ConstantRelocatable( return new (Ctx->allocate<ConstantRelocatable>()) ConstantRelocatable(
Ty, Tuple.Offset, Tuple.Name, Tuple.SuppressMangling, PoolEntryID); Ty, Tuple.Offset, Tuple.Name, Tuple.SuppressMangling, PoolEntryID);
} }
int64_t getOffset() const { return Offset; }
RelocOffsetT getOffset() const { return Offset; }
IceString getName() const { return Name; } IceString getName() const { return Name; }
void setSuppressMangling(bool Value) { SuppressMangling = Value; } void setSuppressMangling(bool Value) { SuppressMangling = Value; }
bool getSuppressMangling() const { return SuppressMangling; } bool getSuppressMangling() const { return SuppressMangling; }
...@@ -222,14 +225,14 @@ public: ...@@ -222,14 +225,14 @@ public:
} }
private: private:
ConstantRelocatable(Type Ty, int64_t Offset, const IceString &Name, ConstantRelocatable(Type Ty, RelocOffsetT Offset, const IceString &Name,
bool SuppressMangling, uint32_t PoolEntryID) bool SuppressMangling, uint32_t PoolEntryID)
: Constant(kConstRelocatable, Ty, PoolEntryID), Offset(Offset), : Constant(kConstRelocatable, Ty, PoolEntryID), Offset(Offset),
Name(Name), SuppressMangling(SuppressMangling) {} Name(Name), SuppressMangling(SuppressMangling) {}
ConstantRelocatable(const ConstantRelocatable &) = delete; ConstantRelocatable(const ConstantRelocatable &) = delete;
ConstantRelocatable &operator=(const ConstantRelocatable &) = delete; ConstantRelocatable &operator=(const ConstantRelocatable &) = delete;
~ConstantRelocatable() override {} ~ConstantRelocatable() override {}
const int64_t Offset; // fixed offset to add const RelocOffsetT Offset; // fixed offset to add
const IceString Name; // optional for debug/dump const IceString Name; // optional for debug/dump
bool SuppressMangling; bool SuppressMangling;
}; };
......
...@@ -1058,6 +1058,7 @@ Operand *TargetX8632::hiOperand(Operand *Operand) { ...@@ -1058,6 +1058,7 @@ Operand *TargetX8632::hiOperand(Operand *Operand) {
Offset = Ctx->getConstantInt32(IceType_i32, 4 + IntOffset->getValue()); Offset = Ctx->getConstantInt32(IceType_i32, 4 + IntOffset->getValue());
} else if (ConstantRelocatable *SymOffset = } else if (ConstantRelocatable *SymOffset =
llvm::dyn_cast<ConstantRelocatable>(Offset)) { llvm::dyn_cast<ConstantRelocatable>(Offset)) {
assert(!Utils::WouldOverflowAdd(SymOffset->getOffset(), 4));
Offset = Ctx->getConstantSym(IceType_i32, 4 + SymOffset->getOffset(), Offset = Ctx->getConstantSym(IceType_i32, 4 + SymOffset->getOffset(),
SymOffset->getName()); SymOffset->getName());
} }
......
...@@ -299,7 +299,7 @@ public: ...@@ -299,7 +299,7 @@ public:
Error(StrBuf.str()); Error(StrBuf.str());
Name = "??"; Name = "??";
} }
const uint64_t Offset = 0; const Ice::RelocOffsetT Offset = 0;
C = getTranslator().getContext()->getConstantSym( C = getTranslator().getContext()->getConstantSym(
getIcePointerType(), Offset, Name); getIcePointerType(), Offset, Name);
ValueIDConstants[ID] = C; ValueIDConstants[ID] = C;
......
...@@ -25,8 +25,6 @@ ...@@ -25,8 +25,6 @@
namespace Ice { namespace Ice {
namespace x86 { namespace x86 {
const Type BrokenType = IceType_i32;
class DirectCallRelocation : public AssemblerFixup { class DirectCallRelocation : public AssemblerFixup {
public: public:
static DirectCallRelocation *create(Assembler *Asm, FixupKind Kind, static DirectCallRelocation *create(Assembler *Asm, FixupKind Kind,
...@@ -56,13 +54,13 @@ Address Address::ofConstPool(GlobalContext *Ctx, Assembler *Asm, ...@@ -56,13 +54,13 @@ Address Address::ofConstPool(GlobalContext *Ctx, Assembler *Asm,
Type Ty = Imm->getType(); Type Ty = Imm->getType();
assert(llvm::isa<ConstantFloat>(Imm) || llvm::isa<ConstantDouble>(Imm)); assert(llvm::isa<ConstantFloat>(Imm) || llvm::isa<ConstantDouble>(Imm));
StrBuf << "L$" << Ty << "$" << Imm->getPoolEntryID(); StrBuf << "L$" << Ty << "$" << Imm->getPoolEntryID();
const int64_t Offset = 0; const RelocOffsetT Offset = 0;
const bool SuppressMangling = true; const bool SuppressMangling = true;
Constant *Sym = Constant *Sym =
Ctx->getConstantSym(Ty, Offset, StrBuf.str(), SuppressMangling); Ctx->getConstantSym(Ty, Offset, StrBuf.str(), SuppressMangling);
AssemblerFixup *Fixup = x86::DisplacementRelocation::create( AssemblerFixup *Fixup = x86::DisplacementRelocation::create(
Asm, FK_Abs_4, llvm::cast<ConstantRelocatable>(Sym)); Asm, FK_Abs_4, llvm::cast<ConstantRelocatable>(Sym));
return x86::Address::Absolute(Offset, Fixup); return x86::Address::Absolute(Fixup);
} }
void AssemblerX86::call(GPRRegister reg) { void AssemblerX86::call(GPRRegister reg) {
...@@ -127,35 +125,68 @@ void AssemblerX86::setcc(CondX86::BrCond condition, ByteRegister dst) { ...@@ -127,35 +125,68 @@ void AssemblerX86::setcc(CondX86::BrCond condition, ByteRegister dst) {
EmitUint8(0xC0 + dst); EmitUint8(0xC0 + dst);
} }
void AssemblerX86::movl(GPRRegister dst, const Immediate &imm) { void AssemblerX86::mov(Type Ty, GPRRegister dst, const Immediate &imm) {
AssemblerBuffer::EnsureCapacity ensured(&buffer_); AssemblerBuffer::EnsureCapacity ensured(&buffer_);
if (isByteSizedType(Ty)) {
EmitUint8(0xB0 + dst);
EmitUint8(imm.value() & 0xFF);
return;
}
if (Ty == IceType_i16)
EmitOperandSizeOverride();
EmitUint8(0xB8 + dst); EmitUint8(0xB8 + dst);
EmitImmediate(BrokenType, imm); EmitImmediate(Ty, imm);
} }
void AssemblerX86::movl(GPRRegister dst, GPRRegister src) { void AssemblerX86::mov(Type Ty, GPRRegister dst, GPRRegister src) {
AssemblerBuffer::EnsureCapacity ensured(&buffer_); AssemblerBuffer::EnsureCapacity ensured(&buffer_);
if (Ty == IceType_i16)
EmitOperandSizeOverride();
if (isByteSizedType(Ty)) {
EmitUint8(0x88);
} else {
EmitUint8(0x89); EmitUint8(0x89);
}
EmitRegisterOperand(src, dst); EmitRegisterOperand(src, dst);
} }
void AssemblerX86::movl(GPRRegister dst, const Address &src) { void AssemblerX86::mov(Type Ty, GPRRegister dst, const Address &src) {
AssemblerBuffer::EnsureCapacity ensured(&buffer_); AssemblerBuffer::EnsureCapacity ensured(&buffer_);
if (Ty == IceType_i16)
EmitOperandSizeOverride();
if (isByteSizedType(Ty)) {
EmitUint8(0x8A);
} else {
EmitUint8(0x8B); EmitUint8(0x8B);
}
EmitOperand(dst, src); EmitOperand(dst, src);
} }
void AssemblerX86::movl(const Address &dst, GPRRegister src) { void AssemblerX86::mov(Type Ty, const Address &dst, GPRRegister src) {
AssemblerBuffer::EnsureCapacity ensured(&buffer_); AssemblerBuffer::EnsureCapacity ensured(&buffer_);
if (Ty == IceType_i16)
EmitOperandSizeOverride();
if (isByteSizedType(Ty)) {
EmitUint8(0x88);
} else {
EmitUint8(0x89); EmitUint8(0x89);
}
EmitOperand(src, dst); EmitOperand(src, dst);
} }
void AssemblerX86::movl(const Address &dst, const Immediate &imm) { void AssemblerX86::mov(Type Ty, const Address &dst, const Immediate &imm) {
AssemblerBuffer::EnsureCapacity ensured(&buffer_); AssemblerBuffer::EnsureCapacity ensured(&buffer_);
if (Ty == IceType_i16)
EmitOperandSizeOverride();
if (isByteSizedType(Ty)) {
EmitUint8(0xC6);
EmitOperand(0, dst);
EmitUint8(imm.value() & 0xFF);
} else {
EmitUint8(0xC7); EmitUint8(0xC7);
EmitOperand(0, dst); EmitOperand(0, dst);
EmitImmediate(BrokenType, imm); EmitImmediate(Ty, imm);
}
} }
void AssemblerX86::movzxb(GPRRegister dst, ByteRegister src) { void AssemblerX86::movzxb(GPRRegister dst, ByteRegister src) {
...@@ -186,27 +217,6 @@ void AssemblerX86::movsxb(GPRRegister dst, const Address &src) { ...@@ -186,27 +217,6 @@ void AssemblerX86::movsxb(GPRRegister dst, const Address &src) {
EmitOperand(dst, src); EmitOperand(dst, src);
} }
void AssemblerX86::movb(ByteRegister dst, const Address &src) {
(void)dst;
(void)src;
// FATAL
llvm_unreachable("Use movzxb or movsxb instead.");
}
void AssemblerX86::movb(const Address &dst, ByteRegister src) {
AssemblerBuffer::EnsureCapacity ensured(&buffer_);
EmitUint8(0x88);
EmitOperand(src, dst);
}
void AssemblerX86::movb(const Address &dst, const Immediate &imm) {
AssemblerBuffer::EnsureCapacity ensured(&buffer_);
EmitUint8(0xC6);
EmitOperand(RegX8632::Encoded_Reg_eax, dst);
assert(imm.is_int8());
EmitUint8(imm.value() & 0xFF);
}
void AssemblerX86::movzxw(GPRRegister dst, GPRRegister src) { void AssemblerX86::movzxw(GPRRegister dst, GPRRegister src) {
AssemblerBuffer::EnsureCapacity ensured(&buffer_); AssemblerBuffer::EnsureCapacity ensured(&buffer_);
EmitUint8(0x0F); EmitUint8(0x0F);
...@@ -235,20 +245,6 @@ void AssemblerX86::movsxw(GPRRegister dst, const Address &src) { ...@@ -235,20 +245,6 @@ void AssemblerX86::movsxw(GPRRegister dst, const Address &src) {
EmitOperand(dst, src); EmitOperand(dst, src);
} }
void AssemblerX86::movw(GPRRegister dst, const Address &src) {
(void)dst;
(void)src;
// FATAL
llvm_unreachable("Use movzxw or movsxw instead.");
}
void AssemblerX86::movw(const Address &dst, GPRRegister src) {
AssemblerBuffer::EnsureCapacity ensured(&buffer_);
EmitOperandSizeOverride();
EmitUint8(0x89);
EmitOperand(src, dst);
}
void AssemblerX86::lea(Type Ty, GPRRegister dst, const Address &src) { void AssemblerX86::lea(Type Ty, GPRRegister dst, const Address &src) {
AssemblerBuffer::EnsureCapacity ensured(&buffer_); AssemblerBuffer::EnsureCapacity ensured(&buffer_);
assert(Ty == IceType_i16 || Ty == IceType_i32); assert(Ty == IceType_i16 || Ty == IceType_i32);
...@@ -927,7 +923,7 @@ void AssemblerX86::unpckhpd(XmmRegister dst, XmmRegister src) { ...@@ -927,7 +923,7 @@ void AssemblerX86::unpckhpd(XmmRegister dst, XmmRegister src) {
void AssemblerX86::set1ps(XmmRegister dst, GPRRegister tmp1, void AssemblerX86::set1ps(XmmRegister dst, GPRRegister tmp1,
const Immediate &imm) { const Immediate &imm) {
// Load 32-bit immediate value into tmp1. // Load 32-bit immediate value into tmp1.
movl(tmp1, imm); mov(IceType_i32, tmp1, imm);
// Move value from tmp1 into dst. // Move value from tmp1 into dst.
movd(dst, tmp1); movd(dst, tmp1);
// Broadcast low lane into other three lanes. // Broadcast low lane into other three lanes.
...@@ -2266,10 +2262,15 @@ void AssemblerX86::EmitOperand(int rm, const Operand &operand) { ...@@ -2266,10 +2262,15 @@ void AssemblerX86::EmitOperand(int rm, const Operand &operand) {
} }
void AssemblerX86::EmitImmediate(Type Ty, const Immediate &imm) { void AssemblerX86::EmitImmediate(Type Ty, const Immediate &imm) {
if (Ty == IceType_i16) if (Ty == IceType_i16) {
assert(!imm.fixup());
EmitInt16(imm.value()); EmitInt16(imm.value());
else } else {
if (imm.fixup()) {
EmitFixup(imm.fixup());
}
EmitInt32(imm.value()); EmitInt32(imm.value());
}
} }
void AssemblerX86::EmitComplexI8(int rm, const Operand &operand, void AssemblerX86::EmitComplexI8(int rm, const Operand &operand,
......
...@@ -20,8 +20,9 @@ ...@@ -20,8 +20,9 @@
#ifndef SUBZERO_SRC_ASSEMBLER_IA32_H_ #ifndef SUBZERO_SRC_ASSEMBLER_IA32_H_
#define SUBZERO_SRC_ASSEMBLER_IA32_H_ #define SUBZERO_SRC_ASSEMBLER_IA32_H_
#include "IceDefs.h"
#include "IceConditionCodesX8632.h" #include "IceConditionCodesX8632.h"
#include "IceDefs.h"
#include "IceOperand.h"
#include "IceRegistersX8632.h" #include "IceRegistersX8632.h"
#include "IceTypes.h" #include "IceTypes.h"
#include "IceUtils.h" #include "IceUtils.h"
...@@ -31,7 +32,6 @@ ...@@ -31,7 +32,6 @@
namespace Ice { namespace Ice {
class Assembler; class Assembler;
class ConstantRelocatable;
using RegX8632::GPRRegister; using RegX8632::GPRRegister;
using RegX8632::XmmRegister; using RegX8632::XmmRegister;
...@@ -67,18 +67,33 @@ private: ...@@ -67,18 +67,33 @@ private:
class Immediate { class Immediate {
public: public:
explicit Immediate(int32_t value) : value_(value) {} explicit Immediate(int32_t value) : value_(value), fixup_(NULL) {}
Immediate(const Immediate &other) : value_(other.value_) {} explicit Immediate(const Immediate &other)
: value_(other.value_), fixup_(other.fixup_) {}
explicit Immediate(AssemblerFixup *fixup)
: value_(fixup->value()->getOffset()), fixup_(fixup) {
// Use the Offset in the "value" for now. If the symbol is part of
// ".bss", then the relocation's symbol will be plain ".bss" and
// the value will need to be adjusted further to be sym's
// bss offset + Offset.
}
int32_t value() const { return value_; } int32_t value() const { return value_; }
AssemblerFixup *fixup() const { return fixup_; }
bool is_int8() const { return Utils::IsInt(8, value_); } bool is_int8() const {
bool is_uint8() const { return Utils::IsUint(8, value_); } // We currently only allow 32-bit fixups, and they usually have value = 0,
bool is_uint16() const { return Utils::IsUint(16, value_); } // so if fixup_ != NULL, it shouldn't be classified as int8/16.
return fixup_ == NULL && Utils::IsInt(8, value_);
}
bool is_uint8() const { return fixup_ == NULL && Utils::IsUint(8, value_); }
bool is_uint16() const { return fixup_ == NULL && Utils::IsUint(16, value_); }
private: private:
const int32_t value_; const int32_t value_;
AssemblerFixup *fixup_;
}; };
class Operand { class Operand {
...@@ -228,10 +243,21 @@ public: ...@@ -228,10 +243,21 @@ public:
return *this; return *this;
} }
static Address Absolute(const uintptr_t addr, AssemblerFixup *fixup) { static Address Absolute(const uintptr_t addr) {
Address result; Address result;
result.SetModRM(0, RegX8632::Encoded_Reg_ebp); result.SetModRM(0, RegX8632::Encoded_Reg_ebp);
result.SetDisp32(addr); result.SetDisp32(addr);
return result;
}
static Address Absolute(AssemblerFixup *fixup) {
Address result;
result.SetModRM(0, RegX8632::Encoded_Reg_ebp);
// Use the Offset in the displacement for now. If the symbol is part of
// ".bss", then the relocation's symbol will be plain .bss and the
// displacement will need to be adjusted further to be sym's
// bss offset + Offset.
result.SetDisp32(fixup->value()->getOffset());
result.SetFixup(fixup); result.SetFixup(fixup);
return result; return result;
} }
...@@ -427,28 +453,22 @@ public: ...@@ -427,28 +453,22 @@ public:
void setcc(CondX86::BrCond condition, ByteRegister dst); void setcc(CondX86::BrCond condition, ByteRegister dst);
void movl(GPRRegister dst, const Immediate &src); void mov(Type Ty, GPRRegister dst, const Immediate &src);
void movl(GPRRegister dst, GPRRegister src); void mov(Type Ty, GPRRegister dst, GPRRegister src);
void movl(GPRRegister dst, const Address &src); void mov(Type Ty, GPRRegister dst, const Address &src);
void movl(const Address &dst, GPRRegister src); void mov(Type Ty, const Address &dst, GPRRegister src);
void movl(const Address &dst, const Immediate &imm); void mov(Type Ty, const Address &dst, const Immediate &imm);
void movzxb(GPRRegister dst, ByteRegister src); void movzxb(GPRRegister dst, ByteRegister src);
void movzxb(GPRRegister dst, const Address &src); void movzxb(GPRRegister dst, const Address &src);
void movsxb(GPRRegister dst, ByteRegister src); void movsxb(GPRRegister dst, ByteRegister src);
void movsxb(GPRRegister dst, const Address &src); void movsxb(GPRRegister dst, const Address &src);
void movb(ByteRegister dst, const Address &src);
void movb(const Address &dst, ByteRegister src);
void movb(const Address &dst, const Immediate &imm);
void movzxw(GPRRegister dst, GPRRegister src); void movzxw(GPRRegister dst, GPRRegister src);
void movzxw(GPRRegister dst, const Address &src); void movzxw(GPRRegister dst, const Address &src);
void movsxw(GPRRegister dst, GPRRegister src); void movsxw(GPRRegister dst, GPRRegister src);
void movsxw(GPRRegister dst, const Address &src); void movsxw(GPRRegister dst, const Address &src);
void movw(GPRRegister dst, const Address &src);
void movw(const Address &dst, GPRRegister src);
void lea(Type Ty, GPRRegister dst, const Address &src); void lea(Type Ty, GPRRegister dst, const Address &src);
...@@ -744,6 +764,8 @@ public: ...@@ -744,6 +764,8 @@ public:
cmpxchg(Ty, address, reg); cmpxchg(Ty, address, reg);
} }
void EmitSegmentOverride(uint8_t prefix) { EmitUint8(prefix); }
intptr_t PreferredLoopAlignment() { return 16; } intptr_t PreferredLoopAlignment() { return 16; }
void Align(intptr_t alignment, intptr_t offset); void Align(intptr_t alignment, intptr_t offset);
void Bind(Label *label); void Bind(Label *label);
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
; those for pmull vary more wildly depending on operand size (rather than ; those for pmull vary more wildly depending on operand size (rather than
; follow a usual pattern). ; follow a usual pattern).
; RUN: %p2i -i %s --args -O2 -mattr=sse4.1 --verbose none \ ; RUN: %p2i -i %s --args -O2 -mattr=sse4.1 -sandbox --verbose none \
; RUN: | llvm-mc -triple=i686-none-nacl -x86-asm-syntax=intel -filetype=obj \ ; RUN: | llvm-mc -triple=i686-none-nacl -x86-asm-syntax=intel -filetype=obj \
; RUN: | llvm-objdump -d --symbolize -x86-asm-syntax=intel - | FileCheck %s ; RUN: | llvm-objdump -d --symbolize -x86-asm-syntax=intel - | FileCheck %s
; RUN: %p2i -i %s --args --verbose none | FileCheck --check-prefix=ERRORS %s ; RUN: %p2i -i %s --args --verbose none | FileCheck --check-prefix=ERRORS %s
...@@ -127,4 +127,38 @@ define <16 x i8> @load_v16xI8(i32 %addr, i32 %addr2, i32 %addr3) { ...@@ -127,4 +127,38 @@ define <16 x i8> @load_v16xI8(i32 %addr, i32 %addr2, i32 %addr3) {
; CHECK-LABEL: load_v16xI8 ; CHECK-LABEL: load_v16xI8
; CHECK: 0f 10 0{{.*}} movups xmm0, xmmword ptr [e{{.*}}] ; CHECK: 0f 10 0{{.*}} movups xmm0, xmmword ptr [e{{.*}}]
; Test segment override prefix. This happens w/ nacl.read.tp.
declare i8* @llvm.nacl.read.tp()
; Also test more address complex operands via address-mode-optimization.
define i32 @test_nacl_read_tp_more_addressing() {
entry:
%ptr = call i8* @llvm.nacl.read.tp()
%__1 = ptrtoint i8* %ptr to i32
%x = add i32 %__1, %__1
%__3 = inttoptr i32 %x to i32*
%v = load i32* %__3, align 1
%v_add = add i32 %v, 1
%ptr2 = call i8* @llvm.nacl.read.tp()
%__6 = ptrtoint i8* %ptr2 to i32
%y = add i32 %__6, -128
%__8 = inttoptr i32 %y to i32*
%v_add2 = add i32 %v, 4
store i32 %v_add2, i32* %__8, align 1
%z = add i32 %__6, 256
%__9 = inttoptr i32 %z to i32*
%v_add3 = add i32 %v, 91
store i32 %v_add2, i32* %__9, align 1
ret i32 %v
}
; CHECK-LABEL: test_nacl_read_tp_more_addressing
; CHECK: 65 8b 05 00 00 00 00 mov eax, dword ptr gs:[0]
; CHECK: 8b 04 00 mov eax, dword ptr [eax + eax]
; CHECK: 65 8b 0d 00 00 00 00 mov ecx, dword ptr gs:[0]
; CHECK: 89 51 80 mov dword ptr [ecx - 128], edx
; CHECK: 89 91 00 01 00 00 mov dword ptr [ecx + 256], edx
; ERRORS-NOT: ICE translation error ; ERRORS-NOT: ICE translation error
...@@ -276,5 +276,44 @@ entry: ...@@ -276,5 +276,44 @@ entry:
; CHECK-LABEL: icmp8BitMemSwapped ; CHECK-LABEL: icmp8BitMemSwapped
; CHECK: cmp {{[abcd]l|byte ptr}} ; CHECK: cmp {{[abcd]l|byte ptr}}
define internal i32 @testPhi8(i32 %arg, i32 %arg2, i32 %arg3, i32 %arg4, i32 %arg5, i32 %arg6, i32 %arg7, i32 %arg8, i32 %arg9, i32 %arg10) {
entry:
%trunc = trunc i32 %arg to i8
%trunc2 = trunc i32 %arg2 to i8
%trunc3 = trunc i32 %arg3 to i8
%trunc4 = trunc i32 %arg4 to i8
%trunc5 = trunc i32 %arg5 to i8
%cmp1 = icmp sgt i32 %arg, 0
br i1 %cmp1, label %next, label %target
next:
%trunc6_16 = trunc i32 %arg6 to i16
%trunc7_16 = trunc i32 %arg7 to i16
%trunc8_16 = trunc i32 %arg8 to i16
%trunc9 = trunc i32 %arg9 to i8
%trunc10 = trunc i32 %arg10 to i8
%trunc7_8 = trunc i16 %trunc7_16 to i8
%trunc6_8 = trunc i16 %trunc6_16 to i8
%trunc8_8 = trunc i16 %trunc8_16 to i8
br label %target
target:
%merge1 = phi i1 [ %cmp1, %entry ], [ false, %next ]
%merge2 = phi i8 [ %trunc, %entry ], [ %trunc6_8, %next ]
%merge3 = phi i8 [ %trunc2, %entry ], [ %trunc7_8, %next ]
%merge5 = phi i8 [ %trunc4, %entry ], [ %trunc9, %next ]
%merge6 = phi i8 [ %trunc5, %entry ], [ %trunc10, %next ]
%merge4 = phi i8 [ %trunc3, %entry ], [ %trunc8_8, %next ]
%res1 = select i1 %merge1, i8 %merge2, i8 %merge3
%res2 = select i1 %merge1, i8 %merge4, i8 %merge5
%res1_2 = select i1 %merge1, i8 %res1, i8 %res2
%res123 = select i1 %merge1, i8 %merge6, i8 %res1_2
%result = zext i8 %res123 to i32
ret i32 %result
}
; CHECK-LABEL: testPhi8
; This assumes there will be some copy from an 8-bit register / stack slot.
; CHECK-DAG: mov {{.*}}, {{[a-d]}}l
; CHECK-DAG: mov {{.*}}, byte ptr
; CHECK-DAG: mov byte ptr {{.*}}
; ERRORS-NOT: ICE translation error ; ERRORS-NOT: ICE translation error
; DUMP-NOT: SZ ; DUMP-NOT: SZ
...@@ -43,7 +43,10 @@ entry: ...@@ -43,7 +43,10 @@ entry:
; CHECK: mov dword ptr [ ; CHECK: mov dword ptr [
; CHECK: movsx ; CHECK: movsx
; CHECK: sar {{.*}}, 31 ; CHECK: sar {{.*}}, 31
; CHECK: [8] ; This appears to be a bug in llvm-mc. It should be [8] and [12] to represent
; i64v and i64+4.
; CHECK-DAG: [8]
; CHECK-DAG: [8]
define void @from_int16() { define void @from_int16() {
entry: entry:
......
; Test of global initializers. ; Test of global initializers.
; RUN: %p2i -i %s --args --verbose inst | FileCheck %s ; Test -ias=0 to test the lea "hack" until we are fully confident in -ias=1
; RUN: %p2i -i %s --args --verbose none -ias=0 | FileCheck %s
; Test -ias=1 and try to cross reference instructions w/ the symbol table.
; RUN: %p2i -i %s --args --verbose none \
; RUN: | llvm-mc -triple=i686-none-nacl -x86-asm-syntax=intel -filetype=obj \
; RUN: | llvm-objdump -d -r --symbolize -x86-asm-syntax=intel - \
; RUN: | FileCheck --check-prefix=IAS %s
; RUN: %p2i -i %s --args --verbose none \ ; RUN: %p2i -i %s --args --verbose none \
; RUN: | llvm-mc -triple=i686-none-nacl -x86-asm-syntax=intel -filetype=obj ; RUN: | llvm-mc -triple=i686-none-nacl -x86-asm-syntax=intel -filetype=obj \
; RUN: | llvm-objdump -d -t --symbolize -x86-asm-syntax=intel - \
; RUN: | FileCheck --check-prefix=SYMTAB %s
; RUN: %p2i -i %s --args --verbose none | FileCheck --check-prefix=ERRORS %s ; RUN: %p2i -i %s --args --verbose none | FileCheck --check-prefix=ERRORS %s
@PrimitiveInit = internal global [4 x i8] c"\1B\00\00\00", align 4 @PrimitiveInit = internal global [4 x i8] c"\1B\00\00\00", align 4
...@@ -114,6 +124,49 @@ entry: ...@@ -114,6 +124,49 @@ entry:
; CHECK: leal ArrayUninit, ; CHECK: leal ArrayUninit,
; CHECK: .intel_syntax ; CHECK: .intel_syntax
; llvm-objdump does not indicate what symbol the mov/relocation applies to
; so we grep for "mov {{.*}}, OFFSET", along with "OFFSET {{.*}} symbol" in
; the symbol table as a sanity check. NOTE: The symbol table sorting has no
; relation to the code's references.
; IAS-LABEL: main
; SYMTAB-LABEL: SYMBOL TABLE
; SYMTAB-DAG: 00000000 {{.*}} .data {{.*}} PrimitiveInit
; IAS: mov {{.*}}, 0
; IAS-NEXT: R_386_32
; IAS: call
; SYMTAB-DAG: 00000000 {{.*}} .rodata {{.*}} PrimitiveInitConst
; IAS: mov {{.*}}, 0
; IAS-NEXT: R_386_32
; IAS: call
; SYMTAB-DAG: 00000000 {{.*}} .bss {{.*}} PrimitiveInitStatic
; IAS: mov {{.*}}, 0
; IAS-NEXT: R_386_32
; IAS: call
; SYMTAB-DAG: 00000004 {{.*}} .bss {{.*}} PrimitiveUninit
; IAS: mov {{.*}}, 4
; IAS-NEXT: R_386_32
; IAS: call
; SYMTAB-DAG: 00000004{{.*}}.data{{.*}}ArrayInit
; IAS: mov {{.*}}, 4
; IAS-NEXT: R_386_32
; IAS: call
; SYMTAB-DAG: 00000018 {{.*}} .data {{.*}} ArrayInitPartial
; IAS: mov {{.*}}, 24
; IAS-NEXT: R_386_32
; IAS: call
; SYMTAB-DAG: 00000008 {{.*}} .bss {{.*}} ArrayUninit
; IAS: mov {{.*}}, 8
; IAS-NEXT: R_386_32
; IAS: call
declare void @use(i32) declare void @use(i32)
define internal i32 @nacl_tp_tdb_offset(i32 %__0) { define internal i32 @nacl_tp_tdb_offset(i32 %__0) {
......
...@@ -6,11 +6,11 @@ ...@@ -6,11 +6,11 @@
; TODO(kschimpf) Find out why lc2i is needed. ; TODO(kschimpf) Find out why lc2i is needed.
; RUN: %lc2i -i %s --args -O2 --verbose none \ ; RUN: %lc2i -i %s --args -O2 --verbose none \
; RUN: | llvm-mc -triple=i686-none-nacl -x86-asm-syntax=intel -filetype=obj \ ; RUN: | llvm-mc -triple=i686-none-nacl -x86-asm-syntax=intel -filetype=obj \
; RUN: | llvm-objdump -d -symbolize -x86-asm-syntax=intel - | FileCheck %s ; RUN: | llvm-objdump -d -r -symbolize -x86-asm-syntax=intel - | FileCheck %s
; TODO(jvoung): llvm-objdump doesn't symbolize global symbols well, so we ; TODO(jvoung): llvm-objdump doesn't symbolize global symbols well, so we
; have [0] == g32_a, [4] == g32_b, [8] == g32_c. ; have 0 == g32_a, 4 == g32_b, 8 == g32_c.
; g32_d is also [0] because it's in the .data section instead of .bss. ; g32_d is also 0 because it's in the .data section instead of .bss.
declare void @llvm.nacl.atomic.fence.all() declare void @llvm.nacl.atomic.fence.all()
declare i32 @llvm.nacl.atomic.load.i32(i32*, i32) declare i32 @llvm.nacl.atomic.load.i32(i32*, i32)
...@@ -50,15 +50,18 @@ entry: ...@@ -50,15 +50,18 @@ entry:
; CHECK: mov {{.*}}, esp ; CHECK: mov {{.*}}, esp
; CHECK: mov dword ptr {{.*}}, 999 ; CHECK: mov dword ptr {{.*}}, 999
; atomic store (w/ its own mfence) ; atomic store (w/ its own mfence)
; CHECK: dword ptr [0] ; CHECK: mov {{.*}}, 0
; CHECK-NEXT: R_386_32
; The load + add are optimized into one everywhere. ; The load + add are optimized into one everywhere.
; CHECK: add {{.*}}, dword ptr ; CHECK: add {{.*}}, dword ptr
; CHECK: mov dword ptr ; CHECK: mov dword ptr
; CHECK: mfence ; CHECK: mfence
; CHECK: dword ptr [4] ; CHECK: mov {{.*}}, 4
; CHECK-NEXT: R_386_32
; CHECK: add {{.*}}, dword ptr ; CHECK: add {{.*}}, dword ptr
; CHECK: mov dword ptr ; CHECK: mov dword ptr
; CHECK: dword ptr [8] ; CHECK: mov {{.*}}, 8
; CHECK-NEXT: R_386_32
; CHECK: add {{.*}}, dword ptr ; CHECK: add {{.*}}, dword ptr
; CHECK: mfence ; CHECK: mfence
; CHECK: mov dword ptr ; CHECK: mov dword ptr
...@@ -93,14 +96,17 @@ entry: ...@@ -93,14 +96,17 @@ entry:
; CHECK: mov {{.*}}, esp ; CHECK: mov {{.*}}, esp
; CHECK: mov dword ptr {{.*}}, 999 ; CHECK: mov dword ptr {{.*}}, 999
; atomic store (w/ its own mfence) ; atomic store (w/ its own mfence)
; CHECK: dword ptr [0] ; CHECK: mov {{.*}}, 0
; CHECK-NEXT: R_386_32
; CHECK: add {{.*}}, dword ptr ; CHECK: add {{.*}}, dword ptr
; CHECK: mov dword ptr ; CHECK: mov dword ptr
; CHECK: mfence ; CHECK: mfence
; CHECK: dword ptr [4] ; CHECK: mov {{.*}}, 4
; CHECK-NEXT: R_386_32
; CHECK: add {{.*}}, dword ptr ; CHECK: add {{.*}}, dword ptr
; CHECK: mov dword ptr ; CHECK: mov dword ptr
; CHECK: dword ptr [8] ; CHECK: mov {{.*}}, 8
; CHECK-NEXT: R_386_32
; CHECK: mfence ; CHECK: mfence
; Load + add can still be optimized into one instruction ; Load + add can still be optimized into one instruction
; because it is not separated by a fence. ; because it is not separated by a fence.
...@@ -137,11 +143,13 @@ entry: ...@@ -137,11 +143,13 @@ entry:
; CHECK: mov {{.*}}, esp ; CHECK: mov {{.*}}, esp
; CHECK: mov dword ptr {{.*}}, 999 ; CHECK: mov dword ptr {{.*}}, 999
; atomic store (w/ its own mfence) ; atomic store (w/ its own mfence)
; CHECK: dword ptr [0] ; CHECK: mov {{.*}}, 0
; CHECK-NEXT: R_386_32
; CHECK: add {{.*}}, dword ptr ; CHECK: add {{.*}}, dword ptr
; CHECK: mov dword ptr ; CHECK: mov dword ptr
; CHECK: mfence ; CHECK: mfence
; CHECK: dword ptr [4] ; CHECK: mov {{.*}}, 4
; CHECK-NEXT: R_386_32
; This load + add are no longer optimized into one, ; This load + add are no longer optimized into one,
; though perhaps it should be legal as long as ; though perhaps it should be legal as long as
; the load stays on the same side of the fence. ; the load stays on the same side of the fence.
...@@ -149,7 +157,8 @@ entry: ...@@ -149,7 +157,8 @@ entry:
; CHECK: mfence ; CHECK: mfence
; CHECK: add {{.*}}, 1 ; CHECK: add {{.*}}, 1
; CHECK: mov dword ptr ; CHECK: mov dword ptr
; CHECK: dword ptr [8] ; CHECK: mov {{.*}}, 8
; CHECK-NEXT: R_386_32
; CHECK: add {{.*}}, dword ptr ; CHECK: add {{.*}}, dword ptr
; CHECK: mov dword ptr ; CHECK: mov dword ptr
...@@ -189,7 +198,8 @@ entry: ...@@ -189,7 +198,8 @@ entry:
ret i32 %b1234 ret i32 %b1234
} }
; CHECK-LABEL: could_have_fused_loads ; CHECK-LABEL: could_have_fused_loads
; CHECK: dword ptr [0] ; CHECK: mov {{.*}}, 0
; CHECK-NEXT: R_386_32
; CHECK: mov {{.*}}, byte ptr ; CHECK: mov {{.*}}, byte ptr
; CHECK: mov {{.*}}, byte ptr ; CHECK: mov {{.*}}, byte ptr
; CHECK: mov {{.*}}, byte ptr ; CHECK: mov {{.*}}, byte ptr
...@@ -213,7 +223,8 @@ branch2: ...@@ -213,7 +223,8 @@ branch2:
ret i32 %z ret i32 %z
} }
; CHECK-LABEL: could_have_hoisted_loads ; CHECK-LABEL: could_have_hoisted_loads
; CHECK: dword ptr [0] ; CHECK: mov {{.*}}, 0
; CHECK-NEXT: R_386_32
; CHECK: jne {{.*}} ; CHECK: jne {{.*}}
; CHECK: mov {{.*}}, dword ptr ; CHECK: mov {{.*}}, dword ptr
; CHECK: ret ; CHECK: ret
......
...@@ -74,11 +74,14 @@ entry: ...@@ -74,11 +74,14 @@ entry:
%x = add i32 %__1, %__1 %x = add i32 %__1, %__1
%__3 = inttoptr i32 %x to i32* %__3 = inttoptr i32 %x to i32*
%v = load i32* %__3, align 1 %v = load i32* %__3, align 1
%v_add = add i32 %v, 1
%ptr2 = call i8* @llvm.nacl.read.tp() %ptr2 = call i8* @llvm.nacl.read.tp()
%__6 = ptrtoint i8* %ptr2 to i32 %__6 = ptrtoint i8* %ptr2 to i32
%y = add i32 %__6, 4 %y = add i32 %__6, 4
%__8 = inttoptr i32 %y to i32* %__8 = inttoptr i32 %y to i32*
store i32 %v, i32* %__8, align 1 %v_add2 = add i32 %v, 4
store i32 %v_add2, i32* %__8, align 1
ret i32 %v ret i32 %v
} }
; CHECK-LABEL: test_nacl_read_tp_more_addressing ; CHECK-LABEL: test_nacl_read_tp_more_addressing
......
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