aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEric Botcazou <ebotcazou@adacore.com>2013-07-22 21:41:44 +0000
committerEric Botcazou <ebotcazou@adacore.com>2013-07-22 21:41:44 +0000
commit9a74db7d9fe882c9581abc190fc2446569ff359d (patch)
tree456e7a0274b3b7a7b98769954c1ec28425700400
parentc1e9b3afd60ef95f2ef449cc5e1c1f6f51e58c89 (diff)
* 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. git-svn-id: https://gcc.gnu.org/svn/gcc/trunk@201147 138bc75d-0d04-0410-961f-82ee72b054a4
-rw-r--r--gcc/ChangeLog35
-rw-r--r--gcc/config.gcc22
-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
-rw-r--r--gcc/doc/invoke.texi4
10 files changed, 228 insertions, 75 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index efc9ac7e51d..6999d3f8454 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,38 @@
+2013-07-22 Eric Botcazou <ebotcazou@adacore.com>
+
+ * 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.
+
2013-07-22 Jürgen Urban <JuergenUrban@gmx.de>
* config.gcc (mips*-*-*): Add --with-fpu support. Make single the
diff --git a/gcc/config.gcc b/gcc/config.gcc
index 1a398a7232f..94c21c04eaf 100644
--- a/gcc/config.gcc
+++ b/gcc/config.gcc
@@ -3662,7 +3662,7 @@ case "${target}" in
case ${val} in
"" | sparc | sparcv9 | sparc64 \
| v7 | cypress \
- | v8 | supersparc | hypersparc | leon \
+ | v8 | supersparc | hypersparc | leon | leon3 \
| sparclite | f930 | f934 | sparclite86x \
| sparclet | tsc701 \
| v9 | ultrasparc | ultrasparc3 | niagara | niagara2 \
@@ -3819,15 +3819,6 @@ case ${target} in
cxx_target_objs="${cxx_target_objs} sh-c.o"
;;
- sparc-leon*-*)
- if test x$with_tune = x ; then
- with_tune=leon;
- fi
-
- # The SPARC port checks this value at compile-time.
- target_cpu_default2="TARGET_CPU_$with_cpu"
- ;;
-
sparc*-*-*)
# Some standard aliases.
case x$with_cpu in
@@ -3839,6 +3830,17 @@ case ${target} in
;;
esac
+ if test x$with_tune = x ; then
+ case ${target} in
+ *-leon-*)
+ with_tune=leon
+ ;;
+ *-leon[3-9]*)
+ with_tune=leon3
+ ;;
+ esac
+ fi
+
# The SPARC port checks this value at compile-time.
target_cpu_default2="TARGET_CPU_$with_cpu"
;;
diff --git a/gcc/config/sparc/leon.md b/gcc/config/sparc/leon.md
index 60815079da6..b511397fe36 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 72791772eb2..b5e9761af2b 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 d473d6fdd7f..48c25dcd5cd 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 c6122c115cd..202d23c0162 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 7f8d4250502..174a6b1ea5f 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 3b50c6c21f9..016e6997422 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 1c1b9774bc3..2f21f812dc9 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")])
diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
index d99d2179875..31553bea64e 100644
--- a/gcc/doc/invoke.texi
+++ b/gcc/doc/invoke.texi
@@ -19491,8 +19491,8 @@ processor (which corresponds to erratum #13 of the AT697E processor).
@item -mfix-ut699
@opindex mfix-ut699
-Enable the documented workarounds for the floating-point errata of the UT699
-processor.
+Enable the documented workarounds for the floating-point errata and the data
+cache nullify errata of the UT699 processor.
@end table
These @samp{-m} options are supported in addition to the above