| 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 |