New test.
[mono.git] / mono / mini / mini-x86.c
index 0a14a4efcc56f7ebcb051c94619a0884268f2bc6..5960329ecec8dd132d6432097dc1e20a31cb3a33 100644 (file)
@@ -22,7 +22,7 @@
 #include "trace.h"
 #include "mini-x86.h"
 #include "inssel.h"
-#include "cpu-pentium.h"
+#include "cpu-x86.h"
 
 /* On windows, these hold the key returned by TlsAlloc () */
 static gint lmf_tls_offset = -1;
@@ -427,7 +427,8 @@ int
 mono_arch_get_argument_info (MonoMethodSignature *csig, int param_count, MonoJitArgumentInfo *arg_info)
 {
        int k, frame_size = 0;
-       int size, align, pad;
+       int size, pad;
+       guint32 align;
        int offset = 8;
        CallInfo *cinfo;
 
@@ -451,8 +452,11 @@ mono_arch_get_argument_info (MonoMethodSignature *csig, int param_count, MonoJit
                
                if (csig->pinvoke)
                        size = mono_type_native_stack_size (csig->params [k], &align);
-               else
-                       size = mono_type_stack_size (csig->params [k], &align);
+               else {
+                       int ialign;
+                       size = mono_type_stack_size (csig->params [k], &ialign);
+                       align = ialign;
+               }
 
                /* ignore alignment for now */
                align = 1;
@@ -886,6 +890,38 @@ mono_arch_create_vars (MonoCompile *cfg)
  * currently alignment in mono_arch_call_opcode is computed without arch_get_argument_info 
  */
 
+static void
+emit_sig_cookie (MonoCompile *cfg, MonoCallInst *call)
+{
+       MonoInst *arg;
+       MonoMethodSignature *tmp_sig;
+       MonoInst *sig_arg;
+
+       /* FIXME: Add support for signature tokens to AOT */
+       cfg->disable_aot = TRUE;
+       MONO_INST_NEW (cfg, arg, OP_OUTARG);
+
+       /*
+        * mono_ArgIterator_Setup assumes the signature cookie is 
+        * passed first and all the arguments which were before it are
+        * passed on the stack after the signature. So compensate by 
+        * passing a different signature.
+        */
+       tmp_sig = mono_metadata_signature_dup (call->signature);
+       tmp_sig->param_count -= call->signature->sentinelpos;
+       tmp_sig->sentinelpos = 0;
+       memcpy (tmp_sig->params, call->signature->params + call->signature->sentinelpos, tmp_sig->param_count * sizeof (MonoType*));
+
+       MONO_INST_NEW (cfg, sig_arg, OP_ICONST);
+       sig_arg->inst_p0 = tmp_sig;
+
+       arg->inst_left = sig_arg;
+       arg->type = STACK_PTR;
+       /* prepend, so they get reversed */
+       arg->next = call->out_args;
+       call->out_args = arg;
+}
+
 /* 
  * take the arguments and generate the arch-specific
  * instructions to properly call the function in call.
@@ -898,7 +934,7 @@ mono_arch_call_opcode (MonoCompile *cfg, MonoBasicBlock* bb, MonoCallInst *call,
        MonoMethodSignature *sig;
        int i, n;
        CallInfo *cinfo;
-       int sentinelpos;
+       int sentinelpos = 0;
 
        sig = call->signature;
        n = sig->param_count + sig->hasthis;
@@ -913,32 +949,7 @@ mono_arch_call_opcode (MonoCompile *cfg, MonoBasicBlock* bb, MonoCallInst *call,
 
                /* Emit the signature cookie just before the implicit arguments */
                if (!sig->pinvoke && (sig->call_convention == MONO_CALL_VARARG) && (i == sentinelpos)) {
-                       MonoMethodSignature *tmp_sig;
-                       MonoInst *sig_arg;
-
-                       /* FIXME: Add support for signature tokens to AOT */
-                       cfg->disable_aot = TRUE;
-                       MONO_INST_NEW (cfg, arg, OP_OUTARG);
-
-                       /*
-                        * mono_ArgIterator_Setup assumes the signature cookie is 
-                        * passed first and all the arguments which were before it are
-                        * passed on the stack after the signature. So compensate by 
-                        * passing a different signature.
-                        */
-                       tmp_sig = mono_metadata_signature_dup (call->signature);
-                       tmp_sig->param_count -= call->signature->sentinelpos;
-                       tmp_sig->sentinelpos = 0;
-                       memcpy (tmp_sig->params, call->signature->params + call->signature->sentinelpos, tmp_sig->param_count * sizeof (MonoType*));
-
-                       MONO_INST_NEW (cfg, sig_arg, OP_ICONST);
-                       sig_arg->inst_p0 = tmp_sig;
-
-                       arg->inst_left = sig_arg;
-                       arg->type = STACK_PTR;
-                       /* prepend, so they get reversed */
-                       arg->next = call->out_args;
-                       call->out_args = arg;
+                       emit_sig_cookie (cfg, call);
                }
 
                if (is_virtual && i == 0) {
@@ -963,8 +974,7 @@ mono_arch_call_opcode (MonoCompile *cfg, MonoBasicBlock* bb, MonoCallInst *call,
                        call->out_args = arg;
 
                        if ((i >= sig->hasthis) && (MONO_TYPE_ISSTRUCT(t))) {
-                               gint align;
-                               guint32 size;
+                               guint32 size, align;
 
                                if (t->type == MONO_TYPE_TYPEDBYREF) {
                                        size = sizeof (MonoTypedRef);
@@ -973,11 +983,14 @@ mono_arch_call_opcode (MonoCompile *cfg, MonoBasicBlock* bb, MonoCallInst *call,
                                else
                                        if (sig->pinvoke)
                                                size = mono_type_native_stack_size (&in->klass->byval_arg, &align);
-                                       else
-                                               size = mono_type_stack_size (&in->klass->byval_arg, &align);
+                                       else {
+                                               int ialign;
+                                               size = mono_type_stack_size (&in->klass->byval_arg, &ialign);
+                                               align = ialign;
+                                       }
                                arg->opcode = OP_OUTARG_VT;
                                arg->klass = in->klass;
-                               arg->unused = sig->pinvoke;
+                               arg->backend.is_pinvoke = sig->pinvoke;
                                arg->inst_imm = size; 
                        }
                        else {
@@ -999,6 +1012,11 @@ mono_arch_call_opcode (MonoCompile *cfg, MonoBasicBlock* bb, MonoCallInst *call,
                }
        }
 
+       /* Handle the case where there are no implicit arguments */
+       if (!sig->pinvoke && (sig->call_convention == MONO_CALL_VARARG) && (n == sentinelpos)) {
+               emit_sig_cookie (cfg, call);
+       }
+
        if (sig->ret && MONO_TYPE_ISSTRUCT (sig->ret)) {
                if (cinfo->ret.storage == ArgValuetypeInReg) {
                        MonoInst *zero_inst;
@@ -1455,7 +1473,7 @@ branch_cc_table [] = {
        X86_CC_O, X86_CC_NO, X86_CC_C, X86_CC_NC
 };
 
-static const char*const * ins_spec = pentium_desc;
+static const char*const * ins_spec = x86_desc;
 
 /*#include "cprop.c"*/
 void
@@ -1993,14 +2011,14 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb)
                        guint8 *jump_to_end;
 
                        /* handle shifts below 32 bits */
-                       x86_shld_reg (code, ins->unused, ins->sreg1);
+                       x86_shld_reg (code, ins->backend.reg3, ins->sreg1);
                        x86_shift_reg (code, X86_SHL, ins->sreg1);
 
                        x86_test_reg_imm (code, X86_ECX, 32);
                        jump_to_end = code; x86_branch8 (code, X86_CC_EQ, 0, TRUE);
 
                        /* handle shift over 32 bit */
-                       x86_mov_reg_reg (code, ins->unused, ins->sreg1, 4);
+                       x86_mov_reg_reg (code, ins->backend.reg3, ins->sreg1, 4);
                        x86_clear_reg (code, ins->sreg1);
                        
                        x86_patch (jump_to_end, code);
@@ -2010,15 +2028,15 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb)
                        guint8 *jump_to_end;
 
                        /* handle shifts below 32 bits */
-                       x86_shrd_reg (code, ins->sreg1, ins->unused);
-                       x86_shift_reg (code, X86_SAR, ins->unused);
+                       x86_shrd_reg (code, ins->sreg1, ins->backend.reg3);
+                       x86_shift_reg (code, X86_SAR, ins->backend.reg3);
 
                        x86_test_reg_imm (code, X86_ECX, 32);
                        jump_to_end = code; x86_branch8 (code, X86_CC_EQ, 0, FALSE);
 
                        /* handle shifts over 31 bits */
-                       x86_mov_reg_reg (code, ins->sreg1, ins->unused, 4);
-                       x86_shift_reg_imm (code, X86_SAR, ins->unused, 31);
+                       x86_mov_reg_reg (code, ins->sreg1, ins->backend.reg3, 4);
+                       x86_shift_reg_imm (code, X86_SAR, ins->backend.reg3, 31);
                        
                        x86_patch (jump_to_end, code);
                        }
@@ -2027,47 +2045,47 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb)
                        guint8 *jump_to_end;
 
                        /* handle shifts below 32 bits */
-                       x86_shrd_reg (code, ins->sreg1, ins->unused);
-                       x86_shift_reg (code, X86_SHR, ins->unused);
+                       x86_shrd_reg (code, ins->sreg1, ins->backend.reg3);
+                       x86_shift_reg (code, X86_SHR, ins->backend.reg3);
 
                        x86_test_reg_imm (code, X86_ECX, 32);
                        jump_to_end = code; x86_branch8 (code, X86_CC_EQ, 0, FALSE);
 
                        /* handle shifts over 31 bits */
-                       x86_mov_reg_reg (code, ins->sreg1, ins->unused, 4);
-                       x86_shift_reg_imm (code, X86_SHR, ins->unused, 31);
+                       x86_mov_reg_reg (code, ins->sreg1, ins->backend.reg3, 4);
+                       x86_clear_reg (code, ins->backend.reg3);
                        
                        x86_patch (jump_to_end, code);
                        }
                        break;
                case OP_LSHL_IMM:
                        if (ins->inst_imm >= 32) {
-                               x86_mov_reg_reg (code, ins->unused, ins->sreg1, 4);
+                               x86_mov_reg_reg (code, ins->backend.reg3, ins->sreg1, 4);
                                x86_clear_reg (code, ins->sreg1);
-                               x86_shift_reg_imm (code, X86_SHL, ins->unused, ins->inst_imm - 32);
+                               x86_shift_reg_imm (code, X86_SHL, ins->backend.reg3, ins->inst_imm - 32);
                        } else {
-                               x86_shld_reg_imm (code, ins->unused, ins->sreg1, ins->inst_imm);
+                               x86_shld_reg_imm (code, ins->backend.reg3, ins->sreg1, ins->inst_imm);
                                x86_shift_reg_imm (code, X86_SHL, ins->sreg1, ins->inst_imm);
                        }
                        break;
                case OP_LSHR_IMM:
                        if (ins->inst_imm >= 32) {
-                               x86_mov_reg_reg (code, ins->sreg1, ins->unused,  4);
-                               x86_shift_reg_imm (code, X86_SAR, ins->unused, 0x1f);
+                               x86_mov_reg_reg (code, ins->sreg1, ins->backend.reg3,  4);
+                               x86_shift_reg_imm (code, X86_SAR, ins->backend.reg3, 0x1f);
                                x86_shift_reg_imm (code, X86_SAR, ins->sreg1, ins->inst_imm - 32);
                        } else {
-                               x86_shrd_reg_imm (code, ins->sreg1, ins->unused, ins->inst_imm);
-                               x86_shift_reg_imm (code, X86_SAR, ins->unused, ins->inst_imm);
+                               x86_shrd_reg_imm (code, ins->sreg1, ins->backend.reg3, ins->inst_imm);
+                               x86_shift_reg_imm (code, X86_SAR, ins->backend.reg3, ins->inst_imm);
                        }
                        break;
                case OP_LSHR_UN_IMM:
                        if (ins->inst_imm >= 32) {
-                               x86_mov_reg_reg (code, ins->sreg1, ins->unused, 4);
-                               x86_clear_reg (code, ins->unused);
+                               x86_mov_reg_reg (code, ins->sreg1, ins->backend.reg3, 4);
+                               x86_clear_reg (code, ins->backend.reg3);
                                x86_shift_reg_imm (code, X86_SHR, ins->sreg1, ins->inst_imm - 32);
                        } else {
-                               x86_shrd_reg_imm (code, ins->sreg1, ins->unused, ins->inst_imm);
-                               x86_shift_reg_imm (code, X86_SHR, ins->unused, ins->inst_imm);
+                               x86_shrd_reg_imm (code, ins->sreg1, ins->backend.reg3, ins->inst_imm);
+                               x86_shift_reg_imm (code, X86_SHR, ins->backend.reg3, ins->inst_imm);
                        }
                        break;
                case CEE_NOT:
@@ -2363,7 +2381,7 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb)
                        x86_pop_reg (code, X86_EDI);
                        break;
                case OP_X86_LEA:
-                       x86_lea_memindex (code, ins->dreg, ins->sreg1, ins->inst_imm, ins->sreg2, ins->unused);
+                       x86_lea_memindex (code, ins->dreg, ins->sreg1, ins->inst_imm, ins->sreg2, ins->backend.shift_amount);
                        break;
                case OP_X86_LEA_MEMBASE:
                        x86_lea_membase (code, ins->dreg, ins->sreg1, ins->inst_imm);
@@ -2589,7 +2607,7 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb)
                        x86_alu_reg_imm (code, X86_SUB, X86_ESP, 8);
                        x86_fist_pop_membase (code, X86_ESP, 0, TRUE);
                        x86_pop_reg (code, ins->dreg);
-                       x86_pop_reg (code, ins->unused);
+                       x86_pop_reg (code, ins->backend.reg3);
                        x86_fldcw_membase (code, X86_ESP, 0);
                        x86_alu_reg_imm (code, X86_ADD, X86_ESP, 4);
                        break;