| Index: src/IceInstX8632.cpp
|
| diff --git a/src/IceInstX8632.cpp b/src/IceInstX8632.cpp
|
| index 93c193f2785934204fc0e6d8b7ab2e92ffce11d4..8c6b99a65ff3d3dcb26428cbf9e6fcb90994a79c 100644
|
| --- a/src/IceInstX8632.cpp
|
| +++ b/src/IceInstX8632.cpp
|
| @@ -12,6 +12,7 @@
|
| //
|
| //===----------------------------------------------------------------------===//
|
|
|
| +#include "assembler_ia32.h"
|
| #include "IceCfg.h"
|
| #include "IceCfgNode.h"
|
| #include "IceConditionCodesX8632.h"
|
| @@ -331,6 +332,47 @@ InstX8632Xchg::InstX8632Xchg(Cfg *Func, Operand *Dest, Variable *Source)
|
|
|
| // ======================== Dump routines ======================== //
|
|
|
| +namespace {
|
| +
|
| +void emitIASBytes(Ostream &Str, const x86::AssemblerX86 *Asm,
|
| + intptr_t StartPosition) {
|
| + intptr_t EndPosition = Asm->GetPosition();
|
| + intptr_t LastFixupLoc = -1;
|
| + AssemblerFixup *LastFixup = NULL;
|
| + if (Asm->GetLatestFixup()) {
|
| + LastFixup = Asm->GetLatestFixup();
|
| + LastFixupLoc = LastFixup->position();
|
| + }
|
| + if (LastFixupLoc < StartPosition) {
|
| + // The fixup doesn't apply to this current block.
|
| + for (intptr_t i = 0; i < EndPosition - StartPosition; ++i) {
|
| + Str << "\t.byte "
|
| + << static_cast<uint32_t>(Asm->LoadBuffer<uint8_t>(StartPosition + i))
|
| + << "\n";
|
| + }
|
| + return;
|
| + }
|
| + const intptr_t FixupSize = 4;
|
| + assert(LastFixupLoc + FixupSize <= EndPosition);
|
| + // The fixup does apply to this current block.
|
| + for (intptr_t i = 0; i < LastFixupLoc - StartPosition; ++i) {
|
| + Str << "\t.byte "
|
| + << static_cast<uint32_t>(Asm->LoadBuffer<uint8_t>(StartPosition + i))
|
| + << "\n";
|
| + }
|
| + Str << "\t.long " << LastFixup->value()->getName();
|
| + if (LastFixup->value()->getOffset()) {
|
| + Str << " + " << LastFixup->value()->getOffset();
|
| + }
|
| + Str << "\n";
|
| + for (intptr_t i = LastFixupLoc + FixupSize; i < EndPosition; ++i) {
|
| + Str << "\t.byte " << static_cast<uint32_t>(Asm->LoadBuffer<uint8_t>(i))
|
| + << "\n";
|
| + }
|
| +}
|
| +
|
| +} // end of anonymous namespace
|
| +
|
| void InstX8632::dump(const Cfg *Func) const {
|
| Ostream &Str = Func->getContext()->getStrDump();
|
| Str << "[X8632] ";
|
| @@ -436,6 +478,38 @@ void emitTwoAddress(const char *Opcode, const Inst *Inst, const Cfg *Func,
|
| Str << "\n";
|
| }
|
|
|
| +void
|
| +emitIASVarOperandTyXMM(const Cfg *Func, Type Ty, const Variable *Var,
|
| + const Operand *Src,
|
| + const x86::AssemblerX86::TypedXmmEmitters &Emitter) {
|
| + x86::AssemblerX86 *Asm = Func->getAssembler<x86::AssemblerX86>();
|
| + intptr_t StartPosition = Asm->GetPosition();
|
| + assert(Var->hasReg());
|
| + RegX8632::XmmRegister VarReg = RegX8632::getEncodedXmm(Var->getRegNum());
|
| + if (const Variable *SrcVar = llvm::dyn_cast<Variable>(Src)) {
|
| + if (SrcVar->hasReg()) {
|
| + RegX8632::XmmRegister SrcReg =
|
| + RegX8632::getEncodedXmm(SrcVar->getRegNum());
|
| + (Asm->*(Emitter.XmmXmm))(Ty, VarReg, SrcReg);
|
| + } else {
|
| + x86::Address SrcStackAddr = static_cast<TargetX8632 *>(Func->getTarget())
|
| + ->stackVarToAsmOperand(SrcVar);
|
| + (Asm->*(Emitter.XmmAddr))(Ty, VarReg, SrcStackAddr);
|
| + }
|
| + } else if (const OperandX8632Mem *Mem =
|
| + llvm::dyn_cast<OperandX8632Mem>(Src)) {
|
| + x86::Address SrcAddr = Mem->toAsmAddress(Asm);
|
| + (Asm->*(Emitter.XmmAddr))(Ty, VarReg, SrcAddr);
|
| + } else if (const Constant *Imm = llvm::dyn_cast<Constant>(Src)) {
|
| + (Asm->*(Emitter.XmmAddr))(
|
| + Ty, VarReg, x86::Address::ofConstPool(Func->getContext(), Asm, Imm));
|
| + } else {
|
| + llvm_unreachable("Unexpected operand type");
|
| + }
|
| + Ostream &Str = Func->getContext()->getStrEmit();
|
| + emitIASBytes(Str, Asm, StartPosition);
|
| +}
|
| +
|
| bool checkForRedundantAssign(const Variable *Dest, const Operand *Source) {
|
| const Variable *Src = llvm::dyn_cast<const Variable>(Source);
|
| if (Src == NULL)
|
| @@ -512,6 +586,56 @@ template <> const char *InstX8632Pblendvb::Opcode = "pblendvb";
|
| template <> const char *InstX8632Pextr::Opcode = "pextr";
|
| template <> const char *InstX8632Pshufd::Opcode = "pshufd";
|
|
|
| +// Binary XMM ops
|
| +template <>
|
| +const x86::AssemblerX86::TypedXmmEmitters InstX8632Addss::Emitter = {
|
| + &x86::AssemblerX86::addss, &x86::AssemblerX86::addss, NULL};
|
| +template <>
|
| +const x86::AssemblerX86::TypedXmmEmitters InstX8632Addps::Emitter = {
|
| + &x86::AssemblerX86::addps, &x86::AssemblerX86::addps, NULL};
|
| +template <>
|
| +const x86::AssemblerX86::TypedXmmEmitters InstX8632Divss::Emitter = {
|
| + &x86::AssemblerX86::divss, &x86::AssemblerX86::divss, NULL};
|
| +template <>
|
| +const x86::AssemblerX86::TypedXmmEmitters InstX8632Divps::Emitter = {
|
| + &x86::AssemblerX86::divps, &x86::AssemblerX86::divps, NULL};
|
| +template <>
|
| +const x86::AssemblerX86::TypedXmmEmitters InstX8632Mulss::Emitter = {
|
| + &x86::AssemblerX86::mulss, &x86::AssemblerX86::mulss, NULL};
|
| +template <>
|
| +const x86::AssemblerX86::TypedXmmEmitters InstX8632Mulps::Emitter = {
|
| + &x86::AssemblerX86::mulps, &x86::AssemblerX86::mulps, NULL};
|
| +template <>
|
| +const x86::AssemblerX86::TypedXmmEmitters InstX8632Padd::Emitter = {
|
| + &x86::AssemblerX86::padd, &x86::AssemblerX86::padd, NULL};
|
| +template <>
|
| +const x86::AssemblerX86::TypedXmmEmitters InstX8632Pand::Emitter = {
|
| + &x86::AssemblerX86::pand, &x86::AssemblerX86::pand, NULL};
|
| +template <>
|
| +const x86::AssemblerX86::TypedXmmEmitters InstX8632Pandn::Emitter = {
|
| + &x86::AssemblerX86::pandn, &x86::AssemblerX86::pandn, NULL};
|
| +template <>
|
| +const x86::AssemblerX86::TypedXmmEmitters InstX8632Pmuludq::Emitter = {
|
| + &x86::AssemblerX86::pmuludq, &x86::AssemblerX86::pmuludq, NULL};
|
| +template <>
|
| +const x86::AssemblerX86::TypedXmmEmitters InstX8632Por::Emitter = {
|
| + &x86::AssemblerX86::por, &x86::AssemblerX86::por, NULL};
|
| +template <>
|
| +const x86::AssemblerX86::TypedXmmEmitters InstX8632Psub::Emitter = {
|
| + &x86::AssemblerX86::psub, &x86::AssemblerX86::psub, NULL};
|
| +template <>
|
| +const x86::AssemblerX86::TypedXmmEmitters InstX8632Pxor::Emitter = {
|
| + &x86::AssemblerX86::pxor, &x86::AssemblerX86::pxor, NULL};
|
| +template <>
|
| +const x86::AssemblerX86::TypedXmmEmitters InstX8632Sqrtss::Emitter = {
|
| + &x86::AssemblerX86::sqrtss, &x86::AssemblerX86::sqrtss, NULL};
|
| +template <>
|
| +const x86::AssemblerX86::TypedXmmEmitters InstX8632Subss::Emitter = {
|
| + &x86::AssemblerX86::subss, &x86::AssemblerX86::subss, NULL};
|
| +template <>
|
| +const x86::AssemblerX86::TypedXmmEmitters InstX8632Subps::Emitter = {
|
| + &x86::AssemblerX86::subps, &x86::AssemblerX86::subps, NULL};
|
| +
|
| template <> void InstX8632Sqrtss::emit(const Cfg *Func) const {
|
| Ostream &Str = Func->getContext()->getStrEmit();
|
| assert(getSrcSize() == 1);
|
| @@ -790,6 +914,28 @@ void InstX8632Cmpps::emit(const Cfg *Func) const {
|
| Str << "\n";
|
| }
|
|
|
| +void InstX8632Cmpps::emitIAS(const Cfg *Func) const {
|
| + Ostream &Str = Func->getContext()->getStrEmit();
|
| + x86::AssemblerX86 *Asm = Func->getAssembler<x86::AssemblerX86>();
|
| + intptr_t StartPosition = Asm->GetPosition();
|
| + assert(getSrcSize() == 2);
|
| + assert(Condition < CondX86::Cmpps_Invalid);
|
| + // Assuming there isn't any load folding for cmpps, and vector constants
|
| + // are not allowed in PNaCl.
|
| + assert(llvm::isa<Variable>(getSrc(1)));
|
| + const Variable *SrcVar = llvm::cast<Variable>(getSrc(1));
|
| + if (SrcVar->hasReg()) {
|
| + Asm->cmpps(RegX8632::getEncodedXmm(getDest()->getRegNum()),
|
| + RegX8632::getEncodedXmm(SrcVar->getRegNum()), Condition);
|
| + } else {
|
| + x86::Address SrcStackAddr = static_cast<TargetX8632 *>(Func->getTarget())
|
| + ->stackVarToAsmOperand(SrcVar);
|
| + Asm->cmpps(RegX8632::getEncodedXmm(getDest()->getRegNum()), SrcStackAddr,
|
| + Condition);
|
| + }
|
| + emitIASBytes(Str, Asm, StartPosition);
|
| +}
|
| +
|
| void InstX8632Cmpps::dump(const Cfg *Func) const {
|
| Ostream &Str = Func->getContext()->getStrDump();
|
| assert(Condition < CondX86::Cmpps_Invalid);
|
| @@ -893,6 +1039,18 @@ void InstX8632Ucomiss::emit(const Cfg *Func) const {
|
| Str << "\n";
|
| }
|
|
|
| +void InstX8632Ucomiss::emitIAS(const Cfg *Func) const {
|
| + assert(getSrcSize() == 2);
|
| + // Currently src0 is always a variable by convention, to avoid having
|
| + // two memory operands.
|
| + assert(llvm::isa<Variable>(getSrc(0)));
|
| + const Variable *Src0 = llvm::cast<Variable>(getSrc(0));
|
| + Type Ty = Src0->getType();
|
| + const static x86::AssemblerX86::TypedXmmEmitters Emitter = {
|
| + &x86::AssemblerX86::ucomiss, &x86::AssemblerX86::ucomiss, NULL};
|
| + emitIASVarOperandTyXMM(Func, Ty, Src0, getSrc(1), Emitter);
|
| +}
|
| +
|
| void InstX8632Ucomiss::dump(const Cfg *Func) const {
|
| Ostream &Str = Func->getContext()->getStrDump();
|
| Str << "ucomiss." << getSrc(0)->getType() << " ";
|
| @@ -1133,6 +1291,15 @@ void InstX8632Nop::emit(const Cfg *Func) const {
|
| Str << "\tnop\t# variant = " << Variant << "\n";
|
| }
|
|
|
| +void InstX8632Nop::emitIAS(const Cfg *Func) const {
|
| + Ostream &Str = Func->getContext()->getStrEmit();
|
| + x86::AssemblerX86 *Asm = Func->getAssembler<x86::AssemblerX86>();
|
| + intptr_t StartPosition = Asm->GetPosition();
|
| + // TODO: Emit the right code for the variant.
|
| + Asm->nop();
|
| + emitIASBytes(Str, Asm, StartPosition);
|
| +}
|
| +
|
| void InstX8632Nop::dump(const Cfg *Func) const {
|
| Ostream &Str = Func->getContext()->getStrDump();
|
| Str << "nop (variant = " << Variant << ")";
|
| @@ -1272,6 +1439,20 @@ void InstX8632Pop::emit(const Cfg *Func) const {
|
| Str << "\n";
|
| }
|
|
|
| +void InstX8632Pop::emitIAS(const Cfg *Func) const {
|
| + Ostream &Str = Func->getContext()->getStrEmit();
|
| + assert(getSrcSize() == 0);
|
| + x86::AssemblerX86 *Asm = Func->getAssembler<x86::AssemblerX86>();
|
| + intptr_t StartPosition = Asm->GetPosition();
|
| + if (getDest()->hasReg()) {
|
| + Asm->popl(RegX8632::getEncodedGPR(getDest()->getRegNum()));
|
| + } else {
|
| + Asm->popl(static_cast<TargetX8632 *>(Func->getTarget())
|
| + ->stackVarToAsmOperand(getDest()));
|
| + }
|
| + emitIASBytes(Str, Asm, StartPosition);
|
| +}
|
| +
|
| void InstX8632Pop::dump(const Cfg *Func) const {
|
| Ostream &Str = Func->getContext()->getStrDump();
|
| dumpDest(Func);
|
| @@ -1284,6 +1465,15 @@ void InstX8632AdjustStack::emit(const Cfg *Func) const {
|
| Func->getTarget()->updateStackAdjustment(Amount);
|
| }
|
|
|
| +void InstX8632AdjustStack::emitIAS(const Cfg *Func) const {
|
| + Ostream &Str = Func->getContext()->getStrEmit();
|
| + x86::AssemblerX86 *Asm = Func->getAssembler<x86::AssemblerX86>();
|
| + intptr_t StartPosition = Asm->GetPosition();
|
| + Asm->subl(RegX8632::Encoded_Reg_esp, x86::Immediate(Amount));
|
| + emitIASBytes(Str, Asm, StartPosition);
|
| + Func->getTarget()->updateStackAdjustment(Amount);
|
| +}
|
| +
|
| void InstX8632AdjustStack::dump(const Cfg *Func) const {
|
| Ostream &Str = Func->getContext()->getStrDump();
|
| Str << "esp = sub.i32 esp, " << Amount;
|
| @@ -1356,6 +1546,14 @@ void InstX8632Ret::emit(const Cfg *Func) const {
|
| Str << "\tret\n";
|
| }
|
|
|
| +void InstX8632Ret::emitIAS(const Cfg *Func) const {
|
| + Ostream &Str = Func->getContext()->getStrEmit();
|
| + x86::AssemblerX86 *Asm = Func->getAssembler<x86::AssemblerX86>();
|
| + intptr_t StartPosition = Asm->GetPosition();
|
| + Asm->ret();
|
| + emitIASBytes(Str, Asm, StartPosition);
|
| +}
|
| +
|
| void InstX8632Ret::dump(const Cfg *Func) const {
|
| Ostream &Str = Func->getContext()->getStrDump();
|
| Type Ty = (getSrcSize() == 0 ? IceType_void : getSrc(0)->getType());
|
| @@ -1498,6 +1696,41 @@ void OperandX8632Mem::dump(const Cfg *Func, Ostream &Str) const {
|
| Str << "]";
|
| }
|
|
|
| +x86::Address OperandX8632Mem::toAsmAddress(Assembler *Asm) const {
|
| + int32_t Disp = 0;
|
| + AssemblerFixup *Fixup = NULL;
|
| + // Determine the offset (is it relocatable?)
|
| + if (getOffset()) {
|
| + if (ConstantInteger32 *CI =
|
| + llvm::dyn_cast<ConstantInteger32>(getOffset())) {
|
| + Disp = static_cast<int32_t>(CI->getValue());
|
| + } else if (ConstantRelocatable *CR =
|
| + llvm::dyn_cast<ConstantRelocatable>(getOffset())) {
|
| + // TODO(jvoung): CR + non-zero-offset isn't really tested yet,
|
| + // since the addressing mode optimization doesn't try to combine
|
| + // ConstantRelocatable with something else.
|
| + assert(CR->getOffset() == 0);
|
| + Fixup = x86::DisplacementRelocation::create(Asm, FK_Abs_4, CR);
|
| + } else {
|
| + llvm_unreachable("Unexpected offset type");
|
| + }
|
| + }
|
| +
|
| + // Now convert to the various possible forms.
|
| + if (getBase() && getIndex()) {
|
| + return x86::Address(RegX8632::getEncodedGPR(getBase()->getRegNum()),
|
| + RegX8632::getEncodedGPR(getIndex()->getRegNum()),
|
| + x86::ScaleFactor(getShift()), Disp);
|
| + } else if (getBase()) {
|
| + return x86::Address(RegX8632::getEncodedGPR(getBase()->getRegNum()), Disp);
|
| + } else if (getIndex()) {
|
| + return x86::Address(RegX8632::getEncodedGPR(getIndex()->getRegNum()),
|
| + x86::ScaleFactor(getShift()), Disp);
|
| + } else {
|
| + return x86::Address::Absolute(Disp, Fixup);
|
| + }
|
| +}
|
| +
|
| void VariableSplit::emit(const Cfg *Func) const {
|
| Ostream &Str = Func->getContext()->getStrEmit();
|
| assert(!Var->hasReg());
|
|
|