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]

[PATCH][RX] v2 instructions support.


Add RX v2 enhancement instructions support.

gcc/ChangeLog
2015/12/10  Yoshinori Sato  <ysato@users.sourceforge.jp>

	* config/rx/constraints.md: Add constraint "q".
	* doc/md.texi: Likewise.
	* config/rx/rx-opts.h(rx_cpu_types): Add type RXV2.
	* config/rx/rx.c(rx_print_operand): Add a0, a1 and extb.
	(rx_expand_prologue): Use v2 instraction.
	(rx_expand_epilogue): Likewise.
	(rx_builtin): Add v2 instruction.
	(rx_expand_builtin): Likewise.
	(rx_expand_builtin_mac): 3 operand support.
	(rx_expand_int_builtin_1_arg): Likewise.
	(rx_expand_int_builtin_0_arg): Delete.
	(rx_expand_builtin_mac2): New function.
	(rx_expand_builtin_fromacc): Likewise.
	(rx_expand_builtin_fromacc2): Likewise.
	(rx_expand_builtin_toacc): Likewise.
	(rx_expand_builtin_toacc2): Likewise.
	(rx_expand_builtin_rac): Likewise.
	* config/rx/rx.h(TARGET_CPU_CPP_BUILTINS): Add v2 define.
	(ALLOW_RXV2_INSNS): New.
	* config/rx/rx.md(constants): Add new builtin enum.
	(addsf3): 3 operands support.
	(mulsf3): Likewise.
	(subsf3): Likewise.
	(fixuns_truncsfsi2): New.
	(floatunssisf2): Likewise.
	(sqrtsf2): Likewise.
	(machi): 3 operands support.
	(maclo): Likewise.
	(mulhi): Likewise.
	(mullo): Likewise.
	(mvfachi): Likewise.
 	(mvfacmi): Likewise.
	(mvtachi): Likewise.
	(mvtaclo): Likewise.
	(racw): Likewise.
	(mvfacgu): New.
	(mvfaclo): Likewise.
	(racl): Likewise.
	(rdacl): Likewise.
	(rdacw): Likewise.
	(emaca): Likewise.
	(emsba): Likewise.
	(maclh): Likewise.
	(msbhi): Likewise.
	(msblo): Likewise.
	(msblh): Likewise.
	* config/rx/sync.md: New file.
	* config/rx/rx.opt: Add rxv2 for mcpu option.
	* config/rx/t-rx: Add v2 for multilib

---
 gcc/config/rx/constraints.md |   7 +
 gcc/config/rx/rx-opts.h      |   3 +-
 gcc/config/rx/rx.c           | 425 +++++++++++++++++++++++++++++++++++++------
 gcc/config/rx/rx.h           |   7 +
 gcc/config/rx/rx.md          | 363 +++++++++++++++++++++++++++++++++---
 gcc/config/rx/rx.opt         |   3 +
 gcc/config/rx/sync.md        | 191 +++++++++++++++++++
 gcc/config/rx/t-rx           |   2 +
 gcc/doc/md.texi              |   2 +
 9 files changed, 915 insertions(+), 88 deletions(-)
 create mode 100644 gcc/config/rx/sync.md

diff --git a/gcc/config/rx/constraints.md b/gcc/config/rx/constraints.md
index b41c232..e388350 100644
--- a/gcc/config/rx/constraints.md
+++ b/gcc/config/rx/constraints.md
@@ -106,3 +106,10 @@
        )
   )
 )
+
+(define_memory_constraint "q"
+  "A MEM which only uses REG addressing."
+  (and (match_code "mem")
+    (match_code "reg" "0")
+  )
+)
diff --git a/gcc/config/rx/rx-opts.h b/gcc/config/rx/rx-opts.h
index fa83e91..52d4dce 100644
--- a/gcc/config/rx/rx-opts.h
+++ b/gcc/config/rx/rx-opts.h
@@ -25,7 +25,8 @@ enum rx_cpu_types
   RX600,
   RX610,
   RX200,
-  RX100
+  RX100,
+  RXV2
 };
 
 #endif
diff --git a/gcc/config/rx/rx.c b/gcc/config/rx/rx.c
index 781b6b1..7b35308 100644
--- a/gcc/config/rx/rx.c
+++ b/gcc/config/rx/rx.c
@@ -639,6 +639,19 @@ rx_print_operand (FILE * file, rtx op, int letter)
 	case 0xa: fprintf (file, "isp"); break;
 	case 0xb: fprintf (file, "fintv"); break;
 	case 0xc: fprintf (file, "intb"); break;
+	case 0xd:
+	  if (ALLOW_RXV2_INSNS)
+	    {
+	      fprintf (file, "extb"); break;
+	    }
+	    goto invalid_register;
+	case 0x40:
+	case 0x41:
+	  if (ALLOW_RXV2_INSNS)
+	    {
+	      fprintf (file, "a%ld", INTVAL(op) - 0x40); break;
+	    } /* RXv1 fall through */
+	invalid_register:
 	default:
 	  warning (0, "unrecognized control register number: %d - using 'psw'",
 		   (int) INTVAL (op));
@@ -731,6 +744,11 @@ rx_print_operand (FILE * file, rtx op, int letter)
       fprintf (file, "%s", reg_names [rx_pid_base_regnum ()]);
       break;
 
+    case 'V':
+      gcc_assert (CONST_INT_P (op));
+      fprintf (file, "a%ld", INTVAL(op));
+      break;
+
     case 'R':
       gcc_assert (GET_MODE_SIZE (GET_MODE (op)) <= 4);
       unsigned_load = true;
@@ -1772,12 +1790,32 @@ rx_expand_prologue (void)
 	  /* We have assumed that there are at least two registers pushed... */
 	  gcc_assert (acc_high != 0);
 
