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