aboutsummaryrefslogtreecommitdiff
path: root/gcc/config/sparc
diff options
context:
space:
mode:
authorEric Botcazou <ebotcazou@adacore.com>2013-07-22 21:41:44 +0000
committerEric Botcazou <ebotcazou@gcc.gnu.org>2013-07-22 21:41:44 +0000
commit38ae58ca9fd17ebf4fe679fe7a91472f5d6c37b1 (patch)
tree456e7a0274b3b7a7b98769954c1ec28425700400 /gcc/config/sparc
parent16a1d8fe2955c301ae61a13c4cbf8bd2c83d17f0 (diff)
downloadgcc-38ae58ca9fd17ebf4fe679fe7a91472f5d6c37b1.zip
gcc-38ae58ca9fd17ebf4fe679fe7a91472f5d6c37b1.tar.gz
gcc-38ae58ca9fd17ebf4fe679fe7a91472f5d6c37b1.tar.bz2
config.gcc (sparc*-*-*): Accept leon3 processor.
* config.gcc (sparc*-*-*): Accept leon3 processor. (sparc-leon*-*): Merge with sparc*-*-* and add leon3 support. * doc/invoke.texi (SPARC Options): Adjust -mfix-ut699 entry. * config/sparc/sparc-opts.h (enum processor_type): Add PROCESSOR_LEON3. * config/sparc/sparc.opt (enum processor_type): Add leon3. (mfix-ut699): Adjust comment. * config/sparc/sparc.h (TARGET_CPU_leon3): New define. (CPP_CPU32_DEFAULT_SPEC): Add leon3 support. (CPP_CPU_SPEC): Likewise. (ASM_CPU_SPEC): Likewise. * config/sparc/sparc.c (leon3_cost): New constant. (sparc_option_override): Add leon3 support. (mem_ref): New function. (sparc_gate_work_around_errata): Return true if -mfix-ut699 is enabled. (sparc_do_work_around_errata): Look into the instruction in the delay slot and adjust accordingly. Add fix for the data cache nullify issues of the UT699. Change insertion position for the NOP. * config/sparc/leon.md (leon_fpalu, leon_fpmds, write_buf): Delete. (leon3_load): New reservation. (leon_store): Bump latency to 2. (grfpu): New automaton. (grfpu_alu): New unit. (grfpu_ds): Likewise. (leon_fp_alu): Adjust. (leon_fp_mult): Delete. (leon_fp_div): Split into leon_fp_divs and leon_fp_divd. (leon_fp_sqrt): Split into leon_fp_sqrts and leon_fp_sqrtd. * config/sparc/sparc.md (cpu): Add leon3. * config/sparc/sync.md (atomic_exchangesi): Disable if -mfix-ut699. (swapsi): Likewise. (atomic_test_and_set): Likewise. (ldstub): Likewise. From-SVN: r201147
Diffstat (limited to 'gcc/config/sparc')
-rw-r--r--gcc/config/sparc/leon.md66
-rw-r--r--gcc/config/sparc/sparc-opts.h1
-rw-r--r--gcc/config/sparc/sparc.c123
-rw-r--r--gcc/config/sparc/sparc.h36
-rw-r--r--gcc/config/sparc/sparc.md3
-rw-r--r--gcc/config/sparc/sparc.opt5
-rw-r--r--gcc/config/sparc/sync.md8
7 files changed, 179 insertions, 63 deletions
diff --git a/gcc/config/sparc/leon.md b/gcc/config/sparc/leon.md
index 6081507..b511397 100644
--- a/gcc/config/sparc/leon.md
+++ b/gcc/config/sparc/leon.md
@@ -17,40 +17,48 @@
;; along with GCC; see the file COPYING3. If not see
;; <http://www.gnu.org/licenses/>.
+;; Leon is a single-issue processor.
(define_automaton "leon")
-(define_cpu_unit "leon_memory, leon_fpalu" "leon")
-(define_cpu_unit "leon_fpmds" "leon")
-(define_cpu_unit "write_buf" "leon")
+(define_cpu_unit "leon_memory" "leon")
(define_insn_reservation "leon_load" 1
- (and (eq_attr "cpu" "leon")
- (eq_attr "type" "load,sload,fpload"))
+ (and (eq_attr "cpu" "leon") (eq_attr "type" "load,sload"))
"leon_memory")
-(define_insn_reservation "leon_store" 1
- (and (eq_attr "cpu" "leon")
- (eq_attr "type" "store,fpstore"))
- "leon_memory+write_buf")
-
-(define_insn_reservation "leon_fp_alu" 1
- (and (eq_attr "cpu" "leon")
- (eq_attr "type" "fp,fpmove"))
- "leon_fpalu, nothing")
-
-(define_insn_reservation "leon_fp_mult" 1
- (and (eq_attr "cpu" "leon")
- (eq_attr "type" "fpmul"))
- "leon_fpmds, nothing")
-
-(define_insn_reservation "leon_fp_div" 16
- (and (eq_attr "cpu" "leon")
- (eq_attr "type" "fpdivs,fpdivd"))
- "leon_fpmds, nothing*15")
-
-(define_insn_reservation "leon_fp_sqrt" 23
- (and (eq_attr "cpu" "leon")
- (eq_attr "type" "fpsqrts,fpsqrtd"))
- "leon_fpmds, nothing*21")
+;; Use a double reservation to work around the load pipeline hazard on UT699.
+(define_insn_reservation "leon3_load" 1
+ (and (eq_attr "cpu" "leon3") (eq_attr "type" "load,sload"))
+ "leon_memory*2")
+(define_insn_reservation "leon_store" 2
+ (and (eq_attr "cpu" "leon,leon3") (eq_attr "type" "store"))
+ "leon_memory*2")
+
+;; This describes Gaisler Research's FPU
+
+(define_automaton "grfpu")
+
+(define_cpu_unit "grfpu_alu" "grfpu")
+(define_cpu_unit "grfpu_ds" "grfpu")
+
+(define_insn_reservation "leon_fp_alu" 4
+ (and (eq_attr "cpu" "leon,leon3") (eq_attr "type" "fp,fpcmp,fpmul"))
+ "grfpu_alu, nothing*3")
+
+(define_insn_reservation "leon_fp_divs" 16
+ (and (eq_attr "cpu" "leon,leon3") (eq_attr "type" "fpdivs"))
+ "grfpu_ds*14, nothing*2")
+
+(define_insn_reservation "leon_fp_divd" 17
+ (and (eq_attr "cpu" "leon,leon3") (eq_attr "type" "fpdivd"))
+ "grfpu_ds*15, nothing*2")
+
+(define_insn_reservation "leon_fp_sqrts" 24
+ (and (eq_attr "cpu" "leon,leon3") (eq_attr "type" "fpsqrts"))
+ "grfpu_ds*22, nothing*2")
+
+(define_insn_reservation "leon_fp_sqrtd" 25
+ (and (eq_attr "cpu" "leon,leon3") (eq_attr "type" "fpsqrtd"))
+ "grfpu_ds*23, nothing*2")
diff --git a/gcc/config/sparc/sparc-opts.h b/gcc/config/sparc/sparc-opts.h
index 7279177..b5e9761 100644
--- a/gcc/config/sparc/sparc-opts.h
+++ b/gcc/config/sparc/sparc-opts.h
@@ -30,6 +30,7 @@ enum processor_type {
PROCESSOR_SUPERSPARC,
PROCESSOR_HYPERSPARC,
PROCESSOR_LEON,
+ PROCESSOR_LEON3,
PROCESSOR_SPARCLITE,
PROCESSOR_F930,
PROCESSOR_F934,
diff --git a/gcc/config/sparc/sparc.c b/gcc/config/sparc/sparc.c
index d473d6f..48c25dc 100644
--- a/gcc/config/sparc/sparc.c
+++ b/gcc/config/sparc/sparc.c
@@ -227,6 +227,30 @@ struct processor_costs leon_costs = {
};
static const
+struct processor_costs leon3_costs = {
+ COSTS_N_INSNS (1), /* int load */
+ COSTS_N_INSNS (1), /* int signed load */
+ COSTS_N_INSNS (1), /* int zeroed load */
+ COSTS_N_INSNS (1), /* float load */
+ COSTS_N_INSNS (1), /* fmov, fneg, fabs */
+ COSTS_N_INSNS (1), /* fadd, fsub */
+ COSTS_N_INSNS (1), /* fcmp */
+ COSTS_N_INSNS (1), /* fmov, fmovr */
+ COSTS_N_INSNS (1), /* fmul */
+ COSTS_N_INSNS (14), /* fdivs */
+ COSTS_N_INSNS (15), /* fdivd */
+ COSTS_N_INSNS (22), /* fsqrts */
+ COSTS_N_INSNS (23), /* fsqrtd */
+ COSTS_N_INSNS (5), /* imul */
+ COSTS_N_INSNS (5), /* imulX */
+ 0, /* imul bit factor */
+ COSTS_N_INSNS (35), /* idiv */
+ COSTS_N_INSNS (35), /* idivX */
+ COSTS_N_INSNS (1), /* movcc/movr */
+ 0, /* shift penalty */
+};
+
+static const
struct processor_costs sparclet_costs = {
COSTS_N_INSNS (3), /* int load */
COSTS_N_INSNS (3), /* int signed load */
@@ -805,17 +829,31 @@ char sparc_hard_reg_printed[8];
struct gcc_target targetm = TARGET_INITIALIZER;
+/* Return the memory reference contained in X if any, zero otherwise. */
+
+static rtx
+mem_ref (rtx x)
+{
+ if (GET_CODE (x) == SIGN_EXTEND || GET_CODE (x) == ZERO_EXTEND)
+ x = XEXP (x, 0);
+
+ if (MEM_P (x))
+ return x;
+
+ return NULL_RTX;
+}
+
/* We use a machine specific pass to enable workarounds for errata.
We need to have the (essentially) final form of the insn stream in order
to properly detect the various hazards. Therefore, this machine specific
pass runs as late as possible. The pass is inserted in the pass pipeline
- at the end of sparc_options_override. */
+ at the end of sparc_option_override. */
static bool
sparc_gate_work_around_errata (void)
{
- /* The only erratum we handle for now is that of the AT697F processor. */
- return sparc_fix_at697f != 0;
+ /* The only errata we handle are those of the AT697F and UT699. */
+ return sparc_fix_at697f != 0 || sparc_fix_ut699 != 0;
}
static unsigned int
@@ -823,14 +861,22 @@ sparc_do_work_around_errata (void)
{
rtx insn, next;
+ /* Force all instructions to be split into their final form. */
+ split_all_insns_noflow ();
+
/* Now look for specific patterns in the insn stream. */
for (insn = get_insns (); insn; insn = next)
{
bool insert_nop = false;
rtx set;
+ /* Look into the instruction in a delay slot. */
+ if (NONJUMP_INSN_P (insn) && GET_CODE (PATTERN (insn)) == SEQUENCE)
+ insn = XVECEXP (PATTERN (insn), 0, 1);
+
/* Look for a single-word load into an odd-numbered FP register. */
- if (NONJUMP_INSN_P (insn)
+ if (sparc_fix_at697f
+ && NONJUMP_INSN_P (insn)
&& (set = single_set (insn)) != NULL_RTX
&& GET_MODE_SIZE (GET_MODE (SET_SRC (set))) == 4
&& MEM_P (SET_SRC (set))
@@ -845,13 +891,13 @@ sparc_do_work_around_errata (void)
/* If the insn has a delay slot, then it cannot be problematic. */
next = next_active_insn (insn);
+ if (!next)
+ break;
if (NONJUMP_INSN_P (next) && GET_CODE (PATTERN (next)) == SEQUENCE)
- code = -1;
- else
- {
- extract_insn (next);
- code = INSN_CODE (next);
- }
+ continue;
+
+ extract_insn (next);
+ code = INSN_CODE (next);
switch (code)
{
@@ -897,12 +943,60 @@ sparc_do_work_around_errata (void)
break;
}
}
+
+ /* Look for a single-word load into an integer register. */
+ else if (sparc_fix_ut699
+ && NONJUMP_INSN_P (insn)
+ && (set = single_set (insn)) != NULL_RTX
+ && GET_MODE_SIZE (GET_MODE (SET_SRC (set))) <= 4
+ && mem_ref (SET_SRC (set)) != NULL_RTX
+ && REG_P (SET_DEST (set))
+ && REGNO (SET_DEST (set)) < 32)
+ {
+ /* There is no problem if the second memory access has a data
+ dependency on the first single-cycle load. */
+ rtx x = SET_DEST (set);
+
+ /* If the insn has a delay slot, then it cannot be problematic. */
+ next = next_active_insn (insn);
+ if (!next)
+ break;
+ if (NONJUMP_INSN_P (next) && GET_CODE (PATTERN (next)) == SEQUENCE)
+ continue;
+
+ /* Look for a second memory access to/from an integer register. */
+ if ((set = single_set (next)) != NULL_RTX)
+ {
+ rtx src = SET_SRC (set);
+ rtx dest = SET_DEST (set);
+ rtx mem;
+
+ /* LDD is affected. */
+ if ((mem = mem_ref (src)) != NULL_RTX
+ && REG_P (dest)
+ && REGNO (dest) < 32
+ && !reg_mentioned_p (x, XEXP (mem, 0)))
+ insert_nop = true;
+
+ /* STD is *not* affected. */
+ else if ((mem = mem_ref (dest)) != NULL_RTX
+ && GET_MODE_SIZE (GET_MODE (mem)) <= 4
+ && (src == const0_rtx
+ || (REG_P (src)
+ && REGNO (src) < 32
+ && REGNO (src) != REGNO (x)))
+ && !reg_mentioned_p (x, XEXP (mem, 0)))
+ insert_nop = true;
+ }
+ }
+
else
next = NEXT_INSN (insn);
if (insert_nop)
- emit_insn_after (gen_nop (), insn);
+ emit_insn_before (gen_nop (), next);
}
+
return 0;
}
@@ -1019,6 +1113,7 @@ sparc_option_override (void)
{ TARGET_CPU_supersparc, PROCESSOR_SUPERSPARC },
{ TARGET_CPU_hypersparc, PROCESSOR_HYPERSPARC },
{ TARGET_CPU_leon, PROCESSOR_LEON },
+ { TARGET_CPU_leon3, PROCESSOR_LEON3 },
{ TARGET_CPU_sparclite, PROCESSOR_F930 },
{ TARGET_CPU_sparclite86x, PROCESSOR_SPARCLITE86X },
{ TARGET_CPU_sparclet, PROCESSOR_TSC701 },
@@ -1033,7 +1128,7 @@ sparc_option_override (void)
};
const struct cpu_default *def;
/* Table of values for -m{cpu,tune}=. This must match the order of
- the PROCESSOR_* enumeration. */
+ the enum processor_type in sparc-opts.h. */
static struct cpu_table {
const char *const name;
const int disable;
@@ -1047,6 +1142,7 @@ sparc_option_override (void)
{ "hypersparc", MASK_ISA, MASK_V8|MASK_FPU },
/* LEON */
{ "leon", MASK_ISA, MASK_V8|MASK_FPU },
+ { "leon3", MASK_ISA, MASK_V8|MASK_FPU },
{ "sparclite", MASK_ISA, MASK_SPARCLITE },
/* The Fujitsu MB86930 is the original sparclite chip, with no FPU. */
{ "f930", MASK_ISA|MASK_FPU, MASK_SPARCLITE },
@@ -1295,6 +1391,9 @@ sparc_option_override (void)
case PROCESSOR_LEON:
sparc_costs = &leon_costs;
break;
+ case PROCESSOR_LEON3:
+ sparc_costs = &leon3_costs;
+ break;
case PROCESSOR_SPARCLET:
case PROCESSOR_TSC701:
sparc_costs = &sparclet_costs;
diff --git a/gcc/config/sparc/sparc.h b/gcc/config/sparc/sparc.h
index c6122c1..202d23c 100644
--- a/gcc/config/sparc/sparc.h
+++ b/gcc/config/sparc/sparc.h
@@ -136,21 +136,22 @@ extern enum cmodel sparc_cmodel;
#define TARGET_CPU_supersparc 2
#define TARGET_CPU_hypersparc 3
#define TARGET_CPU_leon 4
-#define TARGET_CPU_sparclite 5
-#define TARGET_CPU_f930 5 /* alias */
-#define TARGET_CPU_f934 5 /* alias */
-#define TARGET_CPU_sparclite86x 6
-#define TARGET_CPU_sparclet 7
-#define TARGET_CPU_tsc701 7 /* alias */
-#define TARGET_CPU_v9 8 /* generic v9 implementation */
-#define TARGET_CPU_sparcv9 8 /* alias */
-#define TARGET_CPU_sparc64 8 /* alias */
-#define TARGET_CPU_ultrasparc 9
-#define TARGET_CPU_ultrasparc3 10
-#define TARGET_CPU_niagara 11
-#define TARGET_CPU_niagara2 12
-#define TARGET_CPU_niagara3 13
-#define TARGET_CPU_niagara4 14
+#define TARGET_CPU_leon3 5
+#define TARGET_CPU_sparclite 6
+#define TARGET_CPU_f930 6 /* alias */
+#define TARGET_CPU_f934 6 /* alias */
+#define TARGET_CPU_sparclite86x 7
+#define TARGET_CPU_sparclet 8
+#define TARGET_CPU_tsc701 8 /* alias */
+#define TARGET_CPU_v9 9 /* generic v9 implementation */
+#define TARGET_CPU_sparcv9 9 /* alias */
+#define TARGET_CPU_sparc64 9 /* alias */
+#define TARGET_CPU_ultrasparc 10
+#define TARGET_CPU_ultrasparc3 11
+#define TARGET_CPU_niagara 12
+#define TARGET_CPU_niagara2 13
+#define TARGET_CPU_niagara3 14
+#define TARGET_CPU_niagara4 15
#if TARGET_CPU_DEFAULT == TARGET_CPU_v9 \
|| TARGET_CPU_DEFAULT == TARGET_CPU_ultrasparc \
@@ -232,7 +233,8 @@ extern enum cmodel sparc_cmodel;
#define ASM_CPU32_DEFAULT_SPEC ""
#endif
-#if TARGET_CPU_DEFAULT == TARGET_CPU_leon
+#if TARGET_CPU_DEFAULT == TARGET_CPU_leon \
+ || TARGET_CPU_DEFAULT == TARGET_CPU_leon3
#define CPP_CPU32_DEFAULT_SPEC "-D__leon__ -D__sparc_v8__"
#define ASM_CPU32_DEFAULT_SPEC ""
#endif
@@ -282,6 +284,7 @@ extern enum cmodel sparc_cmodel;
%{mcpu=supersparc:-D__supersparc__ -D__sparc_v8__} \
%{mcpu=hypersparc:-D__hypersparc__ -D__sparc_v8__} \
%{mcpu=leon:-D__leon__ -D__sparc_v8__} \
+%{mcpu=leon3:-D__leon__ -D__sparc_v8__} \
%{mcpu=v9:-D__sparc_v9__} \
%{mcpu=ultrasparc:-D__sparc_v9__} \
%{mcpu=ultrasparc3:-D__sparc_v9__} \
@@ -330,6 +333,7 @@ extern enum cmodel sparc_cmodel;
%{mcpu=supersparc:-Av8} \
%{mcpu=hypersparc:-Av8} \
%{mcpu=leon:-Av8} \
+%{mcpu=leon3:-Av8} \
%{mv8plus:-Av8plus} \
%{mcpu=v9:-Av9} \
%{mcpu=ultrasparc:%{!mv8plus:-Av9a}} \
diff --git a/gcc/config/sparc/sparc.md b/gcc/config/sparc/sparc.md
index 7f8d425..174a6b1 100644
--- a/gcc/config/sparc/sparc.md
+++ b/gcc/config/sparc/sparc.md
@@ -206,7 +206,7 @@
;; 'f' for all DF/TFmode values, including those that are specific to the v8.
;; Attribute for cpu type.
-;; These must match the values for enum processor_type in sparc.h.
+;; These must match the values of the enum processor_type in sparc-opts.h.
(define_attr "cpu"
"v7,
cypress,
@@ -214,6 +214,7 @@
supersparc,
hypersparc,
leon,
+ leon3,
sparclite,
f930,
f934,
diff --git a/gcc/config/sparc/sparc.opt b/gcc/config/sparc/sparc.opt
index 3b50c6c..016e699 100644
--- a/gcc/config/sparc/sparc.opt
+++ b/gcc/config/sparc/sparc.opt
@@ -146,6 +146,9 @@ EnumValue
Enum(sparc_processor_type) String(leon) Value(PROCESSOR_LEON)
EnumValue
+Enum(sparc_processor_type) String(leon3) Value(PROCESSOR_LEON3)
+
+EnumValue
Enum(sparc_processor_type) String(sparclite) Value(PROCESSOR_SPARCLITE)
EnumValue
@@ -203,7 +206,7 @@ Enable workaround for single erratum of AT697F processor
mfix-ut699
Target Report RejectNegative Var(sparc_fix_ut699)
-Enable workarounds for the FP errata of the UT699 processor
+Enable workarounds for the errata of the UT699 processor
Mask(LONG_DOUBLE_128)
;; Use 128-bit long double
diff --git a/gcc/config/sparc/sync.md b/gcc/config/sparc/sync.md
index 1c1b977..2f21f81 100644
--- a/gcc/config/sparc/sync.md
+++ b/gcc/config/sparc/sync.md
@@ -220,7 +220,7 @@
(match_operand:SI 1 "memory_operand" "")
(match_operand:SI 2 "register_operand" "")
(match_operand:SI 3 "const_int_operand" "")]
- "TARGET_V8 || TARGET_V9"
+ "(TARGET_V8 || TARGET_V9) && !sparc_fix_ut699"
{
enum memmodel model = (enum memmodel) INTVAL (operands[3]);
@@ -236,7 +236,7 @@
UNSPECV_SWAP))
(set (match_dup 1)
(match_operand:SI 2 "register_operand" "0"))]
- "TARGET_V8 || TARGET_V9"
+ "(TARGET_V8 || TARGET_V9) && !sparc_fix_ut699"
"swap\t%1, %0"
[(set_attr "type" "multi")])
@@ -244,7 +244,7 @@
[(match_operand:QI 0 "register_operand" "")
(match_operand:QI 1 "memory_operand" "")
(match_operand:SI 2 "const_int_operand" "")]
- ""
+ "!sparc_fix_ut699"
{
enum memmodel model = (enum memmodel) INTVAL (operands[2]);
rtx ret;
@@ -268,6 +268,6 @@
(unspec_volatile:QI [(match_operand:QI 1 "memory_operand" "+m")]
UNSPECV_LDSTUB))
(set (match_dup 1) (const_int -1))]
- ""
+ "!sparc_fix_ut699"
"ldstub\t%1, %0"
[(set_attr "type" "multi")])