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 429 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 52 matching lines...) Expand 10 before | Expand all | Expand 10 after 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); |
| 2050 // The llvm-mc assembler using Intel syntax has a bug in which "mov | 2067 Type SrcTy = Src->getType(); |
| 2051 // reg, RelocatableConstant" does not generate the right instruction | 2068 Type DestTy = getDest()->getType(); |
| 2052 // with a relocation. To work around, we emit "lea reg, | 2069 Str << "\tmov" << (!isScalarFloatingType(DestTy) |
| 2053 // RelocatableConstant". Also, the lowering and legalization is | 2070 ? getWidthString(SrcTy) |
| 2054 // changed to allow relocatable constants only in Assign and Call | 2071 : TypeX8632Attributes[DestTy].SdSsString) << "\t"; |
| 2055 // instructions or in Mem operands. TODO(stichnot): remove LEAHACK | |
| 2056 // once a proper emitter is used. | |
| 2057 // | |
| 2058 // In addition, llvm-mc doesn't like "lea eax, bp" or "lea eax, Sp" | |
| 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. | 2072 // For an integer truncation operation, src is wider than dest. |
| 2071 // Ideally, we use a mov instruction whose data width matches the | 2073 // 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 | 2074 // 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 | 2075 // 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 | 2076 // safe, we instead widen the dest to match src. This works even |
| 2075 // for stack-allocated dest variables because typeWidthOnStack() | 2077 // for stack-allocated dest variables because typeWidthOnStack() |
| 2076 // pads to a 4-byte boundary even if only a lower portion is used. | 2078 // 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 | 2079 // TODO: This assert disallows usages such as copying a floating point |
| 2078 // value between a vector and a scalar (which movss is used for). | 2080 // value between a vector and a scalar (which movss is used for). |
| 2079 // Clean this up. | 2081 // Clean this up. |
| 2080 assert(Func->getTarget()->typeWidthInBytesOnStack(getDest()->getType()) == | 2082 assert(Func->getTarget()->typeWidthInBytesOnStack(DestTy) == |
| 2081 Func->getTarget()->typeWidthInBytesOnStack(Src->getType())); | 2083 Func->getTarget()->typeWidthInBytesOnStack(SrcTy)); |
| 2082 if (UseLeaHack) { | 2084 Src->emit(Func); |
| 2083 Src->emit(Func); | 2085 Str << ", "; |
| 2084 Str << ", %"; | 2086 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 } | 2087 } |
| 2094 | 2088 |
| 2095 template <> void InstX8632Mov::emitIAS(const Cfg *Func) const { | 2089 template <> void InstX8632Mov::emitIAS(const Cfg *Func) const { |
| 2096 assert(getSrcSize() == 1); | 2090 assert(getSrcSize() == 1); |
| 2097 const Variable *Dest = getDest(); | 2091 const Variable *Dest = getDest(); |
| 2098 const Operand *Src = getSrc(0); | 2092 const Operand *Src = getSrc(0); |
| 2099 Type DestTy = Dest->getType(); | 2093 Type DestTy = Dest->getType(); |
| 2100 Type SrcTy = Src->getType(); | 2094 Type SrcTy = Src->getType(); |
| 2101 // Mov can be used for GPRs or XMM registers. Also, the type does not | 2095 // 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 | 2096 // necessarily match (Mov can be used for bitcasts). However, when |
| (...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2199 } | 2193 } |
| 2200 | 2194 |
| 2201 template <> void InstX8632Movp::emit(const Cfg *Func) const { | 2195 template <> void InstX8632Movp::emit(const Cfg *Func) const { |
| 2202 // TODO(wala,stichnot): movups works with all vector operands, but | 2196 // TODO(wala,stichnot): movups works with all vector operands, but |
| 2203 // there exist other instructions (movaps, movdqa, movdqu) that may | 2197 // there exist other instructions (movaps, movdqa, movdqu) that may |
| 2204 // perform better, depending on the data type and alignment of the | 2198 // perform better, depending on the data type and alignment of the |
| 2205 // operands. | 2199 // operands. |
| 2206 Ostream &Str = Func->getContext()->getStrEmit(); | 2200 Ostream &Str = Func->getContext()->getStrEmit(); |
| 2207 assert(getSrcSize() == 1); | 2201 assert(getSrcSize() == 1); |
| 2208 Str << "\tmovups\t"; | 2202 Str << "\tmovups\t"; |
| 2203 getSrc(0)->emit(Func); | |
| 2204 Str << ", "; | |
| 2209 getDest()->emit(Func); | 2205 getDest()->emit(Func); |
| 2210 Str << ", "; | |
| 2211 getSrc(0)->emit(Func); | |
| 2212 } | 2206 } |
| 2213 | 2207 |
| 2214 template <> void InstX8632Movp::emitIAS(const Cfg *Func) const { | 2208 template <> void InstX8632Movp::emitIAS(const Cfg *Func) const { |
| 2215 assert(getSrcSize() == 1); | 2209 assert(getSrcSize() == 1); |
| 2216 assert(isVectorType(getDest()->getType())); | 2210 assert(isVectorType(getDest()->getType())); |
| 2217 const Variable *Dest = getDest(); | 2211 const Variable *Dest = getDest(); |
| 2218 const Operand *Src = getSrc(0); | 2212 const Operand *Src = getSrc(0); |
| 2219 const static x86::AssemblerX86::XmmEmitterMovOps Emitter = { | 2213 const static x86::AssemblerX86::XmmEmitterMovOps Emitter = { |
| 2220 &x86::AssemblerX86::movups, &x86::AssemblerX86::movups, | 2214 &x86::AssemblerX86::movups, &x86::AssemblerX86::movups, |
| 2221 &x86::AssemblerX86::movups | 2215 &x86::AssemblerX86::movups |
| 2222 }; | 2216 }; |
| 2223 emitIASMovlikeXMM(Func, Dest, Src, Emitter); | 2217 emitIASMovlikeXMM(Func, Dest, Src, Emitter); |
| 2224 } | 2218 } |
| 2225 | 2219 |
| 2226 template <> void InstX8632Movq::emit(const Cfg *Func) const { | 2220 template <> void InstX8632Movq::emit(const Cfg *Func) const { |
| 2227 Ostream &Str = Func->getContext()->getStrEmit(); | 2221 Ostream &Str = Func->getContext()->getStrEmit(); |
| 2228 assert(getSrcSize() == 1); | 2222 assert(getSrcSize() == 1); |
| 2229 assert(getDest()->getType() == IceType_i64 || | 2223 assert(getDest()->getType() == IceType_i64 || |
| 2230 getDest()->getType() == IceType_f64); | 2224 getDest()->getType() == IceType_f64); |
| 2231 Str << "\tmovq\t"; | 2225 Str << "\tmovq\t"; |
| 2226 getSrc(0)->emit(Func); | |
| 2227 Str << ", "; | |
| 2232 getDest()->emit(Func); | 2228 getDest()->emit(Func); |
| 2233 Str << ", "; | |
| 2234 getSrc(0)->emit(Func); | |
| 2235 } | 2229 } |
| 2236 | 2230 |
| 2237 template <> void InstX8632Movq::emitIAS(const Cfg *Func) const { | 2231 template <> void InstX8632Movq::emitIAS(const Cfg *Func) const { |
| 2238 assert(getSrcSize() == 1); | 2232 assert(getSrcSize() == 1); |
| 2239 assert(getDest()->getType() == IceType_i64 || | 2233 assert(getDest()->getType() == IceType_i64 || |
| 2240 getDest()->getType() == IceType_f64); | 2234 getDest()->getType() == IceType_f64); |
| 2241 const Variable *Dest = getDest(); | 2235 const Variable *Dest = getDest(); |
| 2242 const Operand *Src = getSrc(0); | 2236 const Operand *Src = getSrc(0); |
| 2243 const static x86::AssemblerX86::XmmEmitterMovOps Emitter = { | 2237 const static x86::AssemblerX86::XmmEmitterMovOps Emitter = { |
| 2244 &x86::AssemblerX86::movq, &x86::AssemblerX86::movq, &x86::AssemblerX86::movq | 2238 &x86::AssemblerX86::movq, &x86::AssemblerX86::movq, &x86::AssemblerX86::movq |
| (...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2300 | 2294 |
| 2301 void InstX8632Nop::dump(const Cfg *Func) const { | 2295 void InstX8632Nop::dump(const Cfg *Func) const { |
| 2302 Ostream &Str = Func->getContext()->getStrDump(); | 2296 Ostream &Str = Func->getContext()->getStrDump(); |
| 2303 Str << "nop (variant = " << Variant << ")"; | 2297 Str << "nop (variant = " << Variant << ")"; |
| 2304 } | 2298 } |
| 2305 | 2299 |
| 2306 void InstX8632Fld::emit(const Cfg *Func) const { | 2300 void InstX8632Fld::emit(const Cfg *Func) const { |
| 2307 Ostream &Str = Func->getContext()->getStrEmit(); | 2301 Ostream &Str = Func->getContext()->getStrEmit(); |
| 2308 assert(getSrcSize() == 1); | 2302 assert(getSrcSize() == 1); |
| 2309 Type Ty = getSrc(0)->getType(); | 2303 Type Ty = getSrc(0)->getType(); |
| 2304 SizeT Width = typeWidthInBytes(Ty); | |
| 2310 Variable *Var = llvm::dyn_cast<Variable>(getSrc(0)); | 2305 Variable *Var = llvm::dyn_cast<Variable>(getSrc(0)); |
| 2311 if (Var && Var->hasReg()) { | 2306 if (Var && Var->hasReg()) { |
| 2312 // This is a physical xmm register, so we need to spill it to a | 2307 // This is a physical xmm register, so we need to spill it to a |
| 2313 // temporary stack slot. | 2308 // temporary stack slot. |
| 2314 SizeT Width = typeWidthInBytes(Ty); | 2309 Str << "\tsubl\t$" << Width << ", %esp" |
| 2315 Str << "\tsub\tesp, " << Width << "\n"; | 2310 << "\n"; |
|
jvoung (off chromium)
2014/10/31 22:12:18
\n could fit on the previous line next to %esp
Jim Stichnoth
2014/11/01 13:44:17
Done.
| |
| 2316 Str << "\tmov" << TypeX8632Attributes[Ty].SdSsString << "\t" | 2311 Str << "\tmov" << TypeX8632Attributes[Ty].SdSsString << "\t"; |
| 2317 << TypeX8632Attributes[Ty].WidthString << " [esp], "; | |
| 2318 Var->emit(Func); | 2312 Var->emit(Func); |
| 2319 Str << "\n"; | 2313 Str << ", (%esp)\n"; |
| 2320 Str << "\tfld\t" << TypeX8632Attributes[Ty].WidthString << " [esp]\n"; | 2314 Str << "\tfld" << getFldString(Ty) << "\t" |
| 2321 Str << "\tadd\tesp, " << Width; | 2315 << "(%esp)\n"; |
| 2316 Str << "\taddl\t$" << Width << ", %esp"; | |
| 2322 return; | 2317 return; |
| 2323 } | 2318 } |
| 2324 Str << "\tfld\t"; | 2319 Str << "\tfld" << getFldString(Ty) << "\t"; |
| 2325 getSrc(0)->emit(Func); | 2320 getSrc(0)->emit(Func); |
| 2326 } | 2321 } |
| 2327 | 2322 |
| 2328 void InstX8632Fld::emitIAS(const Cfg *Func) const { | 2323 void InstX8632Fld::emitIAS(const Cfg *Func) const { |
| 2329 x86::AssemblerX86 *Asm = Func->getAssembler<x86::AssemblerX86>(); | 2324 x86::AssemblerX86 *Asm = Func->getAssembler<x86::AssemblerX86>(); |
| 2330 intptr_t StartPosition = Asm->GetPosition(); | 2325 intptr_t StartPosition = Asm->GetPosition(); |
| 2331 assert(getSrcSize() == 1); | 2326 assert(getSrcSize() == 1); |
| 2332 const Operand *Src = getSrc(0); | 2327 const Operand *Src = getSrc(0); |
| 2333 Type Ty = Src->getType(); | 2328 Type Ty = Src->getType(); |
| 2334 if (const auto Var = llvm::dyn_cast<Variable>(Src)) { | 2329 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(); | 2362 Ostream &Str = Func->getContext()->getStrEmit(); |
| 2368 assert(getSrcSize() == 0); | 2363 assert(getSrcSize() == 0); |
| 2369 // TODO(jvoung,stichnot): Utilize this by setting Dest to NULL to | 2364 // TODO(jvoung,stichnot): Utilize this by setting Dest to NULL to |
| 2370 // "partially" delete the fstp if the Dest is unused. | 2365 // "partially" delete the fstp if the Dest is unused. |
| 2371 // Even if Dest is unused, the fstp should be kept for the SideEffects | 2366 // Even if Dest is unused, the fstp should be kept for the SideEffects |
| 2372 // of popping the stack. | 2367 // of popping the stack. |
| 2373 if (getDest() == NULL) { | 2368 if (getDest() == NULL) { |
| 2374 Str << "\tfstp\tst(0)"; | 2369 Str << "\tfstp\tst(0)"; |
| 2375 return; | 2370 return; |
| 2376 } | 2371 } |
| 2372 Type Ty = getDest()->getType(); | |
| 2373 size_t Width = typeWidthInBytes(Ty); | |
| 2377 if (!getDest()->hasReg()) { | 2374 if (!getDest()->hasReg()) { |
| 2378 Str << "\tfstp\t"; | 2375 Str << "\tfstp" << getFldString(Ty) << "\t"; |
| 2379 getDest()->emit(Func); | 2376 getDest()->emit(Func); |
| 2380 return; | 2377 return; |
| 2381 } | 2378 } |
| 2382 // Dest is a physical (xmm) register, so st(0) needs to go through | 2379 // Dest is a physical (xmm) register, so st(0) needs to go through |
| 2383 // memory. Hack this by creating a temporary stack slot, spilling | 2380 // memory. Hack this by creating a temporary stack slot, spilling |
| 2384 // st(0) there, loading it into the xmm register, and deallocating | 2381 // st(0) there, loading it into the xmm register, and deallocating |
| 2385 // the stack slot. | 2382 // the stack slot. |
| 2386 Type Ty = getDest()->getType(); | 2383 Str << "\tsubl\t$" << Width << ", %esp\n"; |
| 2387 size_t Width = typeWidthInBytes(Ty); | 2384 Str << "\tfstp" << getFldString(Ty) << "\t" |
| 2388 Str << "\tsub\tesp, " << Width << "\n"; | 2385 << "(%esp)\n"; |
|
jvoung (off chromium)
2014/10/31 22:12:18
nit: Could do the full fstp on one line like befor
Jim Stichnoth
2014/11/01 13:44:17
Done.
| |
| 2389 Str << "\tfstp\t" << TypeX8632Attributes[Ty].WidthString << " [esp]\n"; | 2386 Str << "\tmov" << TypeX8632Attributes[Ty].SdSsString << "\t" |
| 2390 Str << "\tmov" << TypeX8632Attributes[Ty].SdSsString << "\t"; | 2387 << "(%esp), "; |
| 2391 getDest()->emit(Func); | 2388 getDest()->emit(Func); |
| 2392 Str << ", " << TypeX8632Attributes[Ty].WidthString << " [esp]\n"; | 2389 Str << "\n"; |
| 2393 Str << "\tadd\tesp, " << Width; | 2390 Str << "\taddl\t$" << Width << ", %esp"; |
| 2394 } | 2391 } |
| 2395 | 2392 |
| 2396 void InstX8632Fstp::emitIAS(const Cfg *Func) const { | 2393 void InstX8632Fstp::emitIAS(const Cfg *Func) const { |
| 2397 x86::AssemblerX86 *Asm = Func->getAssembler<x86::AssemblerX86>(); | 2394 x86::AssemblerX86 *Asm = Func->getAssembler<x86::AssemblerX86>(); |
| 2398 intptr_t StartPosition = Asm->GetPosition(); | 2395 intptr_t StartPosition = Asm->GetPosition(); |
| 2399 assert(getSrcSize() == 0); | 2396 assert(getSrcSize() == 0); |
| 2400 const Variable *Dest = getDest(); | 2397 const Variable *Dest = getDest(); |
| 2401 // TODO(jvoung,stichnot): Utilize this by setting Dest to NULL to | 2398 // TODO(jvoung,stichnot): Utilize this by setting Dest to NULL to |
| 2402 // "partially" delete the fstp if the Dest is unused. | 2399 // "partially" delete the fstp if the Dest is unused. |
| 2403 // Even if Dest is unused, the fstp should be kept for the SideEffects | 2400 // 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 { | 2448 template <> void InstX8632Pextr::emit(const Cfg *Func) const { |
| 2452 Ostream &Str = Func->getContext()->getStrEmit(); | 2449 Ostream &Str = Func->getContext()->getStrEmit(); |
| 2453 assert(getSrcSize() == 2); | 2450 assert(getSrcSize() == 2); |
| 2454 // pextrb and pextrd are SSE4.1 instructions. | 2451 // pextrb and pextrd are SSE4.1 instructions. |
| 2455 assert(getSrc(0)->getType() == IceType_v8i16 || | 2452 assert(getSrc(0)->getType() == IceType_v8i16 || |
| 2456 getSrc(0)->getType() == IceType_v8i1 || | 2453 getSrc(0)->getType() == IceType_v8i1 || |
| 2457 static_cast<TargetX8632 *>(Func->getTarget())->getInstructionSet() | 2454 static_cast<TargetX8632 *>(Func->getTarget())->getInstructionSet() |
| 2458 >= TargetX8632::SSE4_1); | 2455 >= TargetX8632::SSE4_1); |
| 2459 Str << "\t" << Opcode | 2456 Str << "\t" << Opcode |
| 2460 << TypeX8632Attributes[getSrc(0)->getType()].PackString << "\t"; | 2457 << TypeX8632Attributes[getSrc(0)->getType()].PackString << "\t"; |
| 2458 getSrc(1)->emit(Func); | |
| 2459 Str << ", "; | |
| 2460 getSrc(0)->emit(Func); | |
| 2461 Str << ", "; | |
| 2461 Variable *Dest = getDest(); | 2462 Variable *Dest = getDest(); |
| 2462 // pextrw must take a register dest. There is an SSE4.1 version that takes | 2463 // 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 | 2464 // a memory dest, but we aren't using it. For uniformity, just restrict |
| 2464 // them all to have a register dest for now. | 2465 // them all to have a register dest for now. |
| 2465 assert(Dest->hasReg()); | 2466 assert(Dest->hasReg()); |
| 2466 Dest->asType(IceType_i32).emit(Func); | 2467 Dest->asType(IceType_i32).emit(Func); |
| 2467 Str << ", "; | |
| 2468 getSrc(0)->emit(Func); | |
| 2469 Str << ", "; | |
| 2470 getSrc(1)->emit(Func); | |
| 2471 } | 2468 } |
| 2472 | 2469 |
| 2473 template <> void InstX8632Pextr::emitIAS(const Cfg *Func) const { | 2470 template <> void InstX8632Pextr::emitIAS(const Cfg *Func) const { |
| 2474 assert(getSrcSize() == 2); | 2471 assert(getSrcSize() == 2); |
| 2475 // pextrb and pextrd are SSE4.1 instructions. | 2472 // pextrb and pextrd are SSE4.1 instructions. |
| 2476 const Variable *Dest = getDest(); | 2473 const Variable *Dest = getDest(); |
| 2477 Type DispatchTy = Dest->getType(); | 2474 Type DispatchTy = Dest->getType(); |
| 2478 assert(DispatchTy == IceType_i16 || | 2475 assert(DispatchTy == IceType_i16 || |
| 2479 static_cast<TargetX8632 *>(Func->getTarget())->getInstructionSet() >= | 2476 static_cast<TargetX8632 *>(Func->getTarget())->getInstructionSet() >= |
| 2480 TargetX8632::SSE4_1); | 2477 TargetX8632::SSE4_1); |
| (...skipping 14 matching lines...) Expand all Loading... | |
| 2495 template <> void InstX8632Pinsr::emit(const Cfg *Func) const { | 2492 template <> void InstX8632Pinsr::emit(const Cfg *Func) const { |
| 2496 Ostream &Str = Func->getContext()->getStrEmit(); | 2493 Ostream &Str = Func->getContext()->getStrEmit(); |
| 2497 assert(getSrcSize() == 3); | 2494 assert(getSrcSize() == 3); |
| 2498 // pinsrb and pinsrd are SSE4.1 instructions. | 2495 // pinsrb and pinsrd are SSE4.1 instructions. |
| 2499 assert(getDest()->getType() == IceType_v8i16 || | 2496 assert(getDest()->getType() == IceType_v8i16 || |
| 2500 getDest()->getType() == IceType_v8i1 || | 2497 getDest()->getType() == IceType_v8i1 || |
| 2501 static_cast<TargetX8632 *>(Func->getTarget())->getInstructionSet() | 2498 static_cast<TargetX8632 *>(Func->getTarget())->getInstructionSet() |
| 2502 >= TargetX8632::SSE4_1); | 2499 >= TargetX8632::SSE4_1); |
| 2503 Str << "\t" << Opcode | 2500 Str << "\t" << Opcode |
| 2504 << TypeX8632Attributes[getDest()->getType()].PackString << "\t"; | 2501 << TypeX8632Attributes[getDest()->getType()].PackString << "\t"; |
| 2505 getDest()->emit(Func); | 2502 getSrc(2)->emit(Func); |
| 2506 Str << ", "; | 2503 Str << ", "; |
| 2507 Operand *Src1 = getSrc(1); | 2504 Operand *Src1 = getSrc(1); |
| 2508 if (Variable *VSrc1 = llvm::dyn_cast<Variable>(Src1)) { | 2505 if (Variable *VSrc1 = llvm::dyn_cast<Variable>(Src1)) { |
| 2509 // If src1 is a register, it should always be r32. | 2506 // If src1 is a register, it should always be r32. |
| 2510 if (VSrc1->hasReg()) { | 2507 if (VSrc1->hasReg()) { |
| 2511 VSrc1->asType(IceType_i32).emit(Func); | 2508 VSrc1->asType(IceType_i32).emit(Func); |
| 2512 } else { | 2509 } else { |
| 2513 VSrc1->emit(Func); | 2510 VSrc1->emit(Func); |
| 2514 } | 2511 } |
| 2515 } else { | 2512 } else { |
| 2516 Src1->emit(Func); | 2513 Src1->emit(Func); |
| 2517 } | 2514 } |
| 2518 Str << ", "; | 2515 Str << ", "; |
| 2519 getSrc(2)->emit(Func); | 2516 getDest()->emit(Func); |
| 2520 } | 2517 } |
| 2521 | 2518 |
| 2522 template <> void InstX8632Pinsr::emitIAS(const Cfg *Func) const { | 2519 template <> void InstX8632Pinsr::emitIAS(const Cfg *Func) const { |
| 2523 assert(getSrcSize() == 3); | 2520 assert(getSrcSize() == 3); |
| 2524 assert(getDest() == getSrc(0)); | 2521 assert(getDest() == getSrc(0)); |
| 2525 // pinsrb and pinsrd are SSE4.1 instructions. | 2522 // pinsrb and pinsrd are SSE4.1 instructions. |
| 2526 const Operand *Src0 = getSrc(1); | 2523 const Operand *Src0 = getSrc(1); |
| 2527 Type DispatchTy = Src0->getType(); | 2524 Type DispatchTy = Src0->getType(); |
| 2528 assert(DispatchTy == IceType_i16 || | 2525 assert(DispatchTy == IceType_i16 || |
| 2529 static_cast<TargetX8632 *>(Func->getTarget())->getInstructionSet() >= | 2526 static_cast<TargetX8632 *>(Func->getTarget())->getInstructionSet() >= |
| (...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2586 } | 2583 } |
| 2587 | 2584 |
| 2588 void InstX8632Pop::dump(const Cfg *Func) const { | 2585 void InstX8632Pop::dump(const Cfg *Func) const { |
| 2589 Ostream &Str = Func->getContext()->getStrDump(); | 2586 Ostream &Str = Func->getContext()->getStrDump(); |
| 2590 dumpDest(Func); | 2587 dumpDest(Func); |
| 2591 Str << " = pop." << getDest()->getType() << " "; | 2588 Str << " = pop." << getDest()->getType() << " "; |
| 2592 } | 2589 } |
| 2593 | 2590 |
| 2594 void InstX8632AdjustStack::emit(const Cfg *Func) const { | 2591 void InstX8632AdjustStack::emit(const Cfg *Func) const { |
| 2595 Ostream &Str = Func->getContext()->getStrEmit(); | 2592 Ostream &Str = Func->getContext()->getStrEmit(); |
| 2596 Str << "\tsub\tesp, " << Amount; | 2593 Str << "\tsubl\t$" << Amount << ", %esp"; |
| 2597 Func->getTarget()->updateStackAdjustment(Amount); | 2594 Func->getTarget()->updateStackAdjustment(Amount); |
| 2598 } | 2595 } |
| 2599 | 2596 |
| 2600 void InstX8632AdjustStack::emitIAS(const Cfg *Func) const { | 2597 void InstX8632AdjustStack::emitIAS(const Cfg *Func) const { |
| 2601 x86::AssemblerX86 *Asm = Func->getAssembler<x86::AssemblerX86>(); | 2598 x86::AssemblerX86 *Asm = Func->getAssembler<x86::AssemblerX86>(); |
| 2602 intptr_t StartPosition = Asm->GetPosition(); | 2599 intptr_t StartPosition = Asm->GetPosition(); |
| 2603 Asm->sub(IceType_i32, RegX8632::Encoded_Reg_esp, x86::Immediate(Amount)); | 2600 Asm->sub(IceType_i32, RegX8632::Encoded_Reg_esp, x86::Immediate(Amount)); |
| 2604 emitIASBytes(Func, Asm, StartPosition); | 2601 emitIASBytes(Func, Asm, StartPosition); |
| 2605 Func->getTarget()->updateStackAdjustment(Amount); | 2602 Func->getTarget()->updateStackAdjustment(Amount); |
| 2606 } | 2603 } |
| (...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2676 Type Ty = (getSrcSize() == 0 ? IceType_void : getSrc(0)->getType()); | 2673 Type Ty = (getSrcSize() == 0 ? IceType_void : getSrc(0)->getType()); |
| 2677 Str << "ret." << Ty << " "; | 2674 Str << "ret." << Ty << " "; |
| 2678 dumpSources(Func); | 2675 dumpSources(Func); |
| 2679 } | 2676 } |
| 2680 | 2677 |
| 2681 void InstX8632Xadd::emit(const Cfg *Func) const { | 2678 void InstX8632Xadd::emit(const Cfg *Func) const { |
| 2682 Ostream &Str = Func->getContext()->getStrEmit(); | 2679 Ostream &Str = Func->getContext()->getStrEmit(); |
| 2683 if (Locked) { | 2680 if (Locked) { |
| 2684 Str << "\tlock"; | 2681 Str << "\tlock"; |
| 2685 } | 2682 } |
| 2686 Str << "\txadd\t"; | 2683 Str << "\txadd" << getWidthString(getSrc(0)->getType()) << "\t"; |
| 2684 getSrc(1)->emit(Func); | |
| 2685 Str << ", "; | |
| 2687 getSrc(0)->emit(Func); | 2686 getSrc(0)->emit(Func); |
| 2688 Str << ", "; | |
| 2689 getSrc(1)->emit(Func); | |
| 2690 } | 2687 } |
| 2691 | 2688 |
| 2692 void InstX8632Xadd::emitIAS(const Cfg *Func) const { | 2689 void InstX8632Xadd::emitIAS(const Cfg *Func) const { |
| 2693 assert(getSrcSize() == 2); | 2690 assert(getSrcSize() == 2); |
| 2694 x86::AssemblerX86 *Asm = Func->getAssembler<x86::AssemblerX86>(); | 2691 x86::AssemblerX86 *Asm = Func->getAssembler<x86::AssemblerX86>(); |
| 2695 intptr_t StartPosition = Asm->GetPosition(); | 2692 intptr_t StartPosition = Asm->GetPosition(); |
| 2696 Type Ty = getSrc(0)->getType(); | 2693 Type Ty = getSrc(0)->getType(); |
| 2697 const OperandX8632Mem *Mem = llvm::cast<OperandX8632Mem>(getSrc(0)); | 2694 const OperandX8632Mem *Mem = llvm::cast<OperandX8632Mem>(getSrc(0)); |
| 2698 assert(Mem->getSegmentRegister() == OperandX8632Mem::DefaultSegment); | 2695 assert(Mem->getSegmentRegister() == OperandX8632Mem::DefaultSegment); |
| 2699 const x86::Address Addr = Mem->toAsmAddress(Asm); | 2696 const x86::Address Addr = Mem->toAsmAddress(Asm); |
| (...skipping 13 matching lines...) Expand all Loading... | |
| 2713 if (Locked) { | 2710 if (Locked) { |
| 2714 Str << "lock "; | 2711 Str << "lock "; |
| 2715 } | 2712 } |
| 2716 Type Ty = getSrc(0)->getType(); | 2713 Type Ty = getSrc(0)->getType(); |
| 2717 Str << "xadd." << Ty << " "; | 2714 Str << "xadd." << Ty << " "; |
| 2718 dumpSources(Func); | 2715 dumpSources(Func); |
| 2719 } | 2716 } |
| 2720 | 2717 |
| 2721 void InstX8632Xchg::emit(const Cfg *Func) const { | 2718 void InstX8632Xchg::emit(const Cfg *Func) const { |
| 2722 Ostream &Str = Func->getContext()->getStrEmit(); | 2719 Ostream &Str = Func->getContext()->getStrEmit(); |
| 2723 Str << "\txchg\t"; | 2720 Str << "\txchg\t"; |
|
jvoung (off chromium)
2014/10/31 22:12:18
I'm surprised this doesn't have the getWidthString
Jim Stichnoth
2014/11/01 13:44:16
Good point. It turns out that for both llvm-mc an
| |
| 2721 getSrc(1)->emit(Func); | |
| 2722 Str << ", "; | |
| 2724 getSrc(0)->emit(Func); | 2723 getSrc(0)->emit(Func); |
| 2725 Str << ", "; | |
| 2726 getSrc(1)->emit(Func); | |
| 2727 } | 2724 } |
| 2728 | 2725 |
| 2729 void InstX8632Xchg::emitIAS(const Cfg *Func) const { | 2726 void InstX8632Xchg::emitIAS(const Cfg *Func) const { |
| 2730 assert(getSrcSize() == 2); | 2727 assert(getSrcSize() == 2); |
| 2731 x86::AssemblerX86 *Asm = Func->getAssembler<x86::AssemblerX86>(); | 2728 x86::AssemblerX86 *Asm = Func->getAssembler<x86::AssemblerX86>(); |
| 2732 intptr_t StartPosition = Asm->GetPosition(); | 2729 intptr_t StartPosition = Asm->GetPosition(); |
| 2733 Type Ty = getSrc(0)->getType(); | 2730 Type Ty = getSrc(0)->getType(); |
| 2734 const OperandX8632Mem *Mem = llvm::cast<OperandX8632Mem>(getSrc(0)); | 2731 const OperandX8632Mem *Mem = llvm::cast<OperandX8632Mem>(getSrc(0)); |
| 2735 assert(Mem->getSegmentRegister() == OperandX8632Mem::DefaultSegment); | 2732 assert(Mem->getSegmentRegister() == OperandX8632Mem::DefaultSegment); |
| 2736 const x86::Address Addr = Mem->toAsmAddress(Asm); | 2733 const x86::Address Addr = Mem->toAsmAddress(Asm); |
| 2737 const Variable *VarReg = llvm::cast<Variable>(getSrc(1)); | 2734 const Variable *VarReg = llvm::cast<Variable>(getSrc(1)); |
| 2738 assert(VarReg->hasReg()); | 2735 assert(VarReg->hasReg()); |
| 2739 const RegX8632::GPRRegister Reg = | 2736 const RegX8632::GPRRegister Reg = |
| 2740 RegX8632::getEncodedGPR(VarReg->getRegNum()); | 2737 RegX8632::getEncodedGPR(VarReg->getRegNum()); |
| 2741 Asm->xchg(Ty, Addr, Reg); | 2738 Asm->xchg(Ty, Addr, Reg); |
| 2742 emitIASBytes(Func, Asm, StartPosition); | 2739 emitIASBytes(Func, Asm, StartPosition); |
| 2743 } | 2740 } |
| 2744 | 2741 |
| 2745 void InstX8632Xchg::dump(const Cfg *Func) const { | 2742 void InstX8632Xchg::dump(const Cfg *Func) const { |
| 2746 Ostream &Str = Func->getContext()->getStrDump(); | 2743 Ostream &Str = Func->getContext()->getStrDump(); |
| 2747 Type Ty = getSrc(0)->getType(); | 2744 Type Ty = getSrc(0)->getType(); |
| 2748 Str << "xchg." << Ty << " "; | 2745 Str << "xchg." << Ty << " "; |
| 2749 dumpSources(Func); | 2746 dumpSources(Func); |
| 2750 } | 2747 } |
| 2751 | 2748 |
| 2752 void OperandX8632Mem::emit(const Cfg *Func) const { | 2749 void OperandX8632Mem::emit(const Cfg *Func) const { |
| 2753 Ostream &Str = Func->getContext()->getStrEmit(); | 2750 Ostream &Str = Func->getContext()->getStrEmit(); |
| 2754 Str << TypeX8632Attributes[getType()].WidthString << " "; | |
| 2755 if (SegmentReg != DefaultSegment) { | 2751 if (SegmentReg != DefaultSegment) { |
| 2756 assert(SegmentReg >= 0 && SegmentReg < SegReg_NUM); | 2752 assert(SegmentReg >= 0 && SegmentReg < SegReg_NUM); |
| 2757 Str << InstX8632SegmentRegNames[SegmentReg] << ":"; | 2753 Str << InstX8632SegmentRegNames[SegmentReg] << ":"; |
| 2758 } | 2754 } |
| 2759 // TODO: The following is an almost verbatim paste of dump(). | 2755 // Emit as Offset(Base,Index,1<<Shift). |
| 2760 bool Dumped = false; | 2756 // Offset is emitted without the leading '$'. |
| 2761 Str << "["; | 2757 // Omit the (Base,Index,1<<Shift) part if Base==NULL. |
| 2758 if (Offset == NULL) { | |
| 2759 // No offset, emit nothing. | |
| 2760 } else if (auto CI = llvm::dyn_cast<ConstantInteger32>(Offset)) { | |
| 2761 if (CI->getValue()) | |
| 2762 // Emit a non-zero offset without a leading '$'. | |
| 2763 Str << CI->getValue(); | |
| 2764 } else if (auto CR = llvm::dyn_cast<ConstantRelocatable>(Offset)) { | |
| 2765 CR->emitWithoutDollar(Func->getContext()); | |
| 2766 } else { | |
| 2767 assert(0); | |
|
jvoung (off chromium)
2014/10/31 22:12:18
could do llvm_unreachable("...")
Jim Stichnoth
2014/11/01 13:44:17
Done.
| |
| 2768 } | |
| 2769 | |
| 2762 if (Base) { | 2770 if (Base) { |
| 2771 Str << "("; | |
| 2763 Base->emit(Func); | 2772 Base->emit(Func); |
| 2764 Dumped = true; | 2773 if (Index) { |
| 2774 Str << ","; | |
| 2775 Index->emit(Func); | |
| 2776 if (Shift) | |
| 2777 Str << "," << (1u << Shift); | |
| 2778 } | |
| 2779 Str << ")"; | |
| 2765 } | 2780 } |
| 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 } | 2781 } |
| 2798 | 2782 |
| 2799 void OperandX8632Mem::dump(const Cfg *Func, Ostream &Str) const { | 2783 void OperandX8632Mem::dump(const Cfg *Func, Ostream &Str) const { |
| 2800 if (SegmentReg != DefaultSegment) { | 2784 if (SegmentReg != DefaultSegment) { |
| 2801 assert(SegmentReg >= 0 && SegmentReg < SegReg_NUM); | 2785 assert(SegmentReg >= 0 && SegmentReg < SegReg_NUM); |
| 2802 Str << InstX8632SegmentRegNames[SegmentReg] << ":"; | 2786 Str << InstX8632SegmentRegNames[SegmentReg] << ":"; |
| 2803 } | 2787 } |
| 2804 bool Dumped = false; | 2788 bool Dumped = false; |
| 2805 Str << "["; | 2789 Str << "["; |
| 2806 if (Base) { | 2790 if (Base) { |
| (...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2896 return x86::Address(RegX8632::getEncodedGPR(Target->getFrameOrStackReg()), | 2880 return x86::Address(RegX8632::getEncodedGPR(Target->getFrameOrStackReg()), |
| 2897 Offset); | 2881 Offset); |
| 2898 } | 2882 } |
| 2899 | 2883 |
| 2900 void VariableSplit::emit(const Cfg *Func) const { | 2884 void VariableSplit::emit(const Cfg *Func) const { |
| 2901 Ostream &Str = Func->getContext()->getStrEmit(); | 2885 Ostream &Str = Func->getContext()->getStrEmit(); |
| 2902 assert(!Var->hasReg()); | 2886 assert(!Var->hasReg()); |
| 2903 // The following is copied/adapted from TargetX8632::emitVariable(). | 2887 // The following is copied/adapted from TargetX8632::emitVariable(). |
| 2904 const TargetLowering *Target = Func->getTarget(); | 2888 const TargetLowering *Target = Func->getTarget(); |
| 2905 const Type Ty = IceType_i32; | 2889 const Type Ty = IceType_i32; |
| 2906 Str << TypeX8632Attributes[Ty].WidthString << " [" | |
| 2907 << Target->getRegName(Target->getFrameOrStackReg(), Ty); | |
| 2908 int32_t Offset = | 2890 int32_t Offset = |
| 2909 Var->getStackOffset() + Target->getStackAdjustment() + getOffset(); | 2891 Var->getStackOffset() + Target->getStackAdjustment() + getOffset(); |
| 2910 if (Offset) { | 2892 if (Offset) |
| 2911 if (Offset > 0) | |
| 2912 Str << "+"; | |
| 2913 Str << Offset; | 2893 Str << Offset; |
| 2914 } | 2894 Str << "(%" << Target->getRegName(Target->getFrameOrStackReg(), Ty) << ")"; |
| 2915 Str << "]"; | |
| 2916 } | 2895 } |
| 2917 | 2896 |
| 2918 void VariableSplit::dump(const Cfg *Func, Ostream &Str) const { | 2897 void VariableSplit::dump(const Cfg *Func, Ostream &Str) const { |
| 2919 switch (Part) { | 2898 switch (Part) { |
| 2920 case Low: | 2899 case Low: |
| 2921 Str << "low"; | 2900 Str << "low"; |
| 2922 break; | 2901 break; |
| 2923 case High: | 2902 case High: |
| 2924 Str << "high"; | 2903 Str << "high"; |
| 2925 break; | 2904 break; |
| 2926 default: | 2905 default: |
| 2927 Str << "???"; | 2906 Str << "???"; |
| 2928 break; | 2907 break; |
| 2929 } | 2908 } |
| 2930 Str << "("; | 2909 Str << "("; |
| 2931 if (Func) | 2910 if (Func) |
| 2932 Var->dump(Func); | 2911 Var->dump(Func); |
| 2933 else | 2912 else |
| 2934 Var->dump(Str); | 2913 Var->dump(Str); |
| 2935 Str << ")"; | 2914 Str << ")"; |
| 2936 } | 2915 } |
| 2937 | 2916 |
| 2938 } // end of namespace Ice | 2917 } // end of namespace Ice |
| OLD | NEW |