Test assembler driver utilities.
Rationale:
Quis custodiet ipsos custodes?
Therefore, it is good to make sure that the drivers
used to test the assembler are doing what is expected.
This also prepares some upcoming improvements wrt.
addressing modes and different register sizes.
Bug: 18380245
Bug: 18380559
Bug: 18380245
Test: assembler_x86[_64]_test
Change-Id: Iadc269c14cb9e15941ec66c362d59d42e9017001
diff --git a/compiler/utils/assembler_test.h b/compiler/utils/assembler_test.h
index ef53d72..5ab558b 100644
--- a/compiler/utils/assembler_test.h
+++ b/compiler/utils/assembler_test.h
@@ -159,7 +159,9 @@
for (auto reg2 : reg2_registers) {
for (int64_t imm : imms) {
ImmType new_imm = CreateImmediate(imm);
- (assembler_.get()->*f)(*reg1, *reg2, new_imm * multiplier + bias);
+ if (f != nullptr) {
+ (assembler_.get()->*f)(*reg1, *reg2, new_imm * multiplier + bias);
+ }
std::string base = fmt;
std::string reg1_string = (this->*GetName1)(*reg1);
@@ -213,7 +215,9 @@
for (auto reg3 : reg3_registers) {
for (int64_t imm : imms) {
ImmType new_imm = CreateImmediate(imm);
- (assembler_.get()->*f)(*reg1, *reg2, *reg3, new_imm + bias);
+ if (f != nullptr) {
+ (assembler_.get()->*f)(*reg1, *reg2, *reg3, new_imm + bias);
+ }
std::string base = fmt;
std::string reg1_string = (this->*GetName1)(*reg1);
@@ -272,7 +276,9 @@
for (auto reg2 : reg2_registers) {
for (int64_t imm : imms) {
ImmType new_imm = CreateImmediate(imm);
- (assembler_.get()->*f)(new_imm, *reg1, *reg2);
+ if (f != nullptr) {
+ (assembler_.get()->*f)(new_imm, *reg1, *reg2);
+ }
std::string base = fmt;
std::string reg1_string = (this->*GetName1)(*reg1);
@@ -320,7 +326,9 @@
for (auto reg : registers) {
for (int64_t imm : imms) {
ImmType new_imm = CreateImmediate(imm);
- (assembler_.get()->*f)(*reg, new_imm + bias);
+ if (f != nullptr) {
+ (assembler_.get()->*f)(*reg, new_imm + bias);
+ }
std::string base = fmt;
std::string reg_string = (this->*GetName)(*reg);
@@ -522,7 +530,9 @@
for (int64_t imm : imms) {
Imm new_imm = CreateImmediate(imm);
- (assembler_.get()->*f)(new_imm);
+ if (f != nullptr) {
+ (assembler_.get()->*f)(new_imm);
+ }
std::string base = fmt;
size_t imm_index = base.find(IMM_TOKEN);
@@ -835,7 +845,9 @@
const std::string& fmt) {
std::string str;
for (auto reg : registers) {
- (assembler_.get()->*f)(*reg);
+ if (f != nullptr) {
+ (assembler_.get()->*f)(*reg);
+ }
std::string base = fmt;
std::string reg_string = (this->*GetName)(*reg);
@@ -866,7 +878,9 @@
std::string str;
for (auto reg1 : reg1_registers) {
for (auto reg2 : reg2_registers) {
- (assembler_.get()->*f)(*reg1, *reg2);
+ if (f != nullptr) {
+ (assembler_.get()->*f)(*reg1, *reg2);
+ }
std::string base = fmt;
std::string reg1_string = (this->*GetName1)(*reg1);
@@ -905,7 +919,9 @@
for (auto reg1 : reg1_registers) {
for (auto reg2 : reg2_registers) {
if (reg1 == reg2) continue;
- (assembler_.get()->*f)(*reg1, *reg2);
+ if (f != nullptr) {
+ (assembler_.get()->*f)(*reg1, *reg2);
+ }
std::string base = fmt;
std::string reg1_string = (this->*GetName1)(*reg1);
@@ -944,7 +960,9 @@
for (auto reg1 : reg1_registers) {
for (auto reg2 : reg2_registers) {
for (auto reg3 : reg3_registers) {
- (assembler_.get()->*f)(*reg1, *reg2, *reg3);
+ if (f != nullptr) {
+ (assembler_.get()->*f)(*reg1, *reg2, *reg3);
+ }
std::string base = fmt;
std::string reg1_string = (this->*GetName1)(*reg1);
@@ -993,7 +1011,9 @@
for (auto reg2 : reg2_registers) {
for (int64_t imm : imms) {
Imm new_imm = CreateImmediate(imm);
- (assembler_.get()->*f)(*reg1, *reg2, new_imm);
+ if (f != nullptr) {
+ (assembler_.get()->*f)(*reg1, *reg2, new_imm);
+ }
std::string base = fmt;
std::string reg1_string = (this->*GetName1)(*reg1);
@@ -1094,7 +1114,9 @@
for (auto reg : registers) {
for (int64_t imm : imms) {
Imm new_imm = CreateImmediate(imm);
- (assembler_.get()->*f)(*reg, new_imm);
+ if (f != nullptr) {
+ (assembler_.get()->*f)(*reg, new_imm);
+ }
std::string base = fmt;
std::string reg_string = GetRegName<kRegView>(*reg);
diff --git a/compiler/utils/x86/assembler_x86_test.cc b/compiler/utils/x86/assembler_x86_test.cc
index d2122db..48e4117 100644
--- a/compiler/utils/x86/assembler_x86_test.cc
+++ b/compiler/utils/x86/assembler_x86_test.cc
@@ -33,6 +33,10 @@
ASSERT_EQ(static_cast<size_t>(5), buffer.Size());
}
+//
+// Test fixture.
+//
+
class AssemblerX86Test : public AssemblerTest<x86::X86Assembler, x86::Register,
x86::XmmRegister, x86::Immediate> {
public:
@@ -105,6 +109,56 @@
std::vector<x86::XmmRegister*> fp_registers_;
};
+//
+// Test repeat drivers used in the tests.
+//
+
+TEST_F(AssemblerX86Test, RepeatRR) {
+ EXPECT_EQ("%eax %eax\n%eax %ebx\n%eax %ecx\n%eax %edx\n%eax %ebp\n%eax %esp\n%eax %esi\n"
+ "%eax %edi\n%ebx %eax\n%ebx %ebx\n%ebx %ecx\n%ebx %edx\n%ebx %ebp\n%ebx %esp\n"
+ "%ebx %esi\n%ebx %edi\n%ecx %eax\n%ecx %ebx\n%ecx %ecx\n%ecx %edx\n%ecx %ebp\n"
+ "%ecx %esp\n%ecx %esi\n%ecx %edi\n%edx %eax\n%edx %ebx\n%edx %ecx\n%edx %edx\n"
+ "%edx %ebp\n%edx %esp\n%edx %esi\n%edx %edi\n%ebp %eax\n%ebp %ebx\n%ebp %ecx\n"
+ "%ebp %edx\n%ebp %ebp\n%ebp %esp\n%ebp %esi\n%ebp %edi\n%esp %eax\n%esp %ebx\n"
+ "%esp %ecx\n%esp %edx\n%esp %ebp\n%esp %esp\n%esp %esi\n%esp %edi\n%esi %eax\n"
+ "%esi %ebx\n%esi %ecx\n%esi %edx\n%esi %ebp\n%esi %esp\n%esi %esi\n%esi %edi\n"
+ "%edi %eax\n%edi %ebx\n%edi %ecx\n%edi %edx\n%edi %ebp\n%edi %esp\n%edi %esi\n"
+ "%edi %edi\n",
+ RepeatRR(/*f*/ nullptr, "%{reg1} %{reg2}"));
+}
+
+TEST_F(AssemblerX86Test, RepeatRI) {
+ EXPECT_EQ("%eax %0\n%eax %-1\n%eax %18\n%ebx %0\n%ebx %-1\n%ebx %18\n%ecx %0\n%ecx %-1\n"
+ "%ecx %18\n%edx %0\n%edx %-1\n%edx %18\n%ebp %0\n%ebp %-1\n%ebp %18\n%esp %0\n"
+ "%esp %-1\n%esp %18\n%esi %0\n%esi %-1\n%esi %18\n%edi %0\n%edi %-1\n%edi %18\n",
+ RepeatRI(/*f*/ nullptr, /*imm_bytes*/ 1U, "%{reg} %{imm}"));
+}
+
+TEST_F(AssemblerX86Test, RepeatFF) {
+ EXPECT_EQ("%XMM0 %XMM0\n%XMM0 %XMM1\n%XMM0 %XMM2\n%XMM0 %XMM3\n%XMM0 %XMM4\n%XMM0 %XMM5\n"
+ "%XMM0 %XMM6\n%XMM0 %XMM7\n%XMM1 %XMM0\n%XMM1 %XMM1\n%XMM1 %XMM2\n%XMM1 %XMM3\n"
+ "%XMM1 %XMM4\n%XMM1 %XMM5\n%XMM1 %XMM6\n%XMM1 %XMM7\n%XMM2 %XMM0\n%XMM2 %XMM1\n"
+ "%XMM2 %XMM2\n%XMM2 %XMM3\n%XMM2 %XMM4\n%XMM2 %XMM5\n%XMM2 %XMM6\n%XMM2 %XMM7\n"
+ "%XMM3 %XMM0\n%XMM3 %XMM1\n%XMM3 %XMM2\n%XMM3 %XMM3\n%XMM3 %XMM4\n%XMM3 %XMM5\n"
+ "%XMM3 %XMM6\n%XMM3 %XMM7\n%XMM4 %XMM0\n%XMM4 %XMM1\n%XMM4 %XMM2\n%XMM4 %XMM3\n"
+ "%XMM4 %XMM4\n%XMM4 %XMM5\n%XMM4 %XMM6\n%XMM4 %XMM7\n%XMM5 %XMM0\n%XMM5 %XMM1\n"
+ "%XMM5 %XMM2\n%XMM5 %XMM3\n%XMM5 %XMM4\n%XMM5 %XMM5\n%XMM5 %XMM6\n%XMM5 %XMM7\n"
+ "%XMM6 %XMM0\n%XMM6 %XMM1\n%XMM6 %XMM2\n%XMM6 %XMM3\n%XMM6 %XMM4\n%XMM6 %XMM5\n"
+ "%XMM6 %XMM6\n%XMM6 %XMM7\n%XMM7 %XMM0\n%XMM7 %XMM1\n%XMM7 %XMM2\n%XMM7 %XMM3\n"
+ "%XMM7 %XMM4\n%XMM7 %XMM5\n%XMM7 %XMM6\n%XMM7 %XMM7\n",
+ RepeatFF(/*f*/ nullptr, "%{reg1} %{reg2}"));
+}
+
+TEST_F(AssemblerX86Test, RepeatFFI) {
+ EXPECT_NE(RepeatFFI(/*f*/ nullptr, /*imm_bytes*/ 1U, "%{reg1} %{reg2} %{imm}")
+ .find("%XMM0 %XMM0 %0\n%XMM0 %XMM0 %-1\n%XMM0 %XMM0 %18\n"
+ "%XMM0 %XMM1 %0\n%XMM0 %XMM1 %-1\n%XMM0 %XMM1 %18\n"),
+ std::string::npos);
+}
+
+//
+// Actual x86 instruction assembler tests.
+//
TEST_F(AssemblerX86Test, Movl) {
GetAssembler()->movl(x86::EAX, x86::EBX);
@@ -838,10 +892,6 @@
DriverStr("psrldq $0x10, %xmm0\n", "psrldqi");
}
-/////////////////
-// Near labels //
-/////////////////
-
TEST_F(AssemblerX86Test, Jecxz) {
x86::NearLabel target;
GetAssembler()->jecxz(&target);
diff --git a/compiler/utils/x86_64/assembler_x86_64_test.cc b/compiler/utils/x86_64/assembler_x86_64_test.cc
index 85afee0..29de925 100644
--- a/compiler/utils/x86_64/assembler_x86_64_test.cc
+++ b/compiler/utils/x86_64/assembler_x86_64_test.cc
@@ -126,6 +126,10 @@
}
};
+//
+// Test fixture.
+//
+
class AssemblerX86_64Test : public AssemblerTest<x86_64::X86_64Assembler, x86_64::CpuRegister,
x86_64::XmmRegister, x86_64::Immediate> {
public:
@@ -273,12 +277,130 @@
std::vector<x86_64::XmmRegister*> fp_registers_;
};
+//
+// Test repeat drivers used in the tests.
+//
+
+TEST_F(AssemblerX86_64Test, RepeatI4) {
+ EXPECT_EQ("%0\n%-1\n%18\n%4660\n%-4660\n%305419896\n%-305419896\n",
+ RepeatI(/*f*/ nullptr, /*imm_bytes*/ 4U, "%{imm}"));
+}
+
+TEST_F(AssemblerX86_64Test, RepeatI8) {
+ EXPECT_EQ("%0\n%-1\n%18\n%4660\n%-4660\n%305419896\n%-305419896\n"
+ "%20015998343868\n%-20015998343868\n%1311768467463790320\n"
+ "%-1311768467463790320\n",
+ RepeatI(/*f*/ nullptr, /*imm_bytes*/ 8U, "%{imm}"));
+}
+
+TEST_F(AssemblerX86_64Test, Repeatr) {
+ EXPECT_EQ("%eax\n%ebx\n%ecx\n%edx\n%ebp\n%esp\n%esi\n%edi\n"
+ "%r8d\n%r9d\n%r10d\n%r11d\n%r12d\n%r13d\n%r14d\n%r15d\n",
+ Repeatr(/*f*/ nullptr, "%{reg}"));
+}
+
+TEST_F(AssemblerX86_64Test, Repeatri) {
+ EXPECT_NE(Repeatri(/*f*/ nullptr, /*imm_bytes*/ 1U, "%{reg} %{imm}").
+ find("%eax %0\n%eax %-1\n%eax %18\n%ebx %0\n%ebx %-1\n%ebx %18\n"
+ "%ecx %0\n%ecx %-1\n%ecx %18\n%edx %0\n%edx %-1\n%edx %18\n"),
+ std::string::npos);
+}
+
+TEST_F(AssemblerX86_64Test, Repeatrr) {
+ EXPECT_NE(Repeatrr(/*f*/ nullptr, "%{reg1} %{reg2}")
+ .find("%eax %eax\n%eax %ebx\n%eax %ecx\n%eax %edx\n"
+ "%eax %ebp\n%eax %esp\n%eax %esi\n%eax %edi\n"),
+ std::string::npos);
+}
+
+TEST_F(AssemblerX86_64Test, Repeatrb) {
+ EXPECT_NE(Repeatrb(/*f*/ nullptr, "%{reg1} %{reg2}").
+ find("%eax %al\n%eax %bl\n%eax %cl\n%eax %dl\n%eax %bpl\n"
+ "%eax %spl\n%eax %sil\n%eax %dil\n%eax %r8b\n%eax %r9b\n"),
+ std::string::npos);
+}
+
+TEST_F(AssemblerX86_64Test, RepeatrF) {
+ EXPECT_NE(RepeatrF(/*f*/ nullptr, "%{reg1} %{reg2}")
+ .find("%eax %xmm0\n%eax %xmm1\n%eax %xmm2\n%eax %xmm3\n"
+ "%eax %xmm4\n%eax %xmm5\n%eax %xmm6\n%eax %xmm7\n"
+ "%eax %xmm8\n%eax %xmm9\n%eax %xmm10\n%eax %xmm11\n"
+ "%eax %xmm12\n%eax %xmm13\n%eax %xmm14\n%eax %xmm15\n"
+ "%ebx %xmm0\n%ebx %xmm1\n%ebx %xmm2\n%ebx %xmm3\n%ebx %xmm4\n"),
+ std::string::npos);
+}
+
+TEST_F(AssemblerX86_64Test, RepeatR) {
+ EXPECT_EQ("%rax\n%rbx\n%rcx\n%rdx\n%rbp\n%rsp\n%rsi\n%rdi\n"
+ "%r8\n%r9\n%r10\n%r11\n%r12\n%r13\n%r14\n%r15\n",
+ RepeatR(/*f*/ nullptr, "%{reg}"));
+}
+
+TEST_F(AssemblerX86_64Test, RepeatRI) {
+ EXPECT_EQ("%rax %0\n%rax %-1\n%rax %18\n%rbx %0\n%rbx %-1\n%rbx %18\n"
+ "%rcx %0\n%rcx %-1\n%rcx %18\n%rdx %0\n%rdx %-1\n%rdx %18\n"
+ "%rbp %0\n%rbp %-1\n%rbp %18\n%rsp %0\n%rsp %-1\n%rsp %18\n"
+ "%rsi %0\n%rsi %-1\n%rsi %18\n%rdi %0\n%rdi %-1\n%rdi %18\n"
+ "%r8 %0\n%r8 %-1\n%r8 %18\n%r9 %0\n%r9 %-1\n%r9 %18\n"
+ "%r10 %0\n%r10 %-1\n%r10 %18\n%r11 %0\n%r11 %-1\n%r11 %18\n"
+ "%r12 %0\n%r12 %-1\n%r12 %18\n%r13 %0\n%r13 %-1\n%r13 %18\n"
+ "%r14 %0\n%r14 %-1\n%r14 %18\n%r15 %0\n%r15 %-1\n%r15 %18\n",
+ RepeatRI(/*f*/ nullptr, /*imm_bytes*/ 1U, "%{reg} %{imm}"));
+}
+
+TEST_F(AssemblerX86_64Test, RepeatRr) {
+ EXPECT_NE(RepeatRr(/*f*/ nullptr, "%{reg1} %{reg2}")
+ .find("%rax %eax\n%rax %ebx\n%rax %ecx\n%rax %edx\n%rax %ebp\n"
+ "%rax %esp\n%rax %esi\n%rax %edi\n%rax %r8d\n%rax %r9d\n"
+ "%rax %r10d\n%rax %r11d\n%rax %r12d\n%rax %r13d\n%rax %r14d\n"
+ "%rax %r15d\n%rbx %eax\n%rbx %ebx\n%rbx %ecx\n%rbx %edx\n"),
+ std::string::npos);
+}
+
+TEST_F(AssemblerX86_64Test, RepeatRR) {
+ EXPECT_NE(RepeatRR(/*f*/ nullptr, "%{reg1} %{reg2}")
+ .find("%rax %rax\n%rax %rbx\n%rax %rcx\n%rax %rdx\n%rax %rbp\n"
+ "%rax %rsp\n%rax %rsi\n%rax %rdi\n%rax %r8\n%rax %r9\n"
+ "%rax %r10\n%rax %r11\n%rax %r12\n%rax %r13\n%rax %r14\n"
+ "%rax %r15\n%rbx %rax\n%rbx %rbx\n%rbx %rcx\n%rbx %rdx\n"),
+ std::string::npos);
+}
+
+TEST_F(AssemblerX86_64Test, RepeatRF) {
+ EXPECT_NE(RepeatRF(/*f*/ nullptr, "%{reg1} %{reg2}")
+ .find("%rax %xmm0\n%rax %xmm1\n%rax %xmm2\n%rax %xmm3\n%rax %xmm4\n"
+ "%rax %xmm5\n%rax %xmm6\n%rax %xmm7\n%rax %xmm8\n%rax %xmm9\n"
+ "%rax %xmm10\n%rax %xmm11\n%rax %xmm12\n%rax %xmm13\n%rax %xmm14\n"
+ "%rax %xmm15\n%rbx %xmm0\n%rbx %xmm1\n%rbx %xmm2\n%rbx %xmm3\n"),
+ std::string::npos);
+}
+
+TEST_F(AssemblerX86_64Test, RepeatFF) {
+ EXPECT_NE(RepeatFF(/*f*/ nullptr, "%{reg1} %{reg2}")
+ .find("%xmm0 %xmm0\n%xmm0 %xmm1\n%xmm0 %xmm2\n%xmm0 %xmm3\n%xmm0 %xmm4\n"
+ "%xmm0 %xmm5\n%xmm0 %xmm6\n%xmm0 %xmm7\n%xmm0 %xmm8\n%xmm0 %xmm9\n"
+ "%xmm0 %xmm10\n%xmm0 %xmm11\n%xmm0 %xmm12\n%xmm0 %xmm13\n%xmm0 %xmm14\n"
+ "%xmm0 %xmm15\n%xmm1 %xmm0\n%xmm1 %xmm1\n%xmm1 %xmm2\n%xmm1 %xmm3\n"),
+ std::string::npos);
+}
+
+TEST_F(AssemblerX86_64Test, RepeatFFI) {
+ EXPECT_NE(RepeatFFI(/*f*/ nullptr, /*imm_bytes*/ 1U, "%{reg1} %{reg2} %{imm}")
+ .find("%xmm0 %xmm0 %0\n%xmm0 %xmm0 %-1\n%xmm0 %xmm0 %18\n"
+ "%xmm0 %xmm1 %0\n%xmm0 %xmm1 %-1\n%xmm0 %xmm1 %18\n"
+ "%xmm0 %xmm2 %0\n%xmm0 %xmm2 %-1\n%xmm0 %xmm2 %18\n"
+ "%xmm0 %xmm3 %0\n%xmm0 %xmm3 %-1\n%xmm0 %xmm3 %18\n"),
+ std::string::npos);
+}
+
+//
+// Actual x86-64 instruction assembler tests.
+//
TEST_F(AssemblerX86_64Test, Toolchain) {
EXPECT_TRUE(CheckTools());
}
-
TEST_F(AssemblerX86_64Test, PushqRegs) {
DriverStr(RepeatR(&x86_64::X86_64Assembler::pushq, "pushq %{reg}"), "pushq");
}
@@ -978,10 +1100,6 @@
DriverStr(RepeatRr(&x86_64::X86_64Assembler::movsxd, "movsxd %{reg2}, %{reg1}"), "movsxd");
}
-///////////////////
-// FP Operations //
-///////////////////
-
TEST_F(AssemblerX86_64Test, Movaps) {
DriverStr(RepeatFF(&x86_64::X86_64Assembler::movaps, "movaps %{reg2}, %{reg1}"), "movaps");
}
@@ -1176,17 +1294,14 @@
DriverStr(RepeatFr(&x86_64::X86_64Assembler::cvtsi2sd, "cvtsi2sd %{reg2}, %{reg1}"), "cvtsi2sd");
}
-
TEST_F(AssemblerX86_64Test, Cvtss2si) {
DriverStr(RepeatrF(&x86_64::X86_64Assembler::cvtss2si, "cvtss2si %{reg2}, %{reg1}"), "cvtss2si");
}
-
TEST_F(AssemblerX86_64Test, Cvtss2sd) {
DriverStr(RepeatFF(&x86_64::X86_64Assembler::cvtss2sd, "cvtss2sd %{reg2}, %{reg1}"), "cvtss2sd");
}
-
TEST_F(AssemblerX86_64Test, Cvtsd2si) {
DriverStr(RepeatrF(&x86_64::X86_64Assembler::cvtsd2si, "cvtsd2si %{reg2}, %{reg1}"), "cvtsd2si");
}
@@ -1586,8 +1701,6 @@
DriverStr(expected, "ucomisd_address");
}
-// X87
-
std::string x87_fn(AssemblerX86_64Test::Base* assembler_test ATTRIBUTE_UNUSED,
x86_64::X86_64Assembler* assembler) {
std::ostringstream str;
@@ -1629,10 +1742,6 @@
DriverStr(expected, "FPUIntegerStore");
}
-////////////////
-// CALL / JMP //
-////////////////
-
TEST_F(AssemblerX86_64Test, Call) {
DriverStr(RepeatR(&x86_64::X86_64Assembler::call, "call *%{reg}"), "call");
}
@@ -1668,10 +1777,6 @@
DriverFn(&ret_and_leave_fn, "retleave");
}
-//////////
-// MISC //
-//////////
-
TEST_F(AssemblerX86_64Test, Bswapl) {
DriverStr(Repeatr(&x86_64::X86_64Assembler::bswapl, "bswap %{reg}"), "bswapl");
}
@@ -1824,11 +1929,6 @@
DriverStr(expected, "cmovq_address");
}
-
-/////////////////
-// Near labels //
-/////////////////
-
TEST_F(AssemblerX86_64Test, Jrcxz) {
x86_64::NearLabel target;
GetAssembler()->jrcxz(&target);