MIPS64: Adjust Base and Offset

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
diff --git a/compiler/utils/mips64/assembler_mips64_test.cc b/compiler/utils/mips64/assembler_mips64_test.cc
index 879807a..e5d3605 100644
--- a/compiler/utils/mips64/assembler_mips64_test.cc
+++ b/compiler/utils/mips64/assembler_mips64_test.cc
@@ -1560,6 +1560,10 @@
   __ 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 @@
   __ 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 @@
   __ 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 @@
   __ 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 @@
   __ 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 @@
   __ 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 @@
   __ 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 @@
       "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"
+      "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"
-      "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"
-      "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 @@
       "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"
+      "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"
-      "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"
-      "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 @@
       "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"
+      "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"
-      "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"
-      "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 @@
       "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"
+      "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"
-      "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"
-      "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 @@
       "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"
+      "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"
-      "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"
-      "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 @@
       "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"
+      "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"
-      "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"
-      "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"
+      "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"
-      "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"
-      "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 @@
       "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"
+      "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"
-      "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"
-      "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"
+      "daui $at, $a0, 1\n"
       "ldc1 $f0, 0($at)\n"
-      "lui $at, 0x1234\n"
-      "ori $at, 0x5678\n"
-      "daddu $at, $at, $a0\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 @@
   __ 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 @@
       "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"
+      "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"
-      "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"
-      "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 @@
       "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"
+      "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"
-      "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"
-      "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 @@
       "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"
+      "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"
-      "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"
-      "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 @@
       "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"
+      "sw $t3, 16($at)\n"
+      "daui $at, $a1, 1\n"
       "sd $a0, 0($at)\n"
-      "lui $at, 0x1234\n"
-      "ori $at, 0x5678\n"
-      "daddu $at, $at, $a1\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 @@
       "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"
+      "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"
-      "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"
-      "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"
+      "swc1 $f0, 12($at)\n"
+      "sw $t3, 16($at)\n"
+      "daui $at, $a0, 1\n"
       "sdc1 $f0, 0($at)\n"
-      "lui $at, 0x1234\n"
-      "ori $at, 0x5678\n"
-      "daddu $at, $at, $a0\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 @@
       "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");
 }
 //////////////////////////////