Support for cross compilation.

Refactor architecture specific files into arm and x86 name spaces. Make
assemblers and calling conventions use the factory pattern and an
instruction set specifier.

Change-Id: I20cd7aecacc1ae3d418221d98bbe1d69be9162a7
diff --git a/src/calling_convention_arm.cc b/src/calling_convention_arm.cc
index 527ce5f..4b4a146 100644
--- a/src/calling_convention_arm.cc
+++ b/src/calling_convention_arm.cc
@@ -1,44 +1,55 @@
 // Copyright 2011 Google Inc. All Rights Reserved.
 
-#include "calling_convention.h"
+#include "calling_convention_arm.h"
 #include "logging.h"
+#include "managed_register_arm.h"
 
 namespace art {
+namespace arm {
 
-ManagedRegister CallingConvention::MethodRegister() {
-  return ManagedRegister::FromCoreRegister(R0);
+// Calling convention
+
+ManagedRegister ArmManagedRuntimeCallingConvention::InterproceduralScratchRegister() {
+  return ArmManagedRegister::FromCoreRegister(IP);  // R12
 }
 
-ManagedRegister CallingConvention::ThreadRegister() {
-  return ManagedRegister::FromCoreRegister(TR);
+ManagedRegister ArmJniCallingConvention::InterproceduralScratchRegister() {
+  return ArmManagedRegister::FromCoreRegister(IP);  // R12
 }
 
-ManagedRegister CallingConvention::InterproceduralScratchRegister() {
-  return ManagedRegister::FromCoreRegister(R12);
-}
-
-ManagedRegister CallingConvention::ReturnRegister() {
-  const Method *method = GetMethod();
-  if (GetMethod()->IsReturnAFloat()) {
-    return ManagedRegister::FromCoreRegister(R0);
-  } else if (GetMethod()->IsReturnADouble()) {
-    return ManagedRegister::FromRegisterPair(R0_R1);
+static ManagedRegister ReturnRegisterForMethod(Method* method) {
+  if (method->IsReturnAFloat()) {
+    return ArmManagedRegister::FromCoreRegister(R0);
+  } else if (method->IsReturnADouble()) {
+    return ArmManagedRegister::FromRegisterPair(R0_R1);
   } else if (method->IsReturnALong()) {
-    return ManagedRegister::FromRegisterPair(R0_R1);
+    return ArmManagedRegister::FromRegisterPair(R0_R1);
   } else if (method->IsReturnVoid()) {
-    return ManagedRegister::NoRegister();
+    return ArmManagedRegister::NoRegister();
   } else {
-    return ManagedRegister::FromCoreRegister(R0);
+    return ArmManagedRegister::FromCoreRegister(R0);
   }
 }
 
+ManagedRegister ArmManagedRuntimeCallingConvention::ReturnRegister() {
+  return ReturnRegisterForMethod(GetMethod());
+}
+
+ManagedRegister ArmJniCallingConvention::ReturnRegister() {
+  return ReturnRegisterForMethod(GetMethod());
+}
+
 // Managed runtime calling convention
 
-bool ManagedRuntimeCallingConvention::IsCurrentParamInRegister() {
+ManagedRegister ArmManagedRuntimeCallingConvention::MethodRegister() {
+  return ArmManagedRegister::FromCoreRegister(R0);
+}
+
+bool ArmManagedRuntimeCallingConvention::IsCurrentParamInRegister() {
   return itr_slots_ < 3;
 }
 
-bool ManagedRuntimeCallingConvention::IsCurrentParamOnStack() {
+bool ArmManagedRuntimeCallingConvention::IsCurrentParamOnStack() {
   if (itr_slots_ < 2) {
     return false;
   } else if (itr_slots_ > 2) {
@@ -52,26 +63,26 @@
 static const Register kManagedArgumentRegisters[] = {
   R1, R2, R3
 };
-ManagedRegister ManagedRuntimeCallingConvention::CurrentParamRegister() {
+ManagedRegister ArmManagedRuntimeCallingConvention::CurrentParamRegister() {
   CHECK(IsCurrentParamInRegister());
   const Method* method = GetMethod();
   if (method->IsParamALongOrDouble(itr_args_)) {
     if (itr_slots_ == 0) {
-      return ManagedRegister::FromRegisterPair(R1_R2);
+      return ArmManagedRegister::FromRegisterPair(R1_R2);
     } else if (itr_slots_ == 1) {
-      return ManagedRegister::FromRegisterPair(R2_R3);
+      return ArmManagedRegister::FromRegisterPair(R2_R3);
     } else {
       // This is a long/double split between registers and the stack
-      return ManagedRegister::FromCoreRegister(
+      return ArmManagedRegister::FromCoreRegister(
         kManagedArgumentRegisters[itr_slots_]);
     }
   } else {
     return
-      ManagedRegister::FromCoreRegister(kManagedArgumentRegisters[itr_slots_]);
+      ArmManagedRegister::FromCoreRegister(kManagedArgumentRegisters[itr_slots_]);
   }
 }
 
-FrameOffset ManagedRuntimeCallingConvention::CurrentParamStackOffset() {
+FrameOffset ArmManagedRuntimeCallingConvention::CurrentParamStackOffset() {
   CHECK(IsCurrentParamOnStack());
   FrameOffset result =
       FrameOffset(displacement_.Int32Value() +   // displacement
@@ -88,7 +99,18 @@
 
 // JNI calling convention
 
-size_t JniCallingConvention::FrameSize() {
+ArmJniCallingConvention::ArmJniCallingConvention(Method* method) :
+    JniCallingConvention(method) {
+  // A synchronized method will call monitor enter clobbering R1, R2 and R3
+  // unless they are spilled.
+  if (method->IsSynchronized()) {
+    spill_regs_.push_back(ArmManagedRegister::FromCoreRegister(R1));
+    spill_regs_.push_back(ArmManagedRegister::FromCoreRegister(R2));
+    spill_regs_.push_back(ArmManagedRegister::FromCoreRegister(R3));
+  }
+}
+
+size_t ArmJniCallingConvention::FrameSize() {
   // Method* and spill area size
   size_t frame_data_size = kPointerSize + SpillAreaSize();
   // References plus 2 words for SIRT header
@@ -98,7 +120,7 @@
                  kStackAlignment);
 }
 
-size_t JniCallingConvention::OutArgSize() {
+size_t ArmJniCallingConvention::OutArgSize() {
   const Method* method = GetMethod();
   size_t padding;  // padding to ensure longs and doubles are not split in AAPCS
   if (method->IsStatic()) {
@@ -112,32 +134,22 @@
                  kStackAlignment);
 }
 
-size_t JniCallingConvention::ReturnPcOffset() {
+size_t ArmJniCallingConvention::ReturnPcOffset() {
   // Link register is always the last value spilled, skip forward one word for
   // the Method* then skip back one word to get the link register (ie +0)
   return SpillAreaSize();
 }
 
-size_t JniCallingConvention::SpillAreaSize() {
+size_t ArmJniCallingConvention::SpillAreaSize() {
   // Space for link register. For synchronized methods we need enough space to
   // save R1, R2 and R3 (R0 is the method register and always preserved)
   return GetMethod()->IsSynchronized() ? (4 * kPointerSize) : kPointerSize;
 }
 
-void JniCallingConvention::ComputeRegsToSpillPreCall(std::vector<ManagedRegister>& regs) {
-  // A synchronized method will call monitor enter clobbering R1, R2 and R3
-  // unless they are spilled.
-  if (GetMethod()->IsSynchronized()) {
-    regs.push_back(ManagedRegister::FromCoreRegister(R1));
-    regs.push_back(ManagedRegister::FromCoreRegister(R2));
-    regs.push_back(ManagedRegister::FromCoreRegister(R3));
-  }
-}
-
 // Will reg be crushed by an outgoing argument?
-bool JniCallingConvention::IsOutArgRegister(ManagedRegister) {
-  // R0 holds the method register and will be crushed by the JNIEnv*
-  return true;
+bool ArmJniCallingConvention::IsOutArgRegister(ManagedRegister mreg) {
+  Register reg = mreg.AsArm().AsCoreRegister();
+  return reg >= R0 && reg <= R3;
 }
 
 // JniCallingConvention ABI follows AAPCS
@@ -146,9 +158,9 @@
 // or IsCurrentParamOnStack() will be called first.
 // Both functions will ensure that we conform to AAPCS.
 //
-bool JniCallingConvention::IsCurrentParamInRegister() {
+bool ArmJniCallingConvention::IsCurrentParamInRegister() {
   // AAPCS processing
-  const Method* method = GetMethod();
+  Method* method = GetMethod();
   int arg_pos = itr_args_ - NumberOfExtraArgumentsForJni(method);
   if ((itr_args_ >= 2) && method->IsParamALongOrDouble(arg_pos)) {
     // itr_slots_ needs to be an even number, according to AAPCS.
@@ -160,34 +172,34 @@
   return itr_slots_ < 4;
 }
 
-bool JniCallingConvention::IsCurrentParamOnStack() {
+bool ArmJniCallingConvention::IsCurrentParamOnStack() {
   return !IsCurrentParamInRegister();
 }
 
 static const Register kJniArgumentRegisters[] = {
   R0, R1, R2, R3
 };
-ManagedRegister JniCallingConvention::CurrentParamRegister() {
+ManagedRegister ArmJniCallingConvention::CurrentParamRegister() {
   CHECK_LT(itr_slots_, 4u);
-  const Method* method = GetMethod();
+  Method* method = GetMethod();
   int arg_pos = itr_args_ - NumberOfExtraArgumentsForJni(method);
   if ((itr_args_ >= 2) && method->IsParamALongOrDouble(arg_pos)) {
     CHECK_EQ(itr_slots_, 2u);
-    return ManagedRegister::FromRegisterPair(R2_R3);
+    return ArmManagedRegister::FromRegisterPair(R2_R3);
   } else {
     return
-      ManagedRegister::FromCoreRegister(kJniArgumentRegisters[itr_slots_]);
+      ArmManagedRegister::FromCoreRegister(kJniArgumentRegisters[itr_slots_]);
   }
 }
 
-FrameOffset JniCallingConvention::CurrentParamStackOffset() {
+FrameOffset ArmJniCallingConvention::CurrentParamStackOffset() {
   CHECK_GE(itr_slots_, 4u);
   return FrameOffset(displacement_.Int32Value() - OutArgSize()
                + ((itr_slots_ - 4) * kPointerSize));
 }
 
-size_t JniCallingConvention::NumberOfOutgoingStackArgs() {
-  const Method* method = GetMethod();
+size_t ArmJniCallingConvention::NumberOfOutgoingStackArgs() {
+  Method* method = GetMethod();
   size_t static_args = method->IsStatic() ? 1 : 0;  // count jclass
   // regular argument parameters and this
   size_t param_args = method->NumArgs() +
@@ -196,4 +208,5 @@
   return static_args + param_args + 1 - 4;
 }
 
+}  // namespace arm
 }  // namespace art