-	  /* Note - the bottom 16 bits of the accumulator are inaccessible.
-	     We just assume that they are zero.  */
-	  emit_insn (gen_mvfacmi (gen_rtx_REG (SImode, acc_low)));
-	  emit_insn (gen_mvfachi (gen_rtx_REG (SImode, acc_high)));
-	  emit_insn (gen_stack_push (gen_rtx_REG (SImode, acc_low)));
-	  emit_insn (gen_stack_push (gen_rtx_REG (SImode, acc_high)));
+	  if (!ALLOW_RXV2_INSNS)
+	    {
+	      /* Note - the bottom 16 bits of the accumulator are inaccessible.
+		 We just assume that they are zero.  */
+	      emit_insn ( gen_mvfacmi (
+			 gen_rtx_REG (SImode, acc_low), GEN_INT(0), GEN_INT(64)));
+	      emit_insn (gen_mvfachi (
+			 gen_rtx_REG (SImode, acc_high), GEN_INT(0), GEN_INT(64)));
+	      emit_insn (gen_stack_push (gen_rtx_REG (SImode, acc_low)));
+	      emit_insn (gen_stack_push (gen_rtx_REG (SImode, acc_high)));
+	    }
+	  else
+	    {
+	      emit_insn ( gen_mvfaclo (
+			 gen_rtx_REG (SImode, acc_low), GEN_INT(0), GEN_INT(64)));
+	      emit_insn (gen_mvfachi (
+			 gen_rtx_REG (SImode, acc_high), GEN_INT(0), GEN_INT(64)));
+	      emit_insn (gen_stack_push (gen_rtx_REG (SImode, acc_low)));
+	      emit_insn (gen_stack_push (gen_rtx_REG (SImode, acc_high)));
+	      emit_insn ( gen_mvfaclo (
+			 gen_rtx_REG (SImode, acc_low), GEN_INT(0), GEN_INT(65)));
+	      emit_insn (gen_mvfachi (
+			 gen_rtx_REG (SImode, acc_high), GEN_INT(0), GEN_INT(65)));
+	      emit_insn (gen_stack_push (gen_rtx_REG (SImode, acc_low)));
+	      emit_insn (gen_stack_push (gen_rtx_REG (SImode, acc_high)));
+	    }
 	}
       else
 	{
@@ -1787,10 +1825,30 @@ rx_expand_prologue (void)
 	  /* We have assumed that there are at least two registers pushed... */
 	  gcc_assert (acc_high <= high);
 
-	  emit_insn (gen_mvfacmi (gen_rtx_REG (SImode, acc_low)));
-	  emit_insn (gen_mvfachi (gen_rtx_REG (SImode, acc_high)));
-	  emit_insn (gen_stack_pushm (GEN_INT (2 * UNITS_PER_WORD),
-				      gen_rx_store_vector (acc_low, acc_high)));
+	  if (!ALLOW_RXV2_INSNS)
+	    {
+	      emit_insn (gen_mvfacmi (
+			 gen_rtx_REG (SImode, acc_low), GEN_INT(0), GEN_INT(64)));
+	      emit_insn (gen_mvfachi (
+			 gen_rtx_REG (SImode, acc_high), GEN_INT(0), GEN_INT(64)));
+	      emit_insn (gen_stack_pushm (GEN_INT (2 * UNITS_PER_WORD),
+					  gen_rx_store_vector (acc_low, acc_high)));
+	    }
+	  else
+	    {
+	      emit_insn (gen_mvfacmi (
+			 gen_rtx_REG (SImode, acc_low), GEN_INT(0), GEN_INT(64)));
+	      emit_insn (gen_mvfachi (
+			 gen_rtx_REG (SImode, acc_high), GEN_INT(0), GEN_INT(64)));
+	      emit_insn (gen_stack_pushm (GEN_INT (2 * UNITS_PER_WORD),
+					  gen_rx_store_vector (acc_low, acc_high)));
+	      emit_insn (gen_mvfacmi (
+			 gen_rtx_REG (SImode, acc_low), GEN_INT(0), GEN_INT(65)));
+	      emit_insn (gen_mvfachi (
+			 gen_rtx_REG (SImode, acc_high), GEN_INT(0), GEN_INT(65)));
+	      emit_insn (gen_stack_pushm (GEN_INT (2 * UNITS_PER_WORD),
+					  gen_rx_store_vector (acc_low, acc_high)));
+	    }
 	}
     }
 
@@ -2100,41 +2158,83 @@ rx_expand_epilogue (bool is_sibcall)
       if (MUST_SAVE_ACC_REGISTER)
 	{
 	  unsigned int acc_low, acc_high;
-
-	  /* Reverse the saving of the accumulator register onto the stack.
-	     Note we must adjust the saved "low" accumulator value as it
-	     is really the middle 32-bits of the accumulator.  */
-	  if (register_mask)
+	  if (!ALLOW_RXV2_INSNS)
 	    {
-	      acc_low = acc_high = 0;
+	      /* Reverse the saving of the accumulator register onto the stack.
+		 Note we must adjust the saved "low" accumulator value as it
+		 is really the middle 32-bits of the accumulator.  */
+	      if (register_mask)
+		{
+		  acc_low = acc_high = 0;
 
-	      for (reg = 1; reg < CC_REGNUM; reg ++)
-		if (register_mask & (1 << reg))
-		  {
-		    if (acc_low == 0)
-		      acc_low = reg;
-		    else
+		  for (reg = 1; reg < CC_REGNUM; reg ++)
+		    if (register_mask & (1 << reg))
 		      {
-			acc_high = reg;
-			break;
+			if (acc_low == 0)
+			  acc_low = reg;
+			else
+			  {
+			    acc_high = reg;
+			    break;
+			  }
 		      }
-		  }
-	      emit_insn (gen_stack_pop (gen_rtx_REG (SImode, acc_high)));
-	      emit_insn (gen_stack_pop (gen_rtx_REG (SImode, acc_low)));
+		  emit_insn (gen_stack_pop (gen_rtx_REG (SImode, acc_high)));
+		  emit_insn (gen_stack_pop (gen_rtx_REG (SImode, acc_low)));
+		}
+	      else
+		{
+		  acc_low = low;
+		  acc_high = low + 1;
+		  emit_insn (gen_stack_popm (GEN_INT (2 * UNITS_PER_WORD),
+					     gen_rx_popm_vector (acc_low, acc_high)));
+		}
+
+	      emit_insn (gen_ashlsi3 (gen_rtx_REG (SImode, acc_low),
+				      gen_rtx_REG (SImode, acc_low),
+				      GEN_INT (16)));
+	      emit_insn (gen_mvtaclo (gen_rtx_REG (SImode, acc_low), GEN_INT(0)));
+	      emit_insn (gen_mvtachi (gen_rtx_REG (SImode, acc_high), GEN_INT(0)));
 	    }
 	  else
 	    {
-	      acc_low = low;
-	      acc_high = low + 1;
-	      emit_insn (gen_stack_popm (GEN_INT (2 * UNITS_PER_WORD),
-					 gen_rx_popm_vector (acc_low, acc_high)));
-	    }
+	      if (register_mask)
+		{
+		  acc_low = acc_high = 0;
 
-	  emit_insn (gen_ashlsi3 (gen_rtx_REG (SImode, acc_low),
-				  gen_rtx_REG (SImode, acc_low),
-				  GEN_INT (16)));
-	  emit_insn (gen_mvtaclo (gen_rtx_REG (SImode, acc_low)));
-	  emit_insn (gen_mvtachi (gen_rtx_REG (SImode, acc_high)));
+		  for (reg = 1; reg < CC_REGNUM; reg ++)
+		    if (register_mask & (1 << reg))
+		      {
+			if (acc_low == 0)
+			  acc_low = reg;
+			else
+			  {
+			    acc_high = reg;
+			    break;
+			  }
+		      }
+		  emit_insn (gen_stack_pop (gen_rtx_REG (SImode, acc_high)));
+		  emit_insn (gen_stack_pop (gen_rtx_REG (SImode, acc_low)));
+		  emit_insn (gen_mvtaclo (gen_rtx_REG (SImode, acc_low), GEN_INT(0)));
+		  emit_insn (gen_mvtachi (gen_rtx_REG (SImode, acc_high), GEN_INT(0)));
+		  emit_insn (gen_stack_pop (gen_rtx_REG (SImode, acc_high)));
+		  emit_insn (gen_stack_pop (gen_rtx_REG (SImode, acc_low)));
+		  emit_insn (gen_mvtaclo (gen_rtx_REG (SImode, acc_low), GEN_INT(1)));
+		  emit_insn (gen_mvtachi (gen_rtx_REG (SImode, acc_high), GEN_INT(1)));
+		}
+	      else
+		{
+		  acc_low = low;
+		  acc_high = low + 1;
+		  emit_insn (gen_stack_popm (GEN_INT (2 * UNITS_PER_WORD),
+					     gen_rx_popm_vector (acc_low, acc_high)));
+		  emit_insn (gen_mvtaclo (gen_rtx_REG (SImode, acc_low), GEN_INT(0)));
+		  emit_insn (gen_mvtachi (gen_rtx_REG (SImode, acc_high), GEN_INT(0)));
+		  emit_insn (gen_stack_popm (GEN_INT (2 * UNITS_PER_WORD),
+					     gen_rx_popm_vector (acc_low, acc_high)));
+		  emit_insn (gen_mvtaclo (gen_rtx_REG (SImode, acc_low), GEN_INT(1)));
+		  emit_insn (gen_mvtachi (gen_rtx_REG (SImode, acc_high), GEN_INT(1)));
+		}
+	    }
 	}
 
       if (register_mask)
@@ -2350,6 +2450,28 @@ enum rx_builtin
   RX_BUILTIN_ROUND,
   RX_BUILTIN_SETPSW,
   RX_BUILTIN_WAIT,
