This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[PATCH][RX] v2 instructions support.
- From: Yoshinori Sato <ysato at sa76r4 dot localdomain>
- To: gcc-patches at gcc dot gnu dot org
- Cc: Yoshinori Sato <ysato at sa76r4 dot localdomain>
- Date: Thu, 10 Dec 2015 23:11:33 +0900
- Subject: [PATCH][RX] v2 instructions support.
- Authentication-results: sourceware.org; auth=none
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