This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: [rfc] multi-word subreg lowering pass


Am Sonntag, 8. Mai 2005 09:48 schrieb Paul Schlie:
> > From: Richard Henderson <rth@redhat.com>
> > ...
> > The Object is to present the register allocator with something that
> > it has more freedom to work with.  This doesn't achieve that goal.
>
> Thanks, after building HEAD with your patches applied, I think I better
> understand.  However there seem to be a few odd things going on. Which the
> following code attempts to show: (including signed char casts for lowered
> operands even though compiled with unsigned chars, and oddly better code
> for in-lined calls than for identical expressions, and finally if the below
> function zed is defined first, the compile will terminate with a bus
> error):
... I think that it is not very useful to test Richard's patch with the 
present back-end. I think also that at this stage we should not start 
complaining about a a couple of ICEs but rather be grateful that Richard's 
work exists :-).

You'll find enclosed an attachment where I have replaced the present patterns 
for sign- and zero- extension by define_expands and where the shifting 
instructions are largely replaced by expanders as well.

IMO, one could try to use the infrastructure Richard's patch provides as a 
base for a complete re-work of the avr back end. Main remaining 
complications, IMO will be 

1.) Re-using the condition codes for branching
2.) Teaching the mid-end algebra on "add-with-carry" "sub-with-carry" 
"compare-with-carry" operations.
3.) Identifying single-bit-test branches.
4.) Finding a way to continue to use movw as frequently as possible.
5.) Make sure that one could continue to use the addiw operations for the 
pointers.

Most of these issues are somewhat related to condition code use and the 
cc0->CCmode issue.
For 5.) one might consider to distinguish pointers from usual numbers by 
defining Pmode to be PHI instead of HI.
I'd also like to suggest to change the convention for __tmp_reg__ and 
__zero_reg__ so that these refer to r2:r3 instead of r0:r1 . This way, one 
could prevent unnecessary moves within the register file for the results of 
multiplications, avoid all of the permanent clr __zero_reg__ and shorten IRQ 
function prologues.

Yours,

Björn


Btw.: As example code showing the potential you might look at the following 
function. It used to generate a function size of 43 with 3.4.3 and now ends 
up with a length of 16!


#include <inttypes.h>

uint32_t a;
int16_t b;

uint16_t 
dummy (uint8_t x, uint32_t y)
{   a = x;
    b = ((uint16_t) (y >> 24)) | (x << 8); 
    return x | (y << 8);
}

Index: avr.md
===================================================================
RCS file: /cvsroot/gcc/gcc/gcc/config/avr/avr.md,v
retrieving revision 1.51
diff -u -r1.51 avr.md
--- avr.md	13 Mar 2005 10:09:53 -0000	1.51
+++ avr.md	8 May 2005 09:47:33 -0000
@@ -35,8 +35,15 @@
 ;;  ~  Output 'r' if not AVR_MEGA.
 
 ;; UNSPEC usage:
-;;  0  Length of a string, see "strlenhi".
-;;  1  Read from a word address in program memory, see "casesi".
+;;  0   Length of a string, see "strlenhi".
+;;  1   Read from a word address in program memory, see "casesi".
+;;  30  Generate sign byte sequence "clr %0 \; sbrs %1,7 \; com %0" 
+;;      for the sign_extend splitter 
+
+(define_constants 
+  [(UNSP_STRLENHI 0)
+   (UNSP_READ_PMEM 1)
+   (UNSP_GEN_SIGN 30)])
 
 ;; Condition code settings.
 (define_attr "cc" "none,set_czn,set_zn,set_n,compare,clobber"
@@ -478,7 +485,8 @@
     [(set (match_dup 4)
 	  (unspec:HI [(match_operand:BLK 1 "memory_operand" "")
 		      (match_operand:QI 2 "const_int_operand" "")
-		      (match_operand:HI 3 "immediate_operand" "")] 0))
+		      (match_operand:HI 3 "immediate_operand" "")] 
+                     UNSP_STRLENHI))
      (set (match_dup 4) (plus:HI (match_dup 4)
 				 (const_int -1)))
      (set (match_operand:HI 0 "register_operand" "")
@@ -499,7 +507,8 @@
   [(set (match_operand:HI 0 "register_operand" "=e")
 	(unspec:HI [(mem:BLK (match_operand:HI 1 "register_operand" "%0"))
 		    (const_int 0)
-		    (match_operand:HI 2 "immediate_operand" "i")] 0))]
+		    (match_operand:HI 2 "immediate_operand" "i")] 
+                    UNSP_STRLENHI))]
   ""
   "ld __tmp_reg__,%a0+
 	tst __tmp_reg__
@@ -964,73 +973,6 @@
   [(set_attr "length" "1,1")
    (set_attr "cc" "set_zn,set_zn")])
 
