Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(184)

Side by Side Diff: src/IceInstX8632.cpp

Issue 1216933015: X8632 Templatization completed. (Closed) Base URL: https://chromium.googlesource.com/native_client/pnacl-subzero.git@master
Patch Set: Eliminates all references to X8632 from Impl files. Created 5 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 //===- subzero/src/IceInstX8632.cpp - X86-32 instruction implementation ---===// 1 //===- subzero/src/IceInstX8632.cpp - X86-32 instruction implementation ---===//
2 // 2 //
3 // The Subzero Code Generator 3 // The Subzero Code Generator
4 // 4 //
5 // This file is distributed under the University of Illinois Open Source 5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details. 6 // License. See LICENSE.TXT for details.
7 // 7 //
8 //===----------------------------------------------------------------------===// 8 //===----------------------------------------------------------------------===//
9 // 9 //
10 // This file implements the InstX8632 and OperandX8632 classes, 10 // This file implements the InstX8632 and OperandX8632 classes,
jvoung (off chromium) 2015/07/06 18:58:45 OperandX8632 is now X86Operand (except for the dum
John 2015/07/06 22:30:08 Done.
11 // primarily the constructors and the dump()/emit() methods. 11 // primarily the constructors and the dump()/emit() methods.
12 // 12 //
13 //===----------------------------------------------------------------------===// 13 //===----------------------------------------------------------------------===//
14 14
15 #include "IceInstX8632.h" 15 #include "IceInstX8632.h"
16 16
17 #include "IceAssemblerX8632.h" 17 #include "IceAssemblerX8632.h"
18 #include "IceCfg.h" 18 #include "IceCfg.h"
19 #include "IceCfgNode.h" 19 #include "IceCfgNode.h"
20 #include "IceConditionCodesX8632.h" 20 #include "IceConditionCodesX8632.h"
21 #include "IceInst.h" 21 #include "IceInst.h"
22 #include "IceRegistersX8632.h" 22 #include "IceRegistersX8632.h"
23 #include "IceTargetLoweringX8632.h" 23 #include "IceTargetLoweringX8632.h"
24 #include "IceOperand.h" 24 #include "IceOperand.h"
25 25
26 namespace Ice { 26 namespace Ice {
27 27
28 namespace { 28 namespace X86Internal {
29 29
30 const struct InstX8632BrAttributes_ { 30 const MachineTraits<TargetX8632>::InstBrAttributesType
31 X8632::Traits::Cond::BrCond Opposite; 31 MachineTraits<TargetX8632>::InstBrAttributes[] = {
32 const char *DisplayString;
33 const char *EmitString;
34 } InstX8632BrAttributes[] = {
35 #define X(tag, encode, opp, dump, emit) \ 32 #define X(tag, encode, opp, dump, emit) \
36 { X8632::Traits::Cond::opp, dump, emit } \ 33 { X8632::Traits::Cond::opp, dump, emit } \
37 , 34 ,
38 ICEINSTX8632BR_TABLE 35 ICEINSTX8632BR_TABLE
39 #undef X 36 #undef X
40 }; 37 };
41 38
42 const struct InstX8632CmppsAttributes_ { 39 const MachineTraits<TargetX8632>::InstCmppsAttributesType
43 const char *EmitString; 40 MachineTraits<TargetX8632>::InstCmppsAttributes[] = {
44 } InstX8632CmppsAttributes[] = {
45 #define X(tag, emit) \ 41 #define X(tag, emit) \
46 { emit } \ 42 { emit } \
47 , 43 ,
48 ICEINSTX8632CMPPS_TABLE 44 ICEINSTX8632CMPPS_TABLE
49 #undef X 45 #undef X
50 }; 46 };
51 47
52 const struct TypeX8632Attributes_ { 48 const MachineTraits<TargetX8632>::TypeAttributesType
53 const char *CvtString; // i (integer), s (single FP), d (double FP) 49 MachineTraits<TargetX8632>::TypeAttributes[] = {
54 const char *SdSsString; // ss, sd, or <blank>
55 const char *PackString; // b, w, d, or <blank>
56 const char *WidthString; // b, w, l, q, or <blank>
57 const char *FldString; // s, l, or <blank>
58 } TypeX8632Attributes[] = {
59 #define X(tag, elementty, cvt, sdss, pack, width, fld) \ 50 #define X(tag, elementty, cvt, sdss, pack, width, fld) \
60 { cvt, sdss, pack, width, fld } \ 51 { cvt, sdss, pack, width, fld } \
61 , 52 ,
62 ICETYPEX8632_TABLE 53 ICETYPEX8632_TABLE
63 #undef X 54 #undef X
64 }; 55 };
65 56
66 const char *InstX8632SegmentRegNames[] = { 57 const char *MachineTraits<TargetX8632>::InstSegmentRegNames[] = {
67 #define X(val, name, prefix) name, 58 #define X(val, name, prefix) name,
68 SEG_REGX8632_TABLE 59 SEG_REGX8632_TABLE
69 #undef X 60 #undef X
70 }; 61 };
71 62
72 uint8_t InstX8632SegmentPrefixes[] = { 63 uint8_t MachineTraits<TargetX8632>::InstSegmentPrefixes[] = {
73 #define X(val, name, prefix) prefix, 64 #define X(val, name, prefix) prefix,
74 SEG_REGX8632_TABLE 65 SEG_REGX8632_TABLE
75 #undef X 66 #undef X
76 }; 67 };
77 68
78 } // end of anonymous namespace 69 void MachineTraits<TargetX8632>::X86Operand::dump(const Cfg *,
79 70 Ostream &Str) const {
80 const char *InstX8632::getWidthString(Type Ty) { 71 if (BuildDefs::dump())
81 return TypeX8632Attributes[Ty].WidthString; 72 Str << "<OperandX8632>";
82 } 73 }
83 74
84 const char *InstX8632::getFldString(Type Ty) { 75 MachineTraits<TargetX8632>::X86OperandMem::X86OperandMem(
85 return TypeX8632Attributes[Ty].FldString; 76 Cfg *Func, Type Ty, Variable *Base, Constant *Offset, Variable *Index,
86 } 77 uint16_t Shift, SegmentRegisters SegmentReg)
87 78 : X86Operand(kMem, Ty), Base(Base), Offset(Offset), Index(Index),
88 X8632::Traits::Cond::BrCond
89 InstX8632::getOppositeCondition(X8632::Traits::Cond::BrCond Cond) {
90 return InstX8632BrAttributes[Cond].Opposite;
91 }
92
93 OperandX8632Mem::OperandX8632Mem(Cfg *Func, Type Ty, Variable *Base,
94 Constant *Offset, Variable *Index,
95 uint16_t Shift, SegmentRegisters SegmentReg)
96 : OperandX8632(kMem, Ty), Base(Base), Offset(Offset), Index(Index),
97 Shift(Shift), SegmentReg(SegmentReg), Randomized(false) { 79 Shift(Shift), SegmentReg(SegmentReg), Randomized(false) {
98 assert(Shift <= 3); 80 assert(Shift <= 3);
99 Vars = nullptr; 81 Vars = nullptr;
100 NumVars = 0; 82 NumVars = 0;
101 if (Base) 83 if (Base)
102 ++NumVars; 84 ++NumVars;
103 if (Index) 85 if (Index)
104 ++NumVars; 86 ++NumVars;
105 if (NumVars) { 87 if (NumVars) {
106 Vars = Func->allocateArrayOf<Variable *>(NumVars); 88 Vars = Func->allocateArrayOf<Variable *>(NumVars);
107 SizeT I = 0; 89 SizeT I = 0;
108 if (Base) 90 if (Base)
109 Vars[I++] = Base; 91 Vars[I++] = Base;
110 if (Index) 92 if (Index)
111 Vars[I++] = Index; 93 Vars[I++] = Index;
112 assert(I == NumVars); 94 assert(I == NumVars);
113 } 95 }
114 } 96 }
jvoung (off chromium) 2015/07/06 18:58:45 newline between ctor and emit?
John 2015/07/06 22:30:09 Done.
115 97 void MachineTraits<TargetX8632>::X86OperandMem::emit(const Cfg *Func) const {
116 InstX8632FakeRMW::InstX8632FakeRMW(Cfg *Func, Operand *Data, Operand *Addr,
117 InstArithmetic::OpKind Op, Variable *Beacon)
118 : InstX8632(Func, InstX8632::FakeRMW, 3, nullptr), Op(Op) {
119 addSource(Data);
120 addSource(Addr);
121 addSource(Beacon);
122 }
123
124 InstX8632AdjustStack::InstX8632AdjustStack(Cfg *Func, SizeT Amount,
125 Variable *Esp)
126 : InstX8632(Func, InstX8632::Adjuststack, 1, Esp), Amount(Amount) {
127 addSource(Esp);
128 }
129
130 InstX8632Mul::InstX8632Mul(Cfg *Func, Variable *Dest, Variable *Source1,
131 Operand *Source2)
132 : InstX8632(Func, InstX8632::Mul, 2, Dest) {
133 addSource(Source1);
134 addSource(Source2);
135 }
136
137 InstX8632Shld::InstX8632Shld(Cfg *Func, Variable *Dest, Variable *Source1,
138 Variable *Source2)
139 : InstX8632(Func, InstX8632::Shld, 3, Dest) {
140 addSource(Dest);
141 addSource(Source1);
142 addSource(Source2);
143 }
144
145 InstX8632Shrd::InstX8632Shrd(Cfg *Func, Variable *Dest, Variable *Source1,
146 Variable *Source2)
147 : InstX8632(Func, InstX8632::Shrd, 3, Dest) {
148 addSource(Dest);
149 addSource(Source1);
150 addSource(Source2);
151 }
152
153 InstX8632Label::InstX8632Label(Cfg *Func, TargetX8632 *Target)
154 : InstX8632(Func, InstX8632::Label, 0, nullptr),
155 Number(Target->makeNextLabelNumber()) {}
156
157 IceString InstX8632Label::getName(const Cfg *Func) const {
158 return ".L" + Func->getFunctionName() + "$local$__" + std::to_string(Number);
159 }
160
161 InstX8632Br::InstX8632Br(Cfg *Func, const CfgNode *TargetTrue,
162 const CfgNode *TargetFalse,
163 const InstX8632Label *Label,
164 X8632::Traits::Cond::BrCond Condition)
165 : InstX8632(Func, InstX8632::Br, 0, nullptr), Condition(Condition),
166 TargetTrue(TargetTrue), TargetFalse(TargetFalse), Label(Label) {}
167
168 bool InstX8632Br::optimizeBranch(const CfgNode *NextNode) {
169 // If there is no next block, then there can be no fallthrough to
170 // optimize.
171 if (NextNode == nullptr)
172 return false;
173 // Intra-block conditional branches can't be optimized.
174 if (Label)
175 return false;
176 // If there is no fallthrough node, such as a non-default case label
177 // for a switch instruction, then there is no opportunity to
178 // optimize.
179 if (getTargetFalse() == nullptr)
180 return false;
181
182 // Unconditional branch to the next node can be removed.
183 if (Condition == X8632::Traits::Cond::Br_None &&
184 getTargetFalse() == NextNode) {
185 assert(getTargetTrue() == nullptr);
186 setDeleted();
187 return true;
188 }
189 // If the fallthrough is to the next node, set fallthrough to nullptr
190 // to indicate.
191 if (getTargetFalse() == NextNode) {
192 TargetFalse = nullptr;
193 return true;
194 }
195 // If TargetTrue is the next node, and TargetFalse is not nullptr
196 // (which was already tested above), then invert the branch
197 // condition, swap the targets, and set new fallthrough to nullptr.
198 if (getTargetTrue() == NextNode) {
199 assert(Condition != X8632::Traits::Cond::Br_None);
200 Condition = getOppositeCondition(Condition);
201 TargetTrue = getTargetFalse();
202 TargetFalse = nullptr;
203 return true;
204 }
205 return false;
206 }
207
208 bool InstX8632Br::repointEdge(CfgNode *OldNode, CfgNode *NewNode) {
209 if (TargetFalse == OldNode) {
210 TargetFalse = NewNode;
211 return true;
212 } else if (TargetTrue == OldNode) {
213 TargetTrue = NewNode;
214 return true;
215 }
216 return false;
217 }
218
219 InstX8632Jmp::InstX8632Jmp(Cfg *Func, Operand *Target)
220 : InstX8632(Func, InstX8632::Jmp, 1, nullptr) {
221 addSource(Target);
222 }
223
224 InstX8632Call::InstX8632Call(Cfg *Func, Variable *Dest, Operand *CallTarget)
225 : InstX8632(Func, InstX8632::Call, 1, Dest) {
226 HasSideEffects = true;
227 addSource(CallTarget);
228 }
229
230 InstX8632Cmov::InstX8632Cmov(Cfg *Func, Variable *Dest, Operand *Source,
231 X8632::Traits::Cond::BrCond Condition)
232 : InstX8632(Func, InstX8632::Cmov, 2, Dest), Condition(Condition) {
233 // The final result is either the original Dest, or Source, so mark
234 // both as sources.
235 addSource(Dest);
236 addSource(Source);
237 }
238
239 InstX8632Cmpps::InstX8632Cmpps(Cfg *Func, Variable *Dest, Operand *Source,
240 X8632::Traits::Cond::CmppsCond Condition)
241 : InstX8632(Func, InstX8632::Cmpps, 2, Dest), Condition(Condition) {
242 addSource(Dest);
243 addSource(Source);
244 }
245
246 InstX8632Cmpxchg::InstX8632Cmpxchg(Cfg *Func, Operand *DestOrAddr,
247 Variable *Eax, Variable *Desired,
248 bool Locked)
249 : InstX8632Lockable(Func, InstX8632::Cmpxchg, 3,
250 llvm::dyn_cast<Variable>(DestOrAddr), Locked) {
251 assert(Eax->getRegNum() == RegX8632::Reg_eax);
252 addSource(DestOrAddr);
253 addSource(Eax);
254 addSource(Desired);
255 }
256
257 InstX8632Cmpxchg8b::InstX8632Cmpxchg8b(Cfg *Func, OperandX8632Mem *Addr,
258 Variable *Edx, Variable *Eax,
259 Variable *Ecx, Variable *Ebx,
260 bool Locked)
261 : InstX8632Lockable(Func, InstX8632::Cmpxchg, 5, nullptr, Locked) {
262 assert(Edx->getRegNum() == RegX8632::Reg_edx);
263 assert(Eax->getRegNum() == RegX8632::Reg_eax);
264 assert(Ecx->getRegNum() == RegX8632::Reg_ecx);
265 assert(Ebx->getRegNum() == RegX8632::Reg_ebx);
266 addSource(Addr);
267 addSource(Edx);
268 addSource(Eax);
269 addSource(Ecx);
270 addSource(Ebx);
271 }
272
273 InstX8632Cvt::InstX8632Cvt(Cfg *Func, Variable *Dest, Operand *Source,
274 CvtVariant Variant)
275 : InstX8632(Func, InstX8632::Cvt, 1, Dest), Variant(Variant) {
276 addSource(Source);
277 }
278
279 InstX8632Icmp::InstX8632Icmp(Cfg *Func, Operand *Src0, Operand *Src1)
280 : InstX8632(Func, InstX8632::Icmp, 2, nullptr) {
281 addSource(Src0);
282 addSource(Src1);
283 }
284
285 InstX8632Ucomiss::InstX8632Ucomiss(Cfg *Func, Operand *Src0, Operand *Src1)
286 : InstX8632(Func, InstX8632::Ucomiss, 2, nullptr) {
287 addSource(Src0);
288 addSource(Src1);
289 }
290
291 InstX8632UD2::InstX8632UD2(Cfg *Func)
292 : InstX8632(Func, InstX8632::UD2, 0, nullptr) {}
293
294 InstX8632Test::InstX8632Test(Cfg *Func, Operand *Src1, Operand *Src2)
295 : InstX8632(Func, InstX8632::Test, 2, nullptr) {
296 addSource(Src1);
297 addSource(Src2);
298 }
299
300 InstX8632Mfence::InstX8632Mfence(Cfg *Func)
301 : InstX8632(Func, InstX8632::Mfence, 0, nullptr) {
302 HasSideEffects = true;
303 }
304
305 InstX8632Store::InstX8632Store(Cfg *Func, Operand *Value, OperandX8632 *Mem)
306 : InstX8632(Func, InstX8632::Store, 2, nullptr) {
307 addSource(Value);
308 addSource(Mem);
309 }
310
311 InstX8632StoreP::InstX8632StoreP(Cfg *Func, Variable *Value,
312 OperandX8632Mem *Mem)
313 : InstX8632(Func, InstX8632::StoreP, 2, nullptr) {
314 addSource(Value);
315 addSource(Mem);
316 }
317
318 InstX8632StoreQ::InstX8632StoreQ(Cfg *Func, Variable *Value,
319 OperandX8632Mem *Mem)
320 : InstX8632(Func, InstX8632::StoreQ, 2, nullptr) {
321 addSource(Value);
322 addSource(Mem);
323 }
324
325 InstX8632Nop::InstX8632Nop(Cfg *Func, InstX8632Nop::NopVariant Variant)
326 : InstX8632(Func, InstX8632::Nop, 0, nullptr), Variant(Variant) {}
327
328 InstX8632Fld::InstX8632Fld(Cfg *Func, Operand *Src)
329 : InstX8632(Func, InstX8632::Fld, 1, nullptr) {
330 addSource(Src);
331 }
332
333 InstX8632Fstp::InstX8632Fstp(Cfg *Func, Variable *Dest)
334 : InstX8632(Func, InstX8632::Fstp, 0, Dest) {}
335
336 InstX8632Pop::InstX8632Pop(Cfg *Func, Variable *Dest)
337 : InstX8632(Func, InstX8632::Pop, 0, Dest) {
338 // A pop instruction affects the stack pointer and so it should not
339 // be allowed to be automatically dead-code eliminated. (The
340 // corresponding push instruction doesn't need this treatment
341 // because it has no dest variable and therefore won't be dead-code
342 // eliminated.) This is needed for late-stage liveness analysis
343 // (e.g. asm-verbose mode).
344 HasSideEffects = true;
345 }
346
347 InstX8632Push::InstX8632Push(Cfg *Func, Variable *Source)
348 : InstX8632(Func, InstX8632::Push, 1, nullptr) {
349 addSource(Source);
350 }
351
352 InstX8632Ret::InstX8632Ret(Cfg *Func, Variable *Source)
353 : InstX8632(Func, InstX8632::Ret, Source ? 1 : 0, nullptr) {
354 if (Source)
355 addSource(Source);
356 }
357
358 InstX8632Setcc::InstX8632Setcc(Cfg *Func, Variable *Dest,
359 X8632::Traits::Cond::BrCond Cond)
360 : InstX8632(Func, InstX8632::Setcc, 0, Dest), Condition(Cond) {}
361
362 InstX8632Xadd::InstX8632Xadd(Cfg *Func, Operand *Dest, Variable *Source,
363 bool Locked)
364 : InstX8632Lockable(Func, InstX8632::Xadd, 2,
365 llvm::dyn_cast<Variable>(Dest), Locked) {
366 addSource(Dest);
367 addSource(Source);
368 }
369
370 InstX8632Xchg::InstX8632Xchg(Cfg *Func, Operand *Dest, Variable *Source)
371 : InstX8632(Func, InstX8632::Xchg, 2, llvm::dyn_cast<Variable>(Dest)) {
372 addSource(Dest);
373 addSource(Source);
374 }
375
376 // ======================== Dump routines ======================== //
377
378 void InstX8632::dump(const Cfg *Func) const {
379 if (!BuildDefs::dump())
380 return;
381 Ostream &Str = Func->getContext()->getStrDump();
382 Str << "[X8632] ";
383 Inst::dump(Func);
384 }
385
386 void InstX8632FakeRMW::dump(const Cfg *Func) const {
387 if (!BuildDefs::dump())
388 return;
389 Ostream &Str = Func->getContext()->getStrDump();
390 Type Ty = getData()->getType();
391 Str << "rmw " << InstArithmetic::getOpName(getOp()) << " " << Ty << " *";
392 getAddr()->dump(Func);
393 Str << ", ";
394 getData()->dump(Func);
395 Str << ", beacon=";
396 getBeacon()->dump(Func);
397 }
398
399 void InstX8632Label::emit(const Cfg *Func) const {
400 if (!BuildDefs::dump())
401 return;
402 Ostream &Str = Func->getContext()->getStrEmit();
403 Str << getName(Func) << ":";
404 }
405
406 void InstX8632Label::emitIAS(const Cfg *Func) const {
407 X8632::AssemblerX8632 *Asm = Func->getAssembler<X8632::AssemblerX8632>();
408 Asm->BindLocalLabel(Number);
409 }
410
411 void InstX8632Label::dump(const Cfg *Func) const {
412 if (!BuildDefs::dump())
413 return;
414 Ostream &Str = Func->getContext()->getStrDump();
415 Str << getName(Func) << ":";
416 }
417
418 void InstX8632Br::emit(const Cfg *Func) const {
419 if (!BuildDefs::dump())
420 return;
421 Ostream &Str = Func->getContext()->getStrEmit();
422 Str << "\t";
423
424 if (Condition == X8632::Traits::Cond::Br_None) {
425 Str << "jmp";
426 } else {
427 Str << InstX8632BrAttributes[Condition].EmitString;
428 }
429
430 if (Label) {
431 Str << "\t" << Label->getName(Func);
432 } else {
433 if (Condition == X8632::Traits::Cond::Br_None) {
434 Str << "\t" << getTargetFalse()->getAsmName();
435 } else {
436 Str << "\t" << getTargetTrue()->getAsmName();
437 if (getTargetFalse()) {
438 Str << "\n\tjmp\t" << getTargetFalse()->getAsmName();
439 }
440 }
441 }
442 }
443
444 void InstX8632Br::emitIAS(const Cfg *Func) const {
445 X8632::AssemblerX8632 *Asm = Func->getAssembler<X8632::AssemblerX8632>();
446 if (Label) {
447 X8632::Label *L = Asm->GetOrCreateLocalLabel(Label->getNumber());
448 // In all these cases, local Labels should only be used for Near.
449 const bool Near = true;
450 if (Condition == X8632::Traits::Cond::Br_None) {
451 Asm->jmp(L, Near);
452 } else {
453 Asm->j(Condition, L, Near);
454 }
455 } else {
456 // Pessimistically assume it's far. This only affects Labels that
457 // are not Bound.
458 const bool Near = false;
459 if (Condition == X8632::Traits::Cond::Br_None) {
460 X8632::Label *L =
461 Asm->GetOrCreateCfgNodeLabel(getTargetFalse()->getIndex());
462 assert(!getTargetTrue());
463 Asm->jmp(L, Near);
464 } else {
465 X8632::Label *L =
466 Asm->GetOrCreateCfgNodeLabel(getTargetTrue()->getIndex());
467 Asm->j(Condition, L, Near);
468 if (getTargetFalse()) {
469 X8632::Label *L2 =
470 Asm->GetOrCreateCfgNodeLabel(getTargetFalse()->getIndex());
471 Asm->jmp(L2, Near);
472 }
473 }
474 }
475 }
476
477 void InstX8632Br::dump(const Cfg *Func) const {
478 if (!BuildDefs::dump())
479 return;
480 Ostream &Str = Func->getContext()->getStrDump();
481 Str << "br ";
482
483 if (Condition == X8632::Traits::Cond::Br_None) {
484 Str << "label %"
485 << (Label ? Label->getName(Func) : getTargetFalse()->getName());
486 return;
487 }
488
489 Str << InstX8632BrAttributes[Condition].DisplayString;
490 if (Label) {
491 Str << ", label %" << Label->getName(Func);
492 } else {
493 Str << ", label %" << getTargetTrue()->getName();
494 if (getTargetFalse()) {
495 Str << ", label %" << getTargetFalse()->getName();
496 }
497 }
498 }
499
500 void InstX8632Jmp::emit(const Cfg *Func) const {
501 if (!BuildDefs::dump())
502 return;
503 Ostream &Str = Func->getContext()->getStrEmit();
504 assert(getSrcSize() == 1);
505 Str << "\tjmp\t*";
506 getJmpTarget()->emit(Func);
507 }
508
509 void InstX8632Jmp::emitIAS(const Cfg *Func) const {
510 // Note: Adapted (mostly copied) from InstX8632Call::emitIAS().
511 X8632::AssemblerX8632 *Asm = Func->getAssembler<X8632::AssemblerX8632>();
512 Operand *Target = getJmpTarget();
513 if (const auto Var = llvm::dyn_cast<Variable>(Target)) {
514 if (Var->hasReg()) {
515 Asm->jmp(RegX8632::getEncodedGPR(Var->getRegNum()));
516 } else {
517 // The jmp instruction with a memory operand should be possible
518 // to encode, but it isn't a valid sandboxed instruction, and
519 // there shouldn't be a register allocation issue to jump
520 // through a scratch register, so we don't really need to bother
521 // implementing it.
522 llvm::report_fatal_error("Assembler can't jmp to memory operand");
523 }
524 } else if (const auto Mem = llvm::dyn_cast<OperandX8632Mem>(Target)) {
525 (void)Mem;
526 assert(Mem->getSegmentRegister() == OperandX8632Mem::DefaultSegment);
527 llvm::report_fatal_error("Assembler can't jmp to memory operand");
528 } else if (const auto CR = llvm::dyn_cast<ConstantRelocatable>(Target)) {
529 assert(CR->getOffset() == 0 && "We only support jumping to a function");
530 Asm->jmp(CR);
531 } else if (const auto Imm = llvm::dyn_cast<ConstantInteger32>(Target)) {
532 // NaCl trampoline calls refer to an address within the sandbox directly.
533 // This is usually only needed for non-IRT builds and otherwise not
534 // very portable or stable. Usually this is only done for "calls"
535 // and not jumps.
536 // TODO(jvoung): Support this when there is a lowering that
537 // actually triggers this case.
538 (void)Imm;
539 llvm::report_fatal_error("Unexpected jmp to absolute address");
540 } else {
541 llvm::report_fatal_error("Unexpected operand type");
542 }
543 }
544
545 void InstX8632Jmp::dump(const Cfg *Func) const {
546 if (!BuildDefs::dump())
547 return;
548 Ostream &Str = Func->getContext()->getStrDump();
549 Str << "jmp ";
550 getJmpTarget()->dump(Func);
551 }
552
553 void InstX8632Call::emit(const Cfg *Func) const {
554 if (!BuildDefs::dump())
555 return;
556 Ostream &Str = Func->getContext()->getStrEmit();
557 assert(getSrcSize() == 1);
558 Str << "\tcall\t";
559 if (const auto CI = llvm::dyn_cast<ConstantInteger32>(getCallTarget())) {
560 // Emit without a leading '$'.
561 Str << CI->getValue();
562 } else if (const auto CallTarget =
563 llvm::dyn_cast<ConstantRelocatable>(getCallTarget())) {
564 CallTarget->emitWithoutPrefix(Func->getTarget());
565 } else {
566 Str << "*";
567 getCallTarget()->emit(Func);
568 }
569 Func->getTarget()->resetStackAdjustment();
570 }
571
572 void InstX8632Call::emitIAS(const Cfg *Func) const {
573 X8632::AssemblerX8632 *Asm = Func->getAssembler<X8632::AssemblerX8632>();
574 Operand *Target = getCallTarget();
575 if (const auto Var = llvm::dyn_cast<Variable>(Target)) {
576 if (Var->hasReg()) {
577 Asm->call(RegX8632::getEncodedGPR(Var->getRegNum()));
578 } else {
579 Asm->call(static_cast<TargetX8632 *>(Func->getTarget())
580 ->stackVarToAsmOperand(Var));
581 }
582 } else if (const auto Mem = llvm::dyn_cast<OperandX8632Mem>(Target)) {
583 assert(Mem->getSegmentRegister() == OperandX8632Mem::DefaultSegment);
584 Asm->call(Mem->toAsmAddress(Asm));
585 } else if (const auto CR = llvm::dyn_cast<ConstantRelocatable>(Target)) {
586 assert(CR->getOffset() == 0 && "We only support calling a function");
587 Asm->call(CR);
588 } else if (const auto Imm = llvm::dyn_cast<ConstantInteger32>(Target)) {
589 Asm->call(X8632::Immediate(Imm->getValue()));
590 } else {
591 llvm_unreachable("Unexpected operand type");
592 }
593 Func->getTarget()->resetStackAdjustment();
594 }
595
596 void InstX8632Call::dump(const Cfg *Func) const {
597 if (!BuildDefs::dump())
598 return;
599 Ostream &Str = Func->getContext()->getStrDump();
600 if (getDest()) {
601 dumpDest(Func);
602 Str << " = ";
603 }
604 Str << "call ";
605 getCallTarget()->dump(Func);
606 }
607
608 // The ShiftHack parameter is used to emit "cl" instead of "ecx" for
609 // shift instructions, in order to be syntactically valid. The
610 // Opcode parameter needs to be char* and not IceString because of
611 // template issues.
612 void InstX8632::emitTwoAddress(const char *Opcode, const Inst *Inst,
613 const Cfg *Func, bool ShiftHack) {
614 if (!BuildDefs::dump())
615 return;
616 Ostream &Str = Func->getContext()->getStrEmit();
617 assert(Inst->getSrcSize() == 2);
618 Operand *Dest = Inst->getDest();
619 if (Dest == nullptr)
620 Dest = Inst->getSrc(0);
621 assert(Dest == Inst->getSrc(0));
622 Operand *Src1 = Inst->getSrc(1);
623 Str << "\t" << Opcode << InstX8632::getWidthString(Dest->getType()) << "\t";
624 const auto ShiftReg = llvm::dyn_cast<Variable>(Src1);
625 if (ShiftHack && ShiftReg && ShiftReg->getRegNum() == RegX8632::Reg_ecx)
626 Str << "%cl";
627 else
628 Src1->emit(Func);
629 Str << ", ";
630 Dest->emit(Func);
631 }
632
633 void emitIASOpTyGPR(const Cfg *Func, Type Ty, const Operand *Op,
634 const X8632::AssemblerX8632::GPREmitterOneOp &Emitter) {
635 X8632::AssemblerX8632 *Asm = Func->getAssembler<X8632::AssemblerX8632>();
636 if (const auto Var = llvm::dyn_cast<Variable>(Op)) {
637 if (Var->hasReg()) {
638 // We cheat a little and use GPRRegister even for byte operations.
639 RegX8632::GPRRegister VarReg =
640 RegX8632::getEncodedByteRegOrGPR(Ty, Var->getRegNum());
641 (Asm->*(Emitter.Reg))(Ty, VarReg);
642 } else {
643 X8632::Traits::Address StackAddr(
644 static_cast<TargetX8632 *>(Func->getTarget())
645 ->stackVarToAsmOperand(Var));
646 (Asm->*(Emitter.Addr))(Ty, StackAddr);
647 }
648 } else if (const auto Mem = llvm::dyn_cast<OperandX8632Mem>(Op)) {
649 Mem->emitSegmentOverride(Asm);
650 (Asm->*(Emitter.Addr))(Ty, Mem->toAsmAddress(Asm));
651 } else {
652 llvm_unreachable("Unexpected operand type");
653 }
654 }
655
656 template <bool VarCanBeByte, bool SrcCanBeByte>
657 void emitIASRegOpTyGPR(const Cfg *Func, Type Ty, const Variable *Var,
658 const Operand *Src,
659 const X8632::AssemblerX8632::GPREmitterRegOp &Emitter) {
660 X8632::AssemblerX8632 *Asm = Func->getAssembler<X8632::AssemblerX8632>();
661 assert(Var->hasReg());
662 // We cheat a little and use GPRRegister even for byte operations.
663 RegX8632::GPRRegister VarReg =
664 VarCanBeByte ? RegX8632::getEncodedByteRegOrGPR(Ty, Var->getRegNum())
665 : RegX8632::getEncodedGPR(Var->getRegNum());
666 if (const auto SrcVar = llvm::dyn_cast<Variable>(Src)) {
667 if (SrcVar->hasReg()) {
668 RegX8632::GPRRegister SrcReg =
669 SrcCanBeByte
670 ? RegX8632::getEncodedByteRegOrGPR(Ty, SrcVar->getRegNum())
671 : RegX8632::getEncodedGPR(SrcVar->getRegNum());
672 (Asm->*(Emitter.GPRGPR))(Ty, VarReg, SrcReg);
673 } else {
674 X8632::Traits::Address SrcStackAddr =
675 static_cast<TargetX8632 *>(Func->getTarget())
676 ->stackVarToAsmOperand(SrcVar);
677 (Asm->*(Emitter.GPRAddr))(Ty, VarReg, SrcStackAddr);
678 }
679 } else if (const auto Mem = llvm::dyn_cast<OperandX8632Mem>(Src)) {
680 Mem->emitSegmentOverride(Asm);
681 (Asm->*(Emitter.GPRAddr))(Ty, VarReg, Mem->toAsmAddress(Asm));
682 } else if (const auto Imm = llvm::dyn_cast<ConstantInteger32>(Src)) {
683 (Asm->*(Emitter.GPRImm))(Ty, VarReg, X8632::Immediate(Imm->getValue()));
684 } else if (const auto Reloc = llvm::dyn_cast<ConstantRelocatable>(Src)) {
685 AssemblerFixup *Fixup = Asm->createFixup(llvm::ELF::R_386_32, Reloc);
686 (Asm->*(Emitter.GPRImm))(Ty, VarReg,
687 X8632::Immediate(Reloc->getOffset(), Fixup));
688 } else if (const auto Split = llvm::dyn_cast<VariableSplit>(Src)) {
689 (Asm->*(Emitter.GPRAddr))(Ty, VarReg, Split->toAsmAddress(Func));
690 } else {
691 llvm_unreachable("Unexpected operand type");
692 }
693 }
694
695 void emitIASAddrOpTyGPR(
696 const Cfg *Func, Type Ty, const X8632::Traits::Address &Addr,
697 const Operand *Src,
698 const X8632::AssemblerX8632::GPREmitterAddrOp &Emitter) {
699 X8632::AssemblerX8632 *Asm = Func->getAssembler<X8632::AssemblerX8632>();
700 // Src can only be Reg or Immediate.
701 if (const auto SrcVar = llvm::dyn_cast<Variable>(Src)) {
702 assert(SrcVar->hasReg());
703 RegX8632::GPRRegister SrcReg =
704 RegX8632::getEncodedByteRegOrGPR(Ty, SrcVar->getRegNum());
705 (Asm->*(Emitter.AddrGPR))(Ty, Addr, SrcReg);
706 } else if (const auto Imm = llvm::dyn_cast<ConstantInteger32>(Src)) {
707 (Asm->*(Emitter.AddrImm))(Ty, Addr, X8632::Immediate(Imm->getValue()));
708 } else if (const auto Reloc = llvm::dyn_cast<ConstantRelocatable>(Src)) {
709 AssemblerFixup *Fixup = Asm->createFixup(llvm::ELF::R_386_32, Reloc);
710 (Asm->*(Emitter.AddrImm))(Ty, Addr,
711 X8632::Immediate(Reloc->getOffset(), Fixup));
712 } else {
713 llvm_unreachable("Unexpected operand type");
714 }
715 }
716
717 void emitIASAsAddrOpTyGPR(
718 const Cfg *Func, Type Ty, const Operand *Op0, const Operand *Op1,
719 const X8632::AssemblerX8632::GPREmitterAddrOp &Emitter) {
720 if (const auto Op0Var = llvm::dyn_cast<Variable>(Op0)) {
721 assert(!Op0Var->hasReg());
722 X8632::Traits::Address StackAddr(
723 static_cast<TargetX8632 *>(Func->getTarget())
724 ->stackVarToAsmOperand(Op0Var));
725 emitIASAddrOpTyGPR(Func, Ty, StackAddr, Op1, Emitter);
726 } else if (const auto Op0Mem = llvm::dyn_cast<OperandX8632Mem>(Op0)) {
727 X8632::AssemblerX8632 *Asm = Func->getAssembler<X8632::AssemblerX8632>();
728 Op0Mem->emitSegmentOverride(Asm);
729 emitIASAddrOpTyGPR(Func, Ty, Op0Mem->toAsmAddress(Asm), Op1, Emitter);
730 } else if (const auto Split = llvm::dyn_cast<VariableSplit>(Op0)) {
731 emitIASAddrOpTyGPR(Func, Ty, Split->toAsmAddress(Func), Op1, Emitter);
732 } else {
733 llvm_unreachable("Unexpected operand type");
734 }
735 }
736
737 void InstX8632::emitIASGPRShift(
738 const Cfg *Func, Type Ty, const Variable *Var, const Operand *Src,
739 const X8632::AssemblerX8632::GPREmitterShiftOp &Emitter) {
740 X8632::AssemblerX8632 *Asm = Func->getAssembler<X8632::AssemblerX8632>();
741 // Technically, the Dest Var can be mem as well, but we only use Reg.
742 // We can extend this to check Dest if we decide to use that form.
743 assert(Var->hasReg());
744 // We cheat a little and use GPRRegister even for byte operations.
745 RegX8632::GPRRegister VarReg =
746 RegX8632::getEncodedByteRegOrGPR(Ty, Var->getRegNum());
747 // Src must be reg == ECX or an Imm8.
748 // This is asserted by the assembler.
749 if (const auto SrcVar = llvm::dyn_cast<Variable>(Src)) {
750 assert(SrcVar->hasReg());
751 RegX8632::GPRRegister SrcReg =
752 RegX8632::getEncodedByteRegOrGPR(Ty, SrcVar->getRegNum());
753 (Asm->*(Emitter.GPRGPR))(Ty, VarReg, SrcReg);
754 } else if (const auto Imm = llvm::dyn_cast<ConstantInteger32>(Src)) {
755 (Asm->*(Emitter.GPRImm))(Ty, VarReg, X8632::Immediate(Imm->getValue()));
756 } else {
757 llvm_unreachable("Unexpected operand type");
758 }
759 }
760
761 void emitIASGPRShiftDouble(
762 const Cfg *Func, const Variable *Dest, const Operand *Src1Op,
763 const Operand *Src2Op,
764 const X8632::AssemblerX8632::GPREmitterShiftD &Emitter) {
765 X8632::AssemblerX8632 *Asm = Func->getAssembler<X8632::AssemblerX8632>();
766 // Dest can be reg or mem, but we only use the reg variant.
767 assert(Dest->hasReg());
768 RegX8632::GPRRegister DestReg = RegX8632::getEncodedGPR(Dest->getRegNum());
769 // SrcVar1 must be reg.
770 const auto SrcVar1 = llvm::cast<Variable>(Src1Op);
771 assert(SrcVar1->hasReg());
772 RegX8632::GPRRegister SrcReg = RegX8632::getEncodedGPR(SrcVar1->getRegNum());
773 Type Ty = SrcVar1->getType();
774 // Src2 can be the implicit CL register or an immediate.
775 if (const auto Imm = llvm::dyn_cast<ConstantInteger32>(Src2Op)) {
776 (Asm->*(Emitter.GPRGPRImm))(Ty, DestReg, SrcReg,
777 X8632::Immediate(Imm->getValue()));
778 } else {
779 assert(llvm::cast<Variable>(Src2Op)->getRegNum() == RegX8632::Reg_ecx);
780 (Asm->*(Emitter.GPRGPR))(Ty, DestReg, SrcReg);
781 }
782 }
783
784 void emitIASXmmShift(const Cfg *Func, Type Ty, const Variable *Var,
785 const Operand *Src,
786 const X8632::AssemblerX8632::XmmEmitterShiftOp &Emitter) {
787 X8632::AssemblerX8632 *Asm = Func->getAssembler<X8632::AssemblerX8632>();
788 assert(Var->hasReg());
789 RegX8632::XmmRegister VarReg = RegX8632::getEncodedXmm(Var->getRegNum());
790 if (const auto SrcVar = llvm::dyn_cast<Variable>(Src)) {
791 if (SrcVar->hasReg()) {
792 RegX8632::XmmRegister SrcReg =
793 RegX8632::getEncodedXmm(SrcVar->getRegNum());
794 (Asm->*(Emitter.XmmXmm))(Ty, VarReg, SrcReg);
795 } else {
796 X8632::Traits::Address SrcStackAddr =
797 static_cast<TargetX8632 *>(Func->getTarget())
798 ->stackVarToAsmOperand(SrcVar);
799 (Asm->*(Emitter.XmmAddr))(Ty, VarReg, SrcStackAddr);
800 }
801 } else if (const auto Mem = llvm::dyn_cast<OperandX8632Mem>(Src)) {
802 assert(Mem->getSegmentRegister() == OperandX8632Mem::DefaultSegment);
803 (Asm->*(Emitter.XmmAddr))(Ty, VarReg, Mem->toAsmAddress(Asm));
804 } else if (const auto Imm = llvm::dyn_cast<ConstantInteger32>(Src)) {
805 (Asm->*(Emitter.XmmImm))(Ty, VarReg, X8632::Immediate(Imm->getValue()));
806 } else {
807 llvm_unreachable("Unexpected operand type");
808 }
809 }
810
811 void emitIASRegOpTyXMM(const Cfg *Func, Type Ty, const Variable *Var,
812 const Operand *Src,
813 const X8632::AssemblerX8632::XmmEmitterRegOp &Emitter) {
814 X8632::AssemblerX8632 *Asm = Func->getAssembler<X8632::AssemblerX8632>();
815 assert(Var->hasReg());
816 RegX8632::XmmRegister VarReg = RegX8632::getEncodedXmm(Var->getRegNum());
817 if (const auto SrcVar = llvm::dyn_cast<Variable>(Src)) {
818 if (SrcVar->hasReg()) {
819 RegX8632::XmmRegister SrcReg =
820 RegX8632::getEncodedXmm(SrcVar->getRegNum());
821 (Asm->*(Emitter.XmmXmm))(Ty, VarReg, SrcReg);
822 } else {
823 X8632::Traits::Address SrcStackAddr =
824 static_cast<TargetX8632 *>(Func->getTarget())
825 ->stackVarToAsmOperand(SrcVar);
826 (Asm->*(Emitter.XmmAddr))(Ty, VarReg, SrcStackAddr);
827 }
828 } else if (const auto Mem = llvm::dyn_cast<OperandX8632Mem>(Src)) {
829 assert(Mem->getSegmentRegister() == OperandX8632Mem::DefaultSegment);
830 (Asm->*(Emitter.XmmAddr))(Ty, VarReg, Mem->toAsmAddress(Asm));
831 } else if (const auto Imm = llvm::dyn_cast<Constant>(Src)) {
832 (Asm->*(Emitter.XmmAddr))(Ty, VarReg,
833 X8632::Traits::Address::ofConstPool(Asm, Imm));
834 } else {
835 llvm_unreachable("Unexpected operand type");
836 }
837 }
838
839 template <typename DReg_t, typename SReg_t, DReg_t (*destEnc)(int32_t),
840 SReg_t (*srcEnc)(int32_t)>
841 void emitIASCastRegOp(
842 const Cfg *Func, Type DispatchTy, const Variable *Dest, const Operand *Src,
843 const X8632::AssemblerX8632::CastEmitterRegOp<DReg_t, SReg_t> Emitter) {
844 X8632::AssemblerX8632 *Asm = Func->getAssembler<X8632::AssemblerX8632>();
845 assert(Dest->hasReg());
846 DReg_t DestReg = destEnc(Dest->getRegNum());
847 if (const auto SrcVar = llvm::dyn_cast<Variable>(Src)) {
848 if (SrcVar->hasReg()) {
849 SReg_t SrcReg = srcEnc(SrcVar->getRegNum());
850 (Asm->*(Emitter.RegReg))(DispatchTy, DestReg, SrcReg);
851 } else {
852 X8632::Traits::Address SrcStackAddr =
853 static_cast<TargetX8632 *>(Func->getTarget())
854 ->stackVarToAsmOperand(SrcVar);
855 (Asm->*(Emitter.RegAddr))(DispatchTy, DestReg, SrcStackAddr);
856 }
857 } else if (const auto Mem = llvm::dyn_cast<OperandX8632Mem>(Src)) {
858 Mem->emitSegmentOverride(Asm);
859 (Asm->*(Emitter.RegAddr))(DispatchTy, DestReg, Mem->toAsmAddress(Asm));
860 } else {
861 llvm_unreachable("Unexpected operand type");
862 }
863 }
864
865 template <typename DReg_t, typename SReg_t, DReg_t (*destEnc)(int32_t),
866 SReg_t (*srcEnc)(int32_t)>
867 void emitIASThreeOpImmOps(
868 const Cfg *Func, Type DispatchTy, const Variable *Dest, const Operand *Src0,
869 const Operand *Src1,
870 const X8632::AssemblerX8632::ThreeOpImmEmitter<DReg_t, SReg_t> Emitter) {
871 X8632::AssemblerX8632 *Asm = Func->getAssembler<X8632::AssemblerX8632>();
872 // This only handles Dest being a register, and Src1 being an immediate.
873 assert(Dest->hasReg());
874 DReg_t DestReg = destEnc(Dest->getRegNum());
875 X8632::Immediate Imm(llvm::cast<ConstantInteger32>(Src1)->getValue());
876 if (const auto SrcVar = llvm::dyn_cast<Variable>(Src0)) {
877 if (SrcVar->hasReg()) {
878 SReg_t SrcReg = srcEnc(SrcVar->getRegNum());
879 (Asm->*(Emitter.RegRegImm))(DispatchTy, DestReg, SrcReg, Imm);
880 } else {
881 X8632::Traits::Address SrcStackAddr =
882 static_cast<TargetX8632 *>(Func->getTarget())
883 ->stackVarToAsmOperand(SrcVar);
884 (Asm->*(Emitter.RegAddrImm))(DispatchTy, DestReg, SrcStackAddr, Imm);
885 }
886 } else if (const auto Mem = llvm::dyn_cast<OperandX8632Mem>(Src0)) {
887 Mem->emitSegmentOverride(Asm);
888 (Asm->*(Emitter.RegAddrImm))(DispatchTy, DestReg, Mem->toAsmAddress(Asm),
889 Imm);
890 } else {
891 llvm_unreachable("Unexpected operand type");
892 }
893 }
894
895 void emitIASMovlikeXMM(const Cfg *Func, const Variable *Dest,
896 const Operand *Src,
897 const X8632::AssemblerX8632::XmmEmitterMovOps Emitter) {
898 X8632::AssemblerX8632 *Asm = Func->getAssembler<X8632::AssemblerX8632>();
899 if (Dest->hasReg()) {
900 RegX8632::XmmRegister DestReg = RegX8632::getEncodedXmm(Dest->getRegNum());
901 if (const auto SrcVar = llvm::dyn_cast<Variable>(Src)) {
902 if (SrcVar->hasReg()) {
903 (Asm->*(Emitter.XmmXmm))(DestReg,
904 RegX8632::getEncodedXmm(SrcVar->getRegNum()));
905 } else {
906 X8632::Traits::Address StackAddr(
907 static_cast<TargetX8632 *>(Func->getTarget())
908 ->stackVarToAsmOperand(SrcVar));
909 (Asm->*(Emitter.XmmAddr))(DestReg, StackAddr);
910 }
911 } else if (const auto SrcMem = llvm::dyn_cast<OperandX8632Mem>(Src)) {
912 assert(SrcMem->getSegmentRegister() == OperandX8632Mem::DefaultSegment);
913 (Asm->*(Emitter.XmmAddr))(DestReg, SrcMem->toAsmAddress(Asm));
914 } else {
915 llvm_unreachable("Unexpected operand type");
916 }
917 } else {
918 X8632::Traits::Address StackAddr(
919 static_cast<TargetX8632 *>(Func->getTarget())
920 ->stackVarToAsmOperand(Dest));
921 // Src must be a register in this case.
922 const auto SrcVar = llvm::cast<Variable>(Src);
923 assert(SrcVar->hasReg());
924 (Asm->*(Emitter.AddrXmm))(StackAddr,
925 RegX8632::getEncodedXmm(SrcVar->getRegNum()));
926 }
927 }
928
929 // In-place ops
930 template <> const char *InstX8632Bswap::Opcode = "bswap";
931 template <> const char *InstX8632Neg::Opcode = "neg";
932 // Unary ops
933 template <> const char *InstX8632Bsf::Opcode = "bsf";
934 template <> const char *InstX8632Bsr::Opcode = "bsr";
935 template <> const char *InstX8632Lea::Opcode = "lea";
936 template <> const char *InstX8632Movd::Opcode = "movd";
937 template <> const char *InstX8632Movsx::Opcode = "movs";
938 template <> const char *InstX8632Movzx::Opcode = "movz";
939 template <> const char *InstX8632Sqrtss::Opcode = "sqrtss";
940 template <> const char *InstX8632Cbwdq::Opcode = "cbw/cwd/cdq";
941 // Mov-like ops
942 template <> const char *InstX8632Mov::Opcode = "mov";
943 template <> const char *InstX8632Movp::Opcode = "movups";
944 template <> const char *InstX8632Movq::Opcode = "movq";
945 // Binary ops
946 template <> const char *InstX8632Add::Opcode = "add";
947 template <> const char *InstX8632AddRMW::Opcode = "add";
948 template <> const char *InstX8632Addps::Opcode = "addps";
949 template <> const char *InstX8632Adc::Opcode = "adc";
950 template <> const char *InstX8632AdcRMW::Opcode = "adc";
951 template <> const char *InstX8632Addss::Opcode = "addss";
952 template <> const char *InstX8632Padd::Opcode = "padd";
953 template <> const char *InstX8632Sub::Opcode = "sub";
954 template <> const char *InstX8632SubRMW::Opcode = "sub";
955 template <> const char *InstX8632Subps::Opcode = "subps";
956 template <> const char *InstX8632Subss::Opcode = "subss";
957 template <> const char *InstX8632Sbb::Opcode = "sbb";
958 template <> const char *InstX8632SbbRMW::Opcode = "sbb";
959 template <> const char *InstX8632Psub::Opcode = "psub";
960 template <> const char *InstX8632And::Opcode = "and";
961 template <> const char *InstX8632AndRMW::Opcode = "and";
962 template <> const char *InstX8632Pand::Opcode = "pand";
963 template <> const char *InstX8632Pandn::Opcode = "pandn";
964 template <> const char *InstX8632Or::Opcode = "or";
965 template <> const char *InstX8632OrRMW::Opcode = "or";
966 template <> const char *InstX8632Por::Opcode = "por";
967 template <> const char *InstX8632Xor::Opcode = "xor";
968 template <> const char *InstX8632XorRMW::Opcode = "xor";
969 template <> const char *InstX8632Pxor::Opcode = "pxor";
970 template <> const char *InstX8632Imul::Opcode = "imul";
971 template <> const char *InstX8632Mulps::Opcode = "mulps";
972 template <> const char *InstX8632Mulss::Opcode = "mulss";
973 template <> const char *InstX8632Pmull::Opcode = "pmull";
974 template <> const char *InstX8632Pmuludq::Opcode = "pmuludq";
975 template <> const char *InstX8632Div::Opcode = "div";
976 template <> const char *InstX8632Divps::Opcode = "divps";
977 template <> const char *InstX8632Idiv::Opcode = "idiv";
978 template <> const char *InstX8632Divss::Opcode = "divss";
979 template <> const char *InstX8632Rol::Opcode = "rol";
980 template <> const char *InstX8632Shl::Opcode = "shl";
981 template <> const char *InstX8632Psll::Opcode = "psll";
982 template <> const char *InstX8632Shr::Opcode = "shr";
983 template <> const char *InstX8632Sar::Opcode = "sar";
984 template <> const char *InstX8632Psra::Opcode = "psra";
985 template <> const char *InstX8632Psrl::Opcode = "psrl";
986 template <> const char *InstX8632Pcmpeq::Opcode = "pcmpeq";
987 template <> const char *InstX8632Pcmpgt::Opcode = "pcmpgt";
988 template <> const char *InstX8632MovssRegs::Opcode = "movss";
989 // Ternary ops
990 template <> const char *InstX8632Insertps::Opcode = "insertps";
991 template <> const char *InstX8632Shufps::Opcode = "shufps";
992 template <> const char *InstX8632Pinsr::Opcode = "pinsr";
993 template <> const char *InstX8632Blendvps::Opcode = "blendvps";
994 template <> const char *InstX8632Pblendvb::Opcode = "pblendvb";
995 // Three address ops
996 template <> const char *InstX8632Pextr::Opcode = "pextr";
997 template <> const char *InstX8632Pshufd::Opcode = "pshufd";
998
999 // Inplace GPR ops
1000 template <>
1001 const X8632::AssemblerX8632::GPREmitterOneOp InstX8632Bswap::Emitter = {
1002 &X8632::AssemblerX8632::bswap, nullptr /* only a reg form exists */
1003 };
1004 template <>
1005 const X8632::AssemblerX8632::GPREmitterOneOp InstX8632Neg::Emitter = {
1006 &X8632::AssemblerX8632::neg, &X8632::AssemblerX8632::neg};
1007
1008 // Unary GPR ops
1009 template <>
1010 const X8632::AssemblerX8632::GPREmitterRegOp InstX8632Bsf::Emitter = {
1011 &X8632::AssemblerX8632::bsf, &X8632::AssemblerX8632::bsf, nullptr};
1012 template <>
1013 const X8632::AssemblerX8632::GPREmitterRegOp InstX8632Bsr::Emitter = {
1014 &X8632::AssemblerX8632::bsr, &X8632::AssemblerX8632::bsr, nullptr};
1015 template <>
1016 const X8632::AssemblerX8632::GPREmitterRegOp InstX8632Lea::Emitter = {
1017 /* reg/reg and reg/imm are illegal */ nullptr, &X8632::AssemblerX8632::lea,
1018 nullptr};
1019 template <>
1020 const X8632::AssemblerX8632::GPREmitterRegOp InstX8632Movsx::Emitter = {
1021 &X8632::AssemblerX8632::movsx, &X8632::AssemblerX8632::movsx, nullptr};
1022 template <>
1023 const X8632::AssemblerX8632::GPREmitterRegOp InstX8632Movzx::Emitter = {
1024 &X8632::AssemblerX8632::movzx, &X8632::AssemblerX8632::movzx, nullptr};
1025
1026 // Unary XMM ops
1027 template <>
1028 const X8632::AssemblerX8632::XmmEmitterRegOp InstX8632Sqrtss::Emitter = {
1029 &X8632::AssemblerX8632::sqrtss, &X8632::AssemblerX8632::sqrtss};
1030
1031 // Binary GPR ops
1032 template <>
1033 const X8632::AssemblerX8632::GPREmitterRegOp InstX8632Add::Emitter = {
1034 &X8632::AssemblerX8632::add, &X8632::AssemblerX8632::add,
1035 &X8632::AssemblerX8632::add};
1036 template <>
1037 const X8632::AssemblerX8632::GPREmitterAddrOp InstX8632AddRMW::Emitter = {
1038 &X8632::AssemblerX8632::add, &X8632::AssemblerX8632::add};
1039 template <>
1040 const X8632::AssemblerX8632::GPREmitterRegOp InstX8632Adc::Emitter = {
1041 &X8632::AssemblerX8632::adc, &X8632::AssemblerX8632::adc,
1042 &X8632::AssemblerX8632::adc};
1043 template <>
1044 const X8632::AssemblerX8632::GPREmitterAddrOp InstX8632AdcRMW::Emitter = {
1045 &X8632::AssemblerX8632::adc, &X8632::AssemblerX8632::adc};
1046 template <>
1047 const X8632::AssemblerX8632::GPREmitterRegOp InstX8632And::Emitter = {
1048 &X8632::AssemblerX8632::And, &X8632::AssemblerX8632::And,
1049 &X8632::AssemblerX8632::And};
1050 template <>
1051 const X8632::AssemblerX8632::GPREmitterAddrOp InstX8632AndRMW::Emitter = {
1052 &X8632::AssemblerX8632::And, &X8632::AssemblerX8632::And};
1053 template <>
1054 const X8632::AssemblerX8632::GPREmitterRegOp InstX8632Or::Emitter = {
1055 &X8632::AssemblerX8632::Or, &X8632::AssemblerX8632::Or,
1056 &X8632::AssemblerX8632::Or};
1057 template <>
1058 const X8632::AssemblerX8632::GPREmitterAddrOp InstX8632OrRMW::Emitter = {
1059 &X8632::AssemblerX8632::Or, &X8632::AssemblerX8632::Or};
1060 template <>
1061 const X8632::AssemblerX8632::GPREmitterRegOp InstX8632Sbb::Emitter = {
1062 &X8632::AssemblerX8632::sbb, &X8632::AssemblerX8632::sbb,
1063 &X8632::AssemblerX8632::sbb};
1064 template <>
1065 const X8632::AssemblerX8632::GPREmitterAddrOp InstX8632SbbRMW::Emitter = {
1066 &X8632::AssemblerX8632::sbb, &X8632::AssemblerX8632::sbb};
1067 template <>
1068 const X8632::AssemblerX8632::GPREmitterRegOp InstX8632Sub::Emitter = {
1069 &X8632::AssemblerX8632::sub, &X8632::AssemblerX8632::sub,
1070 &X8632::AssemblerX8632::sub};
1071 template <>
1072 const X8632::AssemblerX8632::GPREmitterAddrOp InstX8632SubRMW::Emitter = {
1073 &X8632::AssemblerX8632::sub, &X8632::AssemblerX8632::sub};
1074 template <>
1075 const X8632::AssemblerX8632::GPREmitterRegOp InstX8632Xor::Emitter = {
1076 &X8632::AssemblerX8632::Xor, &X8632::AssemblerX8632::Xor,
1077 &X8632::AssemblerX8632::Xor};
1078 template <>
1079 const X8632::AssemblerX8632::GPREmitterAddrOp InstX8632XorRMW::Emitter = {
1080 &X8632::AssemblerX8632::Xor, &X8632::AssemblerX8632::Xor};
1081
1082 // Binary Shift GPR ops
1083 template <>
1084 const X8632::AssemblerX8632::GPREmitterShiftOp InstX8632Rol::Emitter = {
1085 &X8632::AssemblerX8632::rol, &X8632::AssemblerX8632::rol};
1086 template <>
1087 const X8632::AssemblerX8632::GPREmitterShiftOp InstX8632Sar::Emitter = {
1088 &X8632::AssemblerX8632::sar, &X8632::AssemblerX8632::sar};
1089 template <>
1090 const X8632::AssemblerX8632::GPREmitterShiftOp InstX8632Shl::Emitter = {
1091 &X8632::AssemblerX8632::shl, &X8632::AssemblerX8632::shl};
1092 template <>
1093 const X8632::AssemblerX8632::GPREmitterShiftOp InstX8632Shr::Emitter = {
1094 &X8632::AssemblerX8632::shr, &X8632::AssemblerX8632::shr};
1095
1096 // Binary XMM ops
1097 template <>
1098 const X8632::AssemblerX8632::XmmEmitterRegOp InstX8632Addss::Emitter = {
1099 &X8632::AssemblerX8632::addss, &X8632::AssemblerX8632::addss};
1100 template <>
1101 const X8632::AssemblerX8632::XmmEmitterRegOp InstX8632Addps::Emitter = {
1102 &X8632::AssemblerX8632::addps, &X8632::AssemblerX8632::addps};
1103 template <>
1104 const X8632::AssemblerX8632::XmmEmitterRegOp InstX8632Divss::Emitter = {
1105 &X8632::AssemblerX8632::divss, &X8632::AssemblerX8632::divss};
1106 template <>
1107 const X8632::AssemblerX8632::XmmEmitterRegOp InstX8632Divps::Emitter = {
1108 &X8632::AssemblerX8632::divps, &X8632::AssemblerX8632::divps};
1109 template <>
1110 const X8632::AssemblerX8632::XmmEmitterRegOp InstX8632Mulss::Emitter = {
1111 &X8632::AssemblerX8632::mulss, &X8632::AssemblerX8632::mulss};
1112 template <>
1113 const X8632::AssemblerX8632::XmmEmitterRegOp InstX8632Mulps::Emitter = {
1114 &X8632::AssemblerX8632::mulps, &X8632::AssemblerX8632::mulps};
1115 template <>
1116 const X8632::AssemblerX8632::XmmEmitterRegOp InstX8632Padd::Emitter = {
1117 &X8632::AssemblerX8632::padd, &X8632::AssemblerX8632::padd};
1118 template <>
1119 const X8632::AssemblerX8632::XmmEmitterRegOp InstX8632Pand::Emitter = {
1120 &X8632::AssemblerX8632::pand, &X8632::AssemblerX8632::pand};
1121 template <>
1122 const X8632::AssemblerX8632::XmmEmitterRegOp InstX8632Pandn::Emitter = {
1123 &X8632::AssemblerX8632::pandn, &X8632::AssemblerX8632::pandn};
1124 template <>
1125 const X8632::AssemblerX8632::XmmEmitterRegOp InstX8632Pcmpeq::Emitter = {
1126 &X8632::AssemblerX8632::pcmpeq, &X8632::AssemblerX8632::pcmpeq};
1127 template <>
1128 const X8632::AssemblerX8632::XmmEmitterRegOp InstX8632Pcmpgt::Emitter = {
1129 &X8632::AssemblerX8632::pcmpgt, &X8632::AssemblerX8632::pcmpgt};
1130 template <>
1131 const X8632::AssemblerX8632::XmmEmitterRegOp InstX8632Pmull::Emitter = {
1132 &X8632::AssemblerX8632::pmull, &X8632::AssemblerX8632::pmull};
1133 template <>
1134 const X8632::AssemblerX8632::XmmEmitterRegOp InstX8632Pmuludq::Emitter = {
1135 &X8632::AssemblerX8632::pmuludq, &X8632::AssemblerX8632::pmuludq};
1136 template <>
1137 const X8632::AssemblerX8632::XmmEmitterRegOp InstX8632Por::Emitter = {
1138 &X8632::AssemblerX8632::por, &X8632::AssemblerX8632::por};
1139 template <>
1140 const X8632::AssemblerX8632::XmmEmitterRegOp InstX8632Psub::Emitter = {
1141 &X8632::AssemblerX8632::psub, &X8632::AssemblerX8632::psub};
1142 template <>
1143 const X8632::AssemblerX8632::XmmEmitterRegOp InstX8632Pxor::Emitter = {
1144 &X8632::AssemblerX8632::pxor, &X8632::AssemblerX8632::pxor};
1145 template <>
1146 const X8632::AssemblerX8632::XmmEmitterRegOp InstX8632Subss::Emitter = {
1147 &X8632::AssemblerX8632::subss, &X8632::AssemblerX8632::subss};
1148 template <>
1149 const X8632::AssemblerX8632::XmmEmitterRegOp InstX8632Subps::Emitter = {
1150 &X8632::AssemblerX8632::subps, &X8632::AssemblerX8632::subps};
1151
1152 // Binary XMM Shift ops
1153 template <>
1154 const X8632::AssemblerX8632::XmmEmitterShiftOp InstX8632Psll::Emitter = {
1155 &X8632::AssemblerX8632::psll, &X8632::AssemblerX8632::psll,
1156 &X8632::AssemblerX8632::psll};
1157 template <>
1158 const X8632::AssemblerX8632::XmmEmitterShiftOp InstX8632Psra::Emitter = {
1159 &X8632::AssemblerX8632::psra, &X8632::AssemblerX8632::psra,
1160 &X8632::AssemblerX8632::psra};
1161 template <>
1162 const X8632::AssemblerX8632::XmmEmitterShiftOp InstX8632Psrl::Emitter = {
1163 &X8632::AssemblerX8632::psrl, &X8632::AssemblerX8632::psrl,
1164 &X8632::AssemblerX8632::psrl};
1165
1166 template <> void InstX8632Sqrtss::emit(const Cfg *Func) const {
1167 if (!BuildDefs::dump())
1168 return;
1169 Ostream &Str = Func->getContext()->getStrEmit();
1170 assert(getSrcSize() == 1);
1171 Type Ty = getSrc(0)->getType();
1172 assert(isScalarFloatingType(Ty));
1173 Str << "\tsqrt" << TypeX8632Attributes[Ty].SdSsString << "\t";
1174 getSrc(0)->emit(Func);
1175 Str << ", ";
1176 getDest()->emit(Func);
1177 }
1178
1179 template <> void InstX8632Addss::emit(const Cfg *Func) const {
1180 if (!BuildDefs::dump())
1181 return;
1182 char buf[30];
1183 snprintf(buf, llvm::array_lengthof(buf), "add%s",
1184 TypeX8632Attributes[getDest()->getType()].SdSsString);
1185 emitTwoAddress(buf, this, Func);
1186 }
1187
1188 template <> void InstX8632Padd::emit(const Cfg *Func) const {
1189 if (!BuildDefs::dump())
1190 return;
1191 char buf[30];
1192 snprintf(buf, llvm::array_lengthof(buf), "padd%s",
1193 TypeX8632Attributes[getDest()->getType()].PackString);
1194 emitTwoAddress(buf, this, Func);
1195 }
1196
1197 template <> void InstX8632Pmull::emit(const Cfg *Func) const {
1198 if (!BuildDefs::dump())
1199 return;
1200 char buf[30];
1201 bool TypesAreValid = getDest()->getType() == IceType_v4i32 ||
1202 getDest()->getType() == IceType_v8i16;
1203 bool InstructionSetIsValid =
1204 getDest()->getType() == IceType_v8i16 ||
1205 static_cast<TargetX8632 *>(Func->getTarget())->getInstructionSet() >=
1206 X8632::Traits::SSE4_1;
1207 (void)TypesAreValid;
1208 (void)InstructionSetIsValid;
1209 assert(TypesAreValid);
1210 assert(InstructionSetIsValid);
1211 snprintf(buf, llvm::array_lengthof(buf), "pmull%s",
1212 TypeX8632Attributes[getDest()->getType()].PackString);
1213 emitTwoAddress(buf, this, Func);
1214 }
1215
1216 template <> void InstX8632Pmull::emitIAS(const Cfg *Func) const {
1217 Type Ty = getDest()->getType();
1218 bool TypesAreValid = Ty == IceType_v4i32 || Ty == IceType_v8i16;
1219 bool InstructionSetIsValid =
1220 Ty == IceType_v8i16 ||
1221 static_cast<TargetX8632 *>(Func->getTarget())->getInstructionSet() >=
1222 X8632::Traits::SSE4_1;
1223 (void)TypesAreValid;
1224 (void)InstructionSetIsValid;
1225 assert(TypesAreValid);
1226 assert(InstructionSetIsValid);
1227 assert(getSrcSize() == 2);
1228 Type ElementTy = typeElementType(Ty);
1229 emitIASRegOpTyXMM(Func, ElementTy, getDest(), getSrc(1), Emitter);
1230 }
1231
1232 template <> void InstX8632Subss::emit(const Cfg *Func) const {
1233 if (!BuildDefs::dump())
1234 return;
1235 char buf[30];
1236 snprintf(buf, llvm::array_lengthof(buf), "sub%s",
1237 TypeX8632Attributes[getDest()->getType()].SdSsString);
1238 emitTwoAddress(buf, this, Func);
1239 }
1240
1241 template <> void InstX8632Psub::emit(const Cfg *Func) const {
1242 if (!BuildDefs::dump())
1243 return;
1244 char buf[30];
1245 snprintf(buf, llvm::array_lengthof(buf), "psub%s",
1246 TypeX8632Attributes[getDest()->getType()].PackString);
1247 emitTwoAddress(buf, this, Func);
1248 }
1249
1250 template <> void InstX8632Mulss::emit(const Cfg *Func) const {
1251 if (!BuildDefs::dump())
1252 return;
1253 char buf[30];
1254 snprintf(buf, llvm::array_lengthof(buf), "mul%s",
1255 TypeX8632Attributes[getDest()->getType()].SdSsString);
1256 emitTwoAddress(buf, this, Func);
1257 }
1258
1259 template <> void InstX8632Pmuludq::emit(const Cfg *Func) const {
1260 if (!BuildDefs::dump())
1261 return;
1262 assert(getSrc(0)->getType() == IceType_v4i32 &&
1263 getSrc(1)->getType() == IceType_v4i32);
1264 emitTwoAddress(Opcode, this, Func);
1265 }
1266
1267 template <> void InstX8632Divss::emit(const Cfg *Func) const {
1268 if (!BuildDefs::dump())
1269 return;
1270 char buf[30];
1271 snprintf(buf, llvm::array_lengthof(buf), "div%s",
1272 TypeX8632Attributes[getDest()->getType()].SdSsString);
1273 emitTwoAddress(buf, this, Func);
1274 }
1275
1276 template <> void InstX8632Div::emit(const Cfg *Func) const {
1277 if (!BuildDefs::dump())
1278 return;
1279 Ostream &Str = Func->getContext()->getStrEmit();
1280 assert(getSrcSize() == 3);
1281 Operand *Src1 = getSrc(1);
1282 Str << "\t" << Opcode << getWidthString(Src1->getType()) << "\t";
1283 Src1->emit(Func);
1284 }
1285
1286 template <> void InstX8632Div::emitIAS(const Cfg *Func) const {
1287 assert(getSrcSize() == 3);
1288 const Operand *Src = getSrc(1);
1289 Type Ty = Src->getType();
1290 const static X8632::AssemblerX8632::GPREmitterOneOp Emitter = {
1291 &X8632::AssemblerX8632::div, &X8632::AssemblerX8632::div};
1292 emitIASOpTyGPR(Func, Ty, Src, Emitter);
1293 }
1294
1295 template <> void InstX8632Idiv::emit(const Cfg *Func) const {
1296 if (!BuildDefs::dump())
1297 return;
1298 Ostream &Str = Func->getContext()->getStrEmit();
1299 assert(getSrcSize() == 3);
1300 Operand *Src1 = getSrc(1);
1301 Str << "\t" << Opcode << getWidthString(Src1->getType()) << "\t";
1302 Src1->emit(Func);
1303 }
1304
1305 template <> void InstX8632Idiv::emitIAS(const Cfg *Func) const {
1306 assert(getSrcSize() == 3);
1307 const Operand *Src = getSrc(1);
1308 Type Ty = Src->getType();
1309 const static X8632::AssemblerX8632::GPREmitterOneOp Emitter = {
1310 &X8632::AssemblerX8632::idiv, &X8632::AssemblerX8632::idiv};
1311 emitIASOpTyGPR(Func, Ty, Src, Emitter);
1312 }
1313
1314 namespace {
1315
1316 // pblendvb and blendvps take xmm0 as a final implicit argument.
1317 void emitVariableBlendInst(const char *Opcode, const Inst *Inst,
1318 const Cfg *Func) {
1319 if (!BuildDefs::dump())
1320 return;
1321 Ostream &Str = Func->getContext()->getStrEmit();
1322 assert(Inst->getSrcSize() == 3);
1323 assert(llvm::cast<Variable>(Inst->getSrc(2))->getRegNum() ==
1324 RegX8632::Reg_xmm0);
1325 Str << "\t" << Opcode << "\t";
1326 Inst->getSrc(1)->emit(Func);
1327 Str << ", ";
1328 Inst->getDest()->emit(Func);
1329 }
1330
1331 void emitIASVariableBlendInst(
1332 const Inst *Inst, const Cfg *Func,
1333 const X8632::AssemblerX8632::XmmEmitterRegOp &Emitter) {
1334 assert(Inst->getSrcSize() == 3);
1335 assert(llvm::cast<Variable>(Inst->getSrc(2))->getRegNum() ==
1336 RegX8632::Reg_xmm0);
1337 const Variable *Dest = Inst->getDest();
1338 const Operand *Src = Inst->getSrc(1);
1339 emitIASRegOpTyXMM(Func, Dest->getType(), Dest, Src, Emitter);
1340 }
1341
1342 } // end anonymous namespace
1343
1344 template <> void InstX8632Blendvps::emit(const Cfg *Func) const {
1345 if (!BuildDefs::dump())
1346 return;
1347 assert(static_cast<TargetX8632 *>(Func->getTarget())->getInstructionSet() >=
1348 X8632::Traits::SSE4_1);
1349 emitVariableBlendInst(Opcode, this, Func);
1350 }
1351
1352 template <> void InstX8632Blendvps::emitIAS(const Cfg *Func) const {
1353 assert(static_cast<TargetX8632 *>(Func->getTarget())->getInstructionSet() >=
1354 X8632::Traits::SSE4_1);
1355 static const X8632::AssemblerX8632::XmmEmitterRegOp Emitter = {
1356 &X8632::AssemblerX8632::blendvps, &X8632::AssemblerX8632::blendvps};
1357 emitIASVariableBlendInst(this, Func, Emitter);
1358 }
1359
1360 template <> void InstX8632Pblendvb::emit(const Cfg *Func) const {
1361 if (!BuildDefs::dump())
1362 return;
1363 assert(static_cast<TargetX8632 *>(Func->getTarget())->getInstructionSet() >=
1364 X8632::Traits::SSE4_1);
1365 emitVariableBlendInst(Opcode, this, Func);
1366 }
1367
1368 template <> void InstX8632Pblendvb::emitIAS(const Cfg *Func) const {
1369 assert(static_cast<TargetX8632 *>(Func->getTarget())->getInstructionSet() >=
1370 X8632::Traits::SSE4_1);
1371 static const X8632::AssemblerX8632::XmmEmitterRegOp Emitter = {
1372 &X8632::AssemblerX8632::pblendvb, &X8632::AssemblerX8632::pblendvb};
1373 emitIASVariableBlendInst(this, Func, Emitter);
1374 }
1375
1376 template <> void InstX8632Imul::emit(const Cfg *Func) const {
1377 if (!BuildDefs::dump())
1378 return;
1379 Ostream &Str = Func->getContext()->getStrEmit();
1380 assert(getSrcSize() == 2);
1381 Variable *Dest = getDest();
1382 if (isByteSizedArithType(Dest->getType())) {
1383 // The 8-bit version of imul only allows the form "imul r/m8".
1384 const auto Src0Var = llvm::dyn_cast<Variable>(getSrc(0));
1385 (void)Src0Var;
1386 assert(Src0Var && Src0Var->getRegNum() == RegX8632::Reg_eax);
1387 Str << "\timulb\t";
1388 getSrc(1)->emit(Func);
1389 } else if (llvm::isa<Constant>(getSrc(1))) {
1390 Str << "\timul" << getWidthString(Dest->getType()) << "\t";
1391 getSrc(1)->emit(Func);
1392 Str << ", ";
1393 getSrc(0)->emit(Func);
1394 Str << ", ";
1395 Dest->emit(Func);
1396 } else {
1397 emitTwoAddress("imul", this, Func);
1398 }
1399 }
1400
1401 template <> void InstX8632Imul::emitIAS(const Cfg *Func) const {
1402 assert(getSrcSize() == 2);
1403 const Variable *Var = getDest();
1404 Type Ty = Var->getType();
1405 const Operand *Src = getSrc(1);
1406 if (isByteSizedArithType(Ty)) {
1407 // The 8-bit version of imul only allows the form "imul r/m8".
1408 const auto Src0Var = llvm::dyn_cast<Variable>(getSrc(0));
1409 (void)Src0Var;
1410 assert(Src0Var && Src0Var->getRegNum() == RegX8632::Reg_eax);
1411 const X8632::AssemblerX8632::GPREmitterOneOp Emitter = {
1412 &X8632::AssemblerX8632::imul, &X8632::AssemblerX8632::imul};
1413 emitIASOpTyGPR(Func, Ty, getSrc(1), Emitter);
1414 } else {
1415 // We only use imul as a two-address instruction even though
1416 // there is a 3 operand version when one of the operands is a constant.
1417 assert(Var == getSrc(0));
1418 const X8632::AssemblerX8632::GPREmitterRegOp Emitter = {
1419 &X8632::AssemblerX8632::imul, &X8632::AssemblerX8632::imul,
1420 &X8632::AssemblerX8632::imul};
1421 emitIASRegOpTyGPR(Func, Ty, Var, Src, Emitter);
1422 }
1423 }
1424
1425 template <> void InstX8632Insertps::emitIAS(const Cfg *Func) const {
1426 assert(getSrcSize() == 3);
1427 assert(static_cast<TargetX8632 *>(Func->getTarget())->getInstructionSet() >=
1428 X8632::Traits::SSE4_1);
1429 const Variable *Dest = getDest();
1430 assert(Dest == getSrc(0));
1431 Type Ty = Dest->getType();
1432 static const X8632::AssemblerX8632::ThreeOpImmEmitter<
1433 RegX8632::XmmRegister, RegX8632::XmmRegister> Emitter = {
1434 &X8632::AssemblerX8632::insertps, &X8632::AssemblerX8632::insertps};
1435 emitIASThreeOpImmOps<RegX8632::XmmRegister, RegX8632::XmmRegister,
1436 RegX8632::getEncodedXmm, RegX8632::getEncodedXmm>(
1437 Func, Ty, Dest, getSrc(1), getSrc(2), Emitter);
1438 }
1439
1440 template <> void InstX8632Cbwdq::emit(const Cfg *Func) const {
1441 if (!BuildDefs::dump())
1442 return;
1443 Ostream &Str = Func->getContext()->getStrEmit();
1444 assert(getSrcSize() == 1);
1445 Operand *Src0 = getSrc(0);
1446 assert(llvm::isa<Variable>(Src0));
1447 assert(llvm::cast<Variable>(Src0)->getRegNum() == RegX8632::Reg_eax);
1448 switch (Src0->getType()) {
1449 default:
1450 llvm_unreachable("unexpected source type!");
1451 break;
1452 case IceType_i8:
1453 assert(getDest()->getRegNum() == RegX8632::Reg_eax);
1454 Str << "\tcbtw";
1455 break;
1456 case IceType_i16:
1457 assert(getDest()->getRegNum() == RegX8632::Reg_edx);
1458 Str << "\tcwtd";
1459 break;
1460 case IceType_i32:
1461 assert(getDest()->getRegNum() == RegX8632::Reg_edx);
1462 Str << "\tcltd";
1463 break;
1464 }
1465 }
1466
1467 template <> void InstX8632Cbwdq::emitIAS(const Cfg *Func) const {
1468 X8632::AssemblerX8632 *Asm = Func->getAssembler<X8632::AssemblerX8632>();
1469 assert(getSrcSize() == 1);
1470 Operand *Src0 = getSrc(0);
1471 assert(llvm::isa<Variable>(Src0));
1472 assert(llvm::cast<Variable>(Src0)->getRegNum() == RegX8632::Reg_eax);
1473 switch (Src0->getType()) {
1474 default:
1475 llvm_unreachable("unexpected source type!");
1476 break;
1477 case IceType_i8:
1478 assert(getDest()->getRegNum() == RegX8632::Reg_eax);
1479 Asm->cbw();
1480 break;
1481 case IceType_i16:
1482 assert(getDest()->getRegNum() == RegX8632::Reg_edx);
1483 Asm->cwd();
1484 break;
1485 case IceType_i32:
1486 assert(getDest()->getRegNum() == RegX8632::Reg_edx);
1487 Asm->cdq();
1488 break;
1489 }
1490 }
1491
1492 void InstX8632Mul::emit(const Cfg *Func) const {
1493 if (!BuildDefs::dump())
1494 return;
1495 Ostream &Str = Func->getContext()->getStrEmit();
1496 assert(getSrcSize() == 2);
1497 assert(llvm::isa<Variable>(getSrc(0)));
1498 assert(llvm::cast<Variable>(getSrc(0))->getRegNum() == RegX8632::Reg_eax);
1499 assert(getDest()->getRegNum() == RegX8632::Reg_eax); // TODO: allow edx?
1500 Str << "\tmul" << getWidthString(getDest()->getType()) << "\t";
1501 getSrc(1)->emit(Func);
1502 }
1503
1504 void InstX8632Mul::emitIAS(const Cfg *Func) const {
1505 assert(getSrcSize() == 2);
1506 assert(llvm::isa<Variable>(getSrc(0)));
1507 assert(llvm::cast<Variable>(getSrc(0))->getRegNum() == RegX8632::Reg_eax);
1508 assert(getDest()->getRegNum() == RegX8632::Reg_eax); // TODO: allow edx?
1509 const Operand *Src = getSrc(1);
1510 Type Ty = Src->getType();
1511 const static X8632::AssemblerX8632::GPREmitterOneOp Emitter = {
1512 &X8632::AssemblerX8632::mul, &X8632::AssemblerX8632::mul};
1513 emitIASOpTyGPR(Func, Ty, Src, Emitter);
1514 }
1515
1516 void InstX8632Mul::dump(const Cfg *Func) const {
1517 if (!BuildDefs::dump())
1518 return;
1519 Ostream &Str = Func->getContext()->getStrDump();
1520 dumpDest(Func);
1521 Str << " = mul." << getDest()->getType() << " ";
1522 dumpSources(Func);
1523 }
1524
1525 void InstX8632Shld::emit(const Cfg *Func) const {
1526 if (!BuildDefs::dump())
1527 return;
1528 Ostream &Str = Func->getContext()->getStrEmit();
1529 Variable *Dest = getDest();
1530 assert(getSrcSize() == 3);
1531 assert(Dest == getSrc(0));
1532 Str << "\tshld" << getWidthString(Dest->getType()) << "\t";
1533 if (const auto ShiftReg = llvm::dyn_cast<Variable>(getSrc(2))) {
1534 (void)ShiftReg;
1535 assert(ShiftReg->getRegNum() == RegX8632::Reg_ecx);
1536 Str << "%cl";
1537 } else {
1538 getSrc(2)->emit(Func);
1539 }
1540 Str << ", ";
1541 getSrc(1)->emit(Func);
1542 Str << ", ";
1543 Dest->emit(Func);
1544 }
1545
1546 void InstX8632Shld::emitIAS(const Cfg *Func) const {
1547 assert(getSrcSize() == 3);
1548 assert(getDest() == getSrc(0));
1549 const Variable *Dest = getDest();
1550 const Operand *Src1 = getSrc(1);
1551 const Operand *Src2 = getSrc(2);
1552 static const X8632::AssemblerX8632::GPREmitterShiftD Emitter = {
1553 &X8632::AssemblerX8632::shld, &X8632::AssemblerX8632::shld};
1554 emitIASGPRShiftDouble(Func, Dest, Src1, Src2, Emitter);
1555 }
1556
1557 void InstX8632Shld::dump(const Cfg *Func) const {
1558 if (!BuildDefs::dump())
1559 return;
1560 Ostream &Str = Func->getContext()->getStrDump();
1561 dumpDest(Func);
1562 Str << " = shld." << getDest()->getType() << " ";
1563 dumpSources(Func);
1564 }
1565
1566 void InstX8632Shrd::emit(const Cfg *Func) const {
1567 if (!BuildDefs::dump())
1568 return;
1569 Ostream &Str = Func->getContext()->getStrEmit();
1570 Variable *Dest = getDest();
1571 assert(getSrcSize() == 3);
1572 assert(Dest == getSrc(0));
1573 Str << "\tshrd" << getWidthString(Dest->getType()) << "\t";
1574 if (const auto ShiftReg = llvm::dyn_cast<Variable>(getSrc(2))) {
1575 (void)ShiftReg;
1576 assert(ShiftReg->getRegNum() == RegX8632::Reg_ecx);
1577 Str << "%cl";
1578 } else {
1579 getSrc(2)->emit(Func);
1580 }
1581 Str << ", ";
1582 getSrc(1)->emit(Func);
1583 Str << ", ";
1584 Dest->emit(Func);
1585 }
1586
1587 void InstX8632Shrd::emitIAS(const Cfg *Func) const {
1588 assert(getSrcSize() == 3);
1589 assert(getDest() == getSrc(0));
1590 const Variable *Dest = getDest();
1591 const Operand *Src1 = getSrc(1);
1592 const Operand *Src2 = getSrc(2);
1593 static const X8632::AssemblerX8632::GPREmitterShiftD Emitter = {
1594 &X8632::AssemblerX8632::shrd, &X8632::AssemblerX8632::shrd};
1595 emitIASGPRShiftDouble(Func, Dest, Src1, Src2, Emitter);
1596 }
1597
1598 void InstX8632Shrd::dump(const Cfg *Func) const {
1599 if (!BuildDefs::dump())
1600 return;
1601 Ostream &Str = Func->getContext()->getStrDump();
1602 dumpDest(Func);
1603 Str << " = shrd." << getDest()->getType() << " ";
1604 dumpSources(Func);
1605 }
1606
1607 void InstX8632Cmov::emit(const Cfg *Func) const {
1608 if (!BuildDefs::dump())
1609 return;
1610 Ostream &Str = Func->getContext()->getStrEmit();
1611 Variable *Dest = getDest();
1612 Str << "\t";
1613 assert(Condition != X8632::Traits::Cond::Br_None);
1614 assert(getDest()->hasReg());
1615 Str << "cmov" << InstX8632BrAttributes[Condition].DisplayString
1616 << getWidthString(Dest->getType()) << "\t";
1617 getSrc(1)->emit(Func);
1618 Str << ", ";
1619 Dest->emit(Func);
1620 }
1621
1622 void InstX8632Cmov::emitIAS(const Cfg *Func) const {
1623 assert(Condition != X8632::Traits::Cond::Br_None);
1624 assert(getDest()->hasReg());
1625 assert(getSrcSize() == 2);
1626 Operand *Src = getSrc(1);
1627 Type SrcTy = Src->getType();
1628 assert(SrcTy == IceType_i16 || SrcTy == IceType_i32);
1629 X8632::AssemblerX8632 *Asm = Func->getAssembler<X8632::AssemblerX8632>();
1630 if (const auto *SrcVar = llvm::dyn_cast<Variable>(Src)) {
1631 if (SrcVar->hasReg()) {
1632 Asm->cmov(SrcTy, Condition,
1633 RegX8632::getEncodedGPR(getDest()->getRegNum()),
1634 RegX8632::getEncodedGPR(SrcVar->getRegNum()));
1635 } else {
1636 Asm->cmov(SrcTy, Condition,
1637 RegX8632::getEncodedGPR(getDest()->getRegNum()),
1638 static_cast<TargetX8632 *>(Func->getTarget())
1639 ->stackVarToAsmOperand(SrcVar));
1640 }
1641 } else if (const auto Mem = llvm::dyn_cast<OperandX8632Mem>(Src)) {
1642 assert(Mem->getSegmentRegister() == OperandX8632Mem::DefaultSegment);
1643 Asm->cmov(SrcTy, Condition, RegX8632::getEncodedGPR(getDest()->getRegNum()),
1644 Mem->toAsmAddress(Asm));
1645 } else {
1646 llvm_unreachable("Unexpected operand type");
1647 }
1648 }
1649
1650 void InstX8632Cmov::dump(const Cfg *Func) const {
1651 if (!BuildDefs::dump())
1652 return;
1653 Ostream &Str = Func->getContext()->getStrDump();
1654 Str << "cmov" << InstX8632BrAttributes[Condition].DisplayString << ".";
1655 Str << getDest()->getType() << " ";
1656 dumpDest(Func);
1657 Str << ", ";
1658 dumpSources(Func);
1659 }
1660
1661 void InstX8632Cmpps::emit(const Cfg *Func) const {
1662 if (!BuildDefs::dump())
1663 return;
1664 Ostream &Str = Func->getContext()->getStrEmit();
1665 assert(getSrcSize() == 2);
1666 assert(Condition < X8632::Traits::Cond::Cmpps_Invalid);
1667 Str << "\t";
1668 Str << "cmp" << InstX8632CmppsAttributes[Condition].EmitString << "ps"
1669 << "\t";
1670 getSrc(1)->emit(Func);
1671 Str << ", ";
1672 getDest()->emit(Func);
1673 }
1674
1675 void InstX8632Cmpps::emitIAS(const Cfg *Func) const {
1676 X8632::AssemblerX8632 *Asm = Func->getAssembler<X8632::AssemblerX8632>();
1677 assert(getSrcSize() == 2);
1678 assert(Condition < X8632::Traits::Cond::Cmpps_Invalid);
1679 // Assuming there isn't any load folding for cmpps, and vector constants
1680 // are not allowed in PNaCl.
1681 assert(llvm::isa<Variable>(getSrc(1)));
1682 const auto SrcVar = llvm::cast<Variable>(getSrc(1));
1683 if (SrcVar->hasReg()) {
1684 Asm->cmpps(RegX8632::getEncodedXmm(getDest()->getRegNum()),
1685 RegX8632::getEncodedXmm(SrcVar->getRegNum()), Condition);
1686 } else {
1687 X8632::Traits::Address SrcStackAddr =
1688 static_cast<TargetX8632 *>(Func->getTarget())
1689 ->stackVarToAsmOperand(SrcVar);
1690 Asm->cmpps(RegX8632::getEncodedXmm(getDest()->getRegNum()), SrcStackAddr,
1691 Condition);
1692 }
1693 }
1694
1695 void InstX8632Cmpps::dump(const Cfg *Func) const {
1696 if (!BuildDefs::dump())
1697 return;
1698 Ostream &Str = Func->getContext()->getStrDump();
1699 assert(Condition < X8632::Traits::Cond::Cmpps_Invalid);
1700 dumpDest(Func);
1701 Str << " = cmp" << InstX8632CmppsAttributes[Condition].EmitString << "ps"
1702 << "\t";
1703 dumpSources(Func);
1704 }
1705
1706 void InstX8632Cmpxchg::emit(const Cfg *Func) const {
1707 if (!BuildDefs::dump())
1708 return;
1709 Ostream &Str = Func->getContext()->getStrEmit();
1710 assert(getSrcSize() == 3);
1711 if (Locked) {
1712 Str << "\tlock";
1713 }
1714 Str << "\tcmpxchg" << getWidthString(getSrc(0)->getType()) << "\t";
1715 getSrc(2)->emit(Func);
1716 Str << ", ";
1717 getSrc(0)->emit(Func);
1718 }
1719
1720 void InstX8632Cmpxchg::emitIAS(const Cfg *Func) const {
1721 assert(getSrcSize() == 3);
1722 X8632::AssemblerX8632 *Asm = Func->getAssembler<X8632::AssemblerX8632>();
1723 Type Ty = getSrc(0)->getType();
1724 const auto Mem = llvm::cast<OperandX8632Mem>(getSrc(0));
1725 assert(Mem->getSegmentRegister() == OperandX8632Mem::DefaultSegment);
1726 const X8632::Traits::Address Addr = Mem->toAsmAddress(Asm);
1727 const auto VarReg = llvm::cast<Variable>(getSrc(2));
1728 assert(VarReg->hasReg());
1729 const RegX8632::GPRRegister Reg =
1730 RegX8632::getEncodedGPR(VarReg->getRegNum());
1731 Asm->cmpxchg(Ty, Addr, Reg, Locked);
1732 }
1733
1734 void InstX8632Cmpxchg::dump(const Cfg *Func) const {
1735 if (!BuildDefs::dump())
1736 return;
1737 Ostream &Str = Func->getContext()->getStrDump();
1738 if (Locked) {
1739 Str << "lock ";
1740 }
1741 Str << "cmpxchg." << getSrc(0)->getType() << " ";
1742 dumpSources(Func);
1743 }
1744
1745 void InstX8632Cmpxchg8b::emit(const Cfg *Func) const {
1746 if (!BuildDefs::dump())
1747 return;
1748 Ostream &Str = Func->getContext()->getStrEmit();
1749 assert(getSrcSize() == 5);
1750 if (Locked) {
1751 Str << "\tlock";
1752 }
1753 Str << "\tcmpxchg8b\t";
1754 getSrc(0)->emit(Func);
1755 }
1756
1757 void InstX8632Cmpxchg8b::emitIAS(const Cfg *Func) const {
1758 assert(getSrcSize() == 5);
1759 X8632::AssemblerX8632 *Asm = Func->getAssembler<X8632::AssemblerX8632>();
1760 const auto Mem = llvm::cast<OperandX8632Mem>(getSrc(0));
1761 assert(Mem->getSegmentRegister() == OperandX8632Mem::DefaultSegment);
1762 const X8632::Traits::Address Addr = Mem->toAsmAddress(Asm);
1763 Asm->cmpxchg8b(Addr, Locked);
1764 }
1765
1766 void InstX8632Cmpxchg8b::dump(const Cfg *Func) const {
1767 if (!BuildDefs::dump())
1768 return;
1769 Ostream &Str = Func->getContext()->getStrDump();
1770 if (Locked) {
1771 Str << "lock ";
1772 }
1773 Str << "cmpxchg8b ";
1774 dumpSources(Func);
1775 }
1776
1777 void InstX8632Cvt::emit(const Cfg *Func) const {
1778 if (!BuildDefs::dump())
1779 return;
1780 Ostream &Str = Func->getContext()->getStrEmit();
1781 assert(getSrcSize() == 1);
1782 Str << "\tcvt";
1783 if (isTruncating())
1784 Str << "t";
1785 Str << TypeX8632Attributes[getSrc(0)->getType()].CvtString << "2"
1786 << TypeX8632Attributes[getDest()->getType()].CvtString << "\t";
1787 getSrc(0)->emit(Func);
1788 Str << ", ";
1789 getDest()->emit(Func);
1790 }
1791
1792 void InstX8632Cvt::emitIAS(const Cfg *Func) const {
1793 assert(getSrcSize() == 1);
1794 const Variable *Dest = getDest();
1795 const Operand *Src = getSrc(0);
1796 Type DestTy = Dest->getType();
1797 Type SrcTy = Src->getType();
1798 switch (Variant) {
1799 case Si2ss: {
1800 assert(isScalarIntegerType(SrcTy));
1801 assert(typeWidthInBytes(SrcTy) <= 4);
1802 assert(isScalarFloatingType(DestTy));
1803 static const X8632::AssemblerX8632::CastEmitterRegOp<
1804 RegX8632::XmmRegister, RegX8632::GPRRegister> Emitter = {
1805 &X8632::AssemblerX8632::cvtsi2ss, &X8632::AssemblerX8632::cvtsi2ss};
1806 emitIASCastRegOp<RegX8632::XmmRegister, RegX8632::GPRRegister,
1807 RegX8632::getEncodedXmm, RegX8632::getEncodedGPR>(
1808 Func, DestTy, Dest, Src, Emitter);
1809 return;
1810 }
1811 case Tss2si: {
1812 assert(isScalarFloatingType(SrcTy));
1813 assert(isScalarIntegerType(DestTy));
1814 assert(typeWidthInBytes(DestTy) <= 4);
1815 static const X8632::AssemblerX8632::CastEmitterRegOp<
1816 RegX8632::GPRRegister, RegX8632::XmmRegister> Emitter = {
1817 &X8632::AssemblerX8632::cvttss2si, &X8632::AssemblerX8632::cvttss2si};
1818 emitIASCastRegOp<RegX8632::GPRRegister, RegX8632::XmmRegister,
1819 RegX8632::getEncodedGPR, RegX8632::getEncodedXmm>(
1820 Func, SrcTy, Dest, Src, Emitter);
1821 return;
1822 }
1823 case Float2float: {
1824 assert(isScalarFloatingType(SrcTy));
1825 assert(isScalarFloatingType(DestTy));
1826 assert(DestTy != SrcTy);
1827 static const X8632::AssemblerX8632::XmmEmitterRegOp Emitter = {
1828 &X8632::AssemblerX8632::cvtfloat2float,
1829 &X8632::AssemblerX8632::cvtfloat2float};
1830 emitIASRegOpTyXMM(Func, SrcTy, Dest, Src, Emitter);
1831 return;
1832 }
1833 case Dq2ps: {
1834 assert(isVectorIntegerType(SrcTy));
1835 assert(isVectorFloatingType(DestTy));
1836 static const X8632::AssemblerX8632::XmmEmitterRegOp Emitter = {
1837 &X8632::AssemblerX8632::cvtdq2ps, &X8632::AssemblerX8632::cvtdq2ps};
1838 emitIASRegOpTyXMM(Func, DestTy, Dest, Src, Emitter);
1839 return;
1840 }
1841 case Tps2dq: {
1842 assert(isVectorFloatingType(SrcTy));
1843 assert(isVectorIntegerType(DestTy));
1844 static const X8632::AssemblerX8632::XmmEmitterRegOp Emitter = {
1845 &X8632::AssemblerX8632::cvttps2dq, &X8632::AssemblerX8632::cvttps2dq};
1846 emitIASRegOpTyXMM(Func, DestTy, Dest, Src, Emitter);
1847 return;
1848 }
1849 }
1850 }
1851
1852 void InstX8632Cvt::dump(const Cfg *Func) const {
1853 if (!BuildDefs::dump())
1854 return;
1855 Ostream &Str = Func->getContext()->getStrDump();
1856 dumpDest(Func);
1857 Str << " = cvt";
1858 if (isTruncating())
1859 Str << "t";
1860 Str << TypeX8632Attributes[getSrc(0)->getType()].CvtString << "2"
1861 << TypeX8632Attributes[getDest()->getType()].CvtString << " ";
1862 dumpSources(Func);
1863 }
1864
1865 void InstX8632Icmp::emit(const Cfg *Func) const {
1866 if (!BuildDefs::dump())
1867 return;
1868 Ostream &Str = Func->getContext()->getStrEmit();
1869 assert(getSrcSize() == 2);
1870 Str << "\tcmp" << getWidthString(getSrc(0)->getType()) << "\t";
1871 getSrc(1)->emit(Func);
1872 Str << ", ";
1873 getSrc(0)->emit(Func);
1874 }
1875
1876 void InstX8632Icmp::emitIAS(const Cfg *Func) const {
1877 assert(getSrcSize() == 2);
1878 const Operand *Src0 = getSrc(0);
1879 const Operand *Src1 = getSrc(1);
1880 Type Ty = Src0->getType();
1881 static const X8632::AssemblerX8632::GPREmitterRegOp RegEmitter = {
1882 &X8632::AssemblerX8632::cmp, &X8632::AssemblerX8632::cmp,
1883 &X8632::AssemblerX8632::cmp};
1884 static const X8632::AssemblerX8632::GPREmitterAddrOp AddrEmitter = {
1885 &X8632::AssemblerX8632::cmp, &X8632::AssemblerX8632::cmp};
1886 if (const auto SrcVar0 = llvm::dyn_cast<Variable>(Src0)) {
1887 if (SrcVar0->hasReg()) {
1888 emitIASRegOpTyGPR(Func, Ty, SrcVar0, Src1, RegEmitter);
1889 return;
1890 }
1891 }
1892 emitIASAsAddrOpTyGPR(Func, Ty, Src0, Src1, AddrEmitter);
1893 }
1894
1895 void InstX8632Icmp::dump(const Cfg *Func) const {
1896 if (!BuildDefs::dump())
1897 return;
1898 Ostream &Str = Func->getContext()->getStrDump();
1899 Str << "cmp." << getSrc(0)->getType() << " ";
1900 dumpSources(Func);
1901 }
1902
1903 void InstX8632Ucomiss::emit(const Cfg *Func) const {
1904 if (!BuildDefs::dump())
1905 return;
1906 Ostream &Str = Func->getContext()->getStrEmit();
1907 assert(getSrcSize() == 2);
1908 Str << "\tucomi" << TypeX8632Attributes[getSrc(0)->getType()].SdSsString
1909 << "\t";
1910 getSrc(1)->emit(Func);
1911 Str << ", ";
1912 getSrc(0)->emit(Func);
1913 }
1914
1915 void InstX8632Ucomiss::emitIAS(const Cfg *Func) const {
1916 assert(getSrcSize() == 2);
1917 // Currently src0 is always a variable by convention, to avoid having
1918 // two memory operands.
1919 assert(llvm::isa<Variable>(getSrc(0)));
1920 const auto Src0Var = llvm::cast<Variable>(getSrc(0));
1921 Type Ty = Src0Var->getType();
1922 const static X8632::AssemblerX8632::XmmEmitterRegOp Emitter = {
1923 &X8632::AssemblerX8632::ucomiss, &X8632::AssemblerX8632::ucomiss};
1924 emitIASRegOpTyXMM(Func, Ty, Src0Var, getSrc(1), Emitter);
1925 }
1926
1927 void InstX8632Ucomiss::dump(const Cfg *Func) const {
1928 if (!BuildDefs::dump())
1929 return;
1930 Ostream &Str = Func->getContext()->getStrDump();
1931 Str << "ucomiss." << getSrc(0)->getType() << " ";
1932 dumpSources(Func);
1933 }
1934
1935 void InstX8632UD2::emit(const Cfg *Func) const {
1936 if (!BuildDefs::dump())
1937 return;
1938 Ostream &Str = Func->getContext()->getStrEmit();
1939 assert(getSrcSize() == 0);
1940 Str << "\tud2";
1941 }
1942
1943 void InstX8632UD2::emitIAS(const Cfg *Func) const {
1944 X8632::AssemblerX8632 *Asm = Func->getAssembler<X8632::AssemblerX8632>();
1945 Asm->ud2();
1946 }
1947
1948 void InstX8632UD2::dump(const Cfg *Func) const {
1949 if (!BuildDefs::dump())
1950 return;
1951 Ostream &Str = Func->getContext()->getStrDump();
1952 Str << "ud2";
1953 }
1954
1955 void InstX8632Test::emit(const Cfg *Func) const {
1956 if (!BuildDefs::dump())
1957 return;
1958 Ostream &Str = Func->getContext()->getStrEmit();
1959 assert(getSrcSize() == 2);
1960 Str << "\ttest" << getWidthString(getSrc(0)->getType()) << "\t";
1961 getSrc(1)->emit(Func);
1962 Str << ", ";
1963 getSrc(0)->emit(Func);
1964 }
1965
1966 void InstX8632Test::emitIAS(const Cfg *Func) const {
1967 assert(getSrcSize() == 2);
1968 const Operand *Src0 = getSrc(0);
1969 const Operand *Src1 = getSrc(1);
1970 Type Ty = Src0->getType();
1971 // The Reg/Addr form of test is not encodeable.
1972 static const X8632::AssemblerX8632::GPREmitterRegOp RegEmitter = {
1973 &X8632::AssemblerX8632::test, nullptr, &X8632::AssemblerX8632::test};
1974 static const X8632::AssemblerX8632::GPREmitterAddrOp AddrEmitter = {
1975 &X8632::AssemblerX8632::test, &X8632::AssemblerX8632::test};
1976 if (const auto SrcVar0 = llvm::dyn_cast<Variable>(Src0)) {
1977 if (SrcVar0->hasReg()) {
1978 emitIASRegOpTyGPR(Func, Ty, SrcVar0, Src1, RegEmitter);
1979 return;
1980 }
1981 }
1982 llvm_unreachable("Nothing actually generates this so it's untested");
1983 emitIASAsAddrOpTyGPR(Func, Ty, Src0, Src1, AddrEmitter);
1984 }
1985
1986 void InstX8632Test::dump(const Cfg *Func) const {
1987 if (!BuildDefs::dump())
1988 return;
1989 Ostream &Str = Func->getContext()->getStrDump();
1990 Str << "test." << getSrc(0)->getType() << " ";
1991 dumpSources(Func);
1992 }
1993
1994 void InstX8632Mfence::emit(const Cfg *Func) const {
1995 if (!BuildDefs::dump())
1996 return;
1997 Ostream &Str = Func->getContext()->getStrEmit();
1998 assert(getSrcSize() == 0);
1999 Str << "\tmfence";
2000 }
2001
2002 void InstX8632Mfence::emitIAS(const Cfg *Func) const {
2003 X8632::AssemblerX8632 *Asm = Func->getAssembler<X8632::AssemblerX8632>();
2004 Asm->mfence();
2005 }
2006
2007 void InstX8632Mfence::dump(const Cfg *Func) const {
2008 if (!BuildDefs::dump())
2009 return;
2010 Ostream &Str = Func->getContext()->getStrDump();
2011 Str << "mfence";
2012 }
2013
2014 void InstX8632Store::emit(const Cfg *Func) const {
2015 if (!BuildDefs::dump())
2016 return;
2017 Ostream &Str = Func->getContext()->getStrEmit();
2018 assert(getSrcSize() == 2);
2019 Type Ty = getSrc(0)->getType();
2020 Str << "\tmov" << getWidthString(Ty) << TypeX8632Attributes[Ty].SdSsString
2021 << "\t";
2022 getSrc(0)->emit(Func);
2023 Str << ", ";
2024 getSrc(1)->emit(Func);
2025 }
2026
2027 void InstX8632Store::emitIAS(const Cfg *Func) const {
2028 assert(getSrcSize() == 2);
2029 const Operand *Dest = getSrc(1);
2030 const Operand *Src = getSrc(0);
2031 Type DestTy = Dest->getType();
2032 if (isScalarFloatingType(DestTy)) {
2033 // Src must be a register, since Dest is a Mem operand of some kind.
2034 const auto SrcVar = llvm::cast<Variable>(Src);
2035 assert(SrcVar->hasReg());
2036 RegX8632::XmmRegister SrcReg = RegX8632::getEncodedXmm(SrcVar->getRegNum());
2037 X8632::AssemblerX8632 *Asm = Func->getAssembler<X8632::AssemblerX8632>();
2038 if (const auto DestVar = llvm::dyn_cast<Variable>(Dest)) {
2039 assert(!DestVar->hasReg());
2040 X8632::Traits::Address StackAddr(
2041 static_cast<TargetX8632 *>(Func->getTarget())
2042 ->stackVarToAsmOperand(DestVar));
2043 Asm->movss(DestTy, StackAddr, SrcReg);
2044 } else {
2045 const auto DestMem = llvm::cast<OperandX8632Mem>(Dest);
2046 assert(DestMem->getSegmentRegister() == OperandX8632Mem::DefaultSegment);
2047 Asm->movss(DestTy, DestMem->toAsmAddress(Asm), SrcReg);
2048 }
2049 return;
2050 } else {
2051 assert(isScalarIntegerType(DestTy));
2052 static const X8632::AssemblerX8632::GPREmitterAddrOp GPRAddrEmitter = {
2053 &X8632::AssemblerX8632::mov, &X8632::AssemblerX8632::mov};
2054 emitIASAsAddrOpTyGPR(Func, DestTy, Dest, Src, GPRAddrEmitter);
2055 }
2056 }
2057
2058 void InstX8632Store::dump(const Cfg *Func) const {
2059 if (!BuildDefs::dump())
2060 return;
2061 Ostream &Str = Func->getContext()->getStrDump();
2062 Str << "mov." << getSrc(0)->getType() << " ";
2063 getSrc(1)->dump(Func);
2064 Str << ", ";
2065 getSrc(0)->dump(Func);
2066 }
2067
2068 void InstX8632StoreP::emit(const Cfg *Func) const {
2069 if (!BuildDefs::dump())
2070 return;
2071 Ostream &Str = Func->getContext()->getStrEmit();
2072 assert(getSrcSize() == 2);
2073 Str << "\tmovups\t";
2074 getSrc(0)->emit(Func);
2075 Str << ", ";
2076 getSrc(1)->emit(Func);
2077 }
2078
2079 void InstX8632StoreP::emitIAS(const Cfg *Func) const {
2080 X8632::AssemblerX8632 *Asm = Func->getAssembler<X8632::AssemblerX8632>();
2081 assert(getSrcSize() == 2);
2082 const auto SrcVar = llvm::cast<Variable>(getSrc(0));
2083 const auto DestMem = llvm::cast<OperandX8632Mem>(getSrc(1));
2084 assert(DestMem->getSegmentRegister() == OperandX8632Mem::DefaultSegment);
2085 assert(SrcVar->hasReg());
2086 Asm->movups(DestMem->toAsmAddress(Asm),
2087 RegX8632::getEncodedXmm(SrcVar->getRegNum()));
2088 }
2089
2090 void InstX8632StoreP::dump(const Cfg *Func) const {
2091 if (!BuildDefs::dump())
2092 return;
2093 Ostream &Str = Func->getContext()->getStrDump();
2094 Str << "storep." << getSrc(0)->getType() << " ";
2095 getSrc(1)->dump(Func);
2096 Str << ", ";
2097 getSrc(0)->dump(Func);
2098 }
2099
2100 void InstX8632StoreQ::emit(const Cfg *Func) const {
2101 if (!BuildDefs::dump())
2102 return;
2103 Ostream &Str = Func->getContext()->getStrEmit();
2104 assert(getSrcSize() == 2);
2105 assert(getSrc(1)->getType() == IceType_i64 ||
2106 getSrc(1)->getType() == IceType_f64);
2107 Str << "\tmovq\t";
2108 getSrc(0)->emit(Func);
2109 Str << ", ";
2110 getSrc(1)->emit(Func);
2111 }
2112
2113 void InstX8632StoreQ::emitIAS(const Cfg *Func) const {
2114 X8632::AssemblerX8632 *Asm = Func->getAssembler<X8632::AssemblerX8632>();
2115 assert(getSrcSize() == 2);
2116 const auto SrcVar = llvm::cast<Variable>(getSrc(0));
2117 const auto DestMem = llvm::cast<OperandX8632Mem>(getSrc(1));
2118 assert(DestMem->getSegmentRegister() == OperandX8632Mem::DefaultSegment);
2119 assert(SrcVar->hasReg());
2120 Asm->movq(DestMem->toAsmAddress(Asm),
2121 RegX8632::getEncodedXmm(SrcVar->getRegNum()));
2122 }
2123
2124 void InstX8632StoreQ::dump(const Cfg *Func) const {
2125 if (!BuildDefs::dump())
2126 return;
2127 Ostream &Str = Func->getContext()->getStrDump();
2128 Str << "storeq." << getSrc(0)->getType() << " ";
2129 getSrc(1)->dump(Func);
2130 Str << ", ";
2131 getSrc(0)->dump(Func);
2132 }
2133
2134 template <> void InstX8632Lea::emit(const Cfg *Func) const {
2135 if (!BuildDefs::dump())
2136 return;
2137 Ostream &Str = Func->getContext()->getStrEmit();
2138 assert(getSrcSize() == 1);
2139 assert(getDest()->hasReg());
2140 Str << "\tleal\t";
2141 Operand *Src0 = getSrc(0);
2142 if (const auto Src0Var = llvm::dyn_cast<Variable>(Src0)) {
2143 Type Ty = Src0Var->getType();
2144 // lea on x86-32 doesn't accept mem128 operands, so cast VSrc0 to an
2145 // acceptable type.
2146 Src0Var->asType(isVectorType(Ty) ? IceType_i32 : Ty)->emit(Func);
2147 } else {
2148 Src0->emit(Func);
2149 }
2150 Str << ", ";
2151 getDest()->emit(Func);
2152 }
2153
2154 template <> void InstX8632Mov::emit(const Cfg *Func) const {
2155 if (!BuildDefs::dump())
2156 return;
2157 Ostream &Str = Func->getContext()->getStrEmit();
2158 assert(getSrcSize() == 1);
2159 Operand *Src = getSrc(0);
2160 Type SrcTy = Src->getType();
2161 Type DestTy = getDest()->getType();
2162 Str << "\tmov" << (!isScalarFloatingType(DestTy)
2163 ? getWidthString(SrcTy)
2164 : TypeX8632Attributes[DestTy].SdSsString) << "\t";
2165 // For an integer truncation operation, src is wider than dest.
2166 // Ideally, we use a mov instruction whose data width matches the
2167 // narrower dest. This is a problem if e.g. src is a register like
2168 // esi or si where there is no 8-bit version of the register. To be
2169 // safe, we instead widen the dest to match src. This works even
2170 // for stack-allocated dest variables because typeWidthOnStack()
2171 // pads to a 4-byte boundary even if only a lower portion is used.
2172 // TODO: This assert disallows usages such as copying a floating point
2173 // value between a vector and a scalar (which movss is used for).
2174 // Clean this up.
2175 assert(Func->getTarget()->typeWidthInBytesOnStack(DestTy) ==
2176 Func->getTarget()->typeWidthInBytesOnStack(SrcTy));
2177 Src->emit(Func);
2178 Str << ", ";
2179 getDest()->asType(SrcTy)->emit(Func);
2180 }
2181
2182 template <> void InstX8632Mov::emitIAS(const Cfg *Func) const {
2183 assert(getSrcSize() == 1);
2184 const Variable *Dest = getDest();
2185 const Operand *Src = getSrc(0);
2186 Type DestTy = Dest->getType();
2187 Type SrcTy = Src->getType();
2188 // Mov can be used for GPRs or XMM registers. Also, the type does not
2189 // necessarily match (Mov can be used for bitcasts). However, when
2190 // the type does not match, one of the operands must be a register.
2191 // Thus, the strategy is to find out if Src or Dest are a register,
2192 // then use that register's type to decide on which emitter set to use.
2193 // The emitter set will include reg-reg movs, but that case should
2194 // be unused when the types don't match.
2195 static const X8632::AssemblerX8632::XmmEmitterRegOp XmmRegEmitter = {
2196 &X8632::AssemblerX8632::movss, &X8632::AssemblerX8632::movss};
2197 static const X8632::AssemblerX8632::GPREmitterRegOp GPRRegEmitter = {
2198 &X8632::AssemblerX8632::mov, &X8632::AssemblerX8632::mov,
2199 &X8632::AssemblerX8632::mov};
2200 static const X8632::AssemblerX8632::GPREmitterAddrOp GPRAddrEmitter = {
2201 &X8632::AssemblerX8632::mov, &X8632::AssemblerX8632::mov};
2202 // For an integer truncation operation, src is wider than dest.
2203 // Ideally, we use a mov instruction whose data width matches the
2204 // narrower dest. This is a problem if e.g. src is a register like
2205 // esi or si where there is no 8-bit version of the register. To be
2206 // safe, we instead widen the dest to match src. This works even
2207 // for stack-allocated dest variables because typeWidthOnStack()
2208 // pads to a 4-byte boundary even if only a lower portion is used.
2209 // TODO: This assert disallows usages such as copying a floating point
2210 // value between a vector and a scalar (which movss is used for).
2211 // Clean this up.
2212 assert(Func->getTarget()->typeWidthInBytesOnStack(getDest()->getType()) ==
2213 Func->getTarget()->typeWidthInBytesOnStack(Src->getType()));
2214 if (Dest->hasReg()) {
2215 if (isScalarFloatingType(DestTy)) {
2216 emitIASRegOpTyXMM(Func, DestTy, Dest, Src, XmmRegEmitter);
2217 return;
2218 } else {
2219 assert(isScalarIntegerType(DestTy));
2220 // Widen DestTy for truncation (see above note). We should only do this
2221 // when both Src and Dest are integer types.
2222 if (isScalarIntegerType(SrcTy)) {
2223 DestTy = SrcTy;
2224 }
2225 emitIASRegOpTyGPR(Func, DestTy, Dest, Src, GPRRegEmitter);
2226 return;
2227 }
2228 } else {
2229 // Dest must be Stack and Src *could* be a register. Use Src's type
2230 // to decide on the emitters.
2231 X8632::Traits::Address StackAddr(
2232 static_cast<TargetX8632 *>(Func->getTarget())
2233 ->stackVarToAsmOperand(Dest));
2234 if (isScalarFloatingType(SrcTy)) {
2235 // Src must be a register.
2236 const auto SrcVar = llvm::cast<Variable>(Src);
2237 assert(SrcVar->hasReg());
2238 X8632::AssemblerX8632 *Asm = Func->getAssembler<X8632::AssemblerX8632>();
2239 Asm->movss(SrcTy, StackAddr,
2240 RegX8632::getEncodedXmm(SrcVar->getRegNum()));
2241 return;
2242 } else {
2243 // Src can be a register or immediate.
2244 assert(isScalarIntegerType(SrcTy));
2245 emitIASAddrOpTyGPR(Func, SrcTy, StackAddr, Src, GPRAddrEmitter);
2246 return;
2247 }
2248 return;
2249 }
2250 }
2251
2252 template <> void InstX8632Movd::emitIAS(const Cfg *Func) const {
2253 X8632::AssemblerX8632 *Asm = Func->getAssembler<X8632::AssemblerX8632>();
2254 assert(getSrcSize() == 1);
2255 const Variable *Dest = getDest();
2256 const auto SrcVar = llvm::cast<Variable>(getSrc(0));
2257 // For insert/extract element (one of Src/Dest is an Xmm vector and
2258 // the other is an int type).
2259 if (SrcVar->getType() == IceType_i32) {
2260 assert(isVectorType(Dest->getType()));
2261 assert(Dest->hasReg());
2262 RegX8632::XmmRegister DestReg = RegX8632::getEncodedXmm(Dest->getRegNum());
2263 if (SrcVar->hasReg()) {
2264 Asm->movd(DestReg, RegX8632::getEncodedGPR(SrcVar->getRegNum()));
2265 } else {
2266 X8632::Traits::Address StackAddr(
2267 static_cast<TargetX8632 *>(Func->getTarget())
2268 ->stackVarToAsmOperand(SrcVar));
2269 Asm->movd(DestReg, StackAddr);
2270 }
2271 } else {
2272 assert(isVectorType(SrcVar->getType()));
2273 assert(SrcVar->hasReg());
2274 assert(Dest->getType() == IceType_i32);
2275 RegX8632::XmmRegister SrcReg = RegX8632::getEncodedXmm(SrcVar->getRegNum());
2276 if (Dest->hasReg()) {
2277 Asm->movd(RegX8632::getEncodedGPR(Dest->getRegNum()), SrcReg);
2278 } else {
2279 X8632::Traits::Address StackAddr(
2280 static_cast<TargetX8632 *>(Func->getTarget())
2281 ->stackVarToAsmOperand(Dest));
2282 Asm->movd(StackAddr, SrcReg);
2283 }
2284 }
2285 }
2286
2287 template <> void InstX8632Movp::emit(const Cfg *Func) const {
2288 if (!BuildDefs::dump())
2289 return;
2290 // TODO(wala,stichnot): movups works with all vector operands, but
2291 // there exist other instructions (movaps, movdqa, movdqu) that may
2292 // perform better, depending on the data type and alignment of the
2293 // operands.
2294 Ostream &Str = Func->getContext()->getStrEmit();
2295 assert(getSrcSize() == 1);
2296 Str << "\tmovups\t";
2297 getSrc(0)->emit(Func);
2298 Str << ", ";
2299 getDest()->emit(Func);
2300 }
2301
2302 template <> void InstX8632Movp::emitIAS(const Cfg *Func) const {
2303 assert(getSrcSize() == 1);
2304 assert(isVectorType(getDest()->getType()));
2305 const Variable *Dest = getDest();
2306 const Operand *Src = getSrc(0);
2307 const static X8632::AssemblerX8632::XmmEmitterMovOps Emitter = {
2308 &X8632::AssemblerX8632::movups, &X8632::AssemblerX8632::movups,
2309 &X8632::AssemblerX8632::movups};
2310 emitIASMovlikeXMM(Func, Dest, Src, Emitter);
2311 }
2312
2313 template <> void InstX8632Movq::emit(const Cfg *Func) const {
2314 if (!BuildDefs::dump())
2315 return;
2316 Ostream &Str = Func->getContext()->getStrEmit();
2317 assert(getSrcSize() == 1);
2318 assert(getDest()->getType() == IceType_i64 ||
2319 getDest()->getType() == IceType_f64);
2320 Str << "\tmovq\t";
2321 getSrc(0)->emit(Func);
2322 Str << ", ";
2323 getDest()->emit(Func);
2324 }
2325
2326 template <> void InstX8632Movq::emitIAS(const Cfg *Func) const {
2327 assert(getSrcSize() == 1);
2328 assert(getDest()->getType() == IceType_i64 ||
2329 getDest()->getType() == IceType_f64);
2330 const Variable *Dest = getDest();
2331 const Operand *Src = getSrc(0);
2332 const static X8632::AssemblerX8632::XmmEmitterMovOps Emitter = {
2333 &X8632::AssemblerX8632::movq, &X8632::AssemblerX8632::movq,
2334 &X8632::AssemblerX8632::movq};
2335 emitIASMovlikeXMM(Func, Dest, Src, Emitter);
2336 }
2337
2338 template <> void InstX8632MovssRegs::emitIAS(const Cfg *Func) const {
2339 // This is Binop variant is only intended to be used for reg-reg moves
2340 // where part of the Dest register is untouched.
2341 assert(getSrcSize() == 2);
2342 const Variable *Dest = getDest();
2343 assert(Dest == getSrc(0));
2344 const auto SrcVar = llvm::cast<Variable>(getSrc(1));
2345 assert(Dest->hasReg() && SrcVar->hasReg());
2346 X8632::AssemblerX8632 *Asm = Func->getAssembler<X8632::AssemblerX8632>();
2347 Asm->movss(IceType_f32, RegX8632::getEncodedXmm(Dest->getRegNum()),
2348 RegX8632::getEncodedXmm(SrcVar->getRegNum()));
2349 }
2350
2351 template <> void InstX8632Movsx::emitIAS(const Cfg *Func) const {
2352 assert(getSrcSize() == 1);
2353 const Variable *Dest = getDest();
2354 const Operand *Src = getSrc(0);
2355 // Dest must be a > 8-bit register, but Src can be 8-bit. In practice
2356 // we just use the full register for Dest to avoid having an
2357 // OperandSizeOverride prefix. It also allows us to only dispatch on SrcTy.
2358 Type SrcTy = Src->getType();
2359 assert(typeWidthInBytes(Dest->getType()) > 1);
2360 assert(typeWidthInBytes(Dest->getType()) > typeWidthInBytes(SrcTy));
2361 emitIASRegOpTyGPR<false, true>(Func, SrcTy, Dest, Src, Emitter);
2362 }
2363
2364 template <> void InstX8632Movzx::emitIAS(const Cfg *Func) const {
2365 assert(getSrcSize() == 1);
2366 const Variable *Dest = getDest();
2367 const Operand *Src = getSrc(0);
2368 Type SrcTy = Src->getType();
2369 assert(typeWidthInBytes(Dest->getType()) > 1);
2370 assert(typeWidthInBytes(Dest->getType()) > typeWidthInBytes(SrcTy));
2371 emitIASRegOpTyGPR<false, true>(Func, SrcTy, Dest, Src, Emitter);
2372 }
2373
2374 void InstX8632Nop::emit(const Cfg *Func) const {
2375 if (!BuildDefs::dump())
2376 return;
2377 Ostream &Str = Func->getContext()->getStrEmit();
2378 // TODO: Emit the right code for each variant.
2379 Str << "\tnop\t# variant = " << Variant;
2380 }
2381
2382 void InstX8632Nop::emitIAS(const Cfg *Func) const {
2383 X8632::AssemblerX8632 *Asm = Func->getAssembler<X8632::AssemblerX8632>();
2384 // TODO: Emit the right code for the variant.
2385 Asm->nop();
2386 }
2387
2388 void InstX8632Nop::dump(const Cfg *Func) const {
2389 if (!BuildDefs::dump())
2390 return;
2391 Ostream &Str = Func->getContext()->getStrDump();
2392 Str << "nop (variant = " << Variant << ")";
2393 }
2394
2395 void InstX8632Fld::emit(const Cfg *Func) const {
2396 if (!BuildDefs::dump())
2397 return;
2398 Ostream &Str = Func->getContext()->getStrEmit();
2399 assert(getSrcSize() == 1);
2400 Type Ty = getSrc(0)->getType();
2401 SizeT Width = typeWidthInBytes(Ty);
2402 const auto Var = llvm::dyn_cast<Variable>(getSrc(0));
2403 if (Var && Var->hasReg()) {
2404 // This is a physical xmm register, so we need to spill it to a
2405 // temporary stack slot.
2406 Str << "\tsubl\t$" << Width << ", %esp"
2407 << "\n";
2408 Str << "\tmov" << TypeX8632Attributes[Ty].SdSsString << "\t";
2409 Var->emit(Func);
2410 Str << ", (%esp)\n";
2411 Str << "\tfld" << getFldString(Ty) << "\t"
2412 << "(%esp)\n";
2413 Str << "\taddl\t$" << Width << ", %esp";
2414 return;
2415 }
2416 Str << "\tfld" << getFldString(Ty) << "\t";
2417 getSrc(0)->emit(Func);
2418 }
2419
2420 void InstX8632Fld::emitIAS(const Cfg *Func) const {
2421 X8632::AssemblerX8632 *Asm = Func->getAssembler<X8632::AssemblerX8632>();
2422 assert(getSrcSize() == 1);
2423 const Operand *Src = getSrc(0);
2424 Type Ty = Src->getType();
2425 if (const auto Var = llvm::dyn_cast<Variable>(Src)) {
2426 if (Var->hasReg()) {
2427 // This is a physical xmm register, so we need to spill it to a
2428 // temporary stack slot.
2429 X8632::Immediate Width(typeWidthInBytes(Ty));
2430 Asm->sub(IceType_i32, RegX8632::Encoded_Reg_esp, Width);
2431 X8632::Traits::Address StackSlot =
2432 X8632::Traits::Address(RegX8632::Encoded_Reg_esp, 0);
2433 Asm->movss(Ty, StackSlot, RegX8632::getEncodedXmm(Var->getRegNum()));
2434 Asm->fld(Ty, StackSlot);
2435 Asm->add(IceType_i32, RegX8632::Encoded_Reg_esp, Width);
2436 } else {
2437 X8632::Traits::Address StackAddr(
2438 static_cast<TargetX8632 *>(Func->getTarget())
2439 ->stackVarToAsmOperand(Var));
2440 Asm->fld(Ty, StackAddr);
2441 }
2442 } else if (const auto Mem = llvm::dyn_cast<OperandX8632Mem>(Src)) {
2443 assert(Mem->getSegmentRegister() == OperandX8632Mem::DefaultSegment);
2444 Asm->fld(Ty, Mem->toAsmAddress(Asm));
2445 } else if (const auto Imm = llvm::dyn_cast<Constant>(Src)) {
2446 Asm->fld(Ty, X8632::Traits::Address::ofConstPool(Asm, Imm));
2447 } else {
2448 llvm_unreachable("Unexpected operand type");
2449 }
2450 }
2451
2452 void InstX8632Fld::dump(const Cfg *Func) const {
2453 if (!BuildDefs::dump())
2454 return;
2455 Ostream &Str = Func->getContext()->getStrDump();
2456 Str << "fld." << getSrc(0)->getType() << " ";
2457 dumpSources(Func);
2458 }
2459
2460 void InstX8632Fstp::emit(const Cfg *Func) const {
2461 if (!BuildDefs::dump())
2462 return;
2463 Ostream &Str = Func->getContext()->getStrEmit();
2464 assert(getSrcSize() == 0);
2465 // TODO(jvoung,stichnot): Utilize this by setting Dest to nullptr to
2466 // "partially" delete the fstp if the Dest is unused.
2467 // Even if Dest is unused, the fstp should be kept for the SideEffects
2468 // of popping the stack.
2469 if (!getDest()) {
2470 Str << "\tfstp\tst(0)";
2471 return;
2472 }
2473 Type Ty = getDest()->getType();
2474 size_t Width = typeWidthInBytes(Ty);
2475 if (!getDest()->hasReg()) {
2476 Str << "\tfstp" << getFldString(Ty) << "\t";
2477 getDest()->emit(Func);
2478 return;
2479 }
2480 // Dest is a physical (xmm) register, so st(0) needs to go through
2481 // memory. Hack this by creating a temporary stack slot, spilling
2482 // st(0) there, loading it into the xmm register, and deallocating
2483 // the stack slot.
2484 Str << "\tsubl\t$" << Width << ", %esp\n";
2485 Str << "\tfstp" << getFldString(Ty) << "\t"
2486 << "(%esp)\n";
2487 Str << "\tmov" << TypeX8632Attributes[Ty].SdSsString << "\t"
2488 << "(%esp), ";
2489 getDest()->emit(Func);
2490 Str << "\n";
2491 Str << "\taddl\t$" << Width << ", %esp";
2492 }
2493
2494 void InstX8632Fstp::emitIAS(const Cfg *Func) const {
2495 X8632::AssemblerX8632 *Asm = Func->getAssembler<X8632::AssemblerX8632>();
2496 assert(getSrcSize() == 0);
2497 const Variable *Dest = getDest();
2498 // TODO(jvoung,stichnot): Utilize this by setting Dest to nullptr to
2499 // "partially" delete the fstp if the Dest is unused.
2500 // Even if Dest is unused, the fstp should be kept for the SideEffects
2501 // of popping the stack.
2502 if (!Dest) {
2503 Asm->fstp(RegX8632::getEncodedSTReg(0));
2504 return;
2505 }
2506 Type Ty = Dest->getType();
2507 if (!Dest->hasReg()) {
2508 X8632::Traits::Address StackAddr(
2509 static_cast<TargetX8632 *>(Func->getTarget())
2510 ->stackVarToAsmOperand(Dest));
2511 Asm->fstp(Ty, StackAddr);
2512 } else {
2513 // Dest is a physical (xmm) register, so st(0) needs to go through
2514 // memory. Hack this by creating a temporary stack slot, spilling
2515 // st(0) there, loading it into the xmm register, and deallocating
2516 // the stack slot.
2517 X8632::Immediate Width(typeWidthInBytes(Ty));
2518 Asm->sub(IceType_i32, RegX8632::Encoded_Reg_esp, Width);
2519 X8632::Traits::Address StackSlot =
2520 X8632::Traits::Address(RegX8632::Encoded_Reg_esp, 0);
2521 Asm->fstp(Ty, StackSlot);
2522 Asm->movss(Ty, RegX8632::getEncodedXmm(Dest->getRegNum()), StackSlot);
2523 Asm->add(IceType_i32, RegX8632::Encoded_Reg_esp, Width);
2524 }
2525 }
2526
2527 void InstX8632Fstp::dump(const Cfg *Func) const {
2528 if (!BuildDefs::dump())
2529 return;
2530 Ostream &Str = Func->getContext()->getStrDump();
2531 dumpDest(Func);
2532 Str << " = fstp." << getDest()->getType() << ", st(0)";
2533 }
2534
2535 template <> void InstX8632Pcmpeq::emit(const Cfg *Func) const {
2536 if (!BuildDefs::dump())
2537 return;
2538 char buf[30];
2539 snprintf(buf, llvm::array_lengthof(buf), "pcmpeq%s",
2540 TypeX8632Attributes[getDest()->getType()].PackString);
2541 emitTwoAddress(buf, this, Func);
2542 }
2543
2544 template <> void InstX8632Pcmpgt::emit(const Cfg *Func) const {
2545 if (!BuildDefs::dump())
2546 return;
2547 char buf[30];
2548 snprintf(buf, llvm::array_lengthof(buf), "pcmpgt%s",
2549 TypeX8632Attributes[getDest()->getType()].PackString);
2550 emitTwoAddress(buf, this, Func);
2551 }
2552
2553 template <> void InstX8632Pextr::emit(const Cfg *Func) const {
2554 if (!BuildDefs::dump())
2555 return;
2556 Ostream &Str = Func->getContext()->getStrEmit();
2557 assert(getSrcSize() == 2);
2558 // pextrb and pextrd are SSE4.1 instructions.
2559 assert(getSrc(0)->getType() == IceType_v8i16 ||
2560 getSrc(0)->getType() == IceType_v8i1 ||
2561 static_cast<TargetX8632 *>(Func->getTarget())->getInstructionSet() >=
2562 X8632::Traits::SSE4_1);
2563 Str << "\t" << Opcode << TypeX8632Attributes[getSrc(0)->getType()].PackString
2564 << "\t";
2565 getSrc(1)->emit(Func);
2566 Str << ", ";
2567 getSrc(0)->emit(Func);
2568 Str << ", ";
2569 Variable *Dest = getDest();
2570 // pextrw must take a register dest. There is an SSE4.1 version that takes
2571 // a memory dest, but we aren't using it. For uniformity, just restrict
2572 // them all to have a register dest for now.
2573 assert(Dest->hasReg());
2574 Dest->asType(IceType_i32)->emit(Func);
2575 }
2576
2577 template <> void InstX8632Pextr::emitIAS(const Cfg *Func) const {
2578 assert(getSrcSize() == 2);
2579 // pextrb and pextrd are SSE4.1 instructions.
2580 const Variable *Dest = getDest();
2581 Type DispatchTy = Dest->getType();
2582 assert(DispatchTy == IceType_i16 ||
2583 static_cast<TargetX8632 *>(Func->getTarget())->getInstructionSet() >=
2584 X8632::Traits::SSE4_1);
2585 // pextrw must take a register dest. There is an SSE4.1 version that takes
2586 // a memory dest, but we aren't using it. For uniformity, just restrict
2587 // them all to have a register dest for now.
2588 assert(Dest->hasReg());
2589 // pextrw's Src(0) must be a register (both SSE4.1 and SSE2).
2590 assert(llvm::cast<Variable>(getSrc(0))->hasReg());
2591 static const X8632::AssemblerX8632::ThreeOpImmEmitter<
2592 RegX8632::GPRRegister, RegX8632::XmmRegister> Emitter = {
2593 &X8632::AssemblerX8632::pextr, nullptr};
2594 emitIASThreeOpImmOps<RegX8632::GPRRegister, RegX8632::XmmRegister,
2595 RegX8632::getEncodedGPR, RegX8632::getEncodedXmm>(
2596 Func, DispatchTy, Dest, getSrc(0), getSrc(1), Emitter);
2597 }
2598
2599 template <> void InstX8632Pinsr::emit(const Cfg *Func) const {
2600 if (!BuildDefs::dump())
2601 return;
2602 Ostream &Str = Func->getContext()->getStrEmit();
2603 assert(getSrcSize() == 3);
2604 // pinsrb and pinsrd are SSE4.1 instructions.
2605 assert(getDest()->getType() == IceType_v8i16 ||
2606 getDest()->getType() == IceType_v8i1 ||
2607 static_cast<TargetX8632 *>(Func->getTarget())->getInstructionSet() >=
2608 X8632::Traits::SSE4_1);
2609 Str << "\t" << Opcode << TypeX8632Attributes[getDest()->getType()].PackString
2610 << "\t";
2611 getSrc(2)->emit(Func);
2612 Str << ", ";
2613 Operand *Src1 = getSrc(1);
2614 if (const auto Src1Var = llvm::dyn_cast<Variable>(Src1)) {
2615 // If src1 is a register, it should always be r32.
2616 if (Src1Var->hasReg()) {
2617 Src1Var->asType(IceType_i32)->emit(Func);
2618 } else {
2619 Src1Var->emit(Func);
2620 }
2621 } else {
2622 Src1->emit(Func);
2623 }
2624 Str << ", ";
2625 getDest()->emit(Func);
2626 }
2627
2628 template <> void InstX8632Pinsr::emitIAS(const Cfg *Func) const {
2629 assert(getSrcSize() == 3);
2630 assert(getDest() == getSrc(0));
2631 // pinsrb and pinsrd are SSE4.1 instructions.
2632 const Operand *Src0 = getSrc(1);
2633 Type DispatchTy = Src0->getType();
2634 assert(DispatchTy == IceType_i16 ||
2635 static_cast<TargetX8632 *>(Func->getTarget())->getInstructionSet() >=
2636 X8632::Traits::SSE4_1);
2637 // If src1 is a register, it should always be r32 (this should fall out
2638 // from the encodings for ByteRegs overlapping the encodings for r32),
2639 // but we have to trust the regalloc to not choose "ah", where it
2640 // doesn't overlap.
2641 static const X8632::AssemblerX8632::ThreeOpImmEmitter<
2642 RegX8632::XmmRegister, RegX8632::GPRRegister> Emitter = {
2643 &X8632::AssemblerX8632::pinsr, &X8632::AssemblerX8632::pinsr};
2644 emitIASThreeOpImmOps<RegX8632::XmmRegister, RegX8632::GPRRegister,
2645 RegX8632::getEncodedXmm, RegX8632::getEncodedGPR>(
2646 Func, DispatchTy, getDest(), Src0, getSrc(2), Emitter);
2647 }
2648
2649 template <> void InstX8632Pshufd::emitIAS(const Cfg *Func) const {
2650 assert(getSrcSize() == 2);
2651 const Variable *Dest = getDest();
2652 Type Ty = Dest->getType();
2653 static const X8632::AssemblerX8632::ThreeOpImmEmitter<
2654 RegX8632::XmmRegister, RegX8632::XmmRegister> Emitter = {
2655 &X8632::AssemblerX8632::pshufd, &X8632::AssemblerX8632::pshufd};
2656 emitIASThreeOpImmOps<RegX8632::XmmRegister, RegX8632::XmmRegister,
2657 RegX8632::getEncodedXmm, RegX8632::getEncodedXmm>(
2658 Func, Ty, Dest, getSrc(0), getSrc(1), Emitter);
2659 }
2660
2661 template <> void InstX8632Shufps::emitIAS(const Cfg *Func) const {
2662 assert(getSrcSize() == 3);
2663 const Variable *Dest = getDest();
2664 assert(Dest == getSrc(0));
2665 Type Ty = Dest->getType();
2666 static const X8632::AssemblerX8632::ThreeOpImmEmitter<
2667 RegX8632::XmmRegister, RegX8632::XmmRegister> Emitter = {
2668 &X8632::AssemblerX8632::shufps, &X8632::AssemblerX8632::shufps};
2669 emitIASThreeOpImmOps<RegX8632::XmmRegister, RegX8632::XmmRegister,
2670 RegX8632::getEncodedXmm, RegX8632::getEncodedXmm>(
2671 Func, Ty, Dest, getSrc(1), getSrc(2), Emitter);
2672 }
2673
2674 void InstX8632Pop::emit(const Cfg *Func) const {
2675 if (!BuildDefs::dump())
2676 return;
2677 Ostream &Str = Func->getContext()->getStrEmit();
2678 assert(getSrcSize() == 0);
2679 Str << "\tpop\t";
2680 getDest()->emit(Func);
2681 }
2682
2683 void InstX8632Pop::emitIAS(const Cfg *Func) const {
2684 assert(getSrcSize() == 0);
2685 X8632::AssemblerX8632 *Asm = Func->getAssembler<X8632::AssemblerX8632>();
2686 if (getDest()->hasReg()) {
2687 Asm->popl(RegX8632::getEncodedGPR(getDest()->getRegNum()));
2688 } else {
2689 Asm->popl(static_cast<TargetX8632 *>(Func->getTarget())
2690 ->stackVarToAsmOperand(getDest()));
2691 }
2692 }
2693
2694 void InstX8632Pop::dump(const Cfg *Func) const {
2695 if (!BuildDefs::dump())
2696 return;
2697 Ostream &Str = Func->getContext()->getStrDump();
2698 dumpDest(Func);
2699 Str << " = pop." << getDest()->getType() << " ";
2700 }
2701
2702 void InstX8632AdjustStack::emit(const Cfg *Func) const {
2703 if (!BuildDefs::dump())
2704 return;
2705 Ostream &Str = Func->getContext()->getStrEmit();
2706 Str << "\tsubl\t$" << Amount << ", %esp";
2707 Func->getTarget()->updateStackAdjustment(Amount);
2708 }
2709
2710 void InstX8632AdjustStack::emitIAS(const Cfg *Func) const {
2711 X8632::AssemblerX8632 *Asm = Func->getAssembler<X8632::AssemblerX8632>();
2712 Asm->sub(IceType_i32, RegX8632::Encoded_Reg_esp, X8632::Immediate(Amount));
2713 Func->getTarget()->updateStackAdjustment(Amount);
2714 }
2715
2716 void InstX8632AdjustStack::dump(const Cfg *Func) const {
2717 if (!BuildDefs::dump())
2718 return;
2719 Ostream &Str = Func->getContext()->getStrDump();
2720 Str << "esp = sub.i32 esp, " << Amount;
2721 }
2722
2723 void InstX8632Push::emit(const Cfg *Func) const {
2724 if (!BuildDefs::dump())
2725 return;
2726 Ostream &Str = Func->getContext()->getStrEmit();
2727 assert(getSrcSize() == 1);
2728 // Push is currently only used for saving GPRs.
2729 const auto Var = llvm::cast<Variable>(getSrc(0));
2730 assert(Var->hasReg());
2731 Str << "\tpush\t";
2732 Var->emit(Func);
2733 }
2734
2735 void InstX8632Push::emitIAS(const Cfg *Func) const {
2736 assert(getSrcSize() == 1);
2737 // Push is currently only used for saving GPRs.
2738 const auto Var = llvm::cast<Variable>(getSrc(0));
2739 assert(Var->hasReg());
2740 X8632::AssemblerX8632 *Asm = Func->getAssembler<X8632::AssemblerX8632>();
2741 Asm->pushl(RegX8632::getEncodedGPR(Var->getRegNum()));
2742 }
2743
2744 void InstX8632Push::dump(const Cfg *Func) const {
2745 if (!BuildDefs::dump())
2746 return;
2747 Ostream &Str = Func->getContext()->getStrDump();
2748 Str << "push." << getSrc(0)->getType() << " ";
2749 dumpSources(Func);
2750 }
2751
2752 template <> void InstX8632Psll::emit(const Cfg *Func) const {
2753 if (!BuildDefs::dump())
2754 return;
2755 assert(getDest()->getType() == IceType_v8i16 ||
2756 getDest()->getType() == IceType_v8i1 ||
2757 getDest()->getType() == IceType_v4i32 ||
2758 getDest()->getType() == IceType_v4i1);
2759 char buf[30];
2760 snprintf(buf, llvm::array_lengthof(buf), "psll%s",
2761 TypeX8632Attributes[getDest()->getType()].PackString);
2762 emitTwoAddress(buf, this, Func);
2763 }
2764
2765 template <> void InstX8632Psra::emit(const Cfg *Func) const {
2766 if (!BuildDefs::dump())
2767 return;
2768 assert(getDest()->getType() == IceType_v8i16 ||
2769 getDest()->getType() == IceType_v8i1 ||
2770 getDest()->getType() == IceType_v4i32 ||
2771 getDest()->getType() == IceType_v4i1);
2772 char buf[30];
2773 snprintf(buf, llvm::array_lengthof(buf), "psra%s",
2774 TypeX8632Attributes[getDest()->getType()].PackString);
2775 emitTwoAddress(buf, this, Func);
2776 }
2777
2778 template <> void InstX8632Psrl::emit(const Cfg *Func) const {
2779 if (!BuildDefs::dump())
2780 return;
2781 char buf[30];
2782 snprintf(buf, llvm::array_lengthof(buf), "psrl%s",
2783 TypeX8632Attributes[getDest()->getType()].PackString);
2784 emitTwoAddress(buf, this, Func);
2785 }
2786
2787 void InstX8632Ret::emit(const Cfg *Func) const {
2788 if (!BuildDefs::dump())
2789 return;
2790 Ostream &Str = Func->getContext()->getStrEmit();
2791 Str << "\tret";
2792 }
2793
2794 void InstX8632Ret::emitIAS(const Cfg *Func) const {
2795 X8632::AssemblerX8632 *Asm = Func->getAssembler<X8632::AssemblerX8632>();
2796 Asm->ret();
2797 }
2798
2799 void InstX8632Ret::dump(const Cfg *Func) const {
2800 if (!BuildDefs::dump())
2801 return;
2802 Ostream &Str = Func->getContext()->getStrDump();
2803 Type Ty = (getSrcSize() == 0 ? IceType_void : getSrc(0)->getType());
2804 Str << "ret." << Ty << " ";
2805 dumpSources(Func);
2806 }
2807
2808 void InstX8632Setcc::emit(const Cfg *Func) const {
2809 if (!BuildDefs::dump())
2810 return;
2811 Ostream &Str = Func->getContext()->getStrEmit();
2812 Str << "\tset" << InstX8632BrAttributes[Condition].DisplayString << "\t";
2813 Dest->emit(Func);
2814 }
2815
2816 void InstX8632Setcc::emitIAS(const Cfg *Func) const {
2817 assert(Condition != X8632::Traits::Cond::Br_None);
2818 assert(getDest()->getType() == IceType_i1);
2819 assert(getSrcSize() == 0);
2820 X8632::AssemblerX8632 *Asm = Func->getAssembler<X8632::AssemblerX8632>();
2821 if (getDest()->hasReg())
2822 Asm->setcc(Condition, RegX8632::getEncodedByteReg(getDest()->getRegNum()));
2823 else
2824 Asm->setcc(Condition, static_cast<TargetX8632 *>(Func->getTarget())
2825 ->stackVarToAsmOperand(getDest()));
2826 return;
2827 }
2828
2829 void InstX8632Setcc::dump(const Cfg *Func) const {
2830 if (!BuildDefs::dump())
2831 return;
2832 Ostream &Str = Func->getContext()->getStrDump();
2833 Str << "setcc." << InstX8632BrAttributes[Condition].DisplayString << " ";
2834 dumpDest(Func);
2835 }
2836
2837 void InstX8632Xadd::emit(const Cfg *Func) const {
2838 if (!BuildDefs::dump())
2839 return;
2840 Ostream &Str = Func->getContext()->getStrEmit();
2841 if (Locked) {
2842 Str << "\tlock";
2843 }
2844 Str << "\txadd" << getWidthString(getSrc(0)->getType()) << "\t";
2845 getSrc(1)->emit(Func);
2846 Str << ", ";
2847 getSrc(0)->emit(Func);
2848 }
2849
2850 void InstX8632Xadd::emitIAS(const Cfg *Func) const {
2851 assert(getSrcSize() == 2);
2852 X8632::AssemblerX8632 *Asm = Func->getAssembler<X8632::AssemblerX8632>();
2853 Type Ty = getSrc(0)->getType();
2854 const auto Mem = llvm::cast<OperandX8632Mem>(getSrc(0));
2855 assert(Mem->getSegmentRegister() == OperandX8632Mem::DefaultSegment);
2856 const X8632::Traits::Address Addr = Mem->toAsmAddress(Asm);
2857 const auto VarReg = llvm::cast<Variable>(getSrc(1));
2858 assert(VarReg->hasReg());
2859 const RegX8632::GPRRegister Reg =
2860 RegX8632::getEncodedGPR(VarReg->getRegNum());
2861 Asm->xadd(Ty, Addr, Reg, Locked);
2862 }
2863
2864 void InstX8632Xadd::dump(const Cfg *Func) const {
2865 if (!BuildDefs::dump())
2866 return;
2867 Ostream &Str = Func->getContext()->getStrDump();
2868 if (Locked) {
2869 Str << "lock ";
2870 }
2871 Type Ty = getSrc(0)->getType();
2872 Str << "xadd." << Ty << " ";
2873 dumpSources(Func);
2874 }
2875
2876 void InstX8632Xchg::emit(const Cfg *Func) const {
2877 if (!BuildDefs::dump())
2878 return;
2879 Ostream &Str = Func->getContext()->getStrEmit();
2880 Str << "\txchg" << getWidthString(getSrc(0)->getType()) << "\t";
2881 getSrc(1)->emit(Func);
2882 Str << ", ";
2883 getSrc(0)->emit(Func);
2884 }
2885
2886 void InstX8632Xchg::emitIAS(const Cfg *Func) const {
2887 assert(getSrcSize() == 2);
2888 X8632::AssemblerX8632 *Asm = Func->getAssembler<X8632::AssemblerX8632>();
2889 Type Ty = getSrc(0)->getType();
2890 const auto Mem = llvm::cast<OperandX8632Mem>(getSrc(0));
2891 assert(Mem->getSegmentRegister() == OperandX8632Mem::DefaultSegment);
2892 const X8632::Traits::Address Addr = Mem->toAsmAddress(Asm);
2893 const auto VarReg = llvm::cast<Variable>(getSrc(1));
2894 assert(VarReg->hasReg());
2895 const RegX8632::GPRRegister Reg =
2896 RegX8632::getEncodedGPR(VarReg->getRegNum());
2897 Asm->xchg(Ty, Addr, Reg);
2898 }
2899
2900 void InstX8632Xchg::dump(const Cfg *Func) const {
2901 if (!BuildDefs::dump())
2902 return;
2903 Ostream &Str = Func->getContext()->getStrDump();
2904 Type Ty = getSrc(0)->getType();
2905 Str << "xchg." << Ty << " ";
2906 dumpSources(Func);
2907 }
2908
2909 void OperandX8632Mem::emit(const Cfg *Func) const {
2910 if (!BuildDefs::dump()) 98 if (!BuildDefs::dump())
2911 return; 99 return;
2912 Ostream &Str = Func->getContext()->getStrEmit(); 100 Ostream &Str = Func->getContext()->getStrEmit();
2913 if (SegmentReg != DefaultSegment) { 101 if (SegmentReg != DefaultSegment) {
2914 assert(SegmentReg >= 0 && SegmentReg < SegReg_NUM); 102 assert(SegmentReg >= 0 && SegmentReg < SegReg_NUM);
2915 Str << "%" << InstX8632SegmentRegNames[SegmentReg] << ":"; 103 Str << "%" << X8632::Traits::InstSegmentRegNames[SegmentReg] << ":";
2916 } 104 }
2917 // Emit as Offset(Base,Index,1<<Shift). 105 // Emit as Offset(Base,Index,1<<Shift).
2918 // Offset is emitted without the leading '$'. 106 // Offset is emitted without the leading '$'.
2919 // Omit the (Base,Index,1<<Shift) part if Base==nullptr. 107 // Omit the (Base,Index,1<<Shift) part if Base==nullptr.
2920 if (!Offset) { 108 if (!Offset) {
2921 // No offset, emit nothing. 109 // No offset, emit nothing.
2922 } else if (const auto CI = llvm::dyn_cast<ConstantInteger32>(Offset)) { 110 } else if (const auto CI = llvm::dyn_cast<ConstantInteger32>(Offset)) {
2923 if (Base == nullptr || CI->getValue()) 111 if (Base == nullptr || CI->getValue())
2924 // Emit a non-zero offset without a leading '$'. 112 // Emit a non-zero offset without a leading '$'.
2925 Str << CI->getValue(); 113 Str << CI->getValue();
2926 } else if (const auto CR = llvm::dyn_cast<ConstantRelocatable>(Offset)) { 114 } else if (const auto CR = llvm::dyn_cast<ConstantRelocatable>(Offset)) {
2927 CR->emitWithoutPrefix(Func->getTarget()); 115 CR->emitWithoutPrefix(Func->getTarget());
2928 } else { 116 } else {
2929 llvm_unreachable("Invalid offset type for x86 mem operand"); 117 llvm_unreachable("Invalid offset type for x86 mem operand");
2930 } 118 }
2931 119
2932 if (Base) { 120 if (Base) {
2933 Str << "("; 121 Str << "(";
2934 Base->emit(Func); 122 Base->emit(Func);
2935 if (Index) { 123 if (Index) {
2936 Str << ","; 124 Str << ",";
2937 Index->emit(Func); 125 Index->emit(Func);
2938 if (Shift) 126 if (Shift)
2939 Str << "," << (1u << Shift); 127 Str << "," << (1u << Shift);
2940 } 128 }
2941 Str << ")"; 129 Str << ")";
2942 } 130 }
2943 } 131 }
2944 132
2945 void OperandX8632Mem::dump(const Cfg *Func, Ostream &Str) const { 133 void MachineTraits<TargetX8632>::X86OperandMem::dump(const Cfg *Func,
134 Ostream &Str) const {
2946 if (!BuildDefs::dump()) 135 if (!BuildDefs::dump())
2947 return; 136 return;
2948 if (SegmentReg != DefaultSegment) { 137 if (SegmentReg != DefaultSegment) {
2949 assert(SegmentReg >= 0 && SegmentReg < SegReg_NUM); 138 assert(SegmentReg >= 0 && SegmentReg < SegReg_NUM);
2950 Str << InstX8632SegmentRegNames[SegmentReg] << ":"; 139 Str << X8632::Traits::InstSegmentRegNames[SegmentReg] << ":";
2951 } 140 }
2952 bool Dumped = false; 141 bool Dumped = false;
2953 Str << "["; 142 Str << "[";
2954 if (Base) { 143 if (Base) {
2955 if (Func) 144 if (Func)
2956 Base->dump(Func); 145 Base->dump(Func);
2957 else 146 else
2958 Base->dump(Str); 147 Base->dump(Str);
2959 Dumped = true; 148 Dumped = true;
2960 } 149 }
(...skipping 25 matching lines...) Expand all
2986 Str << "+"; 175 Str << "+";
2987 Offset->dump(Func, Str); 176 Offset->dump(Func, Str);
2988 } 177 }
2989 } else { 178 } else {
2990 // There is only the offset. 179 // There is only the offset.
2991 Offset->dump(Func, Str); 180 Offset->dump(Func, Str);
2992 } 181 }
2993 Str << "]"; 182 Str << "]";
2994 } 183 }
2995 184
2996 void OperandX8632Mem::emitSegmentOverride(X8632::AssemblerX8632 *Asm) const { 185 void MachineTraits<TargetX8632>::X86OperandMem::emitSegmentOverride(
186 X8632::AssemblerX8632 *Asm) const {
2997 if (SegmentReg != DefaultSegment) { 187 if (SegmentReg != DefaultSegment) {
2998 assert(SegmentReg >= 0 && SegmentReg < SegReg_NUM); 188 assert(SegmentReg >= 0 && SegmentReg < SegReg_NUM);
2999 Asm->emitSegmentOverride(InstX8632SegmentPrefixes[SegmentReg]); 189 Asm->emitSegmentOverride(X8632::Traits::InstSegmentPrefixes[SegmentReg]);
3000 } 190 }
3001 } 191 }
3002 192
3003 X8632::Traits::Address OperandX8632Mem::toAsmAddress(Assembler *Asm) const { 193 MachineTraits<TargetX8632>::Address
194 MachineTraits<TargetX8632>::X86OperandMem::toAsmAddress(
195 MachineTraits<TargetX8632>::Assembler *Asm) const {
3004 int32_t Disp = 0; 196 int32_t Disp = 0;
3005 AssemblerFixup *Fixup = nullptr; 197 AssemblerFixup *Fixup = nullptr;
3006 // Determine the offset (is it relocatable?) 198 // Determine the offset (is it relocatable?)
3007 if (getOffset()) { 199 if (getOffset()) {
3008 if (const auto CI = llvm::dyn_cast<ConstantInteger32>(getOffset())) { 200 if (const auto CI = llvm::dyn_cast<ConstantInteger32>(getOffset())) {
3009 Disp = static_cast<int32_t>(CI->getValue()); 201 Disp = static_cast<int32_t>(CI->getValue());
3010 } else if (const auto CR = 202 } else if (const auto CR =
3011 llvm::dyn_cast<ConstantRelocatable>(getOffset())) { 203 llvm::dyn_cast<ConstantRelocatable>(getOffset())) {
3012 Disp = CR->getOffset(); 204 Disp = CR->getOffset();
3013 Fixup = Asm->createFixup(llvm::ELF::R_386_32, CR); 205 Fixup = Asm->createFixup(llvm::ELF::R_386_32, CR);
(...skipping 15 matching lines...) Expand all
3029 return X8632::Traits::Address( 221 return X8632::Traits::Address(
3030 RegX8632::getEncodedGPR(getIndex()->getRegNum()), 222 RegX8632::getEncodedGPR(getIndex()->getRegNum()),
3031 X8632::Traits::ScaleFactor(getShift()), Disp); 223 X8632::Traits::ScaleFactor(getShift()), Disp);
3032 } else if (Fixup) { 224 } else if (Fixup) {
3033 return X8632::Traits::Address::Absolute(Disp, Fixup); 225 return X8632::Traits::Address::Absolute(Disp, Fixup);
3034 } else { 226 } else {
3035 return X8632::Traits::Address::Absolute(Disp); 227 return X8632::Traits::Address::Absolute(Disp);
3036 } 228 }
3037 } 229 }
3038 230
3039 X8632::Traits::Address VariableSplit::toAsmAddress(const Cfg *Func) const { 231 MachineTraits<TargetX8632>::Address
232 MachineTraits<TargetX8632>::VariableSplit::toAsmAddress(const Cfg *Func) const {
3040 assert(!Var->hasReg()); 233 assert(!Var->hasReg());
3041 const TargetLowering *Target = Func->getTarget(); 234 const ::Ice::TargetLowering *Target = Func->getTarget();
3042 int32_t Offset = 235 int32_t Offset =
3043 Var->getStackOffset() + Target->getStackAdjustment() + getOffset(); 236 Var->getStackOffset() + Target->getStackAdjustment() + getOffset();
3044 return X8632::Traits::Address( 237 return X8632::Traits::Address(
3045 RegX8632::getEncodedGPR(Target->getFrameOrStackReg()), Offset); 238 RegX8632::getEncodedGPR(Target->getFrameOrStackReg()), Offset);
3046 } 239 }
3047 240
3048 void VariableSplit::emit(const Cfg *Func) const { 241 void MachineTraits<TargetX8632>::VariableSplit::emit(const Cfg *Func) const {
3049 if (!BuildDefs::dump()) 242 if (!BuildDefs::dump())
3050 return; 243 return;
3051 Ostream &Str = Func->getContext()->getStrEmit(); 244 Ostream &Str = Func->getContext()->getStrEmit();
3052 assert(!Var->hasReg()); 245 assert(!Var->hasReg());
3053 // The following is copied/adapted from TargetX8632::emitVariable(). 246 // The following is copied/adapted from TargetX8632::emitVariable().
3054 const TargetLowering *Target = Func->getTarget(); 247 const ::Ice::TargetLowering *Target = Func->getTarget();
3055 const Type Ty = IceType_i32; 248 const Type Ty = IceType_i32;
3056 int32_t Offset = 249 int32_t Offset =
3057 Var->getStackOffset() + Target->getStackAdjustment() + getOffset(); 250 Var->getStackOffset() + Target->getStackAdjustment() + getOffset();
3058 if (Offset) 251 if (Offset)
3059 Str << Offset; 252 Str << Offset;
3060 Str << "(%" << Target->getRegName(Target->getFrameOrStackReg(), Ty) << ")"; 253 Str << "(%" << Target->getRegName(Target->getFrameOrStackReg(), Ty) << ")";
3061 } 254 }
3062 255
3063 void VariableSplit::dump(const Cfg *Func, Ostream &Str) const { 256 void MachineTraits<TargetX8632>::VariableSplit::dump(const Cfg *Func,
257 Ostream &Str) const {
3064 if (!BuildDefs::dump()) 258 if (!BuildDefs::dump())
3065 return; 259 return;
3066 switch (Part) { 260 switch (Part) {
3067 case Low: 261 case Low:
3068 Str << "low"; 262 Str << "low";
3069 break; 263 break;
3070 case High: 264 case High:
3071 Str << "high"; 265 Str << "high";
3072 break; 266 break;
3073 } 267 }
3074 Str << "("; 268 Str << "(";
3075 if (Func) 269 if (Func)
3076 Var->dump(Func); 270 Var->dump(Func);
3077 else 271 else
3078 Var->dump(Str); 272 Var->dump(Str);
3079 Str << ")"; 273 Str << ")";
3080 } 274 }
3081 275
276 } // namespace X86Internal
3082 } // end of namespace Ice 277 } // end of namespace Ice
278
279 X86INSTS_DEFINE_STATIC_DATA(TargetX8632);
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698