This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: [PATCH,SH] Add SH2A new instructions


"Naveen H.S." <naveen.hs@kpitcummins.com> wrote:
>>> First of all, the patch can't be applied to the trunk cleanly.
>>> It seems that you missed the patch in the thread:
> Please find attached the modified patches sh2a (1-4).tar.bz2. The
> patch is applied on the latest GCC sources (gcc- 4.3-20070921). 
> 
>>> Please check again our coding standard:
> Thank you for the valuable comments. We have taken care of all the
> comments in the modified patch.

Could you send separate mails for separate patches next time?

sh2a2.patch can't be applied cleanly.  There are yet many problems
about coding standard, all over the patches.
Please check once more our coding standard.

A few examples from sh2a1.patch:
--- /gcc/config/sh/sh.c	2007-09-19 20:33:07.000000000 +0530
+++ /gcc/config/sh/sh.c	2007-10-01 14:00:25.000000000 +0530
[snip]
+static tree sh_handle_resbank_handler_attribute (tree *, tree, tree, int, bool *);
+static tree sh2a_handle_function_vector_handler_attribute (tree *, tree, tree, int, bool *);

All lines over about 75 columns should be wrapped.

> @@ -3710,7 +3753,7 @@ broken_move (rtx insn)
>  		&& FP_REGISTER_P (REGNO (SET_DEST (pat))))
>  	  && ! (TARGET_SH2A
>  		&& GET_MODE (SET_DEST (pat)) == SImode
> -		&& satisfies_constraint_I20 (SET_SRC (pat)))
> +                && satisfies_constraint_I20 (SET_SRC (pat)))
>  	  && ! satisfies_constraint_I08 (SET_SRC (pat)))
>  	return 1;
>      }

Don't replace a tab with spaces.  You use 8 spaces instead of a tab
at many places in your patches.  Use tabs for them.
Remove extra trailing spaces too.

> @@ -5750,7 +5793,16 @@ push_regs (HARD_REG_SET *mask, int inter
>        if (i != PR_REG
>  	  && (i != FPSCR_REG || ! skip_fpscr)
>  	  && TEST_HARD_REG_BIT (*mask, i))
> -	push (i);
> +           {
> +  	/* If the ISR has RESBANK attribute assigned, don't push any of the
> +   	   the following registers - R0-R14, MACH, MACL and GBR.  */
> +	  if (! (sh_cfun_resbank_handler_p ()
> +                   && (i >= FIRST_GENERAL_REG && i < LAST_GENERAL_REG)
> +                       || i == MACH_REG
> +                       || i == MACL_REG
> +                       || i == GBR_REG))
> +	  push (i);
> +  	}
>      }

Wrong indentation.
Enclose

  (i >= FIRST_GENERAL_REG && i < LAST_GENERAL_REG)
  || i == MACH_REG
  || i == MACL_REG
  || i == GBR_REG

with parenthesis to avoid a compile time warning.  Please
get a log when building and check all compiler warnings.

> @@ -7971,6 +8038,29 @@ const struct attribute_spec sh_attribute
>    { NULL,                0, 0, false, false, false, NULL }
>  };
>  
> +/* Handle an "resbank" attribute  */

Missing period.  s/an "resbank"/a "resbank"/

> --- /gcc/config/sh/sh.md	2007-09-12 09:16:53.000000000 +0530
> +++ /gcc/config/sh/sh.md	2007-10-01 13:17:54.000000000 +0530
[snip]
> +  return \"jsr/n\t@@(%O2,tbr)\";

Use \"jsr/n\\t@@(%O2,tbr)\".

