Message ID | 1449756693-32709-1-git-send-email-ysato@sa76r4.localdomain |
---|---|
State | New |
Headers | show |
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 > >
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}