-(define_insn "andhi3"
-  [(set (match_operand:HI 0 "register_operand" "=r,d,r")
-	  (and:HI (match_operand:HI 1 "register_operand" "%0,0,0")
-		  (match_operand:HI 2 "nonmemory_operand" "r,i,M")))
-   (clobber (match_scratch:QI 3 "=X,X,&d"))]
-  ""
-  "*{
-  if (which_alternative==0)
-    return (AS2 (and,%A0,%A2) CR_TAB
-	    AS2 (and,%B0,%B2));
-  else if (which_alternative==1)
-    {
-      if (GET_CODE (operands[2]) == CONST_INT)
-        {
-	  int mask = INTVAL (operands[2]);
-	  if ((mask & 0xff) != 0xff)
-	    output_asm_insn (AS2 (andi,%A0,lo8(%2)), operands);
-	  if ((mask & 0xff00) != 0xff00)
-	    output_asm_insn (AS2 (andi,%B0,hi8(%2)), operands);
-	  return \"\";
-        }
-        return (AS2 (andi,%A0,lo8(%2)) CR_TAB
-	        AS2 (andi,%B0,hi8(%2)));
-     }
-  return (AS2 (ldi,%3,lo8(%2)) CR_TAB
-          AS2 (and,%A0,%3)     CR_TAB
-          AS1 (clr,%B0));
-}"
-  [(set_attr "length" "2,2,3")
-   (set_attr "cc" "set_n,clobber,set_n")])
-
-(define_insn "andsi3"
-  [(set (match_operand:SI 0 "register_operand" "=r,d")
-	(and:SI (match_operand:SI 1 "register_operand" "%0,0")
-		(match_operand:SI 2 "nonmemory_operand" "r,i")))]
-  ""
-  "*{
-  if (which_alternative==0)
-    return (AS2 (and, %0,%2)   CR_TAB
-	    AS2 (and, %B0,%B2) CR_TAB
-	    AS2 (and, %C0,%C2) CR_TAB
-	    AS2 (and, %D0,%D2));
-  else if (which_alternative==1)
-    {
-      if (GET_CODE (operands[2]) == CONST_INT)
-        {
-	  HOST_WIDE_INT mask = INTVAL (operands[2]);
-	  if ((mask & 0xff) != 0xff)
-	    output_asm_insn (AS2 (andi,%A0,lo8(%2)), operands);
-	  if ((mask & 0xff00) != 0xff00)
-	    output_asm_insn (AS2 (andi,%B0,hi8(%2)), operands);
-	  if ((mask & 0xff0000L) != 0xff0000L)
-	    output_asm_insn (AS2 (andi,%C0,hlo8(%2)), operands);
-	  if ((mask & 0xff000000L) != 0xff000000L)
-	    output_asm_insn (AS2 (andi,%D0,hhi8(%2)), operands);
-	  return \"\";
-        }
-      return (AS2 (andi, %A0,lo8(%2))  CR_TAB
-              AS2 (andi, %B0,hi8(%2)) CR_TAB
-	      AS2 (andi, %C0,hlo8(%2)) CR_TAB
-	      AS2 (andi, %D0,hhi8(%2)));
-    }
-  return \"bug\";
-}"
-  [(set_attr "length" "4,4")
-   (set_attr "cc" "set_n,set_n")])
-
 ;;|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
 ;; ior
 
@@ -1045,86 +987,6 @@
   [(set_attr "length" "1,1")
    (set_attr "cc" "set_zn,set_zn")])
 
-(define_insn "iorhi3"
-  [(set (match_operand:HI 0 "register_operand" "=r,d")
-	(ior:HI (match_operand:HI 1 "register_operand" "%0,0")
-		(match_operand:HI 2 "nonmemory_operand" "r,i")))]
-  ""
-  "*{
-  if (which_alternative==0)
-    return (AS2 (or,%A0,%A2) CR_TAB
-	    AS2 (or,%B0,%B2));
-  if (GET_CODE (operands[2]) == CONST_INT)
-     {
-	int mask = INTVAL (operands[2]);
-	if (mask & 0xff)
-	  output_asm_insn (AS2 (ori,%A0,lo8(%2)), operands);
-	if (mask & 0xff00)
-	  output_asm_insn (AS2 (ori,%B0,hi8(%2)), operands);
-	return \"\";
-      }
-   return (AS2 (ori,%0,lo8(%2)) CR_TAB
-	   AS2 (ori,%B0,hi8(%2)));
-}"  
-  [(set_attr "length" "2,2")
-   (set_attr "cc" "set_n,clobber")])
-
-(define_insn "*iorhi3_clobber"
-  [(set (match_operand:HI 0 "register_operand" "=r,r")
-	(ior:HI (match_operand:HI 1 "register_operand" "%0,0")
-		(match_operand:HI 2 "immediate_operand" "M,i")))
-   (clobber (match_scratch:QI 3 "=&d,&d"))]
-  ""
-  "@
-	ldi %3,lo8(%2)\;or %A0,%3
-	ldi %3,lo8(%2)\;or %A0,%3\;ldi %3,hi8(%2)\;or %B0,%3"
-  [(set_attr "length" "2,4")
-   (set_attr "cc" "clobber,set_n")])
-
-(define_insn "iorsi3"
-  [(set (match_operand:SI 0 "register_operand"        "=r,d")
-	(ior:SI (match_operand:SI 1 "register_operand" "%0,0")
-		(match_operand:SI 2 "nonmemory_operand" "r,i")))]
-  ""
-  "*{
-  if (which_alternative==0)
-    return (AS2 (or, %0,%2)   CR_TAB
-	    AS2 (or, %B0,%B2) CR_TAB
-	    AS2 (or, %C0,%C2) CR_TAB
-	    AS2 (or, %D0,%D2));
-  if (GET_CODE (operands[2]) == CONST_INT)
-     {
-	HOST_WIDE_INT mask = INTVAL (operands[2]);
-	if (mask & 0xff)
-	  output_asm_insn (AS2 (ori,%A0,lo8(%2)), operands);
-	if (mask & 0xff00)
-	  output_asm_insn (AS2 (ori,%B0,hi8(%2)), operands);
-	if (mask & 0xff0000L)
-	  output_asm_insn (AS2 (ori,%C0,hlo8(%2)), operands);
-	if (mask & 0xff000000L)
-	  output_asm_insn (AS2 (ori,%D0,hhi8(%2)), operands);
-	return \"\";
-      }
-  return (AS2 (ori, %A0,lo8(%2))  CR_TAB
-	  AS2 (ori, %B0,hi8(%2)) CR_TAB
-	  AS2 (ori, %C0,hlo8(%2)) CR_TAB
-	  AS2 (ori, %D0,hhi8(%2)));
-}"
-  [(set_attr "length" "4,4")
-   (set_attr "cc" "set_n,clobber")])
-
-(define_insn "*iorsi3_clobber"
-  [(set (match_operand:SI 0 "register_operand"        "=r,r")
-	(ior:SI (match_operand:SI 1 "register_operand" "%0,0")
-		(match_operand:SI 2 "immediate_operand" "M,i")))
-   (clobber (match_scratch:QI 3 "=&d,&d"))]
-  ""
-  "@
-	ldi %3,lo8(%2)\;or %A0,%3
-	ldi %3,lo8(%2)\;or %A0,%3\;ldi %3,hi8(%2)\;or %B0,%3\;ldi %3,hlo8(%2)\;or %C0,%3\;ldi %3,hhi8(%2)\;or %D0,%3"
-  [(set_attr "length" "2,8")
-   (set_attr "cc" "clobber,set_n")])
-
 ;;^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 ;; xor
 