+  RX_BUILTIN_MACHI2,
+  RX_BUILTIN_MACLO2,
+  RX_BUILTIN_MULHI2,
+  RX_BUILTIN_MULLO2,
+  RX_BUILTIN_MVFACHI2,
+  RX_BUILTIN_MVFACMI2,
+  RX_BUILTIN_MVTACHI2,
+  RX_BUILTIN_MVTACLO2,
+  RX_BUILTIN_RACW2,
+  RX_BUILTIN_EMACA,
+  RX_BUILTIN_EMSBA,
+  RX_BUILTIN_EMULA,
+  RX_BUILTIN_MACLH,
+  RX_BUILTIN_MSBHI,
+  RX_BUILTIN_MSBLO,
+  RX_BUILTIN_MSBLH,
+  RX_BUILTIN_MVFACGU,
+  RX_BUILTIN_MVFACLO,
+  RX_BUILTIN_MVTACGU,
+  RX_BUILTIN_RACL,
+  RX_BUILTIN_RDACL,
+  RX_BUILTIN_RDACW,
   RX_BUILTIN_max
 };
 
@@ -2416,6 +2538,26 @@ rx_init_builtins (void)
   ADD_RX_BUILTIN1 (ROUND,   "round",   intSI, float);
   ADD_RX_BUILTIN1 (REVW,    "revw",    intSI, intSI);
   ADD_RX_BUILTIN0 (WAIT,    "wait",    void);
+  ADD_RX_BUILTIN3 (MACHI2,  "machi2",  void,  intSI, intSI, integer);
+  ADD_RX_BUILTIN3 (MACLO2,  "maclo2",  void,  intSI, intSI, integer);
+  ADD_RX_BUILTIN3 (MULHI2,  "mulhi2",  void,  intSI, intSI, integer);
+  ADD_RX_BUILTIN3 (MULLO2,  "mullo2",  void,  intSI, intSI, integer);
+  ADD_RX_BUILTIN2 (MVFACHI2,"mvfachi2",intSI, integer, integer);
+  ADD_RX_BUILTIN2 (MVFACMI2,"mvfacmi2",intSI, integer, integer);
+  ADD_RX_BUILTIN2 (MVTACHI2,"mvtachi2",void,  intSI, integer);
+  ADD_RX_BUILTIN2 (MVTACLO2,"mvtaclo2",void,  intSI, integer);
+  ADD_RX_BUILTIN3 (EMACA,   "emaca",   void,  intSI, intSI, integer);
+  ADD_RX_BUILTIN3 (EMSBA,   "emsba",   void,  intSI, intSI, integer);
+  ADD_RX_BUILTIN3 (MACLH,   "maclh",   void,  intSI, intSI, integer);
+  ADD_RX_BUILTIN3 (MSBHI,   "msbhi",   void,  intSI, intSI, integer);
+  ADD_RX_BUILTIN3 (MSBLO,   "msblo",   void,  intSI, intSI, integer);
+  ADD_RX_BUILTIN3 (MSBLH,   "msblh",   void,  intSI, intSI, integer);
+  ADD_RX_BUILTIN2 (MVFACGU, "mvfacgu", intSI, intSI, integer);
+  ADD_RX_BUILTIN2 (MVFACLO, "mvfaclo", intSI, intSI, integer);
+  ADD_RX_BUILTIN2 (MVTACGU, "mvtacgu", void, intSI, integer);
+  ADD_RX_BUILTIN2 (RACL,    "racl",    void, intSI, integer);
+  ADD_RX_BUILTIN2 (RDACL,   "rdacl",   void, intSI, integer);
+  ADD_RX_BUILTIN2 (RDACW,   "rdacw",   void, intSI, integer);
 }
 
 /* Return the RX builtin for CODE.  */
@@ -2492,7 +2634,7 @@ rx_expand_builtin_mvtipl (rtx arg)
 }
 
 static rtx
-rx_expand_builtin_mac (tree exp, rtx (* gen_func)(rtx, rtx))
+rx_expand_builtin_mac (tree exp, rtx (* gen_func)(rtx, rtx, rtx))
 {
   rtx arg1 = expand_normal (CALL_EXPR_ARG (exp, 0));
   rtx arg2 = expand_normal (CALL_EXPR_ARG (exp, 1));
@@ -2503,36 +2645,172 @@ rx_expand_builtin_mac (tree exp, rtx (* gen_func)(rtx, rtx))
   if (! REG_P (arg2))
     arg2 = force_reg (SImode, arg2);
 
-  emit_insn (gen_func (arg1, arg2));
+  emit_insn (gen_func (arg1, arg2, GEN_INT(64)));
 
   return NULL_RTX;
 }
 
 static rtx
-rx_expand_int_builtin_1_arg (rtx arg,
-			     rtx target,
-			     rtx (* gen_func)(rtx, rtx),
-			     bool mem_ok)
+rx_expand_builtin_mac2 (tree exp, rtx (* gen_func)(rtx, rtx, rtx))
 {
-  if (! REG_P (arg))
-    if (!mem_ok || ! MEM_P (arg))
-      arg = force_reg (SImode, arg);
+  rtx arg1 = expand_normal (CALL_EXPR_ARG (exp, 0));
+  rtx arg2 = expand_normal (CALL_EXPR_ARG (exp, 1));
+  rtx arg3 = expand_normal (CALL_EXPR_ARG (exp, 2));
+  int acc;
+
+  if (!ALLOW_RXV2_INSNS)
+    {
+      error("Required RXv2 instructions.");
+      return NULL_RTX;
+    }
+
+  if (! REG_P (arg1))
+    arg1 = force_reg (SImode, arg1);
+
+  if (! REG_P (arg2))
+    arg2 = force_reg (SImode, arg2);
 
+  if (! CONST_INT_P (arg3))
+    return NULL_RTX;
+
+  acc = INTVAL(arg3);
+  if (acc < 0 || acc > 1)
+    {
+      error("Invalid register number.");
+      return NULL_RTX;
+    }
+
+  emit_insn (gen_func (arg1, arg2, GEN_INT(acc + 64)));
+
+  return NULL_RTX;
+}
+
+static rtx
+rx_expand_builtin_fromacc (rtx target, rtx (* gen_func)(rtx, rtx, rtx))
+{
   if (target == NULL_RTX || ! REG_P (target))
     target = gen_reg_rtx (SImode);
 
-  emit_insn (gen_func (target, arg));
+  emit_insn (gen_func (target, GEN_INT(0), GEN_INT(64)));
+
+  return target;
+}
+
+static rtx
+rx_expand_builtin_fromacc2 (rtx target, tree exp, rtx (* gen_func)(rtx, rtx, rtx))
+{
+  rtx arg1 = expand_normal (CALL_EXPR_ARG (exp, 0));
+  rtx arg2 = expand_normal (CALL_EXPR_ARG (exp, 1));
+  int acc;
+
+  if (!ALLOW_RXV2_INSNS)
+    {
+      error("Required RXv2 instructions.");
+      return NULL_RTX;
+    }
+
+  if (target == NULL_RTX || ! REG_P (target))
+    target = gen_reg_rtx (SImode);
+
+  if (! CONST_INT_P (arg1) || ! CONST_INT_P (arg2))
+    return NULL_RTX;
+
+  acc = INTVAL(arg2);
+  if (acc < 0 || acc > 1)
+    {
+      error("Invalid accumlator number.");
+      return NULL_RTX;
+    }
+
+  if (INTVAL(arg1) < 0 || INTVAL(arg1) > 2)
+    {
+      error("Invalid shift count.");
+      return NULL_RTX;
+    }
+
+  emit_insn (gen_func (target, arg1, GEN_INT(acc+64)));
 
   return target;
 }
 
 static rtx
