Skip to content

Commit

Permalink
x64Emitter: Unit test memory addressing modes
Browse files Browse the repository at this point in the history
Test the behavior of OpArg::WriteRest by using MOV with the various
addressing modes (MatR, MRegSum, etc.) in the source operand.

Both the instruction and the instruction length are validated.
  • Loading branch information
Sintendo committed Jan 13, 2020
1 parent 1701363 commit d5cb858
Showing 1 changed file with 91 additions and 0 deletions.
91 changes: 91 additions & 0 deletions Source/UnitTests/Common/x64EmitterTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -576,6 +576,97 @@ TEST_F(x64EmitterTest, MOV64)
}
}

TEST_F(x64EmitterTest, MOV_AtReg)
{
for (const auto& src : reg64names)
{
std::string segment = src.reg == RSP || src.reg == RBP ? "ss" : "ds";

emitter->MOV(64, R(RAX), MatR(src.reg));
EXPECT_EQ(emitter->GetCodePtr(),
code_buffer + 3 + ((src.reg & 7) == RBP || (src.reg & 7) == RSP));
ExpectDisassembly("mov rax, qword ptr " + segment + ":[" + src.name + "]");
}
}

TEST_F(x64EmitterTest, MOV_RegSum)
{
for (const auto& src2 : reg64names)
{
for (const auto& src1 : reg64names)
{
if (src2.reg == RSP)
continue;
std::string segment = src1.reg == RSP || src1.reg == RBP ? "ss" : "ds";

emitter->MOV(64, R(RAX), MRegSum(src1.reg, src2.reg));
EXPECT_EQ(emitter->GetCodePtr(), code_buffer + 4 + ((src1.reg & 7) == RBP));
ExpectDisassembly("mov rax, qword ptr " + segment + ":[" + src1.name + "+" + src2.name + "]");
}
}
}

TEST_F(x64EmitterTest, MOV_Disp)
{
for (const auto& dest : reg64names)
{
for (const auto& src : reg64names)
{
std::string segment = src.reg == RSP || src.reg == RBP ? "ss" : "ds";

emitter->MOV(64, R(dest.reg), MDisp(src.reg, 42));
EXPECT_EQ(emitter->GetCodePtr(), code_buffer + 4 + ((src.reg & 7) == RSP));
ExpectDisassembly("mov " + dest.name + ", qword ptr " + segment + ":[" + src.name + "+42]");

emitter->MOV(64, R(dest.reg), MDisp(src.reg, 1000));
EXPECT_EQ(emitter->GetCodePtr(), code_buffer + 7 + ((src.reg & 7) == RSP));
ExpectDisassembly("mov " + dest.name + ", qword ptr " + segment + ":[" + src.name + "+1000]");
}
}
}

TEST_F(x64EmitterTest, MOV_Scaled)
{
for (const auto& src : reg64names)
{
if (src.reg == RSP)
continue;

emitter->MOV(64, R(RAX), MScaled(src.reg, 2, 42));
EXPECT_EQ(emitter->GetCodePtr(), code_buffer + 8);
ExpectDisassembly("mov rax, qword ptr ds:[" + src.name + "*2+42]");
}
}

TEST_F(x64EmitterTest, MOV_Complex)
{
for (const auto& src1 : reg64names)
{
std::string segment = src1.reg == RSP || src1.reg == RBP ? "ss" : "ds";

for (const auto& src2 : reg64names)
{
if (src2.reg == RSP)
continue;

emitter->MOV(64, R(RAX), MComplex(src1.reg, src2.reg, 4, 0));
EXPECT_EQ(emitter->GetCodePtr(), code_buffer + 4 + ((src1.reg & 7) == RBP));
ExpectDisassembly("mov rax, qword ptr " + segment + ":[" + src1.name + "+" + src2.name +
"*4]");

emitter->MOV(64, R(RAX), MComplex(src1.reg, src2.reg, 4, 42));
EXPECT_EQ(emitter->GetCodePtr(), code_buffer + 5);
ExpectDisassembly("mov rax, qword ptr " + segment + ":[" + src1.name + "+" + src2.name +
"*4+42]");

emitter->MOV(64, R(RAX), MComplex(src1.reg, src2.reg, 4, 1000));
EXPECT_EQ(emitter->GetCodePtr(), code_buffer + 8);
ExpectDisassembly("mov rax, qword ptr " + segment + ":[" + src1.name + "+" + src2.name +
"*4+1000]");
}
}
}

// TODO: Disassembler inverts operands here.
// TWO_OP_ARITH_TEST(XCHG)
// TWO_OP_ARITH_TEST(TEST)
Expand Down

0 comments on commit d5cb858

Please sign in to comment.