@@ -1137,28 +999,32 @@
   [(set_attr "length" "1")
    (set_attr "cc" "set_zn")])
 
-(define_insn "xorhi3"
-  [(set (match_operand:HI 0 "register_operand" "=r")
-        (xor:HI (match_operand:HI 1 "register_operand" "%0")
-                (match_operand:HI 2 "register_operand" "r")))]
+(define_expand "xorhi3"
+ [(set (subreg:QI (match_operand:HI 0 "register_operand" "=r") 0)
+       (xor:QI (subreg:QI (match_operand:HI 1 "register_operand" "%0") 0)
+               (subreg:QI (match_operand:HI 2 "register_operand" "r")  0)))
+  (set (subreg:QI (match_dup 0) 1)
+       (xor:QI (subreg:QI (match_dup 1) 1)
+               (subreg:QI (match_dup 2) 1))) ]
   ""
-  "eor %0,%2
-	eor %B0,%B2"
-  [(set_attr "length" "2")
-   (set_attr "cc" "set_n")])
+  "")
 
-(define_insn "xorsi3"
-  [(set (match_operand:SI 0 "register_operand" "=r")
-        (xor:SI (match_operand:SI 1 "register_operand" "%0")
-                (match_operand:SI 2 "register_operand" "r")))]
+(define_expand "xorsi3"
+ [(set (subreg:QI (match_operand:SI 0 "register_operand" "=r") 0)
+       (xor:QI (subreg:QI (match_operand:SI 1 "register_operand" "%0") 0)
+               (subreg:QI (match_operand:SI 2 "register_operand" "r")  0)))
+  (set (subreg:QI (match_dup 0) 1)
+       (xor:QI (subreg:QI (match_dup 1) 1)
+               (subreg:QI (match_dup 2) 1))) 
+  (set (subreg:QI (match_dup 0) 2)
+       (xor:QI (subreg:QI (match_dup 1) 2)
+               (subreg:QI (match_dup 2) 2))) 
+  (set (subreg:QI (match_dup 0) 3)
+       (xor:QI (subreg:QI (match_dup 1) 3)
+               (subreg:QI (match_dup 2) 3)))] 
   ""
-  "eor %0,%2
-	eor %B0,%B2
-	eor %C0,%C2
-	eor %D0,%D2"
-  [(set_attr "length" "4")
-   (set_attr "cc" "set_n")])
-
+  "")
+   
 ;;<< << << << << << << << << << << << << << << << << << << << << << << << << <<
 ;; arithmetic shift left
 
@@ -1171,7 +1037,44 @@
   [(set_attr "length" "5,0,1,2,4,6,9")
    (set_attr "cc" "clobber,none,set_czn,set_czn,set_czn,set_czn,clobber")])
 
-(define_insn "ashlhi3"
+(define_expand "ashlhi3"
+  [(set (match_operand:HI 0 "register_operand"           "r")
+	(ashift:HI (match_operand:HI 1 "register_operand" "r")
+		   (match_operand:QI 2 "nonmemory_operand"  "rI")))]
+  ""
+  "if (GET_CODE (operands[2]) == CONST_INT
+       && REG_P (operands[0]) && REG_P (operands[1]))
+     { int value = INTVAL (operands[2]);
+       if (value <= 0)
+        DONE;
+ 
+       rtx rtx_lsb_source = gen_rtx_SUBREG (QImode,operands[1],0);
+       rtx rtx_msb_source = gen_rtx_SUBREG (QImode,operands[1],1);
+       rtx rtx_lsb_target = gen_rtx_SUBREG (QImode,operands[0],0);
+       rtx rtx_msb_target = gen_rtx_SUBREG (QImode,operands[0],1);
+
+       if (value == 8)
+         {
+           emit_insn (gen_movqi (rtx_msb_target,rtx_lsb_source));
+           emit_insn (gen_movqi (rtx_lsb_target,GEN_INT (0))); 
+           DONE; 
+         } 
+       if (value > 15)
+         { 
+           emit_insn (gen_movhi (operands[0],GEN_INT (0) ));
+           DONE;
+         }
+       if (value > 8)
+         {
+           emit_insn (gen_ashlqi3 (rtx_msb_target,
+                                   rtx_lsb_source, GEN_INT (value - 8))); 
+           emit_insn (gen_movqi (rtx_lsb_target,GEN_INT (0))); 
+           DONE;
+         }
+     }"
+)
+
+(define_insn "*ashlhi3"
   [(set (match_operand:HI 0 "register_operand"           "=r,r,r,r,r,r,r")
 	(ashift:HI (match_operand:HI 1 "register_operand" "0,0,0,r,0,0,0")
 		   (match_operand:QI 2 "general_operand"  "r,L,P,O,K,n,Qm")))]
@@ -1180,7 +1083,70 @@
   [(set_attr "length" "6,0,2,2,4,10,10")
    (set_attr "cc" "clobber,none,set_n,clobber,set_n,clobber,clobber")])
 
