| 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 24 matching lines...) Expand all Loading... |
| 35 }; | 35 }; |
| 36 const size_t InstX8632BrAttributesSize = | 36 const size_t InstX8632BrAttributesSize = |
| 37 llvm::array_lengthof(InstX8632BrAttributes); | 37 llvm::array_lengthof(InstX8632BrAttributes); |
| 38 | 38 |
| 39 const struct TypeX8632Attributes_ { | 39 const struct TypeX8632Attributes_ { |
| 40 const char *CvtString; // i (integer), s (single FP), d (double FP) | 40 const char *CvtString; // i (integer), s (single FP), d (double FP) |
| 41 const char *SdSsString; // ss, sd, or <blank> | 41 const char *SdSsString; // ss, sd, or <blank> |
| 42 const char *PackString; // b, w, d, or <blank> | 42 const char *PackString; // b, w, d, or <blank> |
| 43 const char *WidthString; // {byte,word,dword,qword} ptr | 43 const char *WidthString; // {byte,word,dword,qword} ptr |
| 44 } TypeX8632Attributes[] = { | 44 } TypeX8632Attributes[] = { |
| 45 #define X(tag, cvt, sdss, pack, width) \ | 45 #define X(tag, elementty, cvt, sdss, pack, width) \ |
| 46 { cvt, "" sdss, pack, width } \ | 46 { cvt, "" sdss, pack, width } \ |
| 47 , | 47 , |
| 48 ICETYPEX8632_TABLE | 48 ICETYPEX8632_TABLE |
| 49 #undef X | 49 #undef X |
| 50 }; | 50 }; |
| 51 const size_t TypeX8632AttributesSize = | 51 const size_t TypeX8632AttributesSize = |
| 52 llvm::array_lengthof(TypeX8632Attributes); | 52 llvm::array_lengthof(TypeX8632Attributes); |
| 53 | 53 |
| 54 const char *InstX8632SegmentRegNames[] = { | 54 const char *InstX8632SegmentRegNames[] = { |
| 55 #define X(val, name) name, | 55 #define X(val, name) name, |
| (...skipping 376 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 432 if (ShiftReg && ShiftReg->getRegNum() == TargetX8632::Reg_ecx) { | 432 if (ShiftReg && ShiftReg->getRegNum() == TargetX8632::Reg_ecx) { |
| 433 Str << "cl"; | 433 Str << "cl"; |
| 434 EmittedSrc1 = true; | 434 EmittedSrc1 = true; |
| 435 } | 435 } |
| 436 } | 436 } |
| 437 if (!EmittedSrc1) | 437 if (!EmittedSrc1) |
| 438 Inst->getSrc(1)->emit(Func); | 438 Inst->getSrc(1)->emit(Func); |
| 439 Str << "\n"; | 439 Str << "\n"; |
| 440 } | 440 } |
| 441 | 441 |
| 442 |
| 443 // Unary ops |
| 442 template <> const char *InstX8632Bsf::Opcode = "bsf"; | 444 template <> const char *InstX8632Bsf::Opcode = "bsf"; |
| 443 template <> const char *InstX8632Bsr::Opcode = "bsr"; | 445 template <> const char *InstX8632Bsr::Opcode = "bsr"; |
| 446 template <> const char *InstX8632Lea::Opcode = "lea"; |
| 447 template <> const char *InstX8632Movd::Opcode = "movd"; |
| 448 template <> const char *InstX8632Movss::Opcode = "movss"; |
| 444 template <> const char *InstX8632Sqrtss::Opcode = "sqrtss"; | 449 template <> const char *InstX8632Sqrtss::Opcode = "sqrtss"; |
| 450 // Binary ops |
| 445 template <> const char *InstX8632Add::Opcode = "add"; | 451 template <> const char *InstX8632Add::Opcode = "add"; |
| 446 template <> const char *InstX8632Addps::Opcode = "addps"; | 452 template <> const char *InstX8632Addps::Opcode = "addps"; |
| 447 template <> const char *InstX8632Adc::Opcode = "adc"; | 453 template <> const char *InstX8632Adc::Opcode = "adc"; |
| 448 template <> const char *InstX8632Addss::Opcode = "addss"; | 454 template <> const char *InstX8632Addss::Opcode = "addss"; |
| 449 template <> const char *InstX8632Sub::Opcode = "sub"; | 455 template <> const char *InstX8632Sub::Opcode = "sub"; |
| 450 template <> const char *InstX8632Subps::Opcode = "subps"; | 456 template <> const char *InstX8632Subps::Opcode = "subps"; |
| 451 template <> const char *InstX8632Subss::Opcode = "subss"; | 457 template <> const char *InstX8632Subss::Opcode = "subss"; |
| 452 template <> const char *InstX8632Psub::Opcode = "psub"; | 458 template <> const char *InstX8632Psub::Opcode = "psub"; |
| 453 template <> const char *InstX8632Sbb::Opcode = "sbb"; | 459 template <> const char *InstX8632Sbb::Opcode = "sbb"; |
| 454 template <> const char *InstX8632And::Opcode = "and"; | 460 template <> const char *InstX8632And::Opcode = "and"; |
| 455 template <> const char *InstX8632Pand::Opcode = "pand"; | 461 template <> const char *InstX8632Pand::Opcode = "pand"; |
| 456 template <> const char *InstX8632Or::Opcode = "or"; | 462 template <> const char *InstX8632Or::Opcode = "or"; |
| 457 template <> const char *InstX8632Xor::Opcode = "xor"; | 463 template <> const char *InstX8632Xor::Opcode = "xor"; |
| 458 template <> const char *InstX8632Pxor::Opcode = "pxor"; | 464 template <> const char *InstX8632Pxor::Opcode = "pxor"; |
| 459 template <> const char *InstX8632Imul::Opcode = "imul"; | 465 template <> const char *InstX8632Imul::Opcode = "imul"; |
| 460 template <> const char *InstX8632Mulps::Opcode = "mulps"; | 466 template <> const char *InstX8632Mulps::Opcode = "mulps"; |
| 461 template <> const char *InstX8632Mulss::Opcode = "mulss"; | 467 template <> const char *InstX8632Mulss::Opcode = "mulss"; |
| 462 template <> const char *InstX8632Div::Opcode = "div"; | 468 template <> const char *InstX8632Div::Opcode = "div"; |
| 463 template <> const char *InstX8632Divps::Opcode = "divps"; | 469 template <> const char *InstX8632Divps::Opcode = "divps"; |
| 464 template <> const char *InstX8632Idiv::Opcode = "idiv"; | 470 template <> const char *InstX8632Idiv::Opcode = "idiv"; |
| 465 template <> const char *InstX8632Divss::Opcode = "divss"; | 471 template <> const char *InstX8632Divss::Opcode = "divss"; |
| 466 template <> const char *InstX8632Shl::Opcode = "shl"; | 472 template <> const char *InstX8632Shl::Opcode = "shl"; |
| 467 template <> const char *InstX8632Psll::Opcode = "psll"; | 473 template <> const char *InstX8632Psll::Opcode = "psll"; |
| 468 template <> const char *InstX8632Shr::Opcode = "shr"; | 474 template <> const char *InstX8632Shr::Opcode = "shr"; |
| 469 template <> const char *InstX8632Sar::Opcode = "sar"; | 475 template <> const char *InstX8632Sar::Opcode = "sar"; |
| 470 template <> const char *InstX8632Psra::Opcode = "psra"; | 476 template <> const char *InstX8632Psra::Opcode = "psra"; |
| 471 template <> const char *InstX8632Pcmpeq::Opcode = "pcmpeq"; | 477 template <> const char *InstX8632Pcmpeq::Opcode = "pcmpeq"; |
| 472 template <> const char *InstX8632Pcmpgt::Opcode = "pcmpgt"; | 478 template <> const char *InstX8632Pcmpgt::Opcode = "pcmpgt"; |
| 479 // Ternary ops |
| 480 template <> const char *InstX8632Shufps::Opcode = "shufps"; |
| 481 template <> const char *InstX8632Pinsrw::Opcode = "pinsrw"; |
| 482 // Three address ops |
| 483 template <> const char *InstX8632Pextrw::Opcode = "pextrw"; |
| 484 template <> const char *InstX8632Pshufd::Opcode = "pshufd"; |
| 473 | 485 |
| 474 template <> void InstX8632Sqrtss::emit(const Cfg *Func) const { | 486 template <> void InstX8632Sqrtss::emit(const Cfg *Func) const { |
| 475 Ostream &Str = Func->getContext()->getStrEmit(); | 487 Ostream &Str = Func->getContext()->getStrEmit(); |
| 476 assert(getSrcSize() == 1); | 488 assert(getSrcSize() == 1); |
| 477 Type Ty = getSrc(0)->getType(); | 489 Type Ty = getSrc(0)->getType(); |
| 478 assert(Ty == IceType_f32 || Ty == IceType_f64); | 490 assert(Ty == IceType_f32 || Ty == IceType_f64); |
| 479 Str << "\tsqrt" << TypeX8632Attributes[Ty].SdSsString << "\t"; | 491 Str << "\tsqrt" << TypeX8632Attributes[Ty].SdSsString << "\t"; |
| 480 getDest()->emit(Func); | 492 getDest()->emit(Func); |
| 481 Str << ", "; | 493 Str << ", "; |
| 482 getSrc(0)->emit(Func); | 494 getSrc(0)->emit(Func); |
| (...skipping 21 matching lines...) Expand all Loading... |
| 504 emitTwoAddress(buf, this, Func); | 516 emitTwoAddress(buf, this, Func); |
| 505 } | 517 } |
| 506 | 518 |
| 507 template <> void InstX8632Divss::emit(const Cfg *Func) const { | 519 template <> void InstX8632Divss::emit(const Cfg *Func) const { |
| 508 char buf[30]; | 520 char buf[30]; |
| 509 snprintf(buf, llvm::array_lengthof(buf), "div%s", | 521 snprintf(buf, llvm::array_lengthof(buf), "div%s", |
| 510 TypeX8632Attributes[getDest()->getType()].SdSsString); | 522 TypeX8632Attributes[getDest()->getType()].SdSsString); |
| 511 emitTwoAddress(buf, this, Func); | 523 emitTwoAddress(buf, this, Func); |
| 512 } | 524 } |
| 513 | 525 |
| 526 template <> void InstX8632Div::emit(const Cfg *Func) const { |
| 527 Ostream &Str = Func->getContext()->getStrEmit(); |
| 528 assert(getSrcSize() == 3); |
| 529 Str << "\t" << Opcode << "\t"; |
| 530 getSrc(1)->emit(Func); |
| 531 Str << "\n"; |
| 532 } |
| 533 |
| 534 template <> void InstX8632Idiv::emit(const Cfg *Func) const { |
| 535 Ostream &Str = Func->getContext()->getStrEmit(); |
| 536 assert(getSrcSize() == 3); |
| 537 Str << "\t" << Opcode << "\t"; |
| 538 getSrc(1)->emit(Func); |
| 539 Str << "\n"; |
| 540 } |
| 541 |
| 514 template <> void InstX8632Imul::emit(const Cfg *Func) const { | 542 template <> void InstX8632Imul::emit(const Cfg *Func) const { |
| 515 Ostream &Str = Func->getContext()->getStrEmit(); | 543 Ostream &Str = Func->getContext()->getStrEmit(); |
| 516 assert(getSrcSize() == 2); | 544 assert(getSrcSize() == 2); |
| 517 if (getDest()->getType() == IceType_i8) { | 545 if (getDest()->getType() == IceType_i8) { |
| 518 // The 8-bit version of imul only allows the form "imul r/m8". | 546 // The 8-bit version of imul only allows the form "imul r/m8". |
| 519 Variable *Src0 = llvm::dyn_cast<Variable>(getSrc(0)); | 547 Variable *Src0 = llvm::dyn_cast<Variable>(getSrc(0)); |
| 520 assert(Src0 && Src0->getRegNum() == TargetX8632::Reg_eax); | 548 assert(Src0 && Src0->getRegNum() == TargetX8632::Reg_eax); |
| 521 Str << "\timul\t"; | 549 Str << "\timul\t"; |
| 522 getSrc(1)->emit(Func); | 550 getSrc(1)->emit(Func); |
| 523 Str << "\n"; | 551 Str << "\n"; |
| (...skipping 292 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 816 } | 844 } |
| 817 | 845 |
| 818 void InstX8632StoreQ::dump(const Cfg *Func) const { | 846 void InstX8632StoreQ::dump(const Cfg *Func) const { |
| 819 Ostream &Str = Func->getContext()->getStrDump(); | 847 Ostream &Str = Func->getContext()->getStrDump(); |
| 820 Str << "storeq." << getSrc(0)->getType() << " "; | 848 Str << "storeq." << getSrc(0)->getType() << " "; |
| 821 getSrc(1)->dump(Func); | 849 getSrc(1)->dump(Func); |
| 822 Str << ", "; | 850 Str << ", "; |
| 823 getSrc(0)->dump(Func); | 851 getSrc(0)->dump(Func); |
| 824 } | 852 } |
| 825 | 853 |
| 854 template <> void InstX8632Lea::emit(const Cfg *Func) const { |
| 855 Ostream &Str = Func->getContext()->getStrEmit(); |
| 856 assert(getSrcSize() == 1); |
| 857 assert(getDest()->hasReg()); |
| 858 Str << "\tlea\t"; |
| 859 getDest()->emit(Func); |
| 860 Str << ", "; |
| 861 Operand *Src0 = getSrc(0); |
| 862 if (Variable *VSrc0 = llvm::dyn_cast<Variable>(Src0)) { |
| 863 Type Ty = VSrc0->getType(); |
| 864 // lea on x86-32 doesn't accept mem128 operands, so cast VSrc0 to an |
| 865 // acceptable type. |
| 866 VSrc0->asType(isVectorType(Ty) ? IceType_i32 : Ty).emit(Func); |
| 867 } else { |
| 868 Src0->emit(Func); |
| 869 } |
| 870 Str << "\n"; |
| 871 } |
| 872 |
| 826 void InstX8632Mov::emit(const Cfg *Func) const { | 873 void InstX8632Mov::emit(const Cfg *Func) const { |
| 827 Ostream &Str = Func->getContext()->getStrEmit(); | 874 Ostream &Str = Func->getContext()->getStrEmit(); |
| 828 assert(getSrcSize() == 1); | 875 assert(getSrcSize() == 1); |
| 829 Operand *Src = getSrc(0); | 876 Operand *Src = getSrc(0); |
| 830 // The llvm-mc assembler using Intel syntax has a bug in which "mov | 877 // The llvm-mc assembler using Intel syntax has a bug in which "mov |
| 831 // reg, RelocatableConstant" does not generate the right instruction | 878 // reg, RelocatableConstant" does not generate the right instruction |
| 832 // with a relocation. To work around, we emit "lea reg, | 879 // with a relocation. To work around, we emit "lea reg, |
| 833 // [RelocatableConstant]". Also, the lowering and legalization is | 880 // [RelocatableConstant]". Also, the lowering and legalization is |
| 834 // changed to allow relocatable constants only in Assign and Call | 881 // changed to allow relocatable constants only in Assign and Call |
| 835 // instructions or in Mem operands. TODO(stichnot): remove LEAHACK | 882 // instructions or in Mem operands. TODO(stichnot): remove LEAHACK |
| (...skipping 178 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1014 emitTwoAddress(buf, this, Func); | 1061 emitTwoAddress(buf, this, Func); |
| 1015 } | 1062 } |
| 1016 | 1063 |
| 1017 template <> void InstX8632Pcmpgt::emit(const Cfg *Func) const { | 1064 template <> void InstX8632Pcmpgt::emit(const Cfg *Func) const { |
| 1018 char buf[30]; | 1065 char buf[30]; |
| 1019 snprintf(buf, llvm::array_lengthof(buf), "pcmpgt%s", | 1066 snprintf(buf, llvm::array_lengthof(buf), "pcmpgt%s", |
| 1020 TypeX8632Attributes[getDest()->getType()].PackString); | 1067 TypeX8632Attributes[getDest()->getType()].PackString); |
| 1021 emitTwoAddress(buf, this, Func); | 1068 emitTwoAddress(buf, this, Func); |
| 1022 } | 1069 } |
| 1023 | 1070 |
| 1071 template <> void InstX8632Pextrw::emit(const Cfg *Func) const { |
| 1072 Ostream &Str = Func->getContext()->getStrEmit(); |
| 1073 assert(getSrcSize() == 2); |
| 1074 Str << "\t" << Opcode << "\t"; |
| 1075 Variable *Dest = getDest(); |
| 1076 assert(Dest->hasReg() && Dest->getType() == IceType_i16); |
| 1077 // pextrw takes r32 dest. |
| 1078 Dest->asType(IceType_i32).emit(Func); |
| 1079 Str << ", "; |
| 1080 getSrc(0)->emit(Func); |
| 1081 Str << ", "; |
| 1082 getSrc(1)->emit(Func); |
| 1083 Str << "\n"; |
| 1084 } |
| 1085 |
| 1086 template <> void InstX8632Pinsrw::emit(const Cfg *Func) const { |
| 1087 Ostream &Str = Func->getContext()->getStrEmit(); |
| 1088 assert(getSrcSize() == 3); |
| 1089 Str << "\t" << Opcode << "\t"; |
| 1090 getDest()->emit(Func); |
| 1091 Str << ", "; |
| 1092 Operand *Src1 = getSrc(1); |
| 1093 if (Variable *VSrc1 = llvm::dyn_cast<Variable>(Src1)) { |
| 1094 // If src1 is a register, it should be r32. |
| 1095 VSrc1->asType(VSrc1->hasReg() ? IceType_i32 : IceType_i16).emit(Func); |
| 1096 } else { |
| 1097 Src1->emit(Func); |
| 1098 } |
| 1099 Str << ", "; |
| 1100 getSrc(2)->emit(Func); |
| 1101 Str << "\n"; |
| 1102 } |
| 1103 |
| 1024 void InstX8632Pop::emit(const Cfg *Func) const { | 1104 void InstX8632Pop::emit(const Cfg *Func) const { |
| 1025 Ostream &Str = Func->getContext()->getStrEmit(); | 1105 Ostream &Str = Func->getContext()->getStrEmit(); |
| 1026 assert(getSrcSize() == 0); | 1106 assert(getSrcSize() == 0); |
| 1027 Str << "\tpop\t"; | 1107 Str << "\tpop\t"; |
| 1028 getDest()->emit(Func); | 1108 getDest()->emit(Func); |
| 1029 Str << "\n"; | 1109 Str << "\n"; |
| 1030 } | 1110 } |
| 1031 | 1111 |
| 1032 void InstX8632Pop::dump(const Cfg *Func) const { | 1112 void InstX8632Pop::dump(const Cfg *Func) const { |
| 1033 Ostream &Str = Func->getContext()->getStrDump(); | 1113 Ostream &Str = Func->getContext()->getStrDump(); |
| (...skipping 242 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1276 default: | 1356 default: |
| 1277 Str << "???"; | 1357 Str << "???"; |
| 1278 break; | 1358 break; |
| 1279 } | 1359 } |
| 1280 Str << "("; | 1360 Str << "("; |
| 1281 Var->dump(Func); | 1361 Var->dump(Func); |
| 1282 Str << ")"; | 1362 Str << ")"; |
| 1283 } | 1363 } |
| 1284 | 1364 |
| 1285 } // end of namespace Ice | 1365 } // end of namespace Ice |
| OLD | NEW |