2007-08-30 Jonathan Chambers <joncham@gmail.com>
[mono.git] / mono / mini / mini-ia64.c
index 4d67083dc11b09f640149cec68072701143b0716..e59aac9bcb7a652e989dec623b56e1c6c8b9ec5b 100644 (file)
@@ -30,9 +30,6 @@
 static gint appdomain_tls_offset = -1;
 static gint thread_tls_offset = -1;
 
-const char * const ia64_desc [OP_LAST];
-static const char*const * ins_spec = ia64_desc;
-
 #define ALIGN_TO(val,align) ((((guint64)val) + ((align) - 1)) & ~((align) - 1))
 
 #define IS_IMM32(val) ((((guint64)val) >> 32) == 0)
@@ -585,40 +582,6 @@ mono_arch_break (void)
 {
 }
 
-static gboolean
-is_regsize_var (MonoType *t) {
-       if (t->byref)
-               return TRUE;
-       t = mono_type_get_underlying_type (t);
-       switch (t->type) {
-       case MONO_TYPE_I1:
-       case MONO_TYPE_U1:
-       case MONO_TYPE_I2:
-       case MONO_TYPE_U2:
-       case MONO_TYPE_I4:
-       case MONO_TYPE_U4:
-       case MONO_TYPE_I:
-       case MONO_TYPE_U:
-       case MONO_TYPE_PTR:
-       case MONO_TYPE_FNPTR:
-       case MONO_TYPE_BOOLEAN:
-               return TRUE;
-       case MONO_TYPE_OBJECT:
-       case MONO_TYPE_STRING:
-       case MONO_TYPE_CLASS:
-       case MONO_TYPE_SZARRAY:
-       case MONO_TYPE_ARRAY:
-               return TRUE;
-       case MONO_TYPE_GENERICINST:
-               if (!mono_type_generic_inst_is_valuetype (t))
-                       return TRUE;
-               return FALSE;
-       case MONO_TYPE_VALUETYPE:
-               return FALSE;
-       }
-       return FALSE;
-}
-
 GList *
 mono_arch_get_allocatable_int_vars (MonoCompile *cfg)
 {
@@ -635,7 +598,7 @@ mono_arch_get_allocatable_int_vars (MonoCompile *cfg)
        cinfo = get_call_info (sig, FALSE);
 
        for (i = 0; i < sig->param_count + sig->hasthis; ++i) {
-               MonoInst *ins = cfg->varinfo [i];
+               MonoInst *ins = cfg->args [i];
 
                ArgInfo *ainfo = &cinfo->args [i];
 
@@ -661,7 +624,7 @@ mono_arch_get_allocatable_int_vars (MonoCompile *cfg)
                    (ins->opcode != OP_LOCAL && ins->opcode != OP_ARG))
                        continue;
 
-               if (is_regsize_var (ins->inst_vtype)) {
+               if (mono_is_regsize_var (ins->inst_vtype)) {
                        g_assert (MONO_VARINFO (cfg, i)->reg == -1);
                        g_assert (i == vmv->idx);
                        vars = g_list_prepend (vars, vmv);
@@ -723,7 +686,7 @@ mono_ia64_alloc_stacked_registers (MonoCompile *cfg)
        }
 
        /* 
-        * Need to allocate at least 2 out register for use by CEE_THROW / the system
+        * Need to allocate at least 2 out register for use by OP_THROW / the system
         * exception throwing code.
         */
        cfg->arch.n_out_regs = MAX (cfg->arch.n_out_regs, 2);
@@ -875,7 +838,6 @@ mono_arch_allocate_vars (MonoCompile *cfg)
                        // printf ("allocated local %d to ", i); mono_print_tree_nl (inst);
                }
        }
