Long support in optimizing compiler.

- Add stack locations to the Location class.
- Change logic of parameter passing/setup by setting the
  location of such instructions the ones for the calling
  convention.

Change-Id: I4730ad58732813dcb9c238f44f55dfc0baa18799
diff --git a/compiler/optimizing/code_generator_arm.cc b/compiler/optimizing/code_generator_arm.cc
index 4e88765..fe61333 100644
--- a/compiler/optimizing/code_generator_arm.cc
+++ b/compiler/optimizing/code_generator_arm.cc
@@ -17,6 +17,7 @@
 #include "code_generator_arm.h"
 #include "utils/assembler.h"
 #include "utils/arm/assembler_arm.h"
+#include "utils/arm/managed_register_arm.h"
 
 #include "mirror/array.h"
 #include "mirror/art_method.h"
@@ -24,11 +25,20 @@
 #define __ reinterpret_cast<ArmAssembler*>(GetAssembler())->
 
 namespace art {
+
+arm::ArmManagedRegister Location::AsArm() const {
+  return reg().AsArm();
+}
+
 namespace arm {
 
 static constexpr int kNumberOfPushedRegistersAtEntry = 1;
 static constexpr int kCurrentMethodStackOffset = 0;
 
+static Location ArmCoreLocation(Register reg) {
+  return Location::RegisterLocation(ArmManagedRegister::FromCoreRegister(reg));
+}
+
 InstructionCodeGeneratorARM::InstructionCodeGeneratorARM(HGraph* graph, CodeGeneratorARM* codegen)
       : HGraphVisitor(graph),
         assembler_(codegen->GetAssembler()),
@@ -73,18 +83,171 @@
   }
 }
 
