@@ -9840,6 +9840,7 @@
(clobber (reg:CC REG_CC))]
"reload_completed"
{
+ int ldi_ok = test_hard_reg_class (LD_REGS, operands[0]);
int shift = <CODE> == ASHIFT ? INTVAL (operands[2]) : -INTVAL (operands[2]);
int mask = GET_MODE_MASK (<MODE>mode) & INTVAL (operands[3]);
// Position of the output / input bit, respectively.
@@ -9850,6 +9851,217 @@
operands[3] = GEN_INT (obit);
operands[2] = GEN_INT (ibit);
+ /* Special cases requiring MOV to low byte and ANDI. */
+ if ((shift & 7) == 0 && ldi_ok)
+ {
+ if (IN_RANGE (obit, 0, 7))
+ {
+ if (shift == -8)
+ {
+ if (<SIZE> == 2)
+ return "mov %A0,%B1\;andi %A0,lo8(1<<%3)\;clr %B0";
+ if (<SIZE> == 3)
+ return "mov %A0,%B1\;andi %A0,lo8(1<<%3)\;clr %B0\;clr %C0";
+ if (<SIZE> == 4 && !AVR_HAVE_MOVW)
+ return "mov %A0,%B1\;andi %A0,lo8(1<<%3)\;"
+ "clr %B0\;clr %C0\;clr %D0";
+ }
+ else if (shift == -16)
+ {
+ if (<SIZE> == 3)
+ return "mov %A0,%C1\;andi %A0,lo8(1<<%3)\;clr %B0\;clr %C0";
+ if (<SIZE> == 4 && !AVR_HAVE_MOVW)
+ return "mov %A0,%C1\;andi %A0,lo8(1<<%3)\;"
+ "clr %B0\;clr %C0\;clr %D0";
+ }
+ else if (shift == -24 && !AVR_HAVE_MOVW)
+ return "mov %A0,%D1\;andi %A0,lo8(1<<%3)\;"
+ "clr %B0\;clr %C0\;clr %D0";
+ }
+
+ /* Special cases requiring MOV and ANDI. */
+ else if (IN_RANGE (obit, 8, 15))
+ {
+ if (shift == 8)
+ {
+ if (<SIZE> == 2)
+ return "mov %B0,%A1\;andi %B0,lo8(1<<(%3-8))\;clr %A0";
+ if (<SIZE> == 3)
+ return "mov %B0,%A1\;andi %B0,lo8(1<<(%3-8))\;"
+ "clr %A0\;clr %C0";
+ if (<SIZE> == 4 && !AVR_HAVE_MOVW)
+ return "mov %B0,%A1\;andi %B0,lo8(1<<(%3-8))\;"
+ "clr %A0\;clr %C0\;clr %D0";
+ }
+ else if (shift == -8)
+ {
+ if (<SIZE> == 3)
+ return "mov %B0,%C1\;andi %B0,lo8(1<<(%3-8))\;"
+ "clr %A0\;clr %C0";
+ if (<SIZE> == 4 && !AVR_HAVE_MOVW)
+ return "mov %B0,%C1\;andi %B0,lo8(1<<(%3-8))\;"
+ "clr %B0\;clr %C0\;clr %D0";
+ }
+ else if (shift == -16 && !AVR_HAVE_MOVW)
+ return "mov %B0,%D1\;andi %B0,lo8(1<<(%3-8))\;"
+ "clr %A0\;clr %C0\;clr %D0";
+ }
+ else if (IN_RANGE (obit, 16, 23))
+ {
+ if (shift == 16)
+ {
+ if (<SIZE> == 3)
+ return "mov %C0,%A1\;andi %B0,lo8(1<<(%3-16))\;"
+ "clr %A0\;clr %B0";
+ if (<SIZE> == 4 && !AVR_HAVE_MOVW)
+ return "mov %C0,%A1\;andi %B0,lo8(1<<(%3-16))\;"
+ "clr %A0\;clr %B0\;clr %D0";
+ }
+ else if (shift == 8)
+ {
+ if (<SIZE> == 3)
+ return "mov %C0,%B1\;andi %C0,lo8(1<<(%3-16))\;"
+ "clr %A0\;clr %B0";
+ if (<SIZE> == 4 && !AVR_HAVE_MOVW)
+ return "mov %C0,%B1\;andi %C0,lo8(1<<(%3-16))\;"
+ "clr %A0\;clr %C0\;clr %D0";
+ }
+ else if (shift == -8 && !AVR_HAVE_MOVW)
+ return "mov %C0,%D1\;andi %C0,lo8(1<<(%3-16))\;"
+ "clr %A0\;clr %B0\;clr %D0";
+ }
+ else if (IN_RANGE (obit, 24, 31) && !AVR_HAVE_MOVW)
+ {
+ if (shift == 8)
+ return "mov %D0,%C1\;andi %D0,lo8(1<<(%3-24))\;"
+ "clr %A0\;clr %B0\;clr %C0";
+ if (shift == 16)
+ return "mov %D0,%B1\;andi %D0,lo8(1<<(%3-24))\;"
+ "clr %A0\;clr %B0\;clr %C0";
+ if (shift == 24)
+ return "mov %D0,%A1\;andi %D0,lo8(1<<(%3-24))\;"
+ "clr %A0\;clr %B0\;clr %C0";
+ }
+ }
+
+ /* Special cases where the byte is already in place. */
+ if (REGNO (operands[0]) == REGNO (operands[1])
+ && ldi_ok)
+ {
+ if (shift == 1)
+ {
+ if (IN_RANGE (obit, 0, 7))
+ {
+ if (<SIZE> == 1)
+ return "lsl %0\;andi %0,lo8(1<<%3)";
+ if (<SIZE> == 2)
+ return "lsl %A0\;andi %A0,lo8(1<<%3)\;clr %B0";
+ if (<SIZE> == 3)
+ return "lsl %A0\;andi %A0,lo8(1<<%3)\;clr %B0\;clr %C0";
+ if (!AVR_HAVE_MOVW)
+ return "lsl %A0\;andi %A0,lo8(1<<%3)\;"
+ "clr %B0\;clr %C0\;clr %D0";
+ }
+ else if (IN_RANGE (obit, 9, 15))
+ {
+ if (<SIZE> == 2)
+ return "lsl %B0\;andi %B0,lo8(1<<(%3-8))\;clr %A0";
+ if (<SIZE> == 3)
+ return "lsl %B0\;andi %B0,lo8(1<<(%3-8))\;clr %A0\;clr %C0";
+ if (!AVR_HAVE_MOVW)
+ return "lsl %B0\;andi %B0,lo8(1<<(%3-8))\;"
+ "clr %A0\;clr %C0\;clr %D0";
+ }
+ else if (IN_RANGE (obit, 17, 23))
+ {
+ if (<SIZE> == 3)
+ return "lsl %C0\;andi %C0,lo8(1<<(%3-16))\;clr %A0\;clr %B0";
+ if (!AVR_HAVE_MOVW)
+ return "lsl %C0\;andi %C0,lo8(1<<(%3-16))\;"
+ "clr %A0\;clr %B0\;clr %D0";
+ }
+ else if (IN_RANGE (obit, 25, 31) && !AVR_HAVE_MOVW)
+ return "lsl %D0\;andi %D0,lo8(1<<(%3-24))\;"
+ "clr %A0\;clr %B0\;clr %C0";
+ }
+
+ if (shift == -1)
+ {
+ if (IN_RANGE (obit, 0, 6))
+ {
+ if (<SIZE> == 1)
+ return "lsr %0\;andi %0,lo8(1<<%3)";
+ if (<SIZE> == 2)
+ return "lsr %A0\;andi %A0,lo8(1<<%3)\;clr %B0";
+ if (<SIZE> == 3)
+ return "lsr %A0\;andi %A0,lo8(1<<%3)\;clr %B0\;clr %C0";
+ if (!AVR_HAVE_MOVW)
+ return "lsr %A0\;andi %A0,lo8(1<<%3)\;"
+ "clr %B0\;clr %C0\;clr %D0";
+ }
+ else if (IN_RANGE (obit, 8, 14))
+ {
+ if (<SIZE> == 2)
+ return "lsr %B0\;andi %B0,lo8(1<<(%3-8))\;clr %A0";
+ if (<SIZE> == 3)
+ return "lsr %B0\;andi %A0,lo8(1<<(%3-8))\;clr %A0\;clr %C0";
+ if (!AVR_HAVE_MOVW)
+ return "lsr %B0\;andi %B0,lo8(1<<(%3-8))\;"
+ "clr %A0\;clr %C0\;clr %D0";
+ }
+ else if (IN_RANGE (obit, 16, 22))
+ {
+ if (<SIZE> == 3)
+ return "lsr %C0\;andi %C0,lo8(1<<(%3-16))\;clr %A0\;clr %B0";
+ if (!AVR_HAVE_MOVW)
+ return "lsr %C0\;andi %C0,lo8(1<<(%3-16))\;"
+ "clr %A0\;clr %B0\;clr %D0";
+ }
+ else if (IN_RANGE (obit, 24, 30) && !AVR_HAVE_MOVW)
+ return "lsr %D0\;andi %D0,lo8(1<<(%3-24))\;"
+ "clr %A0\;clr %B0\;clr %C0";
+ }
+
+ if ((shift == 4 && IN_RANGE (obit, 4, 7))
+ || (shift == -4 && IN_RANGE (obit, 0, 3)))
+ {
+ if (<SIZE> == 1)
+ return "swap %0\;andi %0,lo8(1<<%3)";
+ if (<SIZE> == 2)
+ return "swap %A0\;andi %A0,lo8(1<<%3)\;clr %B0";
+ if (<SIZE> == 3)
+ return "swap %A0\;andi %A0,lo8(1<<%3)\;clr %B0\;clr %C0";
+ if (!AVR_HAVE_MOVW)
+ return "swap %A0\;andi %A0,lo8(1<<%3)\;"
+ "clr %B0\;clr %C0\;clr %D0";
+ }
+ if ((shift == 4 && IN_RANGE (obit, 12, 15))
+ || (shift == -4 && IN_RANGE (obit, 8, 11)))
+ {
+ if (<SIZE> == 2)
+ return "swap %B0\;andi %B0,lo8(1<<(%3-8))\;clr %A0";
+ if (<SIZE> == 3)
+ return "swap %B0\;andi %B0,lo8(1<<(%3-8))\;clr %A0\;clr %C0";
+ if (!AVR_HAVE_MOVW)
+ return "swap %B0\;andi %B0,lo8(1<<(%3-8))\;"
+ "clr %A0\;clr %C0\;clr %D0";
+ }
+ if ((shift == 4 && IN_RANGE (obit, 20, 23))
+ || (shift == -4 && IN_RANGE (obit, 16, 19)))
+ {
+ if (<SIZE> == 3)
+ return "swap %C0\;andi %C0,lo8(1<<(%3-16))\;clr %A0\;clr %B0";
+ if (!AVR_HAVE_MOVW)
+ return "swap %C0\;andi %C0,lo8(1<<(%3-16))\;"
+ "clr %A0\;clr %B0\;clr %D0";
+ }
+ if (((shift == 4 && IN_RANGE (obit, 28, 31))
+ || (shift == -4 && IN_RANGE (obit, 24, 27)))
+ && !AVR_HAVE_MOVW)
+ return "swap %D0\;andi %D0,lo8(1<<(%3-24))\;"
+ "clr %A0\;clr %B0\;clr %C0";
+ }
+
if (<SIZE> == 1) return "bst %T1%T2\;clr %0\;" "bld %T0%T3";
if (<SIZE> == 2) return "bst %T1%T2\;clr %A0\;clr %B0\;" "bld %T0%T3";
if (<SIZE> == 3) return "bst %T1%T2\;clr %A0\;clr %B0\;clr %C0\;bld %T0%T3";
new file mode 100644
@@ -0,0 +1,10 @@
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+
+unsigned short foo(unsigned short x)
+{
+ return x & 1;
+}
+
+/* { dg-final { scan-assembler "andi r24,1" } } */
+/* { dg-final { scan-assembler "clr r25" } } */
new file mode 100644
@@ -0,0 +1,11 @@
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+
+unsigned short foo(unsigned short x)
+{
+ return (x >> 1) & 1;
+}
+
+/* { dg-final { scan-assembler "lsr r24" } } */
+/* { dg-final { scan-assembler "andi r24,lo8\\(1<<0\\)" } } */
+/* { dg-final { scan-assembler "clr r25" } } */
new file mode 100644
@@ -0,0 +1,11 @@
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+
+unsigned short foo(unsigned short x)
+{
+ return (x >> 2) & 1;
+}
+
+/* { dg-final { scan-assembler "bst r24,2" } } */
+/* { dg-final { scan-assembler-times "clr r2\\d" 2 } } */
+/* { dg-final { scan-assembler "bld r24,0" } } */
new file mode 100644
@@ -0,0 +1,11 @@
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+
+unsigned short foo(unsigned short x)
+{
+ return (x >> 4) & 1;
+}
+
+/* { dg-final { scan-assembler "swap r24" } } */
+/* { dg-final { scan-assembler "andi r24,lo8\\(1<<0\\)" } } */
+/* { dg-final { scan-assembler "clr r25" } } */
new file mode 100644
@@ -0,0 +1,11 @@
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+
+unsigned short foo(unsigned short x)
+{
+ return (x >> 8) & 1;
+}
+
+/* { dg-final { scan-assembler "mov r24,r25" } } */
+/* { dg-final { scan-assembler "andi r24,1" } } */
+/* { dg-final { scan-assembler "ldi r25,0" } } */
new file mode 100644
@@ -0,0 +1,9 @@
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+
+unsigned char foo(unsigned char x)
+{
+ return x & 1;
+}
+
+/* { dg-final { scan-assembler "andi r24,lo8\\(1\\)" } } */
new file mode 100644
@@ -0,0 +1,11 @@
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+
+unsigned char foo(unsigned char x)
+{
+ return (x>>1) & 1;
+}
+
+/* { dg-final { scan-assembler "lsr r24" } } */
+/* { dg-final { scan-assembler "andi r24,1" } } */
+
new file mode 100644
@@ -0,0 +1,12 @@
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+
+unsigned char foo(unsigned char x)
+{
+ return (x>>2) & 1;
+}
+
+/* { dg-final { scan-assembler "bst r24,2" } } */
+/* { dg-final { scan-assembler "clr r24" } } */
+/* { dg-final { scan-assembler "bld r24,0" } } */
+
new file mode 100644
@@ -0,0 +1,11 @@
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+
+unsigned char foo(unsigned char x)
+{
+ return (x>>4) & 1;
+}
+
+/* { dg-final { scan-assembler "swap r24" } } */
+/* { dg-final { scan-assembler "andi r24,1" } } */
+
new file mode 100644
@@ -0,0 +1,10 @@
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+
+unsigned long foo(unsigned long x)
+{
+ return x & 1;
+}
+
+/* { dg-final { scan-assembler "andi r22,1" } } */
+/* { dg-final { scan-assembler-times "clr r2\\d" 3 } } */
new file mode 100644
@@ -0,0 +1,11 @@
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+
+unsigned long foo(unsigned long x)
+{
+ return (x >> 1) & 1;
+}
+
+/* { dg-final { scan-assembler "lsr r22" } } */
+/* { dg-final { scan-assembler "andi r22,lo8\\(1<<0\\)" } } */
+/* { dg-final { scan-assembler-times "clr r2\\d" 3 } } */
new file mode 100644
@@ -0,0 +1,11 @@
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+
+unsigned long foo(unsigned long x)
+{
+ return (x >> 2) & 1;
+}
+
+/* { dg-final { scan-assembler "bst r22,2" } } */
+/* { dg-final { scan-assembler-times "clr r2\\d" 4 } } */
+/* { dg-final { scan-assembler "bld r22,0" } } */
new file mode 100644
@@ -0,0 +1,11 @@
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+
+unsigned long foo(unsigned long x)
+{
+ return (x >> 4) & 1;
+}
+
+/* { dg-final { scan-assembler "swap r22" } } */
+/* { dg-final { scan-assembler "andi r22,lo8\\(1<<0\\)" } } */
+/* { dg-final { scan-assembler-times "clr r2\\d" 3 } } */
new file mode 100644
@@ -0,0 +1,11 @@
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+
+unsigned long foo(unsigned long x)
+{
+ return (x >> 8) & 1;
+}
+
+/* { dg-final { scan-assembler "mov r22,r23" } } */
+/* { dg-final { scan-assembler "andi r22,lo8\\(1<<0\\)" } } */
+/* { dg-final { scan-assembler-times "clr r2\\d" 3 } } */
new file mode 100644
@@ -0,0 +1,11 @@
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+
+unsigned long foo(unsigned long x)
+{
+ return (x >> 16) & 1;
+}
+
+/* { dg-final { scan-assembler "mov r22,r24" } } */
+/* { dg-final { scan-assembler "andi r22,lo8\\(1<<0\\)" } } */
+/* { dg-final { scan-assembler-times "clr r2\\d" 3 } } */