| 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 325 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 336 | 336 |
| 337 InstX8632Xchg::InstX8632Xchg(Cfg *Func, Operand *Dest, Variable *Source) | 337 InstX8632Xchg::InstX8632Xchg(Cfg *Func, Operand *Dest, Variable *Source) |
| 338 : InstX8632(Func, InstX8632::Xchg, 2, llvm::dyn_cast<Variable>(Dest)) { | 338 : InstX8632(Func, InstX8632::Xchg, 2, llvm::dyn_cast<Variable>(Dest)) { |
| 339 addSource(Dest); | 339 addSource(Dest); |
| 340 addSource(Source); | 340 addSource(Source); |
| 341 } | 341 } |
| 342 | 342 |
| 343 // ======================== Dump routines ======================== // | 343 // ======================== Dump routines ======================== // |
| 344 | 344 |
| 345 void InstX8632::dump(const Cfg *Func) const { | 345 void InstX8632::dump(const Cfg *Func) const { |
| 346 if (!ALLOW_DUMP) |
| 347 return; |
| 346 Ostream &Str = Func->getContext()->getStrDump(); | 348 Ostream &Str = Func->getContext()->getStrDump(); |
| 347 Str << "[X8632] "; | 349 Str << "[X8632] "; |
| 348 Inst::dump(Func); | 350 Inst::dump(Func); |
| 349 } | 351 } |
| 350 | 352 |
| 351 void InstX8632Label::emit(const Cfg *Func) const { | 353 void InstX8632Label::emit(const Cfg *Func) const { |
| 354 if (!ALLOW_DUMP) |
| 355 return; |
| 352 Ostream &Str = Func->getContext()->getStrEmit(); | 356 Ostream &Str = Func->getContext()->getStrEmit(); |
| 353 Str << getName(Func) << ":"; | 357 Str << getName(Func) << ":"; |
| 354 } | 358 } |
| 355 | 359 |
| 356 void InstX8632Label::emitIAS(const Cfg *Func) const { | 360 void InstX8632Label::emitIAS(const Cfg *Func) const { |
| 357 x86::AssemblerX86 *Asm = Func->getAssembler<x86::AssemblerX86>(); | 361 x86::AssemblerX86 *Asm = Func->getAssembler<x86::AssemblerX86>(); |
| 358 Asm->BindLocalLabel(Number); | 362 Asm->BindLocalLabel(Number); |
| 359 } | 363 } |
| 360 | 364 |
| 361 void InstX8632Label::dump(const Cfg *Func) const { | 365 void InstX8632Label::dump(const Cfg *Func) const { |
| 366 if (!ALLOW_DUMP) |
| 367 return; |
| 362 Ostream &Str = Func->getContext()->getStrDump(); | 368 Ostream &Str = Func->getContext()->getStrDump(); |
| 363 Str << getName(Func) << ":"; | 369 Str << getName(Func) << ":"; |
| 364 } | 370 } |
| 365 | 371 |
| 366 void InstX8632Br::emit(const Cfg *Func) const { | 372 void InstX8632Br::emit(const Cfg *Func) const { |
| 373 if (!ALLOW_DUMP) |
| 374 return; |
| 367 Ostream &Str = Func->getContext()->getStrEmit(); | 375 Ostream &Str = Func->getContext()->getStrEmit(); |
| 368 Str << "\t"; | 376 Str << "\t"; |
| 369 | 377 |
| 370 if (Condition == CondX86::Br_None) { | 378 if (Condition == CondX86::Br_None) { |
| 371 Str << "jmp"; | 379 Str << "jmp"; |
| 372 } else { | 380 } else { |
| 373 Str << InstX8632BrAttributes[Condition].EmitString; | 381 Str << InstX8632BrAttributes[Condition].EmitString; |
| 374 } | 382 } |
| 375 | 383 |
| 376 if (Label) { | 384 if (Label) { |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 413 if (getTargetFalse()) { | 421 if (getTargetFalse()) { |
| 414 x86::Label *L2 = | 422 x86::Label *L2 = |
| 415 Asm->GetOrCreateCfgNodeLabel(getTargetFalse()->getIndex()); | 423 Asm->GetOrCreateCfgNodeLabel(getTargetFalse()->getIndex()); |
| 416 Asm->jmp(L2, Near); | 424 Asm->jmp(L2, Near); |
| 417 } | 425 } |
| 418 } | 426 } |
| 419 } | 427 } |
| 420 } | 428 } |
| 421 | 429 |
| 422 void InstX8632Br::dump(const Cfg *Func) const { | 430 void InstX8632Br::dump(const Cfg *Func) const { |
| 431 if (!ALLOW_DUMP) |
| 432 return; |
| 423 Ostream &Str = Func->getContext()->getStrDump(); | 433 Ostream &Str = Func->getContext()->getStrDump(); |
| 424 Str << "br "; | 434 Str << "br "; |
| 425 | 435 |
| 426 if (Condition == CondX86::Br_None) { | 436 if (Condition == CondX86::Br_None) { |
| 427 Str << "label %" | 437 Str << "label %" |
| 428 << (Label ? Label->getName(Func) : getTargetFalse()->getName()); | 438 << (Label ? Label->getName(Func) : getTargetFalse()->getName()); |
| 429 return; | 439 return; |
| 430 } | 440 } |
| 431 | 441 |
| 432 Str << InstX8632BrAttributes[Condition].DisplayString; | 442 Str << InstX8632BrAttributes[Condition].DisplayString; |
| 433 if (Label) { | 443 if (Label) { |
| 434 Str << ", label %" << Label->getName(Func); | 444 Str << ", label %" << Label->getName(Func); |
| 435 } else { | 445 } else { |
| 436 Str << ", label %" << getTargetTrue()->getName(); | 446 Str << ", label %" << getTargetTrue()->getName(); |
| 437 if (getTargetFalse()) { | 447 if (getTargetFalse()) { |
| 438 Str << ", label %" << getTargetFalse()->getName(); | 448 Str << ", label %" << getTargetFalse()->getName(); |
| 439 } | 449 } |
| 440 } | 450 } |
| 441 } | 451 } |
| 442 | 452 |
| 443 void InstX8632Call::emit(const Cfg *Func) const { | 453 void InstX8632Call::emit(const Cfg *Func) const { |
| 454 if (!ALLOW_DUMP) |
| 455 return; |
| 444 Ostream &Str = Func->getContext()->getStrEmit(); | 456 Ostream &Str = Func->getContext()->getStrEmit(); |
| 445 assert(getSrcSize() == 1); | 457 assert(getSrcSize() == 1); |
| 446 Str << "\tcall\t"; | 458 Str << "\tcall\t"; |
| 447 if (const auto CallTarget = | 459 if (const auto CallTarget = |
| 448 llvm::dyn_cast<ConstantRelocatable>(getCallTarget())) { | 460 llvm::dyn_cast<ConstantRelocatable>(getCallTarget())) { |
| 449 // TODO(stichnot): All constant targets should suppress the '$', | 461 // TODO(stichnot): All constant targets should suppress the '$', |
| 450 // not just relocatables. | 462 // not just relocatables. |
| 451 CallTarget->emitWithoutDollar(Func->getContext()); | 463 CallTarget->emitWithoutDollar(Func->getContext()); |
| 452 } else { | 464 } else { |
| 453 Str << "*"; | 465 Str << "*"; |
| (...skipping 28 matching lines...) Expand all Loading... |
| 482 // TODO(jvoung): Do we need to support this? | 494 // TODO(jvoung): Do we need to support this? |
| 483 (void)Imm; | 495 (void)Imm; |
| 484 llvm_unreachable("Unexpected call to absolute address"); | 496 llvm_unreachable("Unexpected call to absolute address"); |
| 485 } else { | 497 } else { |
| 486 llvm_unreachable("Unexpected operand type"); | 498 llvm_unreachable("Unexpected operand type"); |
| 487 } | 499 } |
| 488 Func->getTarget()->resetStackAdjustment(); | 500 Func->getTarget()->resetStackAdjustment(); |
| 489 } | 501 } |
| 490 | 502 |
| 491 void InstX8632Call::dump(const Cfg *Func) const { | 503 void InstX8632Call::dump(const Cfg *Func) const { |
| 504 if (!ALLOW_DUMP) |
| 505 return; |
| 492 Ostream &Str = Func->getContext()->getStrDump(); | 506 Ostream &Str = Func->getContext()->getStrDump(); |
| 493 if (getDest()) { | 507 if (getDest()) { |
| 494 dumpDest(Func); | 508 dumpDest(Func); |
| 495 Str << " = "; | 509 Str << " = "; |
| 496 } | 510 } |
| 497 Str << "call "; | 511 Str << "call "; |
| 498 getCallTarget()->dump(Func); | 512 getCallTarget()->dump(Func); |
| 499 } | 513 } |
| 500 | 514 |
| 501 // The ShiftHack parameter is used to emit "cl" instead of "ecx" for | 515 // The ShiftHack parameter is used to emit "cl" instead of "ecx" for |
| 502 // shift instructions, in order to be syntactically valid. The | 516 // shift instructions, in order to be syntactically valid. The |
| 503 // Opcode parameter needs to be char* and not IceString because of | 517 // Opcode parameter needs to be char* and not IceString because of |
| 504 // template issues. | 518 // template issues. |
| 505 void emitTwoAddress(const char *Opcode, const Inst *Inst, const Cfg *Func, | 519 void emitTwoAddress(const char *Opcode, const Inst *Inst, const Cfg *Func, |
| 506 bool ShiftHack) { | 520 bool ShiftHack) { |
| 521 if (!ALLOW_DUMP) |
| 522 return; |
| 507 Ostream &Str = Func->getContext()->getStrEmit(); | 523 Ostream &Str = Func->getContext()->getStrEmit(); |
| 508 assert(Inst->getSrcSize() == 2); | 524 assert(Inst->getSrcSize() == 2); |
| 509 Variable *Dest = Inst->getDest(); | 525 Variable *Dest = Inst->getDest(); |
| 510 assert(Dest == Inst->getSrc(0)); | 526 assert(Dest == Inst->getSrc(0)); |
| 511 Operand *Src1 = Inst->getSrc(1); | 527 Operand *Src1 = Inst->getSrc(1); |
| 512 Str << "\t" << Opcode << InstX8632::getWidthString(Dest->getType()) << "\t"; | 528 Str << "\t" << Opcode << InstX8632::getWidthString(Dest->getType()) << "\t"; |
| 513 const auto ShiftReg = llvm::dyn_cast<Variable>(Src1); | 529 const auto ShiftReg = llvm::dyn_cast<Variable>(Src1); |
| 514 if (ShiftHack && ShiftReg && ShiftReg->getRegNum() == RegX8632::Reg_ecx) | 530 if (ShiftHack && ShiftReg && ShiftReg->getRegNum() == RegX8632::Reg_ecx) |
| 515 Str << "%cl"; | 531 Str << "%cl"; |
| 516 else | 532 else |
| (...skipping 512 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1029 template <> | 1045 template <> |
| 1030 const x86::AssemblerX86::XmmEmitterShiftOp InstX8632Psll::Emitter = { | 1046 const x86::AssemblerX86::XmmEmitterShiftOp InstX8632Psll::Emitter = { |
| 1031 &x86::AssemblerX86::psll, &x86::AssemblerX86::psll, | 1047 &x86::AssemblerX86::psll, &x86::AssemblerX86::psll, |
| 1032 &x86::AssemblerX86::psll}; | 1048 &x86::AssemblerX86::psll}; |
| 1033 template <> | 1049 template <> |
| 1034 const x86::AssemblerX86::XmmEmitterShiftOp InstX8632Psra::Emitter = { | 1050 const x86::AssemblerX86::XmmEmitterShiftOp InstX8632Psra::Emitter = { |
| 1035 &x86::AssemblerX86::psra, &x86::AssemblerX86::psra, | 1051 &x86::AssemblerX86::psra, &x86::AssemblerX86::psra, |
| 1036 &x86::AssemblerX86::psra}; | 1052 &x86::AssemblerX86::psra}; |
| 1037 | 1053 |
| 1038 template <> void InstX8632Sqrtss::emit(const Cfg *Func) const { | 1054 template <> void InstX8632Sqrtss::emit(const Cfg *Func) const { |
| 1055 if (!ALLOW_DUMP) |
| 1056 return; |
| 1039 Ostream &Str = Func->getContext()->getStrEmit(); | 1057 Ostream &Str = Func->getContext()->getStrEmit(); |
| 1040 assert(getSrcSize() == 1); | 1058 assert(getSrcSize() == 1); |
| 1041 Type Ty = getSrc(0)->getType(); | 1059 Type Ty = getSrc(0)->getType(); |
| 1042 assert(isScalarFloatingType(Ty)); | 1060 assert(isScalarFloatingType(Ty)); |
| 1043 Str << "\tsqrt" << TypeX8632Attributes[Ty].SdSsString << "\t"; | 1061 Str << "\tsqrt" << TypeX8632Attributes[Ty].SdSsString << "\t"; |
| 1044 getSrc(0)->emit(Func); | 1062 getSrc(0)->emit(Func); |
| 1045 Str << ", "; | 1063 Str << ", "; |
| 1046 getDest()->emit(Func); | 1064 getDest()->emit(Func); |
| 1047 } | 1065 } |
| 1048 | 1066 |
| 1049 template <> void InstX8632Addss::emit(const Cfg *Func) const { | 1067 template <> void InstX8632Addss::emit(const Cfg *Func) const { |
| 1068 if (!ALLOW_DUMP) |
| 1069 return; |
| 1050 char buf[30]; | 1070 char buf[30]; |
| 1051 snprintf(buf, llvm::array_lengthof(buf), "add%s", | 1071 snprintf(buf, llvm::array_lengthof(buf), "add%s", |
| 1052 TypeX8632Attributes[getDest()->getType()].SdSsString); | 1072 TypeX8632Attributes[getDest()->getType()].SdSsString); |
| 1053 emitTwoAddress(buf, this, Func); | 1073 emitTwoAddress(buf, this, Func); |
| 1054 } | 1074 } |
| 1055 | 1075 |
| 1056 template <> void InstX8632Padd::emit(const Cfg *Func) const { | 1076 template <> void InstX8632Padd::emit(const Cfg *Func) const { |
| 1077 if (!ALLOW_DUMP) |
| 1078 return; |
| 1057 char buf[30]; | 1079 char buf[30]; |
| 1058 snprintf(buf, llvm::array_lengthof(buf), "padd%s", | 1080 snprintf(buf, llvm::array_lengthof(buf), "padd%s", |
| 1059 TypeX8632Attributes[getDest()->getType()].PackString); | 1081 TypeX8632Attributes[getDest()->getType()].PackString); |
| 1060 emitTwoAddress(buf, this, Func); | 1082 emitTwoAddress(buf, this, Func); |
| 1061 } | 1083 } |
| 1062 | 1084 |
| 1063 template <> void InstX8632Pmull::emit(const Cfg *Func) const { | 1085 template <> void InstX8632Pmull::emit(const Cfg *Func) const { |
| 1086 if (!ALLOW_DUMP) |
| 1087 return; |
| 1064 char buf[30]; | 1088 char buf[30]; |
| 1065 bool TypesAreValid = getDest()->getType() == IceType_v4i32 || | 1089 bool TypesAreValid = getDest()->getType() == IceType_v4i32 || |
| 1066 getDest()->getType() == IceType_v8i16; | 1090 getDest()->getType() == IceType_v8i16; |
| 1067 bool InstructionSetIsValid = | 1091 bool InstructionSetIsValid = |
| 1068 getDest()->getType() == IceType_v8i16 || | 1092 getDest()->getType() == IceType_v8i16 || |
| 1069 static_cast<TargetX8632 *>(Func->getTarget())->getInstructionSet() >= | 1093 static_cast<TargetX8632 *>(Func->getTarget())->getInstructionSet() >= |
| 1070 TargetX8632::SSE4_1; | 1094 TargetX8632::SSE4_1; |
| 1071 (void)TypesAreValid; | 1095 (void)TypesAreValid; |
| 1072 (void)InstructionSetIsValid; | 1096 (void)InstructionSetIsValid; |
| 1073 assert(TypesAreValid); | 1097 assert(TypesAreValid); |
| (...skipping 13 matching lines...) Expand all Loading... |
| 1087 (void)TypesAreValid; | 1111 (void)TypesAreValid; |
| 1088 (void)InstructionSetIsValid; | 1112 (void)InstructionSetIsValid; |
| 1089 assert(TypesAreValid); | 1113 assert(TypesAreValid); |
| 1090 assert(InstructionSetIsValid); | 1114 assert(InstructionSetIsValid); |
| 1091 assert(getSrcSize() == 2); | 1115 assert(getSrcSize() == 2); |
| 1092 Type ElementTy = typeElementType(Ty); | 1116 Type ElementTy = typeElementType(Ty); |
| 1093 emitIASRegOpTyXMM(Func, ElementTy, getDest(), getSrc(1), Emitter); | 1117 emitIASRegOpTyXMM(Func, ElementTy, getDest(), getSrc(1), Emitter); |
| 1094 } | 1118 } |
| 1095 | 1119 |
| 1096 template <> void InstX8632Subss::emit(const Cfg *Func) const { | 1120 template <> void InstX8632Subss::emit(const Cfg *Func) const { |
| 1121 if (!ALLOW_DUMP) |
| 1122 return; |
| 1097 char buf[30]; | 1123 char buf[30]; |
| 1098 snprintf(buf, llvm::array_lengthof(buf), "sub%s", | 1124 snprintf(buf, llvm::array_lengthof(buf), "sub%s", |
| 1099 TypeX8632Attributes[getDest()->getType()].SdSsString); | 1125 TypeX8632Attributes[getDest()->getType()].SdSsString); |
| 1100 emitTwoAddress(buf, this, Func); | 1126 emitTwoAddress(buf, this, Func); |
| 1101 } | 1127 } |
| 1102 | 1128 |
| 1103 template <> void InstX8632Psub::emit(const Cfg *Func) const { | 1129 template <> void InstX8632Psub::emit(const Cfg *Func) const { |
| 1130 if (!ALLOW_DUMP) |
| 1131 return; |
| 1104 char buf[30]; | 1132 char buf[30]; |
| 1105 snprintf(buf, llvm::array_lengthof(buf), "psub%s", | 1133 snprintf(buf, llvm::array_lengthof(buf), "psub%s", |
| 1106 TypeX8632Attributes[getDest()->getType()].PackString); | 1134 TypeX8632Attributes[getDest()->getType()].PackString); |
| 1107 emitTwoAddress(buf, this, Func); | 1135 emitTwoAddress(buf, this, Func); |
| 1108 } | 1136 } |
| 1109 | 1137 |
| 1110 template <> void InstX8632Mulss::emit(const Cfg *Func) const { | 1138 template <> void InstX8632Mulss::emit(const Cfg *Func) const { |
| 1139 if (!ALLOW_DUMP) |
| 1140 return; |
| 1111 char buf[30]; | 1141 char buf[30]; |
| 1112 snprintf(buf, llvm::array_lengthof(buf), "mul%s", | 1142 snprintf(buf, llvm::array_lengthof(buf), "mul%s", |
| 1113 TypeX8632Attributes[getDest()->getType()].SdSsString); | 1143 TypeX8632Attributes[getDest()->getType()].SdSsString); |
| 1114 emitTwoAddress(buf, this, Func); | 1144 emitTwoAddress(buf, this, Func); |
| 1115 } | 1145 } |
| 1116 | 1146 |
| 1117 template <> void InstX8632Pmuludq::emit(const Cfg *Func) const { | 1147 template <> void InstX8632Pmuludq::emit(const Cfg *Func) const { |
| 1148 if (!ALLOW_DUMP) |
| 1149 return; |
| 1118 assert(getSrc(0)->getType() == IceType_v4i32 && | 1150 assert(getSrc(0)->getType() == IceType_v4i32 && |
| 1119 getSrc(1)->getType() == IceType_v4i32); | 1151 getSrc(1)->getType() == IceType_v4i32); |
| 1120 emitTwoAddress(Opcode, this, Func); | 1152 emitTwoAddress(Opcode, this, Func); |
| 1121 } | 1153 } |
| 1122 | 1154 |
| 1123 template <> void InstX8632Divss::emit(const Cfg *Func) const { | 1155 template <> void InstX8632Divss::emit(const Cfg *Func) const { |
| 1156 if (!ALLOW_DUMP) |
| 1157 return; |
| 1124 char buf[30]; | 1158 char buf[30]; |
| 1125 snprintf(buf, llvm::array_lengthof(buf), "div%s", | 1159 snprintf(buf, llvm::array_lengthof(buf), "div%s", |
| 1126 TypeX8632Attributes[getDest()->getType()].SdSsString); | 1160 TypeX8632Attributes[getDest()->getType()].SdSsString); |
| 1127 emitTwoAddress(buf, this, Func); | 1161 emitTwoAddress(buf, this, Func); |
| 1128 } | 1162 } |
| 1129 | 1163 |
| 1130 template <> void InstX8632Div::emit(const Cfg *Func) const { | 1164 template <> void InstX8632Div::emit(const Cfg *Func) const { |
| 1165 if (!ALLOW_DUMP) |
| 1166 return; |
| 1131 Ostream &Str = Func->getContext()->getStrEmit(); | 1167 Ostream &Str = Func->getContext()->getStrEmit(); |
| 1132 assert(getSrcSize() == 3); | 1168 assert(getSrcSize() == 3); |
| 1133 Operand *Src1 = getSrc(1); | 1169 Operand *Src1 = getSrc(1); |
| 1134 Str << "\t" << Opcode << getWidthString(Src1->getType()) << "\t"; | 1170 Str << "\t" << Opcode << getWidthString(Src1->getType()) << "\t"; |
| 1135 Src1->emit(Func); | 1171 Src1->emit(Func); |
| 1136 } | 1172 } |
| 1137 | 1173 |
| 1138 template <> void InstX8632Div::emitIAS(const Cfg *Func) const { | 1174 template <> void InstX8632Div::emitIAS(const Cfg *Func) const { |
| 1139 assert(getSrcSize() == 3); | 1175 assert(getSrcSize() == 3); |
| 1140 const Operand *Src = getSrc(1); | 1176 const Operand *Src = getSrc(1); |
| 1141 Type Ty = Src->getType(); | 1177 Type Ty = Src->getType(); |
| 1142 const static x86::AssemblerX86::GPREmitterOneOp Emitter = { | 1178 const static x86::AssemblerX86::GPREmitterOneOp Emitter = { |
| 1143 &x86::AssemblerX86::div, &x86::AssemblerX86::div}; | 1179 &x86::AssemblerX86::div, &x86::AssemblerX86::div}; |
| 1144 emitIASOpTyGPR(Func, Ty, Src, Emitter); | 1180 emitIASOpTyGPR(Func, Ty, Src, Emitter); |
| 1145 } | 1181 } |
| 1146 | 1182 |
| 1147 template <> void InstX8632Idiv::emit(const Cfg *Func) const { | 1183 template <> void InstX8632Idiv::emit(const Cfg *Func) const { |
| 1184 if (!ALLOW_DUMP) |
| 1185 return; |
| 1148 Ostream &Str = Func->getContext()->getStrEmit(); | 1186 Ostream &Str = Func->getContext()->getStrEmit(); |
| 1149 assert(getSrcSize() == 3); | 1187 assert(getSrcSize() == 3); |
| 1150 Operand *Src1 = getSrc(1); | 1188 Operand *Src1 = getSrc(1); |
| 1151 Str << "\t" << Opcode << getWidthString(Src1->getType()) << "\t"; | 1189 Str << "\t" << Opcode << getWidthString(Src1->getType()) << "\t"; |
| 1152 Src1->emit(Func); | 1190 Src1->emit(Func); |
| 1153 } | 1191 } |
| 1154 | 1192 |
| 1155 template <> void InstX8632Idiv::emitIAS(const Cfg *Func) const { | 1193 template <> void InstX8632Idiv::emitIAS(const Cfg *Func) const { |
| 1156 assert(getSrcSize() == 3); | 1194 assert(getSrcSize() == 3); |
| 1157 const Operand *Src = getSrc(1); | 1195 const Operand *Src = getSrc(1); |
| 1158 Type Ty = Src->getType(); | 1196 Type Ty = Src->getType(); |
| 1159 const static x86::AssemblerX86::GPREmitterOneOp Emitter = { | 1197 const static x86::AssemblerX86::GPREmitterOneOp Emitter = { |
| 1160 &x86::AssemblerX86::idiv, &x86::AssemblerX86::idiv}; | 1198 &x86::AssemblerX86::idiv, &x86::AssemblerX86::idiv}; |
| 1161 emitIASOpTyGPR(Func, Ty, Src, Emitter); | 1199 emitIASOpTyGPR(Func, Ty, Src, Emitter); |
| 1162 } | 1200 } |
| 1163 | 1201 |
| 1164 namespace { | 1202 namespace { |
| 1165 | 1203 |
| 1166 // pblendvb and blendvps take xmm0 as a final implicit argument. | 1204 // pblendvb and blendvps take xmm0 as a final implicit argument. |
| 1167 void emitVariableBlendInst(const char *Opcode, const Inst *Inst, | 1205 void emitVariableBlendInst(const char *Opcode, const Inst *Inst, |
| 1168 const Cfg *Func) { | 1206 const Cfg *Func) { |
| 1207 if (!ALLOW_DUMP) |
| 1208 return; |
| 1169 Ostream &Str = Func->getContext()->getStrEmit(); | 1209 Ostream &Str = Func->getContext()->getStrEmit(); |
| 1170 assert(Inst->getSrcSize() == 3); | 1210 assert(Inst->getSrcSize() == 3); |
| 1171 assert(llvm::cast<Variable>(Inst->getSrc(2))->getRegNum() == | 1211 assert(llvm::cast<Variable>(Inst->getSrc(2))->getRegNum() == |
| 1172 RegX8632::Reg_xmm0); | 1212 RegX8632::Reg_xmm0); |
| 1173 Str << "\t" << Opcode << "\t"; | 1213 Str << "\t" << Opcode << "\t"; |
| 1174 Inst->getSrc(1)->emit(Func); | 1214 Inst->getSrc(1)->emit(Func); |
| 1175 Str << ", "; | 1215 Str << ", "; |
| 1176 Inst->getDest()->emit(Func); | 1216 Inst->getDest()->emit(Func); |
| 1177 } | 1217 } |
| 1178 | 1218 |
| 1179 void | 1219 void |
| 1180 emitIASVariableBlendInst(const Inst *Inst, const Cfg *Func, | 1220 emitIASVariableBlendInst(const Inst *Inst, const Cfg *Func, |
| 1181 const x86::AssemblerX86::XmmEmitterRegOp &Emitter) { | 1221 const x86::AssemblerX86::XmmEmitterRegOp &Emitter) { |
| 1182 assert(Inst->getSrcSize() == 3); | 1222 assert(Inst->getSrcSize() == 3); |
| 1183 assert(llvm::cast<Variable>(Inst->getSrc(2))->getRegNum() == | 1223 assert(llvm::cast<Variable>(Inst->getSrc(2))->getRegNum() == |
| 1184 RegX8632::Reg_xmm0); | 1224 RegX8632::Reg_xmm0); |
| 1185 const Variable *Dest = Inst->getDest(); | 1225 const Variable *Dest = Inst->getDest(); |
| 1186 const Operand *Src = Inst->getSrc(1); | 1226 const Operand *Src = Inst->getSrc(1); |
| 1187 emitIASRegOpTyXMM(Func, Dest->getType(), Dest, Src, Emitter); | 1227 emitIASRegOpTyXMM(Func, Dest->getType(), Dest, Src, Emitter); |
| 1188 } | 1228 } |
| 1189 | 1229 |
| 1190 } // end anonymous namespace | 1230 } // end anonymous namespace |
| 1191 | 1231 |
| 1192 template <> void InstX8632Blendvps::emit(const Cfg *Func) const { | 1232 template <> void InstX8632Blendvps::emit(const Cfg *Func) const { |
| 1233 if (!ALLOW_DUMP) |
| 1234 return; |
| 1193 assert(static_cast<TargetX8632 *>(Func->getTarget())->getInstructionSet() >= | 1235 assert(static_cast<TargetX8632 *>(Func->getTarget())->getInstructionSet() >= |
| 1194 TargetX8632::SSE4_1); | 1236 TargetX8632::SSE4_1); |
| 1195 emitVariableBlendInst(Opcode, this, Func); | 1237 emitVariableBlendInst(Opcode, this, Func); |
| 1196 } | 1238 } |
| 1197 | 1239 |
| 1198 template <> void InstX8632Blendvps::emitIAS(const Cfg *Func) const { | 1240 template <> void InstX8632Blendvps::emitIAS(const Cfg *Func) const { |
| 1199 assert(static_cast<TargetX8632 *>(Func->getTarget())->getInstructionSet() >= | 1241 assert(static_cast<TargetX8632 *>(Func->getTarget())->getInstructionSet() >= |
| 1200 TargetX8632::SSE4_1); | 1242 TargetX8632::SSE4_1); |
| 1201 static const x86::AssemblerX86::XmmEmitterRegOp Emitter = { | 1243 static const x86::AssemblerX86::XmmEmitterRegOp Emitter = { |
| 1202 &x86::AssemblerX86::blendvps, &x86::AssemblerX86::blendvps}; | 1244 &x86::AssemblerX86::blendvps, &x86::AssemblerX86::blendvps}; |
| 1203 emitIASVariableBlendInst(this, Func, Emitter); | 1245 emitIASVariableBlendInst(this, Func, Emitter); |
| 1204 } | 1246 } |
| 1205 | 1247 |
| 1206 template <> void InstX8632Pblendvb::emit(const Cfg *Func) const { | 1248 template <> void InstX8632Pblendvb::emit(const Cfg *Func) const { |
| 1249 if (!ALLOW_DUMP) |
| 1250 return; |
| 1207 assert(static_cast<TargetX8632 *>(Func->getTarget())->getInstructionSet() >= | 1251 assert(static_cast<TargetX8632 *>(Func->getTarget())->getInstructionSet() >= |
| 1208 TargetX8632::SSE4_1); | 1252 TargetX8632::SSE4_1); |
| 1209 emitVariableBlendInst(Opcode, this, Func); | 1253 emitVariableBlendInst(Opcode, this, Func); |
| 1210 } | 1254 } |
| 1211 | 1255 |
| 1212 template <> void InstX8632Pblendvb::emitIAS(const Cfg *Func) const { | 1256 template <> void InstX8632Pblendvb::emitIAS(const Cfg *Func) const { |
| 1213 assert(static_cast<TargetX8632 *>(Func->getTarget())->getInstructionSet() >= | 1257 assert(static_cast<TargetX8632 *>(Func->getTarget())->getInstructionSet() >= |
| 1214 TargetX8632::SSE4_1); | 1258 TargetX8632::SSE4_1); |
| 1215 static const x86::AssemblerX86::XmmEmitterRegOp Emitter = { | 1259 static const x86::AssemblerX86::XmmEmitterRegOp Emitter = { |
| 1216 &x86::AssemblerX86::pblendvb, &x86::AssemblerX86::pblendvb}; | 1260 &x86::AssemblerX86::pblendvb, &x86::AssemblerX86::pblendvb}; |
| 1217 emitIASVariableBlendInst(this, Func, Emitter); | 1261 emitIASVariableBlendInst(this, Func, Emitter); |
| 1218 } | 1262 } |
| 1219 | 1263 |
| 1220 template <> void InstX8632Imul::emit(const Cfg *Func) const { | 1264 template <> void InstX8632Imul::emit(const Cfg *Func) const { |
| 1265 if (!ALLOW_DUMP) |
| 1266 return; |
| 1221 Ostream &Str = Func->getContext()->getStrEmit(); | 1267 Ostream &Str = Func->getContext()->getStrEmit(); |
| 1222 assert(getSrcSize() == 2); | 1268 assert(getSrcSize() == 2); |
| 1223 Variable *Dest = getDest(); | 1269 Variable *Dest = getDest(); |
| 1224 if (isByteSizedArithType(Dest->getType())) { | 1270 if (isByteSizedArithType(Dest->getType())) { |
| 1225 // The 8-bit version of imul only allows the form "imul r/m8". | 1271 // The 8-bit version of imul only allows the form "imul r/m8". |
| 1226 const auto Src0Var = llvm::dyn_cast<Variable>(getSrc(0)); | 1272 const auto Src0Var = llvm::dyn_cast<Variable>(getSrc(0)); |
| 1227 (void)Src0Var; | 1273 (void)Src0Var; |
| 1228 assert(Src0Var && Src0Var->getRegNum() == RegX8632::Reg_eax); | 1274 assert(Src0Var && Src0Var->getRegNum() == RegX8632::Reg_eax); |
| 1229 Str << "\timulb\t"; | 1275 Str << "\timulb\t"; |
| 1230 getSrc(1)->emit(Func); | 1276 getSrc(1)->emit(Func); |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1273 Type Ty = Dest->getType(); | 1319 Type Ty = Dest->getType(); |
| 1274 static const x86::AssemblerX86::ThreeOpImmEmitter< | 1320 static const x86::AssemblerX86::ThreeOpImmEmitter< |
| 1275 RegX8632::XmmRegister, RegX8632::XmmRegister> Emitter = { | 1321 RegX8632::XmmRegister, RegX8632::XmmRegister> Emitter = { |
| 1276 &x86::AssemblerX86::insertps, &x86::AssemblerX86::insertps}; | 1322 &x86::AssemblerX86::insertps, &x86::AssemblerX86::insertps}; |
| 1277 emitIASThreeOpImmOps<RegX8632::XmmRegister, RegX8632::XmmRegister, | 1323 emitIASThreeOpImmOps<RegX8632::XmmRegister, RegX8632::XmmRegister, |
| 1278 RegX8632::getEncodedXmm, RegX8632::getEncodedXmm>( | 1324 RegX8632::getEncodedXmm, RegX8632::getEncodedXmm>( |
| 1279 Func, Ty, Dest, getSrc(1), getSrc(2), Emitter); | 1325 Func, Ty, Dest, getSrc(1), getSrc(2), Emitter); |
| 1280 } | 1326 } |
| 1281 | 1327 |
| 1282 template <> void InstX8632Cbwdq::emit(const Cfg *Func) const { | 1328 template <> void InstX8632Cbwdq::emit(const Cfg *Func) const { |
| 1329 if (!ALLOW_DUMP) |
| 1330 return; |
| 1283 Ostream &Str = Func->getContext()->getStrEmit(); | 1331 Ostream &Str = Func->getContext()->getStrEmit(); |
| 1284 assert(getSrcSize() == 1); | 1332 assert(getSrcSize() == 1); |
| 1285 Operand *Src0 = getSrc(0); | 1333 Operand *Src0 = getSrc(0); |
| 1286 assert(llvm::isa<Variable>(Src0)); | 1334 assert(llvm::isa<Variable>(Src0)); |
| 1287 assert(llvm::cast<Variable>(Src0)->getRegNum() == RegX8632::Reg_eax); | 1335 assert(llvm::cast<Variable>(Src0)->getRegNum() == RegX8632::Reg_eax); |
| 1288 switch (Src0->getType()) { | 1336 switch (Src0->getType()) { |
| 1289 default: | 1337 default: |
| 1290 llvm_unreachable("unexpected source type!"); | 1338 llvm_unreachable("unexpected source type!"); |
| 1291 break; | 1339 break; |
| 1292 case IceType_i8: | 1340 case IceType_i8: |
| (...skipping 30 matching lines...) Expand all Loading... |
| 1323 Asm->cwd(); | 1371 Asm->cwd(); |
| 1324 break; | 1372 break; |
| 1325 case IceType_i32: | 1373 case IceType_i32: |
| 1326 assert(getDest()->getRegNum() == RegX8632::Reg_edx); | 1374 assert(getDest()->getRegNum() == RegX8632::Reg_edx); |
| 1327 Asm->cdq(); | 1375 Asm->cdq(); |
| 1328 break; | 1376 break; |
| 1329 } | 1377 } |
| 1330 } | 1378 } |
| 1331 | 1379 |
| 1332 void InstX8632Mul::emit(const Cfg *Func) const { | 1380 void InstX8632Mul::emit(const Cfg *Func) const { |
| 1381 if (!ALLOW_DUMP) |
| 1382 return; |
| 1333 Ostream &Str = Func->getContext()->getStrEmit(); | 1383 Ostream &Str = Func->getContext()->getStrEmit(); |
| 1334 assert(getSrcSize() == 2); | 1384 assert(getSrcSize() == 2); |
| 1335 assert(llvm::isa<Variable>(getSrc(0))); | 1385 assert(llvm::isa<Variable>(getSrc(0))); |
| 1336 assert(llvm::cast<Variable>(getSrc(0))->getRegNum() == RegX8632::Reg_eax); | 1386 assert(llvm::cast<Variable>(getSrc(0))->getRegNum() == RegX8632::Reg_eax); |
| 1337 assert(getDest()->getRegNum() == RegX8632::Reg_eax); // TODO: allow edx? | 1387 assert(getDest()->getRegNum() == RegX8632::Reg_eax); // TODO: allow edx? |
| 1338 Str << "\tmul" << getWidthString(getDest()->getType()) << "\t"; | 1388 Str << "\tmul" << getWidthString(getDest()->getType()) << "\t"; |
| 1339 getSrc(1)->emit(Func); | 1389 getSrc(1)->emit(Func); |
| 1340 } | 1390 } |
| 1341 | 1391 |
| 1342 void InstX8632Mul::emitIAS(const Cfg *Func) const { | 1392 void InstX8632Mul::emitIAS(const Cfg *Func) const { |
| 1343 assert(getSrcSize() == 2); | 1393 assert(getSrcSize() == 2); |
| 1344 assert(llvm::isa<Variable>(getSrc(0))); | 1394 assert(llvm::isa<Variable>(getSrc(0))); |
| 1345 assert(llvm::cast<Variable>(getSrc(0))->getRegNum() == RegX8632::Reg_eax); | 1395 assert(llvm::cast<Variable>(getSrc(0))->getRegNum() == RegX8632::Reg_eax); |
| 1346 assert(getDest()->getRegNum() == RegX8632::Reg_eax); // TODO: allow edx? | 1396 assert(getDest()->getRegNum() == RegX8632::Reg_eax); // TODO: allow edx? |
| 1347 const Operand *Src = getSrc(1); | 1397 const Operand *Src = getSrc(1); |
| 1348 Type Ty = Src->getType(); | 1398 Type Ty = Src->getType(); |
| 1349 const static x86::AssemblerX86::GPREmitterOneOp Emitter = { | 1399 const static x86::AssemblerX86::GPREmitterOneOp Emitter = { |
| 1350 &x86::AssemblerX86::mul, &x86::AssemblerX86::mul}; | 1400 &x86::AssemblerX86::mul, &x86::AssemblerX86::mul}; |
| 1351 emitIASOpTyGPR(Func, Ty, Src, Emitter); | 1401 emitIASOpTyGPR(Func, Ty, Src, Emitter); |
| 1352 } | 1402 } |
| 1353 | 1403 |
| 1354 void InstX8632Mul::dump(const Cfg *Func) const { | 1404 void InstX8632Mul::dump(const Cfg *Func) const { |
| 1405 if (!ALLOW_DUMP) |
| 1406 return; |
| 1355 Ostream &Str = Func->getContext()->getStrDump(); | 1407 Ostream &Str = Func->getContext()->getStrDump(); |
| 1356 dumpDest(Func); | 1408 dumpDest(Func); |
| 1357 Str << " = mul." << getDest()->getType() << " "; | 1409 Str << " = mul." << getDest()->getType() << " "; |
| 1358 dumpSources(Func); | 1410 dumpSources(Func); |
| 1359 } | 1411 } |
| 1360 | 1412 |
| 1361 void InstX8632Shld::emit(const Cfg *Func) const { | 1413 void InstX8632Shld::emit(const Cfg *Func) const { |
| 1414 if (!ALLOW_DUMP) |
| 1415 return; |
| 1362 Ostream &Str = Func->getContext()->getStrEmit(); | 1416 Ostream &Str = Func->getContext()->getStrEmit(); |
| 1363 Variable *Dest = getDest(); | 1417 Variable *Dest = getDest(); |
| 1364 assert(getSrcSize() == 3); | 1418 assert(getSrcSize() == 3); |
| 1365 assert(Dest == getSrc(0)); | 1419 assert(Dest == getSrc(0)); |
| 1366 Str << "\tshld" << getWidthString(Dest->getType()) << "\t"; | 1420 Str << "\tshld" << getWidthString(Dest->getType()) << "\t"; |
| 1367 if (const auto ShiftReg = llvm::dyn_cast<Variable>(getSrc(2))) { | 1421 if (const auto ShiftReg = llvm::dyn_cast<Variable>(getSrc(2))) { |
| 1368 (void)ShiftReg; | 1422 (void)ShiftReg; |
| 1369 assert(ShiftReg->getRegNum() == RegX8632::Reg_ecx); | 1423 assert(ShiftReg->getRegNum() == RegX8632::Reg_ecx); |
| 1370 Str << "%cl"; | 1424 Str << "%cl"; |
| 1371 } else { | 1425 } else { |
| (...skipping 10 matching lines...) Expand all Loading... |
| 1382 assert(getDest() == getSrc(0)); | 1436 assert(getDest() == getSrc(0)); |
| 1383 const Variable *Dest = getDest(); | 1437 const Variable *Dest = getDest(); |
| 1384 const Operand *Src1 = getSrc(1); | 1438 const Operand *Src1 = getSrc(1); |
| 1385 const Operand *Src2 = getSrc(2); | 1439 const Operand *Src2 = getSrc(2); |
| 1386 static const x86::AssemblerX86::GPREmitterShiftD Emitter = { | 1440 static const x86::AssemblerX86::GPREmitterShiftD Emitter = { |
| 1387 &x86::AssemblerX86::shld, &x86::AssemblerX86::shld}; | 1441 &x86::AssemblerX86::shld, &x86::AssemblerX86::shld}; |
| 1388 emitIASGPRShiftDouble(Func, Dest, Src1, Src2, Emitter); | 1442 emitIASGPRShiftDouble(Func, Dest, Src1, Src2, Emitter); |
| 1389 } | 1443 } |
| 1390 | 1444 |
| 1391 void InstX8632Shld::dump(const Cfg *Func) const { | 1445 void InstX8632Shld::dump(const Cfg *Func) const { |
| 1446 if (!ALLOW_DUMP) |
| 1447 return; |
| 1392 Ostream &Str = Func->getContext()->getStrDump(); | 1448 Ostream &Str = Func->getContext()->getStrDump(); |
| 1393 dumpDest(Func); | 1449 dumpDest(Func); |
| 1394 Str << " = shld." << getDest()->getType() << " "; | 1450 Str << " = shld." << getDest()->getType() << " "; |
| 1395 dumpSources(Func); | 1451 dumpSources(Func); |
| 1396 } | 1452 } |
| 1397 | 1453 |
| 1398 void InstX8632Shrd::emit(const Cfg *Func) const { | 1454 void InstX8632Shrd::emit(const Cfg *Func) const { |
| 1455 if (!ALLOW_DUMP) |
| 1456 return; |
| 1399 Ostream &Str = Func->getContext()->getStrEmit(); | 1457 Ostream &Str = Func->getContext()->getStrEmit(); |
| 1400 Variable *Dest = getDest(); | 1458 Variable *Dest = getDest(); |
| 1401 assert(getSrcSize() == 3); | 1459 assert(getSrcSize() == 3); |
| 1402 assert(Dest == getSrc(0)); | 1460 assert(Dest == getSrc(0)); |
| 1403 Str << "\tshrd" << getWidthString(Dest->getType()) << "\t"; | 1461 Str << "\tshrd" << getWidthString(Dest->getType()) << "\t"; |
| 1404 if (const auto ShiftReg = llvm::dyn_cast<Variable>(getSrc(2))) { | 1462 if (const auto ShiftReg = llvm::dyn_cast<Variable>(getSrc(2))) { |
| 1405 (void)ShiftReg; | 1463 (void)ShiftReg; |
| 1406 assert(ShiftReg->getRegNum() == RegX8632::Reg_ecx); | 1464 assert(ShiftReg->getRegNum() == RegX8632::Reg_ecx); |
| 1407 Str << "%cl"; | 1465 Str << "%cl"; |
| 1408 } else { | 1466 } else { |
| (...skipping 10 matching lines...) Expand all Loading... |
| 1419 assert(getDest() == getSrc(0)); | 1477 assert(getDest() == getSrc(0)); |
| 1420 const Variable *Dest = getDest(); | 1478 const Variable *Dest = getDest(); |
| 1421 const Operand *Src1 = getSrc(1); | 1479 const Operand *Src1 = getSrc(1); |
| 1422 const Operand *Src2 = getSrc(2); | 1480 const Operand *Src2 = getSrc(2); |
| 1423 static const x86::AssemblerX86::GPREmitterShiftD Emitter = { | 1481 static const x86::AssemblerX86::GPREmitterShiftD Emitter = { |
| 1424 &x86::AssemblerX86::shrd, &x86::AssemblerX86::shrd}; | 1482 &x86::AssemblerX86::shrd, &x86::AssemblerX86::shrd}; |
| 1425 emitIASGPRShiftDouble(Func, Dest, Src1, Src2, Emitter); | 1483 emitIASGPRShiftDouble(Func, Dest, Src1, Src2, Emitter); |
| 1426 } | 1484 } |
| 1427 | 1485 |
| 1428 void InstX8632Shrd::dump(const Cfg *Func) const { | 1486 void InstX8632Shrd::dump(const Cfg *Func) const { |
| 1487 if (!ALLOW_DUMP) |
| 1488 return; |
| 1429 Ostream &Str = Func->getContext()->getStrDump(); | 1489 Ostream &Str = Func->getContext()->getStrDump(); |
| 1430 dumpDest(Func); | 1490 dumpDest(Func); |
| 1431 Str << " = shrd." << getDest()->getType() << " "; | 1491 Str << " = shrd." << getDest()->getType() << " "; |
| 1432 dumpSources(Func); | 1492 dumpSources(Func); |
| 1433 } | 1493 } |
| 1434 | 1494 |
| 1435 void InstX8632Cmov::emit(const Cfg *Func) const { | 1495 void InstX8632Cmov::emit(const Cfg *Func) const { |
| 1496 if (!ALLOW_DUMP) |
| 1497 return; |
| 1436 Ostream &Str = Func->getContext()->getStrEmit(); | 1498 Ostream &Str = Func->getContext()->getStrEmit(); |
| 1437 Variable *Dest = getDest(); | 1499 Variable *Dest = getDest(); |
| 1438 Str << "\t"; | 1500 Str << "\t"; |
| 1439 assert(Condition != CondX86::Br_None); | 1501 assert(Condition != CondX86::Br_None); |
| 1440 assert(getDest()->hasReg()); | 1502 assert(getDest()->hasReg()); |
| 1441 Str << "cmov" << InstX8632BrAttributes[Condition].DisplayString | 1503 Str << "cmov" << InstX8632BrAttributes[Condition].DisplayString |
| 1442 << getWidthString(Dest->getType()) << "\t"; | 1504 << getWidthString(Dest->getType()) << "\t"; |
| 1443 getSrc(1)->emit(Func); | 1505 getSrc(1)->emit(Func); |
| 1444 Str << ", "; | 1506 Str << ", "; |
| 1445 Dest->emit(Func); | 1507 Dest->emit(Func); |
| 1446 } | 1508 } |
| 1447 | 1509 |
| 1448 void InstX8632Cmov::emitIAS(const Cfg *Func) const { | 1510 void InstX8632Cmov::emitIAS(const Cfg *Func) const { |
| 1449 assert(Condition != CondX86::Br_None); | 1511 assert(Condition != CondX86::Br_None); |
| 1450 assert(getDest()->hasReg()); | 1512 assert(getDest()->hasReg()); |
| 1451 assert(getSrcSize() == 2); | 1513 assert(getSrcSize() == 2); |
| 1452 // Only need the reg/reg form now. | 1514 // Only need the reg/reg form now. |
| 1453 const auto SrcVar = llvm::cast<Variable>(getSrc(1)); | 1515 const auto SrcVar = llvm::cast<Variable>(getSrc(1)); |
| 1454 assert(SrcVar->hasReg()); | 1516 assert(SrcVar->hasReg()); |
| 1455 assert(SrcVar->getType() == IceType_i32); | 1517 assert(SrcVar->getType() == IceType_i32); |
| 1456 x86::AssemblerX86 *Asm = Func->getAssembler<x86::AssemblerX86>(); | 1518 x86::AssemblerX86 *Asm = Func->getAssembler<x86::AssemblerX86>(); |
| 1457 Asm->cmov(Condition, RegX8632::getEncodedGPR(getDest()->getRegNum()), | 1519 Asm->cmov(Condition, RegX8632::getEncodedGPR(getDest()->getRegNum()), |
| 1458 RegX8632::getEncodedGPR(SrcVar->getRegNum())); | 1520 RegX8632::getEncodedGPR(SrcVar->getRegNum())); |
| 1459 } | 1521 } |
| 1460 | 1522 |
| 1461 void InstX8632Cmov::dump(const Cfg *Func) const { | 1523 void InstX8632Cmov::dump(const Cfg *Func) const { |
| 1524 if (!ALLOW_DUMP) |
| 1525 return; |
| 1462 Ostream &Str = Func->getContext()->getStrDump(); | 1526 Ostream &Str = Func->getContext()->getStrDump(); |
| 1463 Str << "cmov" << InstX8632BrAttributes[Condition].DisplayString << "."; | 1527 Str << "cmov" << InstX8632BrAttributes[Condition].DisplayString << "."; |
| 1464 Str << getDest()->getType() << " "; | 1528 Str << getDest()->getType() << " "; |
| 1465 dumpDest(Func); | 1529 dumpDest(Func); |
| 1466 Str << ", "; | 1530 Str << ", "; |
| 1467 dumpSources(Func); | 1531 dumpSources(Func); |
| 1468 } | 1532 } |
| 1469 | 1533 |
| 1470 void InstX8632Cmpps::emit(const Cfg *Func) const { | 1534 void InstX8632Cmpps::emit(const Cfg *Func) const { |
| 1535 if (!ALLOW_DUMP) |
| 1536 return; |
| 1471 Ostream &Str = Func->getContext()->getStrEmit(); | 1537 Ostream &Str = Func->getContext()->getStrEmit(); |
| 1472 assert(getSrcSize() == 2); | 1538 assert(getSrcSize() == 2); |
| 1473 assert(Condition < CondX86::Cmpps_Invalid); | 1539 assert(Condition < CondX86::Cmpps_Invalid); |
| 1474 Str << "\t"; | 1540 Str << "\t"; |
| 1475 Str << "cmp" << InstX8632CmppsAttributes[Condition].EmitString << "ps" | 1541 Str << "cmp" << InstX8632CmppsAttributes[Condition].EmitString << "ps" |
| 1476 << "\t"; | 1542 << "\t"; |
| 1477 getSrc(1)->emit(Func); | 1543 getSrc(1)->emit(Func); |
| 1478 Str << ", "; | 1544 Str << ", "; |
| 1479 getDest()->emit(Func); | 1545 getDest()->emit(Func); |
| 1480 } | 1546 } |
| (...skipping 11 matching lines...) Expand all Loading... |
| 1492 RegX8632::getEncodedXmm(SrcVar->getRegNum()), Condition); | 1558 RegX8632::getEncodedXmm(SrcVar->getRegNum()), Condition); |
| 1493 } else { | 1559 } else { |
| 1494 x86::Address SrcStackAddr = static_cast<TargetX8632 *>(Func->getTarget()) | 1560 x86::Address SrcStackAddr = static_cast<TargetX8632 *>(Func->getTarget()) |
| 1495 ->stackVarToAsmOperand(SrcVar); | 1561 ->stackVarToAsmOperand(SrcVar); |
| 1496 Asm->cmpps(RegX8632::getEncodedXmm(getDest()->getRegNum()), SrcStackAddr, | 1562 Asm->cmpps(RegX8632::getEncodedXmm(getDest()->getRegNum()), SrcStackAddr, |
| 1497 Condition); | 1563 Condition); |
| 1498 } | 1564 } |
| 1499 } | 1565 } |
| 1500 | 1566 |
| 1501 void InstX8632Cmpps::dump(const Cfg *Func) const { | 1567 void InstX8632Cmpps::dump(const Cfg *Func) const { |
| 1568 if (!ALLOW_DUMP) |
| 1569 return; |
| 1502 Ostream &Str = Func->getContext()->getStrDump(); | 1570 Ostream &Str = Func->getContext()->getStrDump(); |
| 1503 assert(Condition < CondX86::Cmpps_Invalid); | 1571 assert(Condition < CondX86::Cmpps_Invalid); |
| 1504 dumpDest(Func); | 1572 dumpDest(Func); |
| 1505 Str << " = cmp" << InstX8632CmppsAttributes[Condition].EmitString << "ps" | 1573 Str << " = cmp" << InstX8632CmppsAttributes[Condition].EmitString << "ps" |
| 1506 << "\t"; | 1574 << "\t"; |
| 1507 dumpSources(Func); | 1575 dumpSources(Func); |
| 1508 } | 1576 } |
| 1509 | 1577 |
| 1510 void InstX8632Cmpxchg::emit(const Cfg *Func) const { | 1578 void InstX8632Cmpxchg::emit(const Cfg *Func) const { |
| 1579 if (!ALLOW_DUMP) |
| 1580 return; |
| 1511 Ostream &Str = Func->getContext()->getStrEmit(); | 1581 Ostream &Str = Func->getContext()->getStrEmit(); |
| 1512 assert(getSrcSize() == 3); | 1582 assert(getSrcSize() == 3); |
| 1513 if (Locked) { | 1583 if (Locked) { |
| 1514 Str << "\tlock"; | 1584 Str << "\tlock"; |
| 1515 } | 1585 } |
| 1516 Str << "\tcmpxchg" << getWidthString(getSrc(0)->getType()) << "\t"; | 1586 Str << "\tcmpxchg" << getWidthString(getSrc(0)->getType()) << "\t"; |
| 1517 getSrc(2)->emit(Func); | 1587 getSrc(2)->emit(Func); |
| 1518 Str << ", "; | 1588 Str << ", "; |
| 1519 getSrc(0)->emit(Func); | 1589 getSrc(0)->emit(Func); |
| 1520 } | 1590 } |
| (...skipping 10 matching lines...) Expand all Loading... |
| 1531 const RegX8632::GPRRegister Reg = | 1601 const RegX8632::GPRRegister Reg = |
| 1532 RegX8632::getEncodedGPR(VarReg->getRegNum()); | 1602 RegX8632::getEncodedGPR(VarReg->getRegNum()); |
| 1533 if (Locked) { | 1603 if (Locked) { |
| 1534 Asm->LockCmpxchg(Ty, Addr, Reg); | 1604 Asm->LockCmpxchg(Ty, Addr, Reg); |
| 1535 } else { | 1605 } else { |
| 1536 Asm->cmpxchg(Ty, Addr, Reg); | 1606 Asm->cmpxchg(Ty, Addr, Reg); |
| 1537 } | 1607 } |
| 1538 } | 1608 } |
| 1539 | 1609 |
| 1540 void InstX8632Cmpxchg::dump(const Cfg *Func) const { | 1610 void InstX8632Cmpxchg::dump(const Cfg *Func) const { |
| 1611 if (!ALLOW_DUMP) |
| 1612 return; |
| 1541 Ostream &Str = Func->getContext()->getStrDump(); | 1613 Ostream &Str = Func->getContext()->getStrDump(); |
| 1542 if (Locked) { | 1614 if (Locked) { |
| 1543 Str << "lock "; | 1615 Str << "lock "; |
| 1544 } | 1616 } |
| 1545 Str << "cmpxchg." << getSrc(0)->getType() << " "; | 1617 Str << "cmpxchg." << getSrc(0)->getType() << " "; |
| 1546 dumpSources(Func); | 1618 dumpSources(Func); |
| 1547 } | 1619 } |
| 1548 | 1620 |
| 1549 void InstX8632Cmpxchg8b::emit(const Cfg *Func) const { | 1621 void InstX8632Cmpxchg8b::emit(const Cfg *Func) const { |
| 1622 if (!ALLOW_DUMP) |
| 1623 return; |
| 1550 Ostream &Str = Func->getContext()->getStrEmit(); | 1624 Ostream &Str = Func->getContext()->getStrEmit(); |
| 1551 assert(getSrcSize() == 5); | 1625 assert(getSrcSize() == 5); |
| 1552 if (Locked) { | 1626 if (Locked) { |
| 1553 Str << "\tlock"; | 1627 Str << "\tlock"; |
| 1554 } | 1628 } |
| 1555 Str << "\tcmpxchg8b\t"; | 1629 Str << "\tcmpxchg8b\t"; |
| 1556 getSrc(0)->emit(Func); | 1630 getSrc(0)->emit(Func); |
| 1557 } | 1631 } |
| 1558 | 1632 |
| 1559 void InstX8632Cmpxchg8b::emitIAS(const Cfg *Func) const { | 1633 void InstX8632Cmpxchg8b::emitIAS(const Cfg *Func) const { |
| 1560 assert(getSrcSize() == 5); | 1634 assert(getSrcSize() == 5); |
| 1561 x86::AssemblerX86 *Asm = Func->getAssembler<x86::AssemblerX86>(); | 1635 x86::AssemblerX86 *Asm = Func->getAssembler<x86::AssemblerX86>(); |
| 1562 const auto Mem = llvm::cast<OperandX8632Mem>(getSrc(0)); | 1636 const auto Mem = llvm::cast<OperandX8632Mem>(getSrc(0)); |
| 1563 assert(Mem->getSegmentRegister() == OperandX8632Mem::DefaultSegment); | 1637 assert(Mem->getSegmentRegister() == OperandX8632Mem::DefaultSegment); |
| 1564 const x86::Address Addr = Mem->toAsmAddress(Asm); | 1638 const x86::Address Addr = Mem->toAsmAddress(Asm); |
| 1565 if (Locked) { | 1639 if (Locked) { |
| 1566 Asm->lock(); | 1640 Asm->lock(); |
| 1567 } | 1641 } |
| 1568 Asm->cmpxchg8b(Addr); | 1642 Asm->cmpxchg8b(Addr); |
| 1569 } | 1643 } |
| 1570 | 1644 |
| 1571 void InstX8632Cmpxchg8b::dump(const Cfg *Func) const { | 1645 void InstX8632Cmpxchg8b::dump(const Cfg *Func) const { |
| 1646 if (!ALLOW_DUMP) |
| 1647 return; |
| 1572 Ostream &Str = Func->getContext()->getStrDump(); | 1648 Ostream &Str = Func->getContext()->getStrDump(); |
| 1573 if (Locked) { | 1649 if (Locked) { |
| 1574 Str << "lock "; | 1650 Str << "lock "; |
| 1575 } | 1651 } |
| 1576 Str << "cmpxchg8b "; | 1652 Str << "cmpxchg8b "; |
| 1577 dumpSources(Func); | 1653 dumpSources(Func); |
| 1578 } | 1654 } |
| 1579 | 1655 |
| 1580 void InstX8632Cvt::emit(const Cfg *Func) const { | 1656 void InstX8632Cvt::emit(const Cfg *Func) const { |
| 1657 if (!ALLOW_DUMP) |
| 1658 return; |
| 1581 Ostream &Str = Func->getContext()->getStrEmit(); | 1659 Ostream &Str = Func->getContext()->getStrEmit(); |
| 1582 assert(getSrcSize() == 1); | 1660 assert(getSrcSize() == 1); |
| 1583 Str << "\tcvt"; | 1661 Str << "\tcvt"; |
| 1584 if (isTruncating()) | 1662 if (isTruncating()) |
| 1585 Str << "t"; | 1663 Str << "t"; |
| 1586 Str << TypeX8632Attributes[getSrc(0)->getType()].CvtString << "2" | 1664 Str << TypeX8632Attributes[getSrc(0)->getType()].CvtString << "2" |
| 1587 << TypeX8632Attributes[getDest()->getType()].CvtString << "\t"; | 1665 << TypeX8632Attributes[getDest()->getType()].CvtString << "\t"; |
| 1588 getSrc(0)->emit(Func); | 1666 getSrc(0)->emit(Func); |
| 1589 Str << ", "; | 1667 Str << ", "; |
| 1590 getDest()->emit(Func); | 1668 getDest()->emit(Func); |
| (...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1643 assert(isVectorIntegerType(DestTy)); | 1721 assert(isVectorIntegerType(DestTy)); |
| 1644 static const x86::AssemblerX86::XmmEmitterRegOp Emitter = { | 1722 static const x86::AssemblerX86::XmmEmitterRegOp Emitter = { |
| 1645 &x86::AssemblerX86::cvttps2dq, &x86::AssemblerX86::cvttps2dq}; | 1723 &x86::AssemblerX86::cvttps2dq, &x86::AssemblerX86::cvttps2dq}; |
| 1646 emitIASRegOpTyXMM(Func, DestTy, Dest, Src, Emitter); | 1724 emitIASRegOpTyXMM(Func, DestTy, Dest, Src, Emitter); |
| 1647 return; | 1725 return; |
| 1648 } | 1726 } |
| 1649 } | 1727 } |
| 1650 } | 1728 } |
| 1651 | 1729 |
| 1652 void InstX8632Cvt::dump(const Cfg *Func) const { | 1730 void InstX8632Cvt::dump(const Cfg *Func) const { |
| 1731 if (!ALLOW_DUMP) |
| 1732 return; |
| 1653 Ostream &Str = Func->getContext()->getStrDump(); | 1733 Ostream &Str = Func->getContext()->getStrDump(); |
| 1654 dumpDest(Func); | 1734 dumpDest(Func); |
| 1655 Str << " = cvt"; | 1735 Str << " = cvt"; |
| 1656 if (isTruncating()) | 1736 if (isTruncating()) |
| 1657 Str << "t"; | 1737 Str << "t"; |
| 1658 Str << TypeX8632Attributes[getSrc(0)->getType()].CvtString << "2" | 1738 Str << TypeX8632Attributes[getSrc(0)->getType()].CvtString << "2" |
| 1659 << TypeX8632Attributes[getDest()->getType()].CvtString << " "; | 1739 << TypeX8632Attributes[getDest()->getType()].CvtString << " "; |
| 1660 dumpSources(Func); | 1740 dumpSources(Func); |
| 1661 } | 1741 } |
| 1662 | 1742 |
| 1663 void InstX8632Icmp::emit(const Cfg *Func) const { | 1743 void InstX8632Icmp::emit(const Cfg *Func) const { |
| 1744 if (!ALLOW_DUMP) |
| 1745 return; |
| 1664 Ostream &Str = Func->getContext()->getStrEmit(); | 1746 Ostream &Str = Func->getContext()->getStrEmit(); |
| 1665 assert(getSrcSize() == 2); | 1747 assert(getSrcSize() == 2); |
| 1666 Str << "\tcmp" << getWidthString(getSrc(0)->getType()) << "\t"; | 1748 Str << "\tcmp" << getWidthString(getSrc(0)->getType()) << "\t"; |
| 1667 getSrc(1)->emit(Func); | 1749 getSrc(1)->emit(Func); |
| 1668 Str << ", "; | 1750 Str << ", "; |
| 1669 getSrc(0)->emit(Func); | 1751 getSrc(0)->emit(Func); |
| 1670 } | 1752 } |
| 1671 | 1753 |
| 1672 void InstX8632Icmp::emitIAS(const Cfg *Func) const { | 1754 void InstX8632Icmp::emitIAS(const Cfg *Func) const { |
| 1673 assert(getSrcSize() == 2); | 1755 assert(getSrcSize() == 2); |
| 1674 const Operand *Src0 = getSrc(0); | 1756 const Operand *Src0 = getSrc(0); |
| 1675 const Operand *Src1 = getSrc(1); | 1757 const Operand *Src1 = getSrc(1); |
| 1676 Type Ty = Src0->getType(); | 1758 Type Ty = Src0->getType(); |
| 1677 static const x86::AssemblerX86::GPREmitterRegOp RegEmitter = { | 1759 static const x86::AssemblerX86::GPREmitterRegOp RegEmitter = { |
| 1678 &x86::AssemblerX86::cmp, &x86::AssemblerX86::cmp, &x86::AssemblerX86::cmp | 1760 &x86::AssemblerX86::cmp, &x86::AssemblerX86::cmp, &x86::AssemblerX86::cmp |
| 1679 }; | 1761 }; |
| 1680 static const x86::AssemblerX86::GPREmitterAddrOp AddrEmitter = { | 1762 static const x86::AssemblerX86::GPREmitterAddrOp AddrEmitter = { |
| 1681 &x86::AssemblerX86::cmp, &x86::AssemblerX86::cmp | 1763 &x86::AssemblerX86::cmp, &x86::AssemblerX86::cmp |
| 1682 }; | 1764 }; |
| 1683 if (const auto SrcVar0 = llvm::dyn_cast<Variable>(Src0)) { | 1765 if (const auto SrcVar0 = llvm::dyn_cast<Variable>(Src0)) { |
| 1684 if (SrcVar0->hasReg()) { | 1766 if (SrcVar0->hasReg()) { |
| 1685 emitIASRegOpTyGPR(Func, Ty, SrcVar0, Src1, RegEmitter); | 1767 emitIASRegOpTyGPR(Func, Ty, SrcVar0, Src1, RegEmitter); |
| 1686 return; | 1768 return; |
| 1687 } | 1769 } |
| 1688 } | 1770 } |
| 1689 emitIASAsAddrOpTyGPR(Func, Ty, Src0, Src1, AddrEmitter); | 1771 emitIASAsAddrOpTyGPR(Func, Ty, Src0, Src1, AddrEmitter); |
| 1690 } | 1772 } |
| 1691 | 1773 |
| 1692 void InstX8632Icmp::dump(const Cfg *Func) const { | 1774 void InstX8632Icmp::dump(const Cfg *Func) const { |
| 1775 if (!ALLOW_DUMP) |
| 1776 return; |
| 1693 Ostream &Str = Func->getContext()->getStrDump(); | 1777 Ostream &Str = Func->getContext()->getStrDump(); |
| 1694 Str << "cmp." << getSrc(0)->getType() << " "; | 1778 Str << "cmp." << getSrc(0)->getType() << " "; |
| 1695 dumpSources(Func); | 1779 dumpSources(Func); |
| 1696 } | 1780 } |
| 1697 | 1781 |
| 1698 void InstX8632Ucomiss::emit(const Cfg *Func) const { | 1782 void InstX8632Ucomiss::emit(const Cfg *Func) const { |
| 1783 if (!ALLOW_DUMP) |
| 1784 return; |
| 1699 Ostream &Str = Func->getContext()->getStrEmit(); | 1785 Ostream &Str = Func->getContext()->getStrEmit(); |
| 1700 assert(getSrcSize() == 2); | 1786 assert(getSrcSize() == 2); |
| 1701 Str << "\tucomi" << TypeX8632Attributes[getSrc(0)->getType()].SdSsString | 1787 Str << "\tucomi" << TypeX8632Attributes[getSrc(0)->getType()].SdSsString |
| 1702 << "\t"; | 1788 << "\t"; |
| 1703 getSrc(1)->emit(Func); | 1789 getSrc(1)->emit(Func); |
| 1704 Str << ", "; | 1790 Str << ", "; |
| 1705 getSrc(0)->emit(Func); | 1791 getSrc(0)->emit(Func); |
| 1706 } | 1792 } |
| 1707 | 1793 |
| 1708 void InstX8632Ucomiss::emitIAS(const Cfg *Func) const { | 1794 void InstX8632Ucomiss::emitIAS(const Cfg *Func) const { |
| 1709 assert(getSrcSize() == 2); | 1795 assert(getSrcSize() == 2); |
| 1710 // Currently src0 is always a variable by convention, to avoid having | 1796 // Currently src0 is always a variable by convention, to avoid having |
| 1711 // two memory operands. | 1797 // two memory operands. |
| 1712 assert(llvm::isa<Variable>(getSrc(0))); | 1798 assert(llvm::isa<Variable>(getSrc(0))); |
| 1713 const auto Src0Var = llvm::cast<Variable>(getSrc(0)); | 1799 const auto Src0Var = llvm::cast<Variable>(getSrc(0)); |
| 1714 Type Ty = Src0Var->getType(); | 1800 Type Ty = Src0Var->getType(); |
| 1715 const static x86::AssemblerX86::XmmEmitterRegOp Emitter = { | 1801 const static x86::AssemblerX86::XmmEmitterRegOp Emitter = { |
| 1716 &x86::AssemblerX86::ucomiss, &x86::AssemblerX86::ucomiss | 1802 &x86::AssemblerX86::ucomiss, &x86::AssemblerX86::ucomiss |
| 1717 }; | 1803 }; |
| 1718 emitIASRegOpTyXMM(Func, Ty, Src0Var, getSrc(1), Emitter); | 1804 emitIASRegOpTyXMM(Func, Ty, Src0Var, getSrc(1), Emitter); |
| 1719 } | 1805 } |
| 1720 | 1806 |
| 1721 void InstX8632Ucomiss::dump(const Cfg *Func) const { | 1807 void InstX8632Ucomiss::dump(const Cfg *Func) const { |
| 1808 if (!ALLOW_DUMP) |
| 1809 return; |
| 1722 Ostream &Str = Func->getContext()->getStrDump(); | 1810 Ostream &Str = Func->getContext()->getStrDump(); |
| 1723 Str << "ucomiss." << getSrc(0)->getType() << " "; | 1811 Str << "ucomiss." << getSrc(0)->getType() << " "; |
| 1724 dumpSources(Func); | 1812 dumpSources(Func); |
| 1725 } | 1813 } |
| 1726 | 1814 |
| 1727 void InstX8632UD2::emit(const Cfg *Func) const { | 1815 void InstX8632UD2::emit(const Cfg *Func) const { |
| 1816 if (!ALLOW_DUMP) |
| 1817 return; |
| 1728 Ostream &Str = Func->getContext()->getStrEmit(); | 1818 Ostream &Str = Func->getContext()->getStrEmit(); |
| 1729 assert(getSrcSize() == 0); | 1819 assert(getSrcSize() == 0); |
| 1730 Str << "\tud2"; | 1820 Str << "\tud2"; |
| 1731 } | 1821 } |
| 1732 | 1822 |
| 1733 void InstX8632UD2::emitIAS(const Cfg *Func) const { | 1823 void InstX8632UD2::emitIAS(const Cfg *Func) const { |
| 1734 x86::AssemblerX86 *Asm = Func->getAssembler<x86::AssemblerX86>(); | 1824 x86::AssemblerX86 *Asm = Func->getAssembler<x86::AssemblerX86>(); |
| 1735 Asm->ud2(); | 1825 Asm->ud2(); |
| 1736 } | 1826 } |
| 1737 | 1827 |
| 1738 void InstX8632UD2::dump(const Cfg *Func) const { | 1828 void InstX8632UD2::dump(const Cfg *Func) const { |
| 1829 if (!ALLOW_DUMP) |
| 1830 return; |
| 1739 Ostream &Str = Func->getContext()->getStrDump(); | 1831 Ostream &Str = Func->getContext()->getStrDump(); |
| 1740 Str << "ud2\n"; | 1832 Str << "ud2\n"; |
| 1741 } | 1833 } |
| 1742 | 1834 |
| 1743 void InstX8632Test::emit(const Cfg *Func) const { | 1835 void InstX8632Test::emit(const Cfg *Func) const { |
| 1836 if (!ALLOW_DUMP) |
| 1837 return; |
| 1744 Ostream &Str = Func->getContext()->getStrEmit(); | 1838 Ostream &Str = Func->getContext()->getStrEmit(); |
| 1745 assert(getSrcSize() == 2); | 1839 assert(getSrcSize() == 2); |
| 1746 Str << "\ttest" << getWidthString(getSrc(0)->getType()) << "\t"; | 1840 Str << "\ttest" << getWidthString(getSrc(0)->getType()) << "\t"; |
| 1747 getSrc(1)->emit(Func); | 1841 getSrc(1)->emit(Func); |
| 1748 Str << ", "; | 1842 Str << ", "; |
| 1749 getSrc(0)->emit(Func); | 1843 getSrc(0)->emit(Func); |
| 1750 } | 1844 } |
| 1751 | 1845 |
| 1752 void InstX8632Test::emitIAS(const Cfg *Func) const { | 1846 void InstX8632Test::emitIAS(const Cfg *Func) const { |
| 1753 assert(getSrcSize() == 2); | 1847 assert(getSrcSize() == 2); |
| (...skipping 10 matching lines...) Expand all Loading... |
| 1764 if (SrcVar0->hasReg()) { | 1858 if (SrcVar0->hasReg()) { |
| 1765 emitIASRegOpTyGPR(Func, Ty, SrcVar0, Src1, RegEmitter); | 1859 emitIASRegOpTyGPR(Func, Ty, SrcVar0, Src1, RegEmitter); |
| 1766 return; | 1860 return; |
| 1767 } | 1861 } |
| 1768 } | 1862 } |
| 1769 llvm_unreachable("Nothing actually generates this so it's untested"); | 1863 llvm_unreachable("Nothing actually generates this so it's untested"); |
| 1770 emitIASAsAddrOpTyGPR(Func, Ty, Src0, Src1, AddrEmitter); | 1864 emitIASAsAddrOpTyGPR(Func, Ty, Src0, Src1, AddrEmitter); |
| 1771 } | 1865 } |
| 1772 | 1866 |
| 1773 void InstX8632Test::dump(const Cfg *Func) const { | 1867 void InstX8632Test::dump(const Cfg *Func) const { |
| 1868 if (!ALLOW_DUMP) |
| 1869 return; |
| 1774 Ostream &Str = Func->getContext()->getStrDump(); | 1870 Ostream &Str = Func->getContext()->getStrDump(); |
| 1775 Str << "test." << getSrc(0)->getType() << " "; | 1871 Str << "test." << getSrc(0)->getType() << " "; |
| 1776 dumpSources(Func); | 1872 dumpSources(Func); |
| 1777 } | 1873 } |
| 1778 | 1874 |
| 1779 void InstX8632Mfence::emit(const Cfg *Func) const { | 1875 void InstX8632Mfence::emit(const Cfg *Func) const { |
| 1876 if (!ALLOW_DUMP) |
| 1877 return; |
| 1780 Ostream &Str = Func->getContext()->getStrEmit(); | 1878 Ostream &Str = Func->getContext()->getStrEmit(); |
| 1781 assert(getSrcSize() == 0); | 1879 assert(getSrcSize() == 0); |
| 1782 Str << "\tmfence"; | 1880 Str << "\tmfence"; |
| 1783 } | 1881 } |
| 1784 | 1882 |
| 1785 void InstX8632Mfence::emitIAS(const Cfg *Func) const { | 1883 void InstX8632Mfence::emitIAS(const Cfg *Func) const { |
| 1786 x86::AssemblerX86 *Asm = Func->getAssembler<x86::AssemblerX86>(); | 1884 x86::AssemblerX86 *Asm = Func->getAssembler<x86::AssemblerX86>(); |
| 1787 Asm->mfence(); | 1885 Asm->mfence(); |
| 1788 } | 1886 } |
| 1789 | 1887 |
| 1790 void InstX8632Mfence::dump(const Cfg *Func) const { | 1888 void InstX8632Mfence::dump(const Cfg *Func) const { |
| 1889 if (!ALLOW_DUMP) |
| 1890 return; |
| 1791 Ostream &Str = Func->getContext()->getStrDump(); | 1891 Ostream &Str = Func->getContext()->getStrDump(); |
| 1792 Str << "mfence\n"; | 1892 Str << "mfence\n"; |
| 1793 } | 1893 } |
| 1794 | 1894 |
| 1795 void InstX8632Store::emit(const Cfg *Func) const { | 1895 void InstX8632Store::emit(const Cfg *Func) const { |
| 1896 if (!ALLOW_DUMP) |
| 1897 return; |
| 1796 Ostream &Str = Func->getContext()->getStrEmit(); | 1898 Ostream &Str = Func->getContext()->getStrEmit(); |
| 1797 assert(getSrcSize() == 2); | 1899 assert(getSrcSize() == 2); |
| 1798 Type Ty = getSrc(0)->getType(); | 1900 Type Ty = getSrc(0)->getType(); |
| 1799 Str << "\tmov" << getWidthString(Ty) << TypeX8632Attributes[Ty].SdSsString | 1901 Str << "\tmov" << getWidthString(Ty) << TypeX8632Attributes[Ty].SdSsString |
| 1800 << "\t"; | 1902 << "\t"; |
| 1801 getSrc(0)->emit(Func); | 1903 getSrc(0)->emit(Func); |
| 1802 Str << ", "; | 1904 Str << ", "; |
| 1803 getSrc(1)->emit(Func); | 1905 getSrc(1)->emit(Func); |
| 1804 } | 1906 } |
| 1805 | 1907 |
| (...skipping 21 matching lines...) Expand all Loading... |
| 1827 return; | 1929 return; |
| 1828 } else { | 1930 } else { |
| 1829 assert(isScalarIntegerType(DestTy)); | 1931 assert(isScalarIntegerType(DestTy)); |
| 1830 static const x86::AssemblerX86::GPREmitterAddrOp GPRAddrEmitter = { | 1932 static const x86::AssemblerX86::GPREmitterAddrOp GPRAddrEmitter = { |
| 1831 &x86::AssemblerX86::mov, &x86::AssemblerX86::mov}; | 1933 &x86::AssemblerX86::mov, &x86::AssemblerX86::mov}; |
| 1832 emitIASAsAddrOpTyGPR(Func, DestTy, Dest, Src, GPRAddrEmitter); | 1934 emitIASAsAddrOpTyGPR(Func, DestTy, Dest, Src, GPRAddrEmitter); |
| 1833 } | 1935 } |
| 1834 } | 1936 } |
| 1835 | 1937 |
| 1836 void InstX8632Store::dump(const Cfg *Func) const { | 1938 void InstX8632Store::dump(const Cfg *Func) const { |
| 1939 if (!ALLOW_DUMP) |
| 1940 return; |
| 1837 Ostream &Str = Func->getContext()->getStrDump(); | 1941 Ostream &Str = Func->getContext()->getStrDump(); |
| 1838 Str << "mov." << getSrc(0)->getType() << " "; | 1942 Str << "mov." << getSrc(0)->getType() << " "; |
| 1839 getSrc(1)->dump(Func); | 1943 getSrc(1)->dump(Func); |
| 1840 Str << ", "; | 1944 Str << ", "; |
| 1841 getSrc(0)->dump(Func); | 1945 getSrc(0)->dump(Func); |
| 1842 } | 1946 } |
| 1843 | 1947 |
| 1844 void InstX8632StoreP::emit(const Cfg *Func) const { | 1948 void InstX8632StoreP::emit(const Cfg *Func) const { |
| 1949 if (!ALLOW_DUMP) |
| 1950 return; |
| 1845 Ostream &Str = Func->getContext()->getStrEmit(); | 1951 Ostream &Str = Func->getContext()->getStrEmit(); |
| 1846 assert(getSrcSize() == 2); | 1952 assert(getSrcSize() == 2); |
| 1847 Str << "\tmovups\t"; | 1953 Str << "\tmovups\t"; |
| 1848 getSrc(0)->emit(Func); | 1954 getSrc(0)->emit(Func); |
| 1849 Str << ", "; | 1955 Str << ", "; |
| 1850 getSrc(1)->emit(Func); | 1956 getSrc(1)->emit(Func); |
| 1851 } | 1957 } |
| 1852 | 1958 |
| 1853 void InstX8632StoreP::emitIAS(const Cfg *Func) const { | 1959 void InstX8632StoreP::emitIAS(const Cfg *Func) const { |
| 1854 x86::AssemblerX86 *Asm = Func->getAssembler<x86::AssemblerX86>(); | 1960 x86::AssemblerX86 *Asm = Func->getAssembler<x86::AssemblerX86>(); |
| 1855 assert(getSrcSize() == 2); | 1961 assert(getSrcSize() == 2); |
| 1856 const auto SrcVar = llvm::cast<Variable>(getSrc(0)); | 1962 const auto SrcVar = llvm::cast<Variable>(getSrc(0)); |
| 1857 const auto DestMem = llvm::cast<OperandX8632Mem>(getSrc(1)); | 1963 const auto DestMem = llvm::cast<OperandX8632Mem>(getSrc(1)); |
| 1858 assert(DestMem->getSegmentRegister() == OperandX8632Mem::DefaultSegment); | 1964 assert(DestMem->getSegmentRegister() == OperandX8632Mem::DefaultSegment); |
| 1859 assert(SrcVar->hasReg()); | 1965 assert(SrcVar->hasReg()); |
| 1860 Asm->movups(DestMem->toAsmAddress(Asm), | 1966 Asm->movups(DestMem->toAsmAddress(Asm), |
| 1861 RegX8632::getEncodedXmm(SrcVar->getRegNum())); | 1967 RegX8632::getEncodedXmm(SrcVar->getRegNum())); |
| 1862 } | 1968 } |
| 1863 | 1969 |
| 1864 void InstX8632StoreP::dump(const Cfg *Func) const { | 1970 void InstX8632StoreP::dump(const Cfg *Func) const { |
| 1971 if (!ALLOW_DUMP) |
| 1972 return; |
| 1865 Ostream &Str = Func->getContext()->getStrDump(); | 1973 Ostream &Str = Func->getContext()->getStrDump(); |
| 1866 Str << "storep." << getSrc(0)->getType() << " "; | 1974 Str << "storep." << getSrc(0)->getType() << " "; |
| 1867 getSrc(1)->dump(Func); | 1975 getSrc(1)->dump(Func); |
| 1868 Str << ", "; | 1976 Str << ", "; |
| 1869 getSrc(0)->dump(Func); | 1977 getSrc(0)->dump(Func); |
| 1870 } | 1978 } |
| 1871 | 1979 |
| 1872 void InstX8632StoreQ::emit(const Cfg *Func) const { | 1980 void InstX8632StoreQ::emit(const Cfg *Func) const { |
| 1981 if (!ALLOW_DUMP) |
| 1982 return; |
| 1873 Ostream &Str = Func->getContext()->getStrEmit(); | 1983 Ostream &Str = Func->getContext()->getStrEmit(); |
| 1874 assert(getSrcSize() == 2); | 1984 assert(getSrcSize() == 2); |
| 1875 assert(getSrc(1)->getType() == IceType_i64 || | 1985 assert(getSrc(1)->getType() == IceType_i64 || |
| 1876 getSrc(1)->getType() == IceType_f64); | 1986 getSrc(1)->getType() == IceType_f64); |
| 1877 Str << "\tmovq\t"; | 1987 Str << "\tmovq\t"; |
| 1878 getSrc(0)->emit(Func); | 1988 getSrc(0)->emit(Func); |
| 1879 Str << ", "; | 1989 Str << ", "; |
| 1880 getSrc(1)->emit(Func); | 1990 getSrc(1)->emit(Func); |
| 1881 } | 1991 } |
| 1882 | 1992 |
| 1883 void InstX8632StoreQ::emitIAS(const Cfg *Func) const { | 1993 void InstX8632StoreQ::emitIAS(const Cfg *Func) const { |
| 1884 x86::AssemblerX86 *Asm = Func->getAssembler<x86::AssemblerX86>(); | 1994 x86::AssemblerX86 *Asm = Func->getAssembler<x86::AssemblerX86>(); |
| 1885 assert(getSrcSize() == 2); | 1995 assert(getSrcSize() == 2); |
| 1886 const auto SrcVar = llvm::cast<Variable>(getSrc(0)); | 1996 const auto SrcVar = llvm::cast<Variable>(getSrc(0)); |
| 1887 const auto DestMem = llvm::cast<OperandX8632Mem>(getSrc(1)); | 1997 const auto DestMem = llvm::cast<OperandX8632Mem>(getSrc(1)); |
| 1888 assert(DestMem->getSegmentRegister() == OperandX8632Mem::DefaultSegment); | 1998 assert(DestMem->getSegmentRegister() == OperandX8632Mem::DefaultSegment); |
| 1889 assert(SrcVar->hasReg()); | 1999 assert(SrcVar->hasReg()); |
| 1890 Asm->movq(DestMem->toAsmAddress(Asm), | 2000 Asm->movq(DestMem->toAsmAddress(Asm), |
| 1891 RegX8632::getEncodedXmm(SrcVar->getRegNum())); | 2001 RegX8632::getEncodedXmm(SrcVar->getRegNum())); |
| 1892 } | 2002 } |
| 1893 | 2003 |
| 1894 void InstX8632StoreQ::dump(const Cfg *Func) const { | 2004 void InstX8632StoreQ::dump(const Cfg *Func) const { |
| 2005 if (!ALLOW_DUMP) |
| 2006 return; |
| 1895 Ostream &Str = Func->getContext()->getStrDump(); | 2007 Ostream &Str = Func->getContext()->getStrDump(); |
| 1896 Str << "storeq." << getSrc(0)->getType() << " "; | 2008 Str << "storeq." << getSrc(0)->getType() << " "; |
| 1897 getSrc(1)->dump(Func); | 2009 getSrc(1)->dump(Func); |
| 1898 Str << ", "; | 2010 Str << ", "; |
| 1899 getSrc(0)->dump(Func); | 2011 getSrc(0)->dump(Func); |
| 1900 } | 2012 } |
| 1901 | 2013 |
| 1902 template <> void InstX8632Lea::emit(const Cfg *Func) const { | 2014 template <> void InstX8632Lea::emit(const Cfg *Func) const { |
| 2015 if (!ALLOW_DUMP) |
| 2016 return; |
| 1903 Ostream &Str = Func->getContext()->getStrEmit(); | 2017 Ostream &Str = Func->getContext()->getStrEmit(); |
| 1904 assert(getSrcSize() == 1); | 2018 assert(getSrcSize() == 1); |
| 1905 assert(getDest()->hasReg()); | 2019 assert(getDest()->hasReg()); |
| 1906 Str << "\tleal\t"; | 2020 Str << "\tleal\t"; |
| 1907 Operand *Src0 = getSrc(0); | 2021 Operand *Src0 = getSrc(0); |
| 1908 if (const auto Src0Var = llvm::dyn_cast<Variable>(Src0)) { | 2022 if (const auto Src0Var = llvm::dyn_cast<Variable>(Src0)) { |
| 1909 Type Ty = Src0Var->getType(); | 2023 Type Ty = Src0Var->getType(); |
| 1910 // lea on x86-32 doesn't accept mem128 operands, so cast VSrc0 to an | 2024 // lea on x86-32 doesn't accept mem128 operands, so cast VSrc0 to an |
| 1911 // acceptable type. | 2025 // acceptable type. |
| 1912 Src0Var->asType(isVectorType(Ty) ? IceType_i32 : Ty).emit(Func); | 2026 Src0Var->asType(isVectorType(Ty) ? IceType_i32 : Ty).emit(Func); |
| 1913 } else { | 2027 } else { |
| 1914 Src0->emit(Func); | 2028 Src0->emit(Func); |
| 1915 } | 2029 } |
| 1916 Str << ", "; | 2030 Str << ", "; |
| 1917 getDest()->emit(Func); | 2031 getDest()->emit(Func); |
| 1918 } | 2032 } |
| 1919 | 2033 |
| 1920 template <> void InstX8632Mov::emit(const Cfg *Func) const { | 2034 template <> void InstX8632Mov::emit(const Cfg *Func) const { |
| 2035 if (!ALLOW_DUMP) |
| 2036 return; |
| 1921 Ostream &Str = Func->getContext()->getStrEmit(); | 2037 Ostream &Str = Func->getContext()->getStrEmit(); |
| 1922 assert(getSrcSize() == 1); | 2038 assert(getSrcSize() == 1); |
| 1923 Operand *Src = getSrc(0); | 2039 Operand *Src = getSrc(0); |
| 1924 Type SrcTy = Src->getType(); | 2040 Type SrcTy = Src->getType(); |
| 1925 Type DestTy = getDest()->getType(); | 2041 Type DestTy = getDest()->getType(); |
| 1926 Str << "\tmov" << (!isScalarFloatingType(DestTy) | 2042 Str << "\tmov" << (!isScalarFloatingType(DestTy) |
| 1927 ? getWidthString(SrcTy) | 2043 ? getWidthString(SrcTy) |
| 1928 : TypeX8632Attributes[DestTy].SdSsString) << "\t"; | 2044 : TypeX8632Attributes[DestTy].SdSsString) << "\t"; |
| 1929 // For an integer truncation operation, src is wider than dest. | 2045 // For an integer truncation operation, src is wider than dest. |
| 1930 // Ideally, we use a mov instruction whose data width matches the | 2046 // Ideally, we use a mov instruction whose data width matches the |
| (...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2039 Asm->movd(RegX8632::getEncodedGPR(Dest->getRegNum()), SrcReg); | 2155 Asm->movd(RegX8632::getEncodedGPR(Dest->getRegNum()), SrcReg); |
| 2040 } else { | 2156 } else { |
| 2041 x86::Address StackAddr(static_cast<TargetX8632 *>(Func->getTarget()) | 2157 x86::Address StackAddr(static_cast<TargetX8632 *>(Func->getTarget()) |
| 2042 ->stackVarToAsmOperand(Dest)); | 2158 ->stackVarToAsmOperand(Dest)); |
| 2043 Asm->movd(StackAddr, SrcReg); | 2159 Asm->movd(StackAddr, SrcReg); |
| 2044 } | 2160 } |
| 2045 } | 2161 } |
| 2046 } | 2162 } |
| 2047 | 2163 |
| 2048 template <> void InstX8632Movp::emit(const Cfg *Func) const { | 2164 template <> void InstX8632Movp::emit(const Cfg *Func) const { |
| 2165 if (!ALLOW_DUMP) |
| 2166 return; |
| 2049 // TODO(wala,stichnot): movups works with all vector operands, but | 2167 // TODO(wala,stichnot): movups works with all vector operands, but |
| 2050 // there exist other instructions (movaps, movdqa, movdqu) that may | 2168 // there exist other instructions (movaps, movdqa, movdqu) that may |
| 2051 // perform better, depending on the data type and alignment of the | 2169 // perform better, depending on the data type and alignment of the |
| 2052 // operands. | 2170 // operands. |
| 2053 Ostream &Str = Func->getContext()->getStrEmit(); | 2171 Ostream &Str = Func->getContext()->getStrEmit(); |
| 2054 assert(getSrcSize() == 1); | 2172 assert(getSrcSize() == 1); |
| 2055 Str << "\tmovups\t"; | 2173 Str << "\tmovups\t"; |
| 2056 getSrc(0)->emit(Func); | 2174 getSrc(0)->emit(Func); |
| 2057 Str << ", "; | 2175 Str << ", "; |
| 2058 getDest()->emit(Func); | 2176 getDest()->emit(Func); |
| 2059 } | 2177 } |
| 2060 | 2178 |
| 2061 template <> void InstX8632Movp::emitIAS(const Cfg *Func) const { | 2179 template <> void InstX8632Movp::emitIAS(const Cfg *Func) const { |
| 2062 assert(getSrcSize() == 1); | 2180 assert(getSrcSize() == 1); |
| 2063 assert(isVectorType(getDest()->getType())); | 2181 assert(isVectorType(getDest()->getType())); |
| 2064 const Variable *Dest = getDest(); | 2182 const Variable *Dest = getDest(); |
| 2065 const Operand *Src = getSrc(0); | 2183 const Operand *Src = getSrc(0); |
| 2066 const static x86::AssemblerX86::XmmEmitterMovOps Emitter = { | 2184 const static x86::AssemblerX86::XmmEmitterMovOps Emitter = { |
| 2067 &x86::AssemblerX86::movups, &x86::AssemblerX86::movups, | 2185 &x86::AssemblerX86::movups, &x86::AssemblerX86::movups, |
| 2068 &x86::AssemblerX86::movups | 2186 &x86::AssemblerX86::movups |
| 2069 }; | 2187 }; |
| 2070 emitIASMovlikeXMM(Func, Dest, Src, Emitter); | 2188 emitIASMovlikeXMM(Func, Dest, Src, Emitter); |
| 2071 } | 2189 } |
| 2072 | 2190 |
| 2073 template <> void InstX8632Movq::emit(const Cfg *Func) const { | 2191 template <> void InstX8632Movq::emit(const Cfg *Func) const { |
| 2192 if (!ALLOW_DUMP) |
| 2193 return; |
| 2074 Ostream &Str = Func->getContext()->getStrEmit(); | 2194 Ostream &Str = Func->getContext()->getStrEmit(); |
| 2075 assert(getSrcSize() == 1); | 2195 assert(getSrcSize() == 1); |
| 2076 assert(getDest()->getType() == IceType_i64 || | 2196 assert(getDest()->getType() == IceType_i64 || |
| 2077 getDest()->getType() == IceType_f64); | 2197 getDest()->getType() == IceType_f64); |
| 2078 Str << "\tmovq\t"; | 2198 Str << "\tmovq\t"; |
| 2079 getSrc(0)->emit(Func); | 2199 getSrc(0)->emit(Func); |
| 2080 Str << ", "; | 2200 Str << ", "; |
| 2081 getDest()->emit(Func); | 2201 getDest()->emit(Func); |
| 2082 } | 2202 } |
| 2083 | 2203 |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2123 assert(getSrcSize() == 1); | 2243 assert(getSrcSize() == 1); |
| 2124 const Variable *Dest = getDest(); | 2244 const Variable *Dest = getDest(); |
| 2125 const Operand *Src = getSrc(0); | 2245 const Operand *Src = getSrc(0); |
| 2126 Type SrcTy = Src->getType(); | 2246 Type SrcTy = Src->getType(); |
| 2127 assert(typeWidthInBytes(Dest->getType()) > 1); | 2247 assert(typeWidthInBytes(Dest->getType()) > 1); |
| 2128 assert(typeWidthInBytes(Dest->getType()) > typeWidthInBytes(SrcTy)); | 2248 assert(typeWidthInBytes(Dest->getType()) > typeWidthInBytes(SrcTy)); |
| 2129 emitIASRegOpTyGPR<false, true>(Func, SrcTy, Dest, Src, Emitter); | 2249 emitIASRegOpTyGPR<false, true>(Func, SrcTy, Dest, Src, Emitter); |
| 2130 } | 2250 } |
| 2131 | 2251 |
| 2132 void InstX8632Nop::emit(const Cfg *Func) const { | 2252 void InstX8632Nop::emit(const Cfg *Func) const { |
| 2253 if (!ALLOW_DUMP) |
| 2254 return; |
| 2133 Ostream &Str = Func->getContext()->getStrEmit(); | 2255 Ostream &Str = Func->getContext()->getStrEmit(); |
| 2134 // TODO: Emit the right code for each variant. | 2256 // TODO: Emit the right code for each variant. |
| 2135 Str << "\tnop\t# variant = " << Variant; | 2257 Str << "\tnop\t# variant = " << Variant; |
| 2136 } | 2258 } |
| 2137 | 2259 |
| 2138 void InstX8632Nop::emitIAS(const Cfg *Func) const { | 2260 void InstX8632Nop::emitIAS(const Cfg *Func) const { |
| 2139 x86::AssemblerX86 *Asm = Func->getAssembler<x86::AssemblerX86>(); | 2261 x86::AssemblerX86 *Asm = Func->getAssembler<x86::AssemblerX86>(); |
| 2140 // TODO: Emit the right code for the variant. | 2262 // TODO: Emit the right code for the variant. |
| 2141 Asm->nop(); | 2263 Asm->nop(); |
| 2142 } | 2264 } |
| 2143 | 2265 |
| 2144 void InstX8632Nop::dump(const Cfg *Func) const { | 2266 void InstX8632Nop::dump(const Cfg *Func) const { |
| 2267 if (!ALLOW_DUMP) |
| 2268 return; |
| 2145 Ostream &Str = Func->getContext()->getStrDump(); | 2269 Ostream &Str = Func->getContext()->getStrDump(); |
| 2146 Str << "nop (variant = " << Variant << ")"; | 2270 Str << "nop (variant = " << Variant << ")"; |
| 2147 } | 2271 } |
| 2148 | 2272 |
| 2149 void InstX8632Fld::emit(const Cfg *Func) const { | 2273 void InstX8632Fld::emit(const Cfg *Func) const { |
| 2274 if (!ALLOW_DUMP) |
| 2275 return; |
| 2150 Ostream &Str = Func->getContext()->getStrEmit(); | 2276 Ostream &Str = Func->getContext()->getStrEmit(); |
| 2151 assert(getSrcSize() == 1); | 2277 assert(getSrcSize() == 1); |
| 2152 Type Ty = getSrc(0)->getType(); | 2278 Type Ty = getSrc(0)->getType(); |
| 2153 SizeT Width = typeWidthInBytes(Ty); | 2279 SizeT Width = typeWidthInBytes(Ty); |
| 2154 const auto Var = llvm::dyn_cast<Variable>(getSrc(0)); | 2280 const auto Var = llvm::dyn_cast<Variable>(getSrc(0)); |
| 2155 if (Var && Var->hasReg()) { | 2281 if (Var && Var->hasReg()) { |
| 2156 // This is a physical xmm register, so we need to spill it to a | 2282 // This is a physical xmm register, so we need to spill it to a |
| 2157 // temporary stack slot. | 2283 // temporary stack slot. |
| 2158 Str << "\tsubl\t$" << Width << ", %esp" | 2284 Str << "\tsubl\t$" << Width << ", %esp" |
| 2159 << "\n"; | 2285 << "\n"; |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2193 assert(Mem->getSegmentRegister() == OperandX8632Mem::DefaultSegment); | 2319 assert(Mem->getSegmentRegister() == OperandX8632Mem::DefaultSegment); |
| 2194 Asm->fld(Ty, Mem->toAsmAddress(Asm)); | 2320 Asm->fld(Ty, Mem->toAsmAddress(Asm)); |
| 2195 } else if (const auto Imm = llvm::dyn_cast<Constant>(Src)) { | 2321 } else if (const auto Imm = llvm::dyn_cast<Constant>(Src)) { |
| 2196 Asm->fld(Ty, x86::Address::ofConstPool(Func->getContext(), Asm, Imm)); | 2322 Asm->fld(Ty, x86::Address::ofConstPool(Func->getContext(), Asm, Imm)); |
| 2197 } else { | 2323 } else { |
| 2198 llvm_unreachable("Unexpected operand type"); | 2324 llvm_unreachable("Unexpected operand type"); |
| 2199 } | 2325 } |
| 2200 } | 2326 } |
| 2201 | 2327 |
| 2202 void InstX8632Fld::dump(const Cfg *Func) const { | 2328 void InstX8632Fld::dump(const Cfg *Func) const { |
| 2329 if (!ALLOW_DUMP) |
| 2330 return; |
| 2203 Ostream &Str = Func->getContext()->getStrDump(); | 2331 Ostream &Str = Func->getContext()->getStrDump(); |
| 2204 Str << "fld." << getSrc(0)->getType() << " "; | 2332 Str << "fld." << getSrc(0)->getType() << " "; |
| 2205 dumpSources(Func); | 2333 dumpSources(Func); |
| 2206 } | 2334 } |
| 2207 | 2335 |
| 2208 void InstX8632Fstp::emit(const Cfg *Func) const { | 2336 void InstX8632Fstp::emit(const Cfg *Func) const { |
| 2337 if (!ALLOW_DUMP) |
| 2338 return; |
| 2209 Ostream &Str = Func->getContext()->getStrEmit(); | 2339 Ostream &Str = Func->getContext()->getStrEmit(); |
| 2210 assert(getSrcSize() == 0); | 2340 assert(getSrcSize() == 0); |
| 2211 // TODO(jvoung,stichnot): Utilize this by setting Dest to nullptr to | 2341 // TODO(jvoung,stichnot): Utilize this by setting Dest to nullptr to |
| 2212 // "partially" delete the fstp if the Dest is unused. | 2342 // "partially" delete the fstp if the Dest is unused. |
| 2213 // Even if Dest is unused, the fstp should be kept for the SideEffects | 2343 // Even if Dest is unused, the fstp should be kept for the SideEffects |
| 2214 // of popping the stack. | 2344 // of popping the stack. |
| 2215 if (!getDest()) { | 2345 if (!getDest()) { |
| 2216 Str << "\tfstp\tst(0)"; | 2346 Str << "\tfstp\tst(0)"; |
| 2217 return; | 2347 return; |
| 2218 } | 2348 } |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2262 x86::Immediate Width(typeWidthInBytes(Ty)); | 2392 x86::Immediate Width(typeWidthInBytes(Ty)); |
| 2263 Asm->sub(IceType_i32, RegX8632::Encoded_Reg_esp, Width); | 2393 Asm->sub(IceType_i32, RegX8632::Encoded_Reg_esp, Width); |
| 2264 x86::Address StackSlot = x86::Address(RegX8632::Encoded_Reg_esp, 0); | 2394 x86::Address StackSlot = x86::Address(RegX8632::Encoded_Reg_esp, 0); |
| 2265 Asm->fstp(Ty, StackSlot); | 2395 Asm->fstp(Ty, StackSlot); |
| 2266 Asm->movss(Ty, RegX8632::getEncodedXmm(Dest->getRegNum()), StackSlot); | 2396 Asm->movss(Ty, RegX8632::getEncodedXmm(Dest->getRegNum()), StackSlot); |
| 2267 Asm->add(IceType_i32, RegX8632::Encoded_Reg_esp, Width); | 2397 Asm->add(IceType_i32, RegX8632::Encoded_Reg_esp, Width); |
| 2268 } | 2398 } |
| 2269 } | 2399 } |
| 2270 | 2400 |
| 2271 void InstX8632Fstp::dump(const Cfg *Func) const { | 2401 void InstX8632Fstp::dump(const Cfg *Func) const { |
| 2402 if (!ALLOW_DUMP) |
| 2403 return; |
| 2272 Ostream &Str = Func->getContext()->getStrDump(); | 2404 Ostream &Str = Func->getContext()->getStrDump(); |
| 2273 dumpDest(Func); | 2405 dumpDest(Func); |
| 2274 Str << " = fstp." << getDest()->getType() << ", st(0)"; | 2406 Str << " = fstp." << getDest()->getType() << ", st(0)"; |
| 2275 Str << "\n"; | 2407 Str << "\n"; |
| 2276 } | 2408 } |
| 2277 | 2409 |
| 2278 template <> void InstX8632Pcmpeq::emit(const Cfg *Func) const { | 2410 template <> void InstX8632Pcmpeq::emit(const Cfg *Func) const { |
| 2411 if (!ALLOW_DUMP) |
| 2412 return; |
| 2279 char buf[30]; | 2413 char buf[30]; |
| 2280 snprintf(buf, llvm::array_lengthof(buf), "pcmpeq%s", | 2414 snprintf(buf, llvm::array_lengthof(buf), "pcmpeq%s", |
| 2281 TypeX8632Attributes[getDest()->getType()].PackString); | 2415 TypeX8632Attributes[getDest()->getType()].PackString); |
| 2282 emitTwoAddress(buf, this, Func); | 2416 emitTwoAddress(buf, this, Func); |
| 2283 } | 2417 } |
| 2284 | 2418 |
| 2285 template <> void InstX8632Pcmpgt::emit(const Cfg *Func) const { | 2419 template <> void InstX8632Pcmpgt::emit(const Cfg *Func) const { |
| 2420 if (!ALLOW_DUMP) |
| 2421 return; |
| 2286 char buf[30]; | 2422 char buf[30]; |
| 2287 snprintf(buf, llvm::array_lengthof(buf), "pcmpgt%s", | 2423 snprintf(buf, llvm::array_lengthof(buf), "pcmpgt%s", |
| 2288 TypeX8632Attributes[getDest()->getType()].PackString); | 2424 TypeX8632Attributes[getDest()->getType()].PackString); |
| 2289 emitTwoAddress(buf, this, Func); | 2425 emitTwoAddress(buf, this, Func); |
| 2290 } | 2426 } |
| 2291 | 2427 |
| 2292 template <> void InstX8632Pextr::emit(const Cfg *Func) const { | 2428 template <> void InstX8632Pextr::emit(const Cfg *Func) const { |
| 2429 if (!ALLOW_DUMP) |
| 2430 return; |
| 2293 Ostream &Str = Func->getContext()->getStrEmit(); | 2431 Ostream &Str = Func->getContext()->getStrEmit(); |
| 2294 assert(getSrcSize() == 2); | 2432 assert(getSrcSize() == 2); |
| 2295 // pextrb and pextrd are SSE4.1 instructions. | 2433 // pextrb and pextrd are SSE4.1 instructions. |
| 2296 assert(getSrc(0)->getType() == IceType_v8i16 || | 2434 assert(getSrc(0)->getType() == IceType_v8i16 || |
| 2297 getSrc(0)->getType() == IceType_v8i1 || | 2435 getSrc(0)->getType() == IceType_v8i1 || |
| 2298 static_cast<TargetX8632 *>(Func->getTarget())->getInstructionSet() | 2436 static_cast<TargetX8632 *>(Func->getTarget())->getInstructionSet() |
| 2299 >= TargetX8632::SSE4_1); | 2437 >= TargetX8632::SSE4_1); |
| 2300 Str << "\t" << Opcode | 2438 Str << "\t" << Opcode |
| 2301 << TypeX8632Attributes[getSrc(0)->getType()].PackString << "\t"; | 2439 << TypeX8632Attributes[getSrc(0)->getType()].PackString << "\t"; |
| 2302 getSrc(1)->emit(Func); | 2440 getSrc(1)->emit(Func); |
| (...skipping 24 matching lines...) Expand all Loading... |
| 2327 assert(llvm::cast<Variable>(getSrc(0))->hasReg()); | 2465 assert(llvm::cast<Variable>(getSrc(0))->hasReg()); |
| 2328 static const x86::AssemblerX86::ThreeOpImmEmitter< | 2466 static const x86::AssemblerX86::ThreeOpImmEmitter< |
| 2329 RegX8632::GPRRegister, RegX8632::XmmRegister> Emitter = { | 2467 RegX8632::GPRRegister, RegX8632::XmmRegister> Emitter = { |
| 2330 &x86::AssemblerX86::pextr, nullptr}; | 2468 &x86::AssemblerX86::pextr, nullptr}; |
| 2331 emitIASThreeOpImmOps<RegX8632::GPRRegister, RegX8632::XmmRegister, | 2469 emitIASThreeOpImmOps<RegX8632::GPRRegister, RegX8632::XmmRegister, |
| 2332 RegX8632::getEncodedGPR, RegX8632::getEncodedXmm>( | 2470 RegX8632::getEncodedGPR, RegX8632::getEncodedXmm>( |
| 2333 Func, DispatchTy, Dest, getSrc(0), getSrc(1), Emitter); | 2471 Func, DispatchTy, Dest, getSrc(0), getSrc(1), Emitter); |
| 2334 } | 2472 } |
| 2335 | 2473 |
| 2336 template <> void InstX8632Pinsr::emit(const Cfg *Func) const { | 2474 template <> void InstX8632Pinsr::emit(const Cfg *Func) const { |
| 2475 if (!ALLOW_DUMP) |
| 2476 return; |
| 2337 Ostream &Str = Func->getContext()->getStrEmit(); | 2477 Ostream &Str = Func->getContext()->getStrEmit(); |
| 2338 assert(getSrcSize() == 3); | 2478 assert(getSrcSize() == 3); |
| 2339 // pinsrb and pinsrd are SSE4.1 instructions. | 2479 // pinsrb and pinsrd are SSE4.1 instructions. |
| 2340 assert(getDest()->getType() == IceType_v8i16 || | 2480 assert(getDest()->getType() == IceType_v8i16 || |
| 2341 getDest()->getType() == IceType_v8i1 || | 2481 getDest()->getType() == IceType_v8i1 || |
| 2342 static_cast<TargetX8632 *>(Func->getTarget())->getInstructionSet() | 2482 static_cast<TargetX8632 *>(Func->getTarget())->getInstructionSet() |
| 2343 >= TargetX8632::SSE4_1); | 2483 >= TargetX8632::SSE4_1); |
| 2344 Str << "\t" << Opcode | 2484 Str << "\t" << Opcode |
| 2345 << TypeX8632Attributes[getDest()->getType()].PackString << "\t"; | 2485 << TypeX8632Attributes[getDest()->getType()].PackString << "\t"; |
| 2346 getSrc(2)->emit(Func); | 2486 getSrc(2)->emit(Func); |
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2400 Type Ty = Dest->getType(); | 2540 Type Ty = Dest->getType(); |
| 2401 static const x86::AssemblerX86::ThreeOpImmEmitter< | 2541 static const x86::AssemblerX86::ThreeOpImmEmitter< |
| 2402 RegX8632::XmmRegister, RegX8632::XmmRegister> Emitter = { | 2542 RegX8632::XmmRegister, RegX8632::XmmRegister> Emitter = { |
| 2403 &x86::AssemblerX86::shufps, &x86::AssemblerX86::shufps}; | 2543 &x86::AssemblerX86::shufps, &x86::AssemblerX86::shufps}; |
| 2404 emitIASThreeOpImmOps<RegX8632::XmmRegister, RegX8632::XmmRegister, | 2544 emitIASThreeOpImmOps<RegX8632::XmmRegister, RegX8632::XmmRegister, |
| 2405 RegX8632::getEncodedXmm, RegX8632::getEncodedXmm>( | 2545 RegX8632::getEncodedXmm, RegX8632::getEncodedXmm>( |
| 2406 Func, Ty, Dest, getSrc(1), getSrc(2), Emitter); | 2546 Func, Ty, Dest, getSrc(1), getSrc(2), Emitter); |
| 2407 } | 2547 } |
| 2408 | 2548 |
| 2409 void InstX8632Pop::emit(const Cfg *Func) const { | 2549 void InstX8632Pop::emit(const Cfg *Func) const { |
| 2550 if (!ALLOW_DUMP) |
| 2551 return; |
| 2410 Ostream &Str = Func->getContext()->getStrEmit(); | 2552 Ostream &Str = Func->getContext()->getStrEmit(); |
| 2411 assert(getSrcSize() == 0); | 2553 assert(getSrcSize() == 0); |
| 2412 Str << "\tpop\t"; | 2554 Str << "\tpop\t"; |
| 2413 getDest()->emit(Func); | 2555 getDest()->emit(Func); |
| 2414 } | 2556 } |
| 2415 | 2557 |
| 2416 void InstX8632Pop::emitIAS(const Cfg *Func) const { | 2558 void InstX8632Pop::emitIAS(const Cfg *Func) const { |
| 2417 assert(getSrcSize() == 0); | 2559 assert(getSrcSize() == 0); |
| 2418 x86::AssemblerX86 *Asm = Func->getAssembler<x86::AssemblerX86>(); | 2560 x86::AssemblerX86 *Asm = Func->getAssembler<x86::AssemblerX86>(); |
| 2419 if (getDest()->hasReg()) { | 2561 if (getDest()->hasReg()) { |
| 2420 Asm->popl(RegX8632::getEncodedGPR(getDest()->getRegNum())); | 2562 Asm->popl(RegX8632::getEncodedGPR(getDest()->getRegNum())); |
| 2421 } else { | 2563 } else { |
| 2422 Asm->popl(static_cast<TargetX8632 *>(Func->getTarget()) | 2564 Asm->popl(static_cast<TargetX8632 *>(Func->getTarget()) |
| 2423 ->stackVarToAsmOperand(getDest())); | 2565 ->stackVarToAsmOperand(getDest())); |
| 2424 } | 2566 } |
| 2425 } | 2567 } |
| 2426 | 2568 |
| 2427 void InstX8632Pop::dump(const Cfg *Func) const { | 2569 void InstX8632Pop::dump(const Cfg *Func) const { |
| 2570 if (!ALLOW_DUMP) |
| 2571 return; |
| 2428 Ostream &Str = Func->getContext()->getStrDump(); | 2572 Ostream &Str = Func->getContext()->getStrDump(); |
| 2429 dumpDest(Func); | 2573 dumpDest(Func); |
| 2430 Str << " = pop." << getDest()->getType() << " "; | 2574 Str << " = pop." << getDest()->getType() << " "; |
| 2431 } | 2575 } |
| 2432 | 2576 |
| 2433 void InstX8632AdjustStack::emit(const Cfg *Func) const { | 2577 void InstX8632AdjustStack::emit(const Cfg *Func) const { |
| 2578 if (!ALLOW_DUMP) |
| 2579 return; |
| 2434 Ostream &Str = Func->getContext()->getStrEmit(); | 2580 Ostream &Str = Func->getContext()->getStrEmit(); |
| 2435 Str << "\tsubl\t$" << Amount << ", %esp"; | 2581 Str << "\tsubl\t$" << Amount << ", %esp"; |
| 2436 Func->getTarget()->updateStackAdjustment(Amount); | 2582 Func->getTarget()->updateStackAdjustment(Amount); |
| 2437 } | 2583 } |
| 2438 | 2584 |
| 2439 void InstX8632AdjustStack::emitIAS(const Cfg *Func) const { | 2585 void InstX8632AdjustStack::emitIAS(const Cfg *Func) const { |
| 2440 x86::AssemblerX86 *Asm = Func->getAssembler<x86::AssemblerX86>(); | 2586 x86::AssemblerX86 *Asm = Func->getAssembler<x86::AssemblerX86>(); |
| 2441 Asm->sub(IceType_i32, RegX8632::Encoded_Reg_esp, x86::Immediate(Amount)); | 2587 Asm->sub(IceType_i32, RegX8632::Encoded_Reg_esp, x86::Immediate(Amount)); |
| 2442 Func->getTarget()->updateStackAdjustment(Amount); | 2588 Func->getTarget()->updateStackAdjustment(Amount); |
| 2443 } | 2589 } |
| 2444 | 2590 |
| 2445 void InstX8632AdjustStack::dump(const Cfg *Func) const { | 2591 void InstX8632AdjustStack::dump(const Cfg *Func) const { |
| 2592 if (!ALLOW_DUMP) |
| 2593 return; |
| 2446 Ostream &Str = Func->getContext()->getStrDump(); | 2594 Ostream &Str = Func->getContext()->getStrDump(); |
| 2447 Str << "esp = sub.i32 esp, " << Amount; | 2595 Str << "esp = sub.i32 esp, " << Amount; |
| 2448 } | 2596 } |
| 2449 | 2597 |
| 2450 void InstX8632Push::emit(const Cfg *Func) const { | 2598 void InstX8632Push::emit(const Cfg *Func) const { |
| 2599 if (!ALLOW_DUMP) |
| 2600 return; |
| 2451 Ostream &Str = Func->getContext()->getStrEmit(); | 2601 Ostream &Str = Func->getContext()->getStrEmit(); |
| 2452 assert(getSrcSize() == 1); | 2602 assert(getSrcSize() == 1); |
| 2453 // Push is currently only used for saving GPRs. | 2603 // Push is currently only used for saving GPRs. |
| 2454 const auto Var = llvm::cast<Variable>(getSrc(0)); | 2604 const auto Var = llvm::cast<Variable>(getSrc(0)); |
| 2455 assert(Var->hasReg()); | 2605 assert(Var->hasReg()); |
| 2456 Str << "\tpush\t"; | 2606 Str << "\tpush\t"; |
| 2457 Var->emit(Func); | 2607 Var->emit(Func); |
| 2458 } | 2608 } |
| 2459 | 2609 |
| 2460 void InstX8632Push::emitIAS(const Cfg *Func) const { | 2610 void InstX8632Push::emitIAS(const Cfg *Func) const { |
| 2461 assert(getSrcSize() == 1); | 2611 assert(getSrcSize() == 1); |
| 2462 // Push is currently only used for saving GPRs. | 2612 // Push is currently only used for saving GPRs. |
| 2463 const auto Var = llvm::cast<Variable>(getSrc(0)); | 2613 const auto Var = llvm::cast<Variable>(getSrc(0)); |
| 2464 assert(Var->hasReg()); | 2614 assert(Var->hasReg()); |
| 2465 x86::AssemblerX86 *Asm = Func->getAssembler<x86::AssemblerX86>(); | 2615 x86::AssemblerX86 *Asm = Func->getAssembler<x86::AssemblerX86>(); |
| 2466 Asm->pushl(RegX8632::getEncodedGPR(Var->getRegNum())); | 2616 Asm->pushl(RegX8632::getEncodedGPR(Var->getRegNum())); |
| 2467 } | 2617 } |
| 2468 | 2618 |
| 2469 void InstX8632Push::dump(const Cfg *Func) const { | 2619 void InstX8632Push::dump(const Cfg *Func) const { |
| 2620 if (!ALLOW_DUMP) |
| 2621 return; |
| 2470 Ostream &Str = Func->getContext()->getStrDump(); | 2622 Ostream &Str = Func->getContext()->getStrDump(); |
| 2471 Str << "push." << getSrc(0)->getType() << " "; | 2623 Str << "push." << getSrc(0)->getType() << " "; |
| 2472 dumpSources(Func); | 2624 dumpSources(Func); |
| 2473 } | 2625 } |
| 2474 | 2626 |
| 2475 template <> void InstX8632Psll::emit(const Cfg *Func) const { | 2627 template <> void InstX8632Psll::emit(const Cfg *Func) const { |
| 2628 if (!ALLOW_DUMP) |
| 2629 return; |
| 2476 assert(getDest()->getType() == IceType_v8i16 || | 2630 assert(getDest()->getType() == IceType_v8i16 || |
| 2477 getDest()->getType() == IceType_v8i1 || | 2631 getDest()->getType() == IceType_v8i1 || |
| 2478 getDest()->getType() == IceType_v4i32 || | 2632 getDest()->getType() == IceType_v4i32 || |
| 2479 getDest()->getType() == IceType_v4i1); | 2633 getDest()->getType() == IceType_v4i1); |
| 2480 char buf[30]; | 2634 char buf[30]; |
| 2481 snprintf(buf, llvm::array_lengthof(buf), "psll%s", | 2635 snprintf(buf, llvm::array_lengthof(buf), "psll%s", |
| 2482 TypeX8632Attributes[getDest()->getType()].PackString); | 2636 TypeX8632Attributes[getDest()->getType()].PackString); |
| 2483 emitTwoAddress(buf, this, Func); | 2637 emitTwoAddress(buf, this, Func); |
| 2484 } | 2638 } |
| 2485 | 2639 |
| 2486 template <> void InstX8632Psra::emit(const Cfg *Func) const { | 2640 template <> void InstX8632Psra::emit(const Cfg *Func) const { |
| 2641 if (!ALLOW_DUMP) |
| 2642 return; |
| 2487 assert(getDest()->getType() == IceType_v8i16 || | 2643 assert(getDest()->getType() == IceType_v8i16 || |
| 2488 getDest()->getType() == IceType_v8i1 || | 2644 getDest()->getType() == IceType_v8i1 || |
| 2489 getDest()->getType() == IceType_v4i32 || | 2645 getDest()->getType() == IceType_v4i32 || |
| 2490 getDest()->getType() == IceType_v4i1); | 2646 getDest()->getType() == IceType_v4i1); |
| 2491 char buf[30]; | 2647 char buf[30]; |
| 2492 snprintf(buf, llvm::array_lengthof(buf), "psra%s", | 2648 snprintf(buf, llvm::array_lengthof(buf), "psra%s", |
| 2493 TypeX8632Attributes[getDest()->getType()].PackString); | 2649 TypeX8632Attributes[getDest()->getType()].PackString); |
| 2494 emitTwoAddress(buf, this, Func); | 2650 emitTwoAddress(buf, this, Func); |
| 2495 } | 2651 } |
| 2496 | 2652 |
| 2497 void InstX8632Ret::emit(const Cfg *Func) const { | 2653 void InstX8632Ret::emit(const Cfg *Func) const { |
| 2654 if (!ALLOW_DUMP) |
| 2655 return; |
| 2498 Ostream &Str = Func->getContext()->getStrEmit(); | 2656 Ostream &Str = Func->getContext()->getStrEmit(); |
| 2499 Str << "\tret"; | 2657 Str << "\tret"; |
| 2500 } | 2658 } |
| 2501 | 2659 |
| 2502 void InstX8632Ret::emitIAS(const Cfg *Func) const { | 2660 void InstX8632Ret::emitIAS(const Cfg *Func) const { |
| 2503 x86::AssemblerX86 *Asm = Func->getAssembler<x86::AssemblerX86>(); | 2661 x86::AssemblerX86 *Asm = Func->getAssembler<x86::AssemblerX86>(); |
| 2504 Asm->ret(); | 2662 Asm->ret(); |
| 2505 } | 2663 } |
| 2506 | 2664 |
| 2507 void InstX8632Ret::dump(const Cfg *Func) const { | 2665 void InstX8632Ret::dump(const Cfg *Func) const { |
| 2666 if (!ALLOW_DUMP) |
| 2667 return; |
| 2508 Ostream &Str = Func->getContext()->getStrDump(); | 2668 Ostream &Str = Func->getContext()->getStrDump(); |
| 2509 Type Ty = (getSrcSize() == 0 ? IceType_void : getSrc(0)->getType()); | 2669 Type Ty = (getSrcSize() == 0 ? IceType_void : getSrc(0)->getType()); |
| 2510 Str << "ret." << Ty << " "; | 2670 Str << "ret." << Ty << " "; |
| 2511 dumpSources(Func); | 2671 dumpSources(Func); |
| 2512 } | 2672 } |
| 2513 | 2673 |
| 2514 void InstX8632Xadd::emit(const Cfg *Func) const { | 2674 void InstX8632Xadd::emit(const Cfg *Func) const { |
| 2675 if (!ALLOW_DUMP) |
| 2676 return; |
| 2515 Ostream &Str = Func->getContext()->getStrEmit(); | 2677 Ostream &Str = Func->getContext()->getStrEmit(); |
| 2516 if (Locked) { | 2678 if (Locked) { |
| 2517 Str << "\tlock"; | 2679 Str << "\tlock"; |
| 2518 } | 2680 } |
| 2519 Str << "\txadd" << getWidthString(getSrc(0)->getType()) << "\t"; | 2681 Str << "\txadd" << getWidthString(getSrc(0)->getType()) << "\t"; |
| 2520 getSrc(1)->emit(Func); | 2682 getSrc(1)->emit(Func); |
| 2521 Str << ", "; | 2683 Str << ", "; |
| 2522 getSrc(0)->emit(Func); | 2684 getSrc(0)->emit(Func); |
| 2523 } | 2685 } |
| 2524 | 2686 |
| 2525 void InstX8632Xadd::emitIAS(const Cfg *Func) const { | 2687 void InstX8632Xadd::emitIAS(const Cfg *Func) const { |
| 2526 assert(getSrcSize() == 2); | 2688 assert(getSrcSize() == 2); |
| 2527 x86::AssemblerX86 *Asm = Func->getAssembler<x86::AssemblerX86>(); | 2689 x86::AssemblerX86 *Asm = Func->getAssembler<x86::AssemblerX86>(); |
| 2528 Type Ty = getSrc(0)->getType(); | 2690 Type Ty = getSrc(0)->getType(); |
| 2529 const auto Mem = llvm::cast<OperandX8632Mem>(getSrc(0)); | 2691 const auto Mem = llvm::cast<OperandX8632Mem>(getSrc(0)); |
| 2530 assert(Mem->getSegmentRegister() == OperandX8632Mem::DefaultSegment); | 2692 assert(Mem->getSegmentRegister() == OperandX8632Mem::DefaultSegment); |
| 2531 const x86::Address Addr = Mem->toAsmAddress(Asm); | 2693 const x86::Address Addr = Mem->toAsmAddress(Asm); |
| 2532 const auto VarReg = llvm::cast<Variable>(getSrc(1)); | 2694 const auto VarReg = llvm::cast<Variable>(getSrc(1)); |
| 2533 assert(VarReg->hasReg()); | 2695 assert(VarReg->hasReg()); |
| 2534 const RegX8632::GPRRegister Reg = | 2696 const RegX8632::GPRRegister Reg = |
| 2535 RegX8632::getEncodedGPR(VarReg->getRegNum()); | 2697 RegX8632::getEncodedGPR(VarReg->getRegNum()); |
| 2536 if (Locked) { | 2698 if (Locked) { |
| 2537 Asm->lock(); | 2699 Asm->lock(); |
| 2538 } | 2700 } |
| 2539 Asm->xadd(Ty, Addr, Reg); | 2701 Asm->xadd(Ty, Addr, Reg); |
| 2540 } | 2702 } |
| 2541 | 2703 |
| 2542 void InstX8632Xadd::dump(const Cfg *Func) const { | 2704 void InstX8632Xadd::dump(const Cfg *Func) const { |
| 2705 if (!ALLOW_DUMP) |
| 2706 return; |
| 2543 Ostream &Str = Func->getContext()->getStrDump(); | 2707 Ostream &Str = Func->getContext()->getStrDump(); |
| 2544 if (Locked) { | 2708 if (Locked) { |
| 2545 Str << "lock "; | 2709 Str << "lock "; |
| 2546 } | 2710 } |
| 2547 Type Ty = getSrc(0)->getType(); | 2711 Type Ty = getSrc(0)->getType(); |
| 2548 Str << "xadd." << Ty << " "; | 2712 Str << "xadd." << Ty << " "; |
| 2549 dumpSources(Func); | 2713 dumpSources(Func); |
| 2550 } | 2714 } |
| 2551 | 2715 |
| 2552 void InstX8632Xchg::emit(const Cfg *Func) const { | 2716 void InstX8632Xchg::emit(const Cfg *Func) const { |
| 2717 if (!ALLOW_DUMP) |
| 2718 return; |
| 2553 Ostream &Str = Func->getContext()->getStrEmit(); | 2719 Ostream &Str = Func->getContext()->getStrEmit(); |
| 2554 Str << "\txchg" << getWidthString(getSrc(0)->getType()) << "\t"; | 2720 Str << "\txchg" << getWidthString(getSrc(0)->getType()) << "\t"; |
| 2555 getSrc(1)->emit(Func); | 2721 getSrc(1)->emit(Func); |
| 2556 Str << ", "; | 2722 Str << ", "; |
| 2557 getSrc(0)->emit(Func); | 2723 getSrc(0)->emit(Func); |
| 2558 } | 2724 } |
| 2559 | 2725 |
| 2560 void InstX8632Xchg::emitIAS(const Cfg *Func) const { | 2726 void InstX8632Xchg::emitIAS(const Cfg *Func) const { |
| 2561 assert(getSrcSize() == 2); | 2727 assert(getSrcSize() == 2); |
| 2562 x86::AssemblerX86 *Asm = Func->getAssembler<x86::AssemblerX86>(); | 2728 x86::AssemblerX86 *Asm = Func->getAssembler<x86::AssemblerX86>(); |
| 2563 Type Ty = getSrc(0)->getType(); | 2729 Type Ty = getSrc(0)->getType(); |
| 2564 const auto Mem = llvm::cast<OperandX8632Mem>(getSrc(0)); | 2730 const auto Mem = llvm::cast<OperandX8632Mem>(getSrc(0)); |
| 2565 assert(Mem->getSegmentRegister() == OperandX8632Mem::DefaultSegment); | 2731 assert(Mem->getSegmentRegister() == OperandX8632Mem::DefaultSegment); |
| 2566 const x86::Address Addr = Mem->toAsmAddress(Asm); | 2732 const x86::Address Addr = Mem->toAsmAddress(Asm); |
| 2567 const auto VarReg = llvm::cast<Variable>(getSrc(1)); | 2733 const auto VarReg = llvm::cast<Variable>(getSrc(1)); |
| 2568 assert(VarReg->hasReg()); | 2734 assert(VarReg->hasReg()); |
| 2569 const RegX8632::GPRRegister Reg = | 2735 const RegX8632::GPRRegister Reg = |
| 2570 RegX8632::getEncodedGPR(VarReg->getRegNum()); | 2736 RegX8632::getEncodedGPR(VarReg->getRegNum()); |
| 2571 Asm->xchg(Ty, Addr, Reg); | 2737 Asm->xchg(Ty, Addr, Reg); |
| 2572 } | 2738 } |
| 2573 | 2739 |
| 2574 void InstX8632Xchg::dump(const Cfg *Func) const { | 2740 void InstX8632Xchg::dump(const Cfg *Func) const { |
| 2741 if (!ALLOW_DUMP) |
| 2742 return; |
| 2575 Ostream &Str = Func->getContext()->getStrDump(); | 2743 Ostream &Str = Func->getContext()->getStrDump(); |
| 2576 Type Ty = getSrc(0)->getType(); | 2744 Type Ty = getSrc(0)->getType(); |
| 2577 Str << "xchg." << Ty << " "; | 2745 Str << "xchg." << Ty << " "; |
| 2578 dumpSources(Func); | 2746 dumpSources(Func); |
| 2579 } | 2747 } |
| 2580 | 2748 |
| 2581 void OperandX8632Mem::emit(const Cfg *Func) const { | 2749 void OperandX8632Mem::emit(const Cfg *Func) const { |
| 2750 if (!ALLOW_DUMP) |
| 2751 return; |
| 2582 Ostream &Str = Func->getContext()->getStrEmit(); | 2752 Ostream &Str = Func->getContext()->getStrEmit(); |
| 2583 if (SegmentReg != DefaultSegment) { | 2753 if (SegmentReg != DefaultSegment) { |
| 2584 assert(SegmentReg >= 0 && SegmentReg < SegReg_NUM); | 2754 assert(SegmentReg >= 0 && SegmentReg < SegReg_NUM); |
| 2585 Str << InstX8632SegmentRegNames[SegmentReg] << ":"; | 2755 Str << InstX8632SegmentRegNames[SegmentReg] << ":"; |
| 2586 } | 2756 } |
| 2587 // Emit as Offset(Base,Index,1<<Shift). | 2757 // Emit as Offset(Base,Index,1<<Shift). |
| 2588 // Offset is emitted without the leading '$'. | 2758 // Offset is emitted without the leading '$'. |
| 2589 // Omit the (Base,Index,1<<Shift) part if Base==nullptr. | 2759 // Omit the (Base,Index,1<<Shift) part if Base==nullptr. |
| 2590 if (!Offset) { | 2760 if (!Offset) { |
| 2591 // No offset, emit nothing. | 2761 // No offset, emit nothing. |
| (...skipping 14 matching lines...) Expand all Loading... |
| 2606 Str << ","; | 2776 Str << ","; |
| 2607 Index->emit(Func); | 2777 Index->emit(Func); |
| 2608 if (Shift) | 2778 if (Shift) |
| 2609 Str << "," << (1u << Shift); | 2779 Str << "," << (1u << Shift); |
| 2610 } | 2780 } |
| 2611 Str << ")"; | 2781 Str << ")"; |
| 2612 } | 2782 } |
| 2613 } | 2783 } |
| 2614 | 2784 |
| 2615 void OperandX8632Mem::dump(const Cfg *Func, Ostream &Str) const { | 2785 void OperandX8632Mem::dump(const Cfg *Func, Ostream &Str) const { |
| 2786 if (!ALLOW_DUMP) |
| 2787 return; |
| 2616 if (SegmentReg != DefaultSegment) { | 2788 if (SegmentReg != DefaultSegment) { |
| 2617 assert(SegmentReg >= 0 && SegmentReg < SegReg_NUM); | 2789 assert(SegmentReg >= 0 && SegmentReg < SegReg_NUM); |
| 2618 Str << InstX8632SegmentRegNames[SegmentReg] << ":"; | 2790 Str << InstX8632SegmentRegNames[SegmentReg] << ":"; |
| 2619 } | 2791 } |
| 2620 bool Dumped = false; | 2792 bool Dumped = false; |
| 2621 Str << "["; | 2793 Str << "["; |
| 2622 if (Base) { | 2794 if (Base) { |
| 2623 if (Func) | 2795 if (Func) |
| 2624 Base->dump(Func); | 2796 Base->dump(Func); |
| 2625 else | 2797 else |
| (...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2705 x86::Address VariableSplit::toAsmAddress(const Cfg *Func) const { | 2877 x86::Address VariableSplit::toAsmAddress(const Cfg *Func) const { |
| 2706 assert(!Var->hasReg()); | 2878 assert(!Var->hasReg()); |
| 2707 const TargetLowering *Target = Func->getTarget(); | 2879 const TargetLowering *Target = Func->getTarget(); |
| 2708 int32_t Offset = | 2880 int32_t Offset = |
| 2709 Var->getStackOffset() + Target->getStackAdjustment() + getOffset(); | 2881 Var->getStackOffset() + Target->getStackAdjustment() + getOffset(); |
| 2710 return x86::Address(RegX8632::getEncodedGPR(Target->getFrameOrStackReg()), | 2882 return x86::Address(RegX8632::getEncodedGPR(Target->getFrameOrStackReg()), |
| 2711 Offset); | 2883 Offset); |
| 2712 } | 2884 } |
| 2713 | 2885 |
| 2714 void VariableSplit::emit(const Cfg *Func) const { | 2886 void VariableSplit::emit(const Cfg *Func) const { |
| 2887 if (!ALLOW_DUMP) |
| 2888 return; |
| 2715 Ostream &Str = Func->getContext()->getStrEmit(); | 2889 Ostream &Str = Func->getContext()->getStrEmit(); |
| 2716 assert(!Var->hasReg()); | 2890 assert(!Var->hasReg()); |
| 2717 // The following is copied/adapted from TargetX8632::emitVariable(). | 2891 // The following is copied/adapted from TargetX8632::emitVariable(). |
| 2718 const TargetLowering *Target = Func->getTarget(); | 2892 const TargetLowering *Target = Func->getTarget(); |
| 2719 const Type Ty = IceType_i32; | 2893 const Type Ty = IceType_i32; |
| 2720 int32_t Offset = | 2894 int32_t Offset = |
| 2721 Var->getStackOffset() + Target->getStackAdjustment() + getOffset(); | 2895 Var->getStackOffset() + Target->getStackAdjustment() + getOffset(); |
| 2722 if (Offset) | 2896 if (Offset) |
| 2723 Str << Offset; | 2897 Str << Offset; |
| 2724 Str << "(%" << Target->getRegName(Target->getFrameOrStackReg(), Ty) << ")"; | 2898 Str << "(%" << Target->getRegName(Target->getFrameOrStackReg(), Ty) << ")"; |
| 2725 } | 2899 } |
| 2726 | 2900 |
| 2727 void VariableSplit::dump(const Cfg *Func, Ostream &Str) const { | 2901 void VariableSplit::dump(const Cfg *Func, Ostream &Str) const { |
| 2902 if (!ALLOW_DUMP) |
| 2903 return; |
| 2728 switch (Part) { | 2904 switch (Part) { |
| 2729 case Low: | 2905 case Low: |
| 2730 Str << "low"; | 2906 Str << "low"; |
| 2731 break; | 2907 break; |
| 2732 case High: | 2908 case High: |
| 2733 Str << "high"; | 2909 Str << "high"; |
| 2734 break; | 2910 break; |
| 2735 default: | 2911 default: |
| 2736 Str << "???"; | 2912 Str << "???"; |
| 2737 break; | 2913 break; |
| 2738 } | 2914 } |
| 2739 Str << "("; | 2915 Str << "("; |
| 2740 if (Func) | 2916 if (Func) |
| 2741 Var->dump(Func); | 2917 Var->dump(Func); |
| 2742 else | 2918 else |
| 2743 Var->dump(Str); | 2919 Var->dump(Str); |
| 2744 Str << ")"; | 2920 Str << ")"; |
| 2745 } | 2921 } |
| 2746 | 2922 |
| 2747 } // end of namespace Ice | 2923 } // end of namespace Ice |
| OLD | NEW |