summaryrefslogtreecommitdiffstats
path: root/gcc/config/avr
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/config/avr')
-rw-r--r--gcc/config/avr/avr.c80
-rw-r--r--gcc/config/avr/avr.md26
2 files changed, 76 insertions, 30 deletions
diff --git a/gcc/config/avr/avr.c b/gcc/config/avr/avr.c
index d2cc33a0293..bde58f029b6 100644
--- a/gcc/config/avr/avr.c
+++ b/gcc/config/avr/avr.c
@@ -763,8 +763,32 @@ expand_prologue (void)
GET_MODE(myfp))));
RTX_FRAME_RELATED_P (insn) = 1;
- insn = emit_move_insn (stack_pointer_rtx, frame_pointer_rtx);
- RTX_FRAME_RELATED_P (insn) = 1;
+ /* Copy to stack pointer. */
+ if (TARGET_TINY_STACK)
+ {
+ insn = emit_move_insn (stack_pointer_rtx, frame_pointer_rtx);
+ RTX_FRAME_RELATED_P (insn) = 1;
+ }
+ else if (TARGET_NO_INTERRUPTS
+ || cfun->machine->is_signal
+ || cfun->machine->is_OS_main)
+ {
+ insn =
+ emit_insn (gen_movhi_sp_r_irq_off (stack_pointer_rtx,
+ frame_pointer_rtx));
+ RTX_FRAME_RELATED_P (insn) = 1;
+ }
+ else if (cfun->machine->is_interrupt)
+ {
+ insn = emit_insn (gen_movhi_sp_r_irq_on (stack_pointer_rtx,
+ frame_pointer_rtx));
+ RTX_FRAME_RELATED_P (insn) = 1;
+ }
+ else
+ {
+ insn = emit_move_insn (stack_pointer_rtx, frame_pointer_rtx);
+ RTX_FRAME_RELATED_P (insn) = 1;
+ }
fp_plus_insns = get_insns ();
end_sequence ();
@@ -915,7 +939,25 @@ expand_epilogue (void)
GET_MODE(myfp))));
/* Copy to stack pointer. */
- emit_move_insn (stack_pointer_rtx, frame_pointer_rtx);
+ if (TARGET_TINY_STACK)
+ {
+ emit_move_insn (stack_pointer_rtx, frame_pointer_rtx);
+ }
+ else if (TARGET_NO_INTERRUPTS
+ || cfun->machine->is_signal)
+ {
+ emit_insn (gen_movhi_sp_r_irq_off (stack_pointer_rtx,
+ frame_pointer_rtx));
+ }
+ else if (cfun->machine->is_interrupt)
+ {
+ emit_insn (gen_movhi_sp_r_irq_on (stack_pointer_rtx,
+ frame_pointer_rtx));
+ }
+ else
+ {
+ emit_move_insn (stack_pointer_rtx, frame_pointer_rtx);
+ }
fp_plus_insns = get_insns ();
end_sequence ();
@@ -1708,32 +1750,12 @@ output_movhi (rtx insn, rtx operands[], int *l)
if (test_hard_reg_class (STACK_REG, dest))
{
if (TARGET_TINY_STACK)
- {
- *l = 1;
- return AS2 (out,__SP_L__,%A1);
- }
- /* Use simple load of stack pointer if no interrupts are used
- or inside main or signal function prologue where they disabled. */
- else if (TARGET_NO_INTERRUPTS
- || (reload_completed
- && cfun->machine->is_signal
- && prologue_epilogue_contains (insn)))
- {
- *l = 2;
- return (AS2 (out,__SP_H__,%B1) CR_TAB
- AS2 (out,__SP_L__,%A1));
- }
- /* In interrupt prolog we know interrupts are enabled. */
- else if (reload_completed
- && cfun->machine->is_interrupt
- && prologue_epilogue_contains (insn))
- {
- *l = 4;
- return ("cli" CR_TAB
- AS2 (out,__SP_H__,%B1) CR_TAB
- "sei" CR_TAB
- AS2 (out,__SP_L__,%A1));
- }
+ return *l = 1, AS2 (out,__SP_L__,%A1);
+ /* Use simple load of stack pointer if no interrupts are
+ used. */
+ else if (TARGET_NO_INTERRUPTS)
+ return *l = 2, (AS2 (out,__SP_H__,%B1) CR_TAB
+ AS2 (out,__SP_L__,%A1));
*l = 5;
return (AS2 (in,__tmp_reg__,__SREG__) CR_TAB
"cli" CR_TAB
diff --git a/gcc/config/avr/avr.md b/gcc/config/avr/avr.md
index ffbbefa74ef..a4914c4aa61 100644
--- a/gcc/config/avr/avr.md
+++ b/gcc/config/avr/avr.md
@@ -56,7 +56,9 @@
(UNSPEC_CLI 3)
(UNSPECV_PROLOGUE_SAVES 0)
- (UNSPECV_EPILOGUE_RESTORES 1)])
+ (UNSPECV_EPILOGUE_RESTORES 1)
+ (UNSPECV_WRITE_SP_IRQ_ON 2)
+ (UNSPECV_WRITE_SP_IRQ_OFF 3)])
(include "predicates.md")
(include "constraints.md")
@@ -230,6 +232,28 @@
[(set_attr "length" "5,2")
(set_attr "cc" "none,none")])
+(define_insn "movhi_sp_r_irq_off"
+ [(set (match_operand:HI 0 "stack_register_operand" "=q")
+ (unspec_volatile:HI [(match_operand:HI 1 "register_operand" "r")]
+ UNSPECV_WRITE_SP_IRQ_OFF))]
+ ""
+ "out __SP_H__, %B1
+ out __SP_L__, %A1"
+ [(set_attr "length" "2")
+ (set_attr "cc" "none")])
+
+(define_insn "movhi_sp_r_irq_on"
+ [(set (match_operand:HI 0 "stack_register_operand" "=q")
+ (unspec_volatile:HI [(match_operand:HI 1 "register_operand" "r")]
+ UNSPECV_WRITE_SP_IRQ_ON))]
+ ""
+ "cli
+ out __SP_H__, %B1
+ sei
+ out __SP_L__, %A1"
+ [(set_attr "length" "4")
+ (set_attr "cc" "none")])
+
(define_peephole2
[(match_scratch:QI 2 "d")
(set (match_operand:HI 0 "l_register_operand" "")
OpenPOWER on IntegriCloud