[msvc] Update csproj files (#4315)
[mono.git] / mono / mini / mini-x86.c
index aafc380d8f98af47218d0440dcaf78d9f6ca6161..b616059dfb6d2f836b2d702ac380d3b54ddb1c6a 100644 (file)
@@ -29,7 +29,7 @@
 #include <mono/utils/mono-counters.h>
 #include <mono/utils/mono-mmap.h>
 #include <mono/utils/mono-memory-model.h>
-#include <mono/utils/mono-hwcap-x86.h>
+#include <mono/utils/mono-hwcap.h>
 #include <mono/utils/mono-threads.h>
 
 #include "trace.h"
@@ -63,9 +63,9 @@ static mono_mutex_t mini_arch_mutex;
 
 #ifdef TARGET_WIN32
 /* Under windows, the default pinvoke calling convention is stdcall */
-#define CALLCONV_IS_STDCALL(sig) ((((sig)->call_convention) == MONO_CALL_STDCALL) || ((sig)->pinvoke && ((sig)->call_convention) == MONO_CALL_DEFAULT) || ((sig)->pinvoke && ((sig)->call_convention) == MONO_CALL_THISCALL))
+#define CALLCONV_IS_STDCALL(sig) ((sig)->pinvoke && ((sig)->call_convention == MONO_CALL_STDCALL || (sig)->call_convention == MONO_CALL_DEFAULT || (sig)->call_convention == MONO_CALL_THISCALL))
 #else
-#define CALLCONV_IS_STDCALL(sig) (((sig)->call_convention) == MONO_CALL_STDCALL || ((sig)->pinvoke && ((sig)->call_convention) == MONO_CALL_THISCALL))
+#define CALLCONV_IS_STDCALL(sig) ((sig)->pinvoke && ((sig)->call_convention == MONO_CALL_STDCALL || (sig)->call_convention == MONO_CALL_THISCALL))
 #endif
 
 #define X86_IS_CALLEE_SAVED_REG(reg) (((reg) == X86_EBX) || ((reg) == X86_EDI) || ((reg) == X86_ESI))
@@ -543,7 +543,7 @@ get_call_info_internal (CallInfo *cinfo, MonoMethodSignature *sig)
        if (cinfo->vtype_retaddr) {
                /* if the function returns a struct on stack, the called method already does a ret $0x4 */
                cinfo->callee_stack_pop = 4;
-       } else if (CALLCONV_IS_STDCALL (sig) && sig->pinvoke) {
+       } else if (CALLCONV_IS_STDCALL (sig)) {
                /* Have to compensate for the stack space popped by the native callee */
                cinfo->callee_stack_pop = stack_size;
        }
@@ -2239,22 +2239,22 @@ emit_move_return_value (MonoCompile *cfg, MonoInst *ins, guint8 *code)
        return code;
 }
 
-#ifdef __APPLE__
+#ifdef TARGET_MACH
 static int tls_gs_offset;
 #endif
 
 gboolean
-mono_x86_have_tls_get (void)
+mono_arch_have_fast_tls (void)
 {
 #ifdef TARGET_MACH
-       static gboolean have_tls_get = FALSE;
+       static gboolean have_fast_tls = FALSE;
        static gboolean inited = FALSE;
+       guint32 *ins;
 
+       if (mini_get_debug_options ()->use_fallback_tls)
+               return FALSE;
        if (inited)
-               return have_tls_get;
-
-#ifdef MONO_HAVE_FAST_TLS
-       guint32 *ins;
+               return have_fast_tls;
 
        ins = (guint32*)pthread_getspecific;
        /*
@@ -2263,56 +2263,29 @@ mono_x86_have_tls_get (void)
         * mov    0x4(%esp),%eax
         * mov    %gs:[offset](,%eax,4),%eax
         */
-       have_tls_get = ins [0] == 0x0424448b && ins [1] == 0x85048b65;
+       have_fast_tls = ins [0] == 0x0424448b && ins [1] == 0x85048b65;
        tls_gs_offset = ins [2];
-#endif
-
        inited = TRUE;
 
-       return have_tls_get;
+       return have_fast_tls;
 #elif defined(TARGET_ANDROID)
        return FALSE;
 #else
+       if (mini_get_debug_options ()->use_fallback_tls)
+               return FALSE;
        return TRUE;
 #endif
 }
 
 static guint8*
