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