Add assembly operations with constants in optimizing compiler.

Change-Id: I5bcc35ab50d4457186effef5592a75d7f4e5b65f
diff --git a/compiler/utils/arm/assembler_arm.cc b/compiler/utils/arm/assembler_arm.cc
index 5fe8246..671ccb6 100644
--- a/compiler/utils/arm/assembler_arm.cc
+++ b/compiler/utils/arm/assembler_arm.cc
@@ -73,6 +73,11 @@
   return os;
 }
 
+ShifterOperand::ShifterOperand(uint32_t immed)
+    : type_(kImmediate), rm_(kNoRegister), rs_(kNoRegister),
+      is_rotate_(false), is_shift_(false), shift_(kNoShift), rotate_(0), immed_(immed) {
+  CHECK(immed < (1u << 12) || ArmAssembler::ModifiedImmediate(immed) != kInvalidModifiedImmediate);
+}
 
 
 uint32_t ShifterOperand::encodingArm() const {
diff --git a/compiler/utils/arm/assembler_arm.h b/compiler/utils/arm/assembler_arm.h
index be19174..54965f6 100644
--- a/compiler/utils/arm/assembler_arm.h
+++ b/compiler/utils/arm/assembler_arm.h
@@ -35,9 +35,7 @@
       is_rotate_(false), is_shift_(false), shift_(kNoShift), rotate_(0), immed_(0) {
   }
 
-  explicit ShifterOperand(uint32_t immed) : type_(kImmediate), rm_(kNoRegister), rs_(kNoRegister),
-      is_rotate_(false), is_shift_(false), shift_(kNoShift), rotate_(0), immed_(immed) {
-  }
+  explicit ShifterOperand(uint32_t immed);
 
   // Data-processing operands - Register
   explicit ShifterOperand(Register rm) : type_(kRegister), rm_(rm), rs_(kNoRegister),
diff --git a/compiler/utils/arm/assembler_thumb2.cc b/compiler/utils/arm/assembler_thumb2.cc
index 2ce4fd2..c693ec0 100644
--- a/compiler/utils/arm/assembler_thumb2.cc
+++ b/compiler/utils/arm/assembler_thumb2.cc
@@ -619,7 +619,8 @@
     return true;
   }
 
