[optimizing compiler] Add DIV_LONG

- for backends: arm, x86, x86_64
- added cqo, idivq, testq assembly for x64_64
- small cleanups

Change-Id: I762ef37880749038ed25d6014370be9a61795200
diff --git a/compiler/optimizing/builder.cc b/compiler/optimizing/builder.cc
index a3ca061..4e2f1cd 100644
--- a/compiler/optimizing/builder.cc
+++ b/compiler/optimizing/builder.cc
@@ -295,6 +295,16 @@
 }
 
 template<typename T>
+void HGraphBuilder::Binop_23x(const Instruction& instruction,
+                              Primitive::Type type,
+                              uint32_t dex_pc) {
+  HInstruction* first = LoadLocal(instruction.VRegB(), type);
+  HInstruction* second = LoadLocal(instruction.VRegC(), type);
+  current_block_->AddInstruction(new (arena_) T(type, first, second, dex_pc));
+  UpdateLocal(instruction.VRegA(), current_block_->GetLastInstruction());
+}
+
+template<typename T>
 void HGraphBuilder::Binop_12x(const Instruction& instruction, Primitive::Type type) {
   HInstruction* first = LoadLocal(instruction.VRegA(), type);
   HInstruction* second = LoadLocal(instruction.VRegB(), type);
@@ -303,6 +313,16 @@
 }
 
 template<typename T>
+void HGraphBuilder::Binop_12x(const Instruction& instruction,
+                              Primitive::Type type,
+                              uint32_t dex_pc) {
+  HInstruction* first = LoadLocal(instruction.VRegA(), type);
+  HInstruction* second = LoadLocal(instruction.VRegB(), type);
+  current_block_->AddInstruction(new (arena_) T(type, first, second, dex_pc));
+  UpdateLocal(instruction.VRegA(), current_block_->GetLastInstruction());
+}
+
+template<typename T>
 void HGraphBuilder::Binop_22s(const Instruction& instruction, bool reverse) {
   HInstruction* first = LoadLocal(instruction.VRegB(), Primitive::kPrimInt);
   HInstruction* second = GetIntConstant(instruction.VRegC_22s());
@@ -548,25 +568,37 @@
   return true;
 }
 
-void HGraphBuilder::BuildCheckedDiv(uint16_t out_reg,
-                                    uint16_t first_reg,
-                                    int32_t second_reg,
-                                    uint32_t dex_offset,
+void HGraphBuilder::BuildCheckedDiv(uint16_t out_vreg,
+                                    uint16_t first_vreg,
+                                    int64_t second_vreg_or_constant,
+                                    uint32_t dex_pc,
                                     Primitive::Type type,
-                                    bool second_is_lit) {
-  DCHECK(type == Primitive::kPrimInt);
+                                    bool second_is_constant) {
+  DCHECK(type == Primitive::kPrimInt || type == Primitive::kPrimLong);
 
-  HInstruction* first = LoadLocal(first_reg, type);
-  HInstruction* second = second_is_lit ? GetIntConstant(second_reg) : LoadLocal(second_reg, type);
-  if (!second->IsIntConstant() || (second->AsIntConstant()->GetValue() == 0)) {
-    second = new (arena_) HDivZeroCheck(second, dex_offset);
+  HInstruction* first = LoadLocal(first_vreg, type);
+  HInstruction* second = nullptr;
+  if (second_is_constant) {
+    if (type == Primitive::kPrimInt) {
+      second = GetIntConstant(second_vreg_or_constant);
+    } else {
+      second = GetLongConstant(second_vreg_or_constant);
+    }
+  } else {
+    second = LoadLocal(second_vreg_or_constant, type);
+  }
+
+  if (!second_is_constant
+      || (type == Primitive::kPrimInt && second->AsIntConstant()->GetValue() == 0)
+      || (type == Primitive::kPrimLong && second->AsLongConstant()->GetValue() == 0)) {
+    second = new (arena_) HDivZeroCheck(second, dex_pc);
     Temporaries temps(graph_);
     current_block_->AddInstruction(second);
     temps.Add(current_block_->GetLastInstruction());
   }
 
-  current_block_->AddInstruction(new (arena_) HDiv(type, first, second));
-  UpdateLocal(out_reg, current_block_->GetLastInstruction());
+  current_block_->AddInstruction(new (arena_) HDiv(type, first, second, dex_pc));
+  UpdateLocal(out_vreg, current_block_->GetLastInstruction());
 }
 
 void HGraphBuilder::BuildArrayAccess(const Instruction& instruction,
@@ -1041,13 +1073,19 @@
       break;
     }
 
+    case Instruction::DIV_LONG: {
+      BuildCheckedDiv(instruction.VRegA(), instruction.VRegB(), instruction.VRegC(),
+                      dex_offset, Primitive::kPrimLong, false);
+      break;
+    }
+
     case Instruction::DIV_FLOAT: {
-      Binop_23x<HDiv>(instruction, Primitive::kPrimFloat);
+      Binop_23x<HDiv>(instruction, Primitive::kPrimFloat, dex_offset);
       break;
     }
 
     case Instruction::DIV_DOUBLE: {
-      Binop_23x<HDiv>(instruction, Primitive::kPrimDouble);
+      Binop_23x<HDiv>(instruction, Primitive::kPrimDouble, dex_offset);
       break;
     }
 
@@ -1142,13 +1180,19 @@
       break;
     }
 
+    case Instruction::DIV_LONG_2ADDR: {
+      BuildCheckedDiv(instruction.VRegA(), instruction.VRegA(), instruction.VRegB(),
+                      dex_offset, Primitive::kPrimLong, false);
+      break;
+    }
+
     case Instruction::DIV_FLOAT_2ADDR: {
-      Binop_12x<HDiv>(instruction, Primitive::kPrimFloat);
+      Binop_12x<HDiv>(instruction, Primitive::kPrimFloat, dex_offset);
       break;
     }
 
     case Instruction::DIV_DOUBLE_2ADDR: {
-      Binop_12x<HDiv>(instruction, Primitive::kPrimDouble);
+      Binop_12x<HDiv>(instruction, Primitive::kPrimDouble, dex_offset);
       break;
     }