Check for sys/auxv.h and only use it if available.
[mono.git] / mono / utils / mono-hwcap-arm.c
1 /*
2  * mono-hwcap-arm.c: ARM hardware feature detection
3  *
4  * Authors:
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)
13  *
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
19  */
20
21 #include "mono/utils/mono-hwcap-arm.h"
22
23 #if defined(PLATFORM_ANDROID)
24 #include <stdio.h>
25 #elif defined(__linux__) && defined(HAVE_SYS_AUXV_H)
26 #include <sys/auxv.h>
27 #elif defined(__APPLE__)
28 #include <mach/machine.h>
29 #include <sys/sysctl.h>
30 #include <sys/types.h>
31 #endif
32
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_has_vfp = FALSE;
38 gboolean mono_hwcap_arm_has_thumb = FALSE;
39 gboolean mono_hwcap_arm_has_thumb2 = FALSE;
40
41 void
42 mono_hwcap_arch_init (void)
43 {
44 #if defined(PLATFORM_ANDROID)
45         /* We can't use the auxiliary vector on Android due to
46          * permissions, so fall back to /proc/cpuinfo.
47          */
48
49         char buf [512];
50         char *line;
51
52         FILE *file = fopen ("/proc/cpuinfo", "r");
53
54         if (file) {
55                 while ((line = fgets (buf, 512, file))) {
56                         if (!strncmp (line, "Processor", 9)) {
57                                 char *ver = strstr (line, "(v");
58
59                                 if (ver) {
60                                         if (ver [2] >= '5')
61                                                 mono_hwcap_arm_is_v5 = TRUE;
62
63                                         if (ver [2] >= '6')
64                                                 mono_hwcap_arm_is_v6 = TRUE;
65
66                                         if (ver [2] >= '7')
67                                                 mono_hwcap_arm_is_v7 = TRUE;
68
69                                         /* TODO: Find a way to detect v7s. */
70                                 }
71
72                                 continue;
73                         }
74
75                         if (!strncmp (line, "Features", 8)) {
76                                 char *thumb = strstr (line, "thumb");
77
78                                 if (thumb)
79                                         mono_hwcap_arm_has_thumb = TRUE;
80
81                                 /* TODO: Find a way to detect Thumb 2. */
82
83                                 char *vfp = strstr (line, "vfp")
84
85                                 if (vfp)
86                                         mono_hwcap_arm_has_vfp = TRUE;
87
88                                 continue;
89                         }
90                 }
91
92                 fclose (file);
93         }
94 #elif defined(__linux__) && defined(HAVE_SYS_AUXV_H)
95         unsigned long hwcap;
96         unsigned long platform;
97
98         if ((hwcap = getauxval(AT_HWCAP))) {
99                 /* HWCAP_ARM_THUMB */
100                 if (hwcap & 0x00000004)
101                         mono_hwcap_arm_has_thumb = TRUE;
102
103                 /* HWCAP_ARM_VFP */
104                 if (hwcap & 0x00000064)
105                         mono_hwcap_arm_has_vfp = TRUE;
106
107                 /* TODO: Find a way to detect Thumb 2. */
108         }
109
110         if ((platform = getauxval(AT_PLATFORM))) {
111                 const char *str = (const char *) platform;
112
113                 if (str [1] >= '5')
114                         mono_hwcap_arm_is_v5 = TRUE;
115
116                 if (str [1] >= '6')
117                         mono_hwcap_arm_is_v6 = TRUE;
118
119                 if (str [1] >= '7')
120                         mono_hwcap_arm_is_v7 = TRUE;
121
122                 /* TODO: Find a way to detect v7s. */
123         }
124 #elif defined(__APPLE__)
125         cpu_subtype_t sub_type;
126         size_t length = sizeof (sub_type);
127
128         sysctlbyname ("hw.cpusubtype", &sub_type, &length, NULL, 0);
129
130         if (sub_type == CPU_SUBTYPE_ARM_V5TEJ || sub_type == CPU_SUBTYPE_ARM_XSCALE) {
131                 mono_hwcap_arm_is_v5 = TRUE;
132         } else if (sub_type == CPU_SUBTYPE_ARM_V6) {
133                 mono_hwcap_arm_is_v5 = TRUE;
134                 mono_hwcap_arm_is_v6 = TRUE;
135         } else if (sub_type == CPU_SUBTYPE_ARM_V7 || sub_type == CPU_SUBTYPE_ARM_V7F || sub_type == CPU_SUBTYPE_ARM_V7K) {
136                 mono_hwcap_arm_is_v5 = TRUE;
137                 mono_hwcap_arm_is_v6 = TRUE;
138                 mono_hwcap_arm_is_v7 = TRUE;
139         }
140
141         /* TODO: Find a way to detect features like Thumb and VFP. */
142 #endif
143 }