| /* |
| * 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::Register, |
| mips::FRegister, |
| uint32_t> { |
| public: |
| typedef AssemblerTest<mips::MipsAssembler, mips::Register, mips::FRegister, uint32_t> Base; |
| |
| 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::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 BranchCondOneRegHelper(void (mips::MipsAssembler::*f)(mips::Register, |
| mips::MipsLabel*), |
| std::string instr_name) { |
| mips::MipsLabel label; |
| (Base::GetAssembler()->*f)(mips::A0, &label); |
| 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); |
| |
| std::string expected = |
| ".set noreorder\n" + |
| instr_name + " $a0, 1f\n" |
| "nop\n" + |
| RepeatInsn(kAdduCount1, "addu $zero, $zero, $zero\n") + |
| "1:\n" + |
| RepeatInsn(kAdduCount2, "addu $zero, $zero, $zero\n") + |
| instr_name + " $a1, 1b\n" |
| "nop\n"; |
| DriverStr(expected, instr_name); |
| } |
| |
| void BranchCondTwoRegsHelper(void (mips::MipsAssembler::*f)(mips::Register, |
| mips::Register, |
| mips::MipsLabel*), |
| std::string instr_name) { |
| mips::MipsLabel label; |
| (Base::GetAssembler()->*f)(mips::A0, mips::A1, &label); |
| 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); |
| |
| std::string expected = |
| ".set noreorder\n" + |
| instr_name + " $a0, $a1, 1f\n" |
| "nop\n" + |
| RepeatInsn(kAdduCount1, "addu $zero, $zero, $zero\n") + |
| "1:\n" + |
| RepeatInsn(kAdduCount2, "addu $zero, $zero, $zero\n") + |
| instr_name + " $a2, $a3, 1b\n" |
| "nop\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"); |
| } |
| |
| TEST_F(AssemblerMIPSTest, B) { |
| mips::MipsLabel label1, label2; |
| __ B(&label1); |
| constexpr size_t kAdduCount1 = 63; |
| for (size_t i = 0; i != kAdduCount1; ++i) { |
| __ Addu(mips::ZERO, mips::ZERO, mips::ZERO); |
| } |
| __ Bind(&label1); |
| __ B(&label2); |
| constexpr size_t kAdduCount2 = 64; |
| for (size_t i = 0; i != kAdduCount2; ++i) { |
| __ Addu(mips::ZERO, mips::ZERO, mips::ZERO); |
| } |
| __ Bind(&label2); |
| __ B(&label1); |
| |
| std::string expected = |
| ".set noreorder\n" |
| "b 1f\n" |
| "nop\n" + |
| RepeatInsn(kAdduCount1, "addu $zero, $zero, $zero\n") + |
| "1:\n" |
| "b 2f\n" |
| "nop\n" + |
| RepeatInsn(kAdduCount2, "addu $zero, $zero, $zero\n") + |
| "2:\n" |
| "b 1b\n" |
| "nop\n"; |
| DriverStr(expected, "B"); |
| } |
| |
| TEST_F(AssemblerMIPSTest, Beq) { |
| __ SetReorder(false); |
| BranchCondTwoRegsHelper(&mips::MipsAssembler::Beq, "Beq"); |
| } |
| |
| TEST_F(AssemblerMIPSTest, Bne) { |
| __ SetReorder(false); |
| BranchCondTwoRegsHelper(&mips::MipsAssembler::Bne, "Bne"); |
| } |
| |
| TEST_F(AssemblerMIPSTest, Beqz) { |
| __ SetReorder(false); |
| mips::MipsLabel label; |
| __ Beqz(mips::A0, &label); |
| 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); |
| } |
| __ Beqz(mips::A1, &label); |
| |
| std::string expected = |
| ".set noreorder\n" |
| "beq $zero, $a0, 1f\n" |
| "nop\n" + |
| RepeatInsn(kAdduCount1, "addu $zero, $zero, $zero\n") + |
| "1:\n" + |
| RepeatInsn(kAdduCount2, "addu $zero, $zero, $zero\n") + |
| "beq $zero, $a1, 1b\n" |
| "nop\n"; |
| DriverStr(expected, "Beqz"); |
| } |
| |
| TEST_F(AssemblerMIPSTest, Bnez) { |
| __ SetReorder(false); |
| mips::MipsLabel label; |
| __ Bnez(mips::A0, &label); |
| 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); |
| } |
| __ Bnez(mips::A1, &label); |
| |
| std::string expected = |
| ".set noreorder\n" |
| "bne $zero, $a0, 1f\n" |
| "nop\n" + |
| RepeatInsn(kAdduCount1, "addu $zero, $zero, $zero\n") + |
| "1:\n" + |
| RepeatInsn(kAdduCount2, "addu $zero, $zero, $zero\n") + |
| "bne $zero, $a1, 1b\n" |
| "nop\n"; |
| DriverStr(expected, "Bnez"); |
| } |
| |
| TEST_F(AssemblerMIPSTest, Bltz) { |
| __ SetReorder(false); |
| BranchCondOneRegHelper(&mips::MipsAssembler::Bltz, "Bltz"); |
| } |
| |
| TEST_F(AssemblerMIPSTest, Bgez) { |
| __ SetReorder(false); |
| BranchCondOneRegHelper(&mips::MipsAssembler::Bgez, "Bgez"); |
| } |
| |
| TEST_F(AssemblerMIPSTest, Blez) { |
| __ SetReorder(false); |
| BranchCondOneRegHelper(&mips::MipsAssembler::Blez, "Blez"); |
| } |
| |
| TEST_F(AssemblerMIPSTest, Bgtz) { |
| __ SetReorder(false); |
| BranchCondOneRegHelper(&mips::MipsAssembler::Bgtz, "Bgtz"); |
| } |
| |
| TEST_F(AssemblerMIPSTest, Blt) { |
| __ SetReorder(false); |
| mips::MipsLabel label; |
| __ Blt(mips::A0, mips::A1, &label); |
| 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); |
| } |
| __ Blt(mips::A2, mips::A3, &label); |
| |
| std::string expected = |
| ".set noreorder\n" |
| "slt $at, $a0, $a1\n" |
| "bne $zero, $at, 1f\n" |
| "nop\n" + |
| RepeatInsn(kAdduCount1, "addu $zero, $zero, $zero\n") + |
| "1:\n" + |
| RepeatInsn(kAdduCount2, "addu $zero, $zero, $zero\n") + |
| "slt $at, $a2, $a3\n" |
| "bne $zero, $at, 1b\n" |
| "nop\n"; |
| DriverStr(expected, "Blt"); |
| } |
| |
| TEST_F(AssemblerMIPSTest, Bge) { |
| __ SetReorder(false); |
| mips::MipsLabel label; |
| __ Bge(mips::A0, mips::A1, &label); |
| 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); |
| } |
| __ Bge(mips::A2, mips::A3, &label); |
| |
| std::string expected = |
| ".set noreorder\n" |
| "slt $at, $a0, $a1\n" |
| "beq $zero, $at, 1f\n" |
| "nop\n" + |
| RepeatInsn(kAdduCount1, "addu $zero, $zero, $zero\n") + |
| "1:\n" + |
| RepeatInsn(kAdduCount2, "addu $zero, $zero, $zero\n") + |
| "slt $at, $a2, $a3\n" |
| "beq $zero, $at, 1b\n" |
| "nop\n"; |
| DriverStr(expected, "Bge"); |
| } |
| |
| TEST_F(AssemblerMIPSTest, Bltu) { |
| __ SetReorder(false); |
| mips::MipsLabel label; |
| __ Bltu(mips::A0, mips::A1, &label); |
| 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); |
| } |
| __ Bltu(mips::A2, mips::A3, &label); |
| |
| std::string expected = |
| ".set noreorder\n" |
| "sltu $at, $a0, $a1\n" |
| "bne $zero, $at, 1f\n" |
| "nop\n" + |
| RepeatInsn(kAdduCount1, "addu $zero, $zero, $zero\n") + |
| "1:\n" + |
| RepeatInsn(kAdduCount2, "addu $zero, $zero, $zero\n") + |
| "sltu $at, $a2, $a3\n" |
| "bne $zero, $at, 1b\n" |
| "nop\n"; |
| DriverStr(expected, "Bltu"); |
| } |
| |
| TEST_F(AssemblerMIPSTest, Bgeu) { |
| __ SetReorder(false); |
| mips::MipsLabel label; |
| __ Bgeu(mips::A0, mips::A1, &label); |
| 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); |
| } |
| __ Bgeu(mips::A2, mips::A3, &label); |
| |
| std::string expected = |
| ".set noreorder\n" |
| "sltu $at, $a0, $a1\n" |
| "beq $zero, $at, 1f\n" |
| "nop\n" + |
| RepeatInsn(kAdduCount1, "addu $zero, $zero, $zero\n") + |
| "1:\n" + |
| RepeatInsn(kAdduCount2, "addu $zero, $zero, $zero\n") + |
| "sltu $at, $a2, $a3\n" |
| "beq $zero, $at, 1b\n" |
| "nop\n"; |
| DriverStr(expected, "Bgeu"); |
| } |
| |
| TEST_F(AssemblerMIPSTest, Bc1f) { |
| __ SetReorder(false); |
| mips::MipsLabel label; |
| __ Bc1f(0, &label); |
| 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); |
| } |
| __ Bc1f(7, &label); |
| |
| std::string expected = |
| ".set noreorder\n" |
| "bc1f $fcc0, 1f\n" |
| "nop\n" + |
| RepeatInsn(kAdduCount1, "addu $zero, $zero, $zero\n") + |
| "1:\n" + |
| RepeatInsn(kAdduCount2, "addu $zero, $zero, $zero\n") + |
| "bc1f $fcc7, 1b\n" |
| "nop\n"; |
| DriverStr(expected, "Bc1f"); |
| } |
| |
| TEST_F(AssemblerMIPSTest, Bc1t) { |
| __ SetReorder(false); |
| mips::MipsLabel label; |
| __ Bc1t(0, &label); |
| 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); |
| } |
| __ Bc1t(7, &label); |
| |
| std::string expected = |
| ".set noreorder\n" |
| "bc1t $fcc0, 1f\n" |
| "nop\n" + |
| RepeatInsn(kAdduCount1, "addu $zero, $zero, $zero\n") + |
| "1:\n" + |
| RepeatInsn(kAdduCount2, "addu $zero, $zero, $zero\n") + |
| "bc1t $fcc7, 1b\n" |
| "nop\n"; |
| DriverStr(expected, "Bc1t"); |
| } |
| |
| /////////////////////// |
| // 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, 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, 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" |
| "beq $zero, $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" |
| "bne $zero, $at, 1b\n" |
| "nop\n" |
| |
| "xor $at, $t0, $t1\n" |
| "slt $at, $t1, $t0\n" |
| "beq $zero, $at, 1b\n" |
| "nop\n" |
| |
| "subu $t0, $t1, $at\n" |
| "sltu $at, $t1, $t0\n" |
| "bne $zero, $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" |
| |
| "bne $zero, $t0, 2b\n" |
| "nop\n" |
| |
| "sltu $at, $t1, $t0\n" |
| "beq $zero, $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" |
| |
| "beq $zero, $t1, 1b\n" |
| "addu $t0, $t1, $t2\n" |
| |
| "bne $t2, $t3, 1b\n" |
| "or $t1, $t2, $t3\n" |
| |
| "slt $at, $t1, $t2\n" |
| "bne $zero, $at, 1b\n" |
| "and $t0, $t1, $t2\n" |
| |
| "slt $at, $t1, $t0\n" |
| "beq $zero, $at, 1b\n" |
| "xor $t2, $t0, $t1\n" |
| |
| "sltu $at, $t1, $t0\n" |
| "bne $zero, $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; |
| __ 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. |
| |
| 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"; |
| 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, LongBranchReorder) { |
| mips::MipsLabel label; |
| __ SetReorder(true); |
| __ Subu(mips::T0, mips::T1, mips::T2); |
| __ 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); |
| } |
| __ Subu(mips::T0, mips::T1, mips::T2); |
| __ 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 = -(kAdduCount1 + 5) * sizeof(uint32_t); |
| |
| std::ostringstream oss; |
| oss << |
| ".set noreorder\n" |
| "subu $t0, $t1, $t2\n" |
| "addiu $sp, $sp, -4\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, 4\n" << |
| RepeatInsn(kAdduCount1, "addu $zero, $zero, $zero\n") << |
| RepeatInsn(kAdduCount2, "addu $zero, $zero, $zero\n") << |
| "subu $t0, $t1, $t2\n" |
| "addiu $sp, $sp, -4\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, 4\n"; |
| std::string expected = oss.str(); |
| DriverStr(expected, "LongBranchReorder"); |
| } |
| |
| #undef __ |
| |
| } // namespace art |