-rx_expand_int_builtin_0_arg (rtx target, rtx (* gen_func)(rtx))
+rx_expand_builtin_toacc (rtx arg, rtx (* gen_func)(rtx, rtx))
 {
+  if (! REG_P (arg))
+    arg = force_reg (SImode, arg);
+
+  emit_insn (gen_func (arg, GEN_INT(64)));
+
+  return NULL_RTX;
+}
+
+static rtx
+rx_expand_builtin_toacc2 (tree exp, rtx (* gen_func)(rtx, rtx))
+{
+  rtx arg1 = expand_normal (CALL_EXPR_ARG (exp, 0));
+  rtx arg2 = expand_normal (CALL_EXPR_ARG (exp, 1));
+  int acc;
+
+  if (!ALLOW_RXV2_INSNS)
+    {
+      error("Required RXv2 instructions.");
+      return NULL_RTX;
+    }
+
+  if (! REG_P (arg1))
+    arg1 = force_reg (SImode, arg1);
+
+  acc = INTVAL(arg2);
+  if (acc < 0 || acc > 1)
+    {
+      error("Invalid accumlator number.");
+      return NULL_RTX;
+    }
+
+  emit_insn (gen_func (arg1, GEN_INT(acc + 64)));
+
+  return NULL_RTX;
+}
+
+static rtx
+rx_expand_builtin_rac (tree exp, rtx (* gen_func)(rtx, rtx))
+{
+  rtx arg1 = expand_normal (CALL_EXPR_ARG (exp, 0));
+  rtx arg2 = expand_normal (CALL_EXPR_ARG (exp, 1));
+  int acc;
+
+  if (!ALLOW_RXV2_INSNS)
+    {
+      error("Required RXv2 instructions.");
+      return NULL_RTX;
+    }
+
+  acc = INTVAL(arg2);
+  if (acc < 0 || acc > 1)
+    {
+      error("Invalid accumlator number.");
+      return NULL_RTX;
+    }
+
+  emit_insn (gen_func (arg1, GEN_INT(acc + 64)));
+
+  return NULL_RTX;
+}
+
+static rtx
+rx_expand_int_builtin_1_arg (rtx arg,
+                             rtx target,
+                             rtx (* gen_func)(rtx, rtx),
+                             bool mem_ok)
+{
+  if (! REG_P (arg))
+    if (!mem_ok || ! MEM_P (arg))
+      arg = force_reg (SImode, arg);
+
   if (target == NULL_RTX || ! REG_P (target))
     target = gen_reg_rtx (SImode);
 
-  emit_insn (gen_func (target));
+  emit_insn (gen_func (target, arg));
 
   return target;
 }
