xref: /aosp_15_r20/external/swiftshader/third_party/subzero/src/IceInstX8664.cpp (revision 03ce13f70fcc45d86ee91b7ee4cab1936a95046e)
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 
701 template void emitIASRegOpTyGPR<true, true>(const Cfg *Func, Type Ty,
702                                             const Variable *Var,
703                                             const Operand *Src,
704                                             const GPREmitterRegOp &Emitter);
705 
emitIASAddrOpTyGPR(const Cfg * Func,Type Ty,const AsmAddress & Addr,const Operand * Src,const GPREmitterAddrOp & Emitter)706 void emitIASAddrOpTyGPR(const Cfg *Func, Type Ty, const AsmAddress &Addr,
707                         const Operand *Src, const GPREmitterAddrOp &Emitter) {
708   Assembler *Asm = Func->getAssembler<Assembler>();
709   // Src can only be Reg or AssemblerImmediate.
710   if (const auto *SrcVar = llvm::dyn_cast<Variable>(Src)) {
711     assert(SrcVar->hasReg());
712     GPRRegister SrcReg = RegX8664::getEncodedGPR(SrcVar->getRegNum());
713     (Asm->*(Emitter.AddrGPR))(Ty, Addr, SrcReg);
714   } else if (const auto *Imm = llvm::dyn_cast<ConstantInteger32>(Src)) {
715     (Asm->*(Emitter.AddrImm))(Ty, Addr, AssemblerImmediate(Imm->getValue()));
716   } else if (const auto *Imm = llvm::dyn_cast<ConstantInteger64>(Src)) {
717     assert(Utils::IsInt(32, Imm->getValue()));
718     (Asm->*(Emitter.AddrImm))(Ty, Addr, AssemblerImmediate(Imm->getValue()));
719   } else if (const auto *Reloc = llvm::dyn_cast<ConstantRelocatable>(Src)) {
720     const auto FixupKind = (Reloc->getName().hasStdString() &&
721                             Reloc->getName().toString() == GlobalOffsetTable)
722                                ? FK_GotPC
723                                : FK_Abs;
724     AssemblerFixup *Fixup = Asm->createFixup(FixupKind, Reloc);
725     (Asm->*(Emitter.AddrImm))(Ty, Addr, AssemblerImmediate(Fixup));
726   } else {
727     llvm_unreachable("Unexpected operand type");
728   }
729 }
730 
emitIASAsAddrOpTyGPR(const Cfg * Func,Type Ty,const Operand * Op0,const Operand * Op1,const GPREmitterAddrOp & Emitter)731 void emitIASAsAddrOpTyGPR(const Cfg *Func, Type Ty, const Operand *Op0,
732                           const Operand *Op1, const GPREmitterAddrOp &Emitter) {
733   auto *Target = InstX86Base::getTarget(Func);
734   if (const auto *Op0Var = llvm::dyn_cast<Variable>(Op0)) {
735     assert(!Op0Var->hasReg());
736     AsmAddress StackAddr(AsmAddress(Op0Var, Target));
737     emitIASAddrOpTyGPR(Func, Ty, StackAddr, Op1, Emitter);
738   } else if (const auto *Op0Mem = llvm::dyn_cast<X86OperandMem>(Op0)) {
739     Assembler *Asm = Func->getAssembler<Assembler>();
740     Op0Mem->emitSegmentOverride(Asm);
741     emitIASAddrOpTyGPR(Func, Ty, AsmAddress(Op0Mem, Asm, Target), Op1, Emitter);
742   } else {
743     llvm_unreachable("Unexpected operand type");
744   }
745 }
746 
emitIASGPRShift(const Cfg * Func,Type Ty,const Variable * Var,const Operand * Src,const GPREmitterShiftOp & Emitter)747 void emitIASGPRShift(const Cfg *Func, Type Ty, const Variable *Var,
748                      const Operand *Src, const GPREmitterShiftOp &Emitter) {
749   Assembler *Asm = Func->getAssembler<Assembler>();
750   // Technically, the Dest Var can be mem as well, but we only use Reg. We can
751   // extend this to check Dest if we decide to use that form.
752   assert(Var->hasReg());
753   // We cheat a little and use GPRRegister even for byte operations.
754   GPRRegister VarReg = RegX8664::getEncodedGPR(Var->getRegNum());
755   // Src must be reg == ECX or an Imm8. This is asserted by the assembler.
756   if (const auto *SrcVar = llvm::dyn_cast<Variable>(Src)) {
757     assert(SrcVar->hasReg());
758     GPRRegister SrcReg = RegX8664::getEncodedGPR(SrcVar->getRegNum());
759     (Asm->*(Emitter.GPRGPR))(Ty, VarReg, SrcReg);
760   } else if (const auto *Imm = llvm::dyn_cast<ConstantInteger32>(Src)) {
761     (Asm->*(Emitter.GPRImm))(Ty, VarReg, AssemblerImmediate(Imm->getValue()));
762   } else if (const auto *Imm = llvm::dyn_cast<ConstantInteger64>(Src)) {
763     assert(Utils::IsInt(32, Imm->getValue()));
764     (Asm->*(Emitter.GPRImm))(Ty, VarReg, AssemblerImmediate(Imm->getValue()));
765   } else {
766     llvm_unreachable("Unexpected operand type");
767   }
768 }
769 
emitIASGPRShiftDouble(const Cfg * Func,const Variable * Dest,const Operand * Src1Op,const Operand * Src2Op,const GPREmitterShiftD & Emitter)770 void emitIASGPRShiftDouble(const Cfg *Func, const Variable *Dest,
771                            const Operand *Src1Op, const Operand *Src2Op,
772                            const GPREmitterShiftD &Emitter) {
773   Assembler *Asm = Func->getAssembler<Assembler>();
774   // Dest can be reg or mem, but we only use the reg variant.
775   assert(Dest->hasReg());
776   GPRRegister DestReg = RegX8664::getEncodedGPR(Dest->getRegNum());
777   // SrcVar1 must be reg.
778   const auto *SrcVar1 = llvm::cast<Variable>(Src1Op);
779   assert(SrcVar1->hasReg());
780   GPRRegister SrcReg = RegX8664::getEncodedGPR(SrcVar1->getRegNum());
781   Type Ty = SrcVar1->getType();
782   // Src2 can be the implicit CL register or an immediate.
783   if (const auto *Imm = llvm::dyn_cast<ConstantInteger32>(Src2Op)) {
784     (Asm->*(Emitter.GPRGPRImm))(Ty, DestReg, SrcReg,
785                                 AssemblerImmediate(Imm->getValue()));
786   } else {
787     assert(llvm::cast<Variable>(Src2Op)->getRegNum() == RegisterSet::Reg_cl);
788     (Asm->*(Emitter.GPRGPR))(Ty, DestReg, SrcReg);
789   }
790 }
791 
emitIASXmmShift(const Cfg * Func,Type Ty,const Variable * Var,const Operand * Src,const XmmEmitterShiftOp & Emitter)792 void emitIASXmmShift(const Cfg *Func, Type Ty, const Variable *Var,
793                      const Operand *Src, const XmmEmitterShiftOp &Emitter) {
794   auto *Target = InstX86Base::getTarget(Func);
795   Assembler *Asm = Func->getAssembler<Assembler>();
796   assert(Var->hasReg());
797   XmmRegister VarReg = RegX8664::getEncodedXmm(Var->getRegNum());
798   if (const auto *SrcVar = llvm::dyn_cast<Variable>(Src)) {
799     if (SrcVar->hasReg()) {
800       XmmRegister SrcReg = RegX8664::getEncodedXmm(SrcVar->getRegNum());
801       (Asm->*(Emitter.XmmXmm))(Ty, VarReg, SrcReg);
802     } else {
803       AsmAddress SrcStackAddr = AsmAddress(SrcVar, Target);
804       (Asm->*(Emitter.XmmAddr))(Ty, VarReg, SrcStackAddr);
805     }
806   } else if (const auto *Mem = llvm::dyn_cast<X86OperandMem>(Src)) {
807     assert(Mem->getSegmentRegister() == X86OperandMem::DefaultSegment);
808     (Asm->*(Emitter.XmmAddr))(Ty, VarReg, AsmAddress(Mem, Asm, Target));
809   } else if (const auto *Imm = llvm::dyn_cast<ConstantInteger32>(Src)) {
810     (Asm->*(Emitter.XmmImm))(Ty, VarReg, AssemblerImmediate(Imm->getValue()));
811   } else {
812     llvm_unreachable("Unexpected operand type");
813   }
814 }
815 
emitIASRegOpTyXMM(const Cfg * Func,Type Ty,const Variable * Var,const Operand * Src,const XmmEmitterRegOp & Emitter)816 void emitIASRegOpTyXMM(const Cfg *Func, Type Ty, const Variable *Var,
817                        const Operand *Src, const XmmEmitterRegOp &Emitter) {
818   auto *Target = InstX86Base::getTarget(Func);
819   Assembler *Asm = Func->getAssembler<Assembler>();
820   assert(Var->hasReg());
821   XmmRegister VarReg = RegX8664::getEncodedXmm(Var->getRegNum());
822   if (const auto *SrcVar = llvm::dyn_cast<Variable>(Src)) {
823     if (SrcVar->hasReg()) {
824       XmmRegister SrcReg = RegX8664::getEncodedXmm(SrcVar->getRegNum());
825       (Asm->*(Emitter.XmmXmm))(Ty, VarReg, SrcReg);
826     } else {
827       AsmAddress SrcStackAddr = AsmAddress(SrcVar, Target);
828       (Asm->*(Emitter.XmmAddr))(Ty, VarReg, SrcStackAddr);
829     }
830   } else if (const auto *Mem = llvm::dyn_cast<X86OperandMem>(Src)) {
831     assert(Mem->getSegmentRegister() == X86OperandMem::DefaultSegment);
832     (Asm->*(Emitter.XmmAddr))(Ty, VarReg, AsmAddress(Mem, Asm, Target));
833   } else if (const auto *Imm = llvm::dyn_cast<Constant>(Src)) {
834     (Asm->*(Emitter.XmmAddr))(Ty, VarReg, AsmAddress(Imm, Asm));
835   } else {
836     llvm_unreachable("Unexpected operand type");
837   }
838 }
839 
840 template <typename DReg_t, typename SReg_t, DReg_t (*destEnc)(RegNumT),
841           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)842 void emitIASCastRegOp(const Cfg *Func, Type DestTy, const Variable *Dest,
843                       Type SrcTy, const Operand *Src,
844                       const CastEmitterRegOp<DReg_t, SReg_t> &Emitter) {
845   auto *Target = InstX86Base::getTarget(Func);
846   Assembler *Asm = Func->getAssembler<Assembler>();
847   assert(Dest->hasReg());
848   DReg_t DestReg = destEnc(Dest->getRegNum());
849   if (const auto *SrcVar = llvm::dyn_cast<Variable>(Src)) {
850     if (SrcVar->hasReg()) {
851       SReg_t SrcReg = srcEnc(SrcVar->getRegNum());
852       (Asm->*(Emitter.RegReg))(DestTy, DestReg, SrcTy, SrcReg);
853     } else {
854       AsmAddress SrcStackAddr = AsmAddress(SrcVar, Target);
855       (Asm->*(Emitter.RegAddr))(DestTy, DestReg, SrcTy, SrcStackAddr);
856     }
857   } else if (const auto *Mem = llvm::dyn_cast<X86OperandMem>(Src)) {
858     Mem->emitSegmentOverride(Asm);
859     (Asm->*(Emitter.RegAddr))(DestTy, DestReg, SrcTy,
860                               AsmAddress(Mem, Asm, Target));
861   } else {
862     llvm_unreachable("Unexpected operand type");
863   }
864 }
865 
866 template <typename DReg_t, typename SReg_t, DReg_t (*destEnc)(RegNumT),
867           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)868 void emitIASThreeOpImmOps(const Cfg *Func, Type DispatchTy,
869                           const Variable *Dest, const Operand *Src0,
870                           const Operand *Src1,
871                           const ThreeOpImmEmitter<DReg_t, SReg_t> Emitter) {
872   auto *Target = InstX86Base::getTarget(Func);
873   Assembler *Asm = Func->getAssembler<Assembler>();
874   // This only handles Dest being a register, and Src1 being an immediate.
875   assert(Dest->hasReg());
876   DReg_t DestReg = destEnc(Dest->getRegNum());
877   AssemblerImmediate Imm(llvm::cast<ConstantInteger32>(Src1)->getValue());
878   if (const auto *SrcVar = llvm::dyn_cast<Variable>(Src0)) {
879     if (SrcVar->hasReg()) {
880       SReg_t SrcReg = srcEnc(SrcVar->getRegNum());
881       (Asm->*(Emitter.RegRegImm))(DispatchTy, DestReg, SrcReg, Imm);
882     } else {
883       AsmAddress SrcStackAddr = AsmAddress(SrcVar, Target);
884       (Asm->*(Emitter.RegAddrImm))(DispatchTy, DestReg, SrcStackAddr, Imm);
885     }
886   } else if (const auto *Mem = llvm::dyn_cast<X86OperandMem>(Src0)) {
887     Mem->emitSegmentOverride(Asm);
888     (Asm->*(Emitter.RegAddrImm))(DispatchTy, DestReg,
889                                  AsmAddress(Mem, Asm, Target), Imm);
890   } else {
891     llvm_unreachable("Unexpected operand type");
892   }
893 }
894 
emitIASMovlikeXMM(const Cfg * Func,const Variable * Dest,const Operand * Src,const XmmEmitterMovOps Emitter)895 void emitIASMovlikeXMM(const Cfg *Func, const Variable *Dest,
896                        const Operand *Src, const XmmEmitterMovOps Emitter) {
897   auto *Target = InstX86Base::getTarget(Func);
898   Assembler *Asm = Func->getAssembler<Assembler>();
899   if (Dest->hasReg()) {
900     XmmRegister DestReg = RegX8664::getEncodedXmm(Dest->getRegNum());
901     if (const auto *SrcVar = llvm::dyn_cast<Variable>(Src)) {
902       if (SrcVar->hasReg()) {
903         (Asm->*(Emitter.XmmXmm))(DestReg,
904                                  RegX8664::getEncodedXmm(SrcVar->getRegNum()));
905       } else {
906         AsmAddress StackAddr(AsmAddress(SrcVar, Target));
907         (Asm->*(Emitter.XmmAddr))(DestReg, StackAddr);
908       }
909     } else if (const auto *SrcMem = llvm::dyn_cast<X86OperandMem>(Src)) {
910       assert(SrcMem->getSegmentRegister() == X86OperandMem::DefaultSegment);
911       (Asm->*(Emitter.XmmAddr))(DestReg, AsmAddress(SrcMem, Asm, Target));
912     } else {
913       llvm_unreachable("Unexpected operand type");
914     }
915   } else {
916     AsmAddress StackAddr(AsmAddress(Dest, Target));
917     // Src must be a register in this case.
918     const auto *SrcVar = llvm::cast<Variable>(Src);
919     assert(SrcVar->hasReg());
920     (Asm->*(Emitter.AddrXmm))(StackAddr,
921                               RegX8664::getEncodedXmm(SrcVar->getRegNum()));
922   }
923 }
924 
dump(const Cfg * Func) const925 void InstX86Movmsk::dump(const Cfg *Func) const {
926   if (!BuildDefs::dump())
927     return;
928   Ostream &Str = Func->getContext()->getStrDump();
929   this->dumpDest(Func);
930   Str << " = movmsk." << this->getSrc(0)->getType() << " ";
931   this->dumpSources(Func);
932 }
933 
emit(const Cfg * Func) const934 void InstX86Movmsk::emit(const Cfg *Func) const {
935   if (!BuildDefs::dump())
936     return;
937   Ostream &Str = Func->getContext()->getStrEmit();
938   assert(this->getSrcSize() == 1);
939   Type SrcTy = this->getSrc(0)->getType();
940   assert(isVectorType(SrcTy));
941   switch (SrcTy) {
942   case IceType_v16i8:
943     Str << "\t"
944            "pmovmskb"
945            "\t";
946     break;
947   case IceType_v4i32:
948   case IceType_v4f32:
949     Str << "\t"
950            "movmskps"
951            "\t";
952     break;
953   default:
954     llvm_unreachable("Unexpected operand type");
955   }
956   this->getSrc(0)->emit(Func);
957   Str << ", ";
958   this->getDest()->emit(Func);
959 }
960 
emitIAS(const Cfg * Func) const961 void InstX86Movmsk::emitIAS(const Cfg *Func) const {
962   assert(this->getSrcSize() == 1);
963   Assembler *Asm = Func->getAssembler<Assembler>();
964   const Variable *Dest = this->getDest();
965   const Variable *Src = llvm::cast<Variable>(this->getSrc(0));
966   const Type DestTy = Dest->getType();
967   (void)DestTy;
968   const Type SrcTy = Src->getType();
969   assert(isVectorType(SrcTy));
970   assert(isScalarIntegerType(DestTy));
971   assert(DestTy == IceType_i32 || DestTy == IceType_i64);
972   XmmRegister SrcReg = RegX8664::getEncodedXmm(Src->getRegNum());
973   GPRRegister DestReg = RegX8664::getEncodedGPR(Dest->getRegNum());
974   Asm->movmsk(SrcTy, DestReg, SrcReg);
975 }
976 
emit(const Cfg * Func) const977 void InstX86Sqrt::emit(const Cfg *Func) const {
978   if (!BuildDefs::dump())
979     return;
980   Ostream &Str = Func->getContext()->getStrEmit();
981   assert(this->getSrcSize() == 1);
982   Type Ty = this->getSrc(0)->getType();
983   assert(isScalarFloatingType(Ty));
984   Str << "\t"
985          "sqrt"
986       << TypeAttributes[Ty].SpSdString << "\t";
987   this->getSrc(0)->emit(Func);
988   Str << ", ";
989   this->getDest()->emit(Func);
990 }
991 
emit(const Cfg * Func) const992 void InstX86Div::emit(const Cfg *Func) const {
993   if (!BuildDefs::dump())
994     return;
995   Ostream &Str = Func->getContext()->getStrEmit();
996   assert(this->getSrcSize() == 3);
997   Operand *Src1 = this->getSrc(1);
998   Str << "\t" << this->Opcode << this->getWidthString(Src1->getType()) << "\t";
999   Src1->emit(Func);
1000 }
1001 
emitIAS(const Cfg * Func) const1002 void InstX86Div::emitIAS(const Cfg *Func) const {
1003   assert(this->getSrcSize() == 3);
1004   const Operand *Src = this->getSrc(1);
1005   Type Ty = Src->getType();
1006   static GPREmitterOneOp Emitter = {&Assembler::div, &Assembler::div};
1007   emitIASOpTyGPR(Func, Ty, Src, Emitter);
1008 }
1009 
emit(const Cfg * Func) const1010 void InstX86Idiv::emit(const Cfg *Func) const {
1011   if (!BuildDefs::dump())
1012     return;
1013   Ostream &Str = Func->getContext()->getStrEmit();
1014   assert(this->getSrcSize() == 3);
1015   Operand *Src1 = this->getSrc(1);
1016   Str << "\t" << this->Opcode << this->getWidthString(Src1->getType()) << "\t";
1017   Src1->emit(Func);
1018 }
1019 
emitIAS(const Cfg * Func) const1020 void InstX86Idiv::emitIAS(const Cfg *Func) const {
1021   assert(this->getSrcSize() == 3);
1022   const Operand *Src = this->getSrc(1);
1023   Type Ty = Src->getType();
1024   static const GPREmitterOneOp Emitter = {&Assembler::idiv, &Assembler::idiv};
1025   emitIASOpTyGPR(Func, Ty, Src, Emitter);
1026 }
1027 
1028 // pblendvb and blendvps take xmm0 as a final implicit argument.
1029 
emitVariableBlendInst(const char * Opcode,const Inst * Instr,const Cfg * Func)1030 void emitVariableBlendInst(const char *Opcode, const Inst *Instr,
1031                            const Cfg *Func) {
1032   if (!BuildDefs::dump())
1033     return;
1034   Ostream &Str = Func->getContext()->getStrEmit();
1035   assert(Instr->getSrcSize() == 3);
1036   assert(llvm::cast<Variable>(Instr->getSrc(2))->getRegNum() ==
1037          RegisterSet::Reg_xmm0);
1038   Str << "\t" << Opcode << "\t";
1039   Instr->getSrc(1)->emit(Func);
1040   Str << ", ";
1041   Instr->getDest()->emit(Func);
1042 }
1043 
emitIASVariableBlendInst(const Inst * Instr,const Cfg * Func,const XmmEmitterRegOp & Emitter)1044 void emitIASVariableBlendInst(const Inst *Instr, const Cfg *Func,
1045                               const XmmEmitterRegOp &Emitter) {
1046   assert(Instr->getSrcSize() == 3);
1047   assert(llvm::cast<Variable>(Instr->getSrc(2))->getRegNum() ==
1048          RegisterSet::Reg_xmm0);
1049   const Variable *Dest = Instr->getDest();
1050   const Operand *Src = Instr->getSrc(1);
1051   emitIASRegOpTyXMM(Func, Dest->getType(), Dest, Src, Emitter);
1052 }
1053 
emit(const Cfg * Func) const1054 void InstX86Blendvps::emit(const Cfg *Func) const {
1055   if (!BuildDefs::dump())
1056     return;
1057   emitVariableBlendInst(this->Opcode, this, Func);
1058 }
1059 
emitIAS(const Cfg * Func) const1060 void InstX86Blendvps::emitIAS(const Cfg *Func) const {
1061   static const XmmEmitterRegOp Emitter = {&Assembler::blendvps,
1062                                           &Assembler::blendvps};
1063   emitIASVariableBlendInst(this, Func, Emitter);
1064 }
1065 
emit(const Cfg * Func) const1066 void InstX86Pblendvb::emit(const Cfg *Func) const {
1067   if (!BuildDefs::dump())
1068     return;
1069   emitVariableBlendInst(this->Opcode, this, Func);
1070 }
1071 
emitIAS(const Cfg * Func) const1072 void InstX86Pblendvb::emitIAS(const Cfg *Func) const {
1073   static const XmmEmitterRegOp Emitter = {&Assembler::pblendvb,
1074                                           &Assembler::pblendvb};
1075   emitIASVariableBlendInst(this, Func, Emitter);
1076 }
1077 
emit(const Cfg * Func) const1078 void InstX86Imul::emit(const Cfg *Func) const {
1079   if (!BuildDefs::dump())
1080     return;
1081   Ostream &Str = Func->getContext()->getStrEmit();
1082   assert(this->getSrcSize() == 2);
1083   Variable *Dest = this->getDest();
1084   if (isByteSizedArithType(Dest->getType())) {
1085     // The 8-bit version of imul only allows the form "imul r/m8".
1086     const auto *Src0Var = llvm::dyn_cast<Variable>(this->getSrc(0));
1087     (void)Src0Var;
1088     assert(Src0Var->getRegNum() == RegisterSet::Reg_al);
1089     Str << "\t"
1090            "imulb\t";
1091     this->getSrc(1)->emit(Func);
1092   } else if (llvm::isa<Constant>(this->getSrc(1))) {
1093     Str << "\t"
1094            "imul"
1095         << this->getWidthString(Dest->getType()) << "\t";
1096     this->getSrc(1)->emit(Func);
1097     Str << ", ";
1098     this->getSrc(0)->emit(Func);
1099     Str << ", ";
1100     Dest->emit(Func);
1101   } else {
1102     this->emitTwoAddress(Func, this->Opcode);
1103   }
1104 }
1105 
emitIAS(const Cfg * Func) const1106 void InstX86Imul::emitIAS(const Cfg *Func) const {
1107   assert(this->getSrcSize() == 2);
1108   const Variable *Var = this->getDest();
1109   Type Ty = Var->getType();
1110   const Operand *Src = this->getSrc(1);
1111   if (isByteSizedArithType(Ty)) {
1112     // The 8-bit version of imul only allows the form "imul r/m8".
1113     const auto *Src0Var = llvm::dyn_cast<Variable>(this->getSrc(0));
1114     (void)Src0Var;
1115     assert(Src0Var->getRegNum() == RegisterSet::Reg_al);
1116     static const GPREmitterOneOp Emitter = {&Assembler::imul, &Assembler::imul};
1117     emitIASOpTyGPR(Func, Ty, this->getSrc(1), Emitter);
1118   } else {
1119     // The two-address version is used when multiplying by a non-constant
1120     // or doing an 8-bit multiply.
1121     assert(Var == this->getSrc(0));
1122     static const GPREmitterRegOp Emitter = {&Assembler::imul, &Assembler::imul,
1123                                             &Assembler::imul};
1124     emitIASRegOpTyGPR(Func, Ty, Var, Src, Emitter);
1125   }
1126 }
1127 
emit(const Cfg * Func) const1128 void InstX86ImulImm::emit(const Cfg *Func) const {
1129   if (!BuildDefs::dump())
1130     return;
1131   Ostream &Str = Func->getContext()->getStrEmit();
1132   assert(this->getSrcSize() == 2);
1133   Variable *Dest = this->getDest();
1134   assert(Dest->getType() == IceType_i16 || Dest->getType() == IceType_i32);
1135   assert(llvm::isa<Constant>(this->getSrc(1)));
1136   Str << "\t"
1137          "imul"
1138       << this->getWidthString(Dest->getType()) << "\t";
1139   this->getSrc(1)->emit(Func);
1140   Str << ", ";
1141   this->getSrc(0)->emit(Func);
1142   Str << ", ";
1143   Dest->emit(Func);
1144 }
1145 
emitIAS(const Cfg * Func) const1146 void InstX86ImulImm::emitIAS(const Cfg *Func) const {
1147   assert(this->getSrcSize() == 2);
1148   const Variable *Dest = this->getDest();
1149   Type Ty = Dest->getType();
1150   assert(llvm::isa<Constant>(this->getSrc(1)));
1151   static const ThreeOpImmEmitter<GPRRegister, GPRRegister> Emitter = {
1152       &Assembler::imul, &Assembler::imul};
1153   emitIASThreeOpImmOps<GPRRegister, GPRRegister, RegX8664::getEncodedGPR,
1154                        RegX8664::getEncodedGPR>(Func, Ty, Dest, this->getSrc(0),
1155                                                 this->getSrc(1), Emitter);
1156 }
1157 
emitIAS(const Cfg * Func) const1158 void InstX86Insertps::emitIAS(const Cfg *Func) const {
1159   assert(this->getSrcSize() == 3);
1160   assert(getInstructionSet(Func) >= SSE4_1);
1161   const Variable *Dest = this->getDest();
1162   assert(Dest == this->getSrc(0));
1163   Type Ty = Dest->getType();
1164   static const ThreeOpImmEmitter<XmmRegister, XmmRegister> Emitter = {
1165       &Assembler::insertps, &Assembler::insertps};
1166   emitIASThreeOpImmOps<XmmRegister, XmmRegister, RegX8664::getEncodedXmm,
1167                        RegX8664::getEncodedXmm>(Func, Ty, Dest, this->getSrc(1),
1168                                                 this->getSrc(2), Emitter);
1169 }
1170 
emit(const Cfg * Func) const1171 void InstX86Cbwdq::emit(const Cfg *Func) const {
1172   if (!BuildDefs::dump())
1173     return;
1174   Ostream &Str = Func->getContext()->getStrEmit();
1175   assert(this->getSrcSize() == 1);
1176   Operand *Src0 = this->getSrc(0);
1177   const auto DestReg = this->getDest()->getRegNum();
1178   const auto SrcReg = llvm::cast<Variable>(Src0)->getRegNum();
1179   (void)DestReg;
1180   (void)SrcReg;
1181   switch (Src0->getType()) {
1182   default:
1183     llvm_unreachable("unexpected source type!");
1184     break;
1185   case IceType_i8:
1186     assert(SrcReg == RegisterSet::Reg_al);
1187     assert(DestReg == RegisterSet::Reg_ax || DestReg == RegisterSet::Reg_ah);
1188     Str << "\t"
1189            "cbtw";
1190     break;
1191   case IceType_i16:
1192     assert(SrcReg == RegisterSet::Reg_ax);
1193     assert(DestReg == RegisterSet::Reg_dx);
1194     Str << "\t"
1195            "cwtd";
1196     break;
1197   case IceType_i32:
1198     assert(SrcReg == RegisterSet::Reg_eax);
1199     assert(DestReg == RegisterSet::Reg_edx);
1200     Str << "\t"
1201            "cltd";
1202     break;
1203   case IceType_i64:
1204     assert(SrcReg == RegisterSet::Reg_rax);
1205     assert(DestReg == RegisterSet::Reg_rdx);
1206     Str << "\t"
1207            "cqo";
1208     break;
1209   }
1210 }
1211 
emitIAS(const Cfg * Func) const1212 void InstX86Cbwdq::emitIAS(const Cfg *Func) const {
1213   Assembler *Asm = Func->getAssembler<Assembler>();
1214   assert(this->getSrcSize() == 1);
1215   Operand *Src0 = this->getSrc(0);
1216   const auto DestReg = this->getDest()->getRegNum();
1217   const auto SrcReg = llvm::cast<Variable>(Src0)->getRegNum();
1218   (void)DestReg;
1219   (void)SrcReg;
1220   switch (Src0->getType()) {
1221   default:
1222     llvm_unreachable("unexpected source type!");
1223     break;
1224   case IceType_i8:
1225     assert(SrcReg == RegisterSet::Reg_al);
1226     assert(DestReg == RegisterSet::Reg_ax || DestReg == RegisterSet::Reg_ah);
1227     Asm->cbw();
1228     break;
1229   case IceType_i16:
1230     assert(SrcReg == RegisterSet::Reg_ax);
1231     assert(DestReg == RegisterSet::Reg_dx);
1232     Asm->cwd();
1233     break;
1234   case IceType_i32:
1235     assert(SrcReg == RegisterSet::Reg_eax);
1236     assert(DestReg == RegisterSet::Reg_edx);
1237     Asm->cdq();
1238     break;
1239   case IceType_i64:
1240     assert(SrcReg == RegisterSet::Reg_rax);
1241     assert(DestReg == RegisterSet::Reg_rdx);
1242     Asm->cqo();
1243     break;
1244   }
1245 }
1246 
emit(const Cfg * Func) const1247 void InstX86Mul::emit(const Cfg *Func) const {
1248   if (!BuildDefs::dump())
1249     return;
1250   Ostream &Str = Func->getContext()->getStrEmit();
1251   assert(this->getSrcSize() == 2);
1252   assert(llvm::isa<Variable>(this->getSrc(0)));
1253   assert(llvm::cast<Variable>(this->getSrc(0))->getRegNum() ==
1254          RegisterSet::Reg_eax);
1255   assert(this->getDest()->getRegNum() == RegisterSet::Reg_eax); // TODO:
1256                                                                 // allow
1257                                                                 // edx?
1258   Str << "\t"
1259          "mul"
1260       << this->getWidthString(this->getDest()->getType()) << "\t";
1261   this->getSrc(1)->emit(Func);
1262 }
1263 
emitIAS(const Cfg * Func) const1264 void InstX86Mul::emitIAS(const Cfg *Func) const {
1265   assert(this->getSrcSize() == 2);
1266   assert(llvm::isa<Variable>(this->getSrc(0)));
1267   assert(llvm::cast<Variable>(this->getSrc(0))->getRegNum() ==
1268          RegisterSet::Reg_eax);
1269   assert(this->getDest()->getRegNum() == RegisterSet::Reg_eax); // TODO:
1270                                                                 // allow
1271                                                                 // edx?
1272   const Operand *Src = this->getSrc(1);
1273   Type Ty = Src->getType();
1274   static const GPREmitterOneOp Emitter = {&Assembler::mul, &Assembler::mul};
1275   emitIASOpTyGPR(Func, Ty, Src, Emitter);
1276 }
1277 
dump(const Cfg * Func) const1278 void InstX86Mul::dump(const Cfg *Func) const {
1279   if (!BuildDefs::dump())
1280     return;
1281   Ostream &Str = Func->getContext()->getStrDump();
1282   this->dumpDest(Func);
1283   Str << " = mul." << this->getDest()->getType() << " ";
1284   this->dumpSources(Func);
1285 }
1286 
emit(const Cfg * Func) const1287 void InstX86Shld::emit(const Cfg *Func) const {
1288   if (!BuildDefs::dump())
1289     return;
1290   Ostream &Str = Func->getContext()->getStrEmit();
1291   Variable *Dest = this->getDest();
1292   assert(this->getSrcSize() == 3);
1293   assert(Dest == this->getSrc(0));
1294   Str << "\t"
1295          "shld"
1296       << this->getWidthString(Dest->getType()) << "\t";
1297   this->getSrc(2)->emit(Func);
1298   Str << ", ";
1299   this->getSrc(1)->emit(Func);
1300   Str << ", ";
1301   Dest->emit(Func);
1302 }
1303 
emitIAS(const Cfg * Func) const1304 void InstX86Shld::emitIAS(const Cfg *Func) const {
1305   assert(this->getSrcSize() == 3);
1306   assert(this->getDest() == this->getSrc(0));
1307   const Variable *Dest = this->getDest();
1308   const Operand *Src1 = this->getSrc(1);
1309   const Operand *Src2 = this->getSrc(2);
1310   static const GPREmitterShiftD Emitter = {&Assembler::shld, &Assembler::shld};
1311   emitIASGPRShiftDouble(Func, Dest, Src1, Src2, Emitter);
1312 }
1313 
dump(const Cfg * Func) const1314 void InstX86Shld::dump(const Cfg *Func) const {
1315   if (!BuildDefs::dump())
1316     return;
1317   Ostream &Str = Func->getContext()->getStrDump();
1318   this->dumpDest(Func);
1319   Str << " = shld." << this->getDest()->getType() << " ";
1320   this->dumpSources(Func);
1321 }
1322 
emit(const Cfg * Func) const1323 void InstX86Shrd::emit(const Cfg *Func) const {
1324   if (!BuildDefs::dump())
1325     return;
1326   Ostream &Str = Func->getContext()->getStrEmit();
1327   Variable *Dest = this->getDest();
1328   assert(this->getSrcSize() == 3);
1329   assert(Dest == this->getSrc(0));
1330   Str << "\t"
1331          "shrd"
1332       << this->getWidthString(Dest->getType()) << "\t";
1333   this->getSrc(2)->emit(Func);
1334   Str << ", ";
1335   this->getSrc(1)->emit(Func);
1336   Str << ", ";
1337   Dest->emit(Func);
1338 }
1339 
emitIAS(const Cfg * Func) const1340 void InstX86Shrd::emitIAS(const Cfg *Func) const {
1341   assert(this->getSrcSize() == 3);
1342   assert(this->getDest() == this->getSrc(0));
1343   const Variable *Dest = this->getDest();
1344   const Operand *Src1 = this->getSrc(1);
1345   const Operand *Src2 = this->getSrc(2);
1346   static const GPREmitterShiftD Emitter = {&Assembler::shrd, &Assembler::shrd};
1347   emitIASGPRShiftDouble(Func, Dest, Src1, Src2, Emitter);
1348 }
1349 
dump(const Cfg * Func) const1350 void InstX86Shrd::dump(const Cfg *Func) const {
1351   if (!BuildDefs::dump())
1352     return;
1353   Ostream &Str = Func->getContext()->getStrDump();
1354   this->dumpDest(Func);
1355   Str << " = shrd." << this->getDest()->getType() << " ";
1356   this->dumpSources(Func);
1357 }
1358 
emit(const Cfg * Func) const1359 void InstX86Cmov::emit(const Cfg *Func) const {
1360   if (!BuildDefs::dump())
1361     return;
1362   Ostream &Str = Func->getContext()->getStrEmit();
1363   Variable *Dest = this->getDest();
1364   Str << "\t";
1365   assert(Condition != Cond::Br_None);
1366   assert(this->getDest()->hasReg());
1367   Str << "cmov" << InstBrAttributes[Condition].DisplayString
1368       << this->getWidthString(Dest->getType()) << "\t";
1369   this->getSrc(1)->emit(Func);
1370   Str << ", ";
1371   Dest->emit(Func);
1372 }
1373 
emitIAS(const Cfg * Func) const1374 void InstX86Cmov::emitIAS(const Cfg *Func) const {
1375   assert(Condition != Cond::Br_None);
1376   assert(this->getDest()->hasReg());
1377   assert(this->getSrcSize() == 2);
1378   Operand *Src = this->getSrc(1);
1379   Type SrcTy = Src->getType();
1380   Assembler *Asm = Func->getAssembler<Assembler>();
1381   auto *Target = InstX86Base::getTarget(Func);
1382   if (const auto *SrcVar = llvm::dyn_cast<Variable>(Src)) {
1383     if (SrcVar->hasReg()) {
1384       Asm->cmov(SrcTy, Condition,
1385                 RegX8664::getEncodedGPR(this->getDest()->getRegNum()),
1386                 RegX8664::getEncodedGPR(SrcVar->getRegNum()));
1387     } else {
1388       Asm->cmov(SrcTy, Condition,
1389                 RegX8664::getEncodedGPR(this->getDest()->getRegNum()),
1390                 AsmAddress(SrcVar, Target));
1391     }
1392   } else if (const auto *Mem = llvm::dyn_cast<X86OperandMem>(Src)) {
1393     assert(Mem->getSegmentRegister() == X86OperandMem::DefaultSegment);
1394     Asm->cmov(SrcTy, Condition,
1395               RegX8664::getEncodedGPR(this->getDest()->getRegNum()),
1396               AsmAddress(Mem, Asm, Target));
1397   } else {
1398     llvm_unreachable("Unexpected operand type");
1399   }
1400 }
1401 
dump(const Cfg * Func) const1402 void InstX86Cmov::dump(const Cfg *Func) const {
1403   if (!BuildDefs::dump())
1404     return;
1405   Ostream &Str = Func->getContext()->getStrDump();
1406   Str << "cmov" << InstBrAttributes[Condition].DisplayString << ".";
1407   Str << this->getDest()->getType() << " ";
1408   this->dumpDest(Func);
1409   Str << ", ";
1410   this->dumpSources(Func);
1411 }
1412 
emit(const Cfg * Func) const1413 void InstX86Cmpps::emit(const Cfg *Func) const {
1414   if (!BuildDefs::dump())
1415     return;
1416   Ostream &Str = Func->getContext()->getStrEmit();
1417   assert(this->getSrcSize() == 2);
1418   assert(Condition < Cond::Cmpps_Invalid);
1419   Type DestTy = this->Dest->getType();
1420   Str << "\t"
1421          "cmp"
1422       << InstCmppsAttributes[Condition].EmitString
1423       << TypeAttributes[DestTy].PdPsString << "\t";
1424   this->getSrc(1)->emit(Func);
1425   Str << ", ";
1426   this->getDest()->emit(Func);
1427 }
1428 
emitIAS(const Cfg * Func) const1429 void InstX86Cmpps::emitIAS(const Cfg *Func) const {
1430   Assembler *Asm = Func->getAssembler<Assembler>();
1431   assert(this->getSrcSize() == 2);
1432   assert(Condition < Cond::Cmpps_Invalid);
1433   // Assuming there isn't any load folding for cmpps, and vector constants are
1434   // not allowed in PNaCl.
1435   assert(llvm::isa<Variable>(this->getSrc(1)));
1436   auto *Target = InstX86Base::getTarget(Func);
1437   const auto *SrcVar = llvm::cast<Variable>(this->getSrc(1));
1438   if (SrcVar->hasReg()) {
1439     Asm->cmpps(this->getDest()->getType(),
1440                RegX8664::getEncodedXmm(this->getDest()->getRegNum()),
1441                RegX8664::getEncodedXmm(SrcVar->getRegNum()), Condition);
1442   } else {
1443     AsmAddress SrcStackAddr = AsmAddress(SrcVar, Target);
1444     Asm->cmpps(this->getDest()->getType(),
1445                RegX8664::getEncodedXmm(this->getDest()->getRegNum()),
1446                SrcStackAddr, Condition);
1447   }
1448 }
1449 
dump(const Cfg * Func) const1450 void InstX86Cmpps::dump(const Cfg *Func) const {
1451   if (!BuildDefs::dump())
1452     return;
1453   Ostream &Str = Func->getContext()->getStrDump();
1454   assert(Condition < Cond::Cmpps_Invalid);
1455   this->dumpDest(Func);
1456   Str << " = cmp" << InstCmppsAttributes[Condition].EmitString
1457       << "ps"
1458          "\t";
1459   this->dumpSources(Func);
1460 }
1461 
emit(const Cfg * Func) const1462 void InstX86Cmpxchg::emit(const Cfg *Func) const {
1463   if (!BuildDefs::dump())
1464     return;
1465   Ostream &Str = Func->getContext()->getStrEmit();
1466   assert(this->getSrcSize() == 3);
1467   if (this->Locked) {
1468     Str << "\t"
1469            "lock";
1470   }
1471   Str << "\t"
1472          "cmpxchg"
1473       << this->getWidthString(this->getSrc(0)->getType()) << "\t";
1474   this->getSrc(2)->emit(Func);
1475   Str << ", ";
1476   this->getSrc(0)->emit(Func);
1477 }
1478 
emitIAS(const Cfg * Func) const1479 void InstX86Cmpxchg::emitIAS(const Cfg *Func) const {
1480   assert(this->getSrcSize() == 3);
1481   Assembler *Asm = Func->getAssembler<Assembler>();
1482   Type Ty = this->getSrc(0)->getType();
1483   auto *Target = InstX86Base::getTarget(Func);
1484   const auto Mem = llvm::cast<X86OperandMem>(this->getSrc(0));
1485   assert(Mem->getSegmentRegister() == X86OperandMem::DefaultSegment);
1486   const AsmAddress Addr = AsmAddress(Mem, Asm, Target);
1487   const auto *VarReg = llvm::cast<Variable>(this->getSrc(2));
1488   assert(VarReg->hasReg());
1489   const GPRRegister Reg = RegX8664::getEncodedGPR(VarReg->getRegNum());
1490   Asm->cmpxchg(Ty, Addr, Reg, this->Locked);
1491 }
1492 
dump(const Cfg * Func) const1493 void InstX86Cmpxchg::dump(const Cfg *Func) const {
1494   if (!BuildDefs::dump())
1495     return;
1496   Ostream &Str = Func->getContext()->getStrDump();
1497   if (this->Locked) {
1498     Str << "lock ";
1499   }
1500   Str << "cmpxchg." << this->getSrc(0)->getType() << " ";
1501   this->dumpSources(Func);
1502 }
1503 
emit(const Cfg * Func) const1504 void InstX86Cmpxchg8b::emit(const Cfg *Func) const {
1505   if (!BuildDefs::dump())
1506     return;
1507   Ostream &Str = Func->getContext()->getStrEmit();
1508   assert(this->getSrcSize() == 5);
1509   if (this->Locked) {
1510     Str << "\t"
1511            "lock";
1512   }
1513   Str << "\t"
1514          "cmpxchg8b\t";
1515   this->getSrc(0)->emit(Func);
1516 }
1517 
emitIAS(const Cfg * Func) const1518 void InstX86Cmpxchg8b::emitIAS(const Cfg *Func) const {
1519   assert(this->getSrcSize() == 5);
1520   Assembler *Asm = Func->getAssembler<Assembler>();
1521   const auto Mem = llvm::cast<X86OperandMem>(this->getSrc(0));
1522   assert(Mem->getSegmentRegister() == X86OperandMem::DefaultSegment);
1523   auto *Target = InstX86Base::getTarget(Func);
1524   const AsmAddress Addr = AsmAddress(Mem, Asm, Target);
1525   Asm->cmpxchg8b(Addr, this->Locked);
1526 }
1527 
dump(const Cfg * Func) const1528 void InstX86Cmpxchg8b::dump(const Cfg *Func) const {
1529   if (!BuildDefs::dump())
1530     return;
1531   Ostream &Str = Func->getContext()->getStrDump();
1532   if (this->Locked) {
1533     Str << "lock ";
1534   }
1535   Str << "cmpxchg8b ";
1536   this->dumpSources(Func);
1537 }
1538 
emit(const Cfg * Func) const1539 void InstX86Cvt::emit(const Cfg *Func) const {
1540   if (!BuildDefs::dump())
1541     return;
1542   Ostream &Str = Func->getContext()->getStrEmit();
1543   assert(this->getSrcSize() == 1);
1544   Str << "\t"
1545          "cvt";
1546   if (isTruncating())
1547     Str << "t";
1548   Str << TypeAttributes[this->getSrc(0)->getType()].CvtString << "2"
1549       << TypeAttributes[this->getDest()->getType()].CvtString << "\t";
1550   this->getSrc(0)->emit(Func);
1551   Str << ", ";
1552   this->getDest()->emit(Func);
1553 }
1554 
emitIAS(const Cfg * Func) const1555 void InstX86Cvt::emitIAS(const Cfg *Func) const {
1556   assert(this->getSrcSize() == 1);
1557   const Variable *Dest = this->getDest();
1558   const Operand *Src = this->getSrc(0);
1559   Type DestTy = Dest->getType();
1560   Type SrcTy = Src->getType();
1561   switch (Variant) {
1562   case Si2ss: {
1563     assert(isScalarIntegerType(SrcTy));
1564     assert(SrcTy == IceType_i32 || SrcTy == IceType_i64);
1565     assert(isScalarFloatingType(DestTy));
1566     static const CastEmitterRegOp<XmmRegister, GPRRegister> Emitter = {
1567         &Assembler::cvtsi2ss, &Assembler::cvtsi2ss};
1568     emitIASCastRegOp<XmmRegister, GPRRegister, RegX8664::getEncodedXmm,
1569                      RegX8664::getEncodedGPR>(Func, DestTy, Dest, SrcTy, Src,
1570                                               Emitter);
1571     return;
1572   }
1573   case Tss2si: {
1574     assert(isScalarFloatingType(SrcTy));
1575     assert(isScalarIntegerType(DestTy));
1576     assert(DestTy == IceType_i32 || DestTy == IceType_i64);
1577     static const CastEmitterRegOp<GPRRegister, XmmRegister> Emitter = {
1578         &Assembler::cvttss2si, &Assembler::cvttss2si};
1579     emitIASCastRegOp<GPRRegister, XmmRegister, RegX8664::getEncodedGPR,
1580                      RegX8664::getEncodedXmm>(Func, DestTy, Dest, SrcTy, Src,
1581                                               Emitter);
1582     return;
1583   }
1584   case Ss2si: {
1585     assert(isScalarFloatingType(SrcTy));
1586     assert(isScalarIntegerType(DestTy));
1587     assert(DestTy == IceType_i32 || DestTy == IceType_i64);
1588     static const CastEmitterRegOp<GPRRegister, XmmRegister> Emitter = {
1589         &Assembler::cvtss2si, &Assembler::cvtss2si};
1590     emitIASCastRegOp<GPRRegister, XmmRegister, RegX8664::getEncodedGPR,
1591                      RegX8664::getEncodedXmm>(Func, DestTy, Dest, SrcTy, Src,
1592                                               Emitter);
1593     return;
1594   }
1595   case Float2float: {
1596     assert(isScalarFloatingType(SrcTy));
1597     assert(isScalarFloatingType(DestTy));
1598     assert(DestTy != SrcTy);
1599     static const XmmEmitterRegOp Emitter = {&Assembler::cvtfloat2float,
1600                                             &Assembler::cvtfloat2float};
1601     emitIASRegOpTyXMM(Func, SrcTy, Dest, Src, Emitter);
1602     return;
1603   }
1604   case Dq2ps: {
1605     assert(isVectorIntegerType(SrcTy));
1606     assert(isVectorFloatingType(DestTy));
1607     static const XmmEmitterRegOp Emitter = {&Assembler::cvtdq2ps,
1608                                             &Assembler::cvtdq2ps};
1609     emitIASRegOpTyXMM(Func, DestTy, Dest, Src, Emitter);
1610     return;
1611   }
1612   case Tps2dq: {
1613     assert(isVectorFloatingType(SrcTy));
1614     assert(isVectorIntegerType(DestTy));
1615     static const XmmEmitterRegOp Emitter = {&Assembler::cvttps2dq,
1616                                             &Assembler::cvttps2dq};
1617     emitIASRegOpTyXMM(Func, DestTy, Dest, Src, Emitter);
1618     return;
1619   }
1620   case Ps2dq: {
1621     assert(isVectorFloatingType(SrcTy));
1622     assert(isVectorIntegerType(DestTy));
1623     static const XmmEmitterRegOp Emitter = {&Assembler::cvtps2dq,
1624                                             &Assembler::cvtps2dq};
1625     emitIASRegOpTyXMM(Func, DestTy, Dest, Src, Emitter);
1626     return;
1627   }
1628   }
1629 }
1630 
dump(const Cfg * Func) const1631 void InstX86Cvt::dump(const Cfg *Func) const {
1632   if (!BuildDefs::dump())
1633     return;
1634   Ostream &Str = Func->getContext()->getStrDump();
1635   this->dumpDest(Func);
1636   Str << " = cvt";
1637   if (isTruncating())
1638     Str << "t";
1639   Str << TypeAttributes[this->getSrc(0)->getType()].CvtString << "2"
1640       << TypeAttributes[this->getDest()->getType()].CvtString << " ";
1641   this->dumpSources(Func);
1642 }
1643 
emit(const Cfg * Func) const1644 void InstX86Round::emit(const Cfg *Func) const {
1645   if (!BuildDefs::dump())
1646     return;
1647   Ostream &Str = Func->getContext()->getStrEmit();
1648   assert(this->getSrcSize() == 3);
1649   Str << "\t" << this->Opcode
1650       << TypeAttributes[this->getDest()->getType()].SpSdString << "\t";
1651   this->getSrc(1)->emit(Func);
1652   Str << ", ";
1653   this->getSrc(0)->emit(Func);
1654   Str << ", ";
1655   this->getDest()->emit(Func);
1656 }
1657 
emitIAS(const Cfg * Func) const1658 void InstX86Round::emitIAS(const Cfg *Func) const {
1659   assert(this->getSrcSize() == 2);
1660   assert(getInstructionSet(Func) >= SSE4_1);
1661   const Variable *Dest = this->getDest();
1662   Type Ty = Dest->getType();
1663   static const ThreeOpImmEmitter<XmmRegister, XmmRegister> Emitter = {
1664       &Assembler::round, &Assembler::round};
1665   emitIASThreeOpImmOps<XmmRegister, XmmRegister, RegX8664::getEncodedXmm,
1666                        RegX8664::getEncodedXmm>(Func, Ty, Dest, this->getSrc(0),
1667                                                 this->getSrc(1), Emitter);
1668 }
1669 
emit(const Cfg * Func) const1670 void InstX86Icmp::emit(const Cfg *Func) const {
1671   if (!BuildDefs::dump())
1672     return;
1673   Ostream &Str = Func->getContext()->getStrEmit();
1674   assert(this->getSrcSize() == 2);
1675   Str << "\t"
1676          "cmp"
1677       << this->getWidthString(this->getSrc(0)->getType()) << "\t";
1678   this->getSrc(1)->emit(Func);
1679   Str << ", ";
1680   this->getSrc(0)->emit(Func);
1681 }
1682 
emitIAS(const Cfg * Func) const1683 void InstX86Icmp::emitIAS(const Cfg *Func) const {
1684   assert(this->getSrcSize() == 2);
1685   const Operand *Src0 = this->getSrc(0);
1686   const Operand *Src1 = this->getSrc(1);
1687   Type Ty = Src0->getType();
1688   static const GPREmitterRegOp RegEmitter = {&Assembler::cmp, &Assembler::cmp,
1689                                              &Assembler::cmp};
1690   static const GPREmitterAddrOp AddrEmitter = {&Assembler::cmp,
1691                                                &Assembler::cmp};
1692   if (const auto *SrcVar0 = llvm::dyn_cast<Variable>(Src0)) {
1693     if (SrcVar0->hasReg()) {
1694       emitIASRegOpTyGPR(Func, Ty, SrcVar0, Src1, RegEmitter);
1695       return;
1696     }
1697   }
1698   emitIASAsAddrOpTyGPR(Func, Ty, Src0, Src1, AddrEmitter);
1699 }
1700 
dump(const Cfg * Func) const1701 void InstX86Icmp::dump(const Cfg *Func) const {
1702   if (!BuildDefs::dump())
1703     return;
1704   Ostream &Str = Func->getContext()->getStrDump();
1705   Str << "cmp." << this->getSrc(0)->getType() << " ";
1706   this->dumpSources(Func);
1707 }
1708 
emit(const Cfg * Func) const1709 void InstX86Ucomiss::emit(const Cfg *Func) const {
1710   if (!BuildDefs::dump())
1711     return;
1712   Ostream &Str = Func->getContext()->getStrEmit();
1713   assert(this->getSrcSize() == 2);
1714   Str << "\t"
1715          "ucomi"
1716       << TypeAttributes[this->getSrc(0)->getType()].SdSsString << "\t";
1717   this->getSrc(1)->emit(Func);
1718   Str << ", ";
1719   this->getSrc(0)->emit(Func);
1720 }
1721 
emitIAS(const Cfg * Func) const1722 void InstX86Ucomiss::emitIAS(const Cfg *Func) const {
1723   assert(this->getSrcSize() == 2);
1724   // Currently src0 is always a variable by convention, to avoid having two
1725   // memory operands.
1726   assert(llvm::isa<Variable>(this->getSrc(0)));
1727   const auto *Src0Var = llvm::cast<Variable>(this->getSrc(0));
1728   Type Ty = Src0Var->getType();
1729   static const XmmEmitterRegOp Emitter = {&Assembler::ucomiss,
1730                                           &Assembler::ucomiss};
1731   emitIASRegOpTyXMM(Func, Ty, Src0Var, this->getSrc(1), Emitter);
1732 }
1733 
dump(const Cfg * Func) const1734 void InstX86Ucomiss::dump(const Cfg *Func) const {
1735   if (!BuildDefs::dump())
1736     return;
1737   Ostream &Str = Func->getContext()->getStrDump();
1738   Str << "ucomiss." << this->getSrc(0)->getType() << " ";
1739   this->dumpSources(Func);
1740 }
1741 
emit(const Cfg * Func) const1742 void InstX86UD2::emit(const Cfg *Func) const {
1743   if (!BuildDefs::dump())
1744     return;
1745   Ostream &Str = Func->getContext()->getStrEmit();
1746   assert(this->getSrcSize() == 0);
1747   Str << "\t"
1748          "ud2";
1749 }
1750 
emitIAS(const Cfg * Func) const1751 void InstX86UD2::emitIAS(const Cfg *Func) const {
1752   Assembler *Asm = Func->getAssembler<Assembler>();
1753   Asm->ud2();
1754 }
1755 
dump(const Cfg * Func) const1756 void InstX86UD2::dump(const Cfg *Func) const {
1757   if (!BuildDefs::dump())
1758     return;
1759   Ostream &Str = Func->getContext()->getStrDump();
1760   Str << "ud2";
1761 }
1762 
emit(const Cfg * Func) const1763 void InstX86Int3::emit(const Cfg *Func) const {
1764   if (!BuildDefs::dump())
1765     return;
1766   Ostream &Str = Func->getContext()->getStrEmit();
1767   assert(this->getSrcSize() == 0);
1768   Str << "\t"
1769          "int 3";
1770 }
1771 
emitIAS(const Cfg * Func) const1772 void InstX86Int3::emitIAS(const Cfg *Func) const {
1773   Assembler *Asm = Func->getAssembler<Assembler>();
1774   Asm->int3();
1775 }
1776 
dump(const Cfg * Func) const1777 void InstX86Int3::dump(const Cfg *Func) const {
1778   if (!BuildDefs::dump())
1779     return;
1780   Ostream &Str = Func->getContext()->getStrDump();
1781   Str << "int 3";
1782 }
1783 
emit(const Cfg * Func) const1784 void InstX86Test::emit(const Cfg *Func) const {
1785   if (!BuildDefs::dump())
1786     return;
1787   Ostream &Str = Func->getContext()->getStrEmit();
1788   assert(this->getSrcSize() == 2);
1789   Str << "\t"
1790          "test"
1791       << this->getWidthString(this->getSrc(0)->getType()) << "\t";
1792   this->getSrc(1)->emit(Func);
1793   Str << ", ";
1794   this->getSrc(0)->emit(Func);
1795 }
1796 
emitIAS(const Cfg * Func) const1797 void InstX86Test::emitIAS(const Cfg *Func) const {
1798   assert(this->getSrcSize() == 2);
1799   const Operand *Src0 = this->getSrc(0);
1800   const Operand *Src1 = this->getSrc(1);
1801   Type Ty = Src0->getType();
1802   // The Reg/Addr form of test is not encodeable.
1803   static const GPREmitterRegOp RegEmitter = {&Assembler::test, nullptr,
1804                                              &Assembler::test};
1805   static const GPREmitterAddrOp AddrEmitter = {&Assembler::test,
1806                                                &Assembler::test};
1807   if (const auto *SrcVar0 = llvm::dyn_cast<Variable>(Src0)) {
1808     if (SrcVar0->hasReg()) {
1809       emitIASRegOpTyGPR(Func, Ty, SrcVar0, Src1, RegEmitter);
1810       return;
1811     }
1812   }
1813   emitIASAsAddrOpTyGPR(Func, Ty, Src0, Src1, AddrEmitter);
1814 }
1815 
dump(const Cfg * Func) const1816 void InstX86Test::dump(const Cfg *Func) const {
1817   if (!BuildDefs::dump())
1818     return;
1819   Ostream &Str = Func->getContext()->getStrDump();
1820   Str << "test." << this->getSrc(0)->getType() << " ";
1821   this->dumpSources(Func);
1822 }
1823 
emit(const Cfg * Func) const1824 void InstX86Mfence::emit(const Cfg *Func) const {
1825   if (!BuildDefs::dump())
1826     return;
1827   Ostream &Str = Func->getContext()->getStrEmit();
1828   assert(this->getSrcSize() == 0);
1829   Str << "\t"
1830          "mfence";
1831 }
1832 
emitIAS(const Cfg * Func) const1833 void InstX86Mfence::emitIAS(const Cfg *Func) const {
1834   Assembler *Asm = Func->getAssembler<Assembler>();
1835   Asm->mfence();
1836 }
1837 
dump(const Cfg * Func) const1838 void InstX86Mfence::dump(const Cfg *Func) const {
1839   if (!BuildDefs::dump())
1840     return;
1841   Ostream &Str = Func->getContext()->getStrDump();
1842   Str << "mfence";
1843 }
1844 
emit(const Cfg * Func) const1845 void InstX86Store::emit(const Cfg *Func) const {
1846   if (!BuildDefs::dump())
1847     return;
1848   Ostream &Str = Func->getContext()->getStrEmit();
1849   assert(this->getSrcSize() == 2);
1850   Type Ty = this->getSrc(0)->getType();
1851   Str << "\t"
1852          "mov"
1853       << this->getWidthString(Ty) << TypeAttributes[Ty].SdSsString << "\t";
1854   this->getSrc(0)->emit(Func);
1855   Str << ", ";
1856   this->getSrc(1)->emit(Func);
1857 }
1858 
emitIAS(const Cfg * Func) const1859 void InstX86Store::emitIAS(const Cfg *Func) const {
1860   assert(this->getSrcSize() == 2);
1861   const Operand *Dest = this->getSrc(1);
1862   const Operand *Src = this->getSrc(0);
1863   Type DestTy = Dest->getType();
1864   if (isScalarFloatingType(DestTy)) {
1865     // Src must be a register, since Dest is a Mem operand of some kind.
1866     const auto *SrcVar = llvm::cast<Variable>(Src);
1867     assert(SrcVar->hasReg());
1868     XmmRegister SrcReg = RegX8664::getEncodedXmm(SrcVar->getRegNum());
1869     Assembler *Asm = Func->getAssembler<Assembler>();
1870     auto *Target = InstX86Base::getTarget(Func);
1871     if (const auto *DestVar = llvm::dyn_cast<Variable>(Dest)) {
1872       assert(!DestVar->hasReg());
1873       AsmAddress StackAddr(AsmAddress(DestVar, Target));
1874       Asm->movss(DestTy, StackAddr, SrcReg);
1875     } else {
1876       const auto DestMem = llvm::cast<X86OperandMem>(Dest);
1877       assert(DestMem->getSegmentRegister() == X86OperandMem::DefaultSegment);
1878       Asm->movss(DestTy, AsmAddress(DestMem, Asm, Target), SrcReg);
1879     }
1880     return;
1881   } else {
1882     assert(isScalarIntegerType(DestTy));
1883     static const GPREmitterAddrOp GPRAddrEmitter = {&Assembler::mov,
1884                                                     &Assembler::mov};
1885     emitIASAsAddrOpTyGPR(Func, DestTy, Dest, Src, GPRAddrEmitter);
1886   }
1887 }
1888 
dump(const Cfg * Func) const1889 void InstX86Store::dump(const Cfg *Func) const {
1890   if (!BuildDefs::dump())
1891     return;
1892   Ostream &Str = Func->getContext()->getStrDump();
1893   Str << "mov." << this->getSrc(0)->getType() << " ";
1894   this->getSrc(1)->dump(Func);
1895   Str << ", ";
1896   this->getSrc(0)->dump(Func);
1897 }
1898 
emit(const Cfg * Func) const1899 void InstX86StoreP::emit(const Cfg *Func) const {
1900   if (!BuildDefs::dump())
1901     return;
1902   Ostream &Str = Func->getContext()->getStrEmit();
1903   assert(this->getSrcSize() == 2);
1904   assert(isVectorType(this->getSrc(1)->getType()));
1905   Str << "\t"
1906          "movups\t";
1907   this->getSrc(0)->emit(Func);
1908   Str << ", ";
1909   this->getSrc(1)->emit(Func);
1910 }
1911 
emitIAS(const Cfg * Func) const1912 void InstX86StoreP::emitIAS(const Cfg *Func) const {
1913   Assembler *Asm = Func->getAssembler<Assembler>();
1914   assert(this->getSrcSize() == 2);
1915   const auto *SrcVar = llvm::cast<Variable>(this->getSrc(0));
1916   const auto DestMem = llvm::cast<X86OperandMem>(this->getSrc(1));
1917   assert(DestMem->getSegmentRegister() == X86OperandMem::DefaultSegment);
1918   assert(SrcVar->hasReg());
1919   auto *Target = InstX86Base::getTarget(Func);
1920   Asm->movups(AsmAddress(DestMem, Asm, Target),
1921               RegX8664::getEncodedXmm(SrcVar->getRegNum()));
1922 }
1923 
dump(const Cfg * Func) const1924 void InstX86StoreP::dump(const Cfg *Func) const {
1925   if (!BuildDefs::dump())
1926     return;
1927   Ostream &Str = Func->getContext()->getStrDump();
1928   Str << "storep." << this->getSrc(0)->getType() << " ";
1929   this->getSrc(1)->dump(Func);
1930   Str << ", ";
1931   this->getSrc(0)->dump(Func);
1932 }
1933 
emit(const Cfg * Func) const1934 void InstX86StoreQ::emit(const Cfg *Func) const {
1935   if (!BuildDefs::dump())
1936     return;
1937   Ostream &Str = Func->getContext()->getStrEmit();
1938   assert(this->getSrcSize() == 2);
1939   assert(this->getSrc(1)->getType() == IceType_i64 ||
1940          this->getSrc(1)->getType() == IceType_f64 ||
1941          isVectorType(this->getSrc(1)->getType()));
1942   Str << "\t"
1943          "movq\t";
1944   this->getSrc(0)->emit(Func);
1945   Str << ", ";
1946   this->getSrc(1)->emit(Func);
1947 }
1948 
emitIAS(const Cfg * Func) const1949 void InstX86StoreQ::emitIAS(const Cfg *Func) const {
1950   Assembler *Asm = Func->getAssembler<Assembler>();
1951   assert(this->getSrcSize() == 2);
1952   const auto *SrcVar = llvm::cast<Variable>(this->getSrc(0));
1953   const auto DestMem = llvm::cast<X86OperandMem>(this->getSrc(1));
1954   assert(DestMem->getSegmentRegister() == X86OperandMem::DefaultSegment);
1955   assert(SrcVar->hasReg());
1956   auto *Target = InstX86Base::getTarget(Func);
1957   Asm->movq(AsmAddress(DestMem, Asm, Target),
1958             RegX8664::getEncodedXmm(SrcVar->getRegNum()));
1959 }
1960 
dump(const Cfg * Func) const1961 void InstX86StoreQ::dump(const Cfg *Func) const {
1962   if (!BuildDefs::dump())
1963     return;
1964   Ostream &Str = Func->getContext()->getStrDump();
1965   Str << "storeq." << this->getSrc(0)->getType() << " ";
1966   this->getSrc(1)->dump(Func);
1967   Str << ", ";
1968   this->getSrc(0)->dump(Func);
1969 }
1970 
emit(const Cfg * Func) const1971 void InstX86StoreD::emit(const Cfg *Func) const {
1972   if (!BuildDefs::dump())
1973     return;
1974   Ostream &Str = Func->getContext()->getStrEmit();
1975   assert(this->getSrcSize() == 2);
1976   assert(this->getSrc(1)->getType() == IceType_i64 ||
1977          this->getSrc(1)->getType() == IceType_f64 ||
1978          isVectorType(this->getSrc(1)->getType()));
1979   Str << "\t"
1980          "movd\t";
1981   this->getSrc(0)->emit(Func);
1982   Str << ", ";
1983   this->getSrc(1)->emit(Func);
1984 }
1985 
emitIAS(const Cfg * Func) const1986 void InstX86StoreD::emitIAS(const Cfg *Func) const {
1987   Assembler *Asm = Func->getAssembler<Assembler>();
1988   assert(this->getSrcSize() == 2);
1989   const auto *SrcVar = llvm::cast<Variable>(this->getSrc(0));
1990   const auto DestMem = llvm::cast<X86OperandMem>(this->getSrc(1));
1991   assert(DestMem->getSegmentRegister() == X86OperandMem::DefaultSegment);
1992   assert(SrcVar->hasReg());
1993   auto *Target = InstX86Base::getTarget(Func);
1994   Asm->movd(SrcVar->getType(), AsmAddress(DestMem, Asm, Target),
1995             RegX8664::getEncodedXmm(SrcVar->getRegNum()));
1996 }
1997 
dump(const Cfg * Func) const1998 void InstX86StoreD::dump(const Cfg *Func) const {
1999   if (!BuildDefs::dump())
2000     return;
2001   Ostream &Str = Func->getContext()->getStrDump();
2002   Str << "stored." << this->getSrc(0)->getType() << " ";
2003   this->getSrc(1)->dump(Func);
2004   Str << ", ";
2005   this->getSrc(0)->dump(Func);
2006 }
2007 
emit(const Cfg * Func) const2008 void InstX86Lea::emit(const Cfg *Func) const {
2009   if (!BuildDefs::dump())
2010     return;
2011   if (auto *Add = this->deoptToAddOrNull(Func)) {
2012     Add->emit(Func);
2013     return;
2014   }
2015 
2016   Ostream &Str = Func->getContext()->getStrEmit();
2017   assert(this->getSrcSize() == 1);
2018   assert(this->getDest()->hasReg());
2019   Str << "\t"
2020          "lea"
2021       << this->getWidthString(this->getDest()->getType()) << "\t";
2022   Operand *Src0 = this->getSrc(0);
2023   if (const auto *Src0Var = llvm::dyn_cast<Variable>(Src0)) {
2024     Type Ty = Src0Var->getType();
2025     // lea on x86-32 doesn't accept mem128 operands, so cast VSrc0 to an
2026     // acceptable type.
2027     Src0Var->asType(Func, isVectorType(Ty) ? IceType_i32 : Ty, RegNumT())
2028         ->emit(Func);
2029   } else {
2030     Src0->emit(Func);
2031   }
2032   Str << ", ";
2033   this->getDest()->emit(Func);
2034 }
2035 
emitIAS(const Cfg * Func) const2036 void InstX86Lea::emitIAS(const Cfg *Func) const {
2037   assert(this->getSrcSize() == 1);
2038   const Variable *Var = this->getDest();
2039   Type Ty = Var->getType();
2040   const Operand *Src = this->getSrc(0);
2041 
2042   if (auto *Add = this->deoptToAddOrNull(Func)) {
2043     Add->emitIAS(Func);
2044     return;
2045   }
2046 
2047   emitIASRegOpTyGPR(Func, Ty, Var, Src, Emitter);
2048 }
2049 
deoptToAddOrNull(const Cfg * Func) const2050 Inst *InstX86Lea::deoptToAddOrNull(const Cfg *Func) const {
2051   // Revert back to Add when the Lea is a 2-address instruction.
2052   // Caller has to emit, this just produces the add instruction.
2053   if (auto *MemOp = llvm::dyn_cast<X86OperandMem>(this->getSrc(0))) {
2054     if (getFlags().getAggressiveLea() &&
2055         MemOp->getBase()->getRegNum() == this->getDest()->getRegNum() &&
2056         MemOp->getIndex() == nullptr && MemOp->getShift() == 0) {
2057       auto *Add = InstX86Add::create(const_cast<Cfg *>(Func), this->getDest(),
2058                                      MemOp->getOffset());
2059       // TODO(manasijm): Remove const_cast by emitting code for add
2060       // directly.
2061       return Add;
2062     }
2063   }
2064   return nullptr;
2065 }
2066 
emit(const Cfg * Func) const2067 void InstX86Mov::emit(const Cfg *Func) const {
2068   if (!BuildDefs::dump())
2069     return;
2070   Ostream &Str = Func->getContext()->getStrEmit();
2071   assert(this->getSrcSize() == 1);
2072   Operand *Src = this->getSrc(0);
2073   Type SrcTy = Src->getType();
2074   Type DestTy = this->getDest()->getType();
2075   if (DestTy == IceType_i64 && llvm::isa<ConstantInteger64>(Src) &&
2076       !Utils::IsInt(32, llvm::cast<ConstantInteger64>(Src)->getValue())) {
2077     Str << "\t"
2078            "movabs"
2079            "\t";
2080   } else {
2081     Str << "\t"
2082            "mov"
2083         << (!isScalarFloatingType(DestTy) ? this->getWidthString(DestTy)
2084                                           : TypeAttributes[DestTy].SdSsString)
2085         << "\t";
2086   }
2087   // For an integer truncation operation, src is wider than dest. In this case,
2088   // we use a mov instruction whose data width matches the narrower dest.
2089   // TODO: This assert disallows usages such as copying a floating
2090   // point value between a vector and a scalar (which movss is used for). Clean
2091   // this up.
2092   assert(InstX86Base::getTarget(Func)->typeWidthInBytesOnStack(DestTy) ==
2093          InstX86Base::getTarget(Func)->typeWidthInBytesOnStack(SrcTy));
2094   const Operand *NewSrc = Src;
2095   if (auto *SrcVar = llvm::dyn_cast<Variable>(Src)) {
2096     RegNumT NewRegNum;
2097     if (SrcVar->hasReg())
2098       NewRegNum = RegX8664::getGprForType(DestTy, SrcVar->getRegNum());
2099     if (SrcTy != DestTy)
2100       NewSrc = SrcVar->asType(Func, DestTy, NewRegNum);
2101   }
2102   NewSrc->emit(Func);
2103   Str << ", ";
2104   this->getDest()->emit(Func);
2105 }
2106 
emitIAS(const Cfg * Func) const2107 void InstX86Mov::emitIAS(const Cfg *Func) const {
2108   assert(this->getSrcSize() == 1);
2109   const Variable *Dest = this->getDest();
2110   const Operand *Src = this->getSrc(0);
2111   Type DestTy = Dest->getType();
2112   Type SrcTy = Src->getType();
2113   // Mov can be used for GPRs or XMM registers. Also, the type does not
2114   // necessarily match (Mov can be used for bitcasts). However, when the type
2115   // does not match, one of the operands must be a register. Thus, the strategy
2116   // is to find out if Src or Dest are a register, then use that register's
2117   // type to decide on which emitter set to use. The emitter set will include
2118   // reg-reg movs, but that case should be unused when the types don't match.
2119   static const XmmEmitterRegOp XmmRegEmitter = {&Assembler::movss,
2120                                                 &Assembler::movss};
2121   static const GPREmitterRegOp GPRRegEmitter = {
2122       &Assembler::mov, &Assembler::mov, &Assembler::mov};
2123   static const GPREmitterAddrOp GPRAddrEmitter = {&Assembler::mov,
2124                                                   &Assembler::mov};
2125   // For an integer truncation operation, src is wider than dest. In this case,
2126   // we use a mov instruction whose data width matches the narrower dest.
2127   // TODO: This assert disallows usages such as copying a floating
2128   // point value between a vector and a scalar (which movss is used for). Clean
2129   // this up.
2130   auto *Target = InstX86Base::getTarget(Func);
2131   assert(Target->typeWidthInBytesOnStack(this->getDest()->getType()) ==
2132          Target->typeWidthInBytesOnStack(Src->getType()));
2133   if (Dest->hasReg()) {
2134     if (isScalarFloatingType(DestTy)) {
2135       emitIASRegOpTyXMM(Func, DestTy, Dest, Src, XmmRegEmitter);
2136       return;
2137     } else {
2138       assert(isScalarIntegerType(DestTy));
2139       // Widen DestTy for truncation (see above note). We should only do this
2140       // when both Src and Dest are integer types.
2141       if (DestTy == IceType_i64) {
2142         if (const auto *C64 = llvm::dyn_cast<ConstantInteger64>(Src)) {
2143           Func->getAssembler<Assembler>()->movabs(
2144               RegX8664::getEncodedGPR(Dest->getRegNum()), C64->getValue());
2145           return;
2146         }
2147       }
2148       if (isScalarIntegerType(SrcTy)) {
2149         SrcTy = DestTy;
2150       }
2151       emitIASRegOpTyGPR(Func, DestTy, Dest, Src, GPRRegEmitter);
2152       return;
2153     }
2154   } else {
2155     // Dest must be Stack and Src *could* be a register. Use Src's type to
2156     // decide on the emitters.
2157     AsmAddress StackAddr(AsmAddress(Dest, Target));
2158     if (isScalarFloatingType(SrcTy)) {
2159       // Src must be a register.
2160       const auto *SrcVar = llvm::cast<Variable>(Src);
2161       assert(SrcVar->hasReg());
2162       Assembler *Asm = Func->getAssembler<Assembler>();
2163       Asm->movss(SrcTy, StackAddr,
2164                  RegX8664::getEncodedXmm(SrcVar->getRegNum()));
2165       return;
2166     } else if (isVectorType(SrcTy)) {
2167       // Src must be a register
2168       const auto *SrcVar = llvm::cast<Variable>(Src);
2169       assert(SrcVar->hasReg());
2170       Assembler *Asm = Func->getAssembler<Assembler>();
2171       Asm->movups(StackAddr, RegX8664::getEncodedXmm(SrcVar->getRegNum()));
2172     } else {
2173       // Src can be a register or immediate.
2174       assert(isScalarIntegerType(SrcTy));
2175       emitIASAddrOpTyGPR(Func, SrcTy, StackAddr, Src, GPRAddrEmitter);
2176       return;
2177     }
2178     return;
2179   }
2180 }
2181 
emit(const Cfg * Func) const2182 void InstX86Movd::emit(const Cfg *Func) const {
2183   if (!BuildDefs::dump())
2184     return;
2185   assert(this->getSrcSize() == 1);
2186   Variable *Dest = this->getDest();
2187   Operand *Src = this->getSrc(0);
2188 
2189   if (Dest->getType() == IceType_i64 || Src->getType() == IceType_i64) {
2190     assert(Dest->getType() == IceType_f64 || Src->getType() == IceType_f64);
2191     assert(Dest->getType() != Src->getType());
2192     Ostream &Str = Func->getContext()->getStrEmit();
2193     Str << "\t"
2194            "movq"
2195            "\t";
2196     Src->emit(Func);
2197     Str << ", ";
2198     Dest->emit(Func);
2199     return;
2200   }
2201 
2202   InstX86BaseUnaryopXmm<InstX86Base::Movd>::emit(Func);
2203 }
2204 
emitIAS(const Cfg * Func) const2205 void InstX86Movd::emitIAS(const Cfg *Func) const {
2206   Assembler *Asm = Func->getAssembler<Assembler>();
2207   assert(this->getSrcSize() == 1);
2208   const Variable *Dest = this->getDest();
2209   auto *Target = InstX86Base::getTarget(Func);
2210   // For insert/extract element (one of Src/Dest is an Xmm vector and the other
2211   // is an int type).
2212   if (const auto *SrcVar = llvm::dyn_cast<Variable>(this->getSrc(0))) {
2213     if (SrcVar->getType() == IceType_i32 || SrcVar->getType() == IceType_i64) {
2214       assert(isVectorType(Dest->getType()) ||
2215              (isScalarFloatingType(Dest->getType()) &&
2216               typeWidthInBytes(SrcVar->getType()) ==
2217                   typeWidthInBytes(Dest->getType())));
2218       assert(Dest->hasReg());
2219       XmmRegister DestReg = RegX8664::getEncodedXmm(Dest->getRegNum());
2220       if (SrcVar->hasReg()) {
2221         Asm->movd(SrcVar->getType(), DestReg,
2222                   RegX8664::getEncodedGPR(SrcVar->getRegNum()));
2223       } else {
2224         AsmAddress StackAddr(AsmAddress(SrcVar, Target));
2225         Asm->movd(SrcVar->getType(), DestReg, StackAddr);
2226       }
2227     } else {
2228       assert(isVectorType(SrcVar->getType()) ||
2229              (isScalarFloatingType(SrcVar->getType()) &&
2230               typeWidthInBytes(SrcVar->getType()) ==
2231                   typeWidthInBytes(Dest->getType())));
2232       assert(SrcVar->hasReg());
2233       assert(Dest->getType() == IceType_i32 || Dest->getType() == IceType_i64);
2234       XmmRegister SrcReg = RegX8664::getEncodedXmm(SrcVar->getRegNum());
2235       if (Dest->hasReg()) {
2236         Asm->movd(Dest->getType(), RegX8664::getEncodedGPR(Dest->getRegNum()),
2237                   SrcReg);
2238       } else {
2239         AsmAddress StackAddr(AsmAddress(Dest, Target));
2240         Asm->movd(Dest->getType(), StackAddr, SrcReg);
2241       }
2242     }
2243   } else {
2244     assert(Dest->hasReg());
2245     XmmRegister DestReg = RegX8664::getEncodedXmm(Dest->getRegNum());
2246     auto *Mem = llvm::cast<X86OperandMem>(this->getSrc(0));
2247     Asm->movd(Mem->getType(), DestReg, AsmAddress(Mem, Asm, Target));
2248   }
2249 }
2250 
emit(const Cfg * Func) const2251 void InstX86Movp::emit(const Cfg *Func) const {
2252   if (!BuildDefs::dump())
2253     return;
2254   // TODO(wala,stichnot): movups works with all vector operands, but there
2255   // exist other instructions (movaps, movdqa, movdqu) that may perform better,
2256   // depending on the data type and alignment of the operands.
2257   Ostream &Str = Func->getContext()->getStrEmit();
2258   assert(this->getSrcSize() == 1);
2259   Str << "\t"
2260          "movups\t";
2261   this->getSrc(0)->emit(Func);
2262   Str << ", ";
2263   this->getDest()->emit(Func);
2264 }
2265 
emitIAS(const Cfg * Func) const2266 void InstX86Movp::emitIAS(const Cfg *Func) const {
2267   assert(this->getSrcSize() == 1);
2268   assert(isVectorType(this->getDest()->getType()));
2269   const Variable *Dest = this->getDest();
2270   const Operand *Src = this->getSrc(0);
2271   static const XmmEmitterMovOps Emitter = {
2272       &Assembler::movups, &Assembler::movups, &Assembler::movups};
2273   emitIASMovlikeXMM(Func, Dest, Src, Emitter);
2274 }
2275 
emit(const Cfg * Func) const2276 void InstX86Movq::emit(const Cfg *Func) const {
2277   if (!BuildDefs::dump())
2278     return;
2279   Ostream &Str = Func->getContext()->getStrEmit();
2280   assert(this->getSrcSize() == 1);
2281   assert(this->getDest()->getType() == IceType_i64 ||
2282          this->getDest()->getType() == IceType_f64);
2283   Str << "\t"
2284          "movq"
2285          "\t";
2286   this->getSrc(0)->emit(Func);
2287   Str << ", ";
2288   this->getDest()->emit(Func);
2289 }
2290 
emitIAS(const Cfg * Func) const2291 void InstX86Movq::emitIAS(const Cfg *Func) const {
2292   assert(this->getSrcSize() == 1);
2293   assert(this->getDest()->getType() == IceType_i64 ||
2294          this->getDest()->getType() == IceType_f64 ||
2295          isVectorType(this->getDest()->getType()));
2296   const Variable *Dest = this->getDest();
2297   const Operand *Src = this->getSrc(0);
2298   static const XmmEmitterMovOps Emitter = {&Assembler::movq, &Assembler::movq,
2299                                            &Assembler::movq};
2300   emitIASMovlikeXMM(Func, Dest, Src, Emitter);
2301 }
2302 
emitIAS(const Cfg * Func) const2303 void InstX86MovssRegs::emitIAS(const Cfg *Func) const {
2304   // This is Binop variant is only intended to be used for reg-reg moves where
2305   // part of the Dest register is untouched.
2306   assert(this->getSrcSize() == 2);
2307   const Variable *Dest = this->getDest();
2308   assert(Dest == this->getSrc(0));
2309   const auto *SrcVar = llvm::cast<Variable>(this->getSrc(1));
2310   assert(Dest->hasReg() && SrcVar->hasReg());
2311   Assembler *Asm = Func->getAssembler<Assembler>();
2312   Asm->movss(IceType_f32, RegX8664::getEncodedXmm(Dest->getRegNum()),
2313              RegX8664::getEncodedXmm(SrcVar->getRegNum()));
2314 }
2315 
emitIAS(const Cfg * Func) const2316 void InstX86Movsx::emitIAS(const Cfg *Func) const {
2317   assert(this->getSrcSize() == 1);
2318   const Variable *Dest = this->getDest();
2319   const Operand *Src = this->getSrc(0);
2320   // Dest must be a > 8-bit register, but Src can be 8-bit. In practice we just
2321   // use the full register for Dest to avoid having an OperandSizeOverride
2322   // prefix. It also allows us to only dispatch on SrcTy.
2323   Type SrcTy = Src->getType();
2324   assert(typeWidthInBytes(Dest->getType()) > 1);
2325   assert(typeWidthInBytes(Dest->getType()) > typeWidthInBytes(SrcTy));
2326   emitIASRegOpTyGPR<false, true>(Func, SrcTy, Dest, Src, this->Emitter);
2327 }
2328 
mayBeElided(const Variable * Dest,const Operand * SrcOpnd) const2329 bool InstX86Movzx::mayBeElided(const Variable *Dest,
2330                                const Operand *SrcOpnd) const {
2331   const auto *Src = llvm::dyn_cast<Variable>(SrcOpnd);
2332 
2333   // Src is not a Variable, so it does not have a register. Movzx can't be
2334   // elided.
2335   if (Src == nullptr)
2336     return false;
2337 
2338   // Movzx to/from memory can't be elided.
2339   if (!Src->hasReg() || !Dest->hasReg())
2340     return false;
2341 
2342   // Reg/reg move with different source and dest can't be elided.
2343   if (RegX8664::getEncodedGPR(Src->getRegNum()) !=
2344       RegX8664::getEncodedGPR(Dest->getRegNum()))
2345     return false;
2346 
2347   // A must-keep movzx 32- to 64-bit is sometimes needed in x86-64 sandboxing.
2348   return !MustKeep;
2349 }
2350 
emit(const Cfg * Func) const2351 void InstX86Movzx::emit(const Cfg *Func) const {
2352   if (!BuildDefs::dump())
2353     return;
2354   // There's no movzx %eXX, %rXX. To zero extend 32- to 64-bits, we emit a
2355   // mov %eXX, %eXX. The processor will still do a movzx[bw]q.
2356   assert(this->getSrcSize() == 1);
2357   const Operand *Src = this->getSrc(0);
2358   const Variable *Dest = this->Dest;
2359   if (Src->getType() == IceType_i32 && Dest->getType() == IceType_i64) {
2360     Ostream &Str = Func->getContext()->getStrEmit();
2361     if (mayBeElided(Dest, Src)) {
2362       Str << "\t/* elided movzx */";
2363     } else {
2364       Str << "\t"
2365              "mov"
2366              "\t";
2367       Src->emit(Func);
2368       Str << ", ";
2369       Dest->asType(Func, IceType_i32,
2370                    RegX8664::getGprForType(IceType_i32, Dest->getRegNum()))
2371           ->emit(Func);
2372       Str << " /* movzx */";
2373     }
2374     return;
2375   }
2376   InstX86BaseUnaryopGPR<InstX86Base::Movzx>::emit(Func);
2377 }
2378 
emitIAS(const Cfg * Func) const2379 void InstX86Movzx::emitIAS(const Cfg *Func) const {
2380   assert(this->getSrcSize() == 1);
2381   const Variable *Dest = this->getDest();
2382   const Operand *Src = this->getSrc(0);
2383   Type SrcTy = Src->getType();
2384   assert(typeWidthInBytes(Dest->getType()) > 1);
2385   assert(typeWidthInBytes(Dest->getType()) > typeWidthInBytes(SrcTy));
2386   if (Src->getType() == IceType_i32 && Dest->getType() == IceType_i64 &&
2387       mayBeElided(Dest, Src)) {
2388     return;
2389   }
2390   emitIASRegOpTyGPR<false, true>(Func, SrcTy, Dest, Src, this->Emitter);
2391 }
2392 
emit(const Cfg * Func) const2393 void InstX86Nop::emit(const Cfg *Func) const {
2394   if (!BuildDefs::dump())
2395     return;
2396   Ostream &Str = Func->getContext()->getStrEmit();
2397   // TODO: Emit the right code for each variant.
2398   Str << "\t"
2399          "nop\t/* variant = "
2400       << Variant << " */";
2401 }
2402 
emitIAS(const Cfg * Func) const2403 void InstX86Nop::emitIAS(const Cfg *Func) const {
2404   Assembler *Asm = Func->getAssembler<Assembler>();
2405   // TODO: Emit the right code for the variant.
2406   Asm->nop();
2407 }
2408 
dump(const Cfg * Func) const2409 void InstX86Nop::dump(const Cfg *Func) const {
2410   if (!BuildDefs::dump())
2411     return;
2412   Ostream &Str = Func->getContext()->getStrDump();
2413   Str << "nop (variant = " << Variant << ")";
2414 }
2415 
emit(const Cfg * Func) const2416 void InstX86Pextr::emit(const Cfg *Func) const {
2417   if (!BuildDefs::dump())
2418     return;
2419   Ostream &Str = Func->getContext()->getStrEmit();
2420   assert(this->getSrcSize() == 2);
2421   // pextrb and pextrd are SSE4.1 instructions.
2422   Str << "\t" << this->Opcode
2423       << TypeAttributes[this->getSrc(0)->getType()].IntegralString << "\t";
2424   this->getSrc(1)->emit(Func);
2425   Str << ", ";
2426   this->getSrc(0)->emit(Func);
2427   Str << ", ";
2428   Variable *Dest = this->getDest();
2429   // pextrw must take a register dest. There is an SSE4.1 version that takes a
2430   // memory dest, but we aren't using it. For uniformity, just restrict them
2431   // all to have a register dest for now.
2432   assert(Dest->hasReg());
2433   Dest->asType(Func, IceType_i32, Dest->getRegNum())->emit(Func);
2434 }
2435 
emitIAS(const Cfg * Func) const2436 void InstX86Pextr::emitIAS(const Cfg *Func) const {
2437   assert(this->getSrcSize() == 2);
2438   // pextrb and pextrd are SSE4.1 instructions.
2439   const Variable *Dest = this->getDest();
2440   Type DispatchTy = getInVectorElementType(this->getSrc(0)->getType());
2441   // pextrw must take a register dest. There is an SSE4.1 version that takes a
2442   // memory dest, but we aren't using it. For uniformity, just restrict them
2443   // all to have a register dest for now.
2444   assert(Dest->hasReg());
2445   // pextrw's Src(0) must be a register (both SSE4.1 and SSE2).
2446   assert(llvm::cast<Variable>(this->getSrc(0))->hasReg());
2447   static const ThreeOpImmEmitter<GPRRegister, XmmRegister> Emitter = {
2448       &Assembler::pextr, nullptr};
2449   emitIASThreeOpImmOps<GPRRegister, XmmRegister, RegX8664::getEncodedGPR,
2450                        RegX8664::getEncodedXmm>(
2451       Func, DispatchTy, Dest, this->getSrc(0), this->getSrc(1), Emitter);
2452 }
2453 
emit(const Cfg * Func) const2454 void InstX86Pinsr::emit(const Cfg *Func) const {
2455   if (!BuildDefs::dump())
2456     return;
2457   Ostream &Str = Func->getContext()->getStrEmit();
2458   assert(this->getSrcSize() == 3);
2459   Str << "\t" << this->Opcode
2460       << TypeAttributes[this->getDest()->getType()].IntegralString << "\t";
2461   this->getSrc(2)->emit(Func);
2462   Str << ", ";
2463   Operand *Src1 = this->getSrc(1);
2464   if (const auto *Src1Var = llvm::dyn_cast<Variable>(Src1)) {
2465     // If src1 is a register, it should always be r32.
2466     if (Src1Var->hasReg()) {
2467       const auto NewRegNum = RegX8664::getBaseReg(Src1Var->getRegNum());
2468       const Variable *NewSrc = Src1Var->asType(Func, IceType_i32, NewRegNum);
2469       NewSrc->emit(Func);
2470     } else {
2471       Src1Var->emit(Func);
2472     }
2473   } else {
2474     Src1->emit(Func);
2475   }
2476   Str << ", ";
2477   this->getDest()->emit(Func);
2478 }
2479 
emitIAS(const Cfg * Func) const2480 void InstX86Pinsr::emitIAS(const Cfg *Func) const {
2481   assert(this->getSrcSize() == 3);
2482   assert(this->getDest() == this->getSrc(0));
2483   // pinsrb and pinsrd are SSE4.1 instructions.
2484   const Operand *Src0 = this->getSrc(1);
2485   Type DispatchTy = Src0->getType();
2486   // If src1 is a register, it should always be r32 (this should fall out from
2487   // the encodings for ByteRegs overlapping the encodings for r32), but we have
2488   // to make sure the register allocator didn't choose an 8-bit high register
2489   // like "ah".
2490   if (BuildDefs::asserts()) {
2491     if (auto *Src0Var = llvm::dyn_cast<Variable>(Src0)) {
2492       if (Src0Var->hasReg()) {
2493         const auto RegNum = Src0Var->getRegNum();
2494         const auto BaseRegNum = RegX8664::getBaseReg(RegNum);
2495         (void)BaseRegNum;
2496         assert(RegX8664::getEncodedGPR(RegNum) ==
2497                RegX8664::getEncodedGPR(BaseRegNum));
2498       }
2499     }
2500   }
2501   static const ThreeOpImmEmitter<XmmRegister, GPRRegister> Emitter = {
2502       &Assembler::pinsr, &Assembler::pinsr};
2503   emitIASThreeOpImmOps<XmmRegister, GPRRegister, RegX8664::getEncodedXmm,
2504                        RegX8664::getEncodedGPR>(
2505       Func, DispatchTy, this->getDest(), Src0, this->getSrc(2), Emitter);
2506 }
2507 
emitIAS(const Cfg * Func) const2508 void InstX86Pshufd::emitIAS(const Cfg *Func) const {
2509   assert(this->getSrcSize() == 2);
2510   const Variable *Dest = this->getDest();
2511   Type Ty = Dest->getType();
2512   static const ThreeOpImmEmitter<XmmRegister, XmmRegister> Emitter = {
2513       &Assembler::pshufd, &Assembler::pshufd};
2514   emitIASThreeOpImmOps<XmmRegister, XmmRegister, RegX8664::getEncodedXmm,
2515                        RegX8664::getEncodedXmm>(Func, Ty, Dest, this->getSrc(0),
2516                                                 this->getSrc(1), Emitter);
2517 }
2518 
emitIAS(const Cfg * Func) const2519 void InstX86Shufps::emitIAS(const Cfg *Func) const {
2520   assert(this->getSrcSize() == 3);
2521   const Variable *Dest = this->getDest();
2522   assert(Dest == this->getSrc(0));
2523   Type Ty = Dest->getType();
2524   static const ThreeOpImmEmitter<XmmRegister, XmmRegister> Emitter = {
2525       &Assembler::shufps, &Assembler::shufps};
2526   emitIASThreeOpImmOps<XmmRegister, XmmRegister, RegX8664::getEncodedXmm,
2527                        RegX8664::getEncodedXmm>(Func, Ty, Dest, this->getSrc(1),
2528                                                 this->getSrc(2), Emitter);
2529 }
2530 
emit(const Cfg * Func) const2531 void InstX86Pop::emit(const Cfg *Func) const {
2532   if (!BuildDefs::dump())
2533     return;
2534   Ostream &Str = Func->getContext()->getStrEmit();
2535   assert(this->getSrcSize() == 0);
2536   Str << "\t"
2537          "pop\t";
2538   this->getDest()->emit(Func);
2539 }
2540 
emitIAS(const Cfg * Func) const2541 void InstX86Pop::emitIAS(const Cfg *Func) const {
2542   assert(this->getSrcSize() == 0);
2543   Assembler *Asm = Func->getAssembler<Assembler>();
2544   if (this->getDest()->hasReg()) {
2545     Asm->popl(RegX8664::getEncodedGPR(this->getDest()->getRegNum()));
2546   } else {
2547     auto *Target = InstX86Base::getTarget(Func);
2548     Asm->popl(AsmAddress(this->getDest(), Target));
2549   }
2550 }
2551 
dump(const Cfg * Func) const2552 void InstX86Pop::dump(const Cfg *Func) const {
2553   if (!BuildDefs::dump())
2554     return;
2555   Ostream &Str = Func->getContext()->getStrDump();
2556   this->dumpDest(Func);
2557   Str << " = pop." << this->getDest()->getType() << " ";
2558 }
2559 
emit(const Cfg * Func) const2560 void InstX86Push::emit(const Cfg *Func) const {
2561   if (!BuildDefs::dump())
2562     return;
2563   Ostream &Str = Func->getContext()->getStrEmit();
2564   Str << "\t"
2565          "push"
2566          "\t";
2567   assert(this->getSrcSize() == 1);
2568   const Operand *Src = this->getSrc(0);
2569   Src->emit(Func);
2570 }
2571 
emitIAS(const Cfg * Func) const2572 void InstX86Push::emitIAS(const Cfg *Func) const {
2573   Assembler *Asm = Func->getAssembler<Assembler>();
2574 
2575   assert(this->getSrcSize() == 1);
2576   const Operand *Src = this->getSrc(0);
2577 
2578   if (const auto *Var = llvm::dyn_cast<Variable>(Src)) {
2579     Asm->pushl(RegX8664::getEncodedGPR(Var->getRegNum()));
2580   } else if (const auto *Const32 = llvm::dyn_cast<ConstantInteger32>(Src)) {
2581     Asm->pushl(AssemblerImmediate(Const32->getValue()));
2582   } else if (auto *CR = llvm::dyn_cast<ConstantRelocatable>(Src)) {
2583     Asm->pushl(CR);
2584   } else {
2585     llvm_unreachable("Unexpected operand type");
2586   }
2587 }
2588 
dump(const Cfg * Func) const2589 void InstX86Push::dump(const Cfg *Func) const {
2590   if (!BuildDefs::dump())
2591     return;
2592   Ostream &Str = Func->getContext()->getStrDump();
2593   Str << "push." << this->getSrc(0)->getType() << " ";
2594   this->dumpSources(Func);
2595 }
2596 
emit(const Cfg * Func) const2597 void InstX86Ret::emit(const Cfg *Func) const {
2598   if (!BuildDefs::dump())
2599     return;
2600   Ostream &Str = Func->getContext()->getStrEmit();
2601   Str << "\t"
2602          "ret";
2603 }
2604 
emitIAS(const Cfg * Func) const2605 void InstX86Ret::emitIAS(const Cfg *Func) const {
2606   Assembler *Asm = Func->getAssembler<Assembler>();
2607   Asm->ret();
2608 }
2609 
dump(const Cfg * Func) const2610 void InstX86Ret::dump(const Cfg *Func) const {
2611   if (!BuildDefs::dump())
2612     return;
2613   Ostream &Str = Func->getContext()->getStrDump();
2614   Type Ty =
2615       (this->getSrcSize() == 0 ? IceType_void : this->getSrc(0)->getType());
2616   Str << "ret." << Ty << " ";
2617   this->dumpSources(Func);
2618 }
2619 
emit(const Cfg * Func) const2620 void InstX86Setcc::emit(const Cfg *Func) const {
2621   if (!BuildDefs::dump())
2622     return;
2623   Ostream &Str = Func->getContext()->getStrEmit();
2624   Str << "\t"
2625          "set"
2626       << InstBrAttributes[Condition].DisplayString << "\t";
2627   this->Dest->emit(Func);
2628 }
2629 
emitIAS(const Cfg * Func) const2630 void InstX86Setcc::emitIAS(const Cfg *Func) const {
2631   assert(Condition != Cond::Br_None);
2632   assert(this->getDest()->getType() == IceType_i1);
2633   assert(this->getSrcSize() == 0);
2634   Assembler *Asm = Func->getAssembler<Assembler>();
2635   auto *Target = InstX86Base::getTarget(Func);
2636   if (this->getDest()->hasReg())
2637     Asm->setcc(Condition,
2638                RegX8664::getEncodedByteReg(this->getDest()->getRegNum()));
2639   else
2640     Asm->setcc(Condition, AsmAddress(this->getDest(), Target));
2641   return;
2642 }
2643 
dump(const Cfg * Func) const2644 void InstX86Setcc::dump(const Cfg *Func) const {
2645   if (!BuildDefs::dump())
2646     return;
2647   Ostream &Str = Func->getContext()->getStrDump();
2648   Str << "setcc." << InstBrAttributes[Condition].DisplayString << " ";
2649   this->dumpDest(Func);
2650 }
2651 
emit(const Cfg * Func) const2652 void InstX86Xadd::emit(const Cfg *Func) const {
2653   if (!BuildDefs::dump())
2654     return;
2655   Ostream &Str = Func->getContext()->getStrEmit();
2656   if (this->Locked) {
2657     Str << "\t"
2658            "lock";
2659   }
2660   Str << "\t"
2661          "xadd"
2662       << this->getWidthString(this->getSrc(0)->getType()) << "\t";
2663   this->getSrc(1)->emit(Func);
2664   Str << ", ";
2665   this->getSrc(0)->emit(Func);
2666 }
2667 
emitIAS(const Cfg * Func) const2668 void InstX86Xadd::emitIAS(const Cfg *Func) const {
2669   assert(this->getSrcSize() == 2);
2670   Assembler *Asm = Func->getAssembler<Assembler>();
2671   Type Ty = this->getSrc(0)->getType();
2672   const auto Mem = llvm::cast<X86OperandMem>(this->getSrc(0));
2673   assert(Mem->getSegmentRegister() == X86OperandMem::DefaultSegment);
2674   auto *Target = InstX86Base::getTarget(Func);
2675   const AsmAddress Addr = AsmAddress(Mem, Asm, Target);
2676   const auto *VarReg = llvm::cast<Variable>(this->getSrc(1));
2677   assert(VarReg->hasReg());
2678   const GPRRegister Reg = RegX8664::getEncodedGPR(VarReg->getRegNum());
2679   Asm->xadd(Ty, Addr, Reg, this->Locked);
2680 }
2681 
dump(const Cfg * Func) const2682 void InstX86Xadd::dump(const Cfg *Func) const {
2683   if (!BuildDefs::dump())
2684     return;
2685   Ostream &Str = Func->getContext()->getStrDump();
2686   if (this->Locked) {
2687     Str << "lock ";
2688   }
2689   Type Ty = this->getSrc(0)->getType();
2690   Str << "xadd." << Ty << " ";
2691   this->dumpSources(Func);
2692 }
2693 
emit(const Cfg * Func) const2694 void InstX86Xchg::emit(const Cfg *Func) const {
2695   if (!BuildDefs::dump())
2696     return;
2697   Ostream &Str = Func->getContext()->getStrEmit();
2698   Str << "\t"
2699          "xchg"
2700       << this->getWidthString(this->getSrc(0)->getType()) << "\t";
2701   this->getSrc(1)->emit(Func);
2702   Str << ", ";
2703   this->getSrc(0)->emit(Func);
2704 }
2705 
emitIAS(const Cfg * Func) const2706 void InstX86Xchg::emitIAS(const Cfg *Func) const {
2707   assert(this->getSrcSize() == 2);
2708   Assembler *Asm = Func->getAssembler<Assembler>();
2709   Type Ty = this->getSrc(0)->getType();
2710   const auto *VarReg1 = llvm::cast<Variable>(this->getSrc(1));
2711   assert(VarReg1->hasReg());
2712   const GPRRegister Reg1 = RegX8664::getEncodedGPR(VarReg1->getRegNum());
2713 
2714   if (const auto *VarReg0 = llvm::dyn_cast<Variable>(this->getSrc(0))) {
2715     assert(VarReg0->hasReg());
2716     const GPRRegister Reg0 = RegX8664::getEncodedGPR(VarReg0->getRegNum());
2717     Asm->xchg(Ty, Reg0, Reg1);
2718     return;
2719   }
2720 
2721   const auto *Mem = llvm::cast<X86OperandMem>(this->getSrc(0));
2722   assert(Mem->getSegmentRegister() == X86OperandMem::DefaultSegment);
2723   auto *Target = InstX86Base::getTarget(Func);
2724   const AsmAddress Addr = AsmAddress(Mem, Asm, Target);
2725   Asm->xchg(Ty, Addr, Reg1);
2726 }
2727 
dump(const Cfg * Func) const2728 void InstX86Xchg::dump(const Cfg *Func) const {
2729   if (!BuildDefs::dump())
2730     return;
2731   Ostream &Str = Func->getContext()->getStrDump();
2732   Type Ty = this->getSrc(0)->getType();
2733   Str << "xchg." << Ty << " ";
2734   this->dumpSources(Func);
2735 }
2736 
emit(const Cfg * Func) const2737 void InstX86IacaStart::emit(const Cfg *Func) const {
2738   if (!BuildDefs::dump())
2739     return;
2740   Ostream &Str = Func->getContext()->getStrEmit();
2741   Str << "\t# IACA_START\n"
2742          "\t.byte 0x0F, 0x0B\n"
2743          "\t"
2744          "movl\t$111, %ebx\n"
2745          "\t.byte 0x64, 0x67, 0x90";
2746 }
2747 
emitIAS(const Cfg * Func) const2748 void InstX86IacaStart::emitIAS(const Cfg *Func) const {
2749   Assembler *Asm = Func->getAssembler<Assembler>();
2750   Asm->iaca_start();
2751 }
2752 
dump(const Cfg * Func) const2753 void InstX86IacaStart::dump(const Cfg *Func) const {
2754   if (!BuildDefs::dump())
2755     return;
2756   Ostream &Str = Func->getContext()->getStrDump();
2757   Str << "IACA_START";
2758 }
2759 
emit(const Cfg * Func) const2760 void InstX86IacaEnd::emit(const Cfg *Func) const {
2761   if (!BuildDefs::dump())
2762     return;
2763   Ostream &Str = Func->getContext()->getStrEmit();
2764   Str << "\t# IACA_END\n"
2765          "\t"
2766          "movl\t$222, %ebx\n"
2767          "\t.byte 0x64, 0x67, 0x90\n"
2768          "\t.byte 0x0F, 0x0B";
2769 }
2770 
emitIAS(const Cfg * Func) const2771 void InstX86IacaEnd::emitIAS(const Cfg *Func) const {
2772   Assembler *Asm = Func->getAssembler<Assembler>();
2773   Asm->iaca_end();
2774 }
2775 
dump(const Cfg * Func) const2776 void InstX86IacaEnd::dump(const Cfg *Func) const {
2777   if (!BuildDefs::dump())
2778     return;
2779   Ostream &Str = Func->getContext()->getStrDump();
2780   Str << "IACA_END";
2781 }
2782 
dump(const Cfg *,Ostream & Str) const2783 void X86Operand::dump(const Cfg *, Ostream &Str) const {
2784   if (BuildDefs::dump())
2785     Str << "<OperandX8664>";
2786 }
2787 
X86OperandMem(Cfg * Func,Type Ty,Variable * Base,Constant * Offset,Variable * Index,uint16_t Shift,bool IsRebased)2788 X86OperandMem::X86OperandMem(Cfg *Func, Type Ty, Variable *Base,
2789                              Constant *Offset, Variable *Index, uint16_t Shift,
2790                              bool IsRebased)
2791     : X86Operand(kMem, Ty), Base(Base), Offset(Offset), Index(Index),
2792       Shift(Shift), IsRebased(IsRebased) {
2793   assert(Shift <= 3);
2794   Vars = nullptr;
2795   NumVars = 0;
2796   if (Base)
2797     ++NumVars;
2798   if (Index)
2799     ++NumVars;
2800   if (NumVars) {
2801     Vars = Func->allocateArrayOf<Variable *>(NumVars);
2802     SizeT I = 0;
2803     if (Base)
2804       Vars[I++] = Base;
2805     if (Index)
2806       Vars[I++] = Index;
2807     assert(I == NumVars);
2808   }
2809 }
2810 
emit(const Cfg * Func) const2811 void X86OperandMem::emit(const Cfg *Func) const {
2812   if (!BuildDefs::dump())
2813     return;
2814   const auto *Target = Func->getTarget();
2815   // If the base is rematerializable, we need to replace it with the correct
2816   // physical register (stack or base pointer), and update the Offset.
2817   int32_t Disp = 0;
2818   if (getBase() && getBase()->isRematerializable()) {
2819     Disp += getBase()->getRematerializableOffset(Target);
2820   }
2821   // The index should never be rematerializable.  But if we ever allow it, then
2822   // we should make sure the rematerialization offset is shifted by the Shift
2823   // value.
2824   if (getIndex())
2825     assert(!getIndex()->isRematerializable());
2826   Ostream &Str = Func->getContext()->getStrEmit();
2827   // Emit as Offset(Base,Index,1<<Shift). Offset is emitted without the leading
2828   // '$'. Omit the (Base,Index,1<<Shift) part if Base==nullptr.
2829   if (getOffset() == nullptr && Disp == 0) {
2830     // No offset, emit nothing.
2831   } else if (getOffset() == nullptr && Disp != 0) {
2832     Str << Disp;
2833   } else if (const auto *CI = llvm::dyn_cast<ConstantInteger32>(Offset)) {
2834     if (Base == nullptr || CI->getValue() || Disp != 0)
2835       // Emit a non-zero offset without a leading '$'.
2836       Str << CI->getValue() + Disp;
2837   } else if (const auto *CR = llvm::dyn_cast<ConstantRelocatable>(Offset)) {
2838     // TODO(sehr): ConstantRelocatable still needs updating for
2839     // rematerializable base/index and Disp.
2840     assert(Disp == 0);
2841     CR->emitWithoutPrefix(Target);
2842     if (Base == nullptr && Index == nullptr) {
2843       // rip-relative addressing.
2844       Str << "(%rip)";
2845     }
2846   } else {
2847     llvm_unreachable("Invalid offset type for x86 mem operand");
2848   }
2849 
2850   if (Base == nullptr && Index == nullptr) {
2851     return;
2852   }
2853 
2854   Str << "(";
2855   if (Base != nullptr) {
2856     const Variable *B = Base;
2857     // TODO(jpp): stop abusing the operand's type to identify LEAs.
2858     const Type MemType = getType();
2859     if (Base->getType() != IceType_i32 && MemType != IceType_void &&
2860         !isVectorType(MemType)) {
2861       // X86-64 is ILP32, but %rsp and %rbp are accessed as 64-bit registers.
2862       // For filetype=asm, they need to be emitted as their 32-bit siblings.
2863       assert(Base->getType() == IceType_i64);
2864       assert(RegX8664::getEncodedGPR(Base->getRegNum()) ==
2865                  RegX8664::Encoded_Reg_rsp ||
2866              RegX8664::getEncodedGPR(Base->getRegNum()) ==
2867                  RegX8664::Encoded_Reg_rbp ||
2868              getType() == IceType_void);
2869       B = B->asType(Func, IceType_i32,
2870                     RegX8664::getGprForType(IceType_i32, Base->getRegNum()));
2871     }
2872 
2873     B->emit(Func);
2874   }
2875 
2876   if (Index != nullptr) {
2877     Variable *I = Index;
2878     Str << ",";
2879     I->emit(Func);
2880     if (Shift)
2881       Str << "," << (1u << Shift);
2882   }
2883 
2884   Str << ")";
2885 }
2886 
dump(const Cfg * Func,Ostream & Str) const2887 void X86OperandMem::dump(const Cfg *Func, Ostream &Str) const {
2888   if (!BuildDefs::dump())
2889     return;
2890   bool Dumped = false;
2891   Str << "[";
2892   int32_t Disp = 0;
2893   if (getBase() && getBase()->isRematerializable()) {
2894     Disp += getBase()->getRematerializableOffset(Func->getTarget());
2895   }
2896   if (Base) {
2897     if (Func)
2898       Base->dump(Func);
2899     else
2900       Base->dump(Str);
2901     Dumped = true;
2902   }
2903   if (Index) {
2904     if (Base)
2905       Str << "+";
2906     if (Shift > 0)
2907       Str << (1u << Shift) << "*";
2908     if (Func)
2909       Index->dump(Func);
2910     else
2911       Index->dump(Str);
2912     Dumped = true;
2913   }
2914   if (Disp) {
2915     if (Disp > 0)
2916       Str << "+";
2917     Str << Disp;
2918     Dumped = true;
2919   }
2920   // Pretty-print the Offset.
2921   bool OffsetIsZero = false;
2922   bool OffsetIsNegative = false;
2923   if (!Offset) {
2924     OffsetIsZero = true;
2925   } else if (const auto *CI = llvm::dyn_cast<ConstantInteger32>(Offset)) {
2926     OffsetIsZero = (CI->getValue() == 0);
2927     OffsetIsNegative = (static_cast<int32_t>(CI->getValue()) < 0);
2928   } else {
2929     assert(llvm::isa<ConstantRelocatable>(Offset));
2930   }
2931   if (Dumped) {
2932     if (!OffsetIsZero) {     // Suppress if Offset is known to be 0
2933       if (!OffsetIsNegative) // Suppress if Offset is known to be negative
2934         Str << "+";
2935       Offset->dump(Func, Str);
2936     }
2937   } else {
2938     // There is only the offset.
2939     Offset->dump(Func, Str);
2940   }
2941   Str << "]";
2942 }
2943 
2944 } // namespace X8664
2945 } // end of namespace Ice
2946