Index: runtime/vm/assembler_arm.cc |
=================================================================== |
--- runtime/vm/assembler_arm.cc (revision 32559) |
+++ runtime/vm/assembler_arm.cc (working copy) |
@@ -6,7 +6,6 @@ |
#if defined(TARGET_ARCH_ARM) |
#include "vm/assembler.h" |
-#include "vm/cpu.h" |
#include "vm/longjump.h" |
#include "vm/runtime_entry.h" |
#include "vm/simulator.h" |
@@ -23,7 +22,98 @@ |
DEFINE_FLAG(bool, print_stop_message, true, "Print stop message."); |
DECLARE_FLAG(bool, inline_alloc); |
+bool CPUFeatures::integer_division_supported_ = false; |
+bool CPUFeatures::neon_supported_ = false; |
+#if defined(DEBUG) |
+bool CPUFeatures::initialized_ = false; |
+#endif |
+ |
+bool CPUFeatures::integer_division_supported() { |
+ DEBUG_ASSERT(initialized_); |
+ return integer_division_supported_; |
+} |
+ |
+ |
+bool CPUFeatures::neon_supported() { |
+ DEBUG_ASSERT(initialized_); |
+ return neon_supported_; |
+} |
+ |
+ |
+// If we are using the simulator, allow tests to enable/disable support for |
+// integer division. |
+#if defined(USING_SIMULATOR) |
+void CPUFeatures::set_integer_division_supported(bool supported) { |
+ integer_division_supported_ = supported; |
+} |
+ |
+ |
+void CPUFeatures::set_neon_supported(bool supported) { |
+ neon_supported_ = supported; |
+} |
+#endif |
+ |
+ |
+// Probe /proc/cpuinfo for features of the ARM processor. |
+#if !defined(USING_SIMULATOR) |
+static bool CPUInfoContainsString(const char* search_string) { |
+ const char* file_name = "/proc/cpuinfo"; |
+ // This is written as a straight shot one pass parser |
+ // and not using STL string and ifstream because, |
+ // on Linux, it's reading from a (non-mmap-able) |
+ // character special device. |
+ FILE* f = NULL; |
+ const char* what = search_string; |
+ |
+ if (NULL == (f = fopen(file_name, "r"))) |
+ return false; |
+ |
+ int k; |
+ while (EOF != (k = fgetc(f))) { |
+ if (k == *what) { |
+ ++what; |
+ while ((*what != '\0') && (*what == fgetc(f))) { |
+ ++what; |
+ } |
+ if (*what == '\0') { |
+ fclose(f); |
+ return true; |
+ } else { |
+ what = search_string; |
+ } |
+ } |
+ } |
+ fclose(f); |
+ |
+ // Did not find string in the proc file. |
+ return false; |
+} |
+#endif |
+ |
+ |
+void CPUFeatures::InitOnce() { |
+#if defined(USING_SIMULATOR) |
+ integer_division_supported_ = true; |
+ neon_supported_ = true; |
+#else |
+ ASSERT(CPUInfoContainsString("ARMv7")); // Implements ARMv7. |
+ ASSERT(CPUInfoContainsString("vfp")); // Has floating point unit. |
+ // Has integer division. |
+ if (CPUInfoContainsString("QCT APQ8064")) { |
+ // Special case for Qualcomm Krait CPUs in Nexus 4 and 7. |
+ integer_division_supported_ = true; |
+ } else { |
+ integer_division_supported_ = CPUInfoContainsString("idiva"); |
+ } |
+ neon_supported_ = CPUInfoContainsString("neon"); |
+#endif // defined(USING_SIMULATOR) |
+#if defined(DEBUG) |
+ initialized_ = true; |
+#endif |
+} |
+ |
+ |
// Instruction encoding bits. |
enum { |
H = 1 << 5, // halfword (or byte) |
@@ -459,7 +549,7 @@ |
void Assembler::EmitDivOp(Condition cond, int32_t opcode, |
Register rd, Register rn, Register rm) { |
- ASSERT(TargetCPUFeatures::integer_division_supported()); |
+ ASSERT(CPUFeatures::integer_division_supported()); |
ASSERT(rd != kNoRegister); |
ASSERT(rn != kNoRegister); |
ASSERT(rm != kNoRegister); |
@@ -2367,7 +2457,7 @@ |
void Assembler::IntegerDivide(Register result, Register left, Register right, |
DRegister tmpl, DRegister tmpr) { |
ASSERT(tmpl != tmpr); |
- if (TargetCPUFeatures::integer_division_supported()) { |
+ if (CPUFeatures::integer_division_supported()) { |
sdiv(result, left, right); |
} else { |
SRegister stmpl = static_cast<SRegister>(2 * tmpl); |