diff options
| author | 2017-07-06 11:55:24 +0200 | |
|---|---|---|
| committer | 2017-07-06 14:04:01 +0200 | |
| commit | 2e0a7e5047fde08ddd220aaa1a0e64d44ecbb420 (patch) | |
| tree | 7c541176dc1b44cc927272f9b38fab4ce7ac9e85 | |
| parent | 209b4c7141d7da61790844cd58bd0a9bab2951d8 (diff) | |
MIPS32: Adds changes neccessary for saving 128 bits of data
Test: mma test-art-host-gtest
Test: ./testrunner.py --optimizing --target in QEMU (MIPS)
Change-Id: I90b7baa1d5f910887bcc3ab80a1a48391ba80c45
| -rw-r--r-- | compiler/Android.bp | 1 | ||||
| -rw-r--r-- | compiler/utils/mips/assembler_mips.cc | 108 | ||||
| -rw-r--r-- | compiler/utils/mips/assembler_mips.h | 47 | ||||
| -rw-r--r-- | compiler/utils/mips/assembler_mips32r5_test.cc | 541 | ||||
| -rw-r--r-- | compiler/utils/mips/assembler_mips32r6_test.cc | 236 |
5 files changed, 931 insertions, 2 deletions
diff --git a/compiler/Android.bp b/compiler/Android.bp index a1269dcaf9..05c4553251 100644 --- a/compiler/Android.bp +++ b/compiler/Android.bp @@ -455,6 +455,7 @@ art_cc_test { srcs: [ "optimizing/emit_swap_mips_test.cc", "utils/mips/assembler_mips_test.cc", + "utils/mips/assembler_mips32r5_test.cc", "utils/mips/assembler_mips32r6_test.cc", ], }, diff --git a/compiler/utils/mips/assembler_mips.cc b/compiler/utils/mips/assembler_mips.cc index 0b05b752da..44b9bb4eb9 100644 --- a/compiler/utils/mips/assembler_mips.cc +++ b/compiler/utils/mips/assembler_mips.cc @@ -4440,6 +4440,106 @@ void MipsAssembler::AdjustBaseAndOffset(Register& base, CHECK_EQ(misalignment, offset & (kMipsDoublewordSize - 1)); } +void MipsAssembler::AdjustBaseOffsetAndElementSizeShift(Register& base, + int32_t& offset, + int& element_size_shift) { + // This method is used to adjust the base register, offset and element_size_shift + // for a vector load/store when the offset doesn't fit into allowed number of bits. + // MSA ld.df and st.df instructions take signed offsets as arguments, but maximum + // offset is dependant on the size of the data format df (10-bit offsets for ld.b, + // 11-bit for ld.h, 12-bit for ld.w and 13-bit for ld.d). + // If element_size_shift is non-negative at entry, it won't be changed, but offset + // will be checked for appropriate alignment. If negative at entry, it will be + // adjusted based on offset for maximum fit. + // It's assumed that `base` is a multiple of 8. + CHECK_NE(base, AT); // Must not overwrite the register `base` while loading `offset`. + + if (element_size_shift >= 0) { + CHECK_LE(element_size_shift, TIMES_8); + CHECK_GE(JAVASTYLE_CTZ(offset), element_size_shift); + } else if (IsAligned<kMipsDoublewordSize>(offset)) { + element_size_shift = TIMES_8; + } else if (IsAligned<kMipsWordSize>(offset)) { + element_size_shift = TIMES_4; + } else if (IsAligned<kMipsHalfwordSize>(offset)) { + element_size_shift = TIMES_2; + } else { + element_size_shift = TIMES_1; + } + + const int low_len = 10 + element_size_shift; // How many low bits of `offset` ld.df/st.df + // will take. + int16_t low = offset & ((1 << low_len) - 1); // Isolate these bits. + low -= (low & (1 << (low_len - 1))) << 1; // Sign-extend these bits. + if (low == offset) { + return; // `offset` fits into ld.df/st.df. + } + + // First, see if `offset` can be represented as a sum of two or three signed offsets. + // This can save an instruction or two. + + // Max int16_t that's a multiple of element size. + const int32_t kMaxDeltaForSimpleAdjustment = 0x8000 - (1 << element_size_shift); + // Max ld.df/st.df offset that's a multiple of element size. + const int32_t kMaxLoadStoreOffset = 0x1ff << element_size_shift; + const int32_t kMaxOffsetForSimpleAdjustment = kMaxDeltaForSimpleAdjustment + kMaxLoadStoreOffset; + const int32_t kMinOffsetForMediumAdjustment = 2 * kMaxDeltaForSimpleAdjustment; + const int32_t kMaxOffsetForMediumAdjustment = kMinOffsetForMediumAdjustment + kMaxLoadStoreOffset; + + if (IsInt<16>(offset)) { + Addiu(AT, base, offset); + offset = 0; + } else if (0 <= offset && offset <= kMaxOffsetForSimpleAdjustment) { + Addiu(AT, base, kMaxDeltaForSimpleAdjustment); + offset -= kMaxDeltaForSimpleAdjustment; + } else if (-kMaxOffsetForSimpleAdjustment <= offset && offset < 0) { + Addiu(AT, base, -kMaxDeltaForSimpleAdjustment); + offset += kMaxDeltaForSimpleAdjustment; + } else if (!IsR6() && 0 <= offset && offset <= kMaxOffsetForMediumAdjustment) { + Addiu(AT, base, kMaxDeltaForSimpleAdjustment); + if (offset <= kMinOffsetForMediumAdjustment) { + Addiu(AT, AT, offset - kMaxDeltaForSimpleAdjustment); + offset = 0; + } else { + Addiu(AT, AT, kMaxDeltaForSimpleAdjustment); + offset -= kMinOffsetForMediumAdjustment; + } + } else if (!IsR6() && -kMaxOffsetForMediumAdjustment <= offset && offset < 0) { + Addiu(AT, base, -kMaxDeltaForSimpleAdjustment); + if (-kMinOffsetForMediumAdjustment <= offset) { + Addiu(AT, AT, offset + kMaxDeltaForSimpleAdjustment); + offset = 0; + } else { + Addiu(AT, AT, -kMaxDeltaForSimpleAdjustment); + offset += kMinOffsetForMediumAdjustment; + } + } else { + // 16-bit or smaller parts of `offset`: + // |31 hi 16|15 mid 13-10|12-9 low 0| + // + // Instructions that supply each part as a signed integer addend: + // |aui |addiu |ld.df/st.df | + uint32_t tmp = static_cast<uint32_t>(offset) - low; // Exclude `low` from the rest of `offset` + // (accounts for sign of `low`). + tmp += (tmp & (UINT32_C(1) << 15)) << 1; // Account for sign extension in addiu. + int16_t mid = Low16Bits(tmp); + int16_t hi = High16Bits(tmp); + if (IsR6()) { + Aui(AT, base, hi); + } else { + Lui(AT, hi); + Addu(AT, AT, base); + } + if (mid != 0) { + Addiu(AT, AT, mid); + } + offset = low; + } + base = AT; + CHECK_GE(JAVASTYLE_CTZ(offset), element_size_shift); + CHECK(IsInt<10>(offset >> element_size_shift)); +} + void MipsAssembler::LoadFromOffset(LoadOperandType type, Register reg, Register base, @@ -4455,6 +4555,10 @@ void MipsAssembler::LoadDFromOffset(FRegister reg, Register base, int32_t offset LoadDFromOffset<>(reg, base, offset); } +void MipsAssembler::LoadQFromOffset(FRegister reg, Register base, int32_t offset) { + LoadQFromOffset<>(reg, base, offset); +} + void MipsAssembler::EmitLoad(ManagedRegister m_dst, Register src_register, int32_t src_offset, size_t size) { MipsManagedRegister dst = m_dst.AsMips(); @@ -4494,6 +4598,10 @@ void MipsAssembler::StoreDToOffset(FRegister reg, Register base, int32_t offset) StoreDToOffset<>(reg, base, offset); } +void MipsAssembler::StoreQToOffset(FRegister reg, Register base, int32_t offset) { + StoreQToOffset<>(reg, base, offset); +} + static dwarf::Reg DWARFReg(Register reg) { return dwarf::Reg::MipsCore(static_cast<int>(reg)); } diff --git a/compiler/utils/mips/assembler_mips.h b/compiler/utils/mips/assembler_mips.h index dd4ce6dc80..a229882d18 100644 --- a/compiler/utils/mips/assembler_mips.h +++ b/compiler/utils/mips/assembler_mips.h @@ -47,14 +47,16 @@ enum LoadOperandType { kLoadSignedHalfword, kLoadUnsignedHalfword, kLoadWord, - kLoadDoubleword + kLoadDoubleword, + kLoadQuadword }; enum StoreOperandType { kStoreByte, kStoreHalfword, kStoreWord, - kStoreDoubleword + kStoreDoubleword, + kStoreQuadword }; // Used to test the values returned by ClassS/ClassD. @@ -646,6 +648,9 @@ class MipsAssembler FINAL : public Assembler, public JNIMacroAssembler<PointerSi int32_t& offset, bool is_doubleword, bool is_float = false); + void AdjustBaseOffsetAndElementSizeShift(Register& base, + int32_t& offset, + int& element_size_shift); private: // This will be used as an argument for loads/stores @@ -793,6 +798,24 @@ class MipsAssembler FINAL : public Assembler, public JNIMacroAssembler<PointerSi } template <typename ImplicitNullChecker = NoImplicitNullChecker> + void LoadQFromOffset(FRegister reg, + Register base, + int32_t offset, + ImplicitNullChecker null_checker = NoImplicitNullChecker()) { + int element_size_shift = -1; + AdjustBaseOffsetAndElementSizeShift(base, offset, element_size_shift); + switch (element_size_shift) { + case TIMES_1: LdB(static_cast<VectorRegister>(reg), base, offset); break; + case TIMES_2: LdH(static_cast<VectorRegister>(reg), base, offset); break; + case TIMES_4: LdW(static_cast<VectorRegister>(reg), base, offset); break; + case TIMES_8: LdD(static_cast<VectorRegister>(reg), base, offset); break; + default: + LOG(FATAL) << "UNREACHABLE"; + } + null_checker(); + } + + template <typename ImplicitNullChecker = NoImplicitNullChecker> void StoreToOffset(StoreOperandType type, Register reg, Register base, @@ -861,12 +884,32 @@ class MipsAssembler FINAL : public Assembler, public JNIMacroAssembler<PointerSi } } + template <typename ImplicitNullChecker = NoImplicitNullChecker> + void StoreQToOffset(FRegister reg, + Register base, + int32_t offset, + ImplicitNullChecker null_checker = NoImplicitNullChecker()) { + int element_size_shift = -1; + AdjustBaseOffsetAndElementSizeShift(base, offset, element_size_shift); + switch (element_size_shift) { + case TIMES_1: StB(static_cast<VectorRegister>(reg), base, offset); break; + case TIMES_2: StH(static_cast<VectorRegister>(reg), base, offset); break; + case TIMES_4: StW(static_cast<VectorRegister>(reg), base, offset); break; + case TIMES_8: StD(static_cast<VectorRegister>(reg), base, offset); break; + default: + LOG(FATAL) << "UNREACHABLE"; + } + null_checker(); + } + void LoadFromOffset(LoadOperandType type, Register reg, Register base, int32_t offset); void LoadSFromOffset(FRegister reg, Register base, int32_t offset); void LoadDFromOffset(FRegister reg, Register base, int32_t offset); + void LoadQFromOffset(FRegister reg, Register base, int32_t offset); void StoreToOffset(StoreOperandType type, Register reg, Register base, int32_t offset); void StoreSToOffset(FRegister reg, Register base, int32_t offset); void StoreDToOffset(FRegister reg, Register base, int32_t offset); + void StoreQToOffset(FRegister reg, Register base, int32_t offset); // Emit data (e.g. encoded instruction or immediate) to the instruction stream. void Emit(uint32_t value); diff --git a/compiler/utils/mips/assembler_mips32r5_test.cc b/compiler/utils/mips/assembler_mips32r5_test.cc new file mode 100644 index 0000000000..24b09b5524 --- /dev/null +++ b/compiler/utils/mips/assembler_mips32r5_test.cc @@ -0,0 +1,541 @@ +/* + * Copyright (C) 2017 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 AssemblerMIPS32r5Test : public AssemblerTest<mips::MipsAssembler, + mips::Register, + mips::FRegister, + uint32_t, + mips::VectorRegister> { + public: + typedef AssemblerTest<mips::MipsAssembler, + mips::Register, + mips::FRegister, + uint32_t, + mips::VectorRegister> Base; + + AssemblerMIPS32r5Test() : + instruction_set_features_(MipsInstructionSetFeatures::FromVariant("mips32r5", nullptr)) { + } + + 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=mips32r5 -mmsa"; + } + + void Pad(std::vector<uint8_t>& data) OVERRIDE { + // The GNU linker unconditionally pads the code segment with NOPs to a size that is a multiple + // of 16 and there doesn't appear to be a way to suppress this padding. Our assembler doesn't + // pad, so, in order for two assembler outputs to match, we need to match the padding as well. + // NOP is encoded as four zero bytes on MIPS. + size_t pad_size = RoundUp(data.size(), 16u) - data.size(); + data.insert(data.end(), pad_size, 0); + } + + std::string GetDisassembleParameters() OVERRIDE { + return " -D -bbinary -mmips:isa32r5"; + } + + mips::MipsAssembler* CreateAssembler(ArenaAllocator* arena) OVERRIDE { + return new (arena) mips::MipsAssembler(arena, instruction_set_features_.get()); + } + + 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)); + + vec_registers_.push_back(new mips::VectorRegister(mips::W0)); + vec_registers_.push_back(new mips::VectorRegister(mips::W1)); + vec_registers_.push_back(new mips::VectorRegister(mips::W2)); + vec_registers_.push_back(new mips::VectorRegister(mips::W3)); + vec_registers_.push_back(new mips::VectorRegister(mips::W4)); + vec_registers_.push_back(new mips::VectorRegister(mips::W5)); + vec_registers_.push_back(new mips::VectorRegister(mips::W6)); + vec_registers_.push_back(new mips::VectorRegister(mips::W7)); + vec_registers_.push_back(new mips::VectorRegister(mips::W8)); + vec_registers_.push_back(new mips::VectorRegister(mips::W9)); + vec_registers_.push_back(new mips::VectorRegister(mips::W10)); + vec_registers_.push_back(new mips::VectorRegister(mips::W11)); + vec_registers_.push_back(new mips::VectorRegister(mips::W12)); + vec_registers_.push_back(new mips::VectorRegister(mips::W13)); + vec_registers_.push_back(new mips::VectorRegister(mips::W14)); + vec_registers_.push_back(new mips::VectorRegister(mips::W15)); + vec_registers_.push_back(new mips::VectorRegister(mips::W16)); + vec_registers_.push_back(new mips::VectorRegister(mips::W17)); + vec_registers_.push_back(new mips::VectorRegister(mips::W18)); + vec_registers_.push_back(new mips::VectorRegister(mips::W19)); + vec_registers_.push_back(new mips::VectorRegister(mips::W20)); + vec_registers_.push_back(new mips::VectorRegister(mips::W21)); + vec_registers_.push_back(new mips::VectorRegister(mips::W22)); + vec_registers_.push_back(new mips::VectorRegister(mips::W23)); + vec_registers_.push_back(new mips::VectorRegister(mips::W24)); + vec_registers_.push_back(new mips::VectorRegister(mips::W25)); + vec_registers_.push_back(new mips::VectorRegister(mips::W26)); + vec_registers_.push_back(new mips::VectorRegister(mips::W27)); + vec_registers_.push_back(new mips::VectorRegister(mips::W28)); + vec_registers_.push_back(new mips::VectorRegister(mips::W29)); + vec_registers_.push_back(new mips::VectorRegister(mips::W30)); + vec_registers_.push_back(new mips::VectorRegister(mips::W31)); + } + } + + void TearDown() OVERRIDE { + AssemblerTest::TearDown(); + STLDeleteElements(®isters_); + STLDeleteElements(&fp_registers_); + STLDeleteElements(&vec_registers_); + } + + std::vector<mips::Register*> GetRegisters() OVERRIDE { + return registers_; + } + + std::vector<mips::FRegister*> GetFPRegisters() OVERRIDE { + return fp_registers_; + } + + std::vector<mips::VectorRegister*> GetVectorRegisters() OVERRIDE { + return vec_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; + } + + private: + std::vector<mips::Register*> registers_; + std::map<mips::Register, std::string, MIPSCpuRegisterCompare> secondary_register_names_; + + std::vector<mips::FRegister*> fp_registers_; + std::vector<mips::VectorRegister*> vec_registers_; + std::unique_ptr<const MipsInstructionSetFeatures> instruction_set_features_; +}; + +TEST_F(AssemblerMIPS32r5Test, Toolchain) { + EXPECT_TRUE(CheckTools()); +} + +TEST_F(AssemblerMIPS32r5Test, LoadQFromOffset) { + __ LoadQFromOffset(mips::F0, mips::A0, 0); + __ LoadQFromOffset(mips::F0, mips::A0, 1); + __ LoadQFromOffset(mips::F0, mips::A0, 2); + __ LoadQFromOffset(mips::F0, mips::A0, 4); + __ LoadQFromOffset(mips::F0, mips::A0, 8); + __ LoadQFromOffset(mips::F0, mips::A0, 511); + __ LoadQFromOffset(mips::F0, mips::A0, 512); + __ LoadQFromOffset(mips::F0, mips::A0, 513); + __ LoadQFromOffset(mips::F0, mips::A0, 514); + __ LoadQFromOffset(mips::F0, mips::A0, 516); + __ LoadQFromOffset(mips::F0, mips::A0, 1022); + __ LoadQFromOffset(mips::F0, mips::A0, 1024); + __ LoadQFromOffset(mips::F0, mips::A0, 1025); + __ LoadQFromOffset(mips::F0, mips::A0, 1026); + __ LoadQFromOffset(mips::F0, mips::A0, 1028); + __ LoadQFromOffset(mips::F0, mips::A0, 2044); + __ LoadQFromOffset(mips::F0, mips::A0, 2048); + __ LoadQFromOffset(mips::F0, mips::A0, 2049); + __ LoadQFromOffset(mips::F0, mips::A0, 2050); + __ LoadQFromOffset(mips::F0, mips::A0, 2052); + __ LoadQFromOffset(mips::F0, mips::A0, 4088); + __ LoadQFromOffset(mips::F0, mips::A0, 4096); + __ LoadQFromOffset(mips::F0, mips::A0, 4097); + __ LoadQFromOffset(mips::F0, mips::A0, 4098); + __ LoadQFromOffset(mips::F0, mips::A0, 4100); + __ LoadQFromOffset(mips::F0, mips::A0, 4104); + __ LoadQFromOffset(mips::F0, mips::A0, 0x7FFC); + __ LoadQFromOffset(mips::F0, mips::A0, 0x8000); + __ LoadQFromOffset(mips::F0, mips::A0, 0x10000); + __ LoadQFromOffset(mips::F0, mips::A0, 0x12345678); + __ LoadQFromOffset(mips::F0, mips::A0, 0x12350078); + __ LoadQFromOffset(mips::F0, mips::A0, -256); + __ LoadQFromOffset(mips::F0, mips::A0, -511); + __ LoadQFromOffset(mips::F0, mips::A0, -513); + __ LoadQFromOffset(mips::F0, mips::A0, -1022); + __ LoadQFromOffset(mips::F0, mips::A0, -1026); + __ LoadQFromOffset(mips::F0, mips::A0, -2044); + __ LoadQFromOffset(mips::F0, mips::A0, -2052); + __ LoadQFromOffset(mips::F0, mips::A0, -4096); + __ LoadQFromOffset(mips::F0, mips::A0, -4104); + __ LoadQFromOffset(mips::F0, mips::A0, -32768); + __ LoadQFromOffset(mips::F0, mips::A0, -36856); + __ LoadQFromOffset(mips::F0, mips::A0, 36856); + __ LoadQFromOffset(mips::F0, mips::A0, -69608); + __ LoadQFromOffset(mips::F0, mips::A0, 69608); + __ LoadQFromOffset(mips::F0, mips::A0, 0xABCDEF00); + __ LoadQFromOffset(mips::F0, mips::A0, 0x7FFFABCD); + + const char* expected = + "ld.d $w0, 0($a0)\n" + "ld.b $w0, 1($a0)\n" + "ld.h $w0, 2($a0)\n" + "ld.w $w0, 4($a0)\n" + "ld.d $w0, 8($a0)\n" + "ld.b $w0, 511($a0)\n" + "ld.d $w0, 512($a0)\n" + "addiu $at, $a0, 513\n" + "ld.b $w0, 0($at)\n" + "ld.h $w0, 514($a0)\n" + "ld.w $w0, 516($a0)\n" + "ld.h $w0, 1022($a0)\n" + "ld.d $w0, 1024($a0)\n" + "addiu $at, $a0, 1025\n" + "ld.b $w0, 0($at)\n" + "addiu $at, $a0, 1026\n" + "ld.h $w0, 0($at)\n" + "ld.w $w0, 1028($a0)\n" + "ld.w $w0, 2044($a0)\n" + "ld.d $w0, 2048($a0)\n" + "addiu $at, $a0, 2049\n" + "ld.b $w0, 0($at)\n" + "addiu $at, $a0, 2050\n" + "ld.h $w0, 0($at)\n" + "addiu $at, $a0, 2052\n" + "ld.w $w0, 0($at)\n" + "ld.d $w0, 4088($a0)\n" + "addiu $at, $a0, 4096\n" + "ld.d $w0, 0($at)\n" + "addiu $at, $a0, 4097\n" + "ld.b $w0, 0($at)\n" + "addiu $at, $a0, 4098\n" + "ld.h $w0, 0($at)\n" + "addiu $at, $a0, 4100\n" + "ld.w $w0, 0($at)\n" + "addiu $at, $a0, 4104\n" + "ld.d $w0, 0($at)\n" + "addiu $at, $a0, 0x7FFC\n" + "ld.w $w0, 0($at)\n" + "addiu $at, $a0, 0x7FF8\n" + "ld.d $w0, 8($at)\n" + "addiu $at, $a0, 32760\n" + "addiu $at, $at, 32760\n" + "ld.d $w0, 16($at)\n" + "lui $at, 4660\n" + "addu $at, $at, $a0\n" + "addiu $at, $at, 24576\n" + "ld.d $w0, -2440($at) # 0xF678\n" + "lui $at, 4661\n" + "addu $at, $at, $a0\n" + "ld.d $w0, 120($at)\n" + "ld.d $w0, -256($a0)\n" + "ld.b $w0, -511($a0)\n" + "addiu $at, $a0, -513\n" + "ld.b $w0, 0($at)\n" + "ld.h $w0, -1022($a0)\n" + "addiu $at, $a0, -1026\n" + "ld.h $w0, 0($at)\n" + "ld.w $w0, -2044($a0)\n" + "addiu $at, $a0, -2052\n" + "ld.w $w0, 0($at)\n" + "ld.d $w0, -4096($a0)\n" + "addiu $at, $a0, -4104\n" + "ld.d $w0, 0($at)\n" + "addiu $at, $a0, -32768\n" + "ld.d $w0, 0($at)\n" + "addiu $at, $a0, -32760\n" + "addiu $at, $at, -4096\n" + "ld.d $w0, 0($at)\n" + "addiu $at, $a0, 32760\n" + "addiu $at, $at, 4096\n" + "ld.d $w0, 0($at)\n" + "addiu $at, $a0, -32760\n" + "addiu $at, $at, -32760\n" + "ld.d $w0, -4088($at)\n" + "addiu $at, $a0, 32760\n" + "addiu $at, $at, 32760\n" + "ld.d $w0, 4088($at)\n" + "lui $at, 0xABCE\n" + "addu $at, $at, $a0\n" + "addiu $at, $at, -8192 # 0xE000\n" + "ld.d $w0, 0xF00($at)\n" + "lui $at, 0x8000\n" + "addu $at, $at, $a0\n" + "addiu $at, $at, -21504 # 0xAC00\n" + "ld.b $w0, -51($at) # 0xFFCD\n"; + DriverStr(expected, "LoadQFromOffset"); +} + +TEST_F(AssemblerMIPS32r5Test, StoreQToOffset) { + __ StoreQToOffset(mips::F0, mips::A0, 0); + __ StoreQToOffset(mips::F0, mips::A0, 1); + __ StoreQToOffset(mips::F0, mips::A0, 2); + __ StoreQToOffset(mips::F0, mips::A0, 4); + __ StoreQToOffset(mips::F0, mips::A0, 8); + __ StoreQToOffset(mips::F0, mips::A0, 511); + __ StoreQToOffset(mips::F0, mips::A0, 512); + __ StoreQToOffset(mips::F0, mips::A0, 513); + __ StoreQToOffset(mips::F0, mips::A0, 514); + __ StoreQToOffset(mips::F0, mips::A0, 516); + __ StoreQToOffset(mips::F0, mips::A0, 1022); + __ StoreQToOffset(mips::F0, mips::A0, 1024); + __ StoreQToOffset(mips::F0, mips::A0, 1025); + __ StoreQToOffset(mips::F0, mips::A0, 1026); + __ StoreQToOffset(mips::F0, mips::A0, 1028); + __ StoreQToOffset(mips::F0, mips::A0, 2044); + __ StoreQToOffset(mips::F0, mips::A0, 2048); + __ StoreQToOffset(mips::F0, mips::A0, 2049); + __ StoreQToOffset(mips::F0, mips::A0, 2050); + __ StoreQToOffset(mips::F0, mips::A0, 2052); + __ StoreQToOffset(mips::F0, mips::A0, 4088); + __ StoreQToOffset(mips::F0, mips::A0, 4096); + __ StoreQToOffset(mips::F0, mips::A0, 4097); + __ StoreQToOffset(mips::F0, mips::A0, 4098); + __ StoreQToOffset(mips::F0, mips::A0, 4100); + __ StoreQToOffset(mips::F0, mips::A0, 4104); + __ StoreQToOffset(mips::F0, mips::A0, 0x7FFC); + __ StoreQToOffset(mips::F0, mips::A0, 0x8000); + __ StoreQToOffset(mips::F0, mips::A0, 0x10000); + __ StoreQToOffset(mips::F0, mips::A0, 0x12345678); + __ StoreQToOffset(mips::F0, mips::A0, 0x12350078); + __ StoreQToOffset(mips::F0, mips::A0, -256); + __ StoreQToOffset(mips::F0, mips::A0, -511); + __ StoreQToOffset(mips::F0, mips::A0, -513); + __ StoreQToOffset(mips::F0, mips::A0, -1022); + __ StoreQToOffset(mips::F0, mips::A0, -1026); + __ StoreQToOffset(mips::F0, mips::A0, -2044); + __ StoreQToOffset(mips::F0, mips::A0, -2052); + __ StoreQToOffset(mips::F0, mips::A0, -4096); + __ StoreQToOffset(mips::F0, mips::A0, -4104); + __ StoreQToOffset(mips::F0, mips::A0, -32768); + __ StoreQToOffset(mips::F0, mips::A0, -36856); + __ StoreQToOffset(mips::F0, mips::A0, 36856); + __ StoreQToOffset(mips::F0, mips::A0, -69608); + __ StoreQToOffset(mips::F0, mips::A0, 69608); + __ StoreQToOffset(mips::F0, mips::A0, 0xABCDEF00); + __ StoreQToOffset(mips::F0, mips::A0, 0x7FFFABCD); + + const char* expected = + "st.d $w0, 0($a0)\n" + "st.b $w0, 1($a0)\n" + "st.h $w0, 2($a0)\n" + "st.w $w0, 4($a0)\n" + "st.d $w0, 8($a0)\n" + "st.b $w0, 511($a0)\n" + "st.d $w0, 512($a0)\n" + "addiu $at, $a0, 513\n" + "st.b $w0, 0($at)\n" + "st.h $w0, 514($a0)\n" + "st.w $w0, 516($a0)\n" + "st.h $w0, 1022($a0)\n" + "st.d $w0, 1024($a0)\n" + "addiu $at, $a0, 1025\n" + "st.b $w0, 0($at)\n" + "addiu $at, $a0, 1026\n" + "st.h $w0, 0($at)\n" + "st.w $w0, 1028($a0)\n" + "st.w $w0, 2044($a0)\n" + "st.d $w0, 2048($a0)\n" + "addiu $at, $a0, 2049\n" + "st.b $w0, 0($at)\n" + "addiu $at, $a0, 2050\n" + "st.h $w0, 0($at)\n" + "addiu $at, $a0, 2052\n" + "st.w $w0, 0($at)\n" + "st.d $w0, 4088($a0)\n" + "addiu $at, $a0, 4096\n" + "st.d $w0, 0($at)\n" + "addiu $at, $a0, 4097\n" + "st.b $w0, 0($at)\n" + "addiu $at, $a0, 4098\n" + "st.h $w0, 0($at)\n" + "addiu $at, $a0, 4100\n" + "st.w $w0, 0($at)\n" + "addiu $at, $a0, 4104\n" + "st.d $w0, 0($at)\n" + "addiu $at, $a0, 0x7FFC\n" + "st.w $w0, 0($at)\n" + "addiu $at, $a0, 0x7FF8\n" + "st.d $w0, 8($at)\n" + "addiu $at, $a0, 32760\n" + "addiu $at, $at, 32760\n" + "st.d $w0, 16($at)\n" + "lui $at, 4660\n" + "addu $at, $at, $a0\n" + "addiu $at, $at, 24576\n" + "st.d $w0, -2440($at) # 0xF678\n" + "lui $at, 4661\n" + "addu $at, $at, $a0\n" + "st.d $w0, 120($at)\n" + "st.d $w0, -256($a0)\n" + "st.b $w0, -511($a0)\n" + "addiu $at, $a0, -513\n" + "st.b $w0, 0($at)\n" + "st.h $w0, -1022($a0)\n" + "addiu $at, $a0, -1026\n" + "st.h $w0, 0($at)\n" + "st.w $w0, -2044($a0)\n" + "addiu $at, $a0, -2052\n" + "st.w $w0, 0($at)\n" + "st.d $w0, -4096($a0)\n" + "addiu $at, $a0, -4104\n" + "st.d $w0, 0($at)\n" + "addiu $at, $a0, -32768\n" + "st.d $w0, 0($at)\n" + "addiu $at, $a0, -32760\n" + "addiu $at, $at, -4096\n" + "st.d $w0, 0($at)\n" + "addiu $at, $a0, 32760\n" + "addiu $at, $at, 4096\n" + "st.d $w0, 0($at)\n" + "addiu $at, $a0, -32760\n" + "addiu $at, $at, -32760\n" + "st.d $w0, -4088($at)\n" + "addiu $at, $a0, 32760\n" + "addiu $at, $at, 32760\n" + "st.d $w0, 4088($at)\n" + "lui $at, 0xABCE\n" + "addu $at, $at, $a0\n" + "addiu $at, $at, -8192 # 0xE000\n" + "st.d $w0, 0xF00($at)\n" + "lui $at, 0x8000\n" + "addu $at, $at, $a0\n" + "addiu $at, $at, -21504 # 0xAC00\n" + "st.b $w0, -51($at) # 0xFFCD\n"; + DriverStr(expected, "StoreQToOffset"); +} + +#undef __ +} // namespace art diff --git a/compiler/utils/mips/assembler_mips32r6_test.cc b/compiler/utils/mips/assembler_mips32r6_test.cc index d4642607ad..6ee2a5cb79 100644 --- a/compiler/utils/mips/assembler_mips32r6_test.cc +++ b/compiler/utils/mips/assembler_mips32r6_test.cc @@ -627,6 +627,124 @@ TEST_F(AssemblerMIPS32r6Test, LoadDFromOffset) { DriverStr(expected, "LoadDFromOffset"); } +TEST_F(AssemblerMIPS32r6Test, LoadQFromOffset) { + __ LoadQFromOffset(mips::F0, mips::A0, 0); + __ LoadQFromOffset(mips::F0, mips::A0, 1); + __ LoadQFromOffset(mips::F0, mips::A0, 2); + __ LoadQFromOffset(mips::F0, mips::A0, 4); + __ LoadQFromOffset(mips::F0, mips::A0, 8); + __ LoadQFromOffset(mips::F0, mips::A0, 511); + __ LoadQFromOffset(mips::F0, mips::A0, 512); + __ LoadQFromOffset(mips::F0, mips::A0, 513); + __ LoadQFromOffset(mips::F0, mips::A0, 514); + __ LoadQFromOffset(mips::F0, mips::A0, 516); + __ LoadQFromOffset(mips::F0, mips::A0, 1022); + __ LoadQFromOffset(mips::F0, mips::A0, 1024); + __ LoadQFromOffset(mips::F0, mips::A0, 1025); + __ LoadQFromOffset(mips::F0, mips::A0, 1026); + __ LoadQFromOffset(mips::F0, mips::A0, 1028); + __ LoadQFromOffset(mips::F0, mips::A0, 2044); + __ LoadQFromOffset(mips::F0, mips::A0, 2048); + __ LoadQFromOffset(mips::F0, mips::A0, 2049); + __ LoadQFromOffset(mips::F0, mips::A0, 2050); + __ LoadQFromOffset(mips::F0, mips::A0, 2052); + __ LoadQFromOffset(mips::F0, mips::A0, 4088); + __ LoadQFromOffset(mips::F0, mips::A0, 4096); + __ LoadQFromOffset(mips::F0, mips::A0, 4097); + __ LoadQFromOffset(mips::F0, mips::A0, 4098); + __ LoadQFromOffset(mips::F0, mips::A0, 4100); + __ LoadQFromOffset(mips::F0, mips::A0, 4104); + __ LoadQFromOffset(mips::F0, mips::A0, 0x7FFC); + __ LoadQFromOffset(mips::F0, mips::A0, 0x8000); + __ LoadQFromOffset(mips::F0, mips::A0, 0x10000); + __ LoadQFromOffset(mips::F0, mips::A0, 0x12345678); + __ LoadQFromOffset(mips::F0, mips::A0, 0x12350078); + __ LoadQFromOffset(mips::F0, mips::A0, -256); + __ LoadQFromOffset(mips::F0, mips::A0, -511); + __ LoadQFromOffset(mips::F0, mips::A0, -513); + __ LoadQFromOffset(mips::F0, mips::A0, -1022); + __ LoadQFromOffset(mips::F0, mips::A0, -1026); + __ LoadQFromOffset(mips::F0, mips::A0, -2044); + __ LoadQFromOffset(mips::F0, mips::A0, -2052); + __ LoadQFromOffset(mips::F0, mips::A0, -4096); + __ LoadQFromOffset(mips::F0, mips::A0, -4104); + __ LoadQFromOffset(mips::F0, mips::A0, -32768); + __ LoadQFromOffset(mips::F0, mips::A0, 0xABCDEF00); + __ LoadQFromOffset(mips::F0, mips::A0, 0x7FFFABCD); + + const char* expected = + "ld.d $w0, 0($a0)\n" + "ld.b $w0, 1($a0)\n" + "ld.h $w0, 2($a0)\n" + "ld.w $w0, 4($a0)\n" + "ld.d $w0, 8($a0)\n" + "ld.b $w0, 511($a0)\n" + "ld.d $w0, 512($a0)\n" + "addiu $at, $a0, 513\n" + "ld.b $w0, 0($at)\n" + "ld.h $w0, 514($a0)\n" + "ld.w $w0, 516($a0)\n" + "ld.h $w0, 1022($a0)\n" + "ld.d $w0, 1024($a0)\n" + "addiu $at, $a0, 1025\n" + "ld.b $w0, 0($at)\n" + "addiu $at, $a0, 1026\n" + "ld.h $w0, 0($at)\n" + "ld.w $w0, 1028($a0)\n" + "ld.w $w0, 2044($a0)\n" + "ld.d $w0, 2048($a0)\n" + "addiu $at, $a0, 2049\n" + "ld.b $w0, 0($at)\n" + "addiu $at, $a0, 2050\n" + "ld.h $w0, 0($at)\n" + "addiu $at, $a0, 2052\n" + "ld.w $w0, 0($at)\n" + "ld.d $w0, 4088($a0)\n" + "addiu $at, $a0, 4096\n" + "ld.d $w0, 0($at)\n" + "addiu $at, $a0, 4097\n" + "ld.b $w0, 0($at)\n" + "addiu $at, $a0, 4098\n" + "ld.h $w0, 0($at)\n" + "addiu $at, $a0, 4100\n" + "ld.w $w0, 0($at)\n" + "addiu $at, $a0, 4104\n" + "ld.d $w0, 0($at)\n" + "addiu $at, $a0, 0x7FFC\n" + "ld.w $w0, 0($at)\n" + "addiu $at, $a0, 0x7FF8\n" + "ld.d $w0, 8($at)\n" + "aui $at, $a0, 0x1\n" + "ld.d $w0, 0($at)\n" + "aui $at, $a0, 0x1234\n" + "addiu $at, $at, 0x6000\n" + "ld.d $w0, -2440($at) # 0xF678\n" + "aui $at, $a0, 0x1235\n" + "ld.d $w0, 0x78($at)\n" + "ld.d $w0, -256($a0)\n" + "ld.b $w0, -511($a0)\n" + "addiu $at, $a0, -513\n" + "ld.b $w0, 0($at)\n" + "ld.h $w0, -1022($a0)\n" + "addiu $at, $a0, -1026\n" + "ld.h $w0, 0($at)\n" + "ld.w $w0, -2044($a0)\n" + "addiu $at, $a0, -2052\n" + "ld.w $w0, 0($at)\n" + "ld.d $w0, -4096($a0)\n" + "addiu $at, $a0, -4104\n" + "ld.d $w0, 0($at)\n" + "addiu $at, $a0, -32768\n" + "ld.d $w0, 0($at)\n" + "aui $at, $a0, 0xABCE\n" + "addiu $at, $at, -8192 # 0xE000\n" + "ld.d $w0, 0xF00($at)\n" + "aui $at, $a0, 0x8000\n" + "addiu $at, $at, -21504 # 0xAC00\n" + "ld.b $w0, -51($at) # 0xFFCD\n"; + DriverStr(expected, "LoadQFromOffset"); +} + TEST_F(AssemblerMIPS32r6Test, StoreDToOffset) { __ StoreDToOffset(mips::F0, mips::A0, -0x8000); __ StoreDToOffset(mips::F0, mips::A0, +0); @@ -711,6 +829,124 @@ TEST_F(AssemblerMIPS32r6Test, StoreDToOffset) { DriverStr(expected, "StoreDToOffset"); } +TEST_F(AssemblerMIPS32r6Test, StoreQToOffset) { + __ StoreQToOffset(mips::F0, mips::A0, 0); + __ StoreQToOffset(mips::F0, mips::A0, 1); + __ StoreQToOffset(mips::F0, mips::A0, 2); + __ StoreQToOffset(mips::F0, mips::A0, 4); + __ StoreQToOffset(mips::F0, mips::A0, 8); + __ StoreQToOffset(mips::F0, mips::A0, 511); + __ StoreQToOffset(mips::F0, mips::A0, 512); + __ StoreQToOffset(mips::F0, mips::A0, 513); + __ StoreQToOffset(mips::F0, mips::A0, 514); + __ StoreQToOffset(mips::F0, mips::A0, 516); + __ StoreQToOffset(mips::F0, mips::A0, 1022); + __ StoreQToOffset(mips::F0, mips::A0, 1024); + __ StoreQToOffset(mips::F0, mips::A0, 1025); + __ StoreQToOffset(mips::F0, mips::A0, 1026); + __ StoreQToOffset(mips::F0, mips::A0, 1028); + __ StoreQToOffset(mips::F0, mips::A0, 2044); + __ StoreQToOffset(mips::F0, mips::A0, 2048); + __ StoreQToOffset(mips::F0, mips::A0, 2049); + __ StoreQToOffset(mips::F0, mips::A0, 2050); + __ StoreQToOffset(mips::F0, mips::A0, 2052); + __ StoreQToOffset(mips::F0, mips::A0, 4088); + __ StoreQToOffset(mips::F0, mips::A0, 4096); + __ StoreQToOffset(mips::F0, mips::A0, 4097); + __ StoreQToOffset(mips::F0, mips::A0, 4098); + __ StoreQToOffset(mips::F0, mips::A0, 4100); + __ StoreQToOffset(mips::F0, mips::A0, 4104); + __ StoreQToOffset(mips::F0, mips::A0, 0x7FFC); + __ StoreQToOffset(mips::F0, mips::A0, 0x8000); + __ StoreQToOffset(mips::F0, mips::A0, 0x10000); + __ StoreQToOffset(mips::F0, mips::A0, 0x12345678); + __ StoreQToOffset(mips::F0, mips::A0, 0x12350078); + __ StoreQToOffset(mips::F0, mips::A0, -256); + __ StoreQToOffset(mips::F0, mips::A0, -511); + __ StoreQToOffset(mips::F0, mips::A0, -513); + __ StoreQToOffset(mips::F0, mips::A0, -1022); + __ StoreQToOffset(mips::F0, mips::A0, -1026); + __ StoreQToOffset(mips::F0, mips::A0, -2044); + __ StoreQToOffset(mips::F0, mips::A0, -2052); + __ StoreQToOffset(mips::F0, mips::A0, -4096); + __ StoreQToOffset(mips::F0, mips::A0, -4104); + __ StoreQToOffset(mips::F0, mips::A0, -32768); + __ StoreQToOffset(mips::F0, mips::A0, 0xABCDEF00); + __ StoreQToOffset(mips::F0, mips::A0, 0x7FFFABCD); + + const char* expected = + "st.d $w0, 0($a0)\n" + "st.b $w0, 1($a0)\n" + "st.h $w0, 2($a0)\n" + "st.w $w0, 4($a0)\n" + "st.d $w0, 8($a0)\n" + "st.b $w0, 511($a0)\n" + "st.d $w0, 512($a0)\n" + "addiu $at, $a0, 513\n" + "st.b $w0, 0($at)\n" + "st.h $w0, 514($a0)\n" + "st.w $w0, 516($a0)\n" + "st.h $w0, 1022($a0)\n" + "st.d $w0, 1024($a0)\n" + "addiu $at, $a0, 1025\n" + "st.b $w0, 0($at)\n" + "addiu $at, $a0, 1026\n" + "st.h $w0, 0($at)\n" + "st.w $w0, 1028($a0)\n" + "st.w $w0, 2044($a0)\n" + "st.d $w0, 2048($a0)\n" + "addiu $at, $a0, 2049\n" + "st.b $w0, 0($at)\n" + "addiu $at, $a0, 2050\n" + "st.h $w0, 0($at)\n" + "addiu $at, $a0, 2052\n" + "st.w $w0, 0($at)\n" + "st.d $w0, 4088($a0)\n" + "addiu $at, $a0, 4096\n" + "st.d $w0, 0($at)\n" + "addiu $at, $a0, 4097\n" + "st.b $w0, 0($at)\n" + "addiu $at, $a0, 4098\n" + "st.h $w0, 0($at)\n" + "addiu $at, $a0, 4100\n" + "st.w $w0, 0($at)\n" + "addiu $at, $a0, 4104\n" + "st.d $w0, 0($at)\n" + "addiu $at, $a0, 0x7FFC\n" + "st.w $w0, 0($at)\n" + "addiu $at, $a0, 0x7FF8\n" + "st.d $w0, 8($at)\n" + "aui $at, $a0, 0x1\n" + "st.d $w0, 0($at)\n" + "aui $at, $a0, 0x1234\n" + "addiu $at, $at, 0x6000\n" + "st.d $w0, -2440($at) # 0xF678\n" + "aui $at, $a0, 0x1235\n" + "st.d $w0, 0x78($at)\n" + "st.d $w0, -256($a0)\n" + "st.b $w0, -511($a0)\n" + "addiu $at, $a0, -513\n" + "st.b $w0, 0($at)\n" + "st.h $w0, -1022($a0)\n" + "addiu $at, $a0, -1026\n" + "st.h $w0, 0($at)\n" + "st.w $w0, -2044($a0)\n" + "addiu $at, $a0, -2052\n" + "st.w $w0, 0($at)\n" + "st.d $w0, -4096($a0)\n" + "addiu $at, $a0, -4104\n" + "st.d $w0, 0($at)\n" + "addiu $at, $a0, -32768\n" + "st.d $w0, 0($at)\n" + "aui $at, $a0, 0xABCE\n" + "addiu $at, $at, -8192 # 0xE000\n" + "st.d $w0, 0xF00($at)\n" + "aui $at, $a0, 0x8000\n" + "addiu $at, $at, -21504 # 0xAC00\n" + "st.b $w0, -51($at) # 0xFFCD\n"; + DriverStr(expected, "StoreQToOffset"); +} + TEST_F(AssemblerMIPS32r6Test, LoadFarthestNearLabelAddress) { mips::MipsLabel label; __ LoadLabelAddress(mips::V0, mips::ZERO, &label); |