| 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 |