1 //===- subzero/src/IceInstX86BaseImpl.h - Generic X86 instructions -*- C++ -*=//
3 // The Subzero Code Generator
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
11 /// This file implements the InstX86Base class and its descendants.
13 //===----------------------------------------------------------------------===//
15 #ifndef SUBZERO_SRC_ICEINSTX86BASEIMPL_H
16 #define SUBZERO_SRC_ICEINSTX86BASEIMPL_H
18 #include "IceInstX86Base.h"
20 #include "IceAssemblerX86Base.h"
22 #include "IceCfgNode.h"
25 #include "IceOperand.h"
26 #include "IceTargetLowering.h"
30 namespace X86Internal {
32 template <class Machine>
33 const char *InstX86Base<Machine>::getWidthString(Type Ty) {
34 return Traits::TypeAttributes[Ty].WidthString;
37 template <class Machine>
38 const char *InstX86Base<Machine>::getFldString(Type Ty) {
39 return Traits::TypeAttributes[Ty].FldString;
42 template <class Machine>
43 typename InstX86Base<Machine>::Traits::Cond::BrCond
44 InstX86Base<Machine>::getOppositeCondition(typename Traits::Cond::BrCond Cond) {
45 return Traits::InstBrAttributes[Cond].Opposite;
48 template <class Machine>
49 InstX86FakeRMW<Machine>::InstX86FakeRMW(Cfg *Func, Operand *Data, Operand *Addr,
50 InstArithmetic::OpKind Op,
52 : InstX86Base<Machine>(Func, InstX86Base<Machine>::FakeRMW, 3, nullptr),
54 this->addSource(Data);
55 this->addSource(Addr);
56 this->addSource(Beacon);
59 template <class Machine>
60 InstX86AdjustStack<Machine>::InstX86AdjustStack(Cfg *Func, SizeT Amount,
62 : InstX86Base<Machine>(Func, InstX86Base<Machine>::Adjuststack, 1, Esp),
67 template <class Machine>
68 InstX86Mul<Machine>::InstX86Mul(Cfg *Func, Variable *Dest, Variable *Source1,
70 : InstX86Base<Machine>(Func, InstX86Base<Machine>::Mul, 2, Dest) {
71 this->addSource(Source1);
72 this->addSource(Source2);
75 template <class Machine>
76 InstX86Shld<Machine>::InstX86Shld(Cfg *Func, Variable *Dest, Variable *Source1,
78 : InstX86Base<Machine>(Func, InstX86Base<Machine>::Shld, 3, Dest) {
79 this->addSource(Dest);
80 this->addSource(Source1);
81 this->addSource(Source2);
84 template <class Machine>
85 InstX86Shrd<Machine>::InstX86Shrd(Cfg *Func, Variable *Dest, Variable *Source1,
87 : InstX86Base<Machine>(Func, InstX86Base<Machine>::Shrd, 3, Dest) {
88 this->addSource(Dest);
89 this->addSource(Source1);
90 this->addSource(Source2);
93 template <class Machine>
94 InstX86Label<Machine>::InstX86Label(
95 Cfg *Func, typename InstX86Base<Machine>::Traits::TargetLowering *Target)
96 : InstX86Base<Machine>(Func, InstX86Base<Machine>::Label, 0, nullptr),
97 Number(Target->makeNextLabelNumber()) {}
99 template <class Machine>
100 IceString InstX86Label<Machine>::getName(const Cfg *Func) const {
101 return ".L" + Func->getFunctionName() + "$local$__" + std::to_string(Number);
104 template <class Machine>
105 InstX86Br<Machine>::InstX86Br(
106 Cfg *Func, const CfgNode *TargetTrue, const CfgNode *TargetFalse,
107 const InstX86Label<Machine> *Label,
108 typename InstX86Base<Machine>::Traits::Cond::BrCond Condition, Mode Kind)
109 : InstX86Base<Machine>(Func, InstX86Base<Machine>::Br, 0, nullptr),
110 Condition(Condition), TargetTrue(TargetTrue), TargetFalse(TargetFalse),
111 Label(Label), Kind(Kind) {}
113 template <class Machine>
114 bool InstX86Br<Machine>::optimizeBranch(const CfgNode *NextNode) {
115 // If there is no next block, then there can be no fallthrough to
117 if (NextNode == nullptr)
119 // Intra-block conditional branches can't be optimized.
122 // If there is no fallthrough node, such as a non-default case label
123 // for a switch instruction, then there is no opportunity to
125 if (getTargetFalse() == nullptr)
128 // Unconditional branch to the next node can be removed.
129 if (Condition == InstX86Base<Machine>::Traits::Cond::Br_None &&
130 getTargetFalse() == NextNode) {
131 assert(getTargetTrue() == nullptr);
135 // If the fallthrough is to the next node, set fallthrough to nullptr
137 if (getTargetFalse() == NextNode) {
138 TargetFalse = nullptr;
141 // If TargetTrue is the next node, and TargetFalse is not nullptr
142 // (which was already tested above), then invert the branch
143 // condition, swap the targets, and set new fallthrough to nullptr.
144 if (getTargetTrue() == NextNode) {
145 assert(Condition != InstX86Base<Machine>::Traits::Cond::Br_None);
146 Condition = this->getOppositeCondition(Condition);
147 TargetTrue = getTargetFalse();
148 TargetFalse = nullptr;
154 template <class Machine>
155 bool InstX86Br<Machine>::repointEdges(CfgNode *OldNode, CfgNode *NewNode) {
157 if (TargetFalse == OldNode) {
158 TargetFalse = NewNode;
161 if (TargetTrue == OldNode) {
162 TargetTrue = NewNode;
168 template <class Machine>
169 InstX86Jmp<Machine>::InstX86Jmp(Cfg *Func, Operand *Target)
170 : InstX86Base<Machine>(Func, InstX86Base<Machine>::Jmp, 1, nullptr) {
171 this->addSource(Target);
174 template <class Machine>
175 InstX86Call<Machine>::InstX86Call(Cfg *Func, Variable *Dest,
177 : InstX86Base<Machine>(Func, InstX86Base<Machine>::Call, 1, Dest) {
178 this->HasSideEffects = true;
179 this->addSource(CallTarget);
182 template <class Machine>
183 InstX86Cmov<Machine>::InstX86Cmov(
184 Cfg *Func, Variable *Dest, Operand *Source,
185 typename InstX86Base<Machine>::Traits::Cond::BrCond Condition)
186 : InstX86Base<Machine>(Func, InstX86Base<Machine>::Cmov, 2, Dest),
187 Condition(Condition) {
188 // The final result is either the original Dest, or Source, so mark
190 this->addSource(Dest);
191 this->addSource(Source);
194 template <class Machine>
195 InstX86Cmpps<Machine>::InstX86Cmpps(
196 Cfg *Func, Variable *Dest, Operand *Source,
197 typename InstX86Base<Machine>::Traits::Cond::CmppsCond Condition)
198 : InstX86Base<Machine>(Func, InstX86Base<Machine>::Cmpps, 2, Dest),
199 Condition(Condition) {
200 this->addSource(Dest);
201 this->addSource(Source);
204 template <class Machine>
205 InstX86Cmpxchg<Machine>::InstX86Cmpxchg(Cfg *Func, Operand *DestOrAddr,
206 Variable *Eax, Variable *Desired,
208 : InstX86BaseLockable<Machine>(Func, InstX86Base<Machine>::Cmpxchg, 3,
209 llvm::dyn_cast<Variable>(DestOrAddr),
211 assert(Eax->getRegNum() ==
212 InstX86Base<Machine>::Traits::RegisterSet::Reg_eax);
213 this->addSource(DestOrAddr);
214 this->addSource(Eax);
215 this->addSource(Desired);
218 template <class Machine>
219 InstX86Cmpxchg8b<Machine>::InstX86Cmpxchg8b(
220 Cfg *Func, typename InstX86Base<Machine>::Traits::X86OperandMem *Addr,
221 Variable *Edx, Variable *Eax, Variable *Ecx, Variable *Ebx, bool Locked)
222 : InstX86BaseLockable<Machine>(Func, InstX86Base<Machine>::Cmpxchg, 5,
224 assert(Edx->getRegNum() ==
225 InstX86Base<Machine>::Traits::RegisterSet::Reg_edx);
226 assert(Eax->getRegNum() ==
227 InstX86Base<Machine>::Traits::RegisterSet::Reg_eax);
228 assert(Ecx->getRegNum() ==
229 InstX86Base<Machine>::Traits::RegisterSet::Reg_ecx);
230 assert(Ebx->getRegNum() ==
231 InstX86Base<Machine>::Traits::RegisterSet::Reg_ebx);
232 this->addSource(Addr);
233 this->addSource(Edx);
234 this->addSource(Eax);
235 this->addSource(Ecx);
236 this->addSource(Ebx);
239 template <class Machine>
240 InstX86Cvt<Machine>::InstX86Cvt(Cfg *Func, Variable *Dest, Operand *Source,
242 : InstX86Base<Machine>(Func, InstX86Base<Machine>::Cvt, 1, Dest),
244 this->addSource(Source);
247 template <class Machine>
248 InstX86Icmp<Machine>::InstX86Icmp(Cfg *Func, Operand *Src0, Operand *Src1)
249 : InstX86Base<Machine>(Func, InstX86Base<Machine>::Icmp, 2, nullptr) {
250 this->addSource(Src0);
251 this->addSource(Src1);
254 template <class Machine>
255 InstX86Ucomiss<Machine>::InstX86Ucomiss(Cfg *Func, Operand *Src0, Operand *Src1)
256 : InstX86Base<Machine>(Func, InstX86Base<Machine>::Ucomiss, 2, nullptr) {
257 this->addSource(Src0);
258 this->addSource(Src1);
261 template <class Machine>
262 InstX86UD2<Machine>::InstX86UD2(Cfg *Func)
263 : InstX86Base<Machine>(Func, InstX86Base<Machine>::UD2, 0, nullptr) {}
265 template <class Machine>
266 InstX86Test<Machine>::InstX86Test(Cfg *Func, Operand *Src1, Operand *Src2)
267 : InstX86Base<Machine>(Func, InstX86Base<Machine>::Test, 2, nullptr) {
268 this->addSource(Src1);
269 this->addSource(Src2);
272 template <class Machine>
273 InstX86Mfence<Machine>::InstX86Mfence(Cfg *Func)
274 : InstX86Base<Machine>(Func, InstX86Base<Machine>::Mfence, 0, nullptr) {
275 this->HasSideEffects = true;
278 template <class Machine>
279 InstX86Store<Machine>::InstX86Store(
280 Cfg *Func, Operand *Value,
281 typename InstX86Base<Machine>::Traits::X86Operand *Mem)
282 : InstX86Base<Machine>(Func, InstX86Base<Machine>::Store, 2, nullptr) {
283 this->addSource(Value);
284 this->addSource(Mem);
287 template <class Machine>
288 InstX86StoreP<Machine>::InstX86StoreP(
289 Cfg *Func, Variable *Value,
290 typename InstX86Base<Machine>::Traits::X86OperandMem *Mem)
291 : InstX86Base<Machine>(Func, InstX86Base<Machine>::StoreP, 2, nullptr) {
292 this->addSource(Value);
293 this->addSource(Mem);
296 template <class Machine>
297 InstX86StoreQ<Machine>::InstX86StoreQ(
298 Cfg *Func, Variable *Value,
299 typename InstX86Base<Machine>::Traits::X86OperandMem *Mem)
300 : InstX86Base<Machine>(Func, InstX86Base<Machine>::StoreQ, 2, nullptr) {
301 this->addSource(Value);
302 this->addSource(Mem);
305 template <class Machine>
306 InstX86Nop<Machine>::InstX86Nop(Cfg *Func, InstX86Nop::NopVariant Variant)
307 : InstX86Base<Machine>(Func, InstX86Base<Machine>::Nop, 0, nullptr),
310 template <class Machine>
311 InstX86Fld<Machine>::InstX86Fld(Cfg *Func, Operand *Src)
312 : InstX86Base<Machine>(Func, InstX86Base<Machine>::Fld, 1, nullptr) {
313 this->addSource(Src);
316 template <class Machine>
317 InstX86Fstp<Machine>::InstX86Fstp(Cfg *Func, Variable *Dest)
318 : InstX86Base<Machine>(Func, InstX86Base<Machine>::Fstp, 0, Dest) {}
320 template <class Machine>
321 InstX86Pop<Machine>::InstX86Pop(Cfg *Func, Variable *Dest)
322 : InstX86Base<Machine>(Func, InstX86Base<Machine>::Pop, 0, Dest) {
323 // A pop instruction affects the stack pointer and so it should not
324 // be allowed to be automatically dead-code eliminated. (The
325 // corresponding push instruction doesn't need this treatment
326 // because it has no dest variable and therefore won't be dead-code
327 // eliminated.) This is needed for late-stage liveness analysis
328 // (e.g. asm-verbose mode).
329 this->HasSideEffects = true;
332 template <class Machine>
333 InstX86Push<Machine>::InstX86Push(Cfg *Func, Variable *Source)
334 : InstX86Base<Machine>(Func, InstX86Base<Machine>::Push, 1, nullptr) {
335 this->addSource(Source);
338 template <class Machine>
339 InstX86Ret<Machine>::InstX86Ret(Cfg *Func, Variable *Source)
340 : InstX86Base<Machine>(Func, InstX86Base<Machine>::Ret, Source ? 1 : 0,
343 this->addSource(Source);
346 template <class Machine>
347 InstX86Setcc<Machine>::InstX86Setcc(
348 Cfg *Func, Variable *Dest,
349 typename InstX86Base<Machine>::Traits::Cond::BrCond Cond)
350 : InstX86Base<Machine>(Func, InstX86Base<Machine>::Setcc, 0, Dest),
353 template <class Machine>
354 InstX86Xadd<Machine>::InstX86Xadd(Cfg *Func, Operand *Dest, Variable *Source,
356 : InstX86BaseLockable<Machine>(Func, InstX86Base<Machine>::Xadd, 2,
357 llvm::dyn_cast<Variable>(Dest), Locked) {
358 this->addSource(Dest);
359 this->addSource(Source);
362 template <class Machine>
363 InstX86Xchg<Machine>::InstX86Xchg(Cfg *Func, Operand *Dest, Variable *Source)
364 : InstX86Base<Machine>(Func, InstX86Base<Machine>::Xchg, 2,
365 llvm::dyn_cast<Variable>(Dest)) {
366 this->addSource(Dest);
367 this->addSource(Source);
370 // ======================== Dump routines ======================== //
372 template <class Machine>
373 void InstX86Base<Machine>::dump(const Cfg *Func) const {
374 if (!BuildDefs::dump())
376 Ostream &Str = Func->getContext()->getStrDump();
377 Str << "[" << Traits::TargetName << "] ";
381 template <class Machine>
382 void InstX86FakeRMW<Machine>::dump(const Cfg *Func) const {
383 if (!BuildDefs::dump())
385 Ostream &Str = Func->getContext()->getStrDump();
386 Type Ty = getData()->getType();
387 Str << "rmw " << InstArithmetic::getOpName(getOp()) << " " << Ty << " *";
388 getAddr()->dump(Func);
390 getData()->dump(Func);
392 getBeacon()->dump(Func);
395 template <class Machine>
396 void InstX86Label<Machine>::emit(const Cfg *Func) const {
397 if (!BuildDefs::dump())
399 Ostream &Str = Func->getContext()->getStrEmit();
400 Str << getName(Func) << ":";
403 template <class Machine>
404 void InstX86Label<Machine>::emitIAS(const Cfg *Func) const {
405 typename InstX86Base<Machine>::Traits::Assembler *Asm =
406 Func->getAssembler<typename InstX86Base<Machine>::Traits::Assembler>();
407 Asm->bindLocalLabel(Number);
410 template <class Machine>
411 void InstX86Label<Machine>::dump(const Cfg *Func) const {
412 if (!BuildDefs::dump())
414 Ostream &Str = Func->getContext()->getStrDump();
415 Str << getName(Func) << ":";
418 template <class Machine> void InstX86Br<Machine>::emit(const Cfg *Func) const {
419 if (!BuildDefs::dump())
421 Ostream &Str = Func->getContext()->getStrEmit();
424 if (Condition == InstX86Base<Machine>::Traits::Cond::Br_None) {
427 Str << InstX86Base<Machine>::Traits::InstBrAttributes[Condition].EmitString;
431 Str << "\t" << Label->getName(Func);
433 if (Condition == InstX86Base<Machine>::Traits::Cond::Br_None) {
434 Str << "\t" << getTargetFalse()->getAsmName();
436 Str << "\t" << getTargetTrue()->getAsmName();
437 if (getTargetFalse()) {
438 Str << "\n\tjmp\t" << getTargetFalse()->getAsmName();
444 template <class Machine>
445 void InstX86Br<Machine>::emitIAS(const Cfg *Func) const {
446 typename InstX86Base<Machine>::Traits::Assembler *Asm =
447 Func->getAssembler<typename InstX86Base<Machine>::Traits::Assembler>();
449 class Label *L = Asm->getOrCreateLocalLabel(Label->getNumber());
450 if (Condition == InstX86Base<Machine>::Traits::Cond::Br_None) {
451 Asm->jmp(L, isNear());
453 Asm->j(Condition, L, isNear());
456 if (Condition == InstX86Base<Machine>::Traits::Cond::Br_None) {
458 Asm->getOrCreateCfgNodeLabel(getTargetFalse()->getIndex());
459 assert(!getTargetTrue());
460 Asm->jmp(L, isNear());
463 Asm->getOrCreateCfgNodeLabel(getTargetTrue()->getIndex());
464 Asm->j(Condition, L, isNear());
465 if (getTargetFalse()) {
467 Asm->getOrCreateCfgNodeLabel(getTargetFalse()->getIndex());
468 Asm->jmp(L2, isNear());
474 template <class Machine> void InstX86Br<Machine>::dump(const Cfg *Func) const {
475 if (!BuildDefs::dump())
477 Ostream &Str = Func->getContext()->getStrDump();
480 if (Condition == InstX86Base<Machine>::Traits::Cond::Br_None) {
482 << (Label ? Label->getName(Func) : getTargetFalse()->getName());
486 Str << InstX86Base<Machine>::Traits::InstBrAttributes[Condition]
489 Str << ", label %" << Label->getName(Func);
491 Str << ", label %" << getTargetTrue()->getName();
492 if (getTargetFalse()) {
493 Str << ", label %" << getTargetFalse()->getName();
497 Str << " // (" << (isNear() ? "near" : "far") << " jump)";
500 template <class Machine> void InstX86Jmp<Machine>::emit(const Cfg *Func) const {
501 if (!BuildDefs::dump())
503 Ostream &Str = Func->getContext()->getStrEmit();
504 assert(this->getSrcSize() == 1);
506 getJmpTarget()->emit(Func);
509 template <class Machine>
510 void InstX86Jmp<Machine>::emitIAS(const Cfg *Func) const {
511 // Note: Adapted (mostly copied) from InstX86Call<Machine>::emitIAS().
512 typename InstX86Base<Machine>::Traits::Assembler *Asm =
513 Func->getAssembler<typename InstX86Base<Machine>::Traits::Assembler>();
514 Operand *Target = getJmpTarget();
515 if (const auto Var = llvm::dyn_cast<Variable>(Target)) {
517 Asm->jmp(InstX86Base<Machine>::Traits::RegisterSet::getEncodedGPR(
520 // The jmp instruction with a memory operand should be possible
521 // to encode, but it isn't a valid sandboxed instruction, and
522 // there shouldn't be a register allocation issue to jump
523 // through a scratch register, so we don't really need to bother
525 llvm::report_fatal_error("Assembler can't jmp to memory operand");
527 } else if (const auto Mem = llvm::dyn_cast<
528 typename InstX86Base<Machine>::Traits::X86OperandMem>(
531 assert(Mem->getSegmentRegister() ==
532 InstX86Base<Machine>::Traits::X86OperandMem::DefaultSegment);
533 llvm::report_fatal_error("Assembler can't jmp to memory operand");
534 } else if (const auto CR = llvm::dyn_cast<ConstantRelocatable>(Target)) {
535 assert(CR->getOffset() == 0 && "We only support jumping to a function");
537 } else if (const auto Imm = llvm::dyn_cast<ConstantInteger32>(Target)) {
538 // NaCl trampoline calls refer to an address within the sandbox directly.
539 // This is usually only needed for non-IRT builds and otherwise not
540 // very portable or stable. Usually this is only done for "calls"
542 // TODO(jvoung): Support this when there is a lowering that
543 // actually triggers this case.
545 llvm::report_fatal_error("Unexpected jmp to absolute address");
547 llvm::report_fatal_error("Unexpected operand type");
551 template <class Machine> void InstX86Jmp<Machine>::dump(const Cfg *Func) const {
552 if (!BuildDefs::dump())
554 Ostream &Str = Func->getContext()->getStrDump();
556 getJmpTarget()->dump(Func);
559 template <class Machine>
560 void InstX86Call<Machine>::emit(const Cfg *Func) const {
561 if (!BuildDefs::dump())
563 Ostream &Str = Func->getContext()->getStrEmit();
564 assert(this->getSrcSize() == 1);
566 if (const auto CI = llvm::dyn_cast<ConstantInteger32>(getCallTarget())) {
567 // Emit without a leading '$'.
568 Str << CI->getValue();
569 } else if (const auto CallTarget =
570 llvm::dyn_cast<ConstantRelocatable>(getCallTarget())) {
571 CallTarget->emitWithoutPrefix(Func->getTarget());
574 getCallTarget()->emit(Func);
576 Func->getTarget()->resetStackAdjustment();
579 template <class Machine>
580 void InstX86Call<Machine>::emitIAS(const Cfg *Func) const {
581 typename InstX86Base<Machine>::Traits::Assembler *Asm =
582 Func->getAssembler<typename InstX86Base<Machine>::Traits::Assembler>();
583 Operand *Target = getCallTarget();
584 if (const auto Var = llvm::dyn_cast<Variable>(Target)) {
586 Asm->call(InstX86Base<Machine>::Traits::RegisterSet::getEncodedGPR(
590 static_cast<typename InstX86Base<Machine>::Traits::TargetLowering *>(
592 ->stackVarToAsmOperand(Var));
594 } else if (const auto Mem = llvm::dyn_cast<
595 typename InstX86Base<Machine>::Traits::X86OperandMem>(
597 assert(Mem->getSegmentRegister() ==
598 InstX86Base<Machine>::Traits::X86OperandMem::DefaultSegment);
599 Asm->call(Mem->toAsmAddress(Asm));
600 } else if (const auto CR = llvm::dyn_cast<ConstantRelocatable>(Target)) {
601 assert(CR->getOffset() == 0 && "We only support calling a function");
603 } else if (const auto Imm = llvm::dyn_cast<ConstantInteger32>(Target)) {
604 Asm->call(Immediate(Imm->getValue()));
606 llvm_unreachable("Unexpected operand type");
608 Func->getTarget()->resetStackAdjustment();
611 template <class Machine>
612 void InstX86Call<Machine>::dump(const Cfg *Func) const {
613 if (!BuildDefs::dump())
615 Ostream &Str = Func->getContext()->getStrDump();
616 if (this->getDest()) {
617 this->dumpDest(Func);
621 getCallTarget()->dump(Func);
624 // The ShiftHack parameter is used to emit "cl" instead of "ecx" for
625 // shift instructions, in order to be syntactically valid. The
626 // this->Opcode parameter needs to be char* and not IceString because of
628 template <class Machine>
629 void InstX86Base<Machine>::emitTwoAddress(const char *Opcode, const Inst *Inst,
630 const Cfg *Func, bool ShiftHack) {
631 if (!BuildDefs::dump())
633 Ostream &Str = Func->getContext()->getStrEmit();
634 assert(Inst->getSrcSize() == 2);
635 Operand *Dest = Inst->getDest();
637 Dest = Inst->getSrc(0);
638 assert(Dest == Inst->getSrc(0));
639 Operand *Src1 = Inst->getSrc(1);
640 Str << "\t" << Opcode << InstX86Base<Machine>::getWidthString(Dest->getType())
642 const auto ShiftReg = llvm::dyn_cast<Variable>(Src1);
643 if (ShiftHack && ShiftReg &&
644 ShiftReg->getRegNum() ==
645 InstX86Base<Machine>::Traits::RegisterSet::Reg_ecx)
653 template <class Machine>
654 void emitIASOpTyGPR(const Cfg *Func, Type Ty, const Operand *Op,
655 const typename InstX86Base<
656 Machine>::Traits::Assembler::GPREmitterOneOp &Emitter) {
657 typename InstX86Base<Machine>::Traits::Assembler *Asm =
658 Func->getAssembler<typename InstX86Base<Machine>::Traits::Assembler>();
659 if (const auto Var = llvm::dyn_cast<Variable>(Op)) {
661 // We cheat a little and use GPRRegister even for byte operations.
662 typename InstX86Base<Machine>::Traits::RegisterSet::GPRRegister VarReg =
663 InstX86Base<Machine>::Traits::RegisterSet::getEncodedByteRegOrGPR(
664 Ty, Var->getRegNum());
665 (Asm->*(Emitter.Reg))(Ty, VarReg);
667 typename InstX86Base<Machine>::Traits::Address StackAddr(
668 static_cast<typename InstX86Base<Machine>::Traits::TargetLowering *>(
670 ->stackVarToAsmOperand(Var));
671 (Asm->*(Emitter.Addr))(Ty, StackAddr);
673 } else if (const auto Mem = llvm::dyn_cast<
674 typename InstX86Base<Machine>::Traits::X86OperandMem>(Op)) {
675 Mem->emitSegmentOverride(Asm);
676 (Asm->*(Emitter.Addr))(Ty, Mem->toAsmAddress(Asm));
678 llvm_unreachable("Unexpected operand type");
682 template <class Machine, bool VarCanBeByte, bool SrcCanBeByte>
683 void emitIASRegOpTyGPR(
684 const Cfg *Func, Type Ty, const Variable *Var, const Operand *Src,
685 const typename InstX86Base<Machine>::Traits::Assembler::GPREmitterRegOp
687 typename InstX86Base<Machine>::Traits::Assembler *Asm =
688 Func->getAssembler<typename InstX86Base<Machine>::Traits::Assembler>();
689 assert(Var->hasReg());
690 // We cheat a little and use GPRRegister even for byte operations.
691 typename InstX86Base<Machine>::Traits::RegisterSet::GPRRegister VarReg =
693 ? InstX86Base<Machine>::Traits::RegisterSet::getEncodedByteRegOrGPR(
694 Ty, Var->getRegNum())
695 : InstX86Base<Machine>::Traits::RegisterSet::getEncodedGPR(
697 if (const auto SrcVar = llvm::dyn_cast<Variable>(Src)) {
698 if (SrcVar->hasReg()) {
699 typename InstX86Base<Machine>::Traits::RegisterSet::GPRRegister SrcReg =
701 ? InstX86Base<Machine>::Traits::RegisterSet::
702 getEncodedByteRegOrGPR(Ty, SrcVar->getRegNum())
703 : InstX86Base<Machine>::Traits::RegisterSet::getEncodedGPR(
704 SrcVar->getRegNum());
705 (Asm->*(Emitter.GPRGPR))(Ty, VarReg, SrcReg);
707 typename InstX86Base<Machine>::Traits::Address SrcStackAddr =
708 static_cast<typename InstX86Base<Machine>::Traits::TargetLowering *>(
710 ->stackVarToAsmOperand(SrcVar);
711 (Asm->*(Emitter.GPRAddr))(Ty, VarReg, SrcStackAddr);
713 } else if (const auto Mem = llvm::dyn_cast<
714 typename InstX86Base<Machine>::Traits::X86OperandMem>(Src)) {
715 Mem->emitSegmentOverride(Asm);
716 (Asm->*(Emitter.GPRAddr))(Ty, VarReg, Mem->toAsmAddress(Asm));
717 } else if (const auto Imm = llvm::dyn_cast<ConstantInteger32>(Src)) {
718 (Asm->*(Emitter.GPRImm))(Ty, VarReg, Immediate(Imm->getValue()));
719 } else if (const auto Reloc = llvm::dyn_cast<ConstantRelocatable>(Src)) {
720 AssemblerFixup *Fixup = Asm->createFixup(llvm::ELF::R_386_32, Reloc);
721 (Asm->*(Emitter.GPRImm))(Ty, VarReg, Immediate(Reloc->getOffset(), Fixup));
722 } else if (const auto Split = llvm::dyn_cast<
723 typename InstX86Base<Machine>::Traits::VariableSplit>(Src)) {
724 (Asm->*(Emitter.GPRAddr))(Ty, VarReg, Split->toAsmAddress(Func));
726 llvm_unreachable("Unexpected operand type");
730 template <class Machine>
731 void emitIASAddrOpTyGPR(
732 const Cfg *Func, Type Ty,
733 const typename InstX86Base<Machine>::Traits::Address &Addr,
735 const typename InstX86Base<Machine>::Traits::Assembler::GPREmitterAddrOp
737 typename InstX86Base<Machine>::Traits::Assembler *Asm =
738 Func->getAssembler<typename InstX86Base<Machine>::Traits::Assembler>();
739 // Src can only be Reg or Immediate.
740 if (const auto SrcVar = llvm::dyn_cast<Variable>(Src)) {
741 assert(SrcVar->hasReg());
742 typename InstX86Base<Machine>::Traits::RegisterSet::GPRRegister SrcReg =
743 InstX86Base<Machine>::Traits::RegisterSet::getEncodedByteRegOrGPR(
744 Ty, SrcVar->getRegNum());
745 (Asm->*(Emitter.AddrGPR))(Ty, Addr, SrcReg);
746 } else if (const auto Imm = llvm::dyn_cast<ConstantInteger32>(Src)) {
747 (Asm->*(Emitter.AddrImm))(Ty, Addr, Immediate(Imm->getValue()));
748 } else if (const auto Reloc = llvm::dyn_cast<ConstantRelocatable>(Src)) {
749 AssemblerFixup *Fixup = Asm->createFixup(llvm::ELF::R_386_32, Reloc);
750 (Asm->*(Emitter.AddrImm))(Ty, Addr, Immediate(Reloc->getOffset(), Fixup));
752 llvm_unreachable("Unexpected operand type");
756 template <class Machine>
757 void emitIASAsAddrOpTyGPR(
758 const Cfg *Func, Type Ty, const Operand *Op0, const Operand *Op1,
759 const typename InstX86Base<Machine>::Traits::Assembler::GPREmitterAddrOp
761 if (const auto Op0Var = llvm::dyn_cast<Variable>(Op0)) {
762 assert(!Op0Var->hasReg());
763 typename InstX86Base<Machine>::Traits::Address StackAddr(
764 static_cast<typename InstX86Base<Machine>::Traits::TargetLowering *>(
766 ->stackVarToAsmOperand(Op0Var));
767 emitIASAddrOpTyGPR<Machine>(Func, Ty, StackAddr, Op1, Emitter);
768 } else if (const auto Op0Mem = llvm::dyn_cast<
769 typename InstX86Base<Machine>::Traits::X86OperandMem>(Op0)) {
770 typename InstX86Base<Machine>::Traits::Assembler *Asm =
771 Func->getAssembler<typename InstX86Base<Machine>::Traits::Assembler>();
772 Op0Mem->emitSegmentOverride(Asm);
773 emitIASAddrOpTyGPR<Machine>(Func, Ty, Op0Mem->toAsmAddress(Asm), Op1,
775 } else if (const auto Split = llvm::dyn_cast<
776 typename InstX86Base<Machine>::Traits::VariableSplit>(Op0)) {
777 emitIASAddrOpTyGPR<Machine>(Func, Ty, Split->toAsmAddress(Func), Op1,
780 llvm_unreachable("Unexpected operand type");
784 template <class Machine>
785 void InstX86Base<Machine>::emitIASGPRShift(
786 const Cfg *Func, Type Ty, const Variable *Var, const Operand *Src,
787 const typename InstX86Base<Machine>::Traits::Assembler::GPREmitterShiftOp
789 typename InstX86Base<Machine>::Traits::Assembler *Asm =
790 Func->getAssembler<typename InstX86Base<Machine>::Traits::Assembler>();
791 // Technically, the Dest Var can be mem as well, but we only use Reg.
792 // We can extend this to check Dest if we decide to use that form.
793 assert(Var->hasReg());
794 // We cheat a little and use GPRRegister even for byte operations.
795 typename InstX86Base<Machine>::Traits::RegisterSet::GPRRegister VarReg =
796 InstX86Base<Machine>::Traits::RegisterSet::getEncodedByteRegOrGPR(
797 Ty, Var->getRegNum());
798 // Src must be reg == ECX or an Imm8.
799 // This is asserted by the assembler.
800 if (const auto SrcVar = llvm::dyn_cast<Variable>(Src)) {
801 assert(SrcVar->hasReg());
802 typename InstX86Base<Machine>::Traits::RegisterSet::GPRRegister SrcReg =
803 InstX86Base<Machine>::Traits::RegisterSet::getEncodedByteRegOrGPR(
804 Ty, SrcVar->getRegNum());
805 (Asm->*(Emitter.GPRGPR))(Ty, VarReg, SrcReg);
806 } else if (const auto Imm = llvm::dyn_cast<ConstantInteger32>(Src)) {
807 (Asm->*(Emitter.GPRImm))(Ty, VarReg, Immediate(Imm->getValue()));
809 llvm_unreachable("Unexpected operand type");
813 template <class Machine>
814 void emitIASGPRShiftDouble(
815 const Cfg *Func, const Variable *Dest, const Operand *Src1Op,
816 const Operand *Src2Op,
817 const typename InstX86Base<Machine>::Traits::Assembler::GPREmitterShiftD
819 typename InstX86Base<Machine>::Traits::Assembler *Asm =
820 Func->getAssembler<typename InstX86Base<Machine>::Traits::Assembler>();
821 // Dest can be reg or mem, but we only use the reg variant.
822 assert(Dest->hasReg());
823 typename InstX86Base<Machine>::Traits::RegisterSet::GPRRegister DestReg =
824 InstX86Base<Machine>::Traits::RegisterSet::getEncodedGPR(
826 // SrcVar1 must be reg.
827 const auto SrcVar1 = llvm::cast<Variable>(Src1Op);
828 assert(SrcVar1->hasReg());
829 typename InstX86Base<Machine>::Traits::RegisterSet::GPRRegister SrcReg =
830 InstX86Base<Machine>::Traits::RegisterSet::getEncodedGPR(
831 SrcVar1->getRegNum());
832 Type Ty = SrcVar1->getType();
833 // Src2 can be the implicit CL register or an immediate.
834 if (const auto Imm = llvm::dyn_cast<ConstantInteger32>(Src2Op)) {
835 (Asm->*(Emitter.GPRGPRImm))(Ty, DestReg, SrcReg,
836 Immediate(Imm->getValue()));
838 assert(llvm::cast<Variable>(Src2Op)->getRegNum() ==
839 InstX86Base<Machine>::Traits::RegisterSet::Reg_ecx);
840 (Asm->*(Emitter.GPRGPR))(Ty, DestReg, SrcReg);
844 template <class Machine>
845 void emitIASXmmShift(
846 const Cfg *Func, Type Ty, const Variable *Var, const Operand *Src,
847 const typename InstX86Base<Machine>::Traits::Assembler::XmmEmitterShiftOp
849 typename InstX86Base<Machine>::Traits::Assembler *Asm =
850 Func->getAssembler<typename InstX86Base<Machine>::Traits::Assembler>();
851 assert(Var->hasReg());
852 typename InstX86Base<Machine>::Traits::RegisterSet::XmmRegister VarReg =
853 InstX86Base<Machine>::Traits::RegisterSet::getEncodedXmm(
855 if (const auto SrcVar = llvm::dyn_cast<Variable>(Src)) {
856 if (SrcVar->hasReg()) {
857 typename InstX86Base<Machine>::Traits::RegisterSet::XmmRegister SrcReg =
858 InstX86Base<Machine>::Traits::RegisterSet::getEncodedXmm(
859 SrcVar->getRegNum());
860 (Asm->*(Emitter.XmmXmm))(Ty, VarReg, SrcReg);
862 typename InstX86Base<Machine>::Traits::Address SrcStackAddr =
863 static_cast<typename InstX86Base<Machine>::Traits::TargetLowering *>(
865 ->stackVarToAsmOperand(SrcVar);
866 (Asm->*(Emitter.XmmAddr))(Ty, VarReg, SrcStackAddr);
868 } else if (const auto Mem = llvm::dyn_cast<
869 typename InstX86Base<Machine>::Traits::X86OperandMem>(Src)) {
870 assert(Mem->getSegmentRegister() ==
871 InstX86Base<Machine>::Traits::X86OperandMem::DefaultSegment);
872 (Asm->*(Emitter.XmmAddr))(Ty, VarReg, Mem->toAsmAddress(Asm));
873 } else if (const auto Imm = llvm::dyn_cast<ConstantInteger32>(Src)) {
874 (Asm->*(Emitter.XmmImm))(Ty, VarReg, Immediate(Imm->getValue()));
876 llvm_unreachable("Unexpected operand type");
880 template <class Machine>
881 void emitIASRegOpTyXMM(
882 const Cfg *Func, Type Ty, const Variable *Var, const Operand *Src,
883 const typename InstX86Base<Machine>::Traits::Assembler::XmmEmitterRegOp
885 typename InstX86Base<Machine>::Traits::Assembler *Asm =
886 Func->getAssembler<typename InstX86Base<Machine>::Traits::Assembler>();
887 assert(Var->hasReg());
888 typename InstX86Base<Machine>::Traits::RegisterSet::XmmRegister VarReg =
889 InstX86Base<Machine>::Traits::RegisterSet::getEncodedXmm(
891 if (const auto SrcVar = llvm::dyn_cast<Variable>(Src)) {
892 if (SrcVar->hasReg()) {
893 typename InstX86Base<Machine>::Traits::RegisterSet::XmmRegister SrcReg =
894 InstX86Base<Machine>::Traits::RegisterSet::getEncodedXmm(
895 SrcVar->getRegNum());
896 (Asm->*(Emitter.XmmXmm))(Ty, VarReg, SrcReg);
898 typename InstX86Base<Machine>::Traits::Address SrcStackAddr =
899 static_cast<typename InstX86Base<Machine>::Traits::TargetLowering *>(
901 ->stackVarToAsmOperand(SrcVar);
902 (Asm->*(Emitter.XmmAddr))(Ty, VarReg, SrcStackAddr);
904 } else if (const auto Mem = llvm::dyn_cast<
905 typename InstX86Base<Machine>::Traits::X86OperandMem>(Src)) {
906 assert(Mem->getSegmentRegister() ==
907 InstX86Base<Machine>::Traits::X86OperandMem::DefaultSegment);
908 (Asm->*(Emitter.XmmAddr))(Ty, VarReg, Mem->toAsmAddress(Asm));
909 } else if (const auto Imm = llvm::dyn_cast<Constant>(Src)) {
910 (Asm->*(Emitter.XmmAddr))(
912 InstX86Base<Machine>::Traits::Address::ofConstPool(Asm, Imm));
914 llvm_unreachable("Unexpected operand type");
918 template <class Machine, typename DReg_t, typename SReg_t,
919 DReg_t (*destEnc)(int32_t), SReg_t (*srcEnc)(int32_t)>
920 void emitIASCastRegOp(const Cfg *Func, Type DispatchTy, const Variable *Dest,
922 const typename InstX86Base<Machine>::Traits::Assembler::
923 template CastEmitterRegOp<DReg_t, SReg_t> &Emitter) {
924 typename InstX86Base<Machine>::Traits::Assembler *Asm =
925 Func->getAssembler<typename InstX86Base<Machine>::Traits::Assembler>();
926 assert(Dest->hasReg());
927 DReg_t DestReg = destEnc(Dest->getRegNum());
928 if (const auto SrcVar = llvm::dyn_cast<Variable>(Src)) {
929 if (SrcVar->hasReg()) {
930 SReg_t SrcReg = srcEnc(SrcVar->getRegNum());
931 (Asm->*(Emitter.RegReg))(DispatchTy, DestReg, SrcReg);
933 typename InstX86Base<Machine>::Traits::Address SrcStackAddr =
934 static_cast<typename InstX86Base<Machine>::Traits::TargetLowering *>(
936 ->stackVarToAsmOperand(SrcVar);
937 (Asm->*(Emitter.RegAddr))(DispatchTy, DestReg, SrcStackAddr);
939 } else if (const auto Mem = llvm::dyn_cast<
940 typename InstX86Base<Machine>::Traits::X86OperandMem>(Src)) {
941 Mem->emitSegmentOverride(Asm);
942 (Asm->*(Emitter.RegAddr))(DispatchTy, DestReg, Mem->toAsmAddress(Asm));
944 llvm_unreachable("Unexpected operand type");
948 template <class Machine, typename DReg_t, typename SReg_t,
949 DReg_t (*destEnc)(int32_t), SReg_t (*srcEnc)(int32_t)>
950 void emitIASThreeOpImmOps(
951 const Cfg *Func, Type DispatchTy, const Variable *Dest, const Operand *Src0,
953 const typename InstX86Base<Machine>::Traits::Assembler::
954 template ThreeOpImmEmitter<DReg_t, SReg_t> Emitter) {
955 typename InstX86Base<Machine>::Traits::Assembler *Asm =
956 Func->getAssembler<typename InstX86Base<Machine>::Traits::Assembler>();
957 // This only handles Dest being a register, and Src1 being an immediate.
958 assert(Dest->hasReg());
959 DReg_t DestReg = destEnc(Dest->getRegNum());
960 Immediate Imm(llvm::cast<ConstantInteger32>(Src1)->getValue());
961 if (const auto SrcVar = llvm::dyn_cast<Variable>(Src0)) {
962 if (SrcVar->hasReg()) {
963 SReg_t SrcReg = srcEnc(SrcVar->getRegNum());
964 (Asm->*(Emitter.RegRegImm))(DispatchTy, DestReg, SrcReg, Imm);
966 typename InstX86Base<Machine>::Traits::Address SrcStackAddr =
967 static_cast<typename InstX86Base<Machine>::Traits::TargetLowering *>(
969 ->stackVarToAsmOperand(SrcVar);
970 (Asm->*(Emitter.RegAddrImm))(DispatchTy, DestReg, SrcStackAddr, Imm);
972 } else if (const auto Mem = llvm::dyn_cast<
973 typename InstX86Base<Machine>::Traits::X86OperandMem>(Src0)) {
974 Mem->emitSegmentOverride(Asm);
975 (Asm->*(Emitter.RegAddrImm))(DispatchTy, DestReg, Mem->toAsmAddress(Asm),
978 llvm_unreachable("Unexpected operand type");
982 template <class Machine>
983 void emitIASMovlikeXMM(
984 const Cfg *Func, const Variable *Dest, const Operand *Src,
985 const typename InstX86Base<Machine>::Traits::Assembler::XmmEmitterMovOps
987 typename InstX86Base<Machine>::Traits::Assembler *Asm =
988 Func->getAssembler<typename InstX86Base<Machine>::Traits::Assembler>();
989 if (Dest->hasReg()) {
990 typename InstX86Base<Machine>::Traits::RegisterSet::XmmRegister DestReg =
991 InstX86Base<Machine>::Traits::RegisterSet::getEncodedXmm(
993 if (const auto SrcVar = llvm::dyn_cast<Variable>(Src)) {
994 if (SrcVar->hasReg()) {
995 (Asm->*(Emitter.XmmXmm))(
996 DestReg, InstX86Base<Machine>::Traits::RegisterSet::getEncodedXmm(
997 SrcVar->getRegNum()));
999 typename InstX86Base<Machine>::Traits::Address StackAddr(
1000 static_cast<typename InstX86Base<Machine>::Traits::TargetLowering
1001 *>(Func->getTarget())
1002 ->stackVarToAsmOperand(SrcVar));
1003 (Asm->*(Emitter.XmmAddr))(DestReg, StackAddr);
1005 } else if (const auto SrcMem = llvm::dyn_cast<
1006 typename InstX86Base<Machine>::Traits::X86OperandMem>(Src)) {
1007 assert(SrcMem->getSegmentRegister() ==
1008 InstX86Base<Machine>::Traits::X86OperandMem::DefaultSegment);
1009 (Asm->*(Emitter.XmmAddr))(DestReg, SrcMem->toAsmAddress(Asm));
1011 llvm_unreachable("Unexpected operand type");
1014 typename InstX86Base<Machine>::Traits::Address StackAddr(
1015 static_cast<typename InstX86Base<Machine>::Traits::TargetLowering *>(
1017 ->stackVarToAsmOperand(Dest));
1018 // Src must be a register in this case.
1019 const auto SrcVar = llvm::cast<Variable>(Src);
1020 assert(SrcVar->hasReg());
1021 (Asm->*(Emitter.AddrXmm))(
1022 StackAddr, InstX86Base<Machine>::Traits::RegisterSet::getEncodedXmm(
1023 SrcVar->getRegNum()));
1027 template <class Machine>
1028 void InstX86Sqrtss<Machine>::emit(const Cfg *Func) const {
1029 if (!BuildDefs::dump())
1031 Ostream &Str = Func->getContext()->getStrEmit();
1032 assert(this->getSrcSize() == 1);
1033 Type Ty = this->getSrc(0)->getType();
1034 assert(isScalarFloatingType(Ty));
1035 Str << "\tsqrt" << InstX86Base<Machine>::Traits::TypeAttributes[Ty].SdSsString
1037 this->getSrc(0)->emit(Func);
1039 this->getDest()->emit(Func);
1042 template <class Machine>
1043 void InstX86Addss<Machine>::emit(const Cfg *Func) const {
1044 if (!BuildDefs::dump())
1048 buf, llvm::array_lengthof(buf), "add%s",
1049 InstX86Base<Machine>::Traits::TypeAttributes[this->getDest()->getType()]
1051 this->emitTwoAddress(buf, this, Func);
1054 template <class Machine>
1055 void InstX86Padd<Machine>::emit(const Cfg *Func) const {
1056 if (!BuildDefs::dump())
1060 buf, llvm::array_lengthof(buf), "padd%s",
1061 InstX86Base<Machine>::Traits::TypeAttributes[this->getDest()->getType()]
1063 this->emitTwoAddress(buf, this, Func);
1066 template <class Machine>
1067 void InstX86Pmull<Machine>::emit(const Cfg *Func) const {
1068 if (!BuildDefs::dump())
1071 bool TypesAreValid = this->getDest()->getType() == IceType_v4i32 ||
1072 this->getDest()->getType() == IceType_v8i16;
1073 bool InstructionSetIsValid =
1074 this->getDest()->getType() == IceType_v8i16 ||
1075 static_cast<typename InstX86Base<Machine>::Traits::TargetLowering *>(
1077 ->getInstructionSet() >= InstX86Base<Machine>::Traits::SSE4_1;
1078 (void)TypesAreValid;
1079 (void)InstructionSetIsValid;
1080 assert(TypesAreValid);
1081 assert(InstructionSetIsValid);
1083 buf, llvm::array_lengthof(buf), "pmull%s",
1084 InstX86Base<Machine>::Traits::TypeAttributes[this->getDest()->getType()]
1086 this->emitTwoAddress(buf, this, Func);
1089 template <class Machine>
1090 void InstX86Pmull<Machine>::emitIAS(const Cfg *Func) const {
1091 Type Ty = this->getDest()->getType();
1092 bool TypesAreValid = Ty == IceType_v4i32 || Ty == IceType_v8i16;
1093 bool InstructionSetIsValid =
1094 Ty == IceType_v8i16 ||
1095 static_cast<typename InstX86Base<Machine>::Traits::TargetLowering *>(
1097 ->getInstructionSet() >= InstX86Base<Machine>::Traits::SSE4_1;
1098 (void)TypesAreValid;
1099 (void)InstructionSetIsValid;
1100 assert(TypesAreValid);
1101 assert(InstructionSetIsValid);
1102 assert(this->getSrcSize() == 2);
1103 Type ElementTy = typeElementType(Ty);
1104 emitIASRegOpTyXMM<Machine>(Func, ElementTy, this->getDest(), this->getSrc(1),
1108 template <class Machine>
1109 void InstX86Subss<Machine>::emit(const Cfg *Func) const {
1110 if (!BuildDefs::dump())
1114 buf, llvm::array_lengthof(buf), "sub%s",
1115 InstX86Base<Machine>::Traits::TypeAttributes[this->getDest()->getType()]
1117 this->emitTwoAddress(buf, this, Func);
1120 template <class Machine>
1121 void InstX86Psub<Machine>::emit(const Cfg *Func) const {
1122 if (!BuildDefs::dump())
1126 buf, llvm::array_lengthof(buf), "psub%s",
1127 InstX86Base<Machine>::Traits::TypeAttributes[this->getDest()->getType()]
1129 this->emitTwoAddress(buf, this, Func);
1132 template <class Machine>
1133 void InstX86Mulss<Machine>::emit(const Cfg *Func) const {
1134 if (!BuildDefs::dump())
1138 buf, llvm::array_lengthof(buf), "mul%s",
1139 InstX86Base<Machine>::Traits::TypeAttributes[this->getDest()->getType()]
1141 this->emitTwoAddress(buf, this, Func);
1144 template <class Machine>
1145 void InstX86Pmuludq<Machine>::emit(const Cfg *Func) const {
1146 if (!BuildDefs::dump())
1148 assert(this->getSrc(0)->getType() == IceType_v4i32 &&
1149 this->getSrc(1)->getType() == IceType_v4i32);
1150 this->emitTwoAddress(this->Opcode, this, Func);
1153 template <class Machine>
1154 void InstX86Divss<Machine>::emit(const Cfg *Func) const {
1155 if (!BuildDefs::dump())
1159 buf, llvm::array_lengthof(buf), "div%s",
1160 InstX86Base<Machine>::Traits::TypeAttributes[this->getDest()->getType()]
1162 this->emitTwoAddress(buf, this, Func);
1165 template <class Machine> void InstX86Div<Machine>::emit(const Cfg *Func) const {
1166 if (!BuildDefs::dump())
1168 Ostream &Str = Func->getContext()->getStrEmit();
1169 assert(this->getSrcSize() == 3);
1170 Operand *Src1 = this->getSrc(1);
1171 Str << "\t" << this->Opcode << this->getWidthString(Src1->getType()) << "\t";
1175 template <class Machine>
1176 void InstX86Div<Machine>::emitIAS(const Cfg *Func) const {
1177 assert(this->getSrcSize() == 3);
1178 const Operand *Src = this->getSrc(1);
1179 Type Ty = Src->getType();
1180 static const typename InstX86Base<Machine>::Traits::Assembler::GPREmitterOneOp
1181 Emitter = {&InstX86Base<Machine>::Traits::Assembler::div,
1182 &InstX86Base<Machine>::Traits::Assembler::div};
1183 emitIASOpTyGPR<Machine>(Func, Ty, Src, Emitter);
1186 template <class Machine>
1187 void InstX86Idiv<Machine>::emit(const Cfg *Func) const {
1188 if (!BuildDefs::dump())
1190 Ostream &Str = Func->getContext()->getStrEmit();
1191 assert(this->getSrcSize() == 3);
1192 Operand *Src1 = this->getSrc(1);
1193 Str << "\t" << this->Opcode << this->getWidthString(Src1->getType()) << "\t";
1197 template <class Machine>
1198 void InstX86Idiv<Machine>::emitIAS(const Cfg *Func) const {
1199 assert(this->getSrcSize() == 3);
1200 const Operand *Src = this->getSrc(1);
1201 Type Ty = Src->getType();
1202 static const typename InstX86Base<Machine>::Traits::Assembler::GPREmitterOneOp
1203 Emitter = {&InstX86Base<Machine>::Traits::Assembler::idiv,
1204 &InstX86Base<Machine>::Traits::Assembler::idiv};
1205 emitIASOpTyGPR<Machine>(Func, Ty, Src, Emitter);
1208 // pblendvb and blendvps take xmm0 as a final implicit argument.
1209 template <class Machine>
1210 void emitVariableBlendInst(const char *Opcode, const Inst *Inst,
1212 if (!BuildDefs::dump())
1214 Ostream &Str = Func->getContext()->getStrEmit();
1215 assert(Inst->getSrcSize() == 3);
1216 assert(llvm::cast<Variable>(Inst->getSrc(2))->getRegNum() ==
1217 InstX86Base<Machine>::Traits::RegisterSet::Reg_xmm0);
1218 Str << "\t" << Opcode << "\t";
1219 Inst->getSrc(1)->emit(Func);
1221 Inst->getDest()->emit(Func);
1224 template <class Machine>
1225 void emitIASVariableBlendInst(
1226 const Inst *Inst, const Cfg *Func,
1227 const typename InstX86Base<Machine>::Traits::Assembler::XmmEmitterRegOp
1229 assert(Inst->getSrcSize() == 3);
1230 assert(llvm::cast<Variable>(Inst->getSrc(2))->getRegNum() ==
1231 InstX86Base<Machine>::Traits::RegisterSet::Reg_xmm0);
1232 const Variable *Dest = Inst->getDest();
1233 const Operand *Src = Inst->getSrc(1);
1234 emitIASRegOpTyXMM<Machine>(Func, Dest->getType(), Dest, Src, Emitter);
1237 template <class Machine>
1238 void InstX86Blendvps<Machine>::emit(const Cfg *Func) const {
1239 if (!BuildDefs::dump())
1241 assert(static_cast<typename InstX86Base<Machine>::Traits::TargetLowering *>(
1243 ->getInstructionSet() >= InstX86Base<Machine>::Traits::SSE4_1);
1244 emitVariableBlendInst<Machine>(this->Opcode, this, Func);
1247 template <class Machine>
1248 void InstX86Blendvps<Machine>::emitIAS(const Cfg *Func) const {
1249 assert(static_cast<typename InstX86Base<Machine>::Traits::TargetLowering *>(
1251 ->getInstructionSet() >= InstX86Base<Machine>::Traits::SSE4_1);
1252 static const typename InstX86Base<Machine>::Traits::Assembler::XmmEmitterRegOp
1253 Emitter = {&InstX86Base<Machine>::Traits::Assembler::blendvps,
1254 &InstX86Base<Machine>::Traits::Assembler::blendvps};
1255 emitIASVariableBlendInst<Machine>(this, Func, Emitter);
1258 template <class Machine>
1259 void InstX86Pblendvb<Machine>::emit(const Cfg *Func) const {
1260 if (!BuildDefs::dump())
1262 assert(static_cast<typename InstX86Base<Machine>::Traits::TargetLowering *>(
1264 ->getInstructionSet() >= InstX86Base<Machine>::Traits::SSE4_1);
1265 emitVariableBlendInst<Machine>(this->Opcode, this, Func);
1268 template <class Machine>
1269 void InstX86Pblendvb<Machine>::emitIAS(const Cfg *Func) const {
1270 assert(static_cast<typename InstX86Base<Machine>::Traits::TargetLowering *>(
1272 ->getInstructionSet() >= InstX86Base<Machine>::Traits::SSE4_1);
1273 static const typename InstX86Base<Machine>::Traits::Assembler::XmmEmitterRegOp
1274 Emitter = {&InstX86Base<Machine>::Traits::Assembler::pblendvb,
1275 &InstX86Base<Machine>::Traits::Assembler::pblendvb};
1276 emitIASVariableBlendInst<Machine>(this, Func, Emitter);
1279 template <class Machine>
1280 void InstX86Imul<Machine>::emit(const Cfg *Func) const {
1281 if (!BuildDefs::dump())
1283 Ostream &Str = Func->getContext()->getStrEmit();
1284 assert(this->getSrcSize() == 2);
1285 Variable *Dest = this->getDest();
1286 if (isByteSizedArithType(Dest->getType())) {
1287 // The 8-bit version of imul only allows the form "imul r/m8".
1288 const auto Src0Var = llvm::dyn_cast<Variable>(this->getSrc(0));
1291 Src0Var->getRegNum() ==
1292 InstX86Base<Machine>::Traits::RegisterSet::Reg_eax);
1294 this->getSrc(1)->emit(Func);
1295 } else if (llvm::isa<Constant>(this->getSrc(1))) {
1296 Str << "\timul" << this->getWidthString(Dest->getType()) << "\t";
1297 this->getSrc(1)->emit(Func);
1299 this->getSrc(0)->emit(Func);
1303 this->emitTwoAddress("imul", this, Func);
1307 template <class Machine>
1308 void InstX86Imul<Machine>::emitIAS(const Cfg *Func) const {
1309 assert(this->getSrcSize() == 2);
1310 const Variable *Var = this->getDest();
1311 Type Ty = Var->getType();
1312 const Operand *Src = this->getSrc(1);
1313 if (isByteSizedArithType(Ty)) {
1314 // The 8-bit version of imul only allows the form "imul r/m8".
1315 const auto Src0Var = llvm::dyn_cast<Variable>(this->getSrc(0));
1318 Src0Var->getRegNum() ==
1319 InstX86Base<Machine>::Traits::RegisterSet::Reg_eax);
1320 static const typename InstX86Base<
1321 Machine>::Traits::Assembler::GPREmitterOneOp Emitter = {
1322 &InstX86Base<Machine>::Traits::Assembler::imul,
1323 &InstX86Base<Machine>::Traits::Assembler::imul};
1324 emitIASOpTyGPR<Machine>(Func, Ty, this->getSrc(1), Emitter);
1326 // We only use imul as a two-address instruction even though
1327 // there is a 3 operand version when one of the operands is a constant.
1328 assert(Var == this->getSrc(0));
1329 static const typename InstX86Base<
1330 Machine>::Traits::Assembler::GPREmitterRegOp Emitter = {
1331 &InstX86Base<Machine>::Traits::Assembler::imul,
1332 &InstX86Base<Machine>::Traits::Assembler::imul,
1333 &InstX86Base<Machine>::Traits::Assembler::imul};
1334 emitIASRegOpTyGPR<Machine>(Func, Ty, Var, Src, Emitter);
1338 template <class Machine>
1339 void InstX86Insertps<Machine>::emitIAS(const Cfg *Func) const {
1340 assert(this->getSrcSize() == 3);
1341 assert(static_cast<typename InstX86Base<Machine>::Traits::TargetLowering *>(
1343 ->getInstructionSet() >= InstX86Base<Machine>::Traits::SSE4_1);
1344 const Variable *Dest = this->getDest();
1345 assert(Dest == this->getSrc(0));
1346 Type Ty = Dest->getType();
1347 static const typename InstX86Base<Machine>::Traits::Assembler::
1348 template ThreeOpImmEmitter<
1349 typename InstX86Base<Machine>::Traits::RegisterSet::XmmRegister,
1350 typename InstX86Base<Machine>::Traits::RegisterSet::XmmRegister>
1351 Emitter = {&InstX86Base<Machine>::Traits::Assembler::insertps,
1352 &InstX86Base<Machine>::Traits::Assembler::insertps};
1353 emitIASThreeOpImmOps<
1354 Machine, typename InstX86Base<Machine>::Traits::RegisterSet::XmmRegister,
1355 typename InstX86Base<Machine>::Traits::RegisterSet::XmmRegister,
1356 InstX86Base<Machine>::Traits::RegisterSet::getEncodedXmm,
1357 InstX86Base<Machine>::Traits::RegisterSet::getEncodedXmm>(
1358 Func, Ty, Dest, this->getSrc(1), this->getSrc(2), Emitter);
1361 template <class Machine>
1362 void InstX86Cbwdq<Machine>::emit(const Cfg *Func) const {
1363 if (!BuildDefs::dump())
1365 Ostream &Str = Func->getContext()->getStrEmit();
1366 assert(this->getSrcSize() == 1);
1367 Operand *Src0 = this->getSrc(0);
1368 assert(llvm::isa<Variable>(Src0));
1369 assert(llvm::cast<Variable>(Src0)->getRegNum() ==
1370 InstX86Base<Machine>::Traits::RegisterSet::Reg_eax);
1371 switch (Src0->getType()) {
1373 llvm_unreachable("unexpected source type!");
1376 assert(this->getDest()->getRegNum() ==
1377 InstX86Base<Machine>::Traits::RegisterSet::Reg_eax);
1381 assert(this->getDest()->getRegNum() ==
1382 InstX86Base<Machine>::Traits::RegisterSet::Reg_edx);
1386 assert(this->getDest()->getRegNum() ==
1387 InstX86Base<Machine>::Traits::RegisterSet::Reg_edx);
1393 template <class Machine>
1394 void InstX86Cbwdq<Machine>::emitIAS(const Cfg *Func) const {
1395 typename InstX86Base<Machine>::Traits::Assembler *Asm =
1396 Func->getAssembler<typename InstX86Base<Machine>::Traits::Assembler>();
1397 assert(this->getSrcSize() == 1);
1398 Operand *Src0 = this->getSrc(0);
1399 assert(llvm::isa<Variable>(Src0));
1400 assert(llvm::cast<Variable>(Src0)->getRegNum() ==
1401 InstX86Base<Machine>::Traits::RegisterSet::Reg_eax);
1402 switch (Src0->getType()) {
1404 llvm_unreachable("unexpected source type!");
1407 assert(this->getDest()->getRegNum() ==
1408 InstX86Base<Machine>::Traits::RegisterSet::Reg_eax);
1412 assert(this->getDest()->getRegNum() ==
1413 InstX86Base<Machine>::Traits::RegisterSet::Reg_edx);
1417 assert(this->getDest()->getRegNum() ==
1418 InstX86Base<Machine>::Traits::RegisterSet::Reg_edx);
1424 template <class Machine> void InstX86Mul<Machine>::emit(const Cfg *Func) const {
1425 if (!BuildDefs::dump())
1427 Ostream &Str = Func->getContext()->getStrEmit();
1428 assert(this->getSrcSize() == 2);
1429 assert(llvm::isa<Variable>(this->getSrc(0)));
1430 assert(llvm::cast<Variable>(this->getSrc(0))->getRegNum() ==
1431 InstX86Base<Machine>::Traits::RegisterSet::Reg_eax);
1433 this->getDest()->getRegNum() ==
1434 InstX86Base<Machine>::Traits::RegisterSet::Reg_eax); // TODO: allow edx?
1435 Str << "\tmul" << this->getWidthString(this->getDest()->getType()) << "\t";
1436 this->getSrc(1)->emit(Func);
1439 template <class Machine>
1440 void InstX86Mul<Machine>::emitIAS(const Cfg *Func) const {
1441 assert(this->getSrcSize() == 2);
1442 assert(llvm::isa<Variable>(this->getSrc(0)));
1443 assert(llvm::cast<Variable>(this->getSrc(0))->getRegNum() ==
1444 InstX86Base<Machine>::Traits::RegisterSet::Reg_eax);
1446 this->getDest()->getRegNum() ==
1447 InstX86Base<Machine>::Traits::RegisterSet::Reg_eax); // TODO: allow edx?
1448 const Operand *Src = this->getSrc(1);
1449 Type Ty = Src->getType();
1450 static const typename InstX86Base<Machine>::Traits::Assembler::GPREmitterOneOp
1451 Emitter = {&InstX86Base<Machine>::Traits::Assembler::mul,
1452 &InstX86Base<Machine>::Traits::Assembler::mul};
1453 emitIASOpTyGPR<Machine>(Func, Ty, Src, Emitter);
1456 template <class Machine> void InstX86Mul<Machine>::dump(const Cfg *Func) const {
1457 if (!BuildDefs::dump())
1459 Ostream &Str = Func->getContext()->getStrDump();
1460 this->dumpDest(Func);
1461 Str << " = mul." << this->getDest()->getType() << " ";
1462 this->dumpSources(Func);
1465 template <class Machine>
1466 void InstX86Shld<Machine>::emit(const Cfg *Func) const {
1467 if (!BuildDefs::dump())
1469 Ostream &Str = Func->getContext()->getStrEmit();
1470 Variable *Dest = this->getDest();
1471 assert(this->getSrcSize() == 3);
1472 assert(Dest == this->getSrc(0));
1473 Str << "\tshld" << this->getWidthString(Dest->getType()) << "\t";
1474 if (const auto ShiftReg = llvm::dyn_cast<Variable>(this->getSrc(2))) {
1476 assert(ShiftReg->getRegNum() ==
1477 InstX86Base<Machine>::Traits::RegisterSet::Reg_ecx);
1480 this->getSrc(2)->emit(Func);
1483 this->getSrc(1)->emit(Func);
1488 template <class Machine>
1489 void InstX86Shld<Machine>::emitIAS(const Cfg *Func) const {
1490 assert(this->getSrcSize() == 3);
1491 assert(this->getDest() == this->getSrc(0));
1492 const Variable *Dest = this->getDest();
1493 const Operand *Src1 = this->getSrc(1);
1494 const Operand *Src2 = this->getSrc(2);
1495 static const typename InstX86Base<
1496 Machine>::Traits::Assembler::GPREmitterShiftD Emitter = {
1497 &InstX86Base<Machine>::Traits::Assembler::shld,
1498 &InstX86Base<Machine>::Traits::Assembler::shld};
1499 emitIASGPRShiftDouble<Machine>(Func, Dest, Src1, Src2, Emitter);
1502 template <class Machine>
1503 void InstX86Shld<Machine>::dump(const Cfg *Func) const {
1504 if (!BuildDefs::dump())
1506 Ostream &Str = Func->getContext()->getStrDump();
1507 this->dumpDest(Func);
1508 Str << " = shld." << this->getDest()->getType() << " ";
1509 this->dumpSources(Func);
1512 template <class Machine>
1513 void InstX86Shrd<Machine>::emit(const Cfg *Func) const {
1514 if (!BuildDefs::dump())
1516 Ostream &Str = Func->getContext()->getStrEmit();
1517 Variable *Dest = this->getDest();
1518 assert(this->getSrcSize() == 3);
1519 assert(Dest == this->getSrc(0));
1520 Str << "\tshrd" << this->getWidthString(Dest->getType()) << "\t";
1521 if (const auto ShiftReg = llvm::dyn_cast<Variable>(this->getSrc(2))) {
1523 assert(ShiftReg->getRegNum() ==
1524 InstX86Base<Machine>::Traits::RegisterSet::Reg_ecx);
1527 this->getSrc(2)->emit(Func);
1530 this->getSrc(1)->emit(Func);
1535 template <class Machine>
1536 void InstX86Shrd<Machine>::emitIAS(const Cfg *Func) const {
1537 assert(this->getSrcSize() == 3);
1538 assert(this->getDest() == this->getSrc(0));
1539 const Variable *Dest = this->getDest();
1540 const Operand *Src1 = this->getSrc(1);
1541 const Operand *Src2 = this->getSrc(2);
1542 static const typename InstX86Base<
1543 Machine>::Traits::Assembler::GPREmitterShiftD Emitter = {
1544 &InstX86Base<Machine>::Traits::Assembler::shrd,
1545 &InstX86Base<Machine>::Traits::Assembler::shrd};
1546 emitIASGPRShiftDouble<Machine>(Func, Dest, Src1, Src2, Emitter);
1549 template <class Machine>
1550 void InstX86Shrd<Machine>::dump(const Cfg *Func) const {
1551 if (!BuildDefs::dump())
1553 Ostream &Str = Func->getContext()->getStrDump();
1554 this->dumpDest(Func);
1555 Str << " = shrd." << this->getDest()->getType() << " ";
1556 this->dumpSources(Func);
1559 template <class Machine>
1560 void InstX86Cmov<Machine>::emit(const Cfg *Func) const {
1561 if (!BuildDefs::dump())
1563 Ostream &Str = Func->getContext()->getStrEmit();
1564 Variable *Dest = this->getDest();
1566 assert(Condition != InstX86Base<Machine>::Traits::Cond::Br_None);
1567 assert(this->getDest()->hasReg());
1569 << InstX86Base<Machine>::Traits::InstBrAttributes[Condition].DisplayString
1570 << this->getWidthString(Dest->getType()) << "\t";
1571 this->getSrc(1)->emit(Func);
1576 template <class Machine>
1577 void InstX86Cmov<Machine>::emitIAS(const Cfg *Func) const {
1578 assert(Condition != InstX86Base<Machine>::Traits::Cond::Br_None);
1579 assert(this->getDest()->hasReg());
1580 assert(this->getSrcSize() == 2);
1581 Operand *Src = this->getSrc(1);
1582 Type SrcTy = Src->getType();
1583 assert(SrcTy == IceType_i16 || SrcTy == IceType_i32);
1584 typename InstX86Base<Machine>::Traits::Assembler *Asm =
1585 Func->getAssembler<typename InstX86Base<Machine>::Traits::Assembler>();
1586 if (const auto *SrcVar = llvm::dyn_cast<Variable>(Src)) {
1587 if (SrcVar->hasReg()) {
1588 Asm->cmov(SrcTy, Condition,
1589 InstX86Base<Machine>::Traits::RegisterSet::getEncodedGPR(
1590 this->getDest()->getRegNum()),
1591 InstX86Base<Machine>::Traits::RegisterSet::getEncodedGPR(
1592 SrcVar->getRegNum()));
1596 InstX86Base<Machine>::Traits::RegisterSet::getEncodedGPR(
1597 this->getDest()->getRegNum()),
1598 static_cast<typename InstX86Base<Machine>::Traits::TargetLowering *>(
1600 ->stackVarToAsmOperand(SrcVar));
1602 } else if (const auto Mem = llvm::dyn_cast<
1603 typename InstX86Base<Machine>::Traits::X86OperandMem>(Src)) {
1604 assert(Mem->getSegmentRegister() ==
1605 InstX86Base<Machine>::Traits::X86OperandMem::DefaultSegment);
1606 Asm->cmov(SrcTy, Condition,
1607 InstX86Base<Machine>::Traits::RegisterSet::getEncodedGPR(
1608 this->getDest()->getRegNum()),
1609 Mem->toAsmAddress(Asm));
1611 llvm_unreachable("Unexpected operand type");
1615 template <class Machine>
1616 void InstX86Cmov<Machine>::dump(const Cfg *Func) const {
1617 if (!BuildDefs::dump())
1619 Ostream &Str = Func->getContext()->getStrDump();
1621 << InstX86Base<Machine>::Traits::InstBrAttributes[Condition].DisplayString
1623 Str << this->getDest()->getType() << " ";
1624 this->dumpDest(Func);
1626 this->dumpSources(Func);
1629 template <class Machine>
1630 void InstX86Cmpps<Machine>::emit(const Cfg *Func) const {
1631 if (!BuildDefs::dump())
1633 Ostream &Str = Func->getContext()->getStrEmit();
1634 assert(this->getSrcSize() == 2);
1635 assert(Condition < InstX86Base<Machine>::Traits::Cond::Cmpps_Invalid);
1638 << InstX86Base<Machine>::Traits::InstCmppsAttributes[Condition].EmitString
1641 this->getSrc(1)->emit(Func);
1643 this->getDest()->emit(Func);
1646 template <class Machine>
1647 void InstX86Cmpps<Machine>::emitIAS(const Cfg *Func) const {
1648 typename InstX86Base<Machine>::Traits::Assembler *Asm =
1649 Func->getAssembler<typename InstX86Base<Machine>::Traits::Assembler>();
1650 assert(this->getSrcSize() == 2);
1651 assert(Condition < InstX86Base<Machine>::Traits::Cond::Cmpps_Invalid);
1652 // Assuming there isn't any load folding for cmpps, and vector constants
1653 // are not allowed in PNaCl.
1654 assert(llvm::isa<Variable>(this->getSrc(1)));
1655 const auto SrcVar = llvm::cast<Variable>(this->getSrc(1));
1656 if (SrcVar->hasReg()) {
1657 Asm->cmpps(InstX86Base<Machine>::Traits::RegisterSet::getEncodedXmm(
1658 this->getDest()->getRegNum()),
1659 InstX86Base<Machine>::Traits::RegisterSet::getEncodedXmm(
1660 SrcVar->getRegNum()),
1663 typename InstX86Base<Machine>::Traits::Address SrcStackAddr =
1664 static_cast<typename InstX86Base<Machine>::Traits::TargetLowering *>(
1666 ->stackVarToAsmOperand(SrcVar);
1667 Asm->cmpps(InstX86Base<Machine>::Traits::RegisterSet::getEncodedXmm(
1668 this->getDest()->getRegNum()),
1669 SrcStackAddr, Condition);
1673 template <class Machine>
1674 void InstX86Cmpps<Machine>::dump(const Cfg *Func) const {
1675 if (!BuildDefs::dump())
1677 Ostream &Str = Func->getContext()->getStrDump();
1678 assert(Condition < InstX86Base<Machine>::Traits::Cond::Cmpps_Invalid);
1679 this->dumpDest(Func);
1681 << InstX86Base<Machine>::Traits::InstCmppsAttributes[Condition].EmitString
1684 this->dumpSources(Func);
1687 template <class Machine>
1688 void InstX86Cmpxchg<Machine>::emit(const Cfg *Func) const {
1689 if (!BuildDefs::dump())
1691 Ostream &Str = Func->getContext()->getStrEmit();
1692 assert(this->getSrcSize() == 3);
1696 Str << "\tcmpxchg" << this->getWidthString(this->getSrc(0)->getType())
1698 this->getSrc(2)->emit(Func);
1700 this->getSrc(0)->emit(Func);
1703 template <class Machine>
1704 void InstX86Cmpxchg<Machine>::emitIAS(const Cfg *Func) const {
1705 assert(this->getSrcSize() == 3);
1706 typename InstX86Base<Machine>::Traits::Assembler *Asm =
1707 Func->getAssembler<typename InstX86Base<Machine>::Traits::Assembler>();
1708 Type Ty = this->getSrc(0)->getType();
1710 llvm::cast<typename InstX86Base<Machine>::Traits::X86OperandMem>(
1712 assert(Mem->getSegmentRegister() ==
1713 InstX86Base<Machine>::Traits::X86OperandMem::DefaultSegment);
1714 const typename InstX86Base<Machine>::Traits::Address Addr =
1715 Mem->toAsmAddress(Asm);
1716 const auto VarReg = llvm::cast<Variable>(this->getSrc(2));
1717 assert(VarReg->hasReg());
1718 const typename InstX86Base<Machine>::Traits::RegisterSet::GPRRegister Reg =
1719 InstX86Base<Machine>::Traits::RegisterSet::getEncodedGPR(
1720 VarReg->getRegNum());
1721 Asm->cmpxchg(Ty, Addr, Reg, this->Locked);
1724 template <class Machine>
1725 void InstX86Cmpxchg<Machine>::dump(const Cfg *Func) const {
1726 if (!BuildDefs::dump())
1728 Ostream &Str = Func->getContext()->getStrDump();
1732 Str << "cmpxchg." << this->getSrc(0)->getType() << " ";
1733 this->dumpSources(Func);
1736 template <class Machine>
1737 void InstX86Cmpxchg8b<Machine>::emit(const Cfg *Func) const {
1738 if (!BuildDefs::dump())
1740 Ostream &Str = Func->getContext()->getStrEmit();
1741 assert(this->getSrcSize() == 5);
1745 Str << "\tcmpxchg8b\t";
1746 this->getSrc(0)->emit(Func);
1749 template <class Machine>
1750 void InstX86Cmpxchg8b<Machine>::emitIAS(const Cfg *Func) const {
1751 assert(this->getSrcSize() == 5);
1752 typename InstX86Base<Machine>::Traits::Assembler *Asm =
1753 Func->getAssembler<typename InstX86Base<Machine>::Traits::Assembler>();
1755 llvm::cast<typename InstX86Base<Machine>::Traits::X86OperandMem>(
1757 assert(Mem->getSegmentRegister() ==
1758 InstX86Base<Machine>::Traits::X86OperandMem::DefaultSegment);
1759 const typename InstX86Base<Machine>::Traits::Address Addr =
1760 Mem->toAsmAddress(Asm);
1761 Asm->cmpxchg8b(Addr, this->Locked);
1764 template <class Machine>
1765 void InstX86Cmpxchg8b<Machine>::dump(const Cfg *Func) const {
1766 if (!BuildDefs::dump())
1768 Ostream &Str = Func->getContext()->getStrDump();
1772 Str << "cmpxchg8b ";
1773 this->dumpSources(Func);
1776 template <class Machine> void InstX86Cvt<Machine>::emit(const Cfg *Func) const {
1777 if (!BuildDefs::dump())
1779 Ostream &Str = Func->getContext()->getStrEmit();
1780 assert(this->getSrcSize() == 1);
1784 Str << InstX86Base<Machine>::Traits::TypeAttributes[this->getSrc(0)
1788 Machine>::Traits::TypeAttributes[this->getDest()->getType()]
1790 this->getSrc(0)->emit(Func);
1792 this->getDest()->emit(Func);
1795 template <class Machine>
1796 void InstX86Cvt<Machine>::emitIAS(const Cfg *Func) const {
1797 assert(this->getSrcSize() == 1);
1798 const Variable *Dest = this->getDest();
1799 const Operand *Src = this->getSrc(0);
1800 Type DestTy = Dest->getType();
1801 Type SrcTy = Src->getType();
1804 assert(isScalarIntegerType(SrcTy));
1805 assert(typeWidthInBytes(SrcTy) <= 4);
1806 assert(isScalarFloatingType(DestTy));
1807 static const typename InstX86Base<Machine>::Traits::Assembler::
1808 template CastEmitterRegOp<
1809 typename InstX86Base<Machine>::Traits::RegisterSet::XmmRegister,
1810 typename InstX86Base<Machine>::Traits::RegisterSet::GPRRegister>
1811 Emitter = {&InstX86Base<Machine>::Traits::Assembler::cvtsi2ss,
1812 &InstX86Base<Machine>::Traits::Assembler::cvtsi2ss};
1815 typename InstX86Base<Machine>::Traits::RegisterSet::XmmRegister,
1816 typename InstX86Base<Machine>::Traits::RegisterSet::GPRRegister,
1817 InstX86Base<Machine>::Traits::RegisterSet::getEncodedXmm,
1818 InstX86Base<Machine>::Traits::RegisterSet::getEncodedGPR>(
1819 Func, DestTy, Dest, Src, Emitter);
1823 assert(isScalarFloatingType(SrcTy));
1824 assert(isScalarIntegerType(DestTy));
1825 assert(typeWidthInBytes(DestTy) <= 4);
1826 static const typename InstX86Base<Machine>::Traits::Assembler::
1827 template CastEmitterRegOp<
1828 typename InstX86Base<Machine>::Traits::RegisterSet::GPRRegister,
1829 typename InstX86Base<Machine>::Traits::RegisterSet::XmmRegister>
1830 Emitter = {&InstX86Base<Machine>::Traits::Assembler::cvttss2si,
1831 &InstX86Base<Machine>::Traits::Assembler::cvttss2si};
1834 typename InstX86Base<Machine>::Traits::RegisterSet::GPRRegister,
1835 typename InstX86Base<Machine>::Traits::RegisterSet::XmmRegister,
1836 InstX86Base<Machine>::Traits::RegisterSet::getEncodedGPR,
1837 InstX86Base<Machine>::Traits::RegisterSet::getEncodedXmm>(
1838 Func, SrcTy, Dest, Src, Emitter);
1842 assert(isScalarFloatingType(SrcTy));
1843 assert(isScalarFloatingType(DestTy));
1844 assert(DestTy != SrcTy);
1845 static const typename InstX86Base<
1846 Machine>::Traits::Assembler::XmmEmitterRegOp Emitter = {
1847 &InstX86Base<Machine>::Traits::Assembler::cvtfloat2float,
1848 &InstX86Base<Machine>::Traits::Assembler::cvtfloat2float};
1849 emitIASRegOpTyXMM<Machine>(Func, SrcTy, Dest, Src, Emitter);
1853 assert(isVectorIntegerType(SrcTy));
1854 assert(isVectorFloatingType(DestTy));
1855 static const typename InstX86Base<
1856 Machine>::Traits::Assembler::XmmEmitterRegOp Emitter = {
1857 &InstX86Base<Machine>::Traits::Assembler::cvtdq2ps,
1858 &InstX86Base<Machine>::Traits::Assembler::cvtdq2ps};
1859 emitIASRegOpTyXMM<Machine>(Func, DestTy, Dest, Src, Emitter);
1863 assert(isVectorFloatingType(SrcTy));
1864 assert(isVectorIntegerType(DestTy));
1865 static const typename InstX86Base<
1866 Machine>::Traits::Assembler::XmmEmitterRegOp Emitter = {
1867 &InstX86Base<Machine>::Traits::Assembler::cvttps2dq,
1868 &InstX86Base<Machine>::Traits::Assembler::cvttps2dq};
1869 emitIASRegOpTyXMM<Machine>(Func, DestTy, Dest, Src, Emitter);
1875 template <class Machine> void InstX86Cvt<Machine>::dump(const Cfg *Func) const {
1876 if (!BuildDefs::dump())
1878 Ostream &Str = Func->getContext()->getStrDump();
1879 this->dumpDest(Func);
1883 Str << InstX86Base<Machine>::Traits::TypeAttributes[this->getSrc(0)
1887 Machine>::Traits::TypeAttributes[this->getDest()->getType()]
1889 this->dumpSources(Func);
1892 template <class Machine>
1893 void InstX86Icmp<Machine>::emit(const Cfg *Func) const {
1894 if (!BuildDefs::dump())
1896 Ostream &Str = Func->getContext()->getStrEmit();
1897 assert(this->getSrcSize() == 2);
1898 Str << "\tcmp" << this->getWidthString(this->getSrc(0)->getType()) << "\t";
1899 this->getSrc(1)->emit(Func);
1901 this->getSrc(0)->emit(Func);
1904 template <class Machine>
1905 void InstX86Icmp<Machine>::emitIAS(const Cfg *Func) const {
1906 assert(this->getSrcSize() == 2);
1907 const Operand *Src0 = this->getSrc(0);
1908 const Operand *Src1 = this->getSrc(1);
1909 Type Ty = Src0->getType();
1910 static const typename InstX86Base<Machine>::Traits::Assembler::GPREmitterRegOp
1911 RegEmitter = {&InstX86Base<Machine>::Traits::Assembler::cmp,
1912 &InstX86Base<Machine>::Traits::Assembler::cmp,
1913 &InstX86Base<Machine>::Traits::Assembler::cmp};
1914 static const typename InstX86Base<
1915 Machine>::Traits::Assembler::GPREmitterAddrOp AddrEmitter = {
1916 &InstX86Base<Machine>::Traits::Assembler::cmp,
1917 &InstX86Base<Machine>::Traits::Assembler::cmp};
1918 if (const auto SrcVar0 = llvm::dyn_cast<Variable>(Src0)) {
1919 if (SrcVar0->hasReg()) {
1920 emitIASRegOpTyGPR<Machine>(Func, Ty, SrcVar0, Src1, RegEmitter);
1924 emitIASAsAddrOpTyGPR<Machine>(Func, Ty, Src0, Src1, AddrEmitter);
1927 template <class Machine>
1928 void InstX86Icmp<Machine>::dump(const Cfg *Func) const {
1929 if (!BuildDefs::dump())
1931 Ostream &Str = Func->getContext()->getStrDump();
1932 Str << "cmp." << this->getSrc(0)->getType() << " ";
1933 this->dumpSources(Func);
1936 template <class Machine>
1937 void InstX86Ucomiss<Machine>::emit(const Cfg *Func) const {
1938 if (!BuildDefs::dump())
1940 Ostream &Str = Func->getContext()->getStrEmit();
1941 assert(this->getSrcSize() == 2);
1943 << InstX86Base<Machine>::Traits::TypeAttributes[this->getSrc(0)
1945 .SdSsString << "\t";
1946 this->getSrc(1)->emit(Func);
1948 this->getSrc(0)->emit(Func);
1951 template <class Machine>
1952 void InstX86Ucomiss<Machine>::emitIAS(const Cfg *Func) const {
1953 assert(this->getSrcSize() == 2);
1954 // Currently src0 is always a variable by convention, to avoid having
1955 // two memory operands.
1956 assert(llvm::isa<Variable>(this->getSrc(0)));
1957 const auto Src0Var = llvm::cast<Variable>(this->getSrc(0));
1958 Type Ty = Src0Var->getType();
1959 static const typename InstX86Base<Machine>::Traits::Assembler::XmmEmitterRegOp
1960 Emitter = {&InstX86Base<Machine>::Traits::Assembler::ucomiss,
1961 &InstX86Base<Machine>::Traits::Assembler::ucomiss};
1962 emitIASRegOpTyXMM<Machine>(Func, Ty, Src0Var, this->getSrc(1), Emitter);
1965 template <class Machine>
1966 void InstX86Ucomiss<Machine>::dump(const Cfg *Func) const {
1967 if (!BuildDefs::dump())
1969 Ostream &Str = Func->getContext()->getStrDump();
1970 Str << "ucomiss." << this->getSrc(0)->getType() << " ";
1971 this->dumpSources(Func);
1974 template <class Machine> void InstX86UD2<Machine>::emit(const Cfg *Func) const {
1975 if (!BuildDefs::dump())
1977 Ostream &Str = Func->getContext()->getStrEmit();
1978 assert(this->getSrcSize() == 0);
1982 template <class Machine>
1983 void InstX86UD2<Machine>::emitIAS(const Cfg *Func) const {
1984 typename InstX86Base<Machine>::Traits::Assembler *Asm =
1985 Func->getAssembler<typename InstX86Base<Machine>::Traits::Assembler>();
1989 template <class Machine> void InstX86UD2<Machine>::dump(const Cfg *Func) const {
1990 if (!BuildDefs::dump())
1992 Ostream &Str = Func->getContext()->getStrDump();
1996 template <class Machine>
1997 void InstX86Test<Machine>::emit(const Cfg *Func) const {
1998 if (!BuildDefs::dump())
2000 Ostream &Str = Func->getContext()->getStrEmit();
2001 assert(this->getSrcSize() == 2);
2002 Str << "\ttest" << this->getWidthString(this->getSrc(0)->getType()) << "\t";
2003 this->getSrc(1)->emit(Func);
2005 this->getSrc(0)->emit(Func);
2008 template <class Machine>
2009 void InstX86Test<Machine>::emitIAS(const Cfg *Func) const {
2010 assert(this->getSrcSize() == 2);
2011 const Operand *Src0 = this->getSrc(0);
2012 const Operand *Src1 = this->getSrc(1);
2013 Type Ty = Src0->getType();
2014 // The Reg/Addr form of test is not encodeable.
2015 static const typename InstX86Base<Machine>::Traits::Assembler::GPREmitterRegOp
2016 RegEmitter = {&InstX86Base<Machine>::Traits::Assembler::test, nullptr,
2017 &InstX86Base<Machine>::Traits::Assembler::test};
2018 static const typename InstX86Base<
2019 Machine>::Traits::Assembler::GPREmitterAddrOp AddrEmitter = {
2020 &InstX86Base<Machine>::Traits::Assembler::test,
2021 &InstX86Base<Machine>::Traits::Assembler::test};
2022 if (const auto SrcVar0 = llvm::dyn_cast<Variable>(Src0)) {
2023 if (SrcVar0->hasReg()) {
2024 emitIASRegOpTyGPR<Machine>(Func, Ty, SrcVar0, Src1, RegEmitter);
2028 llvm_unreachable("Nothing actually generates this so it's untested");
2029 emitIASAsAddrOpTyGPR<Machine>(Func, Ty, Src0, Src1, AddrEmitter);
2032 template <class Machine>
2033 void InstX86Test<Machine>::dump(const Cfg *Func) const {
2034 if (!BuildDefs::dump())
2036 Ostream &Str = Func->getContext()->getStrDump();
2037 Str << "test." << this->getSrc(0)->getType() << " ";
2038 this->dumpSources(Func);
2041 template <class Machine>
2042 void InstX86Mfence<Machine>::emit(const Cfg *Func) const {
2043 if (!BuildDefs::dump())
2045 Ostream &Str = Func->getContext()->getStrEmit();
2046 assert(this->getSrcSize() == 0);
2050 template <class Machine>
2051 void InstX86Mfence<Machine>::emitIAS(const Cfg *Func) const {
2052 typename InstX86Base<Machine>::Traits::Assembler *Asm =
2053 Func->getAssembler<typename InstX86Base<Machine>::Traits::Assembler>();
2057 template <class Machine>
2058 void InstX86Mfence<Machine>::dump(const Cfg *Func) const {
2059 if (!BuildDefs::dump())
2061 Ostream &Str = Func->getContext()->getStrDump();
2065 template <class Machine>
2066 void InstX86Store<Machine>::emit(const Cfg *Func) const {
2067 if (!BuildDefs::dump())
2069 Ostream &Str = Func->getContext()->getStrEmit();
2070 assert(this->getSrcSize() == 2);
2071 Type Ty = this->getSrc(0)->getType();
2072 Str << "\tmov" << this->getWidthString(Ty)
2073 << InstX86Base<Machine>::Traits::TypeAttributes[Ty].SdSsString << "\t";
2074 this->getSrc(0)->emit(Func);
2076 this->getSrc(1)->emit(Func);
2079 template <class Machine>
2080 void InstX86Store<Machine>::emitIAS(const Cfg *Func) const {
2081 assert(this->getSrcSize() == 2);
2082 const Operand *Dest = this->getSrc(1);
2083 const Operand *Src = this->getSrc(0);
2084 Type DestTy = Dest->getType();
2085 if (isScalarFloatingType(DestTy)) {
2086 // Src must be a register, since Dest is a Mem operand of some kind.
2087 const auto SrcVar = llvm::cast<Variable>(Src);
2088 assert(SrcVar->hasReg());
2089 typename InstX86Base<Machine>::Traits::RegisterSet::XmmRegister SrcReg =
2090 InstX86Base<Machine>::Traits::RegisterSet::getEncodedXmm(
2091 SrcVar->getRegNum());
2092 typename InstX86Base<Machine>::Traits::Assembler *Asm =
2093 Func->getAssembler<typename InstX86Base<Machine>::Traits::Assembler>();
2094 if (const auto DestVar = llvm::dyn_cast<Variable>(Dest)) {
2095 assert(!DestVar->hasReg());
2096 typename InstX86Base<Machine>::Traits::Address StackAddr(
2097 static_cast<typename InstX86Base<Machine>::Traits::TargetLowering *>(
2099 ->stackVarToAsmOperand(DestVar));
2100 Asm->movss(DestTy, StackAddr, SrcReg);
2102 const auto DestMem =
2103 llvm::cast<typename InstX86Base<Machine>::Traits::X86OperandMem>(
2105 assert(DestMem->getSegmentRegister() ==
2106 InstX86Base<Machine>::Traits::X86OperandMem::DefaultSegment);
2107 Asm->movss(DestTy, DestMem->toAsmAddress(Asm), SrcReg);
2111 assert(isScalarIntegerType(DestTy));
2112 static const typename InstX86Base<
2113 Machine>::Traits::Assembler::GPREmitterAddrOp GPRAddrEmitter = {
2114 &InstX86Base<Machine>::Traits::Assembler::mov,
2115 &InstX86Base<Machine>::Traits::Assembler::mov};
2116 emitIASAsAddrOpTyGPR<Machine>(Func, DestTy, Dest, Src, GPRAddrEmitter);
2120 template <class Machine>
2121 void InstX86Store<Machine>::dump(const Cfg *Func) const {
2122 if (!BuildDefs::dump())
2124 Ostream &Str = Func->getContext()->getStrDump();
2125 Str << "mov." << this->getSrc(0)->getType() << " ";
2126 this->getSrc(1)->dump(Func);
2128 this->getSrc(0)->dump(Func);
2131 template <class Machine>
2132 void InstX86StoreP<Machine>::emit(const Cfg *Func) const {
2133 if (!BuildDefs::dump())
2135 Ostream &Str = Func->getContext()->getStrEmit();
2136 assert(this->getSrcSize() == 2);
2137 Str << "\tmovups\t";
2138 this->getSrc(0)->emit(Func);
2140 this->getSrc(1)->emit(Func);
2143 template <class Machine>
2144 void InstX86StoreP<Machine>::emitIAS(const Cfg *Func) const {
2145 typename InstX86Base<Machine>::Traits::Assembler *Asm =
2146 Func->getAssembler<typename InstX86Base<Machine>::Traits::Assembler>();
2147 assert(this->getSrcSize() == 2);
2148 const auto SrcVar = llvm::cast<Variable>(this->getSrc(0));
2149 const auto DestMem =
2150 llvm::cast<typename InstX86Base<Machine>::Traits::X86OperandMem>(
2152 assert(DestMem->getSegmentRegister() ==
2153 InstX86Base<Machine>::Traits::X86OperandMem::DefaultSegment);
2154 assert(SrcVar->hasReg());
2155 Asm->movups(DestMem->toAsmAddress(Asm),
2156 InstX86Base<Machine>::Traits::RegisterSet::getEncodedXmm(
2157 SrcVar->getRegNum()));
2160 template <class Machine>
2161 void InstX86StoreP<Machine>::dump(const Cfg *Func) const {
2162 if (!BuildDefs::dump())
2164 Ostream &Str = Func->getContext()->getStrDump();
2165 Str << "storep." << this->getSrc(0)->getType() << " ";
2166 this->getSrc(1)->dump(Func);
2168 this->getSrc(0)->dump(Func);
2171 template <class Machine>
2172 void InstX86StoreQ<Machine>::emit(const Cfg *Func) const {
2173 if (!BuildDefs::dump())
2175 Ostream &Str = Func->getContext()->getStrEmit();
2176 assert(this->getSrcSize() == 2);
2177 assert(this->getSrc(1)->getType() == IceType_i64 ||
2178 this->getSrc(1)->getType() == IceType_f64);
2180 this->getSrc(0)->emit(Func);
2182 this->getSrc(1)->emit(Func);
2185 template <class Machine>
2186 void InstX86StoreQ<Machine>::emitIAS(const Cfg *Func) const {
2187 typename InstX86Base<Machine>::Traits::Assembler *Asm =
2188 Func->getAssembler<typename InstX86Base<Machine>::Traits::Assembler>();
2189 assert(this->getSrcSize() == 2);
2190 const auto SrcVar = llvm::cast<Variable>(this->getSrc(0));
2191 const auto DestMem =
2192 llvm::cast<typename InstX86Base<Machine>::Traits::X86OperandMem>(
2194 assert(DestMem->getSegmentRegister() ==
2195 InstX86Base<Machine>::Traits::X86OperandMem::DefaultSegment);
2196 assert(SrcVar->hasReg());
2197 Asm->movq(DestMem->toAsmAddress(Asm),
2198 InstX86Base<Machine>::Traits::RegisterSet::getEncodedXmm(
2199 SrcVar->getRegNum()));
2202 template <class Machine>
2203 void InstX86StoreQ<Machine>::dump(const Cfg *Func) const {
2204 if (!BuildDefs::dump())
2206 Ostream &Str = Func->getContext()->getStrDump();
2207 Str << "storeq." << this->getSrc(0)->getType() << " ";
2208 this->getSrc(1)->dump(Func);
2210 this->getSrc(0)->dump(Func);
2213 template <class Machine> void InstX86Lea<Machine>::emit(const Cfg *Func) const {
2214 if (!BuildDefs::dump())
2216 Ostream &Str = Func->getContext()->getStrEmit();
2217 assert(this->getSrcSize() == 1);
2218 assert(this->getDest()->hasReg());
2220 Operand *Src0 = this->getSrc(0);
2221 if (const auto Src0Var = llvm::dyn_cast<Variable>(Src0)) {
2222 Type Ty = Src0Var->getType();
2223 // lea on x86-32 doesn't accept mem128 operands, so cast VSrc0 to an
2225 Src0Var->asType(isVectorType(Ty) ? IceType_i32 : Ty)->emit(Func);
2230 this->getDest()->emit(Func);
2233 template <class Machine> void InstX86Mov<Machine>::emit(const Cfg *Func) const {
2234 if (!BuildDefs::dump())
2236 Ostream &Str = Func->getContext()->getStrEmit();
2237 assert(this->getSrcSize() == 1);
2238 Operand *Src = this->getSrc(0);
2239 Type SrcTy = Src->getType();
2240 Type DestTy = this->getDest()->getType();
2242 << (!isScalarFloatingType(DestTy)
2243 ? this->getWidthString(SrcTy)
2244 : InstX86Base<Machine>::Traits::TypeAttributes[DestTy].SdSsString)
2246 // For an integer truncation operation, src is wider than dest.
2247 // Ideally, we use a mov instruction whose data width matches the
2248 // narrower dest. This is a problem if e.g. src is a register like
2249 // esi or si where there is no 8-bit version of the register. To be
2250 // safe, we instead widen the dest to match src. This works even
2251 // for stack-allocated dest variables because typeWidthOnStack()
2252 // pads to a 4-byte boundary even if only a lower portion is used.
2253 // TODO: This assert disallows usages such as copying a floating point
2254 // value between a vector and a scalar (which movss is used for).
2256 assert(Func->getTarget()->typeWidthInBytesOnStack(DestTy) ==
2257 Func->getTarget()->typeWidthInBytesOnStack(SrcTy));
2260 this->getDest()->asType(SrcTy)->emit(Func);
2263 template <class Machine>
2264 void InstX86Mov<Machine>::emitIAS(const Cfg *Func) const {
2265 assert(this->getSrcSize() == 1);
2266 const Variable *Dest = this->getDest();
2267 const Operand *Src = this->getSrc(0);
2268 Type DestTy = Dest->getType();
2269 Type SrcTy = Src->getType();
2270 // Mov can be used for GPRs or XMM registers. Also, the type does not
2271 // necessarily match (Mov can be used for bitcasts). However, when
2272 // the type does not match, one of the operands must be a register.
2273 // Thus, the strategy is to find out if Src or Dest are a register,
2274 // then use that register's type to decide on which emitter set to use.
2275 // The emitter set will include reg-reg movs, but that case should
2276 // be unused when the types don't match.
2277 static const typename InstX86Base<Machine>::Traits::Assembler::XmmEmitterRegOp
2278 XmmRegEmitter = {&InstX86Base<Machine>::Traits::Assembler::movss,
2279 &InstX86Base<Machine>::Traits::Assembler::movss};
2280 static const typename InstX86Base<Machine>::Traits::Assembler::GPREmitterRegOp
2281 GPRRegEmitter = {&InstX86Base<Machine>::Traits::Assembler::mov,
2282 &InstX86Base<Machine>::Traits::Assembler::mov,
2283 &InstX86Base<Machine>::Traits::Assembler::mov};
2284 static const typename InstX86Base<
2285 Machine>::Traits::Assembler::GPREmitterAddrOp GPRAddrEmitter = {
2286 &InstX86Base<Machine>::Traits::Assembler::mov,
2287 &InstX86Base<Machine>::Traits::Assembler::mov};
2288 // For an integer truncation operation, src is wider than dest.
2289 // Ideally, we use a mov instruction whose data width matches the
2290 // narrower dest. This is a problem if e.g. src is a register like
2291 // esi or si where there is no 8-bit version of the register. To be
2292 // safe, we instead widen the dest to match src. This works even
2293 // for stack-allocated dest variables because typeWidthOnStack()
2294 // pads to a 4-byte boundary even if only a lower portion is used.
2295 // TODO: This assert disallows usages such as copying a floating point
2296 // value between a vector and a scalar (which movss is used for).
2299 Func->getTarget()->typeWidthInBytesOnStack(this->getDest()->getType()) ==
2300 Func->getTarget()->typeWidthInBytesOnStack(Src->getType()));
2301 if (Dest->hasReg()) {
2302 if (isScalarFloatingType(DestTy)) {
2303 emitIASRegOpTyXMM<Machine>(Func, DestTy, Dest, Src, XmmRegEmitter);
2306 assert(isScalarIntegerType(DestTy));
2307 // Widen DestTy for truncation (see above note). We should only do this
2308 // when both Src and Dest are integer types.
2309 if (isScalarIntegerType(SrcTy)) {
2312 emitIASRegOpTyGPR<Machine>(Func, DestTy, Dest, Src, GPRRegEmitter);
2316 // Dest must be Stack and Src *could* be a register. Use Src's type
2317 // to decide on the emitters.
2318 typename InstX86Base<Machine>::Traits::Address StackAddr(
2319 static_cast<typename InstX86Base<Machine>::Traits::TargetLowering *>(
2321 ->stackVarToAsmOperand(Dest));
2322 if (isScalarFloatingType(SrcTy)) {
2323 // Src must be a register.
2324 const auto SrcVar = llvm::cast<Variable>(Src);
2325 assert(SrcVar->hasReg());
2326 typename InstX86Base<Machine>::Traits::Assembler *Asm =
2328 typename InstX86Base<Machine>::Traits::Assembler>();
2329 Asm->movss(SrcTy, StackAddr,
2330 InstX86Base<Machine>::Traits::RegisterSet::getEncodedXmm(
2331 SrcVar->getRegNum()));
2334 // Src can be a register or immediate.
2335 assert(isScalarIntegerType(SrcTy));
2336 emitIASAddrOpTyGPR<Machine>(Func, SrcTy, StackAddr, Src, GPRAddrEmitter);
2343 template <class Machine>
2344 void InstX86Movd<Machine>::emitIAS(const Cfg *Func) const {
2345 typename InstX86Base<Machine>::Traits::Assembler *Asm =
2346 Func->getAssembler<typename InstX86Base<Machine>::Traits::Assembler>();
2347 assert(this->getSrcSize() == 1);
2348 const Variable *Dest = this->getDest();
2349 const auto SrcVar = llvm::cast<Variable>(this->getSrc(0));
2350 // For insert/extract element (one of Src/Dest is an Xmm vector and
2351 // the other is an int type).
2352 if (SrcVar->getType() == IceType_i32) {
2353 assert(isVectorType(Dest->getType()));
2354 assert(Dest->hasReg());
2355 typename InstX86Base<Machine>::Traits::RegisterSet::XmmRegister DestReg =
2356 InstX86Base<Machine>::Traits::RegisterSet::getEncodedXmm(
2358 if (SrcVar->hasReg()) {
2360 InstX86Base<Machine>::Traits::RegisterSet::getEncodedGPR(
2361 SrcVar->getRegNum()));
2363 typename InstX86Base<Machine>::Traits::Address StackAddr(
2364 static_cast<typename InstX86Base<Machine>::Traits::TargetLowering *>(
2366 ->stackVarToAsmOperand(SrcVar));
2367 Asm->movd(DestReg, StackAddr);
2370 assert(isVectorType(SrcVar->getType()));
2371 assert(SrcVar->hasReg());
2372 assert(Dest->getType() == IceType_i32);
2373 typename InstX86Base<Machine>::Traits::RegisterSet::XmmRegister SrcReg =
2374 InstX86Base<Machine>::Traits::RegisterSet::getEncodedXmm(
2375 SrcVar->getRegNum());
2376 if (Dest->hasReg()) {
2377 Asm->movd(InstX86Base<Machine>::Traits::RegisterSet::getEncodedGPR(
2381 typename InstX86Base<Machine>::Traits::Address StackAddr(
2382 static_cast<typename InstX86Base<Machine>::Traits::TargetLowering *>(
2384 ->stackVarToAsmOperand(Dest));
2385 Asm->movd(StackAddr, SrcReg);
2390 template <class Machine>
2391 void InstX86Movp<Machine>::emit(const Cfg *Func) const {
2392 if (!BuildDefs::dump())
2394 // TODO(wala,stichnot): movups works with all vector operands, but
2395 // there exist other instructions (movaps, movdqa, movdqu) that may
2396 // perform better, depending on the data type and alignment of the
2398 Ostream &Str = Func->getContext()->getStrEmit();
2399 assert(this->getSrcSize() == 1);
2400 Str << "\tmovups\t";
2401 this->getSrc(0)->emit(Func);
2403 this->getDest()->emit(Func);
2406 template <class Machine>
2407 void InstX86Movp<Machine>::emitIAS(const Cfg *Func) const {
2408 assert(this->getSrcSize() == 1);
2409 assert(isVectorType(this->getDest()->getType()));
2410 const Variable *Dest = this->getDest();
2411 const Operand *Src = this->getSrc(0);
2412 static const typename InstX86Base<
2413 Machine>::Traits::Assembler::XmmEmitterMovOps Emitter = {
2414 &InstX86Base<Machine>::Traits::Assembler::movups,
2415 &InstX86Base<Machine>::Traits::Assembler::movups,
2416 &InstX86Base<Machine>::Traits::Assembler::movups};
2417 emitIASMovlikeXMM<Machine>(Func, Dest, Src, Emitter);
2420 template <class Machine>
2421 void InstX86Movq<Machine>::emit(const Cfg *Func) const {
2422 if (!BuildDefs::dump())
2424 Ostream &Str = Func->getContext()->getStrEmit();
2425 assert(this->getSrcSize() == 1);
2426 assert(this->getDest()->getType() == IceType_i64 ||
2427 this->getDest()->getType() == IceType_f64);
2429 this->getSrc(0)->emit(Func);
2431 this->getDest()->emit(Func);
2434 template <class Machine>
2435 void InstX86Movq<Machine>::emitIAS(const Cfg *Func) const {
2436 assert(this->getSrcSize() == 1);
2437 assert(this->getDest()->getType() == IceType_i64 ||
2438 this->getDest()->getType() == IceType_f64);
2439 const Variable *Dest = this->getDest();
2440 const Operand *Src = this->getSrc(0);
2441 static const typename InstX86Base<
2442 Machine>::Traits::Assembler::XmmEmitterMovOps Emitter = {
2443 &InstX86Base<Machine>::Traits::Assembler::movq,
2444 &InstX86Base<Machine>::Traits::Assembler::movq,
2445 &InstX86Base<Machine>::Traits::Assembler::movq};
2446 emitIASMovlikeXMM<Machine>(Func, Dest, Src, Emitter);
2449 template <class Machine>
2450 void InstX86MovssRegs<Machine>::emitIAS(const Cfg *Func) const {
2451 // This is Binop variant is only intended to be used for reg-reg moves
2452 // where part of the Dest register is untouched.
2453 assert(this->getSrcSize() == 2);
2454 const Variable *Dest = this->getDest();
2455 assert(Dest == this->getSrc(0));
2456 const auto SrcVar = llvm::cast<Variable>(this->getSrc(1));
2457 assert(Dest->hasReg() && SrcVar->hasReg());
2458 typename InstX86Base<Machine>::Traits::Assembler *Asm =
2459 Func->getAssembler<typename InstX86Base<Machine>::Traits::Assembler>();
2460 Asm->movss(IceType_f32,
2461 InstX86Base<Machine>::Traits::RegisterSet::getEncodedXmm(
2463 InstX86Base<Machine>::Traits::RegisterSet::getEncodedXmm(
2464 SrcVar->getRegNum()));
2467 template <class Machine>
2468 void InstX86Movsx<Machine>::emitIAS(const Cfg *Func) const {
2469 assert(this->getSrcSize() == 1);
2470 const Variable *Dest = this->getDest();
2471 const Operand *Src = this->getSrc(0);
2472 // Dest must be a > 8-bit register, but Src can be 8-bit. In practice
2473 // we just use the full register for Dest to avoid having an
2474 // OperandSizeOverride prefix. It also allows us to only dispatch on SrcTy.
2475 Type SrcTy = Src->getType();
2476 assert(typeWidthInBytes(Dest->getType()) > 1);
2477 assert(typeWidthInBytes(Dest->getType()) > typeWidthInBytes(SrcTy));
2478 emitIASRegOpTyGPR<Machine, false, true>(Func, SrcTy, Dest, Src,
2482 template <class Machine>
2483 void InstX86Movzx<Machine>::emitIAS(const Cfg *Func) const {
2484 assert(this->getSrcSize() == 1);
2485 const Variable *Dest = this->getDest();
2486 const Operand *Src = this->getSrc(0);
2487 Type SrcTy = Src->getType();
2488 assert(typeWidthInBytes(Dest->getType()) > 1);
2489 assert(typeWidthInBytes(Dest->getType()) > typeWidthInBytes(SrcTy));
2490 emitIASRegOpTyGPR<Machine, false, true>(Func, SrcTy, Dest, Src,
2494 template <class Machine> void InstX86Nop<Machine>::emit(const Cfg *Func) const {
2495 if (!BuildDefs::dump())
2497 Ostream &Str = Func->getContext()->getStrEmit();
2498 // TODO: Emit the right code for each variant.
2499 Str << "\tnop\t# variant = " << Variant;
2502 template <class Machine>
2503 void InstX86Nop<Machine>::emitIAS(const Cfg *Func) const {
2504 typename InstX86Base<Machine>::Traits::Assembler *Asm =
2505 Func->getAssembler<typename InstX86Base<Machine>::Traits::Assembler>();
2506 // TODO: Emit the right code for the variant.
2510 template <class Machine> void InstX86Nop<Machine>::dump(const Cfg *Func) const {
2511 if (!BuildDefs::dump())
2513 Ostream &Str = Func->getContext()->getStrDump();
2514 Str << "nop (variant = " << Variant << ")";
2517 template <class Machine> void InstX86Fld<Machine>::emit(const Cfg *Func) const {
2518 if (!BuildDefs::dump())
2520 Ostream &Str = Func->getContext()->getStrEmit();
2521 assert(this->getSrcSize() == 1);
2522 Type Ty = this->getSrc(0)->getType();
2523 SizeT Width = typeWidthInBytes(Ty);
2524 const auto Var = llvm::dyn_cast<Variable>(this->getSrc(0));
2525 if (Var && Var->hasReg()) {
2526 // This is a physical xmm register, so we need to spill it to a
2527 // temporary stack slot.
2528 Str << "\tsubl\t$" << Width << ", %esp"
2531 << InstX86Base<Machine>::Traits::TypeAttributes[Ty].SdSsString << "\t";
2533 Str << ", (%esp)\n";
2534 Str << "\tfld" << this->getFldString(Ty) << "\t"
2536 Str << "\taddl\t$" << Width << ", %esp";
2539 Str << "\tfld" << this->getFldString(Ty) << "\t";
2540 this->getSrc(0)->emit(Func);
2543 template <class Machine>
2544 void InstX86Fld<Machine>::emitIAS(const Cfg *Func) const {
2545 typename InstX86Base<Machine>::Traits::Assembler *Asm =
2546 Func->getAssembler<typename InstX86Base<Machine>::Traits::Assembler>();
2547 assert(this->getSrcSize() == 1);
2548 const Operand *Src = this->getSrc(0);
2549 Type Ty = Src->getType();
2550 if (const auto Var = llvm::dyn_cast<Variable>(Src)) {
2551 if (Var->hasReg()) {
2552 // This is a physical xmm register, so we need to spill it to a
2553 // temporary stack slot.
2554 Immediate Width(typeWidthInBytes(Ty));
2555 Asm->sub(IceType_i32,
2556 InstX86Base<Machine>::Traits::RegisterSet::Encoded_Reg_esp,
2558 typename InstX86Base<Machine>::Traits::Address StackSlot =
2559 typename InstX86Base<Machine>::Traits::Address(
2560 InstX86Base<Machine>::Traits::RegisterSet::Encoded_Reg_esp, 0);
2561 Asm->movss(Ty, StackSlot,
2562 InstX86Base<Machine>::Traits::RegisterSet::getEncodedXmm(
2564 Asm->fld(Ty, StackSlot);
2565 Asm->add(IceType_i32,
2566 InstX86Base<Machine>::Traits::RegisterSet::Encoded_Reg_esp,
2569 typename InstX86Base<Machine>::Traits::Address StackAddr(
2570 static_cast<typename InstX86Base<Machine>::Traits::TargetLowering *>(
2572 ->stackVarToAsmOperand(Var));
2573 Asm->fld(Ty, StackAddr);
2575 } else if (const auto Mem = llvm::dyn_cast<
2576 typename InstX86Base<Machine>::Traits::X86OperandMem>(Src)) {
2577 assert(Mem->getSegmentRegister() ==
2578 InstX86Base<Machine>::Traits::X86OperandMem::DefaultSegment);
2579 Asm->fld(Ty, Mem->toAsmAddress(Asm));
2580 } else if (const auto Imm = llvm::dyn_cast<Constant>(Src)) {
2581 Asm->fld(Ty, InstX86Base<Machine>::Traits::Address::ofConstPool(Asm, Imm));
2583 llvm_unreachable("Unexpected operand type");
2587 template <class Machine> void InstX86Fld<Machine>::dump(const Cfg *Func) const {
2588 if (!BuildDefs::dump())
2590 Ostream &Str = Func->getContext()->getStrDump();
2591 Str << "fld." << this->getSrc(0)->getType() << " ";
2592 this->dumpSources(Func);
2595 template <class Machine>
2596 void InstX86Fstp<Machine>::emit(const Cfg *Func) const {
2597 if (!BuildDefs::dump())
2599 Ostream &Str = Func->getContext()->getStrEmit();
2600 assert(this->getSrcSize() == 0);
2601 // TODO(jvoung,stichnot): Utilize this by setting Dest to nullptr to
2602 // "partially" delete the fstp if the Dest is unused.
2603 // Even if Dest is unused, the fstp should be kept for the SideEffects
2604 // of popping the stack.
2605 if (!this->getDest()) {
2606 Str << "\tfstp\tst(0)";
2609 Type Ty = this->getDest()->getType();
2610 size_t Width = typeWidthInBytes(Ty);
2611 if (!this->getDest()->hasReg()) {
2612 Str << "\tfstp" << this->getFldString(Ty) << "\t";
2613 this->getDest()->emit(Func);
2616 // Dest is a physical (xmm) register, so st(0) needs to go through
2617 // memory. Hack this by creating a temporary stack slot, spilling
2618 // st(0) there, loading it into the xmm register, and deallocating
2620 Str << "\tsubl\t$" << Width << ", %esp\n";
2621 Str << "\tfstp" << this->getFldString(Ty) << "\t"
2623 Str << "\tmov" << InstX86Base<Machine>::Traits::TypeAttributes[Ty].SdSsString
2626 this->getDest()->emit(Func);
2628 Str << "\taddl\t$" << Width << ", %esp";
2631 template <class Machine>
2632 void InstX86Fstp<Machine>::emitIAS(const Cfg *Func) const {
2633 typename InstX86Base<Machine>::Traits::Assembler *Asm =
2634 Func->getAssembler<typename InstX86Base<Machine>::Traits::Assembler>();
2635 assert(this->getSrcSize() == 0);
2636 const Variable *Dest = this->getDest();
2637 // TODO(jvoung,stichnot): Utilize this by setting Dest to nullptr to
2638 // "partially" delete the fstp if the Dest is unused.
2639 // Even if Dest is unused, the fstp should be kept for the SideEffects
2640 // of popping the stack.
2642 Asm->fstp(InstX86Base<Machine>::Traits::RegisterSet::getEncodedSTReg(0));
2645 Type Ty = Dest->getType();
2646 if (!Dest->hasReg()) {
2647 typename InstX86Base<Machine>::Traits::Address StackAddr(
2648 static_cast<typename InstX86Base<Machine>::Traits::TargetLowering *>(
2650 ->stackVarToAsmOperand(Dest));
2651 Asm->fstp(Ty, StackAddr);
2653 // Dest is a physical (xmm) register, so st(0) needs to go through
2654 // memory. Hack this by creating a temporary stack slot, spilling
2655 // st(0) there, loading it into the xmm register, and deallocating
2657 Immediate Width(typeWidthInBytes(Ty));
2658 Asm->sub(IceType_i32,
2659 InstX86Base<Machine>::Traits::RegisterSet::Encoded_Reg_esp, Width);
2660 typename InstX86Base<Machine>::Traits::Address StackSlot =
2661 typename InstX86Base<Machine>::Traits::Address(
2662 InstX86Base<Machine>::Traits::RegisterSet::Encoded_Reg_esp, 0);
2663 Asm->fstp(Ty, StackSlot);
2664 Asm->movss(Ty, InstX86Base<Machine>::Traits::RegisterSet::getEncodedXmm(
2667 Asm->add(IceType_i32,
2668 InstX86Base<Machine>::Traits::RegisterSet::Encoded_Reg_esp, Width);
2672 template <class Machine>
2673 void InstX86Fstp<Machine>::dump(const Cfg *Func) const {
2674 if (!BuildDefs::dump())
2676 Ostream &Str = Func->getContext()->getStrDump();
2677 this->dumpDest(Func);
2678 Str << " = fstp." << this->getDest()->getType() << ", st(0)";
2681 template <class Machine>
2682 void InstX86Pcmpeq<Machine>::emit(const Cfg *Func) const {
2683 if (!BuildDefs::dump())
2687 buf, llvm::array_lengthof(buf), "pcmpeq%s",
2688 InstX86Base<Machine>::Traits::TypeAttributes[this->getDest()->getType()]
2690 this->emitTwoAddress(buf, this, Func);
2693 template <class Machine>
2694 void InstX86Pcmpgt<Machine>::emit(const Cfg *Func) const {
2695 if (!BuildDefs::dump())
2699 buf, llvm::array_lengthof(buf), "pcmpgt%s",
2700 InstX86Base<Machine>::Traits::TypeAttributes[this->getDest()->getType()]
2702 this->emitTwoAddress(buf, this, Func);
2705 template <class Machine>
2706 void InstX86Pextr<Machine>::emit(const Cfg *Func) const {
2707 if (!BuildDefs::dump())
2709 Ostream &Str = Func->getContext()->getStrEmit();
2710 assert(this->getSrcSize() == 2);
2711 // pextrb and pextrd are SSE4.1 instructions.
2712 assert(this->getSrc(0)->getType() == IceType_v8i16 ||
2713 this->getSrc(0)->getType() == IceType_v8i1 ||
2714 static_cast<typename InstX86Base<Machine>::Traits::TargetLowering *>(
2716 ->getInstructionSet() >= InstX86Base<Machine>::Traits::SSE4_1);
2717 Str << "\t" << this->Opcode
2718 << InstX86Base<Machine>::Traits::TypeAttributes[this->getSrc(0)
2720 .PackString << "\t";
2721 this->getSrc(1)->emit(Func);
2723 this->getSrc(0)->emit(Func);
2725 Variable *Dest = this->getDest();
2726 // pextrw must take a register dest. There is an SSE4.1 version that takes
2727 // a memory dest, but we aren't using it. For uniformity, just restrict
2728 // them all to have a register dest for now.
2729 assert(Dest->hasReg());
2730 Dest->asType(IceType_i32)->emit(Func);
2733 template <class Machine>
2734 void InstX86Pextr<Machine>::emitIAS(const Cfg *Func) const {
2735 assert(this->getSrcSize() == 2);
2736 // pextrb and pextrd are SSE4.1 instructions.
2737 const Variable *Dest = this->getDest();
2738 Type DispatchTy = Dest->getType();
2739 assert(DispatchTy == IceType_i16 ||
2740 static_cast<typename InstX86Base<Machine>::Traits::TargetLowering *>(
2742 ->getInstructionSet() >= InstX86Base<Machine>::Traits::SSE4_1);
2743 // pextrw must take a register dest. There is an SSE4.1 version that takes
2744 // a memory dest, but we aren't using it. For uniformity, just restrict
2745 // them all to have a register dest for now.
2746 assert(Dest->hasReg());
2747 // pextrw's Src(0) must be a register (both SSE4.1 and SSE2).
2748 assert(llvm::cast<Variable>(this->getSrc(0))->hasReg());
2749 static const typename InstX86Base<Machine>::Traits::Assembler::
2750 template ThreeOpImmEmitter<
2751 typename InstX86Base<Machine>::Traits::RegisterSet::GPRRegister,
2752 typename InstX86Base<Machine>::Traits::RegisterSet::XmmRegister>
2753 Emitter = {&InstX86Base<Machine>::Traits::Assembler::pextr, nullptr};
2754 emitIASThreeOpImmOps<
2755 Machine, typename InstX86Base<Machine>::Traits::RegisterSet::GPRRegister,
2756 typename InstX86Base<Machine>::Traits::RegisterSet::XmmRegister,
2757 InstX86Base<Machine>::Traits::RegisterSet::getEncodedGPR,
2758 InstX86Base<Machine>::Traits::RegisterSet::getEncodedXmm>(
2759 Func, DispatchTy, Dest, this->getSrc(0), this->getSrc(1), Emitter);
2762 template <class Machine>
2763 void InstX86Pinsr<Machine>::emit(const Cfg *Func) const {
2764 if (!BuildDefs::dump())
2766 Ostream &Str = Func->getContext()->getStrEmit();
2767 assert(this->getSrcSize() == 3);
2768 // pinsrb and pinsrd are SSE4.1 instructions.
2769 assert(this->getDest()->getType() == IceType_v8i16 ||
2770 this->getDest()->getType() == IceType_v8i1 ||
2771 static_cast<typename InstX86Base<Machine>::Traits::TargetLowering *>(
2773 ->getInstructionSet() >= InstX86Base<Machine>::Traits::SSE4_1);
2774 Str << "\t" << this->Opcode
2776 Machine>::Traits::TypeAttributes[this->getDest()->getType()]
2777 .PackString << "\t";
2778 this->getSrc(2)->emit(Func);
2780 Operand *Src1 = this->getSrc(1);
2781 if (const auto Src1Var = llvm::dyn_cast<Variable>(Src1)) {
2782 // If src1 is a register, it should always be r32.
2783 if (Src1Var->hasReg()) {
2784 Src1Var->asType(IceType_i32)->emit(Func);
2786 Src1Var->emit(Func);
2792 this->getDest()->emit(Func);
2795 template <class Machine>
2796 void InstX86Pinsr<Machine>::emitIAS(const Cfg *Func) const {
2797 assert(this->getSrcSize() == 3);
2798 assert(this->getDest() == this->getSrc(0));
2799 // pinsrb and pinsrd are SSE4.1 instructions.
2800 const Operand *Src0 = this->getSrc(1);
2801 Type DispatchTy = Src0->getType();
2802 assert(DispatchTy == IceType_i16 ||
2803 static_cast<typename InstX86Base<Machine>::Traits::TargetLowering *>(
2805 ->getInstructionSet() >= InstX86Base<Machine>::Traits::SSE4_1);
2806 // If src1 is a register, it should always be r32 (this should fall out
2807 // from the encodings for ByteRegs overlapping the encodings for r32),
2808 // but we have to trust the regalloc to not choose "ah", where it
2810 static const typename InstX86Base<Machine>::Traits::Assembler::
2811 template ThreeOpImmEmitter<
2812 typename InstX86Base<Machine>::Traits::RegisterSet::XmmRegister,
2813 typename InstX86Base<Machine>::Traits::RegisterSet::GPRRegister>
2814 Emitter = {&InstX86Base<Machine>::Traits::Assembler::pinsr,
2815 &InstX86Base<Machine>::Traits::Assembler::pinsr};
2816 emitIASThreeOpImmOps<
2817 Machine, typename InstX86Base<Machine>::Traits::RegisterSet::XmmRegister,
2818 typename InstX86Base<Machine>::Traits::RegisterSet::GPRRegister,
2819 InstX86Base<Machine>::Traits::RegisterSet::getEncodedXmm,
2820 InstX86Base<Machine>::Traits::RegisterSet::getEncodedGPR>(
2821 Func, DispatchTy, this->getDest(), Src0, this->getSrc(2), Emitter);
2824 template <class Machine>
2825 void InstX86Pshufd<Machine>::emitIAS(const Cfg *Func) const {
2826 assert(this->getSrcSize() == 2);
2827 const Variable *Dest = this->getDest();
2828 Type Ty = Dest->getType();
2829 static const typename InstX86Base<Machine>::Traits::Assembler::
2830 template ThreeOpImmEmitter<
2831 typename InstX86Base<Machine>::Traits::RegisterSet::XmmRegister,
2832 typename InstX86Base<Machine>::Traits::RegisterSet::XmmRegister>
2833 Emitter = {&InstX86Base<Machine>::Traits::Assembler::pshufd,
2834 &InstX86Base<Machine>::Traits::Assembler::pshufd};
2835 emitIASThreeOpImmOps<
2836 Machine, typename InstX86Base<Machine>::Traits::RegisterSet::XmmRegister,
2837 typename InstX86Base<Machine>::Traits::RegisterSet::XmmRegister,
2838 InstX86Base<Machine>::Traits::RegisterSet::getEncodedXmm,
2839 InstX86Base<Machine>::Traits::RegisterSet::getEncodedXmm>(
2840 Func, Ty, Dest, this->getSrc(0), this->getSrc(1), Emitter);
2843 template <class Machine>
2844 void InstX86Shufps<Machine>::emitIAS(const Cfg *Func) const {
2845 assert(this->getSrcSize() == 3);
2846 const Variable *Dest = this->getDest();
2847 assert(Dest == this->getSrc(0));
2848 Type Ty = Dest->getType();
2849 static const typename InstX86Base<Machine>::Traits::Assembler::
2850 template ThreeOpImmEmitter<
2851 typename InstX86Base<Machine>::Traits::RegisterSet::XmmRegister,
2852 typename InstX86Base<Machine>::Traits::RegisterSet::XmmRegister>
2853 Emitter = {&InstX86Base<Machine>::Traits::Assembler::shufps,
2854 &InstX86Base<Machine>::Traits::Assembler::shufps};
2855 emitIASThreeOpImmOps<
2856 Machine, typename InstX86Base<Machine>::Traits::RegisterSet::XmmRegister,
2857 typename InstX86Base<Machine>::Traits::RegisterSet::XmmRegister,
2858 InstX86Base<Machine>::Traits::RegisterSet::getEncodedXmm,
2859 InstX86Base<Machine>::Traits::RegisterSet::getEncodedXmm>(
2860 Func, Ty, Dest, this->getSrc(1), this->getSrc(2), Emitter);
2863 template <class Machine> void InstX86Pop<Machine>::emit(const Cfg *Func) const {
2864 if (!BuildDefs::dump())
2866 Ostream &Str = Func->getContext()->getStrEmit();
2867 assert(this->getSrcSize() == 0);
2869 this->getDest()->emit(Func);
2872 template <class Machine>
2873 void InstX86Pop<Machine>::emitIAS(const Cfg *Func) const {
2874 assert(this->getSrcSize() == 0);
2875 typename InstX86Base<Machine>::Traits::Assembler *Asm =
2876 Func->getAssembler<typename InstX86Base<Machine>::Traits::Assembler>();
2877 if (this->getDest()->hasReg()) {
2878 Asm->popl(InstX86Base<Machine>::Traits::RegisterSet::getEncodedGPR(
2879 this->getDest()->getRegNum()));
2882 static_cast<typename InstX86Base<Machine>::Traits::TargetLowering *>(
2884 ->stackVarToAsmOperand(this->getDest()));
2888 template <class Machine> void InstX86Pop<Machine>::dump(const Cfg *Func) const {
2889 if (!BuildDefs::dump())
2891 Ostream &Str = Func->getContext()->getStrDump();
2892 this->dumpDest(Func);
2893 Str << " = pop." << this->getDest()->getType() << " ";
2896 template <class Machine>
2897 void InstX86AdjustStack<Machine>::emit(const Cfg *Func) const {
2898 if (!BuildDefs::dump())
2900 Ostream &Str = Func->getContext()->getStrEmit();
2901 Str << "\tsubl\t$" << Amount << ", %esp";
2902 Func->getTarget()->updateStackAdjustment(Amount);
2905 template <class Machine>
2906 void InstX86AdjustStack<Machine>::emitIAS(const Cfg *Func) const {
2907 typename InstX86Base<Machine>::Traits::Assembler *Asm =
2908 Func->getAssembler<typename InstX86Base<Machine>::Traits::Assembler>();
2909 Asm->sub(IceType_i32,
2910 InstX86Base<Machine>::Traits::RegisterSet::Encoded_Reg_esp,
2912 Func->getTarget()->updateStackAdjustment(Amount);
2915 template <class Machine>
2916 void InstX86AdjustStack<Machine>::dump(const Cfg *Func) const {
2917 if (!BuildDefs::dump())
2919 Ostream &Str = Func->getContext()->getStrDump();
2920 Str << "esp = sub.i32 esp, " << Amount;
2923 template <class Machine>
2924 void InstX86Push<Machine>::emit(const Cfg *Func) const {
2925 if (!BuildDefs::dump())
2927 Ostream &Str = Func->getContext()->getStrEmit();
2928 assert(this->getSrcSize() == 1);
2929 // Push is currently only used for saving GPRs.
2930 const auto Var = llvm::cast<Variable>(this->getSrc(0));
2931 assert(Var->hasReg());
2936 template <class Machine>
2937 void InstX86Push<Machine>::emitIAS(const Cfg *Func) const {
2938 assert(this->getSrcSize() == 1);
2939 // Push is currently only used for saving GPRs.
2940 const auto Var = llvm::cast<Variable>(this->getSrc(0));
2941 assert(Var->hasReg());
2942 typename InstX86Base<Machine>::Traits::Assembler *Asm =
2943 Func->getAssembler<typename InstX86Base<Machine>::Traits::Assembler>();
2944 Asm->pushl(InstX86Base<Machine>::Traits::RegisterSet::getEncodedGPR(
2948 template <class Machine>
2949 void InstX86Push<Machine>::dump(const Cfg *Func) const {
2950 if (!BuildDefs::dump())
2952 Ostream &Str = Func->getContext()->getStrDump();
2953 Str << "push." << this->getSrc(0)->getType() << " ";
2954 this->dumpSources(Func);
2957 template <class Machine>
2958 void InstX86Psll<Machine>::emit(const Cfg *Func) const {
2959 if (!BuildDefs::dump())
2961 assert(this->getDest()->getType() == IceType_v8i16 ||
2962 this->getDest()->getType() == IceType_v8i1 ||
2963 this->getDest()->getType() == IceType_v4i32 ||
2964 this->getDest()->getType() == IceType_v4i1);
2967 buf, llvm::array_lengthof(buf), "psll%s",
2968 InstX86Base<Machine>::Traits::TypeAttributes[this->getDest()->getType()]
2970 this->emitTwoAddress(buf, this, Func);
2973 template <class Machine>
2974 void InstX86Psra<Machine>::emit(const Cfg *Func) const {
2975 if (!BuildDefs::dump())
2977 assert(this->getDest()->getType() == IceType_v8i16 ||
2978 this->getDest()->getType() == IceType_v8i1 ||
2979 this->getDest()->getType() == IceType_v4i32 ||
2980 this->getDest()->getType() == IceType_v4i1);
2983 buf, llvm::array_lengthof(buf), "psra%s",
2984 InstX86Base<Machine>::Traits::TypeAttributes[this->getDest()->getType()]
2986 this->emitTwoAddress(buf, this, Func);
2989 template <class Machine>
2990 void InstX86Psrl<Machine>::emit(const Cfg *Func) const {
2991 if (!BuildDefs::dump())
2995 buf, llvm::array_lengthof(buf), "psrl%s",
2996 InstX86Base<Machine>::Traits::TypeAttributes[this->getDest()->getType()]
2998 this->emitTwoAddress(buf, this, Func);
3001 template <class Machine> void InstX86Ret<Machine>::emit(const Cfg *Func) const {
3002 if (!BuildDefs::dump())
3004 Ostream &Str = Func->getContext()->getStrEmit();
3008 template <class Machine>
3009 void InstX86Ret<Machine>::emitIAS(const Cfg *Func) const {
3010 typename InstX86Base<Machine>::Traits::Assembler *Asm =
3011 Func->getAssembler<typename InstX86Base<Machine>::Traits::Assembler>();
3015 template <class Machine> void InstX86Ret<Machine>::dump(const Cfg *Func) const {
3016 if (!BuildDefs::dump())
3018 Ostream &Str = Func->getContext()->getStrDump();
3020 (this->getSrcSize() == 0 ? IceType_void : this->getSrc(0)->getType());
3021 Str << "ret." << Ty << " ";
3022 this->dumpSources(Func);
3025 template <class Machine>
3026 void InstX86Setcc<Machine>::emit(const Cfg *Func) const {
3027 if (!BuildDefs::dump())
3029 Ostream &Str = Func->getContext()->getStrEmit();
3031 << InstX86Base<Machine>::Traits::InstBrAttributes[Condition].DisplayString
3033 this->Dest->emit(Func);
3036 template <class Machine>
3037 void InstX86Setcc<Machine>::emitIAS(const Cfg *Func) const {
3038 assert(Condition != InstX86Base<Machine>::Traits::Cond::Br_None);
3039 assert(this->getDest()->getType() == IceType_i1);
3040 assert(this->getSrcSize() == 0);
3041 typename InstX86Base<Machine>::Traits::Assembler *Asm =
3042 Func->getAssembler<typename InstX86Base<Machine>::Traits::Assembler>();
3043 if (this->getDest()->hasReg())
3044 Asm->setcc(Condition,
3045 InstX86Base<Machine>::Traits::RegisterSet::getEncodedByteReg(
3046 this->getDest()->getRegNum()));
3050 static_cast<typename InstX86Base<Machine>::Traits::TargetLowering *>(
3052 ->stackVarToAsmOperand(this->getDest()));
3056 template <class Machine>
3057 void InstX86Setcc<Machine>::dump(const Cfg *Func) const {
3058 if (!BuildDefs::dump())
3060 Ostream &Str = Func->getContext()->getStrDump();
3062 << InstX86Base<Machine>::Traits::InstBrAttributes[Condition].DisplayString
3064 this->dumpDest(Func);
3067 template <class Machine>
3068 void InstX86Xadd<Machine>::emit(const Cfg *Func) const {
3069 if (!BuildDefs::dump())
3071 Ostream &Str = Func->getContext()->getStrEmit();
3075 Str << "\txadd" << this->getWidthString(this->getSrc(0)->getType()) << "\t";
3076 this->getSrc(1)->emit(Func);
3078 this->getSrc(0)->emit(Func);
3081 template <class Machine>
3082 void InstX86Xadd<Machine>::emitIAS(const Cfg *Func) const {
3083 assert(this->getSrcSize() == 2);
3084 typename InstX86Base<Machine>::Traits::Assembler *Asm =
3085 Func->getAssembler<typename InstX86Base<Machine>::Traits::Assembler>();
3086 Type Ty = this->getSrc(0)->getType();
3088 llvm::cast<typename InstX86Base<Machine>::Traits::X86OperandMem>(
3090 assert(Mem->getSegmentRegister() ==
3091 InstX86Base<Machine>::Traits::X86OperandMem::DefaultSegment);
3092 const typename InstX86Base<Machine>::Traits::Address Addr =
3093 Mem->toAsmAddress(Asm);
3094 const auto VarReg = llvm::cast<Variable>(this->getSrc(1));
3095 assert(VarReg->hasReg());
3096 const typename InstX86Base<Machine>::Traits::RegisterSet::GPRRegister Reg =
3097 InstX86Base<Machine>::Traits::RegisterSet::getEncodedGPR(
3098 VarReg->getRegNum());
3099 Asm->xadd(Ty, Addr, Reg, this->Locked);
3102 template <class Machine>
3103 void InstX86Xadd<Machine>::dump(const Cfg *Func) const {
3104 if (!BuildDefs::dump())
3106 Ostream &Str = Func->getContext()->getStrDump();
3110 Type Ty = this->getSrc(0)->getType();
3111 Str << "xadd." << Ty << " ";
3112 this->dumpSources(Func);
3115 template <class Machine>
3116 void InstX86Xchg<Machine>::emit(const Cfg *Func) const {
3117 if (!BuildDefs::dump())
3119 Ostream &Str = Func->getContext()->getStrEmit();
3120 Str << "\txchg" << this->getWidthString(this->getSrc(0)->getType()) << "\t";
3121 this->getSrc(1)->emit(Func);
3123 this->getSrc(0)->emit(Func);
3126 template <class Machine>
3127 void InstX86Xchg<Machine>::emitIAS(const Cfg *Func) const {
3128 assert(this->getSrcSize() == 2);
3129 typename InstX86Base<Machine>::Traits::Assembler *Asm =
3130 Func->getAssembler<typename InstX86Base<Machine>::Traits::Assembler>();
3131 Type Ty = this->getSrc(0)->getType();
3133 llvm::cast<typename InstX86Base<Machine>::Traits::X86OperandMem>(
3135 assert(Mem->getSegmentRegister() ==
3136 InstX86Base<Machine>::Traits::X86OperandMem::DefaultSegment);
3137 const typename InstX86Base<Machine>::Traits::Address Addr =
3138 Mem->toAsmAddress(Asm);
3139 const auto VarReg = llvm::cast<Variable>(this->getSrc(1));
3140 assert(VarReg->hasReg());
3141 const typename InstX86Base<Machine>::Traits::RegisterSet::GPRRegister Reg =
3142 InstX86Base<Machine>::Traits::RegisterSet::getEncodedGPR(
3143 VarReg->getRegNum());
3144 Asm->xchg(Ty, Addr, Reg);
3147 template <class Machine>
3148 void InstX86Xchg<Machine>::dump(const Cfg *Func) const {
3149 if (!BuildDefs::dump())
3151 Ostream &Str = Func->getContext()->getStrDump();
3152 Type Ty = this->getSrc(0)->getType();
3153 Str << "xchg." << Ty << " ";
3154 this->dumpSources(Func);
3157 } // end of namespace X86Internal
3159 } // end of namespace Ice
3161 #endif // SUBZERO_SRC_ICEINSTX86BASEIMPL_H