x86_64: Allow test to skip register pairs. Fix XCHG and enable tests.
Previously tests were disabled for `xchgl reg, reg` variant with all
register pairs, although the problematic case is only `xchg eax, eax`.
This commit allows one to pass an exception list to a testing function
and skip the problematic register pairs instead of disabling the whole
test. The patch adds exception lists to all testing functions that run
over register pairs, although XCHG only needs it for `Repeatrr`.
Enabling the test revealed a few small errors in the XCHG implementation
(namely, source and destination registers were swapped, which does not
affect the result). This commit fixes the implementation so that the
tests pass.
Bug: 65872996
Test: m test-art-host-gtest
Change-Id: Iaa759861330bcfb30db1a8219b805cc479cc3280
diff --git a/compiler/utils/assembler_test.h b/compiler/utils/assembler_test.h
index 9fffda5..bb22fe5 100644
--- a/compiler/utils/assembler_test.h
+++ b/compiler/utils/assembler_test.h
@@ -88,13 +88,16 @@
fmt);
}
- std::string RepeatRR(void (Ass::*f)(Reg, Reg), const std::string& fmt) {
+ std::string RepeatRR(void (Ass::*f)(Reg, Reg),
+ const std::string& fmt,
+ const std::vector<std::pair<Reg, Reg>>* except = nullptr) {
return RepeatTemplatedRegisters<Reg, Reg>(f,
GetRegisters(),
GetRegisters(),
&AssemblerTest::GetRegName<RegisterView::kUsePrimaryName>,
&AssemblerTest::GetRegName<RegisterView::kUsePrimaryName>,
- fmt);
+ fmt,
+ except);
}
std::string RepeatRRNoDupes(void (Ass::*f)(Reg, Reg), const std::string& fmt) {
@@ -106,31 +109,40 @@
fmt);
}
- std::string Repeatrr(void (Ass::*f)(Reg, Reg), const std::string& fmt) {
+ std::string Repeatrr(void (Ass::*f)(Reg, Reg),
+ const std::string& fmt,
+ const std::vector<std::pair<Reg, Reg>>* except = nullptr) {
return RepeatTemplatedRegisters<Reg, Reg>(f,
GetRegisters(),
GetRegisters(),
&AssemblerTest::GetRegName<RegisterView::kUseSecondaryName>,
&AssemblerTest::GetRegName<RegisterView::kUseSecondaryName>,
- fmt);
+ fmt,
+ except);
}
- std::string Repeatww(void (Ass::*f)(Reg, Reg), const std::string& fmt) {
+ std::string Repeatww(void (Ass::*f)(Reg, Reg),
+ const std::string& fmt,
+ const std::vector<std::pair<Reg, Reg>>* except = nullptr) {
return RepeatTemplatedRegisters<Reg, Reg>(f,
GetRegisters(),
GetRegisters(),
&AssemblerTest::GetRegName<RegisterView::kUseTertiaryName>,
&AssemblerTest::GetRegName<RegisterView::kUseTertiaryName>,
- fmt);
+ fmt,
+ except);
}
- std::string Repeatbb(void (Ass::*f)(Reg, Reg), const std::string& fmt) {
+ std::string Repeatbb(void (Ass::*f)(Reg, Reg),
+ const std::string& fmt,
+ const std::vector<std::pair<Reg, Reg>>* except = nullptr) {
return RepeatTemplatedRegisters<Reg, Reg>(f,
GetRegisters(),
GetRegisters(),
&AssemblerTest::GetRegName<RegisterView::kUseQuaternaryName>,
&AssemblerTest::GetRegName<RegisterView::kUseQuaternaryName>,
- fmt);
+ fmt,
+ except);
}
std::string RepeatRRR(void (Ass::*f)(Reg, Reg, Reg), const std::string& fmt) {
@@ -144,22 +156,28 @@
fmt);
}
- std::string Repeatrb(void (Ass::*f)(Reg, Reg), const std::string& fmt) {
+ std::string Repeatrb(void (Ass::*f)(Reg, Reg),
+ const std::string& fmt,
+ const std::vector<std::pair<Reg, Reg>>* except = nullptr) {
return RepeatTemplatedRegisters<Reg, Reg>(f,
GetRegisters(),
GetRegisters(),
&AssemblerTest::GetRegName<RegisterView::kUseSecondaryName>,
&AssemblerTest::GetRegName<RegisterView::kUseQuaternaryName>,
- fmt);
+ fmt,
+ except);
}
- std::string RepeatRr(void (Ass::*f)(Reg, Reg), const std::string& fmt) {
+ std::string RepeatRr(void (Ass::*f)(Reg, Reg),
+ const std::string& fmt,
+ const std::vector<std::pair<Reg, Reg>>* except = nullptr) {
return RepeatTemplatedRegisters<Reg, Reg>(f,
GetRegisters(),
GetRegisters(),
&AssemblerTest::GetRegName<RegisterView::kUsePrimaryName>,
&AssemblerTest::GetRegName<RegisterView::kUseSecondaryName>,
- fmt);
+ fmt,
+ except);
}
std::string RepeatRI(void (Ass::*f)(Reg, const Imm&), size_t imm_bytes, const std::string& fmt) {
@@ -1266,12 +1284,21 @@
const std::vector<Reg2*> reg2_registers,
std::string (AssemblerTest::*GetName1)(const Reg1&),
std::string (AssemblerTest::*GetName2)(const Reg2&),
- const std::string& fmt) {
+ const std::string& fmt,
+ const std::vector<std::pair<Reg1, Reg2>>* except = nullptr) {
WarnOnCombinations(reg1_registers.size() * reg2_registers.size());
std::string str;
for (auto reg1 : reg1_registers) {
for (auto reg2 : reg2_registers) {
+ // Check if this register pair is on the exception list. If so, skip it.
+ if (except != nullptr) {
+ const auto& pair = std::make_pair(*reg1, *reg2);
+ if (std::find(except->begin(), except->end(), pair) != except->end()) {
+ continue;
+ }
+ }
+
if (f != nullptr) {
(assembler_.get()->*f)(*reg1, *reg2);
}