-       g_free (offsets);
        offset += locals_stack_size;
 
        if (!sig->pinvoke && (sig->call_convention == MONO_CALL_VARARG)) {
@@ -886,7 +848,7 @@ mono_arch_allocate_vars (MonoCompile *cfg)
        }
 
        for (i = 0; i < sig->param_count + sig->hasthis; ++i) {
-               inst = cfg->varinfo [i];
+               inst = cfg->args [i];
                if (inst->opcode != OP_REGVAR) {
                        ArgInfo *ainfo = &cinfo->args [i];
                        gboolean inreg = TRUE;
@@ -1273,7 +1235,6 @@ peephole_pass (MonoCompile *cfg, MonoBasicBlock *bb)
                switch (ins->opcode) {
                case OP_MOVE:
                case OP_FMOVE:
-               case OP_SETREG:
                        /*
                         * Removes:
                         *
@@ -1320,127 +1281,6 @@ peephole_pass (MonoCompile *cfg, MonoBasicBlock *bb)
        bb->last_ins = last_ins;
 }
 
-typedef enum {
-       CMP_EQ,
-       CMP_NE,
-       CMP_LE,
-       CMP_GE,
-       CMP_LT,
-       CMP_GT,
-       CMP_LE_UN,
-       CMP_GE_UN,
-       CMP_LT_UN,
-       CMP_GT_UN
-} CompRelation;
-
-typedef enum {
-       CMP_TYPE_L,
-       CMP_TYPE_I,
-       CMP_TYPE_F
-} CompType;
-
-static CompRelation
-opcode_to_cond (int opcode)
-{
-       switch (opcode) {
-       case CEE_BEQ:
-       case OP_CEQ:
-       case OP_IBEQ:
-       case OP_ICEQ:
-       case OP_FBEQ:
-       case OP_FCEQ:
-       case OP_COND_EXC_EQ:
-               return CMP_EQ;
-       case CEE_BNE_UN:
-       case OP_COND_EXC_NE_UN:
-       case OP_IBNE_UN:
-       case OP_FBNE_UN:
-               return CMP_NE;
-       case CEE_BLE:
-       case OP_IBLE:
-       case OP_FBLE:
-               return CMP_LE;
-       case CEE_BGE:
-       case OP_IBGE:
-       case OP_FBGE:
-               return CMP_GE;
-       case CEE_BLT:
-       case OP_COND_EXC_LT:
-       case OP_CLT:
-       case OP_IBLT:
-       case OP_ICLT:
-       case OP_FBLT:
-       case OP_FCLT:
-               return CMP_LT;
-       case CEE_BGT:
-       case OP_COND_EXC_GT:
-       case OP_CGT:
-       case OP_IBGT:
-       case OP_ICGT:
-       case OP_FBGT:
-       case OP_FCGT:
-               return CMP_GT;
-
-       case CEE_BLE_UN:
-       case OP_COND_EXC_LE_UN:
-       case OP_IBLE_UN:
-       case OP_FBLE_UN:
-               return CMP_LE_UN;
-       case CEE_BGE_UN:
-       case OP_IBGE_UN:
-       case OP_FBGE_UN:
-               return CMP_GE_UN;
-       case CEE_BLT_UN:
-       case OP_CLT_UN:
-       case OP_IBLT_UN:
-       case OP_ICLT_UN:
-       case OP_FBLT_UN:
-       case OP_FCLT_UN:
-       case OP_COND_EXC_LT_UN:
-               return CMP_LT_UN;
-       case CEE_BGT_UN:
-       case OP_COND_EXC_GT_UN:
-       case OP_CGT_UN:
-       case OP_IBGT_UN:
-       case OP_ICGT_UN:
-       case OP_FCGT_UN:
-       case OP_FBGT_UN:
-               return CMP_GT_UN;
-       default:
-               printf ("%s\n", mono_inst_name (opcode));
-               NOT_IMPLEMENTED;
-       }
-}
-
-static CompType
-opcode_to_type (int opcode, int cmp_opcode)
-{
-       if ((opcode >= CEE_BEQ) && (opcode <= CEE_BLT_UN))
-               return CMP_TYPE_L;
-       else if ((opcode >= OP_CEQ) && (opcode <= OP_CLT_UN))
-               return CMP_TYPE_L;
-       else if ((opcode >= OP_IBEQ) && (opcode <= OP_IBLE_UN))
-               return CMP_TYPE_I;
-       else if ((opcode >= OP_ICEQ) && (opcode <= OP_ICLT_UN))
-               return CMP_TYPE_I;
-       else if ((opcode >= OP_FBEQ) && (opcode <= OP_FBLE_UN))
-               return CMP_TYPE_F;
-       else if ((opcode >= OP_FCEQ) && (opcode <= OP_FCLT_UN))
-               return CMP_TYPE_F;
-       else if ((opcode >= OP_COND_EXC_EQ) && (opcode <= OP_COND_EXC_LT_UN)) {
-               switch (cmp_opcode) {
-               case OP_ICOMPARE:
-               case OP_ICOMPARE_IMM:
-                       return CMP_TYPE_I;
-               default:
-                       return CMP_TYPE_L;
-               }
-       } else {
-               g_error ("Unknown opcode '%s' in opcode_to_type", mono_inst_name (opcode));
-               return 0;
-       }
-}
-
 int cond_to_ia64_cmp [][3] = {
        {OP_IA64_CMP_EQ, OP_IA64_CMP4_EQ, OP_IA64_FCMP_EQ},
        {OP_IA64_CMP_NE, OP_IA64_CMP4_NE, OP_IA64_FCMP_NE},
@@ -1457,7 +1297,7 @@ int cond_to_ia64_cmp [][3] = {
 static int
 opcode_to_ia64_cmp (int opcode, int cmp_opcode)
 {
-       return cond_to_ia64_cmp [opcode_to_cond (opcode)][opcode_to_type (opcode, cmp_opcode)];
+       return cond_to_ia64_cmp [mono_opcode_to_cond (opcode)][mono_opcode_to_type (opcode, cmp_opcode)];
 }
 
 int cond_to_ia64_cmp_imm [][3] = {
@@ -1477,7 +1317,7 @@ static int
 opcode_to_ia64_cmp_imm (int opcode, int cmp_opcode)
 {
        /* The condition needs to be reversed */
-       return cond_to_ia64_cmp_imm [opcode_to_cond (opcode)][opcode_to_type (opcode, cmp_opcode)];
+       return cond_to_ia64_cmp_imm [mono_opcode_to_cond (opcode)][mono_opcode_to_type (opcode, cmp_opcode)];
 }
 
 static void
@@ -1513,10 +1353,8 @@ mono_arch_lowering_pass (MonoCompile *cfg, MonoBasicBlock *bb)
        MonoInst *ins, *next, *temp, *temp2, *temp3, *last_ins = NULL;
        ins = bb->code;
 
-       if (bb->max_ireg > cfg->rs->next_vireg)
-               cfg->rs->next_vireg = bb->max_ireg;
-       if (bb->max_freg > cfg->rs->next_vfreg)
-               cfg->rs->next_vfreg = bb->max_freg;
+       if (bb->max_vreg > cfg->rs->next_vreg)
+               cfg->rs->next_vreg = bb->max_vreg;
 
        while (ins) {
                switch (ins->opcode) {
@@ -1652,6 +1490,7 @@ mono_arch_lowering_pass (MonoCompile *cfg, MonoBasicBlock *bb)
                case OP_IXOR_IMM:
                case OP_AND_IMM:
                case OP_SHL_IMM:
+               case OP_SHR_IMM:
                case OP_ISHL_IMM:
                case OP_LSHL_IMM:
                case OP_ISHR_IMM:
@@ -1689,6 +1528,7 @@ mono_arch_lowering_pass (MonoCompile *cfg, MonoBasicBlock *bb)
                                switched = TRUE;
                                break;
                        case OP_SHL_IMM:
+                       case OP_SHR_IMM:
                        case OP_ISHL_IMM:
                        case OP_LSHL_IMM:
                        case OP_ISHR_IMM:
@@ -1741,6 +1581,9 @@ mono_arch_lowering_pass (MonoCompile *cfg, MonoBasicBlock *bb)
                        case OP_SHL_IMM:
                                ins->opcode = OP_LSHL;
                                break;
+                       case OP_SHR_IMM:
+                               ins->opcode = OP_LSHR;
+                               break;
                        case OP_LSHL_IMM:
                                ins->opcode = OP_LSHL;
                                break;
@@ -1768,30 +1611,20 @@ mono_arch_lowering_pass (MonoCompile *cfg, MonoBasicBlock *bb)
                case OP_ICOMPARE_IMM: {
                        /* Instead of compare+b<cond>, ia64 has compare<cond>+br */
                        gboolean imm;
+                       CompRelation cond;
 
                        /* 
                         * The compare_imm instructions have switched up arguments, and 
                         * some of them take an imm between -127 and 128.
                         */
                        next = ins->next;
-                       switch (next->opcode) {
-                       case CEE_BGE:
-                       case CEE_BLT:
-                       case OP_COND_EXC_LT:
-                       case OP_IBGE:
-                       case OP_IBLT:
+                       cond = mono_opcode_to_cond (next->opcode);
+                       if ((cond == CMP_LT) || (cond == CMP_GE))
                                imm = ia64_is_imm8 (ins->inst_imm - 1);
-                               break;
-                       case OP_IBGE_UN:
-                       case OP_IBLT_UN:
-                       case CEE_BGE_UN:
-                       case CEE_BLT_UN:
+                       else if ((cond == CMP_LT_UN) || (cond == CMP_GE_UN))
                                imm = ia64_is_imm8 (ins->inst_imm - 1) && (ins->inst_imm > 0);
-                               break;
-                       default:
+                       else
                                imm = ia64_is_imm8 (ins->inst_imm);
-                               break;
-                       }
 
                        if (imm) {
                                ins->opcode = opcode_to_ia64_cmp_imm (next->opcode, ins->opcode);
@@ -2044,8 +1877,7 @@ mono_arch_lowering_pass (MonoCompile *cfg, MonoBasicBlock *bb)
        }
        bb->last_ins = last_ins;
 
-       bb->max_ireg = cfg->rs->next_vireg;
-       bb->max_freg = cfg->rs->next_vfreg;
+       bb->max_vreg = cfg->rs->next_vreg;
 }
 
 void
@@ -2085,7 +1917,7 @@ emit_load_volatile_arguments (MonoCompile *cfg, Ia64CodegenState code)
                ArgInfo *ainfo = cinfo->args + i;
                gint32 stack_offset;
                MonoType *arg_type;
-               ins = cfg->varinfo [i];
+               ins = cfg->args [i];
 
                if (sig->hasthis && (i == 0))
                        arg_type = &mono_defaults.object_class->byval_arg;
@@ -2298,7 +2130,7 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb)
        while (ins) {
                offset = code.buf - cfg->native_code;
 
-               max_len = ((int)(((guint8 *)ins_spec [ins->opcode])[MONO_INST_LEN])) + 128;
+               max_len = ((int)(((guint8 *)ins_get_spec (ins->opcode))[MONO_INST_LEN])) + 128;
 
                while (offset + max_len + 16 > cfg->code_size) {
                        ia64_codegen_close (code);
@@ -2326,7 +2158,7 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb)
                case OP_MOVE:
                        ia64_mov (code, ins->dreg, ins->sreg1);
                        break;
-               case CEE_BR:
+               case OP_BR:
                case OP_IA64_BR_COND: {
                        int pred = 0;
                        if (ins->opcode == OP_IA64_BR_COND)
@@ -2356,7 +2188,7 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb)
                        ia64_begin_bundle (code);
                        ins->inst_c0 = code.buf - cfg->native_code;
                        break;
-               case CEE_NOP:
+               case OP_NOP:
                        break;
                case OP_BR_REG:
                        ia64_mov_to_br (code, IA64_B6, ins->sreg1);
@@ -2492,10 +2324,9 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb)
                case OP_LSHL_IMM:
                        ia64_shl_imm (code, ins->dreg, ins->sreg1, ins->inst_imm);
                        break;
-               case OP_LSHR_IMM:
-                       ia64_shr_imm (code, ins->dreg, ins->sreg1, ins->inst_imm);
-                       break;
+               case OP_SHR_IMM:
                case OP_ISHR_IMM:
+               case OP_LSHR_IMM:
                        ia64_shr_imm (code, ins->dreg, ins->sreg1, ins->inst_imm);
                        break;
                case OP_ISHR_UN_IMM:
@@ -2796,8 +2627,7 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb)
                        break;
                case CEE_CONV_I8:
                case CEE_CONV_I:
-                       /* FIXME: Sign extend ? */
-                       ia64_mov (code, ins->dreg, ins->sreg1);
+                       ia64_sxt4 (code, ins->dreg, ins->sreg1);
                        break;
                case CEE_CONV_U8:
                case CEE_CONV_U:
@@ -2893,7 +2723,7 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb)
                case OP_FNEG:
                        ia64_fmerge_ns (code, ins->dreg, ins->sreg1, ins->sreg1);
                        break;
-               case CEE_CKFINITE:
+               case OP_CKFINITE:
                        /* Quiet NaN */
                        ia64_fclass_m (code, 6, 7, ins->sreg1, 0x080);
                        emit_cond_system_exception (cfg, code, "ArithmeticException", 6);
@@ -2990,7 +2820,7 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb)
 
                        code = emit_move_return_value (cfg, ins, code);
                        break;
