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