aboutsummaryrefslogtreecommitdiff
path: root/gcc/config/cris
diff options
context:
space:
mode:
authorHans-Peter Nilsson <hp@axis.com>2004-03-08 00:32:37 +0000
committerHans-Peter Nilsson <hp@gcc.gnu.org>2004-03-08 00:32:37 +0000
commit86da66b593538809357d60192ede83d02add681d (patch)
tree3cc5898bf48669383218721c23650efbac500168 /gcc/config/cris
parentf5fb3886b2d7b99a5c06f66854262a325f2e9361 (diff)
downloadgcc-86da66b593538809357d60192ede83d02add681d.zip
gcc-86da66b593538809357d60192ede83d02add681d.tar.gz
gcc-86da66b593538809357d60192ede83d02add681d.tar.bz2
re PR target/14471 (Workaround for errata regarding multiplication bug)
PR target/14471 * configure.ac (Target-specific assembler checks) <cris-*-*>: New case, checking for -no-mul-bug-abort option. * configure, config.in: Regenerate. * doc/invoke.texi (CRIS Options): Document -mmul-bug-workaround and -mno-mul-bug-workaround. * config/cris/cris.md ("smulsi3_highpart", "umulsi3_highpart") ("mulsidi3", "umulsidi3"): Prefix output template with "%!". ("umulhisi3", "umulqihi3", "mulsi3", "mulqihi3", "mulhisi3"): Ditto. Make attribute "slottable" dependent on TARGET_MUL_BUG. * config/cris/mulsi3.asm (__Mul) [__CRIS_arch_version >= 10]: Make sure mulu.d is not last on cache-line. * config/cris/cris.h (ASM_SPEC): Translate -mno-mul-bug-workaround into -no-mul-bug-abort depending on HAVE_AS_MUL_BUG_ABORT_OPTION. (TARGET_MASK_MUL_BUG, TARGET_MUL_BUG): New macros. (TARGET_SWITCHES): New options -mmul-bug-workaround and -mno-mul-bug-workaround. (TARGET_DEFAULT): Include TARGET_MASK_MUL_BUG. (PRINT_OPERAND_PUNCT_VALID_P): Include '!'. * config/cris/cris.c (cris_operand_extend_operator): Clarify relation to MULT in head comment. (cris_op_str): Abort for MULT. (cris_print_operand) <case '!'>: New case. From-SVN: r79085
Diffstat (limited to 'gcc/config/cris')
-rw-r--r--gcc/config/cris/cris.c28
-rw-r--r--gcc/config/cris/cris.h39
-rw-r--r--gcc/config/cris/cris.md43
-rw-r--r--gcc/config/cris/mulsi3.asm7
4 files changed, 98 insertions, 19 deletions
diff --git a/gcc/config/cris/cris.c b/gcc/config/cris/cris.c
index 84f27eb..b5568d6 100644
--- a/gcc/config/cris/cris.c
+++ b/gcc/config/cris/cris.c
@@ -332,7 +332,10 @@ cris_commutative_orth_op (rtx x, enum machine_mode mode)
|| code == IOR || code == AND || code == UMIN));
}
-/* Check if MODE is same as mode for X, and X is PLUS or MINUS or UMIN. */
+/* Check if MODE is same as mode for X, and X is PLUS or MINUS or UMIN.
+ By the name, you might think we should include MULT. We don't because
+ it doesn't accept the same addressing modes as the others (ony
+ registers) and there's also the problem of handling TARGET_MUL_BUG. */
int
cris_operand_extend_operator (rtx x, enum machine_mode mode)
@@ -499,7 +502,11 @@ cris_op_str (rtx x)
break;
case MULT:
- return "mul";
+ /* This function is for retrieving a part of an instruction name for
+ an operator, for immediate output. If that ever happens for
+ MULT, we need to apply TARGET_MUL_BUG in the caller. Make sure
+ we notice. */
+ abort ();
break;
case DIV:
@@ -1392,6 +1399,23 @@ cris_print_operand (FILE *file, rtx x, int code)
fputs ("\n\tnop", file);
return;
+ case '!':
+ /* Output directive for alignment padded with "nop" insns.
+ Optimizing for size, it's plain 4-byte alignment, otherwise we
+ align the section to a cache-line (32 bytes) and skip at max 2
+ bytes, i.e. we skip if it's the last insn on a cache-line. The
+ latter is faster by a small amount (for two test-programs 99.6%
+ and 99.9%) and larger by a small amount (ditto 100.1% and
+ 100.2%). This is supposed to be the simplest yet performance-
+ wise least intrusive way to make sure the immediately following
+ (supposed) muls/mulu insn isn't located at the end of a
+ cache-line. */
+ if (TARGET_MUL_BUG)
+ fputs (optimize_size
+ ? ".p2alignw 2,0x050f\n\t"
+ : ".p2alignw 5,0x050f,2\n\t", file);
+ return;
+
case 'H':
/* Print high (most significant) part of something. */
switch (GET_CODE (operand))
diff --git a/gcc/config/cris/cris.h b/gcc/config/cris/cris.h
index 10147b2..da5ab7f 100644
--- a/gcc/config/cris/cris.h
+++ b/gcc/config/cris/cris.h
@@ -171,9 +171,17 @@ extern const char *cris_elinux_stacksize_str;
%{!melinux:%{!maout|melf:%{!fno-vtable-gc:-fvtable-gc}}}}}". */
#define CC1PLUS_SPEC ""
+#ifdef HAVE_AS_MUL_BUG_ABORT_OPTION
+#define MAYBE_AS_NO_MUL_BUG_ABORT \
+ "%{mno-mul-bug-workaround:-no-mul-bug-abort} "
+#else
+#define MAYBE_AS_NO_MUL_BUG_ABORT
+#endif
+
/* Override previous definitions (linux.h). */
#undef ASM_SPEC
#define ASM_SPEC \
+ MAYBE_AS_NO_MUL_BUG_ABORT \
"%{v:-v}\
%(asm_subtarget)"
@@ -326,8 +334,34 @@ extern int target_flags;
#define TARGET_MASK_AVOID_GOTPLT 8192
#define TARGET_AVOID_GOTPLT (target_flags & TARGET_MASK_AVOID_GOTPLT)
+/* Whether or not to work around multiplication instruction hardware bug
+ when generating code for models where it may be present. From the
+ trouble report for Etrax 100 LX: "A multiply operation may cause
+ incorrect cache behaviour under some specific circumstances. The
+ problem can occur if the instruction following the multiply instruction
+ causes a cache miss, and multiply operand 1 (source operand) bits
+ [31:27] matches the logical mapping of the mode register address
+ (0xb0....), and bits [9:2] of operand 1 matches the TLB register
+ address (0x258-0x25f). There is such a mapping in kernel mode or when
+ the MMU is off. Normally there is no such mapping in user mode, and
+ the problem will therefore probably not occur in Linux user mode
+ programs."
+
+ We have no sure-fire way to know from within GCC that we're compiling a
+ user program. For example, -fpic/PIC is used in libgcc which is linked
+ into the kernel. However, the workaround option -mno-mul-bug can be
+ safely used per-package when compiling programs. The same goes for
+ general user-only libraries such as glibc, since there's no user-space
+ driver-like program that gets a mapping of I/O registers (all on the
+ same page, including the TLB registers). */
+#define TARGET_MASK_MUL_BUG 16384
+#define TARGET_MUL_BUG (target_flags & TARGET_MASK_MUL_BUG)
+
#define TARGET_SWITCHES \
{ \
+ {"mul-bug-workaround", TARGET_MASK_MUL_BUG, \
+ N_("Work around bug in multiplication instruction")}, \
+ {"no-mul-bug-workaround", -TARGET_MASK_MUL_BUG, ""}, \
/* No "no-etrax" as it does not really imply any model. \
On the other hand, "etrax" implies the common (and large) \
subset matching all models. */ \
@@ -405,7 +439,7 @@ extern int target_flags;
# define TARGET_DEFAULT \
(TARGET_MASK_SIDE_EFFECT_PREFIXES + TARGET_MASK_STACK_ALIGN \
+ TARGET_MASK_CONST_ALIGN + TARGET_MASK_DATA_ALIGN \
- + TARGET_MASK_PROLOGUE_EPILOGUE)
+ + TARGET_MASK_PROLOGUE_EPILOGUE + TARGET_MASK_MUL_BUG)
#endif
/* For the cris-*-elf subtarget. */
@@ -1474,7 +1508,8 @@ call_ ## FUNC (void) \
cris_print_operand (FILE, X, CODE)
/* For delay-slot handling. */
-#define PRINT_OPERAND_PUNCT_VALID_P(CODE) (CODE == '#')
+#define PRINT_OPERAND_PUNCT_VALID_P(CODE) \
+ ((CODE) == '#' || (CODE) == '!')
#define PRINT_OPERAND_ADDRESS(FILE, ADDR) \
cris_print_operand_address (FILE, ADDR)
diff --git a/gcc/config/cris/cris.md b/gcc/config/cris/cris.md
index 38aa556..dd251e7 100644
--- a/gcc/config/cris/cris.md
+++ b/gcc/config/cris/cris.md
@@ -2469,8 +2469,11 @@
(zero_extend:SI (match_operand:HI 1 "register_operand" "0"))
(zero_extend:SI (match_operand:HI 2 "register_operand" "r"))))]
"TARGET_HAS_MUL_INSNS"
- "mulu.w %2,%0"
- [(set_attr "slottable" "yes")
+ "%!mulu.w %2,%0"
+ [(set (attr "slottable")
+ (if_then_else (ne (symbol_ref "TARGET_MUL_BUG") (const_int 0))
+ (const_string "no")
+ (const_string "yes")))
;; Just N unusable here, but let's be safe.
(set_attr "cc" "clobber")])
@@ -2480,8 +2483,11 @@
(zero_extend:HI (match_operand:QI 1 "register_operand" "0"))
(zero_extend:HI (match_operand:QI 2 "register_operand" "r"))))]
"TARGET_HAS_MUL_INSNS"
- "mulu.b %2,%0"
- [(set_attr "slottable" "yes")
+ "%!mulu.b %2,%0"
+ [(set (attr "slottable")
+ (if_then_else (ne (symbol_ref "TARGET_MUL_BUG") (const_int 0))
+ (const_string "no")
+ (const_string "yes")))
;; Not exactly sure, but let's be safe.
(set_attr "cc" "clobber")])
@@ -2496,8 +2502,11 @@
(mult:SI (match_operand:SI 1 "register_operand" "0")
(match_operand:SI 2 "register_operand" "r")))]
"TARGET_HAS_MUL_INSNS"
- "muls.d %2,%0"
- [(set_attr "slottable" "yes")
+ "%!muls.d %2,%0"
+ [(set (attr "slottable")
+ (if_then_else (ne (symbol_ref "TARGET_MUL_BUG") (const_int 0))
+ (const_string "no")
+ (const_string "yes")))
;; Just N unusable here, but let's be safe.
(set_attr "cc" "clobber")])
@@ -2511,8 +2520,11 @@
(sign_extend:HI (match_operand:QI 1 "register_operand" "0"))
(sign_extend:HI (match_operand:QI 2 "register_operand" "r"))))]
"TARGET_HAS_MUL_INSNS"
- "muls.b %2,%0"
- [(set_attr "slottable" "yes")
+ "%!muls.b %2,%0"
+ [(set (attr "slottable")
+ (if_then_else (ne (symbol_ref "TARGET_MUL_BUG") (const_int 0))
+ (const_string "no")
+ (const_string "yes")))
(set_attr "cc" "clobber")])
(define_insn "mulhisi3"
@@ -2521,8 +2533,11 @@
(sign_extend:SI (match_operand:HI 1 "register_operand" "0"))
(sign_extend:SI (match_operand:HI 2 "register_operand" "r"))))]
"TARGET_HAS_MUL_INSNS"
- "muls.w %2,%0"
- [(set_attr "slottable" "yes")
+ "%!muls.w %2,%0"
+ [(set (attr "slottable")
+ (if_then_else (ne (symbol_ref "TARGET_MUL_BUG") (const_int 0))
+ (const_string "no")
+ (const_string "yes")))
;; Just N unusable here, but let's be safe.
(set_attr "cc" "clobber")])
@@ -2538,7 +2553,7 @@
(sign_extend:DI (match_operand:SI 1 "register_operand" "0"))
(sign_extend:DI (match_operand:SI 2 "register_operand" "r"))))]
"TARGET_HAS_MUL_INSNS"
- "muls.d %2,%M0\;move $mof,%H0")
+ "%!muls.d %2,%M0\;move $mof,%H0")
(define_insn "umulsidi3"
[(set (match_operand:DI 0 "register_operand" "=r")
@@ -2546,7 +2561,7 @@
(zero_extend:DI (match_operand:SI 1 "register_operand" "0"))
(zero_extend:DI (match_operand:SI 2 "register_operand" "r"))))]
"TARGET_HAS_MUL_INSNS"
- "mulu.d %2,%M0\;move $mof,%H0")
+ "%!mulu.d %2,%M0\;move $mof,%H0")
;; This pattern would probably not be needed if we add "mof" in its own
;; register class (and open a can of worms about /not/ pairing it with a
@@ -2565,7 +2580,7 @@
(const_int 32))))
(clobber (match_scratch:SI 3 "=X,1,1"))]
"TARGET_HAS_MUL_INSNS"
- "muls.d %2,%1\;move $mof,%0"
+ "%!muls.d %2,%1\;move $mof,%0"
[(set_attr "cc" "clobber")])
(define_insn "umulsi3_highpart"
@@ -2578,7 +2593,7 @@
(const_int 32))))
(clobber (match_scratch:SI 3 "=X,1,1"))]
"TARGET_HAS_MUL_INSNS"
- "mulu.d %2,%1\;move $mof,%0"
+ "%!mulu.d %2,%1\;move $mof,%0"
[(set_attr "cc" "clobber")])
;; Divide and modulus instructions. CRIS only has a step instruction.
diff --git a/gcc/config/cris/mulsi3.asm b/gcc/config/cris/mulsi3.asm
index 3c482e7..69d9ded 100644
--- a/gcc/config/cris/mulsi3.asm
+++ b/gcc/config/cris/mulsi3.asm
@@ -82,8 +82,13 @@
.type ___Mul,@function
___Mul:
#if defined (__CRIS_arch_version) && __CRIS_arch_version >= 10
- ret
+;; Can't have the mulu.d last on a cache-line (in the delay-slot of the
+;; "ret"), due to hardware bug. See documentation for -mmul-bug-workaround.
+;; Not worthwhile to conditionalize here.
+ .p2alignw 2,0x050f
mulu.d $r11,$r10
+ ret
+ nop
#else
move.d $r10,$r12
move.d $r11,$r9