-  bool can_contain_high_register = opcode == MOV || opcode == ADD || opcode == SUB;
+  bool can_contain_high_register = (opcode == MOV)
+      || ((opcode == ADD || opcode == SUB) && (rn == rd));
 
   if (IsHighRegister(rd) || IsHighRegister(rn)) {
     if (can_contain_high_register) {
@@ -757,23 +758,21 @@
   int32_t encoding = 0;
   if (so.IsImmediate()) {
     // Check special cases.
-    if ((opcode == SUB || opcode == ADD) && rn == SP) {
-      // There are special ADD/SUB rd, SP, #imm12 instructions.
+    if ((opcode == SUB || opcode == ADD) && (so.GetImmediate() < (1u << 12))) {
       if (opcode == SUB) {
         thumb_opcode = 0b0101;
       } else {
         thumb_opcode = 0;
       }
       uint32_t imm = so.GetImmediate();
-      CHECK_LT(imm, (1u << 12));
 
       uint32_t i = (imm >> 11) & 1;
       uint32_t imm3 = (imm >> 8) & 0b111;
       uint32_t imm8 = imm & 0xff;
 
       encoding = B31 | B30 | B29 | B28 | B25 |
-           B19 | B18 | B16 |
            thumb_opcode << 21 |
+           rn << 16 |
            rd << 8 |
            i << 26 |
            imm3 << 12 |
@@ -882,7 +881,12 @@
         }
 
         break;
-      case CMN: thumb_opcode = 0b1011; rn = so.GetRegister(); break;
+      case CMN: {
+        thumb_opcode = 0b1011;
+        rd = rn;
+        rn = so.GetRegister();
+        break;
+      }
       case ORR: thumb_opcode = 0b1100; break;
       case MOV:
         dp_opcode = 0;
diff --git a/compiler/utils/assembler_thumb_test.cc b/compiler/utils/assembler_thumb_test.cc
index 68cb656..25928da 100644
--- a/compiler/utils/assembler_thumb_test.cc
+++ b/compiler/utils/assembler_thumb_test.cc
@@ -14,7 +14,10 @@
  * limitations under the License.
  */
 
+#include <dirent.h>
 #include <fstream>
+#include <sys/types.h>
+#include <map>
 
 #include "gtest/gtest.h"
 #include "utils/arm/assembler_thumb2.h"
@@ -40,6 +43,8 @@
 static constexpr bool kPrintResults = false;
 #endif
 
+static const char* TOOL_PREFIX = "arm-linux-androideabi-";
+
 void SetAndroidData() {
   const char* data = getenv("ANDROID_DATA");
   if (data == nullptr) {
@@ -109,9 +114,9 @@
   // Suffix on toolsdir will be something like "arm-eabi-4.8"
   while ((entry = readdir(dir)) != nullptr) {
     std::string subdir = toolsdir + std::string("/") + std::string(entry->d_name);
-    size_t eabi = subdir.find("arm-eabi-");
+    size_t eabi = subdir.find(TOOL_PREFIX);
     if (eabi != std::string::npos) {
-      std::string suffix = subdir.substr(eabi + sizeof("arm-eabi-"));
+      std::string suffix = subdir.substr(eabi + sizeof(TOOL_PREFIX));
       double version = strtod(suffix.c_str(), nullptr);
       if (version > maxversion) {
         maxversion = version;
@@ -169,19 +174,19 @@
   char cmd[256];
 
   // Assemble the .S
-  snprintf(cmd, sizeof(cmd), "%sarm-eabi-as %s -o %s.o", toolsdir.c_str(), filename, filename);
+  snprintf(cmd, sizeof(cmd), "%s%sas %s -o %s.o", toolsdir.c_str(), TOOL_PREFIX, filename, filename);
   system(cmd);
 
   // Remove the $d symbols to prevent the disassembler dumping the instructions
   // as .word
-  snprintf(cmd, sizeof(cmd), "%sarm-eabi-objcopy -N '$d' %s.o %s.oo", toolsdir.c_str(),
+  snprintf(cmd, sizeof(cmd), "%s%sobjcopy -N '$d' %s.o %s.oo", toolsdir.c_str(), TOOL_PREFIX,
     filename, filename);
   system(cmd);
 
   // Disassemble.
 
-  snprintf(cmd, sizeof(cmd), "%sarm-eabi-objdump -d %s.oo | grep '^  *[0-9a-f][0-9a-f]*:'",
-    toolsdir.c_str(), filename);
+  snprintf(cmd, sizeof(cmd), "%s%sobjdump -d %s.oo | grep '^  *[0-9a-f][0-9a-f]*:'",
+    toolsdir.c_str(), TOOL_PREFIX, filename);
   if (kPrintResults) {
     // Print the results only, don't check. This is used to generate new output for inserting
     // into the .inc file.
diff --git a/compiler/utils/assembler_thumb_test_expected.cc.inc b/compiler/utils/assembler_thumb_test_expected.cc.inc
index 3943e37..18035f3 100644
--- a/compiler/utils/assembler_thumb_test_expected.cc.inc
+++ b/compiler/utils/assembler_thumb_test_expected.cc.inc
@@ -48,8 +48,8 @@
 const char* DataProcessingImmediateResults[] = {
   "   0:	2055      	movs	r0, #85	; 0x55\n",
   "   2:	f06f 0055 	mvn.w	r0, #85	; 0x55\n",
-  "   6:	f101 0055 	add.w	r0, r1, #85	; 0x55\n",
-  "   a:	f1a1 0055 	sub.w	r0, r1, #85	; 0x55\n",
+  "   6:	f201 0055 	addw	r0, r1, #85	; 0x55\n",
+  "   a:	f2a1 0055 	subw	r0, r1, #85	; 0x55\n",
   "   e:	f001 0055 	and.w	r0, r1, #85	; 0x55\n",
   "  12:	f041 0055 	orr.w	r0, r1, #85	; 0x55\n",
   "  16:	f081 0055 	eor.w	r0, r1, #85	; 0x55\n",
diff --git a/compiler/utils/x86_64/assembler_x86_64.cc b/compiler/utils/x86_64/assembler_x86_64.cc
index 78738d8..fe9349b 100644
--- a/compiler/utils/x86_64/assembler_x86_64.cc
+++ b/compiler/utils/x86_64/assembler_x86_64.cc
@@ -869,6 +869,22 @@
 }
 
 
+void X86_64Assembler::cmpq(CpuRegister reg, const Immediate& imm) {
+  AssemblerBuffer::EnsureCapacity ensured(&buffer_);
+  CHECK(imm.is_int32());  // cmpq only supports 32b immediate.
+  EmitRex64(reg);
+  EmitComplex(7, Operand(reg), imm);
+}
+
+
+void X86_64Assembler::cmpq(CpuRegister reg, const Address& address) {
+  AssemblerBuffer::EnsureCapacity ensured(&buffer_);
+  EmitRex64(reg);
+  EmitUint8(0x3B);
+  EmitOperand(reg.LowBits(), address);
+}
+
+
 void X86_64Assembler::addl(CpuRegister dst, CpuRegister src) {
   AssemblerBuffer::EnsureCapacity ensured(&buffer_);
   EmitOptionalRex32(dst, src);
@@ -1063,6 +1079,14 @@
 }
 
 
+void X86_64Assembler::addq(CpuRegister dst, const Address& address) {
+  AssemblerBuffer::EnsureCapacity ensured(&buffer_);
+  EmitRex64(dst);
+  EmitUint8(0x03);
+  EmitOperand(dst.LowBits(), address);
+}
+
+
 void X86_64Assembler::addq(CpuRegister dst, CpuRegister src) {
   AssemblerBuffer::EnsureCapacity ensured(&buffer_);
   // 0x01 is addq r/m64 <- r/m64 + r64, with op1 in r/m and op2 in reg: so reverse EmitRex64
@@ -1118,6 +1142,14 @@
 }
 
 
+void X86_64Assembler::subq(CpuRegister reg, const Address& address) {
+  AssemblerBuffer::EnsureCapacity ensured(&buffer_);
+  EmitRex64(reg);
+  EmitUint8(0x2B);
+  EmitOperand(reg.LowBits() & 7, address);
+}
+
+
 void X86_64Assembler::subl(CpuRegister reg, const Address& address) {
   AssemblerBuffer::EnsureCapacity ensured(&buffer_);
   EmitOptionalRex32(reg, address);
diff --git a/compiler/utils/x86_64/assembler_x86_64.h b/compiler/utils/x86_64/assembler_x86_64.h
index 7514854..330d2d5 100644
--- a/compiler/utils/x86_64/assembler_x86_64.h
+++ b/compiler/utils/x86_64/assembler_x86_64.h
@@ -385,6 +385,8 @@
   void cmpl(const Address& address, const Immediate& imm);
 
   void cmpq(CpuRegister reg0, CpuRegister reg1);
+  void cmpq(CpuRegister reg0, const Immediate& imm);
+  void cmpq(CpuRegister reg0, const Address& address);
 
   void testl(CpuRegister reg1, CpuRegister reg2);
   void testl(CpuRegister reg, const Immediate& imm);
@@ -408,6 +410,7 @@
 
   void addq(CpuRegister reg, const Immediate& imm);
   void addq(CpuRegister dst, CpuRegister src);
+  void addq(CpuRegister dst, const Address& address);
 
   void subl(CpuRegister dst, CpuRegister src);
   void subl(CpuRegister reg, const Immediate& imm);
@@ -415,6 +418,7 @@
 
   void subq(CpuRegister reg, const Immediate& imm);
   void subq(CpuRegister dst, CpuRegister src);
+  void subq(CpuRegister dst, const Address& address);
 
   void cdq();