-(define_insn "ashlsi3"
+(define_expand "ashlsi3"
+  [(set (match_operand:SI 0 "register_operand"           "r")
+	(ashift:SI (match_operand:SI 1 "register_operand" "r")
+		   (match_operand:QI 2 "nonmemory_operand"  "rI")))]
+  ""
+  "if (GET_CODE (operands[2]) == CONST_INT
+       && REG_P (operands[0]) && REG_P (operands[1]))
+     { int value = INTVAL (operands[2]);
+       if (value <= 0)
+        DONE;
+ 
+       rtx rtx_lsb_source    = gen_rtx_SUBREG (QImode,operands[1],0);
+       rtx rtx_mid1sb_source = gen_rtx_SUBREG (QImode,operands[1],1);
+       rtx rtx_mid2sb_source = gen_rtx_SUBREG (QImode,operands[1],2);
+       rtx rtx_msb_source    = gen_rtx_SUBREG (QImode,operands[1],3);
+       rtx rtx_lsb_target    = gen_rtx_SUBREG (QImode,operands[0],0);
+       rtx rtx_mid1sb_target = gen_rtx_SUBREG (QImode,operands[0],1);
+       rtx rtx_mid2sb_target = gen_rtx_SUBREG (QImode,operands[0],2);
+       rtx rtx_msb_target    = gen_rtx_SUBREG (QImode,operands[0],3);
+       
+       if (value == 8)
+         {
+           emit_insn (gen_movqi (rtx_mid1sb_target,rtx_lsb_source));
+           emit_insn (gen_movqi (rtx_mid2sb_target,rtx_mid1sb_source));
+           emit_insn (gen_movqi (rtx_msb_target,rtx_mid2sb_source));
+           emit_insn (gen_movqi (rtx_lsb_target,GEN_INT (0))); 
+           DONE; 
+         } 
+       if (value == 16)
+         {
+           emit_insn (gen_movqi (rtx_mid2sb_target,rtx_lsb_source));
+           emit_insn (gen_movqi (rtx_msb_target,rtx_mid1sb_source));
+           emit_insn (gen_movqi (rtx_mid1sb_target,GEN_INT(0)));
+           emit_insn (gen_movqi (rtx_lsb_target,GEN_INT (0))); 
+
+           DONE; 
+         } 
+       if (value == 24)
+         {
+           emit_insn (gen_movqi (rtx_msb_target,rtx_lsb_source));
+           emit_insn (gen_movqi (rtx_mid1sb_target,GEN_INT(0)));
+           emit_insn (gen_movqi (rtx_lsb_target,GEN_INT (0))); 
+           emit_insn (gen_movqi (rtx_mid2sb_target,GEN_INT (0)));
+           DONE; 
+         } 
+       if (value > 31)
+         { 
+           emit_insn (gen_movsi (operands[0],GEN_INT (0) ));
+           DONE;
+         }
+	 
+       if (value > 24)
+         {
+           emit_insn (gen_ashlqi3 (rtx_msb_target,
+                                   rtx_lsb_source, GEN_INT (value - 24))); 
+           emit_insn (gen_movqi (rtx_mid2sb_target,GEN_INT (0))); 
+           emit_insn (gen_movqi (rtx_mid1sb_target,GEN_INT(0)));
+           emit_insn (gen_movqi (rtx_lsb_target,GEN_INT (0))); 
+           DONE;
+         }
+     }"
+)   
+   
+(define_insn "*ashlsi3_insn"
   [(set (match_operand:SI 0 "register_operand"           "=r,r,r,r,r,r,r")
 	(ashift:SI (match_operand:SI 1 "register_operand" "0,0,0,r,0,0,0")
 		   (match_operand:QI 2 "general_operand"  "r,L,P,O,K,n,Qm")))]
@@ -1245,7 +1211,45 @@
   [(set_attr "length" "5,0,1,2,5,9")
    (set_attr "cc" "clobber,none,clobber,clobber,clobber,clobber")])
 
