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

Side by Side Diff: src/IceInstX8632.cpp

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

Powered by Google App Engine
This is Rietveld 408576698