One non coding standard issue in sh2a1.patch:
> @@ -7203,7 +7264,7 @@ sh_gimplify_va_arg_expr (tree valist, tr
>  	    }
>  	}
>  
> -      if (TARGET_SH4 || TARGET_SH2A_DOUBLE)
> +      if (TARGET_SH4 || TARGET_SH2A || TARGET_SH2A_DOUBLE)
>  	{
>  	  pass_as_float = ((TREE_CODE (eff_type) == REAL_TYPE && size <= 8)
>  			   || (TREE_CODE (eff_type) == COMPLEX_TYPE

Why is this needed?

sh2a2.patch adds a new file sh2a.md:
> --- /gcc/config/sh/sh.md        2007-10-01 16:56:42.000000000 +0530
> +++ /gcc/config/sh/sh.md        2007-10-01 17:00:53.000000000 +0530
> @@ -452,6 +452,7 @@
>  ;; DFA descriptions for the pipelines
> 
>  (include "sh1.md")
> +(include "sh2a.md")
>  (include "shmedia.md")
>  (include "sh4.md")

sh2a.md is not a DFA scheduling description in spite of the first
line of this hunk.  The contents of your sh2a.md could move to
sh.md.  BTW, it's desirable that every newly added instruction has
the corresponding testcase. 

sh2a2.patch has 3 logilally independent parts.  You could split it
into movi20s patch, sh2a T-bit insns patch and sh2a prefetch patch.

> --- /gcc/config/sh/sh.c	2007-10-01 16:56:40.000000000 +0530
> +++ /gcc/config/sh/sh.c	2007-10-01 17:00:31.000000000 +0530
> @@ -3753,8 +3753,8 @@ broken_move (rtx insn)
>  		&& FP_REGISTER_P (REGNO (SET_DEST (pat))))
>  	  && ! (TARGET_SH2A
>  		&& GET_MODE (SET_DEST (pat)) == SImode
> -               && satisfies_constraint_I20 (SET_SRC (pat))
> -               && satisfies_constraint_I28 (SET_SRC (pat)))
> +                && satisfies_constraint_I20 (SET_SRC (pat))
> +                && satisfies_constraint_I28 (SET_SRC (pat)))
>  	  && ! satisfies_constraint_I08 (SET_SRC (pat)))

Broken hunk.  It would be

-		&& satisfies_constraint_I20 (SET_SRC (pat))
+		&& (satisfies_constraint_I20 (SET_SRC (pat))
+		    || satisfies_constraint_I28 (SET_SRC (pat))))

> --- /gcc/config/sh/constraints.md	2007-10-01 16:56:39.000000000 +0530
> +++ /gcc/config/sh/constraints.md	2007-10-01 14:34:00.000000000 +0530
[snip]
> +(define_constraint "I28"
> +  "A signed 28-bit constant, as used in SH2A movi20s."
> +  (and (match_code "const_int")
> +       (match_test "ival >=  -134217728 && ival <= 134217727 && ((ival & 0x000000FF) == 0)")
> +       (match_test "TARGET_SH2A")))

You could avoid the long line with

  (and (match_code "const_int")
       (match_test "ival >=  -134217728 && ival <= 134217727")
       (match_test "(ival & 255) == 0")
       (match_test "TARGET_SH2A"))

for example.

sh2a3.patch could use simple constraints instead of complex
predicates:

diff -uprN ORIG/trunk/gcc/config/sh/sh.c TMP/trunk/gcc/config/sh/sh.c
--- ORIG/trunk/gcc/config/sh/constraints.md	2007-10-11 06:57:12.000000000 +0900
+++ TMP/trunk/gcc/config/sh/constraints.md	2007-10-13 08:50:21.000000000 +0900
@@ -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
@@ -143,6 +145,30 @@
   (and (match_code "const_int")
        (match_test "ival == 1 || ival == 2 || ival == 8 || ival == 16")))
 
