2005-12-12 Zoltan Varga <vargaz@gmail.com>
[mono.git] / mono / mini / mini-arm.c
index 9fbbc12a0649b6bd233543b4c24797750927e48f..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;
@@ -638,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;
@@ -669,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;
@@ -1564,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);
@@ -1597,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) {
@@ -1751,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:
@@ -1947,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);
@@ -2320,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;
@@ -2500,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);
@@ -2509,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);