2004-02-16 Zoltan Varga <vargaz@freemail.hu>
[mono.git] / mono / mini / mini-x86.c
index 34761bbc7cc3758c629d376fe00c368570fe070b..de32a0a1fea0e52eab0ddb85324bb8347b45a008 100644 (file)
@@ -4,6 +4,7 @@
  * Authors:
  *   Paolo Molaro (lupus@ximian.com)
  *   Dietmar Maurer (dietmar@ximian.com)
+ *   Patrik Torstensson
  *
  * (C) 2003 Ximian, Inc.
  */
 
 static gint lmf_tls_offset = -1;
 
+#ifdef PLATFORM_WIN32
+/* Under windows, the default pinvoke calling convention is stdcall */
+#define CALLCONV_IS_STDCALL(call_conv) (((call_conv) == MONO_CALL_STDCALL) || ((call_conv) == MONO_CALL_DEFAULT))
+#else
+#define CALLCONV_IS_STDCALL(call_conv) ((call_conv) == MONO_CALL_STDCALL)
+#endif
+
+static gpointer mono_arch_get_lmf_addr (void);
+
 const char*
 mono_arch_regname (int reg) {
        switch (reg) {
@@ -104,11 +114,15 @@ arch_get_argument_info (MonoMethodSignature *csig, int param_count, MonoJitArgum
 static int indent_level = 0;
 
 static void indent (int diff) {
-       int v = indent_level;
+       int v;
+       if (diff < 0)
+               indent_level += diff;
+       v = indent_level;
        while (v-- > 0) {
                printf (". ");
        }
-       indent_level += diff;
+       if (diff > 0)
+               indent_level += diff;
 }
 
 static gboolean enable_trace = TRUE;
@@ -1251,7 +1265,7 @@ typedef struct {
        int killed_in;
        int last_use;
        int prev_use;
-       int fpflags;    /* used to track if we spill/load */
+       int flags;              /* used to track fp spill/load */
 } RegTrack;
 
 static const char*const * ins_spec = pentium_desc;
@@ -1494,10 +1508,10 @@ alloc_int_reg (MonoCompile *cfg, InstList *curinst, MonoInst *ins, int sym_reg,
 }
 #endif
 
-/* flags used in reginfo->fpflags */
-#define MONO_X86_FP_NEEDS_LOAD_SPILL   32
-#define MONO_X86_FP_NEEDS_SPILL        64
-#define MONO_X86_FP_NEEDS_LOAD         128
+/* flags used in reginfo->flags */
+#define MONO_X86_FP_NEEDS_LOAD_SPILL   1
+#define MONO_X86_FP_NEEDS_SPILL                        2
+#define MONO_X86_FP_NEEDS_LOAD                 4
 
 /*#include "cprop.c"*/
 
@@ -1551,7 +1565,7 @@ mono_arch_local_regalloc (MonoCompile *cfg, MonoBasicBlock *bb)
 
                                spill = g_list_first (fspill_list);
                                if (spill && fpcount < MONO_MAX_FREGS) {
-                                       reginfo1 [ins->sreg1].fpflags |= MONO_X86_FP_NEEDS_LOAD;
+                                       reginfo1 [ins->sreg1].flags |= MONO_X86_FP_NEEDS_LOAD;
                                        fspill_list = g_list_remove (fspill_list, spill->data);
                                } else
                                        fpcount--;
@@ -1569,12 +1583,12 @@ mono_arch_local_regalloc (MonoCompile *cfg, MonoBasicBlock *bb)
                                reginfo2 = reginfof;
                                spill = g_list_first (fspill_list);
                                if (spill) {
-                                       reginfo2 [ins->sreg2].fpflags |= MONO_X86_FP_NEEDS_LOAD;
+                                       reginfo2 [ins->sreg2].flags |= MONO_X86_FP_NEEDS_LOAD;
                                        fspill_list = g_list_remove (fspill_list, spill->data);
                                        if (fpcount >= MONO_MAX_FREGS) {
                                                fspill++;
                                                fspill_list = g_list_prepend (fspill_list, GINT_TO_POINTER(fspill));
-                                               reginfo2 [ins->sreg2].fpflags |= MONO_X86_FP_NEEDS_LOAD_SPILL;
+                                               reginfo2 [ins->sreg2].flags |= MONO_X86_FP_NEEDS_LOAD_SPILL;
                                        }
                                } else
                                        fpcount--;
@@ -1590,7 +1604,7 @@ mono_arch_local_regalloc (MonoCompile *cfg, MonoBasicBlock *bb)
                        if (spec [MONO_INST_DEST] == 'f') {
                                reginfod = reginfof;
                                if (fpcount >= MONO_MAX_FREGS) {
-                                       reginfod [ins->dreg].fpflags |= MONO_X86_FP_NEEDS_SPILL;
+                                       reginfod [ins->dreg].flags |= MONO_X86_FP_NEEDS_SPILL;
                                        fspill++;
                                        fspill_list = g_list_prepend (fspill_list, GINT_TO_POINTER(fspill));
                                        fpcount--;
@@ -1771,7 +1785,7 @@ mono_arch_local_regalloc (MonoCompile *cfg, MonoBasicBlock *bb)
 
                /* Track dreg */
                if (spec [MONO_INST_DEST] == 'f') {
-                       if (reginfof [ins->dreg].fpflags & MONO_X86_FP_NEEDS_SPILL) {
+                       if (reginfof [ins->dreg].flags & MONO_X86_FP_NEEDS_SPILL) {
                                GList *spill_node;
                                MonoInst *store;
                                spill_node = g_list_first (fspill_list);
@@ -1873,11 +1887,11 @@ mono_arch_local_regalloc (MonoCompile *cfg, MonoBasicBlock *bb)
 
                /* Track sreg1 */
                if (spec [MONO_INST_SRC1] == 'f') {
-                       if (reginfof [ins->sreg1].fpflags & MONO_X86_FP_NEEDS_LOAD) {
+                       if (reginfof [ins->sreg1].flags & MONO_X86_FP_NEEDS_LOAD) {
                                MonoInst *load;
                                MonoInst *store = NULL;
 
-                               if (reginfof [ins->sreg1].fpflags & MONO_X86_FP_NEEDS_LOAD_SPILL) {
+                               if (reginfof [ins->sreg1].flags & MONO_X86_FP_NEEDS_LOAD_SPILL) {
                                        GList *spill_node;
                                        spill_node = g_list_first (fspill_list);
                                        g_assert (spill_node);
@@ -1951,16 +1965,16 @@ mono_arch_local_regalloc (MonoCompile *cfg, MonoBasicBlock *bb)
                }
                /* track sreg2 */
                if (spec [MONO_INST_SRC2] == 'f') {
-                       if (reginfof [ins->sreg2].fpflags & MONO_X86_FP_NEEDS_LOAD) {
+                       if (reginfof [ins->sreg2].flags & MONO_X86_FP_NEEDS_LOAD) {
                                MonoInst *load;
                                MonoInst *store = NULL;
 
-                               if (reginfof [ins->sreg2].fpflags & MONO_X86_FP_NEEDS_LOAD_SPILL) {
+                               if (reginfof [ins->sreg2].flags & MONO_X86_FP_NEEDS_LOAD_SPILL) {
                                        GList *spill_node;
 
                                        spill_node = g_list_first (fspill_list);
                                        g_assert (spill_node);
-                                       if (spec [MONO_INST_SRC1] == 'f' && (reginfof [ins->sreg1].fpflags & MONO_X86_FP_NEEDS_LOAD_SPILL))
+                                       if (spec [MONO_INST_SRC1] == 'f' && (reginfof [ins->sreg1].flags & MONO_X86_FP_NEEDS_LOAD_SPILL))
                                                spill_node = g_list_next (spill_node);
        
                                        store = create_spilled_store_float (cfg, GPOINTER_TO_INT (spill_node->data), ins->sreg2, ins);
@@ -2558,7 +2572,7 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb)
                                mono_add_patch_info (cfg, offset, MONO_PATCH_INFO_ABS, call->fptr);
                        }
                        x86_call_code (code, 0);
-                       if (call->stack_usage && (call->signature->call_convention != MONO_CALL_STDCALL))
+                       if (call->stack_usage && !CALLCONV_IS_STDCALL (call->signature->call_convention))
                                x86_alu_reg_imm (code, X86_ADD, X86_ESP, call->stack_usage);
                        break;
                case OP_FCALL_REG:
@@ -2568,7 +2582,7 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb)
                case OP_CALL_REG:
                        call = (MonoCallInst*)ins;
                        x86_call_reg (code, ins->sreg1);
-                       if (call->stack_usage && (call->signature->call_convention != MONO_CALL_STDCALL))
+                       if (call->stack_usage && !CALLCONV_IS_STDCALL (call->signature->call_convention))
                                x86_alu_reg_imm (code, X86_ADD, X86_ESP, call->stack_usage);
                        break;
                case OP_FCALL_MEMBASE:
@@ -2578,7 +2592,7 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb)
                case OP_CALL_MEMBASE:
                        call = (MonoCallInst*)ins;
                        x86_call_membase (code, ins->sreg1, ins->inst_offset);
-                       if (call->stack_usage && (call->signature->call_convention != MONO_CALL_STDCALL))
+                       if (call->stack_usage && !CALLCONV_IS_STDCALL (call->signature->call_convention))
                                x86_alu_reg_imm (code, X86_ADD, X86_ESP, call->stack_usage);
                        break;
                case OP_OUTARG:
@@ -3202,6 +3216,7 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb)
 void
 mono_arch_register_lowlevel_calls (void)
 {
+       mono_register_jit_icall (mono_arch_get_lmf_addr, "mono_arch_get_lmf_addr", NULL, TRUE);
        mono_register_jit_icall (enter_method, "mono_enter_method", NULL, TRUE);
        mono_register_jit_icall (leave_method, "mono_leave_method", NULL, TRUE);
 }
@@ -3244,7 +3259,7 @@ mono_arch_patch_code (MonoMethod *method, MonoDomain *domain, guint8 *code, Mono
                        GSList *list;
 
                        /* get the trampoline to the method from the domain */
-                       target = mono_arch_create_jump_trampoline (patch_info->data.method);
+                       target = mono_create_jump_trampoline (domain, patch_info->data.method, TRUE);
                        if (!domain->jump_target_hash)
                                domain->jump_target_hash = g_hash_table_new (NULL, NULL);
                        list = g_hash_table_lookup (domain->jump_target_hash, patch_info->data.method);
@@ -3425,8 +3440,13 @@ mono_arch_emit_prolog (MonoCompile *cfg)
                        x86_mov_reg_membase (code, X86_EAX, X86_EAX, lmf_tls_offset, 4);
                }
                else {
+#ifdef HAVE_KW_THREAD
+                       mono_add_patch_info (cfg, code - cfg->native_code, MONO_PATCH_INFO_INTERNAL_METHOD, 
+                                                                (gpointer)"mono_arch_get_lmf_addr");
+#else
                        mono_add_patch_info (cfg, code - cfg->native_code, MONO_PATCH_INFO_INTERNAL_METHOD, 
                                                                 (gpointer)"mono_get_lmf_addr");
+#endif
                        x86_call_code (code, 0);
                }
 
@@ -3578,7 +3598,7 @@ mono_arch_emit_epilog (MonoCompile *cfg)
 
        x86_leave (code);
 
-       if (sig->call_convention == MONO_CALL_STDCALL) {
+       if (CALLCONV_IS_STDCALL (sig->call_convention)) {
          MonoJitArgumentInfo *arg_info = alloca (sizeof (MonoJitArgumentInfo) * (sig->param_count + 1));
 
          stack_to_pop = arch_get_argument_info (sig, sig->param_count, arg_info);