-(define_insn "ashrhi3"
+(define_expand "ashrhi3"
+  [(set (match_operand:HI 0 "register_operand"           "r")
+	(ashiftrt:HI (match_operand:HI 1 "register_operand" "r")
+		     (match_operand:QI 2 "nonmemory_operand"  "rI")))]
+  ""
+  "if (GET_CODE (operands[2]) == CONST_INT
+       && REG_P (operands[0]) && REG_P (operands[1]))
+     { int value = INTVAL (operands[2]);
+       if (value <= 0)
+        DONE;
+ 
+       rtx rtx_lsb_source = gen_rtx_SUBREG (QImode,operands[1],0);
+       rtx rtx_msb_source = gen_rtx_SUBREG (QImode,operands[1],1);
+       rtx rtx_lsb_target = gen_rtx_SUBREG (QImode,operands[0],0);
+       rtx rtx_msb_target = gen_rtx_SUBREG (QImode,operands[0],1);
+
+       if (value == 8)
+         {
+           emit_insn (gen_movqi (rtx_lsb_target,rtx_msb_source));
+           emit_insn (gen_generate_extension_byte(rtx_msb_target,rtx_lsb_target)); 
+           DONE; 
+         } 
+       if (value > 15)
+         { 
+           emit_insn (gen_generate_extension_byte(rtx_lsb_target,rtx_msb_source)); 
+           emit_insn (gen_movqi (rtx_msb_target,rtx_lsb_target));
+           DONE;
+         }
+       if (value > 8)
+         {
+           emit_insn (gen_ashrqi3 (rtx_lsb_target,
+                                   rtx_msb_source, GEN_INT (value - 8))); 
+           emit_insn (gen_generate_extension_byte(rtx_msb_target,rtx_lsb_target)); 
+           DONE;
+         }
+     }"
+)
+  
+(define_insn "*ashrhi3"
   [(set (match_operand:HI 0 "register_operand"             "=r,r,r,r,r,r,r")
 	(ashiftrt:HI (match_operand:HI 1 "register_operand" "0,0,0,r,0,0,0")
 		     (match_operand:QI 2 "general_operand"  "r,L,P,O,K,n,Qm")))]
@@ -1254,7 +1258,73 @@
   [(set_attr "length" "6,0,2,4,4,10,10")
    (set_attr "cc" "clobber,none,clobber,set_n,clobber,clobber,clobber")])
 
-(define_insn "ashrsi3"
+(define_expand "ashrsi3"
+  [(set (match_operand:SI 0 "register_operand"           "r")
+	(ashiftrt:SI (match_operand:SI 1 "register_operand" "r")
+		     (match_operand:QI 2 "nonmemory_operand"  "rI")))]
+  ""
+  "if (GET_CODE (operands[2]) == CONST_INT
+       && REG_P (operands[0]) && REG_P (operands[1]))
+     { int value = INTVAL (operands[2]);
+       if (value <= 0)
+        DONE;
+ 
+       rtx rtx_lsb_source    = gen_rtx_SUBREG (QImode,operands[1],0);
+       rtx rtx_mid1sb_source = gen_rtx_SUBREG (QImode,operands[1],1);
+       rtx rtx_mid2sb_source = gen_rtx_SUBREG (QImode,operands[1],2);
+       rtx rtx_msb_source    = gen_rtx_SUBREG (QImode,operands[1],3);
+       rtx rtx_lsb_target    = gen_rtx_SUBREG (QImode,operands[0],0);
+       rtx rtx_mid1sb_target = gen_rtx_SUBREG (QImode,operands[0],1);
+       rtx rtx_mid2sb_target = gen_rtx_SUBREG (QImode,operands[0],2);
+       rtx rtx_msb_target    = gen_rtx_SUBREG (QImode,operands[0],3);
+       
+       if (value == 8)
+         {
+           emit_insn (gen_movqi (rtx_lsb_target,rtx_mid1sb_source)); 
+           emit_insn (gen_movqi (rtx_mid1sb_target,rtx_mid2sb_source)); 
+           emit_insn (gen_movqi (rtx_mid2sb_target,rtx_msb_source));
+           emit_insn (gen_generate_extension_byte(rtx_msb_target,rtx_mid2sb_target)); 
+           DONE; 
+         } 
+       if (value == 16)
+         {
+           emit_insn (gen_movqi (rtx_lsb_target,rtx_mid2sb_source)); 
+           emit_insn (gen_movqi (rtx_mid1sb_target,rtx_msb_source)); 
+           emit_insn (gen_generate_extension_byte(rtx_msb_target,rtx_mid1sb_target)); 
+           emit_insn (gen_movqi (rtx_mid2sb_target,rtx_msb_target));
+           DONE; 
+         } 
+       if (value == 24)
+         {
+           emit_insn (gen_movqi (rtx_lsb_target,rtx_msb_source)); 
+           emit_insn (gen_generate_extension_byte(rtx_msb_target,rtx_lsb_target)); 
+           emit_insn (gen_movqi (rtx_mid1sb_target,rtx_msb_target)); 
+           emit_insn (gen_movqi (rtx_mid2sb_target,rtx_msb_target));	 
+           DONE; 
+         } 
+       if (value > 31)
+         { 
+           emit_insn (gen_generate_extension_byte(rtx_lsb_target,rtx_msb_source)); 
+           emit_insn (gen_movqi (rtx_mid1sb_target,rtx_lsb_target)); 
+           emit_insn (gen_movqi (rtx_mid2sb_target,rtx_lsb_target));	 
+           emit_insn (gen_movqi (rtx_msb_target,rtx_lsb_target));
+	   DONE;
+         }
+	 
+       if (value > 24)
+         {
+           emit_insn (gen_generate_extension_byte(rtx_mid1sb_target,rtx_msb_source)); 
+           emit_insn (gen_ashrqi3 (rtx_lsb_target,
+                                   rtx_msb_source, GEN_INT (value - 24))); 
+           emit_insn (gen_movqi (rtx_mid2sb_target,rtx_mid1sb_target));	 
+           emit_insn (gen_movqi (rtx_msb_target,rtx_mid1sb_target));
+           DONE;
+         }
+     }"
+)   
+
+   
+(define_insn "*ashrsi3"
   [(set (match_operand:SI 0 "register_operand"             "=r,r,r,r,r,r,r")
 	(ashiftrt:SI (match_operand:SI 1 "register_operand" "0,0,0,r,0,0,0")
 		     (match_operand:QI 2 "general_operand"  "r,L,P,O,K,n,Qm")))]
@@ -1319,7 +1389,45 @@
   [(set_attr "length" "5,0,1,2,4,6,9")
    (set_attr "cc" "clobber,none,set_czn,set_czn,set_czn,set_czn,clobber")])
 
