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