@@ -48,6 +48,10 @@
(CARRY_REG 16)
]
)
+
+(define_code_iterator any_lshift [ashift lshiftrt])
+(define_code_iterator any_or_plus [plus ior xor])
+(define_code_iterator any_rotate [rotate rotatert])
;; ::::::::::::::::::::
;; ::
@@ -1301,3 +1323,86 @@
[(parallel [(set (match_dup 2) (match_dup 1))
(set (match_dup 1) (match_dup 2))])])
+;; Recognize shl+and and shr+and as macro instructions.
+(define_insn_and_split "*<code>_and_internal"
+ [(set (match_operand:HI 0 "register_operand" "=r")
+ (and:HI (any_lshift:HI (match_operand 1 "register_operand" "0")
+ (match_operand 2 "const_int_operand" "i"))
+ (match_operand 3 "const_int_operand" "i")))
+ (clobber (reg:BI CARRY_REG))]
+ "IN_RANGE (INTVAL (operands[2]), 0, 15)"
+ "#"
+ "reload_completed"
+ [(parallel [(set (match_dup 0) (any_lshift:HI (match_dup 1) (match_dup 2)))
+ (clobber (reg:BI CARRY_REG))])
+ (set (match_dup 0) (and:HI (match_dup 0) (match_dup 3)))])
+
+;; Swap nibbles instruction
+(define_insn "*swpn"
+ [(set (match_operand:HI 0 "register_operand" "=r")
+ (any_or_plus:HI
+ (any_or_plus:HI
+ (and:HI (ashift:HI (match_operand:HI 1 "register_operand" "0")
+ (const_int 4))
+ (const_int 240))
+ (and:HI (lshiftrt:HI (match_dup 1) (const_int 4))
+ (const_int 15)))
+ (and:HI (match_dup 1) (const_int -256))))]
+ ""
+ "swpn %0")
+
+(define_insn "*swpn_zext"
+ [(set (match_operand:HI 0 "register_operand" "=r")
+ (any_or_plus:HI
+ (and:HI (ashift:HI (match_operand:HI 1 "register_operand" "0")
+ (const_int 4))
+ (const_int 240))
+ (and:HI (lshiftrt:HI (match_dup 1) (const_int 4))
+ (const_int 15))))]
+ ""
+ "swpn %0 | and %0,#255"
+ [(set_attr "length" "6")])
+
+(define_insn "*swpn_sext"
+ [(set (match_operand:HI 0 "register_operand" "=r")
+ (sign_extend:HI
+ (rotate:QI (subreg:QI (match_operand:HI 1 "register_operand" "0") 0)
+ (const_int 4))))]
+ ""
+ "swpn %0 | cbw %0"
+ [(set_attr "length" "4")])
+
+(define_insn "*swpn_sext_2"
+ [(set (match_operand:HI 0 "register_operand" "=r")
+ (sign_extend:HI
+ (subreg:QI
+ (any_or_plus:HI
+ (ashift:HI (match_operand:HI 1 "register_operand" "0")
+ (const_int 4))
+ (subreg:HI (lshiftrt:QI (subreg:QI (match_dup 1) 0)
+ (const_int 4)) 0)) 0)))]
+ ""
+ "swpn %0 | cbw %0"
+ [(set_attr "length" "4")])
+
+;; Recognize swpn_zext+ior as a macro instruction.
+(define_insn_and_split "*swpn_zext_ior"
+ [(set (match_operand:HI 0 "register_operand")
+ (any_or_plus:HI
+ (any_or_plus:HI
+ (and:HI (ashift:HI (match_operand:HI 1 "register_operand")
+ (const_int 4))
+ (const_int 240))
+ (and:HI (lshiftrt:HI (match_dup 1) (const_int 4))
+ (const_int 15)))
+ (match_operand:HI 2 "nonmemory_operand")))]
+ "can_create_pseudo_p ()"
+ "#"
+ "&& 1"
+ [(set (match_dup 3) (ior:HI (and:HI (ashift:HI (match_dup 1) (const_int 4))
+ (const_int 240))
+ (and:HI (lshiftrt:HI (match_dup 1) (const_int 4))
+ (const_int 15))))
+ (set (match_dup 0) (ior:HI (match_dup 3) (match_dup 2)))]
+ "operands[3] = gen_reg_rtx (HImode);")
+
new file mode 100644
@@ -0,0 +1,10 @@
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+unsigned char ior_1(unsigned char x) { return (x>>4) | (x<<4); }
+unsigned char ior_2(unsigned char x) { return (x<<4) | (x>>4); }
+unsigned char xor_1(unsigned char x) { return (x>>4) ^ (x<<4); }
+unsigned char xor_2(unsigned char x) { return (x<<4) ^ (x>>4); }
+unsigned char sum_1(unsigned char x) { return (x>>4) + (x<<4); }
+unsigned char sum_2(unsigned char x) { return (x<<4) + (x>>4); }
+/* { dg-final { scan-assembler-times "swpn r2" 6 } } */
+
new file mode 100644
@@ -0,0 +1,14 @@
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+
+unsigned short ior_1(unsigned short x) { return ((x&0xf0)>>4) | ((x&0x0f)<<4); }
+unsigned short xor_1(unsigned short x) { return ((x&0xf0)>>4) ^ ((x&0x0f)<<4); }
+unsigned short sum_1(unsigned short x) { return ((x&0xf0)>>4) + ((x&0x0f)<<4); }
+
+unsigned short ior_2(unsigned short x) { return ((x&0x0f)<<4) | ((x&0xf0)>>4); }
+unsigned short xor_2(unsigned short x) { return ((x&0x0f)<<4) ^ ((x&0xf0)>>4); }
+unsigned short sum_2(unsigned short x) { return ((x&0x0f)<<4) + ((x&0xf0)>>4); }
+
+/* { dg-final { scan-assembler-times "swpn r2" 6 } } */
+/* { dg-final { scan-assembler-times "and r2,#255" 6 } } */
+
new file mode 100644
@@ -0,0 +1,28 @@
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+
+short ior_1(unsigned short x) {
+ return (signed char)(((x&0xf0)>>4) | ((x&0x0f)<<4));
+}
+
+short xor_1(unsigned short x) {
+ return (signed char)(((x&0xf0)>>4) ^ ((x&0x0f)<<4));
+}
+
+short sum_1(unsigned short x) {
+ return (signed char)(((x&0xf0)>>4) + ((x&0x0f)<<4));
+}
+
+short ior_2(unsigned short x) {
+ return (signed char)(((x&0x0f)<<4) | ((x&0xf0)>>4));
+}
+
+short xor_2(unsigned short x) {
+ return (signed char)(((x&0x0f)<<4) ^ ((x&0xf0)>>4));
+}
+
+short sum_2(unsigned short x) {
+ return (signed char)(((x&0x0f)<<4) + ((x&0xf0)>>4));
+}
+
+/* { dg-final { scan-assembler-times "cbw" 6 } } */
new file mode 100644
@@ -0,0 +1,25 @@
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+
+short ior_abc(short x) { return (x&0xff00) | ((x<<4)&0xf0) | ((x>>4)&0x0f); }
+short ior_acb(short x) { return (x&0xff00) | ((x>>4)&0x0f) | ((x<<4)&0xf0); }
+short ior_bac(short x) { return ((x<<4)&0xf0) | (x&0xff00) | ((x>>4)&0x0f); }
+short ior_bca(short x) { return ((x<<4)&0xf0) | ((x>>4)&0x0f) | (x&0xff00); }
+short ior_cab(short x) { return ((x>>4)&0x0f) | (x&0xff00) | ((x<<4)&0xf0); }
+short ior_cba(short x) { return ((x>>4)&0x0f) | ((x<<4)&0xf0) | (x&0xff00); }
+
+short xor_abc(short x) { return (x&0xff00) ^ ((x<<4)&0xf0) ^ ((x>>4)&0x0f); }
+short xor_acb(short x) { return (x&0xff00) ^ ((x>>4)&0x0f) ^ ((x<<4)&0xf0); }
+short xor_bac(short x) { return ((x<<4)&0xf0) ^ (x&0xff00) ^ ((x>>4)&0x0f); }
+short xor_bca(short x) { return ((x<<4)&0xf0) ^ ((x>>4)&0x0f) ^ (x&0xff00); }
+short xor_cab(short x) { return ((x>>4)&0x0f) ^ (x&0xff00) ^ ((x<<4)&0xf0); }
+short xor_cba(short x) { return ((x>>4)&0x0f) ^ ((x<<4)&0xf0) ^ (x&0xff00); }
+
+short sum_abc(short x) { return (x&0xff00) + ((x<<4)&0xf0) + ((x>>4)&0x0f); }
+short sum_acb(short x) { return (x&0xff00) + ((x>>4)&0x0f) + ((x<<4)&0xf0); }
+short sum_bac(short x) { return ((x<<4)&0xf0) + (x&0xff00) + ((x>>4)&0x0f); }
+short sum_bca(short x) { return ((x<<4)&0xf0) + ((x>>4)&0x0f) + (x&0xff00); }
+short sum_cab(short x) { return ((x>>4)&0x0f) + (x&0xff00) + ((x<<4)&0xf0); }
+short sum_cba(short x) { return ((x>>4)&0x0f) + ((x<<4)&0xf0) + (x&0xff00); }
+
+/* { dg-final { scan-assembler-times "swpn r2" 18 } } */