Committed: target/14471, workaround for errata for CRIS mul insns.

Hans-Peter Nilsson hans-peter.nilsson@axis.com
Mon Mar 8 01:06:00 GMT 2004


See PR for more.  I'll also make libstdc++-v3 be compiled
-mno-mul-bug-workaround on main trunk for non-C-libraries and
cris-*-linux*.

By the way, looks like nobody did "make dvi" for a while; it
breaks due to exceeding TeX limits with "TeX (Web2C 7.3.1)
3.14159" (stock in RH 9).  To check this doc patch, I worked
around it by removing everything inside the "@ifset INTERNALS"
in md.texi.  Film at 11.

Tested cross to cris-axis-elf, no regressions.

Checked in on trunk, 3.3 (except the configure stuff) and 3.4

	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.

Index: invoke.texi
===================================================================
RCS file: /cvs/gcc/gcc/gcc/doc/invoke.texi,v
retrieving revision 1.422
diff -p -c -r1.422 invoke.texi
*** invoke.texi	4 Mar 2004 00:18:53 -0000	1.422
--- invoke.texi	7 Mar 2004 22:24:39 -0000
*************** in the following sections.
*** 609,615 ****
  -metrax4  -metrax100  -mpdebug  -mcc-init  -mno-side-effects @gol
  -mstack-align  -mdata-align  -mconst-align @gol
  -m32-bit  -m16-bit  -m8-bit  -mno-prologue-epilogue  -mno-gotplt @gol
! -melf  -maout  -melinux  -mlinux  -sim  -sim2}
  
  @emph{PDP-11 Options}
  @gccoptlist{-mfpu  -msoft-float  -mac0  -mno-ac0  -m40  -m45  -m10 @gol
--- 609,616 ----
  -metrax4  -metrax100  -mpdebug  -mcc-init  -mno-side-effects @gol
  -mstack-align  -mdata-align  -mconst-align @gol
  -m32-bit  -m16-bit  -m8-bit  -mno-prologue-epilogue  -mno-gotplt @gol
! -melf  -maout  -melinux  -mlinux  -sim  -sim2 @gol
! -mmul-bug-workaround  -mno-mul-bug-workaround}
  
  @emph{PDP-11 Options}
  @gccoptlist{-mfpu  -msoft-float  -mac0  -mno-ac0  -m40  -m45  -m10 @gol
*************** program should be set to @var{n} bytes.
*** 10145,10150 ****
--- 10146,10158 ----
  @opindex metrax100
  The options @option{-metrax4} and @option{-metrax100} are synonyms for
  @option{-march=v3} and @option{-march=v8} respectively.
+ 
+ @item -mmul-bug-workaround
+ @itemx -mno-mul-bug-workaround
+ @opindex mmul-bug-workaround
+ @opindex mno-mul-bug-workaround
+ Work around a bug in the @code{muls} and @code{mulu} instructions for CPU
+ models where it applies.  This option is active by default.
  
  @item -mpdebug
  @opindex mpdebug
Index: configure.ac
===================================================================
RCS file: /cvs/gcc/gcc/gcc/configure.ac,v
retrieving revision 2.6.2.10
diff -p -c -r2.6.2.10 configure.ac
*** configure.ac	25 Feb 2004 21:54:58 -0000	2.6.2.10
--- configure.ac	7 Mar 2004 22:26:15 -0000
*************** case "$target" in
*** 2333,2338 ****
--- 2333,2346 ----
    [Define if your assembler supports explicit relocations.])])
      ;;
  
+   cris-*-*)
+     gcc_GAS_CHECK_FEATURE([-no-mul-bug-abort option],
+       gcc_cv_as_cris_no_mul_bug,[2,15,91],
+       [-no-mul-bug-abort], [.text],,
+       [AC_DEFINE(HAVE_AS_NO_MUL_BUG_ABORT_OPTION, 1,
+ 		[Define if your assembler supports the -no-mul-bug-abort option.])])
+     ;;
+ 
    sparc*-*-*)
      gcc_GAS_CHECK_FEATURE([.register], gcc_cv_as_sparc_register_op,,,
        [.register %g2, #scratch],,
Index: cris.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/cris/cris.c,v
retrieving revision 1.46.10.1
diff -p -c -r1.46.10.1 cris.c
*** cris.c	18 Jan 2004 22:39:57 -0000	1.46.10.1
--- cris.c	7 Mar 2004 22:29:22 -0000
*************** cris_commutative_orth_op (rtx x, enum ma
*** 318,324 ****
  	   || code == IOR || code == AND || code == UMIN));
  }
  
! /* Check if MODE is same as mode for X, and X is PLUS or MINUS or UMIN.  */
  
  int
  cris_operand_extend_operator (rtx x, enum machine_mode mode)
--- 318,327 ----
  	   || code == IOR || code == AND || code == 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)
*************** cris_op_str (rtx x)
*** 485,491 ****
        break;
  
      case MULT:
!       return "mul";
        break;
  
      case DIV:
--- 488,498 ----
        break;
  
      case MULT:
!       /* 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:
*************** cris_print_operand (FILE *file, rtx x, i
*** 1378,1383 ****
--- 1385,1407 ----
  	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))
Index: cris.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/cris/cris.h,v
retrieving revision 1.60
diff -p -c -r1.60 cris.h
*** cris.h	13 Dec 2003 04:44:04 -0000	1.60
--- cris.h	7 Mar 2004 22:29:26 -0000
*************** extern const char *cris_elinux_stacksize
*** 170,178 ****
--- 170,186 ----
     %{!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)"
  
*************** extern int target_flags;
*** 325,332 ****
--- 333,366 ----
  #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.  */					\
