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 template <class Machine>
371 InstX86IacaStart<Machine>::InstX86IacaStart(Cfg *Func)
372 : InstX86Base<Machine>(Func, InstX86Base<Machine>::IacaStart, 0, nullptr) {
373 assert(Func->getContext()->getFlags().getAllowIacaMarks());
376 template <class Machine>
377 InstX86IacaEnd<Machine>::InstX86IacaEnd(Cfg *Func)
378 : InstX86Base<Machine>(Func, InstX86Base<Machine>::IacaEnd, 0, nullptr) {
379 assert(Func->getContext()->getFlags().getAllowIacaMarks());
382 // ======================== Dump routines ======================== //
384 template <class Machine>
385 void InstX86Base<Machine>::dump(const Cfg *Func) const {
386 if (!BuildDefs::dump())
388 Ostream &Str = Func->getContext()->getStrDump();
389 Str << "[" << Traits::TargetName << "] ";
393 template <class Machine>
394 void InstX86FakeRMW<Machine>::dump(const Cfg *Func) const {
395 if (!BuildDefs::dump())
397 Ostream &Str = Func->getContext()->getStrDump();
398 Type Ty = getData()->getType();
399 Str << "rmw " << InstArithmetic::getOpName(getOp()) << " " << Ty << " *";
400 getAddr()->dump(Func);
402 getData()->dump(Func);
404 getBeacon()->dump(Func);
407 template <class Machine>
408 void InstX86Label<Machine>::emit(const Cfg *Func) const {
409 if (!BuildDefs::dump())
411 Ostream &Str = Func->getContext()->getStrEmit();
412 Str << getName(Func) << ":";
415 template <class Machine>
416 void InstX86Label<Machine>::emitIAS(const Cfg *Func) const {
417 typename InstX86Base<Machine>::Traits::Assembler *Asm =
418 Func->getAssembler<typename InstX86Base<Machine>::Traits::Assembler>();
419 Asm->bindLocalLabel(Number);
422 template <class Machine>
423 void InstX86Label<Machine>::dump(const Cfg *Func) const {
424 if (!BuildDefs::dump())
426 Ostream &Str = Func->getContext()->getStrDump();
427 Str << getName(Func) << ":";
430 template <class Machine> void InstX86Br<Machine>::emit(const Cfg *Func) const {
431 if (!BuildDefs::dump())
433 Ostream &Str = Func->getContext()->getStrEmit();
436 if (Condition == InstX86Base<Machine>::Traits::Cond::Br_None) {
439 Str << InstX86Base<Machine>::Traits::InstBrAttributes[Condition].EmitString;
443 Str << "\t" << Label->getName(Func);
445 if (Condition == InstX86Base<Machine>::Traits::Cond::Br_None) {
446 Str << "\t" << getTargetFalse()->getAsmName();
448 Str << "\t" << getTargetTrue()->getAsmName();
449 if (getTargetFalse()) {
450 Str << "\n\tjmp\t" << getTargetFalse()->getAsmName();
456 template <class Machine>
457 void InstX86Br<Machine>::emitIAS(const Cfg *Func) const {
458 typename InstX86Base<Machine>::Traits::Assembler *Asm =
459 Func->getAssembler<typename InstX86Base<Machine>::Traits::Assembler>();
461 class Label *L = Asm->getOrCreateLocalLabel(Label->getNumber());
462 if (Condition == InstX86Base<Machine>::Traits::Cond::Br_None) {
463 Asm->jmp(L, isNear());
465 Asm->j(Condition, L, isNear());
468 if (Condition == InstX86Base<Machine>::Traits::Cond::Br_None) {
470 Asm->getOrCreateCfgNodeLabel(getTargetFalse()->getIndex());
471 assert(!getTargetTrue());
472 Asm->jmp(L, isNear());
475 Asm->getOrCreateCfgNodeLabel(getTargetTrue()->getIndex());
476 Asm->j(Condition, L, isNear());
477 if (getTargetFalse()) {
479 Asm->getOrCreateCfgNodeLabel(getTargetFalse()->getIndex());
480 Asm->jmp(L2, isNear());
486 template <class Machine> void InstX86Br<Machine>::dump(const Cfg *Func) const {
487 if (!BuildDefs::dump())
489 Ostream &Str = Func->getContext()->getStrDump();
492 if (Condition == InstX86Base<Machine>::Traits::Cond::Br_None) {
494 << (Label ? Label->getName(Func) : getTargetFalse()->getName());
498 Str << InstX86Base<Machine>::Traits::InstBrAttributes[Condition]
501 Str << ", label %" << Label->getName(Func);
503 Str << ", label %" << getTargetTrue()->getName();
504 if (getTargetFalse()) {
505 Str << ", label %" << getTargetFalse()->getName();
509 Str << " // (" << (isNear() ? "near" : "far") << " jump)";
512 template <class Machine> void InstX86Jmp<Machine>::emit(const Cfg *Func) const {
513 if (!BuildDefs::dump())
515 Ostream &Str = Func->getContext()->getStrEmit();
516 assert(this->getSrcSize() == 1);
518 getJmpTarget()->emit(Func);
521 template <class Machine>
522 void InstX86Jmp<Machine>::emitIAS(const Cfg *Func) const {
523 // Note: Adapted (mostly copied) from InstX86Call<Machine>::emitIAS().
524 typename InstX86Base<Machine>::Traits::Assembler *Asm =
525 Func->getAssembler<typename InstX86Base<Machine>::Traits::Assembler>();
526 Operand *Target = getJmpTarget();
527 if (const auto Var = llvm::dyn_cast<Variable>(Target)) {
529 Asm->jmp(InstX86Base<Machine>::Traits::RegisterSet::getEncodedGPR(
532 // The jmp instruction with a memory operand should be possible
533 // to encode, but it isn't a valid sandboxed instruction, and
534 // there shouldn't be a register allocation issue to jump
535 // through a scratch register, so we don't really need to bother
537 llvm::report_fatal_error("Assembler can't jmp to memory operand");
539 } else if (const auto Mem = llvm::dyn_cast<
540 typename InstX86Base<Machine>::Traits::X86OperandMem>(
543 assert(Mem->getSegmentRegister() ==
544 InstX86Base<Machine>::Traits::X86OperandMem::DefaultSegment);
545 llvm::report_fatal_error("Assembler can't jmp to memory operand");
546 } else if (const auto CR = llvm::dyn_cast<ConstantRelocatable>(Target)) {
547 assert(CR->getOffset() == 0 && "We only support jumping to a function");
549 } else if (const auto Imm = llvm::dyn_cast<ConstantInteger32>(Target)) {
550 // NaCl trampoline calls refer to an address within the sandbox directly.
551 // This is usually only needed for non-IRT builds and otherwise not
552 // very portable or stable. Usually this is only done for "calls"
554 // TODO(jvoung): Support this when there is a lowering that
555 // actually triggers this case.
557 llvm::report_fatal_error("Unexpected jmp to absolute address");
559 llvm::report_fatal_error("Unexpected operand type");
563 template <class Machine> void InstX86Jmp<Machine>::dump(const Cfg *Func) const {
564 if (!BuildDefs::dump())
566 Ostream &Str = Func->getContext()->getStrDump();
568 getJmpTarget()->dump(Func);
571 template <class Machine>
572 void InstX86Call<Machine>::emit(const Cfg *Func) const {
573 if (!BuildDefs::dump())
575 Ostream &Str = Func->getContext()->getStrEmit();
576 assert(this->getSrcSize() == 1);
578 if (const auto CI = llvm::dyn_cast<ConstantInteger32>(getCallTarget())) {
579 // Emit without a leading '$'.
580 Str << CI->getValue();
581 } else if (const auto CallTarget =
582 llvm::dyn_cast<ConstantRelocatable>(getCallTarget())) {
583 CallTarget->emitWithoutPrefix(Func->getTarget());
586 getCallTarget()->emit(Func);
588 Func->getTarget()->resetStackAdjustment();
591 template <class Machine>
592 void InstX86Call<Machine>::emitIAS(const Cfg *Func) const {
593 typename InstX86Base<Machine>::Traits::Assembler *Asm =
594 Func->getAssembler<typename InstX86Base<Machine>::Traits::Assembler>();
595 Operand *Target = getCallTarget();
596 if (const auto Var = llvm::dyn_cast<Variable>(Target)) {
598 Asm->call(InstX86Base<Machine>::Traits::RegisterSet::getEncodedGPR(
602 static_cast<typename InstX86Base<Machine>::Traits::TargetLowering *>(
604 ->stackVarToAsmOperand(Var));
606 } else if (const auto Mem = llvm::dyn_cast<
607 typename InstX86Base<Machine>::Traits::X86OperandMem>(
609 assert(Mem->getSegmentRegister() ==
610 InstX86Base<Machine>::Traits::X86OperandMem::DefaultSegment);
611 Asm->call(Mem->toAsmAddress(Asm));
612 } else if (const auto CR = llvm::dyn_cast<ConstantRelocatable>(Target)) {
613 assert(CR->getOffset() == 0 && "We only support calling a function");
615 } else if (const auto Imm = llvm::dyn_cast<ConstantInteger32>(Target)) {
616 Asm->call(Immediate(Imm->getValue()));
618 llvm_unreachable("Unexpected operand type");
620 Func->getTarget()->resetStackAdjustment();
623 template <class Machine>
624 void InstX86Call<Machine>::dump(const Cfg *Func) const {
625 if (!BuildDefs::dump())
627 Ostream &Str = Func->getContext()->getStrDump();
628 if (this->getDest()) {
629 this->dumpDest(Func);
633 getCallTarget()->dump(Func);
636 // The ShiftHack parameter is used to emit "cl" instead of "ecx" for
637 // shift instructions, in order to be syntactically valid. The
638 // this->Opcode parameter needs to be char* and not IceString because of
640 template <class Machine>
641 void InstX86Base<Machine>::emitTwoAddress(const char *Opcode, const Inst *Inst,
642 const Cfg *Func, bool ShiftHack) {
643 if (!BuildDefs::dump())
645 Ostream &Str = Func->getContext()->getStrEmit();
646 assert(Inst->getSrcSize() == 2);
647 Operand *Dest = Inst->getDest();
649 Dest = Inst->getSrc(0);
650 assert(Dest == Inst->getSrc(0));
651 Operand *Src1 = Inst->getSrc(1);
652 Str << "\t" << Opcode << InstX86Base<Machine>::getWidthString(Dest->getType())
654 const auto ShiftReg = llvm::dyn_cast<Variable>(Src1);
655 if (ShiftHack && ShiftReg &&
656 ShiftReg->getRegNum() ==
657 InstX86Base<Machine>::Traits::RegisterSet::Reg_ecx)
665 template <class Machine>
666 void emitIASOpTyGPR(const Cfg *Func, Type Ty, const Operand *Op,
667 const typename InstX86Base<
668 Machine>::Traits::Assembler::GPREmitterOneOp &Emitter) {
669 typename InstX86Base<Machine>::Traits::Assembler *Asm =
670 Func->getAssembler<typename InstX86Base<Machine>::Traits::Assembler>();
671 if (const auto Var = llvm::dyn_cast<Variable>(Op)) {
673 // We cheat a little and use GPRRegister even for byte operations.
674 typename InstX86Base<Machine>::Traits::RegisterSet::GPRRegister VarReg =
675 InstX86Base<Machine>::Traits::RegisterSet::getEncodedByteRegOrGPR(
676 Ty, Var->getRegNum());
677 (Asm->*(Emitter.Reg))(Ty, VarReg);
679 typename InstX86Base<Machine>::Traits::Address StackAddr(
680 static_cast<typename InstX86Base<Machine>::Traits::TargetLowering *>(
682 ->stackVarToAsmOperand(Var));
683 (Asm->*(Emitter.Addr))(Ty, StackAddr);
685 } else if (const auto Mem = llvm::dyn_cast<
686 typename InstX86Base<Machine>::Traits::X86OperandMem>(Op)) {
687 Mem->emitSegmentOverride(Asm);
688 (Asm->*(Emitter.Addr))(Ty, Mem->toAsmAddress(Asm));
690 llvm_unreachable("Unexpected operand type");
694 template <class Machine, bool VarCanBeByte, bool SrcCanBeByte>
695 void emitIASRegOpTyGPR(
696 const Cfg *Func, Type Ty, const Variable *Var, const Operand *Src,
697 const typename InstX86Base<Machine>::Traits::Assembler::GPREmitterRegOp
699 typename InstX86Base<Machine>::Traits::Assembler *Asm =
700 Func->getAssembler<typename InstX86Base<Machine>::Traits::Assembler>();
701 assert(Var->hasReg());
702 // We cheat a little and use GPRRegister even for byte operations.
703 typename InstX86Base<Machine>::Traits::RegisterSet::GPRRegister VarReg =
705 ? InstX86Base<Machine>::Traits::RegisterSet::getEncodedByteRegOrGPR(
706 Ty, Var->getRegNum())
707 : InstX86Base<Machine>::Traits::RegisterSet::getEncodedGPR(
709 if (const auto SrcVar = llvm::dyn_cast<Variable>(Src)) {
710 if (SrcVar->hasReg()) {
711 typename InstX86Base<Machine>::Traits::RegisterSet::GPRRegister SrcReg =
713 ? InstX86Base<Machine>::Traits::RegisterSet::
714 getEncodedByteRegOrGPR(Ty, SrcVar->getRegNum())
715 : InstX86Base<Machine>::Traits::RegisterSet::getEncodedGPR(
716 SrcVar->getRegNum());
717 (Asm->*(Emitter.GPRGPR))(Ty, VarReg, SrcReg);
719 typename InstX86Base<Machine>::Traits::Address SrcStackAddr =
720 static_cast<typename InstX86Base<Machine>::Traits::TargetLowering *>(
722 ->stackVarToAsmOperand(SrcVar);
723 (Asm->*(Emitter.GPRAddr))(Ty, VarReg, SrcStackAddr);
725 } else if (const auto Mem = llvm::dyn_cast<
726 typename InstX86Base<Machine>::Traits::X86OperandMem>(Src)) {
727 Mem->emitSegmentOverride(Asm);
728 (Asm->*(Emitter.GPRAddr))(Ty, VarReg, Mem->toAsmAddress(Asm));
729 } else if (const auto Imm = llvm::dyn_cast<ConstantInteger32>(Src)) {
730 (Asm->*(Emitter.GPRImm))(Ty, VarReg, Immediate(Imm->getValue()));
731 } else if (const auto Reloc = llvm::dyn_cast<ConstantRelocatable>(Src)) {
732 AssemblerFixup *Fixup = Asm->createFixup(llvm::ELF::R_386_32, Reloc);
733 (Asm->*(Emitter.GPRImm))(Ty, VarReg, Immediate(Reloc->getOffset(), Fixup));
734 } else if (const auto Split = llvm::dyn_cast<
735 typename InstX86Base<Machine>::Traits::VariableSplit>(Src)) {
736 (Asm->*(Emitter.GPRAddr))(Ty, VarReg, Split->toAsmAddress(Func));
738 llvm_unreachable("Unexpected operand type");
742 template <class Machine>
743 void emitIASAddrOpTyGPR(
744 const Cfg *Func, Type Ty,
745 const typename InstX86Base<Machine>::Traits::Address &Addr,
747 const typename InstX86Base<Machine>::Traits::Assembler::GPREmitterAddrOp
749 typename InstX86Base<Machine>::Traits::Assembler *Asm =
750 Func->getAssembler<typename InstX86Base<Machine>::Traits::Assembler>();
751 // Src can only be Reg or Immediate.
752 if (const auto SrcVar = llvm::dyn_cast<Variable>(Src)) {
753 assert(SrcVar->hasReg());
754 typename InstX86Base<Machine>::Traits::RegisterSet::GPRRegister SrcReg =
755 InstX86Base<Machine>::Traits::RegisterSet::getEncodedByteRegOrGPR(
756 Ty, SrcVar->getRegNum());
757 (Asm->*(Emitter.AddrGPR))(Ty, Addr, SrcReg);
758 } else if (const auto Imm = llvm::dyn_cast<ConstantInteger32>(Src)) {
759 (Asm->*(Emitter.AddrImm))(Ty, Addr, Immediate(Imm->getValue()));
760 } else if (const auto Reloc = llvm::dyn_cast<ConstantRelocatable>(Src)) {
761 AssemblerFixup *Fixup = Asm->createFixup(llvm::ELF::R_386_32, Reloc);
762 (Asm->*(Emitter.AddrImm))(Ty, Addr, Immediate(Reloc->getOffset(), Fixup));
764 llvm_unreachable("Unexpected operand type");
768 template <class Machine>
769 void emitIASAsAddrOpTyGPR(
770 const Cfg *Func, Type Ty, const Operand *Op0, const Operand *Op1,
771 const typename InstX86Base<Machine>::Traits::Assembler::GPREmitterAddrOp
773 if (const auto Op0Var = llvm::dyn_cast<Variable>(Op0)) {
774 assert(!Op0Var->hasReg());
775 typename InstX86Base<Machine>::Traits::Address StackAddr(
776 static_cast<typename InstX86Base<Machine>::Traits::TargetLowering *>(
778 ->stackVarToAsmOperand(Op0Var));
779 emitIASAddrOpTyGPR<Machine>(Func, Ty, StackAddr, Op1, Emitter);
780 } else if (const auto Op0Mem = llvm::dyn_cast<
781 typename InstX86Base<Machine>::Traits::X86OperandMem>(Op0)) {
782 typename InstX86Base<Machine>::Traits::Assembler *Asm =
783 Func->getAssembler<typename InstX86Base<Machine>::Traits::Assembler>();
784 Op0Mem->emitSegmentOverride(Asm);
785 emitIASAddrOpTyGPR<Machine>(Func, Ty, Op0Mem->toAsmAddress(Asm), Op1,
787 } else if (const auto Split = llvm::dyn_cast<
788 typename InstX86Base<Machine>::Traits::VariableSplit>(Op0)) {
789 emitIASAddrOpTyGPR<Machine>(Func, Ty, Split->toAsmAddress(Func), Op1,
792 llvm_unreachable("Unexpected operand type");
796 template <class Machine>
797 void InstX86Base<Machine>::emitIASGPRShift(
798 const Cfg *Func, Type Ty, const Variable *Var, const Operand *Src,
799 const typename InstX86Base<Machine>::Traits::Assembler::GPREmitterShiftOp
801 typename InstX86Base<Machine>::Traits::Assembler *Asm =
802 Func->getAssembler<typename InstX86Base<Machine>::Traits::Assembler>();
803 // Technically, the Dest Var can be mem as well, but we only use Reg.
804 // We can extend this to check Dest if we decide to use that form.
805 assert(Var->hasReg());
806 // We cheat a little and use GPRRegister even for byte operations.
807 typename InstX86Base<Machine>::Traits::RegisterSet::GPRRegister VarReg =
808 InstX86Base<Machine>::Traits::RegisterSet::getEncodedByteRegOrGPR(
809 Ty, Var->getRegNum());
810 // Src must be reg == ECX or an Imm8.
811 // This is asserted by the assembler.
812 if (const auto SrcVar = llvm::dyn_cast<Variable>(Src)) {
813 assert(SrcVar->hasReg());
814 typename InstX86Base<Machine>::Traits::RegisterSet::GPRRegister SrcReg =
815 InstX86Base<Machine>::Traits::RegisterSet::getEncodedByteRegOrGPR(
816 Ty, SrcVar->getRegNum());
817 (Asm->*(Emitter.GPRGPR))(Ty, VarReg, SrcReg);
818 } else if (const auto Imm = llvm::dyn_cast<ConstantInteger32>(Src)) {
819 (Asm->*(Emitter.GPRImm))(Ty, VarReg, Immediate(Imm->getValue()));
821 llvm_unreachable("Unexpected operand type");
825 template <class Machine>
826 void emitIASGPRShiftDouble(
827 const Cfg *Func, const Variable *Dest, const Operand *Src1Op,
828 const Operand *Src2Op,
829 const typename InstX86Base<Machine>::Traits::Assembler::GPREmitterShiftD
831 typename InstX86Base<Machine>::Traits::Assembler *Asm =
832 Func->getAssembler<typename InstX86Base<Machine>::Traits::Assembler>();
833 // Dest can be reg or mem, but we only use the reg variant.
834 assert(Dest->hasReg());
835 typename InstX86Base<Machine>::Traits::RegisterSet::GPRRegister DestReg =
836 InstX86Base<Machine>::Traits::RegisterSet::getEncodedGPR(
838 // SrcVar1 must be reg.
839 const auto SrcVar1 = llvm::cast<Variable>(Src1Op);
840 assert(SrcVar1->hasReg());
841 typename InstX86Base<Machine>::Traits::RegisterSet::GPRRegister SrcReg =
842 InstX86Base<Machine>::Traits::RegisterSet::getEncodedGPR(
843 SrcVar1->getRegNum());
844 Type Ty = SrcVar1->getType();
845 // Src2 can be the implicit CL register or an immediate.
846 if (const auto Imm = llvm::dyn_cast<ConstantInteger32>(Src2Op)) {
847 (Asm->*(Emitter.GPRGPRImm))(Ty, DestReg, SrcReg,
848 Immediate(Imm->getValue()));
850 assert(llvm::cast<Variable>(Src2Op)->getRegNum() ==
851 InstX86Base<Machine>::Traits::RegisterSet::Reg_ecx);
852 (Asm->*(Emitter.GPRGPR))(Ty, DestReg, SrcReg);
856 template <class Machine>
857 void emitIASXmmShift(
858 const Cfg *Func, Type Ty, const Variable *Var, const Operand *Src,
859 const typename InstX86Base<Machine>::Traits::Assembler::XmmEmitterShiftOp
861 typename InstX86Base<Machine>::Traits::Assembler *Asm =
862 Func->getAssembler<typename InstX86Base<Machine>::Traits::Assembler>();
863 assert(Var->hasReg());
864 typename InstX86Base<Machine>::Traits::RegisterSet::XmmRegister VarReg =
865 InstX86Base<Machine>::Traits::RegisterSet::getEncodedXmm(
867 if (const auto SrcVar = llvm::dyn_cast<Variable>(Src)) {
868 if (SrcVar->hasReg()) {
869 typename InstX86Base<Machine>::Traits::RegisterSet::XmmRegister SrcReg =
870 InstX86Base<Machine>::Traits::RegisterSet::getEncodedXmm(
871 SrcVar->getRegNum());
872 (Asm->*(Emitter.XmmXmm))(Ty, VarReg, SrcReg);
874 typename InstX86Base<Machine>::Traits::Address SrcStackAddr =
875 static_cast<typename InstX86Base<Machine>::Traits::TargetLowering *>(
877 ->stackVarToAsmOperand(SrcVar);
878 (Asm->*(Emitter.XmmAddr))(Ty, VarReg, SrcStackAddr);
880 } else if (const auto Mem = llvm::dyn_cast<
881 typename InstX86Base<Machine>::Traits::X86OperandMem>(Src)) {
882 assert(Mem->getSegmentRegister() ==
883 InstX86Base<Machine>::Traits::X86OperandMem::DefaultSegment);
884 (Asm->*(Emitter.XmmAddr))(Ty, VarReg, Mem->toAsmAddress(Asm));
885 } else if (const auto Imm = llvm::dyn_cast<ConstantInteger32>(Src)) {
886 (Asm->*(Emitter.XmmImm))(Ty, VarReg, Immediate(Imm->getValue()));
888 llvm_unreachable("Unexpected operand type");
892 template <class Machine>
893 void emitIASRegOpTyXMM(
894 const Cfg *Func, Type Ty, const Variable *Var, const Operand *Src,
895 const typename InstX86Base<Machine>::Traits::Assembler::XmmEmitterRegOp
897 typename InstX86Base<Machine>::Traits::Assembler *Asm =
898 Func->getAssembler<typename InstX86Base<Machine>::Traits::Assembler>();
899 assert(Var->hasReg());
900 typename InstX86Base<Machine>::Traits::RegisterSet::XmmRegister VarReg =
901 InstX86Base<Machine>::Traits::RegisterSet::getEncodedXmm(
903 if (const auto SrcVar = llvm::dyn_cast<Variable>(Src)) {
904 if (SrcVar->hasReg()) {
905 typename InstX86Base<Machine>::Traits::RegisterSet::XmmRegister SrcReg =
906 InstX86Base<Machine>::Traits::RegisterSet::getEncodedXmm(
907 SrcVar->getRegNum());
908 (Asm->*(Emitter.XmmXmm))(Ty, VarReg, SrcReg);
910 typename InstX86Base<Machine>::Traits::Address SrcStackAddr =
911 static_cast<typename InstX86Base<Machine>::Traits::TargetLowering *>(
913 ->stackVarToAsmOperand(SrcVar);
914 (Asm->*(Emitter.XmmAddr))(Ty, VarReg, SrcStackAddr);
916 } else if (const auto Mem = llvm::dyn_cast<
917 typename InstX86Base<Machine>::Traits::X86OperandMem>(Src)) {
918 assert(Mem->getSegmentRegister() ==
919 InstX86Base<Machine>::Traits::X86OperandMem::DefaultSegment);
920 (Asm->*(Emitter.XmmAddr))(Ty, VarReg, Mem->toAsmAddress(Asm));
921 } else if (const auto Imm = llvm::dyn_cast<Constant>(Src)) {
922 (Asm->*(Emitter.XmmAddr))(
924 InstX86Base<Machine>::Traits::Address::ofConstPool(Asm, Imm));
926 llvm_unreachable("Unexpected operand type");
930 template <class Machine, typename DReg_t, typename SReg_t,
931 DReg_t (*destEnc)(int32_t), SReg_t (*srcEnc)(int32_t)>
932 void emitIASCastRegOp(const Cfg *Func, Type DispatchTy, const Variable *Dest,
934 const typename InstX86Base<Machine>::Traits::Assembler::
935 template CastEmitterRegOp<DReg_t, SReg_t> &Emitter) {
936 typename InstX86Base<Machine>::Traits::Assembler *Asm =
937 Func->getAssembler<typename InstX86Base<Machine>::Traits::Assembler>();
938 assert(Dest->hasReg());
939 DReg_t DestReg = destEnc(Dest->getRegNum());
940 if (const auto SrcVar = llvm::dyn_cast<Variable>(Src)) {
941 if (SrcVar->hasReg()) {
942 SReg_t SrcReg = srcEnc(SrcVar->getRegNum());
943 (Asm->*(Emitter.RegReg))(DispatchTy, DestReg, SrcReg);
945 typename InstX86Base<Machine>::Traits::Address SrcStackAddr =
946 static_cast<typename InstX86Base<Machine>::Traits::TargetLowering *>(
948 ->stackVarToAsmOperand(SrcVar);
949 (Asm->*(Emitter.RegAddr))(DispatchTy, DestReg, SrcStackAddr);
951 } else if (const auto Mem = llvm::dyn_cast<
952 typename InstX86Base<Machine>::Traits::X86OperandMem>(Src)) {
953 Mem->emitSegmentOverride(Asm);
954 (Asm->*(Emitter.RegAddr))(DispatchTy, DestReg, Mem->toAsmAddress(Asm));
956 llvm_unreachable("Unexpected operand type");
960 template <class Machine, typename DReg_t, typename SReg_t,
961 DReg_t (*destEnc)(int32_t), SReg_t (*srcEnc)(int32_t)>
962 void emitIASThreeOpImmOps(
963 const Cfg *Func, Type DispatchTy, const Variable *Dest, const Operand *Src0,
965 const typename InstX86Base<Machine>::Traits::Assembler::
966 template ThreeOpImmEmitter<DReg_t, SReg_t> Emitter) {
967 typename InstX86Base<Machine>::Traits::Assembler *Asm =
968 Func->getAssembler<typename InstX86Base<Machine>::Traits::Assembler>();
969 // This only handles Dest being a register, and Src1 being an immediate.
970 assert(Dest->hasReg());
971 DReg_t DestReg = destEnc(Dest->getRegNum());
972 Immediate Imm(llvm::cast<ConstantInteger32>(Src1)->getValue());
973 if (const auto SrcVar = llvm::dyn_cast<Variable>(Src0)) {
974 if (SrcVar->hasReg()) {
975 SReg_t SrcReg = srcEnc(SrcVar->getRegNum());
976 (Asm->*(Emitter.RegRegImm))(DispatchTy, DestReg, SrcReg, Imm);
978 typename InstX86Base<Machine>::Traits::Address SrcStackAddr =
979 static_cast<typename InstX86Base<Machine>::Traits::TargetLowering *>(
981 ->stackVarToAsmOperand(SrcVar);
982 (Asm->*(Emitter.RegAddrImm))(DispatchTy, DestReg, SrcStackAddr, Imm);
984 } else if (const auto Mem = llvm::dyn_cast<
985 typename InstX86Base<Machine>::Traits::X86OperandMem>(Src0)) {
986 Mem->emitSegmentOverride(Asm);
987 (Asm->*(Emitter.RegAddrImm))(DispatchTy, DestReg, Mem->toAsmAddress(Asm),
990 llvm_unreachable("Unexpected operand type");
994 template <class Machine>
995 void emitIASMovlikeXMM(
996 const Cfg *Func, const Variable *Dest, const Operand *Src,
997 const typename InstX86Base<Machine>::Traits::Assembler::XmmEmitterMovOps
999 typename InstX86Base<Machine>::Traits::Assembler *Asm =
1000 Func->getAssembler<typename InstX86Base<Machine>::Traits::Assembler>();
1001 if (Dest->hasReg()) {
1002 typename InstX86Base<Machine>::Traits::RegisterSet::XmmRegister DestReg =
1003 InstX86Base<Machine>::Traits::RegisterSet::getEncodedXmm(
1005 if (const auto SrcVar = llvm::dyn_cast<Variable>(Src)) {
1006 if (SrcVar->hasReg()) {
1007 (Asm->*(Emitter.XmmXmm))(
1008 DestReg, InstX86Base<Machine>::Traits::RegisterSet::getEncodedXmm(
1009 SrcVar->getRegNum()));
1011 typename InstX86Base<Machine>::Traits::Address StackAddr(
1012 static_cast<typename InstX86Base<Machine>::Traits::TargetLowering
1013 *>(Func->getTarget())
1014 ->stackVarToAsmOperand(SrcVar));
1015 (Asm->*(Emitter.XmmAddr))(DestReg, StackAddr);
1017 } else if (const auto SrcMem = llvm::dyn_cast<
1018 typename InstX86Base<Machine>::Traits::X86OperandMem>(Src)) {
1019 assert(SrcMem->getSegmentRegister() ==
1020 InstX86Base<Machine>::Traits::X86OperandMem::DefaultSegment);
1021 (Asm->*(Emitter.XmmAddr))(DestReg, SrcMem->toAsmAddress(Asm));
1023 llvm_unreachable("Unexpected operand type");
1026 typename InstX86Base<Machine>::Traits::Address StackAddr(
1027 static_cast<typename InstX86Base<Machine>::Traits::TargetLowering *>(
1029 ->stackVarToAsmOperand(Dest));
1030 // Src must be a register in this case.
1031 const auto SrcVar = llvm::cast<Variable>(Src);
1032 assert(SrcVar->hasReg());
1033 (Asm->*(Emitter.AddrXmm))(
1034 StackAddr, InstX86Base<Machine>::Traits::RegisterSet::getEncodedXmm(
1035 SrcVar->getRegNum()));
1039 template <class Machine>
1040 void InstX86Sqrtss<Machine>::emit(const Cfg *Func) const {
1041 if (!BuildDefs::dump())
1043 Ostream &Str = Func->getContext()->getStrEmit();
1044 assert(this->getSrcSize() == 1);
1045 Type Ty = this->getSrc(0)->getType();
1046 assert(isScalarFloatingType(Ty));
1047 Str << "\tsqrt" << InstX86Base<Machine>::Traits::TypeAttributes[Ty].SdSsString
1049 this->getSrc(0)->emit(Func);
1051 this->getDest()->emit(Func);
1054 template <class Machine>
1055 void InstX86Addss<Machine>::emit(const Cfg *Func) const {
1056 if (!BuildDefs::dump())
1060 buf, llvm::array_lengthof(buf), "add%s",
1061 InstX86Base<Machine>::Traits::TypeAttributes[this->getDest()->getType()]
1063 this->emitTwoAddress(buf, this, Func);
1066 template <class Machine>
1067 void InstX86Padd<Machine>::emit(const Cfg *Func) const {
1068 if (!BuildDefs::dump())
1072 buf, llvm::array_lengthof(buf), "padd%s",
1073 InstX86Base<Machine>::Traits::TypeAttributes[this->getDest()->getType()]
1075 this->emitTwoAddress(buf, this, Func);
1078 template <class Machine>
1079 void InstX86Pmull<Machine>::emit(const Cfg *Func) const {
1080 if (!BuildDefs::dump())
1083 bool TypesAreValid = this->getDest()->getType() == IceType_v4i32 ||
1084 this->getDest()->getType() == IceType_v8i16;
1085 bool InstructionSetIsValid =
1086 this->getDest()->getType() == IceType_v8i16 ||
1087 static_cast<typename InstX86Base<Machine>::Traits::TargetLowering *>(
1089 ->getInstructionSet() >= InstX86Base<Machine>::Traits::SSE4_1;
1090 (void)TypesAreValid;
1091 (void)InstructionSetIsValid;
1092 assert(TypesAreValid);
1093 assert(InstructionSetIsValid);
1095 buf, llvm::array_lengthof(buf), "pmull%s",
1096 InstX86Base<Machine>::Traits::TypeAttributes[this->getDest()->getType()]
1098 this->emitTwoAddress(buf, this, Func);
1101 template <class Machine>
1102 void InstX86Pmull<Machine>::emitIAS(const Cfg *Func) const {
1103 Type Ty = this->getDest()->getType();
1104 bool TypesAreValid = Ty == IceType_v4i32 || Ty == IceType_v8i16;
1105 bool InstructionSetIsValid =
1106 Ty == IceType_v8i16 ||
1107 static_cast<typename InstX86Base<Machine>::Traits::TargetLowering *>(
1109 ->getInstructionSet() >= InstX86Base<Machine>::Traits::SSE4_1;
1110 (void)TypesAreValid;
1111 (void)InstructionSetIsValid;
1112 assert(TypesAreValid);
1113 assert(InstructionSetIsValid);
1114 assert(this->getSrcSize() == 2);
1115 Type ElementTy = typeElementType(Ty);
1116 emitIASRegOpTyXMM<Machine>(Func, ElementTy, this->getDest(), this->getSrc(1),
1120 template <class Machine>
1121 void InstX86Subss<Machine>::emit(const Cfg *Func) const {
1122 if (!BuildDefs::dump())
1126 buf, llvm::array_lengthof(buf), "sub%s",
1127 InstX86Base<Machine>::Traits::TypeAttributes[this->getDest()->getType()]
1129 this->emitTwoAddress(buf, this, Func);
1132 template <class Machine>
1133 void InstX86Psub<Machine>::emit(const Cfg *Func) const {
1134 if (!BuildDefs::dump())
1138 buf, llvm::array_lengthof(buf), "psub%s",
1139 InstX86Base<Machine>::Traits::TypeAttributes[this->getDest()->getType()]
1141 this->emitTwoAddress(buf, this, Func);
1144 template <class Machine>
1145 void InstX86Mulss<Machine>::emit(const Cfg *Func) const {
1146 if (!BuildDefs::dump())
1150 buf, llvm::array_lengthof(buf), "mul%s",
1151 InstX86Base<Machine>::Traits::TypeAttributes[this->getDest()->getType()]
1153 this->emitTwoAddress(buf, this, Func);
1156 template <class Machine>
1157 void InstX86Pmuludq<Machine>::emit(const Cfg *Func) const {
1158 if (!BuildDefs::dump())
1160 assert(this->getSrc(0)->getType() == IceType_v4i32 &&
1161 this->getSrc(1)->getType() == IceType_v4i32);
1162 this->emitTwoAddress(this->Opcode, this, Func);
1165 template <class Machine>
1166 void InstX86Divss<Machine>::emit(const Cfg *Func) const {
1167 if (!BuildDefs::dump())
1171 buf, llvm::array_lengthof(buf), "div%s",
1172 InstX86Base<Machine>::Traits::TypeAttributes[this->getDest()->getType()]
1174 this->emitTwoAddress(buf, this, Func);
1177 template <class Machine> void InstX86Div<Machine>::emit(const Cfg *Func) const {
1178 if (!BuildDefs::dump())
1180 Ostream &Str = Func->getContext()->getStrEmit();
1181 assert(this->getSrcSize() == 3);
1182 Operand *Src1 = this->getSrc(1);
1183 Str << "\t" << this->Opcode << this->getWidthString(Src1->getType()) << "\t";
1187 template <class Machine>
1188 void InstX86Div<Machine>::emitIAS(const Cfg *Func) const {
1189 assert(this->getSrcSize() == 3);
1190 const Operand *Src = this->getSrc(1);
1191 Type Ty = Src->getType();
1192 static const typename InstX86Base<Machine>::Traits::Assembler::GPREmitterOneOp
1193 Emitter = {&InstX86Base<Machine>::Traits::Assembler::div,
1194 &InstX86Base<Machine>::Traits::Assembler::div};
1195 emitIASOpTyGPR<Machine>(Func, Ty, Src, Emitter);
1198 template <class Machine>
1199 void InstX86Idiv<Machine>::emit(const Cfg *Func) const {
1200 if (!BuildDefs::dump())
1202 Ostream &Str = Func->getContext()->getStrEmit();
1203 assert(this->getSrcSize() == 3);
1204 Operand *Src1 = this->getSrc(1);
1205 Str << "\t" << this->Opcode << this->getWidthString(Src1->getType()) << "\t";
1209 template <class Machine>
1210 void InstX86Idiv<Machine>::emitIAS(const Cfg *Func) const {
1211 assert(this->getSrcSize() == 3);
1212 const Operand *Src = this->getSrc(1);
1213 Type Ty = Src->getType();
1214 static const typename InstX86Base<Machine>::Traits::Assembler::GPREmitterOneOp
1215 Emitter = {&InstX86Base<Machine>::Traits::Assembler::idiv,
1216 &InstX86Base<Machine>::Traits::Assembler::idiv};
1217 emitIASOpTyGPR<Machine>(Func, Ty, Src, Emitter);
1220 // pblendvb and blendvps take xmm0 as a final implicit argument.
1221 template <class Machine>
1222 void emitVariableBlendInst(const char *Opcode, const Inst *Inst,
1224 if (!BuildDefs::dump())
1226 Ostream &Str = Func->getContext()->getStrEmit();
1227 assert(Inst->getSrcSize() == 3);
1228 assert(llvm::cast<Variable>(Inst->getSrc(2))->getRegNum() ==
1229 InstX86Base<Machine>::Traits::RegisterSet::Reg_xmm0);
1230 Str << "\t" << Opcode << "\t";
1231 Inst->getSrc(1)->emit(Func);
1233 Inst->getDest()->emit(Func);
1236 template <class Machine>
1237 void emitIASVariableBlendInst(
1238 const Inst *Inst, const Cfg *Func,
1239 const typename InstX86Base<Machine>::Traits::Assembler::XmmEmitterRegOp
1241 assert(Inst->getSrcSize() == 3);
1242 assert(llvm::cast<Variable>(Inst->getSrc(2))->getRegNum() ==
1243 InstX86Base<Machine>::Traits::RegisterSet::Reg_xmm0);
1244 const Variable *Dest = Inst->getDest();
1245 const Operand *Src = Inst->getSrc(1);
1246 emitIASRegOpTyXMM<Machine>(Func, Dest->getType(), Dest, Src, Emitter);
1249 template <class Machine>
1250 void InstX86Blendvps<Machine>::emit(const Cfg *Func) const {
1251 if (!BuildDefs::dump())
1253 assert(static_cast<typename InstX86Base<Machine>::Traits::TargetLowering *>(
1255 ->getInstructionSet() >= InstX86Base<Machine>::Traits::SSE4_1);
1256 emitVariableBlendInst<Machine>(this->Opcode, this, Func);
1259 template <class Machine>
1260 void InstX86Blendvps<Machine>::emitIAS(const Cfg *Func) const {
1261 assert(static_cast<typename InstX86Base<Machine>::Traits::TargetLowering *>(
1263 ->getInstructionSet() >= InstX86Base<Machine>::Traits::SSE4_1);
1264 static const typename InstX86Base<Machine>::Traits::Assembler::XmmEmitterRegOp
1265 Emitter = {&InstX86Base<Machine>::Traits::Assembler::blendvps,
1266 &InstX86Base<Machine>::Traits::Assembler::blendvps};
1267 emitIASVariableBlendInst<Machine>(this, Func, Emitter);
1270 template <class Machine>
1271 void InstX86Pblendvb<Machine>::emit(const Cfg *Func) const {
1272 if (!BuildDefs::dump())
1274 assert(static_cast<typename InstX86Base<Machine>::Traits::TargetLowering *>(
1276 ->getInstructionSet() >= InstX86Base<Machine>::Traits::SSE4_1);
1277 emitVariableBlendInst<Machine>(this->Opcode, this, Func);
1280 template <class Machine>
1281 void InstX86Pblendvb<Machine>::emitIAS(const Cfg *Func) const {
1282 assert(static_cast<typename InstX86Base<Machine>::Traits::TargetLowering *>(
1284 ->getInstructionSet() >= InstX86Base<Machine>::Traits::SSE4_1);
1285 static const typename InstX86Base<Machine>::Traits::Assembler::XmmEmitterRegOp
1286 Emitter = {&InstX86Base<Machine>::Traits::Assembler::pblendvb,
1287 &InstX86Base<Machine>::Traits::Assembler::pblendvb};
1288 emitIASVariableBlendInst<Machine>(this, Func, Emitter);
1291 template <class Machine>
1292 void InstX86Imul<Machine>::emit(const Cfg *Func) const {
1293 if (!BuildDefs::dump())
1295 Ostream &Str = Func->getContext()->getStrEmit();
1296 assert(this->getSrcSize() == 2);
1297 Variable *Dest = this->getDest();
1298 if (isByteSizedArithType(Dest->getType())) {
1299 // The 8-bit version of imul only allows the form "imul r/m8".
1300 const auto Src0Var = llvm::dyn_cast<Variable>(this->getSrc(0));
1303 Src0Var->getRegNum() ==
1304 InstX86Base<Machine>::Traits::RegisterSet::Reg_eax);
1306 this->getSrc(1)->emit(Func);
1307 } else if (llvm::isa<Constant>(this->getSrc(1))) {
1308 Str << "\timul" << this->getWidthString(Dest->getType()) << "\t";
1309 this->getSrc(1)->emit(Func);
1311 this->getSrc(0)->emit(Func);
1315 this->emitTwoAddress("imul", this, Func);
1319 template <class Machine>
1320 void InstX86Imul<Machine>::emitIAS(const Cfg *Func) const {
1321 assert(this->getSrcSize() == 2);
1322 const Variable *Var = this->getDest();
1323 Type Ty = Var->getType();
1324 const Operand *Src = this->getSrc(1);
1325 if (isByteSizedArithType(Ty)) {
1326 // The 8-bit version of imul only allows the form "imul r/m8".
1327 const auto Src0Var = llvm::dyn_cast<Variable>(this->getSrc(0));
1330 Src0Var->getRegNum() ==
1331 InstX86Base<Machine>::Traits::RegisterSet::Reg_eax);
1332 static const typename InstX86Base<
1333 Machine>::Traits::Assembler::GPREmitterOneOp Emitter = {
1334 &InstX86Base<Machine>::Traits::Assembler::imul,
1335 &InstX86Base<Machine>::Traits::Assembler::imul};
1336 emitIASOpTyGPR<Machine>(Func, Ty, this->getSrc(1), Emitter);
1338 // We only use imul as a two-address instruction even though
1339 // there is a 3 operand version when one of the operands is a constant.
1340 assert(Var == this->getSrc(0));
1341 static const typename InstX86Base<
1342 Machine>::Traits::Assembler::GPREmitterRegOp Emitter = {
1343 &InstX86Base<Machine>::Traits::Assembler::imul,
1344 &InstX86Base<Machine>::Traits::Assembler::imul,
1345 &InstX86Base<Machine>::Traits::Assembler::imul};
1346 emitIASRegOpTyGPR<Machine>(Func, Ty, Var, Src, Emitter);
1350 template <class Machine>
1351 void InstX86Insertps<Machine>::emitIAS(const Cfg *Func) const {
1352 assert(this->getSrcSize() == 3);
1353 assert(static_cast<typename InstX86Base<Machine>::Traits::TargetLowering *>(
1355 ->getInstructionSet() >= InstX86Base<Machine>::Traits::SSE4_1);
1356 const Variable *Dest = this->getDest();
1357 assert(Dest == this->getSrc(0));
1358 Type Ty = Dest->getType();
1359 static const typename InstX86Base<Machine>::Traits::Assembler::
1360 template ThreeOpImmEmitter<
1361 typename InstX86Base<Machine>::Traits::RegisterSet::XmmRegister,
1362 typename InstX86Base<Machine>::Traits::RegisterSet::XmmRegister>
1363 Emitter = {&InstX86Base<Machine>::Traits::Assembler::insertps,
1364 &InstX86Base<Machine>::Traits::Assembler::insertps};
1365 emitIASThreeOpImmOps<
1366 Machine, typename InstX86Base<Machine>::Traits::RegisterSet::XmmRegister,
1367 typename InstX86Base<Machine>::Traits::RegisterSet::XmmRegister,
1368 InstX86Base<Machine>::Traits::RegisterSet::getEncodedXmm,
1369 InstX86Base<Machine>::Traits::RegisterSet::getEncodedXmm>(
1370 Func, Ty, Dest, this->getSrc(1), this->getSrc(2), Emitter);
1373 template <class Machine>
1374 void InstX86Cbwdq<Machine>::emit(const Cfg *Func) const {
1375 if (!BuildDefs::dump())
1377 Ostream &Str = Func->getContext()->getStrEmit();
1378 assert(this->getSrcSize() == 1);
1379 Operand *Src0 = this->getSrc(0);
1380 assert(llvm::isa<Variable>(Src0));
1381 assert(llvm::cast<Variable>(Src0)->getRegNum() ==
1382 InstX86Base<Machine>::Traits::RegisterSet::Reg_eax);
1383 switch (Src0->getType()) {
1385 llvm_unreachable("unexpected source type!");
1388 assert(this->getDest()->getRegNum() ==
1389 InstX86Base<Machine>::Traits::RegisterSet::Reg_eax);
1393 assert(this->getDest()->getRegNum() ==
1394 InstX86Base<Machine>::Traits::RegisterSet::Reg_edx);
1398 assert(this->getDest()->getRegNum() ==
1399 InstX86Base<Machine>::Traits::RegisterSet::Reg_edx);
1405 template <class Machine>
1406 void InstX86Cbwdq<Machine>::emitIAS(const Cfg *Func) const {
1407 typename InstX86Base<Machine>::Traits::Assembler *Asm =
1408 Func->getAssembler<typename InstX86Base<Machine>::Traits::Assembler>();
1409 assert(this->getSrcSize() == 1);
1410 Operand *Src0 = this->getSrc(0);
1411 assert(llvm::isa<Variable>(Src0));
1412 assert(llvm::cast<Variable>(Src0)->getRegNum() ==
1413 InstX86Base<Machine>::Traits::RegisterSet::Reg_eax);
1414 switch (Src0->getType()) {
1416 llvm_unreachable("unexpected source type!");
1419 assert(this->getDest()->getRegNum() ==
1420 InstX86Base<Machine>::Traits::RegisterSet::Reg_eax);
1424 assert(this->getDest()->getRegNum() ==
1425 InstX86Base<Machine>::Traits::RegisterSet::Reg_edx);
1429 assert(this->getDest()->getRegNum() ==
1430 InstX86Base<Machine>::Traits::RegisterSet::Reg_edx);
1436 template <class Machine> void InstX86Mul<Machine>::emit(const Cfg *Func) const {
1437 if (!BuildDefs::dump())
1439 Ostream &Str = Func->getContext()->getStrEmit();
1440 assert(this->getSrcSize() == 2);
1441 assert(llvm::isa<Variable>(this->getSrc(0)));
1442 assert(llvm::cast<Variable>(this->getSrc(0))->getRegNum() ==
1443 InstX86Base<Machine>::Traits::RegisterSet::Reg_eax);
1445 this->getDest()->getRegNum() ==
1446 InstX86Base<Machine>::Traits::RegisterSet::Reg_eax); // TODO: allow edx?
1447 Str << "\tmul" << this->getWidthString(this->getDest()->getType()) << "\t";
1448 this->getSrc(1)->emit(Func);
1451 template <class Machine>
1452 void InstX86Mul<Machine>::emitIAS(const Cfg *Func) const {
1453 assert(this->getSrcSize() == 2);
1454 assert(llvm::isa<Variable>(this->getSrc(0)));
1455 assert(llvm::cast<Variable>(this->getSrc(0))->getRegNum() ==
1456 InstX86Base<Machine>::Traits::RegisterSet::Reg_eax);
1458 this->getDest()->getRegNum() ==
1459 InstX86Base<Machine>::Traits::RegisterSet::Reg_eax); // TODO: allow edx?
1460 const Operand *Src = this->getSrc(1);
1461 Type Ty = Src->getType();
1462 static const typename InstX86Base<Machine>::Traits::Assembler::GPREmitterOneOp
1463 Emitter = {&InstX86Base<Machine>::Traits::Assembler::mul,
1464 &InstX86Base<Machine>::Traits::Assembler::mul};
1465 emitIASOpTyGPR<Machine>(Func, Ty, Src, Emitter);
1468 template <class Machine> void InstX86Mul<Machine>::dump(const Cfg *Func) const {
1469 if (!BuildDefs::dump())
1471 Ostream &Str = Func->getContext()->getStrDump();
1472 this->dumpDest(Func);
1473 Str << " = mul." << this->getDest()->getType() << " ";
1474 this->dumpSources(Func);
1477 template <class Machine>
1478 void InstX86Shld<Machine>::emit(const Cfg *Func) const {
1479 if (!BuildDefs::dump())
1481 Ostream &Str = Func->getContext()->getStrEmit();
1482 Variable *Dest = this->getDest();
1483 assert(this->getSrcSize() == 3);
1484 assert(Dest == this->getSrc(0));
1485 Str << "\tshld" << this->getWidthString(Dest->getType()) << "\t";
1486 if (const auto ShiftReg = llvm::dyn_cast<Variable>(this->getSrc(2))) {
1488 assert(ShiftReg->getRegNum() ==
1489 InstX86Base<Machine>::Traits::RegisterSet::Reg_ecx);
1492 this->getSrc(2)->emit(Func);
1495 this->getSrc(1)->emit(Func);
1500 template <class Machine>
1501 void InstX86Shld<Machine>::emitIAS(const Cfg *Func) const {
1502 assert(this->getSrcSize() == 3);
1503 assert(this->getDest() == this->getSrc(0));
1504 const Variable *Dest = this->getDest();
1505 const Operand *Src1 = this->getSrc(1);
1506 const Operand *Src2 = this->getSrc(2);
1507 static const typename InstX86Base<
1508 Machine>::Traits::Assembler::GPREmitterShiftD Emitter = {
1509 &InstX86Base<Machine>::Traits::Assembler::shld,
1510 &InstX86Base<Machine>::Traits::Assembler::shld};
1511 emitIASGPRShiftDouble<Machine>(Func, Dest, Src1, Src2, Emitter);
1514 template <class Machine>
1515 void InstX86Shld<Machine>::dump(const Cfg *Func) const {
1516 if (!BuildDefs::dump())
1518 Ostream &Str = Func->getContext()->getStrDump();
1519 this->dumpDest(Func);
1520 Str << " = shld." << this->getDest()->getType() << " ";
1521 this->dumpSources(Func);
1524 template <class Machine>
1525 void InstX86Shrd<Machine>::emit(const Cfg *Func) const {
1526 if (!BuildDefs::dump())
1528 Ostream &Str = Func->getContext()->getStrEmit();
1529 Variable *Dest = this->getDest();
1530 assert(this->getSrcSize() == 3);
1531 assert(Dest == this->getSrc(0));
1532 Str << "\tshrd" << this->getWidthString(Dest->getType()) << "\t";
1533 if (const auto ShiftReg = llvm::dyn_cast<Variable>(this->getSrc(2))) {
1535 assert(ShiftReg->getRegNum() ==
1536 InstX86Base<Machine>::Traits::RegisterSet::Reg_ecx);
1539 this->getSrc(2)->emit(Func);
1542 this->getSrc(1)->emit(Func);
1547 template <class Machine>
1548 void InstX86Shrd<Machine>::emitIAS(const Cfg *Func) const {
1549 assert(this->getSrcSize() == 3);
1550 assert(this->getDest() == this->getSrc(0));
1551 const Variable *Dest = this->getDest();
1552 const Operand *Src1 = this->getSrc(1);
1553 const Operand *Src2 = this->getSrc(2);
1554 static const typename InstX86Base<
1555 Machine>::Traits::Assembler::GPREmitterShiftD Emitter = {
1556 &InstX86Base<Machine>::Traits::Assembler::shrd,
1557 &InstX86Base<Machine>::Traits::Assembler::shrd};
1558 emitIASGPRShiftDouble<Machine>(Func, Dest, Src1, Src2, Emitter);
1561 template <class Machine>
1562 void InstX86Shrd<Machine>::dump(const Cfg *Func) const {
1563 if (!BuildDefs::dump())
1565 Ostream &Str = Func->getContext()->getStrDump();
1566 this->dumpDest(Func);
1567 Str << " = shrd." << this->getDest()->getType() << " ";
1568 this->dumpSources(Func);
1571 template <class Machine>
1572 void InstX86Cmov<Machine>::emit(const Cfg *Func) const {
1573 if (!BuildDefs::dump())
1575 Ostream &Str = Func->getContext()->getStrEmit();
1576 Variable *Dest = this->getDest();
1578 assert(Condition != InstX86Base<Machine>::Traits::Cond::Br_None);
1579 assert(this->getDest()->hasReg());
1581 << InstX86Base<Machine>::Traits::InstBrAttributes[Condition].DisplayString
1582 << this->getWidthString(Dest->getType()) << "\t";
1583 this->getSrc(1)->emit(Func);
1588 template <class Machine>
1589 void InstX86Cmov<Machine>::emitIAS(const Cfg *Func) const {
1590 assert(Condition != InstX86Base<Machine>::Traits::Cond::Br_None);
1591 assert(this->getDest()->hasReg());
1592 assert(this->getSrcSize() == 2);
1593 Operand *Src = this->getSrc(1);
1594 Type SrcTy = Src->getType();
1595 assert(SrcTy == IceType_i16 || SrcTy == IceType_i32);
1596 typename InstX86Base<Machine>::Traits::Assembler *Asm =
1597 Func->getAssembler<typename InstX86Base<Machine>::Traits::Assembler>();
1598 if (const auto *SrcVar = llvm::dyn_cast<Variable>(Src)) {
1599 if (SrcVar->hasReg()) {
1600 Asm->cmov(SrcTy, Condition,
1601 InstX86Base<Machine>::Traits::RegisterSet::getEncodedGPR(
1602 this->getDest()->getRegNum()),
1603 InstX86Base<Machine>::Traits::RegisterSet::getEncodedGPR(
1604 SrcVar->getRegNum()));
1608 InstX86Base<Machine>::Traits::RegisterSet::getEncodedGPR(
1609 this->getDest()->getRegNum()),
1610 static_cast<typename InstX86Base<Machine>::Traits::TargetLowering *>(
1612 ->stackVarToAsmOperand(SrcVar));
1614 } else if (const auto Mem = llvm::dyn_cast<
1615 typename InstX86Base<Machine>::Traits::X86OperandMem>(Src)) {
1616 assert(Mem->getSegmentRegister() ==
1617 InstX86Base<Machine>::Traits::X86OperandMem::DefaultSegment);
1618 Asm->cmov(SrcTy, Condition,
1619 InstX86Base<Machine>::Traits::RegisterSet::getEncodedGPR(
1620 this->getDest()->getRegNum()),
1621 Mem->toAsmAddress(Asm));
1623 llvm_unreachable("Unexpected operand type");
1627 template <class Machine>
1628 void InstX86Cmov<Machine>::dump(const Cfg *Func) const {
1629 if (!BuildDefs::dump())
1631 Ostream &Str = Func->getContext()->getStrDump();
1633 << InstX86Base<Machine>::Traits::InstBrAttributes[Condition].DisplayString
1635 Str << this->getDest()->getType() << " ";
1636 this->dumpDest(Func);
1638 this->dumpSources(Func);
1641 template <class Machine>
1642 void InstX86Cmpps<Machine>::emit(const Cfg *Func) const {
1643 if (!BuildDefs::dump())
1645 Ostream &Str = Func->getContext()->getStrEmit();
1646 assert(this->getSrcSize() == 2);
1647 assert(Condition < InstX86Base<Machine>::Traits::Cond::Cmpps_Invalid);
1650 << InstX86Base<Machine>::Traits::InstCmppsAttributes[Condition].EmitString
1653 this->getSrc(1)->emit(Func);
1655 this->getDest()->emit(Func);
1658 template <class Machine>
1659 void InstX86Cmpps<Machine>::emitIAS(const Cfg *Func) const {
1660 typename InstX86Base<Machine>::Traits::Assembler *Asm =
1661 Func->getAssembler<typename InstX86Base<Machine>::Traits::Assembler>();
1662 assert(this->getSrcSize() == 2);
1663 assert(Condition < InstX86Base<Machine>::Traits::Cond::Cmpps_Invalid);
1664 // Assuming there isn't any load folding for cmpps, and vector constants
1665 // are not allowed in PNaCl.
1666 assert(llvm::isa<Variable>(this->getSrc(1)));
1667 const auto SrcVar = llvm::cast<Variable>(this->getSrc(1));
1668 if (SrcVar->hasReg()) {
1669 Asm->cmpps(InstX86Base<Machine>::Traits::RegisterSet::getEncodedXmm(
1670 this->getDest()->getRegNum()),
1671 InstX86Base<Machine>::Traits::RegisterSet::getEncodedXmm(
1672 SrcVar->getRegNum()),
1675 typename InstX86Base<Machine>::Traits::Address SrcStackAddr =
1676 static_cast<typename InstX86Base<Machine>::Traits::TargetLowering *>(
1678 ->stackVarToAsmOperand(SrcVar);
1679 Asm->cmpps(InstX86Base<Machine>::Traits::RegisterSet::getEncodedXmm(
1680 this->getDest()->getRegNum()),
1681 SrcStackAddr, Condition);
1685 template <class Machine>
1686 void InstX86Cmpps<Machine>::dump(const Cfg *Func) const {
1687 if (!BuildDefs::dump())
1689 Ostream &Str = Func->getContext()->getStrDump();
1690 assert(Condition < InstX86Base<Machine>::Traits::Cond::Cmpps_Invalid);
1691 this->dumpDest(Func);
1693 << InstX86Base<Machine>::Traits::InstCmppsAttributes[Condition].EmitString
1696 this->dumpSources(Func);
1699 template <class Machine>
1700 void InstX86Cmpxchg<Machine>::emit(const Cfg *Func) const {
1701 if (!BuildDefs::dump())
1703 Ostream &Str = Func->getContext()->getStrEmit();
1704 assert(this->getSrcSize() == 3);
1708 Str << "\tcmpxchg" << this->getWidthString(this->getSrc(0)->getType())
1710 this->getSrc(2)->emit(Func);
1712 this->getSrc(0)->emit(Func);
1715 template <class Machine>
1716 void InstX86Cmpxchg<Machine>::emitIAS(const Cfg *Func) const {
1717 assert(this->getSrcSize() == 3);
1718 typename InstX86Base<Machine>::Traits::Assembler *Asm =
1719 Func->getAssembler<typename InstX86Base<Machine>::Traits::Assembler>();
1720 Type Ty = this->getSrc(0)->getType();
1722 llvm::cast<typename InstX86Base<Machine>::Traits::X86OperandMem>(
1724 assert(Mem->getSegmentRegister() ==
1725 InstX86Base<Machine>::Traits::X86OperandMem::DefaultSegment);
1726 const typename InstX86Base<Machine>::Traits::Address Addr =
1727 Mem->toAsmAddress(Asm);
1728 const auto VarReg = llvm::cast<Variable>(this->getSrc(2));
1729 assert(VarReg->hasReg());
1730 const typename InstX86Base<Machine>::Traits::RegisterSet::GPRRegister Reg =
1731 InstX86Base<Machine>::Traits::RegisterSet::getEncodedGPR(
1732 VarReg->getRegNum());
1733 Asm->cmpxchg(Ty, Addr, Reg, this->Locked);
1736 template <class Machine>
1737 void InstX86Cmpxchg<Machine>::dump(const Cfg *Func) const {
1738 if (!BuildDefs::dump())
1740 Ostream &Str = Func->getContext()->getStrDump();
1744 Str << "cmpxchg." << this->getSrc(0)->getType() << " ";
1745 this->dumpSources(Func);
1748 template <class Machine>
1749 void InstX86Cmpxchg8b<Machine>::emit(const Cfg *Func) const {
1750 if (!BuildDefs::dump())
1752 Ostream &Str = Func->getContext()->getStrEmit();
1753 assert(this->getSrcSize() == 5);
1757 Str << "\tcmpxchg8b\t";
1758 this->getSrc(0)->emit(Func);
1761 template <class Machine>
1762 void InstX86Cmpxchg8b<Machine>::emitIAS(const Cfg *Func) const {
1763 assert(this->getSrcSize() == 5);
1764 typename InstX86Base<Machine>::Traits::Assembler *Asm =
1765 Func->getAssembler<typename InstX86Base<Machine>::Traits::Assembler>();
1767 llvm::cast<typename InstX86Base<Machine>::Traits::X86OperandMem>(
1769 assert(Mem->getSegmentRegister() ==
1770 InstX86Base<Machine>::Traits::X86OperandMem::DefaultSegment);
1771 const typename InstX86Base<Machine>::Traits::Address Addr =
1772 Mem->toAsmAddress(Asm);
1773 Asm->cmpxchg8b(Addr, this->Locked);
1776 template <class Machine>
1777 void InstX86Cmpxchg8b<Machine>::dump(const Cfg *Func) const {
1778 if (!BuildDefs::dump())
1780 Ostream &Str = Func->getContext()->getStrDump();
1784 Str << "cmpxchg8b ";
1785 this->dumpSources(Func);
1788 template <class Machine> void InstX86Cvt<Machine>::emit(const Cfg *Func) const {
1789 if (!BuildDefs::dump())
1791 Ostream &Str = Func->getContext()->getStrEmit();
1792 assert(this->getSrcSize() == 1);
1796 Str << InstX86Base<Machine>::Traits::TypeAttributes[this->getSrc(0)
1800 Machine>::Traits::TypeAttributes[this->getDest()->getType()]
1802 this->getSrc(0)->emit(Func);
1804 this->getDest()->emit(Func);
1807 template <class Machine>
1808 void InstX86Cvt<Machine>::emitIAS(const Cfg *Func) const {
1809 assert(this->getSrcSize() == 1);
1810 const Variable *Dest = this->getDest();
1811 const Operand *Src = this->getSrc(0);
1812 Type DestTy = Dest->getType();
1813 Type SrcTy = Src->getType();
1816 assert(isScalarIntegerType(SrcTy));
1817 assert(typeWidthInBytes(SrcTy) <= 4);
1818 assert(isScalarFloatingType(DestTy));
1819 static const typename InstX86Base<Machine>::Traits::Assembler::
1820 template CastEmitterRegOp<
1821 typename InstX86Base<Machine>::Traits::RegisterSet::XmmRegister,
1822 typename InstX86Base<Machine>::Traits::RegisterSet::GPRRegister>
1823 Emitter = {&InstX86Base<Machine>::Traits::Assembler::cvtsi2ss,
1824 &InstX86Base<Machine>::Traits::Assembler::cvtsi2ss};
1827 typename InstX86Base<Machine>::Traits::RegisterSet::XmmRegister,
1828 typename InstX86Base<Machine>::Traits::RegisterSet::GPRRegister,
1829 InstX86Base<Machine>::Traits::RegisterSet::getEncodedXmm,
1830 InstX86Base<Machine>::Traits::RegisterSet::getEncodedGPR>(
1831 Func, DestTy, Dest, Src, Emitter);
1835 assert(isScalarFloatingType(SrcTy));
1836 assert(isScalarIntegerType(DestTy));
1837 assert(typeWidthInBytes(DestTy) <= 4);
1838 static const typename InstX86Base<Machine>::Traits::Assembler::
1839 template CastEmitterRegOp<
1840 typename InstX86Base<Machine>::Traits::RegisterSet::GPRRegister,
1841 typename InstX86Base<Machine>::Traits::RegisterSet::XmmRegister>
1842 Emitter = {&InstX86Base<Machine>::Traits::Assembler::cvttss2si,
1843 &InstX86Base<Machine>::Traits::Assembler::cvttss2si};
1846 typename InstX86Base<Machine>::Traits::RegisterSet::GPRRegister,
1847 typename InstX86Base<Machine>::Traits::RegisterSet::XmmRegister,
1848 InstX86Base<Machine>::Traits::RegisterSet::getEncodedGPR,
1849 InstX86Base<Machine>::Traits::RegisterSet::getEncodedXmm>(
1850 Func, SrcTy, Dest, Src, Emitter);
1854 assert(isScalarFloatingType(SrcTy));
1855 assert(isScalarFloatingType(DestTy));
1856 assert(DestTy != SrcTy);
1857 static const typename InstX86Base<
1858 Machine>::Traits::Assembler::XmmEmitterRegOp Emitter = {
1859 &InstX86Base<Machine>::Traits::Assembler::cvtfloat2float,
1860 &InstX86Base<Machine>::Traits::Assembler::cvtfloat2float};
1861 emitIASRegOpTyXMM<Machine>(Func, SrcTy, Dest, Src, Emitter);
1865 assert(isVectorIntegerType(SrcTy));
1866 assert(isVectorFloatingType(DestTy));
1867 static const typename InstX86Base<
1868 Machine>::Traits::Assembler::XmmEmitterRegOp Emitter = {
1869 &InstX86Base<Machine>::Traits::Assembler::cvtdq2ps,
1870 &InstX86Base<Machine>::Traits::Assembler::cvtdq2ps};
1871 emitIASRegOpTyXMM<Machine>(Func, DestTy, Dest, Src, Emitter);
1875 assert(isVectorFloatingType(SrcTy));
1876 assert(isVectorIntegerType(DestTy));
1877 static const typename InstX86Base<
1878 Machine>::Traits::Assembler::XmmEmitterRegOp Emitter = {
1879 &InstX86Base<Machine>::Traits::Assembler::cvttps2dq,
1880 &InstX86Base<Machine>::Traits::Assembler::cvttps2dq};
1881 emitIASRegOpTyXMM<Machine>(Func, DestTy, Dest, Src, Emitter);
1887 template <class Machine> void InstX86Cvt<Machine>::dump(const Cfg *Func) const {
1888 if (!BuildDefs::dump())
1890 Ostream &Str = Func->getContext()->getStrDump();
1891 this->dumpDest(Func);
1895 Str << InstX86Base<Machine>::Traits::TypeAttributes[this->getSrc(0)
1899 Machine>::Traits::TypeAttributes[this->getDest()->getType()]
1901 this->dumpSources(Func);
1904 template <class Machine>
1905 void InstX86Icmp<Machine>::emit(const Cfg *Func) const {
1906 if (!BuildDefs::dump())
1908 Ostream &Str = Func->getContext()->getStrEmit();
1909 assert(this->getSrcSize() == 2);
1910 Str << "\tcmp" << this->getWidthString(this->getSrc(0)->getType()) << "\t";
1911 this->getSrc(1)->emit(Func);
1913 this->getSrc(0)->emit(Func);
1916 template <class Machine>
1917 void InstX86Icmp<Machine>::emitIAS(const Cfg *Func) const {
1918 assert(this->getSrcSize() == 2);
1919 const Operand *Src0 = this->getSrc(0);
1920 const Operand *Src1 = this->getSrc(1);
1921 Type Ty = Src0->getType();
1922 static const typename InstX86Base<Machine>::Traits::Assembler::GPREmitterRegOp
1923 RegEmitter = {&InstX86Base<Machine>::Traits::Assembler::cmp,
1924 &InstX86Base<Machine>::Traits::Assembler::cmp,
1925 &InstX86Base<Machine>::Traits::Assembler::cmp};
1926 static const typename InstX86Base<
1927 Machine>::Traits::Assembler::GPREmitterAddrOp AddrEmitter = {
1928 &InstX86Base<Machine>::Traits::Assembler::cmp,
1929 &InstX86Base<Machine>::Traits::Assembler::cmp};
1930 if (const auto SrcVar0 = llvm::dyn_cast<Variable>(Src0)) {
1931 if (SrcVar0->hasReg()) {
1932 emitIASRegOpTyGPR<Machine>(Func, Ty, SrcVar0, Src1, RegEmitter);
1936 emitIASAsAddrOpTyGPR<Machine>(Func, Ty, Src0, Src1, AddrEmitter);
1939 template <class Machine>
1940 void InstX86Icmp<Machine>::dump(const Cfg *Func) const {
1941 if (!BuildDefs::dump())
1943 Ostream &Str = Func->getContext()->getStrDump();
1944 Str << "cmp." << this->getSrc(0)->getType() << " ";
1945 this->dumpSources(Func);
1948 template <class Machine>
1949 void InstX86Ucomiss<Machine>::emit(const Cfg *Func) const {
1950 if (!BuildDefs::dump())
1952 Ostream &Str = Func->getContext()->getStrEmit();
1953 assert(this->getSrcSize() == 2);
1955 << InstX86Base<Machine>::Traits::TypeAttributes[this->getSrc(0)
1957 .SdSsString << "\t";
1958 this->getSrc(1)->emit(Func);
1960 this->getSrc(0)->emit(Func);
1963 template <class Machine>
1964 void InstX86Ucomiss<Machine>::emitIAS(const Cfg *Func) const {
1965 assert(this->getSrcSize() == 2);
1966 // Currently src0 is always a variable by convention, to avoid having
1967 // two memory operands.
1968 assert(llvm::isa<Variable>(this->getSrc(0)));
1969 const auto Src0Var = llvm::cast<Variable>(this->getSrc(0));
1970 Type Ty = Src0Var->getType();
1971 static const typename InstX86Base<Machine>::Traits::Assembler::XmmEmitterRegOp
1972 Emitter = {&InstX86Base<Machine>::Traits::Assembler::ucomiss,
1973 &InstX86Base<Machine>::Traits::Assembler::ucomiss};
1974 emitIASRegOpTyXMM<Machine>(Func, Ty, Src0Var, this->getSrc(1), Emitter);
1977 template <class Machine>
1978 void InstX86Ucomiss<Machine>::dump(const Cfg *Func) const {
1979 if (!BuildDefs::dump())
1981 Ostream &Str = Func->getContext()->getStrDump();
1982 Str << "ucomiss." << this->getSrc(0)->getType() << " ";
1983 this->dumpSources(Func);
1986 template <class Machine> void InstX86UD2<Machine>::emit(const Cfg *Func) const {
1987 if (!BuildDefs::dump())
1989 Ostream &Str = Func->getContext()->getStrEmit();
1990 assert(this->getSrcSize() == 0);
1994 template <class Machine>
1995 void InstX86UD2<Machine>::emitIAS(const Cfg *Func) const {
1996 typename InstX86Base<Machine>::Traits::Assembler *Asm =
1997 Func->getAssembler<typename InstX86Base<Machine>::Traits::Assembler>();
2001 template <class Machine> void InstX86UD2<Machine>::dump(const Cfg *Func) const {
2002 if (!BuildDefs::dump())
2004 Ostream &Str = Func->getContext()->getStrDump();
2008 template <class Machine>
2009 void InstX86Test<Machine>::emit(const Cfg *Func) const {
2010 if (!BuildDefs::dump())
2012 Ostream &Str = Func->getContext()->getStrEmit();
2013 assert(this->getSrcSize() == 2);
2014 Str << "\ttest" << this->getWidthString(this->getSrc(0)->getType()) << "\t";
2015 this->getSrc(1)->emit(Func);
2017 this->getSrc(0)->emit(Func);
2020 template <class Machine>
2021 void InstX86Test<Machine>::emitIAS(const Cfg *Func) const {
2022 assert(this->getSrcSize() == 2);
2023 const Operand *Src0 = this->getSrc(0);
2024 const Operand *Src1 = this->getSrc(1);
2025 Type Ty = Src0->getType();
2026 // The Reg/Addr form of test is not encodeable.
2027 static const typename InstX86Base<Machine>::Traits::Assembler::GPREmitterRegOp
2028 RegEmitter = {&InstX86Base<Machine>::Traits::Assembler::test, nullptr,
2029 &InstX86Base<Machine>::Traits::Assembler::test};
2030 static const typename InstX86Base<
2031 Machine>::Traits::Assembler::GPREmitterAddrOp AddrEmitter = {
2032 &InstX86Base<Machine>::Traits::Assembler::test,
2033 &InstX86Base<Machine>::Traits::Assembler::test};
2034 if (const auto SrcVar0 = llvm::dyn_cast<Variable>(Src0)) {
2035 if (SrcVar0->hasReg()) {
2036 emitIASRegOpTyGPR<Machine>(Func, Ty, SrcVar0, Src1, RegEmitter);
2040 llvm_unreachable("Nothing actually generates this so it's untested");
2041 emitIASAsAddrOpTyGPR<Machine>(Func, Ty, Src0, Src1, AddrEmitter);
2044 template <class Machine>
2045 void InstX86Test<Machine>::dump(const Cfg *Func) const {
2046 if (!BuildDefs::dump())
2048 Ostream &Str = Func->getContext()->getStrDump();
2049 Str << "test." << this->getSrc(0)->getType() << " ";
2050 this->dumpSources(Func);
2053 template <class Machine>
2054 void InstX86Mfence<Machine>::emit(const Cfg *Func) const {
2055 if (!BuildDefs::dump())
2057 Ostream &Str = Func->getContext()->getStrEmit();
2058 assert(this->getSrcSize() == 0);
2062 template <class Machine>
2063 void InstX86Mfence<Machine>::emitIAS(const Cfg *Func) const {
2064 typename InstX86Base<Machine>::Traits::Assembler *Asm =
2065 Func->getAssembler<typename InstX86Base<Machine>::Traits::Assembler>();
2069 template <class Machine>
2070 void InstX86Mfence<Machine>::dump(const Cfg *Func) const {
2071 if (!BuildDefs::dump())
2073 Ostream &Str = Func->getContext()->getStrDump();
2077 template <class Machine>
2078 void InstX86Store<Machine>::emit(const Cfg *Func) const {
2079 if (!BuildDefs::dump())
2081 Ostream &Str = Func->getContext()->getStrEmit();
2082 assert(this->getSrcSize() == 2);
2083 Type Ty = this->getSrc(0)->getType();
2084 Str << "\tmov" << this->getWidthString(Ty)
2085 << InstX86Base<Machine>::Traits::TypeAttributes[Ty].SdSsString << "\t";
2086 this->getSrc(0)->emit(Func);
2088 this->getSrc(1)->emit(Func);
2091 template <class Machine>
2092 void InstX86Store<Machine>::emitIAS(const Cfg *Func) const {
2093 assert(this->getSrcSize() == 2);
2094 const Operand *Dest = this->getSrc(1);
2095 const Operand *Src = this->getSrc(0);
2096 Type DestTy = Dest->getType();
2097 if (isScalarFloatingType(DestTy)) {
2098 // Src must be a register, since Dest is a Mem operand of some kind.
2099 const auto SrcVar = llvm::cast<Variable>(Src);
2100 assert(SrcVar->hasReg());
2101 typename InstX86Base<Machine>::Traits::RegisterSet::XmmRegister SrcReg =
2102 InstX86Base<Machine>::Traits::RegisterSet::getEncodedXmm(
2103 SrcVar->getRegNum());
2104 typename InstX86Base<Machine>::Traits::Assembler *Asm =
2105 Func->getAssembler<typename InstX86Base<Machine>::Traits::Assembler>();
2106 if (const auto DestVar = llvm::dyn_cast<Variable>(Dest)) {
2107 assert(!DestVar->hasReg());
2108 typename InstX86Base<Machine>::Traits::Address StackAddr(
2109 static_cast<typename InstX86Base<Machine>::Traits::TargetLowering *>(
2111 ->stackVarToAsmOperand(DestVar));
2112 Asm->movss(DestTy, StackAddr, SrcReg);
2114 const auto DestMem =
2115 llvm::cast<typename InstX86Base<Machine>::Traits::X86OperandMem>(
2117 assert(DestMem->getSegmentRegister() ==
2118 InstX86Base<Machine>::Traits::X86OperandMem::DefaultSegment);
2119 Asm->movss(DestTy, DestMem->toAsmAddress(Asm), SrcReg);
2123 assert(isScalarIntegerType(DestTy));
2124 static const typename InstX86Base<
2125 Machine>::Traits::Assembler::GPREmitterAddrOp GPRAddrEmitter = {
2126 &InstX86Base<Machine>::Traits::Assembler::mov,
2127 &InstX86Base<Machine>::Traits::Assembler::mov};
2128 emitIASAsAddrOpTyGPR<Machine>(Func, DestTy, Dest, Src, GPRAddrEmitter);
2132 template <class Machine>
2133 void InstX86Store<Machine>::dump(const Cfg *Func) const {
2134 if (!BuildDefs::dump())
2136 Ostream &Str = Func->getContext()->getStrDump();
2137 Str << "mov." << this->getSrc(0)->getType() << " ";
2138 this->getSrc(1)->dump(Func);
2140 this->getSrc(0)->dump(Func);
2143 template <class Machine>
2144 void InstX86StoreP<Machine>::emit(const Cfg *Func) const {
2145 if (!BuildDefs::dump())
2147 Ostream &Str = Func->getContext()->getStrEmit();
2148 assert(this->getSrcSize() == 2);
2149 assert(isVectorType(this->getSrc(1)->getType()));
2150 Str << "\tmovups\t";
2151 this->getSrc(0)->emit(Func);
2153 this->getSrc(1)->emit(Func);
2156 template <class Machine>
2157 void InstX86StoreP<Machine>::emitIAS(const Cfg *Func) const {
2158 typename InstX86Base<Machine>::Traits::Assembler *Asm =
2159 Func->getAssembler<typename InstX86Base<Machine>::Traits::Assembler>();
2160 assert(this->getSrcSize() == 2);
2161 const auto SrcVar = llvm::cast<Variable>(this->getSrc(0));
2162 const auto DestMem =
2163 llvm::cast<typename InstX86Base<Machine>::Traits::X86OperandMem>(
2165 assert(DestMem->getSegmentRegister() ==
2166 InstX86Base<Machine>::Traits::X86OperandMem::DefaultSegment);
2167 assert(SrcVar->hasReg());
2168 Asm->movups(DestMem->toAsmAddress(Asm),
2169 InstX86Base<Machine>::Traits::RegisterSet::getEncodedXmm(
2170 SrcVar->getRegNum()));
2173 template <class Machine>
2174 void InstX86StoreP<Machine>::dump(const Cfg *Func) const {
2175 if (!BuildDefs::dump())
2177 Ostream &Str = Func->getContext()->getStrDump();
2178 Str << "storep." << this->getSrc(0)->getType() << " ";
2179 this->getSrc(1)->dump(Func);
2181 this->getSrc(0)->dump(Func);
2184 template <class Machine>
2185 void InstX86StoreQ<Machine>::emit(const Cfg *Func) const {
2186 if (!BuildDefs::dump())
2188 Ostream &Str = Func->getContext()->getStrEmit();
2189 assert(this->getSrcSize() == 2);
2190 assert(this->getSrc(1)->getType() == IceType_i64 ||
2191 this->getSrc(1)->getType() == IceType_f64 ||
2192 isVectorType(this->getSrc(1)->getType()));
2194 this->getSrc(0)->emit(Func);
2196 this->getSrc(1)->emit(Func);
2199 template <class Machine>
2200 void InstX86StoreQ<Machine>::emitIAS(const Cfg *Func) const {
2201 typename InstX86Base<Machine>::Traits::Assembler *Asm =
2202 Func->getAssembler<typename InstX86Base<Machine>::Traits::Assembler>();
2203 assert(this->getSrcSize() == 2);
2204 const auto SrcVar = llvm::cast<Variable>(this->getSrc(0));
2205 const auto DestMem =
2206 llvm::cast<typename InstX86Base<Machine>::Traits::X86OperandMem>(
2208 assert(DestMem->getSegmentRegister() ==
2209 InstX86Base<Machine>::Traits::X86OperandMem::DefaultSegment);
2210 assert(SrcVar->hasReg());
2211 Asm->movq(DestMem->toAsmAddress(Asm),
2212 InstX86Base<Machine>::Traits::RegisterSet::getEncodedXmm(
2213 SrcVar->getRegNum()));
2216 template <class Machine>
2217 void InstX86StoreQ<Machine>::dump(const Cfg *Func) const {
2218 if (!BuildDefs::dump())
2220 Ostream &Str = Func->getContext()->getStrDump();
2221 Str << "storeq." << this->getSrc(0)->getType() << " ";
2222 this->getSrc(1)->dump(Func);
2224 this->getSrc(0)->dump(Func);
2227 template <class Machine> void InstX86Lea<Machine>::emit(const Cfg *Func) const {
2228 if (!BuildDefs::dump())
2230 Ostream &Str = Func->getContext()->getStrEmit();
2231 assert(this->getSrcSize() == 1);
2232 assert(this->getDest()->hasReg());
2234 Operand *Src0 = this->getSrc(0);
2235 if (const auto Src0Var = llvm::dyn_cast<Variable>(Src0)) {
2236 Type Ty = Src0Var->getType();
2237 // lea on x86-32 doesn't accept mem128 operands, so cast VSrc0 to an
2239 Src0Var->asType(isVectorType(Ty) ? IceType_i32 : Ty)->emit(Func);
2244 this->getDest()->emit(Func);
2247 template <class Machine> void InstX86Mov<Machine>::emit(const Cfg *Func) const {
2248 if (!BuildDefs::dump())
2250 Ostream &Str = Func->getContext()->getStrEmit();
2251 assert(this->getSrcSize() == 1);
2252 Operand *Src = this->getSrc(0);
2253 Type SrcTy = Src->getType();
2254 Type DestTy = this->getDest()->getType();
2256 << (!isScalarFloatingType(DestTy)
2257 ? this->getWidthString(SrcTy)
2258 : InstX86Base<Machine>::Traits::TypeAttributes[DestTy].SdSsString)
2260 // For an integer truncation operation, src is wider than dest.
2261 // Ideally, we use a mov instruction whose data width matches the
2262 // narrower dest. This is a problem if e.g. src is a register like
2263 // esi or si where there is no 8-bit version of the register. To be
2264 // safe, we instead widen the dest to match src. This works even
2265 // for stack-allocated dest variables because typeWidthOnStack()
2266 // pads to a 4-byte boundary even if only a lower portion is used.
2267 // TODO: This assert disallows usages such as copying a floating point
2268 // value between a vector and a scalar (which movss is used for).
2270 assert(Func->getTarget()->typeWidthInBytesOnStack(DestTy) ==
2271 Func->getTarget()->typeWidthInBytesOnStack(SrcTy));
2274 this->getDest()->asType(SrcTy)->emit(Func);
2277 template <class Machine>
2278 void InstX86Mov<Machine>::emitIAS(const Cfg *Func) const {
2279 assert(this->getSrcSize() == 1);
2280 const Variable *Dest = this->getDest();
2281 const Operand *Src = this->getSrc(0);
2282 Type DestTy = Dest->getType();
2283 Type SrcTy = Src->getType();
2284 // Mov can be used for GPRs or XMM registers. Also, the type does not
2285 // necessarily match (Mov can be used for bitcasts). However, when
2286 // the type does not match, one of the operands must be a register.
2287 // Thus, the strategy is to find out if Src or Dest are a register,
2288 // then use that register's type to decide on which emitter set to use.
2289 // The emitter set will include reg-reg movs, but that case should
2290 // be unused when the types don't match.
2291 static const typename InstX86Base<Machine>::Traits::Assembler::XmmEmitterRegOp
2292 XmmRegEmitter = {&InstX86Base<Machine>::Traits::Assembler::movss,
2293 &InstX86Base<Machine>::Traits::Assembler::movss};
2294 static const typename InstX86Base<Machine>::Traits::Assembler::GPREmitterRegOp
2295 GPRRegEmitter = {&InstX86Base<Machine>::Traits::Assembler::mov,
2296 &InstX86Base<Machine>::Traits::Assembler::mov,
2297 &InstX86Base<Machine>::Traits::Assembler::mov};
2298 static const typename InstX86Base<
2299 Machine>::Traits::Assembler::GPREmitterAddrOp GPRAddrEmitter = {
2300 &InstX86Base<Machine>::Traits::Assembler::mov,
2301 &InstX86Base<Machine>::Traits::Assembler::mov};
2302 // For an integer truncation operation, src is wider than dest.
2303 // Ideally, we use a mov instruction whose data width matches the
2304 // narrower dest. This is a problem if e.g. src is a register like
2305 // esi or si where there is no 8-bit version of the register. To be
2306 // safe, we instead widen the dest to match src. This works even
2307 // for stack-allocated dest variables because typeWidthOnStack()
2308 // pads to a 4-byte boundary even if only a lower portion is used.
2309 // TODO: This assert disallows usages such as copying a floating point
2310 // value between a vector and a scalar (which movss is used for).
2313 Func->getTarget()->typeWidthInBytesOnStack(this->getDest()->getType()) ==
2314 Func->getTarget()->typeWidthInBytesOnStack(Src->getType()));
2315 if (Dest->hasReg()) {
2316 if (isScalarFloatingType(DestTy)) {
2317 emitIASRegOpTyXMM<Machine>(Func, DestTy, Dest, Src, XmmRegEmitter);
2320 assert(isScalarIntegerType(DestTy));
2321 // Widen DestTy for truncation (see above note). We should only do this
2322 // when both Src and Dest are integer types.
2323 if (isScalarIntegerType(SrcTy)) {
2326 emitIASRegOpTyGPR<Machine>(Func, DestTy, Dest, Src, GPRRegEmitter);
2330 // Dest must be Stack and Src *could* be a register. Use Src's type
2331 // to decide on the emitters.
2332 typename InstX86Base<Machine>::Traits::Address StackAddr(
2333 static_cast<typename InstX86Base<Machine>::Traits::TargetLowering *>(
2335 ->stackVarToAsmOperand(Dest));
2336 if (isScalarFloatingType(SrcTy)) {
2337 // Src must be a register.
2338 const auto SrcVar = llvm::cast<Variable>(Src);
2339 assert(SrcVar->hasReg());
2340 typename InstX86Base<Machine>::Traits::Assembler *Asm =
2342 typename InstX86Base<Machine>::Traits::Assembler>();
2343 Asm->movss(SrcTy, StackAddr,
2344 InstX86Base<Machine>::Traits::RegisterSet::getEncodedXmm(
2345 SrcVar->getRegNum()));
2348 // Src can be a register or immediate.
2349 assert(isScalarIntegerType(SrcTy));
2350 emitIASAddrOpTyGPR<Machine>(Func, SrcTy, StackAddr, Src, GPRAddrEmitter);
2357 template <class Machine>
2358 void InstX86Movd<Machine>::emitIAS(const Cfg *Func) const {
2359 typename InstX86Base<Machine>::Traits::Assembler *Asm =
2360 Func->getAssembler<typename InstX86Base<Machine>::Traits::Assembler>();
2361 assert(this->getSrcSize() == 1);
2362 const Variable *Dest = this->getDest();
2363 const auto SrcVar = llvm::cast<Variable>(this->getSrc(0));
2364 // For insert/extract element (one of Src/Dest is an Xmm vector and
2365 // the other is an int type).
2366 if (SrcVar->getType() == IceType_i32) {
2367 assert(isVectorType(Dest->getType()));
2368 assert(Dest->hasReg());
2369 typename InstX86Base<Machine>::Traits::RegisterSet::XmmRegister DestReg =
2370 InstX86Base<Machine>::Traits::RegisterSet::getEncodedXmm(
2372 if (SrcVar->hasReg()) {
2374 InstX86Base<Machine>::Traits::RegisterSet::getEncodedGPR(
2375 SrcVar->getRegNum()));
2377 typename InstX86Base<Machine>::Traits::Address StackAddr(
2378 static_cast<typename InstX86Base<Machine>::Traits::TargetLowering *>(
2380 ->stackVarToAsmOperand(SrcVar));
2381 Asm->movd(DestReg, StackAddr);
2384 assert(isVectorType(SrcVar->getType()));
2385 assert(SrcVar->hasReg());
2386 assert(Dest->getType() == IceType_i32);
2387 typename InstX86Base<Machine>::Traits::RegisterSet::XmmRegister SrcReg =
2388 InstX86Base<Machine>::Traits::RegisterSet::getEncodedXmm(
2389 SrcVar->getRegNum());
2390 if (Dest->hasReg()) {
2391 Asm->movd(InstX86Base<Machine>::Traits::RegisterSet::getEncodedGPR(
2395 typename InstX86Base<Machine>::Traits::Address StackAddr(
2396 static_cast<typename InstX86Base<Machine>::Traits::TargetLowering *>(
2398 ->stackVarToAsmOperand(Dest));
2399 Asm->movd(StackAddr, SrcReg);
2404 template <class Machine>
2405 void InstX86Movp<Machine>::emit(const Cfg *Func) const {
2406 if (!BuildDefs::dump())
2408 // TODO(wala,stichnot): movups works with all vector operands, but
2409 // there exist other instructions (movaps, movdqa, movdqu) that may
2410 // perform better, depending on the data type and alignment of the
2412 Ostream &Str = Func->getContext()->getStrEmit();
2413 assert(this->getSrcSize() == 1);
2414 Str << "\tmovups\t";
2415 this->getSrc(0)->emit(Func);
2417 this->getDest()->emit(Func);
2420 template <class Machine>
2421 void InstX86Movp<Machine>::emitIAS(const Cfg *Func) const {
2422 assert(this->getSrcSize() == 1);
2423 assert(isVectorType(this->getDest()->getType()));
2424 const Variable *Dest = this->getDest();
2425 const Operand *Src = this->getSrc(0);
2426 static const typename InstX86Base<
2427 Machine>::Traits::Assembler::XmmEmitterMovOps Emitter = {
2428 &InstX86Base<Machine>::Traits::Assembler::movups,
2429 &InstX86Base<Machine>::Traits::Assembler::movups,
2430 &InstX86Base<Machine>::Traits::Assembler::movups};
2431 emitIASMovlikeXMM<Machine>(Func, Dest, Src, Emitter);
2434 template <class Machine>
2435 void InstX86Movq<Machine>::emit(const Cfg *Func) const {
2436 if (!BuildDefs::dump())
2438 Ostream &Str = Func->getContext()->getStrEmit();
2439 assert(this->getSrcSize() == 1);
2440 assert(this->getDest()->getType() == IceType_i64 ||
2441 this->getDest()->getType() == IceType_f64);
2443 this->getSrc(0)->emit(Func);
2445 this->getDest()->emit(Func);
2448 template <class Machine>
2449 void InstX86Movq<Machine>::emitIAS(const Cfg *Func) const {
2450 assert(this->getSrcSize() == 1);
2451 assert(this->getDest()->getType() == IceType_i64 ||
2452 this->getDest()->getType() == IceType_f64);
2453 const Variable *Dest = this->getDest();
2454 const Operand *Src = this->getSrc(0);
2455 static const typename InstX86Base<
2456 Machine>::Traits::Assembler::XmmEmitterMovOps Emitter = {
2457 &InstX86Base<Machine>::Traits::Assembler::movq,
2458 &InstX86Base<Machine>::Traits::Assembler::movq,
2459 &InstX86Base<Machine>::Traits::Assembler::movq};
2460 emitIASMovlikeXMM<Machine>(Func, Dest, Src, Emitter);
2463 template <class Machine>
2464 void InstX86MovssRegs<Machine>::emitIAS(const Cfg *Func) const {
2465 // This is Binop variant is only intended to be used for reg-reg moves
2466 // where part of the Dest register is untouched.
2467 assert(this->getSrcSize() == 2);
2468 const Variable *Dest = this->getDest();
2469 assert(Dest == this->getSrc(0));
2470 const auto SrcVar = llvm::cast<Variable>(this->getSrc(1));
2471 assert(Dest->hasReg() && SrcVar->hasReg());
2472 typename InstX86Base<Machine>::Traits::Assembler *Asm =
2473 Func->getAssembler<typename InstX86Base<Machine>::Traits::Assembler>();
2474 Asm->movss(IceType_f32,
2475 InstX86Base<Machine>::Traits::RegisterSet::getEncodedXmm(
2477 InstX86Base<Machine>::Traits::RegisterSet::getEncodedXmm(
2478 SrcVar->getRegNum()));
2481 template <class Machine>
2482 void InstX86Movsx<Machine>::emitIAS(const Cfg *Func) const {
2483 assert(this->getSrcSize() == 1);
2484 const Variable *Dest = this->getDest();
2485 const Operand *Src = this->getSrc(0);
2486 // Dest must be a > 8-bit register, but Src can be 8-bit. In practice
2487 // we just use the full register for Dest to avoid having an
2488 // OperandSizeOverride prefix. It also allows us to only dispatch on SrcTy.
2489 Type SrcTy = Src->getType();
2490 assert(typeWidthInBytes(Dest->getType()) > 1);
2491 assert(typeWidthInBytes(Dest->getType()) > typeWidthInBytes(SrcTy));
2492 emitIASRegOpTyGPR<Machine, false, true>(Func, SrcTy, Dest, Src,
2496 template <class Machine>
2497 void InstX86Movzx<Machine>::emitIAS(const Cfg *Func) const {
2498 assert(this->getSrcSize() == 1);
2499 const Variable *Dest = this->getDest();
2500 const Operand *Src = this->getSrc(0);
2501 Type SrcTy = Src->getType();
2502 assert(typeWidthInBytes(Dest->getType()) > 1);
2503 assert(typeWidthInBytes(Dest->getType()) > typeWidthInBytes(SrcTy));
2504 emitIASRegOpTyGPR<Machine, false, true>(Func, SrcTy, Dest, Src,
2508 template <class Machine> void InstX86Nop<Machine>::emit(const Cfg *Func) const {
2509 if (!BuildDefs::dump())
2511 Ostream &Str = Func->getContext()->getStrEmit();
2512 // TODO: Emit the right code for each variant.
2513 Str << "\tnop\t# variant = " << Variant;
2516 template <class Machine>
2517 void InstX86Nop<Machine>::emitIAS(const Cfg *Func) const {
2518 typename InstX86Base<Machine>::Traits::Assembler *Asm =
2519 Func->getAssembler<typename InstX86Base<Machine>::Traits::Assembler>();
2520 // TODO: Emit the right code for the variant.
2524 template <class Machine> void InstX86Nop<Machine>::dump(const Cfg *Func) const {
2525 if (!BuildDefs::dump())
2527 Ostream &Str = Func->getContext()->getStrDump();
2528 Str << "nop (variant = " << Variant << ")";
2531 template <class Machine> void InstX86Fld<Machine>::emit(const Cfg *Func) const {
2532 if (!BuildDefs::dump())
2534 Ostream &Str = Func->getContext()->getStrEmit();
2535 assert(this->getSrcSize() == 1);
2536 Type Ty = this->getSrc(0)->getType();
2537 SizeT Width = typeWidthInBytes(Ty);
2538 const auto Var = llvm::dyn_cast<Variable>(this->getSrc(0));
2539 if (Var && Var->hasReg()) {
2540 // This is a physical xmm register, so we need to spill it to a
2541 // temporary stack slot.
2542 Str << "\tsubl\t$" << Width << ", %esp"
2545 << InstX86Base<Machine>::Traits::TypeAttributes[Ty].SdSsString << "\t";
2547 Str << ", (%esp)\n";
2548 Str << "\tfld" << this->getFldString(Ty) << "\t"
2550 Str << "\taddl\t$" << Width << ", %esp";
2553 Str << "\tfld" << this->getFldString(Ty) << "\t";
2554 this->getSrc(0)->emit(Func);
2557 template <class Machine>
2558 void InstX86Fld<Machine>::emitIAS(const Cfg *Func) const {
2559 typename InstX86Base<Machine>::Traits::Assembler *Asm =
2560 Func->getAssembler<typename InstX86Base<Machine>::Traits::Assembler>();
2561 assert(this->getSrcSize() == 1);
2562 const Operand *Src = this->getSrc(0);
2563 Type Ty = Src->getType();
2564 if (const auto Var = llvm::dyn_cast<Variable>(Src)) {
2565 if (Var->hasReg()) {
2566 // This is a physical xmm register, so we need to spill it to a
2567 // temporary stack slot.
2568 Immediate Width(typeWidthInBytes(Ty));
2569 Asm->sub(IceType_i32,
2570 InstX86Base<Machine>::Traits::RegisterSet::Encoded_Reg_esp,
2572 typename InstX86Base<Machine>::Traits::Address StackSlot =
2573 typename InstX86Base<Machine>::Traits::Address(
2574 InstX86Base<Machine>::Traits::RegisterSet::Encoded_Reg_esp, 0);
2575 Asm->movss(Ty, StackSlot,
2576 InstX86Base<Machine>::Traits::RegisterSet::getEncodedXmm(
2578 Asm->fld(Ty, StackSlot);
2579 Asm->add(IceType_i32,
2580 InstX86Base<Machine>::Traits::RegisterSet::Encoded_Reg_esp,
2583 typename InstX86Base<Machine>::Traits::Address StackAddr(
2584 static_cast<typename InstX86Base<Machine>::Traits::TargetLowering *>(
2586 ->stackVarToAsmOperand(Var));
2587 Asm->fld(Ty, StackAddr);
2589 } else if (const auto Mem = llvm::dyn_cast<
2590 typename InstX86Base<Machine>::Traits::X86OperandMem>(Src)) {
2591 assert(Mem->getSegmentRegister() ==
2592 InstX86Base<Machine>::Traits::X86OperandMem::DefaultSegment);
2593 Asm->fld(Ty, Mem->toAsmAddress(Asm));
2594 } else if (const auto Imm = llvm::dyn_cast<Constant>(Src)) {
2595 Asm->fld(Ty, InstX86Base<Machine>::Traits::Address::ofConstPool(Asm, Imm));
2597 llvm_unreachable("Unexpected operand type");
2601 template <class Machine> void InstX86Fld<Machine>::dump(const Cfg *Func) const {
2602 if (!BuildDefs::dump())
2604 Ostream &Str = Func->getContext()->getStrDump();
2605 Str << "fld." << this->getSrc(0)->getType() << " ";
2606 this->dumpSources(Func);
2609 template <class Machine>
2610 void InstX86Fstp<Machine>::emit(const Cfg *Func) const {
2611 if (!BuildDefs::dump())
2613 Ostream &Str = Func->getContext()->getStrEmit();
2614 assert(this->getSrcSize() == 0);
2615 // TODO(jvoung,stichnot): Utilize this by setting Dest to nullptr to
2616 // "partially" delete the fstp if the Dest is unused.
2617 // Even if Dest is unused, the fstp should be kept for the SideEffects
2618 // of popping the stack.
2619 if (!this->getDest()) {
2620 Str << "\tfstp\tst(0)";
2623 Type Ty = this->getDest()->getType();
2624 size_t Width = typeWidthInBytes(Ty);
2625 if (!this->getDest()->hasReg()) {
2626 Str << "\tfstp" << this->getFldString(Ty) << "\t";
2627 this->getDest()->emit(Func);
2630 // Dest is a physical (xmm) register, so st(0) needs to go through
2631 // memory. Hack this by creating a temporary stack slot, spilling
2632 // st(0) there, loading it into the xmm register, and deallocating
2634 Str << "\tsubl\t$" << Width << ", %esp\n";
2635 Str << "\tfstp" << this->getFldString(Ty) << "\t"
2637 Str << "\tmov" << InstX86Base<Machine>::Traits::TypeAttributes[Ty].SdSsString
2640 this->getDest()->emit(Func);
2642 Str << "\taddl\t$" << Width << ", %esp";
2645 template <class Machine>
2646 void InstX86Fstp<Machine>::emitIAS(const Cfg *Func) const {
2647 typename InstX86Base<Machine>::Traits::Assembler *Asm =
2648 Func->getAssembler<typename InstX86Base<Machine>::Traits::Assembler>();
2649 assert(this->getSrcSize() == 0);
2650 const Variable *Dest = this->getDest();
2651 // TODO(jvoung,stichnot): Utilize this by setting Dest to nullptr to
2652 // "partially" delete the fstp if the Dest is unused.
2653 // Even if Dest is unused, the fstp should be kept for the SideEffects
2654 // of popping the stack.
2656 Asm->fstp(InstX86Base<Machine>::Traits::RegisterSet::getEncodedSTReg(0));
2659 Type Ty = Dest->getType();
2660 if (!Dest->hasReg()) {
2661 typename InstX86Base<Machine>::Traits::Address StackAddr(
2662 static_cast<typename InstX86Base<Machine>::Traits::TargetLowering *>(
2664 ->stackVarToAsmOperand(Dest));
2665 Asm->fstp(Ty, StackAddr);
2667 // Dest is a physical (xmm) register, so st(0) needs to go through
2668 // memory. Hack this by creating a temporary stack slot, spilling
2669 // st(0) there, loading it into the xmm register, and deallocating
2671 Immediate Width(typeWidthInBytes(Ty));
2672 Asm->sub(IceType_i32,
2673 InstX86Base<Machine>::Traits::RegisterSet::Encoded_Reg_esp, Width);
2674 typename InstX86Base<Machine>::Traits::Address StackSlot =
2675 typename InstX86Base<Machine>::Traits::Address(
2676 InstX86Base<Machine>::Traits::RegisterSet::Encoded_Reg_esp, 0);
2677 Asm->fstp(Ty, StackSlot);
2678 Asm->movss(Ty, InstX86Base<Machine>::Traits::RegisterSet::getEncodedXmm(
2681 Asm->add(IceType_i32,
2682 InstX86Base<Machine>::Traits::RegisterSet::Encoded_Reg_esp, Width);
2686 template <class Machine>
2687 void InstX86Fstp<Machine>::dump(const Cfg *Func) const {
2688 if (!BuildDefs::dump())
2690 Ostream &Str = Func->getContext()->getStrDump();
2691 this->dumpDest(Func);
2692 Str << " = fstp." << this->getDest()->getType() << ", st(0)";
2695 template <class Machine>
2696 void InstX86Pcmpeq<Machine>::emit(const Cfg *Func) const {
2697 if (!BuildDefs::dump())
2701 buf, llvm::array_lengthof(buf), "pcmpeq%s",
2702 InstX86Base<Machine>::Traits::TypeAttributes[this->getDest()->getType()]
2704 this->emitTwoAddress(buf, this, Func);
2707 template <class Machine>
2708 void InstX86Pcmpgt<Machine>::emit(const Cfg *Func) const {
2709 if (!BuildDefs::dump())
2713 buf, llvm::array_lengthof(buf), "pcmpgt%s",
2714 InstX86Base<Machine>::Traits::TypeAttributes[this->getDest()->getType()]
2716 this->emitTwoAddress(buf, this, Func);
2719 template <class Machine>
2720 void InstX86Pextr<Machine>::emit(const Cfg *Func) const {
2721 if (!BuildDefs::dump())
2723 Ostream &Str = Func->getContext()->getStrEmit();
2724 assert(this->getSrcSize() == 2);
2725 // pextrb and pextrd are SSE4.1 instructions.
2726 assert(this->getSrc(0)->getType() == IceType_v8i16 ||
2727 this->getSrc(0)->getType() == IceType_v8i1 ||
2728 static_cast<typename InstX86Base<Machine>::Traits::TargetLowering *>(
2730 ->getInstructionSet() >= InstX86Base<Machine>::Traits::SSE4_1);
2731 Str << "\t" << this->Opcode
2732 << InstX86Base<Machine>::Traits::TypeAttributes[this->getSrc(0)
2734 .PackString << "\t";
2735 this->getSrc(1)->emit(Func);
2737 this->getSrc(0)->emit(Func);
2739 Variable *Dest = this->getDest();
2740 // pextrw must take a register dest. There is an SSE4.1 version that takes
2741 // a memory dest, but we aren't using it. For uniformity, just restrict
2742 // them all to have a register dest for now.
2743 assert(Dest->hasReg());
2744 Dest->asType(IceType_i32)->emit(Func);
2747 template <class Machine>
2748 void InstX86Pextr<Machine>::emitIAS(const Cfg *Func) const {
2749 assert(this->getSrcSize() == 2);
2750 // pextrb and pextrd are SSE4.1 instructions.
2751 const Variable *Dest = this->getDest();
2752 Type DispatchTy = Dest->getType();
2753 assert(DispatchTy == IceType_i16 ||
2754 static_cast<typename InstX86Base<Machine>::Traits::TargetLowering *>(
2756 ->getInstructionSet() >= InstX86Base<Machine>::Traits::SSE4_1);
2757 // pextrw must take a register dest. There is an SSE4.1 version that takes
2758 // a memory dest, but we aren't using it. For uniformity, just restrict
2759 // them all to have a register dest for now.
2760 assert(Dest->hasReg());
2761 // pextrw's Src(0) must be a register (both SSE4.1 and SSE2).
2762 assert(llvm::cast<Variable>(this->getSrc(0))->hasReg());
2763 static const typename InstX86Base<Machine>::Traits::Assembler::
2764 template ThreeOpImmEmitter<
2765 typename InstX86Base<Machine>::Traits::RegisterSet::GPRRegister,
2766 typename InstX86Base<Machine>::Traits::RegisterSet::XmmRegister>
2767 Emitter = {&InstX86Base<Machine>::Traits::Assembler::pextr, nullptr};
2768 emitIASThreeOpImmOps<
2769 Machine, typename InstX86Base<Machine>::Traits::RegisterSet::GPRRegister,
2770 typename InstX86Base<Machine>::Traits::RegisterSet::XmmRegister,
2771 InstX86Base<Machine>::Traits::RegisterSet::getEncodedGPR,
2772 InstX86Base<Machine>::Traits::RegisterSet::getEncodedXmm>(
2773 Func, DispatchTy, Dest, this->getSrc(0), this->getSrc(1), Emitter);
2776 template <class Machine>
2777 void InstX86Pinsr<Machine>::emit(const Cfg *Func) const {
2778 if (!BuildDefs::dump())
2780 Ostream &Str = Func->getContext()->getStrEmit();
2781 assert(this->getSrcSize() == 3);
2782 // pinsrb and pinsrd are SSE4.1 instructions.
2783 assert(this->getDest()->getType() == IceType_v8i16 ||
2784 this->getDest()->getType() == IceType_v8i1 ||
2785 static_cast<typename InstX86Base<Machine>::Traits::TargetLowering *>(
2787 ->getInstructionSet() >= InstX86Base<Machine>::Traits::SSE4_1);
2788 Str << "\t" << this->Opcode
2790 Machine>::Traits::TypeAttributes[this->getDest()->getType()]
2791 .PackString << "\t";
2792 this->getSrc(2)->emit(Func);
2794 Operand *Src1 = this->getSrc(1);
2795 if (const auto Src1Var = llvm::dyn_cast<Variable>(Src1)) {
2796 // If src1 is a register, it should always be r32.
2797 if (Src1Var->hasReg()) {
2798 Src1Var->asType(IceType_i32)->emit(Func);
2800 Src1Var->emit(Func);
2806 this->getDest()->emit(Func);
2809 template <class Machine>
2810 void InstX86Pinsr<Machine>::emitIAS(const Cfg *Func) const {
2811 assert(this->getSrcSize() == 3);
2812 assert(this->getDest() == this->getSrc(0));
2813 // pinsrb and pinsrd are SSE4.1 instructions.
2814 const Operand *Src0 = this->getSrc(1);
2815 Type DispatchTy = Src0->getType();
2816 assert(DispatchTy == IceType_i16 ||
2817 static_cast<typename InstX86Base<Machine>::Traits::TargetLowering *>(
2819 ->getInstructionSet() >= InstX86Base<Machine>::Traits::SSE4_1);
2820 // If src1 is a register, it should always be r32 (this should fall out
2821 // from the encodings for ByteRegs overlapping the encodings for r32),
2822 // but we have to trust the regalloc to not choose "ah", where it
2824 static const typename InstX86Base<Machine>::Traits::Assembler::
2825 template ThreeOpImmEmitter<
2826 typename InstX86Base<Machine>::Traits::RegisterSet::XmmRegister,
2827 typename InstX86Base<Machine>::Traits::RegisterSet::GPRRegister>
2828 Emitter = {&InstX86Base<Machine>::Traits::Assembler::pinsr,
2829 &InstX86Base<Machine>::Traits::Assembler::pinsr};
2830 emitIASThreeOpImmOps<
2831 Machine, typename InstX86Base<Machine>::Traits::RegisterSet::XmmRegister,
2832 typename InstX86Base<Machine>::Traits::RegisterSet::GPRRegister,
2833 InstX86Base<Machine>::Traits::RegisterSet::getEncodedXmm,
2834 InstX86Base<Machine>::Traits::RegisterSet::getEncodedGPR>(
2835 Func, DispatchTy, this->getDest(), Src0, this->getSrc(2), Emitter);
2838 template <class Machine>
2839 void InstX86Pshufd<Machine>::emitIAS(const Cfg *Func) const {
2840 assert(this->getSrcSize() == 2);
2841 const Variable *Dest = this->getDest();
2842 Type Ty = Dest->getType();
2843 static const typename InstX86Base<Machine>::Traits::Assembler::
2844 template ThreeOpImmEmitter<
2845 typename InstX86Base<Machine>::Traits::RegisterSet::XmmRegister,
2846 typename InstX86Base<Machine>::Traits::RegisterSet::XmmRegister>
2847 Emitter = {&InstX86Base<Machine>::Traits::Assembler::pshufd,
2848 &InstX86Base<Machine>::Traits::Assembler::pshufd};
2849 emitIASThreeOpImmOps<
2850 Machine, typename InstX86Base<Machine>::Traits::RegisterSet::XmmRegister,
2851 typename InstX86Base<Machine>::Traits::RegisterSet::XmmRegister,
2852 InstX86Base<Machine>::Traits::RegisterSet::getEncodedXmm,
2853 InstX86Base<Machine>::Traits::RegisterSet::getEncodedXmm>(
2854 Func, Ty, Dest, this->getSrc(0), this->getSrc(1), Emitter);
2857 template <class Machine>
2858 void InstX86Shufps<Machine>::emitIAS(const Cfg *Func) const {
2859 assert(this->getSrcSize() == 3);
2860 const Variable *Dest = this->getDest();
2861 assert(Dest == this->getSrc(0));
2862 Type Ty = Dest->getType();
2863 static const typename InstX86Base<Machine>::Traits::Assembler::
2864 template ThreeOpImmEmitter<
2865 typename InstX86Base<Machine>::Traits::RegisterSet::XmmRegister,
2866 typename InstX86Base<Machine>::Traits::RegisterSet::XmmRegister>
2867 Emitter = {&InstX86Base<Machine>::Traits::Assembler::shufps,
2868 &InstX86Base<Machine>::Traits::Assembler::shufps};
2869 emitIASThreeOpImmOps<
2870 Machine, typename InstX86Base<Machine>::Traits::RegisterSet::XmmRegister,
2871 typename InstX86Base<Machine>::Traits::RegisterSet::XmmRegister,
2872 InstX86Base<Machine>::Traits::RegisterSet::getEncodedXmm,
2873 InstX86Base<Machine>::Traits::RegisterSet::getEncodedXmm>(
2874 Func, Ty, Dest, this->getSrc(1), this->getSrc(2), Emitter);
2877 template <class Machine> void InstX86Pop<Machine>::emit(const Cfg *Func) const {
2878 if (!BuildDefs::dump())
2880 Ostream &Str = Func->getContext()->getStrEmit();
2881 assert(this->getSrcSize() == 0);
2883 this->getDest()->emit(Func);
2886 template <class Machine>
2887 void InstX86Pop<Machine>::emitIAS(const Cfg *Func) const {
2888 assert(this->getSrcSize() == 0);
2889 typename InstX86Base<Machine>::Traits::Assembler *Asm =
2890 Func->getAssembler<typename InstX86Base<Machine>::Traits::Assembler>();
2891 if (this->getDest()->hasReg()) {
2892 Asm->popl(InstX86Base<Machine>::Traits::RegisterSet::getEncodedGPR(
2893 this->getDest()->getRegNum()));
2896 static_cast<typename InstX86Base<Machine>::Traits::TargetLowering *>(
2898 ->stackVarToAsmOperand(this->getDest()));
2902 template <class Machine> void InstX86Pop<Machine>::dump(const Cfg *Func) const {
2903 if (!BuildDefs::dump())
2905 Ostream &Str = Func->getContext()->getStrDump();
2906 this->dumpDest(Func);
2907 Str << " = pop." << this->getDest()->getType() << " ";
2910 template <class Machine>
2911 void InstX86AdjustStack<Machine>::emit(const Cfg *Func) const {
2912 if (!BuildDefs::dump())
2914 Ostream &Str = Func->getContext()->getStrEmit();
2915 Str << "\tsubl\t$" << Amount << ", %esp";
2916 Func->getTarget()->updateStackAdjustment(Amount);
2919 template <class Machine>
2920 void InstX86AdjustStack<Machine>::emitIAS(const Cfg *Func) const {
2921 typename InstX86Base<Machine>::Traits::Assembler *Asm =
2922 Func->getAssembler<typename InstX86Base<Machine>::Traits::Assembler>();
2923 Asm->sub(IceType_i32,
2924 InstX86Base<Machine>::Traits::RegisterSet::Encoded_Reg_esp,
2926 Func->getTarget()->updateStackAdjustment(Amount);
2929 template <class Machine>
2930 void InstX86AdjustStack<Machine>::dump(const Cfg *Func) const {
2931 if (!BuildDefs::dump())
2933 Ostream &Str = Func->getContext()->getStrDump();
2934 Str << "esp = sub.i32 esp, " << Amount;
2937 template <class Machine>
2938 void InstX86Push<Machine>::emit(const Cfg *Func) const {
2939 if (!BuildDefs::dump())
2941 Ostream &Str = Func->getContext()->getStrEmit();
2942 assert(this->getSrcSize() == 1);
2943 // Push is currently only used for saving GPRs.
2944 const auto Var = llvm::cast<Variable>(this->getSrc(0));
2945 assert(Var->hasReg());
2950 template <class Machine>
2951 void InstX86Push<Machine>::emitIAS(const Cfg *Func) const {
2952 assert(this->getSrcSize() == 1);
2953 // Push is currently only used for saving GPRs.
2954 const auto Var = llvm::cast<Variable>(this->getSrc(0));
2955 assert(Var->hasReg());
2956 typename InstX86Base<Machine>::Traits::Assembler *Asm =
2957 Func->getAssembler<typename InstX86Base<Machine>::Traits::Assembler>();
2958 Asm->pushl(InstX86Base<Machine>::Traits::RegisterSet::getEncodedGPR(
2962 template <class Machine>
2963 void InstX86Push<Machine>::dump(const Cfg *Func) const {
2964 if (!BuildDefs::dump())
2966 Ostream &Str = Func->getContext()->getStrDump();
2967 Str << "push." << this->getSrc(0)->getType() << " ";
2968 this->dumpSources(Func);
2971 template <class Machine>
2972 void InstX86Psll<Machine>::emit(const Cfg *Func) const {
2973 if (!BuildDefs::dump())
2975 assert(this->getDest()->getType() == IceType_v8i16 ||
2976 this->getDest()->getType() == IceType_v8i1 ||
2977 this->getDest()->getType() == IceType_v4i32 ||
2978 this->getDest()->getType() == IceType_v4i1);
2981 buf, llvm::array_lengthof(buf), "psll%s",
2982 InstX86Base<Machine>::Traits::TypeAttributes[this->getDest()->getType()]
2984 this->emitTwoAddress(buf, this, Func);
2987 template <class Machine>
2988 void InstX86Psra<Machine>::emit(const Cfg *Func) const {
2989 if (!BuildDefs::dump())
2991 assert(this->getDest()->getType() == IceType_v8i16 ||
2992 this->getDest()->getType() == IceType_v8i1 ||
2993 this->getDest()->getType() == IceType_v4i32 ||
2994 this->getDest()->getType() == IceType_v4i1);
2997 buf, llvm::array_lengthof(buf), "psra%s",
2998 InstX86Base<Machine>::Traits::TypeAttributes[this->getDest()->getType()]
3000 this->emitTwoAddress(buf, this, Func);
3003 template <class Machine>
3004 void InstX86Psrl<Machine>::emit(const Cfg *Func) const {
3005 if (!BuildDefs::dump())
3009 buf, llvm::array_lengthof(buf), "psrl%s",
3010 InstX86Base<Machine>::Traits::TypeAttributes[this->getDest()->getType()]
3012 this->emitTwoAddress(buf, this, Func);
3015 template <class Machine> void InstX86Ret<Machine>::emit(const Cfg *Func) const {
3016 if (!BuildDefs::dump())
3018 Ostream &Str = Func->getContext()->getStrEmit();
3022 template <class Machine>
3023 void InstX86Ret<Machine>::emitIAS(const Cfg *Func) const {
3024 typename InstX86Base<Machine>::Traits::Assembler *Asm =
3025 Func->getAssembler<typename InstX86Base<Machine>::Traits::Assembler>();
3029 template <class Machine> void InstX86Ret<Machine>::dump(const Cfg *Func) const {
3030 if (!BuildDefs::dump())
3032 Ostream &Str = Func->getContext()->getStrDump();
3034 (this->getSrcSize() == 0 ? IceType_void : this->getSrc(0)->getType());
3035 Str << "ret." << Ty << " ";
3036 this->dumpSources(Func);
3039 template <class Machine>
3040 void InstX86Setcc<Machine>::emit(const Cfg *Func) const {
3041 if (!BuildDefs::dump())
3043 Ostream &Str = Func->getContext()->getStrEmit();
3045 << InstX86Base<Machine>::Traits::InstBrAttributes[Condition].DisplayString
3047 this->Dest->emit(Func);
3050 template <class Machine>
3051 void InstX86Setcc<Machine>::emitIAS(const Cfg *Func) const {
3052 assert(Condition != InstX86Base<Machine>::Traits::Cond::Br_None);
3053 assert(this->getDest()->getType() == IceType_i1);
3054 assert(this->getSrcSize() == 0);
3055 typename InstX86Base<Machine>::Traits::Assembler *Asm =
3056 Func->getAssembler<typename InstX86Base<Machine>::Traits::Assembler>();
3057 if (this->getDest()->hasReg())
3058 Asm->setcc(Condition,
3059 InstX86Base<Machine>::Traits::RegisterSet::getEncodedByteReg(
3060 this->getDest()->getRegNum()));
3064 static_cast<typename InstX86Base<Machine>::Traits::TargetLowering *>(
3066 ->stackVarToAsmOperand(this->getDest()));
3070 template <class Machine>
3071 void InstX86Setcc<Machine>::dump(const Cfg *Func) const {
3072 if (!BuildDefs::dump())
3074 Ostream &Str = Func->getContext()->getStrDump();
3076 << InstX86Base<Machine>::Traits::InstBrAttributes[Condition].DisplayString
3078 this->dumpDest(Func);
3081 template <class Machine>
3082 void InstX86Xadd<Machine>::emit(const Cfg *Func) const {
3083 if (!BuildDefs::dump())
3085 Ostream &Str = Func->getContext()->getStrEmit();
3089 Str << "\txadd" << this->getWidthString(this->getSrc(0)->getType()) << "\t";
3090 this->getSrc(1)->emit(Func);
3092 this->getSrc(0)->emit(Func);
3095 template <class Machine>
3096 void InstX86Xadd<Machine>::emitIAS(const Cfg *Func) const {
3097 assert(this->getSrcSize() == 2);
3098 typename InstX86Base<Machine>::Traits::Assembler *Asm =
3099 Func->getAssembler<typename InstX86Base<Machine>::Traits::Assembler>();
3100 Type Ty = this->getSrc(0)->getType();
3102 llvm::cast<typename InstX86Base<Machine>::Traits::X86OperandMem>(
3104 assert(Mem->getSegmentRegister() ==
3105 InstX86Base<Machine>::Traits::X86OperandMem::DefaultSegment);
3106 const typename InstX86Base<Machine>::Traits::Address Addr =
3107 Mem->toAsmAddress(Asm);
3108 const auto VarReg = llvm::cast<Variable>(this->getSrc(1));
3109 assert(VarReg->hasReg());
3110 const typename InstX86Base<Machine>::Traits::RegisterSet::GPRRegister Reg =
3111 InstX86Base<Machine>::Traits::RegisterSet::getEncodedGPR(
3112 VarReg->getRegNum());
3113 Asm->xadd(Ty, Addr, Reg, this->Locked);
3116 template <class Machine>
3117 void InstX86Xadd<Machine>::dump(const Cfg *Func) const {
3118 if (!BuildDefs::dump())
3120 Ostream &Str = Func->getContext()->getStrDump();
3124 Type Ty = this->getSrc(0)->getType();
3125 Str << "xadd." << Ty << " ";
3126 this->dumpSources(Func);
3129 template <class Machine>
3130 void InstX86Xchg<Machine>::emit(const Cfg *Func) const {
3131 if (!BuildDefs::dump())
3133 Ostream &Str = Func->getContext()->getStrEmit();
3134 Str << "\txchg" << this->getWidthString(this->getSrc(0)->getType()) << "\t";
3135 this->getSrc(1)->emit(Func);
3137 this->getSrc(0)->emit(Func);
3140 template <class Machine>
3141 void InstX86Xchg<Machine>::emitIAS(const Cfg *Func) const {
3142 assert(this->getSrcSize() == 2);
3143 typename InstX86Base<Machine>::Traits::Assembler *Asm =
3144 Func->getAssembler<typename InstX86Base<Machine>::Traits::Assembler>();
3145 Type Ty = this->getSrc(0)->getType();
3147 llvm::cast<typename InstX86Base<Machine>::Traits::X86OperandMem>(
3149 assert(Mem->getSegmentRegister() ==
3150 InstX86Base<Machine>::Traits::X86OperandMem::DefaultSegment);
3151 const typename InstX86Base<Machine>::Traits::Address Addr =
3152 Mem->toAsmAddress(Asm);
3153 const auto VarReg = llvm::cast<Variable>(this->getSrc(1));
3154 assert(VarReg->hasReg());
3155 const typename InstX86Base<Machine>::Traits::RegisterSet::GPRRegister Reg =
3156 InstX86Base<Machine>::Traits::RegisterSet::getEncodedGPR(
3157 VarReg->getRegNum());
3158 Asm->xchg(Ty, Addr, Reg);
3161 template <class Machine>
3162 void InstX86Xchg<Machine>::dump(const Cfg *Func) const {
3163 if (!BuildDefs::dump())
3165 Ostream &Str = Func->getContext()->getStrDump();
3166 Type Ty = this->getSrc(0)->getType();
3167 Str << "xchg." << Ty << " ";
3168 this->dumpSources(Func);
3171 template <class Machine>
3172 void InstX86IacaStart<Machine>::emit(const Cfg *Func) const {
3173 if (!BuildDefs::dump())
3175 Ostream &Str = Func->getContext()->getStrEmit();
3176 Str << "\t# IACA_START\n"
3177 << "\t.byte 0x0F, 0x0B\n"
3178 << "\tmovl\t$111, %ebx\n"
3179 << "\t.byte 0x64, 0x67, 0x90";
3182 template <class Machine>
3183 void InstX86IacaStart<Machine>::emitIAS(const Cfg *Func) const {
3184 typename InstX86Base<Machine>::Traits::Assembler *Asm =
3185 Func->getAssembler<typename InstX86Base<Machine>::Traits::Assembler>();
3189 template <class Machine>
3190 void InstX86IacaStart<Machine>::dump(const Cfg *Func) const {
3191 if (!BuildDefs::dump())
3193 Ostream &Str = Func->getContext()->getStrDump();
3194 Str << "IACA_START";
3197 template <class Machine>
3198 void InstX86IacaEnd<Machine>::emit(const Cfg *Func) const {
3199 if (!BuildDefs::dump())
3201 Ostream &Str = Func->getContext()->getStrEmit();
3202 Str << "\t# IACA_END\n"
3203 << "\tmovl\t$222, %ebx\n"
3204 << "\t.byte 0x64, 0x67, 0x90\n"
3205 << "\t.byte 0x0F, 0x0B";
3208 template <class Machine>
3209 void InstX86IacaEnd<Machine>::emitIAS(const Cfg *Func) const {
3210 typename InstX86Base<Machine>::Traits::Assembler *Asm =
3211 Func->getAssembler<typename InstX86Base<Machine>::Traits::Assembler>();
3215 template <class Machine>
3216 void InstX86IacaEnd<Machine>::dump(const Cfg *Func) const {
3217 if (!BuildDefs::dump())
3219 Ostream &Str = Func->getContext()->getStrDump();
3223 } // end of namespace X86Internal
3225 } // end of namespace Ice
3227 #endif // SUBZERO_SRC_ICEINSTX86BASEIMPL_H