Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(23)

Unified Diff: src/IceInstX8632.cpp

Issue 656983002: emitIAS for Shld and Shrd and the ternary and three-address ops. (Closed) Base URL: https://chromium.googlesource.com/native_client/pnacl-subzero.git@master
Patch Set: stuff Created 6 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « src/IceInstX8632.h ('k') | src/assembler_ia32.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/IceInstX8632.cpp
diff --git a/src/IceInstX8632.cpp b/src/IceInstX8632.cpp
index 75c294fcfdc603205633902b4c8b59a8ca4aedf9..6b1e40cc4e88164dc37734a1a03357bd66867603 100644
--- a/src/IceInstX8632.cpp
+++ b/src/IceInstX8632.cpp
@@ -602,6 +602,30 @@ void emitIASGPRShift(const Cfg *Func, Type Ty, const Variable *Var,
emitIASBytes(Func, Asm, StartPosition);
}
+void emitIASGPRShiftDouble(const Cfg *Func, const Variable *Dest,
+ const Operand *Src1Op, const Operand *Src2Op,
+ const x86::AssemblerX86::GPREmitterShiftD &Emitter) {
+ x86::AssemblerX86 *Asm = Func->getAssembler<x86::AssemblerX86>();
+ intptr_t StartPosition = Asm->GetPosition();
+ // Dest can be reg or mem, but we only use the reg variant.
+ assert(Dest->hasReg());
+ RegX8632::GPRRegister DestReg = RegX8632::getEncodedGPR(Dest->getRegNum());
+ // Src1 must be reg.
+ const auto Src1 = llvm::cast<Variable>(Src1Op);
+ assert(Src1->hasReg());
+ RegX8632::GPRRegister SrcReg = RegX8632::getEncodedGPR(Src1->getRegNum());
+ Type Ty = Src1->getType();
+ // Src2 can be the implicit CL register or an immediate.
+ if (const auto Imm = llvm::dyn_cast<ConstantInteger32>(Src2Op)) {
+ (Asm->*(Emitter.GPRGPRImm))(Ty, DestReg, SrcReg,
+ x86::Immediate(Imm->getValue()));
+ } else {
+ assert(llvm::cast<Variable>(Src2Op)->getRegNum() == RegX8632::Reg_ecx);
+ (Asm->*(Emitter.GPRGPR))(Ty, DestReg, SrcReg);
+ }
+ emitIASBytes(Func, Asm, StartPosition);
+}
+
void emitIASXmmShift(const Cfg *Func, Type Ty, const Variable *Var,
const Operand *Src,
const x86::AssemblerX86::XmmEmitterShiftOp &Emitter) {
@@ -686,6 +710,37 @@ void emitIASCastRegOp(
emitIASBytes(Func, Asm, StartPosition);
}
+template <typename DReg_t, typename SReg_t, DReg_t (*destEnc)(int32_t),
+ SReg_t (*srcEnc)(int32_t)>
+void emitIASThreeOpImmOps(
+ const Cfg *Func, Type DispatchTy, const Variable *Dest, const Operand *Src0,
+ const Operand *Src1,
+ const x86::AssemblerX86::ThreeOpImmEmitter<DReg_t, SReg_t> Emitter) {
+ x86::AssemblerX86 *Asm = Func->getAssembler<x86::AssemblerX86>();
+ intptr_t StartPosition = Asm->GetPosition();
+ // This only handles Dest being a register, and Src1 being an immediate.
+ assert(Dest->hasReg());
+ DReg_t DestReg = destEnc(Dest->getRegNum());
+ x86::Immediate Imm(llvm::cast<ConstantInteger32>(Src1)->getValue());
+ if (const auto SrcVar = llvm::dyn_cast<Variable>(Src0)) {
+ if (SrcVar->hasReg()) {
+ SReg_t SrcReg = srcEnc(SrcVar->getRegNum());
+ (Asm->*(Emitter.RegRegImm))(DispatchTy, DestReg, SrcReg, Imm);
+ } else {
+ x86::Address SrcStackAddr = static_cast<TargetX8632 *>(Func->getTarget())
+ ->stackVarToAsmOperand(SrcVar);
+ (Asm->*(Emitter.RegAddrImm))(DispatchTy, DestReg, SrcStackAddr, Imm);
+ }
+ } else if (const auto Mem = llvm::dyn_cast<OperandX8632Mem>(Src0)) {
+ Mem->emitSegmentOverride(Asm);
+ (Asm->*(Emitter.RegAddrImm))(DispatchTy, DestReg, Mem->toAsmAddress(Asm),
+ Imm);
+ } else {
+ llvm_unreachable("Unexpected operand type");
+ }
+ emitIASBytes(Func, Asm, StartPosition);
+}
+
void emitIASMovlikeXMM(const Cfg *Func, const Variable *Dest,
const Operand *Src,
const x86::AssemblerX86::XmmEmitterMovOps Emitter) {
@@ -1174,6 +1229,21 @@ template <> void InstX8632Imul::emitIAS(const Cfg *Func) const {
}
}
+template <> void InstX8632Insertps::emitIAS(const Cfg *Func) const {
+ assert(getSrcSize() == 3);
+ assert(static_cast<TargetX8632 *>(Func->getTarget())->getInstructionSet() >=
+ TargetX8632::SSE4_1);
+ const Variable *Dest = getDest();
+ assert(Dest == getSrc(0));
+ Type Ty = Dest->getType();
+ static const x86::AssemblerX86::ThreeOpImmEmitter<
+ RegX8632::XmmRegister, RegX8632::XmmRegister> Emitter = {
+ &x86::AssemblerX86::insertps, &x86::AssemblerX86::insertps};
+ emitIASThreeOpImmOps<RegX8632::XmmRegister, RegX8632::XmmRegister,
+ RegX8632::getEncodedXmm, RegX8632::getEncodedXmm>(
+ Func, Ty, Dest, getSrc(1), getSrc(2), Emitter);
+}
+
template <> void InstX8632Cbwdq::emit(const Cfg *Func) const {
Ostream &Str = Func->getContext()->getStrEmit();
assert(getSrcSize() == 1);
@@ -1275,6 +1345,17 @@ void InstX8632Shld::emit(const Cfg *Func) const {
Str << "\n";
}
+void InstX8632Shld::emitIAS(const Cfg *Func) const {
+ assert(getSrcSize() == 3);
+ assert(getDest() == getSrc(0));
+ const Variable *Dest = getDest();
+ const Operand *Src1 = getSrc(1);
+ const Operand *Src2 = getSrc(2);
+ static const x86::AssemblerX86::GPREmitterShiftD Emitter = {
+ &x86::AssemblerX86::shld, &x86::AssemblerX86::shld};
+ emitIASGPRShiftDouble(Func, Dest, Src1, Src2, Emitter);
+}
+
void InstX8632Shld::dump(const Cfg *Func) const {
Ostream &Str = Func->getContext()->getStrDump();
dumpDest(Func);
@@ -1301,6 +1382,17 @@ void InstX8632Shrd::emit(const Cfg *Func) const {
Str << "\n";
}
+void InstX8632Shrd::emitIAS(const Cfg *Func) const {
+ assert(getSrcSize() == 3);
+ assert(getDest() == getSrc(0));
+ const Variable *Dest = getDest();
+ const Operand *Src1 = getSrc(1);
+ const Operand *Src2 = getSrc(2);
+ static const x86::AssemblerX86::GPREmitterShiftD Emitter = {
+ &x86::AssemblerX86::shrd, &x86::AssemblerX86::shrd};
+ emitIASGPRShiftDouble(Func, Dest, Src1, Src2, Emitter);
+}
+
void InstX8632Shrd::dump(const Cfg *Func) const {
Ostream &Str = Func->getContext()->getStrDump();
dumpDest(Func);
@@ -2240,8 +2332,10 @@ template <> void InstX8632Pextr::emit(const Cfg *Func) const {
Str << "\t" << Opcode
<< TypeX8632Attributes[getSrc(0)->getType()].PackString << "\t";
Variable *Dest = getDest();
- // pextrw must take a register dest.
- assert(Dest->getType() != IceType_i16 || Dest->hasReg());
+ // pextrw must take a register dest. There is an SSE4.1 version that takes
+ // a memory dest, but we aren't using it. For uniformity, just restrict
+ // them all to have a register dest for now.
Jim Stichnoth 2014/10/15 02:09:27 Just wondering if you've thought about what happen
jvoung (off chromium) 2014/10/15 16:23:43 I think we would have to impose some legalizations
Jim Stichnoth 2014/10/15 16:45:59 After writing my comment, I convinced myself that
+ assert(Dest->hasReg());
Dest->asType(IceType_i32).emit(Func);
Str << ", ";
getSrc(0)->emit(Func);
@@ -2250,6 +2344,28 @@ template <> void InstX8632Pextr::emit(const Cfg *Func) const {
Str << "\n";
}
+template <> void InstX8632Pextr::emitIAS(const Cfg *Func) const {
+ assert(getSrcSize() == 2);
+ // pextrb and pextrd are SSE4.1 instructions.
+ const Variable *Dest = getDest();
+ Type DispatchTy = Dest->getType();
+ assert(DispatchTy == IceType_i16 ||
+ static_cast<TargetX8632 *>(Func->getTarget())->getInstructionSet() >=
+ TargetX8632::SSE4_1);
+ // pextrw must take a register dest. There is an SSE4.1 version that takes
+ // a memory dest, but we aren't using it. For uniformity, just restrict
+ // them all to have a register dest for now.
+ assert(Dest->hasReg());
+ // pextrw's Src(0) must be a register (both SSE4.1 and SSE2).
+ assert(llvm::cast<Variable>(getSrc(0))->hasReg());
+ static const x86::AssemblerX86::ThreeOpImmEmitter<
+ RegX8632::GPRRegister, RegX8632::XmmRegister> Emitter = {
+ &x86::AssemblerX86::pextr, NULL};
+ emitIASThreeOpImmOps<RegX8632::GPRRegister, RegX8632::XmmRegister,
+ RegX8632::getEncodedGPR, RegX8632::getEncodedXmm>(
+ Func, DispatchTy, Dest, getSrc(0), getSrc(1), Emitter);
+}
+
template <> void InstX8632Pinsr::emit(const Cfg *Func) const {
Ostream &Str = Func->getContext()->getStrEmit();
assert(getSrcSize() == 3);
@@ -2278,6 +2394,52 @@ template <> void InstX8632Pinsr::emit(const Cfg *Func) const {
Str << "\n";
}
+template <> void InstX8632Pinsr::emitIAS(const Cfg *Func) const {
+ assert(getSrcSize() == 3);
+ assert(getDest() == getSrc(0));
+ // pinsrb and pinsrd are SSE4.1 instructions.
+ const Operand *Src0 = getSrc(1);
+ Type DispatchTy = Src0->getType();
+ assert(DispatchTy == IceType_i16 ||
+ static_cast<TargetX8632 *>(Func->getTarget())->getInstructionSet() >=
+ TargetX8632::SSE4_1);
+ // If src1 is a register, it should always be r32 (this should fall out
+ // from the encodings for ByteRegs overlapping the encodings for r32),
+ // but we have to trust the regalloc to not choose "ah", where it
+ // doesn't overlap.
+ static const x86::AssemblerX86::ThreeOpImmEmitter<
+ RegX8632::XmmRegister, RegX8632::GPRRegister> Emitter = {
+ &x86::AssemblerX86::pinsr, &x86::AssemblerX86::pinsr};
+ emitIASThreeOpImmOps<RegX8632::XmmRegister, RegX8632::GPRRegister,
+ RegX8632::getEncodedXmm, RegX8632::getEncodedGPR>(
+ Func, DispatchTy, getDest(), Src0, getSrc(2), Emitter);
+}
+
+template <> void InstX8632Pshufd::emitIAS(const Cfg *Func) const {
+ assert(getSrcSize() == 2);
+ const Variable *Dest = getDest();
+ Type Ty = Dest->getType();
+ static const x86::AssemblerX86::ThreeOpImmEmitter<
+ RegX8632::XmmRegister, RegX8632::XmmRegister> Emitter = {
+ &x86::AssemblerX86::pshufd, &x86::AssemblerX86::pshufd};
+ emitIASThreeOpImmOps<RegX8632::XmmRegister, RegX8632::XmmRegister,
+ RegX8632::getEncodedXmm, RegX8632::getEncodedXmm>(
+ Func, Ty, Dest, getSrc(0), getSrc(1), Emitter);
+}
+
+template <> void InstX8632Shufps::emitIAS(const Cfg *Func) const {
+ assert(getSrcSize() == 3);
+ const Variable *Dest = getDest();
+ assert(Dest == getSrc(0));
+ Type Ty = Dest->getType();
+ static const x86::AssemblerX86::ThreeOpImmEmitter<
+ RegX8632::XmmRegister, RegX8632::XmmRegister> Emitter = {
+ &x86::AssemblerX86::shufps, &x86::AssemblerX86::shufps};
+ emitIASThreeOpImmOps<RegX8632::XmmRegister, RegX8632::XmmRegister,
+ RegX8632::getEncodedXmm, RegX8632::getEncodedXmm>(
+ Func, Ty, Dest, getSrc(1), getSrc(2), Emitter);
+}
+
void InstX8632Pop::emit(const Cfg *Func) const {
Ostream &Str = Func->getContext()->getStrEmit();
assert(getSrcSize() == 0);
« no previous file with comments | « src/IceInstX8632.h ('k') | src/assembler_ia32.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698