Author: zoltan
Date: 2008-02-08 08:43:30 -0500 (Fri, 08 Feb 2008)
New Revision: 95241

Modified:
   trunk/mono/mono/mini/ChangeLog
   trunk/mono/mono/mini/mini-arm.c
Log:
2008-02-08  Zoltan Varga  <[EMAIL PROTECTED]>

        * objects.cs: Add tests for large argument offsets on ARM.

        * mini-arm.c (mono_arch_emit_prolog): Fix handling of arguments with 
large 
        stack offsets. Fixes #359651.


Modified: trunk/mono/mono/mini/ChangeLog
===================================================================
--- trunk/mono/mono/mini/ChangeLog      2008-02-08 13:36:44 UTC (rev 95240)
+++ trunk/mono/mono/mini/ChangeLog      2008-02-08 13:43:30 UTC (rev 95241)
@@ -1,5 +1,10 @@
 2008-02-08  Zoltan Varga  <[EMAIL PROTECTED]>
 
+       * objects.cs: Add tests for large argument offsets on ARM.
+
+       * mini-arm.c (mono_arch_emit_prolog): Fix handling of arguments with 
large 
+       stack offsets. Fixes #359651.
+
        * mini.c (mono_normalize_opcodes): Remap CEE_CONV_R4/R8 properly.
 
        * cpu-s390x.md: Add OP_LCONV_TO_R4/R8.

Modified: trunk/mono/mono/mini/mini-arm.c
===================================================================
--- trunk/mono/mono/mini/mini-arm.c     2008-02-08 13:36:44 UTC (rev 95240)
+++ trunk/mono/mono/mini/mini-arm.c     2008-02-08 13:43:30 UTC (rev 95241)
@@ -3261,8 +3261,12 @@
                        else if (ainfo->regtype == RegTypeFP) {
                                g_assert_not_reached ();
                        } else if (ainfo->regtype == RegTypeBase) {
-                               g_assert (arm_is_imm12 (prev_sp_offset + 
ainfo->offset));
-                               ARM_LDR_IMM (code, inst->dreg, ARMREG_SP, 
(prev_sp_offset + ainfo->offset));
+                               if (arm_is_imm12 (prev_sp_offset + 
ainfo->offset)) {
+                                       ARM_LDR_IMM (code, inst->dreg, 
ARMREG_SP, (prev_sp_offset + ainfo->offset));
+                               } else {
+                                       code = mono_arm_emit_load_imm (code, 
ARMREG_IP, inst->inst_offset);
+                                       ARM_LDR_REG_REG (code, inst->dreg, 
ARMREG_SP, ARMREG_IP);
+                               }
                        } else
                                g_assert_not_reached ();
 
@@ -3285,8 +3289,8 @@
                                                ARM_STRH_IMM (code, ainfo->reg, 
inst->inst_basereg, inst->inst_offset);
                                        } else {
                                                code = mono_arm_emit_load_imm 
(code, ARMREG_IP, inst->inst_offset);
-                                               ARM_ADD_REG_REG (code, 
ARMREG_IP, ARMREG_IP, inst->inst_basereg);
-                                               ARM_STRH_IMM (code, ainfo->reg, 
ARMREG_IP, 0);
+                                               /* note: the args are reversed 
in the macro */
+                                               ARM_STRH_REG_REG (code, 
inst->inst_basereg, ainfo->reg, ARMREG_IP);
                                        }
                                        break;
                                case 8:
