blob: 2d8f6d17a05f7215d72207a67e07bcf1e14a7e3d [file] [log] [blame]
John Porto921856d2015-07-07 11:56:26 -07001//===- subzero/src/IceInstX86BaseImpl.h - Generic X86 instructions -*- C++ -*=//
2//
3// The Subzero Code Generator
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9///
10/// \file
Jim Stichnoth92a6e5b2015-12-02 16:52:44 -080011/// \brief Implements the InstX86Base class and its descendants.
John Porto921856d2015-07-07 11:56:26 -070012///
13//===----------------------------------------------------------------------===//
14
15#ifndef SUBZERO_SRC_ICEINSTX86BASEIMPL_H
16#define SUBZERO_SRC_ICEINSTX86BASEIMPL_H
17
18#include "IceInstX86Base.h"
19
20#include "IceAssemblerX86Base.h"
21#include "IceCfg.h"
22#include "IceCfgNode.h"
23#include "IceDefs.h"
24#include "IceInst.h"
25#include "IceOperand.h"
26#include "IceTargetLowering.h"
27
28namespace Ice {
29
30namespace X86Internal {
31
32template <class Machine>
33const char *InstX86Base<Machine>::getWidthString(Type Ty) {
34 return Traits::TypeAttributes[Ty].WidthString;
35}
36
37template <class Machine>
38const char *InstX86Base<Machine>::getFldString(Type Ty) {
39 return Traits::TypeAttributes[Ty].FldString;
40}
41
42template <class Machine>
43typename InstX86Base<Machine>::Traits::Cond::BrCond
44InstX86Base<Machine>::getOppositeCondition(typename Traits::Cond::BrCond Cond) {
45 return Traits::InstBrAttributes[Cond].Opposite;
46}
47
48template <class Machine>
49InstX86FakeRMW<Machine>::InstX86FakeRMW(Cfg *Func, Operand *Data, Operand *Addr,
50 InstArithmetic::OpKind Op,
51 Variable *Beacon)
52 : InstX86Base<Machine>(Func, InstX86Base<Machine>::FakeRMW, 3, nullptr),
53 Op(Op) {
54 this->addSource(Data);
55 this->addSource(Addr);
56 this->addSource(Beacon);
57}
58
59template <class Machine>
John Porto921856d2015-07-07 11:56:26 -070060InstX86Mul<Machine>::InstX86Mul(Cfg *Func, Variable *Dest, Variable *Source1,
61 Operand *Source2)
62 : InstX86Base<Machine>(Func, InstX86Base<Machine>::Mul, 2, Dest) {
63 this->addSource(Source1);
64 this->addSource(Source2);
65}
66
67template <class Machine>
68InstX86Shld<Machine>::InstX86Shld(Cfg *Func, Variable *Dest, Variable *Source1,
David Sehr55f2e6d2015-09-22 09:17:39 -070069 Operand *Source2)
John Porto921856d2015-07-07 11:56:26 -070070 : InstX86Base<Machine>(Func, InstX86Base<Machine>::Shld, 3, Dest) {
71 this->addSource(Dest);
72 this->addSource(Source1);
73 this->addSource(Source2);
74}
75
76template <class Machine>
77InstX86Shrd<Machine>::InstX86Shrd(Cfg *Func, Variable *Dest, Variable *Source1,
David Sehr55f2e6d2015-09-22 09:17:39 -070078 Operand *Source2)
John Porto921856d2015-07-07 11:56:26 -070079 : InstX86Base<Machine>(Func, InstX86Base<Machine>::Shrd, 3, Dest) {
80 this->addSource(Dest);
81 this->addSource(Source1);
82 this->addSource(Source2);
83}
84
85template <class Machine>
86InstX86Label<Machine>::InstX86Label(
87 Cfg *Func, typename InstX86Base<Machine>::Traits::TargetLowering *Target)
88 : InstX86Base<Machine>(Func, InstX86Base<Machine>::Label, 0, nullptr),
89 Number(Target->makeNextLabelNumber()) {}
90
91template <class Machine>
92IceString InstX86Label<Machine>::getName(const Cfg *Func) const {
93 return ".L" + Func->getFunctionName() + "$local$__" + std::to_string(Number);
94}
95
96template <class Machine>
97InstX86Br<Machine>::InstX86Br(
98 Cfg *Func, const CfgNode *TargetTrue, const CfgNode *TargetFalse,
99 const InstX86Label<Machine> *Label,
Andrew Scull86df4e92015-07-30 13:54:44 -0700100 typename InstX86Base<Machine>::Traits::Cond::BrCond Condition, Mode Kind)
John Porto921856d2015-07-07 11:56:26 -0700101 : InstX86Base<Machine>(Func, InstX86Base<Machine>::Br, 0, nullptr),
102 Condition(Condition), TargetTrue(TargetTrue), TargetFalse(TargetFalse),
Andrew Scull86df4e92015-07-30 13:54:44 -0700103 Label(Label), Kind(Kind) {}
John Porto921856d2015-07-07 11:56:26 -0700104
105template <class Machine>
106bool InstX86Br<Machine>::optimizeBranch(const CfgNode *NextNode) {
Andrew Scull57e12682015-09-16 11:30:19 -0700107 // If there is no next block, then there can be no fallthrough to optimize.
John Porto921856d2015-07-07 11:56:26 -0700108 if (NextNode == nullptr)
109 return false;
110 // Intra-block conditional branches can't be optimized.
111 if (Label)
112 return false;
Andrew Scull57e12682015-09-16 11:30:19 -0700113 // If there is no fallthrough node, such as a non-default case label for a
114 // switch instruction, then there is no opportunity to optimize.
John Porto921856d2015-07-07 11:56:26 -0700115 if (getTargetFalse() == nullptr)
116 return false;
117
118 // Unconditional branch to the next node can be removed.
119 if (Condition == InstX86Base<Machine>::Traits::Cond::Br_None &&
120 getTargetFalse() == NextNode) {
121 assert(getTargetTrue() == nullptr);
122 this->setDeleted();
123 return true;
124 }
Andrew Scull57e12682015-09-16 11:30:19 -0700125 // If the fallthrough is to the next node, set fallthrough to nullptr to
126 // indicate.
John Porto921856d2015-07-07 11:56:26 -0700127 if (getTargetFalse() == NextNode) {
128 TargetFalse = nullptr;
129 return true;
130 }
Andrew Scull57e12682015-09-16 11:30:19 -0700131 // If TargetTrue is the next node, and TargetFalse is not nullptr (which was
132 // already tested above), then invert the branch condition, swap the targets,
133 // and set new fallthrough to nullptr.
John Porto921856d2015-07-07 11:56:26 -0700134 if (getTargetTrue() == NextNode) {
135 assert(Condition != InstX86Base<Machine>::Traits::Cond::Br_None);
136 Condition = this->getOppositeCondition(Condition);
137 TargetTrue = getTargetFalse();
138 TargetFalse = nullptr;
139 return true;
140 }
141 return false;
142}
143
144template <class Machine>
Andrew Scull87f80c12015-07-20 10:19:16 -0700145bool InstX86Br<Machine>::repointEdges(CfgNode *OldNode, CfgNode *NewNode) {
146 bool Found = false;
John Porto921856d2015-07-07 11:56:26 -0700147 if (TargetFalse == OldNode) {
148 TargetFalse = NewNode;
Andrew Scull87f80c12015-07-20 10:19:16 -0700149 Found = true;
John Porto921856d2015-07-07 11:56:26 -0700150 }
Andrew Scull87f80c12015-07-20 10:19:16 -0700151 if (TargetTrue == OldNode) {
152 TargetTrue = NewNode;
153 Found = true;
154 }
155 return Found;
John Porto921856d2015-07-07 11:56:26 -0700156}
157
158template <class Machine>
159InstX86Jmp<Machine>::InstX86Jmp(Cfg *Func, Operand *Target)
160 : InstX86Base<Machine>(Func, InstX86Base<Machine>::Jmp, 1, nullptr) {
161 this->addSource(Target);
162}
163
164template <class Machine>
165InstX86Call<Machine>::InstX86Call(Cfg *Func, Variable *Dest,
166 Operand *CallTarget)
167 : InstX86Base<Machine>(Func, InstX86Base<Machine>::Call, 1, Dest) {
168 this->HasSideEffects = true;
169 this->addSource(CallTarget);
170}
171
172template <class Machine>
173InstX86Cmov<Machine>::InstX86Cmov(
174 Cfg *Func, Variable *Dest, Operand *Source,
175 typename InstX86Base<Machine>::Traits::Cond::BrCond Condition)
176 : InstX86Base<Machine>(Func, InstX86Base<Machine>::Cmov, 2, Dest),
177 Condition(Condition) {
Andrew Scull57e12682015-09-16 11:30:19 -0700178 // The final result is either the original Dest, or Source, so mark both as
179 // sources.
John Porto921856d2015-07-07 11:56:26 -0700180 this->addSource(Dest);
181 this->addSource(Source);
182}
183
184template <class Machine>
185InstX86Cmpps<Machine>::InstX86Cmpps(
186 Cfg *Func, Variable *Dest, Operand *Source,
187 typename InstX86Base<Machine>::Traits::Cond::CmppsCond Condition)
188 : InstX86Base<Machine>(Func, InstX86Base<Machine>::Cmpps, 2, Dest),
189 Condition(Condition) {
190 this->addSource(Dest);
191 this->addSource(Source);
192}
193
194template <class Machine>
195InstX86Cmpxchg<Machine>::InstX86Cmpxchg(Cfg *Func, Operand *DestOrAddr,
196 Variable *Eax, Variable *Desired,
197 bool Locked)
198 : InstX86BaseLockable<Machine>(Func, InstX86Base<Machine>::Cmpxchg, 3,
199 llvm::dyn_cast<Variable>(DestOrAddr),
200 Locked) {
John Porto3c275ce2015-12-22 08:14:00 -0800201 constexpr uint16_t Encoded_rAX = 0;
202 (void)Encoded_rAX;
203 assert(InstX86Base<Machine>::Traits::getEncodedGPR(Eax->getRegNum()) ==
204 Encoded_rAX);
John Porto921856d2015-07-07 11:56:26 -0700205 this->addSource(DestOrAddr);
206 this->addSource(Eax);
207 this->addSource(Desired);
208}
209
210template <class Machine>
211InstX86Cmpxchg8b<Machine>::InstX86Cmpxchg8b(
212 Cfg *Func, typename InstX86Base<Machine>::Traits::X86OperandMem *Addr,
213 Variable *Edx, Variable *Eax, Variable *Ecx, Variable *Ebx, bool Locked)
214 : InstX86BaseLockable<Machine>(Func, InstX86Base<Machine>::Cmpxchg, 5,
215 nullptr, Locked) {
216 assert(Edx->getRegNum() ==
217 InstX86Base<Machine>::Traits::RegisterSet::Reg_edx);
218 assert(Eax->getRegNum() ==
219 InstX86Base<Machine>::Traits::RegisterSet::Reg_eax);
220 assert(Ecx->getRegNum() ==
221 InstX86Base<Machine>::Traits::RegisterSet::Reg_ecx);
222 assert(Ebx->getRegNum() ==
223 InstX86Base<Machine>::Traits::RegisterSet::Reg_ebx);
224 this->addSource(Addr);
225 this->addSource(Edx);
226 this->addSource(Eax);
227 this->addSource(Ecx);
228 this->addSource(Ebx);
229}
230
231template <class Machine>
232InstX86Cvt<Machine>::InstX86Cvt(Cfg *Func, Variable *Dest, Operand *Source,
233 CvtVariant Variant)
234 : InstX86Base<Machine>(Func, InstX86Base<Machine>::Cvt, 1, Dest),
235 Variant(Variant) {
236 this->addSource(Source);
237}
238
239template <class Machine>
240InstX86Icmp<Machine>::InstX86Icmp(Cfg *Func, Operand *Src0, Operand *Src1)
241 : InstX86Base<Machine>(Func, InstX86Base<Machine>::Icmp, 2, nullptr) {
242 this->addSource(Src0);
243 this->addSource(Src1);
244}
245
246template <class Machine>
247InstX86Ucomiss<Machine>::InstX86Ucomiss(Cfg *Func, Operand *Src0, Operand *Src1)
248 : InstX86Base<Machine>(Func, InstX86Base<Machine>::Ucomiss, 2, nullptr) {
249 this->addSource(Src0);
250 this->addSource(Src1);
251}
252
253template <class Machine>
254InstX86UD2<Machine>::InstX86UD2(Cfg *Func)
255 : InstX86Base<Machine>(Func, InstX86Base<Machine>::UD2, 0, nullptr) {}
256
257template <class Machine>
258InstX86Test<Machine>::InstX86Test(Cfg *Func, Operand *Src1, Operand *Src2)
259 : InstX86Base<Machine>(Func, InstX86Base<Machine>::Test, 2, nullptr) {
260 this->addSource(Src1);
261 this->addSource(Src2);
262}
263
264template <class Machine>
265InstX86Mfence<Machine>::InstX86Mfence(Cfg *Func)
266 : InstX86Base<Machine>(Func, InstX86Base<Machine>::Mfence, 0, nullptr) {
267 this->HasSideEffects = true;
268}
269
270template <class Machine>
271InstX86Store<Machine>::InstX86Store(
272 Cfg *Func, Operand *Value,
273 typename InstX86Base<Machine>::Traits::X86Operand *Mem)
274 : InstX86Base<Machine>(Func, InstX86Base<Machine>::Store, 2, nullptr) {
275 this->addSource(Value);
276 this->addSource(Mem);
277}
278
279template <class Machine>
280InstX86StoreP<Machine>::InstX86StoreP(
281 Cfg *Func, Variable *Value,
282 typename InstX86Base<Machine>::Traits::X86OperandMem *Mem)
283 : InstX86Base<Machine>(Func, InstX86Base<Machine>::StoreP, 2, nullptr) {
284 this->addSource(Value);
285 this->addSource(Mem);
286}
287
288template <class Machine>
289InstX86StoreQ<Machine>::InstX86StoreQ(
290 Cfg *Func, Variable *Value,
291 typename InstX86Base<Machine>::Traits::X86OperandMem *Mem)
292 : InstX86Base<Machine>(Func, InstX86Base<Machine>::StoreQ, 2, nullptr) {
293 this->addSource(Value);
294 this->addSource(Mem);
295}
296
297template <class Machine>
298InstX86Nop<Machine>::InstX86Nop(Cfg *Func, InstX86Nop::NopVariant Variant)
299 : InstX86Base<Machine>(Func, InstX86Base<Machine>::Nop, 0, nullptr),
300 Variant(Variant) {}
301
302template <class Machine>
303InstX86Fld<Machine>::InstX86Fld(Cfg *Func, Operand *Src)
304 : InstX86Base<Machine>(Func, InstX86Base<Machine>::Fld, 1, nullptr) {
305 this->addSource(Src);
306}
307
308template <class Machine>
309InstX86Fstp<Machine>::InstX86Fstp(Cfg *Func, Variable *Dest)
310 : InstX86Base<Machine>(Func, InstX86Base<Machine>::Fstp, 0, Dest) {}
311
312template <class Machine>
313InstX86Pop<Machine>::InstX86Pop(Cfg *Func, Variable *Dest)
314 : InstX86Base<Machine>(Func, InstX86Base<Machine>::Pop, 0, Dest) {
Andrew Scull57e12682015-09-16 11:30:19 -0700315 // A pop instruction affects the stack pointer and so it should not be
316 // allowed to be automatically dead-code eliminated. (The corresponding push
317 // instruction doesn't need this treatment because it has no dest variable
318 // and therefore won't be dead-code eliminated.) This is needed for
319 // late-stage liveness analysis (e.g. asm-verbose mode).
John Porto921856d2015-07-07 11:56:26 -0700320 this->HasSideEffects = true;
321}
322
323template <class Machine>
324InstX86Push<Machine>::InstX86Push(Cfg *Func, Variable *Source)
325 : InstX86Base<Machine>(Func, InstX86Base<Machine>::Push, 1, nullptr) {
326 this->addSource(Source);
327}
328
329template <class Machine>
330InstX86Ret<Machine>::InstX86Ret(Cfg *Func, Variable *Source)
331 : InstX86Base<Machine>(Func, InstX86Base<Machine>::Ret, Source ? 1 : 0,
332 nullptr) {
333 if (Source)
334 this->addSource(Source);
335}
336
337template <class Machine>
338InstX86Setcc<Machine>::InstX86Setcc(
339 Cfg *Func, Variable *Dest,
340 typename InstX86Base<Machine>::Traits::Cond::BrCond Cond)
341 : InstX86Base<Machine>(Func, InstX86Base<Machine>::Setcc, 0, Dest),
342 Condition(Cond) {}
343
344template <class Machine>
345InstX86Xadd<Machine>::InstX86Xadd(Cfg *Func, Operand *Dest, Variable *Source,
346 bool Locked)
347 : InstX86BaseLockable<Machine>(Func, InstX86Base<Machine>::Xadd, 2,
348 llvm::dyn_cast<Variable>(Dest), Locked) {
349 this->addSource(Dest);
350 this->addSource(Source);
351}
352
353template <class Machine>
354InstX86Xchg<Machine>::InstX86Xchg(Cfg *Func, Operand *Dest, Variable *Source)
355 : InstX86Base<Machine>(Func, InstX86Base<Machine>::Xchg, 2,
356 llvm::dyn_cast<Variable>(Dest)) {
357 this->addSource(Dest);
358 this->addSource(Source);
359}
360
Andrew Scull2c862522015-08-06 08:41:53 -0700361template <class Machine>
362InstX86IacaStart<Machine>::InstX86IacaStart(Cfg *Func)
363 : InstX86Base<Machine>(Func, InstX86Base<Machine>::IacaStart, 0, nullptr) {
364 assert(Func->getContext()->getFlags().getAllowIacaMarks());
365}
366
367template <class Machine>
368InstX86IacaEnd<Machine>::InstX86IacaEnd(Cfg *Func)
369 : InstX86Base<Machine>(Func, InstX86Base<Machine>::IacaEnd, 0, nullptr) {
370 assert(Func->getContext()->getFlags().getAllowIacaMarks());
371}
372
John Porto921856d2015-07-07 11:56:26 -0700373// ======================== Dump routines ======================== //
374
375template <class Machine>
376void 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
384template <class Machine>
385void InstX86FakeRMW<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
398template <class Machine>
399void InstX86Label<Machine>::emit(const Cfg *Func) const {
400 if (!BuildDefs::dump())
401 return;
402 Ostream &Str = Func->getContext()->getStrEmit();
403 Str << getName(Func) << ":";
404}
405
406template <class Machine>
407void InstX86Label<Machine>::emitIAS(const Cfg *Func) const {
408 typename InstX86Base<Machine>::Traits::Assembler *Asm =
409 Func->getAssembler<typename InstX86Base<Machine>::Traits::Assembler>();
Andrew Scull86df4e92015-07-30 13:54:44 -0700410 Asm->bindLocalLabel(Number);
John Porto921856d2015-07-07 11:56:26 -0700411}
412
413template <class Machine>
414void InstX86Label<Machine>::dump(const Cfg *Func) const {
415 if (!BuildDefs::dump())
416 return;
417 Ostream &Str = Func->getContext()->getStrDump();
418 Str << getName(Func) << ":";
419}
420
421template <class Machine> void InstX86Br<Machine>::emit(const Cfg *Func) const {
422 if (!BuildDefs::dump())
423 return;
424 Ostream &Str = Func->getContext()->getStrEmit();
425 Str << "\t";
426
427 if (Condition == InstX86Base<Machine>::Traits::Cond::Br_None) {
428 Str << "jmp";
429 } else {
430 Str << InstX86Base<Machine>::Traits::InstBrAttributes[Condition].EmitString;
431 }
432
433 if (Label) {
434 Str << "\t" << Label->getName(Func);
435 } else {
436 if (Condition == InstX86Base<Machine>::Traits::Cond::Br_None) {
437 Str << "\t" << getTargetFalse()->getAsmName();
438 } else {
439 Str << "\t" << getTargetTrue()->getAsmName();
440 if (getTargetFalse()) {
Jim Stichnoth6106df82015-12-16 06:17:58 -0800441 Str << "\n\t"
442 "jmp\t" << getTargetFalse()->getAsmName();
John Porto921856d2015-07-07 11:56:26 -0700443 }
444 }
445 }
446}
447
448template <class Machine>
449void InstX86Br<Machine>::emitIAS(const Cfg *Func) const {
450 typename InstX86Base<Machine>::Traits::Assembler *Asm =
451 Func->getAssembler<typename InstX86Base<Machine>::Traits::Assembler>();
452 if (Label) {
Andrew Scull86df4e92015-07-30 13:54:44 -0700453 class Label *L = Asm->getOrCreateLocalLabel(Label->getNumber());
John Porto921856d2015-07-07 11:56:26 -0700454 if (Condition == InstX86Base<Machine>::Traits::Cond::Br_None) {
Andrew Scull86df4e92015-07-30 13:54:44 -0700455 Asm->jmp(L, isNear());
John Porto921856d2015-07-07 11:56:26 -0700456 } else {
Andrew Scull86df4e92015-07-30 13:54:44 -0700457 Asm->j(Condition, L, isNear());
John Porto921856d2015-07-07 11:56:26 -0700458 }
459 } else {
John Porto921856d2015-07-07 11:56:26 -0700460 if (Condition == InstX86Base<Machine>::Traits::Cond::Br_None) {
461 class Label *L =
Andrew Scull86df4e92015-07-30 13:54:44 -0700462 Asm->getOrCreateCfgNodeLabel(getTargetFalse()->getIndex());
John Porto921856d2015-07-07 11:56:26 -0700463 assert(!getTargetTrue());
Andrew Scull86df4e92015-07-30 13:54:44 -0700464 Asm->jmp(L, isNear());
John Porto921856d2015-07-07 11:56:26 -0700465 } else {
466 class Label *L =
Andrew Scull86df4e92015-07-30 13:54:44 -0700467 Asm->getOrCreateCfgNodeLabel(getTargetTrue()->getIndex());
468 Asm->j(Condition, L, isNear());
John Porto921856d2015-07-07 11:56:26 -0700469 if (getTargetFalse()) {
470 class Label *L2 =
Andrew Scull86df4e92015-07-30 13:54:44 -0700471 Asm->getOrCreateCfgNodeLabel(getTargetFalse()->getIndex());
472 Asm->jmp(L2, isNear());
John Porto921856d2015-07-07 11:56:26 -0700473 }
474 }
475 }
476}
477
478template <class Machine> void InstX86Br<Machine>::dump(const Cfg *Func) const {
479 if (!BuildDefs::dump())
480 return;
481 Ostream &Str = Func->getContext()->getStrDump();
482 Str << "br ";
483
484 if (Condition == InstX86Base<Machine>::Traits::Cond::Br_None) {
485 Str << "label %"
486 << (Label ? Label->getName(Func) : getTargetFalse()->getName());
487 return;
488 }
489
490 Str << InstX86Base<Machine>::Traits::InstBrAttributes[Condition]
491 .DisplayString;
492 if (Label) {
493 Str << ", label %" << Label->getName(Func);
494 } else {
495 Str << ", label %" << getTargetTrue()->getName();
496 if (getTargetFalse()) {
497 Str << ", label %" << getTargetFalse()->getName();
498 }
499 }
Andrew Scull86df4e92015-07-30 13:54:44 -0700500
501 Str << " // (" << (isNear() ? "near" : "far") << " jump)";
John Porto921856d2015-07-07 11:56:26 -0700502}
503
504template <class Machine> void InstX86Jmp<Machine>::emit(const Cfg *Func) const {
505 if (!BuildDefs::dump())
506 return;
507 Ostream &Str = Func->getContext()->getStrEmit();
508 assert(this->getSrcSize() == 1);
Jim Stichnoth6106df82015-12-16 06:17:58 -0800509 Str << "\t"
510 "jmp\t*";
John Porto921856d2015-07-07 11:56:26 -0700511 getJmpTarget()->emit(Func);
512}
513
514template <class Machine>
515void InstX86Jmp<Machine>::emitIAS(const Cfg *Func) const {
516 // Note: Adapted (mostly copied) from InstX86Call<Machine>::emitIAS().
517 typename InstX86Base<Machine>::Traits::Assembler *Asm =
518 Func->getAssembler<typename InstX86Base<Machine>::Traits::Assembler>();
519 Operand *Target = getJmpTarget();
Jim Stichnoth5bff61c2015-10-28 09:26:00 -0700520 if (const auto *Var = llvm::dyn_cast<Variable>(Target)) {
John Porto921856d2015-07-07 11:56:26 -0700521 if (Var->hasReg()) {
Jim Stichnoth5bff61c2015-10-28 09:26:00 -0700522 Asm->jmp(InstX86Base<Machine>::Traits::getEncodedGPR(Var->getRegNum()));
John Porto921856d2015-07-07 11:56:26 -0700523 } else {
Andrew Scull57e12682015-09-16 11:30:19 -0700524 // The jmp instruction with a memory operand should be possible to
525 // encode, but it isn't a valid sandboxed instruction, and there
526 // shouldn't be a register allocation issue to jump through a scratch
527 // register, so we don't really need to bother implementing it.
John Porto921856d2015-07-07 11:56:26 -0700528 llvm::report_fatal_error("Assembler can't jmp to memory operand");
529 }
Jim Stichnoth5bff61c2015-10-28 09:26:00 -0700530 } else if (const auto *Mem = llvm::dyn_cast<
John Porto921856d2015-07-07 11:56:26 -0700531 typename InstX86Base<Machine>::Traits::X86OperandMem>(
532 Target)) {
533 (void)Mem;
534 assert(Mem->getSegmentRegister() ==
535 InstX86Base<Machine>::Traits::X86OperandMem::DefaultSegment);
536 llvm::report_fatal_error("Assembler can't jmp to memory operand");
Jim Stichnoth5bff61c2015-10-28 09:26:00 -0700537 } else if (const auto *CR = llvm::dyn_cast<ConstantRelocatable>(Target)) {
John Porto921856d2015-07-07 11:56:26 -0700538 assert(CR->getOffset() == 0 && "We only support jumping to a function");
539 Asm->jmp(CR);
Jim Stichnoth5bff61c2015-10-28 09:26:00 -0700540 } else if (const auto *Imm = llvm::dyn_cast<ConstantInteger32>(Target)) {
John Porto921856d2015-07-07 11:56:26 -0700541 // NaCl trampoline calls refer to an address within the sandbox directly.
Andrew Scull57e12682015-09-16 11:30:19 -0700542 // This is usually only needed for non-IRT builds and otherwise not very
543 // portable or stable. Usually this is only done for "calls" and not jumps.
544 // TODO(jvoung): Support this when there is a lowering that actually
545 // triggers this case.
John Porto921856d2015-07-07 11:56:26 -0700546 (void)Imm;
547 llvm::report_fatal_error("Unexpected jmp to absolute address");
548 } else {
549 llvm::report_fatal_error("Unexpected operand type");
550 }
551}
552
553template <class Machine> void InstX86Jmp<Machine>::dump(const Cfg *Func) const {
554 if (!BuildDefs::dump())
555 return;
556 Ostream &Str = Func->getContext()->getStrDump();
557 Str << "jmp ";
558 getJmpTarget()->dump(Func);
559}
560
561template <class Machine>
562void InstX86Call<Machine>::emit(const Cfg *Func) const {
563 if (!BuildDefs::dump())
564 return;
565 Ostream &Str = Func->getContext()->getStrEmit();
566 assert(this->getSrcSize() == 1);
Jim Stichnoth6106df82015-12-16 06:17:58 -0800567 Str << "\t"
568 "call\t";
David Sehr4318a412015-11-11 15:01:55 -0800569 Operand *CallTarget = getCallTarget();
David Sehrb8e49c12015-11-12 14:41:22 -0800570 auto *Target = InstX86Base<Machine>::getTarget(Func);
David Sehr4318a412015-11-11 15:01:55 -0800571 if (const auto *CI = llvm::dyn_cast<ConstantInteger32>(CallTarget)) {
John Porto921856d2015-07-07 11:56:26 -0700572 // Emit without a leading '$'.
573 Str << CI->getValue();
David Sehr4318a412015-11-11 15:01:55 -0800574 } else if (const auto DirectCallTarget =
575 llvm::dyn_cast<ConstantRelocatable>(CallTarget)) {
576 DirectCallTarget->emitWithoutPrefix(Target);
John Porto921856d2015-07-07 11:56:26 -0700577 } else {
578 Str << "*";
David Sehr4318a412015-11-11 15:01:55 -0800579 CallTarget->emit(Func);
John Porto921856d2015-07-07 11:56:26 -0700580 }
John Porto921856d2015-07-07 11:56:26 -0700581}
582
583template <class Machine>
584void InstX86Call<Machine>::emitIAS(const Cfg *Func) const {
585 typename InstX86Base<Machine>::Traits::Assembler *Asm =
586 Func->getAssembler<typename InstX86Base<Machine>::Traits::Assembler>();
David Sehr4318a412015-11-11 15:01:55 -0800587 Operand *CallTarget = getCallTarget();
David Sehrb8e49c12015-11-12 14:41:22 -0800588 auto *Target = InstX86Base<Machine>::getTarget(Func);
David Sehr4318a412015-11-11 15:01:55 -0800589 if (const auto *Var = llvm::dyn_cast<Variable>(CallTarget)) {
John Porto921856d2015-07-07 11:56:26 -0700590 if (Var->hasReg()) {
Jim Stichnoth5bff61c2015-10-28 09:26:00 -0700591 Asm->call(InstX86Base<Machine>::Traits::getEncodedGPR(Var->getRegNum()));
John Porto921856d2015-07-07 11:56:26 -0700592 } else {
David Sehrb8e49c12015-11-12 14:41:22 -0800593 Asm->call(Target->stackVarToAsmOperand(Var));
John Porto921856d2015-07-07 11:56:26 -0700594 }
Jim Stichnoth5bff61c2015-10-28 09:26:00 -0700595 } else if (const auto *Mem = llvm::dyn_cast<
John Porto921856d2015-07-07 11:56:26 -0700596 typename InstX86Base<Machine>::Traits::X86OperandMem>(
David Sehr4318a412015-11-11 15:01:55 -0800597 CallTarget)) {
John Porto921856d2015-07-07 11:56:26 -0700598 assert(Mem->getSegmentRegister() ==
599 InstX86Base<Machine>::Traits::X86OperandMem::DefaultSegment);
David Sehr4318a412015-11-11 15:01:55 -0800600 Asm->call(Mem->toAsmAddress(Asm, Target));
601 } else if (const auto *CR = llvm::dyn_cast<ConstantRelocatable>(CallTarget)) {
John Porto921856d2015-07-07 11:56:26 -0700602 assert(CR->getOffset() == 0 && "We only support calling a function");
603 Asm->call(CR);
David Sehr4318a412015-11-11 15:01:55 -0800604 } else if (const auto *Imm = llvm::dyn_cast<ConstantInteger32>(CallTarget)) {
John Porto921856d2015-07-07 11:56:26 -0700605 Asm->call(Immediate(Imm->getValue()));
606 } else {
607 llvm_unreachable("Unexpected operand type");
608 }
John Porto921856d2015-07-07 11:56:26 -0700609}
610
611template <class Machine>
612void InstX86Call<Machine>::dump(const Cfg *Func) const {
613 if (!BuildDefs::dump())
614 return;
615 Ostream &Str = Func->getContext()->getStrDump();
616 if (this->getDest()) {
617 this->dumpDest(Func);
618 Str << " = ";
619 }
620 Str << "call ";
621 getCallTarget()->dump(Func);
622}
623
Jim Stichnoth5bff61c2015-10-28 09:26:00 -0700624// The this->Opcode parameter needs to be char* and not IceString because of
625// template issues.
John Porto921856d2015-07-07 11:56:26 -0700626template <class Machine>
David Sehr6da7ae22015-12-17 15:01:30 -0800627void InstX86Base<Machine>::emitTwoAddress(const Cfg *Func, const char *Opcode,
628 const char *Suffix) const {
John Porto921856d2015-07-07 11:56:26 -0700629 if (!BuildDefs::dump())
630 return;
631 Ostream &Str = Func->getContext()->getStrEmit();
David Sehr6da7ae22015-12-17 15:01:30 -0800632 assert(getSrcSize() == 2);
633 Operand *Dest = getDest();
John Porto921856d2015-07-07 11:56:26 -0700634 if (Dest == nullptr)
David Sehr6da7ae22015-12-17 15:01:30 -0800635 Dest = getSrc(0);
636 assert(Dest == getSrc(0));
637 Operand *Src1 = getSrc(1);
638 Str << "\t" << Opcode << Suffix
639 << InstX86Base<Machine>::getWidthString(Dest->getType()) << "\t";
Jim Stichnoth5bff61c2015-10-28 09:26:00 -0700640 Src1->emit(Func);
John Porto921856d2015-07-07 11:56:26 -0700641 Str << ", ";
642 Dest->emit(Func);
643}
644
645template <class Machine>
646void emitIASOpTyGPR(const Cfg *Func, Type Ty, const Operand *Op,
647 const typename InstX86Base<
648 Machine>::Traits::Assembler::GPREmitterOneOp &Emitter) {
David Sehrb8e49c12015-11-12 14:41:22 -0800649 auto *Target = InstX86Base<Machine>::getTarget(Func);
John Porto921856d2015-07-07 11:56:26 -0700650 typename InstX86Base<Machine>::Traits::Assembler *Asm =
651 Func->getAssembler<typename InstX86Base<Machine>::Traits::Assembler>();
Jim Stichnoth5bff61c2015-10-28 09:26:00 -0700652 if (const auto *Var = llvm::dyn_cast<Variable>(Op)) {
John Porto921856d2015-07-07 11:56:26 -0700653 if (Var->hasReg()) {
654 // We cheat a little and use GPRRegister even for byte operations.
655 typename InstX86Base<Machine>::Traits::RegisterSet::GPRRegister VarReg =
Jim Stichnoth5bff61c2015-10-28 09:26:00 -0700656 InstX86Base<Machine>::Traits::getEncodedGPR(Var->getRegNum());
John Porto921856d2015-07-07 11:56:26 -0700657 (Asm->*(Emitter.Reg))(Ty, VarReg);
658 } else {
659 typename InstX86Base<Machine>::Traits::Address StackAddr(
David Sehrb8e49c12015-11-12 14:41:22 -0800660 Target->stackVarToAsmOperand(Var));
John Porto921856d2015-07-07 11:56:26 -0700661 (Asm->*(Emitter.Addr))(Ty, StackAddr);
662 }
Jim Stichnoth5bff61c2015-10-28 09:26:00 -0700663 } else if (const auto *Mem = llvm::dyn_cast<
John Porto921856d2015-07-07 11:56:26 -0700664 typename InstX86Base<Machine>::Traits::X86OperandMem>(Op)) {
665 Mem->emitSegmentOverride(Asm);
David Sehr4318a412015-11-11 15:01:55 -0800666 (Asm->*(Emitter.Addr))(Ty, Mem->toAsmAddress(Asm, Target));
John Porto921856d2015-07-07 11:56:26 -0700667 } else {
668 llvm_unreachable("Unexpected operand type");
669 }
670}
671
672template <class Machine, bool VarCanBeByte, bool SrcCanBeByte>
673void emitIASRegOpTyGPR(
674 const Cfg *Func, Type Ty, const Variable *Var, const Operand *Src,
675 const typename InstX86Base<Machine>::Traits::Assembler::GPREmitterRegOp
676 &Emitter) {
David Sehrb8e49c12015-11-12 14:41:22 -0800677 auto *Target = InstX86Base<Machine>::getTarget(Func);
John Porto921856d2015-07-07 11:56:26 -0700678 typename InstX86Base<Machine>::Traits::Assembler *Asm =
679 Func->getAssembler<typename InstX86Base<Machine>::Traits::Assembler>();
680 assert(Var->hasReg());
681 // We cheat a little and use GPRRegister even for byte operations.
682 typename InstX86Base<Machine>::Traits::RegisterSet::GPRRegister VarReg =
683 VarCanBeByte
Jim Stichnoth5bff61c2015-10-28 09:26:00 -0700684 ? InstX86Base<Machine>::Traits::getEncodedGPR(Var->getRegNum())
685 : InstX86Base<Machine>::Traits::getEncodedGPR(Var->getRegNum());
686 if (const auto *SrcVar = llvm::dyn_cast<Variable>(Src)) {
John Porto921856d2015-07-07 11:56:26 -0700687 if (SrcVar->hasReg()) {
688 typename InstX86Base<Machine>::Traits::RegisterSet::GPRRegister SrcReg =
689 SrcCanBeByte
Jim Stichnoth5bff61c2015-10-28 09:26:00 -0700690 ? InstX86Base<Machine>::Traits::getEncodedGPR(SrcVar->getRegNum())
691 : InstX86Base<Machine>::Traits::getEncodedGPR(
John Porto921856d2015-07-07 11:56:26 -0700692 SrcVar->getRegNum());
693 (Asm->*(Emitter.GPRGPR))(Ty, VarReg, SrcReg);
694 } else {
695 typename InstX86Base<Machine>::Traits::Address SrcStackAddr =
David Sehrb8e49c12015-11-12 14:41:22 -0800696 Target->stackVarToAsmOperand(SrcVar);
John Porto921856d2015-07-07 11:56:26 -0700697 (Asm->*(Emitter.GPRAddr))(Ty, VarReg, SrcStackAddr);
698 }
Jim Stichnoth5bff61c2015-10-28 09:26:00 -0700699 } else if (const auto *Mem = llvm::dyn_cast<
John Porto921856d2015-07-07 11:56:26 -0700700 typename InstX86Base<Machine>::Traits::X86OperandMem>(Src)) {
701 Mem->emitSegmentOverride(Asm);
David Sehr4318a412015-11-11 15:01:55 -0800702 (Asm->*(Emitter.GPRAddr))(Ty, VarReg, Mem->toAsmAddress(Asm, Target));
Jim Stichnoth5bff61c2015-10-28 09:26:00 -0700703 } else if (const auto *Imm = llvm::dyn_cast<ConstantInteger32>(Src)) {
John Porto921856d2015-07-07 11:56:26 -0700704 (Asm->*(Emitter.GPRImm))(Ty, VarReg, Immediate(Imm->getValue()));
Jim Stichnoth5bff61c2015-10-28 09:26:00 -0700705 } else if (const auto *Reloc = llvm::dyn_cast<ConstantRelocatable>(Src)) {
John Porto1d235422015-08-12 12:37:53 -0700706 AssemblerFixup *Fixup =
707 Asm->createFixup(InstX86Base<Machine>::Traits::RelFixup, Reloc);
John Porto921856d2015-07-07 11:56:26 -0700708 (Asm->*(Emitter.GPRImm))(Ty, VarReg, Immediate(Reloc->getOffset(), Fixup));
Jim Stichnoth5bff61c2015-10-28 09:26:00 -0700709 } else if (const auto *Split = llvm::dyn_cast<
John Porto921856d2015-07-07 11:56:26 -0700710 typename InstX86Base<Machine>::Traits::VariableSplit>(Src)) {
711 (Asm->*(Emitter.GPRAddr))(Ty, VarReg, Split->toAsmAddress(Func));
712 } else {
713 llvm_unreachable("Unexpected operand type");
714 }
715}
716
717template <class Machine>
718void emitIASAddrOpTyGPR(
719 const Cfg *Func, Type Ty,
720 const typename InstX86Base<Machine>::Traits::Address &Addr,
721 const Operand *Src,
722 const typename InstX86Base<Machine>::Traits::Assembler::GPREmitterAddrOp
723 &Emitter) {
724 typename InstX86Base<Machine>::Traits::Assembler *Asm =
725 Func->getAssembler<typename InstX86Base<Machine>::Traits::Assembler>();
726 // Src can only be Reg or Immediate.
Jim Stichnoth5bff61c2015-10-28 09:26:00 -0700727 if (const auto *SrcVar = llvm::dyn_cast<Variable>(Src)) {
John Porto921856d2015-07-07 11:56:26 -0700728 assert(SrcVar->hasReg());
729 typename InstX86Base<Machine>::Traits::RegisterSet::GPRRegister SrcReg =
Jim Stichnoth5bff61c2015-10-28 09:26:00 -0700730 InstX86Base<Machine>::Traits::getEncodedGPR(SrcVar->getRegNum());
John Porto921856d2015-07-07 11:56:26 -0700731 (Asm->*(Emitter.AddrGPR))(Ty, Addr, SrcReg);
Jim Stichnoth5bff61c2015-10-28 09:26:00 -0700732 } else if (const auto *Imm = llvm::dyn_cast<ConstantInteger32>(Src)) {
John Porto921856d2015-07-07 11:56:26 -0700733 (Asm->*(Emitter.AddrImm))(Ty, Addr, Immediate(Imm->getValue()));
Jim Stichnoth5bff61c2015-10-28 09:26:00 -0700734 } else if (const auto *Reloc = llvm::dyn_cast<ConstantRelocatable>(Src)) {
John Porto1d235422015-08-12 12:37:53 -0700735 AssemblerFixup *Fixup =
736 Asm->createFixup(InstX86Base<Machine>::Traits::RelFixup, Reloc);
John Porto921856d2015-07-07 11:56:26 -0700737 (Asm->*(Emitter.AddrImm))(Ty, Addr, Immediate(Reloc->getOffset(), Fixup));
738 } else {
739 llvm_unreachable("Unexpected operand type");
740 }
741}
742
743template <class Machine>
744void emitIASAsAddrOpTyGPR(
745 const Cfg *Func, Type Ty, const Operand *Op0, const Operand *Op1,
746 const typename InstX86Base<Machine>::Traits::Assembler::GPREmitterAddrOp
747 &Emitter) {
David Sehrb8e49c12015-11-12 14:41:22 -0800748 auto *Target = InstX86Base<Machine>::getTarget(Func);
Jim Stichnoth5bff61c2015-10-28 09:26:00 -0700749 if (const auto *Op0Var = llvm::dyn_cast<Variable>(Op0)) {
John Porto921856d2015-07-07 11:56:26 -0700750 assert(!Op0Var->hasReg());
751 typename InstX86Base<Machine>::Traits::Address StackAddr(
David Sehrb8e49c12015-11-12 14:41:22 -0800752 Target->stackVarToAsmOperand(Op0Var));
John Porto921856d2015-07-07 11:56:26 -0700753 emitIASAddrOpTyGPR<Machine>(Func, Ty, StackAddr, Op1, Emitter);
Jim Stichnoth5bff61c2015-10-28 09:26:00 -0700754 } else if (const auto *Op0Mem = llvm::dyn_cast<
John Porto921856d2015-07-07 11:56:26 -0700755 typename InstX86Base<Machine>::Traits::X86OperandMem>(Op0)) {
756 typename InstX86Base<Machine>::Traits::Assembler *Asm =
757 Func->getAssembler<typename InstX86Base<Machine>::Traits::Assembler>();
758 Op0Mem->emitSegmentOverride(Asm);
David Sehr4318a412015-11-11 15:01:55 -0800759 emitIASAddrOpTyGPR<Machine>(Func, Ty, Op0Mem->toAsmAddress(Asm, Target),
760 Op1, Emitter);
Jim Stichnoth5bff61c2015-10-28 09:26:00 -0700761 } else if (const auto *Split = llvm::dyn_cast<
John Porto921856d2015-07-07 11:56:26 -0700762 typename InstX86Base<Machine>::Traits::VariableSplit>(Op0)) {
763 emitIASAddrOpTyGPR<Machine>(Func, Ty, Split->toAsmAddress(Func), Op1,
764 Emitter);
765 } else {
766 llvm_unreachable("Unexpected operand type");
767 }
768}
769
770template <class Machine>
771void InstX86Base<Machine>::emitIASGPRShift(
772 const Cfg *Func, Type Ty, const Variable *Var, const Operand *Src,
773 const typename InstX86Base<Machine>::Traits::Assembler::GPREmitterShiftOp
774 &Emitter) {
775 typename InstX86Base<Machine>::Traits::Assembler *Asm =
776 Func->getAssembler<typename InstX86Base<Machine>::Traits::Assembler>();
Andrew Scull57e12682015-09-16 11:30:19 -0700777 // Technically, the Dest Var can be mem as well, but we only use Reg. We can
778 // extend this to check Dest if we decide to use that form.
John Porto921856d2015-07-07 11:56:26 -0700779 assert(Var->hasReg());
780 // We cheat a little and use GPRRegister even for byte operations.
781 typename InstX86Base<Machine>::Traits::RegisterSet::GPRRegister VarReg =
Jim Stichnoth5bff61c2015-10-28 09:26:00 -0700782 InstX86Base<Machine>::Traits::getEncodedGPR(Var->getRegNum());
Andrew Scull57e12682015-09-16 11:30:19 -0700783 // Src must be reg == ECX or an Imm8. This is asserted by the assembler.
Jim Stichnoth5bff61c2015-10-28 09:26:00 -0700784 if (const auto *SrcVar = llvm::dyn_cast<Variable>(Src)) {
John Porto921856d2015-07-07 11:56:26 -0700785 assert(SrcVar->hasReg());
786 typename InstX86Base<Machine>::Traits::RegisterSet::GPRRegister SrcReg =
Jim Stichnoth5bff61c2015-10-28 09:26:00 -0700787 InstX86Base<Machine>::Traits::getEncodedGPR(SrcVar->getRegNum());
John Porto921856d2015-07-07 11:56:26 -0700788 (Asm->*(Emitter.GPRGPR))(Ty, VarReg, SrcReg);
Jim Stichnoth5bff61c2015-10-28 09:26:00 -0700789 } else if (const auto *Imm = llvm::dyn_cast<ConstantInteger32>(Src)) {
John Porto921856d2015-07-07 11:56:26 -0700790 (Asm->*(Emitter.GPRImm))(Ty, VarReg, Immediate(Imm->getValue()));
791 } else {
792 llvm_unreachable("Unexpected operand type");
793 }
794}
795
796template <class Machine>
797void emitIASGPRShiftDouble(
798 const Cfg *Func, const Variable *Dest, const Operand *Src1Op,
799 const Operand *Src2Op,
800 const typename InstX86Base<Machine>::Traits::Assembler::GPREmitterShiftD
801 &Emitter) {
802 typename InstX86Base<Machine>::Traits::Assembler *Asm =
803 Func->getAssembler<typename InstX86Base<Machine>::Traits::Assembler>();
804 // Dest can be reg or mem, but we only use the reg variant.
805 assert(Dest->hasReg());
806 typename InstX86Base<Machine>::Traits::RegisterSet::GPRRegister DestReg =
Jim Stichnoth5bff61c2015-10-28 09:26:00 -0700807 InstX86Base<Machine>::Traits::getEncodedGPR(Dest->getRegNum());
John Porto921856d2015-07-07 11:56:26 -0700808 // SrcVar1 must be reg.
Jim Stichnoth5bff61c2015-10-28 09:26:00 -0700809 const auto *SrcVar1 = llvm::cast<Variable>(Src1Op);
John Porto921856d2015-07-07 11:56:26 -0700810 assert(SrcVar1->hasReg());
811 typename InstX86Base<Machine>::Traits::RegisterSet::GPRRegister SrcReg =
Jim Stichnoth5bff61c2015-10-28 09:26:00 -0700812 InstX86Base<Machine>::Traits::getEncodedGPR(SrcVar1->getRegNum());
John Porto921856d2015-07-07 11:56:26 -0700813 Type Ty = SrcVar1->getType();
814 // Src2 can be the implicit CL register or an immediate.
Jim Stichnoth5bff61c2015-10-28 09:26:00 -0700815 if (const auto *Imm = llvm::dyn_cast<ConstantInteger32>(Src2Op)) {
John Porto921856d2015-07-07 11:56:26 -0700816 (Asm->*(Emitter.GPRGPRImm))(Ty, DestReg, SrcReg,
817 Immediate(Imm->getValue()));
818 } else {
819 assert(llvm::cast<Variable>(Src2Op)->getRegNum() ==
Jim Stichnoth5bff61c2015-10-28 09:26:00 -0700820 InstX86Base<Machine>::Traits::RegisterSet::Reg_cl);
John Porto921856d2015-07-07 11:56:26 -0700821 (Asm->*(Emitter.GPRGPR))(Ty, DestReg, SrcReg);
822 }
823}
824
825template <class Machine>
826void emitIASXmmShift(
827 const Cfg *Func, Type Ty, const Variable *Var, const Operand *Src,
828 const typename InstX86Base<Machine>::Traits::Assembler::XmmEmitterShiftOp
829 &Emitter) {
David Sehrb8e49c12015-11-12 14:41:22 -0800830 auto *Target = InstX86Base<Machine>::getTarget(Func);
John Porto921856d2015-07-07 11:56:26 -0700831 typename InstX86Base<Machine>::Traits::Assembler *Asm =
832 Func->getAssembler<typename InstX86Base<Machine>::Traits::Assembler>();
833 assert(Var->hasReg());
834 typename InstX86Base<Machine>::Traits::RegisterSet::XmmRegister VarReg =
Jim Stichnoth5bff61c2015-10-28 09:26:00 -0700835 InstX86Base<Machine>::Traits::getEncodedXmm(Var->getRegNum());
836 if (const auto *SrcVar = llvm::dyn_cast<Variable>(Src)) {
John Porto921856d2015-07-07 11:56:26 -0700837 if (SrcVar->hasReg()) {
838 typename InstX86Base<Machine>::Traits::RegisterSet::XmmRegister SrcReg =
Jim Stichnoth5bff61c2015-10-28 09:26:00 -0700839 InstX86Base<Machine>::Traits::getEncodedXmm(SrcVar->getRegNum());
John Porto921856d2015-07-07 11:56:26 -0700840 (Asm->*(Emitter.XmmXmm))(Ty, VarReg, SrcReg);
841 } else {
842 typename InstX86Base<Machine>::Traits::Address SrcStackAddr =
David Sehrb8e49c12015-11-12 14:41:22 -0800843 Target->stackVarToAsmOperand(SrcVar);
John Porto921856d2015-07-07 11:56:26 -0700844 (Asm->*(Emitter.XmmAddr))(Ty, VarReg, SrcStackAddr);
845 }
Jim Stichnoth5bff61c2015-10-28 09:26:00 -0700846 } else if (const auto *Mem = llvm::dyn_cast<
John Porto921856d2015-07-07 11:56:26 -0700847 typename InstX86Base<Machine>::Traits::X86OperandMem>(Src)) {
848 assert(Mem->getSegmentRegister() ==
849 InstX86Base<Machine>::Traits::X86OperandMem::DefaultSegment);
David Sehr4318a412015-11-11 15:01:55 -0800850 (Asm->*(Emitter.XmmAddr))(Ty, VarReg, Mem->toAsmAddress(Asm, Target));
Jim Stichnoth5bff61c2015-10-28 09:26:00 -0700851 } else if (const auto *Imm = llvm::dyn_cast<ConstantInteger32>(Src)) {
John Porto921856d2015-07-07 11:56:26 -0700852 (Asm->*(Emitter.XmmImm))(Ty, VarReg, Immediate(Imm->getValue()));
853 } else {
854 llvm_unreachable("Unexpected operand type");
855 }
856}
857
858template <class Machine>
859void emitIASRegOpTyXMM(
860 const Cfg *Func, Type Ty, const Variable *Var, const Operand *Src,
861 const typename InstX86Base<Machine>::Traits::Assembler::XmmEmitterRegOp
862 &Emitter) {
David Sehrb8e49c12015-11-12 14:41:22 -0800863 auto *Target = InstX86Base<Machine>::getTarget(Func);
John Porto921856d2015-07-07 11:56:26 -0700864 typename InstX86Base<Machine>::Traits::Assembler *Asm =
865 Func->getAssembler<typename InstX86Base<Machine>::Traits::Assembler>();
866 assert(Var->hasReg());
867 typename InstX86Base<Machine>::Traits::RegisterSet::XmmRegister VarReg =
Jim Stichnoth5bff61c2015-10-28 09:26:00 -0700868 InstX86Base<Machine>::Traits::getEncodedXmm(Var->getRegNum());
869 if (const auto *SrcVar = llvm::dyn_cast<Variable>(Src)) {
John Porto921856d2015-07-07 11:56:26 -0700870 if (SrcVar->hasReg()) {
871 typename InstX86Base<Machine>::Traits::RegisterSet::XmmRegister SrcReg =
Jim Stichnoth5bff61c2015-10-28 09:26:00 -0700872 InstX86Base<Machine>::Traits::getEncodedXmm(SrcVar->getRegNum());
John Porto921856d2015-07-07 11:56:26 -0700873 (Asm->*(Emitter.XmmXmm))(Ty, VarReg, SrcReg);
874 } else {
875 typename InstX86Base<Machine>::Traits::Address SrcStackAddr =
David Sehrb8e49c12015-11-12 14:41:22 -0800876 Target->stackVarToAsmOperand(SrcVar);
John Porto921856d2015-07-07 11:56:26 -0700877 (Asm->*(Emitter.XmmAddr))(Ty, VarReg, SrcStackAddr);
878 }
Jim Stichnoth5bff61c2015-10-28 09:26:00 -0700879 } else if (const auto *Mem = llvm::dyn_cast<
John Porto921856d2015-07-07 11:56:26 -0700880 typename InstX86Base<Machine>::Traits::X86OperandMem>(Src)) {
881 assert(Mem->getSegmentRegister() ==
882 InstX86Base<Machine>::Traits::X86OperandMem::DefaultSegment);
David Sehr4318a412015-11-11 15:01:55 -0800883 (Asm->*(Emitter.XmmAddr))(Ty, VarReg, Mem->toAsmAddress(Asm, Target));
Jim Stichnoth5bff61c2015-10-28 09:26:00 -0700884 } else if (const auto *Imm = llvm::dyn_cast<Constant>(Src)) {
John Porto921856d2015-07-07 11:56:26 -0700885 (Asm->*(Emitter.XmmAddr))(
886 Ty, VarReg,
887 InstX86Base<Machine>::Traits::Address::ofConstPool(Asm, Imm));
888 } else {
889 llvm_unreachable("Unexpected operand type");
890 }
891}
892
893template <class Machine, typename DReg_t, typename SReg_t,
894 DReg_t (*destEnc)(int32_t), SReg_t (*srcEnc)(int32_t)>
John Porto1d235422015-08-12 12:37:53 -0700895void emitIASCastRegOp(const Cfg *Func, Type DestTy, const Variable *Dest,
896 Type SrcTy, const Operand *Src,
John Porto921856d2015-07-07 11:56:26 -0700897 const typename InstX86Base<Machine>::Traits::Assembler::
898 template CastEmitterRegOp<DReg_t, SReg_t> &Emitter) {
David Sehrb8e49c12015-11-12 14:41:22 -0800899 auto *Target = InstX86Base<Machine>::getTarget(Func);
John Porto921856d2015-07-07 11:56:26 -0700900 typename InstX86Base<Machine>::Traits::Assembler *Asm =
901 Func->getAssembler<typename InstX86Base<Machine>::Traits::Assembler>();
902 assert(Dest->hasReg());
903 DReg_t DestReg = destEnc(Dest->getRegNum());
Jim Stichnoth5bff61c2015-10-28 09:26:00 -0700904 if (const auto *SrcVar = llvm::dyn_cast<Variable>(Src)) {
John Porto921856d2015-07-07 11:56:26 -0700905 if (SrcVar->hasReg()) {
906 SReg_t SrcReg = srcEnc(SrcVar->getRegNum());
John Porto1d235422015-08-12 12:37:53 -0700907 (Asm->*(Emitter.RegReg))(DestTy, DestReg, SrcTy, SrcReg);
John Porto921856d2015-07-07 11:56:26 -0700908 } else {
909 typename InstX86Base<Machine>::Traits::Address SrcStackAddr =
David Sehrb8e49c12015-11-12 14:41:22 -0800910 Target->stackVarToAsmOperand(SrcVar);
John Porto1d235422015-08-12 12:37:53 -0700911 (Asm->*(Emitter.RegAddr))(DestTy, DestReg, SrcTy, SrcStackAddr);
John Porto921856d2015-07-07 11:56:26 -0700912 }
Jim Stichnoth5bff61c2015-10-28 09:26:00 -0700913 } else if (const auto *Mem = llvm::dyn_cast<
John Porto921856d2015-07-07 11:56:26 -0700914 typename InstX86Base<Machine>::Traits::X86OperandMem>(Src)) {
915 Mem->emitSegmentOverride(Asm);
David Sehr4318a412015-11-11 15:01:55 -0800916 (Asm->*(Emitter.RegAddr))(DestTy, DestReg, SrcTy,
917 Mem->toAsmAddress(Asm, Target));
John Porto921856d2015-07-07 11:56:26 -0700918 } else {
919 llvm_unreachable("Unexpected operand type");
920 }
921}
922
923template <class Machine, typename DReg_t, typename SReg_t,
924 DReg_t (*destEnc)(int32_t), SReg_t (*srcEnc)(int32_t)>
925void emitIASThreeOpImmOps(
926 const Cfg *Func, Type DispatchTy, const Variable *Dest, const Operand *Src0,
927 const Operand *Src1,
928 const typename InstX86Base<Machine>::Traits::Assembler::
929 template ThreeOpImmEmitter<DReg_t, SReg_t> Emitter) {
David Sehrb8e49c12015-11-12 14:41:22 -0800930 auto *Target = InstX86Base<Machine>::getTarget(Func);
John Porto921856d2015-07-07 11:56:26 -0700931 typename InstX86Base<Machine>::Traits::Assembler *Asm =
932 Func->getAssembler<typename InstX86Base<Machine>::Traits::Assembler>();
933 // This only handles Dest being a register, and Src1 being an immediate.
934 assert(Dest->hasReg());
935 DReg_t DestReg = destEnc(Dest->getRegNum());
936 Immediate Imm(llvm::cast<ConstantInteger32>(Src1)->getValue());
Jim Stichnoth5bff61c2015-10-28 09:26:00 -0700937 if (const auto *SrcVar = llvm::dyn_cast<Variable>(Src0)) {
John Porto921856d2015-07-07 11:56:26 -0700938 if (SrcVar->hasReg()) {
939 SReg_t SrcReg = srcEnc(SrcVar->getRegNum());
940 (Asm->*(Emitter.RegRegImm))(DispatchTy, DestReg, SrcReg, Imm);
941 } else {
942 typename InstX86Base<Machine>::Traits::Address SrcStackAddr =
David Sehrb8e49c12015-11-12 14:41:22 -0800943 Target->stackVarToAsmOperand(SrcVar);
John Porto921856d2015-07-07 11:56:26 -0700944 (Asm->*(Emitter.RegAddrImm))(DispatchTy, DestReg, SrcStackAddr, Imm);
945 }
Jim Stichnoth5bff61c2015-10-28 09:26:00 -0700946 } else if (const auto *Mem = llvm::dyn_cast<
John Porto921856d2015-07-07 11:56:26 -0700947 typename InstX86Base<Machine>::Traits::X86OperandMem>(Src0)) {
948 Mem->emitSegmentOverride(Asm);
David Sehr4318a412015-11-11 15:01:55 -0800949 (Asm->*(Emitter.RegAddrImm))(DispatchTy, DestReg,
950 Mem->toAsmAddress(Asm, Target), Imm);
John Porto921856d2015-07-07 11:56:26 -0700951 } else {
952 llvm_unreachable("Unexpected operand type");
953 }
954}
955
956template <class Machine>
957void emitIASMovlikeXMM(
958 const Cfg *Func, const Variable *Dest, const Operand *Src,
959 const typename InstX86Base<Machine>::Traits::Assembler::XmmEmitterMovOps
960 Emitter) {
David Sehrb8e49c12015-11-12 14:41:22 -0800961 auto *Target = InstX86Base<Machine>::getTarget(Func);
John Porto921856d2015-07-07 11:56:26 -0700962 typename InstX86Base<Machine>::Traits::Assembler *Asm =
963 Func->getAssembler<typename InstX86Base<Machine>::Traits::Assembler>();
964 if (Dest->hasReg()) {
965 typename InstX86Base<Machine>::Traits::RegisterSet::XmmRegister DestReg =
Jim Stichnoth5bff61c2015-10-28 09:26:00 -0700966 InstX86Base<Machine>::Traits::getEncodedXmm(Dest->getRegNum());
967 if (const auto *SrcVar = llvm::dyn_cast<Variable>(Src)) {
John Porto921856d2015-07-07 11:56:26 -0700968 if (SrcVar->hasReg()) {
969 (Asm->*(Emitter.XmmXmm))(
Jim Stichnoth5bff61c2015-10-28 09:26:00 -0700970 DestReg,
971 InstX86Base<Machine>::Traits::getEncodedXmm(SrcVar->getRegNum()));
John Porto921856d2015-07-07 11:56:26 -0700972 } else {
973 typename InstX86Base<Machine>::Traits::Address StackAddr(
David Sehrb8e49c12015-11-12 14:41:22 -0800974 Target->stackVarToAsmOperand(SrcVar));
John Porto921856d2015-07-07 11:56:26 -0700975 (Asm->*(Emitter.XmmAddr))(DestReg, StackAddr);
976 }
Jim Stichnoth5bff61c2015-10-28 09:26:00 -0700977 } else if (const auto *SrcMem = llvm::dyn_cast<
John Porto921856d2015-07-07 11:56:26 -0700978 typename InstX86Base<Machine>::Traits::X86OperandMem>(Src)) {
979 assert(SrcMem->getSegmentRegister() ==
980 InstX86Base<Machine>::Traits::X86OperandMem::DefaultSegment);
David Sehr4318a412015-11-11 15:01:55 -0800981 (Asm->*(Emitter.XmmAddr))(DestReg, SrcMem->toAsmAddress(Asm, Target));
John Porto921856d2015-07-07 11:56:26 -0700982 } else {
983 llvm_unreachable("Unexpected operand type");
984 }
985 } else {
986 typename InstX86Base<Machine>::Traits::Address StackAddr(
David Sehrb8e49c12015-11-12 14:41:22 -0800987 Target->stackVarToAsmOperand(Dest));
John Porto921856d2015-07-07 11:56:26 -0700988 // Src must be a register in this case.
Jim Stichnoth5bff61c2015-10-28 09:26:00 -0700989 const auto *SrcVar = llvm::cast<Variable>(Src);
John Porto921856d2015-07-07 11:56:26 -0700990 assert(SrcVar->hasReg());
991 (Asm->*(Emitter.AddrXmm))(
Jim Stichnoth5bff61c2015-10-28 09:26:00 -0700992 StackAddr,
993 InstX86Base<Machine>::Traits::getEncodedXmm(SrcVar->getRegNum()));
John Porto921856d2015-07-07 11:56:26 -0700994 }
995}
996
997template <class Machine>
998void InstX86Sqrtss<Machine>::emit(const Cfg *Func) const {
999 if (!BuildDefs::dump())
1000 return;
1001 Ostream &Str = Func->getContext()->getStrEmit();
1002 assert(this->getSrcSize() == 1);
1003 Type Ty = this->getSrc(0)->getType();
1004 assert(isScalarFloatingType(Ty));
Jim Stichnoth6106df82015-12-16 06:17:58 -08001005 Str << "\t"
1006 "sqrt" << InstX86Base<Machine>::Traits::TypeAttributes[Ty].SdSsString
John Porto921856d2015-07-07 11:56:26 -07001007 << "\t";
1008 this->getSrc(0)->emit(Func);
1009 Str << ", ";
1010 this->getDest()->emit(Func);
1011}
1012
John Porto921856d2015-07-07 11:56:26 -07001013template <class Machine> void InstX86Div<Machine>::emit(const Cfg *Func) const {
1014 if (!BuildDefs::dump())
1015 return;
1016 Ostream &Str = Func->getContext()->getStrEmit();
1017 assert(this->getSrcSize() == 3);
1018 Operand *Src1 = this->getSrc(1);
1019 Str << "\t" << this->Opcode << this->getWidthString(Src1->getType()) << "\t";
1020 Src1->emit(Func);
1021}
1022
1023template <class Machine>
1024void InstX86Div<Machine>::emitIAS(const Cfg *Func) const {
1025 assert(this->getSrcSize() == 3);
1026 const Operand *Src = this->getSrc(1);
1027 Type Ty = Src->getType();
1028 static const typename InstX86Base<Machine>::Traits::Assembler::GPREmitterOneOp
1029 Emitter = {&InstX86Base<Machine>::Traits::Assembler::div,
1030 &InstX86Base<Machine>::Traits::Assembler::div};
1031 emitIASOpTyGPR<Machine>(Func, Ty, Src, Emitter);
1032}
1033
1034template <class Machine>
1035void InstX86Idiv<Machine>::emit(const Cfg *Func) const {
1036 if (!BuildDefs::dump())
1037 return;
1038 Ostream &Str = Func->getContext()->getStrEmit();
1039 assert(this->getSrcSize() == 3);
1040 Operand *Src1 = this->getSrc(1);
1041 Str << "\t" << this->Opcode << this->getWidthString(Src1->getType()) << "\t";
1042 Src1->emit(Func);
1043}
1044
1045template <class Machine>
1046void InstX86Idiv<Machine>::emitIAS(const Cfg *Func) const {
1047 assert(this->getSrcSize() == 3);
1048 const Operand *Src = this->getSrc(1);
1049 Type Ty = Src->getType();
1050 static const typename InstX86Base<Machine>::Traits::Assembler::GPREmitterOneOp
1051 Emitter = {&InstX86Base<Machine>::Traits::Assembler::idiv,
1052 &InstX86Base<Machine>::Traits::Assembler::idiv};
1053 emitIASOpTyGPR<Machine>(Func, Ty, Src, Emitter);
1054}
1055
1056// pblendvb and blendvps take xmm0 as a final implicit argument.
1057template <class Machine>
1058void emitVariableBlendInst(const char *Opcode, const Inst *Inst,
1059 const Cfg *Func) {
1060 if (!BuildDefs::dump())
1061 return;
1062 Ostream &Str = Func->getContext()->getStrEmit();
1063 assert(Inst->getSrcSize() == 3);
1064 assert(llvm::cast<Variable>(Inst->getSrc(2))->getRegNum() ==
1065 InstX86Base<Machine>::Traits::RegisterSet::Reg_xmm0);
1066 Str << "\t" << Opcode << "\t";
1067 Inst->getSrc(1)->emit(Func);
1068 Str << ", ";
1069 Inst->getDest()->emit(Func);
1070}
1071
1072template <class Machine>
1073void emitIASVariableBlendInst(
1074 const Inst *Inst, const Cfg *Func,
1075 const typename InstX86Base<Machine>::Traits::Assembler::XmmEmitterRegOp
1076 &Emitter) {
1077 assert(Inst->getSrcSize() == 3);
1078 assert(llvm::cast<Variable>(Inst->getSrc(2))->getRegNum() ==
1079 InstX86Base<Machine>::Traits::RegisterSet::Reg_xmm0);
1080 const Variable *Dest = Inst->getDest();
1081 const Operand *Src = Inst->getSrc(1);
1082 emitIASRegOpTyXMM<Machine>(Func, Dest->getType(), Dest, Src, Emitter);
1083}
1084
1085template <class Machine>
1086void InstX86Blendvps<Machine>::emit(const Cfg *Func) const {
1087 if (!BuildDefs::dump())
1088 return;
John Porto921856d2015-07-07 11:56:26 -07001089 emitVariableBlendInst<Machine>(this->Opcode, this, Func);
1090}
1091
1092template <class Machine>
1093void InstX86Blendvps<Machine>::emitIAS(const Cfg *Func) const {
John Porto921856d2015-07-07 11:56:26 -07001094 static const typename InstX86Base<Machine>::Traits::Assembler::XmmEmitterRegOp
1095 Emitter = {&InstX86Base<Machine>::Traits::Assembler::blendvps,
1096 &InstX86Base<Machine>::Traits::Assembler::blendvps};
1097 emitIASVariableBlendInst<Machine>(this, Func, Emitter);
1098}
1099
1100template <class Machine>
1101void InstX86Pblendvb<Machine>::emit(const Cfg *Func) const {
1102 if (!BuildDefs::dump())
1103 return;
John Porto921856d2015-07-07 11:56:26 -07001104 emitVariableBlendInst<Machine>(this->Opcode, this, Func);
1105}
1106
1107template <class Machine>
1108void InstX86Pblendvb<Machine>::emitIAS(const Cfg *Func) const {
John Porto921856d2015-07-07 11:56:26 -07001109 static const typename InstX86Base<Machine>::Traits::Assembler::XmmEmitterRegOp
1110 Emitter = {&InstX86Base<Machine>::Traits::Assembler::pblendvb,
1111 &InstX86Base<Machine>::Traits::Assembler::pblendvb};
1112 emitIASVariableBlendInst<Machine>(this, Func, Emitter);
1113}
1114
1115template <class Machine>
1116void InstX86Imul<Machine>::emit(const Cfg *Func) const {
1117 if (!BuildDefs::dump())
1118 return;
1119 Ostream &Str = Func->getContext()->getStrEmit();
1120 assert(this->getSrcSize() == 2);
1121 Variable *Dest = this->getDest();
1122 if (isByteSizedArithType(Dest->getType())) {
1123 // The 8-bit version of imul only allows the form "imul r/m8".
Jim Stichnoth5bff61c2015-10-28 09:26:00 -07001124 const auto *Src0Var = llvm::dyn_cast<Variable>(this->getSrc(0));
John Porto921856d2015-07-07 11:56:26 -07001125 (void)Src0Var;
Jim Stichnoth5bff61c2015-10-28 09:26:00 -07001126 assert(Src0Var->getRegNum() ==
1127 InstX86Base<Machine>::Traits::RegisterSet::Reg_al);
Jim Stichnoth6106df82015-12-16 06:17:58 -08001128 Str << "\t"
1129 "imulb\t";
John Porto921856d2015-07-07 11:56:26 -07001130 this->getSrc(1)->emit(Func);
1131 } else if (llvm::isa<Constant>(this->getSrc(1))) {
Jim Stichnoth6106df82015-12-16 06:17:58 -08001132 Str << "\t"
1133 "imul" << this->getWidthString(Dest->getType()) << "\t";
John Porto921856d2015-07-07 11:56:26 -07001134 this->getSrc(1)->emit(Func);
1135 Str << ", ";
1136 this->getSrc(0)->emit(Func);
1137 Str << ", ";
1138 Dest->emit(Func);
1139 } else {
David Sehr6da7ae22015-12-17 15:01:30 -08001140 this->emitTwoAddress(Func, this->Opcode);
John Porto921856d2015-07-07 11:56:26 -07001141 }
1142}
1143
1144template <class Machine>
1145void InstX86Imul<Machine>::emitIAS(const Cfg *Func) const {
1146 assert(this->getSrcSize() == 2);
1147 const Variable *Var = this->getDest();
1148 Type Ty = Var->getType();
1149 const Operand *Src = this->getSrc(1);
1150 if (isByteSizedArithType(Ty)) {
1151 // The 8-bit version of imul only allows the form "imul r/m8".
Jim Stichnoth5bff61c2015-10-28 09:26:00 -07001152 const auto *Src0Var = llvm::dyn_cast<Variable>(this->getSrc(0));
John Porto921856d2015-07-07 11:56:26 -07001153 (void)Src0Var;
Jim Stichnoth5bff61c2015-10-28 09:26:00 -07001154 assert(Src0Var->getRegNum() ==
1155 InstX86Base<Machine>::Traits::RegisterSet::Reg_al);
John Porto921856d2015-07-07 11:56:26 -07001156 static const typename InstX86Base<
1157 Machine>::Traits::Assembler::GPREmitterOneOp Emitter = {
1158 &InstX86Base<Machine>::Traits::Assembler::imul,
1159 &InstX86Base<Machine>::Traits::Assembler::imul};
1160 emitIASOpTyGPR<Machine>(Func, Ty, this->getSrc(1), Emitter);
1161 } else {
David Sehre11f8782015-10-06 10:26:57 -07001162 // The two-address version is used when multiplying by a non-constant
1163 // or doing an 8-bit multiply.
John Porto921856d2015-07-07 11:56:26 -07001164 assert(Var == this->getSrc(0));
1165 static const typename InstX86Base<
1166 Machine>::Traits::Assembler::GPREmitterRegOp Emitter = {
1167 &InstX86Base<Machine>::Traits::Assembler::imul,
1168 &InstX86Base<Machine>::Traits::Assembler::imul,
1169 &InstX86Base<Machine>::Traits::Assembler::imul};
1170 emitIASRegOpTyGPR<Machine>(Func, Ty, Var, Src, Emitter);
1171 }
1172}
1173
1174template <class Machine>
David Sehre11f8782015-10-06 10:26:57 -07001175void InstX86ImulImm<Machine>::emit(const Cfg *Func) const {
1176 if (!BuildDefs::dump())
1177 return;
1178 Ostream &Str = Func->getContext()->getStrEmit();
1179 assert(this->getSrcSize() == 2);
1180 Variable *Dest = this->getDest();
1181 assert(Dest->getType() == IceType_i16 || Dest->getType() == IceType_i32);
1182 assert(llvm::isa<Constant>(this->getSrc(1)));
Jim Stichnoth6106df82015-12-16 06:17:58 -08001183 Str << "\t"
1184 "imul" << this->getWidthString(Dest->getType()) << "\t";
David Sehre11f8782015-10-06 10:26:57 -07001185 this->getSrc(1)->emit(Func);
1186 Str << ", ";
1187 this->getSrc(0)->emit(Func);
1188 Str << ", ";
1189 Dest->emit(Func);
1190}
1191
1192template <class Machine>
1193void InstX86ImulImm<Machine>::emitIAS(const Cfg *Func) const {
1194 assert(this->getSrcSize() == 2);
1195 const Variable *Dest = this->getDest();
1196 Type Ty = Dest->getType();
1197 assert(llvm::isa<Constant>(this->getSrc(1)));
1198 static const typename InstX86Base<Machine>::Traits::Assembler::
1199 template ThreeOpImmEmitter<
1200 typename InstX86Base<Machine>::Traits::RegisterSet::GPRRegister,
1201 typename InstX86Base<Machine>::Traits::RegisterSet::GPRRegister>
1202 Emitter = {&InstX86Base<Machine>::Traits::Assembler::imul,
1203 &InstX86Base<Machine>::Traits::Assembler::imul};
1204 emitIASThreeOpImmOps<
1205 Machine, typename InstX86Base<Machine>::Traits::RegisterSet::GPRRegister,
1206 typename InstX86Base<Machine>::Traits::RegisterSet::GPRRegister,
Jim Stichnoth5bff61c2015-10-28 09:26:00 -07001207 InstX86Base<Machine>::Traits::getEncodedGPR,
1208 InstX86Base<Machine>::Traits::getEncodedGPR>(
David Sehre11f8782015-10-06 10:26:57 -07001209 Func, Ty, Dest, this->getSrc(0), this->getSrc(1), Emitter);
1210}
1211
1212template <class Machine>
John Porto921856d2015-07-07 11:56:26 -07001213void InstX86Insertps<Machine>::emitIAS(const Cfg *Func) const {
1214 assert(this->getSrcSize() == 3);
David Sehr7f42a822015-11-13 16:59:02 -08001215 assert(InstX86Base<Machine>::getTarget(Func)->getInstructionSet() >=
1216 InstX86Base<Machine>::Traits::SSE4_1);
John Porto921856d2015-07-07 11:56:26 -07001217 const Variable *Dest = this->getDest();
1218 assert(Dest == this->getSrc(0));
1219 Type Ty = Dest->getType();
1220 static const typename InstX86Base<Machine>::Traits::Assembler::
1221 template ThreeOpImmEmitter<
1222 typename InstX86Base<Machine>::Traits::RegisterSet::XmmRegister,
1223 typename InstX86Base<Machine>::Traits::RegisterSet::XmmRegister>
1224 Emitter = {&InstX86Base<Machine>::Traits::Assembler::insertps,
1225 &InstX86Base<Machine>::Traits::Assembler::insertps};
1226 emitIASThreeOpImmOps<
1227 Machine, typename InstX86Base<Machine>::Traits::RegisterSet::XmmRegister,
1228 typename InstX86Base<Machine>::Traits::RegisterSet::XmmRegister,
Jim Stichnoth5bff61c2015-10-28 09:26:00 -07001229 InstX86Base<Machine>::Traits::getEncodedXmm,
1230 InstX86Base<Machine>::Traits::getEncodedXmm>(
John Porto921856d2015-07-07 11:56:26 -07001231 Func, Ty, Dest, this->getSrc(1), this->getSrc(2), Emitter);
1232}
1233
1234template <class Machine>
1235void InstX86Cbwdq<Machine>::emit(const Cfg *Func) const {
1236 if (!BuildDefs::dump())
1237 return;
1238 Ostream &Str = Func->getContext()->getStrEmit();
1239 assert(this->getSrcSize() == 1);
1240 Operand *Src0 = this->getSrc(0);
Jim Stichnothc59288b2015-11-09 11:38:40 -08001241 int32_t DestReg = this->getDest()->getRegNum();
1242 int32_t SrcReg = llvm::cast<Variable>(Src0)->getRegNum();
1243 (void)DestReg;
1244 (void)SrcReg;
John Porto921856d2015-07-07 11:56:26 -07001245 switch (Src0->getType()) {
1246 default:
1247 llvm_unreachable("unexpected source type!");
1248 break;
1249 case IceType_i8:
Jim Stichnothc59288b2015-11-09 11:38:40 -08001250 assert(SrcReg == InstX86Base<Machine>::Traits::RegisterSet::Reg_al);
1251 assert(DestReg == InstX86Base<Machine>::Traits::RegisterSet::Reg_ax ||
1252 DestReg == InstX86Base<Machine>::Traits::RegisterSet::Reg_ah);
John Porto1d235422015-08-12 12:37:53 -07001253 Str << "\t"
Jim Stichnoth6106df82015-12-16 06:17:58 -08001254 "cbtw";
John Porto921856d2015-07-07 11:56:26 -07001255 break;
1256 case IceType_i16:
Jim Stichnothc59288b2015-11-09 11:38:40 -08001257 assert(SrcReg == InstX86Base<Machine>::Traits::RegisterSet::Reg_ax);
1258 assert(DestReg == InstX86Base<Machine>::Traits::RegisterSet::Reg_dx);
John Porto1d235422015-08-12 12:37:53 -07001259 Str << "\t"
Jim Stichnoth6106df82015-12-16 06:17:58 -08001260 "cwtd";
John Porto921856d2015-07-07 11:56:26 -07001261 break;
1262 case IceType_i32:
Jim Stichnothc59288b2015-11-09 11:38:40 -08001263 assert(SrcReg == InstX86Base<Machine>::Traits::RegisterSet::Reg_eax);
1264 assert(DestReg == InstX86Base<Machine>::Traits::RegisterSet::Reg_edx);
John Porto1d235422015-08-12 12:37:53 -07001265 Str << "\t"
Jim Stichnoth6106df82015-12-16 06:17:58 -08001266 "cltd";
John Porto1d235422015-08-12 12:37:53 -07001267 break;
1268 case IceType_i64:
John Porto008f4ce2015-12-24 13:22:18 -08001269 assert(InstX86Base<Machine>::Traits::Is64Bit);
1270 assert(SrcReg == InstX86Base<Machine>::Traits::getRaxOrDie());
1271 assert(DestReg == InstX86Base<Machine>::Traits::getRdxOrDie());
John Porto1d235422015-08-12 12:37:53 -07001272 Str << "\t"
John Porto008f4ce2015-12-24 13:22:18 -08001273 "cqo";
John Porto921856d2015-07-07 11:56:26 -07001274 break;
1275 }
1276}
1277
1278template <class Machine>
1279void InstX86Cbwdq<Machine>::emitIAS(const Cfg *Func) const {
1280 typename InstX86Base<Machine>::Traits::Assembler *Asm =
1281 Func->getAssembler<typename InstX86Base<Machine>::Traits::Assembler>();
1282 assert(this->getSrcSize() == 1);
1283 Operand *Src0 = this->getSrc(0);
Jim Stichnothc59288b2015-11-09 11:38:40 -08001284 int32_t DestReg = this->getDest()->getRegNum();
1285 int32_t SrcReg = llvm::cast<Variable>(Src0)->getRegNum();
1286 (void)DestReg;
1287 (void)SrcReg;
John Porto921856d2015-07-07 11:56:26 -07001288 switch (Src0->getType()) {
1289 default:
1290 llvm_unreachable("unexpected source type!");
1291 break;
1292 case IceType_i8:
Jim Stichnothc59288b2015-11-09 11:38:40 -08001293 assert(SrcReg == InstX86Base<Machine>::Traits::RegisterSet::Reg_al);
1294 assert(DestReg == InstX86Base<Machine>::Traits::RegisterSet::Reg_ax ||
1295 DestReg == InstX86Base<Machine>::Traits::RegisterSet::Reg_ah);
John Porto921856d2015-07-07 11:56:26 -07001296 Asm->cbw();
1297 break;
1298 case IceType_i16:
Jim Stichnothc59288b2015-11-09 11:38:40 -08001299 assert(SrcReg == InstX86Base<Machine>::Traits::RegisterSet::Reg_ax);
1300 assert(DestReg == InstX86Base<Machine>::Traits::RegisterSet::Reg_dx);
John Porto921856d2015-07-07 11:56:26 -07001301 Asm->cwd();
1302 break;
1303 case IceType_i32:
Jim Stichnothc59288b2015-11-09 11:38:40 -08001304 assert(SrcReg == InstX86Base<Machine>::Traits::RegisterSet::Reg_eax);
1305 assert(DestReg == InstX86Base<Machine>::Traits::RegisterSet::Reg_edx);
John Porto921856d2015-07-07 11:56:26 -07001306 Asm->cdq();
1307 break;
John Porto1d235422015-08-12 12:37:53 -07001308 case IceType_i64:
John Porto3c275ce2015-12-22 08:14:00 -08001309 assert(InstX86Base<Machine>::Traits::Is64Bit);
1310 assert(SrcReg == InstX86Base<Machine>::Traits::getRaxOrDie());
1311 assert(DestReg == InstX86Base<Machine>::Traits::getRdxOrDie());
John Porto1d235422015-08-12 12:37:53 -07001312 Asm->cqo();
1313 break;
John Porto921856d2015-07-07 11:56:26 -07001314 }
1315}
1316
1317template <class Machine> void InstX86Mul<Machine>::emit(const Cfg *Func) const {
1318 if (!BuildDefs::dump())
1319 return;
1320 Ostream &Str = Func->getContext()->getStrEmit();
1321 assert(this->getSrcSize() == 2);
1322 assert(llvm::isa<Variable>(this->getSrc(0)));
1323 assert(llvm::cast<Variable>(this->getSrc(0))->getRegNum() ==
1324 InstX86Base<Machine>::Traits::RegisterSet::Reg_eax);
1325 assert(
1326 this->getDest()->getRegNum() ==
1327 InstX86Base<Machine>::Traits::RegisterSet::Reg_eax); // TODO: allow edx?
Jim Stichnoth6106df82015-12-16 06:17:58 -08001328 Str << "\t"
1329 "mul" << this->getWidthString(this->getDest()->getType()) << "\t";
John Porto921856d2015-07-07 11:56:26 -07001330 this->getSrc(1)->emit(Func);
1331}
1332
1333template <class Machine>
1334void InstX86Mul<Machine>::emitIAS(const Cfg *Func) const {
1335 assert(this->getSrcSize() == 2);
1336 assert(llvm::isa<Variable>(this->getSrc(0)));
1337 assert(llvm::cast<Variable>(this->getSrc(0))->getRegNum() ==
1338 InstX86Base<Machine>::Traits::RegisterSet::Reg_eax);
1339 assert(
1340 this->getDest()->getRegNum() ==
1341 InstX86Base<Machine>::Traits::RegisterSet::Reg_eax); // TODO: allow edx?
1342 const Operand *Src = this->getSrc(1);
1343 Type Ty = Src->getType();
1344 static const typename InstX86Base<Machine>::Traits::Assembler::GPREmitterOneOp
1345 Emitter = {&InstX86Base<Machine>::Traits::Assembler::mul,
1346 &InstX86Base<Machine>::Traits::Assembler::mul};
1347 emitIASOpTyGPR<Machine>(Func, Ty, Src, Emitter);
1348}
1349
1350template <class Machine> void InstX86Mul<Machine>::dump(const Cfg *Func) const {
1351 if (!BuildDefs::dump())
1352 return;
1353 Ostream &Str = Func->getContext()->getStrDump();
1354 this->dumpDest(Func);
1355 Str << " = mul." << this->getDest()->getType() << " ";
1356 this->dumpSources(Func);
1357}
1358
1359template <class Machine>
1360void InstX86Shld<Machine>::emit(const Cfg *Func) const {
1361 if (!BuildDefs::dump())
1362 return;
1363 Ostream &Str = Func->getContext()->getStrEmit();
1364 Variable *Dest = this->getDest();
1365 assert(this->getSrcSize() == 3);
1366 assert(Dest == this->getSrc(0));
Jim Stichnoth6106df82015-12-16 06:17:58 -08001367 Str << "\t"
1368 "shld" << this->getWidthString(Dest->getType()) << "\t";
Jim Stichnoth5bff61c2015-10-28 09:26:00 -07001369 this->getSrc(2)->emit(Func);
John Porto921856d2015-07-07 11:56:26 -07001370 Str << ", ";
1371 this->getSrc(1)->emit(Func);
1372 Str << ", ";
1373 Dest->emit(Func);
1374}
1375
1376template <class Machine>
1377void InstX86Shld<Machine>::emitIAS(const Cfg *Func) const {
1378 assert(this->getSrcSize() == 3);
1379 assert(this->getDest() == this->getSrc(0));
1380 const Variable *Dest = this->getDest();
1381 const Operand *Src1 = this->getSrc(1);
1382 const Operand *Src2 = this->getSrc(2);
1383 static const typename InstX86Base<
1384 Machine>::Traits::Assembler::GPREmitterShiftD Emitter = {
1385 &InstX86Base<Machine>::Traits::Assembler::shld,
1386 &InstX86Base<Machine>::Traits::Assembler::shld};
1387 emitIASGPRShiftDouble<Machine>(Func, Dest, Src1, Src2, Emitter);
1388}
1389
1390template <class Machine>
1391void InstX86Shld<Machine>::dump(const Cfg *Func) const {
1392 if (!BuildDefs::dump())
1393 return;
1394 Ostream &Str = Func->getContext()->getStrDump();
1395 this->dumpDest(Func);
1396 Str << " = shld." << this->getDest()->getType() << " ";
1397 this->dumpSources(Func);
1398}
1399
1400template <class Machine>
1401void InstX86Shrd<Machine>::emit(const Cfg *Func) const {
1402 if (!BuildDefs::dump())
1403 return;
1404 Ostream &Str = Func->getContext()->getStrEmit();
1405 Variable *Dest = this->getDest();
1406 assert(this->getSrcSize() == 3);
1407 assert(Dest == this->getSrc(0));
Jim Stichnoth6106df82015-12-16 06:17:58 -08001408 Str << "\t"
1409 "shrd" << this->getWidthString(Dest->getType()) << "\t";
Jim Stichnoth5bff61c2015-10-28 09:26:00 -07001410 this->getSrc(2)->emit(Func);
John Porto921856d2015-07-07 11:56:26 -07001411 Str << ", ";
1412 this->getSrc(1)->emit(Func);
1413 Str << ", ";
1414 Dest->emit(Func);
1415}
1416
1417template <class Machine>
1418void InstX86Shrd<Machine>::emitIAS(const Cfg *Func) const {
1419 assert(this->getSrcSize() == 3);
1420 assert(this->getDest() == this->getSrc(0));
1421 const Variable *Dest = this->getDest();
1422 const Operand *Src1 = this->getSrc(1);
1423 const Operand *Src2 = this->getSrc(2);
1424 static const typename InstX86Base<
1425 Machine>::Traits::Assembler::GPREmitterShiftD Emitter = {
1426 &InstX86Base<Machine>::Traits::Assembler::shrd,
1427 &InstX86Base<Machine>::Traits::Assembler::shrd};
1428 emitIASGPRShiftDouble<Machine>(Func, Dest, Src1, Src2, Emitter);
1429}
1430
1431template <class Machine>
1432void InstX86Shrd<Machine>::dump(const Cfg *Func) const {
1433 if (!BuildDefs::dump())
1434 return;
1435 Ostream &Str = Func->getContext()->getStrDump();
1436 this->dumpDest(Func);
1437 Str << " = shrd." << this->getDest()->getType() << " ";
1438 this->dumpSources(Func);
1439}
1440
1441template <class Machine>
1442void InstX86Cmov<Machine>::emit(const Cfg *Func) const {
1443 if (!BuildDefs::dump())
1444 return;
1445 Ostream &Str = Func->getContext()->getStrEmit();
1446 Variable *Dest = this->getDest();
1447 Str << "\t";
1448 assert(Condition != InstX86Base<Machine>::Traits::Cond::Br_None);
1449 assert(this->getDest()->hasReg());
1450 Str << "cmov"
1451 << InstX86Base<Machine>::Traits::InstBrAttributes[Condition].DisplayString
1452 << this->getWidthString(Dest->getType()) << "\t";
1453 this->getSrc(1)->emit(Func);
1454 Str << ", ";
1455 Dest->emit(Func);
1456}
1457
1458template <class Machine>
1459void InstX86Cmov<Machine>::emitIAS(const Cfg *Func) const {
1460 assert(Condition != InstX86Base<Machine>::Traits::Cond::Br_None);
1461 assert(this->getDest()->hasReg());
1462 assert(this->getSrcSize() == 2);
1463 Operand *Src = this->getSrc(1);
1464 Type SrcTy = Src->getType();
John Porto1d235422015-08-12 12:37:53 -07001465 assert(SrcTy == IceType_i16 || SrcTy == IceType_i32 ||
1466 (InstX86Base<Machine>::Traits::Is64Bit));
John Porto921856d2015-07-07 11:56:26 -07001467 typename InstX86Base<Machine>::Traits::Assembler *Asm =
1468 Func->getAssembler<typename InstX86Base<Machine>::Traits::Assembler>();
David Sehrb8e49c12015-11-12 14:41:22 -08001469 auto *Target = InstX86Base<Machine>::getTarget(Func);
John Porto921856d2015-07-07 11:56:26 -07001470 if (const auto *SrcVar = llvm::dyn_cast<Variable>(Src)) {
1471 if (SrcVar->hasReg()) {
Jim Stichnoth5bff61c2015-10-28 09:26:00 -07001472 Asm->cmov(
1473 SrcTy, Condition, InstX86Base<Machine>::Traits::getEncodedGPR(
1474 this->getDest()->getRegNum()),
1475 InstX86Base<Machine>::Traits::getEncodedGPR(SrcVar->getRegNum()));
John Porto921856d2015-07-07 11:56:26 -07001476 } else {
David Sehr21fd1032015-11-13 16:32:37 -08001477 Asm->cmov(SrcTy, Condition, InstX86Base<Machine>::Traits::getEncodedGPR(
1478 this->getDest()->getRegNum()),
1479 Target->stackVarToAsmOperand(SrcVar));
John Porto921856d2015-07-07 11:56:26 -07001480 }
Jim Stichnoth5bff61c2015-10-28 09:26:00 -07001481 } else if (const auto *Mem = llvm::dyn_cast<
John Porto921856d2015-07-07 11:56:26 -07001482 typename InstX86Base<Machine>::Traits::X86OperandMem>(Src)) {
1483 assert(Mem->getSegmentRegister() ==
1484 InstX86Base<Machine>::Traits::X86OperandMem::DefaultSegment);
Jim Stichnoth5bff61c2015-10-28 09:26:00 -07001485 Asm->cmov(SrcTy, Condition, InstX86Base<Machine>::Traits::getEncodedGPR(
1486 this->getDest()->getRegNum()),
David Sehr4318a412015-11-11 15:01:55 -08001487 Mem->toAsmAddress(Asm, Target));
John Porto921856d2015-07-07 11:56:26 -07001488 } else {
1489 llvm_unreachable("Unexpected operand type");
1490 }
1491}
1492
1493template <class Machine>
1494void InstX86Cmov<Machine>::dump(const Cfg *Func) const {
1495 if (!BuildDefs::dump())
1496 return;
1497 Ostream &Str = Func->getContext()->getStrDump();
1498 Str << "cmov"
1499 << InstX86Base<Machine>::Traits::InstBrAttributes[Condition].DisplayString
1500 << ".";
1501 Str << this->getDest()->getType() << " ";
1502 this->dumpDest(Func);
1503 Str << ", ";
1504 this->dumpSources(Func);
1505}
1506
1507template <class Machine>
1508void InstX86Cmpps<Machine>::emit(const Cfg *Func) const {
1509 if (!BuildDefs::dump())
1510 return;
1511 Ostream &Str = Func->getContext()->getStrEmit();
1512 assert(this->getSrcSize() == 2);
1513 assert(Condition < InstX86Base<Machine>::Traits::Cond::Cmpps_Invalid);
David Sehre3984282015-12-15 17:34:55 -08001514 Type DestTy = this->Dest->getType();
Jim Stichnoth6106df82015-12-16 06:17:58 -08001515 Str << "\t"
1516 "cmp"
John Porto921856d2015-07-07 11:56:26 -07001517 << InstX86Base<Machine>::Traits::InstCmppsAttributes[Condition].EmitString
David Sehre3984282015-12-15 17:34:55 -08001518 << InstX86Base<Machine>::Traits::TypeAttributes[DestTy].PdPsString
John Porto921856d2015-07-07 11:56:26 -07001519 << "\t";
1520 this->getSrc(1)->emit(Func);
1521 Str << ", ";
1522 this->getDest()->emit(Func);
1523}
1524
1525template <class Machine>
1526void InstX86Cmpps<Machine>::emitIAS(const Cfg *Func) const {
1527 typename InstX86Base<Machine>::Traits::Assembler *Asm =
1528 Func->getAssembler<typename InstX86Base<Machine>::Traits::Assembler>();
1529 assert(this->getSrcSize() == 2);
1530 assert(Condition < InstX86Base<Machine>::Traits::Cond::Cmpps_Invalid);
Andrew Scull57e12682015-09-16 11:30:19 -07001531 // Assuming there isn't any load folding for cmpps, and vector constants are
1532 // not allowed in PNaCl.
John Porto921856d2015-07-07 11:56:26 -07001533 assert(llvm::isa<Variable>(this->getSrc(1)));
David Sehrb8e49c12015-11-12 14:41:22 -08001534 auto *Target = InstX86Base<Machine>::getTarget(Func);
Jim Stichnoth5bff61c2015-10-28 09:26:00 -07001535 const auto *SrcVar = llvm::cast<Variable>(this->getSrc(1));
John Porto921856d2015-07-07 11:56:26 -07001536 if (SrcVar->hasReg()) {
David Sehre3984282015-12-15 17:34:55 -08001537 Asm->cmpps(this->getDest()->getType(),
1538 InstX86Base<Machine>::Traits::getEncodedXmm(
John Porto921856d2015-07-07 11:56:26 -07001539 this->getDest()->getRegNum()),
Jim Stichnoth5bff61c2015-10-28 09:26:00 -07001540 InstX86Base<Machine>::Traits::getEncodedXmm(SrcVar->getRegNum()),
John Porto921856d2015-07-07 11:56:26 -07001541 Condition);
1542 } else {
1543 typename InstX86Base<Machine>::Traits::Address SrcStackAddr =
David Sehrb8e49c12015-11-12 14:41:22 -08001544 Target->stackVarToAsmOperand(SrcVar);
David Sehre3984282015-12-15 17:34:55 -08001545 Asm->cmpps(this->getDest()->getType(),
1546 InstX86Base<Machine>::Traits::getEncodedXmm(
John Porto921856d2015-07-07 11:56:26 -07001547 this->getDest()->getRegNum()),
1548 SrcStackAddr, Condition);
1549 }
1550}
1551
1552template <class Machine>
1553void InstX86Cmpps<Machine>::dump(const Cfg *Func) const {
1554 if (!BuildDefs::dump())
1555 return;
1556 Ostream &Str = Func->getContext()->getStrDump();
1557 assert(Condition < InstX86Base<Machine>::Traits::Cond::Cmpps_Invalid);
1558 this->dumpDest(Func);
1559 Str << " = cmp"
1560 << InstX86Base<Machine>::Traits::InstCmppsAttributes[Condition].EmitString
1561 << "ps"
Jim Stichnoth6106df82015-12-16 06:17:58 -08001562 "\t";
John Porto921856d2015-07-07 11:56:26 -07001563 this->dumpSources(Func);
1564}
1565
1566template <class Machine>
1567void InstX86Cmpxchg<Machine>::emit(const Cfg *Func) const {
1568 if (!BuildDefs::dump())
1569 return;
1570 Ostream &Str = Func->getContext()->getStrEmit();
1571 assert(this->getSrcSize() == 3);
1572 if (this->Locked) {
Jim Stichnoth6106df82015-12-16 06:17:58 -08001573 Str << "\t"
1574 "lock";
John Porto921856d2015-07-07 11:56:26 -07001575 }
Jim Stichnoth6106df82015-12-16 06:17:58 -08001576 Str << "\t"
1577 "cmpxchg" << this->getWidthString(this->getSrc(0)->getType()) << "\t";
John Porto921856d2015-07-07 11:56:26 -07001578 this->getSrc(2)->emit(Func);
1579 Str << ", ";
1580 this->getSrc(0)->emit(Func);
1581}
1582
1583template <class Machine>
1584void InstX86Cmpxchg<Machine>::emitIAS(const Cfg *Func) const {
1585 assert(this->getSrcSize() == 3);
1586 typename InstX86Base<Machine>::Traits::Assembler *Asm =
1587 Func->getAssembler<typename InstX86Base<Machine>::Traits::Assembler>();
1588 Type Ty = this->getSrc(0)->getType();
David Sehrb8e49c12015-11-12 14:41:22 -08001589 auto *Target = InstX86Base<Machine>::getTarget(Func);
John Porto921856d2015-07-07 11:56:26 -07001590 const auto Mem =
1591 llvm::cast<typename InstX86Base<Machine>::Traits::X86OperandMem>(
1592 this->getSrc(0));
1593 assert(Mem->getSegmentRegister() ==
1594 InstX86Base<Machine>::Traits::X86OperandMem::DefaultSegment);
1595 const typename InstX86Base<Machine>::Traits::Address Addr =
David Sehr4318a412015-11-11 15:01:55 -08001596 Mem->toAsmAddress(Asm, Target);
Jim Stichnoth5bff61c2015-10-28 09:26:00 -07001597 const auto *VarReg = llvm::cast<Variable>(this->getSrc(2));
John Porto921856d2015-07-07 11:56:26 -07001598 assert(VarReg->hasReg());
1599 const typename InstX86Base<Machine>::Traits::RegisterSet::GPRRegister Reg =
Jim Stichnoth5bff61c2015-10-28 09:26:00 -07001600 InstX86Base<Machine>::Traits::getEncodedGPR(VarReg->getRegNum());
John Porto921856d2015-07-07 11:56:26 -07001601 Asm->cmpxchg(Ty, Addr, Reg, this->Locked);
1602}
1603
1604template <class Machine>
1605void InstX86Cmpxchg<Machine>::dump(const Cfg *Func) const {
1606 if (!BuildDefs::dump())
1607 return;
1608 Ostream &Str = Func->getContext()->getStrDump();
1609 if (this->Locked) {
1610 Str << "lock ";
1611 }
1612 Str << "cmpxchg." << this->getSrc(0)->getType() << " ";
1613 this->dumpSources(Func);
1614}
1615
1616template <class Machine>
1617void InstX86Cmpxchg8b<Machine>::emit(const Cfg *Func) const {
1618 if (!BuildDefs::dump())
1619 return;
1620 Ostream &Str = Func->getContext()->getStrEmit();
1621 assert(this->getSrcSize() == 5);
1622 if (this->Locked) {
Jim Stichnoth6106df82015-12-16 06:17:58 -08001623 Str << "\t"
1624 "lock";
John Porto921856d2015-07-07 11:56:26 -07001625 }
Jim Stichnoth6106df82015-12-16 06:17:58 -08001626 Str << "\t"
1627 "cmpxchg8b\t";
John Porto921856d2015-07-07 11:56:26 -07001628 this->getSrc(0)->emit(Func);
1629}
1630
1631template <class Machine>
1632void InstX86Cmpxchg8b<Machine>::emitIAS(const Cfg *Func) const {
1633 assert(this->getSrcSize() == 5);
1634 typename InstX86Base<Machine>::Traits::Assembler *Asm =
1635 Func->getAssembler<typename InstX86Base<Machine>::Traits::Assembler>();
1636 const auto Mem =
1637 llvm::cast<typename InstX86Base<Machine>::Traits::X86OperandMem>(
1638 this->getSrc(0));
1639 assert(Mem->getSegmentRegister() ==
1640 InstX86Base<Machine>::Traits::X86OperandMem::DefaultSegment);
David Sehrb8e49c12015-11-12 14:41:22 -08001641 auto *Target = InstX86Base<Machine>::getTarget(Func);
John Porto921856d2015-07-07 11:56:26 -07001642 const typename InstX86Base<Machine>::Traits::Address Addr =
David Sehr4318a412015-11-11 15:01:55 -08001643 Mem->toAsmAddress(Asm, Target);
John Porto921856d2015-07-07 11:56:26 -07001644 Asm->cmpxchg8b(Addr, this->Locked);
1645}
1646
1647template <class Machine>
1648void InstX86Cmpxchg8b<Machine>::dump(const Cfg *Func) const {
1649 if (!BuildDefs::dump())
1650 return;
1651 Ostream &Str = Func->getContext()->getStrDump();
1652 if (this->Locked) {
1653 Str << "lock ";
1654 }
1655 Str << "cmpxchg8b ";
1656 this->dumpSources(Func);
1657}
1658
1659template <class Machine> void InstX86Cvt<Machine>::emit(const Cfg *Func) const {
1660 if (!BuildDefs::dump())
1661 return;
1662 Ostream &Str = Func->getContext()->getStrEmit();
1663 assert(this->getSrcSize() == 1);
Jim Stichnoth6106df82015-12-16 06:17:58 -08001664 Str << "\t"
1665 "cvt";
John Porto921856d2015-07-07 11:56:26 -07001666 if (isTruncating())
1667 Str << "t";
1668 Str << InstX86Base<Machine>::Traits::TypeAttributes[this->getSrc(0)
1669 ->getType()]
1670 .CvtString << "2"
1671 << InstX86Base<
1672 Machine>::Traits::TypeAttributes[this->getDest()->getType()]
1673 .CvtString << "\t";
1674 this->getSrc(0)->emit(Func);
1675 Str << ", ";
1676 this->getDest()->emit(Func);
1677}
1678
1679template <class Machine>
1680void InstX86Cvt<Machine>::emitIAS(const Cfg *Func) const {
1681 assert(this->getSrcSize() == 1);
1682 const Variable *Dest = this->getDest();
1683 const Operand *Src = this->getSrc(0);
1684 Type DestTy = Dest->getType();
1685 Type SrcTy = Src->getType();
1686 switch (Variant) {
1687 case Si2ss: {
1688 assert(isScalarIntegerType(SrcTy));
John Porto1d235422015-08-12 12:37:53 -07001689 if (!InstX86Base<Machine>::Traits::Is64Bit) {
1690 assert(typeWidthInBytes(SrcTy) <= 4);
1691 } else {
1692 assert(SrcTy == IceType_i32 || SrcTy == IceType_i64);
1693 }
John Porto921856d2015-07-07 11:56:26 -07001694 assert(isScalarFloatingType(DestTy));
1695 static const typename InstX86Base<Machine>::Traits::Assembler::
1696 template CastEmitterRegOp<
1697 typename InstX86Base<Machine>::Traits::RegisterSet::XmmRegister,
1698 typename InstX86Base<Machine>::Traits::RegisterSet::GPRRegister>
1699 Emitter = {&InstX86Base<Machine>::Traits::Assembler::cvtsi2ss,
1700 &InstX86Base<Machine>::Traits::Assembler::cvtsi2ss};
1701 emitIASCastRegOp<
1702 Machine,
1703 typename InstX86Base<Machine>::Traits::RegisterSet::XmmRegister,
1704 typename InstX86Base<Machine>::Traits::RegisterSet::GPRRegister,
Jim Stichnoth5bff61c2015-10-28 09:26:00 -07001705 InstX86Base<Machine>::Traits::getEncodedXmm,
1706 InstX86Base<Machine>::Traits::getEncodedGPR>(Func, DestTy, Dest, SrcTy,
1707 Src, Emitter);
John Porto921856d2015-07-07 11:56:26 -07001708 return;
1709 }
1710 case Tss2si: {
1711 assert(isScalarFloatingType(SrcTy));
1712 assert(isScalarIntegerType(DestTy));
John Porto1d235422015-08-12 12:37:53 -07001713 if (!InstX86Base<Machine>::Traits::Is64Bit) {
1714 assert(typeWidthInBytes(DestTy) <= 4);
1715 } else {
1716 assert(DestTy == IceType_i32 || DestTy == IceType_i64);
1717 }
John Porto921856d2015-07-07 11:56:26 -07001718 static const typename InstX86Base<Machine>::Traits::Assembler::
1719 template CastEmitterRegOp<
1720 typename InstX86Base<Machine>::Traits::RegisterSet::GPRRegister,
1721 typename InstX86Base<Machine>::Traits::RegisterSet::XmmRegister>
1722 Emitter = {&InstX86Base<Machine>::Traits::Assembler::cvttss2si,
1723 &InstX86Base<Machine>::Traits::Assembler::cvttss2si};
1724 emitIASCastRegOp<
1725 Machine,
1726 typename InstX86Base<Machine>::Traits::RegisterSet::GPRRegister,
1727 typename InstX86Base<Machine>::Traits::RegisterSet::XmmRegister,
Jim Stichnoth5bff61c2015-10-28 09:26:00 -07001728 InstX86Base<Machine>::Traits::getEncodedGPR,
1729 InstX86Base<Machine>::Traits::getEncodedXmm>(Func, DestTy, Dest, SrcTy,
1730 Src, Emitter);
John Porto921856d2015-07-07 11:56:26 -07001731 return;
1732 }
1733 case Float2float: {
1734 assert(isScalarFloatingType(SrcTy));
1735 assert(isScalarFloatingType(DestTy));
1736 assert(DestTy != SrcTy);
1737 static const typename InstX86Base<
1738 Machine>::Traits::Assembler::XmmEmitterRegOp Emitter = {
1739 &InstX86Base<Machine>::Traits::Assembler::cvtfloat2float,
1740 &InstX86Base<Machine>::Traits::Assembler::cvtfloat2float};
1741 emitIASRegOpTyXMM<Machine>(Func, SrcTy, Dest, Src, Emitter);
1742 return;
1743 }
1744 case Dq2ps: {
1745 assert(isVectorIntegerType(SrcTy));
1746 assert(isVectorFloatingType(DestTy));
1747 static const typename InstX86Base<
1748 Machine>::Traits::Assembler::XmmEmitterRegOp Emitter = {
1749 &InstX86Base<Machine>::Traits::Assembler::cvtdq2ps,
1750 &InstX86Base<Machine>::Traits::Assembler::cvtdq2ps};
1751 emitIASRegOpTyXMM<Machine>(Func, DestTy, Dest, Src, Emitter);
1752 return;
1753 }
1754 case Tps2dq: {
1755 assert(isVectorFloatingType(SrcTy));
1756 assert(isVectorIntegerType(DestTy));
1757 static const typename InstX86Base<
1758 Machine>::Traits::Assembler::XmmEmitterRegOp Emitter = {
1759 &InstX86Base<Machine>::Traits::Assembler::cvttps2dq,
1760 &InstX86Base<Machine>::Traits::Assembler::cvttps2dq};
1761 emitIASRegOpTyXMM<Machine>(Func, DestTy, Dest, Src, Emitter);
1762 return;
1763 }
1764 }
1765}
1766
1767template <class Machine> void InstX86Cvt<Machine>::dump(const Cfg *Func) const {
1768 if (!BuildDefs::dump())
1769 return;
1770 Ostream &Str = Func->getContext()->getStrDump();
1771 this->dumpDest(Func);
1772 Str << " = cvt";
1773 if (isTruncating())
1774 Str << "t";
1775 Str << InstX86Base<Machine>::Traits::TypeAttributes[this->getSrc(0)
1776 ->getType()]
1777 .CvtString << "2"
1778 << InstX86Base<
1779 Machine>::Traits::TypeAttributes[this->getDest()->getType()]
1780 .CvtString << " ";
1781 this->dumpSources(Func);
1782}
1783
1784template <class Machine>
1785void InstX86Icmp<Machine>::emit(const Cfg *Func) const {
1786 if (!BuildDefs::dump())
1787 return;
1788 Ostream &Str = Func->getContext()->getStrEmit();
1789 assert(this->getSrcSize() == 2);
Jim Stichnoth6106df82015-12-16 06:17:58 -08001790 Str << "\t"
1791 "cmp" << this->getWidthString(this->getSrc(0)->getType()) << "\t";
John Porto921856d2015-07-07 11:56:26 -07001792 this->getSrc(1)->emit(Func);
1793 Str << ", ";
1794 this->getSrc(0)->emit(Func);
1795}
1796
1797template <class Machine>
1798void InstX86Icmp<Machine>::emitIAS(const Cfg *Func) const {
1799 assert(this->getSrcSize() == 2);
1800 const Operand *Src0 = this->getSrc(0);
1801 const Operand *Src1 = this->getSrc(1);
1802 Type Ty = Src0->getType();
1803 static const typename InstX86Base<Machine>::Traits::Assembler::GPREmitterRegOp
1804 RegEmitter = {&InstX86Base<Machine>::Traits::Assembler::cmp,
1805 &InstX86Base<Machine>::Traits::Assembler::cmp,
1806 &InstX86Base<Machine>::Traits::Assembler::cmp};
1807 static const typename InstX86Base<
1808 Machine>::Traits::Assembler::GPREmitterAddrOp AddrEmitter = {
1809 &InstX86Base<Machine>::Traits::Assembler::cmp,
1810 &InstX86Base<Machine>::Traits::Assembler::cmp};
Jim Stichnoth5bff61c2015-10-28 09:26:00 -07001811 if (const auto *SrcVar0 = llvm::dyn_cast<Variable>(Src0)) {
John Porto921856d2015-07-07 11:56:26 -07001812 if (SrcVar0->hasReg()) {
1813 emitIASRegOpTyGPR<Machine>(Func, Ty, SrcVar0, Src1, RegEmitter);
1814 return;
1815 }
1816 }
1817 emitIASAsAddrOpTyGPR<Machine>(Func, Ty, Src0, Src1, AddrEmitter);
1818}
1819
1820template <class Machine>
1821void InstX86Icmp<Machine>::dump(const Cfg *Func) const {
1822 if (!BuildDefs::dump())
1823 return;
1824 Ostream &Str = Func->getContext()->getStrDump();
1825 Str << "cmp." << this->getSrc(0)->getType() << " ";
1826 this->dumpSources(Func);
1827}
1828
1829template <class Machine>
1830void InstX86Ucomiss<Machine>::emit(const Cfg *Func) const {
1831 if (!BuildDefs::dump())
1832 return;
1833 Ostream &Str = Func->getContext()->getStrEmit();
1834 assert(this->getSrcSize() == 2);
Jim Stichnoth6106df82015-12-16 06:17:58 -08001835 Str << "\t"
1836 "ucomi"
John Porto921856d2015-07-07 11:56:26 -07001837 << InstX86Base<Machine>::Traits::TypeAttributes[this->getSrc(0)
1838 ->getType()]
1839 .SdSsString << "\t";
1840 this->getSrc(1)->emit(Func);
1841 Str << ", ";
1842 this->getSrc(0)->emit(Func);
1843}
1844
1845template <class Machine>
1846void InstX86Ucomiss<Machine>::emitIAS(const Cfg *Func) const {
1847 assert(this->getSrcSize() == 2);
Andrew Scull57e12682015-09-16 11:30:19 -07001848 // Currently src0 is always a variable by convention, to avoid having two
1849 // memory operands.
John Porto921856d2015-07-07 11:56:26 -07001850 assert(llvm::isa<Variable>(this->getSrc(0)));
Jim Stichnoth5bff61c2015-10-28 09:26:00 -07001851 const auto *Src0Var = llvm::cast<Variable>(this->getSrc(0));
John Porto921856d2015-07-07 11:56:26 -07001852 Type Ty = Src0Var->getType();
1853 static const typename InstX86Base<Machine>::Traits::Assembler::XmmEmitterRegOp
1854 Emitter = {&InstX86Base<Machine>::Traits::Assembler::ucomiss,
1855 &InstX86Base<Machine>::Traits::Assembler::ucomiss};
1856 emitIASRegOpTyXMM<Machine>(Func, Ty, Src0Var, this->getSrc(1), Emitter);
1857}
1858
1859template <class Machine>
1860void InstX86Ucomiss<Machine>::dump(const Cfg *Func) const {
1861 if (!BuildDefs::dump())
1862 return;
1863 Ostream &Str = Func->getContext()->getStrDump();
1864 Str << "ucomiss." << this->getSrc(0)->getType() << " ";
1865 this->dumpSources(Func);
1866}
1867
1868template <class Machine> void InstX86UD2<Machine>::emit(const Cfg *Func) const {
1869 if (!BuildDefs::dump())
1870 return;
1871 Ostream &Str = Func->getContext()->getStrEmit();
1872 assert(this->getSrcSize() == 0);
Jim Stichnoth6106df82015-12-16 06:17:58 -08001873 Str << "\t"
1874 "ud2";
John Porto921856d2015-07-07 11:56:26 -07001875}
1876
1877template <class Machine>
1878void InstX86UD2<Machine>::emitIAS(const Cfg *Func) const {
1879 typename InstX86Base<Machine>::Traits::Assembler *Asm =
1880 Func->getAssembler<typename InstX86Base<Machine>::Traits::Assembler>();
1881 Asm->ud2();
1882}
1883
1884template <class Machine> void InstX86UD2<Machine>::dump(const Cfg *Func) const {
1885 if (!BuildDefs::dump())
1886 return;
1887 Ostream &Str = Func->getContext()->getStrDump();
1888 Str << "ud2";
1889}
1890
1891template <class Machine>
1892void InstX86Test<Machine>::emit(const Cfg *Func) const {
1893 if (!BuildDefs::dump())
1894 return;
1895 Ostream &Str = Func->getContext()->getStrEmit();
1896 assert(this->getSrcSize() == 2);
Jim Stichnoth6106df82015-12-16 06:17:58 -08001897 Str << "\t"
1898 "test" << this->getWidthString(this->getSrc(0)->getType()) << "\t";
John Porto921856d2015-07-07 11:56:26 -07001899 this->getSrc(1)->emit(Func);
1900 Str << ", ";
1901 this->getSrc(0)->emit(Func);
1902}
1903
1904template <class Machine>
1905void InstX86Test<Machine>::emitIAS(const Cfg *Func) const {
1906 assert(this->getSrcSize() == 2);
1907 const Operand *Src0 = this->getSrc(0);
1908 const Operand *Src1 = this->getSrc(1);
1909 Type Ty = Src0->getType();
1910 // The Reg/Addr form of test is not encodeable.
1911 static const typename InstX86Base<Machine>::Traits::Assembler::GPREmitterRegOp
1912 RegEmitter = {&InstX86Base<Machine>::Traits::Assembler::test, nullptr,
1913 &InstX86Base<Machine>::Traits::Assembler::test};
1914 static const typename InstX86Base<
1915 Machine>::Traits::Assembler::GPREmitterAddrOp AddrEmitter = {
1916 &InstX86Base<Machine>::Traits::Assembler::test,
1917 &InstX86Base<Machine>::Traits::Assembler::test};
Jim Stichnoth5bff61c2015-10-28 09:26:00 -07001918 if (const auto *SrcVar0 = llvm::dyn_cast<Variable>(Src0)) {
John Porto921856d2015-07-07 11:56:26 -07001919 if (SrcVar0->hasReg()) {
1920 emitIASRegOpTyGPR<Machine>(Func, Ty, SrcVar0, Src1, RegEmitter);
1921 return;
1922 }
1923 }
John Porto921856d2015-07-07 11:56:26 -07001924 emitIASAsAddrOpTyGPR<Machine>(Func, Ty, Src0, Src1, AddrEmitter);
1925}
1926
1927template <class Machine>
1928void InstX86Test<Machine>::dump(const Cfg *Func) const {
1929 if (!BuildDefs::dump())
1930 return;
1931 Ostream &Str = Func->getContext()->getStrDump();
1932 Str << "test." << this->getSrc(0)->getType() << " ";
1933 this->dumpSources(Func);
1934}
1935
1936template <class Machine>
1937void InstX86Mfence<Machine>::emit(const Cfg *Func) const {
1938 if (!BuildDefs::dump())
1939 return;
1940 Ostream &Str = Func->getContext()->getStrEmit();
1941 assert(this->getSrcSize() == 0);
Jim Stichnoth6106df82015-12-16 06:17:58 -08001942 Str << "\t"
1943 "mfence";
John Porto921856d2015-07-07 11:56:26 -07001944}
1945
1946template <class Machine>
1947void InstX86Mfence<Machine>::emitIAS(const Cfg *Func) const {
1948 typename InstX86Base<Machine>::Traits::Assembler *Asm =
1949 Func->getAssembler<typename InstX86Base<Machine>::Traits::Assembler>();
1950 Asm->mfence();
1951}
1952
1953template <class Machine>
1954void InstX86Mfence<Machine>::dump(const Cfg *Func) const {
1955 if (!BuildDefs::dump())
1956 return;
1957 Ostream &Str = Func->getContext()->getStrDump();
1958 Str << "mfence";
1959}
1960
1961template <class Machine>
1962void InstX86Store<Machine>::emit(const Cfg *Func) const {
1963 if (!BuildDefs::dump())
1964 return;
1965 Ostream &Str = Func->getContext()->getStrEmit();
1966 assert(this->getSrcSize() == 2);
1967 Type Ty = this->getSrc(0)->getType();
Jim Stichnoth6106df82015-12-16 06:17:58 -08001968 Str << "\t"
1969 "mov" << this->getWidthString(Ty)
John Porto921856d2015-07-07 11:56:26 -07001970 << InstX86Base<Machine>::Traits::TypeAttributes[Ty].SdSsString << "\t";
1971 this->getSrc(0)->emit(Func);
1972 Str << ", ";
1973 this->getSrc(1)->emit(Func);
1974}
1975
1976template <class Machine>
1977void InstX86Store<Machine>::emitIAS(const Cfg *Func) const {
1978 assert(this->getSrcSize() == 2);
1979 const Operand *Dest = this->getSrc(1);
1980 const Operand *Src = this->getSrc(0);
1981 Type DestTy = Dest->getType();
1982 if (isScalarFloatingType(DestTy)) {
1983 // Src must be a register, since Dest is a Mem operand of some kind.
Jim Stichnoth5bff61c2015-10-28 09:26:00 -07001984 const auto *SrcVar = llvm::cast<Variable>(Src);
John Porto921856d2015-07-07 11:56:26 -07001985 assert(SrcVar->hasReg());
1986 typename InstX86Base<Machine>::Traits::RegisterSet::XmmRegister SrcReg =
Jim Stichnoth5bff61c2015-10-28 09:26:00 -07001987 InstX86Base<Machine>::Traits::getEncodedXmm(SrcVar->getRegNum());
John Porto921856d2015-07-07 11:56:26 -07001988 typename InstX86Base<Machine>::Traits::Assembler *Asm =
1989 Func->getAssembler<typename InstX86Base<Machine>::Traits::Assembler>();
David Sehrb8e49c12015-11-12 14:41:22 -08001990 auto *Target = InstX86Base<Machine>::getTarget(Func);
Jim Stichnoth5bff61c2015-10-28 09:26:00 -07001991 if (const auto *DestVar = llvm::dyn_cast<Variable>(Dest)) {
John Porto921856d2015-07-07 11:56:26 -07001992 assert(!DestVar->hasReg());
1993 typename InstX86Base<Machine>::Traits::Address StackAddr(
David Sehrb8e49c12015-11-12 14:41:22 -08001994 Target->stackVarToAsmOperand(DestVar));
John Porto921856d2015-07-07 11:56:26 -07001995 Asm->movss(DestTy, StackAddr, SrcReg);
1996 } else {
1997 const auto DestMem =
1998 llvm::cast<typename InstX86Base<Machine>::Traits::X86OperandMem>(
1999 Dest);
2000 assert(DestMem->getSegmentRegister() ==
2001 InstX86Base<Machine>::Traits::X86OperandMem::DefaultSegment);
David Sehr4318a412015-11-11 15:01:55 -08002002 Asm->movss(DestTy, DestMem->toAsmAddress(Asm, Target), SrcReg);
John Porto921856d2015-07-07 11:56:26 -07002003 }
2004 return;
2005 } else {
2006 assert(isScalarIntegerType(DestTy));
2007 static const typename InstX86Base<
2008 Machine>::Traits::Assembler::GPREmitterAddrOp GPRAddrEmitter = {
2009 &InstX86Base<Machine>::Traits::Assembler::mov,
2010 &InstX86Base<Machine>::Traits::Assembler::mov};
2011 emitIASAsAddrOpTyGPR<Machine>(Func, DestTy, Dest, Src, GPRAddrEmitter);
2012 }
2013}
2014
2015template <class Machine>
2016void InstX86Store<Machine>::dump(const Cfg *Func) const {
2017 if (!BuildDefs::dump())
2018 return;
2019 Ostream &Str = Func->getContext()->getStrDump();
2020 Str << "mov." << this->getSrc(0)->getType() << " ";
2021 this->getSrc(1)->dump(Func);
2022 Str << ", ";
2023 this->getSrc(0)->dump(Func);
2024}
2025
2026template <class Machine>
2027void InstX86StoreP<Machine>::emit(const Cfg *Func) const {
2028 if (!BuildDefs::dump())
2029 return;
2030 Ostream &Str = Func->getContext()->getStrEmit();
2031 assert(this->getSrcSize() == 2);
Andrew Scull713dbde2015-08-04 14:25:27 -07002032 assert(isVectorType(this->getSrc(1)->getType()));
Jim Stichnoth6106df82015-12-16 06:17:58 -08002033 Str << "\t"
2034 "movups\t";
John Porto921856d2015-07-07 11:56:26 -07002035 this->getSrc(0)->emit(Func);
2036 Str << ", ";
2037 this->getSrc(1)->emit(Func);
2038}
2039
2040template <class Machine>
2041void InstX86StoreP<Machine>::emitIAS(const Cfg *Func) const {
2042 typename InstX86Base<Machine>::Traits::Assembler *Asm =
2043 Func->getAssembler<typename InstX86Base<Machine>::Traits::Assembler>();
2044 assert(this->getSrcSize() == 2);
Jim Stichnoth5bff61c2015-10-28 09:26:00 -07002045 const auto *SrcVar = llvm::cast<Variable>(this->getSrc(0));
John Porto921856d2015-07-07 11:56:26 -07002046 const auto DestMem =
2047 llvm::cast<typename InstX86Base<Machine>::Traits::X86OperandMem>(
2048 this->getSrc(1));
2049 assert(DestMem->getSegmentRegister() ==
2050 InstX86Base<Machine>::Traits::X86OperandMem::DefaultSegment);
2051 assert(SrcVar->hasReg());
David Sehrb8e49c12015-11-12 14:41:22 -08002052 auto *Target = InstX86Base<Machine>::getTarget(Func);
David Sehr4318a412015-11-11 15:01:55 -08002053 Asm->movups(DestMem->toAsmAddress(Asm, Target),
Jim Stichnoth5bff61c2015-10-28 09:26:00 -07002054 InstX86Base<Machine>::Traits::getEncodedXmm(SrcVar->getRegNum()));
John Porto921856d2015-07-07 11:56:26 -07002055}
2056
2057template <class Machine>
2058void InstX86StoreP<Machine>::dump(const Cfg *Func) const {
2059 if (!BuildDefs::dump())
2060 return;
2061 Ostream &Str = Func->getContext()->getStrDump();
2062 Str << "storep." << this->getSrc(0)->getType() << " ";
2063 this->getSrc(1)->dump(Func);
2064 Str << ", ";
2065 this->getSrc(0)->dump(Func);
2066}
2067
2068template <class Machine>
2069void InstX86StoreQ<Machine>::emit(const Cfg *Func) const {
2070 if (!BuildDefs::dump())
2071 return;
2072 Ostream &Str = Func->getContext()->getStrEmit();
2073 assert(this->getSrcSize() == 2);
2074 assert(this->getSrc(1)->getType() == IceType_i64 ||
Andrew Scull713dbde2015-08-04 14:25:27 -07002075 this->getSrc(1)->getType() == IceType_f64 ||
2076 isVectorType(this->getSrc(1)->getType()));
Jim Stichnoth6106df82015-12-16 06:17:58 -08002077 Str << "\t"
2078 "movq\t";
John Porto921856d2015-07-07 11:56:26 -07002079 this->getSrc(0)->emit(Func);
2080 Str << ", ";
2081 this->getSrc(1)->emit(Func);
2082}
2083
2084template <class Machine>
2085void InstX86StoreQ<Machine>::emitIAS(const Cfg *Func) const {
2086 typename InstX86Base<Machine>::Traits::Assembler *Asm =
2087 Func->getAssembler<typename InstX86Base<Machine>::Traits::Assembler>();
2088 assert(this->getSrcSize() == 2);
Jim Stichnoth5bff61c2015-10-28 09:26:00 -07002089 const auto *SrcVar = llvm::cast<Variable>(this->getSrc(0));
John Porto921856d2015-07-07 11:56:26 -07002090 const auto DestMem =
2091 llvm::cast<typename InstX86Base<Machine>::Traits::X86OperandMem>(
2092 this->getSrc(1));
2093 assert(DestMem->getSegmentRegister() ==
2094 InstX86Base<Machine>::Traits::X86OperandMem::DefaultSegment);
2095 assert(SrcVar->hasReg());
David Sehrb8e49c12015-11-12 14:41:22 -08002096 auto *Target = InstX86Base<Machine>::getTarget(Func);
David Sehr4318a412015-11-11 15:01:55 -08002097 Asm->movq(DestMem->toAsmAddress(Asm, Target),
Jim Stichnoth5bff61c2015-10-28 09:26:00 -07002098 InstX86Base<Machine>::Traits::getEncodedXmm(SrcVar->getRegNum()));
John Porto921856d2015-07-07 11:56:26 -07002099}
2100
2101template <class Machine>
2102void InstX86StoreQ<Machine>::dump(const Cfg *Func) const {
2103 if (!BuildDefs::dump())
2104 return;
2105 Ostream &Str = Func->getContext()->getStrDump();
2106 Str << "storeq." << this->getSrc(0)->getType() << " ";
2107 this->getSrc(1)->dump(Func);
2108 Str << ", ";
2109 this->getSrc(0)->dump(Func);
2110}
2111
2112template <class Machine> void InstX86Lea<Machine>::emit(const Cfg *Func) const {
2113 if (!BuildDefs::dump())
2114 return;
2115 Ostream &Str = Func->getContext()->getStrEmit();
2116 assert(this->getSrcSize() == 1);
2117 assert(this->getDest()->hasReg());
Jim Stichnoth6106df82015-12-16 06:17:58 -08002118 Str << "\t"
2119 "leal\t";
John Porto921856d2015-07-07 11:56:26 -07002120 Operand *Src0 = this->getSrc(0);
Jim Stichnoth5bff61c2015-10-28 09:26:00 -07002121 if (const auto *Src0Var = llvm::dyn_cast<Variable>(Src0)) {
John Porto921856d2015-07-07 11:56:26 -07002122 Type Ty = Src0Var->getType();
2123 // lea on x86-32 doesn't accept mem128 operands, so cast VSrc0 to an
2124 // acceptable type.
Jim Stichnoth5bff61c2015-10-28 09:26:00 -07002125 Src0Var->asType(isVectorType(Ty) ? IceType_i32 : Ty, Variable::NoRegister)
2126 ->emit(Func);
John Porto921856d2015-07-07 11:56:26 -07002127 } else {
2128 Src0->emit(Func);
2129 }
2130 Str << ", ";
2131 this->getDest()->emit(Func);
2132}
2133
2134template <class Machine> void InstX86Mov<Machine>::emit(const Cfg *Func) const {
2135 if (!BuildDefs::dump())
2136 return;
2137 Ostream &Str = Func->getContext()->getStrEmit();
2138 assert(this->getSrcSize() == 1);
2139 Operand *Src = this->getSrc(0);
2140 Type SrcTy = Src->getType();
2141 Type DestTy = this->getDest()->getType();
John Porto1d235422015-08-12 12:37:53 -07002142 if (InstX86Base<Machine>::Traits::Is64Bit && DestTy == IceType_i64 &&
John Porto008f4ce2015-12-24 13:22:18 -08002143 llvm::isa<ConstantInteger64>(Src)) {
Jim Stichnoth6106df82015-12-16 06:17:58 -08002144 Str << "\t"
John Porto008f4ce2015-12-24 13:22:18 -08002145 "movabs"
2146 "\t";
John Porto1d235422015-08-12 12:37:53 -07002147 } else {
Jim Stichnoth6106df82015-12-16 06:17:58 -08002148 Str << "\t"
2149 "mov" << (!isScalarFloatingType(DestTy)
2150 ? this->getWidthString(DestTy)
2151 : InstX86Base<Machine>::Traits::TypeAttributes[DestTy]
2152 .SdSsString) << "\t";
John Porto1d235422015-08-12 12:37:53 -07002153 }
Jim Stichnothc59288b2015-11-09 11:38:40 -08002154 // For an integer truncation operation, src is wider than dest. In this case,
2155 // we use a mov instruction whose data width matches the narrower dest.
Andrew Scull57e12682015-09-16 11:30:19 -07002156 // TODO: This assert disallows usages such as copying a floating
2157 // point value between a vector and a scalar (which movss is used for). Clean
2158 // this up.
David Sehr7f42a822015-11-13 16:59:02 -08002159 assert(
2160 InstX86Base<Machine>::getTarget(Func)->typeWidthInBytesOnStack(DestTy) ==
2161 InstX86Base<Machine>::getTarget(Func)->typeWidthInBytesOnStack(SrcTy));
Jim Stichnothc59288b2015-11-09 11:38:40 -08002162 const Operand *NewSrc = Src;
2163 if (auto *SrcVar = llvm::dyn_cast<Variable>(Src)) {
2164 int32_t NewRegNum = Variable::NoRegister;
2165 if (SrcVar->hasReg())
2166 NewRegNum = InstX86Base<Machine>::Traits::getGprForType(
2167 DestTy, SrcVar->getRegNum());
2168 if (SrcTy != DestTy)
2169 NewSrc = SrcVar->asType(DestTy, NewRegNum);
2170 }
2171 NewSrc->emit(Func);
John Porto921856d2015-07-07 11:56:26 -07002172 Str << ", ";
Jim Stichnothc59288b2015-11-09 11:38:40 -08002173 this->getDest()->emit(Func);
John Porto921856d2015-07-07 11:56:26 -07002174}
2175
2176template <class Machine>
2177void InstX86Mov<Machine>::emitIAS(const Cfg *Func) const {
2178 assert(this->getSrcSize() == 1);
2179 const Variable *Dest = this->getDest();
2180 const Operand *Src = this->getSrc(0);
2181 Type DestTy = Dest->getType();
2182 Type SrcTy = Src->getType();
2183 // Mov can be used for GPRs or XMM registers. Also, the type does not
Andrew Scull57e12682015-09-16 11:30:19 -07002184 // necessarily match (Mov can be used for bitcasts). However, when the type
2185 // does not match, one of the operands must be a register. Thus, the strategy
2186 // is to find out if Src or Dest are a register, then use that register's
2187 // type to decide on which emitter set to use. The emitter set will include
2188 // reg-reg movs, but that case should be unused when the types don't match.
John Porto921856d2015-07-07 11:56:26 -07002189 static const typename InstX86Base<Machine>::Traits::Assembler::XmmEmitterRegOp
2190 XmmRegEmitter = {&InstX86Base<Machine>::Traits::Assembler::movss,
2191 &InstX86Base<Machine>::Traits::Assembler::movss};
2192 static const typename InstX86Base<Machine>::Traits::Assembler::GPREmitterRegOp
2193 GPRRegEmitter = {&InstX86Base<Machine>::Traits::Assembler::mov,
2194 &InstX86Base<Machine>::Traits::Assembler::mov,
2195 &InstX86Base<Machine>::Traits::Assembler::mov};
2196 static const typename InstX86Base<
2197 Machine>::Traits::Assembler::GPREmitterAddrOp GPRAddrEmitter = {
2198 &InstX86Base<Machine>::Traits::Assembler::mov,
2199 &InstX86Base<Machine>::Traits::Assembler::mov};
Jim Stichnothc59288b2015-11-09 11:38:40 -08002200 // For an integer truncation operation, src is wider than dest. In this case,
2201 // we use a mov instruction whose data width matches the narrower dest.
Andrew Scull57e12682015-09-16 11:30:19 -07002202 // TODO: This assert disallows usages such as copying a floating
2203 // point value between a vector and a scalar (which movss is used for). Clean
2204 // this up.
David Sehrb8e49c12015-11-12 14:41:22 -08002205 auto *Target = InstX86Base<Machine>::getTarget(Func);
David Sehr4318a412015-11-11 15:01:55 -08002206 assert(Target->typeWidthInBytesOnStack(this->getDest()->getType()) ==
2207 Target->typeWidthInBytesOnStack(Src->getType()));
John Porto921856d2015-07-07 11:56:26 -07002208 if (Dest->hasReg()) {
2209 if (isScalarFloatingType(DestTy)) {
2210 emitIASRegOpTyXMM<Machine>(Func, DestTy, Dest, Src, XmmRegEmitter);
2211 return;
2212 } else {
2213 assert(isScalarIntegerType(DestTy));
2214 // Widen DestTy for truncation (see above note). We should only do this
2215 // when both Src and Dest are integer types.
John Porto008f4ce2015-12-24 13:22:18 -08002216 if (InstX86Base<Machine>::Traits::Is64Bit && DestTy == IceType_i64) {
John Porto1d235422015-08-12 12:37:53 -07002217 if (const auto *C64 = llvm::dyn_cast<ConstantInteger64>(Src)) {
John Porto008f4ce2015-12-24 13:22:18 -08002218 Func->getAssembler<typename InstX86Base<Machine>::Traits::Assembler>()
2219 ->movabs(InstX86Base<Machine>::Traits::getEncodedGPR(
2220 Dest->getRegNum()),
2221 C64->getValue());
2222 return;
John Porto1d235422015-08-12 12:37:53 -07002223 }
John Porto1d235422015-08-12 12:37:53 -07002224 }
John Porto921856d2015-07-07 11:56:26 -07002225 if (isScalarIntegerType(SrcTy)) {
Jim Stichnothc59288b2015-11-09 11:38:40 -08002226 SrcTy = DestTy;
John Porto921856d2015-07-07 11:56:26 -07002227 }
2228 emitIASRegOpTyGPR<Machine>(Func, DestTy, Dest, Src, GPRRegEmitter);
2229 return;
2230 }
2231 } else {
Andrew Scull57e12682015-09-16 11:30:19 -07002232 // Dest must be Stack and Src *could* be a register. Use Src's type to
2233 // decide on the emitters.
John Porto921856d2015-07-07 11:56:26 -07002234 typename InstX86Base<Machine>::Traits::Address StackAddr(
David Sehrb8e49c12015-11-12 14:41:22 -08002235 Target->stackVarToAsmOperand(Dest));
John Porto921856d2015-07-07 11:56:26 -07002236 if (isScalarFloatingType(SrcTy)) {
2237 // Src must be a register.
Jim Stichnoth5bff61c2015-10-28 09:26:00 -07002238 const auto *SrcVar = llvm::cast<Variable>(Src);
John Porto921856d2015-07-07 11:56:26 -07002239 assert(SrcVar->hasReg());
2240 typename InstX86Base<Machine>::Traits::Assembler *Asm =
2241 Func->getAssembler<
2242 typename InstX86Base<Machine>::Traits::Assembler>();
Jim Stichnoth5bff61c2015-10-28 09:26:00 -07002243 Asm->movss(SrcTy, StackAddr, InstX86Base<Machine>::Traits::getEncodedXmm(
2244 SrcVar->getRegNum()));
John Porto921856d2015-07-07 11:56:26 -07002245 return;
2246 } else {
2247 // Src can be a register or immediate.
2248 assert(isScalarIntegerType(SrcTy));
2249 emitIASAddrOpTyGPR<Machine>(Func, SrcTy, StackAddr, Src, GPRAddrEmitter);
2250 return;
2251 }
2252 return;
2253 }
2254}
2255
2256template <class Machine>
John Porto008f4ce2015-12-24 13:22:18 -08002257void InstX86Movd<Machine>::emit(const Cfg *Func) const {
2258 if (!BuildDefs::dump())
2259 return;
2260 assert(this->getSrcSize() == 1);
2261 Variable *Dest = this->getDest();
2262 Operand *Src = this->getSrc(0);
2263
2264 if (Dest->getType() == IceType_i64 || Src->getType() == IceType_i64) {
2265 assert(Dest->getType() == IceType_f64 || Src->getType() == IceType_f64);
2266 assert(Dest->getType() != Src->getType());
2267 Ostream &Str = Func->getContext()->getStrEmit();
2268 Str << "\t"
2269 "movq"
2270 "\t";
2271 Src->emit(Func);
2272 Str << ", ";
2273 Dest->emit(Func);
2274 return;
2275 }
2276
2277 InstX86BaseUnaryopXmm<Machine, InstX86Base<Machine>::Movd>::emit(Func);
2278}
2279
2280template <class Machine>
John Porto921856d2015-07-07 11:56:26 -07002281void InstX86Movd<Machine>::emitIAS(const Cfg *Func) const {
2282 typename InstX86Base<Machine>::Traits::Assembler *Asm =
2283 Func->getAssembler<typename InstX86Base<Machine>::Traits::Assembler>();
2284 assert(this->getSrcSize() == 1);
2285 const Variable *Dest = this->getDest();
David Sehrb8e49c12015-11-12 14:41:22 -08002286 auto *Target = InstX86Base<Machine>::getTarget(Func);
Andrew Scull57e12682015-09-16 11:30:19 -07002287 // For insert/extract element (one of Src/Dest is an Xmm vector and the other
2288 // is an int type).
John Porto3c275ce2015-12-22 08:14:00 -08002289 if (const auto *SrcVar = llvm::dyn_cast<Variable>(this->getSrc(0))) {
2290 if (SrcVar->getType() == IceType_i32 ||
2291 (InstX86Base<Machine>::Traits::Is64Bit &&
2292 SrcVar->getType() == IceType_i64)) {
2293 assert(isVectorType(Dest->getType()) ||
2294 (isScalarFloatingType(Dest->getType()) &&
2295 typeWidthInBytes(SrcVar->getType()) ==
2296 typeWidthInBytes(Dest->getType())));
2297 assert(Dest->hasReg());
2298 typename InstX86Base<Machine>::Traits::RegisterSet::XmmRegister DestReg =
2299 InstX86Base<Machine>::Traits::getEncodedXmm(Dest->getRegNum());
2300 if (SrcVar->hasReg()) {
2301 Asm->movd(
2302 SrcVar->getType(), DestReg,
2303 InstX86Base<Machine>::Traits::getEncodedGPR(SrcVar->getRegNum()));
2304 } else {
2305 typename InstX86Base<Machine>::Traits::Address StackAddr(
2306 Target->stackVarToAsmOperand(SrcVar));
2307 Asm->movd(SrcVar->getType(), DestReg, StackAddr);
2308 }
2309 } else {
2310 assert(isVectorType(SrcVar->getType()) ||
2311 (isScalarFloatingType(SrcVar->getType()) &&
2312 typeWidthInBytes(SrcVar->getType()) ==
2313 typeWidthInBytes(Dest->getType())));
2314 assert(SrcVar->hasReg());
2315 assert(Dest->getType() == IceType_i32 ||
2316 (InstX86Base<Machine>::Traits::Is64Bit &&
2317 Dest->getType() == IceType_i64));
2318 typename InstX86Base<Machine>::Traits::RegisterSet::XmmRegister SrcReg =
2319 InstX86Base<Machine>::Traits::getEncodedXmm(SrcVar->getRegNum());
2320 if (Dest->hasReg()) {
2321 Asm->movd(Dest->getType(), InstX86Base<Machine>::Traits::getEncodedGPR(
2322 Dest->getRegNum()),
2323 SrcReg);
2324 } else {
2325 typename InstX86Base<Machine>::Traits::Address StackAddr(
2326 Target->stackVarToAsmOperand(Dest));
2327 Asm->movd(Dest->getType(), StackAddr, SrcReg);
2328 }
2329 }
2330 } else {
John Porto921856d2015-07-07 11:56:26 -07002331 assert(Dest->hasReg());
2332 typename InstX86Base<Machine>::Traits::RegisterSet::XmmRegister DestReg =
Jim Stichnoth5bff61c2015-10-28 09:26:00 -07002333 InstX86Base<Machine>::Traits::getEncodedXmm(Dest->getRegNum());
John Porto3c275ce2015-12-22 08:14:00 -08002334 auto *Mem =
2335 llvm::cast<typename InstX86Base<Machine>::Traits::X86OperandMem>(
2336 this->getSrc(0));
2337 Asm->movd(Mem->getType(), DestReg, Mem->toAsmAddress(Asm, Target));
John Porto921856d2015-07-07 11:56:26 -07002338 }
2339}
2340
2341template <class Machine>
2342void InstX86Movp<Machine>::emit(const Cfg *Func) const {
2343 if (!BuildDefs::dump())
2344 return;
Andrew Scull57e12682015-09-16 11:30:19 -07002345 // TODO(wala,stichnot): movups works with all vector operands, but there
2346 // exist other instructions (movaps, movdqa, movdqu) that may perform better,
2347 // depending on the data type and alignment of the operands.
John Porto921856d2015-07-07 11:56:26 -07002348 Ostream &Str = Func->getContext()->getStrEmit();
2349 assert(this->getSrcSize() == 1);
Jim Stichnoth6106df82015-12-16 06:17:58 -08002350 Str << "\t"
2351 "movups\t";
John Porto921856d2015-07-07 11:56:26 -07002352 this->getSrc(0)->emit(Func);
2353 Str << ", ";
2354 this->getDest()->emit(Func);
2355}
2356
2357template <class Machine>
2358void InstX86Movp<Machine>::emitIAS(const Cfg *Func) const {
2359 assert(this->getSrcSize() == 1);
2360 assert(isVectorType(this->getDest()->getType()));
2361 const Variable *Dest = this->getDest();
2362 const Operand *Src = this->getSrc(0);
2363 static const typename InstX86Base<
2364 Machine>::Traits::Assembler::XmmEmitterMovOps Emitter = {
2365 &InstX86Base<Machine>::Traits::Assembler::movups,
2366 &InstX86Base<Machine>::Traits::Assembler::movups,
2367 &InstX86Base<Machine>::Traits::Assembler::movups};
2368 emitIASMovlikeXMM<Machine>(Func, Dest, Src, Emitter);
2369}
2370
2371template <class Machine>
2372void InstX86Movq<Machine>::emit(const Cfg *Func) const {
2373 if (!BuildDefs::dump())
2374 return;
2375 Ostream &Str = Func->getContext()->getStrEmit();
2376 assert(this->getSrcSize() == 1);
2377 assert(this->getDest()->getType() == IceType_i64 ||
2378 this->getDest()->getType() == IceType_f64);
Jim Stichnoth6106df82015-12-16 06:17:58 -08002379 Str << "\t"
John Porto008f4ce2015-12-24 13:22:18 -08002380 "movq"
2381 "\t";
John Porto921856d2015-07-07 11:56:26 -07002382 this->getSrc(0)->emit(Func);
2383 Str << ", ";
2384 this->getDest()->emit(Func);
2385}
2386
2387template <class Machine>
2388void InstX86Movq<Machine>::emitIAS(const Cfg *Func) const {
2389 assert(this->getSrcSize() == 1);
2390 assert(this->getDest()->getType() == IceType_i64 ||
2391 this->getDest()->getType() == IceType_f64);
2392 const Variable *Dest = this->getDest();
2393 const Operand *Src = this->getSrc(0);
2394 static const typename InstX86Base<
2395 Machine>::Traits::Assembler::XmmEmitterMovOps Emitter = {
2396 &InstX86Base<Machine>::Traits::Assembler::movq,
2397 &InstX86Base<Machine>::Traits::Assembler::movq,
2398 &InstX86Base<Machine>::Traits::Assembler::movq};
2399 emitIASMovlikeXMM<Machine>(Func, Dest, Src, Emitter);
2400}
2401
2402template <class Machine>
2403void InstX86MovssRegs<Machine>::emitIAS(const Cfg *Func) const {
Andrew Scull57e12682015-09-16 11:30:19 -07002404 // This is Binop variant is only intended to be used for reg-reg moves where
2405 // part of the Dest register is untouched.
John Porto921856d2015-07-07 11:56:26 -07002406 assert(this->getSrcSize() == 2);
2407 const Variable *Dest = this->getDest();
2408 assert(Dest == this->getSrc(0));
Jim Stichnoth5bff61c2015-10-28 09:26:00 -07002409 const auto *SrcVar = llvm::cast<Variable>(this->getSrc(1));
John Porto921856d2015-07-07 11:56:26 -07002410 assert(Dest->hasReg() && SrcVar->hasReg());
2411 typename InstX86Base<Machine>::Traits::Assembler *Asm =
2412 Func->getAssembler<typename InstX86Base<Machine>::Traits::Assembler>();
2413 Asm->movss(IceType_f32,
Jim Stichnoth5bff61c2015-10-28 09:26:00 -07002414 InstX86Base<Machine>::Traits::getEncodedXmm(Dest->getRegNum()),
2415 InstX86Base<Machine>::Traits::getEncodedXmm(SrcVar->getRegNum()));
John Porto921856d2015-07-07 11:56:26 -07002416}
2417
2418template <class Machine>
2419void InstX86Movsx<Machine>::emitIAS(const Cfg *Func) const {
2420 assert(this->getSrcSize() == 1);
2421 const Variable *Dest = this->getDest();
2422 const Operand *Src = this->getSrc(0);
Andrew Scull57e12682015-09-16 11:30:19 -07002423 // Dest must be a > 8-bit register, but Src can be 8-bit. In practice we just
2424 // use the full register for Dest to avoid having an OperandSizeOverride
2425 // prefix. It also allows us to only dispatch on SrcTy.
John Porto921856d2015-07-07 11:56:26 -07002426 Type SrcTy = Src->getType();
2427 assert(typeWidthInBytes(Dest->getType()) > 1);
2428 assert(typeWidthInBytes(Dest->getType()) > typeWidthInBytes(SrcTy));
2429 emitIASRegOpTyGPR<Machine, false, true>(Func, SrcTy, Dest, Src,
2430 this->Emitter);
2431}
2432
2433template <class Machine>
John Porto008f4ce2015-12-24 13:22:18 -08002434void InstX86Movzx<Machine>::emit(const Cfg *Func) const {
2435 if (!BuildDefs::dump())
2436 return;
2437 if (InstX86Base<Machine>::Traits::Is64Bit) {
2438 // There's no movzx %eXX, %rXX. To zero extend 32- to 64-bits, we emit a
2439 // mov %eXX, %eXX. The processor will still do a movzx[bw]q.
2440 assert(this->getSrcSize() == 1);
2441 const Operand *Src = this->getSrc(0);
2442 const Variable *Dest = this->Dest;
2443 if (Src->getType() == IceType_i32 && Dest->getType() == IceType_i64) {
2444 Ostream &Str = Func->getContext()->getStrEmit();
2445 Str << "\t"
2446 "mov"
2447 "\t";
2448 Src->emit(Func);
2449 Str << ", ";
2450 Dest->asType(IceType_i32, InstX86Base<Machine>::Traits::getGprForType(
2451 IceType_i32, Dest->getRegNum()))
2452 ->emit(Func);
2453 Str << " /* movzx */";
2454 return;
2455 }
2456 }
2457 InstX86BaseUnaryopGPR<Machine, InstX86Base<Machine>::Movzx>::emit(Func);
2458}
2459
2460template <class Machine>
John Porto921856d2015-07-07 11:56:26 -07002461void InstX86Movzx<Machine>::emitIAS(const Cfg *Func) const {
2462 assert(this->getSrcSize() == 1);
2463 const Variable *Dest = this->getDest();
2464 const Operand *Src = this->getSrc(0);
2465 Type SrcTy = Src->getType();
2466 assert(typeWidthInBytes(Dest->getType()) > 1);
2467 assert(typeWidthInBytes(Dest->getType()) > typeWidthInBytes(SrcTy));
2468 emitIASRegOpTyGPR<Machine, false, true>(Func, SrcTy, Dest, Src,
2469 this->Emitter);
2470}
2471
2472template <class Machine> void InstX86Nop<Machine>::emit(const Cfg *Func) const {
2473 if (!BuildDefs::dump())
2474 return;
2475 Ostream &Str = Func->getContext()->getStrEmit();
2476 // TODO: Emit the right code for each variant.
Jim Stichnoth6106df82015-12-16 06:17:58 -08002477 Str << "\t"
Jim Stichnoth751e27e2015-12-16 12:40:31 -08002478 "nop\t/* variant = " << Variant << " */";
John Porto921856d2015-07-07 11:56:26 -07002479}
2480
2481template <class Machine>
2482void InstX86Nop<Machine>::emitIAS(const Cfg *Func) const {
2483 typename InstX86Base<Machine>::Traits::Assembler *Asm =
2484 Func->getAssembler<typename InstX86Base<Machine>::Traits::Assembler>();
2485 // TODO: Emit the right code for the variant.
2486 Asm->nop();
2487}
2488
2489template <class Machine> void InstX86Nop<Machine>::dump(const Cfg *Func) const {
2490 if (!BuildDefs::dump())
2491 return;
2492 Ostream &Str = Func->getContext()->getStrDump();
2493 Str << "nop (variant = " << Variant << ")";
2494}
2495
2496template <class Machine> void InstX86Fld<Machine>::emit(const Cfg *Func) const {
2497 if (!BuildDefs::dump())
2498 return;
2499 Ostream &Str = Func->getContext()->getStrEmit();
2500 assert(this->getSrcSize() == 1);
2501 Type Ty = this->getSrc(0)->getType();
Jim Stichnoth5bff61c2015-10-28 09:26:00 -07002502 const auto *Var = llvm::dyn_cast<Variable>(this->getSrc(0));
John Porto921856d2015-07-07 11:56:26 -07002503 if (Var && Var->hasReg()) {
Andrew Scull57e12682015-09-16 11:30:19 -07002504 // This is a physical xmm register, so we need to spill it to a temporary
David Sehr0d9cf482015-11-16 17:00:38 -08002505 // stack slot. Function prolog emission guarantees that there is sufficient
2506 // space to do this.
Jim Stichnoth6106df82015-12-16 06:17:58 -08002507 Str << "\t"
2508 "mov" << InstX86Base<Machine>::Traits::TypeAttributes[Ty].SdSsString
2509 << "\t";
John Porto921856d2015-07-07 11:56:26 -07002510 Var->emit(Func);
Jim Stichnoth6106df82015-12-16 06:17:58 -08002511 Str << ", (%esp)\n"
2512 "\t"
2513 "fld" << this->getFldString(Ty) << "\t"
2514 "(%esp)";
John Porto921856d2015-07-07 11:56:26 -07002515 return;
2516 }
Jim Stichnoth6106df82015-12-16 06:17:58 -08002517 Str << "\t"
2518 "fld" << this->getFldString(Ty) << "\t";
John Porto921856d2015-07-07 11:56:26 -07002519 this->getSrc(0)->emit(Func);
2520}
2521
2522template <class Machine>
2523void InstX86Fld<Machine>::emitIAS(const Cfg *Func) const {
2524 typename InstX86Base<Machine>::Traits::Assembler *Asm =
2525 Func->getAssembler<typename InstX86Base<Machine>::Traits::Assembler>();
2526 assert(this->getSrcSize() == 1);
2527 const Operand *Src = this->getSrc(0);
David Sehrb8e49c12015-11-12 14:41:22 -08002528 auto *Target = InstX86Base<Machine>::getTarget(Func);
John Porto921856d2015-07-07 11:56:26 -07002529 Type Ty = Src->getType();
Jim Stichnoth5bff61c2015-10-28 09:26:00 -07002530 if (const auto *Var = llvm::dyn_cast<Variable>(Src)) {
John Porto921856d2015-07-07 11:56:26 -07002531 if (Var->hasReg()) {
Andrew Scull57e12682015-09-16 11:30:19 -07002532 // This is a physical xmm register, so we need to spill it to a temporary
David Sehr0d9cf482015-11-16 17:00:38 -08002533 // stack slot. Function prolog emission guarantees that there is
2534 // sufficient space to do this.
John Porto921856d2015-07-07 11:56:26 -07002535 typename InstX86Base<Machine>::Traits::Address StackSlot =
2536 typename InstX86Base<Machine>::Traits::Address(
David Sehraa0b1a12015-10-27 16:55:40 -07002537 InstX86Base<Machine>::Traits::RegisterSet::Encoded_Reg_esp, 0,
2538 AssemblerFixup::NoFixup);
John Porto921856d2015-07-07 11:56:26 -07002539 Asm->movss(Ty, StackSlot,
Jim Stichnoth5bff61c2015-10-28 09:26:00 -07002540 InstX86Base<Machine>::Traits::getEncodedXmm(Var->getRegNum()));
John Porto921856d2015-07-07 11:56:26 -07002541 Asm->fld(Ty, StackSlot);
John Porto921856d2015-07-07 11:56:26 -07002542 } else {
2543 typename InstX86Base<Machine>::Traits::Address StackAddr(
David Sehrb8e49c12015-11-12 14:41:22 -08002544 Target->stackVarToAsmOperand(Var));
John Porto921856d2015-07-07 11:56:26 -07002545 Asm->fld(Ty, StackAddr);
2546 }
Jim Stichnoth5bff61c2015-10-28 09:26:00 -07002547 } else if (const auto *Mem = llvm::dyn_cast<
John Porto921856d2015-07-07 11:56:26 -07002548 typename InstX86Base<Machine>::Traits::X86OperandMem>(Src)) {
2549 assert(Mem->getSegmentRegister() ==
2550 InstX86Base<Machine>::Traits::X86OperandMem::DefaultSegment);
David Sehr4318a412015-11-11 15:01:55 -08002551 Asm->fld(Ty, Mem->toAsmAddress(Asm, Target));
Jim Stichnoth5bff61c2015-10-28 09:26:00 -07002552 } else if (const auto *Imm = llvm::dyn_cast<Constant>(Src)) {
John Porto921856d2015-07-07 11:56:26 -07002553 Asm->fld(Ty, InstX86Base<Machine>::Traits::Address::ofConstPool(Asm, Imm));
2554 } else {
2555 llvm_unreachable("Unexpected operand type");
2556 }
2557}
2558
2559template <class Machine> void InstX86Fld<Machine>::dump(const Cfg *Func) const {
2560 if (!BuildDefs::dump())
2561 return;
2562 Ostream &Str = Func->getContext()->getStrDump();
2563 Str << "fld." << this->getSrc(0)->getType() << " ";
2564 this->dumpSources(Func);
2565}
2566
2567template <class Machine>
2568void InstX86Fstp<Machine>::emit(const Cfg *Func) const {
2569 if (!BuildDefs::dump())
2570 return;
2571 Ostream &Str = Func->getContext()->getStrEmit();
2572 assert(this->getSrcSize() == 0);
2573 // TODO(jvoung,stichnot): Utilize this by setting Dest to nullptr to
Andrew Scull57e12682015-09-16 11:30:19 -07002574 // "partially" delete the fstp if the Dest is unused. Even if Dest is unused,
2575 // the fstp should be kept for the SideEffects of popping the stack.
John Porto921856d2015-07-07 11:56:26 -07002576 if (!this->getDest()) {
Jim Stichnoth6106df82015-12-16 06:17:58 -08002577 Str << "\t"
2578 "fstp\t"
2579 "st(0)";
John Porto921856d2015-07-07 11:56:26 -07002580 return;
2581 }
2582 Type Ty = this->getDest()->getType();
John Porto921856d2015-07-07 11:56:26 -07002583 if (!this->getDest()->hasReg()) {
Jim Stichnoth6106df82015-12-16 06:17:58 -08002584 Str << "\t"
2585 "fstp" << this->getFldString(Ty) << "\t";
John Porto921856d2015-07-07 11:56:26 -07002586 this->getDest()->emit(Func);
2587 return;
2588 }
Andrew Scull57e12682015-09-16 11:30:19 -07002589 // Dest is a physical (xmm) register, so st(0) needs to go through memory.
David Sehr21fd1032015-11-13 16:32:37 -08002590 // Hack this by using caller-reserved memory at the top of stack, spilling
2591 // st(0) there, and loading it into the xmm register.
Jim Stichnoth6106df82015-12-16 06:17:58 -08002592 Str << "\t"
2593 "fstp" << this->getFldString(Ty) << "\t"
2594 "(%esp)\n";
2595 Str << "\t"
2596 "mov" << InstX86Base<Machine>::Traits::TypeAttributes[Ty].SdSsString
John Porto921856d2015-07-07 11:56:26 -07002597 << "\t"
Jim Stichnoth6106df82015-12-16 06:17:58 -08002598 "(%esp), ";
John Porto921856d2015-07-07 11:56:26 -07002599 this->getDest()->emit(Func);
John Porto921856d2015-07-07 11:56:26 -07002600}
2601
2602template <class Machine>
2603void InstX86Fstp<Machine>::emitIAS(const Cfg *Func) const {
2604 typename InstX86Base<Machine>::Traits::Assembler *Asm =
2605 Func->getAssembler<typename InstX86Base<Machine>::Traits::Assembler>();
2606 assert(this->getSrcSize() == 0);
2607 const Variable *Dest = this->getDest();
2608 // TODO(jvoung,stichnot): Utilize this by setting Dest to nullptr to
Andrew Scull57e12682015-09-16 11:30:19 -07002609 // "partially" delete the fstp if the Dest is unused. Even if Dest is unused,
2610 // the fstp should be kept for the SideEffects of popping the stack.
John Porto921856d2015-07-07 11:56:26 -07002611 if (!Dest) {
2612 Asm->fstp(InstX86Base<Machine>::Traits::RegisterSet::getEncodedSTReg(0));
2613 return;
2614 }
David Sehrb8e49c12015-11-12 14:41:22 -08002615 auto *Target = InstX86Base<Machine>::getTarget(Func);
John Porto921856d2015-07-07 11:56:26 -07002616 Type Ty = Dest->getType();
2617 if (!Dest->hasReg()) {
2618 typename InstX86Base<Machine>::Traits::Address StackAddr(
David Sehrb8e49c12015-11-12 14:41:22 -08002619 Target->stackVarToAsmOperand(Dest));
John Porto921856d2015-07-07 11:56:26 -07002620 Asm->fstp(Ty, StackAddr);
2621 } else {
Andrew Scull57e12682015-09-16 11:30:19 -07002622 // Dest is a physical (xmm) register, so st(0) needs to go through memory.
David Sehr21fd1032015-11-13 16:32:37 -08002623 // Hack this by using caller-reserved memory at the top of stack, spilling
2624 // st(0) there, and loading it into the xmm register.
John Porto921856d2015-07-07 11:56:26 -07002625 typename InstX86Base<Machine>::Traits::Address StackSlot =
2626 typename InstX86Base<Machine>::Traits::Address(
David Sehraa0b1a12015-10-27 16:55:40 -07002627 InstX86Base<Machine>::Traits::RegisterSet::Encoded_Reg_esp, 0,
2628 AssemblerFixup::NoFixup);
John Porto921856d2015-07-07 11:56:26 -07002629 Asm->fstp(Ty, StackSlot);
Jim Stichnoth5bff61c2015-10-28 09:26:00 -07002630 Asm->movss(Ty,
2631 InstX86Base<Machine>::Traits::getEncodedXmm(Dest->getRegNum()),
John Porto921856d2015-07-07 11:56:26 -07002632 StackSlot);
John Porto921856d2015-07-07 11:56:26 -07002633 }
2634}
2635
2636template <class Machine>
2637void InstX86Fstp<Machine>::dump(const Cfg *Func) const {
2638 if (!BuildDefs::dump())
2639 return;
2640 Ostream &Str = Func->getContext()->getStrDump();
2641 this->dumpDest(Func);
2642 Str << " = fstp." << this->getDest()->getType() << ", st(0)";
2643}
2644
2645template <class Machine>
John Porto921856d2015-07-07 11:56:26 -07002646void InstX86Pextr<Machine>::emit(const Cfg *Func) const {
2647 if (!BuildDefs::dump())
2648 return;
2649 Ostream &Str = Func->getContext()->getStrEmit();
2650 assert(this->getSrcSize() == 2);
2651 // pextrb and pextrd are SSE4.1 instructions.
John Porto921856d2015-07-07 11:56:26 -07002652 Str << "\t" << this->Opcode
2653 << InstX86Base<Machine>::Traits::TypeAttributes[this->getSrc(0)
2654 ->getType()]
2655 .PackString << "\t";
2656 this->getSrc(1)->emit(Func);
2657 Str << ", ";
2658 this->getSrc(0)->emit(Func);
2659 Str << ", ";
2660 Variable *Dest = this->getDest();
Andrew Scull57e12682015-09-16 11:30:19 -07002661 // pextrw must take a register dest. There is an SSE4.1 version that takes a
2662 // memory dest, but we aren't using it. For uniformity, just restrict them
2663 // all to have a register dest for now.
John Porto921856d2015-07-07 11:56:26 -07002664 assert(Dest->hasReg());
Jim Stichnoth5bff61c2015-10-28 09:26:00 -07002665 Dest->asType(IceType_i32, Dest->getRegNum())->emit(Func);
John Porto921856d2015-07-07 11:56:26 -07002666}
2667
2668template <class Machine>
2669void InstX86Pextr<Machine>::emitIAS(const Cfg *Func) const {
2670 assert(this->getSrcSize() == 2);
2671 // pextrb and pextrd are SSE4.1 instructions.
2672 const Variable *Dest = this->getDest();
Jim Stichnoth5bff61c2015-10-28 09:26:00 -07002673 Type DispatchTy = InstX86Base<Machine>::Traits::getInVectorElementType(
2674 this->getSrc(0)->getType());
Andrew Scull57e12682015-09-16 11:30:19 -07002675 // pextrw must take a register dest. There is an SSE4.1 version that takes a
2676 // memory dest, but we aren't using it. For uniformity, just restrict them
2677 // all to have a register dest for now.
John Porto921856d2015-07-07 11:56:26 -07002678 assert(Dest->hasReg());
2679 // pextrw's Src(0) must be a register (both SSE4.1 and SSE2).
2680 assert(llvm::cast<Variable>(this->getSrc(0))->hasReg());
2681 static const typename InstX86Base<Machine>::Traits::Assembler::
2682 template ThreeOpImmEmitter<
2683 typename InstX86Base<Machine>::Traits::RegisterSet::GPRRegister,
2684 typename InstX86Base<Machine>::Traits::RegisterSet::XmmRegister>
2685 Emitter = {&InstX86Base<Machine>::Traits::Assembler::pextr, nullptr};
2686 emitIASThreeOpImmOps<
2687 Machine, typename InstX86Base<Machine>::Traits::RegisterSet::GPRRegister,
2688 typename InstX86Base<Machine>::Traits::RegisterSet::XmmRegister,
Jim Stichnoth5bff61c2015-10-28 09:26:00 -07002689 InstX86Base<Machine>::Traits::getEncodedGPR,
2690 InstX86Base<Machine>::Traits::getEncodedXmm>(
John Porto921856d2015-07-07 11:56:26 -07002691 Func, DispatchTy, Dest, this->getSrc(0), this->getSrc(1), Emitter);
2692}
2693
2694template <class Machine>
2695void InstX86Pinsr<Machine>::emit(const Cfg *Func) const {
2696 if (!BuildDefs::dump())
2697 return;
2698 Ostream &Str = Func->getContext()->getStrEmit();
2699 assert(this->getSrcSize() == 3);
John Porto921856d2015-07-07 11:56:26 -07002700 Str << "\t" << this->Opcode
2701 << InstX86Base<
2702 Machine>::Traits::TypeAttributes[this->getDest()->getType()]
2703 .PackString << "\t";
2704 this->getSrc(2)->emit(Func);
2705 Str << ", ";
2706 Operand *Src1 = this->getSrc(1);
Jim Stichnoth5bff61c2015-10-28 09:26:00 -07002707 if (const auto *Src1Var = llvm::dyn_cast<Variable>(Src1)) {
John Porto921856d2015-07-07 11:56:26 -07002708 // If src1 is a register, it should always be r32.
2709 if (Src1Var->hasReg()) {
Jim Stichnoth5bff61c2015-10-28 09:26:00 -07002710 int32_t NewRegNum =
2711 InstX86Base<Machine>::Traits::getBaseReg(Src1Var->getRegNum());
2712 const Variable *NewSrc = Src1Var->asType(IceType_i32, NewRegNum);
2713 NewSrc->emit(Func);
John Porto921856d2015-07-07 11:56:26 -07002714 } else {
2715 Src1Var->emit(Func);
2716 }
2717 } else {
2718 Src1->emit(Func);
2719 }
2720 Str << ", ";
2721 this->getDest()->emit(Func);
2722}
2723
2724template <class Machine>
2725void InstX86Pinsr<Machine>::emitIAS(const Cfg *Func) const {
2726 assert(this->getSrcSize() == 3);
2727 assert(this->getDest() == this->getSrc(0));
2728 // pinsrb and pinsrd are SSE4.1 instructions.
2729 const Operand *Src0 = this->getSrc(1);
2730 Type DispatchTy = Src0->getType();
Andrew Scull57e12682015-09-16 11:30:19 -07002731 // If src1 is a register, it should always be r32 (this should fall out from
2732 // the encodings for ByteRegs overlapping the encodings for r32), but we have
Jim Stichnoth5bff61c2015-10-28 09:26:00 -07002733 // to make sure the register allocator didn't choose an 8-bit high register
2734 // like "ah".
2735 if (BuildDefs::asserts()) {
2736 if (auto *Src0Var = llvm::dyn_cast<Variable>(Src0)) {
2737 if (Src0Var->hasReg()) {
2738 int32_t RegNum = Src0Var->getRegNum();
2739 int32_t BaseRegNum = InstX86Base<Machine>::Traits::getBaseReg(RegNum);
2740 (void)BaseRegNum;
2741 assert(InstX86Base<Machine>::Traits::getEncodedGPR(RegNum) ==
2742 InstX86Base<Machine>::Traits::getEncodedGPR(BaseRegNum));
2743 }
2744 }
2745 }
John Porto921856d2015-07-07 11:56:26 -07002746 static const typename InstX86Base<Machine>::Traits::Assembler::
2747 template ThreeOpImmEmitter<
2748 typename InstX86Base<Machine>::Traits::RegisterSet::XmmRegister,
2749 typename InstX86Base<Machine>::Traits::RegisterSet::GPRRegister>
2750 Emitter = {&InstX86Base<Machine>::Traits::Assembler::pinsr,
2751 &InstX86Base<Machine>::Traits::Assembler::pinsr};
2752 emitIASThreeOpImmOps<
2753 Machine, typename InstX86Base<Machine>::Traits::RegisterSet::XmmRegister,
2754 typename InstX86Base<Machine>::Traits::RegisterSet::GPRRegister,
Jim Stichnoth5bff61c2015-10-28 09:26:00 -07002755 InstX86Base<Machine>::Traits::getEncodedXmm,
2756 InstX86Base<Machine>::Traits::getEncodedGPR>(
John Porto921856d2015-07-07 11:56:26 -07002757 Func, DispatchTy, this->getDest(), Src0, this->getSrc(2), Emitter);
2758}
2759
2760template <class Machine>
2761void InstX86Pshufd<Machine>::emitIAS(const Cfg *Func) const {
2762 assert(this->getSrcSize() == 2);
2763 const Variable *Dest = this->getDest();
2764 Type Ty = Dest->getType();
2765 static const typename InstX86Base<Machine>::Traits::Assembler::
2766 template ThreeOpImmEmitter<
2767 typename InstX86Base<Machine>::Traits::RegisterSet::XmmRegister,
2768 typename InstX86Base<Machine>::Traits::RegisterSet::XmmRegister>
2769 Emitter = {&InstX86Base<Machine>::Traits::Assembler::pshufd,
2770 &InstX86Base<Machine>::Traits::Assembler::pshufd};
2771 emitIASThreeOpImmOps<
2772 Machine, typename InstX86Base<Machine>::Traits::RegisterSet::XmmRegister,
2773 typename InstX86Base<Machine>::Traits::RegisterSet::XmmRegister,
Jim Stichnoth5bff61c2015-10-28 09:26:00 -07002774 InstX86Base<Machine>::Traits::getEncodedXmm,
2775 InstX86Base<Machine>::Traits::getEncodedXmm>(
John Porto921856d2015-07-07 11:56:26 -07002776 Func, Ty, Dest, this->getSrc(0), this->getSrc(1), Emitter);
2777}
2778
2779template <class Machine>
2780void InstX86Shufps<Machine>::emitIAS(const Cfg *Func) const {
2781 assert(this->getSrcSize() == 3);
2782 const Variable *Dest = this->getDest();
2783 assert(Dest == this->getSrc(0));
2784 Type Ty = Dest->getType();
2785 static const typename InstX86Base<Machine>::Traits::Assembler::
2786 template ThreeOpImmEmitter<
2787 typename InstX86Base<Machine>::Traits::RegisterSet::XmmRegister,
2788 typename InstX86Base<Machine>::Traits::RegisterSet::XmmRegister>
2789 Emitter = {&InstX86Base<Machine>::Traits::Assembler::shufps,
2790 &InstX86Base<Machine>::Traits::Assembler::shufps};
2791 emitIASThreeOpImmOps<
2792 Machine, typename InstX86Base<Machine>::Traits::RegisterSet::XmmRegister,
2793 typename InstX86Base<Machine>::Traits::RegisterSet::XmmRegister,
Jim Stichnoth5bff61c2015-10-28 09:26:00 -07002794 InstX86Base<Machine>::Traits::getEncodedXmm,
2795 InstX86Base<Machine>::Traits::getEncodedXmm>(
John Porto921856d2015-07-07 11:56:26 -07002796 Func, Ty, Dest, this->getSrc(1), this->getSrc(2), Emitter);
2797}
2798
2799template <class Machine> void InstX86Pop<Machine>::emit(const Cfg *Func) const {
2800 if (!BuildDefs::dump())
2801 return;
2802 Ostream &Str = Func->getContext()->getStrEmit();
2803 assert(this->getSrcSize() == 0);
Jim Stichnoth6106df82015-12-16 06:17:58 -08002804 Str << "\t"
2805 "pop\t";
John Porto921856d2015-07-07 11:56:26 -07002806 this->getDest()->emit(Func);
2807}
2808
2809template <class Machine>
2810void InstX86Pop<Machine>::emitIAS(const Cfg *Func) const {
2811 assert(this->getSrcSize() == 0);
2812 typename InstX86Base<Machine>::Traits::Assembler *Asm =
2813 Func->getAssembler<typename InstX86Base<Machine>::Traits::Assembler>();
2814 if (this->getDest()->hasReg()) {
Jim Stichnoth5bff61c2015-10-28 09:26:00 -07002815 Asm->popl(InstX86Base<Machine>::Traits::getEncodedGPR(
John Porto921856d2015-07-07 11:56:26 -07002816 this->getDest()->getRegNum()));
2817 } else {
David Sehrb8e49c12015-11-12 14:41:22 -08002818 auto *Target = InstX86Base<Machine>::getTarget(Func);
2819 Asm->popl(Target->stackVarToAsmOperand(this->getDest()));
John Porto921856d2015-07-07 11:56:26 -07002820 }
2821}
2822
2823template <class Machine> void InstX86Pop<Machine>::dump(const Cfg *Func) const {
2824 if (!BuildDefs::dump())
2825 return;
2826 Ostream &Str = Func->getContext()->getStrDump();
2827 this->dumpDest(Func);
2828 Str << " = pop." << this->getDest()->getType() << " ";
2829}
2830
2831template <class Machine>
John Porto921856d2015-07-07 11:56:26 -07002832void InstX86Push<Machine>::emit(const Cfg *Func) const {
2833 if (!BuildDefs::dump())
2834 return;
2835 Ostream &Str = Func->getContext()->getStrEmit();
2836 assert(this->getSrcSize() == 1);
2837 // Push is currently only used for saving GPRs.
Jim Stichnoth5bff61c2015-10-28 09:26:00 -07002838 const auto *Var = llvm::cast<Variable>(this->getSrc(0));
John Porto921856d2015-07-07 11:56:26 -07002839 assert(Var->hasReg());
Jim Stichnoth6106df82015-12-16 06:17:58 -08002840 Str << "\t"
2841 "push\t";
John Porto921856d2015-07-07 11:56:26 -07002842 Var->emit(Func);
2843}
2844
2845template <class Machine>
2846void InstX86Push<Machine>::emitIAS(const Cfg *Func) const {
2847 assert(this->getSrcSize() == 1);
2848 // Push is currently only used for saving GPRs.
Jim Stichnoth5bff61c2015-10-28 09:26:00 -07002849 const auto *Var = llvm::cast<Variable>(this->getSrc(0));
John Porto921856d2015-07-07 11:56:26 -07002850 assert(Var->hasReg());
2851 typename InstX86Base<Machine>::Traits::Assembler *Asm =
2852 Func->getAssembler<typename InstX86Base<Machine>::Traits::Assembler>();
Jim Stichnoth5bff61c2015-10-28 09:26:00 -07002853 Asm->pushl(InstX86Base<Machine>::Traits::getEncodedGPR(Var->getRegNum()));
John Porto921856d2015-07-07 11:56:26 -07002854}
2855
2856template <class Machine>
2857void InstX86Push<Machine>::dump(const Cfg *Func) const {
2858 if (!BuildDefs::dump())
2859 return;
2860 Ostream &Str = Func->getContext()->getStrDump();
2861 Str << "push." << this->getSrc(0)->getType() << " ";
2862 this->dumpSources(Func);
2863}
2864
John Porto921856d2015-07-07 11:56:26 -07002865template <class Machine> void InstX86Ret<Machine>::emit(const Cfg *Func) const {
2866 if (!BuildDefs::dump())
2867 return;
2868 Ostream &Str = Func->getContext()->getStrEmit();
Jim Stichnoth6106df82015-12-16 06:17:58 -08002869 Str << "\t"
2870 "ret";
John Porto921856d2015-07-07 11:56:26 -07002871}
2872
2873template <class Machine>
2874void InstX86Ret<Machine>::emitIAS(const Cfg *Func) const {
2875 typename InstX86Base<Machine>::Traits::Assembler *Asm =
2876 Func->getAssembler<typename InstX86Base<Machine>::Traits::Assembler>();
2877 Asm->ret();
2878}
2879
2880template <class Machine> void InstX86Ret<Machine>::dump(const Cfg *Func) const {
2881 if (!BuildDefs::dump())
2882 return;
2883 Ostream &Str = Func->getContext()->getStrDump();
2884 Type Ty =
2885 (this->getSrcSize() == 0 ? IceType_void : this->getSrc(0)->getType());
2886 Str << "ret." << Ty << " ";
2887 this->dumpSources(Func);
2888}
2889
2890template <class Machine>
2891void InstX86Setcc<Machine>::emit(const Cfg *Func) const {
2892 if (!BuildDefs::dump())
2893 return;
2894 Ostream &Str = Func->getContext()->getStrEmit();
Jim Stichnoth6106df82015-12-16 06:17:58 -08002895 Str << "\t"
2896 "set"
John Porto921856d2015-07-07 11:56:26 -07002897 << InstX86Base<Machine>::Traits::InstBrAttributes[Condition].DisplayString
2898 << "\t";
2899 this->Dest->emit(Func);
2900}
2901
2902template <class Machine>
2903void InstX86Setcc<Machine>::emitIAS(const Cfg *Func) const {
2904 assert(Condition != InstX86Base<Machine>::Traits::Cond::Br_None);
2905 assert(this->getDest()->getType() == IceType_i1);
2906 assert(this->getSrcSize() == 0);
2907 typename InstX86Base<Machine>::Traits::Assembler *Asm =
2908 Func->getAssembler<typename InstX86Base<Machine>::Traits::Assembler>();
David Sehrb8e49c12015-11-12 14:41:22 -08002909 auto *Target = InstX86Base<Machine>::getTarget(Func);
John Porto921856d2015-07-07 11:56:26 -07002910 if (this->getDest()->hasReg())
Jim Stichnoth5bff61c2015-10-28 09:26:00 -07002911 Asm->setcc(Condition, InstX86Base<Machine>::Traits::getEncodedByteReg(
2912 this->getDest()->getRegNum()));
John Porto921856d2015-07-07 11:56:26 -07002913 else
David Sehrb8e49c12015-11-12 14:41:22 -08002914 Asm->setcc(Condition, Target->stackVarToAsmOperand(this->getDest()));
John Porto921856d2015-07-07 11:56:26 -07002915 return;
2916}
2917
2918template <class Machine>
2919void InstX86Setcc<Machine>::dump(const Cfg *Func) const {
2920 if (!BuildDefs::dump())
2921 return;
2922 Ostream &Str = Func->getContext()->getStrDump();
2923 Str << "setcc."
2924 << InstX86Base<Machine>::Traits::InstBrAttributes[Condition].DisplayString
2925 << " ";
2926 this->dumpDest(Func);
2927}
2928
2929template <class Machine>
2930void InstX86Xadd<Machine>::emit(const Cfg *Func) const {
2931 if (!BuildDefs::dump())
2932 return;
2933 Ostream &Str = Func->getContext()->getStrEmit();
2934 if (this->Locked) {
Jim Stichnoth6106df82015-12-16 06:17:58 -08002935 Str << "\t"
2936 "lock";
John Porto921856d2015-07-07 11:56:26 -07002937 }
Jim Stichnoth6106df82015-12-16 06:17:58 -08002938 Str << "\t"
2939 "xadd" << this->getWidthString(this->getSrc(0)->getType()) << "\t";
John Porto921856d2015-07-07 11:56:26 -07002940 this->getSrc(1)->emit(Func);
2941 Str << ", ";
2942 this->getSrc(0)->emit(Func);
2943}
2944
2945template <class Machine>
2946void InstX86Xadd<Machine>::emitIAS(const Cfg *Func) const {
2947 assert(this->getSrcSize() == 2);
2948 typename InstX86Base<Machine>::Traits::Assembler *Asm =
2949 Func->getAssembler<typename InstX86Base<Machine>::Traits::Assembler>();
2950 Type Ty = this->getSrc(0)->getType();
2951 const auto Mem =
2952 llvm::cast<typename InstX86Base<Machine>::Traits::X86OperandMem>(
2953 this->getSrc(0));
2954 assert(Mem->getSegmentRegister() ==
2955 InstX86Base<Machine>::Traits::X86OperandMem::DefaultSegment);
David Sehrb8e49c12015-11-12 14:41:22 -08002956 auto *Target = InstX86Base<Machine>::getTarget(Func);
John Porto921856d2015-07-07 11:56:26 -07002957 const typename InstX86Base<Machine>::Traits::Address Addr =
David Sehr4318a412015-11-11 15:01:55 -08002958 Mem->toAsmAddress(Asm, Target);
Jim Stichnoth5bff61c2015-10-28 09:26:00 -07002959 const auto *VarReg = llvm::cast<Variable>(this->getSrc(1));
John Porto921856d2015-07-07 11:56:26 -07002960 assert(VarReg->hasReg());
2961 const typename InstX86Base<Machine>::Traits::RegisterSet::GPRRegister Reg =
Jim Stichnoth5bff61c2015-10-28 09:26:00 -07002962 InstX86Base<Machine>::Traits::getEncodedGPR(VarReg->getRegNum());
John Porto921856d2015-07-07 11:56:26 -07002963 Asm->xadd(Ty, Addr, Reg, this->Locked);
2964}
2965
2966template <class Machine>
2967void InstX86Xadd<Machine>::dump(const Cfg *Func) const {
2968 if (!BuildDefs::dump())
2969 return;
2970 Ostream &Str = Func->getContext()->getStrDump();
2971 if (this->Locked) {
2972 Str << "lock ";
2973 }
2974 Type Ty = this->getSrc(0)->getType();
2975 Str << "xadd." << Ty << " ";
2976 this->dumpSources(Func);
2977}
2978
2979template <class Machine>
2980void InstX86Xchg<Machine>::emit(const Cfg *Func) const {
2981 if (!BuildDefs::dump())
2982 return;
2983 Ostream &Str = Func->getContext()->getStrEmit();
Jim Stichnoth6106df82015-12-16 06:17:58 -08002984 Str << "\t"
2985 "xchg" << this->getWidthString(this->getSrc(0)->getType()) << "\t";
John Porto921856d2015-07-07 11:56:26 -07002986 this->getSrc(1)->emit(Func);
2987 Str << ", ";
2988 this->getSrc(0)->emit(Func);
2989}
2990
2991template <class Machine>
2992void InstX86Xchg<Machine>::emitIAS(const Cfg *Func) const {
2993 assert(this->getSrcSize() == 2);
2994 typename InstX86Base<Machine>::Traits::Assembler *Asm =
2995 Func->getAssembler<typename InstX86Base<Machine>::Traits::Assembler>();
2996 Type Ty = this->getSrc(0)->getType();
Andrew Scullcfa628b2015-08-20 14:23:05 -07002997 const auto *VarReg1 = llvm::cast<Variable>(this->getSrc(1));
2998 assert(VarReg1->hasReg());
2999 const typename InstX86Base<Machine>::Traits::RegisterSet::GPRRegister Reg1 =
Jim Stichnoth5bff61c2015-10-28 09:26:00 -07003000 InstX86Base<Machine>::Traits::getEncodedGPR(VarReg1->getRegNum());
Andrew Scullcfa628b2015-08-20 14:23:05 -07003001
3002 if (const auto *VarReg0 = llvm::dyn_cast<Variable>(this->getSrc(0))) {
3003 assert(VarReg0->hasReg());
3004 const typename InstX86Base<Machine>::Traits::RegisterSet::GPRRegister Reg0 =
Jim Stichnoth5bff61c2015-10-28 09:26:00 -07003005 InstX86Base<Machine>::Traits::getEncodedGPR(VarReg0->getRegNum());
Andrew Scullcfa628b2015-08-20 14:23:05 -07003006 Asm->xchg(Ty, Reg0, Reg1);
3007 return;
3008 }
3009
3010 const auto *Mem =
John Porto921856d2015-07-07 11:56:26 -07003011 llvm::cast<typename InstX86Base<Machine>::Traits::X86OperandMem>(
3012 this->getSrc(0));
3013 assert(Mem->getSegmentRegister() ==
3014 InstX86Base<Machine>::Traits::X86OperandMem::DefaultSegment);
David Sehrb8e49c12015-11-12 14:41:22 -08003015 auto *Target = InstX86Base<Machine>::getTarget(Func);
John Porto921856d2015-07-07 11:56:26 -07003016 const typename InstX86Base<Machine>::Traits::Address Addr =
David Sehr4318a412015-11-11 15:01:55 -08003017 Mem->toAsmAddress(Asm, Target);
Andrew Scullcfa628b2015-08-20 14:23:05 -07003018 Asm->xchg(Ty, Addr, Reg1);
John Porto921856d2015-07-07 11:56:26 -07003019}
3020
3021template <class Machine>
3022void InstX86Xchg<Machine>::dump(const Cfg *Func) const {
3023 if (!BuildDefs::dump())
3024 return;
3025 Ostream &Str = Func->getContext()->getStrDump();
3026 Type Ty = this->getSrc(0)->getType();
3027 Str << "xchg." << Ty << " ";
3028 this->dumpSources(Func);
3029}
3030
Andrew Scull2c862522015-08-06 08:41:53 -07003031template <class Machine>
3032void InstX86IacaStart<Machine>::emit(const Cfg *Func) const {
3033 if (!BuildDefs::dump())
3034 return;
3035 Ostream &Str = Func->getContext()->getStrEmit();
3036 Str << "\t# IACA_START\n"
Jim Stichnoth6106df82015-12-16 06:17:58 -08003037 "\t.byte 0x0F, 0x0B\n"
3038 "\t"
3039 "movl\t$111, %ebx\n"
3040 "\t.byte 0x64, 0x67, 0x90";
Andrew Scull2c862522015-08-06 08:41:53 -07003041}
3042
3043template <class Machine>
3044void InstX86IacaStart<Machine>::emitIAS(const Cfg *Func) const {
3045 typename InstX86Base<Machine>::Traits::Assembler *Asm =
3046 Func->getAssembler<typename InstX86Base<Machine>::Traits::Assembler>();
3047 Asm->iaca_start();
3048}
3049
3050template <class Machine>
3051void InstX86IacaStart<Machine>::dump(const Cfg *Func) const {
3052 if (!BuildDefs::dump())
3053 return;
3054 Ostream &Str = Func->getContext()->getStrDump();
3055 Str << "IACA_START";
3056}
3057
3058template <class Machine>
3059void InstX86IacaEnd<Machine>::emit(const Cfg *Func) const {
3060 if (!BuildDefs::dump())
3061 return;
3062 Ostream &Str = Func->getContext()->getStrEmit();
3063 Str << "\t# IACA_END\n"
Jim Stichnoth6106df82015-12-16 06:17:58 -08003064 "\t"
3065 "movl\t$222, %ebx\n"
3066 "\t.byte 0x64, 0x67, 0x90\n"
3067 "\t.byte 0x0F, 0x0B";
Andrew Scull2c862522015-08-06 08:41:53 -07003068}
3069
3070template <class Machine>
3071void InstX86IacaEnd<Machine>::emitIAS(const Cfg *Func) const {
3072 typename InstX86Base<Machine>::Traits::Assembler *Asm =
3073 Func->getAssembler<typename InstX86Base<Machine>::Traits::Assembler>();
3074 Asm->iaca_end();
3075}
3076
3077template <class Machine>
3078void InstX86IacaEnd<Machine>::dump(const Cfg *Func) const {
3079 if (!BuildDefs::dump())
3080 return;
3081 Ostream &Str = Func->getContext()->getStrDump();
3082 Str << "IACA_END";
3083}
3084
John Porto921856d2015-07-07 11:56:26 -07003085} // end of namespace X86Internal
3086
3087} // end of namespace Ice
3088
3089#endif // SUBZERO_SRC_ICEINSTX86BASEIMPL_H