OSDN Git Service

MIPS64: Adjust Base and Offset
authorChris Larsen <chris.larsen@imgtec.com>
Thu, 15 Dec 2016 19:44:14 +0000 (11:44 -0800)
committerChris Larsen <chris.larsen@imgtec.com>
Thu, 16 Mar 2017 21:40:13 +0000 (14:40 -0700)
Minimize the number of statements needed to load/store data at an
arbitrary offset from a base register.

Test: test-art-host-gtest
Test: ART_TEST_OPTIMIZING=true test-art-target-run-test

Change-Id: I76cc4b715dbb5b41c76b3c537fbd62bae8409bc0

compiler/utils/mips64/assembler_mips64.cc
compiler/utils/mips64/assembler_mips64.h
compiler/utils/mips64/assembler_mips64_test.cc

index 39eb589..c410365 100644 (file)
@@ -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,
index b98db65..2c5072e 100644 (file)
@@ -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:
index 879807a..e5d3605 100644 (file)
@@ -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");
 }
 //////////////////////////////