[PATCH][RX] v2 instructions support.

Yoshinori Sato ysato@users.sourceforge.jp
Thu Dec 24 06:38:00 GMT 2015


Ping.

On Thu, 10 Dec 2015 23:11:33 +0900,
Yoshinori Sato wrote:
> 
> 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
> 
> 



More information about the Gcc-patches mailing list