-mono_x86_emit_tls_set (guint8* code, int sreg, int tls_offset)
-{
-#if defined(__APPLE__)
-       x86_prefix (code, X86_GS_PREFIX);
-       x86_mov_mem_reg (code, tls_gs_offset + (tls_offset * 4), sreg, 4);
-#elif defined(TARGET_WIN32)
-       g_assert_not_reached ();
-#else
-       x86_prefix (code, X86_GS_PREFIX);
-       x86_mov_mem_reg (code, tls_offset, sreg, 4);
-#endif
-       return code;
-}
-
-/*
- * mono_x86_emit_tls_get:
- * @code: buffer to store code to
- * @dreg: hard register where to place the result
- * @tls_offset: offset info
- *
- * mono_x86_emit_tls_get emits in @code the native code that puts in
- * the dreg register the item in the thread local storage identified
- * by tls_offset.
- *
- * Returns: a pointer to the end of the stored code
- */
-guint8*
 mono_x86_emit_tls_get (guint8* code, int dreg, int tls_offset)
 {
-#if defined(__APPLE__)
+#if defined(TARGET_MACH)
        x86_prefix (code, X86_GS_PREFIX);
        x86_mov_reg_mem (code, dreg, tls_gs_offset + (tls_offset * 4), 4);
 #elif defined(TARGET_WIN32)
-       /* 
-        * See the Under the Hood article in the May 1996 issue of Microsoft Systems 
+       /*
+        * See the Under the Hood article in the May 1996 issue of Microsoft Systems
         * Journal and/or a disassembly of the TlsGet () function.
         */
        x86_prefix (code, X86_FS_PREFIX);
@@ -2345,55 +2318,19 @@ mono_x86_emit_tls_get (guint8* code, int dreg, int tls_offset)
 }
 
 static guint8*
-emit_tls_get_reg (guint8* code, int dreg, int offset_reg)
+mono_x86_emit_tls_set (guint8* code, int sreg, int tls_offset)
 {
-       /* offset_reg contains a value translated by mono_arch_translate_tls_offset () */
-#if defined(__APPLE__) || defined(__linux__)
-       if (dreg != offset_reg)
-               x86_mov_reg_reg (code, dreg, offset_reg, sizeof (mgreg_t));
+#if defined(TARGET_MACH)
        x86_prefix (code, X86_GS_PREFIX);
-       x86_mov_reg_membase (code, dreg, dreg, 0, sizeof (mgreg_t));
-#else
-       g_assert_not_reached ();
-#endif
-       return code;
-}
-
-guint8*
-mono_x86_emit_tls_get_reg (guint8* code, int dreg, int offset_reg)
-{
-       return emit_tls_get_reg (code, dreg, offset_reg);
-}
-
-static guint8*
-emit_tls_set_reg (guint8* code, int sreg, int offset_reg)
-{
-       /* offset_reg contains a value translated by mono_arch_translate_tls_offset () */
-#ifdef HOST_WIN32
+       x86_mov_mem_reg (code, tls_gs_offset + (tls_offset * 4), sreg, 4);
+#elif defined(TARGET_WIN32)
        g_assert_not_reached ();
-#elif defined(__APPLE__) || defined(__linux__)
-       x86_prefix (code, X86_GS_PREFIX);
-       x86_mov_membase_reg (code, offset_reg, 0, sreg, sizeof (mgreg_t));
 #else
-       g_assert_not_reached ();
+       x86_prefix (code, X86_GS_PREFIX);
+       x86_mov_mem_reg (code, tls_offset, sreg, 4);
 #endif
        return code;
 }
- /*
- * mono_arch_translate_tls_offset:
- *
- *   Translate the TLS offset OFFSET computed by MONO_THREAD_VAR_OFFSET () into a format usable by OP_TLS_GET_REG/OP_TLS_SET_REG.
- */
-int
-mono_arch_translate_tls_offset (int offset)
-{
-#ifdef __APPLE__
-       return tls_gs_offset + (offset * 4);
-#else
-       return offset;
-#endif
-}
 
 /*
  * emit_setup_lmf:
@@ -4151,18 +4088,10 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb)
                        code = mono_x86_emit_tls_get (code, ins->dreg, ins->inst_offset);
                        break;
                }
-               case OP_TLS_GET_REG: {
-                       code = emit_tls_get_reg (code, ins->dreg, ins->sreg1);
-                       break;
-               }
                case OP_TLS_SET: {
                        code = mono_x86_emit_tls_set (code, ins->sreg1, ins->inst_offset);
                        break;
                }
-               case OP_TLS_SET_REG: {
-                       code = emit_tls_set_reg (code, ins->sreg1, ins->sreg2);
-                       break;
-               }
                case OP_MEMORY_BARRIER: {
                        if (ins->backend.memory_barrier_kind == MONO_MEMORY_BARRIER_SEQ) {
                                x86_prefix (code, X86_LOCK_PREFIX);
@@ -4872,6 +4801,9 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb)
                case OP_XZERO:
                        x86_sse_alu_pd_reg_reg (code, X86_SSE_PXOR, ins->dreg, ins->dreg);
                        break;
+               case OP_XONES:
+                       x86_sse_alu_pd_reg_reg (code, X86_SSE_PCMPEQB, ins->dreg, ins->dreg);
+                       break;
 
                case OP_FCONV_TO_R8_X:
                        x86_fst_membase (code, ins->backend.spill_var->inst_basereg, ins->backend.spill_var->inst_offset, TRUE, TRUE);
@@ -5325,40 +5257,29 @@ mono_arch_emit_epilog (MonoCompile *cfg)
        if (method->save_lmf) {
                gint32 lmf_offset = cfg->lmf_var->inst_offset;
                guint8 *patch;
-               gboolean supported = FALSE;
-
-               if (cfg->compile_aot) {
-#if defined(MONO_HAVE_FAST_TLS)
-                       supported = TRUE;
-#endif
-               } else if (mono_get_jit_tls_offset () != -1) {
-                       supported = TRUE;
-               }
 
                /* check if we need to restore protection of the stack after a stack overflow */
