blob: 8c6b99a65ff3d3dcb26428cbf9e6fcb90994a79c [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
Jan Voung8acded02014-09-22 18:02:25 -070015#include "assembler_ia32.h"
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -070016#include "IceCfg.h"
17#include "IceCfgNode.h"
Jan Voungbd385e42014-09-18 18:18:10 -070018#include "IceConditionCodesX8632.h"
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -070019#include "IceInst.h"
20#include "IceInstX8632.h"
Jan Voungbd385e42014-09-18 18:18:10 -070021#include "IceRegistersX8632.h"
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -070022#include "IceTargetLoweringX8632.h"
23#include "IceOperand.h"
24
25namespace Ice {
26
27namespace {
28
29const struct InstX8632BrAttributes_ {
Jan Voungbd385e42014-09-18 18:18:10 -070030 CondX86::BrCond Opposite;
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -070031 const char *DisplayString;
32 const char *EmitString;
33} InstX8632BrAttributes[] = {
Jan Voungbd385e42014-09-18 18:18:10 -070034#define X(tag, encode, opp, dump, emit) \
35 { CondX86::opp, dump, emit } \
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -070036 ,
37 ICEINSTX8632BR_TABLE
38#undef X
39 };
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -070040
Matt Walace0ca8f2014-07-24 12:34:20 -070041const struct InstX8632CmppsAttributes_ {
42 const char *EmitString;
43} InstX8632CmppsAttributes[] = {
44#define X(tag, emit) \
45 { emit } \
46 ,
47 ICEINSTX8632CMPPS_TABLE
48#undef X
49 };
Matt Walace0ca8f2014-07-24 12:34:20 -070050
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -070051const struct TypeX8632Attributes_ {
52 const char *CvtString; // i (integer), s (single FP), d (double FP)
53 const char *SdSsString; // ss, sd, or <blank>
Matt Wala83b80362014-07-16 10:21:30 -070054 const char *PackString; // b, w, d, or <blank>
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -070055 const char *WidthString; // {byte,word,dword,qword} ptr
56} TypeX8632Attributes[] = {
Matt Wala49889232014-07-18 12:45:09 -070057#define X(tag, elementty, cvt, sdss, pack, width) \
Matt Wala83b80362014-07-16 10:21:30 -070058 { cvt, "" sdss, pack, width } \
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -070059 ,
60 ICETYPEX8632_TABLE
61#undef X
62 };
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -070063
Jan Voung3bd9f1a2014-06-18 10:50:57 -070064const char *InstX8632SegmentRegNames[] = {
Jan Vounga3a01a22014-07-14 10:32:41 -070065#define X(val, name) name,
66 SEG_REGX8632_TABLE
Jan Voung3bd9f1a2014-06-18 10:50:57 -070067#undef X
68};
Jan Voung3bd9f1a2014-06-18 10:50:57 -070069
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -070070} // end of anonymous namespace
71
72const char *InstX8632::getWidthString(Type Ty) {
73 return TypeX8632Attributes[Ty].WidthString;
74}
75
76OperandX8632Mem::OperandX8632Mem(Cfg *Func, Type Ty, Variable *Base,
77 Constant *Offset, Variable *Index,
Jan Voung3bd9f1a2014-06-18 10:50:57 -070078 uint16_t Shift, SegmentRegisters SegmentReg)
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -070079 : OperandX8632(kMem, Ty), Base(Base), Offset(Offset), Index(Index),
Jan Voung3bd9f1a2014-06-18 10:50:57 -070080 Shift(Shift), SegmentReg(SegmentReg) {
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -070081 assert(Shift <= 3);
82 Vars = NULL;
83 NumVars = 0;
84 if (Base)
85 ++NumVars;
86 if (Index)
87 ++NumVars;
88 if (NumVars) {
89 Vars = Func->allocateArrayOf<Variable *>(NumVars);
90 SizeT I = 0;
91 if (Base)
92 Vars[I++] = Base;
93 if (Index)
94 Vars[I++] = Index;
95 assert(I == NumVars);
96 }
97}
98
Jim Stichnoth144cdce2014-09-22 16:02:59 -070099InstX8632AdjustStack::InstX8632AdjustStack(Cfg *Func, SizeT Amount,
100 Variable *Esp)
101 : InstX8632(Func, InstX8632::Adjuststack, 1, Esp), Amount(Amount) {
102 addSource(Esp);
103}
Matt Wala105b7042014-08-11 19:56:19 -0700104
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700105InstX8632Mul::InstX8632Mul(Cfg *Func, Variable *Dest, Variable *Source1,
106 Operand *Source2)
107 : InstX8632(Func, InstX8632::Mul, 2, Dest) {
108 addSource(Source1);
109 addSource(Source2);
110}
111
112InstX8632Shld::InstX8632Shld(Cfg *Func, Variable *Dest, Variable *Source1,
113 Variable *Source2)
114 : InstX8632(Func, InstX8632::Shld, 3, Dest) {
115 addSource(Dest);
116 addSource(Source1);
117 addSource(Source2);
118}
119
120InstX8632Shrd::InstX8632Shrd(Cfg *Func, Variable *Dest, Variable *Source1,
121 Variable *Source2)
122 : InstX8632(Func, InstX8632::Shrd, 3, Dest) {
123 addSource(Dest);
124 addSource(Source1);
125 addSource(Source2);
126}
127
128InstX8632Label::InstX8632Label(Cfg *Func, TargetX8632 *Target)
129 : InstX8632(Func, InstX8632::Label, 0, NULL),
130 Number(Target->makeNextLabelNumber()) {}
131
132IceString InstX8632Label::getName(const Cfg *Func) const {
133 char buf[30];
134 snprintf(buf, llvm::array_lengthof(buf), "%u", Number);
Jim Stichnoth206833c2014-08-07 10:58:05 -0700135 return ".L" + Func->getFunctionName() + "$local$__" + buf;
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700136}
137
Jim Stichnothff9c7062014-09-18 04:50:49 -0700138InstX8632Br::InstX8632Br(Cfg *Func, const CfgNode *TargetTrue,
139 const CfgNode *TargetFalse,
Jan Voungbd385e42014-09-18 18:18:10 -0700140 const InstX8632Label *Label, CondX86::BrCond Condition)
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700141 : InstX8632(Func, InstX8632::Br, 0, NULL), Condition(Condition),
142 TargetTrue(TargetTrue), TargetFalse(TargetFalse), Label(Label) {}
143
Jim Stichnothff9c7062014-09-18 04:50:49 -0700144bool InstX8632Br::optimizeBranch(const CfgNode *NextNode) {
145 // If there is no next block, then there can be no fallthrough to
146 // optimize.
147 if (NextNode == NULL)
148 return false;
149 // Intra-block conditional branches can't be optimized.
150 if (Label)
151 return false;
152 // If there is no fallthrough node, such as a non-default case label
153 // for a switch instruction, then there is no opportunity to
154 // optimize.
155 if (getTargetFalse() == NULL)
156 return false;
157
158 // Unconditional branch to the next node can be removed.
Jan Voungbd385e42014-09-18 18:18:10 -0700159 if (Condition == CondX86::Br_None && getTargetFalse() == NextNode) {
Jim Stichnothff9c7062014-09-18 04:50:49 -0700160 assert(getTargetTrue() == NULL);
161 setDeleted();
162 return true;
163 }
164 // If the fallthrough is to the next node, set fallthrough to NULL
165 // to indicate.
166 if (getTargetFalse() == NextNode) {
167 TargetFalse = NULL;
168 return true;
169 }
170 // If TargetTrue is the next node, and TargetFalse is non-NULL
171 // (which was already tested above), then invert the branch
172 // condition, swap the targets, and set new fallthrough to NULL.
173 if (getTargetTrue() == NextNode) {
Jan Voungbd385e42014-09-18 18:18:10 -0700174 assert(Condition != CondX86::Br_None);
Jim Stichnothff9c7062014-09-18 04:50:49 -0700175 Condition = InstX8632BrAttributes[Condition].Opposite;
176 TargetTrue = getTargetFalse();
177 TargetFalse = NULL;
178 return true;
179 }
180 return false;
181}
182
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700183InstX8632Call::InstX8632Call(Cfg *Func, Variable *Dest, Operand *CallTarget)
184 : InstX8632(Func, InstX8632::Call, 1, Dest) {
185 HasSideEffects = true;
186 addSource(CallTarget);
187}
188
Jan Vounge4da26f2014-07-15 17:52:39 -0700189InstX8632Cmov::InstX8632Cmov(Cfg *Func, Variable *Dest, Operand *Source,
Jan Voungbd385e42014-09-18 18:18:10 -0700190 CondX86::BrCond Condition)
Jan Vounge4da26f2014-07-15 17:52:39 -0700191 : InstX8632(Func, InstX8632::Cmov, 2, Dest), Condition(Condition) {
192 // The final result is either the original Dest, or Source, so mark
193 // both as sources.
194 addSource(Dest);
195 addSource(Source);
196}
197
Matt Walace0ca8f2014-07-24 12:34:20 -0700198InstX8632Cmpps::InstX8632Cmpps(Cfg *Func, Variable *Dest, Operand *Source,
Jan Voungbd385e42014-09-18 18:18:10 -0700199 CondX86::CmppsCond Condition)
Matt Walace0ca8f2014-07-24 12:34:20 -0700200 : InstX8632(Func, InstX8632::Cmpps, 2, Dest), Condition(Condition) {
201 addSource(Dest);
202 addSource(Source);
203}
204
Jan Vounga3a01a22014-07-14 10:32:41 -0700205InstX8632Cmpxchg::InstX8632Cmpxchg(Cfg *Func, Operand *DestOrAddr,
206 Variable *Eax, Variable *Desired,
207 bool Locked)
208 : InstX8632Lockable(Func, InstX8632::Cmpxchg, 3,
209 llvm::dyn_cast<Variable>(DestOrAddr), Locked) {
Jan Voungbd385e42014-09-18 18:18:10 -0700210 assert(Eax->getRegNum() == RegX8632::Reg_eax);
Jan Vounga3a01a22014-07-14 10:32:41 -0700211 addSource(DestOrAddr);
212 addSource(Eax);
213 addSource(Desired);
214}
215
216InstX8632Cmpxchg8b::InstX8632Cmpxchg8b(Cfg *Func, OperandX8632 *Addr,
217 Variable *Edx, Variable *Eax,
218 Variable *Ecx, Variable *Ebx,
219 bool Locked)
220 : InstX8632Lockable(Func, InstX8632::Cmpxchg, 5, NULL, Locked) {
Jan Voungbd385e42014-09-18 18:18:10 -0700221 assert(Edx->getRegNum() == RegX8632::Reg_edx);
222 assert(Eax->getRegNum() == RegX8632::Reg_eax);
223 assert(Ecx->getRegNum() == RegX8632::Reg_ecx);
224 assert(Ebx->getRegNum() == RegX8632::Reg_ebx);
Jan Vounga3a01a22014-07-14 10:32:41 -0700225 addSource(Addr);
226 addSource(Edx);
227 addSource(Eax);
228 addSource(Ecx);
229 addSource(Ebx);
230}
231
Jim Stichnothb63cd882014-09-08 10:47:23 -0700232InstX8632Cvt::InstX8632Cvt(Cfg *Func, Variable *Dest, Operand *Source,
233 bool Trunc)
234 : InstX8632(Func, InstX8632::Cvt, 1, Dest), Trunc(Trunc) {
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700235 addSource(Source);
236}
237
238InstX8632Icmp::InstX8632Icmp(Cfg *Func, Operand *Src0, Operand *Src1)
239 : InstX8632(Func, InstX8632::Icmp, 2, NULL) {
240 addSource(Src0);
241 addSource(Src1);
242}
243
244InstX8632Ucomiss::InstX8632Ucomiss(Cfg *Func, Operand *Src0, Operand *Src1)
245 : InstX8632(Func, InstX8632::Ucomiss, 2, NULL) {
246 addSource(Src0);
247 addSource(Src1);
248}
249
Jan Voung3bd9f1a2014-06-18 10:50:57 -0700250InstX8632UD2::InstX8632UD2(Cfg *Func)
251 : InstX8632(Func, InstX8632::UD2, 0, NULL) {}
252
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700253InstX8632Test::InstX8632Test(Cfg *Func, Operand *Src1, Operand *Src2)
254 : InstX8632(Func, InstX8632::Test, 2, NULL) {
255 addSource(Src1);
256 addSource(Src2);
257}
258
Jan Voung5cd240d2014-06-25 10:36:46 -0700259InstX8632Mfence::InstX8632Mfence(Cfg *Func)
260 : InstX8632(Func, InstX8632::Mfence, 0, NULL) {
261 HasSideEffects = true;
262}
263
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700264InstX8632Store::InstX8632Store(Cfg *Func, Operand *Value, OperandX8632 *Mem)
265 : InstX8632(Func, InstX8632::Store, 2, NULL) {
266 addSource(Value);
267 addSource(Mem);
268}
269
Matt Wala105b7042014-08-11 19:56:19 -0700270InstX8632StoreP::InstX8632StoreP(Cfg *Func, Operand *Value, OperandX8632 *Mem)
271 : InstX8632(Func, InstX8632::StoreP, 2, NULL) {
272 addSource(Value);
273 addSource(Mem);
274}
275
Jan Voung5cd240d2014-06-25 10:36:46 -0700276InstX8632StoreQ::InstX8632StoreQ(Cfg *Func, Operand *Value, OperandX8632 *Mem)
277 : InstX8632(Func, InstX8632::StoreQ, 2, NULL) {
278 addSource(Value);
279 addSource(Mem);
280}
281
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700282InstX8632Movsx::InstX8632Movsx(Cfg *Func, Variable *Dest, Operand *Source)
283 : InstX8632(Func, InstX8632::Movsx, 1, Dest) {
284 addSource(Source);
285}
286
287InstX8632Movzx::InstX8632Movzx(Cfg *Func, Variable *Dest, Operand *Source)
288 : InstX8632(Func, InstX8632::Movzx, 1, Dest) {
289 addSource(Source);
290}
291
Matt Walac3302742014-08-15 16:21:56 -0700292InstX8632Nop::InstX8632Nop(Cfg *Func, InstX8632Nop::NopVariant Variant)
293 : InstX8632(Func, InstX8632::Nop, 0, NULL), Variant(Variant) {}
294
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700295InstX8632Fld::InstX8632Fld(Cfg *Func, Operand *Src)
296 : InstX8632(Func, InstX8632::Fld, 1, NULL) {
297 addSource(Src);
298}
299
300InstX8632Fstp::InstX8632Fstp(Cfg *Func, Variable *Dest)
301 : InstX8632(Func, InstX8632::Fstp, 0, Dest) {}
302
303InstX8632Pop::InstX8632Pop(Cfg *Func, Variable *Dest)
304 : InstX8632(Func, InstX8632::Pop, 0, Dest) {}
305
306InstX8632Push::InstX8632Push(Cfg *Func, Operand *Source,
307 bool SuppressStackAdjustment)
308 : InstX8632(Func, InstX8632::Push, 1, NULL),
309 SuppressStackAdjustment(SuppressStackAdjustment) {
310 addSource(Source);
311}
312
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700313InstX8632Ret::InstX8632Ret(Cfg *Func, Variable *Source)
314 : InstX8632(Func, InstX8632::Ret, Source ? 1 : 0, NULL) {
315 if (Source)
316 addSource(Source);
317}
318
Jan Voung5cd240d2014-06-25 10:36:46 -0700319InstX8632Xadd::InstX8632Xadd(Cfg *Func, Operand *Dest, Variable *Source,
320 bool Locked)
Jan Vounga3a01a22014-07-14 10:32:41 -0700321 : InstX8632Lockable(Func, InstX8632::Xadd, 2,
322 llvm::dyn_cast<Variable>(Dest), Locked) {
323 addSource(Dest);
324 addSource(Source);
325}
326
327InstX8632Xchg::InstX8632Xchg(Cfg *Func, Operand *Dest, Variable *Source)
328 : InstX8632(Func, InstX8632::Xchg, 2, llvm::dyn_cast<Variable>(Dest)) {
Jan Voung5cd240d2014-06-25 10:36:46 -0700329 addSource(Dest);
330 addSource(Source);
331}
332
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700333// ======================== Dump routines ======================== //
334
Jan Voung8acded02014-09-22 18:02:25 -0700335namespace {
336
337void emitIASBytes(Ostream &Str, const x86::AssemblerX86 *Asm,
338 intptr_t StartPosition) {
339 intptr_t EndPosition = Asm->GetPosition();
340 intptr_t LastFixupLoc = -1;
341 AssemblerFixup *LastFixup = NULL;
342 if (Asm->GetLatestFixup()) {
343 LastFixup = Asm->GetLatestFixup();
344 LastFixupLoc = LastFixup->position();
345 }
346 if (LastFixupLoc < StartPosition) {
347 // The fixup doesn't apply to this current block.
348 for (intptr_t i = 0; i < EndPosition - StartPosition; ++i) {
349 Str << "\t.byte "
350 << static_cast<uint32_t>(Asm->LoadBuffer<uint8_t>(StartPosition + i))
351 << "\n";
352 }
353 return;
354 }
355 const intptr_t FixupSize = 4;
356 assert(LastFixupLoc + FixupSize <= EndPosition);
357 // The fixup does apply to this current block.
358 for (intptr_t i = 0; i < LastFixupLoc - StartPosition; ++i) {
359 Str << "\t.byte "
360 << static_cast<uint32_t>(Asm->LoadBuffer<uint8_t>(StartPosition + i))
361 << "\n";
362 }
363 Str << "\t.long " << LastFixup->value()->getName();
364 if (LastFixup->value()->getOffset()) {
365 Str << " + " << LastFixup->value()->getOffset();
366 }
367 Str << "\n";
368 for (intptr_t i = LastFixupLoc + FixupSize; i < EndPosition; ++i) {
369 Str << "\t.byte " << static_cast<uint32_t>(Asm->LoadBuffer<uint8_t>(i))
370 << "\n";
371 }
372}
373
374} // end of anonymous namespace
375
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700376void InstX8632::dump(const Cfg *Func) const {
377 Ostream &Str = Func->getContext()->getStrDump();
378 Str << "[X8632] ";
379 Inst::dump(Func);
380}
381
382void InstX8632Label::emit(const Cfg *Func) const {
383 Ostream &Str = Func->getContext()->getStrEmit();
384 Str << getName(Func) << ":\n";
385}
386
387void InstX8632Label::dump(const Cfg *Func) const {
388 Ostream &Str = Func->getContext()->getStrDump();
389 Str << getName(Func) << ":";
390}
391
392void InstX8632Br::emit(const Cfg *Func) const {
393 Ostream &Str = Func->getContext()->getStrEmit();
394 Str << "\t";
395
Jan Voungbd385e42014-09-18 18:18:10 -0700396 if (Condition == CondX86::Br_None) {
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700397 Str << "jmp";
398 } else {
399 Str << InstX8632BrAttributes[Condition].EmitString;
400 }
401
402 if (Label) {
403 Str << "\t" << Label->getName(Func) << "\n";
404 } else {
Jan Voungbd385e42014-09-18 18:18:10 -0700405 if (Condition == CondX86::Br_None) {
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700406 Str << "\t" << getTargetFalse()->getAsmName() << "\n";
407 } else {
408 Str << "\t" << getTargetTrue()->getAsmName() << "\n";
409 if (getTargetFalse()) {
410 Str << "\tjmp\t" << getTargetFalse()->getAsmName() << "\n";
411 }
412 }
413 }
414}
415
416void InstX8632Br::dump(const Cfg *Func) const {
417 Ostream &Str = Func->getContext()->getStrDump();
418 Str << "br ";
419
Jan Voungbd385e42014-09-18 18:18:10 -0700420 if (Condition == CondX86::Br_None) {
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700421 Str << "label %"
422 << (Label ? Label->getName(Func) : getTargetFalse()->getName());
423 return;
424 }
425
426 Str << InstX8632BrAttributes[Condition].DisplayString;
427 if (Label) {
428 Str << ", label %" << Label->getName(Func);
429 } else {
430 Str << ", label %" << getTargetTrue()->getName();
431 if (getTargetFalse()) {
432 Str << ", label %" << getTargetFalse()->getName();
433 }
434 }
435}
436
437void InstX8632Call::emit(const Cfg *Func) const {
438 Ostream &Str = Func->getContext()->getStrEmit();
439 assert(getSrcSize() == 1);
440 Str << "\tcall\t";
441 getCallTarget()->emit(Func);
442 Str << "\n";
443 Func->getTarget()->resetStackAdjustment();
444}
445
446void InstX8632Call::dump(const Cfg *Func) const {
447 Ostream &Str = Func->getContext()->getStrDump();
448 if (getDest()) {
449 dumpDest(Func);
450 Str << " = ";
451 }
452 Str << "call ";
453 getCallTarget()->dump(Func);
454}
455
456// The ShiftHack parameter is used to emit "cl" instead of "ecx" for
457// shift instructions, in order to be syntactically valid. The
458// Opcode parameter needs to be char* and not IceString because of
459// template issues.
460void emitTwoAddress(const char *Opcode, const Inst *Inst, const Cfg *Func,
461 bool ShiftHack) {
462 Ostream &Str = Func->getContext()->getStrEmit();
463 assert(Inst->getSrcSize() == 2);
464 assert(Inst->getDest() == Inst->getSrc(0));
465 Str << "\t" << Opcode << "\t";
466 Inst->getDest()->emit(Func);
467 Str << ", ";
468 bool EmittedSrc1 = false;
469 if (ShiftHack) {
470 Variable *ShiftReg = llvm::dyn_cast<Variable>(Inst->getSrc(1));
Jan Voungbd385e42014-09-18 18:18:10 -0700471 if (ShiftReg && ShiftReg->getRegNum() == RegX8632::Reg_ecx) {
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700472 Str << "cl";
473 EmittedSrc1 = true;
474 }
475 }
476 if (!EmittedSrc1)
477 Inst->getSrc(1)->emit(Func);
478 Str << "\n";
479}
480
Jan Voung8acded02014-09-22 18:02:25 -0700481void
482emitIASVarOperandTyXMM(const Cfg *Func, Type Ty, const Variable *Var,
483 const Operand *Src,
484 const x86::AssemblerX86::TypedXmmEmitters &Emitter) {
485 x86::AssemblerX86 *Asm = Func->getAssembler<x86::AssemblerX86>();
486 intptr_t StartPosition = Asm->GetPosition();
487 assert(Var->hasReg());
488 RegX8632::XmmRegister VarReg = RegX8632::getEncodedXmm(Var->getRegNum());
489 if (const Variable *SrcVar = llvm::dyn_cast<Variable>(Src)) {
490 if (SrcVar->hasReg()) {
491 RegX8632::XmmRegister SrcReg =
492 RegX8632::getEncodedXmm(SrcVar->getRegNum());
493 (Asm->*(Emitter.XmmXmm))(Ty, VarReg, SrcReg);
494 } else {
495 x86::Address SrcStackAddr = static_cast<TargetX8632 *>(Func->getTarget())
496 ->stackVarToAsmOperand(SrcVar);
497 (Asm->*(Emitter.XmmAddr))(Ty, VarReg, SrcStackAddr);
498 }
499 } else if (const OperandX8632Mem *Mem =
500 llvm::dyn_cast<OperandX8632Mem>(Src)) {
501 x86::Address SrcAddr = Mem->toAsmAddress(Asm);
502 (Asm->*(Emitter.XmmAddr))(Ty, VarReg, SrcAddr);
503 } else if (const Constant *Imm = llvm::dyn_cast<Constant>(Src)) {
504 (Asm->*(Emitter.XmmAddr))(
505 Ty, VarReg, x86::Address::ofConstPool(Func->getContext(), Asm, Imm));
506 } else {
507 llvm_unreachable("Unexpected operand type");
508 }
509 Ostream &Str = Func->getContext()->getStrEmit();
510 emitIASBytes(Str, Asm, StartPosition);
511}
512
Matt Walae58178a2014-08-12 13:15:04 -0700513bool checkForRedundantAssign(const Variable *Dest, const Operand *Source) {
514 const Variable *Src = llvm::dyn_cast<const Variable>(Source);
515 if (Src == NULL)
516 return false;
517 if (Dest->hasReg() && Dest->getRegNum() == Src->getRegNum()) {
518 // TODO: On x86-64, instructions like "mov eax, eax" are used to
519 // clear the upper 32 bits of rax. We need to recognize and
520 // preserve these.
521 return true;
522 }
523 if (!Dest->hasReg() && !Src->hasReg() &&
524 Dest->getStackOffset() == Src->getStackOffset())
525 return true;
526 return false;
527}
Matt Wala49889232014-07-18 12:45:09 -0700528
Jan Voung7fa813b2014-07-18 13:01:08 -0700529// In-place ops
530template <> const char *InstX8632Bswap::Opcode = "bswap";
531template <> const char *InstX8632Neg::Opcode = "neg";
Matt Wala49889232014-07-18 12:45:09 -0700532// Unary ops
Jan Vounge4da26f2014-07-15 17:52:39 -0700533template <> const char *InstX8632Bsf::Opcode = "bsf";
534template <> const char *InstX8632Bsr::Opcode = "bsr";
Matt Wala49889232014-07-18 12:45:09 -0700535template <> const char *InstX8632Lea::Opcode = "lea";
536template <> const char *InstX8632Movd::Opcode = "movd";
Jan Vounge4da26f2014-07-15 17:52:39 -0700537template <> const char *InstX8632Sqrtss::Opcode = "sqrtss";
Matt Wala51e8cfb2014-08-08 08:39:40 -0700538template <> const char *InstX8632Cbwdq::Opcode = "cbw/cwd/cdq";
Matt Walae58178a2014-08-12 13:15:04 -0700539// Mov-like ops
540template <> const char *InstX8632Mov::Opcode = "mov";
541template <> const char *InstX8632Movp::Opcode = "movups";
542template <> const char *InstX8632Movq::Opcode = "movq";
Matt Wala49889232014-07-18 12:45:09 -0700543// Binary ops
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700544template <> const char *InstX8632Add::Opcode = "add";
Matt Wala8d1072e2014-07-11 15:43:51 -0700545template <> const char *InstX8632Addps::Opcode = "addps";
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700546template <> const char *InstX8632Adc::Opcode = "adc";
547template <> const char *InstX8632Addss::Opcode = "addss";
Matt Wala7fa22d82014-07-17 12:41:31 -0700548template <> const char *InstX8632Padd::Opcode = "padd";
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700549template <> const char *InstX8632Sub::Opcode = "sub";
Matt Wala8d1072e2014-07-11 15:43:51 -0700550template <> const char *InstX8632Subps::Opcode = "subps";
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700551template <> const char *InstX8632Subss::Opcode = "subss";
552template <> const char *InstX8632Sbb::Opcode = "sbb";
Matt Wala7fa22d82014-07-17 12:41:31 -0700553template <> const char *InstX8632Psub::Opcode = "psub";
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700554template <> const char *InstX8632And::Opcode = "and";
Matt Wala83b80362014-07-16 10:21:30 -0700555template <> const char *InstX8632Pand::Opcode = "pand";
Matt Wala9cb61e22014-07-24 09:44:42 -0700556template <> const char *InstX8632Pandn::Opcode = "pandn";
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700557template <> const char *InstX8632Or::Opcode = "or";
Matt Wala7fa22d82014-07-17 12:41:31 -0700558template <> const char *InstX8632Por::Opcode = "por";
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700559template <> const char *InstX8632Xor::Opcode = "xor";
Matt Wala928f1292014-07-07 16:50:46 -0700560template <> const char *InstX8632Pxor::Opcode = "pxor";
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700561template <> const char *InstX8632Imul::Opcode = "imul";
Matt Wala8d1072e2014-07-11 15:43:51 -0700562template <> const char *InstX8632Mulps::Opcode = "mulps";
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700563template <> const char *InstX8632Mulss::Opcode = "mulss";
Matt Wala0a450512014-07-30 12:44:39 -0700564template <> const char *InstX8632Pmull::Opcode = "pmull";
Matt Wala7fa22d82014-07-17 12:41:31 -0700565template <> const char *InstX8632Pmuludq::Opcode = "pmuludq";
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700566template <> const char *InstX8632Div::Opcode = "div";
Matt Wala8d1072e2014-07-11 15:43:51 -0700567template <> const char *InstX8632Divps::Opcode = "divps";
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700568template <> const char *InstX8632Idiv::Opcode = "idiv";
569template <> const char *InstX8632Divss::Opcode = "divss";
Jan Voung7fa813b2014-07-18 13:01:08 -0700570template <> const char *InstX8632Rol::Opcode = "rol";
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700571template <> const char *InstX8632Shl::Opcode = "shl";
Matt Wala83b80362014-07-16 10:21:30 -0700572template <> const char *InstX8632Psll::Opcode = "psll";
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700573template <> const char *InstX8632Shr::Opcode = "shr";
574template <> const char *InstX8632Sar::Opcode = "sar";
Matt Wala83b80362014-07-16 10:21:30 -0700575template <> const char *InstX8632Psra::Opcode = "psra";
576template <> const char *InstX8632Pcmpeq::Opcode = "pcmpeq";
577template <> const char *InstX8632Pcmpgt::Opcode = "pcmpgt";
Matt Walacfe51462014-07-25 15:57:56 -0700578template <> const char *InstX8632Movss::Opcode = "movss";
Matt Wala49889232014-07-18 12:45:09 -0700579// Ternary ops
Matt Wala0a450512014-07-30 12:44:39 -0700580template <> const char *InstX8632Insertps::Opcode = "insertps";
Matt Wala49889232014-07-18 12:45:09 -0700581template <> const char *InstX8632Shufps::Opcode = "shufps";
Matt Wala0a450512014-07-30 12:44:39 -0700582template <> const char *InstX8632Pinsr::Opcode = "pinsr";
583template <> const char *InstX8632Blendvps::Opcode = "blendvps";
584template <> const char *InstX8632Pblendvb::Opcode = "pblendvb";
Matt Wala49889232014-07-18 12:45:09 -0700585// Three address ops
Matt Wala0a450512014-07-30 12:44:39 -0700586template <> const char *InstX8632Pextr::Opcode = "pextr";
Matt Wala49889232014-07-18 12:45:09 -0700587template <> const char *InstX8632Pshufd::Opcode = "pshufd";
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700588
Jan Voung8acded02014-09-22 18:02:25 -0700589// Binary XMM ops
590template <>
591const x86::AssemblerX86::TypedXmmEmitters InstX8632Addss::Emitter = {
592 &x86::AssemblerX86::addss, &x86::AssemblerX86::addss, NULL};
593template <>
594const x86::AssemblerX86::TypedXmmEmitters InstX8632Addps::Emitter = {
595 &x86::AssemblerX86::addps, &x86::AssemblerX86::addps, NULL};
596template <>
597const x86::AssemblerX86::TypedXmmEmitters InstX8632Divss::Emitter = {
598 &x86::AssemblerX86::divss, &x86::AssemblerX86::divss, NULL};
599template <>
600const x86::AssemblerX86::TypedXmmEmitters InstX8632Divps::Emitter = {
601 &x86::AssemblerX86::divps, &x86::AssemblerX86::divps, NULL};
602template <>
603const x86::AssemblerX86::TypedXmmEmitters InstX8632Mulss::Emitter = {
604 &x86::AssemblerX86::mulss, &x86::AssemblerX86::mulss, NULL};
605template <>
606const x86::AssemblerX86::TypedXmmEmitters InstX8632Mulps::Emitter = {
607 &x86::AssemblerX86::mulps, &x86::AssemblerX86::mulps, NULL};
608template <>
609const x86::AssemblerX86::TypedXmmEmitters InstX8632Padd::Emitter = {
610 &x86::AssemblerX86::padd, &x86::AssemblerX86::padd, NULL};
611template <>
612const x86::AssemblerX86::TypedXmmEmitters InstX8632Pand::Emitter = {
613 &x86::AssemblerX86::pand, &x86::AssemblerX86::pand, NULL};
614template <>
615const x86::AssemblerX86::TypedXmmEmitters InstX8632Pandn::Emitter = {
616 &x86::AssemblerX86::pandn, &x86::AssemblerX86::pandn, NULL};
617template <>
618const x86::AssemblerX86::TypedXmmEmitters InstX8632Pmuludq::Emitter = {
619 &x86::AssemblerX86::pmuludq, &x86::AssemblerX86::pmuludq, NULL};
620template <>
621const x86::AssemblerX86::TypedXmmEmitters InstX8632Por::Emitter = {
622 &x86::AssemblerX86::por, &x86::AssemblerX86::por, NULL};
623template <>
624const x86::AssemblerX86::TypedXmmEmitters InstX8632Psub::Emitter = {
625 &x86::AssemblerX86::psub, &x86::AssemblerX86::psub, NULL};
626template <>
627const x86::AssemblerX86::TypedXmmEmitters InstX8632Pxor::Emitter = {
628 &x86::AssemblerX86::pxor, &x86::AssemblerX86::pxor, NULL};
629template <>
630const x86::AssemblerX86::TypedXmmEmitters InstX8632Sqrtss::Emitter = {
631 &x86::AssemblerX86::sqrtss, &x86::AssemblerX86::sqrtss, NULL};
632template <>
633const x86::AssemblerX86::TypedXmmEmitters InstX8632Subss::Emitter = {
634 &x86::AssemblerX86::subss, &x86::AssemblerX86::subss, NULL};
635template <>
636const x86::AssemblerX86::TypedXmmEmitters InstX8632Subps::Emitter = {
637 &x86::AssemblerX86::subps, &x86::AssemblerX86::subps, NULL};
638
Jan Vounge4da26f2014-07-15 17:52:39 -0700639template <> void InstX8632Sqrtss::emit(const Cfg *Func) const {
640 Ostream &Str = Func->getContext()->getStrEmit();
641 assert(getSrcSize() == 1);
642 Type Ty = getSrc(0)->getType();
643 assert(Ty == IceType_f32 || Ty == IceType_f64);
644 Str << "\tsqrt" << TypeX8632Attributes[Ty].SdSsString << "\t";
645 getDest()->emit(Func);
646 Str << ", ";
647 getSrc(0)->emit(Func);
648 Str << "\n";
649}
650
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700651template <> void InstX8632Addss::emit(const Cfg *Func) const {
652 char buf[30];
653 snprintf(buf, llvm::array_lengthof(buf), "add%s",
654 TypeX8632Attributes[getDest()->getType()].SdSsString);
655 emitTwoAddress(buf, this, Func);
656}
657
Matt Wala7fa22d82014-07-17 12:41:31 -0700658template <> void InstX8632Padd::emit(const Cfg *Func) const {
659 char buf[30];
660 snprintf(buf, llvm::array_lengthof(buf), "padd%s",
661 TypeX8632Attributes[getDest()->getType()].PackString);
662 emitTwoAddress(buf, this, Func);
663}
664
Matt Wala0a450512014-07-30 12:44:39 -0700665template <> void InstX8632Pmull::emit(const Cfg *Func) const {
666 char buf[30];
667 bool TypesAreValid = getDest()->getType() == IceType_v4i32 ||
668 getDest()->getType() == IceType_v8i16;
669 bool InstructionSetIsValid =
670 getDest()->getType() == IceType_v8i16 ||
671 static_cast<TargetX8632 *>(Func->getTarget())->getInstructionSet() >=
672 TargetX8632::SSE4_1;
673 (void)TypesAreValid;
674 (void)InstructionSetIsValid;
675 assert(TypesAreValid);
676 assert(InstructionSetIsValid);
677 snprintf(buf, llvm::array_lengthof(buf), "pmull%s",
678 TypeX8632Attributes[getDest()->getType()].PackString);
679 emitTwoAddress(buf, this, Func);
680}
681
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700682template <> void InstX8632Subss::emit(const Cfg *Func) const {
683 char buf[30];
684 snprintf(buf, llvm::array_lengthof(buf), "sub%s",
685 TypeX8632Attributes[getDest()->getType()].SdSsString);
686 emitTwoAddress(buf, this, Func);
687}
688
Matt Wala7fa22d82014-07-17 12:41:31 -0700689template <> void InstX8632Psub::emit(const Cfg *Func) const {
690 char buf[30];
691 snprintf(buf, llvm::array_lengthof(buf), "psub%s",
692 TypeX8632Attributes[getDest()->getType()].PackString);
693 emitTwoAddress(buf, this, Func);
694}
695
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700696template <> void InstX8632Mulss::emit(const Cfg *Func) const {
697 char buf[30];
698 snprintf(buf, llvm::array_lengthof(buf), "mul%s",
699 TypeX8632Attributes[getDest()->getType()].SdSsString);
700 emitTwoAddress(buf, this, Func);
701}
702
Matt Wala7fa22d82014-07-17 12:41:31 -0700703template <> void InstX8632Pmuludq::emit(const Cfg *Func) const {
704 assert(getSrc(0)->getType() == IceType_v4i32 &&
705 getSrc(1)->getType() == IceType_v4i32);
706 emitTwoAddress(Opcode, this, Func);
707}
708
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700709template <> void InstX8632Divss::emit(const Cfg *Func) const {
710 char buf[30];
711 snprintf(buf, llvm::array_lengthof(buf), "div%s",
712 TypeX8632Attributes[getDest()->getType()].SdSsString);
713 emitTwoAddress(buf, this, Func);
714}
715
Matt Wala49889232014-07-18 12:45:09 -0700716template <> void InstX8632Div::emit(const Cfg *Func) const {
717 Ostream &Str = Func->getContext()->getStrEmit();
718 assert(getSrcSize() == 3);
719 Str << "\t" << Opcode << "\t";
720 getSrc(1)->emit(Func);
721 Str << "\n";
722}
723
724template <> void InstX8632Idiv::emit(const Cfg *Func) const {
725 Ostream &Str = Func->getContext()->getStrEmit();
726 assert(getSrcSize() == 3);
727 Str << "\t" << Opcode << "\t";
728 getSrc(1)->emit(Func);
729 Str << "\n";
730}
731
Matt Wala0a450512014-07-30 12:44:39 -0700732
733namespace {
734
735// pblendvb and blendvps take xmm0 as a final implicit argument.
736void emitVariableBlendInst(const char *Opcode, const Inst *Inst,
737 const Cfg *Func) {
738 Ostream &Str = Func->getContext()->getStrEmit();
739 assert(Inst->getSrcSize() == 3);
740 assert(llvm::isa<Variable>(Inst->getSrc(2)));
741 assert(llvm::cast<Variable>(Inst->getSrc(2))->getRegNum() ==
Jan Voungbd385e42014-09-18 18:18:10 -0700742 RegX8632::Reg_xmm0);
Matt Wala0a450512014-07-30 12:44:39 -0700743 Str << "\t" << Opcode << "\t";
744 Inst->getDest()->emit(Func);
745 Str << ", ";
746 Inst->getSrc(1)->emit(Func);
747 Str << "\n";
748}
749
750} // end anonymous namespace
751
752template <> void InstX8632Blendvps::emit(const Cfg *Func) const {
753 assert(static_cast<TargetX8632 *>(Func->getTarget())->getInstructionSet() >=
754 TargetX8632::SSE4_1);
755 emitVariableBlendInst(Opcode, this, Func);
756}
757
758template <> void InstX8632Pblendvb::emit(const Cfg *Func) const {
759 assert(static_cast<TargetX8632 *>(Func->getTarget())->getInstructionSet() >=
760 TargetX8632::SSE4_1);
761 emitVariableBlendInst(Opcode, this, Func);
762}
763
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700764template <> void InstX8632Imul::emit(const Cfg *Func) const {
765 Ostream &Str = Func->getContext()->getStrEmit();
766 assert(getSrcSize() == 2);
767 if (getDest()->getType() == IceType_i8) {
768 // The 8-bit version of imul only allows the form "imul r/m8".
769 Variable *Src0 = llvm::dyn_cast<Variable>(getSrc(0));
Jim Stichnoth6e992142014-07-30 14:45:20 -0700770 (void)Src0;
Jan Voungbd385e42014-09-18 18:18:10 -0700771 assert(Src0 && Src0->getRegNum() == RegX8632::Reg_eax);
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700772 Str << "\timul\t";
773 getSrc(1)->emit(Func);
774 Str << "\n";
775 } else if (llvm::isa<Constant>(getSrc(1))) {
776 Str << "\timul\t";
777 getDest()->emit(Func);
778 Str << ", ";
779 getSrc(0)->emit(Func);
780 Str << ", ";
781 getSrc(1)->emit(Func);
782 Str << "\n";
783 } else {
784 emitTwoAddress("imul", this, Func);
785 }
786}
787
Matt Wala51e8cfb2014-08-08 08:39:40 -0700788template <> void InstX8632Cbwdq::emit(const Cfg *Func) const {
789 Ostream &Str = Func->getContext()->getStrEmit();
790 assert(getSrcSize() == 1);
791 Operand *Src0 = getSrc(0);
792 assert(llvm::isa<Variable>(Src0));
Jan Voungbd385e42014-09-18 18:18:10 -0700793 assert(llvm::cast<Variable>(Src0)->getRegNum() == RegX8632::Reg_eax);
Matt Wala51e8cfb2014-08-08 08:39:40 -0700794 switch (Src0->getType()) {
795 default:
796 llvm_unreachable("unexpected source type!");
797 break;
798 case IceType_i8:
Jan Voungbd385e42014-09-18 18:18:10 -0700799 assert(getDest()->getRegNum() == RegX8632::Reg_eax);
Matt Wala51e8cfb2014-08-08 08:39:40 -0700800 Str << "\tcbw\n";
801 break;
802 case IceType_i16:
Jan Voungbd385e42014-09-18 18:18:10 -0700803 assert(getDest()->getRegNum() == RegX8632::Reg_edx);
Matt Wala51e8cfb2014-08-08 08:39:40 -0700804 Str << "\tcwd\n";
805 break;
806 case IceType_i32:
Jan Voungbd385e42014-09-18 18:18:10 -0700807 assert(getDest()->getRegNum() == RegX8632::Reg_edx);
Matt Wala51e8cfb2014-08-08 08:39:40 -0700808 Str << "\tcdq\n";
809 break;
810 }
811}
812
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700813void InstX8632Mul::emit(const Cfg *Func) const {
814 Ostream &Str = Func->getContext()->getStrEmit();
815 assert(getSrcSize() == 2);
816 assert(llvm::isa<Variable>(getSrc(0)));
Jan Voungbd385e42014-09-18 18:18:10 -0700817 assert(llvm::dyn_cast<Variable>(getSrc(0))->getRegNum() == RegX8632::Reg_eax);
818 assert(getDest()->getRegNum() == RegX8632::Reg_eax); // TODO: allow edx?
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700819 Str << "\tmul\t";
820 getSrc(1)->emit(Func);
821 Str << "\n";
822}
823
824void InstX8632Mul::dump(const Cfg *Func) const {
825 Ostream &Str = Func->getContext()->getStrDump();
826 dumpDest(Func);
827 Str << " = mul." << getDest()->getType() << " ";
828 dumpSources(Func);
829}
830
831void InstX8632Shld::emit(const Cfg *Func) const {
832 Ostream &Str = Func->getContext()->getStrEmit();
833 assert(getSrcSize() == 3);
834 assert(getDest() == getSrc(0));
835 Str << "\tshld\t";
836 getDest()->emit(Func);
837 Str << ", ";
838 getSrc(1)->emit(Func);
839 Str << ", ";
840 if (Variable *ShiftReg = llvm::dyn_cast<Variable>(getSrc(2))) {
Jim Stichnoth6e992142014-07-30 14:45:20 -0700841 (void)ShiftReg;
Jan Voungbd385e42014-09-18 18:18:10 -0700842 assert(ShiftReg->getRegNum() == RegX8632::Reg_ecx);
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700843 Str << "cl";
844 } else {
845 getSrc(2)->emit(Func);
846 }
847 Str << "\n";
848}
849
850void InstX8632Shld::dump(const Cfg *Func) const {
851 Ostream &Str = Func->getContext()->getStrDump();
852 dumpDest(Func);
853 Str << " = shld." << getDest()->getType() << " ";
854 dumpSources(Func);
855}
856
857void InstX8632Shrd::emit(const Cfg *Func) const {
858 Ostream &Str = Func->getContext()->getStrEmit();
859 assert(getSrcSize() == 3);
860 assert(getDest() == getSrc(0));
861 Str << "\tshrd\t";
862 getDest()->emit(Func);
863 Str << ", ";
864 getSrc(1)->emit(Func);
865 Str << ", ";
866 if (Variable *ShiftReg = llvm::dyn_cast<Variable>(getSrc(2))) {
Jim Stichnoth6e992142014-07-30 14:45:20 -0700867 (void)ShiftReg;
Jan Voungbd385e42014-09-18 18:18:10 -0700868 assert(ShiftReg->getRegNum() == RegX8632::Reg_ecx);
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700869 Str << "cl";
870 } else {
871 getSrc(2)->emit(Func);
872 }
873 Str << "\n";
874}
875
876void InstX8632Shrd::dump(const Cfg *Func) const {
877 Ostream &Str = Func->getContext()->getStrDump();
878 dumpDest(Func);
879 Str << " = shrd." << getDest()->getType() << " ";
880 dumpSources(Func);
881}
882
Jan Vounge4da26f2014-07-15 17:52:39 -0700883void InstX8632Cmov::emit(const Cfg *Func) const {
884 Ostream &Str = Func->getContext()->getStrEmit();
885 Str << "\t";
Jan Voungbd385e42014-09-18 18:18:10 -0700886 assert(Condition != CondX86::Br_None);
Jan Vounge4da26f2014-07-15 17:52:39 -0700887 assert(getDest()->hasReg());
888 Str << "cmov" << InstX8632BrAttributes[Condition].DisplayString << "\t";
889 getDest()->emit(Func);
890 Str << ", ";
891 getSrc(1)->emit(Func);
892 Str << "\n";
893}
894
895void InstX8632Cmov::dump(const Cfg *Func) const {
896 Ostream &Str = Func->getContext()->getStrDump();
897 Str << "cmov" << InstX8632BrAttributes[Condition].DisplayString << ".";
898 Str << getDest()->getType() << " ";
899 dumpDest(Func);
900 Str << ", ";
901 dumpSources(Func);
902}
903
Matt Walace0ca8f2014-07-24 12:34:20 -0700904void InstX8632Cmpps::emit(const Cfg *Func) const {
905 Ostream &Str = Func->getContext()->getStrEmit();
906 assert(getSrcSize() == 2);
Jan Voungbd385e42014-09-18 18:18:10 -0700907 assert(Condition < CondX86::Cmpps_Invalid);
Matt Walace0ca8f2014-07-24 12:34:20 -0700908 Str << "\t";
909 Str << "cmp" << InstX8632CmppsAttributes[Condition].EmitString << "ps"
910 << "\t";
911 getDest()->emit(Func);
912 Str << ", ";
913 getSrc(1)->emit(Func);
914 Str << "\n";
915}
916
Jan Voung8acded02014-09-22 18:02:25 -0700917void InstX8632Cmpps::emitIAS(const Cfg *Func) const {
918 Ostream &Str = Func->getContext()->getStrEmit();
919 x86::AssemblerX86 *Asm = Func->getAssembler<x86::AssemblerX86>();
920 intptr_t StartPosition = Asm->GetPosition();
921 assert(getSrcSize() == 2);
922 assert(Condition < CondX86::Cmpps_Invalid);
923 // Assuming there isn't any load folding for cmpps, and vector constants
924 // are not allowed in PNaCl.
925 assert(llvm::isa<Variable>(getSrc(1)));
926 const Variable *SrcVar = llvm::cast<Variable>(getSrc(1));
927 if (SrcVar->hasReg()) {
928 Asm->cmpps(RegX8632::getEncodedXmm(getDest()->getRegNum()),
929 RegX8632::getEncodedXmm(SrcVar->getRegNum()), Condition);
930 } else {
931 x86::Address SrcStackAddr = static_cast<TargetX8632 *>(Func->getTarget())
932 ->stackVarToAsmOperand(SrcVar);
933 Asm->cmpps(RegX8632::getEncodedXmm(getDest()->getRegNum()), SrcStackAddr,
934 Condition);
935 }
936 emitIASBytes(Str, Asm, StartPosition);
937}
938
Matt Walace0ca8f2014-07-24 12:34:20 -0700939void InstX8632Cmpps::dump(const Cfg *Func) const {
940 Ostream &Str = Func->getContext()->getStrDump();
Jan Voungbd385e42014-09-18 18:18:10 -0700941 assert(Condition < CondX86::Cmpps_Invalid);
Matt Walace0ca8f2014-07-24 12:34:20 -0700942 dumpDest(Func);
943 Str << " = cmp" << InstX8632CmppsAttributes[Condition].EmitString << "ps"
944 << "\t";
945 dumpSources(Func);
946}
947
Jan Vounga3a01a22014-07-14 10:32:41 -0700948void InstX8632Cmpxchg::emit(const Cfg *Func) const {
949 Ostream &Str = Func->getContext()->getStrEmit();
950 assert(getSrcSize() == 3);
951 if (Locked) {
952 Str << "\tlock";
953 }
954 Str << "\tcmpxchg\t";
955 getSrc(0)->emit(Func);
956 Str << ", ";
957 getSrc(2)->emit(Func);
958 Str << "\n";
959}
960
961void InstX8632Cmpxchg::dump(const Cfg *Func) const {
962 Ostream &Str = Func->getContext()->getStrDump();
963 if (Locked) {
964 Str << "lock ";
965 }
966 Str << "cmpxchg." << getSrc(0)->getType() << " ";
967 dumpSources(Func);
968}
969
970void InstX8632Cmpxchg8b::emit(const Cfg *Func) const {
971 Ostream &Str = Func->getContext()->getStrEmit();
972 assert(getSrcSize() == 5);
973 if (Locked) {
974 Str << "\tlock";
975 }
976 Str << "\tcmpxchg8b\t";
977 getSrc(0)->emit(Func);
978 Str << "\n";
979}
980
981void InstX8632Cmpxchg8b::dump(const Cfg *Func) const {
982 Ostream &Str = Func->getContext()->getStrDump();
983 if (Locked) {
984 Str << "lock ";
985 }
986 Str << "cmpxchg8b ";
987 dumpSources(Func);
988}
989
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700990void InstX8632Cvt::emit(const Cfg *Func) const {
991 Ostream &Str = Func->getContext()->getStrEmit();
992 assert(getSrcSize() == 1);
Jim Stichnothb63cd882014-09-08 10:47:23 -0700993 Str << "\tcvt";
994 if (Trunc)
995 Str << "t";
996 Str << TypeX8632Attributes[getSrc(0)->getType()].CvtString << "2"
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700997 << TypeX8632Attributes[getDest()->getType()].CvtString << "\t";
998 getDest()->emit(Func);
999 Str << ", ";
1000 getSrc(0)->emit(Func);
1001 Str << "\n";
1002}
1003
1004void InstX8632Cvt::dump(const Cfg *Func) const {
1005 Ostream &Str = Func->getContext()->getStrDump();
1006 dumpDest(Func);
Jim Stichnothb63cd882014-09-08 10:47:23 -07001007 Str << " = cvt";
1008 if (Trunc)
1009 Str << "t";
1010 Str << TypeX8632Attributes[getSrc(0)->getType()].CvtString << "2"
1011 << TypeX8632Attributes[getDest()->getType()].CvtString << " ";
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -07001012 dumpSources(Func);
1013}
1014
1015void InstX8632Icmp::emit(const Cfg *Func) const {
1016 Ostream &Str = Func->getContext()->getStrEmit();
1017 assert(getSrcSize() == 2);
1018 Str << "\tcmp\t";
1019 getSrc(0)->emit(Func);
1020 Str << ", ";
1021 getSrc(1)->emit(Func);
1022 Str << "\n";
1023}
1024
1025void InstX8632Icmp::dump(const Cfg *Func) const {
1026 Ostream &Str = Func->getContext()->getStrDump();
1027 Str << "cmp." << getSrc(0)->getType() << " ";
1028 dumpSources(Func);
1029}
1030
1031void InstX8632Ucomiss::emit(const Cfg *Func) const {
1032 Ostream &Str = Func->getContext()->getStrEmit();
1033 assert(getSrcSize() == 2);
1034 Str << "\tucomi" << TypeX8632Attributes[getSrc(0)->getType()].SdSsString
1035 << "\t";
1036 getSrc(0)->emit(Func);
1037 Str << ", ";
1038 getSrc(1)->emit(Func);
1039 Str << "\n";
1040}
1041
Jan Voung8acded02014-09-22 18:02:25 -07001042void InstX8632Ucomiss::emitIAS(const Cfg *Func) const {
1043 assert(getSrcSize() == 2);
1044 // Currently src0 is always a variable by convention, to avoid having
1045 // two memory operands.
1046 assert(llvm::isa<Variable>(getSrc(0)));
1047 const Variable *Src0 = llvm::cast<Variable>(getSrc(0));
1048 Type Ty = Src0->getType();
1049 const static x86::AssemblerX86::TypedXmmEmitters Emitter = {
1050 &x86::AssemblerX86::ucomiss, &x86::AssemblerX86::ucomiss, NULL};
1051 emitIASVarOperandTyXMM(Func, Ty, Src0, getSrc(1), Emitter);
1052}
1053
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -07001054void InstX8632Ucomiss::dump(const Cfg *Func) const {
1055 Ostream &Str = Func->getContext()->getStrDump();
1056 Str << "ucomiss." << getSrc(0)->getType() << " ";
1057 dumpSources(Func);
1058}
1059
Jan Voung3bd9f1a2014-06-18 10:50:57 -07001060void InstX8632UD2::emit(const Cfg *Func) const {
1061 Ostream &Str = Func->getContext()->getStrEmit();
1062 assert(getSrcSize() == 0);
1063 Str << "\tud2\n";
1064}
1065
1066void InstX8632UD2::dump(const Cfg *Func) const {
1067 Ostream &Str = Func->getContext()->getStrDump();
1068 Str << "ud2\n";
1069}
1070
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -07001071void InstX8632Test::emit(const Cfg *Func) const {
1072 Ostream &Str = Func->getContext()->getStrEmit();
1073 assert(getSrcSize() == 2);
1074 Str << "\ttest\t";
1075 getSrc(0)->emit(Func);
1076 Str << ", ";
1077 getSrc(1)->emit(Func);
1078 Str << "\n";
1079}
1080
1081void InstX8632Test::dump(const Cfg *Func) const {
1082 Ostream &Str = Func->getContext()->getStrDump();
1083 Str << "test." << getSrc(0)->getType() << " ";
1084 dumpSources(Func);
1085}
1086
Jan Voung5cd240d2014-06-25 10:36:46 -07001087void InstX8632Mfence::emit(const Cfg *Func) const {
1088 Ostream &Str = Func->getContext()->getStrEmit();
1089 assert(getSrcSize() == 0);
1090 Str << "\tmfence\n";
1091}
1092
1093void InstX8632Mfence::dump(const Cfg *Func) const {
1094 Ostream &Str = Func->getContext()->getStrDump();
1095 Str << "mfence\n";
1096}
1097
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -07001098void InstX8632Store::emit(const Cfg *Func) const {
1099 Ostream &Str = Func->getContext()->getStrEmit();
1100 assert(getSrcSize() == 2);
Jan Voung5a13f452014-06-18 10:42:02 -07001101 Str << "\tmov" << TypeX8632Attributes[getSrc(0)->getType()].SdSsString
1102 << "\t";
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -07001103 getSrc(1)->emit(Func);
1104 Str << ", ";
1105 getSrc(0)->emit(Func);
1106 Str << "\n";
1107}
1108
1109void InstX8632Store::dump(const Cfg *Func) const {
1110 Ostream &Str = Func->getContext()->getStrDump();
1111 Str << "mov." << getSrc(0)->getType() << " ";
1112 getSrc(1)->dump(Func);
1113 Str << ", ";
1114 getSrc(0)->dump(Func);
1115}
1116
Matt Wala105b7042014-08-11 19:56:19 -07001117void InstX8632StoreP::emit(const Cfg *Func) const {
1118 Ostream &Str = Func->getContext()->getStrEmit();
1119 assert(getSrcSize() == 2);
1120 Str << "\tmovups\t";
1121 getSrc(1)->emit(Func);
1122 Str << ", ";
1123 getSrc(0)->emit(Func);
1124 Str << "\n";
1125}
1126
1127void InstX8632StoreP::dump(const Cfg *Func) const {
1128 Ostream &Str = Func->getContext()->getStrDump();
1129 Str << "storep." << getSrc(0)->getType() << " ";
1130 getSrc(1)->dump(Func);
1131 Str << ", ";
1132 getSrc(0)->dump(Func);
1133}
1134
Jan Voung5cd240d2014-06-25 10:36:46 -07001135void InstX8632StoreQ::emit(const Cfg *Func) const {
1136 Ostream &Str = Func->getContext()->getStrEmit();
1137 assert(getSrcSize() == 2);
1138 assert(getSrc(1)->getType() == IceType_i64 ||
1139 getSrc(1)->getType() == IceType_f64);
1140 Str << "\tmovq\t";
1141 getSrc(1)->emit(Func);
1142 Str << ", ";
1143 getSrc(0)->emit(Func);
1144 Str << "\n";
1145}
1146
1147void InstX8632StoreQ::dump(const Cfg *Func) const {
1148 Ostream &Str = Func->getContext()->getStrDump();
1149 Str << "storeq." << getSrc(0)->getType() << " ";
1150 getSrc(1)->dump(Func);
1151 Str << ", ";
1152 getSrc(0)->dump(Func);
1153}
1154
Matt Wala49889232014-07-18 12:45:09 -07001155template <> void InstX8632Lea::emit(const Cfg *Func) const {
1156 Ostream &Str = Func->getContext()->getStrEmit();
1157 assert(getSrcSize() == 1);
1158 assert(getDest()->hasReg());
1159 Str << "\tlea\t";
1160 getDest()->emit(Func);
1161 Str << ", ";
1162 Operand *Src0 = getSrc(0);
1163 if (Variable *VSrc0 = llvm::dyn_cast<Variable>(Src0)) {
1164 Type Ty = VSrc0->getType();
1165 // lea on x86-32 doesn't accept mem128 operands, so cast VSrc0 to an
1166 // acceptable type.
1167 VSrc0->asType(isVectorType(Ty) ? IceType_i32 : Ty).emit(Func);
1168 } else {
1169 Src0->emit(Func);
1170 }
1171 Str << "\n";
1172}
1173
Matt Walae58178a2014-08-12 13:15:04 -07001174template <> void InstX8632Mov::emit(const Cfg *Func) const {
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -07001175 Ostream &Str = Func->getContext()->getStrEmit();
1176 assert(getSrcSize() == 1);
Jim Stichnothde4ca712014-06-29 08:13:48 -07001177 Operand *Src = getSrc(0);
1178 // The llvm-mc assembler using Intel syntax has a bug in which "mov
1179 // reg, RelocatableConstant" does not generate the right instruction
1180 // with a relocation. To work around, we emit "lea reg,
Jim Stichnoth523ef722014-09-04 11:32:20 -07001181 // RelocatableConstant". Also, the lowering and legalization is
Jim Stichnothde4ca712014-06-29 08:13:48 -07001182 // changed to allow relocatable constants only in Assign and Call
1183 // instructions or in Mem operands. TODO(stichnot): remove LEAHACK
1184 // once a proper emitter is used.
Jim Stichnoth523ef722014-09-04 11:32:20 -07001185 //
1186 // In addition, llvm-mc doesn't like "lea eax, bp" or "lea eax, Sp"
1187 // or "lea eax, flags" etc., when the relocatable constant name is a
1188 // reserved word. The hack-on-top-of-hack is to temporarily drop
1189 // into AT&T syntax for this lea instruction.
Jim Stichnothde4ca712014-06-29 08:13:48 -07001190 bool UseLeaHack = llvm::isa<ConstantRelocatable>(Src);
Jim Stichnoth523ef722014-09-04 11:32:20 -07001191 if (UseLeaHack) {
1192 Str << ".att_syntax\n";
1193 Str << "\tleal";
1194 } else {
1195 Str << "\tmov" << TypeX8632Attributes[getDest()->getType()].SdSsString;
1196 }
Jim Stichnothde4ca712014-06-29 08:13:48 -07001197 Str << "\t";
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -07001198 // For an integer truncation operation, src is wider than dest.
1199 // Ideally, we use a mov instruction whose data width matches the
1200 // narrower dest. This is a problem if e.g. src is a register like
1201 // esi or si where there is no 8-bit version of the register. To be
1202 // safe, we instead widen the dest to match src. This works even
1203 // for stack-allocated dest variables because typeWidthOnStack()
1204 // pads to a 4-byte boundary even if only a lower portion is used.
Matt Wala49889232014-07-18 12:45:09 -07001205 // TODO: This assert disallows usages such as copying a floating point
1206 // value between a vector and a scalar (which movss is used for).
1207 // Clean this up.
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -07001208 assert(Func->getTarget()->typeWidthInBytesOnStack(getDest()->getType()) ==
Jim Stichnothde4ca712014-06-29 08:13:48 -07001209 Func->getTarget()->typeWidthInBytesOnStack(Src->getType()));
Jim Stichnoth523ef722014-09-04 11:32:20 -07001210 if (UseLeaHack) {
1211 Src->emit(Func);
1212 Str << ", %";
1213 getDest()->emit(Func);
1214 Str << "\n";
1215 Str << ".intel_syntax\n";
1216 } else {
1217 getDest()->asType(Src->getType()).emit(Func);
1218 Str << ", ";
1219 Src->emit(Func);
1220 Str << "\n";
1221 }
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -07001222}
1223
Matt Walae58178a2014-08-12 13:15:04 -07001224template <> void InstX8632Movp::emit(const Cfg *Func) const {
Matt Wala928f1292014-07-07 16:50:46 -07001225 // TODO(wala,stichnot): movups works with all vector operands, but
1226 // there exist other instructions (movaps, movdqa, movdqu) that may
1227 // perform better, depending on the data type and alignment of the
1228 // operands.
1229 Ostream &Str = Func->getContext()->getStrEmit();
1230 assert(getSrcSize() == 1);
1231 Str << "\tmovups\t";
1232 getDest()->emit(Func);
1233 Str << ", ";
1234 getSrc(0)->emit(Func);
1235 Str << "\n";
1236}
1237
Matt Walae58178a2014-08-12 13:15:04 -07001238template <> void InstX8632Movq::emit(const Cfg *Func) const {
Jan Voung5cd240d2014-06-25 10:36:46 -07001239 Ostream &Str = Func->getContext()->getStrEmit();
1240 assert(getSrcSize() == 1);
1241 assert(getDest()->getType() == IceType_i64 ||
1242 getDest()->getType() == IceType_f64);
1243 Str << "\tmovq\t";
1244 getDest()->emit(Func);
1245 Str << ", ";
1246 getSrc(0)->emit(Func);
1247 Str << "\n";
1248}
1249
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -07001250void InstX8632Movsx::emit(const Cfg *Func) const {
1251 Ostream &Str = Func->getContext()->getStrEmit();
1252 assert(getSrcSize() == 1);
1253 Str << "\tmovsx\t";
1254 getDest()->emit(Func);
1255 Str << ", ";
1256 getSrc(0)->emit(Func);
1257 Str << "\n";
1258}
1259
1260void InstX8632Movsx::dump(const Cfg *Func) const {
1261 Ostream &Str = Func->getContext()->getStrDump();
1262 Str << "movsx." << getDest()->getType() << "." << getSrc(0)->getType();
1263 Str << " ";
1264 dumpDest(Func);
1265 Str << ", ";
1266 dumpSources(Func);
1267}
1268
1269void InstX8632Movzx::emit(const Cfg *Func) const {
1270 Ostream &Str = Func->getContext()->getStrEmit();
1271 assert(getSrcSize() == 1);
1272 Str << "\tmovzx\t";
1273 getDest()->emit(Func);
1274 Str << ", ";
1275 getSrc(0)->emit(Func);
1276 Str << "\n";
1277}
1278
1279void InstX8632Movzx::dump(const Cfg *Func) const {
1280 Ostream &Str = Func->getContext()->getStrDump();
1281 Str << "movzx." << getDest()->getType() << "." << getSrc(0)->getType();
1282 Str << " ";
1283 dumpDest(Func);
1284 Str << ", ";
1285 dumpSources(Func);
1286}
1287
Matt Walac3302742014-08-15 16:21:56 -07001288void InstX8632Nop::emit(const Cfg *Func) const {
1289 Ostream &Str = Func->getContext()->getStrEmit();
1290 // TODO: Emit the right code for each variant.
1291 Str << "\tnop\t# variant = " << Variant << "\n";
1292}
1293
Jan Voung8acded02014-09-22 18:02:25 -07001294void InstX8632Nop::emitIAS(const Cfg *Func) const {
1295 Ostream &Str = Func->getContext()->getStrEmit();
1296 x86::AssemblerX86 *Asm = Func->getAssembler<x86::AssemblerX86>();
1297 intptr_t StartPosition = Asm->GetPosition();
1298 // TODO: Emit the right code for the variant.
1299 Asm->nop();
1300 emitIASBytes(Str, Asm, StartPosition);
1301}
1302
Matt Walac3302742014-08-15 16:21:56 -07001303void InstX8632Nop::dump(const Cfg *Func) const {
1304 Ostream &Str = Func->getContext()->getStrDump();
1305 Str << "nop (variant = " << Variant << ")";
1306}
1307
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -07001308void InstX8632Fld::emit(const Cfg *Func) const {
1309 Ostream &Str = Func->getContext()->getStrEmit();
1310 assert(getSrcSize() == 1);
1311 Type Ty = getSrc(0)->getType();
1312 Variable *Var = llvm::dyn_cast<Variable>(getSrc(0));
1313 if (Var && Var->hasReg()) {
1314 // This is a physical xmm register, so we need to spill it to a
1315 // temporary stack slot.
1316 SizeT Width = typeWidthInBytes(Ty);
1317 Str << "\tsub\tesp, " << Width << "\n";
1318 Str << "\tmov" << TypeX8632Attributes[Ty].SdSsString << "\t"
1319 << TypeX8632Attributes[Ty].WidthString << " [esp], ";
1320 Var->emit(Func);
1321 Str << "\n";
1322 Str << "\tfld\t" << TypeX8632Attributes[Ty].WidthString << " [esp]\n";
1323 Str << "\tadd\tesp, " << Width << "\n";
1324 return;
1325 }
1326 Str << "\tfld\t";
1327 getSrc(0)->emit(Func);
1328 Str << "\n";
1329}
1330
1331void InstX8632Fld::dump(const Cfg *Func) const {
1332 Ostream &Str = Func->getContext()->getStrDump();
1333 Str << "fld." << getSrc(0)->getType() << " ";
1334 dumpSources(Func);
1335}
1336
1337void InstX8632Fstp::emit(const Cfg *Func) const {
1338 Ostream &Str = Func->getContext()->getStrEmit();
1339 assert(getSrcSize() == 0);
1340 if (getDest() == NULL) {
1341 Str << "\tfstp\tst(0)\n";
1342 return;
1343 }
1344 if (!getDest()->hasReg()) {
1345 Str << "\tfstp\t";
1346 getDest()->emit(Func);
1347 Str << "\n";
1348 return;
1349 }
1350 // Dest is a physical (xmm) register, so st(0) needs to go through
1351 // memory. Hack this by creating a temporary stack slot, spilling
1352 // st(0) there, loading it into the xmm register, and deallocating
1353 // the stack slot.
1354 Type Ty = getDest()->getType();
1355 size_t Width = typeWidthInBytes(Ty);
1356 Str << "\tsub\tesp, " << Width << "\n";
1357 Str << "\tfstp\t" << TypeX8632Attributes[Ty].WidthString << " [esp]\n";
1358 Str << "\tmov" << TypeX8632Attributes[Ty].SdSsString << "\t";
1359 getDest()->emit(Func);
1360 Str << ", " << TypeX8632Attributes[Ty].WidthString << " [esp]\n";
1361 Str << "\tadd\tesp, " << Width << "\n";
1362}
1363
1364void InstX8632Fstp::dump(const Cfg *Func) const {
1365 Ostream &Str = Func->getContext()->getStrDump();
1366 dumpDest(Func);
1367 Str << " = fstp." << getDest()->getType() << ", st(0)";
1368 Str << "\n";
1369}
1370
Matt Wala83b80362014-07-16 10:21:30 -07001371template <> void InstX8632Pcmpeq::emit(const Cfg *Func) const {
1372 char buf[30];
1373 snprintf(buf, llvm::array_lengthof(buf), "pcmpeq%s",
1374 TypeX8632Attributes[getDest()->getType()].PackString);
1375 emitTwoAddress(buf, this, Func);
1376}
1377
1378template <> void InstX8632Pcmpgt::emit(const Cfg *Func) const {
1379 char buf[30];
1380 snprintf(buf, llvm::array_lengthof(buf), "pcmpgt%s",
1381 TypeX8632Attributes[getDest()->getType()].PackString);
1382 emitTwoAddress(buf, this, Func);
1383}
1384
Matt Wala0a450512014-07-30 12:44:39 -07001385template <> void InstX8632Pextr::emit(const Cfg *Func) const {
Matt Wala49889232014-07-18 12:45:09 -07001386 Ostream &Str = Func->getContext()->getStrEmit();
1387 assert(getSrcSize() == 2);
Matt Wala0a450512014-07-30 12:44:39 -07001388 // pextrb and pextrd are SSE4.1 instructions.
1389 assert(getSrc(0)->getType() == IceType_v8i16 ||
1390 getSrc(0)->getType() == IceType_v8i1 ||
1391 static_cast<TargetX8632 *>(Func->getTarget())->getInstructionSet()
1392 >= TargetX8632::SSE4_1);
1393 Str << "\t" << Opcode
1394 << TypeX8632Attributes[getSrc(0)->getType()].PackString << "\t";
Matt Wala49889232014-07-18 12:45:09 -07001395 Variable *Dest = getDest();
Matt Wala0a450512014-07-30 12:44:39 -07001396 // pextrw must take a register dest.
1397 assert(Dest->getType() != IceType_i16 || Dest->hasReg());
Matt Wala49889232014-07-18 12:45:09 -07001398 Dest->asType(IceType_i32).emit(Func);
1399 Str << ", ";
1400 getSrc(0)->emit(Func);
1401 Str << ", ";
1402 getSrc(1)->emit(Func);
1403 Str << "\n";
1404}
1405
Matt Wala0a450512014-07-30 12:44:39 -07001406template <> void InstX8632Pinsr::emit(const Cfg *Func) const {
Matt Wala49889232014-07-18 12:45:09 -07001407 Ostream &Str = Func->getContext()->getStrEmit();
1408 assert(getSrcSize() == 3);
Matt Wala0a450512014-07-30 12:44:39 -07001409 // pinsrb and pinsrd are SSE4.1 instructions.
1410 assert(getDest()->getType() == IceType_v8i16 ||
1411 getDest()->getType() == IceType_v8i1 ||
1412 static_cast<TargetX8632 *>(Func->getTarget())->getInstructionSet()
1413 >= TargetX8632::SSE4_1);
1414 Str << "\t" << Opcode
1415 << TypeX8632Attributes[getDest()->getType()].PackString << "\t";
Matt Wala49889232014-07-18 12:45:09 -07001416 getDest()->emit(Func);
1417 Str << ", ";
1418 Operand *Src1 = getSrc(1);
1419 if (Variable *VSrc1 = llvm::dyn_cast<Variable>(Src1)) {
Matt Wala0a450512014-07-30 12:44:39 -07001420 // If src1 is a register, it should always be r32.
1421 if (VSrc1->hasReg()) {
1422 VSrc1->asType(IceType_i32).emit(Func);
1423 } else {
1424 VSrc1->emit(Func);
1425 }
Matt Wala49889232014-07-18 12:45:09 -07001426 } else {
1427 Src1->emit(Func);
1428 }
1429 Str << ", ";
1430 getSrc(2)->emit(Func);
1431 Str << "\n";
1432}
1433
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -07001434void InstX8632Pop::emit(const Cfg *Func) const {
1435 Ostream &Str = Func->getContext()->getStrEmit();
1436 assert(getSrcSize() == 0);
1437 Str << "\tpop\t";
1438 getDest()->emit(Func);
1439 Str << "\n";
1440}
1441
Jan Voung8acded02014-09-22 18:02:25 -07001442void InstX8632Pop::emitIAS(const Cfg *Func) const {
1443 Ostream &Str = Func->getContext()->getStrEmit();
1444 assert(getSrcSize() == 0);
1445 x86::AssemblerX86 *Asm = Func->getAssembler<x86::AssemblerX86>();
1446 intptr_t StartPosition = Asm->GetPosition();
1447 if (getDest()->hasReg()) {
1448 Asm->popl(RegX8632::getEncodedGPR(getDest()->getRegNum()));
1449 } else {
1450 Asm->popl(static_cast<TargetX8632 *>(Func->getTarget())
1451 ->stackVarToAsmOperand(getDest()));
1452 }
1453 emitIASBytes(Str, Asm, StartPosition);
1454}
1455
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -07001456void InstX8632Pop::dump(const Cfg *Func) const {
1457 Ostream &Str = Func->getContext()->getStrDump();
1458 dumpDest(Func);
1459 Str << " = pop." << getDest()->getType() << " ";
1460}
1461
Matt Wala105b7042014-08-11 19:56:19 -07001462void InstX8632AdjustStack::emit(const Cfg *Func) const {
1463 Ostream &Str = Func->getContext()->getStrEmit();
1464 Str << "\tsub\tesp, " << Amount << "\n";
1465 Func->getTarget()->updateStackAdjustment(Amount);
1466}
1467
Jan Voung8acded02014-09-22 18:02:25 -07001468void InstX8632AdjustStack::emitIAS(const Cfg *Func) const {
1469 Ostream &Str = Func->getContext()->getStrEmit();
1470 x86::AssemblerX86 *Asm = Func->getAssembler<x86::AssemblerX86>();
1471 intptr_t StartPosition = Asm->GetPosition();
1472 Asm->subl(RegX8632::Encoded_Reg_esp, x86::Immediate(Amount));
1473 emitIASBytes(Str, Asm, StartPosition);
1474 Func->getTarget()->updateStackAdjustment(Amount);
1475}
1476
Matt Wala105b7042014-08-11 19:56:19 -07001477void InstX8632AdjustStack::dump(const Cfg *Func) const {
1478 Ostream &Str = Func->getContext()->getStrDump();
1479 Str << "esp = sub.i32 esp, " << Amount;
1480}
1481
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -07001482void InstX8632Push::emit(const Cfg *Func) const {
1483 Ostream &Str = Func->getContext()->getStrEmit();
1484 assert(getSrcSize() == 1);
1485 Type Ty = getSrc(0)->getType();
1486 Variable *Var = llvm::dyn_cast<Variable>(getSrc(0));
Matt Wala45a06232014-07-09 16:33:22 -07001487 if ((isVectorType(Ty) || Ty == IceType_f32 || Ty == IceType_f64) && Var &&
1488 Var->hasReg()) {
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -07001489 // The xmm registers can't be directly pushed, so we fake it by
1490 // decrementing esp and then storing to [esp].
1491 Str << "\tsub\tesp, " << typeWidthInBytes(Ty) << "\n";
1492 if (!SuppressStackAdjustment)
1493 Func->getTarget()->updateStackAdjustment(typeWidthInBytes(Ty));
Matt Wala45a06232014-07-09 16:33:22 -07001494 if (isVectorType(Ty)) {
1495 Str << "\tmovups\txmmword ptr [esp], ";
1496 } else {
1497 Str << "\tmov" << TypeX8632Attributes[Ty].SdSsString << "\t"
1498 << TypeX8632Attributes[Ty].WidthString << " [esp], ";
1499 }
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -07001500 getSrc(0)->emit(Func);
1501 Str << "\n";
1502 } else if (Ty == IceType_f64 && (!Var || !Var->hasReg())) {
1503 // A double on the stack has to be pushed as two halves. Push the
1504 // upper half followed by the lower half for little-endian. TODO:
1505 // implement.
1506 llvm_unreachable("Missing support for pushing doubles from memory");
1507 } else {
1508 Str << "\tpush\t";
1509 getSrc(0)->emit(Func);
1510 Str << "\n";
1511 if (!SuppressStackAdjustment)
1512 Func->getTarget()->updateStackAdjustment(4);
1513 }
1514}
1515
1516void InstX8632Push::dump(const Cfg *Func) const {
1517 Ostream &Str = Func->getContext()->getStrDump();
1518 Str << "push." << getSrc(0)->getType() << " ";
1519 dumpSources(Func);
1520}
1521
Matt Wala83b80362014-07-16 10:21:30 -07001522template <> void InstX8632Psll::emit(const Cfg *Func) const {
1523 assert(getDest()->getType() == IceType_v8i16 ||
Matt Wala0a450512014-07-30 12:44:39 -07001524 getDest()->getType() == IceType_v8i1 ||
1525 getDest()->getType() == IceType_v4i32 ||
1526 getDest()->getType() == IceType_v4i1);
Matt Wala83b80362014-07-16 10:21:30 -07001527 char buf[30];
1528 snprintf(buf, llvm::array_lengthof(buf), "psll%s",
1529 TypeX8632Attributes[getDest()->getType()].PackString);
1530 emitTwoAddress(buf, this, Func);
1531}
1532
1533template <> void InstX8632Psra::emit(const Cfg *Func) const {
1534 assert(getDest()->getType() == IceType_v8i16 ||
Matt Wala0a450512014-07-30 12:44:39 -07001535 getDest()->getType() == IceType_v8i1 ||
1536 getDest()->getType() == IceType_v4i32 ||
1537 getDest()->getType() == IceType_v4i1);
Matt Wala83b80362014-07-16 10:21:30 -07001538 char buf[30];
1539 snprintf(buf, llvm::array_lengthof(buf), "psra%s",
1540 TypeX8632Attributes[getDest()->getType()].PackString);
1541 emitTwoAddress(buf, this, Func);
1542}
1543
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -07001544void InstX8632Ret::emit(const Cfg *Func) const {
1545 Ostream &Str = Func->getContext()->getStrEmit();
1546 Str << "\tret\n";
1547}
1548
Jan Voung8acded02014-09-22 18:02:25 -07001549void InstX8632Ret::emitIAS(const Cfg *Func) const {
1550 Ostream &Str = Func->getContext()->getStrEmit();
1551 x86::AssemblerX86 *Asm = Func->getAssembler<x86::AssemblerX86>();
1552 intptr_t StartPosition = Asm->GetPosition();
1553 Asm->ret();
1554 emitIASBytes(Str, Asm, StartPosition);
1555}
1556
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -07001557void InstX8632Ret::dump(const Cfg *Func) const {
1558 Ostream &Str = Func->getContext()->getStrDump();
1559 Type Ty = (getSrcSize() == 0 ? IceType_void : getSrc(0)->getType());
1560 Str << "ret." << Ty << " ";
1561 dumpSources(Func);
1562}
1563
Jan Voung5cd240d2014-06-25 10:36:46 -07001564void InstX8632Xadd::emit(const Cfg *Func) const {
1565 Ostream &Str = Func->getContext()->getStrEmit();
1566 if (Locked) {
Jan Vounga3a01a22014-07-14 10:32:41 -07001567 Str << "\tlock";
Jan Voung5cd240d2014-06-25 10:36:46 -07001568 }
Jan Vounga3a01a22014-07-14 10:32:41 -07001569 Str << "\txadd\t";
Jan Voung5cd240d2014-06-25 10:36:46 -07001570 getSrc(0)->emit(Func);
1571 Str << ", ";
1572 getSrc(1)->emit(Func);
1573 Str << "\n";
1574}
1575
1576void InstX8632Xadd::dump(const Cfg *Func) const {
1577 Ostream &Str = Func->getContext()->getStrDump();
1578 if (Locked) {
1579 Str << "lock ";
1580 }
1581 Type Ty = getSrc(0)->getType();
1582 Str << "xadd." << Ty << " ";
1583 dumpSources(Func);
1584}
1585
Jan Vounga3a01a22014-07-14 10:32:41 -07001586void InstX8632Xchg::emit(const Cfg *Func) const {
1587 Ostream &Str = Func->getContext()->getStrEmit();
1588 Str << "\txchg\t";
1589 getSrc(0)->emit(Func);
1590 Str << ", ";
1591 getSrc(1)->emit(Func);
1592 Str << "\n";
1593}
1594
1595void InstX8632Xchg::dump(const Cfg *Func) const {
1596 Ostream &Str = Func->getContext()->getStrDump();
1597 Type Ty = getSrc(0)->getType();
1598 Str << "xchg." << Ty << " ";
1599 dumpSources(Func);
1600}
1601
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -07001602void OperandX8632Mem::emit(const Cfg *Func) const {
1603 Ostream &Str = Func->getContext()->getStrEmit();
1604 Str << TypeX8632Attributes[getType()].WidthString << " ";
Jan Voung3bd9f1a2014-06-18 10:50:57 -07001605 if (SegmentReg != DefaultSegment) {
Jim Stichnoth5acafbc2014-07-30 15:37:39 -07001606 assert(SegmentReg >= 0 && SegmentReg < SegReg_NUM);
Jan Voung3bd9f1a2014-06-18 10:50:57 -07001607 Str << InstX8632SegmentRegNames[SegmentReg] << ":";
1608 }
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -07001609 // TODO: The following is an almost verbatim paste of dump().
1610 bool Dumped = false;
1611 Str << "[";
1612 if (Base) {
1613 Base->emit(Func);
1614 Dumped = true;
1615 }
1616 if (Index) {
1617 assert(Base);
1618 Str << "+";
1619 if (Shift > 0)
1620 Str << (1u << Shift) << "*";
1621 Index->emit(Func);
1622 Dumped = true;
1623 }
1624 // Pretty-print the Offset.
1625 bool OffsetIsZero = false;
1626 bool OffsetIsNegative = false;
1627 if (Offset == NULL) {
1628 OffsetIsZero = true;
Jan Voungbc004632014-09-16 15:09:10 -07001629 } else if (ConstantInteger32 *CI =
1630 llvm::dyn_cast<ConstantInteger32>(Offset)) {
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -07001631 OffsetIsZero = (CI->getValue() == 0);
Jan Voungbc004632014-09-16 15:09:10 -07001632 OffsetIsNegative = (static_cast<int32_t>(CI->getValue()) < 0);
1633 } else {
1634 assert(llvm::isa<ConstantRelocatable>(Offset));
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -07001635 }
Jan Voung3bd9f1a2014-06-18 10:50:57 -07001636 if (Dumped) {
1637 if (!OffsetIsZero) { // Suppress if Offset is known to be 0
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -07001638 if (!OffsetIsNegative) // Suppress if Offset is known to be negative
1639 Str << "+";
Jan Voung3bd9f1a2014-06-18 10:50:57 -07001640 Offset->emit(Func);
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -07001641 }
Jan Voung3bd9f1a2014-06-18 10:50:57 -07001642 } else {
1643 // There is only the offset.
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -07001644 Offset->emit(Func);
1645 }
1646 Str << "]";
1647}
1648
Jim Stichnoth2e8bfbb2014-09-16 10:16:00 -07001649void OperandX8632Mem::dump(const Cfg *Func, Ostream &Str) const {
Jan Voung3bd9f1a2014-06-18 10:50:57 -07001650 if (SegmentReg != DefaultSegment) {
Jim Stichnoth5acafbc2014-07-30 15:37:39 -07001651 assert(SegmentReg >= 0 && SegmentReg < SegReg_NUM);
Jan Voung3bd9f1a2014-06-18 10:50:57 -07001652 Str << InstX8632SegmentRegNames[SegmentReg] << ":";
1653 }
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -07001654 bool Dumped = false;
1655 Str << "[";
1656 if (Base) {
Jim Stichnoth2e8bfbb2014-09-16 10:16:00 -07001657 if (Func)
1658 Base->dump(Func);
1659 else
1660 Base->dump(Str);
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -07001661 Dumped = true;
1662 }
1663 if (Index) {
1664 assert(Base);
1665 Str << "+";
1666 if (Shift > 0)
1667 Str << (1u << Shift) << "*";
Jim Stichnoth2e8bfbb2014-09-16 10:16:00 -07001668 if (Func)
1669 Index->dump(Func);
1670 else
1671 Index->dump(Str);
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -07001672 Dumped = true;
1673 }
1674 // Pretty-print the Offset.
1675 bool OffsetIsZero = false;
1676 bool OffsetIsNegative = false;
1677 if (Offset == NULL) {
1678 OffsetIsZero = true;
Jan Voungbc004632014-09-16 15:09:10 -07001679 } else if (ConstantInteger32 *CI =
1680 llvm::dyn_cast<ConstantInteger32>(Offset)) {
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -07001681 OffsetIsZero = (CI->getValue() == 0);
Jan Voungbc004632014-09-16 15:09:10 -07001682 OffsetIsNegative = (static_cast<int32_t>(CI->getValue()) < 0);
1683 } else {
1684 assert(llvm::isa<ConstantRelocatable>(Offset));
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -07001685 }
Jan Voung3bd9f1a2014-06-18 10:50:57 -07001686 if (Dumped) {
1687 if (!OffsetIsZero) { // Suppress if Offset is known to be 0
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -07001688 if (!OffsetIsNegative) // Suppress if Offset is known to be negative
1689 Str << "+";
Jim Stichnoth2e8bfbb2014-09-16 10:16:00 -07001690 Offset->dump(Func, Str);
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -07001691 }
Jan Voung3bd9f1a2014-06-18 10:50:57 -07001692 } else {
1693 // There is only the offset.
Jim Stichnoth2e8bfbb2014-09-16 10:16:00 -07001694 Offset->dump(Func, Str);
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -07001695 }
1696 Str << "]";
1697}
1698
Jan Voung8acded02014-09-22 18:02:25 -07001699x86::Address OperandX8632Mem::toAsmAddress(Assembler *Asm) const {
1700 int32_t Disp = 0;
1701 AssemblerFixup *Fixup = NULL;
1702 // Determine the offset (is it relocatable?)
1703 if (getOffset()) {
1704 if (ConstantInteger32 *CI =
1705 llvm::dyn_cast<ConstantInteger32>(getOffset())) {
1706 Disp = static_cast<int32_t>(CI->getValue());
1707 } else if (ConstantRelocatable *CR =
1708 llvm::dyn_cast<ConstantRelocatable>(getOffset())) {
1709 // TODO(jvoung): CR + non-zero-offset isn't really tested yet,
1710 // since the addressing mode optimization doesn't try to combine
1711 // ConstantRelocatable with something else.
1712 assert(CR->getOffset() == 0);
1713 Fixup = x86::DisplacementRelocation::create(Asm, FK_Abs_4, CR);
1714 } else {
1715 llvm_unreachable("Unexpected offset type");
1716 }
1717 }
1718
1719 // Now convert to the various possible forms.
1720 if (getBase() && getIndex()) {
1721 return x86::Address(RegX8632::getEncodedGPR(getBase()->getRegNum()),
1722 RegX8632::getEncodedGPR(getIndex()->getRegNum()),
1723 x86::ScaleFactor(getShift()), Disp);
1724 } else if (getBase()) {
1725 return x86::Address(RegX8632::getEncodedGPR(getBase()->getRegNum()), Disp);
1726 } else if (getIndex()) {
1727 return x86::Address(RegX8632::getEncodedGPR(getIndex()->getRegNum()),
1728 x86::ScaleFactor(getShift()), Disp);
1729 } else {
1730 return x86::Address::Absolute(Disp, Fixup);
1731 }
1732}
1733
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -07001734void VariableSplit::emit(const Cfg *Func) const {
1735 Ostream &Str = Func->getContext()->getStrEmit();
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -07001736 assert(!Var->hasReg());
1737 // The following is copied/adapted from TargetX8632::emitVariable().
1738 const TargetLowering *Target = Func->getTarget();
1739 const Type Ty = IceType_i32;
1740 Str << TypeX8632Attributes[Ty].WidthString << " ["
1741 << Target->getRegName(Target->getFrameOrStackReg(), Ty);
1742 int32_t Offset = Var->getStackOffset() + Target->getStackAdjustment();
1743 if (Part == High)
1744 Offset += 4;
1745 if (Offset) {
1746 if (Offset > 0)
1747 Str << "+";
1748 Str << Offset;
1749 }
1750 Str << "]";
1751}
1752
Jim Stichnoth2e8bfbb2014-09-16 10:16:00 -07001753void VariableSplit::dump(const Cfg *Func, Ostream &Str) const {
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -07001754 switch (Part) {
1755 case Low:
1756 Str << "low";
1757 break;
1758 case High:
1759 Str << "high";
1760 break;
1761 default:
1762 Str << "???";
1763 break;
1764 }
1765 Str << "(";
Jim Stichnoth2e8bfbb2014-09-16 10:16:00 -07001766 if (Func)
1767 Var->dump(Func);
1768 else
1769 Var->dump(Str);
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -07001770 Str << ")";
1771}
1772
1773} // end of namespace Ice