blob: fb9bba00f81a08a69cd227f9fa4ca80f2d7af9b8 [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),
Jim Stichnoth467ffe52016-03-29 15:01:06 -070097 LabelNumber(Target->makeNextLabelNumber()) {
98 if (BuildDefs::dump()) {
99 Name = GlobalString::createWithString(
100 Func->getContext(), ".L" + Func->getFunctionName() + "$local$__" +
101 std::to_string(LabelNumber));
102 } else {
103 Name = GlobalString::createWithoutString(Func->getContext());
104 }
John Porto921856d2015-07-07 11:56:26 -0700105}
106
John Porto4a566862016-01-04 09:33:41 -0800107template <typename TraitsType>
Jim Stichnoth5d5b6622016-09-09 09:29:08 -0700108InstImpl<TraitsType>::InstX86Br::InstX86Br(Cfg *Func, const CfgNode *TargetTrue,
109 const CfgNode *TargetFalse,
110 const InstX86Label *Label,
111 BrCond Condition, Mode Kind)
John Porto4a566862016-01-04 09:33:41 -0800112 : InstX86Base(Func, InstX86Base::Br, 0, nullptr), Condition(Condition),
113 TargetTrue(TargetTrue), TargetFalse(TargetFalse), Label(Label),
114 Kind(Kind) {}
John Porto921856d2015-07-07 11:56:26 -0700115
John Porto4a566862016-01-04 09:33:41 -0800116template <typename TraitsType>
117bool InstImpl<TraitsType>::InstX86Br::optimizeBranch(const CfgNode *NextNode) {
Andrew Scull57e12682015-09-16 11:30:19 -0700118 // If there is no next block, then there can be no fallthrough to optimize.
John Porto921856d2015-07-07 11:56:26 -0700119 if (NextNode == nullptr)
120 return false;
121 // Intra-block conditional branches can't be optimized.
122 if (Label)
123 return false;
Andrew Scull57e12682015-09-16 11:30:19 -0700124 // If there is no fallthrough node, such as a non-default case label for a
125 // switch instruction, then there is no opportunity to optimize.
John Porto921856d2015-07-07 11:56:26 -0700126 if (getTargetFalse() == nullptr)
127 return false;
128
129 // Unconditional branch to the next node can be removed.
John Porto4a566862016-01-04 09:33:41 -0800130 if (Condition == Cond::Br_None && getTargetFalse() == NextNode) {
John Porto921856d2015-07-07 11:56:26 -0700131 assert(getTargetTrue() == nullptr);
132 this->setDeleted();
133 return true;
134 }
Andrew Scull57e12682015-09-16 11:30:19 -0700135 // If the fallthrough is to the next node, set fallthrough to nullptr to
136 // indicate.
John Porto921856d2015-07-07 11:56:26 -0700137 if (getTargetFalse() == NextNode) {
138 TargetFalse = nullptr;
139 return true;
140 }
Andrew Scull57e12682015-09-16 11:30:19 -0700141 // If TargetTrue is the next node, and TargetFalse is not nullptr (which was
142 // already tested above), then invert the branch condition, swap the targets,
143 // and set new fallthrough to nullptr.
John Porto921856d2015-07-07 11:56:26 -0700144 if (getTargetTrue() == NextNode) {
John Porto4a566862016-01-04 09:33:41 -0800145 assert(Condition != Cond::Br_None);
John Porto921856d2015-07-07 11:56:26 -0700146 Condition = this->getOppositeCondition(Condition);
147 TargetTrue = getTargetFalse();
148 TargetFalse = nullptr;
149 return true;
150 }
151 return false;
152}
153
John Porto4a566862016-01-04 09:33:41 -0800154template <typename TraitsType>
155bool InstImpl<TraitsType>::InstX86Br::repointEdges(CfgNode *OldNode,
156 CfgNode *NewNode) {
Andrew Scull87f80c12015-07-20 10:19:16 -0700157 bool Found = false;
John Porto921856d2015-07-07 11:56:26 -0700158 if (TargetFalse == OldNode) {
159 TargetFalse = NewNode;
Andrew Scull87f80c12015-07-20 10:19:16 -0700160 Found = true;
John Porto921856d2015-07-07 11:56:26 -0700161 }
Andrew Scull87f80c12015-07-20 10:19:16 -0700162 if (TargetTrue == OldNode) {
163 TargetTrue = NewNode;
164 Found = true;
165 }
166 return Found;
John Porto921856d2015-07-07 11:56:26 -0700167}
168
John Porto4a566862016-01-04 09:33:41 -0800169template <typename TraitsType>
170InstImpl<TraitsType>::InstX86Jmp::InstX86Jmp(Cfg *Func, Operand *Target)
171 : InstX86Base(Func, InstX86Base::Jmp, 1, nullptr) {
John Porto921856d2015-07-07 11:56:26 -0700172 this->addSource(Target);
173}
174
John Porto4a566862016-01-04 09:33:41 -0800175template <typename TraitsType>
176InstImpl<TraitsType>::InstX86Call::InstX86Call(Cfg *Func, Variable *Dest,
177 Operand *CallTarget)
178 : InstX86Base(Func, InstX86Base::Call, 1, Dest) {
John Porto921856d2015-07-07 11:56:26 -0700179 this->HasSideEffects = true;
180 this->addSource(CallTarget);
181}
182
John Porto4a566862016-01-04 09:33:41 -0800183template <typename TraitsType>
Nicolas Capense3cabda2016-10-18 16:27:27 -0400184InstImpl<TraitsType>::InstX86Movmsk::InstX86Movmsk(Cfg *Func, Variable *Dest,
185 Operand *Source)
186 : InstX86Base(Func, InstX86Base::Movmsk, 1, Dest) {
187 this->addSource(Source);
188}
189
190template <typename TraitsType>
John Porto4a566862016-01-04 09:33:41 -0800191InstImpl<TraitsType>::InstX86Cmov::InstX86Cmov(Cfg *Func, Variable *Dest,
192 Operand *Source,
193 BrCond Condition)
194 : InstX86Base(Func, InstX86Base::Cmov, 2, Dest), Condition(Condition) {
Andrew Scull57e12682015-09-16 11:30:19 -0700195 // The final result is either the original Dest, or Source, so mark both as
196 // sources.
John Porto921856d2015-07-07 11:56:26 -0700197 this->addSource(Dest);
198 this->addSource(Source);
199}
200
John Porto4a566862016-01-04 09:33:41 -0800201template <typename TraitsType>
202InstImpl<TraitsType>::InstX86Cmpps::InstX86Cmpps(Cfg *Func, Variable *Dest,
203 Operand *Source,
204 CmppsCond Condition)
205 : InstX86Base(Func, InstX86Base::Cmpps, 2, Dest), Condition(Condition) {
John Porto921856d2015-07-07 11:56:26 -0700206 this->addSource(Dest);
207 this->addSource(Source);
208}
209
John Porto4a566862016-01-04 09:33:41 -0800210template <typename TraitsType>
211InstImpl<TraitsType>::InstX86Cmpxchg::InstX86Cmpxchg(Cfg *Func,
212 Operand *DestOrAddr,
213 Variable *Eax,
214 Variable *Desired,
215 bool Locked)
216 : InstImpl<TraitsType>::InstX86BaseLockable(
217 Func, InstX86Base::Cmpxchg, 3, llvm::dyn_cast<Variable>(DestOrAddr),
218 Locked) {
John Porto3c275ce2015-12-22 08:14:00 -0800219 constexpr uint16_t Encoded_rAX = 0;
220 (void)Encoded_rAX;
John Porto4a566862016-01-04 09:33:41 -0800221 assert(Traits::getEncodedGPR(Eax->getRegNum()) == Encoded_rAX);
John Porto921856d2015-07-07 11:56:26 -0700222 this->addSource(DestOrAddr);
223 this->addSource(Eax);
224 this->addSource(Desired);
225}
226
John Porto4a566862016-01-04 09:33:41 -0800227template <typename TraitsType>
228InstImpl<TraitsType>::InstX86Cmpxchg8b::InstX86Cmpxchg8b(
229 Cfg *Func, X86OperandMem *Addr, Variable *Edx, Variable *Eax, Variable *Ecx,
230 Variable *Ebx, bool Locked)
231 : InstImpl<TraitsType>::InstX86BaseLockable(Func, InstX86Base::Cmpxchg, 5,
232 nullptr, Locked) {
233 assert(Edx->getRegNum() == RegisterSet::Reg_edx);
234 assert(Eax->getRegNum() == RegisterSet::Reg_eax);
235 assert(Ecx->getRegNum() == RegisterSet::Reg_ecx);
236 assert(Ebx->getRegNum() == RegisterSet::Reg_ebx);
John Porto921856d2015-07-07 11:56:26 -0700237 this->addSource(Addr);
238 this->addSource(Edx);
239 this->addSource(Eax);
240 this->addSource(Ecx);
241 this->addSource(Ebx);
242}
243
John Porto4a566862016-01-04 09:33:41 -0800244template <typename TraitsType>
245InstImpl<TraitsType>::InstX86Cvt::InstX86Cvt(Cfg *Func, Variable *Dest,
246 Operand *Source,
247 CvtVariant Variant)
248 : InstX86Base(Func, InstX86Base::Cvt, 1, Dest), Variant(Variant) {
John Porto921856d2015-07-07 11:56:26 -0700249 this->addSource(Source);
250}
251
John Porto4a566862016-01-04 09:33:41 -0800252template <typename TraitsType>
253InstImpl<TraitsType>::InstX86Icmp::InstX86Icmp(Cfg *Func, Operand *Src0,
254 Operand *Src1)
255 : InstX86Base(Func, InstX86Base::Icmp, 2, nullptr) {
John Porto921856d2015-07-07 11:56:26 -0700256 this->addSource(Src0);
257 this->addSource(Src1);
258}
259
John Porto4a566862016-01-04 09:33:41 -0800260template <typename TraitsType>
261InstImpl<TraitsType>::InstX86Ucomiss::InstX86Ucomiss(Cfg *Func, Operand *Src0,
262 Operand *Src1)
263 : InstX86Base(Func, InstX86Base::Ucomiss, 2, nullptr) {
John Porto921856d2015-07-07 11:56:26 -0700264 this->addSource(Src0);
265 this->addSource(Src1);
266}
267
John Porto4a566862016-01-04 09:33:41 -0800268template <typename TraitsType>
269InstImpl<TraitsType>::InstX86UD2::InstX86UD2(Cfg *Func)
270 : InstX86Base(Func, InstX86Base::UD2, 0, nullptr) {}
John Porto921856d2015-07-07 11:56:26 -0700271
John Porto4a566862016-01-04 09:33:41 -0800272template <typename TraitsType>
Eric Holk67c7c412016-04-15 13:05:37 -0700273InstImpl<TraitsType>::InstX86Int3::InstX86Int3(Cfg *Func)
274 : InstX86Base(Func, InstX86Base::Int3, 0, nullptr) {}
275
276template <typename TraitsType>
John Porto4a566862016-01-04 09:33:41 -0800277InstImpl<TraitsType>::InstX86Test::InstX86Test(Cfg *Func, Operand *Src1,
278 Operand *Src2)
279 : InstX86Base(Func, InstX86Base::Test, 2, nullptr) {
John Porto921856d2015-07-07 11:56:26 -0700280 this->addSource(Src1);
281 this->addSource(Src2);
282}
283
John Porto4a566862016-01-04 09:33:41 -0800284template <typename TraitsType>
285InstImpl<TraitsType>::InstX86Mfence::InstX86Mfence(Cfg *Func)
286 : InstX86Base(Func, InstX86Base::Mfence, 0, nullptr) {
John Porto921856d2015-07-07 11:56:26 -0700287 this->HasSideEffects = true;
288}
289
John Porto4a566862016-01-04 09:33:41 -0800290template <typename TraitsType>
291InstImpl<TraitsType>::InstX86Store::InstX86Store(Cfg *Func, Operand *Value,
292 X86Operand *Mem)
293 : InstX86Base(Func, InstX86Base::Store, 2, nullptr) {
John Porto921856d2015-07-07 11:56:26 -0700294 this->addSource(Value);
295 this->addSource(Mem);
296}
297
John Porto4a566862016-01-04 09:33:41 -0800298template <typename TraitsType>
299InstImpl<TraitsType>::InstX86StoreP::InstX86StoreP(Cfg *Func, Variable *Value,
300 X86OperandMem *Mem)
301 : InstX86Base(Func, InstX86Base::StoreP, 2, nullptr) {
John Porto921856d2015-07-07 11:56:26 -0700302 this->addSource(Value);
303 this->addSource(Mem);
304}
305
John Porto4a566862016-01-04 09:33:41 -0800306template <typename TraitsType>
Nicolas Capensacfb3df2016-10-03 10:46:30 -0400307InstImpl<TraitsType>::InstX86StoreQ::InstX86StoreQ(Cfg *Func, Operand *Value,
John Porto4a566862016-01-04 09:33:41 -0800308 X86OperandMem *Mem)
309 : InstX86Base(Func, InstX86Base::StoreQ, 2, nullptr) {
John Porto921856d2015-07-07 11:56:26 -0700310 this->addSource(Value);
311 this->addSource(Mem);
312}
313
John Porto4a566862016-01-04 09:33:41 -0800314template <typename TraitsType>
Nicolas Capensacfb3df2016-10-03 10:46:30 -0400315InstImpl<TraitsType>::InstX86StoreD::InstX86StoreD(Cfg *Func, Operand *Value,
316 X86OperandMem *Mem)
317 : InstX86Base(Func, InstX86Base::StoreD, 2, nullptr) {
318 this->addSource(Value);
319 this->addSource(Mem);
320}
321
322template <typename TraitsType>
Jim Stichnoth5d5b6622016-09-09 09:29:08 -0700323InstImpl<TraitsType>::InstX86Nop::InstX86Nop(Cfg *Func, NopVariant Variant)
John Porto4a566862016-01-04 09:33:41 -0800324 : InstX86Base(Func, InstX86Base::Nop, 0, nullptr), Variant(Variant) {}
John Porto921856d2015-07-07 11:56:26 -0700325
John Porto4a566862016-01-04 09:33:41 -0800326template <typename TraitsType>
327InstImpl<TraitsType>::InstX86Fld::InstX86Fld(Cfg *Func, Operand *Src)
328 : InstX86Base(Func, InstX86Base::Fld, 1, nullptr) {
John Porto921856d2015-07-07 11:56:26 -0700329 this->addSource(Src);
330}
331
John Porto4a566862016-01-04 09:33:41 -0800332template <typename TraitsType>
333InstImpl<TraitsType>::InstX86Fstp::InstX86Fstp(Cfg *Func, Variable *Dest)
334 : InstX86Base(Func, InstX86Base::Fstp, 0, Dest) {}
John Porto921856d2015-07-07 11:56:26 -0700335
John Porto4a566862016-01-04 09:33:41 -0800336template <typename TraitsType>
337InstImpl<TraitsType>::InstX86Pop::InstX86Pop(Cfg *Func, Variable *Dest)
338 : InstX86Base(Func, InstX86Base::Pop, 0, Dest) {
Andrew Scull57e12682015-09-16 11:30:19 -0700339 // A pop instruction affects the stack pointer and so it should not be
340 // allowed to be automatically dead-code eliminated. (The corresponding push
341 // instruction doesn't need this treatment because it has no dest variable
342 // and therefore won't be dead-code eliminated.) This is needed for
343 // late-stage liveness analysis (e.g. asm-verbose mode).
John Porto921856d2015-07-07 11:56:26 -0700344 this->HasSideEffects = true;
345}
346
John Porto4a566862016-01-04 09:33:41 -0800347template <typename TraitsType>
John Porto56958cb2016-01-14 09:18:18 -0800348InstImpl<TraitsType>::InstX86Push::InstX86Push(Cfg *Func, Operand *Source)
John Porto4a566862016-01-04 09:33:41 -0800349 : InstX86Base(Func, InstX86Base::Push, 1, nullptr) {
John Porto921856d2015-07-07 11:56:26 -0700350 this->addSource(Source);
351}
352
John Porto4a566862016-01-04 09:33:41 -0800353template <typename TraitsType>
John Porto56958cb2016-01-14 09:18:18 -0800354InstImpl<TraitsType>::InstX86Push::InstX86Push(Cfg *Func, InstX86Label *L)
355 : InstX86Base(Func, InstX86Base::Push, 0, nullptr), Label(L) {}
356
357template <typename TraitsType>
John Porto4a566862016-01-04 09:33:41 -0800358InstImpl<TraitsType>::InstX86Ret::InstX86Ret(Cfg *Func, Variable *Source)
359 : InstX86Base(Func, InstX86Base::Ret, Source ? 1 : 0, nullptr) {
John Porto921856d2015-07-07 11:56:26 -0700360 if (Source)
361 this->addSource(Source);
362}
363
John Porto4a566862016-01-04 09:33:41 -0800364template <typename TraitsType>
365InstImpl<TraitsType>::InstX86Setcc::InstX86Setcc(Cfg *Func, Variable *Dest,
366 BrCond Cond)
367 : InstX86Base(Func, InstX86Base::Setcc, 0, Dest), Condition(Cond) {}
John Porto921856d2015-07-07 11:56:26 -0700368
John Porto4a566862016-01-04 09:33:41 -0800369template <typename TraitsType>
370InstImpl<TraitsType>::InstX86Xadd::InstX86Xadd(Cfg *Func, Operand *Dest,
371 Variable *Source, bool Locked)
372 : InstImpl<TraitsType>::InstX86BaseLockable(
373 Func, InstX86Base::Xadd, 2, llvm::dyn_cast<Variable>(Dest), Locked) {
John Porto921856d2015-07-07 11:56:26 -0700374 this->addSource(Dest);
375 this->addSource(Source);
376}
377
John Porto4a566862016-01-04 09:33:41 -0800378template <typename TraitsType>
379InstImpl<TraitsType>::InstX86Xchg::InstX86Xchg(Cfg *Func, Operand *Dest,
380 Variable *Source)
381 : InstX86Base(Func, InstX86Base::Xchg, 2, llvm::dyn_cast<Variable>(Dest)) {
John Porto921856d2015-07-07 11:56:26 -0700382 this->addSource(Dest);
383 this->addSource(Source);
384}
385
John Porto4a566862016-01-04 09:33:41 -0800386template <typename TraitsType>
387InstImpl<TraitsType>::InstX86IacaStart::InstX86IacaStart(Cfg *Func)
388 : InstX86Base(Func, InstX86Base::IacaStart, 0, nullptr) {
Karl Schimpfd4699942016-04-02 09:55:31 -0700389 assert(getFlags().getAllowIacaMarks());
Andrew Scull2c862522015-08-06 08:41:53 -0700390}
391
John Porto4a566862016-01-04 09:33:41 -0800392template <typename TraitsType>
393InstImpl<TraitsType>::InstX86IacaEnd::InstX86IacaEnd(Cfg *Func)
394 : InstX86Base(Func, InstX86Base::IacaEnd, 0, nullptr) {
Karl Schimpfd4699942016-04-02 09:55:31 -0700395 assert(getFlags().getAllowIacaMarks());
Andrew Scull2c862522015-08-06 08:41:53 -0700396}
397
John Porto921856d2015-07-07 11:56:26 -0700398// ======================== Dump routines ======================== //
399
John Porto4a566862016-01-04 09:33:41 -0800400template <typename TraitsType>
401void InstImpl<TraitsType>::InstX86Base::dump(const Cfg *Func) const {
John Porto921856d2015-07-07 11:56:26 -0700402 if (!BuildDefs::dump())
403 return;
404 Ostream &Str = Func->getContext()->getStrDump();
405 Str << "[" << Traits::TargetName << "] ";
406 Inst::dump(Func);
407}
408
John Porto4a566862016-01-04 09:33:41 -0800409template <typename TraitsType>
410void InstImpl<TraitsType>::InstX86FakeRMW::dump(const Cfg *Func) const {
John Porto921856d2015-07-07 11:56:26 -0700411 if (!BuildDefs::dump())
412 return;
413 Ostream &Str = Func->getContext()->getStrDump();
414 Type Ty = getData()->getType();
415 Str << "rmw " << InstArithmetic::getOpName(getOp()) << " " << Ty << " *";
416 getAddr()->dump(Func);
417 Str << ", ";
418 getData()->dump(Func);
419 Str << ", beacon=";
420 getBeacon()->dump(Func);
421}
422
John Porto4a566862016-01-04 09:33:41 -0800423template <typename TraitsType>
Jim Stichnoth8ff4b282016-01-04 15:39:06 -0800424void InstImpl<TraitsType>::InstX86GetIP::emit(const Cfg *Func) const {
425 if (!BuildDefs::dump())
426 return;
John Porto6e8d3fa2016-02-04 10:35:20 -0800427 const auto *Dest = this->getDest();
428 assert(Dest->hasReg());
Jim Stichnoth8ff4b282016-01-04 15:39:06 -0800429 Ostream &Str = Func->getContext()->getStrEmit();
Jim Stichnoth8ff4b282016-01-04 15:39:06 -0800430 Str << "\t"
John Porto6e8d3fa2016-02-04 10:35:20 -0800431 "call"
432 "\t";
433 auto *Target = static_cast<TargetLowering *>(Func->getTarget());
434 Target->emitWithoutPrefix(Target->createGetIPForRegister(Dest));
Jim Stichnoth8ff4b282016-01-04 15:39:06 -0800435}
436
437template <typename TraitsType>
438void InstImpl<TraitsType>::InstX86GetIP::emitIAS(const Cfg *Func) const {
John Porto6e8d3fa2016-02-04 10:35:20 -0800439 const auto *Dest = this->getDest();
Jim Stichnoth8ff4b282016-01-04 15:39:06 -0800440 Assembler *Asm = Func->getAssembler<Assembler>();
John Porto6e8d3fa2016-02-04 10:35:20 -0800441 assert(Dest->hasReg());
442 Asm->call(static_cast<TargetLowering *>(Func->getTarget())
443 ->createGetIPForRegister(Dest));
Jim Stichnoth8ff4b282016-01-04 15:39:06 -0800444}
445
446template <typename TraitsType>
447void InstImpl<TraitsType>::InstX86GetIP::dump(const Cfg *Func) const {
448 if (!BuildDefs::dump())
449 return;
450 Ostream &Str = Func->getContext()->getStrDump();
451 this->getDest()->dump(Func);
452 Str << " = call getIP";
453}
454
455template <typename TraitsType>
John Porto4a566862016-01-04 09:33:41 -0800456void InstImpl<TraitsType>::InstX86Label::emit(const Cfg *Func) const {
John Porto921856d2015-07-07 11:56:26 -0700457 if (!BuildDefs::dump())
458 return;
459 Ostream &Str = Func->getContext()->getStrEmit();
Jim Stichnoth467ffe52016-03-29 15:01:06 -0700460 Str << getLabelName() << ":";
John Porto921856d2015-07-07 11:56:26 -0700461}
462
John Porto4a566862016-01-04 09:33:41 -0800463template <typename TraitsType>
464void InstImpl<TraitsType>::InstX86Label::emitIAS(const Cfg *Func) const {
465 Assembler *Asm = Func->getAssembler<Assembler>();
Jim Stichnoth467ffe52016-03-29 15:01:06 -0700466 Asm->bindLocalLabel(LabelNumber);
John Porto27fddcc2016-02-02 15:06:09 -0800467 if (OffsetReloc != nullptr) {
468 Asm->bindRelocOffset(OffsetReloc);
469 }
John Porto921856d2015-07-07 11:56:26 -0700470}
471
John Porto4a566862016-01-04 09:33:41 -0800472template <typename TraitsType>
473void InstImpl<TraitsType>::InstX86Label::dump(const Cfg *Func) const {
John Porto921856d2015-07-07 11:56:26 -0700474 if (!BuildDefs::dump())
475 return;
476 Ostream &Str = Func->getContext()->getStrDump();
Jim Stichnoth467ffe52016-03-29 15:01:06 -0700477 Str << getLabelName() << ":";
John Porto921856d2015-07-07 11:56:26 -0700478}
479
John Porto4a566862016-01-04 09:33:41 -0800480template <typename TraitsType>
481void InstImpl<TraitsType>::InstX86Br::emit(const Cfg *Func) const {
John Porto921856d2015-07-07 11:56:26 -0700482 if (!BuildDefs::dump())
483 return;
484 Ostream &Str = Func->getContext()->getStrEmit();
485 Str << "\t";
486
John Porto4a566862016-01-04 09:33:41 -0800487 if (Condition == Cond::Br_None) {
John Porto921856d2015-07-07 11:56:26 -0700488 Str << "jmp";
489 } else {
John Porto4a566862016-01-04 09:33:41 -0800490 Str << Traits::InstBrAttributes[Condition].EmitString;
John Porto921856d2015-07-07 11:56:26 -0700491 }
492
493 if (Label) {
Jim Stichnoth467ffe52016-03-29 15:01:06 -0700494 Str << "\t" << Label->getLabelName();
John Porto921856d2015-07-07 11:56:26 -0700495 } else {
John Porto4a566862016-01-04 09:33:41 -0800496 if (Condition == Cond::Br_None) {
John Porto921856d2015-07-07 11:56:26 -0700497 Str << "\t" << getTargetFalse()->getAsmName();
498 } else {
499 Str << "\t" << getTargetTrue()->getAsmName();
500 if (getTargetFalse()) {
Jim Stichnoth6106df82015-12-16 06:17:58 -0800501 Str << "\n\t"
502 "jmp\t" << getTargetFalse()->getAsmName();
John Porto921856d2015-07-07 11:56:26 -0700503 }
504 }
505 }
506}
507
John Porto4a566862016-01-04 09:33:41 -0800508template <typename TraitsType>
509void InstImpl<TraitsType>::InstX86Br::emitIAS(const Cfg *Func) const {
510 Assembler *Asm = Func->getAssembler<Assembler>();
John Porto921856d2015-07-07 11:56:26 -0700511 if (Label) {
Jim Stichnoth467ffe52016-03-29 15:01:06 -0700512 auto *L = Asm->getOrCreateLocalLabel(Label->getLabelNumber());
John Porto4a566862016-01-04 09:33:41 -0800513 if (Condition == Cond::Br_None) {
Andrew Scull86df4e92015-07-30 13:54:44 -0700514 Asm->jmp(L, isNear());
John Porto921856d2015-07-07 11:56:26 -0700515 } else {
Andrew Scull86df4e92015-07-30 13:54:44 -0700516 Asm->j(Condition, L, isNear());
John Porto921856d2015-07-07 11:56:26 -0700517 }
518 } else {
John Porto4a566862016-01-04 09:33:41 -0800519 if (Condition == Cond::Br_None) {
520 auto *L = Asm->getOrCreateCfgNodeLabel(getTargetFalse()->getIndex());
John Porto921856d2015-07-07 11:56:26 -0700521 assert(!getTargetTrue());
Andrew Scull86df4e92015-07-30 13:54:44 -0700522 Asm->jmp(L, isNear());
John Porto921856d2015-07-07 11:56:26 -0700523 } else {
John Porto4a566862016-01-04 09:33:41 -0800524 auto *L = Asm->getOrCreateCfgNodeLabel(getTargetTrue()->getIndex());
Andrew Scull86df4e92015-07-30 13:54:44 -0700525 Asm->j(Condition, L, isNear());
John Porto921856d2015-07-07 11:56:26 -0700526 if (getTargetFalse()) {
John Porto4a566862016-01-04 09:33:41 -0800527 auto *L2 = Asm->getOrCreateCfgNodeLabel(getTargetFalse()->getIndex());
Andrew Scull86df4e92015-07-30 13:54:44 -0700528 Asm->jmp(L2, isNear());
John Porto921856d2015-07-07 11:56:26 -0700529 }
530 }
531 }
532}
533
John Porto4a566862016-01-04 09:33:41 -0800534template <typename TraitsType>
535void InstImpl<TraitsType>::InstX86Br::dump(const Cfg *Func) const {
John Porto921856d2015-07-07 11:56:26 -0700536 if (!BuildDefs::dump())
537 return;
538 Ostream &Str = Func->getContext()->getStrDump();
539 Str << "br ";
540
John Porto4a566862016-01-04 09:33:41 -0800541 if (Condition == Cond::Br_None) {
Jim Stichnoth467ffe52016-03-29 15:01:06 -0700542 if (Label) {
543 Str << "label %" << Label->getLabelName();
544 } else {
545 Str << "label %" << getTargetFalse()->getName();
546 }
John Porto921856d2015-07-07 11:56:26 -0700547 return;
548 }
549
John Porto4a566862016-01-04 09:33:41 -0800550 Str << Traits::InstBrAttributes[Condition].DisplayString;
John Porto921856d2015-07-07 11:56:26 -0700551 if (Label) {
Jim Stichnoth467ffe52016-03-29 15:01:06 -0700552 Str << ", label %" << Label->getLabelName();
John Porto921856d2015-07-07 11:56:26 -0700553 } else {
554 Str << ", label %" << getTargetTrue()->getName();
555 if (getTargetFalse()) {
556 Str << ", label %" << getTargetFalse()->getName();
557 }
558 }
Andrew Scull86df4e92015-07-30 13:54:44 -0700559
560 Str << " // (" << (isNear() ? "near" : "far") << " jump)";
John Porto921856d2015-07-07 11:56:26 -0700561}
562
John Porto4a566862016-01-04 09:33:41 -0800563template <typename TraitsType>
564void InstImpl<TraitsType>::InstX86Jmp::emit(const Cfg *Func) const {
John Porto921856d2015-07-07 11:56:26 -0700565 if (!BuildDefs::dump())
566 return;
567 Ostream &Str = Func->getContext()->getStrEmit();
568 assert(this->getSrcSize() == 1);
John Porto56958cb2016-01-14 09:18:18 -0800569 const Operand *Src = this->getSrc(0);
570 if (Traits::Is64Bit) {
571 if (const auto *CR = llvm::dyn_cast<ConstantRelocatable>(Src)) {
572 Str << "\t"
573 "jmp"
574 "\t" << CR->getName();
575 return;
576 }
577 }
Jim Stichnoth6106df82015-12-16 06:17:58 -0800578 Str << "\t"
John Porto56958cb2016-01-14 09:18:18 -0800579 "jmp"
580 "\t*";
John Porto921856d2015-07-07 11:56:26 -0700581 getJmpTarget()->emit(Func);
582}
583
John Porto4a566862016-01-04 09:33:41 -0800584template <typename TraitsType>
585void InstImpl<TraitsType>::InstX86Jmp::emitIAS(const Cfg *Func) const {
586 // Note: Adapted (mostly copied) from
587 // InstImpl<TraitsType>::InstX86Call::emitIAS().
588 Assembler *Asm = Func->getAssembler<Assembler>();
John Porto921856d2015-07-07 11:56:26 -0700589 Operand *Target = getJmpTarget();
Jim Stichnoth5bff61c2015-10-28 09:26:00 -0700590 if (const auto *Var = llvm::dyn_cast<Variable>(Target)) {
John Porto921856d2015-07-07 11:56:26 -0700591 if (Var->hasReg()) {
John Porto4a566862016-01-04 09:33:41 -0800592 Asm->jmp(Traits::getEncodedGPR(Var->getRegNum()));
John Porto921856d2015-07-07 11:56:26 -0700593 } else {
Andrew Scull57e12682015-09-16 11:30:19 -0700594 // The jmp instruction with a memory operand should be possible to
595 // encode, but it isn't a valid sandboxed instruction, and there
596 // shouldn't be a register allocation issue to jump through a scratch
597 // register, so we don't really need to bother implementing it.
John Porto921856d2015-07-07 11:56:26 -0700598 llvm::report_fatal_error("Assembler can't jmp to memory operand");
599 }
John Porto4a566862016-01-04 09:33:41 -0800600 } else if (const auto *Mem = llvm::dyn_cast<X86OperandMem>(Target)) {
John Porto921856d2015-07-07 11:56:26 -0700601 (void)Mem;
John Porto4a566862016-01-04 09:33:41 -0800602 assert(Mem->getSegmentRegister() == X86OperandMem::DefaultSegment);
John Porto921856d2015-07-07 11:56:26 -0700603 llvm::report_fatal_error("Assembler can't jmp to memory operand");
Jim Stichnoth5bff61c2015-10-28 09:26:00 -0700604 } else if (const auto *CR = llvm::dyn_cast<ConstantRelocatable>(Target)) {
John Porto921856d2015-07-07 11:56:26 -0700605 Asm->jmp(CR);
Jim Stichnoth5bff61c2015-10-28 09:26:00 -0700606 } else if (const auto *Imm = llvm::dyn_cast<ConstantInteger32>(Target)) {
John Porto921856d2015-07-07 11:56:26 -0700607 // NaCl trampoline calls refer to an address within the sandbox directly.
Andrew Scull57e12682015-09-16 11:30:19 -0700608 // This is usually only needed for non-IRT builds and otherwise not very
609 // portable or stable. Usually this is only done for "calls" and not jumps.
John Porto34d276a2016-01-27 06:31:53 -0800610 Asm->jmp(AssemblerImmediate(Imm->getValue()));
John Porto921856d2015-07-07 11:56:26 -0700611 } else {
612 llvm::report_fatal_error("Unexpected operand type");
613 }
614}
615
John Porto4a566862016-01-04 09:33:41 -0800616template <typename TraitsType>
617void InstImpl<TraitsType>::InstX86Jmp::dump(const Cfg *Func) const {
John Porto921856d2015-07-07 11:56:26 -0700618 if (!BuildDefs::dump())
619 return;
620 Ostream &Str = Func->getContext()->getStrDump();
621 Str << "jmp ";
622 getJmpTarget()->dump(Func);
623}
624
John Porto4a566862016-01-04 09:33:41 -0800625template <typename TraitsType>
626void InstImpl<TraitsType>::InstX86Call::emit(const Cfg *Func) const {
John Porto921856d2015-07-07 11:56:26 -0700627 if (!BuildDefs::dump())
628 return;
629 Ostream &Str = Func->getContext()->getStrEmit();
630 assert(this->getSrcSize() == 1);
Jim Stichnoth6106df82015-12-16 06:17:58 -0800631 Str << "\t"
632 "call\t";
David Sehr4318a412015-11-11 15:01:55 -0800633 Operand *CallTarget = getCallTarget();
John Porto4a566862016-01-04 09:33:41 -0800634 auto *Target = InstX86Base::getTarget(Func);
David Sehr4318a412015-11-11 15:01:55 -0800635 if (const auto *CI = llvm::dyn_cast<ConstantInteger32>(CallTarget)) {
John Porto921856d2015-07-07 11:56:26 -0700636 // Emit without a leading '$'.
637 Str << CI->getValue();
David Sehr4318a412015-11-11 15:01:55 -0800638 } else if (const auto DirectCallTarget =
639 llvm::dyn_cast<ConstantRelocatable>(CallTarget)) {
640 DirectCallTarget->emitWithoutPrefix(Target);
John Porto921856d2015-07-07 11:56:26 -0700641 } else {
642 Str << "*";
David Sehr4318a412015-11-11 15:01:55 -0800643 CallTarget->emit(Func);
John Porto921856d2015-07-07 11:56:26 -0700644 }
John Porto921856d2015-07-07 11:56:26 -0700645}
646
John Porto4a566862016-01-04 09:33:41 -0800647template <typename TraitsType>
648void InstImpl<TraitsType>::InstX86Call::emitIAS(const Cfg *Func) const {
649 Assembler *Asm = Func->getAssembler<Assembler>();
David Sehr4318a412015-11-11 15:01:55 -0800650 Operand *CallTarget = getCallTarget();
John Porto4a566862016-01-04 09:33:41 -0800651 auto *Target = InstX86Base::getTarget(Func);
David Sehr4318a412015-11-11 15:01:55 -0800652 if (const auto *Var = llvm::dyn_cast<Variable>(CallTarget)) {
John Porto921856d2015-07-07 11:56:26 -0700653 if (Var->hasReg()) {
John Porto4a566862016-01-04 09:33:41 -0800654 Asm->call(Traits::getEncodedGPR(Var->getRegNum()));
John Porto921856d2015-07-07 11:56:26 -0700655 } else {
David Sehrb8e49c12015-11-12 14:41:22 -0800656 Asm->call(Target->stackVarToAsmOperand(Var));
John Porto921856d2015-07-07 11:56:26 -0700657 }
John Porto4a566862016-01-04 09:33:41 -0800658 } else if (const auto *Mem = llvm::dyn_cast<X86OperandMem>(CallTarget)) {
659 assert(Mem->getSegmentRegister() == X86OperandMem::DefaultSegment);
David Sehr4318a412015-11-11 15:01:55 -0800660 Asm->call(Mem->toAsmAddress(Asm, Target));
661 } else if (const auto *CR = llvm::dyn_cast<ConstantRelocatable>(CallTarget)) {
John Porto921856d2015-07-07 11:56:26 -0700662 Asm->call(CR);
David Sehr4318a412015-11-11 15:01:55 -0800663 } else if (const auto *Imm = llvm::dyn_cast<ConstantInteger32>(CallTarget)) {
John Porto4a566862016-01-04 09:33:41 -0800664 Asm->call(AssemblerImmediate(Imm->getValue()));
John Porto921856d2015-07-07 11:56:26 -0700665 } else {
666 llvm_unreachable("Unexpected operand type");
667 }
John Porto921856d2015-07-07 11:56:26 -0700668}
669
John Porto4a566862016-01-04 09:33:41 -0800670template <typename TraitsType>
671void InstImpl<TraitsType>::InstX86Call::dump(const Cfg *Func) const {
John Porto921856d2015-07-07 11:56:26 -0700672 if (!BuildDefs::dump())
673 return;
674 Ostream &Str = Func->getContext()->getStrDump();
675 if (this->getDest()) {
676 this->dumpDest(Func);
677 Str << " = ";
678 }
679 Str << "call ";
680 getCallTarget()->dump(Func);
681}
682
Jim Stichnoth467ffe52016-03-29 15:01:06 -0700683// The this->Opcode parameter needs to be char* and not std::string because of
Jim Stichnoth5bff61c2015-10-28 09:26:00 -0700684// template issues.
John Porto4a566862016-01-04 09:33:41 -0800685template <typename TraitsType>
686void InstImpl<TraitsType>::InstX86Base::emitTwoAddress(
687 const Cfg *Func, const char *Opcode, const char *Suffix) const {
John Porto921856d2015-07-07 11:56:26 -0700688 if (!BuildDefs::dump())
689 return;
690 Ostream &Str = Func->getContext()->getStrEmit();
David Sehr6da7ae22015-12-17 15:01:30 -0800691 assert(getSrcSize() == 2);
692 Operand *Dest = getDest();
John Porto921856d2015-07-07 11:56:26 -0700693 if (Dest == nullptr)
David Sehr6da7ae22015-12-17 15:01:30 -0800694 Dest = getSrc(0);
695 assert(Dest == getSrc(0));
696 Operand *Src1 = getSrc(1);
697 Str << "\t" << Opcode << Suffix
John Porto4a566862016-01-04 09:33:41 -0800698 << InstX86Base::getWidthString(Dest->getType()) << "\t";
Jim Stichnoth5bff61c2015-10-28 09:26:00 -0700699 Src1->emit(Func);
John Porto921856d2015-07-07 11:56:26 -0700700 Str << ", ";
701 Dest->emit(Func);
702}
703
John Porto4a566862016-01-04 09:33:41 -0800704template <typename TraitsType>
705void InstImpl<TraitsType>::emitIASOpTyGPR(const Cfg *Func, Type Ty,
706 const Operand *Op,
707 const GPREmitterOneOp &Emitter) {
708 auto *Target = InstX86Base::getTarget(Func);
709 Assembler *Asm = Func->getAssembler<Assembler>();
Jim Stichnoth5bff61c2015-10-28 09:26:00 -0700710 if (const auto *Var = llvm::dyn_cast<Variable>(Op)) {
John Porto921856d2015-07-07 11:56:26 -0700711 if (Var->hasReg()) {
712 // We cheat a little and use GPRRegister even for byte operations.
John Porto4a566862016-01-04 09:33:41 -0800713 GPRRegister VarReg = Traits::getEncodedGPR(Var->getRegNum());
John Porto921856d2015-07-07 11:56:26 -0700714 (Asm->*(Emitter.Reg))(Ty, VarReg);
715 } else {
John Porto4a566862016-01-04 09:33:41 -0800716 Address StackAddr(Target->stackVarToAsmOperand(Var));
John Porto921856d2015-07-07 11:56:26 -0700717 (Asm->*(Emitter.Addr))(Ty, StackAddr);
718 }
John Porto4a566862016-01-04 09:33:41 -0800719 } else if (const auto *Mem = llvm::dyn_cast<X86OperandMem>(Op)) {
John Porto921856d2015-07-07 11:56:26 -0700720 Mem->emitSegmentOverride(Asm);
David Sehr4318a412015-11-11 15:01:55 -0800721 (Asm->*(Emitter.Addr))(Ty, Mem->toAsmAddress(Asm, Target));
John Porto921856d2015-07-07 11:56:26 -0700722 } else {
723 llvm_unreachable("Unexpected operand type");
724 }
725}
726
John Porto4a566862016-01-04 09:33:41 -0800727template <typename TraitsType>
728template <bool VarCanBeByte, bool SrcCanBeByte>
John Porto56958cb2016-01-14 09:18:18 -0800729void InstImpl<TraitsType>::emitIASRegOpTyGPR(const Cfg *Func, bool IsLea,
730 Type Ty, const Variable *Var,
John Porto4a566862016-01-04 09:33:41 -0800731 const Operand *Src,
732 const GPREmitterRegOp &Emitter) {
733 auto *Target = InstX86Base::getTarget(Func);
734 Assembler *Asm = Func->getAssembler<Assembler>();
John Porto921856d2015-07-07 11:56:26 -0700735 assert(Var->hasReg());
736 // We cheat a little and use GPRRegister even for byte operations.
John Porto4a566862016-01-04 09:33:41 -0800737 GPRRegister VarReg = VarCanBeByte ? Traits::getEncodedGPR(Var->getRegNum())
738 : Traits::getEncodedGPR(Var->getRegNum());
Jim Stichnoth5bff61c2015-10-28 09:26:00 -0700739 if (const auto *SrcVar = llvm::dyn_cast<Variable>(Src)) {
John Porto921856d2015-07-07 11:56:26 -0700740 if (SrcVar->hasReg()) {
John Porto4a566862016-01-04 09:33:41 -0800741 GPRRegister SrcReg = SrcCanBeByte
742 ? Traits::getEncodedGPR(SrcVar->getRegNum())
743 : Traits::getEncodedGPR(SrcVar->getRegNum());
John Porto921856d2015-07-07 11:56:26 -0700744 (Asm->*(Emitter.GPRGPR))(Ty, VarReg, SrcReg);
745 } else {
John Porto4a566862016-01-04 09:33:41 -0800746 Address SrcStackAddr = Target->stackVarToAsmOperand(SrcVar);
John Porto921856d2015-07-07 11:56:26 -0700747 (Asm->*(Emitter.GPRAddr))(Ty, VarReg, SrcStackAddr);
748 }
John Porto4a566862016-01-04 09:33:41 -0800749 } else if (const auto *Mem = llvm::dyn_cast<X86OperandMem>(Src)) {
John Porto921856d2015-07-07 11:56:26 -0700750 Mem->emitSegmentOverride(Asm);
John Porto56958cb2016-01-14 09:18:18 -0800751 (Asm->*(Emitter.GPRAddr))(Ty, VarReg,
752 Mem->toAsmAddress(Asm, Target, IsLea));
Jim Stichnoth5bff61c2015-10-28 09:26:00 -0700753 } else if (const auto *Imm = llvm::dyn_cast<ConstantInteger32>(Src)) {
John Porto4a566862016-01-04 09:33:41 -0800754 (Asm->*(Emitter.GPRImm))(Ty, VarReg, AssemblerImmediate(Imm->getValue()));
Jim Stichnoth9c2c0932016-06-14 07:27:22 -0700755 } else if (const auto *Imm = llvm::dyn_cast<ConstantInteger64>(Src)) {
756 assert(Traits::Is64Bit);
757 assert(Utils::IsInt(32, Imm->getValue()));
758 (Asm->*(Emitter.GPRImm))(Ty, VarReg, AssemblerImmediate(Imm->getValue()));
Jim Stichnoth5bff61c2015-10-28 09:26:00 -0700759 } else if (const auto *Reloc = llvm::dyn_cast<ConstantRelocatable>(Src)) {
Jim Stichnoth467ffe52016-03-29 15:01:06 -0700760 const auto FixupKind = (Reloc->getName().hasStdString() &&
761 Reloc->getName().toString() == GlobalOffsetTable)
John Porto6e8d3fa2016-02-04 10:35:20 -0800762 ? Traits::FK_GotPC
763 : Traits::TargetLowering::getAbsFixup();
764 AssemblerFixup *Fixup = Asm->createFixup(FixupKind, Reloc);
765 (Asm->*(Emitter.GPRImm))(Ty, VarReg, AssemblerImmediate(Fixup));
John Porto4a566862016-01-04 09:33:41 -0800766 } else if (const auto *Split = llvm::dyn_cast<VariableSplit>(Src)) {
John Porto921856d2015-07-07 11:56:26 -0700767 (Asm->*(Emitter.GPRAddr))(Ty, VarReg, Split->toAsmAddress(Func));
768 } else {
769 llvm_unreachable("Unexpected operand type");
770 }
771}
772
John Porto4a566862016-01-04 09:33:41 -0800773template <typename TraitsType>
774void InstImpl<TraitsType>::emitIASAddrOpTyGPR(const Cfg *Func, Type Ty,
775 const Address &Addr,
776 const Operand *Src,
777 const GPREmitterAddrOp &Emitter) {
778 Assembler *Asm = Func->getAssembler<Assembler>();
779 // Src can only be Reg or AssemblerImmediate.
Jim Stichnoth5bff61c2015-10-28 09:26:00 -0700780 if (const auto *SrcVar = llvm::dyn_cast<Variable>(Src)) {
John Porto921856d2015-07-07 11:56:26 -0700781 assert(SrcVar->hasReg());
John Porto4a566862016-01-04 09:33:41 -0800782 GPRRegister SrcReg = Traits::getEncodedGPR(SrcVar->getRegNum());
John Porto921856d2015-07-07 11:56:26 -0700783 (Asm->*(Emitter.AddrGPR))(Ty, Addr, SrcReg);
Jim Stichnoth5bff61c2015-10-28 09:26:00 -0700784 } else if (const auto *Imm = llvm::dyn_cast<ConstantInteger32>(Src)) {
John Porto4a566862016-01-04 09:33:41 -0800785 (Asm->*(Emitter.AddrImm))(Ty, Addr, AssemblerImmediate(Imm->getValue()));
Jim Stichnoth9c2c0932016-06-14 07:27:22 -0700786 } else if (const auto *Imm = llvm::dyn_cast<ConstantInteger64>(Src)) {
787 assert(Traits::Is64Bit);
788 assert(Utils::IsInt(32, Imm->getValue()));
789 (Asm->*(Emitter.AddrImm))(Ty, Addr, AssemblerImmediate(Imm->getValue()));
Jim Stichnoth5bff61c2015-10-28 09:26:00 -0700790 } else if (const auto *Reloc = llvm::dyn_cast<ConstantRelocatable>(Src)) {
Jim Stichnoth467ffe52016-03-29 15:01:06 -0700791 const auto FixupKind = (Reloc->getName().hasStdString() &&
792 Reloc->getName().toString() == GlobalOffsetTable)
John Porto6e8d3fa2016-02-04 10:35:20 -0800793 ? Traits::FK_GotPC
794 : Traits::TargetLowering::getAbsFixup();
795 AssemblerFixup *Fixup = Asm->createFixup(FixupKind, Reloc);
796 (Asm->*(Emitter.AddrImm))(Ty, Addr, AssemblerImmediate(Fixup));
John Porto921856d2015-07-07 11:56:26 -0700797 } else {
798 llvm_unreachable("Unexpected operand type");
799 }
800}
801
John Porto4a566862016-01-04 09:33:41 -0800802template <typename TraitsType>
803void InstImpl<TraitsType>::emitIASAsAddrOpTyGPR(
John Porto921856d2015-07-07 11:56:26 -0700804 const Cfg *Func, Type Ty, const Operand *Op0, const Operand *Op1,
John Porto4a566862016-01-04 09:33:41 -0800805 const GPREmitterAddrOp &Emitter) {
806 auto *Target = InstX86Base::getTarget(Func);
Jim Stichnoth5bff61c2015-10-28 09:26:00 -0700807 if (const auto *Op0Var = llvm::dyn_cast<Variable>(Op0)) {
John Porto921856d2015-07-07 11:56:26 -0700808 assert(!Op0Var->hasReg());
John Porto4a566862016-01-04 09:33:41 -0800809 Address StackAddr(Target->stackVarToAsmOperand(Op0Var));
810 emitIASAddrOpTyGPR(Func, Ty, StackAddr, Op1, Emitter);
811 } else if (const auto *Op0Mem = llvm::dyn_cast<X86OperandMem>(Op0)) {
812 Assembler *Asm = Func->getAssembler<Assembler>();
John Porto921856d2015-07-07 11:56:26 -0700813 Op0Mem->emitSegmentOverride(Asm);
John Porto4a566862016-01-04 09:33:41 -0800814 emitIASAddrOpTyGPR(Func, Ty, Op0Mem->toAsmAddress(Asm, Target), Op1,
815 Emitter);
816 } else if (const auto *Split = llvm::dyn_cast<VariableSplit>(Op0)) {
817 emitIASAddrOpTyGPR(Func, Ty, Split->toAsmAddress(Func), Op1, Emitter);
John Porto921856d2015-07-07 11:56:26 -0700818 } else {
819 llvm_unreachable("Unexpected operand type");
820 }
821}
822
John Porto4a566862016-01-04 09:33:41 -0800823template <typename TraitsType>
824void InstImpl<TraitsType>::emitIASGPRShift(const Cfg *Func, Type Ty,
825 const Variable *Var,
826 const Operand *Src,
827 const GPREmitterShiftOp &Emitter) {
828 Assembler *Asm = Func->getAssembler<Assembler>();
Andrew Scull57e12682015-09-16 11:30:19 -0700829 // Technically, the Dest Var can be mem as well, but we only use Reg. We can
830 // extend this to check Dest if we decide to use that form.
John Porto921856d2015-07-07 11:56:26 -0700831 assert(Var->hasReg());
832 // We cheat a little and use GPRRegister even for byte operations.
John Porto4a566862016-01-04 09:33:41 -0800833 GPRRegister VarReg = Traits::getEncodedGPR(Var->getRegNum());
Andrew Scull57e12682015-09-16 11:30:19 -0700834 // Src must be reg == ECX or an Imm8. This is asserted by the assembler.
Jim Stichnoth5bff61c2015-10-28 09:26:00 -0700835 if (const auto *SrcVar = llvm::dyn_cast<Variable>(Src)) {
John Porto921856d2015-07-07 11:56:26 -0700836 assert(SrcVar->hasReg());
John Porto4a566862016-01-04 09:33:41 -0800837 GPRRegister SrcReg = Traits::getEncodedGPR(SrcVar->getRegNum());
John Porto921856d2015-07-07 11:56:26 -0700838 (Asm->*(Emitter.GPRGPR))(Ty, VarReg, SrcReg);
Jim Stichnoth5bff61c2015-10-28 09:26:00 -0700839 } else if (const auto *Imm = llvm::dyn_cast<ConstantInteger32>(Src)) {
John Porto4a566862016-01-04 09:33:41 -0800840 (Asm->*(Emitter.GPRImm))(Ty, VarReg, AssemblerImmediate(Imm->getValue()));
Jim Stichnoth9c2c0932016-06-14 07:27:22 -0700841 } else if (const auto *Imm = llvm::dyn_cast<ConstantInteger64>(Src)) {
842 assert(Traits::Is64Bit);
843 assert(Utils::IsInt(32, Imm->getValue()));
844 (Asm->*(Emitter.GPRImm))(Ty, VarReg, AssemblerImmediate(Imm->getValue()));
John Porto921856d2015-07-07 11:56:26 -0700845 } else {
846 llvm_unreachable("Unexpected operand type");
847 }
848}
849
John Porto4a566862016-01-04 09:33:41 -0800850template <typename TraitsType>
851void InstImpl<TraitsType>::emitIASGPRShiftDouble(
John Porto921856d2015-07-07 11:56:26 -0700852 const Cfg *Func, const Variable *Dest, const Operand *Src1Op,
John Porto4a566862016-01-04 09:33:41 -0800853 const Operand *Src2Op, const GPREmitterShiftD &Emitter) {
854 Assembler *Asm = Func->getAssembler<Assembler>();
John Porto921856d2015-07-07 11:56:26 -0700855 // Dest can be reg or mem, but we only use the reg variant.
856 assert(Dest->hasReg());
John Porto4a566862016-01-04 09:33:41 -0800857 GPRRegister DestReg = Traits::getEncodedGPR(Dest->getRegNum());
John Porto921856d2015-07-07 11:56:26 -0700858 // SrcVar1 must be reg.
Jim Stichnoth5bff61c2015-10-28 09:26:00 -0700859 const auto *SrcVar1 = llvm::cast<Variable>(Src1Op);
John Porto921856d2015-07-07 11:56:26 -0700860 assert(SrcVar1->hasReg());
John Porto4a566862016-01-04 09:33:41 -0800861 GPRRegister SrcReg = Traits::getEncodedGPR(SrcVar1->getRegNum());
John Porto921856d2015-07-07 11:56:26 -0700862 Type Ty = SrcVar1->getType();
863 // Src2 can be the implicit CL register or an immediate.
Jim Stichnoth5bff61c2015-10-28 09:26:00 -0700864 if (const auto *Imm = llvm::dyn_cast<ConstantInteger32>(Src2Op)) {
John Porto921856d2015-07-07 11:56:26 -0700865 (Asm->*(Emitter.GPRGPRImm))(Ty, DestReg, SrcReg,
John Porto4a566862016-01-04 09:33:41 -0800866 AssemblerImmediate(Imm->getValue()));
John Porto921856d2015-07-07 11:56:26 -0700867 } else {
John Porto4a566862016-01-04 09:33:41 -0800868 assert(llvm::cast<Variable>(Src2Op)->getRegNum() == RegisterSet::Reg_cl);
John Porto921856d2015-07-07 11:56:26 -0700869 (Asm->*(Emitter.GPRGPR))(Ty, DestReg, SrcReg);
870 }
871}
872
John Porto4a566862016-01-04 09:33:41 -0800873template <typename TraitsType>
874void InstImpl<TraitsType>::emitIASXmmShift(const Cfg *Func, Type Ty,
875 const Variable *Var,
876 const Operand *Src,
877 const XmmEmitterShiftOp &Emitter) {
878 auto *Target = InstX86Base::getTarget(Func);
879 Assembler *Asm = Func->getAssembler<Assembler>();
John Porto921856d2015-07-07 11:56:26 -0700880 assert(Var->hasReg());
John Porto4a566862016-01-04 09:33:41 -0800881 XmmRegister VarReg = Traits::getEncodedXmm(Var->getRegNum());
Jim Stichnoth5bff61c2015-10-28 09:26:00 -0700882 if (const auto *SrcVar = llvm::dyn_cast<Variable>(Src)) {
John Porto921856d2015-07-07 11:56:26 -0700883 if (SrcVar->hasReg()) {
John Porto4a566862016-01-04 09:33:41 -0800884 XmmRegister SrcReg = Traits::getEncodedXmm(SrcVar->getRegNum());
John Porto921856d2015-07-07 11:56:26 -0700885 (Asm->*(Emitter.XmmXmm))(Ty, VarReg, SrcReg);
886 } else {
John Porto4a566862016-01-04 09:33:41 -0800887 Address SrcStackAddr = Target->stackVarToAsmOperand(SrcVar);
John Porto921856d2015-07-07 11:56:26 -0700888 (Asm->*(Emitter.XmmAddr))(Ty, VarReg, SrcStackAddr);
889 }
John Porto4a566862016-01-04 09:33:41 -0800890 } else if (const auto *Mem = llvm::dyn_cast<X86OperandMem>(Src)) {
891 assert(Mem->getSegmentRegister() == X86OperandMem::DefaultSegment);
David Sehr4318a412015-11-11 15:01:55 -0800892 (Asm->*(Emitter.XmmAddr))(Ty, VarReg, Mem->toAsmAddress(Asm, Target));
Jim Stichnoth5bff61c2015-10-28 09:26:00 -0700893 } else if (const auto *Imm = llvm::dyn_cast<ConstantInteger32>(Src)) {
John Porto4a566862016-01-04 09:33:41 -0800894 (Asm->*(Emitter.XmmImm))(Ty, VarReg, AssemblerImmediate(Imm->getValue()));
John Porto921856d2015-07-07 11:56:26 -0700895 } else {
896 llvm_unreachable("Unexpected operand type");
897 }
898}
899
John Porto4a566862016-01-04 09:33:41 -0800900template <typename TraitsType>
901void InstImpl<TraitsType>::emitIASRegOpTyXMM(const Cfg *Func, Type Ty,
902 const Variable *Var,
903 const Operand *Src,
904 const XmmEmitterRegOp &Emitter) {
905 auto *Target = InstX86Base::getTarget(Func);
906 Assembler *Asm = Func->getAssembler<Assembler>();
John Porto921856d2015-07-07 11:56:26 -0700907 assert(Var->hasReg());
John Porto4a566862016-01-04 09:33:41 -0800908 XmmRegister VarReg = Traits::getEncodedXmm(Var->getRegNum());
Jim Stichnoth5bff61c2015-10-28 09:26:00 -0700909 if (const auto *SrcVar = llvm::dyn_cast<Variable>(Src)) {
John Porto921856d2015-07-07 11:56:26 -0700910 if (SrcVar->hasReg()) {
John Porto4a566862016-01-04 09:33:41 -0800911 XmmRegister SrcReg = Traits::getEncodedXmm(SrcVar->getRegNum());
John Porto921856d2015-07-07 11:56:26 -0700912 (Asm->*(Emitter.XmmXmm))(Ty, VarReg, SrcReg);
913 } else {
John Porto4a566862016-01-04 09:33:41 -0800914 Address SrcStackAddr = Target->stackVarToAsmOperand(SrcVar);
John Porto921856d2015-07-07 11:56:26 -0700915 (Asm->*(Emitter.XmmAddr))(Ty, VarReg, SrcStackAddr);
916 }
John Porto4a566862016-01-04 09:33:41 -0800917 } else if (const auto *Mem = llvm::dyn_cast<X86OperandMem>(Src)) {
918 assert(Mem->getSegmentRegister() == X86OperandMem::DefaultSegment);
David Sehr4318a412015-11-11 15:01:55 -0800919 (Asm->*(Emitter.XmmAddr))(Ty, VarReg, Mem->toAsmAddress(Asm, Target));
Jim Stichnoth5bff61c2015-10-28 09:26:00 -0700920 } else if (const auto *Imm = llvm::dyn_cast<Constant>(Src)) {
John Porto4a566862016-01-04 09:33:41 -0800921 (Asm->*(Emitter.XmmAddr))(Ty, VarReg,
922 Traits::Address::ofConstPool(Asm, Imm));
John Porto921856d2015-07-07 11:56:26 -0700923 } else {
924 llvm_unreachable("Unexpected operand type");
925 }
926}
927
John Porto4a566862016-01-04 09:33:41 -0800928template <typename TraitsType>
Jim Stichnoth8aa39662016-02-10 11:20:30 -0800929template <typename DReg_t, typename SReg_t, DReg_t (*destEnc)(RegNumT),
930 SReg_t (*srcEnc)(RegNumT)>
John Porto4a566862016-01-04 09:33:41 -0800931void InstImpl<TraitsType>::emitIASCastRegOp(
932 const Cfg *Func, Type DestTy, const Variable *Dest, Type SrcTy,
933 const Operand *Src, const CastEmitterRegOp<DReg_t, SReg_t> &Emitter) {
934 auto *Target = InstX86Base::getTarget(Func);
935 Assembler *Asm = Func->getAssembler<Assembler>();
John Porto921856d2015-07-07 11:56:26 -0700936 assert(Dest->hasReg());
937 DReg_t DestReg = destEnc(Dest->getRegNum());
Jim Stichnoth5bff61c2015-10-28 09:26:00 -0700938 if (const auto *SrcVar = llvm::dyn_cast<Variable>(Src)) {
John Porto921856d2015-07-07 11:56:26 -0700939 if (SrcVar->hasReg()) {
940 SReg_t SrcReg = srcEnc(SrcVar->getRegNum());
John Porto1d235422015-08-12 12:37:53 -0700941 (Asm->*(Emitter.RegReg))(DestTy, DestReg, SrcTy, SrcReg);
John Porto921856d2015-07-07 11:56:26 -0700942 } else {
John Porto4a566862016-01-04 09:33:41 -0800943 Address SrcStackAddr = Target->stackVarToAsmOperand(SrcVar);
John Porto1d235422015-08-12 12:37:53 -0700944 (Asm->*(Emitter.RegAddr))(DestTy, DestReg, SrcTy, SrcStackAddr);
John Porto921856d2015-07-07 11:56:26 -0700945 }
John Porto4a566862016-01-04 09:33:41 -0800946 } else if (const auto *Mem = llvm::dyn_cast<X86OperandMem>(Src)) {
John Porto921856d2015-07-07 11:56:26 -0700947 Mem->emitSegmentOverride(Asm);
David Sehr4318a412015-11-11 15:01:55 -0800948 (Asm->*(Emitter.RegAddr))(DestTy, DestReg, SrcTy,
949 Mem->toAsmAddress(Asm, Target));
John Porto921856d2015-07-07 11:56:26 -0700950 } else {
951 llvm_unreachable("Unexpected operand type");
952 }
953}
954
John Porto4a566862016-01-04 09:33:41 -0800955template <typename TraitsType>
Jim Stichnoth8aa39662016-02-10 11:20:30 -0800956template <typename DReg_t, typename SReg_t, DReg_t (*destEnc)(RegNumT),
957 SReg_t (*srcEnc)(RegNumT)>
John Porto4a566862016-01-04 09:33:41 -0800958void InstImpl<TraitsType>::emitIASThreeOpImmOps(
John Porto921856d2015-07-07 11:56:26 -0700959 const Cfg *Func, Type DispatchTy, const Variable *Dest, const Operand *Src0,
John Porto4a566862016-01-04 09:33:41 -0800960 const Operand *Src1, const ThreeOpImmEmitter<DReg_t, SReg_t> Emitter) {
961 auto *Target = InstX86Base::getTarget(Func);
962 Assembler *Asm = Func->getAssembler<Assembler>();
John Porto921856d2015-07-07 11:56:26 -0700963 // This only handles Dest being a register, and Src1 being an immediate.
964 assert(Dest->hasReg());
965 DReg_t DestReg = destEnc(Dest->getRegNum());
John Porto4a566862016-01-04 09:33:41 -0800966 AssemblerImmediate Imm(llvm::cast<ConstantInteger32>(Src1)->getValue());
Jim Stichnoth5bff61c2015-10-28 09:26:00 -0700967 if (const auto *SrcVar = llvm::dyn_cast<Variable>(Src0)) {
John Porto921856d2015-07-07 11:56:26 -0700968 if (SrcVar->hasReg()) {
969 SReg_t SrcReg = srcEnc(SrcVar->getRegNum());
970 (Asm->*(Emitter.RegRegImm))(DispatchTy, DestReg, SrcReg, Imm);
971 } else {
John Porto4a566862016-01-04 09:33:41 -0800972 Address SrcStackAddr = Target->stackVarToAsmOperand(SrcVar);
John Porto921856d2015-07-07 11:56:26 -0700973 (Asm->*(Emitter.RegAddrImm))(DispatchTy, DestReg, SrcStackAddr, Imm);
974 }
John Porto4a566862016-01-04 09:33:41 -0800975 } else if (const auto *Mem = llvm::dyn_cast<X86OperandMem>(Src0)) {
John Porto921856d2015-07-07 11:56:26 -0700976 Mem->emitSegmentOverride(Asm);
David Sehr4318a412015-11-11 15:01:55 -0800977 (Asm->*(Emitter.RegAddrImm))(DispatchTy, DestReg,
978 Mem->toAsmAddress(Asm, Target), Imm);
John Porto921856d2015-07-07 11:56:26 -0700979 } else {
980 llvm_unreachable("Unexpected operand type");
981 }
982}
983
John Porto4a566862016-01-04 09:33:41 -0800984template <typename TraitsType>
985void InstImpl<TraitsType>::emitIASMovlikeXMM(const Cfg *Func,
986 const Variable *Dest,
987 const Operand *Src,
988 const XmmEmitterMovOps Emitter) {
989 auto *Target = InstX86Base::getTarget(Func);
990 Assembler *Asm = Func->getAssembler<Assembler>();
John Porto921856d2015-07-07 11:56:26 -0700991 if (Dest->hasReg()) {
John Porto4a566862016-01-04 09:33:41 -0800992 XmmRegister DestReg = Traits::getEncodedXmm(Dest->getRegNum());
Jim Stichnoth5bff61c2015-10-28 09:26:00 -0700993 if (const auto *SrcVar = llvm::dyn_cast<Variable>(Src)) {
John Porto921856d2015-07-07 11:56:26 -0700994 if (SrcVar->hasReg()) {
John Porto4a566862016-01-04 09:33:41 -0800995 (Asm->*(Emitter.XmmXmm))(DestReg,
996 Traits::getEncodedXmm(SrcVar->getRegNum()));
John Porto921856d2015-07-07 11:56:26 -0700997 } else {
John Porto4a566862016-01-04 09:33:41 -0800998 Address StackAddr(Target->stackVarToAsmOperand(SrcVar));
John Porto921856d2015-07-07 11:56:26 -0700999 (Asm->*(Emitter.XmmAddr))(DestReg, StackAddr);
1000 }
John Porto4a566862016-01-04 09:33:41 -08001001 } else if (const auto *SrcMem = llvm::dyn_cast<X86OperandMem>(Src)) {
1002 assert(SrcMem->getSegmentRegister() == X86OperandMem::DefaultSegment);
David Sehr4318a412015-11-11 15:01:55 -08001003 (Asm->*(Emitter.XmmAddr))(DestReg, SrcMem->toAsmAddress(Asm, Target));
John Porto921856d2015-07-07 11:56:26 -07001004 } else {
1005 llvm_unreachable("Unexpected operand type");
1006 }
1007 } else {
John Porto4a566862016-01-04 09:33:41 -08001008 Address StackAddr(Target->stackVarToAsmOperand(Dest));
John Porto921856d2015-07-07 11:56:26 -07001009 // Src must be a register in this case.
Jim Stichnoth5bff61c2015-10-28 09:26:00 -07001010 const auto *SrcVar = llvm::cast<Variable>(Src);
John Porto921856d2015-07-07 11:56:26 -07001011 assert(SrcVar->hasReg());
John Porto4a566862016-01-04 09:33:41 -08001012 (Asm->*(Emitter.AddrXmm))(StackAddr,
1013 Traits::getEncodedXmm(SrcVar->getRegNum()));
John Porto921856d2015-07-07 11:56:26 -07001014 }
1015}
1016
John Porto4a566862016-01-04 09:33:41 -08001017template <typename TraitsType>
Nicolas Capense3cabda2016-10-18 16:27:27 -04001018void InstImpl<TraitsType>::InstX86Movmsk::dump(const Cfg *Func) const {
1019 if (!BuildDefs::dump())
1020 return;
1021 Ostream &Str = Func->getContext()->getStrDump();
1022 this->dumpDest(Func);
1023 Str << " = movmsk." << this->getSrc(0)->getType() << " ";
1024 this->dumpSources(Func);
1025}
1026
1027template <typename TraitsType>
1028void InstImpl<TraitsType>::InstX86Movmsk::emit(const Cfg *Func) const {
1029 if (!BuildDefs::dump())
1030 return;
1031 Ostream &Str = Func->getContext()->getStrEmit();
1032 assert(this->getSrcSize() == 1);
1033 Type SrcTy = this->getSrc(0)->getType();
1034 assert(isVectorType(SrcTy));
1035 switch (SrcTy) {
1036 case IceType_v16i8:
1037 Str << "\t"
1038 "pmovmskb"
1039 "\t";
1040 break;
1041 case IceType_v4i32:
1042 case IceType_v4f32:
1043 Str << "\t"
1044 "movmskps"
1045 "\t";
1046 break;
1047 default:
1048 llvm_unreachable("Unexpected operand type");
1049 }
1050 this->getSrc(0)->emit(Func);
1051 Str << ", ";
1052 this->getDest()->emit(Func);
1053}
1054
1055template <typename TraitsType>
1056void InstImpl<TraitsType>::InstX86Movmsk::emitIAS(const Cfg *Func) const {
1057 assert(this->getSrcSize() == 1);
1058 Assembler *Asm = Func->getAssembler<Assembler>();
1059 const Variable *Dest = this->getDest();
1060 const Variable *Src = llvm::cast<Variable>(this->getSrc(0));
1061 const Type DestTy = Dest->getType();
Nicolas Capens61593fb2016-10-24 11:04:22 -04001062 (void)DestTy;
Nicolas Capense3cabda2016-10-18 16:27:27 -04001063 const Type SrcTy = Src->getType();
1064 assert(isVectorType(SrcTy));
1065 assert(isScalarIntegerType(DestTy));
Nicolas Capensdbf81e02017-01-14 12:53:55 -05001066 if (Traits::Is64Bit) {
Nicolas Capense3cabda2016-10-18 16:27:27 -04001067 assert(DestTy == IceType_i32 || DestTy == IceType_i64);
Nicolas Capensdbf81e02017-01-14 12:53:55 -05001068 } else {
1069 assert(typeWidthInBytes(DestTy) <= 4);
Nicolas Capense3cabda2016-10-18 16:27:27 -04001070 }
1071 XmmRegister SrcReg = Traits::getEncodedXmm(Src->getRegNum());
1072 GPRRegister DestReg = Traits::getEncodedGPR(Dest->getRegNum());
1073 Asm->movmsk(SrcTy, DestReg, SrcReg);
1074}
1075
1076template <typename TraitsType>
Nicolas Capens956cfd62016-10-31 14:28:09 -04001077void InstImpl<TraitsType>::InstX86Sqrt::emit(const Cfg *Func) const {
John Porto921856d2015-07-07 11:56:26 -07001078 if (!BuildDefs::dump())
1079 return;
1080 Ostream &Str = Func->getContext()->getStrEmit();
1081 assert(this->getSrcSize() == 1);
1082 Type Ty = this->getSrc(0)->getType();
1083 assert(isScalarFloatingType(Ty));
Jim Stichnoth6106df82015-12-16 06:17:58 -08001084 Str << "\t"
Nicolas Capens13cde0f2016-10-26 10:36:11 -04001085 "sqrt" << Traits::TypeAttributes[Ty].SpSdString << "\t";
John Porto921856d2015-07-07 11:56:26 -07001086 this->getSrc(0)->emit(Func);
1087 Str << ", ";
1088 this->getDest()->emit(Func);
1089}
1090
John Porto4a566862016-01-04 09:33:41 -08001091template <typename TraitsType>
1092void InstImpl<TraitsType>::InstX86Div::emit(const Cfg *Func) const {
John Porto921856d2015-07-07 11:56:26 -07001093 if (!BuildDefs::dump())
1094 return;
1095 Ostream &Str = Func->getContext()->getStrEmit();
1096 assert(this->getSrcSize() == 3);
1097 Operand *Src1 = this->getSrc(1);
1098 Str << "\t" << this->Opcode << this->getWidthString(Src1->getType()) << "\t";
1099 Src1->emit(Func);
1100}
1101
John Porto4a566862016-01-04 09:33:41 -08001102template <typename TraitsType>
1103void InstImpl<TraitsType>::InstX86Div::emitIAS(const Cfg *Func) const {
John Porto921856d2015-07-07 11:56:26 -07001104 assert(this->getSrcSize() == 3);
1105 const Operand *Src = this->getSrc(1);
1106 Type Ty = Src->getType();
John Porto4a566862016-01-04 09:33:41 -08001107 static GPREmitterOneOp Emitter = {&Assembler::div, &Assembler::div};
1108 emitIASOpTyGPR(Func, Ty, Src, Emitter);
John Porto921856d2015-07-07 11:56:26 -07001109}
1110
John Porto4a566862016-01-04 09:33:41 -08001111template <typename TraitsType>
1112void InstImpl<TraitsType>::InstX86Idiv::emit(const Cfg *Func) const {
John Porto921856d2015-07-07 11:56:26 -07001113 if (!BuildDefs::dump())
1114 return;
1115 Ostream &Str = Func->getContext()->getStrEmit();
1116 assert(this->getSrcSize() == 3);
1117 Operand *Src1 = this->getSrc(1);
1118 Str << "\t" << this->Opcode << this->getWidthString(Src1->getType()) << "\t";
1119 Src1->emit(Func);
1120}
1121
John Porto4a566862016-01-04 09:33:41 -08001122template <typename TraitsType>
1123void InstImpl<TraitsType>::InstX86Idiv::emitIAS(const Cfg *Func) const {
John Porto921856d2015-07-07 11:56:26 -07001124 assert(this->getSrcSize() == 3);
1125 const Operand *Src = this->getSrc(1);
1126 Type Ty = Src->getType();
John Porto4a566862016-01-04 09:33:41 -08001127 static const GPREmitterOneOp Emitter = {&Assembler::idiv, &Assembler::idiv};
1128 emitIASOpTyGPR(Func, Ty, Src, Emitter);
John Porto921856d2015-07-07 11:56:26 -07001129}
1130
1131// pblendvb and blendvps take xmm0 as a final implicit argument.
John Porto4a566862016-01-04 09:33:41 -08001132template <typename TraitsType>
1133void InstImpl<TraitsType>::emitVariableBlendInst(const char *Opcode,
Jim Stichnoth8cfeb692016-02-05 09:50:02 -08001134 const Inst *Instr,
John Porto4a566862016-01-04 09:33:41 -08001135 const Cfg *Func) {
John Porto921856d2015-07-07 11:56:26 -07001136 if (!BuildDefs::dump())
1137 return;
1138 Ostream &Str = Func->getContext()->getStrEmit();
Jim Stichnoth8cfeb692016-02-05 09:50:02 -08001139 assert(Instr->getSrcSize() == 3);
1140 assert(llvm::cast<Variable>(Instr->getSrc(2))->getRegNum() ==
John Porto4a566862016-01-04 09:33:41 -08001141 RegisterSet::Reg_xmm0);
John Porto921856d2015-07-07 11:56:26 -07001142 Str << "\t" << Opcode << "\t";
Jim Stichnoth8cfeb692016-02-05 09:50:02 -08001143 Instr->getSrc(1)->emit(Func);
John Porto921856d2015-07-07 11:56:26 -07001144 Str << ", ";
Jim Stichnoth8cfeb692016-02-05 09:50:02 -08001145 Instr->getDest()->emit(Func);
John Porto921856d2015-07-07 11:56:26 -07001146}
1147
John Porto4a566862016-01-04 09:33:41 -08001148template <typename TraitsType>
1149void InstImpl<TraitsType>::emitIASVariableBlendInst(
Jim Stichnoth8cfeb692016-02-05 09:50:02 -08001150 const Inst *Instr, const Cfg *Func, const XmmEmitterRegOp &Emitter) {
1151 assert(Instr->getSrcSize() == 3);
1152 assert(llvm::cast<Variable>(Instr->getSrc(2))->getRegNum() ==
John Porto4a566862016-01-04 09:33:41 -08001153 RegisterSet::Reg_xmm0);
Jim Stichnoth8cfeb692016-02-05 09:50:02 -08001154 const Variable *Dest = Instr->getDest();
1155 const Operand *Src = Instr->getSrc(1);
John Porto4a566862016-01-04 09:33:41 -08001156 emitIASRegOpTyXMM(Func, Dest->getType(), Dest, Src, Emitter);
John Porto921856d2015-07-07 11:56:26 -07001157}
1158
John Porto4a566862016-01-04 09:33:41 -08001159template <typename TraitsType>
1160void InstImpl<TraitsType>::InstX86Blendvps::emit(const Cfg *Func) const {
John Porto921856d2015-07-07 11:56:26 -07001161 if (!BuildDefs::dump())
1162 return;
John Porto4a566862016-01-04 09:33:41 -08001163 emitVariableBlendInst(this->Opcode, this, Func);
John Porto921856d2015-07-07 11:56:26 -07001164}
1165
John Porto4a566862016-01-04 09:33:41 -08001166template <typename TraitsType>
1167void InstImpl<TraitsType>::InstX86Blendvps::emitIAS(const Cfg *Func) const {
1168 static const XmmEmitterRegOp Emitter = {&Assembler::blendvps,
1169 &Assembler::blendvps};
1170 emitIASVariableBlendInst(this, Func, Emitter);
John Porto921856d2015-07-07 11:56:26 -07001171}
1172
John Porto4a566862016-01-04 09:33:41 -08001173template <typename TraitsType>
1174void InstImpl<TraitsType>::InstX86Pblendvb::emit(const Cfg *Func) const {
John Porto921856d2015-07-07 11:56:26 -07001175 if (!BuildDefs::dump())
1176 return;
John Porto4a566862016-01-04 09:33:41 -08001177 emitVariableBlendInst(this->Opcode, this, Func);
John Porto921856d2015-07-07 11:56:26 -07001178}
1179
John Porto4a566862016-01-04 09:33:41 -08001180template <typename TraitsType>
1181void InstImpl<TraitsType>::InstX86Pblendvb::emitIAS(const Cfg *Func) const {
1182 static const XmmEmitterRegOp Emitter = {&Assembler::pblendvb,
1183 &Assembler::pblendvb};
1184 emitIASVariableBlendInst(this, Func, Emitter);
John Porto921856d2015-07-07 11:56:26 -07001185}
1186
John Porto4a566862016-01-04 09:33:41 -08001187template <typename TraitsType>
1188void InstImpl<TraitsType>::InstX86Imul::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() == 2);
1193 Variable *Dest = this->getDest();
1194 if (isByteSizedArithType(Dest->getType())) {
1195 // The 8-bit version of imul only allows the form "imul r/m8".
Jim Stichnoth5bff61c2015-10-28 09:26:00 -07001196 const auto *Src0Var = llvm::dyn_cast<Variable>(this->getSrc(0));
John Porto921856d2015-07-07 11:56:26 -07001197 (void)Src0Var;
John Porto4a566862016-01-04 09:33:41 -08001198 assert(Src0Var->getRegNum() == RegisterSet::Reg_al);
Jim Stichnoth6106df82015-12-16 06:17:58 -08001199 Str << "\t"
1200 "imulb\t";
John Porto921856d2015-07-07 11:56:26 -07001201 this->getSrc(1)->emit(Func);
1202 } else if (llvm::isa<Constant>(this->getSrc(1))) {
Jim Stichnoth6106df82015-12-16 06:17:58 -08001203 Str << "\t"
1204 "imul" << this->getWidthString(Dest->getType()) << "\t";
John Porto921856d2015-07-07 11:56:26 -07001205 this->getSrc(1)->emit(Func);
1206 Str << ", ";
1207 this->getSrc(0)->emit(Func);
1208 Str << ", ";
1209 Dest->emit(Func);
1210 } else {
David Sehr6da7ae22015-12-17 15:01:30 -08001211 this->emitTwoAddress(Func, this->Opcode);
John Porto921856d2015-07-07 11:56:26 -07001212 }
1213}
1214
John Porto4a566862016-01-04 09:33:41 -08001215template <typename TraitsType>
1216void InstImpl<TraitsType>::InstX86Imul::emitIAS(const Cfg *Func) const {
John Porto921856d2015-07-07 11:56:26 -07001217 assert(this->getSrcSize() == 2);
1218 const Variable *Var = this->getDest();
1219 Type Ty = Var->getType();
1220 const Operand *Src = this->getSrc(1);
1221 if (isByteSizedArithType(Ty)) {
1222 // The 8-bit version of imul only allows the form "imul r/m8".
Jim Stichnoth5bff61c2015-10-28 09:26:00 -07001223 const auto *Src0Var = llvm::dyn_cast<Variable>(this->getSrc(0));
John Porto921856d2015-07-07 11:56:26 -07001224 (void)Src0Var;
John Porto4a566862016-01-04 09:33:41 -08001225 assert(Src0Var->getRegNum() == RegisterSet::Reg_al);
1226 static const GPREmitterOneOp Emitter = {&Assembler::imul, &Assembler::imul};
1227 emitIASOpTyGPR(Func, Ty, this->getSrc(1), Emitter);
John Porto921856d2015-07-07 11:56:26 -07001228 } else {
David Sehre11f8782015-10-06 10:26:57 -07001229 // The two-address version is used when multiplying by a non-constant
1230 // or doing an 8-bit multiply.
John Porto921856d2015-07-07 11:56:26 -07001231 assert(Var == this->getSrc(0));
John Porto4a566862016-01-04 09:33:41 -08001232 static const GPREmitterRegOp Emitter = {&Assembler::imul, &Assembler::imul,
1233 &Assembler::imul};
John Porto56958cb2016-01-14 09:18:18 -08001234 constexpr bool NotLea = false;
1235 emitIASRegOpTyGPR(Func, NotLea, Ty, Var, Src, Emitter);
John Porto921856d2015-07-07 11:56:26 -07001236 }
1237}
1238
John Porto4a566862016-01-04 09:33:41 -08001239template <typename TraitsType>
1240void InstImpl<TraitsType>::InstX86ImulImm::emit(const Cfg *Func) const {
David Sehre11f8782015-10-06 10:26:57 -07001241 if (!BuildDefs::dump())
1242 return;
1243 Ostream &Str = Func->getContext()->getStrEmit();
1244 assert(this->getSrcSize() == 2);
1245 Variable *Dest = this->getDest();
1246 assert(Dest->getType() == IceType_i16 || Dest->getType() == IceType_i32);
1247 assert(llvm::isa<Constant>(this->getSrc(1)));
Jim Stichnoth6106df82015-12-16 06:17:58 -08001248 Str << "\t"
1249 "imul" << this->getWidthString(Dest->getType()) << "\t";
David Sehre11f8782015-10-06 10:26:57 -07001250 this->getSrc(1)->emit(Func);
1251 Str << ", ";
1252 this->getSrc(0)->emit(Func);
1253 Str << ", ";
1254 Dest->emit(Func);
1255}
1256
John Porto4a566862016-01-04 09:33:41 -08001257template <typename TraitsType>
1258void InstImpl<TraitsType>::InstX86ImulImm::emitIAS(const Cfg *Func) const {
David Sehre11f8782015-10-06 10:26:57 -07001259 assert(this->getSrcSize() == 2);
1260 const Variable *Dest = this->getDest();
1261 Type Ty = Dest->getType();
1262 assert(llvm::isa<Constant>(this->getSrc(1)));
John Porto4a566862016-01-04 09:33:41 -08001263 static const ThreeOpImmEmitter<GPRRegister, GPRRegister> Emitter = {
1264 &Assembler::imul, &Assembler::imul};
1265 emitIASThreeOpImmOps<GPRRegister, GPRRegister, Traits::getEncodedGPR,
1266 Traits::getEncodedGPR>(Func, Ty, Dest, this->getSrc(0),
1267 this->getSrc(1), Emitter);
David Sehre11f8782015-10-06 10:26:57 -07001268}
1269
John Porto4a566862016-01-04 09:33:41 -08001270template <typename TraitsType>
1271void InstImpl<TraitsType>::InstX86Insertps::emitIAS(const Cfg *Func) const {
John Porto921856d2015-07-07 11:56:26 -07001272 assert(this->getSrcSize() == 3);
John Porto4a566862016-01-04 09:33:41 -08001273 assert(InstX86Base::getTarget(Func)->getInstructionSet() >= Traits::SSE4_1);
John Porto921856d2015-07-07 11:56:26 -07001274 const Variable *Dest = this->getDest();
1275 assert(Dest == this->getSrc(0));
1276 Type Ty = Dest->getType();
John Porto4a566862016-01-04 09:33:41 -08001277 static const ThreeOpImmEmitter<XmmRegister, XmmRegister> Emitter = {
1278 &Assembler::insertps, &Assembler::insertps};
1279 emitIASThreeOpImmOps<XmmRegister, XmmRegister, Traits::getEncodedXmm,
1280 Traits::getEncodedXmm>(Func, Ty, Dest, this->getSrc(1),
1281 this->getSrc(2), Emitter);
John Porto921856d2015-07-07 11:56:26 -07001282}
1283
John Porto4a566862016-01-04 09:33:41 -08001284template <typename TraitsType>
1285void InstImpl<TraitsType>::InstX86Cbwdq::emit(const Cfg *Func) const {
John Porto921856d2015-07-07 11:56:26 -07001286 if (!BuildDefs::dump())
1287 return;
1288 Ostream &Str = Func->getContext()->getStrEmit();
1289 assert(this->getSrcSize() == 1);
1290 Operand *Src0 = this->getSrc(0);
Jim Stichnoth8aa39662016-02-10 11:20:30 -08001291 const auto DestReg = this->getDest()->getRegNum();
1292 const auto SrcReg = llvm::cast<Variable>(Src0)->getRegNum();
Jim Stichnothc59288b2015-11-09 11:38:40 -08001293 (void)DestReg;
1294 (void)SrcReg;
John Porto921856d2015-07-07 11:56:26 -07001295 switch (Src0->getType()) {
1296 default:
1297 llvm_unreachable("unexpected source type!");
1298 break;
1299 case IceType_i8:
John Porto4a566862016-01-04 09:33:41 -08001300 assert(SrcReg == RegisterSet::Reg_al);
1301 assert(DestReg == RegisterSet::Reg_ax || DestReg == RegisterSet::Reg_ah);
John Porto1d235422015-08-12 12:37:53 -07001302 Str << "\t"
Jim Stichnoth6106df82015-12-16 06:17:58 -08001303 "cbtw";
John Porto921856d2015-07-07 11:56:26 -07001304 break;
1305 case IceType_i16:
John Porto4a566862016-01-04 09:33:41 -08001306 assert(SrcReg == RegisterSet::Reg_ax);
1307 assert(DestReg == RegisterSet::Reg_dx);
John Porto1d235422015-08-12 12:37:53 -07001308 Str << "\t"
Jim Stichnoth6106df82015-12-16 06:17:58 -08001309 "cwtd";
John Porto921856d2015-07-07 11:56:26 -07001310 break;
1311 case IceType_i32:
John Porto4a566862016-01-04 09:33:41 -08001312 assert(SrcReg == RegisterSet::Reg_eax);
1313 assert(DestReg == RegisterSet::Reg_edx);
John Porto1d235422015-08-12 12:37:53 -07001314 Str << "\t"
Jim Stichnoth6106df82015-12-16 06:17:58 -08001315 "cltd";
John Porto1d235422015-08-12 12:37:53 -07001316 break;
1317 case IceType_i64:
John Porto4a566862016-01-04 09:33:41 -08001318 assert(Traits::Is64Bit);
1319 assert(SrcReg == Traits::getRaxOrDie());
1320 assert(DestReg == Traits::getRdxOrDie());
John Porto1d235422015-08-12 12:37:53 -07001321 Str << "\t"
John Porto008f4ce2015-12-24 13:22:18 -08001322 "cqo";
John Porto921856d2015-07-07 11:56:26 -07001323 break;
1324 }
1325}
1326
John Porto4a566862016-01-04 09:33:41 -08001327template <typename TraitsType>
1328void InstImpl<TraitsType>::InstX86Cbwdq::emitIAS(const Cfg *Func) const {
1329 Assembler *Asm = Func->getAssembler<Assembler>();
John Porto921856d2015-07-07 11:56:26 -07001330 assert(this->getSrcSize() == 1);
1331 Operand *Src0 = this->getSrc(0);
Jim Stichnoth8aa39662016-02-10 11:20:30 -08001332 const auto DestReg = this->getDest()->getRegNum();
1333 const auto SrcReg = llvm::cast<Variable>(Src0)->getRegNum();
Jim Stichnothc59288b2015-11-09 11:38:40 -08001334 (void)DestReg;
1335 (void)SrcReg;
John Porto921856d2015-07-07 11:56:26 -07001336 switch (Src0->getType()) {
1337 default:
1338 llvm_unreachable("unexpected source type!");
1339 break;
1340 case IceType_i8:
John Porto4a566862016-01-04 09:33:41 -08001341 assert(SrcReg == RegisterSet::Reg_al);
1342 assert(DestReg == RegisterSet::Reg_ax || DestReg == RegisterSet::Reg_ah);
John Porto921856d2015-07-07 11:56:26 -07001343 Asm->cbw();
1344 break;
1345 case IceType_i16:
John Porto4a566862016-01-04 09:33:41 -08001346 assert(SrcReg == RegisterSet::Reg_ax);
1347 assert(DestReg == RegisterSet::Reg_dx);
John Porto921856d2015-07-07 11:56:26 -07001348 Asm->cwd();
1349 break;
1350 case IceType_i32:
John Porto4a566862016-01-04 09:33:41 -08001351 assert(SrcReg == RegisterSet::Reg_eax);
1352 assert(DestReg == RegisterSet::Reg_edx);
John Porto921856d2015-07-07 11:56:26 -07001353 Asm->cdq();
1354 break;
John Porto1d235422015-08-12 12:37:53 -07001355 case IceType_i64:
John Porto4a566862016-01-04 09:33:41 -08001356 assert(Traits::Is64Bit);
1357 assert(SrcReg == Traits::getRaxOrDie());
1358 assert(DestReg == Traits::getRdxOrDie());
John Porto1d235422015-08-12 12:37:53 -07001359 Asm->cqo();
1360 break;
John Porto921856d2015-07-07 11:56:26 -07001361 }
1362}
1363
John Porto4a566862016-01-04 09:33:41 -08001364template <typename TraitsType>
1365void InstImpl<TraitsType>::InstX86Mul::emit(const Cfg *Func) const {
John Porto921856d2015-07-07 11:56:26 -07001366 if (!BuildDefs::dump())
1367 return;
1368 Ostream &Str = Func->getContext()->getStrEmit();
1369 assert(this->getSrcSize() == 2);
1370 assert(llvm::isa<Variable>(this->getSrc(0)));
1371 assert(llvm::cast<Variable>(this->getSrc(0))->getRegNum() ==
John Porto4a566862016-01-04 09:33:41 -08001372 RegisterSet::Reg_eax);
1373 assert(this->getDest()->getRegNum() == RegisterSet::Reg_eax); // TODO:
1374 // allow
1375 // edx?
Jim Stichnoth6106df82015-12-16 06:17:58 -08001376 Str << "\t"
1377 "mul" << this->getWidthString(this->getDest()->getType()) << "\t";
John Porto921856d2015-07-07 11:56:26 -07001378 this->getSrc(1)->emit(Func);
1379}
1380
John Porto4a566862016-01-04 09:33:41 -08001381template <typename TraitsType>
1382void InstImpl<TraitsType>::InstX86Mul::emitIAS(const Cfg *Func) const {
John Porto921856d2015-07-07 11:56:26 -07001383 assert(this->getSrcSize() == 2);
1384 assert(llvm::isa<Variable>(this->getSrc(0)));
1385 assert(llvm::cast<Variable>(this->getSrc(0))->getRegNum() ==
John Porto4a566862016-01-04 09:33:41 -08001386 RegisterSet::Reg_eax);
1387 assert(this->getDest()->getRegNum() == RegisterSet::Reg_eax); // TODO:
1388 // allow
1389 // edx?
John Porto921856d2015-07-07 11:56:26 -07001390 const Operand *Src = this->getSrc(1);
1391 Type Ty = Src->getType();
John Porto4a566862016-01-04 09:33:41 -08001392 static const GPREmitterOneOp Emitter = {&Assembler::mul, &Assembler::mul};
1393 emitIASOpTyGPR(Func, Ty, Src, Emitter);
John Porto921856d2015-07-07 11:56:26 -07001394}
1395
John Porto4a566862016-01-04 09:33:41 -08001396template <typename TraitsType>
1397void InstImpl<TraitsType>::InstX86Mul::dump(const Cfg *Func) const {
John Porto921856d2015-07-07 11:56:26 -07001398 if (!BuildDefs::dump())
1399 return;
1400 Ostream &Str = Func->getContext()->getStrDump();
1401 this->dumpDest(Func);
1402 Str << " = mul." << this->getDest()->getType() << " ";
1403 this->dumpSources(Func);
1404}
1405
John Porto4a566862016-01-04 09:33:41 -08001406template <typename TraitsType>
1407void InstImpl<TraitsType>::InstX86Shld::emit(const Cfg *Func) const {
John Porto921856d2015-07-07 11:56:26 -07001408 if (!BuildDefs::dump())
1409 return;
1410 Ostream &Str = Func->getContext()->getStrEmit();
1411 Variable *Dest = this->getDest();
1412 assert(this->getSrcSize() == 3);
1413 assert(Dest == this->getSrc(0));
Jim Stichnoth6106df82015-12-16 06:17:58 -08001414 Str << "\t"
1415 "shld" << this->getWidthString(Dest->getType()) << "\t";
Jim Stichnoth5bff61c2015-10-28 09:26:00 -07001416 this->getSrc(2)->emit(Func);
John Porto921856d2015-07-07 11:56:26 -07001417 Str << ", ";
1418 this->getSrc(1)->emit(Func);
1419 Str << ", ";
1420 Dest->emit(Func);
1421}
1422
John Porto4a566862016-01-04 09:33:41 -08001423template <typename TraitsType>
1424void InstImpl<TraitsType>::InstX86Shld::emitIAS(const Cfg *Func) const {
John Porto921856d2015-07-07 11:56:26 -07001425 assert(this->getSrcSize() == 3);
1426 assert(this->getDest() == this->getSrc(0));
1427 const Variable *Dest = this->getDest();
1428 const Operand *Src1 = this->getSrc(1);
1429 const Operand *Src2 = this->getSrc(2);
John Porto4a566862016-01-04 09:33:41 -08001430 static const GPREmitterShiftD Emitter = {&Assembler::shld, &Assembler::shld};
1431 emitIASGPRShiftDouble(Func, Dest, Src1, Src2, Emitter);
John Porto921856d2015-07-07 11:56:26 -07001432}
1433
John Porto4a566862016-01-04 09:33:41 -08001434template <typename TraitsType>
1435void InstImpl<TraitsType>::InstX86Shld::dump(const Cfg *Func) const {
John Porto921856d2015-07-07 11:56:26 -07001436 if (!BuildDefs::dump())
1437 return;
1438 Ostream &Str = Func->getContext()->getStrDump();
1439 this->dumpDest(Func);
1440 Str << " = shld." << this->getDest()->getType() << " ";
1441 this->dumpSources(Func);
1442}
1443
John Porto4a566862016-01-04 09:33:41 -08001444template <typename TraitsType>
1445void InstImpl<TraitsType>::InstX86Shrd::emit(const Cfg *Func) const {
John Porto921856d2015-07-07 11:56:26 -07001446 if (!BuildDefs::dump())
1447 return;
1448 Ostream &Str = Func->getContext()->getStrEmit();
1449 Variable *Dest = this->getDest();
1450 assert(this->getSrcSize() == 3);
1451 assert(Dest == this->getSrc(0));
Jim Stichnoth6106df82015-12-16 06:17:58 -08001452 Str << "\t"
1453 "shrd" << this->getWidthString(Dest->getType()) << "\t";
Jim Stichnoth5bff61c2015-10-28 09:26:00 -07001454 this->getSrc(2)->emit(Func);
John Porto921856d2015-07-07 11:56:26 -07001455 Str << ", ";
1456 this->getSrc(1)->emit(Func);
1457 Str << ", ";
1458 Dest->emit(Func);
1459}
1460
John Porto4a566862016-01-04 09:33:41 -08001461template <typename TraitsType>
1462void InstImpl<TraitsType>::InstX86Shrd::emitIAS(const Cfg *Func) const {
John Porto921856d2015-07-07 11:56:26 -07001463 assert(this->getSrcSize() == 3);
1464 assert(this->getDest() == this->getSrc(0));
1465 const Variable *Dest = this->getDest();
1466 const Operand *Src1 = this->getSrc(1);
1467 const Operand *Src2 = this->getSrc(2);
John Porto4a566862016-01-04 09:33:41 -08001468 static const GPREmitterShiftD Emitter = {&Assembler::shrd, &Assembler::shrd};
1469 emitIASGPRShiftDouble(Func, Dest, Src1, Src2, Emitter);
John Porto921856d2015-07-07 11:56:26 -07001470}
1471
John Porto4a566862016-01-04 09:33:41 -08001472template <typename TraitsType>
1473void InstImpl<TraitsType>::InstX86Shrd::dump(const Cfg *Func) const {
John Porto921856d2015-07-07 11:56:26 -07001474 if (!BuildDefs::dump())
1475 return;
1476 Ostream &Str = Func->getContext()->getStrDump();
1477 this->dumpDest(Func);
1478 Str << " = shrd." << this->getDest()->getType() << " ";
1479 this->dumpSources(Func);
1480}
1481
John Porto4a566862016-01-04 09:33:41 -08001482template <typename TraitsType>
1483void InstImpl<TraitsType>::InstX86Cmov::emit(const Cfg *Func) const {
John Porto921856d2015-07-07 11:56:26 -07001484 if (!BuildDefs::dump())
1485 return;
1486 Ostream &Str = Func->getContext()->getStrEmit();
1487 Variable *Dest = this->getDest();
1488 Str << "\t";
John Porto4a566862016-01-04 09:33:41 -08001489 assert(Condition != Cond::Br_None);
John Porto921856d2015-07-07 11:56:26 -07001490 assert(this->getDest()->hasReg());
John Porto4a566862016-01-04 09:33:41 -08001491 Str << "cmov" << Traits::InstBrAttributes[Condition].DisplayString
John Porto921856d2015-07-07 11:56:26 -07001492 << this->getWidthString(Dest->getType()) << "\t";
1493 this->getSrc(1)->emit(Func);
1494 Str << ", ";
1495 Dest->emit(Func);
1496}
1497
John Porto4a566862016-01-04 09:33:41 -08001498template <typename TraitsType>
1499void InstImpl<TraitsType>::InstX86Cmov::emitIAS(const Cfg *Func) const {
1500 assert(Condition != Cond::Br_None);
John Porto921856d2015-07-07 11:56:26 -07001501 assert(this->getDest()->hasReg());
1502 assert(this->getSrcSize() == 2);
1503 Operand *Src = this->getSrc(1);
1504 Type SrcTy = Src->getType();
John Porto4a566862016-01-04 09:33:41 -08001505 assert(SrcTy == IceType_i16 || SrcTy == IceType_i32 || (Traits::Is64Bit));
1506 Assembler *Asm = Func->getAssembler<Assembler>();
1507 auto *Target = InstX86Base::getTarget(Func);
John Porto921856d2015-07-07 11:56:26 -07001508 if (const auto *SrcVar = llvm::dyn_cast<Variable>(Src)) {
1509 if (SrcVar->hasReg()) {
John Porto4a566862016-01-04 09:33:41 -08001510 Asm->cmov(SrcTy, Condition,
1511 Traits::getEncodedGPR(this->getDest()->getRegNum()),
1512 Traits::getEncodedGPR(SrcVar->getRegNum()));
John Porto921856d2015-07-07 11:56:26 -07001513 } else {
John Porto4a566862016-01-04 09:33:41 -08001514 Asm->cmov(SrcTy, Condition,
1515 Traits::getEncodedGPR(this->getDest()->getRegNum()),
David Sehr21fd1032015-11-13 16:32:37 -08001516 Target->stackVarToAsmOperand(SrcVar));
John Porto921856d2015-07-07 11:56:26 -07001517 }
John Porto4a566862016-01-04 09:33:41 -08001518 } else if (const auto *Mem = llvm::dyn_cast<X86OperandMem>(Src)) {
1519 assert(Mem->getSegmentRegister() == X86OperandMem::DefaultSegment);
1520 Asm->cmov(SrcTy, Condition,
1521 Traits::getEncodedGPR(this->getDest()->getRegNum()),
David Sehr4318a412015-11-11 15:01:55 -08001522 Mem->toAsmAddress(Asm, Target));
John Porto921856d2015-07-07 11:56:26 -07001523 } else {
1524 llvm_unreachable("Unexpected operand type");
1525 }
1526}
1527
John Porto4a566862016-01-04 09:33:41 -08001528template <typename TraitsType>
1529void InstImpl<TraitsType>::InstX86Cmov::dump(const Cfg *Func) const {
John Porto921856d2015-07-07 11:56:26 -07001530 if (!BuildDefs::dump())
1531 return;
1532 Ostream &Str = Func->getContext()->getStrDump();
John Porto4a566862016-01-04 09:33:41 -08001533 Str << "cmov" << Traits::InstBrAttributes[Condition].DisplayString << ".";
John Porto921856d2015-07-07 11:56:26 -07001534 Str << this->getDest()->getType() << " ";
1535 this->dumpDest(Func);
1536 Str << ", ";
1537 this->dumpSources(Func);
1538}
1539
John Porto4a566862016-01-04 09:33:41 -08001540template <typename TraitsType>
1541void InstImpl<TraitsType>::InstX86Cmpps::emit(const Cfg *Func) const {
John Porto921856d2015-07-07 11:56:26 -07001542 if (!BuildDefs::dump())
1543 return;
1544 Ostream &Str = Func->getContext()->getStrEmit();
1545 assert(this->getSrcSize() == 2);
John Porto4a566862016-01-04 09:33:41 -08001546 assert(Condition < Cond::Cmpps_Invalid);
David Sehre3984282015-12-15 17:34:55 -08001547 Type DestTy = this->Dest->getType();
Jim Stichnoth6106df82015-12-16 06:17:58 -08001548 Str << "\t"
John Porto4a566862016-01-04 09:33:41 -08001549 "cmp" << Traits::InstCmppsAttributes[Condition].EmitString
1550 << Traits::TypeAttributes[DestTy].PdPsString << "\t";
John Porto921856d2015-07-07 11:56:26 -07001551 this->getSrc(1)->emit(Func);
1552 Str << ", ";
1553 this->getDest()->emit(Func);
1554}
1555
John Porto4a566862016-01-04 09:33:41 -08001556template <typename TraitsType>
1557void InstImpl<TraitsType>::InstX86Cmpps::emitIAS(const Cfg *Func) const {
1558 Assembler *Asm = Func->getAssembler<Assembler>();
John Porto921856d2015-07-07 11:56:26 -07001559 assert(this->getSrcSize() == 2);
John Porto4a566862016-01-04 09:33:41 -08001560 assert(Condition < Cond::Cmpps_Invalid);
Andrew Scull57e12682015-09-16 11:30:19 -07001561 // Assuming there isn't any load folding for cmpps, and vector constants are
1562 // not allowed in PNaCl.
John Porto921856d2015-07-07 11:56:26 -07001563 assert(llvm::isa<Variable>(this->getSrc(1)));
John Porto4a566862016-01-04 09:33:41 -08001564 auto *Target = InstX86Base::getTarget(Func);
Jim Stichnoth5bff61c2015-10-28 09:26:00 -07001565 const auto *SrcVar = llvm::cast<Variable>(this->getSrc(1));
John Porto921856d2015-07-07 11:56:26 -07001566 if (SrcVar->hasReg()) {
David Sehre3984282015-12-15 17:34:55 -08001567 Asm->cmpps(this->getDest()->getType(),
John Porto4a566862016-01-04 09:33:41 -08001568 Traits::getEncodedXmm(this->getDest()->getRegNum()),
1569 Traits::getEncodedXmm(SrcVar->getRegNum()), Condition);
John Porto921856d2015-07-07 11:56:26 -07001570 } else {
John Porto4a566862016-01-04 09:33:41 -08001571 Address SrcStackAddr = Target->stackVarToAsmOperand(SrcVar);
David Sehre3984282015-12-15 17:34:55 -08001572 Asm->cmpps(this->getDest()->getType(),
John Porto4a566862016-01-04 09:33:41 -08001573 Traits::getEncodedXmm(this->getDest()->getRegNum()),
John Porto921856d2015-07-07 11:56:26 -07001574 SrcStackAddr, Condition);
1575 }
1576}
1577
John Porto4a566862016-01-04 09:33:41 -08001578template <typename TraitsType>
1579void InstImpl<TraitsType>::InstX86Cmpps::dump(const Cfg *Func) const {
John Porto921856d2015-07-07 11:56:26 -07001580 if (!BuildDefs::dump())
1581 return;
1582 Ostream &Str = Func->getContext()->getStrDump();
John Porto4a566862016-01-04 09:33:41 -08001583 assert(Condition < Cond::Cmpps_Invalid);
John Porto921856d2015-07-07 11:56:26 -07001584 this->dumpDest(Func);
John Porto4a566862016-01-04 09:33:41 -08001585 Str << " = cmp" << Traits::InstCmppsAttributes[Condition].EmitString << "ps"
1586 "\t";
John Porto921856d2015-07-07 11:56:26 -07001587 this->dumpSources(Func);
1588}
1589
John Porto4a566862016-01-04 09:33:41 -08001590template <typename TraitsType>
1591void InstImpl<TraitsType>::InstX86Cmpxchg::emit(const Cfg *Func) const {
John Porto921856d2015-07-07 11:56:26 -07001592 if (!BuildDefs::dump())
1593 return;
1594 Ostream &Str = Func->getContext()->getStrEmit();
1595 assert(this->getSrcSize() == 3);
1596 if (this->Locked) {
Jim Stichnoth6106df82015-12-16 06:17:58 -08001597 Str << "\t"
1598 "lock";
John Porto921856d2015-07-07 11:56:26 -07001599 }
Jim Stichnoth6106df82015-12-16 06:17:58 -08001600 Str << "\t"
1601 "cmpxchg" << this->getWidthString(this->getSrc(0)->getType()) << "\t";
John Porto921856d2015-07-07 11:56:26 -07001602 this->getSrc(2)->emit(Func);
1603 Str << ", ";
1604 this->getSrc(0)->emit(Func);
1605}
1606
John Porto4a566862016-01-04 09:33:41 -08001607template <typename TraitsType>
1608void InstImpl<TraitsType>::InstX86Cmpxchg::emitIAS(const Cfg *Func) const {
John Porto921856d2015-07-07 11:56:26 -07001609 assert(this->getSrcSize() == 3);
John Porto4a566862016-01-04 09:33:41 -08001610 Assembler *Asm = Func->getAssembler<Assembler>();
John Porto921856d2015-07-07 11:56:26 -07001611 Type Ty = this->getSrc(0)->getType();
John Porto4a566862016-01-04 09:33:41 -08001612 auto *Target = InstX86Base::getTarget(Func);
1613 const auto Mem = llvm::cast<X86OperandMem>(this->getSrc(0));
1614 assert(Mem->getSegmentRegister() == X86OperandMem::DefaultSegment);
1615 const Address Addr = Mem->toAsmAddress(Asm, Target);
Jim Stichnoth5bff61c2015-10-28 09:26:00 -07001616 const auto *VarReg = llvm::cast<Variable>(this->getSrc(2));
John Porto921856d2015-07-07 11:56:26 -07001617 assert(VarReg->hasReg());
John Porto4a566862016-01-04 09:33:41 -08001618 const GPRRegister Reg = Traits::getEncodedGPR(VarReg->getRegNum());
John Porto921856d2015-07-07 11:56:26 -07001619 Asm->cmpxchg(Ty, Addr, Reg, this->Locked);
1620}
1621
John Porto4a566862016-01-04 09:33:41 -08001622template <typename TraitsType>
1623void InstImpl<TraitsType>::InstX86Cmpxchg::dump(const Cfg *Func) const {
John Porto921856d2015-07-07 11:56:26 -07001624 if (!BuildDefs::dump())
1625 return;
1626 Ostream &Str = Func->getContext()->getStrDump();
1627 if (this->Locked) {
1628 Str << "lock ";
1629 }
1630 Str << "cmpxchg." << this->getSrc(0)->getType() << " ";
1631 this->dumpSources(Func);
1632}
1633
John Porto4a566862016-01-04 09:33:41 -08001634template <typename TraitsType>
1635void InstImpl<TraitsType>::InstX86Cmpxchg8b::emit(const Cfg *Func) const {
John Porto921856d2015-07-07 11:56:26 -07001636 if (!BuildDefs::dump())
1637 return;
1638 Ostream &Str = Func->getContext()->getStrEmit();
1639 assert(this->getSrcSize() == 5);
1640 if (this->Locked) {
Jim Stichnoth6106df82015-12-16 06:17:58 -08001641 Str << "\t"
1642 "lock";
John Porto921856d2015-07-07 11:56:26 -07001643 }
Jim Stichnoth6106df82015-12-16 06:17:58 -08001644 Str << "\t"
1645 "cmpxchg8b\t";
John Porto921856d2015-07-07 11:56:26 -07001646 this->getSrc(0)->emit(Func);
1647}
1648
John Porto4a566862016-01-04 09:33:41 -08001649template <typename TraitsType>
1650void InstImpl<TraitsType>::InstX86Cmpxchg8b::emitIAS(const Cfg *Func) const {
John Porto921856d2015-07-07 11:56:26 -07001651 assert(this->getSrcSize() == 5);
John Porto4a566862016-01-04 09:33:41 -08001652 Assembler *Asm = Func->getAssembler<Assembler>();
1653 const auto Mem = llvm::cast<X86OperandMem>(this->getSrc(0));
1654 assert(Mem->getSegmentRegister() == X86OperandMem::DefaultSegment);
1655 auto *Target = InstX86Base::getTarget(Func);
1656 const Address Addr = Mem->toAsmAddress(Asm, Target);
John Porto921856d2015-07-07 11:56:26 -07001657 Asm->cmpxchg8b(Addr, this->Locked);
1658}
1659
John Porto4a566862016-01-04 09:33:41 -08001660template <typename TraitsType>
1661void InstImpl<TraitsType>::InstX86Cmpxchg8b::dump(const Cfg *Func) const {
John Porto921856d2015-07-07 11:56:26 -07001662 if (!BuildDefs::dump())
1663 return;
1664 Ostream &Str = Func->getContext()->getStrDump();
1665 if (this->Locked) {
1666 Str << "lock ";
1667 }
1668 Str << "cmpxchg8b ";
1669 this->dumpSources(Func);
1670}
1671
John Porto4a566862016-01-04 09:33:41 -08001672template <typename TraitsType>
1673void InstImpl<TraitsType>::InstX86Cvt::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() == 1);
Jim Stichnoth6106df82015-12-16 06:17:58 -08001678 Str << "\t"
1679 "cvt";
John Porto921856d2015-07-07 11:56:26 -07001680 if (isTruncating())
1681 Str << "t";
John Porto4a566862016-01-04 09:33:41 -08001682 Str << Traits::TypeAttributes[this->getSrc(0)->getType()].CvtString << "2"
1683 << Traits::TypeAttributes[this->getDest()->getType()].CvtString << "\t";
John Porto921856d2015-07-07 11:56:26 -07001684 this->getSrc(0)->emit(Func);
1685 Str << ", ";
1686 this->getDest()->emit(Func);
1687}
1688
John Porto4a566862016-01-04 09:33:41 -08001689template <typename TraitsType>
1690void InstImpl<TraitsType>::InstX86Cvt::emitIAS(const Cfg *Func) const {
John Porto921856d2015-07-07 11:56:26 -07001691 assert(this->getSrcSize() == 1);
1692 const Variable *Dest = this->getDest();
1693 const Operand *Src = this->getSrc(0);
1694 Type DestTy = Dest->getType();
1695 Type SrcTy = Src->getType();
1696 switch (Variant) {
1697 case Si2ss: {
1698 assert(isScalarIntegerType(SrcTy));
John Porto4a566862016-01-04 09:33:41 -08001699 if (!Traits::Is64Bit) {
John Porto1d235422015-08-12 12:37:53 -07001700 assert(typeWidthInBytes(SrcTy) <= 4);
1701 } else {
1702 assert(SrcTy == IceType_i32 || SrcTy == IceType_i64);
1703 }
John Porto921856d2015-07-07 11:56:26 -07001704 assert(isScalarFloatingType(DestTy));
John Porto4a566862016-01-04 09:33:41 -08001705 static const CastEmitterRegOp<XmmRegister, GPRRegister> Emitter = {
1706 &Assembler::cvtsi2ss, &Assembler::cvtsi2ss};
1707 emitIASCastRegOp<XmmRegister, GPRRegister, Traits::getEncodedXmm,
1708 Traits::getEncodedGPR>(Func, DestTy, Dest, SrcTy, Src,
1709 Emitter);
John Porto921856d2015-07-07 11:56:26 -07001710 return;
1711 }
1712 case Tss2si: {
1713 assert(isScalarFloatingType(SrcTy));
1714 assert(isScalarIntegerType(DestTy));
Nicolas Capensdbf81e02017-01-14 12:53:55 -05001715 if (Traits::Is64Bit) {
John Porto1d235422015-08-12 12:37:53 -07001716 assert(DestTy == IceType_i32 || DestTy == IceType_i64);
Nicolas Capensdbf81e02017-01-14 12:53:55 -05001717 } else {
1718 assert(typeWidthInBytes(DestTy) <= 4);
John Porto1d235422015-08-12 12:37:53 -07001719 }
John Porto4a566862016-01-04 09:33:41 -08001720 static const CastEmitterRegOp<GPRRegister, XmmRegister> Emitter = {
1721 &Assembler::cvttss2si, &Assembler::cvttss2si};
1722 emitIASCastRegOp<GPRRegister, XmmRegister, Traits::getEncodedGPR,
1723 Traits::getEncodedXmm>(Func, DestTy, Dest, SrcTy, Src,
1724 Emitter);
John Porto921856d2015-07-07 11:56:26 -07001725 return;
1726 }
Nicolas Capensdbf81e02017-01-14 12:53:55 -05001727 case Ss2si: {
1728 assert(isScalarFloatingType(SrcTy));
1729 assert(isScalarIntegerType(DestTy));
1730 if (Traits::Is64Bit) {
1731 assert(DestTy == IceType_i32 || DestTy == IceType_i64);
1732 } else {
1733 assert(typeWidthInBytes(DestTy) <= 4);
1734 }
1735 static const CastEmitterRegOp<GPRRegister, XmmRegister> Emitter = {
1736 &Assembler::cvtss2si, &Assembler::cvtss2si};
1737 emitIASCastRegOp<GPRRegister, XmmRegister, Traits::getEncodedGPR,
1738 Traits::getEncodedXmm>(Func, DestTy, Dest, SrcTy, Src,
1739 Emitter);
1740 return;
1741 }
John Porto921856d2015-07-07 11:56:26 -07001742 case Float2float: {
1743 assert(isScalarFloatingType(SrcTy));
1744 assert(isScalarFloatingType(DestTy));
1745 assert(DestTy != SrcTy);
John Porto4a566862016-01-04 09:33:41 -08001746 static const XmmEmitterRegOp Emitter = {&Assembler::cvtfloat2float,
1747 &Assembler::cvtfloat2float};
1748 emitIASRegOpTyXMM(Func, SrcTy, Dest, Src, Emitter);
John Porto921856d2015-07-07 11:56:26 -07001749 return;
1750 }
1751 case Dq2ps: {
1752 assert(isVectorIntegerType(SrcTy));
1753 assert(isVectorFloatingType(DestTy));
John Porto4a566862016-01-04 09:33:41 -08001754 static const XmmEmitterRegOp Emitter = {&Assembler::cvtdq2ps,
1755 &Assembler::cvtdq2ps};
1756 emitIASRegOpTyXMM(Func, DestTy, Dest, Src, Emitter);
John Porto921856d2015-07-07 11:56:26 -07001757 return;
1758 }
1759 case Tps2dq: {
1760 assert(isVectorFloatingType(SrcTy));
1761 assert(isVectorIntegerType(DestTy));
John Porto4a566862016-01-04 09:33:41 -08001762 static const XmmEmitterRegOp Emitter = {&Assembler::cvttps2dq,
1763 &Assembler::cvttps2dq};
1764 emitIASRegOpTyXMM(Func, DestTy, Dest, Src, Emitter);
John Porto921856d2015-07-07 11:56:26 -07001765 return;
1766 }
Nicolas Capensdbf81e02017-01-14 12:53:55 -05001767 case Ps2dq: {
1768 assert(isVectorFloatingType(SrcTy));
1769 assert(isVectorIntegerType(DestTy));
1770 static const XmmEmitterRegOp Emitter = {&Assembler::cvtps2dq,
1771 &Assembler::cvtps2dq};
1772 emitIASRegOpTyXMM(Func, DestTy, Dest, Src, Emitter);
1773 return;
1774 }
John Porto921856d2015-07-07 11:56:26 -07001775 }
1776}
1777
John Porto4a566862016-01-04 09:33:41 -08001778template <typename TraitsType>
1779void InstImpl<TraitsType>::InstX86Cvt::dump(const Cfg *Func) const {
John Porto921856d2015-07-07 11:56:26 -07001780 if (!BuildDefs::dump())
1781 return;
1782 Ostream &Str = Func->getContext()->getStrDump();
1783 this->dumpDest(Func);
1784 Str << " = cvt";
1785 if (isTruncating())
1786 Str << "t";
John Porto4a566862016-01-04 09:33:41 -08001787 Str << Traits::TypeAttributes[this->getSrc(0)->getType()].CvtString << "2"
1788 << Traits::TypeAttributes[this->getDest()->getType()].CvtString << " ";
John Porto921856d2015-07-07 11:56:26 -07001789 this->dumpSources(Func);
1790}
1791
John Porto4a566862016-01-04 09:33:41 -08001792template <typename TraitsType>
Nicolas Capensf0d12c32016-10-27 15:17:41 -04001793void InstImpl<TraitsType>::InstX86Round::emit(const Cfg *Func) const {
1794 if (!BuildDefs::dump())
1795 return;
1796 Ostream &Str = Func->getContext()->getStrEmit();
1797 assert(this->getSrcSize() == 3);
1798 Str << "\t" << this->Opcode
Nicolas Capens83425de2016-11-01 17:18:51 -04001799 << Traits::TypeAttributes[this->getDest()->getType()].SpSdString << "\t";
Nicolas Capensf0d12c32016-10-27 15:17:41 -04001800 this->getSrc(1)->emit(Func);
1801 Str << ", ";
1802 this->getSrc(0)->emit(Func);
1803 Str << ", ";
1804 this->getDest()->emit(Func);
1805}
1806
1807template <typename TraitsType>
1808void InstImpl<TraitsType>::InstX86Round::emitIAS(const Cfg *Func) const {
1809 assert(this->getSrcSize() == 2);
1810 assert(InstX86Base::getTarget(Func)->getInstructionSet() >= Traits::SSE4_1);
1811 const Variable *Dest = this->getDest();
1812 Type Ty = Dest->getType();
1813 static const ThreeOpImmEmitter<XmmRegister, XmmRegister> Emitter = {
1814 &Assembler::round, &Assembler::round};
1815 emitIASThreeOpImmOps<XmmRegister, XmmRegister, Traits::getEncodedXmm,
1816 Traits::getEncodedXmm>(Func, Ty, Dest, this->getSrc(0),
1817 this->getSrc(1), Emitter);
1818}
1819
1820template <typename TraitsType>
John Porto4a566862016-01-04 09:33:41 -08001821void InstImpl<TraitsType>::InstX86Icmp::emit(const Cfg *Func) const {
John Porto921856d2015-07-07 11:56:26 -07001822 if (!BuildDefs::dump())
1823 return;
1824 Ostream &Str = Func->getContext()->getStrEmit();
1825 assert(this->getSrcSize() == 2);
Jim Stichnoth6106df82015-12-16 06:17:58 -08001826 Str << "\t"
1827 "cmp" << this->getWidthString(this->getSrc(0)->getType()) << "\t";
John Porto921856d2015-07-07 11:56:26 -07001828 this->getSrc(1)->emit(Func);
1829 Str << ", ";
1830 this->getSrc(0)->emit(Func);
1831}
1832
John Porto4a566862016-01-04 09:33:41 -08001833template <typename TraitsType>
1834void InstImpl<TraitsType>::InstX86Icmp::emitIAS(const Cfg *Func) const {
John Porto921856d2015-07-07 11:56:26 -07001835 assert(this->getSrcSize() == 2);
1836 const Operand *Src0 = this->getSrc(0);
1837 const Operand *Src1 = this->getSrc(1);
1838 Type Ty = Src0->getType();
John Porto4a566862016-01-04 09:33:41 -08001839 static const GPREmitterRegOp RegEmitter = {&Assembler::cmp, &Assembler::cmp,
1840 &Assembler::cmp};
1841 static const GPREmitterAddrOp AddrEmitter = {&Assembler::cmp,
1842 &Assembler::cmp};
Jim Stichnoth5bff61c2015-10-28 09:26:00 -07001843 if (const auto *SrcVar0 = llvm::dyn_cast<Variable>(Src0)) {
John Porto921856d2015-07-07 11:56:26 -07001844 if (SrcVar0->hasReg()) {
John Porto56958cb2016-01-14 09:18:18 -08001845 constexpr bool NotLea = false;
1846 emitIASRegOpTyGPR(Func, NotLea, Ty, SrcVar0, Src1, RegEmitter);
John Porto921856d2015-07-07 11:56:26 -07001847 return;
1848 }
1849 }
John Porto4a566862016-01-04 09:33:41 -08001850 emitIASAsAddrOpTyGPR(Func, Ty, Src0, Src1, AddrEmitter);
John Porto921856d2015-07-07 11:56:26 -07001851}
1852
John Porto4a566862016-01-04 09:33:41 -08001853template <typename TraitsType>
1854void InstImpl<TraitsType>::InstX86Icmp::dump(const Cfg *Func) const {
John Porto921856d2015-07-07 11:56:26 -07001855 if (!BuildDefs::dump())
1856 return;
1857 Ostream &Str = Func->getContext()->getStrDump();
1858 Str << "cmp." << this->getSrc(0)->getType() << " ";
1859 this->dumpSources(Func);
1860}
1861
John Porto4a566862016-01-04 09:33:41 -08001862template <typename TraitsType>
1863void InstImpl<TraitsType>::InstX86Ucomiss::emit(const Cfg *Func) const {
John Porto921856d2015-07-07 11:56:26 -07001864 if (!BuildDefs::dump())
1865 return;
1866 Ostream &Str = Func->getContext()->getStrEmit();
1867 assert(this->getSrcSize() == 2);
Jim Stichnoth6106df82015-12-16 06:17:58 -08001868 Str << "\t"
1869 "ucomi"
John Porto4a566862016-01-04 09:33:41 -08001870 << Traits::TypeAttributes[this->getSrc(0)->getType()].SdSsString << "\t";
John Porto921856d2015-07-07 11:56:26 -07001871 this->getSrc(1)->emit(Func);
1872 Str << ", ";
1873 this->getSrc(0)->emit(Func);
1874}
1875
John Porto4a566862016-01-04 09:33:41 -08001876template <typename TraitsType>
1877void InstImpl<TraitsType>::InstX86Ucomiss::emitIAS(const Cfg *Func) const {
John Porto921856d2015-07-07 11:56:26 -07001878 assert(this->getSrcSize() == 2);
Andrew Scull57e12682015-09-16 11:30:19 -07001879 // Currently src0 is always a variable by convention, to avoid having two
1880 // memory operands.
John Porto921856d2015-07-07 11:56:26 -07001881 assert(llvm::isa<Variable>(this->getSrc(0)));
Jim Stichnoth5bff61c2015-10-28 09:26:00 -07001882 const auto *Src0Var = llvm::cast<Variable>(this->getSrc(0));
John Porto921856d2015-07-07 11:56:26 -07001883 Type Ty = Src0Var->getType();
John Porto4a566862016-01-04 09:33:41 -08001884 static const XmmEmitterRegOp Emitter = {&Assembler::ucomiss,
1885 &Assembler::ucomiss};
1886 emitIASRegOpTyXMM(Func, Ty, Src0Var, this->getSrc(1), Emitter);
John Porto921856d2015-07-07 11:56:26 -07001887}
1888
John Porto4a566862016-01-04 09:33:41 -08001889template <typename TraitsType>
1890void InstImpl<TraitsType>::InstX86Ucomiss::dump(const Cfg *Func) const {
John Porto921856d2015-07-07 11:56:26 -07001891 if (!BuildDefs::dump())
1892 return;
1893 Ostream &Str = Func->getContext()->getStrDump();
1894 Str << "ucomiss." << this->getSrc(0)->getType() << " ";
1895 this->dumpSources(Func);
1896}
1897
John Porto4a566862016-01-04 09:33:41 -08001898template <typename TraitsType>
1899void InstImpl<TraitsType>::InstX86UD2::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() == 0);
Jim Stichnoth6106df82015-12-16 06:17:58 -08001904 Str << "\t"
1905 "ud2";
John Porto921856d2015-07-07 11:56:26 -07001906}
1907
John Porto4a566862016-01-04 09:33:41 -08001908template <typename TraitsType>
1909void InstImpl<TraitsType>::InstX86UD2::emitIAS(const Cfg *Func) const {
1910 Assembler *Asm = Func->getAssembler<Assembler>();
John Porto921856d2015-07-07 11:56:26 -07001911 Asm->ud2();
1912}
1913
John Porto4a566862016-01-04 09:33:41 -08001914template <typename TraitsType>
1915void InstImpl<TraitsType>::InstX86UD2::dump(const Cfg *Func) const {
John Porto921856d2015-07-07 11:56:26 -07001916 if (!BuildDefs::dump())
1917 return;
1918 Ostream &Str = Func->getContext()->getStrDump();
1919 Str << "ud2";
1920}
1921
John Porto4a566862016-01-04 09:33:41 -08001922template <typename TraitsType>
Eric Holk67c7c412016-04-15 13:05:37 -07001923void InstImpl<TraitsType>::InstX86Int3::emit(const Cfg *Func) const {
1924 if (!BuildDefs::dump())
1925 return;
1926 Ostream &Str = Func->getContext()->getStrEmit();
1927 assert(this->getSrcSize() == 0);
1928 Str << "\t"
1929 "int 3";
1930}
1931
1932template <typename TraitsType>
1933void InstImpl<TraitsType>::InstX86Int3::emitIAS(const Cfg *Func) const {
1934 Assembler *Asm = Func->getAssembler<Assembler>();
1935 Asm->int3();
1936}
1937
1938template <typename TraitsType>
1939void InstImpl<TraitsType>::InstX86Int3::dump(const Cfg *Func) const {
1940 if (!BuildDefs::dump())
1941 return;
1942 Ostream &Str = Func->getContext()->getStrDump();
1943 Str << "int 3";
1944}
1945
1946template <typename TraitsType>
John Porto4a566862016-01-04 09:33:41 -08001947void InstImpl<TraitsType>::InstX86Test::emit(const Cfg *Func) const {
John Porto921856d2015-07-07 11:56:26 -07001948 if (!BuildDefs::dump())
1949 return;
1950 Ostream &Str = Func->getContext()->getStrEmit();
1951 assert(this->getSrcSize() == 2);
Jim Stichnoth6106df82015-12-16 06:17:58 -08001952 Str << "\t"
1953 "test" << this->getWidthString(this->getSrc(0)->getType()) << "\t";
John Porto921856d2015-07-07 11:56:26 -07001954 this->getSrc(1)->emit(Func);
1955 Str << ", ";
1956 this->getSrc(0)->emit(Func);
1957}
1958
John Porto4a566862016-01-04 09:33:41 -08001959template <typename TraitsType>
1960void InstImpl<TraitsType>::InstX86Test::emitIAS(const Cfg *Func) const {
John Porto921856d2015-07-07 11:56:26 -07001961 assert(this->getSrcSize() == 2);
1962 const Operand *Src0 = this->getSrc(0);
1963 const Operand *Src1 = this->getSrc(1);
1964 Type Ty = Src0->getType();
1965 // The Reg/Addr form of test is not encodeable.
John Porto4a566862016-01-04 09:33:41 -08001966 static const GPREmitterRegOp RegEmitter = {&Assembler::test, nullptr,
1967 &Assembler::test};
1968 static const GPREmitterAddrOp AddrEmitter = {&Assembler::test,
1969 &Assembler::test};
Jim Stichnoth5bff61c2015-10-28 09:26:00 -07001970 if (const auto *SrcVar0 = llvm::dyn_cast<Variable>(Src0)) {
John Porto921856d2015-07-07 11:56:26 -07001971 if (SrcVar0->hasReg()) {
John Porto56958cb2016-01-14 09:18:18 -08001972 constexpr bool NotLea = false;
1973 emitIASRegOpTyGPR(Func, NotLea, Ty, SrcVar0, Src1, RegEmitter);
John Porto921856d2015-07-07 11:56:26 -07001974 return;
1975 }
1976 }
John Porto4a566862016-01-04 09:33:41 -08001977 emitIASAsAddrOpTyGPR(Func, Ty, Src0, Src1, AddrEmitter);
John Porto921856d2015-07-07 11:56:26 -07001978}
1979
John Porto4a566862016-01-04 09:33:41 -08001980template <typename TraitsType>
1981void InstImpl<TraitsType>::InstX86Test::dump(const Cfg *Func) const {
John Porto921856d2015-07-07 11:56:26 -07001982 if (!BuildDefs::dump())
1983 return;
1984 Ostream &Str = Func->getContext()->getStrDump();
1985 Str << "test." << this->getSrc(0)->getType() << " ";
1986 this->dumpSources(Func);
1987}
1988
John Porto4a566862016-01-04 09:33:41 -08001989template <typename TraitsType>
1990void InstImpl<TraitsType>::InstX86Mfence::emit(const Cfg *Func) const {
John Porto921856d2015-07-07 11:56:26 -07001991 if (!BuildDefs::dump())
1992 return;
1993 Ostream &Str = Func->getContext()->getStrEmit();
1994 assert(this->getSrcSize() == 0);
Jim Stichnoth6106df82015-12-16 06:17:58 -08001995 Str << "\t"
1996 "mfence";
John Porto921856d2015-07-07 11:56:26 -07001997}
1998
John Porto4a566862016-01-04 09:33:41 -08001999template <typename TraitsType>
2000void InstImpl<TraitsType>::InstX86Mfence::emitIAS(const Cfg *Func) const {
2001 Assembler *Asm = Func->getAssembler<Assembler>();
John Porto921856d2015-07-07 11:56:26 -07002002 Asm->mfence();
2003}
2004
John Porto4a566862016-01-04 09:33:41 -08002005template <typename TraitsType>
2006void InstImpl<TraitsType>::InstX86Mfence::dump(const Cfg *Func) const {
John Porto921856d2015-07-07 11:56:26 -07002007 if (!BuildDefs::dump())
2008 return;
2009 Ostream &Str = Func->getContext()->getStrDump();
2010 Str << "mfence";
2011}
2012
John Porto4a566862016-01-04 09:33:41 -08002013template <typename TraitsType>
2014void InstImpl<TraitsType>::InstX86Store::emit(const Cfg *Func) const {
John Porto921856d2015-07-07 11:56:26 -07002015 if (!BuildDefs::dump())
2016 return;
2017 Ostream &Str = Func->getContext()->getStrEmit();
2018 assert(this->getSrcSize() == 2);
2019 Type Ty = this->getSrc(0)->getType();
Jim Stichnoth6106df82015-12-16 06:17:58 -08002020 Str << "\t"
2021 "mov" << this->getWidthString(Ty)
John Porto4a566862016-01-04 09:33:41 -08002022 << Traits::TypeAttributes[Ty].SdSsString << "\t";
John Porto921856d2015-07-07 11:56:26 -07002023 this->getSrc(0)->emit(Func);
2024 Str << ", ";
2025 this->getSrc(1)->emit(Func);
2026}
2027
John Porto4a566862016-01-04 09:33:41 -08002028template <typename TraitsType>
2029void InstImpl<TraitsType>::InstX86Store::emitIAS(const Cfg *Func) const {
John Porto921856d2015-07-07 11:56:26 -07002030 assert(this->getSrcSize() == 2);
2031 const Operand *Dest = this->getSrc(1);
2032 const Operand *Src = this->getSrc(0);
2033 Type DestTy = Dest->getType();
2034 if (isScalarFloatingType(DestTy)) {
2035 // Src must be a register, since Dest is a Mem operand of some kind.
Jim Stichnoth5bff61c2015-10-28 09:26:00 -07002036 const auto *SrcVar = llvm::cast<Variable>(Src);
John Porto921856d2015-07-07 11:56:26 -07002037 assert(SrcVar->hasReg());
John Porto4a566862016-01-04 09:33:41 -08002038 XmmRegister SrcReg = Traits::getEncodedXmm(SrcVar->getRegNum());
2039 Assembler *Asm = Func->getAssembler<Assembler>();
2040 auto *Target = InstX86Base::getTarget(Func);
Jim Stichnoth5bff61c2015-10-28 09:26:00 -07002041 if (const auto *DestVar = llvm::dyn_cast<Variable>(Dest)) {
John Porto921856d2015-07-07 11:56:26 -07002042 assert(!DestVar->hasReg());
John Porto4a566862016-01-04 09:33:41 -08002043 Address StackAddr(Target->stackVarToAsmOperand(DestVar));
John Porto921856d2015-07-07 11:56:26 -07002044 Asm->movss(DestTy, StackAddr, SrcReg);
2045 } else {
John Porto4a566862016-01-04 09:33:41 -08002046 const auto DestMem = llvm::cast<X86OperandMem>(Dest);
2047 assert(DestMem->getSegmentRegister() == X86OperandMem::DefaultSegment);
David Sehr4318a412015-11-11 15:01:55 -08002048 Asm->movss(DestTy, DestMem->toAsmAddress(Asm, Target), SrcReg);
John Porto921856d2015-07-07 11:56:26 -07002049 }
2050 return;
2051 } else {
2052 assert(isScalarIntegerType(DestTy));
John Porto4a566862016-01-04 09:33:41 -08002053 static const GPREmitterAddrOp GPRAddrEmitter = {&Assembler::mov,
2054 &Assembler::mov};
2055 emitIASAsAddrOpTyGPR(Func, DestTy, Dest, Src, GPRAddrEmitter);
John Porto921856d2015-07-07 11:56:26 -07002056 }
2057}
2058
John Porto4a566862016-01-04 09:33:41 -08002059template <typename TraitsType>
2060void InstImpl<TraitsType>::InstX86Store::dump(const Cfg *Func) const {
John Porto921856d2015-07-07 11:56:26 -07002061 if (!BuildDefs::dump())
2062 return;
2063 Ostream &Str = Func->getContext()->getStrDump();
2064 Str << "mov." << this->getSrc(0)->getType() << " ";
2065 this->getSrc(1)->dump(Func);
2066 Str << ", ";
2067 this->getSrc(0)->dump(Func);
2068}
2069
John Porto4a566862016-01-04 09:33:41 -08002070template <typename TraitsType>
2071void InstImpl<TraitsType>::InstX86StoreP::emit(const Cfg *Func) const {
John Porto921856d2015-07-07 11:56:26 -07002072 if (!BuildDefs::dump())
2073 return;
2074 Ostream &Str = Func->getContext()->getStrEmit();
2075 assert(this->getSrcSize() == 2);
Andrew Scull713dbde2015-08-04 14:25:27 -07002076 assert(isVectorType(this->getSrc(1)->getType()));
Jim Stichnoth6106df82015-12-16 06:17:58 -08002077 Str << "\t"
2078 "movups\t";
John Porto921856d2015-07-07 11:56:26 -07002079 this->getSrc(0)->emit(Func);
2080 Str << ", ";
2081 this->getSrc(1)->emit(Func);
2082}
2083
John Porto4a566862016-01-04 09:33:41 -08002084template <typename TraitsType>
2085void InstImpl<TraitsType>::InstX86StoreP::emitIAS(const Cfg *Func) const {
2086 Assembler *Asm = Func->getAssembler<Assembler>();
John Porto921856d2015-07-07 11:56:26 -07002087 assert(this->getSrcSize() == 2);
Jim Stichnoth5bff61c2015-10-28 09:26:00 -07002088 const auto *SrcVar = llvm::cast<Variable>(this->getSrc(0));
John Porto4a566862016-01-04 09:33:41 -08002089 const auto DestMem = llvm::cast<X86OperandMem>(this->getSrc(1));
2090 assert(DestMem->getSegmentRegister() == X86OperandMem::DefaultSegment);
John Porto921856d2015-07-07 11:56:26 -07002091 assert(SrcVar->hasReg());
John Porto4a566862016-01-04 09:33:41 -08002092 auto *Target = InstX86Base::getTarget(Func);
David Sehr4318a412015-11-11 15:01:55 -08002093 Asm->movups(DestMem->toAsmAddress(Asm, Target),
John Porto4a566862016-01-04 09:33:41 -08002094 Traits::getEncodedXmm(SrcVar->getRegNum()));
John Porto921856d2015-07-07 11:56:26 -07002095}
2096
John Porto4a566862016-01-04 09:33:41 -08002097template <typename TraitsType>
2098void InstImpl<TraitsType>::InstX86StoreP::dump(const Cfg *Func) const {
John Porto921856d2015-07-07 11:56:26 -07002099 if (!BuildDefs::dump())
2100 return;
2101 Ostream &Str = Func->getContext()->getStrDump();
2102 Str << "storep." << this->getSrc(0)->getType() << " ";
2103 this->getSrc(1)->dump(Func);
2104 Str << ", ";
2105 this->getSrc(0)->dump(Func);
2106}
2107
John Porto4a566862016-01-04 09:33:41 -08002108template <typename TraitsType>
2109void InstImpl<TraitsType>::InstX86StoreQ::emit(const Cfg *Func) const {
John Porto921856d2015-07-07 11:56:26 -07002110 if (!BuildDefs::dump())
2111 return;
2112 Ostream &Str = Func->getContext()->getStrEmit();
2113 assert(this->getSrcSize() == 2);
2114 assert(this->getSrc(1)->getType() == IceType_i64 ||
Andrew Scull713dbde2015-08-04 14:25:27 -07002115 this->getSrc(1)->getType() == IceType_f64 ||
2116 isVectorType(this->getSrc(1)->getType()));
Jim Stichnoth6106df82015-12-16 06:17:58 -08002117 Str << "\t"
2118 "movq\t";
John Porto921856d2015-07-07 11:56:26 -07002119 this->getSrc(0)->emit(Func);
2120 Str << ", ";
2121 this->getSrc(1)->emit(Func);
2122}
2123
John Porto4a566862016-01-04 09:33:41 -08002124template <typename TraitsType>
2125void InstImpl<TraitsType>::InstX86StoreQ::emitIAS(const Cfg *Func) const {
2126 Assembler *Asm = Func->getAssembler<Assembler>();
John Porto921856d2015-07-07 11:56:26 -07002127 assert(this->getSrcSize() == 2);
Jim Stichnoth5bff61c2015-10-28 09:26:00 -07002128 const auto *SrcVar = llvm::cast<Variable>(this->getSrc(0));
John Porto4a566862016-01-04 09:33:41 -08002129 const auto DestMem = llvm::cast<X86OperandMem>(this->getSrc(1));
2130 assert(DestMem->getSegmentRegister() == X86OperandMem::DefaultSegment);
John Porto921856d2015-07-07 11:56:26 -07002131 assert(SrcVar->hasReg());
John Porto4a566862016-01-04 09:33:41 -08002132 auto *Target = InstX86Base::getTarget(Func);
David Sehr4318a412015-11-11 15:01:55 -08002133 Asm->movq(DestMem->toAsmAddress(Asm, Target),
John Porto4a566862016-01-04 09:33:41 -08002134 Traits::getEncodedXmm(SrcVar->getRegNum()));
John Porto921856d2015-07-07 11:56:26 -07002135}
2136
John Porto4a566862016-01-04 09:33:41 -08002137template <typename TraitsType>
2138void InstImpl<TraitsType>::InstX86StoreQ::dump(const Cfg *Func) const {
John Porto921856d2015-07-07 11:56:26 -07002139 if (!BuildDefs::dump())
2140 return;
2141 Ostream &Str = Func->getContext()->getStrDump();
2142 Str << "storeq." << this->getSrc(0)->getType() << " ";
2143 this->getSrc(1)->dump(Func);
2144 Str << ", ";
2145 this->getSrc(0)->dump(Func);
2146}
2147
John Porto4a566862016-01-04 09:33:41 -08002148template <typename TraitsType>
Nicolas Capensacfb3df2016-10-03 10:46:30 -04002149void InstImpl<TraitsType>::InstX86StoreD::emit(const Cfg *Func) const {
2150 if (!BuildDefs::dump())
2151 return;
2152 Ostream &Str = Func->getContext()->getStrEmit();
2153 assert(this->getSrcSize() == 2);
2154 assert(this->getSrc(1)->getType() == IceType_i64 ||
2155 this->getSrc(1)->getType() == IceType_f64 ||
2156 isVectorType(this->getSrc(1)->getType()));
2157 Str << "\t"
2158 "movd\t";
2159 this->getSrc(0)->emit(Func);
2160 Str << ", ";
2161 this->getSrc(1)->emit(Func);
2162}
2163
2164template <typename TraitsType>
2165void InstImpl<TraitsType>::InstX86StoreD::emitIAS(const Cfg *Func) const {
2166 Assembler *Asm = Func->getAssembler<Assembler>();
2167 assert(this->getSrcSize() == 2);
2168 const auto *SrcVar = llvm::cast<Variable>(this->getSrc(0));
2169 const auto DestMem = llvm::cast<X86OperandMem>(this->getSrc(1));
2170 assert(DestMem->getSegmentRegister() == X86OperandMem::DefaultSegment);
2171 assert(SrcVar->hasReg());
2172 auto *Target = InstX86Base::getTarget(Func);
2173 Asm->movd(SrcVar->getType(), DestMem->toAsmAddress(Asm, Target),
2174 Traits::getEncodedXmm(SrcVar->getRegNum()));
2175}
2176
2177template <typename TraitsType>
2178void InstImpl<TraitsType>::InstX86StoreD::dump(const Cfg *Func) const {
2179 if (!BuildDefs::dump())
2180 return;
2181 Ostream &Str = Func->getContext()->getStrDump();
2182 Str << "stored." << this->getSrc(0)->getType() << " ";
2183 this->getSrc(1)->dump(Func);
2184 Str << ", ";
2185 this->getSrc(0)->dump(Func);
2186}
2187
2188template <typename TraitsType>
John Porto4a566862016-01-04 09:33:41 -08002189void InstImpl<TraitsType>::InstX86Lea::emit(const Cfg *Func) const {
John Porto921856d2015-07-07 11:56:26 -07002190 if (!BuildDefs::dump())
2191 return;
Manasij Mukherjee5b7e1c02016-08-04 14:28:37 -07002192 if (auto *Add = this->deoptLeaToAddOrNull(Func)) {
2193 Add->emit(Func);
2194 return;
2195 }
2196
John Porto921856d2015-07-07 11:56:26 -07002197 Ostream &Str = Func->getContext()->getStrEmit();
2198 assert(this->getSrcSize() == 1);
2199 assert(this->getDest()->hasReg());
Jim Stichnoth6106df82015-12-16 06:17:58 -08002200 Str << "\t"
John Porto56958cb2016-01-14 09:18:18 -08002201 "lea" << this->getWidthString(this->getDest()->getType()) << "\t";
John Porto921856d2015-07-07 11:56:26 -07002202 Operand *Src0 = this->getSrc(0);
Jim Stichnoth5bff61c2015-10-28 09:26:00 -07002203 if (const auto *Src0Var = llvm::dyn_cast<Variable>(Src0)) {
John Porto921856d2015-07-07 11:56:26 -07002204 Type Ty = Src0Var->getType();
2205 // lea on x86-32 doesn't accept mem128 operands, so cast VSrc0 to an
2206 // acceptable type.
Jim Stichnoth467ffe52016-03-29 15:01:06 -07002207 Src0Var->asType(Func, isVectorType(Ty) ? IceType_i32 : Ty, RegNumT())
2208 ->emit(Func);
John Porto921856d2015-07-07 11:56:26 -07002209 } else {
2210 Src0->emit(Func);
2211 }
2212 Str << ", ";
2213 this->getDest()->emit(Func);
2214}
2215
John Porto4a566862016-01-04 09:33:41 -08002216template <typename TraitsType>
2217void InstImpl<TraitsType>::InstX86Mov::emit(const Cfg *Func) const {
John Porto921856d2015-07-07 11:56:26 -07002218 if (!BuildDefs::dump())
2219 return;
2220 Ostream &Str = Func->getContext()->getStrEmit();
2221 assert(this->getSrcSize() == 1);
2222 Operand *Src = this->getSrc(0);
2223 Type SrcTy = Src->getType();
2224 Type DestTy = this->getDest()->getType();
John Porto4a566862016-01-04 09:33:41 -08002225 if (Traits::Is64Bit && DestTy == IceType_i64 &&
Jim Stichnoth9c2c0932016-06-14 07:27:22 -07002226 llvm::isa<ConstantInteger64>(Src) &&
2227 !Utils::IsInt(32, llvm::cast<ConstantInteger64>(Src)->getValue())) {
Jim Stichnoth6106df82015-12-16 06:17:58 -08002228 Str << "\t"
John Porto008f4ce2015-12-24 13:22:18 -08002229 "movabs"
2230 "\t";
John Porto1d235422015-08-12 12:37:53 -07002231 } else {
Jim Stichnoth6106df82015-12-16 06:17:58 -08002232 Str << "\t"
2233 "mov" << (!isScalarFloatingType(DestTy)
2234 ? this->getWidthString(DestTy)
John Porto4a566862016-01-04 09:33:41 -08002235 : Traits::TypeAttributes[DestTy].SdSsString) << "\t";
John Porto1d235422015-08-12 12:37:53 -07002236 }
Jim Stichnothc59288b2015-11-09 11:38:40 -08002237 // For an integer truncation operation, src is wider than dest. In this case,
2238 // we use a mov instruction whose data width matches the narrower dest.
Andrew Scull57e12682015-09-16 11:30:19 -07002239 // TODO: This assert disallows usages such as copying a floating
2240 // point value between a vector and a scalar (which movss is used for). Clean
2241 // this up.
John Porto4a566862016-01-04 09:33:41 -08002242 assert(InstX86Base::getTarget(Func)->typeWidthInBytesOnStack(DestTy) ==
2243 InstX86Base::getTarget(Func)->typeWidthInBytesOnStack(SrcTy));
Jim Stichnothc59288b2015-11-09 11:38:40 -08002244 const Operand *NewSrc = Src;
2245 if (auto *SrcVar = llvm::dyn_cast<Variable>(Src)) {
Reed Kotler5fa0a5f2016-02-15 20:01:24 -08002246 RegNumT NewRegNum;
Jim Stichnothc59288b2015-11-09 11:38:40 -08002247 if (SrcVar->hasReg())
John Porto4a566862016-01-04 09:33:41 -08002248 NewRegNum = Traits::getGprForType(DestTy, SrcVar->getRegNum());
Jim Stichnothc59288b2015-11-09 11:38:40 -08002249 if (SrcTy != DestTy)
Jim Stichnoth467ffe52016-03-29 15:01:06 -07002250 NewSrc = SrcVar->asType(Func, DestTy, NewRegNum);
Jim Stichnothc59288b2015-11-09 11:38:40 -08002251 }
2252 NewSrc->emit(Func);
John Porto921856d2015-07-07 11:56:26 -07002253 Str << ", ";
Jim Stichnothc59288b2015-11-09 11:38:40 -08002254 this->getDest()->emit(Func);
John Porto921856d2015-07-07 11:56:26 -07002255}
2256
John Porto4a566862016-01-04 09:33:41 -08002257template <typename TraitsType>
2258void InstImpl<TraitsType>::InstX86Mov::emitIAS(const Cfg *Func) const {
John Porto921856d2015-07-07 11:56:26 -07002259 assert(this->getSrcSize() == 1);
2260 const Variable *Dest = this->getDest();
2261 const Operand *Src = this->getSrc(0);
2262 Type DestTy = Dest->getType();
2263 Type SrcTy = Src->getType();
2264 // Mov can be used for GPRs or XMM registers. Also, the type does not
Andrew Scull57e12682015-09-16 11:30:19 -07002265 // necessarily match (Mov can be used for bitcasts). However, when the type
2266 // does not match, one of the operands must be a register. Thus, the strategy
2267 // is to find out if Src or Dest are a register, then use that register's
2268 // type to decide on which emitter set to use. The emitter set will include
2269 // reg-reg movs, but that case should be unused when the types don't match.
John Porto4a566862016-01-04 09:33:41 -08002270 static const XmmEmitterRegOp XmmRegEmitter = {&Assembler::movss,
2271 &Assembler::movss};
2272 static const GPREmitterRegOp GPRRegEmitter = {
2273 &Assembler::mov, &Assembler::mov, &Assembler::mov};
2274 static const GPREmitterAddrOp GPRAddrEmitter = {&Assembler::mov,
2275 &Assembler::mov};
Jim Stichnothc59288b2015-11-09 11:38:40 -08002276 // For an integer truncation operation, src is wider than dest. In this case,
2277 // we use a mov instruction whose data width matches the narrower dest.
Andrew Scull57e12682015-09-16 11:30:19 -07002278 // TODO: This assert disallows usages such as copying a floating
2279 // point value between a vector and a scalar (which movss is used for). Clean
2280 // this up.
John Porto4a566862016-01-04 09:33:41 -08002281 auto *Target = InstX86Base::getTarget(Func);
David Sehr4318a412015-11-11 15:01:55 -08002282 assert(Target->typeWidthInBytesOnStack(this->getDest()->getType()) ==
2283 Target->typeWidthInBytesOnStack(Src->getType()));
John Porto921856d2015-07-07 11:56:26 -07002284 if (Dest->hasReg()) {
2285 if (isScalarFloatingType(DestTy)) {
John Porto4a566862016-01-04 09:33:41 -08002286 emitIASRegOpTyXMM(Func, DestTy, Dest, Src, XmmRegEmitter);
John Porto921856d2015-07-07 11:56:26 -07002287 return;
2288 } else {
2289 assert(isScalarIntegerType(DestTy));
2290 // Widen DestTy for truncation (see above note). We should only do this
2291 // when both Src and Dest are integer types.
John Porto4a566862016-01-04 09:33:41 -08002292 if (Traits::Is64Bit && DestTy == IceType_i64) {
John Porto1d235422015-08-12 12:37:53 -07002293 if (const auto *C64 = llvm::dyn_cast<ConstantInteger64>(Src)) {
John Porto4a566862016-01-04 09:33:41 -08002294 Func->getAssembler<Assembler>()->movabs(
2295 Traits::getEncodedGPR(Dest->getRegNum()), C64->getValue());
John Porto008f4ce2015-12-24 13:22:18 -08002296 return;
John Porto1d235422015-08-12 12:37:53 -07002297 }
John Porto1d235422015-08-12 12:37:53 -07002298 }
John Porto921856d2015-07-07 11:56:26 -07002299 if (isScalarIntegerType(SrcTy)) {
Jim Stichnothc59288b2015-11-09 11:38:40 -08002300 SrcTy = DestTy;
John Porto921856d2015-07-07 11:56:26 -07002301 }
John Porto56958cb2016-01-14 09:18:18 -08002302 constexpr bool NotLea = false;
2303 emitIASRegOpTyGPR(Func, NotLea, DestTy, Dest, Src, GPRRegEmitter);
John Porto921856d2015-07-07 11:56:26 -07002304 return;
2305 }
2306 } else {
Andrew Scull57e12682015-09-16 11:30:19 -07002307 // Dest must be Stack and Src *could* be a register. Use Src's type to
2308 // decide on the emitters.
John Porto4a566862016-01-04 09:33:41 -08002309 Address StackAddr(Target->stackVarToAsmOperand(Dest));
John Porto921856d2015-07-07 11:56:26 -07002310 if (isScalarFloatingType(SrcTy)) {
2311 // Src must be a register.
Jim Stichnoth5bff61c2015-10-28 09:26:00 -07002312 const auto *SrcVar = llvm::cast<Variable>(Src);
John Porto921856d2015-07-07 11:56:26 -07002313 assert(SrcVar->hasReg());
John Porto4a566862016-01-04 09:33:41 -08002314 Assembler *Asm = Func->getAssembler<Assembler>();
2315 Asm->movss(SrcTy, StackAddr, Traits::getEncodedXmm(SrcVar->getRegNum()));
John Porto921856d2015-07-07 11:56:26 -07002316 return;
2317 } else {
2318 // Src can be a register or immediate.
2319 assert(isScalarIntegerType(SrcTy));
John Porto4a566862016-01-04 09:33:41 -08002320 emitIASAddrOpTyGPR(Func, SrcTy, StackAddr, Src, GPRAddrEmitter);
John Porto921856d2015-07-07 11:56:26 -07002321 return;
2322 }
2323 return;
2324 }
2325}
2326
John Porto4a566862016-01-04 09:33:41 -08002327template <typename TraitsType>
2328void InstImpl<TraitsType>::InstX86Movd::emit(const Cfg *Func) const {
John Porto008f4ce2015-12-24 13:22:18 -08002329 if (!BuildDefs::dump())
2330 return;
2331 assert(this->getSrcSize() == 1);
2332 Variable *Dest = this->getDest();
2333 Operand *Src = this->getSrc(0);
2334
2335 if (Dest->getType() == IceType_i64 || Src->getType() == IceType_i64) {
2336 assert(Dest->getType() == IceType_f64 || Src->getType() == IceType_f64);
2337 assert(Dest->getType() != Src->getType());
2338 Ostream &Str = Func->getContext()->getStrEmit();
2339 Str << "\t"
2340 "movq"
2341 "\t";
2342 Src->emit(Func);
2343 Str << ", ";
2344 Dest->emit(Func);
2345 return;
2346 }
2347
John Porto4a566862016-01-04 09:33:41 -08002348 InstX86BaseUnaryopXmm<InstX86Base::Movd>::emit(Func);
John Porto008f4ce2015-12-24 13:22:18 -08002349}
2350
John Porto4a566862016-01-04 09:33:41 -08002351template <typename TraitsType>
2352void InstImpl<TraitsType>::InstX86Movd::emitIAS(const Cfg *Func) const {
2353 Assembler *Asm = Func->getAssembler<Assembler>();
John Porto921856d2015-07-07 11:56:26 -07002354 assert(this->getSrcSize() == 1);
2355 const Variable *Dest = this->getDest();
John Porto4a566862016-01-04 09:33:41 -08002356 auto *Target = InstX86Base::getTarget(Func);
Andrew Scull57e12682015-09-16 11:30:19 -07002357 // For insert/extract element (one of Src/Dest is an Xmm vector and the other
2358 // is an int type).
John Porto3c275ce2015-12-22 08:14:00 -08002359 if (const auto *SrcVar = llvm::dyn_cast<Variable>(this->getSrc(0))) {
2360 if (SrcVar->getType() == IceType_i32 ||
John Porto4a566862016-01-04 09:33:41 -08002361 (Traits::Is64Bit && SrcVar->getType() == IceType_i64)) {
John Porto3c275ce2015-12-22 08:14:00 -08002362 assert(isVectorType(Dest->getType()) ||
2363 (isScalarFloatingType(Dest->getType()) &&
2364 typeWidthInBytes(SrcVar->getType()) ==
2365 typeWidthInBytes(Dest->getType())));
2366 assert(Dest->hasReg());
John Porto4a566862016-01-04 09:33:41 -08002367 XmmRegister DestReg = Traits::getEncodedXmm(Dest->getRegNum());
John Porto3c275ce2015-12-22 08:14:00 -08002368 if (SrcVar->hasReg()) {
John Porto4a566862016-01-04 09:33:41 -08002369 Asm->movd(SrcVar->getType(), DestReg,
2370 Traits::getEncodedGPR(SrcVar->getRegNum()));
John Porto3c275ce2015-12-22 08:14:00 -08002371 } else {
John Porto4a566862016-01-04 09:33:41 -08002372 Address StackAddr(Target->stackVarToAsmOperand(SrcVar));
John Porto3c275ce2015-12-22 08:14:00 -08002373 Asm->movd(SrcVar->getType(), DestReg, StackAddr);
2374 }
2375 } else {
2376 assert(isVectorType(SrcVar->getType()) ||
2377 (isScalarFloatingType(SrcVar->getType()) &&
2378 typeWidthInBytes(SrcVar->getType()) ==
2379 typeWidthInBytes(Dest->getType())));
2380 assert(SrcVar->hasReg());
2381 assert(Dest->getType() == IceType_i32 ||
John Porto4a566862016-01-04 09:33:41 -08002382 (Traits::Is64Bit && Dest->getType() == IceType_i64));
2383 XmmRegister SrcReg = Traits::getEncodedXmm(SrcVar->getRegNum());
John Porto3c275ce2015-12-22 08:14:00 -08002384 if (Dest->hasReg()) {
John Porto4a566862016-01-04 09:33:41 -08002385 Asm->movd(Dest->getType(), Traits::getEncodedGPR(Dest->getRegNum()),
John Porto3c275ce2015-12-22 08:14:00 -08002386 SrcReg);
2387 } else {
John Porto4a566862016-01-04 09:33:41 -08002388 Address StackAddr(Target->stackVarToAsmOperand(Dest));
John Porto3c275ce2015-12-22 08:14:00 -08002389 Asm->movd(Dest->getType(), StackAddr, SrcReg);
2390 }
2391 }
2392 } else {
John Porto921856d2015-07-07 11:56:26 -07002393 assert(Dest->hasReg());
John Porto4a566862016-01-04 09:33:41 -08002394 XmmRegister DestReg = Traits::getEncodedXmm(Dest->getRegNum());
2395 auto *Mem = llvm::cast<X86OperandMem>(this->getSrc(0));
John Porto3c275ce2015-12-22 08:14:00 -08002396 Asm->movd(Mem->getType(), DestReg, Mem->toAsmAddress(Asm, Target));
John Porto921856d2015-07-07 11:56:26 -07002397 }
2398}
2399
John Porto4a566862016-01-04 09:33:41 -08002400template <typename TraitsType>
2401void InstImpl<TraitsType>::InstX86Movp::emit(const Cfg *Func) const {
John Porto921856d2015-07-07 11:56:26 -07002402 if (!BuildDefs::dump())
2403 return;
Andrew Scull57e12682015-09-16 11:30:19 -07002404 // TODO(wala,stichnot): movups works with all vector operands, but there
2405 // exist other instructions (movaps, movdqa, movdqu) that may perform better,
2406 // depending on the data type and alignment of the operands.
John Porto921856d2015-07-07 11:56:26 -07002407 Ostream &Str = Func->getContext()->getStrEmit();
2408 assert(this->getSrcSize() == 1);
Jim Stichnoth6106df82015-12-16 06:17:58 -08002409 Str << "\t"
2410 "movups\t";
John Porto921856d2015-07-07 11:56:26 -07002411 this->getSrc(0)->emit(Func);
2412 Str << ", ";
2413 this->getDest()->emit(Func);
2414}
2415
John Porto4a566862016-01-04 09:33:41 -08002416template <typename TraitsType>
2417void InstImpl<TraitsType>::InstX86Movp::emitIAS(const Cfg *Func) const {
John Porto921856d2015-07-07 11:56:26 -07002418 assert(this->getSrcSize() == 1);
2419 assert(isVectorType(this->getDest()->getType()));
2420 const Variable *Dest = this->getDest();
2421 const Operand *Src = this->getSrc(0);
John Porto4a566862016-01-04 09:33:41 -08002422 static const XmmEmitterMovOps Emitter = {
2423 &Assembler::movups, &Assembler::movups, &Assembler::movups};
2424 emitIASMovlikeXMM(Func, Dest, Src, Emitter);
John Porto921856d2015-07-07 11:56:26 -07002425}
2426
John Porto4a566862016-01-04 09:33:41 -08002427template <typename TraitsType>
2428void InstImpl<TraitsType>::InstX86Movq::emit(const Cfg *Func) const {
John Porto921856d2015-07-07 11:56:26 -07002429 if (!BuildDefs::dump())
2430 return;
2431 Ostream &Str = Func->getContext()->getStrEmit();
2432 assert(this->getSrcSize() == 1);
2433 assert(this->getDest()->getType() == IceType_i64 ||
2434 this->getDest()->getType() == IceType_f64);
Jim Stichnoth6106df82015-12-16 06:17:58 -08002435 Str << "\t"
John Porto008f4ce2015-12-24 13:22:18 -08002436 "movq"
2437 "\t";
John Porto921856d2015-07-07 11:56:26 -07002438 this->getSrc(0)->emit(Func);
2439 Str << ", ";
2440 this->getDest()->emit(Func);
2441}
2442
John Porto4a566862016-01-04 09:33:41 -08002443template <typename TraitsType>
2444void InstImpl<TraitsType>::InstX86Movq::emitIAS(const Cfg *Func) const {
John Porto921856d2015-07-07 11:56:26 -07002445 assert(this->getSrcSize() == 1);
2446 assert(this->getDest()->getType() == IceType_i64 ||
Nicolas Capensacfb3df2016-10-03 10:46:30 -04002447 this->getDest()->getType() == IceType_f64 ||
2448 isVectorType(this->getDest()->getType()));
John Porto921856d2015-07-07 11:56:26 -07002449 const Variable *Dest = this->getDest();
2450 const Operand *Src = this->getSrc(0);
John Porto4a566862016-01-04 09:33:41 -08002451 static const XmmEmitterMovOps Emitter = {&Assembler::movq, &Assembler::movq,
2452 &Assembler::movq};
2453 emitIASMovlikeXMM(Func, Dest, Src, Emitter);
John Porto921856d2015-07-07 11:56:26 -07002454}
2455
John Porto4a566862016-01-04 09:33:41 -08002456template <typename TraitsType>
2457void InstImpl<TraitsType>::InstX86MovssRegs::emitIAS(const Cfg *Func) const {
Andrew Scull57e12682015-09-16 11:30:19 -07002458 // This is Binop variant is only intended to be used for reg-reg moves where
2459 // part of the Dest register is untouched.
John Porto921856d2015-07-07 11:56:26 -07002460 assert(this->getSrcSize() == 2);
2461 const Variable *Dest = this->getDest();
2462 assert(Dest == this->getSrc(0));
Jim Stichnoth5bff61c2015-10-28 09:26:00 -07002463 const auto *SrcVar = llvm::cast<Variable>(this->getSrc(1));
John Porto921856d2015-07-07 11:56:26 -07002464 assert(Dest->hasReg() && SrcVar->hasReg());
John Porto4a566862016-01-04 09:33:41 -08002465 Assembler *Asm = Func->getAssembler<Assembler>();
2466 Asm->movss(IceType_f32, Traits::getEncodedXmm(Dest->getRegNum()),
2467 Traits::getEncodedXmm(SrcVar->getRegNum()));
John Porto921856d2015-07-07 11:56:26 -07002468}
2469
John Porto4a566862016-01-04 09:33:41 -08002470template <typename TraitsType>
2471void InstImpl<TraitsType>::InstX86Movsx::emitIAS(const Cfg *Func) const {
John Porto921856d2015-07-07 11:56:26 -07002472 assert(this->getSrcSize() == 1);
2473 const Variable *Dest = this->getDest();
2474 const Operand *Src = this->getSrc(0);
Andrew Scull57e12682015-09-16 11:30:19 -07002475 // Dest must be a > 8-bit register, but Src can be 8-bit. In practice we just
2476 // use the full register for Dest to avoid having an OperandSizeOverride
2477 // prefix. It also allows us to only dispatch on SrcTy.
John Porto921856d2015-07-07 11:56:26 -07002478 Type SrcTy = Src->getType();
2479 assert(typeWidthInBytes(Dest->getType()) > 1);
2480 assert(typeWidthInBytes(Dest->getType()) > typeWidthInBytes(SrcTy));
John Porto56958cb2016-01-14 09:18:18 -08002481 constexpr bool NotLea = false;
2482 emitIASRegOpTyGPR<false, true>(Func, NotLea, SrcTy, Dest, Src, this->Emitter);
2483}
2484
2485template <typename TraitsType>
2486bool InstImpl<TraitsType>::InstX86Movzx::mayBeElided(
2487 const Variable *Dest, const Operand *SrcOpnd) const {
2488 assert(Traits::Is64Bit);
2489 const auto *Src = llvm::dyn_cast<Variable>(SrcOpnd);
2490
2491 // Src is not a Variable, so it does not have a register. Movzx can't be
2492 // elided.
2493 if (Src == nullptr)
2494 return false;
2495
2496 // Movzx to/from memory can't be elided.
2497 if (!Src->hasReg() || !Dest->hasReg())
2498 return false;
2499
2500 // Reg/reg move with different source and dest can't be elided.
2501 if (Traits::getEncodedGPR(Src->getRegNum()) !=
2502 Traits::getEncodedGPR(Dest->getRegNum()))
2503 return false;
2504
2505 // A must-keep movzx 32- to 64-bit is sometimes needed in x86-64 sandboxing.
2506 return !MustKeep;
John Porto921856d2015-07-07 11:56:26 -07002507}
2508
John Porto4a566862016-01-04 09:33:41 -08002509template <typename TraitsType>
2510void InstImpl<TraitsType>::InstX86Movzx::emit(const Cfg *Func) const {
John Porto008f4ce2015-12-24 13:22:18 -08002511 if (!BuildDefs::dump())
2512 return;
John Porto4a566862016-01-04 09:33:41 -08002513 if (Traits::Is64Bit) {
John Porto008f4ce2015-12-24 13:22:18 -08002514 // There's no movzx %eXX, %rXX. To zero extend 32- to 64-bits, we emit a
2515 // mov %eXX, %eXX. The processor will still do a movzx[bw]q.
2516 assert(this->getSrcSize() == 1);
2517 const Operand *Src = this->getSrc(0);
2518 const Variable *Dest = this->Dest;
2519 if (Src->getType() == IceType_i32 && Dest->getType() == IceType_i64) {
2520 Ostream &Str = Func->getContext()->getStrEmit();
John Porto56958cb2016-01-14 09:18:18 -08002521 if (mayBeElided(Dest, Src)) {
2522 Str << "\t/* elided movzx */";
2523 } else {
2524 Str << "\t"
2525 "mov"
2526 "\t";
2527 Src->emit(Func);
2528 Str << ", ";
Jim Stichnoth467ffe52016-03-29 15:01:06 -07002529 Dest->asType(Func, IceType_i32,
John Porto56958cb2016-01-14 09:18:18 -08002530 Traits::getGprForType(IceType_i32, Dest->getRegNum()))
2531 ->emit(Func);
2532 Str << " /* movzx */";
2533 }
John Porto008f4ce2015-12-24 13:22:18 -08002534 return;
2535 }
2536 }
John Porto4a566862016-01-04 09:33:41 -08002537 InstX86BaseUnaryopGPR<InstX86Base::Movzx>::emit(Func);
John Porto008f4ce2015-12-24 13:22:18 -08002538}
2539
John Porto4a566862016-01-04 09:33:41 -08002540template <typename TraitsType>
2541void InstImpl<TraitsType>::InstX86Movzx::emitIAS(const Cfg *Func) const {
John Porto921856d2015-07-07 11:56:26 -07002542 assert(this->getSrcSize() == 1);
2543 const Variable *Dest = this->getDest();
2544 const Operand *Src = this->getSrc(0);
2545 Type SrcTy = Src->getType();
2546 assert(typeWidthInBytes(Dest->getType()) > 1);
2547 assert(typeWidthInBytes(Dest->getType()) > typeWidthInBytes(SrcTy));
John Porto56958cb2016-01-14 09:18:18 -08002548 if (Traits::Is64Bit) {
2549 if (Src->getType() == IceType_i32 && Dest->getType() == IceType_i64 &&
2550 mayBeElided(Dest, Src)) {
2551 return;
2552 }
2553 }
2554 constexpr bool NotLea = false;
2555 emitIASRegOpTyGPR<false, true>(Func, NotLea, SrcTy, Dest, Src, this->Emitter);
John Porto921856d2015-07-07 11:56:26 -07002556}
2557
John Porto4a566862016-01-04 09:33:41 -08002558template <typename TraitsType>
2559void InstImpl<TraitsType>::InstX86Nop::emit(const Cfg *Func) const {
John Porto921856d2015-07-07 11:56:26 -07002560 if (!BuildDefs::dump())
2561 return;
2562 Ostream &Str = Func->getContext()->getStrEmit();
2563 // TODO: Emit the right code for each variant.
Jim Stichnoth6106df82015-12-16 06:17:58 -08002564 Str << "\t"
Jim Stichnoth751e27e2015-12-16 12:40:31 -08002565 "nop\t/* variant = " << Variant << " */";
John Porto921856d2015-07-07 11:56:26 -07002566}
2567
John Porto4a566862016-01-04 09:33:41 -08002568template <typename TraitsType>
2569void InstImpl<TraitsType>::InstX86Nop::emitIAS(const Cfg *Func) const {
2570 Assembler *Asm = Func->getAssembler<Assembler>();
John Porto921856d2015-07-07 11:56:26 -07002571 // TODO: Emit the right code for the variant.
2572 Asm->nop();
2573}
2574
John Porto4a566862016-01-04 09:33:41 -08002575template <typename TraitsType>
2576void InstImpl<TraitsType>::InstX86Nop::dump(const Cfg *Func) const {
John Porto921856d2015-07-07 11:56:26 -07002577 if (!BuildDefs::dump())
2578 return;
2579 Ostream &Str = Func->getContext()->getStrDump();
2580 Str << "nop (variant = " << Variant << ")";
2581}
2582
John Porto4a566862016-01-04 09:33:41 -08002583template <typename TraitsType>
2584void InstImpl<TraitsType>::InstX86Fld::emit(const Cfg *Func) const {
John Porto921856d2015-07-07 11:56:26 -07002585 if (!BuildDefs::dump())
2586 return;
2587 Ostream &Str = Func->getContext()->getStrEmit();
2588 assert(this->getSrcSize() == 1);
2589 Type Ty = this->getSrc(0)->getType();
Jim Stichnoth5bff61c2015-10-28 09:26:00 -07002590 const auto *Var = llvm::dyn_cast<Variable>(this->getSrc(0));
John Porto921856d2015-07-07 11:56:26 -07002591 if (Var && Var->hasReg()) {
Andrew Scull57e12682015-09-16 11:30:19 -07002592 // This is a physical xmm register, so we need to spill it to a temporary
David Sehr0d9cf482015-11-16 17:00:38 -08002593 // stack slot. Function prolog emission guarantees that there is sufficient
2594 // space to do this.
Jim Stichnoth6106df82015-12-16 06:17:58 -08002595 Str << "\t"
John Porto4a566862016-01-04 09:33:41 -08002596 "mov" << Traits::TypeAttributes[Ty].SdSsString << "\t";
John Porto921856d2015-07-07 11:56:26 -07002597 Var->emit(Func);
Jim Stichnoth6106df82015-12-16 06:17:58 -08002598 Str << ", (%esp)\n"
2599 "\t"
2600 "fld" << this->getFldString(Ty) << "\t"
2601 "(%esp)";
John Porto921856d2015-07-07 11:56:26 -07002602 return;
2603 }
Jim Stichnoth6106df82015-12-16 06:17:58 -08002604 Str << "\t"
2605 "fld" << this->getFldString(Ty) << "\t";
John Porto921856d2015-07-07 11:56:26 -07002606 this->getSrc(0)->emit(Func);
2607}
2608
John Porto4a566862016-01-04 09:33:41 -08002609template <typename TraitsType>
2610void InstImpl<TraitsType>::InstX86Fld::emitIAS(const Cfg *Func) const {
2611 Assembler *Asm = Func->getAssembler<Assembler>();
John Porto921856d2015-07-07 11:56:26 -07002612 assert(this->getSrcSize() == 1);
2613 const Operand *Src = this->getSrc(0);
John Porto4a566862016-01-04 09:33:41 -08002614 auto *Target = InstX86Base::getTarget(Func);
John Porto921856d2015-07-07 11:56:26 -07002615 Type Ty = Src->getType();
Jim Stichnoth5bff61c2015-10-28 09:26:00 -07002616 if (const auto *Var = llvm::dyn_cast<Variable>(Src)) {
John Porto921856d2015-07-07 11:56:26 -07002617 if (Var->hasReg()) {
Andrew Scull57e12682015-09-16 11:30:19 -07002618 // This is a physical xmm register, so we need to spill it to a temporary
David Sehr0d9cf482015-11-16 17:00:38 -08002619 // stack slot. Function prolog emission guarantees that there is
2620 // sufficient space to do this.
John Porto4a566862016-01-04 09:33:41 -08002621 Address StackSlot =
2622 Address(RegisterSet::Encoded_Reg_esp, 0, AssemblerFixup::NoFixup);
2623 Asm->movss(Ty, StackSlot, Traits::getEncodedXmm(Var->getRegNum()));
John Porto921856d2015-07-07 11:56:26 -07002624 Asm->fld(Ty, StackSlot);
John Porto921856d2015-07-07 11:56:26 -07002625 } else {
John Porto4a566862016-01-04 09:33:41 -08002626 Address StackAddr(Target->stackVarToAsmOperand(Var));
John Porto921856d2015-07-07 11:56:26 -07002627 Asm->fld(Ty, StackAddr);
2628 }
John Porto4a566862016-01-04 09:33:41 -08002629 } else if (const auto *Mem = llvm::dyn_cast<X86OperandMem>(Src)) {
2630 assert(Mem->getSegmentRegister() == X86OperandMem::DefaultSegment);
David Sehr4318a412015-11-11 15:01:55 -08002631 Asm->fld(Ty, Mem->toAsmAddress(Asm, Target));
Jim Stichnoth5bff61c2015-10-28 09:26:00 -07002632 } else if (const auto *Imm = llvm::dyn_cast<Constant>(Src)) {
John Porto4a566862016-01-04 09:33:41 -08002633 Asm->fld(Ty, Traits::Address::ofConstPool(Asm, Imm));
John Porto921856d2015-07-07 11:56:26 -07002634 } else {
2635 llvm_unreachable("Unexpected operand type");
2636 }
2637}
2638
John Porto4a566862016-01-04 09:33:41 -08002639template <typename TraitsType>
2640void InstImpl<TraitsType>::InstX86Fld::dump(const Cfg *Func) const {
John Porto921856d2015-07-07 11:56:26 -07002641 if (!BuildDefs::dump())
2642 return;
2643 Ostream &Str = Func->getContext()->getStrDump();
2644 Str << "fld." << this->getSrc(0)->getType() << " ";
2645 this->dumpSources(Func);
2646}
2647
John Porto4a566862016-01-04 09:33:41 -08002648template <typename TraitsType>
2649void InstImpl<TraitsType>::InstX86Fstp::emit(const Cfg *Func) const {
John Porto921856d2015-07-07 11:56:26 -07002650 if (!BuildDefs::dump())
2651 return;
2652 Ostream &Str = Func->getContext()->getStrEmit();
2653 assert(this->getSrcSize() == 0);
2654 // TODO(jvoung,stichnot): Utilize this by setting Dest to nullptr to
Andrew Scull57e12682015-09-16 11:30:19 -07002655 // "partially" delete the fstp if the Dest is unused. Even if Dest is unused,
2656 // the fstp should be kept for the SideEffects of popping the stack.
John Porto921856d2015-07-07 11:56:26 -07002657 if (!this->getDest()) {
Jim Stichnoth6106df82015-12-16 06:17:58 -08002658 Str << "\t"
2659 "fstp\t"
2660 "st(0)";
John Porto921856d2015-07-07 11:56:26 -07002661 return;
2662 }
2663 Type Ty = this->getDest()->getType();
John Porto921856d2015-07-07 11:56:26 -07002664 if (!this->getDest()->hasReg()) {
Jim Stichnoth6106df82015-12-16 06:17:58 -08002665 Str << "\t"
2666 "fstp" << this->getFldString(Ty) << "\t";
John Porto921856d2015-07-07 11:56:26 -07002667 this->getDest()->emit(Func);
2668 return;
2669 }
Andrew Scull57e12682015-09-16 11:30:19 -07002670 // Dest is a physical (xmm) register, so st(0) needs to go through memory.
David Sehr21fd1032015-11-13 16:32:37 -08002671 // Hack this by using caller-reserved memory at the top of stack, spilling
2672 // st(0) there, and loading it into the xmm register.
Jim Stichnoth6106df82015-12-16 06:17:58 -08002673 Str << "\t"
2674 "fstp" << this->getFldString(Ty) << "\t"
2675 "(%esp)\n";
2676 Str << "\t"
John Porto4a566862016-01-04 09:33:41 -08002677 "mov" << Traits::TypeAttributes[Ty].SdSsString << "\t"
2678 "(%esp), ";
John Porto921856d2015-07-07 11:56:26 -07002679 this->getDest()->emit(Func);
John Porto921856d2015-07-07 11:56:26 -07002680}
2681
John Porto4a566862016-01-04 09:33:41 -08002682template <typename TraitsType>
2683void InstImpl<TraitsType>::InstX86Fstp::emitIAS(const Cfg *Func) const {
2684 Assembler *Asm = Func->getAssembler<Assembler>();
John Porto921856d2015-07-07 11:56:26 -07002685 assert(this->getSrcSize() == 0);
2686 const Variable *Dest = this->getDest();
2687 // TODO(jvoung,stichnot): Utilize this by setting Dest to nullptr to
Andrew Scull57e12682015-09-16 11:30:19 -07002688 // "partially" delete the fstp if the Dest is unused. Even if Dest is unused,
2689 // the fstp should be kept for the SideEffects of popping the stack.
John Porto921856d2015-07-07 11:56:26 -07002690 if (!Dest) {
John Porto4a566862016-01-04 09:33:41 -08002691 Asm->fstp(RegisterSet::getEncodedSTReg(0));
John Porto921856d2015-07-07 11:56:26 -07002692 return;
2693 }
John Porto4a566862016-01-04 09:33:41 -08002694 auto *Target = InstX86Base::getTarget(Func);
John Porto921856d2015-07-07 11:56:26 -07002695 Type Ty = Dest->getType();
2696 if (!Dest->hasReg()) {
John Porto4a566862016-01-04 09:33:41 -08002697 Address StackAddr(Target->stackVarToAsmOperand(Dest));
John Porto921856d2015-07-07 11:56:26 -07002698 Asm->fstp(Ty, StackAddr);
2699 } else {
Andrew Scull57e12682015-09-16 11:30:19 -07002700 // Dest is a physical (xmm) register, so st(0) needs to go through memory.
David Sehr21fd1032015-11-13 16:32:37 -08002701 // Hack this by using caller-reserved memory at the top of stack, spilling
2702 // st(0) there, and loading it into the xmm register.
John Porto4a566862016-01-04 09:33:41 -08002703 Address StackSlot =
2704 Address(RegisterSet::Encoded_Reg_esp, 0, AssemblerFixup::NoFixup);
John Porto921856d2015-07-07 11:56:26 -07002705 Asm->fstp(Ty, StackSlot);
John Porto4a566862016-01-04 09:33:41 -08002706 Asm->movss(Ty, Traits::getEncodedXmm(Dest->getRegNum()), StackSlot);
John Porto921856d2015-07-07 11:56:26 -07002707 }
2708}
2709
John Porto4a566862016-01-04 09:33:41 -08002710template <typename TraitsType>
2711void InstImpl<TraitsType>::InstX86Fstp::dump(const Cfg *Func) const {
John Porto921856d2015-07-07 11:56:26 -07002712 if (!BuildDefs::dump())
2713 return;
2714 Ostream &Str = Func->getContext()->getStrDump();
2715 this->dumpDest(Func);
2716 Str << " = fstp." << this->getDest()->getType() << ", st(0)";
2717}
2718
John Porto4a566862016-01-04 09:33:41 -08002719template <typename TraitsType>
2720void InstImpl<TraitsType>::InstX86Pextr::emit(const Cfg *Func) const {
John Porto921856d2015-07-07 11:56:26 -07002721 if (!BuildDefs::dump())
2722 return;
2723 Ostream &Str = Func->getContext()->getStrEmit();
2724 assert(this->getSrcSize() == 2);
2725 // pextrb and pextrd are SSE4.1 instructions.
John Porto921856d2015-07-07 11:56:26 -07002726 Str << "\t" << this->Opcode
Nicolas Capens7638e272016-10-06 11:33:55 -04002727 << Traits::TypeAttributes[this->getSrc(0)->getType()].IntegralString
2728 << "\t";
John Porto921856d2015-07-07 11:56:26 -07002729 this->getSrc(1)->emit(Func);
2730 Str << ", ";
2731 this->getSrc(0)->emit(Func);
2732 Str << ", ";
2733 Variable *Dest = this->getDest();
Andrew Scull57e12682015-09-16 11:30:19 -07002734 // pextrw must take a register dest. There is an SSE4.1 version that takes a
2735 // memory dest, but we aren't using it. For uniformity, just restrict them
2736 // all to have a register dest for now.
John Porto921856d2015-07-07 11:56:26 -07002737 assert(Dest->hasReg());
Jim Stichnoth467ffe52016-03-29 15:01:06 -07002738 Dest->asType(Func, IceType_i32, Dest->getRegNum())->emit(Func);
John Porto921856d2015-07-07 11:56:26 -07002739}
2740
John Porto4a566862016-01-04 09:33:41 -08002741template <typename TraitsType>
2742void InstImpl<TraitsType>::InstX86Pextr::emitIAS(const Cfg *Func) const {
John Porto921856d2015-07-07 11:56:26 -07002743 assert(this->getSrcSize() == 2);
2744 // pextrb and pextrd are SSE4.1 instructions.
2745 const Variable *Dest = this->getDest();
John Porto4a566862016-01-04 09:33:41 -08002746 Type DispatchTy = Traits::getInVectorElementType(this->getSrc(0)->getType());
Andrew Scull57e12682015-09-16 11:30:19 -07002747 // pextrw must take a register dest. There is an SSE4.1 version that takes a
2748 // memory dest, but we aren't using it. For uniformity, just restrict them
2749 // all to have a register dest for now.
John Porto921856d2015-07-07 11:56:26 -07002750 assert(Dest->hasReg());
2751 // pextrw's Src(0) must be a register (both SSE4.1 and SSE2).
2752 assert(llvm::cast<Variable>(this->getSrc(0))->hasReg());
John Porto4a566862016-01-04 09:33:41 -08002753 static const ThreeOpImmEmitter<GPRRegister, XmmRegister> Emitter = {
2754 &Assembler::pextr, nullptr};
2755 emitIASThreeOpImmOps<GPRRegister, XmmRegister, Traits::getEncodedGPR,
2756 Traits::getEncodedXmm>(
John Porto921856d2015-07-07 11:56:26 -07002757 Func, DispatchTy, Dest, this->getSrc(0), this->getSrc(1), Emitter);
2758}
2759
John Porto4a566862016-01-04 09:33:41 -08002760template <typename TraitsType>
2761void InstImpl<TraitsType>::InstX86Pinsr::emit(const Cfg *Func) const {
John Porto921856d2015-07-07 11:56:26 -07002762 if (!BuildDefs::dump())
2763 return;
2764 Ostream &Str = Func->getContext()->getStrEmit();
2765 assert(this->getSrcSize() == 3);
John Porto921856d2015-07-07 11:56:26 -07002766 Str << "\t" << this->Opcode
Nicolas Capens7638e272016-10-06 11:33:55 -04002767 << Traits::TypeAttributes[this->getDest()->getType()].IntegralString
2768 << "\t";
John Porto921856d2015-07-07 11:56:26 -07002769 this->getSrc(2)->emit(Func);
2770 Str << ", ";
2771 Operand *Src1 = this->getSrc(1);
Jim Stichnoth5bff61c2015-10-28 09:26:00 -07002772 if (const auto *Src1Var = llvm::dyn_cast<Variable>(Src1)) {
John Porto921856d2015-07-07 11:56:26 -07002773 // If src1 is a register, it should always be r32.
2774 if (Src1Var->hasReg()) {
Jim Stichnoth8aa39662016-02-10 11:20:30 -08002775 const auto NewRegNum = Traits::getBaseReg(Src1Var->getRegNum());
Jim Stichnoth467ffe52016-03-29 15:01:06 -07002776 const Variable *NewSrc = Src1Var->asType(Func, IceType_i32, NewRegNum);
Jim Stichnoth5bff61c2015-10-28 09:26:00 -07002777 NewSrc->emit(Func);
John Porto921856d2015-07-07 11:56:26 -07002778 } else {
2779 Src1Var->emit(Func);
2780 }
2781 } else {
2782 Src1->emit(Func);
2783 }
2784 Str << ", ";
2785 this->getDest()->emit(Func);
2786}
2787
John Porto4a566862016-01-04 09:33:41 -08002788template <typename TraitsType>
2789void InstImpl<TraitsType>::InstX86Pinsr::emitIAS(const Cfg *Func) const {
John Porto921856d2015-07-07 11:56:26 -07002790 assert(this->getSrcSize() == 3);
2791 assert(this->getDest() == this->getSrc(0));
2792 // pinsrb and pinsrd are SSE4.1 instructions.
2793 const Operand *Src0 = this->getSrc(1);
2794 Type DispatchTy = Src0->getType();
Andrew Scull57e12682015-09-16 11:30:19 -07002795 // If src1 is a register, it should always be r32 (this should fall out from
2796 // the encodings for ByteRegs overlapping the encodings for r32), but we have
Jim Stichnoth5bff61c2015-10-28 09:26:00 -07002797 // to make sure the register allocator didn't choose an 8-bit high register
2798 // like "ah".
2799 if (BuildDefs::asserts()) {
2800 if (auto *Src0Var = llvm::dyn_cast<Variable>(Src0)) {
2801 if (Src0Var->hasReg()) {
Jim Stichnoth8aa39662016-02-10 11:20:30 -08002802 const auto RegNum = Src0Var->getRegNum();
2803 const auto BaseRegNum = Traits::getBaseReg(RegNum);
Jim Stichnoth5bff61c2015-10-28 09:26:00 -07002804 (void)BaseRegNum;
John Porto4a566862016-01-04 09:33:41 -08002805 assert(Traits::getEncodedGPR(RegNum) ==
2806 Traits::getEncodedGPR(BaseRegNum));
Jim Stichnoth5bff61c2015-10-28 09:26:00 -07002807 }
2808 }
2809 }
John Porto4a566862016-01-04 09:33:41 -08002810 static const ThreeOpImmEmitter<XmmRegister, GPRRegister> Emitter = {
2811 &Assembler::pinsr, &Assembler::pinsr};
2812 emitIASThreeOpImmOps<XmmRegister, GPRRegister, Traits::getEncodedXmm,
2813 Traits::getEncodedGPR>(Func, DispatchTy, this->getDest(),
2814 Src0, this->getSrc(2), Emitter);
John Porto921856d2015-07-07 11:56:26 -07002815}
2816
John Porto4a566862016-01-04 09:33:41 -08002817template <typename TraitsType>
2818void InstImpl<TraitsType>::InstX86Pshufd::emitIAS(const Cfg *Func) const {
John Porto921856d2015-07-07 11:56:26 -07002819 assert(this->getSrcSize() == 2);
2820 const Variable *Dest = this->getDest();
2821 Type Ty = Dest->getType();
John Porto4a566862016-01-04 09:33:41 -08002822 static const ThreeOpImmEmitter<XmmRegister, XmmRegister> Emitter = {
2823 &Assembler::pshufd, &Assembler::pshufd};
2824 emitIASThreeOpImmOps<XmmRegister, XmmRegister, Traits::getEncodedXmm,
2825 Traits::getEncodedXmm>(Func, Ty, Dest, this->getSrc(0),
2826 this->getSrc(1), Emitter);
John Porto921856d2015-07-07 11:56:26 -07002827}
2828
John Porto4a566862016-01-04 09:33:41 -08002829template <typename TraitsType>
2830void InstImpl<TraitsType>::InstX86Shufps::emitIAS(const Cfg *Func) const {
John Porto921856d2015-07-07 11:56:26 -07002831 assert(this->getSrcSize() == 3);
2832 const Variable *Dest = this->getDest();
2833 assert(Dest == this->getSrc(0));
2834 Type Ty = Dest->getType();
John Porto4a566862016-01-04 09:33:41 -08002835 static const ThreeOpImmEmitter<XmmRegister, XmmRegister> Emitter = {
2836 &Assembler::shufps, &Assembler::shufps};
2837 emitIASThreeOpImmOps<XmmRegister, XmmRegister, Traits::getEncodedXmm,
2838 Traits::getEncodedXmm>(Func, Ty, Dest, this->getSrc(1),
2839 this->getSrc(2), Emitter);
John Porto921856d2015-07-07 11:56:26 -07002840}
2841
John Porto4a566862016-01-04 09:33:41 -08002842template <typename TraitsType>
2843void InstImpl<TraitsType>::InstX86Pop::emit(const Cfg *Func) const {
John Porto921856d2015-07-07 11:56:26 -07002844 if (!BuildDefs::dump())
2845 return;
2846 Ostream &Str = Func->getContext()->getStrEmit();
2847 assert(this->getSrcSize() == 0);
Jim Stichnoth6106df82015-12-16 06:17:58 -08002848 Str << "\t"
2849 "pop\t";
John Porto921856d2015-07-07 11:56:26 -07002850 this->getDest()->emit(Func);
2851}
2852
John Porto4a566862016-01-04 09:33:41 -08002853template <typename TraitsType>
2854void InstImpl<TraitsType>::InstX86Pop::emitIAS(const Cfg *Func) const {
John Porto921856d2015-07-07 11:56:26 -07002855 assert(this->getSrcSize() == 0);
John Porto4a566862016-01-04 09:33:41 -08002856 Assembler *Asm = Func->getAssembler<Assembler>();
John Porto921856d2015-07-07 11:56:26 -07002857 if (this->getDest()->hasReg()) {
John Porto4a566862016-01-04 09:33:41 -08002858 Asm->popl(Traits::getEncodedGPR(this->getDest()->getRegNum()));
John Porto921856d2015-07-07 11:56:26 -07002859 } else {
John Porto4a566862016-01-04 09:33:41 -08002860 auto *Target = InstX86Base::getTarget(Func);
David Sehrb8e49c12015-11-12 14:41:22 -08002861 Asm->popl(Target->stackVarToAsmOperand(this->getDest()));
John Porto921856d2015-07-07 11:56:26 -07002862 }
2863}
2864
John Porto4a566862016-01-04 09:33:41 -08002865template <typename TraitsType>
2866void InstImpl<TraitsType>::InstX86Pop::dump(const Cfg *Func) const {
John Porto921856d2015-07-07 11:56:26 -07002867 if (!BuildDefs::dump())
2868 return;
2869 Ostream &Str = Func->getContext()->getStrDump();
2870 this->dumpDest(Func);
2871 Str << " = pop." << this->getDest()->getType() << " ";
2872}
2873
John Porto4a566862016-01-04 09:33:41 -08002874template <typename TraitsType>
2875void InstImpl<TraitsType>::InstX86Push::emit(const Cfg *Func) const {
John Porto921856d2015-07-07 11:56:26 -07002876 if (!BuildDefs::dump())
2877 return;
2878 Ostream &Str = Func->getContext()->getStrEmit();
Jim Stichnoth6106df82015-12-16 06:17:58 -08002879 Str << "\t"
John Porto56958cb2016-01-14 09:18:18 -08002880 "push"
2881 "\t";
2882 assert(this->getSrcSize() == 1);
2883 const Operand *Src = this->getSrc(0);
2884 Src->emit(Func);
John Porto921856d2015-07-07 11:56:26 -07002885}
2886
John Porto4a566862016-01-04 09:33:41 -08002887template <typename TraitsType>
2888void InstImpl<TraitsType>::InstX86Push::emitIAS(const Cfg *Func) const {
John Porto4a566862016-01-04 09:33:41 -08002889 Assembler *Asm = Func->getAssembler<Assembler>();
John Porto56958cb2016-01-14 09:18:18 -08002890
2891 assert(this->getSrcSize() == 1);
2892 const Operand *Src = this->getSrc(0);
2893
2894 if (const auto *Var = llvm::dyn_cast<Variable>(Src)) {
2895 Asm->pushl(Traits::getEncodedGPR(Var->getRegNum()));
2896 } else if (const auto *Const32 = llvm::dyn_cast<ConstantInteger32>(Src)) {
2897 Asm->pushl(AssemblerImmediate(Const32->getValue()));
2898 } else if (auto *CR = llvm::dyn_cast<ConstantRelocatable>(Src)) {
2899 Asm->pushl(CR);
2900 } else {
2901 llvm_unreachable("Unexpected operand type");
2902 }
John Porto921856d2015-07-07 11:56:26 -07002903}
2904
John Porto4a566862016-01-04 09:33:41 -08002905template <typename TraitsType>
2906void InstImpl<TraitsType>::InstX86Push::dump(const Cfg *Func) const {
John Porto921856d2015-07-07 11:56:26 -07002907 if (!BuildDefs::dump())
2908 return;
2909 Ostream &Str = Func->getContext()->getStrDump();
2910 Str << "push." << this->getSrc(0)->getType() << " ";
2911 this->dumpSources(Func);
2912}
2913
John Porto4a566862016-01-04 09:33:41 -08002914template <typename TraitsType>
2915void InstImpl<TraitsType>::InstX86Ret::emit(const Cfg *Func) const {
John Porto921856d2015-07-07 11:56:26 -07002916 if (!BuildDefs::dump())
2917 return;
2918 Ostream &Str = Func->getContext()->getStrEmit();
Jim Stichnoth6106df82015-12-16 06:17:58 -08002919 Str << "\t"
2920 "ret";
John Porto921856d2015-07-07 11:56:26 -07002921}
2922
John Porto4a566862016-01-04 09:33:41 -08002923template <typename TraitsType>
2924void InstImpl<TraitsType>::InstX86Ret::emitIAS(const Cfg *Func) const {
2925 Assembler *Asm = Func->getAssembler<Assembler>();
John Porto921856d2015-07-07 11:56:26 -07002926 Asm->ret();
2927}
2928
John Porto4a566862016-01-04 09:33:41 -08002929template <typename TraitsType>
2930void InstImpl<TraitsType>::InstX86Ret::dump(const Cfg *Func) const {
John Porto921856d2015-07-07 11:56:26 -07002931 if (!BuildDefs::dump())
2932 return;
2933 Ostream &Str = Func->getContext()->getStrDump();
2934 Type Ty =
2935 (this->getSrcSize() == 0 ? IceType_void : this->getSrc(0)->getType());
2936 Str << "ret." << Ty << " ";
2937 this->dumpSources(Func);
2938}
2939
John Porto4a566862016-01-04 09:33:41 -08002940template <typename TraitsType>
2941void InstImpl<TraitsType>::InstX86Setcc::emit(const Cfg *Func) const {
John Porto921856d2015-07-07 11:56:26 -07002942 if (!BuildDefs::dump())
2943 return;
2944 Ostream &Str = Func->getContext()->getStrEmit();
Jim Stichnoth6106df82015-12-16 06:17:58 -08002945 Str << "\t"
John Porto4a566862016-01-04 09:33:41 -08002946 "set" << Traits::InstBrAttributes[Condition].DisplayString << "\t";
John Porto921856d2015-07-07 11:56:26 -07002947 this->Dest->emit(Func);
2948}
2949
John Porto4a566862016-01-04 09:33:41 -08002950template <typename TraitsType>
2951void InstImpl<TraitsType>::InstX86Setcc::emitIAS(const Cfg *Func) const {
2952 assert(Condition != Cond::Br_None);
John Porto921856d2015-07-07 11:56:26 -07002953 assert(this->getDest()->getType() == IceType_i1);
2954 assert(this->getSrcSize() == 0);
John Porto4a566862016-01-04 09:33:41 -08002955 Assembler *Asm = Func->getAssembler<Assembler>();
2956 auto *Target = InstX86Base::getTarget(Func);
John Porto921856d2015-07-07 11:56:26 -07002957 if (this->getDest()->hasReg())
John Porto4a566862016-01-04 09:33:41 -08002958 Asm->setcc(Condition,
2959 Traits::getEncodedByteReg(this->getDest()->getRegNum()));
John Porto921856d2015-07-07 11:56:26 -07002960 else
David Sehrb8e49c12015-11-12 14:41:22 -08002961 Asm->setcc(Condition, Target->stackVarToAsmOperand(this->getDest()));
John Porto921856d2015-07-07 11:56:26 -07002962 return;
2963}
2964
John Porto4a566862016-01-04 09:33:41 -08002965template <typename TraitsType>
2966void InstImpl<TraitsType>::InstX86Setcc::dump(const Cfg *Func) const {
John Porto921856d2015-07-07 11:56:26 -07002967 if (!BuildDefs::dump())
2968 return;
2969 Ostream &Str = Func->getContext()->getStrDump();
John Porto4a566862016-01-04 09:33:41 -08002970 Str << "setcc." << Traits::InstBrAttributes[Condition].DisplayString << " ";
John Porto921856d2015-07-07 11:56:26 -07002971 this->dumpDest(Func);
2972}
2973
John Porto4a566862016-01-04 09:33:41 -08002974template <typename TraitsType>
2975void InstImpl<TraitsType>::InstX86Xadd::emit(const Cfg *Func) const {
John Porto921856d2015-07-07 11:56:26 -07002976 if (!BuildDefs::dump())
2977 return;
2978 Ostream &Str = Func->getContext()->getStrEmit();
2979 if (this->Locked) {
Jim Stichnoth6106df82015-12-16 06:17:58 -08002980 Str << "\t"
2981 "lock";
John Porto921856d2015-07-07 11:56:26 -07002982 }
Jim Stichnoth6106df82015-12-16 06:17:58 -08002983 Str << "\t"
2984 "xadd" << this->getWidthString(this->getSrc(0)->getType()) << "\t";
John Porto921856d2015-07-07 11:56:26 -07002985 this->getSrc(1)->emit(Func);
2986 Str << ", ";
2987 this->getSrc(0)->emit(Func);
2988}
2989
John Porto4a566862016-01-04 09:33:41 -08002990template <typename TraitsType>
2991void InstImpl<TraitsType>::InstX86Xadd::emitIAS(const Cfg *Func) const {
John Porto921856d2015-07-07 11:56:26 -07002992 assert(this->getSrcSize() == 2);
John Porto4a566862016-01-04 09:33:41 -08002993 Assembler *Asm = Func->getAssembler<Assembler>();
John Porto921856d2015-07-07 11:56:26 -07002994 Type Ty = this->getSrc(0)->getType();
John Porto4a566862016-01-04 09:33:41 -08002995 const auto Mem = llvm::cast<X86OperandMem>(this->getSrc(0));
2996 assert(Mem->getSegmentRegister() == X86OperandMem::DefaultSegment);
2997 auto *Target = InstX86Base::getTarget(Func);
2998 const Address Addr = Mem->toAsmAddress(Asm, Target);
Jim Stichnoth5bff61c2015-10-28 09:26:00 -07002999 const auto *VarReg = llvm::cast<Variable>(this->getSrc(1));
John Porto921856d2015-07-07 11:56:26 -07003000 assert(VarReg->hasReg());
John Porto4a566862016-01-04 09:33:41 -08003001 const GPRRegister Reg = Traits::getEncodedGPR(VarReg->getRegNum());
John Porto921856d2015-07-07 11:56:26 -07003002 Asm->xadd(Ty, Addr, Reg, this->Locked);
3003}
3004
John Porto4a566862016-01-04 09:33:41 -08003005template <typename TraitsType>
3006void InstImpl<TraitsType>::InstX86Xadd::dump(const Cfg *Func) const {
John Porto921856d2015-07-07 11:56:26 -07003007 if (!BuildDefs::dump())
3008 return;
3009 Ostream &Str = Func->getContext()->getStrDump();
3010 if (this->Locked) {
3011 Str << "lock ";
3012 }
3013 Type Ty = this->getSrc(0)->getType();
3014 Str << "xadd." << Ty << " ";
3015 this->dumpSources(Func);
3016}
3017
John Porto4a566862016-01-04 09:33:41 -08003018template <typename TraitsType>
3019void InstImpl<TraitsType>::InstX86Xchg::emit(const Cfg *Func) const {
John Porto921856d2015-07-07 11:56:26 -07003020 if (!BuildDefs::dump())
3021 return;
3022 Ostream &Str = Func->getContext()->getStrEmit();
Jim Stichnoth6106df82015-12-16 06:17:58 -08003023 Str << "\t"
3024 "xchg" << this->getWidthString(this->getSrc(0)->getType()) << "\t";
John Porto921856d2015-07-07 11:56:26 -07003025 this->getSrc(1)->emit(Func);
3026 Str << ", ";
3027 this->getSrc(0)->emit(Func);
3028}
3029
John Porto4a566862016-01-04 09:33:41 -08003030template <typename TraitsType>
3031void InstImpl<TraitsType>::InstX86Xchg::emitIAS(const Cfg *Func) const {
John Porto921856d2015-07-07 11:56:26 -07003032 assert(this->getSrcSize() == 2);
John Porto4a566862016-01-04 09:33:41 -08003033 Assembler *Asm = Func->getAssembler<Assembler>();
John Porto921856d2015-07-07 11:56:26 -07003034 Type Ty = this->getSrc(0)->getType();
Andrew Scullcfa628b2015-08-20 14:23:05 -07003035 const auto *VarReg1 = llvm::cast<Variable>(this->getSrc(1));
3036 assert(VarReg1->hasReg());
John Porto4a566862016-01-04 09:33:41 -08003037 const GPRRegister Reg1 = Traits::getEncodedGPR(VarReg1->getRegNum());
Andrew Scullcfa628b2015-08-20 14:23:05 -07003038
3039 if (const auto *VarReg0 = llvm::dyn_cast<Variable>(this->getSrc(0))) {
3040 assert(VarReg0->hasReg());
John Porto4a566862016-01-04 09:33:41 -08003041 const GPRRegister Reg0 = Traits::getEncodedGPR(VarReg0->getRegNum());
Andrew Scullcfa628b2015-08-20 14:23:05 -07003042 Asm->xchg(Ty, Reg0, Reg1);
3043 return;
3044 }
3045
John Porto4a566862016-01-04 09:33:41 -08003046 const auto *Mem = llvm::cast<X86OperandMem>(this->getSrc(0));
3047 assert(Mem->getSegmentRegister() == X86OperandMem::DefaultSegment);
3048 auto *Target = InstX86Base::getTarget(Func);
3049 const Address Addr = Mem->toAsmAddress(Asm, Target);
Andrew Scullcfa628b2015-08-20 14:23:05 -07003050 Asm->xchg(Ty, Addr, Reg1);
John Porto921856d2015-07-07 11:56:26 -07003051}
3052
John Porto4a566862016-01-04 09:33:41 -08003053template <typename TraitsType>
3054void InstImpl<TraitsType>::InstX86Xchg::dump(const Cfg *Func) const {
John Porto921856d2015-07-07 11:56:26 -07003055 if (!BuildDefs::dump())
3056 return;
3057 Ostream &Str = Func->getContext()->getStrDump();
3058 Type Ty = this->getSrc(0)->getType();
3059 Str << "xchg." << Ty << " ";
3060 this->dumpSources(Func);
3061}
3062
John Porto4a566862016-01-04 09:33:41 -08003063template <typename TraitsType>
3064void InstImpl<TraitsType>::InstX86IacaStart::emit(const Cfg *Func) const {
Andrew Scull2c862522015-08-06 08:41:53 -07003065 if (!BuildDefs::dump())
3066 return;
3067 Ostream &Str = Func->getContext()->getStrEmit();
3068 Str << "\t# IACA_START\n"
Jim Stichnoth6106df82015-12-16 06:17:58 -08003069 "\t.byte 0x0F, 0x0B\n"
3070 "\t"
3071 "movl\t$111, %ebx\n"
3072 "\t.byte 0x64, 0x67, 0x90";
Andrew Scull2c862522015-08-06 08:41:53 -07003073}
3074
John Porto4a566862016-01-04 09:33:41 -08003075template <typename TraitsType>
3076void InstImpl<TraitsType>::InstX86IacaStart::emitIAS(const Cfg *Func) const {
3077 Assembler *Asm = Func->getAssembler<Assembler>();
Andrew Scull2c862522015-08-06 08:41:53 -07003078 Asm->iaca_start();
3079}
3080
John Porto4a566862016-01-04 09:33:41 -08003081template <typename TraitsType>
3082void InstImpl<TraitsType>::InstX86IacaStart::dump(const Cfg *Func) const {
Andrew Scull2c862522015-08-06 08:41:53 -07003083 if (!BuildDefs::dump())
3084 return;
3085 Ostream &Str = Func->getContext()->getStrDump();
3086 Str << "IACA_START";
3087}
3088
John Porto4a566862016-01-04 09:33:41 -08003089template <typename TraitsType>
3090void InstImpl<TraitsType>::InstX86IacaEnd::emit(const Cfg *Func) const {
Andrew Scull2c862522015-08-06 08:41:53 -07003091 if (!BuildDefs::dump())
3092 return;
3093 Ostream &Str = Func->getContext()->getStrEmit();
3094 Str << "\t# IACA_END\n"
Jim Stichnoth6106df82015-12-16 06:17:58 -08003095 "\t"
3096 "movl\t$222, %ebx\n"
3097 "\t.byte 0x64, 0x67, 0x90\n"
3098 "\t.byte 0x0F, 0x0B";
Andrew Scull2c862522015-08-06 08:41:53 -07003099}
3100
John Porto4a566862016-01-04 09:33:41 -08003101template <typename TraitsType>
3102void InstImpl<TraitsType>::InstX86IacaEnd::emitIAS(const Cfg *Func) const {
3103 Assembler *Asm = Func->getAssembler<Assembler>();
Andrew Scull2c862522015-08-06 08:41:53 -07003104 Asm->iaca_end();
3105}
3106
John Porto4a566862016-01-04 09:33:41 -08003107template <typename TraitsType>
3108void InstImpl<TraitsType>::InstX86IacaEnd::dump(const Cfg *Func) const {
Andrew Scull2c862522015-08-06 08:41:53 -07003109 if (!BuildDefs::dump())
3110 return;
3111 Ostream &Str = Func->getContext()->getStrDump();
3112 Str << "IACA_END";
3113}
3114
John Porto4a566862016-01-04 09:33:41 -08003115} // end of namespace X86NAMESPACE
John Porto921856d2015-07-07 11:56:26 -07003116
3117} // end of namespace Ice
3118
3119#endif // SUBZERO_SRC_ICEINSTX86BASEIMPL_H