Support hardware divide instruction

Bug: 11299025

Uses sdiv for division and a combo of sdiv, mul and sub for modulus.
Only does this on processors that are capable of the sdiv instruction, as determined
by the build system.

Also provides a command line arg --instruction-set-features= to allow cross compilation.
Makefile adds the --instruction-set-features= arg to build-time dex2oat runs and defaults
it to something obtained from the target architecture.

Provides a GetInstructionSetFeatures() function on CompilerDriver that can be
queried for various features.  The only feature supported right now is hasDivideInstruction().

Also adds a few more instructions to the ARM disassembler

b/11535253 is an addition to this CL to be done later.

Change-Id: Ia8aaf801fd94bc71e476902749cf20f74eba9f68
diff --git a/dex2oat/dex2oat.cc b/dex2oat/dex2oat.cc
index 98c62ce..1472337 100644
--- a/dex2oat/dex2oat.cc
+++ b/dex2oat/dex2oat.cc
@@ -131,6 +131,10 @@
   UsageError("      Example: --instruction-set=x86");
   UsageError("      Default: arm");
   UsageError("");
+  UsageError("  --instruction-set-features=...,: Specify instruction set features");
+  UsageError("      Example: --instruction-set-features=div");
+  UsageError("      Default: default");
+  UsageError("");
   UsageError("  --compiler-backend=(Quick|QuickGBC|Portable): select compiler backend");
   UsageError("      set.");
   UsageError("      Example: --compiler-backend=Portable");
@@ -155,13 +159,15 @@
                      Runtime::Options& options,
                      CompilerBackend compiler_backend,
                      InstructionSet instruction_set,
+                     InstructionSetFeatures instruction_set_features,
                      size_t thread_count)
       SHARED_TRYLOCK_FUNCTION(true, Locks::mutator_lock_) {
     if (!CreateRuntime(options, instruction_set)) {
       *p_dex2oat = NULL;
       return false;
     }
-    *p_dex2oat = new Dex2Oat(Runtime::Current(), compiler_backend, instruction_set, thread_count);
+    *p_dex2oat = new Dex2Oat(Runtime::Current(), compiler_backend, instruction_set,
+        instruction_set_features, thread_count);
     return true;
   }
 
@@ -257,6 +263,7 @@
 
     UniquePtr<CompilerDriver> driver(new CompilerDriver(compiler_backend_,
                                                         instruction_set_,
+                                                        instruction_set_features_,
                                                         image,
                                                         image_classes.release(),
                                                         thread_count_,
@@ -330,9 +337,11 @@
   explicit Dex2Oat(Runtime* runtime,
                    CompilerBackend compiler_backend,
                    InstructionSet instruction_set,
+                   InstructionSetFeatures instruction_set_features,
                    size_t thread_count)
       : compiler_backend_(compiler_backend),
         instruction_set_(instruction_set),
+        instruction_set_features_(instruction_set_features),
         runtime_(runtime),
         thread_count_(thread_count),
         start_ns_(NanoTime()) {
@@ -391,6 +400,7 @@
   const CompilerBackend compiler_backend_;
 
   const InstructionSet instruction_set_;
+  const InstructionSetFeatures instruction_set_features_;
 
   Runtime* runtime_;
   size_t thread_count_;
@@ -559,6 +569,32 @@
 const unsigned int WatchDog::kWatchDogWarningSeconds;
 const unsigned int WatchDog::kWatchDogTimeoutSeconds;
 
+// Given a set of instruction features from the build, parse it.  The
+// input 'str' is a comma separated list of feature names.  Parse it and
+// return the InstructionSetFeatures object.
+static InstructionSetFeatures ParseFeatureList(std::string str) {
+  InstructionSetFeatures result;
+  typedef std::vector<std::string> FeatureList;
+  FeatureList features;
+  Split(str, ',', features);
+  for (FeatureList::iterator i = features.begin(); i != features.end(); i++) {
+    std::string feature = Trim(*i);
+    if (feature == "default") {
+      // Nothing to do.
+    } else if (feature == "div") {
+      // Supports divide instruction.
+       result.SetHasDivideInstruction(true);
+    } else if (feature == "nodiv") {
+      // Turn off support for divide instruction.
+      result.SetHasDivideInstruction(false);
+    } else {
+      Usage("Unknown instruction set feature: '%s'", feature.c_str());
+    }
+  }
+  // others...
+  return result;
+}
+
 static int dex2oat(int argc, char** argv) {
   base::TimingLogger timings("compiler", false, false);
 
@@ -595,6 +631,15 @@
 #else
   CompilerBackend compiler_backend = kQuick;
 #endif
+
+  // Take the default set of instruction features from the build if present.
+  InstructionSetFeatures instruction_set_features =
+#ifdef ART_DEFAULT_INSTRUCTION_SET_FEATURES
+    ParseFeatureList(STRINGIFY(ART_DEFAULT_INSTRUCTION_SET_FEATURES));
+#else
+    ParseFeatureList("default");
+#endif
+
 #if defined(__arm__)
   InstructionSet instruction_set = kThumb2;
 #elif defined(__i386__)
@@ -604,6 +649,8 @@
 #else
 #error "Unsupported architecture"
 #endif
+
+
   bool is_host = false;
   bool dump_stats = false;
   bool dump_timing = false;
@@ -678,6 +725,9 @@
       } else if (instruction_set_str == "x86") {
         instruction_set = kX86;
       }
+    } else if (option.starts_with("--instruction-set-features=")) {
+      StringPiece str = option.substr(strlen("--instruction-set-features=")).data();
+      instruction_set_features = ParseFeatureList(str.as_string());
     } else if (option.starts_with("--compiler-backend=")) {
       StringPiece backend_str = option.substr(strlen("--compiler-backend=")).data();
       if (backend_str == "Quick") {
@@ -870,7 +920,8 @@
 #endif
 
   Dex2Oat* p_dex2oat;
-  if (!Dex2Oat::Create(&p_dex2oat, options, compiler_backend, instruction_set, thread_count)) {
+  if (!Dex2Oat::Create(&p_dex2oat, options, compiler_backend, instruction_set,
+      instruction_set_features, thread_count)) {
     LOG(ERROR) << "Failed to create dex2oat";
     return EXIT_FAILURE;
   }
@@ -1093,8 +1144,6 @@
 
   return EXIT_SUCCESS;
 }
-
-
 }  // namespace art
 
 int main(int argc, char** argv) {