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 |