2005-12-12 Zoltan Varga <vargaz@gmail.com>
[mono.git] / mono / mini / mini-arm.c
index bd4a11a6619e03260f914a6cc4075ce43f193d3d..7a100ad9d92c19c0e8c6842fdb03d03af6906899 100644 (file)
@@ -336,8 +336,8 @@ add_general (guint *gr, guint *stack_size, ArgInfo *ainfo, gboolean simple)
                }
        } else {
                if (*gr > ARMREG_R2) {
-                       *stack_size += 7;
-                       *stack_size &= ~7;
+                       /**stack_size += 7;
+                       *stack_size &= ~7;*/
                        ainfo->offset = *stack_size;
                        ainfo->reg = ARMREG_SP; /* in the caller */
                        ainfo->regtype = RegTypeBase;
@@ -549,17 +549,6 @@ mono_arch_allocate_vars (MonoCompile *m)
        /* allow room for the vararg method args: void* and long/double */
        if (mono_jit_trace_calls != NULL && mono_trace_eval (m->method))
                m->param_area = MAX (m->param_area, sizeof (gpointer)*8);
-       /* this is bug #60332: remove when #59509 is fixed, so no weird vararg 
-        * call convs needs to be handled this way.
-        */
-       if (m->flags & MONO_CFG_HAS_VARARGS)
-               m->param_area = MAX (m->param_area, sizeof (gpointer)*8);
-       /* gtk-sharp and other broken code will dllimport vararg functions even with
-        * non-varargs signatures. Since there is little hope people will get this right
-        * we assume they won't.
-        */
-       if (m->method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE)
-               m->param_area = MAX (m->param_area, sizeof (gpointer)*8);
 
        header = mono_method_get_header (m->method);
 
@@ -649,6 +638,11 @@ mono_arch_allocate_vars (MonoCompile *m)
                else
                        size = mono_type_size (inst->inst_vtype, &align);
 
+               /* FIXME: if a structure is misaligned, our memcpy doesn't work,
+                * since it loads/stores misaligned words, which don't do the right thing.
+                */
+               if (align < 4 && size >= 4)
+                       align = 4;
                offset += align - 1;
                offset &= ~(align - 1);
                inst->inst_offset = offset;
@@ -680,6 +674,11 @@ mono_arch_allocate_vars (MonoCompile *m)
                        inst->opcode = OP_REGOFFSET;
                        inst->inst_basereg = frame_reg;
                        size = mono_type_size (sig->params [i], &align);
+                       /* FIXME: if a structure is misaligned, our memcpy doesn't work,
+                        * since it loads/stores misaligned words, which don't do the right thing.
+                        */
+                       if (align < 4 && size >= 4)
+                               align = 4;
                        offset += align - 1;
                        offset &= ~(align - 1);
                        inst->inst_offset = offset;
@@ -1575,6 +1574,21 @@ arm_patch (guchar *code, const guchar *target)
                /* branch and exchange: the address is constructed in a reg */
                g_assert_not_reached ();
        } else {
+               guint32 ccode [3];
+               guint32 *tmp = ccode;
+               ARM_LDR_IMM (tmp, ARMREG_IP, ARMREG_PC, 0);
+               ARM_MOV_REG_REG (tmp, ARMREG_LR, ARMREG_PC);
+               ARM_MOV_REG_REG (tmp, ARMREG_PC, ARMREG_IP);
+               if (ins == ccode [2]) {
+                       tmp = (guint32*)code;
+                       tmp [-1] = (guint32)target;
+                       return;
+               }
+               if (ins == ccode [0]) {
+                       tmp = (guint32*)code;
+                       tmp [2] = (guint32)target;
+                       return;
+               }
                g_assert_not_reached ();
        }
 //     g_print ("patched with 0x%08x\n", ins);
@@ -1608,6 +1622,14 @@ guint8*
 mono_arm_emit_load_imm (guint8 *code, int dreg, guint32 val)
 {
        int imm8, rot_amount;
+#if 0
+       ARM_LDR_IMM (code, dreg, ARMREG_PC, 0);
+       /* skip the constant pool */
+       ARM_B (code, 0);
+       *(int*)code = val;
+       code += 4;
+       return code;
+#endif
        if ((imm8 = mono_arm_is_rotated_imm8 (val, &rot_amount)) >= 0) {
                ARM_MOV_REG_IMM (code, dreg, imm8, rot_amount);
        } else if ((imm8 = mono_arm_is_rotated_imm8 (~val, &rot_amount)) >= 0) {
@@ -1762,16 +1784,19 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb)
                        ARM_LDR_REG_REG (code, ins->dreg, ins->inst_basereg, ins->sreg2);
                        break;
                case OP_LOADI1_MEMINDEX:
-                       ARM_LDRSB_REG_REG (code, ins->dreg, ins->inst_basereg, ins->sreg2);
+                       /* note: the args are reversed in the macro */
+                       ARM_LDRSB_REG_REG (code, ins->inst_basereg, ins->dreg, ins->sreg2);
                        break;
                case OP_LOADU1_MEMINDEX:
                        ARM_LDRB_REG_REG (code, ins->dreg, ins->inst_basereg, ins->sreg2);
                        break;
                case OP_LOADI2_MEMINDEX:
-                       ARM_LDRSH_REG_REG (code, ins->inst_basereg, ins->sreg2, ins->dreg);
+                       /* note: the args are reversed in the macro */
+                       ARM_LDRSH_REG_REG (code, ins->inst_basereg, ins->dreg, ins->sreg2);
                        break;
                case OP_LOADU2_MEMINDEX:
-                       ARM_LDRH_REG_REG (code, ins->inst_basereg, ins->sreg2, ins->dreg);
+                       /* note: the args are reversed in the macro */
+                       ARM_LDRH_REG_REG (code, ins->inst_basereg, ins->dreg, ins->sreg2);
                        break;
                case OP_LOAD_MEMBASE:
                case OP_LOADI4_MEMBASE:
@@ -1958,16 +1983,19 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb)
                        ARM_SHL_REG (code, ins->dreg, ins->sreg1, ins->sreg2);
                        break;
                case OP_SHL_IMM:
-                       ARM_SHL_IMM (code, ins->dreg, ins->sreg1, (ins->inst_imm & 0x1f));
+                       if (ins->inst_imm)
+                               ARM_SHL_IMM (code, ins->dreg, ins->sreg1, (ins->inst_imm & 0x1f));
                        break;
                case CEE_SHR:
                        ARM_SAR_REG (code, ins->dreg, ins->sreg1, ins->sreg2);
                        break;
                case OP_SHR_IMM:
-                       ARM_SAR_IMM (code, ins->dreg, ins->sreg1, (ins->inst_imm & 0x1f));
+                       if (ins->inst_imm)
+                               ARM_SAR_IMM (code, ins->dreg, ins->sreg1, (ins->inst_imm & 0x1f));
                        break;
                case OP_SHR_UN_IMM:
-                       ARM_SHR_IMM (code, ins->dreg, ins->sreg1, (ins->inst_imm & 0x1f));
+                       if (ins->inst_imm)
+                               ARM_SHR_IMM (code, ins->dreg, ins->sreg1, (ins->inst_imm & 0x1f));
                        break;
                case CEE_SHR_UN:
                        ARM_SHR_REG (code, ins->dreg, ins->sreg1, ins->sreg2);
@@ -2012,14 +2040,14 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb)
                        break;
                case OP_SETLRET: {
                        int saved = ins->sreg2;
-                       if (ins->sreg2 == ARMREG_R0) {
+                       if (ins->sreg2 == ARM_LSW_REG) {
                                ARM_MOV_REG_REG (code, ARMREG_LR, ins->sreg2);
                                saved = ARMREG_LR;
                        }
-                       if (ins->sreg1 != ARMREG_R0)
-                               ARM_MOV_REG_REG (code, ARMREG_R0, ins->sreg1);
-                       if (saved != ARMREG_R1)
-                               ARM_MOV_REG_REG (code, ARMREG_R1, saved);
+                       if (ins->sreg1 != ARM_LSW_REG)
+                               ARM_MOV_REG_REG (code, ARM_LSW_REG, ins->sreg1);
+                       if (saved != ARM_MSW_REG)
+                               ARM_MOV_REG_REG (code, ARM_MSW_REG, saved);
                        break;
                }
                case OP_SETFREG:
@@ -2035,7 +2063,6 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb)
                         */
                        g_assert (!cfg->method->save_lmf);
                        code = emit_big_add (code, ARMREG_SP, cfg->frame_reg, cfg->stack_usage);