+(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_constraint "M"
   "Integer constant 1."
   (and (match_code "const_int")

diff -uprN ORIG/trunk/gcc/config/sh/sh.c TMP/trunk/gcc/config/sh/sh.c
--- ORIG/trunk/gcc/config/sh/sh.c	2007-10-11 06:55:21.000000000 +0900
+++ TMP/trunk/gcc/config/sh/sh.c	2007-10-13 10:09:04.000000000 +0900
@@ -655,6 +655,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.  */
 
@@ -873,6 +874,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 -uprN ORIG/trunk/gcc/config/sh/sh.md TMP/trunk/gcc/config/sh/sh.md
--- ORIG/trunk/gcc/config/sh/sh.md	2007-10-11 09:07:32.000000000 +0900
+++ TMP/trunk/gcc/config/sh/sh.md	2007-10-13 09:18:56.000000000 +0900
@@ -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")


sh2a4.patch looks most problematic.  It seems that there are too
many issues.  First of all, the trunk is not even compiled with it:

.../gcc/config/sh/sh2a.md:104: error: undefined machine-specific constraint at this point: "K03"

sh2a.md:

* If define_insn has a C statement part, it should return a value.
The C statement parts of bclr2, bset2, bst1, bst_mem, bld_mem, bld_mem1,
bldnot1, bit_cst and bnot_cst have no terminating return statements.

* bclr2, bset2, bst1, bst_mem, bld_mem and bldnot1 have null constraints
for memory operands.  This will cause reload problems. 

* bst3, bst_mem, bld_reg, bld_mem1, bldnot1, bit_reg, bit_cst and
bnot_cst may implicitly clobber T_REG.

* bclr2, bset2, bst3, bst_mem, bld_reg, bld_mem1, bldnot1, bit_reg,
bit_cst and bnot_cst may generate multiple instructions as text.

* The length of insn isn't set at all.

sh.md:

* It looks that the patch takes care of 2-bit field in the insv
expander but does something odd.

* The patch doesn't handle the sign extension at all in the extv
expander.

sh.c:

* You add the operand format %cN which is reserved by output_asm_insn.

I think that sh2a4.patch should be completely rewritten.
I've attached a simple patch implementing SH2A bitwise instructions.
This patch is standalone and tested against the C testsuite with no
regressions at -m2a.  It also enables SH2A 4-byte mov.b instructions.
I've tried to use bxxx insns for 2-bit fields, but dropped that part
from the patch.  It increased not only memory accesses but also
the code size in some cases.  A typical example is

struct a { unsigned int x: 4, k: 2, y: 26; };
void foo (struct a *p)
{
  (p+5)->x = 21;
  (p+5)->k = 0;
  (p+5)->y = 0x200000;
}

I've kept b{and,or}{not,} and bxor insns in the patch, though I
suspect that the current compiler can never use these insns.
If this is the case, they should be removed.

You should confirm that the use of SH2A bitwise operations doesn't
cause performance/size regressions with real applications.  If it's
hard to prove, the use of bitwise operations should be controled
with the option -mbitops or some such which is off by default.

Regards,
	kaz
--
diff --exclude=.svn -uprN ORIG/trunk/gcc/config/sh/constraints.md TMP/trunk/gcc/config/sh/constraints.md
--- ORIG/trunk/gcc/config/sh/constraints.md	2007-10-08 15:36:38.000000000 +0900
+++ TMP/trunk/gcc/config/sh/constraints.md	2007-10-11 06:57:12.000000000 +0900
@@ -39,6 +39,7 @@
 ;; Rxx: reserved for exotic register classes.
 ;; Sxx: extra memory (storage) constraints
 ;;  Sua: unaligned memory operations
+;;  Sbw: sh2a bitwise memory operations
 ;; W: vector
 ;; Z: zero in any mode
 ;;
@@ -117,11 +118,21 @@
   (and (match_code "const_int")
        (match_test "CONST_OK_FOR_J16 (ival)")))
 
+(define_constraint "K03"
+  "An unsigned 3-bit constant, as used in SH2A bclr, bset, etc."
+  (and (match_code "const_int")
+       (match_test "ival >= 0 && ival <= 7")))
+ 
 (define_constraint "K08"
   "An unsigned 8-bit constant, as used in and, or, etc."
   (and (match_code "const_int")
        (match_test "ival >= 0 && ival <= 255")))
  
+(define_constraint "K12"
+  "An unsigned 8-bit constant, as used in SH2A 12-bit display."
+  (and (match_code "const_int")
+       (match_test "ival >= 0 && ival <= 4095")))
+ 
 (define_constraint "K16"
   "An unsigned 16-bit constant, as used in SHmedia shori."
   (and (match_code "const_int")
@@ -207,3 +218,10 @@
   "@internal"
   (and (match_test "memory_operand (op, GET_MODE (op))")
        (match_test "GET_CODE (XEXP (op, 0)) != PLUS")))
+
+(define_memory_constraint "Sbw"
+  "A memory reference, as used in SH2A bclr.b, bset.b, etc."
+  (and (match_test "MEM_P (op) && GET_MODE (op) == QImode")
+       (match_test "GET_CODE (XEXP (op, 0)) == PLUS")
+       (match_test "REG_P (XEXP (XEXP (op, 0), 0))")
+       (match_test "satisfies_constraint_K12 (XEXP (XEXP (op, 0), 1))")))
diff --exclude=.svn -uprN ORIG/trunk/gcc/config/sh/predicates.md TMP/trunk/gcc/config/sh/predicates.md
--- ORIG/trunk/gcc/config/sh/predicates.md	2007-10-08 15:36:38.000000000 +0900
+++ TMP/trunk/gcc/config/sh/predicates.md	2007-10-11 06:56:30.000000000 +0900
@@ -789,3 +789,22 @@
     return 0;
   return arith_reg_operand (op, mode);
 })
