* 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-x86.h"
#include <unistd.h>
#endif
-#if defined(TARGET_X86)
-#include "mono/utils/mono-codeman.h"
-
-typedef void (* CpuidFunc) (int id, int *p_eax, int *p_ebx, int *p_ecx, int *p_edx);
-
-static MonoCodeManager *code_man;
-static CpuidFunc func;
-
-#if defined(__native_client__)
-static const guchar cpuid_impl [] = {
- 0x55, /* push %ebp */
- 0x89, 0xe5, /* mov %esp, %ebp */
- 0x53, /* push %ebx */
- 0x8b, 0x45, 0x08, /* mov 0x8 (%ebp), %eax */
- 0x0f, 0xa2, /* cpuid */
- 0x50, /* push %eax */
- 0x8b, 0x45, 0x10, /* mov 0x10 (%ebp), %eax */
- 0x89, 0x18, /* mov %ebx, (%eax) */
- 0x8b, 0x45, 0x14, /* mov 0x14 (%ebp), %eax */
- 0x89, 0x08, /* mov %ecx, (%eax) */
- 0x8b, 0x45, 0x18, /* mov 0x18 (%ebp), %eax */
- 0x89, 0x10, /* mov %edx, (%eax) */
- 0x58, /* pop %eax */
- 0x8b, 0x55, 0x0c, /* mov 0xc (%ebp), %edx */
- 0x89, 0x02, /* mov %eax, (%edx) */
- 0x5b, /* pop %ebx */
- 0xc9, /* leave */
- 0x59, 0x83, 0xe1, 0xe0, 0xff, 0xe1, /* naclret */
- 0xf4, 0xf4, 0xf4, 0xf4, 0xf4, 0xf4, /* padding, to provide bundle aligned version */
- 0xf4, 0xf4, 0xf4, 0xf4, 0xf4, 0xf4,
- 0xf4, 0xf4, 0xf4, 0xf4, 0xf4, 0xf4,
- 0xf4, 0xf4, 0xf4, 0xf4, 0xf4, 0xf4,
- 0xf4,
-};
-#else
-static const guchar cpuid_impl [] = {
- 0x55, /* push %ebp */
- 0x89, 0xe5, /* mov %esp, %ebp */
- 0x53, /* push %ebx */
- 0x8b, 0x45, 0x08, /* mov 0x8 (%ebp), %eax */
- 0x0f, 0xa2, /* cpuid */
- 0x50, /* push %eax */
- 0x8b, 0x45, 0x10, /* mov 0x10 (%ebp), %eax */
- 0x89, 0x18, /* mov %ebx, (%eax) */
- 0x8b, 0x45, 0x14, /* mov 0x14 (%ebp), %eax */
- 0x89, 0x08, /* mov %ecx, (%eax) */
- 0x8b, 0x45, 0x18, /* mov 0x18 (%ebp), %eax */
- 0x89, 0x10, /* mov %edx, (%eax) */
- 0x58, /* pop %eax */
- 0x8b, 0x55, 0x0c, /* mov 0xc (%ebp), %edx */
- 0x89, 0x02, /* mov %eax, (%edx) */
- 0x5b, /* pop %ebx */
- 0xc9, /* leave */
- 0xc3, /* ret */
-};
-#endif
-
+#if defined(_MSC_VER)
+#include <intrin.h>
#endif
gboolean mono_hwcap_x86_is_xen = FALSE;
static gboolean
cpuid (int id, int *p_eax, int *p_ebx, int *p_ecx, int *p_edx)
{
-#if defined(TARGET_X86)
-
-#if defined(__native_client__)
- func (id, p_eax, p_ebx, p_ecx, p_edx);
+#if defined(_MSC_VER)
+ int info [4];
+#endif
- return TRUE;
-#else
+ /* First, make sure we can use cpuid if we're on 32-bit. */
+#if defined(TARGET_X86)
gboolean have_cpuid = FALSE;
#if defined(_MSC_VER)
}
#else
__asm__ __volatile__ (
- "pushfl\n"
- "popl %%eax\n"
- "movl %%eax, %%edx\n"
- "xorl $0x200000, %%eax\n"
- "pushl %%eax\n"
- "popfl\n"
- "pushfl\n"
- "popl %%eax\n"
- "xorl %%edx, %%eax\n"
- "andl $0x200000, %%eax\n"
- "movl %%eax, %0"
+ "pushfl\n\t"
+ "popl\t%%eax\n\t"
+ "movl\t%%eax, %%edx\n\t"
+ "xorl\t$0x200000, %%eax\n\t"
+ "pushl\t%%eax\n\t"
+ "popfl\n\t"
+ "pushfl\n\t"
+ "popl\t%%eax\n\t"
+ "xorl\t%%edx, %%eax\n\t"
+ "andl\t$0x200000, %%eax\n\t"
+ "movl\t%%eax, %0\n\t"
: "=r" (have_cpuid)
:
: "%eax", "%edx"
);
#endif
- if (have_cpuid) {
- func (id, p_eax, p_ebx, p_ecx, p_edx);
-
- return TRUE;
- }
-
- return FALSE;
+ if (!have_cpuid)
+ return FALSE;
#endif
-#else
-
+ /* Now issue the actual cpuid instruction. We can use
+ MSVC's __cpuid on both 32-bit and 64-bit. */
#if defined(_MSC_VER)
- int info [4];
__cpuid (info, id);
*p_eax = info [0];
*p_ebx = info [1];
*p_ecx = info [2];
*p_edx = info [3];
+#elif defined(TARGET_X86)
+ /* This complicated stuff is necessary because EBX
+ may be used by the compiler in PIC mode. */
+ __asm__ __volatile__ (
+ "xchgl\t%%ebx, %k1\n\t"
+ "cpuid\n\t"
+ "xchgl\t%%ebx, %k1\n\t"
+ : "=a" (*p_eax), "=&r" (*p_ebx), "=c" (*p_ecx), "=d" (*p_edx)
+ : "0" (id)
+ );
#else
__asm__ __volatile__ (
- "cpuid"
+ "cpuid\n\t"
: "=a" (*p_eax), "=b" (*p_ebx), "=c" (*p_ecx), "=d" (*p_edx)
: "a" (id)
);
#endif
return TRUE;
-#endif
}
void
-mono_hwcap_init (void)
+mono_hwcap_arch_init (void)
{
-#if defined(TARGET_X86)
- code_man = mono_code_manager_new ();
-
-#if defined(__native_client__)
- gpointer ptr = mono_code_manager_reserve (code_man, sizeof (cpuid_impl));
- memcpy (ptr, cpuid_impl, sizeof (cpuid_impl));
- gpointer end_ptr = ptr + sizeof (cpuid_impl);
-
- guint8 *code = nacl_code_manager_get_dest (code_man, ptr);
- mono_code_manager_commit (code_man, ptr, sizeof (cpuid_impl), end_ptr - ptr);
-
- func = (CpuidFunc) code;
-#else
- gpointer ptr = mono_code_manager_reserve (code_man, sizeof (cpuid_impl));
- memcpy (ptr, cpuid_impl, sizeof (cpuid_impl));
-
- func = (CpuidFunc) ptr;
-#endif
-
-#endif
-
int eax, ebx, ecx, edx;
if (cpuid (1, &eax, &ebx, &ecx, &edx)) {
}
}
-#if defined(TARGET_X86)
- mono_code_manager_destroy (code_man);
-#endif
-
#if defined(HAVE_UNISTD_H)
mono_hwcap_x86_is_xen = !access ("/proc/xen", F_OK);
#endif
}
+
+void
+mono_hwcap_print (FILE *f)
+{
+ g_fprintf (f, "mono_hwcap_x86_is_xen = %i\n", mono_hwcap_x86_is_xen);
+ g_fprintf (f, "mono_hwcap_x86_has_cmov = %i\n", mono_hwcap_x86_has_cmov);
+ g_fprintf (f, "mono_hwcap_x86_has_fcmov = %i\n", mono_hwcap_x86_has_fcmov);
+ g_fprintf (f, "mono_hwcap_x86_has_sse1 = %i\n", mono_hwcap_x86_has_sse1);
+ g_fprintf (f, "mono_hwcap_x86_has_sse2 = %i\n", mono_hwcap_x86_has_sse2);
+ g_fprintf (f, "mono_hwcap_x86_has_sse3 = %i\n", mono_hwcap_x86_has_sse3);
+ g_fprintf (f, "mono_hwcap_x86_has_ssse3 = %i\n", mono_hwcap_x86_has_ssse3);
+ g_fprintf (f, "mono_hwcap_x86_has_sse41 = %i\n", mono_hwcap_x86_has_sse41);
+ g_fprintf (f, "mono_hwcap_x86_has_sse42 = %i\n", mono_hwcap_x86_has_sse42);
+ g_fprintf (f, "mono_hwcap_x86_has_sse4a = %i\n", mono_hwcap_x86_has_sse4a);
+}