Index: src/IceInstX8632.cpp |
diff --git a/src/IceInstX8632.cpp b/src/IceInstX8632.cpp |
index 6b1e40cc4e88164dc37734a1a03357bd66867603..e41fe8227684ca626a5d87d74f596864e81c18d1 100644 |
--- a/src/IceInstX8632.cpp |
+++ b/src/IceInstX8632.cpp |
@@ -287,16 +287,6 @@ InstX8632StoreQ::InstX8632StoreQ(Cfg *Func, Variable *Value, |
addSource(Mem); |
} |
-InstX8632Movsx::InstX8632Movsx(Cfg *Func, Variable *Dest, Operand *Source) |
- : InstX8632(Func, InstX8632::Movsx, 1, Dest) { |
- addSource(Source); |
-} |
- |
-InstX8632Movzx::InstX8632Movzx(Cfg *Func, Variable *Dest, Operand *Source) |
- : InstX8632(Func, InstX8632::Movzx, 1, Dest) { |
- addSource(Source); |
-} |
- |
InstX8632Nop::InstX8632Nop(Cfg *Func, InstX8632Nop::NopVariant Variant) |
: InstX8632(Func, InstX8632::Nop, 0, NULL), Variant(Variant) {} |
@@ -516,6 +506,7 @@ void emitIASOpTyGPR(const Cfg *Func, Type Ty, const Operand *Op, |
emitIASBytes(Func, Asm, StartPosition); |
} |
+template <bool VarCanBeByte, bool SrcCanBeByte> |
void emitIASRegOpTyGPR(const Cfg *Func, Type Ty, const Variable *Var, |
const Operand *Src, |
const x86::AssemblerX86::GPREmitterRegOp &Emitter) { |
@@ -524,11 +515,14 @@ void emitIASRegOpTyGPR(const Cfg *Func, Type Ty, const Variable *Var, |
assert(Var->hasReg()); |
// We cheat a little and use GPRRegister even for byte operations. |
RegX8632::GPRRegister VarReg = |
- RegX8632::getEncodedByteRegOrGPR(Ty, Var->getRegNum()); |
+ VarCanBeByte ? RegX8632::getEncodedByteRegOrGPR(Ty, Var->getRegNum()) |
+ : RegX8632::getEncodedGPR(Var->getRegNum()); |
if (const auto SrcVar = llvm::dyn_cast<Variable>(Src)) { |
if (SrcVar->hasReg()) { |
RegX8632::GPRRegister SrcReg = |
- RegX8632::getEncodedByteRegOrGPR(Ty, SrcVar->getRegNum()); |
+ SrcCanBeByte |
+ ? RegX8632::getEncodedByteRegOrGPR(Ty, SrcVar->getRegNum()) |
+ : RegX8632::getEncodedGPR(SrcVar->getRegNum()); |
(Asm->*(Emitter.GPRGPR))(Ty, VarReg, SrcReg); |
} else { |
x86::Address SrcStackAddr = static_cast<TargetX8632 *>(Func->getTarget()) |
@@ -799,6 +793,8 @@ template <> const char *InstX8632Bsf::Opcode = "bsf"; |
template <> const char *InstX8632Bsr::Opcode = "bsr"; |
template <> const char *InstX8632Lea::Opcode = "lea"; |
template <> const char *InstX8632Movd::Opcode = "movd"; |
+template <> const char *InstX8632Movsx::Opcode = "movsx"; |
+template <> const char *InstX8632Movzx::Opcode = "movzx"; |
template <> const char *InstX8632Sqrtss::Opcode = "sqrtss"; |
template <> const char *InstX8632Cbwdq::Opcode = "cbw/cwd/cdq"; |
// Mov-like ops |
@@ -869,6 +865,12 @@ const x86::AssemblerX86::GPREmitterRegOp InstX8632Bsr::Emitter = { |
template <> |
const x86::AssemblerX86::GPREmitterRegOp InstX8632Lea::Emitter = { |
/* reg/reg and reg/imm are illegal */ NULL, &x86::AssemblerX86::lea, NULL}; |
+template <> |
+const x86::AssemblerX86::GPREmitterRegOp InstX8632Movsx::Emitter = { |
+ &x86::AssemblerX86::movsx, &x86::AssemblerX86::movsx, NULL}; |
+template <> |
+const x86::AssemblerX86::GPREmitterRegOp InstX8632Movzx::Emitter = { |
+ &x86::AssemblerX86::movzx, &x86::AssemblerX86::movzx, NULL}; |
// Unary XMM ops |
template <> |
@@ -2117,42 +2119,27 @@ template <> void InstX8632MovssRegs::emitIAS(const Cfg *Func) const { |
emitIASBytes(Func, Asm, StartPosition); |
} |
-void InstX8632Movsx::emit(const Cfg *Func) const { |
- Ostream &Str = Func->getContext()->getStrEmit(); |
+template <> void InstX8632Movsx::emitIAS(const Cfg *Func) const { |
assert(getSrcSize() == 1); |
- Str << "\tmovsx\t"; |
- getDest()->emit(Func); |
- Str << ", "; |
- getSrc(0)->emit(Func); |
- Str << "\n"; |
-} |
- |
-void InstX8632Movsx::dump(const Cfg *Func) const { |
- Ostream &Str = Func->getContext()->getStrDump(); |
- Str << "movsx." << getDest()->getType() << "." << getSrc(0)->getType(); |
- Str << " "; |
- dumpDest(Func); |
- Str << ", "; |
- dumpSources(Func); |
+ const Variable *Dest = getDest(); |
+ const Operand *Src = getSrc(0); |
+ // Dest must be a > 8-bit register, but Src can be 8-bit. In practice |
+ // we just use the full register for Dest to avoid having an |
+ // OperandSizeOverride prefix. It also allows us to only dispatch on SrcTy. |
+ Type SrcTy = Src->getType(); |
+ assert(typeWidthInBytes(Dest->getType()) > 1); |
+ assert(typeWidthInBytes(Dest->getType()) > typeWidthInBytes(SrcTy)); |
+ emitIASRegOpTyGPR<false, true>(Func, SrcTy, Dest, Src, Emitter); |
} |
-void InstX8632Movzx::emit(const Cfg *Func) const { |
- Ostream &Str = Func->getContext()->getStrEmit(); |
+template <> void InstX8632Movzx::emitIAS(const Cfg *Func) const { |
assert(getSrcSize() == 1); |
- Str << "\tmovzx\t"; |
- getDest()->emit(Func); |
- Str << ", "; |
- getSrc(0)->emit(Func); |
- Str << "\n"; |
-} |
- |
-void InstX8632Movzx::dump(const Cfg *Func) const { |
- Ostream &Str = Func->getContext()->getStrDump(); |
- Str << "movzx." << getDest()->getType() << "." << getSrc(0)->getType(); |
- Str << " "; |
- dumpDest(Func); |
- Str << ", "; |
- dumpSources(Func); |
+ const Variable *Dest = getDest(); |
+ const Operand *Src = getSrc(0); |
+ Type SrcTy = Src->getType(); |
+ assert(typeWidthInBytes(Dest->getType()) > 1); |
+ assert(typeWidthInBytes(Dest->getType()) > typeWidthInBytes(SrcTy)); |
+ emitIASRegOpTyGPR<false, true>(Func, SrcTy, Dest, Src, Emitter); |
} |
void InstX8632Nop::emit(const Cfg *Func) const { |