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

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

Powered by Google App Engine
This is Rietveld 408576698