blob: 6a087e8f066db3977790f21d041730d49e275bcc [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"
Jim Stichnoth8ff4b282016-01-04 15:39:06 -080027#include "IceTargetLoweringX86Base.h"
John Porto921856d2015-07-07 11:56:26 -070028
29namespace Ice {
30
John Porto4a566862016-01-04 09:33:41 -080031namespace X86NAMESPACE {
John Porto921856d2015-07-07 11:56:26 -070032
John Porto4a566862016-01-04 09:33:41 -080033template <typename TraitsType>
34const char *InstImpl<TraitsType>::InstX86Base::getWidthString(Type Ty) {
John Porto921856d2015-07-07 11:56:26 -070035 return Traits::TypeAttributes[Ty].WidthString;
36}
37
John Porto4a566862016-01-04 09:33:41 -080038template <typename TraitsType>
39const char *InstImpl<TraitsType>::InstX86Base::getFldString(Type Ty) {
John Porto921856d2015-07-07 11:56:26 -070040 return Traits::TypeAttributes[Ty].FldString;
41}
42
John Porto4a566862016-01-04 09:33:41 -080043template <typename TraitsType>
44typename InstImpl<TraitsType>::Cond::BrCond
45InstImpl<TraitsType>::InstX86Base::getOppositeCondition(BrCond Cond) {
John Porto921856d2015-07-07 11:56:26 -070046 return Traits::InstBrAttributes[Cond].Opposite;
47}
48
John Porto4a566862016-01-04 09:33:41 -080049template <typename TraitsType>
50InstImpl<TraitsType>::InstX86FakeRMW::InstX86FakeRMW(Cfg *Func, Operand *Data,
51 Operand *Addr,
52 InstArithmetic::OpKind Op,
53 Variable *Beacon)
54 : InstX86Base(Func, InstX86Base::FakeRMW, 3, nullptr), Op(Op) {
John Porto921856d2015-07-07 11:56:26 -070055 this->addSource(Data);
56 this->addSource(Addr);
57 this->addSource(Beacon);
58}
59
John Porto4a566862016-01-04 09:33:41 -080060template <typename TraitsType>
Jim Stichnoth8ff4b282016-01-04 15:39:06 -080061InstImpl<TraitsType>::InstX86GetIP::InstX86GetIP(Cfg *Func, Variable *Dest)
62 : InstX86Base(Func, InstX86Base::GetIP, 0, Dest) {}
63
64template <typename TraitsType>
John Porto4a566862016-01-04 09:33:41 -080065InstImpl<TraitsType>::InstX86Mul::InstX86Mul(Cfg *Func, Variable *Dest,
66 Variable *Source1,
67 Operand *Source2)
68 : InstX86Base(Func, InstX86Base::Mul, 2, Dest) {
John Porto921856d2015-07-07 11:56:26 -070069 this->addSource(Source1);
70 this->addSource(Source2);
71}
72
John Porto4a566862016-01-04 09:33:41 -080073template <typename TraitsType>
74InstImpl<TraitsType>::InstX86Shld::InstX86Shld(Cfg *Func, Variable *Dest,
75 Variable *Source1,
76 Operand *Source2)
77 : InstX86Base(Func, InstX86Base::Shld, 3, Dest) {
John Porto921856d2015-07-07 11:56:26 -070078 this->addSource(Dest);
79 this->addSource(Source1);
80 this->addSource(Source2);
81}
82
John Porto4a566862016-01-04 09:33:41 -080083template <typename TraitsType>
84InstImpl<TraitsType>::InstX86Shrd::InstX86Shrd(Cfg *Func, Variable *Dest,
85 Variable *Source1,
86 Operand *Source2)
87 : InstX86Base(Func, InstX86Base::Shrd, 3, Dest) {
John Porto921856d2015-07-07 11:56:26 -070088 this->addSource(Dest);
89 this->addSource(Source1);
90 this->addSource(Source2);
91}
92
John Porto4a566862016-01-04 09:33:41 -080093template <typename TraitsType>
94InstImpl<TraitsType>::InstX86Label::InstX86Label(Cfg *Func,
95 TargetLowering *Target)
96 : InstX86Base(Func, InstX86Base::Label, 0, nullptr),
John Porto921856d2015-07-07 11:56:26 -070097 Number(Target->makeNextLabelNumber()) {}
98
John Porto4a566862016-01-04 09:33:41 -080099template <typename TraitsType>
100IceString InstImpl<TraitsType>::InstX86Label::getName(const Cfg *Func) const {
John Porto921856d2015-07-07 11:56:26 -0700101 return ".L" + Func->getFunctionName() + "$local$__" + std::to_string(Number);
102}
103
John Porto4a566862016-01-04 09:33:41 -0800104template <typename TraitsType>
105InstImpl<TraitsType>::InstX86Br::InstX86Br(
John Porto921856d2015-07-07 11:56:26 -0700106 Cfg *Func, const CfgNode *TargetTrue, const CfgNode *TargetFalse,
John Porto4a566862016-01-04 09:33:41 -0800107 const InstImpl<TraitsType>::InstX86Label *Label, BrCond Condition,
108 Mode Kind)
109 : InstX86Base(Func, InstX86Base::Br, 0, nullptr), Condition(Condition),
110 TargetTrue(TargetTrue), TargetFalse(TargetFalse), Label(Label),
111 Kind(Kind) {}
John Porto921856d2015-07-07 11:56:26 -0700112
John Porto4a566862016-01-04 09:33:41 -0800113template <typename TraitsType>
114bool InstImpl<TraitsType>::InstX86Br::optimizeBranch(const CfgNode *NextNode) {
Andrew Scull57e12682015-09-16 11:30:19 -0700115 // If there is no next block, then there can be no fallthrough to optimize.
John Porto921856d2015-07-07 11:56:26 -0700116 if (NextNode == nullptr)
117 return false;
118 // Intra-block conditional branches can't be optimized.
119 if (Label)
120 return false;
Andrew Scull57e12682015-09-16 11:30:19 -0700121 // If there is no fallthrough node, such as a non-default case label for a
122 // switch instruction, then there is no opportunity to optimize.
John Porto921856d2015-07-07 11:56:26 -0700123 if (getTargetFalse() == nullptr)
124 return false;
125
126 // Unconditional branch to the next node can be removed.
John Porto4a566862016-01-04 09:33:41 -0800127 if (Condition == Cond::Br_None && getTargetFalse() == NextNode) {
John Porto921856d2015-07-07 11:56:26 -0700128 assert(getTargetTrue() == nullptr);
129 this->setDeleted();
130 return true;
131 }
Andrew Scull57e12682015-09-16 11:30:19 -0700132 // If the fallthrough is to the next node, set fallthrough to nullptr to
133 // indicate.
John Porto921856d2015-07-07 11:56:26 -0700134 if (getTargetFalse() == NextNode) {
135 TargetFalse = nullptr;
136 return true;
137 }
Andrew Scull57e12682015-09-16 11:30:19 -0700138 // If TargetTrue is the next node, and TargetFalse is not nullptr (which was
139 // already tested above), then invert the branch condition, swap the targets,
140 // and set new fallthrough to nullptr.
John Porto921856d2015-07-07 11:56:26 -0700141 if (getTargetTrue() == NextNode) {
John Porto4a566862016-01-04 09:33:41 -0800142 assert(Condition != Cond::Br_None);
John Porto921856d2015-07-07 11:56:26 -0700143 Condition = this->getOppositeCondition(Condition);
144 TargetTrue = getTargetFalse();
145 TargetFalse = nullptr;
146 return true;
147 }
148 return false;
149}
150
John Porto4a566862016-01-04 09:33:41 -0800151template <typename TraitsType>
152bool InstImpl<TraitsType>::InstX86Br::repointEdges(CfgNode *OldNode,
153 CfgNode *NewNode) {
Andrew Scull87f80c12015-07-20 10:19:16 -0700154 bool Found = false;
John Porto921856d2015-07-07 11:56:26 -0700155 if (TargetFalse == OldNode) {
156 TargetFalse = NewNode;
Andrew Scull87f80c12015-07-20 10:19:16 -0700157 Found = true;
John Porto921856d2015-07-07 11:56:26 -0700158 }
Andrew Scull87f80c12015-07-20 10:19:16 -0700159 if (TargetTrue == OldNode) {
160 TargetTrue = NewNode;
161 Found = true;
162 }
163 return Found;
John Porto921856d2015-07-07 11:56:26 -0700164}
165
John Porto4a566862016-01-04 09:33:41 -0800166template <typename TraitsType>
167InstImpl<TraitsType>::InstX86Jmp::InstX86Jmp(Cfg *Func, Operand *Target)
168 : InstX86Base(Func, InstX86Base::Jmp, 1, nullptr) {
John Porto921856d2015-07-07 11:56:26 -0700169 this->addSource(Target);
170}
171
John Porto4a566862016-01-04 09:33:41 -0800172template <typename TraitsType>
173InstImpl<TraitsType>::InstX86Call::InstX86Call(Cfg *Func, Variable *Dest,
174 Operand *CallTarget)
175 : InstX86Base(Func, InstX86Base::Call, 1, Dest) {
John Porto921856d2015-07-07 11:56:26 -0700176 this->HasSideEffects = true;
177 this->addSource(CallTarget);
178}
179
John Porto4a566862016-01-04 09:33:41 -0800180template <typename TraitsType>
181InstImpl<TraitsType>::InstX86Cmov::InstX86Cmov(Cfg *Func, Variable *Dest,
182 Operand *Source,
183 BrCond Condition)
184 : InstX86Base(Func, InstX86Base::Cmov, 2, Dest), Condition(Condition) {
Andrew Scull57e12682015-09-16 11:30:19 -0700185 // The final result is either the original Dest, or Source, so mark both as
186 // sources.
John Porto921856d2015-07-07 11:56:26 -0700187 this->addSource(Dest);
188 this->addSource(Source);
189}
190
John Porto4a566862016-01-04 09:33:41 -0800191template <typename TraitsType>
192InstImpl<TraitsType>::InstX86Cmpps::InstX86Cmpps(Cfg *Func, Variable *Dest,
193 Operand *Source,
194 CmppsCond Condition)
195 : InstX86Base(Func, InstX86Base::Cmpps, 2, Dest), Condition(Condition) {
John Porto921856d2015-07-07 11:56:26 -0700196 this->addSource(Dest);
197 this->addSource(Source);
198}
199
John Porto4a566862016-01-04 09:33:41 -0800200template <typename TraitsType>
201InstImpl<TraitsType>::InstX86Cmpxchg::InstX86Cmpxchg(Cfg *Func,
202 Operand *DestOrAddr,
203 Variable *Eax,
204 Variable *Desired,
205 bool Locked)
206 : InstImpl<TraitsType>::InstX86BaseLockable(
207 Func, InstX86Base::Cmpxchg, 3, llvm::dyn_cast<Variable>(DestOrAddr),
208 Locked) {
John Porto3c275ce2015-12-22 08:14:00 -0800209 constexpr uint16_t Encoded_rAX = 0;
210 (void)Encoded_rAX;
John Porto4a566862016-01-04 09:33:41 -0800211 assert(Traits::getEncodedGPR(Eax->getRegNum()) == Encoded_rAX);
John Porto921856d2015-07-07 11:56:26 -0700212 this->addSource(DestOrAddr);
213 this->addSource(Eax);
214 this->addSource(Desired);
215}
216
John Porto4a566862016-01-04 09:33:41 -0800217template <typename TraitsType>
218InstImpl<TraitsType>::InstX86Cmpxchg8b::InstX86Cmpxchg8b(
219 Cfg *Func, X86OperandMem *Addr, Variable *Edx, Variable *Eax, Variable *Ecx,
220 Variable *Ebx, bool Locked)
221 : InstImpl<TraitsType>::InstX86BaseLockable(Func, InstX86Base::Cmpxchg, 5,
222 nullptr, Locked) {
223 assert(Edx->getRegNum() == RegisterSet::Reg_edx);
224 assert(Eax->getRegNum() == RegisterSet::Reg_eax);
225 assert(Ecx->getRegNum() == RegisterSet::Reg_ecx);
226 assert(Ebx->getRegNum() == RegisterSet::Reg_ebx);
John Porto921856d2015-07-07 11:56:26 -0700227 this->addSource(Addr);
228 this->addSource(Edx);
229 this->addSource(Eax);
230 this->addSource(Ecx);
231 this->addSource(Ebx);
232}
233
John Porto4a566862016-01-04 09:33:41 -0800234template <typename TraitsType>
235InstImpl<TraitsType>::InstX86Cvt::InstX86Cvt(Cfg *Func, Variable *Dest,
236 Operand *Source,
237 CvtVariant Variant)
238 : InstX86Base(Func, InstX86Base::Cvt, 1, Dest), Variant(Variant) {
John Porto921856d2015-07-07 11:56:26 -0700239 this->addSource(Source);
240}
241
John Porto4a566862016-01-04 09:33:41 -0800242template <typename TraitsType>
243InstImpl<TraitsType>::InstX86Icmp::InstX86Icmp(Cfg *Func, Operand *Src0,
244 Operand *Src1)
245 : InstX86Base(Func, InstX86Base::Icmp, 2, nullptr) {
John Porto921856d2015-07-07 11:56:26 -0700246 this->addSource(Src0);
247 this->addSource(Src1);
248}
249
John Porto4a566862016-01-04 09:33:41 -0800250template <typename TraitsType>
251InstImpl<TraitsType>::InstX86Ucomiss::InstX86Ucomiss(Cfg *Func, Operand *Src0,
252 Operand *Src1)
253 : InstX86Base(Func, InstX86Base::Ucomiss, 2, nullptr) {
John Porto921856d2015-07-07 11:56:26 -0700254 this->addSource(Src0);
255 this->addSource(Src1);
256}
257
John Porto4a566862016-01-04 09:33:41 -0800258template <typename TraitsType>
259InstImpl<TraitsType>::InstX86UD2::InstX86UD2(Cfg *Func)
260 : InstX86Base(Func, InstX86Base::UD2, 0, nullptr) {}
John Porto921856d2015-07-07 11:56:26 -0700261
John Porto4a566862016-01-04 09:33:41 -0800262template <typename TraitsType>
263InstImpl<TraitsType>::InstX86Test::InstX86Test(Cfg *Func, Operand *Src1,
264 Operand *Src2)
265 : InstX86Base(Func, InstX86Base::Test, 2, nullptr) {
John Porto921856d2015-07-07 11:56:26 -0700266 this->addSource(Src1);
267 this->addSource(Src2);
268}
269
John Porto4a566862016-01-04 09:33:41 -0800270template <typename TraitsType>
271InstImpl<TraitsType>::InstX86Mfence::InstX86Mfence(Cfg *Func)
272 : InstX86Base(Func, InstX86Base::Mfence, 0, nullptr) {
John Porto921856d2015-07-07 11:56:26 -0700273 this->HasSideEffects = true;
274}
275
John Porto4a566862016-01-04 09:33:41 -0800276template <typename TraitsType>
277InstImpl<TraitsType>::InstX86Store::InstX86Store(Cfg *Func, Operand *Value,
278 X86Operand *Mem)
279 : InstX86Base(Func, InstX86Base::Store, 2, nullptr) {
John Porto921856d2015-07-07 11:56:26 -0700280 this->addSource(Value);
281 this->addSource(Mem);
282}
283
John Porto4a566862016-01-04 09:33:41 -0800284template <typename TraitsType>
285InstImpl<TraitsType>::InstX86StoreP::InstX86StoreP(Cfg *Func, Variable *Value,
286 X86OperandMem *Mem)
287 : InstX86Base(Func, InstX86Base::StoreP, 2, nullptr) {
John Porto921856d2015-07-07 11:56:26 -0700288 this->addSource(Value);
289 this->addSource(Mem);
290}
291
John Porto4a566862016-01-04 09:33:41 -0800292template <typename TraitsType>
293InstImpl<TraitsType>::InstX86StoreQ::InstX86StoreQ(Cfg *Func, Variable *Value,
294 X86OperandMem *Mem)
295 : InstX86Base(Func, InstX86Base::StoreQ, 2, nullptr) {
John Porto921856d2015-07-07 11:56:26 -0700296 this->addSource(Value);
297 this->addSource(Mem);
298}
299
John Porto4a566862016-01-04 09:33:41 -0800300template <typename TraitsType>
301InstImpl<TraitsType>::InstX86Nop::InstX86Nop(Cfg *Func,
302 InstX86Nop::NopVariant Variant)
303 : InstX86Base(Func, InstX86Base::Nop, 0, nullptr), Variant(Variant) {}
John Porto921856d2015-07-07 11:56:26 -0700304
John Porto4a566862016-01-04 09:33:41 -0800305template <typename TraitsType>
306InstImpl<TraitsType>::InstX86Fld::InstX86Fld(Cfg *Func, Operand *Src)
307 : InstX86Base(Func, InstX86Base::Fld, 1, nullptr) {
John Porto921856d2015-07-07 11:56:26 -0700308 this->addSource(Src);
309}
310
John Porto4a566862016-01-04 09:33:41 -0800311template <typename TraitsType>
312InstImpl<TraitsType>::InstX86Fstp::InstX86Fstp(Cfg *Func, Variable *Dest)
313 : InstX86Base(Func, InstX86Base::Fstp, 0, Dest) {}
John Porto921856d2015-07-07 11:56:26 -0700314
John Porto4a566862016-01-04 09:33:41 -0800315template <typename TraitsType>
316InstImpl<TraitsType>::InstX86Pop::InstX86Pop(Cfg *Func, Variable *Dest)
317 : InstX86Base(Func, InstX86Base::Pop, 0, Dest) {
Andrew Scull57e12682015-09-16 11:30:19 -0700318 // A pop instruction affects the stack pointer and so it should not be
319 // allowed to be automatically dead-code eliminated. (The corresponding push
320 // instruction doesn't need this treatment because it has no dest variable
321 // and therefore won't be dead-code eliminated.) This is needed for
322 // late-stage liveness analysis (e.g. asm-verbose mode).
John Porto921856d2015-07-07 11:56:26 -0700323 this->HasSideEffects = true;
324}
325
John Porto4a566862016-01-04 09:33:41 -0800326template <typename TraitsType>
John Porto56958cb2016-01-14 09:18:18 -0800327InstImpl<TraitsType>::InstX86Push::InstX86Push(Cfg *Func, Operand *Source)
John Porto4a566862016-01-04 09:33:41 -0800328 : InstX86Base(Func, InstX86Base::Push, 1, nullptr) {
John Porto921856d2015-07-07 11:56:26 -0700329 this->addSource(Source);
330}
331
John Porto4a566862016-01-04 09:33:41 -0800332template <typename TraitsType>
John Porto56958cb2016-01-14 09:18:18 -0800333InstImpl<TraitsType>::InstX86Push::InstX86Push(Cfg *Func, InstX86Label *L)
334 : InstX86Base(Func, InstX86Base::Push, 0, nullptr), Label(L) {}
335
336template <typename TraitsType>
John Porto4a566862016-01-04 09:33:41 -0800337InstImpl<TraitsType>::InstX86Ret::InstX86Ret(Cfg *Func, Variable *Source)
338 : InstX86Base(Func, InstX86Base::Ret, Source ? 1 : 0, nullptr) {
John Porto921856d2015-07-07 11:56:26 -0700339 if (Source)
340 this->addSource(Source);
341}
342
John Porto4a566862016-01-04 09:33:41 -0800343template <typename TraitsType>
344InstImpl<TraitsType>::InstX86Setcc::InstX86Setcc(Cfg *Func, Variable *Dest,
345 BrCond Cond)
346 : InstX86Base(Func, InstX86Base::Setcc, 0, Dest), Condition(Cond) {}
John Porto921856d2015-07-07 11:56:26 -0700347
John Porto4a566862016-01-04 09:33:41 -0800348template <typename TraitsType>
349InstImpl<TraitsType>::InstX86Xadd::InstX86Xadd(Cfg *Func, Operand *Dest,
350 Variable *Source, bool Locked)
351 : InstImpl<TraitsType>::InstX86BaseLockable(
352 Func, InstX86Base::Xadd, 2, llvm::dyn_cast<Variable>(Dest), Locked) {
John Porto921856d2015-07-07 11:56:26 -0700353 this->addSource(Dest);
354 this->addSource(Source);
355}
356
John Porto4a566862016-01-04 09:33:41 -0800357template <typename TraitsType>
358InstImpl<TraitsType>::InstX86Xchg::InstX86Xchg(Cfg *Func, Operand *Dest,
359 Variable *Source)
360 : InstX86Base(Func, InstX86Base::Xchg, 2, llvm::dyn_cast<Variable>(Dest)) {
John Porto921856d2015-07-07 11:56:26 -0700361 this->addSource(Dest);
362 this->addSource(Source);
363}
364
John Porto4a566862016-01-04 09:33:41 -0800365template <typename TraitsType>
366InstImpl<TraitsType>::InstX86IacaStart::InstX86IacaStart(Cfg *Func)
367 : InstX86Base(Func, InstX86Base::IacaStart, 0, nullptr) {
Andrew Scull2c862522015-08-06 08:41:53 -0700368 assert(Func->getContext()->getFlags().getAllowIacaMarks());
369}
370
John Porto4a566862016-01-04 09:33:41 -0800371template <typename TraitsType>
372InstImpl<TraitsType>::InstX86IacaEnd::InstX86IacaEnd(Cfg *Func)
373 : InstX86Base(Func, InstX86Base::IacaEnd, 0, nullptr) {
Andrew Scull2c862522015-08-06 08:41:53 -0700374 assert(Func->getContext()->getFlags().getAllowIacaMarks());
375}
376
John Porto921856d2015-07-07 11:56:26 -0700377// ======================== Dump routines ======================== //
378
John Porto4a566862016-01-04 09:33:41 -0800379template <typename TraitsType>
380void InstImpl<TraitsType>::InstX86Base::dump(const Cfg *Func) const {
John Porto921856d2015-07-07 11:56:26 -0700381 if (!BuildDefs::dump())
382 return;
383 Ostream &Str = Func->getContext()->getStrDump();
384 Str << "[" << Traits::TargetName << "] ";
385 Inst::dump(Func);
386}
387
John Porto4a566862016-01-04 09:33:41 -0800388template <typename TraitsType>
389void InstImpl<TraitsType>::InstX86FakeRMW::dump(const Cfg *Func) const {
John Porto921856d2015-07-07 11:56:26 -0700390 if (!BuildDefs::dump())
391 return;
392 Ostream &Str = Func->getContext()->getStrDump();
393 Type Ty = getData()->getType();
394 Str << "rmw " << InstArithmetic::getOpName(getOp()) << " " << Ty << " *";
395 getAddr()->dump(Func);
396 Str << ", ";
397 getData()->dump(Func);
398 Str << ", beacon=";
399 getBeacon()->dump(Func);
400}
401
John Porto4a566862016-01-04 09:33:41 -0800402template <typename TraitsType>
Jim Stichnoth8ff4b282016-01-04 15:39:06 -0800403void InstImpl<TraitsType>::InstX86GetIP::emit(const Cfg *Func) const {
404 if (!BuildDefs::dump())
405 return;
John Porto6e8d3fa2016-02-04 10:35:20 -0800406 const auto *Dest = this->getDest();
407 assert(Dest->hasReg());
Jim Stichnoth8ff4b282016-01-04 15:39:06 -0800408 Ostream &Str = Func->getContext()->getStrEmit();
Jim Stichnoth8ff4b282016-01-04 15:39:06 -0800409 Str << "\t"
John Porto6e8d3fa2016-02-04 10:35:20 -0800410 "call"
411 "\t";
412 auto *Target = static_cast<TargetLowering *>(Func->getTarget());
413 Target->emitWithoutPrefix(Target->createGetIPForRegister(Dest));
Jim Stichnoth8ff4b282016-01-04 15:39:06 -0800414}
415
416template <typename TraitsType>
417void InstImpl<TraitsType>::InstX86GetIP::emitIAS(const Cfg *Func) const {
John Porto6e8d3fa2016-02-04 10:35:20 -0800418 const auto *Dest = this->getDest();
Jim Stichnoth8ff4b282016-01-04 15:39:06 -0800419 Assembler *Asm = Func->getAssembler<Assembler>();
John Porto6e8d3fa2016-02-04 10:35:20 -0800420 assert(Dest->hasReg());
421 Asm->call(static_cast<TargetLowering *>(Func->getTarget())
422 ->createGetIPForRegister(Dest));
Jim Stichnoth8ff4b282016-01-04 15:39:06 -0800423}
424
425template <typename TraitsType>
426void InstImpl<TraitsType>::InstX86GetIP::dump(const Cfg *Func) const {
427 if (!BuildDefs::dump())
428 return;
429 Ostream &Str = Func->getContext()->getStrDump();
430 this->getDest()->dump(Func);
431 Str << " = call getIP";
432}
433
434template <typename TraitsType>
John Porto4a566862016-01-04 09:33:41 -0800435void InstImpl<TraitsType>::InstX86Label::emit(const Cfg *Func) const {
John Porto921856d2015-07-07 11:56:26 -0700436 if (!BuildDefs::dump())
437 return;
438 Ostream &Str = Func->getContext()->getStrEmit();
439 Str << getName(Func) << ":";
440}
441
John Porto4a566862016-01-04 09:33:41 -0800442template <typename TraitsType>
443void InstImpl<TraitsType>::InstX86Label::emitIAS(const Cfg *Func) const {
444 Assembler *Asm = Func->getAssembler<Assembler>();
Andrew Scull86df4e92015-07-30 13:54:44 -0700445 Asm->bindLocalLabel(Number);
John Porto27fddcc2016-02-02 15:06:09 -0800446 if (OffsetReloc != nullptr) {
447 Asm->bindRelocOffset(OffsetReloc);
448 }
John Porto921856d2015-07-07 11:56:26 -0700449}
450
John Porto4a566862016-01-04 09:33:41 -0800451template <typename TraitsType>
452void InstImpl<TraitsType>::InstX86Label::dump(const Cfg *Func) const {
John Porto921856d2015-07-07 11:56:26 -0700453 if (!BuildDefs::dump())
454 return;
455 Ostream &Str = Func->getContext()->getStrDump();
456 Str << getName(Func) << ":";
457}
458
John Porto4a566862016-01-04 09:33:41 -0800459template <typename TraitsType>
460void InstImpl<TraitsType>::InstX86Br::emit(const Cfg *Func) const {
John Porto921856d2015-07-07 11:56:26 -0700461 if (!BuildDefs::dump())
462 return;
463 Ostream &Str = Func->getContext()->getStrEmit();
464 Str << "\t";
465
John Porto4a566862016-01-04 09:33:41 -0800466 if (Condition == Cond::Br_None) {
John Porto921856d2015-07-07 11:56:26 -0700467 Str << "jmp";
468 } else {
John Porto4a566862016-01-04 09:33:41 -0800469 Str << Traits::InstBrAttributes[Condition].EmitString;
John Porto921856d2015-07-07 11:56:26 -0700470 }
471
472 if (Label) {
473 Str << "\t" << Label->getName(Func);
474 } else {
John Porto4a566862016-01-04 09:33:41 -0800475 if (Condition == Cond::Br_None) {
John Porto921856d2015-07-07 11:56:26 -0700476 Str << "\t" << getTargetFalse()->getAsmName();
477 } else {
478 Str << "\t" << getTargetTrue()->getAsmName();
479 if (getTargetFalse()) {
Jim Stichnoth6106df82015-12-16 06:17:58 -0800480 Str << "\n\t"
481 "jmp\t" << getTargetFalse()->getAsmName();
John Porto921856d2015-07-07 11:56:26 -0700482 }
483 }
484 }
485}
486
John Porto4a566862016-01-04 09:33:41 -0800487template <typename TraitsType>
488void InstImpl<TraitsType>::InstX86Br::emitIAS(const Cfg *Func) const {
489 Assembler *Asm = Func->getAssembler<Assembler>();
John Porto921856d2015-07-07 11:56:26 -0700490 if (Label) {
John Porto4a566862016-01-04 09:33:41 -0800491 auto *L = Asm->getOrCreateLocalLabel(Label->getNumber());
492 if (Condition == Cond::Br_None) {
Andrew Scull86df4e92015-07-30 13:54:44 -0700493 Asm->jmp(L, isNear());
John Porto921856d2015-07-07 11:56:26 -0700494 } else {
Andrew Scull86df4e92015-07-30 13:54:44 -0700495 Asm->j(Condition, L, isNear());
John Porto921856d2015-07-07 11:56:26 -0700496 }
497 } else {
John Porto4a566862016-01-04 09:33:41 -0800498 if (Condition == Cond::Br_None) {
499 auto *L = Asm->getOrCreateCfgNodeLabel(getTargetFalse()->getIndex());
John Porto921856d2015-07-07 11:56:26 -0700500 assert(!getTargetTrue());
Andrew Scull86df4e92015-07-30 13:54:44 -0700501 Asm->jmp(L, isNear());
John Porto921856d2015-07-07 11:56:26 -0700502 } else {
John Porto4a566862016-01-04 09:33:41 -0800503 auto *L = Asm->getOrCreateCfgNodeLabel(getTargetTrue()->getIndex());
Andrew Scull86df4e92015-07-30 13:54:44 -0700504 Asm->j(Condition, L, isNear());
John Porto921856d2015-07-07 11:56:26 -0700505 if (getTargetFalse()) {
John Porto4a566862016-01-04 09:33:41 -0800506 auto *L2 = Asm->getOrCreateCfgNodeLabel(getTargetFalse()->getIndex());
Andrew Scull86df4e92015-07-30 13:54:44 -0700507 Asm->jmp(L2, isNear());
John Porto921856d2015-07-07 11:56:26 -0700508 }
509 }
510 }
511}
512
John Porto4a566862016-01-04 09:33:41 -0800513template <typename TraitsType>
514void InstImpl<TraitsType>::InstX86Br::dump(const Cfg *Func) const {
John Porto921856d2015-07-07 11:56:26 -0700515 if (!BuildDefs::dump())
516 return;
517 Ostream &Str = Func->getContext()->getStrDump();
518 Str << "br ";
519
John Porto4a566862016-01-04 09:33:41 -0800520 if (Condition == Cond::Br_None) {
John Porto921856d2015-07-07 11:56:26 -0700521 Str << "label %"
522 << (Label ? Label->getName(Func) : getTargetFalse()->getName());
523 return;
524 }
525
John Porto4a566862016-01-04 09:33:41 -0800526 Str << Traits::InstBrAttributes[Condition].DisplayString;
John Porto921856d2015-07-07 11:56:26 -0700527 if (Label) {
528 Str << ", label %" << Label->getName(Func);
529 } else {
530 Str << ", label %" << getTargetTrue()->getName();
531 if (getTargetFalse()) {
532 Str << ", label %" << getTargetFalse()->getName();
533 }
534 }
Andrew Scull86df4e92015-07-30 13:54:44 -0700535
536 Str << " // (" << (isNear() ? "near" : "far") << " jump)";
John Porto921856d2015-07-07 11:56:26 -0700537}
538
John Porto4a566862016-01-04 09:33:41 -0800539template <typename TraitsType>
540void InstImpl<TraitsType>::InstX86Jmp::emit(const Cfg *Func) const {
John Porto921856d2015-07-07 11:56:26 -0700541 if (!BuildDefs::dump())
542 return;
543 Ostream &Str = Func->getContext()->getStrEmit();
544 assert(this->getSrcSize() == 1);
John Porto56958cb2016-01-14 09:18:18 -0800545 const Operand *Src = this->getSrc(0);
546 if (Traits::Is64Bit) {
547 if (const auto *CR = llvm::dyn_cast<ConstantRelocatable>(Src)) {
548 Str << "\t"
549 "jmp"
550 "\t" << CR->getName();
551 return;
552 }
553 }
Jim Stichnoth6106df82015-12-16 06:17:58 -0800554 Str << "\t"
John Porto56958cb2016-01-14 09:18:18 -0800555 "jmp"
556 "\t*";
John Porto921856d2015-07-07 11:56:26 -0700557 getJmpTarget()->emit(Func);
558}
559
John Porto4a566862016-01-04 09:33:41 -0800560template <typename TraitsType>
561void InstImpl<TraitsType>::InstX86Jmp::emitIAS(const Cfg *Func) const {
562 // Note: Adapted (mostly copied) from
563 // InstImpl<TraitsType>::InstX86Call::emitIAS().
564 Assembler *Asm = Func->getAssembler<Assembler>();
John Porto921856d2015-07-07 11:56:26 -0700565 Operand *Target = getJmpTarget();
Jim Stichnoth5bff61c2015-10-28 09:26:00 -0700566 if (const auto *Var = llvm::dyn_cast<Variable>(Target)) {
John Porto921856d2015-07-07 11:56:26 -0700567 if (Var->hasReg()) {
John Porto4a566862016-01-04 09:33:41 -0800568 Asm->jmp(Traits::getEncodedGPR(Var->getRegNum()));
John Porto921856d2015-07-07 11:56:26 -0700569 } else {
Andrew Scull57e12682015-09-16 11:30:19 -0700570 // The jmp instruction with a memory operand should be possible to
571 // encode, but it isn't a valid sandboxed instruction, and there
572 // shouldn't be a register allocation issue to jump through a scratch
573 // register, so we don't really need to bother implementing it.
John Porto921856d2015-07-07 11:56:26 -0700574 llvm::report_fatal_error("Assembler can't jmp to memory operand");
575 }
John Porto4a566862016-01-04 09:33:41 -0800576 } else if (const auto *Mem = llvm::dyn_cast<X86OperandMem>(Target)) {
John Porto921856d2015-07-07 11:56:26 -0700577 (void)Mem;
John Porto4a566862016-01-04 09:33:41 -0800578 assert(Mem->getSegmentRegister() == X86OperandMem::DefaultSegment);
John Porto921856d2015-07-07 11:56:26 -0700579 llvm::report_fatal_error("Assembler can't jmp to memory operand");
Jim Stichnoth5bff61c2015-10-28 09:26:00 -0700580 } else if (const auto *CR = llvm::dyn_cast<ConstantRelocatable>(Target)) {
John Porto921856d2015-07-07 11:56:26 -0700581 Asm->jmp(CR);
Jim Stichnoth5bff61c2015-10-28 09:26:00 -0700582 } else if (const auto *Imm = llvm::dyn_cast<ConstantInteger32>(Target)) {
John Porto921856d2015-07-07 11:56:26 -0700583 // NaCl trampoline calls refer to an address within the sandbox directly.
Andrew Scull57e12682015-09-16 11:30:19 -0700584 // This is usually only needed for non-IRT builds and otherwise not very
585 // portable or stable. Usually this is only done for "calls" and not jumps.
John Porto34d276a2016-01-27 06:31:53 -0800586 Asm->jmp(AssemblerImmediate(Imm->getValue()));
John Porto921856d2015-07-07 11:56:26 -0700587 } else {
588 llvm::report_fatal_error("Unexpected operand type");
589 }
590}
591
John Porto4a566862016-01-04 09:33:41 -0800592template <typename TraitsType>
593void InstImpl<TraitsType>::InstX86Jmp::dump(const Cfg *Func) const {
John Porto921856d2015-07-07 11:56:26 -0700594 if (!BuildDefs::dump())
595 return;
596 Ostream &Str = Func->getContext()->getStrDump();
597 Str << "jmp ";
598 getJmpTarget()->dump(Func);
599}
600
John Porto4a566862016-01-04 09:33:41 -0800601template <typename TraitsType>
602void InstImpl<TraitsType>::InstX86Call::emit(const Cfg *Func) const {
John Porto921856d2015-07-07 11:56:26 -0700603 if (!BuildDefs::dump())
604 return;
605 Ostream &Str = Func->getContext()->getStrEmit();
606 assert(this->getSrcSize() == 1);
Jim Stichnoth6106df82015-12-16 06:17:58 -0800607 Str << "\t"
608 "call\t";
David Sehr4318a412015-11-11 15:01:55 -0800609 Operand *CallTarget = getCallTarget();
John Porto4a566862016-01-04 09:33:41 -0800610 auto *Target = InstX86Base::getTarget(Func);
David Sehr4318a412015-11-11 15:01:55 -0800611 if (const auto *CI = llvm::dyn_cast<ConstantInteger32>(CallTarget)) {
John Porto921856d2015-07-07 11:56:26 -0700612 // Emit without a leading '$'.
613 Str << CI->getValue();
David Sehr4318a412015-11-11 15:01:55 -0800614 } else if (const auto DirectCallTarget =
615 llvm::dyn_cast<ConstantRelocatable>(CallTarget)) {
616 DirectCallTarget->emitWithoutPrefix(Target);
John Porto921856d2015-07-07 11:56:26 -0700617 } else {
618 Str << "*";
David Sehr4318a412015-11-11 15:01:55 -0800619 CallTarget->emit(Func);
John Porto921856d2015-07-07 11:56:26 -0700620 }
John Porto921856d2015-07-07 11:56:26 -0700621}
622
John Porto4a566862016-01-04 09:33:41 -0800623template <typename TraitsType>
624void InstImpl<TraitsType>::InstX86Call::emitIAS(const Cfg *Func) const {
625 Assembler *Asm = Func->getAssembler<Assembler>();
David Sehr4318a412015-11-11 15:01:55 -0800626 Operand *CallTarget = getCallTarget();
John Porto4a566862016-01-04 09:33:41 -0800627 auto *Target = InstX86Base::getTarget(Func);
David Sehr4318a412015-11-11 15:01:55 -0800628 if (const auto *Var = llvm::dyn_cast<Variable>(CallTarget)) {
John Porto921856d2015-07-07 11:56:26 -0700629 if (Var->hasReg()) {
John Porto4a566862016-01-04 09:33:41 -0800630 Asm->call(Traits::getEncodedGPR(Var->getRegNum()));
John Porto921856d2015-07-07 11:56:26 -0700631 } else {
David Sehrb8e49c12015-11-12 14:41:22 -0800632 Asm->call(Target->stackVarToAsmOperand(Var));
John Porto921856d2015-07-07 11:56:26 -0700633 }
John Porto4a566862016-01-04 09:33:41 -0800634 } else if (const auto *Mem = llvm::dyn_cast<X86OperandMem>(CallTarget)) {
635 assert(Mem->getSegmentRegister() == X86OperandMem::DefaultSegment);
David Sehr4318a412015-11-11 15:01:55 -0800636 Asm->call(Mem->toAsmAddress(Asm, Target));
637 } else if (const auto *CR = llvm::dyn_cast<ConstantRelocatable>(CallTarget)) {
John Porto921856d2015-07-07 11:56:26 -0700638 Asm->call(CR);
David Sehr4318a412015-11-11 15:01:55 -0800639 } else if (const auto *Imm = llvm::dyn_cast<ConstantInteger32>(CallTarget)) {
John Porto4a566862016-01-04 09:33:41 -0800640 Asm->call(AssemblerImmediate(Imm->getValue()));
John Porto921856d2015-07-07 11:56:26 -0700641 } else {
642 llvm_unreachable("Unexpected operand type");
643 }
John Porto921856d2015-07-07 11:56:26 -0700644}
645
John Porto4a566862016-01-04 09:33:41 -0800646template <typename TraitsType>
647void InstImpl<TraitsType>::InstX86Call::dump(const Cfg *Func) const {
John Porto921856d2015-07-07 11:56:26 -0700648 if (!BuildDefs::dump())
649 return;
650 Ostream &Str = Func->getContext()->getStrDump();
651 if (this->getDest()) {
652 this->dumpDest(Func);
653 Str << " = ";
654 }
655 Str << "call ";
656 getCallTarget()->dump(Func);
657}
658
Jim Stichnoth5bff61c2015-10-28 09:26:00 -0700659// The this->Opcode parameter needs to be char* and not IceString because of
660// template issues.
John Porto4a566862016-01-04 09:33:41 -0800661template <typename TraitsType>
662void InstImpl<TraitsType>::InstX86Base::emitTwoAddress(
663 const Cfg *Func, const char *Opcode, const char *Suffix) const {
John Porto921856d2015-07-07 11:56:26 -0700664 if (!BuildDefs::dump())
665 return;
666 Ostream &Str = Func->getContext()->getStrEmit();
David Sehr6da7ae22015-12-17 15:01:30 -0800667 assert(getSrcSize() == 2);
668 Operand *Dest = getDest();
John Porto921856d2015-07-07 11:56:26 -0700669 if (Dest == nullptr)
David Sehr6da7ae22015-12-17 15:01:30 -0800670 Dest = getSrc(0);
671 assert(Dest == getSrc(0));
672 Operand *Src1 = getSrc(1);
673 Str << "\t" << Opcode << Suffix
John Porto4a566862016-01-04 09:33:41 -0800674 << InstX86Base::getWidthString(Dest->getType()) << "\t";
Jim Stichnoth5bff61c2015-10-28 09:26:00 -0700675 Src1->emit(Func);
John Porto921856d2015-07-07 11:56:26 -0700676 Str << ", ";
677 Dest->emit(Func);
678}
679
John Porto4a566862016-01-04 09:33:41 -0800680template <typename TraitsType>
681void InstImpl<TraitsType>::emitIASOpTyGPR(const Cfg *Func, Type Ty,
682 const Operand *Op,
683 const GPREmitterOneOp &Emitter) {
684 auto *Target = InstX86Base::getTarget(Func);
685 Assembler *Asm = Func->getAssembler<Assembler>();
Jim Stichnoth5bff61c2015-10-28 09:26:00 -0700686 if (const auto *Var = llvm::dyn_cast<Variable>(Op)) {
John Porto921856d2015-07-07 11:56:26 -0700687 if (Var->hasReg()) {
688 // We cheat a little and use GPRRegister even for byte operations.
John Porto4a566862016-01-04 09:33:41 -0800689 GPRRegister VarReg = Traits::getEncodedGPR(Var->getRegNum());
John Porto921856d2015-07-07 11:56:26 -0700690 (Asm->*(Emitter.Reg))(Ty, VarReg);
691 } else {
John Porto4a566862016-01-04 09:33:41 -0800692 Address StackAddr(Target->stackVarToAsmOperand(Var));
John Porto921856d2015-07-07 11:56:26 -0700693 (Asm->*(Emitter.Addr))(Ty, StackAddr);
694 }
John Porto4a566862016-01-04 09:33:41 -0800695 } else if (const auto *Mem = llvm::dyn_cast<X86OperandMem>(Op)) {
John Porto921856d2015-07-07 11:56:26 -0700696 Mem->emitSegmentOverride(Asm);
David Sehr4318a412015-11-11 15:01:55 -0800697 (Asm->*(Emitter.Addr))(Ty, Mem->toAsmAddress(Asm, Target));
John Porto921856d2015-07-07 11:56:26 -0700698 } else {
699 llvm_unreachable("Unexpected operand type");
700 }
701}
702
John Porto4a566862016-01-04 09:33:41 -0800703template <typename TraitsType>
704template <bool VarCanBeByte, bool SrcCanBeByte>
John Porto56958cb2016-01-14 09:18:18 -0800705void InstImpl<TraitsType>::emitIASRegOpTyGPR(const Cfg *Func, bool IsLea,
706 Type Ty, const Variable *Var,
John Porto4a566862016-01-04 09:33:41 -0800707 const Operand *Src,
708 const GPREmitterRegOp &Emitter) {
709 auto *Target = InstX86Base::getTarget(Func);
710 Assembler *Asm = Func->getAssembler<Assembler>();
John Porto921856d2015-07-07 11:56:26 -0700711 assert(Var->hasReg());
712 // We cheat a little and use GPRRegister even for byte operations.
John Porto4a566862016-01-04 09:33:41 -0800713 GPRRegister VarReg = VarCanBeByte ? Traits::getEncodedGPR(Var->getRegNum())
714 : Traits::getEncodedGPR(Var->getRegNum());
Jim Stichnoth5bff61c2015-10-28 09:26:00 -0700715 if (const auto *SrcVar = llvm::dyn_cast<Variable>(Src)) {
John Porto921856d2015-07-07 11:56:26 -0700716 if (SrcVar->hasReg()) {
John Porto4a566862016-01-04 09:33:41 -0800717 GPRRegister SrcReg = SrcCanBeByte
718 ? Traits::getEncodedGPR(SrcVar->getRegNum())
719 : Traits::getEncodedGPR(SrcVar->getRegNum());
John Porto921856d2015-07-07 11:56:26 -0700720 (Asm->*(Emitter.GPRGPR))(Ty, VarReg, SrcReg);
721 } else {
John Porto4a566862016-01-04 09:33:41 -0800722 Address SrcStackAddr = Target->stackVarToAsmOperand(SrcVar);
John Porto921856d2015-07-07 11:56:26 -0700723 (Asm->*(Emitter.GPRAddr))(Ty, VarReg, SrcStackAddr);
724 }
John Porto4a566862016-01-04 09:33:41 -0800725 } else if (const auto *Mem = llvm::dyn_cast<X86OperandMem>(Src)) {
John Porto921856d2015-07-07 11:56:26 -0700726 Mem->emitSegmentOverride(Asm);
John Porto56958cb2016-01-14 09:18:18 -0800727 (Asm->*(Emitter.GPRAddr))(Ty, VarReg,
728 Mem->toAsmAddress(Asm, Target, IsLea));
Jim Stichnoth5bff61c2015-10-28 09:26:00 -0700729 } else if (const auto *Imm = llvm::dyn_cast<ConstantInteger32>(Src)) {
John Porto4a566862016-01-04 09:33:41 -0800730 (Asm->*(Emitter.GPRImm))(Ty, VarReg, AssemblerImmediate(Imm->getValue()));
Jim Stichnoth5bff61c2015-10-28 09:26:00 -0700731 } else if (const auto *Reloc = llvm::dyn_cast<ConstantRelocatable>(Src)) {
John Porto6e8d3fa2016-02-04 10:35:20 -0800732 const auto FixupKind = Reloc->getName() == GlobalOffsetTable
733 ? Traits::FK_GotPC
734 : Traits::TargetLowering::getAbsFixup();
735 AssemblerFixup *Fixup = Asm->createFixup(FixupKind, Reloc);
736 (Asm->*(Emitter.GPRImm))(Ty, VarReg, AssemblerImmediate(Fixup));
John Porto4a566862016-01-04 09:33:41 -0800737 } else if (const auto *Split = llvm::dyn_cast<VariableSplit>(Src)) {
John Porto921856d2015-07-07 11:56:26 -0700738 (Asm->*(Emitter.GPRAddr))(Ty, VarReg, Split->toAsmAddress(Func));
739 } else {
740 llvm_unreachable("Unexpected operand type");
741 }
742}
743
John Porto4a566862016-01-04 09:33:41 -0800744template <typename TraitsType>
745void InstImpl<TraitsType>::emitIASAddrOpTyGPR(const Cfg *Func, Type Ty,
746 const Address &Addr,
747 const Operand *Src,
748 const GPREmitterAddrOp &Emitter) {
749 Assembler *Asm = Func->getAssembler<Assembler>();
750 // Src can only be Reg or AssemblerImmediate.
Jim Stichnoth5bff61c2015-10-28 09:26:00 -0700751 if (const auto *SrcVar = llvm::dyn_cast<Variable>(Src)) {
John Porto921856d2015-07-07 11:56:26 -0700752 assert(SrcVar->hasReg());
John Porto4a566862016-01-04 09:33:41 -0800753 GPRRegister SrcReg = Traits::getEncodedGPR(SrcVar->getRegNum());
John Porto921856d2015-07-07 11:56:26 -0700754 (Asm->*(Emitter.AddrGPR))(Ty, Addr, SrcReg);
Jim Stichnoth5bff61c2015-10-28 09:26:00 -0700755 } else if (const auto *Imm = llvm::dyn_cast<ConstantInteger32>(Src)) {
John Porto4a566862016-01-04 09:33:41 -0800756 (Asm->*(Emitter.AddrImm))(Ty, Addr, AssemblerImmediate(Imm->getValue()));
Jim Stichnoth5bff61c2015-10-28 09:26:00 -0700757 } else if (const auto *Reloc = llvm::dyn_cast<ConstantRelocatable>(Src)) {
John Porto6e8d3fa2016-02-04 10:35:20 -0800758 const auto FixupKind = Reloc->getName() == GlobalOffsetTable
759 ? Traits::FK_GotPC
760 : Traits::TargetLowering::getAbsFixup();
761 AssemblerFixup *Fixup = Asm->createFixup(FixupKind, Reloc);
762 (Asm->*(Emitter.AddrImm))(Ty, Addr, AssemblerImmediate(Fixup));
John Porto921856d2015-07-07 11:56:26 -0700763 } else {
764 llvm_unreachable("Unexpected operand type");
765 }
766}
767
John Porto4a566862016-01-04 09:33:41 -0800768template <typename TraitsType>
769void InstImpl<TraitsType>::emitIASAsAddrOpTyGPR(
John Porto921856d2015-07-07 11:56:26 -0700770 const Cfg *Func, Type Ty, const Operand *Op0, const Operand *Op1,
John Porto4a566862016-01-04 09:33:41 -0800771 const GPREmitterAddrOp &Emitter) {
772 auto *Target = InstX86Base::getTarget(Func);
Jim Stichnoth5bff61c2015-10-28 09:26:00 -0700773 if (const auto *Op0Var = llvm::dyn_cast<Variable>(Op0)) {
John Porto921856d2015-07-07 11:56:26 -0700774 assert(!Op0Var->hasReg());
John Porto4a566862016-01-04 09:33:41 -0800775 Address StackAddr(Target->stackVarToAsmOperand(Op0Var));
776 emitIASAddrOpTyGPR(Func, Ty, StackAddr, Op1, Emitter);
777 } else if (const auto *Op0Mem = llvm::dyn_cast<X86OperandMem>(Op0)) {
778 Assembler *Asm = Func->getAssembler<Assembler>();
John Porto921856d2015-07-07 11:56:26 -0700779 Op0Mem->emitSegmentOverride(Asm);
John Porto4a566862016-01-04 09:33:41 -0800780 emitIASAddrOpTyGPR(Func, Ty, Op0Mem->toAsmAddress(Asm, Target), Op1,
781 Emitter);
782 } else if (const auto *Split = llvm::dyn_cast<VariableSplit>(Op0)) {
783 emitIASAddrOpTyGPR(Func, Ty, Split->toAsmAddress(Func), Op1, Emitter);
John Porto921856d2015-07-07 11:56:26 -0700784 } else {
785 llvm_unreachable("Unexpected operand type");
786 }
787}
788
John Porto4a566862016-01-04 09:33:41 -0800789template <typename TraitsType>
790void InstImpl<TraitsType>::emitIASGPRShift(const Cfg *Func, Type Ty,
791 const Variable *Var,
792 const Operand *Src,
793 const GPREmitterShiftOp &Emitter) {
794 Assembler *Asm = Func->getAssembler<Assembler>();
Andrew Scull57e12682015-09-16 11:30:19 -0700795 // Technically, the Dest Var can be mem as well, but we only use Reg. We can
796 // extend this to check Dest if we decide to use that form.
John Porto921856d2015-07-07 11:56:26 -0700797 assert(Var->hasReg());
798 // We cheat a little and use GPRRegister even for byte operations.
John Porto4a566862016-01-04 09:33:41 -0800799 GPRRegister VarReg = Traits::getEncodedGPR(Var->getRegNum());
Andrew Scull57e12682015-09-16 11:30:19 -0700800 // Src must be reg == ECX or an Imm8. This is asserted by the assembler.
Jim Stichnoth5bff61c2015-10-28 09:26:00 -0700801 if (const auto *SrcVar = llvm::dyn_cast<Variable>(Src)) {
John Porto921856d2015-07-07 11:56:26 -0700802 assert(SrcVar->hasReg());
John Porto4a566862016-01-04 09:33:41 -0800803 GPRRegister SrcReg = Traits::getEncodedGPR(SrcVar->getRegNum());
John Porto921856d2015-07-07 11:56:26 -0700804 (Asm->*(Emitter.GPRGPR))(Ty, VarReg, SrcReg);
Jim Stichnoth5bff61c2015-10-28 09:26:00 -0700805 } else if (const auto *Imm = llvm::dyn_cast<ConstantInteger32>(Src)) {
John Porto4a566862016-01-04 09:33:41 -0800806 (Asm->*(Emitter.GPRImm))(Ty, VarReg, AssemblerImmediate(Imm->getValue()));
John Porto921856d2015-07-07 11:56:26 -0700807 } else {
808 llvm_unreachable("Unexpected operand type");
809 }
810}
811
John Porto4a566862016-01-04 09:33:41 -0800812template <typename TraitsType>
813void InstImpl<TraitsType>::emitIASGPRShiftDouble(
John Porto921856d2015-07-07 11:56:26 -0700814 const Cfg *Func, const Variable *Dest, const Operand *Src1Op,
John Porto4a566862016-01-04 09:33:41 -0800815 const Operand *Src2Op, const GPREmitterShiftD &Emitter) {
816 Assembler *Asm = Func->getAssembler<Assembler>();
John Porto921856d2015-07-07 11:56:26 -0700817 // Dest can be reg or mem, but we only use the reg variant.
818 assert(Dest->hasReg());
John Porto4a566862016-01-04 09:33:41 -0800819 GPRRegister DestReg = Traits::getEncodedGPR(Dest->getRegNum());
John Porto921856d2015-07-07 11:56:26 -0700820 // SrcVar1 must be reg.
Jim Stichnoth5bff61c2015-10-28 09:26:00 -0700821 const auto *SrcVar1 = llvm::cast<Variable>(Src1Op);
John Porto921856d2015-07-07 11:56:26 -0700822 assert(SrcVar1->hasReg());
John Porto4a566862016-01-04 09:33:41 -0800823 GPRRegister SrcReg = Traits::getEncodedGPR(SrcVar1->getRegNum());
John Porto921856d2015-07-07 11:56:26 -0700824 Type Ty = SrcVar1->getType();
825 // Src2 can be the implicit CL register or an immediate.
Jim Stichnoth5bff61c2015-10-28 09:26:00 -0700826 if (const auto *Imm = llvm::dyn_cast<ConstantInteger32>(Src2Op)) {
John Porto921856d2015-07-07 11:56:26 -0700827 (Asm->*(Emitter.GPRGPRImm))(Ty, DestReg, SrcReg,
John Porto4a566862016-01-04 09:33:41 -0800828 AssemblerImmediate(Imm->getValue()));
John Porto921856d2015-07-07 11:56:26 -0700829 } else {
John Porto4a566862016-01-04 09:33:41 -0800830 assert(llvm::cast<Variable>(Src2Op)->getRegNum() == RegisterSet::Reg_cl);
John Porto921856d2015-07-07 11:56:26 -0700831 (Asm->*(Emitter.GPRGPR))(Ty, DestReg, SrcReg);
832 }
833}
834
John Porto4a566862016-01-04 09:33:41 -0800835template <typename TraitsType>
836void InstImpl<TraitsType>::emitIASXmmShift(const Cfg *Func, Type Ty,
837 const Variable *Var,
838 const Operand *Src,
839 const XmmEmitterShiftOp &Emitter) {
840 auto *Target = InstX86Base::getTarget(Func);
841 Assembler *Asm = Func->getAssembler<Assembler>();
John Porto921856d2015-07-07 11:56:26 -0700842 assert(Var->hasReg());
John Porto4a566862016-01-04 09:33:41 -0800843 XmmRegister VarReg = Traits::getEncodedXmm(Var->getRegNum());
Jim Stichnoth5bff61c2015-10-28 09:26:00 -0700844 if (const auto *SrcVar = llvm::dyn_cast<Variable>(Src)) {
John Porto921856d2015-07-07 11:56:26 -0700845 if (SrcVar->hasReg()) {
John Porto4a566862016-01-04 09:33:41 -0800846 XmmRegister SrcReg = Traits::getEncodedXmm(SrcVar->getRegNum());
John Porto921856d2015-07-07 11:56:26 -0700847 (Asm->*(Emitter.XmmXmm))(Ty, VarReg, SrcReg);
848 } else {
John Porto4a566862016-01-04 09:33:41 -0800849 Address SrcStackAddr = Target->stackVarToAsmOperand(SrcVar);
John Porto921856d2015-07-07 11:56:26 -0700850 (Asm->*(Emitter.XmmAddr))(Ty, VarReg, SrcStackAddr);
851 }
John Porto4a566862016-01-04 09:33:41 -0800852 } else if (const auto *Mem = llvm::dyn_cast<X86OperandMem>(Src)) {
853 assert(Mem->getSegmentRegister() == X86OperandMem::DefaultSegment);
David Sehr4318a412015-11-11 15:01:55 -0800854 (Asm->*(Emitter.XmmAddr))(Ty, VarReg, Mem->toAsmAddress(Asm, Target));
Jim Stichnoth5bff61c2015-10-28 09:26:00 -0700855 } else if (const auto *Imm = llvm::dyn_cast<ConstantInteger32>(Src)) {
John Porto4a566862016-01-04 09:33:41 -0800856 (Asm->*(Emitter.XmmImm))(Ty, VarReg, AssemblerImmediate(Imm->getValue()));
John Porto921856d2015-07-07 11:56:26 -0700857 } else {
858 llvm_unreachable("Unexpected operand type");
859 }
860}
861
John Porto4a566862016-01-04 09:33:41 -0800862template <typename TraitsType>
863void InstImpl<TraitsType>::emitIASRegOpTyXMM(const Cfg *Func, Type Ty,
864 const Variable *Var,
865 const Operand *Src,
866 const XmmEmitterRegOp &Emitter) {
867 auto *Target = InstX86Base::getTarget(Func);
868 Assembler *Asm = Func->getAssembler<Assembler>();
John Porto921856d2015-07-07 11:56:26 -0700869 assert(Var->hasReg());
John Porto4a566862016-01-04 09:33:41 -0800870 XmmRegister VarReg = Traits::getEncodedXmm(Var->getRegNum());
Jim Stichnoth5bff61c2015-10-28 09:26:00 -0700871 if (const auto *SrcVar = llvm::dyn_cast<Variable>(Src)) {
John Porto921856d2015-07-07 11:56:26 -0700872 if (SrcVar->hasReg()) {
John Porto4a566862016-01-04 09:33:41 -0800873 XmmRegister SrcReg = Traits::getEncodedXmm(SrcVar->getRegNum());
John Porto921856d2015-07-07 11:56:26 -0700874 (Asm->*(Emitter.XmmXmm))(Ty, VarReg, SrcReg);
875 } else {
John Porto4a566862016-01-04 09:33:41 -0800876 Address SrcStackAddr = Target->stackVarToAsmOperand(SrcVar);
John Porto921856d2015-07-07 11:56:26 -0700877 (Asm->*(Emitter.XmmAddr))(Ty, VarReg, SrcStackAddr);
878 }
John Porto4a566862016-01-04 09:33:41 -0800879 } else if (const auto *Mem = llvm::dyn_cast<X86OperandMem>(Src)) {
880 assert(Mem->getSegmentRegister() == X86OperandMem::DefaultSegment);
David Sehr4318a412015-11-11 15:01:55 -0800881 (Asm->*(Emitter.XmmAddr))(Ty, VarReg, Mem->toAsmAddress(Asm, Target));
Jim Stichnoth5bff61c2015-10-28 09:26:00 -0700882 } else if (const auto *Imm = llvm::dyn_cast<Constant>(Src)) {
John Porto4a566862016-01-04 09:33:41 -0800883 (Asm->*(Emitter.XmmAddr))(Ty, VarReg,
884 Traits::Address::ofConstPool(Asm, Imm));
John Porto921856d2015-07-07 11:56:26 -0700885 } else {
886 llvm_unreachable("Unexpected operand type");
887 }
888}
889
John Porto4a566862016-01-04 09:33:41 -0800890template <typename TraitsType>
Jim Stichnoth8aa39662016-02-10 11:20:30 -0800891template <typename DReg_t, typename SReg_t, DReg_t (*destEnc)(RegNumT),
892 SReg_t (*srcEnc)(RegNumT)>
John Porto4a566862016-01-04 09:33:41 -0800893void InstImpl<TraitsType>::emitIASCastRegOp(
894 const Cfg *Func, Type DestTy, const Variable *Dest, Type SrcTy,
895 const Operand *Src, const CastEmitterRegOp<DReg_t, SReg_t> &Emitter) {
896 auto *Target = InstX86Base::getTarget(Func);
897 Assembler *Asm = Func->getAssembler<Assembler>();
John Porto921856d2015-07-07 11:56:26 -0700898 assert(Dest->hasReg());
899 DReg_t DestReg = destEnc(Dest->getRegNum());
Jim Stichnoth5bff61c2015-10-28 09:26:00 -0700900 if (const auto *SrcVar = llvm::dyn_cast<Variable>(Src)) {
John Porto921856d2015-07-07 11:56:26 -0700901 if (SrcVar->hasReg()) {
902 SReg_t SrcReg = srcEnc(SrcVar->getRegNum());
John Porto1d235422015-08-12 12:37:53 -0700903 (Asm->*(Emitter.RegReg))(DestTy, DestReg, SrcTy, SrcReg);
John Porto921856d2015-07-07 11:56:26 -0700904 } else {
John Porto4a566862016-01-04 09:33:41 -0800905 Address SrcStackAddr = Target->stackVarToAsmOperand(SrcVar);
John Porto1d235422015-08-12 12:37:53 -0700906 (Asm->*(Emitter.RegAddr))(DestTy, DestReg, SrcTy, SrcStackAddr);
John Porto921856d2015-07-07 11:56:26 -0700907 }
John Porto4a566862016-01-04 09:33:41 -0800908 } else if (const auto *Mem = llvm::dyn_cast<X86OperandMem>(Src)) {
John Porto921856d2015-07-07 11:56:26 -0700909 Mem->emitSegmentOverride(Asm);
David Sehr4318a412015-11-11 15:01:55 -0800910 (Asm->*(Emitter.RegAddr))(DestTy, DestReg, SrcTy,
911 Mem->toAsmAddress(Asm, Target));
John Porto921856d2015-07-07 11:56:26 -0700912 } else {
913 llvm_unreachable("Unexpected operand type");
914 }
915}
916
John Porto4a566862016-01-04 09:33:41 -0800917template <typename TraitsType>
Jim Stichnoth8aa39662016-02-10 11:20:30 -0800918template <typename DReg_t, typename SReg_t, DReg_t (*destEnc)(RegNumT),
919 SReg_t (*srcEnc)(RegNumT)>
John Porto4a566862016-01-04 09:33:41 -0800920void InstImpl<TraitsType>::emitIASThreeOpImmOps(
John Porto921856d2015-07-07 11:56:26 -0700921 const Cfg *Func, Type DispatchTy, const Variable *Dest, const Operand *Src0,
John Porto4a566862016-01-04 09:33:41 -0800922 const Operand *Src1, const ThreeOpImmEmitter<DReg_t, SReg_t> Emitter) {
923 auto *Target = InstX86Base::getTarget(Func);
924 Assembler *Asm = Func->getAssembler<Assembler>();
John Porto921856d2015-07-07 11:56:26 -0700925 // This only handles Dest being a register, and Src1 being an immediate.
926 assert(Dest->hasReg());
927 DReg_t DestReg = destEnc(Dest->getRegNum());
John Porto4a566862016-01-04 09:33:41 -0800928 AssemblerImmediate Imm(llvm::cast<ConstantInteger32>(Src1)->getValue());
Jim Stichnoth5bff61c2015-10-28 09:26:00 -0700929 if (const auto *SrcVar = llvm::dyn_cast<Variable>(Src0)) {
John Porto921856d2015-07-07 11:56:26 -0700930 if (SrcVar->hasReg()) {
931 SReg_t SrcReg = srcEnc(SrcVar->getRegNum());
932 (Asm->*(Emitter.RegRegImm))(DispatchTy, DestReg, SrcReg, Imm);
933 } else {
John Porto4a566862016-01-04 09:33:41 -0800934 Address SrcStackAddr = Target->stackVarToAsmOperand(SrcVar);
John Porto921856d2015-07-07 11:56:26 -0700935 (Asm->*(Emitter.RegAddrImm))(DispatchTy, DestReg, SrcStackAddr, Imm);
936 }
John Porto4a566862016-01-04 09:33:41 -0800937 } else if (const auto *Mem = llvm::dyn_cast<X86OperandMem>(Src0)) {
John Porto921856d2015-07-07 11:56:26 -0700938 Mem->emitSegmentOverride(Asm);
David Sehr4318a412015-11-11 15:01:55 -0800939 (Asm->*(Emitter.RegAddrImm))(DispatchTy, DestReg,
940 Mem->toAsmAddress(Asm, Target), Imm);
John Porto921856d2015-07-07 11:56:26 -0700941 } else {
942 llvm_unreachable("Unexpected operand type");
943 }
944}
945
John Porto4a566862016-01-04 09:33:41 -0800946template <typename TraitsType>
947void InstImpl<TraitsType>::emitIASMovlikeXMM(const Cfg *Func,
948 const Variable *Dest,
949 const Operand *Src,
950 const XmmEmitterMovOps Emitter) {
951 auto *Target = InstX86Base::getTarget(Func);
952 Assembler *Asm = Func->getAssembler<Assembler>();
John Porto921856d2015-07-07 11:56:26 -0700953 if (Dest->hasReg()) {
John Porto4a566862016-01-04 09:33:41 -0800954 XmmRegister DestReg = Traits::getEncodedXmm(Dest->getRegNum());
Jim Stichnoth5bff61c2015-10-28 09:26:00 -0700955 if (const auto *SrcVar = llvm::dyn_cast<Variable>(Src)) {
John Porto921856d2015-07-07 11:56:26 -0700956 if (SrcVar->hasReg()) {
John Porto4a566862016-01-04 09:33:41 -0800957 (Asm->*(Emitter.XmmXmm))(DestReg,
958 Traits::getEncodedXmm(SrcVar->getRegNum()));
John Porto921856d2015-07-07 11:56:26 -0700959 } else {
John Porto4a566862016-01-04 09:33:41 -0800960 Address StackAddr(Target->stackVarToAsmOperand(SrcVar));
John Porto921856d2015-07-07 11:56:26 -0700961 (Asm->*(Emitter.XmmAddr))(DestReg, StackAddr);
962 }
John Porto4a566862016-01-04 09:33:41 -0800963 } else if (const auto *SrcMem = llvm::dyn_cast<X86OperandMem>(Src)) {
964 assert(SrcMem->getSegmentRegister() == X86OperandMem::DefaultSegment);
David Sehr4318a412015-11-11 15:01:55 -0800965 (Asm->*(Emitter.XmmAddr))(DestReg, SrcMem->toAsmAddress(Asm, Target));
John Porto921856d2015-07-07 11:56:26 -0700966 } else {
967 llvm_unreachable("Unexpected operand type");
968 }
969 } else {
John Porto4a566862016-01-04 09:33:41 -0800970 Address StackAddr(Target->stackVarToAsmOperand(Dest));
John Porto921856d2015-07-07 11:56:26 -0700971 // Src must be a register in this case.
Jim Stichnoth5bff61c2015-10-28 09:26:00 -0700972 const auto *SrcVar = llvm::cast<Variable>(Src);
John Porto921856d2015-07-07 11:56:26 -0700973 assert(SrcVar->hasReg());
John Porto4a566862016-01-04 09:33:41 -0800974 (Asm->*(Emitter.AddrXmm))(StackAddr,
975 Traits::getEncodedXmm(SrcVar->getRegNum()));
John Porto921856d2015-07-07 11:56:26 -0700976 }
977}
978
John Porto4a566862016-01-04 09:33:41 -0800979template <typename TraitsType>
980void InstImpl<TraitsType>::InstX86Sqrtss::emit(const Cfg *Func) const {
John Porto921856d2015-07-07 11:56:26 -0700981 if (!BuildDefs::dump())
982 return;
983 Ostream &Str = Func->getContext()->getStrEmit();
984 assert(this->getSrcSize() == 1);
985 Type Ty = this->getSrc(0)->getType();
986 assert(isScalarFloatingType(Ty));
Jim Stichnoth6106df82015-12-16 06:17:58 -0800987 Str << "\t"
John Porto4a566862016-01-04 09:33:41 -0800988 "sqrt" << Traits::TypeAttributes[Ty].SdSsString << "\t";
John Porto921856d2015-07-07 11:56:26 -0700989 this->getSrc(0)->emit(Func);
990 Str << ", ";
991 this->getDest()->emit(Func);
992}
993
John Porto4a566862016-01-04 09:33:41 -0800994template <typename TraitsType>
995void InstImpl<TraitsType>::InstX86Div::emit(const Cfg *Func) const {
John Porto921856d2015-07-07 11:56:26 -0700996 if (!BuildDefs::dump())
997 return;
998 Ostream &Str = Func->getContext()->getStrEmit();
999 assert(this->getSrcSize() == 3);
1000 Operand *Src1 = this->getSrc(1);
1001 Str << "\t" << this->Opcode << this->getWidthString(Src1->getType()) << "\t";
1002 Src1->emit(Func);
1003}
1004
John Porto4a566862016-01-04 09:33:41 -08001005template <typename TraitsType>
1006void InstImpl<TraitsType>::InstX86Div::emitIAS(const Cfg *Func) const {
John Porto921856d2015-07-07 11:56:26 -07001007 assert(this->getSrcSize() == 3);
1008 const Operand *Src = this->getSrc(1);
1009 Type Ty = Src->getType();
John Porto4a566862016-01-04 09:33:41 -08001010 static GPREmitterOneOp Emitter = {&Assembler::div, &Assembler::div};
1011 emitIASOpTyGPR(Func, Ty, Src, Emitter);
John Porto921856d2015-07-07 11:56:26 -07001012}
1013
John Porto4a566862016-01-04 09:33:41 -08001014template <typename TraitsType>
1015void InstImpl<TraitsType>::InstX86Idiv::emit(const Cfg *Func) const {
John Porto921856d2015-07-07 11:56:26 -07001016 if (!BuildDefs::dump())
1017 return;
1018 Ostream &Str = Func->getContext()->getStrEmit();
1019 assert(this->getSrcSize() == 3);
1020 Operand *Src1 = this->getSrc(1);
1021 Str << "\t" << this->Opcode << this->getWidthString(Src1->getType()) << "\t";
1022 Src1->emit(Func);
1023}
1024
John Porto4a566862016-01-04 09:33:41 -08001025template <typename TraitsType>
1026void InstImpl<TraitsType>::InstX86Idiv::emitIAS(const Cfg *Func) const {
John Porto921856d2015-07-07 11:56:26 -07001027 assert(this->getSrcSize() == 3);
1028 const Operand *Src = this->getSrc(1);
1029 Type Ty = Src->getType();
John Porto4a566862016-01-04 09:33:41 -08001030 static const GPREmitterOneOp Emitter = {&Assembler::idiv, &Assembler::idiv};
1031 emitIASOpTyGPR(Func, Ty, Src, Emitter);
John Porto921856d2015-07-07 11:56:26 -07001032}
1033
1034// pblendvb and blendvps take xmm0 as a final implicit argument.
John Porto4a566862016-01-04 09:33:41 -08001035template <typename TraitsType>
1036void InstImpl<TraitsType>::emitVariableBlendInst(const char *Opcode,
Jim Stichnoth8cfeb692016-02-05 09:50:02 -08001037 const Inst *Instr,
John Porto4a566862016-01-04 09:33:41 -08001038 const Cfg *Func) {
John Porto921856d2015-07-07 11:56:26 -07001039 if (!BuildDefs::dump())
1040 return;
1041 Ostream &Str = Func->getContext()->getStrEmit();
Jim Stichnoth8cfeb692016-02-05 09:50:02 -08001042 assert(Instr->getSrcSize() == 3);
1043 assert(llvm::cast<Variable>(Instr->getSrc(2))->getRegNum() ==
John Porto4a566862016-01-04 09:33:41 -08001044 RegisterSet::Reg_xmm0);
John Porto921856d2015-07-07 11:56:26 -07001045 Str << "\t" << Opcode << "\t";
Jim Stichnoth8cfeb692016-02-05 09:50:02 -08001046 Instr->getSrc(1)->emit(Func);
John Porto921856d2015-07-07 11:56:26 -07001047 Str << ", ";
Jim Stichnoth8cfeb692016-02-05 09:50:02 -08001048 Instr->getDest()->emit(Func);
John Porto921856d2015-07-07 11:56:26 -07001049}
1050
John Porto4a566862016-01-04 09:33:41 -08001051template <typename TraitsType>
1052void InstImpl<TraitsType>::emitIASVariableBlendInst(
Jim Stichnoth8cfeb692016-02-05 09:50:02 -08001053 const Inst *Instr, const Cfg *Func, const XmmEmitterRegOp &Emitter) {
1054 assert(Instr->getSrcSize() == 3);
1055 assert(llvm::cast<Variable>(Instr->getSrc(2))->getRegNum() ==
John Porto4a566862016-01-04 09:33:41 -08001056 RegisterSet::Reg_xmm0);
Jim Stichnoth8cfeb692016-02-05 09:50:02 -08001057 const Variable *Dest = Instr->getDest();
1058 const Operand *Src = Instr->getSrc(1);
John Porto4a566862016-01-04 09:33:41 -08001059 emitIASRegOpTyXMM(Func, Dest->getType(), Dest, Src, Emitter);
John Porto921856d2015-07-07 11:56:26 -07001060}
1061
John Porto4a566862016-01-04 09:33:41 -08001062template <typename TraitsType>
1063void InstImpl<TraitsType>::InstX86Blendvps::emit(const Cfg *Func) const {
John Porto921856d2015-07-07 11:56:26 -07001064 if (!BuildDefs::dump())
1065 return;
John Porto4a566862016-01-04 09:33:41 -08001066 emitVariableBlendInst(this->Opcode, this, Func);
John Porto921856d2015-07-07 11:56:26 -07001067}
1068
John Porto4a566862016-01-04 09:33:41 -08001069template <typename TraitsType>
1070void InstImpl<TraitsType>::InstX86Blendvps::emitIAS(const Cfg *Func) const {
1071 static const XmmEmitterRegOp Emitter = {&Assembler::blendvps,
1072 &Assembler::blendvps};
1073 emitIASVariableBlendInst(this, Func, Emitter);
John Porto921856d2015-07-07 11:56:26 -07001074}
1075
John Porto4a566862016-01-04 09:33:41 -08001076template <typename TraitsType>
1077void InstImpl<TraitsType>::InstX86Pblendvb::emit(const Cfg *Func) const {
John Porto921856d2015-07-07 11:56:26 -07001078 if (!BuildDefs::dump())
1079 return;
John Porto4a566862016-01-04 09:33:41 -08001080 emitVariableBlendInst(this->Opcode, this, Func);
John Porto921856d2015-07-07 11:56:26 -07001081}
1082
John Porto4a566862016-01-04 09:33:41 -08001083template <typename TraitsType>
1084void InstImpl<TraitsType>::InstX86Pblendvb::emitIAS(const Cfg *Func) const {
1085 static const XmmEmitterRegOp Emitter = {&Assembler::pblendvb,
1086 &Assembler::pblendvb};
1087 emitIASVariableBlendInst(this, Func, Emitter);
John Porto921856d2015-07-07 11:56:26 -07001088}
1089
John Porto4a566862016-01-04 09:33:41 -08001090template <typename TraitsType>
1091void InstImpl<TraitsType>::InstX86Imul::emit(const Cfg *Func) const {
John Porto921856d2015-07-07 11:56:26 -07001092 if (!BuildDefs::dump())
1093 return;
1094 Ostream &Str = Func->getContext()->getStrEmit();
1095 assert(this->getSrcSize() == 2);
1096 Variable *Dest = this->getDest();
1097 if (isByteSizedArithType(Dest->getType())) {
1098 // The 8-bit version of imul only allows the form "imul r/m8".
Jim Stichnoth5bff61c2015-10-28 09:26:00 -07001099 const auto *Src0Var = llvm::dyn_cast<Variable>(this->getSrc(0));
John Porto921856d2015-07-07 11:56:26 -07001100 (void)Src0Var;
John Porto4a566862016-01-04 09:33:41 -08001101 assert(Src0Var->getRegNum() == RegisterSet::Reg_al);
Jim Stichnoth6106df82015-12-16 06:17:58 -08001102 Str << "\t"
1103 "imulb\t";
John Porto921856d2015-07-07 11:56:26 -07001104 this->getSrc(1)->emit(Func);
1105 } else if (llvm::isa<Constant>(this->getSrc(1))) {
Jim Stichnoth6106df82015-12-16 06:17:58 -08001106 Str << "\t"
1107 "imul" << this->getWidthString(Dest->getType()) << "\t";
John Porto921856d2015-07-07 11:56:26 -07001108 this->getSrc(1)->emit(Func);
1109 Str << ", ";
1110 this->getSrc(0)->emit(Func);
1111 Str << ", ";
1112 Dest->emit(Func);
1113 } else {
David Sehr6da7ae22015-12-17 15:01:30 -08001114 this->emitTwoAddress(Func, this->Opcode);
John Porto921856d2015-07-07 11:56:26 -07001115 }
1116}
1117
John Porto4a566862016-01-04 09:33:41 -08001118template <typename TraitsType>
1119void InstImpl<TraitsType>::InstX86Imul::emitIAS(const Cfg *Func) const {
John Porto921856d2015-07-07 11:56:26 -07001120 assert(this->getSrcSize() == 2);
1121 const Variable *Var = this->getDest();
1122 Type Ty = Var->getType();
1123 const Operand *Src = this->getSrc(1);
1124 if (isByteSizedArithType(Ty)) {
1125 // The 8-bit version of imul only allows the form "imul r/m8".
Jim Stichnoth5bff61c2015-10-28 09:26:00 -07001126 const auto *Src0Var = llvm::dyn_cast<Variable>(this->getSrc(0));
John Porto921856d2015-07-07 11:56:26 -07001127 (void)Src0Var;
John Porto4a566862016-01-04 09:33:41 -08001128 assert(Src0Var->getRegNum() == RegisterSet::Reg_al);
1129 static const GPREmitterOneOp Emitter = {&Assembler::imul, &Assembler::imul};
1130 emitIASOpTyGPR(Func, Ty, this->getSrc(1), Emitter);
John Porto921856d2015-07-07 11:56:26 -07001131 } else {
David Sehre11f8782015-10-06 10:26:57 -07001132 // The two-address version is used when multiplying by a non-constant
1133 // or doing an 8-bit multiply.
John Porto921856d2015-07-07 11:56:26 -07001134 assert(Var == this->getSrc(0));
John Porto4a566862016-01-04 09:33:41 -08001135 static const GPREmitterRegOp Emitter = {&Assembler::imul, &Assembler::imul,
1136 &Assembler::imul};
John Porto56958cb2016-01-14 09:18:18 -08001137 constexpr bool NotLea = false;
1138 emitIASRegOpTyGPR(Func, NotLea, Ty, Var, Src, Emitter);
John Porto921856d2015-07-07 11:56:26 -07001139 }
1140}
1141
John Porto4a566862016-01-04 09:33:41 -08001142template <typename TraitsType>
1143void InstImpl<TraitsType>::InstX86ImulImm::emit(const Cfg *Func) const {
David Sehre11f8782015-10-06 10:26:57 -07001144 if (!BuildDefs::dump())
1145 return;
1146 Ostream &Str = Func->getContext()->getStrEmit();
1147 assert(this->getSrcSize() == 2);
1148 Variable *Dest = this->getDest();
1149 assert(Dest->getType() == IceType_i16 || Dest->getType() == IceType_i32);
1150 assert(llvm::isa<Constant>(this->getSrc(1)));
Jim Stichnoth6106df82015-12-16 06:17:58 -08001151 Str << "\t"
1152 "imul" << this->getWidthString(Dest->getType()) << "\t";
David Sehre11f8782015-10-06 10:26:57 -07001153 this->getSrc(1)->emit(Func);
1154 Str << ", ";
1155 this->getSrc(0)->emit(Func);
1156 Str << ", ";
1157 Dest->emit(Func);
1158}
1159
John Porto4a566862016-01-04 09:33:41 -08001160template <typename TraitsType>
1161void InstImpl<TraitsType>::InstX86ImulImm::emitIAS(const Cfg *Func) const {
David Sehre11f8782015-10-06 10:26:57 -07001162 assert(this->getSrcSize() == 2);
1163 const Variable *Dest = this->getDest();
1164 Type Ty = Dest->getType();
1165 assert(llvm::isa<Constant>(this->getSrc(1)));
John Porto4a566862016-01-04 09:33:41 -08001166 static const ThreeOpImmEmitter<GPRRegister, GPRRegister> Emitter = {
1167 &Assembler::imul, &Assembler::imul};
1168 emitIASThreeOpImmOps<GPRRegister, GPRRegister, Traits::getEncodedGPR,
1169 Traits::getEncodedGPR>(Func, Ty, Dest, this->getSrc(0),
1170 this->getSrc(1), Emitter);
David Sehre11f8782015-10-06 10:26:57 -07001171}
1172
John Porto4a566862016-01-04 09:33:41 -08001173template <typename TraitsType>
1174void InstImpl<TraitsType>::InstX86Insertps::emitIAS(const Cfg *Func) const {
John Porto921856d2015-07-07 11:56:26 -07001175 assert(this->getSrcSize() == 3);
John Porto4a566862016-01-04 09:33:41 -08001176 assert(InstX86Base::getTarget(Func)->getInstructionSet() >= Traits::SSE4_1);
John Porto921856d2015-07-07 11:56:26 -07001177 const Variable *Dest = this->getDest();
1178 assert(Dest == this->getSrc(0));
1179 Type Ty = Dest->getType();
John Porto4a566862016-01-04 09:33:41 -08001180 static const ThreeOpImmEmitter<XmmRegister, XmmRegister> Emitter = {
1181 &Assembler::insertps, &Assembler::insertps};
1182 emitIASThreeOpImmOps<XmmRegister, XmmRegister, Traits::getEncodedXmm,
1183 Traits::getEncodedXmm>(Func, Ty, Dest, this->getSrc(1),
1184 this->getSrc(2), Emitter);
John Porto921856d2015-07-07 11:56:26 -07001185}
1186
John Porto4a566862016-01-04 09:33:41 -08001187template <typename TraitsType>
1188void InstImpl<TraitsType>::InstX86Cbwdq::emit(const Cfg *Func) const {
John Porto921856d2015-07-07 11:56:26 -07001189 if (!BuildDefs::dump())
1190 return;
1191 Ostream &Str = Func->getContext()->getStrEmit();
1192 assert(this->getSrcSize() == 1);
1193 Operand *Src0 = this->getSrc(0);
Jim Stichnoth8aa39662016-02-10 11:20:30 -08001194 const auto DestReg = this->getDest()->getRegNum();
1195 const auto SrcReg = llvm::cast<Variable>(Src0)->getRegNum();
Jim Stichnothc59288b2015-11-09 11:38:40 -08001196 (void)DestReg;
1197 (void)SrcReg;
John Porto921856d2015-07-07 11:56:26 -07001198 switch (Src0->getType()) {
1199 default:
1200 llvm_unreachable("unexpected source type!");
1201 break;
1202 case IceType_i8:
John Porto4a566862016-01-04 09:33:41 -08001203 assert(SrcReg == RegisterSet::Reg_al);
1204 assert(DestReg == RegisterSet::Reg_ax || DestReg == RegisterSet::Reg_ah);
John Porto1d235422015-08-12 12:37:53 -07001205 Str << "\t"
Jim Stichnoth6106df82015-12-16 06:17:58 -08001206 "cbtw";
John Porto921856d2015-07-07 11:56:26 -07001207 break;
1208 case IceType_i16:
John Porto4a566862016-01-04 09:33:41 -08001209 assert(SrcReg == RegisterSet::Reg_ax);
1210 assert(DestReg == RegisterSet::Reg_dx);
John Porto1d235422015-08-12 12:37:53 -07001211 Str << "\t"
Jim Stichnoth6106df82015-12-16 06:17:58 -08001212 "cwtd";
John Porto921856d2015-07-07 11:56:26 -07001213 break;
1214 case IceType_i32:
John Porto4a566862016-01-04 09:33:41 -08001215 assert(SrcReg == RegisterSet::Reg_eax);
1216 assert(DestReg == RegisterSet::Reg_edx);
John Porto1d235422015-08-12 12:37:53 -07001217 Str << "\t"
Jim Stichnoth6106df82015-12-16 06:17:58 -08001218 "cltd";
John Porto1d235422015-08-12 12:37:53 -07001219 break;
1220 case IceType_i64:
John Porto4a566862016-01-04 09:33:41 -08001221 assert(Traits::Is64Bit);
1222 assert(SrcReg == Traits::getRaxOrDie());
1223 assert(DestReg == Traits::getRdxOrDie());
John Porto1d235422015-08-12 12:37:53 -07001224 Str << "\t"
John Porto008f4ce2015-12-24 13:22:18 -08001225 "cqo";
John Porto921856d2015-07-07 11:56:26 -07001226 break;
1227 }
1228}
1229
John Porto4a566862016-01-04 09:33:41 -08001230template <typename TraitsType>
1231void InstImpl<TraitsType>::InstX86Cbwdq::emitIAS(const Cfg *Func) const {
1232 Assembler *Asm = Func->getAssembler<Assembler>();
John Porto921856d2015-07-07 11:56:26 -07001233 assert(this->getSrcSize() == 1);
1234 Operand *Src0 = this->getSrc(0);
Jim Stichnoth8aa39662016-02-10 11:20:30 -08001235 const auto DestReg = this->getDest()->getRegNum();
1236 const auto SrcReg = llvm::cast<Variable>(Src0)->getRegNum();
Jim Stichnothc59288b2015-11-09 11:38:40 -08001237 (void)DestReg;
1238 (void)SrcReg;
John Porto921856d2015-07-07 11:56:26 -07001239 switch (Src0->getType()) {
1240 default:
1241 llvm_unreachable("unexpected source type!");
1242 break;
1243 case IceType_i8:
John Porto4a566862016-01-04 09:33:41 -08001244 assert(SrcReg == RegisterSet::Reg_al);
1245 assert(DestReg == RegisterSet::Reg_ax || DestReg == RegisterSet::Reg_ah);
John Porto921856d2015-07-07 11:56:26 -07001246 Asm->cbw();
1247 break;
1248 case IceType_i16:
John Porto4a566862016-01-04 09:33:41 -08001249 assert(SrcReg == RegisterSet::Reg_ax);
1250 assert(DestReg == RegisterSet::Reg_dx);
John Porto921856d2015-07-07 11:56:26 -07001251 Asm->cwd();
1252 break;
1253 case IceType_i32:
John Porto4a566862016-01-04 09:33:41 -08001254 assert(SrcReg == RegisterSet::Reg_eax);
1255 assert(DestReg == RegisterSet::Reg_edx);
John Porto921856d2015-07-07 11:56:26 -07001256 Asm->cdq();
1257 break;
John Porto1d235422015-08-12 12:37:53 -07001258 case IceType_i64:
John Porto4a566862016-01-04 09:33:41 -08001259 assert(Traits::Is64Bit);
1260 assert(SrcReg == Traits::getRaxOrDie());
1261 assert(DestReg == Traits::getRdxOrDie());
John Porto1d235422015-08-12 12:37:53 -07001262 Asm->cqo();
1263 break;
John Porto921856d2015-07-07 11:56:26 -07001264 }
1265}
1266
John Porto4a566862016-01-04 09:33:41 -08001267template <typename TraitsType>
1268void InstImpl<TraitsType>::InstX86Mul::emit(const Cfg *Func) const {
John Porto921856d2015-07-07 11:56:26 -07001269 if (!BuildDefs::dump())
1270 return;
1271 Ostream &Str = Func->getContext()->getStrEmit();
1272 assert(this->getSrcSize() == 2);
1273 assert(llvm::isa<Variable>(this->getSrc(0)));
1274 assert(llvm::cast<Variable>(this->getSrc(0))->getRegNum() ==
John Porto4a566862016-01-04 09:33:41 -08001275 RegisterSet::Reg_eax);
1276 assert(this->getDest()->getRegNum() == RegisterSet::Reg_eax); // TODO:
1277 // allow
1278 // edx?
Jim Stichnoth6106df82015-12-16 06:17:58 -08001279 Str << "\t"
1280 "mul" << this->getWidthString(this->getDest()->getType()) << "\t";
John Porto921856d2015-07-07 11:56:26 -07001281 this->getSrc(1)->emit(Func);
1282}
1283
John Porto4a566862016-01-04 09:33:41 -08001284template <typename TraitsType>
1285void InstImpl<TraitsType>::InstX86Mul::emitIAS(const Cfg *Func) const {
John Porto921856d2015-07-07 11:56:26 -07001286 assert(this->getSrcSize() == 2);
1287 assert(llvm::isa<Variable>(this->getSrc(0)));
1288 assert(llvm::cast<Variable>(this->getSrc(0))->getRegNum() ==
John Porto4a566862016-01-04 09:33:41 -08001289 RegisterSet::Reg_eax);
1290 assert(this->getDest()->getRegNum() == RegisterSet::Reg_eax); // TODO:
1291 // allow
1292 // edx?
John Porto921856d2015-07-07 11:56:26 -07001293 const Operand *Src = this->getSrc(1);
1294 Type Ty = Src->getType();
John Porto4a566862016-01-04 09:33:41 -08001295 static const GPREmitterOneOp Emitter = {&Assembler::mul, &Assembler::mul};
1296 emitIASOpTyGPR(Func, Ty, Src, Emitter);
John Porto921856d2015-07-07 11:56:26 -07001297}
1298
John Porto4a566862016-01-04 09:33:41 -08001299template <typename TraitsType>
1300void InstImpl<TraitsType>::InstX86Mul::dump(const Cfg *Func) const {
John Porto921856d2015-07-07 11:56:26 -07001301 if (!BuildDefs::dump())
1302 return;
1303 Ostream &Str = Func->getContext()->getStrDump();
1304 this->dumpDest(Func);
1305 Str << " = mul." << this->getDest()->getType() << " ";
1306 this->dumpSources(Func);
1307}
1308
John Porto4a566862016-01-04 09:33:41 -08001309template <typename TraitsType>
1310void InstImpl<TraitsType>::InstX86Shld::emit(const Cfg *Func) const {
John Porto921856d2015-07-07 11:56:26 -07001311 if (!BuildDefs::dump())
1312 return;
1313 Ostream &Str = Func->getContext()->getStrEmit();
1314 Variable *Dest = this->getDest();
1315 assert(this->getSrcSize() == 3);
1316 assert(Dest == this->getSrc(0));
Jim Stichnoth6106df82015-12-16 06:17:58 -08001317 Str << "\t"
1318 "shld" << this->getWidthString(Dest->getType()) << "\t";
Jim Stichnoth5bff61c2015-10-28 09:26:00 -07001319 this->getSrc(2)->emit(Func);
John Porto921856d2015-07-07 11:56:26 -07001320 Str << ", ";
1321 this->getSrc(1)->emit(Func);
1322 Str << ", ";
1323 Dest->emit(Func);
1324}
1325
John Porto4a566862016-01-04 09:33:41 -08001326template <typename TraitsType>
1327void InstImpl<TraitsType>::InstX86Shld::emitIAS(const Cfg *Func) const {
John Porto921856d2015-07-07 11:56:26 -07001328 assert(this->getSrcSize() == 3);
1329 assert(this->getDest() == this->getSrc(0));
1330 const Variable *Dest = this->getDest();
1331 const Operand *Src1 = this->getSrc(1);
1332 const Operand *Src2 = this->getSrc(2);
John Porto4a566862016-01-04 09:33:41 -08001333 static const GPREmitterShiftD Emitter = {&Assembler::shld, &Assembler::shld};
1334 emitIASGPRShiftDouble(Func, Dest, Src1, Src2, Emitter);
John Porto921856d2015-07-07 11:56:26 -07001335}
1336
John Porto4a566862016-01-04 09:33:41 -08001337template <typename TraitsType>
1338void InstImpl<TraitsType>::InstX86Shld::dump(const Cfg *Func) const {
John Porto921856d2015-07-07 11:56:26 -07001339 if (!BuildDefs::dump())
1340 return;
1341 Ostream &Str = Func->getContext()->getStrDump();
1342 this->dumpDest(Func);
1343 Str << " = shld." << this->getDest()->getType() << " ";
1344 this->dumpSources(Func);
1345}
1346
John Porto4a566862016-01-04 09:33:41 -08001347template <typename TraitsType>
1348void InstImpl<TraitsType>::InstX86Shrd::emit(const Cfg *Func) const {
John Porto921856d2015-07-07 11:56:26 -07001349 if (!BuildDefs::dump())
1350 return;
1351 Ostream &Str = Func->getContext()->getStrEmit();
1352 Variable *Dest = this->getDest();
1353 assert(this->getSrcSize() == 3);
1354 assert(Dest == this->getSrc(0));
Jim Stichnoth6106df82015-12-16 06:17:58 -08001355 Str << "\t"
1356 "shrd" << this->getWidthString(Dest->getType()) << "\t";
Jim Stichnoth5bff61c2015-10-28 09:26:00 -07001357 this->getSrc(2)->emit(Func);
John Porto921856d2015-07-07 11:56:26 -07001358 Str << ", ";
1359 this->getSrc(1)->emit(Func);
1360 Str << ", ";
1361 Dest->emit(Func);
1362}
1363
John Porto4a566862016-01-04 09:33:41 -08001364template <typename TraitsType>
1365void InstImpl<TraitsType>::InstX86Shrd::emitIAS(const Cfg *Func) const {
John Porto921856d2015-07-07 11:56:26 -07001366 assert(this->getSrcSize() == 3);
1367 assert(this->getDest() == this->getSrc(0));
1368 const Variable *Dest = this->getDest();
1369 const Operand *Src1 = this->getSrc(1);
1370 const Operand *Src2 = this->getSrc(2);
John Porto4a566862016-01-04 09:33:41 -08001371 static const GPREmitterShiftD Emitter = {&Assembler::shrd, &Assembler::shrd};
1372 emitIASGPRShiftDouble(Func, Dest, Src1, Src2, Emitter);
John Porto921856d2015-07-07 11:56:26 -07001373}
1374
John Porto4a566862016-01-04 09:33:41 -08001375template <typename TraitsType>
1376void InstImpl<TraitsType>::InstX86Shrd::dump(const Cfg *Func) const {
John Porto921856d2015-07-07 11:56:26 -07001377 if (!BuildDefs::dump())
1378 return;
1379 Ostream &Str = Func->getContext()->getStrDump();
1380 this->dumpDest(Func);
1381 Str << " = shrd." << this->getDest()->getType() << " ";
1382 this->dumpSources(Func);
1383}
1384
John Porto4a566862016-01-04 09:33:41 -08001385template <typename TraitsType>
1386void InstImpl<TraitsType>::InstX86Cmov::emit(const Cfg *Func) const {
John Porto921856d2015-07-07 11:56:26 -07001387 if (!BuildDefs::dump())
1388 return;
1389 Ostream &Str = Func->getContext()->getStrEmit();
1390 Variable *Dest = this->getDest();
1391 Str << "\t";
John Porto4a566862016-01-04 09:33:41 -08001392 assert(Condition != Cond::Br_None);
John Porto921856d2015-07-07 11:56:26 -07001393 assert(this->getDest()->hasReg());
John Porto4a566862016-01-04 09:33:41 -08001394 Str << "cmov" << Traits::InstBrAttributes[Condition].DisplayString
John Porto921856d2015-07-07 11:56:26 -07001395 << this->getWidthString(Dest->getType()) << "\t";
1396 this->getSrc(1)->emit(Func);
1397 Str << ", ";
1398 Dest->emit(Func);
1399}
1400
John Porto4a566862016-01-04 09:33:41 -08001401template <typename TraitsType>
1402void InstImpl<TraitsType>::InstX86Cmov::emitIAS(const Cfg *Func) const {
1403 assert(Condition != Cond::Br_None);
John Porto921856d2015-07-07 11:56:26 -07001404 assert(this->getDest()->hasReg());
1405 assert(this->getSrcSize() == 2);
1406 Operand *Src = this->getSrc(1);
1407 Type SrcTy = Src->getType();
John Porto4a566862016-01-04 09:33:41 -08001408 assert(SrcTy == IceType_i16 || SrcTy == IceType_i32 || (Traits::Is64Bit));
1409 Assembler *Asm = Func->getAssembler<Assembler>();
1410 auto *Target = InstX86Base::getTarget(Func);
John Porto921856d2015-07-07 11:56:26 -07001411 if (const auto *SrcVar = llvm::dyn_cast<Variable>(Src)) {
1412 if (SrcVar->hasReg()) {
John Porto4a566862016-01-04 09:33:41 -08001413 Asm->cmov(SrcTy, Condition,
1414 Traits::getEncodedGPR(this->getDest()->getRegNum()),
1415 Traits::getEncodedGPR(SrcVar->getRegNum()));
John Porto921856d2015-07-07 11:56:26 -07001416 } else {
John Porto4a566862016-01-04 09:33:41 -08001417 Asm->cmov(SrcTy, Condition,
1418 Traits::getEncodedGPR(this->getDest()->getRegNum()),
David Sehr21fd1032015-11-13 16:32:37 -08001419 Target->stackVarToAsmOperand(SrcVar));
John Porto921856d2015-07-07 11:56:26 -07001420 }
John Porto4a566862016-01-04 09:33:41 -08001421 } else if (const auto *Mem = llvm::dyn_cast<X86OperandMem>(Src)) {
1422 assert(Mem->getSegmentRegister() == X86OperandMem::DefaultSegment);
1423 Asm->cmov(SrcTy, Condition,
1424 Traits::getEncodedGPR(this->getDest()->getRegNum()),
David Sehr4318a412015-11-11 15:01:55 -08001425 Mem->toAsmAddress(Asm, Target));
John Porto921856d2015-07-07 11:56:26 -07001426 } else {
1427 llvm_unreachable("Unexpected operand type");
1428 }
1429}
1430
John Porto4a566862016-01-04 09:33:41 -08001431template <typename TraitsType>
1432void InstImpl<TraitsType>::InstX86Cmov::dump(const Cfg *Func) const {
John Porto921856d2015-07-07 11:56:26 -07001433 if (!BuildDefs::dump())
1434 return;
1435 Ostream &Str = Func->getContext()->getStrDump();
John Porto4a566862016-01-04 09:33:41 -08001436 Str << "cmov" << Traits::InstBrAttributes[Condition].DisplayString << ".";
John Porto921856d2015-07-07 11:56:26 -07001437 Str << this->getDest()->getType() << " ";
1438 this->dumpDest(Func);
1439 Str << ", ";
1440 this->dumpSources(Func);
1441}
1442
John Porto4a566862016-01-04 09:33:41 -08001443template <typename TraitsType>
1444void InstImpl<TraitsType>::InstX86Cmpps::emit(const Cfg *Func) const {
John Porto921856d2015-07-07 11:56:26 -07001445 if (!BuildDefs::dump())
1446 return;
1447 Ostream &Str = Func->getContext()->getStrEmit();
1448 assert(this->getSrcSize() == 2);
John Porto4a566862016-01-04 09:33:41 -08001449 assert(Condition < Cond::Cmpps_Invalid);
David Sehre3984282015-12-15 17:34:55 -08001450 Type DestTy = this->Dest->getType();
Jim Stichnoth6106df82015-12-16 06:17:58 -08001451 Str << "\t"
John Porto4a566862016-01-04 09:33:41 -08001452 "cmp" << Traits::InstCmppsAttributes[Condition].EmitString
1453 << Traits::TypeAttributes[DestTy].PdPsString << "\t";
John Porto921856d2015-07-07 11:56:26 -07001454 this->getSrc(1)->emit(Func);
1455 Str << ", ";
1456 this->getDest()->emit(Func);
1457}
1458
John Porto4a566862016-01-04 09:33:41 -08001459template <typename TraitsType>
1460void InstImpl<TraitsType>::InstX86Cmpps::emitIAS(const Cfg *Func) const {
1461 Assembler *Asm = Func->getAssembler<Assembler>();
John Porto921856d2015-07-07 11:56:26 -07001462 assert(this->getSrcSize() == 2);
John Porto4a566862016-01-04 09:33:41 -08001463 assert(Condition < Cond::Cmpps_Invalid);
Andrew Scull57e12682015-09-16 11:30:19 -07001464 // Assuming there isn't any load folding for cmpps, and vector constants are
1465 // not allowed in PNaCl.
John Porto921856d2015-07-07 11:56:26 -07001466 assert(llvm::isa<Variable>(this->getSrc(1)));
John Porto4a566862016-01-04 09:33:41 -08001467 auto *Target = InstX86Base::getTarget(Func);
Jim Stichnoth5bff61c2015-10-28 09:26:00 -07001468 const auto *SrcVar = llvm::cast<Variable>(this->getSrc(1));
John Porto921856d2015-07-07 11:56:26 -07001469 if (SrcVar->hasReg()) {
David Sehre3984282015-12-15 17:34:55 -08001470 Asm->cmpps(this->getDest()->getType(),
John Porto4a566862016-01-04 09:33:41 -08001471 Traits::getEncodedXmm(this->getDest()->getRegNum()),
1472 Traits::getEncodedXmm(SrcVar->getRegNum()), Condition);
John Porto921856d2015-07-07 11:56:26 -07001473 } else {
John Porto4a566862016-01-04 09:33:41 -08001474 Address SrcStackAddr = Target->stackVarToAsmOperand(SrcVar);
David Sehre3984282015-12-15 17:34:55 -08001475 Asm->cmpps(this->getDest()->getType(),
John Porto4a566862016-01-04 09:33:41 -08001476 Traits::getEncodedXmm(this->getDest()->getRegNum()),
John Porto921856d2015-07-07 11:56:26 -07001477 SrcStackAddr, Condition);
1478 }
1479}
1480
John Porto4a566862016-01-04 09:33:41 -08001481template <typename TraitsType>
1482void InstImpl<TraitsType>::InstX86Cmpps::dump(const Cfg *Func) const {
John Porto921856d2015-07-07 11:56:26 -07001483 if (!BuildDefs::dump())
1484 return;
1485 Ostream &Str = Func->getContext()->getStrDump();
John Porto4a566862016-01-04 09:33:41 -08001486 assert(Condition < Cond::Cmpps_Invalid);
John Porto921856d2015-07-07 11:56:26 -07001487 this->dumpDest(Func);
John Porto4a566862016-01-04 09:33:41 -08001488 Str << " = cmp" << Traits::InstCmppsAttributes[Condition].EmitString << "ps"
1489 "\t";
John Porto921856d2015-07-07 11:56:26 -07001490 this->dumpSources(Func);
1491}
1492
John Porto4a566862016-01-04 09:33:41 -08001493template <typename TraitsType>
1494void InstImpl<TraitsType>::InstX86Cmpxchg::emit(const Cfg *Func) const {
John Porto921856d2015-07-07 11:56:26 -07001495 if (!BuildDefs::dump())
1496 return;
1497 Ostream &Str = Func->getContext()->getStrEmit();
1498 assert(this->getSrcSize() == 3);
1499 if (this->Locked) {
Jim Stichnoth6106df82015-12-16 06:17:58 -08001500 Str << "\t"
1501 "lock";
John Porto921856d2015-07-07 11:56:26 -07001502 }
Jim Stichnoth6106df82015-12-16 06:17:58 -08001503 Str << "\t"
1504 "cmpxchg" << this->getWidthString(this->getSrc(0)->getType()) << "\t";
John Porto921856d2015-07-07 11:56:26 -07001505 this->getSrc(2)->emit(Func);
1506 Str << ", ";
1507 this->getSrc(0)->emit(Func);
1508}
1509
John Porto4a566862016-01-04 09:33:41 -08001510template <typename TraitsType>
1511void InstImpl<TraitsType>::InstX86Cmpxchg::emitIAS(const Cfg *Func) const {
John Porto921856d2015-07-07 11:56:26 -07001512 assert(this->getSrcSize() == 3);
John Porto4a566862016-01-04 09:33:41 -08001513 Assembler *Asm = Func->getAssembler<Assembler>();
John Porto921856d2015-07-07 11:56:26 -07001514 Type Ty = this->getSrc(0)->getType();
John Porto4a566862016-01-04 09:33:41 -08001515 auto *Target = InstX86Base::getTarget(Func);
1516 const auto Mem = llvm::cast<X86OperandMem>(this->getSrc(0));
1517 assert(Mem->getSegmentRegister() == X86OperandMem::DefaultSegment);
1518 const Address Addr = Mem->toAsmAddress(Asm, Target);
Jim Stichnoth5bff61c2015-10-28 09:26:00 -07001519 const auto *VarReg = llvm::cast<Variable>(this->getSrc(2));
John Porto921856d2015-07-07 11:56:26 -07001520 assert(VarReg->hasReg());
John Porto4a566862016-01-04 09:33:41 -08001521 const GPRRegister Reg = Traits::getEncodedGPR(VarReg->getRegNum());
John Porto921856d2015-07-07 11:56:26 -07001522 Asm->cmpxchg(Ty, Addr, Reg, this->Locked);
1523}
1524
John Porto4a566862016-01-04 09:33:41 -08001525template <typename TraitsType>
1526void InstImpl<TraitsType>::InstX86Cmpxchg::dump(const Cfg *Func) const {
John Porto921856d2015-07-07 11:56:26 -07001527 if (!BuildDefs::dump())
1528 return;
1529 Ostream &Str = Func->getContext()->getStrDump();
1530 if (this->Locked) {
1531 Str << "lock ";
1532 }
1533 Str << "cmpxchg." << this->getSrc(0)->getType() << " ";
1534 this->dumpSources(Func);
1535}
1536
John Porto4a566862016-01-04 09:33:41 -08001537template <typename TraitsType>
1538void InstImpl<TraitsType>::InstX86Cmpxchg8b::emit(const Cfg *Func) const {
John Porto921856d2015-07-07 11:56:26 -07001539 if (!BuildDefs::dump())
1540 return;
1541 Ostream &Str = Func->getContext()->getStrEmit();
1542 assert(this->getSrcSize() == 5);
1543 if (this->Locked) {
Jim Stichnoth6106df82015-12-16 06:17:58 -08001544 Str << "\t"
1545 "lock";
John Porto921856d2015-07-07 11:56:26 -07001546 }
Jim Stichnoth6106df82015-12-16 06:17:58 -08001547 Str << "\t"
1548 "cmpxchg8b\t";
John Porto921856d2015-07-07 11:56:26 -07001549 this->getSrc(0)->emit(Func);
1550}
1551
John Porto4a566862016-01-04 09:33:41 -08001552template <typename TraitsType>
1553void InstImpl<TraitsType>::InstX86Cmpxchg8b::emitIAS(const Cfg *Func) const {
John Porto921856d2015-07-07 11:56:26 -07001554 assert(this->getSrcSize() == 5);
John Porto4a566862016-01-04 09:33:41 -08001555 Assembler *Asm = Func->getAssembler<Assembler>();
1556 const auto Mem = llvm::cast<X86OperandMem>(this->getSrc(0));
1557 assert(Mem->getSegmentRegister() == X86OperandMem::DefaultSegment);
1558 auto *Target = InstX86Base::getTarget(Func);
1559 const Address Addr = Mem->toAsmAddress(Asm, Target);
John Porto921856d2015-07-07 11:56:26 -07001560 Asm->cmpxchg8b(Addr, this->Locked);
1561}
1562
John Porto4a566862016-01-04 09:33:41 -08001563template <typename TraitsType>
1564void InstImpl<TraitsType>::InstX86Cmpxchg8b::dump(const Cfg *Func) const {
John Porto921856d2015-07-07 11:56:26 -07001565 if (!BuildDefs::dump())
1566 return;
1567 Ostream &Str = Func->getContext()->getStrDump();
1568 if (this->Locked) {
1569 Str << "lock ";
1570 }
1571 Str << "cmpxchg8b ";
1572 this->dumpSources(Func);
1573}
1574
John Porto4a566862016-01-04 09:33:41 -08001575template <typename TraitsType>
1576void InstImpl<TraitsType>::InstX86Cvt::emit(const Cfg *Func) const {
John Porto921856d2015-07-07 11:56:26 -07001577 if (!BuildDefs::dump())
1578 return;
1579 Ostream &Str = Func->getContext()->getStrEmit();
1580 assert(this->getSrcSize() == 1);
Jim Stichnoth6106df82015-12-16 06:17:58 -08001581 Str << "\t"
1582 "cvt";
John Porto921856d2015-07-07 11:56:26 -07001583 if (isTruncating())
1584 Str << "t";
John Porto4a566862016-01-04 09:33:41 -08001585 Str << Traits::TypeAttributes[this->getSrc(0)->getType()].CvtString << "2"
1586 << Traits::TypeAttributes[this->getDest()->getType()].CvtString << "\t";
John Porto921856d2015-07-07 11:56:26 -07001587 this->getSrc(0)->emit(Func);
1588 Str << ", ";
1589 this->getDest()->emit(Func);
1590}
1591
John Porto4a566862016-01-04 09:33:41 -08001592template <typename TraitsType>
1593void InstImpl<TraitsType>::InstX86Cvt::emitIAS(const Cfg *Func) const {
John Porto921856d2015-07-07 11:56:26 -07001594 assert(this->getSrcSize() == 1);
1595 const Variable *Dest = this->getDest();
1596 const Operand *Src = this->getSrc(0);
1597 Type DestTy = Dest->getType();
1598 Type SrcTy = Src->getType();
1599 switch (Variant) {
1600 case Si2ss: {
1601 assert(isScalarIntegerType(SrcTy));
John Porto4a566862016-01-04 09:33:41 -08001602 if (!Traits::Is64Bit) {
John Porto1d235422015-08-12 12:37:53 -07001603 assert(typeWidthInBytes(SrcTy) <= 4);
1604 } else {
1605 assert(SrcTy == IceType_i32 || SrcTy == IceType_i64);
1606 }
John Porto921856d2015-07-07 11:56:26 -07001607 assert(isScalarFloatingType(DestTy));
John Porto4a566862016-01-04 09:33:41 -08001608 static const CastEmitterRegOp<XmmRegister, GPRRegister> Emitter = {
1609 &Assembler::cvtsi2ss, &Assembler::cvtsi2ss};
1610 emitIASCastRegOp<XmmRegister, GPRRegister, Traits::getEncodedXmm,
1611 Traits::getEncodedGPR>(Func, DestTy, Dest, SrcTy, Src,
1612 Emitter);
John Porto921856d2015-07-07 11:56:26 -07001613 return;
1614 }
1615 case Tss2si: {
1616 assert(isScalarFloatingType(SrcTy));
1617 assert(isScalarIntegerType(DestTy));
John Porto4a566862016-01-04 09:33:41 -08001618 if (!Traits::Is64Bit) {
John Porto1d235422015-08-12 12:37:53 -07001619 assert(typeWidthInBytes(DestTy) <= 4);
1620 } else {
1621 assert(DestTy == IceType_i32 || DestTy == IceType_i64);
1622 }
John Porto4a566862016-01-04 09:33:41 -08001623 static const CastEmitterRegOp<GPRRegister, XmmRegister> Emitter = {
1624 &Assembler::cvttss2si, &Assembler::cvttss2si};
1625 emitIASCastRegOp<GPRRegister, XmmRegister, Traits::getEncodedGPR,
1626 Traits::getEncodedXmm>(Func, DestTy, Dest, SrcTy, Src,
1627 Emitter);
John Porto921856d2015-07-07 11:56:26 -07001628 return;
1629 }
1630 case Float2float: {
1631 assert(isScalarFloatingType(SrcTy));
1632 assert(isScalarFloatingType(DestTy));
1633 assert(DestTy != SrcTy);
John Porto4a566862016-01-04 09:33:41 -08001634 static const XmmEmitterRegOp Emitter = {&Assembler::cvtfloat2float,
1635 &Assembler::cvtfloat2float};
1636 emitIASRegOpTyXMM(Func, SrcTy, Dest, Src, Emitter);
John Porto921856d2015-07-07 11:56:26 -07001637 return;
1638 }
1639 case Dq2ps: {
1640 assert(isVectorIntegerType(SrcTy));
1641 assert(isVectorFloatingType(DestTy));
John Porto4a566862016-01-04 09:33:41 -08001642 static const XmmEmitterRegOp Emitter = {&Assembler::cvtdq2ps,
1643 &Assembler::cvtdq2ps};
1644 emitIASRegOpTyXMM(Func, DestTy, Dest, Src, Emitter);
John Porto921856d2015-07-07 11:56:26 -07001645 return;
1646 }
1647 case Tps2dq: {
1648 assert(isVectorFloatingType(SrcTy));
1649 assert(isVectorIntegerType(DestTy));
John Porto4a566862016-01-04 09:33:41 -08001650 static const XmmEmitterRegOp Emitter = {&Assembler::cvttps2dq,
1651 &Assembler::cvttps2dq};
1652 emitIASRegOpTyXMM(Func, DestTy, Dest, Src, Emitter);
John Porto921856d2015-07-07 11:56:26 -07001653 return;
1654 }
1655 }
1656}
1657
John Porto4a566862016-01-04 09:33:41 -08001658template <typename TraitsType>
1659void InstImpl<TraitsType>::InstX86Cvt::dump(const Cfg *Func) const {
John Porto921856d2015-07-07 11:56:26 -07001660 if (!BuildDefs::dump())
1661 return;
1662 Ostream &Str = Func->getContext()->getStrDump();
1663 this->dumpDest(Func);
1664 Str << " = cvt";
1665 if (isTruncating())
1666 Str << "t";
John Porto4a566862016-01-04 09:33:41 -08001667 Str << Traits::TypeAttributes[this->getSrc(0)->getType()].CvtString << "2"
1668 << Traits::TypeAttributes[this->getDest()->getType()].CvtString << " ";
John Porto921856d2015-07-07 11:56:26 -07001669 this->dumpSources(Func);
1670}
1671
John Porto4a566862016-01-04 09:33:41 -08001672template <typename TraitsType>
1673void InstImpl<TraitsType>::InstX86Icmp::emit(const Cfg *Func) const {
John Porto921856d2015-07-07 11:56:26 -07001674 if (!BuildDefs::dump())
1675 return;
1676 Ostream &Str = Func->getContext()->getStrEmit();
1677 assert(this->getSrcSize() == 2);
Jim Stichnoth6106df82015-12-16 06:17:58 -08001678 Str << "\t"
1679 "cmp" << this->getWidthString(this->getSrc(0)->getType()) << "\t";
John Porto921856d2015-07-07 11:56:26 -07001680 this->getSrc(1)->emit(Func);
1681 Str << ", ";
1682 this->getSrc(0)->emit(Func);
1683}
1684
John Porto4a566862016-01-04 09:33:41 -08001685template <typename TraitsType>
1686void InstImpl<TraitsType>::InstX86Icmp::emitIAS(const Cfg *Func) const {
John Porto921856d2015-07-07 11:56:26 -07001687 assert(this->getSrcSize() == 2);
1688 const Operand *Src0 = this->getSrc(0);
1689 const Operand *Src1 = this->getSrc(1);
1690 Type Ty = Src0->getType();
John Porto4a566862016-01-04 09:33:41 -08001691 static const GPREmitterRegOp RegEmitter = {&Assembler::cmp, &Assembler::cmp,
1692 &Assembler::cmp};
1693 static const GPREmitterAddrOp AddrEmitter = {&Assembler::cmp,
1694 &Assembler::cmp};
Jim Stichnoth5bff61c2015-10-28 09:26:00 -07001695 if (const auto *SrcVar0 = llvm::dyn_cast<Variable>(Src0)) {
John Porto921856d2015-07-07 11:56:26 -07001696 if (SrcVar0->hasReg()) {
John Porto56958cb2016-01-14 09:18:18 -08001697 constexpr bool NotLea = false;
1698 emitIASRegOpTyGPR(Func, NotLea, Ty, SrcVar0, Src1, RegEmitter);
John Porto921856d2015-07-07 11:56:26 -07001699 return;
1700 }
1701 }
John Porto4a566862016-01-04 09:33:41 -08001702 emitIASAsAddrOpTyGPR(Func, Ty, Src0, Src1, AddrEmitter);
John Porto921856d2015-07-07 11:56:26 -07001703}
1704
John Porto4a566862016-01-04 09:33:41 -08001705template <typename TraitsType>
1706void InstImpl<TraitsType>::InstX86Icmp::dump(const Cfg *Func) const {
John Porto921856d2015-07-07 11:56:26 -07001707 if (!BuildDefs::dump())
1708 return;
1709 Ostream &Str = Func->getContext()->getStrDump();
1710 Str << "cmp." << this->getSrc(0)->getType() << " ";
1711 this->dumpSources(Func);
1712}
1713
John Porto4a566862016-01-04 09:33:41 -08001714template <typename TraitsType>
1715void InstImpl<TraitsType>::InstX86Ucomiss::emit(const Cfg *Func) const {
John Porto921856d2015-07-07 11:56:26 -07001716 if (!BuildDefs::dump())
1717 return;
1718 Ostream &Str = Func->getContext()->getStrEmit();
1719 assert(this->getSrcSize() == 2);
Jim Stichnoth6106df82015-12-16 06:17:58 -08001720 Str << "\t"
1721 "ucomi"
John Porto4a566862016-01-04 09:33:41 -08001722 << Traits::TypeAttributes[this->getSrc(0)->getType()].SdSsString << "\t";
John Porto921856d2015-07-07 11:56:26 -07001723 this->getSrc(1)->emit(Func);
1724 Str << ", ";
1725 this->getSrc(0)->emit(Func);
1726}
1727
John Porto4a566862016-01-04 09:33:41 -08001728template <typename TraitsType>
1729void InstImpl<TraitsType>::InstX86Ucomiss::emitIAS(const Cfg *Func) const {
John Porto921856d2015-07-07 11:56:26 -07001730 assert(this->getSrcSize() == 2);
Andrew Scull57e12682015-09-16 11:30:19 -07001731 // Currently src0 is always a variable by convention, to avoid having two
1732 // memory operands.
John Porto921856d2015-07-07 11:56:26 -07001733 assert(llvm::isa<Variable>(this->getSrc(0)));
Jim Stichnoth5bff61c2015-10-28 09:26:00 -07001734 const auto *Src0Var = llvm::cast<Variable>(this->getSrc(0));
John Porto921856d2015-07-07 11:56:26 -07001735 Type Ty = Src0Var->getType();
John Porto4a566862016-01-04 09:33:41 -08001736 static const XmmEmitterRegOp Emitter = {&Assembler::ucomiss,
1737 &Assembler::ucomiss};
1738 emitIASRegOpTyXMM(Func, Ty, Src0Var, this->getSrc(1), Emitter);
John Porto921856d2015-07-07 11:56:26 -07001739}
1740
John Porto4a566862016-01-04 09:33:41 -08001741template <typename TraitsType>
1742void InstImpl<TraitsType>::InstX86Ucomiss::dump(const Cfg *Func) const {
John Porto921856d2015-07-07 11:56:26 -07001743 if (!BuildDefs::dump())
1744 return;
1745 Ostream &Str = Func->getContext()->getStrDump();
1746 Str << "ucomiss." << this->getSrc(0)->getType() << " ";
1747 this->dumpSources(Func);
1748}
1749
John Porto4a566862016-01-04 09:33:41 -08001750template <typename TraitsType>
1751void InstImpl<TraitsType>::InstX86UD2::emit(const Cfg *Func) const {
John Porto921856d2015-07-07 11:56:26 -07001752 if (!BuildDefs::dump())
1753 return;
1754 Ostream &Str = Func->getContext()->getStrEmit();
1755 assert(this->getSrcSize() == 0);
Jim Stichnoth6106df82015-12-16 06:17:58 -08001756 Str << "\t"
1757 "ud2";
John Porto921856d2015-07-07 11:56:26 -07001758}
1759
John Porto4a566862016-01-04 09:33:41 -08001760template <typename TraitsType>
1761void InstImpl<TraitsType>::InstX86UD2::emitIAS(const Cfg *Func) const {
1762 Assembler *Asm = Func->getAssembler<Assembler>();
John Porto921856d2015-07-07 11:56:26 -07001763 Asm->ud2();
1764}
1765
John Porto4a566862016-01-04 09:33:41 -08001766template <typename TraitsType>
1767void InstImpl<TraitsType>::InstX86UD2::dump(const Cfg *Func) const {
John Porto921856d2015-07-07 11:56:26 -07001768 if (!BuildDefs::dump())
1769 return;
1770 Ostream &Str = Func->getContext()->getStrDump();
1771 Str << "ud2";
1772}
1773
John Porto4a566862016-01-04 09:33:41 -08001774template <typename TraitsType>
1775void InstImpl<TraitsType>::InstX86Test::emit(const Cfg *Func) const {
John Porto921856d2015-07-07 11:56:26 -07001776 if (!BuildDefs::dump())
1777 return;
1778 Ostream &Str = Func->getContext()->getStrEmit();
1779 assert(this->getSrcSize() == 2);
Jim Stichnoth6106df82015-12-16 06:17:58 -08001780 Str << "\t"
1781 "test" << this->getWidthString(this->getSrc(0)->getType()) << "\t";
John Porto921856d2015-07-07 11:56:26 -07001782 this->getSrc(1)->emit(Func);
1783 Str << ", ";
1784 this->getSrc(0)->emit(Func);
1785}
1786
John Porto4a566862016-01-04 09:33:41 -08001787template <typename TraitsType>
1788void InstImpl<TraitsType>::InstX86Test::emitIAS(const Cfg *Func) const {
John Porto921856d2015-07-07 11:56:26 -07001789 assert(this->getSrcSize() == 2);
1790 const Operand *Src0 = this->getSrc(0);
1791 const Operand *Src1 = this->getSrc(1);
1792 Type Ty = Src0->getType();
1793 // The Reg/Addr form of test is not encodeable.
John Porto4a566862016-01-04 09:33:41 -08001794 static const GPREmitterRegOp RegEmitter = {&Assembler::test, nullptr,
1795 &Assembler::test};
1796 static const GPREmitterAddrOp AddrEmitter = {&Assembler::test,
1797 &Assembler::test};
Jim Stichnoth5bff61c2015-10-28 09:26:00 -07001798 if (const auto *SrcVar0 = llvm::dyn_cast<Variable>(Src0)) {
John Porto921856d2015-07-07 11:56:26 -07001799 if (SrcVar0->hasReg()) {
John Porto56958cb2016-01-14 09:18:18 -08001800 constexpr bool NotLea = false;
1801 emitIASRegOpTyGPR(Func, NotLea, Ty, SrcVar0, Src1, RegEmitter);
John Porto921856d2015-07-07 11:56:26 -07001802 return;
1803 }
1804 }
John Porto4a566862016-01-04 09:33:41 -08001805 emitIASAsAddrOpTyGPR(Func, Ty, Src0, Src1, AddrEmitter);
John Porto921856d2015-07-07 11:56:26 -07001806}
1807
John Porto4a566862016-01-04 09:33:41 -08001808template <typename TraitsType>
1809void InstImpl<TraitsType>::InstX86Test::dump(const Cfg *Func) const {
John Porto921856d2015-07-07 11:56:26 -07001810 if (!BuildDefs::dump())
1811 return;
1812 Ostream &Str = Func->getContext()->getStrDump();
1813 Str << "test." << this->getSrc(0)->getType() << " ";
1814 this->dumpSources(Func);
1815}
1816
John Porto4a566862016-01-04 09:33:41 -08001817template <typename TraitsType>
1818void InstImpl<TraitsType>::InstX86Mfence::emit(const Cfg *Func) const {
John Porto921856d2015-07-07 11:56:26 -07001819 if (!BuildDefs::dump())
1820 return;
1821 Ostream &Str = Func->getContext()->getStrEmit();
1822 assert(this->getSrcSize() == 0);
Jim Stichnoth6106df82015-12-16 06:17:58 -08001823 Str << "\t"
1824 "mfence";
John Porto921856d2015-07-07 11:56:26 -07001825}
1826
John Porto4a566862016-01-04 09:33:41 -08001827template <typename TraitsType>
1828void InstImpl<TraitsType>::InstX86Mfence::emitIAS(const Cfg *Func) const {
1829 Assembler *Asm = Func->getAssembler<Assembler>();
John Porto921856d2015-07-07 11:56:26 -07001830 Asm->mfence();
1831}
1832
John Porto4a566862016-01-04 09:33:41 -08001833template <typename TraitsType>
1834void InstImpl<TraitsType>::InstX86Mfence::dump(const Cfg *Func) const {
John Porto921856d2015-07-07 11:56:26 -07001835 if (!BuildDefs::dump())
1836 return;
1837 Ostream &Str = Func->getContext()->getStrDump();
1838 Str << "mfence";
1839}
1840
John Porto4a566862016-01-04 09:33:41 -08001841template <typename TraitsType>
1842void InstImpl<TraitsType>::InstX86Store::emit(const Cfg *Func) const {
John Porto921856d2015-07-07 11:56:26 -07001843 if (!BuildDefs::dump())
1844 return;
1845 Ostream &Str = Func->getContext()->getStrEmit();
1846 assert(this->getSrcSize() == 2);
1847 Type Ty = this->getSrc(0)->getType();
Jim Stichnoth6106df82015-12-16 06:17:58 -08001848 Str << "\t"
1849 "mov" << this->getWidthString(Ty)
John Porto4a566862016-01-04 09:33:41 -08001850 << Traits::TypeAttributes[Ty].SdSsString << "\t";
John Porto921856d2015-07-07 11:56:26 -07001851 this->getSrc(0)->emit(Func);
1852 Str << ", ";
1853 this->getSrc(1)->emit(Func);
1854}
1855
John Porto4a566862016-01-04 09:33:41 -08001856template <typename TraitsType>
1857void InstImpl<TraitsType>::InstX86Store::emitIAS(const Cfg *Func) const {
John Porto921856d2015-07-07 11:56:26 -07001858 assert(this->getSrcSize() == 2);
1859 const Operand *Dest = this->getSrc(1);
1860 const Operand *Src = this->getSrc(0);
1861 Type DestTy = Dest->getType();
1862 if (isScalarFloatingType(DestTy)) {
1863 // Src must be a register, since Dest is a Mem operand of some kind.
Jim Stichnoth5bff61c2015-10-28 09:26:00 -07001864 const auto *SrcVar = llvm::cast<Variable>(Src);
John Porto921856d2015-07-07 11:56:26 -07001865 assert(SrcVar->hasReg());
John Porto4a566862016-01-04 09:33:41 -08001866 XmmRegister SrcReg = Traits::getEncodedXmm(SrcVar->getRegNum());
1867 Assembler *Asm = Func->getAssembler<Assembler>();
1868 auto *Target = InstX86Base::getTarget(Func);
Jim Stichnoth5bff61c2015-10-28 09:26:00 -07001869 if (const auto *DestVar = llvm::dyn_cast<Variable>(Dest)) {
John Porto921856d2015-07-07 11:56:26 -07001870 assert(!DestVar->hasReg());
John Porto4a566862016-01-04 09:33:41 -08001871 Address StackAddr(Target->stackVarToAsmOperand(DestVar));
John Porto921856d2015-07-07 11:56:26 -07001872 Asm->movss(DestTy, StackAddr, SrcReg);
1873 } else {
John Porto4a566862016-01-04 09:33:41 -08001874 const auto DestMem = llvm::cast<X86OperandMem>(Dest);
1875 assert(DestMem->getSegmentRegister() == X86OperandMem::DefaultSegment);
David Sehr4318a412015-11-11 15:01:55 -08001876 Asm->movss(DestTy, DestMem->toAsmAddress(Asm, Target), SrcReg);
John Porto921856d2015-07-07 11:56:26 -07001877 }
1878 return;
1879 } else {
1880 assert(isScalarIntegerType(DestTy));
John Porto4a566862016-01-04 09:33:41 -08001881 static const GPREmitterAddrOp GPRAddrEmitter = {&Assembler::mov,
1882 &Assembler::mov};
1883 emitIASAsAddrOpTyGPR(Func, DestTy, Dest, Src, GPRAddrEmitter);
John Porto921856d2015-07-07 11:56:26 -07001884 }
1885}
1886
John Porto4a566862016-01-04 09:33:41 -08001887template <typename TraitsType>
1888void InstImpl<TraitsType>::InstX86Store::dump(const Cfg *Func) const {
John Porto921856d2015-07-07 11:56:26 -07001889 if (!BuildDefs::dump())
1890 return;
1891 Ostream &Str = Func->getContext()->getStrDump();
1892 Str << "mov." << this->getSrc(0)->getType() << " ";
1893 this->getSrc(1)->dump(Func);
1894 Str << ", ";
1895 this->getSrc(0)->dump(Func);
1896}
1897
John Porto4a566862016-01-04 09:33:41 -08001898template <typename TraitsType>
1899void InstImpl<TraitsType>::InstX86StoreP::emit(const Cfg *Func) const {
John Porto921856d2015-07-07 11:56:26 -07001900 if (!BuildDefs::dump())
1901 return;
1902 Ostream &Str = Func->getContext()->getStrEmit();
1903 assert(this->getSrcSize() == 2);
Andrew Scull713dbde2015-08-04 14:25:27 -07001904 assert(isVectorType(this->getSrc(1)->getType()));
Jim Stichnoth6106df82015-12-16 06:17:58 -08001905 Str << "\t"
1906 "movups\t";
John Porto921856d2015-07-07 11:56:26 -07001907 this->getSrc(0)->emit(Func);
1908 Str << ", ";
1909 this->getSrc(1)->emit(Func);
1910}
1911
John Porto4a566862016-01-04 09:33:41 -08001912template <typename TraitsType>
1913void InstImpl<TraitsType>::InstX86StoreP::emitIAS(const Cfg *Func) const {
1914 Assembler *Asm = Func->getAssembler<Assembler>();
John Porto921856d2015-07-07 11:56:26 -07001915 assert(this->getSrcSize() == 2);
Jim Stichnoth5bff61c2015-10-28 09:26:00 -07001916 const auto *SrcVar = llvm::cast<Variable>(this->getSrc(0));
John Porto4a566862016-01-04 09:33:41 -08001917 const auto DestMem = llvm::cast<X86OperandMem>(this->getSrc(1));
1918 assert(DestMem->getSegmentRegister() == X86OperandMem::DefaultSegment);
John Porto921856d2015-07-07 11:56:26 -07001919 assert(SrcVar->hasReg());
John Porto4a566862016-01-04 09:33:41 -08001920 auto *Target = InstX86Base::getTarget(Func);
David Sehr4318a412015-11-11 15:01:55 -08001921 Asm->movups(DestMem->toAsmAddress(Asm, Target),
John Porto4a566862016-01-04 09:33:41 -08001922 Traits::getEncodedXmm(SrcVar->getRegNum()));
John Porto921856d2015-07-07 11:56:26 -07001923}
1924
John Porto4a566862016-01-04 09:33:41 -08001925template <typename TraitsType>
1926void InstImpl<TraitsType>::InstX86StoreP::dump(const Cfg *Func) const {
John Porto921856d2015-07-07 11:56:26 -07001927 if (!BuildDefs::dump())
1928 return;
1929 Ostream &Str = Func->getContext()->getStrDump();
1930 Str << "storep." << this->getSrc(0)->getType() << " ";
1931 this->getSrc(1)->dump(Func);
1932 Str << ", ";
1933 this->getSrc(0)->dump(Func);
1934}
1935
John Porto4a566862016-01-04 09:33:41 -08001936template <typename TraitsType>
1937void InstImpl<TraitsType>::InstX86StoreQ::emit(const Cfg *Func) const {
John Porto921856d2015-07-07 11:56:26 -07001938 if (!BuildDefs::dump())
1939 return;
1940 Ostream &Str = Func->getContext()->getStrEmit();
1941 assert(this->getSrcSize() == 2);
1942 assert(this->getSrc(1)->getType() == IceType_i64 ||
Andrew Scull713dbde2015-08-04 14:25:27 -07001943 this->getSrc(1)->getType() == IceType_f64 ||
1944 isVectorType(this->getSrc(1)->getType()));
Jim Stichnoth6106df82015-12-16 06:17:58 -08001945 Str << "\t"
1946 "movq\t";
John Porto921856d2015-07-07 11:56:26 -07001947 this->getSrc(0)->emit(Func);
1948 Str << ", ";
1949 this->getSrc(1)->emit(Func);
1950}
1951
John Porto4a566862016-01-04 09:33:41 -08001952template <typename TraitsType>
1953void InstImpl<TraitsType>::InstX86StoreQ::emitIAS(const Cfg *Func) const {
1954 Assembler *Asm = Func->getAssembler<Assembler>();
John Porto921856d2015-07-07 11:56:26 -07001955 assert(this->getSrcSize() == 2);
Jim Stichnoth5bff61c2015-10-28 09:26:00 -07001956 const auto *SrcVar = llvm::cast<Variable>(this->getSrc(0));
John Porto4a566862016-01-04 09:33:41 -08001957 const auto DestMem = llvm::cast<X86OperandMem>(this->getSrc(1));
1958 assert(DestMem->getSegmentRegister() == X86OperandMem::DefaultSegment);
John Porto921856d2015-07-07 11:56:26 -07001959 assert(SrcVar->hasReg());
John Porto4a566862016-01-04 09:33:41 -08001960 auto *Target = InstX86Base::getTarget(Func);
David Sehr4318a412015-11-11 15:01:55 -08001961 Asm->movq(DestMem->toAsmAddress(Asm, Target),
John Porto4a566862016-01-04 09:33:41 -08001962 Traits::getEncodedXmm(SrcVar->getRegNum()));
John Porto921856d2015-07-07 11:56:26 -07001963}
1964
John Porto4a566862016-01-04 09:33:41 -08001965template <typename TraitsType>
1966void InstImpl<TraitsType>::InstX86StoreQ::dump(const Cfg *Func) const {
John Porto921856d2015-07-07 11:56:26 -07001967 if (!BuildDefs::dump())
1968 return;
1969 Ostream &Str = Func->getContext()->getStrDump();
1970 Str << "storeq." << this->getSrc(0)->getType() << " ";
1971 this->getSrc(1)->dump(Func);
1972 Str << ", ";
1973 this->getSrc(0)->dump(Func);
1974}
1975
John Porto4a566862016-01-04 09:33:41 -08001976template <typename TraitsType>
1977void InstImpl<TraitsType>::InstX86Lea::emit(const Cfg *Func) const {
John Porto921856d2015-07-07 11:56:26 -07001978 if (!BuildDefs::dump())
1979 return;
1980 Ostream &Str = Func->getContext()->getStrEmit();
1981 assert(this->getSrcSize() == 1);
1982 assert(this->getDest()->hasReg());
Jim Stichnoth6106df82015-12-16 06:17:58 -08001983 Str << "\t"
John Porto56958cb2016-01-14 09:18:18 -08001984 "lea" << this->getWidthString(this->getDest()->getType()) << "\t";
John Porto921856d2015-07-07 11:56:26 -07001985 Operand *Src0 = this->getSrc(0);
Jim Stichnoth5bff61c2015-10-28 09:26:00 -07001986 if (const auto *Src0Var = llvm::dyn_cast<Variable>(Src0)) {
John Porto921856d2015-07-07 11:56:26 -07001987 Type Ty = Src0Var->getType();
1988 // lea on x86-32 doesn't accept mem128 operands, so cast VSrc0 to an
1989 // acceptable type.
Jim Stichnoth8aa39662016-02-10 11:20:30 -08001990 Src0Var->asType(isVectorType(Ty) ? IceType_i32 : Ty, RegNumT::NoRegister)
Jim Stichnoth5bff61c2015-10-28 09:26:00 -07001991 ->emit(Func);
John Porto921856d2015-07-07 11:56:26 -07001992 } else {
1993 Src0->emit(Func);
1994 }
1995 Str << ", ";
1996 this->getDest()->emit(Func);
1997}
1998
John Porto4a566862016-01-04 09:33:41 -08001999template <typename TraitsType>
2000void InstImpl<TraitsType>::InstX86Mov::emit(const Cfg *Func) const {
John Porto921856d2015-07-07 11:56:26 -07002001 if (!BuildDefs::dump())
2002 return;
2003 Ostream &Str = Func->getContext()->getStrEmit();
2004 assert(this->getSrcSize() == 1);
2005 Operand *Src = this->getSrc(0);
2006 Type SrcTy = Src->getType();
2007 Type DestTy = this->getDest()->getType();
John Porto4a566862016-01-04 09:33:41 -08002008 if (Traits::Is64Bit && DestTy == IceType_i64 &&
John Porto008f4ce2015-12-24 13:22:18 -08002009 llvm::isa<ConstantInteger64>(Src)) {
Jim Stichnoth6106df82015-12-16 06:17:58 -08002010 Str << "\t"
John Porto008f4ce2015-12-24 13:22:18 -08002011 "movabs"
2012 "\t";
John Porto1d235422015-08-12 12:37:53 -07002013 } else {
Jim Stichnoth6106df82015-12-16 06:17:58 -08002014 Str << "\t"
2015 "mov" << (!isScalarFloatingType(DestTy)
2016 ? this->getWidthString(DestTy)
John Porto4a566862016-01-04 09:33:41 -08002017 : Traits::TypeAttributes[DestTy].SdSsString) << "\t";
John Porto1d235422015-08-12 12:37:53 -07002018 }
Jim Stichnothc59288b2015-11-09 11:38:40 -08002019 // For an integer truncation operation, src is wider than dest. In this case,
2020 // we use a mov instruction whose data width matches the narrower dest.
Andrew Scull57e12682015-09-16 11:30:19 -07002021 // TODO: This assert disallows usages such as copying a floating
2022 // point value between a vector and a scalar (which movss is used for). Clean
2023 // this up.
John Porto4a566862016-01-04 09:33:41 -08002024 assert(InstX86Base::getTarget(Func)->typeWidthInBytesOnStack(DestTy) ==
2025 InstX86Base::getTarget(Func)->typeWidthInBytesOnStack(SrcTy));
Jim Stichnothc59288b2015-11-09 11:38:40 -08002026 const Operand *NewSrc = Src;
2027 if (auto *SrcVar = llvm::dyn_cast<Variable>(Src)) {
Jim Stichnoth8aa39662016-02-10 11:20:30 -08002028 auto NewRegNum = RegNumT::NoRegister;
Jim Stichnothc59288b2015-11-09 11:38:40 -08002029 if (SrcVar->hasReg())
John Porto4a566862016-01-04 09:33:41 -08002030 NewRegNum = Traits::getGprForType(DestTy, SrcVar->getRegNum());
Jim Stichnothc59288b2015-11-09 11:38:40 -08002031 if (SrcTy != DestTy)
2032 NewSrc = SrcVar->asType(DestTy, NewRegNum);
2033 }
2034 NewSrc->emit(Func);
John Porto921856d2015-07-07 11:56:26 -07002035 Str << ", ";
Jim Stichnothc59288b2015-11-09 11:38:40 -08002036 this->getDest()->emit(Func);
John Porto921856d2015-07-07 11:56:26 -07002037}
2038
John Porto4a566862016-01-04 09:33:41 -08002039template <typename TraitsType>
2040void InstImpl<TraitsType>::InstX86Mov::emitIAS(const Cfg *Func) const {
John Porto921856d2015-07-07 11:56:26 -07002041 assert(this->getSrcSize() == 1);
2042 const Variable *Dest = this->getDest();
2043 const Operand *Src = this->getSrc(0);
2044 Type DestTy = Dest->getType();
2045 Type SrcTy = Src->getType();
2046 // Mov can be used for GPRs or XMM registers. Also, the type does not
Andrew Scull57e12682015-09-16 11:30:19 -07002047 // necessarily match (Mov can be used for bitcasts). However, when the type
2048 // does not match, one of the operands must be a register. Thus, the strategy
2049 // is to find out if Src or Dest are a register, then use that register's
2050 // type to decide on which emitter set to use. The emitter set will include
2051 // reg-reg movs, but that case should be unused when the types don't match.
John Porto4a566862016-01-04 09:33:41 -08002052 static const XmmEmitterRegOp XmmRegEmitter = {&Assembler::movss,
2053 &Assembler::movss};
2054 static const GPREmitterRegOp GPRRegEmitter = {
2055 &Assembler::mov, &Assembler::mov, &Assembler::mov};
2056 static const GPREmitterAddrOp GPRAddrEmitter = {&Assembler::mov,
2057 &Assembler::mov};
Jim Stichnothc59288b2015-11-09 11:38:40 -08002058 // For an integer truncation operation, src is wider than dest. In this case,
2059 // we use a mov instruction whose data width matches the narrower dest.
Andrew Scull57e12682015-09-16 11:30:19 -07002060 // TODO: This assert disallows usages such as copying a floating
2061 // point value between a vector and a scalar (which movss is used for). Clean
2062 // this up.
John Porto4a566862016-01-04 09:33:41 -08002063 auto *Target = InstX86Base::getTarget(Func);
David Sehr4318a412015-11-11 15:01:55 -08002064 assert(Target->typeWidthInBytesOnStack(this->getDest()->getType()) ==
2065 Target->typeWidthInBytesOnStack(Src->getType()));
John Porto921856d2015-07-07 11:56:26 -07002066 if (Dest->hasReg()) {
2067 if (isScalarFloatingType(DestTy)) {
John Porto4a566862016-01-04 09:33:41 -08002068 emitIASRegOpTyXMM(Func, DestTy, Dest, Src, XmmRegEmitter);
John Porto921856d2015-07-07 11:56:26 -07002069 return;
2070 } else {
2071 assert(isScalarIntegerType(DestTy));
2072 // Widen DestTy for truncation (see above note). We should only do this
2073 // when both Src and Dest are integer types.
John Porto4a566862016-01-04 09:33:41 -08002074 if (Traits::Is64Bit && DestTy == IceType_i64) {
John Porto1d235422015-08-12 12:37:53 -07002075 if (const auto *C64 = llvm::dyn_cast<ConstantInteger64>(Src)) {
John Porto4a566862016-01-04 09:33:41 -08002076 Func->getAssembler<Assembler>()->movabs(
2077 Traits::getEncodedGPR(Dest->getRegNum()), C64->getValue());
John Porto008f4ce2015-12-24 13:22:18 -08002078 return;
John Porto1d235422015-08-12 12:37:53 -07002079 }
John Porto1d235422015-08-12 12:37:53 -07002080 }
John Porto921856d2015-07-07 11:56:26 -07002081 if (isScalarIntegerType(SrcTy)) {
Jim Stichnothc59288b2015-11-09 11:38:40 -08002082 SrcTy = DestTy;
John Porto921856d2015-07-07 11:56:26 -07002083 }
John Porto56958cb2016-01-14 09:18:18 -08002084 constexpr bool NotLea = false;
2085 emitIASRegOpTyGPR(Func, NotLea, DestTy, Dest, Src, GPRRegEmitter);
John Porto921856d2015-07-07 11:56:26 -07002086 return;
2087 }
2088 } else {
Andrew Scull57e12682015-09-16 11:30:19 -07002089 // Dest must be Stack and Src *could* be a register. Use Src's type to
2090 // decide on the emitters.
John Porto4a566862016-01-04 09:33:41 -08002091 Address StackAddr(Target->stackVarToAsmOperand(Dest));
John Porto921856d2015-07-07 11:56:26 -07002092 if (isScalarFloatingType(SrcTy)) {
2093 // Src must be a register.
Jim Stichnoth5bff61c2015-10-28 09:26:00 -07002094 const auto *SrcVar = llvm::cast<Variable>(Src);
John Porto921856d2015-07-07 11:56:26 -07002095 assert(SrcVar->hasReg());
John Porto4a566862016-01-04 09:33:41 -08002096 Assembler *Asm = Func->getAssembler<Assembler>();
2097 Asm->movss(SrcTy, StackAddr, Traits::getEncodedXmm(SrcVar->getRegNum()));
John Porto921856d2015-07-07 11:56:26 -07002098 return;
2099 } else {
2100 // Src can be a register or immediate.
2101 assert(isScalarIntegerType(SrcTy));
John Porto4a566862016-01-04 09:33:41 -08002102 emitIASAddrOpTyGPR(Func, SrcTy, StackAddr, Src, GPRAddrEmitter);
John Porto921856d2015-07-07 11:56:26 -07002103 return;
2104 }
2105 return;
2106 }
2107}
2108
John Porto4a566862016-01-04 09:33:41 -08002109template <typename TraitsType>
2110void InstImpl<TraitsType>::InstX86Movd::emit(const Cfg *Func) const {
John Porto008f4ce2015-12-24 13:22:18 -08002111 if (!BuildDefs::dump())
2112 return;
2113 assert(this->getSrcSize() == 1);
2114 Variable *Dest = this->getDest();
2115 Operand *Src = this->getSrc(0);
2116
2117 if (Dest->getType() == IceType_i64 || Src->getType() == IceType_i64) {
2118 assert(Dest->getType() == IceType_f64 || Src->getType() == IceType_f64);
2119 assert(Dest->getType() != Src->getType());
2120 Ostream &Str = Func->getContext()->getStrEmit();
2121 Str << "\t"
2122 "movq"
2123 "\t";
2124 Src->emit(Func);
2125 Str << ", ";
2126 Dest->emit(Func);
2127 return;
2128 }
2129
John Porto4a566862016-01-04 09:33:41 -08002130 InstX86BaseUnaryopXmm<InstX86Base::Movd>::emit(Func);
John Porto008f4ce2015-12-24 13:22:18 -08002131}
2132
John Porto4a566862016-01-04 09:33:41 -08002133template <typename TraitsType>
2134void InstImpl<TraitsType>::InstX86Movd::emitIAS(const Cfg *Func) const {
2135 Assembler *Asm = Func->getAssembler<Assembler>();
John Porto921856d2015-07-07 11:56:26 -07002136 assert(this->getSrcSize() == 1);
2137 const Variable *Dest = this->getDest();
John Porto4a566862016-01-04 09:33:41 -08002138 auto *Target = InstX86Base::getTarget(Func);
Andrew Scull57e12682015-09-16 11:30:19 -07002139 // For insert/extract element (one of Src/Dest is an Xmm vector and the other
2140 // is an int type).
John Porto3c275ce2015-12-22 08:14:00 -08002141 if (const auto *SrcVar = llvm::dyn_cast<Variable>(this->getSrc(0))) {
2142 if (SrcVar->getType() == IceType_i32 ||
John Porto4a566862016-01-04 09:33:41 -08002143 (Traits::Is64Bit && SrcVar->getType() == IceType_i64)) {
John Porto3c275ce2015-12-22 08:14:00 -08002144 assert(isVectorType(Dest->getType()) ||
2145 (isScalarFloatingType(Dest->getType()) &&
2146 typeWidthInBytes(SrcVar->getType()) ==
2147 typeWidthInBytes(Dest->getType())));
2148 assert(Dest->hasReg());
John Porto4a566862016-01-04 09:33:41 -08002149 XmmRegister DestReg = Traits::getEncodedXmm(Dest->getRegNum());
John Porto3c275ce2015-12-22 08:14:00 -08002150 if (SrcVar->hasReg()) {
John Porto4a566862016-01-04 09:33:41 -08002151 Asm->movd(SrcVar->getType(), DestReg,
2152 Traits::getEncodedGPR(SrcVar->getRegNum()));
John Porto3c275ce2015-12-22 08:14:00 -08002153 } else {
John Porto4a566862016-01-04 09:33:41 -08002154 Address StackAddr(Target->stackVarToAsmOperand(SrcVar));
John Porto3c275ce2015-12-22 08:14:00 -08002155 Asm->movd(SrcVar->getType(), DestReg, StackAddr);
2156 }
2157 } else {
2158 assert(isVectorType(SrcVar->getType()) ||
2159 (isScalarFloatingType(SrcVar->getType()) &&
2160 typeWidthInBytes(SrcVar->getType()) ==
2161 typeWidthInBytes(Dest->getType())));
2162 assert(SrcVar->hasReg());
2163 assert(Dest->getType() == IceType_i32 ||
John Porto4a566862016-01-04 09:33:41 -08002164 (Traits::Is64Bit && Dest->getType() == IceType_i64));
2165 XmmRegister SrcReg = Traits::getEncodedXmm(SrcVar->getRegNum());
John Porto3c275ce2015-12-22 08:14:00 -08002166 if (Dest->hasReg()) {
John Porto4a566862016-01-04 09:33:41 -08002167 Asm->movd(Dest->getType(), Traits::getEncodedGPR(Dest->getRegNum()),
John Porto3c275ce2015-12-22 08:14:00 -08002168 SrcReg);
2169 } else {
John Porto4a566862016-01-04 09:33:41 -08002170 Address StackAddr(Target->stackVarToAsmOperand(Dest));
John Porto3c275ce2015-12-22 08:14:00 -08002171 Asm->movd(Dest->getType(), StackAddr, SrcReg);
2172 }
2173 }
2174 } else {
John Porto921856d2015-07-07 11:56:26 -07002175 assert(Dest->hasReg());
John Porto4a566862016-01-04 09:33:41 -08002176 XmmRegister DestReg = Traits::getEncodedXmm(Dest->getRegNum());
2177 auto *Mem = llvm::cast<X86OperandMem>(this->getSrc(0));
John Porto3c275ce2015-12-22 08:14:00 -08002178 Asm->movd(Mem->getType(), DestReg, Mem->toAsmAddress(Asm, Target));
John Porto921856d2015-07-07 11:56:26 -07002179 }
2180}
2181
John Porto4a566862016-01-04 09:33:41 -08002182template <typename TraitsType>
2183void InstImpl<TraitsType>::InstX86Movp::emit(const Cfg *Func) const {
John Porto921856d2015-07-07 11:56:26 -07002184 if (!BuildDefs::dump())
2185 return;
Andrew Scull57e12682015-09-16 11:30:19 -07002186 // TODO(wala,stichnot): movups works with all vector operands, but there
2187 // exist other instructions (movaps, movdqa, movdqu) that may perform better,
2188 // depending on the data type and alignment of the operands.
John Porto921856d2015-07-07 11:56:26 -07002189 Ostream &Str = Func->getContext()->getStrEmit();
2190 assert(this->getSrcSize() == 1);
Jim Stichnoth6106df82015-12-16 06:17:58 -08002191 Str << "\t"
2192 "movups\t";
John Porto921856d2015-07-07 11:56:26 -07002193 this->getSrc(0)->emit(Func);
2194 Str << ", ";
2195 this->getDest()->emit(Func);
2196}
2197
John Porto4a566862016-01-04 09:33:41 -08002198template <typename TraitsType>
2199void InstImpl<TraitsType>::InstX86Movp::emitIAS(const Cfg *Func) const {
John Porto921856d2015-07-07 11:56:26 -07002200 assert(this->getSrcSize() == 1);
2201 assert(isVectorType(this->getDest()->getType()));
2202 const Variable *Dest = this->getDest();
2203 const Operand *Src = this->getSrc(0);
John Porto4a566862016-01-04 09:33:41 -08002204 static const XmmEmitterMovOps Emitter = {
2205 &Assembler::movups, &Assembler::movups, &Assembler::movups};
2206 emitIASMovlikeXMM(Func, Dest, Src, Emitter);
John Porto921856d2015-07-07 11:56:26 -07002207}
2208
John Porto4a566862016-01-04 09:33:41 -08002209template <typename TraitsType>
2210void InstImpl<TraitsType>::InstX86Movq::emit(const Cfg *Func) const {
John Porto921856d2015-07-07 11:56:26 -07002211 if (!BuildDefs::dump())
2212 return;
2213 Ostream &Str = Func->getContext()->getStrEmit();
2214 assert(this->getSrcSize() == 1);
2215 assert(this->getDest()->getType() == IceType_i64 ||
2216 this->getDest()->getType() == IceType_f64);
Jim Stichnoth6106df82015-12-16 06:17:58 -08002217 Str << "\t"
John Porto008f4ce2015-12-24 13:22:18 -08002218 "movq"
2219 "\t";
John Porto921856d2015-07-07 11:56:26 -07002220 this->getSrc(0)->emit(Func);
2221 Str << ", ";
2222 this->getDest()->emit(Func);
2223}
2224
John Porto4a566862016-01-04 09:33:41 -08002225template <typename TraitsType>
2226void InstImpl<TraitsType>::InstX86Movq::emitIAS(const Cfg *Func) const {
John Porto921856d2015-07-07 11:56:26 -07002227 assert(this->getSrcSize() == 1);
2228 assert(this->getDest()->getType() == IceType_i64 ||
2229 this->getDest()->getType() == IceType_f64);
2230 const Variable *Dest = this->getDest();
2231 const Operand *Src = this->getSrc(0);
John Porto4a566862016-01-04 09:33:41 -08002232 static const XmmEmitterMovOps Emitter = {&Assembler::movq, &Assembler::movq,
2233 &Assembler::movq};
2234 emitIASMovlikeXMM(Func, Dest, Src, Emitter);
John Porto921856d2015-07-07 11:56:26 -07002235}
2236
John Porto4a566862016-01-04 09:33:41 -08002237template <typename TraitsType>
2238void InstImpl<TraitsType>::InstX86MovssRegs::emitIAS(const Cfg *Func) const {
Andrew Scull57e12682015-09-16 11:30:19 -07002239 // This is Binop variant is only intended to be used for reg-reg moves where
2240 // part of the Dest register is untouched.
John Porto921856d2015-07-07 11:56:26 -07002241 assert(this->getSrcSize() == 2);
2242 const Variable *Dest = this->getDest();
2243 assert(Dest == this->getSrc(0));
Jim Stichnoth5bff61c2015-10-28 09:26:00 -07002244 const auto *SrcVar = llvm::cast<Variable>(this->getSrc(1));
John Porto921856d2015-07-07 11:56:26 -07002245 assert(Dest->hasReg() && SrcVar->hasReg());
John Porto4a566862016-01-04 09:33:41 -08002246 Assembler *Asm = Func->getAssembler<Assembler>();
2247 Asm->movss(IceType_f32, Traits::getEncodedXmm(Dest->getRegNum()),
2248 Traits::getEncodedXmm(SrcVar->getRegNum()));
John Porto921856d2015-07-07 11:56:26 -07002249}
2250
John Porto4a566862016-01-04 09:33:41 -08002251template <typename TraitsType>
2252void InstImpl<TraitsType>::InstX86Movsx::emitIAS(const Cfg *Func) const {
John Porto921856d2015-07-07 11:56:26 -07002253 assert(this->getSrcSize() == 1);
2254 const Variable *Dest = this->getDest();
2255 const Operand *Src = this->getSrc(0);
Andrew Scull57e12682015-09-16 11:30:19 -07002256 // Dest must be a > 8-bit register, but Src can be 8-bit. In practice we just
2257 // use the full register for Dest to avoid having an OperandSizeOverride
2258 // prefix. It also allows us to only dispatch on SrcTy.
John Porto921856d2015-07-07 11:56:26 -07002259 Type SrcTy = Src->getType();
2260 assert(typeWidthInBytes(Dest->getType()) > 1);
2261 assert(typeWidthInBytes(Dest->getType()) > typeWidthInBytes(SrcTy));
John Porto56958cb2016-01-14 09:18:18 -08002262 constexpr bool NotLea = false;
2263 emitIASRegOpTyGPR<false, true>(Func, NotLea, SrcTy, Dest, Src, this->Emitter);
2264}
2265
2266template <typename TraitsType>
2267bool InstImpl<TraitsType>::InstX86Movzx::mayBeElided(
2268 const Variable *Dest, const Operand *SrcOpnd) const {
2269 assert(Traits::Is64Bit);
2270 const auto *Src = llvm::dyn_cast<Variable>(SrcOpnd);
2271
2272 // Src is not a Variable, so it does not have a register. Movzx can't be
2273 // elided.
2274 if (Src == nullptr)
2275 return false;
2276
2277 // Movzx to/from memory can't be elided.
2278 if (!Src->hasReg() || !Dest->hasReg())
2279 return false;
2280
2281 // Reg/reg move with different source and dest can't be elided.
2282 if (Traits::getEncodedGPR(Src->getRegNum()) !=
2283 Traits::getEncodedGPR(Dest->getRegNum()))
2284 return false;
2285
2286 // A must-keep movzx 32- to 64-bit is sometimes needed in x86-64 sandboxing.
2287 return !MustKeep;
John Porto921856d2015-07-07 11:56:26 -07002288}
2289
John Porto4a566862016-01-04 09:33:41 -08002290template <typename TraitsType>
2291void InstImpl<TraitsType>::InstX86Movzx::emit(const Cfg *Func) const {
John Porto008f4ce2015-12-24 13:22:18 -08002292 if (!BuildDefs::dump())
2293 return;
John Porto4a566862016-01-04 09:33:41 -08002294 if (Traits::Is64Bit) {
John Porto008f4ce2015-12-24 13:22:18 -08002295 // There's no movzx %eXX, %rXX. To zero extend 32- to 64-bits, we emit a
2296 // mov %eXX, %eXX. The processor will still do a movzx[bw]q.
2297 assert(this->getSrcSize() == 1);
2298 const Operand *Src = this->getSrc(0);
2299 const Variable *Dest = this->Dest;
2300 if (Src->getType() == IceType_i32 && Dest->getType() == IceType_i64) {
2301 Ostream &Str = Func->getContext()->getStrEmit();
John Porto56958cb2016-01-14 09:18:18 -08002302 if (mayBeElided(Dest, Src)) {
2303 Str << "\t/* elided movzx */";
2304 } else {
2305 Str << "\t"
2306 "mov"
2307 "\t";
2308 Src->emit(Func);
2309 Str << ", ";
2310 Dest->asType(IceType_i32,
2311 Traits::getGprForType(IceType_i32, Dest->getRegNum()))
2312 ->emit(Func);
2313 Str << " /* movzx */";
2314 }
John Porto008f4ce2015-12-24 13:22:18 -08002315 return;
2316 }
2317 }
John Porto4a566862016-01-04 09:33:41 -08002318 InstX86BaseUnaryopGPR<InstX86Base::Movzx>::emit(Func);
John Porto008f4ce2015-12-24 13:22:18 -08002319}
2320
John Porto4a566862016-01-04 09:33:41 -08002321template <typename TraitsType>
2322void InstImpl<TraitsType>::InstX86Movzx::emitIAS(const Cfg *Func) const {
John Porto921856d2015-07-07 11:56:26 -07002323 assert(this->getSrcSize() == 1);
2324 const Variable *Dest = this->getDest();
2325 const Operand *Src = this->getSrc(0);
2326 Type SrcTy = Src->getType();
2327 assert(typeWidthInBytes(Dest->getType()) > 1);
2328 assert(typeWidthInBytes(Dest->getType()) > typeWidthInBytes(SrcTy));
John Porto56958cb2016-01-14 09:18:18 -08002329 if (Traits::Is64Bit) {
2330 if (Src->getType() == IceType_i32 && Dest->getType() == IceType_i64 &&
2331 mayBeElided(Dest, Src)) {
2332 return;
2333 }
2334 }
2335 constexpr bool NotLea = false;
2336 emitIASRegOpTyGPR<false, true>(Func, NotLea, SrcTy, Dest, Src, this->Emitter);
John Porto921856d2015-07-07 11:56:26 -07002337}
2338
John Porto4a566862016-01-04 09:33:41 -08002339template <typename TraitsType>
2340void InstImpl<TraitsType>::InstX86Nop::emit(const Cfg *Func) const {
John Porto921856d2015-07-07 11:56:26 -07002341 if (!BuildDefs::dump())
2342 return;
2343 Ostream &Str = Func->getContext()->getStrEmit();
2344 // TODO: Emit the right code for each variant.
Jim Stichnoth6106df82015-12-16 06:17:58 -08002345 Str << "\t"
Jim Stichnoth751e27e2015-12-16 12:40:31 -08002346 "nop\t/* variant = " << Variant << " */";
John Porto921856d2015-07-07 11:56:26 -07002347}
2348
John Porto4a566862016-01-04 09:33:41 -08002349template <typename TraitsType>
2350void InstImpl<TraitsType>::InstX86Nop::emitIAS(const Cfg *Func) const {
2351 Assembler *Asm = Func->getAssembler<Assembler>();
John Porto921856d2015-07-07 11:56:26 -07002352 // TODO: Emit the right code for the variant.
2353 Asm->nop();
2354}
2355
John Porto4a566862016-01-04 09:33:41 -08002356template <typename TraitsType>
2357void InstImpl<TraitsType>::InstX86Nop::dump(const Cfg *Func) const {
John Porto921856d2015-07-07 11:56:26 -07002358 if (!BuildDefs::dump())
2359 return;
2360 Ostream &Str = Func->getContext()->getStrDump();
2361 Str << "nop (variant = " << Variant << ")";
2362}
2363
John Porto4a566862016-01-04 09:33:41 -08002364template <typename TraitsType>
2365void InstImpl<TraitsType>::InstX86Fld::emit(const Cfg *Func) const {
John Porto921856d2015-07-07 11:56:26 -07002366 if (!BuildDefs::dump())
2367 return;
2368 Ostream &Str = Func->getContext()->getStrEmit();
2369 assert(this->getSrcSize() == 1);
2370 Type Ty = this->getSrc(0)->getType();
Jim Stichnoth5bff61c2015-10-28 09:26:00 -07002371 const auto *Var = llvm::dyn_cast<Variable>(this->getSrc(0));
John Porto921856d2015-07-07 11:56:26 -07002372 if (Var && Var->hasReg()) {
Andrew Scull57e12682015-09-16 11:30:19 -07002373 // This is a physical xmm register, so we need to spill it to a temporary
David Sehr0d9cf482015-11-16 17:00:38 -08002374 // stack slot. Function prolog emission guarantees that there is sufficient
2375 // space to do this.
Jim Stichnoth6106df82015-12-16 06:17:58 -08002376 Str << "\t"
John Porto4a566862016-01-04 09:33:41 -08002377 "mov" << Traits::TypeAttributes[Ty].SdSsString << "\t";
John Porto921856d2015-07-07 11:56:26 -07002378 Var->emit(Func);
Jim Stichnoth6106df82015-12-16 06:17:58 -08002379 Str << ", (%esp)\n"
2380 "\t"
2381 "fld" << this->getFldString(Ty) << "\t"
2382 "(%esp)";
John Porto921856d2015-07-07 11:56:26 -07002383 return;
2384 }
Jim Stichnoth6106df82015-12-16 06:17:58 -08002385 Str << "\t"
2386 "fld" << this->getFldString(Ty) << "\t";
John Porto921856d2015-07-07 11:56:26 -07002387 this->getSrc(0)->emit(Func);
2388}
2389
John Porto4a566862016-01-04 09:33:41 -08002390template <typename TraitsType>
2391void InstImpl<TraitsType>::InstX86Fld::emitIAS(const Cfg *Func) const {
2392 Assembler *Asm = Func->getAssembler<Assembler>();
John Porto921856d2015-07-07 11:56:26 -07002393 assert(this->getSrcSize() == 1);
2394 const Operand *Src = this->getSrc(0);
John Porto4a566862016-01-04 09:33:41 -08002395 auto *Target = InstX86Base::getTarget(Func);
John Porto921856d2015-07-07 11:56:26 -07002396 Type Ty = Src->getType();
Jim Stichnoth5bff61c2015-10-28 09:26:00 -07002397 if (const auto *Var = llvm::dyn_cast<Variable>(Src)) {
John Porto921856d2015-07-07 11:56:26 -07002398 if (Var->hasReg()) {
Andrew Scull57e12682015-09-16 11:30:19 -07002399 // This is a physical xmm register, so we need to spill it to a temporary
David Sehr0d9cf482015-11-16 17:00:38 -08002400 // stack slot. Function prolog emission guarantees that there is
2401 // sufficient space to do this.
John Porto4a566862016-01-04 09:33:41 -08002402 Address StackSlot =
2403 Address(RegisterSet::Encoded_Reg_esp, 0, AssemblerFixup::NoFixup);
2404 Asm->movss(Ty, StackSlot, Traits::getEncodedXmm(Var->getRegNum()));
John Porto921856d2015-07-07 11:56:26 -07002405 Asm->fld(Ty, StackSlot);
John Porto921856d2015-07-07 11:56:26 -07002406 } else {
John Porto4a566862016-01-04 09:33:41 -08002407 Address StackAddr(Target->stackVarToAsmOperand(Var));
John Porto921856d2015-07-07 11:56:26 -07002408 Asm->fld(Ty, StackAddr);
2409 }
John Porto4a566862016-01-04 09:33:41 -08002410 } else if (const auto *Mem = llvm::dyn_cast<X86OperandMem>(Src)) {
2411 assert(Mem->getSegmentRegister() == X86OperandMem::DefaultSegment);
David Sehr4318a412015-11-11 15:01:55 -08002412 Asm->fld(Ty, Mem->toAsmAddress(Asm, Target));
Jim Stichnoth5bff61c2015-10-28 09:26:00 -07002413 } else if (const auto *Imm = llvm::dyn_cast<Constant>(Src)) {
John Porto4a566862016-01-04 09:33:41 -08002414 Asm->fld(Ty, Traits::Address::ofConstPool(Asm, Imm));
John Porto921856d2015-07-07 11:56:26 -07002415 } else {
2416 llvm_unreachable("Unexpected operand type");
2417 }
2418}
2419
John Porto4a566862016-01-04 09:33:41 -08002420template <typename TraitsType>
2421void InstImpl<TraitsType>::InstX86Fld::dump(const Cfg *Func) const {
John Porto921856d2015-07-07 11:56:26 -07002422 if (!BuildDefs::dump())
2423 return;
2424 Ostream &Str = Func->getContext()->getStrDump();
2425 Str << "fld." << this->getSrc(0)->getType() << " ";
2426 this->dumpSources(Func);
2427}
2428
John Porto4a566862016-01-04 09:33:41 -08002429template <typename TraitsType>
2430void InstImpl<TraitsType>::InstX86Fstp::emit(const Cfg *Func) const {
John Porto921856d2015-07-07 11:56:26 -07002431 if (!BuildDefs::dump())
2432 return;
2433 Ostream &Str = Func->getContext()->getStrEmit();
2434 assert(this->getSrcSize() == 0);
2435 // TODO(jvoung,stichnot): Utilize this by setting Dest to nullptr to
Andrew Scull57e12682015-09-16 11:30:19 -07002436 // "partially" delete the fstp if the Dest is unused. Even if Dest is unused,
2437 // the fstp should be kept for the SideEffects of popping the stack.
John Porto921856d2015-07-07 11:56:26 -07002438 if (!this->getDest()) {
Jim Stichnoth6106df82015-12-16 06:17:58 -08002439 Str << "\t"
2440 "fstp\t"
2441 "st(0)";
John Porto921856d2015-07-07 11:56:26 -07002442 return;
2443 }
2444 Type Ty = this->getDest()->getType();
John Porto921856d2015-07-07 11:56:26 -07002445 if (!this->getDest()->hasReg()) {
Jim Stichnoth6106df82015-12-16 06:17:58 -08002446 Str << "\t"
2447 "fstp" << this->getFldString(Ty) << "\t";
John Porto921856d2015-07-07 11:56:26 -07002448 this->getDest()->emit(Func);
2449 return;
2450 }
Andrew Scull57e12682015-09-16 11:30:19 -07002451 // Dest is a physical (xmm) register, so st(0) needs to go through memory.
David Sehr21fd1032015-11-13 16:32:37 -08002452 // Hack this by using caller-reserved memory at the top of stack, spilling
2453 // st(0) there, and loading it into the xmm register.
Jim Stichnoth6106df82015-12-16 06:17:58 -08002454 Str << "\t"
2455 "fstp" << this->getFldString(Ty) << "\t"
2456 "(%esp)\n";
2457 Str << "\t"
John Porto4a566862016-01-04 09:33:41 -08002458 "mov" << Traits::TypeAttributes[Ty].SdSsString << "\t"
2459 "(%esp), ";
John Porto921856d2015-07-07 11:56:26 -07002460 this->getDest()->emit(Func);
John Porto921856d2015-07-07 11:56:26 -07002461}
2462
John Porto4a566862016-01-04 09:33:41 -08002463template <typename TraitsType>
2464void InstImpl<TraitsType>::InstX86Fstp::emitIAS(const Cfg *Func) const {
2465 Assembler *Asm = Func->getAssembler<Assembler>();
John Porto921856d2015-07-07 11:56:26 -07002466 assert(this->getSrcSize() == 0);
2467 const Variable *Dest = this->getDest();
2468 // TODO(jvoung,stichnot): Utilize this by setting Dest to nullptr to
Andrew Scull57e12682015-09-16 11:30:19 -07002469 // "partially" delete the fstp if the Dest is unused. Even if Dest is unused,
2470 // the fstp should be kept for the SideEffects of popping the stack.
John Porto921856d2015-07-07 11:56:26 -07002471 if (!Dest) {
John Porto4a566862016-01-04 09:33:41 -08002472 Asm->fstp(RegisterSet::getEncodedSTReg(0));
John Porto921856d2015-07-07 11:56:26 -07002473 return;
2474 }
John Porto4a566862016-01-04 09:33:41 -08002475 auto *Target = InstX86Base::getTarget(Func);
John Porto921856d2015-07-07 11:56:26 -07002476 Type Ty = Dest->getType();
2477 if (!Dest->hasReg()) {
John Porto4a566862016-01-04 09:33:41 -08002478 Address StackAddr(Target->stackVarToAsmOperand(Dest));
John Porto921856d2015-07-07 11:56:26 -07002479 Asm->fstp(Ty, StackAddr);
2480 } else {
Andrew Scull57e12682015-09-16 11:30:19 -07002481 // Dest is a physical (xmm) register, so st(0) needs to go through memory.
David Sehr21fd1032015-11-13 16:32:37 -08002482 // Hack this by using caller-reserved memory at the top of stack, spilling
2483 // st(0) there, and loading it into the xmm register.
John Porto4a566862016-01-04 09:33:41 -08002484 Address StackSlot =
2485 Address(RegisterSet::Encoded_Reg_esp, 0, AssemblerFixup::NoFixup);
John Porto921856d2015-07-07 11:56:26 -07002486 Asm->fstp(Ty, StackSlot);
John Porto4a566862016-01-04 09:33:41 -08002487 Asm->movss(Ty, Traits::getEncodedXmm(Dest->getRegNum()), StackSlot);
John Porto921856d2015-07-07 11:56:26 -07002488 }
2489}
2490
John Porto4a566862016-01-04 09:33:41 -08002491template <typename TraitsType>
2492void InstImpl<TraitsType>::InstX86Fstp::dump(const Cfg *Func) const {
John Porto921856d2015-07-07 11:56:26 -07002493 if (!BuildDefs::dump())
2494 return;
2495 Ostream &Str = Func->getContext()->getStrDump();
2496 this->dumpDest(Func);
2497 Str << " = fstp." << this->getDest()->getType() << ", st(0)";
2498}
2499
John Porto4a566862016-01-04 09:33:41 -08002500template <typename TraitsType>
2501void InstImpl<TraitsType>::InstX86Pextr::emit(const Cfg *Func) const {
John Porto921856d2015-07-07 11:56:26 -07002502 if (!BuildDefs::dump())
2503 return;
2504 Ostream &Str = Func->getContext()->getStrEmit();
2505 assert(this->getSrcSize() == 2);
2506 // pextrb and pextrd are SSE4.1 instructions.
John Porto921856d2015-07-07 11:56:26 -07002507 Str << "\t" << this->Opcode
John Porto4a566862016-01-04 09:33:41 -08002508 << Traits::TypeAttributes[this->getSrc(0)->getType()].PackString << "\t";
John Porto921856d2015-07-07 11:56:26 -07002509 this->getSrc(1)->emit(Func);
2510 Str << ", ";
2511 this->getSrc(0)->emit(Func);
2512 Str << ", ";
2513 Variable *Dest = this->getDest();
Andrew Scull57e12682015-09-16 11:30:19 -07002514 // pextrw must take a register dest. There is an SSE4.1 version that takes a
2515 // memory dest, but we aren't using it. For uniformity, just restrict them
2516 // all to have a register dest for now.
John Porto921856d2015-07-07 11:56:26 -07002517 assert(Dest->hasReg());
Jim Stichnoth5bff61c2015-10-28 09:26:00 -07002518 Dest->asType(IceType_i32, Dest->getRegNum())->emit(Func);
John Porto921856d2015-07-07 11:56:26 -07002519}
2520
John Porto4a566862016-01-04 09:33:41 -08002521template <typename TraitsType>
2522void InstImpl<TraitsType>::InstX86Pextr::emitIAS(const Cfg *Func) const {
John Porto921856d2015-07-07 11:56:26 -07002523 assert(this->getSrcSize() == 2);
2524 // pextrb and pextrd are SSE4.1 instructions.
2525 const Variable *Dest = this->getDest();
John Porto4a566862016-01-04 09:33:41 -08002526 Type DispatchTy = Traits::getInVectorElementType(this->getSrc(0)->getType());
Andrew Scull57e12682015-09-16 11:30:19 -07002527 // pextrw must take a register dest. There is an SSE4.1 version that takes a
2528 // memory dest, but we aren't using it. For uniformity, just restrict them
2529 // all to have a register dest for now.
John Porto921856d2015-07-07 11:56:26 -07002530 assert(Dest->hasReg());
2531 // pextrw's Src(0) must be a register (both SSE4.1 and SSE2).
2532 assert(llvm::cast<Variable>(this->getSrc(0))->hasReg());
John Porto4a566862016-01-04 09:33:41 -08002533 static const ThreeOpImmEmitter<GPRRegister, XmmRegister> Emitter = {
2534 &Assembler::pextr, nullptr};
2535 emitIASThreeOpImmOps<GPRRegister, XmmRegister, Traits::getEncodedGPR,
2536 Traits::getEncodedXmm>(
John Porto921856d2015-07-07 11:56:26 -07002537 Func, DispatchTy, Dest, this->getSrc(0), this->getSrc(1), Emitter);
2538}
2539
John Porto4a566862016-01-04 09:33:41 -08002540template <typename TraitsType>
2541void InstImpl<TraitsType>::InstX86Pinsr::emit(const Cfg *Func) const {
John Porto921856d2015-07-07 11:56:26 -07002542 if (!BuildDefs::dump())
2543 return;
2544 Ostream &Str = Func->getContext()->getStrEmit();
2545 assert(this->getSrcSize() == 3);
John Porto921856d2015-07-07 11:56:26 -07002546 Str << "\t" << this->Opcode
John Porto4a566862016-01-04 09:33:41 -08002547 << Traits::TypeAttributes[this->getDest()->getType()].PackString << "\t";
John Porto921856d2015-07-07 11:56:26 -07002548 this->getSrc(2)->emit(Func);
2549 Str << ", ";
2550 Operand *Src1 = this->getSrc(1);
Jim Stichnoth5bff61c2015-10-28 09:26:00 -07002551 if (const auto *Src1Var = llvm::dyn_cast<Variable>(Src1)) {
John Porto921856d2015-07-07 11:56:26 -07002552 // If src1 is a register, it should always be r32.
2553 if (Src1Var->hasReg()) {
Jim Stichnoth8aa39662016-02-10 11:20:30 -08002554 const auto NewRegNum = Traits::getBaseReg(Src1Var->getRegNum());
Jim Stichnoth5bff61c2015-10-28 09:26:00 -07002555 const Variable *NewSrc = Src1Var->asType(IceType_i32, NewRegNum);
2556 NewSrc->emit(Func);
John Porto921856d2015-07-07 11:56:26 -07002557 } else {
2558 Src1Var->emit(Func);
2559 }
2560 } else {
2561 Src1->emit(Func);
2562 }
2563 Str << ", ";
2564 this->getDest()->emit(Func);
2565}
2566
John Porto4a566862016-01-04 09:33:41 -08002567template <typename TraitsType>
2568void InstImpl<TraitsType>::InstX86Pinsr::emitIAS(const Cfg *Func) const {
John Porto921856d2015-07-07 11:56:26 -07002569 assert(this->getSrcSize() == 3);
2570 assert(this->getDest() == this->getSrc(0));
2571 // pinsrb and pinsrd are SSE4.1 instructions.
2572 const Operand *Src0 = this->getSrc(1);
2573 Type DispatchTy = Src0->getType();
Andrew Scull57e12682015-09-16 11:30:19 -07002574 // If src1 is a register, it should always be r32 (this should fall out from
2575 // the encodings for ByteRegs overlapping the encodings for r32), but we have
Jim Stichnoth5bff61c2015-10-28 09:26:00 -07002576 // to make sure the register allocator didn't choose an 8-bit high register
2577 // like "ah".
2578 if (BuildDefs::asserts()) {
2579 if (auto *Src0Var = llvm::dyn_cast<Variable>(Src0)) {
2580 if (Src0Var->hasReg()) {
Jim Stichnoth8aa39662016-02-10 11:20:30 -08002581 const auto RegNum = Src0Var->getRegNum();
2582 const auto BaseRegNum = Traits::getBaseReg(RegNum);
Jim Stichnoth5bff61c2015-10-28 09:26:00 -07002583 (void)BaseRegNum;
John Porto4a566862016-01-04 09:33:41 -08002584 assert(Traits::getEncodedGPR(RegNum) ==
2585 Traits::getEncodedGPR(BaseRegNum));
Jim Stichnoth5bff61c2015-10-28 09:26:00 -07002586 }
2587 }
2588 }
John Porto4a566862016-01-04 09:33:41 -08002589 static const ThreeOpImmEmitter<XmmRegister, GPRRegister> Emitter = {
2590 &Assembler::pinsr, &Assembler::pinsr};
2591 emitIASThreeOpImmOps<XmmRegister, GPRRegister, Traits::getEncodedXmm,
2592 Traits::getEncodedGPR>(Func, DispatchTy, this->getDest(),
2593 Src0, this->getSrc(2), Emitter);
John Porto921856d2015-07-07 11:56:26 -07002594}
2595
John Porto4a566862016-01-04 09:33:41 -08002596template <typename TraitsType>
2597void InstImpl<TraitsType>::InstX86Pshufd::emitIAS(const Cfg *Func) const {
John Porto921856d2015-07-07 11:56:26 -07002598 assert(this->getSrcSize() == 2);
2599 const Variable *Dest = this->getDest();
2600 Type Ty = Dest->getType();
John Porto4a566862016-01-04 09:33:41 -08002601 static const ThreeOpImmEmitter<XmmRegister, XmmRegister> Emitter = {
2602 &Assembler::pshufd, &Assembler::pshufd};
2603 emitIASThreeOpImmOps<XmmRegister, XmmRegister, Traits::getEncodedXmm,
2604 Traits::getEncodedXmm>(Func, Ty, Dest, this->getSrc(0),
2605 this->getSrc(1), Emitter);
John Porto921856d2015-07-07 11:56:26 -07002606}
2607
John Porto4a566862016-01-04 09:33:41 -08002608template <typename TraitsType>
2609void InstImpl<TraitsType>::InstX86Shufps::emitIAS(const Cfg *Func) const {
John Porto921856d2015-07-07 11:56:26 -07002610 assert(this->getSrcSize() == 3);
2611 const Variable *Dest = this->getDest();
2612 assert(Dest == this->getSrc(0));
2613 Type Ty = Dest->getType();
John Porto4a566862016-01-04 09:33:41 -08002614 static const ThreeOpImmEmitter<XmmRegister, XmmRegister> Emitter = {
2615 &Assembler::shufps, &Assembler::shufps};
2616 emitIASThreeOpImmOps<XmmRegister, XmmRegister, Traits::getEncodedXmm,
2617 Traits::getEncodedXmm>(Func, Ty, Dest, this->getSrc(1),
2618 this->getSrc(2), Emitter);
John Porto921856d2015-07-07 11:56:26 -07002619}
2620
John Porto4a566862016-01-04 09:33:41 -08002621template <typename TraitsType>
2622void InstImpl<TraitsType>::InstX86Pop::emit(const Cfg *Func) const {
John Porto921856d2015-07-07 11:56:26 -07002623 if (!BuildDefs::dump())
2624 return;
2625 Ostream &Str = Func->getContext()->getStrEmit();
2626 assert(this->getSrcSize() == 0);
Jim Stichnoth6106df82015-12-16 06:17:58 -08002627 Str << "\t"
2628 "pop\t";
John Porto921856d2015-07-07 11:56:26 -07002629 this->getDest()->emit(Func);
2630}
2631
John Porto4a566862016-01-04 09:33:41 -08002632template <typename TraitsType>
2633void InstImpl<TraitsType>::InstX86Pop::emitIAS(const Cfg *Func) const {
John Porto921856d2015-07-07 11:56:26 -07002634 assert(this->getSrcSize() == 0);
John Porto4a566862016-01-04 09:33:41 -08002635 Assembler *Asm = Func->getAssembler<Assembler>();
John Porto921856d2015-07-07 11:56:26 -07002636 if (this->getDest()->hasReg()) {
John Porto4a566862016-01-04 09:33:41 -08002637 Asm->popl(Traits::getEncodedGPR(this->getDest()->getRegNum()));
John Porto921856d2015-07-07 11:56:26 -07002638 } else {
John Porto4a566862016-01-04 09:33:41 -08002639 auto *Target = InstX86Base::getTarget(Func);
David Sehrb8e49c12015-11-12 14:41:22 -08002640 Asm->popl(Target->stackVarToAsmOperand(this->getDest()));
John Porto921856d2015-07-07 11:56:26 -07002641 }
2642}
2643
John Porto4a566862016-01-04 09:33:41 -08002644template <typename TraitsType>
2645void InstImpl<TraitsType>::InstX86Pop::dump(const Cfg *Func) const {
John Porto921856d2015-07-07 11:56:26 -07002646 if (!BuildDefs::dump())
2647 return;
2648 Ostream &Str = Func->getContext()->getStrDump();
2649 this->dumpDest(Func);
2650 Str << " = pop." << this->getDest()->getType() << " ";
2651}
2652
John Porto4a566862016-01-04 09:33:41 -08002653template <typename TraitsType>
2654void InstImpl<TraitsType>::InstX86Push::emit(const Cfg *Func) const {
John Porto921856d2015-07-07 11:56:26 -07002655 if (!BuildDefs::dump())
2656 return;
2657 Ostream &Str = Func->getContext()->getStrEmit();
Jim Stichnoth6106df82015-12-16 06:17:58 -08002658 Str << "\t"
John Porto56958cb2016-01-14 09:18:18 -08002659 "push"
2660 "\t";
2661 assert(this->getSrcSize() == 1);
2662 const Operand *Src = this->getSrc(0);
2663 Src->emit(Func);
John Porto921856d2015-07-07 11:56:26 -07002664}
2665
John Porto4a566862016-01-04 09:33:41 -08002666template <typename TraitsType>
2667void InstImpl<TraitsType>::InstX86Push::emitIAS(const Cfg *Func) const {
John Porto4a566862016-01-04 09:33:41 -08002668 Assembler *Asm = Func->getAssembler<Assembler>();
John Porto56958cb2016-01-14 09:18:18 -08002669
2670 assert(this->getSrcSize() == 1);
2671 const Operand *Src = this->getSrc(0);
2672
2673 if (const auto *Var = llvm::dyn_cast<Variable>(Src)) {
2674 Asm->pushl(Traits::getEncodedGPR(Var->getRegNum()));
2675 } else if (const auto *Const32 = llvm::dyn_cast<ConstantInteger32>(Src)) {
2676 Asm->pushl(AssemblerImmediate(Const32->getValue()));
2677 } else if (auto *CR = llvm::dyn_cast<ConstantRelocatable>(Src)) {
2678 Asm->pushl(CR);
2679 } else {
2680 llvm_unreachable("Unexpected operand type");
2681 }
John Porto921856d2015-07-07 11:56:26 -07002682}
2683
John Porto4a566862016-01-04 09:33:41 -08002684template <typename TraitsType>
2685void InstImpl<TraitsType>::InstX86Push::dump(const Cfg *Func) const {
John Porto921856d2015-07-07 11:56:26 -07002686 if (!BuildDefs::dump())
2687 return;
2688 Ostream &Str = Func->getContext()->getStrDump();
2689 Str << "push." << this->getSrc(0)->getType() << " ";
2690 this->dumpSources(Func);
2691}
2692
John Porto4a566862016-01-04 09:33:41 -08002693template <typename TraitsType>
2694void InstImpl<TraitsType>::InstX86Ret::emit(const Cfg *Func) const {
John Porto921856d2015-07-07 11:56:26 -07002695 if (!BuildDefs::dump())
2696 return;
2697 Ostream &Str = Func->getContext()->getStrEmit();
Jim Stichnoth6106df82015-12-16 06:17:58 -08002698 Str << "\t"
2699 "ret";
John Porto921856d2015-07-07 11:56:26 -07002700}
2701
John Porto4a566862016-01-04 09:33:41 -08002702template <typename TraitsType>
2703void InstImpl<TraitsType>::InstX86Ret::emitIAS(const Cfg *Func) const {
2704 Assembler *Asm = Func->getAssembler<Assembler>();
John Porto921856d2015-07-07 11:56:26 -07002705 Asm->ret();
2706}
2707
John Porto4a566862016-01-04 09:33:41 -08002708template <typename TraitsType>
2709void InstImpl<TraitsType>::InstX86Ret::dump(const Cfg *Func) const {
John Porto921856d2015-07-07 11:56:26 -07002710 if (!BuildDefs::dump())
2711 return;
2712 Ostream &Str = Func->getContext()->getStrDump();
2713 Type Ty =
2714 (this->getSrcSize() == 0 ? IceType_void : this->getSrc(0)->getType());
2715 Str << "ret." << Ty << " ";
2716 this->dumpSources(Func);
2717}
2718
John Porto4a566862016-01-04 09:33:41 -08002719template <typename TraitsType>
2720void InstImpl<TraitsType>::InstX86Setcc::emit(const Cfg *Func) const {
John Porto921856d2015-07-07 11:56:26 -07002721 if (!BuildDefs::dump())
2722 return;
2723 Ostream &Str = Func->getContext()->getStrEmit();
Jim Stichnoth6106df82015-12-16 06:17:58 -08002724 Str << "\t"
John Porto4a566862016-01-04 09:33:41 -08002725 "set" << Traits::InstBrAttributes[Condition].DisplayString << "\t";
John Porto921856d2015-07-07 11:56:26 -07002726 this->Dest->emit(Func);
2727}
2728
John Porto4a566862016-01-04 09:33:41 -08002729template <typename TraitsType>
2730void InstImpl<TraitsType>::InstX86Setcc::emitIAS(const Cfg *Func) const {
2731 assert(Condition != Cond::Br_None);
John Porto921856d2015-07-07 11:56:26 -07002732 assert(this->getDest()->getType() == IceType_i1);
2733 assert(this->getSrcSize() == 0);
John Porto4a566862016-01-04 09:33:41 -08002734 Assembler *Asm = Func->getAssembler<Assembler>();
2735 auto *Target = InstX86Base::getTarget(Func);
John Porto921856d2015-07-07 11:56:26 -07002736 if (this->getDest()->hasReg())
John Porto4a566862016-01-04 09:33:41 -08002737 Asm->setcc(Condition,
2738 Traits::getEncodedByteReg(this->getDest()->getRegNum()));
John Porto921856d2015-07-07 11:56:26 -07002739 else
David Sehrb8e49c12015-11-12 14:41:22 -08002740 Asm->setcc(Condition, Target->stackVarToAsmOperand(this->getDest()));
John Porto921856d2015-07-07 11:56:26 -07002741 return;
2742}
2743
John Porto4a566862016-01-04 09:33:41 -08002744template <typename TraitsType>
2745void InstImpl<TraitsType>::InstX86Setcc::dump(const Cfg *Func) const {
John Porto921856d2015-07-07 11:56:26 -07002746 if (!BuildDefs::dump())
2747 return;
2748 Ostream &Str = Func->getContext()->getStrDump();
John Porto4a566862016-01-04 09:33:41 -08002749 Str << "setcc." << Traits::InstBrAttributes[Condition].DisplayString << " ";
John Porto921856d2015-07-07 11:56:26 -07002750 this->dumpDest(Func);
2751}
2752
John Porto4a566862016-01-04 09:33:41 -08002753template <typename TraitsType>
2754void InstImpl<TraitsType>::InstX86Xadd::emit(const Cfg *Func) const {
John Porto921856d2015-07-07 11:56:26 -07002755 if (!BuildDefs::dump())
2756 return;
2757 Ostream &Str = Func->getContext()->getStrEmit();
2758 if (this->Locked) {
Jim Stichnoth6106df82015-12-16 06:17:58 -08002759 Str << "\t"
2760 "lock";
John Porto921856d2015-07-07 11:56:26 -07002761 }
Jim Stichnoth6106df82015-12-16 06:17:58 -08002762 Str << "\t"
2763 "xadd" << this->getWidthString(this->getSrc(0)->getType()) << "\t";
John Porto921856d2015-07-07 11:56:26 -07002764 this->getSrc(1)->emit(Func);
2765 Str << ", ";
2766 this->getSrc(0)->emit(Func);
2767}
2768
John Porto4a566862016-01-04 09:33:41 -08002769template <typename TraitsType>
2770void InstImpl<TraitsType>::InstX86Xadd::emitIAS(const Cfg *Func) const {
John Porto921856d2015-07-07 11:56:26 -07002771 assert(this->getSrcSize() == 2);
John Porto4a566862016-01-04 09:33:41 -08002772 Assembler *Asm = Func->getAssembler<Assembler>();
John Porto921856d2015-07-07 11:56:26 -07002773 Type Ty = this->getSrc(0)->getType();
John Porto4a566862016-01-04 09:33:41 -08002774 const auto Mem = llvm::cast<X86OperandMem>(this->getSrc(0));
2775 assert(Mem->getSegmentRegister() == X86OperandMem::DefaultSegment);
2776 auto *Target = InstX86Base::getTarget(Func);
2777 const Address Addr = Mem->toAsmAddress(Asm, Target);
Jim Stichnoth5bff61c2015-10-28 09:26:00 -07002778 const auto *VarReg = llvm::cast<Variable>(this->getSrc(1));
John Porto921856d2015-07-07 11:56:26 -07002779 assert(VarReg->hasReg());
John Porto4a566862016-01-04 09:33:41 -08002780 const GPRRegister Reg = Traits::getEncodedGPR(VarReg->getRegNum());
John Porto921856d2015-07-07 11:56:26 -07002781 Asm->xadd(Ty, Addr, Reg, this->Locked);
2782}
2783
John Porto4a566862016-01-04 09:33:41 -08002784template <typename TraitsType>
2785void InstImpl<TraitsType>::InstX86Xadd::dump(const Cfg *Func) const {
John Porto921856d2015-07-07 11:56:26 -07002786 if (!BuildDefs::dump())
2787 return;
2788 Ostream &Str = Func->getContext()->getStrDump();
2789 if (this->Locked) {
2790 Str << "lock ";
2791 }
2792 Type Ty = this->getSrc(0)->getType();
2793 Str << "xadd." << Ty << " ";
2794 this->dumpSources(Func);
2795}
2796
John Porto4a566862016-01-04 09:33:41 -08002797template <typename TraitsType>
2798void InstImpl<TraitsType>::InstX86Xchg::emit(const Cfg *Func) const {
John Porto921856d2015-07-07 11:56:26 -07002799 if (!BuildDefs::dump())
2800 return;
2801 Ostream &Str = Func->getContext()->getStrEmit();
Jim Stichnoth6106df82015-12-16 06:17:58 -08002802 Str << "\t"
2803 "xchg" << this->getWidthString(this->getSrc(0)->getType()) << "\t";
John Porto921856d2015-07-07 11:56:26 -07002804 this->getSrc(1)->emit(Func);
2805 Str << ", ";
2806 this->getSrc(0)->emit(Func);
2807}
2808
John Porto4a566862016-01-04 09:33:41 -08002809template <typename TraitsType>
2810void InstImpl<TraitsType>::InstX86Xchg::emitIAS(const Cfg *Func) const {
John Porto921856d2015-07-07 11:56:26 -07002811 assert(this->getSrcSize() == 2);
John Porto4a566862016-01-04 09:33:41 -08002812 Assembler *Asm = Func->getAssembler<Assembler>();
John Porto921856d2015-07-07 11:56:26 -07002813 Type Ty = this->getSrc(0)->getType();
Andrew Scullcfa628b2015-08-20 14:23:05 -07002814 const auto *VarReg1 = llvm::cast<Variable>(this->getSrc(1));
2815 assert(VarReg1->hasReg());
John Porto4a566862016-01-04 09:33:41 -08002816 const GPRRegister Reg1 = Traits::getEncodedGPR(VarReg1->getRegNum());
Andrew Scullcfa628b2015-08-20 14:23:05 -07002817
2818 if (const auto *VarReg0 = llvm::dyn_cast<Variable>(this->getSrc(0))) {
2819 assert(VarReg0->hasReg());
John Porto4a566862016-01-04 09:33:41 -08002820 const GPRRegister Reg0 = Traits::getEncodedGPR(VarReg0->getRegNum());
Andrew Scullcfa628b2015-08-20 14:23:05 -07002821 Asm->xchg(Ty, Reg0, Reg1);
2822 return;
2823 }
2824
John Porto4a566862016-01-04 09:33:41 -08002825 const auto *Mem = llvm::cast<X86OperandMem>(this->getSrc(0));
2826 assert(Mem->getSegmentRegister() == X86OperandMem::DefaultSegment);
2827 auto *Target = InstX86Base::getTarget(Func);
2828 const Address Addr = Mem->toAsmAddress(Asm, Target);
Andrew Scullcfa628b2015-08-20 14:23:05 -07002829 Asm->xchg(Ty, Addr, Reg1);
John Porto921856d2015-07-07 11:56:26 -07002830}
2831
John Porto4a566862016-01-04 09:33:41 -08002832template <typename TraitsType>
2833void InstImpl<TraitsType>::InstX86Xchg::dump(const Cfg *Func) const {
John Porto921856d2015-07-07 11:56:26 -07002834 if (!BuildDefs::dump())
2835 return;
2836 Ostream &Str = Func->getContext()->getStrDump();
2837 Type Ty = this->getSrc(0)->getType();
2838 Str << "xchg." << Ty << " ";
2839 this->dumpSources(Func);
2840}
2841
John Porto4a566862016-01-04 09:33:41 -08002842template <typename TraitsType>
2843void InstImpl<TraitsType>::InstX86IacaStart::emit(const Cfg *Func) const {
Andrew Scull2c862522015-08-06 08:41:53 -07002844 if (!BuildDefs::dump())
2845 return;
2846 Ostream &Str = Func->getContext()->getStrEmit();
2847 Str << "\t# IACA_START\n"
Jim Stichnoth6106df82015-12-16 06:17:58 -08002848 "\t.byte 0x0F, 0x0B\n"
2849 "\t"
2850 "movl\t$111, %ebx\n"
2851 "\t.byte 0x64, 0x67, 0x90";
Andrew Scull2c862522015-08-06 08:41:53 -07002852}
2853
John Porto4a566862016-01-04 09:33:41 -08002854template <typename TraitsType>
2855void InstImpl<TraitsType>::InstX86IacaStart::emitIAS(const Cfg *Func) const {
2856 Assembler *Asm = Func->getAssembler<Assembler>();
Andrew Scull2c862522015-08-06 08:41:53 -07002857 Asm->iaca_start();
2858}
2859
John Porto4a566862016-01-04 09:33:41 -08002860template <typename TraitsType>
2861void InstImpl<TraitsType>::InstX86IacaStart::dump(const Cfg *Func) const {
Andrew Scull2c862522015-08-06 08:41:53 -07002862 if (!BuildDefs::dump())
2863 return;
2864 Ostream &Str = Func->getContext()->getStrDump();
2865 Str << "IACA_START";
2866}
2867
John Porto4a566862016-01-04 09:33:41 -08002868template <typename TraitsType>
2869void InstImpl<TraitsType>::InstX86IacaEnd::emit(const Cfg *Func) const {
Andrew Scull2c862522015-08-06 08:41:53 -07002870 if (!BuildDefs::dump())
2871 return;
2872 Ostream &Str = Func->getContext()->getStrEmit();
2873 Str << "\t# IACA_END\n"
Jim Stichnoth6106df82015-12-16 06:17:58 -08002874 "\t"
2875 "movl\t$222, %ebx\n"
2876 "\t.byte 0x64, 0x67, 0x90\n"
2877 "\t.byte 0x0F, 0x0B";
Andrew Scull2c862522015-08-06 08:41:53 -07002878}
2879
John Porto4a566862016-01-04 09:33:41 -08002880template <typename TraitsType>
2881void InstImpl<TraitsType>::InstX86IacaEnd::emitIAS(const Cfg *Func) const {
2882 Assembler *Asm = Func->getAssembler<Assembler>();
Andrew Scull2c862522015-08-06 08:41:53 -07002883 Asm->iaca_end();
2884}
2885
John Porto4a566862016-01-04 09:33:41 -08002886template <typename TraitsType>
2887void InstImpl<TraitsType>::InstX86IacaEnd::dump(const Cfg *Func) const {
Andrew Scull2c862522015-08-06 08:41:53 -07002888 if (!BuildDefs::dump())
2889 return;
2890 Ostream &Str = Func->getContext()->getStrDump();
2891 Str << "IACA_END";
2892}
2893
John Porto4a566862016-01-04 09:33:41 -08002894} // end of namespace X86NAMESPACE
John Porto921856d2015-07-07 11:56:26 -07002895
2896} // end of namespace Ice
2897
2898#endif // SUBZERO_SRC_ICEINSTX86BASEIMPL_H