| 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, |
| 11 // primarily the constructors and the dump()/emit() methods. | 11 // primarily the constructors and the dump()/emit() methods. |
| 12 // | 12 // |
| 13 //===----------------------------------------------------------------------===// | 13 //===----------------------------------------------------------------------===// |
| 14 | 14 |
| 15 #include "IceCfg.h" | 15 #include "IceCfg.h" |
| 16 #include "IceCfgNode.h" | 16 #include "IceCfgNode.h" |
| 17 #include "IceConditionCodesX8632.h" |
| 17 #include "IceInst.h" | 18 #include "IceInst.h" |
| 18 #include "IceInstX8632.h" | 19 #include "IceInstX8632.h" |
| 20 #include "IceRegistersX8632.h" |
| 19 #include "IceTargetLoweringX8632.h" | 21 #include "IceTargetLoweringX8632.h" |
| 20 #include "IceOperand.h" | 22 #include "IceOperand.h" |
| 21 | 23 |
| 22 namespace Ice { | 24 namespace Ice { |
| 23 | 25 |
| 24 namespace { | 26 namespace { |
| 25 | 27 |
| 26 const struct InstX8632BrAttributes_ { | 28 const struct InstX8632BrAttributes_ { |
| 27 InstX8632::BrCond Opposite; | 29 CondX86::BrCond Opposite; |
| 28 const char *DisplayString; | 30 const char *DisplayString; |
| 29 const char *EmitString; | 31 const char *EmitString; |
| 30 } InstX8632BrAttributes[] = { | 32 } InstX8632BrAttributes[] = { |
| 31 #define X(tag, opp, dump, emit) \ | 33 #define X(tag, encode, opp, dump, emit) \ |
| 32 { InstX8632::opp, dump, emit } \ | 34 { CondX86::opp, dump, emit } \ |
| 33 , | 35 , |
| 34 ICEINSTX8632BR_TABLE | 36 ICEINSTX8632BR_TABLE |
| 35 #undef X | 37 #undef X |
| 36 }; | 38 }; |
| 37 | 39 |
| 38 const struct InstX8632CmppsAttributes_ { | 40 const struct InstX8632CmppsAttributes_ { |
| 39 const char *EmitString; | 41 const char *EmitString; |
| 40 } InstX8632CmppsAttributes[] = { | 42 } InstX8632CmppsAttributes[] = { |
| 41 #define X(tag, emit) \ | 43 #define X(tag, emit) \ |
| 42 { emit } \ | 44 { emit } \ |
| (...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 124 Number(Target->makeNextLabelNumber()) {} | 126 Number(Target->makeNextLabelNumber()) {} |
| 125 | 127 |
| 126 IceString InstX8632Label::getName(const Cfg *Func) const { | 128 IceString InstX8632Label::getName(const Cfg *Func) const { |
| 127 char buf[30]; | 129 char buf[30]; |
| 128 snprintf(buf, llvm::array_lengthof(buf), "%u", Number); | 130 snprintf(buf, llvm::array_lengthof(buf), "%u", Number); |
| 129 return ".L" + Func->getFunctionName() + "$local$__" + buf; | 131 return ".L" + Func->getFunctionName() + "$local$__" + buf; |
| 130 } | 132 } |
| 131 | 133 |
| 132 InstX8632Br::InstX8632Br(Cfg *Func, const CfgNode *TargetTrue, | 134 InstX8632Br::InstX8632Br(Cfg *Func, const CfgNode *TargetTrue, |
| 133 const CfgNode *TargetFalse, | 135 const CfgNode *TargetFalse, |
| 134 const InstX8632Label *Label, | 136 const InstX8632Label *Label, CondX86::BrCond Condition) |
| 135 InstX8632::BrCond Condition) | |
| 136 : InstX8632(Func, InstX8632::Br, 0, NULL), Condition(Condition), | 137 : InstX8632(Func, InstX8632::Br, 0, NULL), Condition(Condition), |
| 137 TargetTrue(TargetTrue), TargetFalse(TargetFalse), Label(Label) {} | 138 TargetTrue(TargetTrue), TargetFalse(TargetFalse), Label(Label) {} |
| 138 | 139 |
| 139 bool InstX8632Br::optimizeBranch(const CfgNode *NextNode) { | 140 bool InstX8632Br::optimizeBranch(const CfgNode *NextNode) { |
| 140 // If there is no next block, then there can be no fallthrough to | 141 // If there is no next block, then there can be no fallthrough to |
| 141 // optimize. | 142 // optimize. |
| 142 if (NextNode == NULL) | 143 if (NextNode == NULL) |
| 143 return false; | 144 return false; |
| 144 // Intra-block conditional branches can't be optimized. | 145 // Intra-block conditional branches can't be optimized. |
| 145 if (Label) | 146 if (Label) |
| 146 return false; | 147 return false; |
| 147 // If there is no fallthrough node, such as a non-default case label | 148 // If there is no fallthrough node, such as a non-default case label |
| 148 // for a switch instruction, then there is no opportunity to | 149 // for a switch instruction, then there is no opportunity to |
| 149 // optimize. | 150 // optimize. |
| 150 if (getTargetFalse() == NULL) | 151 if (getTargetFalse() == NULL) |
| 151 return false; | 152 return false; |
| 152 | 153 |
| 153 // Unconditional branch to the next node can be removed. | 154 // Unconditional branch to the next node can be removed. |
| 154 if (Condition == Br_None && getTargetFalse() == NextNode) { | 155 if (Condition == CondX86::Br_None && getTargetFalse() == NextNode) { |
| 155 assert(getTargetTrue() == NULL); | 156 assert(getTargetTrue() == NULL); |
| 156 setDeleted(); | 157 setDeleted(); |
| 157 return true; | 158 return true; |
| 158 } | 159 } |
| 159 // If the fallthrough is to the next node, set fallthrough to NULL | 160 // If the fallthrough is to the next node, set fallthrough to NULL |
| 160 // to indicate. | 161 // to indicate. |
| 161 if (getTargetFalse() == NextNode) { | 162 if (getTargetFalse() == NextNode) { |
| 162 TargetFalse = NULL; | 163 TargetFalse = NULL; |
| 163 return true; | 164 return true; |
| 164 } | 165 } |
| 165 // If TargetTrue is the next node, and TargetFalse is non-NULL | 166 // If TargetTrue is the next node, and TargetFalse is non-NULL |
| 166 // (which was already tested above), then invert the branch | 167 // (which was already tested above), then invert the branch |
| 167 // condition, swap the targets, and set new fallthrough to NULL. | 168 // condition, swap the targets, and set new fallthrough to NULL. |
| 168 if (getTargetTrue() == NextNode) { | 169 if (getTargetTrue() == NextNode) { |
| 169 assert(Condition != Br_None); | 170 assert(Condition != CondX86::Br_None); |
| 170 Condition = InstX8632BrAttributes[Condition].Opposite; | 171 Condition = InstX8632BrAttributes[Condition].Opposite; |
| 171 TargetTrue = getTargetFalse(); | 172 TargetTrue = getTargetFalse(); |
| 172 TargetFalse = NULL; | 173 TargetFalse = NULL; |
| 173 return true; | 174 return true; |
| 174 } | 175 } |
| 175 return false; | 176 return false; |
| 176 } | 177 } |
| 177 | 178 |
| 178 InstX8632Call::InstX8632Call(Cfg *Func, Variable *Dest, Operand *CallTarget) | 179 InstX8632Call::InstX8632Call(Cfg *Func, Variable *Dest, Operand *CallTarget) |
| 179 : InstX8632(Func, InstX8632::Call, 1, Dest) { | 180 : InstX8632(Func, InstX8632::Call, 1, Dest) { |
| 180 HasSideEffects = true; | 181 HasSideEffects = true; |
| 181 addSource(CallTarget); | 182 addSource(CallTarget); |
| 182 } | 183 } |
| 183 | 184 |
| 184 InstX8632Cmov::InstX8632Cmov(Cfg *Func, Variable *Dest, Operand *Source, | 185 InstX8632Cmov::InstX8632Cmov(Cfg *Func, Variable *Dest, Operand *Source, |
| 185 InstX8632::BrCond Condition) | 186 CondX86::BrCond Condition) |
| 186 : InstX8632(Func, InstX8632::Cmov, 2, Dest), Condition(Condition) { | 187 : InstX8632(Func, InstX8632::Cmov, 2, Dest), Condition(Condition) { |
| 187 // The final result is either the original Dest, or Source, so mark | 188 // The final result is either the original Dest, or Source, so mark |
| 188 // both as sources. | 189 // both as sources. |
| 189 addSource(Dest); | 190 addSource(Dest); |
| 190 addSource(Source); | 191 addSource(Source); |
| 191 } | 192 } |
| 192 | 193 |
| 193 InstX8632Cmpps::InstX8632Cmpps(Cfg *Func, Variable *Dest, Operand *Source, | 194 InstX8632Cmpps::InstX8632Cmpps(Cfg *Func, Variable *Dest, Operand *Source, |
| 194 InstX8632Cmpps::CmppsCond Condition) | 195 CondX86::CmppsCond Condition) |
| 195 : InstX8632(Func, InstX8632::Cmpps, 2, Dest), Condition(Condition) { | 196 : InstX8632(Func, InstX8632::Cmpps, 2, Dest), Condition(Condition) { |
| 196 addSource(Dest); | 197 addSource(Dest); |
| 197 addSource(Source); | 198 addSource(Source); |
| 198 } | 199 } |
| 199 | 200 |
| 200 InstX8632Cmpxchg::InstX8632Cmpxchg(Cfg *Func, Operand *DestOrAddr, | 201 InstX8632Cmpxchg::InstX8632Cmpxchg(Cfg *Func, Operand *DestOrAddr, |
| 201 Variable *Eax, Variable *Desired, | 202 Variable *Eax, Variable *Desired, |
| 202 bool Locked) | 203 bool Locked) |
| 203 : InstX8632Lockable(Func, InstX8632::Cmpxchg, 3, | 204 : InstX8632Lockable(Func, InstX8632::Cmpxchg, 3, |
| 204 llvm::dyn_cast<Variable>(DestOrAddr), Locked) { | 205 llvm::dyn_cast<Variable>(DestOrAddr), Locked) { |
| 205 assert(Eax->getRegNum() == TargetX8632::Reg_eax); | 206 assert(Eax->getRegNum() == RegX8632::Reg_eax); |
| 206 addSource(DestOrAddr); | 207 addSource(DestOrAddr); |
| 207 addSource(Eax); | 208 addSource(Eax); |
| 208 addSource(Desired); | 209 addSource(Desired); |
| 209 } | 210 } |
| 210 | 211 |
| 211 InstX8632Cmpxchg8b::InstX8632Cmpxchg8b(Cfg *Func, OperandX8632 *Addr, | 212 InstX8632Cmpxchg8b::InstX8632Cmpxchg8b(Cfg *Func, OperandX8632 *Addr, |
| 212 Variable *Edx, Variable *Eax, | 213 Variable *Edx, Variable *Eax, |
| 213 Variable *Ecx, Variable *Ebx, | 214 Variable *Ecx, Variable *Ebx, |
| 214 bool Locked) | 215 bool Locked) |
| 215 : InstX8632Lockable(Func, InstX8632::Cmpxchg, 5, NULL, Locked) { | 216 : InstX8632Lockable(Func, InstX8632::Cmpxchg, 5, NULL, Locked) { |
| 216 assert(Edx->getRegNum() == TargetX8632::Reg_edx); | 217 assert(Edx->getRegNum() == RegX8632::Reg_edx); |
| 217 assert(Eax->getRegNum() == TargetX8632::Reg_eax); | 218 assert(Eax->getRegNum() == RegX8632::Reg_eax); |
| 218 assert(Ecx->getRegNum() == TargetX8632::Reg_ecx); | 219 assert(Ecx->getRegNum() == RegX8632::Reg_ecx); |
| 219 assert(Ebx->getRegNum() == TargetX8632::Reg_ebx); | 220 assert(Ebx->getRegNum() == RegX8632::Reg_ebx); |
| 220 addSource(Addr); | 221 addSource(Addr); |
| 221 addSource(Edx); | 222 addSource(Edx); |
| 222 addSource(Eax); | 223 addSource(Eax); |
| 223 addSource(Ecx); | 224 addSource(Ecx); |
| 224 addSource(Ebx); | 225 addSource(Ebx); |
| 225 } | 226 } |
| 226 | 227 |
| 227 InstX8632Cvt::InstX8632Cvt(Cfg *Func, Variable *Dest, Operand *Source, | 228 InstX8632Cvt::InstX8632Cvt(Cfg *Func, Variable *Dest, Operand *Source, |
| 228 bool Trunc) | 229 bool Trunc) |
| 229 : InstX8632(Func, InstX8632::Cvt, 1, Dest), Trunc(Trunc) { | 230 : InstX8632(Func, InstX8632::Cvt, 1, Dest), Trunc(Trunc) { |
| (...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 340 | 341 |
| 341 void InstX8632Label::dump(const Cfg *Func) const { | 342 void InstX8632Label::dump(const Cfg *Func) const { |
| 342 Ostream &Str = Func->getContext()->getStrDump(); | 343 Ostream &Str = Func->getContext()->getStrDump(); |
| 343 Str << getName(Func) << ":"; | 344 Str << getName(Func) << ":"; |
| 344 } | 345 } |
| 345 | 346 |
| 346 void InstX8632Br::emit(const Cfg *Func) const { | 347 void InstX8632Br::emit(const Cfg *Func) const { |
| 347 Ostream &Str = Func->getContext()->getStrEmit(); | 348 Ostream &Str = Func->getContext()->getStrEmit(); |
| 348 Str << "\t"; | 349 Str << "\t"; |
| 349 | 350 |
| 350 if (Condition == Br_None) { | 351 if (Condition == CondX86::Br_None) { |
| 351 Str << "jmp"; | 352 Str << "jmp"; |
| 352 } else { | 353 } else { |
| 353 Str << InstX8632BrAttributes[Condition].EmitString; | 354 Str << InstX8632BrAttributes[Condition].EmitString; |
| 354 } | 355 } |
| 355 | 356 |
| 356 if (Label) { | 357 if (Label) { |
| 357 Str << "\t" << Label->getName(Func) << "\n"; | 358 Str << "\t" << Label->getName(Func) << "\n"; |
| 358 } else { | 359 } else { |
| 359 if (Condition == Br_None) { | 360 if (Condition == CondX86::Br_None) { |
| 360 Str << "\t" << getTargetFalse()->getAsmName() << "\n"; | 361 Str << "\t" << getTargetFalse()->getAsmName() << "\n"; |
| 361 } else { | 362 } else { |
| 362 Str << "\t" << getTargetTrue()->getAsmName() << "\n"; | 363 Str << "\t" << getTargetTrue()->getAsmName() << "\n"; |
| 363 if (getTargetFalse()) { | 364 if (getTargetFalse()) { |
| 364 Str << "\tjmp\t" << getTargetFalse()->getAsmName() << "\n"; | 365 Str << "\tjmp\t" << getTargetFalse()->getAsmName() << "\n"; |
| 365 } | 366 } |
| 366 } | 367 } |
| 367 } | 368 } |
| 368 } | 369 } |
| 369 | 370 |
| 370 void InstX8632Br::dump(const Cfg *Func) const { | 371 void InstX8632Br::dump(const Cfg *Func) const { |
| 371 Ostream &Str = Func->getContext()->getStrDump(); | 372 Ostream &Str = Func->getContext()->getStrDump(); |
| 372 Str << "br "; | 373 Str << "br "; |
| 373 | 374 |
| 374 if (Condition == Br_None) { | 375 if (Condition == CondX86::Br_None) { |
| 375 Str << "label %" | 376 Str << "label %" |
| 376 << (Label ? Label->getName(Func) : getTargetFalse()->getName()); | 377 << (Label ? Label->getName(Func) : getTargetFalse()->getName()); |
| 377 return; | 378 return; |
| 378 } | 379 } |
| 379 | 380 |
| 380 Str << InstX8632BrAttributes[Condition].DisplayString; | 381 Str << InstX8632BrAttributes[Condition].DisplayString; |
| 381 if (Label) { | 382 if (Label) { |
| 382 Str << ", label %" << Label->getName(Func); | 383 Str << ", label %" << Label->getName(Func); |
| 383 } else { | 384 } else { |
| 384 Str << ", label %" << getTargetTrue()->getName(); | 385 Str << ", label %" << getTargetTrue()->getName(); |
| (...skipping 30 matching lines...) Expand all Loading... |
| 415 bool ShiftHack) { | 416 bool ShiftHack) { |
| 416 Ostream &Str = Func->getContext()->getStrEmit(); | 417 Ostream &Str = Func->getContext()->getStrEmit(); |
| 417 assert(Inst->getSrcSize() == 2); | 418 assert(Inst->getSrcSize() == 2); |
| 418 assert(Inst->getDest() == Inst->getSrc(0)); | 419 assert(Inst->getDest() == Inst->getSrc(0)); |
| 419 Str << "\t" << Opcode << "\t"; | 420 Str << "\t" << Opcode << "\t"; |
| 420 Inst->getDest()->emit(Func); | 421 Inst->getDest()->emit(Func); |
| 421 Str << ", "; | 422 Str << ", "; |
| 422 bool EmittedSrc1 = false; | 423 bool EmittedSrc1 = false; |
| 423 if (ShiftHack) { | 424 if (ShiftHack) { |
| 424 Variable *ShiftReg = llvm::dyn_cast<Variable>(Inst->getSrc(1)); | 425 Variable *ShiftReg = llvm::dyn_cast<Variable>(Inst->getSrc(1)); |
| 425 if (ShiftReg && ShiftReg->getRegNum() == TargetX8632::Reg_ecx) { | 426 if (ShiftReg && ShiftReg->getRegNum() == RegX8632::Reg_ecx) { |
| 426 Str << "cl"; | 427 Str << "cl"; |
| 427 EmittedSrc1 = true; | 428 EmittedSrc1 = true; |
| 428 } | 429 } |
| 429 } | 430 } |
| 430 if (!EmittedSrc1) | 431 if (!EmittedSrc1) |
| 431 Inst->getSrc(1)->emit(Func); | 432 Inst->getSrc(1)->emit(Func); |
| 432 Str << "\n"; | 433 Str << "\n"; |
| 433 } | 434 } |
| 434 | 435 |
| 435 bool checkForRedundantAssign(const Variable *Dest, const Operand *Source) { | 436 bool checkForRedundantAssign(const Variable *Dest, const Operand *Source) { |
| (...skipping 168 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 604 | 605 |
| 605 namespace { | 606 namespace { |
| 606 | 607 |
| 607 // pblendvb and blendvps take xmm0 as a final implicit argument. | 608 // pblendvb and blendvps take xmm0 as a final implicit argument. |
| 608 void emitVariableBlendInst(const char *Opcode, const Inst *Inst, | 609 void emitVariableBlendInst(const char *Opcode, const Inst *Inst, |
| 609 const Cfg *Func) { | 610 const Cfg *Func) { |
| 610 Ostream &Str = Func->getContext()->getStrEmit(); | 611 Ostream &Str = Func->getContext()->getStrEmit(); |
| 611 assert(Inst->getSrcSize() == 3); | 612 assert(Inst->getSrcSize() == 3); |
| 612 assert(llvm::isa<Variable>(Inst->getSrc(2))); | 613 assert(llvm::isa<Variable>(Inst->getSrc(2))); |
| 613 assert(llvm::cast<Variable>(Inst->getSrc(2))->getRegNum() == | 614 assert(llvm::cast<Variable>(Inst->getSrc(2))->getRegNum() == |
| 614 TargetX8632::Reg_xmm0); | 615 RegX8632::Reg_xmm0); |
| 615 Str << "\t" << Opcode << "\t"; | 616 Str << "\t" << Opcode << "\t"; |
| 616 Inst->getDest()->emit(Func); | 617 Inst->getDest()->emit(Func); |
| 617 Str << ", "; | 618 Str << ", "; |
| 618 Inst->getSrc(1)->emit(Func); | 619 Inst->getSrc(1)->emit(Func); |
| 619 Str << "\n"; | 620 Str << "\n"; |
| 620 } | 621 } |
| 621 | 622 |
| 622 } // end anonymous namespace | 623 } // end anonymous namespace |
| 623 | 624 |
| 624 template <> void InstX8632Blendvps::emit(const Cfg *Func) const { | 625 template <> void InstX8632Blendvps::emit(const Cfg *Func) const { |
| 625 assert(static_cast<TargetX8632 *>(Func->getTarget())->getInstructionSet() >= | 626 assert(static_cast<TargetX8632 *>(Func->getTarget())->getInstructionSet() >= |
| 626 TargetX8632::SSE4_1); | 627 TargetX8632::SSE4_1); |
| 627 emitVariableBlendInst(Opcode, this, Func); | 628 emitVariableBlendInst(Opcode, this, Func); |
| 628 } | 629 } |
| 629 | 630 |
| 630 template <> void InstX8632Pblendvb::emit(const Cfg *Func) const { | 631 template <> void InstX8632Pblendvb::emit(const Cfg *Func) const { |
| 631 assert(static_cast<TargetX8632 *>(Func->getTarget())->getInstructionSet() >= | 632 assert(static_cast<TargetX8632 *>(Func->getTarget())->getInstructionSet() >= |
| 632 TargetX8632::SSE4_1); | 633 TargetX8632::SSE4_1); |
| 633 emitVariableBlendInst(Opcode, this, Func); | 634 emitVariableBlendInst(Opcode, this, Func); |
| 634 } | 635 } |
| 635 | 636 |
| 636 template <> void InstX8632Imul::emit(const Cfg *Func) const { | 637 template <> void InstX8632Imul::emit(const Cfg *Func) const { |
| 637 Ostream &Str = Func->getContext()->getStrEmit(); | 638 Ostream &Str = Func->getContext()->getStrEmit(); |
| 638 assert(getSrcSize() == 2); | 639 assert(getSrcSize() == 2); |
| 639 if (getDest()->getType() == IceType_i8) { | 640 if (getDest()->getType() == IceType_i8) { |
| 640 // The 8-bit version of imul only allows the form "imul r/m8". | 641 // The 8-bit version of imul only allows the form "imul r/m8". |
| 641 Variable *Src0 = llvm::dyn_cast<Variable>(getSrc(0)); | 642 Variable *Src0 = llvm::dyn_cast<Variable>(getSrc(0)); |
| 642 (void)Src0; | 643 (void)Src0; |
| 643 assert(Src0 && Src0->getRegNum() == TargetX8632::Reg_eax); | 644 assert(Src0 && Src0->getRegNum() == RegX8632::Reg_eax); |
| 644 Str << "\timul\t"; | 645 Str << "\timul\t"; |
| 645 getSrc(1)->emit(Func); | 646 getSrc(1)->emit(Func); |
| 646 Str << "\n"; | 647 Str << "\n"; |
| 647 } else if (llvm::isa<Constant>(getSrc(1))) { | 648 } else if (llvm::isa<Constant>(getSrc(1))) { |
| 648 Str << "\timul\t"; | 649 Str << "\timul\t"; |
| 649 getDest()->emit(Func); | 650 getDest()->emit(Func); |
| 650 Str << ", "; | 651 Str << ", "; |
| 651 getSrc(0)->emit(Func); | 652 getSrc(0)->emit(Func); |
| 652 Str << ", "; | 653 Str << ", "; |
| 653 getSrc(1)->emit(Func); | 654 getSrc(1)->emit(Func); |
| 654 Str << "\n"; | 655 Str << "\n"; |
| 655 } else { | 656 } else { |
| 656 emitTwoAddress("imul", this, Func); | 657 emitTwoAddress("imul", this, Func); |
| 657 } | 658 } |
| 658 } | 659 } |
| 659 | 660 |
| 660 template <> void InstX8632Cbwdq::emit(const Cfg *Func) const { | 661 template <> void InstX8632Cbwdq::emit(const Cfg *Func) const { |
| 661 Ostream &Str = Func->getContext()->getStrEmit(); | 662 Ostream &Str = Func->getContext()->getStrEmit(); |
| 662 assert(getSrcSize() == 1); | 663 assert(getSrcSize() == 1); |
| 663 Operand *Src0 = getSrc(0); | 664 Operand *Src0 = getSrc(0); |
| 664 assert(llvm::isa<Variable>(Src0)); | 665 assert(llvm::isa<Variable>(Src0)); |
| 665 assert(llvm::cast<Variable>(Src0)->getRegNum() == TargetX8632::Reg_eax); | 666 assert(llvm::cast<Variable>(Src0)->getRegNum() == RegX8632::Reg_eax); |
| 666 switch (Src0->getType()) { | 667 switch (Src0->getType()) { |
| 667 default: | 668 default: |
| 668 llvm_unreachable("unexpected source type!"); | 669 llvm_unreachable("unexpected source type!"); |
| 669 break; | 670 break; |
| 670 case IceType_i8: | 671 case IceType_i8: |
| 671 assert(getDest()->getRegNum() == TargetX8632::Reg_eax); | 672 assert(getDest()->getRegNum() == RegX8632::Reg_eax); |
| 672 Str << "\tcbw\n"; | 673 Str << "\tcbw\n"; |
| 673 break; | 674 break; |
| 674 case IceType_i16: | 675 case IceType_i16: |
| 675 assert(getDest()->getRegNum() == TargetX8632::Reg_edx); | 676 assert(getDest()->getRegNum() == RegX8632::Reg_edx); |
| 676 Str << "\tcwd\n"; | 677 Str << "\tcwd\n"; |
| 677 break; | 678 break; |
| 678 case IceType_i32: | 679 case IceType_i32: |
| 679 assert(getDest()->getRegNum() == TargetX8632::Reg_edx); | 680 assert(getDest()->getRegNum() == RegX8632::Reg_edx); |
| 680 Str << "\tcdq\n"; | 681 Str << "\tcdq\n"; |
| 681 break; | 682 break; |
| 682 } | 683 } |
| 683 } | 684 } |
| 684 | 685 |
| 685 void InstX8632Mul::emit(const Cfg *Func) const { | 686 void InstX8632Mul::emit(const Cfg *Func) const { |
| 686 Ostream &Str = Func->getContext()->getStrEmit(); | 687 Ostream &Str = Func->getContext()->getStrEmit(); |
| 687 assert(getSrcSize() == 2); | 688 assert(getSrcSize() == 2); |
| 688 assert(llvm::isa<Variable>(getSrc(0))); | 689 assert(llvm::isa<Variable>(getSrc(0))); |
| 689 assert(llvm::dyn_cast<Variable>(getSrc(0))->getRegNum() == | 690 assert(llvm::dyn_cast<Variable>(getSrc(0))->getRegNum() == RegX8632::Reg_eax); |
| 690 TargetX8632::Reg_eax); | 691 assert(getDest()->getRegNum() == RegX8632::Reg_eax); // TODO: allow edx? |
| 691 assert(getDest()->getRegNum() == TargetX8632::Reg_eax); // TODO: allow edx? | |
| 692 Str << "\tmul\t"; | 692 Str << "\tmul\t"; |
| 693 getSrc(1)->emit(Func); | 693 getSrc(1)->emit(Func); |
| 694 Str << "\n"; | 694 Str << "\n"; |
| 695 } | 695 } |
| 696 | 696 |
| 697 void InstX8632Mul::dump(const Cfg *Func) const { | 697 void InstX8632Mul::dump(const Cfg *Func) const { |
| 698 Ostream &Str = Func->getContext()->getStrDump(); | 698 Ostream &Str = Func->getContext()->getStrDump(); |
| 699 dumpDest(Func); | 699 dumpDest(Func); |
| 700 Str << " = mul." << getDest()->getType() << " "; | 700 Str << " = mul." << getDest()->getType() << " "; |
| 701 dumpSources(Func); | 701 dumpSources(Func); |
| 702 } | 702 } |
| 703 | 703 |
| 704 void InstX8632Shld::emit(const Cfg *Func) const { | 704 void InstX8632Shld::emit(const Cfg *Func) const { |
| 705 Ostream &Str = Func->getContext()->getStrEmit(); | 705 Ostream &Str = Func->getContext()->getStrEmit(); |
| 706 assert(getSrcSize() == 3); | 706 assert(getSrcSize() == 3); |
| 707 assert(getDest() == getSrc(0)); | 707 assert(getDest() == getSrc(0)); |
| 708 Str << "\tshld\t"; | 708 Str << "\tshld\t"; |
| 709 getDest()->emit(Func); | 709 getDest()->emit(Func); |
| 710 Str << ", "; | 710 Str << ", "; |
| 711 getSrc(1)->emit(Func); | 711 getSrc(1)->emit(Func); |
| 712 Str << ", "; | 712 Str << ", "; |
| 713 if (Variable *ShiftReg = llvm::dyn_cast<Variable>(getSrc(2))) { | 713 if (Variable *ShiftReg = llvm::dyn_cast<Variable>(getSrc(2))) { |
| 714 (void)ShiftReg; | 714 (void)ShiftReg; |
| 715 assert(ShiftReg->getRegNum() == TargetX8632::Reg_ecx); | 715 assert(ShiftReg->getRegNum() == RegX8632::Reg_ecx); |
| 716 Str << "cl"; | 716 Str << "cl"; |
| 717 } else { | 717 } else { |
| 718 getSrc(2)->emit(Func); | 718 getSrc(2)->emit(Func); |
| 719 } | 719 } |
| 720 Str << "\n"; | 720 Str << "\n"; |
| 721 } | 721 } |
| 722 | 722 |
| 723 void InstX8632Shld::dump(const Cfg *Func) const { | 723 void InstX8632Shld::dump(const Cfg *Func) const { |
| 724 Ostream &Str = Func->getContext()->getStrDump(); | 724 Ostream &Str = Func->getContext()->getStrDump(); |
| 725 dumpDest(Func); | 725 dumpDest(Func); |
| 726 Str << " = shld." << getDest()->getType() << " "; | 726 Str << " = shld." << getDest()->getType() << " "; |
| 727 dumpSources(Func); | 727 dumpSources(Func); |
| 728 } | 728 } |
| 729 | 729 |
| 730 void InstX8632Shrd::emit(const Cfg *Func) const { | 730 void InstX8632Shrd::emit(const Cfg *Func) const { |
| 731 Ostream &Str = Func->getContext()->getStrEmit(); | 731 Ostream &Str = Func->getContext()->getStrEmit(); |
| 732 assert(getSrcSize() == 3); | 732 assert(getSrcSize() == 3); |
| 733 assert(getDest() == getSrc(0)); | 733 assert(getDest() == getSrc(0)); |
| 734 Str << "\tshrd\t"; | 734 Str << "\tshrd\t"; |
| 735 getDest()->emit(Func); | 735 getDest()->emit(Func); |
| 736 Str << ", "; | 736 Str << ", "; |
| 737 getSrc(1)->emit(Func); | 737 getSrc(1)->emit(Func); |
| 738 Str << ", "; | 738 Str << ", "; |
| 739 if (Variable *ShiftReg = llvm::dyn_cast<Variable>(getSrc(2))) { | 739 if (Variable *ShiftReg = llvm::dyn_cast<Variable>(getSrc(2))) { |
| 740 (void)ShiftReg; | 740 (void)ShiftReg; |
| 741 assert(ShiftReg->getRegNum() == TargetX8632::Reg_ecx); | 741 assert(ShiftReg->getRegNum() == RegX8632::Reg_ecx); |
| 742 Str << "cl"; | 742 Str << "cl"; |
| 743 } else { | 743 } else { |
| 744 getSrc(2)->emit(Func); | 744 getSrc(2)->emit(Func); |
| 745 } | 745 } |
| 746 Str << "\n"; | 746 Str << "\n"; |
| 747 } | 747 } |
| 748 | 748 |
| 749 void InstX8632Shrd::dump(const Cfg *Func) const { | 749 void InstX8632Shrd::dump(const Cfg *Func) const { |
| 750 Ostream &Str = Func->getContext()->getStrDump(); | 750 Ostream &Str = Func->getContext()->getStrDump(); |
| 751 dumpDest(Func); | 751 dumpDest(Func); |
| 752 Str << " = shrd." << getDest()->getType() << " "; | 752 Str << " = shrd." << getDest()->getType() << " "; |
| 753 dumpSources(Func); | 753 dumpSources(Func); |
| 754 } | 754 } |
| 755 | 755 |
| 756 void InstX8632Cmov::emit(const Cfg *Func) const { | 756 void InstX8632Cmov::emit(const Cfg *Func) const { |
| 757 Ostream &Str = Func->getContext()->getStrEmit(); | 757 Ostream &Str = Func->getContext()->getStrEmit(); |
| 758 Str << "\t"; | 758 Str << "\t"; |
| 759 assert(Condition != Br_None); | 759 assert(Condition != CondX86::Br_None); |
| 760 assert(getDest()->hasReg()); | 760 assert(getDest()->hasReg()); |
| 761 Str << "cmov" << InstX8632BrAttributes[Condition].DisplayString << "\t"; | 761 Str << "cmov" << InstX8632BrAttributes[Condition].DisplayString << "\t"; |
| 762 getDest()->emit(Func); | 762 getDest()->emit(Func); |
| 763 Str << ", "; | 763 Str << ", "; |
| 764 getSrc(1)->emit(Func); | 764 getSrc(1)->emit(Func); |
| 765 Str << "\n"; | 765 Str << "\n"; |
| 766 } | 766 } |
| 767 | 767 |
| 768 void InstX8632Cmov::dump(const Cfg *Func) const { | 768 void InstX8632Cmov::dump(const Cfg *Func) const { |
| 769 Ostream &Str = Func->getContext()->getStrDump(); | 769 Ostream &Str = Func->getContext()->getStrDump(); |
| 770 Str << "cmov" << InstX8632BrAttributes[Condition].DisplayString << "."; | 770 Str << "cmov" << InstX8632BrAttributes[Condition].DisplayString << "."; |
| 771 Str << getDest()->getType() << " "; | 771 Str << getDest()->getType() << " "; |
| 772 dumpDest(Func); | 772 dumpDest(Func); |
| 773 Str << ", "; | 773 Str << ", "; |
| 774 dumpSources(Func); | 774 dumpSources(Func); |
| 775 } | 775 } |
| 776 | 776 |
| 777 void InstX8632Cmpps::emit(const Cfg *Func) const { | 777 void InstX8632Cmpps::emit(const Cfg *Func) const { |
| 778 Ostream &Str = Func->getContext()->getStrEmit(); | 778 Ostream &Str = Func->getContext()->getStrEmit(); |
| 779 assert(getSrcSize() == 2); | 779 assert(getSrcSize() == 2); |
| 780 assert(Condition < Cmpps_Invalid); | 780 assert(Condition < CondX86::Cmpps_Invalid); |
| 781 Str << "\t"; | 781 Str << "\t"; |
| 782 Str << "cmp" << InstX8632CmppsAttributes[Condition].EmitString << "ps" | 782 Str << "cmp" << InstX8632CmppsAttributes[Condition].EmitString << "ps" |
| 783 << "\t"; | 783 << "\t"; |
| 784 getDest()->emit(Func); | 784 getDest()->emit(Func); |
| 785 Str << ", "; | 785 Str << ", "; |
| 786 getSrc(1)->emit(Func); | 786 getSrc(1)->emit(Func); |
| 787 Str << "\n"; | 787 Str << "\n"; |
| 788 } | 788 } |
| 789 | 789 |
| 790 void InstX8632Cmpps::dump(const Cfg *Func) const { | 790 void InstX8632Cmpps::dump(const Cfg *Func) const { |
| 791 Ostream &Str = Func->getContext()->getStrDump(); | 791 Ostream &Str = Func->getContext()->getStrDump(); |
| 792 assert(Condition < Cmpps_Invalid); | 792 assert(Condition < CondX86::Cmpps_Invalid); |
| 793 dumpDest(Func); | 793 dumpDest(Func); |
| 794 Str << " = cmp" << InstX8632CmppsAttributes[Condition].EmitString << "ps" | 794 Str << " = cmp" << InstX8632CmppsAttributes[Condition].EmitString << "ps" |
| 795 << "\t"; | 795 << "\t"; |
| 796 dumpSources(Func); | 796 dumpSources(Func); |
| 797 } | 797 } |
| 798 | 798 |
| 799 void InstX8632Cmpxchg::emit(const Cfg *Func) const { | 799 void InstX8632Cmpxchg::emit(const Cfg *Func) const { |
| 800 Ostream &Str = Func->getContext()->getStrEmit(); | 800 Ostream &Str = Func->getContext()->getStrEmit(); |
| 801 assert(getSrcSize() == 3); | 801 assert(getSrcSize() == 3); |
| 802 if (Locked) { | 802 if (Locked) { |
| (...skipping 727 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1530 } | 1530 } |
| 1531 Str << "("; | 1531 Str << "("; |
| 1532 if (Func) | 1532 if (Func) |
| 1533 Var->dump(Func); | 1533 Var->dump(Func); |
| 1534 else | 1534 else |
| 1535 Var->dump(Str); | 1535 Var->dump(Str); |
| 1536 Str << ")"; | 1536 Str << ")"; |
| 1537 } | 1537 } |
| 1538 | 1538 |
| 1539 } // end of namespace Ice | 1539 } // end of namespace Ice |
| OLD | NEW |