diff --git a/gcc/config/stormy16/stormy16.md b/gcc/config/stormy16/stormy16.md index b2e86ee..be1ee04 100644 --- a/gcc/config/stormy16/stormy16.md +++ b/gcc/config/stormy16/stormy16.md @@ -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 "*_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);") + diff --git a/gcc/testsuite/gcc.target/xstormy16/swpn-1.c b/gcc/testsuite/gcc.target/xstormy16/swpn-1.c new file mode 100644 index 0000000..a2c9316 --- /dev/null +++ b/gcc/testsuite/gcc.target/xstormy16/swpn-1.c @@ -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 } } */ + diff --git a/gcc/testsuite/gcc.target/xstormy16/swpn-2.c b/gcc/testsuite/gcc.target/xstormy16/swpn-2.c new file mode 100644 index 0000000..f26c296 --- /dev/null +++ b/gcc/testsuite/gcc.target/xstormy16/swpn-2.c @@ -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 } } */ + diff --git a/gcc/testsuite/gcc.target/xstormy16/swpn-3.c b/gcc/testsuite/gcc.target/xstormy16/swpn-3.c new file mode 100644 index 0000000..6109c6a --- /dev/null +++ b/gcc/testsuite/gcc.target/xstormy16/swpn-3.c @@ -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 } } */ diff --git a/gcc/testsuite/gcc.target/xstormy16/swpn-4.c b/gcc/testsuite/gcc.target/xstormy16/swpn-4.c new file mode 100644 index 0000000..4a31dc6 --- /dev/null +++ b/gcc/testsuite/gcc.target/xstormy16/swpn-4.c @@ -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 } } */