diff options
| -rw-r--r-- | compiler/utils/mips64/assembler_mips64.cc | 85 | ||||
| -rw-r--r-- | compiler/utils/mips64/assembler_mips64.h | 49 | ||||
| -rw-r--r-- | compiler/utils/mips64/assembler_mips64_test.cc | 545 |
3 files changed, 372 insertions, 307 deletions
diff --git a/compiler/utils/mips64/assembler_mips64.cc b/compiler/utils/mips64/assembler_mips64.cc index 39eb5893d8..c410365a8c 100644 --- a/compiler/utils/mips64/assembler_mips64.cc +++ b/compiler/utils/mips64/assembler_mips64.cc @@ -2020,6 +2020,91 @@ void Mips64Assembler::Bc1nez(FpuRegister ft, Mips64Label* label) { Bcond(label, kCondT, static_cast<GpuRegister>(ft), ZERO); } +void Mips64Assembler::AdjustBaseAndOffset(GpuRegister& base, + int32_t& offset, + bool is_doubleword) { + // This method is used to adjust the base register and offset pair + // for a load/store when the offset doesn't fit into int16_t. + // It is assumed that `base + offset` is sufficiently aligned for memory + // operands that are machine word in size or smaller. For doubleword-sized + // operands it's assumed that `base` is a multiple of 8, while `offset` + // may be a multiple of 4 (e.g. 4-byte-aligned long and double arguments + // and spilled variables on the stack accessed relative to the stack + // pointer register). + // We preserve the "alignment" of `offset` by adjusting it by a multiple of 8. + CHECK_NE(base, AT); // Must not overwrite the register `base` while loading `offset`. + + bool doubleword_aligned = IsAligned<kMips64DoublewordSize>(offset); + bool two_accesses = is_doubleword && !doubleword_aligned; + + // IsInt<16> must be passed a signed value, hence the static cast below. + if (IsInt<16>(offset) && + (!two_accesses || IsInt<16>(static_cast<int32_t>(offset + kMips64WordSize)))) { + // Nothing to do: `offset` (and, if needed, `offset + 4`) fits into int16_t. + return; + } + + // Remember the "(mis)alignment" of `offset`, it will be checked at the end. + uint32_t misalignment = offset & (kMips64DoublewordSize - 1); + + // First, see if `offset` can be represented as a sum of two 16-bit signed + // offsets. This can save an instruction. + // To simplify matters, only do this for a symmetric range of offsets from + // about -64KB to about +64KB, allowing further addition of 4 when accessing + // 64-bit variables with two 32-bit accesses. + constexpr int32_t kMinOffsetForSimpleAdjustment = 0x7ff8; // Max int16_t that's a multiple of 8. + constexpr int32_t kMaxOffsetForSimpleAdjustment = 2 * kMinOffsetForSimpleAdjustment; + + if (0 <= offset && offset <= kMaxOffsetForSimpleAdjustment) { + Daddiu(AT, base, kMinOffsetForSimpleAdjustment); + offset -= kMinOffsetForSimpleAdjustment; + } else if (-kMaxOffsetForSimpleAdjustment <= offset && offset < 0) { + Daddiu(AT, base, -kMinOffsetForSimpleAdjustment); + offset += kMinOffsetForSimpleAdjustment; + } else { + // In more complex cases take advantage of the daui instruction, e.g.: + // daui AT, base, offset_high + // [dahi AT, 1] // When `offset` is close to +2GB. + // lw reg_lo, offset_low(AT) + // [lw reg_hi, (offset_low+4)(AT)] // If misaligned 64-bit load. + // or when offset_low+4 overflows int16_t: + // daui AT, base, offset_high + // daddiu AT, AT, 8 + // lw reg_lo, (offset_low-8)(AT) + // lw reg_hi, (offset_low-4)(AT) + int16_t offset_low = Low16Bits(offset); + int32_t offset_low32 = offset_low; + int16_t offset_high = High16Bits(offset); + bool increment_hi16 = offset_low < 0; + bool overflow_hi16 = false; + + if (increment_hi16) { + offset_high++; + overflow_hi16 = (offset_high == -32768); + } + Daui(AT, base, offset_high); + + if (overflow_hi16) { + Dahi(AT, 1); + } + + if (two_accesses && !IsInt<16>(static_cast<int32_t>(offset_low32 + kMips64WordSize))) { + // Avoid overflow in the 16-bit offset of the load/store instruction when adding 4. + Daddiu(AT, AT, kMips64DoublewordSize); + offset_low32 -= kMips64DoublewordSize; + } + + offset = offset_low32; + } + base = AT; + + CHECK(IsInt<16>(offset)); + if (two_accesses) { + CHECK(IsInt<16>(static_cast<int32_t>(offset + kMips64WordSize))); + } + CHECK_EQ(misalignment, offset & (kMips64DoublewordSize - 1)); +} + void Mips64Assembler::LoadFromOffset(LoadOperandType type, GpuRegister reg, GpuRegister base, diff --git a/compiler/utils/mips64/assembler_mips64.h b/compiler/utils/mips64/assembler_mips64.h index b98db65fbd..2c5072efe9 100644 --- a/compiler/utils/mips64/assembler_mips64.h +++ b/compiler/utils/mips64/assembler_mips64.h @@ -772,6 +772,7 @@ class Mips64Assembler FINAL : public Assembler, public JNIMacroAssembler<Pointer void Bc1nez(FpuRegister ft, Mips64Label* label); void EmitLoad(ManagedRegister m_dst, GpuRegister src_register, int32_t src_offset, size_t size); + void AdjustBaseAndOffset(GpuRegister& base, int32_t& offset, bool is_doubleword); private: // This will be used as an argument for loads/stores @@ -791,14 +792,7 @@ class Mips64Assembler FINAL : public Assembler, public JNIMacroAssembler<Pointer // We permit `base` and `temp` to coincide (however, we check that neither is AT), // in which case the `base` register may be overwritten in the process. CHECK_NE(temp, AT); // Must not use AT as temp, so as not to overwrite the adjusted base. - if (!IsInt<16>(offset) || - (type == kStoreDoubleword && !IsAligned<kMips64DoublewordSize>(offset) && - !IsInt<16>(static_cast<int32_t>(offset + kMips64WordSize)))) { - LoadConst32(AT, offset & ~(kMips64DoublewordSize - 1)); - Daddu(AT, AT, base); - base = AT; - offset &= (kMips64DoublewordSize - 1); - } + AdjustBaseAndOffset(base, offset, /* is_doubleword */ (type == kStoreDoubleword)); GpuRegister reg; // If the adjustment left `base` unchanged and equal to `temp`, we can't use `temp` // to load and hold the value but we can use AT instead as AT hasn't been used yet. @@ -867,14 +861,7 @@ class Mips64Assembler FINAL : public Assembler, public JNIMacroAssembler<Pointer GpuRegister base, int32_t offset, ImplicitNullChecker null_checker = NoImplicitNullChecker()) { - if (!IsInt<16>(offset) || - (type == kLoadDoubleword && !IsAligned<kMips64DoublewordSize>(offset) && - !IsInt<16>(static_cast<int32_t>(offset + kMips64WordSize)))) { - LoadConst32(AT, offset & ~(kMips64DoublewordSize - 1)); - Daddu(AT, AT, base); - base = AT; - offset &= (kMips64DoublewordSize - 1); - } + AdjustBaseAndOffset(base, offset, /* is_doubleword */ (type == kLoadDoubleword)); switch (type) { case kLoadSignedByte: @@ -921,14 +908,7 @@ class Mips64Assembler FINAL : public Assembler, public JNIMacroAssembler<Pointer GpuRegister base, int32_t offset, ImplicitNullChecker null_checker = NoImplicitNullChecker()) { - if (!IsInt<16>(offset) || - (type == kLoadDoubleword && !IsAligned<kMips64DoublewordSize>(offset) && - !IsInt<16>(static_cast<int32_t>(offset + kMips64WordSize)))) { - LoadConst32(AT, offset & ~(kMips64DoublewordSize - 1)); - Daddu(AT, AT, base); - base = AT; - offset &= (kMips64DoublewordSize - 1); - } + AdjustBaseAndOffset(base, offset, /* is_doubleword */ (type == kLoadDoubleword)); switch (type) { case kLoadWord: @@ -959,14 +939,10 @@ class Mips64Assembler FINAL : public Assembler, public JNIMacroAssembler<Pointer GpuRegister base, int32_t offset, ImplicitNullChecker null_checker = NoImplicitNullChecker()) { - if (!IsInt<16>(offset) || - (type == kStoreDoubleword && !IsAligned<kMips64DoublewordSize>(offset) && - !IsInt<16>(static_cast<int32_t>(offset + kMips64WordSize)))) { - LoadConst32(AT, offset & ~(kMips64DoublewordSize - 1)); - Daddu(AT, AT, base); - base = AT; - offset &= (kMips64DoublewordSize - 1); - } + // Must not use AT as `reg`, so as not to overwrite the value being stored + // with the adjusted `base`. + CHECK_NE(reg, AT); + AdjustBaseAndOffset(base, offset, /* is_doubleword */ (type == kStoreDoubleword)); switch (type) { case kStoreByte: @@ -1005,14 +981,7 @@ class Mips64Assembler FINAL : public Assembler, public JNIMacroAssembler<Pointer GpuRegister base, int32_t offset, ImplicitNullChecker null_checker = NoImplicitNullChecker()) { - if (!IsInt<16>(offset) || - (type == kStoreDoubleword && !IsAligned<kMips64DoublewordSize>(offset) && - !IsInt<16>(static_cast<int32_t>(offset + kMips64WordSize)))) { - LoadConst32(AT, offset & ~(kMips64DoublewordSize - 1)); - Daddu(AT, AT, base); - base = AT; - offset &= (kMips64DoublewordSize - 1); - } + AdjustBaseAndOffset(base, offset, /* is_doubleword */ (type == kStoreDoubleword)); switch (type) { case kStoreWord: diff --git a/compiler/utils/mips64/assembler_mips64_test.cc b/compiler/utils/mips64/assembler_mips64_test.cc index 879807ac32..e5d3605b01 100644 --- a/compiler/utils/mips64/assembler_mips64_test.cc +++ b/compiler/utils/mips64/assembler_mips64_test.cc @@ -1560,6 +1560,10 @@ TEST_F(AssemblerMIPS64Test, LoadFromOffset) { __ LoadFromOffset(mips64::kLoadSignedByte, mips64::A0, mips64::A1, -256); __ LoadFromOffset(mips64::kLoadSignedByte, mips64::A0, mips64::A1, -32768); __ LoadFromOffset(mips64::kLoadSignedByte, mips64::A0, mips64::A1, 0xABCDEF00); + __ LoadFromOffset(mips64::kLoadSignedByte, mips64::A0, mips64::A1, 0x7FFFFFFE); + __ LoadFromOffset(mips64::kLoadSignedByte, mips64::A0, mips64::A1, 0x7FFFFFFF); + __ LoadFromOffset(mips64::kLoadSignedByte, mips64::A0, mips64::A1, 0x80000000); + __ LoadFromOffset(mips64::kLoadSignedByte, mips64::A0, mips64::A1, 0x80000001); __ LoadFromOffset(mips64::kLoadUnsignedByte, mips64::A0, mips64::A0, 0); __ LoadFromOffset(mips64::kLoadUnsignedByte, mips64::A0, mips64::A1, 0); @@ -1574,6 +1578,10 @@ TEST_F(AssemblerMIPS64Test, LoadFromOffset) { __ LoadFromOffset(mips64::kLoadUnsignedByte, mips64::A0, mips64::A1, -256); __ LoadFromOffset(mips64::kLoadUnsignedByte, mips64::A0, mips64::A1, -32768); __ LoadFromOffset(mips64::kLoadUnsignedByte, mips64::A0, mips64::A1, 0xABCDEF00); + __ LoadFromOffset(mips64::kLoadUnsignedByte, mips64::A0, mips64::A1, 0x7FFFFFFE); + __ LoadFromOffset(mips64::kLoadUnsignedByte, mips64::A0, mips64::A1, 0x7FFFFFFF); + __ LoadFromOffset(mips64::kLoadUnsignedByte, mips64::A0, mips64::A1, 0x80000000); + __ LoadFromOffset(mips64::kLoadUnsignedByte, mips64::A0, mips64::A1, 0x80000001); __ LoadFromOffset(mips64::kLoadSignedHalfword, mips64::A0, mips64::A0, 0); __ LoadFromOffset(mips64::kLoadSignedHalfword, mips64::A0, mips64::A1, 0); @@ -1588,6 +1596,10 @@ TEST_F(AssemblerMIPS64Test, LoadFromOffset) { __ LoadFromOffset(mips64::kLoadSignedHalfword, mips64::A0, mips64::A1, -256); __ LoadFromOffset(mips64::kLoadSignedHalfword, mips64::A0, mips64::A1, -32768); __ LoadFromOffset(mips64::kLoadSignedHalfword, mips64::A0, mips64::A1, 0xABCDEF00); + __ LoadFromOffset(mips64::kLoadSignedHalfword, mips64::A0, mips64::A1, 0x7FFFFFFC); + __ LoadFromOffset(mips64::kLoadSignedHalfword, mips64::A0, mips64::A1, 0x7FFFFFFE); + __ LoadFromOffset(mips64::kLoadSignedHalfword, mips64::A0, mips64::A1, 0x80000000); + __ LoadFromOffset(mips64::kLoadSignedHalfword, mips64::A0, mips64::A1, 0x80000002); __ LoadFromOffset(mips64::kLoadUnsignedHalfword, mips64::A0, mips64::A0, 0); __ LoadFromOffset(mips64::kLoadUnsignedHalfword, mips64::A0, mips64::A1, 0); @@ -1602,6 +1614,10 @@ TEST_F(AssemblerMIPS64Test, LoadFromOffset) { __ LoadFromOffset(mips64::kLoadUnsignedHalfword, mips64::A0, mips64::A1, -256); __ LoadFromOffset(mips64::kLoadUnsignedHalfword, mips64::A0, mips64::A1, -32768); __ LoadFromOffset(mips64::kLoadUnsignedHalfword, mips64::A0, mips64::A1, 0xABCDEF00); + __ LoadFromOffset(mips64::kLoadUnsignedHalfword, mips64::A0, mips64::A1, 0x7FFFFFFC); + __ LoadFromOffset(mips64::kLoadUnsignedHalfword, mips64::A0, mips64::A1, 0x7FFFFFFE); + __ LoadFromOffset(mips64::kLoadUnsignedHalfword, mips64::A0, mips64::A1, 0x80000000); + __ LoadFromOffset(mips64::kLoadUnsignedHalfword, mips64::A0, mips64::A1, 0x80000002); __ LoadFromOffset(mips64::kLoadWord, mips64::A0, mips64::A0, 0); __ LoadFromOffset(mips64::kLoadWord, mips64::A0, mips64::A1, 0); @@ -1616,6 +1632,10 @@ TEST_F(AssemblerMIPS64Test, LoadFromOffset) { __ LoadFromOffset(mips64::kLoadWord, mips64::A0, mips64::A1, -256); __ LoadFromOffset(mips64::kLoadWord, mips64::A0, mips64::A1, -32768); __ LoadFromOffset(mips64::kLoadWord, mips64::A0, mips64::A1, 0xABCDEF00); + __ LoadFromOffset(mips64::kLoadWord, mips64::A0, mips64::A1, 0x7FFFFFF8); + __ LoadFromOffset(mips64::kLoadWord, mips64::A0, mips64::A1, 0x7FFFFFFC); + __ LoadFromOffset(mips64::kLoadWord, mips64::A0, mips64::A1, 0x80000000); + __ LoadFromOffset(mips64::kLoadWord, mips64::A0, mips64::A1, 0x80000004); __ LoadFromOffset(mips64::kLoadUnsignedWord, mips64::A0, mips64::A0, 0); __ LoadFromOffset(mips64::kLoadUnsignedWord, mips64::A0, mips64::A1, 0); @@ -1630,6 +1650,10 @@ TEST_F(AssemblerMIPS64Test, LoadFromOffset) { __ LoadFromOffset(mips64::kLoadUnsignedWord, mips64::A0, mips64::A1, -256); __ LoadFromOffset(mips64::kLoadUnsignedWord, mips64::A0, mips64::A1, -32768); __ LoadFromOffset(mips64::kLoadUnsignedWord, mips64::A0, mips64::A1, 0xABCDEF00); + __ LoadFromOffset(mips64::kLoadUnsignedWord, mips64::A0, mips64::A1, 0x7FFFFFF8); + __ LoadFromOffset(mips64::kLoadUnsignedWord, mips64::A0, mips64::A1, 0x7FFFFFFC); + __ LoadFromOffset(mips64::kLoadUnsignedWord, mips64::A0, mips64::A1, 0x80000000); + __ LoadFromOffset(mips64::kLoadUnsignedWord, mips64::A0, mips64::A1, 0x80000004); __ LoadFromOffset(mips64::kLoadDoubleword, mips64::A0, mips64::A0, 0); __ LoadFromOffset(mips64::kLoadDoubleword, mips64::A0, mips64::A1, 0); @@ -1640,10 +1664,15 @@ TEST_F(AssemblerMIPS64Test, LoadFromOffset) { __ LoadFromOffset(mips64::kLoadDoubleword, mips64::A0, mips64::A1, 0x8000); __ LoadFromOffset(mips64::kLoadDoubleword, mips64::A0, mips64::A1, 0x8004); __ LoadFromOffset(mips64::kLoadDoubleword, mips64::A0, mips64::A1, 0x10000); + __ LoadFromOffset(mips64::kLoadDoubleword, mips64::A0, mips64::A1, 0x27FFC); __ LoadFromOffset(mips64::kLoadDoubleword, mips64::A0, mips64::A1, 0x12345678); __ LoadFromOffset(mips64::kLoadDoubleword, mips64::A0, mips64::A1, -256); __ LoadFromOffset(mips64::kLoadDoubleword, mips64::A0, mips64::A1, -32768); __ LoadFromOffset(mips64::kLoadDoubleword, mips64::A0, mips64::A1, 0xABCDEF00); + __ LoadFromOffset(mips64::kLoadDoubleword, mips64::A0, mips64::A1, 0x7FFFFFF8); + __ LoadFromOffset(mips64::kLoadDoubleword, mips64::A0, mips64::A1, 0x7FFFFFFC); + __ LoadFromOffset(mips64::kLoadDoubleword, mips64::A0, mips64::A1, 0x80000000); + __ LoadFromOffset(mips64::kLoadDoubleword, mips64::A0, mips64::A1, 0x80000004); const char* expected = "lb $a0, 0($a0)\n" @@ -1652,25 +1681,28 @@ TEST_F(AssemblerMIPS64Test, LoadFromOffset) { "lb $a0, 256($a1)\n" "lb $a0, 1000($a1)\n" "lb $a0, 0x7FFF($a1)\n" - "ori $at, $zero, 0x8000\n" - "daddu $at, $at, $a1\n" - "lb $a0, 0($at)\n" - "ori $at, $zero, 0x8000\n" - "daddu $at, $at, $a1\n" - "lb $a0, 1($at)\n" - "lui $at, 1\n" - "daddu $at, $at, $a1\n" - "lb $a0, 0($at)\n" - "lui $at, 0x1234\n" - "ori $at, 0x5678\n" - "daddu $at, $at, $a1\n" + "daddiu $at, $a1, 0x7FF8\n" + "lb $a0, 8($at)\n" + "daddiu $at, $a1, 32760\n" + "lb $a0, 9($at)\n" + "daui $at, $a1, 1\n" "lb $a0, 0($at)\n" + "daui $at, $a1, 0x1234\n" + "lb $a0, 0x5678($at)\n" "lb $a0, -256($a1)\n" "lb $a0, -32768($a1)\n" - "lui $at, 0xABCD\n" - "ori $at, 0xEF00\n" - "daddu $at, $at, $a1\n" + "daui $at, $a1, 0xABCE\n" + "lb $a0, -4352($at)\n" + "daui $at, $a1, 32768\n" + "dahi $at, $at, 1\n" + "lb $a0, -2($at)\n" + "daui $at, $a1, 32768\n" + "dahi $at, $at, 1\n" + "lb $a0, -1($at)\n" + "daui $at, $a1, 32768\n" "lb $a0, 0($at)\n" + "daui $at, $a1, 32768\n" + "lb $a0, 1($at)\n" "lbu $a0, 0($a0)\n" "lbu $a0, 0($a1)\n" @@ -1678,25 +1710,28 @@ TEST_F(AssemblerMIPS64Test, LoadFromOffset) { "lbu $a0, 256($a1)\n" "lbu $a0, 1000($a1)\n" "lbu $a0, 0x7FFF($a1)\n" - "ori $at, $zero, 0x8000\n" - "daddu $at, $at, $a1\n" - "lbu $a0, 0($at)\n" - "ori $at, $zero, 0x8000\n" - "daddu $at, $at, $a1\n" - "lbu $a0, 1($at)\n" - "lui $at, 1\n" - "daddu $at, $at, $a1\n" - "lbu $a0, 0($at)\n" - "lui $at, 0x1234\n" - "ori $at, 0x5678\n" - "daddu $at, $at, $a1\n" + "daddiu $at, $a1, 0x7FF8\n" + "lbu $a0, 8($at)\n" + "daddiu $at, $a1, 32760\n" + "lbu $a0, 9($at)\n" + "daui $at, $a1, 1\n" "lbu $a0, 0($at)\n" + "daui $at, $a1, 0x1234\n" + "lbu $a0, 0x5678($at)\n" "lbu $a0, -256($a1)\n" "lbu $a0, -32768($a1)\n" - "lui $at, 0xABCD\n" - "ori $at, 0xEF00\n" - "daddu $at, $at, $a1\n" + "daui $at, $a1, 0xABCE\n" + "lbu $a0, -4352($at)\n" + "daui $at, $a1, 32768\n" + "dahi $at, $at, 1\n" + "lbu $a0, -2($at)\n" + "daui $at, $a1, 32768\n" + "dahi $at, $at, 1\n" + "lbu $a0, -1($at)\n" + "daui $at, $a1, 32768\n" "lbu $a0, 0($at)\n" + "daui $at, $a1, 32768\n" + "lbu $a0, 1($at)\n" "lh $a0, 0($a0)\n" "lh $a0, 0($a1)\n" @@ -1704,25 +1739,28 @@ TEST_F(AssemblerMIPS64Test, LoadFromOffset) { "lh $a0, 256($a1)\n" "lh $a0, 1000($a1)\n" "lh $a0, 0x7FFE($a1)\n" - "ori $at, $zero, 0x8000\n" - "daddu $at, $at, $a1\n" - "lh $a0, 0($at)\n" - "ori $at, $zero, 0x8000\n" - "daddu $at, $at, $a1\n" - "lh $a0, 2($at)\n" - "lui $at, 1\n" - "daddu $at, $at, $a1\n" - "lh $a0, 0($at)\n" - "lui $at, 0x1234\n" - "ori $at, 0x5678\n" - "daddu $at, $at, $a1\n" + "daddiu $at, $a1, 0x7FF8\n" + "lh $a0, 8($at)\n" + "daddiu $at, $a1, 32760\n" + "lh $a0, 10($at)\n" + "daui $at, $a1, 1\n" "lh $a0, 0($at)\n" + "daui $at, $a1, 0x1234\n" + "lh $a0, 0x5678($at)\n" "lh $a0, -256($a1)\n" "lh $a0, -32768($a1)\n" - "lui $at, 0xABCD\n" - "ori $at, 0xEF00\n" - "daddu $at, $at, $a1\n" + "daui $at, $a1, 0xABCE\n" + "lh $a0, -4352($at)\n" + "daui $at, $a1, 32768\n" + "dahi $at, $at, 1\n" + "lh $a0, -4($at)\n" + "daui $at, $a1, 32768\n" + "dahi $at, $at, 1\n" + "lh $a0, -2($at)\n" + "daui $at, $a1, 32768\n" "lh $a0, 0($at)\n" + "daui $at, $a1, 32768\n" + "lh $a0, 2($at)\n" "lhu $a0, 0($a0)\n" "lhu $a0, 0($a1)\n" @@ -1730,25 +1768,28 @@ TEST_F(AssemblerMIPS64Test, LoadFromOffset) { "lhu $a0, 256($a1)\n" "lhu $a0, 1000($a1)\n" "lhu $a0, 0x7FFE($a1)\n" - "ori $at, $zero, 0x8000\n" - "daddu $at, $at, $a1\n" - "lhu $a0, 0($at)\n" - "ori $at, $zero, 0x8000\n" - "daddu $at, $at, $a1\n" - "lhu $a0, 2($at)\n" - "lui $at, 1\n" - "daddu $at, $at, $a1\n" - "lhu $a0, 0($at)\n" - "lui $at, 0x1234\n" - "ori $at, 0x5678\n" - "daddu $at, $at, $a1\n" + "daddiu $at, $a1, 0x7FF8\n" + "lhu $a0, 8($at)\n" + "daddiu $at, $a1, 32760\n" + "lhu $a0, 10($at)\n" + "daui $at, $a1, 1\n" "lhu $a0, 0($at)\n" + "daui $at, $a1, 0x1234\n" + "lhu $a0, 0x5678($at)\n" "lhu $a0, -256($a1)\n" "lhu $a0, -32768($a1)\n" - "lui $at, 0xABCD\n" - "ori $at, 0xEF00\n" - "daddu $at, $at, $a1\n" + "daui $at, $a1, 0xABCE\n" + "lhu $a0, -4352($at)\n" + "daui $at, $a1, 32768\n" + "dahi $at, $at, 1\n" + "lhu $a0, -4($at)\n" + "daui $at, $a1, 32768\n" + "dahi $at, $at, 1\n" + "lhu $a0, -2($at)\n" + "daui $at, $a1, 32768\n" "lhu $a0, 0($at)\n" + "daui $at, $a1, 32768\n" + "lhu $a0, 2($at)\n" "lw $a0, 0($a0)\n" "lw $a0, 0($a1)\n" @@ -1756,25 +1797,28 @@ TEST_F(AssemblerMIPS64Test, LoadFromOffset) { "lw $a0, 256($a1)\n" "lw $a0, 1000($a1)\n" "lw $a0, 0x7FFC($a1)\n" - "ori $at, $zero, 0x8000\n" - "daddu $at, $at, $a1\n" - "lw $a0, 0($at)\n" - "ori $at, $zero, 0x8000\n" - "daddu $at, $at, $a1\n" - "lw $a0, 4($at)\n" - "lui $at, 1\n" - "daddu $at, $at, $a1\n" - "lw $a0, 0($at)\n" - "lui $at, 0x1234\n" - "ori $at, 0x5678\n" - "daddu $at, $at, $a1\n" + "daddiu $at, $a1, 0x7FF8\n" + "lw $a0, 8($at)\n" + "daddiu $at, $a1, 32760\n" + "lw $a0, 12($at)\n" + "daui $at, $a1, 1\n" "lw $a0, 0($at)\n" + "daui $at, $a1, 0x1234\n" + "lw $a0, 0x5678($at)\n" "lw $a0, -256($a1)\n" "lw $a0, -32768($a1)\n" - "lui $at, 0xABCD\n" - "ori $at, 0xEF00\n" - "daddu $at, $at, $a1\n" + "daui $at, $a1, 0xABCE\n" + "lw $a0, -4352($at)\n" + "daui $at, $a1, 32768\n" + "dahi $at, $at, 1\n" + "lw $a0, -8($at)\n" + "daui $at, $a1, 32768\n" + "dahi $at, $at, 1\n" + "lw $a0, -4($at)\n" + "daui $at, $a1, 32768\n" "lw $a0, 0($at)\n" + "daui $at, $a1, 32768\n" + "lw $a0, 4($at)\n" "lwu $a0, 0($a0)\n" "lwu $a0, 0($a1)\n" @@ -1782,59 +1826,73 @@ TEST_F(AssemblerMIPS64Test, LoadFromOffset) { "lwu $a0, 256($a1)\n" "lwu $a0, 1000($a1)\n" "lwu $a0, 0x7FFC($a1)\n" - "ori $at, $zero, 0x8000\n" - "daddu $at, $at, $a1\n" - "lwu $a0, 0($at)\n" - "ori $at, $zero, 0x8000\n" - "daddu $at, $at, $a1\n" - "lwu $a0, 4($at)\n" - "lui $at, 1\n" - "daddu $at, $at, $a1\n" - "lwu $a0, 0($at)\n" - "lui $at, 0x1234\n" - "ori $at, 0x5678\n" - "daddu $at, $at, $a1\n" + "daddiu $at, $a1, 0x7FF8\n" + "lwu $a0, 8($at)\n" + "daddiu $at, $a1, 32760\n" + "lwu $a0, 12($at)\n" + "daui $at, $a1, 1\n" "lwu $a0, 0($at)\n" + "daui $at, $a1, 0x1234\n" + "lwu $a0, 0x5678($at)\n" "lwu $a0, -256($a1)\n" "lwu $a0, -32768($a1)\n" - "lui $at, 0xABCD\n" - "ori $at, 0xEF00\n" - "daddu $at, $at, $a1\n" + "daui $at, $a1, 0xABCE\n" + "lwu $a0, -4352($at)\n" + "daui $at, $a1, 32768\n" + "dahi $at, $at, 1\n" + "lwu $a0, -8($at)\n" + "daui $at, $a1, 32768\n" + "dahi $at, $at, 1\n" + "lwu $a0, -4($at)\n" + "daui $at, $a1, 32768\n" "lwu $a0, 0($at)\n" + "daui $at, $a1, 32768\n" + "lwu $a0, 4($at)\n" "ld $a0, 0($a0)\n" "ld $a0, 0($a1)\n" "lwu $a0, 4($a1)\n" "lwu $t3, 8($a1)\n" - "dins $a0, $t3, 32, 32\n" + "dinsu $a0, $t3, 32, 32\n" "ld $a0, 256($a1)\n" "ld $a0, 1000($a1)\n" - "ori $at, $zero, 0x7FF8\n" - "daddu $at, $at, $a1\n" + "daddiu $at, $a1, 32760\n" "lwu $a0, 4($at)\n" "lwu $t3, 8($at)\n" - "dins $a0, $t3, 32, 32\n" - "ori $at, $zero, 0x8000\n" - "daddu $at, $at, $a1\n" - "ld $a0, 0($at)\n" - "ori $at, $zero, 0x8000\n" - "daddu $at, $at, $a1\n" - "lwu $a0, 4($at)\n" - "lwu $t3, 8($at)\n" - "dins $a0, $t3, 32, 32\n" - "lui $at, 1\n" - "daddu $at, $at, $a1\n" - "ld $a0, 0($at)\n" - "lui $at, 0x1234\n" - "ori $at, 0x5678\n" - "daddu $at, $at, $a1\n" + "dinsu $a0, $t3, 32, 32\n" + "daddiu $at, $a1, 32760\n" + "ld $a0, 8($at)\n" + "daddiu $at, $a1, 32760\n" + "lwu $a0, 12($at)\n" + "lwu $t3, 16($at)\n" + "dinsu $a0, $t3, 32, 32\n" + "daui $at, $a1, 1\n" "ld $a0, 0($at)\n" + "daui $at, $a1, 2\n" + "daddiu $at, $at, 8\n" + "lwu $a0, 0x7ff4($at)\n" + "lwu $t3, 0x7ff8($at)\n" + "dinsu $a0, $t3, 32, 32\n" + "daui $at, $a1, 0x1234\n" + "ld $a0, 0x5678($at)\n" "ld $a0, -256($a1)\n" "ld $a0, -32768($a1)\n" - "lui $at, 0xABCD\n" - "ori $at, 0xEF00\n" - "daddu $at, $at, $a1\n" - "ld $a0, 0($at)\n"; + "daui $at, $a1, 0xABCE\n" + "ld $a0, -4352($at)\n" + "daui $at, $a1, 32768\n" + "dahi $at, $at, 1\n" + "ld $a0, -8($at)\n" + "daui $at, $a1, 32768\n" + "dahi $at, $at, 1\n" + "lwu $a0, -4($at)\n" + "lwu $t3, 0($at)\n" + "dinsu $a0, $t3, 32, 32\n" + "daui $at, $a1, 32768\n" + "ld $a0, 0($at)\n" + "daui $at, $a1, 32768\n" + "lwu $a0, 4($at)\n" + "lwu $t3, 8($at)\n" + "dinsu $a0, $t3, 32, 32\n"; DriverStr(expected, "LoadFromOffset"); } @@ -1868,57 +1926,42 @@ TEST_F(AssemblerMIPS64Test, LoadFpuFromOffset) { "lwc1 $f0, 4($a0)\n" "lwc1 $f0, 256($a0)\n" "lwc1 $f0, 0x7FFC($a0)\n" - "ori $at, $zero, 0x8000\n" - "daddu $at, $at, $a0\n" - "lwc1 $f0, 0($at)\n" - "ori $at, $zero, 0x8000\n" - "daddu $at, $at, $a0\n" - "lwc1 $f0, 4($at)\n" - "lui $at, 1\n" - "daddu $at, $at, $a0\n" - "lwc1 $f0, 0($at)\n" - "lui $at, 0x1234\n" - "ori $at, 0x5678\n" - "daddu $at, $at, $a0\n" + "daddiu $at, $a0, 32760 # 0x7FF8\n" + "lwc1 $f0, 8($at)\n" + "daddiu $at, $a0, 32760 # 0x7FF8\n" + "lwc1 $f0, 12($at)\n" + "daui $at, $a0, 1\n" "lwc1 $f0, 0($at)\n" + "daui $at, $a0, 4660 # 0x1234\n" + "lwc1 $f0, 22136($at) # 0x5678\n" "lwc1 $f0, -256($a0)\n" "lwc1 $f0, -32768($a0)\n" - "lui $at, 0xABCD\n" - "ori $at, 0xEF00\n" - "daddu $at, $at, $a0\n" - "lwc1 $f0, 0($at)\n" + "daui $at, $a0, 0xABCE\n" + "lwc1 $f0, -0x1100($at) # 0xEF00\n" "ldc1 $f0, 0($a0)\n" "lwc1 $f0, 4($a0)\n" "lw $t3, 8($a0)\n" "mthc1 $t3, $f0\n" "ldc1 $f0, 256($a0)\n" - "ori $at, $zero, 0x7FF8\n" - "daddu $at, $at, $a0\n" + "daddiu $at, $a0, 32760 # 0x7FF8\n" "lwc1 $f0, 4($at)\n" "lw $t3, 8($at)\n" "mthc1 $t3, $f0\n" - "ori $at, $zero, 0x8000\n" - "daddu $at, $at, $a0\n" - "ldc1 $f0, 0($at)\n" - "ori $at, $zero, 0x8000\n" - "daddu $at, $at, $a0\n" - "lwc1 $f0, 4($at)\n" - "lw $t3, 8($at)\n" + "daddiu $at, $a0, 32760 # 0x7FF8\n" + "ldc1 $f0, 8($at)\n" + "daddiu $at, $a0, 32760 # 0x7FF8\n" + "lwc1 $f0, 12($at)\n" + "lw $t3, 16($at)\n" "mthc1 $t3, $f0\n" - "lui $at, 1\n" - "daddu $at, $at, $a0\n" - "ldc1 $f0, 0($at)\n" - "lui $at, 0x1234\n" - "ori $at, 0x5678\n" - "daddu $at, $at, $a0\n" + "daui $at, $a0, 1\n" "ldc1 $f0, 0($at)\n" + "daui $at, $a0, 4660 # 0x1234\n" + "ldc1 $f0, 22136($at) # 0x5678\n" "ldc1 $f0, -256($a0)\n" "ldc1 $f0, -32768($a0)\n" - "lui $at, 0xABCD\n" - "ori $at, 0xEF00\n" - "daddu $at, $at, $a0\n" - "ldc1 $f0, 0($at)\n"; + "daui $at, $a0, 0xABCE\n" + "ldc1 $f0, -0x1100($at) # 0xEF00\n"; DriverStr(expected, "LoadFpuFromOffset"); } @@ -1978,6 +2021,10 @@ TEST_F(AssemblerMIPS64Test, StoreToOffset) { __ StoreToOffset(mips64::kStoreDoubleword, mips64::A0, mips64::A1, -256); __ StoreToOffset(mips64::kStoreDoubleword, mips64::A0, mips64::A1, -32768); __ StoreToOffset(mips64::kStoreDoubleword, mips64::A0, mips64::A1, 0xABCDEF00); + __ StoreToOffset(mips64::kStoreDoubleword, mips64::A0, mips64::A1, 0x7FFFFFF8); + __ StoreToOffset(mips64::kStoreDoubleword, mips64::A0, mips64::A1, 0x7FFFFFFC); + __ StoreToOffset(mips64::kStoreDoubleword, mips64::A0, mips64::A1, 0x80000000); + __ StoreToOffset(mips64::kStoreDoubleword, mips64::A0, mips64::A1, 0x80000004); const char* expected = "sb $a0, 0($a0)\n" @@ -1986,25 +2033,18 @@ TEST_F(AssemblerMIPS64Test, StoreToOffset) { "sb $a0, 256($a1)\n" "sb $a0, 1000($a1)\n" "sb $a0, 0x7FFF($a1)\n" - "ori $at, $zero, 0x8000\n" - "daddu $at, $at, $a1\n" - "sb $a0, 0($at)\n" - "ori $at, $zero, 0x8000\n" - "daddu $at, $at, $a1\n" - "sb $a0, 1($at)\n" - "lui $at, 1\n" - "daddu $at, $at, $a1\n" - "sb $a0, 0($at)\n" - "lui $at, 0x1234\n" - "ori $at, 0x5678\n" - "daddu $at, $at, $a1\n" + "daddiu $at, $a1, 0x7FF8\n" + "sb $a0, 8($at)\n" + "daddiu $at, $a1, 0x7FF8\n" + "sb $a0, 9($at)\n" + "daui $at, $a1, 1\n" "sb $a0, 0($at)\n" + "daui $at, $a1, 4660 # 0x1234\n" + "sb $a0, 22136($at) # 0x5678\n" "sb $a0, -256($a1)\n" "sb $a0, -32768($a1)\n" - "lui $at, 0xABCD\n" - "ori $at, 0xEF00\n" - "daddu $at, $at, $a1\n" - "sb $a0, 0($at)\n" + "daui $at, $a1, 43982 # 0xABCE\n" + "sb $a0, -4352($at) # 0xEF00\n" "sh $a0, 0($a0)\n" "sh $a0, 0($a1)\n" @@ -2012,25 +2052,18 @@ TEST_F(AssemblerMIPS64Test, StoreToOffset) { "sh $a0, 256($a1)\n" "sh $a0, 1000($a1)\n" "sh $a0, 0x7FFE($a1)\n" - "ori $at, $zero, 0x8000\n" - "daddu $at, $at, $a1\n" - "sh $a0, 0($at)\n" - "ori $at, $zero, 0x8000\n" - "daddu $at, $at, $a1\n" - "sh $a0, 2($at)\n" - "lui $at, 1\n" - "daddu $at, $at, $a1\n" - "sh $a0, 0($at)\n" - "lui $at, 0x1234\n" - "ori $at, 0x5678\n" - "daddu $at, $at, $a1\n" + "daddiu $at, $a1, 0x7FF8\n" + "sh $a0, 8($at)\n" + "daddiu $at, $a1, 0x7FF8\n" + "sh $a0, 10($at)\n" + "daui $at, $a1, 1\n" "sh $a0, 0($at)\n" + "daui $at, $a1, 4660 # 0x1234\n" + "sh $a0, 22136($at) # 0x5678\n" "sh $a0, -256($a1)\n" "sh $a0, -32768($a1)\n" - "lui $at, 0xABCD\n" - "ori $at, 0xEF00\n" - "daddu $at, $at, $a1\n" - "sh $a0, 0($at)\n" + "daui $at, $a1, 43982 # 0xABCE\n" + "sh $a0, -4352($at) # 0xEF00\n" "sw $a0, 0($a0)\n" "sw $a0, 0($a1)\n" @@ -2038,25 +2071,18 @@ TEST_F(AssemblerMIPS64Test, StoreToOffset) { "sw $a0, 256($a1)\n" "sw $a0, 1000($a1)\n" "sw $a0, 0x7FFC($a1)\n" - "ori $at, $zero, 0x8000\n" - "daddu $at, $at, $a1\n" - "sw $a0, 0($at)\n" - "ori $at, $zero, 0x8000\n" - "daddu $at, $at, $a1\n" - "sw $a0, 4($at)\n" - "lui $at, 1\n" - "daddu $at, $at, $a1\n" - "sw $a0, 0($at)\n" - "lui $at, 0x1234\n" - "ori $at, 0x5678\n" - "daddu $at, $at, $a1\n" + "daddiu $at, $a1, 0x7FF8\n" + "sw $a0, 8($at)\n" + "daddiu $at, $a1, 0x7FF8\n" + "sw $a0, 12($at)\n" + "daui $at, $a1, 1\n" "sw $a0, 0($at)\n" + "daui $at, $a1, 4660 # 0x1234\n" + "sw $a0, 22136($at) # 0x5678\n" "sw $a0, -256($a1)\n" "sw $a0, -32768($a1)\n" - "lui $at, 0xABCD\n" - "ori $at, 0xEF00\n" - "daddu $at, $at, $a1\n" - "sw $a0, 0($at)\n" + "daui $at, $a1, 43982 # 0xABCE\n" + "sw $a0, -4352($at) # 0xEF00\n" "sd $a0, 0($a0)\n" "sd $a0, 0($a1)\n" @@ -2065,32 +2091,38 @@ TEST_F(AssemblerMIPS64Test, StoreToOffset) { "sw $t3, 8($a1)\n" "sd $a0, 256($a1)\n" "sd $a0, 1000($a1)\n" - "ori $at, $zero, 0x7FF8\n" - "daddu $at, $at, $a1\n" + "daddiu $at, $a1, 0x7FF8\n" "sw $a0, 4($at)\n" "dsrl32 $t3, $a0, 0\n" "sw $t3, 8($at)\n" - "ori $at, $zero, 0x8000\n" - "daddu $at, $at, $a1\n" - "sd $a0, 0($at)\n" - "ori $at, $zero, 0x8000\n" - "daddu $at, $at, $a1\n" - "sw $a0, 4($at)\n" + "daddiu $at, $a1, 32760 # 0x7FF8\n" + "sd $a0, 8($at)\n" + "daddiu $at, $a1, 32760 # 0x7FF8\n" + "sw $a0, 12($at)\n" "dsrl32 $t3, $a0, 0\n" - "sw $t3, 8($at)\n" - "lui $at, 1\n" - "daddu $at, $at, $a1\n" - "sd $a0, 0($at)\n" - "lui $at, 0x1234\n" - "ori $at, 0x5678\n" - "daddu $at, $at, $a1\n" + "sw $t3, 16($at)\n" + "daui $at, $a1, 1\n" "sd $a0, 0($at)\n" + "daui $at, $a1, 4660 # 0x1234\n" + "sd $a0, 22136($at) # 0x5678\n" "sd $a0, -256($a1)\n" "sd $a0, -32768($a1)\n" - "lui $at, 0xABCD\n" - "ori $at, 0xEF00\n" - "daddu $at, $at, $a1\n" - "sd $a0, 0($at)\n"; + "daui $at, $a1, 0xABCE\n" + "sd $a0, -0x1100($at)\n" + "daui $at, $a1, 0x8000\n" + "dahi $at, $at, 1\n" + "sd $a0, -8($at)\n" + "daui $at, $a1, 0x8000\n" + "dahi $at, $at, 1\n" + "sw $a0, -4($at) # 0xFFFC\n" + "dsrl32 $t3, $a0, 0\n" + "sw $t3, 0($at) # 0x0\n" + "daui $at, $a1, 0x8000\n" + "sd $a0, 0($at) # 0x0\n" + "daui $at, $a1, 0x8000\n" + "sw $a0, 4($at) # 0x4\n" + "dsrl32 $t3, $a0, 0\n" + "sw $t3, 8($at) # 0x8\n"; DriverStr(expected, "StoreToOffset"); } @@ -2124,57 +2156,42 @@ TEST_F(AssemblerMIPS64Test, StoreFpuToOffset) { "swc1 $f0, 4($a0)\n" "swc1 $f0, 256($a0)\n" "swc1 $f0, 0x7FFC($a0)\n" - "ori $at, $zero, 0x8000\n" - "daddu $at, $at, $a0\n" - "swc1 $f0, 0($at)\n" - "ori $at, $zero, 0x8000\n" - "daddu $at, $at, $a0\n" - "swc1 $f0, 4($at)\n" - "lui $at, 1\n" - "daddu $at, $at, $a0\n" - "swc1 $f0, 0($at)\n" - "lui $at, 0x1234\n" - "ori $at, 0x5678\n" - "daddu $at, $at, $a0\n" + "daddiu $at, $a0, 32760 # 0x7FF8\n" + "swc1 $f0, 8($at)\n" + "daddiu $at, $a0, 32760 # 0x7FF8\n" + "swc1 $f0, 12($at)\n" + "daui $at, $a0, 1\n" "swc1 $f0, 0($at)\n" + "daui $at, $a0, 4660 # 0x1234\n" + "swc1 $f0, 22136($at) # 0x5678\n" "swc1 $f0, -256($a0)\n" "swc1 $f0, -32768($a0)\n" - "lui $at, 0xABCD\n" - "ori $at, 0xEF00\n" - "daddu $at, $at, $a0\n" - "swc1 $f0, 0($at)\n" + "daui $at, $a0, 0xABCE\n" + "swc1 $f0, -0x1100($at)\n" "sdc1 $f0, 0($a0)\n" "mfhc1 $t3, $f0\n" "swc1 $f0, 4($a0)\n" "sw $t3, 8($a0)\n" "sdc1 $f0, 256($a0)\n" - "ori $at, $zero, 0x7FF8\n" - "daddu $at, $at, $a0\n" + "daddiu $at, $a0, 32760 # 0x7FF8\n" "mfhc1 $t3, $f0\n" "swc1 $f0, 4($at)\n" "sw $t3, 8($at)\n" - "ori $at, $zero, 0x8000\n" - "daddu $at, $at, $a0\n" - "sdc1 $f0, 0($at)\n" - "ori $at, $zero, 0x8000\n" - "daddu $at, $at, $a0\n" + "daddiu $at, $a0, 32760 # 0x7FF8\n" + "sdc1 $f0, 8($at)\n" + "daddiu $at, $a0, 32760 # 0x7FF8\n" "mfhc1 $t3, $f0\n" - "swc1 $f0, 4($at)\n" - "sw $t3, 8($at)\n" - "lui $at, 1\n" - "daddu $at, $at, $a0\n" - "sdc1 $f0, 0($at)\n" - "lui $at, 0x1234\n" - "ori $at, 0x5678\n" - "daddu $at, $at, $a0\n" + "swc1 $f0, 12($at)\n" + "sw $t3, 16($at)\n" + "daui $at, $a0, 1\n" "sdc1 $f0, 0($at)\n" + "daui $at, $a0, 4660 # 0x1234\n" + "sdc1 $f0, 22136($at) # 0x5678\n" "sdc1 $f0, -256($a0)\n" "sdc1 $f0, -32768($a0)\n" - "lui $at, 0xABCD\n" - "ori $at, 0xEF00\n" - "daddu $at, $at, $a0\n" - "sdc1 $f0, 0($at)\n"; + "daui $at, $a0, 0xABCE\n" + "sdc1 $f0, -0x1100($at)\n"; DriverStr(expected, "StoreFpuToOffset"); } @@ -2234,24 +2251,18 @@ TEST_F(AssemblerMIPS64Test, StoreConstToOffset) { "lui $at,0x1234\n" "ori $at, $at, 0x5678\n" "sw $at, 0($t8)\n" - "lui $at, 0xffff\n" - "ori $at, $at, 0x10\n" - "daddu $at, $at, $a1\n" - "sw $zero, 0($at)\n" - "li $at, 0xfff0\n" - "daddu $at, $at, $a1\n" - "lui $t8, 0x1234\n" - "ori $t8, $t8, 0x5678\n" - "sw $t8, 0($at)\n" - "lui $at, 0xffff\n" - "ori $at, $at, 0x10\n" - "daddu $at, $at, $t8\n" - "sw $zero, 0($at)\n" - "li $at, 0xfff0\n" - "daddu $at, $at, $t8\n" - "lui $t8, 0x1234\n" - "ori $t8, $t8, 0x5678\n" - "sw $t8, 0($at)\n"; + "daddiu $at, $a1, -32760 # 0x8008\n" + "sw $zero, -32760($at) # 0x8008\n" + "daddiu $at, $a1, 32760 # 0x7FF8\n" + "lui $t8, 4660 # 0x1234\n" + "ori $t8, $t8, 22136 # 0x5678\n" + "sw $t8, 32760($at) # 0x7FF8\n" + "daddiu $at, $t8, -32760 # 0x8008\n" + "sw $zero, -32760($at) # 0x8008\n" + "daddiu $at, $t8, 32760 # 0x7FF8\n" + "lui $t8, 4660 # 0x1234\n" + "ori $t8, $t8, 22136 # 0x5678\n" + "sw $t8, 32760($at) # 0x7FF8\n"; DriverStr(expected, "StoreConstToOffset"); } ////////////////////////////// |