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 |