diff options
Diffstat (limited to 'gcc/config')
-rw-r--r-- | gcc/config/avr/avr.c | 80 | ||||
-rw-r--r-- | gcc/config/avr/avr.md | 26 |
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" "") |