First set of licensing changes
[mono.git] / mono / utils / mono-hwcap-arm.c
index b13b589af94c960e10be597fbe60f513a668ac91..6cf8065d06a43e421bfb59737800ff73536d3f86 100644 (file)
  * 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];
@@ -69,53 +132,38 @@ mono_hwcap_init (void)
                        }
 
                        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);
+}