First set of licensing changes
[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  * Licensed under the MIT license. See LICENSE file in the project root for full license information.
20  */
21
22 #include "mono/utils/mono-hwcap-arm.h"
23
24 #if defined(HAVE_SYS_AUXV_H) && !defined(PLATFORM_ANDROID)
25 #include <sys/auxv.h>
26 #elif defined(__APPLE__)
27 #include <mach/machine.h>
28 #include <sys/sysctl.h>
29 #include <sys/types.h>
30 #else
31 #include <stdio.h>
32 #endif
33
34 gboolean mono_hwcap_arm_is_v5 = FALSE;
35 gboolean mono_hwcap_arm_is_v6 = FALSE;
36 gboolean mono_hwcap_arm_is_v7 = FALSE;
37 gboolean mono_hwcap_arm_has_vfp = FALSE;
38 gboolean mono_hwcap_arm_has_vfp3 = FALSE;
39 gboolean mono_hwcap_arm_has_vfp3_d16 = FALSE;
40 gboolean mono_hwcap_arm_has_thumb = FALSE;
41 gboolean mono_hwcap_arm_has_thumb2 = FALSE;
42
43 void
44 mono_hwcap_arch_init (void)
45 {
46 #if defined(HAVE_SYS_AUXV_H) && !defined(PLATFORM_ANDROID)
47         unsigned long hwcap;
48         unsigned long platform;
49
50         if ((hwcap = getauxval(AT_HWCAP))) {
51                 /* HWCAP_ARM_THUMB */
52                 if (hwcap & 0x00000004)
53                         mono_hwcap_arm_has_thumb = TRUE;
54
55                 /* HWCAP_ARM_VFP */
56                 if (hwcap & 0x00000040)
57                         mono_hwcap_arm_has_vfp = TRUE;
58
59                 /* HWCAP_ARM_VFPv3 */
60                 if (hwcap & 0x00002000)
61                         mono_hwcap_arm_has_vfp3 = TRUE;
62
63                 /* HWCAP_ARM_VFPv3D16 */
64                 if (hwcap & 0x00004000)
65                         mono_hwcap_arm_has_vfp3_d16 = TRUE;
66
67                 /* TODO: Find a way to detect Thumb 2. */
68         }
69
70         if ((platform = getauxval(AT_PLATFORM))) {
71                 const char *str = (const char *) platform;
72
73                 if (str [1] >= '5')
74                         mono_hwcap_arm_is_v5 = TRUE;
75
76                 if (str [1] >= '6')
77                         mono_hwcap_arm_is_v6 = TRUE;
78
79                 if (str [1] >= '7')
80                         mono_hwcap_arm_is_v7 = TRUE;
81
82                 /* TODO: Find a way to detect v7s. */
83         }
84 #elif defined(__APPLE__)
85         cpu_subtype_t sub_type;
86         size_t length = sizeof (sub_type);
87
88         sysctlbyname ("hw.cpusubtype", &sub_type, &length, NULL, 0);
89
90         if (sub_type == CPU_SUBTYPE_ARM_V5TEJ || sub_type == CPU_SUBTYPE_ARM_XSCALE) {
91                 mono_hwcap_arm_is_v5 = TRUE;
92         } else if (sub_type == CPU_SUBTYPE_ARM_V6) {
93                 mono_hwcap_arm_is_v5 = TRUE;
94                 mono_hwcap_arm_is_v6 = TRUE;
95         } else if (sub_type == CPU_SUBTYPE_ARM_V7 || sub_type == CPU_SUBTYPE_ARM_V7F || sub_type == CPU_SUBTYPE_ARM_V7K) {
96                 mono_hwcap_arm_is_v5 = TRUE;
97                 mono_hwcap_arm_is_v6 = TRUE;
98                 mono_hwcap_arm_is_v7 = TRUE;
99         }
100
101         /* TODO: Find a way to detect features like Thumb and VFP. */
102 #else
103         /* We can't use the auxiliary vector on Android due to
104          * permissions, so fall back to /proc/cpuinfo. We also
105          * hit this path if the target doesn't have sys/auxv.h.
106          */
107
108         char buf [512];
109         char *line;
110
111         FILE *file = fopen ("/proc/cpuinfo", "r");
112
113         if (file) {
114                 while ((line = fgets (buf, 512, file))) {
115                         if (!strncmp (line, "Processor", 9)) {
116                                 char *ver = strstr (line, "(v");
117
118                                 if (ver) {
119                                         if (ver [2] >= '5')
120                                                 mono_hwcap_arm_is_v5 = TRUE;
121
122                                         if (ver [2] >= '6')
123                                                 mono_hwcap_arm_is_v6 = TRUE;
124
125                                         if (ver [2] >= '7')
126                                                 mono_hwcap_arm_is_v7 = TRUE;
127
128                                         /* TODO: Find a way to detect v7s. */
129                                 }
130
131                                 continue;
132                         }
133
134                         if (!strncmp (line, "Features", 8)) {
135                                 if (strstr (line, "thumb"))
136                                         mono_hwcap_arm_has_thumb = TRUE;
137
138                                 /* TODO: Find a way to detect Thumb 2. */
139
140                                 if (strstr (line, "vfp"))
141                                         mono_hwcap_arm_has_vfp = TRUE;
142
143                                 if (strstr (line, "vfpv3"))
144                                         mono_hwcap_arm_has_vfp3 = TRUE;
145
146                                 if (strstr (line, "vfpv3-d16"))
147                                         mono_hwcap_arm_has_vfp3_d16 = TRUE;
148
149                                 continue;
150                         }
151                 }
152
153                 fclose (file);
154         }
155 #endif
156 }
157
158 void
159 mono_hwcap_print(FILE *f)
160 {
161         g_fprintf (f, "mono_hwcap_arm_is_v5 = %i\n", mono_hwcap_arm_is_v5);
162         g_fprintf (f, "mono_hwcap_arm_is_v6 = %i\n", mono_hwcap_arm_is_v6);
163         g_fprintf (f, "mono_hwcap_arm_is_v7 = %i\n", mono_hwcap_arm_is_v7);
164         g_fprintf (f, "mono_hwcap_arm_has_vfp = %i\n", mono_hwcap_arm_has_vfp);
165         g_fprintf (f, "mono_hwcap_arm_has_vfp3 = %i\n", mono_hwcap_arm_has_vfp3);
166         g_fprintf (f, "mono_hwcap_arm_has_vfp3_d16 = %i\n", mono_hwcap_arm_has_vfp3_d16);
167         g_fprintf (f, "mono_hwcap_arm_has_thumb = %i\n", mono_hwcap_arm_has_thumb);
168         g_fprintf (f, "mono_hwcap_arm_has_thumb2 = %i\n", mono_hwcap_arm_has_thumb2);
169 }