-(define_insn "lshrhi3"
+(define_expand "lshrhi3"
+  [(set (match_operand:HI 0 "register_operand"           "r")
+	(lshiftrt:HI (match_operand:HI 1 "register_operand" "r")
+		     (match_operand:QI 2 "nonmemory_operand"  "rI")))]
+  ""
+  "if (GET_CODE (operands[2]) == CONST_INT
+       && REG_P (operands[0]) && REG_P (operands[1]))
+     { int value = INTVAL (operands[2]);
+       if (value <= 0)
+        DONE;
+ 
+       rtx rtx_lsb_source = gen_rtx_SUBREG (QImode,operands[1],0);
+       rtx rtx_msb_source = gen_rtx_SUBREG (QImode,operands[1],1);
+       rtx rtx_lsb_target = gen_rtx_SUBREG (QImode,operands[0],0);
+       rtx rtx_msb_target = gen_rtx_SUBREG (QImode,operands[0],1);
+
+       if (value == 8)
+         {
+           emit_insn (gen_movqi (rtx_lsb_target,rtx_msb_source));
+           emit_insn (gen_movqi (rtx_msb_target,GEN_INT (0))); 
+           DONE; 
+         } 
+       if (value > 15)
+         { 
+           emit_insn (gen_movqi (rtx_lsb_target,GEN_INT (0))); 
+           emit_insn (gen_movqi (rtx_msb_target,rtx_lsb_target));
+           DONE;
+         }
+       if (value > 8)
+         {
+           emit_insn (gen_movqi (rtx_msb_target,GEN_INT (0))); 
+           emit_insn (gen_lshrqi3 (rtx_lsb_target,
+                                   rtx_msb_source, GEN_INT (value - 8))); 
+           DONE;
+         }
+     }"
+)   
+   
+(define_insn "*lshrhi3"
   [(set (match_operand:HI 0 "register_operand"             "=r,r,r,r,r,r,r")
 	(lshiftrt:HI (match_operand:HI 1 "register_operand" "0,0,0,r,0,0,0")
 		     (match_operand:QI 2 "general_operand"  "r,L,P,O,K,n,Qm")))]
@@ -1328,7 +1436,70 @@
   [(set_attr "length" "6,0,2,2,4,10,10")
    (set_attr "cc" "clobber,none,clobber,clobber,clobber,clobber,clobber")])
 
