aboutsummaryrefslogtreecommitdiff
path: root/gcc/config/avr
diff options
context:
space:
mode:
authorGeorg-Johann Lay <avr@gjlay.de>2011-09-23 10:14:23 +0000
committerGeorg-Johann Lay <gjl@gcc.gnu.org>2011-09-23 10:14:23 +0000
commit5d94b9886327df3f4b977d4bc0d1d09c1b6d3220 (patch)
treef91cb94b7c6d3afa66fa6743fe352b3a8b63d84e /gcc/config/avr
parent9acebb8a99e519c40f0f3fb419c9adbb1c2c8209 (diff)
downloadgcc-5d94b9886327df3f4b977d4bc0d1d09c1b6d3220.zip
gcc-5d94b9886327df3f4b977d4bc0d1d09c1b6d3220.tar.gz
gcc-5d94b9886327df3f4b977d4bc0d1d09c1b6d3220.tar.bz2
re PR target/50446 ([avr] Implement rotate patterns with offset 1)
PR target/50446 * config/avr/avr.md (rotlqi3): Support all offsets 0..7. (rotlqi3_4): Turn insn into expander. (*rotlqi3): New insn. (rotlhi3, rotlsi3): Support rotate left/right by 1. (*rotlhi2.1, *rotlhi2.15): New insns. (*rotlsi2.1, *rotlsi2.31): New insns. * config/avr/constraints.md (C03, C05, C06, C07): New constraints. From-SVN: r179116
Diffstat (limited to 'gcc/config/avr')
-rw-r--r--gcc/config/avr/avr.md121
-rw-r--r--gcc/config/avr/constraints.md20
2 files changed, 119 insertions, 22 deletions
diff --git a/gcc/config/avr/avr.md b/gcc/config/avr/avr.md
index ab17104..c7a28c7 100644
--- a/gcc/config/avr/avr.md
+++ b/gcc/config/avr/avr.md
@@ -2390,23 +2390,38 @@
(define_expand "rotlqi3"
[(set (match_operand:QI 0 "register_operand" "")
- (rotate:QI (match_operand:QI 1 "register_operand" "")
- (match_operand:QI 2 "const_int_operand" "")))]
+ (rotate:QI (match_operand:QI 1 "register_operand" "")
+ (match_operand:QI 2 "const_0_to_7_operand" "")))]
""
- "
-{
- if (!CONST_INT_P (operands[2]) || (INTVAL (operands[2]) != 4))
- FAIL;
-}")
+ {
+ if (!CONST_INT_P (operands[2]))
+ FAIL;
-(define_insn "rotlqi3_4"
- [(set (match_operand:QI 0 "register_operand" "=r")
- (rotate:QI (match_operand:QI 1 "register_operand" "0")
- (const_int 4)))]
+ operands[2] = gen_int_mode (INTVAL (operands[2]) & 7, QImode);
+ })
+
+;; Expander used by __builtin_avr_swap
+(define_expand "rotlqi3_4"
+ [(set (match_operand:QI 0 "register_operand" "")
+ (rotate:QI (match_operand:QI 1 "register_operand" "")
+ (const_int 4)))])
+
+(define_insn "*rotlqi3"
+ [(set (match_operand:QI 0 "register_operand" "=r,r,r ,r ,r ,r ,r ,r")
+ (rotate:QI (match_operand:QI 1 "register_operand" "0,0,0 ,0 ,0 ,0 ,0 ,0")
+ (match_operand:QI 2 "const_0_to_7_operand" "P,K,C03,C04,C05,C06,C07,L")))]
""
- "swap %0"
- [(set_attr "length" "1")
- (set_attr "cc" "none")])
+ "@
+ lsl %0\;adc %0,__zero_reg__
+ lsl %0\;adc %0,__zero_reg__\;lsl %0\;adc %0,__zero_reg__
+ swap %0\;bst %0,0\;ror %0\;bld %0,7
+ swap %0
+ swap %0\;lsl %0\;adc %0,__zero_reg__
+ swap %0\;lsl %0\;adc %0,__zero_reg__\;lsl %0\;adc %0,__zero_reg__
+ bst %0,0\;ror %0\;bld %0,7
+ "
+ [(set_attr "length" "2,4,4,1,3,5,3,0")
+ (set_attr "cc" "set_n,set_n,clobber,none,set_n,set_n,clobber,none")])
;; Split all rotates of HI,SI and DImode registers where rotation is by
;; a whole number of bytes. The split creates the appropriate moves and
@@ -2418,25 +2433,79 @@
(define_mode_attr rotx [(DI "&r,&r,X") (SI "&r,&r,X") (HI "X,X,X")])
(define_mode_attr rotsmode [(DI "QI") (SI "HI") (HI "QI")])
+;; "rotlhi3"
+;; "rotlsi3"
+;; "rotldi3"
(define_expand "rotl<mode>3"
[(parallel [(set (match_operand:HIDI 0 "register_operand" "")
- (rotate:HIDI (match_operand:HIDI 1 "register_operand" "")
- (match_operand:VOID 2 "const_int_operand" "")))
- (clobber (match_dup 3))])]
+ (rotate:HIDI (match_operand:HIDI 1 "register_operand" "")
+ (match_operand:VOID 2 "const_int_operand" "")))
+ (clobber (match_dup 3))])]
""
{
- if (CONST_INT_P (operands[2])
- && 0 == INTVAL (operands[2]) % 8)
+ int offset;
+
+ if (!CONST_INT_P (operands[2]))
+ FAIL;
+
+ offset = INTVAL (operands[2]);
+
+ if (0 == offset % 8)
{
- if (AVR_HAVE_MOVW && 0 == INTVAL (operands[2]) % 16)
+ if (AVR_HAVE_MOVW && 0 == offset % 16)
operands[3] = gen_rtx_SCRATCH (<rotsmode>mode);
else
operands[3] = gen_rtx_SCRATCH (QImode);
}
+ else if (<MODE>mode != DImode
+ && (offset == 1
+ || offset == GET_MODE_BITSIZE (<MODE>mode) -1))
+ {
+ /*; Support rotate left/right by 1 */
+
+ emit_move_insn (operands[0],
+ gen_rtx_ROTATE (<MODE>mode, operands[1], operands[2]));
+ DONE;
+ }
else
FAIL;
})
+(define_insn "*rotlhi2.1"
+ [(set (match_operand:HI 0 "register_operand" "=r")
+ (rotate:HI (match_operand:HI 1 "register_operand" "0")
+ (const_int 1)))]
+ ""
+ "lsl %A0\;rol %B0\;adc %A0,__zero_reg__"
+ [(set_attr "length" "3")
+ (set_attr "cc" "clobber")])
+
+(define_insn "*rotlhi2.15"
+ [(set (match_operand:HI 0 "register_operand" "=r")
+ (rotate:HI (match_operand:HI 1 "register_operand" "0")
+ (const_int 15)))]
+ ""
+ "bst %A0,0\;ror %B0\;ror %A0\;bld %B0,7"
+ [(set_attr "length" "3")
+ (set_attr "cc" "clobber")])
+
+(define_insn "*rotlsi2.1"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (rotate:SI (match_operand:SI 1 "register_operand" "0")
+ (const_int 1)))]
+ ""
+ "lsl %A0\;rol %B0\;rol %C0\;rol %D0\;adc %A0,__zero_reg__"
+ [(set_attr "length" "5")
+ (set_attr "cc" "clobber")])
+
+(define_insn "*rotlsi2.31"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (rotate:SI (match_operand:SI 1 "register_operand" "0")
+ (const_int 31)))]
+ ""
+ "bst %A0,0\;ror %D0\;ror %C0\;ror %B0\;ror %A0\;bld %D0,7"
+ [(set_attr "length" "6")
+ (set_attr "cc" "clobber")])
;; Overlapping non-HImode registers often (but not always) need a scratch.
;; The best we can do is use early clobber alternative "#&r" so that
@@ -2444,7 +2513,11 @@
;; allocation does not prefer non-overlapping.
-; Split word aligned rotates using scratch that is mode dependent.
+;; Split word aligned rotates using scratch that is mode dependent.
+
+;; "*rotwhi"
+;; "*rotwsi"
+;; "*rotwdi"
(define_insn_and_split "*rotw<mode>"
[(set (match_operand:HIDI 0 "register_operand" "=r,r,#&r")
(rotate:HIDI (match_operand:HIDI 1 "register_operand" "0,r,r")
@@ -2462,7 +2535,11 @@
})
-; Split byte aligned rotates using scratch that is always QI mode.
+;; Split byte aligned rotates using scratch that is always QI mode.
+
+;; "*rotbhi"
+;; "*rotbsi"
+;; "*rotbdi"
(define_insn_and_split "*rotb<mode>"
[(set (match_operand:HIDI 0 "register_operand" "=r,r,#&r")
(rotate:HIDI (match_operand:HIDI 1 "register_operand" "0,r,r")
diff --git a/gcc/config/avr/constraints.md b/gcc/config/avr/constraints.md
index d6c172f..f02c197 100644
--- a/gcc/config/avr/constraints.md
+++ b/gcc/config/avr/constraints.md
@@ -108,11 +108,31 @@
(and (match_code "mem")
(match_test "extra_constraint_Q (op)")))
+(define_constraint "C03"
+ "Constant integer 3."
+ (and (match_code "const_int")
+ (match_test "ival == 3")))
+
(define_constraint "C04"
"Constant integer 4."
(and (match_code "const_int")
(match_test "ival == 4")))
+(define_constraint "C05"
+ "Constant integer 5."
+ (and (match_code "const_int")
+ (match_test "ival == 5")))
+
+(define_constraint "C06"
+ "Constant integer 6."
+ (and (match_code "const_int")
+ (match_test "ival == 6")))
+
+(define_constraint "C07"
+ "Constant integer 7."
+ (and (match_code "const_int")
+ (match_test "ival == 7")))
+
(define_constraint "Ca2"
"Constant 2-byte integer that allows AND without clobber register."
(and (match_code "const_int")