+static constexpr Register kParameterCoreRegisters[] = { R1, R2, R3 };
+static constexpr RegisterPair kParameterCorePairRegisters[] = { R1_R2, R2_R3 };
+static constexpr size_t kParameterCoreRegistersLength = arraysize(kParameterCoreRegisters);
+
+class InvokeDexCallingConvention : public CallingConvention<Register> {
+ public:
+  InvokeDexCallingConvention()
+      : CallingConvention(kParameterCoreRegisters, kParameterCoreRegistersLength) {}
+
+  RegisterPair GetRegisterPairAt(size_t argument_index) {
+    DCHECK_LT(argument_index + 1, GetNumberOfRegisters());
+    return kParameterCorePairRegisters[argument_index];
+  }
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(InvokeDexCallingConvention);
+};
+
+void CodeGeneratorARM::Move32(Location destination, Location source) {
+  if (source.Equals(destination)) {
+    return;
+  }
+  if (destination.IsRegister()) {
+    if (source.IsRegister()) {
+      __ Mov(destination.AsArm().AsCoreRegister(), source.AsArm().AsCoreRegister());
+    } else {
+      __ ldr(destination.AsArm().AsCoreRegister(), Address(SP, source.GetStackIndex()));
+    }
+  } else {
+    DCHECK(destination.IsStackSlot());
+    if (source.IsRegister()) {
+      __ str(source.AsArm().AsCoreRegister(), Address(SP, destination.GetStackIndex()));
+    } else {
+      __ ldr(R0, Address(SP, source.GetStackIndex()));
+      __ str(R0, Address(SP, destination.GetStackIndex()));
+    }
+  }
+}
+
+void CodeGeneratorARM::Move64(Location destination, Location source) {
+  if (source.Equals(destination)) {
+    return;
+  }
+  if (destination.IsRegister()) {
+    if (source.IsRegister()) {
+      __ Mov(destination.AsArm().AsRegisterPairLow(), source.AsArm().AsRegisterPairLow());
+      __ Mov(destination.AsArm().AsRegisterPairHigh(), source.AsArm().AsRegisterPairHigh());
+    } else if (source.IsQuickParameter()) {
+      uint32_t argument_index = source.GetQuickParameterIndex();
+      InvokeDexCallingConvention calling_convention;
+      __ Mov(destination.AsArm().AsRegisterPairLow(),
+             calling_convention.GetRegisterAt(argument_index));
+      __ ldr(destination.AsArm().AsRegisterPairHigh(),
+             Address(SP, calling_convention.GetStackOffsetOf(argument_index + 1) + GetFrameSize()));
+    } else {
+      DCHECK(source.IsDoubleStackSlot());
+      if (destination.AsArm().AsRegisterPair() == R1_R2) {
+        __ ldr(R1, Address(SP, source.GetStackIndex()));
+        __ ldr(R2, Address(SP, source.GetHighStackIndex(kArmWordSize)));
+      } else {
+        __ LoadFromOffset(kLoadWordPair, destination.AsArm().AsRegisterPairLow(),
+                          SP, source.GetStackIndex());
+      }
+    }
+  } else if (destination.IsQuickParameter()) {
+    InvokeDexCallingConvention calling_convention;
+    uint32_t argument_index = destination.GetQuickParameterIndex();
+    if (source.IsRegister()) {
+      __ Mov(calling_convention.GetRegisterAt(argument_index), source.AsArm().AsRegisterPairLow());
+      __ str(source.AsArm().AsRegisterPairHigh(),
+             Address(SP, calling_convention.GetStackOffsetOf(argument_index + 1)));
+    } else {
+      DCHECK(source.IsDoubleStackSlot());
+      __ ldr(calling_convention.GetRegisterAt(argument_index), Address(SP, source.GetStackIndex()));
+      __ ldr(R0, Address(SP, source.GetHighStackIndex(kArmWordSize)));
+      __ str(R0, Address(SP, calling_convention.GetStackOffsetOf(argument_index + 1)));
+    }
+  } else {
+    DCHECK(destination.IsDoubleStackSlot());
+    if (source.IsRegister()) {
+      if (source.AsArm().AsRegisterPair() == R1_R2) {
+        __ str(R1, Address(SP, destination.GetStackIndex()));
+        __ str(R2, Address(SP, destination.GetHighStackIndex(kArmWordSize)));
+      } else {
+        __ StoreToOffset(kStoreWordPair, source.AsArm().AsRegisterPairLow(),
+                         SP, destination.GetStackIndex());
+      }
+    } else if (source.IsQuickParameter()) {
+      InvokeDexCallingConvention calling_convention;
+      uint32_t argument_index = source.GetQuickParameterIndex();
+      __ str(calling_convention.GetRegisterAt(argument_index),
+             Address(SP, destination.GetStackIndex()));
+      __ ldr(R0,
+             Address(SP, calling_convention.GetStackOffsetOf(argument_index + 1) + GetFrameSize()));
+      __ str(R0, Address(SP, destination.GetHighStackIndex(kArmWordSize)));
+    } else {
+      DCHECK(source.IsDoubleStackSlot());
+      __ ldr(R0, Address(SP, source.GetStackIndex()));
+      __ str(R0, Address(SP, destination.GetStackIndex()));
+      __ ldr(R0, Address(SP, source.GetHighStackIndex(kArmWordSize)));
+      __ str(R0, Address(SP, destination.GetHighStackIndex(kArmWordSize)));
+    }
+  }
+}
+
 void CodeGeneratorARM::Move(HInstruction* instruction, Location location, HInstruction* move_for) {
   if (instruction->AsIntConstant() != nullptr) {
-    __ LoadImmediate(location.reg<Register>(), instruction->AsIntConstant()->GetValue());
+    int32_t value = instruction->AsIntConstant()->GetValue();
+    if (location.IsRegister()) {
+      __ LoadImmediate(location.AsArm().AsCoreRegister(), value);
+    } else {
+      __ LoadImmediate(R0, value);
+      __ str(R0, Address(SP, location.GetStackIndex()));
+    }
+  } else if (instruction->AsLongConstant() != nullptr) {
+    int64_t value = instruction->AsLongConstant()->GetValue();
+    if (location.IsRegister()) {
+      __ LoadImmediate(location.AsArm().AsRegisterPairLow(), Low32Bits(value));
+      __ LoadImmediate(location.AsArm().AsRegisterPairHigh(), High32Bits(value));
+    } else {
+      __ LoadImmediate(R0, Low32Bits(value));
+      __ str(R0, Address(SP, location.GetStackIndex()));
+      __ LoadImmediate(R0, High32Bits(value));
+      __ str(R0, Address(SP, location.GetHighStackIndex(kArmWordSize)));
+    }
   } else if (instruction->AsLoadLocal() != nullptr) {
-    __ LoadFromOffset(kLoadWord, location.reg<Register>(),
-                      SP, GetStackSlot(instruction->AsLoadLocal()->GetLocal()));
+    uint32_t stack_slot = GetStackSlot(instruction->AsLoadLocal()->GetLocal());
+    switch (instruction->GetType()) {
+      case Primitive::kPrimBoolean:
+      case Primitive::kPrimByte:
+      case Primitive::kPrimChar:
+      case Primitive::kPrimShort:
+      case Primitive::kPrimInt:
+      case Primitive::kPrimNot:
+        Move32(location, Location::StackSlot(stack_slot));
+        break;
+
+      case Primitive::kPrimLong:
+        Move64(location, Location::DoubleStackSlot(stack_slot));
+        break;
+
+      default:
+        LOG(FATAL) << "Unimplemented type " << instruction->GetType();
+    }
   } else {
     // This can currently only happen when the instruction that requests the move
     // is the next to be compiled.
     DCHECK_EQ(instruction->GetNext(), move_for);
-    __ mov(location.reg<Register>(),
-           ShifterOperand(instruction->GetLocations()->Out().reg<Register>()));
+    switch (instruction->GetType()) {
+      case Primitive::kPrimBoolean:
+      case Primitive::kPrimByte:
+      case Primitive::kPrimChar:
+      case Primitive::kPrimShort:
+      case Primitive::kPrimNot:
+      case Primitive::kPrimInt:
+        Move32(location, instruction->GetLocations()->Out());
+        break;
+
+      case Primitive::kPrimLong:
+        Move64(location, instruction->GetLocations()->Out());
+        break;
+
+      default:
+        LOG(FATAL) << "Unimplemented type " << instruction->GetType();
+    }
   }
 }
 