-               if (supported) {
-                       if (cfg->compile_aot) {
-                               code = emit_load_aotconst (NULL, code, cfg, NULL, X86_ECX, MONO_PATCH_INFO_TLS_OFFSET, GINT_TO_POINTER (TLS_KEY_JIT_TLS));
-
-                               code = emit_tls_get_reg (code, X86_ECX, X86_ECX);
-                       } else {
-                               code = mono_x86_emit_tls_get (code, X86_ECX, mono_get_jit_tls_offset ());
-                       }
-
-                       /* we load the value in a separate instruction: this mechanism may be
-                        * used later as a safer way to do thread interruption
-                        */
-                       x86_mov_reg_membase (code, X86_ECX, X86_ECX, MONO_STRUCT_OFFSET (MonoJitTlsData, restore_stack_prot), 4);
-                       x86_alu_reg_imm (code, X86_CMP, X86_ECX, 0);
-                       patch = code;
-                       x86_branch8 (code, X86_CC_Z, 0, FALSE);
-                       /* note that the call trampoline will preserve eax/edx */
-                       x86_call_reg (code, X86_ECX);
-                       x86_patch (patch, code);
+               if (!cfg->compile_aot && mono_arch_have_fast_tls () && mono_tls_get_tls_offset (TLS_KEY_JIT_TLS) != -1) {
+                       code = mono_x86_emit_tls_get (code, X86_ECX, mono_tls_get_tls_offset (TLS_KEY_JIT_TLS));
                } else {
-                       /* FIXME: maybe save the jit tls in the prolog */
+                       gpointer func = mono_tls_get_tls_getter (TLS_KEY_JIT_TLS, TRUE);
+                       /* FIXME use tls only from IR level */
+                       x86_xchg_reg_reg (code, X86_EAX, X86_ECX, 4);
+                       code = emit_call (cfg, code, MONO_PATCH_INFO_INTERNAL_METHOD, func);
+                       x86_xchg_reg_reg (code, X86_EAX, X86_ECX, 4);
                }
 
+               /* we load the value in a separate instruction: this mechanism may be
+                * used later as a safer way to do thread interruption
+                */
+               x86_mov_reg_membase (code, X86_ECX, X86_ECX, MONO_STRUCT_OFFSET (MonoJitTlsData, restore_stack_prot), 4);
+               x86_alu_reg_imm (code, X86_CMP, X86_ECX, 0);
+               patch = code;
+               x86_branch8 (code, X86_CC_Z, 0, FALSE);
+               /* note that the call trampoline will preserve eax/edx */
+               x86_call_reg (code, X86_ECX);
+               x86_patch (patch, code);
+
                /* restore caller saved regs */
                if (cfg->used_int_regs & (1 << X86_EBX)) {
                        x86_mov_reg_membase (code, X86_EBX, cfg->frame_reg, lmf_offset + MONO_STRUCT_OFFSET (MonoLMF, ebx), 4);
@@ -5613,7 +5534,7 @@ imt_branch_distance (MonoIMTCheckItem **imt_entries, int start, int target)
  * LOCKING: called with the domain lock held
  */
 gpointer
-mono_arch_build_imt_thunk (MonoVTable *vtable, MonoDomain *domain, MonoIMTCheckItem **imt_entries, int count,
+mono_arch_build_imt_trampoline (MonoVTable *vtable, MonoDomain *domain, MonoIMTCheckItem **imt_entries, int count,
        gpointer fail_tramp)
 {
        int i;
@@ -5645,7 +5566,7 @@ mono_arch_build_imt_thunk (MonoVTable *vtable, MonoDomain *domain, MonoIMTCheckI
                size += item->chunk_size;
        }
        if (fail_tramp)
-               code = mono_method_alloc_generic_virtual_thunk (domain, size);
+               code = mono_method_alloc_generic_virtual_trampoline (domain, size);
        else
                code = mono_domain_code_reserve (domain, size);
        start = code;
@@ -5715,7 +5636,7 @@ mono_arch_build_imt_thunk (MonoVTable *vtable, MonoDomain *domain, MonoIMTCheckI
        }
 
        if (!fail_tramp)
-               mono_stats.imt_thunks_size += code - start;
+               mono_stats.imt_trampolines_size += code - start;
        g_assert (code - start <= size);
 
 #if DEBUG_IMT
@@ -5730,7 +5651,7 @@ mono_arch_build_imt_thunk (MonoVTable *vtable, MonoDomain *domain, MonoIMTCheckI
                if (vtable)
                        buff = g_strdup_printf ("imt_%s_%s_entries_%d", vtable->klass->name_space, vtable->klass->name, count);
                else
-                       buff = g_strdup_printf ("imt_thunk_entries_%d", count);
+                       buff = g_strdup_printf ("imt_trampoline_entries_%d", count);
                mono_emit_jit_tramp (start, code - start, buff);
                g_free (buff);
        }