-               case CEE_JMP: {
+               case OP_JMP: {
                        /*
                         * Keep in sync with the code in emit_epilog.
                         */
@@ -3025,7 +2855,7 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb)
 
                        break;
                }
-               case CEE_BREAK:
+               case OP_BREAK:
                        code = emit_call (cfg, code, MONO_PATCH_INFO_ABS, mono_arch_break);
                        break;
 
@@ -3035,8 +2865,8 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb)
                        /* FIXME: Sigaltstack support */
 
                        /* keep alignment */
-                       ia64_adds_imm (code, GP_SCRATCH_REG, MONO_ARCH_FRAME_ALIGNMENT - 1, ins->sreg1);
-                       ia64_movl (code, GP_SCRATCH_REG2, ~(MONO_ARCH_FRAME_ALIGNMENT - 1));
+                       ia64_adds_imm (code, GP_SCRATCH_REG, MONO_ARCH_LOCALLOC_ALIGNMENT - 1, ins->sreg1);
+                       ia64_movl (code, GP_SCRATCH_REG2, ~(MONO_ARCH_LOCALLOC_ALIGNMENT - 1));
                        ia64_and (code, GP_SCRATCH_REG, GP_SCRATCH_REG, GP_SCRATCH_REG2);
 
                        ia64_sub (code, IA64_SP, IA64_SP, GP_SCRATCH_REG);