@@ -3311,15 +3315,24 @@
                                ARM_STR_IMM (code, ARMREG_LR, 
inst->inst_basereg, inst->inst_offset + 4);
                                ARM_STR_IMM (code, ARMREG_R3, 
inst->inst_basereg, inst->inst_offset);
                        } else if (ainfo->regtype == RegTypeBase) {
-                               g_assert (arm_is_imm12 (prev_sp_offset + 
ainfo->offset));
+                               if (arm_is_imm12 (prev_sp_offset + 
ainfo->offset)) {
+                                       ARM_LDR_IMM (code, ARMREG_LR, 
ARMREG_SP, (prev_sp_offset + ainfo->offset));
+                               } else {
+                                       code = mono_arm_emit_load_imm (code, 
ARMREG_IP, prev_sp_offset + ainfo->offset);
+                                       ARM_LDR_REG_REG (code, ARMREG_LR, 
ARMREG_SP, ARMREG_IP);
+                               }
+
                                switch (ainfo->size) {
                                case 1:
-                                       ARM_LDR_IMM (code, ARMREG_LR, 
ARMREG_SP, (prev_sp_offset + ainfo->offset));
-                                       g_assert (arm_is_imm12 
(inst->inst_offset));
-                                       ARM_STRB_IMM (code, ARMREG_LR, 
inst->inst_basereg, inst->inst_offset);
+                                       if (arm_is_imm8 (inst->inst_offset)) {
+                                               ARM_STRB_IMM (code, ARMREG_LR, 
inst->inst_basereg, inst->inst_offset);
+                                       } else {
+                                               code = mono_arm_emit_load_imm 
(code, ARMREG_IP, inst->inst_offset);
+                                               ARM_ADD_REG_REG (code, 
ARMREG_IP, ARMREG_IP, inst->inst_basereg);
+                                               ARM_STRB_IMM (code, ARMREG_LR, 
ARMREG_IP, 0);
+                                       }
                                        break;
                                case 2:
-                                       ARM_LDR_IMM (code, ARMREG_LR, 
ARMREG_SP, (prev_sp_offset + ainfo->offset));
                                        if (arm_is_imm8 (inst->inst_offset)) {
                                                ARM_STRH_IMM (code, ARMREG_LR, 
inst->inst_basereg, inst->inst_offset);
                                        } else {
@@ -3329,18 +3342,36 @@
                                        }
                                        break;
                                case 8:
-                                       g_assert (arm_is_imm12 
(inst->inst_offset));
-                                       ARM_LDR_IMM (code, ARMREG_LR, 
ARMREG_SP, (prev_sp_offset + ainfo->offset));
-                                       ARM_STR_IMM (code, ARMREG_LR, 
inst->inst_basereg, inst->inst_offset);
-                                       g_assert (arm_is_imm12 (prev_sp_offset 
+ ainfo->offset + 4));
-                                       g_assert (arm_is_imm12 
(inst->inst_offset + 4));
-                                       ARM_LDR_IMM (code, ARMREG_LR, 
ARMREG_SP, (prev_sp_offset + ainfo->offset + 4));
-                                       ARM_STR_IMM (code, ARMREG_LR, 
inst->inst_basereg, inst->inst_offset + 4);
+                                       if (arm_is_imm12 (inst->inst_offset)) {
+                                               ARM_STR_IMM (code, ARMREG_LR, 
inst->inst_basereg, inst->inst_offset);
+                                       } else {
+                                               code = mono_arm_emit_load_imm 
(code, ARMREG_IP, inst->inst_offset);
+                                               ARM_ADD_REG_REG (code, 
ARMREG_IP, ARMREG_IP, inst->inst_basereg);
+                                               ARM_STR_IMM (code, ARMREG_LR, 
ARMREG_IP, 0);
+                                       }
+                                       if (arm_is_imm12 (prev_sp_offset + 
ainfo->offset + 4)) {
+                                               ARM_LDR_IMM (code, ARMREG_LR, 
ARMREG_SP, (prev_sp_offset + ainfo->offset + 4));
+                                       } else {
+                                               code = mono_arm_emit_load_imm 
(code, ARMREG_IP, prev_sp_offset + ainfo->offset + 4);
+                                               ARM_ADD_REG_REG (code, 
ARMREG_IP, ARMREG_IP, ARMREG_SP);
+                                               ARM_LDR_IMM (code, ARMREG_LR, 
ARMREG_IP, 0);
+                                       }
+                                       if (arm_is_imm12 (inst->inst_offset + 
4)) {
+                                               ARM_STR_IMM (code, ARMREG_LR, 
inst->inst_basereg, inst->inst_offset + 4);
+                                       } else {
+                                               code = mono_arm_emit_load_imm 
(code, ARMREG_IP, inst->inst_offset + 4);
+                                               ARM_ADD_REG_REG (code, 
ARMREG_IP, ARMREG_IP, inst->inst_basereg);
+                                               ARM_STR_IMM (code, ARMREG_LR, 
ARMREG_IP, 0);
+                                       }
                                        break;
                                default:
-                                       g_assert (arm_is_imm12 
(inst->inst_offset));
-                                       ARM_LDR_IMM (code, ARMREG_LR, 
ARMREG_SP, (prev_sp_offset + ainfo->offset));
-                                       ARM_STR_IMM (code, ARMREG_LR, 
inst->inst_basereg, inst->inst_offset);
+                                       if (arm_is_imm12 (inst->inst_offset)) {
+                                               ARM_STR_IMM (code, ARMREG_LR, 
inst->inst_basereg, inst->inst_offset);
+                                       } else {
+                                               code = mono_arm_emit_load_imm 
(code, ARMREG_IP, inst->inst_offset);
+                                               ARM_ADD_REG_REG (code, 
ARMREG_IP, ARMREG_IP, inst->inst_basereg);
+                                               ARM_STR_IMM (code, ARMREG_LR, 
ARMREG_IP, 0);
+                                       }
                                        break;
                                }
                        } else if (ainfo->regtype == RegTypeFP) {
@@ -3353,8 +3384,13 @@
                                if (mono_class_from_mono_type 
(inst->inst_vtype))
                                        size = mono_class_native_size 
(mono_class_from_mono_type (inst->inst_vtype), NULL);
                                for (cur_reg = 0; cur_reg < ainfo->size; 
++cur_reg) {
-                                       g_assert (arm_is_imm12 (doffset));
-                                       ARM_STR_IMM (code, ainfo->reg + 
cur_reg, inst->inst_basereg, doffset);
+                                       if (arm_is_imm12 (doffset)) {
+                                               ARM_STR_IMM (code, ainfo->reg + 
cur_reg, inst->inst_basereg, doffset);
+                                       } else {
+                                               code = mono_arm_emit_load_imm 
(code, ARMREG_IP, doffset);
+                                               ARM_ADD_REG_REG (code, 
ARMREG_IP, ARMREG_IP, inst->inst_basereg);
+                                               ARM_STR_IMM (code, ainfo->reg + 
cur_reg, ARMREG_IP, 0);
+                                       }
                                        soffset += sizeof (gpointer);
                                        doffset += sizeof (gpointer);
                                }

_______________________________________________
Mono-patches maillist  -  [email protected]
http://lists.ximian.com/mailman/listinfo/mono-patches

Reply via email to