@@ -114,13 +277,13 @@
 
 void LocationsBuilderARM::VisitIf(HIf* if_instr) {
   LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(if_instr);
-  locations->SetInAt(0, Location(R0));
+  locations->SetInAt(0, ArmCoreLocation(R0));
   if_instr->SetLocations(locations);
 }
 
 void InstructionCodeGeneratorARM::VisitIf(HIf* if_instr) {
   // TODO: Generate the input as a condition, instead of materializing in a register.
-  __ cmp(if_instr->GetLocations()->InAt(0).reg<Register>(), ShifterOperand(0));
+  __ cmp(if_instr->GetLocations()->InAt(0).AsArm().AsCoreRegister(), ShifterOperand(0));
   __ b(codegen_->GetLabelOf(if_instr->IfFalseSuccessor()), EQ);
   if (!codegen_->GoesToNextBlock(if_instr->GetBlock(), if_instr->IfTrueSuccessor())) {
     __ b(codegen_->GetLabelOf(if_instr->IfTrueSuccessor()));
@@ -129,18 +292,18 @@
 
 void LocationsBuilderARM::VisitEqual(HEqual* equal) {
   LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(equal);
-  locations->SetInAt(0, Location(R0));
-  locations->SetInAt(1, Location(R1));
-  locations->SetOut(Location(R0));
+  locations->SetInAt(0, ArmCoreLocation(R0));
+  locations->SetInAt(1, ArmCoreLocation(R1));
+  locations->SetOut(ArmCoreLocation(R0));
   equal->SetLocations(locations);
 }
 
 void InstructionCodeGeneratorARM::VisitEqual(HEqual* equal) {
   LocationSummary* locations = equal->GetLocations();
-  __ teq(locations->InAt(0).reg<Register>(),
-         ShifterOperand(locations->InAt(1).reg<Register>()));
-  __ mov(locations->Out().reg<Register>(), ShifterOperand(1), EQ);
-  __ mov(locations->Out().reg<Register>(), ShifterOperand(0), NE);
+  __ teq(locations->InAt(0).AsArm().AsCoreRegister(),
+         ShifterOperand(locations->InAt(1).AsArm().AsCoreRegister()));
+  __ mov(locations->Out().AsArm().AsCoreRegister(), ShifterOperand(1), EQ);
+  __ mov(locations->Out().AsArm().AsCoreRegister(), ShifterOperand(0), NE);
 }
 
 void LocationsBuilderARM::VisitLocal(HLocal* local) {
@@ -161,14 +324,27 @@
 
 void LocationsBuilderARM::VisitStoreLocal(HStoreLocal* store) {
   LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(store);
-  locations->SetInAt(1, Location(R0));
+  switch (store->InputAt(1)->GetType()) {
+    case Primitive::kPrimBoolean:
+    case Primitive::kPrimByte:
+    case Primitive::kPrimChar:
+    case Primitive::kPrimShort:
+    case Primitive::kPrimInt:
+    case Primitive::kPrimNot:
+      locations->SetInAt(1, Location::StackSlot(codegen_->GetStackSlot(store->GetLocal())));
+      break;
+
+    case Primitive::kPrimLong:
+      locations->SetInAt(1, Location::DoubleStackSlot(codegen_->GetStackSlot(store->GetLocal())));
+      break;
+
+    default:
+      LOG(FATAL) << "Unimplemented local type " << store->InputAt(1)->GetType();
+  }
   store->SetLocations(locations);
 }
 
 void InstructionCodeGeneratorARM::VisitStoreLocal(HStoreLocal* store) {
-  LocationSummary* locations = store->GetLocations();
-  __ StoreToOffset(kStoreWord, locations->InAt(1).reg<Register>(),
-                   SP, codegen_->GetStackSlot(store->GetLocal()));
 }
 
 void LocationsBuilderARM::VisitIntConstant(HIntConstant* constant) {
@@ -179,6 +355,14 @@
   // Will be generated at use site.
 }
 
+void LocationsBuilderARM::VisitLongConstant(HLongConstant* constant) {
+  constant->SetLocations(nullptr);
+}
+
+void InstructionCodeGeneratorARM::VisitLongConstant(HLongConstant* constant) {
+  // Will be generated at use site.
+}
+
 void LocationsBuilderARM::VisitReturnVoid(HReturnVoid* ret) {
   ret->SetLocations(nullptr);
 }
@@ -189,56 +373,118 @@
 
 void LocationsBuilderARM::VisitReturn(HReturn* ret) {
   LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(ret);
-  locations->SetInAt(0, Location(R0));
+  switch (ret->InputAt(0)->GetType()) {
+    case Primitive::kPrimBoolean:
+    case Primitive::kPrimByte:
+    case Primitive::kPrimChar:
+    case Primitive::kPrimShort:
+    case Primitive::kPrimInt:
+    case Primitive::kPrimNot:
+      locations->SetInAt(0, ArmCoreLocation(R0));
+      break;
+
+    case Primitive::kPrimLong:
+      locations->SetInAt(0, Location::RegisterLocation(ArmManagedRegister::FromRegisterPair(R0_R1)));
+      break;
+
+    default:
+      LOG(FATAL) << "Unimplemented return type " << ret->InputAt(0)->GetType();
+  }
+
   ret->SetLocations(locations);
 }
 
 void InstructionCodeGeneratorARM::VisitReturn(HReturn* ret) {
-  DCHECK_EQ(ret->GetLocations()->InAt(0).reg<Register>(), R0);
+  if (kIsDebugBuild) {
+    switch (ret->InputAt(0)->GetType()) {
+      case Primitive::kPrimBoolean:
+      case Primitive::kPrimByte:
+      case Primitive::kPrimChar:
+      case Primitive::kPrimShort:
+      case Primitive::kPrimInt:
+      case Primitive::kPrimNot:
+        DCHECK_EQ(ret->GetLocations()->InAt(0).AsArm().AsCoreRegister(), R0);
+        break;
+
+      case Primitive::kPrimLong:
+        DCHECK_EQ(ret->GetLocations()->InAt(0).AsArm().AsRegisterPair(), R0_R1);
+        break;
+
+      default:
+        LOG(FATAL) << "Unimplemented return type " << ret->InputAt(0)->GetType();
+    }
+  }
   codegen_->GenerateFrameExit();
 }
 
-static constexpr Register kParameterCoreRegisters[] = { R1, R2, R3 };
-static constexpr size_t kParameterCoreRegistersLength = arraysize(kParameterCoreRegisters);
-
-class InvokeDexCallingConvention : public CallingConvention<Register> {
- public:
-  InvokeDexCallingConvention()
-      : CallingConvention(kParameterCoreRegisters, kParameterCoreRegistersLength) {}
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(InvokeDexCallingConvention);
-};
-
 void LocationsBuilderARM::VisitPushArgument(HPushArgument* argument) {
   LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(argument);
   InvokeDexCallingConvention calling_convention;
-  if (argument->GetArgumentIndex() < calling_convention.GetNumberOfRegisters()) {
-    Location location = Location(calling_convention.GetRegisterAt(argument->GetArgumentIndex()));
-    locations->SetInAt(0, location);
-    locations->SetOut(location);
-  } else {
-    locations->SetInAt(0, Location(R0));
+  uint32_t argument_index = argument->GetArgumentIndex();
+  switch (argument->InputAt(0)->GetType()) {
+    case Primitive::kPrimBoolean:
+    case Primitive::kPrimByte:
+    case Primitive::kPrimChar:
+    case Primitive::kPrimShort:
+    case Primitive::kPrimInt:
+    case Primitive::kPrimNot: {
+      if (argument_index < calling_convention.GetNumberOfRegisters()) {
+        locations->SetInAt(0, ArmCoreLocation(calling_convention.GetRegisterAt(argument_index)));
+      } else {
+        locations->SetInAt(
+            0, Location::StackSlot(calling_convention.GetStackOffsetOf(argument_index)));
+      }
+      break;
+    }
+    case Primitive::kPrimLong: {
+      if (argument_index + 1 < calling_convention.GetNumberOfRegisters()) {
+        Location location = Location::RegisterLocation(ArmManagedRegister::FromRegisterPair(
+            calling_convention.GetRegisterPairAt(argument_index)));
+        locations->SetInAt(0, location);
+      } else if (argument_index + 1 == calling_convention.GetNumberOfRegisters()) {
+        locations->SetInAt(0, Location::QuickParameter(argument_index));
+      } else {
+        locations->SetInAt(
+            0, Location::DoubleStackSlot(calling_convention.GetStackOffsetOf(argument_index)));
+      }
+      break;
+    }
+    default:
+      LOG(FATAL) << "Unimplemented argument type " << argument->InputAt(0)->GetType();
   }
   argument->SetLocations(locations);
 }
 
 void InstructionCodeGeneratorARM::VisitPushArgument(HPushArgument* argument) {
-  uint8_t argument_index = argument->GetArgumentIndex();
-  InvokeDexCallingConvention calling_convention;
-  size_t parameter_registers = calling_convention.GetNumberOfRegisters();
-  LocationSummary* locations = argument->GetLocations();
-  if (argument_index >= parameter_registers) {
-    uint8_t offset = calling_convention.GetStackOffsetOf(argument_index);
-    __ StoreToOffset(kStoreWord, locations->InAt(0).reg<Register>(), SP, offset);
-  } else {
-    DCHECK_EQ(locations->Out().reg<Register>(), locations->InAt(0).reg<Register>());
-  }
+  // Nothing to do.
 }
 
 void LocationsBuilderARM::VisitInvokeStatic(HInvokeStatic* invoke) {
   LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(invoke);
-  locations->AddTemp(Location(R0));
+  locations->AddTemp(ArmCoreLocation(R0));
+    switch (invoke->GetType()) {
+    case Primitive::kPrimBoolean:
+    case Primitive::kPrimByte:
+    case Primitive::kPrimChar:
+    case Primitive::kPrimShort:
+    case Primitive::kPrimInt:
+    case Primitive::kPrimNot:
+      locations->SetOut(ArmCoreLocation(R0));
+      break;
+
+    case Primitive::kPrimLong:
+      locations->SetOut(Location::RegisterLocation(ArmManagedRegister::FromRegisterPair(R0_R1)));
+      break;
+
+    case Primitive::kPrimVoid:
+      break;
+
+    case Primitive::kPrimDouble:
+    case Primitive::kPrimFloat:
+      LOG(FATAL) << "Unimplemented return type " << invoke->GetType();
+      break;
+  }
+
   invoke->SetLocations(locations);
 }
 
@@ -247,7 +493,7 @@
 }
 
 void InstructionCodeGeneratorARM::VisitInvokeStatic(HInvokeStatic* invoke) {
-  Register temp = invoke->GetLocations()->GetTemp(0).reg<Register>();
+  Register temp = invoke->GetLocations()->GetTemp(0).AsArm().AsCoreRegister();
   size_t index_in_cache = mirror::Array::DataOffset(sizeof(mirror::Object*)).Int32Value() +
       invoke->GetIndexInDexCache() * kArmWordSize;
 
@@ -277,13 +523,30 @@
   LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(add);
   switch (add->GetResultType()) {
     case Primitive::kPrimInt: {
-      locations->SetInAt(0, Location(R0));
-      locations->SetInAt(1, Location(R1));
-      locations->SetOut(Location(R0));
+      locations->SetInAt(0, ArmCoreLocation(R0));
+      locations->SetInAt(1, ArmCoreLocation(R1));
+      locations->SetOut(ArmCoreLocation(R0));
       break;
     }
+
+    case Primitive::kPrimLong: {
+      locations->SetInAt(
+          0, Location::RegisterLocation(ArmManagedRegister::FromRegisterPair(R0_R1)));
+      locations->SetInAt(
+          1, Location::RegisterLocation(ArmManagedRegister::FromRegisterPair(R2_R3)));
+      locations->SetOut(Location::RegisterLocation(ArmManagedRegister::FromRegisterPair(R0_R1)));
+      break;
+    }
+
+    case Primitive::kPrimBoolean:
+    case Primitive::kPrimByte:
+    case Primitive::kPrimChar:
+    case Primitive::kPrimShort:
+      LOG(FATAL) << "Unexpected add type " << add->GetResultType();
+      break;
+
     default:
-      LOG(FATAL) << "Unimplemented";
+      LOG(FATAL) << "Unimplemented add type " << add->GetResultType();
   }
   add->SetLocations(locations);
 }
@@ -292,12 +555,29 @@
   LocationSummary* locations = add->GetLocations();
   switch (add->GetResultType()) {
     case Primitive::kPrimInt:
-      __ add(locations->Out().reg<Register>(),
-             locations->InAt(0).reg<Register>(),
-             ShifterOperand(locations->InAt(1).reg<Register>()));
+      __ add(locations->Out().AsArm().AsCoreRegister(),
+             locations->InAt(0).AsArm().AsCoreRegister(),
+             ShifterOperand(locations->InAt(1).AsArm().AsCoreRegister()));
       break;
+
+    case Primitive::kPrimLong:
+      __ adds(locations->Out().AsArm().AsRegisterPairLow(),
+              locations->InAt(0).AsArm().AsRegisterPairLow(),
+              ShifterOperand(locations->InAt(1).AsArm().AsRegisterPairLow()));
+      __ adc(locations->Out().AsArm().AsRegisterPairHigh(),
+             locations->InAt(0).AsArm().AsRegisterPairHigh(),
+             ShifterOperand(locations->InAt(1).AsArm().AsRegisterPairHigh()));
+      break;
+
+    case Primitive::kPrimBoolean:
+    case Primitive::kPrimByte:
+    case Primitive::kPrimChar:
+    case Primitive::kPrimShort:
+      LOG(FATAL) << "Unexpected add type " << add->GetResultType();
+      break;
+
     default:
-      LOG(FATAL) << "Unimplemented";
+      LOG(FATAL) << "Unimplemented add type " << add->GetResultType();
   }
 }
 
@@ -305,13 +585,30 @@
   LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(sub);
   switch (sub->GetResultType()) {
     case Primitive::kPrimInt: {
-      locations->SetInAt(0, Location(R0));
-      locations->SetInAt(1, Location(R1));
-      locations->SetOut(Location(R0));
+      locations->SetInAt(0, ArmCoreLocation(R0));
+      locations->SetInAt(1, ArmCoreLocation(R1));
+      locations->SetOut(ArmCoreLocation(R0));
       break;
     }
+
+    case Primitive::kPrimLong: {
+      locations->SetInAt(
+          0, Location::RegisterLocation(ArmManagedRegister::FromRegisterPair(R0_R1)));
+      locations->SetInAt(
+          1, Location::RegisterLocation(ArmManagedRegister::FromRegisterPair(R2_R3)));
+      locations->SetOut(Location::RegisterLocation(ArmManagedRegister::FromRegisterPair(R0_R1)));
+      break;
+    }
+
+    case Primitive::kPrimBoolean:
+    case Primitive::kPrimByte:
+    case Primitive::kPrimChar:
+    case Primitive::kPrimShort:
+      LOG(FATAL) << "Unexpected sub type " << sub->GetResultType();
+      break;
+
     default:
-      LOG(FATAL) << "Unimplemented";
+      LOG(FATAL) << "Unimplemented sub type " << sub->GetResultType();
   }
   sub->SetLocations(locations);
 }
@@ -320,12 +617,29 @@
   LocationSummary* locations = sub->GetLocations();
   switch (sub->GetResultType()) {
     case Primitive::kPrimInt:
-      __ sub(locations->Out().reg<Register>(),
-             locations->InAt(0).reg<Register>(),
-             ShifterOperand(locations->InAt(1).reg<Register>()));
+      __ sub(locations->Out().AsArm().AsCoreRegister(),
+             locations->InAt(0).AsArm().AsCoreRegister(),
+             ShifterOperand(locations->InAt(1).AsArm().AsCoreRegister()));
       break;
+
+    case Primitive::kPrimLong:
+      __ subs(locations->Out().AsArm().AsRegisterPairLow(),
+              locations->InAt(0).AsArm().AsRegisterPairLow(),
+              ShifterOperand(locations->InAt(1).AsArm().AsRegisterPairLow()));
+      __ sbc(locations->Out().AsArm().AsRegisterPairHigh(),
+             locations->InAt(0).AsArm().AsRegisterPairHigh(),
+             ShifterOperand(locations->InAt(1).AsArm().AsRegisterPairHigh()));
+      break;
+
+    case Primitive::kPrimBoolean:
+    case Primitive::kPrimByte:
+    case Primitive::kPrimChar:
+    case Primitive::kPrimShort:
+      LOG(FATAL) << "Unexpected sub type " << sub->GetResultType();
+      break;
+
     default:
-      LOG(FATAL) << "Unimplemented";
+      LOG(FATAL) << "Unimplemented sub type " << sub->GetResultType();
   }
 }
 
