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 269 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
280 addSource(Mem); | 280 addSource(Mem); |
281 } | 281 } |
282 | 282 |
283 InstX8632StoreQ::InstX8632StoreQ(Cfg *Func, Variable *Value, | 283 InstX8632StoreQ::InstX8632StoreQ(Cfg *Func, Variable *Value, |
284 OperandX8632Mem *Mem) | 284 OperandX8632Mem *Mem) |
285 : InstX8632(Func, InstX8632::StoreQ, 2, NULL) { | 285 : InstX8632(Func, InstX8632::StoreQ, 2, NULL) { |
286 addSource(Value); | 286 addSource(Value); |
287 addSource(Mem); | 287 addSource(Mem); |
288 } | 288 } |
289 | 289 |
290 InstX8632Movsx::InstX8632Movsx(Cfg *Func, Variable *Dest, Operand *Source) | |
291 : InstX8632(Func, InstX8632::Movsx, 1, Dest) { | |
292 addSource(Source); | |
293 } | |
294 | |
295 InstX8632Movzx::InstX8632Movzx(Cfg *Func, Variable *Dest, Operand *Source) | |
296 : InstX8632(Func, InstX8632::Movzx, 1, Dest) { | |
297 addSource(Source); | |
298 } | |
299 | |
300 InstX8632Nop::InstX8632Nop(Cfg *Func, InstX8632Nop::NopVariant Variant) | 290 InstX8632Nop::InstX8632Nop(Cfg *Func, InstX8632Nop::NopVariant Variant) |
301 : InstX8632(Func, InstX8632::Nop, 0, NULL), Variant(Variant) {} | 291 : InstX8632(Func, InstX8632::Nop, 0, NULL), Variant(Variant) {} |
302 | 292 |
303 InstX8632Fld::InstX8632Fld(Cfg *Func, Operand *Src) | 293 InstX8632Fld::InstX8632Fld(Cfg *Func, Operand *Src) |
304 : InstX8632(Func, InstX8632::Fld, 1, NULL) { | 294 : InstX8632(Func, InstX8632::Fld, 1, NULL) { |
305 addSource(Src); | 295 addSource(Src); |
306 } | 296 } |
307 | 297 |
308 InstX8632Fstp::InstX8632Fstp(Cfg *Func, Variable *Dest) | 298 InstX8632Fstp::InstX8632Fstp(Cfg *Func, Variable *Dest) |
309 : InstX8632(Func, InstX8632::Fstp, 0, Dest) {} | 299 : InstX8632(Func, InstX8632::Fstp, 0, Dest) {} |
(...skipping 199 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
509 } | 499 } |
510 } else if (const auto Mem = llvm::dyn_cast<OperandX8632Mem>(Op)) { | 500 } else if (const auto Mem = llvm::dyn_cast<OperandX8632Mem>(Op)) { |
511 Mem->emitSegmentOverride(Asm); | 501 Mem->emitSegmentOverride(Asm); |
512 (Asm->*(Emitter.Addr))(Ty, Mem->toAsmAddress(Asm)); | 502 (Asm->*(Emitter.Addr))(Ty, Mem->toAsmAddress(Asm)); |
513 } else { | 503 } else { |
514 llvm_unreachable("Unexpected operand type"); | 504 llvm_unreachable("Unexpected operand type"); |
515 } | 505 } |
516 emitIASBytes(Func, Asm, StartPosition); | 506 emitIASBytes(Func, Asm, StartPosition); |
517 } | 507 } |
518 | 508 |
| 509 template <bool VarCanBeByte, bool SrcCanBeByte> |
519 void emitIASRegOpTyGPR(const Cfg *Func, Type Ty, const Variable *Var, | 510 void emitIASRegOpTyGPR(const Cfg *Func, Type Ty, const Variable *Var, |
520 const Operand *Src, | 511 const Operand *Src, |
521 const x86::AssemblerX86::GPREmitterRegOp &Emitter) { | 512 const x86::AssemblerX86::GPREmitterRegOp &Emitter) { |
522 x86::AssemblerX86 *Asm = Func->getAssembler<x86::AssemblerX86>(); | 513 x86::AssemblerX86 *Asm = Func->getAssembler<x86::AssemblerX86>(); |
523 intptr_t StartPosition = Asm->GetPosition(); | 514 intptr_t StartPosition = Asm->GetPosition(); |
524 assert(Var->hasReg()); | 515 assert(Var->hasReg()); |
525 // We cheat a little and use GPRRegister even for byte operations. | 516 // We cheat a little and use GPRRegister even for byte operations. |
526 RegX8632::GPRRegister VarReg = | 517 RegX8632::GPRRegister VarReg = |
527 RegX8632::getEncodedByteRegOrGPR(Ty, Var->getRegNum()); | 518 VarCanBeByte ? RegX8632::getEncodedByteRegOrGPR(Ty, Var->getRegNum()) |
| 519 : RegX8632::getEncodedGPR(Var->getRegNum()); |
528 if (const auto SrcVar = llvm::dyn_cast<Variable>(Src)) { | 520 if (const auto SrcVar = llvm::dyn_cast<Variable>(Src)) { |
529 if (SrcVar->hasReg()) { | 521 if (SrcVar->hasReg()) { |
530 RegX8632::GPRRegister SrcReg = | 522 RegX8632::GPRRegister SrcReg = |
531 RegX8632::getEncodedByteRegOrGPR(Ty, SrcVar->getRegNum()); | 523 SrcCanBeByte |
| 524 ? RegX8632::getEncodedByteRegOrGPR(Ty, SrcVar->getRegNum()) |
| 525 : RegX8632::getEncodedGPR(SrcVar->getRegNum()); |
532 (Asm->*(Emitter.GPRGPR))(Ty, VarReg, SrcReg); | 526 (Asm->*(Emitter.GPRGPR))(Ty, VarReg, SrcReg); |
533 } else { | 527 } else { |
534 x86::Address SrcStackAddr = static_cast<TargetX8632 *>(Func->getTarget()) | 528 x86::Address SrcStackAddr = static_cast<TargetX8632 *>(Func->getTarget()) |
535 ->stackVarToAsmOperand(SrcVar); | 529 ->stackVarToAsmOperand(SrcVar); |
536 (Asm->*(Emitter.GPRAddr))(Ty, VarReg, SrcStackAddr); | 530 (Asm->*(Emitter.GPRAddr))(Ty, VarReg, SrcStackAddr); |
537 } | 531 } |
538 } else if (const auto Mem = llvm::dyn_cast<OperandX8632Mem>(Src)) { | 532 } else if (const auto Mem = llvm::dyn_cast<OperandX8632Mem>(Src)) { |
539 Mem->emitSegmentOverride(Asm); | 533 Mem->emitSegmentOverride(Asm); |
540 (Asm->*(Emitter.GPRAddr))(Ty, VarReg, Mem->toAsmAddress(Asm)); | 534 (Asm->*(Emitter.GPRAddr))(Ty, VarReg, Mem->toAsmAddress(Asm)); |
541 } else if (const auto Imm = llvm::dyn_cast<ConstantInteger32>(Src)) { | 535 } else if (const auto Imm = llvm::dyn_cast<ConstantInteger32>(Src)) { |
(...skipping 250 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
792 } | 786 } |
793 | 787 |
794 // In-place ops | 788 // In-place ops |
795 template <> const char *InstX8632Bswap::Opcode = "bswap"; | 789 template <> const char *InstX8632Bswap::Opcode = "bswap"; |
796 template <> const char *InstX8632Neg::Opcode = "neg"; | 790 template <> const char *InstX8632Neg::Opcode = "neg"; |
797 // Unary ops | 791 // Unary ops |
798 template <> const char *InstX8632Bsf::Opcode = "bsf"; | 792 template <> const char *InstX8632Bsf::Opcode = "bsf"; |
799 template <> const char *InstX8632Bsr::Opcode = "bsr"; | 793 template <> const char *InstX8632Bsr::Opcode = "bsr"; |
800 template <> const char *InstX8632Lea::Opcode = "lea"; | 794 template <> const char *InstX8632Lea::Opcode = "lea"; |
801 template <> const char *InstX8632Movd::Opcode = "movd"; | 795 template <> const char *InstX8632Movd::Opcode = "movd"; |
| 796 template <> const char *InstX8632Movsx::Opcode = "movsx"; |
| 797 template <> const char *InstX8632Movzx::Opcode = "movzx"; |
802 template <> const char *InstX8632Sqrtss::Opcode = "sqrtss"; | 798 template <> const char *InstX8632Sqrtss::Opcode = "sqrtss"; |
803 template <> const char *InstX8632Cbwdq::Opcode = "cbw/cwd/cdq"; | 799 template <> const char *InstX8632Cbwdq::Opcode = "cbw/cwd/cdq"; |
804 // Mov-like ops | 800 // Mov-like ops |
805 template <> const char *InstX8632Mov::Opcode = "mov"; | 801 template <> const char *InstX8632Mov::Opcode = "mov"; |
806 template <> const char *InstX8632Movp::Opcode = "movups"; | 802 template <> const char *InstX8632Movp::Opcode = "movups"; |
807 template <> const char *InstX8632Movq::Opcode = "movq"; | 803 template <> const char *InstX8632Movq::Opcode = "movq"; |
808 // Binary ops | 804 // Binary ops |
809 template <> const char *InstX8632Add::Opcode = "add"; | 805 template <> const char *InstX8632Add::Opcode = "add"; |
810 template <> const char *InstX8632Addps::Opcode = "addps"; | 806 template <> const char *InstX8632Addps::Opcode = "addps"; |
811 template <> const char *InstX8632Adc::Opcode = "adc"; | 807 template <> const char *InstX8632Adc::Opcode = "adc"; |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
862 // Unary GPR ops | 858 // Unary GPR ops |
863 template <> | 859 template <> |
864 const x86::AssemblerX86::GPREmitterRegOp InstX8632Bsf::Emitter = { | 860 const x86::AssemblerX86::GPREmitterRegOp InstX8632Bsf::Emitter = { |
865 &x86::AssemblerX86::bsf, &x86::AssemblerX86::bsf, NULL}; | 861 &x86::AssemblerX86::bsf, &x86::AssemblerX86::bsf, NULL}; |
866 template <> | 862 template <> |
867 const x86::AssemblerX86::GPREmitterRegOp InstX8632Bsr::Emitter = { | 863 const x86::AssemblerX86::GPREmitterRegOp InstX8632Bsr::Emitter = { |
868 &x86::AssemblerX86::bsr, &x86::AssemblerX86::bsr, NULL}; | 864 &x86::AssemblerX86::bsr, &x86::AssemblerX86::bsr, NULL}; |
869 template <> | 865 template <> |
870 const x86::AssemblerX86::GPREmitterRegOp InstX8632Lea::Emitter = { | 866 const x86::AssemblerX86::GPREmitterRegOp InstX8632Lea::Emitter = { |
871 /* reg/reg and reg/imm are illegal */ NULL, &x86::AssemblerX86::lea, NULL}; | 867 /* reg/reg and reg/imm are illegal */ NULL, &x86::AssemblerX86::lea, NULL}; |
| 868 template <> |
| 869 const x86::AssemblerX86::GPREmitterRegOp InstX8632Movsx::Emitter = { |
| 870 &x86::AssemblerX86::movsx, &x86::AssemblerX86::movsx, NULL}; |
| 871 template <> |
| 872 const x86::AssemblerX86::GPREmitterRegOp InstX8632Movzx::Emitter = { |
| 873 &x86::AssemblerX86::movzx, &x86::AssemblerX86::movzx, NULL}; |
872 | 874 |
873 // Unary XMM ops | 875 // Unary XMM ops |
874 template <> | 876 template <> |
875 const x86::AssemblerX86::XmmEmitterRegOp InstX8632Sqrtss::Emitter = { | 877 const x86::AssemblerX86::XmmEmitterRegOp InstX8632Sqrtss::Emitter = { |
876 &x86::AssemblerX86::sqrtss, &x86::AssemblerX86::sqrtss | 878 &x86::AssemblerX86::sqrtss, &x86::AssemblerX86::sqrtss |
877 }; | 879 }; |
878 | 880 |
879 // Binary GPR ops | 881 // Binary GPR ops |
880 template <> | 882 template <> |
881 const x86::AssemblerX86::GPREmitterRegOp InstX8632Add::Emitter = { | 883 const x86::AssemblerX86::GPREmitterRegOp InstX8632Add::Emitter = { |
(...skipping 1228 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2110 assert(Dest == getSrc(0)); | 2112 assert(Dest == getSrc(0)); |
2111 const Variable *Src = llvm::cast<Variable>(getSrc(1)); | 2113 const Variable *Src = llvm::cast<Variable>(getSrc(1)); |
2112 assert(Dest->hasReg() && Src->hasReg()); | 2114 assert(Dest->hasReg() && Src->hasReg()); |
2113 x86::AssemblerX86 *Asm = Func->getAssembler<x86::AssemblerX86>(); | 2115 x86::AssemblerX86 *Asm = Func->getAssembler<x86::AssemblerX86>(); |
2114 intptr_t StartPosition = Asm->GetPosition(); | 2116 intptr_t StartPosition = Asm->GetPosition(); |
2115 Asm->movss(IceType_f32, RegX8632::getEncodedXmm(Dest->getRegNum()), | 2117 Asm->movss(IceType_f32, RegX8632::getEncodedXmm(Dest->getRegNum()), |
2116 RegX8632::getEncodedXmm(Src->getRegNum())); | 2118 RegX8632::getEncodedXmm(Src->getRegNum())); |
2117 emitIASBytes(Func, Asm, StartPosition); | 2119 emitIASBytes(Func, Asm, StartPosition); |
2118 } | 2120 } |
2119 | 2121 |
2120 void InstX8632Movsx::emit(const Cfg *Func) const { | 2122 template <> void InstX8632Movsx::emitIAS(const Cfg *Func) const { |
2121 Ostream &Str = Func->getContext()->getStrEmit(); | |
2122 assert(getSrcSize() == 1); | 2123 assert(getSrcSize() == 1); |
2123 Str << "\tmovsx\t"; | 2124 const Variable *Dest = getDest(); |
2124 getDest()->emit(Func); | 2125 const Operand *Src = getSrc(0); |
2125 Str << ", "; | 2126 // Dest must be a > 8-bit register, but Src can be 8-bit. In practice |
2126 getSrc(0)->emit(Func); | 2127 // we just use the full register for Dest to avoid having an |
2127 Str << "\n"; | 2128 // OperandSizeOverride prefix. It also allows us to only dispatch on SrcTy. |
| 2129 Type SrcTy = Src->getType(); |
| 2130 assert(typeWidthInBytes(Dest->getType()) > 1); |
| 2131 assert(typeWidthInBytes(Dest->getType()) > typeWidthInBytes(SrcTy)); |
| 2132 emitIASRegOpTyGPR<false, true>(Func, SrcTy, Dest, Src, Emitter); |
2128 } | 2133 } |
2129 | 2134 |
2130 void InstX8632Movsx::dump(const Cfg *Func) const { | 2135 template <> void InstX8632Movzx::emitIAS(const Cfg *Func) const { |
2131 Ostream &Str = Func->getContext()->getStrDump(); | |
2132 Str << "movsx." << getDest()->getType() << "." << getSrc(0)->getType(); | |
2133 Str << " "; | |
2134 dumpDest(Func); | |
2135 Str << ", "; | |
2136 dumpSources(Func); | |
2137 } | |
2138 | |
2139 void InstX8632Movzx::emit(const Cfg *Func) const { | |
2140 Ostream &Str = Func->getContext()->getStrEmit(); | |
2141 assert(getSrcSize() == 1); | 2136 assert(getSrcSize() == 1); |
2142 Str << "\tmovzx\t"; | 2137 const Variable *Dest = getDest(); |
2143 getDest()->emit(Func); | 2138 const Operand *Src = getSrc(0); |
2144 Str << ", "; | 2139 Type SrcTy = Src->getType(); |
2145 getSrc(0)->emit(Func); | 2140 assert(typeWidthInBytes(Dest->getType()) > 1); |
2146 Str << "\n"; | 2141 assert(typeWidthInBytes(Dest->getType()) > typeWidthInBytes(SrcTy)); |
2147 } | 2142 emitIASRegOpTyGPR<false, true>(Func, SrcTy, Dest, Src, Emitter); |
2148 | |
2149 void InstX8632Movzx::dump(const Cfg *Func) const { | |
2150 Ostream &Str = Func->getContext()->getStrDump(); | |
2151 Str << "movzx." << getDest()->getType() << "." << getSrc(0)->getType(); | |
2152 Str << " "; | |
2153 dumpDest(Func); | |
2154 Str << ", "; | |
2155 dumpSources(Func); | |
2156 } | 2143 } |
2157 | 2144 |
2158 void InstX8632Nop::emit(const Cfg *Func) const { | 2145 void InstX8632Nop::emit(const Cfg *Func) const { |
2159 Ostream &Str = Func->getContext()->getStrEmit(); | 2146 Ostream &Str = Func->getContext()->getStrEmit(); |
2160 // TODO: Emit the right code for each variant. | 2147 // TODO: Emit the right code for each variant. |
2161 Str << "\tnop\t# variant = " << Variant << "\n"; | 2148 Str << "\tnop\t# variant = " << Variant << "\n"; |
2162 } | 2149 } |
2163 | 2150 |
2164 void InstX8632Nop::emitIAS(const Cfg *Func) const { | 2151 void InstX8632Nop::emitIAS(const Cfg *Func) const { |
2165 x86::AssemblerX86 *Asm = Func->getAssembler<x86::AssemblerX86>(); | 2152 x86::AssemblerX86 *Asm = Func->getAssembler<x86::AssemblerX86>(); |
(...skipping 642 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2808 } | 2795 } |
2809 Str << "("; | 2796 Str << "("; |
2810 if (Func) | 2797 if (Func) |
2811 Var->dump(Func); | 2798 Var->dump(Func); |
2812 else | 2799 else |
2813 Var->dump(Str); | 2800 Var->dump(Str); |
2814 Str << ")"; | 2801 Str << ")"; |
2815 } | 2802 } |
2816 | 2803 |
2817 } // end of namespace Ice | 2804 } // end of namespace Ice |
OLD | NEW |