/*
* Copyright (C) 2015 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_mips.h"
#include <map>
#include "base/stl_util.h"
#include "utils/assembler_test.h"
#define __ GetAssembler()->
namespace art {
struct MIPSCpuRegisterCompare {
bool operator()(const mips::Register& a, const mips::Register& b) const {
return a < b;
}
};
class AssemblerMIPSTest : public AssemblerTest<mips::MipsAssembler,
mips::MipsLabel,
mips::Register,
mips::FRegister,
uint32_t> {
public:
using Base = AssemblerTest<mips::MipsAssembler,
mips::MipsLabel,
mips::Register,
mips::FRegister,
uint32_t>;
// These tests were taking too long, so we hide the DriverStr() from AssemblerTest<>
// and reimplement it without the verification against `assembly_string`. b/73903608
void DriverStr(const std::string& assembly_string ATTRIBUTE_UNUSED,
const std::string& test_name ATTRIBUTE_UNUSED) {
GetAssembler()->FinalizeCode();
std::vector<uint8_t> data(GetAssembler()->CodeSize());
MemoryRegion code(data.data(), data.size());
GetAssembler()->FinalizeInstructions(code);
}
protected:
// Get the typically used name for this architecture, e.g., aarch64, x86-64, ...
std::string GetArchitectureString() override {
return "mips";
}
std::string GetAssemblerParameters() override {
return " --no-warn -32 -march=mips32r2";
}
std::string GetDisassembleParameters() override {
return " -D -bbinary -mmips:isa32r2";
}
void SetUpHelpers() override {
if (registers_.size() == 0) {
registers_.push_back(new mips::Register(mips::ZERO));
registers_.push_back(new mips::Register(mips::AT));
registers_.push_back(new mips::Register(mips::V0));
registers_.push_back(new mips::Register(mips::V1));
registers_.push_back(new mips::Register(mips::A0));
registers_.push_back(new mips::Register(mips::A1));
registers_.push_back(new mips::Register(mips::A2));
registers_.push_back(new mips::Register(mips::A3));
registers_.push_back(new mips::Register(mips::T0));
registers_.push_back(new mips::Register(mips::T1));
registers_.push_back(new mips::Register(mips::T2));
registers_.push_back(new mips::Register(mips::T3));
registers_.push_back(new mips::Register(mips::T4));
registers_.push_back(new mips::Register(mips::T5));
registers_.push_back(new mips::Register(mips::T6));
registers_.push_back(new mips::Register(mips::T7));
registers_.push_back(new mips::Register(mips::S0));
registers_.push_back(new mips::Register(mips::S1));
registers_.push_back(new mips::Register(mips::S2));
registers_.push_back(new mips::Register(mips::S3));
registers_.push_back(new mips::Register(mips::S4));
registers_.push_back(new mips::Register(mips::S5));
registers_.push_back(new mips::Register(mips::S6));
registers_.push_back(new mips::Register(mips::S7));
registers_.push_back(new mips::Register(mips::T8));
registers_.push_back(new mips::Register(mips::T9));
registers_.push_back(new mips::Register(mips::K0));
registers_.push_back(new mips::Register(mips::K1));
registers_.push_back(new mips::Register(mips::GP));
registers_.push_back(new mips::Register(mips::SP));
registers_.push_back(new mips::Register(mips::FP));
registers_.push_back(new mips::Register(mips::RA));
secondary_register_names_.emplace(mips::Register(mips::ZERO), "zero");
secondary_register_names_.emplace(mips::Register(mips::AT), "at");
secondary_register_names_.emplace(mips::Register(mips::V0), "v0");
secondary_register_names_.emplace(mips::Register(mips::V1), "v1");
secondary_register_names_.emplace(mips::Register(mips::A0), "a0");
secondary_register_names_.emplace(mips::Register(mips::A1), "a1");
secondary_register_names_.emplace(mips::Register(mips::A2), "a2");
secondary_register_names_.emplace(mips::Register(mips::A3), "a3");
secondary_register_names_.emplace(mips::Register(mips::T0), "t0");
secondary_register_names_.emplace(mips::Register(mips::T1), "t1");
secondary_register_names_.emplace(mips::Register(mips::T2), "t2");
secondary_register_names_.emplace(mips::Register(mips::T3), "t3");
secondary_register_names_.emplace(mips::Register(mips::T4), "t4");
secondary_register_names_.emplace(mips::Register(mips::T5), "t5");
secondary_register_names_.emplace(mips::Register(mips::T6), "t6");
secondary_register_names_.emplace(mips::Register(mips::T7), "t7");
secondary_register_names_.emplace(mips::Register(mips::S0), "s0");
secondary_register_names_.emplace(mips::Register(mips::S1), "s1");
secondary_register_names_.emplace(mips::Register(mips::S2), "s2");
secondary_register_names_.emplace(mips::Register(mips::S3), "s3");
secondary_register_names_.emplace(mips::Register(mips::S4), "s4");
secondary_register_names_.emplace(mips::Register(mips::S5), "s5");
secondary_register_names_.emplace(mips::Register(mips::S6), "s6");
secondary_register_names_.emplace(mips::Register(mips::S7), "s7");
secondary_register_names_.emplace(mips::Register(mips::T8), "t8");
secondary_register_names_.emplace(mips::Register(mips::T9), "t9");
secondary_register_names_.emplace(mips::Register(mips::K0), "k0");
secondary_register_names_.emplace(mips::Register(mips::K1), "k1");
secondary_register_names_.emplace(mips::Register(mips::GP), "gp");
secondary_register_names_.emplace(mips::Register(mips::SP), "sp");
secondary_register_names_.emplace(mips::Register(mips::FP), "fp");
secondary_register_names_.emplace(mips::Register(mips::RA), "ra");
fp_registers_.push_back(new mips::FRegister(mips::F0));
fp_registers_.push_back(new mips::FRegister(mips::F1));
fp_registers_.push_back(new mips::FRegister(mips::F2));
fp_registers_.push_back(new mips::FRegister(mips::F3));
fp_registers_.push_back(new mips::FRegister(mips::F4));
fp_registers_.push_back(new mips::FRegister(mips::F5));
fp_registers_.push_back(new mips::FRegister(mips::F6));
fp_registers_.push_back(new mips::FRegister(mips::F7));
fp_registers_.push_back(new mips::FRegister(mips::F8));
fp_registers_.push_back(new mips::FRegister(mips::F9));
fp_registers_.push_back(new mips::FRegister(mips::F10));
fp_registers_.push_back(new mips::FRegister(mips::F11));
fp_registers_.push_back(new mips::FRegister(mips::F12));
fp_registers_.push_back(new mips::FRegister(mips::F13));
fp_registers_.push_back(new mips::FRegister(mips::F14));
fp_registers_.push_back(new mips::FRegister(mips::F15));
fp_registers_.push_back(new mips::FRegister(mips::F16));
fp_registers_.push_back(new mips::FRegister(mips::F17));
fp_registers_.push_back(new mips::FRegister(mips::F18));
fp_registers_.push_back(new mips::FRegister(mips::F19));
fp_registers_.push_back(new mips::FRegister(mips::F20));
fp_registers_.push_back(new mips::FRegister(mips::F21));
fp_registers_.push_back(new mips::FRegister(mips::F22));
fp_registers_.push_back(new mips::FRegister(mips::F23));
fp_registers_.push_back(new mips::FRegister(mips::F24));
fp_registers_.push_back(new mips::FRegister(mips::F25));
fp_registers_.push_back(new mips::FRegister(mips::F26));
fp_registers_.push_back(new mips::FRegister(mips::F27));
fp_registers_.push_back(new mips::FRegister(mips::F28));
fp_registers_.push_back(new mips::FRegister(mips::F29));
fp_registers_.push_back(new mips::FRegister(mips::F30));
fp_registers_.push_back(new mips::FRegister(mips::F31));
}
}
void TearDown() override {
AssemblerTest::TearDown();
STLDeleteElements(®isters_);
STLDeleteElements(&fp_registers_);
}
std::vector<mips::MipsLabel> GetAddresses() override {
UNIMPLEMENTED(FATAL) << "Feature not implemented yet";
UNREACHABLE();
}
std::vector<mips::Register*> GetRegisters() override {
return registers_;
}
std::vector<mips::FRegister*> GetFPRegisters() override {
return fp_registers_;
}
uint32_t CreateImmediate(int64_t imm_value) override {
return imm_value;
}
std::string GetSecondaryRegisterName(const mips::Register& reg) override {
CHECK(secondary_register_names_.find(reg) != secondary_register_names_.end());
return secondary_register_names_[reg];
}
std::string RepeatInsn(size_t count, const std::string& insn) {
std::string result;
for (; count != 0u; --count) {
result += insn;
}
return result;
}
void BranchHelper(void (mips::MipsAssembler::*f)(mips::MipsLabel*,
bool),
const std::string& instr_name,
bool is_bare = false) {
__ SetReorder(false);
mips::MipsLabel label1, label2;
(Base::GetAssembler()->*f)(&label1, is_bare);
constexpr size_t kAdduCount1 = 63;
for (size_t i = 0; i != kAdduCount1; ++i) {
__ Addu(mips::ZERO, mips::ZERO, mips::ZERO);
}
__ Bind(&label1);
(Base::GetAssembler()->*f)(&label2, is_bare);
constexpr size_t kAdduCount2 = 64;
for (size_t i = 0; i != kAdduCount2; ++i) {
__ Addu(mips::ZERO, mips::ZERO, mips::ZERO);
}
__ Bind(&label2);
(Base::GetAssembler()->*f)(&label1, is_bare);
__ Addu(mips::ZERO, mips::ZERO, mips::ZERO);
std::string expected =
".set noreorder\n" +
instr_name + " 1f\n" +
(is_bare ? "" : "nop\n") +
RepeatInsn(kAdduCount1, "addu $zero, $zero, $zero\n") +
"1:\n" +
instr_name + " 2f\n" +
(is_bare ? "" : "nop\n") +
RepeatInsn(kAdduCount2, "addu $zero, $zero, $zero\n") +
"2:\n" +
instr_name + " 1b\n" +
(is_bare ? "" : "nop\n") +
"addu $zero, $zero, $zero\n";
DriverStr(expected, instr_name);
}
void BranchCondOneRegHelper(void (mips::MipsAssembler::*f)(mips::Register,
mips::MipsLabel*,
bool),
const std::string& instr_name,
bool is_bare = false) {
__ SetReorder(false);
mips::MipsLabel label;
(Base::GetAssembler()->*f)(mips::A0, &label, is_bare);
constexpr size_t kAdduCount1 = 63;
for (size_t i = 0; i != kAdduCount1; ++i) {
__ Addu(mips::ZERO, mips::ZERO, mips::ZERO);
}
__ Bind(&label);
constexpr size_t kAdduCount2 = 64;
for (size_t i = 0; i != kAdduCount2; ++i) {
__ Addu(mips::ZERO, mips::ZERO, mips::ZERO);
}
(Base::GetAssembler()->*f)(mips::A1, &label, is_bare);
__ Addu(mips::ZERO, mips::ZERO, mips::ZERO);
std::string expected =
".set noreorder\n" +
instr_name + " $a0, 1f\n" +
(is_bare ? "" : "nop\n") +
RepeatInsn(kAdduCount1, "addu $zero, $zero, $zero\n") +
"1:\n" +
RepeatInsn(kAdduCount2, "addu $zero, $zero, $zero\n") +
instr_name + " $a1, 1b\n" +
(is_bare ? "" : "nop\n") +
"addu $zero, $zero, $zero\n";
DriverStr(expected, instr_name);
}
void BranchCondTwoRegsHelper(void (mips::MipsAssembler::*f)(mips::Register,
mips::Register,
mips::MipsLabel*,
bool),
const std::string& instr_name,
bool is_bare = false) {
__ SetReorder(false);
mips::MipsLabel label;
(Base::GetAssembler()->*f)(mips::A0, mips::A1, &label, is_bare);
constexpr size_t kAdduCount1 = 63;
for (size_t i = 0; i != kAdduCount1; ++i) {
__ Addu(mips::ZERO, mips::ZERO, mips::ZERO);
}
__ Bind(&label);
constexpr size_t kAdduCount2 = 64;
for (size_t i = 0; i != kAdduCount2; ++i) {
__ Addu(mips::ZERO, mips::ZERO, mips::ZERO);
}
(Base::GetAssembler()->*f)(mips::A2, mips::A3, &label, is_bare);
__ Addu(mips::ZERO, mips::ZERO, mips::ZERO);
std::string expected =
".set noreorder\n" +
instr_name + " $a0, $a1, 1f\n" +
(is_bare ? "" : "nop\n") +
RepeatInsn(kAdduCount1, "addu $zero, $zero, $zero\n") +
"1:\n" +
RepeatInsn(kAdduCount2, "addu $zero, $zero, $zero\n") +
instr_name + " $a2, $a3, 1b\n" +
(is_bare ? "" : "nop\n") +
"addu $zero, $zero, $zero\n";
DriverStr(expected, instr_name);
}
void BranchFpuCondCodeHelper(void (mips::MipsAssembler::*f)(int,
mips::MipsLabel*,
bool),
const std::string& instr_name,
bool is_bare = false) {
__ SetReorder(false);
mips::MipsLabel label;
(Base::GetAssembler()->*f)(0, &label, is_bare);
constexpr size_t kAdduCount1 = 63;
for (size_t i = 0; i != kAdduCount1; ++i) {
__ Addu(mips::ZERO, mips::ZERO, mips::ZERO);
}
__ Bind(&label);
constexpr size_t kAdduCount2 = 64;
for (size_t i = 0; i != kAdduCount2; ++i) {
__ Addu(mips::ZERO, mips::ZERO, mips::ZERO);
}
(Base::GetAssembler()->*f)(7, &label, is_bare);
__ Addu(mips::ZERO, mips::ZERO, mips::ZERO);
std::string expected =
".set noreorder\n" +
instr_name + " $fcc0, 1f\n" +
(is_bare ? "" : "nop\n") +
RepeatInsn(kAdduCount1, "addu $zero, $zero, $zero\n") +
"1:\n" +
RepeatInsn(kAdduCount2, "addu $zero, $zero, $zero\n") +
instr_name + " $fcc7, 1b\n" +
(is_bare ? "" : "nop\n") +
"addu $zero, $zero, $zero\n";
DriverStr(expected, instr_name);
}
private:
std::vector<mips::Register*> registers_;
std::map<mips::Register, std::string, MIPSCpuRegisterCompare> secondary_register_names_;
std::vector<mips::FRegister*> fp_registers_;
};
TEST_F(AssemblerMIPSTest, Toolchain) {
EXPECT_TRUE(CheckTools());
}
TEST_F(AssemblerMIPSTest, Addu) {
DriverStr(RepeatRRR(&mips::MipsAssembler::Addu, "addu ${reg1}, ${reg2}, ${reg3}"), "Addu");
}
TEST_F(AssemblerMIPSTest, Addiu) {
DriverStr(RepeatRRIb(&mips::MipsAssembler::Addiu, -16, "addiu ${reg1}, ${reg2}, {imm}"), "Addiu");
}
TEST_F(AssemblerMIPSTest, Subu) {
DriverStr(RepeatRRR(&mips::MipsAssembler::Subu, "subu ${reg1}, ${reg2}, ${reg3}"), "Subu");
}
TEST_F(AssemblerMIPSTest, MultR2) {
DriverStr(RepeatRR(&mips::MipsAssembler::MultR2, "mult ${reg1}, ${reg2}"), "MultR2");
}
TEST_F(AssemblerMIPSTest, MultuR2) {
DriverStr(RepeatRR(&mips::MipsAssembler::MultuR2, "multu ${reg1}, ${reg2}"), "MultuR2");
}
TEST_F(AssemblerMIPSTest, DivR2Basic) {
DriverStr(RepeatRR(&mips::MipsAssembler::DivR2, "div $zero, ${reg1}, ${reg2}"), "DivR2Basic");
}
TEST_F(AssemblerMIPSTest, DivuR2Basic) {
DriverStr(RepeatRR(&mips::MipsAssembler::DivuR2, "divu $zero, ${reg1}, ${reg2}"), "DivuR2Basic");
}
TEST_F(AssemblerMIPSTest, MulR2) {
DriverStr(RepeatRRR(&mips::MipsAssembler::MulR2, "mul ${reg1}, ${reg2}, ${reg3}"), "MulR2");
}
TEST_F(AssemblerMIPSTest, DivR2) {
DriverStr(RepeatRRR(&mips::MipsAssembler::DivR2, "div $zero, ${reg2}, ${reg3}\nmflo ${reg1}"),
"DivR2");
}
TEST_F(AssemblerMIPSTest, ModR2) {
DriverStr(RepeatRRR(&mips::MipsAssembler::ModR2, "div $zero, ${reg2}, ${reg3}\nmfhi ${reg1}"),
"ModR2");
}
TEST_F(AssemblerMIPSTest, DivuR2) {
DriverStr(RepeatRRR(&mips::MipsAssembler::DivuR2, "divu $zero, ${reg2}, ${reg3}\nmflo ${reg1}"),
"DivuR2");
}
TEST_F(AssemblerMIPSTest, ModuR2) {
DriverStr(RepeatRRR(&mips::MipsAssembler::ModuR2, "divu $zero, ${reg2}, ${reg3}\nmfhi ${reg1}"),
"ModuR2");
}
TEST_F(AssemblerMIPSTest, And) {
DriverStr(RepeatRRR(&mips::MipsAssembler::And, "and ${reg1}, ${reg2}, ${reg3}"), "And");
}
TEST_F(AssemblerMIPSTest, Andi) {
DriverStr(RepeatRRIb(&mips::MipsAssembler::Andi, 16, "andi ${reg1}, ${reg2}, {imm}"), "Andi");
}
TEST_F(AssemblerMIPSTest, Or) {
DriverStr(RepeatRRR(&mips::MipsAssembler::Or, "or ${reg1}, ${reg2}, ${reg3}"), "Or");
}
TEST_F(AssemblerMIPSTest, Ori) {
DriverStr(RepeatRRIb(&mips::MipsAssembler::Ori, 16, "ori ${reg1}, ${reg2}, {imm}"), "Ori");
}
TEST_F(AssemblerMIPSTest, Xor) {
DriverStr(RepeatRRR(&mips::MipsAssembler::Xor, "xor ${reg1}, ${reg2}, ${reg3}"), "Xor");
}
TEST_F(AssemblerMIPSTest, Xori) {
DriverStr(RepeatRRIb(&mips::MipsAssembler::Xori, 16, "xori ${reg1}, ${reg2}, {imm}"), "Xori");
}
TEST_F(AssemblerMIPSTest, Nor) {
DriverStr(RepeatRRR(&mips::MipsAssembler::Nor, "nor ${reg1}, ${reg2}, ${reg3}"), "Nor");
}
//////////
// MISC //
//////////
TEST_F(AssemblerMIPSTest, Movz) {
DriverStr(RepeatRRR(&mips::MipsAssembler::Movz, "movz ${reg1}, ${reg2}, ${reg3}"), "Movz");
}
TEST_F(AssemblerMIPSTest, Movn) {
DriverStr(RepeatRRR(&mips::MipsAssembler::Movn, "movn ${reg1}, ${reg2}, ${reg3}"), "Movn");
}
TEST_F(AssemblerMIPSTest, Seb) {
DriverStr(RepeatRR(&mips::MipsAssembler::Seb, "seb ${reg1}, ${reg2}"), "Seb");
}
TEST_F(AssemblerMIPSTest, Seh) {
DriverStr(RepeatRR(&mips::MipsAssembler::Seh, "seh ${reg1}, ${reg2}"), "Seh");
}
TEST_F(AssemblerMIPSTest, Sll) {
DriverStr(RepeatRRIb(&mips::MipsAssembler::Sll, 5, "sll ${reg1}, ${reg2}, {imm}"), "Sll");
}
TEST_F(AssemblerMIPSTest, Srl) {
DriverStr(RepeatRRIb(&mips::MipsAssembler::Srl, 5, "srl ${reg1}, ${reg2}, {imm}"), "Srl");
}
TEST_F(AssemblerMIPSTest, Sra) {
DriverStr(RepeatRRIb(&mips::MipsAssembler::Sra, 5, "sra ${reg1}, ${reg2}, {imm}"), "Sra");
}
TEST_F(AssemblerMIPSTest, Sllv) {
DriverStr(RepeatRRR(&mips::MipsAssembler::Sllv, "sllv ${reg1}, ${reg2}, ${reg3}"), "Sllv");
}
TEST_F(AssemblerMIPSTest, Srlv) {
DriverStr(RepeatRRR(&mips::MipsAssembler::Srlv, "srlv ${reg1}, ${reg2}, ${reg3}"), "Srlv");
}
TEST_F(AssemblerMIPSTest, Rotrv) {
DriverStr(RepeatRRR(&mips::MipsAssembler::Rotrv, "rotrv ${reg1}, ${reg2}, ${reg3}"), "rotrv");
}
TEST_F(AssemblerMIPSTest, Srav) {
DriverStr(RepeatRRR(&mips::MipsAssembler::Srav, "srav ${reg1}, ${reg2}, ${reg3}"), "Srav");
}
TEST_F(AssemblerMIPSTest, Ins) {
std::vector<mips::Register*> regs = GetRegisters();
WarnOnCombinations(regs.size() * regs.size() * 33 * 16);
std::string expected;
for (mips::Register* reg1 : regs) {
for (mips::Register* reg2 : regs) {
for (int32_t pos = 0; pos < 32; pos++) {
for (int32_t size = 1; pos + size <= 32; size++) {
__ Ins(*reg1, *reg2, pos, size);
std::ostringstream instr;
instr << "ins $" << *reg1 << ", $" << *reg2 << ", " << pos << ", " << size << "\n";
expected += instr.str();
}
}
}
}
DriverStr(expected, "Ins");
}
TEST_F(AssemblerMIPSTest, Ext) {
std::vector<mips::Register*> regs = GetRegisters();
WarnOnCombinations(regs.size() * regs.size() * 33 * 16);
std::string expected;
for (mips::Register* reg1 : regs) {
for (mips::Register* reg2 : regs) {
for (int32_t pos = 0; pos < 32; pos++) {
for (int32_t size = 1; pos + size <= 32; size++) {
__ Ext(*reg1, *reg2, pos, size);
std::ostringstream instr;
instr << "ext $" << *reg1 << ", $" << *reg2 << ", " << pos << ", " << size << "\n";
expected += instr.str();
}
}
}
}
DriverStr(expected, "Ext");
}
TEST_F(AssemblerMIPSTest, ClzR2) {
DriverStr(RepeatRR(&mips::MipsAssembler::ClzR2, "clz ${reg1}, ${reg2}"), "clzR2");
}
TEST_F(AssemblerMIPSTest, CloR2) {
DriverStr(RepeatRR(&mips::MipsAssembler::CloR2, "clo ${reg1}, ${reg2}"), "cloR2");
}
TEST_F(AssemblerMIPSTest, Lb) {
DriverStr(RepeatRRIb(&mips::MipsAssembler::Lb, -16, "lb ${reg1}, {imm}(${reg2})"), "Lb");
}
TEST_F(AssemblerMIPSTest, Lh) {
DriverStr(RepeatRRIb(&mips::MipsAssembler::Lh, -16, "lh ${reg1}, {imm}(${reg2})"), "Lh");
}
TEST_F(AssemblerMIPSTest, Lwl) {
DriverStr(RepeatRRIb(&mips::MipsAssembler::Lwl, -16, "lwl ${reg1}, {imm}(${reg2})"), "Lwl");
}
TEST_F(AssemblerMIPSTest, Lw) {
DriverStr(RepeatRRIb(&mips::MipsAssembler::Lw, -16, "lw ${reg1}, {imm}(${reg2})"), "Lw");
}
TEST_F(AssemblerMIPSTest, Lwr) {
DriverStr(RepeatRRIb(&mips::MipsAssembler::Lwr, -16, "lwr ${reg1}, {imm}(${reg2})"), "Lwr");
}
TEST_F(AssemblerMIPSTest, Lbu) {
DriverStr(RepeatRRIb(&mips::MipsAssembler::Lbu, -16, "lbu ${reg1}, {imm}(${reg2})"), "Lbu");
}
TEST_F(AssemblerMIPSTest, Lhu) {
DriverStr(RepeatRRIb(&mips::MipsAssembler::Lhu, -16, "lhu ${reg1}, {imm}(${reg2})"), "Lhu");
}
TEST_F(AssemblerMIPSTest, Lui) {
DriverStr(RepeatRIb(&mips::MipsAssembler::Lui, 16, "lui ${reg}, {imm}"), "Lui");
}
TEST_F(AssemblerMIPSTest, Mfhi) {
DriverStr(RepeatR(&mips::MipsAssembler::Mfhi, "mfhi ${reg}"), "Mfhi");
}
TEST_F(AssemblerMIPSTest, Mflo) {
DriverStr(RepeatR(&mips::MipsAssembler::Mflo, "mflo ${reg}"), "Mflo");
}
TEST_F(AssemblerMIPSTest, Sb) {
DriverStr(RepeatRRIb(&mips::MipsAssembler::Sb, -16, "sb ${reg1}, {imm}(${reg2})"), "Sb");
}
TEST_F(AssemblerMIPSTest, Sh) {
DriverStr(RepeatRRIb(&mips::MipsAssembler::Sh, -16, "sh ${reg1}, {imm}(${reg2})"), "Sh");
}
TEST_F(AssemblerMIPSTest, Swl) {
DriverStr(RepeatRRIb(&mips::MipsAssembler::Swl, -16, "swl ${reg1}, {imm}(${reg2})"), "Swl");
}
TEST_F(AssemblerMIPSTest, Sw) {
DriverStr(RepeatRRIb(&mips::MipsAssembler::Sw, -16, "sw ${reg1}, {imm}(${reg2})"), "Sw");
}
TEST_F(AssemblerMIPSTest, Swr) {
DriverStr(RepeatRRIb(&mips::MipsAssembler::Swr, -16, "swr ${reg1}, {imm}(${reg2})"), "Swr");
}
TEST_F(AssemblerMIPSTest, LlR2) {
DriverStr(RepeatRRIb(&mips::MipsAssembler::LlR2, -16, "ll ${reg1}, {imm}(${reg2})"), "LlR2");
}
TEST_F(AssemblerMIPSTest, ScR2) {
DriverStr(RepeatRRIb(&mips::MipsAssembler::ScR2, -16, "sc ${reg1}, {imm}(${reg2})"), "ScR2");
}
TEST_F(AssemblerMIPSTest, Slt) {
DriverStr(RepeatRRR(&mips::MipsAssembler::Slt, "slt ${reg1}, ${reg2}, ${reg3}"), "Slt");
}
TEST_F(AssemblerMIPSTest, Sltu) {
DriverStr(RepeatRRR(&mips::MipsAssembler::Sltu, "sltu ${reg1}, ${reg2}, ${reg3}"), "Sltu");
}
TEST_F(AssemblerMIPSTest, Slti) {
DriverStr(RepeatRRIb(&mips::MipsAssembler::Slti, -16, "slti ${reg1}, ${reg2}, {imm}"), "Slti");
}
TEST_F(AssemblerMIPSTest, Sltiu) {
DriverStr(RepeatRRIb(&mips::MipsAssembler::Sltiu, -16, "sltiu ${reg1}, ${reg2}, {imm}"), "Sltiu");
}
TEST_F(AssemblerMIPSTest, AddS) {
DriverStr(RepeatFFF(&mips::MipsAssembler::AddS, "add.s ${reg1}, ${reg2}, ${reg3}"), "AddS");
}
TEST_F(AssemblerMIPSTest, AddD) {
DriverStr(RepeatFFF(&mips::MipsAssembler::AddD, "add.d ${reg1}, ${reg2}, ${reg3}"), "AddD");
}
TEST_F(AssemblerMIPSTest, SubS) {
DriverStr(RepeatFFF(&mips::MipsAssembler::SubS, "sub.s ${reg1}, ${reg2}, ${reg3}"), "SubS");
}
TEST_F(AssemblerMIPSTest, SubD) {
DriverStr(RepeatFFF(&mips::MipsAssembler::SubD, "sub.d ${reg1}, ${reg2}, ${reg3}"), "SubD");
}
TEST_F(AssemblerMIPSTest, MulS) {
DriverStr(RepeatFFF(&mips::MipsAssembler::MulS, "mul.s ${reg1}, ${reg2}, ${reg3}"), "MulS");
}
TEST_F(AssemblerMIPSTest, MulD) {
DriverStr(RepeatFFF(&mips::MipsAssembler::MulD, "mul.d ${reg1}, ${reg2}, ${reg3}"), "MulD");
}
TEST_F(AssemblerMIPSTest, DivS) {
DriverStr(RepeatFFF(&mips::MipsAssembler::DivS, "div.s ${reg1}, ${reg2}, ${reg3}"), "DivS");
}
TEST_F(AssemblerMIPSTest, DivD) {
DriverStr(RepeatFFF(&mips::MipsAssembler::DivD, "div.d ${reg1}, ${reg2}, ${reg3}"), "DivD");
}
TEST_F(AssemblerMIPSTest, MovS) {
DriverStr(RepeatFF(&mips::MipsAssembler::MovS, "mov.s ${reg1}, ${reg2}"), "MovS");
}
TEST_F(AssemblerMIPSTest, MovD) {
DriverStr(RepeatFF(&mips::MipsAssembler::MovD, "mov.d ${reg1}, ${reg2}"), "MovD");
}
TEST_F(AssemblerMIPSTest, NegS) {
DriverStr(RepeatFF(&mips::MipsAssembler::NegS, "neg.s ${reg1}, ${reg2}"), "NegS");
}
TEST_F(AssemblerMIPSTest, NegD) {
DriverStr(RepeatFF(&mips::MipsAssembler::NegD, "neg.d ${reg1}, ${reg2}"), "NegD");
}
TEST_F(AssemblerMIPSTest, FloorWS) {
DriverStr(RepeatFF(&mips::MipsAssembler::FloorWS, "floor.w.s ${reg1}, ${reg2}"), "floor.w.s");
}
TEST_F(AssemblerMIPSTest, FloorWD) {
DriverStr(RepeatFF(&mips::MipsAssembler::FloorWD, "floor.w.d ${reg1}, ${reg2}"), "floor.w.d");
}
TEST_F(AssemblerMIPSTest, CunS) {
DriverStr(RepeatIbFF(&mips::MipsAssembler::CunS, 3, "c.un.s $fcc{imm}, ${reg1}, ${reg2}"),
"CunS");
}
TEST_F(AssemblerMIPSTest, CeqS) {
DriverStr(RepeatIbFF(&mips::MipsAssembler::CeqS, 3, "c.eq.s $fcc{imm}, ${reg1}, ${reg2}"),
"CeqS");
}
TEST_F(AssemblerMIPSTest, CueqS) {
DriverStr(RepeatIbFF(&mips::MipsAssembler::CueqS, 3, "c.ueq.s $fcc{imm}, ${reg1}, ${reg2}"),
"CueqS");
}
TEST_F(AssemblerMIPSTest, ColtS) {
DriverStr(RepeatIbFF(&mips::MipsAssembler::ColtS, 3, "c.olt.s $fcc{imm}, ${reg1}, ${reg2}"),
"ColtS");
}
TEST_F(AssemblerMIPSTest, CultS) {
DriverStr(RepeatIbFF(&mips::MipsAssembler::CultS, 3, "c.ult.s $fcc{imm}, ${reg1}, ${reg2}"),
"CultS");
}
TEST_F(AssemblerMIPSTest, ColeS) {
DriverStr(RepeatIbFF(&mips::MipsAssembler::ColeS, 3, "c.ole.s $fcc{imm}, ${reg1}, ${reg2}"),
"ColeS");
}
TEST_F(AssemblerMIPSTest, CuleS) {
DriverStr(RepeatIbFF(&mips::MipsAssembler::CuleS, 3, "c.ule.s $fcc{imm}, ${reg1}, ${reg2}"),
"CuleS");
}
TEST_F(AssemblerMIPSTest, CunD) {
DriverStr(RepeatIbFF(&mips::MipsAssembler::CunD, 3, "c.un.d $fcc{imm}, ${reg1}, ${reg2}"),
"CunD");
}
TEST_F(AssemblerMIPSTest, CeqD) {
DriverStr(RepeatIbFF(&mips::MipsAssembler::CeqD, 3, "c.eq.d $fcc{imm}, ${reg1}, ${reg2}"),
"CeqD");
}
TEST_F(AssemblerMIPSTest, CueqD) {
DriverStr(RepeatIbFF(&mips::MipsAssembler::CueqD, 3, "c.ueq.d $fcc{imm}, ${reg1}, ${reg2}"),
"CueqD");
}
TEST_F(AssemblerMIPSTest, ColtD) {
DriverStr(RepeatIbFF(&mips::MipsAssembler::ColtD, 3, "c.olt.d $fcc{imm}, ${reg1}, ${reg2}"),
"ColtD");
}
TEST_F(AssemblerMIPSTest, CultD) {
DriverStr(RepeatIbFF(&mips::MipsAssembler::CultD, 3, "c.ult.d $fcc{imm}, ${reg1}, ${reg2}"),
"CultD");
}
TEST_F(AssemblerMIPSTest, ColeD) {
DriverStr(RepeatIbFF(&mips::MipsAssembler::ColeD, 3, "c.ole.d $fcc{imm}, ${reg1}, ${reg2}"),
"ColeD");
}
TEST_F(AssemblerMIPSTest, CuleD) {
DriverStr(RepeatIbFF(&mips::MipsAssembler::CuleD, 3, "c.ule.d $fcc{imm}, ${reg1}, ${reg2}"),
"CuleD");
}
TEST_F(AssemblerMIPSTest, Movf) {
DriverStr(RepeatRRIb(&mips::MipsAssembler::Movf, 3, "movf ${reg1}, ${reg2}, $fcc{imm}"), "Movf");
}
TEST_F(AssemblerMIPSTest, Movt) {
DriverStr(RepeatRRIb(&mips::MipsAssembler::Movt, 3, "movt ${reg1}, ${reg2}, $fcc{imm}"), "Movt");
}
TEST_F(AssemblerMIPSTest, MovfS) {
DriverStr(RepeatFFIb(&mips::MipsAssembler::MovfS, 3, "movf.s ${reg1}, ${reg2}, $fcc{imm}"),
"MovfS");
}
TEST_F(AssemblerMIPSTest, MovfD) {
DriverStr(RepeatFFIb(&mips::MipsAssembler::MovfD, 3, "movf.d ${reg1}, ${reg2}, $fcc{imm}"),
"MovfD");
}
TEST_F(AssemblerMIPSTest, MovtS) {
DriverStr(RepeatFFIb(&mips::MipsAssembler::MovtS, 3, "movt.s ${reg1}, ${reg2}, $fcc{imm}"),
"MovtS");
}
TEST_F(AssemblerMIPSTest, MovtD) {
DriverStr(RepeatFFIb(&mips::MipsAssembler::MovtD, 3, "movt.d ${reg1}, ${reg2}, $fcc{imm}"),
"MovtD");
}
TEST_F(AssemblerMIPSTest, MovzS) {
DriverStr(RepeatFFR(&mips::MipsAssembler::MovzS, "movz.s ${reg1}, ${reg2}, ${reg3}"), "MovzS");
}
TEST_F(AssemblerMIPSTest, MovzD) {
DriverStr(RepeatFFR(&mips::MipsAssembler::MovzD, "movz.d ${reg1}, ${reg2}, ${reg3}"), "MovzD");
}
TEST_F(AssemblerMIPSTest, MovnS) {
DriverStr(RepeatFFR(&mips::MipsAssembler::MovnS, "movn.s ${reg1}, ${reg2}, ${reg3}"), "MovnS");
}
TEST_F(AssemblerMIPSTest, MovnD) {
DriverStr(RepeatFFR(&mips::MipsAssembler::MovnD, "movn.d ${reg1}, ${reg2}, ${reg3}"), "MovnD");
}
TEST_F(AssemblerMIPSTest, CvtSW) {
DriverStr(RepeatFF(&mips::MipsAssembler::Cvtsw, "cvt.s.w ${reg1}, ${reg2}"), "CvtSW");
}
TEST_F(AssemblerMIPSTest, CvtDW) {
DriverStr(RepeatFF(&mips::MipsAssembler::Cvtdw, "cvt.d.w ${reg1}, ${reg2}"), "CvtDW");
}
TEST_F(AssemblerMIPSTest, CvtSL) {
DriverStr(RepeatFF(&mips::MipsAssembler::Cvtsl, "cvt.s.l ${reg1}, ${reg2}"), "CvtSL");
}
TEST_F(AssemblerMIPSTest, CvtDL) {
DriverStr(RepeatFF(&mips::MipsAssembler::Cvtdl, "cvt.d.l ${reg1}, ${reg2}"), "CvtDL");
}
TEST_F(AssemblerMIPSTest, CvtSD) {
DriverStr(RepeatFF(&mips::MipsAssembler::Cvtsd, "cvt.s.d ${reg1}, ${reg2}"), "CvtSD");
}
TEST_F(AssemblerMIPSTest, CvtDS) {
DriverStr(RepeatFF(&mips::MipsAssembler::Cvtds, "cvt.d.s ${reg1}, ${reg2}"), "CvtDS");
}
TEST_F(AssemblerMIPSTest, TruncWS) {
DriverStr(RepeatFF(&mips::MipsAssembler::TruncWS, "trunc.w.s ${reg1}, ${reg2}"), "TruncWS");
}
TEST_F(AssemblerMIPSTest, TruncWD) {
DriverStr(RepeatFF(&mips::MipsAssembler::TruncWD, "trunc.w.d ${reg1}, ${reg2}"), "TruncWD");
}
TEST_F(AssemblerMIPSTest, TruncLS) {
DriverStr(RepeatFF(&mips::MipsAssembler::TruncLS, "trunc.l.s ${reg1}, ${reg2}"), "TruncLS");
}
TEST_F(AssemblerMIPSTest, TruncLD) {
DriverStr(RepeatFF(&mips::MipsAssembler::TruncLD, "trunc.l.d ${reg1}, ${reg2}"), "TruncLD");
}
TEST_F(AssemblerMIPSTest, Mfc1) {
DriverStr(RepeatRF(&mips::MipsAssembler::Mfc1, "mfc1 ${reg1}, ${reg2}"), "Mfc1");
}
TEST_F(AssemblerMIPSTest, Mtc1) {
DriverStr(RepeatRF(&mips::MipsAssembler::Mtc1, "mtc1 ${reg1}, ${reg2}"), "Mtc1");
}
TEST_F(AssemblerMIPSTest, Mfhc1) {
DriverStr(RepeatRF(&mips::MipsAssembler::Mfhc1, "mfhc1 ${reg1}, ${reg2}"), "Mfhc1");
}
TEST_F(AssemblerMIPSTest, Mthc1) {
DriverStr(RepeatRF(&mips::MipsAssembler::Mthc1, "mthc1 ${reg1}, ${reg2}"), "Mthc1");
}
TEST_F(AssemblerMIPSTest, Lwc1) {
DriverStr(RepeatFRIb(&mips::MipsAssembler::Lwc1, -16, "lwc1 ${reg1}, {imm}(${reg2})"), "Lwc1");
}
TEST_F(AssemblerMIPSTest, Ldc1) {
DriverStr(RepeatFRIb(&mips::MipsAssembler::Ldc1, -16, "ldc1 ${reg1}, {imm}(${reg2})"), "Ldc1");
}
TEST_F(AssemblerMIPSTest, Swc1) {
DriverStr(RepeatFRIb(&mips::MipsAssembler::Swc1, -16, "swc1 ${reg1}, {imm}(${reg2})"), "Swc1");
}
TEST_F(AssemblerMIPSTest, Sdc1) {
DriverStr(RepeatFRIb(&mips::MipsAssembler::Sdc1, -16, "sdc1 ${reg1}, {imm}(${reg2})"), "Sdc1");
}
TEST_F(AssemblerMIPSTest, Move) {
DriverStr(RepeatRR(&mips::MipsAssembler::Move, "or ${reg1}, ${reg2}, $zero"), "Move");
}
TEST_F(AssemblerMIPSTest, Clear) {
DriverStr(RepeatR(&mips::MipsAssembler::Clear, "or ${reg}, $zero, $zero"), "Clear");
}
TEST_F(AssemblerMIPSTest, Not) {
DriverStr(RepeatRR(&mips::MipsAssembler::Not, "nor ${reg1}, ${reg2}, $zero"), "Not");
}
TEST_F(AssemblerMIPSTest, Addiu32) {
__ Addiu32(mips::A1, mips::A2, -0x8000);
__ Addiu32(mips::A1, mips::A2, +0);
__ Addiu32(mips::A1, mips::A2, +0x7FFF);
__ Addiu32(mips::A1, mips::A2, -0x10000);
__ Addiu32(mips::A1, mips::A2, -0x8001);
__ Addiu32(mips::A1, mips::A2, +0x8000);
__ Addiu32(mips::A1, mips::A2, +0xFFFE);
__ Addiu32(mips::A1, mips::A2, -0x10001);
__ Addiu32(mips::A1, mips::A2, +0xFFFF);
__ Addiu32(mips::A1, mips::A2, +0x10000);
__ Addiu32(mips::A1, mips::A2, +0x10001);
__ Addiu32(mips::A1, mips::A2, +0x12345678);
const char* expected =
"addiu $a1, $a2, -0x8000\n"
"addiu $a1, $a2, 0\n"
"addiu $a1, $a2, 0x7FFF\n"
"addiu $at, $a2, -0x8000\n"
"addiu $a1, $at, -0x8000\n"
"addiu $at, $a2, -0x8000\n"
"addiu $a1, $at, -1\n"
"addiu $at, $a2, 0x7FFF\n"
"addiu $a1, $at, 1\n"
"addiu $at, $a2, 0x7FFF\n"
"addiu $a1, $at, 0x7FFF\n"
"lui $at, 0xFFFE\n"
"ori $at, $at, 0xFFFF\n"
"addu $a1, $a2, $at\n"
"ori $at, $zero, 0xFFFF\n"
"addu $a1, $a2, $at\n"
"lui $at, 1\n"
"addu $a1, $a2, $at\n"
"lui $at, 1\n"
"ori $at, $at, 1\n"
"addu $a1, $a2, $at\n"
"lui $at, 0x1234\n"
"ori $at, $at, 0x5678\n"
"addu $a1, $a2, $at\n";
DriverStr(expected, "Addiu32");
}
TEST_F(AssemblerMIPSTest, LoadFromOffset) {
__ LoadFromOffset(mips::kLoadSignedByte, mips::A3, mips::A1, -0x8000);
__ LoadFromOffset(mips::kLoadSignedByte, mips::A3, mips::A1, +0);
__ LoadFromOffset(mips::kLoadSignedByte, mips::A3, mips::A1, +0x7FF8);
__ LoadFromOffset(mips::kLoadSignedByte, mips::A3, mips::A1, +0x7FFB);
__ LoadFromOffset(mips::kLoadSignedByte, mips::A3, mips::A1, +0x7FFC);
__ LoadFromOffset(mips::kLoadSignedByte, mips::A3, mips::A1, +0x7FFF);
__ LoadFromOffset(mips::kLoadSignedByte, mips::A3, mips::A1, -0xFFF0);
__ LoadFromOffset(mips::kLoadSignedByte, mips::A3, mips::A1, -0x8008);
__ LoadFromOffset(mips::kLoadSignedByte, mips::A3, mips::A1, -0x8001);
__ LoadFromOffset(mips::kLoadSignedByte, mips::A3, mips::A1, +0x8000);
__ LoadFromOffset(mips::kLoadSignedByte, mips::A3, mips::A1, +0xFFF0);
__ LoadFromOffset(mips::kLoadSignedByte, mips::A3, mips::A1, -0x17FE8);
__ LoadFromOffset(mips::kLoadSignedByte, mips::A3, mips::A1, -0x0FFF8);
__ LoadFromOffset(mips::kLoadSignedByte, mips::A3, mips::A1, -0x0FFF1);
__ LoadFromOffset(mips::kLoadSignedByte, mips::A3, mips::A1, +0x0FFF1);
__ LoadFromOffset(mips::kLoadSignedByte, mips::A3, mips::A1, +0x0FFF8);
__ LoadFromOffset(mips::kLoadSignedByte, mips::A3, mips::A1, +0x17FE8);
__ LoadFromOffset(mips::kLoadSignedByte, mips::A3, mips::A1, -0x17FF0);
__ LoadFromOffset(mips::kLoadSignedByte, mips::A3, mips::A1, -0x17FE9);
__ LoadFromOffset(mips::kLoadSignedByte, mips::A3, mips::A1, +0x17FE9);
__ LoadFromOffset(mips::kLoadSignedByte, mips::A3, mips::A1, +0x17FF0);
__ LoadFromOffset(mips::kLoadSignedByte, mips::A3, mips::A1, +0x12345678);
__ LoadFromOffset(mips::kLoadUnsignedByte, mips::A3, mips::A1, -0x8000);
__ LoadFromOffset(mips::kLoadUnsignedByte, mips::A3, mips::A1, +0);
__ LoadFromOffset(mips::kLoadUnsignedByte, mips::A3, mips::A1, +0x7FF8);
__ LoadFromOffset(mips::kLoadUnsignedByte, mips::A3, mips::A1, +0x7FFB);
__ LoadFromOffset(mips::kLoadUnsignedByte, mips::A3, mips::A1, +0x7FFC);
__ LoadFromOffset(mips::kLoadUnsignedByte, mips::A3, mips::A1, +0x7FFF);
__ LoadFromOffset(mips::kLoadUnsignedByte, mips::A3, mips::A1, -0xFFF0);
__ LoadFromOffset(mips::kLoadUnsignedByte, mips::A3, mips::A1, -0x8008);
__ LoadFromOffset(mips::kLoadUnsignedByte, mips::A3, mips::A1, -0x8001);
__ LoadFromOffset(mips::kLoadUnsignedByte, mips::A3, mips::A1, +0x8000);
__ LoadFromOffset(mips::kLoadUnsignedByte, mips::A3, mips::A1, +0xFFF0);
__ LoadFromOffset(mips::kLoadUnsignedByte, mips::A3, mips::A1, -0x17FE8);
__ LoadFromOffset(mips::kLoadUnsignedByte, mips::A3, mips::A1, -0x0FFF8);
__ LoadFromOffset(mips::kLoadUnsignedByte, mips::A3, mips::A1, -0x0FFF1);
__ LoadFromOffset(mips::kLoadUnsignedByte, mips::A3, mips::A1, +0x0FFF1);
__ LoadFromOffset(mips::kLoadUnsignedByte, mips::A3, mips::A1, +0x0FFF8);
__ LoadFromOffset(mips::kLoadUnsignedByte, mips::A3, mips::A1, +0x17FE8);
__ LoadFromOffset(mips::kLoadUnsignedByte, mips::A3, mips::A1, -0x17FF0);
__ LoadFromOffset(mips::kLoadUnsignedByte, mips::A3, mips::A1, -0x17FE9);
__ LoadFromOffset(mips::kLoadUnsignedByte, mips::A3, mips::A1, +0x17FE9);
__ LoadFromOffset(mips::kLoadUnsignedByte, mips::A3, mips::A1, +0x17FF0);
__ LoadFromOffset(mips::kLoadUnsignedByte, mips::A3, mips::A1, +0x12345678);
__ LoadFromOffset(mips::kLoadSignedHalfword, mips::A3, mips::A1, -0x8000);
__ LoadFromOffset(mips::kLoadSignedHalfword, mips::A3, mips::A1, +0);
__ LoadFromOffset(mips::kLoadSignedHalfword, mips::A3, mips::A1, +0x7FF8);
__ LoadFromOffset(mips::kLoadSignedHalfword, mips::A3, mips::A1, +0x7FFB);
__ LoadFromOffset(mips::kLoadSignedHalfword, mips::A3, mips::A1, +0x7FFC);
__ LoadFromOffset(mips::kLoadSignedHalfword, mips::A3, mips::A1, +0x7FFF);
__ LoadFromOffset(mips::kLoadSignedHalfword, mips::A3, mips::A1, -0xFFF0);
__ LoadFromOffset(mips::kLoadSignedHalfword, mips::A3, mips::A1, -0x8008);
__ LoadFromOffset(mips::kLoadSignedHalfword, mips::A3, mips::A1, -0x8001);
__ LoadFromOffset(mips::kLoadSignedHalfword, mips::A3, mips::A1, +0x8000);
__ LoadFromOffset(mips::kLoadSignedHalfword, mips::A3, mips::A1, +0xFFF0);
__ LoadFromOffset(mips::kLoadSignedHalfword, mips::A3, mips::A1, -0x17FE8);
__ LoadFromOffset(mips::kLoadSignedHalfword, mips::A3, mips::A1, -0x0FFF8);
__ LoadFromOffset(mips::kLoadSignedHalfword, mips::A3, mips::A1, -0x0FFF1);
__ LoadFromOffset(mips::kLoadSignedHalfword, mips::A3, mips::A1, +0x0FFF1);
__ LoadFromOffset(mips::kLoadSignedHalfword, mips::A3, mips::A1, +0x0FFF8);
__ LoadFromOffset(mips::kLoadSignedHalfword, mips::A3, mips::A1, +0x17FE8);
__ LoadFromOffset(mips::kLoadSignedHalfword, mips::A3, mips::A1, -0x17FF0);
__ LoadFromOffset(mips::kLoadSignedHalfword, mips::A3, mips::A1, -0x17FE9);
__ LoadFromOffset(mips::kLoadSignedHalfword, mips::A3, mips::A1, +0x17FE9);
__ LoadFromOffset(mips::kLoadSignedHalfword, mips::A3, mips::A1, +0x17FF0);
__ LoadFromOffset(mips::kLoadSignedHalfword, mips::A3, mips::A1, +0x12345678);
__ LoadFromOffset(mips::kLoadUnsignedHalfword, mips::A3, mips::A1, -0x8000);
__ LoadFromOffset(mips::kLoadUnsignedHalfword, mips::A3, mips::A1, +0);
__ LoadFromOffset(mips::kLoadUnsignedHalfword, mips::A3, mips::A1, +0x7FF8);
__ LoadFromOffset(mips::kLoadUnsignedHalfword, mips::A3, mips::A1, +0x7FFB);
__ LoadFromOffset(mips::kLoadUnsignedHalfword, mips::A3, mips::A1, +0x7FFC);
__ LoadFromOffset(mips::kLoadUnsignedHalfword, mips::A3, mips::A1, +0x7FFF);
__ LoadFromOffset(mips::kLoadUnsignedHalfword, mips::A3, mips::A1, -0xFFF0);
__ LoadFromOffset(mips::kLoadUnsignedHalfword, mips::A3, mips::A1, -0x8008);
__ LoadFromOffset(mips::kLoadUnsignedHalfword, mips::A3, mips::A1, -0x8001);
__ LoadFromOffset(mips::kLoadUnsignedHalfword, mips::A3, mips::A1, +0x8000);
__ LoadFromOffset(mips::kLoadUnsignedHalfword, mips::A3, mips::A1, +0xFFF0);
__ LoadFromOffset(mips::kLoadUnsignedHalfword, mips::A3, mips::A1, -0x17FE8);
__ LoadFromOffset(mips::kLoadUnsignedHalfword, mips::A3, mips::A1, -0x0FFF8);
__ LoadFromOffset(mips::kLoadUnsignedHalfword, mips::A3, mips::A1, -0x0FFF1);
__ LoadFromOffset(mips::kLoadUnsignedHalfword, mips::A3, mips::A1, +0x0FFF1);
__ LoadFromOffset(mips::kLoadUnsignedHalfword, mips::A3, mips::A1, +0x0FFF8);
__ LoadFromOffset(mips::kLoadUnsignedHalfword, mips::A3, mips::A1, +0x17FE8);
__ LoadFromOffset(mips::kLoadUnsignedHalfword, mips::A3, mips::A1, -0x17FF0);
__ LoadFromOffset(mips::kLoadUnsignedHalfword, mips::A3, mips::A1, -0x17FE9);
__ LoadFromOffset(mips::kLoadUnsignedHalfword, mips::A3, mips::A1, +0x17FE9);
__ LoadFromOffset(mips::kLoadUnsignedHalfword, mips::A3, mips::A1, +0x17FF0);
__ LoadFromOffset(mips::kLoadUnsignedHalfword, mips::A3, mips::A1, +0x12345678);
__ LoadFromOffset(mips::kLoadWord, mips::A3, mips::A1, -0x8000);
__ LoadFromOffset(mips::kLoadWord, mips::A3, mips::A1, +0);
__ LoadFromOffset(mips::kLoadWord, mips::A3, mips::A1, +0x7FF8);
__ LoadFromOffset(mips::kLoadWord, mips::A3, mips::A1, +0x7FFB);
__ LoadFromOffset(mips::kLoadWord, mips::A3, mips::A1, +0x7FFC);
__ LoadFromOffset(mips::kLoadWord, mips::A3, mips::A1, +0x7FFF);
__ LoadFromOffset(mips::kLoadWord, mips::A3, mips::A1, -0xFFF0);
__ LoadFromOffset(mips::kLoadWord, mips::A3, mips::A1, -0x8008);
__ LoadFromOffset(mips::kLoadWord, mips::A3, mips::A1, -0x8001);
__ LoadFromOffset(mips::kLoadWord, mips::A3, mips::A1, +0x8000);
__ LoadFromOffset(mips::kLoadWord, mips::A3, mips::A1, +0xFFF0);
__ LoadFromOffset(mips::kLoadWord, mips::A3, mips::A1, -0x17FE8);
__ LoadFromOffset(mips::kLoadWord, mips::A3, mips::A1, -0x0FFF8);
__ LoadFromOffset(mips::kLoadWord, mips::A3, mips::A1, -0x0FFF1);
__ LoadFromOffset(mips::kLoadWord, mips::A3, mips::A1, +0x0FFF1);
__ LoadFromOffset(mips::kLoadWord, mips::A3, mips::A1, +0x0FFF8);
__ LoadFromOffset(mips::kLoadWord, mips::A3, mips::A1, +0x17FE8);
__ LoadFromOffset(mips::kLoadWord, mips::A3, mips::A1, -0x17FF0);
__ LoadFromOffset(mips::kLoadWord, mips::A3, mips::A1, -0x17FE9);
__ LoadFromOffset(mips::kLoadWord, mips::A3, mips::A1, +0x17FE9);
__ LoadFromOffset(mips::kLoadWord, mips::A3, mips::A1, +0x17FF0);
__ LoadFromOffset(mips::kLoadWord, mips::A3, mips::A1, +0x12345678);
__ LoadFromOffset(mips::kLoadDoubleword, mips::A0, mips::A2, -0x8000);
__ LoadFromOffset(mips::kLoadDoubleword, mips::A0, mips::A2, +0);
__ LoadFromOffset(mips::kLoadDoubleword, mips::A0, mips::A2, +0x7FF8);
__ LoadFromOffset(mips::kLoadDoubleword, mips::A0, mips::A2, +0x7FFB);
__ LoadFromOffset(mips::kLoadDoubleword, mips::A0, mips::A2, +0x7FFC);
__ LoadFromOffset(mips::kLoadDoubleword, mips::A0, mips::A2, +0x7FFF);
__ LoadFromOffset(mips::kLoadDoubleword, mips::A0, mips::A2, -0xFFF0);
__ LoadFromOffset(mips::kLoadDoubleword, mips::A0, mips::A2, -0x8008);
__ LoadFromOffset(mips::kLoadDoubleword, mips::A0, mips::A2, -0x8001);
__ LoadFromOffset(mips::kLoadDoubleword, mips::A0, mips::A2, +0x8000);
__ LoadFromOffset(mips::kLoadDoubleword, mips::A0, mips::A2, +0xFFF0);
__ LoadFromOffset(mips::kLoadDoubleword, mips::A0, mips::A2, -0x17FE8);
__ LoadFromOffset(mips::kLoadDoubleword, mips::A0, mips::A2, -0x0FFF8);
__ LoadFromOffset(mips::kLoadDoubleword, mips::A0, mips::A2, -0x0FFF1);
__ LoadFromOffset(mips::kLoadDoubleword, mips::A0, mips::A2, +0x0FFF1);
__ LoadFromOffset(mips::kLoadDoubleword, mips::A0, mips::A2, +0x0FFF8);
__ LoadFromOffset(mips::kLoadDoubleword, mips::A0, mips::A2, +0x17FE8);
__ LoadFromOffset(mips::kLoadDoubleword, mips::A0, mips::A2, -0x17FF0);
__ LoadFromOffset(mips::kLoadDoubleword, mips::A0, mips::A2, -0x17FE9);
__ LoadFromOffset(mips::kLoadDoubleword, mips::A0, mips::A2, +0x17FE9);
__ LoadFromOffset(mips::kLoadDoubleword, mips::A0, mips::A2, +0x17FF0);
__ LoadFromOffset(mips::kLoadDoubleword, mips::A0, mips::A2, +0x12345678);
const char* expected =
"lb $a3, -0x8000($a1)\n"
"lb $a3, 0($a1)\n"
"lb $a3, 0x7FF8($a1)\n"
"lb $a3, 0x7FFB($a1)\n"
"lb $a3, 0x7FFC($a1)\n"
"lb $a3, 0x7FFF($a1)\n"
"addiu $at, $a1, -0x7FF8\n"
"lb $a3, -0x7FF8($at)\n"
"addiu $at, $a1, -0x7FF8\n"
"lb $a3, -0x10($at)\n"
"addiu $at, $a1, -0x7FF8\n"
"lb $a3, -9($at)\n"
"addiu $at, $a1, 0x7FF8\n"
"lb $a3, 8($at)\n"
"addiu $at, $a1, 0x7FF8\n"
"lb $a3, 0x7FF8($at)\n"
"addiu $at, $a1, -0x7FF8\n"
"addiu $at, $at, -0x7FF8\n"
"lb $a3, -0x7FF8($at)\n"
"addiu $at, $a1, -0x7FF8\n"
"addiu $at, $at, -0x7FF8\n"
"lb $a3, -8($at)\n"
"addiu $at, $a1, -0x7FF8\n"
"addiu $at, $at, -0x7FF8\n"
"lb $a3, -1($at)\n"
"addiu $at, $a1, 0x7FF8\n"
"addiu $at, $at, 0x7FF8\n"
"lb $a3, 1($at)\n"
"addiu $at, $a1, 0x7FF8\n"
"addiu $at, $at, 0x7FF8\n"
"lb $a3, 8($at)\n"
"addiu $at, $a1, 0x7FF8\n"
"addiu $at, $at, 0x7FF8\n"
"lb $a3, 0x7FF8($at)\n"
"lui $at, 0xFFFE\n"
"ori $at, $at, 0x8010\n"
"addu $at, $at, $a1\n"
"lb $a3, 0($at)\n"
"lui $at, 0xFFFE\n"
"ori $at, $at, 0x8010\n"
"addu $at, $at, $a1\n"
"lb $a3, 7($at)\n"
"lui $at, 0x1\n"
"ori $at, $at, 0x7FE8\n"
"addu $at, $at, $a1\n"
"lb $a3, 1($at)\n"
"lui $at, 0x1\n"
"ori $at, $at, 0x7FF0\n"
"addu $at, $at, $a1\n"
"lb $a3, 0($at)\n"
"lui $at, 0x1234\n"
"ori $at, $at, 0x5678\n"
"addu $at, $at, $a1\n"
"lb $a3, 0($at)\n"
"lbu $a3, -0x8000($a1)\n"
"lbu $a3, 0($a1)\n"
"lbu $a3, 0x7FF8($a1)\n"
"lbu $a3, 0x7FFB($a1)\n"
"lbu $a3, 0x7FFC($a1)\n"
"lbu $a3, 0x7FFF($a1)\n"
"addiu $at, $a1, -0x7FF8\n"
"lbu $a3, -0x7FF8($at)\n"
"addiu $at, $a1, -0x7FF8\n"
"lbu $a3, -0x10($at)\n"
"addiu $at, $a1, -0x7FF8\n"
"lbu $a3, -9($at)\n"
"addiu $at, $a1, 0x7FF8\n"
"lbu $a3, 8($at)\n"
"addiu $at, $a1, 0x7FF8\n"
"lbu $a3, 0x7FF8($at)\n"
"addiu $at, $a1, -0x7FF8\n"
"addiu $at, $at, -0x7FF8\n"
"lbu $a3, -0x7FF8($at)\n"
"addiu $at, $a1, -0x7FF8\n"
"addiu $at, $at, -0x7FF8\n"
"lbu $a3, -8($at)\n"
"addiu $at, $a1, -0x7FF8\n"
"addiu $at, $at, -0x7FF8\n"
"lbu $a3, -1($at)\n"
"addiu $at, $a1, 0x7FF8\n"
"addiu $at, $at, 0x7FF8\n"
"lbu $a3, 1($at)\n"
"addiu $at, $a1, 0x7FF8\n"
"addiu $at, $at, 0x7FF8\n"
"lbu $a3, 8($at)\n"
"addiu $at, $a1, 0x7FF8\n"
"addiu $at, $at, 0x7FF8\n"
"lbu $a3, 0x7FF8($at)\n"
"lui $at, 0xFFFE\n"
"ori $at, $at, 0x8010\n"
"addu $at, $at, $a1\n"
"lbu $a3, 0($at)\n"
"lui $at, 0xFFFE\n"
"ori $at, $at, 0x8010\n"
"addu $at, $at, $a1\n"
"lbu $a3, 7($at)\n"
"lui $at, 0x1\n"
"ori $at, $at, 0x7FE8\n"
"addu $at, $at, $a1\n"
"lbu $a3, 1($at)\n"
"lui $at, 0x1\n"
"ori $at, $at, 0x7FF0\n"
"addu $at, $at, $a1\n"
"lbu $a3, 0($at)\n"
"lui $at, 0x1234\n"
"ori $at, $at, 0x5678\n"
"addu $at, $at, $a1\n"
"lbu $a3, 0($at)\n"
"lh $a3, -0x8000($a1)\n"
"lh $a3, 0($a1)\n"
"lh $a3, 0x7FF8($a1)\n"
"lh $a3, 0x7FFB($a1)\n"
"lh $a3, 0x7FFC($a1)\n"
"lh $a3, 0x7FFF($a1)\n"
"addiu $at, $a1, -0x7FF8\n"
"lh $a3, -0x7FF8($at)\n"
"addiu $at, $a1, -0x7FF8\n"
"lh $a3, -0x10($at)\n"
"addiu $at, $a1, -0x7FF8\n"
"lh $a3, -9($at)\n"
"addiu $at, $a1, 0x7FF8\n"
"lh $a3, 8($at)\n"
"addiu $at, $a1, 0x7FF8\n"
"lh $a3, 0x7FF8($at)\n"
"addiu $at, $a1, -0x7FF8\n"
"addiu $at, $at, -0x7FF8\n"
"lh $a3, -0x7FF8($at)\n"
"addiu $at, $a1, -0x7FF8\n"
"addiu $at, $at, -0x7FF8\n"
"lh $a3, -8($at)\n"
"addiu $at, $a1, -0x7FF8\n"
"addiu $at, $at, -0x7FF8\n"
"lh $a3, -1($at)\n"
"addiu $at, $a1, 0x7FF8\n"
"addiu $at, $at, 0x7FF8\n"
"lh $a3, 1($at)\n"
"addiu $at, $a1, 0x7FF8\n"
"addiu $at, $at, 0x7FF8\n"
"lh $a3, 8($at)\n"
"addiu $at, $a1, 0x7FF8\n"
"addiu $at, $at, 0x7FF8\n"
"lh $a3, 0x7FF8($at)\n"
"lui $at, 0xFFFE\n"
"ori $at, $at, 0x8010\n"
"addu $at, $at, $a1\n"
"lh $a3, 0($at)\n"
"lui $at, 0xFFFE\n"
"ori $at, $at, 0x8010\n"
"addu $at, $at, $a1\n"
"lh $a3, 7($at)\n"
"lui $at, 0x1\n"
"ori $at, $at, 0x7FE8\n"
"addu $at, $at, $a1\n"
"lh $a3, 1($at)\n"
"lui $at, 0x1\n"
"ori $at, $at, 0x7FF0\n"
"addu $at, $at, $a1\n"
"lh $a3, 0($at)\n"
"lui $at, 0x1234\n"
"ori $at, $at, 0x5678\n"
"addu $at, $at, $a1\n"
"lh $a3, 0($at)\n"
"lhu $a3, -0x8000($a1)\n"
"lhu $a3, 0($a1)\n"
"lhu $a3, 0x7FF8($a1)\n"
"lhu $a3, 0x7FFB($a1)\n"
"lhu $a3, 0x7FFC($a1)\n"
"lhu $a3, 0x7FFF($a1)\n"
"addiu $at, $a1, -0x7FF8\n"
"lhu $a3, -0x7FF8($at)\n"
"addiu $at, $a1, -0x7FF8\n"
"lhu $a3, -0x10($at)\n"
"addiu $at, $a1, -0x7FF8\n"
"lhu $a3, -9($at)\n"
"addiu $at, $a1, 0x7FF8\n"
"lhu $a3, 8($at)\n"
"addiu $at, $a1, 0x7FF8\n"
"lhu $a3, 0x7FF8($at)\n"
"addiu $at, $a1, -0x7FF8\n"
"addiu $at, $at, -0x7FF8\n"
"lhu $a3, -0x7FF8($at)\n"
"addiu $at, $a1, -0x7FF8\n"
"addiu $at, $at, -0x7FF8\n"
"lhu $a3, -8($at)\n"
"addiu $at, $a1, -0x7FF8\n"
"addiu $at, $at, -0x7FF8\n"
"lhu $a3, -1($at)\n"
"addiu $at, $a1, 0x7FF8\n"
"addiu $at, $at, 0x7FF8\n"
"lhu $a3, 1($at)\n"
"addiu $at, $a1, 0x7FF8\n"
"addiu $at, $at, 0x7FF8\n"
"lhu $a3, 8($at)\n"
"addiu $at, $a1, 0x7FF8\n"
"addiu $at, $at, 0x7FF8\n"
"lhu $a3, 0x7FF8($at)\n"
"lui $at, 0xFFFE\n"
"ori $at, $at, 0x8010\n"
"addu $at, $at, $a1\n"
"lhu $a3, 0($at)\n"
"lui $at, 0xFFFE\n"
"ori $at, $at, 0x8010\n"
"addu $at, $at, $a1\n"
"lhu $a3, 7($at)\n"
"lui $at, 0x1\n"
"ori $at, $at, 0x7FE8\n"
"addu $at, $at, $a1\n"
"lhu $a3, 1($at)\n"
"lui $at, 0x1\n"
"ori $at, $at, 0x7FF0\n"
"addu $at, $at, $a1\n"
"lhu $a3, 0($at)\n"
"lui $at, 0x1234\n"
"ori $at, $at, 0x5678\n"
"addu $at, $at, $a1\n"
"lhu $a3, 0($at)\n"
"lw $a3, -0x8000($a1)\n"
"lw $a3, 0($a1)\n"
"lw $a3, 0x7FF8($a1)\n"
"lw $a3, 0x7FFB($a1)\n"
"lw $a3, 0x7FFC($a1)\n"
"lw $a3, 0x7FFF($a1)\n"
"addiu $at, $a1, -0x7FF8\n"
"lw $a3, -0x7FF8($at)\n"
"addiu $at, $a1, -0x7FF8\n"
"lw $a3, -0x10($at)\n"
"addiu $at, $a1, -0x7FF8\n"
"lw $a3, -9($at)\n"
"addiu $at, $a1, 0x7FF8\n"
"lw $a3, 8($at)\n"
"addiu $at, $a1, 0x7FF8\n"
"lw $a3, 0x7FF8($at)\n"
"addiu $at, $a1, -0x7FF8\n"
"addiu $at, $at, -0x7FF8\n"
"lw $a3, -0x7FF8($at)\n"
"addiu $at, $a1, -0x7FF8\n"
"addiu $at, $at, -0x7FF8\n"
"lw $a3, -8($at)\n"
"addiu $at, $a1, -0x7FF8\n"
"addiu $at, $at, -0x7FF8\n"
"lw $a3, -1($at)\n"
"addiu $at, $a1, 0x7FF8\n"
"addiu $at, $at, 0x7FF8\n"
"lw $a3, 1($at)\n"
"addiu $at, $a1, 0x7FF8\n"
"addiu $at, $at, 0x7FF8\n"
"lw $a3, 8($at)\n"
"addiu $at, $a1, 0x7FF8\n"
"addiu $at, $at, 0x7FF8\n"
"lw $a3, 0x7FF8($at)\n"
"lui $at, 0xFFFE\n"
"ori $at, $at, 0x8010\n"
"addu $at, $at, $a1\n"
"lw $a3, 0($at)\n"
"lui $at, 0xFFFE\n"
"ori $at, $at, 0x8010\n"
"addu $at, $at, $a1\n"
"lw $a3, 7($at)\n"
"lui $at, 0x1\n"
"ori $at, $at, 0x7FE8\n"
"addu $at, $at, $a1\n"
"lw $a3, 1($at)\n"
"lui $at, 0x1\n"
"ori $at, $at, 0x7FF0\n"
"addu $at, $at, $a1\n"
"lw $a3, 0($at)\n"
"lui $at, 0x1234\n"
"ori $at, $at, 0x5678\n"
"addu $at, $at, $a1\n"
"lw $a3, 0($at)\n"
"lw $a0, -0x8000($a2)\n"
"lw $a1, -0x7FFC($a2)\n"
"lw $a0, 0($a2)\n"
"lw $a1, 4($a2)\n"
"lw $a0, 0x7FF8($a2)\n"
"lw $a1, 0x7FFC($a2)\n"
"lw $a0, 0x7FFB($a2)\n"
"lw $a1, 0x7FFF($a2)\n"
"addiu $at, $a2, 0x7FF8\n"
"lw $a0, 4($at)\n"
"lw $a1, 8($at)\n"
"addiu $at, $a2, 0x7FF8\n"
"lw $a0, 7($at)\n"
"lw $a1, 11($at)\n"
"addiu $at, $a2, -0x7FF8\n"
"lw $a0, -0x7FF8($at)\n"
"lw $a1, -0x7FF4($at)\n"
"addiu $at, $a2, -0x7FF8\n"
"lw $a0, -0x10($at)\n"
"lw $a1, -0xC($at)\n"
"addiu $at, $a2, -0x7FF8\n"
"lw $a0, -9($at)\n"
"lw $a1, -5($at)\n"
"addiu $at, $a2, 0x7FF8\n"
"lw $a0, 8($at)\n"
"lw $a1, 12($at)\n"
"addiu $at, $a2, 0x7FF8\n"
"lw $a0, 0x7FF8($at)\n"
"lw $a1, 0x7FFC($at)\n"
"addiu $at, $a2, -0x7FF8\n"
"addiu $at, $at, -0x7FF8\n"
"lw $a0, -0x7FF8($at)\n"
"lw $a1, -0x7FF4($at)\n"
"addiu $at, $a2, -0x7FF8\n"
"addiu $at, $at, -0x7FF8\n"
"lw $a0, -8($at)\n"
"lw $a1, -4($at)\n"
"addiu $at, $a2, -0x7FF8\n"
"addiu $at, $at, -0x7FF8\n"
"lw $a0, -1($at)\n"
"lw $a1, 3($at)\n"
"addiu $at, $a2, 0x7FF8\n"
"addiu $at, $at, 0x7FF8\n"
"lw $a0, 1($at)\n"
"lw $a1, 5($at)\n"
"addiu $at, $a2, 0x7FF8\n"
"addiu $at, $at, 0x7FF8\n"
"lw $a0, 8($at)\n"
"lw $a1, 12($at)\n"
"addiu $at, $a2, 0x7FF8\n"
"addiu $at, $at, 0x7FF8\n"
"lw $a0, 0x7FF8($at)\n"
"lw $a1, 0x7FFC($at)\n"
"lui $at, 0xFFFE\n"
"ori $at, $at, 0x8010\n"
"addu $at, $at, $a2\n"
"lw $a0, 0($at)\n"
"lw $a1, 4($at)\n"
"lui $at, 0xFFFE\n"
"ori $at, $at, 0x8010\n"
"addu $at, $at, $a2\n"
"lw $a0, 7($at)\n"
"lw $a1, 11($at)\n"
"lui $at, 0x1\n"
"ori $at, $at, 0x7FE8\n"
"addu $at, $at, $a2\n"
"lw $a0, 1($at)\n"
"lw $a1, 5($at)\n"
"lui $at, 0x1\n"
"ori $at, $at, 0x7FF0\n"
"addu $at, $at, $a2\n"
"lw $a0, 0($at)\n"
"lw $a1, 4($at)\n"
"lui $at, 0x1234\n"
"ori $at, $at, 0x5678\n"
"addu $at, $at, $a2\n"
"lw $a0, 0($at)\n"
"lw $a1, 4($at)\n";
DriverStr(expected, "LoadFromOffset");
}
TEST_F(AssemblerMIPSTest, LoadSFromOffset) {
__ LoadSFromOffset(mips::F2, mips::A0, -0x8000);
__ LoadSFromOffset(mips::F2, mips::A0, +0);
__ LoadSFromOffset(mips::F2, mips::A0, +0x7FF8);
__ LoadSFromOffset(mips::F2, mips::A0, +0x7FFB);
__ LoadSFromOffset(mips::F2, mips::A0, +0x7FFC);
__ LoadSFromOffset(mips::F2, mips::A0, +0x7FFF);
__ LoadSFromOffset(mips::F2, mips::A0, -0xFFF0);
__ LoadSFromOffset(mips::F2, mips::A0, -0x8008);
__ LoadSFromOffset(mips::F2, mips::A0, -0x8001);
__ LoadSFromOffset(mips::F2, mips::A0, +0x8000);
__ LoadSFromOffset(mips::F2, mips::A0, +0xFFF0);
__ LoadSFromOffset(mips::F2, mips::A0, -0x17FE8);
__ LoadSFromOffset(mips::F2, mips::A0, -0x0FFF8);
__ LoadSFromOffset(mips::F2, mips::A0, -0x0FFF1);
__ LoadSFromOffset(mips::F2, mips::A0, +0x0FFF1);
__ LoadSFromOffset(mips::F2, mips::A0, +0x0FFF8);
__ LoadSFromOffset(mips::F2, mips::A0, +0x17FE8);
__ LoadSFromOffset(mips::F2, mips::A0, -0x17FF0);
__ LoadSFromOffset(mips::F2, mips::A0, -0x17FE9);
__ LoadSFromOffset(mips::F2, mips::A0, +0x17FE9);
__ LoadSFromOffset(mips::F2, mips::A0, +0x17FF0);
__ LoadSFromOffset(mips::F2, mips::A0, +0x12345678);
const char* expected =
"lwc1 $f2, -0x8000($a0)\n"
"lwc1 $f2, 0($a0)\n"
"lwc1 $f2, 0x7FF8($a0)\n"
"lwc1 $f2, 0x7FFB($a0)\n"
"lwc1 $f2, 0x7FFC($a0)\n"
"lwc1 $f2, 0x7FFF($a0)\n"
"addiu $at, $a0, -0x7FF8\n"
"lwc1 $f2, -0x7FF8($at)\n"
"addiu $at, $a0, -0x7FF8\n"
"lwc1 $f2, -0x10($at)\n"
"addiu $at, $a0, -0x7FF8\n"
"lwc1 $f2, -9($at)\n"
"addiu $at, $a0, 0x7FF8\n"
"lwc1 $f2, 8($at)\n"
"addiu $at, $a0, 0x7FF8\n"
"lwc1 $f2, 0x7FF8($at)\n"
"addiu $at, $a0, -0x7FF8\n"
"addiu $at, $at, -0x7FF8\n"
"lwc1 $f2, -0x7FF8($at)\n"
"addiu $at, $a0, -0x7FF8\n"
"addiu $at, $at, -0x7FF8\n"
"lwc1 $f2, -8($at)\n"
"addiu $at, $a0, -0x7FF8\n"
"addiu $at, $at, -0x7FF8\n"
"lwc1 $f2, -1($at)\n"
"addiu $at, $a0, 0x7FF8\n"
"addiu $at, $at, 0x7FF8\n"
"lwc1 $f2, 1($at)\n"
"addiu $at, $a0, 0x7FF8\n"
"addiu $at, $at, 0x7FF8\n"
"lwc1 $f2, 8($at)\n"
"addiu $at, $a0, 0x7FF8\n"
"addiu $at, $at, 0x7FF8\n"
"lwc1 $f2, 0x7FF8($at)\n"
"lui $at, 0xFFFE\n"
"ori $at, $at, 0x8010\n"
"addu $at, $at, $a0\n"
"lwc1 $f2, 0($at)\n"
"lui $at, 0xFFFE\n"
"ori $at, $at, 0x8010\n"
"addu $at, $at, $a0\n"
"lwc1 $f2, 7($at)\n"
"lui $at, 0x1\n"
"ori $at, $at, 0x7FE8\n"
"addu $at, $at, $a0\n"
"lwc1 $f2, 1($at)\n"
"lui $at, 0x1\n"
"ori $at, $at, 0x7FF0\n"
"addu $at, $at, $a0\n"
"lwc1 $f2, 0($at)\n"
"lui $at, 0x1234\n"
"ori $at, $at, 0x5678\n"
"addu $at, $at, $a0\n"
"lwc1 $f2, 0($at)\n";
DriverStr(expected, "LoadSFromOffset");
}
TEST_F(AssemblerMIPSTest, LoadDFromOffset) {
__ LoadDFromOffset(mips::F0, mips::A0, -0x8000);
__ LoadDFromOffset(mips::F0, mips::A0, +0);
__ LoadDFromOffset(mips::F0, mips::A0, +0x7FF8);
__ LoadDFromOffset(mips::F0, mips::A0, +0x7FFB);
__ LoadDFromOffset(mips::F0, mips::A0, +0x7FFC);
__ LoadDFromOffset(mips::F0, mips::A0, +0x7FFF);
__ LoadDFromOffset(mips::F0, mips::A0, -0xFFF0);
__ LoadDFromOffset(mips::F0, mips::A0, -0x8008);
__ LoadDFromOffset(mips::F0, mips::A0, -0x8001);
__ LoadDFromOffset(mips::F0, mips::A0, +0x8000);
__ LoadDFromOffset(mips::F0, mips::A0, +0xFFF0);
__ LoadDFromOffset(mips::F0, mips::A0, -0x17FE8);
__ LoadDFromOffset(mips::F0, mips::A0, -0x0FFF8);
__ LoadDFromOffset(mips::F0, mips::A0, -0x0FFF1);
__ LoadDFromOffset(mips::F0, mips::A0, +0x0FFF1);
__ LoadDFromOffset(mips::F0, mips::A0, +0x0FFF8);
__ LoadDFromOffset(mips::F0, mips::A0, +0x17FE8);
__ LoadDFromOffset(mips::F0, mips::A0, -0x17FF0);
__ LoadDFromOffset(mips::F0, mips::A0, -0x17FE9);
__ LoadDFromOffset(mips::F0, mips::A0, +0x17FE9);
__ LoadDFromOffset(mips::F0, mips::A0, +0x17FF0);
__ LoadDFromOffset(mips::F0, mips::A0, +0x12345678);
const char* expected =
"ldc1 $f0, -0x8000($a0)\n"
"ldc1 $f0, 0($a0)\n"
"ldc1 $f0, 0x7FF8($a0)\n"
"lwc1 $f0, 0x7FFB($a0)\n"
"lwc1 $f1, 0x7FFF($a0)\n"
"addiu $at, $a0, 0x7FF8\n"
"lwc1 $f0, 4($at)\n"
"lwc1 $f1, 8($at)\n"
"addiu $at, $a0, 0x7FF8\n"
"lwc1 $f0, 7($at)\n"
"lwc1 $f1, 11($at)\n"
"addiu $at, $a0, -0x7FF8\n"
"ldc1 $f0, -0x7FF8($at)\n"
"addiu $at, $a0, -0x7FF8\n"
"ldc1 $f0, -0x10($at)\n"
"addiu $at, $a0, -0x7FF8\n"
"lwc1 $f0, -9($at)\n"
"lwc1 $f1, -5($at)\n"
"addiu $at, $a0, 0x7FF8\n"
"ldc1 $f0, 8($at)\n"
"addiu $at, $a0, 0x7FF8\n"
"ldc1 $f0, 0x7FF8($at)\n"
"addiu $at, $a0, -0x7FF8\n"
"addiu $at, $at, -0x7FF8\n"
"ldc1 $f0, -0x7FF8($at)\n"
"addiu $at, $a0, -0x7FF8\n"
"addiu $at, $at, -0x7FF8\n"
"ldc1 $f0, -8($at)\n"
"addiu $at, $a0, -0x7FF8\n"
"addiu $at, $at, -0x7FF8\n"
"lwc1 $f0, -1($at)\n"
"lwc1 $f1, 3($at)\n"
"addiu $at, $a0, 0x7FF8\n"
"addiu $at, $at, 0x7FF8\n"
"lwc1 $f0, 1($at)\n"
"lwc1 $f1, 5($at)\n"
"addiu $at, $a0, 0x7FF8\n"
"addiu $at, $at, 0x7FF8\n"
"ldc1 $f0, 8($at)\n"
"addiu $at, $a0, 0x7FF8\n"
"addiu $at, $at, 0x7FF8\n"
"ldc1 $f0, 0x7FF8($at)\n"
"lui $at, 0xFFFE\n"
"ori $at, $at, 0x8010\n"
"addu $at, $at, $a0\n"
"ldc1 $f0, 0($at)\n"
"lui $at, 0xFFFE\n"
"ori $at, $at, 0x8010\n"
"addu $at, $at, $a0\n"
"lwc1 $f0, 7($at)\n"
"lwc1 $f1, 11($at)\n"
"lui $at, 0x1\n"
"ori $at, $at, 0x7FE8\n"
"addu $at, $at, $a0\n"
"lwc1 $f0, 1($at)\n"
"lwc1 $f1, 5($at)\n"
"lui $at, 0x1\n"
"ori $at, $at, 0x7FF0\n"
"addu $at, $at, $a0\n"
"ldc1 $f0, 0($at)\n"
"lui $at, 0x1234\n"
"ori $at, $at, 0x5678\n"
"addu $at, $at, $a0\n"
"ldc1 $f0, 0($at)\n";
DriverStr(expected, "LoadDFromOffset");
}
TEST_F(AssemblerMIPSTest, StoreToOffset) {
__ StoreToOffset(mips::kStoreByte, mips::A3, mips::A1, -0x8000);
__ StoreToOffset(mips::kStoreByte, mips::A3, mips::A1, +0);
__ StoreToOffset(mips::kStoreByte, mips::A3, mips::A1, +0x7FF8);
__ StoreToOffset(mips::kStoreByte, mips::A3, mips::A1, +0x7FFB);
__ StoreToOffset(mips::kStoreByte, mips::A3, mips::A1, +0x7FFC);
__ StoreToOffset(mips::kStoreByte, mips::A3, mips::A1, +0x7FFF);
__ StoreToOffset(mips::kStoreByte, mips::A3, mips::A1, -0xFFF0);
__ StoreToOffset(mips::kStoreByte, mips::A3, mips::A1, -0x8008);
__ StoreToOffset(mips::kStoreByte, mips::A3, mips::A1, -0x8001);
__ StoreToOffset(mips::kStoreByte, mips::A3, mips::A1, +0x8000);
__ StoreToOffset(mips::kStoreByte, mips::A3, mips::A1, +0xFFF0);
__ StoreToOffset(mips::kStoreByte, mips::A3, mips::A1, -0x17FE8);
__ StoreToOffset(mips::kStoreByte, mips::A3, mips::A1, -0x0FFF8);
__ StoreToOffset(mips::kStoreByte, mips::A3, mips::A1, -0x0FFF1);
__ StoreToOffset(mips::kStoreByte, mips::A3, mips::A1, +0x0FFF1);
__ StoreToOffset(mips::kStoreByte, mips::A3, mips::A1, +0x0FFF8);
__ StoreToOffset(mips::kStoreByte, mips::A3, mips::A1, +0x17FE8);
__ StoreToOffset(mips::kStoreByte, mips::A3, mips::A1, -0x17FF0);
__ StoreToOffset(mips::kStoreByte, mips::A3, mips::A1, -0x17FE9);
__ StoreToOffset(mips::kStoreByte, mips::A3, mips::A1, +0x17FE9);
__ StoreToOffset(mips::kStoreByte, mips::A3, mips::A1, +0x17FF0);
__ StoreToOffset(mips::kStoreByte, mips::A3, mips::A1, +0x12345678);
__ StoreToOffset(mips::kStoreHalfword, mips::A3, mips::A1, -0x8000);
__ StoreToOffset(mips::kStoreHalfword, mips::A3, mips::A1, +0);
__ StoreToOffset(mips::kStoreHalfword, mips::A3, mips::A1, +0x7FF8);
__ StoreToOffset(mips::kStoreHalfword, mips::A3, mips::A1, +0x7FFB);
__ StoreToOffset(mips::kStoreHalfword, mips::A3, mips::A1, +0x7FFC);
__ StoreToOffset(mips::kStoreHalfword, mips::A3, mips::A1, +0x7FFF);
__ StoreToOffset(mips::kStoreHalfword, mips::A3, mips::A1, -0xFFF0);
__ StoreToOffset(mips::kStoreHalfword, mips::A3, mips::A1, -0x8008);
__ StoreToOffset(mips::kStoreHalfword, mips::A3, mips::A1, -0x8001);
__ StoreToOffset(mips::kStoreHalfword, mips::A3, mips::A1, +0x8000);
__ StoreToOffset(mips::kStoreHalfword, mips::A3, mips::A1, +0xFFF0);
__ StoreToOffset(mips::kStoreHalfword, mips::A3, mips::A1, -0x17FE8);
__ StoreToOffset(mips::kStoreHalfword, mips::A3, mips::A1, -0x0FFF8);
__ StoreToOffset(mips::kStoreHalfword, mips::A3, mips::A1, -0x0FFF1);
__ StoreToOffset(mips::kStoreHalfword, mips::A3, mips::A1, +0x0FFF1);
__ StoreToOffset(mips::kStoreHalfword, mips::A3, mips::A1, +0x0FFF8);
__ StoreToOffset(mips::kStoreHalfword, mips::A3, mips::A1, +0x17FE8);
__ StoreToOffset(mips::kStoreHalfword, mips::A3, mips::A1, -0x17FF0);
__ StoreToOffset(mips::kStoreHalfword, mips::A3, mips::A1, -0x17FE9);
__ StoreToOffset(mips::kStoreHalfword, mips::A3, mips::A1, +0x17FE9);
__ StoreToOffset(mips::kStoreHalfword, mips::A3, mips::A1, +0x17FF0);
__ StoreToOffset(mips::kStoreHalfword, mips::A3, mips::A1, +0x12345678);
__ StoreToOffset(mips::kStoreWord, mips::A3, mips::A1, -0x8000);
__ StoreToOffset(mips::kStoreWord, mips::A3, mips::A1, +0);
__ StoreToOffset(mips::kStoreWord, mips::A3, mips::A1, +0x7FF8);
__ StoreToOffset(mips::kStoreWord, mips::A3, mips::A1, +0x7FFB);
__ StoreToOffset(mips::kStoreWord, mips::A3, mips::A1, +0x7FFC);
__ StoreToOffset(mips::kStoreWord, mips::A3, mips::A1, +0x7FFF);
__ StoreToOffset(mips::kStoreWord, mips::A3, mips::A1, -0xFFF0);
__ StoreToOffset(mips::kStoreWord, mips::A3, mips::A1, -0x8008);
__ StoreToOffset(mips::kStoreWord, mips::A3, mips::A1, -0x8001);
__ StoreToOffset(mips::kStoreWord, mips::A3, mips::A1, +0x8000);
__ StoreToOffset(mips::kStoreWord, mips::A3, mips::A1, +0xFFF0);
__ StoreToOffset(mips::kStoreWord, mips::A3, mips::A1, -0x17FE8);
__ StoreToOffset(mips::kStoreWord, mips::A3, mips::A1, -0x0FFF8);
__ StoreToOffset(mips::kStoreWord, mips::A3, mips::A1, -0x0FFF1);
__ StoreToOffset(mips::kStoreWord, mips::A3, mips::A1, +0x0FFF1);
__ StoreToOffset(mips::kStoreWord, mips::A3, mips::A1, +0x0FFF8);
__ StoreToOffset(mips::kStoreWord, mips::A3, mips::A1, +0x17FE8);
__ StoreToOffset(mips::kStoreWord, mips::A3, mips::A1, -0x17FF0);
__ StoreToOffset(mips::kStoreWord, mips::A3, mips::A1, -0x17FE9);
__ StoreToOffset(mips::kStoreWord, mips::A3, mips::A1, +0x17FE9);
__ StoreToOffset(mips::kStoreWord, mips::A3, mips::A1, +0x17FF0);
__ StoreToOffset(mips::kStoreWord, mips::A3, mips::A1, +0x12345678);
__ StoreToOffset(mips::kStoreDoubleword, mips::A0, mips::A2, -0x8000);
__ StoreToOffset(mips::kStoreDoubleword, mips::A0, mips::A2, +0);
__ StoreToOffset(mips::kStoreDoubleword, mips::A0, mips::A2, +0x7FF8);
__ StoreToOffset(mips::kStoreDoubleword, mips::A0, mips::A2, +0x7FFB);
__ StoreToOffset(mips::kStoreDoubleword, mips::A0, mips::A2, +0x7FFC);
__ StoreToOffset(mips::kStoreDoubleword, mips::A0, mips::A2, +0x7FFF);
__ StoreToOffset(mips::kStoreDoubleword, mips::A0, mips::A2, -0xFFF0);
__ StoreToOffset(mips::kStoreDoubleword, mips::A0, mips::A2, -0x8008);
__ StoreToOffset(mips::kStoreDoubleword, mips::A0, mips::A2, -0x8001);
__ StoreToOffset(mips::kStoreDoubleword, mips::A0, mips::A2, +0x8000);
__ StoreToOffset(mips::kStoreDoubleword, mips::A0, mips::A2, +0xFFF0);
__ StoreToOffset(mips::kStoreDoubleword, mips::A0, mips::A2, -0x17FE8);
__ StoreToOffset(mips::kStoreDoubleword, mips::A0, mips::A2, -0x0FFF8);
__ StoreToOffset(mips::kStoreDoubleword, mips::A0, mips::A2, -0x0FFF1);
__ StoreToOffset(mips::kStoreDoubleword, mips::A0, mips::A2, +0x0FFF1);
__ StoreToOffset(mips::kStoreDoubleword, mips::A0, mips::A2, +0x0FFF8);
__ StoreToOffset(mips::kStoreDoubleword, mips::A0, mips::A2, +0x17FE8);
__ StoreToOffset(mips::kStoreDoubleword, mips::A0, mips::A2, -0x17FF0);
__ StoreToOffset(mips::kStoreDoubleword, mips::A0, mips::A2, -0x17FE9);
__ StoreToOffset(mips::kStoreDoubleword, mips::A0, mips::A2, +0x17FE9);
__ StoreToOffset(mips::kStoreDoubleword, mips::A0, mips::A2, +0x17FF0);
__ StoreToOffset(mips::kStoreDoubleword, mips::A0, mips::A2, +0x12345678);
const char* expected =
"sb $a3, -0x8000($a1)\n"
"sb $a3, 0($a1)\n"
"sb $a3, 0x7FF8($a1)\n"
"sb $a3, 0x7FFB($a1)\n"
"sb $a3, 0x7FFC($a1)\n"
"sb $a3, 0x7FFF($a1)\n"
"addiu $at, $a1, -0x7FF8\n"
"sb $a3, -0x7FF8($at)\n"
"addiu $at, $a1, -0x7FF8\n"
"sb $a3, -0x10($at)\n"
"addiu $at, $a1, -0x7FF8\n"
"sb $a3, -9($at)\n"
"addiu $at, $a1, 0x7FF8\n"
"sb $a3, 8($at)\n"
"addiu $at, $a1, 0x7FF8\n"
"sb $a3, 0x7FF8($at)\n"
"addiu $at, $a1, -0x7FF8\n"
"addiu $at, $at, -0x7FF8\n"
"sb $a3, -0x7FF8($at)\n"
"addiu $at, $a1, -0x7FF8\n"
"addiu $at, $at, -0x7FF8\n"
"sb $a3, -8($at)\n"
"addiu $at, $a1, -0x7FF8\n"
"addiu $at, $at, -0x7FF8\n"
"sb $a3, -1($at)\n"
"addiu $at, $a1, 0x7FF8\n"
"addiu $at, $at, 0x7FF8\n"
"sb $a3, 1($at)\n"
"addiu $at, $a1, 0x7FF8\n"
"addiu $at, $at, 0x7FF8\n"
"sb $a3, 8($at)\n"
"addiu $at, $a1, 0x7FF8\n"
"addiu $at, $at, 0x7FF8\n"
"sb $a3, 0x7FF8($at)\n"
"lui $at, 0xFFFE\n"
"ori $at, $at, 0x8010\n"
"addu $at, $at, $a1\n"
"sb $a3, 0($at)\n"
"lui $at, 0xFFFE\n"
"ori $at, $at, 0x8010\n"
"addu $at, $at, $a1\n"
"sb $a3, 7($at)\n"
"lui $at, 0x1\n"
"ori $at, $at, 0x7FE8\n"
"addu $at, $at, $a1\n"
"sb $a3, 1($at)\n"
"lui $at, 0x1\n"
"ori $at, $at, 0x7FF0\n"
"addu $at, $at, $a1\n"
"sb $a3, 0($at)\n"
"lui $at, 0x1234\n"
"ori $at, $at, 0x5678\n"
"addu $at, $at, $a1\n"
"sb $a3, 0($at)\n"
"sh $a3, -0x8000($a1)\n"
"sh $a3, 0($a1)\n"
"sh $a3, 0x7FF8($a1)\n"
"sh $a3, 0x7FFB($a1)\n"
"sh $a3, 0x7FFC($a1)\n"
"sh $a3, 0x7FFF($a1)\n"
"addiu $at, $a1, -0x7FF8\n"
"sh $a3, -0x7FF8($at)\n"
"addiu $at, $a1, -0x7FF8\n"
"sh $a3, -0x10($at)\n"
"addiu $at, $a1, -0x7FF8\n"
"sh $a3, -9($at)\n"
"addiu $at, $a1, 0x7FF8\n"
"sh $a3, 8($at)\n"
"addiu $at, $a1, 0x7FF8\n"
"sh $a3, 0x7FF8($at)\n"
"addiu $at, $a1, -0x7FF8\n"
"addiu $at, $at, -0x7FF8\n"
"sh $a3, -0x7FF8($at)\n"
"addiu $at, $a1, -0x7FF8\n"
"addiu $at, $at, -0x7FF8\n"
"sh $a3, -8($at)\n"
"addiu $at, $a1, -0x7FF8\n"
"addiu $at, $at, -0x7FF8\n"
"sh $a3, -1($at)\n"
"addiu $at, $a1, 0x7FF8\n"
"addiu $at, $at, 0x7FF8\n"
"sh $a3, 1($at)\n"
"addiu $at, $a1, 0x7FF8\n"
"addiu $at, $at, 0x7FF8\n"
"sh $a3, 8($at)\n"
"addiu $at, $a1, 0x7FF8\n"
"addiu $at, $at, 0x7FF8\n"
"sh $a3, 0x7FF8($at)\n"
"lui $at, 0xFFFE\n"
"ori $at, $at, 0x8010\n"
"addu $at, $at, $a1\n"
"sh $a3, 0($at)\n"
"lui $at, 0xFFFE\n"
"ori $at, $at, 0x8010\n"
"addu $at, $at, $a1\n"
"sh $a3, 7($at)\n"
"lui $at, 0x1\n"
"ori $at, $at, 0x7FE8\n"
"addu $at, $at, $a1\n"
"sh $a3, 1($at)\n"
"lui $at, 0x1\n"
"ori $at, $at, 0x7FF0\n"
"addu $at, $at, $a1\n"
"sh $a3, 0($at)\n"
"lui $at, 0x1234\n"
"ori $at, $at, 0x5678\n"
"addu $at, $at, $a1\n"
"sh $a3, 0($at)\n"
"sw $a3, -0x8000($a1)\n"
"sw $a3, 0($a1)\n"
"sw $a3, 0x7FF8($a1)\n"
"sw $a3, 0x7FFB($a1)\n"
"sw $a3, 0x7FFC($a1)\n"
"sw $a3, 0x7FFF($a1)\n"
"addiu $at, $a1, -0x7FF8\n"
"sw $a3, -0x7FF8($at)\n"
"addiu $at, $a1, -0x7FF8\n"
"sw $a3, -0x10($at)\n"
"addiu $at, $a1, -0x7FF8\n"
"sw $a3, -9($at)\n"
"addiu $at, $a1, 0x7FF8\n"
"sw $a3, 8($at)\n"
"addiu $at, $a1, 0x7FF8\n"
"sw $a3, 0x7FF8($at)\n"
"addiu $at, $a1, -0x7FF8\n"
"addiu $at, $at, -0x7FF8\n"
"sw $a3, -0x7FF8($at)\n"
"addiu $at, $a1, -0x7FF8\n"
"addiu $at, $at, -0x7FF8\n"
"sw $a3, -8($at)\n"
"addiu $at, $a1, -0x7FF8\n"
"addiu $at, $at, -0x7FF8\n"
"sw $a3, -1($at)\n"
"addiu $at, $a1, 0x7FF8\n"
"addiu $at, $at, 0x7FF8\n"
"sw $a3, 1($at)\n"
"addiu $at, $a1, 0x7FF8\n"
"addiu $at, $at, 0x7FF8\n"
"sw $a3, 8($at)\n"
"addiu $at, $a1, 0x7FF8\n"
"addiu $at, $at, 0x7FF8\n"
"sw $a3, 0x7FF8($at)\n"
"lui $at, 0xFFFE\n"
"ori $at, $at, 0x8010\n"
"addu $at, $at, $a1\n"
"sw $a3, 0($at)\n"
"lui $at, 0xFFFE\n"
"ori $at, $at, 0x8010\n"
"addu $at, $at, $a1\n"
"sw $a3, 7($at)\n"
"lui $at, 0x1\n"
"ori $at, $at, 0x7FE8\n"
"addu $at, $at, $a1\n"
"sw $a3, 1($at)\n"
"lui $at, 0x1\n"
"ori $at, $at, 0x7FF0\n"
"addu $at, $at, $a1\n"
"sw $a3, 0($at)\n"
"lui $at, 0x1234\n"
"ori $at, $at, 0x5678\n"
"addu $at, $at, $a1\n"
"sw $a3, 0($at)\n"
"sw $a0, -0x8000($a2)\n"
"sw $a1, -0x7FFC($a2)\n"
"sw $a0, 0($a2)\n"
"sw $a1, 4($a2)\n"
"sw $a0, 0x7FF8($a2)\n"
"sw $a1, 0x7FFC($a2)\n"
"sw $a0, 0x7FFB($a2)\n"
"sw $a1, 0x7FFF($a2)\n"
"addiu $at, $a2, 0x7FF8\n"
"sw $a0, 4($at)\n"
"sw $a1, 8($at)\n"
"addiu $at, $a2, 0x7FF8\n"
"sw $a0, 7($at)\n"
"sw $a1, 11($at)\n"
"addiu $at, $a2, -0x7FF8\n"
"sw $a0, -0x7FF8($at)\n"
"sw $a1, -0x7FF4($at)\n"
"addiu $at, $a2, -0x7FF8\n"
"sw $a0, -0x10($at)\n"
"sw $a1, -0xC($at)\n"
"addiu $at, $a2, -0x7FF8\n"
"sw $a0, -9($at)\n"
"sw $a1, -5($at)\n"
"addiu $at, $a2, 0x7FF8\n"
"sw $a0, 8($at)\n"
"sw $a1, 12($at)\n"
"addiu $at, $a2, 0x7FF8\n"
"sw $a0, 0x7FF8($at)\n"
"sw $a1, 0x7FFC($at)\n"
"addiu $at, $a2, -0x7FF8\n"
"addiu $at, $at, -0x7FF8\n"
"sw $a0, -0x7FF8($at)\n"
"sw $a1, -0x7FF4($at)\n"
"addiu $at, $a2, -0x7FF8\n"
"addiu $at, $at, -0x7FF8\n"
"sw $a0, -8($at)\n"
"sw $a1, -4($at)\n"
"addiu $at, $a2, -0x7FF8\n"
"addiu $at, $at, -0x7FF8\n"
"sw $a0, -1($at)\n"
"sw $a1, 3($at)\n"
"addiu $at, $a2, 0x7FF8\n"
"addiu $at, $at, 0x7FF8\n"
"sw $a0, 1($at)\n"
"sw $a1, 5($at)\n"
"addiu $at, $a2, 0x7FF8\n"
"addiu $at, $at, 0x7FF8\n"
"sw $a0, 8($at)\n"
"sw $a1, 12($at)\n"
"addiu $at, $a2, 0x7FF8\n"
"addiu $at, $at, 0x7FF8\n"
"sw $a0, 0x7FF8($at)\n"
"sw $a1, 0x7FFC($at)\n"
"lui $at, 0xFFFE\n"
"ori $at, $at, 0x8010\n"
"addu $at, $at, $a2\n"
"sw $a0, 0($at)\n"
"sw $a1, 4($at)\n"
"lui $at, 0xFFFE\n"
"ori $at, $at, 0x8010\n"
"addu $at, $at, $a2\n"
"sw $a0, 7($at)\n"
"sw $a1, 11($at)\n"
"lui $at, 0x1\n"
"ori $at, $at, 0x7FE8\n"
"addu $at, $at, $a2\n"
"sw $a0, 1($at)\n"
"sw $a1, 5($at)\n"
"lui $at, 0x1\n"
"ori $at, $at, 0x7FF0\n"
"addu $at, $at, $a2\n"
"sw $a0, 0($at)\n"
"sw $a1, 4($at)\n"
"lui $at, 0x1234\n"
"ori $at, $at, 0x5678\n"
"addu $at, $at, $a2\n"
"sw $a0, 0($at)\n"
"sw $a1, 4($at)\n";
DriverStr(expected, "StoreToOffset");
}
TEST_F(AssemblerMIPSTest, StoreSToOffset) {
__ StoreSToOffset(mips::F2, mips::A0, -0x8000);
__ StoreSToOffset(mips::F2, mips::A0, +0);
__ StoreSToOffset(mips::F2, mips::A0, +0x7FF8);
__ StoreSToOffset(mips::F2, mips::A0, +0x7FFB);
__ StoreSToOffset(mips::F2, mips::A0, +0x7FFC);
__ StoreSToOffset(mips::F2, mips::A0, +0x7FFF);
__ StoreSToOffset(mips::F2, mips::A0, -0xFFF0);
__ StoreSToOffset(mips::F2, mips::A0, -0x8008);
__ StoreSToOffset(mips::F2, mips::A0, -0x8001);
__ StoreSToOffset(mips::F2, mips::A0, +0x8000);
__ StoreSToOffset(mips::F2, mips::A0, +0xFFF0);
__ StoreSToOffset(mips::F2, mips::A0, -0x17FE8);
__ StoreSToOffset(mips::F2, mips::A0, -0x0FFF8);
__ StoreSToOffset(mips::F2, mips::A0, -0x0FFF1);
__ StoreSToOffset(mips::F2, mips::A0, +0x0FFF1);
__ StoreSToOffset(mips::F2, mips::A0, +0x0FFF8);
__ StoreSToOffset(mips::F2, mips::A0, +0x17FE8);
__ StoreSToOffset(mips::F2, mips::A0, -0x17FF0);
__ StoreSToOffset(mips::F2, mips::A0, -0x17FE9);
__ StoreSToOffset(mips::F2, mips::A0, +0x17FE9);
__ StoreSToOffset(mips::F2, mips::A0, +0x17FF0);
__ StoreSToOffset(mips::F2, mips::A0, +0x12345678);
const char* expected =
"swc1 $f2, -0x8000($a0)\n"
"swc1 $f2, 0($a0)\n"
"swc1 $f2, 0x7FF8($a0)\n"
"swc1 $f2, 0x7FFB($a0)\n"
"swc1 $f2, 0x7FFC($a0)\n"
"swc1 $f2, 0x7FFF($a0)\n"
"addiu $at, $a0, -0x7FF8\n"
"swc1 $f2, -0x7FF8($at)\n"
"addiu $at, $a0, -0x7FF8\n"
"swc1 $f2, -0x10($at)\n"
"addiu $at, $a0, -0x7FF8\n"
"swc1 $f2, -9($at)\n"
"addiu $at, $a0, 0x7FF8\n"
"swc1 $f2, 8($at)\n"
"addiu $at, $a0, 0x7FF8\n"
"swc1 $f2, 0x7FF8($at)\n"
"addiu $at, $a0, -0x7FF8\n"
"addiu $at, $at, -0x7FF8\n"
"swc1 $f2, -0x7FF8($at)\n"
"addiu $at, $a0, -0x7FF8\n"
"addiu $at, $at, -0x7FF8\n"
"swc1 $f2, -8($at)\n"
"addiu $at, $a0, -0x7FF8\n"
"addiu $at, $at, -0x7FF8\n"
"swc1 $f2, -1($at)\n"
"addiu $at, $a0, 0x7FF8\n"
"addiu $at, $at, 0x7FF8\n"
"swc1 $f2, 1($at)\n"
"addiu $at, $a0, 0x7FF8\n"
"addiu $at, $at, 0x7FF8\n"
"swc1 $f2, 8($at)\n"
"addiu $at, $a0, 0x7FF8\n"
"addiu $at, $at, 0x7FF8\n"
"swc1 $f2, 0x7FF8($at)\n"
"lui $at, 0xFFFE\n"
"ori $at, $at, 0x8010\n"
"addu $at, $at, $a0\n"
"swc1 $f2, 0($at)\n"
"lui $at, 0xFFFE\n"
"ori $at, $at, 0x8010\n"
"addu $at, $at, $a0\n"
"swc1 $f2, 7($at)\n"
"lui $at, 0x1\n"
"ori $at, $at, 0x7FE8\n"
"addu $at, $at, $a0\n"
"swc1 $f2, 1($at)\n"
"lui $at, 0x1\n"
"ori $at, $at, 0x7FF0\n"
"addu $at, $at, $a0\n"
"swc1 $f2, 0($at)\n"
"lui $at, 0x1234\n"
"ori $at, $at, 0x5678\n"
"addu $at, $at, $a0\n"
"swc1 $f2, 0($at)\n";
DriverStr(expected, "StoreSToOffset");
}
TEST_F(AssemblerMIPSTest, StoreDToOffset) {
__ StoreDToOffset(mips::F0, mips::A0, -0x8000);
__ StoreDToOffset(mips::F0, mips::A0, +0);
__ StoreDToOffset(mips::F0, mips::A0, +0x7FF8);
__ StoreDToOffset(mips::F0, mips::A0, +0x7FFB);
__ StoreDToOffset(mips::F0, mips::A0, +0x7FFC);
__ StoreDToOffset(mips::F0, mips::A0, +0x7FFF);
__ StoreDToOffset(mips::F0, mips::A0, -0xFFF0);
__ StoreDToOffset(mips::F0, mips::A0, -0x8008);
__ StoreDToOffset(mips::F0, mips::A0, -0x8001);
__ StoreDToOffset(mips::F0, mips::A0, +0x8000);
__ StoreDToOffset(mips::F0, mips::A0, +0xFFF0);
__ StoreDToOffset(mips::F0, mips::A0, -0x17FE8);
__ StoreDToOffset(mips::F0, mips::A0, -0x0FFF8);
__ StoreDToOffset(mips::F0, mips::A0, -0x0FFF1);
__ StoreDToOffset(mips::F0, mips::A0, +0x0FFF1);
__ StoreDToOffset(mips::F0, mips::A0, +0x0FFF8);
__ StoreDToOffset(mips::F0, mips::A0, +0x17FE8);
__ StoreDToOffset(mips::F0, mips::A0, -0x17FF0);
__ StoreDToOffset(mips::F0, mips::A0, -0x17FE9);
__ StoreDToOffset(mips::F0, mips::A0, +0x17FE9);
__ StoreDToOffset(mips::F0, mips::A0, +0x17FF0);
__ StoreDToOffset(mips::F0, mips::A0, +0x12345678);
const char* expected =
"sdc1 $f0, -0x8000($a0)\n"
"sdc1 $f0, 0($a0)\n"
"sdc1 $f0, 0x7FF8($a0)\n"
"swc1 $f0, 0x7FFB($a0)\n"
"swc1 $f1, 0x7FFF($a0)\n"
"addiu $at, $a0, 0x7FF8\n"
"swc1 $f0, 4($at)\n"
"swc1 $f1, 8($at)\n"
"addiu $at, $a0, 0x7FF8\n"
"swc1 $f0, 7($at)\n"
"swc1 $f1, 11($at)\n"
"addiu $at, $a0, -0x7FF8\n"
"sdc1 $f0, -0x7FF8($at)\n"
"addiu $at, $a0, -0x7FF8\n"
"sdc1 $f0, -0x10($at)\n"
"addiu $at, $a0, -0x7FF8\n"
"swc1 $f0, -9($at)\n"
"swc1 $f1, -5($at)\n"
"addiu $at, $a0, 0x7FF8\n"
"sdc1 $f0, 8($at)\n"
"addiu $at, $a0, 0x7FF8\n"
"sdc1 $f0, 0x7FF8($at)\n"
"addiu $at, $a0, -0x7FF8\n"
"addiu $at, $at, -0x7FF8\n"
"sdc1 $f0, -0x7FF8($at)\n"
"addiu $at, $a0, -0x7FF8\n"
"addiu $at, $at, -0x7FF8\n"
"sdc1 $f0, -8($at)\n"
"addiu $at, $a0, -0x7FF8\n"
"addiu $at, $at, -0x7FF8\n"
"swc1 $f0, -1($at)\n"
"swc1 $f1, 3($at)\n"
"addiu $at, $a0, 0x7FF8\n"
"addiu $at, $at, 0x7FF8\n"
"swc1 $f0, 1($at)\n"
"swc1 $f1, 5($at)\n"
"addiu $at, $a0, 0x7FF8\n"
"addiu $at, $at, 0x7FF8\n"
"sdc1 $f0, 8($at)\n"
"addiu $at, $a0, 0x7FF8\n"
"addiu $at, $at, 0x7FF8\n"
"sdc1 $f0, 0x7FF8($at)\n"
"lui $at, 0xFFFE\n"
"ori $at, $at, 0x8010\n"
"addu $at, $at, $a0\n"
"sdc1 $f0, 0($at)\n"
"lui $at, 0xFFFE\n"
"ori $at, $at, 0x8010\n"
"addu $at, $at, $a0\n"
"swc1 $f0, 7($at)\n"
"swc1 $f1, 11($at)\n"
"lui $at, 0x1\n"
"ori $at, $at, 0x7FE8\n"
"addu $at, $at, $a0\n"
"swc1 $f0, 1($at)\n"
"swc1 $f1, 5($at)\n"
"lui $at, 0x1\n"
"ori $at, $at, 0x7FF0\n"
"addu $at, $at, $a0\n"
"sdc1 $f0, 0($at)\n"
"lui $at, 0x1234\n"
"ori $at, $at, 0x5678\n"
"addu $at, $at, $a0\n"
"sdc1 $f0, 0($at)\n";
DriverStr(expected, "StoreDToOffset");
}
TEST_F(AssemblerMIPSTest, StoreConstToOffset) {
__ StoreConstToOffset(mips::kStoreByte, 0xFF, mips::A1, +0, mips::T8);
__ StoreConstToOffset(mips::kStoreHalfword, 0xFFFF, mips::A1, +0, mips::T8);
__ StoreConstToOffset(mips::kStoreWord, 0x12345678, mips::A1, +0, mips::T8);
__ StoreConstToOffset(mips::kStoreDoubleword, 0x123456789ABCDEF0, mips::A1, +0, mips::T8);
__ StoreConstToOffset(mips::kStoreByte, 0, mips::A1, +0, mips::T8);
__ StoreConstToOffset(mips::kStoreHalfword, 0, mips::A1, +0, mips::T8);
__ StoreConstToOffset(mips::kStoreWord, 0, mips::A1, +0, mips::T8);
__ StoreConstToOffset(mips::kStoreDoubleword, 0, mips::A1, +0, mips::T8);
__ StoreConstToOffset(mips::kStoreDoubleword, 0x1234567812345678, mips::A1, +0, mips::T8);
__ StoreConstToOffset(mips::kStoreDoubleword, 0x1234567800000000, mips::A1, +0, mips::T8);
__ StoreConstToOffset(mips::kStoreDoubleword, 0x0000000012345678, mips::A1, +0, mips::T8);
__ StoreConstToOffset(mips::kStoreWord, 0, mips::T8, +0, mips::T8);
__ StoreConstToOffset(mips::kStoreWord, 0x12345678, mips::T8, +0, mips::T8);
__ StoreConstToOffset(mips::kStoreWord, 0, mips::A1, -0xFFF0, mips::T8);
__ StoreConstToOffset(mips::kStoreWord, 0x12345678, mips::A1, +0xFFF0, mips::T8);
__ StoreConstToOffset(mips::kStoreWord, 0, mips::T8, -0xFFF0, mips::T8);
__ StoreConstToOffset(mips::kStoreWord, 0x12345678, mips::T8, +0xFFF0, mips::T8);
const char* expected =
"ori $t8, $zero, 0xFF\n"
"sb $t8, 0($a1)\n"
"ori $t8, $zero, 0xFFFF\n"
"sh $t8, 0($a1)\n"
"lui $t8, 0x1234\n"
"ori $t8, $t8, 0x5678\n"
"sw $t8, 0($a1)\n"
"lui $t8, 0x9ABC\n"
"ori $t8, $t8, 0xDEF0\n"
"sw $t8, 0($a1)\n"
"lui $t8, 0x1234\n"
"ori $t8, $t8, 0x5678\n"
"sw $t8, 4($a1)\n"
"sb $zero, 0($a1)\n"
"sh $zero, 0($a1)\n"
"sw $zero, 0($a1)\n"
"sw $zero, 0($a1)\n"
"sw $zero, 4($a1)\n"
"lui $t8, 0x1234\n"
"ori $t8, $t8, 0x5678\n"
"sw $t8, 0($a1)\n"
"sw $t8, 4($a1)\n"
"sw $zero, 0($a1)\n"
"lui $t8, 0x1234\n"
"ori $t8, $t8, 0x5678\n"
"sw $t8, 4($a1)\n"
"lui $t8, 0x1234\n"
"ori $t8, $t8, 0x5678\n"
"sw $t8, 0($a1)\n"
"sw $zero, 4($a1)\n"
"sw $zero, 0($t8)\n"
"lui $at, 0x1234\n"
"ori $at, $at, 0x5678\n"
"sw $at, 0($t8)\n"
"addiu $at, $a1, -0x7FF8\n"
"sw $zero, -0x7FF8($at)\n"
"addiu $at, $a1, 0x7FF8\n"
"lui $t8, 0x1234\n"
"ori $t8, $t8, 0x5678\n"
"sw $t8, 0x7FF8($at)\n"
"addiu $at, $t8, -0x7FF8\n"
"sw $zero, -0x7FF8($at)\n"
"addiu $at, $t8, 0x7FF8\n"
"lui $t8, 0x1234\n"
"ori $t8, $t8, 0x5678\n"
"sw $t8, 0x7FF8($at)\n";
DriverStr(expected, "StoreConstToOffset");
}
//////////////
// BRANCHES //
//////////////
TEST_F(AssemblerMIPSTest, B) {
BranchHelper(&mips::MipsAssembler::B, "B");
}
TEST_F(AssemblerMIPSTest, Bal) {
BranchHelper(&mips::MipsAssembler::Bal, "Bal");
}
TEST_F(AssemblerMIPSTest, Beq) {
BranchCondTwoRegsHelper(&mips::MipsAssembler::Beq, "Beq");
}
TEST_F(AssemblerMIPSTest, Bne) {
BranchCondTwoRegsHelper(&mips::MipsAssembler::Bne, "Bne");
}
TEST_F(AssemblerMIPSTest, Beqz) {
BranchCondOneRegHelper(&mips::MipsAssembler::Beqz, "Beqz");
}
TEST_F(AssemblerMIPSTest, Bnez) {
BranchCondOneRegHelper(&mips::MipsAssembler::Bnez, "Bnez");
}
TEST_F(AssemblerMIPSTest, Bltz) {
BranchCondOneRegHelper(&mips::MipsAssembler::Bltz, "Bltz");
}
TEST_F(AssemblerMIPSTest, Bgez) {
BranchCondOneRegHelper(&mips::MipsAssembler::Bgez, "Bgez");
}
TEST_F(AssemblerMIPSTest, Blez) {
BranchCondOneRegHelper(&mips::MipsAssembler::Blez, "Blez");
}
TEST_F(AssemblerMIPSTest, Bgtz) {
BranchCondOneRegHelper(&mips::MipsAssembler::Bgtz, "Bgtz");
}
TEST_F(AssemblerMIPSTest, Blt) {
BranchCondTwoRegsHelper(&mips::MipsAssembler::Blt, "Blt");
}
TEST_F(AssemblerMIPSTest, Bge) {
BranchCondTwoRegsHelper(&mips::MipsAssembler::Bge, "Bge");
}
TEST_F(AssemblerMIPSTest, Bltu) {
BranchCondTwoRegsHelper(&mips::MipsAssembler::Bltu, "Bltu");
}
TEST_F(AssemblerMIPSTest, Bgeu) {
BranchCondTwoRegsHelper(&mips::MipsAssembler::Bgeu, "Bgeu");
}
TEST_F(AssemblerMIPSTest, Bc1f) {
BranchFpuCondCodeHelper(&mips::MipsAssembler::Bc1f, "Bc1f");
}
TEST_F(AssemblerMIPSTest, Bc1t) {
BranchFpuCondCodeHelper(&mips::MipsAssembler::Bc1t, "Bc1t");
}
TEST_F(AssemblerMIPSTest, BareB) {
BranchHelper(&mips::MipsAssembler::B, "B", /* is_bare= */ true);
}
TEST_F(AssemblerMIPSTest, BareBal) {
BranchHelper(&mips::MipsAssembler::Bal, "Bal", /* is_bare= */ true);
}
TEST_F(AssemblerMIPSTest, BareBeq) {
BranchCondTwoRegsHelper(&mips::MipsAssembler::Beq, "Beq", /* is_bare= */ true);
}
TEST_F(AssemblerMIPSTest, BareBne) {
BranchCondTwoRegsHelper(&mips::MipsAssembler::Bne, "Bne", /* is_bare= */ true);
}
TEST_F(AssemblerMIPSTest, BareBeqz) {
BranchCondOneRegHelper(&mips::MipsAssembler::Beqz, "Beqz", /* is_bare= */ true);
}
TEST_F(AssemblerMIPSTest, BareBnez) {
BranchCondOneRegHelper(&mips::MipsAssembler::Bnez, "Bnez", /* is_bare= */ true);
}
TEST_F(AssemblerMIPSTest, BareBltz) {
BranchCondOneRegHelper(&mips::MipsAssembler::Bltz, "Bltz", /* is_bare= */ true);
}
TEST_F(AssemblerMIPSTest, BareBgez) {
BranchCondOneRegHelper(&mips::MipsAssembler::Bgez, "Bgez", /* is_bare= */ true);
}
TEST_F(AssemblerMIPSTest, BareBlez) {
BranchCondOneRegHelper(&mips::MipsAssembler::Blez, "Blez", /* is_bare= */ true);
}
TEST_F(AssemblerMIPSTest, BareBgtz) {
BranchCondOneRegHelper(&mips::MipsAssembler::Bgtz, "Bgtz", /* is_bare= */ true);
}
TEST_F(AssemblerMIPSTest, BareBlt) {
BranchCondTwoRegsHelper(&mips::MipsAssembler::Blt, "Blt", /* is_bare= */ true);
}
TEST_F(AssemblerMIPSTest, BareBge) {
BranchCondTwoRegsHelper(&mips::MipsAssembler::Bge, "Bge", /* is_bare= */ true);
}
TEST_F(AssemblerMIPSTest, BareBltu) {
BranchCondTwoRegsHelper(&mips::MipsAssembler::Bltu, "Bltu", /* is_bare= */ true);
}
TEST_F(AssemblerMIPSTest, BareBgeu) {
BranchCondTwoRegsHelper(&mips::MipsAssembler::Bgeu, "Bgeu", /* is_bare= */ true);
}
TEST_F(AssemblerMIPSTest, BareBc1f) {
BranchFpuCondCodeHelper(&mips::MipsAssembler::Bc1f, "Bc1f", /* is_bare= */ true);
}
TEST_F(AssemblerMIPSTest, BareBc1t) {
BranchFpuCondCodeHelper(&mips::MipsAssembler::Bc1t, "Bc1t", /* is_bare= */ true);
}
TEST_F(AssemblerMIPSTest, ImpossibleReordering) {
mips::MipsLabel label1, label2;
__ SetReorder(true);
__ B(&label1); // No preceding or target instruction for the delay slot.
__ Addu(mips::T0, mips::T1, mips::T2);
__ Bind(&label1);
__ B(&label1); // The preceding label prevents moving Addu into the delay slot.
__ B(&label1); // No preceding or target instruction for the delay slot.
__ Addu(mips::T0, mips::T1, mips::T2);
__ Beqz(mips::T0, &label1); // T0 dependency.
__ Or(mips::T1, mips::T2, mips::T3);
__ Bne(mips::T2, mips::T1, &label1); // T1 dependency.
__ And(mips::T0, mips::T1, mips::T2);
__ Blt(mips::T1, mips::T0, &label1); // T0 dependency.
__ Xor(mips::AT, mips::T0, mips::T1);
__ Bge(mips::T1, mips::T0, &label1); // AT dependency.
__ Subu(mips::T0, mips::T1, mips::AT);
__ Bltu(mips::T1, mips::T0, &label1); // AT dependency.
__ ColtS(1, mips::F2, mips::F4);
__ Bc1t(1, &label1); // cc1 dependency.
__ Move(mips::T0, mips::RA);
__ Bal(&label1); // RA dependency.
__ Lw(mips::RA, mips::T0, 0);
__ Bal(&label1); // RA dependency.
__ LlR2(mips::T9, mips::T0, 0);
__ Jalr(mips::T9); // T9 dependency.
__ Sw(mips::RA, mips::T0, 0);
__ Jalr(mips::T9); // RA dependency.
__ Lw(mips::T1, mips::T0, 0);
__ Jalr(mips::T1, mips::T9); // T1 dependency.
__ ScR2(mips::T9, mips::T0, 0);
__ Jr(mips::T9); // T9 dependency.
__ Bind(&label2);
__ Bnez(mips::T0, &label2); // No preceding instruction for the delay slot.
__ Bgeu(mips::T1, mips::T0, &label2); // No preceding instruction for the delay slot.
__ Bc1f(2, &label2); // No preceding instruction for the delay slot.
__ Bal(&label2); // No preceding instruction for the delay slot.
__ Jalr(mips::T9); // No preceding instruction for the delay slot.
__ Addu(mips::T0, mips::T1, mips::T2);
__ CodePosition(); // Drops the delay slot candidate (the last instruction).
__ Beq(mips::T1, mips::T2, &label2); // No preceding or target instruction for the delay slot.
std::string expected =
".set noreorder\n"
"b 1f\n"
"nop\n"
"addu $t0, $t1, $t2\n"
"1:\n"
"b 1b\n"
"nop\n"
"b 1b\n"
"nop\n"
"addu $t0, $t1, $t2\n"
"beqz $t0, 1b\n"
"nop\n"
"or $t1, $t2, $t3\n"
"bne $t2, $t1, 1b\n"
"nop\n"
"and $t0, $t1, $t2\n"
"slt $at, $t1, $t0\n"
"bnez $at, 1b\n"
"nop\n"
"xor $at, $t0, $t1\n"
"slt $at, $t1, $t0\n"
"beqz $at, 1b\n"
"nop\n"
"subu $t0, $t1, $at\n"
"sltu $at, $t1, $t0\n"
"bnez $at, 1b\n"
"nop\n"
"c.olt.s $fcc1, $f2, $f4\n"
"bc1t $fcc1, 1b\n"
"nop\n"
"or $t0, $ra, $zero\n"
"bal 1b\n"
"nop\n"
"lw $ra, 0($t0)\n"
"bal 1b\n"
"nop\n"
"ll $t9, 0($t0)\n"
"jalr $t9\n"
"nop\n"
"sw $ra, 0($t0)\n"
"jalr $t9\n"
"nop\n"
"lw $t1, 0($t0)\n"
"jalr $t1, $t9\n"
"nop\n"
"sc $t9, 0($t0)\n"
"jalr $zero, $t9\n"
"nop\n"
"2:\n"
"bnez $t0, 2b\n"
"nop\n"
"sltu $at, $t1, $t0\n"
"beqz $at, 2b\n"
"nop\n"
"bc1f $fcc2, 2b\n"
"nop\n"
"bal 2b\n"
"nop\n"
"jalr $t9\n"
"nop\n"
"addu $t0, $t1, $t2\n"
"beq $t1, $t2, 2b\n"
"nop\n";
DriverStr(expected, "ImpossibleReordering");
}
TEST_F(AssemblerMIPSTest, Reordering) {
mips::MipsLabel label1, label2;
__ SetReorder(true);
__ Bind(&label1);
__ Bind(&label2);
__ Addu(mips::T0, mips::T1, mips::T2);
__ Beqz(mips::T1, &label1);
__ Or(mips::T1, mips::T2, mips::T3);
__ Bne(mips::T2, mips::T3, &label1);
__ And(mips::T0, mips::T1, mips::T2);
__ Blt(mips::T1, mips::T2, &label1);
__ Xor(mips::T2, mips::T0, mips::T1);
__ Bge(mips::T1, mips::T0, &label1);
__ Subu(mips::T2, mips::T1, mips::T0);
__ Bltu(mips::T1, mips::T0, &label1);
__ ColtS(0, mips::F2, mips::F4);
__ Bc1t(1, &label1);
__ Move(mips::T0, mips::T1);
__ Bal(&label1);
__ LlR2(mips::T1, mips::T0, 0);
__ Jalr(mips::T9);
__ ScR2(mips::T1, mips::T0, 0);
__ Jr(mips::T9);
std::string expected =
".set noreorder\n"
"1:\n"
"beqz $t1, 1b\n"
"addu $t0, $t1, $t2\n"
"bne $t2, $t3, 1b\n"
"or $t1, $t2, $t3\n"
"slt $at, $t1, $t2\n"
"bnez $at, 1b\n"
"and $t0, $t1, $t2\n"
"slt $at, $t1, $t0\n"
"beqz $at, 1b\n"
"xor $t2, $t0, $t1\n"
"sltu $at, $t1, $t0\n"
"bnez $at, 1b\n"
"subu $t2, $t1, $t0\n"
"bc1t $fcc1, 1b\n"
"c.olt.s $fcc0, $f2, $f4\n"
"bal 1b\n"
"or $t0, $t1, $zero\n"
"jalr $t9\n"
"ll $t1, 0($t0)\n"
"jalr $zero, $t9\n"
"sc $t1, 0($t0)\n";
DriverStr(expected, "Reordering");
}
TEST_F(AssemblerMIPSTest, AbsorbTargetInstruction) {
mips::MipsLabel label1, label2, label3, label4, label5, label6;
mips::MipsLabel label7, label8, label9, label10, label11, label12, label13;
__ SetReorder(true);
__ B(&label1);
__ Bind(&label1);
__ Addu(mips::T0, mips::T1, mips::T2);
__ Bind(&label2);
__ Xor(mips::T0, mips::T1, mips::T2);
__ Addu(mips::T0, mips::T1, mips::T2);
__ Bind(&label3); // Prevents reordering ADDU above with B below.
__ B(&label2);
__ B(&label4);
__ Bind(&label4);
__ Addu(mips::T0, mips::T1, mips::T2);
__ CodePosition(); // Prevents absorbing ADDU above.
__ B(&label5);
__ Bind(&label5);
__ Addu(mips::T0, mips::T1, mips::T2);
__ Bind(&label6);
__ CodePosition(); // Even across Bind(), CodePosition() prevents absorbing the ADDU above.
__ Nop();
__ B(&label7);
__ Bind(&label7);
__ Lw(mips::V0, mips::A0, 0x5678); // Possibly patchable instruction, not absorbed.
__ Nop();
__ B(&label8);
__ Bind(&label8);
__ Sw(mips::V0, mips::A0, 0x5678); // Possibly patchable instruction, not absorbed.
__ Nop();
__ B(&label9);
__ Bind(&label9);
__ Addiu(mips::V0, mips::A0, 0x5678); // Possibly patchable instruction, not absorbed.
__ Nop();
__ B(&label10);
__ Bind(&label10);
__ Lw(mips::V0, mips::A0, 0x5680); // Immediate isn't 0x5678, absorbed.
__ Nop();
__ B(&label11);
__ Bind(&label11);
__ Sw(mips::V0, mips::A0, 0x5680); // Immediate isn't 0x5678, absorbed.
__ Nop();
__ B(&label12);
__ Bind(&label12);
__ Addiu(mips::V0, mips::A0, 0x5680); // Immediate isn't 0x5678, absorbed.
__ Nop();
__ B(&label13);
__ Bind(&label13);
__ Andi(mips::V0, mips::A0, 0x5678); // Not one of patchable instructions, absorbed.
std::string expected =
".set noreorder\n"
"b 1f\n"
"addu $t0, $t1, $t2\n"
"addu $t0, $t1, $t2\n"
"1:\n"
"xor $t0, $t1, $t2\n"
"2:\n"
"addu $t0, $t1, $t2\n"
"b 2b\n"
"xor $t0, $t1, $t2\n"
"b 4f\n"
"nop\n"
"4:\n"
"addu $t0, $t1, $t2\n"
"b 5f\n"
"nop\n"
"5:\n"
"addu $t0, $t1, $t2\n"
"nop\n"
"b 7f\n"
"nop\n"
"7:\n"
"lw $v0, 0x5678($a0)\n"
"nop\n"
"b 8f\n"
"nop\n"
"8:\n"
"sw $v0, 0x5678($a0)\n"
"nop\n"
"b 9f\n"
"nop\n"
"9:\n"
"addiu $v0, $a0, 0x5678\n"
"nop\n"
"b 10f\n"
"lw $v0, 0x5680($a0)\n"
"lw $v0, 0x5680($a0)\n"
"10:\n"
"nop\n"
"b 11f\n"
"sw $v0, 0x5680($a0)\n"
"sw $v0, 0x5680($a0)\n"
"11:\n"
"nop\n"
"b 12f\n"
"addiu $v0, $a0, 0x5680\n"
"addiu $v0, $a0, 0x5680\n"
"12:\n"
"nop\n"
"b 13f\n"
"andi $v0, $a0, 0x5678\n"
"andi $v0, $a0, 0x5678\n"
"13:\n";
DriverStr(expected, "AbsorbTargetInstruction");
}
TEST_F(AssemblerMIPSTest, SetReorder) {
mips::MipsLabel label1, label2, label3, label4, label5, label6;
__ SetReorder(true);
__ Bind(&label1);
__ Addu(mips::T0, mips::T1, mips::T2);
__ B(&label1);
__ B(&label5);
__ B(&label6);
__ SetReorder(false);
__ Bind(&label2);
__ Addu(mips::T0, mips::T1, mips::T2);
__ B(&label2);
__ B(&label5);
__ B(&label6);
__ SetReorder(true);
__ Bind(&label3);
__ Addu(mips::T0, mips::T1, mips::T2);
__ B(&label3);
__ B(&label5);
__ B(&label6);
__ SetReorder(false);
__ Bind(&label4);
__ Addu(mips::T0, mips::T1, mips::T2);
__ B(&label4);
__ B(&label5);
__ B(&label6);
__ SetReorder(true);
__ Bind(&label5);
__ Subu(mips::T0, mips::T1, mips::T2);
__ SetReorder(false);
__ Bind(&label6);
__ Xor(mips::T0, mips::T1, mips::T2);
std::string expected =
".set noreorder\n"
"1:\n"
"b 1b\n"
"addu $t0, $t1, $t2\n"
"b 55f\n"
"subu $t0, $t1, $t2\n"
"b 6f\n"
"nop\n"
"2:\n"
"addu $t0, $t1, $t2\n"
"b 2b\n"
"nop\n"
"b 5f\n"
"nop\n"
"b 6f\n"
"nop\n"
"3:\n"
"b 3b\n"
"addu $t0, $t1, $t2\n"
"b 55f\n"
"subu $t0, $t1, $t2\n"
"b 6f\n"
"nop\n"
"4:\n"
"addu $t0, $t1, $t2\n"
"b 4b\n"
"nop\n"
"b 5f\n"
"nop\n"
"b 6f\n"
"nop\n"
"5:\n"
"subu $t0, $t1, $t2\n"
"55:\n"
"6:\n"
"xor $t0, $t1, $t2\n";
DriverStr(expected, "SetReorder");
}
TEST_F(AssemblerMIPSTest, ReorderPatchedInstruction) {
__ SetReorder(true);
mips::MipsLabel label1, label2;
mips::MipsLabel patcher_label1, patcher_label2, patcher_label3, patcher_label4, patcher_label5;
__ Lw(mips::V0, mips::A0, 0x5678, &patcher_label1);
__ Beq(mips::A0, mips::A1, &label1);
constexpr uint32_t kAdduCount1 = 63;
for (size_t i = 0; i != kAdduCount1; ++i) {
__ Addu(mips::ZERO, mips::ZERO, mips::ZERO);
}
__ Bind(&label1);
__ Sw(mips::V0, mips::A0, 0x5678, &patcher_label2);
__ Bltz(mips::V1, &label2);
constexpr uint32_t kAdduCount2 = 64;
for (size_t i = 0; i != kAdduCount2; ++i) {
__ Addu(mips::ZERO, mips::ZERO, mips::ZERO);
}
__ Bind(&label2);
__ Addiu(mips::V0, mips::A0, 0x5678, &patcher_label3);
__ B(&label1);
__ Lw(mips::V0, mips::A0, 0x5678, &patcher_label4);
__ Jalr(mips::T9);
__ Sw(mips::V0, mips::A0, 0x5678, &patcher_label5);
__ Blt(mips::V0, mips::V1, &label2);
__ Addu(mips::ZERO, mips::ZERO, mips::ZERO);
std::string expected =
".set noreorder\n"
"beq $a0, $a1, 1f\n"
"lw $v0, 0x5678($a0)\n" +
RepeatInsn(kAdduCount1, "addu $zero, $zero, $zero\n") +
"1:\n"
"bltz $v1, 2f\n"
"sw $v0, 0x5678($a0)\n" +
RepeatInsn(kAdduCount2, "addu $zero, $zero, $zero\n") +
"2:\n"
"b 1b\n"
"addiu $v0, $a0, 0x5678\n"
"jalr $t9\n"
"lw $v0, 0x5678($a0)\n"
"slt $at, $v0, $v1\n"
"bnez $at, 2b\n"
"sw $v0, 0x5678($a0)\n"
"addu $zero, $zero, $zero\n";
DriverStr(expected, "ReorderPatchedInstruction");
EXPECT_EQ(__ GetLabelLocation(&patcher_label1), 1 * 4u);
EXPECT_EQ(__ GetLabelLocation(&patcher_label2), (kAdduCount1 + 3) * 4u);
EXPECT_EQ(__ GetLabelLocation(&patcher_label3), (kAdduCount1 + kAdduCount2 + 5) * 4u);
EXPECT_EQ(__ GetLabelLocation(&patcher_label4), (kAdduCount1 + kAdduCount2 + 7) * 4u);
EXPECT_EQ(__ GetLabelLocation(&patcher_label5), (kAdduCount1 + kAdduCount2 + 10) * 4u);
}
TEST_F(AssemblerMIPSTest, LongBranchReorder) {
mips::MipsLabel label, patcher_label1, patcher_label2;
__ SetReorder(true);
__ Addiu(mips::T0, mips::T1, 0x5678, &patcher_label1);
__ B(&label);
constexpr uint32_t kAdduCount1 = (1u << 15) + 1;
for (size_t i = 0; i != kAdduCount1; ++i) {
__ Addu(mips::ZERO, mips::ZERO, mips::ZERO);
}
__ Bind(&label);
constexpr uint32_t kAdduCount2 = (1u << 15) + 1;
for (size_t i = 0; i != kAdduCount2; ++i) {
__ Addu(mips::ZERO, mips::ZERO, mips::ZERO);
}
__ Addiu(mips::T0, mips::T1, 0x5678, &patcher_label2);
__ B(&label);
// Account for 5 extra instructions: ori, addu, lw, jalr, addiu.
uint32_t offset_forward = (kAdduCount1 + 5) * sizeof(uint32_t);
// Account for 5 extra instructions: subu, addiu, sw, nal, lui.
uint32_t offset_back = static_cast<uint32_t>(-(kAdduCount1 + 5) * sizeof(uint32_t));
std::ostringstream oss;
oss <<
".set noreorder\n"
"addiu $t0, $t1, 0x5678\n"
"addiu $sp, $sp, -16\n"
"sw $ra, 0($sp)\n"
"bltzal $zero, .+4\n"
"lui $at, 0x" << std::hex << High16Bits(offset_forward) << "\n"
"ori $at, $at, 0x" << std::hex << Low16Bits(offset_forward) << "\n"
"addu $at, $at, $ra\n"
"lw $ra, 0($sp)\n"
"jalr $zero, $at\n"
"addiu $sp, $sp, 16\n" <<
RepeatInsn(kAdduCount1, "addu $zero, $zero, $zero\n") <<
RepeatInsn(kAdduCount2, "addu $zero, $zero, $zero\n") <<
"addiu $t0, $t1, 0x5678\n"
"addiu $sp, $sp, -16\n"
"sw $ra, 0($sp)\n"
"bltzal $zero, .+4\n"
"lui $at, 0x" << std::hex << High16Bits(offset_back) << "\n"
"ori $at, $at, 0x" << std::hex << Low16Bits(offset_back) << "\n"
"addu $at, $at, $ra\n"
"lw $ra, 0($sp)\n"
"jalr $zero, $at\n"
"addiu $sp, $sp, 16\n";
std::string expected = oss.str();
DriverStr(expected, "LongBranchReorder");
EXPECT_EQ(__ GetLabelLocation(&patcher_label1), 0 * 4u);
EXPECT_EQ(__ GetLabelLocation(&patcher_label2), (kAdduCount1 + kAdduCount2 + 10) * 4u);
}
///////////////////////
// Loading Constants //
///////////////////////
TEST_F(AssemblerMIPSTest, LoadConst32) {
// IsUint<16>(value)
__ LoadConst32(mips::V0, 0);
__ LoadConst32(mips::V0, 65535);
// IsInt<16>(value)
__ LoadConst32(mips::V0, -1);
__ LoadConst32(mips::V0, -32768);
// Everything else
__ LoadConst32(mips::V0, 65536);
__ LoadConst32(mips::V0, 65537);
__ LoadConst32(mips::V0, 2147483647);
__ LoadConst32(mips::V0, -32769);
__ LoadConst32(mips::V0, -65536);
__ LoadConst32(mips::V0, -65537);
__ LoadConst32(mips::V0, -2147483647);
__ LoadConst32(mips::V0, -2147483648);
const char* expected =
// IsUint<16>(value)
"ori $v0, $zero, 0\n" // __ LoadConst32(mips::V0, 0);
"ori $v0, $zero, 65535\n" // __ LoadConst32(mips::V0, 65535);
// IsInt<16>(value)
"addiu $v0, $zero, -1\n" // __ LoadConst32(mips::V0, -1);
"addiu $v0, $zero, -32768\n" // __ LoadConst32(mips::V0, -32768);
// Everything else
"lui $v0, 1\n" // __ LoadConst32(mips::V0, 65536);
"lui $v0, 1\n" // __ LoadConst32(mips::V0, 65537);
"ori $v0, 1\n" // "
"lui $v0, 32767\n" // __ LoadConst32(mips::V0, 2147483647);
"ori $v0, 65535\n" // "
"lui $v0, 65535\n" // __ LoadConst32(mips::V0, -32769);
"ori $v0, 32767\n" // "
"lui $v0, 65535\n" // __ LoadConst32(mips::V0, -65536);
"lui $v0, 65534\n" // __ LoadConst32(mips::V0, -65537);
"ori $v0, 65535\n" // "
"lui $v0, 32768\n" // __ LoadConst32(mips::V0, -2147483647);
"ori $v0, 1\n" // "
"lui $v0, 32768\n"; // __ LoadConst32(mips::V0, -2147483648);
DriverStr(expected, "LoadConst32");
}
TEST_F(AssemblerMIPSTest, LoadFarthestNearLabelAddress) {
mips::MipsLabel label;
__ BindPcRelBaseLabel();
__ LoadLabelAddress(mips::V0, mips::V1, &label);
constexpr size_t kAddiuCount = 0x1FDE;
for (size_t i = 0; i != kAddiuCount; ++i) {
__ Addiu(mips::A0, mips::A1, 0);
}
__ Bind(&label);
std::string expected =
"1:\n"
"addiu $v0, $v1, %lo(2f - 1b)\n" +
RepeatInsn(kAddiuCount, "addiu $a0, $a1, %hi(2f - 1b)\n") +
"2:\n";
DriverStr(expected, "LoadFarthestNearLabelAddress");
}
TEST_F(AssemblerMIPSTest, LoadNearestFarLabelAddress) {
mips::MipsLabel label;
__ BindPcRelBaseLabel();
__ LoadLabelAddress(mips::V0, mips::V1, &label);
constexpr size_t kAdduCount = 0x1FDF;
for (size_t i = 0; i != kAdduCount; ++i) {
__ Addu(mips::ZERO, mips::ZERO, mips::ZERO);
}
__ Bind(&label);
std::string expected =
"1:\n"
"lui $at, %hi(2f - 1b)\n"
"ori $at, $at, %lo(2f - 1b)\n"
"addu $v0, $at, $v1\n" +
RepeatInsn(kAdduCount, "addu $zero, $zero, $zero\n") +
"2:\n";
DriverStr(expected, "LoadNearestFarLabelAddress");
}
TEST_F(AssemblerMIPSTest, LoadFarthestNearLabelAddressUsingNal) {
mips::MipsLabel label;
__ LoadLabelAddress(mips::V0, mips::ZERO, &label);
constexpr size_t kAddiuCount = 0x1FDE;
for (size_t i = 0; i != kAddiuCount; ++i) {
__ Addiu(mips::A0, mips::A1, 0);
}
__ Bind(&label);
std::string expected =
".set noreorder\n"
"bltzal $zero, .+4\n"
"addiu $v0, $ra, %lo(2f - 1f)\n"
"1:\n" +
RepeatInsn(kAddiuCount, "addiu $a0, $a1, %hi(2f - 1b)\n") +
"2:\n";
DriverStr(expected, "LoadFarthestNearLabelAddressUsingNal");
}
TEST_F(AssemblerMIPSTest, LoadNearestFarLabelAddressUsingNal) {
mips::MipsLabel label;
__ LoadLabelAddress(mips::V0, mips::ZERO, &label);
constexpr size_t kAdduCount = 0x1FDF;
for (size_t i = 0; i != kAdduCount; ++i) {
__ Addu(mips::ZERO, mips::ZERO, mips::ZERO);
}
__ Bind(&label);
std::string expected =
".set noreorder\n"
"bltzal $zero, .+4\n"
"lui $at, %hi(2f - 1f)\n"
"1:\n"
"ori $at, $at, %lo(2f - 1b)\n"
"addu $v0, $at, $ra\n" +
RepeatInsn(kAdduCount, "addu $zero, $zero, $zero\n") +
"2:\n";
DriverStr(expected, "LoadNearestFarLabelAddressUsingNal");
}
TEST_F(AssemblerMIPSTest, LoadFarthestNearLiteral) {
mips::Literal* literal = __ NewLiteral<uint32_t>(0x12345678);
__ BindPcRelBaseLabel();
__ LoadLiteral(mips::V0, mips::V1, literal);
constexpr size_t kAddiuCount = 0x1FDE;
for (size_t i = 0; i != kAddiuCount; ++i) {
__ Addiu(mips::A0, mips::A1, 0);
}
std::string expected =
"1:\n"
"lw $v0, %lo(2f - 1b)($v1)\n" +
RepeatInsn(kAddiuCount, "addiu $a0, $a1, %hi(2f - 1b)\n") +
"2:\n"
".word 0x12345678\n";
DriverStr(expected, "LoadFarthestNearLiteral");
}
TEST_F(AssemblerMIPSTest, LoadNearestFarLiteral) {
mips::Literal* literal = __ NewLiteral<uint32_t>(0x12345678);
__ BindPcRelBaseLabel();
__ LoadLiteral(mips::V0, mips::V1, literal);
constexpr size_t kAdduCount = 0x1FDF;
for (size_t i = 0; i != kAdduCount; ++i) {
__ Addu(mips::ZERO, mips::ZERO, mips::ZERO);
}
std::string expected =
"1:\n"
"lui $at, %hi(2f - 1b)\n"
"addu $at, $at, $v1\n"
"lw $v0, %lo(2f - 1b)($at)\n" +
RepeatInsn(kAdduCount, "addu $zero, $zero, $zero\n") +
"2:\n"
".word 0x12345678\n";
DriverStr(expected, "LoadNearestFarLiteral");
}
TEST_F(AssemblerMIPSTest, LoadFarthestNearLiteralUsingNal) {
mips::Literal* literal = __ NewLiteral<uint32_t>(0x12345678);
__ LoadLiteral(mips::V0, mips::ZERO, literal);
constexpr size_t kAddiuCount = 0x1FDE;
for (size_t i = 0; i != kAddiuCount; ++i) {
__ Addiu(mips::A0, mips::A1, 0);
}
std::string expected =
".set noreorder\n"
"bltzal $zero, .+4\n"
"lw $v0, %lo(2f - 1f)($ra)\n"
"1:\n" +
RepeatInsn(kAddiuCount, "addiu $a0, $a1, %hi(2f - 1b)\n") +
"2:\n"
".word 0x12345678\n";
DriverStr(expected, "LoadFarthestNearLiteralUsingNal");
}
TEST_F(AssemblerMIPSTest, LoadNearestFarLiteralUsingNal) {
mips::Literal* literal = __ NewLiteral<uint32_t>(0x12345678);
__ LoadLiteral(mips::V0, mips::ZERO, literal);
constexpr size_t kAdduCount = 0x1FDF;
for (size_t i = 0; i != kAdduCount; ++i) {
__ Addu(mips::ZERO, mips::ZERO, mips::ZERO);
}
std::string expected =
".set noreorder\n"
"bltzal $zero, .+4\n"
"lui $at, %hi(2f - 1f)\n"
"1:\n"
"addu $at, $at, $ra\n"
"lw $v0, %lo(2f - 1b)($at)\n" +
RepeatInsn(kAdduCount, "addu $zero, $zero, $zero\n") +
"2:\n"
".word 0x12345678\n";
DriverStr(expected, "LoadNearestFarLiteralUsingNal");
}
#undef __
} // namespace art