+
+;; Return 1 if OP is a valid destination operand for sh2a bitwise
+;; memory operations.
+
+(define_predicate "bitwise_memory_operand"
+  (match_code "mem")
+{
+  if (GET_CODE (op) == MEM)
+    {
+      if (REG_P (XEXP (op, 0)))
+	return 1;
+
+      if (GET_CODE (XEXP (op, 0)) == PLUS
+	  && GET_CODE (XEXP (XEXP (op, 0), 0)) == REG
+	  && satisfies_constraint_K12 (XEXP (XEXP (op, 0), 1)))
+        return 1;
+    }
+  return 0;
+})
diff --exclude=.svn -uprN ORIG/trunk/gcc/config/sh/sh.c TMP/trunk/gcc/config/sh/sh.c
--- ORIG/trunk/gcc/config/sh/sh.c	2007-10-08 15:36:38.000000000 +0900
+++ TMP/trunk/gcc/config/sh/sh.c	2007-10-11 06:55:21.000000000 +0900
@@ -656,6 +656,7 @@ print_operand_address (FILE *stream, rtx
    'm'  print a pair `base,offset' or `base,index', for LD and ST.
    'U'  Likewise for {LD,ST}{HI,LO}.
    'u'  prints the lowest 16 bits of CONST_INT, as an unsigned value.
+   't'  print a memory address which is a register.
    'o'  output an operator.  */
 
 void
@@ -790,6 +791,21 @@ print_operand (FILE *stream, rtx x, int 
 	  break;
 	}
       break;
+
+    case 't':
+      gcc_assert (GET_CODE (x) == MEM);
+      x = XEXP (x, 0);
+      switch (GET_CODE (x))
+	{
+	case REG:
+	case SUBREG:
+	  print_operand (stream, x, 0);
+	  break;
+	default:
+	  break;
+	}
+      break;
+
     case 'o':
       switch (GET_CODE (x))
 	{
diff --exclude=.svn -uprN ORIG/trunk/gcc/config/sh/sh.h TMP/trunk/gcc/config/sh/sh.h
--- ORIG/trunk/gcc/config/sh/sh.h	2007-10-08 15:36:38.000000000 +0900
+++ TMP/trunk/gcc/config/sh/sh.h	2007-10-10 08:13:34.000000000 +0900
@@ -2459,6 +2459,12 @@ struct sh_args {
 	    else							\
 	      break;							\
 	  }								\
+	if (TARGET_SH2A)						\
+	  {								\
+	    if (GET_MODE_SIZE (MODE) == 1				\
+		&& (unsigned) INTVAL (OP) < 4096)			\
+	    goto LABEL;							\
+	  }								\
 	if (MODE_DISP_OK_4 ((OP), (MODE)))  goto LABEL;		      	\
 	if (MODE_DISP_OK_8 ((OP), (MODE)))  goto LABEL;		      	\
       }									\
diff --exclude=.svn -uprN ORIG/trunk/gcc/config/sh/sh.md TMP/trunk/gcc/config/sh/sh.md
--- ORIG/trunk/gcc/config/sh/sh.md	2007-10-08 15:36:38.000000000 +0900
+++ TMP/trunk/gcc/config/sh/sh.md	2007-10-12 08:18:27.000000000 +0900
@@ -4692,7 +4692,12 @@ label:
   "@
 	exts.b	%1,%0
 	mov.b	%1,%0"
-  [(set_attr "type" "arith,load")])
+  [(set_attr "type" "arith,load")
+   (set_attr_alternative "length"
+     [(const_int 2)
+       (if_then_else
+	(ne (symbol_ref "TARGET_SH2A") (const_int 0))
+	(const_int 4) (const_int 2))])])
 
 (define_insn "*extendqisi2_media"
   [(set (match_operand:SI 0 "register_operand" "=r,r")
@@ -4730,7 +4735,12 @@ label:
   "@
 	exts.b	%1,%0
 	mov.b	%1,%0"
-  [(set_attr "type" "arith,load")])
+  [(set_attr "type" "arith,load")
+   (set_attr_alternative "length"
+     [(const_int 2)
+       (if_then_else
+	(ne (symbol_ref "TARGET_SH2A") (const_int 0))
+	(const_int 4) (const_int 2))])])
 
 /* It would seem useful to combine the truncXi patterns into the movXi
    patterns, but unary operators are ignored when matching constraints,
@@ -5276,7 +5286,19 @@ label:
 	movt	%0
 	sts	%1,%0
 	lds	%1,%0"
- [(set_attr "type" "move,movi8,load,store,arith,prget,prset")])
+ [(set_attr "type" "move,movi8,load,store,arith,prget,prset")
+  (set_attr_alternative "length"
+     [(const_int 2)
+      (const_int 2)
+      (if_then_else
+	(ne (symbol_ref "TARGET_SH2A") (const_int 0))
+	(const_int 4) (const_int 2))
+      (if_then_else
+	(ne (symbol_ref "TARGET_SH2A") (const_int 0))
+	(const_int 4) (const_int 2))
+      (const_int 2)
+      (const_int 2)
+      (const_int 2)])])
 
 (define_insn "*movqi_media"
   [(set (match_operand:QI 0 "general_movdst_operand" "=r,r,r,m")
@@ -11497,6 +11519,35 @@ mov.l\\t1f,r0\\n\\
   HOST_WIDE_INT bitsize, size, v = 0;
   rtx x = operands[3];
 
+  if (TARGET_SH2A
+      && satisfies_constraint_M (operands[1])
+      && satisfies_constraint_K03 (operands[2]))
+    {
+      if (satisfies_constraint_N (operands[3]))
+	{
+	  emit_insn (gen_bclr_m2a (operands[0], operands[2]));
+	  DONE;
+        }
+      else if (satisfies_constraint_M (operands[3]))
+	{
+	  emit_insn (gen_bset_m2a (operands[0], operands[2]));
+	  DONE;
+	}
+      else if ((REG_P (operands[3]) && REGNO (operands[3]) == T_REG)
+	       && satisfies_constraint_M (operands[1]))
+	{
+	  emit_insn (gen_bst_m2a (operands[0], operands[2]));
+	  DONE;
+	}
+      else if (REG_P (operands[3])
+	       && satisfies_constraint_M (operands[1]))
+	{
+	  emit_insn (gen_bld_reg (operands[3], const0_rtx));
+	  emit_insn (gen_bst_m2a (operands[0], operands[2]));
+	  DONE;
+	}
+    }
+
   /* ??? expmed doesn't care for non-register predicates.  */
   if (! memory_operand (operands[0], VOIDmode)
       || ! immediate_operand (operands[1], VOIDmode)
@@ -11595,8 +11646,18 @@ mov.l\\t1f,r0\\n\\
 	(zero_extract:SI (match_operand:QI 1 "unaligned_load_operand" "")
 			 (match_operand 2 "const_int_operand" "")
 			 (match_operand 3 "const_int_operand" "")))]
