Chromium Code Reviews| 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 452 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 463 template <> const char *InstX8632Divps::Opcode = "divps"; | 463 template <> const char *InstX8632Divps::Opcode = "divps"; |
| 464 template <> const char *InstX8632Idiv::Opcode = "idiv"; | 464 template <> const char *InstX8632Idiv::Opcode = "idiv"; |
| 465 template <> const char *InstX8632Divss::Opcode = "divss"; | 465 template <> const char *InstX8632Divss::Opcode = "divss"; |
| 466 template <> const char *InstX8632Shl::Opcode = "shl"; | 466 template <> const char *InstX8632Shl::Opcode = "shl"; |
| 467 template <> const char *InstX8632Psll::Opcode = "psll"; | 467 template <> const char *InstX8632Psll::Opcode = "psll"; |
| 468 template <> const char *InstX8632Shr::Opcode = "shr"; | 468 template <> const char *InstX8632Shr::Opcode = "shr"; |
| 469 template <> const char *InstX8632Sar::Opcode = "sar"; | 469 template <> const char *InstX8632Sar::Opcode = "sar"; |
| 470 template <> const char *InstX8632Psra::Opcode = "psra"; | 470 template <> const char *InstX8632Psra::Opcode = "psra"; |
| 471 template <> const char *InstX8632Pcmpeq::Opcode = "pcmpeq"; | 471 template <> const char *InstX8632Pcmpeq::Opcode = "pcmpeq"; |
| 472 template <> const char *InstX8632Pcmpgt::Opcode = "pcmpgt"; | 472 template <> const char *InstX8632Pcmpgt::Opcode = "pcmpgt"; |
| 473 template <> const char *InstX8632Pextrw::Opcode = "pextrw"; | |
| 474 template <> const char *InstX8632Pinsrw::Opcode = "pinsrw"; | |
| 475 template <> const char *InstX8632Shufps::Opcode = "shufps"; | |
| 476 template <> const char *InstX8632Pshufd::Opcode = "pshufd"; | |
| 477 template <> const char *InstX8632Lea::Opcode = "lea"; | |
|
jvoung (off chromium)
2014/07/17 19:36:38
Cluster lea, and movd w/ the other unary ops?
Cou
wala
2014/07/17 22:14:12
Done.
| |
| 478 template <> const char *InstX8632Movd::Opcode = "movd"; | |
| 479 template <> const char *InstX8632Movss::Opcode = "movss"; | |
| 473 | 480 |
| 474 template <> void InstX8632Sqrtss::emit(const Cfg *Func) const { | 481 template <> void InstX8632Sqrtss::emit(const Cfg *Func) const { |
| 475 Ostream &Str = Func->getContext()->getStrEmit(); | 482 Ostream &Str = Func->getContext()->getStrEmit(); |
| 476 assert(getSrcSize() == 1); | 483 assert(getSrcSize() == 1); |
| 477 Type Ty = getSrc(0)->getType(); | 484 Type Ty = getSrc(0)->getType(); |
| 478 assert(Ty == IceType_f32 || Ty == IceType_f64); | 485 assert(Ty == IceType_f32 || Ty == IceType_f64); |
| 479 Str << "\tsqrt" << TypeX8632Attributes[Ty].SdSsString << "\t"; | 486 Str << "\tsqrt" << TypeX8632Attributes[Ty].SdSsString << "\t"; |
| 480 getDest()->emit(Func); | 487 getDest()->emit(Func); |
| 481 Str << ", "; | 488 Str << ", "; |
| 482 getSrc(0)->emit(Func); | 489 getSrc(0)->emit(Func); |
| (...skipping 21 matching lines...) Expand all Loading... | |
| 504 emitTwoAddress(buf, this, Func); | 511 emitTwoAddress(buf, this, Func); |
| 505 } | 512 } |
| 506 | 513 |
| 507 template <> void InstX8632Divss::emit(const Cfg *Func) const { | 514 template <> void InstX8632Divss::emit(const Cfg *Func) const { |
| 508 char buf[30]; | 515 char buf[30]; |
| 509 snprintf(buf, llvm::array_lengthof(buf), "div%s", | 516 snprintf(buf, llvm::array_lengthof(buf), "div%s", |
| 510 TypeX8632Attributes[getDest()->getType()].SdSsString); | 517 TypeX8632Attributes[getDest()->getType()].SdSsString); |
| 511 emitTwoAddress(buf, this, Func); | 518 emitTwoAddress(buf, this, Func); |
| 512 } | 519 } |
| 513 | 520 |
| 521 template <> void InstX8632Div::emit(const Cfg *Func) const { | |
| 522 Ostream &Str = Func->getContext()->getStrEmit(); | |
| 523 assert(getSrcSize() == 3); | |
| 524 Str << "\t" << Opcode << "\t"; | |
| 525 getSrc(1)->emit(Func); | |
| 526 Str << "\n"; | |
| 527 } | |
| 528 | |
| 529 template <> void InstX8632Idiv::emit(const Cfg *Func) const { | |
| 530 Ostream &Str = Func->getContext()->getStrEmit(); | |
| 531 assert(getSrcSize() == 3); | |
| 532 Str << "\t" << Opcode << "\t"; | |
| 533 getSrc(1)->emit(Func); | |
| 534 Str << "\n"; | |
| 535 } | |
| 536 | |
| 514 template <> void InstX8632Imul::emit(const Cfg *Func) const { | 537 template <> void InstX8632Imul::emit(const Cfg *Func) const { |
| 515 Ostream &Str = Func->getContext()->getStrEmit(); | 538 Ostream &Str = Func->getContext()->getStrEmit(); |
| 516 assert(getSrcSize() == 2); | 539 assert(getSrcSize() == 2); |
| 517 if (getDest()->getType() == IceType_i8) { | 540 if (getDest()->getType() == IceType_i8) { |
| 518 // The 8-bit version of imul only allows the form "imul r/m8". | 541 // The 8-bit version of imul only allows the form "imul r/m8". |
| 519 Variable *Src0 = llvm::dyn_cast<Variable>(getSrc(0)); | 542 Variable *Src0 = llvm::dyn_cast<Variable>(getSrc(0)); |
| 520 assert(Src0 && Src0->getRegNum() == TargetX8632::Reg_eax); | 543 assert(Src0 && Src0->getRegNum() == TargetX8632::Reg_eax); |
| 521 Str << "\timul\t"; | 544 Str << "\timul\t"; |
| 522 getSrc(1)->emit(Func); | 545 getSrc(1)->emit(Func); |
| 523 Str << "\n"; | 546 Str << "\n"; |
| (...skipping 292 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 816 } | 839 } |
| 817 | 840 |
| 818 void InstX8632StoreQ::dump(const Cfg *Func) const { | 841 void InstX8632StoreQ::dump(const Cfg *Func) const { |
| 819 Ostream &Str = Func->getContext()->getStrDump(); | 842 Ostream &Str = Func->getContext()->getStrDump(); |
| 820 Str << "storeq." << getSrc(0)->getType() << " "; | 843 Str << "storeq." << getSrc(0)->getType() << " "; |
| 821 getSrc(1)->dump(Func); | 844 getSrc(1)->dump(Func); |
| 822 Str << ", "; | 845 Str << ", "; |
| 823 getSrc(0)->dump(Func); | 846 getSrc(0)->dump(Func); |
| 824 } | 847 } |
| 825 | 848 |
| 849 template <> void InstX8632Lea::emit(const Cfg *Func) const { | |
| 850 Ostream &Str = Func->getContext()->getStrEmit(); | |
| 851 assert(getSrcSize() == 1); | |
| 852 assert(getDest()->hasReg()); | |
| 853 Str << "\tlea\t"; | |
| 854 getDest()->emit(Func); | |
| 855 Str << ", "; | |
| 856 Operand *Src0 = getSrc(0); | |
| 857 if (Variable *VSrc0 = llvm::dyn_cast<Variable>(Src0)) { | |
| 858 Type Ty = VSrc0->getType(); | |
| 859 // lea on x86-32 doesn't accept mem128 operands, so cast VSrc0 to an | |
| 860 // acceptable type. | |
| 861 VSrc0->asType(isVectorType(Ty) ? IceType_i32 : Ty).emit(Func); | |
| 862 } else { | |
| 863 Src0->emit(Func); | |
| 864 } | |
| 865 Str << "\n"; | |
| 866 } | |
| 867 | |
| 826 void InstX8632Mov::emit(const Cfg *Func) const { | 868 void InstX8632Mov::emit(const Cfg *Func) const { |
| 827 Ostream &Str = Func->getContext()->getStrEmit(); | 869 Ostream &Str = Func->getContext()->getStrEmit(); |
| 828 assert(getSrcSize() == 1); | 870 assert(getSrcSize() == 1); |
| 829 Operand *Src = getSrc(0); | 871 Operand *Src = getSrc(0); |
| 830 // The llvm-mc assembler using Intel syntax has a bug in which "mov | 872 // The llvm-mc assembler using Intel syntax has a bug in which "mov |
| 831 // reg, RelocatableConstant" does not generate the right instruction | 873 // reg, RelocatableConstant" does not generate the right instruction |
| 832 // with a relocation. To work around, we emit "lea reg, | 874 // with a relocation. To work around, we emit "lea reg, |
| 833 // [RelocatableConstant]". Also, the lowering and legalization is | 875 // [RelocatableConstant]". Also, the lowering and legalization is |
| 834 // changed to allow relocatable constants only in Assign and Call | 876 // changed to allow relocatable constants only in Assign and Call |
| 835 // instructions or in Mem operands. TODO(stichnot): remove LEAHACK | 877 // instructions or in Mem operands. TODO(stichnot): remove LEAHACK |
| 836 // once a proper emitter is used. | 878 // once a proper emitter is used. |
| 837 bool UseLeaHack = llvm::isa<ConstantRelocatable>(Src); | 879 bool UseLeaHack = llvm::isa<ConstantRelocatable>(Src); |
| 838 Str << "\t"; | 880 Str << "\t"; |
| 839 if (UseLeaHack) | 881 if (UseLeaHack) |
| 840 Str << "lea"; | 882 Str << "lea"; |
| 841 else | 883 else |
| 842 Str << "mov" << TypeX8632Attributes[getDest()->getType()].SdSsString; | 884 Str << "mov" << TypeX8632Attributes[getDest()->getType()].SdSsString; |
|
jvoung (off chromium)
2014/07/17 19:36:38
This regular mov will overlap a bit w/ the added m
wala
2014/07/17 22:14:12
I need to copy a single floating point value out o
Jim Stichnoth
2014/07/18 17:21:01
OK. This is something that will need to be cleane
wala
2014/07/18 19:36:13
Done.
| |
| 843 Str << "\t"; | 885 Str << "\t"; |
| 844 // For an integer truncation operation, src is wider than dest. | 886 // For an integer truncation operation, src is wider than dest. |
| 845 // Ideally, we use a mov instruction whose data width matches the | 887 // Ideally, we use a mov instruction whose data width matches the |
| 846 // narrower dest. This is a problem if e.g. src is a register like | 888 // narrower dest. This is a problem if e.g. src is a register like |
| 847 // esi or si where there is no 8-bit version of the register. To be | 889 // esi or si where there is no 8-bit version of the register. To be |
| 848 // safe, we instead widen the dest to match src. This works even | 890 // safe, we instead widen the dest to match src. This works even |
| 849 // for stack-allocated dest variables because typeWidthOnStack() | 891 // for stack-allocated dest variables because typeWidthOnStack() |
| 850 // pads to a 4-byte boundary even if only a lower portion is used. | 892 // pads to a 4-byte boundary even if only a lower portion is used. |
| 851 assert(Func->getTarget()->typeWidthInBytesOnStack(getDest()->getType()) == | 893 assert(Func->getTarget()->typeWidthInBytesOnStack(getDest()->getType()) == |
| 852 Func->getTarget()->typeWidthInBytesOnStack(Src->getType())); | 894 Func->getTarget()->typeWidthInBytesOnStack(Src->getType())); |
| (...skipping 161 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1014 emitTwoAddress(buf, this, Func); | 1056 emitTwoAddress(buf, this, Func); |
| 1015 } | 1057 } |
| 1016 | 1058 |
| 1017 template <> void InstX8632Pcmpgt::emit(const Cfg *Func) const { | 1059 template <> void InstX8632Pcmpgt::emit(const Cfg *Func) const { |
| 1018 char buf[30]; | 1060 char buf[30]; |
| 1019 snprintf(buf, llvm::array_lengthof(buf), "pcmpgt%s", | 1061 snprintf(buf, llvm::array_lengthof(buf), "pcmpgt%s", |
| 1020 TypeX8632Attributes[getDest()->getType()].PackString); | 1062 TypeX8632Attributes[getDest()->getType()].PackString); |
| 1021 emitTwoAddress(buf, this, Func); | 1063 emitTwoAddress(buf, this, Func); |
| 1022 } | 1064 } |
| 1023 | 1065 |
| 1066 template <> void InstX8632Pextrw::emit(const Cfg *Func) const { | |
| 1067 Ostream &Str = Func->getContext()->getStrEmit(); | |
| 1068 assert(getSrcSize() == 2); | |
| 1069 Str << "\t" << Opcode << "\t"; | |
| 1070 Variable *Dest = getDest(); | |
| 1071 assert(Dest->hasReg() && Dest->getType() == IceType_i16); | |
| 1072 // pextrw takes r32 dest. | |
| 1073 Dest->asType(IceType_i32).emit(Func); | |
| 1074 Str << ", "; | |
| 1075 getSrc(0)->emit(Func); | |
| 1076 Str << ", "; | |
| 1077 getSrc(1)->emit(Func); | |
| 1078 Str << "\n"; | |
| 1079 } | |
| 1080 | |
| 1081 template <> void InstX8632Pinsrw::emit(const Cfg *Func) const { | |
| 1082 Ostream &Str = Func->getContext()->getStrEmit(); | |
| 1083 assert(getSrcSize() == 3); | |
| 1084 Str << "\t" << Opcode << "\t"; | |
| 1085 getDest()->emit(Func); | |
| 1086 Str << ", "; | |
| 1087 Operand *Src1 = getSrc(1); | |
| 1088 if (Variable *VSrc1 = llvm::dyn_cast<Variable>(Src1)) { | |
| 1089 // If src1 is a register, it should be r32. | |
| 1090 VSrc1->asType(VSrc1->hasReg() ? IceType_i32 : IceType_i16).emit(Func); | |
| 1091 } else { | |
| 1092 Src1->emit(Func); | |
| 1093 } | |
| 1094 Str << ", "; | |
| 1095 getSrc(2)->emit(Func); | |
| 1096 Str << "\n"; | |
| 1097 } | |
| 1098 | |
| 1024 void InstX8632Pop::emit(const Cfg *Func) const { | 1099 void InstX8632Pop::emit(const Cfg *Func) const { |
| 1025 Ostream &Str = Func->getContext()->getStrEmit(); | 1100 Ostream &Str = Func->getContext()->getStrEmit(); |
| 1026 assert(getSrcSize() == 0); | 1101 assert(getSrcSize() == 0); |
| 1027 Str << "\tpop\t"; | 1102 Str << "\tpop\t"; |
| 1028 getDest()->emit(Func); | 1103 getDest()->emit(Func); |
| 1029 Str << "\n"; | 1104 Str << "\n"; |
| 1030 } | 1105 } |
| 1031 | 1106 |
| 1032 void InstX8632Pop::dump(const Cfg *Func) const { | 1107 void InstX8632Pop::dump(const Cfg *Func) const { |
| 1033 Ostream &Str = Func->getContext()->getStrDump(); | 1108 Ostream &Str = Func->getContext()->getStrDump(); |
| (...skipping 242 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1276 default: | 1351 default: |
| 1277 Str << "???"; | 1352 Str << "???"; |
| 1278 break; | 1353 break; |
| 1279 } | 1354 } |
| 1280 Str << "("; | 1355 Str << "("; |
| 1281 Var->dump(Func); | 1356 Var->dump(Func); |
| 1282 Str << ")"; | 1357 Str << ")"; |
| 1283 } | 1358 } |
| 1284 | 1359 |
| 1285 } // end of namespace Ice | 1360 } // end of namespace Ice |
| OLD | NEW |