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.
It adds new tests and passes without regression.
Ok for trunk?
Johann
--
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-u16.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.
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-u16.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 --git a/gcc/config/avr/avr.cc b/gcc/config/avr/avr.cc
index 8fab896b70f..725e47c2678 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 d0d78ba818a..04d838ef8a7 100644
--- a/gcc/config/avr/avr.md
+++ b/gcc/config/avr/avr.md
@@ -5147,9 +5147,9 @@ (define_insn "*ashl<mode>3"
(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 @@ (define_insn_and_split "ashl<mode>3"
(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 @@ (define_peephole2
;; "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 @@ (define_insn_and_split "ashl<mode>3"
(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 @@ (define_peephole2
;; "*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 @@ (define_insn_and_split "*ashl<mode>3_const_split"
(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 @@ (define_peephole2
;; "*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 @@ (define_insn_and_split "*ashl<mode>3_const_split"
(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_expand "ashlpsi3"
})
(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 @@ (define_insn_and_split "*ashlpsi3_split"
(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 @@ (define_insn "*ashr<mode>3"
;; "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 @@ (define_insn_and_split "ashrpsi3"
(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 @@ (define_insn "*ashrpsi3"
;; "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 @@ (define_insn_and_split "ashr<mode>3"
(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 @@ (define_peephole2
;; "*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 @@ (define_insn_and_split "*ashr<mode>3_const_split"
(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 @@ (define_peephole2
;; "*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 @@ (define_insn_and_split "*ashr<mode>3_const_split"
(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 00000000000..191c07bd770
--- /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 00000000000..4fd66f3f621
--- /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 00000000000..8c374f0c399
--- /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 00000000000..d279dd1ae33
--- /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 00000000000..80546ef1c87
--- /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 00000000000..45e1b0bab88
--- /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 00000000000..674878e43f3
--- /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 00000000000..f3243dc6d45
--- /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 00000000000..9e358a83d44
--- /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 00000000000..6acdd4e2672
--- /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 00000000000..af55e547632
--- /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 00000000000..e0bbb1e5194
--- /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 00000000000..68305e2b2b6
--- /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 ();
+ }
+ }
+}