@@ -2606,14 +2884,14 @@ rx_expand_builtin (tree exp,
     case RX_BUILTIN_MACLO:   return rx_expand_builtin_mac (exp, gen_maclo);
     case RX_BUILTIN_MULHI:   return rx_expand_builtin_mac (exp, gen_mulhi);
     case RX_BUILTIN_MULLO:   return rx_expand_builtin_mac (exp, gen_mullo);
-    case RX_BUILTIN_MVFACHI: return rx_expand_int_builtin_0_arg
+    case RX_BUILTIN_MVFACHI: return rx_expand_builtin_fromacc
 	(target, gen_mvfachi);
-    case RX_BUILTIN_MVFACMI: return rx_expand_int_builtin_0_arg
+    case RX_BUILTIN_MVFACMI: return rx_expand_builtin_fromacc
 	(target, gen_mvfacmi);
-    case RX_BUILTIN_MVTACHI: return rx_expand_void_builtin_1_arg
-	(op, gen_mvtachi, true);
-    case RX_BUILTIN_MVTACLO: return rx_expand_void_builtin_1_arg
-	(op, gen_mvtaclo, true);
+    case RX_BUILTIN_MVTACHI: return rx_expand_builtin_toacc
+	(op, gen_mvtachi);
+    case RX_BUILTIN_MVTACLO: return rx_expand_builtin_toacc
+	(op, gen_mvtaclo);
     case RX_BUILTIN_RMPA:
       if (rx_allow_string_insns)
 	emit_insn (gen_rmpa ());
@@ -2623,13 +2901,44 @@ rx_expand_builtin (tree exp,
     case RX_BUILTIN_MVFC:    return rx_expand_builtin_mvfc (arg, target);
     case RX_BUILTIN_MVTC:    return rx_expand_builtin_mvtc (exp);
     case RX_BUILTIN_MVTIPL:  return rx_expand_builtin_mvtipl (op);
-    case RX_BUILTIN_RACW:    return rx_expand_void_builtin_1_arg
-	(op, gen_racw, false);
+    case RX_BUILTIN_RACW:
+      emit_insn (gen_racw (op, GEN_INT(64))); return NULL_RTX;
     case RX_BUILTIN_ROUND:   return rx_expand_builtin_round (op, target);
     case RX_BUILTIN_REVW:    return rx_expand_int_builtin_1_arg
 	(op, target, gen_revw, false);
     case RX_BUILTIN_WAIT:    emit_insn (gen_wait ()); return NULL_RTX;
-
+    case RX_BUILTIN_MACHI2:   return rx_expand_builtin_mac2 (exp, gen_machi);
+    case RX_BUILTIN_MACLO2:   return rx_expand_builtin_mac2 (exp, gen_maclo);
+    case RX_BUILTIN_MULHI2:   return rx_expand_builtin_mac2 (exp, gen_mulhi);
+    case RX_BUILTIN_MULLO2:   return rx_expand_builtin_mac2 (exp, gen_mullo);
+    case RX_BUILTIN_MVFACHI2: return rx_expand_builtin_fromacc2
+	(target, exp, gen_mvfachi);
+    case RX_BUILTIN_MVFACMI2: return rx_expand_builtin_fromacc2
+	(target, exp, gen_mvfacmi);
+    case RX_BUILTIN_MVTACHI2: return rx_expand_builtin_toacc2
+	(exp, gen_mvtachi);
+    case RX_BUILTIN_MVTACLO2: return rx_expand_builtin_toacc2
+	(exp, gen_mvtaclo);
+    case RX_BUILTIN_RACW2:    return rx_expand_builtin_rac (exp, gen_racw);
+    case RX_BUILTIN_EMACA:    return rx_expand_builtin_fromacc2
+	(target, exp, gen_emaca);
+    case RX_BUILTIN_EMSBA:    return rx_expand_builtin_fromacc2
+	(target, exp, gen_emsba);
+    case RX_BUILTIN_MACLH:    return rx_expand_builtin_fromacc2
+	(target, exp, gen_maclh);
+    case RX_BUILTIN_MSBHI:    return rx_expand_builtin_fromacc2
+	(target, exp, gen_msbhi);
+    case RX_BUILTIN_MSBLO:    return rx_expand_builtin_fromacc2
+	(target, exp, gen_msblo);
+    case RX_BUILTIN_MSBLH:    return rx_expand_builtin_fromacc2
+	(target, exp, gen_msblh);
+    case RX_BUILTIN_MVFACGU:  return rx_expand_builtin_fromacc2
+	(target, exp, gen_mvfacgu);
+    case RX_BUILTIN_MVFACLO:  return rx_expand_builtin_fromacc2
+	(target, exp, gen_mvfaclo);
+    case RX_BUILTIN_RACL:    return rx_expand_builtin_rac (exp, gen_racl);
+    case RX_BUILTIN_RDACL:   return rx_expand_builtin_rac (exp, gen_rdacl);
+    case RX_BUILTIN_RDACW:   return rx_expand_builtin_rac (exp, gen_rdacw);
     default:
       internal_error ("bad builtin code");
       break;
diff --git a/gcc/config/rx/rx.h b/gcc/config/rx/rx.h
index d2d6bce..bf599ad 100644
--- a/gcc/config/rx/rx.h
+++ b/gcc/config/rx/rx.h
@@ -44,6 +44,11 @@
           builtin_define ("__RX600__");		\
           builtin_assert ("machine=RX600");	\
         }					\
+      else if (rx_cpu_type == RXV2)		\
+        {					\
+          builtin_define ("__RXv2__");		\
+          builtin_assert ("machine=RXv2");	\
+        }					\
 						\
       if (TARGET_BIG_ENDIAN_DATA)		\
 	builtin_define ("__RX_BIG_ENDIAN__");	\
@@ -650,6 +655,8 @@ typedef unsigned int CUMULATIVE_ARGS;
 /* This macro is used to decide when RX FPU instructions can be used.  */
 #define ALLOW_RX_FPU_INSNS	(TARGET_USE_FPU)
 
+#define ALLOW_RXV2_INSNS	(rx_cpu_type == RXV2)
+
 #define BRANCH_COST(SPEED,PREDICT)       1
 #define REGISTER_MOVE_COST(MODE,FROM,TO) 2
 
diff --git a/gcc/config/rx/rx.md b/gcc/config/rx/rx.md
index 6faf771..fae26d0 100644
--- a/gcc/config/rx/rx.md
+++ b/gcc/config/rx/rx.md
@@ -35,6 +35,7 @@
 (define_constants
   [
    (SP_REG 0)
+   (R1_REG 1)
    (CC_REG 		   16)
 
    (UNSPEC_LOW_REG         0)
@@ -73,8 +74,22 @@
    (UNSPEC_BUILTIN_SAT     49)
    (UNSPEC_BUILTIN_SETPSW  50)
    (UNSPEC_BUILTIN_WAIT	   51)
-
-   (UNSPEC_PID_ADDR	   52)
+   (UNSPEC_BUILTIN_MOVCO   52)
+   (UNSPEC_BUILTIN_MOVLI   53)
+   (UNSPEC_BUILTIN_EMACA   54)
+   (UNSPEC_BUILTIN_EMSBA   55)
+   (UNSPEC_BUILTIN_MACLH   56)
+   (UNSPEC_BUILTIN_MSBHI   57)
+   (UNSPEC_BUILTIN_MSBLO   58)
+   (UNSPEC_BUILTIN_MSBLH   59)
+   (UNSPEC_BUILTIN_MVFACGU 60)
+   (UNSPEC_BUILTIN_MVFACLO 61)
+   (UNSPEC_BUILTIN_MVTACGU 62)
+   (UNSPEC_BUILTIN_RACL    63)
+   (UNSPEC_BUILTIN_RDACL   64)
+   (UNSPEC_BUILTIN_RDACW   65)
+
+   (UNSPEC_PID_ADDR	   66)
   ]
 )
 
@@ -1877,7 +1892,40 @@
 
 ;; Floating Point Instructions
 
-(define_insn "addsf3"
+(define_expand "addsf3"
+  [(set (match_operand:SF          0 "register_operand"  "=r")
+	(plus:SF (match_operand:SF 1 "register_operand"  "r")
+		 (match_operand:SF 2 "rx_source_operand"  "FQr")))
+   (clobber (reg:CC CC_REG))]
+"ALLOW_RX_FPU_INSNS "
+{ if(!ALLOW_RXV2_INSNS) {
+    emit_insn(gen_addsf3_rx(operands[0],
+                              operands[1],
+                              operands[2]));
+  } else {
+    emit_insn(gen_addsf3_rxv2(operands[0],
+                              operands[1],
+                              operands[2]));
+  }
+  DONE;
+})
+
+(define_insn "addsf3_rxv2"
+  [(set (match_operand:SF          0 "register_operand"  "=r,r,r,r")
+	(plus:SF (match_operand:SF 1 "register_operand"  "%r,0,0,0")
+		 (match_operand:SF 2 "register_operand"  "r,r,F,Q")))
+   (clobber (reg:CC CC_REG))]
+  "ALLOW_RXV2_INSNS"
+  "@
+  fadd\t%2, %1, %0
+  fadd\t%2, %0
+  fadd\t%2, %0
+  fadd\t%2, %0"
+  [(set_attr "timings" "44,44,44,66")
+   (set_attr "length" "3,3,7,5")]
+)
+
+(define_insn "addsf3_rx"
   [(set (match_operand:SF          0 "register_operand"  "=r,r,r")
 	(plus:SF (match_operand:SF 1 "register_operand"  "%0,0,0")
 		 (match_operand:SF 2 "rx_source_operand"  "r,F,Q")))
@@ -1899,7 +1947,40 @@
    (set_attr "length" "3,7,5")]
 )
 
-(define_insn "mulsf3"
+(define_expand "mulsf3"
+  [(set (match_operand:SF          0 "register_operand" "=r,r,r")
+	(mult:SF (match_operand:SF 1 "register_operand" "%0,0,0")
+		(match_operand:SF  2 "rx_source_operand" "r,F,Q")))
+   (clobber (reg:CC CC_REG))]
+"ALLOW_RX_FPU_INSNS || ALLOW_RXV2_INSNS"
+{ if(!ALLOW_RXV2_INSNS) {
+    emit_insn(gen_mulsf3_rx(operands[0],
+                              operands[1],
+                              operands[2]));
+  } else {
+    emit_insn(gen_mulsf3_rxv2(operands[0],
+                              operands[1],
+                              operands[2]));
+  }
+  DONE;
+})
+
+(define_insn "mulsf3_rxv2"
+  [(set (match_operand:SF          0 "register_operand" "=r,r,r,r")
+	(mult:SF (match_operand:SF 1 "register_operand" "%r,0,0,0")
+		(match_operand:SF  2 "rx_source_operand" "r,r,F,Q")))
+   (clobber (reg:CC CC_REG))]
+  "ALLOW_RXV2_INSNS"
+  "@
+  fmul\t%2, %1, %0
+  fmul\t%2, %0
+  fmul\t%2, %0
+  fmul\t%2, %0"
+  [(set_attr "timings" "33,33,33,55")
+   (set_attr "length"  "3,3,7,5")]
+)
+
+(define_insn "mulsf3_rx"
   [(set (match_operand:SF          0 "register_operand" "=r,r,r")
 	(mult:SF (match_operand:SF 1 "register_operand" "%0,0,0")
 		(match_operand:SF  2 "rx_source_operand" "r,F,Q")))
@@ -1910,7 +1991,40 @@
    (set_attr "length"  "3,7,5")]
 )
 
-(define_insn "subsf3"
+(define_expand "subsf3"
+  [(set (match_operand:SF          0 "register_operand"  "=r")
+	(minus:SF (match_operand:SF 1 "register_operand"  "r")
+		 (match_operand:SF 2 "rx_source_operand"  "FQr")))
+   (clobber (reg:CC CC_REG))]
+"ALLOW_RX_FPU_INSNS || ALLOW_RXV2_INSNS"
+{ if(!ALLOW_RXV2_INSNS) {
+    emit_insn(gen_subsf3_rx(operands[0],
+                              operands[1],
+                              operands[2]));
+  } else {
+    emit_insn(gen_subsf3_rxv2(operands[0],
+                              operands[1],
+                              operands[2]));
+  }
+  DONE;
+})
+
+(define_insn "subsf3_rxv2"
+  [(set (match_operand:SF           0 "register_operand" "=r,r,r,r")
+	(minus:SF (match_operand:SF 1 "register_operand"  "r,0,0,0")
+		  (match_operand:SF 2 "rx_source_operand" "r,r,F,Q")))
+   (clobber (reg:CC CC_REG))]
+  "ALLOW_RXV2_INSNS"
+  "@
+  fsub\t%1, %2, %0
+  fsub\t%Q2, %0
+  fsub\t%Q2, %0
+  fsub\t%Q2, %0"
+  [(set_attr "timings" "44,44,44,66")
+   (set_attr "length" "3,3,7,5")]
+)
+
+(define_insn "subsf3_rx"
   [(set (match_operand:SF           0 "register_operand" "=r,r,r")
 	(minus:SF (match_operand:SF 1 "register_operand"  "0,0,0")
 		  (match_operand:SF 2 "rx_source_operand" "r,F,Q")))
@@ -1940,6 +2054,36 @@
   [(set_attr "timings" "22,44")
    (set_attr "length" "3,6")]
 )
+
+(define_insn "fixuns_truncsfsi2"
+  [(set (match_operand:SI         0 "register_operand"  "=r,r")
+	(fix:SI (match_operand:SF 1 "rx_compare_operand" "r,Q")))
+   (clobber (reg:CC CC_REG))]
+  "ALLOW_RX_FPU_INSNS && ALLOW_RXV2_INSNS"
+  "ftou\t%Q1, %0"
+  [(set_attr "timings" "22,44")
+   (set_attr "length" "3,5")]
+)
+
+(define_insn "floatunssisf2"
+  [(set (match_operand:SF           0 "register_operand"  "=r,r")
+	(float:SF (match_operand:SI 1 "rx_compare_operand" "r,Q")))
+   (clobber (reg:CC CC_REG))]
+  "ALLOW_RX_FPU_INSNS && ALLOW_RXV2_INSNS"
+  "utof\t%Q1, %0"
+  [(set_attr "timings" "22,44")
+   (set_attr "length" "3,6")]
+)
+
+(define_insn "sqrtsf2"
+  [(set (match_operand:SF 0 "register_operand" "=r,r")
+        (sqrt:SF (match_operand:SF 1 "rx_source_operand" "r,Q")))
+   (clobber (reg:CC CC_REG))]
+  "ALLOW_RX_FPU_INSNS && ALLOW_RXV2_INSNS"
+  "fsqrt\t%Q1, %0"
+  [(set_attr "timings" "22,44")
+   (set_attr "length" "3,5")]
+)
 
 ;; Bit manipulation instructions.
 
@@ -2379,87 +2523,185 @@
 ;; Multiply & Accumulate (high)
 (define_insn "machi"
   [(unspec:SI [(match_operand:SI 0 "register_operand" "r")
-	       (match_operand:SI 1 "register_operand" "r")]
+	       (match_operand:SI 1 "register_operand" "r")
+	       (match_operand:SI 2 "immediate_operand" "i")]
 	      UNSPEC_BUILTIN_MACHI)]
-  ""
-  "machi\t%0, %1"
-  [(set_attr "length" "3")]
+""
+{
+  if(ALLOW_RXV2_INSNS)
+    return "machi\t%0,%1,%C2";
+  else
+    return "machi\t%0, %1";
+ }
+ [(set_attr "length" "3")]
 )
 
 ;; Multiply & Accumulate (low)
 (define_insn "maclo"
   [(unspec:SI [(match_operand:SI 0 "register_operand" "r")
-	       (match_operand:SI 1 "register_operand" "r")]
+	       (match_operand:SI 1 "register_operand" "r")
+	       (match_operand:SI 2 "immediate_operand" "i")]
 	      UNSPEC_BUILTIN_MACLO)]
   ""
-  "maclo\t%0, %1"
+{if(ALLOW_RXV2_INSNS)
+  return "machi\t%0,%1,%a2";
+else
+  return "machi\t%0, %1";
+}
   [(set_attr "length" "3")]
 )
 
 ;; Multiply (high)
 (define_insn "mulhi"
   [(unspec:SI [(match_operand:SI 0 "register_operand" "r")
-	       (match_operand:SI 1 "register_operand" "r")]
+	       (match_operand:SI 1 "register_operand" "r")
+	       (match_operand:SI 2 "immediate_operand" "i")]
 	      UNSPEC_BUILTIN_MULHI)]
   ""
-  "mulhi\t%0, %1"
+{if(ALLOW_RXV2_INSNS)
+  return "mulhi\t%0,%1,%C2";
+else
+  return "mulhi\t%0, %1";
+}
   [(set_attr "length" "3")]
 )
 
 ;; Multiply (low)
 (define_insn "mullo"
-  [(unspec:SI [(match_operand:SI 0 "register_operand" "r")
-	       (match_operand:SI 1 "register_operand" "r")]
-	      UNSPEC_BUILTIN_MULLO)]
-  ""
-  "mullo\t%0, %1"
+  [(set (match_operand:SI 0 "register_operand"  "=r")
+	(unspec:SI [(match_operand:SI 1 "immediate_operand"  "i")
+		    (match_operand:SI 2 "immediate_operand"  "i")]
+	      UNSPEC_BUILTIN_MULLO))]
+  ""
+{if(ALLOW_RXV2_INSNS)
+  return "mullo\t%0,%1,%a2";
+else
+  return "mullo\t%0, %1";
+}
   [(set_attr "length" "3")]
 )
 
 ;; Move from Accumulator (high)
 (define_insn "mvfachi"
   [(set (match_operand:SI 0 "register_operand" "=r")
-	(unspec:SI [(const_int 0)]
+	(unspec:SI [(match_operand:SI 1 "immediate_operand" "i")
+	            (match_operand:SI 2 "immediate_operand" "i")]
 		   UNSPEC_BUILTIN_MVFACHI))]
   ""
-  "mvfachi\t%0"
+{if(ALLOW_RXV2_INSNS)
+  return "mvfachi\t%1,%C2,%0";
+else
+  return "movfachi\t%0";
+}
   [(set_attr "length" "3")]
 )
 
-;; Move from Accumulator (middle)
+;; Move from Accumulator (midlle)
 (define_insn "mvfacmi"
   [(set (match_operand:SI 0 "register_operand" "=r")
-	(unspec:SI [(const_int 0)]
+	(unspec:SI [(match_operand:SI 1 "immediate_operand" "i")
+	       (match_operand:SI 2 "immediate_operand" "i")]
 		   UNSPEC_BUILTIN_MVFACMI))]
   ""
-  "mvfacmi\t%0"
+{if(ALLOW_RXV2_INSNS)
+  return "mvfacmi\t%1,%C2,%0";
+else
+  return "movfacmi\t%0";
+}
   [(set_attr "length" "3")]
 )
 
 ;; Move to Accumulator (high)
 (define_insn "mvtachi"
-  [(unspec_volatile:SI [(match_operand:SI 0 "register_operand" "r")]
+  [(unspec_volatile:SI [(match_operand:SI 0 "register_operand" "r")
+			(match_operand:SI 1 "immediate_operand" "i")]
 		       UNSPEC_BUILTIN_MVTACHI)]
   ""
-  "mvtachi\t%0"
+{if(ALLOW_RXV2_INSNS)
+  return "mvtachi\t%0,%C1";
+else
+  return "mvtachi\t%0";
+}
   [(set_attr "length" "3")]
 )
 
 ;; Move to Accumulator (low)
 (define_insn "mvtaclo"
-  [(unspec_volatile:SI [(match_operand:SI 0 "register_operand" "r")]
+  [(unspec_volatile:SI [(match_operand:SI 0 "register_operand" "r")
+			(match_operand:SI 1 "immediate_operand" "i")]
 		       UNSPEC_BUILTIN_MVTACLO)]
   ""
-  "mvtaclo\t%0"
+{if(ALLOW_RXV2_INSNS)
+  return "mvtaclo\t%0,%C1";
+else
+  return "mvtaclo\t%0";
+}
+  [(set_attr "length" "3")]
+)
+
+;; Move from Accumulator (gurd)
+(define_insn "mvfacgu"
+  [(set (match_operand:SI 0 "register_operand" "=r")
+	(unspec:SI [(match_operand:SI 1 "immediate_operand" "i")
+	       (match_operand:SI 2 "immediate_operand" "i")]
+		   UNSPEC_BUILTIN_MVFACGU))]
+  "ALLOW_RXV2_INSNS"
+  "mvfacgu\t%1,%C2,%0"
+  [(set_attr "length" "3")]
+)
+
+;; Move from Accumulator (low)
+(define_insn "mvfaclo"
+  [(set (match_operand:SI 0 "register_operand" "=r")
+	(unspec:SI [(match_operand:SI 1 "immediate_operand" "i")
+	       (match_operand:SI 2 "immediate_operand" "i")]
+		   UNSPEC_BUILTIN_MVFACLO))]
+  "ALLOW_RXV2_INSNS"
+  "mvfaclo\t%1,%C2,%0"
   [(set_attr "length" "3")]
 )
 
 ;; Round Accumulator
 (define_insn "racw"
-  [(unspec_volatile:SI [(match_operand:SI 0 "immediate_operand" "i")]
+  [(unspec_volatile:SI [(match_operand:SI 0 "immediate_operand" "i")
+			(match_operand:SI 1 "immediate_operand" "i")]
 		       UNSPEC_BUILTIN_RACW)]
   ""
-  "racw\t%0"
+{if(ALLOW_RXV2_INSNS)
+  return "racw\t%0,%C1";
+else
+  return "racw\t%0";
+}
+  [(set_attr "length" "3")]
+)
+
+;; Round Accumulator
+(define_insn "racl"
+  [(unspec_volatile:SI [(match_operand:SI 0 "immediate_operand" "i")
+		        (match_operand:SI 1 "immediate_operand" "i")]
+		       UNSPEC_BUILTIN_RACL)]
+  "ALLOW_RXV2_INSNS"
+  "racl\t%0,%C1"
+  [(set_attr "length" "3")]
+)
+
+;; Round Accumulator
+(define_insn "rdacl"
+  [(unspec_volatile:SI [(match_operand:SI 0 "immediate_operand" "i")
+		        (match_operand:SI 1 "immediate_operand" "i")]
+		       UNSPEC_BUILTIN_RDACL)]
+  "ALLOW_RXV2_INSNS"
+  "rdacl\t%0,%C1"
+  [(set_attr "length" "3")]
+)
+
+;; Round Accumulator
+(define_insn "rdacw"
+  [(unspec_volatile:SI [(match_operand:SI 0 "immediate_operand" "i")
+			(match_operand:SI 1 "immediate_operand" "i")]
+		       UNSPEC_BUILTIN_RDACW)]
+  "ALLOW_RXV2_INSNS"
+  "rdacw\t%0,%C1"
   [(set_attr "length" "3")]
 )
 
@@ -2477,6 +2719,67 @@
    (set_attr "timings" "1010")]
 )
 
+;; Multiply & Accumulate (low)
+(define_insn "emaca"
+  [(unspec:SI [(match_operand:SI 0 "register_operand" "r")
+	       (match_operand:SI 1 "register_operand" "r")
+	       (match_operand:SI 2 "immediate_operand" "i")]
+	      UNSPEC_BUILTIN_EMACA)]
+  "ALLOW_RXV2_INSNS"
+  "emaca\t%0,%1,%a2";
+  [(set_attr "length" "3")]
+)
+
+(define_insn "emsba"
+  [(unspec:SI [(match_operand:SI 0 "register_operand" "r")
+	       (match_operand:SI 1 "register_operand" "r")
+	       (match_operand:SI 2 "immediate_operand" "i")]
+	      UNSPEC_BUILTIN_EMSBA)]
+  "ALLOW_RXV2_INSNS"
+  "emsbs\t%0,%1,%a2";
+  [(set_attr "length" "3")]
+)
+
+(define_insn "maclh"
+  [(unspec:SI [(match_operand:SI 0 "register_operand" "r")
+	       (match_operand:SI 1 "register_operand" "r")
+	       (match_operand:SI 2 "immediate_operand" "i")]
+	      UNSPEC_BUILTIN_MACLH)]
+  "ALLOW_RXV2_INSNS"
+  "maclh\t%0,%1,%a2";
+  [(set_attr "length" "3")]
+)
+
+(define_insn "msbhi"
+  [(unspec:SI [(match_operand:SI 0 "register_operand" "r")
+	       (match_operand:SI 1 "register_operand" "r")
+	       (match_operand:SI 2 "immediate_operand" "i")]
+	      UNSPEC_BUILTIN_MSBHI)]
+  "ALLOW_RXV2_INSNS"
+  "msbhi\t%0,%1,%a2";
+  [(set_attr "length" "3")]
+)
+
+(define_insn "msblo"
+  [(unspec:SI [(match_operand:SI 0 "register_operand" "r")
+	       (match_operand:SI 1 "register_operand" "r")
+	       (match_operand:SI 2 "immediate_operand" "i")]
+	      UNSPEC_BUILTIN_MSBLO)]
+  "ALLOW_RXV2_INSNS"
+  "msblo\t%0,%1,%a2";
+  [(set_attr "length" "3")]
+)
+
+(define_insn "msblh"
+  [(unspec:SI [(match_operand:SI 0 "register_operand" "r")
+	       (match_operand:SI 1 "register_operand" "r")
+	       (match_operand:SI 2 "immediate_operand" "i")]
+	      UNSPEC_BUILTIN_MSBLH)]
+  "ALLOW_RXV2_INSNS"
+  "msblh\t%0,%1,%a2";
+  [(set_attr "length" "3")]
+)
+
 ;;---------- Arithmetic ------------------------
 
 ;; Byte swap (two 16-bit values).
@@ -2639,3 +2942,5 @@
   [(set_attr "length" "16")
    (set_attr "timings" "22")]
 )
+
+(include "sync.md")
diff --git a/gcc/config/rx/rx.opt b/gcc/config/rx/rx.opt
index 56e8adf..4378815 100644
--- a/gcc/config/rx/rx.opt
+++ b/gcc/config/rx/rx.opt
@@ -64,6 +64,9 @@ Enum(rx_cpu_types) String(rx600) Value(RX600)
 EnumValue
 Enum(rx_cpu_types) String(rx100) Value(RX100)
 
+EnumValue
+Enum(rx_cpu_types) String(rxv2) Value(RXV2)
+
 ;---------------------------------------------------
 
 mbig-endian-data
diff --git a/gcc/config/rx/sync.md b/gcc/config/rx/sync.md
new file mode 100644
index 0000000..1d19d2e
--- /dev/null
+++ b/gcc/config/rx/sync.md
@@ -0,0 +1,191 @@
+;; GCC machine description for RXv2 synchronization instructions.
+;; Copyright (C) 2011-2015 Free Software Foundation, Inc.
+;;
+;; This file is part of GCC.
+;;
+;; GCC is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 3, or (at your option)
+;; any later version.
+;;
+;; GCC is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+;; GNU General Public License for more details.
+;;
+;; You should have received a copy of the GNU General Public License
+;; along with GCC; see the file COPYING3.  If not see
+;; <http://www.gnu.org/licenses/>.
+;;
+;;
+
+(define_c_enum "unspec" [
+  UNSPEC_ATOMIC
+])
+
+(define_c_enum "unspecv" [
+  UNSPECV_CMPXCHG_1
+  UNSPECV_CMPXCHG_2
+  UNSPECV_CMPXCHG_3
+])
+
+(define_code_iterator FETCHOP [plus minus ior xor and])
+(define_code_attr fetchop_name
+  [(plus "add") (minus "sub") (ior "or") (xor "xor") (and "and")])
+
+(define_code_attr fetchop_constraint_1_llcs
+  [(plus "ri") (minus "r") (ior "ri") (xor "ri") (and "ri")])
+
+;;------------------------------------------------------------------------------
+;; comapre and swap
+
+(define_expand "atomic_compare_and_swapsi"
+  [(match_operand:SI 0 "register_operand")		;; bool success output
+   (match_operand:SI 1 "register_operand")		;; oldval output
+   (match_operand:SI 2 "memory_operand")	;; memory
+   (match_operand:SI 3 "general_operand")	;; expected input
+   (match_operand:SI 4 "general_operand")	;; newval input
+   (match_operand:SI 5 "const_int_operand")		;; is_weak
+   (match_operand:SI 6 "const_int_operand")		;; success model
+   (match_operand:SI 7 "const_int_operand")]		;; failure model
+  ""
+{
+  rtx mem = operands[2];
+  rtx old_val = gen_lowpart (SImode, operands[1]);
+  rtx exp_val = operands[3];
+  rtx new_val = operands[4];
+
+  if (ALLOW_RXV2_INSNS) {
+    emit_insn (gen_atomic_compare_and_swapsi_1 (old_val, mem,
+					      exp_val, new_val));
+
+    DONE;
+  } else {
+    FAIL;
+  }
+})
+
+(define_insn "atomic_compare_and_swapsi_1"
+  [(set (match_operand:SI 0 "register_operand" "=&r")
+	(unspec_volatile:SI
+	  [(match_operand:SI 1 "memory_operand" "=q")
+	   (match_operand:SI 2 "general_operand" "ri")
+	   (match_operand:SI 3 "general_operand" "ri")]
+	  UNSPECV_CMPXCHG_1))
+   (set (match_dup 1)
+	(unspec_volatile:SI [(const_int 0)] UNSPECV_CMPXCHG_2))
+   (set (reg:SI CC_REG)
+	(unspec_volatile:SI [(const_int 0)] UNSPECV_CMPXCHG_3))
+  (clobber (reg:SI CC_REG))
+  (clobber (reg:SI R1_REG))]
+  "ALLOW_RXV2_INSNS"
+  "\r0:	movli	%1,r1
+	cmp	%2,r1
+	bne	0f
+	mov	r1,%0
+	mov	%3,r1
+	movco	r1,%1
+	tst	r1,r1
+	bne	0b
+0:"
+  [(set_attr "length" "19")])
+
+;;------------------------------------------------------------------------------
+;; read - write - return old value
+(define_insn "atomic_exchangesi"
+  [(set (match_operand:SI 0 "register_operand" "=&r")	;; oldval output
+   (match_operand:SI 1 "memory_operand" "=m"))		;; memory
+   (match_operand:SI 3 "const_int_operand")		;; memory model
+   (set (match_dup 1)
+	(match_operand:SI 2 "register_operand" "0"))]		;; input
+  ""
+  "xchg %1,%0"
+  [(set_attr "length" "4")])
+
+;;------------------------------------------------------------------------------
+;; read - add|sub|or|and|xor|nand - write - return old value
+
+(define_insn "atomic_fetch_<fetchop_name>si"
+  [(set (match_operand:SI 0 "register_operand" "=&mr")
+	(match_operand:SI 1 "memory_operand" "=mr"))
+   (set (match_dup 1)
+	(unspec:SI
+	  [(FETCHOP:SI (match_dup 1)
+	     (match_operand:SI 2 "general_operand" "g"))]
+	  UNSPEC_ATOMIC))
+   (match_operand:SI 3 "const_int_operand")
+   (clobber (reg:SI CC_REG))
+   (clobber (reg:SI R1_REG))]
+  "ALLOW_RXV2_INSNS"
+  "\r0:	movli	%1,r1
+	mov	r1,%0
+	<fetchop_name>	%2,r1
+	movco	r1,%1
+	tst	r1,r1
+	beq	0b";
+  [(set_attr "length" "15")])
+
+(define_insn "atomic_fetch_nandsi"
+  [(set (match_operand:SI 0 "register_operand" "=&r")
+	(match_operand:SI 1 "memory_operand" "=q"))
+   (set (match_dup 1)
+	(unspec:SI
+	  [(not:SI (and:SI (match_dup 1)
+		       (match_operand:SI 2 "general_operand" "ri")))]
+	  UNSPEC_ATOMIC))
+   (match_operand:SI 3 "const_int_operand")
+   (clobber (reg:SI CC_REG))
+   (clobber (reg:SI R1_REG))]
+  "ALLOW_RXV2_INSNS"
+  "\r0:	movli	%1,r1
+	mov	r1,%0
+	and	%2,r1
+	not	r1
+	movco	r1,%1
+	tst	r1,r1
+	beq	0b"
+  [(set_attr "length" "16")])
+
+;;------------------------------------------------------------------------------
+;; read - add|sub|or|and|xor|nand - write - return new value
+
+(define_insn "atomic_<fetchop_name>_fetchsi"
+  [(set (match_operand:SI 0 "register_operand" "=&r")
+	(FETCHOP:SI
+	  (match_operand:SI 1 "memory_operand" "=m")
+	  (match_operand:SI 2 "general_operand" "ri")))
+   (set (match_dup 1)
+	(unspec:SI
+	  [(FETCHOP:SI (match_dup 1) (match_dup 2))]
+	  UNSPEC_ATOMIC))
+   (match_operand:SI 3 "const_int_operand" "")
+   (clobber (reg:SI CC_REG))]
+  "ALLOW_RXV2_INSNS"
+  "\r0:	movli	%1,%0
+	<fetchop_name>	%2,%0
+	movco	%0,%1
+	tst	%0,%0
+	beq	0b
+	mov.L	%1,%0"
+  [(set_attr "length" "15")])
+
+(define_insn "atomic_nand_fetchsi"
+  [(set (match_operand:SI 0 "register_operand" "=&r")
+	(not:SI (and:SI
+	  (match_operand:SI 1 "memory_operand" "=q")
+	  (match_operand:SI 2 "general_operand" "ri"))))
+   (set (match_dup 1)
+	(unspec:SI
+	  [(not:SI (and:SI (match_dup 1) (match_dup 2)))]
+	  UNSPEC_ATOMIC))
+   (match_operand:SI 3 "const_int_operand")
+   (clobber (reg:SI CC_REG))]
+  "ALLOW_RXV2_INSNS"
+  "\r0:	movli	%1,%0
+	and	%2,%0
+	not	%0
+	movco	%0,%1
+	tst	%0,%0
+	bf	0b
+	mov.L	%1,%0"
+  [(set_attr "length" "16")])
diff --git a/gcc/config/rx/t-rx b/gcc/config/rx/t-rx
index f29fd3d..a5f0ef0 100644
--- a/gcc/config/rx/t-rx
+++ b/gcc/config/rx/t-rx
@@ -30,6 +30,8 @@ MULTILIB_DIRNAMES   =  64-bit-double  no-fpu-libs   big-endian-data   pid
 
 MULTILIB_OPTIONS   += mno-allow-string-insns
 MULTILIB_DIRNAMES  += no-strings
+MULTILIB_OPTIONS   += mcpu=rxv2
+MULTILIB_DIRNAMES  += v2
 
 MULTILIB_MATCHES    = nofpu=mnofpu  nofpu=mcpu?rx200  nofpu=mcpu?rx100
 
diff --git a/gcc/doc/md.texi b/gcc/doc/md.texi
index 4848e64..4fc5265 100644
--- a/gcc/doc/md.texi
+++ b/gcc/doc/md.texi
@@ -3445,6 +3445,8 @@ A constant in the range @minus{}8388608 to 8388607, inclusive.
 @item Uint04
 A constant in the range 0 to 15, inclusive.
 
+@item q
+A register indirect adressing.
 @end table
 
 @item S/390 and zSeries---@file{config/s390/s390.h}
-- 
2.6.1



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