From c84f34bd500bbf201b68ae8520f3b3039d2f3f50 Mon Sep 17 00:00:00 2001 From: Sintendo Date: Wed, 29 May 2019 00:47:12 +0200 Subject: [PATCH 1/2] x64Emitter: Short MOVs for 32bit immediates Prior to this commit, the emitter would emit a 7-byte instruction when loading a 32-bit immediate to a 64-bit register. 0: 48 c7 c0 ff ff ff 7f mov rax,0x7fffffff With this change, it will check if it can instead emit a load to a 32-bit register, which takes only 5 or 6 bytes. 0: b8 ff ff ff 7f mov eax,0x7fffffff --- Source/Core/Common/x64Emitter.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Source/Core/Common/x64Emitter.cpp b/Source/Core/Common/x64Emitter.cpp index 63c094ad6f..947e6e5614 100644 --- a/Source/Core/Common/x64Emitter.cpp +++ b/Source/Core/Common/x64Emitter.cpp @@ -1591,8 +1591,9 @@ void XEmitter::XOR(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(a2.offset)) + if (bits == 64 && a1.IsSimpleReg() && + ((a2.scale == SCALE_IMM64 && a2.offset == static_cast(a2.offset)) || + (a2.scale == SCALE_IMM32 && static_cast(a2.offset) >= 0))) { WriteNormalOp(32, NormalOp::MOV, a1, a2.AsImm32()); return; From 9fe315035809bdd4272897fa3565ae3c3e94382c Mon Sep 17 00:00:00 2001 From: Sintendo Date: Wed, 29 May 2019 00:49:15 +0200 Subject: [PATCH 2/2] x64EmitterTest: Test 64-bit MOV with 32-bit immediate --- Source/UnitTests/Common/x64EmitterTest.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/Source/UnitTests/Common/x64EmitterTest.cpp b/Source/UnitTests/Common/x64EmitterTest.cpp index 020e53afa2..dedac29df3 100644 --- a/Source/UnitTests/Common/x64EmitterTest.cpp +++ b/Source/UnitTests/Common/x64EmitterTest.cpp @@ -554,7 +554,7 @@ TWO_OP_ARITH_TEST(OR) TWO_OP_ARITH_TEST(XOR) TWO_OP_ARITH_TEST(MOV) -TEST_F(x64EmitterTest, MOV_Imm64) +TEST_F(x64EmitterTest, MOV64) { for (size_t i = 0; i < reg64names.size(); i++) { @@ -569,6 +569,10 @@ TEST_F(x64EmitterTest, MOV_Imm64) emitter->MOV(64, R(reg64names[i].reg), Imm64(0xDEADBEEF)); EXPECT_EQ(emitter->GetCodePtr(), code_buffer + 5 + (i > 7)); ExpectDisassembly("mov " + reg32names[i].name + ", 0xdeadbeef"); + + emitter->MOV(64, R(reg64names[i].reg), Imm32(0x7FFFFFFF)); + EXPECT_EQ(emitter->GetCodePtr(), code_buffer + 5 + (i > 7)); + ExpectDisassembly("mov " + reg32names[i].name + ", 0x7fffffff"); } }