@@ -3044,7 +2874,7 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb)
                        ia64_mov (code, ins->dreg, IA64_SP);
 
                        /* An area at sp is reserved by the ABI for parameter passing */
-                       abi_offset = - ALIGN_TO (cfg->param_area + 16, MONO_ARCH_FRAME_ALIGNMENT);
+                       abi_offset = - ALIGN_TO (cfg->param_area + 16, MONO_ARCH_LOCALLOC_ALIGNMENT);
                        if (ia64_is_adds_imm (abi_offset))
                                ia64_adds_imm (code, IA64_SP, abi_offset, IA64_SP);
                        else {
@@ -3195,7 +3025,7 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb)
 
                        break;
                }
-               case CEE_ENDFINALLY:
+               case OP_ENDFINALLY:
                case OP_ENDFILTER: {
                        /* FIXME: Return the value in ENDFILTER */
                        MonoInst *spvar = mono_find_spvar_for_region (cfg, bb->region);
@@ -3219,7 +3049,7 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb)
                        ia64_br_cond_reg (code, IA64_B6);
                        break;
                }
-               case CEE_THROW:
+               case OP_THROW:
                        ia64_mov (code, cfg->arch.reg_out0, ins->sreg1);
                        code = emit_call (cfg, code, MONO_PATCH_INFO_INTERNAL_METHOD, 
                                                          (gpointer)"mono_arch_throw_exception");
