blob: bb994409ce4c21077d97d3ca22d1cbfb71a82717 [file] [log] [blame]
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -07001//===- subzero/src/IceInstX8632.cpp - X86-32 instruction implementation ---===//
2//
3// The Subzero Code Generator
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// This file implements the InstX8632 and OperandX8632 classes,
11// primarily the constructors and the dump()/emit() methods.
12//
13//===----------------------------------------------------------------------===//
14
15#include "IceCfg.h"
16#include "IceCfgNode.h"
17#include "IceInst.h"
18#include "IceInstX8632.h"
19#include "IceTargetLoweringX8632.h"
20#include "IceOperand.h"
21
22namespace Ice {
23
24namespace {
25
26const struct InstX8632BrAttributes_ {
27 const char *DisplayString;
28 const char *EmitString;
29} InstX8632BrAttributes[] = {
30#define X(tag, dump, emit) \
31 { dump, emit } \
32 ,
33 ICEINSTX8632BR_TABLE
34#undef X
35 };
36const size_t InstX8632BrAttributesSize =
37 llvm::array_lengthof(InstX8632BrAttributes);
38
39const struct TypeX8632Attributes_ {
40 const char *CvtString; // i (integer), s (single FP), d (double FP)
41 const char *SdSsString; // ss, sd, or <blank>
Matt Wala83b80362014-07-16 10:21:30 -070042 const char *PackString; // b, w, d, or <blank>
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -070043 const char *WidthString; // {byte,word,dword,qword} ptr
44} TypeX8632Attributes[] = {
Matt Wala83b80362014-07-16 10:21:30 -070045#define X(tag, cvt, sdss, pack, width) \
46 { cvt, "" sdss, pack, width } \
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -070047 ,
48 ICETYPEX8632_TABLE
49#undef X
50 };
51const size_t TypeX8632AttributesSize =
52 llvm::array_lengthof(TypeX8632Attributes);
53
Jan Voung3bd9f1a2014-06-18 10:50:57 -070054const char *InstX8632SegmentRegNames[] = {
Jan Vounga3a01a22014-07-14 10:32:41 -070055#define X(val, name) name,
56 SEG_REGX8632_TABLE
Jan Voung3bd9f1a2014-06-18 10:50:57 -070057#undef X
58};
59const size_t InstX8632SegmentRegNamesSize =
60 llvm::array_lengthof(InstX8632SegmentRegNames);
61
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -070062} // end of anonymous namespace
63
64const char *InstX8632::getWidthString(Type Ty) {
65 return TypeX8632Attributes[Ty].WidthString;
66}
67
68OperandX8632Mem::OperandX8632Mem(Cfg *Func, Type Ty, Variable *Base,
69 Constant *Offset, Variable *Index,
Jan Voung3bd9f1a2014-06-18 10:50:57 -070070 uint16_t Shift, SegmentRegisters SegmentReg)
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -070071 : OperandX8632(kMem, Ty), Base(Base), Offset(Offset), Index(Index),
Jan Voung3bd9f1a2014-06-18 10:50:57 -070072 Shift(Shift), SegmentReg(SegmentReg) {
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -070073 assert(Shift <= 3);
74 Vars = NULL;
75 NumVars = 0;
76 if (Base)
77 ++NumVars;
78 if (Index)
79 ++NumVars;
80 if (NumVars) {
81 Vars = Func->allocateArrayOf<Variable *>(NumVars);
82 SizeT I = 0;
83 if (Base)
84 Vars[I++] = Base;
85 if (Index)
86 Vars[I++] = Index;
87 assert(I == NumVars);
88 }
89}
90
91InstX8632Mul::InstX8632Mul(Cfg *Func, Variable *Dest, Variable *Source1,
92 Operand *Source2)
93 : InstX8632(Func, InstX8632::Mul, 2, Dest) {
94 addSource(Source1);
95 addSource(Source2);
96}
97
Jan Vounge4da26f2014-07-15 17:52:39 -070098InstX8632Neg::InstX8632Neg(Cfg *Func, Operand *SrcDest)
99 : InstX8632(Func, InstX8632::Neg, 1, llvm::dyn_cast<Variable>(SrcDest)) {
100 addSource(SrcDest);
101}
102
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700103InstX8632Shld::InstX8632Shld(Cfg *Func, Variable *Dest, Variable *Source1,
104 Variable *Source2)
105 : InstX8632(Func, InstX8632::Shld, 3, Dest) {
106 addSource(Dest);
107 addSource(Source1);
108 addSource(Source2);
109}
110
111InstX8632Shrd::InstX8632Shrd(Cfg *Func, Variable *Dest, Variable *Source1,
112 Variable *Source2)
113 : InstX8632(Func, InstX8632::Shrd, 3, Dest) {
114 addSource(Dest);
115 addSource(Source1);
116 addSource(Source2);
117}
118
119InstX8632Label::InstX8632Label(Cfg *Func, TargetX8632 *Target)
120 : InstX8632(Func, InstX8632::Label, 0, NULL),
121 Number(Target->makeNextLabelNumber()) {}
122
123IceString InstX8632Label::getName(const Cfg *Func) const {
124 char buf[30];
125 snprintf(buf, llvm::array_lengthof(buf), "%u", Number);
126 return ".L" + Func->getFunctionName() + "$__" + buf;
127}
128
129InstX8632Br::InstX8632Br(Cfg *Func, CfgNode *TargetTrue, CfgNode *TargetFalse,
Jan Vounge4da26f2014-07-15 17:52:39 -0700130 InstX8632Label *Label, InstX8632::BrCond Condition)
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700131 : InstX8632(Func, InstX8632::Br, 0, NULL), Condition(Condition),
132 TargetTrue(TargetTrue), TargetFalse(TargetFalse), Label(Label) {}
133
134InstX8632Call::InstX8632Call(Cfg *Func, Variable *Dest, Operand *CallTarget)
135 : InstX8632(Func, InstX8632::Call, 1, Dest) {
136 HasSideEffects = true;
137 addSource(CallTarget);
138}
139
140InstX8632Cdq::InstX8632Cdq(Cfg *Func, Variable *Dest, Operand *Source)
141 : InstX8632(Func, InstX8632::Cdq, 1, Dest) {
142 assert(Dest->getRegNum() == TargetX8632::Reg_edx);
143 assert(llvm::isa<Variable>(Source));
144 assert(llvm::dyn_cast<Variable>(Source)->getRegNum() == TargetX8632::Reg_eax);
145 addSource(Source);
146}
147
Jan Vounge4da26f2014-07-15 17:52:39 -0700148InstX8632Cmov::InstX8632Cmov(Cfg *Func, Variable *Dest, Operand *Source,
149 InstX8632::BrCond Condition)
150 : InstX8632(Func, InstX8632::Cmov, 2, Dest), Condition(Condition) {
151 // The final result is either the original Dest, or Source, so mark
152 // both as sources.
153 addSource(Dest);
154 addSource(Source);
155}
156
Jan Vounga3a01a22014-07-14 10:32:41 -0700157InstX8632Cmpxchg::InstX8632Cmpxchg(Cfg *Func, Operand *DestOrAddr,
158 Variable *Eax, Variable *Desired,
159 bool Locked)
160 : InstX8632Lockable(Func, InstX8632::Cmpxchg, 3,
161 llvm::dyn_cast<Variable>(DestOrAddr), Locked) {
162 assert(Eax->getRegNum() == TargetX8632::Reg_eax);
163 addSource(DestOrAddr);
164 addSource(Eax);
165 addSource(Desired);
166}
167
168InstX8632Cmpxchg8b::InstX8632Cmpxchg8b(Cfg *Func, OperandX8632 *Addr,
169 Variable *Edx, Variable *Eax,
170 Variable *Ecx, Variable *Ebx,
171 bool Locked)
172 : InstX8632Lockable(Func, InstX8632::Cmpxchg, 5, NULL, Locked) {
173 assert(Edx->getRegNum() == TargetX8632::Reg_edx);
174 assert(Eax->getRegNum() == TargetX8632::Reg_eax);
175 assert(Ecx->getRegNum() == TargetX8632::Reg_ecx);
176 assert(Ebx->getRegNum() == TargetX8632::Reg_ebx);
177 addSource(Addr);
178 addSource(Edx);
179 addSource(Eax);
180 addSource(Ecx);
181 addSource(Ebx);
182}
183
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700184InstX8632Cvt::InstX8632Cvt(Cfg *Func, Variable *Dest, Operand *Source)
185 : InstX8632(Func, InstX8632::Cvt, 1, Dest) {
186 addSource(Source);
187}
188
189InstX8632Icmp::InstX8632Icmp(Cfg *Func, Operand *Src0, Operand *Src1)
190 : InstX8632(Func, InstX8632::Icmp, 2, NULL) {
191 addSource(Src0);
192 addSource(Src1);
193}
194
195InstX8632Ucomiss::InstX8632Ucomiss(Cfg *Func, Operand *Src0, Operand *Src1)
196 : InstX8632(Func, InstX8632::Ucomiss, 2, NULL) {
197 addSource(Src0);
198 addSource(Src1);
199}
200
Jan Voung3bd9f1a2014-06-18 10:50:57 -0700201InstX8632UD2::InstX8632UD2(Cfg *Func)
202 : InstX8632(Func, InstX8632::UD2, 0, NULL) {}
203
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700204InstX8632Test::InstX8632Test(Cfg *Func, Operand *Src1, Operand *Src2)
205 : InstX8632(Func, InstX8632::Test, 2, NULL) {
206 addSource(Src1);
207 addSource(Src2);
208}
209
Jan Voung5cd240d2014-06-25 10:36:46 -0700210InstX8632Mfence::InstX8632Mfence(Cfg *Func)
211 : InstX8632(Func, InstX8632::Mfence, 0, NULL) {
212 HasSideEffects = true;
213}
214
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700215InstX8632Store::InstX8632Store(Cfg *Func, Operand *Value, OperandX8632 *Mem)
216 : InstX8632(Func, InstX8632::Store, 2, NULL) {
217 addSource(Value);
218 addSource(Mem);
219}
220
221InstX8632Mov::InstX8632Mov(Cfg *Func, Variable *Dest, Operand *Source)
222 : InstX8632(Func, InstX8632::Mov, 1, Dest) {
223 addSource(Source);
224}
225
Matt Wala928f1292014-07-07 16:50:46 -0700226InstX8632Movp::InstX8632Movp(Cfg *Func, Variable *Dest, Operand *Source)
227 : InstX8632(Func, InstX8632::Movp, 1, Dest) {
228 addSource(Source);
229}
230
Jan Voung5cd240d2014-06-25 10:36:46 -0700231InstX8632StoreQ::InstX8632StoreQ(Cfg *Func, Operand *Value, OperandX8632 *Mem)
232 : InstX8632(Func, InstX8632::StoreQ, 2, NULL) {
233 addSource(Value);
234 addSource(Mem);
235}
236
237InstX8632Movq::InstX8632Movq(Cfg *Func, Variable *Dest, Operand *Source)
238 : InstX8632(Func, InstX8632::Movq, 1, Dest) {
239 addSource(Source);
240}
241
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700242InstX8632Movsx::InstX8632Movsx(Cfg *Func, Variable *Dest, Operand *Source)
243 : InstX8632(Func, InstX8632::Movsx, 1, Dest) {
244 addSource(Source);
245}
246
247InstX8632Movzx::InstX8632Movzx(Cfg *Func, Variable *Dest, Operand *Source)
248 : InstX8632(Func, InstX8632::Movzx, 1, Dest) {
249 addSource(Source);
250}
251
252InstX8632Fld::InstX8632Fld(Cfg *Func, Operand *Src)
253 : InstX8632(Func, InstX8632::Fld, 1, NULL) {
254 addSource(Src);
255}
256
257InstX8632Fstp::InstX8632Fstp(Cfg *Func, Variable *Dest)
258 : InstX8632(Func, InstX8632::Fstp, 0, Dest) {}
259
260InstX8632Pop::InstX8632Pop(Cfg *Func, Variable *Dest)
261 : InstX8632(Func, InstX8632::Pop, 0, Dest) {}
262
263InstX8632Push::InstX8632Push(Cfg *Func, Operand *Source,
264 bool SuppressStackAdjustment)
265 : InstX8632(Func, InstX8632::Push, 1, NULL),
266 SuppressStackAdjustment(SuppressStackAdjustment) {
267 addSource(Source);
268}
269
270bool InstX8632Mov::isRedundantAssign() const {
Matt Wala928f1292014-07-07 16:50:46 -0700271 // TODO(stichnot): The isRedundantAssign() implementations for
272 // InstX8632Mov, InstX8632Movp, and InstX8632Movq are
273 // identical. Consolidate them.
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700274 Variable *Src = llvm::dyn_cast<Variable>(getSrc(0));
275 if (Src == NULL)
276 return false;
277 if (getDest()->hasReg() && getDest()->getRegNum() == Src->getRegNum()) {
278 // TODO: On x86-64, instructions like "mov eax, eax" are used to
279 // clear the upper 32 bits of rax. We need to recognize and
280 // preserve these.
281 return true;
282 }
283 if (!getDest()->hasReg() && !Src->hasReg() &&
284 Dest->getStackOffset() == Src->getStackOffset())
285 return true;
286 return false;
287}
288
Matt Wala928f1292014-07-07 16:50:46 -0700289bool InstX8632Movp::isRedundantAssign() const {
290 Variable *Src = llvm::dyn_cast<Variable>(getSrc(0));
291 if (Src == NULL)
292 return false;
293 if (getDest()->hasReg() && getDest()->getRegNum() == Src->getRegNum()) {
294 return true;
295 }
296 if (!getDest()->hasReg() && !Src->hasReg() &&
297 Dest->getStackOffset() == Src->getStackOffset())
298 return true;
299 return false;
300}
301
Jan Voung5cd240d2014-06-25 10:36:46 -0700302bool InstX8632Movq::isRedundantAssign() const {
303 Variable *Src = llvm::dyn_cast<Variable>(getSrc(0));
304 if (Src == NULL)
305 return false;
306 if (getDest()->hasReg() && getDest()->getRegNum() == Src->getRegNum()) {
307 return true;
308 }
309 if (!getDest()->hasReg() && !Src->hasReg() &&
310 Dest->getStackOffset() == Src->getStackOffset())
311 return true;
312 return false;
313}
314
Matt Wala7fa22d82014-07-17 12:41:31 -0700315InstX8632Pshufd::InstX8632Pshufd(Cfg *Func, Variable *Dest, Operand *Source1,
316 Operand *Source2)
317 : InstX8632(Func, InstX8632::Pshufd, 2, Dest) {
318 addSource(Source1);
319 addSource(Source2);
320}
321
322InstX8632Shufps::InstX8632Shufps(Cfg *Func, Variable *Dest, Operand *Source1,
323 Operand *Source2)
324 : InstX8632(Func, InstX8632::Shufps, 3, Dest) {
325 addSource(Dest);
326 addSource(Source1);
327 addSource(Source2);
328}
329
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700330InstX8632Ret::InstX8632Ret(Cfg *Func, Variable *Source)
331 : InstX8632(Func, InstX8632::Ret, Source ? 1 : 0, NULL) {
332 if (Source)
333 addSource(Source);
334}
335
Jan Voung5cd240d2014-06-25 10:36:46 -0700336InstX8632Xadd::InstX8632Xadd(Cfg *Func, Operand *Dest, Variable *Source,
337 bool Locked)
Jan Vounga3a01a22014-07-14 10:32:41 -0700338 : InstX8632Lockable(Func, InstX8632::Xadd, 2,
339 llvm::dyn_cast<Variable>(Dest), Locked) {
340 addSource(Dest);
341 addSource(Source);
342}
343
344InstX8632Xchg::InstX8632Xchg(Cfg *Func, Operand *Dest, Variable *Source)
345 : InstX8632(Func, InstX8632::Xchg, 2, llvm::dyn_cast<Variable>(Dest)) {
Jan Voung5cd240d2014-06-25 10:36:46 -0700346 addSource(Dest);
347 addSource(Source);
348}
349
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700350// ======================== Dump routines ======================== //
351
352void InstX8632::dump(const Cfg *Func) const {
353 Ostream &Str = Func->getContext()->getStrDump();
354 Str << "[X8632] ";
355 Inst::dump(Func);
356}
357
358void InstX8632Label::emit(const Cfg *Func) const {
359 Ostream &Str = Func->getContext()->getStrEmit();
360 Str << getName(Func) << ":\n";
361}
362
363void InstX8632Label::dump(const Cfg *Func) const {
364 Ostream &Str = Func->getContext()->getStrDump();
365 Str << getName(Func) << ":";
366}
367
368void InstX8632Br::emit(const Cfg *Func) const {
369 Ostream &Str = Func->getContext()->getStrEmit();
370 Str << "\t";
371
372 if (Condition == Br_None) {
373 Str << "jmp";
374 } else {
375 Str << InstX8632BrAttributes[Condition].EmitString;
376 }
377
378 if (Label) {
379 Str << "\t" << Label->getName(Func) << "\n";
380 } else {
381 if (Condition == Br_None) {
382 Str << "\t" << getTargetFalse()->getAsmName() << "\n";
383 } else {
384 Str << "\t" << getTargetTrue()->getAsmName() << "\n";
385 if (getTargetFalse()) {
386 Str << "\tjmp\t" << getTargetFalse()->getAsmName() << "\n";
387 }
388 }
389 }
390}
391
392void InstX8632Br::dump(const Cfg *Func) const {
393 Ostream &Str = Func->getContext()->getStrDump();
394 Str << "br ";
395
396 if (Condition == Br_None) {
397 Str << "label %"
398 << (Label ? Label->getName(Func) : getTargetFalse()->getName());
399 return;
400 }
401
402 Str << InstX8632BrAttributes[Condition].DisplayString;
403 if (Label) {
404 Str << ", label %" << Label->getName(Func);
405 } else {
406 Str << ", label %" << getTargetTrue()->getName();
407 if (getTargetFalse()) {
408 Str << ", label %" << getTargetFalse()->getName();
409 }
410 }
411}
412
413void InstX8632Call::emit(const Cfg *Func) const {
414 Ostream &Str = Func->getContext()->getStrEmit();
415 assert(getSrcSize() == 1);
416 Str << "\tcall\t";
417 getCallTarget()->emit(Func);
418 Str << "\n";
419 Func->getTarget()->resetStackAdjustment();
420}
421
422void InstX8632Call::dump(const Cfg *Func) const {
423 Ostream &Str = Func->getContext()->getStrDump();
424 if (getDest()) {
425 dumpDest(Func);
426 Str << " = ";
427 }
428 Str << "call ";
429 getCallTarget()->dump(Func);
430}
431
432// The ShiftHack parameter is used to emit "cl" instead of "ecx" for
433// shift instructions, in order to be syntactically valid. The
434// Opcode parameter needs to be char* and not IceString because of
435// template issues.
436void emitTwoAddress(const char *Opcode, const Inst *Inst, const Cfg *Func,
437 bool ShiftHack) {
438 Ostream &Str = Func->getContext()->getStrEmit();
439 assert(Inst->getSrcSize() == 2);
440 assert(Inst->getDest() == Inst->getSrc(0));
441 Str << "\t" << Opcode << "\t";
442 Inst->getDest()->emit(Func);
443 Str << ", ";
444 bool EmittedSrc1 = false;
445 if (ShiftHack) {
446 Variable *ShiftReg = llvm::dyn_cast<Variable>(Inst->getSrc(1));
447 if (ShiftReg && ShiftReg->getRegNum() == TargetX8632::Reg_ecx) {
448 Str << "cl";
449 EmittedSrc1 = true;
450 }
451 }
452 if (!EmittedSrc1)
453 Inst->getSrc(1)->emit(Func);
454 Str << "\n";
455}
456
Jan Vounge4da26f2014-07-15 17:52:39 -0700457template <> const char *InstX8632Bsf::Opcode = "bsf";
458template <> const char *InstX8632Bsr::Opcode = "bsr";
459template <> const char *InstX8632Sqrtss::Opcode = "sqrtss";
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700460template <> const char *InstX8632Add::Opcode = "add";
Matt Wala8d1072e2014-07-11 15:43:51 -0700461template <> const char *InstX8632Addps::Opcode = "addps";
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700462template <> const char *InstX8632Adc::Opcode = "adc";
463template <> const char *InstX8632Addss::Opcode = "addss";
Matt Wala7fa22d82014-07-17 12:41:31 -0700464template <> const char *InstX8632Padd::Opcode = "padd";
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700465template <> const char *InstX8632Sub::Opcode = "sub";
Matt Wala8d1072e2014-07-11 15:43:51 -0700466template <> const char *InstX8632Subps::Opcode = "subps";
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700467template <> const char *InstX8632Subss::Opcode = "subss";
468template <> const char *InstX8632Sbb::Opcode = "sbb";
Matt Wala7fa22d82014-07-17 12:41:31 -0700469template <> const char *InstX8632Psub::Opcode = "psub";
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700470template <> const char *InstX8632And::Opcode = "and";
Matt Wala83b80362014-07-16 10:21:30 -0700471template <> const char *InstX8632Pand::Opcode = "pand";
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700472template <> const char *InstX8632Or::Opcode = "or";
Matt Wala7fa22d82014-07-17 12:41:31 -0700473template <> const char *InstX8632Por::Opcode = "por";
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700474template <> const char *InstX8632Xor::Opcode = "xor";
Matt Wala928f1292014-07-07 16:50:46 -0700475template <> const char *InstX8632Pxor::Opcode = "pxor";
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700476template <> const char *InstX8632Imul::Opcode = "imul";
Matt Wala8d1072e2014-07-11 15:43:51 -0700477template <> const char *InstX8632Mulps::Opcode = "mulps";
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700478template <> const char *InstX8632Mulss::Opcode = "mulss";
Matt Wala7fa22d82014-07-17 12:41:31 -0700479template <> const char *InstX8632Pmullw::Opcode = "pmullw";
480template <> const char *InstX8632Pmuludq::Opcode = "pmuludq";
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700481template <> const char *InstX8632Div::Opcode = "div";
Matt Wala8d1072e2014-07-11 15:43:51 -0700482template <> const char *InstX8632Divps::Opcode = "divps";
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700483template <> const char *InstX8632Idiv::Opcode = "idiv";
484template <> const char *InstX8632Divss::Opcode = "divss";
485template <> const char *InstX8632Shl::Opcode = "shl";
Matt Wala83b80362014-07-16 10:21:30 -0700486template <> const char *InstX8632Psll::Opcode = "psll";
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700487template <> const char *InstX8632Shr::Opcode = "shr";
488template <> const char *InstX8632Sar::Opcode = "sar";
Matt Wala83b80362014-07-16 10:21:30 -0700489template <> const char *InstX8632Psra::Opcode = "psra";
490template <> const char *InstX8632Pcmpeq::Opcode = "pcmpeq";
491template <> const char *InstX8632Pcmpgt::Opcode = "pcmpgt";
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700492
Jan Vounge4da26f2014-07-15 17:52:39 -0700493template <> void InstX8632Sqrtss::emit(const Cfg *Func) const {
494 Ostream &Str = Func->getContext()->getStrEmit();
495 assert(getSrcSize() == 1);
496 Type Ty = getSrc(0)->getType();
497 assert(Ty == IceType_f32 || Ty == IceType_f64);
498 Str << "\tsqrt" << TypeX8632Attributes[Ty].SdSsString << "\t";
499 getDest()->emit(Func);
500 Str << ", ";
501 getSrc(0)->emit(Func);
502 Str << "\n";
503}
504
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700505template <> void InstX8632Addss::emit(const Cfg *Func) const {
506 char buf[30];
507 snprintf(buf, llvm::array_lengthof(buf), "add%s",
508 TypeX8632Attributes[getDest()->getType()].SdSsString);
509 emitTwoAddress(buf, this, Func);
510}
511
Matt Wala7fa22d82014-07-17 12:41:31 -0700512template <> void InstX8632Padd::emit(const Cfg *Func) const {
513 char buf[30];
514 snprintf(buf, llvm::array_lengthof(buf), "padd%s",
515 TypeX8632Attributes[getDest()->getType()].PackString);
516 emitTwoAddress(buf, this, Func);
517}
518
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700519template <> void InstX8632Subss::emit(const Cfg *Func) const {
520 char buf[30];
521 snprintf(buf, llvm::array_lengthof(buf), "sub%s",
522 TypeX8632Attributes[getDest()->getType()].SdSsString);
523 emitTwoAddress(buf, this, Func);
524}
525
Matt Wala7fa22d82014-07-17 12:41:31 -0700526template <> void InstX8632Psub::emit(const Cfg *Func) const {
527 char buf[30];
528 snprintf(buf, llvm::array_lengthof(buf), "psub%s",
529 TypeX8632Attributes[getDest()->getType()].PackString);
530 emitTwoAddress(buf, this, Func);
531}
532
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700533template <> void InstX8632Mulss::emit(const Cfg *Func) const {
534 char buf[30];
535 snprintf(buf, llvm::array_lengthof(buf), "mul%s",
536 TypeX8632Attributes[getDest()->getType()].SdSsString);
537 emitTwoAddress(buf, this, Func);
538}
539
Matt Wala7fa22d82014-07-17 12:41:31 -0700540template <> void InstX8632Pmullw::emit(const Cfg *Func) const {
541 assert(getSrc(0)->getType() == IceType_v8i16 &&
542 getSrc(1)->getType() == IceType_v8i16);
543 emitTwoAddress(Opcode, this, Func);
544}
545
546template <> void InstX8632Pmuludq::emit(const Cfg *Func) const {
547 assert(getSrc(0)->getType() == IceType_v4i32 &&
548 getSrc(1)->getType() == IceType_v4i32);
549 emitTwoAddress(Opcode, this, Func);
550}
551
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700552template <> void InstX8632Divss::emit(const Cfg *Func) const {
553 char buf[30];
554 snprintf(buf, llvm::array_lengthof(buf), "div%s",
555 TypeX8632Attributes[getDest()->getType()].SdSsString);
556 emitTwoAddress(buf, this, Func);
557}
558
559template <> void InstX8632Imul::emit(const Cfg *Func) const {
560 Ostream &Str = Func->getContext()->getStrEmit();
561 assert(getSrcSize() == 2);
562 if (getDest()->getType() == IceType_i8) {
563 // The 8-bit version of imul only allows the form "imul r/m8".
564 Variable *Src0 = llvm::dyn_cast<Variable>(getSrc(0));
565 assert(Src0 && Src0->getRegNum() == TargetX8632::Reg_eax);
566 Str << "\timul\t";
567 getSrc(1)->emit(Func);
568 Str << "\n";
569 } else if (llvm::isa<Constant>(getSrc(1))) {
570 Str << "\timul\t";
571 getDest()->emit(Func);
572 Str << ", ";
573 getSrc(0)->emit(Func);
574 Str << ", ";
575 getSrc(1)->emit(Func);
576 Str << "\n";
577 } else {
578 emitTwoAddress("imul", this, Func);
579 }
580}
581
582void InstX8632Mul::emit(const Cfg *Func) const {
583 Ostream &Str = Func->getContext()->getStrEmit();
584 assert(getSrcSize() == 2);
585 assert(llvm::isa<Variable>(getSrc(0)));
586 assert(llvm::dyn_cast<Variable>(getSrc(0))->getRegNum() ==
587 TargetX8632::Reg_eax);
588 assert(getDest()->getRegNum() == TargetX8632::Reg_eax); // TODO: allow edx?
589 Str << "\tmul\t";
590 getSrc(1)->emit(Func);
591 Str << "\n";
592}
593
594void InstX8632Mul::dump(const Cfg *Func) const {
595 Ostream &Str = Func->getContext()->getStrDump();
596 dumpDest(Func);
597 Str << " = mul." << getDest()->getType() << " ";
598 dumpSources(Func);
599}
600
Jan Vounge4da26f2014-07-15 17:52:39 -0700601void InstX8632Neg::emit(const Cfg *Func) const {
602 Ostream &Str = Func->getContext()->getStrEmit();
603 assert(getSrcSize() == 1);
604 Str << "\tneg\t";
605 getSrc(0)->emit(Func);
606 Str << "\n";
607}
608
609void InstX8632Neg::dump(const Cfg *Func) const {
610 Ostream &Str = Func->getContext()->getStrDump();
611 dumpDest(Func);
612 Str << " = neg." << getDest()->getType() << " ";
613 dumpSources(Func);
614}
615
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700616void InstX8632Shld::emit(const Cfg *Func) const {
617 Ostream &Str = Func->getContext()->getStrEmit();
618 assert(getSrcSize() == 3);
619 assert(getDest() == getSrc(0));
620 Str << "\tshld\t";
621 getDest()->emit(Func);
622 Str << ", ";
623 getSrc(1)->emit(Func);
624 Str << ", ";
625 if (Variable *ShiftReg = llvm::dyn_cast<Variable>(getSrc(2))) {
626 assert(ShiftReg->getRegNum() == TargetX8632::Reg_ecx);
627 Str << "cl";
628 } else {
629 getSrc(2)->emit(Func);
630 }
631 Str << "\n";
632}
633
634void InstX8632Shld::dump(const Cfg *Func) const {
635 Ostream &Str = Func->getContext()->getStrDump();
636 dumpDest(Func);
637 Str << " = shld." << getDest()->getType() << " ";
638 dumpSources(Func);
639}
640
641void InstX8632Shrd::emit(const Cfg *Func) const {
642 Ostream &Str = Func->getContext()->getStrEmit();
643 assert(getSrcSize() == 3);
644 assert(getDest() == getSrc(0));
645 Str << "\tshrd\t";
646 getDest()->emit(Func);
647 Str << ", ";
648 getSrc(1)->emit(Func);
649 Str << ", ";
650 if (Variable *ShiftReg = llvm::dyn_cast<Variable>(getSrc(2))) {
651 assert(ShiftReg->getRegNum() == TargetX8632::Reg_ecx);
652 Str << "cl";
653 } else {
654 getSrc(2)->emit(Func);
655 }
656 Str << "\n";
657}
658
659void InstX8632Shrd::dump(const Cfg *Func) const {
660 Ostream &Str = Func->getContext()->getStrDump();
661 dumpDest(Func);
662 Str << " = shrd." << getDest()->getType() << " ";
663 dumpSources(Func);
664}
665
666void InstX8632Cdq::emit(const Cfg *Func) const {
667 Ostream &Str = Func->getContext()->getStrEmit();
668 assert(getSrcSize() == 1);
669 Str << "\tcdq\n";
670}
671
672void InstX8632Cdq::dump(const Cfg *Func) const {
673 Ostream &Str = Func->getContext()->getStrDump();
674 dumpDest(Func);
675 Str << " = cdq." << getSrc(0)->getType() << " ";
676 dumpSources(Func);
677}
678
Jan Vounge4da26f2014-07-15 17:52:39 -0700679void InstX8632Cmov::emit(const Cfg *Func) const {
680 Ostream &Str = Func->getContext()->getStrEmit();
681 Str << "\t";
682 assert(Condition != Br_None);
683 assert(getDest()->hasReg());
684 Str << "cmov" << InstX8632BrAttributes[Condition].DisplayString << "\t";
685 getDest()->emit(Func);
686 Str << ", ";
687 getSrc(1)->emit(Func);
688 Str << "\n";
689}
690
691void InstX8632Cmov::dump(const Cfg *Func) const {
692 Ostream &Str = Func->getContext()->getStrDump();
693 Str << "cmov" << InstX8632BrAttributes[Condition].DisplayString << ".";
694 Str << getDest()->getType() << " ";
695 dumpDest(Func);
696 Str << ", ";
697 dumpSources(Func);
698}
699
Jan Vounga3a01a22014-07-14 10:32:41 -0700700void InstX8632Cmpxchg::emit(const Cfg *Func) const {
701 Ostream &Str = Func->getContext()->getStrEmit();
702 assert(getSrcSize() == 3);
703 if (Locked) {
704 Str << "\tlock";
705 }
706 Str << "\tcmpxchg\t";
707 getSrc(0)->emit(Func);
708 Str << ", ";
709 getSrc(2)->emit(Func);
710 Str << "\n";
711}
712
713void InstX8632Cmpxchg::dump(const Cfg *Func) const {
714 Ostream &Str = Func->getContext()->getStrDump();
715 if (Locked) {
716 Str << "lock ";
717 }
718 Str << "cmpxchg." << getSrc(0)->getType() << " ";
719 dumpSources(Func);
720}
721
722void InstX8632Cmpxchg8b::emit(const Cfg *Func) const {
723 Ostream &Str = Func->getContext()->getStrEmit();
724 assert(getSrcSize() == 5);
725 if (Locked) {
726 Str << "\tlock";
727 }
728 Str << "\tcmpxchg8b\t";
729 getSrc(0)->emit(Func);
730 Str << "\n";
731}
732
733void InstX8632Cmpxchg8b::dump(const Cfg *Func) const {
734 Ostream &Str = Func->getContext()->getStrDump();
735 if (Locked) {
736 Str << "lock ";
737 }
738 Str << "cmpxchg8b ";
739 dumpSources(Func);
740}
741
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700742void InstX8632Cvt::emit(const Cfg *Func) const {
743 Ostream &Str = Func->getContext()->getStrEmit();
744 assert(getSrcSize() == 1);
Matt Wala83b80362014-07-16 10:21:30 -0700745 Str << "\tcvt" << TypeX8632Attributes[getSrc(0)->getType()].CvtString << "2"
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700746 << TypeX8632Attributes[getDest()->getType()].CvtString << "\t";
747 getDest()->emit(Func);
748 Str << ", ";
749 getSrc(0)->emit(Func);
750 Str << "\n";
751}
752
753void InstX8632Cvt::dump(const Cfg *Func) const {
754 Ostream &Str = Func->getContext()->getStrDump();
755 dumpDest(Func);
Matt Wala83b80362014-07-16 10:21:30 -0700756 Str << " = cvt" << TypeX8632Attributes[getSrc(0)->getType()].CvtString
757 << "2" << TypeX8632Attributes[getDest()->getType()].CvtString << " ";
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700758 dumpSources(Func);
759}
760
761void InstX8632Icmp::emit(const Cfg *Func) const {
762 Ostream &Str = Func->getContext()->getStrEmit();
763 assert(getSrcSize() == 2);
764 Str << "\tcmp\t";
765 getSrc(0)->emit(Func);
766 Str << ", ";
767 getSrc(1)->emit(Func);
768 Str << "\n";
769}
770
771void InstX8632Icmp::dump(const Cfg *Func) const {
772 Ostream &Str = Func->getContext()->getStrDump();
773 Str << "cmp." << getSrc(0)->getType() << " ";
774 dumpSources(Func);
775}
776
777void InstX8632Ucomiss::emit(const Cfg *Func) const {
778 Ostream &Str = Func->getContext()->getStrEmit();
779 assert(getSrcSize() == 2);
780 Str << "\tucomi" << TypeX8632Attributes[getSrc(0)->getType()].SdSsString
781 << "\t";
782 getSrc(0)->emit(Func);
783 Str << ", ";
784 getSrc(1)->emit(Func);
785 Str << "\n";
786}
787
788void InstX8632Ucomiss::dump(const Cfg *Func) const {
789 Ostream &Str = Func->getContext()->getStrDump();
790 Str << "ucomiss." << getSrc(0)->getType() << " ";
791 dumpSources(Func);
792}
793
Jan Voung3bd9f1a2014-06-18 10:50:57 -0700794void InstX8632UD2::emit(const Cfg *Func) const {
795 Ostream &Str = Func->getContext()->getStrEmit();
796 assert(getSrcSize() == 0);
797 Str << "\tud2\n";
798}
799
800void InstX8632UD2::dump(const Cfg *Func) const {
801 Ostream &Str = Func->getContext()->getStrDump();
802 Str << "ud2\n";
803}
804
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700805void InstX8632Test::emit(const Cfg *Func) const {
806 Ostream &Str = Func->getContext()->getStrEmit();
807 assert(getSrcSize() == 2);
808 Str << "\ttest\t";
809 getSrc(0)->emit(Func);
810 Str << ", ";
811 getSrc(1)->emit(Func);
812 Str << "\n";
813}
814
815void InstX8632Test::dump(const Cfg *Func) const {
816 Ostream &Str = Func->getContext()->getStrDump();
817 Str << "test." << getSrc(0)->getType() << " ";
818 dumpSources(Func);
819}
820
Jan Voung5cd240d2014-06-25 10:36:46 -0700821void InstX8632Mfence::emit(const Cfg *Func) const {
822 Ostream &Str = Func->getContext()->getStrEmit();
823 assert(getSrcSize() == 0);
824 Str << "\tmfence\n";
825}
826
827void InstX8632Mfence::dump(const Cfg *Func) const {
828 Ostream &Str = Func->getContext()->getStrDump();
829 Str << "mfence\n";
830}
831
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700832void InstX8632Store::emit(const Cfg *Func) const {
833 Ostream &Str = Func->getContext()->getStrEmit();
834 assert(getSrcSize() == 2);
Jan Voung5a13f452014-06-18 10:42:02 -0700835 Str << "\tmov" << TypeX8632Attributes[getSrc(0)->getType()].SdSsString
836 << "\t";
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700837 getSrc(1)->emit(Func);
838 Str << ", ";
839 getSrc(0)->emit(Func);
840 Str << "\n";
841}
842
843void InstX8632Store::dump(const Cfg *Func) const {
844 Ostream &Str = Func->getContext()->getStrDump();
845 Str << "mov." << getSrc(0)->getType() << " ";
846 getSrc(1)->dump(Func);
847 Str << ", ";
848 getSrc(0)->dump(Func);
849}
850
Jan Voung5cd240d2014-06-25 10:36:46 -0700851void InstX8632StoreQ::emit(const Cfg *Func) const {
852 Ostream &Str = Func->getContext()->getStrEmit();
853 assert(getSrcSize() == 2);
854 assert(getSrc(1)->getType() == IceType_i64 ||
855 getSrc(1)->getType() == IceType_f64);
856 Str << "\tmovq\t";
857 getSrc(1)->emit(Func);
858 Str << ", ";
859 getSrc(0)->emit(Func);
860 Str << "\n";
861}
862
863void InstX8632StoreQ::dump(const Cfg *Func) const {
864 Ostream &Str = Func->getContext()->getStrDump();
865 Str << "storeq." << getSrc(0)->getType() << " ";
866 getSrc(1)->dump(Func);
867 Str << ", ";
868 getSrc(0)->dump(Func);
869}
870
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700871void InstX8632Mov::emit(const Cfg *Func) const {
872 Ostream &Str = Func->getContext()->getStrEmit();
873 assert(getSrcSize() == 1);
Jim Stichnothde4ca712014-06-29 08:13:48 -0700874 Operand *Src = getSrc(0);
875 // The llvm-mc assembler using Intel syntax has a bug in which "mov
876 // reg, RelocatableConstant" does not generate the right instruction
877 // with a relocation. To work around, we emit "lea reg,
878 // [RelocatableConstant]". Also, the lowering and legalization is
879 // changed to allow relocatable constants only in Assign and Call
880 // instructions or in Mem operands. TODO(stichnot): remove LEAHACK
881 // once a proper emitter is used.
882 bool UseLeaHack = llvm::isa<ConstantRelocatable>(Src);
883 Str << "\t";
884 if (UseLeaHack)
885 Str << "lea";
886 else
887 Str << "mov" << TypeX8632Attributes[getDest()->getType()].SdSsString;
888 Str << "\t";
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700889 // For an integer truncation operation, src is wider than dest.
890 // Ideally, we use a mov instruction whose data width matches the
891 // narrower dest. This is a problem if e.g. src is a register like
892 // esi or si where there is no 8-bit version of the register. To be
893 // safe, we instead widen the dest to match src. This works even
894 // for stack-allocated dest variables because typeWidthOnStack()
895 // pads to a 4-byte boundary even if only a lower portion is used.
896 assert(Func->getTarget()->typeWidthInBytesOnStack(getDest()->getType()) ==
Jim Stichnothde4ca712014-06-29 08:13:48 -0700897 Func->getTarget()->typeWidthInBytesOnStack(Src->getType()));
898 getDest()->asType(Src->getType()).emit(Func);
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700899 Str << ", ";
Jim Stichnothde4ca712014-06-29 08:13:48 -0700900 Src->emit(Func);
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700901 Str << "\n";
902}
903
904void InstX8632Mov::dump(const Cfg *Func) const {
905 Ostream &Str = Func->getContext()->getStrDump();
906 Str << "mov." << getDest()->getType() << " ";
907 dumpDest(Func);
908 Str << ", ";
909 dumpSources(Func);
910}
911
Matt Wala928f1292014-07-07 16:50:46 -0700912void InstX8632Movp::emit(const Cfg *Func) const {
913 // TODO(wala,stichnot): movups works with all vector operands, but
914 // there exist other instructions (movaps, movdqa, movdqu) that may
915 // perform better, depending on the data type and alignment of the
916 // operands.
917 Ostream &Str = Func->getContext()->getStrEmit();
918 assert(getSrcSize() == 1);
919 Str << "\tmovups\t";
920 getDest()->emit(Func);
921 Str << ", ";
922 getSrc(0)->emit(Func);
923 Str << "\n";
924}
925
Matt Wala45a06232014-07-09 16:33:22 -0700926void InstX8632Movp::dump(const Cfg *Func) const {
927 Ostream &Str = Func->getContext()->getStrDump();
928 Str << "movups." << getDest()->getType() << " ";
929 dumpDest(Func);
930 Str << ", ";
931 dumpSources(Func);
932}
933
Jan Voung5cd240d2014-06-25 10:36:46 -0700934void InstX8632Movq::emit(const Cfg *Func) const {
935 Ostream &Str = Func->getContext()->getStrEmit();
936 assert(getSrcSize() == 1);
937 assert(getDest()->getType() == IceType_i64 ||
938 getDest()->getType() == IceType_f64);
939 Str << "\tmovq\t";
940 getDest()->emit(Func);
941 Str << ", ";
942 getSrc(0)->emit(Func);
943 Str << "\n";
944}
945
946void InstX8632Movq::dump(const Cfg *Func) const {
947 Ostream &Str = Func->getContext()->getStrDump();
948 Str << "movq." << getDest()->getType() << " ";
949 dumpDest(Func);
950 Str << ", ";
951 dumpSources(Func);
952}
953
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700954void InstX8632Movsx::emit(const Cfg *Func) const {
955 Ostream &Str = Func->getContext()->getStrEmit();
956 assert(getSrcSize() == 1);
957 Str << "\tmovsx\t";
958 getDest()->emit(Func);
959 Str << ", ";
960 getSrc(0)->emit(Func);
961 Str << "\n";
962}
963
964void InstX8632Movsx::dump(const Cfg *Func) const {
965 Ostream &Str = Func->getContext()->getStrDump();
966 Str << "movsx." << getDest()->getType() << "." << getSrc(0)->getType();
967 Str << " ";
968 dumpDest(Func);
969 Str << ", ";
970 dumpSources(Func);
971}
972
973void InstX8632Movzx::emit(const Cfg *Func) const {
974 Ostream &Str = Func->getContext()->getStrEmit();
975 assert(getSrcSize() == 1);
976 Str << "\tmovzx\t";
977 getDest()->emit(Func);
978 Str << ", ";
979 getSrc(0)->emit(Func);
980 Str << "\n";
981}
982
983void InstX8632Movzx::dump(const Cfg *Func) const {
984 Ostream &Str = Func->getContext()->getStrDump();
985 Str << "movzx." << getDest()->getType() << "." << getSrc(0)->getType();
986 Str << " ";
987 dumpDest(Func);
988 Str << ", ";
989 dumpSources(Func);
990}
991
992void InstX8632Fld::emit(const Cfg *Func) const {
993 Ostream &Str = Func->getContext()->getStrEmit();
994 assert(getSrcSize() == 1);
995 Type Ty = getSrc(0)->getType();
996 Variable *Var = llvm::dyn_cast<Variable>(getSrc(0));
997 if (Var && Var->hasReg()) {
998 // This is a physical xmm register, so we need to spill it to a
999 // temporary stack slot.
1000 SizeT Width = typeWidthInBytes(Ty);
1001 Str << "\tsub\tesp, " << Width << "\n";
1002 Str << "\tmov" << TypeX8632Attributes[Ty].SdSsString << "\t"
1003 << TypeX8632Attributes[Ty].WidthString << " [esp], ";
1004 Var->emit(Func);
1005 Str << "\n";
1006 Str << "\tfld\t" << TypeX8632Attributes[Ty].WidthString << " [esp]\n";
1007 Str << "\tadd\tesp, " << Width << "\n";
1008 return;
1009 }
1010 Str << "\tfld\t";
1011 getSrc(0)->emit(Func);
1012 Str << "\n";
1013}
1014
1015void InstX8632Fld::dump(const Cfg *Func) const {
1016 Ostream &Str = Func->getContext()->getStrDump();
1017 Str << "fld." << getSrc(0)->getType() << " ";
1018 dumpSources(Func);
1019}
1020
1021void InstX8632Fstp::emit(const Cfg *Func) const {
1022 Ostream &Str = Func->getContext()->getStrEmit();
1023 assert(getSrcSize() == 0);
1024 if (getDest() == NULL) {
1025 Str << "\tfstp\tst(0)\n";
1026 return;
1027 }
1028 if (!getDest()->hasReg()) {
1029 Str << "\tfstp\t";
1030 getDest()->emit(Func);
1031 Str << "\n";
1032 return;
1033 }
1034 // Dest is a physical (xmm) register, so st(0) needs to go through
1035 // memory. Hack this by creating a temporary stack slot, spilling
1036 // st(0) there, loading it into the xmm register, and deallocating
1037 // the stack slot.
1038 Type Ty = getDest()->getType();
1039 size_t Width = typeWidthInBytes(Ty);
1040 Str << "\tsub\tesp, " << Width << "\n";
1041 Str << "\tfstp\t" << TypeX8632Attributes[Ty].WidthString << " [esp]\n";
1042 Str << "\tmov" << TypeX8632Attributes[Ty].SdSsString << "\t";
1043 getDest()->emit(Func);
1044 Str << ", " << TypeX8632Attributes[Ty].WidthString << " [esp]\n";
1045 Str << "\tadd\tesp, " << Width << "\n";
1046}
1047
1048void InstX8632Fstp::dump(const Cfg *Func) const {
1049 Ostream &Str = Func->getContext()->getStrDump();
1050 dumpDest(Func);
1051 Str << " = fstp." << getDest()->getType() << ", st(0)";
1052 Str << "\n";
1053}
1054
Matt Wala83b80362014-07-16 10:21:30 -07001055template <> void InstX8632Pcmpeq::emit(const Cfg *Func) const {
1056 char buf[30];
1057 snprintf(buf, llvm::array_lengthof(buf), "pcmpeq%s",
1058 TypeX8632Attributes[getDest()->getType()].PackString);
1059 emitTwoAddress(buf, this, Func);
1060}
1061
1062template <> void InstX8632Pcmpgt::emit(const Cfg *Func) const {
1063 char buf[30];
1064 snprintf(buf, llvm::array_lengthof(buf), "pcmpgt%s",
1065 TypeX8632Attributes[getDest()->getType()].PackString);
1066 emitTwoAddress(buf, this, Func);
1067}
1068
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -07001069void InstX8632Pop::emit(const Cfg *Func) const {
1070 Ostream &Str = Func->getContext()->getStrEmit();
1071 assert(getSrcSize() == 0);
1072 Str << "\tpop\t";
1073 getDest()->emit(Func);
1074 Str << "\n";
1075}
1076
1077void InstX8632Pop::dump(const Cfg *Func) const {
1078 Ostream &Str = Func->getContext()->getStrDump();
1079 dumpDest(Func);
1080 Str << " = pop." << getDest()->getType() << " ";
1081}
1082
1083void InstX8632Push::emit(const Cfg *Func) const {
1084 Ostream &Str = Func->getContext()->getStrEmit();
1085 assert(getSrcSize() == 1);
1086 Type Ty = getSrc(0)->getType();
1087 Variable *Var = llvm::dyn_cast<Variable>(getSrc(0));
Matt Wala45a06232014-07-09 16:33:22 -07001088 if ((isVectorType(Ty) || Ty == IceType_f32 || Ty == IceType_f64) && Var &&
1089 Var->hasReg()) {
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -07001090 // The xmm registers can't be directly pushed, so we fake it by
1091 // decrementing esp and then storing to [esp].
1092 Str << "\tsub\tesp, " << typeWidthInBytes(Ty) << "\n";
1093 if (!SuppressStackAdjustment)
1094 Func->getTarget()->updateStackAdjustment(typeWidthInBytes(Ty));
Matt Wala45a06232014-07-09 16:33:22 -07001095 if (isVectorType(Ty)) {
1096 Str << "\tmovups\txmmword ptr [esp], ";
1097 } else {
1098 Str << "\tmov" << TypeX8632Attributes[Ty].SdSsString << "\t"
1099 << TypeX8632Attributes[Ty].WidthString << " [esp], ";
1100 }
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -07001101 getSrc(0)->emit(Func);
1102 Str << "\n";
1103 } else if (Ty == IceType_f64 && (!Var || !Var->hasReg())) {
1104 // A double on the stack has to be pushed as two halves. Push the
1105 // upper half followed by the lower half for little-endian. TODO:
1106 // implement.
1107 llvm_unreachable("Missing support for pushing doubles from memory");
1108 } else {
1109 Str << "\tpush\t";
1110 getSrc(0)->emit(Func);
1111 Str << "\n";
1112 if (!SuppressStackAdjustment)
1113 Func->getTarget()->updateStackAdjustment(4);
1114 }
1115}
1116
1117void InstX8632Push::dump(const Cfg *Func) const {
1118 Ostream &Str = Func->getContext()->getStrDump();
1119 Str << "push." << getSrc(0)->getType() << " ";
1120 dumpSources(Func);
1121}
1122
Matt Wala83b80362014-07-16 10:21:30 -07001123template <> void InstX8632Psll::emit(const Cfg *Func) const {
1124 assert(getDest()->getType() == IceType_v8i16 ||
1125 getDest()->getType() == IceType_v4i32);
1126 char buf[30];
1127 snprintf(buf, llvm::array_lengthof(buf), "psll%s",
1128 TypeX8632Attributes[getDest()->getType()].PackString);
1129 emitTwoAddress(buf, this, Func);
1130}
1131
1132template <> void InstX8632Psra::emit(const Cfg *Func) const {
1133 assert(getDest()->getType() == IceType_v8i16 ||
1134 getDest()->getType() == IceType_v4i32);
1135 char buf[30];
1136 snprintf(buf, llvm::array_lengthof(buf), "psra%s",
1137 TypeX8632Attributes[getDest()->getType()].PackString);
1138 emitTwoAddress(buf, this, Func);
1139}
1140
Matt Wala7fa22d82014-07-17 12:41:31 -07001141void InstX8632Pshufd::emit(const Cfg *Func) const {
1142 Ostream &Str = Func->getContext()->getStrEmit();
1143 assert(getSrcSize() == 2);
1144 Str << "\tpshufd\t";
1145 getDest()->emit(Func);
1146 Str << ", ";
1147 getSrc(0)->emit(Func);
1148 Str << ", ";
1149 getSrc(1)->emit(Func);
1150 Str << "\n";
1151}
1152
1153void InstX8632Pshufd::dump(const Cfg *Func) const {
1154 Ostream &Str = Func->getContext()->getStrDump();
1155 dumpDest(Func);
1156 Str << " = pshufd." << getDest()->getType() << " ";
1157 dumpSources(Func);
Matt Wala83b80362014-07-16 10:21:30 -07001158}
1159
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -07001160void InstX8632Ret::emit(const Cfg *Func) const {
1161 Ostream &Str = Func->getContext()->getStrEmit();
1162 Str << "\tret\n";
1163}
1164
1165void InstX8632Ret::dump(const Cfg *Func) const {
1166 Ostream &Str = Func->getContext()->getStrDump();
1167 Type Ty = (getSrcSize() == 0 ? IceType_void : getSrc(0)->getType());
1168 Str << "ret." << Ty << " ";
1169 dumpSources(Func);
1170}
1171
Matt Wala7fa22d82014-07-17 12:41:31 -07001172void InstX8632Shufps::emit(const Cfg *Func) const {
1173 Ostream &Str = Func->getContext()->getStrEmit();
1174 assert(getSrcSize() == 3);
1175 Str << "\tshufps\t";
1176 getDest()->emit(Func);
1177 Str << ", ";
1178 getSrc(1)->emit(Func);
1179 Str << ", ";
1180 getSrc(2)->emit(Func);
1181 Str << "\n";
1182}
1183
1184void InstX8632Shufps::dump(const Cfg *Func) const {
1185 Ostream &Str = Func->getContext()->getStrDump();
1186 dumpDest(Func);
1187 Str << " = shufps." << getDest()->getType() << " ";
1188 dumpSources(Func);
1189}
1190
Jan Voung5cd240d2014-06-25 10:36:46 -07001191void InstX8632Xadd::emit(const Cfg *Func) const {
1192 Ostream &Str = Func->getContext()->getStrEmit();
1193 if (Locked) {
Jan Vounga3a01a22014-07-14 10:32:41 -07001194 Str << "\tlock";
Jan Voung5cd240d2014-06-25 10:36:46 -07001195 }
Jan Vounga3a01a22014-07-14 10:32:41 -07001196 Str << "\txadd\t";
Jan Voung5cd240d2014-06-25 10:36:46 -07001197 getSrc(0)->emit(Func);
1198 Str << ", ";
1199 getSrc(1)->emit(Func);
1200 Str << "\n";
1201}
1202
1203void InstX8632Xadd::dump(const Cfg *Func) const {
1204 Ostream &Str = Func->getContext()->getStrDump();
1205 if (Locked) {
1206 Str << "lock ";
1207 }
1208 Type Ty = getSrc(0)->getType();
1209 Str << "xadd." << Ty << " ";
1210 dumpSources(Func);
1211}
1212
Jan Vounga3a01a22014-07-14 10:32:41 -07001213void InstX8632Xchg::emit(const Cfg *Func) const {
1214 Ostream &Str = Func->getContext()->getStrEmit();
1215 Str << "\txchg\t";
1216 getSrc(0)->emit(Func);
1217 Str << ", ";
1218 getSrc(1)->emit(Func);
1219 Str << "\n";
1220}
1221
1222void InstX8632Xchg::dump(const Cfg *Func) const {
1223 Ostream &Str = Func->getContext()->getStrDump();
1224 Type Ty = getSrc(0)->getType();
1225 Str << "xchg." << Ty << " ";
1226 dumpSources(Func);
1227}
1228
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -07001229void OperandX8632::dump(const Cfg *Func) const {
1230 Ostream &Str = Func->getContext()->getStrDump();
1231 Str << "<OperandX8632>";
1232}
1233
1234void OperandX8632Mem::emit(const Cfg *Func) const {
1235 Ostream &Str = Func->getContext()->getStrEmit();
1236 Str << TypeX8632Attributes[getType()].WidthString << " ";
Jan Voung3bd9f1a2014-06-18 10:50:57 -07001237 if (SegmentReg != DefaultSegment) {
1238 assert(SegmentReg >= 0 &&
1239 static_cast<size_t>(SegmentReg) < InstX8632SegmentRegNamesSize);
1240 Str << InstX8632SegmentRegNames[SegmentReg] << ":";
1241 }
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -07001242 // TODO: The following is an almost verbatim paste of dump().
1243 bool Dumped = false;
1244 Str << "[";
1245 if (Base) {
1246 Base->emit(Func);
1247 Dumped = true;
1248 }
1249 if (Index) {
1250 assert(Base);
1251 Str << "+";
1252 if (Shift > 0)
1253 Str << (1u << Shift) << "*";
1254 Index->emit(Func);
1255 Dumped = true;
1256 }
1257 // Pretty-print the Offset.
1258 bool OffsetIsZero = false;
1259 bool OffsetIsNegative = false;
1260 if (Offset == NULL) {
1261 OffsetIsZero = true;
1262 } else if (ConstantInteger *CI = llvm::dyn_cast<ConstantInteger>(Offset)) {
1263 OffsetIsZero = (CI->getValue() == 0);
1264 OffsetIsNegative = (static_cast<int64_t>(CI->getValue()) < 0);
1265 }
Jan Voung3bd9f1a2014-06-18 10:50:57 -07001266 if (Dumped) {
1267 if (!OffsetIsZero) { // Suppress if Offset is known to be 0
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -07001268 if (!OffsetIsNegative) // Suppress if Offset is known to be negative
1269 Str << "+";
Jan Voung3bd9f1a2014-06-18 10:50:57 -07001270 Offset->emit(Func);
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -07001271 }
Jan Voung3bd9f1a2014-06-18 10:50:57 -07001272 } else {
1273 // There is only the offset.
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -07001274 Offset->emit(Func);
1275 }
1276 Str << "]";
1277}
1278
1279void OperandX8632Mem::dump(const Cfg *Func) const {
1280 Ostream &Str = Func->getContext()->getStrDump();
Jan Voung3bd9f1a2014-06-18 10:50:57 -07001281 if (SegmentReg != DefaultSegment) {
1282 assert(SegmentReg >= 0 &&
1283 static_cast<size_t>(SegmentReg) < InstX8632SegmentRegNamesSize);
1284 Str << InstX8632SegmentRegNames[SegmentReg] << ":";
1285 }
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -07001286 bool Dumped = false;
1287 Str << "[";
1288 if (Base) {
1289 Base->dump(Func);
1290 Dumped = true;
1291 }
1292 if (Index) {
1293 assert(Base);
1294 Str << "+";
1295 if (Shift > 0)
1296 Str << (1u << Shift) << "*";
1297 Index->dump(Func);
1298 Dumped = true;
1299 }
1300 // Pretty-print the Offset.
1301 bool OffsetIsZero = false;
1302 bool OffsetIsNegative = false;
1303 if (Offset == NULL) {
1304 OffsetIsZero = true;
1305 } else if (ConstantInteger *CI = llvm::dyn_cast<ConstantInteger>(Offset)) {
1306 OffsetIsZero = (CI->getValue() == 0);
1307 OffsetIsNegative = (static_cast<int64_t>(CI->getValue()) < 0);
1308 }
Jan Voung3bd9f1a2014-06-18 10:50:57 -07001309 if (Dumped) {
1310 if (!OffsetIsZero) { // Suppress if Offset is known to be 0
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -07001311 if (!OffsetIsNegative) // Suppress if Offset is known to be negative
1312 Str << "+";
Jan Voung3bd9f1a2014-06-18 10:50:57 -07001313 Offset->dump(Func);
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -07001314 }
Jan Voung3bd9f1a2014-06-18 10:50:57 -07001315 } else {
1316 // There is only the offset.
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -07001317 Offset->dump(Func);
1318 }
1319 Str << "]";
1320}
1321
1322void VariableSplit::emit(const Cfg *Func) const {
1323 Ostream &Str = Func->getContext()->getStrEmit();
1324 assert(Var->getLocalUseNode() == NULL ||
1325 Var->getLocalUseNode() == Func->getCurrentNode());
1326 assert(!Var->hasReg());
1327 // The following is copied/adapted from TargetX8632::emitVariable().
1328 const TargetLowering *Target = Func->getTarget();
1329 const Type Ty = IceType_i32;
1330 Str << TypeX8632Attributes[Ty].WidthString << " ["
1331 << Target->getRegName(Target->getFrameOrStackReg(), Ty);
1332 int32_t Offset = Var->getStackOffset() + Target->getStackAdjustment();
1333 if (Part == High)
1334 Offset += 4;
1335 if (Offset) {
1336 if (Offset > 0)
1337 Str << "+";
1338 Str << Offset;
1339 }
1340 Str << "]";
1341}
1342
1343void VariableSplit::dump(const Cfg *Func) const {
1344 Ostream &Str = Func->getContext()->getStrDump();
1345 switch (Part) {
1346 case Low:
1347 Str << "low";
1348 break;
1349 case High:
1350 Str << "high";
1351 break;
1352 default:
1353 Str << "???";
1354 break;
1355 }
1356 Str << "(";
1357 Var->dump(Func);
1358 Str << ")";
1359}
1360
1361} // end of namespace Ice