Several instructions were added to the RXv2 (RX64M and RX71M) CPU. http://documentation.renesas.com/doc/products/mpumcu/doc/rx_family/r01us0071ej0100_rxv2sm.pdf
This patch is supported new instruction for RX target. diff --git a/gcc/ChangeLog b/gcc/ChangeLog index d5d3aaa..437d9cc 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,43 @@ +2015-0404 Yoshinori Sato <ys...@users.sourceforge.jp> + + * config/rx/rx.opt (rx_cpu_types): Add RXv2. + * config/rx/rx-opts.h (rx_cpu_types): Likewise. + * config/rx/t-rx: Add rxv2 option. + * config/rx/rx.c (rx_print_operand): Add RXv2 registers. + (rx_expand_prologue): Add accumlator address. + (rx_expand_epilogue): Likewise. + (rx_expand_int_builtin_1_arg): Likwise. + (rx_expand_builtin_mac): Likewise. + (rx_builtin): Add new builtins. + (rx_init_builtins): Likewise. + (rx_expand_builtin): Likewise. + (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 RXv2. + (ALLOW_RXV2_INSNS): New. + * config/rx/rx.md (R1_REG, UNSPEC_BUILTIN_MOVCO): New. + (UNSPEC_BUILTIN_MOVLI, UNSPEC_BUILTIN_EMACA): Likewise. + (UNSPEC_BUILTIN_EMSBA, UNSPEC_BUILTIN_MACLH): Likewise. + (UNSPEC_BUILTIN_MSBHI, UNSPEC_BUILTIN_MSBLO): Likewise. + (UNSPEC_BUILTIN_MSBLH, UNSPEC_BUILTIN_MVFACGU): Likewise. + (UNSPEC_BUILTIN_MVFACLO, UNSPEC_BUILTIN_MVTACGU): Likewise. + (UNSPEC_BUILTIN_RACL, UNSPEC_BUILTIN_RDACL): Likewise. + (UNSPEC_BUILTIN_RDACW): Likewise. + (addsf3, mulsf3, subsf3, machi, mulhi, mullo): Add RXv2 pattern. + (mvfachi, mvfacmi, mvtaclo, racw): Likewise. + (addsf3_rx, addsf_rxv2, mulsf_rx, mulsf_rxv2): New. + (subsf3_rx, subsf_rxv2, fixuns_truncsfsi2): Likewise. + (floatunssisf2, sqrtsf2, mvfacgu, mvfaclo): Likewise. + (racl, rdacl, rdacw, emaca, emsba, maclh): Likewise. + (msbhi, msblo, msblh): Likewise. + * config/rx/constraints.md: (define_memory_constraint "q"): + New constraint. + * config/rx/sync.md: New. + 2015-04-04 Richard Biener <rguent...@suse.de> PR tree-optimization/64909 diff --git a/gcc/config/rx/constraints.md b/gcc/config/rx/constraints.md index d46f9da..ccfe3a0 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 6fe21aa..92247c2 100644 --- a/gcc/config/rx/rx.c +++ b/gcc/config/rx/rx.c @@ -673,6 +673,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)); @@ -765,6 +778,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; @@ -829,7 +847,6 @@ rx_print_operand (FILE * file, rtx op, int letter) } break; } - /* Fall through. */ default: @@ -1788,10 +1805,15 @@ rx_expand_prologue (void) /* 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) + { + 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 { @@ -1801,10 +1823,15 @@ 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))); + } } } @@ -2139,8 +2166,11 @@ rx_expand_epilogue (bool is_sibcall) 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))); + if (!ALLOW_RXV2_INSNS) + { + 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))); + } } if (register_mask) @@ -2356,6 +2386,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 }; @@ -2422,6 +2474,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. */ @@ -2498,7 +2570,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)); @@ -2509,36 +2581,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; } @@ -2612,25 +2820,56 @@ 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: emit_insn (gen_rmpa ()); return NULL_RTX; 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 4c56624..b01d240 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__"); \ @@ -643,6 +648,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 590c70f..ae603a2 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" + "emacs\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 1ccda4c..5b95e0e 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..13a04b1 --- /dev/null +++ b/gcc/config/rx/sync.md @@ -0,0 +1,187 @@ +;; 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]; + + emit_insn (gen_atomic_compare_and_swapsi_1 (old_val, mem, + exp_val, new_val)); + + DONE; +}) + +(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 b532be6..6c7b591 100644 --- a/gcc/config/rx/t-rx +++ b/gcc/config/rx/t-rx @@ -20,8 +20,8 @@ # Enable multilibs: -MULTILIB_OPTIONS = m64bit-doubles nofpu mbig-endian-data mpid -MULTILIB_DIRNAMES = 64-bit-double no-fpu-libs big-endian-data pid +MULTILIB_OPTIONS = m64bit-doubles nofpu mbig-endian-data mpid mcpu=rxv2 +MULTILIB_DIRNAMES = 64-bit-double no-fpu-libs big-endian-data pid rxv2 # If necessary uncomment the next two lines to generate multilibs # using the old, broken, ABI. -- Yoshinori Sato <ys...@users.sourceforge.jp>