This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[PATCH] AVR: rev.2: implement HI/SI logic operations and sign/zero extension by define_insn_and_split instead of define_insn
- From: BjÃrn Haase <bjoern dot m dot haase at web dot de>
- To: Denis Chertykov <denisc at overta dot ru>
- Cc: Andy Hutchinson <HutchinsonAndy at netscape dot net>,marekm at amelek dot gda dot pl,gcc-patches at gcc dot gnu dot org
- Date: Sun, 17 Apr 2005 11:18:07 +0200
- Subject: [PATCH] AVR: rev.2: implement HI/SI logic operations and sign/zero extension by define_insn_and_split instead of define_insn
- References: <200504032154.35580.bjoern.m.haase@web.de>
Hello Denis,
here is again the patch considering your remarks. I have been able to remove
most of the explicit insn templates in the define_insn_and_split patterns.
However, I did not succeed in removing them completely. A single case makes
problem: lable reference immediates. This case still remains handled by the
shortened unsplitted instruction patterns. I have also experimented with
using gen_lowpart/gen_highpart. When using them I got about 40 additional
regressions due to ICE in gen_lowpart/gen_highpart. Namely, these functions
seem to fail on subreg input operands and as well on immediate label
references. Also the resulting code did not get smaller. So I decided to
stick to the explicit subreg expressions.
I have tested the patch on the testsuite setup using the atmega128 simulator
and did not observe any regression.
Yours,
BjÃrn
BTW, what is happening with Andy's RTL-prologue/epilogue patch? IMHO, the
patch would be ready for check-in on mainline 4.1.?
2005-15-04 Bjoern Haase <bjoern.m.haase@web.de>
* config/avr/avr.md:
replace magic numbers for unspec numbering by (define_constants ).
add new unspec for generation of sign extension byte.
extend define_insn to define_insn_and_split for the patterns...
"andhi" (here also tiny change in define_insn pattern), "andsi"
"iorhi", "iorhi_clobber", "iorsi", "iorsi_clobber"
"extendqihi2", "extendqisi2", "extendhisi2"
"zero_extendqihi2", "zero_extendqisi2", "zero_extendhisi2"
replace "xorhi" and "xorsi" patterns by expanders
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 17 Apr 2005 09:58:58 -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,72 +973,145 @@
[(set_attr "length" "1,1")
(set_attr "cc" "set_zn,set_zn")])
-(define_insn "andhi3"
+(define_insn_and_split "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")))
+ (match_operand:HI 2 "nonmemory_operand" "r,i,i")))
(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)
+ /* Emit unsplitted insn in case of label refs. */
+ 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 (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));
+ AS2 (ldi,%3,hi8(%2)) CR_TAB
+ AS2 (and,%B0,%3));
}"
- [(set_attr "length" "2,2,3")
- (set_attr "cc" "set_n,clobber,set_n")])
+ " reload_completed
+ && ((GET_CODE(operands[2]) == CONST_INT) || REG_P(operands[2]))"
+ [(set (subreg:QI (match_dup 0) 0)
+ (and:QI (subreg:QI (match_dup 1) 0)
+ (subreg:QI (match_dup 2) 0)))
+ (set (subreg:QI (match_dup 0) 1)
+ (and:QI (subreg:QI (match_dup 1) 1)
+ (subreg:QI (match_dup 2) 1)))]
+ "if (GET_CODE(operands[2]) == CONST_INT)
+ {
+ /* If operands[2] is a register, use the template above. */
+ /* In case of const ints optimize away andi reg,0xff and */
+ /* replace andi reg,0 by ldi reg,0 . */
+ int value = INTVAL(operands[2]);
+ int j;
+ int bytes_of_mode = 2;
+ for (j=0; j < bytes_of_mode; j++)
+ {
+ rtx immediate_operand;
+ rtx subreg_operand;
+
+ int qi_immediate = (value & 0x000000FF);
+ if (qi_immediate & 0x0080)
+ qi_immediate -= 256;
+ immediate_operand = GEN_INT (qi_immediate);
+ subreg_operand = gen_rtx_SUBREG (QImode,operands[0],j);
+
+ if (qi_immediate == 0)
+ {
+ emit_insn (gen_movqi (subreg_operand,
+ immediate_operand));
+
+ }
+ else if (qi_immediate != -1)
+ {
+ /* check whether or not we can use andi. */
+ if ((REGNO (operands[0])+j) < 16)
+ {
+ emit_insn (gen_movqi (operands[3],
+ immediate_operand));
+ emit_insn (gen_andqi3 (subreg_operand,
+ subreg_operand,
+ operands[3]));
+ }
+ else
+ {
+ emit_insn (gen_andqi3 (subreg_operand,
+ subreg_operand,
+ immediate_operand));
+ }
+ }
+ value = value >> 8;
+ }
+ DONE;
+ }
+ "
+ [(set_attr "length" "2,2,4")
+ (set_attr "cc" "set_n,clobber,clobber")])
-(define_insn "andsi3"
+(define_insn_and_split "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 \"\";
- }
+ /* Emit unsplitted insn in case of label refs. */
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\";
}"
+ " reload_completed
+ && ((GET_CODE(operands[2]) == CONST_INT) || REG_P(operands[2]))"
+ [(set (subreg:QI (match_dup 0) 0)
+ (and:QI (subreg:QI (match_dup 1) 0)
+ (subreg:QI (match_dup 2) 0)))
+ (set (subreg:QI (match_dup 0) 1)
+ (and:QI (subreg:QI (match_dup 1) 1)
+ (subreg:QI (match_dup 2) 1)))
+ (set (subreg:QI (match_dup 0) 2)
+ (and:QI (subreg:QI (match_dup 1) 2)
+ (subreg:QI (match_dup 2) 2)))
+ (set (subreg:QI (match_dup 0) 3)
+ (and:QI (subreg:QI (match_dup 1) 3)
+ (subreg:QI (match_dup 2) 3)))]
+ "if (GET_CODE(operands[2]) == CONST_INT)
+ {
+ /* If operands[2] is a register, use the template above. */
+ int value = INTVAL(operands[2]);
+ int j;
+ int bytes_of_mode = 4;
+ for (j=0; j < bytes_of_mode; j++)
+ {
+ rtx immediate_operand;
+ rtx subreg_operand;
+
+ int qi_immediate = (value & 0x000000FF);
+ if (qi_immediate & 0x0080)
+ qi_immediate -= 256;
+ immediate_operand = GEN_INT (qi_immediate);
+ subreg_operand = gen_rtx_SUBREG (QImode,operands[0],j);
+
+ if (qi_immediate == 0)
+ {
+ emit_insn (gen_movqi (subreg_operand,
+ immediate_operand));
+
+ }
+ else if (qi_immediate != -1)
+ {
+ emit_insn (gen_andqi3 (subreg_operand,
+ subreg_operand,
+ immediate_operand));
+ }
+ value = value >> 8;
+ }
+ DONE;
+ }
+ "
[(set_attr "length" "4,4")
- (set_attr "cc" "set_n,set_n")])
+ (set_attr "cc" "set_n,clobber")])
;;|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
;; ior
@@ -1045,31 +1127,62 @@
[(set_attr "length" "1,1")
(set_attr "cc" "set_zn,set_zn")])
-(define_insn "iorhi3"
+(define_insn_and_split "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 \"\";
- }
+ /* Emit unsplitted insn in case of label refs. */
return (AS2 (ori,%0,lo8(%2)) CR_TAB
AS2 (ori,%B0,hi8(%2)));
-}"
+}"
+ " reload_completed
+ && ((GET_CODE(operands[2]) == CONST_INT) || REG_P(operands[2]))"
+ [(set (subreg:QI (match_dup 0) 0)
+ (ior:QI (subreg:QI (match_dup 1) 0)
+ (subreg:QI (match_dup 2) 0)))
+ (set (subreg:QI (match_dup 0) 1)
+ (ior:QI (subreg:QI (match_dup 1) 1)
+ (subreg:QI (match_dup 2) 1)))]
+ "if (GET_CODE(operands[2]) == CONST_INT)
+ {
+ /* If operands[2] is a register, use the template above. */
+ int value = INTVAL(operands[2]);
+ int j;
+ int bytes_of_mode = 2;
+ for (j=0; j < bytes_of_mode; j++)
+ {
+ rtx immediate_operand;
+ rtx subreg_operand;
+
+ int qi_immediate = (value & 0x000000FF);
+ if (qi_immediate & 0x0080)
+ qi_immediate -= 256;
+ immediate_operand = GEN_INT (qi_immediate);
+ subreg_operand = gen_rtx_SUBREG (QImode,operands[0],j);
+
+ if (qi_immediate == -1)
+ {
+ emit_insn (gen_movqi (subreg_operand,
+ immediate_operand));
+
+ }
+ else if (qi_immediate != 0)
+ {
+ emit_insn (gen_iorqi3 (subreg_operand,
+ subreg_operand,
+ immediate_operand));
+ }
+ value = value >> 8;
+ }
+ DONE;
+ }
+ "
[(set_attr "length" "2,2")
(set_attr "cc" "set_n,clobber")])
-(define_insn "*iorhi3_clobber"
+(define_insn_and_split "*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")))
@@ -1078,42 +1191,126 @@
"@
ldi %3,lo8(%2)\;or %A0,%3
ldi %3,lo8(%2)\;or %A0,%3\;ldi %3,hi8(%2)\;or %B0,%3"
+ " reload_completed
+ && ((GET_CODE(operands[2]) == CONST_INT) || REG_P(operands[2]))"
+ [(set (subreg:QI (match_dup 0) 0)
+ (ior:QI (subreg:QI (match_dup 1) 0)
+ (subreg:QI (match_dup 2) 0)))
+ (set (subreg:QI (match_dup 0) 1)
+ (ior:QI (subreg:QI (match_dup 1) 1)
+ (subreg:QI (match_dup 2) 1)))]
+ "if (GET_CODE(operands[2]) == CONST_INT)
+ {
+ /* If operands[2] is a register, use the template above. */
+ int value = INTVAL(operands[2]);
+ int j;
+ int bytes_of_mode = 2;
+ for (j=0; j < bytes_of_mode; j++)
+ {
+ rtx immediate_operand;
+ rtx subreg_operand;
+
+ int qi_immediate = (value & 0x000000FF);
+ if (qi_immediate & 0x0080)
+ qi_immediate -= 256;
+ immediate_operand = GEN_INT (qi_immediate);
+ subreg_operand = gen_rtx_SUBREG (QImode,operands[0],j);
+
+ if (qi_immediate == -1)
+ {
+ emit_insn (gen_movqi (subreg_operand,
+ immediate_operand));
+ }
+ else if (qi_immediate != 0)
+ {
+ /* check whether or not we can use ori. */
+ if ((REGNO (operands[0])+j) < 16)
+ {
+ emit_insn (gen_movqi (operands[3],
+ immediate_operand));
+ emit_insn (gen_iorqi3 (subreg_operand,
+ subreg_operand,
+ operands[3]));
+ }
+ else
+ {
+ emit_insn (gen_iorqi3 (subreg_operand,
+ subreg_operand,
+ immediate_operand));
+ }
+ }
+ value = value >> 8;
+ }
+ DONE;
+ }
+ "
[(set_attr "length" "2,4")
- (set_attr "cc" "clobber,set_n")])
+ (set_attr "cc" "clobber,clobber")])
-(define_insn "iorsi3"
+(define_insn_and_split "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 \"\";
- }
+ /* emit unsplitted insn in case of label refs. */
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)));
}"
+ " reload_completed
+ && ((GET_CODE(operands[2]) == CONST_INT) || REG_P(operands[2]))"
+ [(set (subreg:QI (match_dup 0) 0)
+ (ior:QI (subreg:QI (match_dup 1) 0)
+ (subreg:QI (match_dup 2) 0)))
+ (set (subreg:QI (match_dup 0) 1)
+ (ior:QI (subreg:QI (match_dup 1) 1)
+ (subreg:QI (match_dup 2) 1)))
+ (set (subreg:QI (match_dup 0) 2)
+ (ior:QI (subreg:QI (match_dup 1) 2)
+ (subreg:QI (match_dup 2) 2)))
+ (set (subreg:QI (match_dup 0) 3)
+ (ior:QI (subreg:QI (match_dup 1) 3)
+ (subreg:QI (match_dup 2) 3)))]
+ "if (GET_CODE(operands[2]) == CONST_INT)
+ {
+ /* If operands[2] is a register, use the template above. */
+ int value = INTVAL(operands[2]);
+ int j;
+ int bytes_of_mode = 4;
+ for (j=0; j < bytes_of_mode; j++)
+ {
+ rtx immediate_operand;
+ rtx subreg_operand;
+
+ int qi_immediate = (value & 0x000000FF);
+ if (qi_immediate & 0x0080)
+ qi_immediate -= 256;
+ immediate_operand = GEN_INT (qi_immediate);
+ subreg_operand = gen_rtx_SUBREG (QImode,operands[0],j);
+
+ if (qi_immediate == -1)
+ {
+ emit_insn (gen_movqi (subreg_operand,
+ immediate_operand));
+
+ }
+ else if (qi_immediate != 0)
+ {
+ emit_insn (gen_iorqi3 (subreg_operand,
+ subreg_operand,
+ immediate_operand));
+ }
+ value = value >> 8;
+ }
+ DONE;
+ }
+ "
[(set_attr "length" "4,4")
(set_attr "cc" "set_n,clobber")])
-(define_insn "*iorsi3_clobber"
+(define_insn_and_split "*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")))
@@ -1122,8 +1319,67 @@
"@
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"
+ " reload_completed
+ && ((GET_CODE(operands[2]) == CONST_INT) || REG_P(operands[2]))"
+ [(set (subreg:QI (match_dup 0) 0)
+ (ior:QI (subreg:QI (match_dup 1) 0)
+ (subreg:QI (match_dup 2) 0)))
+ (set (subreg:QI (match_dup 0) 1)
+ (ior:QI (subreg:QI (match_dup 1) 1)
+ (subreg:QI (match_dup 2) 1)))
+ (set (subreg:QI (match_dup 0) 2)
+ (ior:QI (subreg:QI (match_dup 1) 2)
+ (subreg:QI (match_dup 2) 2)))
+ (set (subreg:QI (match_dup 0) 3)
+ (ior:QI (subreg:QI (match_dup 1) 3)
+ (subreg:QI (match_dup 2) 3)))]
+ "if (GET_CODE(operands[2]) == CONST_INT)
+ {
+ /* If operands[2] is a register, use the template above. */
+ int value = INTVAL(operands[2]);
+ int j;
+ int bytes_of_mode = 4;
+ for (j=0; j < bytes_of_mode; j++)
+ {
+ rtx immediate_operand;
+ rtx subreg_operand;
+
+ int qi_immediate = (value & 0x000000FF);
+ if (qi_immediate & 0x0080)
+ qi_immediate -= 256;
+ immediate_operand = GEN_INT (qi_immediate);
+ subreg_operand = gen_rtx_SUBREG (QImode,operands[0],j);
+
+ if (qi_immediate == -1)
+ {
+ emit_insn (gen_movqi (subreg_operand,
+ immediate_operand));
+ }
+ else if (qi_immediate != 0)
+ {
+ /* check whether or not we can use ori. */
+ if ((REGNO (operands[0])+j) < 16)
+ {
+ emit_insn (gen_movqi (operands[3],
+ immediate_operand));
+ emit_insn (gen_iorqi3 (subreg_operand,
+ subreg_operand,
+ operands[3]));
+ }
+ else
+ {
+ emit_insn (gen_iorqi3 (subreg_operand,
+ subreg_operand,
+ immediate_operand));
+ }
+ }
+ value = value >> 8;
+ }
+ DONE;
+ }
+ "
[(set_attr "length" "2,8")
- (set_attr "cc" "clobber,set_n")])
+ (set_attr "cc" "clobber,clobber")])
;;^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
;; xor
@@ -1137,28 +1393,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
@@ -1486,33 +1746,69 @@
;; xx<---x xx<---x xx<---x xx<---x xx<---x xx<---x xx<---x xx<---x xx<---x
;; sign extend
-(define_insn "extendqihi2"
+(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_insn_and_split "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"
+ "reload_completed"
+ [ (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_attr "length" "3,4")
(set_attr "cc" "set_n,set_n")])
-(define_insn "extendqisi2"
+(define_insn_and_split "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"
+ "reload_completed"
+ [ (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))]
+ ""
[(set_attr "length" "5,6")
(set_attr "cc" "set_n,set_n")])
-(define_insn "extendhisi2"
+(define_insn_and_split "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"
+ "reload_completed"
+ [ (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))]
+ ""
[(set_attr_alternative "length"
[(const_int 4)
(if_then_else (eq_attr "mcu_enhanced" "yes")
@@ -1523,33 +1819,57 @@
;; xx<---x xx<---x xx<---x xx<---x xx<---x xx<---x xx<---x xx<---x xx<---x
;; zero extend
-(define_insn "zero_extendqihi2"
+(define_insn_and_split "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"
+ "reload_completed"
+ [ (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_attr "length" "1,2")
(set_attr "cc" "set_n,set_n")])
-(define_insn "zero_extendqisi2"
+(define_insn_and_split "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"
+ "reload_completed"
+ [ (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))]
+ ""
[(set_attr "length" "3,4")
(set_attr "cc" "set_n,set_n")])
-(define_insn "zero_extendhisi2"
+(define_insn_and_split "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"
+ "reload_completed"
+ [ (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))]
+ ""
[(set_attr_alternative "length"
[(const_int 2)
(if_then_else (eq_attr "mcu_enhanced" "yes")
@@ -2176,7 +2496,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 +2518,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 +2533,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 +2567,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))])]
""