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