Merge pull request #2816 from xmcclure/profile-clean-0
[mono.git] / mono / utils / mono-hwcap-x86.c
index 1605539ab17f7d897d883973342c10b6555abaca..4a96aa3a088eeb3d6a646c123c603bb305c29296 100644 (file)
@@ -16,6 +16,7 @@
  * 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;
@@ -97,13 +43,12 @@ gboolean mono_hwcap_x86_has_sse4a = 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)
@@ -122,77 +67,59 @@ cpuid (int id, int *p_eax, int *p_ebx, int *p_ecx, int *p_edx)
        }
 #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)) {
@@ -231,11 +158,22 @@ mono_hwcap_init (void)
                }
        }
 
-#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);
+}