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

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

Powered by Google App Engine
This is Rietveld 408576698