diff options
author | Richard Earnshaw <rearnsha@arm.com> | 2005-08-20 10:31:42 +0000 |
---|---|---|
committer | Richard Earnshaw <rearnsha@gcc.gnu.org> | 2005-08-20 10:31:42 +0000 |
commit | 2591db658c39d384b250273edf597d1d6344c8f8 (patch) | |
tree | 604eb1e500ff62801c72486adca54f29901c087e /gcc | |
parent | fc437ce97f748ab58c9acbf32483c268ac97e320 (diff) | |
download | gcc-2591db658c39d384b250273edf597d1d6344c8f8.zip gcc-2591db658c39d384b250273edf597d1d6344c8f8.tar.gz gcc-2591db658c39d384b250273edf597d1d6344c8f8.tar.bz2 |
arm.h (arm_stack_offsets): Add locals_base field.
* arm.h (arm_stack_offsets): Add locals_base field.
* arm.c (arm_get_frame_offsets): Compute it.
(thumb_compute_initial_elimination offset): Make the Thumb frame
pointer point to the base of the local variables.
(thumb_expand_prologue): Update accordingly.
(thumb_expand_epilogue): Likewise.
* arm.md (thumb_movhi_clobber): Make this insn a define_expand. Change
mode of clobbered scratch to DImode. Handle a case that's known to
need this.
From-SVN: r103301
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/ChangeLog | 13 | ||||
-rw-r--r-- | gcc/config/arm/arm.c | 69 | ||||
-rw-r--r-- | gcc/config/arm/arm.h | 1 | ||||
-rw-r--r-- | gcc/config/arm/arm.md | 20 |
4 files changed, 73 insertions, 30 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 949087e..795baf1 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,16 @@ +2005-08-20 Richard Earnshaw <richard.earnshaw@arm.com> + + * arm.h (arm_stack_offsets): Add locals_base field. + * arm.c (arm_get_frame_offsets): Compute it. + (thumb_compute_initial_elimination offset): Make the Thumb frame + pointer point to the base of the local variables. + (thumb_expand_prologue): Update accordingly. + (thumb_expand_epilogue): Likewise. + + * arm.md (thumb_movhi_clobber): Make this insn a define_expand. Change + mode of clobbered scratch to DImode. Handle a case that's known to + need this. + 2005-08-19 David Edelsohn <edelsohn@gnu.org> * config/rs6000/rs6000.md (gt0<mode>): Delete. diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c index 0235c53..9037838 100644 --- a/gcc/config/arm/arm.c +++ b/gcc/config/arm/arm.c @@ -9992,7 +9992,7 @@ thumb_force_lr_save (void) | | \ | | local | | variables - | | / + locals base pointer -> | | / -- | | \ | | outgoing @@ -10109,8 +10109,9 @@ arm_get_frame_offsets (void) && (offsets->soft_frame & 7)) offsets->soft_frame += 4; - offsets->outgoing_args = offsets->soft_frame + frame_size - + current_function_outgoing_args_size; + offsets->locals_base = offsets->soft_frame + frame_size; + offsets->outgoing_args = (offsets->locals_base + + current_function_outgoing_args_size); if (ARM_DOUBLEWORD_ALIGN) { @@ -13158,8 +13159,10 @@ arm_init_expanders (void) } -/* Like arm_compute_initial_elimination offset. Simpler because - THUMB_HARD_FRAME_POINTER isn't actually the ABI specified frame pointer. */ +/* Like arm_compute_initial_elimination offset. Simpler because there + isn't an ABI specified frame pointer for Thumb. Instead, we set it + to point at the base of the local variables after static stack + space for a function has been allocated. */ HOST_WIDE_INT thumb_compute_initial_elimination_offset (unsigned int from, unsigned int to) @@ -13179,10 +13182,12 @@ thumb_compute_initial_elimination_offset (unsigned int from, unsigned int to) case FRAME_POINTER_REGNUM: return offsets->soft_frame - offsets->saved_args; - case THUMB_HARD_FRAME_POINTER_REGNUM: case ARM_HARD_FRAME_POINTER_REGNUM: return offsets->saved_regs - offsets->saved_args; + case THUMB_HARD_FRAME_POINTER_REGNUM: + return offsets->locals_base - offsets->saved_args; + default: gcc_unreachable (); } @@ -13194,10 +13199,12 @@ thumb_compute_initial_elimination_offset (unsigned int from, unsigned int to) case STACK_POINTER_REGNUM: return offsets->outgoing_args - offsets->soft_frame; - case THUMB_HARD_FRAME_POINTER_REGNUM: case ARM_HARD_FRAME_POINTER_REGNUM: return offsets->saved_regs - offsets->soft_frame; + case THUMB_HARD_FRAME_POINTER_REGNUM: + return offsets->locals_base - offsets->soft_frame; + default: gcc_unreachable (); } @@ -13239,18 +13246,11 @@ thumb_expand_prologue (void) if (flag_pic) arm_load_pic_register (live_regs_mask); - offsets = arm_get_frame_offsets (); - - if (frame_pointer_needed) - { - insn = emit_insn (gen_movsi (hard_frame_pointer_rtx, - stack_pointer_rtx)); - RTX_FRAME_RELATED_P (insn) = 1; - } - else if (CALLER_INTERWORKING_SLOT_SIZE > 0) + if (!frame_pointer_needed && CALLER_INTERWORKING_SLOT_SIZE > 0) emit_move_insn (gen_rtx_REG (Pmode, ARM_HARD_FRAME_POINTER_REGNUM), stack_pointer_rtx); + offsets = arm_get_frame_offsets (); amount = offsets->outgoing_args - offsets->saved_regs; if (amount) { @@ -13336,12 +13336,29 @@ thumb_expand_prologue (void) REG_NOTES (insn)); } } - /* If the frame pointer is needed, emit a special barrier that - will prevent the scheduler from moving stores to the frame - before the stack adjustment. */ - if (frame_pointer_needed) - emit_insn (gen_stack_tie (stack_pointer_rtx, - hard_frame_pointer_rtx)); + } + + if (frame_pointer_needed) + { + amount = offsets->outgoing_args - offsets->locals_base; + + if (amount < 1024) + insn = emit_insn (gen_addsi3 (hard_frame_pointer_rtx, + stack_pointer_rtx, GEN_INT (amount))); + else + { + emit_insn (gen_movsi (hard_frame_pointer_rtx, GEN_INT (amount))); + insn = emit_insn (gen_addsi3 (hard_frame_pointer_rtx, + hard_frame_pointer_rtx, + stack_pointer_rtx)); + dwarf = gen_rtx_SET (SImode, hard_frame_pointer_rtx, + plus_constant (stack_pointer_rtx, amount)); + RTX_FRAME_RELATED_P (dwarf) = 1; + REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_FRAME_RELATED_EXPR, dwarf, + REG_NOTES (insn)); + } + + RTX_FRAME_RELATED_P (insn) = 1; } if (current_function_profile || !TARGET_SCHED_PROLOG) @@ -13373,8 +13390,12 @@ thumb_expand_epilogue (void) amount = offsets->outgoing_args - offsets->saved_regs; if (frame_pointer_needed) - emit_insn (gen_movsi (stack_pointer_rtx, hard_frame_pointer_rtx)); - else if (amount) + { + emit_insn (gen_movsi (stack_pointer_rtx, hard_frame_pointer_rtx)); + amount = offsets->locals_base - offsets->saved_regs; + } + + if (amount) { if (amount < 512) emit_insn (gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx, diff --git a/gcc/config/arm/arm.h b/gcc/config/arm/arm.h index a434d4f..64b5e37 100644 --- a/gcc/config/arm/arm.h +++ b/gcc/config/arm/arm.h @@ -1476,6 +1476,7 @@ typedef struct arm_stack_offsets GTY(()) int frame; /* ARM_HARD_FRAME_POINTER_REGNUM. */ int saved_regs; int soft_frame; /* FRAME_POINTER_REGNUM. */ + int locals_base; /* THUMB_HARD_FRAME_POINTER_REGNUM. */ int outgoing_args; /* STACK_POINTER_REGNUM. */ } arm_stack_offsets; diff --git a/gcc/config/arm/arm.md b/gcc/config/arm/arm.md index eaa7d51..3bc62de 100644 --- a/gcc/config/arm/arm.md +++ b/gcc/config/arm/arm.md @@ -4951,13 +4951,21 @@ [(set_attr "predicable" "yes")] ) -(define_insn "thumb_movhi_clobber" - [(set (match_operand:HI 0 "memory_operand" "=m") - (match_operand:HI 1 "register_operand" "l")) - (clobber (match_operand:SI 2 "register_operand" "=&l"))] +(define_expand "thumb_movhi_clobber" + [(set (match_operand:HI 0 "memory_operand" "") + (match_operand:HI 1 "register_operand" "")) + (clobber (match_operand:DI 2 "register_operand" ""))] "TARGET_THUMB" - "* - gcc_unreachable ();" + " + if (strict_memory_address_p (HImode, XEXP (operands[0], 0)) + && REGNO (operands[1]) <= LAST_LO_REGNUM) + { + emit_insn (gen_movhi (operands[0], operands[1])); + DONE; + } + /* XXX Fixme, need to handle other cases here as well. */ + gcc_unreachable (); + " ) ;; We use a DImode scratch because we may occasionally need an additional |