/*
* Copyright (C) 2014 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "assembler_x86_64.h"
#include <inttypes.h>
#include <map>
#include <random>
#include "base/bit_utils.h"
#include "base/stl_util.h"
#include "jni_macro_assembler_x86_64.h"
#include "utils/assembler_test.h"
#include "utils/jni_macro_assembler_test.h"
namespace art {
TEST(AssemblerX86_64, CreateBuffer) {
ArenaPool pool;
ArenaAllocator arena(&pool);
AssemblerBuffer buffer(&arena);
AssemblerBuffer::EnsureCapacity ensured(&buffer);
buffer.Emit<uint8_t>(0x42);
ASSERT_EQ(static_cast<size_t>(1), buffer.Size());
buffer.Emit<int32_t>(42);
ASSERT_EQ(static_cast<size_t>(5), buffer.Size());
}
#ifdef ART_TARGET_ANDROID
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(IsInt<8>(i)) << i;
}
for (int32_t i = 128; i < 255; i++) {
EXPECT_FALSE(IsInt<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(IsInt<8>(value)) << value;
}
// Negative ones.
for (int32_t i = -1; i >= -128; i--) {
EXPECT_TRUE(IsInt<8>(i)) << i;
}
for (int32_t i = -129; i > -256; i--) {
EXPECT_FALSE(IsInt<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(IsInt<8>(value)) << value;
}
// 64bit.
for (int64_t i = 0; i < 128; i++) {
EXPECT_TRUE(IsInt<8>(i)) << i;
}
for (int32_t i = 128; i < 255; i++) {
EXPECT_FALSE(IsInt<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(IsInt<8>(value)) << value;
}
// Negative ones.
for (int64_t i = -1; i >= -128; i--) {
EXPECT_TRUE(IsInt<8>(i)) << i;
}
for (int64_t i = -129; i > -256; i--) {
EXPECT_FALSE(IsInt<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(IsInt<8>(value)) << value;
}
int64_t value = INT64_C(0x1200000010);
x86_64::Immediate imm(value);
EXPECT_FALSE(imm.is_int8());
EXPECT_FALSE(imm.is_int16());
EXPECT_FALSE(imm.is_int32());
value = INT64_C(0x8000000000000001);
x86_64::Immediate imm2(value);
EXPECT_FALSE(imm2.is_int8());
EXPECT_FALSE(imm2.is_int16());
EXPECT_FALSE(imm2.is_int32());
}
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::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 {
return "x86_64";
}
std::string GetDisassembleParameters() OVERRIDE {
return " -D -bbinary -mi386:x86-64 -Mx86-64,addr64,data32 --no-show-raw-insn";
}
void SetUpHelpers() OVERRIDE {
if (registers_.size() == 0) {
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));
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");
tertiary_register_names_.emplace(x86_64::CpuRegister(x86_64::RAX), "ax");
tertiary_register_names_.emplace(x86_64::CpuRegister(x86_64::RBX), "bx");
tertiary_register_names_.emplace(x86_64::CpuRegister(x86_64::RCX), "cx");
tertiary_register_names_.emplace(x86_64::CpuRegister(x86_64::RDX), "dx");
tertiary_register_names_.emplace(x86_64::CpuRegister(x86_64::RBP), "bp");
tertiary_register_names_.emplace(x86_64::CpuRegister(x86_64::RSP), "sp");
tertiary_register_names_.emplace(x86_64::CpuRegister(x86_64::RSI), "si");
tertiary_register_names_.emplace(x86_64::CpuRegister(x86_64::RDI), "di");
tertiary_register_names_.emplace(x86_64::CpuRegister(x86_64::R8), "r8w");
tertiary_register_names_.emplace(x86_64::CpuRegister(x86_64::R9), "r9w");
tertiary_register_names_.emplace(x86_64::CpuRegister(x86_64::R10), "r10w");
tertiary_register_names_.emplace(x86_64::CpuRegister(x86_64::R11), "r11w");
tertiary_register_names_.emplace(x86_64::CpuRegister(x86_64::R12), "r12w");
tertiary_register_names_.emplace(x86_64::CpuRegister(x86_64::R13), "r13w");
tertiary_register_names_.emplace(x86_64::CpuRegister(x86_64::R14), "r14w");
tertiary_register_names_.emplace(x86_64::CpuRegister(x86_64::R15), "r15w");
quaternary_register_names_.emplace(x86_64::CpuRegister(x86_64::RAX), "al");
quaternary_register_names_.emplace(x86_64::CpuRegister(x86_64::RBX), "bl");
quaternary_register_names_.emplace(x86_64::CpuRegister(x86_64::RCX), "cl");
quaternary_register_names_.emplace(x86_64::CpuRegister(x86_64::RDX), "dl");
quaternary_register_names_.emplace(x86_64::CpuRegister(x86_64::RBP), "bpl");
quaternary_register_names_.emplace(x86_64::CpuRegister(x86_64::RSP), "spl");
quaternary_register_names_.emplace(x86_64::CpuRegister(x86_64::RSI), "sil");
quaternary_register_names_.emplace(x86_64::CpuRegister(x86_64::RDI), "dil");
quaternary_register_names_.emplace(x86_64::CpuRegister(x86_64::R8), "r8b");
quaternary_register_names_.emplace(x86_64::CpuRegister(x86_64::R9), "r9b");
quaternary_register_names_.emplace(x86_64::CpuRegister(x86_64::R10), "r10b");
quaternary_register_names_.emplace(x86_64::CpuRegister(x86_64::R11), "r11b");
quaternary_register_names_.emplace(x86_64::CpuRegister(x86_64::R12), "r12b");
quaternary_register_names_.emplace(x86_64::CpuRegister(x86_64::R13), "r13b");
quaternary_register_names_.emplace(x86_64::CpuRegister(x86_64::R14), "r14b");
quaternary_register_names_.emplace(x86_64::CpuRegister(x86_64::R15), "r15b");
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];
}
std::string GetTertiaryRegisterName(const x86_64::CpuRegister& reg) OVERRIDE {
CHECK(tertiary_register_names_.find(reg) != tertiary_register_names_.end());
return tertiary_register_names_[reg];
}
std::string GetQuaternaryRegisterName(const x86_64::CpuRegister& reg) OVERRIDE {
CHECK(quaternary_register_names_.find(reg) != quaternary_register_names_.end());
return quaternary_register_names_[reg];
}
private:
std::vector<x86_64::CpuRegister*> registers_;
std::map<x86_64::CpuRegister, std::string, X86_64CpuRegisterCompare> secondary_register_names_;
std::map<x86_64::CpuRegister, std::string, X86_64CpuRegisterCompare> tertiary_register_names_;
std::map<x86_64::CpuRegister, std::string, X86_64CpuRegisterCompare> quaternary_register_names_;
std::vector<x86_64::XmmRegister*> fp_registers_;
};
TEST_F(AssemblerX86_64Test, Toolchain) {
EXPECT_TRUE(CheckTools());
}
TEST_F(AssemblerX86_64Test, PushqRegs) {
DriverStr(RepeatR(&x86_64::X86_64Assembler::pushq, "pushq %{reg}"), "pushq");
}
TEST_F(AssemblerX86_64Test, PushqImm) {
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");
}
TEST_F(AssemblerX86_64Test, MovqImm) {
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");
}
TEST_F(AssemblerX86_64Test, AddqImm) {
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, ImulqReg1) {
DriverStr(RepeatR(&x86_64::X86_64Assembler::imulq, "imulq %{reg}"), "imulq");
}
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");
}
TEST_F(AssemblerX86_64Test, SubqImm) {
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 count.
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");
}
// Shlq only allows CL as the shift count.
std::string shlq_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->shlq(*reg, shifter);
str << "shlq %cl, %" << assembler_test->GetRegisterName(*reg) << "\n";
}
return str.str();
}
TEST_F(AssemblerX86_64Test, ShlqReg) {
DriverFn(&shlq_fn, "shlq");
}
TEST_F(AssemblerX86_64Test, ShlqImm) {
DriverStr(RepeatRI(&x86_64::X86_64Assembler::shlq, 1U, "shlq ${imm}, %{reg}"), "shlqi");
}
// Shrl only allows CL as the shift count.
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");
}
// Shrq only allows CL as the shift count.
std::string shrq_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->shrq(*reg, shifter);
str << "shrq %cl, %" << assembler_test->GetRegisterName(*reg) << "\n";
}
return str.str();
}
TEST_F(AssemblerX86_64Test, ShrqReg) {
DriverFn(&shrq_fn, "shrq");
}
TEST_F(AssemblerX86_64Test, ShrqImm) {
DriverStr(RepeatRI(&x86_64::X86_64Assembler::shrq, 1U, "shrq ${imm}, %{reg}"), "shrqi");
}
// Sarl only allows CL as the shift count.
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");
}
// Sarq only allows CL as the shift count.
std::string sarq_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->sarq(*reg, shifter);
str << "sarq %cl, %" << assembler_test->GetRegisterName(*reg) << "\n";
}
return str.str();
}
TEST_F(AssemblerX86_64Test, SarqReg) {
DriverFn(&sarq_fn, "sarq");
}
TEST_F(AssemblerX86_64Test, SarqImm) {
DriverStr(RepeatRI(&x86_64::X86_64Assembler::sarq, 1U, "sarq ${imm}, %{reg}"), "sarqi");
}
// Rorl only allows CL as the shift count.
std::string rorl_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->rorl(*reg, shifter);
str << "rorl %cl, %" << assembler_test->GetSecondaryRegisterName(*reg) << "\n";
}
return str.str();
}
TEST_F(AssemblerX86_64Test, RorlReg) {
DriverFn(&rorl_fn, "rorl");
}
TEST_F(AssemblerX86_64Test, RorlImm) {
DriverStr(Repeatri(&x86_64::X86_64Assembler::rorl, 1U, "rorl ${imm}, %{reg}"), "rorli");
}
// Roll only allows CL as the shift count.
std::string roll_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->roll(*reg, shifter);
str << "roll %cl, %" << assembler_test->GetSecondaryRegisterName(*reg) << "\n";
}
return str.str();
}
TEST_F(AssemblerX86_64Test, RollReg) {
DriverFn(&roll_fn, "roll");
}
TEST_F(AssemblerX86_64Test, RollImm) {
DriverStr(Repeatri(&x86_64::X86_64Assembler::roll, 1U, "roll ${imm}, %{reg}"), "rolli");
}
// Rorq only allows CL as the shift count.
std::string rorq_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->rorq(*reg, shifter);
str << "rorq %cl, %" << assembler_test->GetRegisterName(*reg) << "\n";
}
return str.str();
}
TEST_F(AssemblerX86_64Test, RorqReg) {
DriverFn(&rorq_fn, "rorq");
}
TEST_F(AssemblerX86_64Test, RorqImm) {
DriverStr(RepeatRI(&x86_64::X86_64Assembler::rorq, 1U, "rorq ${imm}, %{reg}"), "rorqi");
}
// Rolq only allows CL as the shift count.
std::string rolq_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->rolq(*reg, shifter);
str << "rolq %cl, %" << assembler_test->GetRegisterName(*reg) << "\n";
}
return str.str();
}
TEST_F(AssemblerX86_64Test, RolqReg) {
DriverFn(&rolq_fn, "rolq");
}
TEST_F(AssemblerX86_64Test, RolqImm) {
DriverStr(RepeatRI(&x86_64::X86_64Assembler::rolq, 1U, "rolq ${imm}, %{reg}"), "rolqi");
}
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, 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, LockCmpxchgl) {
GetAssembler()->LockCmpxchgl(x86_64::Address(
x86_64::CpuRegister(x86_64::RDI), x86_64::CpuRegister(x86_64::RBX), x86_64::TIMES_4, 12),
x86_64::CpuRegister(x86_64::RSI));
GetAssembler()->LockCmpxchgl(x86_64::Address(
x86_64::CpuRegister(x86_64::RDI), x86_64::CpuRegister(x86_64::R9), x86_64::TIMES_4, 12),
x86_64::CpuRegister(x86_64::RSI));
GetAssembler()->LockCmpxchgl(x86_64::Address(
x86_64::CpuRegister(x86_64::RDI), x86_64::CpuRegister(x86_64::R9), x86_64::TIMES_4, 12),
x86_64::CpuRegister(x86_64::R8));
GetAssembler()->LockCmpxchgl(x86_64::Address(
x86_64::CpuRegister(x86_64::R13), 0), x86_64::CpuRegister(x86_64::RSI));
GetAssembler()->LockCmpxchgl(x86_64::Address(
x86_64::CpuRegister(x86_64::R13), x86_64::CpuRegister(x86_64::R9), x86_64::TIMES_1, 0),
x86_64::CpuRegister(x86_64::RSI));
const char* expected =
"lock cmpxchgl %ESI, 0xc(%RDI,%RBX,4)\n"
"lock cmpxchgl %ESI, 0xc(%RDI,%R9,4)\n"
"lock cmpxchgl %R8d, 0xc(%RDI,%R9,4)\n"
"lock cmpxchgl %ESI, (%R13)\n"
"lock cmpxchgl %ESI, (%R13,%R9,1)\n";
DriverStr(expected, "lock_cmpxchgl");
}
TEST_F(AssemblerX86_64Test, LockCmpxchgq) {
GetAssembler()->LockCmpxchgq(x86_64::Address(
x86_64::CpuRegister(x86_64::RDI), x86_64::CpuRegister(x86_64::RBX), x86_64::TIMES_4, 12),
x86_64::CpuRegister(x86_64::RSI));
GetAssembler()->LockCmpxchgq(x86_64::Address(
x86_64::CpuRegister(x86_64::RDI), x86_64::CpuRegister(x86_64::R9), x86_64::TIMES_4, 12),
x86_64::CpuRegister(x86_64::RSI));
GetAssembler()->LockCmpxchgq(x86_64::Address(
x86_64::CpuRegister(x86_64::RDI), x86_64::CpuRegister(x86_64::R9), x86_64::TIMES_4, 12),
x86_64::CpuRegister(x86_64::R8));
GetAssembler()->LockCmpxchgq(x86_64::Address(
x86_64::CpuRegister(x86_64::R13), 0), x86_64::CpuRegister(x86_64::RSI));
GetAssembler()->LockCmpxchgq(x86_64::Address(
x86_64::CpuRegister(x86_64::R13), x86_64::CpuRegister(x86_64::R9), x86_64::TIMES_1, 0),
x86_64::CpuRegister(x86_64::RSI));
const char* expected =
"lock cmpxchg %RSI, 0xc(%RDI,%RBX,4)\n"
"lock cmpxchg %RSI, 0xc(%RDI,%R9,4)\n"
"lock cmpxchg %R8, 0xc(%RDI,%R9,4)\n"
"lock cmpxchg %RSI, (%R13)\n"
"lock cmpxchg %RSI, (%R13,%R9,1)\n";
DriverStr(expected, "lock_cmpxchg");
}
TEST_F(AssemblerX86_64Test, Movl) {
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(
x86_64::CpuRegister(x86_64::RDI), x86_64::CpuRegister(x86_64::R9), x86_64::TIMES_4, 12));
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));
GetAssembler()->movl(x86_64::CpuRegister(x86_64::RAX), x86_64::Address(
x86_64::CpuRegister(x86_64::R13), 0));
GetAssembler()->movl(x86_64::CpuRegister(x86_64::RAX), x86_64::Address(
x86_64::CpuRegister(x86_64::R13), x86_64::CpuRegister(x86_64::R9), x86_64::TIMES_1, 0));
const char* expected =
"movl 0xc(%RDI,%RBX,4), %EAX\n"
"movl 0xc(%RDI,%R9,4), %EAX\n"
"movl 0xc(%RDI,%R9,4), %R8d\n"
"movl (%R13), %EAX\n"
"movl (%R13,%R9,1), %EAX\n";
DriverStr(expected, "movl");
}
TEST_F(AssemblerX86_64Test, Movw) {
GetAssembler()->movw(x86_64::Address(x86_64::CpuRegister(x86_64::RAX), 0),
x86_64::CpuRegister(x86_64::R9));
GetAssembler()->movw(x86_64::Address(x86_64::CpuRegister(x86_64::RAX), 0),
x86_64::Immediate(0));
GetAssembler()->movw(x86_64::Address(x86_64::CpuRegister(x86_64::R9), 0),
x86_64::Immediate(0));
GetAssembler()->movw(x86_64::Address(x86_64::CpuRegister(x86_64::R14), 0),
x86_64::Immediate(0));
const char* expected =
"movw %R9w, 0(%RAX)\n"
"movw $0, 0(%RAX)\n"
"movw $0, 0(%R9)\n"
"movw $0, 0(%R14)\n";
DriverStr(expected, "movw");
}
TEST_F(AssemblerX86_64Test, Cmpw) {
GetAssembler()->cmpw(x86_64::Address(x86_64::CpuRegister(x86_64::RAX), 0),
x86_64::Immediate(0));
GetAssembler()->cmpw(x86_64::Address(x86_64::CpuRegister(x86_64::R9), 0),
x86_64::Immediate(0));
GetAssembler()->cmpw(x86_64::Address(x86_64::CpuRegister(x86_64::R14), 0),
x86_64::Immediate(0));
const char* expected =
"cmpw $0, 0(%RAX)\n"
"cmpw $0, 0(%R9)\n"
"cmpw $0, 0(%R14)\n";
DriverStr(expected, "cmpw");
}
TEST_F(AssemblerX86_64Test, MovqAddrImm) {
GetAssembler()->movq(x86_64::Address(x86_64::CpuRegister(x86_64::RAX), 0),
x86_64::Immediate(-5));
const char* expected = "movq $-5, 0(%RAX)\n";
DriverStr(expected, "movq");
}
TEST_F(AssemblerX86_64Test, Movntl) {
GetAssembler()->movntl(x86_64::Address(
x86_64::CpuRegister(x86_64::RDI), x86_64::CpuRegister(x86_64::RBX), x86_64::TIMES_4, 12), x86_64::CpuRegister(x86_64::RAX));
GetAssembler()->movntl(x86_64::Address(
x86_64::CpuRegister(x86_64::RDI), x86_64::CpuRegister(x86_64::R9), x86_64::TIMES_4, 12), x86_64::CpuRegister(x86_64::RAX));
GetAssembler()->movntl(x86_64::Address(
x86_64::CpuRegister(x86_64::RDI), x86_64::CpuRegister(x86_64::R9), x86_64::TIMES_4, 12), x86_64::CpuRegister(x86_64::RAX));
GetAssembler()->movntl(x86_64::Address(x86_64::CpuRegister(x86_64::R13), 0), x86_64::CpuRegister(x86_64::RAX));
GetAssembler()->movntl(x86_64::Address(
x86_64::CpuRegister(x86_64::R13), x86_64::CpuRegister(x86_64::R9), x86_64::TIMES_1, 0), x86_64::CpuRegister(x86_64::R9));
const char* expected =
"movntil %EAX, 0xc(%RDI,%RBX,4)\n"
"movntil %EAX, 0xc(%RDI,%R9,4)\n"
"movntil %EAX, 0xc(%RDI,%R9,4)\n"
"movntil %EAX, (%R13)\n"
"movntil %R9d, (%R13,%R9,1)\n";
DriverStr(expected, "movntl");
}
TEST_F(AssemblerX86_64Test, Movntq) {
GetAssembler()->movntq(x86_64::Address(
x86_64::CpuRegister(x86_64::RDI), x86_64::CpuRegister(x86_64::RBX), x86_64::TIMES_4, 12), x86_64::CpuRegister(x86_64::RAX));
GetAssembler()->movntq(x86_64::Address(
x86_64::CpuRegister(x86_64::RDI), x86_64::CpuRegister(x86_64::R9), x86_64::TIMES_4, 12), x86_64::CpuRegister(x86_64::RAX));
GetAssembler()->movntq(x86_64::Address(
x86_64::CpuRegister(x86_64::RDI), x86_64::CpuRegister(x86_64::R9), x86_64::TIMES_4, 12), x86_64::CpuRegister(x86_64::RAX));
GetAssembler()->movntq(x86_64::Address(x86_64::CpuRegister(x86_64::R13), 0), x86_64::CpuRegister(x86_64::RAX));
GetAssembler()->movntq(x86_64::Address(
x86_64::CpuRegister(x86_64::R13), x86_64::CpuRegister(x86_64::R9), x86_64::TIMES_1, 0), x86_64::CpuRegister(x86_64::R9));
const char* expected =
"movntiq %RAX, 0xc(%RDI,%RBX,4)\n"
"movntiq %RAX, 0xc(%RDI,%R9,4)\n"
"movntiq %RAX, 0xc(%RDI,%R9,4)\n"
"movntiq %RAX, (%R13)\n"
"movntiq %R9, (%R13,%R9,1)\n";
DriverStr(expected, "movntq");
}
TEST_F(AssemblerX86_64Test, Cvtsi2ssAddr) {
GetAssembler()->cvtsi2ss(x86_64::XmmRegister(x86_64::XMM0),
x86_64::Address(x86_64::CpuRegister(x86_64::RAX), 0),
false);
GetAssembler()->cvtsi2ss(x86_64::XmmRegister(x86_64::XMM0),
x86_64::Address(x86_64::CpuRegister(x86_64::RAX), 0),
true);
const char* expected = "cvtsi2ss 0(%RAX), %xmm0\n"
"cvtsi2ssq 0(%RAX), %xmm0\n";
DriverStr(expected, "cvtsi2ss");
}
TEST_F(AssemblerX86_64Test, Cvtsi2sdAddr) {
GetAssembler()->cvtsi2sd(x86_64::XmmRegister(x86_64::XMM0),
x86_64::Address(x86_64::CpuRegister(x86_64::RAX), 0),
false);
GetAssembler()->cvtsi2sd(x86_64::XmmRegister(x86_64::XMM0),
x86_64::Address(x86_64::CpuRegister(x86_64::RAX), 0),
true);
const char* expected = "cvtsi2sd 0(%RAX), %xmm0\n"
"cvtsi2sdq 0(%RAX), %xmm0\n";
DriverStr(expected, "cvtsi2sd");
}
TEST_F(AssemblerX86_64Test, CmpqAddr) {
GetAssembler()->cmpq(x86_64::CpuRegister(x86_64::R12),
x86_64::Address(x86_64::CpuRegister(x86_64::R9), 0));
const char* expected = "cmpq 0(%R9), %R12\n";
DriverStr(expected, "cmpq");
}
TEST_F(AssemblerX86_64Test, MovsxdAddr) {
GetAssembler()->movsxd(x86_64::CpuRegister(x86_64::R12),
x86_64::Address(x86_64::CpuRegister(x86_64::R9), 0));
const char* expected = "movslq 0(%R9), %R12\n";
DriverStr(expected, "movsxd");
}
TEST_F(AssemblerX86_64Test, TestqAddr) {
GetAssembler()->testq(x86_64::CpuRegister(x86_64::R12),
x86_64::Address(x86_64::CpuRegister(x86_64::R9), 0));
const char* expected = "testq 0(%R9), %R12\n";
DriverStr(expected, "testq");
}
TEST_F(AssemblerX86_64Test, AddqAddr) {
GetAssembler()->addq(x86_64::CpuRegister(x86_64::R12),
x86_64::Address(x86_64::CpuRegister(x86_64::R9), 0));
const char* expected = "addq 0(%R9), %R12\n";
DriverStr(expected, "addq");
}
TEST_F(AssemblerX86_64Test, SubqAddr) {
GetAssembler()->subq(x86_64::CpuRegister(x86_64::R12),
x86_64::Address(x86_64::CpuRegister(x86_64::R9), 0));
const char* expected = "subq 0(%R9), %R12\n";
DriverStr(expected, "subq");
}
TEST_F(AssemblerX86_64Test, Cvtss2sdAddr) {
GetAssembler()->cvtss2sd(x86_64::XmmRegister(x86_64::XMM0),
x86_64::Address(x86_64::CpuRegister(x86_64::RAX), 0));
const char* expected = "cvtss2sd 0(%RAX), %xmm0\n";
DriverStr(expected, "cvtss2sd");
}
TEST_F(AssemblerX86_64Test, Cvtsd2ssAddr) {
GetAssembler()->cvtsd2ss(x86_64::XmmRegister(x86_64::XMM0),
x86_64::Address(x86_64::CpuRegister(x86_64::RAX), 0));
const char* expected = "cvtsd2ss 0(%RAX), %xmm0\n";
DriverStr(expected, "cvtsd2ss");
}
TEST_F(AssemblerX86_64Test, ComissAddr) {
GetAssembler()->comiss(x86_64::XmmRegister(x86_64::XMM14),
x86_64::Address(x86_64::CpuRegister(x86_64::RAX), 0));
const char* expected = "comiss 0(%RAX), %xmm14\n";
DriverStr(expected, "comiss");
}
TEST_F(AssemblerX86_64Test, ComisdAddr) {
GetAssembler()->comisd(x86_64::XmmRegister(x86_64::XMM0),
x86_64::Address(x86_64::CpuRegister(x86_64::R9), 0));
const char* expected = "comisd 0(%R9), %xmm0\n";
DriverStr(expected, "comisd");
}
TEST_F(AssemblerX86_64Test, UComissAddr) {
GetAssembler()->ucomiss(x86_64::XmmRegister(x86_64::XMM0),
x86_64::Address(x86_64::CpuRegister(x86_64::RAX), 0));
const char* expected = "ucomiss 0(%RAX), %xmm0\n";
DriverStr(expected, "ucomiss");
}
TEST_F(AssemblerX86_64Test, UComisdAddr) {
GetAssembler()->ucomisd(x86_64::XmmRegister(x86_64::XMM0),
x86_64::Address(x86_64::CpuRegister(x86_64::RAX), 0));
const char* expected = "ucomisd 0(%RAX), %xmm0\n";
DriverStr(expected, "ucomisd");
}
TEST_F(AssemblerX86_64Test, Andq) {
GetAssembler()->andq(x86_64::CpuRegister(x86_64::R9),
x86_64::Address(x86_64::CpuRegister(x86_64::RAX), 0));
const char* expected = "andq 0(%RAX), %r9\n";
DriverStr(expected, "andq");
}
TEST_F(AssemblerX86_64Test, Orq) {
GetAssembler()->orq(x86_64::CpuRegister(x86_64::R9),
x86_64::Address(x86_64::CpuRegister(x86_64::RAX), 0));
const char* expected = "orq 0(%RAX), %r9\n";
DriverStr(expected, "orq");
}
TEST_F(AssemblerX86_64Test, Xorq) {
GetAssembler()->xorq(x86_64::CpuRegister(x86_64::R9),
x86_64::Address(x86_64::CpuRegister(x86_64::RAX), 0));
const char* expected = "xorq 0(%RAX), %r9\n";
DriverStr(expected, "xorq");
}
TEST_F(AssemblerX86_64Test, RepneScasb) {
GetAssembler()->repne_scasb();
const char* expected = "repne scasb\n";
DriverStr(expected, "repne_scasb");
}
TEST_F(AssemblerX86_64Test, RepneScasw) {
GetAssembler()->repne_scasw();
const char* expected = "repne scasw\n";
DriverStr(expected, "repne_scasw");
}
TEST_F(AssemblerX86_64Test, RepMovsw) {
GetAssembler()->rep_movsw();
const char* expected = "rep movsw\n";
DriverStr(expected, "rep_movsw");
}
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, MovapsAddr) {
GetAssembler()->movaps(x86_64::XmmRegister(x86_64::XMM0), x86_64::Address(x86_64::CpuRegister(x86_64::RSP), 4));
GetAssembler()->movaps(x86_64::Address(x86_64::CpuRegister(x86_64::RSP), 2), x86_64::XmmRegister(x86_64::XMM1));
const char* expected =
"movaps 0x4(%RSP), %xmm0\n"
"movaps %xmm1, 0x2(%RSP)\n";
DriverStr(expected, "movaps_address");
}
TEST_F(AssemblerX86_64Test, MovupsAddr) {
GetAssembler()->movups(x86_64::XmmRegister(x86_64::XMM0), x86_64::Address(x86_64::CpuRegister(x86_64::RSP), 4));
GetAssembler()->movups(x86_64::Address(x86_64::CpuRegister(x86_64::RSP), 2), x86_64::XmmRegister(x86_64::XMM1));
const char* expected =
"movups 0x4(%RSP), %xmm0\n"
"movups %xmm1, 0x2(%RSP)\n";
DriverStr(expected, "movups_address");
}
TEST_F(AssemblerX86_64Test, Movss) {
DriverStr(RepeatFF(&x86_64::X86_64Assembler::movss, "movss %{reg2}, %{reg1}"), "movss");
}
TEST_F(AssemblerX86_64Test, Movapd) {
DriverStr(RepeatFF(&x86_64::X86_64Assembler::movapd, "movapd %{reg2}, %{reg1}"), "movapd");
}
TEST_F(AssemblerX86_64Test, MovapdAddr) {
GetAssembler()->movapd(x86_64::XmmRegister(x86_64::XMM0), x86_64::Address(x86_64::CpuRegister(x86_64::RSP), 4));
GetAssembler()->movapd(x86_64::Address(x86_64::CpuRegister(x86_64::RSP), 2), x86_64::XmmRegister(x86_64::XMM1));
const char* expected =
"movapd 0x4(%RSP), %xmm0\n"
"movapd %xmm1, 0x2(%RSP)\n";
DriverStr(expected, "movapd_address");
}
TEST_F(AssemblerX86_64Test, MovupdAddr) {
GetAssembler()->movupd(x86_64::XmmRegister(x86_64::XMM0), x86_64::Address(x86_64::CpuRegister(x86_64::RSP), 4));
GetAssembler()->movupd(x86_64::Address(x86_64::CpuRegister(x86_64::RSP), 2), x86_64::XmmRegister(x86_64::XMM1));
const char* expected =
"movupd 0x4(%RSP), %xmm0\n"
"movupd %xmm1, 0x2(%RSP)\n";
DriverStr(expected, "movupd_address");
}
TEST_F(AssemblerX86_64Test, Movsd) {
DriverStr(RepeatFF(&x86_64::X86_64Assembler::movsd, "movsd %{reg2}, %{reg1}"), "movsd");
}
TEST_F(AssemblerX86_64Test, Movdqa) {
DriverStr(RepeatFF(&x86_64::X86_64Assembler::movdqa, "movdqa %{reg2}, %{reg1}"), "movapd");
}
TEST_F(AssemblerX86_64Test, MovdqaAddr) {
GetAssembler()->movdqa(x86_64::XmmRegister(x86_64::XMM0), x86_64::Address(x86_64::CpuRegister(x86_64::RSP), 4));
GetAssembler()->movdqa(x86_64::Address(x86_64::CpuRegister(x86_64::RSP), 2), x86_64::XmmRegister(x86_64::XMM1));
const char* expected =
"movdqa 0x4(%RSP), %xmm0\n"
"movdqa %xmm1, 0x2(%RSP)\n";
DriverStr(expected, "movdqa_address");
}
TEST_F(AssemblerX86_64Test, MovdquAddr) {
GetAssembler()->movdqu(x86_64::XmmRegister(x86_64::XMM0), x86_64::Address(x86_64::CpuRegister(x86_64::RSP), 4));
GetAssembler()->movdqu(x86_64::Address(x86_64::CpuRegister(x86_64::RSP), 2), x86_64::XmmRegister(x86_64::XMM1));
const char* expected =
"movdqu 0x4(%RSP), %xmm0\n"
"movdqu %xmm1, 0x2(%RSP)\n";
DriverStr(expected, "movdqu_address");
}
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, Addps) {
DriverStr(RepeatFF(&x86_64::X86_64Assembler::addps, "addps %{reg2}, %{reg1}"), "addps");
}
TEST_F(AssemblerX86_64Test, Addpd) {
DriverStr(RepeatFF(&x86_64::X86_64Assembler::addpd, "addpd %{reg2}, %{reg1}"), "addpd");
}
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, Subps) {
DriverStr(RepeatFF(&x86_64::X86_64Assembler::subps, "subps %{reg2}, %{reg1}"), "subps");
}
TEST_F(AssemblerX86_64Test, Subpd) {
DriverStr(RepeatFF(&x86_64::X86_64Assembler::subpd, "subpd %{reg2}, %{reg1}"), "subpd");
}
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, Mulps) {
DriverStr(RepeatFF(&x86_64::X86_64Assembler::mulps, "mulps %{reg2}, %{reg1}"), "mulps");
}
TEST_F(AssemblerX86_64Test, Mulpd) {
DriverStr(RepeatFF(&x86_64::X86_64Assembler::mulpd, "mulpd %{reg2}, %{reg1}"), "mulpd");
}
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, Divps) {
DriverStr(RepeatFF(&x86_64::X86_64Assembler::divps, "divps %{reg2}, %{reg1}"), "divps");
}
TEST_F(AssemblerX86_64Test, Divpd) {
DriverStr(RepeatFF(&x86_64::X86_64Assembler::divpd, "divpd %{reg2}, %{reg1}"), "divpd");
}
TEST_F(AssemblerX86_64Test, Paddb) {
DriverStr(RepeatFF(&x86_64::X86_64Assembler::paddb, "paddb %{reg2}, %{reg1}"), "paddb");
}
TEST_F(AssemblerX86_64Test, Psubb) {
DriverStr(RepeatFF(&x86_64::X86_64Assembler::psubb, "psubb %{reg2}, %{reg1}"), "psubb");
}
TEST_F(AssemblerX86_64Test, Paddw) {
DriverStr(RepeatFF(&x86_64::X86_64Assembler::paddw, "paddw %{reg2}, %{reg1}"), "paddw");
}
TEST_F(AssemblerX86_64Test, Psubw) {
DriverStr(RepeatFF(&x86_64::X86_64Assembler::psubw, "psubw %{reg2}, %{reg1}"), "psubw");
}
TEST_F(AssemblerX86_64Test, Pmullw) {
DriverStr(RepeatFF(&x86_64::X86_64Assembler::pmullw, "pmullw %{reg2}, %{reg1}"), "pmullw");
}
TEST_F(AssemblerX86_64Test, Paddd) {
DriverStr(RepeatFF(&x86_64::X86_64Assembler::paddd, "paddd %{reg2}, %{reg1}"), "paddd");
}
TEST_F(AssemblerX86_64Test, Psubd) {
DriverStr(RepeatFF(&x86_64::X86_64Assembler::psubd, "psubd %{reg2}, %{reg1}"), "psubd");
}
TEST_F(AssemblerX86_64Test, Pmulld) {
DriverStr(RepeatFF(&x86_64::X86_64Assembler::pmulld, "pmulld %{reg2}, %{reg1}"), "pmulld");
}
TEST_F(AssemblerX86_64Test, Paddq) {
DriverStr(RepeatFF(&x86_64::X86_64Assembler::paddq, "paddq %{reg2}, %{reg1}"), "paddq");
}
TEST_F(AssemblerX86_64Test, Psubq) {
DriverStr(RepeatFF(&x86_64::X86_64Assembler::psubq, "psubq %{reg2}, %{reg1}"), "psubq");
}
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, Cvtdq2ps) {
DriverStr(RepeatFF(&x86_64::X86_64Assembler::cvtdq2ps, "cvtdq2ps %{reg2}, %{reg1}"), "cvtdq2ps");
}
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, Ucomiss) {
DriverStr(RepeatFF(&x86_64::X86_64Assembler::ucomiss, "ucomiss %{reg2}, %{reg1}"), "ucomiss");
}
TEST_F(AssemblerX86_64Test, Ucomisd) {
DriverStr(RepeatFF(&x86_64::X86_64Assembler::ucomisd, "ucomisd %{reg2}, %{reg1}"), "ucomisd");
}
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, Roundss) {
DriverStr(RepeatFFI(&x86_64::X86_64Assembler::roundss, 1, "roundss ${imm}, %{reg2}, %{reg1}"), "roundss");
}
TEST_F(AssemblerX86_64Test, Roundsd) {
DriverStr(RepeatFFI(&x86_64::X86_64Assembler::roundsd, 1, "roundsd ${imm}, %{reg2}, %{reg1}"), "roundsd");
}
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");
}
TEST_F(AssemblerX86_64Test, Pxor) {
DriverStr(RepeatFF(&x86_64::X86_64Assembler::pxor, "pxor %{reg2}, %{reg1}"), "pxor");
}
TEST_F(AssemblerX86_64Test, Andps) {
DriverStr(RepeatFF(&x86_64::X86_64Assembler::andps, "andps %{reg2}, %{reg1}"), "andps");
}
TEST_F(AssemblerX86_64Test, Andpd) {
DriverStr(RepeatFF(&x86_64::X86_64Assembler::andpd, "andpd %{reg2}, %{reg1}"), "andpd");
}
TEST_F(AssemblerX86_64Test, Pand) {
DriverStr(RepeatFF(&x86_64::X86_64Assembler::pand, "pand %{reg2}, %{reg1}"), "pand");
}
TEST_F(AssemblerX86_64Test, andnpd) {
DriverStr(RepeatFF(&x86_64::X86_64Assembler::andnpd, "andnpd %{reg2}, %{reg1}"), "andnpd");
}
TEST_F(AssemblerX86_64Test, andnps) {
DriverStr(RepeatFF(&x86_64::X86_64Assembler::andnps, "andnps %{reg2}, %{reg1}"), "andnps");
}
TEST_F(AssemblerX86_64Test, Pandn) {
DriverStr(RepeatFF(&x86_64::X86_64Assembler::pandn, "pandn %{reg2}, %{reg1}"), "pandn");
}
TEST_F(AssemblerX86_64Test, Orps) {
DriverStr(RepeatFF(&x86_64::X86_64Assembler::orps, "orps %{reg2}, %{reg1}"), "orps");
}
TEST_F(AssemblerX86_64Test, Orpd) {
DriverStr(RepeatFF(&x86_64::X86_64Assembler::orpd, "orpd %{reg2}, %{reg1}"), "orpd");
}
TEST_F(AssemblerX86_64Test, Por) {
DriverStr(RepeatFF(&x86_64::X86_64Assembler::por, "por %{reg2}, %{reg1}"), "por");
}
TEST_F(AssemblerX86_64Test, Pavgb) {
DriverStr(RepeatFF(&x86_64::X86_64Assembler::pavgb, "pavgb %{reg2}, %{reg1}"), "pavgb");
}
TEST_F(AssemblerX86_64Test, Pavgw) {
DriverStr(RepeatFF(&x86_64::X86_64Assembler::pavgw, "pavgw %{reg2}, %{reg1}"), "pavgw");
}
TEST_F(AssemblerX86_64Test, PCmpeqb) {
DriverStr(RepeatFF(&x86_64::X86_64Assembler::pcmpeqb, "pcmpeqb %{reg2}, %{reg1}"), "pcmpeqb");
}
TEST_F(AssemblerX86_64Test, PCmpeqw) {
DriverStr(RepeatFF(&x86_64::X86_64Assembler::pcmpeqw, "pcmpeqw %{reg2}, %{reg1}"), "pcmpeqw");
}
TEST_F(AssemblerX86_64Test, PCmpeqd) {
DriverStr(RepeatFF(&x86_64::X86_64Assembler::pcmpeqd, "pcmpeqd %{reg2}, %{reg1}"), "pcmpeqd");
}
TEST_F(AssemblerX86_64Test, PCmpeqq) {
DriverStr(RepeatFF(&x86_64::X86_64Assembler::pcmpeqq, "pcmpeqq %{reg2}, %{reg1}"), "pcmpeqq");
}
TEST_F(AssemblerX86_64Test, PCmpgtb) {
DriverStr(RepeatFF(&x86_64::X86_64Assembler::pcmpgtb, "pcmpgtb %{reg2}, %{reg1}"), "pcmpgtb");
}
TEST_F(AssemblerX86_64Test, PCmpgtw) {
DriverStr(RepeatFF(&x86_64::X86_64Assembler::pcmpgtw, "pcmpgtw %{reg2}, %{reg1}"), "pcmpgtw");
}
TEST_F(AssemblerX86_64Test, PCmpgtd) {
DriverStr(RepeatFF(&x86_64::X86_64Assembler::pcmpgtd, "pcmpgtd %{reg2}, %{reg1}"), "pcmpgtd");
}
TEST_F(AssemblerX86_64Test, PCmpgtq) {
DriverStr(RepeatFF(&x86_64::X86_64Assembler::pcmpgtq, "pcmpgtq %{reg2}, %{reg1}"), "pcmpgtq");
}
TEST_F(AssemblerX86_64Test, Shufps) {
DriverStr(RepeatFFI(&x86_64::X86_64Assembler::shufps, 1, "shufps ${imm}, %{reg2}, %{reg1}"), "shufps");
}
TEST_F(AssemblerX86_64Test, Shufpd) {
DriverStr(RepeatFFI(&x86_64::X86_64Assembler::shufpd, 1, "shufpd ${imm}, %{reg2}, %{reg1}"), "shufpd");
}
TEST_F(AssemblerX86_64Test, PShufd) {
DriverStr(RepeatFFI(&x86_64::X86_64Assembler::pshufd, 1, "pshufd ${imm}, %{reg2}, %{reg1}"), "pshufd");
}
TEST_F(AssemblerX86_64Test, Punpcklbw) {
DriverStr(RepeatFF(&x86_64::X86_64Assembler::punpcklbw, "punpcklbw %{reg2}, %{reg1}"), "punpcklbw");
}
TEST_F(AssemblerX86_64Test, Punpcklwd) {
DriverStr(RepeatFF(&x86_64::X86_64Assembler::punpcklwd, "punpcklwd %{reg2}, %{reg1}"), "punpcklwd");
}
TEST_F(AssemblerX86_64Test, Punpckldq) {
DriverStr(RepeatFF(&x86_64::X86_64Assembler::punpckldq, "punpckldq %{reg2}, %{reg1}"), "punpckldq");
}
TEST_F(AssemblerX86_64Test, Punpcklqdq) {
DriverStr(RepeatFF(&x86_64::X86_64Assembler::punpcklqdq, "punpcklqdq %{reg2}, %{reg1}"), "punpcklqdq");
}
TEST_F(AssemblerX86_64Test, Psllw) {
GetAssembler()->psllw(x86_64::XmmRegister(x86_64::XMM0), x86_64::Immediate(1));
GetAssembler()->psllw(x86_64::XmmRegister(x86_64::XMM15), x86_64::Immediate(2));
DriverStr("psllw $1, %xmm0\n"
"psllw $2, %xmm15\n", "psllwi");
}
TEST_F(AssemblerX86_64Test, Pslld) {
GetAssembler()->pslld(x86_64::XmmRegister(x86_64::XMM0), x86_64::Immediate(1));
GetAssembler()->pslld(x86_64::XmmRegister(x86_64::XMM15), x86_64::Immediate(2));
DriverStr("pslld $1, %xmm0\n"
"pslld $2, %xmm15\n", "pslldi");
}
TEST_F(AssemblerX86_64Test, Psllq) {
GetAssembler()->psllq(x86_64::XmmRegister(x86_64::XMM0), x86_64::Immediate(1));
GetAssembler()->psllq(x86_64::XmmRegister(x86_64::XMM15), x86_64::Immediate(2));
DriverStr("psllq $1, %xmm0\n"
"psllq $2, %xmm15\n", "psllqi");
}
TEST_F(AssemblerX86_64Test, Psraw) {
GetAssembler()->psraw(x86_64::XmmRegister(x86_64::XMM0), x86_64::Immediate(1));
GetAssembler()->psraw(x86_64::XmmRegister(x86_64::XMM15), x86_64::Immediate(2));
DriverStr("psraw $1, %xmm0\n"
"psraw $2, %xmm15\n", "psrawi");
}
TEST_F(AssemblerX86_64Test, Psrad) {
GetAssembler()->psrad(x86_64::XmmRegister(x86_64::XMM0), x86_64::Immediate(1));
GetAssembler()->psrad(x86_64::XmmRegister(x86_64::XMM15), x86_64::Immediate(2));
DriverStr("psrad $1, %xmm0\n"
"psrad $2, %xmm15\n", "psradi");
}
TEST_F(AssemblerX86_64Test, Psrlw) {
GetAssembler()->psrlw(x86_64::XmmRegister(x86_64::XMM0), x86_64::Immediate(1));
GetAssembler()->psrlw(x86_64::XmmRegister(x86_64::XMM15), x86_64::Immediate(2));
DriverStr("psrlw $1, %xmm0\n"
"psrlw $2, %xmm15\n", "psrlwi");
}
TEST_F(AssemblerX86_64Test, Psrld) {
GetAssembler()->psrld(x86_64::XmmRegister(x86_64::XMM0), x86_64::Immediate(1));
GetAssembler()->psrld(x86_64::XmmRegister(x86_64::XMM15), x86_64::Immediate(2));
DriverStr("psrld $1, %xmm0\n"
"psrld $2, %xmm15\n", "pslldi");
}
TEST_F(AssemblerX86_64Test, Psrlq) {
GetAssembler()->psrlq(x86_64::XmmRegister(x86_64::XMM0), x86_64::Immediate(1));
GetAssembler()->psrlq(x86_64::XmmRegister(x86_64::XMM15), x86_64::Immediate(2));
DriverStr("psrlq $1, %xmm0\n"
"psrlq $2, %xmm15\n", "pslrqi");
}
TEST_F(AssemblerX86_64Test, UcomissAddress) {
GetAssembler()->ucomiss(x86_64::XmmRegister(x86_64::XMM0), x86_64::Address(
x86_64::CpuRegister(x86_64::RDI), x86_64::CpuRegister(x86_64::RBX), x86_64::TIMES_4, 12));
GetAssembler()->ucomiss(x86_64::XmmRegister(x86_64::XMM1), x86_64::Address(
x86_64::CpuRegister(x86_64::RDI), x86_64::CpuRegister(x86_64::R9), x86_64::TIMES_4, 12));
GetAssembler()->ucomiss(x86_64::XmmRegister(x86_64::XMM2), x86_64::Address(
x86_64::CpuRegister(x86_64::RDI), x86_64::CpuRegister(x86_64::R9), x86_64::TIMES_4, 12));
GetAssembler()->ucomiss(x86_64::XmmRegister(x86_64::XMM3), x86_64::Address(
x86_64::CpuRegister(x86_64::R13), 0));
GetAssembler()->ucomiss(x86_64::XmmRegister(x86_64::XMM4), x86_64::Address(
x86_64::CpuRegister(x86_64::R13), x86_64::CpuRegister(x86_64::R9), x86_64::TIMES_1, 0));
const char* expected =
"ucomiss 0xc(%RDI,%RBX,4), %xmm0\n"
"ucomiss 0xc(%RDI,%R9,4), %xmm1\n"
"ucomiss 0xc(%RDI,%R9,4), %xmm2\n"
"ucomiss (%R13), %xmm3\n"
"ucomiss (%R13,%R9,1), %xmm4\n";
DriverStr(expected, "ucomiss_address");
}
TEST_F(AssemblerX86_64Test, UcomisdAddress) {
GetAssembler()->ucomisd(x86_64::XmmRegister(x86_64::XMM0), x86_64::Address(
x86_64::CpuRegister(x86_64::RDI), x86_64::CpuRegister(x86_64::RBX), x86_64::TIMES_4, 12));
GetAssembler()->ucomisd(x86_64::XmmRegister(x86_64::XMM1), x86_64::Address(
x86_64::CpuRegister(x86_64::RDI), x86_64::CpuRegister(x86_64::R9), x86_64::TIMES_4, 12));
GetAssembler()->ucomisd(x86_64::XmmRegister(x86_64::XMM2), x86_64::Address(
x86_64::CpuRegister(x86_64::RDI), x86_64::CpuRegister(x86_64::R9), x86_64::TIMES_4, 12));
GetAssembler()->ucomisd(x86_64::XmmRegister(x86_64::XMM3), x86_64::Address(
x86_64::CpuRegister(x86_64::R13), 0));
GetAssembler()->ucomisd(x86_64::XmmRegister(x86_64::XMM4), x86_64::Address(
x86_64::CpuRegister(x86_64::R13), x86_64::CpuRegister(x86_64::R9), x86_64::TIMES_1, 0));
const char* expected =
"ucomisd 0xc(%RDI,%RBX,4), %xmm0\n"
"ucomisd 0xc(%RDI,%R9,4), %xmm1\n"
"ucomisd 0xc(%RDI,%R9,4), %xmm2\n"
"ucomisd (%R13), %xmm3\n"
"ucomisd (%R13,%R9,1), %xmm4\n";
DriverStr(expected, "ucomisd_address");
}
// 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");
}
TEST_F(AssemblerX86_64Test, FPUIntegerLoad) {
GetAssembler()->filds(x86_64::Address(x86_64::CpuRegister(x86_64::RSP), 4));
GetAssembler()->fildl(x86_64::Address(x86_64::CpuRegister(x86_64::RSP), 12));
const char* expected =
"fildl 0x4(%RSP)\n"
"fildll 0xc(%RSP)\n";
DriverStr(expected, "FPUIntegerLoad");
}
TEST_F(AssemblerX86_64Test, FPUIntegerStore) {
GetAssembler()->fistps(x86_64::Address(x86_64::CpuRegister(x86_64::RSP), 16));
GetAssembler()->fistpl(x86_64::Address(x86_64::CpuRegister(x86_64::RSP), 24));
const char* expected =
"fistpl 0x10(%RSP)\n"
"fistpll 0x18(%RSP)\n";
DriverStr(expected, "FPUIntegerStore");
}
////////////////
// 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 //
//////////
TEST_F(AssemblerX86_64Test, Bswapl) {
DriverStr(Repeatr(&x86_64::X86_64Assembler::bswapl, "bswap %{reg}"), "bswapl");
}
TEST_F(AssemblerX86_64Test, Bswapq) {
DriverStr(RepeatR(&x86_64::X86_64Assembler::bswapq, "bswap %{reg}"), "bswapq");
}
TEST_F(AssemblerX86_64Test, Bsfl) {
DriverStr(Repeatrr(&x86_64::X86_64Assembler::bsfl, "bsfl %{reg2}, %{reg1}"), "bsfl");
}
TEST_F(AssemblerX86_64Test, BsflAddress) {
GetAssembler()->bsfl(x86_64::CpuRegister(x86_64::R10), x86_64::Address(
x86_64::CpuRegister(x86_64::RDI), x86_64::CpuRegister(x86_64::RBX), x86_64::TIMES_4, 12));
GetAssembler()->bsfl(x86_64::CpuRegister(x86_64::RDI), x86_64::Address(
x86_64::CpuRegister(x86_64::R10), x86_64::CpuRegister(x86_64::RBX), x86_64::TIMES_4, 12));
GetAssembler()->bsfl(x86_64::CpuRegister(x86_64::RDI), x86_64::Address(
x86_64::CpuRegister(x86_64::RDI), x86_64::CpuRegister(x86_64::R9), x86_64::TIMES_4, 12));
const char* expected =
"bsfl 0xc(%RDI,%RBX,4), %R10d\n"
"bsfl 0xc(%R10,%RBX,4), %edi\n"
"bsfl 0xc(%RDI,%R9,4), %edi\n";
DriverStr(expected, "bsfl_address");
}
TEST_F(AssemblerX86_64Test, Bsfq) {
DriverStr(RepeatRR(&x86_64::X86_64Assembler::bsfq, "bsfq %{reg2}, %{reg1}"), "bsfq");
}
TEST_F(AssemblerX86_64Test, BsfqAddress) {
GetAssembler()->bsfq(x86_64::CpuRegister(x86_64::R10), x86_64::Address(
x86_64::CpuRegister(x86_64::RDI), x86_64::CpuRegister(x86_64::RBX), x86_64::TIMES_4, 12));
GetAssembler()->bsfq(x86_64::CpuRegister(x86_64::RDI), x86_64::Address(
x86_64::CpuRegister(x86_64::R10), x86_64::CpuRegister(x86_64::RBX), x86_64::TIMES_4, 12));
GetAssembler()->bsfq(x86_64::CpuRegister(x86_64::RDI), x86_64::Address(
x86_64::CpuRegister(x86_64::RDI), x86_64::CpuRegister(x86_64::R9), x86_64::TIMES_4, 12));
const char* expected =
"bsfq 0xc(%RDI,%RBX,4), %R10\n"
"bsfq 0xc(%R10,%RBX,4), %RDI\n"
"bsfq 0xc(%RDI,%R9,4), %RDI\n";
DriverStr(expected, "bsfq_address");
}
TEST_F(AssemblerX86_64Test, Bsrl) {
DriverStr(Repeatrr(&x86_64::X86_64Assembler::bsrl, "bsrl %{reg2}, %{reg1}"), "bsrl");
}
TEST_F(AssemblerX86_64Test, BsrlAddress) {
GetAssembler()->bsrl(x86_64::CpuRegister(x86_64::R10), x86_64::Address(
x86_64::CpuRegister(x86_64::RDI), x86_64::CpuRegister(x86_64::RBX), x86_64::TIMES_4, 12));
GetAssembler()->bsrl(x86_64::CpuRegister(x86_64::RDI), x86_64::Address(
x86_64::CpuRegister(x86_64::R10), x86_64::CpuRegister(x86_64::RBX), x86_64::TIMES_4, 12));
GetAssembler()->bsrl(x86_64::CpuRegister(x86_64::RDI), x86_64::Address(
x86_64::CpuRegister(x86_64::RDI), x86_64::CpuRegister(x86_64::R9), x86_64::TIMES_4, 12));
const char* expected =
"bsrl 0xc(%RDI,%RBX,4), %R10d\n"
"bsrl 0xc(%R10,%RBX,4), %edi\n"
"bsrl 0xc(%RDI,%R9,4), %edi\n";
DriverStr(expected, "bsrl_address");
}
TEST_F(AssemblerX86_64Test, Bsrq) {
DriverStr(RepeatRR(&x86_64::X86_64Assembler::bsrq, "bsrq %{reg2}, %{reg1}"), "bsrq");
}
TEST_F(AssemblerX86_64Test, BsrqAddress) {
GetAssembler()->bsrq(x86_64::CpuRegister(x86_64::R10), x86_64::Address(
x86_64::CpuRegister(x86_64::RDI), x86_64::CpuRegister(x86_64::RBX), x86_64::TIMES_4, 12));
GetAssembler()->bsrq(x86_64::CpuRegister(x86_64::RDI), x86_64::Address(
x86_64::CpuRegister(x86_64::R10), x86_64::CpuRegister(x86_64::RBX), x86_64::TIMES_4, 12));
GetAssembler()->bsrq(x86_64::CpuRegister(x86_64::RDI), x86_64::Address(
x86_64::CpuRegister(x86_64::RDI), x86_64::CpuRegister(x86_64::R9), x86_64::TIMES_4, 12));
const char* expected =
"bsrq 0xc(%RDI,%RBX,4), %R10\n"
"bsrq 0xc(%R10,%RBX,4), %RDI\n"
"bsrq 0xc(%RDI,%R9,4), %RDI\n";
DriverStr(expected, "bsrq_address");
}
TEST_F(AssemblerX86_64Test, Popcntl) {
DriverStr(Repeatrr(&x86_64::X86_64Assembler::popcntl, "popcntl %{reg2}, %{reg1}"), "popcntl");
}
TEST_F(AssemblerX86_64Test, PopcntlAddress) {
GetAssembler()->popcntl(x86_64::CpuRegister(x86_64::R10), x86_64::Address(
x86_64::CpuRegister(x86_64::RDI), x86_64::CpuRegister(x86_64::RBX), x86_64::TIMES_4, 12));
GetAssembler()->popcntl(x86_64::CpuRegister(x86_64::RDI), x86_64::Address(
x86_64::CpuRegister(x86_64::R10), x86_64::CpuRegister(x86_64::RBX), x86_64::TIMES_4, 12));
GetAssembler()->popcntl(x86_64::CpuRegister(x86_64::RDI), x86_64::Address(
x86_64::CpuRegister(x86_64::RDI), x86_64::CpuRegister(x86_64::R9), x86_64::TIMES_4, 12));
const char* expected =
"popcntl 0xc(%RDI,%RBX,4), %R10d\n"
"popcntl 0xc(%R10,%RBX,4), %edi\n"
"popcntl 0xc(%RDI,%R9,4), %edi\n";
DriverStr(expected, "popcntl_address");
}
TEST_F(AssemblerX86_64Test, Popcntq) {
DriverStr(RepeatRR(&x86_64::X86_64Assembler::popcntq, "popcntq %{reg2}, %{reg1}"), "popcntq");
}
TEST_F(AssemblerX86_64Test, PopcntqAddress) {
GetAssembler()->popcntq(x86_64::CpuRegister(x86_64::R10), x86_64::Address(
x86_64::CpuRegister(x86_64::RDI), x86_64::CpuRegister(x86_64::RBX), x86_64::TIMES_4, 12));
GetAssembler()->popcntq(x86_64::CpuRegister(x86_64::RDI), x86_64::Address(
x86_64::CpuRegister(x86_64::R10), x86_64::CpuRegister(x86_64::RBX), x86_64::TIMES_4, 12));
GetAssembler()->popcntq(x86_64::CpuRegister(x86_64::RDI), x86_64::Address(
x86_64::CpuRegister(x86_64::RDI), x86_64::CpuRegister(x86_64::R9), x86_64::TIMES_4, 12));
const char* expected =
"popcntq 0xc(%RDI,%RBX,4), %R10\n"
"popcntq 0xc(%R10,%RBX,4), %RDI\n"
"popcntq 0xc(%RDI,%R9,4), %RDI\n";
DriverStr(expected, "popcntq_address");
}
TEST_F(AssemblerX86_64Test, CmovlAddress) {
GetAssembler()->cmov(x86_64::kEqual, x86_64::CpuRegister(x86_64::R10), x86_64::Address(
x86_64::CpuRegister(x86_64::RDI), x86_64::CpuRegister(x86_64::RBX), x86_64::TIMES_4, 12), false);
GetAssembler()->cmov(x86_64::kNotEqual, x86_64::CpuRegister(x86_64::RDI), x86_64::Address(
x86_64::CpuRegister(x86_64::R10), x86_64::CpuRegister(x86_64::RBX), x86_64::TIMES_4, 12), false);
GetAssembler()->cmov(x86_64::kEqual, x86_64::CpuRegister(x86_64::RDI), x86_64::Address(
x86_64::CpuRegister(x86_64::RDI), x86_64::CpuRegister(x86_64::R9), x86_64::TIMES_4, 12), false);
const char* expected =
"cmovzl 0xc(%RDI,%RBX,4), %R10d\n"
"cmovnzl 0xc(%R10,%RBX,4), %edi\n"
"cmovzl 0xc(%RDI,%R9,4), %edi\n";
DriverStr(expected, "cmovl_address");
}
TEST_F(AssemblerX86_64Test, CmovqAddress) {
GetAssembler()->cmov(x86_64::kEqual, x86_64::CpuRegister(x86_64::R10), x86_64::Address(
x86_64::CpuRegister(x86_64::RDI), x86_64::CpuRegister(x86_64::RBX), x86_64::TIMES_4, 12), true);
GetAssembler()->cmov(x86_64::kNotEqual, x86_64::CpuRegister(x86_64::RDI), x86_64::Address(
x86_64::CpuRegister(x86_64::R10), x86_64::CpuRegister(x86_64::RBX), x86_64::TIMES_4, 12), true);
GetAssembler()->cmov(x86_64::kEqual, x86_64::CpuRegister(x86_64::RDI), x86_64::Address(
x86_64::CpuRegister(x86_64::RDI), x86_64::CpuRegister(x86_64::R9), x86_64::TIMES_4, 12), true);
const char* expected =
"cmovzq 0xc(%RDI,%RBX,4), %R10\n"
"cmovnzq 0xc(%R10,%RBX,4), %rdi\n"
"cmovzq 0xc(%RDI,%R9,4), %rdi\n";
DriverStr(expected, "cmovq_address");
}
/////////////////
// Near labels //
/////////////////
TEST_F(AssemblerX86_64Test, Jrcxz) {
x86_64::NearLabel target;
GetAssembler()->jrcxz(&target);
GetAssembler()->addl(x86_64::CpuRegister(x86_64::RDI),
x86_64::Address(x86_64::CpuRegister(x86_64::RSP), 4));
GetAssembler()->Bind(&target);
const char* expected =
"jrcxz 1f\n"
"addl 4(%RSP),%EDI\n"
"1:\n";
DriverStr(expected, "jrcxz");
}
TEST_F(AssemblerX86_64Test, NearLabel) {
// Test both forward and backward branches.
x86_64::NearLabel start, target;
GetAssembler()->Bind(&start);
GetAssembler()->j(x86_64::kEqual, &target);
GetAssembler()->jmp(&target);
GetAssembler()->jrcxz(&target);
GetAssembler()->addl(x86_64::CpuRegister(x86_64::RDI),
x86_64::Address(x86_64::CpuRegister(x86_64::RSP), 4));
GetAssembler()->Bind(&target);
GetAssembler()->j(x86_64::kNotEqual, &start);
GetAssembler()->jmp(&start);
const char* expected =
"1: je 2f\n"
"jmp 2f\n"
"jrcxz 2f\n"
"addl 4(%RSP),%EDI\n"
"2: jne 1b\n"
"jmp 1b\n";
DriverStr(expected, "near_label");
}
std::string setcc_test_fn(AssemblerX86_64Test::Base* assembler_test,
x86_64::X86_64Assembler* assembler) {
// From Condition
/*
kOverflow = 0,
kNoOverflow = 1,
kBelow = 2,
kAboveEqual = 3,
kEqual = 4,
kNotEqual = 5,
kBelowEqual = 6,
kAbove = 7,
kSign = 8,
kNotSign = 9,
kParityEven = 10,
kParityOdd = 11,
kLess = 12,
kGreaterEqual = 13,
kLessEqual = 14,
*/
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 = assembler_test->GetRegisters();
std::ostringstream str;
for (auto reg : registers) {
for (size_t i = 0; i < 15; ++i) {
assembler->setcc(static_cast<x86_64::Condition>(i), *reg);
str << "set" << suffixes[i] << " %" << assembler_test->GetQuaternaryRegisterName(*reg) << "\n";
}
}
return str.str();
}
TEST_F(AssemblerX86_64Test, SetCC) {
DriverFn(&setcc_test_fn, "setcc");
}
TEST_F(AssemblerX86_64Test, MovzxbRegs) {
DriverStr(Repeatrb(&x86_64::X86_64Assembler::movzxb, "movzbl %{reg2}, %{reg1}"), "movzxb");
}
TEST_F(AssemblerX86_64Test, MovsxbRegs) {
DriverStr(Repeatrb(&x86_64::X86_64Assembler::movsxb, "movsbl %{reg2}, %{reg1}"), "movsxb");
}
TEST_F(AssemblerX86_64Test, Repnescasw) {
GetAssembler()->repne_scasw();
const char* expected = "repne scasw\n";
DriverStr(expected, "Repnescasw");
}
TEST_F(AssemblerX86_64Test, Repecmpsw) {
GetAssembler()->repe_cmpsw();
const char* expected = "repe cmpsw\n";
DriverStr(expected, "Repecmpsw");
}
TEST_F(AssemblerX86_64Test, Repecmpsl) {
GetAssembler()->repe_cmpsl();
const char* expected = "repe cmpsl\n";
DriverStr(expected, "Repecmpsl");
}
TEST_F(AssemblerX86_64Test, Repecmpsq) {
GetAssembler()->repe_cmpsq();
const char* expected = "repe cmpsq\n";
DriverStr(expected, "Repecmpsq");
}
TEST_F(AssemblerX86_64Test, Cmpb) {
GetAssembler()->cmpb(x86_64::Address(x86_64::CpuRegister(x86_64::RDI), 128),
x86_64::Immediate(0));
const char* expected = "cmpb $0, 128(%RDI)\n";
DriverStr(expected, "cmpb");
}
TEST_F(AssemblerX86_64Test, TestbAddressImmediate) {
GetAssembler()->testb(
x86_64::Address(x86_64::CpuRegister(x86_64::RDI),
x86_64::CpuRegister(x86_64::RBX),
x86_64::TIMES_4,
12),
x86_64::Immediate(1));
GetAssembler()->testb(
x86_64::Address(x86_64::CpuRegister(x86_64::RSP), FrameOffset(7)),
x86_64::Immediate(-128));
GetAssembler()->testb(
x86_64::Address(x86_64::CpuRegister(x86_64::RBX), MemberOffset(130)),
x86_64::Immediate(127));
const char* expected =
"testb $1, 0xc(%RDI,%RBX,4)\n"
"testb $-128, 0x7(%RSP)\n"
"testb $127, 0x82(%RBX)\n";
DriverStr(expected, "TestbAddressImmediate");
}
TEST_F(AssemblerX86_64Test, TestlAddressImmediate) {
GetAssembler()->testl(
x86_64::Address(x86_64::CpuRegister(x86_64::RDI),
x86_64::CpuRegister(x86_64::RBX),
x86_64::TIMES_4,
12),
x86_64::Immediate(1));
GetAssembler()->testl(
x86_64::Address(x86_64::CpuRegister(x86_64::RSP), FrameOffset(7)),
x86_64::Immediate(-100000));
GetAssembler()->testl(
x86_64::Address(x86_64::CpuRegister(x86_64::RBX), MemberOffset(130)),
x86_64::Immediate(77777777));
const char* expected =
"testl $1, 0xc(%RDI,%RBX,4)\n"
"testl $-100000, 0x7(%RSP)\n"
"testl $77777777, 0x82(%RBX)\n";
DriverStr(expected, "TestlAddressImmediate");
}
class JNIMacroAssemblerX86_64Test : public JNIMacroAssemblerTest<x86_64::X86_64JNIMacroAssembler> {
public:
using Base = JNIMacroAssemblerTest<x86_64::X86_64JNIMacroAssembler>;
protected:
// Get the typically used name for this architecture, e.g., aarch64, x86-64, ...
std::string GetArchitectureString() OVERRIDE {
return "x86_64";
}
std::string GetDisassembleParameters() OVERRIDE {
return " -D -bbinary -mi386:x86-64 -Mx86-64,addr64,data32 --no-show-raw-insn";
}
private:
};
static x86_64::X86_64ManagedRegister ManagedFromCpu(x86_64::Register r) {
return x86_64::X86_64ManagedRegister::FromCpuRegister(r);
}
static x86_64::X86_64ManagedRegister ManagedFromFpu(x86_64::FloatRegister r) {
return x86_64::X86_64ManagedRegister::FromXmmRegister(r);
}
std::string buildframe_test_fn(JNIMacroAssemblerX86_64Test::Base* assembler_test ATTRIBUTE_UNUSED,
x86_64::X86_64JNIMacroAssembler* assembler) {
// TODO: more interesting spill registers / entry spills.
// Two random spill regs.
const ManagedRegister raw_spill_regs[] = {
ManagedFromCpu(x86_64::R10),
ManagedFromCpu(x86_64::RSI)
};
ArrayRef<const ManagedRegister> spill_regs(raw_spill_regs);
// Three random entry spills.
ManagedRegisterEntrySpills entry_spills;
ManagedRegisterSpill spill(ManagedFromCpu(x86_64::RAX), 8, 0);
entry_spills.push_back(spill);
ManagedRegisterSpill spill2(ManagedFromCpu(x86_64::RBX), 8, 8);
entry_spills.push_back(spill2);
ManagedRegisterSpill spill3(ManagedFromFpu(x86_64::XMM1), 8, 16);
entry_spills.push_back(spill3);
x86_64::X86_64ManagedRegister method_reg = ManagedFromCpu(x86_64::RDI);
size_t frame_size = 10 * kStackAlignment;
assembler->BuildFrame(10 * kStackAlignment, method_reg, spill_regs, entry_spills);
// Construct assembly text counterpart.
std::ostringstream str;
// 1) Push the spill_regs.
str << "pushq %rsi\n";
str << "pushq %r10\n";
// 2) Move down the stack pointer.
ssize_t displacement = static_cast<ssize_t>(frame_size) - (spill_regs.size() * 8 + 8);
str << "subq $" << displacement << ", %rsp\n";
// 3) Store method reference.
str << "movq %rdi, (%rsp)\n";
// 4) Entry spills.
str << "movq %rax, " << frame_size + 0 << "(%rsp)\n";
str << "movq %rbx, " << frame_size + 8 << "(%rsp)\n";
str << "movsd %xmm1, " << frame_size + 16 << "(%rsp)\n";
return str.str();
}
TEST_F(JNIMacroAssemblerX86_64Test, BuildFrame) {
DriverFn(&buildframe_test_fn, "BuildFrame");
}
std::string removeframe_test_fn(JNIMacroAssemblerX86_64Test::Base* assembler_test ATTRIBUTE_UNUSED,
x86_64::X86_64JNIMacroAssembler* assembler) {
// TODO: more interesting spill registers / entry spills.
// Two random spill regs.
const ManagedRegister raw_spill_regs[] = {
ManagedFromCpu(x86_64::R10),
ManagedFromCpu(x86_64::RSI)
};
ArrayRef<const ManagedRegister> spill_regs(raw_spill_regs);
size_t frame_size = 10 * kStackAlignment;
assembler->RemoveFrame(10 * kStackAlignment, spill_regs);
// Construct assembly text counterpart.
std::ostringstream str;
// 1) Move up the stack pointer.
ssize_t displacement = static_cast<ssize_t>(frame_size) - spill_regs.size() * 8 - 8;
str << "addq $" << displacement << ", %rsp\n";
// 2) Pop spill regs.
str << "popq %r10\n";
str << "popq %rsi\n";
str << "ret\n";
return str.str();
}
TEST_F(JNIMacroAssemblerX86_64Test, RemoveFrame) {
DriverFn(&removeframe_test_fn, "RemoveFrame");
}
std::string increaseframe_test_fn(
JNIMacroAssemblerX86_64Test::Base* assembler_test ATTRIBUTE_UNUSED,
x86_64::X86_64JNIMacroAssembler* assembler) {
assembler->IncreaseFrameSize(0U);
assembler->IncreaseFrameSize(kStackAlignment);
assembler->IncreaseFrameSize(10 * kStackAlignment);
// Construct assembly text counterpart.
std::ostringstream str;
str << "addq $0, %rsp\n";
str << "addq $-" << kStackAlignment << ", %rsp\n";
str << "addq $-" << 10 * kStackAlignment << ", %rsp\n";
return str.str();
}
TEST_F(JNIMacroAssemblerX86_64Test, IncreaseFrame) {
DriverFn(&increaseframe_test_fn, "IncreaseFrame");
}
std::string decreaseframe_test_fn(
JNIMacroAssemblerX86_64Test::Base* assembler_test ATTRIBUTE_UNUSED,
x86_64::X86_64JNIMacroAssembler* assembler) {
assembler->DecreaseFrameSize(0U);
assembler->DecreaseFrameSize(kStackAlignment);
assembler->DecreaseFrameSize(10 * kStackAlignment);
// Construct assembly text counterpart.
std::ostringstream str;
str << "addq $0, %rsp\n";
str << "addq $" << kStackAlignment << ", %rsp\n";
str << "addq $" << 10 * kStackAlignment << ", %rsp\n";
return str.str();
}
TEST_F(JNIMacroAssemblerX86_64Test, DecreaseFrame) {
DriverFn(&decreaseframe_test_fn, "DecreaseFrame");
}
} // namespace art