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 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 45 { emit } \ | 45 { emit } \ |
| 46 , | 46 , |
| 47 ICEINSTX8632CMPPS_TABLE | 47 ICEINSTX8632CMPPS_TABLE |
| 48 #undef X | 48 #undef X |
| 49 }; | 49 }; |
| 50 | 50 |
| 51 const struct TypeX8632Attributes_ { | 51 const struct TypeX8632Attributes_ { |
| 52 const char *CvtString; // i (integer), s (single FP), d (double FP) | 52 const char *CvtString; // i (integer), s (single FP), d (double FP) |
| 53 const char *SdSsString; // ss, sd, or <blank> | 53 const char *SdSsString; // ss, sd, or <blank> |
| 54 const char *PackString; // b, w, d, or <blank> | 54 const char *PackString; // b, w, d, or <blank> |
| 55 const char *WidthString; // {byte,word,dword,qword} ptr | 55 const char *WidthString; // b, w, l, q, or <blank> |
| 56 const char *FldString; // s, l, or <blank> | |
| 56 } TypeX8632Attributes[] = { | 57 } TypeX8632Attributes[] = { |
| 57 #define X(tag, elementty, cvt, sdss, pack, width) \ | 58 #define X(tag, elementty, cvt, sdss, pack, width, fld) \ |
| 58 { cvt, "" sdss, pack, width } \ | 59 { cvt, sdss, pack, width, fld } \ |
| 59 , | 60 , |
| 60 ICETYPEX8632_TABLE | 61 ICETYPEX8632_TABLE |
| 61 #undef X | 62 #undef X |
| 62 }; | 63 }; |
| 63 | 64 |
| 64 const char *InstX8632SegmentRegNames[] = { | 65 const char *InstX8632SegmentRegNames[] = { |
| 65 #define X(val, name, prefix) name, | 66 #define X(val, name, prefix) name, |
| 66 SEG_REGX8632_TABLE | 67 SEG_REGX8632_TABLE |
| 67 #undef X | 68 #undef X |
| 68 }; | 69 }; |
| 69 | 70 |
| 70 uint8_t InstX8632SegmentPrefixes[] = { | 71 uint8_t InstX8632SegmentPrefixes[] = { |
| 71 #define X(val, name, prefix) prefix, | 72 #define X(val, name, prefix) prefix, |
| 72 SEG_REGX8632_TABLE | 73 SEG_REGX8632_TABLE |
| 73 #undef X | 74 #undef X |
| 74 }; | 75 }; |
| 75 | 76 |
| 76 } // end of anonymous namespace | 77 } // end of anonymous namespace |
| 77 | 78 |
| 78 const char *InstX8632::getWidthString(Type Ty) { | 79 const char *InstX8632::getWidthString(Type Ty) { |
| 79 return TypeX8632Attributes[Ty].WidthString; | 80 return TypeX8632Attributes[Ty].WidthString; |
| 80 } | 81 } |
| 81 | 82 |
| 83 const char *InstX8632::getFldString(Type Ty) { | |
| 84 return TypeX8632Attributes[Ty].FldString; | |
| 85 } | |
| 86 | |
| 82 OperandX8632Mem::OperandX8632Mem(Cfg *Func, Type Ty, Variable *Base, | 87 OperandX8632Mem::OperandX8632Mem(Cfg *Func, Type Ty, Variable *Base, |
| 83 Constant *Offset, Variable *Index, | 88 Constant *Offset, Variable *Index, |
| 84 uint16_t Shift, SegmentRegisters SegmentReg) | 89 uint16_t Shift, SegmentRegisters SegmentReg) |
| 85 : OperandX8632(kMem, Ty), Base(Base), Offset(Offset), Index(Index), | 90 : OperandX8632(kMem, Ty), Base(Base), Offset(Offset), Index(Index), |
| 86 Shift(Shift), SegmentReg(SegmentReg) { | 91 Shift(Shift), SegmentReg(SegmentReg) { |
| 87 assert(Shift <= 3); | 92 assert(Shift <= 3); |
| 88 Vars = NULL; | 93 Vars = NULL; |
| 89 NumVars = 0; | 94 NumVars = 0; |
| 90 if (Base) | 95 if (Base) |
| 91 ++NumVars; | 96 ++NumVars; |
| (...skipping 339 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 431 // fixups are used (and text assembler is not used). | 436 // fixups are used (and text assembler is not used). |
| 432 Ostream &Str = Func->getContext()->getStrEmit(); | 437 Ostream &Str = Func->getContext()->getStrEmit(); |
| 433 Str << getName(Func) << ":\n"; | 438 Str << getName(Func) << ":\n"; |
| 434 } | 439 } |
| 435 | 440 |
| 436 void InstX8632Label::dump(const Cfg *Func) const { | 441 void InstX8632Label::dump(const Cfg *Func) const { |
| 437 Ostream &Str = Func->getContext()->getStrDump(); | 442 Ostream &Str = Func->getContext()->getStrDump(); |
| 438 Str << getName(Func) << ":"; | 443 Str << getName(Func) << ":"; |
| 439 } | 444 } |
| 440 | 445 |
| 441 void InstX8632Br::emit(const Cfg *Func) const { | 446 void InstX8632Br::emit(const Cfg *Func) const { |
|
Jim Stichnoth
2014/10/31 20:55:19
No change in branch syntax for AT&T.
| |
| 442 Ostream &Str = Func->getContext()->getStrEmit(); | 447 Ostream &Str = Func->getContext()->getStrEmit(); |
| 443 Str << "\t"; | 448 Str << "\t"; |
| 444 | 449 |
| 445 if (Condition == CondX86::Br_None) { | 450 if (Condition == CondX86::Br_None) { |
| 446 Str << "jmp"; | 451 Str << "jmp"; |
| 447 } else { | 452 } else { |
| 448 Str << InstX8632BrAttributes[Condition].EmitString; | 453 Str << InstX8632BrAttributes[Condition].EmitString; |
| 449 } | 454 } |
| 450 | 455 |
| 451 if (Label) { | 456 if (Label) { |
| (...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 521 if (getTargetFalse()) { | 526 if (getTargetFalse()) { |
| 522 Str << ", label %" << getTargetFalse()->getName(); | 527 Str << ", label %" << getTargetFalse()->getName(); |
| 523 } | 528 } |
| 524 } | 529 } |
| 525 } | 530 } |
| 526 | 531 |
| 527 void InstX8632Call::emit(const Cfg *Func) const { | 532 void InstX8632Call::emit(const Cfg *Func) const { |
| 528 Ostream &Str = Func->getContext()->getStrEmit(); | 533 Ostream &Str = Func->getContext()->getStrEmit(); |
| 529 assert(getSrcSize() == 1); | 534 assert(getSrcSize() == 1); |
| 530 Str << "\tcall\t"; | 535 Str << "\tcall\t"; |
| 531 getCallTarget()->emit(Func); | 536 if (auto CallTarget = llvm::dyn_cast<ConstantRelocatable>(getCallTarget())) { |
| 537 // TODO(stichnot): All constant targets should suppress the '$', | |
| 538 // not just relocatables. | |
| 539 CallTarget->emitWithoutDollar(Func->getContext()); | |
| 540 } else { | |
| 541 Str << "*"; | |
| 542 getCallTarget()->emit(Func); | |
| 543 } | |
| 532 Func->getTarget()->resetStackAdjustment(); | 544 Func->getTarget()->resetStackAdjustment(); |
| 533 } | 545 } |
| 534 | 546 |
| 535 void InstX8632Call::emitIAS(const Cfg *Func) const { | 547 void InstX8632Call::emitIAS(const Cfg *Func) const { |
| 536 x86::AssemblerX86 *Asm = Func->getAssembler<x86::AssemblerX86>(); | 548 x86::AssemblerX86 *Asm = Func->getAssembler<x86::AssemblerX86>(); |
| 537 intptr_t StartPosition = Asm->GetPosition(); | 549 intptr_t StartPosition = Asm->GetPosition(); |
| 538 Operand *Target = getCallTarget(); | 550 Operand *Target = getCallTarget(); |
| 539 bool NeedsFallback = false; | 551 bool NeedsFallback = false; |
| 540 if (const auto Var = llvm::dyn_cast<Variable>(Target)) { | 552 if (const auto Var = llvm::dyn_cast<Variable>(Target)) { |
| 541 if (Var->hasReg()) { | 553 if (Var->hasReg()) { |
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 590 } | 602 } |
| 591 | 603 |
| 592 // The ShiftHack parameter is used to emit "cl" instead of "ecx" for | 604 // The ShiftHack parameter is used to emit "cl" instead of "ecx" for |
| 593 // shift instructions, in order to be syntactically valid. The | 605 // shift instructions, in order to be syntactically valid. The |
| 594 // Opcode parameter needs to be char* and not IceString because of | 606 // Opcode parameter needs to be char* and not IceString because of |
| 595 // template issues. | 607 // template issues. |
| 596 void emitTwoAddress(const char *Opcode, const Inst *Inst, const Cfg *Func, | 608 void emitTwoAddress(const char *Opcode, const Inst *Inst, const Cfg *Func, |
| 597 bool ShiftHack) { | 609 bool ShiftHack) { |
| 598 Ostream &Str = Func->getContext()->getStrEmit(); | 610 Ostream &Str = Func->getContext()->getStrEmit(); |
| 599 assert(Inst->getSrcSize() == 2); | 611 assert(Inst->getSrcSize() == 2); |
| 600 assert(Inst->getDest() == Inst->getSrc(0)); | 612 Variable *Dest = Inst->getDest(); |
| 601 Str << "\t" << Opcode << "\t"; | 613 assert(Dest == Inst->getSrc(0)); |
| 602 Inst->getDest()->emit(Func); | 614 Operand *Src1 = Inst->getSrc(1); |
| 615 Str << "\t" << Opcode << InstX8632::getWidthString(Dest->getType()) << "\t"; | |
| 616 Variable *ShiftReg = llvm::dyn_cast<Variable>(Src1); | |
| 617 if (ShiftHack && ShiftReg && ShiftReg->getRegNum() == RegX8632::Reg_ecx) | |
| 618 Str << "%cl"; | |
| 619 else | |
| 620 Src1->emit(Func); | |
| 603 Str << ", "; | 621 Str << ", "; |
| 604 bool EmittedSrc1 = false; | 622 Dest->emit(Func); |
| 605 if (ShiftHack) { | |
| 606 Variable *ShiftReg = llvm::dyn_cast<Variable>(Inst->getSrc(1)); | |
| 607 if (ShiftReg && ShiftReg->getRegNum() == RegX8632::Reg_ecx) { | |
| 608 Str << "cl"; | |
| 609 EmittedSrc1 = true; | |
| 610 } | |
| 611 } | |
| 612 if (!EmittedSrc1) | |
| 613 Inst->getSrc(1)->emit(Func); | |
| 614 } | 623 } |
| 615 | 624 |
| 616 void emitIASOpTyGPR(const Cfg *Func, Type Ty, const Operand *Op, | 625 void emitIASOpTyGPR(const Cfg *Func, Type Ty, const Operand *Op, |
| 617 const x86::AssemblerX86::GPREmitterOneOp &Emitter) { | 626 const x86::AssemblerX86::GPREmitterOneOp &Emitter) { |
| 618 x86::AssemblerX86 *Asm = Func->getAssembler<x86::AssemblerX86>(); | 627 x86::AssemblerX86 *Asm = Func->getAssembler<x86::AssemblerX86>(); |
| 619 intptr_t StartPosition = Asm->GetPosition(); | 628 intptr_t StartPosition = Asm->GetPosition(); |
| 620 if (const auto Var = llvm::dyn_cast<Variable>(Op)) { | 629 if (const auto Var = llvm::dyn_cast<Variable>(Op)) { |
| 621 if (Var->hasReg()) { | 630 if (Var->hasReg()) { |
| 622 // We cheat a little and use GPRRegister even for byte operations. | 631 // We cheat a little and use GPRRegister even for byte operations. |
| 623 RegX8632::GPRRegister VarReg = | 632 RegX8632::GPRRegister VarReg = |
| (...skipping 311 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 935 } | 944 } |
| 936 | 945 |
| 937 // In-place ops | 946 // In-place ops |
| 938 template <> const char *InstX8632Bswap::Opcode = "bswap"; | 947 template <> const char *InstX8632Bswap::Opcode = "bswap"; |
| 939 template <> const char *InstX8632Neg::Opcode = "neg"; | 948 template <> const char *InstX8632Neg::Opcode = "neg"; |
| 940 // Unary ops | 949 // Unary ops |
| 941 template <> const char *InstX8632Bsf::Opcode = "bsf"; | 950 template <> const char *InstX8632Bsf::Opcode = "bsf"; |
| 942 template <> const char *InstX8632Bsr::Opcode = "bsr"; | 951 template <> const char *InstX8632Bsr::Opcode = "bsr"; |
| 943 template <> const char *InstX8632Lea::Opcode = "lea"; | 952 template <> const char *InstX8632Lea::Opcode = "lea"; |
| 944 template <> const char *InstX8632Movd::Opcode = "movd"; | 953 template <> const char *InstX8632Movd::Opcode = "movd"; |
| 945 template <> const char *InstX8632Movsx::Opcode = "movsx"; | 954 template <> const char *InstX8632Movsx::Opcode = "movs"; |
| 946 template <> const char *InstX8632Movzx::Opcode = "movzx"; | 955 template <> const char *InstX8632Movzx::Opcode = "movz"; |
| 947 template <> const char *InstX8632Sqrtss::Opcode = "sqrtss"; | 956 template <> const char *InstX8632Sqrtss::Opcode = "sqrtss"; |
| 948 template <> const char *InstX8632Cbwdq::Opcode = "cbw/cwd/cdq"; | 957 template <> const char *InstX8632Cbwdq::Opcode = "cbw/cwd/cdq"; |
| 949 // Mov-like ops | 958 // Mov-like ops |
| 950 template <> const char *InstX8632Mov::Opcode = "mov"; | 959 template <> const char *InstX8632Mov::Opcode = "mov"; |
| 951 template <> const char *InstX8632Movp::Opcode = "movups"; | 960 template <> const char *InstX8632Movp::Opcode = "movups"; |
| 952 template <> const char *InstX8632Movq::Opcode = "movq"; | 961 template <> const char *InstX8632Movq::Opcode = "movq"; |
| 953 // Binary ops | 962 // Binary ops |
| 954 template <> const char *InstX8632Add::Opcode = "add"; | 963 template <> const char *InstX8632Add::Opcode = "add"; |
| 955 template <> const char *InstX8632Addps::Opcode = "addps"; | 964 template <> const char *InstX8632Addps::Opcode = "addps"; |
| 956 template <> const char *InstX8632Adc::Opcode = "adc"; | 965 template <> const char *InstX8632Adc::Opcode = "adc"; |
| (...skipping 190 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1147 const x86::AssemblerX86::XmmEmitterShiftOp InstX8632Psra::Emitter = { | 1156 const x86::AssemblerX86::XmmEmitterShiftOp InstX8632Psra::Emitter = { |
| 1148 &x86::AssemblerX86::psra, &x86::AssemblerX86::psra, | 1157 &x86::AssemblerX86::psra, &x86::AssemblerX86::psra, |
| 1149 &x86::AssemblerX86::psra}; | 1158 &x86::AssemblerX86::psra}; |
| 1150 | 1159 |
| 1151 template <> void InstX8632Sqrtss::emit(const Cfg *Func) const { | 1160 template <> void InstX8632Sqrtss::emit(const Cfg *Func) const { |
| 1152 Ostream &Str = Func->getContext()->getStrEmit(); | 1161 Ostream &Str = Func->getContext()->getStrEmit(); |
| 1153 assert(getSrcSize() == 1); | 1162 assert(getSrcSize() == 1); |
| 1154 Type Ty = getSrc(0)->getType(); | 1163 Type Ty = getSrc(0)->getType(); |
| 1155 assert(isScalarFloatingType(Ty)); | 1164 assert(isScalarFloatingType(Ty)); |
| 1156 Str << "\tsqrt" << TypeX8632Attributes[Ty].SdSsString << "\t"; | 1165 Str << "\tsqrt" << TypeX8632Attributes[Ty].SdSsString << "\t"; |
| 1166 getSrc(0)->emit(Func); | |
| 1167 Str << ", "; | |
| 1157 getDest()->emit(Func); | 1168 getDest()->emit(Func); |
| 1158 Str << ", "; | |
| 1159 getSrc(0)->emit(Func); | |
| 1160 } | 1169 } |
| 1161 | 1170 |
| 1162 template <> void InstX8632Addss::emit(const Cfg *Func) const { | 1171 template <> void InstX8632Addss::emit(const Cfg *Func) const { |
| 1163 char buf[30]; | 1172 char buf[30]; |
| 1164 snprintf(buf, llvm::array_lengthof(buf), "add%s", | 1173 snprintf(buf, llvm::array_lengthof(buf), "add%s", |
| 1165 TypeX8632Attributes[getDest()->getType()].SdSsString); | 1174 TypeX8632Attributes[getDest()->getType()].SdSsString); |
| 1166 emitTwoAddress(buf, this, Func); | 1175 emitTwoAddress(buf, this, Func); |
| 1167 } | 1176 } |
| 1168 | 1177 |
| 1169 template <> void InstX8632Padd::emit(const Cfg *Func) const { | 1178 template <> void InstX8632Padd::emit(const Cfg *Func) const { |
| (...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1236 template <> void InstX8632Divss::emit(const Cfg *Func) const { | 1245 template <> void InstX8632Divss::emit(const Cfg *Func) const { |
| 1237 char buf[30]; | 1246 char buf[30]; |
| 1238 snprintf(buf, llvm::array_lengthof(buf), "div%s", | 1247 snprintf(buf, llvm::array_lengthof(buf), "div%s", |
| 1239 TypeX8632Attributes[getDest()->getType()].SdSsString); | 1248 TypeX8632Attributes[getDest()->getType()].SdSsString); |
| 1240 emitTwoAddress(buf, this, Func); | 1249 emitTwoAddress(buf, this, Func); |
| 1241 } | 1250 } |
| 1242 | 1251 |
| 1243 template <> void InstX8632Div::emit(const Cfg *Func) const { | 1252 template <> void InstX8632Div::emit(const Cfg *Func) const { |
| 1244 Ostream &Str = Func->getContext()->getStrEmit(); | 1253 Ostream &Str = Func->getContext()->getStrEmit(); |
| 1245 assert(getSrcSize() == 3); | 1254 assert(getSrcSize() == 3); |
| 1246 Str << "\t" << Opcode << "\t"; | 1255 Operand *Src1 = getSrc(1); |
| 1247 getSrc(1)->emit(Func); | 1256 Str << "\t" << Opcode << getWidthString(Src1->getType()) << "\t"; |
| 1257 Src1->emit(Func); | |
| 1248 } | 1258 } |
| 1249 | 1259 |
| 1250 template <> void InstX8632Div::emitIAS(const Cfg *Func) const { | 1260 template <> void InstX8632Div::emitIAS(const Cfg *Func) const { |
| 1251 assert(getSrcSize() == 3); | 1261 assert(getSrcSize() == 3); |
| 1252 const Operand *Src = getSrc(1); | 1262 const Operand *Src = getSrc(1); |
| 1253 Type Ty = Src->getType(); | 1263 Type Ty = Src->getType(); |
| 1254 const static x86::AssemblerX86::GPREmitterOneOp Emitter = { | 1264 const static x86::AssemblerX86::GPREmitterOneOp Emitter = { |
| 1255 &x86::AssemblerX86::div, &x86::AssemblerX86::div}; | 1265 &x86::AssemblerX86::div, &x86::AssemblerX86::div}; |
| 1256 emitIASOpTyGPR(Func, Ty, Src, Emitter); | 1266 emitIASOpTyGPR(Func, Ty, Src, Emitter); |
| 1257 } | 1267 } |
| 1258 | 1268 |
| 1259 template <> void InstX8632Idiv::emit(const Cfg *Func) const { | 1269 template <> void InstX8632Idiv::emit(const Cfg *Func) const { |
| 1260 Ostream &Str = Func->getContext()->getStrEmit(); | 1270 Ostream &Str = Func->getContext()->getStrEmit(); |
| 1261 assert(getSrcSize() == 3); | 1271 assert(getSrcSize() == 3); |
| 1262 Str << "\t" << Opcode << "\t"; | 1272 Operand *Src1 = getSrc(1); |
| 1263 getSrc(1)->emit(Func); | 1273 Str << "\t" << Opcode << getWidthString(Src1->getType()) << "\t"; |
| 1274 Src1->emit(Func); | |
| 1264 } | 1275 } |
| 1265 | 1276 |
| 1266 template <> void InstX8632Idiv::emitIAS(const Cfg *Func) const { | 1277 template <> void InstX8632Idiv::emitIAS(const Cfg *Func) const { |
| 1267 assert(getSrcSize() == 3); | 1278 assert(getSrcSize() == 3); |
| 1268 const Operand *Src = getSrc(1); | 1279 const Operand *Src = getSrc(1); |
| 1269 Type Ty = Src->getType(); | 1280 Type Ty = Src->getType(); |
| 1270 const static x86::AssemblerX86::GPREmitterOneOp Emitter = { | 1281 const static x86::AssemblerX86::GPREmitterOneOp Emitter = { |
| 1271 &x86::AssemblerX86::idiv, &x86::AssemblerX86::idiv}; | 1282 &x86::AssemblerX86::idiv, &x86::AssemblerX86::idiv}; |
| 1272 emitIASOpTyGPR(Func, Ty, Src, Emitter); | 1283 emitIASOpTyGPR(Func, Ty, Src, Emitter); |
| 1273 } | 1284 } |
| 1274 | 1285 |
| 1275 namespace { | 1286 namespace { |
| 1276 | 1287 |
| 1277 // pblendvb and blendvps take xmm0 as a final implicit argument. | 1288 // pblendvb and blendvps take xmm0 as a final implicit argument. |
| 1278 void emitVariableBlendInst(const char *Opcode, const Inst *Inst, | 1289 void emitVariableBlendInst(const char *Opcode, const Inst *Inst, |
| 1279 const Cfg *Func) { | 1290 const Cfg *Func) { |
| 1280 Ostream &Str = Func->getContext()->getStrEmit(); | 1291 Ostream &Str = Func->getContext()->getStrEmit(); |
| 1281 assert(Inst->getSrcSize() == 3); | 1292 assert(Inst->getSrcSize() == 3); |
| 1282 assert(llvm::cast<Variable>(Inst->getSrc(2))->getRegNum() == | 1293 assert(llvm::cast<Variable>(Inst->getSrc(2))->getRegNum() == |
| 1283 RegX8632::Reg_xmm0); | 1294 RegX8632::Reg_xmm0); |
| 1284 Str << "\t" << Opcode << "\t"; | 1295 Str << "\t" << Opcode << "\t"; |
| 1296 Inst->getSrc(1)->emit(Func); | |
| 1297 Str << ", "; | |
| 1285 Inst->getDest()->emit(Func); | 1298 Inst->getDest()->emit(Func); |
| 1286 Str << ", "; | |
| 1287 Inst->getSrc(1)->emit(Func); | |
| 1288 } | 1299 } |
| 1289 | 1300 |
| 1290 void | 1301 void |
| 1291 emitIASVariableBlendInst(const Inst *Inst, const Cfg *Func, | 1302 emitIASVariableBlendInst(const Inst *Inst, const Cfg *Func, |
| 1292 const x86::AssemblerX86::XmmEmitterRegOp &Emitter) { | 1303 const x86::AssemblerX86::XmmEmitterRegOp &Emitter) { |
| 1293 assert(Inst->getSrcSize() == 3); | 1304 assert(Inst->getSrcSize() == 3); |
| 1294 assert(llvm::cast<Variable>(Inst->getSrc(2))->getRegNum() == | 1305 assert(llvm::cast<Variable>(Inst->getSrc(2))->getRegNum() == |
| 1295 RegX8632::Reg_xmm0); | 1306 RegX8632::Reg_xmm0); |
| 1296 const Variable *Dest = Inst->getDest(); | 1307 const Variable *Dest = Inst->getDest(); |
| 1297 const Operand *Src = Inst->getSrc(1); | 1308 const Operand *Src = Inst->getSrc(1); |
| (...skipping 26 matching lines...) Expand all Loading... | |
| 1324 assert(static_cast<TargetX8632 *>(Func->getTarget())->getInstructionSet() >= | 1335 assert(static_cast<TargetX8632 *>(Func->getTarget())->getInstructionSet() >= |
| 1325 TargetX8632::SSE4_1); | 1336 TargetX8632::SSE4_1); |
| 1326 static const x86::AssemblerX86::XmmEmitterRegOp Emitter = { | 1337 static const x86::AssemblerX86::XmmEmitterRegOp Emitter = { |
| 1327 &x86::AssemblerX86::pblendvb, &x86::AssemblerX86::pblendvb}; | 1338 &x86::AssemblerX86::pblendvb, &x86::AssemblerX86::pblendvb}; |
| 1328 emitIASVariableBlendInst(this, Func, Emitter); | 1339 emitIASVariableBlendInst(this, Func, Emitter); |
| 1329 } | 1340 } |
| 1330 | 1341 |
| 1331 template <> void InstX8632Imul::emit(const Cfg *Func) const { | 1342 template <> void InstX8632Imul::emit(const Cfg *Func) const { |
| 1332 Ostream &Str = Func->getContext()->getStrEmit(); | 1343 Ostream &Str = Func->getContext()->getStrEmit(); |
| 1333 assert(getSrcSize() == 2); | 1344 assert(getSrcSize() == 2); |
| 1334 if (isByteSizedArithType(getDest()->getType())) { | 1345 Variable *Dest = getDest(); |
| 1346 if (isByteSizedArithType(Dest->getType())) { | |
| 1335 // The 8-bit version of imul only allows the form "imul r/m8". | 1347 // The 8-bit version of imul only allows the form "imul r/m8". |
| 1336 Variable *Src0 = llvm::dyn_cast<Variable>(getSrc(0)); | 1348 Variable *Src0 = llvm::dyn_cast<Variable>(getSrc(0)); |
| 1337 (void)Src0; | 1349 (void)Src0; |
| 1338 assert(Src0 && Src0->getRegNum() == RegX8632::Reg_eax); | 1350 assert(Src0 && Src0->getRegNum() == RegX8632::Reg_eax); |
| 1339 Str << "\timul\t"; | 1351 Str << "\timulb\t"; |
| 1340 getSrc(1)->emit(Func); | 1352 getSrc(1)->emit(Func); |
| 1341 } else if (llvm::isa<Constant>(getSrc(1))) { | 1353 } else if (llvm::isa<Constant>(getSrc(1))) { |
| 1342 Str << "\timul\t"; | 1354 Str << "\timul" << getWidthString(Dest->getType()) << "\t"; |
| 1343 getDest()->emit(Func); | 1355 getSrc(1)->emit(Func); |
| 1344 Str << ", "; | 1356 Str << ", "; |
| 1345 getSrc(0)->emit(Func); | 1357 getSrc(0)->emit(Func); |
| 1346 Str << ", "; | 1358 Str << ", "; |
| 1347 getSrc(1)->emit(Func); | 1359 Dest->emit(Func); |
| 1348 } else { | 1360 } else { |
| 1349 emitTwoAddress("imul", this, Func); | 1361 emitTwoAddress("imul", this, Func); |
| 1350 } | 1362 } |
| 1351 } | 1363 } |
| 1352 | 1364 |
| 1353 template <> void InstX8632Imul::emitIAS(const Cfg *Func) const { | 1365 template <> void InstX8632Imul::emitIAS(const Cfg *Func) const { |
| 1354 assert(getSrcSize() == 2); | 1366 assert(getSrcSize() == 2); |
| 1355 const Variable *Var = getDest(); | 1367 const Variable *Var = getDest(); |
| 1356 Type Ty = Var->getType(); | 1368 Type Ty = Var->getType(); |
| 1357 const Operand *Src = getSrc(1); | 1369 const Operand *Src = getSrc(1); |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1394 assert(getSrcSize() == 1); | 1406 assert(getSrcSize() == 1); |
| 1395 Operand *Src0 = getSrc(0); | 1407 Operand *Src0 = getSrc(0); |
| 1396 assert(llvm::isa<Variable>(Src0)); | 1408 assert(llvm::isa<Variable>(Src0)); |
| 1397 assert(llvm::cast<Variable>(Src0)->getRegNum() == RegX8632::Reg_eax); | 1409 assert(llvm::cast<Variable>(Src0)->getRegNum() == RegX8632::Reg_eax); |
| 1398 switch (Src0->getType()) { | 1410 switch (Src0->getType()) { |
| 1399 default: | 1411 default: |
| 1400 llvm_unreachable("unexpected source type!"); | 1412 llvm_unreachable("unexpected source type!"); |
| 1401 break; | 1413 break; |
| 1402 case IceType_i8: | 1414 case IceType_i8: |
| 1403 assert(getDest()->getRegNum() == RegX8632::Reg_eax); | 1415 assert(getDest()->getRegNum() == RegX8632::Reg_eax); |
| 1404 Str << "\tcbw"; | 1416 Str << "\tcbtw"; |
| 1405 break; | 1417 break; |
| 1406 case IceType_i16: | 1418 case IceType_i16: |
| 1407 assert(getDest()->getRegNum() == RegX8632::Reg_edx); | 1419 assert(getDest()->getRegNum() == RegX8632::Reg_edx); |
| 1408 Str << "\tcwd"; | 1420 Str << "\tcwtd"; |
| 1409 break; | 1421 break; |
| 1410 case IceType_i32: | 1422 case IceType_i32: |
| 1411 assert(getDest()->getRegNum() == RegX8632::Reg_edx); | 1423 assert(getDest()->getRegNum() == RegX8632::Reg_edx); |
| 1412 Str << "\tcdq"; | 1424 Str << "\tcltd"; |
| 1413 break; | 1425 break; |
| 1414 } | 1426 } |
| 1415 } | 1427 } |
| 1416 | 1428 |
| 1417 template <> void InstX8632Cbwdq::emitIAS(const Cfg *Func) const { | 1429 template <> void InstX8632Cbwdq::emitIAS(const Cfg *Func) const { |
| 1418 x86::AssemblerX86 *Asm = Func->getAssembler<x86::AssemblerX86>(); | 1430 x86::AssemblerX86 *Asm = Func->getAssembler<x86::AssemblerX86>(); |
| 1419 intptr_t StartPosition = Asm->GetPosition(); | 1431 intptr_t StartPosition = Asm->GetPosition(); |
| 1420 assert(getSrcSize() == 1); | 1432 assert(getSrcSize() == 1); |
| 1421 Operand *Src0 = getSrc(0); | 1433 Operand *Src0 = getSrc(0); |
| 1422 assert(llvm::isa<Variable>(Src0)); | 1434 assert(llvm::isa<Variable>(Src0)); |
| (...skipping 17 matching lines...) Expand all Loading... | |
| 1440 } | 1452 } |
| 1441 emitIASBytes(Func, Asm, StartPosition); | 1453 emitIASBytes(Func, Asm, StartPosition); |
| 1442 } | 1454 } |
| 1443 | 1455 |
| 1444 void InstX8632Mul::emit(const Cfg *Func) const { | 1456 void InstX8632Mul::emit(const Cfg *Func) const { |
| 1445 Ostream &Str = Func->getContext()->getStrEmit(); | 1457 Ostream &Str = Func->getContext()->getStrEmit(); |
| 1446 assert(getSrcSize() == 2); | 1458 assert(getSrcSize() == 2); |
| 1447 assert(llvm::isa<Variable>(getSrc(0))); | 1459 assert(llvm::isa<Variable>(getSrc(0))); |
| 1448 assert(llvm::dyn_cast<Variable>(getSrc(0))->getRegNum() == RegX8632::Reg_eax); | 1460 assert(llvm::dyn_cast<Variable>(getSrc(0))->getRegNum() == RegX8632::Reg_eax); |
| 1449 assert(getDest()->getRegNum() == RegX8632::Reg_eax); // TODO: allow edx? | 1461 assert(getDest()->getRegNum() == RegX8632::Reg_eax); // TODO: allow edx? |
| 1450 Str << "\tmul\t"; | 1462 Str << "\tmul" << getWidthString(getDest()->getType()) << "\t"; |
| 1451 getSrc(1)->emit(Func); | 1463 getSrc(1)->emit(Func); |
| 1452 } | 1464 } |
| 1453 | 1465 |
| 1454 void InstX8632Mul::emitIAS(const Cfg *Func) const { | 1466 void InstX8632Mul::emitIAS(const Cfg *Func) const { |
| 1455 assert(getSrcSize() == 2); | 1467 assert(getSrcSize() == 2); |
| 1456 assert(llvm::isa<Variable>(getSrc(0))); | 1468 assert(llvm::isa<Variable>(getSrc(0))); |
| 1457 assert(llvm::dyn_cast<Variable>(getSrc(0))->getRegNum() == RegX8632::Reg_eax); | 1469 assert(llvm::dyn_cast<Variable>(getSrc(0))->getRegNum() == RegX8632::Reg_eax); |
| 1458 assert(getDest()->getRegNum() == RegX8632::Reg_eax); // TODO: allow edx? | 1470 assert(getDest()->getRegNum() == RegX8632::Reg_eax); // TODO: allow edx? |
| 1459 const Operand *Src = getSrc(1); | 1471 const Operand *Src = getSrc(1); |
| 1460 Type Ty = Src->getType(); | 1472 Type Ty = Src->getType(); |
| 1461 const static x86::AssemblerX86::GPREmitterOneOp Emitter = { | 1473 const static x86::AssemblerX86::GPREmitterOneOp Emitter = { |
| 1462 &x86::AssemblerX86::mul, &x86::AssemblerX86::mul}; | 1474 &x86::AssemblerX86::mul, &x86::AssemblerX86::mul}; |
| 1463 emitIASOpTyGPR(Func, Ty, Src, Emitter); | 1475 emitIASOpTyGPR(Func, Ty, Src, Emitter); |
| 1464 } | 1476 } |
| 1465 | 1477 |
| 1466 void InstX8632Mul::dump(const Cfg *Func) const { | 1478 void InstX8632Mul::dump(const Cfg *Func) const { |
| 1467 Ostream &Str = Func->getContext()->getStrDump(); | 1479 Ostream &Str = Func->getContext()->getStrDump(); |
| 1468 dumpDest(Func); | 1480 dumpDest(Func); |
| 1469 Str << " = mul." << getDest()->getType() << " "; | 1481 Str << " = mul." << getDest()->getType() << " "; |
| 1470 dumpSources(Func); | 1482 dumpSources(Func); |
| 1471 } | 1483 } |
| 1472 | 1484 |
| 1473 void InstX8632Shld::emit(const Cfg *Func) const { | 1485 void InstX8632Shld::emit(const Cfg *Func) const { |
| 1474 Ostream &Str = Func->getContext()->getStrEmit(); | 1486 Ostream &Str = Func->getContext()->getStrEmit(); |
| 1487 Variable *Dest = getDest(); | |
| 1475 assert(getSrcSize() == 3); | 1488 assert(getSrcSize() == 3); |
| 1476 assert(getDest() == getSrc(0)); | 1489 assert(Dest == getSrc(0)); |
| 1477 Str << "\tshld\t"; | 1490 Str << "\tshld" << getWidthString(Dest->getType()) << "\t"; |
| 1478 getDest()->emit(Func); | 1491 if (Variable *ShiftReg = llvm::dyn_cast<Variable>(getSrc(2))) { |
| 1492 (void)ShiftReg; | |
| 1493 assert(ShiftReg->getRegNum() == RegX8632::Reg_ecx); | |
| 1494 Str << "%cl"; | |
| 1495 } else { | |
| 1496 getSrc(2)->emit(Func); | |
| 1497 } | |
| 1479 Str << ", "; | 1498 Str << ", "; |
| 1480 getSrc(1)->emit(Func); | 1499 getSrc(1)->emit(Func); |
| 1481 Str << ", "; | 1500 Str << ", "; |
| 1482 if (Variable *ShiftReg = llvm::dyn_cast<Variable>(getSrc(2))) { | 1501 Dest->emit(Func); |
| 1483 (void)ShiftReg; | |
| 1484 assert(ShiftReg->getRegNum() == RegX8632::Reg_ecx); | |
| 1485 Str << "cl"; | |
| 1486 } else { | |
| 1487 getSrc(2)->emit(Func); | |
| 1488 } | |
| 1489 } | 1502 } |
| 1490 | 1503 |
| 1491 void InstX8632Shld::emitIAS(const Cfg *Func) const { | 1504 void InstX8632Shld::emitIAS(const Cfg *Func) const { |
| 1492 assert(getSrcSize() == 3); | 1505 assert(getSrcSize() == 3); |
| 1493 assert(getDest() == getSrc(0)); | 1506 assert(getDest() == getSrc(0)); |
| 1494 const Variable *Dest = getDest(); | 1507 const Variable *Dest = getDest(); |
| 1495 const Operand *Src1 = getSrc(1); | 1508 const Operand *Src1 = getSrc(1); |
| 1496 const Operand *Src2 = getSrc(2); | 1509 const Operand *Src2 = getSrc(2); |
| 1497 static const x86::AssemblerX86::GPREmitterShiftD Emitter = { | 1510 static const x86::AssemblerX86::GPREmitterShiftD Emitter = { |
| 1498 &x86::AssemblerX86::shld, &x86::AssemblerX86::shld}; | 1511 &x86::AssemblerX86::shld, &x86::AssemblerX86::shld}; |
| 1499 emitIASGPRShiftDouble(Func, Dest, Src1, Src2, Emitter); | 1512 emitIASGPRShiftDouble(Func, Dest, Src1, Src2, Emitter); |
| 1500 } | 1513 } |
| 1501 | 1514 |
| 1502 void InstX8632Shld::dump(const Cfg *Func) const { | 1515 void InstX8632Shld::dump(const Cfg *Func) const { |
| 1503 Ostream &Str = Func->getContext()->getStrDump(); | 1516 Ostream &Str = Func->getContext()->getStrDump(); |
| 1504 dumpDest(Func); | 1517 dumpDest(Func); |
| 1505 Str << " = shld." << getDest()->getType() << " "; | 1518 Str << " = shld." << getDest()->getType() << " "; |
| 1506 dumpSources(Func); | 1519 dumpSources(Func); |
| 1507 } | 1520 } |
| 1508 | 1521 |
| 1509 void InstX8632Shrd::emit(const Cfg *Func) const { | 1522 void InstX8632Shrd::emit(const Cfg *Func) const { |
| 1510 Ostream &Str = Func->getContext()->getStrEmit(); | 1523 Ostream &Str = Func->getContext()->getStrEmit(); |
| 1524 Variable *Dest = getDest(); | |
| 1511 assert(getSrcSize() == 3); | 1525 assert(getSrcSize() == 3); |
| 1512 assert(getDest() == getSrc(0)); | 1526 assert(Dest == getSrc(0)); |
| 1513 Str << "\tshrd\t"; | 1527 Str << "\tshrd" << getWidthString(Dest->getType()) << "\t"; |
| 1514 getDest()->emit(Func); | 1528 if (Variable *ShiftReg = llvm::dyn_cast<Variable>(getSrc(2))) { |
| 1529 (void)ShiftReg; | |
| 1530 assert(ShiftReg->getRegNum() == RegX8632::Reg_ecx); | |
| 1531 Str << "%cl"; | |
| 1532 } else { | |
| 1533 getSrc(2)->emit(Func); | |
| 1534 } | |
| 1515 Str << ", "; | 1535 Str << ", "; |
| 1516 getSrc(1)->emit(Func); | 1536 getSrc(1)->emit(Func); |
| 1517 Str << ", "; | 1537 Str << ", "; |
| 1518 if (Variable *ShiftReg = llvm::dyn_cast<Variable>(getSrc(2))) { | 1538 Dest->emit(Func); |
| 1519 (void)ShiftReg; | |
| 1520 assert(ShiftReg->getRegNum() == RegX8632::Reg_ecx); | |
| 1521 Str << "cl"; | |
| 1522 } else { | |
| 1523 getSrc(2)->emit(Func); | |
| 1524 } | |
| 1525 } | 1539 } |
| 1526 | 1540 |
| 1527 void InstX8632Shrd::emitIAS(const Cfg *Func) const { | 1541 void InstX8632Shrd::emitIAS(const Cfg *Func) const { |
| 1528 assert(getSrcSize() == 3); | 1542 assert(getSrcSize() == 3); |
| 1529 assert(getDest() == getSrc(0)); | 1543 assert(getDest() == getSrc(0)); |
| 1530 const Variable *Dest = getDest(); | 1544 const Variable *Dest = getDest(); |
| 1531 const Operand *Src1 = getSrc(1); | 1545 const Operand *Src1 = getSrc(1); |
| 1532 const Operand *Src2 = getSrc(2); | 1546 const Operand *Src2 = getSrc(2); |
| 1533 static const x86::AssemblerX86::GPREmitterShiftD Emitter = { | 1547 static const x86::AssemblerX86::GPREmitterShiftD Emitter = { |
| 1534 &x86::AssemblerX86::shrd, &x86::AssemblerX86::shrd}; | 1548 &x86::AssemblerX86::shrd, &x86::AssemblerX86::shrd}; |
| 1535 emitIASGPRShiftDouble(Func, Dest, Src1, Src2, Emitter); | 1549 emitIASGPRShiftDouble(Func, Dest, Src1, Src2, Emitter); |
| 1536 } | 1550 } |
| 1537 | 1551 |
| 1538 void InstX8632Shrd::dump(const Cfg *Func) const { | 1552 void InstX8632Shrd::dump(const Cfg *Func) const { |
| 1539 Ostream &Str = Func->getContext()->getStrDump(); | 1553 Ostream &Str = Func->getContext()->getStrDump(); |
| 1540 dumpDest(Func); | 1554 dumpDest(Func); |
| 1541 Str << " = shrd." << getDest()->getType() << " "; | 1555 Str << " = shrd." << getDest()->getType() << " "; |
| 1542 dumpSources(Func); | 1556 dumpSources(Func); |
| 1543 } | 1557 } |
| 1544 | 1558 |
| 1545 void InstX8632Cmov::emit(const Cfg *Func) const { | 1559 void InstX8632Cmov::emit(const Cfg *Func) const { |
| 1546 Ostream &Str = Func->getContext()->getStrEmit(); | 1560 Ostream &Str = Func->getContext()->getStrEmit(); |
| 1561 Variable *Dest = getDest(); | |
| 1547 Str << "\t"; | 1562 Str << "\t"; |
| 1548 assert(Condition != CondX86::Br_None); | 1563 assert(Condition != CondX86::Br_None); |
| 1549 assert(getDest()->hasReg()); | 1564 assert(getDest()->hasReg()); |
| 1550 Str << "cmov" << InstX8632BrAttributes[Condition].DisplayString << "\t"; | 1565 Str << "cmov" << InstX8632BrAttributes[Condition].DisplayString |
| 1551 getDest()->emit(Func); | 1566 << getWidthString(Dest->getType()) << "\t"; |
| 1567 getSrc(1)->emit(Func); | |
| 1552 Str << ", "; | 1568 Str << ", "; |
| 1553 getSrc(1)->emit(Func); | 1569 Dest->emit(Func); |
| 1554 } | 1570 } |
| 1555 | 1571 |
| 1556 void InstX8632Cmov::emitIAS(const Cfg *Func) const { | 1572 void InstX8632Cmov::emitIAS(const Cfg *Func) const { |
| 1557 assert(Condition != CondX86::Br_None); | 1573 assert(Condition != CondX86::Br_None); |
| 1558 assert(getDest()->hasReg()); | 1574 assert(getDest()->hasReg()); |
| 1559 assert(getSrcSize() == 2); | 1575 assert(getSrcSize() == 2); |
| 1560 // Only need the reg/reg form now. | 1576 // Only need the reg/reg form now. |
| 1561 const Variable *Src = llvm::cast<Variable>(getSrc(1)); | 1577 const Variable *Src = llvm::cast<Variable>(getSrc(1)); |
| 1562 assert(Src->hasReg()); | 1578 assert(Src->hasReg()); |
| 1563 assert(Src->getType() == IceType_i32); | 1579 assert(Src->getType() == IceType_i32); |
| (...skipping 13 matching lines...) Expand all Loading... | |
| 1577 dumpSources(Func); | 1593 dumpSources(Func); |
| 1578 } | 1594 } |
| 1579 | 1595 |
| 1580 void InstX8632Cmpps::emit(const Cfg *Func) const { | 1596 void InstX8632Cmpps::emit(const Cfg *Func) const { |
| 1581 Ostream &Str = Func->getContext()->getStrEmit(); | 1597 Ostream &Str = Func->getContext()->getStrEmit(); |
| 1582 assert(getSrcSize() == 2); | 1598 assert(getSrcSize() == 2); |
| 1583 assert(Condition < CondX86::Cmpps_Invalid); | 1599 assert(Condition < CondX86::Cmpps_Invalid); |
| 1584 Str << "\t"; | 1600 Str << "\t"; |
| 1585 Str << "cmp" << InstX8632CmppsAttributes[Condition].EmitString << "ps" | 1601 Str << "cmp" << InstX8632CmppsAttributes[Condition].EmitString << "ps" |
| 1586 << "\t"; | 1602 << "\t"; |
| 1603 getSrc(1)->emit(Func); | |
| 1604 Str << ", "; | |
| 1587 getDest()->emit(Func); | 1605 getDest()->emit(Func); |
| 1588 Str << ", "; | |
| 1589 getSrc(1)->emit(Func); | |
| 1590 } | 1606 } |
| 1591 | 1607 |
| 1592 void InstX8632Cmpps::emitIAS(const Cfg *Func) const { | 1608 void InstX8632Cmpps::emitIAS(const Cfg *Func) const { |
| 1593 x86::AssemblerX86 *Asm = Func->getAssembler<x86::AssemblerX86>(); | 1609 x86::AssemblerX86 *Asm = Func->getAssembler<x86::AssemblerX86>(); |
| 1594 intptr_t StartPosition = Asm->GetPosition(); | 1610 intptr_t StartPosition = Asm->GetPosition(); |
| 1595 assert(getSrcSize() == 2); | 1611 assert(getSrcSize() == 2); |
| 1596 assert(Condition < CondX86::Cmpps_Invalid); | 1612 assert(Condition < CondX86::Cmpps_Invalid); |
| 1597 // Assuming there isn't any load folding for cmpps, and vector constants | 1613 // Assuming there isn't any load folding for cmpps, and vector constants |
| 1598 // are not allowed in PNaCl. | 1614 // are not allowed in PNaCl. |
| 1599 assert(llvm::isa<Variable>(getSrc(1))); | 1615 assert(llvm::isa<Variable>(getSrc(1))); |
| (...skipping 18 matching lines...) Expand all Loading... | |
| 1618 << "\t"; | 1634 << "\t"; |
| 1619 dumpSources(Func); | 1635 dumpSources(Func); |
| 1620 } | 1636 } |
| 1621 | 1637 |
| 1622 void InstX8632Cmpxchg::emit(const Cfg *Func) const { | 1638 void InstX8632Cmpxchg::emit(const Cfg *Func) const { |
| 1623 Ostream &Str = Func->getContext()->getStrEmit(); | 1639 Ostream &Str = Func->getContext()->getStrEmit(); |
| 1624 assert(getSrcSize() == 3); | 1640 assert(getSrcSize() == 3); |
| 1625 if (Locked) { | 1641 if (Locked) { |
| 1626 Str << "\tlock"; | 1642 Str << "\tlock"; |
| 1627 } | 1643 } |
| 1628 Str << "\tcmpxchg\t"; | 1644 Str << "\tcmpxchg" << getWidthString(getSrc(0)->getType()) << "\t"; |
| 1645 getSrc(2)->emit(Func); | |
| 1646 Str << ", "; | |
| 1629 getSrc(0)->emit(Func); | 1647 getSrc(0)->emit(Func); |
| 1630 Str << ", "; | |
| 1631 getSrc(2)->emit(Func); | |
| 1632 } | 1648 } |
| 1633 | 1649 |
| 1634 void InstX8632Cmpxchg::emitIAS(const Cfg *Func) const { | 1650 void InstX8632Cmpxchg::emitIAS(const Cfg *Func) const { |
| 1635 assert(getSrcSize() == 3); | 1651 assert(getSrcSize() == 3); |
| 1636 x86::AssemblerX86 *Asm = Func->getAssembler<x86::AssemblerX86>(); | 1652 x86::AssemblerX86 *Asm = Func->getAssembler<x86::AssemblerX86>(); |
| 1637 intptr_t StartPosition = Asm->GetPosition(); | 1653 intptr_t StartPosition = Asm->GetPosition(); |
| 1638 Type Ty = getSrc(0)->getType(); | 1654 Type Ty = getSrc(0)->getType(); |
| 1639 const OperandX8632Mem *Mem = llvm::cast<OperandX8632Mem>(getSrc(0)); | 1655 const OperandX8632Mem *Mem = llvm::cast<OperandX8632Mem>(getSrc(0)); |
| 1640 assert(Mem->getSegmentRegister() == OperandX8632Mem::DefaultSegment); | 1656 assert(Mem->getSegmentRegister() == OperandX8632Mem::DefaultSegment); |
| 1641 const x86::Address Addr = Mem->toAsmAddress(Asm); | 1657 const x86::Address Addr = Mem->toAsmAddress(Asm); |
| (...skipping 11 matching lines...) Expand all Loading... | |
| 1653 | 1669 |
| 1654 void InstX8632Cmpxchg::dump(const Cfg *Func) const { | 1670 void InstX8632Cmpxchg::dump(const Cfg *Func) const { |
| 1655 Ostream &Str = Func->getContext()->getStrDump(); | 1671 Ostream &Str = Func->getContext()->getStrDump(); |
| 1656 if (Locked) { | 1672 if (Locked) { |
| 1657 Str << "lock "; | 1673 Str << "lock "; |
| 1658 } | 1674 } |
| 1659 Str << "cmpxchg." << getSrc(0)->getType() << " "; | 1675 Str << "cmpxchg." << getSrc(0)->getType() << " "; |
| 1660 dumpSources(Func); | 1676 dumpSources(Func); |
| 1661 } | 1677 } |
| 1662 | 1678 |
| 1663 void InstX8632Cmpxchg8b::emit(const Cfg *Func) const { | 1679 void InstX8632Cmpxchg8b::emit(const Cfg *Func) const { |
|
Jim Stichnoth
2014/10/31 20:55:19
No syntax changes since only one operand is emitte
| |
| 1664 Ostream &Str = Func->getContext()->getStrEmit(); | 1680 Ostream &Str = Func->getContext()->getStrEmit(); |
| 1665 assert(getSrcSize() == 5); | 1681 assert(getSrcSize() == 5); |
| 1666 if (Locked) { | 1682 if (Locked) { |
| 1667 Str << "\tlock"; | 1683 Str << "\tlock"; |
| 1668 } | 1684 } |
| 1669 Str << "\tcmpxchg8b\t"; | 1685 Str << "\tcmpxchg8b\t"; |
| 1670 getSrc(0)->emit(Func); | 1686 getSrc(0)->emit(Func); |
| 1671 } | 1687 } |
| 1672 | 1688 |
| 1673 void InstX8632Cmpxchg8b::emitIAS(const Cfg *Func) const { | 1689 void InstX8632Cmpxchg8b::emitIAS(const Cfg *Func) const { |
| (...skipping 20 matching lines...) Expand all Loading... | |
| 1694 } | 1710 } |
| 1695 | 1711 |
| 1696 void InstX8632Cvt::emit(const Cfg *Func) const { | 1712 void InstX8632Cvt::emit(const Cfg *Func) const { |
| 1697 Ostream &Str = Func->getContext()->getStrEmit(); | 1713 Ostream &Str = Func->getContext()->getStrEmit(); |
| 1698 assert(getSrcSize() == 1); | 1714 assert(getSrcSize() == 1); |
| 1699 Str << "\tcvt"; | 1715 Str << "\tcvt"; |
| 1700 if (isTruncating()) | 1716 if (isTruncating()) |
| 1701 Str << "t"; | 1717 Str << "t"; |
| 1702 Str << TypeX8632Attributes[getSrc(0)->getType()].CvtString << "2" | 1718 Str << TypeX8632Attributes[getSrc(0)->getType()].CvtString << "2" |
| 1703 << TypeX8632Attributes[getDest()->getType()].CvtString << "\t"; | 1719 << TypeX8632Attributes[getDest()->getType()].CvtString << "\t"; |
| 1720 getSrc(0)->emit(Func); | |
| 1721 Str << ", "; | |
| 1704 getDest()->emit(Func); | 1722 getDest()->emit(Func); |
| 1705 Str << ", "; | |
| 1706 getSrc(0)->emit(Func); | |
| 1707 } | 1723 } |
| 1708 | 1724 |
| 1709 void InstX8632Cvt::emitIAS(const Cfg *Func) const { | 1725 void InstX8632Cvt::emitIAS(const Cfg *Func) const { |
| 1710 assert(getSrcSize() == 1); | 1726 assert(getSrcSize() == 1); |
| 1711 const Variable *Dest = getDest(); | 1727 const Variable *Dest = getDest(); |
| 1712 const Operand *Src = getSrc(0); | 1728 const Operand *Src = getSrc(0); |
| 1713 Type DestTy = Dest->getType(); | 1729 Type DestTy = Dest->getType(); |
| 1714 Type SrcTy = Src->getType(); | 1730 Type SrcTy = Src->getType(); |
| 1715 switch (Variant) { | 1731 switch (Variant) { |
| 1716 case Si2ss: { | 1732 case Si2ss: { |
| (...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1772 if (isTruncating()) | 1788 if (isTruncating()) |
| 1773 Str << "t"; | 1789 Str << "t"; |
| 1774 Str << TypeX8632Attributes[getSrc(0)->getType()].CvtString << "2" | 1790 Str << TypeX8632Attributes[getSrc(0)->getType()].CvtString << "2" |
| 1775 << TypeX8632Attributes[getDest()->getType()].CvtString << " "; | 1791 << TypeX8632Attributes[getDest()->getType()].CvtString << " "; |
| 1776 dumpSources(Func); | 1792 dumpSources(Func); |
| 1777 } | 1793 } |
| 1778 | 1794 |
| 1779 void InstX8632Icmp::emit(const Cfg *Func) const { | 1795 void InstX8632Icmp::emit(const Cfg *Func) const { |
| 1780 Ostream &Str = Func->getContext()->getStrEmit(); | 1796 Ostream &Str = Func->getContext()->getStrEmit(); |
| 1781 assert(getSrcSize() == 2); | 1797 assert(getSrcSize() == 2); |
| 1782 Str << "\tcmp\t"; | 1798 Str << "\tcmp" << getWidthString(getSrc(0)->getType()) << "\t"; |
| 1799 getSrc(1)->emit(Func); | |
| 1800 Str << ", "; | |
| 1783 getSrc(0)->emit(Func); | 1801 getSrc(0)->emit(Func); |
| 1784 Str << ", "; | |
| 1785 getSrc(1)->emit(Func); | |
| 1786 } | 1802 } |
| 1787 | 1803 |
| 1788 void InstX8632Icmp::emitIAS(const Cfg *Func) const { | 1804 void InstX8632Icmp::emitIAS(const Cfg *Func) const { |
| 1789 assert(getSrcSize() == 2); | 1805 assert(getSrcSize() == 2); |
| 1790 const Operand *Src0 = getSrc(0); | 1806 const Operand *Src0 = getSrc(0); |
| 1791 const Operand *Src1 = getSrc(1); | 1807 const Operand *Src1 = getSrc(1); |
| 1792 Type Ty = Src0->getType(); | 1808 Type Ty = Src0->getType(); |
| 1793 static const x86::AssemblerX86::GPREmitterRegOp RegEmitter = { | 1809 static const x86::AssemblerX86::GPREmitterRegOp RegEmitter = { |
| 1794 &x86::AssemblerX86::cmp, &x86::AssemblerX86::cmp, &x86::AssemblerX86::cmp | 1810 &x86::AssemblerX86::cmp, &x86::AssemblerX86::cmp, &x86::AssemblerX86::cmp |
| 1795 }; | 1811 }; |
| (...skipping 13 matching lines...) Expand all Loading... | |
| 1809 Ostream &Str = Func->getContext()->getStrDump(); | 1825 Ostream &Str = Func->getContext()->getStrDump(); |
| 1810 Str << "cmp." << getSrc(0)->getType() << " "; | 1826 Str << "cmp." << getSrc(0)->getType() << " "; |
| 1811 dumpSources(Func); | 1827 dumpSources(Func); |
| 1812 } | 1828 } |
| 1813 | 1829 |
| 1814 void InstX8632Ucomiss::emit(const Cfg *Func) const { | 1830 void InstX8632Ucomiss::emit(const Cfg *Func) const { |
| 1815 Ostream &Str = Func->getContext()->getStrEmit(); | 1831 Ostream &Str = Func->getContext()->getStrEmit(); |
| 1816 assert(getSrcSize() == 2); | 1832 assert(getSrcSize() == 2); |
| 1817 Str << "\tucomi" << TypeX8632Attributes[getSrc(0)->getType()].SdSsString | 1833 Str << "\tucomi" << TypeX8632Attributes[getSrc(0)->getType()].SdSsString |
| 1818 << "\t"; | 1834 << "\t"; |
| 1835 getSrc(1)->emit(Func); | |
| 1836 Str << ", "; | |
| 1819 getSrc(0)->emit(Func); | 1837 getSrc(0)->emit(Func); |
| 1820 Str << ", "; | |
| 1821 getSrc(1)->emit(Func); | |
| 1822 } | 1838 } |
| 1823 | 1839 |
| 1824 void InstX8632Ucomiss::emitIAS(const Cfg *Func) const { | 1840 void InstX8632Ucomiss::emitIAS(const Cfg *Func) const { |
| 1825 assert(getSrcSize() == 2); | 1841 assert(getSrcSize() == 2); |
| 1826 // Currently src0 is always a variable by convention, to avoid having | 1842 // Currently src0 is always a variable by convention, to avoid having |
| 1827 // two memory operands. | 1843 // two memory operands. |
| 1828 assert(llvm::isa<Variable>(getSrc(0))); | 1844 assert(llvm::isa<Variable>(getSrc(0))); |
| 1829 const Variable *Src0 = llvm::cast<Variable>(getSrc(0)); | 1845 const Variable *Src0 = llvm::cast<Variable>(getSrc(0)); |
| 1830 Type Ty = Src0->getType(); | 1846 Type Ty = Src0->getType(); |
| 1831 const static x86::AssemblerX86::XmmEmitterRegOp Emitter = { | 1847 const static x86::AssemblerX86::XmmEmitterRegOp Emitter = { |
| (...skipping 22 matching lines...) Expand all Loading... | |
| 1854 } | 1870 } |
| 1855 | 1871 |
| 1856 void InstX8632UD2::dump(const Cfg *Func) const { | 1872 void InstX8632UD2::dump(const Cfg *Func) const { |
| 1857 Ostream &Str = Func->getContext()->getStrDump(); | 1873 Ostream &Str = Func->getContext()->getStrDump(); |
| 1858 Str << "ud2\n"; | 1874 Str << "ud2\n"; |
| 1859 } | 1875 } |
| 1860 | 1876 |
| 1861 void InstX8632Test::emit(const Cfg *Func) const { | 1877 void InstX8632Test::emit(const Cfg *Func) const { |
| 1862 Ostream &Str = Func->getContext()->getStrEmit(); | 1878 Ostream &Str = Func->getContext()->getStrEmit(); |
| 1863 assert(getSrcSize() == 2); | 1879 assert(getSrcSize() == 2); |
| 1864 Str << "\ttest\t"; | 1880 Str << "\ttest" << getWidthString(getSrc(0)->getType()) << "\t"; |
| 1881 getSrc(1)->emit(Func); | |
| 1882 Str << ", "; | |
| 1865 getSrc(0)->emit(Func); | 1883 getSrc(0)->emit(Func); |
| 1866 Str << ", "; | |
| 1867 getSrc(1)->emit(Func); | |
| 1868 } | 1884 } |
| 1869 | 1885 |
| 1870 void InstX8632Test::emitIAS(const Cfg *Func) const { | 1886 void InstX8632Test::emitIAS(const Cfg *Func) const { |
| 1871 assert(getSrcSize() == 2); | 1887 assert(getSrcSize() == 2); |
| 1872 const Operand *Src0 = getSrc(0); | 1888 const Operand *Src0 = getSrc(0); |
| 1873 const Operand *Src1 = getSrc(1); | 1889 const Operand *Src1 = getSrc(1); |
| 1874 Type Ty = Src0->getType(); | 1890 Type Ty = Src0->getType(); |
| 1875 // The Reg/Addr form of test is not encodeable. | 1891 // The Reg/Addr form of test is not encodeable. |
| 1876 static const x86::AssemblerX86::GPREmitterRegOp RegEmitter = { | 1892 static const x86::AssemblerX86::GPREmitterRegOp RegEmitter = { |
| 1877 &x86::AssemblerX86::test, NULL, &x86::AssemblerX86::test | 1893 &x86::AssemblerX86::test, NULL, &x86::AssemblerX86::test |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1909 } | 1925 } |
| 1910 | 1926 |
| 1911 void InstX8632Mfence::dump(const Cfg *Func) const { | 1927 void InstX8632Mfence::dump(const Cfg *Func) const { |
| 1912 Ostream &Str = Func->getContext()->getStrDump(); | 1928 Ostream &Str = Func->getContext()->getStrDump(); |
| 1913 Str << "mfence\n"; | 1929 Str << "mfence\n"; |
| 1914 } | 1930 } |
| 1915 | 1931 |
| 1916 void InstX8632Store::emit(const Cfg *Func) const { | 1932 void InstX8632Store::emit(const Cfg *Func) const { |
| 1917 Ostream &Str = Func->getContext()->getStrEmit(); | 1933 Ostream &Str = Func->getContext()->getStrEmit(); |
| 1918 assert(getSrcSize() == 2); | 1934 assert(getSrcSize() == 2); |
| 1919 Str << "\tmov" << TypeX8632Attributes[getSrc(0)->getType()].SdSsString | 1935 Type Ty = getSrc(0)->getType(); |
| 1936 Str << "\tmov" << getWidthString(Ty) << TypeX8632Attributes[Ty].SdSsString | |
| 1920 << "\t"; | 1937 << "\t"; |
| 1938 getSrc(0)->emit(Func); | |
| 1939 Str << ", "; | |
| 1921 getSrc(1)->emit(Func); | 1940 getSrc(1)->emit(Func); |
| 1922 Str << ", "; | |
| 1923 getSrc(0)->emit(Func); | |
| 1924 } | 1941 } |
| 1925 | 1942 |
| 1926 void InstX8632Store::emitIAS(const Cfg *Func) const { | 1943 void InstX8632Store::emitIAS(const Cfg *Func) const { |
| 1927 assert(getSrcSize() == 2); | 1944 assert(getSrcSize() == 2); |
| 1928 const Operand *Dest = getSrc(1); | 1945 const Operand *Dest = getSrc(1); |
| 1929 const Operand *Src = getSrc(0); | 1946 const Operand *Src = getSrc(0); |
| 1930 Type DestTy = Dest->getType(); | 1947 Type DestTy = Dest->getType(); |
| 1931 if (isScalarFloatingType(DestTy)) { | 1948 if (isScalarFloatingType(DestTy)) { |
| 1932 // Src must be a register, since Dest is a Mem operand of some kind. | 1949 // Src must be a register, since Dest is a Mem operand of some kind. |
| 1933 const Variable *SrcVar = llvm::cast<Variable>(Src); | 1950 const Variable *SrcVar = llvm::cast<Variable>(Src); |
| (...skipping 26 matching lines...) Expand all Loading... | |
| 1960 Str << "mov." << getSrc(0)->getType() << " "; | 1977 Str << "mov." << getSrc(0)->getType() << " "; |
| 1961 getSrc(1)->dump(Func); | 1978 getSrc(1)->dump(Func); |
| 1962 Str << ", "; | 1979 Str << ", "; |
| 1963 getSrc(0)->dump(Func); | 1980 getSrc(0)->dump(Func); |
| 1964 } | 1981 } |
| 1965 | 1982 |
| 1966 void InstX8632StoreP::emit(const Cfg *Func) const { | 1983 void InstX8632StoreP::emit(const Cfg *Func) const { |
| 1967 Ostream &Str = Func->getContext()->getStrEmit(); | 1984 Ostream &Str = Func->getContext()->getStrEmit(); |
| 1968 assert(getSrcSize() == 2); | 1985 assert(getSrcSize() == 2); |
| 1969 Str << "\tmovups\t"; | 1986 Str << "\tmovups\t"; |
| 1987 getSrc(0)->emit(Func); | |
| 1988 Str << ", "; | |
| 1970 getSrc(1)->emit(Func); | 1989 getSrc(1)->emit(Func); |
| 1971 Str << ", "; | |
| 1972 getSrc(0)->emit(Func); | |
| 1973 } | 1990 } |
| 1974 | 1991 |
| 1975 void InstX8632StoreP::emitIAS(const Cfg *Func) const { | 1992 void InstX8632StoreP::emitIAS(const Cfg *Func) const { |
| 1976 x86::AssemblerX86 *Asm = Func->getAssembler<x86::AssemblerX86>(); | 1993 x86::AssemblerX86 *Asm = Func->getAssembler<x86::AssemblerX86>(); |
| 1977 intptr_t StartPosition = Asm->GetPosition(); | 1994 intptr_t StartPosition = Asm->GetPosition(); |
| 1978 assert(getSrcSize() == 2); | 1995 assert(getSrcSize() == 2); |
| 1979 const Variable *Src = llvm::cast<Variable>(getSrc(0)); | 1996 const Variable *Src = llvm::cast<Variable>(getSrc(0)); |
| 1980 const OperandX8632Mem *DestMem = llvm::cast<OperandX8632Mem>(getSrc(1)); | 1997 const OperandX8632Mem *DestMem = llvm::cast<OperandX8632Mem>(getSrc(1)); |
| 1981 assert(DestMem->getSegmentRegister() == OperandX8632Mem::DefaultSegment); | 1998 assert(DestMem->getSegmentRegister() == OperandX8632Mem::DefaultSegment); |
| 1982 assert(Src->hasReg()); | 1999 assert(Src->hasReg()); |
| 1983 Asm->movups(DestMem->toAsmAddress(Asm), | 2000 Asm->movups(DestMem->toAsmAddress(Asm), |
| 1984 RegX8632::getEncodedXmm(Src->getRegNum())); | 2001 RegX8632::getEncodedXmm(Src->getRegNum())); |
| 1985 emitIASBytes(Func, Asm, StartPosition); | 2002 emitIASBytes(Func, Asm, StartPosition); |
| 1986 } | 2003 } |
| 1987 | 2004 |
| 1988 void InstX8632StoreP::dump(const Cfg *Func) const { | 2005 void InstX8632StoreP::dump(const Cfg *Func) const { |
| 1989 Ostream &Str = Func->getContext()->getStrDump(); | 2006 Ostream &Str = Func->getContext()->getStrDump(); |
| 1990 Str << "storep." << getSrc(0)->getType() << " "; | 2007 Str << "storep." << getSrc(0)->getType() << " "; |
| 1991 getSrc(1)->dump(Func); | 2008 getSrc(1)->dump(Func); |
| 1992 Str << ", "; | 2009 Str << ", "; |
| 1993 getSrc(0)->dump(Func); | 2010 getSrc(0)->dump(Func); |
| 1994 } | 2011 } |
| 1995 | 2012 |
| 1996 void InstX8632StoreQ::emit(const Cfg *Func) const { | 2013 void InstX8632StoreQ::emit(const Cfg *Func) const { |
| 1997 Ostream &Str = Func->getContext()->getStrEmit(); | 2014 Ostream &Str = Func->getContext()->getStrEmit(); |
| 1998 assert(getSrcSize() == 2); | 2015 assert(getSrcSize() == 2); |
| 1999 assert(getSrc(1)->getType() == IceType_i64 || | 2016 assert(getSrc(1)->getType() == IceType_i64 || |
| 2000 getSrc(1)->getType() == IceType_f64); | 2017 getSrc(1)->getType() == IceType_f64); |
| 2001 Str << "\tmovq\t"; | 2018 Str << "\tmovq\t"; |
| 2019 getSrc(0)->emit(Func); | |
| 2020 Str << ", "; | |
| 2002 getSrc(1)->emit(Func); | 2021 getSrc(1)->emit(Func); |
| 2003 Str << ", "; | |
| 2004 getSrc(0)->emit(Func); | |
| 2005 } | 2022 } |
| 2006 | 2023 |
| 2007 void InstX8632StoreQ::emitIAS(const Cfg *Func) const { | 2024 void InstX8632StoreQ::emitIAS(const Cfg *Func) const { |
| 2008 x86::AssemblerX86 *Asm = Func->getAssembler<x86::AssemblerX86>(); | 2025 x86::AssemblerX86 *Asm = Func->getAssembler<x86::AssemblerX86>(); |
| 2009 intptr_t StartPosition = Asm->GetPosition(); | 2026 intptr_t StartPosition = Asm->GetPosition(); |
| 2010 assert(getSrcSize() == 2); | 2027 assert(getSrcSize() == 2); |
| 2011 const Variable *Src = llvm::cast<Variable>(getSrc(0)); | 2028 const Variable *Src = llvm::cast<Variable>(getSrc(0)); |
| 2012 const OperandX8632Mem *DestMem = llvm::cast<OperandX8632Mem>(getSrc(1)); | 2029 const OperandX8632Mem *DestMem = llvm::cast<OperandX8632Mem>(getSrc(1)); |
| 2013 assert(DestMem->getSegmentRegister() == OperandX8632Mem::DefaultSegment); | 2030 assert(DestMem->getSegmentRegister() == OperandX8632Mem::DefaultSegment); |
| 2014 assert(Src->hasReg()); | 2031 assert(Src->hasReg()); |
| 2015 Asm->movq(DestMem->toAsmAddress(Asm), | 2032 Asm->movq(DestMem->toAsmAddress(Asm), |
| 2016 RegX8632::getEncodedXmm(Src->getRegNum())); | 2033 RegX8632::getEncodedXmm(Src->getRegNum())); |
| 2017 emitIASBytes(Func, Asm, StartPosition); | 2034 emitIASBytes(Func, Asm, StartPosition); |
| 2018 } | 2035 } |
| 2019 | 2036 |
| 2020 void InstX8632StoreQ::dump(const Cfg *Func) const { | 2037 void InstX8632StoreQ::dump(const Cfg *Func) const { |
| 2021 Ostream &Str = Func->getContext()->getStrDump(); | 2038 Ostream &Str = Func->getContext()->getStrDump(); |
| 2022 Str << "storeq." << getSrc(0)->getType() << " "; | 2039 Str << "storeq." << getSrc(0)->getType() << " "; |
| 2023 getSrc(1)->dump(Func); | 2040 getSrc(1)->dump(Func); |
| 2024 Str << ", "; | 2041 Str << ", "; |
| 2025 getSrc(0)->dump(Func); | 2042 getSrc(0)->dump(Func); |
| 2026 } | 2043 } |
| 2027 | 2044 |
| 2028 template <> void InstX8632Lea::emit(const Cfg *Func) const { | 2045 template <> void InstX8632Lea::emit(const Cfg *Func) const { |
| 2029 Ostream &Str = Func->getContext()->getStrEmit(); | 2046 Ostream &Str = Func->getContext()->getStrEmit(); |
| 2030 assert(getSrcSize() == 1); | 2047 assert(getSrcSize() == 1); |
| 2031 assert(getDest()->hasReg()); | 2048 assert(getDest()->hasReg()); |
| 2032 Str << "\tlea\t"; | 2049 Str << "\tleal\t"; |
| 2033 getDest()->emit(Func); | |
| 2034 Str << ", "; | |
| 2035 Operand *Src0 = getSrc(0); | 2050 Operand *Src0 = getSrc(0); |
| 2036 if (Variable *VSrc0 = llvm::dyn_cast<Variable>(Src0)) { | 2051 if (Variable *VSrc0 = llvm::dyn_cast<Variable>(Src0)) { |
| 2037 Type Ty = VSrc0->getType(); | 2052 Type Ty = VSrc0->getType(); |
| 2038 // lea on x86-32 doesn't accept mem128 operands, so cast VSrc0 to an | 2053 // lea on x86-32 doesn't accept mem128 operands, so cast VSrc0 to an |
| 2039 // acceptable type. | 2054 // acceptable type. |
| 2040 VSrc0->asType(isVectorType(Ty) ? IceType_i32 : Ty).emit(Func); | 2055 VSrc0->asType(isVectorType(Ty) ? IceType_i32 : Ty).emit(Func); |
| 2041 } else { | 2056 } else { |
| 2042 Src0->emit(Func); | 2057 Src0->emit(Func); |
| 2043 } | 2058 } |
| 2059 Str << ", "; | |
| 2060 getDest()->emit(Func); | |
| 2044 } | 2061 } |
| 2045 | 2062 |
| 2046 template <> void InstX8632Mov::emit(const Cfg *Func) const { | 2063 template <> void InstX8632Mov::emit(const Cfg *Func) const { |
| 2047 Ostream &Str = Func->getContext()->getStrEmit(); | 2064 Ostream &Str = Func->getContext()->getStrEmit(); |
| 2048 assert(getSrcSize() == 1); | 2065 assert(getSrcSize() == 1); |
| 2049 Operand *Src = getSrc(0); | 2066 Operand *Src = getSrc(0); |
| 2067 Type SrcTy = Src->getType(); | |
| 2068 Type DestTy = getDest()->getType(); | |
| 2050 // The llvm-mc assembler using Intel syntax has a bug in which "mov | 2069 // The llvm-mc assembler using Intel syntax has a bug in which "mov |
| 2051 // reg, RelocatableConstant" does not generate the right instruction | 2070 // reg, RelocatableConstant" does not generate the right instruction |
| 2052 // with a relocation. To work around, we emit "lea reg, | 2071 // with a relocation. To work around, we emit "lea reg, |
| 2053 // RelocatableConstant". Also, the lowering and legalization is | 2072 // RelocatableConstant". Also, the lowering and legalization is |
| 2054 // changed to allow relocatable constants only in Assign and Call | 2073 // changed to allow relocatable constants only in Assign and Call |
| 2055 // instructions or in Mem operands. TODO(stichnot): remove LEAHACK | 2074 // instructions or in Mem operands. |
| 2056 // once a proper emitter is used. | 2075 Str << "\tmov" << (!isScalarFloatingType(DestTy) |
| 2057 // | 2076 ? getWidthString(SrcTy) |
| 2058 // In addition, llvm-mc doesn't like "lea eax, bp" or "lea eax, Sp" | 2077 : TypeX8632Attributes[DestTy].SdSsString) << "\t"; |
| 2059 // or "lea eax, flags" etc., when the relocatable constant name is a | |
| 2060 // reserved word. The hack-on-top-of-hack is to temporarily drop | |
| 2061 // into AT&T syntax for this lea instruction. | |
| 2062 bool UseLeaHack = llvm::isa<ConstantRelocatable>(Src); | |
| 2063 if (UseLeaHack) { | |
| 2064 Str << ".att_syntax\n"; | |
| 2065 Str << "\tleal"; | |
| 2066 } else { | |
| 2067 Str << "\tmov" << TypeX8632Attributes[getDest()->getType()].SdSsString; | |
| 2068 } | |
| 2069 Str << "\t"; | |
| 2070 // For an integer truncation operation, src is wider than dest. | 2078 // For an integer truncation operation, src is wider than dest. |
| 2071 // Ideally, we use a mov instruction whose data width matches the | 2079 // Ideally, we use a mov instruction whose data width matches the |
| 2072 // narrower dest. This is a problem if e.g. src is a register like | 2080 // narrower dest. This is a problem if e.g. src is a register like |
| 2073 // esi or si where there is no 8-bit version of the register. To be | 2081 // esi or si where there is no 8-bit version of the register. To be |
| 2074 // safe, we instead widen the dest to match src. This works even | 2082 // safe, we instead widen the dest to match src. This works even |
| 2075 // for stack-allocated dest variables because typeWidthOnStack() | 2083 // for stack-allocated dest variables because typeWidthOnStack() |
| 2076 // pads to a 4-byte boundary even if only a lower portion is used. | 2084 // pads to a 4-byte boundary even if only a lower portion is used. |
| 2077 // TODO: This assert disallows usages such as copying a floating point | 2085 // TODO: This assert disallows usages such as copying a floating point |
| 2078 // value between a vector and a scalar (which movss is used for). | 2086 // value between a vector and a scalar (which movss is used for). |
| 2079 // Clean this up. | 2087 // Clean this up. |
| 2080 assert(Func->getTarget()->typeWidthInBytesOnStack(getDest()->getType()) == | 2088 assert(Func->getTarget()->typeWidthInBytesOnStack(DestTy) == |
| 2081 Func->getTarget()->typeWidthInBytesOnStack(Src->getType())); | 2089 Func->getTarget()->typeWidthInBytesOnStack(SrcTy)); |
| 2082 if (UseLeaHack) { | 2090 Src->emit(Func); |
| 2083 Src->emit(Func); | 2091 Str << ", "; |
| 2084 Str << ", %"; | 2092 getDest()->asType(SrcTy).emit(Func); |
| 2085 getDest()->emit(Func); | |
| 2086 Str << "\n"; | |
| 2087 Str << ".intel_syntax"; | |
| 2088 } else { | |
| 2089 getDest()->asType(Src->getType()).emit(Func); | |
| 2090 Str << ", "; | |
| 2091 Src->emit(Func); | |
| 2092 } | |
| 2093 } | 2093 } |
| 2094 | 2094 |
| 2095 template <> void InstX8632Mov::emitIAS(const Cfg *Func) const { | 2095 template <> void InstX8632Mov::emitIAS(const Cfg *Func) const { |
| 2096 assert(getSrcSize() == 1); | 2096 assert(getSrcSize() == 1); |
| 2097 const Variable *Dest = getDest(); | 2097 const Variable *Dest = getDest(); |
| 2098 const Operand *Src = getSrc(0); | 2098 const Operand *Src = getSrc(0); |
| 2099 Type DestTy = Dest->getType(); | 2099 Type DestTy = Dest->getType(); |
| 2100 Type SrcTy = Src->getType(); | 2100 Type SrcTy = Src->getType(); |
| 2101 // Mov can be used for GPRs or XMM registers. Also, the type does not | 2101 // Mov can be used for GPRs or XMM registers. Also, the type does not |
| 2102 // necessarily match (Mov can be used for bitcasts). However, when | 2102 // necessarily match (Mov can be used for bitcasts). However, when |
| (...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2199 } | 2199 } |
| 2200 | 2200 |
| 2201 template <> void InstX8632Movp::emit(const Cfg *Func) const { | 2201 template <> void InstX8632Movp::emit(const Cfg *Func) const { |
| 2202 // TODO(wala,stichnot): movups works with all vector operands, but | 2202 // TODO(wala,stichnot): movups works with all vector operands, but |
| 2203 // there exist other instructions (movaps, movdqa, movdqu) that may | 2203 // there exist other instructions (movaps, movdqa, movdqu) that may |
| 2204 // perform better, depending on the data type and alignment of the | 2204 // perform better, depending on the data type and alignment of the |
| 2205 // operands. | 2205 // operands. |
| 2206 Ostream &Str = Func->getContext()->getStrEmit(); | 2206 Ostream &Str = Func->getContext()->getStrEmit(); |
| 2207 assert(getSrcSize() == 1); | 2207 assert(getSrcSize() == 1); |
| 2208 Str << "\tmovups\t"; | 2208 Str << "\tmovups\t"; |
| 2209 getSrc(0)->emit(Func); | |
| 2210 Str << ", "; | |
| 2209 getDest()->emit(Func); | 2211 getDest()->emit(Func); |
| 2210 Str << ", "; | |
| 2211 getSrc(0)->emit(Func); | |
| 2212 } | 2212 } |
| 2213 | 2213 |
| 2214 template <> void InstX8632Movp::emitIAS(const Cfg *Func) const { | 2214 template <> void InstX8632Movp::emitIAS(const Cfg *Func) const { |
| 2215 assert(getSrcSize() == 1); | 2215 assert(getSrcSize() == 1); |
| 2216 assert(isVectorType(getDest()->getType())); | 2216 assert(isVectorType(getDest()->getType())); |
| 2217 const Variable *Dest = getDest(); | 2217 const Variable *Dest = getDest(); |
| 2218 const Operand *Src = getSrc(0); | 2218 const Operand *Src = getSrc(0); |
| 2219 const static x86::AssemblerX86::XmmEmitterMovOps Emitter = { | 2219 const static x86::AssemblerX86::XmmEmitterMovOps Emitter = { |
| 2220 &x86::AssemblerX86::movups, &x86::AssemblerX86::movups, | 2220 &x86::AssemblerX86::movups, &x86::AssemblerX86::movups, |
| 2221 &x86::AssemblerX86::movups | 2221 &x86::AssemblerX86::movups |
| 2222 }; | 2222 }; |
| 2223 emitIASMovlikeXMM(Func, Dest, Src, Emitter); | 2223 emitIASMovlikeXMM(Func, Dest, Src, Emitter); |
| 2224 } | 2224 } |
| 2225 | 2225 |
| 2226 template <> void InstX8632Movq::emit(const Cfg *Func) const { | 2226 template <> void InstX8632Movq::emit(const Cfg *Func) const { |
| 2227 Ostream &Str = Func->getContext()->getStrEmit(); | 2227 Ostream &Str = Func->getContext()->getStrEmit(); |
| 2228 assert(getSrcSize() == 1); | 2228 assert(getSrcSize() == 1); |
| 2229 assert(getDest()->getType() == IceType_i64 || | 2229 assert(getDest()->getType() == IceType_i64 || |
| 2230 getDest()->getType() == IceType_f64); | 2230 getDest()->getType() == IceType_f64); |
| 2231 Str << "\tmovq\t"; | 2231 Str << "\tmovq\t"; |
| 2232 getSrc(0)->emit(Func); | |
| 2233 Str << ", "; | |
| 2232 getDest()->emit(Func); | 2234 getDest()->emit(Func); |
| 2233 Str << ", "; | |
| 2234 getSrc(0)->emit(Func); | |
| 2235 } | 2235 } |
| 2236 | 2236 |
| 2237 template <> void InstX8632Movq::emitIAS(const Cfg *Func) const { | 2237 template <> void InstX8632Movq::emitIAS(const Cfg *Func) const { |
| 2238 assert(getSrcSize() == 1); | 2238 assert(getSrcSize() == 1); |
| 2239 assert(getDest()->getType() == IceType_i64 || | 2239 assert(getDest()->getType() == IceType_i64 || |
| 2240 getDest()->getType() == IceType_f64); | 2240 getDest()->getType() == IceType_f64); |
| 2241 const Variable *Dest = getDest(); | 2241 const Variable *Dest = getDest(); |
| 2242 const Operand *Src = getSrc(0); | 2242 const Operand *Src = getSrc(0); |
| 2243 const static x86::AssemblerX86::XmmEmitterMovOps Emitter = { | 2243 const static x86::AssemblerX86::XmmEmitterMovOps Emitter = { |
| 2244 &x86::AssemblerX86::movq, &x86::AssemblerX86::movq, &x86::AssemblerX86::movq | 2244 &x86::AssemblerX86::movq, &x86::AssemblerX86::movq, &x86::AssemblerX86::movq |
| (...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2300 | 2300 |
| 2301 void InstX8632Nop::dump(const Cfg *Func) const { | 2301 void InstX8632Nop::dump(const Cfg *Func) const { |
| 2302 Ostream &Str = Func->getContext()->getStrDump(); | 2302 Ostream &Str = Func->getContext()->getStrDump(); |
| 2303 Str << "nop (variant = " << Variant << ")"; | 2303 Str << "nop (variant = " << Variant << ")"; |
| 2304 } | 2304 } |
| 2305 | 2305 |
| 2306 void InstX8632Fld::emit(const Cfg *Func) const { | 2306 void InstX8632Fld::emit(const Cfg *Func) const { |
| 2307 Ostream &Str = Func->getContext()->getStrEmit(); | 2307 Ostream &Str = Func->getContext()->getStrEmit(); |
| 2308 assert(getSrcSize() == 1); | 2308 assert(getSrcSize() == 1); |
| 2309 Type Ty = getSrc(0)->getType(); | 2309 Type Ty = getSrc(0)->getType(); |
| 2310 SizeT Width = typeWidthInBytes(Ty); | |
| 2310 Variable *Var = llvm::dyn_cast<Variable>(getSrc(0)); | 2311 Variable *Var = llvm::dyn_cast<Variable>(getSrc(0)); |
| 2311 if (Var && Var->hasReg()) { | 2312 if (Var && Var->hasReg()) { |
| 2312 // This is a physical xmm register, so we need to spill it to a | 2313 // This is a physical xmm register, so we need to spill it to a |
| 2313 // temporary stack slot. | 2314 // temporary stack slot. |
| 2314 SizeT Width = typeWidthInBytes(Ty); | 2315 Str << "\tsubl\t$" << Width << ", %esp" |
| 2315 Str << "\tsub\tesp, " << Width << "\n"; | 2316 << "\n"; |
| 2316 Str << "\tmov" << TypeX8632Attributes[Ty].SdSsString << "\t" | 2317 Str << "\tmov" << TypeX8632Attributes[Ty].SdSsString << "\t"; |
| 2317 << TypeX8632Attributes[Ty].WidthString << " [esp], "; | |
| 2318 Var->emit(Func); | 2318 Var->emit(Func); |
| 2319 Str << "\n"; | 2319 Str << ", (%esp)\n"; |
| 2320 Str << "\tfld\t" << TypeX8632Attributes[Ty].WidthString << " [esp]\n"; | 2320 Str << "\tfld" << getFldString(Ty) << "\t" |
| 2321 Str << "\tadd\tesp, " << Width; | 2321 << "(%esp)\n"; |
| 2322 Str << "\taddl\t$" << Width << ", %esp"; | |
| 2322 return; | 2323 return; |
| 2323 } | 2324 } |
| 2324 Str << "\tfld\t"; | 2325 Str << "\tfld" << getFldString(Ty) << "\t"; |
| 2325 getSrc(0)->emit(Func); | 2326 getSrc(0)->emit(Func); |
| 2326 } | 2327 } |
| 2327 | 2328 |
| 2328 void InstX8632Fld::emitIAS(const Cfg *Func) const { | 2329 void InstX8632Fld::emitIAS(const Cfg *Func) const { |
| 2329 x86::AssemblerX86 *Asm = Func->getAssembler<x86::AssemblerX86>(); | 2330 x86::AssemblerX86 *Asm = Func->getAssembler<x86::AssemblerX86>(); |
| 2330 intptr_t StartPosition = Asm->GetPosition(); | 2331 intptr_t StartPosition = Asm->GetPosition(); |
| 2331 assert(getSrcSize() == 1); | 2332 assert(getSrcSize() == 1); |
| 2332 const Operand *Src = getSrc(0); | 2333 const Operand *Src = getSrc(0); |
| 2333 Type Ty = Src->getType(); | 2334 Type Ty = Src->getType(); |
| 2334 if (const auto Var = llvm::dyn_cast<Variable>(Src)) { | 2335 if (const auto Var = llvm::dyn_cast<Variable>(Src)) { |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2367 Ostream &Str = Func->getContext()->getStrEmit(); | 2368 Ostream &Str = Func->getContext()->getStrEmit(); |
| 2368 assert(getSrcSize() == 0); | 2369 assert(getSrcSize() == 0); |
| 2369 // TODO(jvoung,stichnot): Utilize this by setting Dest to NULL to | 2370 // TODO(jvoung,stichnot): Utilize this by setting Dest to NULL to |
| 2370 // "partially" delete the fstp if the Dest is unused. | 2371 // "partially" delete the fstp if the Dest is unused. |
| 2371 // Even if Dest is unused, the fstp should be kept for the SideEffects | 2372 // Even if Dest is unused, the fstp should be kept for the SideEffects |
| 2372 // of popping the stack. | 2373 // of popping the stack. |
| 2373 if (getDest() == NULL) { | 2374 if (getDest() == NULL) { |
| 2374 Str << "\tfstp\tst(0)"; | 2375 Str << "\tfstp\tst(0)"; |
| 2375 return; | 2376 return; |
| 2376 } | 2377 } |
| 2378 Type Ty = getDest()->getType(); | |
| 2379 size_t Width = typeWidthInBytes(Ty); | |
| 2377 if (!getDest()->hasReg()) { | 2380 if (!getDest()->hasReg()) { |
| 2378 Str << "\tfstp\t"; | 2381 Str << "\tfstp" << getFldString(Ty) << "\t"; |
| 2379 getDest()->emit(Func); | 2382 getDest()->emit(Func); |
| 2380 return; | 2383 return; |
| 2381 } | 2384 } |
| 2382 // Dest is a physical (xmm) register, so st(0) needs to go through | 2385 // Dest is a physical (xmm) register, so st(0) needs to go through |
| 2383 // memory. Hack this by creating a temporary stack slot, spilling | 2386 // memory. Hack this by creating a temporary stack slot, spilling |
| 2384 // st(0) there, loading it into the xmm register, and deallocating | 2387 // st(0) there, loading it into the xmm register, and deallocating |
| 2385 // the stack slot. | 2388 // the stack slot. |
| 2386 Type Ty = getDest()->getType(); | 2389 Str << "\tsubl\t$" << Width << ", %esp\n"; |
| 2387 size_t Width = typeWidthInBytes(Ty); | 2390 Str << "\tfstp" << getFldString(Ty) << "\t" |
| 2388 Str << "\tsub\tesp, " << Width << "\n"; | 2391 << "(%esp)\n"; |
| 2389 Str << "\tfstp\t" << TypeX8632Attributes[Ty].WidthString << " [esp]\n"; | 2392 Str << "\tmov" << TypeX8632Attributes[Ty].SdSsString << "\t" |
| 2390 Str << "\tmov" << TypeX8632Attributes[Ty].SdSsString << "\t"; | 2393 << "(%esp), "; |
| 2391 getDest()->emit(Func); | 2394 getDest()->emit(Func); |
| 2392 Str << ", " << TypeX8632Attributes[Ty].WidthString << " [esp]\n"; | 2395 Str << "\n"; |
| 2393 Str << "\tadd\tesp, " << Width; | 2396 Str << "\taddl\t$" << Width << ", %esp"; |
| 2394 } | 2397 } |
| 2395 | 2398 |
| 2396 void InstX8632Fstp::emitIAS(const Cfg *Func) const { | 2399 void InstX8632Fstp::emitIAS(const Cfg *Func) const { |
| 2397 x86::AssemblerX86 *Asm = Func->getAssembler<x86::AssemblerX86>(); | 2400 x86::AssemblerX86 *Asm = Func->getAssembler<x86::AssemblerX86>(); |
| 2398 intptr_t StartPosition = Asm->GetPosition(); | 2401 intptr_t StartPosition = Asm->GetPosition(); |
| 2399 assert(getSrcSize() == 0); | 2402 assert(getSrcSize() == 0); |
| 2400 const Variable *Dest = getDest(); | 2403 const Variable *Dest = getDest(); |
| 2401 // TODO(jvoung,stichnot): Utilize this by setting Dest to NULL to | 2404 // TODO(jvoung,stichnot): Utilize this by setting Dest to NULL to |
| 2402 // "partially" delete the fstp if the Dest is unused. | 2405 // "partially" delete the fstp if the Dest is unused. |
| 2403 // Even if Dest is unused, the fstp should be kept for the SideEffects | 2406 // Even if Dest is unused, the fstp should be kept for the SideEffects |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2451 template <> void InstX8632Pextr::emit(const Cfg *Func) const { | 2454 template <> void InstX8632Pextr::emit(const Cfg *Func) const { |
| 2452 Ostream &Str = Func->getContext()->getStrEmit(); | 2455 Ostream &Str = Func->getContext()->getStrEmit(); |
| 2453 assert(getSrcSize() == 2); | 2456 assert(getSrcSize() == 2); |
| 2454 // pextrb and pextrd are SSE4.1 instructions. | 2457 // pextrb and pextrd are SSE4.1 instructions. |
| 2455 assert(getSrc(0)->getType() == IceType_v8i16 || | 2458 assert(getSrc(0)->getType() == IceType_v8i16 || |
| 2456 getSrc(0)->getType() == IceType_v8i1 || | 2459 getSrc(0)->getType() == IceType_v8i1 || |
| 2457 static_cast<TargetX8632 *>(Func->getTarget())->getInstructionSet() | 2460 static_cast<TargetX8632 *>(Func->getTarget())->getInstructionSet() |
| 2458 >= TargetX8632::SSE4_1); | 2461 >= TargetX8632::SSE4_1); |
| 2459 Str << "\t" << Opcode | 2462 Str << "\t" << Opcode |
| 2460 << TypeX8632Attributes[getSrc(0)->getType()].PackString << "\t"; | 2463 << TypeX8632Attributes[getSrc(0)->getType()].PackString << "\t"; |
| 2464 getSrc(1)->emit(Func); | |
| 2465 Str << ", "; | |
| 2466 getSrc(0)->emit(Func); | |
| 2467 Str << ", "; | |
| 2461 Variable *Dest = getDest(); | 2468 Variable *Dest = getDest(); |
| 2462 // pextrw must take a register dest. There is an SSE4.1 version that takes | 2469 // pextrw must take a register dest. There is an SSE4.1 version that takes |
| 2463 // a memory dest, but we aren't using it. For uniformity, just restrict | 2470 // a memory dest, but we aren't using it. For uniformity, just restrict |
| 2464 // them all to have a register dest for now. | 2471 // them all to have a register dest for now. |
| 2465 assert(Dest->hasReg()); | 2472 assert(Dest->hasReg()); |
| 2466 Dest->asType(IceType_i32).emit(Func); | 2473 Dest->asType(IceType_i32).emit(Func); |
| 2467 Str << ", "; | |
| 2468 getSrc(0)->emit(Func); | |
| 2469 Str << ", "; | |
| 2470 getSrc(1)->emit(Func); | |
| 2471 } | 2474 } |
| 2472 | 2475 |
| 2473 template <> void InstX8632Pextr::emitIAS(const Cfg *Func) const { | 2476 template <> void InstX8632Pextr::emitIAS(const Cfg *Func) const { |
| 2474 assert(getSrcSize() == 2); | 2477 assert(getSrcSize() == 2); |
| 2475 // pextrb and pextrd are SSE4.1 instructions. | 2478 // pextrb and pextrd are SSE4.1 instructions. |
| 2476 const Variable *Dest = getDest(); | 2479 const Variable *Dest = getDest(); |
| 2477 Type DispatchTy = Dest->getType(); | 2480 Type DispatchTy = Dest->getType(); |
| 2478 assert(DispatchTy == IceType_i16 || | 2481 assert(DispatchTy == IceType_i16 || |
| 2479 static_cast<TargetX8632 *>(Func->getTarget())->getInstructionSet() >= | 2482 static_cast<TargetX8632 *>(Func->getTarget())->getInstructionSet() >= |
| 2480 TargetX8632::SSE4_1); | 2483 TargetX8632::SSE4_1); |
| (...skipping 14 matching lines...) Expand all Loading... | |
| 2495 template <> void InstX8632Pinsr::emit(const Cfg *Func) const { | 2498 template <> void InstX8632Pinsr::emit(const Cfg *Func) const { |
| 2496 Ostream &Str = Func->getContext()->getStrEmit(); | 2499 Ostream &Str = Func->getContext()->getStrEmit(); |
| 2497 assert(getSrcSize() == 3); | 2500 assert(getSrcSize() == 3); |
| 2498 // pinsrb and pinsrd are SSE4.1 instructions. | 2501 // pinsrb and pinsrd are SSE4.1 instructions. |
| 2499 assert(getDest()->getType() == IceType_v8i16 || | 2502 assert(getDest()->getType() == IceType_v8i16 || |
| 2500 getDest()->getType() == IceType_v8i1 || | 2503 getDest()->getType() == IceType_v8i1 || |
| 2501 static_cast<TargetX8632 *>(Func->getTarget())->getInstructionSet() | 2504 static_cast<TargetX8632 *>(Func->getTarget())->getInstructionSet() |
| 2502 >= TargetX8632::SSE4_1); | 2505 >= TargetX8632::SSE4_1); |
| 2503 Str << "\t" << Opcode | 2506 Str << "\t" << Opcode |
| 2504 << TypeX8632Attributes[getDest()->getType()].PackString << "\t"; | 2507 << TypeX8632Attributes[getDest()->getType()].PackString << "\t"; |
| 2505 getDest()->emit(Func); | 2508 getSrc(2)->emit(Func); |
| 2506 Str << ", "; | 2509 Str << ", "; |
| 2507 Operand *Src1 = getSrc(1); | 2510 Operand *Src1 = getSrc(1); |
| 2508 if (Variable *VSrc1 = llvm::dyn_cast<Variable>(Src1)) { | 2511 if (Variable *VSrc1 = llvm::dyn_cast<Variable>(Src1)) { |
| 2509 // If src1 is a register, it should always be r32. | 2512 // If src1 is a register, it should always be r32. |
| 2510 if (VSrc1->hasReg()) { | 2513 if (VSrc1->hasReg()) { |
| 2511 VSrc1->asType(IceType_i32).emit(Func); | 2514 VSrc1->asType(IceType_i32).emit(Func); |
| 2512 } else { | 2515 } else { |
| 2513 VSrc1->emit(Func); | 2516 VSrc1->emit(Func); |
| 2514 } | 2517 } |
| 2515 } else { | 2518 } else { |
| 2516 Src1->emit(Func); | 2519 Src1->emit(Func); |
| 2517 } | 2520 } |
| 2518 Str << ", "; | 2521 Str << ", "; |
| 2519 getSrc(2)->emit(Func); | 2522 getDest()->emit(Func); |
| 2520 } | 2523 } |
| 2521 | 2524 |
| 2522 template <> void InstX8632Pinsr::emitIAS(const Cfg *Func) const { | 2525 template <> void InstX8632Pinsr::emitIAS(const Cfg *Func) const { |
| 2523 assert(getSrcSize() == 3); | 2526 assert(getSrcSize() == 3); |
| 2524 assert(getDest() == getSrc(0)); | 2527 assert(getDest() == getSrc(0)); |
| 2525 // pinsrb and pinsrd are SSE4.1 instructions. | 2528 // pinsrb and pinsrd are SSE4.1 instructions. |
| 2526 const Operand *Src0 = getSrc(1); | 2529 const Operand *Src0 = getSrc(1); |
| 2527 Type DispatchTy = Src0->getType(); | 2530 Type DispatchTy = Src0->getType(); |
| 2528 assert(DispatchTy == IceType_i16 || | 2531 assert(DispatchTy == IceType_i16 || |
| 2529 static_cast<TargetX8632 *>(Func->getTarget())->getInstructionSet() >= | 2532 static_cast<TargetX8632 *>(Func->getTarget())->getInstructionSet() >= |
| (...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2586 } | 2589 } |
| 2587 | 2590 |
| 2588 void InstX8632Pop::dump(const Cfg *Func) const { | 2591 void InstX8632Pop::dump(const Cfg *Func) const { |
| 2589 Ostream &Str = Func->getContext()->getStrDump(); | 2592 Ostream &Str = Func->getContext()->getStrDump(); |
| 2590 dumpDest(Func); | 2593 dumpDest(Func); |
| 2591 Str << " = pop." << getDest()->getType() << " "; | 2594 Str << " = pop." << getDest()->getType() << " "; |
| 2592 } | 2595 } |
| 2593 | 2596 |
| 2594 void InstX8632AdjustStack::emit(const Cfg *Func) const { | 2597 void InstX8632AdjustStack::emit(const Cfg *Func) const { |
| 2595 Ostream &Str = Func->getContext()->getStrEmit(); | 2598 Ostream &Str = Func->getContext()->getStrEmit(); |
| 2596 Str << "\tsub\tesp, " << Amount; | 2599 Str << "\tsubl\t$" << Amount << ", %esp"; |
| 2597 Func->getTarget()->updateStackAdjustment(Amount); | 2600 Func->getTarget()->updateStackAdjustment(Amount); |
| 2598 } | 2601 } |
| 2599 | 2602 |
| 2600 void InstX8632AdjustStack::emitIAS(const Cfg *Func) const { | 2603 void InstX8632AdjustStack::emitIAS(const Cfg *Func) const { |
| 2601 x86::AssemblerX86 *Asm = Func->getAssembler<x86::AssemblerX86>(); | 2604 x86::AssemblerX86 *Asm = Func->getAssembler<x86::AssemblerX86>(); |
| 2602 intptr_t StartPosition = Asm->GetPosition(); | 2605 intptr_t StartPosition = Asm->GetPosition(); |
| 2603 Asm->sub(IceType_i32, RegX8632::Encoded_Reg_esp, x86::Immediate(Amount)); | 2606 Asm->sub(IceType_i32, RegX8632::Encoded_Reg_esp, x86::Immediate(Amount)); |
| 2604 emitIASBytes(Func, Asm, StartPosition); | 2607 emitIASBytes(Func, Asm, StartPosition); |
| 2605 Func->getTarget()->updateStackAdjustment(Amount); | 2608 Func->getTarget()->updateStackAdjustment(Amount); |
| 2606 } | 2609 } |
| (...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2676 Type Ty = (getSrcSize() == 0 ? IceType_void : getSrc(0)->getType()); | 2679 Type Ty = (getSrcSize() == 0 ? IceType_void : getSrc(0)->getType()); |
| 2677 Str << "ret." << Ty << " "; | 2680 Str << "ret." << Ty << " "; |
| 2678 dumpSources(Func); | 2681 dumpSources(Func); |
| 2679 } | 2682 } |
| 2680 | 2683 |
| 2681 void InstX8632Xadd::emit(const Cfg *Func) const { | 2684 void InstX8632Xadd::emit(const Cfg *Func) const { |
| 2682 Ostream &Str = Func->getContext()->getStrEmit(); | 2685 Ostream &Str = Func->getContext()->getStrEmit(); |
| 2683 if (Locked) { | 2686 if (Locked) { |
| 2684 Str << "\tlock"; | 2687 Str << "\tlock"; |
| 2685 } | 2688 } |
| 2686 Str << "\txadd\t"; | 2689 Str << "\txadd" << getWidthString(getSrc(0)->getType()) << "\t"; |
| 2690 getSrc(1)->emit(Func); | |
| 2691 Str << ", "; | |
| 2687 getSrc(0)->emit(Func); | 2692 getSrc(0)->emit(Func); |
| 2688 Str << ", "; | |
| 2689 getSrc(1)->emit(Func); | |
| 2690 } | 2693 } |
| 2691 | 2694 |
| 2692 void InstX8632Xadd::emitIAS(const Cfg *Func) const { | 2695 void InstX8632Xadd::emitIAS(const Cfg *Func) const { |
| 2693 assert(getSrcSize() == 2); | 2696 assert(getSrcSize() == 2); |
| 2694 x86::AssemblerX86 *Asm = Func->getAssembler<x86::AssemblerX86>(); | 2697 x86::AssemblerX86 *Asm = Func->getAssembler<x86::AssemblerX86>(); |
| 2695 intptr_t StartPosition = Asm->GetPosition(); | 2698 intptr_t StartPosition = Asm->GetPosition(); |
| 2696 Type Ty = getSrc(0)->getType(); | 2699 Type Ty = getSrc(0)->getType(); |
| 2697 const OperandX8632Mem *Mem = llvm::cast<OperandX8632Mem>(getSrc(0)); | 2700 const OperandX8632Mem *Mem = llvm::cast<OperandX8632Mem>(getSrc(0)); |
| 2698 assert(Mem->getSegmentRegister() == OperandX8632Mem::DefaultSegment); | 2701 assert(Mem->getSegmentRegister() == OperandX8632Mem::DefaultSegment); |
| 2699 const x86::Address Addr = Mem->toAsmAddress(Asm); | 2702 const x86::Address Addr = Mem->toAsmAddress(Asm); |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2744 | 2747 |
| 2745 void InstX8632Xchg::dump(const Cfg *Func) const { | 2748 void InstX8632Xchg::dump(const Cfg *Func) const { |
| 2746 Ostream &Str = Func->getContext()->getStrDump(); | 2749 Ostream &Str = Func->getContext()->getStrDump(); |
| 2747 Type Ty = getSrc(0)->getType(); | 2750 Type Ty = getSrc(0)->getType(); |
| 2748 Str << "xchg." << Ty << " "; | 2751 Str << "xchg." << Ty << " "; |
| 2749 dumpSources(Func); | 2752 dumpSources(Func); |
| 2750 } | 2753 } |
| 2751 | 2754 |
| 2752 void OperandX8632Mem::emit(const Cfg *Func) const { | 2755 void OperandX8632Mem::emit(const Cfg *Func) const { |
| 2753 Ostream &Str = Func->getContext()->getStrEmit(); | 2756 Ostream &Str = Func->getContext()->getStrEmit(); |
| 2754 Str << TypeX8632Attributes[getType()].WidthString << " "; | |
| 2755 if (SegmentReg != DefaultSegment) { | 2757 if (SegmentReg != DefaultSegment) { |
| 2756 assert(SegmentReg >= 0 && SegmentReg < SegReg_NUM); | 2758 assert(SegmentReg >= 0 && SegmentReg < SegReg_NUM); |
| 2757 Str << InstX8632SegmentRegNames[SegmentReg] << ":"; | 2759 Str << InstX8632SegmentRegNames[SegmentReg] << ":"; |
| 2758 } | 2760 } |
| 2759 // TODO: The following is an almost verbatim paste of dump(). | 2761 // Emit as Offset(Base,Index,1<<Shift). |
| 2760 bool Dumped = false; | 2762 // Offset is emitted without the leading '$'. |
| 2761 Str << "["; | 2763 // Omit the (Base,Index,1<<Shift) part if Base==NULL. |
| 2764 if (Offset == NULL) { | |
| 2765 // No offset, emit nothing. | |
| 2766 } else if (auto CI = llvm::dyn_cast<ConstantInteger32>(Offset)) { | |
| 2767 if (CI->getValue()) | |
| 2768 // Emit a non-zero offset without a leading '$'. | |
| 2769 Str << CI->getValue(); | |
| 2770 } else if (auto CR = llvm::dyn_cast<ConstantRelocatable>(Offset)) { | |
| 2771 CR->emitWithoutDollar(Func->getContext()); | |
| 2772 } else { | |
| 2773 assert(0); | |
| 2774 } | |
| 2775 | |
| 2762 if (Base) { | 2776 if (Base) { |
| 2777 Str << "("; | |
| 2763 Base->emit(Func); | 2778 Base->emit(Func); |
| 2764 Dumped = true; | 2779 if (Index) { |
| 2780 Str << ","; | |
| 2781 Index->emit(Func); | |
| 2782 if (Shift) | |
| 2783 Str << "," << (1u << Shift); | |
| 2784 } | |
| 2785 Str << ")"; | |
| 2765 } | 2786 } |
| 2766 if (Index) { | |
| 2767 assert(Base); | |
| 2768 Str << "+"; | |
| 2769 if (Shift > 0) | |
| 2770 Str << (1u << Shift) << "*"; | |
| 2771 Index->emit(Func); | |
| 2772 Dumped = true; | |
| 2773 } | |
| 2774 // Pretty-print the Offset. | |
| 2775 bool OffsetIsZero = false; | |
| 2776 bool OffsetIsNegative = false; | |
| 2777 if (Offset == NULL) { | |
| 2778 OffsetIsZero = true; | |
| 2779 } else if (ConstantInteger32 *CI = | |
| 2780 llvm::dyn_cast<ConstantInteger32>(Offset)) { | |
| 2781 OffsetIsZero = (CI->getValue() == 0); | |
| 2782 OffsetIsNegative = (static_cast<int32_t>(CI->getValue()) < 0); | |
| 2783 } else { | |
| 2784 assert(llvm::isa<ConstantRelocatable>(Offset)); | |
| 2785 } | |
| 2786 if (Dumped) { | |
| 2787 if (!OffsetIsZero) { // Suppress if Offset is known to be 0 | |
| 2788 if (!OffsetIsNegative) // Suppress if Offset is known to be negative | |
| 2789 Str << "+"; | |
| 2790 Offset->emit(Func); | |
| 2791 } | |
| 2792 } else { | |
| 2793 // There is only the offset. | |
| 2794 Offset->emit(Func); | |
| 2795 } | |
| 2796 Str << "]"; | |
| 2797 } | 2787 } |
| 2798 | 2788 |
| 2799 void OperandX8632Mem::dump(const Cfg *Func, Ostream &Str) const { | 2789 void OperandX8632Mem::dump(const Cfg *Func, Ostream &Str) const { |
| 2800 if (SegmentReg != DefaultSegment) { | 2790 if (SegmentReg != DefaultSegment) { |
| 2801 assert(SegmentReg >= 0 && SegmentReg < SegReg_NUM); | 2791 assert(SegmentReg >= 0 && SegmentReg < SegReg_NUM); |
| 2802 Str << InstX8632SegmentRegNames[SegmentReg] << ":"; | 2792 Str << InstX8632SegmentRegNames[SegmentReg] << ":"; |
| 2803 } | 2793 } |
| 2804 bool Dumped = false; | 2794 bool Dumped = false; |
| 2805 Str << "["; | 2795 Str << "["; |
| 2806 if (Base) { | 2796 if (Base) { |
| (...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2896 return x86::Address(RegX8632::getEncodedGPR(Target->getFrameOrStackReg()), | 2886 return x86::Address(RegX8632::getEncodedGPR(Target->getFrameOrStackReg()), |
| 2897 Offset); | 2887 Offset); |
| 2898 } | 2888 } |
| 2899 | 2889 |
| 2900 void VariableSplit::emit(const Cfg *Func) const { | 2890 void VariableSplit::emit(const Cfg *Func) const { |
| 2901 Ostream &Str = Func->getContext()->getStrEmit(); | 2891 Ostream &Str = Func->getContext()->getStrEmit(); |
| 2902 assert(!Var->hasReg()); | 2892 assert(!Var->hasReg()); |
| 2903 // The following is copied/adapted from TargetX8632::emitVariable(). | 2893 // The following is copied/adapted from TargetX8632::emitVariable(). |
| 2904 const TargetLowering *Target = Func->getTarget(); | 2894 const TargetLowering *Target = Func->getTarget(); |
| 2905 const Type Ty = IceType_i32; | 2895 const Type Ty = IceType_i32; |
| 2906 Str << TypeX8632Attributes[Ty].WidthString << " [" | |
| 2907 << Target->getRegName(Target->getFrameOrStackReg(), Ty); | |
| 2908 int32_t Offset = | 2896 int32_t Offset = |
| 2909 Var->getStackOffset() + Target->getStackAdjustment() + getOffset(); | 2897 Var->getStackOffset() + Target->getStackAdjustment() + getOffset(); |
| 2910 if (Offset) { | 2898 if (Offset) |
| 2911 if (Offset > 0) | |
| 2912 Str << "+"; | |
| 2913 Str << Offset; | 2899 Str << Offset; |
| 2914 } | 2900 Str << "(%" << Target->getRegName(Target->getFrameOrStackReg(), Ty) << ")"; |
| 2915 Str << "]"; | |
| 2916 } | 2901 } |
| 2917 | 2902 |
| 2918 void VariableSplit::dump(const Cfg *Func, Ostream &Str) const { | 2903 void VariableSplit::dump(const Cfg *Func, Ostream &Str) const { |
| 2919 switch (Part) { | 2904 switch (Part) { |
| 2920 case Low: | 2905 case Low: |
| 2921 Str << "low"; | 2906 Str << "low"; |
| 2922 break; | 2907 break; |
| 2923 case High: | 2908 case High: |
| 2924 Str << "high"; | 2909 Str << "high"; |
| 2925 break; | 2910 break; |
| 2926 default: | 2911 default: |
| 2927 Str << "???"; | 2912 Str << "???"; |
| 2928 break; | 2913 break; |
| 2929 } | 2914 } |
| 2930 Str << "("; | 2915 Str << "("; |
| 2931 if (Func) | 2916 if (Func) |
| 2932 Var->dump(Func); | 2917 Var->dump(Func); |
| 2933 else | 2918 else |
| 2934 Var->dump(Str); | 2919 Var->dump(Str); |
| 2935 Str << ")"; | 2920 Str << ")"; |
| 2936 } | 2921 } |
| 2937 | 2922 |
| 2938 } // end of namespace Ice | 2923 } // end of namespace Ice |
| OLD | NEW |