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 <ys...@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
>
>