Index: config/avr/avr.md =================================================================== --- config/avr/avr.md (revision 179206) +++ config/avr/avr.md (working copy) @@ -136,7 +136,7 @@ (define_attr "length" "" ;; Otherwise do special processing depending on the attribute. (define_attr "adjust_len" - "out_bitop, out_plus, tsthi, tstsi, compare, + "out_bitop, out_plus, addto_sp, tsthi, tstsi, compare, mov8, mov16, mov32, reload_in16, reload_in32, ashlqi, ashrqi, lshrqi, ashlhi, ashrhi, lshrhi, @@ -346,15 +346,6 @@ (define_expand "movhi" } }") -(define_insn "*movhi_sp" - [(set (match_operand:HI 0 "register_operand" "=q,r") - (match_operand:HI 1 "register_operand" "r,q"))] - "((stack_register_operand(operands[0], HImode) && register_operand (operands[1], HImode)) - || (register_operand (operands[0], HImode) && stack_register_operand(operands[1], HImode)))" - "* return output_movhi (insn, operands, NULL);" - [(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")] @@ -767,142 +758,16 @@ (define_insn "*addhi3_zero_extend1" [(set_attr "length" "2") (set_attr "cc" "set_n")]) -(define_insn "*addhi3_sp_R_pc2" +(define_insn "*addhi3_sp_R" [(set (match_operand:HI 1 "stack_register_operand" "=q") (plus:HI (match_operand:HI 2 "stack_register_operand" "q") (match_operand:HI 0 "avr_sp_immediate_operand" "R")))] - "AVR_2_BYTE_PC" - "*{ - if (CONST_INT_P (operands[0])) - { - switch(INTVAL (operands[0])) - { - case -6: - return \"rcall .\" CR_TAB - \"rcall .\" CR_TAB - \"rcall .\"; - case -5: - return \"rcall .\" CR_TAB - \"rcall .\" CR_TAB - \"push __tmp_reg__\"; - case -4: - return \"rcall .\" CR_TAB - \"rcall .\"; - case -3: - return \"rcall .\" CR_TAB - \"push __tmp_reg__\"; - case -2: - return \"rcall .\"; - case -1: - return \"push __tmp_reg__\"; - case 0: - return \"\"; - case 1: - return \"pop __tmp_reg__\"; - case 2: - return \"pop __tmp_reg__\" CR_TAB - \"pop __tmp_reg__\"; - case 3: - return \"pop __tmp_reg__\" CR_TAB - \"pop __tmp_reg__\" CR_TAB - \"pop __tmp_reg__\"; - case 4: - return \"pop __tmp_reg__\" CR_TAB - \"pop __tmp_reg__\" CR_TAB - \"pop __tmp_reg__\" CR_TAB - \"pop __tmp_reg__\"; - case 5: - return \"pop __tmp_reg__\" CR_TAB - \"pop __tmp_reg__\" CR_TAB - \"pop __tmp_reg__\" CR_TAB - \"pop __tmp_reg__\" CR_TAB - \"pop __tmp_reg__\"; - } - } - return \"bug\"; - }" - [(set (attr "length") - (cond [(eq (const_int -6) (symbol_ref "INTVAL (operands[0])")) (const_int 3) - (eq (const_int -5) (symbol_ref "INTVAL (operands[0])")) (const_int 3) - (eq (const_int -4) (symbol_ref "INTVAL (operands[0])")) (const_int 2) - (eq (const_int -3) (symbol_ref "INTVAL (operands[0])")) (const_int 2) - (eq (const_int -2) (symbol_ref "INTVAL (operands[0])")) (const_int 1) - (eq (const_int -1) (symbol_ref "INTVAL (operands[0])")) (const_int 1) - (eq (const_int 0) (symbol_ref "INTVAL (operands[0])")) (const_int 0) - (eq (const_int 1) (symbol_ref "INTVAL (operands[0])")) (const_int 1) - (eq (const_int 2) (symbol_ref "INTVAL (operands[0])")) (const_int 2) - (eq (const_int 3) (symbol_ref "INTVAL (operands[0])")) (const_int 3) - (eq (const_int 4) (symbol_ref "INTVAL (operands[0])")) (const_int 4) - (eq (const_int 5) (symbol_ref "INTVAL (operands[0])")) (const_int 5)] - (const_int 0)))]) - -(define_insn "*addhi3_sp_R_pc3" - [(set (match_operand:HI 1 "stack_register_operand" "=q") - (plus:HI (match_operand:HI 2 "stack_register_operand" "q") - (match_operand:QI 0 "avr_sp_immediate_operand" "R")))] - "AVR_3_BYTE_PC" - "*{ - if (CONST_INT_P (operands[0])) - { - switch(INTVAL (operands[0])) - { - case -6: - return \"rcall .\" CR_TAB - \"rcall .\"; - case -5: - return \"rcall .\" CR_TAB - \"push __tmp_reg__\" CR_TAB - \"push __tmp_reg__\"; - case -4: - return \"rcall .\" CR_TAB - \"push __tmp_reg__\"; - case -3: - return \"rcall .\"; - case -2: - return \"push __tmp_reg__\" CR_TAB - \"push __tmp_reg__\"; - case -1: - return \"push __tmp_reg__\"; - case 0: - return \"\"; - case 1: - return \"pop __tmp_reg__\"; - case 2: - return \"pop __tmp_reg__\" CR_TAB - \"pop __tmp_reg__\"; - case 3: - return \"pop __tmp_reg__\" CR_TAB - \"pop __tmp_reg__\" CR_TAB - \"pop __tmp_reg__\"; - case 4: - return \"pop __tmp_reg__\" CR_TAB - \"pop __tmp_reg__\" CR_TAB - \"pop __tmp_reg__\" CR_TAB - \"pop __tmp_reg__\"; - case 5: - return \"pop __tmp_reg__\" CR_TAB - \"pop __tmp_reg__\" CR_TAB - \"pop __tmp_reg__\" CR_TAB - \"pop __tmp_reg__\" CR_TAB - \"pop __tmp_reg__\"; - } - } - return \"bug\"; - }" - [(set (attr "length") - (cond [(eq (const_int -6) (symbol_ref "INTVAL (operands[0])")) (const_int 2) - (eq (const_int -5) (symbol_ref "INTVAL (operands[0])")) (const_int 3) - (eq (const_int -4) (symbol_ref "INTVAL (operands[0])")) (const_int 2) - (eq (const_int -3) (symbol_ref "INTVAL (operands[0])")) (const_int 1) - (eq (const_int -2) (symbol_ref "INTVAL (operands[0])")) (const_int 2) - (eq (const_int -1) (symbol_ref "INTVAL (operands[0])")) (const_int 1) - (eq (const_int 0) (symbol_ref "INTVAL (operands[0])")) (const_int 0) - (eq (const_int 1) (symbol_ref "INTVAL (operands[0])")) (const_int 1) - (eq (const_int 2) (symbol_ref "INTVAL (operands[0])")) (const_int 2) - (eq (const_int 3) (symbol_ref "INTVAL (operands[0])")) (const_int 3) - (eq (const_int 4) (symbol_ref "INTVAL (operands[0])")) (const_int 4) - (eq (const_int 5) (symbol_ref "INTVAL (operands[0])")) (const_int 5)] - (const_int 0)))]) + "" + { + return avr_out_addto_sp (operands, NULL); + } + [(set_attr "length" "5") + (set_attr "adjust_len" "addto_sp")]) (define_insn "*addhi3" [(set (match_operand:HI 0 "register_operand" "=r,!w,!w,d,r,r") Index: config/avr/avr-protos.h =================================================================== --- config/avr/avr-protos.h (revision 179205) +++ config/avr/avr-protos.h (working copy) @@ -83,6 +83,7 @@ extern void avr_output_addr_vec_elt (FIL extern const char *avr_out_sbxx_branch (rtx insn, rtx operands[]); extern const char* avr_out_bitop (rtx, rtx*, int*); extern const char* avr_out_plus (rtx*, int*); +extern const char* avr_out_addto_sp (rtx*, int*); extern bool avr_popcount_each_byte (rtx, int, int); extern int extra_constraint_Q (rtx x); Index: config/avr/avr.c =================================================================== --- config/avr/avr.c (revision 179206) +++ config/avr/avr.c (working copy) @@ -4896,6 +4896,47 @@ avr_out_bitop (rtx insn, rtx *xop, int * return ""; } + +/* PLEN == NULL: Output code to add CONST_INT OP[0] to SP. + PLEN != NULL: Set *PLEN to the length of that sequence. + Return "". */ + +const char* +avr_out_addto_sp (rtx *op, int *plen) +{ + int pc_len = AVR_2_BYTE_PC ? 2 : 3; + int addend = INTVAL (op[0]); + + if (plen) + *plen = 0; + + if (addend < 0) + { + if (flag_verbose_asm || flag_print_asm_name) + avr_asm_len (ASM_COMMENT_START "SP -= %n0", op, plen, 0); + + while (addend <= -pc_len) + { + addend += pc_len; + avr_asm_len ("rcall .", op, plen, 1); + } + + while (addend++ < 0) + avr_asm_len ("push __zero_reg__", op, plen, 1); + } + else if (addend > 0) + { + if (flag_verbose_asm || flag_print_asm_name) + avr_asm_len (ASM_COMMENT_START "SP += %0", op, plen, 0); + + while (addend-- > 0) + avr_asm_len ("pop __tmp_reg__", op, plen, 1); + } + + return ""; +} + + /* Create RTL split patterns for byte sized rotate expressions. This produces a series of move instructions and considers overlap situations. Overlapping non-HImode operands need a scratch register. */ @@ -5089,6 +5130,8 @@ adjust_insn_length (rtx insn, int len) case ADJUST_LEN_OUT_BITOP: avr_out_bitop (insn, op, &len); break; case ADJUST_LEN_OUT_PLUS: avr_out_plus (op, &len); break; + + case ADJUST_LEN_ADDTO_SP: avr_out_addto_sp (op, &len); break; case ADJUST_LEN_MOV8: output_movqi (insn, op, &len); break; case ADJUST_LEN_MOV16: output_movhi (insn, op, &len); break;