-                       ARM_ADD_REG_IMM8 (code, ARMREG_SP, cfg->frame_reg, cfg->stack_usage);
                        ARM_POP_NWB (code, cfg->used_int_regs | ((1 << ARMREG_SP)) | ((1 << ARMREG_LR)));
                        mono_add_patch_info (cfg, (guint8*) code - cfg->native_code, MONO_PATCH_INFO_METHOD_JUMP, ins->inst_p0);
                        ARM_B (code, 0);
@@ -2332,12 +2359,13 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb)
                        /* save the temp register */
                        ARM_SUB_REG_IMM8 (code, ARMREG_SP, ARMREG_SP, 8);
                        ARM_STFD (code, tmpreg, ARMREG_SP, 0);
-                       ARM_LDFD (code, tmpreg, ARMREG_PC, 4);
+                       ARM_LDFD (code, tmpreg, ARMREG_PC, 12);
                        ARM_FPA_ADFD (code, ins->dreg, ins->dreg, tmpreg);
                        ARM_LDFD (code, tmpreg, ARMREG_SP, 0);
                        ARM_ADD_REG_IMM8 (code, ARMREG_SP, ARMREG_SP, 8);
                        /* skip the constant pool */
-                       ARM_B (code, 4);
+                       ARM_B (code, 8);
+                       code += 4;
                        *(int*)code = 0x41f00000;
                        code += 4;
                        *(int*)code = 0;
