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

Side by Side Diff: src/IceInstX86BaseImpl.h

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

Powered by Google App Engine
This is Rietveld 408576698