Commit b99353a2 by Kito Cheng Committed by Chung-Ju Wu

[NDS32] Implment n9 pipeline.

gcc/
	* config.gcc (nds32*): Add nds32-utils.o into extra_objs.
	* config/nds32/nds32-n9-2r1w.md: New file.
	* config/nds32/nds32-n9-3r2w.md: New file.
	* config/nds32/nds32-opts.h (nds32_cpu_type, nds32_mul_type,
	nds32_register_ports): New or modify for cpu n9.
	* config/nds32/nds32-pipelines-auxiliary.c: Implementation for n9
	pipeline.
	* config/nds32/nds32-protos.h: More declarations for n9 pipeline.
	* config/nds32/nds32-utils.c: New file.
	* config/nds32/nds32.h (TARGET_PIPELINE_N9, TARGET_PIPELINE_SIMPLE,
	TARGET_MUL_SLOW): Define.
	* config/nds32/nds32.md (pipeline_model): New attribute.
	* config/nds32/nds32.opt (mcpu, mconfig-mul, mconfig-register-ports):
	New options that support cpu n9.
	* config/nds32/pipelines.md: Include n9 settings.
	* config/nds32/t-nds32 (nds32-utils.o): Add dependency.

Co-Authored-By: Chung-Ju Wu <jasonwucj@gmail.com>

