Chromium Code Reviews| 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); |