2 * mono-hwcap-x86.c: x86 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-x86.h"
23 #if defined(HAVE_UNISTD_H)
31 gboolean mono_hwcap_x86_is_xen = FALSE;
32 gboolean mono_hwcap_x86_has_cmov = FALSE;
33 gboolean mono_hwcap_x86_has_fcmov = FALSE;
34 gboolean mono_hwcap_x86_has_sse1 = FALSE;
35 gboolean mono_hwcap_x86_has_sse2 = FALSE;
36 gboolean mono_hwcap_x86_has_sse3 = FALSE;
37 gboolean mono_hwcap_x86_has_ssse3 = FALSE;
38 gboolean mono_hwcap_x86_has_sse41 = FALSE;
39 gboolean mono_hwcap_x86_has_sse42 = FALSE;
40 gboolean mono_hwcap_x86_has_sse4a = FALSE;
42 #if defined(MONO_CROSS_COMPILE)
44 mono_hwcap_arch_init (void)
49 cpuid (int id, int *p_eax, int *p_ebx, int *p_ecx, int *p_edx)
55 /* First, make sure we can use cpuid if we're on 32-bit. */
56 #if defined(TARGET_X86)
57 gboolean have_cpuid = FALSE;
74 __asm__ __volatile__ (
77 "movl\t%%eax, %%edx\n\t"
78 "xorl\t$0x200000, %%eax\n\t"
83 "xorl\t%%edx, %%eax\n\t"
84 "andl\t$0x200000, %%eax\n\t"
96 /* Now issue the actual cpuid instruction. We can use
97 MSVC's __cpuid on both 32-bit and 64-bit. */
104 #elif defined(TARGET_X86)
105 /* This complicated stuff is necessary because EBX
106 may be used by the compiler in PIC mode. */
107 __asm__ __volatile__ (
108 "xchgl\t%%ebx, %k1\n\t"
110 "xchgl\t%%ebx, %k1\n\t"
111 : "=a" (*p_eax), "=&r" (*p_ebx), "=c" (*p_ecx), "=d" (*p_edx)
115 __asm__ __volatile__ (
117 : "=a" (*p_eax), "=b" (*p_ebx), "=c" (*p_ecx), "=d" (*p_edx)
126 mono_hwcap_arch_init (void)
128 int eax, ebx, ecx, edx;
130 if (cpuid (1, &eax, &ebx, &ecx, &edx)) {
131 if (edx & (1 << 15)) {
132 mono_hwcap_x86_has_cmov = TRUE;
135 mono_hwcap_x86_has_fcmov = TRUE;
139 mono_hwcap_x86_has_sse1 = TRUE;
142 mono_hwcap_x86_has_sse2 = TRUE;
145 mono_hwcap_x86_has_sse3 = TRUE;
148 mono_hwcap_x86_has_ssse3 = TRUE;
151 mono_hwcap_x86_has_sse41 = TRUE;
154 mono_hwcap_x86_has_sse42 = TRUE;
157 if (cpuid (0x80000000, &eax, &ebx, &ecx, &edx)) {
158 if ((unsigned int) eax >= 0x80000001 && ebx == 0x68747541 && ecx == 0x444D4163 && edx == 0x69746E65) {
159 if (cpuid (0x80000001, &eax, &ebx, &ecx, &edx)) {
161 mono_hwcap_x86_has_sse4a = TRUE;
166 #if defined(HAVE_UNISTD_H)
167 mono_hwcap_x86_is_xen = !access ("/proc/xen", F_OK);
173 mono_hwcap_print (FILE *f)
175 g_fprintf (f, "mono_hwcap_x86_is_xen = %i\n", mono_hwcap_x86_is_xen);
176 g_fprintf (f, "mono_hwcap_x86_has_cmov = %i\n", mono_hwcap_x86_has_cmov);
177 g_fprintf (f, "mono_hwcap_x86_has_fcmov = %i\n", mono_hwcap_x86_has_fcmov);
178 g_fprintf (f, "mono_hwcap_x86_has_sse1 = %i\n", mono_hwcap_x86_has_sse1);
179 g_fprintf (f, "mono_hwcap_x86_has_sse2 = %i\n", mono_hwcap_x86_has_sse2);
180 g_fprintf (f, "mono_hwcap_x86_has_sse3 = %i\n", mono_hwcap_x86_has_sse3);
181 g_fprintf (f, "mono_hwcap_x86_has_ssse3 = %i\n", mono_hwcap_x86_has_ssse3);
182 g_fprintf (f, "mono_hwcap_x86_has_sse41 = %i\n", mono_hwcap_x86_has_sse41);
183 g_fprintf (f, "mono_hwcap_x86_has_sse42 = %i\n", mono_hwcap_x86_has_sse42);
184 g_fprintf (f, "mono_hwcap_x86_has_sse4a = %i\n", mono_hwcap_x86_has_sse4a);