namespace art {
+// Helper for a constexpr string length.
+constexpr size_t ConstexprStrLen(char const* str, size_t count = 0) {
+ return ('\0' == str[0]) ? count : ConstexprStrLen(str+1, count+1);
+}
+
// Use a glocal static variable to keep the same name for all test data. Else we'll just spam the
// temp directory.
static std::string tmpnam_;
-template<typename Ass, typename Reg, typename Imm>
+template<typename Ass, typename Reg, typename FPReg, typename Imm>
class AssemblerTest : public testing::Test {
public:
+ enum class RegisterView { // private
+ kUsePrimaryName,
+ kUseSecondaryName
+ };
+
Ass* GetAssembler() {
return assembler_.get();
}
- typedef std::string (*TestFn)(Ass* assembler);
+ typedef std::string (*TestFn)(AssemblerTest* assembler_test, Ass* assembler);
void DriverFn(TestFn f, std::string test_name) {
- Driver(f(assembler_.get()), test_name);
+ Driver(f(this, assembler_.get()), test_name);
}
// This driver assumes the assembler has already been called.
}
std::string RepeatR(void (Ass::*f)(Reg), std::string fmt) {
- const std::vector<Reg*> registers = GetRegisters();
- std::string str;
- for (auto reg : registers) {
- (assembler_.get()->*f)(*reg);
- std::string base = fmt;
-
- size_t reg_index = base.find("{reg}");
- if (reg_index != std::string::npos) {
- std::ostringstream sreg;
- sreg << *reg;
- std::string reg_string = sreg.str();
- base.replace(reg_index, 5, reg_string);
- }
+ return RepeatTemplatedRegister<Reg>(f,
+ GetRegisters(),
+ &AssemblerTest::GetRegName<RegisterView::kUsePrimaryName>,
+ fmt);
+ }
- if (str.size() > 0) {
- str += "\n";
- }
- str += base;
- }
- // Add a newline at the end.
- str += "\n";
- return str;
+ std::string Repeatr(void (Ass::*f)(Reg), std::string fmt) {
+ return RepeatTemplatedRegister<Reg>(f,
+ GetRegisters(),
+ &AssemblerTest::GetRegName<RegisterView::kUseSecondaryName>,
+ fmt);
}
std::string RepeatRR(void (Ass::*f)(Reg, Reg), std::string fmt) {
- const std::vector<Reg*> registers = GetRegisters();
- std::string str;
- for (auto reg1 : registers) {
- for (auto reg2 : registers) {
- (assembler_.get()->*f)(*reg1, *reg2);
- std::string base = fmt;
-
- size_t reg1_index = base.find("{reg1}");
- if (reg1_index != std::string::npos) {
- std::ostringstream sreg;
- sreg << *reg1;
- std::string reg_string = sreg.str();
- base.replace(reg1_index, 6, reg_string);
- }
+ return RepeatTemplatedRegisters<Reg, Reg>(f,
+ GetRegisters(),
+ GetRegisters(),
+ &AssemblerTest::GetRegName<RegisterView::kUsePrimaryName>,
+ &AssemblerTest::GetRegName<RegisterView::kUsePrimaryName>,
+ fmt);
+ }
- size_t reg2_index = base.find("{reg2}");
- if (reg2_index != std::string::npos) {
- std::ostringstream sreg;
- sreg << *reg2;
- std::string reg_string = sreg.str();
- base.replace(reg2_index, 6, reg_string);
- }
+ std::string Repeatrr(void (Ass::*f)(Reg, Reg), std::string fmt) {
+ return RepeatTemplatedRegisters<Reg, Reg>(f,
+ GetRegisters(),
+ GetRegisters(),
+ &AssemblerTest::GetRegName<RegisterView::kUseSecondaryName>,
+ &AssemblerTest::GetRegName<RegisterView::kUseSecondaryName>,
+ fmt);
+ }
- if (str.size() > 0) {
- str += "\n";
- }
- str += base;
- }
- }
- // Add a newline at the end.
- str += "\n";
- return str;
+ std::string RepeatRr(void (Ass::*f)(Reg, Reg), std::string fmt) {
+ return RepeatTemplatedRegisters<Reg, Reg>(f,
+ GetRegisters(),
+ GetRegisters(),
+ &AssemblerTest::GetRegName<RegisterView::kUsePrimaryName>,
+ &AssemblerTest::GetRegName<RegisterView::kUseSecondaryName>,
+ fmt);
}
std::string RepeatRI(void (Ass::*f)(Reg, const Imm&), size_t imm_bytes, std::string fmt) {
- const std::vector<Reg*> registers = GetRegisters();
- std::string str;
- std::vector<int64_t> imms = CreateImmediateValues(imm_bytes);
- for (auto reg : registers) {
- for (int64_t imm : imms) {
- Imm new_imm = CreateImmediate(imm);
- (assembler_.get()->*f)(*reg, new_imm);
- std::string base = fmt;
+ return RepeatRegisterImm<RegisterView::kUsePrimaryName>(f, imm_bytes, fmt);
+ }
- size_t reg_index = base.find("{reg}");
- if (reg_index != std::string::npos) {
- std::ostringstream sreg;
- sreg << *reg;
- std::string reg_string = sreg.str();
- base.replace(reg_index, 5, reg_string);
- }
+ std::string Repeatri(void (Ass::*f)(Reg, const Imm&), size_t imm_bytes, std::string fmt) {
+ return RepeatRegisterImm<RegisterView::kUseSecondaryName>(f, imm_bytes, fmt);
+ }
- size_t imm_index = base.find("{imm}");
- if (imm_index != std::string::npos) {
- std::ostringstream sreg;
- sreg << imm;
- std::string imm_string = sreg.str();
- base.replace(imm_index, 5, imm_string);
- }
+ std::string RepeatFF(void (Ass::*f)(FPReg, FPReg), std::string fmt) {
+ return RepeatTemplatedRegisters<FPReg, FPReg>(f,
+ GetFPRegisters(),
+ GetFPRegisters(),
+ &AssemblerTest::GetFPRegName,
+ &AssemblerTest::GetFPRegName,
+ fmt);
+ }
- if (str.size() > 0) {
- str += "\n";
- }
- str += base;
- }
- }
- // Add a newline at the end.
- str += "\n";
- return str;
+ std::string RepeatFR(void (Ass::*f)(FPReg, Reg), std::string fmt) {
+ return RepeatTemplatedRegisters<FPReg, Reg>(f,
+ GetFPRegisters(),
+ GetRegisters(),
+ &AssemblerTest::GetFPRegName,
+ &AssemblerTest::GetRegName<RegisterView::kUsePrimaryName>,
+ fmt);
+ }
+
+ std::string RepeatFr(void (Ass::*f)(FPReg, Reg), std::string fmt) {
+ return RepeatTemplatedRegisters<FPReg, Reg>(f,
+ GetFPRegisters(),
+ GetRegisters(),
+ &AssemblerTest::GetFPRegName,
+ &AssemblerTest::GetRegName<RegisterView::kUseSecondaryName>,
+ fmt);
+ }
+
+ std::string RepeatRF(void (Ass::*f)(Reg, FPReg), std::string fmt) {
+ return RepeatTemplatedRegisters<Reg, FPReg>(f,
+ GetRegisters(),
+ GetFPRegisters(),
+ &AssemblerTest::GetRegName<RegisterView::kUsePrimaryName>,
+ &AssemblerTest::GetFPRegName,
+ fmt);
}
- std::string RepeatI(void (Ass::*f)(const Imm&), size_t imm_bytes, std::string fmt) {
+ std::string RepeatrF(void (Ass::*f)(Reg, FPReg), std::string fmt) {
+ return RepeatTemplatedRegisters<Reg, FPReg>(f,
+ GetRegisters(),
+ GetFPRegisters(),
+ &AssemblerTest::GetRegName<RegisterView::kUseSecondaryName>,
+ &AssemblerTest::GetFPRegName,
+ fmt);
+ }
+
+ std::string RepeatI(void (Ass::*f)(const Imm&), size_t imm_bytes, std::string fmt,
+ bool as_uint = false) {
std::string str;
- std::vector<int64_t> imms = CreateImmediateValues(imm_bytes);
+ std::vector<int64_t> imms = CreateImmediateValues(imm_bytes, as_uint);
for (int64_t imm : imms) {
Imm new_imm = CreateImmediate(imm);
(assembler_.get()->*f)(new_imm);
std::string base = fmt;
- size_t imm_index = base.find("{imm}");
+ 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, 5, imm_string);
+ base.replace(imm_index, ConstexprStrLen(IMM_TOKEN), imm_string);
}
if (str.size() > 0) {
return true;
}
+ // The following functions are public so that TestFn can use them...
+
+ virtual std::vector<Reg*> GetRegisters() = 0;
+
+ virtual std::vector<FPReg*> GetFPRegisters() {
+ UNIMPLEMENTED(FATAL) << "Architecture does not support floating-point registers";
+ UNREACHABLE();
+ }
+
+ // Secondary register names are the secondary view on registers, e.g., 32b on 64b systems.
+ virtual std::string GetSecondaryRegisterName(const Reg& reg ATTRIBUTE_UNUSED) {
+ UNIMPLEMENTED(FATAL) << "Architecture does not support secondary registers";
+ UNREACHABLE();
+ }
+
protected:
+ explicit AssemblerTest() {}
+
void SetUp() OVERRIDE {
assembler_.reset(new Ass());
// Override this to set up any architecture-specific things, e.g., register vectors.
virtual void SetUpHelpers() {}
- virtual std::vector<Reg*> GetRegisters() = 0;
-
// Get the typically used name for this architecture, e.g., aarch64, x86_64, ...
virtual std::string GetArchitectureString() = 0;
}
// Create a couple of immediate values up to the number of bytes given.
- virtual std::vector<int64_t> CreateImmediateValues(size_t imm_bytes) {
+ virtual std::vector<int64_t> CreateImmediateValues(size_t imm_bytes, bool as_uint = false) {
std::vector<int64_t> res;
res.push_back(0);
- res.push_back(-1);
+ if (!as_uint) {
+ res.push_back(-1);
+ } else {
+ res.push_back(0xFF);
+ }
res.push_back(0x12);
if (imm_bytes >= 2) {
res.push_back(0x1234);
- res.push_back(-0x1234);
+ if (!as_uint) {
+ res.push_back(-0x1234);
+ } else {
+ res.push_back(0xFFFF);
+ }
if (imm_bytes >= 4) {
res.push_back(0x12345678);
- res.push_back(-0x12345678);
+ if (!as_uint) {
+ res.push_back(-0x12345678);
+ } else {
+ res.push_back(0xFFFFFFFF);
+ }
if (imm_bytes >= 6) {
res.push_back(0x123456789ABC);
- res.push_back(-0x123456789ABC);
+ if (!as_uint) {
+ res.push_back(-0x123456789ABC);
+ }
if (imm_bytes >= 8) {
res.push_back(0x123456789ABCDEF0);
- res.push_back(-0x123456789ABCDEF0);
+ if (!as_uint) {
+ res.push_back(-0x123456789ABCDEF0);
+ } else {
+ res.push_back(0xFFFFFFFFFFFFFFFF);
+ }
}
}
}
// Create an immediate from the specific value.
virtual Imm CreateImmediate(int64_t imm_value) = 0;
+ template <typename RegType>
+ std::string RepeatTemplatedRegister(void (Ass::*f)(RegType),
+ const std::vector<RegType*> registers,
+ std::string (AssemblerTest::*GetName)(const RegType&),
+ std::string fmt) {
+ std::string str;
+ for (auto reg : registers) {
+ (assembler_.get()->*f)(*reg);
+ std::string base = fmt;
+
+ std::string reg_string = (this->*GetName)(*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;
+ }
+
+ template <typename Reg1, typename Reg2>
+ std::string RepeatTemplatedRegisters(void (Ass::*f)(Reg1, Reg2),
+ const std::vector<Reg1*> reg1_registers,
+ const std::vector<Reg2*> reg2_registers,
+ std::string (AssemblerTest::*GetName1)(const Reg1&),
+ std::string (AssemblerTest::*GetName2)(const Reg2&),
+ std::string fmt) {
+ std::string str;
+ for (auto reg1 : reg1_registers) {
+ for (auto reg2 : reg2_registers) {
+ (assembler_.get()->*f)(*reg1, *reg2);
+ std::string base = fmt;
+
+ std::string reg1_string = (this->*GetName1)(*reg1);
+ size_t reg1_index;
+ while ((reg1_index = base.find(REG1_TOKEN)) != std::string::npos) {
+ base.replace(reg1_index, ConstexprStrLen(REG1_TOKEN), reg1_string);
+ }
+
+ std::string reg2_string = (this->*GetName2)(*reg2);
+ size_t reg2_index;
+ while ((reg2_index = base.find(REG2_TOKEN)) != std::string::npos) {
+ base.replace(reg2_index, ConstexprStrLen(REG2_TOKEN), reg2_string);
+ }
+
+ if (str.size() > 0) {
+ str += "\n";
+ }
+ str += base;
+ }
+ }
+ // Add a newline at the end.
+ str += "\n";
+ return str;
+ }
+
private:
+ template <RegisterView kRegView>
+ std::string GetRegName(const Reg& reg) {
+ std::ostringstream sreg;
+ switch (kRegView) {
+ case RegisterView::kUsePrimaryName:
+ sreg << reg;
+ break;
+
+ case RegisterView::kUseSecondaryName:
+ sreg << GetSecondaryRegisterName(reg);
+ break;
+ }
+ return sreg.str();
+ }
+
+ std::string GetFPRegName(const FPReg& reg) {
+ std::ostringstream sreg;
+ sreg << reg;
+ return sreg.str();
+ }
+
+ template <RegisterView kRegView>
+ std::string RepeatRegisterImm(void (Ass::*f)(Reg, const Imm&), size_t imm_bytes,
+ std::string fmt) {
+ const std::vector<Reg*> registers = GetRegisters();
+ std::string str;
+ std::vector<int64_t> imms = CreateImmediateValues(imm_bytes);
+ for (auto reg : registers) {
+ for (int64_t imm : imms) {
+ Imm new_imm = CreateImmediate(imm);
+ (assembler_.get()->*f)(*reg, new_imm);
+ std::string base = fmt;
+
+ std::string reg_string = GetRegName<kRegView>(*reg);
+ size_t reg_index;
+ while ((reg_index = base.find(REG_TOKEN)) != std::string::npos) {
+ base.replace(reg_index, ConstexprStrLen(REG_TOKEN), reg_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;
+ }
+
// Driver() assembles and compares the results. If the results are not equal and we have a
// disassembler, disassemble both and check whether they have the same mnemonics (in which case
// we just warn).
bool result = CompareFiles(data_name + ".dis", as_name + ".dis");
- if (result) {
- std::remove(data_name.c_str());
- std::remove(as_name.c_str());
- std::remove((data_name + ".dis").c_str());
- std::remove((as_name + ".dis").c_str());
- }
+ // If you want to take a look at the differences between the ART assembler and GCC, comment
+ // out the removal code.
+ std::remove(data_name.c_str());
+ std::remove(as_name.c_str());
+ std::remove((data_name + ".dis").c_str());
+ std::remove((as_name + ".dis").c_str());
return result;
}
return tmpnam_;
}
+ static constexpr size_t OBJDUMP_SECTION_LINE_MIN_TOKENS = 6;
+
+ static constexpr const char* REG_TOKEN = "{reg}";
+ static constexpr const char* REG1_TOKEN = "{reg1}";
+ static constexpr const char* REG2_TOKEN = "{reg2}";
+ static constexpr const char* IMM_TOKEN = "{imm}";
+
std::unique_ptr<Ass> assembler_;
std::string resolved_assembler_cmd_;
std::string android_data_;
- static constexpr size_t OBJDUMP_SECTION_LINE_MIN_TOKENS = 6;
+ DISALLOW_COPY_AND_ASSIGN(AssemblerTest);
};
} // namespace art
#include "assembler_x86_64.h"
+#include <inttypes.h>
+#include <map>
+#include <random>
+
#include "base/stl_util.h"
#include "utils/assembler_test.h"
+#include "utils.h"
namespace art {
ASSERT_EQ(static_cast<size_t>(5), buffer.Size());
}
+#ifdef HAVE_ANDROID_OS
+static constexpr size_t kRandomIterations = 1000; // Devices might be puny, don't stress them...
+#else
+static constexpr size_t kRandomIterations = 100000; // Hosts are pretty powerful.
+#endif
+
+TEST(AssemblerX86_64, SignExtension) {
+ // 32bit.
+ for (int32_t i = 0; i < 128; i++) {
+ EXPECT_TRUE(IsInt32(8, i)) << i;
+ }
+ for (int32_t i = 128; i < 255; i++) {
+ EXPECT_FALSE(IsInt32(8, i)) << i;
+ }
+ // Do some higher ones randomly.
+ std::random_device rd;
+ std::default_random_engine e1(rd());
+ std::uniform_int_distribution<int32_t> uniform_dist(256, INT32_MAX);
+ for (size_t i = 0; i < kRandomIterations; i++) {
+ int32_t value = uniform_dist(e1);
+ EXPECT_FALSE(IsInt32(8, value)) << value;
+ }
+
+ // Negative ones.
+ for (int32_t i = -1; i >= -128; i--) {
+ EXPECT_TRUE(IsInt32(8, i)) << i;
+ }
+
+ for (int32_t i = -129; i > -256; i--) {
+ EXPECT_FALSE(IsInt32(8, i)) << i;
+ }
+
+ // Do some lower ones randomly.
+ std::uniform_int_distribution<int32_t> uniform_dist2(INT32_MIN, -256);
+ for (size_t i = 0; i < 100; i++) {
+ int32_t value = uniform_dist2(e1);
+ EXPECT_FALSE(IsInt32(8, value)) << value;
+ }
+
+ // 64bit.
+ for (int64_t i = 0; i < 128; i++) {
+ EXPECT_TRUE(IsInt64(8, i)) << i;
+ }
+ for (int32_t i = 128; i < 255; i++) {
+ EXPECT_FALSE(IsInt64(8, i)) << i;
+ }
+ // Do some higher ones randomly.
+ std::uniform_int_distribution<int64_t> uniform_dist3(256, INT64_MAX);
+ for (size_t i = 0; i < 100; i++) {
+ int64_t value = uniform_dist3(e1);
+ EXPECT_FALSE(IsInt64(8, value)) << value;
+ }
+
+ // Negative ones.
+ for (int64_t i = -1; i >= -128; i--) {
+ EXPECT_TRUE(IsInt64(8, i)) << i;
+ }
+
+ for (int64_t i = -129; i > -256; i--) {
+ EXPECT_FALSE(IsInt64(8, i)) << i;
+ }
+
+ // Do some lower ones randomly.
+ std::uniform_int_distribution<int64_t> uniform_dist4(INT64_MIN, -256);
+ for (size_t i = 0; i < kRandomIterations; i++) {
+ int64_t value = uniform_dist4(e1);
+ EXPECT_FALSE(IsInt64(8, value)) << value;
+ }
+}
+
+struct X86_64CpuRegisterCompare {
+ bool operator()(const x86_64::CpuRegister& a, const x86_64::CpuRegister& b) const {
+ return a.AsRegister() < b.AsRegister();
+ }
+};
+
class AssemblerX86_64Test : public AssemblerTest<x86_64::X86_64Assembler, x86_64::CpuRegister,
- x86_64::Immediate> {
+ x86_64::XmmRegister, x86_64::Immediate> {
+ public:
+ typedef AssemblerTest<x86_64::X86_64Assembler, x86_64::CpuRegister,
+ x86_64::XmmRegister, x86_64::Immediate> Base;
+
protected:
// Get the typically used name for this architecture, e.g., aarch64, x86-64, ...
std::string GetArchitectureString() OVERRIDE {
registers_.push_back(new x86_64::CpuRegister(x86_64::R13));
registers_.push_back(new x86_64::CpuRegister(x86_64::R14));
registers_.push_back(new x86_64::CpuRegister(x86_64::R15));
+
+ secondary_register_names_.emplace(x86_64::CpuRegister(x86_64::RAX), "eax");
+ secondary_register_names_.emplace(x86_64::CpuRegister(x86_64::RBX), "ebx");
+ secondary_register_names_.emplace(x86_64::CpuRegister(x86_64::RCX), "ecx");
+ secondary_register_names_.emplace(x86_64::CpuRegister(x86_64::RDX), "edx");
+ secondary_register_names_.emplace(x86_64::CpuRegister(x86_64::RBP), "ebp");
+ secondary_register_names_.emplace(x86_64::CpuRegister(x86_64::RSP), "esp");
+ secondary_register_names_.emplace(x86_64::CpuRegister(x86_64::RSI), "esi");
+ secondary_register_names_.emplace(x86_64::CpuRegister(x86_64::RDI), "edi");
+ secondary_register_names_.emplace(x86_64::CpuRegister(x86_64::R8), "r8d");
+ secondary_register_names_.emplace(x86_64::CpuRegister(x86_64::R9), "r9d");
+ secondary_register_names_.emplace(x86_64::CpuRegister(x86_64::R10), "r10d");
+ secondary_register_names_.emplace(x86_64::CpuRegister(x86_64::R11), "r11d");
+ secondary_register_names_.emplace(x86_64::CpuRegister(x86_64::R12), "r12d");
+ secondary_register_names_.emplace(x86_64::CpuRegister(x86_64::R13), "r13d");
+ secondary_register_names_.emplace(x86_64::CpuRegister(x86_64::R14), "r14d");
+ secondary_register_names_.emplace(x86_64::CpuRegister(x86_64::R15), "r15d");
+
+ fp_registers_.push_back(new x86_64::XmmRegister(x86_64::XMM0));
+ fp_registers_.push_back(new x86_64::XmmRegister(x86_64::XMM1));
+ fp_registers_.push_back(new x86_64::XmmRegister(x86_64::XMM2));
+ fp_registers_.push_back(new x86_64::XmmRegister(x86_64::XMM3));
+ fp_registers_.push_back(new x86_64::XmmRegister(x86_64::XMM4));
+ fp_registers_.push_back(new x86_64::XmmRegister(x86_64::XMM5));
+ fp_registers_.push_back(new x86_64::XmmRegister(x86_64::XMM6));
+ fp_registers_.push_back(new x86_64::XmmRegister(x86_64::XMM7));
+ fp_registers_.push_back(new x86_64::XmmRegister(x86_64::XMM8));
+ fp_registers_.push_back(new x86_64::XmmRegister(x86_64::XMM9));
+ fp_registers_.push_back(new x86_64::XmmRegister(x86_64::XMM10));
+ fp_registers_.push_back(new x86_64::XmmRegister(x86_64::XMM11));
+ fp_registers_.push_back(new x86_64::XmmRegister(x86_64::XMM12));
+ fp_registers_.push_back(new x86_64::XmmRegister(x86_64::XMM13));
+ fp_registers_.push_back(new x86_64::XmmRegister(x86_64::XMM14));
+ fp_registers_.push_back(new x86_64::XmmRegister(x86_64::XMM15));
}
}
void TearDown() OVERRIDE {
AssemblerTest::TearDown();
STLDeleteElements(®isters_);
+ STLDeleteElements(&fp_registers_);
}
std::vector<x86_64::CpuRegister*> GetRegisters() OVERRIDE {
return registers_;
}
+ std::vector<x86_64::XmmRegister*> GetFPRegisters() OVERRIDE {
+ return fp_registers_;
+ }
+
x86_64::Immediate CreateImmediate(int64_t imm_value) OVERRIDE {
return x86_64::Immediate(imm_value);
}
+ std::string GetSecondaryRegisterName(const x86_64::CpuRegister& reg) OVERRIDE {
+ CHECK(secondary_register_names_.find(reg) != secondary_register_names_.end());
+ return secondary_register_names_[reg];
+ }
+
private:
std::vector<x86_64::CpuRegister*> registers_;
+ std::map<x86_64::CpuRegister, std::string, X86_64CpuRegisterCompare> secondary_register_names_;
+
+ std::vector<x86_64::XmmRegister*> fp_registers_;
};
DriverStr(RepeatI(&x86_64::X86_64Assembler::pushq, 4U, "pushq ${imm}"), "pushqi");
}
-
TEST_F(AssemblerX86_64Test, MovqRegs) {
DriverStr(RepeatRR(&x86_64::X86_64Assembler::movq, "movq %{reg2}, %{reg1}"), "movq");
}
DriverStr(RepeatRI(&x86_64::X86_64Assembler::movq, 8U, "movq ${imm}, %{reg}"), "movqi");
}
+TEST_F(AssemblerX86_64Test, MovlRegs) {
+ DriverStr(Repeatrr(&x86_64::X86_64Assembler::movl, "mov %{reg2}, %{reg1}"), "movl");
+}
+
+TEST_F(AssemblerX86_64Test, MovlImm) {
+ DriverStr(Repeatri(&x86_64::X86_64Assembler::movl, 4U, "mov ${imm}, %{reg}"), "movli");
+}
TEST_F(AssemblerX86_64Test, AddqRegs) {
DriverStr(RepeatRR(&x86_64::X86_64Assembler::addq, "addq %{reg2}, %{reg1}"), "addq");
DriverStr(RepeatRI(&x86_64::X86_64Assembler::addq, 4U, "addq ${imm}, %{reg}"), "addqi");
}
+TEST_F(AssemblerX86_64Test, AddlRegs) {
+ DriverStr(Repeatrr(&x86_64::X86_64Assembler::addl, "add %{reg2}, %{reg1}"), "addl");
+}
+
+TEST_F(AssemblerX86_64Test, AddlImm) {
+ DriverStr(Repeatri(&x86_64::X86_64Assembler::addl, 4U, "add ${imm}, %{reg}"), "addli");
+}
+
TEST_F(AssemblerX86_64Test, ImulqRegs) {
DriverStr(RepeatRR(&x86_64::X86_64Assembler::imulq, "imulq %{reg2}, %{reg1}"), "imulq");
}
+TEST_F(AssemblerX86_64Test, ImulqImm) {
+ DriverStr(RepeatRI(&x86_64::X86_64Assembler::imulq, 4U, "imulq ${imm}, %{reg}, %{reg}"),
+ "imulqi");
+}
+
+TEST_F(AssemblerX86_64Test, ImullRegs) {
+ DriverStr(Repeatrr(&x86_64::X86_64Assembler::imull, "imul %{reg2}, %{reg1}"), "imull");
+}
+
+TEST_F(AssemblerX86_64Test, ImullImm) {
+ DriverStr(Repeatri(&x86_64::X86_64Assembler::imull, 4U, "imull ${imm}, %{reg}, %{reg}"),
+ "imulli");
+}
+
+TEST_F(AssemblerX86_64Test, Mull) {
+ DriverStr(Repeatr(&x86_64::X86_64Assembler::mull, "mull %{reg}"), "mull");
+}
+
TEST_F(AssemblerX86_64Test, SubqRegs) {
DriverStr(RepeatRR(&x86_64::X86_64Assembler::subq, "subq %{reg2}, %{reg1}"), "subq");
}
DriverStr(RepeatRI(&x86_64::X86_64Assembler::subq, 4U, "subq ${imm}, %{reg}"), "subqi");
}
+TEST_F(AssemblerX86_64Test, SublRegs) {
+ DriverStr(Repeatrr(&x86_64::X86_64Assembler::subl, "sub %{reg2}, %{reg1}"), "subl");
+}
+
+TEST_F(AssemblerX86_64Test, SublImm) {
+ DriverStr(Repeatri(&x86_64::X86_64Assembler::subl, 4U, "sub ${imm}, %{reg}"), "subli");
+}
+
+// Shll only allows CL as the shift register.
+std::string shll_fn(AssemblerX86_64Test::Base* assembler_test, x86_64::X86_64Assembler* assembler) {
+ std::ostringstream str;
+
+ std::vector<x86_64::CpuRegister*> registers = assembler_test->GetRegisters();
+
+ x86_64::CpuRegister shifter(x86_64::RCX);
+ for (auto reg : registers) {
+ assembler->shll(*reg, shifter);
+ str << "shll %cl, %" << assembler_test->GetSecondaryRegisterName(*reg) << "\n";
+ }
+
+ return str.str();
+}
+
+TEST_F(AssemblerX86_64Test, ShllReg) {
+ DriverFn(&shll_fn, "shll");
+}
+
+TEST_F(AssemblerX86_64Test, ShllImm) {
+ DriverStr(Repeatri(&x86_64::X86_64Assembler::shll, 1U, "shll ${imm}, %{reg}"), "shlli");
+}
+
+// Shrl only allows CL as the shift register.
+std::string shrl_fn(AssemblerX86_64Test::Base* assembler_test, x86_64::X86_64Assembler* assembler) {
+ std::ostringstream str;
+
+ std::vector<x86_64::CpuRegister*> registers = assembler_test->GetRegisters();
+
+ x86_64::CpuRegister shifter(x86_64::RCX);
+ for (auto reg : registers) {
+ assembler->shrl(*reg, shifter);
+ str << "shrl %cl, %" << assembler_test->GetSecondaryRegisterName(*reg) << "\n";
+ }
+
+ return str.str();
+}
+
+TEST_F(AssemblerX86_64Test, ShrlReg) {
+ DriverFn(&shrl_fn, "shrl");
+}
+
+TEST_F(AssemblerX86_64Test, ShrlImm) {
+ DriverStr(Repeatri(&x86_64::X86_64Assembler::shrl, 1U, "shrl ${imm}, %{reg}"), "shrli");
+}
+
+// Sarl only allows CL as the shift register.
+std::string sarl_fn(AssemblerX86_64Test::Base* assembler_test, x86_64::X86_64Assembler* assembler) {
+ std::ostringstream str;
+
+ std::vector<x86_64::CpuRegister*> registers = assembler_test->GetRegisters();
+
+ x86_64::CpuRegister shifter(x86_64::RCX);
+ for (auto reg : registers) {
+ assembler->sarl(*reg, shifter);
+ str << "sarl %cl, %" << assembler_test->GetSecondaryRegisterName(*reg) << "\n";
+ }
+
+ return str.str();
+}
+
+TEST_F(AssemblerX86_64Test, SarlReg) {
+ DriverFn(&sarl_fn, "sarl");
+}
+
+TEST_F(AssemblerX86_64Test, SarlImm) {
+ DriverStr(Repeatri(&x86_64::X86_64Assembler::sarl, 1U, "sarl ${imm}, %{reg}"), "sarli");
+}
TEST_F(AssemblerX86_64Test, CmpqRegs) {
DriverStr(RepeatRR(&x86_64::X86_64Assembler::cmpq, "cmpq %{reg2}, %{reg1}"), "cmpq");
}
+TEST_F(AssemblerX86_64Test, CmpqImm) {
+ DriverStr(RepeatRI(&x86_64::X86_64Assembler::cmpq, 4U /* cmpq only supports 32b imm */,
+ "cmpq ${imm}, %{reg}"), "cmpqi");
+}
+
+TEST_F(AssemblerX86_64Test, CmplRegs) {
+ DriverStr(Repeatrr(&x86_64::X86_64Assembler::cmpl, "cmp %{reg2}, %{reg1}"), "cmpl");
+}
+
+TEST_F(AssemblerX86_64Test, CmplImm) {
+ DriverStr(Repeatri(&x86_64::X86_64Assembler::cmpl, 4U, "cmpl ${imm}, %{reg}"), "cmpli");
+}
+
+TEST_F(AssemblerX86_64Test, Testl) {
+ // Note: uses different order for GCC than usual. This makes GCC happy, and doesn't have an
+ // impact on functional correctness.
+ DriverStr(Repeatrr(&x86_64::X86_64Assembler::testl, "testl %{reg1}, %{reg2}"), "testl");
+}
+
+TEST_F(AssemblerX86_64Test, Negq) {
+ DriverStr(RepeatR(&x86_64::X86_64Assembler::negq, "negq %{reg}"), "negq");
+}
+
+TEST_F(AssemblerX86_64Test, Negl) {
+ DriverStr(Repeatr(&x86_64::X86_64Assembler::negl, "negl %{reg}"), "negl");
+}
+
+TEST_F(AssemblerX86_64Test, Notq) {
+ DriverStr(RepeatR(&x86_64::X86_64Assembler::notq, "notq %{reg}"), "notq");
+}
+
+TEST_F(AssemblerX86_64Test, Notl) {
+ DriverStr(Repeatr(&x86_64::X86_64Assembler::notl, "notl %{reg}"), "notl");
+}
+
+TEST_F(AssemblerX86_64Test, AndqRegs) {
+ DriverStr(RepeatRR(&x86_64::X86_64Assembler::andq, "andq %{reg2}, %{reg1}"), "andq");
+}
+
+TEST_F(AssemblerX86_64Test, AndqImm) {
+ DriverStr(RepeatRI(&x86_64::X86_64Assembler::andq, 4U /* andq only supports 32b imm */,
+ "andq ${imm}, %{reg}"), "andqi");
+}
+
+TEST_F(AssemblerX86_64Test, AndlRegs) {
+ DriverStr(Repeatrr(&x86_64::X86_64Assembler::andl, "andl %{reg2}, %{reg1}"), "andl");
+}
+
+TEST_F(AssemblerX86_64Test, AndlImm) {
+ DriverStr(Repeatri(&x86_64::X86_64Assembler::andl, 4U, "andl ${imm}, %{reg}"), "andli");
+}
+
+TEST_F(AssemblerX86_64Test, OrqRegs) {
+ DriverStr(RepeatRR(&x86_64::X86_64Assembler::orq, "orq %{reg2}, %{reg1}"), "orq");
+}
+
+TEST_F(AssemblerX86_64Test, OrlRegs) {
+ DriverStr(Repeatrr(&x86_64::X86_64Assembler::orl, "orl %{reg2}, %{reg1}"), "orl");
+}
+
+TEST_F(AssemblerX86_64Test, OrlImm) {
+ DriverStr(Repeatri(&x86_64::X86_64Assembler::orl, 4U, "orl ${imm}, %{reg}"), "orli");
+}
+
+TEST_F(AssemblerX86_64Test, XorqRegs) {
+ DriverStr(RepeatRR(&x86_64::X86_64Assembler::xorq, "xorq %{reg2}, %{reg1}"), "xorq");
+}
TEST_F(AssemblerX86_64Test, XorqImm) {
DriverStr(RepeatRI(&x86_64::X86_64Assembler::xorq, 4U, "xorq ${imm}, %{reg}"), "xorqi");
}
-TEST_F(AssemblerX86_64Test, Movaps) {
- GetAssembler()->movaps(x86_64::XmmRegister(x86_64::XMM0), x86_64::XmmRegister(x86_64::XMM8));
- DriverStr("movaps %xmm8, %xmm0", "movaps");
-}
-
-TEST_F(AssemblerX86_64Test, Movd) {
- GetAssembler()->movd(x86_64::XmmRegister(x86_64::XMM0), x86_64::CpuRegister(x86_64::R11));
- GetAssembler()->movd(x86_64::XmmRegister(x86_64::XMM0), x86_64::CpuRegister(x86_64::RAX));
- GetAssembler()->movd(x86_64::XmmRegister(x86_64::XMM8), x86_64::CpuRegister(x86_64::R11));
- GetAssembler()->movd(x86_64::XmmRegister(x86_64::XMM8), x86_64::CpuRegister(x86_64::RAX));
- GetAssembler()->movd(x86_64::CpuRegister(x86_64::R11), x86_64::XmmRegister(x86_64::XMM0));
- GetAssembler()->movd(x86_64::CpuRegister(x86_64::RAX), x86_64::XmmRegister(x86_64::XMM0));
- GetAssembler()->movd(x86_64::CpuRegister(x86_64::R11), x86_64::XmmRegister(x86_64::XMM8));
- GetAssembler()->movd(x86_64::CpuRegister(x86_64::RAX), x86_64::XmmRegister(x86_64::XMM8));
- const char* expected =
- "movd %r11, %xmm0\n"
- "movd %rax, %xmm0\n"
- "movd %r11, %xmm8\n"
- "movd %rax, %xmm8\n"
- "movd %xmm0, %r11\n"
- "movd %xmm0, %rax\n"
- "movd %xmm8, %r11\n"
- "movd %xmm8, %rax\n";
- DriverStr(expected, "movd");
+TEST_F(AssemblerX86_64Test, XorlRegs) {
+ DriverStr(Repeatrr(&x86_64::X86_64Assembler::xorl, "xor %{reg2}, %{reg1}"), "xorl");
+}
+
+TEST_F(AssemblerX86_64Test, XorlImm) {
+ DriverStr(Repeatri(&x86_64::X86_64Assembler::xorl, 4U, "xor ${imm}, %{reg}"), "xorli");
+}
+
+TEST_F(AssemblerX86_64Test, Xchgq) {
+ DriverStr(RepeatRR(&x86_64::X86_64Assembler::xchgq, "xchgq %{reg2}, %{reg1}"), "xchgq");
+}
+
+TEST_F(AssemblerX86_64Test, Xchgl) {
+ // Test is disabled because GCC generates 0x87 0xC0 for xchgl eax, eax. All other cases are the
+ // same. Anyone know why it doesn't emit a simple 0x90? It does so for xchgq rax, rax...
+ // DriverStr(Repeatrr(&x86_64::X86_64Assembler::xchgl, "xchgl %{reg2}, %{reg1}"), "xchgl");
}
TEST_F(AssemblerX86_64Test, Movl) {
- GetAssembler()->movl(x86_64::CpuRegister(x86_64::R8), x86_64::CpuRegister(x86_64::R11));
- GetAssembler()->movl(x86_64::CpuRegister(x86_64::RAX), x86_64::CpuRegister(x86_64::R11));
GetAssembler()->movl(x86_64::CpuRegister(x86_64::RAX), x86_64::Address(
x86_64::CpuRegister(x86_64::RDI), x86_64::CpuRegister(x86_64::RBX), x86_64::TIMES_4, 12));
GetAssembler()->movl(x86_64::CpuRegister(x86_64::RAX), x86_64::Address(
GetAssembler()->movl(x86_64::CpuRegister(x86_64::R8), x86_64::Address(
x86_64::CpuRegister(x86_64::RDI), x86_64::CpuRegister(x86_64::R9), x86_64::TIMES_4, 12));
const char* expected =
- "movl %R11d, %R8d\n"
- "movl %R11d, %EAX\n"
"movl 0xc(%RDI,%RBX,4), %EAX\n"
"movl 0xc(%RDI,%R9,4), %EAX\n"
"movl 0xc(%RDI,%R9,4), %R8d\n";
DriverStr(expected, "movw");
}
-TEST_F(AssemblerX86_64Test, IMulImmediate) {
- GetAssembler()->imull(x86_64::CpuRegister(x86_64::RAX), x86_64::Immediate(0x40000));
- GetAssembler()->imull(x86_64::CpuRegister(x86_64::R8), x86_64::Immediate(0x40000));
- const char* expected =
- "imull $0x40000,%eax,%eax\n"
- "imull $0x40000,%r8d,%r8d\n";
- DriverStr(expected, "imul");
+TEST_F(AssemblerX86_64Test, Movsxd) {
+ 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");
+}
+
+TEST_F(AssemblerX86_64Test, Movss) {
+ DriverStr(RepeatFF(&x86_64::X86_64Assembler::movss, "movss %{reg2}, %{reg1}"), "movss");
+}
+
+TEST_F(AssemblerX86_64Test, Movsd) {
+ DriverStr(RepeatFF(&x86_64::X86_64Assembler::movsd, "movsd %{reg2}, %{reg1}"), "movsd");
+}
+
+TEST_F(AssemblerX86_64Test, Movd1) {
+ DriverStr(RepeatFR(&x86_64::X86_64Assembler::movd, "movd %{reg2}, %{reg1}"), "movd.1");
+}
+
+TEST_F(AssemblerX86_64Test, Movd2) {
+ DriverStr(RepeatRF(&x86_64::X86_64Assembler::movd, "movd %{reg2}, %{reg1}"), "movd.2");
+}
+
+TEST_F(AssemblerX86_64Test, Addss) {
+ DriverStr(RepeatFF(&x86_64::X86_64Assembler::addss, "addss %{reg2}, %{reg1}"), "addss");
+}
+
+TEST_F(AssemblerX86_64Test, Addsd) {
+ DriverStr(RepeatFF(&x86_64::X86_64Assembler::addsd, "addsd %{reg2}, %{reg1}"), "addsd");
+}
+
+TEST_F(AssemblerX86_64Test, Subss) {
+ DriverStr(RepeatFF(&x86_64::X86_64Assembler::subss, "subss %{reg2}, %{reg1}"), "subss");
+}
+
+TEST_F(AssemblerX86_64Test, Subsd) {
+ DriverStr(RepeatFF(&x86_64::X86_64Assembler::subsd, "subsd %{reg2}, %{reg1}"), "subsd");
+}
+
+TEST_F(AssemblerX86_64Test, Mulss) {
+ DriverStr(RepeatFF(&x86_64::X86_64Assembler::mulss, "mulss %{reg2}, %{reg1}"), "mulss");
+}
+
+TEST_F(AssemblerX86_64Test, Mulsd) {
+ DriverStr(RepeatFF(&x86_64::X86_64Assembler::mulsd, "mulsd %{reg2}, %{reg1}"), "mulsd");
+}
+
+TEST_F(AssemblerX86_64Test, Divss) {
+ DriverStr(RepeatFF(&x86_64::X86_64Assembler::divss, "divss %{reg2}, %{reg1}"), "divss");
+}
+
+TEST_F(AssemblerX86_64Test, Divsd) {
+ DriverStr(RepeatFF(&x86_64::X86_64Assembler::divsd, "divsd %{reg2}, %{reg1}"), "divsd");
+}
+
+TEST_F(AssemblerX86_64Test, Cvtsi2ss) {
+ DriverStr(RepeatFr(&x86_64::X86_64Assembler::cvtsi2ss, "cvtsi2ss %{reg2}, %{reg1}"), "cvtsi2ss");
+}
+
+TEST_F(AssemblerX86_64Test, Cvtsi2sd) {
+ 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");
+}
+
+TEST_F(AssemblerX86_64Test, Cvttss2si) {
+ DriverStr(RepeatrF(&x86_64::X86_64Assembler::cvttss2si, "cvttss2si %{reg2}, %{reg1}"),
+ "cvttss2si");
+}
+
+TEST_F(AssemblerX86_64Test, Cvttsd2si) {
+ DriverStr(RepeatrF(&x86_64::X86_64Assembler::cvttsd2si, "cvttsd2si %{reg2}, %{reg1}"),
+ "cvttsd2si");
+}
+
+TEST_F(AssemblerX86_64Test, Cvtsd2ss) {
+ DriverStr(RepeatFF(&x86_64::X86_64Assembler::cvtsd2ss, "cvtsd2ss %{reg2}, %{reg1}"), "cvtsd2ss");
+}
+
+TEST_F(AssemblerX86_64Test, Cvtdq2pd) {
+ DriverStr(RepeatFF(&x86_64::X86_64Assembler::cvtdq2pd, "cvtdq2pd %{reg2}, %{reg1}"), "cvtdq2pd");
+}
+
+TEST_F(AssemblerX86_64Test, Comiss) {
+ DriverStr(RepeatFF(&x86_64::X86_64Assembler::comiss, "comiss %{reg2}, %{reg1}"), "comiss");
+}
+
+TEST_F(AssemblerX86_64Test, Comisd) {
+ DriverStr(RepeatFF(&x86_64::X86_64Assembler::comisd, "comisd %{reg2}, %{reg1}"), "comisd");
+}
+
+TEST_F(AssemblerX86_64Test, Sqrtss) {
+ DriverStr(RepeatFF(&x86_64::X86_64Assembler::sqrtss, "sqrtss %{reg2}, %{reg1}"), "sqrtss");
+}
+
+TEST_F(AssemblerX86_64Test, Sqrtsd) {
+ DriverStr(RepeatFF(&x86_64::X86_64Assembler::sqrtsd, "sqrtsd %{reg2}, %{reg1}"), "sqrtsd");
+}
+
+TEST_F(AssemblerX86_64Test, Xorps) {
+ DriverStr(RepeatFF(&x86_64::X86_64Assembler::xorps, "xorps %{reg2}, %{reg1}"), "xorps");
+}
+
+TEST_F(AssemblerX86_64Test, Xorpd) {
+ DriverStr(RepeatFF(&x86_64::X86_64Assembler::xorpd, "xorpd %{reg2}, %{reg1}"), "xorpd");
+}
+
+// X87
+
+std::string x87_fn(AssemblerX86_64Test::Base* assembler_test ATTRIBUTE_UNUSED,
+ x86_64::X86_64Assembler* assembler) {
+ std::ostringstream str;
+
+ assembler->fincstp();
+ str << "fincstp\n";
+
+ assembler->fsin();
+ str << "fsin\n";
+
+ assembler->fcos();
+ str << "fcos\n";
+
+ assembler->fptan();
+ str << "fptan\n";
+
+ return str.str();
+}
+
+TEST_F(AssemblerX86_64Test, X87) {
+ DriverFn(&x87_fn, "x87");
+}
+
+////////////////
+// CALL / JMP //
+////////////////
+
+TEST_F(AssemblerX86_64Test, Call) {
+ DriverStr(RepeatR(&x86_64::X86_64Assembler::call, "call *%{reg}"), "call");
+}
+
+TEST_F(AssemblerX86_64Test, Jmp) {
+ DriverStr(RepeatR(&x86_64::X86_64Assembler::jmp, "jmp *%{reg}"), "jmp");
+}
+
+TEST_F(AssemblerX86_64Test, Enter) {
+ DriverStr(RepeatI(&x86_64::X86_64Assembler::enter, 2U /* 16b immediate */, "enter ${imm}, $0",
+ true /* Only non-negative number */), "enter");
+}
+
+TEST_F(AssemblerX86_64Test, RetImm) {
+ DriverStr(RepeatI(&x86_64::X86_64Assembler::ret, 2U /* 16b immediate */, "ret ${imm}",
+ true /* Only non-negative number */), "reti");
+}
+
+std::string ret_and_leave_fn(AssemblerX86_64Test::Base* assembler_test ATTRIBUTE_UNUSED,
+ x86_64::X86_64Assembler* assembler) {
+ std::ostringstream str;
+
+ assembler->ret();
+ str << "ret\n";
+
+ assembler->leave();
+ str << "leave\n";
+
+ return str.str();
+}
+
+TEST_F(AssemblerX86_64Test, RetAndLeave) {
+ DriverFn(&ret_and_leave_fn, "retleave");
}
+//////////
+// MISC //
+//////////
-std::string setcc_test_fn(x86_64::X86_64Assembler* assembler) {
+std::string setcc_test_fn(AssemblerX86_64Test::Base* assembler_test,
+ x86_64::X86_64Assembler* assembler) {
// From Condition
/*
kOverflow = 0,
std::string suffixes[15] = { "o", "no", "b", "ae", "e", "ne", "be", "a", "s", "ns", "pe", "po",
"l", "ge", "le" };
- std::vector<x86_64::CpuRegister*> registers;
- registers.push_back(new x86_64::CpuRegister(x86_64::RAX));
- registers.push_back(new x86_64::CpuRegister(x86_64::RBX));
- registers.push_back(new x86_64::CpuRegister(x86_64::RCX));
- registers.push_back(new x86_64::CpuRegister(x86_64::RDX));
- registers.push_back(new x86_64::CpuRegister(x86_64::RBP));
- registers.push_back(new x86_64::CpuRegister(x86_64::RSP));
- registers.push_back(new x86_64::CpuRegister(x86_64::RSI));
- registers.push_back(new x86_64::CpuRegister(x86_64::RDI));
- registers.push_back(new x86_64::CpuRegister(x86_64::R8));
- registers.push_back(new x86_64::CpuRegister(x86_64::R9));
- registers.push_back(new x86_64::CpuRegister(x86_64::R10));
- registers.push_back(new x86_64::CpuRegister(x86_64::R11));
- registers.push_back(new x86_64::CpuRegister(x86_64::R12));
- registers.push_back(new x86_64::CpuRegister(x86_64::R13));
- registers.push_back(new x86_64::CpuRegister(x86_64::R14));
- registers.push_back(new x86_64::CpuRegister(x86_64::R15));
+ std::vector<x86_64::CpuRegister*> registers = assembler_test->GetRegisters();
std::string byte_regs[16];
byte_regs[x86_64::RAX] = "al";
}
}
- STLDeleteElements(®isters);
return str.str();
}
return x86_64::X86_64ManagedRegister::FromXmmRegister(r);
}
-std::string buildframe_test_fn(x86_64::X86_64Assembler* assembler) {
+std::string buildframe_test_fn(AssemblerX86_64Test::Base* assembler_test ATTRIBUTE_UNUSED,
+ x86_64::X86_64Assembler* assembler) {
// TODO: more interesting spill registers / entry spills.
// Two random spill regs.
DriverFn(&buildframe_test_fn, "BuildFrame");
}
-std::string removeframe_test_fn(x86_64::X86_64Assembler* assembler) {
+std::string removeframe_test_fn(AssemblerX86_64Test::Base* assembler_test ATTRIBUTE_UNUSED,
+ x86_64::X86_64Assembler* assembler) {
// TODO: more interesting spill registers / entry spills.
// Two random spill regs.
DriverFn(&removeframe_test_fn, "RemoveFrame");
}
-std::string increaseframe_test_fn(x86_64::X86_64Assembler* assembler) {
+std::string increaseframe_test_fn(AssemblerX86_64Test::Base* assembler_test ATTRIBUTE_UNUSED,
+ x86_64::X86_64Assembler* assembler) {
assembler->IncreaseFrameSize(0U);
assembler->IncreaseFrameSize(kStackAlignment);
assembler->IncreaseFrameSize(10 * kStackAlignment);
DriverFn(&increaseframe_test_fn, "IncreaseFrame");
}
-std::string decreaseframe_test_fn(x86_64::X86_64Assembler* assembler) {
+std::string decreaseframe_test_fn(AssemblerX86_64Test::Base* assembler_test ATTRIBUTE_UNUSED,
+ x86_64::X86_64Assembler* assembler) {
assembler->DecreaseFrameSize(0U);
assembler->DecreaseFrameSize(kStackAlignment);
assembler->DecreaseFrameSize(10 * kStackAlignment);