Chromium Code Reviews| Index: src/IceInstX8632.cpp |
| diff --git a/src/IceInstX8632.cpp b/src/IceInstX8632.cpp |
| index 305be738b5288d764268cbf33241617ec6c740a2..df29cc7731f80bfae44b7e23e6a82559560e9336 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" |
| @@ -328,6 +329,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] "; |
| @@ -433,6 +475,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); |
|
Jim Stichnoth
2014/09/22 21:58:13
My head is exploding trying to figure out what ->*
jvoung (off chromium)
2014/09/23 00:26:16
Acknowledged.
|
| + } 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) |
| @@ -509,6 +583,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); |
| @@ -521,6 +645,14 @@ template <> void InstX8632Sqrtss::emit(const Cfg *Func) const { |
| Str << "\n"; |
| } |
| +template <> void InstX8632Addps::emitIAS(const Cfg *Func) const { |
| + assert(getSrcSize() == 2); |
| + Type Ty = getDest()->getType(); |
| + const static x86::AssemblerX86::TypedXmmEmitters Emitter = { |
| + &x86::AssemblerX86::addps, &x86::AssemblerX86::addps, NULL}; |
| + emitIASVarOperandTyXMM(Func, Ty, getDest(), getSrc(1), Emitter); |
| +} |
| + |
| template <> void InstX8632Addss::emit(const Cfg *Func) const { |
| char buf[30]; |
| snprintf(buf, llvm::array_lengthof(buf), "add%s", |
| @@ -787,6 +919,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); |
| @@ -890,6 +1044,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() << " "; |
| @@ -1130,6 +1296,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 << ")"; |
| @@ -1269,6 +1444,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); |
| @@ -1281,6 +1470,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; |
| @@ -1353,6 +1551,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()); |
| @@ -1495,6 +1701,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->getLocalUseNode() == NULL || |