From-SVN: r259218
parent 43fa41c1
2018-04-08 Kito Cheng <kito.cheng@gmail.com>
Chung-Ju Wu <jasonwucj@gmail.com>
* config.gcc (nds32*): Add nds32-utils.o into extra_objs.
* config/nds32/nds32-n9-2r1w.md: New file.
* config/nds32/nds32-n9-3r2w.md: New file.
* config/nds32/nds32-opts.h (nds32_cpu_type, nds32_mul_type,
nds32_register_ports): New or modify for cpu n9.
* config/nds32/nds32-pipelines-auxiliary.c: Implementation for n9
pipeline.
* config/nds32/nds32-protos.h: More declarations for n9 pipeline.
* config/nds32/nds32-utils.c: New file.
* config/nds32/nds32.h (TARGET_PIPELINE_N9, TARGET_PIPELINE_SIMPLE,
TARGET_MUL_SLOW): Define.
* config/nds32/nds32.md (pipeline_model): New attribute.
* config/nds32/nds32.opt (mcpu, mconfig-mul, mconfig-register-ports):
New options that support cpu n9.
* config/nds32/pipelines.md: Include n9 settings.
* config/nds32/t-nds32 (nds32-utils.o): Add dependency.
2018-04-08 Chung-Ju Wu <jasonwucj@gmail.com>
* config/nds32/nds32-md-auxiliary.c (output_cond_branch): Output align
......
......@@ -445,7 +445,7 @@ mips*-*-*)
nds32*)
cpu_type=nds32
extra_headers="nds32_intrinsic.h"
extra_objs="nds32-cost.o nds32-intrinsic.o nds32-isr.o nds32-md-auxiliary.o nds32-pipelines-auxiliary.o nds32-predicates.o nds32-memory-manipulation.o nds32-fp-as-gp.o nds32-relax-opt.o"
extra_objs="nds32-cost.o nds32-intrinsic.o nds32-isr.o nds32-md-auxiliary.o nds32-pipelines-auxiliary.o nds32-predicates.o nds32-memory-manipulation.o nds32-fp-as-gp.o nds32-relax-opt.o nds32-utils.o"
;;
nios2-*-*)
cpu_type=nios2
......
......@@ -34,6 +34,13 @@ enum nds32_arch_type
ARCH_V3S
};
/* The various ANDES CPU. */
enum nds32_cpu_type
{
CPU_N9,
CPU_SIMPLE
};
/* The code model defines the address generation strategy. */
enum nds32_cmodel_type
{
......@@ -42,10 +49,19 @@ enum nds32_cmodel_type
CMODEL_LARGE
};
/* The various ANDES CPU. */
enum nds32_cpu_type
/* Multiply instruction configuration. */
enum nds32_mul_type
{
MUL_TYPE_FAST_1,
MUL_TYPE_FAST_2,
MUL_TYPE_SLOW
};
/* Register ports configuration. */
enum nds32_register_ports
{
CPU_N9
REG_PORT_3R2W,
REG_PORT_2R1W
};
/* Which ABI to use. */
......
......@@ -97,6 +97,13 @@ extern void nds32_expand_unaligned_store (rtx *, enum machine_mode);
extern bool nds32_valid_multiple_load_store_p (rtx, bool, bool);
/* Auxiliary functions for guard function checking in pipelines.md. */
extern bool nds32_n9_2r1w_mm_to_ex_p (rtx_insn *, rtx_insn *);
extern bool nds32_n9_3r2w_mm_to_ex_p (rtx_insn *, rtx_insn *);
extern bool nds32_n9_last_load_to_ex_p (rtx_insn *, rtx_insn *);
/* Auxiliary functions for stack operation predicate checking. */
extern bool nds32_valid_stack_push_pop_p (rtx, bool);
......@@ -225,6 +232,29 @@ extern void nds32_cpu_cpp_builtins(struct cpp_reader *);
extern bool nds32_split_double_word_load_store_p (rtx *,bool);
namespace nds32 {
extern rtx extract_pattern_from_insn (rtx);
size_t parallel_elements (rtx);
rtx parallel_element (rtx, int);
bool load_single_p (rtx_insn *);
bool store_single_p (rtx_insn *);
bool load_double_p (rtx_insn *);
bool store_double_p (rtx_insn *);
bool post_update_insn_p (rtx_insn *);
bool immed_offset_p (rtx);
int find_post_update_rtx (rtx_insn *);
rtx extract_mem_rtx (rtx_insn *);
rtx extract_base_reg (rtx_insn *);
rtx extract_shift_reg (rtx);
bool movd44_insn_p (rtx_insn *);
rtx extract_mac_non_acc_rtx (rtx_insn *);
} // namespace nds32
/* Functions for create nds32 specific optimization pass. */
extern rtl_opt_pass *make_pass_nds32_relax_opt (gcc::context *);
......
/* Auxiliary functions for pipeline descriptions pattern of Andes
NDS32 cpu for GNU compiler
Copyright (C) 2012-2018 Free Software Foundation, Inc.
Contributed by Andes Technology Corporation.
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 IN_TARGET_CODE 1
#include "config.h"
#include "system.h"
#include "coretypes.h"
#include "backend.h"
#include "target.h"
#include "rtl.h"
#include "tree.h"
#include "memmodel.h"
#include "tm_p.h"
#include "optabs.h" /* For GEN_FCN. */
#include "recog.h"
#include "tm-constrs.h"
#include "insn-attr.h"
namespace nds32 {
/* Get the rtx in the PATTERN field of an insn. If INSN is not an insn,
the funciton doesn't change anything and returns it directly. */
rtx
extract_pattern_from_insn (rtx insn)
{
if (INSN_P (insn))
return PATTERN (insn);
return insn;
}
/* Get the number of elements in a parallel rtx. */
size_t
parallel_elements (rtx parallel_rtx)
{
parallel_rtx = extract_pattern_from_insn (parallel_rtx);
gcc_assert (GET_CODE (parallel_rtx) == PARALLEL);
return XVECLEN (parallel_rtx, 0);
}
/* Extract an rtx from a parallel rtx with index NTH. If NTH is a negative
value, the function returns the last NTH rtx. */
rtx
parallel_element (rtx parallel_rtx, int nth)
{
parallel_rtx = extract_pattern_from_insn (parallel_rtx);
gcc_assert (GET_CODE (parallel_rtx) == PARALLEL);
int len = parallel_elements (parallel_rtx);
if (nth >= 0)
{
if (nth >= len)
return NULL_RTX;
return XVECEXP (parallel_rtx, 0, nth);
}
else
{
if (len + nth < 0)
return NULL_RTX;
return XVECEXP (parallel_rtx, 0, len + nth);
}
}
/* Functions to determine whether INSN is single-word, double-word
or partial-word load/store insn. */
bool
load_single_p (rtx_insn *insn)
{
if (get_attr_type (insn) != TYPE_LOAD)
return false;
if (INSN_CODE (insn) == CODE_FOR_move_di ||
INSN_CODE (insn) == CODE_FOR_move_df)
return false;
return true;
}
bool
store_single_p (rtx_insn *insn)
{
if (get_attr_type (insn) != TYPE_STORE)
return false;
if (INSN_CODE (insn) == CODE_FOR_move_di ||
INSN_CODE (insn) == CODE_FOR_move_df)
return false;
return true;
}
bool
load_double_p (rtx_insn *insn)
{
if (get_attr_type (insn) != TYPE_LOAD)
return false;
if (INSN_CODE (insn) != CODE_FOR_move_di &&
INSN_CODE (insn) != CODE_FOR_move_df)
return false;
return true;
}
bool
store_double_p (rtx_insn *insn)
{
if (get_attr_type (insn) != TYPE_STORE)
return false;
if (INSN_CODE (insn) != CODE_FOR_move_di &&
INSN_CODE (insn) != CODE_FOR_move_df)
return false;
return true;
}
/* Determine if INSN is a post update insn. */
bool
post_update_insn_p (rtx_insn *insn)
{
if (find_post_update_rtx (insn) == -1)
return false;
else
return true;
}
/* Check if the address of MEM_RTX consists of a base register and an
immediate offset. */
bool
immed_offset_p (rtx mem_rtx)
{
gcc_assert (MEM_P (mem_rtx));
rtx addr_rtx = XEXP (mem_rtx, 0);
/* (mem (reg)) is equivalent to (mem (plus (reg) (const_int 0))) */
if (REG_P (addr_rtx))
return true;
/* (mem (plus (reg) (const_int))) */
if (GET_CODE (addr_rtx) == PLUS
&& GET_CODE (XEXP (addr_rtx, 1)) == CONST_INT)
return true;
return false;
}
/* Find the post update rtx in INSN. If INSN is a load/store multiple insn,
the function returns the vector index of its parallel part. If INSN is a
single load/store insn, the function returns 0. If INSN is not a post-
update insn, the function returns -1. */
int
find_post_update_rtx (rtx_insn *insn)
{
rtx mem_rtx;
int i, len;
switch (get_attr_type (insn))
{
case TYPE_LOAD_MULTIPLE:
case TYPE_STORE_MULTIPLE:
/* Find a pattern in a parallel rtx:
(set (reg) (plus (reg) (const_int))) */
len = parallel_elements (insn);
for (i = 0; i < len; ++i)
{
rtx curr_insn = parallel_element (insn, i);
if (GET_CODE (curr_insn) == SET
&& REG_P (SET_DEST (curr_insn))
&& GET_CODE (SET_SRC (curr_insn)) == PLUS)
return i;
}
return -1;
case TYPE_LOAD:
case TYPE_FLOAD:
case TYPE_STORE:
case TYPE_FSTORE:
mem_rtx = extract_mem_rtx (insn);
/* (mem (post_inc (reg))) */
switch (GET_CODE (XEXP (mem_rtx, 0)))
{
case POST_INC:
case POST_DEC:
case POST_MODIFY:
return 0;
default:
return -1;
}
default:
gcc_unreachable ();
}
}
/* Extract the MEM rtx from a load/store insn. */
rtx
extract_mem_rtx (rtx_insn *insn)
{
rtx body = PATTERN (insn);
switch (get_attr_type (insn))
{
case TYPE_LOAD:
case TYPE_FLOAD:
if (MEM_P (SET_SRC (body)))
return SET_SRC (body);
/* unaligned address: (unspec [(mem)]) */
if (GET_CODE (SET_SRC (body)) == UNSPEC)
{
gcc_assert (MEM_P (XVECEXP (SET_SRC (body), 0, 0)));
return XVECEXP (SET_SRC (body), 0, 0);
}
/* (sign_extend (mem)) */
gcc_assert (MEM_P (XEXP (SET_SRC (body), 0)));
return XEXP (SET_SRC (body), 0);
case TYPE_STORE:
case TYPE_FSTORE:
if (MEM_P (SET_DEST (body)))
return SET_DEST (body);
/* unaligned address: (unspec [(mem)]) */
if (GET_CODE (SET_DEST (body)) == UNSPEC)
{
gcc_assert (MEM_P (XVECEXP (SET_DEST (body), 0, 0)));
return XVECEXP (SET_DEST (body), 0, 0);
}
/* (sign_extend (mem)) */
gcc_assert (MEM_P (XEXP (SET_DEST (body), 0)));
return XEXP (SET_DEST (body), 0);
default:
gcc_unreachable ();
}
}
/* Extract the base register from load/store insns. The function returns
NULL_RTX if the address is not consist of any registers. */
rtx
extract_base_reg (rtx_insn *insn)
{
int post_update_rtx_index;
rtx mem_rtx;
rtx plus_rtx;
/* Find the MEM rtx. If we can find an insn updating the base register,
the base register will be returned directly. */
switch (get_attr_type (insn))
{
case TYPE_LOAD_MULTIPLE:
post_update_rtx_index = find_post_update_rtx (insn);
if (post_update_rtx_index != -1)
return SET_DEST (parallel_element (insn, post_update_rtx_index));
mem_rtx = SET_SRC (parallel_element (insn, 0));
break;
case TYPE_STORE_MULTIPLE:
post_update_rtx_index = find_post_update_rtx (insn);
if (post_update_rtx_index != -1)
return SET_DEST (parallel_element (insn, post_update_rtx_index));
mem_rtx = SET_DEST (parallel_element (insn, 0));
break;
case TYPE_LOAD:
case TYPE_FLOAD:
case TYPE_STORE:
case TYPE_FSTORE:
mem_rtx = extract_mem_rtx (insn);
break;
default:
gcc_unreachable ();
}
gcc_assert (MEM_P (mem_rtx));
/* (mem (reg)) */
if (REG_P (XEXP (mem_rtx, 0)))
return XEXP (mem_rtx, 0);
plus_rtx = XEXP (mem_rtx, 0);
if (GET_CODE (plus_rtx) == SYMBOL_REF
|| GET_CODE (plus_rtx) == CONST)
return NULL_RTX;
gcc_assert (GET_CODE (plus_rtx) == PLUS
|| GET_CODE (plus_rtx) == POST_INC
|| GET_CODE (plus_rtx) == POST_DEC
|| GET_CODE (plus_rtx) == POST_MODIFY);
gcc_assert (REG_P (XEXP (plus_rtx, 0)));
/* (mem (plus (reg) (const_int))) or
(mem (post_inc (reg))) or
(mem (post_dec (reg))) or
(mem (post_modify (reg) (plus (reg) (reg)))) */
return XEXP (plus_rtx, 0);
}
/* Extract the register of the shift operand from an ALU_SHIFT rtx. */
rtx
extract_shift_reg (rtx alu_shift_rtx)
{
alu_shift_rtx = extract_pattern_from_insn (alu_shift_rtx);
rtx alu_rtx = SET_SRC (alu_shift_rtx);
rtx shift_rtx;
/* Various forms of ALU_SHIFT can be made by the combiner.
See the difference between add_slli and sub_slli in nds32.md. */
if (REG_P (XEXP (alu_rtx, 0)))
shift_rtx = XEXP (alu_rtx, 1);
else
shift_rtx = XEXP (alu_rtx, 0);
return XEXP (shift_rtx, 0);
}
/* Check if INSN is a movd44 insn. */
bool
movd44_insn_p (rtx_insn *insn)
{
if (get_attr_type (insn) == TYPE_ALU
&& (INSN_CODE (insn) == CODE_FOR_move_di
|| INSN_CODE (insn) == CODE_FOR_move_df))
{
rtx body = PATTERN (insn);
gcc_assert (GET_CODE (body) == SET);
rtx src = SET_SRC (body);
rtx dest = SET_DEST (body);
if ((REG_P (src) || GET_CODE (src) == SUBREG)
&& (REG_P (dest) || GET_CODE (dest) == SUBREG))
return true;
return false;
}
return false;
}
/* Extract the rtx representing non-accumulation operands of a MAC insn. */
rtx
extract_mac_non_acc_rtx (rtx_insn *insn)
{
rtx exp = SET_SRC (PATTERN (insn));
switch (get_attr_type (insn))
{
case TYPE_MAC:
if (REG_P (XEXP (exp, 0)))
return XEXP (exp, 1);
else
return XEXP (exp, 0);
default:
gcc_unreachable ();
}
}
} // namespace nds32
......@@ -502,6 +502,11 @@ enum nds32_builtins
|| nds32_arch_option == ARCH_V3S)
#define TARGET_ISA_V3M (nds32_arch_option == ARCH_V3M)
#define TARGET_PIPELINE_N9 \
(nds32_cpu_option == CPU_N9)
#define TARGET_PIPELINE_SIMPLE \
(nds32_cpu_option == CPU_SIMPLE)
#define TARGET_CMODEL_SMALL \
(nds32_cmodel_option == CMODEL_SMALL)
#define TARGET_CMODEL_MEDIUM \
......@@ -515,6 +520,8 @@ enum nds32_builtins
(nds32_cmodel_option == CMODEL_SMALL\
|| nds32_cmodel_option == CMODEL_MEDIUM)
#define TARGET_MUL_SLOW \
(nds32_mul_config == MUL_TYPE_SLOW)
/* Run-time Target Specification. */
#define TARGET_SOFT_FLOAT (nds32_abi == NDS32_ABI_V2)
......@@ -553,6 +560,7 @@ enum nds32_builtins
" %{!mno-ext-fpu-dp:%{!mext-fpu-dp:-mext-fpu-dp}}}" \
" %{march=v3s:%{!mfloat-abi=*:-mfloat-abi=hard}" \
" %{!mno-ext-fpu-sp:%{!mext-fpu-sp:-mext-fpu-sp}}}" }, \
{"cpu", "%{!mcpu=*:-mcpu=%(VALUE)}" }, \
{"float", "%{!mfloat-abi=*:-mfloat-abi=%(VALUE)}" }
#define CC1_SPEC \
......
......@@ -53,6 +53,15 @@
(include "nds32-peephole2.md")
;; ------------------------------------------------------------------------
;; CPU pipeline model.
(define_attr "pipeline_model" "n9,simple"
(const
(cond [(match_test "nds32_cpu_option == CPU_N9") (const_string "n9")
(match_test "nds32_cpu_option == CPU_SIMPLE") (const_string "simple")]
(const_string "n9"))))
;; Insn type, it is used to default other attribute values.
(define_attr "type"
"unknown,load,store,load_multiple,store_multiple,alu,alu_shift,pbsad,pbsada,mul,mac,div,branch,mmu,misc,\
......
......@@ -177,6 +177,21 @@ Known cpu types (for use with the -mcpu= option):
EnumValue
Enum(nds32_cpu_type) String(n9) Value(CPU_N9)
EnumValue
Enum(nds32_cpu_type) String(n903) Value(CPU_N9)
EnumValue
Enum(nds32_cpu_type) String(n903a) Value(CPU_N9)
EnumValue
Enum(nds32_cpu_type) String(n968) Value(CPU_N9)
EnumValue
Enum(nds32_cpu_type) String(n968a) Value(CPU_N9)
EnumValue
Enum(nds32_cpu_type) String(simple) Value(CPU_SIMPLE)
mconfig-fpu=
Target RejectNegative Joined Enum(float_reg_number) Var(nds32_fp_regnum) Init(TARGET_CONFIG_FPU_DEFAULT)
Specify a fpu configuration value from 0 to 7; 0-3 is as FPU spec says, and 4-7 is corresponding to 0-3.
......@@ -209,6 +224,38 @@ Enum(float_reg_number) String(6) Value(NDS32_CONFIG_FPU_6)
EnumValue
Enum(float_reg_number) String(7) Value(NDS32_CONFIG_FPU_7)
mconfig-mul=
Target RejectNegative Joined Enum(nds32_mul_type) Var(nds32_mul_config) Init(MUL_TYPE_FAST_1)
Specify configuration of instruction mul: fast1, fast2 or slow. The default is fast1.
Enum
Name(nds32_mul_type) Type(enum nds32_mul_type)
EnumValue
Enum(nds32_mul_type) String(fast) Value(MUL_TYPE_FAST_1)
EnumValue
Enum(nds32_mul_type) String(fast1) Value(MUL_TYPE_FAST_1)
EnumValue
Enum(nds32_mul_type) String(fast2) Value(MUL_TYPE_FAST_2)
EnumValue
Enum(nds32_mul_type) String(slow) Value(MUL_TYPE_SLOW)
mconfig-register-ports=
Target RejectNegative Joined Enum(nds32_register_ports) Var(nds32_register_ports_config) Init(REG_PORT_3R2W)
Specify how many read/write ports for n9/n10 cores. The value should be 3r2w or 2r1w.
Enum
Name(nds32_register_ports) Type(enum nds32_register_ports)
EnumValue
Enum(nds32_register_ports) String(3r2w) Value(REG_PORT_3R2W)
EnumValue
Enum(nds32_register_ports) String(2r1w) Value(REG_PORT_2R1W)
mctor-dtor
Target Report
Enable constructor/destructor feature.
......
......@@ -18,12 +18,24 @@
;; along with GCC; see the file COPYING3. If not see
;; <http://www.gnu.org/licenses/>.
(define_automaton "nds32_machine")
(define_cpu_unit "general_unit" "nds32_machine")
;; ------------------------------------------------------------------------
;; Include N9/N10 pipeline settings.
;; ------------------------------------------------------------------------
(include "nds32-n9-3r2w.md")
(include "nds32-n9-2r1w.md")
;; ------------------------------------------------------------------------
;; Define simple pipeline settings.
;; ------------------------------------------------------------------------
(define_automaton "nds32_simple_machine")
(define_cpu_unit "simple_unit" "nds32_simple_machine")
(define_insn_reservation "simple_insn" 1
(eq_attr "type" "unknown,load,store,load_multiple,store_multiple,alu,alu_shift,mul,mac,div,branch,mmu,misc")
"general_unit")
(eq_attr "pipeline_model" "simple")
"simple_unit")
;; ------------------------------------------------------------------------
......@@ -131,3 +131,16 @@ nds32-relax-opt.o: \
intl.h libfuncs.h $(PARAMS_H) $(OPTS_H)
$(COMPILER) -c $(ALL_COMPILERFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) \
$(srcdir)/config/nds32/nds32-relax-opt.c
nds32-utils.o: \
$(srcdir)/config/nds32/nds32-utils.c \
$(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
$(RTL_H) $(TREE_H) $(HASH_TABLE_H) $(OBSTACK_H) $(REGS_H) hard-reg-set.h \
insn-config.h conditions.h output.h dumpfile.h \
$(INSN_ATTR_H) $(FLAGS_H) reload.h $(FUNCTION_H) \
$(EXPR_H) $(OPTABS_H) $(RECOG_H) $(CGRAPH_H) \
$(GGC_H) except.h $(C_PRAGMA_H) $(TM_P_H) \
$(TARGET_H) $(TARGET_DEF_H) debug.h langhooks.h $(DF_H) \
intl.h libfuncs.h $(PARAMS_H) $(OPTS_H)
$(COMPILER) -c $(ALL_COMPILERFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) \
$(srcdir)/config/nds32/nds32-utils.c
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment