OLD | NEW |
1 //===- subzero/src/IceInstX8632.cpp - X86-32 instruction implementation ---===// | 1 //===- subzero/src/IceInstX8632.cpp - X86-32 instruction implementation ---===// |
2 // | 2 // |
3 // The Subzero Code Generator | 3 // The Subzero Code Generator |
4 // | 4 // |
5 // This file is distributed under the University of Illinois Open Source | 5 // This file is distributed under the University of Illinois Open Source |
6 // License. See LICENSE.TXT for details. | 6 // License. See LICENSE.TXT for details. |
7 // | 7 // |
8 //===----------------------------------------------------------------------===// | 8 //===----------------------------------------------------------------------===// |
9 // | 9 // |
10 // This file implements the InstX8632 and OperandX8632 classes, | 10 // This file implements the InstX8632 and OperandX8632 classes, |
(...skipping 148 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
159 | 159 |
160 InstX8632UD2::InstX8632UD2(Cfg *Func) | 160 InstX8632UD2::InstX8632UD2(Cfg *Func) |
161 : InstX8632(Func, InstX8632::UD2, 0, NULL) {} | 161 : InstX8632(Func, InstX8632::UD2, 0, NULL) {} |
162 | 162 |
163 InstX8632Test::InstX8632Test(Cfg *Func, Operand *Src1, Operand *Src2) | 163 InstX8632Test::InstX8632Test(Cfg *Func, Operand *Src1, Operand *Src2) |
164 : InstX8632(Func, InstX8632::Test, 2, NULL) { | 164 : InstX8632(Func, InstX8632::Test, 2, NULL) { |
165 addSource(Src1); | 165 addSource(Src1); |
166 addSource(Src2); | 166 addSource(Src2); |
167 } | 167 } |
168 | 168 |
| 169 InstX8632Mfence::InstX8632Mfence(Cfg *Func) |
| 170 : InstX8632(Func, InstX8632::Mfence, 0, NULL) { |
| 171 HasSideEffects = true; |
| 172 } |
| 173 |
169 InstX8632Store::InstX8632Store(Cfg *Func, Operand *Value, OperandX8632 *Mem) | 174 InstX8632Store::InstX8632Store(Cfg *Func, Operand *Value, OperandX8632 *Mem) |
170 : InstX8632(Func, InstX8632::Store, 2, NULL) { | 175 : InstX8632(Func, InstX8632::Store, 2, NULL) { |
171 addSource(Value); | 176 addSource(Value); |
172 addSource(Mem); | 177 addSource(Mem); |
173 } | 178 } |
174 | 179 |
175 InstX8632Mov::InstX8632Mov(Cfg *Func, Variable *Dest, Operand *Source) | 180 InstX8632Mov::InstX8632Mov(Cfg *Func, Variable *Dest, Operand *Source) |
176 : InstX8632(Func, InstX8632::Mov, 1, Dest) { | 181 : InstX8632(Func, InstX8632::Mov, 1, Dest) { |
177 addSource(Source); | 182 addSource(Source); |
178 } | 183 } |
179 | 184 |
| 185 InstX8632StoreQ::InstX8632StoreQ(Cfg *Func, Operand *Value, OperandX8632 *Mem) |
| 186 : InstX8632(Func, InstX8632::StoreQ, 2, NULL) { |
| 187 addSource(Value); |
| 188 addSource(Mem); |
| 189 } |
| 190 |
| 191 InstX8632Movq::InstX8632Movq(Cfg *Func, Variable *Dest, Operand *Source) |
| 192 : InstX8632(Func, InstX8632::Movq, 1, Dest) { |
| 193 addSource(Source); |
| 194 } |
| 195 |
180 InstX8632Movsx::InstX8632Movsx(Cfg *Func, Variable *Dest, Operand *Source) | 196 InstX8632Movsx::InstX8632Movsx(Cfg *Func, Variable *Dest, Operand *Source) |
181 : InstX8632(Func, InstX8632::Movsx, 1, Dest) { | 197 : InstX8632(Func, InstX8632::Movsx, 1, Dest) { |
182 addSource(Source); | 198 addSource(Source); |
183 } | 199 } |
184 | 200 |
185 InstX8632Movzx::InstX8632Movzx(Cfg *Func, Variable *Dest, Operand *Source) | 201 InstX8632Movzx::InstX8632Movzx(Cfg *Func, Variable *Dest, Operand *Source) |
186 : InstX8632(Func, InstX8632::Movzx, 1, Dest) { | 202 : InstX8632(Func, InstX8632::Movzx, 1, Dest) { |
187 addSource(Source); | 203 addSource(Source); |
188 } | 204 } |
189 | 205 |
(...skipping 24 matching lines...) Expand all Loading... |
214 // clear the upper 32 bits of rax. We need to recognize and | 230 // clear the upper 32 bits of rax. We need to recognize and |
215 // preserve these. | 231 // preserve these. |
216 return true; | 232 return true; |
217 } | 233 } |
218 if (!getDest()->hasReg() && !Src->hasReg() && | 234 if (!getDest()->hasReg() && !Src->hasReg() && |
219 Dest->getStackOffset() == Src->getStackOffset()) | 235 Dest->getStackOffset() == Src->getStackOffset()) |
220 return true; | 236 return true; |
221 return false; | 237 return false; |
222 } | 238 } |
223 | 239 |
| 240 bool InstX8632Movq::isRedundantAssign() const { |
| 241 Variable *Src = llvm::dyn_cast<Variable>(getSrc(0)); |
| 242 if (Src == NULL) |
| 243 return false; |
| 244 if (getDest()->hasReg() && getDest()->getRegNum() == Src->getRegNum()) { |
| 245 return true; |
| 246 } |
| 247 if (!getDest()->hasReg() && !Src->hasReg() && |
| 248 Dest->getStackOffset() == Src->getStackOffset()) |
| 249 return true; |
| 250 return false; |
| 251 } |
| 252 |
224 InstX8632Ret::InstX8632Ret(Cfg *Func, Variable *Source) | 253 InstX8632Ret::InstX8632Ret(Cfg *Func, Variable *Source) |
225 : InstX8632(Func, InstX8632::Ret, Source ? 1 : 0, NULL) { | 254 : InstX8632(Func, InstX8632::Ret, Source ? 1 : 0, NULL) { |
226 if (Source) | 255 if (Source) |
227 addSource(Source); | 256 addSource(Source); |
228 } | 257 } |
229 | 258 |
| 259 InstX8632Xadd::InstX8632Xadd(Cfg *Func, Operand *Dest, Variable *Source, |
| 260 bool Locked) |
| 261 : InstX8632(Func, InstX8632::Xadd, 2, llvm::dyn_cast<Variable>(Dest)), |
| 262 Locked(Locked) { |
| 263 HasSideEffects = Locked; |
| 264 addSource(Dest); |
| 265 addSource(Source); |
| 266 } |
| 267 |
230 // ======================== Dump routines ======================== // | 268 // ======================== Dump routines ======================== // |
231 | 269 |
232 void InstX8632::dump(const Cfg *Func) const { | 270 void InstX8632::dump(const Cfg *Func) const { |
233 Ostream &Str = Func->getContext()->getStrDump(); | 271 Ostream &Str = Func->getContext()->getStrDump(); |
234 Str << "[X8632] "; | 272 Str << "[X8632] "; |
235 Inst::dump(Func); | 273 Inst::dump(Func); |
236 } | 274 } |
237 | 275 |
238 void InstX8632Label::emit(const Cfg *Func) const { | 276 void InstX8632Label::emit(const Cfg *Func) const { |
239 Ostream &Str = Func->getContext()->getStrEmit(); | 277 Ostream &Str = Func->getContext()->getStrEmit(); |
(...skipping 317 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
557 getSrc(1)->emit(Func); | 595 getSrc(1)->emit(Func); |
558 Str << "\n"; | 596 Str << "\n"; |
559 } | 597 } |
560 | 598 |
561 void InstX8632Test::dump(const Cfg *Func) const { | 599 void InstX8632Test::dump(const Cfg *Func) const { |
562 Ostream &Str = Func->getContext()->getStrDump(); | 600 Ostream &Str = Func->getContext()->getStrDump(); |
563 Str << "test." << getSrc(0)->getType() << " "; | 601 Str << "test." << getSrc(0)->getType() << " "; |
564 dumpSources(Func); | 602 dumpSources(Func); |
565 } | 603 } |
566 | 604 |
| 605 void InstX8632Mfence::emit(const Cfg *Func) const { |
| 606 Ostream &Str = Func->getContext()->getStrEmit(); |
| 607 assert(getSrcSize() == 0); |
| 608 Str << "\tmfence\n"; |
| 609 } |
| 610 |
| 611 void InstX8632Mfence::dump(const Cfg *Func) const { |
| 612 Ostream &Str = Func->getContext()->getStrDump(); |
| 613 Str << "mfence\n"; |
| 614 } |
| 615 |
567 void InstX8632Store::emit(const Cfg *Func) const { | 616 void InstX8632Store::emit(const Cfg *Func) const { |
568 Ostream &Str = Func->getContext()->getStrEmit(); | 617 Ostream &Str = Func->getContext()->getStrEmit(); |
569 assert(getSrcSize() == 2); | 618 assert(getSrcSize() == 2); |
570 Str << "\tmov" << TypeX8632Attributes[getSrc(0)->getType()].SdSsString | 619 Str << "\tmov" << TypeX8632Attributes[getSrc(0)->getType()].SdSsString |
571 << "\t"; | 620 << "\t"; |
572 getSrc(1)->emit(Func); | 621 getSrc(1)->emit(Func); |
573 Str << ", "; | 622 Str << ", "; |
574 getSrc(0)->emit(Func); | 623 getSrc(0)->emit(Func); |
575 Str << "\n"; | 624 Str << "\n"; |
576 } | 625 } |
577 | 626 |
578 void InstX8632Store::dump(const Cfg *Func) const { | 627 void InstX8632Store::dump(const Cfg *Func) const { |
579 Ostream &Str = Func->getContext()->getStrDump(); | 628 Ostream &Str = Func->getContext()->getStrDump(); |
580 Str << "mov." << getSrc(0)->getType() << " "; | 629 Str << "mov." << getSrc(0)->getType() << " "; |
581 getSrc(1)->dump(Func); | 630 getSrc(1)->dump(Func); |
582 Str << ", "; | 631 Str << ", "; |
583 getSrc(0)->dump(Func); | 632 getSrc(0)->dump(Func); |
584 } | 633 } |
585 | 634 |
| 635 void InstX8632StoreQ::emit(const Cfg *Func) const { |
| 636 Ostream &Str = Func->getContext()->getStrEmit(); |
| 637 assert(getSrcSize() == 2); |
| 638 assert(getSrc(1)->getType() == IceType_i64 || |
| 639 getSrc(1)->getType() == IceType_f64); |
| 640 Str << "\tmovq\t"; |
| 641 getSrc(1)->emit(Func); |
| 642 Str << ", "; |
| 643 getSrc(0)->emit(Func); |
| 644 Str << "\n"; |
| 645 } |
| 646 |
| 647 void InstX8632StoreQ::dump(const Cfg *Func) const { |
| 648 Ostream &Str = Func->getContext()->getStrDump(); |
| 649 Str << "storeq." << getSrc(0)->getType() << " "; |
| 650 getSrc(1)->dump(Func); |
| 651 Str << ", "; |
| 652 getSrc(0)->dump(Func); |
| 653 } |
| 654 |
586 void InstX8632Mov::emit(const Cfg *Func) const { | 655 void InstX8632Mov::emit(const Cfg *Func) const { |
587 Ostream &Str = Func->getContext()->getStrEmit(); | 656 Ostream &Str = Func->getContext()->getStrEmit(); |
588 assert(getSrcSize() == 1); | 657 assert(getSrcSize() == 1); |
589 Str << "\tmov" << TypeX8632Attributes[getDest()->getType()].SdSsString | 658 Str << "\tmov" << TypeX8632Attributes[getDest()->getType()].SdSsString |
590 << "\t"; | 659 << "\t"; |
591 // For an integer truncation operation, src is wider than dest. | 660 // For an integer truncation operation, src is wider than dest. |
592 // Ideally, we use a mov instruction whose data width matches the | 661 // Ideally, we use a mov instruction whose data width matches the |
593 // narrower dest. This is a problem if e.g. src is a register like | 662 // narrower dest. This is a problem if e.g. src is a register like |
594 // esi or si where there is no 8-bit version of the register. To be | 663 // esi or si where there is no 8-bit version of the register. To be |
595 // safe, we instead widen the dest to match src. This works even | 664 // safe, we instead widen the dest to match src. This works even |
596 // for stack-allocated dest variables because typeWidthOnStack() | 665 // for stack-allocated dest variables because typeWidthOnStack() |
597 // pads to a 4-byte boundary even if only a lower portion is used. | 666 // pads to a 4-byte boundary even if only a lower portion is used. |
598 assert(Func->getTarget()->typeWidthInBytesOnStack(getDest()->getType()) == | 667 assert(Func->getTarget()->typeWidthInBytesOnStack(getDest()->getType()) == |
599 Func->getTarget()->typeWidthInBytesOnStack(getSrc(0)->getType())); | 668 Func->getTarget()->typeWidthInBytesOnStack(getSrc(0)->getType())); |
600 getDest()->asType(getSrc(0)->getType()).emit(Func); | 669 getDest()->asType(getSrc(0)->getType()).emit(Func); |
601 Str << ", "; | 670 Str << ", "; |
602 getSrc(0)->emit(Func); | 671 getSrc(0)->emit(Func); |
603 Str << "\n"; | 672 Str << "\n"; |
604 } | 673 } |
605 | 674 |
606 void InstX8632Mov::dump(const Cfg *Func) const { | 675 void InstX8632Mov::dump(const Cfg *Func) const { |
607 Ostream &Str = Func->getContext()->getStrDump(); | 676 Ostream &Str = Func->getContext()->getStrDump(); |
608 Str << "mov." << getDest()->getType() << " "; | 677 Str << "mov." << getDest()->getType() << " "; |
609 dumpDest(Func); | 678 dumpDest(Func); |
610 Str << ", "; | 679 Str << ", "; |
611 dumpSources(Func); | 680 dumpSources(Func); |
612 } | 681 } |
613 | 682 |
| 683 void InstX8632Movq::emit(const Cfg *Func) const { |
| 684 Ostream &Str = Func->getContext()->getStrEmit(); |
| 685 assert(getSrcSize() == 1); |
| 686 assert(getDest()->getType() == IceType_i64 || |
| 687 getDest()->getType() == IceType_f64); |
| 688 Str << "\tmovq\t"; |
| 689 getDest()->emit(Func); |
| 690 Str << ", "; |
| 691 getSrc(0)->emit(Func); |
| 692 Str << "\n"; |
| 693 } |
| 694 |
| 695 void InstX8632Movq::dump(const Cfg *Func) const { |
| 696 Ostream &Str = Func->getContext()->getStrDump(); |
| 697 Str << "movq." << getDest()->getType() << " "; |
| 698 dumpDest(Func); |
| 699 Str << ", "; |
| 700 dumpSources(Func); |
| 701 } |
| 702 |
614 void InstX8632Movsx::emit(const Cfg *Func) const { | 703 void InstX8632Movsx::emit(const Cfg *Func) const { |
615 Ostream &Str = Func->getContext()->getStrEmit(); | 704 Ostream &Str = Func->getContext()->getStrEmit(); |
616 assert(getSrcSize() == 1); | 705 assert(getSrcSize() == 1); |
617 Str << "\tmovsx\t"; | 706 Str << "\tmovsx\t"; |
618 getDest()->emit(Func); | 707 getDest()->emit(Func); |
619 Str << ", "; | 708 Str << ", "; |
620 getSrc(0)->emit(Func); | 709 getSrc(0)->emit(Func); |
621 Str << "\n"; | 710 Str << "\n"; |
622 } | 711 } |
623 | 712 |
(...skipping 142 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
766 Str << "\tret\n"; | 855 Str << "\tret\n"; |
767 } | 856 } |
768 | 857 |
769 void InstX8632Ret::dump(const Cfg *Func) const { | 858 void InstX8632Ret::dump(const Cfg *Func) const { |
770 Ostream &Str = Func->getContext()->getStrDump(); | 859 Ostream &Str = Func->getContext()->getStrDump(); |
771 Type Ty = (getSrcSize() == 0 ? IceType_void : getSrc(0)->getType()); | 860 Type Ty = (getSrcSize() == 0 ? IceType_void : getSrc(0)->getType()); |
772 Str << "ret." << Ty << " "; | 861 Str << "ret." << Ty << " "; |
773 dumpSources(Func); | 862 dumpSources(Func); |
774 } | 863 } |
775 | 864 |
| 865 void InstX8632Xadd::emit(const Cfg *Func) const { |
| 866 Ostream &Str = Func->getContext()->getStrEmit(); |
| 867 if (Locked) { |
| 868 Str << "\tlock xadd "; |
| 869 } else { |
| 870 Str << "\txadd\t"; |
| 871 } |
| 872 getSrc(0)->emit(Func); |
| 873 Str << ", "; |
| 874 getSrc(1)->emit(Func); |
| 875 Str << "\n"; |
| 876 } |
| 877 |
| 878 void InstX8632Xadd::dump(const Cfg *Func) const { |
| 879 Ostream &Str = Func->getContext()->getStrDump(); |
| 880 if (Locked) { |
| 881 Str << "lock "; |
| 882 } |
| 883 Type Ty = getSrc(0)->getType(); |
| 884 Str << "xadd." << Ty << " "; |
| 885 dumpSources(Func); |
| 886 } |
| 887 |
776 void OperandX8632::dump(const Cfg *Func) const { | 888 void OperandX8632::dump(const Cfg *Func) const { |
777 Ostream &Str = Func->getContext()->getStrDump(); | 889 Ostream &Str = Func->getContext()->getStrDump(); |
778 Str << "<OperandX8632>"; | 890 Str << "<OperandX8632>"; |
779 } | 891 } |
780 | 892 |
781 void OperandX8632Mem::emit(const Cfg *Func) const { | 893 void OperandX8632Mem::emit(const Cfg *Func) const { |
782 Ostream &Str = Func->getContext()->getStrEmit(); | 894 Ostream &Str = Func->getContext()->getStrEmit(); |
783 Str << TypeX8632Attributes[getType()].WidthString << " "; | 895 Str << TypeX8632Attributes[getType()].WidthString << " "; |
784 if (SegmentReg != DefaultSegment) { | 896 if (SegmentReg != DefaultSegment) { |
785 assert(SegmentReg >= 0 && | 897 assert(SegmentReg >= 0 && |
(...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
899 default: | 1011 default: |
900 Str << "???"; | 1012 Str << "???"; |
901 break; | 1013 break; |
902 } | 1014 } |
903 Str << "("; | 1015 Str << "("; |
904 Var->dump(Func); | 1016 Var->dump(Func); |
905 Str << ")"; | 1017 Str << ")"; |
906 } | 1018 } |
907 | 1019 |
908 } // end of namespace Ice | 1020 } // end of namespace Ice |
OLD | NEW |