*************** extern int target_flags;
*** 404,410 ****
  # define TARGET_DEFAULT \
   (TARGET_MASK_SIDE_EFFECT_PREFIXES + TARGET_MASK_STACK_ALIGN \
    + TARGET_MASK_CONST_ALIGN + TARGET_MASK_DATA_ALIGN \
!   + TARGET_MASK_PROLOGUE_EPILOGUE)
  #endif
  
  /* For the cris-*-elf subtarget.  */
--- 438,444 ----
  # 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_MUL_BUG)
  #endif
  
  /* For the cris-*-elf subtarget.  */
*************** call_ ## FUNC (void)						\
*** 1497,1503 ****
   cris_print_operand (FILE, X, CODE)
  
  /* For delay-slot handling.  */
! #define PRINT_OPERAND_PUNCT_VALID_P(CODE) (CODE == '#')
  
  #define PRINT_OPERAND_ADDRESS(FILE, ADDR)	\
     cris_print_operand_address (FILE, ADDR)
--- 1531,1538 ----
   cris_print_operand (FILE, X, CODE)
  
  /* For delay-slot handling.  */
! #define PRINT_OPERAND_PUNCT_VALID_P(CODE)	\
!  ((CODE) == '#' || (CODE) == '!')
  
  #define PRINT_OPERAND_ADDRESS(FILE, ADDR)	\
     cris_print_operand_address (FILE, ADDR)
Index: cris.md
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/cris/cris.md,v
retrieving revision 1.11.4.1
diff -p -c -r1.11.4.1 cris.md
*** cris.md	22 Feb 2004 11:13:04 -0000	1.11.4.1
--- cris.md	7 Mar 2004 22:29:26 -0000
***************
*** 2468,2475 ****
  	 (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")
     ;; Just N unusable here, but let's be safe.
     (set_attr "cc" "clobber")])
  
--- 2468,2478 ----
  	 (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")
! 	(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")])
  
***************
*** 2479,2486 ****
  	 (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")
     ;; Not exactly sure, but let's be safe.
     (set_attr "cc" "clobber")])
  
--- 2482,2492 ----
  	 (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")
! 	(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")])
  
***************
*** 2495,2502 ****
  	(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")
     ;; Just N unusable here, but let's be safe.
     (set_attr "cc" "clobber")])
  
--- 2501,2511 ----
  	(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")
! 	(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")])
  
***************
*** 2510,2517 ****
  	 (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")
     (set_attr "cc" "clobber")])
  
  (define_insn "mulhisi3"
--- 2519,2529 ----
  	 (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")
! 	(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"
***************
*** 2520,2527 ****
  	 (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")
     ;; Just N unusable here, but let's be safe.
     (set_attr "cc" "clobber")])
  
--- 2532,2542 ----
  	 (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")
! 	(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")])
  
***************
*** 2537,2543 ****
  	 (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")
  
  (define_insn "umulsidi3"
    [(set (match_operand:DI 0 "register_operand" "=r")
--- 2552,2558 ----
  	 (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")
  
  (define_insn "umulsidi3"
    [(set (match_operand:DI 0 "register_operand" "=r")
***************
*** 2545,2551 ****
  	 (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")
  
  ;; 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
--- 2560,2566 ----
  	 (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")
  
  ;; 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
***************
*** 2564,2570 ****
  	  (const_int 32))))
     (clobber (match_scratch:SI 3 "=X,1,1"))]
    "TARGET_HAS_MUL_INSNS"
!   "muls.d %2,%1\;move $mof,%0"
    [(set_attr "cc" "clobber")])
  
  (define_insn "umulsi3_highpart"
--- 2579,2585 ----
  	  (const_int 32))))
     (clobber (match_scratch:SI 3 "=X,1,1"))]
    "TARGET_HAS_MUL_INSNS"
!   "%!muls.d %2,%1\;move $mof,%0"
    [(set_attr "cc" "clobber")])
  
  (define_insn "umulsi3_highpart"
***************
*** 2577,2583 ****
  	  (const_int 32))))
     (clobber (match_scratch:SI 3 "=X,1,1"))]
    "TARGET_HAS_MUL_INSNS"
!   "mulu.d %2,%1\;move $mof,%0"
    [(set_attr "cc" "clobber")])
  
  ;; Divide and modulus instructions.  CRIS only has a step instruction.
--- 2592,2598 ----
  	  (const_int 32))))
     (clobber (match_scratch:SI 3 "=X,1,1"))]
    "TARGET_HAS_MUL_INSNS"
!   "%!mulu.d %2,%1\;move $mof,%0"
    [(set_attr "cc" "clobber")])
  
  ;; Divide and modulus instructions.  CRIS only has a step instruction.
Index: mulsi3.asm
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/cris/mulsi3.asm,v
retrieving revision 1.1
diff -p -c -r1.1 mulsi3.asm
*** mulsi3.asm	11 Oct 2001 17:02:36 -0000	1.1
--- mulsi3.asm	7 Mar 2004 22:29:27 -0000
***************
*** 82,89 ****
  	.type	___Mul,@function
  ___Mul:
  #if defined (__CRIS_arch_version) && __CRIS_arch_version >= 10
! 	ret
  	mulu.d $r11,$r10
  #else
  	move.d $r10,$r12
  	move.d $r11,$r9
--- 82,94 ----
  	.type	___Mul,@function
  ___Mul:
  #if defined (__CRIS_arch_version) && __CRIS_arch_version >= 10
! ;; 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

brgds, H-P



More information about the Gcc-patches mailing list