@@ -4038,7 +3868,7 @@ mono_arch_emit_prolog (MonoCompile *cfg)
                ArgInfo *ainfo = cinfo->args + i;
                gint32 stack_offset;
                MonoType *arg_type;
-               inst = cfg->varinfo [i];
+               inst = cfg->args [i];
 
                if (sig->hasthis && (i == 0))
                        arg_type = &mono_defaults.object_class->byval_arg;
@@ -4054,9 +3884,13 @@ mono_arch_emit_prolog (MonoCompile *cfg)
                        switch (ainfo->storage) {
                        case ArgInIReg:
                        case ArgInFloatReg:
-                               /* FIXME: big offsets */
                                g_assert (inst->opcode == OP_REGOFFSET);
-                               ia64_adds_imm (code, GP_SCRATCH_REG, inst->inst_offset, inst->inst_basereg);
+                               if (ia64_is_adds_imm (inst->inst_offset))
+                                       ia64_adds_imm (code, GP_SCRATCH_REG, inst->inst_offset, inst->inst_basereg);
+                               else {
+                                       ia64_movl (code, GP_SCRATCH_REG2, inst->inst_offset);
+                                       ia64_add (code, GP_SCRATCH_REG, GP_SCRATCH_REG, GP_SCRATCH_REG2);
+                               }
                                if (arg_type->byref)
                                        ia64_st8_hint (code, GP_SCRATCH_REG, cfg->arch.reg_in0 + ainfo->reg, 0);
                                else {
@@ -4170,7 +4004,7 @@ mono_arch_emit_epilog (MonoCompile *cfg)
 
        ia64_codegen_init (code, buf);
 
-       /* the code restoring the registers must be kept in sync with CEE_JMP */
+       /* the code restoring the registers must be kept in sync with OP_JMP */
        pos = 0;
        
        if (method->save_lmf) {
@@ -4425,7 +4259,7 @@ mono_arch_instrument_prolog (MonoCompile *cfg, void *func, void *p, gboolean ena
 
                        /* Save arguments to the stack */
                        for (i = 0; i < n; ++i) {
-                               ins = cfg->varinfo [i];
+                               ins = cfg->args [i];
 
                                if (ins->opcode == OP_REGVAR) {
                                        ia64_movl (code, GP_SCRATCH_REG, (i * 8));