Add repeat support for memory addresses.
Rationale:
This enables exhaustive testing of instructions
that use memory addresses. First use case of
the generics is x86.
Bug: 18380245
Bug: 18380559
Bug: 18380348
Test: assembler_x86[_64]_test
Change-Id: Ib0ad6fa65477b0c6fc04642ff980a4b9543d16d5
diff --git a/compiler/utils/assembler_test.h b/compiler/utils/assembler_test.h
index 5ab558b..12954a4 100644
--- a/compiler/utils/assembler_test.h
+++ b/compiler/utils/assembler_test.h
@@ -46,7 +46,12 @@
// For use in the template as the default type to get a nonvector registers version.
struct NoVectorRegs {};
-template<typename Ass, typename Reg, typename FPReg, typename Imm, typename VecReg = NoVectorRegs>
+template<typename Ass,
+ typename Addr,
+ typename Reg,
+ typename FPReg,
+ typename Imm,
+ typename VecReg = NoVectorRegs>
class AssemblerTest : public testing::Test {
public:
Ass* GetAssembler() {
@@ -64,6 +69,10 @@
DriverWrapper(assembly_string, test_name);
}
+ //
+ // Register repeats.
+ //
+
std::string RepeatR(void (Ass::*f)(Reg), const std::string& fmt) {
return RepeatTemplatedRegister<Reg>(f,
GetRegisters(),
@@ -636,13 +645,23 @@
// The following functions are public so that TestFn can use them...
+ // Returns a vector of address used by any of the repeat methods
+ // involving an "A" (e.g. RepeatA).
+ virtual std::vector<Addr> GetAddresses() = 0;
+
+ // Returns a vector of registers used by any of the repeat methods
+ // involving an "R" (e.g. RepeatR).
virtual std::vector<Reg*> GetRegisters() = 0;
+ // Returns a vector of fp-registers used by any of the repeat methods
+ // involving an "F" (e.g. RepeatFF).
virtual std::vector<FPReg*> GetFPRegisters() {
UNIMPLEMENTED(FATAL) << "Architecture does not support floating-point registers";
UNREACHABLE();
}
+ // Returns a vector of dedicated simd-registers used by any of the repeat
+ // methods involving an "V" (e.g. RepeatVV).
virtual std::vector<VecReg*> GetVectorRegisters() {
UNIMPLEMENTED(FATAL) << "Architecture does not support vector registers";
UNREACHABLE();
@@ -838,6 +857,268 @@
// Create an immediate from the specific value.
virtual Imm CreateImmediate(int64_t imm_value) = 0;
+ //
+ // Addresses repeats.
+ //
+
+ // Repeats over addresses provided by fixture.
+ std::string RepeatA(void (Ass::*f)(const Addr&), const std::string& fmt) {
+ return RepeatA(f, GetAddresses(), fmt);
+ }
+
+ // Variant that takes explicit vector of addresss
+ // (to test restricted addressing modes set).
+ std::string RepeatA(void (Ass::*f)(const Addr&),
+ const std::vector<Addr>& a,
+ const std::string& fmt) {
+ return RepeatTemplatedMem<Addr>(f, a, &AssemblerTest::GetAddrName, fmt);
+ }
+
+ // Repeats over addresses and immediates provided by fixture.
+ std::string RepeatAI(void (Ass::*f)(const Addr&, const Imm&),
+ size_t imm_bytes,
+ const std::string& fmt) {
+ return RepeatAI(f, imm_bytes, GetAddresses(), fmt);
+ }
+
+ // Variant that takes explicit vector of addresss
+ // (to test restricted addressing modes set).
+ std::string RepeatAI(void (Ass::*f)(const Addr&, const Imm&),
+ size_t imm_bytes,
+ const std::vector<Addr>& a,
+ const std::string& fmt) {
+ return RepeatTemplatedMemImm<Addr>(f, imm_bytes, a, &AssemblerTest::GetAddrName, fmt);
+ }
+
+ // Repeats over registers and addresses provided by fixture.
+ std::string RepeatRA(void (Ass::*f)(Reg, const Addr&), const std::string& fmt) {
+ return RepeatRA(f, GetAddresses(), fmt);
+ }
+
+ // Variant that takes explicit vector of addresss
+ // (to test restricted addressing modes set).
+ std::string RepeatRA(void (Ass::*f)(Reg, const Addr&),
+ const std::vector<Addr>& a,
+ const std::string& fmt) {
+ return RepeatTemplatedRegMem<Reg, Addr>(
+ f,
+ GetRegisters(),
+ a,
+ &AssemblerTest::GetRegName<RegisterView::kUsePrimaryName>,
+ &AssemblerTest::GetAddrName,
+ fmt);
+ }
+
+ // Repeats over fp-registers and addresses provided by fixture.
+ std::string RepeatFA(void (Ass::*f)(FPReg, const Addr&), const std::string& fmt) {
+ return RepeatFA(f, GetAddresses(), fmt);
+ }
+
+ // Variant that takes explicit vector of addresss
+ // (to test restricted addressing modes set).
+ std::string RepeatFA(void (Ass::*f)(FPReg, const Addr&),
+ const std::vector<Addr>& a,
+ const std::string& fmt) {
+ return RepeatTemplatedRegMem<FPReg, Addr>(
+ f,
+ GetFPRegisters(),
+ a,
+ &AssemblerTest::GetFPRegName,
+ &AssemblerTest::GetAddrName,
+ fmt);
+ }
+
+ // Repeats over addresses and registers provided by fixture.
+ std::string RepeatAR(void (Ass::*f)(const Addr&, Reg), const std::string& fmt) {
+ return RepeatAR(f, GetAddresses(), fmt);
+ }
+
+ // Variant that takes explicit vector of addresss
+ // (to test restricted addressing modes set).
+ std::string RepeatAR(void (Ass::*f)(const Addr&, Reg),
+ const std::vector<Addr>& a,
+ const std::string& fmt) {
+ return RepeatTemplatedMemReg<Addr, Reg>(
+ f,
+ a,
+ GetRegisters(),
+ &AssemblerTest::GetAddrName,
+ &AssemblerTest::GetRegName<RegisterView::kUsePrimaryName>,
+ fmt);
+ }
+
+ // Repeats over addresses and fp-registers provided by fixture.
+ std::string RepeatAF(void (Ass::*f)(const Addr&, FPReg), const std::string& fmt) {
+ return RepeatAF(f, GetAddresses(), fmt);
+ }
+
+ // Variant that takes explicit vector of addresss
+ // (to test restricted addressing modes set).
+ std::string RepeatAF(void (Ass::*f)(const Addr&, FPReg),
+ const std::vector<Addr>& a,
+ const std::string& fmt) {
+ return RepeatTemplatedMemReg<Addr, FPReg>(
+ f,
+ a,
+ GetFPRegisters(),
+ &AssemblerTest::GetAddrName,
+ &AssemblerTest::GetFPRegName,
+ fmt);
+ }
+
+ template <typename AddrType>
+ std::string RepeatTemplatedMem(void (Ass::*f)(const AddrType&),
+ const std::vector<AddrType> addresses,
+ std::string (AssemblerTest::*GetAName)(const AddrType&),
+ const std::string& fmt) {
+ WarnOnCombinations(addresses.size());
+ std::string str;
+ for (auto addr : addresses) {
+ if (f != nullptr) {
+ (assembler_.get()->*f)(addr);
+ }
+ std::string base = fmt;
+
+ std::string addr_string = (this->*GetAName)(addr);
+ size_t addr_index;
+ if ((addr_index = base.find(ADDRESS_TOKEN)) != std::string::npos) {
+ base.replace(addr_index, ConstexprStrLen(ADDRESS_TOKEN), addr_string);
+ }
+
+ if (str.size() > 0) {
+ str += "\n";
+ }
+ str += base;
+ }
+ // Add a newline at the end.
+ str += "\n";
+ return str;
+ }
+
+ template <typename AddrType>
+ std::string RepeatTemplatedMemImm(void (Ass::*f)(const AddrType&, const Imm&),
+ size_t imm_bytes,
+ const std::vector<AddrType> addresses,
+ std::string (AssemblerTest::*GetAName)(const AddrType&),
+ const std::string& fmt) {
+ std::vector<int64_t> imms = CreateImmediateValues(imm_bytes);
+ WarnOnCombinations(addresses.size() * imms.size());
+ std::string str;
+ for (auto addr : addresses) {
+ for (int64_t imm : imms) {
+ Imm new_imm = CreateImmediate(imm);
+ if (f != nullptr) {
+ (assembler_.get()->*f)(addr, new_imm);
+ }
+ std::string base = fmt;
+
+ std::string addr_string = (this->*GetAName)(addr);
+ size_t addr_index;
+ if ((addr_index = base.find(ADDRESS_TOKEN)) != std::string::npos) {
+ base.replace(addr_index, ConstexprStrLen(ADDRESS_TOKEN), addr_string);
+ }
+
+ size_t imm_index = base.find(IMM_TOKEN);
+ if (imm_index != std::string::npos) {
+ std::ostringstream sreg;
+ sreg << imm;
+ std::string imm_string = sreg.str();
+ base.replace(imm_index, ConstexprStrLen(IMM_TOKEN), imm_string);
+ }
+
+ if (str.size() > 0) {
+ str += "\n";
+ }
+ str += base;
+ }
+ }
+ // Add a newline at the end.
+ str += "\n";
+ return str;
+ }
+
+ template <typename RegType, typename AddrType>
+ std::string RepeatTemplatedRegMem(void (Ass::*f)(RegType, const AddrType&),
+ const std::vector<RegType*> registers,
+ const std::vector<AddrType> addresses,
+ std::string (AssemblerTest::*GetRName)(const RegType&),
+ std::string (AssemblerTest::*GetAName)(const AddrType&),
+ const std::string& fmt) {
+ WarnOnCombinations(addresses.size() * registers.size());
+ std::string str;
+ for (auto reg : registers) {
+ for (auto addr : addresses) {
+ if (f != nullptr) {
+ (assembler_.get()->*f)(*reg, addr);
+ }
+ std::string base = fmt;
+
+ std::string reg_string = (this->*GetRName)(*reg);
+ size_t reg_index;
+ if ((reg_index = base.find(REG_TOKEN)) != std::string::npos) {
+ base.replace(reg_index, ConstexprStrLen(REG_TOKEN), reg_string);
+ }
+
+ std::string addr_string = (this->*GetAName)(addr);
+ size_t addr_index;
+ if ((addr_index = base.find(ADDRESS_TOKEN)) != std::string::npos) {
+ base.replace(addr_index, ConstexprStrLen(ADDRESS_TOKEN), addr_string);
+ }
+
+ if (str.size() > 0) {
+ str += "\n";
+ }
+ str += base;
+ }
+ }
+ // Add a newline at the end.
+ str += "\n";
+ return str;
+ }
+
+ template <typename AddrType, typename RegType>
+ std::string RepeatTemplatedMemReg(void (Ass::*f)(const AddrType&, RegType),
+ const std::vector<AddrType> addresses,
+ const std::vector<RegType*> registers,
+ std::string (AssemblerTest::*GetAName)(const AddrType&),
+ std::string (AssemblerTest::*GetRName)(const RegType&),
+ const std::string& fmt) {
+ WarnOnCombinations(addresses.size() * registers.size());
+ std::string str;
+ for (auto addr : addresses) {
+ for (auto reg : registers) {
+ if (f != nullptr) {
+ (assembler_.get()->*f)(addr, *reg);
+ }
+ std::string base = fmt;
+
+ std::string addr_string = (this->*GetAName)(addr);
+ size_t addr_index;
+ if ((addr_index = base.find(ADDRESS_TOKEN)) != std::string::npos) {
+ base.replace(addr_index, ConstexprStrLen(ADDRESS_TOKEN), addr_string);
+ }
+
+ std::string reg_string = (this->*GetRName)(*reg);
+ size_t reg_index;
+ if ((reg_index = base.find(REG_TOKEN)) != std::string::npos) {
+ base.replace(reg_index, ConstexprStrLen(REG_TOKEN), reg_string);
+ }
+
+ if (str.size() > 0) {
+ str += "\n";
+ }
+ str += base;
+ }
+ }
+ // Add a newline at the end.
+ str += "\n";
+ return str;
+ }
+
+ //
+ // Register repeats.
+ //
+
template <typename RegType>
std::string RepeatTemplatedRegister(void (Ass::*f)(RegType),
const std::vector<RegType*> registers,
@@ -1048,6 +1329,12 @@
return str;
}
+ std::string GetAddrName(const Addr& addr) {
+ std::ostringstream saddr;
+ saddr << addr;
+ return saddr.str();
+ }
+
template <RegisterView kRegView>
std::string GetRegName(const Reg& reg) {
std::ostringstream sreg;
@@ -1094,6 +1381,7 @@
}
}
+ static constexpr const char* ADDRESS_TOKEN = "{mem}";
static constexpr const char* REG_TOKEN = "{reg}";
static constexpr const char* REG1_TOKEN = "{reg1}";
static constexpr const char* REG2_TOKEN = "{reg2}";
diff --git a/compiler/utils/mips/assembler_mips32r5_test.cc b/compiler/utils/mips/assembler_mips32r5_test.cc
index 24b09b5..a3662db 100644
--- a/compiler/utils/mips/assembler_mips32r5_test.cc
+++ b/compiler/utils/mips/assembler_mips32r5_test.cc
@@ -32,12 +32,14 @@
};
class AssemblerMIPS32r5Test : public AssemblerTest<mips::MipsAssembler,
+ mips::MipsLabel,
mips::Register,
mips::FRegister,
uint32_t,
mips::VectorRegister> {
public:
typedef AssemblerTest<mips::MipsAssembler,
+ mips::MipsLabel,
mips::Register,
mips::FRegister,
uint32_t,
@@ -217,6 +219,11 @@
STLDeleteElements(&vec_registers_);
}
+ std::vector<mips::MipsLabel> GetAddresses() {
+ UNIMPLEMENTED(FATAL) << "Feature not implemented yet";
+ UNREACHABLE();
+ }
+
std::vector<mips::Register*> GetRegisters() OVERRIDE {
return registers_;
}
diff --git a/compiler/utils/mips/assembler_mips32r6_test.cc b/compiler/utils/mips/assembler_mips32r6_test.cc
index a5cd5a7..b6cb30a 100644
--- a/compiler/utils/mips/assembler_mips32r6_test.cc
+++ b/compiler/utils/mips/assembler_mips32r6_test.cc
@@ -32,12 +32,14 @@
};
class AssemblerMIPS32r6Test : public AssemblerTest<mips::MipsAssembler,
+ mips::MipsLabel,
mips::Register,
mips::FRegister,
uint32_t,
mips::VectorRegister> {
public:
typedef AssemblerTest<mips::MipsAssembler,
+ mips::MipsLabel,
mips::Register,
mips::FRegister,
uint32_t,
@@ -230,6 +232,11 @@
STLDeleteElements(&vec_registers_);
}
+ std::vector<mips::MipsLabel> GetAddresses() {
+ UNIMPLEMENTED(FATAL) << "Feature not implemented yet";
+ UNREACHABLE();
+ }
+
std::vector<mips::Register*> GetRegisters() OVERRIDE {
return registers_;
}
diff --git a/compiler/utils/mips/assembler_mips_test.cc b/compiler/utils/mips/assembler_mips_test.cc
index 680c347..eed83a5 100644
--- a/compiler/utils/mips/assembler_mips_test.cc
+++ b/compiler/utils/mips/assembler_mips_test.cc
@@ -32,11 +32,16 @@
};
class AssemblerMIPSTest : public AssemblerTest<mips::MipsAssembler,
+ mips::MipsLabel,
mips::Register,
mips::FRegister,
uint32_t> {
public:
- typedef AssemblerTest<mips::MipsAssembler, mips::Register, mips::FRegister, uint32_t> Base;
+ typedef AssemblerTest<mips::MipsAssembler,
+ mips::MipsLabel,
+ mips::Register,
+ mips::FRegister,
+ uint32_t> Base;
protected:
// Get the typically used name for this architecture, e.g., aarch64, x86-64, ...
@@ -161,6 +166,11 @@
STLDeleteElements(&fp_registers_);
}
+ std::vector<mips::MipsLabel> GetAddresses() {
+ UNIMPLEMENTED(FATAL) << "Feature not implemented yet";
+ UNREACHABLE();
+ }
+
std::vector<mips::Register*> GetRegisters() OVERRIDE {
return registers_;
}
diff --git a/compiler/utils/mips64/assembler_mips64_test.cc b/compiler/utils/mips64/assembler_mips64_test.cc
index fc0bd36..16a36f9 100644
--- a/compiler/utils/mips64/assembler_mips64_test.cc
+++ b/compiler/utils/mips64/assembler_mips64_test.cc
@@ -35,12 +35,14 @@
};
class AssemblerMIPS64Test : public AssemblerTest<mips64::Mips64Assembler,
+ mips64::Mips64Label,
mips64::GpuRegister,
mips64::FpuRegister,
uint32_t,
mips64::VectorRegister> {
public:
typedef AssemblerTest<mips64::Mips64Assembler,
+ mips64::Mips64Label,
mips64::GpuRegister,
mips64::FpuRegister,
uint32_t,
@@ -228,6 +230,11 @@
STLDeleteElements(&vec_registers_);
}
+ std::vector<mips64::Mips64Label> GetAddresses() {
+ UNIMPLEMENTED(FATAL) << "Feature not implemented yet";
+ UNREACHABLE();
+ }
+
std::vector<mips64::GpuRegister*> GetRegisters() OVERRIDE {
return registers_;
}
diff --git a/compiler/utils/x86/assembler_x86.cc b/compiler/utils/x86/assembler_x86.cc
index b89af10..3162a32 100644
--- a/compiler/utils/x86/assembler_x86.cc
+++ b/compiler/utils/x86/assembler_x86.cc
@@ -32,6 +32,33 @@
return os << "ST" << static_cast<int>(reg);
}
+std::ostream& operator<<(std::ostream& os, const Address& addr) {
+ switch (addr.mod()) {
+ case 0:
+ if (addr.rm() == ESP && addr.index() != ESP) {
+ return os << "(%" << addr.base() << ",%"
+ << addr.index() << "," << (1 << addr.scale()) << ")";
+ }
+ return os << "(%" << addr.rm() << ")";
+ case 1:
+ if (addr.rm() == ESP && addr.index() != ESP) {
+ return os << static_cast<int>(addr.disp8())
+ << "(%" << addr.base() << ",%"
+ << addr.index() << "," << (1 << addr.scale()) << ")";
+ }
+ return os << static_cast<int>(addr.disp8()) << "(%" << addr.rm() << ")";
+ case 2:
+ if (addr.rm() == ESP && addr.index() != ESP) {
+ return os << static_cast<int>(addr.disp32())
+ << "(%" << addr.base() << ",%"
+ << addr.index() << "," << (1 << addr.scale()) << ")";
+ }
+ return os << static_cast<int>(addr.disp32()) << "(%" << addr.rm() << ")";
+ default:
+ return os << "<address?>";
+ }
+}
+
void X86Assembler::call(Register reg) {
AssemblerBuffer::EnsureCapacity ensured(&buffer_);
EmitUint8(0xFF);
diff --git a/compiler/utils/x86/assembler_x86.h b/compiler/utils/x86/assembler_x86.h
index 511eeb9..2964dba 100644
--- a/compiler/utils/x86/assembler_x86.h
+++ b/compiler/utils/x86/assembler_x86.h
@@ -235,6 +235,7 @@
}
};
+std::ostream& operator<<(std::ostream& os, const Address& addr);
// This is equivalent to the Label class, used in a slightly different context. We
// inherit the functionality of the Label class, but prevent unintended
diff --git a/compiler/utils/x86/assembler_x86_test.cc b/compiler/utils/x86/assembler_x86_test.cc
index 48e4117..c28ed3b 100644
--- a/compiler/utils/x86/assembler_x86_test.cc
+++ b/compiler/utils/x86/assembler_x86_test.cc
@@ -37,11 +37,17 @@
// Test fixture.
//
-class AssemblerX86Test : public AssemblerTest<x86::X86Assembler, x86::Register,
- x86::XmmRegister, x86::Immediate> {
+class AssemblerX86Test : public AssemblerTest<x86::X86Assembler,
+ x86::Address,
+ x86::Register,
+ x86::XmmRegister,
+ x86::Immediate> {
public:
- typedef AssemblerTest<x86::X86Assembler, x86::Register,
- x86::XmmRegister, x86::Immediate> Base;
+ typedef AssemblerTest<x86::X86Assembler,
+ x86::Address,
+ x86::Register,
+ x86::XmmRegister,
+ x86::Immediate> Base;
protected:
std::string GetArchitectureString() OVERRIDE {
@@ -57,6 +63,31 @@
}
void SetUpHelpers() OVERRIDE {
+ if (addresses_singleton_.size() == 0) {
+ // One addressing mode to test the repeat drivers.
+ addresses_singleton_.push_back(x86::Address(x86::EAX, x86::EBX, x86::TIMES_1, 2));
+ }
+
+ if (addresses_.size() == 0) {
+ // Several addressing modes.
+ addresses_.push_back(x86::Address(x86::EDI, x86::EAX, x86::TIMES_1, 15));
+ addresses_.push_back(x86::Address(x86::EDI, x86::EBX, x86::TIMES_2, 16));
+ addresses_.push_back(x86::Address(x86::EDI, x86::ECX, x86::TIMES_4, 17));
+ addresses_.push_back(x86::Address(x86::EDI, x86::EDX, x86::TIMES_8, 18));
+ addresses_.push_back(x86::Address(x86::EAX, -1));
+ addresses_.push_back(x86::Address(x86::EBX, 0));
+ addresses_.push_back(x86::Address(x86::ESI, 1));
+ addresses_.push_back(x86::Address(x86::EDI, 987654321));
+ // Several addressing modes with the special ESP.
+ addresses_.push_back(x86::Address(x86::ESP, x86::EAX, x86::TIMES_1, 15));
+ addresses_.push_back(x86::Address(x86::ESP, x86::EBX, x86::TIMES_2, 16));
+ addresses_.push_back(x86::Address(x86::ESP, x86::ECX, x86::TIMES_4, 17));
+ addresses_.push_back(x86::Address(x86::ESP, x86::EDX, x86::TIMES_8, 18));
+ addresses_.push_back(x86::Address(x86::ESP, -1));
+ addresses_.push_back(x86::Address(x86::ESP, 0));
+ addresses_.push_back(x86::Address(x86::ESP, 1));
+ addresses_.push_back(x86::Address(x86::ESP, 987654321));
+ }
if (registers_.size() == 0) {
registers_.insert(end(registers_),
{ // NOLINT(whitespace/braces)
@@ -92,6 +123,10 @@
STLDeleteElements(&fp_registers_);
}
+ std::vector<x86::Address> GetAddresses() OVERRIDE {
+ return addresses_;
+ }
+
std::vector<x86::Register*> GetRegisters() OVERRIDE {
return registers_;
}
@@ -104,7 +139,10 @@
return x86::Immediate(imm_value);
}
+ std::vector<x86::Address> addresses_singleton_;
+
private:
+ std::vector<x86::Address> addresses_;
std::vector<x86::Register*> registers_;
std::vector<x86::XmmRegister*> fp_registers_;
};
@@ -128,10 +166,10 @@
}
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}"));
+ 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) {
@@ -150,30 +188,67 @@
}
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"),
+ 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);
}
+TEST_F(AssemblerX86Test, RepeatA) {
+ EXPECT_EQ("2(%eax,%ebx,1)\n", RepeatA(/*f*/ nullptr, addresses_singleton_, "{mem}"));
+}
+
+TEST_F(AssemblerX86Test, RepeatAI) {
+ EXPECT_EQ("2(%eax,%ebx,1) $0\n2(%eax,%ebx,1) $-1\n2(%eax,%ebx,1) $18\n",
+ RepeatAI(/*f*/ nullptr, /*imm_bytes*/ 1U, addresses_singleton_, "{mem} ${imm}"));
+}
+
+TEST_F(AssemblerX86Test, RepeatRA) {
+ EXPECT_EQ("%eax 2(%eax,%ebx,1)\n%ebx 2(%eax,%ebx,1)\n%ecx 2(%eax,%ebx,1)\n"
+ "%edx 2(%eax,%ebx,1)\n%ebp 2(%eax,%ebx,1)\n%esp 2(%eax,%ebx,1)\n"
+ "%esi 2(%eax,%ebx,1)\n%edi 2(%eax,%ebx,1)\n",
+ RepeatRA(/*f*/ nullptr, addresses_singleton_, "%{reg} {mem}"));
+}
+
+TEST_F(AssemblerX86Test, RepeatAR) {
+ EXPECT_EQ("2(%eax,%ebx,1) %eax\n2(%eax,%ebx,1) %ebx\n2(%eax,%ebx,1) %ecx\n"
+ "2(%eax,%ebx,1) %edx\n2(%eax,%ebx,1) %ebp\n2(%eax,%ebx,1) %esp\n"
+ "2(%eax,%ebx,1) %esi\n2(%eax,%ebx,1) %edi\n",
+ RepeatAR(/*f*/ nullptr, addresses_singleton_, "{mem} %{reg}"));
+}
+
+TEST_F(AssemblerX86Test, RepeatFA) {
+ EXPECT_EQ("%XMM0 2(%eax,%ebx,1)\n%XMM1 2(%eax,%ebx,1)\n%XMM2 2(%eax,%ebx,1)\n"
+ "%XMM3 2(%eax,%ebx,1)\n%XMM4 2(%eax,%ebx,1)\n%XMM5 2(%eax,%ebx,1)\n"
+ "%XMM6 2(%eax,%ebx,1)\n%XMM7 2(%eax,%ebx,1)\n",
+ RepeatFA(/*f*/ nullptr, addresses_singleton_, "%{reg} {mem}"));
+}
+
+TEST_F(AssemblerX86Test, RepeatAF) {
+ EXPECT_EQ("2(%eax,%ebx,1) %XMM0\n2(%eax,%ebx,1) %XMM1\n2(%eax,%ebx,1) %XMM2\n"
+ "2(%eax,%ebx,1) %XMM3\n2(%eax,%ebx,1) %XMM4\n2(%eax,%ebx,1) %XMM5\n"
+ "2(%eax,%ebx,1) %XMM6\n2(%eax,%ebx,1) %XMM7\n",
+ RepeatAF(/*f*/ nullptr, addresses_singleton_, "{mem} %{reg}"));
+}
+
//
// Actual x86 instruction assembler tests.
//
TEST_F(AssemblerX86Test, Movl) {
- GetAssembler()->movl(x86::EAX, x86::EBX);
- const char* expected = "mov %ebx, %eax\n";
- DriverStr(expected, "movl");
+ DriverStr(RepeatRR(&x86::X86Assembler::movl, "movl %{reg2}, %{reg1}"), "movl");
+}
+
+TEST_F(AssemblerX86Test, MovlLoad) {
+ DriverStr(RepeatRA(&x86::X86Assembler::movl, "movl {mem}, %{reg}"), "movl-load");
+}
+
+TEST_F(AssemblerX86Test, MovlStore) {
+ DriverStr(RepeatAR(&x86::X86Assembler::movl, "movl %{reg}, {mem}"), "movl-store");
}
TEST_F(AssemblerX86Test, Movntl) {
- GetAssembler()->movntl(x86::Address(x86::EDI, x86::EBX, x86::TIMES_4, 12), x86::EAX);
- GetAssembler()->movntl(x86::Address(x86::EDI, 0), x86::EAX);
- const char* expected =
- "movntil %EAX, 0xc(%EDI,%EBX,4)\n"
- "movntil %EAX, (%EDI)\n";
-
- DriverStr(expected, "movntl");
+ DriverStr(RepeatAR(&x86::X86Assembler::movntl, "movntil %{reg}, {mem}"), "movntl");
}
TEST_F(AssemblerX86Test, LoadLongConstant) {
@@ -187,66 +262,29 @@
}
TEST_F(AssemblerX86Test, LockCmpxchgl) {
- GetAssembler()->LockCmpxchgl(x86::Address(
- x86::Register(x86::EDI), x86::Register(x86::EBX), x86::TIMES_4, 12),
- x86::Register(x86::ESI));
- GetAssembler()->LockCmpxchgl(x86::Address(
- x86::Register(x86::EDI), x86::Register(x86::ESI), x86::TIMES_4, 12),
- x86::Register(x86::ESI));
- GetAssembler()->LockCmpxchgl(x86::Address(
- x86::Register(x86::EDI), x86::Register(x86::ESI), x86::TIMES_4, 12),
- x86::Register(x86::EDI));
- GetAssembler()->LockCmpxchgl(x86::Address(
- x86::Register(x86::EBP), 0), x86::Register(x86::ESI));
- GetAssembler()->LockCmpxchgl(x86::Address(
- x86::Register(x86::EBP), x86::Register(x86::ESI), x86::TIMES_1, 0),
- x86::Register(x86::ESI));
- const char* expected =
- "lock cmpxchgl %ESI, 0xc(%EDI,%EBX,4)\n"
- "lock cmpxchgl %ESI, 0xc(%EDI,%ESI,4)\n"
- "lock cmpxchgl %EDI, 0xc(%EDI,%ESI,4)\n"
- "lock cmpxchgl %ESI, (%EBP)\n"
- "lock cmpxchgl %ESI, (%EBP,%ESI,1)\n";
-
- DriverStr(expected, "lock_cmpxchgl");
+ DriverStr(RepeatAR(&x86::X86Assembler::LockCmpxchgl,
+ "lock cmpxchgl %{reg}, {mem}"), "lock_cmpxchgl");
}
TEST_F(AssemblerX86Test, LockCmpxchg8b) {
- GetAssembler()->LockCmpxchg8b(x86::Address(
- x86::Register(x86::EDI), x86::Register(x86::EBX), x86::TIMES_4, 12));
- GetAssembler()->LockCmpxchg8b(x86::Address(
- x86::Register(x86::EDI), x86::Register(x86::ESI), x86::TIMES_4, 12));
- GetAssembler()->LockCmpxchg8b(x86::Address(
- x86::Register(x86::EDI), x86::Register(x86::ESI), x86::TIMES_4, 12));
- GetAssembler()->LockCmpxchg8b(x86::Address(x86::Register(x86::EBP), 0));
- GetAssembler()->LockCmpxchg8b(x86::Address(
- x86::Register(x86::EBP), x86::Register(x86::ESI), x86::TIMES_1, 0));
- const char* expected =
- "lock cmpxchg8b 0xc(%EDI,%EBX,4)\n"
- "lock cmpxchg8b 0xc(%EDI,%ESI,4)\n"
- "lock cmpxchg8b 0xc(%EDI,%ESI,4)\n"
- "lock cmpxchg8b (%EBP)\n"
- "lock cmpxchg8b (%EBP,%ESI,1)\n";
-
- DriverStr(expected, "lock_cmpxchg8b");
+ DriverStr(RepeatA(&x86::X86Assembler::LockCmpxchg8b,
+ "lock cmpxchg8b {mem}"), "lock_cmpxchg8b");
}
-TEST_F(AssemblerX86Test, FPUIntegerLoad) {
- GetAssembler()->filds(x86::Address(x86::Register(x86::ESP), 4));
- GetAssembler()->fildl(x86::Address(x86::Register(x86::ESP), 12));
- const char* expected =
- "fildl 0x4(%ESP)\n"
- "fildll 0xc(%ESP)\n";
- DriverStr(expected, "FPUIntegerLoad");
+TEST_F(AssemblerX86Test, FPUIntegerLoadS) {
+ DriverStr(RepeatA(&x86::X86Assembler::filds, "fildl {mem}"), "fildd");
}
-TEST_F(AssemblerX86Test, FPUIntegerStore) {
- GetAssembler()->fistps(x86::Address(x86::Register(x86::ESP), 16));
- GetAssembler()->fistpl(x86::Address(x86::Register(x86::ESP), 24));
- const char* expected =
- "fistpl 0x10(%ESP)\n"
- "fistpll 0x18(%ESP)\n";
- DriverStr(expected, "FPUIntegerStore");
+TEST_F(AssemblerX86Test, FPUIntegerLoadL) {
+ DriverStr(RepeatA(&x86::X86Assembler::fildl, "fildll {mem}"), "fildl");
+}
+
+TEST_F(AssemblerX86Test, FPUIntegerStoreS) {
+ DriverStr(RepeatA(&x86::X86Assembler::fistps, "fistpl {mem}"), "fistps");
+}
+
+TEST_F(AssemblerX86Test, FPUIntegerStoreL) {
+ DriverStr(RepeatA(&x86::X86Assembler::fistpl, "fistpll {mem}"), "fistpl");
}
TEST_F(AssemblerX86Test, Repnescasb) {
@@ -296,12 +334,7 @@
}
TEST_F(AssemblerX86Test, BsflAddress) {
- GetAssembler()->bsfl(x86::Register(x86::EDI), x86::Address(
- x86::Register(x86::EDI), x86::Register(x86::EBX), x86::TIMES_4, 12));
- const char* expected =
- "bsfl 0xc(%EDI,%EBX,4), %EDI\n";
-
- DriverStr(expected, "bsfl_address");
+ DriverStr(RepeatRA(&x86::X86Assembler::bsfl, "bsfl {mem}, %{reg}"), "bsfl_address");
}
TEST_F(AssemblerX86Test, Bsrl) {
@@ -309,12 +342,7 @@
}
TEST_F(AssemblerX86Test, BsrlAddress) {
- GetAssembler()->bsrl(x86::Register(x86::EDI), x86::Address(
- x86::Register(x86::EDI), x86::Register(x86::EBX), x86::TIMES_4, 12));
- const char* expected =
- "bsrl 0xc(%EDI,%EBX,4), %EDI\n";
-
- DriverStr(expected, "bsrl_address");
+ DriverStr(RepeatRA(&x86::X86Assembler::bsrl, "bsrl {mem}, %{reg}"), "bsrl_address");
}
TEST_F(AssemblerX86Test, Popcntl) {
@@ -322,26 +350,18 @@
}
TEST_F(AssemblerX86Test, PopcntlAddress) {
- GetAssembler()->popcntl(x86::Register(x86::EDI), x86::Address(
- x86::Register(x86::EDI), x86::Register(x86::EBX), x86::TIMES_4, 12));
- const char* expected =
- "popcntl 0xc(%EDI,%EBX,4), %EDI\n";
-
- DriverStr(expected, "popcntl_address");
+ DriverStr(RepeatRA(&x86::X86Assembler::popcntl, "popcntl {mem}, %{reg}"), "popcntl_address");
}
// Rorl only allows CL as the shift count.
std::string rorl_fn(AssemblerX86Test::Base* assembler_test, x86::X86Assembler* assembler) {
std::ostringstream str;
-
std::vector<x86::Register*> registers = assembler_test->GetRegisters();
-
x86::Register shifter(x86::ECX);
for (auto reg : registers) {
assembler->rorl(*reg, shifter);
str << "rorl %cl, %" << assembler_test->GetRegisterName(*reg) << "\n";
}
-
return str.str();
}
@@ -356,15 +376,12 @@
// Roll only allows CL as the shift count.
std::string roll_fn(AssemblerX86Test::Base* assembler_test, x86::X86Assembler* assembler) {
std::ostringstream str;
-
std::vector<x86::Register*> registers = assembler_test->GetRegisters();
-
x86::Register shifter(x86::ECX);
for (auto reg : registers) {
assembler->roll(*reg, shifter);
str << "roll %cl, %" << assembler_test->GetRegisterName(*reg) << "\n";
}
-
return str.str();
}
@@ -385,41 +402,29 @@
}
TEST_F(AssemblerX86Test, ComissAddr) {
- GetAssembler()->comiss(x86::XmmRegister(x86::XMM0), x86::Address(x86::EAX, 0));
- const char* expected = "comiss 0(%EAX), %xmm0\n";
- DriverStr(expected, "comiss");
+ DriverStr(RepeatFA(&x86::X86Assembler::comiss, "comiss {mem}, %{reg}"), "comiss");
}
TEST_F(AssemblerX86Test, UComissAddr) {
- GetAssembler()->ucomiss(x86::XmmRegister(x86::XMM0), x86::Address(x86::EAX, 0));
- const char* expected = "ucomiss 0(%EAX), %xmm0\n";
- DriverStr(expected, "ucomiss");
+ DriverStr(RepeatFA(&x86::X86Assembler::ucomiss, "ucomiss {mem}, %{reg}"), "ucomiss");
}
TEST_F(AssemblerX86Test, ComisdAddr) {
- GetAssembler()->comisd(x86::XmmRegister(x86::XMM0), x86::Address(x86::EAX, 0));
- const char* expected = "comisd 0(%EAX), %xmm0\n";
- DriverStr(expected, "comisd");
+ DriverStr(RepeatFA(&x86::X86Assembler::comisd, "comisd {mem}, %{reg}"), "comisd");
}
TEST_F(AssemblerX86Test, UComisdAddr) {
- GetAssembler()->ucomisd(x86::XmmRegister(x86::XMM0), x86::Address(x86::EAX, 0));
- const char* expected = "ucomisd 0(%EAX), %xmm0\n";
- DriverStr(expected, "ucomisd");
+ DriverStr(RepeatFA(&x86::X86Assembler::ucomisd, "ucomisd {mem}, %{reg}"), "ucomisd");
}
TEST_F(AssemblerX86Test, RoundSS) {
- GetAssembler()->roundss(
- x86::XmmRegister(x86::XMM0), x86::XmmRegister(x86::XMM1), x86::Immediate(1));
- const char* expected = "roundss $1, %xmm1, %xmm0\n";
- DriverStr(expected, "roundss");
+ DriverStr(RepeatFFI(&x86::X86Assembler::roundss, 1U,
+ "roundss ${imm}, %{reg2}, %{reg1}"), "roundss");
}
TEST_F(AssemblerX86Test, RoundSD) {
- GetAssembler()->roundsd(
- x86::XmmRegister(x86::XMM0), x86::XmmRegister(x86::XMM1), x86::Immediate(1));
- const char* expected = "roundsd $1, %xmm1, %xmm0\n";
- DriverStr(expected, "roundsd");
+ DriverStr(RepeatFFI(&x86::X86Assembler::roundsd, 1U,
+ "roundsd ${imm}, %{reg2}, %{reg1}"), "roundsd");
}
TEST_F(AssemblerX86Test, CmovlAddress) {
@@ -433,110 +438,75 @@
"cmovzl 0xc(%EDI,%EBX,4), %eax\n"
"cmovnzl 0xc(%ESI,%EBX,4), %edi\n"
"cmovzl 0xc(%EDI,%EAX,4), %edi\n";
-
DriverStr(expected, "cmovl_address");
}
TEST_F(AssemblerX86Test, TestbAddressImmediate) {
- GetAssembler()->testb(
- x86::Address(x86::Register(x86::EDI), x86::Register(x86::EBX), x86::TIMES_4, 12),
- x86::Immediate(1));
- GetAssembler()->testb(
- x86::Address(x86::Register(x86::ESP), FrameOffset(7)),
- x86::Immediate(-128));
- GetAssembler()->testb(
- x86::Address(x86::Register(x86::EBX), MemberOffset(130)),
- x86::Immediate(127));
- const char* expected =
- "testb $1, 0xc(%EDI,%EBX,4)\n"
- "testb $-128, 0x7(%ESP)\n"
- "testb $127, 0x82(%EBX)\n";
-
- DriverStr(expected, "TestbAddressImmediate");
+ DriverStr(RepeatAI(&x86::X86Assembler::testb, /*imm_bytes*/ 1U, "testb ${imm}, {mem}"), "testb");
}
TEST_F(AssemblerX86Test, TestlAddressImmediate) {
- GetAssembler()->testl(
- x86::Address(x86::Register(x86::EDI), x86::Register(x86::EBX), x86::TIMES_4, 12),
- x86::Immediate(1));
- GetAssembler()->testl(
- x86::Address(x86::Register(x86::ESP), FrameOffset(7)),
- x86::Immediate(-100000));
- GetAssembler()->testl(
- x86::Address(x86::Register(x86::EBX), MemberOffset(130)),
- x86::Immediate(77777777));
- const char* expected =
- "testl $1, 0xc(%EDI,%EBX,4)\n"
- "testl $-100000, 0x7(%ESP)\n"
- "testl $77777777, 0x82(%EBX)\n";
-
- DriverStr(expected, "TestlAddressImmediate");
+ DriverStr(RepeatAI(&x86::X86Assembler::testl, /*imm_bytes*/ 4U, "testl ${imm}, {mem}"), "testl");
}
TEST_F(AssemblerX86Test, Movaps) {
DriverStr(RepeatFF(&x86::X86Assembler::movaps, "movaps %{reg2}, %{reg1}"), "movaps");
}
-TEST_F(AssemblerX86Test, MovapsAddr) {
- GetAssembler()->movaps(x86::XmmRegister(x86::XMM0), x86::Address(x86::Register(x86::ESP), 4));
- GetAssembler()->movaps(x86::Address(x86::Register(x86::ESP), 2), x86::XmmRegister(x86::XMM1));
- const char* expected =
- "movaps 0x4(%ESP), %xmm0\n"
- "movaps %xmm1, 0x2(%ESP)\n";
- DriverStr(expected, "movaps_address");
+TEST_F(AssemblerX86Test, MovapsLoad) {
+ DriverStr(RepeatFA(&x86::X86Assembler::movaps, "movaps {mem}, %{reg}"), "movaps_load");
}
-TEST_F(AssemblerX86Test, MovupsAddr) {
- GetAssembler()->movups(x86::XmmRegister(x86::XMM0), x86::Address(x86::Register(x86::ESP), 4));
- GetAssembler()->movups(x86::Address(x86::Register(x86::ESP), 2), x86::XmmRegister(x86::XMM1));
- const char* expected =
- "movups 0x4(%ESP), %xmm0\n"
- "movups %xmm1, 0x2(%ESP)\n";
- DriverStr(expected, "movups_address");
+TEST_F(AssemblerX86Test, MovapsStore) {
+ DriverStr(RepeatAF(&x86::X86Assembler::movaps, "movaps %{reg}, {mem}"), "movaps_store");
+}
+
+TEST_F(AssemblerX86Test, MovupsLoad) {
+ DriverStr(RepeatFA(&x86::X86Assembler::movups, "movups {mem}, %{reg}"), "movups_load");
+}
+
+TEST_F(AssemblerX86Test, MovupsStore) {
+ DriverStr(RepeatAF(&x86::X86Assembler::movups, "movups %{reg}, {mem}"), "movups_store");
}
TEST_F(AssemblerX86Test, Movapd) {
DriverStr(RepeatFF(&x86::X86Assembler::movapd, "movapd %{reg2}, %{reg1}"), "movapd");
}
-TEST_F(AssemblerX86Test, MovapdAddr) {
- GetAssembler()->movapd(x86::XmmRegister(x86::XMM0), x86::Address(x86::Register(x86::ESP), 4));
- GetAssembler()->movapd(x86::Address(x86::Register(x86::ESP), 2), x86::XmmRegister(x86::XMM1));
- const char* expected =
- "movapd 0x4(%ESP), %xmm0\n"
- "movapd %xmm1, 0x2(%ESP)\n";
- DriverStr(expected, "movapd_address");
+TEST_F(AssemblerX86Test, MovapdLoad) {
+ DriverStr(RepeatFA(&x86::X86Assembler::movapd, "movapd {mem}, %{reg}"), "movapd_load");
}
-TEST_F(AssemblerX86Test, MovupdAddr) {
- GetAssembler()->movupd(x86::XmmRegister(x86::XMM0), x86::Address(x86::Register(x86::ESP), 4));
- GetAssembler()->movupd(x86::Address(x86::Register(x86::ESP), 2), x86::XmmRegister(x86::XMM1));
- const char* expected =
- "movupd 0x4(%ESP), %xmm0\n"
- "movupd %xmm1, 0x2(%ESP)\n";
- DriverStr(expected, "movupd_address");
+TEST_F(AssemblerX86Test, MovapdStore) {
+ DriverStr(RepeatAF(&x86::X86Assembler::movapd, "movapd %{reg}, {mem}"), "movapd_store");
+}
+
+TEST_F(AssemblerX86Test, MovupdLoad) {
+ DriverStr(RepeatFA(&x86::X86Assembler::movupd, "movupd {mem}, %{reg}"), "movupd_load");
+}
+
+TEST_F(AssemblerX86Test, MovupdStore) {
+ DriverStr(RepeatAF(&x86::X86Assembler::movupd, "movupd %{reg}, {mem}"), "movupd_store");
}
TEST_F(AssemblerX86Test, Movdqa) {
DriverStr(RepeatFF(&x86::X86Assembler::movdqa, "movdqa %{reg2}, %{reg1}"), "movdqa");
}
-TEST_F(AssemblerX86Test, MovdqaAddr) {
- GetAssembler()->movdqa(x86::XmmRegister(x86::XMM0), x86::Address(x86::Register(x86::ESP), 4));
- GetAssembler()->movdqa(x86::Address(x86::Register(x86::ESP), 2), x86::XmmRegister(x86::XMM1));
- const char* expected =
- "movdqa 0x4(%ESP), %xmm0\n"
- "movdqa %xmm1, 0x2(%ESP)\n";
- DriverStr(expected, "movdqa_address");
+TEST_F(AssemblerX86Test, MovdqaLoad) {
+ DriverStr(RepeatFA(&x86::X86Assembler::movdqa, "movdqa {mem}, %{reg}"), "movdqa_load");
}
-TEST_F(AssemblerX86Test, MovdquAddr) {
- GetAssembler()->movdqu(x86::XmmRegister(x86::XMM0), x86::Address(x86::Register(x86::ESP), 4));
- GetAssembler()->movdqu(x86::Address(x86::Register(x86::ESP), 2), x86::XmmRegister(x86::XMM1));
- const char* expected =
- "movdqu 0x4(%ESP), %xmm0\n"
- "movdqu %xmm1, 0x2(%ESP)\n";
- DriverStr(expected, "movdqu_address");
+TEST_F(AssemblerX86Test, MovdqaStore) {
+ DriverStr(RepeatAF(&x86::X86Assembler::movdqa, "movdqa %{reg}, {mem}"), "movdqa_store");
+}
+
+TEST_F(AssemblerX86Test, MovdquLoad) {
+ DriverStr(RepeatFA(&x86::X86Assembler::movdqu, "movdqu {mem}, %{reg}"), "movdqu_load");
+}
+
+TEST_F(AssemblerX86Test, MovdquStore) {
+ DriverStr(RepeatAF(&x86::X86Assembler::movdqu, "movdqu %{reg}, {mem}"), "movdqu_store");
}
TEST_F(AssemblerX86Test, AddPS) {
@@ -901,7 +871,6 @@
"jecxz 1f\n"
"addl 4(%ESP),%EDI\n"
"1:\n";
-
DriverStr(expected, "jecxz");
}
@@ -923,14 +892,11 @@
"addl 4(%ESP),%EDI\n"
"2: jne 1b\n"
"jmp 1b\n";
-
DriverStr(expected, "near_label");
}
TEST_F(AssemblerX86Test, Cmpb) {
- GetAssembler()->cmpb(x86::Address(x86::EDI, 128), x86::Immediate(0));
- const char* expected = "cmpb $0, 128(%EDI)\n";
- DriverStr(expected, "cmpb");
+ DriverStr(RepeatAI(&x86::X86Assembler::cmpb, /*imm_bytes*/ 1U, "cmpb ${imm}, {mem}"), "cmpb");
}
} // namespace art
diff --git a/compiler/utils/x86_64/assembler_x86_64_test.cc b/compiler/utils/x86_64/assembler_x86_64_test.cc
index 29de925..3e6110d 100644
--- a/compiler/utils/x86_64/assembler_x86_64_test.cc
+++ b/compiler/utils/x86_64/assembler_x86_64_test.cc
@@ -130,11 +130,17 @@
// Test fixture.
//
-class AssemblerX86_64Test : public AssemblerTest<x86_64::X86_64Assembler, x86_64::CpuRegister,
- x86_64::XmmRegister, x86_64::Immediate> {
+class AssemblerX86_64Test : public AssemblerTest<x86_64::X86_64Assembler,
+ x86_64::Address,
+ x86_64::CpuRegister,
+ x86_64::XmmRegister,
+ x86_64::Immediate> {
public:
- typedef AssemblerTest<x86_64::X86_64Assembler, x86_64::CpuRegister,
- x86_64::XmmRegister, x86_64::Immediate> Base;
+ typedef AssemblerTest<x86_64::X86_64Assembler,
+ x86_64::Address,
+ x86_64::CpuRegister,
+ x86_64::XmmRegister,
+ x86_64::Immediate> Base;
protected:
// Get the typically used name for this architecture, e.g., aarch64, x86-64, ...
@@ -241,6 +247,11 @@
STLDeleteElements(&fp_registers_);
}
+ std::vector<x86_64::Address> GetAddresses() {
+ UNIMPLEMENTED(FATAL) << "Feature not implemented yet";
+ UNREACHABLE();
+ }
+
std::vector<x86_64::CpuRegister*> GetRegisters() OVERRIDE {
return registers_;
}