• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //===- subzero/src/IceInstX8664.cpp - X86-64 instruction implementation ---===//
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 /// \brief This file defines X8664 specific data related to X8664 Instructions.
12 ///
13 //===----------------------------------------------------------------------===//
14 
15 #include "IceInstX8664.h"
16 
17 #include "IceAssemblerX8664.h"
18 #include "IceCfg.h"
19 #include "IceCfgNode.h"
20 #include "IceConditionCodesX86.h"
21 #include "IceDefs.h"
22 #include "IceInst.h"
23 #include "IceInstX8664.def"
24 #include "IceOperand.h"
25 #include "IceRegistersX8664.h"
26 #include "IceTargetLowering.h"
27 #include "IceTargetLoweringX8664.h"
28 
29 namespace Ice {
30 namespace X8664 {
31 
32 struct InstBrAttributesType {
33   CondX86::BrCond Opposite;
34   const char *const DisplayString;
35   const char *const EmitString;
36 };
37 
38 struct InstCmppsAttributesType {
39   const char *const EmitString;
40 };
41 
42 struct TypeAttributesType {
43   const Type InVectorElementType;
44   const char *const CvtString;      // i (integer), s (single FP), d (double FP)
45   const char *const SdSsString;     // ss, sd, or <blank>
46   const char *const PdPsString;     // ps, pd, or <blank>
47   const char *const SpSdString;     // ss, sd, ps, pd, or <blank>
48   const char *const IntegralString; // b, w, d, or <blank>
49   const char *const UnpackString;   // bw, wd, dq, or <blank>
50   const char *const PackString;     // wb, dw, or <blank>
51   const char *const WidthString;    // b, w, l, q, or <blank>
52   const char *const FldString;      // s, l, or <blank>
53 };
54 
55 constexpr InstBrAttributesType InstBrAttributes[] = {
56 #define X(val, encode, opp, dump, emit) {CondX86::opp, dump, emit},
57     ICEINSTX86BR_TABLE
58 #undef X
59 };
60 
61 constexpr InstCmppsAttributesType InstCmppsAttributes[] = {
62 #define X(val, emit) {emit},
63     ICEINSTX86CMPPS_TABLE
64 #undef X
65 };
66 
67 constexpr TypeAttributesType TypeAttributes[] = {
68 #define X(tag, elty, cvt, sdss, pdps, spsd, int_, unpack, pack, width, fld)    \
69   {IceType_##elty, cvt, sdss, pdps, spsd, int_, unpack, pack, width, fld},
70     ICETYPEX86_TABLE
71 #undef X
72 };
73 
getWidthString(Type Ty)74 const char *InstX86Base::getWidthString(Type Ty) {
75   return TypeAttributes[Ty].WidthString;
76 }
77 
getFldString(Type Ty)78 const char *InstX86Base::getFldString(Type Ty) {
79   return TypeAttributes[Ty].FldString;
80 }
81 
getSseSuffixString(Type DestTy,SseSuffix Suffix)82 const char *InstX86Base::getSseSuffixString(Type DestTy, SseSuffix Suffix) {
83   switch (Suffix) {
84   default:
85   case InstX86Base::SseSuffix::None:
86     return "";
87   case InstX86Base::SseSuffix::Packed:
88     return TypeAttributes[DestTy].PdPsString;
89   case InstX86Base::SseSuffix::Unpack:
90     return TypeAttributes[DestTy].UnpackString;
91   case InstX86Base::SseSuffix::Scalar:
92     return TypeAttributes[DestTy].SdSsString;
93   case InstX86Base::SseSuffix::Integral:
94     return TypeAttributes[DestTy].IntegralString;
95   case InstX86Base::SseSuffix::Pack:
96     return TypeAttributes[DestTy].PackString;
97   }
98 }
99 
100 /// Return the type which the elements of the vector have in the X86
101 /// representation of the vector.
getInVectorElementType(Type Ty)102 Type InstX86Base::getInVectorElementType(Type Ty) {
103   assert(isVectorType(Ty));
104   assert(Ty < std::size(TypeAttributes));
105   return TypeAttributes[Ty].InVectorElementType;
106 }
107 
getOppositeCondition(BrCond Cond)108 Cond::BrCond InstX86Base::getOppositeCondition(BrCond Cond) {
109   return InstBrAttributes[Cond].Opposite;
110 }
111 
InstX86FakeRMW(Cfg * Func,Operand * Data,Operand * Addr,InstArithmetic::OpKind Op,Variable * Beacon)112 InstX86FakeRMW::InstX86FakeRMW(Cfg *Func, Operand *Data, Operand *Addr,
113                                InstArithmetic::OpKind Op, Variable *Beacon)
114     : InstX86Base(Func, InstX86Base::FakeRMW, 3, nullptr), Op(Op) {
115   this->addSource(Data);
116   this->addSource(Addr);
117   this->addSource(Beacon);
118 }
119 
InstX86Mul(Cfg * Func,Variable * Dest,Variable * Source1,Operand * Source2)120 InstX86Mul::InstX86Mul(Cfg *Func, Variable *Dest, Variable *Source1,
121                        Operand *Source2)
122     : InstX86Base(Func, InstX86Base::Mul, 2, Dest) {
123   this->addSource(Source1);
124   this->addSource(Source2);
125 }
126 
InstX86Shld(Cfg * Func,Variable * Dest,Variable * Source1,Operand * Source2)127 InstX86Shld::InstX86Shld(Cfg *Func, Variable *Dest, Variable *Source1,
128                          Operand *Source2)
129     : InstX86Base(Func, InstX86Base::Shld, 3, Dest) {
130   this->addSource(Dest);
131   this->addSource(Source1);
132   this->addSource(Source2);
133 }
134 
InstX86Shrd(Cfg * Func,Variable * Dest,Variable * Source1,Operand * Source2)135 InstX86Shrd::InstX86Shrd(Cfg *Func, Variable *Dest, Variable *Source1,
136                          Operand *Source2)
137     : InstX86Base(Func, InstX86Base::Shrd, 3, Dest) {
138   this->addSource(Dest);
139   this->addSource(Source1);
140   this->addSource(Source2);
141 }
142 
InstX86Label(Cfg * Func,TargetLowering * Target)143 InstX86Label::InstX86Label(Cfg *Func, TargetLowering *Target)
144     : InstX86Base(Func, InstX86Base::Label, 0, nullptr),
145       LabelNumber(Target->makeNextLabelNumber()) {
146   if (BuildDefs::dump()) {
147     Name = GlobalString::createWithString(
148         Func->getContext(), ".L" + Func->getFunctionName() + "$local$__" +
149                                 std::to_string(LabelNumber));
150   } else {
151     Name = GlobalString::createWithoutString(Func->getContext());
152   }
153 }
154 
InstX86Br(Cfg * Func,const CfgNode * TargetTrue,const CfgNode * TargetFalse,const InstX86Label * Label,BrCond Condition,Mode Kind)155 InstX86Br::InstX86Br(Cfg *Func, const CfgNode *TargetTrue,
156                      const CfgNode *TargetFalse, const InstX86Label *Label,
157                      BrCond Condition, Mode Kind)
158     : InstX86Base(Func, InstX86Base::Br, 0, nullptr), Condition(Condition),
159       TargetTrue(TargetTrue), TargetFalse(TargetFalse), Label(Label),
160       Kind(Kind) {}
161 
optimizeBranch(const CfgNode * NextNode)162 bool InstX86Br::optimizeBranch(const CfgNode *NextNode) {
163   // If there is no next block, then there can be no fallthrough to optimize.
164   if (NextNode == nullptr)
165     return false;
166   // Intra-block conditional branches can't be optimized.
167   if (Label)
168     return false;
169   // If there is no fallthrough node, such as a non-default case label for a
170   // switch instruction, then there is no opportunity to optimize.
171   if (getTargetFalse() == nullptr)
172     return false;
173 
174   // Unconditional branch to the next node can be removed.
175   if (Condition == Cond::Br_None && getTargetFalse() == NextNode) {
176     assert(getTargetTrue() == nullptr);
177     this->setDeleted();
178     return true;
179   }
180   // If the fallthrough is to the next node, set fallthrough to nullptr to
181   // indicate.
182   if (getTargetFalse() == NextNode) {
183     TargetFalse = nullptr;
184     return true;
185   }
186   // If TargetTrue is the next node, and TargetFalse is not nullptr (which was
187   // already tested above), then invert the branch condition, swap the targets,
188   // and set new fallthrough to nullptr.
189   if (getTargetTrue() == NextNode) {
190     assert(Condition != Cond::Br_None);
191     Condition = this->getOppositeCondition(Condition);
192     TargetTrue = getTargetFalse();
193     TargetFalse = nullptr;
194     return true;
195   }
196   return false;
197 }
198 
repointEdges(CfgNode * OldNode,CfgNode * NewNode)199 bool InstX86Br::repointEdges(CfgNode *OldNode, CfgNode *NewNode) {
200   bool Found = false;
201   if (TargetFalse == OldNode) {
202     TargetFalse = NewNode;
203     Found = true;
204   }
205   if (TargetTrue == OldNode) {
206     TargetTrue = NewNode;
207     Found = true;
208   }
209   return Found;
210 }
211 
InstX86Jmp(Cfg * Func,Operand * Target)212 InstX86Jmp::InstX86Jmp(Cfg *Func, Operand *Target)
213     : InstX86Base(Func, InstX86Base::Jmp, 1, nullptr) {
214   this->addSource(Target);
215 }
216 
InstX86Call(Cfg * Func,Variable * Dest,Operand * CallTarget)217 InstX86Call::InstX86Call(Cfg *Func, Variable *Dest, Operand *CallTarget)
218     : InstX86Base(Func, InstX86Base::Call, 1, Dest) {
219   this->HasSideEffects = true;
220   this->addSource(CallTarget);
221 }
222 
InstX86Movmsk(Cfg * Func,Variable * Dest,Operand * Source)223 InstX86Movmsk::InstX86Movmsk(Cfg *Func, Variable *Dest, Operand *Source)
224     : InstX86Base(Func, InstX86Base::Movmsk, 1, Dest) {
225   this->addSource(Source);
226 }
227 
InstX86Cmov(Cfg * Func,Variable * Dest,Operand * Source,BrCond Condition)228 InstX86Cmov::InstX86Cmov(Cfg *Func, Variable *Dest, Operand *Source,
229                          BrCond Condition)
230     : InstX86Base(Func, InstX86Base::Cmov, 2, Dest), Condition(Condition) {
231   // The final result is either the original Dest, or Source, so mark both as
232   // sources.
233   this->addSource(Dest);
234   this->addSource(Source);
235 }
236 
InstX86Cmpps(Cfg * Func,Variable * Dest,Operand * Source,CmppsCond Condition)237 InstX86Cmpps::InstX86Cmpps(Cfg *Func, Variable *Dest, Operand *Source,
238                            CmppsCond Condition)
239     : InstX86Base(Func, InstX86Base::Cmpps, 2, Dest), Condition(Condition) {
240   this->addSource(Dest);
241   this->addSource(Source);
242 }
243 
InstX86Cmpxchg(Cfg * Func,Operand * DestOrAddr,Variable * Eax,Variable * Desired,bool Locked)244 InstX86Cmpxchg::InstX86Cmpxchg(Cfg *Func, Operand *DestOrAddr, Variable *Eax,
245                                Variable *Desired, bool Locked)
246     : InstX86BaseLockable(Func, InstX86Base::Cmpxchg, 3,
247                           llvm::dyn_cast<Variable>(DestOrAddr), Locked) {
248   constexpr uint16_t Encoded_rAX = 0;
249   (void)Encoded_rAX;
250   assert(RegX8664::getEncodedGPR(Eax->getRegNum()) == Encoded_rAX);
251   this->addSource(DestOrAddr);
252   this->addSource(Eax);
253   this->addSource(Desired);
254 }
255 
InstX86Cmpxchg8b(Cfg * Func,X86OperandMem * Addr,Variable * Edx,Variable * Eax,Variable * Ecx,Variable * Ebx,bool Locked)256 InstX86Cmpxchg8b::InstX86Cmpxchg8b(Cfg *Func, X86OperandMem *Addr,
257                                    Variable *Edx, Variable *Eax, Variable *Ecx,
258                                    Variable *Ebx, bool Locked)
259     : InstX86BaseLockable(Func, InstX86Base::Cmpxchg, 5, nullptr, Locked) {
260   assert(Edx->getRegNum() == RegisterSet::Reg_edx);
261   assert(Eax->getRegNum() == RegisterSet::Reg_eax);
262   assert(Ecx->getRegNum() == RegisterSet::Reg_ecx);
263   assert(Ebx->getRegNum() == RegisterSet::Reg_ebx);
264   this->addSource(Addr);
265   this->addSource(Edx);
266   this->addSource(Eax);
267   this->addSource(Ecx);
268   this->addSource(Ebx);
269 }
270 
InstX86Cvt(Cfg * Func,Variable * Dest,Operand * Source,CvtVariant Variant)271 InstX86Cvt::InstX86Cvt(Cfg *Func, Variable *Dest, Operand *Source,
272                        CvtVariant Variant)
273     : InstX86Base(Func, InstX86Base::Cvt, 1, Dest), Variant(Variant) {
274   this->addSource(Source);
275 }
276 
InstX86Icmp(Cfg * Func,Operand * Src0,Operand * Src1)277 InstX86Icmp::InstX86Icmp(Cfg *Func, Operand *Src0, Operand *Src1)
278     : InstX86Base(Func, InstX86Base::Icmp, 2, nullptr) {
279   this->addSource(Src0);
280   this->addSource(Src1);
281 }
282 
InstX86Ucomiss(Cfg * Func,Operand * Src0,Operand * Src1)283 InstX86Ucomiss::InstX86Ucomiss(Cfg *Func, Operand *Src0, Operand *Src1)
284     : InstX86Base(Func, InstX86Base::Ucomiss, 2, nullptr) {
285   this->addSource(Src0);
286   this->addSource(Src1);
287 }
288 
InstX86UD2(Cfg * Func)289 InstX86UD2::InstX86UD2(Cfg *Func)
290     : InstX86Base(Func, InstX86Base::UD2, 0, nullptr) {}
291 
InstX86Int3(Cfg * Func)292 InstX86Int3::InstX86Int3(Cfg *Func)
293     : InstX86Base(Func, InstX86Base::Int3, 0, nullptr) {}
294 
InstX86Test(Cfg * Func,Operand * Src1,Operand * Src2)295 InstX86Test::InstX86Test(Cfg *Func, Operand *Src1, Operand *Src2)
296     : InstX86Base(Func, InstX86Base::Test, 2, nullptr) {
297   this->addSource(Src1);
298   this->addSource(Src2);
299 }
300 
InstX86Mfence(Cfg * Func)301 InstX86Mfence::InstX86Mfence(Cfg *Func)
302     : InstX86Base(Func, InstX86Base::Mfence, 0, nullptr) {
303   this->HasSideEffects = true;
304 }
305 
InstX86Store(Cfg * Func,Operand * Value,X86Operand * Mem)306 InstX86Store::InstX86Store(Cfg *Func, Operand *Value, X86Operand *Mem)
307     : InstX86Base(Func, InstX86Base::Store, 2, nullptr) {
308   this->addSource(Value);
309   this->addSource(Mem);
310 }
311 
InstX86StoreP(Cfg * Func,Variable * Value,X86OperandMem * Mem)312 InstX86StoreP::InstX86StoreP(Cfg *Func, Variable *Value, X86OperandMem *Mem)
313     : InstX86Base(Func, InstX86Base::StoreP, 2, nullptr) {
314   this->addSource(Value);
315   this->addSource(Mem);
316 }
317 
InstX86StoreQ(Cfg * Func,Operand * Value,X86OperandMem * Mem)318 InstX86StoreQ::InstX86StoreQ(Cfg *Func, Operand *Value, X86OperandMem *Mem)
319     : InstX86Base(Func, InstX86Base::StoreQ, 2, nullptr) {
320   this->addSource(Value);
321   this->addSource(Mem);
322 }
323 
InstX86StoreD(Cfg * Func,Operand * Value,X86OperandMem * Mem)324 InstX86StoreD::InstX86StoreD(Cfg *Func, Operand *Value, X86OperandMem *Mem)
325     : InstX86Base(Func, InstX86Base::StoreD, 2, nullptr) {
326   this->addSource(Value);
327   this->addSource(Mem);
328 }
329 
InstX86Nop(Cfg * Func,NopVariant Variant)330 InstX86Nop::InstX86Nop(Cfg *Func, NopVariant Variant)
331     : InstX86Base(Func, InstX86Base::Nop, 0, nullptr), Variant(Variant) {}
332 
InstX86Pop(Cfg * Func,Variable * Dest)333 InstX86Pop::InstX86Pop(Cfg *Func, Variable *Dest)
334     : InstX86Base(Func, InstX86Base::Pop, 0, Dest) {
335   // A pop instruction affects the stack pointer and so it should not be
336   // allowed to be automatically dead-code eliminated. (The corresponding push
337   // instruction doesn't need this treatment because it has no dest variable
338   // and therefore won't be dead-code eliminated.) This is needed for
339   // late-stage liveness analysis (e.g. asm-verbose mode).
340   this->HasSideEffects = true;
341 }
342 
InstX86Push(Cfg * Func,Operand * Source)343 InstX86Push::InstX86Push(Cfg *Func, Operand *Source)
344     : InstX86Base(Func, InstX86Base::Push, 1, nullptr) {
345   this->addSource(Source);
346 }
347 
InstX86Ret(Cfg * Func,Variable * Source)348 InstX86Ret::InstX86Ret(Cfg *Func, Variable *Source)
349     : InstX86Base(Func, InstX86Base::Ret, Source ? 1 : 0, nullptr) {
350   if (Source)
351     this->addSource(Source);
352 }
353 
InstX86Setcc(Cfg * Func,Variable * Dest,BrCond Cond)354 InstX86Setcc::InstX86Setcc(Cfg *Func, Variable *Dest, BrCond Cond)
355     : InstX86Base(Func, InstX86Base::Setcc, 0, Dest), Condition(Cond) {}
356 
InstX86Xadd(Cfg * Func,Operand * Dest,Variable * Source,bool Locked)357 InstX86Xadd::InstX86Xadd(Cfg *Func, Operand *Dest, Variable *Source,
358                          bool Locked)
359     : InstX86BaseLockable(Func, InstX86Base::Xadd, 2,
360                           llvm::dyn_cast<Variable>(Dest), Locked) {
361   this->addSource(Dest);
362   this->addSource(Source);
363 }
364 
InstX86Xchg(Cfg * Func,Operand * Dest,Variable * Source)365 InstX86Xchg::InstX86Xchg(Cfg *Func, Operand *Dest, Variable *Source)
366     : InstX86Base(Func, InstX86Base::Xchg, 2, llvm::dyn_cast<Variable>(Dest)) {
367   this->addSource(Dest);
368   this->addSource(Source);
369 }
370 
InstX86IacaStart(Cfg * Func)371 InstX86IacaStart::InstX86IacaStart(Cfg *Func)
372     : InstX86Base(Func, InstX86Base::IacaStart, 0, nullptr) {
373   assert(getFlags().getAllowIacaMarks());
374 }
375 
InstX86IacaEnd(Cfg * Func)376 InstX86IacaEnd::InstX86IacaEnd(Cfg *Func)
377     : InstX86Base(Func, InstX86Base::IacaEnd, 0, nullptr) {
378   assert(getFlags().getAllowIacaMarks());
379 }
380 
381 // ======================== Dump routines ======================== //
382 
dump(const Cfg * Func) const383 void InstX86Base::dump(const Cfg *Func) const {
384   if (!BuildDefs::dump())
385     return;
386   Ostream &Str = Func->getContext()->getStrDump();
387   Str << "[X8664] ";
388   Inst::dump(Func);
389 }
390 
dump(const Cfg * Func) const391 void InstX86FakeRMW::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 
emit(const Cfg * Func) const404 void InstX86Label::emit(const Cfg *Func) const {
405   if (!BuildDefs::dump())
406     return;
407   Ostream &Str = Func->getContext()->getStrEmit();
408   Str << getLabelName() << ":";
409 }
410 
emitIAS(const Cfg * Func) const411 void InstX86Label::emitIAS(const Cfg *Func) const {
412   Assembler *Asm = Func->getAssembler<Assembler>();
413   Asm->bindLocalLabel(LabelNumber);
414   if (OffsetReloc != nullptr) {
415     Asm->bindRelocOffset(OffsetReloc);
416   }
417 }
418 
dump(const Cfg * Func) const419 void InstX86Label::dump(const Cfg *Func) const {
420   if (!BuildDefs::dump())
421     return;
422   Ostream &Str = Func->getContext()->getStrDump();
423   Str << getLabelName() << ":";
424 }
425 
emit(const Cfg * Func) const426 void InstX86Br::emit(const Cfg *Func) const {
427   if (!BuildDefs::dump())
428     return;
429   Ostream &Str = Func->getContext()->getStrEmit();
430   Str << "\t";
431 
432   if (Condition == Cond::Br_None) {
433     Str << "jmp";
434   } else {
435     Str << InstBrAttributes[Condition].EmitString;
436   }
437 
438   if (Label) {
439     Str << "\t" << Label->getLabelName();
440   } else {
441     if (Condition == Cond::Br_None) {
442       Str << "\t" << getTargetFalse()->getAsmName();
443     } else {
444       Str << "\t" << getTargetTrue()->getAsmName();
445       if (getTargetFalse()) {
446         Str << "\n\t"
447                "jmp\t"
448             << getTargetFalse()->getAsmName();
449       }
450     }
451   }
452 }
453 
emitIAS(const Cfg * Func) const454 void InstX86Br::emitIAS(const Cfg *Func) const {
455   Assembler *Asm = Func->getAssembler<Assembler>();
456   if (Label) {
457     auto *L = Asm->getOrCreateLocalLabel(Label->getLabelNumber());
458     if (Condition == Cond::Br_None) {
459       Asm->jmp(L, isNear());
460     } else {
461       Asm->j(Condition, L, isNear());
462     }
463   } else {
464     if (Condition == Cond::Br_None) {
465       auto *L = Asm->getOrCreateCfgNodeLabel(getTargetFalse()->getIndex());
466       assert(!getTargetTrue());
467       Asm->jmp(L, isNear());
468     } else {
469       auto *L = Asm->getOrCreateCfgNodeLabel(getTargetTrue()->getIndex());
470       Asm->j(Condition, L, isNear());
471       if (getTargetFalse()) {
472         auto *L2 = Asm->getOrCreateCfgNodeLabel(getTargetFalse()->getIndex());
473         Asm->jmp(L2, isNear());
474       }
475     }
476   }
477 }
478 
dump(const Cfg * Func) const479 void InstX86Br::dump(const Cfg *Func) const {
480   if (!BuildDefs::dump())
481     return;
482   Ostream &Str = Func->getContext()->getStrDump();
483   Str << "br ";
484 
485   if (Condition == Cond::Br_None) {
486     if (Label) {
487       Str << "label %" << Label->getLabelName();
488     } else {
489       Str << "label %" << getTargetFalse()->getName();
490     }
491     return;
492   }
493 
494   Str << InstBrAttributes[Condition].DisplayString;
495   if (Label) {
496     Str << ", label %" << Label->getLabelName();
497   } else {
498     Str << ", label %" << getTargetTrue()->getName();
499     if (getTargetFalse()) {
500       Str << ", label %" << getTargetFalse()->getName();
501     }
502   }
503 
504   Str << " // (" << (isNear() ? "near" : "far") << " jump)";
505 }
506 
emit(const Cfg * Func) const507 void InstX86Jmp::emit(const Cfg *Func) const {
508   if (!BuildDefs::dump())
509     return;
510   Ostream &Str = Func->getContext()->getStrEmit();
511   assert(this->getSrcSize() == 1);
512   const Operand *Src = this->getSrc(0);
513   if (const auto *CR = llvm::dyn_cast<ConstantRelocatable>(Src)) {
514     Str << "\t"
515            "jmp"
516            "\t"
517         << CR->getName();
518     return;
519   }
520   Str << "\t"
521          "jmp"
522          "\t*";
523   getJmpTarget()->emit(Func);
524 }
525 
emitIAS(const Cfg * Func) const526 void InstX86Jmp::emitIAS(const Cfg *Func) const {
527   // Note: Adapted (mostly copied) from
528   // InstX86Call::emitIAS().
529   Assembler *Asm = Func->getAssembler<Assembler>();
530   Operand *Target = getJmpTarget();
531   if (const auto *Var = llvm::dyn_cast<Variable>(Target)) {
532     if (Var->hasReg()) {
533       Asm->jmp(RegX8664::getEncodedGPR(Var->getRegNum()));
534     } else {
535       // The jmp instruction with a memory operand should be possible to
536       // encode, but it isn't a valid sandboxed instruction, and there
537       // shouldn't be a register allocation issue to jump through a scratch
538       // register, so we don't really need to bother implementing it.
539       llvm::report_fatal_error("Assembler can't jmp to memory operand");
540     }
541   } else if (const auto *Mem = llvm::dyn_cast<X86OperandMem>(Target)) {
542     (void)Mem;
543     assert(Mem->getSegmentRegister() == X86OperandMem::DefaultSegment);
544     llvm::report_fatal_error("Assembler can't jmp to memory operand");
545   } else if (const auto *CR = llvm::dyn_cast<ConstantRelocatable>(Target)) {
546     Asm->jmp(CR);
547   } else if (const auto *Imm = llvm::dyn_cast<ConstantInteger32>(Target)) {
548     // NaCl trampoline calls refer to an address within the sandbox directly.
549     // This is usually only needed for non-IRT builds and otherwise not very
550     // portable or stable. Usually this is only done for "calls" and not jumps.
551     Asm->jmp(AssemblerImmediate(Imm->getValue()));
552   } else {
553     llvm::report_fatal_error("Unexpected operand type");
554   }
555 }
556 
dump(const Cfg * Func) const557 void InstX86Jmp::dump(const Cfg *Func) const {
558   if (!BuildDefs::dump())
559     return;
560   Ostream &Str = Func->getContext()->getStrDump();
561   Str << "jmp ";
562   getJmpTarget()->dump(Func);
563 }
564 
emit(const Cfg * Func) const565 void InstX86Call::emit(const Cfg *Func) const {
566   if (!BuildDefs::dump())
567     return;
568   Ostream &Str = Func->getContext()->getStrEmit();
569   assert(this->getSrcSize() == 1);
570   Str << "\t"
571          "call\t";
572   Operand *CallTarget = getCallTarget();
573   auto *Target = InstX86Base::getTarget(Func);
574   if (const auto *CI = llvm::dyn_cast<ConstantInteger32>(CallTarget)) {
575     // Emit without a leading '$'.
576     Str << CI->getValue();
577   } else if (const auto DirectCallTarget =
578                  llvm::dyn_cast<ConstantRelocatable>(CallTarget)) {
579     DirectCallTarget->emitWithoutPrefix(Target);
580   } else {
581     Str << "*";
582     CallTarget->emit(Func);
583   }
584 }
585 
emitIAS(const Cfg * Func) const586 void InstX86Call::emitIAS(const Cfg *Func) const {
587   Assembler *Asm = Func->getAssembler<Assembler>();
588   Operand *CallTarget = getCallTarget();
589   auto *Target = InstX86Base::getTarget(Func);
590   if (const auto *Var = llvm::dyn_cast<Variable>(CallTarget)) {
591     if (Var->hasReg()) {
592       Asm->call(RegX8664::getEncodedGPR(Var->getRegNum()));
593     } else {
594       Asm->call(AsmAddress(Var, Target));
595     }
596   } else if (const auto *Mem = llvm::dyn_cast<X86OperandMem>(CallTarget)) {
597     assert(Mem->getSegmentRegister() == X86OperandMem::DefaultSegment);
598     Asm->call(AsmAddress(Mem, Asm, Target));
599   } else if (const auto *CR = llvm::dyn_cast<ConstantRelocatable>(CallTarget)) {
600     Asm->call(CR);
601   } else if (const auto *Imm = llvm::dyn_cast<ConstantInteger32>(CallTarget)) {
602     Asm->call(AssemblerImmediate(Imm->getValue()));
603   } else {
604     llvm_unreachable("Unexpected operand type");
605   }
606 }
607 
dump(const Cfg * Func) const608 void InstX86Call::dump(const Cfg *Func) const {
609   if (!BuildDefs::dump())
610     return;
611   Ostream &Str = Func->getContext()->getStrDump();
612   if (this->getDest()) {
613     this->dumpDest(Func);
614     Str << " = ";
615   }
616   Str << "call ";
617   getCallTarget()->dump(Func);
618 }
619 
620 // The this->Opcode parameter needs to be char* and not std::string because of
621 // template issues.
622 
emitTwoAddress(const Cfg * Func,const char * Opcode,const char * Suffix) const623 void InstX86Base::emitTwoAddress(const Cfg *Func, const char *Opcode,
624                                  const char *Suffix) const {
625   if (!BuildDefs::dump())
626     return;
627   Ostream &Str = Func->getContext()->getStrEmit();
628   assert(getSrcSize() == 2);
629   Operand *Dest = getDest();
630   if (Dest == nullptr)
631     Dest = getSrc(0);
632   assert(Dest == getSrc(0));
633   Operand *Src1 = getSrc(1);
634   Str << "\t" << Opcode << Suffix
635       << InstX86Base::getWidthString(Dest->getType()) << "\t";
636   Src1->emit(Func);
637   Str << ", ";
638   Dest->emit(Func);
639 }
640 
emitIASOpTyGPR(const Cfg * Func,Type Ty,const Operand * Op,const GPREmitterOneOp & Emitter)641 void emitIASOpTyGPR(const Cfg *Func, Type Ty, const Operand *Op,
642                     const GPREmitterOneOp &Emitter) {
643   auto *Target = InstX86Base::getTarget(Func);
644   Assembler *Asm = Func->getAssembler<Assembler>();
645   if (const auto *Var = llvm::dyn_cast<Variable>(Op)) {
646     if (Var->hasReg()) {
647       // We cheat a little and use GPRRegister even for byte operations.
648       GPRRegister VarReg = RegX8664::getEncodedGPR(Var->getRegNum());
649       (Asm->*(Emitter.Reg))(Ty, VarReg);
650     } else {
651       AsmAddress StackAddr(AsmAddress(Var, Target));
652       (Asm->*(Emitter.Addr))(Ty, StackAddr);
653     }
654   } else if (const auto *Mem = llvm::dyn_cast<X86OperandMem>(Op)) {
655     Mem->emitSegmentOverride(Asm);
656     (Asm->*(Emitter.Addr))(Ty, AsmAddress(Mem, Asm, Target));
657   } else {
658     llvm_unreachable("Unexpected operand type");
659   }
660 }
661 
662 template <bool VarCanBeByte, bool SrcCanBeByte>
emitIASRegOpTyGPR(const Cfg * Func,Type Ty,const Variable * Var,const Operand * Src,const GPREmitterRegOp & Emitter)663 void emitIASRegOpTyGPR(const Cfg *Func, Type Ty, const Variable *Var,
664                        const Operand *Src, const GPREmitterRegOp &Emitter) {
665   auto *Target = InstX86Base::getTarget(Func);
666   Assembler *Asm = Func->getAssembler<Assembler>();
667   assert(Var->hasReg());
668   // We cheat a little and use GPRRegister even for byte operations.
669   GPRRegister VarReg = VarCanBeByte ? RegX8664::getEncodedGPR(Var->getRegNum())
670                                     : RegX8664::getEncodedGPR(Var->getRegNum());
671   if (const auto *SrcVar = llvm::dyn_cast<Variable>(Src)) {
672     if (SrcVar->hasReg()) {
673       GPRRegister SrcReg = SrcCanBeByte
674                                ? RegX8664::getEncodedGPR(SrcVar->getRegNum())
675                                : RegX8664::getEncodedGPR(SrcVar->getRegNum());
676       (Asm->*(Emitter.GPRGPR))(Ty, VarReg, SrcReg);
677     } else {
678       AsmAddress SrcStackAddr = AsmAddress(SrcVar, Target);
679       (Asm->*(Emitter.GPRAddr))(Ty, VarReg, SrcStackAddr);
680     }
681   } else if (const auto *Mem = llvm::dyn_cast<X86OperandMem>(Src)) {
682     Mem->emitSegmentOverride(Asm);
683     (Asm->*(Emitter.GPRAddr))(Ty, VarReg, AsmAddress(Mem, Asm, Target));
684   } else if (const auto *Imm = llvm::dyn_cast<ConstantInteger32>(Src)) {
685     (Asm->*(Emitter.GPRImm))(Ty, VarReg, AssemblerImmediate(Imm->getValue()));
686   } else if (const auto *Imm = llvm::dyn_cast<ConstantInteger64>(Src)) {
687     assert(Utils::IsInt(32, Imm->getValue()));
688     (Asm->*(Emitter.GPRImm))(Ty, VarReg, AssemblerImmediate(Imm->getValue()));
689   } else if (const auto *Reloc = llvm::dyn_cast<ConstantRelocatable>(Src)) {
690     const auto FixupKind = (Reloc->getName().hasStdString() &&
691                             Reloc->getName().toString() == GlobalOffsetTable)
692                                ? FK_GotPC
693                                : FK_Abs;
694     AssemblerFixup *Fixup = Asm->createFixup(FixupKind, Reloc);
695     (Asm->*(Emitter.GPRImm))(Ty, VarReg, AssemblerImmediate(Fixup));
696   } else {
697     llvm_unreachable("Unexpected operand type");
698   }
699 }
700 
emitIASAddrOpTyGPR(const Cfg * Func,Type Ty,const AsmAddress & Addr,const Operand * Src,const GPREmitterAddrOp & Emitter)701 void emitIASAddrOpTyGPR(const Cfg *Func, Type Ty, const AsmAddress &Addr,
702                         const Operand *Src, const GPREmitterAddrOp &Emitter) {
703   Assembler *Asm = Func->getAssembler<Assembler>();
704   // Src can only be Reg or AssemblerImmediate.
705   if (const auto *SrcVar = llvm::dyn_cast<Variable>(Src)) {
706     assert(SrcVar->hasReg());
707     GPRRegister SrcReg = RegX8664::getEncodedGPR(SrcVar->getRegNum());
708     (Asm->*(Emitter.AddrGPR))(Ty, Addr, SrcReg);
709   } else if (const auto *Imm = llvm::dyn_cast<ConstantInteger32>(Src)) {
710     (Asm->*(Emitter.AddrImm))(Ty, Addr, AssemblerImmediate(Imm->getValue()));
711   } else if (const auto *Imm = llvm::dyn_cast<ConstantInteger64>(Src)) {
712     assert(Utils::IsInt(32, Imm->getValue()));
713     (Asm->*(Emitter.AddrImm))(Ty, Addr, AssemblerImmediate(Imm->getValue()));
714   } else if (const auto *Reloc = llvm::dyn_cast<ConstantRelocatable>(Src)) {
715     const auto FixupKind = (Reloc->getName().hasStdString() &&
716                             Reloc->getName().toString() == GlobalOffsetTable)
717                                ? FK_GotPC
718                                : FK_Abs;
719     AssemblerFixup *Fixup = Asm->createFixup(FixupKind, Reloc);
720     (Asm->*(Emitter.AddrImm))(Ty, Addr, AssemblerImmediate(Fixup));
721   } else {
722     llvm_unreachable("Unexpected operand type");
723   }
724 }
725 
emitIASAsAddrOpTyGPR(const Cfg * Func,Type Ty,const Operand * Op0,const Operand * Op1,const GPREmitterAddrOp & Emitter)726 void emitIASAsAddrOpTyGPR(const Cfg *Func, Type Ty, const Operand *Op0,
727                           const Operand *Op1, const GPREmitterAddrOp &Emitter) {
728   auto *Target = InstX86Base::getTarget(Func);
729   if (const auto *Op0Var = llvm::dyn_cast<Variable>(Op0)) {
730     assert(!Op0Var->hasReg());
731     AsmAddress StackAddr(AsmAddress(Op0Var, Target));
732     emitIASAddrOpTyGPR(Func, Ty, StackAddr, Op1, Emitter);
733   } else if (const auto *Op0Mem = llvm::dyn_cast<X86OperandMem>(Op0)) {
734     Assembler *Asm = Func->getAssembler<Assembler>();
735     Op0Mem->emitSegmentOverride(Asm);
736     emitIASAddrOpTyGPR(Func, Ty, AsmAddress(Op0Mem, Asm, Target), Op1, Emitter);
737   } else {
738     llvm_unreachable("Unexpected operand type");
739   }
740 }
741 
emitIASGPRShift(const Cfg * Func,Type Ty,const Variable * Var,const Operand * Src,const GPREmitterShiftOp & Emitter)742 void emitIASGPRShift(const Cfg *Func, Type Ty, const Variable *Var,
743                      const Operand *Src, const GPREmitterShiftOp &Emitter) {
744   Assembler *Asm = Func->getAssembler<Assembler>();
745   // Technically, the Dest Var can be mem as well, but we only use Reg. We can
746   // extend this to check Dest if we decide to use that form.
747   assert(Var->hasReg());
748   // We cheat a little and use GPRRegister even for byte operations.
749   GPRRegister VarReg = RegX8664::getEncodedGPR(Var->getRegNum());
750   // Src must be reg == ECX or an Imm8. This is asserted by the assembler.
751   if (const auto *SrcVar = llvm::dyn_cast<Variable>(Src)) {
752     assert(SrcVar->hasReg());
753     GPRRegister SrcReg = RegX8664::getEncodedGPR(SrcVar->getRegNum());
754     (Asm->*(Emitter.GPRGPR))(Ty, VarReg, SrcReg);
755   } else if (const auto *Imm = llvm::dyn_cast<ConstantInteger32>(Src)) {
756     (Asm->*(Emitter.GPRImm))(Ty, VarReg, AssemblerImmediate(Imm->getValue()));
757   } else if (const auto *Imm = llvm::dyn_cast<ConstantInteger64>(Src)) {
758     assert(Utils::IsInt(32, Imm->getValue()));
759     (Asm->*(Emitter.GPRImm))(Ty, VarReg, AssemblerImmediate(Imm->getValue()));
760   } else {
761     llvm_unreachable("Unexpected operand type");
762   }
763 }
764 
emitIASGPRShiftDouble(const Cfg * Func,const Variable * Dest,const Operand * Src1Op,const Operand * Src2Op,const GPREmitterShiftD & Emitter)765 void emitIASGPRShiftDouble(const Cfg *Func, const Variable *Dest,
766                            const Operand *Src1Op, const Operand *Src2Op,
767                            const GPREmitterShiftD &Emitter) {
768   Assembler *Asm = Func->getAssembler<Assembler>();
769   // Dest can be reg or mem, but we only use the reg variant.
770   assert(Dest->hasReg());
771   GPRRegister DestReg = RegX8664::getEncodedGPR(Dest->getRegNum());
772   // SrcVar1 must be reg.
773   const auto *SrcVar1 = llvm::cast<Variable>(Src1Op);
774   assert(SrcVar1->hasReg());
775   GPRRegister SrcReg = RegX8664::getEncodedGPR(SrcVar1->getRegNum());
776   Type Ty = SrcVar1->getType();
777   // Src2 can be the implicit CL register or an immediate.
778   if (const auto *Imm = llvm::dyn_cast<ConstantInteger32>(Src2Op)) {
779     (Asm->*(Emitter.GPRGPRImm))(Ty, DestReg, SrcReg,
780                                 AssemblerImmediate(Imm->getValue()));
781   } else {
782     assert(llvm::cast<Variable>(Src2Op)->getRegNum() == RegisterSet::Reg_cl);
783     (Asm->*(Emitter.GPRGPR))(Ty, DestReg, SrcReg);
784   }
785 }
786 
emitIASXmmShift(const Cfg * Func,Type Ty,const Variable * Var,const Operand * Src,const XmmEmitterShiftOp & Emitter)787 void emitIASXmmShift(const Cfg *Func, Type Ty, const Variable *Var,
788                      const Operand *Src, const XmmEmitterShiftOp &Emitter) {
789   auto *Target = InstX86Base::getTarget(Func);
790   Assembler *Asm = Func->getAssembler<Assembler>();
791   assert(Var->hasReg());
792   XmmRegister VarReg = RegX8664::getEncodedXmm(Var->getRegNum());
793   if (const auto *SrcVar = llvm::dyn_cast<Variable>(Src)) {
794     if (SrcVar->hasReg()) {
795       XmmRegister SrcReg = RegX8664::getEncodedXmm(SrcVar->getRegNum());
796       (Asm->*(Emitter.XmmXmm))(Ty, VarReg, SrcReg);
797     } else {
798       AsmAddress SrcStackAddr = AsmAddress(SrcVar, Target);
799       (Asm->*(Emitter.XmmAddr))(Ty, VarReg, SrcStackAddr);
800     }
801   } else if (const auto *Mem = llvm::dyn_cast<X86OperandMem>(Src)) {
802     assert(Mem->getSegmentRegister() == X86OperandMem::DefaultSegment);
803     (Asm->*(Emitter.XmmAddr))(Ty, VarReg, AsmAddress(Mem, Asm, Target));
804   } else if (const auto *Imm = llvm::dyn_cast<ConstantInteger32>(Src)) {
805     (Asm->*(Emitter.XmmImm))(Ty, VarReg, AssemblerImmediate(Imm->getValue()));
806   } else {
807     llvm_unreachable("Unexpected operand type");
808   }
809 }
810 
emitIASRegOpTyXMM(const Cfg * Func,Type Ty,const Variable * Var,const Operand * Src,const XmmEmitterRegOp & Emitter)811 void emitIASRegOpTyXMM(const Cfg *Func, Type Ty, const Variable *Var,
812                        const Operand *Src, const XmmEmitterRegOp &Emitter) {
813   auto *Target = InstX86Base::getTarget(Func);
814   Assembler *Asm = Func->getAssembler<Assembler>();
815   assert(Var->hasReg());
816   XmmRegister VarReg = RegX8664::getEncodedXmm(Var->getRegNum());
817   if (const auto *SrcVar = llvm::dyn_cast<Variable>(Src)) {
818     if (SrcVar->hasReg()) {
819       XmmRegister SrcReg = RegX8664::getEncodedXmm(SrcVar->getRegNum());
820       (Asm->*(Emitter.XmmXmm))(Ty, VarReg, SrcReg);
821     } else {
822       AsmAddress SrcStackAddr = AsmAddress(SrcVar, Target);
823       (Asm->*(Emitter.XmmAddr))(Ty, VarReg, SrcStackAddr);
824     }
825   } else if (const auto *Mem = llvm::dyn_cast<X86OperandMem>(Src)) {
826     assert(Mem->getSegmentRegister() == X86OperandMem::DefaultSegment);
827     (Asm->*(Emitter.XmmAddr))(Ty, VarReg, AsmAddress(Mem, Asm, Target));
828   } else if (const auto *Imm = llvm::dyn_cast<Constant>(Src)) {
829     (Asm->*(Emitter.XmmAddr))(Ty, VarReg, AsmAddress(Imm, Asm));
830   } else {
831     llvm_unreachable("Unexpected operand type");
832   }
833 }
834 
835 template <typename DReg_t, typename SReg_t, DReg_t (*destEnc)(RegNumT),
836           SReg_t (*srcEnc)(RegNumT)>
emitIASCastRegOp(const Cfg * Func,Type DestTy,const Variable * Dest,Type SrcTy,const Operand * Src,const CastEmitterRegOp<DReg_t,SReg_t> & Emitter)837 void emitIASCastRegOp(const Cfg *Func, Type DestTy, const Variable *Dest,
838                       Type SrcTy, const Operand *Src,
839                       const CastEmitterRegOp<DReg_t, SReg_t> &Emitter) {
840   auto *Target = InstX86Base::getTarget(Func);
841   Assembler *Asm = Func->getAssembler<Assembler>();
842   assert(Dest->hasReg());
843   DReg_t DestReg = destEnc(Dest->getRegNum());
844   if (const auto *SrcVar = llvm::dyn_cast<Variable>(Src)) {
845     if (SrcVar->hasReg()) {
846       SReg_t SrcReg = srcEnc(SrcVar->getRegNum());
847       (Asm->*(Emitter.RegReg))(DestTy, DestReg, SrcTy, SrcReg);
848     } else {
849       AsmAddress SrcStackAddr = AsmAddress(SrcVar, Target);
850       (Asm->*(Emitter.RegAddr))(DestTy, DestReg, SrcTy, SrcStackAddr);
851     }
852   } else if (const auto *Mem = llvm::dyn_cast<X86OperandMem>(Src)) {
853     Mem->emitSegmentOverride(Asm);
854     (Asm->*(Emitter.RegAddr))(DestTy, DestReg, SrcTy,
855                               AsmAddress(Mem, Asm, Target));
856   } else {
857     llvm_unreachable("Unexpected operand type");
858   }
859 }
860 
861 template <typename DReg_t, typename SReg_t, DReg_t (*destEnc)(RegNumT),
862           SReg_t (*srcEnc)(RegNumT)>
emitIASThreeOpImmOps(const Cfg * Func,Type DispatchTy,const Variable * Dest,const Operand * Src0,const Operand * Src1,const ThreeOpImmEmitter<DReg_t,SReg_t> Emitter)863 void emitIASThreeOpImmOps(const Cfg *Func, Type DispatchTy,
864                           const Variable *Dest, const Operand *Src0,
865                           const Operand *Src1,
866                           const ThreeOpImmEmitter<DReg_t, SReg_t> Emitter) {
867   auto *Target = InstX86Base::getTarget(Func);
868   Assembler *Asm = Func->getAssembler<Assembler>();
869   // This only handles Dest being a register, and Src1 being an immediate.
870   assert(Dest->hasReg());
871   DReg_t DestReg = destEnc(Dest->getRegNum());
872   AssemblerImmediate Imm(llvm::cast<ConstantInteger32>(Src1)->getValue());
873   if (const auto *SrcVar = llvm::dyn_cast<Variable>(Src0)) {
874     if (SrcVar->hasReg()) {
875       SReg_t SrcReg = srcEnc(SrcVar->getRegNum());
876       (Asm->*(Emitter.RegRegImm))(DispatchTy, DestReg, SrcReg, Imm);
877     } else {
878       AsmAddress SrcStackAddr = AsmAddress(SrcVar, Target);
879       (Asm->*(Emitter.RegAddrImm))(DispatchTy, DestReg, SrcStackAddr, Imm);
880     }
881   } else if (const auto *Mem = llvm::dyn_cast<X86OperandMem>(Src0)) {
882     Mem->emitSegmentOverride(Asm);
883     (Asm->*(Emitter.RegAddrImm))(DispatchTy, DestReg,
884                                  AsmAddress(Mem, Asm, Target), Imm);
885   } else {
886     llvm_unreachable("Unexpected operand type");
887   }
888 }
889 
emitIASMovlikeXMM(const Cfg * Func,const Variable * Dest,const Operand * Src,const XmmEmitterMovOps Emitter)890 void emitIASMovlikeXMM(const Cfg *Func, const Variable *Dest,
891                        const Operand *Src, const XmmEmitterMovOps Emitter) {
892   auto *Target = InstX86Base::getTarget(Func);
893   Assembler *Asm = Func->getAssembler<Assembler>();
894   if (Dest->hasReg()) {
895     XmmRegister DestReg = RegX8664::getEncodedXmm(Dest->getRegNum());
896     if (const auto *SrcVar = llvm::dyn_cast<Variable>(Src)) {
897       if (SrcVar->hasReg()) {
898         (Asm->*(Emitter.XmmXmm))(DestReg,
899                                  RegX8664::getEncodedXmm(SrcVar->getRegNum()));
900       } else {
901         AsmAddress StackAddr(AsmAddress(SrcVar, Target));
902         (Asm->*(Emitter.XmmAddr))(DestReg, StackAddr);
903       }
904     } else if (const auto *SrcMem = llvm::dyn_cast<X86OperandMem>(Src)) {
905       assert(SrcMem->getSegmentRegister() == X86OperandMem::DefaultSegment);
906       (Asm->*(Emitter.XmmAddr))(DestReg, AsmAddress(SrcMem, Asm, Target));
907     } else {
908       llvm_unreachable("Unexpected operand type");
909     }
910   } else {
911     AsmAddress StackAddr(AsmAddress(Dest, Target));
912     // Src must be a register in this case.
913     const auto *SrcVar = llvm::cast<Variable>(Src);
914     assert(SrcVar->hasReg());
915     (Asm->*(Emitter.AddrXmm))(StackAddr,
916                               RegX8664::getEncodedXmm(SrcVar->getRegNum()));
917   }
918 }
919 
dump(const Cfg * Func) const920 void InstX86Movmsk::dump(const Cfg *Func) const {
921   if (!BuildDefs::dump())
922     return;
923   Ostream &Str = Func->getContext()->getStrDump();
924   this->dumpDest(Func);
925   Str << " = movmsk." << this->getSrc(0)->getType() << " ";
926   this->dumpSources(Func);
927 }
928 
emit(const Cfg * Func) const929 void InstX86Movmsk::emit(const Cfg *Func) const {
930   if (!BuildDefs::dump())
931     return;
932   Ostream &Str = Func->getContext()->getStrEmit();
933   assert(this->getSrcSize() == 1);
934   Type SrcTy = this->getSrc(0)->getType();
935   assert(isVectorType(SrcTy));
936   switch (SrcTy) {
937   case IceType_v16i8:
938     Str << "\t"
939            "pmovmskb"
940            "\t";
941     break;
942   case IceType_v4i32:
943   case IceType_v4f32:
944     Str << "\t"
945            "movmskps"
946            "\t";
947     break;
948   default:
949     llvm_unreachable("Unexpected operand type");
950   }
951   this->getSrc(0)->emit(Func);
952   Str << ", ";
953   this->getDest()->emit(Func);
954 }
955 
emitIAS(const Cfg * Func) const956 void InstX86Movmsk::emitIAS(const Cfg *Func) const {
957   assert(this->getSrcSize() == 1);
958   Assembler *Asm = Func->getAssembler<Assembler>();
959   const Variable *Dest = this->getDest();
960   const Variable *Src = llvm::cast<Variable>(this->getSrc(0));
961   const Type DestTy = Dest->getType();
962   (void)DestTy;
963   const Type SrcTy = Src->getType();
964   assert(isVectorType(SrcTy));
965   assert(isScalarIntegerType(DestTy));
966   assert(DestTy == IceType_i32 || DestTy == IceType_i64);
967   XmmRegister SrcReg = RegX8664::getEncodedXmm(Src->getRegNum());
968   GPRRegister DestReg = RegX8664::getEncodedGPR(Dest->getRegNum());
969   Asm->movmsk(SrcTy, DestReg, SrcReg);
970 }
971 
emit(const Cfg * Func) const972 void InstX86Sqrt::emit(const Cfg *Func) const {
973   if (!BuildDefs::dump())
974     return;
975   Ostream &Str = Func->getContext()->getStrEmit();
976   assert(this->getSrcSize() == 1);
977   Type Ty = this->getSrc(0)->getType();
978   assert(isScalarFloatingType(Ty));
979   Str << "\t"
980          "sqrt"
981       << TypeAttributes[Ty].SpSdString << "\t";
982   this->getSrc(0)->emit(Func);
983   Str << ", ";
984   this->getDest()->emit(Func);
985 }
986 
emit(const Cfg * Func) const987 void InstX86Div::emit(const Cfg *Func) const {
988   if (!BuildDefs::dump())
989     return;
990   Ostream &Str = Func->getContext()->getStrEmit();
991   assert(this->getSrcSize() == 3);
992   Operand *Src1 = this->getSrc(1);
993   Str << "\t" << this->Opcode << this->getWidthString(Src1->getType()) << "\t";
994   Src1->emit(Func);
995 }
996 
emitIAS(const Cfg * Func) const997 void InstX86Div::emitIAS(const Cfg *Func) const {
998   assert(this->getSrcSize() == 3);
999   const Operand *Src = this->getSrc(1);
1000   Type Ty = Src->getType();
1001   static GPREmitterOneOp Emitter = {&Assembler::div, &Assembler::div};
1002   emitIASOpTyGPR(Func, Ty, Src, Emitter);
1003 }
1004 
emit(const Cfg * Func) const1005 void InstX86Idiv::emit(const Cfg *Func) const {
1006   if (!BuildDefs::dump())
1007     return;
1008   Ostream &Str = Func->getContext()->getStrEmit();
1009   assert(this->getSrcSize() == 3);
1010   Operand *Src1 = this->getSrc(1);
1011   Str << "\t" << this->Opcode << this->getWidthString(Src1->getType()) << "\t";
1012   Src1->emit(Func);
1013 }
1014 
emitIAS(const Cfg * Func) const1015 void InstX86Idiv::emitIAS(const Cfg *Func) const {
1016   assert(this->getSrcSize() == 3);
1017   const Operand *Src = this->getSrc(1);
1018   Type Ty = Src->getType();
1019   static const GPREmitterOneOp Emitter = {&Assembler::idiv, &Assembler::idiv};
1020   emitIASOpTyGPR(Func, Ty, Src, Emitter);
1021 }
1022 
1023 // pblendvb and blendvps take xmm0 as a final implicit argument.
1024 
emitVariableBlendInst(const char * Opcode,const Inst * Instr,const Cfg * Func)1025 void emitVariableBlendInst(const char *Opcode, const Inst *Instr,
1026                            const Cfg *Func) {
1027   if (!BuildDefs::dump())
1028     return;
1029   Ostream &Str = Func->getContext()->getStrEmit();
1030   assert(Instr->getSrcSize() == 3);
1031   assert(llvm::cast<Variable>(Instr->getSrc(2))->getRegNum() ==
1032          RegisterSet::Reg_xmm0);
1033   Str << "\t" << Opcode << "\t";
1034   Instr->getSrc(1)->emit(Func);
1035   Str << ", ";
1036   Instr->getDest()->emit(Func);
1037 }
1038 
emitIASVariableBlendInst(const Inst * Instr,const Cfg * Func,const XmmEmitterRegOp & Emitter)1039 void emitIASVariableBlendInst(const Inst *Instr, const Cfg *Func,
1040                               const XmmEmitterRegOp &Emitter) {
1041   assert(Instr->getSrcSize() == 3);
1042   assert(llvm::cast<Variable>(Instr->getSrc(2))->getRegNum() ==
1043          RegisterSet::Reg_xmm0);
1044   const Variable *Dest = Instr->getDest();
1045   const Operand *Src = Instr->getSrc(1);
1046   emitIASRegOpTyXMM(Func, Dest->getType(), Dest, Src, Emitter);
1047 }
1048 
emit(const Cfg * Func) const1049 void InstX86Blendvps::emit(const Cfg *Func) const {
1050   if (!BuildDefs::dump())
1051     return;
1052   emitVariableBlendInst(this->Opcode, this, Func);
1053 }
1054 
emitIAS(const Cfg * Func) const1055 void InstX86Blendvps::emitIAS(const Cfg *Func) const {
1056   static const XmmEmitterRegOp Emitter = {&Assembler::blendvps,
1057                                           &Assembler::blendvps};
1058   emitIASVariableBlendInst(this, Func, Emitter);
1059 }
1060 
emit(const Cfg * Func) const1061 void InstX86Pblendvb::emit(const Cfg *Func) const {
1062   if (!BuildDefs::dump())
1063     return;
1064   emitVariableBlendInst(this->Opcode, this, Func);
1065 }
1066 
emitIAS(const Cfg * Func) const1067 void InstX86Pblendvb::emitIAS(const Cfg *Func) const {
1068   static const XmmEmitterRegOp Emitter = {&Assembler::pblendvb,
1069                                           &Assembler::pblendvb};
1070   emitIASVariableBlendInst(this, Func, Emitter);
1071 }
1072 
emit(const Cfg * Func) const1073 void InstX86Imul::emit(const Cfg *Func) const {
1074   if (!BuildDefs::dump())
1075     return;
1076   Ostream &Str = Func->getContext()->getStrEmit();
1077   assert(this->getSrcSize() == 2);
1078   Variable *Dest = this->getDest();
1079   if (isByteSizedArithType(Dest->getType())) {
1080     // The 8-bit version of imul only allows the form "imul r/m8".
1081     const auto *Src0Var = llvm::dyn_cast<Variable>(this->getSrc(0));
1082     (void)Src0Var;
1083     assert(Src0Var->getRegNum() == RegisterSet::Reg_al);
1084     Str << "\t"
1085            "imulb\t";
1086     this->getSrc(1)->emit(Func);
1087   } else if (llvm::isa<Constant>(this->getSrc(1))) {
1088     Str << "\t"
1089            "imul"
1090         << this->getWidthString(Dest->getType()) << "\t";
1091     this->getSrc(1)->emit(Func);
1092     Str << ", ";
1093     this->getSrc(0)->emit(Func);
1094     Str << ", ";
1095     Dest->emit(Func);
1096   } else {
1097     this->emitTwoAddress(Func, this->Opcode);
1098   }
1099 }
1100 
emitIAS(const Cfg * Func) const1101 void InstX86Imul::emitIAS(const Cfg *Func) const {
1102   assert(this->getSrcSize() == 2);
1103   const Variable *Var = this->getDest();
1104   Type Ty = Var->getType();
1105   const Operand *Src = this->getSrc(1);
1106   if (isByteSizedArithType(Ty)) {
1107     // The 8-bit version of imul only allows the form "imul r/m8".
1108     const auto *Src0Var = llvm::dyn_cast<Variable>(this->getSrc(0));
1109     (void)Src0Var;
1110     assert(Src0Var->getRegNum() == RegisterSet::Reg_al);
1111     static const GPREmitterOneOp Emitter = {&Assembler::imul, &Assembler::imul};
1112     emitIASOpTyGPR(Func, Ty, this->getSrc(1), Emitter);
1113   } else {
1114     // The two-address version is used when multiplying by a non-constant
1115     // or doing an 8-bit multiply.
1116     assert(Var == this->getSrc(0));
1117     static const GPREmitterRegOp Emitter = {&Assembler::imul, &Assembler::imul,
1118                                             &Assembler::imul};
1119     emitIASRegOpTyGPR(Func, Ty, Var, Src, Emitter);
1120   }
1121 }
1122 
emit(const Cfg * Func) const1123 void InstX86ImulImm::emit(const Cfg *Func) const {
1124   if (!BuildDefs::dump())
1125     return;
1126   Ostream &Str = Func->getContext()->getStrEmit();
1127   assert(this->getSrcSize() == 2);
1128   Variable *Dest = this->getDest();
1129   assert(Dest->getType() == IceType_i16 || Dest->getType() == IceType_i32);
1130   assert(llvm::isa<Constant>(this->getSrc(1)));
1131   Str << "\t"
1132          "imul"
1133       << this->getWidthString(Dest->getType()) << "\t";
1134   this->getSrc(1)->emit(Func);
1135   Str << ", ";
1136   this->getSrc(0)->emit(Func);
1137   Str << ", ";
1138   Dest->emit(Func);
1139 }
1140 
emitIAS(const Cfg * Func) const1141 void InstX86ImulImm::emitIAS(const Cfg *Func) const {
1142   assert(this->getSrcSize() == 2);
1143   const Variable *Dest = this->getDest();
1144   Type Ty = Dest->getType();
1145   assert(llvm::isa<Constant>(this->getSrc(1)));
1146   static const ThreeOpImmEmitter<GPRRegister, GPRRegister> Emitter = {
1147       &Assembler::imul, &Assembler::imul};
1148   emitIASThreeOpImmOps<GPRRegister, GPRRegister, RegX8664::getEncodedGPR,
1149                        RegX8664::getEncodedGPR>(Func, Ty, Dest, this->getSrc(0),
1150                                                 this->getSrc(1), Emitter);
1151 }
1152 
emitIAS(const Cfg * Func) const1153 void InstX86Insertps::emitIAS(const Cfg *Func) const {
1154   assert(this->getSrcSize() == 3);
1155   assert(getInstructionSet(Func) >= SSE4_1);
1156   const Variable *Dest = this->getDest();
1157   assert(Dest == this->getSrc(0));
1158   Type Ty = Dest->getType();
1159   static const ThreeOpImmEmitter<XmmRegister, XmmRegister> Emitter = {
1160       &Assembler::insertps, &Assembler::insertps};
1161   emitIASThreeOpImmOps<XmmRegister, XmmRegister, RegX8664::getEncodedXmm,
1162                        RegX8664::getEncodedXmm>(Func, Ty, Dest, this->getSrc(1),
1163                                                 this->getSrc(2), Emitter);
1164 }
1165 
emit(const Cfg * Func) const1166 void InstX86Cbwdq::emit(const Cfg *Func) const {
1167   if (!BuildDefs::dump())
1168     return;
1169   Ostream &Str = Func->getContext()->getStrEmit();
1170   assert(this->getSrcSize() == 1);
1171   Operand *Src0 = this->getSrc(0);
1172   const auto DestReg = this->getDest()->getRegNum();
1173   const auto SrcReg = llvm::cast<Variable>(Src0)->getRegNum();
1174   (void)DestReg;
1175   (void)SrcReg;
1176   switch (Src0->getType()) {
1177   default:
1178     llvm_unreachable("unexpected source type!");
1179     break;
1180   case IceType_i8:
1181     assert(SrcReg == RegisterSet::Reg_al);
1182     assert(DestReg == RegisterSet::Reg_ax || DestReg == RegisterSet::Reg_ah);
1183     Str << "\t"
1184            "cbtw";
1185     break;
1186   case IceType_i16:
1187     assert(SrcReg == RegisterSet::Reg_ax);
1188     assert(DestReg == RegisterSet::Reg_dx);
1189     Str << "\t"
1190            "cwtd";
1191     break;
1192   case IceType_i32:
1193     assert(SrcReg == RegisterSet::Reg_eax);
1194     assert(DestReg == RegisterSet::Reg_edx);
1195     Str << "\t"
1196            "cltd";
1197     break;
1198   case IceType_i64:
1199     assert(SrcReg == RegisterSet::Reg_rax);
1200     assert(DestReg == RegisterSet::Reg_rdx);
1201     Str << "\t"
1202            "cqo";
1203     break;
1204   }
1205 }
1206 
emitIAS(const Cfg * Func) const1207 void InstX86Cbwdq::emitIAS(const Cfg *Func) const {
1208   Assembler *Asm = Func->getAssembler<Assembler>();
1209   assert(this->getSrcSize() == 1);
1210   Operand *Src0 = this->getSrc(0);
1211   const auto DestReg = this->getDest()->getRegNum();
1212   const auto SrcReg = llvm::cast<Variable>(Src0)->getRegNum();
1213   (void)DestReg;
1214   (void)SrcReg;
1215   switch (Src0->getType()) {
1216   default:
1217     llvm_unreachable("unexpected source type!");
1218     break;
1219   case IceType_i8:
1220     assert(SrcReg == RegisterSet::Reg_al);
1221     assert(DestReg == RegisterSet::Reg_ax || DestReg == RegisterSet::Reg_ah);
1222     Asm->cbw();
1223     break;
1224   case IceType_i16:
1225     assert(SrcReg == RegisterSet::Reg_ax);
1226     assert(DestReg == RegisterSet::Reg_dx);
1227     Asm->cwd();
1228     break;
1229   case IceType_i32:
1230     assert(SrcReg == RegisterSet::Reg_eax);
1231     assert(DestReg == RegisterSet::Reg_edx);
1232     Asm->cdq();
1233     break;
1234   case IceType_i64:
1235     assert(SrcReg == RegisterSet::Reg_rax);
1236     assert(DestReg == RegisterSet::Reg_rdx);
1237     Asm->cqo();
1238     break;
1239   }
1240 }
1241 
emit(const Cfg * Func) const1242 void InstX86Mul::emit(const Cfg *Func) const {
1243   if (!BuildDefs::dump())
1244     return;
1245   Ostream &Str = Func->getContext()->getStrEmit();
1246   assert(this->getSrcSize() == 2);
1247   assert(llvm::isa<Variable>(this->getSrc(0)));
1248   assert(llvm::cast<Variable>(this->getSrc(0))->getRegNum() ==
1249          RegisterSet::Reg_eax);
1250   assert(this->getDest()->getRegNum() == RegisterSet::Reg_eax); // TODO:
1251                                                                 // allow
1252                                                                 // edx?
1253   Str << "\t"
1254          "mul"
1255       << this->getWidthString(this->getDest()->getType()) << "\t";
1256   this->getSrc(1)->emit(Func);
1257 }
1258 
emitIAS(const Cfg * Func) const1259 void InstX86Mul::emitIAS(const Cfg *Func) const {
1260   assert(this->getSrcSize() == 2);
1261   assert(llvm::isa<Variable>(this->getSrc(0)));
1262   assert(llvm::cast<Variable>(this->getSrc(0))->getRegNum() ==
1263          RegisterSet::Reg_eax);
1264   assert(this->getDest()->getRegNum() == RegisterSet::Reg_eax); // TODO:
1265                                                                 // allow
1266                                                                 // edx?
1267   const Operand *Src = this->getSrc(1);
1268   Type Ty = Src->getType();
1269   static const GPREmitterOneOp Emitter = {&Assembler::mul, &Assembler::mul};
1270   emitIASOpTyGPR(Func, Ty, Src, Emitter);
1271 }
1272 
dump(const Cfg * Func) const1273 void InstX86Mul::dump(const Cfg *Func) const {
1274   if (!BuildDefs::dump())
1275     return;
1276   Ostream &Str = Func->getContext()->getStrDump();
1277   this->dumpDest(Func);
1278   Str << " = mul." << this->getDest()->getType() << " ";
1279   this->dumpSources(Func);
1280 }
1281 
emit(const Cfg * Func) const1282 void InstX86Shld::emit(const Cfg *Func) const {
1283   if (!BuildDefs::dump())
1284     return;
1285   Ostream &Str = Func->getContext()->getStrEmit();
1286   Variable *Dest = this->getDest();
1287   assert(this->getSrcSize() == 3);
1288   assert(Dest == this->getSrc(0));
1289   Str << "\t"
1290          "shld"
1291       << this->getWidthString(Dest->getType()) << "\t";
1292   this->getSrc(2)->emit(Func);
1293   Str << ", ";
1294   this->getSrc(1)->emit(Func);
1295   Str << ", ";
1296   Dest->emit(Func);
1297 }
1298 
emitIAS(const Cfg * Func) const1299 void InstX86Shld::emitIAS(const Cfg *Func) const {
1300   assert(this->getSrcSize() == 3);
1301   assert(this->getDest() == this->getSrc(0));
1302   const Variable *Dest = this->getDest();
1303   const Operand *Src1 = this->getSrc(1);
1304   const Operand *Src2 = this->getSrc(2);
1305   static const GPREmitterShiftD Emitter = {&Assembler::shld, &Assembler::shld};
1306   emitIASGPRShiftDouble(Func, Dest, Src1, Src2, Emitter);
1307 }
1308 
dump(const Cfg * Func) const1309 void InstX86Shld::dump(const Cfg *Func) const {
1310   if (!BuildDefs::dump())
1311     return;
1312   Ostream &Str = Func->getContext()->getStrDump();
1313   this->dumpDest(Func);
1314   Str << " = shld." << this->getDest()->getType() << " ";
1315   this->dumpSources(Func);
1316 }
1317 
emit(const Cfg * Func) const1318 void InstX86Shrd::emit(const Cfg *Func) const {
1319   if (!BuildDefs::dump())
1320     return;
1321   Ostream &Str = Func->getContext()->getStrEmit();
1322   Variable *Dest = this->getDest();
1323   assert(this->getSrcSize() == 3);
1324   assert(Dest == this->getSrc(0));
1325   Str << "\t"
1326          "shrd"
1327       << this->getWidthString(Dest->getType()) << "\t";
1328   this->getSrc(2)->emit(Func);
1329   Str << ", ";
1330   this->getSrc(1)->emit(Func);
1331   Str << ", ";
1332   Dest->emit(Func);
1333 }
1334 
emitIAS(const Cfg * Func) const1335 void InstX86Shrd::emitIAS(const Cfg *Func) const {
1336   assert(this->getSrcSize() == 3);
1337   assert(this->getDest() == this->getSrc(0));
1338   const Variable *Dest = this->getDest();
1339   const Operand *Src1 = this->getSrc(1);
1340   const Operand *Src2 = this->getSrc(2);
1341   static const GPREmitterShiftD Emitter = {&Assembler::shrd, &Assembler::shrd};
1342   emitIASGPRShiftDouble(Func, Dest, Src1, Src2, Emitter);
1343 }
1344 
dump(const Cfg * Func) const1345 void InstX86Shrd::dump(const Cfg *Func) const {
1346   if (!BuildDefs::dump())
1347     return;
1348   Ostream &Str = Func->getContext()->getStrDump();
1349   this->dumpDest(Func);
1350   Str << " = shrd." << this->getDest()->getType() << " ";
1351   this->dumpSources(Func);
1352 }
1353 
emit(const Cfg * Func) const1354 void InstX86Cmov::emit(const Cfg *Func) const {
1355   if (!BuildDefs::dump())
1356     return;
1357   Ostream &Str = Func->getContext()->getStrEmit();
1358   Variable *Dest = this->getDest();
1359   Str << "\t";
1360   assert(Condition != Cond::Br_None);
1361   assert(this->getDest()->hasReg());
1362   Str << "cmov" << InstBrAttributes[Condition].DisplayString
1363       << this->getWidthString(Dest->getType()) << "\t";
1364   this->getSrc(1)->emit(Func);
1365   Str << ", ";
1366   Dest->emit(Func);
1367 }
1368 
emitIAS(const Cfg * Func) const1369 void InstX86Cmov::emitIAS(const Cfg *Func) const {
1370   assert(Condition != Cond::Br_None);
1371   assert(this->getDest()->hasReg());
1372   assert(this->getSrcSize() == 2);
1373   Operand *Src = this->getSrc(1);
1374   Type SrcTy = Src->getType();
1375   Assembler *Asm = Func->getAssembler<Assembler>();
1376   auto *Target = InstX86Base::getTarget(Func);
1377   if (const auto *SrcVar = llvm::dyn_cast<Variable>(Src)) {
1378     if (SrcVar->hasReg()) {
1379       Asm->cmov(SrcTy, Condition,
1380                 RegX8664::getEncodedGPR(this->getDest()->getRegNum()),
1381                 RegX8664::getEncodedGPR(SrcVar->getRegNum()));
1382     } else {
1383       Asm->cmov(SrcTy, Condition,
1384                 RegX8664::getEncodedGPR(this->getDest()->getRegNum()),
1385                 AsmAddress(SrcVar, Target));
1386     }
1387   } else if (const auto *Mem = llvm::dyn_cast<X86OperandMem>(Src)) {
1388     assert(Mem->getSegmentRegister() == X86OperandMem::DefaultSegment);
1389     Asm->cmov(SrcTy, Condition,
1390               RegX8664::getEncodedGPR(this->getDest()->getRegNum()),
1391               AsmAddress(Mem, Asm, Target));
1392   } else {
1393     llvm_unreachable("Unexpected operand type");
1394   }
1395 }
1396 
dump(const Cfg * Func) const1397 void InstX86Cmov::dump(const Cfg *Func) const {
1398   if (!BuildDefs::dump())
1399     return;
1400   Ostream &Str = Func->getContext()->getStrDump();
1401   Str << "cmov" << InstBrAttributes[Condition].DisplayString << ".";
1402   Str << this->getDest()->getType() << " ";
1403   this->dumpDest(Func);
1404   Str << ", ";
1405   this->dumpSources(Func);
1406 }
1407 
emit(const Cfg * Func) const1408 void InstX86Cmpps::emit(const Cfg *Func) const {
1409   if (!BuildDefs::dump())
1410     return;
1411   Ostream &Str = Func->getContext()->getStrEmit();
1412   assert(this->getSrcSize() == 2);
1413   assert(Condition < Cond::Cmpps_Invalid);
1414   Type DestTy = this->Dest->getType();
1415   Str << "\t"
1416          "cmp"
1417       << InstCmppsAttributes[Condition].EmitString
1418       << TypeAttributes[DestTy].PdPsString << "\t";
1419   this->getSrc(1)->emit(Func);
1420   Str << ", ";
1421   this->getDest()->emit(Func);
1422 }
1423 
emitIAS(const Cfg * Func) const1424 void InstX86Cmpps::emitIAS(const Cfg *Func) const {
1425   Assembler *Asm = Func->getAssembler<Assembler>();
1426   assert(this->getSrcSize() == 2);
1427   assert(Condition < Cond::Cmpps_Invalid);
1428   // Assuming there isn't any load folding for cmpps, and vector constants are
1429   // not allowed in PNaCl.
1430   assert(llvm::isa<Variable>(this->getSrc(1)));
1431   auto *Target = InstX86Base::getTarget(Func);
1432   const auto *SrcVar = llvm::cast<Variable>(this->getSrc(1));
1433   if (SrcVar->hasReg()) {
1434     Asm->cmpps(this->getDest()->getType(),
1435                RegX8664::getEncodedXmm(this->getDest()->getRegNum()),
1436                RegX8664::getEncodedXmm(SrcVar->getRegNum()), Condition);
1437   } else {
1438     AsmAddress SrcStackAddr = AsmAddress(SrcVar, Target);
1439     Asm->cmpps(this->getDest()->getType(),
1440                RegX8664::getEncodedXmm(this->getDest()->getRegNum()),
1441                SrcStackAddr, Condition);
1442   }
1443 }
1444 
dump(const Cfg * Func) const1445 void InstX86Cmpps::dump(const Cfg *Func) const {
1446   if (!BuildDefs::dump())
1447     return;
1448   Ostream &Str = Func->getContext()->getStrDump();
1449   assert(Condition < Cond::Cmpps_Invalid);
1450   this->dumpDest(Func);
1451   Str << " = cmp" << InstCmppsAttributes[Condition].EmitString
1452       << "ps"
1453          "\t";
1454   this->dumpSources(Func);
1455 }
1456 
emit(const Cfg * Func) const1457 void InstX86Cmpxchg::emit(const Cfg *Func) const {
1458   if (!BuildDefs::dump())
1459     return;
1460   Ostream &Str = Func->getContext()->getStrEmit();
1461   assert(this->getSrcSize() == 3);
1462   if (this->Locked) {
1463     Str << "\t"
1464            "lock";
1465   }
1466   Str << "\t"
1467          "cmpxchg"
1468       << this->getWidthString(this->getSrc(0)->getType()) << "\t";
1469   this->getSrc(2)->emit(Func);
1470   Str << ", ";
1471   this->getSrc(0)->emit(Func);
1472 }
1473 
emitIAS(const Cfg * Func) const1474 void InstX86Cmpxchg::emitIAS(const Cfg *Func) const {
1475   assert(this->getSrcSize() == 3);
1476   Assembler *Asm = Func->getAssembler<Assembler>();
1477   Type Ty = this->getSrc(0)->getType();
1478   auto *Target = InstX86Base::getTarget(Func);
1479   const auto Mem = llvm::cast<X86OperandMem>(this->getSrc(0));
1480   assert(Mem->getSegmentRegister() == X86OperandMem::DefaultSegment);
1481   const AsmAddress Addr = AsmAddress(Mem, Asm, Target);
1482   const auto *VarReg = llvm::cast<Variable>(this->getSrc(2));
1483   assert(VarReg->hasReg());
1484   const GPRRegister Reg = RegX8664::getEncodedGPR(VarReg->getRegNum());
1485   Asm->cmpxchg(Ty, Addr, Reg, this->Locked);
1486 }
1487 
dump(const Cfg * Func) const1488 void InstX86Cmpxchg::dump(const Cfg *Func) const {
1489   if (!BuildDefs::dump())
1490     return;
1491   Ostream &Str = Func->getContext()->getStrDump();
1492   if (this->Locked) {
1493     Str << "lock ";
1494   }
1495   Str << "cmpxchg." << this->getSrc(0)->getType() << " ";
1496   this->dumpSources(Func);
1497 }
1498 
emit(const Cfg * Func) const1499 void InstX86Cmpxchg8b::emit(const Cfg *Func) const {
1500   if (!BuildDefs::dump())
1501     return;
1502   Ostream &Str = Func->getContext()->getStrEmit();
1503   assert(this->getSrcSize() == 5);
1504   if (this->Locked) {
1505     Str << "\t"
1506            "lock";
1507   }
1508   Str << "\t"
1509          "cmpxchg8b\t";
1510   this->getSrc(0)->emit(Func);
1511 }
1512 
emitIAS(const Cfg * Func) const1513 void InstX86Cmpxchg8b::emitIAS(const Cfg *Func) const {
1514   assert(this->getSrcSize() == 5);
1515   Assembler *Asm = Func->getAssembler<Assembler>();
1516   const auto Mem = llvm::cast<X86OperandMem>(this->getSrc(0));
1517   assert(Mem->getSegmentRegister() == X86OperandMem::DefaultSegment);
1518   auto *Target = InstX86Base::getTarget(Func);
1519   const AsmAddress Addr = AsmAddress(Mem, Asm, Target);
1520   Asm->cmpxchg8b(Addr, this->Locked);
1521 }
1522 
dump(const Cfg * Func) const1523 void InstX86Cmpxchg8b::dump(const Cfg *Func) const {
1524   if (!BuildDefs::dump())
1525     return;
1526   Ostream &Str = Func->getContext()->getStrDump();
1527   if (this->Locked) {
1528     Str << "lock ";
1529   }
1530   Str << "cmpxchg8b ";
1531   this->dumpSources(Func);
1532 }
1533 
emit(const Cfg * Func) const1534 void InstX86Cvt::emit(const Cfg *Func) const {
1535   if (!BuildDefs::dump())
1536     return;
1537   Ostream &Str = Func->getContext()->getStrEmit();
1538   assert(this->getSrcSize() == 1);
1539   Str << "\t"
1540          "cvt";
1541   if (isTruncating())
1542     Str << "t";
1543   Str << TypeAttributes[this->getSrc(0)->getType()].CvtString << "2"
1544       << TypeAttributes[this->getDest()->getType()].CvtString << "\t";
1545   this->getSrc(0)->emit(Func);
1546   Str << ", ";
1547   this->getDest()->emit(Func);
1548 }
1549 
emitIAS(const Cfg * Func) const1550 void InstX86Cvt::emitIAS(const Cfg *Func) const {
1551   assert(this->getSrcSize() == 1);
1552   const Variable *Dest = this->getDest();
1553   const Operand *Src = this->getSrc(0);
1554   Type DestTy = Dest->getType();
1555   Type SrcTy = Src->getType();
1556   switch (Variant) {
1557   case Si2ss: {
1558     assert(isScalarIntegerType(SrcTy));
1559     assert(SrcTy == IceType_i32 || SrcTy == IceType_i64);
1560     assert(isScalarFloatingType(DestTy));
1561     static const CastEmitterRegOp<XmmRegister, GPRRegister> Emitter = {
1562         &Assembler::cvtsi2ss, &Assembler::cvtsi2ss};
1563     emitIASCastRegOp<XmmRegister, GPRRegister, RegX8664::getEncodedXmm,
1564                      RegX8664::getEncodedGPR>(Func, DestTy, Dest, SrcTy, Src,
1565                                               Emitter);
1566     return;
1567   }
1568   case Tss2si: {
1569     assert(isScalarFloatingType(SrcTy));
1570     assert(isScalarIntegerType(DestTy));
1571     assert(DestTy == IceType_i32 || DestTy == IceType_i64);
1572     static const CastEmitterRegOp<GPRRegister, XmmRegister> Emitter = {
1573         &Assembler::cvttss2si, &Assembler::cvttss2si};
1574     emitIASCastRegOp<GPRRegister, XmmRegister, RegX8664::getEncodedGPR,
1575                      RegX8664::getEncodedXmm>(Func, DestTy, Dest, SrcTy, Src,
1576                                               Emitter);
1577     return;
1578   }
1579   case Ss2si: {
1580     assert(isScalarFloatingType(SrcTy));
1581     assert(isScalarIntegerType(DestTy));
1582     assert(DestTy == IceType_i32 || DestTy == IceType_i64);
1583     static const CastEmitterRegOp<GPRRegister, XmmRegister> Emitter = {
1584         &Assembler::cvtss2si, &Assembler::cvtss2si};
1585     emitIASCastRegOp<GPRRegister, XmmRegister, RegX8664::getEncodedGPR,
1586                      RegX8664::getEncodedXmm>(Func, DestTy, Dest, SrcTy, Src,
1587                                               Emitter);
1588     return;
1589   }
1590   case Float2float: {
1591     assert(isScalarFloatingType(SrcTy));
1592     assert(isScalarFloatingType(DestTy));
1593     assert(DestTy != SrcTy);
1594     static const XmmEmitterRegOp Emitter = {&Assembler::cvtfloat2float,
1595                                             &Assembler::cvtfloat2float};
1596     emitIASRegOpTyXMM(Func, SrcTy, Dest, Src, Emitter);
1597     return;
1598   }
1599   case Dq2ps: {
1600     assert(isVectorIntegerType(SrcTy));
1601     assert(isVectorFloatingType(DestTy));
1602     static const XmmEmitterRegOp Emitter = {&Assembler::cvtdq2ps,
1603                                             &Assembler::cvtdq2ps};
1604     emitIASRegOpTyXMM(Func, DestTy, Dest, Src, Emitter);
1605     return;
1606   }
1607   case Tps2dq: {
1608     assert(isVectorFloatingType(SrcTy));
1609     assert(isVectorIntegerType(DestTy));
1610     static const XmmEmitterRegOp Emitter = {&Assembler::cvttps2dq,
1611                                             &Assembler::cvttps2dq};
1612     emitIASRegOpTyXMM(Func, DestTy, Dest, Src, Emitter);
1613     return;
1614   }
1615   case Ps2dq: {
1616     assert(isVectorFloatingType(SrcTy));
1617     assert(isVectorIntegerType(DestTy));
1618     static const XmmEmitterRegOp Emitter = {&Assembler::cvtps2dq,
1619                                             &Assembler::cvtps2dq};
1620     emitIASRegOpTyXMM(Func, DestTy, Dest, Src, Emitter);
1621     return;
1622   }
1623   }
1624 }
1625 
dump(const Cfg * Func) const1626 void InstX86Cvt::dump(const Cfg *Func) const {
1627   if (!BuildDefs::dump())
1628     return;
1629   Ostream &Str = Func->getContext()->getStrDump();
1630   this->dumpDest(Func);
1631   Str << " = cvt";
1632   if (isTruncating())
1633     Str << "t";
1634   Str << TypeAttributes[this->getSrc(0)->getType()].CvtString << "2"
1635       << TypeAttributes[this->getDest()->getType()].CvtString << " ";
1636   this->dumpSources(Func);
1637 }
1638 
emit(const Cfg * Func) const1639 void InstX86Round::emit(const Cfg *Func) const {
1640   if (!BuildDefs::dump())
1641     return;
1642   Ostream &Str = Func->getContext()->getStrEmit();
1643   assert(this->getSrcSize() == 3);
1644   Str << "\t" << this->Opcode
1645       << TypeAttributes[this->getDest()->getType()].SpSdString << "\t";
1646   this->getSrc(1)->emit(Func);
1647   Str << ", ";
1648   this->getSrc(0)->emit(Func);
1649   Str << ", ";
1650   this->getDest()->emit(Func);
1651 }
1652 
emitIAS(const Cfg * Func) const1653 void InstX86Round::emitIAS(const Cfg *Func) const {
1654   assert(this->getSrcSize() == 2);
1655   assert(getInstructionSet(Func) >= SSE4_1);
1656   const Variable *Dest = this->getDest();
1657   Type Ty = Dest->getType();
1658   static const ThreeOpImmEmitter<XmmRegister, XmmRegister> Emitter = {
1659       &Assembler::round, &Assembler::round};
1660   emitIASThreeOpImmOps<XmmRegister, XmmRegister, RegX8664::getEncodedXmm,
1661                        RegX8664::getEncodedXmm>(Func, Ty, Dest, this->getSrc(0),
1662                                                 this->getSrc(1), Emitter);
1663 }
1664 
emit(const Cfg * Func) const1665 void InstX86Icmp::emit(const Cfg *Func) const {
1666   if (!BuildDefs::dump())
1667     return;
1668   Ostream &Str = Func->getContext()->getStrEmit();
1669   assert(this->getSrcSize() == 2);
1670   Str << "\t"
1671          "cmp"
1672       << this->getWidthString(this->getSrc(0)->getType()) << "\t";
1673   this->getSrc(1)->emit(Func);
1674   Str << ", ";
1675   this->getSrc(0)->emit(Func);
1676 }
1677 
emitIAS(const Cfg * Func) const1678 void InstX86Icmp::emitIAS(const Cfg *Func) const {
1679   assert(this->getSrcSize() == 2);
1680   const Operand *Src0 = this->getSrc(0);
1681   const Operand *Src1 = this->getSrc(1);
1682   Type Ty = Src0->getType();
1683   static const GPREmitterRegOp RegEmitter = {&Assembler::cmp, &Assembler::cmp,
1684                                              &Assembler::cmp};
1685   static const GPREmitterAddrOp AddrEmitter = {&Assembler::cmp,
1686                                                &Assembler::cmp};
1687   if (const auto *SrcVar0 = llvm::dyn_cast<Variable>(Src0)) {
1688     if (SrcVar0->hasReg()) {
1689       emitIASRegOpTyGPR(Func, Ty, SrcVar0, Src1, RegEmitter);
1690       return;
1691     }
1692   }
1693   emitIASAsAddrOpTyGPR(Func, Ty, Src0, Src1, AddrEmitter);
1694 }
1695 
dump(const Cfg * Func) const1696 void InstX86Icmp::dump(const Cfg *Func) const {
1697   if (!BuildDefs::dump())
1698     return;
1699   Ostream &Str = Func->getContext()->getStrDump();
1700   Str << "cmp." << this->getSrc(0)->getType() << " ";
1701   this->dumpSources(Func);
1702 }
1703 
emit(const Cfg * Func) const1704 void InstX86Ucomiss::emit(const Cfg *Func) const {
1705   if (!BuildDefs::dump())
1706     return;
1707   Ostream &Str = Func->getContext()->getStrEmit();
1708   assert(this->getSrcSize() == 2);
1709   Str << "\t"
1710          "ucomi"
1711       << TypeAttributes[this->getSrc(0)->getType()].SdSsString << "\t";
1712   this->getSrc(1)->emit(Func);
1713   Str << ", ";
1714   this->getSrc(0)->emit(Func);
1715 }
1716 
emitIAS(const Cfg * Func) const1717 void InstX86Ucomiss::emitIAS(const Cfg *Func) const {
1718   assert(this->getSrcSize() == 2);
1719   // Currently src0 is always a variable by convention, to avoid having two
1720   // memory operands.
1721   assert(llvm::isa<Variable>(this->getSrc(0)));
1722   const auto *Src0Var = llvm::cast<Variable>(this->getSrc(0));
1723   Type Ty = Src0Var->getType();
1724   static const XmmEmitterRegOp Emitter = {&Assembler::ucomiss,
1725                                           &Assembler::ucomiss};
1726   emitIASRegOpTyXMM(Func, Ty, Src0Var, this->getSrc(1), Emitter);
1727 }
1728 
dump(const Cfg * Func) const1729 void InstX86Ucomiss::dump(const Cfg *Func) const {
1730   if (!BuildDefs::dump())
1731     return;
1732   Ostream &Str = Func->getContext()->getStrDump();
1733   Str << "ucomiss." << this->getSrc(0)->getType() << " ";
1734   this->dumpSources(Func);
1735 }
1736 
emit(const Cfg * Func) const1737 void InstX86UD2::emit(const Cfg *Func) const {
1738   if (!BuildDefs::dump())
1739     return;
1740   Ostream &Str = Func->getContext()->getStrEmit();
1741   assert(this->getSrcSize() == 0);
1742   Str << "\t"
1743          "ud2";
1744 }
1745 
emitIAS(const Cfg * Func) const1746 void InstX86UD2::emitIAS(const Cfg *Func) const {
1747   Assembler *Asm = Func->getAssembler<Assembler>();
1748   Asm->ud2();
1749 }
1750 
dump(const Cfg * Func) const1751 void InstX86UD2::dump(const Cfg *Func) const {
1752   if (!BuildDefs::dump())
1753     return;
1754   Ostream &Str = Func->getContext()->getStrDump();
1755   Str << "ud2";
1756 }
1757 
emit(const Cfg * Func) const1758 void InstX86Int3::emit(const Cfg *Func) const {
1759   if (!BuildDefs::dump())
1760     return;
1761   Ostream &Str = Func->getContext()->getStrEmit();
1762   assert(this->getSrcSize() == 0);
1763   Str << "\t"
1764          "int 3";
1765 }
1766 
emitIAS(const Cfg * Func) const1767 void InstX86Int3::emitIAS(const Cfg *Func) const {
1768   Assembler *Asm = Func->getAssembler<Assembler>();
1769   Asm->int3();
1770 }
1771 
dump(const Cfg * Func) const1772 void InstX86Int3::dump(const Cfg *Func) const {
1773   if (!BuildDefs::dump())
1774     return;
1775   Ostream &Str = Func->getContext()->getStrDump();
1776   Str << "int 3";
1777 }
1778 
emit(const Cfg * Func) const1779 void InstX86Test::emit(const Cfg *Func) const {
1780   if (!BuildDefs::dump())
1781     return;
1782   Ostream &Str = Func->getContext()->getStrEmit();
1783   assert(this->getSrcSize() == 2);
1784   Str << "\t"
1785          "test"
1786       << this->getWidthString(this->getSrc(0)->getType()) << "\t";
1787   this->getSrc(1)->emit(Func);
1788   Str << ", ";
1789   this->getSrc(0)->emit(Func);
1790 }
1791 
emitIAS(const Cfg * Func) const1792 void InstX86Test::emitIAS(const Cfg *Func) const {
1793   assert(this->getSrcSize() == 2);
1794   const Operand *Src0 = this->getSrc(0);
1795   const Operand *Src1 = this->getSrc(1);
1796   Type Ty = Src0->getType();
1797   // The Reg/Addr form of test is not encodeable.
1798   static const GPREmitterRegOp RegEmitter = {&Assembler::test, nullptr,
1799                                              &Assembler::test};
1800   static const GPREmitterAddrOp AddrEmitter = {&Assembler::test,
1801                                                &Assembler::test};
1802   if (const auto *SrcVar0 = llvm::dyn_cast<Variable>(Src0)) {
1803     if (SrcVar0->hasReg()) {
1804       emitIASRegOpTyGPR(Func, Ty, SrcVar0, Src1, RegEmitter);
1805       return;
1806     }
1807   }
1808   emitIASAsAddrOpTyGPR(Func, Ty, Src0, Src1, AddrEmitter);
1809 }
1810 
dump(const Cfg * Func) const1811 void InstX86Test::dump(const Cfg *Func) const {
1812   if (!BuildDefs::dump())
1813     return;
1814   Ostream &Str = Func->getContext()->getStrDump();
1815   Str << "test." << this->getSrc(0)->getType() << " ";
1816   this->dumpSources(Func);
1817 }
1818 
emit(const Cfg * Func) const1819 void InstX86Mfence::emit(const Cfg *Func) const {
1820   if (!BuildDefs::dump())
1821     return;
1822   Ostream &Str = Func->getContext()->getStrEmit();
1823   assert(this->getSrcSize() == 0);
1824   Str << "\t"
1825          "mfence";
1826 }
1827 
emitIAS(const Cfg * Func) const1828 void InstX86Mfence::emitIAS(const Cfg *Func) const {
1829   Assembler *Asm = Func->getAssembler<Assembler>();
1830   Asm->mfence();
1831 }
1832 
dump(const Cfg * Func) const1833 void InstX86Mfence::dump(const Cfg *Func) const {
1834   if (!BuildDefs::dump())
1835     return;
1836   Ostream &Str = Func->getContext()->getStrDump();
1837   Str << "mfence";
1838 }
1839 
emit(const Cfg * Func) const1840 void InstX86Store::emit(const Cfg *Func) const {
1841   if (!BuildDefs::dump())
1842     return;
1843   Ostream &Str = Func->getContext()->getStrEmit();
1844   assert(this->getSrcSize() == 2);
1845   Type Ty = this->getSrc(0)->getType();
1846   Str << "\t"
1847          "mov"
1848       << this->getWidthString(Ty) << TypeAttributes[Ty].SdSsString << "\t";
1849   this->getSrc(0)->emit(Func);
1850   Str << ", ";
1851   this->getSrc(1)->emit(Func);
1852 }
1853 
emitIAS(const Cfg * Func) const1854 void InstX86Store::emitIAS(const Cfg *Func) const {
1855   assert(this->getSrcSize() == 2);
1856   const Operand *Dest = this->getSrc(1);
1857   const Operand *Src = this->getSrc(0);
1858   Type DestTy = Dest->getType();
1859   if (isScalarFloatingType(DestTy)) {
1860     // Src must be a register, since Dest is a Mem operand of some kind.
1861     const auto *SrcVar = llvm::cast<Variable>(Src);
1862     assert(SrcVar->hasReg());
1863     XmmRegister SrcReg = RegX8664::getEncodedXmm(SrcVar->getRegNum());
1864     Assembler *Asm = Func->getAssembler<Assembler>();
1865     auto *Target = InstX86Base::getTarget(Func);
1866     if (const auto *DestVar = llvm::dyn_cast<Variable>(Dest)) {
1867       assert(!DestVar->hasReg());
1868       AsmAddress StackAddr(AsmAddress(DestVar, Target));
1869       Asm->movss(DestTy, StackAddr, SrcReg);
1870     } else {
1871       const auto DestMem = llvm::cast<X86OperandMem>(Dest);
1872       assert(DestMem->getSegmentRegister() == X86OperandMem::DefaultSegment);
1873       Asm->movss(DestTy, AsmAddress(DestMem, Asm, Target), SrcReg);
1874     }
1875     return;
1876   } else {
1877     assert(isScalarIntegerType(DestTy));
1878     static const GPREmitterAddrOp GPRAddrEmitter = {&Assembler::mov,
1879                                                     &Assembler::mov};
1880     emitIASAsAddrOpTyGPR(Func, DestTy, Dest, Src, GPRAddrEmitter);
1881   }
1882 }
1883 
dump(const Cfg * Func) const1884 void InstX86Store::dump(const Cfg *Func) const {
1885   if (!BuildDefs::dump())
1886     return;
1887   Ostream &Str = Func->getContext()->getStrDump();
1888   Str << "mov." << this->getSrc(0)->getType() << " ";
1889   this->getSrc(1)->dump(Func);
1890   Str << ", ";
1891   this->getSrc(0)->dump(Func);
1892 }
1893 
emit(const Cfg * Func) const1894 void InstX86StoreP::emit(const Cfg *Func) const {
1895   if (!BuildDefs::dump())
1896     return;
1897   Ostream &Str = Func->getContext()->getStrEmit();
1898   assert(this->getSrcSize() == 2);
1899   assert(isVectorType(this->getSrc(1)->getType()));
1900   Str << "\t"
1901          "movups\t";
1902   this->getSrc(0)->emit(Func);
1903   Str << ", ";
1904   this->getSrc(1)->emit(Func);
1905 }
1906 
emitIAS(const Cfg * Func) const1907 void InstX86StoreP::emitIAS(const Cfg *Func) const {
1908   Assembler *Asm = Func->getAssembler<Assembler>();
1909   assert(this->getSrcSize() == 2);
1910   const auto *SrcVar = llvm::cast<Variable>(this->getSrc(0));
1911   const auto DestMem = llvm::cast<X86OperandMem>(this->getSrc(1));
1912   assert(DestMem->getSegmentRegister() == X86OperandMem::DefaultSegment);
1913   assert(SrcVar->hasReg());
1914   auto *Target = InstX86Base::getTarget(Func);
1915   Asm->movups(AsmAddress(DestMem, Asm, Target),
1916               RegX8664::getEncodedXmm(SrcVar->getRegNum()));
1917 }
1918 
dump(const Cfg * Func) const1919 void InstX86StoreP::dump(const Cfg *Func) const {
1920   if (!BuildDefs::dump())
1921     return;
1922   Ostream &Str = Func->getContext()->getStrDump();
1923   Str << "storep." << this->getSrc(0)->getType() << " ";
1924   this->getSrc(1)->dump(Func);
1925   Str << ", ";
1926   this->getSrc(0)->dump(Func);
1927 }
1928 
emit(const Cfg * Func) const1929 void InstX86StoreQ::emit(const Cfg *Func) const {
1930   if (!BuildDefs::dump())
1931     return;
1932   Ostream &Str = Func->getContext()->getStrEmit();
1933   assert(this->getSrcSize() == 2);
1934   assert(this->getSrc(1)->getType() == IceType_i64 ||
1935          this->getSrc(1)->getType() == IceType_f64 ||
1936          isVectorType(this->getSrc(1)->getType()));
1937   Str << "\t"
1938          "movq\t";
1939   this->getSrc(0)->emit(Func);
1940   Str << ", ";
1941   this->getSrc(1)->emit(Func);
1942 }
1943 
emitIAS(const Cfg * Func) const1944 void InstX86StoreQ::emitIAS(const Cfg *Func) const {
1945   Assembler *Asm = Func->getAssembler<Assembler>();
1946   assert(this->getSrcSize() == 2);
1947   const auto *SrcVar = llvm::cast<Variable>(this->getSrc(0));
1948   const auto DestMem = llvm::cast<X86OperandMem>(this->getSrc(1));
1949   assert(DestMem->getSegmentRegister() == X86OperandMem::DefaultSegment);
1950   assert(SrcVar->hasReg());
1951   auto *Target = InstX86Base::getTarget(Func);
1952   Asm->movq(AsmAddress(DestMem, Asm, Target),
1953             RegX8664::getEncodedXmm(SrcVar->getRegNum()));
1954 }
1955 
dump(const Cfg * Func) const1956 void InstX86StoreQ::dump(const Cfg *Func) const {
1957   if (!BuildDefs::dump())
1958     return;
1959   Ostream &Str = Func->getContext()->getStrDump();
1960   Str << "storeq." << this->getSrc(0)->getType() << " ";
1961   this->getSrc(1)->dump(Func);
1962   Str << ", ";
1963   this->getSrc(0)->dump(Func);
1964 }
1965 
emit(const Cfg * Func) const1966 void InstX86StoreD::emit(const Cfg *Func) const {
1967   if (!BuildDefs::dump())
1968     return;
1969   Ostream &Str = Func->getContext()->getStrEmit();
1970   assert(this->getSrcSize() == 2);
1971   assert(this->getSrc(1)->getType() == IceType_i64 ||
1972          this->getSrc(1)->getType() == IceType_f64 ||
1973          isVectorType(this->getSrc(1)->getType()));
1974   Str << "\t"
1975          "movd\t";
1976   this->getSrc(0)->emit(Func);
1977   Str << ", ";
1978   this->getSrc(1)->emit(Func);
1979 }
1980 
emitIAS(const Cfg * Func) const1981 void InstX86StoreD::emitIAS(const Cfg *Func) const {
1982   Assembler *Asm = Func->getAssembler<Assembler>();
1983   assert(this->getSrcSize() == 2);
1984   const auto *SrcVar = llvm::cast<Variable>(this->getSrc(0));
1985   const auto DestMem = llvm::cast<X86OperandMem>(this->getSrc(1));
1986   assert(DestMem->getSegmentRegister() == X86OperandMem::DefaultSegment);
1987   assert(SrcVar->hasReg());
1988   auto *Target = InstX86Base::getTarget(Func);
1989   Asm->movd(SrcVar->getType(), AsmAddress(DestMem, Asm, Target),
1990             RegX8664::getEncodedXmm(SrcVar->getRegNum()));
1991 }
1992 
dump(const Cfg * Func) const1993 void InstX86StoreD::dump(const Cfg *Func) const {
1994   if (!BuildDefs::dump())
1995     return;
1996   Ostream &Str = Func->getContext()->getStrDump();
1997   Str << "stored." << this->getSrc(0)->getType() << " ";
1998   this->getSrc(1)->dump(Func);
1999   Str << ", ";
2000   this->getSrc(0)->dump(Func);
2001 }
2002 
emit(const Cfg * Func) const2003 void InstX86Lea::emit(const Cfg *Func) const {
2004   if (!BuildDefs::dump())
2005     return;
2006   if (auto *Add = this->deoptToAddOrNull(Func)) {
2007     Add->emit(Func);
2008     return;
2009   }
2010 
2011   Ostream &Str = Func->getContext()->getStrEmit();
2012   assert(this->getSrcSize() == 1);
2013   assert(this->getDest()->hasReg());
2014   Str << "\t"
2015          "lea"
2016       << this->getWidthString(this->getDest()->getType()) << "\t";
2017   Operand *Src0 = this->getSrc(0);
2018   if (const auto *Src0Var = llvm::dyn_cast<Variable>(Src0)) {
2019     Type Ty = Src0Var->getType();
2020     // lea on x86-32 doesn't accept mem128 operands, so cast VSrc0 to an
2021     // acceptable type.
2022     Src0Var->asType(Func, isVectorType(Ty) ? IceType_i32 : Ty, RegNumT())
2023         ->emit(Func);
2024   } else {
2025     Src0->emit(Func);
2026   }
2027   Str << ", ";
2028   this->getDest()->emit(Func);
2029 }
2030 
emitIAS(const Cfg * Func) const2031 void InstX86Lea::emitIAS(const Cfg *Func) const {
2032   assert(this->getSrcSize() == 1);
2033   const Variable *Var = this->getDest();
2034   Type Ty = Var->getType();
2035   const Operand *Src = this->getSrc(0);
2036 
2037   if (auto *Add = this->deoptToAddOrNull(Func)) {
2038     Add->emitIAS(Func);
2039     return;
2040   }
2041 
2042   emitIASRegOpTyGPR(Func, Ty, Var, Src, Emitter);
2043 }
2044 
deoptToAddOrNull(const Cfg * Func) const2045 Inst *InstX86Lea::deoptToAddOrNull(const Cfg *Func) const {
2046   // Revert back to Add when the Lea is a 2-address instruction.
2047   // Caller has to emit, this just produces the add instruction.
2048   if (auto *MemOp = llvm::dyn_cast<X86OperandMem>(this->getSrc(0))) {
2049     if (getFlags().getAggressiveLea() &&
2050         MemOp->getBase()->getRegNum() == this->getDest()->getRegNum() &&
2051         MemOp->getIndex() == nullptr && MemOp->getShift() == 0) {
2052       auto *Add = InstX86Add::create(const_cast<Cfg *>(Func), this->getDest(),
2053                                      MemOp->getOffset());
2054       // TODO(manasijm): Remove const_cast by emitting code for add
2055       // directly.
2056       return Add;
2057     }
2058   }
2059   return nullptr;
2060 }
2061 
emit(const Cfg * Func) const2062 void InstX86Mov::emit(const Cfg *Func) const {
2063   if (!BuildDefs::dump())
2064     return;
2065   Ostream &Str = Func->getContext()->getStrEmit();
2066   assert(this->getSrcSize() == 1);
2067   Operand *Src = this->getSrc(0);
2068   Type SrcTy = Src->getType();
2069   Type DestTy = this->getDest()->getType();
2070   if (DestTy == IceType_i64 && llvm::isa<ConstantInteger64>(Src) &&
2071       !Utils::IsInt(32, llvm::cast<ConstantInteger64>(Src)->getValue())) {
2072     Str << "\t"
2073            "movabs"
2074            "\t";
2075   } else {
2076     Str << "\t"
2077            "mov"
2078         << (!isScalarFloatingType(DestTy) ? this->getWidthString(DestTy)
2079                                           : TypeAttributes[DestTy].SdSsString)
2080         << "\t";
2081   }
2082   // For an integer truncation operation, src is wider than dest. In this case,
2083   // we use a mov instruction whose data width matches the narrower dest.
2084   // TODO: This assert disallows usages such as copying a floating
2085   // point value between a vector and a scalar (which movss is used for). Clean
2086   // this up.
2087   assert(InstX86Base::getTarget(Func)->typeWidthInBytesOnStack(DestTy) ==
2088          InstX86Base::getTarget(Func)->typeWidthInBytesOnStack(SrcTy));
2089   const Operand *NewSrc = Src;
2090   if (auto *SrcVar = llvm::dyn_cast<Variable>(Src)) {
2091     RegNumT NewRegNum;
2092     if (SrcVar->hasReg())
2093       NewRegNum = RegX8664::getGprForType(DestTy, SrcVar->getRegNum());
2094     if (SrcTy != DestTy)
2095       NewSrc = SrcVar->asType(Func, DestTy, NewRegNum);
2096   }
2097   NewSrc->emit(Func);
2098   Str << ", ";
2099   this->getDest()->emit(Func);
2100 }
2101 
emitIAS(const Cfg * Func) const2102 void InstX86Mov::emitIAS(const Cfg *Func) const {
2103   assert(this->getSrcSize() == 1);
2104   const Variable *Dest = this->getDest();
2105   const Operand *Src = this->getSrc(0);
2106   Type DestTy = Dest->getType();
2107   Type SrcTy = Src->getType();
2108   // Mov can be used for GPRs or XMM registers. Also, the type does not
2109   // necessarily match (Mov can be used for bitcasts). However, when the type
2110   // does not match, one of the operands must be a register. Thus, the strategy
2111   // is to find out if Src or Dest are a register, then use that register's
2112   // type to decide on which emitter set to use. The emitter set will include
2113   // reg-reg movs, but that case should be unused when the types don't match.
2114   static const XmmEmitterRegOp XmmRegEmitter = {&Assembler::movss,
2115                                                 &Assembler::movss};
2116   static const GPREmitterRegOp GPRRegEmitter = {
2117       &Assembler::mov, &Assembler::mov, &Assembler::mov};
2118   static const GPREmitterAddrOp GPRAddrEmitter = {&Assembler::mov,
2119                                                   &Assembler::mov};
2120   // For an integer truncation operation, src is wider than dest. In this case,
2121   // we use a mov instruction whose data width matches the narrower dest.
2122   // TODO: This assert disallows usages such as copying a floating
2123   // point value between a vector and a scalar (which movss is used for). Clean
2124   // this up.
2125   auto *Target = InstX86Base::getTarget(Func);
2126   assert(Target->typeWidthInBytesOnStack(this->getDest()->getType()) ==
2127          Target->typeWidthInBytesOnStack(Src->getType()));
2128   if (Dest->hasReg()) {
2129     if (isScalarFloatingType(DestTy)) {
2130       emitIASRegOpTyXMM(Func, DestTy, Dest, Src, XmmRegEmitter);
2131       return;
2132     } else {
2133       assert(isScalarIntegerType(DestTy));
2134       // Widen DestTy for truncation (see above note). We should only do this
2135       // when both Src and Dest are integer types.
2136       if (DestTy == IceType_i64) {
2137         if (const auto *C64 = llvm::dyn_cast<ConstantInteger64>(Src)) {
2138           Func->getAssembler<Assembler>()->movabs(
2139               RegX8664::getEncodedGPR(Dest->getRegNum()), C64->getValue());
2140           return;
2141         }
2142       }
2143       if (isScalarIntegerType(SrcTy)) {
2144         SrcTy = DestTy;
2145       }
2146       emitIASRegOpTyGPR(Func, DestTy, Dest, Src, GPRRegEmitter);
2147       return;
2148     }
2149   } else {
2150     // Dest must be Stack and Src *could* be a register. Use Src's type to
2151     // decide on the emitters.
2152     AsmAddress StackAddr(AsmAddress(Dest, Target));
2153     if (isScalarFloatingType(SrcTy)) {
2154       // Src must be a register.
2155       const auto *SrcVar = llvm::cast<Variable>(Src);
2156       assert(SrcVar->hasReg());
2157       Assembler *Asm = Func->getAssembler<Assembler>();
2158       Asm->movss(SrcTy, StackAddr,
2159                  RegX8664::getEncodedXmm(SrcVar->getRegNum()));
2160       return;
2161     } else if (isVectorType(SrcTy)) {
2162       // Src must be a register
2163       const auto *SrcVar = llvm::cast<Variable>(Src);
2164       assert(SrcVar->hasReg());
2165       Assembler *Asm = Func->getAssembler<Assembler>();
2166       Asm->movups(StackAddr, RegX8664::getEncodedXmm(SrcVar->getRegNum()));
2167     } else {
2168       // Src can be a register or immediate.
2169       assert(isScalarIntegerType(SrcTy));
2170       emitIASAddrOpTyGPR(Func, SrcTy, StackAddr, Src, GPRAddrEmitter);
2171       return;
2172     }
2173     return;
2174   }
2175 }
2176 
emit(const Cfg * Func) const2177 void InstX86Movd::emit(const Cfg *Func) const {
2178   if (!BuildDefs::dump())
2179     return;
2180   assert(this->getSrcSize() == 1);
2181   Variable *Dest = this->getDest();
2182   Operand *Src = this->getSrc(0);
2183 
2184   if (Dest->getType() == IceType_i64 || Src->getType() == IceType_i64) {
2185     assert(Dest->getType() == IceType_f64 || Src->getType() == IceType_f64);
2186     assert(Dest->getType() != Src->getType());
2187     Ostream &Str = Func->getContext()->getStrEmit();
2188     Str << "\t"
2189            "movq"
2190            "\t";
2191     Src->emit(Func);
2192     Str << ", ";
2193     Dest->emit(Func);
2194     return;
2195   }
2196 
2197   InstX86BaseUnaryopXmm<InstX86Base::Movd>::emit(Func);
2198 }
2199 
emitIAS(const Cfg * Func) const2200 void InstX86Movd::emitIAS(const Cfg *Func) const {
2201   Assembler *Asm = Func->getAssembler<Assembler>();
2202   assert(this->getSrcSize() == 1);
2203   const Variable *Dest = this->getDest();
2204   auto *Target = InstX86Base::getTarget(Func);
2205   // For insert/extract element (one of Src/Dest is an Xmm vector and the other
2206   // is an int type).
2207   if (const auto *SrcVar = llvm::dyn_cast<Variable>(this->getSrc(0))) {
2208     if (SrcVar->getType() == IceType_i32 || SrcVar->getType() == IceType_i64) {
2209       assert(isVectorType(Dest->getType()) ||
2210              (isScalarFloatingType(Dest->getType()) &&
2211               typeWidthInBytes(SrcVar->getType()) ==
2212                   typeWidthInBytes(Dest->getType())));
2213       assert(Dest->hasReg());
2214       XmmRegister DestReg = RegX8664::getEncodedXmm(Dest->getRegNum());
2215       if (SrcVar->hasReg()) {
2216         Asm->movd(SrcVar->getType(), DestReg,
2217                   RegX8664::getEncodedGPR(SrcVar->getRegNum()));
2218       } else {
2219         AsmAddress StackAddr(AsmAddress(SrcVar, Target));
2220         Asm->movd(SrcVar->getType(), DestReg, StackAddr);
2221       }
2222     } else {
2223       assert(isVectorType(SrcVar->getType()) ||
2224              (isScalarFloatingType(SrcVar->getType()) &&
2225               typeWidthInBytes(SrcVar->getType()) ==
2226                   typeWidthInBytes(Dest->getType())));
2227       assert(SrcVar->hasReg());
2228       assert(Dest->getType() == IceType_i32 || Dest->getType() == IceType_i64);
2229       XmmRegister SrcReg = RegX8664::getEncodedXmm(SrcVar->getRegNum());
2230       if (Dest->hasReg()) {
2231         Asm->movd(Dest->getType(), RegX8664::getEncodedGPR(Dest->getRegNum()),
2232                   SrcReg);
2233       } else {
2234         AsmAddress StackAddr(AsmAddress(Dest, Target));
2235         Asm->movd(Dest->getType(), StackAddr, SrcReg);
2236       }
2237     }
2238   } else {
2239     assert(Dest->hasReg());
2240     XmmRegister DestReg = RegX8664::getEncodedXmm(Dest->getRegNum());
2241     auto *Mem = llvm::cast<X86OperandMem>(this->getSrc(0));
2242     Asm->movd(Mem->getType(), DestReg, AsmAddress(Mem, Asm, Target));
2243   }
2244 }
2245 
emit(const Cfg * Func) const2246 void InstX86Movp::emit(const Cfg *Func) const {
2247   if (!BuildDefs::dump())
2248     return;
2249   // TODO(wala,stichnot): movups works with all vector operands, but there
2250   // exist other instructions (movaps, movdqa, movdqu) that may perform better,
2251   // depending on the data type and alignment of the operands.
2252   Ostream &Str = Func->getContext()->getStrEmit();
2253   assert(this->getSrcSize() == 1);
2254   Str << "\t"
2255          "movups\t";
2256   this->getSrc(0)->emit(Func);
2257   Str << ", ";
2258   this->getDest()->emit(Func);
2259 }
2260 
emitIAS(const Cfg * Func) const2261 void InstX86Movp::emitIAS(const Cfg *Func) const {
2262   assert(this->getSrcSize() == 1);
2263   assert(isVectorType(this->getDest()->getType()));
2264   const Variable *Dest = this->getDest();
2265   const Operand *Src = this->getSrc(0);
2266   static const XmmEmitterMovOps Emitter = {
2267       &Assembler::movups, &Assembler::movups, &Assembler::movups};
2268   emitIASMovlikeXMM(Func, Dest, Src, Emitter);
2269 }
2270 
emit(const Cfg * Func) const2271 void InstX86Movq::emit(const Cfg *Func) const {
2272   if (!BuildDefs::dump())
2273     return;
2274   Ostream &Str = Func->getContext()->getStrEmit();
2275   assert(this->getSrcSize() == 1);
2276   assert(this->getDest()->getType() == IceType_i64 ||
2277          this->getDest()->getType() == IceType_f64);
2278   Str << "\t"
2279          "movq"
2280          "\t";
2281   this->getSrc(0)->emit(Func);
2282   Str << ", ";
2283   this->getDest()->emit(Func);
2284 }
2285 
emitIAS(const Cfg * Func) const2286 void InstX86Movq::emitIAS(const Cfg *Func) const {
2287   assert(this->getSrcSize() == 1);
2288   assert(this->getDest()->getType() == IceType_i64 ||
2289          this->getDest()->getType() == IceType_f64 ||
2290          isVectorType(this->getDest()->getType()));
2291   const Variable *Dest = this->getDest();
2292   const Operand *Src = this->getSrc(0);
2293   static const XmmEmitterMovOps Emitter = {&Assembler::movq, &Assembler::movq,
2294                                            &Assembler::movq};
2295   emitIASMovlikeXMM(Func, Dest, Src, Emitter);
2296 }
2297 
emitIAS(const Cfg * Func) const2298 void InstX86MovssRegs::emitIAS(const Cfg *Func) const {
2299   // This is Binop variant is only intended to be used for reg-reg moves where
2300   // part of the Dest register is untouched.
2301   assert(this->getSrcSize() == 2);
2302   const Variable *Dest = this->getDest();
2303   assert(Dest == this->getSrc(0));
2304   const auto *SrcVar = llvm::cast<Variable>(this->getSrc(1));
2305   assert(Dest->hasReg() && SrcVar->hasReg());
2306   Assembler *Asm = Func->getAssembler<Assembler>();
2307   Asm->movss(IceType_f32, RegX8664::getEncodedXmm(Dest->getRegNum()),
2308              RegX8664::getEncodedXmm(SrcVar->getRegNum()));
2309 }
2310 
emitIAS(const Cfg * Func) const2311 void InstX86Movsx::emitIAS(const Cfg *Func) const {
2312   assert(this->getSrcSize() == 1);
2313   const Variable *Dest = this->getDest();
2314   const Operand *Src = this->getSrc(0);
2315   // Dest must be a > 8-bit register, but Src can be 8-bit. In practice we just
2316   // use the full register for Dest to avoid having an OperandSizeOverride
2317   // prefix. It also allows us to only dispatch on SrcTy.
2318   Type SrcTy = Src->getType();
2319   assert(typeWidthInBytes(Dest->getType()) > 1);
2320   assert(typeWidthInBytes(Dest->getType()) > typeWidthInBytes(SrcTy));
2321   emitIASRegOpTyGPR<false, true>(Func, SrcTy, Dest, Src, this->Emitter);
2322 }
2323 
mayBeElided(const Variable * Dest,const Operand * SrcOpnd) const2324 bool InstX86Movzx::mayBeElided(const Variable *Dest,
2325                                const Operand *SrcOpnd) const {
2326   const auto *Src = llvm::dyn_cast<Variable>(SrcOpnd);
2327 
2328   // Src is not a Variable, so it does not have a register. Movzx can't be
2329   // elided.
2330   if (Src == nullptr)
2331     return false;
2332 
2333   // Movzx to/from memory can't be elided.
2334   if (!Src->hasReg() || !Dest->hasReg())
2335     return false;
2336 
2337   // Reg/reg move with different source and dest can't be elided.
2338   if (RegX8664::getEncodedGPR(Src->getRegNum()) !=
2339       RegX8664::getEncodedGPR(Dest->getRegNum()))
2340     return false;
2341 
2342   // A must-keep movzx 32- to 64-bit is sometimes needed in x86-64 sandboxing.
2343   return !MustKeep;
2344 }
2345 
emit(const Cfg * Func) const2346 void InstX86Movzx::emit(const Cfg *Func) const {
2347   if (!BuildDefs::dump())
2348     return;
2349   // There's no movzx %eXX, %rXX. To zero extend 32- to 64-bits, we emit a
2350   // mov %eXX, %eXX. The processor will still do a movzx[bw]q.
2351   assert(this->getSrcSize() == 1);
2352   const Operand *Src = this->getSrc(0);
2353   const Variable *Dest = this->Dest;
2354   if (Src->getType() == IceType_i32 && Dest->getType() == IceType_i64) {
2355     Ostream &Str = Func->getContext()->getStrEmit();
2356     if (mayBeElided(Dest, Src)) {
2357       Str << "\t/* elided movzx */";
2358     } else {
2359       Str << "\t"
2360              "mov"
2361              "\t";
2362       Src->emit(Func);
2363       Str << ", ";
2364       Dest->asType(Func, IceType_i32,
2365                    RegX8664::getGprForType(IceType_i32, Dest->getRegNum()))
2366           ->emit(Func);
2367       Str << " /* movzx */";
2368     }
2369     return;
2370   }
2371   InstX86BaseUnaryopGPR<InstX86Base::Movzx>::emit(Func);
2372 }
2373 
emitIAS(const Cfg * Func) const2374 void InstX86Movzx::emitIAS(const Cfg *Func) const {
2375   assert(this->getSrcSize() == 1);
2376   const Variable *Dest = this->getDest();
2377   const Operand *Src = this->getSrc(0);
2378   Type SrcTy = Src->getType();
2379   assert(typeWidthInBytes(Dest->getType()) > 1);
2380   assert(typeWidthInBytes(Dest->getType()) > typeWidthInBytes(SrcTy));
2381   if (Src->getType() == IceType_i32 && Dest->getType() == IceType_i64 &&
2382       mayBeElided(Dest, Src)) {
2383     return;
2384   }
2385   emitIASRegOpTyGPR<false, true>(Func, SrcTy, Dest, Src, this->Emitter);
2386 }
2387 
emit(const Cfg * Func) const2388 void InstX86Nop::emit(const Cfg *Func) const {
2389   if (!BuildDefs::dump())
2390     return;
2391   Ostream &Str = Func->getContext()->getStrEmit();
2392   // TODO: Emit the right code for each variant.
2393   Str << "\t"
2394          "nop\t/* variant = "
2395       << Variant << " */";
2396 }
2397 
emitIAS(const Cfg * Func) const2398 void InstX86Nop::emitIAS(const Cfg *Func) const {
2399   Assembler *Asm = Func->getAssembler<Assembler>();
2400   // TODO: Emit the right code for the variant.
2401   Asm->nop();
2402 }
2403 
dump(const Cfg * Func) const2404 void InstX86Nop::dump(const Cfg *Func) const {
2405   if (!BuildDefs::dump())
2406     return;
2407   Ostream &Str = Func->getContext()->getStrDump();
2408   Str << "nop (variant = " << Variant << ")";
2409 }
2410 
emit(const Cfg * Func) const2411 void InstX86Pextr::emit(const Cfg *Func) const {
2412   if (!BuildDefs::dump())
2413     return;
2414   Ostream &Str = Func->getContext()->getStrEmit();
2415   assert(this->getSrcSize() == 2);
2416   // pextrb and pextrd are SSE4.1 instructions.
2417   Str << "\t" << this->Opcode
2418       << TypeAttributes[this->getSrc(0)->getType()].IntegralString << "\t";
2419   this->getSrc(1)->emit(Func);
2420   Str << ", ";
2421   this->getSrc(0)->emit(Func);
2422   Str << ", ";
2423   Variable *Dest = this->getDest();
2424   // pextrw must take a register dest. There is an SSE4.1 version that takes a
2425   // memory dest, but we aren't using it. For uniformity, just restrict them
2426   // all to have a register dest for now.
2427   assert(Dest->hasReg());
2428   Dest->asType(Func, IceType_i32, Dest->getRegNum())->emit(Func);
2429 }
2430 
emitIAS(const Cfg * Func) const2431 void InstX86Pextr::emitIAS(const Cfg *Func) const {
2432   assert(this->getSrcSize() == 2);
2433   // pextrb and pextrd are SSE4.1 instructions.
2434   const Variable *Dest = this->getDest();
2435   Type DispatchTy = getInVectorElementType(this->getSrc(0)->getType());
2436   // pextrw must take a register dest. There is an SSE4.1 version that takes a
2437   // memory dest, but we aren't using it. For uniformity, just restrict them
2438   // all to have a register dest for now.
2439   assert(Dest->hasReg());
2440   // pextrw's Src(0) must be a register (both SSE4.1 and SSE2).
2441   assert(llvm::cast<Variable>(this->getSrc(0))->hasReg());
2442   static const ThreeOpImmEmitter<GPRRegister, XmmRegister> Emitter = {
2443       &Assembler::pextr, nullptr};
2444   emitIASThreeOpImmOps<GPRRegister, XmmRegister, RegX8664::getEncodedGPR,
2445                        RegX8664::getEncodedXmm>(
2446       Func, DispatchTy, Dest, this->getSrc(0), this->getSrc(1), Emitter);
2447 }
2448 
emit(const Cfg * Func) const2449 void InstX86Pinsr::emit(const Cfg *Func) const {
2450   if (!BuildDefs::dump())
2451     return;
2452   Ostream &Str = Func->getContext()->getStrEmit();
2453   assert(this->getSrcSize() == 3);
2454   Str << "\t" << this->Opcode
2455       << TypeAttributes[this->getDest()->getType()].IntegralString << "\t";
2456   this->getSrc(2)->emit(Func);
2457   Str << ", ";
2458   Operand *Src1 = this->getSrc(1);
2459   if (const auto *Src1Var = llvm::dyn_cast<Variable>(Src1)) {
2460     // If src1 is a register, it should always be r32.
2461     if (Src1Var->hasReg()) {
2462       const auto NewRegNum = RegX8664::getBaseReg(Src1Var->getRegNum());
2463       const Variable *NewSrc = Src1Var->asType(Func, IceType_i32, NewRegNum);
2464       NewSrc->emit(Func);
2465     } else {
2466       Src1Var->emit(Func);
2467     }
2468   } else {
2469     Src1->emit(Func);
2470   }
2471   Str << ", ";
2472   this->getDest()->emit(Func);
2473 }
2474 
emitIAS(const Cfg * Func) const2475 void InstX86Pinsr::emitIAS(const Cfg *Func) const {
2476   assert(this->getSrcSize() == 3);
2477   assert(this->getDest() == this->getSrc(0));
2478   // pinsrb and pinsrd are SSE4.1 instructions.
2479   const Operand *Src0 = this->getSrc(1);
2480   Type DispatchTy = Src0->getType();
2481   // If src1 is a register, it should always be r32 (this should fall out from
2482   // the encodings for ByteRegs overlapping the encodings for r32), but we have
2483   // to make sure the register allocator didn't choose an 8-bit high register
2484   // like "ah".
2485   if (BuildDefs::asserts()) {
2486     if (auto *Src0Var = llvm::dyn_cast<Variable>(Src0)) {
2487       if (Src0Var->hasReg()) {
2488         const auto RegNum = Src0Var->getRegNum();
2489         const auto BaseRegNum = RegX8664::getBaseReg(RegNum);
2490         (void)BaseRegNum;
2491         assert(RegX8664::getEncodedGPR(RegNum) ==
2492                RegX8664::getEncodedGPR(BaseRegNum));
2493       }
2494     }
2495   }
2496   static const ThreeOpImmEmitter<XmmRegister, GPRRegister> Emitter = {
2497       &Assembler::pinsr, &Assembler::pinsr};
2498   emitIASThreeOpImmOps<XmmRegister, GPRRegister, RegX8664::getEncodedXmm,
2499                        RegX8664::getEncodedGPR>(
2500       Func, DispatchTy, this->getDest(), Src0, this->getSrc(2), Emitter);
2501 }
2502 
emitIAS(const Cfg * Func) const2503 void InstX86Pshufd::emitIAS(const Cfg *Func) const {
2504   assert(this->getSrcSize() == 2);
2505   const Variable *Dest = this->getDest();
2506   Type Ty = Dest->getType();
2507   static const ThreeOpImmEmitter<XmmRegister, XmmRegister> Emitter = {
2508       &Assembler::pshufd, &Assembler::pshufd};
2509   emitIASThreeOpImmOps<XmmRegister, XmmRegister, RegX8664::getEncodedXmm,
2510                        RegX8664::getEncodedXmm>(Func, Ty, Dest, this->getSrc(0),
2511                                                 this->getSrc(1), Emitter);
2512 }
2513 
emitIAS(const Cfg * Func) const2514 void InstX86Shufps::emitIAS(const Cfg *Func) const {
2515   assert(this->getSrcSize() == 3);
2516   const Variable *Dest = this->getDest();
2517   assert(Dest == this->getSrc(0));
2518   Type Ty = Dest->getType();
2519   static const ThreeOpImmEmitter<XmmRegister, XmmRegister> Emitter = {
2520       &Assembler::shufps, &Assembler::shufps};
2521   emitIASThreeOpImmOps<XmmRegister, XmmRegister, RegX8664::getEncodedXmm,
2522                        RegX8664::getEncodedXmm>(Func, Ty, Dest, this->getSrc(1),
2523                                                 this->getSrc(2), Emitter);
2524 }
2525 
emit(const Cfg * Func) const2526 void InstX86Pop::emit(const Cfg *Func) const {
2527   if (!BuildDefs::dump())
2528     return;
2529   Ostream &Str = Func->getContext()->getStrEmit();
2530   assert(this->getSrcSize() == 0);
2531   Str << "\t"
2532          "pop\t";
2533   this->getDest()->emit(Func);
2534 }
2535 
emitIAS(const Cfg * Func) const2536 void InstX86Pop::emitIAS(const Cfg *Func) const {
2537   assert(this->getSrcSize() == 0);
2538   Assembler *Asm = Func->getAssembler<Assembler>();
2539   if (this->getDest()->hasReg()) {
2540     Asm->popl(RegX8664::getEncodedGPR(this->getDest()->getRegNum()));
2541   } else {
2542     auto *Target = InstX86Base::getTarget(Func);
2543     Asm->popl(AsmAddress(this->getDest(), Target));
2544   }
2545 }
2546 
dump(const Cfg * Func) const2547 void InstX86Pop::dump(const Cfg *Func) const {
2548   if (!BuildDefs::dump())
2549     return;
2550   Ostream &Str = Func->getContext()->getStrDump();
2551   this->dumpDest(Func);
2552   Str << " = pop." << this->getDest()->getType() << " ";
2553 }
2554 
emit(const Cfg * Func) const2555 void InstX86Push::emit(const Cfg *Func) const {
2556   if (!BuildDefs::dump())
2557     return;
2558   Ostream &Str = Func->getContext()->getStrEmit();
2559   Str << "\t"
2560          "push"
2561          "\t";
2562   assert(this->getSrcSize() == 1);
2563   const Operand *Src = this->getSrc(0);
2564   Src->emit(Func);
2565 }
2566 
emitIAS(const Cfg * Func) const2567 void InstX86Push::emitIAS(const Cfg *Func) const {
2568   Assembler *Asm = Func->getAssembler<Assembler>();
2569 
2570   assert(this->getSrcSize() == 1);
2571   const Operand *Src = this->getSrc(0);
2572 
2573   if (const auto *Var = llvm::dyn_cast<Variable>(Src)) {
2574     Asm->pushl(RegX8664::getEncodedGPR(Var->getRegNum()));
2575   } else if (const auto *Const32 = llvm::dyn_cast<ConstantInteger32>(Src)) {
2576     Asm->pushl(AssemblerImmediate(Const32->getValue()));
2577   } else if (auto *CR = llvm::dyn_cast<ConstantRelocatable>(Src)) {
2578     Asm->pushl(CR);
2579   } else {
2580     llvm_unreachable("Unexpected operand type");
2581   }
2582 }
2583 
dump(const Cfg * Func) const2584 void InstX86Push::dump(const Cfg *Func) const {
2585   if (!BuildDefs::dump())
2586     return;
2587   Ostream &Str = Func->getContext()->getStrDump();
2588   Str << "push." << this->getSrc(0)->getType() << " ";
2589   this->dumpSources(Func);
2590 }
2591 
emit(const Cfg * Func) const2592 void InstX86Ret::emit(const Cfg *Func) const {
2593   if (!BuildDefs::dump())
2594     return;
2595   Ostream &Str = Func->getContext()->getStrEmit();
2596   Str << "\t"
2597          "ret";
2598 }
2599 
emitIAS(const Cfg * Func) const2600 void InstX86Ret::emitIAS(const Cfg *Func) const {
2601   Assembler *Asm = Func->getAssembler<Assembler>();
2602   Asm->ret();
2603 }
2604 
dump(const Cfg * Func) const2605 void InstX86Ret::dump(const Cfg *Func) const {
2606   if (!BuildDefs::dump())
2607     return;
2608   Ostream &Str = Func->getContext()->getStrDump();
2609   Type Ty =
2610       (this->getSrcSize() == 0 ? IceType_void : this->getSrc(0)->getType());
2611   Str << "ret." << Ty << " ";
2612   this->dumpSources(Func);
2613 }
2614 
emit(const Cfg * Func) const2615 void InstX86Setcc::emit(const Cfg *Func) const {
2616   if (!BuildDefs::dump())
2617     return;
2618   Ostream &Str = Func->getContext()->getStrEmit();
2619   Str << "\t"
2620          "set"
2621       << InstBrAttributes[Condition].DisplayString << "\t";
2622   this->Dest->emit(Func);
2623 }
2624 
emitIAS(const Cfg * Func) const2625 void InstX86Setcc::emitIAS(const Cfg *Func) const {
2626   assert(Condition != Cond::Br_None);
2627   assert(this->getDest()->getType() == IceType_i1);
2628   assert(this->getSrcSize() == 0);
2629   Assembler *Asm = Func->getAssembler<Assembler>();
2630   auto *Target = InstX86Base::getTarget(Func);
2631   if (this->getDest()->hasReg())
2632     Asm->setcc(Condition,
2633                RegX8664::getEncodedByteReg(this->getDest()->getRegNum()));
2634   else
2635     Asm->setcc(Condition, AsmAddress(this->getDest(), Target));
2636   return;
2637 }
2638 
dump(const Cfg * Func) const2639 void InstX86Setcc::dump(const Cfg *Func) const {
2640   if (!BuildDefs::dump())
2641     return;
2642   Ostream &Str = Func->getContext()->getStrDump();
2643   Str << "setcc." << InstBrAttributes[Condition].DisplayString << " ";
2644   this->dumpDest(Func);
2645 }
2646 
emit(const Cfg * Func) const2647 void InstX86Xadd::emit(const Cfg *Func) const {
2648   if (!BuildDefs::dump())
2649     return;
2650   Ostream &Str = Func->getContext()->getStrEmit();
2651   if (this->Locked) {
2652     Str << "\t"
2653            "lock";
2654   }
2655   Str << "\t"
2656          "xadd"
2657       << this->getWidthString(this->getSrc(0)->getType()) << "\t";
2658   this->getSrc(1)->emit(Func);
2659   Str << ", ";
2660   this->getSrc(0)->emit(Func);
2661 }
2662 
emitIAS(const Cfg * Func) const2663 void InstX86Xadd::emitIAS(const Cfg *Func) const {
2664   assert(this->getSrcSize() == 2);
2665   Assembler *Asm = Func->getAssembler<Assembler>();
2666   Type Ty = this->getSrc(0)->getType();
2667   const auto Mem = llvm::cast<X86OperandMem>(this->getSrc(0));
2668   assert(Mem->getSegmentRegister() == X86OperandMem::DefaultSegment);
2669   auto *Target = InstX86Base::getTarget(Func);
2670   const AsmAddress Addr = AsmAddress(Mem, Asm, Target);
2671   const auto *VarReg = llvm::cast<Variable>(this->getSrc(1));
2672   assert(VarReg->hasReg());
2673   const GPRRegister Reg = RegX8664::getEncodedGPR(VarReg->getRegNum());
2674   Asm->xadd(Ty, Addr, Reg, this->Locked);
2675 }
2676 
dump(const Cfg * Func) const2677 void InstX86Xadd::dump(const Cfg *Func) const {
2678   if (!BuildDefs::dump())
2679     return;
2680   Ostream &Str = Func->getContext()->getStrDump();
2681   if (this->Locked) {
2682     Str << "lock ";
2683   }
2684   Type Ty = this->getSrc(0)->getType();
2685   Str << "xadd." << Ty << " ";
2686   this->dumpSources(Func);
2687 }
2688 
emit(const Cfg * Func) const2689 void InstX86Xchg::emit(const Cfg *Func) const {
2690   if (!BuildDefs::dump())
2691     return;
2692   Ostream &Str = Func->getContext()->getStrEmit();
2693   Str << "\t"
2694          "xchg"
2695       << this->getWidthString(this->getSrc(0)->getType()) << "\t";
2696   this->getSrc(1)->emit(Func);
2697   Str << ", ";
2698   this->getSrc(0)->emit(Func);
2699 }
2700 
emitIAS(const Cfg * Func) const2701 void InstX86Xchg::emitIAS(const Cfg *Func) const {
2702   assert(this->getSrcSize() == 2);
2703   Assembler *Asm = Func->getAssembler<Assembler>();
2704   Type Ty = this->getSrc(0)->getType();
2705   const auto *VarReg1 = llvm::cast<Variable>(this->getSrc(1));
2706   assert(VarReg1->hasReg());
2707   const GPRRegister Reg1 = RegX8664::getEncodedGPR(VarReg1->getRegNum());
2708 
2709   if (const auto *VarReg0 = llvm::dyn_cast<Variable>(this->getSrc(0))) {
2710     assert(VarReg0->hasReg());
2711     const GPRRegister Reg0 = RegX8664::getEncodedGPR(VarReg0->getRegNum());
2712     Asm->xchg(Ty, Reg0, Reg1);
2713     return;
2714   }
2715 
2716   const auto *Mem = llvm::cast<X86OperandMem>(this->getSrc(0));
2717   assert(Mem->getSegmentRegister() == X86OperandMem::DefaultSegment);
2718   auto *Target = InstX86Base::getTarget(Func);
2719   const AsmAddress Addr = AsmAddress(Mem, Asm, Target);
2720   Asm->xchg(Ty, Addr, Reg1);
2721 }
2722 
dump(const Cfg * Func) const2723 void InstX86Xchg::dump(const Cfg *Func) const {
2724   if (!BuildDefs::dump())
2725     return;
2726   Ostream &Str = Func->getContext()->getStrDump();
2727   Type Ty = this->getSrc(0)->getType();
2728   Str << "xchg." << Ty << " ";
2729   this->dumpSources(Func);
2730 }
2731 
emit(const Cfg * Func) const2732 void InstX86IacaStart::emit(const Cfg *Func) const {
2733   if (!BuildDefs::dump())
2734     return;
2735   Ostream &Str = Func->getContext()->getStrEmit();
2736   Str << "\t# IACA_START\n"
2737          "\t.byte 0x0F, 0x0B\n"
2738          "\t"
2739          "movl\t$111, %ebx\n"
2740          "\t.byte 0x64, 0x67, 0x90";
2741 }
2742 
emitIAS(const Cfg * Func) const2743 void InstX86IacaStart::emitIAS(const Cfg *Func) const {
2744   Assembler *Asm = Func->getAssembler<Assembler>();
2745   Asm->iaca_start();
2746 }
2747 
dump(const Cfg * Func) const2748 void InstX86IacaStart::dump(const Cfg *Func) const {
2749   if (!BuildDefs::dump())
2750     return;
2751   Ostream &Str = Func->getContext()->getStrDump();
2752   Str << "IACA_START";
2753 }
2754 
emit(const Cfg * Func) const2755 void InstX86IacaEnd::emit(const Cfg *Func) const {
2756   if (!BuildDefs::dump())
2757     return;
2758   Ostream &Str = Func->getContext()->getStrEmit();
2759   Str << "\t# IACA_END\n"
2760          "\t"
2761          "movl\t$222, %ebx\n"
2762          "\t.byte 0x64, 0x67, 0x90\n"
2763          "\t.byte 0x0F, 0x0B";
2764 }
2765 
emitIAS(const Cfg * Func) const2766 void InstX86IacaEnd::emitIAS(const Cfg *Func) const {
2767   Assembler *Asm = Func->getAssembler<Assembler>();
2768   Asm->iaca_end();
2769 }
2770 
dump(const Cfg * Func) const2771 void InstX86IacaEnd::dump(const Cfg *Func) const {
2772   if (!BuildDefs::dump())
2773     return;
2774   Ostream &Str = Func->getContext()->getStrDump();
2775   Str << "IACA_END";
2776 }
2777 
dump(const Cfg *,Ostream & Str) const2778 void X86Operand::dump(const Cfg *, Ostream &Str) const {
2779   if (BuildDefs::dump())
2780     Str << "<OperandX8664>";
2781 }
2782 
X86OperandMem(Cfg * Func,Type Ty,Variable * Base,Constant * Offset,Variable * Index,uint16_t Shift,bool IsRebased)2783 X86OperandMem::X86OperandMem(Cfg *Func, Type Ty, Variable *Base,
2784                              Constant *Offset, Variable *Index, uint16_t Shift,
2785                              bool IsRebased)
2786     : X86Operand(kMem, Ty), Base(Base), Offset(Offset), Index(Index),
2787       Shift(Shift), IsRebased(IsRebased) {
2788   assert(Shift <= 3);
2789   Vars = nullptr;
2790   NumVars = 0;
2791   if (Base)
2792     ++NumVars;
2793   if (Index)
2794     ++NumVars;
2795   if (NumVars) {
2796     Vars = Func->allocateArrayOf<Variable *>(NumVars);
2797     SizeT I = 0;
2798     if (Base)
2799       Vars[I++] = Base;
2800     if (Index)
2801       Vars[I++] = Index;
2802     assert(I == NumVars);
2803   }
2804 }
2805 
emit(const Cfg * Func) const2806 void X86OperandMem::emit(const Cfg *Func) const {
2807   if (!BuildDefs::dump())
2808     return;
2809   const auto *Target = Func->getTarget();
2810   // If the base is rematerializable, we need to replace it with the correct
2811   // physical register (stack or base pointer), and update the Offset.
2812   int32_t Disp = 0;
2813   if (getBase() && getBase()->isRematerializable()) {
2814     Disp += getBase()->getRematerializableOffset(Target);
2815   }
2816   // The index should never be rematerializable.  But if we ever allow it, then
2817   // we should make sure the rematerialization offset is shifted by the Shift
2818   // value.
2819   if (getIndex())
2820     assert(!getIndex()->isRematerializable());
2821   Ostream &Str = Func->getContext()->getStrEmit();
2822   // Emit as Offset(Base,Index,1<<Shift). Offset is emitted without the leading
2823   // '$'. Omit the (Base,Index,1<<Shift) part if Base==nullptr.
2824   if (getOffset() == nullptr && Disp == 0) {
2825     // No offset, emit nothing.
2826   } else if (getOffset() == nullptr && Disp != 0) {
2827     Str << Disp;
2828   } else if (const auto *CI = llvm::dyn_cast<ConstantInteger32>(Offset)) {
2829     if (Base == nullptr || CI->getValue() || Disp != 0)
2830       // Emit a non-zero offset without a leading '$'.
2831       Str << CI->getValue() + Disp;
2832   } else if (const auto *CR = llvm::dyn_cast<ConstantRelocatable>(Offset)) {
2833     // TODO(sehr): ConstantRelocatable still needs updating for
2834     // rematerializable base/index and Disp.
2835     assert(Disp == 0);
2836     CR->emitWithoutPrefix(Target);
2837     if (Base == nullptr && Index == nullptr) {
2838       // rip-relative addressing.
2839       Str << "(%rip)";
2840     }
2841   } else {
2842     llvm_unreachable("Invalid offset type for x86 mem operand");
2843   }
2844 
2845   if (Base == nullptr && Index == nullptr) {
2846     return;
2847   }
2848 
2849   Str << "(";
2850   if (Base != nullptr) {
2851     const Variable *B = Base;
2852     // TODO(jpp): stop abusing the operand's type to identify LEAs.
2853     const Type MemType = getType();
2854     if (Base->getType() != IceType_i32 && MemType != IceType_void &&
2855         !isVectorType(MemType)) {
2856       // X86-64 is ILP32, but %rsp and %rbp are accessed as 64-bit registers.
2857       // For filetype=asm, they need to be emitted as their 32-bit siblings.
2858       assert(Base->getType() == IceType_i64);
2859       assert(RegX8664::getEncodedGPR(Base->getRegNum()) ==
2860                  RegX8664::Encoded_Reg_rsp ||
2861              RegX8664::getEncodedGPR(Base->getRegNum()) ==
2862                  RegX8664::Encoded_Reg_rbp ||
2863              getType() == IceType_void);
2864       B = B->asType(Func, IceType_i32,
2865                     RegX8664::getGprForType(IceType_i32, Base->getRegNum()));
2866     }
2867 
2868     B->emit(Func);
2869   }
2870 
2871   if (Index != nullptr) {
2872     Variable *I = Index;
2873     Str << ",";
2874     I->emit(Func);
2875     if (Shift)
2876       Str << "," << (1u << Shift);
2877   }
2878 
2879   Str << ")";
2880 }
2881 
dump(const Cfg * Func,Ostream & Str) const2882 void X86OperandMem::dump(const Cfg *Func, Ostream &Str) const {
2883   if (!BuildDefs::dump())
2884     return;
2885   bool Dumped = false;
2886   Str << "[";
2887   int32_t Disp = 0;
2888   if (getBase() && getBase()->isRematerializable()) {
2889     Disp += getBase()->getRematerializableOffset(Func->getTarget());
2890   }
2891   if (Base) {
2892     if (Func)
2893       Base->dump(Func);
2894     else
2895       Base->dump(Str);
2896     Dumped = true;
2897   }
2898   if (Index) {
2899     if (Base)
2900       Str << "+";
2901     if (Shift > 0)
2902       Str << (1u << Shift) << "*";
2903     if (Func)
2904       Index->dump(Func);
2905     else
2906       Index->dump(Str);
2907     Dumped = true;
2908   }
2909   if (Disp) {
2910     if (Disp > 0)
2911       Str << "+";
2912     Str << Disp;
2913     Dumped = true;
2914   }
2915   // Pretty-print the Offset.
2916   bool OffsetIsZero = false;
2917   bool OffsetIsNegative = false;
2918   if (!Offset) {
2919     OffsetIsZero = true;
2920   } else if (const auto *CI = llvm::dyn_cast<ConstantInteger32>(Offset)) {
2921     OffsetIsZero = (CI->getValue() == 0);
2922     OffsetIsNegative = (static_cast<int32_t>(CI->getValue()) < 0);
2923   } else {
2924     assert(llvm::isa<ConstantRelocatable>(Offset));
2925   }
2926   if (Dumped) {
2927     if (!OffsetIsZero) {     // Suppress if Offset is known to be 0
2928       if (!OffsetIsNegative) // Suppress if Offset is known to be negative
2929         Str << "+";
2930       Offset->dump(Func, Str);
2931     }
2932   } else {
2933     // There is only the offset.
2934     Offset->dump(Func, Str);
2935   }
2936   Str << "]";
2937 }
2938 
2939 } // namespace X8664
2940 } // end of namespace Ice
2941