@@ -345,7 +659,7 @@
 
 void LocationsBuilderARM::VisitNewInstance(HNewInstance* instruction) {
   LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(instruction);
-  locations->SetOut(Location(R0));
+  locations->SetOut(ArmCoreLocation(R0));
   instruction->SetLocations(locations);
 }
 
@@ -365,34 +679,55 @@
   LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(instruction);
   InvokeDexCallingConvention calling_convention;
   uint32_t argument_index = instruction->GetIndex();
-  if (argument_index < calling_convention.GetNumberOfRegisters()) {
-    locations->SetOut(Location(calling_convention.GetRegisterAt(argument_index)));
-  } else {
-    locations->SetOut(Location(R0));
+  switch (instruction->GetType()) {
+    case Primitive::kPrimBoolean:
+    case Primitive::kPrimByte:
+    case Primitive::kPrimChar:
+    case Primitive::kPrimShort:
+    case Primitive::kPrimInt:
+    case Primitive::kPrimNot:
+      if (argument_index < calling_convention.GetNumberOfRegisters()) {
+        locations->SetOut(ArmCoreLocation(calling_convention.GetRegisterAt(argument_index)));
+      } else {
+        locations->SetOut(Location::StackSlot(
+            calling_convention.GetStackOffsetOf(argument_index) + codegen_->GetFrameSize()));
+      }
+      break;
+
+    case Primitive::kPrimLong:
+      if (argument_index + 1 < calling_convention.GetNumberOfRegisters()) {
+        locations->SetOut(Location::RegisterLocation(ArmManagedRegister::FromRegisterPair(
+            (calling_convention.GetRegisterPairAt(argument_index)))));
+      } else if (argument_index + 1 == calling_convention.GetNumberOfRegisters()) {
+        // Spanning a register and a stack slot. Use the quick parameter kind.
+        locations->SetOut(Location::QuickParameter(argument_index));
+      } else {
+        locations->SetOut(Location::DoubleStackSlot(
+            calling_convention.GetStackOffsetOf(argument_index) + codegen_->GetFrameSize()));
+      }
+      break;
+
+    default:
+      LOG(FATAL) << "Unimplemented parameter type " << instruction->GetType();
   }
   instruction->SetLocations(locations);
 }
 
 void InstructionCodeGeneratorARM::VisitParameterValue(HParameterValue* instruction) {
-  LocationSummary* locations = instruction->GetLocations();
-  InvokeDexCallingConvention calling_convention;
-  uint8_t argument_index = instruction->GetIndex();
-  if (argument_index >= calling_convention.GetNumberOfRegisters()) {
-    uint8_t offset = calling_convention.GetStackOffsetOf(argument_index);
-    __ ldr(locations->Out().reg<Register>(), Address(SP, offset + codegen_->GetFrameSize()));
-  }
+  // Nothing to do, the parameter is already at its location.
 }
 
 void LocationsBuilderARM::VisitNot(HNot* instruction) {
   LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(instruction);
-  locations->SetInAt(0, Location(R0));
-  locations->SetOut(Location(R0));
+  locations->SetInAt(0, ArmCoreLocation(R0));
+  locations->SetOut(ArmCoreLocation(R0));
   instruction->SetLocations(locations);
 }
 
 void InstructionCodeGeneratorARM::VisitNot(HNot* instruction) {
   LocationSummary* locations = instruction->GetLocations();
-  __ eor(locations->Out().reg<Register>(), locations->InAt(0).reg<Register>(), ShifterOperand(1));
+  __ eor(locations->Out().AsArm().AsCoreRegister(),
+         locations->InAt(0).AsArm().AsCoreRegister(), ShifterOperand(1));
 }
 
 }  // namespace arm