Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mono/mono.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorZoltan Varga <vargaz@gmail.com>2014-11-05 06:45:14 +0300
committerZoltan Varga <vargaz@gmail.com>2014-11-11 01:18:46 +0300
commit0637e03e6af49672bec290bceefc3b46ea13dc82 (patch)
treee2f346245728bc99ce9227cf164fe2088a2f143f
parentad389c3fc7ed654edf3050ebcf1b2ac25f621681 (diff)
[arm] Fix OP_LOCALLOC on arm so it correctly adjusts sp with the param area size even if the size is large. Fixes #24221.monotouch-8.4.0-branch
-rw-r--r--mono/mini/mini-arm.c39
1 files changed, 29 insertions, 10 deletions
diff --git a/mono/mini/mini-arm.c b/mono/mini/mini-arm.c
index b644d7dca7a..ba51b94a11a 100644
--- a/mono/mini/mini-arm.c
+++ b/mono/mini/mini-arm.c
@@ -247,9 +247,32 @@ emit_big_add (guint8 *code, int dreg, int sreg, int imm)
ARM_ADD_REG_IMM (code, dreg, sreg, imm8, rot_amount);
return code;
}
- g_assert (dreg != sreg);
- code = mono_arm_emit_load_imm (code, dreg, imm);
- ARM_ADD_REG_REG (code, dreg, dreg, sreg);
+ if (dreg == sreg) {
+ code = mono_arm_emit_load_imm (code, ARMREG_IP, imm);
+ ARM_ADD_REG_REG (code, dreg, sreg, ARMREG_IP);
+ } else {
+ code = mono_arm_emit_load_imm (code, dreg, imm);
+ ARM_ADD_REG_REG (code, dreg, dreg, sreg);
+ }
+ return code;
+}
+
+/* If dreg == sreg, this clobbers IP */
+static guint8*
+emit_sub_imm (guint8 *code, int dreg, int sreg, int imm)
+{
+ int imm8, rot_amount;
+ if ((imm8 = mono_arm_is_rotated_imm8 (imm, &rot_amount)) >= 0) {
+ ARM_SUB_REG_IMM (code, dreg, sreg, imm8, rot_amount);
+ return code;
+ }
+ if (dreg == sreg) {
+ code = mono_arm_emit_load_imm (code, ARMREG_IP, imm);
+ ARM_SUB_REG_REG (code, dreg, sreg, ARMREG_IP);
+ } else {
+ code = mono_arm_emit_load_imm (code, dreg, imm);
+ ARM_SUB_REG_REG (code, dreg, dreg, sreg);
+ }
return code;
}
@@ -4945,15 +4968,9 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb)
break;
}
case OP_LOCALLOC: {
- /* keep alignment */
- int alloca_waste = cfg->param_area;
- alloca_waste += 7;
- alloca_waste &= ~7;
/* round the size to 8 bytes */
ARM_ADD_REG_IMM8 (code, ins->dreg, ins->sreg1, 7);
ARM_BIC_REG_IMM8 (code, ins->dreg, ins->dreg, 7);
- if (alloca_waste)
- ARM_ADD_REG_IMM8 (code, ins->dreg, ins->dreg, alloca_waste);
ARM_SUB_REG_REG (code, ARMREG_SP, ARMREG_SP, ins->dreg);
/* memzero the area: dreg holds the size, sp is the pointer */
if (ins->flags & MONO_INST_INIT) {
@@ -4969,7 +4986,9 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb)
ARM_B_COND (code, ARMCOND_GE, 0);
arm_patch (code - 4, start_loop);
}
- ARM_ADD_REG_IMM8 (code, ins->dreg, ARMREG_SP, alloca_waste);
+ ARM_MOV_REG_REG (code, ins->dreg, ARMREG_SP);
+ if (cfg->param_area)
+ code = emit_sub_imm (code, ARMREG_SP, ARMREG_SP, ALIGN_TO (cfg->param_area, MONO_ARCH_FRAME_ALIGNMENT));
break;
}
case OP_DYN_CALL: {