Merge pull request #7414 from Sintendo/shortmovs
x64Emitter: emit shorter MOVs for 64-bit immediates
This commit is contained in:
commit
32ef8706e5
|
@ -1469,11 +1469,21 @@ void OpArg::WriteNormalOp(XEmitter* emit, bool toRM, NormalOp op, const OpArg& o
|
||||||
// mov reg64, imm64
|
// mov reg64, imm64
|
||||||
else if (op == NormalOp::MOV)
|
else if (op == NormalOp::MOV)
|
||||||
{
|
{
|
||||||
emit->Write8(0xB8 + (offsetOrBaseReg & 7));
|
// movabs reg64, imm64 (10 bytes)
|
||||||
emit->Write64((u64)operand.offset);
|
if (static_cast<s64>(operand.offset) != static_cast<s32>(operand.offset))
|
||||||
return;
|
{
|
||||||
|
emit->Write8(0xB8 + (offsetOrBaseReg & 7));
|
||||||
|
emit->Write64(operand.offset);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// mov reg64, simm32 (7 bytes)
|
||||||
|
emit->Write8(op_def.imm32);
|
||||||
|
immToWrite = 32;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ASSERT_MSG(DYNA_REC, 0, "WriteNormalOp - Only MOV can take 64-bit imm");
|
||||||
}
|
}
|
||||||
ASSERT_MSG(DYNA_REC, 0, "WriteNormalOp - Only MOV can take 64-bit imm");
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -1581,6 +1591,12 @@ void XEmitter::XOR(int bits, const OpArg& a1, const OpArg& a2)
|
||||||
}
|
}
|
||||||
void XEmitter::MOV(int bits, const OpArg& a1, const OpArg& a2)
|
void XEmitter::MOV(int bits, const OpArg& a1, const OpArg& a2)
|
||||||
{
|
{
|
||||||
|
if (bits == 64 && a1.IsSimpleReg() && a2.scale == SCALE_IMM64 &&
|
||||||
|
a2.offset == static_cast<u32>(a2.offset))
|
||||||
|
{
|
||||||
|
WriteNormalOp(32, NormalOp::MOV, a1, a2.AsImm32());
|
||||||
|
return;
|
||||||
|
}
|
||||||
if (a1.IsSimpleReg() && a2.IsSimpleReg() && a1.GetSimpleReg() == a2.GetSimpleReg())
|
if (a1.IsSimpleReg() && a2.IsSimpleReg() && a1.GetSimpleReg() == a2.GetSimpleReg())
|
||||||
ERROR_LOG(DYNA_REC, "Redundant MOV @ %p - bug in JIT?", code);
|
ERROR_LOG(DYNA_REC, "Redundant MOV @ %p - bug in JIT?", code);
|
||||||
WriteNormalOp(bits, NormalOp::MOV, a1, a2);
|
WriteNormalOp(bits, NormalOp::MOV, a1, a2);
|
||||||
|
|
|
@ -35,7 +35,10 @@ const std::vector<NamedReg> reg8names{
|
||||||
};
|
};
|
||||||
|
|
||||||
const std::vector<NamedReg> reg8hnames{
|
const std::vector<NamedReg> reg8hnames{
|
||||||
{AH, "ah"}, {BH, "bh"}, {CH, "ch"}, {DH, "dh"},
|
{AH, "ah"},
|
||||||
|
{BH, "bh"},
|
||||||
|
{CH, "ch"},
|
||||||
|
{DH, "dh"},
|
||||||
};
|
};
|
||||||
|
|
||||||
const std::vector<NamedReg> reg16names{
|
const std::vector<NamedReg> reg16names{
|
||||||
|
@ -306,10 +309,12 @@ TEST_F(x64EmitterTest, CMOVcc_Register)
|
||||||
emitter->CMOVcc(32, RAX, R(R12), cc.cc);
|
emitter->CMOVcc(32, RAX, R(R12), cc.cc);
|
||||||
emitter->CMOVcc(16, RAX, R(R12), cc.cc);
|
emitter->CMOVcc(16, RAX, R(R12), cc.cc);
|
||||||
|
|
||||||
ExpectDisassembly("cmov" + cc.name + " rax, r12 "
|
ExpectDisassembly("cmov" + cc.name +
|
||||||
"cmov" +
|
" rax, r12 "
|
||||||
cc.name + " eax, r12d "
|
"cmov" +
|
||||||
"cmov" +
|
cc.name +
|
||||||
|
" eax, r12d "
|
||||||
|
"cmov" +
|
||||||
cc.name + " ax, r12w");
|
cc.name + " ax, r12w");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -379,10 +384,12 @@ TEST_F(x64EmitterTest, MOVNT_DQ_PS_PD)
|
||||||
emitter->MOVNTDQ(MatR(RAX), r.reg);
|
emitter->MOVNTDQ(MatR(RAX), r.reg);
|
||||||
emitter->MOVNTPS(MatR(RAX), r.reg);
|
emitter->MOVNTPS(MatR(RAX), r.reg);
|
||||||
emitter->MOVNTPD(MatR(RAX), r.reg);
|
emitter->MOVNTPD(MatR(RAX), r.reg);
|
||||||
ExpectDisassembly("movntdq dqword ptr ds:[rax], " + r.name + " "
|
ExpectDisassembly("movntdq dqword ptr ds:[rax], " + r.name +
|
||||||
"movntps dqword ptr ds:[rax], " +
|
" "
|
||||||
r.name + " "
|
"movntps dqword ptr ds:[rax], " +
|
||||||
"movntpd dqword ptr ds:[rax], " +
|
r.name +
|
||||||
|
" "
|
||||||
|
"movntpd dqword ptr ds:[rax], " +
|
||||||
r.name);
|
r.name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -547,6 +554,24 @@ TWO_OP_ARITH_TEST(OR)
|
||||||
TWO_OP_ARITH_TEST(XOR)
|
TWO_OP_ARITH_TEST(XOR)
|
||||||
TWO_OP_ARITH_TEST(MOV)
|
TWO_OP_ARITH_TEST(MOV)
|
||||||
|
|
||||||
|
TEST_F(x64EmitterTest, MOV_Imm64)
|
||||||
|
{
|
||||||
|
for (size_t i = 0; i < reg64names.size(); i++)
|
||||||
|
{
|
||||||
|
emitter->MOV(64, R(reg64names[i].reg), Imm64(0xDEADBEEFDEADBEEF));
|
||||||
|
EXPECT_EQ(emitter->GetCodePtr(), code_buffer + 10);
|
||||||
|
ExpectDisassembly("mov " + reg64names[i].name + ", 0xdeadbeefdeadbeef");
|
||||||
|
|
||||||
|
emitter->MOV(64, R(reg64names[i].reg), Imm64(0xFFFFFFFFDEADBEEF));
|
||||||
|
EXPECT_EQ(emitter->GetCodePtr(), code_buffer + 7);
|
||||||
|
ExpectDisassembly("mov " + reg64names[i].name + ", 0xffffffffdeadbeef");
|
||||||
|
|
||||||
|
emitter->MOV(64, R(reg64names[i].reg), Imm64(0xDEADBEEF));
|
||||||
|
EXPECT_EQ(emitter->GetCodePtr(), code_buffer + 5 + (i > 7));
|
||||||
|
ExpectDisassembly("mov " + reg32names[i].name + ", 0xdeadbeef");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// TODO: Disassembler inverts operands here.
|
// TODO: Disassembler inverts operands here.
|
||||||
// TWO_OP_ARITH_TEST(XCHG)
|
// TWO_OP_ARITH_TEST(XCHG)
|
||||||
// TWO_OP_ARITH_TEST(TEST)
|
// TWO_OP_ARITH_TEST(TEST)
|
||||||
|
@ -558,7 +583,8 @@ TEST_F(x64EmitterTest, BSWAP)
|
||||||
int bits;
|
int bits;
|
||||||
std::vector<NamedReg> regs;
|
std::vector<NamedReg> regs;
|
||||||
} regsets[] = {
|
} regsets[] = {
|
||||||
{32, reg32names}, {64, reg64names},
|
{32, reg32names},
|
||||||
|
{64, reg64names},
|
||||||
};
|
};
|
||||||
for (const auto& regset : regsets)
|
for (const auto& regset : regsets)
|
||||||
for (const auto& r : regset.regs)
|
for (const auto& r : regset.regs)
|
||||||
|
@ -871,7 +897,8 @@ TWO_OP_SSE_TEST(PMOVZXDQ, "qword")
|
||||||
std::string out_name; \
|
std::string out_name; \
|
||||||
std::string size; \
|
std::string size; \
|
||||||
} regsets[] = { \
|
} regsets[] = { \
|
||||||
{32, reg32names, "eax", "dword"}, {64, reg64names, "rax", "qword"}, \
|
{32, reg32names, "eax", "dword"}, \
|
||||||
|
{64, reg64names, "rax", "qword"}, \
|
||||||
}; \
|
}; \
|
||||||
for (const auto& regset : regsets) \
|
for (const auto& regset : regsets) \
|
||||||
for (const auto& r : regset.regs) \
|
for (const auto& r : regset.regs) \
|
||||||
|
@ -903,7 +930,8 @@ VEX_RMR_TEST(BZHI)
|
||||||
std::string out_name; \
|
std::string out_name; \
|
||||||
std::string size; \
|
std::string size; \
|
||||||
} regsets[] = { \
|
} regsets[] = { \
|
||||||
{32, reg32names, "eax", "dword"}, {64, reg64names, "rax", "qword"}, \
|
{32, reg32names, "eax", "dword"}, \
|
||||||
|
{64, reg64names, "rax", "qword"}, \
|
||||||
}; \
|
}; \
|
||||||
for (const auto& regset : regsets) \
|
for (const auto& regset : regsets) \
|
||||||
for (const auto& r : regset.regs) \
|
for (const auto& r : regset.regs) \
|
||||||
|
@ -934,7 +962,8 @@ VEX_RRM_TEST(ANDN)
|
||||||
std::string out_name; \
|
std::string out_name; \
|
||||||
std::string size; \
|
std::string size; \
|
||||||
} regsets[] = { \
|
} regsets[] = { \
|
||||||
{32, reg32names, "eax", "dword"}, {64, reg64names, "rax", "qword"}, \
|
{32, reg32names, "eax", "dword"}, \
|
||||||
|
{64, reg64names, "rax", "qword"}, \
|
||||||
}; \
|
}; \
|
||||||
for (const auto& regset : regsets) \
|
for (const auto& regset : regsets) \
|
||||||
for (const auto& r : regset.regs) \
|
for (const auto& r : regset.regs) \
|
||||||
|
@ -963,7 +992,8 @@ VEX_RM_TEST(BLSI)
|
||||||
std::string out_name; \
|
std::string out_name; \
|
||||||
std::string size; \
|
std::string size; \
|
||||||
} regsets[] = { \
|
} regsets[] = { \
|
||||||
{32, reg32names, "eax", "dword"}, {64, reg64names, "rax", "qword"}, \
|
{32, reg32names, "eax", "dword"}, \
|
||||||
|
{64, reg64names, "rax", "qword"}, \
|
||||||
}; \
|
}; \
|
||||||
for (const auto& regset : regsets) \
|
for (const auto& regset : regsets) \
|
||||||
for (const auto& r : regset.regs) \
|
for (const auto& r : regset.regs) \
|
||||||
|
|
Loading…
Reference in New Issue