* Copyright 2006 Broadcom
* Copyright 2007-2008 Andreas Faerber
* Copyright 2011-2013 Xamarin Inc
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
*/
#include "mono/utils/mono-hwcap-arm.h"
-#if defined(PLATFORM_ANDROID)
-#include <stdio.h>
-#elif defined(__linux__)
+#if defined(HAVE_SYS_AUXV_H) && !defined(PLATFORM_ANDROID)
#include <sys/auxv.h>
+#elif defined(__APPLE__)
+#include <mach/machine.h>
+#include <sys/sysctl.h>
+#include <sys/types.h>
+#else
+#include <stdio.h>
#endif
gboolean mono_hwcap_arm_is_v5 = FALSE;
gboolean mono_hwcap_arm_is_v6 = FALSE;
gboolean mono_hwcap_arm_is_v7 = FALSE;
-gboolean mono_hwcap_arm_is_v7s = FALSE;
gboolean mono_hwcap_arm_has_vfp = FALSE;
+gboolean mono_hwcap_arm_has_vfp3 = FALSE;
+gboolean mono_hwcap_arm_has_vfp3_d16 = FALSE;
gboolean mono_hwcap_arm_has_thumb = FALSE;
gboolean mono_hwcap_arm_has_thumb2 = FALSE;
void
-mono_hwcap_init (void)
+mono_hwcap_arch_init (void)
{
-#if defined(PLATFORM_ANDROID)
+#if defined(HAVE_SYS_AUXV_H) && !defined(PLATFORM_ANDROID)
+ unsigned long hwcap;
+ unsigned long platform;
+
+ if ((hwcap = getauxval(AT_HWCAP))) {
+ /* HWCAP_ARM_THUMB */
+ if (hwcap & 0x00000004)
+ mono_hwcap_arm_has_thumb = TRUE;
+
+ /* HWCAP_ARM_VFP */
+ if (hwcap & 0x00000040)
+ mono_hwcap_arm_has_vfp = TRUE;
+
+ /* HWCAP_ARM_VFPv3 */
+ if (hwcap & 0x00002000)
+ mono_hwcap_arm_has_vfp3 = TRUE;
+
+ /* HWCAP_ARM_VFPv3D16 */
+ if (hwcap & 0x00004000)
+ mono_hwcap_arm_has_vfp3_d16 = TRUE;
+
+ /* TODO: Find a way to detect Thumb 2. */
+ }
+
+ if ((platform = getauxval(AT_PLATFORM))) {
+ const char *str = (const char *) platform;
+
+ if (str [1] >= '5')
+ mono_hwcap_arm_is_v5 = TRUE;
+
+ if (str [1] >= '6')
+ mono_hwcap_arm_is_v6 = TRUE;
+
+ if (str [1] >= '7')
+ mono_hwcap_arm_is_v7 = TRUE;
+
+ /* TODO: Find a way to detect v7s. */
+ }
+#elif defined(__APPLE__)
+ cpu_subtype_t sub_type;
+ size_t length = sizeof (sub_type);
+
+ sysctlbyname ("hw.cpusubtype", &sub_type, &length, NULL, 0);
+
+ if (sub_type == CPU_SUBTYPE_ARM_V5TEJ || sub_type == CPU_SUBTYPE_ARM_XSCALE) {
+ mono_hwcap_arm_is_v5 = TRUE;
+ } else if (sub_type == CPU_SUBTYPE_ARM_V6) {
+ mono_hwcap_arm_is_v5 = TRUE;
+ mono_hwcap_arm_is_v6 = TRUE;
+ } else if (sub_type == CPU_SUBTYPE_ARM_V7 || sub_type == CPU_SUBTYPE_ARM_V7F || sub_type == CPU_SUBTYPE_ARM_V7K) {
+ mono_hwcap_arm_is_v5 = TRUE;
+ mono_hwcap_arm_is_v6 = TRUE;
+ mono_hwcap_arm_is_v7 = TRUE;
+ }
+
+ /* TODO: Find a way to detect features like Thumb and VFP. */
+#else
/* We can't use the auxiliary vector on Android due to
- * permissions, so fall back to /proc/cpuinfo.
+ * permissions, so fall back to /proc/cpuinfo. We also
+ * hit this path if the target doesn't have sys/auxv.h.
*/
char buf [512];
}
if (!strncmp (line, "Features", 8)) {
- char *thumb = strstr (line, "thumb");
-
- if (thumb)
+ if (strstr (line, "thumb"))
mono_hwcap_arm_has_thumb = TRUE;
/* TODO: Find a way to detect Thumb 2. */
- char *vfp = strstr (line, "vfp")
-
- if (vfp)
+ if (strstr (line, "vfp"))
mono_hwcap_arm_has_vfp = TRUE;
+ if (strstr (line, "vfpv3"))
+ mono_hwcap_arm_has_vfp3 = TRUE;
+
+ if (strstr (line, "vfpv3-d16"))
+ mono_hwcap_arm_has_vfp3_d16 = TRUE;
+
continue;
}
}
fclose (file);
}
-#elif defined(__linux__)
- unsigned long hwcap;
- unsigned long platform;
-
- if ((hwcap = getauxval(AT_HWCAP))) {
- /* HWCAP_ARM_THUMB */
- if (hwcap & 0x00000004)
- mono_hwcap_arm_has_thumb = TRUE;
-
- /* HWCAP_ARM_VFP */
- if (hwcap & 0x00000064)
- mono_hwcap_arm_has_vfp = TRUE;
-
- /* TODO: Find a way to detect Thumb 2. */
- }
-
- if ((platform = getauxval(AT_PLATFORM))) {
- const char *str = (const char *) platform;
-
- if (str [1] >= '5')
- mono_hwcap_arm_is_v5 = TRUE;
-
- if (str [1] >= '6')
- mono_hwcap_arm_is_v6 = TRUE;
-
- if (str [1] >= '7')
- mono_hwcap_arm_is_v7 = TRUE;
-
- /* TODO: Find a way to detect v7s. */
- }
#endif
}
+
+void
+mono_hwcap_print(FILE *f)
+{
+ g_fprintf (f, "mono_hwcap_arm_is_v5 = %i\n", mono_hwcap_arm_is_v5);
+ g_fprintf (f, "mono_hwcap_arm_is_v6 = %i\n", mono_hwcap_arm_is_v6);
+ g_fprintf (f, "mono_hwcap_arm_is_v7 = %i\n", mono_hwcap_arm_is_v7);
+ g_fprintf (f, "mono_hwcap_arm_has_vfp = %i\n", mono_hwcap_arm_has_vfp);
+ g_fprintf (f, "mono_hwcap_arm_has_vfp3 = %i\n", mono_hwcap_arm_has_vfp3);
+ g_fprintf (f, "mono_hwcap_arm_has_vfp3_d16 = %i\n", mono_hwcap_arm_has_vfp3_d16);
+ g_fprintf (f, "mono_hwcap_arm_has_thumb = %i\n", mono_hwcap_arm_has_thumb);
+ g_fprintf (f, "mono_hwcap_arm_has_thumb2 = %i\n", mono_hwcap_arm_has_thumb2);
+}