OLD | NEW |
---|---|
(Empty) | |
1 //===- subzero/src/IceInstX8632.cpp - X86-32 instruction implementation ---===// | |
2 // | |
3 // The Subzero Code Generator | |
4 // | |
5 // This file is distributed under the University of Illinois Open Source | |
6 // License. See LICENSE.TXT for details. | |
7 // | |
8 //===----------------------------------------------------------------------===// | |
9 // | |
10 // This file implements the InstX8632 and OperandX8632 classes, | |
11 // primarily the constructors and the dump()/emit() methods. | |
12 // | |
13 //===----------------------------------------------------------------------===// | |
14 | |
15 #include "IceCfg.h" | |
16 #include "IceCfgNode.h" | |
17 #include "IceInst.h" | |
18 #include "IceInstX8632.h" | |
19 #include "IceTargetLoweringX8632.h" | |
20 #include "IceOperand.h" | |
21 | |
22 namespace Ice { | |
23 | |
24 namespace { | |
25 | |
26 const struct _InstX8632BrAttributes { | |
27 const char *DisplayString; | |
28 const char *EmitString; | |
29 } InstX8632BrAttributes[] = { | |
30 #define X(tag, dump, emit) \ | |
31 { dump, emit } \ | |
32 , | |
33 ICEINSTX8632BR_TABLE | |
34 #undef X | |
35 }; | |
36 const size_t InstX8632BrAttributesSize = | |
37 llvm::array_lengthof(InstX8632BrAttributes); | |
38 | |
39 const struct _TypeX8632Attributes { | |
jvoung (off chromium)
2014/05/03 00:13:28
make indenting consistent here? (BrAttributes were
JF
2014/05/04 23:54:58
Same thing on reserved name.
Jim Stichnoth
2014/05/05 07:03:55
"make format" fail. :(
Jim Stichnoth
2014/05/05 07:03:55
I changed all "struct _Foo" to "struct Foo_".
| |
40 const char *CvtString; // i (integer), s (single FP), d (double FP) | |
41 const char *SdSsString; // ss, sd, or <blank> | |
42 const char *WidthString; // {byte,word,dword,qword} ptr | |
jvoung (off chromium)
2014/05/03 00:13:28
not sure why ptr -- does byte, word, dword, qword
Jim Stichnoth
2014/05/05 07:03:55
WidthString is only used for the emit() routines.
jvoung (off chromium)
2014/05/15 23:47:34
Ah ok, I'm clearly not used to the Intel syntax ;-
| |
43 } TypeX8632Attributes[] = { | |
44 #define X(tag, cvt, sdss, width) \ | |
45 { cvt, "" sdss, width }, | |
46 ICETYPEX8632_TABLE | |
47 #undef X | |
48 }; | |
49 const size_t TypeX8632AttributesSize = llvm::array_lengthof(TypeX8632Attribute s); | |
50 | |
51 } // end of anonymous namespace | |
52 | |
53 const char *InstX8632::getWidthString(Type Ty) { | |
54 return TypeX8632Attributes[Ty].WidthString; | |
55 } | |
56 | |
57 OperandX8632Mem::OperandX8632Mem(Cfg *Func, Type Ty, Variable *Base, | |
58 Constant *Offset, Variable *Index, | |
59 uint32_t Shift) | |
60 : OperandX8632(kMem, Ty), Base(Base), Offset(Offset), Index(Index), | |
61 Shift(Shift) { | |
62 Vars = NULL; | |
63 NumVars = 0; | |
64 if (Base) | |
65 ++NumVars; | |
66 if (Index) | |
67 ++NumVars; | |
68 if (NumVars) { | |
69 Vars = Func->allocateArrayOf<Variable *>(NumVars); | |
70 SizeT I = 0; | |
71 if (Base) | |
72 Vars[I++] = Base; | |
73 if (Index) | |
74 Vars[I++] = Index; | |
75 assert(I == NumVars); | |
76 } | |
77 } | |
78 | |
79 InstX8632Mul::InstX8632Mul(Cfg *Func, Variable *Dest, Variable *Source1, | |
80 Operand *Source2) | |
81 : InstX8632(Func, InstX8632::Mul, 2, Dest) { | |
82 addSource(Source1); | |
83 addSource(Source2); | |
84 } | |
85 | |
86 InstX8632Shld::InstX8632Shld(Cfg *Func, Variable *Dest, Variable *Source1, | |
87 Variable *Source2) | |
88 : InstX8632(Func, InstX8632::Shld, 3, Dest) { | |
89 addSource(Dest); | |
90 addSource(Source1); | |
91 addSource(Source2); | |
92 } | |
93 | |
94 InstX8632Shrd::InstX8632Shrd(Cfg *Func, Variable *Dest, Variable *Source1, | |
95 Variable *Source2) | |
96 : InstX8632(Func, InstX8632::Shrd, 3, Dest) { | |
97 addSource(Dest); | |
98 addSource(Source1); | |
99 addSource(Source2); | |
100 } | |
101 | |
102 InstX8632Label::InstX8632Label(Cfg *Func, TargetX8632 *Target) | |
103 : InstX8632(Func, InstX8632::Label, 0, NULL), | |
104 Number(Target->makeNextLabelNumber()) {} | |
105 | |
106 IceString InstX8632Label::getName(const Cfg *Func) const { | |
107 char buf[30]; | |
108 snprintf(buf, llvm::array_lengthof(buf), "%u", Number); | |
109 return ".L" + Func->getFunctionName() + "$__" + buf; | |
110 } | |
111 | |
112 InstX8632Br::InstX8632Br(Cfg *Func, CfgNode *TargetTrue, CfgNode *TargetFalse, | |
113 InstX8632Label *Label, InstX8632Br::BrCond Condition) | |
114 : InstX8632(Func, InstX8632::Br, 0, NULL), Condition(Condition), | |
115 TargetTrue(TargetTrue), TargetFalse(TargetFalse), Label(Label) {} | |
116 | |
117 InstX8632Call::InstX8632Call(Cfg *Func, Variable *Dest, Operand *CallTarget) | |
118 : InstX8632(Func, InstX8632::Call, 1, Dest) { | |
119 HasSideEffects = true; | |
120 addSource(CallTarget); | |
121 } | |
122 | |
123 InstX8632Cdq::InstX8632Cdq(Cfg *Func, Variable *Dest, Operand *Source) | |
124 : InstX8632(Func, InstX8632::Cdq, 1, Dest) { | |
125 assert(Dest->getRegNum() == TargetX8632::Reg_edx); | |
126 assert(llvm::isa<Variable>(Source)); | |
127 assert(llvm::dyn_cast<Variable>(Source)->getRegNum() == TargetX8632::Reg_eax); | |
128 addSource(Source); | |
129 } | |
130 | |
131 InstX8632Cvt::InstX8632Cvt(Cfg *Func, Variable *Dest, Operand *Source) | |
132 : InstX8632(Func, InstX8632::Cvt, 1, Dest) { | |
133 addSource(Source); | |
134 } | |
135 | |
136 InstX8632Icmp::InstX8632Icmp(Cfg *Func, Operand *Src0, Operand *Src1) | |
137 : InstX8632(Func, InstX8632::Icmp, 2, NULL) { | |
138 addSource(Src0); | |
139 addSource(Src1); | |
140 } | |
141 | |
142 InstX8632Ucomiss::InstX8632Ucomiss(Cfg *Func, Operand *Src0, Operand *Src1) | |
143 : InstX8632(Func, InstX8632::Ucomiss, 2, NULL) { | |
144 addSource(Src0); | |
145 addSource(Src1); | |
146 } | |
147 | |
148 InstX8632Test::InstX8632Test(Cfg *Func, Operand *Src1, Operand *Src2) | |
149 : InstX8632(Func, InstX8632::Test, 2, NULL) { | |
150 addSource(Src1); | |
151 addSource(Src2); | |
152 } | |
153 | |
154 InstX8632Store::InstX8632Store(Cfg *Func, Operand *Value, OperandX8632 *Mem) | |
155 : InstX8632(Func, InstX8632::Store, 2, NULL) { | |
156 addSource(Value); | |
157 addSource(Mem); | |
158 } | |
159 | |
160 InstX8632Mov::InstX8632Mov(Cfg *Func, Variable *Dest, Operand *Source) | |
161 : InstX8632(Func, InstX8632::Mov, 1, Dest) { | |
162 addSource(Source); | |
163 } | |
164 | |
165 InstX8632Movsx::InstX8632Movsx(Cfg *Func, Variable *Dest, Operand *Source) | |
166 : InstX8632(Func, InstX8632::Movsx, 1, Dest) { | |
167 addSource(Source); | |
168 } | |
169 | |
170 InstX8632Movzx::InstX8632Movzx(Cfg *Func, Variable *Dest, Operand *Source) | |
171 : InstX8632(Func, InstX8632::Movzx, 1, Dest) { | |
172 addSource(Source); | |
173 } | |
174 | |
175 InstX8632Fld::InstX8632Fld(Cfg *Func, Operand *Src) | |
176 : InstX8632(Func, InstX8632::Fld, 1, NULL) { | |
177 addSource(Src); | |
178 } | |
179 | |
180 InstX8632Fstp::InstX8632Fstp(Cfg *Func, Variable *Dest) | |
181 : InstX8632(Func, InstX8632::Fstp, 0, Dest) {} | |
182 | |
183 InstX8632Pop::InstX8632Pop(Cfg *Func, Variable *Dest) | |
184 : InstX8632(Func, InstX8632::Pop, 1, Dest) {} | |
jvoung (off chromium)
2014/05/03 00:13:28
Could the MaxSrcs be 0 since there's no addSource(
Jim Stichnoth
2014/05/05 07:03:55
Done.
| |
185 | |
186 InstX8632Push::InstX8632Push(Cfg *Func, Operand *Source, | |
187 bool SuppressStackAdjustment) | |
188 : InstX8632(Func, InstX8632::Push, 1, NULL), | |
189 SuppressStackAdjustment(SuppressStackAdjustment) { | |
190 addSource(Source); | |
191 } | |
192 | |
193 bool InstX8632Mov::isRedundantAssign() const { | |
194 Variable *Src = llvm::dyn_cast<Variable>(getSrc(0)); | |
195 if (Src == NULL) | |
196 return false; | |
197 if (getDest()->hasReg() && getDest()->getRegNum() == Src->getRegNum()) { | |
198 // TODO: On x86-64, instructions like "mov eax, eax" are used to | |
199 // clear the upper 32 bits of rax. We need to recognize and | |
200 // preserve these. | |
201 return true; | |
202 } | |
203 if (!getDest()->hasReg() && !Src->hasReg() && | |
204 Dest->getStackOffset() == Src->getStackOffset()) | |
205 return true; | |
206 return false; | |
207 } | |
208 | |
209 InstX8632Ret::InstX8632Ret(Cfg *Func, Variable *Source) | |
210 : InstX8632(Func, InstX8632::Ret, Source ? 1 : 0, NULL) { | |
211 if (Source) | |
212 addSource(Source); | |
213 } | |
214 | |
215 // ======================== Dump routines ======================== // | |
216 | |
217 void InstX8632::dump(const Cfg *Func) const { | |
218 Ostream &Str = Func->getContext()->getStrDump(); | |
219 Str << "[X8632] "; | |
220 Inst::dump(Func); | |
221 } | |
222 | |
223 void InstX8632Label::emit(const Cfg *Func) const { | |
224 Ostream &Str = Func->getContext()->getStrEmit(); | |
225 Str << getName(Func) << ":\n"; | |
226 } | |
227 | |
228 void InstX8632Label::dump(const Cfg *Func) const { | |
229 Ostream &Str = Func->getContext()->getStrDump(); | |
230 Str << getName(Func) << ":"; | |
231 } | |
232 | |
233 void InstX8632Br::emit(const Cfg *Func) const { | |
234 Ostream &Str = Func->getContext()->getStrEmit(); | |
235 Str << "\t"; | |
236 | |
237 if (Condition == Br_None) { | |
238 Str << "jmp"; | |
239 } else { | |
240 Str << InstX8632BrAttributes[Condition].EmitString; | |
241 } | |
242 | |
243 if (Label) { | |
244 Str << "\t" << Label->getName(Func) << "\n"; | |
245 } else { | |
246 if (Condition == Br_None) { | |
247 Str << "\t" << getTargetFalse()->getAsmName() << "\n"; | |
248 } else { | |
249 Str << "\t" << getTargetTrue()->getAsmName() << "\n"; | |
250 if (getTargetFalse()) { | |
251 Str << "\tjmp\t" << getTargetFalse()->getAsmName() << "\n"; | |
252 } | |
253 } | |
254 } | |
255 } | |
256 | |
257 void InstX8632Br::dump(const Cfg *Func) const { | |
258 Ostream &Str = Func->getContext()->getStrDump(); | |
259 Str << "br "; | |
260 | |
261 if (Condition == Br_None) { | |
262 Str << "label %" | |
263 << (Label ? Label->getName(Func) : getTargetFalse()->getName()); | |
264 return; | |
265 } | |
266 | |
267 Str << InstX8632BrAttributes[Condition].DisplayString; | |
268 if (Label) { | |
269 Str << ", label %" << Label->getName(Func); | |
270 } else { | |
271 Str << ", label %" << getTargetTrue()->getName(); | |
272 if (getTargetFalse()) { | |
273 Str << ", label %" << getTargetFalse()->getName(); | |
274 } | |
275 } | |
276 } | |
277 | |
278 void InstX8632Call::emit(const Cfg *Func) const { | |
279 Ostream &Str = Func->getContext()->getStrEmit(); | |
280 assert(getSrcSize() == 1); | |
281 Str << "\tcall\t"; | |
282 getCallTarget()->emit(Func); | |
283 Str << "\n"; | |
284 Func->getTarget()->resetStackAdjustment(); | |
285 } | |
286 | |
287 void InstX8632Call::dump(const Cfg *Func) const { | |
288 Ostream &Str = Func->getContext()->getStrDump(); | |
289 if (getDest()) { | |
290 dumpDest(Func); | |
291 Str << " = "; | |
292 } | |
293 Str << "call "; | |
294 getCallTarget()->dump(Func); | |
295 } | |
296 | |
297 // The ShiftHack parameter is used to emit "cl" instead of "ecx" for | |
298 // shift instructions, in order to be syntactically valid. The | |
299 // Opcode parameter needs to be char* and not IceString because of | |
300 // template issues. | |
301 void emitTwoAddress(const char *Opcode, const Inst *Inst, const Cfg *Func, | |
302 bool ShiftHack) { | |
303 Ostream &Str = Func->getContext()->getStrEmit(); | |
304 assert(Inst->getSrcSize() == 2); | |
305 assert(Inst->getDest() == Inst->getSrc(0)); | |
306 Str << "\t" << Opcode << "\t"; | |
307 Inst->getDest()->emit(Func); | |
308 Str << ", "; | |
309 bool EmittedSrc1 = false; | |
310 if (ShiftHack) { | |
311 Variable *ShiftReg = llvm::dyn_cast<Variable>(Inst->getSrc(1)); | |
312 if (ShiftReg && ShiftReg->getRegNum() == TargetX8632::Reg_ecx) { | |
313 Str << "cl"; | |
314 EmittedSrc1 = true; | |
315 } | |
316 } | |
317 if (!EmittedSrc1) | |
318 Inst->getSrc(1)->emit(Func); | |
319 Str << "\n"; | |
320 } | |
321 | |
322 template <> const char *InstX8632Add::Opcode = "add"; | |
323 template <> const char *InstX8632Adc::Opcode = "adc"; | |
324 template <> const char *InstX8632Addss::Opcode = "addss"; | |
325 template <> const char *InstX8632Sub::Opcode = "sub"; | |
326 template <> const char *InstX8632Subss::Opcode = "subss"; | |
327 template <> const char *InstX8632Sbb::Opcode = "sbb"; | |
328 template <> const char *InstX8632And::Opcode = "and"; | |
329 template <> const char *InstX8632Or::Opcode = "or"; | |
330 template <> const char *InstX8632Xor::Opcode = "xor"; | |
331 template <> const char *InstX8632Imul::Opcode = "imul"; | |
332 template <> const char *InstX8632Mulss::Opcode = "mulss"; | |
333 template <> const char *InstX8632Div::Opcode = "div"; | |
334 template <> const char *InstX8632Idiv::Opcode = "idiv"; | |
335 template <> const char *InstX8632Divss::Opcode = "divss"; | |
336 template <> const char *InstX8632Shl::Opcode = "shl"; | |
337 template <> const char *InstX8632Shr::Opcode = "shr"; | |
338 template <> const char *InstX8632Sar::Opcode = "sar"; | |
339 | |
340 template <> void InstX8632Addss::emit(const Cfg *Func) const { | |
341 char buf[30]; | |
342 snprintf(buf, llvm::array_lengthof(buf), "add%s", TypeX8632Attributes[getDest( )->getType()].SdSsString); | |
jvoung (off chromium)
2014/05/03 00:13:28
80 col
clang-format?
Jim Stichnoth
2014/05/05 07:03:55
Done.
| |
343 emitTwoAddress(buf, | |
344 this, Func); | |
jvoung (off chromium)
2014/05/03 00:13:28
fit on one line?
Jim Stichnoth
2014/05/05 07:03:55
Done.
| |
345 } | |
346 | |
347 template <> void InstX8632Subss::emit(const Cfg *Func) const { | |
348 char buf[30]; | |
349 snprintf(buf, llvm::array_lengthof(buf), "sub%s", TypeX8632Attributes[getDest( )->getType()].SdSsString); | |
350 emitTwoAddress(buf, | |
351 this, Func); | |
352 } | |
353 | |
354 template <> void InstX8632Mulss::emit(const Cfg *Func) const { | |
355 char buf[30]; | |
356 snprintf(buf, llvm::array_lengthof(buf), "mul%s", TypeX8632Attributes[getDest( )->getType()].SdSsString); | |
357 emitTwoAddress(buf, | |
358 this, Func); | |
359 } | |
360 | |
361 template <> void InstX8632Divss::emit(const Cfg *Func) const { | |
362 char buf[30]; | |
363 snprintf(buf, llvm::array_lengthof(buf), "div%s", TypeX8632Attributes[getDest( )->getType()].SdSsString); | |
364 emitTwoAddress(buf, | |
365 this, Func); | |
366 } | |
367 | |
368 template <> void InstX8632Imul::emit(const Cfg *Func) const { | |
369 Ostream &Str = Func->getContext()->getStrEmit(); | |
370 assert(getSrcSize() == 2); | |
371 if (getDest()->getType() == IceType_i8) { | |
372 // The 8-bit version of imul only allows the form "imul r/m8". | |
373 Variable *Src0 = llvm::dyn_cast<Variable>(getSrc(0)); | |
374 assert(Src0 && Src0->getRegNum() == TargetX8632::Reg_eax); | |
375 Str << "\timul\t"; | |
376 getSrc(1)->emit(Func); | |
377 Str << "\n"; | |
378 } else if (llvm::isa<Constant>(getSrc(1))) { | |
379 Str << "\timul\t"; | |
380 getDest()->emit(Func); | |
381 Str << ", "; | |
382 getSrc(0)->emit(Func); | |
383 Str << ", "; | |
384 getSrc(1)->emit(Func); | |
385 Str << "\n"; | |
386 } else { | |
387 emitTwoAddress("imul", this, Func); | |
388 } | |
389 } | |
390 | |
391 void InstX8632Mul::emit(const Cfg *Func) const { | |
392 Ostream &Str = Func->getContext()->getStrEmit(); | |
393 assert(getSrcSize() == 2); | |
394 assert(llvm::isa<Variable>(getSrc(0))); | |
395 assert(llvm::dyn_cast<Variable>(getSrc(0))->getRegNum() == | |
396 TargetX8632::Reg_eax); | |
397 assert(getDest()->getRegNum() == TargetX8632::Reg_eax); // TODO: allow edx? | |
398 Str << "\tmul\t"; | |
399 getSrc(1)->emit(Func); | |
400 Str << "\n"; | |
401 } | |
402 | |
403 void InstX8632Mul::dump(const Cfg *Func) const { | |
404 Ostream &Str = Func->getContext()->getStrDump(); | |
405 dumpDest(Func); | |
406 Str << " = mul." << getDest()->getType() << " "; | |
407 dumpSources(Func); | |
408 } | |
409 | |
410 void InstX8632Shld::emit(const Cfg *Func) const { | |
411 Ostream &Str = Func->getContext()->getStrEmit(); | |
412 assert(getSrcSize() == 3); | |
413 assert(getDest() == getSrc(0)); | |
414 Str << "\tshld\t"; | |
415 getDest()->emit(Func); | |
416 Str << ", "; | |
417 getSrc(1)->emit(Func); | |
418 Str << ", "; | |
419 bool ShiftHack = true; | |
jvoung (off chromium)
2014/05/03 00:13:28
Is setting ShiftHack = true for documentation? I
Jim Stichnoth
2014/05/05 07:03:55
Fixed based on your suggestion below.
| |
420 bool EmittedSrc1 = false; | |
jvoung (off chromium)
2014/05/03 00:13:28
should this be "EmittedSrc2" instead? Or can this
Jim Stichnoth
2014/05/05 07:03:55
Yeah - I think this was the remnants of copy&paste
| |
421 if (ShiftHack) { | |
422 Variable *ShiftReg = llvm::dyn_cast<Variable>(getSrc(2)); | |
423 if (ShiftReg && ShiftReg->getRegNum() == TargetX8632::Reg_ecx) { | |
jvoung (off chromium)
2014/05/03 00:13:28
can the register be anything other than ecx?
Jim Stichnoth
2014/05/05 07:03:55
No - it's either an immediate or cl.
| |
424 Str << "cl"; | |
425 EmittedSrc1 = true; | |
426 } | |
427 } | |
428 if (!EmittedSrc1) | |
429 getSrc(2)->emit(Func); | |
430 Str << "\n"; | |
431 } | |
432 | |
433 void InstX8632Shld::dump(const Cfg *Func) const { | |
434 Ostream &Str = Func->getContext()->getStrDump(); | |
435 dumpDest(Func); | |
436 Str << " = shld." << getDest()->getType() << " "; | |
437 dumpSources(Func); | |
438 } | |
439 | |
440 void InstX8632Shrd::emit(const Cfg *Func) const { | |
441 Ostream &Str = Func->getContext()->getStrEmit(); | |
442 assert(getSrcSize() == 3); | |
443 assert(getDest() == getSrc(0)); | |
444 Str << "\tshrd\t"; | |
445 getDest()->emit(Func); | |
446 Str << ", "; | |
447 getSrc(1)->emit(Func); | |
448 Str << ", "; | |
449 bool ShiftHack = true; | |
450 bool EmittedSrc1 = false; | |
451 if (ShiftHack) { | |
452 Variable *ShiftReg = llvm::dyn_cast<Variable>(getSrc(2)); | |
453 if (ShiftReg && ShiftReg->getRegNum() == TargetX8632::Reg_ecx) { | |
454 Str << "cl"; | |
455 EmittedSrc1 = true; | |
456 } | |
457 } | |
458 if (!EmittedSrc1) | |
459 getSrc(2)->emit(Func); | |
460 Str << "\n"; | |
461 } | |
462 | |
463 void InstX8632Shrd::dump(const Cfg *Func) const { | |
464 Ostream &Str = Func->getContext()->getStrDump(); | |
465 dumpDest(Func); | |
466 Str << " = shrd." << getDest()->getType() << " "; | |
467 dumpSources(Func); | |
468 } | |
469 | |
470 void InstX8632Cdq::emit(const Cfg *Func) const { | |
471 Ostream &Str = Func->getContext()->getStrEmit(); | |
472 assert(getSrcSize() == 1); | |
473 Str << "\tcdq\n"; | |
474 } | |
475 | |
476 void InstX8632Cdq::dump(const Cfg *Func) const { | |
477 Ostream &Str = Func->getContext()->getStrDump(); | |
478 dumpDest(Func); | |
479 Str << " = cdq." << getSrc(0)->getType() << " "; | |
480 dumpSources(Func); | |
481 } | |
482 | |
483 void InstX8632Cvt::emit(const Cfg *Func) const { | |
484 Ostream &Str = Func->getContext()->getStrEmit(); | |
485 assert(getSrcSize() == 1); | |
486 Str << "\tcvts" << TypeX8632Attributes[getSrc(0)->getType()].CvtString << "2s" | |
487 << TypeX8632Attributes[getDest()->getType()].CvtString << "\t"; | |
488 getDest()->emit(Func); | |
489 Str << ", "; | |
490 getSrc(0)->emit(Func); | |
491 Str << "\n"; | |
492 } | |
493 | |
494 void InstX8632Cvt::dump(const Cfg *Func) const { | |
495 Ostream &Str = Func->getContext()->getStrDump(); | |
496 dumpDest(Func); | |
497 Str << " = cvts" << TypeX8632Attributes[getSrc(0)->getType()].CvtString << "2s " | |
498 << TypeX8632Attributes[getDest()->getType()].CvtString << " "; | |
499 dumpSources(Func); | |
500 } | |
501 | |
502 void InstX8632Icmp::emit(const Cfg *Func) const { | |
503 Ostream &Str = Func->getContext()->getStrEmit(); | |
504 assert(getSrcSize() == 2); | |
505 Str << "\tcmp\t"; | |
506 getSrc(0)->emit(Func); | |
507 Str << ", "; | |
508 getSrc(1)->emit(Func); | |
509 Str << "\n"; | |
510 } | |
511 | |
512 void InstX8632Icmp::dump(const Cfg *Func) const { | |
513 Ostream &Str = Func->getContext()->getStrDump(); | |
514 Str << "cmp." << getSrc(0)->getType() << " "; | |
515 dumpSources(Func); | |
516 } | |
517 | |
518 void InstX8632Ucomiss::emit(const Cfg *Func) const { | |
519 Ostream &Str = Func->getContext()->getStrEmit(); | |
520 assert(getSrcSize() == 2); | |
521 Str << "\tucomi" << TypeX8632Attributes[getSrc(0)->getType()].SdSsString << "\ t"; | |
522 getSrc(0)->emit(Func); | |
523 Str << ", "; | |
524 getSrc(1)->emit(Func); | |
525 Str << "\n"; | |
526 } | |
527 | |
528 void InstX8632Ucomiss::dump(const Cfg *Func) const { | |
529 Ostream &Str = Func->getContext()->getStrDump(); | |
530 Str << "ucomiss." << getSrc(0)->getType() << " "; | |
531 dumpSources(Func); | |
532 } | |
533 | |
534 void InstX8632Test::emit(const Cfg *Func) const { | |
535 Ostream &Str = Func->getContext()->getStrEmit(); | |
536 assert(getSrcSize() == 2); | |
537 Str << "\ttest\t"; | |
538 getSrc(0)->emit(Func); | |
539 Str << ", "; | |
540 getSrc(1)->emit(Func); | |
541 Str << "\n"; | |
542 } | |
543 | |
544 void InstX8632Test::dump(const Cfg *Func) const { | |
545 Ostream &Str = Func->getContext()->getStrDump(); | |
546 Str << "test." << getSrc(0)->getType() << " "; | |
547 dumpSources(Func); | |
548 } | |
549 | |
550 void InstX8632Store::emit(const Cfg *Func) const { | |
551 Ostream &Str = Func->getContext()->getStrEmit(); | |
552 assert(getSrcSize() == 2); | |
553 Str << "\tmov\t"; | |
554 getSrc(1)->emit(Func); | |
555 Str << ", "; | |
556 getSrc(0)->emit(Func); | |
557 Str << "\n"; | |
558 } | |
559 | |
560 void InstX8632Store::dump(const Cfg *Func) const { | |
561 Ostream &Str = Func->getContext()->getStrDump(); | |
562 Str << "mov." << getSrc(0)->getType() << " "; | |
563 getSrc(1)->dump(Func); | |
564 Str << ", "; | |
565 getSrc(0)->dump(Func); | |
566 } | |
567 | |
568 void InstX8632Mov::emit(const Cfg *Func) const { | |
569 Ostream &Str = Func->getContext()->getStrEmit(); | |
570 assert(getSrcSize() == 1); | |
571 Str << "\tmov" << TypeX8632Attributes[getDest()->getType()].SdSsString << "\t" ; | |
572 // For an integer truncation operation, src is wider than dest. | |
573 // Ideally, we use a mov instruction whose data width matches the | |
574 // narrower dest. This is a problem if e.g. src is a register like | |
575 // esi or si where there is no 8-bit version of the register. To be | |
576 // safe, we instead widen the dest to match src. This works even | |
577 // for stack-allocated dest variables because typeWidthOnStack() | |
578 // pads to a 4-byte boundary even if only a lower portion is used. | |
579 assert(Func->getTarget()->typeWidthInBytesOnStack(getDest()->getType()) == | |
580 Func->getTarget()->typeWidthInBytesOnStack(getSrc(0)->getType())); | |
581 getDest()->asType(getSrc(0)->getType()).emit(Func); | |
582 Str << ", "; | |
583 getSrc(0)->emit(Func); | |
584 Str << "\n"; | |
585 } | |
586 | |
587 void InstX8632Mov::dump(const Cfg *Func) const { | |
588 Ostream &Str = Func->getContext()->getStrDump(); | |
589 Str << "mov." << getDest()->getType() << " "; | |
590 dumpDest(Func); | |
591 Str << ", "; | |
592 dumpSources(Func); | |
593 } | |
594 | |
595 void InstX8632Movsx::emit(const Cfg *Func) const { | |
596 Ostream &Str = Func->getContext()->getStrEmit(); | |
597 assert(getSrcSize() == 1); | |
598 Str << "\tmovsx\t"; | |
599 getDest()->emit(Func); | |
600 Str << ", "; | |
601 getSrc(0)->emit(Func); | |
602 Str << "\n"; | |
603 } | |
604 | |
605 void InstX8632Movsx::dump(const Cfg *Func) const { | |
606 Ostream &Str = Func->getContext()->getStrDump(); | |
607 Str << "movsx." << getDest()->getType() << "." << getSrc(0)->getType(); | |
608 Str << " "; | |
609 dumpDest(Func); | |
610 Str << ", "; | |
611 dumpSources(Func); | |
612 } | |
613 | |
614 void InstX8632Movzx::emit(const Cfg *Func) const { | |
615 Ostream &Str = Func->getContext()->getStrEmit(); | |
616 assert(getSrcSize() == 1); | |
617 Str << "\tmovzx\t"; | |
618 getDest()->emit(Func); | |
619 Str << ", "; | |
620 getSrc(0)->emit(Func); | |
621 Str << "\n"; | |
622 } | |
623 | |
624 void InstX8632Movzx::dump(const Cfg *Func) const { | |
625 Ostream &Str = Func->getContext()->getStrDump(); | |
626 Str << "movzx." << getDest()->getType() << "." << getSrc(0)->getType(); | |
627 Str << " "; | |
628 dumpDest(Func); | |
629 Str << ", "; | |
630 dumpSources(Func); | |
631 } | |
632 | |
633 void InstX8632Fld::emit(const Cfg *Func) const { | |
634 Ostream &Str = Func->getContext()->getStrEmit(); | |
635 assert(getSrcSize() == 1); | |
636 //bool isDouble = (getSrc(0)->getType() == IceType_f64); | |
jvoung (off chromium)
2014/05/03 00:13:28
can remove commented out code?
Jim Stichnoth
2014/05/05 07:03:55
Done.
| |
637 Type Ty = getSrc(0)->getType(); | |
638 Variable *Var = llvm::dyn_cast<Variable>(getSrc(0)); | |
639 if (Var && Var->hasReg()) { | |
640 // This is a physical xmm register, so we need to spill it to a | |
641 // temporary stack slot. | |
642 SizeT Width = typeWidthInBytes(Ty); | |
643 Str << "\tsub\tesp, " << Width << "\n"; | |
644 Str << "\tmov" << TypeX8632Attributes[Ty].SdSsString << "\t" << TypeX8632Att ributes[Ty].WidthString << " [esp], "; | |
645 Var->emit(Func); | |
646 Str << "\n"; | |
647 Str << "\tfld\t" << TypeX8632Attributes[Ty].WidthString << " [esp]\n"; | |
648 Str << "\tadd\tesp, " << Width << "\n"; | |
649 return; | |
650 } | |
651 Str << "\tfld\t"; | |
652 getSrc(0)->emit(Func); | |
653 Str << "\n"; | |
654 } | |
655 | |
656 void InstX8632Fld::dump(const Cfg *Func) const { | |
657 Ostream &Str = Func->getContext()->getStrDump(); | |
658 Str << "fld." << getSrc(0)->getType() << " "; | |
659 dumpSources(Func); | |
660 } | |
661 | |
662 void InstX8632Fstp::emit(const Cfg *Func) const { | |
663 Ostream &Str = Func->getContext()->getStrEmit(); | |
664 assert(getSrcSize() == 0); | |
665 if (getDest() == NULL) { | |
666 Str << "\tfstp\tst(0)\n"; | |
667 return; | |
668 } | |
669 if (!getDest()->hasReg()) { | |
670 Str << "\tfstp\t"; | |
671 getDest()->emit(Func); | |
672 Str << "\n"; | |
673 return; | |
674 } | |
675 // Dest is a physical (xmm) register, so st(0) needs to go through | |
676 // memory. Hack this by creating a temporary stack slot, spilling | |
677 // st(0) there, loading it into the xmm register, and deallocating | |
678 // the stack slot. | |
679 Type Ty = getDest()->getType(); | |
680 size_t Width = typeWidthInBytes(Ty); | |
681 Str << "\tsub\tesp, " << Width << "\n"; | |
682 Str << "\tfstp\t" << TypeX8632Attributes[Ty].WidthString << " [esp]\n"; | |
683 Str << "\tmov" << TypeX8632Attributes[Ty].SdSsString << "\t"; | |
684 getDest()->emit(Func); | |
685 Str << ", " <<TypeX8632Attributes[Ty].WidthString << " [esp]\n"; | |
686 Str << "\tadd\tesp, " << Width << "\n"; | |
687 } | |
688 | |
689 void InstX8632Fstp::dump(const Cfg *Func) const { | |
690 Ostream &Str = Func->getContext()->getStrDump(); | |
691 dumpDest(Func); | |
692 Str << " = fstp." << getDest()->getType() << ", st(0)"; | |
693 Str << "\n"; | |
694 } | |
695 | |
696 void InstX8632Pop::emit(const Cfg *Func) const { | |
697 Ostream &Str = Func->getContext()->getStrEmit(); | |
698 assert(getSrcSize() == 0); | |
699 Str << "\tpop\t"; | |
700 getDest()->emit(Func); | |
701 Str << "\n"; | |
702 } | |
703 | |
704 void InstX8632Pop::dump(const Cfg *Func) const { | |
705 Ostream &Str = Func->getContext()->getStrDump(); | |
706 dumpDest(Func); | |
707 Str << " = pop." << getDest()->getType() << " "; | |
708 } | |
709 | |
710 void InstX8632Push::emit(const Cfg *Func) const { | |
711 Ostream &Str = Func->getContext()->getStrEmit(); | |
712 assert(getSrcSize() == 1); | |
713 Type Ty = getSrc(0)->getType(); | |
714 Variable *Var = llvm::dyn_cast<Variable>(getSrc(0)); | |
715 if ((Ty == IceType_f32 || Ty == IceType_f64) && Var && Var->hasReg()) { | |
716 // The xmm registers can't be directly pushed, so we fake it by | |
717 // decrementing esp and then storing to [esp]. | |
718 Str << "\tsub\tesp, " << typeWidthInBytes(Ty) << "\n"; | |
719 if (!SuppressStackAdjustment) | |
720 Func->getTarget()->updateStackAdjustment(typeWidthInBytes(Ty)); | |
721 Str << "\tmov" << TypeX8632Attributes[Ty].SdSsString << "\t" << TypeX8632Att ributes[Ty].WidthString << " [esp], "; | |
722 getSrc(0)->emit(Func); | |
723 Str << "\n"; | |
724 } else if (Ty == IceType_f64 && (!Var || !Var->hasReg())) { | |
725 // A double on the stack has to be pushed as two halves. Push the | |
726 // upper half followed by the lower half for little-endian. TODO: | |
727 // implement. | |
728 llvm_unreachable("Missing support for pushing doubles from memory"); | |
729 } else { | |
730 Str << "\tpush\t"; | |
731 getSrc(0)->emit(Func); | |
732 Str << "\n"; | |
733 if (!SuppressStackAdjustment) | |
734 Func->getTarget()->updateStackAdjustment(4); | |
735 } | |
736 } | |
737 | |
738 void InstX8632Push::dump(const Cfg *Func) const { | |
739 Ostream &Str = Func->getContext()->getStrDump(); | |
740 Str << "push." << getSrc(0)->getType() << " "; | |
741 dumpSources(Func); | |
742 } | |
743 | |
744 void InstX8632Ret::emit(const Cfg *Func) const { | |
745 Ostream &Str = Func->getContext()->getStrEmit(); | |
746 Str << "\tret\n"; | |
747 } | |
748 | |
749 void InstX8632Ret::dump(const Cfg *Func) const { | |
750 Ostream &Str = Func->getContext()->getStrDump(); | |
751 Type Ty = (getSrcSize() == 0 ? IceType_void : getSrc(0)->getType()); | |
752 Str << "ret." << Ty << " "; | |
753 dumpSources(Func); | |
754 } | |
755 | |
756 void OperandX8632::dump(const Cfg *Func) const { | |
757 Ostream &Str = Func->getContext()->getStrDump(); | |
758 Str << "<OperandX8632>"; | |
759 } | |
760 | |
761 void OperandX8632Mem::emit(const Cfg *Func) const { | |
762 Ostream &Str = Func->getContext()->getStrEmit(); | |
763 Str << TypeX8632Attributes[getType()].WidthString << " "; | |
764 // TODO: The following is an almost verbatim paste of dump(). | |
765 bool Dumped = false; | |
766 Str << "["; | |
767 if (Base) { | |
768 Base->emit(Func); | |
769 Dumped = true; | |
770 } | |
771 if (Index) { | |
772 assert(Base); | |
773 Str << "+"; | |
774 if (Shift > 0) | |
775 Str << (1u << Shift) << "*"; | |
776 Index->emit(Func); | |
777 Dumped = true; | |
778 } | |
779 // Pretty-print the Offset. | |
780 bool OffsetIsZero = false; | |
781 bool OffsetIsNegative = false; | |
782 if (Offset == NULL) { | |
783 OffsetIsZero = true; | |
784 } else if (ConstantInteger *CI = llvm::dyn_cast<ConstantInteger>(Offset)) { | |
785 OffsetIsZero = (CI->getValue() == 0); | |
786 OffsetIsNegative = (static_cast<int64_t>(CI->getValue()) < 0); | |
787 } | |
788 if (!OffsetIsZero) { // Suppress if Offset is known to be 0 | |
789 if (Dumped) { | |
790 if (!OffsetIsNegative) // Suppress if Offset is known to be negative | |
791 Str << "+"; | |
792 } | |
793 Offset->emit(Func); | |
794 } | |
795 Str << "]"; | |
796 } | |
797 | |
798 void OperandX8632Mem::dump(const Cfg *Func) const { | |
799 Ostream &Str = Func->getContext()->getStrDump(); | |
800 bool Dumped = false; | |
801 Str << "["; | |
802 if (Base) { | |
803 Base->dump(Func); | |
804 Dumped = true; | |
805 } | |
806 if (Index) { | |
807 assert(Base); | |
808 Str << "+"; | |
809 if (Shift > 0) | |
810 Str << (1u << Shift) << "*"; | |
811 Index->dump(Func); | |
812 Dumped = true; | |
813 } | |
814 // Pretty-print the Offset. | |
815 bool OffsetIsZero = false; | |
816 bool OffsetIsNegative = false; | |
817 if (Offset == NULL) { | |
818 OffsetIsZero = true; | |
819 } else if (ConstantInteger *CI = llvm::dyn_cast<ConstantInteger>(Offset)) { | |
820 OffsetIsZero = (CI->getValue() == 0); | |
821 OffsetIsNegative = (static_cast<int64_t>(CI->getValue()) < 0); | |
822 } | |
823 if (!OffsetIsZero) { // Suppress if Offset is known to be 0 | |
824 if (Dumped) { | |
825 if (!OffsetIsNegative) // Suppress if Offset is known to be negative | |
826 Str << "+"; | |
827 } | |
828 Offset->dump(Func); | |
829 } | |
830 Str << "]"; | |
831 } | |
832 | |
833 void VariableSplit::emit(const Cfg *Func) const { | |
834 Ostream &Str = Func->getContext()->getStrEmit(); | |
835 assert(Var->getLocalUseNode() == NULL || | |
836 Var->getLocalUseNode() == Func->getCurrentNode()); | |
837 assert(!Var->hasReg()); | |
838 // The following is copied/adapted from TargetX8632::emitVariable(). | |
839 const TargetLowering *Target = Func->getTarget(); | |
840 const Type Ty = IceType_i32; | |
841 Str << TypeX8632Attributes[Ty].WidthString << " [" | |
842 << Target->getRegName(Target->getFrameOrStackReg(), | |
843 Ty); | |
844 int32_t Offset = | |
845 Var->getStackOffset() + Target->getStackAdjustment(); | |
846 if (Part == High) | |
847 Offset += 4; | |
848 if (Offset) { | |
849 if (Offset > 0) | |
850 Str << "+"; | |
851 Str << Offset; | |
852 } | |
853 Str << "]"; | |
854 } | |
855 | |
856 void VariableSplit::dump(const Cfg *Func) const { | |
857 Ostream &Str = Func->getContext()->getStrDump(); | |
858 switch (Part) { | |
859 case Low: | |
860 Str << "low"; | |
861 break; | |
862 case High: | |
863 Str << "high"; | |
864 break; | |
865 default: | |
866 Str << "???"; | |
867 break; | |
868 } | |
869 Str << "("; | |
870 Var->dump(Func); | |
871 Str << ")"; | |
872 } | |
873 | |
874 } // end of namespace Ice | |
OLD | NEW |