https://gcc.gnu.org/g:9f7b323caab2215042df0ab0f4eef251c54128fc
commit r15-5467-g9f7b323caab2215042df0ab0f4eef251c54128fc Author: Georg-Johann Lay <a...@gjlay.de> Date: Mon Nov 18 17:35:33 2024 +0100 AVR: Overhaul shift insns. This patch adds 3-operand alternatives to the shift insns for offsets that are one less than the bit-size of the mode. For example, ashrhi3 can support "r,r,C15" without overhead. Apart from that, the asm out functions for the shifts now use avr_asm_len to print assembly and to track the isnsns' lengths. gcc/ * config/avr/avr.md (ashlhi3, *ashlhi3_const_split, *ashlhi3_const) (*ashlpsi3_split, *ashlpsi3) (ashlsi3, *ashlsi3_const_split, *ashlsi3_const) (ashrhi3, *ashrhi3, ashrpsi3, *ashrpsi3, ashrsi3, *ashrsi3) (*ashrhi3_const_split, *ashrhi3_const, *ashrsi3_const_split, *ashrsi3_const): Add constraint alternatives that allow a 3-operand operation when the shift offset is one less than the mode's bitsize. * config/avr/avr.cc (ashl<mode>3_out, ashr<mode>3_out) (lshr<mode>3_out): Use avr_asm_len for asm_out and length tracking. (ashrhi3_out, ashlhi3_out): Support the new "r,r,C15" alternatives. (ashrsi3_out, ashlsi3_out): Support the new "r,r,C31" alternatives. (avr_out_ashrpsi3, avr_out_ashlpsi3): Support the new "r,r,C23" alternatives. gcc/testsuite/ * gcc.target/avr/torture/test-shift.h: New file. * gcc.target/avr/torture/shift-l-u32.c: New test. * gcc.target/avr/torture/shift-r-u32.c: New test. * gcc.target/avr/torture/shift-r-i32.c: New test. * gcc.target/avr/torture/shift-l-u24.c: New test. * gcc.target/avr/torture/shift-r-u24.c: New test. * gcc.target/avr/torture/shift-r-i24.c: New test. * gcc.target/avr/torture/shift-l-u16.c: New test. * gcc.target/avr/torture/shift-r-u16.c: New test. * gcc.target/avr/torture/shift-r-i16.c: New test. * gcc.target/avr/torture/shift-l-u8.c: New test. * gcc.target/avr/torture/shift-r-u8.c: New test. * gcc.target/avr/torture/shift-r-i8.c: New test. Diff: --- gcc/config/avr/avr.cc | 1531 ++++++++------------ gcc/config/avr/avr.md | 158 +- gcc/testsuite/gcc.target/avr/torture/shift-l-u16.c | 25 + gcc/testsuite/gcc.target/avr/torture/shift-l-u24.c | 25 + gcc/testsuite/gcc.target/avr/torture/shift-l-u32.c | 25 + gcc/testsuite/gcc.target/avr/torture/shift-l-u8.c | 25 + gcc/testsuite/gcc.target/avr/torture/shift-r-i16.c | 25 + gcc/testsuite/gcc.target/avr/torture/shift-r-i24.c | 25 + gcc/testsuite/gcc.target/avr/torture/shift-r-i32.c | 25 + gcc/testsuite/gcc.target/avr/torture/shift-r-i8.c | 25 + gcc/testsuite/gcc.target/avr/torture/shift-r-u16.c | 25 + gcc/testsuite/gcc.target/avr/torture/shift-r-u24.c | 25 + gcc/testsuite/gcc.target/avr/torture/shift-r-u32.c | 25 + gcc/testsuite/gcc.target/avr/torture/shift-r-u8.c | 25 + gcc/testsuite/gcc.target/avr/torture/test-shift.h | 125 ++ 15 files changed, 1142 insertions(+), 972 deletions(-) diff --git a/gcc/config/avr/avr.cc b/gcc/config/avr/avr.cc index 0a9d26af0755..4ad07acd789b 100644 --- a/gcc/config/avr/avr.cc +++ b/gcc/config/avr/avr.cc @@ -6598,7 +6598,9 @@ avr_out_cmp_ext (rtx xop[], rtx_code code, int *plen) available and SCRATCH, otherwise (no scratch available) TEMPL is an assembler template that shifts by one position. - T_LEN is the length of this template. */ + T_LEN is the length of this template. + PLEN != 0: Set *PLEN to the length of the sequence in words. + PLEN == 0: Output instructions. */ void out_shift_with_cnt (const char *templ, rtx_insn *insn, rtx operands[], @@ -6721,96 +6723,59 @@ out_shift_with_cnt (const char *templ, rtx_insn *insn, rtx operands[], /* 8bit shift left ((char)x << i) */ const char * -ashlqi3_out (rtx_insn *insn, rtx operands[], int *len) +ashlqi3_out (rtx_insn *insn, rtx operands[], int *plen) { if (CONST_INT_P (operands[2])) { - int k; + bool ldreg_p = test_hard_reg_class (LD_REGS, operands[0]); + int offs = INTVAL (operands[2]); - if (!len) - len = &k; + if (plen) + *plen = 0; - switch (INTVAL (operands[2])) + if (offs <= 3 + || (offs <= 6 && ! ldreg_p)) + { + for (int i = 0; i < offs; ++i) + avr_asm_len ("lsl %0", operands, plen, 1); + return ""; + } + + switch (offs) { default: - if (INTVAL (operands[2]) < 8) + if (offs < 8) break; - - *len = 1; - return "clr %0"; + return avr_asm_len ("clr %0", operands, plen, 1); case 1: - *len = 1; - return "lsl %0"; - case 2: - *len = 2; - return ("lsl %0" CR_TAB - "lsl %0"); - case 3: - *len = 3; - return ("lsl %0" CR_TAB - "lsl %0" CR_TAB - "lsl %0"); + gcc_unreachable (); case 4: - if (test_hard_reg_class (LD_REGS, operands[0])) - { - *len = 2; - return ("swap %0" CR_TAB - "andi %0,0xf0"); - } - *len = 4; - return ("lsl %0" CR_TAB - "lsl %0" CR_TAB - "lsl %0" CR_TAB - "lsl %0"); - + return avr_asm_len ("swap %0" CR_TAB + "andi %0,0xf0", operands, plen, 2); case 5: - if (test_hard_reg_class (LD_REGS, operands[0])) - { - *len = 3; - return ("swap %0" CR_TAB - "lsl %0" CR_TAB - "andi %0,0xe0"); - } - *len = 5; - return ("lsl %0" CR_TAB - "lsl %0" CR_TAB - "lsl %0" CR_TAB - "lsl %0" CR_TAB - "lsl %0"); - + return avr_asm_len ("swap %0" CR_TAB + "lsl %0" CR_TAB + "andi %0,0xe0", operands, plen, 3); case 6: - if (test_hard_reg_class (LD_REGS, operands[0])) - { - *len = 4; - return ("swap %0" CR_TAB - "lsl %0" CR_TAB - "lsl %0" CR_TAB - "andi %0,0xc0"); - } - *len = 6; - return ("lsl %0" CR_TAB - "lsl %0" CR_TAB - "lsl %0" CR_TAB - "lsl %0" CR_TAB - "lsl %0" CR_TAB - "lsl %0"); - + return avr_asm_len ("swap %0" CR_TAB + "lsl %0" CR_TAB + "lsl %0" CR_TAB + "andi %0,0xc0", operands, plen, 4); case 7: - *len = 3; - return ("bst %1,0" CR_TAB - "clr %0" CR_TAB - "bld %0,7"); + return avr_asm_len ("bst %1,0" CR_TAB + "clr %0" CR_TAB + "bld %0,7", operands, plen, 3); } } else if (CONSTANT_P (operands[2])) fatal_insn ("internal compiler error. Incorrect shift:", insn); out_shift_with_cnt ("lsl %0", - insn, operands, len, 1); + insn, operands, plen, 1); return ""; } @@ -6818,19 +6783,17 @@ ashlqi3_out (rtx_insn *insn, rtx operands[], int *len) /* 16bit shift left ((short)x << i) */ const char * -ashlhi3_out (rtx_insn *insn, rtx operands[], int *len) +ashlhi3_out (rtx_insn *insn, rtx operands[], int *plen) { if (CONST_INT_P (operands[2])) { - int scratch = (GET_CODE (PATTERN (insn)) == PARALLEL - && XVECLEN (PATTERN (insn), 0) == 3 - && REG_P (operands[3])); - int ldi_ok = test_hard_reg_class (LD_REGS, operands[0]); - int k; - int *t = len; + bool scratch = (GET_CODE (PATTERN (insn)) == PARALLEL + && XVECLEN (PATTERN (insn), 0) == 3 + && REG_P (operands[3])); + bool ldi_ok = test_hard_reg_class (LD_REGS, operands[0]); - if (!len) - len = &k; + if (plen) + *plen = 0; switch (INTVAL (operands[2])) { @@ -6838,238 +6801,182 @@ ashlhi3_out (rtx_insn *insn, rtx operands[], int *len) if (INTVAL (operands[2]) < 16) break; - *len = 2; - return ("clr %B0" CR_TAB - "clr %A0"); - + return avr_asm_len ("clr %B0" CR_TAB + "clr %A0", operands, plen, 2); case 4: if (optimize_size && scratch) break; /* 5 */ if (ldi_ok) - { - *len = 6; - return ("swap %A0" CR_TAB - "swap %B0" CR_TAB - "andi %B0,0xf0" CR_TAB - "eor %B0,%A0" CR_TAB - "andi %A0,0xf0" CR_TAB - "eor %B0,%A0"); - } + return avr_asm_len ("swap %A0" CR_TAB + "swap %B0" CR_TAB + "andi %B0,0xf0" CR_TAB + "eor %B0,%A0" CR_TAB + "andi %A0,0xf0" CR_TAB + "eor %B0,%A0", operands, plen, 6); if (scratch) - { - *len = 7; - return ("swap %A0" CR_TAB - "swap %B0" CR_TAB - "ldi %3,0xf0" CR_TAB - "and %B0,%3" CR_TAB - "eor %B0,%A0" CR_TAB - "and %A0,%3" CR_TAB - "eor %B0,%A0"); - } + return avr_asm_len ("swap %A0" CR_TAB + "swap %B0" CR_TAB + "ldi %3,0xf0" CR_TAB + "and %B0,%3" CR_TAB + "eor %B0,%A0" CR_TAB + "and %A0,%3" CR_TAB + "eor %B0,%A0", operands, plen, 7); break; /* optimize_size ? 6 : 8 */ case 5: if (optimize_size) break; /* scratch ? 5 : 6 */ if (ldi_ok) - { - *len = 8; - return ("lsl %A0" CR_TAB - "rol %B0" CR_TAB - "swap %A0" CR_TAB - "swap %B0" CR_TAB - "andi %B0,0xf0" CR_TAB - "eor %B0,%A0" CR_TAB - "andi %A0,0xf0" CR_TAB - "eor %B0,%A0"); - } + return avr_asm_len ("lsl %A0" CR_TAB + "rol %B0" CR_TAB + "swap %A0" CR_TAB + "swap %B0" CR_TAB + "andi %B0,0xf0" CR_TAB + "eor %B0,%A0" CR_TAB + "andi %A0,0xf0" CR_TAB + "eor %B0,%A0", operands, plen, 8); if (scratch) - { - *len = 9; - return ("lsl %A0" CR_TAB - "rol %B0" CR_TAB - "swap %A0" CR_TAB - "swap %B0" CR_TAB - "ldi %3,0xf0" CR_TAB - "and %B0,%3" CR_TAB - "eor %B0,%A0" CR_TAB - "and %A0,%3" CR_TAB - "eor %B0,%A0"); - } + return avr_asm_len ("lsl %A0" CR_TAB + "rol %B0" CR_TAB + "swap %A0" CR_TAB + "swap %B0" CR_TAB + "ldi %3,0xf0" CR_TAB + "and %B0,%3" CR_TAB + "eor %B0,%A0" CR_TAB + "and %A0,%3" CR_TAB + "eor %B0,%A0", operands, plen, 9); break; /* 10 */ case 6: if (optimize_size) break; /* scratch ? 5 : 6 */ - *len = 9; - return ("clr __tmp_reg__" CR_TAB - "lsr %B0" CR_TAB - "ror %A0" CR_TAB - "ror __tmp_reg__" CR_TAB - "lsr %B0" CR_TAB - "ror %A0" CR_TAB - "ror __tmp_reg__" CR_TAB - "mov %B0,%A0" CR_TAB - "mov %A0,__tmp_reg__"); - + return avr_asm_len ("clr __tmp_reg__" CR_TAB + "lsr %B0" CR_TAB + "ror %A0" CR_TAB + "ror __tmp_reg__" CR_TAB + "lsr %B0" CR_TAB + "ror %A0" CR_TAB + "ror __tmp_reg__" CR_TAB + "mov %B0,%A0" CR_TAB + "mov %A0,__tmp_reg__", operands, plen, 9); case 7: - *len = 5; - return ("lsr %B0" CR_TAB - "mov %B0,%A0" CR_TAB - "clr %A0" CR_TAB - "ror %B0" CR_TAB - "ror %A0"); - + return avr_asm_len ("lsr %B0" CR_TAB + "mov %B0,%A0" CR_TAB + "clr %A0" CR_TAB + "ror %B0" CR_TAB + "ror %A0", operands, plen, 5); case 8: - return *len = 2, ("mov %B0,%A1" CR_TAB - "clr %A0"); - + return avr_asm_len ("mov %B0,%A1" CR_TAB + "clr %A0", operands, plen, 2); case 9: - *len = 3; - return ("mov %B0,%A0" CR_TAB - "clr %A0" CR_TAB - "lsl %B0"); - + return avr_asm_len ("mov %B0,%A0" CR_TAB + "clr %A0" CR_TAB + "lsl %B0", operands, plen, 3); case 10: - *len = 4; - return ("mov %B0,%A0" CR_TAB - "clr %A0" CR_TAB - "lsl %B0" CR_TAB - "lsl %B0"); - + return avr_asm_len ("mov %B0,%A0" CR_TAB + "clr %A0" CR_TAB + "lsl %B0" CR_TAB + "lsl %B0", operands, plen, 4); case 11: - *len = 5; - return ("mov %B0,%A0" CR_TAB - "clr %A0" CR_TAB - "lsl %B0" CR_TAB - "lsl %B0" CR_TAB - "lsl %B0"); - + return avr_asm_len ("mov %B0,%A0" CR_TAB + "clr %A0" CR_TAB + "lsl %B0" CR_TAB + "lsl %B0" CR_TAB + "lsl %B0", operands, plen, 5); case 12: if (ldi_ok) - { - *len = 4; - return ("mov %B0,%A0" CR_TAB - "clr %A0" CR_TAB - "swap %B0" CR_TAB - "andi %B0,0xf0"); - } + return avr_asm_len ("mov %B0,%A0" CR_TAB + "clr %A0" CR_TAB + "swap %B0" CR_TAB + "andi %B0,0xf0", operands, plen, 4); if (scratch) - { - *len = 5; - return ("mov %B0,%A0" CR_TAB - "clr %A0" CR_TAB - "swap %B0" CR_TAB - "ldi %3,0xf0" CR_TAB - "and %B0,%3"); - } - *len = 6; - return ("mov %B0,%A0" CR_TAB - "clr %A0" CR_TAB - "lsl %B0" CR_TAB - "lsl %B0" CR_TAB - "lsl %B0" CR_TAB - "lsl %B0"); - + return avr_asm_len ("mov %B0,%A0" CR_TAB + "clr %A0" CR_TAB + "swap %B0" CR_TAB + "ldi %3,0xf0" CR_TAB + "and %B0,%3", operands, plen, 5); + + return avr_asm_len ("mov %B0,%A0" CR_TAB + "clr %A0" CR_TAB + "lsl %B0" CR_TAB + "lsl %B0" CR_TAB + "lsl %B0" CR_TAB + "lsl %B0", operands, plen, 6); case 13: if (ldi_ok) - { - *len = 5; - return ("mov %B0,%A0" CR_TAB - "clr %A0" CR_TAB - "swap %B0" CR_TAB - "lsl %B0" CR_TAB - "andi %B0,0xe0"); - } + return avr_asm_len ("mov %B0,%A0" CR_TAB + "clr %A0" CR_TAB + "swap %B0" CR_TAB + "lsl %B0" CR_TAB + "andi %B0,0xe0", operands, plen, 5); if (AVR_HAVE_MUL && scratch) - { - *len = 5; - return ("ldi %3,0x20" CR_TAB - "mul %A0,%3" CR_TAB - "mov %B0,r0" CR_TAB - "clr %A0" CR_TAB - "clr __zero_reg__"); - } + return avr_asm_len ("ldi %3,0x20" CR_TAB + "mul %A0,%3" CR_TAB + "mov %B0,r0" CR_TAB + "clr %A0" CR_TAB + "clr __zero_reg__", operands, plen, 5); if (optimize_size && scratch) break; /* 5 */ + if (scratch) - { - *len = 6; - return ("mov %B0,%A0" CR_TAB - "clr %A0" CR_TAB - "swap %B0" CR_TAB - "lsl %B0" CR_TAB - "ldi %3,0xe0" CR_TAB - "and %B0,%3"); - } + return avr_asm_len ("mov %B0,%A0" CR_TAB + "clr %A0" CR_TAB + "swap %B0" CR_TAB + "lsl %B0" CR_TAB + "ldi %3,0xe0" CR_TAB + "and %B0,%3", operands, plen, 6); if (AVR_HAVE_MUL) - { - *len = 6; - return ("set" CR_TAB - "bld r1,5" CR_TAB - "mul %A0,r1" CR_TAB - "mov %B0,r0" CR_TAB - "clr %A0" CR_TAB - "clr __zero_reg__"); - } - *len = 7; - return ("mov %B0,%A0" CR_TAB - "clr %A0" CR_TAB - "lsl %B0" CR_TAB - "lsl %B0" CR_TAB - "lsl %B0" CR_TAB - "lsl %B0" CR_TAB - "lsl %B0"); - + return avr_asm_len ("set" CR_TAB + "bld r1,5" CR_TAB + "mul %A0,r1" CR_TAB + "mov %B0,r0" CR_TAB + "clr %A0" CR_TAB + "clr __zero_reg__", operands, plen, 6); + return avr_asm_len ("mov %B0,%A0" CR_TAB + "clr %A0" CR_TAB + "lsl %B0" CR_TAB + "lsl %B0" CR_TAB + "lsl %B0" CR_TAB + "lsl %B0" CR_TAB + "lsl %B0", operands, plen, 7); case 14: if (AVR_HAVE_MUL && ldi_ok) - { - *len = 5; - return ("ldi %B0,0x40" CR_TAB - "mul %A0,%B0" CR_TAB - "mov %B0,r0" CR_TAB - "clr %A0" CR_TAB - "clr __zero_reg__"); - } + return avr_asm_len ("ldi %B0,0x40" CR_TAB + "mul %A0,%B0" CR_TAB + "mov %B0,r0" CR_TAB + "clr %A0" CR_TAB + "clr __zero_reg__", operands, plen, 5); if (AVR_HAVE_MUL && scratch) - { - *len = 5; - return ("ldi %3,0x40" CR_TAB - "mul %A0,%3" CR_TAB - "mov %B0,r0" CR_TAB - "clr %A0" CR_TAB - "clr __zero_reg__"); - } + return avr_asm_len ("ldi %3,0x40" CR_TAB + "mul %A0,%3" CR_TAB + "mov %B0,r0" CR_TAB + "clr %A0" CR_TAB + "clr __zero_reg__", operands, plen, 5); if (optimize_size && ldi_ok) - { - *len = 5; - return ("mov %B0,%A0" CR_TAB - "ldi %A0,6" "\n1:\t" - "lsl %B0" CR_TAB - "dec %A0" CR_TAB - "brne 1b"); - } + return avr_asm_len ("mov %B0,%A0" CR_TAB + "ldi %A0,6" "\n1:\t" + "lsl %B0" CR_TAB + "dec %A0" CR_TAB + "brne 1b", operands, plen, 5); if (optimize_size && scratch) break; /* 5 */ - *len = 6; - return ("clr %B0" CR_TAB - "lsr %A0" CR_TAB - "ror %B0" CR_TAB - "lsr %A0" CR_TAB - "ror %B0" CR_TAB - "clr %A0"); + return avr_asm_len ("clr %B0" CR_TAB + "lsr %A0" CR_TAB + "ror %B0" CR_TAB + "lsr %A0" CR_TAB + "ror %B0" CR_TAB + "clr %A0", operands, plen, 6); case 15: - *len = 4; - return ("clr %B0" CR_TAB - "lsr %A0" CR_TAB - "ror %B0" CR_TAB - "clr %A0"); - } - len = t; + return avr_asm_len ("bst %A1,0" CR_TAB + "clr %A0" CR_TAB + "clr %B0" CR_TAB + "bld %B0,7", operands, plen, 4); + } // switch } + out_shift_with_cnt ("lsl %A0" CR_TAB - "rol %B0", insn, operands, len, 2); + "rol %B0", insn, operands, plen, 2); return ""; } @@ -7084,6 +6991,9 @@ avr_out_ashlpsi3 (rtx_insn *insn, rtx *op, int *plen) if (CONST_INT_P (op[2])) { + int reg0 = REGNO (op[0]); + int reg1 = REGNO (op[1]); + switch (INTVAL (op[2])) { default: @@ -7093,40 +7003,26 @@ avr_out_ashlpsi3 (rtx_insn *insn, rtx *op, int *plen) return avr_asm_len ("clr %A0" CR_TAB "clr %B0" CR_TAB "clr %C0", op, plen, 3); - case 8: - { - int reg0 = REGNO (op[0]); - int reg1 = REGNO (op[1]); - - if (reg0 >= reg1) - return avr_asm_len ("mov %C0,%B1" CR_TAB - "mov %B0,%A1" CR_TAB - "clr %A0", op, plen, 3); - else - return avr_asm_len ("clr %A0" CR_TAB - "mov %B0,%A1" CR_TAB - "mov %C0,%B1", op, plen, 3); - } - + return reg0 >= reg1 + ? avr_asm_len ("mov %C0,%B1" CR_TAB + "mov %B0,%A1" CR_TAB + "clr %A0", op, plen, 3) + : avr_asm_len ("clr %A0" CR_TAB + "mov %B0,%A1" CR_TAB + "mov %C0,%B1", op, plen, 3); case 16: - { - int reg0 = REGNO (op[0]); - int reg1 = REGNO (op[1]); - - if (reg0 + 2 != reg1) - avr_asm_len ("mov %C0,%A1", op, plen, 1); - - return avr_asm_len ("clr %B0" CR_TAB - "clr %A0", op, plen, 2); - } + if (reg0 + 2 != reg1) + avr_asm_len ("mov %C0,%A1", op, plen, 1); + return avr_asm_len ("clr %B0" CR_TAB + "clr %A0", op, plen, 2); case 23: - return avr_asm_len ("clr %C0" CR_TAB - "lsr %A0" CR_TAB - "ror %C0" CR_TAB - "clr %B0" CR_TAB - "clr %A0", op, plen, 5); + return avr_asm_len ("bst %A1,0" CR_TAB + "clr %A0" CR_TAB + "clr %B0" CR_TAB + "clr %C0" CR_TAB + "bld %C0,7", op, plen, 5); } } @@ -7140,15 +7036,15 @@ avr_out_ashlpsi3 (rtx_insn *insn, rtx *op, int *plen) /* 32bit shift left ((long)x << i) */ const char * -ashlsi3_out (rtx_insn *insn, rtx operands[], int *len) +ashlsi3_out (rtx_insn *insn, rtx operands[], int *plen) { if (CONST_INT_P (operands[2])) { - int k; - int *t = len; + int reg0 = true_regnum (operands[0]); + int reg1 = true_regnum (operands[1]); - if (!len) - len = &k; + if (plen) + *plen = 0; switch (INTVAL (operands[2])) { @@ -7156,73 +7052,61 @@ ashlsi3_out (rtx_insn *insn, rtx operands[], int *len) if (INTVAL (operands[2]) < 32) break; - if (AVR_HAVE_MOVW) - return *len = 3, ("clr %D0" CR_TAB - "clr %C0" CR_TAB - "movw %A0,%C0"); - *len = 4; - return ("clr %D0" CR_TAB - "clr %C0" CR_TAB - "clr %B0" CR_TAB - "clr %A0"); - + return AVR_HAVE_MOVW + ? avr_asm_len ("clr %D0" CR_TAB + "clr %C0" CR_TAB + "movw %A0,%C0", operands, plen, 3) + : avr_asm_len ("clr %D0" CR_TAB + "clr %C0" CR_TAB + "clr %B0" CR_TAB + "clr %A0", operands, plen, 4); case 8: - { - int reg0 = true_regnum (operands[0]); - int reg1 = true_regnum (operands[1]); - *len = 4; - if (reg0 >= reg1) - return ("mov %D0,%C1" CR_TAB - "mov %C0,%B1" CR_TAB - "mov %B0,%A1" CR_TAB - "clr %A0"); - else - return ("clr %A0" CR_TAB - "mov %B0,%A1" CR_TAB - "mov %C0,%B1" CR_TAB - "mov %D0,%C1"); - } - + return reg0 >= reg1 + ? avr_asm_len ("mov %D0,%C1" CR_TAB + "mov %C0,%B1" CR_TAB + "mov %B0,%A1" CR_TAB + "clr %A0", operands, plen, 4) + : avr_asm_len ("clr %A0" CR_TAB + "mov %B0,%A1" CR_TAB + "mov %C0,%B1" CR_TAB + "mov %D0,%C1", operands, plen, 4); case 16: - { - int reg0 = true_regnum (operands[0]); - int reg1 = true_regnum (operands[1]); - if (reg0 + 2 == reg1) - return *len = 2, ("clr %B0" CR_TAB - "clr %A0"); - if (AVR_HAVE_MOVW) - return *len = 3, ("movw %C0,%A1" CR_TAB - "clr %B0" CR_TAB - "clr %A0"); - else - return *len = 4, ("mov %C0,%A1" CR_TAB - "mov %D0,%B1" CR_TAB - "clr %B0" CR_TAB - "clr %A0"); - } - + if (reg0 + 2 == reg1) + return avr_asm_len ("clr %B0" CR_TAB + "clr %A0", operands, plen, 2); + return AVR_HAVE_MOVW + ? avr_asm_len ("movw %C0,%A1" CR_TAB + "clr %B0" CR_TAB + "clr %A0", operands, plen, 3) + : avr_asm_len ("mov %C0,%A1" CR_TAB + "mov %D0,%B1" CR_TAB + "clr %B0" CR_TAB + "clr %A0", operands, plen, 4); case 24: - *len = 4; - return ("mov %D0,%A1" CR_TAB - "clr %C0" CR_TAB - "clr %B0" CR_TAB - "clr %A0"); - + return avr_asm_len ("mov %D0,%A1" CR_TAB + "clr %C0" CR_TAB + "clr %B0" CR_TAB + "clr %A0", operands, plen, 4); case 31: - *len = 6; - return ("clr %D0" CR_TAB - "lsr %A0" CR_TAB - "ror %D0" CR_TAB - "clr %C0" CR_TAB - "clr %B0" CR_TAB - "clr %A0"); + return AVR_HAVE_MOVW + ? avr_asm_len ("bst %A1,0" CR_TAB + "clr %A0" CR_TAB + "clr %B0" CR_TAB + "movw %C0,%A0" CR_TAB + "bld %D0,7", operands, plen, 5) + : avr_asm_len ("bst %A1,0" CR_TAB + "clr %A0" CR_TAB + "clr %B0" CR_TAB + "clr %D0" CR_TAB + "clr %C0" CR_TAB + "bld %D0,7", operands, plen, 6); } - len = t; } + out_shift_with_cnt ("lsl %A0" CR_TAB "rol %B0" CR_TAB "rol %C0" CR_TAB - "rol %D0", insn, operands, len, 4); + "rol %D0", insn, operands, plen, 4); return ""; } @@ -7275,19 +7159,17 @@ ashrqi3_out (rtx_insn *insn, rtx operands[], int *plen) /* 16bit arithmetic shift right ((signed short)x >> i) */ const char * -ashrhi3_out (rtx_insn *insn, rtx operands[], int *len) +ashrhi3_out (rtx_insn *insn, rtx operands[], int *plen) { if (CONST_INT_P (operands[2])) { - int scratch = (GET_CODE (PATTERN (insn)) == PARALLEL - && XVECLEN (PATTERN (insn), 0) == 3 - && REG_P (operands[3])); - int ldi_ok = test_hard_reg_class (LD_REGS, operands[0]); - int k; - int *t = len; + bool scratch = (GET_CODE (PATTERN (insn)) == PARALLEL + && XVECLEN (PATTERN (insn), 0) == 3 + && REG_P (operands[3])); + bool ldi_ok = test_hard_reg_class (LD_REGS, operands[0]); - if (!len) - len = &k; + if (plen) + *plen = 0; switch (INTVAL (operands[2])) { @@ -7299,125 +7181,99 @@ ashrhi3_out (rtx_insn *insn, rtx operands[], int *len) case 6: if (optimize_size) break; /* scratch ? 5 : 6 */ - *len = 8; - return ("mov __tmp_reg__,%A0" CR_TAB - "mov %A0,%B0" CR_TAB - "lsl __tmp_reg__" CR_TAB - "rol %A0" CR_TAB - "sbc %B0,%B0" CR_TAB - "lsl __tmp_reg__" CR_TAB - "rol %A0" CR_TAB - "rol %B0"); - + return avr_asm_len ("mov __tmp_reg__,%A0" CR_TAB + "mov %A0,%B0" CR_TAB + "lsl __tmp_reg__" CR_TAB + "rol %A0" CR_TAB + "sbc %B0,%B0" CR_TAB + "lsl __tmp_reg__" CR_TAB + "rol %A0" CR_TAB + "rol %B0", operands, plen, 8); case 7: - *len = 4; - return ("lsl %A0" CR_TAB - "mov %A0,%B0" CR_TAB - "rol %A0" CR_TAB - "sbc %B0,%B0"); - + return avr_asm_len ("lsl %A0" CR_TAB + "mov %A0,%B0" CR_TAB + "rol %A0" CR_TAB + "sbc %B0,%B0", operands, plen, 4); case 8: { int reg0 = true_regnum (operands[0]); int reg1 = true_regnum (operands[1]); - if (reg0 == reg1) - return *len = 3, ("mov %A0,%B0" CR_TAB - "lsl %B0" CR_TAB - "sbc %B0,%B0"); - else - return *len = 4, ("mov %A0,%B1" CR_TAB - "clr %B0" CR_TAB - "sbrc %A0,7" CR_TAB - "dec %B0"); + return reg0 == reg1 + ? avr_asm_len ("mov %A0,%B0" CR_TAB + "lsl %B0" CR_TAB + "sbc %B0,%B0", operands, plen, 3) + : avr_asm_len ("mov %A0,%B1" CR_TAB + "clr %B0" CR_TAB + "sbrc %A0,7" CR_TAB + "dec %B0", operands, plen, 4); } case 9: - *len = 4; - return ("mov %A0,%B0" CR_TAB - "lsl %B0" CR_TAB - "sbc %B0,%B0" CR_TAB - "asr %A0"); - + return avr_asm_len ("mov %A0,%B0" CR_TAB + "lsl %B0" CR_TAB + "sbc %B0,%B0" CR_TAB + "asr %A0", operands, plen, 4); case 10: - *len = 5; - return ("mov %A0,%B0" CR_TAB - "lsl %B0" CR_TAB - "sbc %B0,%B0" CR_TAB - "asr %A0" CR_TAB - "asr %A0"); - + return avr_asm_len ("mov %A0,%B0" CR_TAB + "lsl %B0" CR_TAB + "sbc %B0,%B0" CR_TAB + "asr %A0" CR_TAB + "asr %A0", operands, plen, 5); case 11: if (AVR_HAVE_MUL && ldi_ok) - { - *len = 5; - return ("ldi %A0,0x20" CR_TAB - "muls %B0,%A0" CR_TAB - "mov %A0,r1" CR_TAB - "sbc %B0,%B0" CR_TAB - "clr __zero_reg__"); - } + return avr_asm_len ("ldi %A0,0x20" CR_TAB + "muls %B0,%A0" CR_TAB + "mov %A0,r1" CR_TAB + "sbc %B0,%B0" CR_TAB + "clr __zero_reg__", operands, plen, 5); if (optimize_size && scratch) break; /* 5 */ - *len = 6; - return ("mov %A0,%B0" CR_TAB - "lsl %B0" CR_TAB - "sbc %B0,%B0" CR_TAB - "asr %A0" CR_TAB - "asr %A0" CR_TAB - "asr %A0"); - + return avr_asm_len ("mov %A0,%B0" CR_TAB + "lsl %B0" CR_TAB + "sbc %B0,%B0" CR_TAB + "asr %A0" CR_TAB + "asr %A0" CR_TAB + "asr %A0", operands, plen, 6); case 12: if (AVR_HAVE_MUL && ldi_ok) - { - *len = 5; - return ("ldi %A0,0x10" CR_TAB - "muls %B0,%A0" CR_TAB - "mov %A0,r1" CR_TAB - "sbc %B0,%B0" CR_TAB - "clr __zero_reg__"); - } + return avr_asm_len ("ldi %A0,0x10" CR_TAB + "muls %B0,%A0" CR_TAB + "mov %A0,r1" CR_TAB + "sbc %B0,%B0" CR_TAB + "clr __zero_reg__", operands, plen, 5); if (optimize_size && scratch) break; /* 5 */ - *len = 7; - return ("mov %A0,%B0" CR_TAB - "lsl %B0" CR_TAB - "sbc %B0,%B0" CR_TAB - "asr %A0" CR_TAB - "asr %A0" CR_TAB - "asr %A0" CR_TAB - "asr %A0"); - + return avr_asm_len ("mov %A0,%B0" CR_TAB + "lsl %B0" CR_TAB + "sbc %B0,%B0" CR_TAB + "asr %A0" CR_TAB + "asr %A0" CR_TAB + "asr %A0" CR_TAB + "asr %A0", operands, plen, 7); case 13: if (AVR_HAVE_MUL && ldi_ok) - { - *len = 5; - return ("ldi %A0,0x08" CR_TAB - "muls %B0,%A0" CR_TAB - "mov %A0,r1" CR_TAB - "sbc %B0,%B0" CR_TAB - "clr __zero_reg__"); - } + return avr_asm_len ("ldi %A0,0x08" CR_TAB + "muls %B0,%A0" CR_TAB + "mov %A0,r1" CR_TAB + "sbc %B0,%B0" CR_TAB + "clr __zero_reg__", operands, plen, 5); if (optimize_size) break; /* scratch ? 5 : 7 */ - *len = 8; - return ("mov %A0,%B0" CR_TAB - "lsl %B0" CR_TAB - "sbc %B0,%B0" CR_TAB - "asr %A0" CR_TAB - "asr %A0" CR_TAB - "asr %A0" CR_TAB - "asr %A0" CR_TAB - "asr %A0"); - + return avr_asm_len ("mov %A0,%B0" CR_TAB + "lsl %B0" CR_TAB + "sbc %B0,%B0" CR_TAB + "asr %A0" CR_TAB + "asr %A0" CR_TAB + "asr %A0" CR_TAB + "asr %A0" CR_TAB + "asr %A0", operands, plen, 8); case 14: - *len = 5; - return ("lsl %B0" CR_TAB - "sbc %A0,%A0" CR_TAB - "lsl %B0" CR_TAB - "mov %B0,%A0" CR_TAB - "rol %A0"); - + return avr_asm_len ("lsl %B0" CR_TAB + "sbc %A0,%A0" CR_TAB + "lsl %B0" CR_TAB + "mov %B0,%A0" CR_TAB + "rol %A0", operands, plen, 5); default: if (INTVAL (operands[2]) < 16) break; @@ -7425,14 +7281,22 @@ ashrhi3_out (rtx_insn *insn, rtx operands[], int *len) /* fall through */ case 15: - return *len = 3, ("lsl %B0" CR_TAB - "sbc %A0,%A0" CR_TAB - "mov %B0,%A0"); - } - len = t; + { + rtx xop[2] = { operands[0], operands[1] }; + if (! reg_unused_after (insn, xop[1])) + { + avr_asm_len ("mov %B0,%B1", xop, plen, 1); + xop[1] = xop[0]; + } + return avr_asm_len ("lsl %B1" CR_TAB + "sbc %A0,%A0" CR_TAB + "mov %B0,%A0", xop, plen, 3); + } + } // switch } + out_shift_with_cnt ("asr %B0" CR_TAB - "ror %A0", insn, operands, len, 2); + "ror %A0", insn, operands, plen, 2); return ""; } @@ -7453,28 +7317,24 @@ avr_out_ashrpsi3 (rtx_insn *insn, rtx *op, int *plen) switch (INTVAL (op[2])) { case 8: - if (dest <= src) - return avr_asm_len ("mov %A0,%B1" CR_TAB - "mov %B0,%C1" CR_TAB - "clr %C0" CR_TAB - "sbrc %B0,7" CR_TAB - "dec %C0", op, plen, 5); - else - return avr_asm_len ("clr %C0" CR_TAB - "sbrc %C1,7" CR_TAB - "dec %C0" CR_TAB - "mov %B0,%C1" CR_TAB - "mov %A0,%B1", op, plen, 5); - + return dest <= src + ? avr_asm_len ("mov %A0,%B1" CR_TAB + "mov %B0,%C1" CR_TAB + "clr %C0" CR_TAB + "sbrc %B0,7" CR_TAB + "dec %C0", op, plen, 5) + : avr_asm_len ("clr %C0" CR_TAB + "sbrc %C1,7" CR_TAB + "dec %C0" CR_TAB + "mov %B0,%C1" CR_TAB + "mov %A0,%B1", op, plen, 5); case 16: if (dest != src + 2) avr_asm_len ("mov %A0,%C1", op, plen, 1); - return avr_asm_len ("clr %B0" CR_TAB "sbrc %A0,7" CR_TAB "com %B0" CR_TAB "mov %C0,%B0", op, plen, 4); - default: if (INTVAL (op[2]) < 24) break; @@ -7482,10 +7342,18 @@ avr_out_ashrpsi3 (rtx_insn *insn, rtx *op, int *plen) /* fall through */ case 23: - return avr_asm_len ("lsl %C0" CR_TAB - "sbc %A0,%A0" CR_TAB - "mov %B0,%A0" CR_TAB - "mov %C0,%A0", op, plen, 4); + { + rtx xop[2] = { op[0], op[1] }; + if (! reg_unused_after (insn, xop[1])) + { + avr_asm_len ("mov %C0,%C1", xop, plen, 1); + xop[1] = xop[0]; + } + return avr_asm_len ("lsl %C1" CR_TAB + "sbc %A0,%A0" CR_TAB + "mov %B0,%A0" CR_TAB + "mov %C0,%A0", xop, plen, 4); + } } /* switch */ } @@ -7499,72 +7367,57 @@ avr_out_ashrpsi3 (rtx_insn *insn, rtx *op, int *plen) /* 32-bit arithmetic shift right ((signed long)x >> i) */ const char * -ashrsi3_out (rtx_insn *insn, rtx operands[], int *len) +ashrsi3_out (rtx_insn *insn, rtx operands[], int *plen) { if (CONST_INT_P (operands[2])) { - int k; - int *t = len; + if (plen) + *plen = 0; - if (!len) - len = &k; + int reg0 = true_regnum (operands[0]); + int reg1 = true_regnum (operands[1]); switch (INTVAL (operands[2])) { case 8: - { - int reg0 = true_regnum (operands[0]); - int reg1 = true_regnum (operands[1]); - *len=6; - if (reg0 <= reg1) - return ("mov %A0,%B1" CR_TAB - "mov %B0,%C1" CR_TAB - "mov %C0,%D1" CR_TAB - "clr %D0" CR_TAB - "sbrc %C0,7" CR_TAB - "dec %D0"); - else - return ("clr %D0" CR_TAB - "sbrc %D1,7" CR_TAB - "dec %D0" CR_TAB - "mov %C0,%D1" CR_TAB - "mov %B0,%C1" CR_TAB - "mov %A0,%B1"); - } - + return reg0 <= reg1 + ? avr_asm_len ("mov %A0,%B1" CR_TAB + "mov %B0,%C1" CR_TAB + "mov %C0,%D1" CR_TAB + "clr %D0" CR_TAB + "sbrc %C0,7" CR_TAB + "dec %D0", operands, plen, 6) + : avr_asm_len ("clr %D0" CR_TAB + "sbrc %D1,7" CR_TAB + "dec %D0" CR_TAB + "mov %C0,%D1" CR_TAB + "mov %B0,%C1" CR_TAB + "mov %A0,%B1", operands, plen, 6); case 16: - { - int reg0 = true_regnum (operands[0]); - int reg1 = true_regnum (operands[1]); - - if (reg0 == reg1 + 2) - return *len = 4, ("clr %D0" CR_TAB + if (reg0 == reg1 + 2) + return avr_asm_len ("clr %D0" CR_TAB "sbrc %B0,7" CR_TAB "com %D0" CR_TAB - "mov %C0,%D0"); - if (AVR_HAVE_MOVW) - return *len = 5, ("movw %A0,%C1" CR_TAB - "clr %D0" CR_TAB - "sbrc %B0,7" CR_TAB - "com %D0" CR_TAB - "mov %C0,%D0"); - else - return *len = 6, ("mov %B0,%D1" CR_TAB - "mov %A0,%C1" CR_TAB - "clr %D0" CR_TAB - "sbrc %B0,7" CR_TAB - "com %D0" CR_TAB - "mov %C0,%D0"); - } - + "mov %C0,%D0", operands, plen, 4); + return AVR_HAVE_MOVW + ? avr_asm_len ("movw %A0,%C1" CR_TAB + "clr %D0" CR_TAB + "sbrc %B0,7" CR_TAB + "com %D0" CR_TAB + "mov %C0,%D0", operands, plen, 5) + : avr_asm_len ("mov %B0,%D1" CR_TAB + "mov %A0,%C1" CR_TAB + "clr %D0" CR_TAB + "sbrc %B0,7" CR_TAB + "com %D0" CR_TAB + "mov %C0,%D0", operands, plen, 6); case 24: - return *len = 6, ("mov %A0,%D1" CR_TAB - "clr %D0" CR_TAB - "sbrc %A0,7" CR_TAB - "com %D0" CR_TAB - "mov %B0,%D0" CR_TAB - "mov %C0,%D0"); - + return avr_asm_len ("mov %A0,%D1" CR_TAB + "clr %D0" CR_TAB + "sbrc %A0,7" CR_TAB + "com %D0" CR_TAB + "mov %B0,%D0" CR_TAB + "mov %C0,%D0", operands, plen, 6); default: if (INTVAL (operands[2]) < 32) break; @@ -7572,377 +7425,287 @@ ashrsi3_out (rtx_insn *insn, rtx operands[], int *len) /* fall through */ case 31: - if (AVR_HAVE_MOVW) - return *len = 4, ("lsl %D0" CR_TAB - "sbc %A0,%A0" CR_TAB - "mov %B0,%A0" CR_TAB - "movw %C0,%A0"); - else - return *len = 5, ("lsl %D0" CR_TAB - "sbc %A0,%A0" CR_TAB - "mov %B0,%A0" CR_TAB - "mov %C0,%A0" CR_TAB - "mov %D0,%A0"); - } - len = t; + { + rtx xop[2] = { operands[0], operands[1] }; + if (! reg_unused_after (insn, xop[1])) + { + avr_asm_len ("mov %D0,%D1", xop, plen, 1); + xop[1] = xop[0]; + } + return AVR_HAVE_MOVW + ? avr_asm_len ("lsl %D1" CR_TAB + "sbc %A0,%A0" CR_TAB + "mov %B0,%A0" CR_TAB + "movw %C0,%A0", xop, plen, 4) + : avr_asm_len ("lsl %D1" CR_TAB + "sbc %A0,%A0" CR_TAB + "mov %B0,%A0" CR_TAB + "mov %C0,%A0" CR_TAB + "mov %D0,%A0", xop, plen, 5); + } + } // switch } + out_shift_with_cnt ("asr %D0" CR_TAB "ror %C0" CR_TAB "ror %B0" CR_TAB - "ror %A0", insn, operands, len, 4); + "ror %A0", insn, operands, plen, 4); return ""; } /* 8-bit logic shift right ((unsigned char)x >> i) */ const char * -lshrqi3_out (rtx_insn *insn, rtx operands[], int *len) +lshrqi3_out (rtx_insn *insn, rtx operands[], int *plen) { if (CONST_INT_P (operands[2])) { - int k; + bool ldreg_p = test_hard_reg_class (LD_REGS, operands[0]); + int offs = INTVAL (operands[2]); - if (!len) - len = &k; + if (plen) + *plen = 0; + + if (offs <= 3 + || (offs <= 6 && ! ldreg_p)) + { + for (int i = 0; i < offs; ++i) + avr_asm_len ("lsr %0", operands, plen, 1); + return ""; + } switch (INTVAL (operands[2])) { default: if (INTVAL (operands[2]) < 8) break; - - *len = 1; - return "clr %0"; + return avr_asm_len ("clr %0", operands, plen, 1); case 1: - *len = 1; - return "lsr %0"; - case 2: - *len = 2; - return ("lsr %0" CR_TAB - "lsr %0"); case 3: - *len = 3; - return ("lsr %0" CR_TAB - "lsr %0" CR_TAB - "lsr %0"); + gcc_unreachable (); case 4: - if (test_hard_reg_class (LD_REGS, operands[0])) - { - *len=2; - return ("swap %0" CR_TAB - "andi %0,0x0f"); - } - *len = 4; - return ("lsr %0" CR_TAB - "lsr %0" CR_TAB - "lsr %0" CR_TAB - "lsr %0"); - + return avr_asm_len ("swap %0" CR_TAB + "andi %0,0x0f", operands, plen, 2); case 5: - if (test_hard_reg_class (LD_REGS, operands[0])) - { - *len = 3; - return ("swap %0" CR_TAB - "lsr %0" CR_TAB - "andi %0,0x7"); - } - *len = 5; - return ("lsr %0" CR_TAB - "lsr %0" CR_TAB - "lsr %0" CR_TAB - "lsr %0" CR_TAB - "lsr %0"); - + return avr_asm_len ("swap %0" CR_TAB + "lsr %0" CR_TAB + "andi %0,0x7", operands, plen, 3); case 6: - if (test_hard_reg_class (LD_REGS, operands[0])) - { - *len = 4; - return ("swap %0" CR_TAB - "lsr %0" CR_TAB - "lsr %0" CR_TAB - "andi %0,0x3"); - } - *len = 6; - return ("lsr %0" CR_TAB - "lsr %0" CR_TAB - "lsr %0" CR_TAB - "lsr %0" CR_TAB - "lsr %0" CR_TAB - "lsr %0"); - + return avr_asm_len ("swap %0" CR_TAB + "lsr %0" CR_TAB + "lsr %0" CR_TAB + "andi %0,0x3", operands, plen, 4); case 7: - *len = 3; - return ("bst %1,7" CR_TAB - "clr %0" CR_TAB - "bld %0,0"); + return avr_asm_len ("bst %1,7" CR_TAB + "clr %0" CR_TAB + "bld %0,0", operands, plen, 3); } } else if (CONSTANT_P (operands[2])) fatal_insn ("internal compiler error. Incorrect shift:", insn); out_shift_with_cnt ("lsr %0", - insn, operands, len, 1); + insn, operands, plen, 1); return ""; } /* 16-bit logic shift right ((unsigned short)x >> i) */ const char * -lshrhi3_out (rtx_insn *insn, rtx operands[], int *len) +lshrhi3_out (rtx_insn *insn, rtx operands[], int *plen) { if (CONST_INT_P (operands[2])) { - int scratch = (GET_CODE (PATTERN (insn)) == PARALLEL - && XVECLEN (PATTERN (insn), 0) == 3 - && REG_P (operands[3])); - int ldi_ok = test_hard_reg_class (LD_REGS, operands[0]); - int k; - int *t = len; + bool scratch = (GET_CODE (PATTERN (insn)) == PARALLEL + && XVECLEN (PATTERN (insn), 0) == 3 + && REG_P (operands[3])); + bool ldi_ok = test_hard_reg_class (LD_REGS, operands[0]); - if (!len) - len = &k; + if (plen) + *plen = 0; switch (INTVAL (operands[2])) { default: if (INTVAL (operands[2]) < 16) break; - - *len = 2; - return ("clr %B0" CR_TAB - "clr %A0"); + return avr_asm_len ("clr %B0" CR_TAB + "clr %A0", operands, plen, 2); case 4: if (optimize_size && scratch) break; /* 5 */ if (ldi_ok) - { - *len = 6; - return ("swap %B0" CR_TAB - "swap %A0" CR_TAB - "andi %A0,0x0f" CR_TAB - "eor %A0,%B0" CR_TAB - "andi %B0,0x0f" CR_TAB - "eor %A0,%B0"); - } + return avr_asm_len ("swap %B0" CR_TAB + "swap %A0" CR_TAB + "andi %A0,0x0f" CR_TAB + "eor %A0,%B0" CR_TAB + "andi %B0,0x0f" CR_TAB + "eor %A0,%B0", operands, plen, 6); if (scratch) - { - *len = 7; - return ("swap %B0" CR_TAB - "swap %A0" CR_TAB - "ldi %3,0x0f" CR_TAB - "and %A0,%3" CR_TAB - "eor %A0,%B0" CR_TAB - "and %B0,%3" CR_TAB - "eor %A0,%B0"); - } + return avr_asm_len ("swap %B0" CR_TAB + "swap %A0" CR_TAB + "ldi %3,0x0f" CR_TAB + "and %A0,%3" CR_TAB + "eor %A0,%B0" CR_TAB + "and %B0,%3" CR_TAB + "eor %A0,%B0", operands, plen, 7); break; /* optimize_size ? 6 : 8 */ case 5: if (optimize_size) break; /* scratch ? 5 : 6 */ if (ldi_ok) - { - *len = 8; - return ("lsr %B0" CR_TAB - "ror %A0" CR_TAB - "swap %B0" CR_TAB - "swap %A0" CR_TAB - "andi %A0,0x0f" CR_TAB - "eor %A0,%B0" CR_TAB - "andi %B0,0x0f" CR_TAB - "eor %A0,%B0"); - } + return avr_asm_len ("lsr %B0" CR_TAB + "ror %A0" CR_TAB + "swap %B0" CR_TAB + "swap %A0" CR_TAB + "andi %A0,0x0f" CR_TAB + "eor %A0,%B0" CR_TAB + "andi %B0,0x0f" CR_TAB + "eor %A0,%B0", operands, plen, 8); if (scratch) - { - *len = 9; - return ("lsr %B0" CR_TAB - "ror %A0" CR_TAB - "swap %B0" CR_TAB - "swap %A0" CR_TAB - "ldi %3,0x0f" CR_TAB - "and %A0,%3" CR_TAB - "eor %A0,%B0" CR_TAB - "and %B0,%3" CR_TAB - "eor %A0,%B0"); - } + return avr_asm_len ("lsr %B0" CR_TAB + "ror %A0" CR_TAB + "swap %B0" CR_TAB + "swap %A0" CR_TAB + "ldi %3,0x0f" CR_TAB + "and %A0,%3" CR_TAB + "eor %A0,%B0" CR_TAB + "and %B0,%3" CR_TAB + "eor %A0,%B0", operands, plen, 9); break; /* 10 */ case 6: if (optimize_size) break; /* scratch ? 5 : 6 */ - *len = 9; - return ("clr __tmp_reg__" CR_TAB - "lsl %A0" CR_TAB - "rol %B0" CR_TAB - "rol __tmp_reg__" CR_TAB - "lsl %A0" CR_TAB - "rol %B0" CR_TAB - "rol __tmp_reg__" CR_TAB - "mov %A0,%B0" CR_TAB - "mov %B0,__tmp_reg__"); - + return avr_asm_len ("clr __tmp_reg__" CR_TAB + "lsl %A0" CR_TAB + "rol %B0" CR_TAB + "rol __tmp_reg__" CR_TAB + "lsl %A0" CR_TAB + "rol %B0" CR_TAB + "rol __tmp_reg__" CR_TAB + "mov %A0,%B0" CR_TAB + "mov %B0,__tmp_reg__", operands, plen, 9); case 7: - *len = 5; - return ("lsl %A0" CR_TAB - "mov %A0,%B0" CR_TAB - "rol %A0" CR_TAB - "sbc %B0,%B0" CR_TAB - "neg %B0"); - + return avr_asm_len ("lsl %A0" CR_TAB + "mov %A0,%B0" CR_TAB + "rol %A0" CR_TAB + "sbc %B0,%B0" CR_TAB + "neg %B0", operands, plen, 5); case 8: - return *len = 2, ("mov %A0,%B1" CR_TAB - "clr %B0"); - + return avr_asm_len ("mov %A0,%B1" CR_TAB + "clr %B0", operands, plen, 2); case 9: - *len = 3; - return ("mov %A0,%B0" CR_TAB - "clr %B0" CR_TAB - "lsr %A0"); - + return avr_asm_len ("mov %A0,%B0" CR_TAB + "clr %B0" CR_TAB + "lsr %A0", operands, plen, 3); case 10: - *len = 4; - return ("mov %A0,%B0" CR_TAB - "clr %B0" CR_TAB - "lsr %A0" CR_TAB - "lsr %A0"); - + return avr_asm_len ("mov %A0,%B0" CR_TAB + "clr %B0" CR_TAB + "lsr %A0" CR_TAB + "lsr %A0", operands, plen, 4); case 11: - *len = 5; - return ("mov %A0,%B0" CR_TAB - "clr %B0" CR_TAB - "lsr %A0" CR_TAB - "lsr %A0" CR_TAB - "lsr %A0"); - + return avr_asm_len ("mov %A0,%B0" CR_TAB + "clr %B0" CR_TAB + "lsr %A0" CR_TAB + "lsr %A0" CR_TAB + "lsr %A0", operands, plen, 5); case 12: if (ldi_ok) - { - *len = 4; - return ("mov %A0,%B0" CR_TAB - "clr %B0" CR_TAB - "swap %A0" CR_TAB - "andi %A0,0x0f"); - } - if (scratch) - { - *len = 5; - return ("mov %A0,%B0" CR_TAB - "clr %B0" CR_TAB - "swap %A0" CR_TAB - "ldi %3,0x0f" CR_TAB - "and %A0,%3"); - } - *len = 6; - return ("mov %A0,%B0" CR_TAB - "clr %B0" CR_TAB - "lsr %A0" CR_TAB - "lsr %A0" CR_TAB - "lsr %A0" CR_TAB - "lsr %A0"); - + return avr_asm_len ("mov %A0,%B0" CR_TAB + "clr %B0" CR_TAB + "swap %A0" CR_TAB + "andi %A0,0x0f", operands, plen, 4); + return scratch + ? avr_asm_len ("mov %A0,%B0" CR_TAB + "clr %B0" CR_TAB + "swap %A0" CR_TAB + "ldi %3,0x0f" CR_TAB + "and %A0,%3", operands, plen, 5) + : avr_asm_len ("mov %A0,%B0" CR_TAB + "clr %B0" CR_TAB + "lsr %A0" CR_TAB + "lsr %A0" CR_TAB + "lsr %A0" CR_TAB + "lsr %A0", operands, plen, 6); case 13: if (ldi_ok) - { - *len = 5; - return ("mov %A0,%B0" CR_TAB - "clr %B0" CR_TAB - "swap %A0" CR_TAB - "lsr %A0" CR_TAB - "andi %A0,0x07"); - } + return avr_asm_len ("mov %A0,%B0" CR_TAB + "clr %B0" CR_TAB + "swap %A0" CR_TAB + "lsr %A0" CR_TAB + "andi %A0,0x07", operands, plen, 5); if (AVR_HAVE_MUL && scratch) - { - *len = 5; - return ("ldi %3,0x08" CR_TAB - "mul %B0,%3" CR_TAB - "mov %A0,r1" CR_TAB - "clr %B0" CR_TAB - "clr __zero_reg__"); - } + return avr_asm_len ("ldi %3,0x08" CR_TAB + "mul %B0,%3" CR_TAB + "mov %A0,r1" CR_TAB + "clr %B0" CR_TAB + "clr __zero_reg__", operands, plen, 5); if (optimize_size && scratch) break; /* 5 */ if (scratch) - { - *len = 6; - return ("mov %A0,%B0" CR_TAB - "clr %B0" CR_TAB - "swap %A0" CR_TAB - "lsr %A0" CR_TAB - "ldi %3,0x07" CR_TAB - "and %A0,%3"); - } - if (AVR_HAVE_MUL) - { - *len = 6; - return ("set" CR_TAB - "bld r1,3" CR_TAB - "mul %B0,r1" CR_TAB - "mov %A0,r1" CR_TAB - "clr %B0" CR_TAB - "clr __zero_reg__"); - } - *len = 7; - return ("mov %A0,%B0" CR_TAB - "clr %B0" CR_TAB - "lsr %A0" CR_TAB - "lsr %A0" CR_TAB - "lsr %A0" CR_TAB - "lsr %A0" CR_TAB - "lsr %A0"); - + return avr_asm_len ("mov %A0,%B0" CR_TAB + "clr %B0" CR_TAB + "swap %A0" CR_TAB + "lsr %A0" CR_TAB + "ldi %3,0x07" CR_TAB + "and %A0,%3", operands, plen, 6); + return AVR_HAVE_MUL + ? avr_asm_len ("set" CR_TAB + "bld r1,3" CR_TAB + "mul %B0,r1" CR_TAB + "mov %A0,r1" CR_TAB + "clr %B0" CR_TAB + "clr __zero_reg__", operands, plen, 6) + : avr_asm_len ("mov %A0,%B0" CR_TAB + "clr %B0" CR_TAB + "lsr %A0" CR_TAB + "lsr %A0" CR_TAB + "lsr %A0" CR_TAB + "lsr %A0" CR_TAB + "lsr %A0", operands, plen, 7); case 14: if (AVR_HAVE_MUL && ldi_ok) - { - *len = 5; - return ("ldi %A0,0x04" CR_TAB - "mul %B0,%A0" CR_TAB - "mov %A0,r1" CR_TAB - "clr %B0" CR_TAB - "clr __zero_reg__"); - } + return avr_asm_len ("ldi %A0,0x04" CR_TAB + "mul %B0,%A0" CR_TAB + "mov %A0,r1" CR_TAB + "clr %B0" CR_TAB + "clr __zero_reg__", operands, plen, 5); if (AVR_HAVE_MUL && scratch) - { - *len = 5; - return ("ldi %3,0x04" CR_TAB - "mul %B0,%3" CR_TAB - "mov %A0,r1" CR_TAB - "clr %B0" CR_TAB - "clr __zero_reg__"); - } + return avr_asm_len ("ldi %3,0x04" CR_TAB + "mul %B0,%3" CR_TAB + "mov %A0,r1" CR_TAB + "clr %B0" CR_TAB + "clr __zero_reg__", operands, plen, 5); if (optimize_size && ldi_ok) - { - *len = 5; - return ("mov %A0,%B0" CR_TAB - "ldi %B0,6" "\n1:\t" - "lsr %A0" CR_TAB - "dec %B0" CR_TAB - "brne 1b"); - } + return avr_asm_len ("mov %A0,%B0" CR_TAB + "ldi %B0,6" "\n1:\t" + "lsr %A0" CR_TAB + "dec %B0" CR_TAB + "brne 1b", operands, plen, 5); if (optimize_size && scratch) break; /* 5 */ - *len = 6; - return ("clr %A0" CR_TAB - "lsl %B0" CR_TAB - "rol %A0" CR_TAB - "lsl %B0" CR_TAB - "rol %A0" CR_TAB - "clr %B0"); - + return avr_asm_len ("clr %A0" CR_TAB + "lsl %B0" CR_TAB + "rol %A0" CR_TAB + "lsl %B0" CR_TAB + "rol %A0" CR_TAB + "clr %B0", operands, plen, 6); case 15: - *len = 4; - return ("bst %B1,7" CR_TAB - "clr %A0" CR_TAB - "clr %B0" CR_TAB - "bld %A0,0"); + return avr_asm_len ("bst %B1,7" CR_TAB + "clr %A0" CR_TAB + "clr %B0" CR_TAB + "bld %A0,0", operands, plen, 4); } - len = t; } + out_shift_with_cnt ("lsr %B0" CR_TAB - "ror %A0", insn, operands, len, 2); + "ror %A0", insn, operands, plen, 2); return ""; } @@ -8004,15 +7767,15 @@ avr_out_lshrpsi3 (rtx_insn *insn, rtx *op, int *plen) /* 32-bit logic shift right ((unsigned int)x >> i) */ const char * -lshrsi3_out (rtx_insn *insn, rtx operands[], int *len) +lshrsi3_out (rtx_insn *insn, rtx operands[], int *plen) { if (CONST_INT_P (operands[2])) { - int k; - int *t = len; + int reg0 = true_regnum (operands[0]); + int reg1 = true_regnum (operands[1]); - if (!len) - len = &k; + if (plen) + *plen = 0; switch (INTVAL (operands[2])) { @@ -8020,79 +7783,61 @@ lshrsi3_out (rtx_insn *insn, rtx operands[], int *len) if (INTVAL (operands[2]) < 32) break; - if (AVR_HAVE_MOVW) - return *len = 3, ("clr %D0" CR_TAB - "clr %C0" CR_TAB - "movw %A0,%C0"); - *len = 4; - return ("clr %D0" CR_TAB - "clr %C0" CR_TAB - "clr %B0" CR_TAB - "clr %A0"); - + return AVR_HAVE_MOVW + ? avr_asm_len ("clr %D0" CR_TAB + "clr %C0" CR_TAB + "movw %A0,%C0", operands, plen, 3) + : avr_asm_len ("clr %D0" CR_TAB + "clr %C0" CR_TAB + "clr %B0" CR_TAB + "clr %A0", operands, plen, 4); case 8: - { - int reg0 = true_regnum (operands[0]); - int reg1 = true_regnum (operands[1]); - *len = 4; - if (reg0 <= reg1) - return ("mov %A0,%B1" CR_TAB - "mov %B0,%C1" CR_TAB - "mov %C0,%D1" CR_TAB - "clr %D0"); - else - return ("clr %D0" CR_TAB - "mov %C0,%D1" CR_TAB - "mov %B0,%C1" CR_TAB - "mov %A0,%B1"); - } - + return reg0 <= reg1 + ? avr_asm_len ("mov %A0,%B1" CR_TAB + "mov %B0,%C1" CR_TAB + "mov %C0,%D1" CR_TAB + "clr %D0", operands, plen, 4) + : avr_asm_len ("clr %D0" CR_TAB + "mov %C0,%D1" CR_TAB + "mov %B0,%C1" CR_TAB + "mov %A0,%B1", operands, plen, 4); case 16: - { - int reg0 = true_regnum (operands[0]); - int reg1 = true_regnum (operands[1]); - - if (reg0 == reg1 + 2) - return *len = 2, ("clr %C0" CR_TAB - "clr %D0"); - if (AVR_HAVE_MOVW) - return *len = 3, ("movw %A0,%C1" CR_TAB - "clr %C0" CR_TAB - "clr %D0"); - else - return *len = 4, ("mov %B0,%D1" CR_TAB - "mov %A0,%C1" CR_TAB - "clr %C0" CR_TAB - "clr %D0"); - } - + if (reg0 == reg1 + 2) + return avr_asm_len ("clr %C0" CR_TAB + "clr %D0", operands, plen, 2); + return AVR_HAVE_MOVW + ? avr_asm_len ("movw %A0,%C1" CR_TAB + "clr %C0" CR_TAB + "clr %D0", operands, plen, 3) + : avr_asm_len ("mov %B0,%D1" CR_TAB + "mov %A0,%C1" CR_TAB + "clr %C0" CR_TAB + "clr %D0", operands, plen, 4); case 24: - return *len = 4, ("mov %A0,%D1" CR_TAB - "clr %B0" CR_TAB - "clr %C0" CR_TAB - "clr %D0"); - + return avr_asm_len ("mov %A0,%D1" CR_TAB + "clr %B0" CR_TAB + "clr %C0" CR_TAB + "clr %D0", operands, plen, 4); case 31: - if (AVR_HAVE_MOVW) - return *len = 5, ("bst %D1,7" CR_TAB - "clr %A0" CR_TAB - "clr %B0" CR_TAB - "movw %C0,%A0" CR_TAB - "bld %A0,0"); - *len = 6; - return ("bst %D1,7" CR_TAB - "clr %A0" CR_TAB - "clr %B0" CR_TAB - "clr %C0" CR_TAB - "clr %D0" CR_TAB - "bld %A0,0"); - } - len = t; + return AVR_HAVE_MOVW + ? avr_asm_len ("bst %D1,7" CR_TAB + "clr %A0" CR_TAB + "clr %B0" CR_TAB + "movw %C0,%A0" CR_TAB + "bld %A0,0", operands, plen, 5) + : avr_asm_len ("bst %D1,7" CR_TAB + "clr %A0" CR_TAB + "clr %B0" CR_TAB + "clr %C0" CR_TAB + "clr %D0" CR_TAB + "bld %A0,0", operands, plen, 6); + } // switch } + out_shift_with_cnt ("lsr %D0" CR_TAB "ror %C0" CR_TAB "ror %B0" CR_TAB - "ror %A0", insn, operands, len, 4); + "ror %A0", insn, operands, plen, 4); return ""; } diff --git a/gcc/config/avr/avr.md b/gcc/config/avr/avr.md index d0d78ba818a0..04d838ef8a72 100644 --- a/gcc/config/avr/avr.md +++ b/gcc/config/avr/avr.md @@ -5147,9 +5147,9 @@ (set_attr "adjust_len" "ashlqi")]) (define_insn_and_split "ashl<mode>3" - [(set (match_operand:ALL2 0 "register_operand" "=r,r,r,r,r,r,r") - (ashift:ALL2 (match_operand:ALL2 1 "register_operand" "0,0,0,r,0,0,0") - (match_operand:QI 2 "nop_general_operand" "r,L,P,O,K,n,Qm")))] + [(set (match_operand:ALL2 0 "register_operand" "=r,r,r,r ,r,r,r") + (ashift:ALL2 (match_operand:ALL2 1 "register_operand" "0,0,0,r ,0,0,0") + (match_operand:QI 2 "nop_general_operand" "r,L,P,O C15,K,n,Qm")))] "" "#" "&& reload_completed" @@ -5159,15 +5159,15 @@ (clobber (reg:CC REG_CC))])]) (define_insn "*ashl<mode>3" - [(set (match_operand:ALL2 0 "register_operand" "=r,r,r,r,r,r,r") - (ashift:ALL2 (match_operand:ALL2 1 "register_operand" "0,0,0,r,0,0,0") - (match_operand:QI 2 "nop_general_operand" "r,L,P,O,K,n,Qm"))) + [(set (match_operand:ALL2 0 "register_operand" "=r,r,r,r ,r,r,r") + (ashift:ALL2 (match_operand:ALL2 1 "register_operand" "0,0,0,r ,0,0,0") + (match_operand:QI 2 "nop_general_operand" "r,L,P,O C15,K,n,Qm"))) (clobber (reg:CC REG_CC))] "reload_completed" { return ashlhi3_out (insn, operands, NULL); } - [(set_attr "length" "6,0,2,2,4,10,10") + [(set_attr "length" "6,0,2,3,4,10,10") (set_attr "adjust_len" "ashlhi")]) @@ -5257,9 +5257,9 @@ ;; "ashlsq3" "ashlusq3" ;; "ashlsa3" "ashlusa3" (define_insn_and_split "ashl<mode>3" - [(set (match_operand:ALL4 0 "register_operand" "=r,r,r,r,r,r,r") - (ashift:ALL4 (match_operand:ALL4 1 "register_operand" "0,0,0,r,0,0,0") - (match_operand:QI 2 "nop_general_operand" "r,L,P,O,K,n,Qm")))] + [(set (match_operand:ALL4 0 "register_operand" "=r,r,r,r ,r,r,r") + (ashift:ALL4 (match_operand:ALL4 1 "register_operand" "0,0,0,r ,0,0,0") + (match_operand:QI 2 "nop_general_operand" "r,L,P,O C31,K,n,Qm")))] "" "#" "&& reload_completed" @@ -5269,15 +5269,15 @@ (clobber (reg:CC REG_CC))])]) (define_insn "*ashl<mode>3" - [(set (match_operand:ALL4 0 "register_operand" "=r,r,r,r,r,r,r") - (ashift:ALL4 (match_operand:ALL4 1 "register_operand" "0,0,0,r,0,0,0") - (match_operand:QI 2 "nop_general_operand" "r,L,P,O,K,n,Qm"))) + [(set (match_operand:ALL4 0 "register_operand" "=r,r,r,r ,r,r,r") + (ashift:ALL4 (match_operand:ALL4 1 "register_operand" "0,0,0,r ,0,0,0") + (match_operand:QI 2 "nop_general_operand" "r,L,P,O C31,K,n,Qm"))) (clobber (reg:CC REG_CC))] "reload_completed" { return ashlsi3_out (insn, operands, NULL); } - [(set_attr "length" "8,0,4,4,8,10,12") + [(set_attr "length" "8,0,4,5,8,10,12") (set_attr "adjust_len" "ashlsi")]) ;; Optimize if a scratch register from LD_REGS happens to be available. @@ -5354,10 +5354,10 @@ ;; "*ashlhq3_const" "*ashluhq3_const" ;; "*ashlha3_const" "*ashluha3_const" (define_insn_and_split "*ashl<mode>3_const_split" - [(set (match_operand:ALL2 0 "register_operand" "=r,r,r,r,r") - (ashift:ALL2 (match_operand:ALL2 1 "register_operand" "0,0,r,0,0") - (match_operand:QI 2 "const_int_operand" "L,P,O,K,n"))) - (clobber (match_scratch:QI 3 "=X,X,X,X,&d"))] + [(set (match_operand:ALL2 0 "register_operand" "=r,r,r ,r,r") + (ashift:ALL2 (match_operand:ALL2 1 "register_operand" "0,0,r ,0,0") + (match_operand:QI 2 "const_int_operand" "L,P,O C15,K,n"))) + (clobber (match_scratch:QI 3 "=X,X,X ,X,&d"))] "reload_completed" "#" "&& reload_completed" @@ -5368,10 +5368,10 @@ (clobber (reg:CC REG_CC))])]) (define_insn "*ashl<mode>3_const" - [(set (match_operand:ALL2 0 "register_operand" "=r,r,r,r,r") - (ashift:ALL2 (match_operand:ALL2 1 "register_operand" "0,0,r,0,0") - (match_operand:QI 2 "const_int_operand" "L,P,O,K,n"))) - (clobber (match_scratch:QI 3 "=X,X,X,X,&d")) + [(set (match_operand:ALL2 0 "register_operand" "=r,r,r ,r,r") + (ashift:ALL2 (match_operand:ALL2 1 "register_operand" "0,0,r ,0,0") + (match_operand:QI 2 "const_int_operand" "L,P,O C15,K,n"))) + (clobber (match_scratch:QI 3 "=X,X,X ,X,&d")) (clobber (reg:CC REG_CC))] "reload_completed" { @@ -5397,10 +5397,10 @@ ;; "*ashlsq3_const" "*ashlusq3_const" ;; "*ashlsa3_const" "*ashlusa3_const" (define_insn_and_split "*ashl<mode>3_const_split" - [(set (match_operand:ALL4 0 "register_operand" "=r,r,r,r") - (ashift:ALL4 (match_operand:ALL4 1 "register_operand" "0,0,r,0") - (match_operand:QI 2 "const_int_operand" "L,P,O,n"))) - (clobber (match_scratch:QI 3 "=X,X,X,&d"))] + [(set (match_operand:ALL4 0 "register_operand" "=r,r,r ,r") + (ashift:ALL4 (match_operand:ALL4 1 "register_operand" "0,0,r ,0") + (match_operand:QI 2 "const_int_operand" "L,P,O C31,n"))) + (clobber (match_scratch:QI 3 "=X,X,X ,&d"))] "reload_completed" "#" "&& reload_completed" @@ -5411,16 +5411,16 @@ (clobber (reg:CC REG_CC))])]) (define_insn "*ashl<mode>3_const" - [(set (match_operand:ALL4 0 "register_operand" "=r,r,r,r") - (ashift:ALL4 (match_operand:ALL4 1 "register_operand" "0,0,r,0") - (match_operand:QI 2 "const_int_operand" "L,P,O,n"))) - (clobber (match_scratch:QI 3 "=X,X,X,&d")) + [(set (match_operand:ALL4 0 "register_operand" "=r,r,r ,r") + (ashift:ALL4 (match_operand:ALL4 1 "register_operand" "0,0,r ,0") + (match_operand:QI 2 "const_int_operand" "L,P,O C31,n"))) + (clobber (match_scratch:QI 3 "=X,X,X ,&d")) (clobber (reg:CC REG_CC))] "reload_completed" { return ashlsi3_out (insn, operands, NULL); } - [(set_attr "length" "0,4,4,10") + [(set_attr "length" "0,4,5,10") (set_attr "adjust_len" "ashlsi")]) (define_expand "ashlpsi3" @@ -5451,10 +5451,10 @@ }) (define_insn_and_split "*ashlpsi3_split" - [(set (match_operand:PSI 0 "register_operand" "=r,r,r,r") - (ashift:PSI (match_operand:PSI 1 "register_operand" "0,0,r,0") - (match_operand:QI 2 "nonmemory_operand" "r,P,O,n"))) - (clobber (match_scratch:QI 3 "=X,X,X,&d"))] + [(set (match_operand:PSI 0 "register_operand" "=r,r,r ,r") + (ashift:PSI (match_operand:PSI 1 "register_operand" "0,0,r ,0") + (match_operand:QI 2 "nonmemory_operand" "r,P,O C23,n"))) + (clobber (match_scratch:QI 3 "=X,X,X ,&d"))] "" "#" "&& reload_completed" @@ -5465,10 +5465,10 @@ (clobber (reg:CC REG_CC))])]) (define_insn "*ashlpsi3" - [(set (match_operand:PSI 0 "register_operand" "=r,r,r,r") - (ashift:PSI (match_operand:PSI 1 "register_operand" "0,0,r,0") - (match_operand:QI 2 "nonmemory_operand" "r,P,O,n"))) - (clobber (match_scratch:QI 3 "=X,X,X,&d")) + [(set (match_operand:PSI 0 "register_operand" "=r,r,r ,r") + (ashift:PSI (match_operand:PSI 1 "register_operand" "0,0,r ,0") + (match_operand:QI 2 "nonmemory_operand" "r,P,O C23,n"))) + (clobber (match_scratch:QI 3 "=X,X,X ,&d")) (clobber (reg:CC REG_CC))] "reload_completed" { @@ -5509,34 +5509,34 @@ ;; "ashrhq3" "ashruhq3" ;; "ashrha3" "ashruha3" (define_insn_and_split "ashr<mode>3" - [(set (match_operand:ALL2 0 "register_operand" "=r,r,r,r,r,r,r") - (ashiftrt:ALL2 (match_operand:ALL2 1 "register_operand" "0,0,0,r,0,0,0") - (match_operand:QI 2 "nop_general_operand" "r,L,P,O,K,n,Qm")))] + [(set (match_operand:ALL2 0 "register_operand" "=r,r,r,r ,r,r,r") + (ashiftrt:ALL2 (match_operand:ALL2 1 "register_operand" "0,0,0,r ,0,0,0") + (match_operand:QI 2 "nop_general_operand" "r,L,P,O C15,K,n,Qm")))] "" "#" "&& reload_completed" - [(parallel [(set (match_operand:ALL2 0 "register_operand" "=r,r,r,r,r,r,r") - (ashiftrt:ALL2 (match_operand:ALL2 1 "register_operand" "0,0,0,r,0,0,0") - (match_operand:QI 2 "nop_general_operand" "r,L,P,O,K,n,Qm"))) + [(parallel [(set (match_dup 0) + (ashiftrt:ALL2 (match_dup 1) + (match_dup 2))) (clobber (reg:CC REG_CC))])]) (define_insn "*ashr<mode>3" - [(set (match_operand:ALL2 0 "register_operand" "=r,r,r,r,r,r,r") - (ashiftrt:ALL2 (match_operand:ALL2 1 "register_operand" "0,0,0,r,0,0,0") - (match_operand:QI 2 "nop_general_operand" "r,L,P,O,K,n,Qm"))) + [(set (match_operand:ALL2 0 "register_operand" "=r,r,r,r ,r,r,r") + (ashiftrt:ALL2 (match_operand:ALL2 1 "register_operand" "0,0,0,r ,0,0,0") + (match_operand:QI 2 "nop_general_operand" "r,L,P,O C15,K,n,Qm"))) (clobber (reg:CC REG_CC))] "reload_completed" { return ashrhi3_out (insn, operands, NULL); } - [(set_attr "length" "6,0,2,4,4,10,10") + [(set_attr "length" "6,0,2,5,4,10,10") (set_attr "adjust_len" "ashrhi")]) (define_insn_and_split "ashrpsi3" - [(set (match_operand:PSI 0 "register_operand" "=r,r,r,r,r") - (ashiftrt:PSI (match_operand:PSI 1 "register_operand" "0,0,0,r,0") - (match_operand:QI 2 "nonmemory_operand" "r,P,K,O,n"))) - (clobber (match_scratch:QI 3 "=X,X,X,X,&d"))] + [(set (match_operand:PSI 0 "register_operand" "=r,r,r,r ,r") + (ashiftrt:PSI (match_operand:PSI 1 "register_operand" "0,0,0,r ,0") + (match_operand:QI 2 "nonmemory_operand" "r,P,K,O C23,n"))) + (clobber (match_scratch:QI 3 "=X,X,X,X ,&d"))] "" "#" "&& reload_completed" @@ -5547,10 +5547,10 @@ (clobber (reg:CC REG_CC))])]) (define_insn "*ashrpsi3" - [(set (match_operand:PSI 0 "register_operand" "=r,r,r,r,r") - (ashiftrt:PSI (match_operand:PSI 1 "register_operand" "0,0,0,r,0") - (match_operand:QI 2 "nonmemory_operand" "r,P,K,O,n"))) - (clobber (match_scratch:QI 3 "=X,X,X,X,&d")) + [(set (match_operand:PSI 0 "register_operand" "=r,r,r,r ,r") + (ashiftrt:PSI (match_operand:PSI 1 "register_operand" "0,0,0,r ,0") + (match_operand:QI 2 "nonmemory_operand" "r,P,K,O C23,n"))) + (clobber (match_scratch:QI 3 "=X,X,X,X ,&d")) (clobber (reg:CC REG_CC))] "reload_completed" { @@ -5562,9 +5562,9 @@ ;; "ashrsq3" "ashrusq3" ;; "ashrsa3" "ashrusa3" (define_insn_and_split "ashr<mode>3" - [(set (match_operand:ALL4 0 "register_operand" "=r,r,r,r,r,r,r") - (ashiftrt:ALL4 (match_operand:ALL4 1 "register_operand" "0,0,0,r,0,0,0") - (match_operand:QI 2 "nop_general_operand" "r,L,P,O,K,n,Qm")))] + [(set (match_operand:ALL4 0 "register_operand" "=r,r,r,r ,r,r,r") + (ashiftrt:ALL4 (match_operand:ALL4 1 "register_operand" "0,0,0,r ,0,0,0") + (match_operand:QI 2 "nop_general_operand" "r,L,P,O C31,K,n,Qm")))] "" "#" "&& reload_completed" @@ -5574,9 +5574,9 @@ (clobber (reg:CC REG_CC))])]) (define_insn "*ashr<mode>3" - [(set (match_operand:ALL4 0 "register_operand" "=r,r,r,r,r,r,r") - (ashiftrt:ALL4 (match_operand:ALL4 1 "register_operand" "0,0,0,r,0,0,0") - (match_operand:QI 2 "nop_general_operand" "r,L,P,O,K,n,Qm"))) + [(set (match_operand:ALL4 0 "register_operand" "=r,r,r,r ,r,r,r") + (ashiftrt:ALL4 (match_operand:ALL4 1 "register_operand" "0,0,0,r ,0,0,0") + (match_operand:QI 2 "nop_general_operand" "r,L,P,O C31,K,n,Qm"))) (clobber (reg:CC REG_CC))] "reload_completed" { @@ -5604,10 +5604,10 @@ ;; "*ashrhq3_const" "*ashruhq3_const" ;; "*ashrha3_const" "*ashruha3_const" (define_insn_and_split "*ashr<mode>3_const_split" - [(set (match_operand:ALL2 0 "register_operand" "=r,r,r,r,r") - (ashiftrt:ALL2 (match_operand:ALL2 1 "register_operand" "0,0,r,0,0") - (match_operand:QI 2 "const_int_operand" "L,P,O,K,n"))) - (clobber (match_scratch:QI 3 "=X,X,X,X,&d"))] + [(set (match_operand:ALL2 0 "register_operand" "=r,r,r ,r,r") + (ashiftrt:ALL2 (match_operand:ALL2 1 "register_operand" "0,0,r ,0,0") + (match_operand:QI 2 "const_int_operand" "L,P,O C15,K,n"))) + (clobber (match_scratch:QI 3 "=X,X,X ,X,&d"))] "reload_completed" "#" "&& reload_completed" @@ -5618,10 +5618,10 @@ (clobber (reg:CC REG_CC))])]) (define_insn "*ashr<mode>3_const" - [(set (match_operand:ALL2 0 "register_operand" "=r,r,r,r,r") - (ashiftrt:ALL2 (match_operand:ALL2 1 "register_operand" "0,0,r,0,0") - (match_operand:QI 2 "const_int_operand" "L,P,O,K,n"))) - (clobber (match_scratch:QI 3 "=X,X,X,X,&d")) + [(set (match_operand:ALL2 0 "register_operand" "=r,r,r ,r,r") + (ashiftrt:ALL2 (match_operand:ALL2 1 "register_operand" "0,0,r ,0,0") + (match_operand:QI 2 "const_int_operand" "L,P,O C15,K,n"))) + (clobber (match_scratch:QI 3 "=X,X,X ,X,&d")) (clobber (reg:CC REG_CC))] "reload_completed" { @@ -5647,10 +5647,10 @@ ;; "*ashrsq3_const" "*ashrusq3_const" ;; "*ashrsa3_const" "*ashrusa3_const" (define_insn_and_split "*ashr<mode>3_const_split" - [(set (match_operand:ALL4 0 "register_operand" "=r,r,r,r") - (ashiftrt:ALL4 (match_operand:ALL4 1 "register_operand" "0,0,r,0") - (match_operand:QI 2 "const_int_operand" "L,P,O,n"))) - (clobber (match_scratch:QI 3 "=X,X,X,&d"))] + [(set (match_operand:ALL4 0 "register_operand" "=r,r,r ,r") + (ashiftrt:ALL4 (match_operand:ALL4 1 "register_operand" "0,0,r ,0") + (match_operand:QI 2 "const_int_operand" "L,P,O C31,n"))) + (clobber (match_scratch:QI 3 "=X,X,X ,&d"))] "reload_completed" "#" "&& reload_completed" @@ -5661,10 +5661,10 @@ (clobber (reg:CC REG_CC))])]) (define_insn "*ashr<mode>3_const" - [(set (match_operand:ALL4 0 "register_operand" "=r,r,r,r") - (ashiftrt:ALL4 (match_operand:ALL4 1 "register_operand" "0,0,r,0") - (match_operand:QI 2 "const_int_operand" "L,P,O,n"))) - (clobber (match_scratch:QI 3 "=X,X,X,&d")) + [(set (match_operand:ALL4 0 "register_operand" "=r,r,r ,r") + (ashiftrt:ALL4 (match_operand:ALL4 1 "register_operand" "0,0,r ,0") + (match_operand:QI 2 "const_int_operand" "L,P,O C31,n"))) + (clobber (match_scratch:QI 3 "=X,X,X ,&d")) (clobber (reg:CC REG_CC))] "reload_completed" { diff --git a/gcc/testsuite/gcc.target/avr/torture/shift-l-u16.c b/gcc/testsuite/gcc.target/avr/torture/shift-l-u16.c new file mode 100644 index 000000000000..191c07bd7707 --- /dev/null +++ b/gcc/testsuite/gcc.target/avr/torture/shift-l-u16.c @@ -0,0 +1,25 @@ +/* { dg-do run } */ +/* { dg-additional-options { -std=gnu99 -fwrapv } } */ + +#define OP << +#define BITS 16 +typedef __UINT16_TYPE__ T; + +#include "test-shift.h" + +const AS T vals[] = + { + 1, 0x01a2, 0x7f32, 0x7e81, 0x7654 + }; + +int main (void) +{ + for (int i = 0; i < ARRAY_SIZE (vals); ++i) + { + testx (vals[i]); + testx (-vals[i]); + } + testx (0x8000); + + return 0; +} diff --git a/gcc/testsuite/gcc.target/avr/torture/shift-l-u24.c b/gcc/testsuite/gcc.target/avr/torture/shift-l-u24.c new file mode 100644 index 000000000000..4fd66f3f621b --- /dev/null +++ b/gcc/testsuite/gcc.target/avr/torture/shift-l-u24.c @@ -0,0 +1,25 @@ +/* { dg-do run } */ +/* { dg-additional-options { -std=gnu99 -fwrapv } } */ + +#define OP << +#define BITS 24 +typedef __uint24 T; + +#include "test-shift.h" + +const AS T vals[] = + { + 1, 0x01a273, 0x7f324b, 0x7e801, 0x765432 + }; + +int main (void) +{ + for (int i = 0; i < ARRAY_SIZE (vals); ++i) + { + testx (vals[i]); + testx (-vals[i]); + } + testx (0x800000); + + return 0; +} diff --git a/gcc/testsuite/gcc.target/avr/torture/shift-l-u32.c b/gcc/testsuite/gcc.target/avr/torture/shift-l-u32.c new file mode 100644 index 000000000000..8c374f0c3995 --- /dev/null +++ b/gcc/testsuite/gcc.target/avr/torture/shift-l-u32.c @@ -0,0 +1,25 @@ +/* { dg-do run } */ +/* { dg-additional-options { -std=gnu99 -fwrapv } } */ + +#define OP << +#define BITS 32 +typedef __UINT32_TYPE__ T; + +#include "test-shift.h" + +const AS T vals[] = + { + 1, 0x01a273b9, 0x7f324b01, 0x7e80102, 0x76543219 + }; + +int main (void) +{ + for (int i = 0; i < ARRAY_SIZE (vals); ++i) + { + testx (vals[i]); + testx (-vals[i]); + } + testx (0x80000000); + + return 0; +} diff --git a/gcc/testsuite/gcc.target/avr/torture/shift-l-u8.c b/gcc/testsuite/gcc.target/avr/torture/shift-l-u8.c new file mode 100644 index 000000000000..d279dd1ae33e --- /dev/null +++ b/gcc/testsuite/gcc.target/avr/torture/shift-l-u8.c @@ -0,0 +1,25 @@ +/* { dg-do run } */ +/* { dg-additional-options { -std=gnu99 -fwrapv } } */ + +#define OP << +#define BITS 8 +typedef __UINT8_TYPE__ T; + +#include "test-shift.h" + +const AS T vals[] = + { + 1, 0x55, 0x7f, 0x6e, 0x54 + }; + +int main (void) +{ + for (int i = 0; i < ARRAY_SIZE (vals); ++i) + { + testx (vals[i]); + testx (-vals[i]); + } + testx (0x80); + + return 0; +} diff --git a/gcc/testsuite/gcc.target/avr/torture/shift-r-i16.c b/gcc/testsuite/gcc.target/avr/torture/shift-r-i16.c new file mode 100644 index 000000000000..80546ef1c876 --- /dev/null +++ b/gcc/testsuite/gcc.target/avr/torture/shift-r-i16.c @@ -0,0 +1,25 @@ +/* { dg-do run } */ +/* { dg-additional-options { -std=gnu99 -fwrapv } } */ + +#define OP >> +#define BITS 16 +typedef __INT16_TYPE__ T; + +#include "test-shift.h" + +const AS T vals[] = + { + 1, 0x01a2, 0x7f32, 0x7e81, 0x7654 + }; + +int main (void) +{ + for (int i = 0; i < ARRAY_SIZE (vals); ++i) + { + testx (vals[i]); + testx (-vals[i]); + } + testx ((T) 0x8000); + + return 0; +} diff --git a/gcc/testsuite/gcc.target/avr/torture/shift-r-i24.c b/gcc/testsuite/gcc.target/avr/torture/shift-r-i24.c new file mode 100644 index 000000000000..45e1b0bab883 --- /dev/null +++ b/gcc/testsuite/gcc.target/avr/torture/shift-r-i24.c @@ -0,0 +1,25 @@ +/* { dg-do run } */ +/* { dg-additional-options { -std=gnu99 -fwrapv } } */ + +#define OP >> +#define BITS 24 +typedef __int24 T; + +#include "test-shift.h" + +const AS T vals[] = + { + 1, 0x01a273, 0x7f324b, 0x7e801, 0x765432 + }; + +int main (void) +{ + for (int i = 0; i < ARRAY_SIZE (vals); ++i) + { + testx (vals[i]); + testx (-vals[i]); + } + testx ((T) 0x800000); + + return 0; +} diff --git a/gcc/testsuite/gcc.target/avr/torture/shift-r-i32.c b/gcc/testsuite/gcc.target/avr/torture/shift-r-i32.c new file mode 100644 index 000000000000..674878e43f3d --- /dev/null +++ b/gcc/testsuite/gcc.target/avr/torture/shift-r-i32.c @@ -0,0 +1,25 @@ +/* { dg-do run } */ +/* { dg-additional-options { -std=gnu99 -fwrapv } } */ + +#define OP >> +#define BITS 32 +typedef __INT32_TYPE__ T; + +#include "test-shift.h" + +const AS T vals[] = + { + 1, 0x01a273b9, 0x7f324b01, 0x7e80102, 0x76543219 + }; + +int main (void) +{ + for (int i = 0; i < ARRAY_SIZE (vals); ++i) + { + testx (vals[i]); + testx (-vals[i]); + } + testx (0x80000000); + + return 0; +} diff --git a/gcc/testsuite/gcc.target/avr/torture/shift-r-i8.c b/gcc/testsuite/gcc.target/avr/torture/shift-r-i8.c new file mode 100644 index 000000000000..f3243dc6d454 --- /dev/null +++ b/gcc/testsuite/gcc.target/avr/torture/shift-r-i8.c @@ -0,0 +1,25 @@ +/* { dg-do run } */ +/* { dg-additional-options { -std=gnu99 -fwrapv } } */ + +#define OP >> +#define BITS 8 +typedef __INT8_TYPE__ T; + +#include "test-shift.h" + +const AS T vals[] = + { + 1, 0x72, 0x32, 0x6f, 0x76 + }; + +int main (void) +{ + for (int i = 0; i < ARRAY_SIZE (vals); ++i) + { + testx (vals[i]); + testx (-vals[i]); + } + testx ((T) 0x80); + + return 0; +} diff --git a/gcc/testsuite/gcc.target/avr/torture/shift-r-u16.c b/gcc/testsuite/gcc.target/avr/torture/shift-r-u16.c new file mode 100644 index 000000000000..9e358a83d44e --- /dev/null +++ b/gcc/testsuite/gcc.target/avr/torture/shift-r-u16.c @@ -0,0 +1,25 @@ +/* { dg-do run } */ +/* { dg-additional-options { -std=gnu99 -fwrapv } } */ + +#define OP >> +#define BITS 16 +typedef __UINT16_TYPE__ T; + +#include "test-shift.h" + +const AS T vals[] = + { + 1, 0x01a2, 0x7f32, 0x7e81, 0x7654 + }; + +int main (void) +{ + for (int i = 0; i < ARRAY_SIZE (vals); ++i) + { + testx (vals[i]); + testx (-vals[i]); + } + testx (0x8000); + + return 0; +} diff --git a/gcc/testsuite/gcc.target/avr/torture/shift-r-u24.c b/gcc/testsuite/gcc.target/avr/torture/shift-r-u24.c new file mode 100644 index 000000000000..6acdd4e2672d --- /dev/null +++ b/gcc/testsuite/gcc.target/avr/torture/shift-r-u24.c @@ -0,0 +1,25 @@ +/* { dg-do run } */ +/* { dg-additional-options { -std=gnu99 -fwrapv } } */ + +#define OP >> +#define BITS 24 +typedef __uint24 T; + +#include "test-shift.h" + +const AS T vals[] = + { + 1, 0x01a273, 0x7f324b, 0x7e801, 0x765432 + }; + +int main (void) +{ + for (int i = 0; i < ARRAY_SIZE (vals); ++i) + { + testx (vals[i]); + testx (-vals[i]); + } + testx (0x800000); + + return 0; +} diff --git a/gcc/testsuite/gcc.target/avr/torture/shift-r-u32.c b/gcc/testsuite/gcc.target/avr/torture/shift-r-u32.c new file mode 100644 index 000000000000..af55e5476324 --- /dev/null +++ b/gcc/testsuite/gcc.target/avr/torture/shift-r-u32.c @@ -0,0 +1,25 @@ +/* { dg-do run } */ +/* { dg-additional-options { -std=gnu99 -fwrapv } } */ + +#define OP >> +#define BITS 32 +typedef __UINT32_TYPE__ T; + +#include "test-shift.h" + +const AS T vals[] = + { + 1, 0x01a273b9, 0x7f324b01, 0x7e80102, 0x76543219 + }; + +int main (void) +{ + for (int i = 0; i < ARRAY_SIZE (vals); ++i) + { + testx (vals[i]); + testx (-vals[i]); + } + testx (0x80000000); + + return 0; +} diff --git a/gcc/testsuite/gcc.target/avr/torture/shift-r-u8.c b/gcc/testsuite/gcc.target/avr/torture/shift-r-u8.c new file mode 100644 index 000000000000..e0bbb1e5194a --- /dev/null +++ b/gcc/testsuite/gcc.target/avr/torture/shift-r-u8.c @@ -0,0 +1,25 @@ +/* { dg-do run } */ +/* { dg-additional-options { -std=gnu99 -fwrapv } } */ + +#define OP >> +#define BITS 8 +typedef __UINT8_TYPE__ T; + +#include "test-shift.h" + +const AS T vals[] = + { + 1, 0x55, 0x7f, 0x78, 0x54 + }; + +int main (void) +{ + for (int i = 0; i < ARRAY_SIZE (vals); ++i) + { + testx (vals[i]); + testx (-vals[i]); + } + testx (0x80); + + return 0; +} diff --git a/gcc/testsuite/gcc.target/avr/torture/test-shift.h b/gcc/testsuite/gcc.target/avr/torture/test-shift.h new file mode 100644 index 000000000000..68305e2b2b6a --- /dev/null +++ b/gcc/testsuite/gcc.target/avr/torture/test-shift.h @@ -0,0 +1,125 @@ +#define NI __attribute__((noipa)) + +NI +T shiftN (T x, int n) +{ + return x OP n; +} + +#define MK_FUN(N) \ + NI \ + T shift_##N##_r22 (T x) \ + { \ + return x OP N; \ + } \ + \ + NI \ + T shift_##N##_r20 (T x) \ + { \ + register T r20 __asm("20") = x OP N; \ + __asm ("nop ; %0" : "+r" (r20)); \ + return r20; \ + } \ + \ + NI \ + T shift_##N##_r24 (T x) \ + { \ + register T r24 __asm("24") = x OP N; \ + __asm ("nop ; %0" : "+r" (r24)); \ + return r24; \ + } \ + +MK_FUN (1) +MK_FUN (2) +MK_FUN (3) +MK_FUN (4) +MK_FUN (5) +MK_FUN (6) +MK_FUN (7) + +#if BITS > 8 +MK_FUN (8) +MK_FUN (9) +MK_FUN (10) +MK_FUN (11) +MK_FUN (12) +MK_FUN (13) +MK_FUN (14) +MK_FUN (15) +#endif + +#if BITS > 16 +MK_FUN (16) +MK_FUN (17) +MK_FUN (18) +MK_FUN (19) +MK_FUN (20) +MK_FUN (21) +MK_FUN (22) +MK_FUN (23) +#endif + +#if BITS > 24 +MK_FUN (24) +MK_FUN (25) +MK_FUN (26) +MK_FUN (27) +MK_FUN (28) +MK_FUN (29) +MK_FUN (30) +MK_FUN (31) +#endif + +#define ARRAY_SIZE(X) ((int) (sizeof (X) / sizeof (*X))) + +#ifdef __FLASH +#define AS __flash +#else +#define AS /* empty */ +#endif + +typedef T (*fun_t) (T); + +typedef struct +{ + fun_t f[3]; +} fun3_t; + +#define FN(N) { { shift_##N##_r20, shift_##N##_r22, shift_##N##_r24 } } + +const AS fun3_t funcs[] = + { + FN (1), FN (2), FN (3), FN (4), FN (5), FN (6), FN (7), +#if BITS > 8 + FN (8), FN (9), FN (10), FN (11), FN (12), FN (13), FN (14), FN (15), +#endif +#if BITS > 16 + FN (16), FN (17), FN (18), FN (19), FN (20), FN (21), FN (22), FN (23), +#endif +#if BITS > 24 + FN (24), FN (25), FN (26), FN (27), FN (28), FN (29), FN (30), FN (31), +#endif + }; + +void test1 (fun_t fun, T x, int n) +{ + T res = shiftN (x, n); + if (res != fun (x)) + __builtin_abort (); +} + +void testx (T x) +{ + for (int i = 0; i < ARRAY_SIZE (funcs); ++i) + { + const int n = 1 + i; + const T res = shiftN (x, n); + + for (int j = 0; j < ARRAY_SIZE (funcs[i].f); ++j) + { + fun_t f = funcs[i].f[j]; + if (f (x) != res) + __builtin_abort (); + } + } +}