2 * mono-hwcap-arm.c: ARM hardware feature detection
5 * Alex Rønne Petersen (alexrp@xamarin.com)
6 * Elijah Taylor (elijahtaylor@google.com)
7 * Miguel de Icaza (miguel@xamarin.com)
8 * Neale Ferguson (Neale.Ferguson@SoftwareAG-usa.com)
9 * Paolo Molaro (lupus@xamarin.com)
10 * Rodrigo Kumpera (kumpera@gmail.com)
11 * Sebastien Pouliot (sebastien@xamarin.com)
12 * Zoltan Varga (vargaz@xamarin.com)
14 * Copyright 2003 Ximian, Inc.
15 * Copyright 2003-2011 Novell, Inc
16 * Copyright 2006 Broadcom
17 * Copyright 2007-2008 Andreas Faerber
18 * Copyright 2011-2013 Xamarin Inc
21 #include "mono/utils/mono-hwcap-arm.h"
23 #if defined(HAVE_SYS_AUXV_H) && !defined(PLATFORM_ANDROID)
25 #elif defined(__APPLE__)
26 #include <mach/machine.h>
27 #include <sys/sysctl.h>
28 #include <sys/types.h>
33 gboolean mono_hwcap_arm_is_v5 = FALSE;
34 gboolean mono_hwcap_arm_is_v6 = FALSE;
35 gboolean mono_hwcap_arm_is_v7 = FALSE;
36 gboolean mono_hwcap_arm_is_v7s = FALSE;
37 gboolean mono_hwcap_arm_is_v7k = FALSE;
38 gboolean mono_hwcap_arm_has_vfp = FALSE;
39 gboolean mono_hwcap_arm_has_vfp3 = FALSE;
40 gboolean mono_hwcap_arm_has_vfp3_d16 = FALSE;
41 gboolean mono_hwcap_arm_has_thumb = FALSE;
42 gboolean mono_hwcap_arm_has_thumb2 = FALSE;
45 mono_hwcap_arch_init (void)
47 #if defined(HAVE_SYS_AUXV_H) && !defined(PLATFORM_ANDROID)
49 unsigned long platform;
51 if ((hwcap = getauxval(AT_HWCAP))) {
53 if (hwcap & 0x00000004)
54 mono_hwcap_arm_has_thumb = TRUE;
57 if (hwcap & 0x00000040)
58 mono_hwcap_arm_has_vfp = TRUE;
61 if (hwcap & 0x00002000)
62 mono_hwcap_arm_has_vfp3 = TRUE;
64 /* HWCAP_ARM_VFPv3D16 */
65 if (hwcap & 0x00004000)
66 mono_hwcap_arm_has_vfp3_d16 = TRUE;
68 /* TODO: Find a way to detect Thumb 2. */
71 if ((platform = getauxval(AT_PLATFORM))) {
72 const char *str = (const char *) platform;
75 mono_hwcap_arm_is_v5 = TRUE;
78 mono_hwcap_arm_is_v6 = TRUE;
81 mono_hwcap_arm_is_v7 = TRUE;
83 /* TODO: Find a way to detect v7s. */
85 #elif defined(__APPLE__)
86 cpu_subtype_t sub_type;
87 size_t length = sizeof (sub_type);
89 sysctlbyname ("hw.cpusubtype", &sub_type, &length, NULL, 0);
91 if (sub_type == CPU_SUBTYPE_ARM_V5TEJ || sub_type == CPU_SUBTYPE_ARM_XSCALE) {
92 mono_hwcap_arm_is_v5 = TRUE;
93 } else if (sub_type == CPU_SUBTYPE_ARM_V6) {
94 mono_hwcap_arm_is_v5 = TRUE;
95 mono_hwcap_arm_is_v6 = TRUE;
96 } else if (sub_type == CPU_SUBTYPE_ARM_V7 || sub_type == CPU_SUBTYPE_ARM_V7F || sub_type == CPU_SUBTYPE_ARM_V7K) {
97 mono_hwcap_arm_is_v5 = TRUE;
98 mono_hwcap_arm_is_v6 = TRUE;
99 mono_hwcap_arm_is_v7 = TRUE;
102 /* TODO: Find a way to detect features like Thumb and VFP. */
104 /* We can't use the auxiliary vector on Android due to
105 * permissions, so fall back to /proc/cpuinfo. We also
106 * hit this path if the target doesn't have sys/auxv.h.
112 FILE *file = fopen ("/proc/cpuinfo", "r");
115 while ((line = fgets (buf, 512, file))) {
116 if (!strncmp (line, "Processor", 9)) {
117 char *ver = strstr (line, "(v");
121 mono_hwcap_arm_is_v5 = TRUE;
124 mono_hwcap_arm_is_v6 = TRUE;
127 mono_hwcap_arm_is_v7 = TRUE;
129 /* TODO: Find a way to detect v7s. */
135 if (!strncmp (line, "Features", 8)) {
136 if (strstr (line, "thumb"))
137 mono_hwcap_arm_has_thumb = TRUE;
139 /* TODO: Find a way to detect Thumb 2. */
141 if (strstr (line, "vfp"))
142 mono_hwcap_arm_has_vfp = TRUE;
144 if (strstr (line, "vfpv3"))
145 mono_hwcap_arm_has_vfp3 = TRUE;
147 if (strstr (line, "vfpv3-d16"))
148 mono_hwcap_arm_has_vfp3_d16 = TRUE;
160 mono_hwcap_print(FILE *f)
162 g_fprintf (f, "mono_hwcap_arm_is_v5 = %i\n", mono_hwcap_arm_is_v5);
163 g_fprintf (f, "mono_hwcap_arm_is_v6 = %i\n", mono_hwcap_arm_is_v6);
164 g_fprintf (f, "mono_hwcap_arm_is_v7 = %i\n", mono_hwcap_arm_is_v7);
165 g_fprintf (f, "mono_hwcap_arm_is_v7s = %i\n", mono_hwcap_arm_is_v7s);
166 g_fprintf (f, "mono_hwcap_arm_is_v7k = %i\n", mono_hwcap_arm_is_v7k);
167 g_fprintf (f, "mono_hwcap_arm_has_vfp = %i\n", mono_hwcap_arm_has_vfp);
168 g_fprintf (f, "mono_hwcap_arm_has_vfp3 = %i\n", mono_hwcap_arm_has_vfp3);
169 g_fprintf (f, "mono_hwcap_arm_has_vfp3_d16 = %i\n", mono_hwcap_arm_has_vfp3_d16);
170 g_fprintf (f, "mono_hwcap_arm_has_thumb = %i\n", mono_hwcap_arm_has_thumb);
171 g_fprintf (f, "mono_hwcap_arm_has_thumb2 = %i\n", mono_hwcap_arm_has_thumb2);