OSDN Git Service

Optimize 64-bit shifts by constants for x86-32
[android-x86/external-swiftshader.git] / src / IceInstX86BaseImpl.h
1 //===- subzero/src/IceInstX86BaseImpl.h - Generic X86 instructions -*- C++ -*=//
2 //
3 //                        The Subzero Code Generator
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 ///
10 /// \file
11 /// This file implements the InstX86Base class and its descendants.
12 ///
13 //===----------------------------------------------------------------------===//
14
15 #ifndef SUBZERO_SRC_ICEINSTX86BASEIMPL_H
16 #define SUBZERO_SRC_ICEINSTX86BASEIMPL_H
17
18 #include "IceInstX86Base.h"
19
20 #include "IceAssemblerX86Base.h"
21 #include "IceCfg.h"
22 #include "IceCfgNode.h"
23 #include "IceDefs.h"
24 #include "IceInst.h"
25 #include "IceOperand.h"
26 #include "IceTargetLowering.h"
27
28 namespace Ice {
29
30 namespace X86Internal {
31
32 template <class Machine>
33 const char *InstX86Base<Machine>::getWidthString(Type Ty) {
34   return Traits::TypeAttributes[Ty].WidthString;
35 }
36
37 template <class Machine>
38 const char *InstX86Base<Machine>::getFldString(Type Ty) {
39   return Traits::TypeAttributes[Ty].FldString;
40 }
41
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;
46 }
47
48 template <class Machine>
49 InstX86FakeRMW<Machine>::InstX86FakeRMW(Cfg *Func, Operand *Data, Operand *Addr,
50                                         InstArithmetic::OpKind Op,
51                                         Variable *Beacon)
52     : InstX86Base<Machine>(Func, InstX86Base<Machine>::FakeRMW, 3, nullptr),
53       Op(Op) {
54   this->addSource(Data);
55   this->addSource(Addr);
56   this->addSource(Beacon);
57 }
58
59 template <class Machine>
60 InstX86AdjustStack<Machine>::InstX86AdjustStack(Cfg *Func, SizeT Amount,
61                                                 Variable *Esp)
62     : InstX86Base<Machine>(Func, InstX86Base<Machine>::Adjuststack, 1, Esp),
63       Amount(Amount) {
64   this->addSource(Esp);
65 }
66
67 template <class Machine>
68 InstX86Mul<Machine>::InstX86Mul(Cfg *Func, Variable *Dest, Variable *Source1,
69                                 Operand *Source2)
70     : InstX86Base<Machine>(Func, InstX86Base<Machine>::Mul, 2, Dest) {
71   this->addSource(Source1);
72   this->addSource(Source2);
73 }
74
75 template <class Machine>
76 InstX86Shld<Machine>::InstX86Shld(Cfg *Func, Variable *Dest, Variable *Source1,
77                                   Operand *Source2)
78     : InstX86Base<Machine>(Func, InstX86Base<Machine>::Shld, 3, Dest) {
79   this->addSource(Dest);
80   this->addSource(Source1);
81   this->addSource(Source2);
82 }
83
84 template <class Machine>
85 InstX86Shrd<Machine>::InstX86Shrd(Cfg *Func, Variable *Dest, Variable *Source1,
86                                   Operand *Source2)
87     : InstX86Base<Machine>(Func, InstX86Base<Machine>::Shrd, 3, Dest) {
88   this->addSource(Dest);
89   this->addSource(Source1);
90   this->addSource(Source2);
91 }
92
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()) {}
98
99 template <class Machine>
100 IceString InstX86Label<Machine>::getName(const Cfg *Func) const {
101   return ".L" + Func->getFunctionName() + "$local$__" + std::to_string(Number);
102 }
103
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) {}
112
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 optimize.
116   if (NextNode == nullptr)
117     return false;
118   // Intra-block conditional branches can't be optimized.
119   if (Label)
120     return false;
121   // If there is no fallthrough node, such as a non-default case label for a
122   // switch instruction, then there is no opportunity to optimize.
123   if (getTargetFalse() == nullptr)
124     return false;
125
126   // Unconditional branch to the next node can be removed.
127   if (Condition == InstX86Base<Machine>::Traits::Cond::Br_None &&
128       getTargetFalse() == NextNode) {
129     assert(getTargetTrue() == nullptr);
130     this->setDeleted();
131     return true;
132   }
133   // If the fallthrough is to the next node, set fallthrough to nullptr to
134   // indicate.
135   if (getTargetFalse() == NextNode) {
136     TargetFalse = nullptr;
137     return true;
138   }
139   // If TargetTrue is the next node, and TargetFalse is not nullptr (which was
140   // already tested above), then invert the branch condition, swap the targets,
141   // and set new fallthrough to nullptr.
142   if (getTargetTrue() == NextNode) {
143     assert(Condition != InstX86Base<Machine>::Traits::Cond::Br_None);
144     Condition = this->getOppositeCondition(Condition);
145     TargetTrue = getTargetFalse();
146     TargetFalse = nullptr;
147     return true;
148   }
149   return false;
150 }
151
152 template <class Machine>
153 bool InstX86Br<Machine>::repointEdges(CfgNode *OldNode, CfgNode *NewNode) {
154   bool Found = false;
155   if (TargetFalse == OldNode) {
156     TargetFalse = NewNode;
157     Found = true;
158   }
159   if (TargetTrue == OldNode) {
160     TargetTrue = NewNode;
161     Found = true;
162   }
163   return Found;
164 }
165
166 template <class Machine>
167 InstX86Jmp<Machine>::InstX86Jmp(Cfg *Func, Operand *Target)
168     : InstX86Base<Machine>(Func, InstX86Base<Machine>::Jmp, 1, nullptr) {
169   this->addSource(Target);
170 }
171
172 template <class Machine>
173 InstX86Call<Machine>::InstX86Call(Cfg *Func, Variable *Dest,
174                                   Operand *CallTarget)
175     : InstX86Base<Machine>(Func, InstX86Base<Machine>::Call, 1, Dest) {
176   this->HasSideEffects = true;
177   this->addSource(CallTarget);
178 }
179
180 template <class Machine>
181 InstX86Cmov<Machine>::InstX86Cmov(
182     Cfg *Func, Variable *Dest, Operand *Source,
183     typename InstX86Base<Machine>::Traits::Cond::BrCond Condition)
184     : InstX86Base<Machine>(Func, InstX86Base<Machine>::Cmov, 2, Dest),
185       Condition(Condition) {
186   // The final result is either the original Dest, or Source, so mark both as
187   // sources.
188   this->addSource(Dest);
189   this->addSource(Source);
190 }
191
192 template <class Machine>
193 InstX86Cmpps<Machine>::InstX86Cmpps(
194     Cfg *Func, Variable *Dest, Operand *Source,
195     typename InstX86Base<Machine>::Traits::Cond::CmppsCond Condition)
196     : InstX86Base<Machine>(Func, InstX86Base<Machine>::Cmpps, 2, Dest),
197       Condition(Condition) {
198   this->addSource(Dest);
199   this->addSource(Source);
200 }
201
202 template <class Machine>
203 InstX86Cmpxchg<Machine>::InstX86Cmpxchg(Cfg *Func, Operand *DestOrAddr,
204                                         Variable *Eax, Variable *Desired,
205                                         bool Locked)
206     : InstX86BaseLockable<Machine>(Func, InstX86Base<Machine>::Cmpxchg, 3,
207                                    llvm::dyn_cast<Variable>(DestOrAddr),
208                                    Locked) {
209   assert(Eax->getRegNum() ==
210          InstX86Base<Machine>::Traits::RegisterSet::Reg_eax);
211   this->addSource(DestOrAddr);
212   this->addSource(Eax);
213   this->addSource(Desired);
214 }
215
216 template <class Machine>
217 InstX86Cmpxchg8b<Machine>::InstX86Cmpxchg8b(
218     Cfg *Func, typename InstX86Base<Machine>::Traits::X86OperandMem *Addr,
219     Variable *Edx, Variable *Eax, Variable *Ecx, Variable *Ebx, bool Locked)
220     : InstX86BaseLockable<Machine>(Func, InstX86Base<Machine>::Cmpxchg, 5,
221                                    nullptr, Locked) {
222   assert(Edx->getRegNum() ==
223          InstX86Base<Machine>::Traits::RegisterSet::Reg_edx);
224   assert(Eax->getRegNum() ==
225          InstX86Base<Machine>::Traits::RegisterSet::Reg_eax);
226   assert(Ecx->getRegNum() ==
227          InstX86Base<Machine>::Traits::RegisterSet::Reg_ecx);
228   assert(Ebx->getRegNum() ==
229          InstX86Base<Machine>::Traits::RegisterSet::Reg_ebx);
230   this->addSource(Addr);
231   this->addSource(Edx);
232   this->addSource(Eax);
233   this->addSource(Ecx);
234   this->addSource(Ebx);
235 }
236
237 template <class Machine>
238 InstX86Cvt<Machine>::InstX86Cvt(Cfg *Func, Variable *Dest, Operand *Source,
239                                 CvtVariant Variant)
240     : InstX86Base<Machine>(Func, InstX86Base<Machine>::Cvt, 1, Dest),
241       Variant(Variant) {
242   this->addSource(Source);
243 }
244
245 template <class Machine>
246 InstX86Icmp<Machine>::InstX86Icmp(Cfg *Func, Operand *Src0, Operand *Src1)
247     : InstX86Base<Machine>(Func, InstX86Base<Machine>::Icmp, 2, nullptr) {
248   this->addSource(Src0);
249   this->addSource(Src1);
250 }
251
252 template <class Machine>
253 InstX86Ucomiss<Machine>::InstX86Ucomiss(Cfg *Func, Operand *Src0, Operand *Src1)
254     : InstX86Base<Machine>(Func, InstX86Base<Machine>::Ucomiss, 2, nullptr) {
255   this->addSource(Src0);
256   this->addSource(Src1);
257 }
258
259 template <class Machine>
260 InstX86UD2<Machine>::InstX86UD2(Cfg *Func)
261     : InstX86Base<Machine>(Func, InstX86Base<Machine>::UD2, 0, nullptr) {}
262
263 template <class Machine>
264 InstX86Test<Machine>::InstX86Test(Cfg *Func, Operand *Src1, Operand *Src2)
265     : InstX86Base<Machine>(Func, InstX86Base<Machine>::Test, 2, nullptr) {
266   this->addSource(Src1);
267   this->addSource(Src2);
268 }
269
270 template <class Machine>
271 InstX86Mfence<Machine>::InstX86Mfence(Cfg *Func)
272     : InstX86Base<Machine>(Func, InstX86Base<Machine>::Mfence, 0, nullptr) {
273   this->HasSideEffects = true;
274 }
275
276 template <class Machine>
277 InstX86Store<Machine>::InstX86Store(
278     Cfg *Func, Operand *Value,
279     typename InstX86Base<Machine>::Traits::X86Operand *Mem)
280     : InstX86Base<Machine>(Func, InstX86Base<Machine>::Store, 2, nullptr) {
281   this->addSource(Value);
282   this->addSource(Mem);
283 }
284
285 template <class Machine>
286 InstX86StoreP<Machine>::InstX86StoreP(
287     Cfg *Func, Variable *Value,
288     typename InstX86Base<Machine>::Traits::X86OperandMem *Mem)
289     : InstX86Base<Machine>(Func, InstX86Base<Machine>::StoreP, 2, nullptr) {
290   this->addSource(Value);
291   this->addSource(Mem);
292 }
293
294 template <class Machine>
295 InstX86StoreQ<Machine>::InstX86StoreQ(
296     Cfg *Func, Variable *Value,
297     typename InstX86Base<Machine>::Traits::X86OperandMem *Mem)
298     : InstX86Base<Machine>(Func, InstX86Base<Machine>::StoreQ, 2, nullptr) {
299   this->addSource(Value);
300   this->addSource(Mem);
301 }
302
303 template <class Machine>
304 InstX86Nop<Machine>::InstX86Nop(Cfg *Func, InstX86Nop::NopVariant Variant)
305     : InstX86Base<Machine>(Func, InstX86Base<Machine>::Nop, 0, nullptr),
306       Variant(Variant) {}
307
308 template <class Machine>
309 InstX86Fld<Machine>::InstX86Fld(Cfg *Func, Operand *Src)
310     : InstX86Base<Machine>(Func, InstX86Base<Machine>::Fld, 1, nullptr) {
311   this->addSource(Src);
312 }
313
314 template <class Machine>
315 InstX86Fstp<Machine>::InstX86Fstp(Cfg *Func, Variable *Dest)
316     : InstX86Base<Machine>(Func, InstX86Base<Machine>::Fstp, 0, Dest) {}
317
318 template <class Machine>
319 InstX86Pop<Machine>::InstX86Pop(Cfg *Func, Variable *Dest)
320     : InstX86Base<Machine>(Func, InstX86Base<Machine>::Pop, 0, Dest) {
321   // A pop instruction affects the stack pointer and so it should not be
322   // allowed to be automatically dead-code eliminated. (The corresponding push
323   // instruction doesn't need this treatment because it has no dest variable
324   // and therefore won't be dead-code eliminated.) This is needed for
325   // late-stage liveness analysis (e.g. asm-verbose mode).
326   this->HasSideEffects = true;
327 }
328
329 template <class Machine>
330 InstX86Push<Machine>::InstX86Push(Cfg *Func, Variable *Source)
331     : InstX86Base<Machine>(Func, InstX86Base<Machine>::Push, 1, nullptr) {
332   this->addSource(Source);
333 }
334
335 template <class Machine>
336 InstX86Ret<Machine>::InstX86Ret(Cfg *Func, Variable *Source)
337     : InstX86Base<Machine>(Func, InstX86Base<Machine>::Ret, Source ? 1 : 0,
338                            nullptr) {
339   if (Source)
340     this->addSource(Source);
341 }
342
343 template <class Machine>
344 InstX86Setcc<Machine>::InstX86Setcc(
345     Cfg *Func, Variable *Dest,
346     typename InstX86Base<Machine>::Traits::Cond::BrCond Cond)
347     : InstX86Base<Machine>(Func, InstX86Base<Machine>::Setcc, 0, Dest),
348       Condition(Cond) {}
349
350 template <class Machine>
351 InstX86Xadd<Machine>::InstX86Xadd(Cfg *Func, Operand *Dest, Variable *Source,
352                                   bool Locked)
353     : InstX86BaseLockable<Machine>(Func, InstX86Base<Machine>::Xadd, 2,
354                                    llvm::dyn_cast<Variable>(Dest), Locked) {
355   this->addSource(Dest);
356   this->addSource(Source);
357 }
358
359 template <class Machine>
360 InstX86Xchg<Machine>::InstX86Xchg(Cfg *Func, Operand *Dest, Variable *Source)
361     : InstX86Base<Machine>(Func, InstX86Base<Machine>::Xchg, 2,
362                            llvm::dyn_cast<Variable>(Dest)) {
363   this->addSource(Dest);
364   this->addSource(Source);
365 }
366
367 template <class Machine>
368 InstX86IacaStart<Machine>::InstX86IacaStart(Cfg *Func)
369     : InstX86Base<Machine>(Func, InstX86Base<Machine>::IacaStart, 0, nullptr) {
370   assert(Func->getContext()->getFlags().getAllowIacaMarks());
371 }
372
373 template <class Machine>
374 InstX86IacaEnd<Machine>::InstX86IacaEnd(Cfg *Func)
375     : InstX86Base<Machine>(Func, InstX86Base<Machine>::IacaEnd, 0, nullptr) {
376   assert(Func->getContext()->getFlags().getAllowIacaMarks());
377 }
378
379 // ======================== Dump routines ======================== //
380
381 template <class Machine>
382 void InstX86Base<Machine>::dump(const Cfg *Func) const {
383   if (!BuildDefs::dump())
384     return;
385   Ostream &Str = Func->getContext()->getStrDump();
386   Str << "[" << Traits::TargetName << "] ";
387   Inst::dump(Func);
388 }
389
390 template <class Machine>
391 void InstX86FakeRMW<Machine>::dump(const Cfg *Func) const {
392   if (!BuildDefs::dump())
393     return;
394   Ostream &Str = Func->getContext()->getStrDump();
395   Type Ty = getData()->getType();
396   Str << "rmw " << InstArithmetic::getOpName(getOp()) << " " << Ty << " *";
397   getAddr()->dump(Func);
398   Str << ", ";
399   getData()->dump(Func);
400   Str << ", beacon=";
401   getBeacon()->dump(Func);
402 }
403
404 template <class Machine>
405 void InstX86Label<Machine>::emit(const Cfg *Func) const {
406   if (!BuildDefs::dump())
407     return;
408   Ostream &Str = Func->getContext()->getStrEmit();
409   Str << getName(Func) << ":";
410 }
411
412 template <class Machine>
413 void InstX86Label<Machine>::emitIAS(const Cfg *Func) const {
414   typename InstX86Base<Machine>::Traits::Assembler *Asm =
415       Func->getAssembler<typename InstX86Base<Machine>::Traits::Assembler>();
416   Asm->bindLocalLabel(Number);
417 }
418
419 template <class Machine>
420 void InstX86Label<Machine>::dump(const Cfg *Func) const {
421   if (!BuildDefs::dump())
422     return;
423   Ostream &Str = Func->getContext()->getStrDump();
424   Str << getName(Func) << ":";
425 }
426
427 template <class Machine> void InstX86Br<Machine>::emit(const Cfg *Func) const {
428   if (!BuildDefs::dump())
429     return;
430   Ostream &Str = Func->getContext()->getStrEmit();
431   Str << "\t";
432
433   if (Condition == InstX86Base<Machine>::Traits::Cond::Br_None) {
434     Str << "jmp";
435   } else {
436     Str << InstX86Base<Machine>::Traits::InstBrAttributes[Condition].EmitString;
437   }
438
439   if (Label) {
440     Str << "\t" << Label->getName(Func);
441   } else {
442     if (Condition == InstX86Base<Machine>::Traits::Cond::Br_None) {
443       Str << "\t" << getTargetFalse()->getAsmName();
444     } else {
445       Str << "\t" << getTargetTrue()->getAsmName();
446       if (getTargetFalse()) {
447         Str << "\n\tjmp\t" << getTargetFalse()->getAsmName();
448       }
449     }
450   }
451 }
452
453 template <class Machine>
454 void InstX86Br<Machine>::emitIAS(const Cfg *Func) const {
455   typename InstX86Base<Machine>::Traits::Assembler *Asm =
456       Func->getAssembler<typename InstX86Base<Machine>::Traits::Assembler>();
457   if (Label) {
458     class Label *L = Asm->getOrCreateLocalLabel(Label->getNumber());
459     if (Condition == InstX86Base<Machine>::Traits::Cond::Br_None) {
460       Asm->jmp(L, isNear());
461     } else {
462       Asm->j(Condition, L, isNear());
463     }
464   } else {
465     if (Condition == InstX86Base<Machine>::Traits::Cond::Br_None) {
466       class Label *L =
467           Asm->getOrCreateCfgNodeLabel(getTargetFalse()->getIndex());
468       assert(!getTargetTrue());
469       Asm->jmp(L, isNear());
470     } else {
471       class Label *L =
472           Asm->getOrCreateCfgNodeLabel(getTargetTrue()->getIndex());
473       Asm->j(Condition, L, isNear());
474       if (getTargetFalse()) {
475         class Label *L2 =
476             Asm->getOrCreateCfgNodeLabel(getTargetFalse()->getIndex());
477         Asm->jmp(L2, isNear());
478       }
479     }
480   }
481 }
482
483 template <class Machine> void InstX86Br<Machine>::dump(const Cfg *Func) const {
484   if (!BuildDefs::dump())
485     return;
486   Ostream &Str = Func->getContext()->getStrDump();
487   Str << "br ";
488
489   if (Condition == InstX86Base<Machine>::Traits::Cond::Br_None) {
490     Str << "label %"
491         << (Label ? Label->getName(Func) : getTargetFalse()->getName());
492     return;
493   }
494
495   Str << InstX86Base<Machine>::Traits::InstBrAttributes[Condition]
496              .DisplayString;
497   if (Label) {
498     Str << ", label %" << Label->getName(Func);
499   } else {
500     Str << ", label %" << getTargetTrue()->getName();
501     if (getTargetFalse()) {
502       Str << ", label %" << getTargetFalse()->getName();
503     }
504   }
505
506   Str << " // (" << (isNear() ? "near" : "far") << " jump)";
507 }
508
509 template <class Machine> void InstX86Jmp<Machine>::emit(const Cfg *Func) const {
510   if (!BuildDefs::dump())
511     return;
512   Ostream &Str = Func->getContext()->getStrEmit();
513   assert(this->getSrcSize() == 1);
514   Str << "\tjmp\t*";
515   getJmpTarget()->emit(Func);
516 }
517
518 template <class Machine>
519 void InstX86Jmp<Machine>::emitIAS(const Cfg *Func) const {
520   // Note: Adapted (mostly copied) from InstX86Call<Machine>::emitIAS().
521   typename InstX86Base<Machine>::Traits::Assembler *Asm =
522       Func->getAssembler<typename InstX86Base<Machine>::Traits::Assembler>();
523   Operand *Target = getJmpTarget();
524   if (const auto Var = llvm::dyn_cast<Variable>(Target)) {
525     if (Var->hasReg()) {
526       Asm->jmp(InstX86Base<Machine>::Traits::RegisterSet::getEncodedGPR(
527           Var->getRegNum()));
528     } else {
529       // The jmp instruction with a memory operand should be possible to
530       // encode, but it isn't a valid sandboxed instruction, and there
531       // shouldn't be a register allocation issue to jump through a scratch
532       // register, so we don't really need to bother implementing it.
533       llvm::report_fatal_error("Assembler can't jmp to memory operand");
534     }
535   } else if (const auto Mem = llvm::dyn_cast<
536                  typename InstX86Base<Machine>::Traits::X86OperandMem>(
537                  Target)) {
538     (void)Mem;
539     assert(Mem->getSegmentRegister() ==
540            InstX86Base<Machine>::Traits::X86OperandMem::DefaultSegment);
541     llvm::report_fatal_error("Assembler can't jmp to memory operand");
542   } else if (const auto CR = llvm::dyn_cast<ConstantRelocatable>(Target)) {
543     assert(CR->getOffset() == 0 && "We only support jumping to a function");
544     Asm->jmp(CR);
545   } else if (const auto Imm = llvm::dyn_cast<ConstantInteger32>(Target)) {
546     // NaCl trampoline calls refer to an address within the sandbox directly.
547     // This is usually only needed for non-IRT builds and otherwise not very
548     // portable or stable. Usually this is only done for "calls" and not jumps.
549     // TODO(jvoung): Support this when there is a lowering that actually
550     // triggers this case.
551     (void)Imm;
552     llvm::report_fatal_error("Unexpected jmp to absolute address");
553   } else {
554     llvm::report_fatal_error("Unexpected operand type");
555   }
556 }
557
558 template <class Machine> void InstX86Jmp<Machine>::dump(const Cfg *Func) const {
559   if (!BuildDefs::dump())
560     return;
561   Ostream &Str = Func->getContext()->getStrDump();
562   Str << "jmp ";
563   getJmpTarget()->dump(Func);
564 }
565
566 template <class Machine>
567 void InstX86Call<Machine>::emit(const Cfg *Func) const {
568   if (!BuildDefs::dump())
569     return;
570   Ostream &Str = Func->getContext()->getStrEmit();
571   assert(this->getSrcSize() == 1);
572   Str << "\tcall\t";
573   if (const auto CI = llvm::dyn_cast<ConstantInteger32>(getCallTarget())) {
574     // Emit without a leading '$'.
575     Str << CI->getValue();
576   } else if (const auto CallTarget =
577                  llvm::dyn_cast<ConstantRelocatable>(getCallTarget())) {
578     CallTarget->emitWithoutPrefix(Func->getTarget());
579   } else {
580     Str << "*";
581     getCallTarget()->emit(Func);
582   }
583   Func->getTarget()->resetStackAdjustment();
584 }
585
586 template <class Machine>
587 void InstX86Call<Machine>::emitIAS(const Cfg *Func) const {
588   typename InstX86Base<Machine>::Traits::Assembler *Asm =
589       Func->getAssembler<typename InstX86Base<Machine>::Traits::Assembler>();
590   Operand *Target = getCallTarget();
591   if (const auto Var = llvm::dyn_cast<Variable>(Target)) {
592     if (Var->hasReg()) {
593       Asm->call(InstX86Base<Machine>::Traits::RegisterSet::getEncodedGPR(
594           Var->getRegNum()));
595     } else {
596       Asm->call(
597           static_cast<typename InstX86Base<Machine>::Traits::TargetLowering *>(
598               Func->getTarget())
599               ->stackVarToAsmOperand(Var));
600     }
601   } else if (const auto Mem = llvm::dyn_cast<
602                  typename InstX86Base<Machine>::Traits::X86OperandMem>(
603                  Target)) {
604     assert(Mem->getSegmentRegister() ==
605            InstX86Base<Machine>::Traits::X86OperandMem::DefaultSegment);
606     Asm->call(Mem->toAsmAddress(Asm));
607   } else if (const auto CR = llvm::dyn_cast<ConstantRelocatable>(Target)) {
608     assert(CR->getOffset() == 0 && "We only support calling a function");
609     Asm->call(CR);
610   } else if (const auto Imm = llvm::dyn_cast<ConstantInteger32>(Target)) {
611     Asm->call(Immediate(Imm->getValue()));
612   } else {
613     llvm_unreachable("Unexpected operand type");
614   }
615   Func->getTarget()->resetStackAdjustment();
616 }
617
618 template <class Machine>
619 void InstX86Call<Machine>::dump(const Cfg *Func) const {
620   if (!BuildDefs::dump())
621     return;
622   Ostream &Str = Func->getContext()->getStrDump();
623   if (this->getDest()) {
624     this->dumpDest(Func);
625     Str << " = ";
626   }
627   Str << "call ";
628   getCallTarget()->dump(Func);
629 }
630
631 // The ShiftHack parameter is used to emit "cl" instead of "ecx" for shift
632 // instructions, in order to be syntactically valid. The this->Opcode parameter
633 // needs to be char* and not IceString because of template issues.
634 template <class Machine>
635 void InstX86Base<Machine>::emitTwoAddress(const char *Opcode, const Inst *Inst,
636                                           const Cfg *Func, bool ShiftHack) {
637   if (!BuildDefs::dump())
638     return;
639   Ostream &Str = Func->getContext()->getStrEmit();
640   assert(Inst->getSrcSize() == 2);
641   Operand *Dest = Inst->getDest();
642   if (Dest == nullptr)
643     Dest = Inst->getSrc(0);
644   assert(Dest == Inst->getSrc(0));
645   Operand *Src1 = Inst->getSrc(1);
646   Str << "\t" << Opcode << InstX86Base<Machine>::getWidthString(Dest->getType())
647       << "\t";
648   const auto ShiftReg = llvm::dyn_cast<Variable>(Src1);
649   if (ShiftHack && ShiftReg &&
650       ShiftReg->getRegNum() ==
651           InstX86Base<Machine>::Traits::RegisterSet::Reg_ecx)
652     Str << "%cl";
653   else
654     Src1->emit(Func);
655   Str << ", ";
656   Dest->emit(Func);
657 }
658
659 template <class Machine>
660 void emitIASOpTyGPR(const Cfg *Func, Type Ty, const Operand *Op,
661                     const typename InstX86Base<
662                         Machine>::Traits::Assembler::GPREmitterOneOp &Emitter) {
663   typename InstX86Base<Machine>::Traits::Assembler *Asm =
664       Func->getAssembler<typename InstX86Base<Machine>::Traits::Assembler>();
665   if (const auto Var = llvm::dyn_cast<Variable>(Op)) {
666     if (Var->hasReg()) {
667       // We cheat a little and use GPRRegister even for byte operations.
668       typename InstX86Base<Machine>::Traits::RegisterSet::GPRRegister VarReg =
669           InstX86Base<Machine>::Traits::RegisterSet::getEncodedByteRegOrGPR(
670               Ty, Var->getRegNum());
671       (Asm->*(Emitter.Reg))(Ty, VarReg);
672     } else {
673       typename InstX86Base<Machine>::Traits::Address StackAddr(
674           static_cast<typename InstX86Base<Machine>::Traits::TargetLowering *>(
675               Func->getTarget())
676               ->stackVarToAsmOperand(Var));
677       (Asm->*(Emitter.Addr))(Ty, StackAddr);
678     }
679   } else if (const auto Mem = llvm::dyn_cast<
680                  typename InstX86Base<Machine>::Traits::X86OperandMem>(Op)) {
681     Mem->emitSegmentOverride(Asm);
682     (Asm->*(Emitter.Addr))(Ty, Mem->toAsmAddress(Asm));
683   } else {
684     llvm_unreachable("Unexpected operand type");
685   }
686 }
687
688 template <class Machine, bool VarCanBeByte, bool SrcCanBeByte>
689 void emitIASRegOpTyGPR(
690     const Cfg *Func, Type Ty, const Variable *Var, const Operand *Src,
691     const typename InstX86Base<Machine>::Traits::Assembler::GPREmitterRegOp
692         &Emitter) {
693   typename InstX86Base<Machine>::Traits::Assembler *Asm =
694       Func->getAssembler<typename InstX86Base<Machine>::Traits::Assembler>();
695   assert(Var->hasReg());
696   // We cheat a little and use GPRRegister even for byte operations.
697   typename InstX86Base<Machine>::Traits::RegisterSet::GPRRegister VarReg =
698       VarCanBeByte
699           ? InstX86Base<Machine>::Traits::RegisterSet::getEncodedByteRegOrGPR(
700                 Ty, Var->getRegNum())
701           : InstX86Base<Machine>::Traits::RegisterSet::getEncodedGPR(
702                 Var->getRegNum());
703   if (const auto SrcVar = llvm::dyn_cast<Variable>(Src)) {
704     if (SrcVar->hasReg()) {
705       typename InstX86Base<Machine>::Traits::RegisterSet::GPRRegister SrcReg =
706           SrcCanBeByte
707               ? InstX86Base<Machine>::Traits::RegisterSet::
708                     getEncodedByteRegOrGPR(Ty, SrcVar->getRegNum())
709               : InstX86Base<Machine>::Traits::RegisterSet::getEncodedGPR(
710                     SrcVar->getRegNum());
711       (Asm->*(Emitter.GPRGPR))(Ty, VarReg, SrcReg);
712     } else {
713       typename InstX86Base<Machine>::Traits::Address SrcStackAddr =
714           static_cast<typename InstX86Base<Machine>::Traits::TargetLowering *>(
715               Func->getTarget())
716               ->stackVarToAsmOperand(SrcVar);
717       (Asm->*(Emitter.GPRAddr))(Ty, VarReg, SrcStackAddr);
718     }
719   } else if (const auto Mem = llvm::dyn_cast<
720                  typename InstX86Base<Machine>::Traits::X86OperandMem>(Src)) {
721     Mem->emitSegmentOverride(Asm);
722     (Asm->*(Emitter.GPRAddr))(Ty, VarReg, Mem->toAsmAddress(Asm));
723   } else if (const auto Imm = llvm::dyn_cast<ConstantInteger32>(Src)) {
724     (Asm->*(Emitter.GPRImm))(Ty, VarReg, Immediate(Imm->getValue()));
725   } else if (const auto Reloc = llvm::dyn_cast<ConstantRelocatable>(Src)) {
726     AssemblerFixup *Fixup =
727         Asm->createFixup(InstX86Base<Machine>::Traits::RelFixup, Reloc);
728     (Asm->*(Emitter.GPRImm))(Ty, VarReg, Immediate(Reloc->getOffset(), Fixup));
729   } else if (const auto Split = llvm::dyn_cast<
730                  typename InstX86Base<Machine>::Traits::VariableSplit>(Src)) {
731     (Asm->*(Emitter.GPRAddr))(Ty, VarReg, Split->toAsmAddress(Func));
732   } else {
733     llvm_unreachable("Unexpected operand type");
734   }
735 }
736
737 template <class Machine>
738 void emitIASAddrOpTyGPR(
739     const Cfg *Func, Type Ty,
740     const typename InstX86Base<Machine>::Traits::Address &Addr,
741     const Operand *Src,
742     const typename InstX86Base<Machine>::Traits::Assembler::GPREmitterAddrOp
743         &Emitter) {
744   typename InstX86Base<Machine>::Traits::Assembler *Asm =
745       Func->getAssembler<typename InstX86Base<Machine>::Traits::Assembler>();
746   // Src can only be Reg or Immediate.
747   if (const auto SrcVar = llvm::dyn_cast<Variable>(Src)) {
748     assert(SrcVar->hasReg());
749     typename InstX86Base<Machine>::Traits::RegisterSet::GPRRegister SrcReg =
750         InstX86Base<Machine>::Traits::RegisterSet::getEncodedByteRegOrGPR(
751             Ty, SrcVar->getRegNum());
752     (Asm->*(Emitter.AddrGPR))(Ty, Addr, SrcReg);
753   } else if (const auto Imm = llvm::dyn_cast<ConstantInteger32>(Src)) {
754     (Asm->*(Emitter.AddrImm))(Ty, Addr, Immediate(Imm->getValue()));
755   } else if (const auto Reloc = llvm::dyn_cast<ConstantRelocatable>(Src)) {
756     AssemblerFixup *Fixup =
757         Asm->createFixup(InstX86Base<Machine>::Traits::RelFixup, Reloc);
758     (Asm->*(Emitter.AddrImm))(Ty, Addr, Immediate(Reloc->getOffset(), Fixup));
759   } else {
760     llvm_unreachable("Unexpected operand type");
761   }
762 }
763
764 template <class Machine>
765 void emitIASAsAddrOpTyGPR(
766     const Cfg *Func, Type Ty, const Operand *Op0, const Operand *Op1,
767     const typename InstX86Base<Machine>::Traits::Assembler::GPREmitterAddrOp
768         &Emitter) {
769   if (const auto Op0Var = llvm::dyn_cast<Variable>(Op0)) {
770     assert(!Op0Var->hasReg());
771     typename InstX86Base<Machine>::Traits::Address StackAddr(
772         static_cast<typename InstX86Base<Machine>::Traits::TargetLowering *>(
773             Func->getTarget())
774             ->stackVarToAsmOperand(Op0Var));
775     emitIASAddrOpTyGPR<Machine>(Func, Ty, StackAddr, Op1, Emitter);
776   } else if (const auto Op0Mem = llvm::dyn_cast<
777                  typename InstX86Base<Machine>::Traits::X86OperandMem>(Op0)) {
778     typename InstX86Base<Machine>::Traits::Assembler *Asm =
779         Func->getAssembler<typename InstX86Base<Machine>::Traits::Assembler>();
780     Op0Mem->emitSegmentOverride(Asm);
781     emitIASAddrOpTyGPR<Machine>(Func, Ty, Op0Mem->toAsmAddress(Asm), Op1,
782                                 Emitter);
783   } else if (const auto Split = llvm::dyn_cast<
784                  typename InstX86Base<Machine>::Traits::VariableSplit>(Op0)) {
785     emitIASAddrOpTyGPR<Machine>(Func, Ty, Split->toAsmAddress(Func), Op1,
786                                 Emitter);
787   } else {
788     llvm_unreachable("Unexpected operand type");
789   }
790 }
791
792 template <class Machine>
793 void InstX86Base<Machine>::emitIASGPRShift(
794     const Cfg *Func, Type Ty, const Variable *Var, const Operand *Src,
795     const typename InstX86Base<Machine>::Traits::Assembler::GPREmitterShiftOp
796         &Emitter) {
797   typename InstX86Base<Machine>::Traits::Assembler *Asm =
798       Func->getAssembler<typename InstX86Base<Machine>::Traits::Assembler>();
799   // Technically, the Dest Var can be mem as well, but we only use Reg. We can
800   // extend this to check Dest if we decide to use that form.
801   assert(Var->hasReg());
802   // We cheat a little and use GPRRegister even for byte operations.
803   typename InstX86Base<Machine>::Traits::RegisterSet::GPRRegister VarReg =
804       InstX86Base<Machine>::Traits::RegisterSet::getEncodedByteRegOrGPR(
805           Ty, Var->getRegNum());
806   // Src must be reg == ECX or an Imm8. This is asserted by the assembler.
807   if (const auto SrcVar = llvm::dyn_cast<Variable>(Src)) {
808     assert(SrcVar->hasReg());
809     typename InstX86Base<Machine>::Traits::RegisterSet::GPRRegister SrcReg =
810         InstX86Base<Machine>::Traits::RegisterSet::getEncodedByteRegOrGPR(
811             Ty, SrcVar->getRegNum());
812     (Asm->*(Emitter.GPRGPR))(Ty, VarReg, SrcReg);
813   } else if (const auto Imm = llvm::dyn_cast<ConstantInteger32>(Src)) {
814     (Asm->*(Emitter.GPRImm))(Ty, VarReg, Immediate(Imm->getValue()));
815   } else {
816     llvm_unreachable("Unexpected operand type");
817   }
818 }
819
820 template <class Machine>
821 void emitIASGPRShiftDouble(
822     const Cfg *Func, const Variable *Dest, const Operand *Src1Op,
823     const Operand *Src2Op,
824     const typename InstX86Base<Machine>::Traits::Assembler::GPREmitterShiftD
825         &Emitter) {
826   typename InstX86Base<Machine>::Traits::Assembler *Asm =
827       Func->getAssembler<typename InstX86Base<Machine>::Traits::Assembler>();
828   // Dest can be reg or mem, but we only use the reg variant.
829   assert(Dest->hasReg());
830   typename InstX86Base<Machine>::Traits::RegisterSet::GPRRegister DestReg =
831       InstX86Base<Machine>::Traits::RegisterSet::getEncodedGPR(
832           Dest->getRegNum());
833   // SrcVar1 must be reg.
834   const auto SrcVar1 = llvm::cast<Variable>(Src1Op);
835   assert(SrcVar1->hasReg());
836   typename InstX86Base<Machine>::Traits::RegisterSet::GPRRegister SrcReg =
837       InstX86Base<Machine>::Traits::RegisterSet::getEncodedGPR(
838           SrcVar1->getRegNum());
839   Type Ty = SrcVar1->getType();
840   // Src2 can be the implicit CL register or an immediate.
841   if (const auto Imm = llvm::dyn_cast<ConstantInteger32>(Src2Op)) {
842     (Asm->*(Emitter.GPRGPRImm))(Ty, DestReg, SrcReg,
843                                 Immediate(Imm->getValue()));
844   } else {
845     assert(llvm::cast<Variable>(Src2Op)->getRegNum() ==
846            InstX86Base<Machine>::Traits::RegisterSet::Reg_ecx);
847     (Asm->*(Emitter.GPRGPR))(Ty, DestReg, SrcReg);
848   }
849 }
850
851 template <class Machine>
852 void emitIASXmmShift(
853     const Cfg *Func, Type Ty, const Variable *Var, const Operand *Src,
854     const typename InstX86Base<Machine>::Traits::Assembler::XmmEmitterShiftOp
855         &Emitter) {
856   typename InstX86Base<Machine>::Traits::Assembler *Asm =
857       Func->getAssembler<typename InstX86Base<Machine>::Traits::Assembler>();
858   assert(Var->hasReg());
859   typename InstX86Base<Machine>::Traits::RegisterSet::XmmRegister VarReg =
860       InstX86Base<Machine>::Traits::RegisterSet::getEncodedXmm(
861           Var->getRegNum());
862   if (const auto SrcVar = llvm::dyn_cast<Variable>(Src)) {
863     if (SrcVar->hasReg()) {
864       typename InstX86Base<Machine>::Traits::RegisterSet::XmmRegister SrcReg =
865           InstX86Base<Machine>::Traits::RegisterSet::getEncodedXmm(
866               SrcVar->getRegNum());
867       (Asm->*(Emitter.XmmXmm))(Ty, VarReg, SrcReg);
868     } else {
869       typename InstX86Base<Machine>::Traits::Address SrcStackAddr =
870           static_cast<typename InstX86Base<Machine>::Traits::TargetLowering *>(
871               Func->getTarget())
872               ->stackVarToAsmOperand(SrcVar);
873       (Asm->*(Emitter.XmmAddr))(Ty, VarReg, SrcStackAddr);
874     }
875   } else if (const auto Mem = llvm::dyn_cast<
876                  typename InstX86Base<Machine>::Traits::X86OperandMem>(Src)) {
877     assert(Mem->getSegmentRegister() ==
878            InstX86Base<Machine>::Traits::X86OperandMem::DefaultSegment);
879     (Asm->*(Emitter.XmmAddr))(Ty, VarReg, Mem->toAsmAddress(Asm));
880   } else if (const auto Imm = llvm::dyn_cast<ConstantInteger32>(Src)) {
881     (Asm->*(Emitter.XmmImm))(Ty, VarReg, Immediate(Imm->getValue()));
882   } else {
883     llvm_unreachable("Unexpected operand type");
884   }
885 }
886
887 template <class Machine>
888 void emitIASRegOpTyXMM(
889     const Cfg *Func, Type Ty, const Variable *Var, const Operand *Src,
890     const typename InstX86Base<Machine>::Traits::Assembler::XmmEmitterRegOp
891         &Emitter) {
892   typename InstX86Base<Machine>::Traits::Assembler *Asm =
893       Func->getAssembler<typename InstX86Base<Machine>::Traits::Assembler>();
894   assert(Var->hasReg());
895   typename InstX86Base<Machine>::Traits::RegisterSet::XmmRegister VarReg =
896       InstX86Base<Machine>::Traits::RegisterSet::getEncodedXmm(
897           Var->getRegNum());
898   if (const auto SrcVar = llvm::dyn_cast<Variable>(Src)) {
899     if (SrcVar->hasReg()) {
900       typename InstX86Base<Machine>::Traits::RegisterSet::XmmRegister SrcReg =
901           InstX86Base<Machine>::Traits::RegisterSet::getEncodedXmm(
902               SrcVar->getRegNum());
903       (Asm->*(Emitter.XmmXmm))(Ty, VarReg, SrcReg);
904     } else {
905       typename InstX86Base<Machine>::Traits::Address SrcStackAddr =
906           static_cast<typename InstX86Base<Machine>::Traits::TargetLowering *>(
907               Func->getTarget())
908               ->stackVarToAsmOperand(SrcVar);
909       (Asm->*(Emitter.XmmAddr))(Ty, VarReg, SrcStackAddr);
910     }
911   } else if (const auto Mem = llvm::dyn_cast<
912                  typename InstX86Base<Machine>::Traits::X86OperandMem>(Src)) {
913     assert(Mem->getSegmentRegister() ==
914            InstX86Base<Machine>::Traits::X86OperandMem::DefaultSegment);
915     (Asm->*(Emitter.XmmAddr))(Ty, VarReg, Mem->toAsmAddress(Asm));
916   } else if (const auto Imm = llvm::dyn_cast<Constant>(Src)) {
917     (Asm->*(Emitter.XmmAddr))(
918         Ty, VarReg,
919         InstX86Base<Machine>::Traits::Address::ofConstPool(Asm, Imm));
920   } else {
921     llvm_unreachable("Unexpected operand type");
922   }
923 }
924
925 template <class Machine, typename DReg_t, typename SReg_t,
926           DReg_t (*destEnc)(int32_t), SReg_t (*srcEnc)(int32_t)>
927 void emitIASCastRegOp(const Cfg *Func, Type DestTy, const Variable *Dest,
928                       Type SrcTy, const Operand *Src,
929                       const typename InstX86Base<Machine>::Traits::Assembler::
930                           template CastEmitterRegOp<DReg_t, SReg_t> &Emitter) {
931   typename InstX86Base<Machine>::Traits::Assembler *Asm =
932       Func->getAssembler<typename InstX86Base<Machine>::Traits::Assembler>();
933   assert(Dest->hasReg());
934   DReg_t DestReg = destEnc(Dest->getRegNum());
935   if (const auto SrcVar = llvm::dyn_cast<Variable>(Src)) {
936     if (SrcVar->hasReg()) {
937       SReg_t SrcReg = srcEnc(SrcVar->getRegNum());
938       (Asm->*(Emitter.RegReg))(DestTy, DestReg, SrcTy, SrcReg);
939     } else {
940       typename InstX86Base<Machine>::Traits::Address SrcStackAddr =
941           static_cast<typename InstX86Base<Machine>::Traits::TargetLowering *>(
942               Func->getTarget())
943               ->stackVarToAsmOperand(SrcVar);
944       (Asm->*(Emitter.RegAddr))(DestTy, DestReg, SrcTy, SrcStackAddr);
945     }
946   } else if (const auto Mem = llvm::dyn_cast<
947                  typename InstX86Base<Machine>::Traits::X86OperandMem>(Src)) {
948     Mem->emitSegmentOverride(Asm);
949     (Asm->*(Emitter.RegAddr))(DestTy, DestReg, SrcTy, Mem->toAsmAddress(Asm));
950   } else {
951     llvm_unreachable("Unexpected operand type");
952   }
953 }
954
955 template <class Machine, typename DReg_t, typename SReg_t,
956           DReg_t (*destEnc)(int32_t), SReg_t (*srcEnc)(int32_t)>
957 void emitIASThreeOpImmOps(
958     const Cfg *Func, Type DispatchTy, const Variable *Dest, const Operand *Src0,
959     const Operand *Src1,
960     const typename InstX86Base<Machine>::Traits::Assembler::
961         template ThreeOpImmEmitter<DReg_t, SReg_t> Emitter) {
962   typename InstX86Base<Machine>::Traits::Assembler *Asm =
963       Func->getAssembler<typename InstX86Base<Machine>::Traits::Assembler>();
964   // This only handles Dest being a register, and Src1 being an immediate.
965   assert(Dest->hasReg());
966   DReg_t DestReg = destEnc(Dest->getRegNum());
967   Immediate Imm(llvm::cast<ConstantInteger32>(Src1)->getValue());
968   if (const auto SrcVar = llvm::dyn_cast<Variable>(Src0)) {
969     if (SrcVar->hasReg()) {
970       SReg_t SrcReg = srcEnc(SrcVar->getRegNum());
971       (Asm->*(Emitter.RegRegImm))(DispatchTy, DestReg, SrcReg, Imm);
972     } else {
973       typename InstX86Base<Machine>::Traits::Address SrcStackAddr =
974           static_cast<typename InstX86Base<Machine>::Traits::TargetLowering *>(
975               Func->getTarget())
976               ->stackVarToAsmOperand(SrcVar);
977       (Asm->*(Emitter.RegAddrImm))(DispatchTy, DestReg, SrcStackAddr, Imm);
978     }
979   } else if (const auto Mem = llvm::dyn_cast<
980                  typename InstX86Base<Machine>::Traits::X86OperandMem>(Src0)) {
981     Mem->emitSegmentOverride(Asm);
982     (Asm->*(Emitter.RegAddrImm))(DispatchTy, DestReg, Mem->toAsmAddress(Asm),
983                                  Imm);
984   } else {
985     llvm_unreachable("Unexpected operand type");
986   }
987 }
988
989 template <class Machine>
990 void emitIASMovlikeXMM(
991     const Cfg *Func, const Variable *Dest, const Operand *Src,
992     const typename InstX86Base<Machine>::Traits::Assembler::XmmEmitterMovOps
993         Emitter) {
994   typename InstX86Base<Machine>::Traits::Assembler *Asm =
995       Func->getAssembler<typename InstX86Base<Machine>::Traits::Assembler>();
996   if (Dest->hasReg()) {
997     typename InstX86Base<Machine>::Traits::RegisterSet::XmmRegister DestReg =
998         InstX86Base<Machine>::Traits::RegisterSet::getEncodedXmm(
999             Dest->getRegNum());
1000     if (const auto SrcVar = llvm::dyn_cast<Variable>(Src)) {
1001       if (SrcVar->hasReg()) {
1002         (Asm->*(Emitter.XmmXmm))(
1003             DestReg, InstX86Base<Machine>::Traits::RegisterSet::getEncodedXmm(
1004                          SrcVar->getRegNum()));
1005       } else {
1006         typename InstX86Base<Machine>::Traits::Address StackAddr(
1007             static_cast<typename InstX86Base<Machine>::Traits::TargetLowering
1008                             *>(Func->getTarget())
1009                 ->stackVarToAsmOperand(SrcVar));
1010         (Asm->*(Emitter.XmmAddr))(DestReg, StackAddr);
1011       }
1012     } else if (const auto SrcMem = llvm::dyn_cast<
1013                    typename InstX86Base<Machine>::Traits::X86OperandMem>(Src)) {
1014       assert(SrcMem->getSegmentRegister() ==
1015              InstX86Base<Machine>::Traits::X86OperandMem::DefaultSegment);
1016       (Asm->*(Emitter.XmmAddr))(DestReg, SrcMem->toAsmAddress(Asm));
1017     } else {
1018       llvm_unreachable("Unexpected operand type");
1019     }
1020   } else {
1021     typename InstX86Base<Machine>::Traits::Address StackAddr(
1022         static_cast<typename InstX86Base<Machine>::Traits::TargetLowering *>(
1023             Func->getTarget())
1024             ->stackVarToAsmOperand(Dest));
1025     // Src must be a register in this case.
1026     const auto SrcVar = llvm::cast<Variable>(Src);
1027     assert(SrcVar->hasReg());
1028     (Asm->*(Emitter.AddrXmm))(
1029         StackAddr, InstX86Base<Machine>::Traits::RegisterSet::getEncodedXmm(
1030                        SrcVar->getRegNum()));
1031   }
1032 }
1033
1034 template <class Machine>
1035 void InstX86Sqrtss<Machine>::emit(const Cfg *Func) const {
1036   if (!BuildDefs::dump())
1037     return;
1038   Ostream &Str = Func->getContext()->getStrEmit();
1039   assert(this->getSrcSize() == 1);
1040   Type Ty = this->getSrc(0)->getType();
1041   assert(isScalarFloatingType(Ty));
1042   Str << "\tsqrt" << InstX86Base<Machine>::Traits::TypeAttributes[Ty].SdSsString
1043       << "\t";
1044   this->getSrc(0)->emit(Func);
1045   Str << ", ";
1046   this->getDest()->emit(Func);
1047 }
1048
1049 template <class Machine>
1050 void InstX86Addss<Machine>::emit(const Cfg *Func) const {
1051   if (!BuildDefs::dump())
1052     return;
1053   char buf[30];
1054   snprintf(
1055       buf, llvm::array_lengthof(buf), "add%s",
1056       InstX86Base<Machine>::Traits::TypeAttributes[this->getDest()->getType()]
1057           .SdSsString);
1058   this->emitTwoAddress(buf, this, Func);
1059 }
1060
1061 template <class Machine>
1062 void InstX86Padd<Machine>::emit(const Cfg *Func) const {
1063   if (!BuildDefs::dump())
1064     return;
1065   char buf[30];
1066   snprintf(
1067       buf, llvm::array_lengthof(buf), "padd%s",
1068       InstX86Base<Machine>::Traits::TypeAttributes[this->getDest()->getType()]
1069           .PackString);
1070   this->emitTwoAddress(buf, this, Func);
1071 }
1072
1073 template <class Machine>
1074 void InstX86Pmull<Machine>::emit(const Cfg *Func) const {
1075   if (!BuildDefs::dump())
1076     return;
1077   char buf[30];
1078   bool TypesAreValid = this->getDest()->getType() == IceType_v4i32 ||
1079                        this->getDest()->getType() == IceType_v8i16;
1080   bool InstructionSetIsValid =
1081       this->getDest()->getType() == IceType_v8i16 ||
1082       static_cast<typename InstX86Base<Machine>::Traits::TargetLowering *>(
1083           Func->getTarget())
1084               ->getInstructionSet() >= InstX86Base<Machine>::Traits::SSE4_1;
1085   (void)TypesAreValid;
1086   (void)InstructionSetIsValid;
1087   assert(TypesAreValid);
1088   assert(InstructionSetIsValid);
1089   snprintf(
1090       buf, llvm::array_lengthof(buf), "pmull%s",
1091       InstX86Base<Machine>::Traits::TypeAttributes[this->getDest()->getType()]
1092           .PackString);
1093   this->emitTwoAddress(buf, this, Func);
1094 }
1095
1096 template <class Machine>
1097 void InstX86Pmull<Machine>::emitIAS(const Cfg *Func) const {
1098   Type Ty = this->getDest()->getType();
1099   bool TypesAreValid = Ty == IceType_v4i32 || Ty == IceType_v8i16;
1100   bool InstructionSetIsValid =
1101       Ty == IceType_v8i16 ||
1102       static_cast<typename InstX86Base<Machine>::Traits::TargetLowering *>(
1103           Func->getTarget())
1104               ->getInstructionSet() >= InstX86Base<Machine>::Traits::SSE4_1;
1105   (void)TypesAreValid;
1106   (void)InstructionSetIsValid;
1107   assert(TypesAreValid);
1108   assert(InstructionSetIsValid);
1109   assert(this->getSrcSize() == 2);
1110   Type ElementTy = typeElementType(Ty);
1111   emitIASRegOpTyXMM<Machine>(Func, ElementTy, this->getDest(), this->getSrc(1),
1112                              this->Emitter);
1113 }
1114
1115 template <class Machine>
1116 void InstX86Subss<Machine>::emit(const Cfg *Func) const {
1117   if (!BuildDefs::dump())
1118     return;
1119   char buf[30];
1120   snprintf(
1121       buf, llvm::array_lengthof(buf), "sub%s",
1122       InstX86Base<Machine>::Traits::TypeAttributes[this->getDest()->getType()]
1123           .SdSsString);
1124   this->emitTwoAddress(buf, this, Func);
1125 }
1126
1127 template <class Machine>
1128 void InstX86Psub<Machine>::emit(const Cfg *Func) const {
1129   if (!BuildDefs::dump())
1130     return;
1131   char buf[30];
1132   snprintf(
1133       buf, llvm::array_lengthof(buf), "psub%s",
1134       InstX86Base<Machine>::Traits::TypeAttributes[this->getDest()->getType()]
1135           .PackString);
1136   this->emitTwoAddress(buf, this, Func);
1137 }
1138
1139 template <class Machine>
1140 void InstX86Mulss<Machine>::emit(const Cfg *Func) const {
1141   if (!BuildDefs::dump())
1142     return;
1143   char buf[30];
1144   snprintf(
1145       buf, llvm::array_lengthof(buf), "mul%s",
1146       InstX86Base<Machine>::Traits::TypeAttributes[this->getDest()->getType()]
1147           .SdSsString);
1148   this->emitTwoAddress(buf, this, Func);
1149 }
1150
1151 template <class Machine>
1152 void InstX86Pmuludq<Machine>::emit(const Cfg *Func) const {
1153   if (!BuildDefs::dump())
1154     return;
1155   assert(this->getSrc(0)->getType() == IceType_v4i32 &&
1156          this->getSrc(1)->getType() == IceType_v4i32);
1157   this->emitTwoAddress(this->Opcode, this, Func);
1158 }
1159
1160 template <class Machine>
1161 void InstX86Divss<Machine>::emit(const Cfg *Func) const {
1162   if (!BuildDefs::dump())
1163     return;
1164   char buf[30];
1165   snprintf(
1166       buf, llvm::array_lengthof(buf), "div%s",
1167       InstX86Base<Machine>::Traits::TypeAttributes[this->getDest()->getType()]
1168           .SdSsString);
1169   this->emitTwoAddress(buf, this, Func);
1170 }
1171
1172 template <class Machine> void InstX86Div<Machine>::emit(const Cfg *Func) const {
1173   if (!BuildDefs::dump())
1174     return;
1175   Ostream &Str = Func->getContext()->getStrEmit();
1176   assert(this->getSrcSize() == 3);
1177   Operand *Src1 = this->getSrc(1);
1178   Str << "\t" << this->Opcode << this->getWidthString(Src1->getType()) << "\t";
1179   Src1->emit(Func);
1180 }
1181
1182 template <class Machine>
1183 void InstX86Div<Machine>::emitIAS(const Cfg *Func) const {
1184   assert(this->getSrcSize() == 3);
1185   const Operand *Src = this->getSrc(1);
1186   Type Ty = Src->getType();
1187   static const typename InstX86Base<Machine>::Traits::Assembler::GPREmitterOneOp
1188       Emitter = {&InstX86Base<Machine>::Traits::Assembler::div,
1189                  &InstX86Base<Machine>::Traits::Assembler::div};
1190   emitIASOpTyGPR<Machine>(Func, Ty, Src, Emitter);
1191 }
1192
1193 template <class Machine>
1194 void InstX86Idiv<Machine>::emit(const Cfg *Func) const {
1195   if (!BuildDefs::dump())
1196     return;
1197   Ostream &Str = Func->getContext()->getStrEmit();
1198   assert(this->getSrcSize() == 3);
1199   Operand *Src1 = this->getSrc(1);
1200   Str << "\t" << this->Opcode << this->getWidthString(Src1->getType()) << "\t";
1201   Src1->emit(Func);
1202 }
1203
1204 template <class Machine>
1205 void InstX86Idiv<Machine>::emitIAS(const Cfg *Func) const {
1206   assert(this->getSrcSize() == 3);
1207   const Operand *Src = this->getSrc(1);
1208   Type Ty = Src->getType();
1209   static const typename InstX86Base<Machine>::Traits::Assembler::GPREmitterOneOp
1210       Emitter = {&InstX86Base<Machine>::Traits::Assembler::idiv,
1211                  &InstX86Base<Machine>::Traits::Assembler::idiv};
1212   emitIASOpTyGPR<Machine>(Func, Ty, Src, Emitter);
1213 }
1214
1215 // pblendvb and blendvps take xmm0 as a final implicit argument.
1216 template <class Machine>
1217 void emitVariableBlendInst(const char *Opcode, const Inst *Inst,
1218                            const Cfg *Func) {
1219   if (!BuildDefs::dump())
1220     return;
1221   Ostream &Str = Func->getContext()->getStrEmit();
1222   assert(Inst->getSrcSize() == 3);
1223   assert(llvm::cast<Variable>(Inst->getSrc(2))->getRegNum() ==
1224          InstX86Base<Machine>::Traits::RegisterSet::Reg_xmm0);
1225   Str << "\t" << Opcode << "\t";
1226   Inst->getSrc(1)->emit(Func);
1227   Str << ", ";
1228   Inst->getDest()->emit(Func);
1229 }
1230
1231 template <class Machine>
1232 void emitIASVariableBlendInst(
1233     const Inst *Inst, const Cfg *Func,
1234     const typename InstX86Base<Machine>::Traits::Assembler::XmmEmitterRegOp
1235         &Emitter) {
1236   assert(Inst->getSrcSize() == 3);
1237   assert(llvm::cast<Variable>(Inst->getSrc(2))->getRegNum() ==
1238          InstX86Base<Machine>::Traits::RegisterSet::Reg_xmm0);
1239   const Variable *Dest = Inst->getDest();
1240   const Operand *Src = Inst->getSrc(1);
1241   emitIASRegOpTyXMM<Machine>(Func, Dest->getType(), Dest, Src, Emitter);
1242 }
1243
1244 template <class Machine>
1245 void InstX86Blendvps<Machine>::emit(const Cfg *Func) const {
1246   if (!BuildDefs::dump())
1247     return;
1248   assert(static_cast<typename InstX86Base<Machine>::Traits::TargetLowering *>(
1249              Func->getTarget())
1250              ->getInstructionSet() >= InstX86Base<Machine>::Traits::SSE4_1);
1251   emitVariableBlendInst<Machine>(this->Opcode, this, Func);
1252 }
1253
1254 template <class Machine>
1255 void InstX86Blendvps<Machine>::emitIAS(const Cfg *Func) const {
1256   assert(static_cast<typename InstX86Base<Machine>::Traits::TargetLowering *>(
1257              Func->getTarget())
1258              ->getInstructionSet() >= InstX86Base<Machine>::Traits::SSE4_1);
1259   static const typename InstX86Base<Machine>::Traits::Assembler::XmmEmitterRegOp
1260       Emitter = {&InstX86Base<Machine>::Traits::Assembler::blendvps,
1261                  &InstX86Base<Machine>::Traits::Assembler::blendvps};
1262   emitIASVariableBlendInst<Machine>(this, Func, Emitter);
1263 }
1264
1265 template <class Machine>
1266 void InstX86Pblendvb<Machine>::emit(const Cfg *Func) const {
1267   if (!BuildDefs::dump())
1268     return;
1269   assert(static_cast<typename InstX86Base<Machine>::Traits::TargetLowering *>(
1270              Func->getTarget())
1271              ->getInstructionSet() >= InstX86Base<Machine>::Traits::SSE4_1);
1272   emitVariableBlendInst<Machine>(this->Opcode, this, Func);
1273 }
1274
1275 template <class Machine>
1276 void InstX86Pblendvb<Machine>::emitIAS(const Cfg *Func) const {
1277   assert(static_cast<typename InstX86Base<Machine>::Traits::TargetLowering *>(
1278              Func->getTarget())
1279              ->getInstructionSet() >= InstX86Base<Machine>::Traits::SSE4_1);
1280   static const typename InstX86Base<Machine>::Traits::Assembler::XmmEmitterRegOp
1281       Emitter = {&InstX86Base<Machine>::Traits::Assembler::pblendvb,
1282                  &InstX86Base<Machine>::Traits::Assembler::pblendvb};
1283   emitIASVariableBlendInst<Machine>(this, Func, Emitter);
1284 }
1285
1286 template <class Machine>
1287 void InstX86Imul<Machine>::emit(const Cfg *Func) const {
1288   if (!BuildDefs::dump())
1289     return;
1290   Ostream &Str = Func->getContext()->getStrEmit();
1291   assert(this->getSrcSize() == 2);
1292   Variable *Dest = this->getDest();
1293   if (isByteSizedArithType(Dest->getType())) {
1294     // The 8-bit version of imul only allows the form "imul r/m8".
1295     const auto Src0Var = llvm::dyn_cast<Variable>(this->getSrc(0));
1296     (void)Src0Var;
1297     assert(Src0Var &&
1298            Src0Var->getRegNum() ==
1299                InstX86Base<Machine>::Traits::RegisterSet::Reg_eax);
1300     Str << "\timulb\t";
1301     this->getSrc(1)->emit(Func);
1302   } else if (llvm::isa<Constant>(this->getSrc(1))) {
1303     Str << "\timul" << this->getWidthString(Dest->getType()) << "\t";
1304     this->getSrc(1)->emit(Func);
1305     Str << ", ";
1306     this->getSrc(0)->emit(Func);
1307     Str << ", ";
1308     Dest->emit(Func);
1309   } else {
1310     this->emitTwoAddress("imul", this, Func);
1311   }
1312 }
1313
1314 template <class Machine>
1315 void InstX86Imul<Machine>::emitIAS(const Cfg *Func) const {
1316   assert(this->getSrcSize() == 2);
1317   const Variable *Var = this->getDest();
1318   Type Ty = Var->getType();
1319   const Operand *Src = this->getSrc(1);
1320   if (isByteSizedArithType(Ty)) {
1321     // The 8-bit version of imul only allows the form "imul r/m8".
1322     const auto Src0Var = llvm::dyn_cast<Variable>(this->getSrc(0));
1323     (void)Src0Var;
1324     assert(Src0Var &&
1325            Src0Var->getRegNum() ==
1326                InstX86Base<Machine>::Traits::RegisterSet::Reg_eax);
1327     static const typename InstX86Base<
1328         Machine>::Traits::Assembler::GPREmitterOneOp Emitter = {
1329         &InstX86Base<Machine>::Traits::Assembler::imul,
1330         &InstX86Base<Machine>::Traits::Assembler::imul};
1331     emitIASOpTyGPR<Machine>(Func, Ty, this->getSrc(1), Emitter);
1332   } else {
1333     // We only use imul as a two-address instruction even though there is a 3
1334     // operand version when one of the operands is a constant.
1335     assert(Var == this->getSrc(0));
1336     static const typename InstX86Base<
1337         Machine>::Traits::Assembler::GPREmitterRegOp Emitter = {
1338         &InstX86Base<Machine>::Traits::Assembler::imul,
1339         &InstX86Base<Machine>::Traits::Assembler::imul,
1340         &InstX86Base<Machine>::Traits::Assembler::imul};
1341     emitIASRegOpTyGPR<Machine>(Func, Ty, Var, Src, Emitter);
1342   }
1343 }
1344
1345 template <class Machine>
1346 void InstX86Insertps<Machine>::emitIAS(const Cfg *Func) const {
1347   assert(this->getSrcSize() == 3);
1348   assert(static_cast<typename InstX86Base<Machine>::Traits::TargetLowering *>(
1349              Func->getTarget())
1350              ->getInstructionSet() >= InstX86Base<Machine>::Traits::SSE4_1);
1351   const Variable *Dest = this->getDest();
1352   assert(Dest == this->getSrc(0));
1353   Type Ty = Dest->getType();
1354   static const typename InstX86Base<Machine>::Traits::Assembler::
1355       template ThreeOpImmEmitter<
1356           typename InstX86Base<Machine>::Traits::RegisterSet::XmmRegister,
1357           typename InstX86Base<Machine>::Traits::RegisterSet::XmmRegister>
1358           Emitter = {&InstX86Base<Machine>::Traits::Assembler::insertps,
1359                      &InstX86Base<Machine>::Traits::Assembler::insertps};
1360   emitIASThreeOpImmOps<
1361       Machine, typename InstX86Base<Machine>::Traits::RegisterSet::XmmRegister,
1362       typename InstX86Base<Machine>::Traits::RegisterSet::XmmRegister,
1363       InstX86Base<Machine>::Traits::RegisterSet::getEncodedXmm,
1364       InstX86Base<Machine>::Traits::RegisterSet::getEncodedXmm>(
1365       Func, Ty, Dest, this->getSrc(1), this->getSrc(2), Emitter);
1366 }
1367
1368 template <class Machine>
1369 void InstX86Cbwdq<Machine>::emit(const Cfg *Func) const {
1370   if (!BuildDefs::dump())
1371     return;
1372   Ostream &Str = Func->getContext()->getStrEmit();
1373   assert(this->getSrcSize() == 1);
1374   Operand *Src0 = this->getSrc(0);
1375   assert(llvm::isa<Variable>(Src0));
1376   assert(llvm::cast<Variable>(Src0)->getRegNum() ==
1377          InstX86Base<Machine>::Traits::RegisterSet::Reg_eax);
1378   switch (Src0->getType()) {
1379   default:
1380     llvm_unreachable("unexpected source type!");
1381     break;
1382   case IceType_i8:
1383     assert(this->getDest()->getRegNum() ==
1384            InstX86Base<Machine>::Traits::RegisterSet::Reg_eax);
1385     Str << "\t"
1386         << "cbtw";
1387     break;
1388   case IceType_i16:
1389     assert(this->getDest()->getRegNum() ==
1390            InstX86Base<Machine>::Traits::RegisterSet::Reg_edx);
1391     Str << "\t"
1392         << "cwtd";
1393     break;
1394   case IceType_i32:
1395     assert(this->getDest()->getRegNum() ==
1396            InstX86Base<Machine>::Traits::RegisterSet::Reg_edx);
1397     Str << "\t"
1398         << "cltd";
1399     break;
1400   case IceType_i64:
1401     assert(this->getDest()->getRegNum() ==
1402            InstX86Base<Machine>::Traits::RegisterSet::Reg_edx);
1403     Str << "\t"
1404         << "cdto";
1405     break;
1406   }
1407 }
1408
1409 template <class Machine>
1410 void InstX86Cbwdq<Machine>::emitIAS(const Cfg *Func) const {
1411   typename InstX86Base<Machine>::Traits::Assembler *Asm =
1412       Func->getAssembler<typename InstX86Base<Machine>::Traits::Assembler>();
1413   assert(this->getSrcSize() == 1);
1414   Operand *Src0 = this->getSrc(0);
1415   assert(llvm::isa<Variable>(Src0));
1416   assert(llvm::cast<Variable>(Src0)->getRegNum() ==
1417          InstX86Base<Machine>::Traits::RegisterSet::Reg_eax);
1418   switch (Src0->getType()) {
1419   default:
1420     llvm_unreachable("unexpected source type!");
1421     break;
1422   case IceType_i8:
1423     assert(this->getDest()->getRegNum() ==
1424            InstX86Base<Machine>::Traits::RegisterSet::Reg_eax);
1425     Asm->cbw();
1426     break;
1427   case IceType_i16:
1428     assert(this->getDest()->getRegNum() ==
1429            InstX86Base<Machine>::Traits::RegisterSet::Reg_edx);
1430     Asm->cwd();
1431     break;
1432   case IceType_i32:
1433     assert(this->getDest()->getRegNum() ==
1434            InstX86Base<Machine>::Traits::RegisterSet::Reg_edx);
1435     Asm->cdq();
1436     break;
1437   case IceType_i64:
1438     assert(this->getDest()->getRegNum() ==
1439            InstX86Base<Machine>::Traits::RegisterSet::Reg_edx);
1440     Asm->cqo();
1441     break;
1442   }
1443 }
1444
1445 template <class Machine> void InstX86Mul<Machine>::emit(const Cfg *Func) const {
1446   if (!BuildDefs::dump())
1447     return;
1448   Ostream &Str = Func->getContext()->getStrEmit();
1449   assert(this->getSrcSize() == 2);
1450   assert(llvm::isa<Variable>(this->getSrc(0)));
1451   assert(llvm::cast<Variable>(this->getSrc(0))->getRegNum() ==
1452          InstX86Base<Machine>::Traits::RegisterSet::Reg_eax);
1453   assert(
1454       this->getDest()->getRegNum() ==
1455       InstX86Base<Machine>::Traits::RegisterSet::Reg_eax); // TODO: allow edx?
1456   Str << "\tmul" << this->getWidthString(this->getDest()->getType()) << "\t";
1457   this->getSrc(1)->emit(Func);
1458 }
1459
1460 template <class Machine>
1461 void InstX86Mul<Machine>::emitIAS(const Cfg *Func) const {
1462   assert(this->getSrcSize() == 2);
1463   assert(llvm::isa<Variable>(this->getSrc(0)));
1464   assert(llvm::cast<Variable>(this->getSrc(0))->getRegNum() ==
1465          InstX86Base<Machine>::Traits::RegisterSet::Reg_eax);
1466   assert(
1467       this->getDest()->getRegNum() ==
1468       InstX86Base<Machine>::Traits::RegisterSet::Reg_eax); // TODO: allow edx?
1469   const Operand *Src = this->getSrc(1);
1470   Type Ty = Src->getType();
1471   static const typename InstX86Base<Machine>::Traits::Assembler::GPREmitterOneOp
1472       Emitter = {&InstX86Base<Machine>::Traits::Assembler::mul,
1473                  &InstX86Base<Machine>::Traits::Assembler::mul};
1474   emitIASOpTyGPR<Machine>(Func, Ty, Src, Emitter);
1475 }
1476
1477 template <class Machine> void InstX86Mul<Machine>::dump(const Cfg *Func) const {
1478   if (!BuildDefs::dump())
1479     return;
1480   Ostream &Str = Func->getContext()->getStrDump();
1481   this->dumpDest(Func);
1482   Str << " = mul." << this->getDest()->getType() << " ";
1483   this->dumpSources(Func);
1484 }
1485
1486 template <class Machine>
1487 void InstX86Shld<Machine>::emit(const Cfg *Func) const {
1488   if (!BuildDefs::dump())
1489     return;
1490   Ostream &Str = Func->getContext()->getStrEmit();
1491   Variable *Dest = this->getDest();
1492   assert(this->getSrcSize() == 3);
1493   assert(Dest == this->getSrc(0));
1494   Str << "\tshld" << this->getWidthString(Dest->getType()) << "\t";
1495   if (const auto ShiftReg = llvm::dyn_cast<Variable>(this->getSrc(2))) {
1496     (void)ShiftReg;
1497     assert(ShiftReg->getRegNum() ==
1498            InstX86Base<Machine>::Traits::RegisterSet::Reg_ecx);
1499     Str << "%cl";
1500   } else {
1501     this->getSrc(2)->emit(Func);
1502   }
1503   Str << ", ";
1504   this->getSrc(1)->emit(Func);
1505   Str << ", ";
1506   Dest->emit(Func);
1507 }
1508
1509 template <class Machine>
1510 void InstX86Shld<Machine>::emitIAS(const Cfg *Func) const {
1511   assert(this->getSrcSize() == 3);
1512   assert(this->getDest() == this->getSrc(0));
1513   const Variable *Dest = this->getDest();
1514   const Operand *Src1 = this->getSrc(1);
1515   const Operand *Src2 = this->getSrc(2);
1516   static const typename InstX86Base<
1517       Machine>::Traits::Assembler::GPREmitterShiftD Emitter = {
1518       &InstX86Base<Machine>::Traits::Assembler::shld,
1519       &InstX86Base<Machine>::Traits::Assembler::shld};
1520   emitIASGPRShiftDouble<Machine>(Func, Dest, Src1, Src2, Emitter);
1521 }
1522
1523 template <class Machine>
1524 void InstX86Shld<Machine>::dump(const Cfg *Func) const {
1525   if (!BuildDefs::dump())
1526     return;
1527   Ostream &Str = Func->getContext()->getStrDump();
1528   this->dumpDest(Func);
1529   Str << " = shld." << this->getDest()->getType() << " ";
1530   this->dumpSources(Func);
1531 }
1532
1533 template <class Machine>
1534 void InstX86Shrd<Machine>::emit(const Cfg *Func) const {
1535   if (!BuildDefs::dump())
1536     return;
1537   Ostream &Str = Func->getContext()->getStrEmit();
1538   Variable *Dest = this->getDest();
1539   assert(this->getSrcSize() == 3);
1540   assert(Dest == this->getSrc(0));
1541   Str << "\tshrd" << this->getWidthString(Dest->getType()) << "\t";
1542   if (const auto ShiftReg = llvm::dyn_cast<Variable>(this->getSrc(2))) {
1543     (void)ShiftReg;
1544     assert(ShiftReg->getRegNum() ==
1545            InstX86Base<Machine>::Traits::RegisterSet::Reg_ecx);
1546     Str << "%cl";
1547   } else {
1548     this->getSrc(2)->emit(Func);
1549   }
1550   Str << ", ";
1551   this->getSrc(1)->emit(Func);
1552   Str << ", ";
1553   Dest->emit(Func);
1554 }
1555
1556 template <class Machine>
1557 void InstX86Shrd<Machine>::emitIAS(const Cfg *Func) const {
1558   assert(this->getSrcSize() == 3);
1559   assert(this->getDest() == this->getSrc(0));
1560   const Variable *Dest = this->getDest();
1561   const Operand *Src1 = this->getSrc(1);
1562   const Operand *Src2 = this->getSrc(2);
1563   static const typename InstX86Base<
1564       Machine>::Traits::Assembler::GPREmitterShiftD Emitter = {
1565       &InstX86Base<Machine>::Traits::Assembler::shrd,
1566       &InstX86Base<Machine>::Traits::Assembler::shrd};
1567   emitIASGPRShiftDouble<Machine>(Func, Dest, Src1, Src2, Emitter);
1568 }
1569
1570 template <class Machine>
1571 void InstX86Shrd<Machine>::dump(const Cfg *Func) const {
1572   if (!BuildDefs::dump())
1573     return;
1574   Ostream &Str = Func->getContext()->getStrDump();
1575   this->dumpDest(Func);
1576   Str << " = shrd." << this->getDest()->getType() << " ";
1577   this->dumpSources(Func);
1578 }
1579
1580 template <class Machine>
1581 void InstX86Cmov<Machine>::emit(const Cfg *Func) const {
1582   if (!BuildDefs::dump())
1583     return;
1584   Ostream &Str = Func->getContext()->getStrEmit();
1585   Variable *Dest = this->getDest();
1586   Str << "\t";
1587   assert(Condition != InstX86Base<Machine>::Traits::Cond::Br_None);
1588   assert(this->getDest()->hasReg());
1589   Str << "cmov"
1590       << InstX86Base<Machine>::Traits::InstBrAttributes[Condition].DisplayString
1591       << this->getWidthString(Dest->getType()) << "\t";
1592   this->getSrc(1)->emit(Func);
1593   Str << ", ";
1594   Dest->emit(Func);
1595 }
1596
1597 template <class Machine>
1598 void InstX86Cmov<Machine>::emitIAS(const Cfg *Func) const {
1599   assert(Condition != InstX86Base<Machine>::Traits::Cond::Br_None);
1600   assert(this->getDest()->hasReg());
1601   assert(this->getSrcSize() == 2);
1602   Operand *Src = this->getSrc(1);
1603   Type SrcTy = Src->getType();
1604   assert(SrcTy == IceType_i16 || SrcTy == IceType_i32 ||
1605          (InstX86Base<Machine>::Traits::Is64Bit));
1606   typename InstX86Base<Machine>::Traits::Assembler *Asm =
1607       Func->getAssembler<typename InstX86Base<Machine>::Traits::Assembler>();
1608   if (const auto *SrcVar = llvm::dyn_cast<Variable>(Src)) {
1609     if (SrcVar->hasReg()) {
1610       Asm->cmov(SrcTy, Condition,
1611                 InstX86Base<Machine>::Traits::RegisterSet::getEncodedGPR(
1612                     this->getDest()->getRegNum()),
1613                 InstX86Base<Machine>::Traits::RegisterSet::getEncodedGPR(
1614                     SrcVar->getRegNum()));
1615     } else {
1616       Asm->cmov(
1617           SrcTy, Condition,
1618           InstX86Base<Machine>::Traits::RegisterSet::getEncodedGPR(
1619               this->getDest()->getRegNum()),
1620           static_cast<typename InstX86Base<Machine>::Traits::TargetLowering *>(
1621               Func->getTarget())
1622               ->stackVarToAsmOperand(SrcVar));
1623     }
1624   } else if (const auto Mem = llvm::dyn_cast<
1625                  typename InstX86Base<Machine>::Traits::X86OperandMem>(Src)) {
1626     assert(Mem->getSegmentRegister() ==
1627            InstX86Base<Machine>::Traits::X86OperandMem::DefaultSegment);
1628     Asm->cmov(SrcTy, Condition,
1629               InstX86Base<Machine>::Traits::RegisterSet::getEncodedGPR(
1630                   this->getDest()->getRegNum()),
1631               Mem->toAsmAddress(Asm));
1632   } else {
1633     llvm_unreachable("Unexpected operand type");
1634   }
1635 }
1636
1637 template <class Machine>
1638 void InstX86Cmov<Machine>::dump(const Cfg *Func) const {
1639   if (!BuildDefs::dump())
1640     return;
1641   Ostream &Str = Func->getContext()->getStrDump();
1642   Str << "cmov"
1643       << InstX86Base<Machine>::Traits::InstBrAttributes[Condition].DisplayString
1644       << ".";
1645   Str << this->getDest()->getType() << " ";
1646   this->dumpDest(Func);
1647   Str << ", ";
1648   this->dumpSources(Func);
1649 }
1650
1651 template <class Machine>
1652 void InstX86Cmpps<Machine>::emit(const Cfg *Func) const {
1653   if (!BuildDefs::dump())
1654     return;
1655   Ostream &Str = Func->getContext()->getStrEmit();
1656   assert(this->getSrcSize() == 2);
1657   assert(Condition < InstX86Base<Machine>::Traits::Cond::Cmpps_Invalid);
1658   Str << "\t";
1659   Str << "cmp"
1660       << InstX86Base<Machine>::Traits::InstCmppsAttributes[Condition].EmitString
1661       << "ps"
1662       << "\t";
1663   this->getSrc(1)->emit(Func);
1664   Str << ", ";
1665   this->getDest()->emit(Func);
1666 }
1667
1668 template <class Machine>
1669 void InstX86Cmpps<Machine>::emitIAS(const Cfg *Func) const {
1670   typename InstX86Base<Machine>::Traits::Assembler *Asm =
1671       Func->getAssembler<typename InstX86Base<Machine>::Traits::Assembler>();
1672   assert(this->getSrcSize() == 2);
1673   assert(Condition < InstX86Base<Machine>::Traits::Cond::Cmpps_Invalid);
1674   // Assuming there isn't any load folding for cmpps, and vector constants are
1675   // not allowed in PNaCl.
1676   assert(llvm::isa<Variable>(this->getSrc(1)));
1677   const auto SrcVar = llvm::cast<Variable>(this->getSrc(1));
1678   if (SrcVar->hasReg()) {
1679     Asm->cmpps(InstX86Base<Machine>::Traits::RegisterSet::getEncodedXmm(
1680                    this->getDest()->getRegNum()),
1681                InstX86Base<Machine>::Traits::RegisterSet::getEncodedXmm(
1682                    SrcVar->getRegNum()),
1683                Condition);
1684   } else {
1685     typename InstX86Base<Machine>::Traits::Address SrcStackAddr =
1686         static_cast<typename InstX86Base<Machine>::Traits::TargetLowering *>(
1687             Func->getTarget())
1688             ->stackVarToAsmOperand(SrcVar);
1689     Asm->cmpps(InstX86Base<Machine>::Traits::RegisterSet::getEncodedXmm(
1690                    this->getDest()->getRegNum()),
1691                SrcStackAddr, Condition);
1692   }
1693 }
1694
1695 template <class Machine>
1696 void InstX86Cmpps<Machine>::dump(const Cfg *Func) const {
1697   if (!BuildDefs::dump())
1698     return;
1699   Ostream &Str = Func->getContext()->getStrDump();
1700   assert(Condition < InstX86Base<Machine>::Traits::Cond::Cmpps_Invalid);
1701   this->dumpDest(Func);
1702   Str << " = cmp"
1703       << InstX86Base<Machine>::Traits::InstCmppsAttributes[Condition].EmitString
1704       << "ps"
1705       << "\t";
1706   this->dumpSources(Func);
1707 }
1708
1709 template <class Machine>
1710 void InstX86Cmpxchg<Machine>::emit(const Cfg *Func) const {
1711   if (!BuildDefs::dump())
1712     return;
1713   Ostream &Str = Func->getContext()->getStrEmit();
1714   assert(this->getSrcSize() == 3);
1715   if (this->Locked) {
1716     Str << "\tlock";
1717   }
1718   Str << "\tcmpxchg" << this->getWidthString(this->getSrc(0)->getType())
1719       << "\t";
1720   this->getSrc(2)->emit(Func);
1721   Str << ", ";
1722   this->getSrc(0)->emit(Func);
1723 }
1724
1725 template <class Machine>
1726 void InstX86Cmpxchg<Machine>::emitIAS(const Cfg *Func) const {
1727   assert(this->getSrcSize() == 3);
1728   typename InstX86Base<Machine>::Traits::Assembler *Asm =
1729       Func->getAssembler<typename InstX86Base<Machine>::Traits::Assembler>();
1730   Type Ty = this->getSrc(0)->getType();
1731   const auto Mem =
1732       llvm::cast<typename InstX86Base<Machine>::Traits::X86OperandMem>(
1733           this->getSrc(0));
1734   assert(Mem->getSegmentRegister() ==
1735          InstX86Base<Machine>::Traits::X86OperandMem::DefaultSegment);
1736   const typename InstX86Base<Machine>::Traits::Address Addr =
1737       Mem->toAsmAddress(Asm);
1738   const auto VarReg = llvm::cast<Variable>(this->getSrc(2));
1739   assert(VarReg->hasReg());
1740   const typename InstX86Base<Machine>::Traits::RegisterSet::GPRRegister Reg =
1741       InstX86Base<Machine>::Traits::RegisterSet::getEncodedGPR(
1742           VarReg->getRegNum());
1743   Asm->cmpxchg(Ty, Addr, Reg, this->Locked);
1744 }
1745
1746 template <class Machine>
1747 void InstX86Cmpxchg<Machine>::dump(const Cfg *Func) const {
1748   if (!BuildDefs::dump())
1749     return;
1750   Ostream &Str = Func->getContext()->getStrDump();
1751   if (this->Locked) {
1752     Str << "lock ";
1753   }
1754   Str << "cmpxchg." << this->getSrc(0)->getType() << " ";
1755   this->dumpSources(Func);
1756 }
1757
1758 template <class Machine>
1759 void InstX86Cmpxchg8b<Machine>::emit(const Cfg *Func) const {
1760   if (!BuildDefs::dump())
1761     return;
1762   Ostream &Str = Func->getContext()->getStrEmit();
1763   assert(this->getSrcSize() == 5);
1764   if (this->Locked) {
1765     Str << "\tlock";
1766   }
1767   Str << "\tcmpxchg8b\t";
1768   this->getSrc(0)->emit(Func);
1769 }
1770
1771 template <class Machine>
1772 void InstX86Cmpxchg8b<Machine>::emitIAS(const Cfg *Func) const {
1773   assert(this->getSrcSize() == 5);
1774   typename InstX86Base<Machine>::Traits::Assembler *Asm =
1775       Func->getAssembler<typename InstX86Base<Machine>::Traits::Assembler>();
1776   const auto Mem =
1777       llvm::cast<typename InstX86Base<Machine>::Traits::X86OperandMem>(
1778           this->getSrc(0));
1779   assert(Mem->getSegmentRegister() ==
1780          InstX86Base<Machine>::Traits::X86OperandMem::DefaultSegment);
1781   const typename InstX86Base<Machine>::Traits::Address Addr =
1782       Mem->toAsmAddress(Asm);
1783   Asm->cmpxchg8b(Addr, this->Locked);
1784 }
1785
1786 template <class Machine>
1787 void InstX86Cmpxchg8b<Machine>::dump(const Cfg *Func) const {
1788   if (!BuildDefs::dump())
1789     return;
1790   Ostream &Str = Func->getContext()->getStrDump();
1791   if (this->Locked) {
1792     Str << "lock ";
1793   }
1794   Str << "cmpxchg8b ";
1795   this->dumpSources(Func);
1796 }
1797
1798 template <class Machine> void InstX86Cvt<Machine>::emit(const Cfg *Func) const {
1799   if (!BuildDefs::dump())
1800     return;
1801   Ostream &Str = Func->getContext()->getStrEmit();
1802   assert(this->getSrcSize() == 1);
1803   Str << "\tcvt";
1804   if (isTruncating())
1805     Str << "t";
1806   Str << InstX86Base<Machine>::Traits::TypeAttributes[this->getSrc(0)
1807                                                           ->getType()]
1808              .CvtString << "2"
1809       << InstX86Base<
1810              Machine>::Traits::TypeAttributes[this->getDest()->getType()]
1811              .CvtString << "\t";
1812   this->getSrc(0)->emit(Func);
1813   Str << ", ";
1814   this->getDest()->emit(Func);
1815 }
1816
1817 template <class Machine>
1818 void InstX86Cvt<Machine>::emitIAS(const Cfg *Func) const {
1819   assert(this->getSrcSize() == 1);
1820   const Variable *Dest = this->getDest();
1821   const Operand *Src = this->getSrc(0);
1822   Type DestTy = Dest->getType();
1823   Type SrcTy = Src->getType();
1824   switch (Variant) {
1825   case Si2ss: {
1826     assert(isScalarIntegerType(SrcTy));
1827     if (!InstX86Base<Machine>::Traits::Is64Bit) {
1828       assert(typeWidthInBytes(SrcTy) <= 4);
1829     } else {
1830       assert(SrcTy == IceType_i32 || SrcTy == IceType_i64);
1831     }
1832     assert(isScalarFloatingType(DestTy));
1833     static const typename InstX86Base<Machine>::Traits::Assembler::
1834         template CastEmitterRegOp<
1835             typename InstX86Base<Machine>::Traits::RegisterSet::XmmRegister,
1836             typename InstX86Base<Machine>::Traits::RegisterSet::GPRRegister>
1837             Emitter = {&InstX86Base<Machine>::Traits::Assembler::cvtsi2ss,
1838                        &InstX86Base<Machine>::Traits::Assembler::cvtsi2ss};
1839     emitIASCastRegOp<
1840         Machine,
1841         typename InstX86Base<Machine>::Traits::RegisterSet::XmmRegister,
1842         typename InstX86Base<Machine>::Traits::RegisterSet::GPRRegister,
1843         InstX86Base<Machine>::Traits::RegisterSet::getEncodedXmm,
1844         InstX86Base<Machine>::Traits::RegisterSet::getEncodedGPR>(
1845         Func, DestTy, Dest, SrcTy, Src, Emitter);
1846     return;
1847   }
1848   case Tss2si: {
1849     assert(isScalarFloatingType(SrcTy));
1850     assert(isScalarIntegerType(DestTy));
1851     if (!InstX86Base<Machine>::Traits::Is64Bit) {
1852       assert(typeWidthInBytes(DestTy) <= 4);
1853     } else {
1854       assert(DestTy == IceType_i32 || DestTy == IceType_i64);
1855     }
1856     static const typename InstX86Base<Machine>::Traits::Assembler::
1857         template CastEmitterRegOp<
1858             typename InstX86Base<Machine>::Traits::RegisterSet::GPRRegister,
1859             typename InstX86Base<Machine>::Traits::RegisterSet::XmmRegister>
1860             Emitter = {&InstX86Base<Machine>::Traits::Assembler::cvttss2si,
1861                        &InstX86Base<Machine>::Traits::Assembler::cvttss2si};
1862     emitIASCastRegOp<
1863         Machine,
1864         typename InstX86Base<Machine>::Traits::RegisterSet::GPRRegister,
1865         typename InstX86Base<Machine>::Traits::RegisterSet::XmmRegister,
1866         InstX86Base<Machine>::Traits::RegisterSet::getEncodedGPR,
1867         InstX86Base<Machine>::Traits::RegisterSet::getEncodedXmm>(
1868         Func, DestTy, Dest, SrcTy, Src, Emitter);
1869     return;
1870   }
1871   case Float2float: {
1872     assert(isScalarFloatingType(SrcTy));
1873     assert(isScalarFloatingType(DestTy));
1874     assert(DestTy != SrcTy);
1875     static const typename InstX86Base<
1876         Machine>::Traits::Assembler::XmmEmitterRegOp Emitter = {
1877         &InstX86Base<Machine>::Traits::Assembler::cvtfloat2float,
1878         &InstX86Base<Machine>::Traits::Assembler::cvtfloat2float};
1879     emitIASRegOpTyXMM<Machine>(Func, SrcTy, Dest, Src, Emitter);
1880     return;
1881   }
1882   case Dq2ps: {
1883     assert(isVectorIntegerType(SrcTy));
1884     assert(isVectorFloatingType(DestTy));
1885     static const typename InstX86Base<
1886         Machine>::Traits::Assembler::XmmEmitterRegOp Emitter = {
1887         &InstX86Base<Machine>::Traits::Assembler::cvtdq2ps,
1888         &InstX86Base<Machine>::Traits::Assembler::cvtdq2ps};
1889     emitIASRegOpTyXMM<Machine>(Func, DestTy, Dest, Src, Emitter);
1890     return;
1891   }
1892   case Tps2dq: {
1893     assert(isVectorFloatingType(SrcTy));
1894     assert(isVectorIntegerType(DestTy));
1895     static const typename InstX86Base<
1896         Machine>::Traits::Assembler::XmmEmitterRegOp Emitter = {
1897         &InstX86Base<Machine>::Traits::Assembler::cvttps2dq,
1898         &InstX86Base<Machine>::Traits::Assembler::cvttps2dq};
1899     emitIASRegOpTyXMM<Machine>(Func, DestTy, Dest, Src, Emitter);
1900     return;
1901   }
1902   }
1903 }
1904
1905 template <class Machine> void InstX86Cvt<Machine>::dump(const Cfg *Func) const {
1906   if (!BuildDefs::dump())
1907     return;
1908   Ostream &Str = Func->getContext()->getStrDump();
1909   this->dumpDest(Func);
1910   Str << " = cvt";
1911   if (isTruncating())
1912     Str << "t";
1913   Str << InstX86Base<Machine>::Traits::TypeAttributes[this->getSrc(0)
1914                                                           ->getType()]
1915              .CvtString << "2"
1916       << InstX86Base<
1917              Machine>::Traits::TypeAttributes[this->getDest()->getType()]
1918              .CvtString << " ";
1919   this->dumpSources(Func);
1920 }
1921
1922 template <class Machine>
1923 void InstX86Icmp<Machine>::emit(const Cfg *Func) const {
1924   if (!BuildDefs::dump())
1925     return;
1926   Ostream &Str = Func->getContext()->getStrEmit();
1927   assert(this->getSrcSize() == 2);
1928   Str << "\tcmp" << this->getWidthString(this->getSrc(0)->getType()) << "\t";
1929   this->getSrc(1)->emit(Func);
1930   Str << ", ";
1931   this->getSrc(0)->emit(Func);
1932 }
1933
1934 template <class Machine>
1935 void InstX86Icmp<Machine>::emitIAS(const Cfg *Func) const {
1936   assert(this->getSrcSize() == 2);
1937   const Operand *Src0 = this->getSrc(0);
1938   const Operand *Src1 = this->getSrc(1);
1939   Type Ty = Src0->getType();
1940   static const typename InstX86Base<Machine>::Traits::Assembler::GPREmitterRegOp
1941       RegEmitter = {&InstX86Base<Machine>::Traits::Assembler::cmp,
1942                     &InstX86Base<Machine>::Traits::Assembler::cmp,
1943                     &InstX86Base<Machine>::Traits::Assembler::cmp};
1944   static const typename InstX86Base<
1945       Machine>::Traits::Assembler::GPREmitterAddrOp AddrEmitter = {
1946       &InstX86Base<Machine>::Traits::Assembler::cmp,
1947       &InstX86Base<Machine>::Traits::Assembler::cmp};
1948   if (const auto SrcVar0 = llvm::dyn_cast<Variable>(Src0)) {
1949     if (SrcVar0->hasReg()) {
1950       emitIASRegOpTyGPR<Machine>(Func, Ty, SrcVar0, Src1, RegEmitter);
1951       return;
1952     }
1953   }
1954   emitIASAsAddrOpTyGPR<Machine>(Func, Ty, Src0, Src1, AddrEmitter);
1955 }
1956
1957 template <class Machine>
1958 void InstX86Icmp<Machine>::dump(const Cfg *Func) const {
1959   if (!BuildDefs::dump())
1960     return;
1961   Ostream &Str = Func->getContext()->getStrDump();
1962   Str << "cmp." << this->getSrc(0)->getType() << " ";
1963   this->dumpSources(Func);
1964 }
1965
1966 template <class Machine>
1967 void InstX86Ucomiss<Machine>::emit(const Cfg *Func) const {
1968   if (!BuildDefs::dump())
1969     return;
1970   Ostream &Str = Func->getContext()->getStrEmit();
1971   assert(this->getSrcSize() == 2);
1972   Str << "\tucomi"
1973       << InstX86Base<Machine>::Traits::TypeAttributes[this->getSrc(0)
1974                                                           ->getType()]
1975              .SdSsString << "\t";
1976   this->getSrc(1)->emit(Func);
1977   Str << ", ";
1978   this->getSrc(0)->emit(Func);
1979 }
1980
1981 template <class Machine>
1982 void InstX86Ucomiss<Machine>::emitIAS(const Cfg *Func) const {
1983   assert(this->getSrcSize() == 2);
1984   // Currently src0 is always a variable by convention, to avoid having two
1985   // memory operands.
1986   assert(llvm::isa<Variable>(this->getSrc(0)));
1987   const auto Src0Var = llvm::cast<Variable>(this->getSrc(0));
1988   Type Ty = Src0Var->getType();
1989   static const typename InstX86Base<Machine>::Traits::Assembler::XmmEmitterRegOp
1990       Emitter = {&InstX86Base<Machine>::Traits::Assembler::ucomiss,
1991                  &InstX86Base<Machine>::Traits::Assembler::ucomiss};
1992   emitIASRegOpTyXMM<Machine>(Func, Ty, Src0Var, this->getSrc(1), Emitter);
1993 }
1994
1995 template <class Machine>
1996 void InstX86Ucomiss<Machine>::dump(const Cfg *Func) const {
1997   if (!BuildDefs::dump())
1998     return;
1999   Ostream &Str = Func->getContext()->getStrDump();
2000   Str << "ucomiss." << this->getSrc(0)->getType() << " ";
2001   this->dumpSources(Func);
2002 }
2003
2004 template <class Machine> void InstX86UD2<Machine>::emit(const Cfg *Func) const {
2005   if (!BuildDefs::dump())
2006     return;
2007   Ostream &Str = Func->getContext()->getStrEmit();
2008   assert(this->getSrcSize() == 0);
2009   Str << "\tud2";
2010 }
2011
2012 template <class Machine>
2013 void InstX86UD2<Machine>::emitIAS(const Cfg *Func) const {
2014   typename InstX86Base<Machine>::Traits::Assembler *Asm =
2015       Func->getAssembler<typename InstX86Base<Machine>::Traits::Assembler>();
2016   Asm->ud2();
2017 }
2018
2019 template <class Machine> void InstX86UD2<Machine>::dump(const Cfg *Func) const {
2020   if (!BuildDefs::dump())
2021     return;
2022   Ostream &Str = Func->getContext()->getStrDump();
2023   Str << "ud2";
2024 }
2025
2026 template <class Machine>
2027 void InstX86Test<Machine>::emit(const Cfg *Func) const {
2028   if (!BuildDefs::dump())
2029     return;
2030   Ostream &Str = Func->getContext()->getStrEmit();
2031   assert(this->getSrcSize() == 2);
2032   Str << "\ttest" << this->getWidthString(this->getSrc(0)->getType()) << "\t";
2033   this->getSrc(1)->emit(Func);
2034   Str << ", ";
2035   this->getSrc(0)->emit(Func);
2036 }
2037
2038 template <class Machine>
2039 void InstX86Test<Machine>::emitIAS(const Cfg *Func) const {
2040   assert(this->getSrcSize() == 2);
2041   const Operand *Src0 = this->getSrc(0);
2042   const Operand *Src1 = this->getSrc(1);
2043   Type Ty = Src0->getType();
2044   // The Reg/Addr form of test is not encodeable.
2045   static const typename InstX86Base<Machine>::Traits::Assembler::GPREmitterRegOp
2046       RegEmitter = {&InstX86Base<Machine>::Traits::Assembler::test, nullptr,
2047                     &InstX86Base<Machine>::Traits::Assembler::test};
2048   static const typename InstX86Base<
2049       Machine>::Traits::Assembler::GPREmitterAddrOp AddrEmitter = {
2050       &InstX86Base<Machine>::Traits::Assembler::test,
2051       &InstX86Base<Machine>::Traits::Assembler::test};
2052   if (const auto SrcVar0 = llvm::dyn_cast<Variable>(Src0)) {
2053     if (SrcVar0->hasReg()) {
2054       emitIASRegOpTyGPR<Machine>(Func, Ty, SrcVar0, Src1, RegEmitter);
2055       return;
2056     }
2057   }
2058   llvm_unreachable("Nothing actually generates this so it's untested");
2059   emitIASAsAddrOpTyGPR<Machine>(Func, Ty, Src0, Src1, AddrEmitter);
2060 }
2061
2062 template <class Machine>
2063 void InstX86Test<Machine>::dump(const Cfg *Func) const {
2064   if (!BuildDefs::dump())
2065     return;
2066   Ostream &Str = Func->getContext()->getStrDump();
2067   Str << "test." << this->getSrc(0)->getType() << " ";
2068   this->dumpSources(Func);
2069 }
2070
2071 template <class Machine>
2072 void InstX86Mfence<Machine>::emit(const Cfg *Func) const {
2073   if (!BuildDefs::dump())
2074     return;
2075   Ostream &Str = Func->getContext()->getStrEmit();
2076   assert(this->getSrcSize() == 0);
2077   Str << "\tmfence";
2078 }
2079
2080 template <class Machine>
2081 void InstX86Mfence<Machine>::emitIAS(const Cfg *Func) const {
2082   typename InstX86Base<Machine>::Traits::Assembler *Asm =
2083       Func->getAssembler<typename InstX86Base<Machine>::Traits::Assembler>();
2084   Asm->mfence();
2085 }
2086
2087 template <class Machine>
2088 void InstX86Mfence<Machine>::dump(const Cfg *Func) const {
2089   if (!BuildDefs::dump())
2090     return;
2091   Ostream &Str = Func->getContext()->getStrDump();
2092   Str << "mfence";
2093 }
2094
2095 template <class Machine>
2096 void InstX86Store<Machine>::emit(const Cfg *Func) const {
2097   if (!BuildDefs::dump())
2098     return;
2099   Ostream &Str = Func->getContext()->getStrEmit();
2100   assert(this->getSrcSize() == 2);
2101   Type Ty = this->getSrc(0)->getType();
2102   Str << "\tmov" << this->getWidthString(Ty)
2103       << InstX86Base<Machine>::Traits::TypeAttributes[Ty].SdSsString << "\t";
2104   this->getSrc(0)->emit(Func);
2105   Str << ", ";
2106   this->getSrc(1)->emit(Func);
2107 }
2108
2109 template <class Machine>
2110 void InstX86Store<Machine>::emitIAS(const Cfg *Func) const {
2111   assert(this->getSrcSize() == 2);
2112   const Operand *Dest = this->getSrc(1);
2113   const Operand *Src = this->getSrc(0);
2114   Type DestTy = Dest->getType();
2115   if (isScalarFloatingType(DestTy)) {
2116     // Src must be a register, since Dest is a Mem operand of some kind.
2117     const auto SrcVar = llvm::cast<Variable>(Src);
2118     assert(SrcVar->hasReg());
2119     typename InstX86Base<Machine>::Traits::RegisterSet::XmmRegister SrcReg =
2120         InstX86Base<Machine>::Traits::RegisterSet::getEncodedXmm(
2121             SrcVar->getRegNum());
2122     typename InstX86Base<Machine>::Traits::Assembler *Asm =
2123         Func->getAssembler<typename InstX86Base<Machine>::Traits::Assembler>();
2124     if (const auto DestVar = llvm::dyn_cast<Variable>(Dest)) {
2125       assert(!DestVar->hasReg());
2126       typename InstX86Base<Machine>::Traits::Address StackAddr(
2127           static_cast<typename InstX86Base<Machine>::Traits::TargetLowering *>(
2128               Func->getTarget())
2129               ->stackVarToAsmOperand(DestVar));
2130       Asm->movss(DestTy, StackAddr, SrcReg);
2131     } else {
2132       const auto DestMem =
2133           llvm::cast<typename InstX86Base<Machine>::Traits::X86OperandMem>(
2134               Dest);
2135       assert(DestMem->getSegmentRegister() ==
2136              InstX86Base<Machine>::Traits::X86OperandMem::DefaultSegment);
2137       Asm->movss(DestTy, DestMem->toAsmAddress(Asm), SrcReg);
2138     }
2139     return;
2140   } else {
2141     assert(isScalarIntegerType(DestTy));
2142     static const typename InstX86Base<
2143         Machine>::Traits::Assembler::GPREmitterAddrOp GPRAddrEmitter = {
2144         &InstX86Base<Machine>::Traits::Assembler::mov,
2145         &InstX86Base<Machine>::Traits::Assembler::mov};
2146     emitIASAsAddrOpTyGPR<Machine>(Func, DestTy, Dest, Src, GPRAddrEmitter);
2147   }
2148 }
2149
2150 template <class Machine>
2151 void InstX86Store<Machine>::dump(const Cfg *Func) const {
2152   if (!BuildDefs::dump())
2153     return;
2154   Ostream &Str = Func->getContext()->getStrDump();
2155   Str << "mov." << this->getSrc(0)->getType() << " ";
2156   this->getSrc(1)->dump(Func);
2157   Str << ", ";
2158   this->getSrc(0)->dump(Func);
2159 }
2160
2161 template <class Machine>
2162 void InstX86StoreP<Machine>::emit(const Cfg *Func) const {
2163   if (!BuildDefs::dump())
2164     return;
2165   Ostream &Str = Func->getContext()->getStrEmit();
2166   assert(this->getSrcSize() == 2);
2167   assert(isVectorType(this->getSrc(1)->getType()));
2168   Str << "\tmovups\t";
2169   this->getSrc(0)->emit(Func);
2170   Str << ", ";
2171   this->getSrc(1)->emit(Func);
2172 }
2173
2174 template <class Machine>
2175 void InstX86StoreP<Machine>::emitIAS(const Cfg *Func) const {
2176   typename InstX86Base<Machine>::Traits::Assembler *Asm =
2177       Func->getAssembler<typename InstX86Base<Machine>::Traits::Assembler>();
2178   assert(this->getSrcSize() == 2);
2179   const auto SrcVar = llvm::cast<Variable>(this->getSrc(0));
2180   const auto DestMem =
2181       llvm::cast<typename InstX86Base<Machine>::Traits::X86OperandMem>(
2182           this->getSrc(1));
2183   assert(DestMem->getSegmentRegister() ==
2184          InstX86Base<Machine>::Traits::X86OperandMem::DefaultSegment);
2185   assert(SrcVar->hasReg());
2186   Asm->movups(DestMem->toAsmAddress(Asm),
2187               InstX86Base<Machine>::Traits::RegisterSet::getEncodedXmm(
2188                   SrcVar->getRegNum()));
2189 }
2190
2191 template <class Machine>
2192 void InstX86StoreP<Machine>::dump(const Cfg *Func) const {
2193   if (!BuildDefs::dump())
2194     return;
2195   Ostream &Str = Func->getContext()->getStrDump();
2196   Str << "storep." << this->getSrc(0)->getType() << " ";
2197   this->getSrc(1)->dump(Func);
2198   Str << ", ";
2199   this->getSrc(0)->dump(Func);
2200 }
2201
2202 template <class Machine>
2203 void InstX86StoreQ<Machine>::emit(const Cfg *Func) const {
2204   if (!BuildDefs::dump())
2205     return;
2206   Ostream &Str = Func->getContext()->getStrEmit();
2207   assert(this->getSrcSize() == 2);
2208   assert(this->getSrc(1)->getType() == IceType_i64 ||
2209          this->getSrc(1)->getType() == IceType_f64 ||
2210          isVectorType(this->getSrc(1)->getType()));
2211   Str << "\tmovq\t";
2212   this->getSrc(0)->emit(Func);
2213   Str << ", ";
2214   this->getSrc(1)->emit(Func);
2215 }
2216
2217 template <class Machine>
2218 void InstX86StoreQ<Machine>::emitIAS(const Cfg *Func) const {
2219   typename InstX86Base<Machine>::Traits::Assembler *Asm =
2220       Func->getAssembler<typename InstX86Base<Machine>::Traits::Assembler>();
2221   assert(this->getSrcSize() == 2);
2222   const auto SrcVar = llvm::cast<Variable>(this->getSrc(0));
2223   const auto DestMem =
2224       llvm::cast<typename InstX86Base<Machine>::Traits::X86OperandMem>(
2225           this->getSrc(1));
2226   assert(DestMem->getSegmentRegister() ==
2227          InstX86Base<Machine>::Traits::X86OperandMem::DefaultSegment);
2228   assert(SrcVar->hasReg());
2229   Asm->movq(DestMem->toAsmAddress(Asm),
2230             InstX86Base<Machine>::Traits::RegisterSet::getEncodedXmm(
2231                 SrcVar->getRegNum()));
2232 }
2233
2234 template <class Machine>
2235 void InstX86StoreQ<Machine>::dump(const Cfg *Func) const {
2236   if (!BuildDefs::dump())
2237     return;
2238   Ostream &Str = Func->getContext()->getStrDump();
2239   Str << "storeq." << this->getSrc(0)->getType() << " ";
2240   this->getSrc(1)->dump(Func);
2241   Str << ", ";
2242   this->getSrc(0)->dump(Func);
2243 }
2244
2245 template <class Machine> void InstX86Lea<Machine>::emit(const Cfg *Func) const {
2246   if (!BuildDefs::dump())
2247     return;
2248   Ostream &Str = Func->getContext()->getStrEmit();
2249   assert(this->getSrcSize() == 1);
2250   assert(this->getDest()->hasReg());
2251   Str << "\tleal\t";
2252   Operand *Src0 = this->getSrc(0);
2253   if (const auto Src0Var = llvm::dyn_cast<Variable>(Src0)) {
2254     Type Ty = Src0Var->getType();
2255     // lea on x86-32 doesn't accept mem128 operands, so cast VSrc0 to an
2256     // acceptable type.
2257     Src0Var->asType(isVectorType(Ty) ? IceType_i32 : Ty)->emit(Func);
2258   } else {
2259     Src0->emit(Func);
2260   }
2261   Str << ", ";
2262   this->getDest()->emit(Func);
2263 }
2264
2265 inline bool isIntegerConstant(const Operand *Op) {
2266   return llvm::isa<ConstantInteger32>(Op) || llvm::isa<ConstantInteger64>(Op);
2267 }
2268
2269 template <class Machine> void InstX86Mov<Machine>::emit(const Cfg *Func) const {
2270   if (!BuildDefs::dump())
2271     return;
2272   Ostream &Str = Func->getContext()->getStrEmit();
2273   assert(this->getSrcSize() == 1);
2274   Operand *Src = this->getSrc(0);
2275   Type SrcTy = Src->getType();
2276   Type DestTy = this->getDest()->getType();
2277   if (InstX86Base<Machine>::Traits::Is64Bit && DestTy == IceType_i64 &&
2278       isIntegerConstant(Src)) {
2279     Str << "\tmovabs\t";
2280   } else {
2281     Str << "\tmov"
2282         << (!isScalarFloatingType(DestTy)
2283                 ? this->getWidthString(SrcTy)
2284                 : InstX86Base<Machine>::Traits::TypeAttributes[DestTy]
2285                       .SdSsString) << "\t";
2286   }
2287   // For an integer truncation operation, src is wider than dest. Ideally, we
2288   // use a mov instruction whose data width matches the narrower dest. This is
2289   // a problem if e.g. src is a register like esi or si where there is no 8-bit
2290   // version of the register. To be safe, we instead widen the dest to match
2291   // src. This works even for stack-allocated dest variables because
2292   // typeWidthOnStack() pads to a 4-byte boundary even if only a lower portion
2293   // is used.
2294   // TODO: This assert disallows usages such as copying a floating
2295   // point value between a vector and a scalar (which movss is used for). Clean
2296   // this up.
2297   assert(Func->getTarget()->typeWidthInBytesOnStack(DestTy) ==
2298          Func->getTarget()->typeWidthInBytesOnStack(SrcTy));
2299   Src->emit(Func);
2300   Str << ", ";
2301   this->getDest()->asType(SrcTy)->emit(Func);
2302 }
2303
2304 template <class Machine>
2305 void InstX86Mov<Machine>::emitIAS(const Cfg *Func) const {
2306   assert(this->getSrcSize() == 1);
2307   const Variable *Dest = this->getDest();
2308   const Operand *Src = this->getSrc(0);
2309   Type DestTy = Dest->getType();
2310   Type SrcTy = Src->getType();
2311   // Mov can be used for GPRs or XMM registers. Also, the type does not
2312   // necessarily match (Mov can be used for bitcasts). However, when the type
2313   // does not match, one of the operands must be a register. Thus, the strategy
2314   // is to find out if Src or Dest are a register, then use that register's
2315   // type to decide on which emitter set to use. The emitter set will include
2316   // reg-reg movs, but that case should be unused when the types don't match.
2317   static const typename InstX86Base<Machine>::Traits::Assembler::XmmEmitterRegOp
2318       XmmRegEmitter = {&InstX86Base<Machine>::Traits::Assembler::movss,
2319                        &InstX86Base<Machine>::Traits::Assembler::movss};
2320   static const typename InstX86Base<Machine>::Traits::Assembler::GPREmitterRegOp
2321       GPRRegEmitter = {&InstX86Base<Machine>::Traits::Assembler::mov,
2322                        &InstX86Base<Machine>::Traits::Assembler::mov,
2323                        &InstX86Base<Machine>::Traits::Assembler::mov};
2324   static const typename InstX86Base<
2325       Machine>::Traits::Assembler::GPREmitterAddrOp GPRAddrEmitter = {
2326       &InstX86Base<Machine>::Traits::Assembler::mov,
2327       &InstX86Base<Machine>::Traits::Assembler::mov};
2328   // For an integer truncation operation, src is wider than dest. Ideally, we
2329   // use a mov instruction whose data width matches the narrower dest. This is
2330   // a problem if e.g. src is a register like esi or si where there is no 8-bit
2331   // version of the register. To be safe, we instead widen the dest to match
2332   // src. This works even for stack-allocated dest variables because
2333   // typeWidthOnStack() pads to a 4-byte boundary even if only a lower portion
2334   // is used.
2335   // TODO: This assert disallows usages such as copying a floating
2336   // point value between a vector and a scalar (which movss is used for). Clean
2337   // this up.
2338   assert(
2339       Func->getTarget()->typeWidthInBytesOnStack(this->getDest()->getType()) ==
2340       Func->getTarget()->typeWidthInBytesOnStack(Src->getType()));
2341   if (Dest->hasReg()) {
2342     if (isScalarFloatingType(DestTy)) {
2343       emitIASRegOpTyXMM<Machine>(Func, DestTy, Dest, Src, XmmRegEmitter);
2344       return;
2345     } else {
2346       assert(isScalarIntegerType(DestTy));
2347       // Widen DestTy for truncation (see above note). We should only do this
2348       // when both Src and Dest are integer types.
2349       if (InstX86Base<Machine>::Traits::Is64Bit && DestTy == IceType_i64 &&
2350           isIntegerConstant(Src)) {
2351         uint64_t Value = -1;
2352         if (const auto *C64 = llvm::dyn_cast<ConstantInteger64>(Src)) {
2353           Value = C64->getValue();
2354         } else {
2355           Value = llvm::cast<ConstantInteger32>(Src)->getValue();
2356         }
2357         Func->getAssembler<typename InstX86Base<Machine>::Traits::Assembler>()
2358             ->movabs(InstX86Base<Machine>::Traits::RegisterSet::getEncodedGPR(
2359                          Dest->getRegNum()),
2360                      Value);
2361         return;
2362       }
2363       if (isScalarIntegerType(SrcTy)) {
2364         DestTy = SrcTy;
2365       }
2366       emitIASRegOpTyGPR<Machine>(Func, DestTy, Dest, Src, GPRRegEmitter);
2367       return;
2368     }
2369   } else {
2370     // Dest must be Stack and Src *could* be a register. Use Src's type to
2371     // decide on the emitters.
2372     typename InstX86Base<Machine>::Traits::Address StackAddr(
2373         static_cast<typename InstX86Base<Machine>::Traits::TargetLowering *>(
2374             Func->getTarget())
2375             ->stackVarToAsmOperand(Dest));
2376     if (isScalarFloatingType(SrcTy)) {
2377       // Src must be a register.
2378       const auto SrcVar = llvm::cast<Variable>(Src);
2379       assert(SrcVar->hasReg());
2380       typename InstX86Base<Machine>::Traits::Assembler *Asm =
2381           Func->getAssembler<
2382               typename InstX86Base<Machine>::Traits::Assembler>();
2383       Asm->movss(SrcTy, StackAddr,
2384                  InstX86Base<Machine>::Traits::RegisterSet::getEncodedXmm(
2385                      SrcVar->getRegNum()));
2386       return;
2387     } else {
2388       // Src can be a register or immediate.
2389       assert(isScalarIntegerType(SrcTy));
2390       emitIASAddrOpTyGPR<Machine>(Func, SrcTy, StackAddr, Src, GPRAddrEmitter);
2391       return;
2392     }
2393     return;
2394   }
2395 }
2396
2397 template <class Machine>
2398 void InstX86Movd<Machine>::emitIAS(const Cfg *Func) const {
2399   typename InstX86Base<Machine>::Traits::Assembler *Asm =
2400       Func->getAssembler<typename InstX86Base<Machine>::Traits::Assembler>();
2401   assert(this->getSrcSize() == 1);
2402   const Variable *Dest = this->getDest();
2403   const auto SrcVar = llvm::cast<Variable>(this->getSrc(0));
2404   // For insert/extract element (one of Src/Dest is an Xmm vector and the other
2405   // is an int type).
2406   if (SrcVar->getType() == IceType_i32 ||
2407       (InstX86Base<Machine>::Traits::Is64Bit &&
2408        SrcVar->getType() == IceType_i64)) {
2409     assert(isVectorType(Dest->getType()) ||
2410            (isScalarFloatingType(Dest->getType()) &&
2411             typeWidthInBytes(SrcVar->getType()) ==
2412                 typeWidthInBytes(Dest->getType())));
2413     assert(Dest->hasReg());
2414     typename InstX86Base<Machine>::Traits::RegisterSet::XmmRegister DestReg =
2415         InstX86Base<Machine>::Traits::RegisterSet::getEncodedXmm(
2416             Dest->getRegNum());
2417     if (SrcVar->hasReg()) {
2418       Asm->movd(SrcVar->getType(), DestReg,
2419                 InstX86Base<Machine>::Traits::RegisterSet::getEncodedGPR(
2420                     SrcVar->getRegNum()));
2421     } else {
2422       typename InstX86Base<Machine>::Traits::Address StackAddr(
2423           static_cast<typename InstX86Base<Machine>::Traits::TargetLowering *>(
2424               Func->getTarget())
2425               ->stackVarToAsmOperand(SrcVar));
2426       Asm->movd(SrcVar->getType(), DestReg, StackAddr);
2427     }
2428   } else {
2429     assert(isVectorType(SrcVar->getType()) ||
2430            (isScalarFloatingType(SrcVar->getType()) &&
2431             typeWidthInBytes(SrcVar->getType()) ==
2432                 typeWidthInBytes(Dest->getType())));
2433     assert(SrcVar->hasReg());
2434     assert(Dest->getType() == IceType_i32 ||
2435            (InstX86Base<Machine>::Traits::Is64Bit &&
2436             Dest->getType() == IceType_i64));
2437     typename InstX86Base<Machine>::Traits::RegisterSet::XmmRegister SrcReg =
2438         InstX86Base<Machine>::Traits::RegisterSet::getEncodedXmm(
2439             SrcVar->getRegNum());
2440     if (Dest->hasReg()) {
2441       Asm->movd(Dest->getType(),
2442                 InstX86Base<Machine>::Traits::RegisterSet::getEncodedGPR(
2443                     Dest->getRegNum()),
2444                 SrcReg);
2445     } else {
2446       typename InstX86Base<Machine>::Traits::Address StackAddr(
2447           static_cast<typename InstX86Base<Machine>::Traits::TargetLowering *>(
2448               Func->getTarget())
2449               ->stackVarToAsmOperand(Dest));
2450       Asm->movd(Dest->getType(), StackAddr, SrcReg);
2451     }
2452   }
2453 }
2454
2455 template <class Machine>
2456 void InstX86Movp<Machine>::emit(const Cfg *Func) const {
2457   if (!BuildDefs::dump())
2458     return;
2459   // TODO(wala,stichnot): movups works with all vector operands, but there
2460   // exist other instructions (movaps, movdqa, movdqu) that may perform better,
2461   // depending on the data type and alignment of the operands.
2462   Ostream &Str = Func->getContext()->getStrEmit();
2463   assert(this->getSrcSize() == 1);
2464   Str << "\tmovups\t";
2465   this->getSrc(0)->emit(Func);
2466   Str << ", ";
2467   this->getDest()->emit(Func);
2468 }
2469
2470 template <class Machine>
2471 void InstX86Movp<Machine>::emitIAS(const Cfg *Func) const {
2472   assert(this->getSrcSize() == 1);
2473   assert(isVectorType(this->getDest()->getType()));
2474   const Variable *Dest = this->getDest();
2475   const Operand *Src = this->getSrc(0);
2476   static const typename InstX86Base<
2477       Machine>::Traits::Assembler::XmmEmitterMovOps Emitter = {
2478       &InstX86Base<Machine>::Traits::Assembler::movups,
2479       &InstX86Base<Machine>::Traits::Assembler::movups,
2480       &InstX86Base<Machine>::Traits::Assembler::movups};
2481   emitIASMovlikeXMM<Machine>(Func, Dest, Src, Emitter);
2482 }
2483
2484 template <class Machine>
2485 void InstX86Movq<Machine>::emit(const Cfg *Func) const {
2486   if (!BuildDefs::dump())
2487     return;
2488   Ostream &Str = Func->getContext()->getStrEmit();
2489   assert(this->getSrcSize() == 1);
2490   assert(this->getDest()->getType() == IceType_i64 ||
2491          this->getDest()->getType() == IceType_f64);
2492   Str << "\tmovq\t";
2493   this->getSrc(0)->emit(Func);
2494   Str << ", ";
2495   this->getDest()->emit(Func);
2496 }
2497
2498 template <class Machine>
2499 void InstX86Movq<Machine>::emitIAS(const Cfg *Func) const {
2500   assert(this->getSrcSize() == 1);
2501   assert(this->getDest()->getType() == IceType_i64 ||
2502          this->getDest()->getType() == IceType_f64);
2503   const Variable *Dest = this->getDest();
2504   const Operand *Src = this->getSrc(0);
2505   static const typename InstX86Base<
2506       Machine>::Traits::Assembler::XmmEmitterMovOps Emitter = {
2507       &InstX86Base<Machine>::Traits::Assembler::movq,
2508       &InstX86Base<Machine>::Traits::Assembler::movq,
2509       &InstX86Base<Machine>::Traits::Assembler::movq};
2510   emitIASMovlikeXMM<Machine>(Func, Dest, Src, Emitter);
2511 }
2512
2513 template <class Machine>
2514 void InstX86MovssRegs<Machine>::emitIAS(const Cfg *Func) const {
2515   // This is Binop variant is only intended to be used for reg-reg moves where
2516   // part of the Dest register is untouched.
2517   assert(this->getSrcSize() == 2);
2518   const Variable *Dest = this->getDest();
2519   assert(Dest == this->getSrc(0));
2520   const auto SrcVar = llvm::cast<Variable>(this->getSrc(1));
2521   assert(Dest->hasReg() && SrcVar->hasReg());
2522   typename InstX86Base<Machine>::Traits::Assembler *Asm =
2523       Func->getAssembler<typename InstX86Base<Machine>::Traits::Assembler>();
2524   Asm->movss(IceType_f32,
2525              InstX86Base<Machine>::Traits::RegisterSet::getEncodedXmm(
2526                  Dest->getRegNum()),
2527              InstX86Base<Machine>::Traits::RegisterSet::getEncodedXmm(
2528                  SrcVar->getRegNum()));
2529 }
2530
2531 template <class Machine>
2532 void InstX86Movsx<Machine>::emitIAS(const Cfg *Func) const {
2533   assert(this->getSrcSize() == 1);
2534   const Variable *Dest = this->getDest();
2535   const Operand *Src = this->getSrc(0);
2536   // Dest must be a > 8-bit register, but Src can be 8-bit. In practice we just
2537   // use the full register for Dest to avoid having an OperandSizeOverride
2538   // prefix. It also allows us to only dispatch on SrcTy.
2539   Type SrcTy = Src->getType();
2540   assert(typeWidthInBytes(Dest->getType()) > 1);
2541   assert(typeWidthInBytes(Dest->getType()) > typeWidthInBytes(SrcTy));
2542   emitIASRegOpTyGPR<Machine, false, true>(Func, SrcTy, Dest, Src,
2543                                           this->Emitter);
2544 }
2545
2546 template <class Machine>
2547 void InstX86Movzx<Machine>::emitIAS(const Cfg *Func) const {
2548   assert(this->getSrcSize() == 1);
2549   const Variable *Dest = this->getDest();
2550   const Operand *Src = this->getSrc(0);
2551   Type SrcTy = Src->getType();
2552   assert(typeWidthInBytes(Dest->getType()) > 1);
2553   assert(typeWidthInBytes(Dest->getType()) > typeWidthInBytes(SrcTy));
2554   emitIASRegOpTyGPR<Machine, false, true>(Func, SrcTy, Dest, Src,
2555                                           this->Emitter);
2556 }
2557
2558 template <class Machine> void InstX86Nop<Machine>::emit(const Cfg *Func) const {
2559   if (!BuildDefs::dump())
2560     return;
2561   Ostream &Str = Func->getContext()->getStrEmit();
2562   // TODO: Emit the right code for each variant.
2563   Str << "\tnop\t# variant = " << Variant;
2564 }
2565
2566 template <class Machine>
2567 void InstX86Nop<Machine>::emitIAS(const Cfg *Func) const {
2568   typename InstX86Base<Machine>::Traits::Assembler *Asm =
2569       Func->getAssembler<typename InstX86Base<Machine>::Traits::Assembler>();
2570   // TODO: Emit the right code for the variant.
2571   Asm->nop();
2572 }
2573
2574 template <class Machine> void InstX86Nop<Machine>::dump(const Cfg *Func) const {
2575   if (!BuildDefs::dump())
2576     return;
2577   Ostream &Str = Func->getContext()->getStrDump();
2578   Str << "nop (variant = " << Variant << ")";
2579 }
2580
2581 template <class Machine> void InstX86Fld<Machine>::emit(const Cfg *Func) const {
2582   if (!BuildDefs::dump())
2583     return;
2584   Ostream &Str = Func->getContext()->getStrEmit();
2585   assert(this->getSrcSize() == 1);
2586   Type Ty = this->getSrc(0)->getType();
2587   SizeT Width = typeWidthInBytes(Ty);
2588   const auto Var = llvm::dyn_cast<Variable>(this->getSrc(0));
2589   if (Var && Var->hasReg()) {
2590     // This is a physical xmm register, so we need to spill it to a temporary
2591     // stack slot.
2592     Str << "\tsubl\t$" << Width << ", %esp"
2593         << "\n";
2594     Str << "\tmov"
2595         << InstX86Base<Machine>::Traits::TypeAttributes[Ty].SdSsString << "\t";
2596     Var->emit(Func);
2597     Str << ", (%esp)\n";
2598     Str << "\tfld" << this->getFldString(Ty) << "\t"
2599         << "(%esp)\n";
2600     Str << "\taddl\t$" << Width << ", %esp";
2601     return;
2602   }
2603   Str << "\tfld" << this->getFldString(Ty) << "\t";
2604   this->getSrc(0)->emit(Func);
2605 }
2606
2607 template <class Machine>
2608 void InstX86Fld<Machine>::emitIAS(const Cfg *Func) const {
2609   typename InstX86Base<Machine>::Traits::Assembler *Asm =
2610       Func->getAssembler<typename InstX86Base<Machine>::Traits::Assembler>();
2611   assert(this->getSrcSize() == 1);
2612   const Operand *Src = this->getSrc(0);
2613   Type Ty = Src->getType();
2614   if (const auto Var = llvm::dyn_cast<Variable>(Src)) {
2615     if (Var->hasReg()) {
2616       // This is a physical xmm register, so we need to spill it to a temporary
2617       // stack slot.
2618       Immediate Width(typeWidthInBytes(Ty));
2619       Asm->sub(IceType_i32,
2620                InstX86Base<Machine>::Traits::RegisterSet::Encoded_Reg_esp,
2621                Width);
2622       typename InstX86Base<Machine>::Traits::Address StackSlot =
2623           typename InstX86Base<Machine>::Traits::Address(
2624               InstX86Base<Machine>::Traits::RegisterSet::Encoded_Reg_esp, 0);
2625       Asm->movss(Ty, StackSlot,
2626                  InstX86Base<Machine>::Traits::RegisterSet::getEncodedXmm(
2627                      Var->getRegNum()));
2628       Asm->fld(Ty, StackSlot);
2629       Asm->add(IceType_i32,
2630                InstX86Base<Machine>::Traits::RegisterSet::Encoded_Reg_esp,
2631                Width);
2632     } else {
2633       typename InstX86Base<Machine>::Traits::Address StackAddr(
2634           static_cast<typename InstX86Base<Machine>::Traits::TargetLowering *>(
2635               Func->getTarget())
2636               ->stackVarToAsmOperand(Var));
2637       Asm->fld(Ty, StackAddr);
2638     }
2639   } else if (const auto Mem = llvm::dyn_cast<
2640                  typename InstX86Base<Machine>::Traits::X86OperandMem>(Src)) {
2641     assert(Mem->getSegmentRegister() ==
2642            InstX86Base<Machine>::Traits::X86OperandMem::DefaultSegment);
2643     Asm->fld(Ty, Mem->toAsmAddress(Asm));
2644   } else if (const auto Imm = llvm::dyn_cast<Constant>(Src)) {
2645     Asm->fld(Ty, InstX86Base<Machine>::Traits::Address::ofConstPool(Asm, Imm));
2646   } else {
2647     llvm_unreachable("Unexpected operand type");
2648   }
2649 }
2650
2651 template <class Machine> void InstX86Fld<Machine>::dump(const Cfg *Func) const {
2652   if (!BuildDefs::dump())
2653     return;
2654   Ostream &Str = Func->getContext()->getStrDump();
2655   Str << "fld." << this->getSrc(0)->getType() << " ";
2656   this->dumpSources(Func);
2657 }
2658
2659 template <class Machine>
2660 void InstX86Fstp<Machine>::emit(const Cfg *Func) const {
2661   if (!BuildDefs::dump())
2662     return;
2663   Ostream &Str = Func->getContext()->getStrEmit();
2664   assert(this->getSrcSize() == 0);
2665   // TODO(jvoung,stichnot): Utilize this by setting Dest to nullptr to
2666   // "partially" delete the fstp if the Dest is unused. Even if Dest is unused,
2667   // the fstp should be kept for the SideEffects of popping the stack.
2668   if (!this->getDest()) {
2669     Str << "\tfstp\tst(0)";
2670     return;
2671   }
2672   Type Ty = this->getDest()->getType();
2673   size_t Width = typeWidthInBytes(Ty);
2674   if (!this->getDest()->hasReg()) {
2675     Str << "\tfstp" << this->getFldString(Ty) << "\t";
2676     this->getDest()->emit(Func);
2677     return;
2678   }
2679   // Dest is a physical (xmm) register, so st(0) needs to go through memory.
2680   // Hack this by creating a temporary stack slot, spilling st(0) there,
2681   // loading it into the xmm register, and deallocating the stack slot.
2682   Str << "\tsubl\t$" << Width << ", %esp\n";
2683   Str << "\tfstp" << this->getFldString(Ty) << "\t"
2684       << "(%esp)\n";
2685   Str << "\tmov" << InstX86Base<Machine>::Traits::TypeAttributes[Ty].SdSsString
2686       << "\t"
2687       << "(%esp), ";
2688   this->getDest()->emit(Func);
2689   Str << "\n";
2690   Str << "\taddl\t$" << Width << ", %esp";
2691 }
2692
2693 template <class Machine>
2694 void InstX86Fstp<Machine>::emitIAS(const Cfg *Func) const {
2695   typename InstX86Base<Machine>::Traits::Assembler *Asm =
2696       Func->getAssembler<typename InstX86Base<Machine>::Traits::Assembler>();
2697   assert(this->getSrcSize() == 0);
2698   const Variable *Dest = this->getDest();
2699   // TODO(jvoung,stichnot): Utilize this by setting Dest to nullptr to
2700   // "partially" delete the fstp if the Dest is unused. Even if Dest is unused,
2701   // the fstp should be kept for the SideEffects of popping the stack.
2702   if (!Dest) {
2703     Asm->fstp(InstX86Base<Machine>::Traits::RegisterSet::getEncodedSTReg(0));
2704     return;
2705   }
2706   Type Ty = Dest->getType();
2707   if (!Dest->hasReg()) {
2708     typename InstX86Base<Machine>::Traits::Address StackAddr(
2709         static_cast<typename InstX86Base<Machine>::Traits::TargetLowering *>(
2710             Func->getTarget())
2711             ->stackVarToAsmOperand(Dest));
2712     Asm->fstp(Ty, StackAddr);
2713   } else {
2714     // Dest is a physical (xmm) register, so st(0) needs to go through memory.
2715     // Hack this by creating a temporary stack slot, spilling st(0) there,
2716     // loading it into the xmm register, and deallocating the stack slot.
2717     Immediate Width(typeWidthInBytes(Ty));
2718     Asm->sub(IceType_i32,
2719              InstX86Base<Machine>::Traits::RegisterSet::Encoded_Reg_esp, Width);
2720     typename InstX86Base<Machine>::Traits::Address StackSlot =
2721         typename InstX86Base<Machine>::Traits::Address(
2722             InstX86Base<Machine>::Traits::RegisterSet::Encoded_Reg_esp, 0);
2723     Asm->fstp(Ty, StackSlot);
2724     Asm->movss(Ty, InstX86Base<Machine>::Traits::RegisterSet::getEncodedXmm(
2725                        Dest->getRegNum()),
2726                StackSlot);
2727     Asm->add(IceType_i32,
2728              InstX86Base<Machine>::Traits::RegisterSet::Encoded_Reg_esp, Width);
2729   }
2730 }
2731
2732 template <class Machine>
2733 void InstX86Fstp<Machine>::dump(const Cfg *Func) const {
2734   if (!BuildDefs::dump())
2735     return;
2736   Ostream &Str = Func->getContext()->getStrDump();
2737   this->dumpDest(Func);
2738   Str << " = fstp." << this->getDest()->getType() << ", st(0)";
2739 }
2740
2741 template <class Machine>
2742 void InstX86Pcmpeq<Machine>::emit(const Cfg *Func) const {
2743   if (!BuildDefs::dump())
2744     return;
2745   char buf[30];
2746   snprintf(
2747       buf, llvm::array_lengthof(buf), "pcmpeq%s",
2748       InstX86Base<Machine>::Traits::TypeAttributes[this->getDest()->getType()]
2749           .PackString);
2750   this->emitTwoAddress(buf, this, Func);
2751 }
2752
2753 template <class Machine>
2754 void InstX86Pcmpgt<Machine>::emit(const Cfg *Func) const {
2755   if (!BuildDefs::dump())
2756     return;
2757   char buf[30];
2758   snprintf(
2759       buf, llvm::array_lengthof(buf), "pcmpgt%s",
2760       InstX86Base<Machine>::Traits::TypeAttributes[this->getDest()->getType()]
2761           .PackString);
2762   this->emitTwoAddress(buf, this, Func);
2763 }
2764
2765 template <class Machine>
2766 void InstX86Pextr<Machine>::emit(const Cfg *Func) const {
2767   if (!BuildDefs::dump())
2768     return;
2769   Ostream &Str = Func->getContext()->getStrEmit();
2770   assert(this->getSrcSize() == 2);
2771   // pextrb and pextrd are SSE4.1 instructions.
2772   assert(this->getSrc(0)->getType() == IceType_v8i16 ||
2773          this->getSrc(0)->getType() == IceType_v8i1 ||
2774          static_cast<typename InstX86Base<Machine>::Traits::TargetLowering *>(
2775              Func->getTarget())
2776                  ->getInstructionSet() >= InstX86Base<Machine>::Traits::SSE4_1);
2777   Str << "\t" << this->Opcode
2778       << InstX86Base<Machine>::Traits::TypeAttributes[this->getSrc(0)
2779                                                           ->getType()]
2780              .PackString << "\t";
2781   this->getSrc(1)->emit(Func);
2782   Str << ", ";
2783   this->getSrc(0)->emit(Func);
2784   Str << ", ";
2785   Variable *Dest = this->getDest();
2786   // pextrw must take a register dest. There is an SSE4.1 version that takes a
2787   // memory dest, but we aren't using it. For uniformity, just restrict them
2788   // all to have a register dest for now.
2789   assert(Dest->hasReg());
2790   Dest->asType(IceType_i32)->emit(Func);
2791 }
2792
2793 template <class Machine>
2794 void InstX86Pextr<Machine>::emitIAS(const Cfg *Func) const {
2795   assert(this->getSrcSize() == 2);
2796   // pextrb and pextrd are SSE4.1 instructions.
2797   const Variable *Dest = this->getDest();
2798   Type DispatchTy = Dest->getType();
2799   assert(DispatchTy == IceType_i16 ||
2800          static_cast<typename InstX86Base<Machine>::Traits::TargetLowering *>(
2801              Func->getTarget())
2802                  ->getInstructionSet() >= InstX86Base<Machine>::Traits::SSE4_1);
2803   // pextrw must take a register dest. There is an SSE4.1 version that takes a
2804   // memory dest, but we aren't using it. For uniformity, just restrict them
2805   // all to have a register dest for now.
2806   assert(Dest->hasReg());
2807   // pextrw's Src(0) must be a register (both SSE4.1 and SSE2).
2808   assert(llvm::cast<Variable>(this->getSrc(0))->hasReg());
2809   static const typename InstX86Base<Machine>::Traits::Assembler::
2810       template ThreeOpImmEmitter<
2811           typename InstX86Base<Machine>::Traits::RegisterSet::GPRRegister,
2812           typename InstX86Base<Machine>::Traits::RegisterSet::XmmRegister>
2813           Emitter = {&InstX86Base<Machine>::Traits::Assembler::pextr, nullptr};
2814   emitIASThreeOpImmOps<
2815       Machine, typename InstX86Base<Machine>::Traits::RegisterSet::GPRRegister,
2816       typename InstX86Base<Machine>::Traits::RegisterSet::XmmRegister,
2817       InstX86Base<Machine>::Traits::RegisterSet::getEncodedGPR,
2818       InstX86Base<Machine>::Traits::RegisterSet::getEncodedXmm>(
2819       Func, DispatchTy, Dest, this->getSrc(0), this->getSrc(1), Emitter);
2820 }
2821
2822 template <class Machine>
2823 void InstX86Pinsr<Machine>::emit(const Cfg *Func) const {
2824   if (!BuildDefs::dump())
2825     return;
2826   Ostream &Str = Func->getContext()->getStrEmit();
2827   assert(this->getSrcSize() == 3);
2828   // pinsrb and pinsrd are SSE4.1 instructions.
2829   assert(this->getDest()->getType() == IceType_v8i16 ||
2830          this->getDest()->getType() == IceType_v8i1 ||
2831          static_cast<typename InstX86Base<Machine>::Traits::TargetLowering *>(
2832              Func->getTarget())
2833                  ->getInstructionSet() >= InstX86Base<Machine>::Traits::SSE4_1);
2834   Str << "\t" << this->Opcode
2835       << InstX86Base<
2836              Machine>::Traits::TypeAttributes[this->getDest()->getType()]
2837              .PackString << "\t";
2838   this->getSrc(2)->emit(Func);
2839   Str << ", ";
2840   Operand *Src1 = this->getSrc(1);
2841   if (const auto Src1Var = llvm::dyn_cast<Variable>(Src1)) {
2842     // If src1 is a register, it should always be r32.
2843     if (Src1Var->hasReg()) {
2844       Src1Var->asType(IceType_i32)->emit(Func);
2845     } else {
2846       Src1Var->emit(Func);
2847     }
2848   } else {
2849     Src1->emit(Func);
2850   }
2851   Str << ", ";
2852   this->getDest()->emit(Func);
2853 }
2854
2855 template <class Machine>
2856 void InstX86Pinsr<Machine>::emitIAS(const Cfg *Func) const {
2857   assert(this->getSrcSize() == 3);
2858   assert(this->getDest() == this->getSrc(0));
2859   // pinsrb and pinsrd are SSE4.1 instructions.
2860   const Operand *Src0 = this->getSrc(1);
2861   Type DispatchTy = Src0->getType();
2862   assert(DispatchTy == IceType_i16 ||
2863          static_cast<typename InstX86Base<Machine>::Traits::TargetLowering *>(
2864              Func->getTarget())
2865                  ->getInstructionSet() >= InstX86Base<Machine>::Traits::SSE4_1);
2866   // If src1 is a register, it should always be r32 (this should fall out from
2867   // the encodings for ByteRegs overlapping the encodings for r32), but we have
2868   // to trust the regalloc to not choose "ah", where it doesn't overlap.
2869   static const typename InstX86Base<Machine>::Traits::Assembler::
2870       template ThreeOpImmEmitter<
2871           typename InstX86Base<Machine>::Traits::RegisterSet::XmmRegister,
2872           typename InstX86Base<Machine>::Traits::RegisterSet::GPRRegister>
2873           Emitter = {&InstX86Base<Machine>::Traits::Assembler::pinsr,
2874                      &InstX86Base<Machine>::Traits::Assembler::pinsr};
2875   emitIASThreeOpImmOps<
2876       Machine, typename InstX86Base<Machine>::Traits::RegisterSet::XmmRegister,
2877       typename InstX86Base<Machine>::Traits::RegisterSet::GPRRegister,
2878       InstX86Base<Machine>::Traits::RegisterSet::getEncodedXmm,
2879       InstX86Base<Machine>::Traits::RegisterSet::getEncodedGPR>(
2880       Func, DispatchTy, this->getDest(), Src0, this->getSrc(2), Emitter);
2881 }
2882
2883 template <class Machine>
2884 void InstX86Pshufd<Machine>::emitIAS(const Cfg *Func) const {
2885   assert(this->getSrcSize() == 2);
2886   const Variable *Dest = this->getDest();
2887   Type Ty = Dest->getType();
2888   static const typename InstX86Base<Machine>::Traits::Assembler::
2889       template ThreeOpImmEmitter<
2890           typename InstX86Base<Machine>::Traits::RegisterSet::XmmRegister,
2891           typename InstX86Base<Machine>::Traits::RegisterSet::XmmRegister>
2892           Emitter = {&InstX86Base<Machine>::Traits::Assembler::pshufd,
2893                      &InstX86Base<Machine>::Traits::Assembler::pshufd};
2894   emitIASThreeOpImmOps<
2895       Machine, typename InstX86Base<Machine>::Traits::RegisterSet::XmmRegister,
2896       typename InstX86Base<Machine>::Traits::RegisterSet::XmmRegister,
2897       InstX86Base<Machine>::Traits::RegisterSet::getEncodedXmm,
2898       InstX86Base<Machine>::Traits::RegisterSet::getEncodedXmm>(
2899       Func, Ty, Dest, this->getSrc(0), this->getSrc(1), Emitter);
2900 }
2901
2902 template <class Machine>
2903 void InstX86Shufps<Machine>::emitIAS(const Cfg *Func) const {
2904   assert(this->getSrcSize() == 3);
2905   const Variable *Dest = this->getDest();
2906   assert(Dest == this->getSrc(0));
2907   Type Ty = Dest->getType();
2908   static const typename InstX86Base<Machine>::Traits::Assembler::
2909       template ThreeOpImmEmitter<
2910           typename InstX86Base<Machine>::Traits::RegisterSet::XmmRegister,
2911           typename InstX86Base<Machine>::Traits::RegisterSet::XmmRegister>
2912           Emitter = {&InstX86Base<Machine>::Traits::Assembler::shufps,
2913                      &InstX86Base<Machine>::Traits::Assembler::shufps};
2914   emitIASThreeOpImmOps<
2915       Machine, typename InstX86Base<Machine>::Traits::RegisterSet::XmmRegister,
2916       typename InstX86Base<Machine>::Traits::RegisterSet::XmmRegister,
2917       InstX86Base<Machine>::Traits::RegisterSet::getEncodedXmm,
2918       InstX86Base<Machine>::Traits::RegisterSet::getEncodedXmm>(
2919       Func, Ty, Dest, this->getSrc(1), this->getSrc(2), Emitter);
2920 }
2921
2922 template <class Machine> void InstX86Pop<Machine>::emit(const Cfg *Func) const {
2923   if (!BuildDefs::dump())
2924     return;
2925   Ostream &Str = Func->getContext()->getStrEmit();
2926   assert(this->getSrcSize() == 0);
2927   Str << "\tpop\t";
2928   this->getDest()->emit(Func);
2929 }
2930
2931 template <class Machine>
2932 void InstX86Pop<Machine>::emitIAS(const Cfg *Func) const {
2933   assert(this->getSrcSize() == 0);
2934   typename InstX86Base<Machine>::Traits::Assembler *Asm =
2935       Func->getAssembler<typename InstX86Base<Machine>::Traits::Assembler>();
2936   if (this->getDest()->hasReg()) {
2937     Asm->popl(InstX86Base<Machine>::Traits::RegisterSet::getEncodedGPR(
2938         this->getDest()->getRegNum()));
2939   } else {
2940     Asm->popl(
2941         static_cast<typename InstX86Base<Machine>::Traits::TargetLowering *>(
2942             Func->getTarget())
2943             ->stackVarToAsmOperand(this->getDest()));
2944   }
2945 }
2946
2947 template <class Machine> void InstX86Pop<Machine>::dump(const Cfg *Func) const {
2948   if (!BuildDefs::dump())
2949     return;
2950   Ostream &Str = Func->getContext()->getStrDump();
2951   this->dumpDest(Func);
2952   Str << " = pop." << this->getDest()->getType() << " ";
2953 }
2954
2955 template <class Machine>
2956 void InstX86AdjustStack<Machine>::emit(const Cfg *Func) const {
2957   if (!BuildDefs::dump())
2958     return;
2959   Ostream &Str = Func->getContext()->getStrEmit();
2960   Str << "\tsubl\t$" << Amount << ", %esp";
2961   Func->getTarget()->updateStackAdjustment(Amount);
2962 }
2963
2964 template <class Machine>
2965 void InstX86AdjustStack<Machine>::emitIAS(const Cfg *Func) const {
2966   typename InstX86Base<Machine>::Traits::Assembler *Asm =
2967       Func->getAssembler<typename InstX86Base<Machine>::Traits::Assembler>();
2968   Asm->sub(IceType_i32,
2969            InstX86Base<Machine>::Traits::RegisterSet::Encoded_Reg_esp,
2970            Immediate(Amount));
2971   Func->getTarget()->updateStackAdjustment(Amount);
2972 }
2973
2974 template <class Machine>
2975 void InstX86AdjustStack<Machine>::dump(const Cfg *Func) const {
2976   if (!BuildDefs::dump())
2977     return;
2978   Ostream &Str = Func->getContext()->getStrDump();
2979   Str << "esp = sub.i32 esp, " << Amount;
2980 }
2981
2982 template <class Machine>
2983 void InstX86Push<Machine>::emit(const Cfg *Func) const {
2984   if (!BuildDefs::dump())
2985     return;
2986   Ostream &Str = Func->getContext()->getStrEmit();
2987   assert(this->getSrcSize() == 1);
2988   // Push is currently only used for saving GPRs.
2989   const auto Var = llvm::cast<Variable>(this->getSrc(0));
2990   assert(Var->hasReg());
2991   Str << "\tpush\t";
2992   Var->emit(Func);
2993 }
2994
2995 template <class Machine>
2996 void InstX86Push<Machine>::emitIAS(const Cfg *Func) const {
2997   assert(this->getSrcSize() == 1);
2998   // Push is currently only used for saving GPRs.
2999   const auto Var = llvm::cast<Variable>(this->getSrc(0));
3000   assert(Var->hasReg());
3001   typename InstX86Base<Machine>::Traits::Assembler *Asm =
3002       Func->getAssembler<typename InstX86Base<Machine>::Traits::Assembler>();
3003   Asm->pushl(InstX86Base<Machine>::Traits::RegisterSet::getEncodedGPR(
3004       Var->getRegNum()));
3005 }
3006
3007 template <class Machine>
3008 void InstX86Push<Machine>::dump(const Cfg *Func) const {
3009   if (!BuildDefs::dump())
3010     return;
3011   Ostream &Str = Func->getContext()->getStrDump();
3012   Str << "push." << this->getSrc(0)->getType() << " ";
3013   this->dumpSources(Func);
3014 }
3015
3016 template <class Machine>
3017 void InstX86Psll<Machine>::emit(const Cfg *Func) const {
3018   if (!BuildDefs::dump())
3019     return;
3020   assert(this->getDest()->getType() == IceType_v8i16 ||
3021          this->getDest()->getType() == IceType_v8i1 ||
3022          this->getDest()->getType() == IceType_v4i32 ||
3023          this->getDest()->getType() == IceType_v4i1);
3024   char buf[30];
3025   snprintf(
3026       buf, llvm::array_lengthof(buf), "psll%s",
3027       InstX86Base<Machine>::Traits::TypeAttributes[this->getDest()->getType()]
3028           .PackString);
3029   this->emitTwoAddress(buf, this, Func);
3030 }
3031
3032 template <class Machine>
3033 void InstX86Psra<Machine>::emit(const Cfg *Func) const {
3034   if (!BuildDefs::dump())
3035     return;
3036   assert(this->getDest()->getType() == IceType_v8i16 ||
3037          this->getDest()->getType() == IceType_v8i1 ||
3038          this->getDest()->getType() == IceType_v4i32 ||
3039          this->getDest()->getType() == IceType_v4i1);
3040   char buf[30];
3041   snprintf(
3042       buf, llvm::array_lengthof(buf), "psra%s",
3043       InstX86Base<Machine>::Traits::TypeAttributes[this->getDest()->getType()]
3044           .PackString);
3045   this->emitTwoAddress(buf, this, Func);
3046 }
3047
3048 template <class Machine>
3049 void InstX86Psrl<Machine>::emit(const Cfg *Func) const {
3050   if (!BuildDefs::dump())
3051     return;
3052   char buf[30];
3053   snprintf(
3054       buf, llvm::array_lengthof(buf), "psrl%s",
3055       InstX86Base<Machine>::Traits::TypeAttributes[this->getDest()->getType()]
3056           .PackString);
3057   this->emitTwoAddress(buf, this, Func);
3058 }
3059
3060 template <class Machine> void InstX86Ret<Machine>::emit(const Cfg *Func) const {
3061   if (!BuildDefs::dump())
3062     return;
3063   Ostream &Str = Func->getContext()->getStrEmit();
3064   Str << "\tret";
3065 }
3066
3067 template <class Machine>
3068 void InstX86Ret<Machine>::emitIAS(const Cfg *Func) const {
3069   typename InstX86Base<Machine>::Traits::Assembler *Asm =
3070       Func->getAssembler<typename InstX86Base<Machine>::Traits::Assembler>();
3071   Asm->ret();
3072 }
3073
3074 template <class Machine> void InstX86Ret<Machine>::dump(const Cfg *Func) const {
3075   if (!BuildDefs::dump())
3076     return;
3077   Ostream &Str = Func->getContext()->getStrDump();
3078   Type Ty =
3079       (this->getSrcSize() == 0 ? IceType_void : this->getSrc(0)->getType());
3080   Str << "ret." << Ty << " ";
3081   this->dumpSources(Func);
3082 }
3083
3084 template <class Machine>
3085 void InstX86Setcc<Machine>::emit(const Cfg *Func) const {
3086   if (!BuildDefs::dump())
3087     return;
3088   Ostream &Str = Func->getContext()->getStrEmit();
3089   Str << "\tset"
3090       << InstX86Base<Machine>::Traits::InstBrAttributes[Condition].DisplayString
3091       << "\t";
3092   this->Dest->emit(Func);
3093 }
3094
3095 template <class Machine>
3096 void InstX86Setcc<Machine>::emitIAS(const Cfg *Func) const {
3097   assert(Condition != InstX86Base<Machine>::Traits::Cond::Br_None);
3098   assert(this->getDest()->getType() == IceType_i1);
3099   assert(this->getSrcSize() == 0);
3100   typename InstX86Base<Machine>::Traits::Assembler *Asm =
3101       Func->getAssembler<typename InstX86Base<Machine>::Traits::Assembler>();
3102   if (this->getDest()->hasReg())
3103     Asm->setcc(Condition,
3104                InstX86Base<Machine>::Traits::RegisterSet::getEncodedByteReg(
3105                    this->getDest()->getRegNum()));
3106   else
3107     Asm->setcc(
3108         Condition,
3109         static_cast<typename InstX86Base<Machine>::Traits::TargetLowering *>(
3110             Func->getTarget())
3111             ->stackVarToAsmOperand(this->getDest()));
3112   return;
3113 }
3114
3115 template <class Machine>
3116 void InstX86Setcc<Machine>::dump(const Cfg *Func) const {
3117   if (!BuildDefs::dump())
3118     return;
3119   Ostream &Str = Func->getContext()->getStrDump();
3120   Str << "setcc."
3121       << InstX86Base<Machine>::Traits::InstBrAttributes[Condition].DisplayString
3122       << " ";
3123   this->dumpDest(Func);
3124 }
3125
3126 template <class Machine>
3127 void InstX86Xadd<Machine>::emit(const Cfg *Func) const {
3128   if (!BuildDefs::dump())
3129     return;
3130   Ostream &Str = Func->getContext()->getStrEmit();
3131   if (this->Locked) {
3132     Str << "\tlock";
3133   }
3134   Str << "\txadd" << this->getWidthString(this->getSrc(0)->getType()) << "\t";
3135   this->getSrc(1)->emit(Func);
3136   Str << ", ";
3137   this->getSrc(0)->emit(Func);
3138 }
3139
3140 template <class Machine>
3141 void InstX86Xadd<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();
3146   const auto Mem =
3147       llvm::cast<typename InstX86Base<Machine>::Traits::X86OperandMem>(
3148           this->getSrc(0));
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->xadd(Ty, Addr, Reg, this->Locked);
3159 }
3160
3161 template <class Machine>
3162 void InstX86Xadd<Machine>::dump(const Cfg *Func) const {
3163   if (!BuildDefs::dump())
3164     return;
3165   Ostream &Str = Func->getContext()->getStrDump();
3166   if (this->Locked) {
3167     Str << "lock ";
3168   }
3169   Type Ty = this->getSrc(0)->getType();
3170   Str << "xadd." << Ty << " ";
3171   this->dumpSources(Func);
3172 }
3173
3174 template <class Machine>
3175 void InstX86Xchg<Machine>::emit(const Cfg *Func) const {
3176   if (!BuildDefs::dump())
3177     return;
3178   Ostream &Str = Func->getContext()->getStrEmit();
3179   Str << "\txchg" << this->getWidthString(this->getSrc(0)->getType()) << "\t";
3180   this->getSrc(1)->emit(Func);
3181   Str << ", ";
3182   this->getSrc(0)->emit(Func);
3183 }
3184
3185 template <class Machine>
3186 void InstX86Xchg<Machine>::emitIAS(const Cfg *Func) const {
3187   assert(this->getSrcSize() == 2);
3188   typename InstX86Base<Machine>::Traits::Assembler *Asm =
3189       Func->getAssembler<typename InstX86Base<Machine>::Traits::Assembler>();
3190   Type Ty = this->getSrc(0)->getType();
3191   const auto *VarReg1 = llvm::cast<Variable>(this->getSrc(1));
3192   assert(VarReg1->hasReg());
3193   const typename InstX86Base<Machine>::Traits::RegisterSet::GPRRegister Reg1 =
3194       InstX86Base<Machine>::Traits::RegisterSet::getEncodedGPR(
3195           VarReg1->getRegNum());
3196
3197   if (const auto *VarReg0 = llvm::dyn_cast<Variable>(this->getSrc(0))) {
3198     assert(VarReg0->hasReg());
3199     const typename InstX86Base<Machine>::Traits::RegisterSet::GPRRegister Reg0 =
3200         InstX86Base<Machine>::Traits::RegisterSet::getEncodedGPR(
3201             VarReg0->getRegNum());
3202     Asm->xchg(Ty, Reg0, Reg1);
3203     return;
3204   }
3205
3206   const auto *Mem =
3207       llvm::cast<typename InstX86Base<Machine>::Traits::X86OperandMem>(
3208           this->getSrc(0));
3209   assert(Mem->getSegmentRegister() ==
3210          InstX86Base<Machine>::Traits::X86OperandMem::DefaultSegment);
3211   const typename InstX86Base<Machine>::Traits::Address Addr =
3212       Mem->toAsmAddress(Asm);
3213   Asm->xchg(Ty, Addr, Reg1);
3214 }
3215
3216 template <class Machine>
3217 void InstX86Xchg<Machine>::dump(const Cfg *Func) const {
3218   if (!BuildDefs::dump())
3219     return;
3220   Ostream &Str = Func->getContext()->getStrDump();
3221   Type Ty = this->getSrc(0)->getType();
3222   Str << "xchg." << Ty << " ";
3223   this->dumpSources(Func);
3224 }
3225
3226 template <class Machine>
3227 void InstX86IacaStart<Machine>::emit(const Cfg *Func) const {
3228   if (!BuildDefs::dump())
3229     return;
3230   Ostream &Str = Func->getContext()->getStrEmit();
3231   Str << "\t# IACA_START\n"
3232       << "\t.byte 0x0F, 0x0B\n"
3233       << "\tmovl\t$111, %ebx\n"
3234       << "\t.byte 0x64, 0x67, 0x90";
3235 }
3236
3237 template <class Machine>
3238 void InstX86IacaStart<Machine>::emitIAS(const Cfg *Func) const {
3239   typename InstX86Base<Machine>::Traits::Assembler *Asm =
3240       Func->getAssembler<typename InstX86Base<Machine>::Traits::Assembler>();
3241   Asm->iaca_start();
3242 }
3243
3244 template <class Machine>
3245 void InstX86IacaStart<Machine>::dump(const Cfg *Func) const {
3246   if (!BuildDefs::dump())
3247     return;
3248   Ostream &Str = Func->getContext()->getStrDump();
3249   Str << "IACA_START";
3250 }
3251
3252 template <class Machine>
3253 void InstX86IacaEnd<Machine>::emit(const Cfg *Func) const {
3254   if (!BuildDefs::dump())
3255     return;
3256   Ostream &Str = Func->getContext()->getStrEmit();
3257   Str << "\t# IACA_END\n"
3258       << "\tmovl\t$222, %ebx\n"
3259       << "\t.byte 0x64, 0x67, 0x90\n"
3260       << "\t.byte 0x0F, 0x0B";
3261 }
3262
3263 template <class Machine>
3264 void InstX86IacaEnd<Machine>::emitIAS(const Cfg *Func) const {
3265   typename InstX86Base<Machine>::Traits::Assembler *Asm =
3266       Func->getAssembler<typename InstX86Base<Machine>::Traits::Assembler>();
3267   Asm->iaca_end();
3268 }
3269
3270 template <class Machine>
3271 void InstX86IacaEnd<Machine>::dump(const Cfg *Func) const {
3272   if (!BuildDefs::dump())
3273     return;
3274   Ostream &Str = Func->getContext()->getStrDump();
3275   Str << "IACA_END";
3276 }
3277
3278 } // end of namespace X86Internal
3279
3280 } // end of namespace Ice
3281
3282 #endif // SUBZERO_SRC_ICEINSTX86BASEIMPL_H