aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRichard Earnshaw <rearnsha@arm.com>2005-08-20 10:31:42 +0000
committerRichard Earnshaw <rearnsha@gcc.gnu.org>2005-08-20 10:31:42 +0000
commit2591db658c39d384b250273edf597d1d6344c8f8 (patch)
tree604eb1e500ff62801c72486adca54f29901c087e
parentfc437ce97f748ab58c9acbf32483c268ac97e320 (diff)
downloadgcc-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
-rw-r--r--gcc/ChangeLog13
-rw-r--r--gcc/config/arm/arm.c69
-rw-r--r--gcc/config/arm/arm.h1
-rw-r--r--gcc/config/arm/arm.md20
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