summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndrew Hsieh <andrewhsieh@google.com>2012-11-02 21:54:11 -0700
committerAndrew Hsieh <andrewhsieh@google.com>2012-11-02 21:54:11 -0700
commitaf537b8206a515f942e5ee0338113bd485b55eb7 (patch)
tree79a4558ce6daec9ac902e1846e90ec94d904fa88
parentc796025f7dc5f8df7c0f9c76bcaee96a7716912d (diff)
downloadandroid_external_v8-af537b8206a515f942e5ee0338113bd485b55eb7.tar.gz
android_external_v8-af537b8206a515f942e5ee0338113bd485b55eb7.tar.bz2
android_external_v8-af537b8206a515f942e5ee0338113bd485b55eb7.zip
Fix ARM hardfloat detection in linux
See http://code.google.com/p/v8/issues/detail?id=2140 https://chromiumcodereview.appspot.com/10713009 The original code fails to detect at run-time when compiled with GCC 4.7, because the undefined behavior of casting void to double, and the r0/r1 clobbered in assembly code isn't reaching the use when compared to 1.0 in VFP reg. In summary, the old code is incorrect and overkill, and the new code fix it. Change-Id: I6b63a4f9789e08089368e431a5553f482400725a
-rw-r--r--src/platform-linux.cc71
1 files changed, 33 insertions, 38 deletions
diff --git a/src/platform-linux.cc b/src/platform-linux.cc
index 9781407e..6c4a549c 100644
--- a/src/platform-linux.cc
+++ b/src/platform-linux.cc
@@ -190,48 +190,43 @@ bool OS::ArmCpuHasFeature(CpuFeature feature) {
}
-// Simple helper function to detect whether the C code is compiled with
-// option -mfloat-abi=hard. The register d0 is loaded with 1.0 and the register
-// pair r0, r1 is loaded with 0.0. If -mfloat-abi=hard is pased to GCC then
-// calling this will return 1.0 and otherwise 0.0.
-static void ArmUsingHardFloatHelper() {
- asm("mov r0, #0":::"r0");
-#if defined(__VFP_FP__) && !defined(__SOFTFP__)
- // Load 0x3ff00000 into r1 using instructions available in both ARM
- // and Thumb mode.
- asm("mov r1, #3":::"r1");
- asm("mov r2, #255":::"r2");
- asm("lsl r1, r1, #8":::"r1");
- asm("orr r1, r1, r2":::"r1");
- asm("lsl r1, r1, #20":::"r1");
- // For vmov d0, r0, r1 use ARM mode.
-#ifdef __thumb__
- asm volatile(
- "@ Enter ARM Mode \n\t"
- " adr r3, 1f \n\t"
- " bx r3 \n\t"
- " .ALIGN 4 \n\t"
- " .ARM \n"
- "1: vmov d0, r0, r1 \n\t"
- "@ Enter THUMB Mode\n\t"
- " adr r3, 2f+1 \n\t"
- " bx r3 \n\t"
- " .THUMB \n"
- "2: \n\t":::"r3");
+bool OS::ArmUsingHardFloat() {
+ // GCC versions 4.6 and above define __ARM_PCS or __ARM_PCS_VFP to specify
+ // the Floating Point ABI used (PCS stands for Procedure Call Standard).
+ // We use these as well as a couple of other defines to statically determine
+ // what FP ABI used.
+ // GCC versions 4.4 and below don't support hard-fp.
+ // GCC versions 4.5 may support hard-fp without defining __ARM_PCS or
+ // __ARM_PCS_VFP.
+
+#define GCC_VERSION (__GNUC__ * 10000 \
+ + __GNUC_MINOR__ * 100 \
+ + __GNUC_PATCHLEVEL__)
+#if GCC_VERSION >= 40600
+#if defined(__ARM_PCS_VFP)
+ return true;
#else
- asm("vmov d0, r0, r1");
-#endif // __thumb__
-#endif // defined(__VFP_FP__) && !defined(__SOFTFP__)
- asm("mov r1, #0":::"r1");
-}
+ return false;
+#endif
+#elif GCC_VERSION < 40500
+ return false;
-bool OS::ArmUsingHardFloat() {
- // Cast helper function from returning void to returning double.
- typedef double (*F)();
- F f = FUNCTION_CAST<F>(FUNCTION_ADDR(ArmUsingHardFloatHelper));
- return f() == 1.0;
+#else
+#if defined(__ARM_PCS_VFP)
+ return true;
+#elif defined(__ARM_PCS) || defined(__SOFTFP) || !defined(__VFP_FP__)
+ return false;
+#else
+#error "Your version of GCC does not report the FP ABI compiled for." \
+ "Please report it on this issue" \
+ "http://code.google.com/p/v8/issues/detail?id=2140"
+
+#endif
+#endif
+#undef GCC_VERSION
}
+
#endif // def __arm__