From: Georg-Johann Lay Date: Fri, 24 Oct 2014 14:25:10 +0000 (+0000) Subject: avr-protos.h (avr_out_sign_extend): New. X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=8e3d9e673a07f84908bb7bb6b8e313ec45e6ed78;p=gcc.git avr-protos.h (avr_out_sign_extend): New. * avr-protos.h (avr_out_sign_extend): New. * avr.c (avr_adjust_insn_length) [ADJUST_LEN_SEXT]: Handle. (avr_out_sign_extend): New function. * avr.md (extendqihi2, extendqipsi2, extendqisi2, extendhipsi2) (extendhisi2, extendpsisi2): Use it. (adjust_len) [sext]: New. From-SVN: r216668 --- diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 3d46f4cbdcf..8863eb68531 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,12 @@ +2014-10-24 Georg-Johann Lay + + * avr-protos.h (avr_out_sign_extend): New. + * avr.c (avr_adjust_insn_length) [ADJUST_LEN_SEXT]: Handle. + (avr_out_sign_extend): New function. + * avr.md (extendqihi2, extendqipsi2, extendqisi2, extendhipsi2) + (extendhisi2, extendpsisi2): Use it. + (adjust_len) [sext]: New. + 2014-10-24 Martin Liska * ipa-icf.c (sem_function::compare_phi_node): PHI result comparison diff --git a/gcc/config/avr/avr-protos.h b/gcc/config/avr/avr-protos.h index 6342c087d4a..62c2055b7c9 100644 --- a/gcc/config/avr/avr-protos.h +++ b/gcc/config/avr/avr-protos.h @@ -57,6 +57,7 @@ extern const char *avr_out_compare (rtx_insn *, rtx*, int*); extern const char *avr_out_compare64 (rtx_insn *, rtx*, int*); extern const char *ret_cond_branch (rtx x, int len, int reverse); extern const char *avr_out_movpsi (rtx_insn *, rtx*, int*); +extern const char *avr_out_sign_extend (rtx_insn *, rtx*, int*); extern const char *ashlqi3_out (rtx_insn *insn, rtx operands[], int *len); extern const char *ashlhi3_out (rtx_insn *insn, rtx operands[], int *len); diff --git a/gcc/config/avr/avr.c b/gcc/config/avr/avr.c index d5b0707b36a..38fce723f38 100644 --- a/gcc/config/avr/avr.c +++ b/gcc/config/avr/avr.c @@ -7734,6 +7734,56 @@ avr_out_bitop (rtx insn, rtx *xop, int *plen) } +/* Output sign extension from XOP[1] to XOP[0] and return "". + If PLEN == NULL, print assembler instructions to perform the operation; + otherwise, set *PLEN to the length of the instruction sequence (in words) + as printed with PLEN == NULL. */ + +const char* +avr_out_sign_extend (rtx_insn *insn, rtx *xop, int *plen) +{ + // Size in bytes of source resp. destination operand. + unsigned n_src = GET_MODE_SIZE (GET_MODE (xop[1])); + unsigned n_dest = GET_MODE_SIZE (GET_MODE (xop[0])); + rtx r_msb = all_regs_rtx[REGNO (xop[1]) + n_src - 1]; + + if (plen) + *plen = 0; + + // Copy destination to source + + if (REGNO (xop[0]) != REGNO (xop[1])) + { + gcc_assert (n_src <= 2); + + if (n_src == 2) + avr_asm_len (AVR_HAVE_MOVW + ? "movw %0,%1" + : "mov %B0,%B1", xop, plen, 1); + if (n_src == 1 || !AVR_HAVE_MOVW) + avr_asm_len ("mov %A0,%A1", xop, plen, 1); + } + + // Set Carry to the sign bit MSB.7... + + if (REGNO (xop[0]) == REGNO (xop[1]) + || !reg_unused_after (insn, r_msb)) + { + avr_asm_len ("mov __tmp_reg__,%0", &r_msb, plen, 1); + r_msb = tmp_reg_rtx; + } + + avr_asm_len ("lsl %0", &r_msb, plen, 1); + + // ...and propagate it to all the new sign bits + + for (unsigned n = n_src; n < n_dest; n++) + avr_asm_len ("sbc %0,%0", &all_regs_rtx[REGNO (xop[0]) + n], plen, 1); + + return ""; +} + + /* PLEN == NULL: Output code to add CONST_INT OP[0] to SP. PLEN != NULL: Set *PLEN to the length of that sequence. Return "". */ @@ -8578,6 +8628,7 @@ avr_adjust_insn_length (rtx_insn *insn, int len) case ADJUST_LEN_MOVMEM: avr_out_movmem (insn, op, &len); break; case ADJUST_LEN_XLOAD: avr_out_xload (insn, op, &len); break; case ADJUST_LEN_LPM: avr_out_lpm (insn, op, &len); break; + case ADJUST_LEN_SEXT: avr_out_sign_extend (insn, op, &len); break; case ADJUST_LEN_SFRACT: avr_out_fract (insn, op, true, &len); break; case ADJUST_LEN_UFRACT: avr_out_fract (insn, op, false, &len); break; diff --git a/gcc/config/avr/avr.md b/gcc/config/avr/avr.md index 5d3f6e19911..c6c11cff7fb 100644 --- a/gcc/config/avr/avr.md +++ b/gcc/config/avr/avr.md @@ -147,7 +147,7 @@ ;; Otherwise do special processing depending on the attribute. (define_attr "adjust_len" - "out_bitop, plus, addto_sp, + "out_bitop, plus, addto_sp, sext, tsthi, tstpsi, tstsi, compare, compare64, call, mov8, mov16, mov24, mov32, reload_in16, reload_in24, reload_in32, ufract, sfract, round, @@ -4174,62 +4174,66 @@ [(set (match_operand:HI 0 "register_operand" "=r,r") (sign_extend:HI (match_operand:QI 1 "combine_pseudo_register_operand" "0,*r")))] "" - "@ - clr %B0\;sbrc %0,7\;com %B0 - mov %A0,%A1\;clr %B0\;sbrc %A0,7\;com %B0" + { + return avr_out_sign_extend (insn, operands, NULL); + } [(set_attr "length" "3,4") - (set_attr "cc" "set_n,set_n")]) + (set_attr "adjust_len" "sext") + (set_attr "cc" "set_n")]) (define_insn "extendqipsi2" [(set (match_operand:PSI 0 "register_operand" "=r,r") (sign_extend:PSI (match_operand:QI 1 "combine_pseudo_register_operand" "0,*r")))] "" - "@ - clr %B0\;sbrc %A0,7\;com %B0\;mov %C0,%B0 - mov %A0,%A1\;clr %B0\;sbrc %A0,7\;com %B0\;mov %C0,%B0" + { + return avr_out_sign_extend (insn, operands, NULL); + } [(set_attr "length" "4,5") - (set_attr "cc" "set_n,set_n")]) + (set_attr "adjust_len" "sext") + (set_attr "cc" "set_n")]) (define_insn "extendqisi2" [(set (match_operand:SI 0 "register_operand" "=r,r") (sign_extend:SI (match_operand:QI 1 "combine_pseudo_register_operand" "0,*r")))] "" - "@ - clr %B0\;sbrc %A0,7\;com %B0\;mov %C0,%B0\;mov %D0,%B0 - mov %A0,%A1\;clr %B0\;sbrc %A0,7\;com %B0\;mov %C0,%B0\;mov %D0,%B0" + { + return avr_out_sign_extend (insn, operands, NULL); + } [(set_attr "length" "5,6") - (set_attr "cc" "set_n,set_n")]) + (set_attr "adjust_len" "sext") + (set_attr "cc" "set_n")]) (define_insn "extendhipsi2" - [(set (match_operand:PSI 0 "register_operand" "=r,r ,r") - (sign_extend:PSI (match_operand:HI 1 "combine_pseudo_register_operand" "0,*r,*r")))] + [(set (match_operand:PSI 0 "register_operand" "=r,r") + (sign_extend:PSI (match_operand:HI 1 "combine_pseudo_register_operand" "0,*r")))] "" - "@ - clr %C0\;sbrc %B0,7\;com %C0 - mov %A0,%A1\;mov %B0,%B1\;clr %C0\;sbrc %B0,7\;com %C0 - movw %A0,%A1\;clr %C0\;sbrc %B0,7\;com %C0" - [(set_attr "length" "3,5,4") - (set_attr "isa" "*,mov,movw") + { + return avr_out_sign_extend (insn, operands, NULL); + } + [(set_attr "length" "3,5") + (set_attr "adjust_len" "sext") (set_attr "cc" "set_n")]) (define_insn "extendhisi2" - [(set (match_operand:SI 0 "register_operand" "=r,r ,r") - (sign_extend:SI (match_operand:HI 1 "combine_pseudo_register_operand" "0,*r,*r")))] + [(set (match_operand:SI 0 "register_operand" "=r,r") + (sign_extend:SI (match_operand:HI 1 "combine_pseudo_register_operand" "0,*r")))] "" - "@ - clr %C0\;sbrc %B0,7\;com %C0\;mov %D0,%C0 - mov %A0,%A1\;mov %B0,%B1\;clr %C0\;sbrc %B0,7\;com %C0\;mov %D0,%C0 - movw %A0,%A1\;clr %C0\;sbrc %B0,7\;com %C0\;mov %D0,%C0" - [(set_attr "length" "4,6,5") - (set_attr "isa" "*,mov,movw") + { + return avr_out_sign_extend (insn, operands, NULL); + } + [(set_attr "length" "4,6") + (set_attr "adjust_len" "sext") (set_attr "cc" "set_n")]) (define_insn "extendpsisi2" [(set (match_operand:SI 0 "register_operand" "=r") (sign_extend:SI (match_operand:PSI 1 "combine_pseudo_register_operand" "0")))] "" - "clr %D0\;sbrc %C0,7\;com %D0" + { + return avr_out_sign_extend (insn, operands, NULL); + } [(set_attr "length" "3") + (set_attr "adjust_len" "sext") (set_attr "cc" "set_n")]) ;; xx<---x xx<---x xx<---x xx<---x xx<---x xx<---x xx<---x xx<---x xx<---x