diff --git a/gcc/config/mips/mips-cpus.def b/gcc/config/mips/mips-cpus.def index 07fbf9c..08b1509 100644 --- a/gcc/config/mips/mips-cpus.def +++ b/gcc/config/mips/mips-cpus.def @@ -136,6 +136,7 @@ MIPS_CPU ("1004kc", PROCESSOR_24KC, 33, 0) /* 1004K with MT/DSP. */ MIPS_CPU ("1004kf2_1", PROCESSOR_24KF2_1, 33, 0) MIPS_CPU ("1004kf", PROCESSOR_24KF2_1, 33, 0) MIPS_CPU ("1004kf1_1", PROCESSOR_24KF1_1, 33, 0) +MIPS_CPU ("p5600", PROCESSOR_P5600, 33, PTF_AVOID_BRANCHLIKELY) /* MIPS64 processors. */ MIPS_CPU ("5kc", PROCESSOR_5KC, 64, 0) diff --git a/gcc/config/mips/mips-protos.h b/gcc/config/mips/mips-protos.h index 3d59b7b..0b8125a 100644 --- a/gcc/config/mips/mips-protos.h +++ b/gcc/config/mips/mips-protos.h @@ -315,6 +315,7 @@ extern bool mips16e_save_restore_pattern_p (rtx, HOST_WIDE_INT, extern bool mask_low_and_shift_p (enum machine_mode, rtx, rtx, int); extern int mask_low_and_shift_len (enum machine_mode, rtx, rtx); extern bool and_operands_ok (enum machine_mode, rtx, rtx); +extern bool mips_fmadd_bypass (rtx, rtx); union mips_gen_fn_ptrs { diff --git a/gcc/config/mips/mips.c b/gcc/config/mips/mips.c index 143169b..5fd6878 100644 --- a/gcc/config/mips/mips.c +++ b/gcc/config/mips/mips.c @@ -1173,6 +1173,19 @@ static const struct mips_rtx_cost_data COSTS_N_INSNS (68), /* int_div_di */ 1, /* branch_cost */ 4 /* memory_latency */ + }, + { /* P5600 */ + COSTS_N_INSNS (4), /* fp_add */ + COSTS_N_INSNS (5), /* fp_mult_sf */ + COSTS_N_INSNS (5), /* fp_mult_df */ + COSTS_N_INSNS (17), /* fp_div_sf */ + COSTS_N_INSNS (17), /* fp_div_df */ + COSTS_N_INSNS (5), /* int_mult_si */ + COSTS_N_INSNS (5), /* int_mult_di */ + COSTS_N_INSNS (8), /* int_div_si */ + COSTS_N_INSNS (8), /* int_div_di */ + 2, /* branch_cost */ + 10 /* memory_latency */ } }; @@ -13059,6 +13072,35 @@ mips_output_division (const char *division, rtx *operands) return s; } +/* Return true if destination of IN_INSN is used as add source in + OUT_INSN. Both IN_INSN and OUT_INSN are of type fmadd. Example: + madd.s dst, x, y, z + madd.s a, dst, b, c */ + +bool +mips_fmadd_bypass (rtx out_insn, rtx in_insn) +{ + int dst_reg, src_reg; + + gcc_assert (get_attr_type (in_insn) == TYPE_FMADD); + gcc_assert (get_attr_type (out_insn) == TYPE_FMADD); + + if (recog_memoized (in_insn) < 0 + || recog_memoized (out_insn) < 0) + return false; + + extract_insn (in_insn); + dst_reg = REG_P (recog_data.operand[0]); + + extract_insn (out_insn); + src_reg = REG_P (recog_data.operand[1]); + + if (dst_reg == src_reg) + return true; + + return false; +} + /* Return true if IN_INSN is a multiply-add or multiply-subtract instruction and if OUT_INSN assigns to the accumulator operand. */ @@ -13194,6 +13236,7 @@ mips_issue_rate (void) case PROCESSOR_LOONGSON_2E: case PROCESSOR_LOONGSON_2F: case PROCESSOR_LOONGSON_3A: + case PROCESSOR_P5600: return 4; case PROCESSOR_XLP: @@ -13329,6 +13372,9 @@ mips_multipass_dfa_lookahead (void) if (TUNE_OCTEON) return 2; + if (TUNE_P5600) + return 4; + return 0; } diff --git a/gcc/config/mips/mips.h b/gcc/config/mips/mips.h index a786d4c..f6cc4d5 100644 --- a/gcc/config/mips/mips.h +++ b/gcc/config/mips/mips.h @@ -232,6 +232,7 @@ struct mips_cpu_info { || mips_arch == PROCESSOR_SB1A) #define TARGET_SR71K (mips_arch == PROCESSOR_SR71000) #define TARGET_XLP (mips_arch == PROCESSOR_XLP) +#define TARGET_P5600 (mips_arch == PROCESSOR_P5600) /* Scheduling target defines. */ #define TUNE_20KC (mips_tune == PROCESSOR_20KC) @@ -260,6 +261,7 @@ struct mips_cpu_info { || mips_tune == PROCESSOR_OCTEON2) #define TUNE_SB1 (mips_tune == PROCESSOR_SB1 \ || mips_tune == PROCESSOR_SB1A) +#define TUNE_P5600 (mips_tune == PROCESSOR_P5600) /* Whether vector modes and intrinsics for ST Microelectronics Loongson-2E/2F processors should be enabled. In o32 pairs of @@ -302,7 +304,8 @@ struct mips_cpu_info { #define TUNE_MACC_CHAINS (TUNE_MIPS5500 \ || TUNE_MIPS4120 \ || TUNE_MIPS4130 \ - || TUNE_24K) + || TUNE_24K \ + || TUNE_P5600) #define TARGET_OLDABI (mips_abi == ABI_32 || mips_abi == ABI_O64) #define TARGET_NEWABI (mips_abi == ABI_N32 || mips_abi == ABI_64) @@ -699,7 +702,7 @@ struct mips_cpu_info { |march=r10000|march=r12000|march=r14000|march=r16000:-mips4} \ %{march=mips32|march=4kc|march=4km|march=4kp|march=4ksc:-mips32} \ %{march=mips32r2|march=m4k|march=4ke*|march=4ksd|march=24k* \ - |march=34k*|march=74k*|march=m14k*|march=1004k*: -mips32r2} \ + |march=34k*|march=74k*|march=m14k*|march=1004k*|march=p5600: -mips32r2} \ %{march=mips64|march=5k*|march=20k*|march=sb1*|march=sr71000 \ |march=xlr: -mips64} \ %{march=mips64r2|march=loongson3a|march=octeon|march=xlp: -mips64r2} \ diff --git a/gcc/config/mips/mips.md b/gcc/config/mips/mips.md index 1e3e9e6..32d1101 100644 --- a/gcc/config/mips/mips.md +++ b/gcc/config/mips/mips.md @@ -65,6 +65,7 @@ sr71000 xlr xlp + p5600 ]) (define_c_enum "unspec" [ @@ -1050,6 +1051,7 @@ (eq_attr "type" "ghost") "nothing") +(include "p5600.md") (include "4k.md") (include "5k.md") (include "20kc.md") diff --git a/gcc/config/mips/p5600.md b/gcc/config/mips/p5600.md new file mode 100644 index 0000000..706f83d --- /dev/null +++ b/gcc/config/mips/p5600.md @@ -0,0 +1,204 @@ +;; DFA-based pipeline description for P5600. +;; +;; Copyright (C) 2007-2014 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 +;; . + +(define_automaton "p5600_agen_pipe, p5600_alu_pipe, p5600_fpu_pipe") + +;; The address generation queue (AGQ) has AL2, CTISTD and LDSTA pipes +(define_cpu_unit "p5600_agq, p5600_al2, p5600_ctistd, p5600_ldsta, + p5600_gpdiv" "p5600_agen_pipe") + +;; The arithmetic-logic-unit queue (ALQ) has ALU pipe +(define_cpu_unit "p5600_alq, p5600_alu" "p5600_alu_pipe") + +;; The floating-point-unit queue (FPQ) has short and long pipes +(define_cpu_unit "p5600_fpu_short, p5600_fpu_long" "p5600_fpu_pipe") + +;; Short FPU pipeline +(define_cpu_unit "p5600_fpu_store" "p5600_fpu_pipe") + +;; Long FPU pipeline +(define_cpu_unit "p5600_fpu_apu" "p5600_fpu_pipe") + +(define_reservation "p5600_agq_al2" "p5600_agq, p5600_al2") +(define_reservation "p5600_agq_ctistd" "p5600_agq, p5600_ctistd") +(define_reservation "p5600_agq_ldsta" "p5600_agq, p5600_ldsta") +(define_reservation "p5600_alq_alu" "p5600_alq, p5600_alu") + +;; +;; FPU pipe +;; + +;; fadd, fsub +(define_insn_reservation "p5600_fpu_fadd" 4 + (eq_attr "type" "fadd,fabs,fneg") + "p5600_fpu_long, p5600_fpu_apu") + +;; fabs, fneg, fcmp +(define_insn_reservation "p5600_fpu_fabs" 2 + (eq_attr "type" "fabs,fneg,fcmp,fmove") + "p5600_fpu_short, p5600_fpu_apu") + +;; fload +(define_insn_reservation "p5600_fpu_fload" 8 + (eq_attr "type" "fpload,fpidxload") + "p5600_fpu_long, p5600_fpu_apu") + +;; fstore +(define_insn_reservation "p5600_fpu_fstore" 1 + (eq_attr "type" "fpstore,fpidxstore") + "p5600_fpu_short, p5600_fpu_apu") + +;; fmadd +(define_insn_reservation "p5600_fpu_fmadd" 9 + (eq_attr "type" "fmadd") + "p5600_fpu_long, p5600_fpu_apu") + +;; fmul +(define_insn_reservation "p5600_fpu_fmul" 5 + (eq_attr "type" "fmul") + "p5600_fpu_long, p5600_fpu_apu") + +;; fdiv, fsqrt +(define_insn_reservation "p5600_fpu_div" 17 + (eq_attr "type" "fdiv,frdiv,fsqrt,frsqrt") + "p5600_fpu_long, p5600_fpu_apu*17") + +;; fcvt +(define_insn_reservation "p5600_fpu_fcvt" 4 + (eq_attr "type" "fcvt") + "p5600_fpu_long, p5600_fpu_apu") + +;; mtc +(define_insn_reservation "p5600_fpu_fmtc" 7 + (eq_attr "type" "mtc") + "p5600_fpu_short, p5600_fpu_store") + +;; mfc +(define_insn_reservation "p5600_fpu_fmfc" 4 + (eq_attr "type" "mfc") + "p5600_fpu_short, p5600_fpu_store") + +;; madd/msub feeding into the add source +;; madd.fmt dst, x, y, z -> madd.fmt a, dst, b, c 5 cycles +(define_bypass 5 "p5600_fpu_fmadd" "p5600_fpu_fmadd" "mips_fmadd_bypass") + +;; +;; Integer pipe +;; + +;; AND +(define_insn_reservation "p5600_int_and" 1 + (eq_attr "move_type" "logical") + "p5600_alq_alu") + +;; LUI +(define_insn_reservation "p5600_int_lui" 1 + (eq_attr "move_type" "const") + "p5600_alq_alu") + +;; Load LB, LBU, LH, LHU, LQ, LW, LW_I2F, LWXS +(define_insn_reservation "p5600_int_load" 4 + (eq_attr "move_type" "load") + "p5600_agq_ldsta") + +;; store +(define_insn_reservation "p5600_int_store" 3 + (eq_attr "move_type" "store") + "p5600_agq_ldsta") + +;; ANDI, SLL, SRL, SEB, SEH +(define_insn_reservation "p5600_int_arith_1" 1 + (eq_attr "move_type" "andi,sll0,signext") + "p5600_agq_al2 | p5600_alq_alu") + +;; ADDI, ADDIU, ORI, XORI, ADD, ADDU +(define_insn_reservation "p5600_int_arith_2" 1 + (eq_attr "alu_type" "add,or,xor") + "p5600_agq_al2 | p5600_alq_alu") + +;; NOR, SUB +(define_insn_reservation "p5600_int_arith_3" 1 + (eq_attr "alu_type" "nor,sub") + "p5600_alq_alu") + +;; SRL, SRA, ROTR, SLT, SLLV, SRLV +(define_insn_reservation "p5600_int_arith_4" 1 + (eq_attr "type" "shift,slt,move") + "p5600_agq_al2 | p5600_alq_alu") + +;; NOP +(define_insn_reservation "p5600_int_nop" 0 + (eq_attr "type" "nop") + "p5600_agq_al2") + +;; CLO CLZ +(define_insn_reservation "p5600_int_countbits" 1 + (eq_attr "type" "clz") + "p5600_agq_al2") + +;; Conditional moves +(define_insn_reservation "p5600_int_condmove" 1 + (eq_attr "type" "condmove") + "p5600_agq_al2") + +;; MADD MSUB +(define_insn_reservation "p5600_dsp_mac" 5 + (eq_attr "type" "imadd") + "p5600_agq_al2") + +;; MFHI/LO +(define_insn_reservation "p5600_dsp_mfhilo" 1 + (eq_attr "type" "mfhi,mflo") + "p5600_agq_al2") + +;; MTHI/LO +(define_insn_reservation "p5600_dsp_mthilo" 5 + (eq_attr "type" "mthi,mtlo") + "p5600_agq_al2") + +;; MULT MULTU MUL +(define_insn_reservation "p5600_dsp_mult" 5 + (eq_attr "type" "imul3,imul") + "p5600_agq_al2") + +;; branch and jump +(define_insn_reservation "p5600_int_branch" 1 + (eq_attr "type" "branch,jump") + "p5600_agq_ctistd") + +;; prefetch +(define_insn_reservation "p5600_int_prefetch" 3 + (eq_attr "type" "prefetch,prefetchx") + "p5600_agq_ldsta") + +;; devide +(define_insn_reservation "p5600_int_div" 8 + (eq_attr "type" "idiv") + "p5600_agq_al2+p5600_gpdiv*8") + +;; arith +(define_insn_reservation "p5600_int_arith_5" 2 + (eq_attr "type" "arith") + "p5600_agq_al2") + +;; call +(define_insn_reservation "p5600_int_call" 2 + (eq_attr "jal" "indirect,direct") + "p5600_agq_ctistd")