Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(568)

Side by Side Diff: src/IceInstX86BaseImpl.h

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

Powered by Google App Engine
This is Rietveld 408576698