-  "TARGET_SH4A_ARCH"
+  "TARGET_SH4A_ARCH || TARGET_SH2A"
 {
+  if (TARGET_SH2A
+      && satisfies_constraint_M (operands[2])
+      && satisfies_constraint_K03 (operands[3]))
+    {
+      emit_insn (gen_bld_m2a (operands[1], operands[3]));
+      if (REGNO (operands[0]) != T_REG)
+	emit_insn (gen_movsi (operands[0], gen_rtx_REG (SImode, T_REG)));
+      DONE;
+    }
+
   if (TARGET_SH4A_ARCH
       && INTVAL (operands[2]) == 32
       && INTVAL (operands[3]) == -24 * (BITS_BIG_ENDIAN != BYTES_BIG_ENDIAN)
@@ -11611,6 +11672,168 @@ mov.l\\t1f,r0\\n\\
   FAIL;
 })
 
+;; SH2A instructions for bitwise operations.
+
+;; Clear a bit in a memory location.
+(define_insn "bclr_m2a"
+  [(set (match_operand:QI 0 "bitwise_memory_operand" "+Sbw,m")
+	(and:QI
+	    (not:QI (ashift:QI (const_int 1)
+			(match_operand:QI 1 "const_int_operand" "K03,K03")))
+	    (match_dup 0)))]
+  "TARGET_SH2A"
+  "@
+	bclr.b\\t%1,%0
+	bclr.b\\t%1,@(0,%t0)"
+  [(set_attr "length" "4,4")])
+
+;; Set a bit in a memory location.
+(define_insn "bset_m2a"
+  [(set (match_operand:QI 0 "bitwise_memory_operand" "+Sbw,m")
+	(ior:QI
+	    (ashift:QI (const_int 1)
+			(match_operand:QI 1 "const_int_operand" "K03,K03"))
+	    (match_dup 0)))]
+  "TARGET_SH2A"
+  "@
+	bset.b\\t%1,%0
+	bset.b\\t%1,@(0,%t0)"
+  [(set_attr "length" "4")])
+
+;; Transfer the contents of the T bit to a specified bit of memory.
+(define_insn "bst_m2a"
+  [(set (match_operand:QI 0 "bitwise_memory_operand" "+Sbw,m")
+	(if_then_else (eq (reg:SI T_REG) (const_int 0))
+	    (and:QI
+		(not:QI (ashift:QI (const_int 1)
+			(match_operand:QI 1 "const_int_operand" "K03,K03")))
+		(match_dup 0))
+	    (ior:QI
+		(ashift:QI (const_int 1) (match_dup 1))
+		(match_dup 0))))]
+  "TARGET_SH2A"
+  "@
+	bst.b\\t%1,%0
+	bst.b\\t%1,@(0,%t0)"
+  [(set_attr "length" "4")])
+
+;; Store a specified bit of memory in the T bit.
+(define_insn "bld_m2a"
+  [(set (reg:SI T_REG)
+	(zero_extract:SI
+	    (match_operand:QI 0 "bitwise_memory_operand" "Sbw,m")
+	    (const_int 1)
+	    (match_operand 1 "const_int_operand" "K03,K03")))]
+  "TARGET_SH2A"
+  "@
+	bld.b\\t%1,%0
+	bld.b\\t%1,@(0,%t0)"
+  [(set_attr "length" "4,4")])
+
+;; Store a specified bit of the LSB 8 bits of a register in the T bit.
+(define_insn "bld_reg"
+  [(set (reg:SI T_REG)
+	(zero_extract:SI (match_operand:SI 0 "arith_reg_operand" "r")
+			 (const_int 1)
+			 (match_operand 1 "const_int_operand" "K03")))]
+  "TARGET_SH2A"
+  "bld\\t%1,%0")
+
+(define_insn "*bld_regqi"
+  [(set (reg:SI T_REG)
+	(zero_extract:SI (match_operand:QI 0 "arith_reg_operand" "r")
+			 (const_int 1)
+			 (match_operand 1 "const_int_operand" "K03")))]
+  "TARGET_SH2A"
+  "bld\\t%1,%0")
+
+;; Store logical inverse of a specified bit of memory in the T bit.
+(define_insn "bldnot_m2a"
+  [(set (reg:SI T_REG)
+	(not:SI (zero_extract:SI
+	    (match_operand:QI 0 "bitwise_memory_operand" "Sbw,m")
+	    (const_int 1)
+	    (match_operand 1 "const_int_operand" "K03,K03"))))]
+  "TARGET_SH2A"
+  "@
+	bldnot.b\\t%1,%0
+	bldnot.b\\t%1,@(0,%t0)"
+  [(set_attr "length" "4,4")])
+
+;; Take logical and of a specified bit of memory with the T bit and
+;; store its result in the T bit.
+(define_insn "band_m2a"
+  [(set (reg:SI T_REG)
+	(and:SI (reg:SI T_REG)
+		(zero_extract:SI
+		    (match_operand:QI 0 "bitwise_memory_operand" "Sbw,m")
+		    (const_int 1)
+		    (match_operand 1 "const_int_operand" "K03,K03"))))]
+  "TARGET_SH2A"
+  "@
+	band.b\\t%1,%0
+	band.b\\t%1,@(0,%t0)"
+  [(set_attr "length" "4,4")])
+
+;; Take logical and of logical inverse of a specified bit of memory
+;; with the T bit and store its result in the T bit.
+(define_insn "bandnot_m2a"
+  [(set (reg:SI T_REG)
+	(and:SI (reg:SI T_REG)
+		(not:SI (zero_extract:SI
+		    (match_operand:QI 0 "bitwise_memory_operand" "Sbw,m")
+		    (const_int 1)
+		    (match_operand 1 "const_int_operand" "K03,K03")))))]
+  "TARGET_SH2A"
+  "@
+	bandnot.b\\t%1,%0
+	bandnot.b\\t%1,@(0,%t0)"
+  [(set_attr "length" "4,4")])
+
+;; Take logical or of a specified bit of memory with the T bit and
+;; store its result in the T bit.
+(define_insn "bor_m2a"
+  [(set (reg:SI T_REG)
+	(ior:SI (reg:SI T_REG)
+		(zero_extract:SI
+		    (match_operand:QI 0 "bitwise_memory_operand" "Sbw,m")
+		    (const_int 1)
+		    (match_operand 1 "const_int_operand" "K03,K03"))))]
+  "TARGET_SH2A"
+  "@
+	bor.b\\t%1,%0
+	bor.b\\t%1,@(0,%t0)"
+  [(set_attr "length" "4,4")])
+
+;; Take logical or of logical inverse of a specified bit of memory
+;; with the T bit and store its result in the T bit.
+(define_insn "bornot_m2a"
+  [(set (reg:SI T_REG)
+	(ior:SI (reg:SI T_REG)
+		(not:SI (zero_extract:SI
+		    (match_operand:QI 0 "bitwise_memory_operand" "Sbw,m")
+		    (const_int 1)
+		    (match_operand 1 "const_int_operand" "K03,K03")))))]
+  "TARGET_SH2A"
+  "@
+	bornot.b\\t%1,%0
+	bornot.b\\t%1,@(0,%t0)"
+  [(set_attr "length" "4,4")])
+
+;; Take exclusive or of a specified bit of memory with the T bit and
+;; store its result in the T bit.
+(define_insn "bxor_m2a"
+  [(set (reg:SI T_REG)
+	(xor:SI (reg:SI T_REG)
+		(zero_extract:SI
+		    (match_operand:QI 0 "bitwise_memory_operand" "Sbw,m")
+		    (const_int 1)
+		    (match_operand 1 "const_int_operand" "K03,K03"))))]
+  "TARGET_SH2A"
+  "@
+	bxor.b\\t%1,%0
+	bxor.b\\t%1,@(0,%t0)"
+  [(set_attr "length" "4,4")])
 
 ;; -------------------------------------------------------------------------
 ;; Peepholes


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]