diff -upr gcc-4.3-20070921/gcc/config/sh/constraints.md tars/gcc-4.3-20070921/gcc/config/sh/constraints.md --- gcc-4.3-20070921/gcc/config/sh/constraints.md 2007-10-24 12:09:31.000000000 +0530 +++ tars/gcc-4.3-20070921/gcc/config/sh/constraints.md 2007-10-24 12:18:12.000000000 +0530 @@ -35,6 +35,8 @@ ;; M: 1 ;; N: 0 ;; P27: 1 | 2 | 8 | 16 +;; Pso: 1 | 2 | 4 | 8 | 16 | 32 | 64 | 128 +;; Psz: ~1 | ~2 | ~4 | ~8 | ~16 | ~32 | ~64 | ~128 ;; Q: pc relative load operand ;; Rxx: reserved for exotic register classes. ;; Sxx: extra memory (storage) constraints @@ -204,6 +206,30 @@ PIC_DIRECT_ADDR_P." (match_test "IS_NON_EXPLICIT_CONSTANT_P (op)")) +(define_constraint "Pso" + "Integer constant with a single bit set in its lower 8-bit." + (and (match_code "const_int") + (ior (match_test "ival == 1") + (match_test "ival == 2") + (match_test "ival == 4") + (match_test "ival == 8") + (match_test "ival == 16") + (match_test "ival == 32") + (match_test "ival == 64") + (match_test "ival == 128")))) + +(define_constraint "Psz" + "Integer constant with a single zero bit in the lower 8-bit." + (and (match_code "const_int") + (ior (match_test "~ival == 1") + (match_test "~ival == 2") + (match_test "~ival == 4") + (match_test "~ival == 8") + (match_test "~ival == 16") + (match_test "~ival == 32") + (match_test "~ival == 64") + (match_test "~ival == 128")))) + (define_memory_constraint "Sr0" "@internal" (and (match_test "memory_operand (op, GET_MODE (op))") diff -upr gcc-4.3-20070921/gcc/config/sh/sh.c tars/gcc-4.3-20070921/gcc/config/sh/sh.c --- gcc-4.3-20070921/gcc/config/sh/sh.c 2007-10-24 12:18:00.000000000 +0530 +++ tars/gcc-4.3-20070921/gcc/config/sh/sh.c 2007-10-24 12:18:12.000000000 +0530 @@ -676,6 +676,8 @@ print_operand_address (FILE *stream, rtx 'd' print a V2SF reg as dN instead of fpN. 'm' print a pair `base,offset' or `base,index', for LD and ST. 'U' Likewise for {LD,ST}{HI,LO}. + 'V' print the position of a single bit set. + 'W' print the position of a single bit cleared. 'u' prints the lowest 16 bits of CONST_INT, as an unsigned value. 'o' output an operator. */ @@ -883,6 +885,22 @@ print_operand (FILE *stream, rtx x, int } break; + case 'V': + { + int num = exact_log2 (INTVAL (x)); + gcc_assert (num >= 0); + fprintf (stream, "#%d", num); + } + break; + + case 'W': + { + int num = exact_log2 (~INTVAL (x)); + gcc_assert (num >= 0); + fprintf (stream, "#%d", num); + } + break; + case 'd': gcc_assert (GET_CODE (x) == REG && GET_MODE (x) == V2SFmode); diff -upr gcc-4.3-20070921/gcc/config/sh/sh.md tars/gcc-4.3-20070921/gcc/config/sh/sh.md --- gcc-4.3-20070921/gcc/config/sh/sh.md 2007-10-24 12:18:00.000000000 +0530 +++ tars/gcc-4.3-20070921/gcc/config/sh/sh.md 2007-10-24 12:18:12.000000000 +0530 @@ -3164,6 +3164,14 @@ label: andi %1, %2, %0" [(set_attr "type" "arith_media")]) +(define_insn "*andsi3_bclr" + [(set (match_operand:SI 0 "arith_reg_dest" "=r") + (and:SI (match_operand:SI 1 "arith_reg_operand" "%0") + (match_operand:SI 2 "const_int_operand" "Psz")))] + "TARGET_SH2A && satisfies_constraint_Psz (operands[2])" + "bclr\\t%W2,%0" + [(set_attr "type" "arith")]) + ;; If the constant is 255, then emit an extu.b instruction instead of an ;; and, since that will give better code. @@ -3246,6 +3254,14 @@ label: ori %1, %2, %0" [(set_attr "type" "arith_media")]) +(define_insn "*iorsi3_bset" + [(set (match_operand:SI 0 "arith_reg_dest" "=r") + (ior:SI (match_operand:SI 1 "arith_reg_operand" "%0") + (match_operand:SI 2 "const_int_operand" "Pso")))] + "TARGET_SH2A && satisfies_constraint_Pso (operands[2])" + "bset\\t%V2,%0" + [(set_attr "type" "arith")]) + (define_insn "iordi3" [(set (match_operand:DI 0 "arith_reg_dest" "=r,r") (ior:DI (match_operand:DI 1 "arith_reg_operand" "%r,r") diff -uprN gcc-4.3-20070921/gcc/testsuite/gcc.target/sh/sh2a-bclr.c tars/gcc-4.3-20070921/gcc/testsuite/gcc.target/sh/sh2a-bclr.c --- gcc-4.3-20070921/gcc/testsuite/gcc.target/sh/sh2a-bclr.c 1970-01-01 05:30:00.000000000 +0530 +++ tars/gcc-4.3-20070921/gcc/testsuite/gcc.target/sh/sh2a-bclr.c 2007-10-24 12:20:01.000000000 +0530 @@ -0,0 +1,63 @@ +/* Testcase to check generation of a SH2A specific instruction + "BCLR #imm3,Rn" */ + +/* { dg-do assemble {target sh*-*-*}} */ +/* { dg-options "-O1" } */ +/* { dg-skip-if "" { "sh*-*-*" } "*" "-m2a -m2a-nofpu -m2a-single + -m2a-single-only" } */ +/* { dg-final { scan-assembler "bclr"} } */ + +struct a +{ + char a, b; + short c; +}; + +/* This function generates the instruction "BCLR #imm3,Rn" only + on using optimization option "-O1" and above */ + +int +a2 () +{ + volatile int j; + volatile static struct a x = { 1, 66, ~1 }, y = + { + 1, 2, ~2}; + + if (j > 1) + return (x.a == y.a && (x.b & ~1) == y.b); + if (j > 2) + return (x.a == y.a && (x.b & ~2) == y.b); + if (j > 3) + return (x.a == y.a && (x.b & ~4) == y.b); + if (j > 4) + return (x.a == y.a && (x.b & ~8) == y.b); + if (j > 5) + return (x.a == y.a && (x.b & ~16) == y.b); + if (j > 6) + return (x.a == y.a && (x.b & ~32) == y.b); + if (j > 7) + return (x.a == y.a && (x.b & ~64) == y.b); + if (j > 8) + return (x.a == y.a && (x.b & ~128) == y.b); +} + +int +main () +{ + volatile unsigned char x; + + x &= 0xFE; + x &= 0xFD; + x &= 0xFB; + x &= 0xF7; + x &= 0xEF; + x &= 0xDF; + x &= 0xBF; + x &= 0x7F; + + if (!a2 ()) + return 0; +} + + diff -uprN gcc-4.3-20070921/gcc/testsuite/gcc.target/sh/sh2a-bset.c tars/gcc-4.3-20070921/gcc/testsuite/gcc.target/sh/sh2a-bset.c --- gcc-4.3-20070921/gcc/testsuite/gcc.target/sh/sh2a-bset.c 1970-01-01 05:30:00.000000000 +0530 +++ tars/gcc-4.3-20070921/gcc/testsuite/gcc.target/sh/sh2a-bset.c 2007-10-24 12:20:50.000000000 +0530 @@ -0,0 +1,62 @@ +/* Testcase to check generation of a SH2A specific instruction + "BSET #imm3,Rn" */ + +/* { dg-do assemble {target sh*-*-*}} */ +/* { dg-options "-O1" } */ +/* { dg-skip-if "" { "sh*-*-*" } "*" "-m2a -m2a-nofpu -m2a-single + -m2a-single-only" } */ +/* { dg-final { scan-assembler "bclr"} } */ + +struct a +{ + char a, b; + short c; +}; + +/* This function generates the instruction "BSET #imm3,Rn" only + on using optimization option "-O1" and above */ + +int +a2 () +{ + volatile int j; + volatile static struct a x = { 1, 66, ~1 }, y = + { + 1, 2, ~2}; + + if (j > 1) + return (x.a == y.a && (x.b | 1) == y.b); + if (j > 2) + return (x.a == y.a && (x.b | 2) == y.b); + if (j > 3) + return (x.a == y.a && (x.b | 4) == y.b); + if (j > 4) + return (x.a == y.a && (x.b | 8) == y.b); + if (j > 5) + return (x.a == y.a && (x.b | 16) == y.b); + if (j > 6) + return (x.a == y.a && (x.b | 32) == y.b); + if (j > 7) + return (x.a == y.a && (x.b | 64) == y.b); + if (j > 8) + return (x.a == y.a && (x.b | 128) == y.b); +} + +int +main () +{ + volatile unsigned char x; + + x |= 0x1; + x |= 0x2; + x |= 0x4; + x |= 0x8; + x |= 0x16; + x |= 0x32; + x |= 0x64; + x |= 0x128; + + if (!a2 ()) + return 0; +} +