diff options
author | Zoltan Varga <vargaz@gmail.com> | 2014-11-05 06:45:14 +0300 |
---|---|---|
committer | Zoltan Varga <vargaz@gmail.com> | 2014-11-11 01:18:46 +0300 |
commit | 0637e03e6af49672bec290bceefc3b46ea13dc82 (patch) | |
tree | e2f346245728bc99ce9227cf164fe2088a2f143f | |
parent | ad389c3fc7ed654edf3050ebcf1b2ac25f621681 (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.c | 39 |
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: { |