-(define_insn "lshrsi3"
+   
+(define_expand "lshrsi3"
+  [(set (match_operand:SI 0 "register_operand"           "r")
+	(lshiftrt:SI (match_operand:SI 1 "register_operand" "r")
+		     (match_operand:QI 2 "nonmemory_operand"  "rI")))]
+  ""
+  "if (GET_CODE (operands[2]) == CONST_INT
+       && REG_P (operands[0]) && REG_P (operands[1]))
+     { int value = INTVAL (operands[2]);
+       if (value <= 0)
+        DONE;
+ 
+       rtx rtx_lsb_source    = gen_rtx_SUBREG (QImode,operands[1],0);
+       rtx rtx_mid1sb_source = gen_rtx_SUBREG (QImode,operands[1],1);
+       rtx rtx_mid2sb_source = gen_rtx_SUBREG (QImode,operands[1],2);
+       rtx rtx_msb_source    = gen_rtx_SUBREG (QImode,operands[1],3);
+       rtx rtx_lsb_target    = gen_rtx_SUBREG (QImode,operands[0],0);
+       rtx rtx_mid1sb_target = gen_rtx_SUBREG (QImode,operands[0],1);
+       rtx rtx_mid2sb_target = gen_rtx_SUBREG (QImode,operands[0],2);
+       rtx rtx_msb_target    = gen_rtx_SUBREG (QImode,operands[0],3);
+       
+       if (value == 8)
+         {
+           emit_insn (gen_movqi (rtx_lsb_target,rtx_mid1sb_source)); 
+           emit_insn (gen_movqi (rtx_mid1sb_target,rtx_mid2sb_source)); 
+           emit_insn (gen_movqi (rtx_mid2sb_target,rtx_msb_source));
+           emit_insn (gen_movqi (rtx_msb_target,GEN_INT (0)));
+           DONE; 
+         } 
+       if (value == 16)
+         {
+           emit_insn (gen_movqi (rtx_lsb_target,rtx_mid2sb_source)); 
+           emit_insn (gen_movqi (rtx_mid1sb_target,rtx_msb_source)); 
+           emit_insn (gen_movqi (rtx_msb_target,GEN_INT (0)));
+           emit_insn (gen_movqi (rtx_mid2sb_target,GEN_INT (0)));
+           DONE; 
+         } 
+       if (value == 24)
+         {
+           emit_insn (gen_movqi (rtx_lsb_target,rtx_msb_source)); 
+           emit_insn (gen_movqi (rtx_msb_target,GEN_INT (0)));
+           emit_insn (gen_movqi (rtx_mid1sb_target,GEN_INT (0))); 
+           emit_insn (gen_movqi (rtx_mid2sb_target,GEN_INT (0)));	 
+           DONE; 
+         } 
+       if (value > 31)
+         { 
+           emit_insn (gen_movsi (operands[0],GEN_INT (0)));
+	   DONE;
+         }
+	 
+       if (value > 24)
+         {
+           emit_insn (gen_lshrqi3 (rtx_lsb_target,
+                                   rtx_msb_source, GEN_INT (value - 24))); 
+           emit_insn (gen_movqi (rtx_mid1sb_target,GEN_INT (0)));	 
+           emit_insn (gen_movqi (rtx_mid2sb_target,GEN_INT (0)));	 
+           emit_insn (gen_movqi (rtx_msb_target,GEN_INT (0)));
+           DONE;
+         }
+     }"
+)
+
+(define_insn "*lshrsi3"
   [(set (match_operand:SI 0 "register_operand"             "=r,r,r,r,r,r,r")
 	(lshiftrt:SI (match_operand:SI 1 "register_operand" "0,0,0,r,0,0,0")
 		     (match_operand:QI 2 "general_operand"  "r,L,P,O,K,n,Qm")))]
@@ -1486,77 +1657,90 @@
 ;; xx<---x xx<---x xx<---x xx<---x xx<---x xx<---x xx<---x xx<---x xx<---x
 ;; sign extend
 
-(define_insn "extendqihi2"
-  [(set (match_operand:HI 0 "register_operand" "=r,r")
-        (sign_extend:HI (match_operand:QI 1 "register_operand" "0,*r")))]
-  ""
-  "@
-	clr %B0\;sbrc %0,7\;com %B0
-	mov %A0,%A1\;clr %B0\;sbrc %A0,7\;com %B0"
-  [(set_attr "length" "3,4")
-   (set_attr "cc" "set_n,set_n")])
-
-(define_insn "extendqisi2"
-  [(set (match_operand:SI 0 "register_operand" "=r,r")
-        (sign_extend:SI (match_operand:QI 1 "register_operand" "0,*r")))]
-  ""
-  "@
-	clr %B0\;sbrc %A0,7\;com %B0\;mov %C0,%B0\;mov %D0,%B0
-	mov %A0,%A1\;clr %B0\;sbrc %A0,7\;com %B0\;mov %C0,%B0\;mov %D0,%B0"
-  [(set_attr "length" "5,6")
-   (set_attr "cc" "set_n,set_n")])
-
-(define_insn "extendhisi2"
-  [(set (match_operand:SI 0 "register_operand"               "=r,&r")
-        (sign_extend:SI (match_operand:HI 1 "register_operand" "0,*r")))]
-  ""
-  "@
-	clr %C0\;sbrc %B0,7\;com %C0\;mov %D0,%C0
-	{mov %A0,%A1\;mov %B0,%B1|movw %A0,%A1}\;clr %C0\;sbrc %B0,7\;com %C0\;mov %D0,%C0"
-  [(set_attr_alternative "length"
-			 [(const_int 4)
-			  (if_then_else (eq_attr "mcu_enhanced" "yes")
-					(const_int 5)
-					(const_int 6))])
-   (set_attr "cc" "set_n,set_n")])
+(define_insn "generate_extension_byte"
+ [(set (match_operand:QI 0 "register_operand" "=&r,=r") 
+       (unspec:QI [(match_operand:QI 1 "register_operand" "r,r")] 
+                  UNSP_GEN_SIGN ))]
+ ""
+ "@
+  clr %0\;sbrc %1,7\;com %0
+  mov __tmp_reg__,%1\;clr %0\;sbrc __tmp_reg__,7\;com %0"
+ [(set_attr "length" "3,4")
+   (set_attr "cc" "clobber,clobber")])
+ 
 
+(define_expand "extendqihi2"
+  [ (set (subreg:QI (match_operand:HI 0 "register_operand" "=r,r") 0)
+         (match_operand:QI 1 "register_operand" "0,*r"))
+    (set (subreg:QI (match_dup 0) 1)
+         (unspec:QI [(match_dup 1)] UNSP_GEN_SIGN))]
+  ""
+  "if (!REG_P (operands[1]))
+     FAIL;"
+)
+(define_expand "extendqisi2"
+  [ (set (subreg:QI (match_operand:HI 0 "register_operand" "=r,r") 0)
+         (match_operand:QI 1 "register_operand" "0,*r"))
+    (set (subreg:QI (match_dup 0) 1)
+         (unspec:QI [(match_dup 1)] UNSP_GEN_SIGN))
+    (set (subreg:QI (match_dup 0) 2)
+         (subreg:QI (match_dup 0) 1))
+    (set (subreg:QI (match_dup 0) 3)
+         (subreg:QI (match_dup 0) 1))]
+  ""  
+  "if (!REG_P (operands[1]))
+     FAIL;"
+)
+
+(define_expand "extendhisi2"
+  [ (set (subreg:HI (match_operand:HI 0 "register_operand" "=r,r") 0)
+         (match_operand:HI 1 "register_operand" "0,*r"))
+    (set (subreg:QI (match_dup 0) 2)
+         (unspec:QI [(subreg:QI (match_dup 1) 1)] UNSP_GEN_SIGN))
+    (set (subreg:QI (match_dup 0) 3)
+         (subreg:QI (match_dup 0) 2))]
+  ""  
+  "if (!REG_P (operands[1]))
+     FAIL;"
+)
 ;; xx<---x xx<---x xx<---x xx<---x xx<---x xx<---x xx<---x xx<---x xx<---x
 ;; zero extend
 
-(define_insn "zero_extendqihi2"
-  [(set (match_operand:HI 0 "register_operand" "=r,r")
-        (zero_extend:HI (match_operand:QI 1 "register_operand" "0,*r")))]
-  ""
-  "@
-	clr %B0
-	mov %A0,%A1\;clr %B0"
-  [(set_attr "length" "1,2")
-   (set_attr "cc" "set_n,set_n")])
-
-(define_insn "zero_extendqisi2"
-  [(set (match_operand:SI 0 "register_operand" "=r,r")
-        (zero_extend:SI (match_operand:QI 1 "register_operand" "0,*r")))]
-  ""
-  "@
-	clr %B0\;clr %C0\;clr %D0
-	mov %A0,%A1\;clr %B0\;clr %C0\;clr %D0"
-  [(set_attr "length" "3,4")
-   (set_attr "cc" "set_n,set_n")])
-
-(define_insn "zero_extendhisi2"
-  [(set (match_operand:SI 0 "register_operand" "=r,&r")
-        (zero_extend:SI (match_operand:HI 1 "register_operand" "0,*r")))]
-  ""
-  "@
-	clr %C0\;clr %D0
-	{mov %A0,%A1\;mov %B0,%B1|movw %A0,%A1}\;clr %C0\;clr %D0"
-  [(set_attr_alternative "length"
-			 [(const_int 2)
-			  (if_then_else (eq_attr "mcu_enhanced" "yes")
-					(const_int 3)
-					(const_int 4))])
-   (set_attr "cc" "set_n,set_n")])
-
+(define_expand "zero_extendqihi2"
+  [ (set (subreg:QI (match_operand:HI 0 "register_operand" "=r,r") 0)
+         (match_operand:QI 1 "register_operand" "0,*r"))
+    (set (subreg:QI (match_dup 0) 1)
+         (const_int 0))]
+  ""
+  "if (!REG_P (operands[1]))
+     FAIL;"
+)
+
+(define_expand "zero_extendqisi2"
+  [ (set (subreg:QI (match_operand:HI 0 "register_operand" "=r,r") 0)
+         (match_operand:QI 1 "register_operand" "0,*r"))
+    (set (subreg:QI (match_dup 0) 1)
+         (const_int 0))
+    (set (subreg:QI (match_dup 0) 2)
+         (const_int 0))
+    (set (subreg:QI (match_dup 0) 3)
+         (const_int 0))]
+  ""
+  "if (!REG_P (operands[1]))
+     FAIL;"
+)
+
+(define_expand "zero_extendhisi2"
+  [ (set (subreg:HI (match_operand:HI 0 "register_operand" "=r,r") 0)
+         (match_operand:HI 1 "register_operand" "0,*r"))
+    (set (subreg:QI (match_dup 0) 2)
+         (const_int 0))
+    (set (subreg:QI (match_dup 0) 3)
+         (const_int 0))]
+  ""
+  "if (!REG_P (operands[1]))
+     FAIL;"
+)
 ;;<=><=><=><=><=><=><=><=><=><=><=><=><=><=><=><=><=><=><=><=><=><=><=><=><=>
 ;; compare
 
@@ -2176,7 +2360,8 @@
 
 ;; Table made from "rjmp" instructions for <=8K devices.
 (define_insn "*tablejump_rjmp"
-  [(set (pc) (unspec:HI [(match_operand:HI 0 "register_operand" "!z,*r")] 1))
+  [(set (pc) (unspec:HI [(match_operand:HI 0 "register_operand" "!z,*r")] 
+                        UNSP_READ_PMEM))
    (use (label_ref (match_operand 1 "" "")))
    (clobber (match_dup 0))]
   "!AVR_MEGA"
@@ -2197,7 +2382,8 @@
    (set_attr "cc" "clobber")])
 
 (define_insn "*tablejump_enh"
-  [(set (pc) (unspec:HI [(match_operand:HI 0 "register_operand" "z")] 1))
+  [(set (pc) (unspec:HI [(match_operand:HI 0 "register_operand" "z")] 
+                        UNSP_READ_PMEM))
    (use (label_ref (match_operand 1 "" "")))
    (clobber (match_dup 0))]
   "AVR_MEGA && AVR_ENHANCED"
@@ -2211,7 +2397,8 @@
    (set_attr "cc" "clobber")])
 
 (define_insn "*tablejump"
-  [(set (pc) (unspec:HI [(match_operand:HI 0 "register_operand" "z")] 1))
+  [(set (pc) (unspec:HI [(match_operand:HI 0 "register_operand" "z")] 
+                        UNSP_READ_PMEM))
    (use (label_ref (match_operand 1 "" "")))
    (clobber (match_dup 0))]
   "AVR_MEGA"
@@ -2244,7 +2431,7 @@
    (set (match_dup 6)
 	(plus:HI (match_dup 6) (label_ref (match_operand:HI 3 "" ""))))
 
-   (parallel [(set (pc) (unspec:HI [(match_dup 6)] 1))
+   (parallel [(set (pc) (unspec:HI [(match_dup 6)] UNSP_READ_PMEM))
 	      (use (label_ref (match_dup 3)))
 	      (clobber (match_dup 6))])]
   ""

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]