@@ -2512,7 +2540,7 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb)
                case OP_FBGE_UN:
                        ARM_FCMP (code, ARM_FPA_CMF, ins->sreg1, ins->sreg2);
                        EMIT_COND_BRANCH_FLAGS (ins, ARMCOND_VS); /* V set */
-                       EMIT_COND_BRANCH_FLAGS (ins, ARMCOND_CS);
+                       EMIT_COND_BRANCH_FLAGS (ins, ARMCOND_GE);
                        break;
                case OP_FBLE:
                        ARM_FCMP (code, ARM_FPA_CMF, ins->sreg2, ins->sreg1);
@@ -2521,7 +2549,7 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb)
                case OP_FBLE_UN:
                        ARM_FCMP (code, ARM_FPA_CMF, ins->sreg2, ins->sreg1);
                        EMIT_COND_BRANCH_FLAGS (ins, ARMCOND_VS); /* V set */
-                       EMIT_COND_BRANCH_FLAGS (ins, ARMCOND_CS); /* swapped */
+                       EMIT_COND_BRANCH_FLAGS (ins, ARMCOND_GE); /* swapped */
                        break;
                case CEE_CKFINITE: {
                        /*ppc_stfd (code, ins->sreg1, -8, ppc_sp);
@@ -3030,6 +3058,7 @@ mono_arch_emit_exceptions (MonoCompile *cfg)
                switch (patch_info->type) {
                case MONO_PATCH_INFO_EXC: {
                        unsigned char *ip = patch_info->ip.i + cfg->native_code;
+                       const char *ex_name = patch_info->data.target;
                        i = exception_id_by_name (patch_info->data.target);
                        if (exc_throw_pos [i]) {
                                arm_patch (ip, exc_throw_pos [i]);
@@ -3039,6 +3068,8 @@ mono_arch_emit_exceptions (MonoCompile *cfg)
                                exc_throw_pos [i] = code;
                        }
                        arm_patch (ip, code);
+                       //*(int*)code = 0xef9f0001;
+                       code += 4;
                        /*mono_add_patch_info (cfg, code - cfg->native_code, MONO_PATCH_INFO_EXC_NAME, patch_info->data.target);*/
                        ARM_LDR_IMM (code, ARMREG_R0, ARMREG_PC, 0);
                        /* we got here from a conditional call, so the calling ip is set in lr already */
@@ -3046,7 +3077,7 @@ mono_arch_emit_exceptions (MonoCompile *cfg)
                        patch_info->data.name = "mono_arch_throw_exception_by_name";
                        patch_info->ip.i = code - cfg->native_code;
                        ARM_B (code, 0);
-                       *(gpointer*)code = patch_info->data.target;
+                       *(gpointer*)code = ex_name;
                        code += 4;
                        break;
                }
@@ -3131,3 +3162,11 @@ mono_arch_flush_register_windows (void)
 {
 }
 
+void
+mono_arch_fixup_jinfo (MonoCompile *cfg)
+{
+       /* max encoded stack usage is 64KB * 4 */
+       g_assert ((cfg->stack_usage & ~(0xffff << 2)) == 0);
+       cfg->jit_info->used_regs |= cfg->stack_usage << 14;
+}
+