This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Patch to remove the mips hilo register


One of the obstacles to putting whole functions in .set noreorder
is that some md patterns are shorter than they claim.

An example is hilo_delay, which has the default length of 4,
but doesn't actually emit anything.  Rather than just change that
particular pattern, it seemed like a good time to get rid of the
(infamous!) hilo register altogether.

Only two patterns set the register to useful values: mulsidi3 and
umulsidi3.  This patch combines the patterns into one, changes the
destination constraint to use a GPR, and then splits the pattern up
in the same way as the existing hilo->gpr reload code.

Once that's done, there's no reason to keep hilo.  Removing it
simplifies the multiply/divide patterns and gets rid of some nasty
reload code.  (The gpr->hilo code is just bogus, it doesn't set
the hilo register at all...)

The only remaining use of reload_in[sd]i was for mips16 code:

  - To get round the lack of a mips16 mtlo instruction, gpr->lo reloads
    were done using multiplication.  Not only was this really hideous
    (as the code itself admits ;) but the gpr->hi case wasn't
    implemented, it would just ICE.

    Moves are the only mips16 patterns to accept lo or hi rvalues.  So I
    think the only reason we'd try to move into hi or lo is if a pseudo
    gets allocated to it.  We try to prevent this happening, e.g. in
    mips_register_move_cost.  I don't know whether that code is
    guaranteed to work (from the comment, it sounds like the original
    author wasn't too sure either).  But if it doesn't, the hi case is
    just as likely to be trigger as the lo case.  And since we ICE
    for hi, it seems reasonable to do the same for lo.

    Or, put it another way: we really do want to avoid using hi and
    lo for anything other than temporaries.  If for some reason we
    fail to do that, it would be better to fix it than to use
    multiplication as a form of register move.

  - reload_insi has code to handle reloads of (plus $sp reg).
    The patch that introduced it was:

        http://gcc.gnu.org/ml/gcc-patches/1999-06n/msg00350.html

    To quote from the message:

        This can happen as a result of register elimination and
        form_sum converting (plus reg (plus SP CONST)) to
        (plus (plus reg SP) CONST).

    Checking out a copy of reload1.c from about that time, it seems
    that eliminate_regs() was applied to the whole body of an insn.
    So presumably this transformation would occur on a normal add like:

        (set (reg x) (plus fp (reg y)))

    Nowadays eliminate_regs() is only applied to operands and memory
    references (is that right?).  Since (plus fp reg) isn't valid
    in either context, I don't believe this code is needed any more.
    In an insn like the above, we just replace fp with (plus sp CONST)
    without "simplifying" the whole pattern.  (plus sp CONST) is then
    reloaded correctly.

In summary, I don't think we need reload_in[sd]i or reload_out[sd]i
once hilo is gone.  Removing the mips16 code showed no regressions
on mips64vrel-elf.

By necessity, the patch touches every multiplication and division
pattern.  Hope I didn't screw it up.  While there, I noticed a couple
of suspicious-looking things:

   - The !optimize div/mod patterns accepted constant operands
     (the h/w instruction is register-only).

   - There seemed to be a missing early-clobber marker in
     *mul_acc_si and *mul_sub_si.

Patch passes bootstrap on mips-sgi-irix6.5.  Tested against that,
mipsel-linux-gnu, mips64vrel-elf and mipsisa64-elf.  I also
benchmarked the patch on a vr5400 board (both with -march=vr5400
and -mips4 -mtune=vr5400, which exercise different multiplication
patterns).  The patch was a slight improvement for one program,
the rest showed no change.

OK to install?

Richard

 mips.c  |   60 +---
 mips.h  |   28 --
 mips.md |  873 +++++++++++++++++++---------------------------------------------
 3 files changed, 289 insertions(+), 672 deletions(-)


	* config/mips/mips.c (mips_reg_names): Change hilo entry to "".
	(mips_sw_reg_names): Likewise.
	(mips_regno_to_class): Change hilo entry to NO_REGS.
	(hilo_operand): Use MD_REG_P.
	(extend_operator): New predicate.
	(override_options): Remove 'a' constraint.
	(mips_secondary_reload_class): Remove hilo handling.  Also remove
	handling of (plus sp reg) reloads for mips16.
	(mips_register_move_cost): Remove hilo handling.
	* config/mips/mips.h (FIXED_REGISTERS): Make hilo entry fixed.
	(MD_REG_LAST): Remove hilo from range.
	(HILO_REGNUM): Delete.
	(reg_class): Remove HILO_REG and HILO_AND_GR_REGS.
	(REG_CLASS_NAMES, REG_CLASS_CONTENTS): Update accordingly.
	(PREDICATE_CODES): Add entry for extend_operator.
	(DEBUG_REGISTER_NAMES): Change hilo entry to "".
	* config/mips/mips.md: Remove hilo clobbers wherever they occur.
	Remove constraints from multiplication define_expands.  Remove
	clobbers from "decorative" define_expand patterns.
	(UNSPEC_HILO_DELAY): Delete.
	(*mul_acc_si, *mul_sub_si): Add early-clobber to operand 6.
	(mulsidi3, umulsidi3): Change pattern to match the TARGET_64BIT case.
	Adjust C code to just emit insns for !TARGET_64BIT.
	(mulsidi3_internal): Rename to mulsidi3_32bit.
	(mulsidi3_64bit): Use a "d" constraint for the destination.
	Use extend_operator so that the pattern can handle umulsidi3 as well.
	Split the instruction after reload.
	(*mulsidi3_64bit_parts): New pattern, generated by mulsidi3_64bit.
	(umulsidi3_internal): Rename to umulsidi3_32bit.
	(umulsidi3_64bit): Remove.
	(*smsac_di, *umsac_di): Line-wrap fixes.
	(udivsi3_internal): Don't allow operand 2 to be constant.
	(udivdi3_internal, umodsi3_internal, umoddi3_internal): Likewise.
	(movdi_internal2, movsi_internal): Remove hilo alternatives.
	(reload_in[sd]i, reload_out[sd]i, hilo_delay): Remove.

Index: config/mips/mips.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/mips/mips.c,v
retrieving revision 1.272
diff -u -d -p -F^\([(a-zA-Z0-9_]\|#define\) -r1.272 mips.c
--- config/mips/mips.c	3 Jun 2003 08:57:54 -0000	1.272
+++ config/mips/mips.c	7 Jun 2003 09:37:00 -0000
@@ -597,7 +597,7 @@ char mips_reg_names[][8] =
  "$f8",  "$f9",  "$f10", "$f11", "$f12", "$f13", "$f14", "$f15",
  "$f16", "$f17", "$f18", "$f19", "$f20", "$f21", "$f22", "$f23",
  "$f24", "$f25", "$f26", "$f27", "$f28", "$f29", "$f30", "$f31",
- "hi",   "lo",   "accum","$fcc0","$fcc1","$fcc2","$fcc3","$fcc4",
+ "hi",   "lo",   "",     "$fcc0","$fcc1","$fcc2","$fcc3","$fcc4",
  "$fcc5","$fcc6","$fcc7","", "",     "",     "",     "",
  "$c0r0", "$c0r1", "$c0r2", "$c0r3", "$c0r4", "$c0r5", "$c0r6", "$c0r7",
  "$c0r8", "$c0r9", "$c0r10","$c0r11","$c0r12","$c0r13","$c0r14","$c0r15",
@@ -626,7 +626,7 @@ char mips_sw_reg_names[][8] =
   "$f8",  "$f9",  "$f10", "$f11", "$f12", "$f13", "$f14", "$f15",
   "$f16", "$f17", "$f18", "$f19", "$f20", "$f21", "$f22", "$f23",
   "$f24", "$f25", "$f26", "$f27", "$f28", "$f29", "$f30", "$f31",
-  "hi",   "lo",   "accum","$fcc0","$fcc1","$fcc2","$fcc3","$fcc4",
+  "hi",   "lo",   "",     "$fcc0","$fcc1","$fcc2","$fcc3","$fcc4",
   "$fcc5","$fcc6","$fcc7","$rap", "",     "",     "",     "",
   "$c0r0", "$c0r1", "$c0r2", "$c0r3", "$c0r4", "$c0r5", "$c0r6", "$c0r7",
   "$c0r8", "$c0r9", "$c0r10","$c0r11","$c0r12","$c0r13","$c0r14","$c0r15",
@@ -661,7 +661,7 @@ const enum reg_class mips_regno_to_class
   FP_REGS,	FP_REGS,	FP_REGS,	FP_REGS,
   FP_REGS,	FP_REGS,	FP_REGS,	FP_REGS,
   FP_REGS,	FP_REGS,	FP_REGS,	FP_REGS,
-  HI_REG,	LO_REG,		HILO_REG,	ST_REGS,
+  HI_REG,	LO_REG,		NO_REGS,	ST_REGS,
   ST_REGS,	ST_REGS,	ST_REGS,	ST_REGS,
   ST_REGS,	ST_REGS,	ST_REGS,	NO_REGS,
   NO_REGS,	NO_REGS,	NO_REGS,	NO_REGS,
@@ -1516,8 +1516,18 @@ hilo_operand (op, mode)
      enum machine_mode mode;
 {
   return ((mode == VOIDmode || mode == GET_MODE (op))
-	  && REG_P (op)
-	  && (REGNO (op) == HI_REGNUM || REGNO (op) == LO_REGNUM));
+	  && REG_P (op) && MD_REG_P (REGNO (op)));
+}
+
+/* Return true if OP is an extension operator.  */
+
+int
+extend_operator (op, mode)
+     rtx op;
+     enum machine_mode mode;
+{
+  return ((mode == VOIDmode || mode == GET_MODE (op))
+	  && (GET_CODE (op) == ZERO_EXTEND || GET_CODE (op) == SIGN_EXTEND));
 }
 
 /* Return nonzero if the code of this rtx pattern is EQ or NE.  */
@@ -5543,7 +5553,6 @@ override_options ()
   mips_char_to_class['f'] = (TARGET_HARD_FLOAT ? FP_REGS : NO_REGS);
   mips_char_to_class['h'] = HI_REG;
   mips_char_to_class['l'] = LO_REG;
-  mips_char_to_class['a'] = HILO_REG;
   mips_char_to_class['x'] = MD_REGS;
   mips_char_to_class['b'] = ALL_REGS;
   mips_char_to_class['c'] = (TARGET_ABICALLS ? PIC_FN_ADDR_REG :
@@ -8577,20 +8586,6 @@ mips_secondary_reload_class (class, mode
       && DANGEROUS_FOR_LA25_P (x))
     return LEA_REGS;
 
-  /* We always require a general register when copying anything to
-     HILO_REGNUM, except when copying an SImode value from HILO_REGNUM
-     to a general register, or when copying from register 0.  */
-  if (class == HILO_REG && regno != GP_REG_FIRST + 0)
-    return ((! in_p
-	     && gp_reg_p
-	     && GET_MODE_SIZE (mode) <= GET_MODE_SIZE (SImode))
-	    ? NO_REGS : gr_regs);
-  else if (regno == HILO_REGNUM)
-    return ((in_p
-	     && class == gr_regs
-	     && GET_MODE_SIZE (mode) <= GET_MODE_SIZE (SImode))
-	    ? NO_REGS : gr_regs);
-
   /* Copying from HI or LO to anywhere other than a general register
      requires a general register.  */
   if (class == HI_REG || class == LO_REG || class == MD_REGS)
@@ -8672,19 +8667,6 @@ mips_secondary_reload_class (class, mode
 	}
       if (! gp_reg_p)
 	{
-	  /* The stack pointer isn't a valid operand to an add instruction,
-	     so we need to load it into M16_REGS first.  This can happen as
-	     a result of register elimination and form_sum converting
-	     (plus reg (plus SP CONST)) to (plus (plus reg SP) CONST).  We
-	     need an extra register if the dest is the same as the other
-	     register.  In that case, we can't fix the problem by loading SP
-	     into the dest first.  */
-	  if (GET_CODE (x) == PLUS && GET_CODE (XEXP (x, 0)) == REG
-	      && GET_CODE (XEXP (x, 1)) == REG
-	      && (XEXP (x, 0) == stack_pointer_rtx
-		  || XEXP (x, 1) == stack_pointer_rtx))
-	    return (class == M16_REGS ? M16_NA_REGS : M16_REGS);
-
 	  if (class == M16_REGS || class == M16_NA_REGS)
 	    return NO_REGS;
 	  return M16_REGS;
@@ -9811,10 +9793,10 @@ mips_reorg ()
    should do this if the `movM' pattern's constraints do not allow
    such copying.
 
-   ??? We make make the cost of moving from HI/LO/HILO/MD into general
+   ??? We make the cost of moving from HI/LO into general
    registers the same as for one of moving general registers to
-   HI/LO/HILO/MD for TARGET_MIPS16 in order to prevent allocating a
-   pseudo to HI/LO/HILO/MD.  This might hurt optimizations though, it
+   HI/LO for TARGET_MIPS16 in order to prevent allocating a
+   pseudo to HI/LO.  This might hurt optimizations though, it
    isn't clear if it is wise.  And it might not work in all cases.  We
    could solve the DImode LO reg problem by using a multiply, just
    like reload_{in,out}si.  We could solve the SImode/HImode HI reg
@@ -9849,8 +9831,7 @@ mips_register_move_cost (mode, to, from)
 	}
       else if (to == FP_REGS)
 	return 4;
-      else if (to == HI_REG || to == LO_REG || to == MD_REGS
-	       || to == HILO_REG)
+      else if (to == HI_REG || to == LO_REG || to == MD_REGS)
 	{
 	  if (TARGET_MIPS16)
 	    return 12;
@@ -9871,8 +9852,7 @@ mips_register_move_cost (mode, to, from)
       else if (to == ST_REGS)
 	return 8;
     }  /* from == FP_REGS */
-  else if (from == HI_REG || from == LO_REG || from == MD_REGS
-	   || from == HILO_REG)
+  else if (from == HI_REG || from == LO_REG || from == MD_REGS)
     {
       if (GR_REG_CLASS_P (to))
 	{
Index: config/mips/mips.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/mips/mips.h,v
retrieving revision 1.255
diff -u -d -p -F^\([(a-zA-Z0-9_]\|#define\) -r1.255 mips.h
--- config/mips/mips.h	30 May 2003 12:02:45 -0000	1.255
+++ config/mips/mips.h	7 Jun 2003 09:37:03 -0000
@@ -1774,14 +1774,9 @@ #define PROMOTE_FUNCTION_RETURN
 
    On the Mips, we have 32 integer registers, 32 floating point
    registers, 8 condition code registers, and the special registers
-   hi, lo, hilo, and rap.  Afetr that we have 32 COP0 registers, 32
-   COP2 registers, and 32 COp3 registers.  (COP1 is the floating-point
-   processor.)  The 8 condition code registers are only used if
-   mips_isa >= 4.  The hilo register is only used in 64 bit mode.  It
-   represents a 64 bit value stored as two 32 bit values in the hi and
-   lo registers; this is the result of the mult instruction.  rap is a
-   pointer to the stack where the return address reg ($31) was stored.
-   This is needed for C++ exception handling.  */
+   hi and lo.  After that we have 32 COP0 registers, 32 COP2 registers,
+   and 32 COP3 registers.  (COP1 is the floating-point processor.)
+   The 8 condition code registers are only used if mips_isa >= 4.  */
 
 #define FIRST_PSEUDO_REGISTER 176
 
@@ -1802,7 +1797,7 @@ #define FIXED_REGISTERS							\
   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0,			\
   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,			\
   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,			\
-  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1,			\
+  0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1,			\
   /* COP0 registers */							\
   1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,			\
   1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,			\
@@ -1886,7 +1881,7 @@ #define FP_REG_NUM   (FP_REG_LAST - FP_R
 #define FP_DBX_FIRST ((write_symbols == DBX_DEBUG) ? 38 : 32)
 
 #define MD_REG_FIRST 64
-#define MD_REG_LAST  66
+#define MD_REG_LAST  65
 #define MD_REG_NUM   (MD_REG_LAST - MD_REG_FIRST + 1)
 #define MD_DBX_FIRST (FP_DBX_FIRST + FP_REG_NUM)
 
@@ -1913,7 +1908,6 @@ #define ALL_COP_REG_NUM (COP3_REG_LAST -
 #define AT_REGNUM	(GP_REG_FIRST + 1)
 #define HI_REGNUM	(MD_REG_FIRST + 0)
 #define LO_REGNUM	(MD_REG_FIRST + 1)
-#define HILO_REGNUM	(MD_REG_FIRST + 2)
 
 /* FPSW_REGNUM is the single condition code used if mips_isa < 4.  If
    mips_isa >= 4, it should not be used, and an arbitrary ST_REG
@@ -2093,14 +2087,12 @@ enum reg_class
   FP_REGS,			/* floating point registers */
   HI_REG,			/* hi register */
   LO_REG,			/* lo register */
-  HILO_REG,			/* hilo register pair for 64 bit mode mult */
   MD_REGS,			/* multiply/divide registers (hi/lo) */
   COP0_REGS,			/* generic coprocessor classes */
   COP2_REGS,
   COP3_REGS,
   HI_AND_GR_REGS,		/* union classes */
   LO_AND_GR_REGS,
-  HILO_AND_GR_REGS,
   HI_AND_FP_REGS,
   COP0_AND_GR_REGS,
   COP2_AND_GR_REGS,
@@ -2133,7 +2125,6 @@ #define REG_CLASS_NAMES							\
   "FP_REGS",								\
   "HI_REG",								\
   "LO_REG",								\
-  "HILO_REG",								\
   "MD_REGS",								\
   /* coprocessor registers */						\
   "COP0_REGS",								\
@@ -2141,7 +2132,6 @@ #define REG_CLASS_NAMES							\
   "COP3_REGS",								\
   "HI_AND_GR_REGS",							\
   "LO_AND_GR_REGS",							\
-  "HILO_AND_GR_REGS",							\
   "HI_AND_FP_REGS",							\
   "COP0_AND_GR_REGS",							\
   "COP2_AND_GR_REGS",							\
@@ -2176,14 +2166,12 @@ #define REG_CLASS_CONTENTS						\
   { 0x00000000, 0xffffffff, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },	/* floating registers*/	\
   { 0x00000000, 0x00000000, 0x00000001, 0x00000000, 0x00000000, 0x00000000 },	/* hi register */	\
   { 0x00000000, 0x00000000, 0x00000002, 0x00000000, 0x00000000, 0x00000000 },	/* lo register */	\
-  { 0x00000000, 0x00000000, 0x00000004, 0x00000000, 0x00000000, 0x00000000 },	/* hilo register */	\
   { 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x00000000, 0x00000000 },	/* mul/div registers */	\
   { 0x00000000, 0x00000000, 0xffff0000, 0x0000ffff, 0x00000000, 0x00000000 }, /* cop0 registers */ \
   { 0x00000000, 0x00000000, 0x00000000, 0xffff0000, 0x0000ffff, 0x00000000 }, /* cop2 registers */ \
   { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xffff0000, 0x0000ffff }, /* cop3 registers */ \
   { 0xffffffff, 0x00000000, 0x00000001, 0x00000000, 0x00000000, 0x00000000 },	/* union classes */     \
   { 0xffffffff, 0x00000000, 0x00000002, 0x00000000, 0x00000000, 0x00000000 },				\
-  { 0xffffffff, 0x00000000, 0x00000004, 0x00000000, 0x00000000, 0x00000000 },				\
   { 0x00000000, 0xffffffff, 0x00000001, 0x00000000, 0x00000000, 0x00000000 },				\
   { 0xffffffff, 0x00000000, 0xffff0000, 0x0000ffff, 0x00000000, 0x00000000 },			\
   { 0xffffffff, 0x00000000, 0x00000000, 0xffff0000, 0x0000ffff, 0x00000000 },	\
@@ -2277,7 +2265,6 @@ #define ORDER_REGS_FOR_LOCAL_ALLOC mips_
    'h'	Hi register
    'l'	Lo register
    'x'	Multiply/divide registers
-   'a'	HILO_REG
    'z'	FP Status register
    'B'  Cop0 register
    'C'  Cop2 register
@@ -3403,7 +3390,8 @@ #define PREDICATE_CODES							\
   {"consttable_operand",	{ LABEL_REF, SYMBOL_REF, CONST_INT,	\
 				  CONST_DOUBLE, CONST }},		\
   {"fcc_register_operand",	{ REG, SUBREG }},			\
-  {"hilo_operand",		{ REG }},
+  {"hilo_operand",		{ REG }},				\
+  {"extend_operator",		{ ZERO_EXTEND, SIGN_EXTEND }},
 
 /* A list of predicates that do special things with modes, and so
    should not elicit warnings for VOIDmode match_operand.  */
@@ -3637,7 +3625,7 @@ #define DEBUG_REGISTER_NAMES						\
   "$f8",  "$f9",  "$f10", "$f11", "$f12", "$f13", "$f14", "$f15",	\
   "$f16", "$f17", "$f18", "$f19", "$f20", "$f21", "$f22", "$f23",	\
   "$f24", "$f25", "$f26", "$f27", "$f28", "$f29", "$f30", "$f31",	\
-  "hi",   "lo",   "accum","$fcc0","$fcc1","$fcc2","$fcc3","$fcc4",	\
+  "hi",   "lo",   "",     "$fcc0","$fcc1","$fcc2","$fcc3","$fcc4",	\
   "$fcc5","$fcc6","$fcc7","$rap", "",     "",     "",     "",		\
   "$c0r0", "$c0r1", "$c0r2", "$c0r3", "$c0r4", "$c0r5", "$c0r6", "$c0r7",\
   "$c0r8", "$c0r9", "$c0r10","$c0r11","$c0r12","$c0r13","$c0r14","$c0r15",\
Index: config/mips/mips.md
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/mips/mips.md,v
retrieving revision 1.171
diff -u -d -p -F^\([(a-zA-Z0-9_]\|#define\) -r1.171 mips.md
--- config/mips/mips.md	29 May 2003 08:33:25 -0000	1.171
+++ config/mips/mips.md	7 Jun 2003 09:37:03 -0000
@@ -31,7 +31,6 @@ (define_constants
    (UNSPEC_LOAD_DF_HIGH		 1)
    (UNSPEC_STORE_DF_HIGH	 2)
    (UNSPEC_GET_FNADDR		 4)
-   (UNSPEC_HILO_DELAY		 5)
    (UNSPEC_BLOCKAGE		 6)
    (UNSPEC_LOADGP		 7)
    (UNSPEC_SETJMP		 8)
@@ -1847,11 +1846,9 @@ (define_insn "mulsf3_r4300"
 ;; this by keeping the mflo with the mult on the R4000.
 
 (define_expand "mulsi3"
-  [(set (match_operand:SI 0 "register_operand" "=l")
-	(mult:SI (match_operand:SI 1 "register_operand" "d")
-		 (match_operand:SI 2 "register_operand" "d")))
-   (clobber (match_scratch:SI 3 "=h"))
-   (clobber (match_scratch:SI 4 "=a"))]
+  [(set (match_operand:SI 0 "register_operand" "")
+	(mult:SI (match_operand:SI 1 "register_operand" "")
+		 (match_operand:SI 2 "register_operand" "")))]
   ""
   "
 {
@@ -1869,8 +1866,7 @@ (define_insn "mulsi3_mult3"
 	(mult:SI (match_operand:SI 1 "register_operand" "d,d")
 		 (match_operand:SI 2 "register_operand" "d,d")))
    (clobber (match_scratch:SI 3 "=h,h"))
-   (clobber (match_scratch:SI 4 "=l,X"))
-   (clobber (match_scratch:SI 5 "=a,a"))]
+   (clobber (match_scratch:SI 4 "=l,X"))]
   "GENERATE_MULT3_SI
    || TARGET_MAD"
   "*
@@ -1897,36 +1893,32 @@ (define_insn "mulsi3_mult3"
 ;; Operand 1: GPR (1st multiplication operand)
 ;; Operand 2: GPR (2nd multiplication operand)
 ;; Operand 3: HI
-;; Operand 4: HILO
-;; Operand 5: GPR (destination)
+;; Operand 4: GPR (destination)
 (define_peephole2
   [(parallel
        [(set (match_operand:SI 0 "register_operand" "")
 	     (mult:SI (match_operand:SI 1 "register_operand" "")
 		      (match_operand:SI 2 "register_operand" "")))
         (clobber (match_operand:SI 3 "register_operand" ""))
-        (clobber (scratch:SI))
-        (clobber (match_operand:SI 4 "register_operand" ""))])
-   (set (match_operand:SI 5 "register_operand" "")
+        (clobber (scratch:SI))])
+   (set (match_operand:SI 4 "register_operand" "")
         (match_dup 0))]
   "GENERATE_MULT3_SI
    && true_regnum (operands[0]) == LO_REGNUM
-   && GP_REG_P (true_regnum (operands[5]))
+   && GP_REG_P (true_regnum (operands[4]))
    && peep2_reg_dead_p (2, operands[0])"
   [(parallel
-       [(set (match_dup 5)
+       [(set (match_dup 4)
 	     (mult:SI (match_dup 1)
 		      (match_dup 2)))
         (clobber (match_dup 3))
-        (clobber (match_dup 0))
-        (clobber (match_dup 4))])])
+        (clobber (match_dup 0))])])
 
 (define_insn "mulsi3_internal"
   [(set (match_operand:SI 0 "register_operand" "=l")
 	(mult:SI (match_operand:SI 1 "register_operand" "d")
 		 (match_operand:SI 2 "register_operand" "d")))
-   (clobber (match_scratch:SI 3 "=h"))
-   (clobber (match_scratch:SI 4 "=a"))]
+   (clobber (match_scratch:SI 3 "=h"))]
   "!TARGET_MIPS4000 || TARGET_MIPS16"
   "mult\\t%1,%2"
   [(set_attr "type"	"imul")
@@ -1937,8 +1929,7 @@ (define_insn "mulsi3_r4000"
 	(mult:SI (match_operand:SI 1 "register_operand" "d")
 		 (match_operand:SI 2 "register_operand" "d")))
    (clobber (match_scratch:SI 3 "=h"))
-   (clobber (match_scratch:SI 4 "=l"))
-   (clobber (match_scratch:SI 5 "=a"))]
+   (clobber (match_scratch:SI 4 "=l"))]
   "TARGET_MIPS4000 && !TARGET_MIPS16"
   "mult\t%1,%2\;mflo\t%0"
   [(set_attr "type"	"imul")
@@ -1964,8 +1955,7 @@ (define_insn "*mul_acc_si"
 		 (match_operand:SI 3 "register_operand" "0,l,*d")))
    (clobber (match_scratch:SI 4 "=h,h,h"))
    (clobber (match_scratch:SI 5 "=X,3,l"))
-   (clobber (match_scratch:SI 6 "=a,a,a"))
-   (clobber (match_scratch:SI 7 "=X,X,d"))]
+   (clobber (match_scratch:SI 6 "=X,X,&d"))]
   "(TARGET_MIPS3900
    || ISA_HAS_MADD_MSUB)
    && !TARGET_MIPS16"
@@ -1990,17 +1980,15 @@ (define_split
 		 (match_operand:SI 3 "register_operand" "")))
    (clobber (match_scratch:SI 4 ""))
    (clobber (match_scratch:SI 5 ""))
-   (clobber (match_scratch:SI 6 ""))
-   (clobber (match_scratch:SI 7 ""))]
+   (clobber (match_scratch:SI 6 ""))]
   "reload_completed && !TARGET_DEBUG_D_MODE
    && GP_REG_P (true_regnum (operands[0]))
    && GP_REG_P (true_regnum (operands[3]))"
-  [(parallel [(set (match_dup 7)
+  [(parallel [(set (match_dup 6)
 		   (mult:SI (match_dup 1) (match_dup 2)))
 	      (clobber (match_dup 4))
-	      (clobber (match_dup 5))
-	      (clobber (match_dup 6))])
-   (set (match_dup 0) (plus:SI (match_dup 7) (match_dup 3)))]
+	      (clobber (match_dup 5))])
+   (set (match_dup 0) (plus:SI (match_dup 6) (match_dup 3)))]
   "")
 
 ;; Splitter to copy result of MADD to a general register
@@ -2011,8 +1999,7 @@ (define_split
                  (match_operand:SI          3 "register_operand" "")))
    (clobber (match_scratch:SI               4 ""))
    (clobber (match_scratch:SI               5 ""))
-   (clobber (match_scratch:SI               6 ""))
-   (clobber (match_scratch:SI               7 ""))]
+   (clobber (match_scratch:SI               6 ""))]
   "reload_completed && !TARGET_DEBUG_D_MODE
    && GP_REG_P (true_regnum (operands[0]))
    && true_regnum (operands[3]) == LO_REGNUM"
@@ -2021,8 +2008,7 @@ (define_split
                             (match_dup 3)))
               (clobber (match_dup 4))
               (clobber (match_dup 5))
-              (clobber (match_dup 6))
-              (clobber (match_dup 7))])
+              (clobber (match_dup 6))])
    (set (match_dup 0) (match_dup 3))]
   "")
 
@@ -2032,8 +2018,7 @@ (define_insn "*macc"
 			  (match_operand:SI 2 "register_operand" "d,d"))
 		 (match_operand:SI 3 "register_operand" "0,l")))
    (clobber (match_scratch:SI 4 "=h,h"))
-   (clobber (match_scratch:SI 5 "=X,3"))
-   (clobber (match_scratch:SI 6 "=a,a"))]
+   (clobber (match_scratch:SI 5 "=X,3"))]
   "ISA_HAS_MACC"
   "*
 {
@@ -2057,8 +2042,7 @@ (define_insn "*macc2"
 	(plus:SI (mult:SI (match_dup 1)
 			  (match_dup 2))
 		 (match_dup 0)))
-   (clobber (match_scratch:SI 4 "=h"))
-   (clobber (match_scratch:SI 5 "=a"))]
+   (clobber (match_scratch:SI 4 "=h"))]
   "ISA_HAS_MACC && reload_completed"
   "macc\\t%3,%1,%2"
   [(set_attr "type"	"imadd")
@@ -2070,8 +2054,7 @@ (define_insn "*macc2"
 ;; Operand 1: GPR (1st multiplication operand)
 ;; Operand 2: GPR (2nd multiplication operand)
 ;; Operand 3: HI
-;; Operand 4: HILO
-;; Operand 5: GPR (destination)
+;; Operand 4: GPR (destination)
 (define_peephole2
   [(parallel
        [(set (match_operand:SI 0 "register_operand" "")
@@ -2079,23 +2062,21 @@ (define_peephole2
 			       (match_operand:SI 2 "register_operand" ""))
 		      (match_dup 0)))
 	(clobber (match_operand:SI 3 "register_operand" ""))
-	(clobber (scratch:SI))
-	(clobber (match_operand:SI 4 "register_operand" ""))])
-   (set (match_operand:SI 5 "register_operand" "")
+	(clobber (scratch:SI))])
+   (set (match_operand:SI 4 "register_operand" "")
 	(match_dup 0))]
   "ISA_HAS_MACC
    && true_regnum (operands[0]) == LO_REGNUM
-   && GP_REG_P (true_regnum (operands[5]))"
+   && GP_REG_P (true_regnum (operands[4]))"
   [(parallel [(set (match_dup 0)
 		   (plus:SI (mult:SI (match_dup 1)
 				     (match_dup 2))
 			    (match_dup 0)))
-	      (set (match_dup 5)
+	      (set (match_dup 4)
 		   (plus:SI (mult:SI (match_dup 1)
 				     (match_dup 2))
 			    (match_dup 0)))
-	      (clobber (match_dup 3))
-	      (clobber (match_dup 4))])]
+	      (clobber (match_dup 3))])]
   "")
 
 ;; When we have a three-address multiplication instruction, it should
@@ -2112,7 +2093,6 @@ (define_peephole2
 ;; Operand 4: GPR (1st multiplication operand)
 ;; Operand 5: GPR (2nd multiplication operand)
 ;; Operand 6: HI
-;; Operand 7: HILO
 (define_peephole2
   [(match_scratch:SI 0 "d")
    (set (match_operand:SI 1 "register_operand" "")
@@ -2124,8 +2104,7 @@ (define_peephole2
 			       (match_operand:SI 5 "register_operand" ""))
 		      (match_dup 1)))
 	(clobber (match_operand:SI 6 "register_operand" ""))
-	(clobber (match_dup 1))
-	(clobber (match_operand:SI 7 "register_operand" ""))])]
+	(clobber (match_dup 1))])]
   "ISA_HAS_MACC && GENERATE_MULT3_SI
    && true_regnum (operands[1]) == LO_REGNUM
    && peep2_reg_dead_p (2, operands[1])
@@ -2134,8 +2113,7 @@ (define_peephole2
 		   (mult:SI (match_dup 4)
 			    (match_dup 5)))
 	      (clobber (match_dup 6))
-	      (clobber (match_dup 1))
-	      (clobber (match_dup 7))])
+	      (clobber (match_dup 1))])
    (set (match_dup 3)
 	(plus:SI (match_dup 0)
 		 (match_dup 2)))]
@@ -2149,8 +2127,7 @@ (define_peephole2
 ;; Operand 3: GPR (1st multiplication operand)
 ;; Operand 4: GPR (2nd multiplication operand)
 ;; Operand 5: HI
-;; Operand 6: HILO
-;; Operand 7: GPR (destination)
+;; Operand 6: GPR (destination)
 (define_peephole2
   [(match_scratch:SI 0 "d")
    (set (match_operand:SI 1 "register_operand" "")
@@ -2162,22 +2139,20 @@ (define_peephole2
 			       (match_operand:SI 4 "register_operand" ""))
 		      (match_dup 1)))
 	(clobber (match_operand:SI 5 "register_operand" ""))
-	(clobber (scratch:SI))
-	(clobber (match_operand:SI 6 "register_operand" ""))])
+	(clobber (scratch:SI))])
    (match_dup 0)
-   (set (match_operand:SI 7 "register_operand" "")
+   (set (match_operand:SI 6 "register_operand" "")
 	(match_dup 1))]
   "ISA_HAS_MACC && GENERATE_MULT3_SI
    && true_regnum (operands[1]) == LO_REGNUM
    && peep2_reg_dead_p (3, operands[1])
-   && GP_REG_P (true_regnum (operands[7]))"
+   && GP_REG_P (true_regnum (operands[6]))"
   [(parallel [(set (match_dup 0)
 		   (mult:SI (match_dup 3)
 			    (match_dup 4)))
 	      (clobber (match_dup 5))
-	      (clobber (match_dup 1))
-	      (clobber (match_dup 6))])
-   (set (match_dup 7)
+	      (clobber (match_dup 1))])
+   (set (match_dup 6)
 	(plus:SI (match_dup 0)
 		 (match_dup 2)))]
   "")
@@ -2189,8 +2164,7 @@ (define_insn "*mul_sub_si"
                            (match_operand:SI 3 "register_operand" "d,d,d"))))
    (clobber (match_scratch:SI 4 "=h,h,h"))
    (clobber (match_scratch:SI 5 "=X,1,l"))
-   (clobber (match_scratch:SI 6 "=a,a,a"))
-   (clobber (match_scratch:SI 7 "=X,X,d"))]
+   (clobber (match_scratch:SI 6 "=X,X,&d"))]
   "ISA_HAS_MADD_MSUB"
   "*
 {
@@ -2210,17 +2184,15 @@ (define_split
                            (match_operand:SI 3 "register_operand" ""))))
    (clobber (match_scratch:SI 4 ""))
    (clobber (match_scratch:SI 5 ""))
-   (clobber (match_scratch:SI 6 ""))
-   (clobber (match_scratch:SI 7 ""))]
+   (clobber (match_scratch:SI 6 ""))]
   "reload_completed && !TARGET_DEBUG_D_MODE
    && GP_REG_P (true_regnum (operands[0]))
    && GP_REG_P (true_regnum (operands[1]))"
-  [(parallel [(set (match_dup 7)
+  [(parallel [(set (match_dup 6)
                    (mult:SI (match_dup 2) (match_dup 3)))
               (clobber (match_dup 4))
-              (clobber (match_dup 5))
-              (clobber (match_dup 6))])
-   (set (match_dup 0) (minus:SI (match_dup 1) (match_dup 7)))]
+              (clobber (match_dup 5))])
+   (set (match_dup 0) (minus:SI (match_dup 1) (match_dup 6)))]
   "")
 
 ;; Splitter to copy result of MSUB to a general register
@@ -2231,8 +2203,7 @@ (define_split
                            (match_operand:SI 3 "register_operand" ""))))
    (clobber (match_scratch:SI 4 ""))
    (clobber (match_scratch:SI 5 ""))
-   (clobber (match_scratch:SI 6 ""))
-   (clobber (match_scratch:SI 7 ""))]
+   (clobber (match_scratch:SI 6 ""))]
   "reload_completed && !TARGET_DEBUG_D_MODE
    && GP_REG_P (true_regnum (operands[0]))
    && true_regnum (operands[1]) == LO_REGNUM"
@@ -2241,8 +2212,7 @@ (define_split
                              (mult:SI (match_dup 2) (match_dup 3))))
               (clobber (match_dup 4))
               (clobber (match_dup 5))
-              (clobber (match_dup 6))
-              (clobber (match_dup 7))])
+              (clobber (match_dup 6))])
    (set (match_dup 0) (match_dup 1))]
   "")
 
@@ -2251,8 +2221,7 @@ (define_insn "*muls"
         (neg:SI (mult:SI (match_operand:SI 1 "register_operand" "d,d")
                          (match_operand:SI 2 "register_operand" "d,d"))))
    (clobber (match_scratch:SI              3                    "=h,h"))
-   (clobber (match_scratch:SI              4                    "=a,a"))
-   (clobber (match_scratch:SI              5                    "=X,l"))]
+   (clobber (match_scratch:SI              4                    "=X,l"))]
   "ISA_HAS_MULS"
   "@
    muls\\t$0,%1,%2
@@ -2266,8 +2235,7 @@ (define_insn "*msac"
                   (mult:SI (match_operand:SI 2 "register_operand" "d,d")
                            (match_operand:SI 3 "register_operand" "d,d"))))
    (clobber (match_scratch:SI 4 "=h,h"))
-   (clobber (match_scratch:SI 5 "=X,1"))
-   (clobber (match_scratch:SI 6 "=a,a"))]
+   (clobber (match_scratch:SI 5 "=X,1"))]
   "ISA_HAS_MSAC"
   "*
 {
@@ -2282,11 +2250,9 @@ (define_insn "*msac"
    (set_attr "mode"     "SI")])
 
 (define_expand "muldi3"
-  [(set (match_operand:DI 0 "register_operand" "=l")
-	(mult:DI (match_operand:DI 1 "register_operand" "d")
-		 (match_operand:DI 2 "register_operand" "d")))
-   (clobber (match_scratch:DI 3 "=h"))
-   (clobber (match_scratch:DI 4 "=a"))]
+  [(set (match_operand:DI 0 "register_operand" "")
+	(mult:DI (match_operand:DI 1 "register_operand" "")
+		 (match_operand:DI 2 "register_operand" "")))]
   "TARGET_64BIT"
 
   "
@@ -2302,8 +2268,7 @@ (define_insn "muldi3_internal"
   [(set (match_operand:DI 0 "register_operand" "=l")
 	(mult:DI (match_operand:DI 1 "register_operand" "d")
 		 (match_operand:DI 2 "register_operand" "d")))
-   (clobber (match_scratch:DI 3 "=h"))
-   (clobber (match_scratch:DI 4 "=a"))]
+   (clobber (match_scratch:DI 3 "=h"))]
   "TARGET_64BIT && !TARGET_MIPS4000"
   "dmult\\t%1,%2"
   [(set_attr "type"	"imul")
@@ -2314,8 +2279,7 @@ (define_insn "muldi3_internal2"
 	(mult:DI (match_operand:DI 1 "register_operand" "d")
 		 (match_operand:DI 2 "register_operand" "d")))
    (clobber (match_scratch:DI 3 "=h"))
-   (clobber (match_scratch:DI 4 "=l"))
-   (clobber (match_scratch:DI 5 "=a"))]
+   (clobber (match_scratch:DI 4 "=l"))]
   "TARGET_64BIT && (GENERATE_MULT3_DI || TARGET_MIPS4000)"
   {
     if (GENERATE_MULT3_DI)
@@ -2333,86 +2297,139 @@ (define_insn "muldi3_internal2"
 ;; ??? We could define a mulditi3 pattern when TARGET_64BIT.
 
 (define_expand "mulsidi3"
-  [(set (match_operand:DI 0 "register_operand" "=x")
-	(mult:DI (sign_extend:DI (match_operand:SI 1 "register_operand" "d"))
-		 (sign_extend:DI (match_operand:SI 2 "register_operand" "d"))))]
+  [(parallel
+      [(set (match_operand:DI 0 "register_operand" "")
+	    (mult:DI
+	       (sign_extend:DI (match_operand:SI 1 "register_operand" ""))
+	       (sign_extend:DI (match_operand:SI 2 "register_operand" ""))))
+       (clobber (scratch:DI))
+       (clobber (scratch:DI))
+       (clobber (scratch:DI))])]
   ""
-  "
-{
-  if (TARGET_64BIT)
-    emit_insn (gen_mulsidi3_64bit (operands[0], operands[1], operands[2]));
-  else
-    emit_insn (gen_mulsidi3_internal (operands[0], operands[1], operands[2]));
-  DONE;
-}")
+  {
+    if (!TARGET_64BIT)
+      {
+	emit_insn (gen_mulsidi3_32bit (operands[0], operands[1], operands[2]));
+	DONE;
+      }
+   })
 
-(define_insn "mulsidi3_internal"
+(define_insn "mulsidi3_32bit"
   [(set (match_operand:DI 0 "register_operand" "=x")
-	(mult:DI (sign_extend:DI (match_operand:SI 1 "register_operand" "d"))
-		 (sign_extend:DI (match_operand:SI 2 "register_operand" "d"))))
-   (clobber (match_scratch:SI 3 "=a"))]
+	(mult:DI
+	   (sign_extend:DI (match_operand:SI 1 "register_operand" "d"))
+	   (sign_extend:DI (match_operand:SI 2 "register_operand" "d"))))]
   "!TARGET_64BIT"
   "mult\\t%1,%2"
   [(set_attr "type"	"imul")
    (set_attr "mode"	"SI")])
 
-(define_insn "mulsidi3_64bit"
-  [(set (match_operand:DI 0 "register_operand" "=a")
-	(mult:DI (sign_extend:DI (match_operand:SI 1 "register_operand" "d"))
-		 (sign_extend:DI (match_operand:SI 2 "register_operand" "d"))))
-   (clobber (match_scratch:DI 3 "=l"))
-   (clobber (match_scratch:DI 4 "=h"))]
-  "TARGET_64BIT"
-  "mult\\t%1,%2"
-  [(set_attr "type"	"imul")
-   (set_attr "mode"	"SI")])
+(define_insn_and_split "*mulsidi3_64bit"
+  [(set (match_operand:DI 0 "register_operand" "=d")
+	(mult:DI (match_operator:DI 1 "extend_operator"
+		    [(match_operand:SI 3 "register_operand" "d")])
+		 (match_operator:DI 2 "extend_operator"
+		    [(match_operand:SI 4 "register_operand" "d")])))
+   (clobber (match_scratch:DI 5 "=l"))
+   (clobber (match_scratch:DI 6 "=h"))
+   (clobber (match_scratch:DI 7 "=d"))]
+  "TARGET_64BIT && GET_CODE (operands[1]) == GET_CODE (operands[2])"
+  "#"
+  "&& reload_completed"
+  [(parallel
+       [(set (match_dup 5)
+	     (sign_extend:DI
+		(mult:SI (match_dup 3)
+		         (match_dup 4))))
+	(set (match_dup 6)
+	     (ashiftrt:DI
+		(mult:DI (match_dup 1)
+			 (match_dup 2))
+		(const_int 32)))])
 
-(define_expand "umulsidi3"
-  [(set (match_operand:DI 0 "register_operand" "=x")
-	(mult:DI (zero_extend:DI (match_operand:SI 1 "register_operand" "d"))
-		 (zero_extend:DI (match_operand:SI 2 "register_operand" "d"))))]
+   ;; OP7 <- LO, OP0 <- HI
+   (set (match_dup 7) (match_dup 5))
+   (set (match_dup 0) (match_dup 6))
+
+   ;; Zero-extend OP7.
+   (set (match_dup 7)
+	(ashift:DI (match_dup 7)
+		   (const_int 32)))
+   (set (match_dup 7)
+	(lshiftrt:DI (match_dup 7)
+		     (const_int 32)))
+
+   ;; Shift OP0 into place.
+   (set (match_dup 0)
+	(ashift:DI (match_dup 0)
+		   (const_int 32)))
+
+   ;; OR the two halves together
+   (set (match_dup 0)
+	(ior:DI (match_dup 0)
+		(match_dup 7)))]
   ""
-  "
-{
-  if (TARGET_64BIT)
-    emit_insn (gen_umulsidi3_64bit (operands[0], operands[1], operands[2]));
-  else
-    emit_insn (gen_umulsidi3_internal (operands[0], operands[1], operands[2]));
+  [(set_attr "type"	"imul")
+   (set_attr "mode"	"SI")
+   (set_attr "length"	"24")])
 
-  DONE;
-}")
+(define_insn "*mulsidi3_64bit_parts"
+  [(set (match_operand:DI 0 "register_operand" "=l")
+	(sign_extend:DI
+	   (mult:SI (match_operand:SI 2 "register_operand" "d")
+		    (match_operand:SI 3 "register_operand" "d"))))
+   (set (match_operand:DI 1 "register_operand" "=h")
+	(ashiftrt:DI
+	   (mult:DI
+	      (match_operator:DI 4 "extend_operator" [(match_dup 2)])
+	      (match_operator:DI 5 "extend_operator" [(match_dup 3)]))
+	   (const_int 32)))]
+  "TARGET_64BIT && GET_CODE (operands[4]) == GET_CODE (operands[5])"
+  {
+    if (GET_CODE (operands[4]) == SIGN_EXTEND)
+      return "mult\t%2,%3";
+    else
+      return "multu\t%2,%3";
+  }
+  [(set_attr "type" "imul")
+   (set_attr "mode" "SI")])
 
+(define_expand "umulsidi3"
+  [(parallel
+      [(set (match_operand:DI 0 "register_operand" "")
+	    (mult:DI
+	       (zero_extend:DI (match_operand:SI 1 "register_operand" ""))
+	       (zero_extend:DI (match_operand:SI 2 "register_operand" ""))))
+       (clobber (scratch:DI))
+       (clobber (scratch:DI))
+       (clobber (scratch:DI))])]
+  ""
+  {
+    if (!TARGET_64BIT)
+      {
+        emit_insn (gen_umulsidi3_32bit (operands[0], operands[1],
+					operands[2]));
+	DONE;
+      }
+  })
 
-(define_insn "umulsidi3_internal"
+(define_insn "umulsidi3_32bit"
   [(set (match_operand:DI 0 "register_operand" "=x")
-	(mult:DI (zero_extend:DI (match_operand:SI 1 "register_operand" "d"))
-		 (zero_extend:DI (match_operand:SI 2 "register_operand" "d"))))
-   (clobber (match_scratch:SI 3 "=a"))]
+	(mult:DI
+	   (zero_extend:DI (match_operand:SI 1 "register_operand" "d"))
+	   (zero_extend:DI (match_operand:SI 2 "register_operand" "d"))))]
   "!TARGET_64BIT"
   "multu\\t%1,%2"
   [(set_attr "type"	"imul")
    (set_attr "mode"	"SI")])
 
-(define_insn "umulsidi3_64bit"
-  [(set (match_operand:DI 0 "register_operand" "=a")
-	(mult:DI (zero_extend:DI (match_operand:SI 1 "register_operand" "d"))
-		 (zero_extend:DI (match_operand:SI 2 "register_operand" "d"))))
-   (clobber (match_scratch:DI 3 "=l"))
-   (clobber (match_scratch:DI 4 "=h"))]
-  "TARGET_64BIT"
-  "multu\\t%1,%2"
-  [(set_attr "type"	"imul")
-   (set_attr "mode"	"SI")])
-
-;; Widening multiply with negation.  It isn't worth using this pattern
-;; for 64-bit code since the reload sequence for HILO_REGNUM is so long.
+;; Widening multiply with negation.
 (define_insn "*muls_di"
   [(set (match_operand:DI 0 "register_operand" "=x")
         (neg:DI
 	 (mult:DI
 	  (sign_extend:DI (match_operand:SI 1 "register_operand" "d"))
-	  (sign_extend:DI (match_operand:SI 2 "register_operand" "d")))))
-   (clobber (match_scratch:SI 3 "=a"))]
+	  (sign_extend:DI (match_operand:SI 2 "register_operand" "d")))))]
   "!TARGET_64BIT && ISA_HAS_MULS"
   "muls\\t$0,%1,%2"
   [(set_attr "type"     "imul")
@@ -2424,22 +2441,20 @@ (define_insn "*umuls_di"
 	(neg:DI
 	 (mult:DI
 	  (zero_extend:DI (match_operand:SI 1 "register_operand" "d"))
-	  (zero_extend:DI (match_operand:SI 2 "register_operand" "d")))))
-   (clobber (match_scratch:SI 3 "=a"))]
+	  (zero_extend:DI (match_operand:SI 2 "register_operand" "d")))))]
   "!TARGET_64BIT && ISA_HAS_MULS"
   "mulsu\\t$0,%1,%2"
   [(set_attr "type"     "imul")
    (set_attr "length"   "4")
    (set_attr "mode"     "SI")])
 
-;; Not used for 64-bit code: see comment for *muls_di.
 (define_insn "*smsac_di"
   [(set (match_operand:DI 0 "register_operand" "=x")
-        (minus:DI (match_operand:DI 3 "register_operand" "0")
-		  (mult:DI
-		   (sign_extend:DI (match_operand:SI 1 "register_operand" "d"))
-		   (sign_extend:DI (match_operand:SI 2 "register_operand" "d")))))
-   (clobber (match_scratch:SI 4 "=a"))]
+        (minus:DI
+	   (match_operand:DI 3 "register_operand" "0")
+	   (mult:DI
+	      (sign_extend:DI (match_operand:SI 1 "register_operand" "d"))
+	      (sign_extend:DI (match_operand:SI 2 "register_operand" "d")))))]
   "!TARGET_64BIT && ISA_HAS_MSAC"
   "*
 {
@@ -2454,11 +2469,11 @@ (define_insn "*smsac_di"
 
 (define_insn "*umsac_di"
   [(set (match_operand:DI 0 "register_operand" "=x")
-	(minus:DI (match_operand:DI 3 "register_operand" "0")
-		  (mult:DI
-		   (zero_extend:DI (match_operand:SI 1 "register_operand" "d"))
-		   (zero_extend:DI (match_operand:SI 2 "register_operand" "d")))))
-   (clobber (match_scratch:SI 4 "=a"))]
+	(minus:DI
+	   (match_operand:DI 3 "register_operand" "0")
+	   (mult:DI
+	      (zero_extend:DI (match_operand:SI 1 "register_operand" "d"))
+	      (zero_extend:DI (match_operand:SI 2 "register_operand" "d")))))]
   "!TARGET_64BIT && ISA_HAS_MSAC"
   "*
 {
@@ -2473,11 +2488,11 @@ (define_insn "*umsac_di"
 
 ;; _highpart patterns
 (define_expand "umulsi3_highpart"
-  [(set (match_operand:SI 0 "register_operand" "=h")
+  [(set (match_operand:SI 0 "register_operand" "")
 	(truncate:SI
 	 (lshiftrt:DI
-	  (mult:DI (zero_extend:DI (match_operand:SI 1 "register_operand" "d"))
-		   (zero_extend:DI (match_operand:SI 2 "register_operand" "d")))
+	  (mult:DI (zero_extend:DI (match_operand:SI 1 "register_operand" ""))
+		   (zero_extend:DI (match_operand:SI 2 "register_operand" "")))
 	  (const_int 32))))]
   ""
   "
@@ -2498,8 +2513,7 @@ (define_insn "umulsi3_highpart_internal"
 	  (mult:DI (zero_extend:DI (match_operand:SI 1 "register_operand" "d"))
 		   (zero_extend:DI (match_operand:SI 2 "register_operand" "d")))
 	  (const_int 32))))
-   (clobber (match_scratch:SI 3 "=l"))
-   (clobber (match_scratch:SI 4 "=a"))]
+   (clobber (match_scratch:SI 3 "=l"))]
   "!ISA_HAS_MULHI"
   "multu\\t%1,%2"
   [(set_attr "type"   "imul")
@@ -2514,8 +2528,7 @@ (define_insn "umulsi3_highpart_mulhi_int
 		   (zero_extend:DI (match_operand:SI 2 "register_operand" "d,d")))
 	  (const_int 32))))
    (clobber (match_scratch:SI 3 "=l,l"))
-   (clobber (match_scratch:SI 4 "=a,a"))
-   (clobber (match_scratch:SI 5 "=X,h"))]
+   (clobber (match_scratch:SI 4 "=X,h"))]
   "ISA_HAS_MULHI"
   "@
    multu\\t%1,%2
@@ -2533,8 +2546,7 @@ (define_insn "umulsi3_highpart_neg_mulhi
 		    (zero_extend:DI (match_operand:SI 2 "register_operand" "d,d"))))
 	  (const_int 32))))
    (clobber (match_scratch:SI 3 "=l,l"))
-   (clobber (match_scratch:SI 4 "=a,a"))
-   (clobber (match_scratch:SI 5 "=X,h"))]
+   (clobber (match_scratch:SI 4 "=X,h"))]
   "ISA_HAS_MULHI"
   "@
    mulshiu\\t%.,%1,%2
@@ -2544,11 +2556,11 @@ (define_insn "umulsi3_highpart_neg_mulhi
    (set_attr "length" "4")])
 
 (define_expand "smulsi3_highpart"
-  [(set (match_operand:SI 0 "register_operand" "=h")
+  [(set (match_operand:SI 0 "register_operand" "")
 	(truncate:SI
 	 (lshiftrt:DI
-	  (mult:DI (sign_extend:DI (match_operand:SI 1 "register_operand" "d"))
-		   (sign_extend:DI (match_operand:SI 2 "register_operand" "d")))
+	  (mult:DI (sign_extend:DI (match_operand:SI 1 "register_operand" ""))
+		   (sign_extend:DI (match_operand:SI 2 "register_operand" "")))
          (const_int 32))))]
   ""
   "
@@ -2569,8 +2581,7 @@ (define_insn "smulsi3_highpart_internal"
 	  (mult:DI (sign_extend:DI (match_operand:SI 1 "register_operand" "d"))
 		   (sign_extend:DI (match_operand:SI 2 "register_operand" "d")))
 	  (const_int 32))))
-   (clobber (match_scratch:SI 3 "=l"))
-   (clobber (match_scratch:SI 4 "=a"))]
+   (clobber (match_scratch:SI 3 "=l"))]
   "!ISA_HAS_MULHI"
   "mult\\t%1,%2"
   [(set_attr "type"	"imul")
@@ -2585,8 +2596,7 @@ (define_insn "smulsi3_highpart_mulhi_int
 		   (sign_extend:DI (match_operand:SI 2 "register_operand" "d,d")))
 	  (const_int 32))))
    (clobber (match_scratch:SI 3 "=l,l"))
-   (clobber (match_scratch:SI 4 "=a,a"))
-   (clobber (match_scratch:SI 5 "=X,h"))]
+   (clobber (match_scratch:SI 4 "=X,h"))]
   "ISA_HAS_MULHI"
   "@
    mult\\t%1,%2
@@ -2604,8 +2614,7 @@ (define_insn "smulsi3_highpart_neg_mulhi
 		    (sign_extend:DI (match_operand:SI 2 "register_operand" "d,d"))))
 	  (const_int 32))))
    (clobber (match_scratch:SI 3 "=l,l"))
-   (clobber (match_scratch:SI 4 "=a,a"))
-   (clobber (match_scratch:SI 5 "=X,h"))]
+   (clobber (match_scratch:SI 4 "=X,h"))]
   "ISA_HAS_MULHI"
   "@
    mulshi\\t%.,%1,%2
@@ -2621,8 +2630,7 @@ (define_insn "smuldi3_highpart"
 	   (sign_extend:TI (match_operand:DI 1 "register_operand" "d"))
 	   (sign_extend:TI (match_operand:DI 2 "register_operand" "d")))
          (const_int 64))))
-   (clobber (match_scratch:DI 3 "=l"))
-   (clobber (match_scratch:DI 4 "=a"))]
+   (clobber (match_scratch:DI 3 "=l"))]
   "TARGET_64BIT"
   "dmult\\t%1,%2"
   [(set_attr "type"	"imul")
@@ -2636,8 +2644,7 @@ (define_insn "umuldi3_highpart"
 	   (zero_extend:TI (match_operand:DI 1 "register_operand" "d"))
 	   (zero_extend:TI (match_operand:DI 2 "register_operand" "d")))
 	  (const_int 64))))
-   (clobber (match_scratch:DI 3 "=l"))
-   (clobber (match_scratch:DI 4 "=a"))]
+   (clobber (match_scratch:DI 3 "=l"))]
   "TARGET_64BIT"
   "dmultu\\t%1,%2"
   [(set_attr "type"	"imul")
@@ -2652,21 +2659,18 @@ (define_insn "madsi"
 	(plus:SI (mult:SI (match_operand:SI 1 "register_operand" "d")
 			  (match_operand:SI 2 "register_operand" "d"))
 		 (match_dup 0)))
-   (clobber (match_scratch:SI 3 "=h"))
-   (clobber (match_scratch:SI 4 "=a"))]
+   (clobber (match_scratch:SI 3 "=h"))]
   "TARGET_MAD"
   "mad\\t%1,%2"
   [(set_attr "type"	"imadd")
    (set_attr "mode"	"SI")])
 
-;; Only use this pattern in 32-bit code: see *muls_di.
 (define_insn "*umul_acc_di"
   [(set (match_operand:DI 0 "register_operand" "=x")
 	(plus:DI
 	 (mult:DI (zero_extend:DI (match_operand:SI 1 "register_operand" "d"))
 		  (zero_extend:DI (match_operand:SI 2 "register_operand" "d")))
-	 (match_operand:DI 3 "register_operand" "0")))
-   (clobber (match_scratch:SI 4 "=a"))]
+	 (match_operand:DI 3 "register_operand" "0")))]
   "(TARGET_MAD || ISA_HAS_MACC)
    && !TARGET_64BIT"
   "*
@@ -2687,8 +2691,7 @@ (define_insn "*smul_acc_di"
 	(plus:DI
 	 (mult:DI (sign_extend:DI (match_operand:SI 1 "register_operand" "d"))
 		  (sign_extend:DI (match_operand:SI 2 "register_operand" "d")))
-	 (match_operand:DI 3 "register_operand" "0")))
-   (clobber (match_scratch:SI 4 "=a"))]
+	 (match_operand:DI 3 "register_operand" "0")))]
   "(TARGET_MAD || ISA_HAS_MACC)
    && !TARGET_64BIT"
   "*
@@ -2844,15 +2847,12 @@ (define_insn ""
 ;; available.
 
 (define_expand "divmodsi4"
-  [(set (match_operand:SI 0 "register_operand" "=d")
-	(div:SI (match_operand:SI 1 "register_operand" "d")
-		(match_operand:SI 2 "register_operand" "d")))
-   (set (match_operand:SI 3 "register_operand" "=d")
+  [(set (match_operand:SI 0 "register_operand" "")
+	(div:SI (match_operand:SI 1 "register_operand" "")
+		(match_operand:SI 2 "register_operand" "")))
+   (set (match_operand:SI 3 "register_operand" "")
 	(mod:SI (match_dup 1)
-		(match_dup 2)))
-   (clobber (match_scratch:SI 4 "=l"))
-   (clobber (match_scratch:SI 5 "=h"))
-   (clobber (match_scratch:SI 6 "=a"))]
+		(match_dup 2)))]
   "optimize"
   "
 {
@@ -2886,23 +2886,19 @@ (define_insn "divmodsi4_internal"
 		(match_operand:SI 2 "register_operand" "d")))
    (set (match_operand:SI 3 "register_operand" "=h")
 	(mod:SI (match_dup 1)
-		(match_dup 2)))
-   (clobber (match_scratch:SI 4 "=a"))]
+		(match_dup 2)))]
   "optimize"
   "div\\t$0,%1,%2"
   [(set_attr "type"	"idiv")
    (set_attr "mode"	"SI")])
 
 (define_expand "divmoddi4"
-  [(set (match_operand:DI 0 "register_operand" "=d")
-	(div:DI (match_operand:DI 1 "register_operand" "d")
-		(match_operand:DI 2 "register_operand" "d")))
-   (set (match_operand:DI 3 "register_operand" "=d")
+  [(set (match_operand:DI 0 "register_operand" "")
+	(div:DI (match_operand:DI 1 "register_operand" "")
+		(match_operand:DI 2 "register_operand" "")))
+   (set (match_operand:DI 3 "register_operand" "")
 	(mod:DI (match_dup 1)
-		(match_dup 2)))
-   (clobber (match_scratch:DI 4 "=l"))
-   (clobber (match_scratch:DI 5 "=h"))
-   (clobber (match_scratch:DI 6 "=a"))]
+		(match_dup 2)))]
   "TARGET_64BIT && optimize"
   "
 {
@@ -2934,23 +2930,19 @@ (define_insn "divmoddi4_internal"
 		(match_operand:DI 2 "register_operand" "d")))
    (set (match_operand:DI 3 "register_operand" "=h")
 	(mod:DI (match_dup 1)
-		(match_dup 2)))
-   (clobber (match_scratch:DI 4 "=a"))]
+		(match_dup 2)))]
   "TARGET_64BIT && optimize"
   "ddiv\\t$0,%1,%2"
   [(set_attr "type"	"idiv")
    (set_attr "mode"	"SI")])
 
 (define_expand "udivmodsi4"
-  [(set (match_operand:SI 0 "register_operand" "=d")
-	(udiv:SI (match_operand:SI 1 "register_operand" "d")
-		 (match_operand:SI 2 "register_operand" "d")))
-   (set (match_operand:SI 3 "register_operand" "=d")
+  [(set (match_operand:SI 0 "register_operand" "")
+	(udiv:SI (match_operand:SI 1 "register_operand" "")
+		 (match_operand:SI 2 "register_operand" "")))
+   (set (match_operand:SI 3 "register_operand" "")
 	(umod:SI (match_dup 1)
-		 (match_dup 2)))
-   (clobber (match_scratch:SI 4 "=l"))
-   (clobber (match_scratch:SI 5 "=h"))
-   (clobber (match_scratch:SI 6 "=a"))]
+		 (match_dup 2)))]
   "optimize"
   "
 {
@@ -2972,23 +2964,19 @@ (define_insn "udivmodsi4_internal"
 		 (match_operand:SI 2 "register_operand" "d")))
    (set (match_operand:SI 3 "register_operand" "=h")
 	(umod:SI (match_dup 1)
-		 (match_dup 2)))
-   (clobber (match_scratch:SI 4 "=a"))]
+		 (match_dup 2)))]
   "optimize"
   "divu\\t$0,%1,%2"
   [(set_attr "type"	"idiv")
    (set_attr "mode"	"SI")])
 
 (define_expand "udivmoddi4"
-  [(set (match_operand:DI 0 "register_operand" "=d")
-	(udiv:DI (match_operand:DI 1 "register_operand" "d")
-		 (match_operand:DI 2 "register_operand" "d")))
-   (set (match_operand:DI 3 "register_operand" "=d")
+  [(set (match_operand:DI 0 "register_operand" "")
+	(udiv:DI (match_operand:DI 1 "register_operand" "")
+		 (match_operand:DI 2 "register_operand" "")))
+   (set (match_operand:DI 3 "register_operand" "")
 	(umod:DI (match_dup 1)
-		 (match_dup 2)))
-   (clobber (match_scratch:DI 4 "=l"))
-   (clobber (match_scratch:DI 5 "=h"))
-   (clobber (match_scratch:DI 6 "=a"))]
+		 (match_dup 2)))]
   "TARGET_64BIT && optimize"
   "
 {
@@ -3010,8 +2998,7 @@ (define_insn "udivmoddi4_internal"
 		 (match_operand:DI 2 "register_operand" "d")))
    (set (match_operand:DI 3 "register_operand" "=h")
 	(umod:DI (match_dup 1)
-		 (match_dup 2)))
-   (clobber (match_scratch:DI 4 "=a"))]
+		 (match_dup 2)))]
   "TARGET_64BIT && optimize"
   "ddivu\\t$0,%1,%2"
   [(set_attr "type"	"idiv")
@@ -3111,11 +3098,9 @@ (define_insn "div_trap_mips16"
    (set_attr "length" "12")])
 
 (define_expand "divsi3"
-  [(set (match_operand:SI 0 "register_operand" "=l")
-	(div:SI (match_operand:SI 1 "register_operand" "d")
-		(match_operand:SI 2 "register_operand" "d")))
-   (clobber (match_scratch:SI 3 "=h"))
-   (clobber (match_scratch:SI 4 "=a"))]
+  [(set (match_operand:SI 0 "register_operand" "")
+	(div:SI (match_operand:SI 1 "register_operand" "")
+		(match_operand:SI 2 "register_operand" "")))]
   "!optimize"
   "
 {
@@ -3146,20 +3131,17 @@ (define_expand "divsi3"
 (define_insn "divsi3_internal"
   [(set (match_operand:SI 0 "register_operand" "=l")
 	(div:SI (match_operand:SI 1 "register_operand" "d")
-		(match_operand:SI 2 "nonmemory_operand" "di")))
-   (clobber (match_scratch:SI 3 "=h"))
-   (clobber (match_scratch:SI 4 "=a"))]
+		(match_operand:SI 2 "register_operand" "d")))
+   (clobber (match_scratch:SI 3 "=h"))]
   "!optimize"
   "div\\t$0,%1,%2"
   [(set_attr "type"	"idiv")
    (set_attr "mode"	"SI")])
 
 (define_expand "divdi3"
-  [(set (match_operand:DI 0 "register_operand" "=l")
-	(div:DI (match_operand:DI 1 "register_operand" "d")
-		(match_operand:DI 2 "register_operand" "d")))
-   (clobber (match_scratch:DI 3 "=h"))
-   (clobber (match_scratch:DI 4 "=a"))]
+  [(set (match_operand:DI 0 "register_operand" "")
+	(div:DI (match_operand:DI 1 "register_operand" "")
+		(match_operand:DI 2 "register_operand" "")))]
   "TARGET_64BIT && !optimize"
   "
 {
@@ -3187,20 +3169,17 @@ (define_expand "divdi3"
 (define_insn "divdi3_internal"
   [(set (match_operand:DI 0 "register_operand" "=l")
 	(div:DI (match_operand:DI 1 "register_operand" "d")
-		(match_operand:DI 2 "nonmemory_operand" "di")))
-   (clobber (match_scratch:SI 3 "=h"))
-   (clobber (match_scratch:SI 4 "=a"))]
+		(match_operand:DI 2 "register_operand" "d")))
+   (clobber (match_scratch:SI 3 "=h"))]
   "TARGET_64BIT && !optimize"
   "ddiv\\t$0,%1,%2"
   [(set_attr "type"	"idiv")
    (set_attr "mode"	"DI")])
 
 (define_expand "modsi3"
-  [(set (match_operand:SI 0 "register_operand" "=h")
-	(mod:SI (match_operand:SI 1 "register_operand" "d")
-		(match_operand:SI 2 "register_operand" "d")))
-   (clobber (match_scratch:SI 3 "=l"))
-   (clobber (match_scratch:SI 4 "=a"))]
+  [(set (match_operand:SI 0 "register_operand" "")
+	(mod:SI (match_operand:SI 1 "register_operand" "")
+		(match_operand:SI 2 "register_operand" "")))]
   "!optimize"
   "
 {
@@ -3230,20 +3209,17 @@ (define_expand "modsi3"
 (define_insn "modsi3_internal"
   [(set (match_operand:SI 0 "register_operand" "=h")
 	(mod:SI (match_operand:SI 1 "register_operand" "d")
-		(match_operand:SI 2 "nonmemory_operand" "di")))
-   (clobber (match_scratch:SI 3 "=l"))
-   (clobber (match_scratch:SI 4 "=a"))]
+		(match_operand:SI 2 "register_operand" "d")))
+   (clobber (match_scratch:SI 3 "=l"))]
   "!optimize"
   "div\\t$0,%1,%2"
   [(set_attr "type"	"idiv")
    (set_attr "mode"	"SI")])
 
 (define_expand "moddi3"
-  [(set (match_operand:DI 0 "register_operand" "=h")
-	(mod:DI (match_operand:DI 1 "register_operand" "d")
-		(match_operand:DI 2 "register_operand" "d")))
-   (clobber (match_scratch:DI 3 "=l"))
-   (clobber (match_scratch:DI 4 "=a"))]
+  [(set (match_operand:DI 0 "register_operand" "")
+	(mod:DI (match_operand:DI 1 "register_operand" "")
+		(match_operand:DI 2 "register_operand" "")))]
   "TARGET_64BIT && !optimize"
   "
 {
@@ -3271,20 +3247,17 @@ (define_expand "moddi3"
 (define_insn "moddi3_internal"
   [(set (match_operand:DI 0 "register_operand" "=h")
 	(mod:DI (match_operand:DI 1 "register_operand" "d")
-		(match_operand:DI 2 "nonmemory_operand" "di")))
-   (clobber (match_scratch:SI 3 "=l"))
-   (clobber (match_scratch:SI 4 "=a"))]
+		(match_operand:DI 2 "register_operand" "d")))
+   (clobber (match_scratch:SI 3 "=l"))]
   "TARGET_64BIT && !optimize"
   "ddiv\\t$0,%1,%2"
   [(set_attr "type"	"idiv")
    (set_attr "mode"	"DI")])
 
 (define_expand "udivsi3"
-  [(set (match_operand:SI 0 "register_operand" "=l")
-	(udiv:SI (match_operand:SI 1 "register_operand" "d")
-		 (match_operand:SI 2 "register_operand" "d")))
-   (clobber (match_scratch:SI 3 "=h"))
-   (clobber (match_scratch:SI 4 "=a"))]
+  [(set (match_operand:SI 0 "register_operand" "")
+	(udiv:SI (match_operand:SI 1 "register_operand" "")
+		 (match_operand:SI 2 "register_operand" "")))]
   "!optimize"
   "
 {
@@ -3302,20 +3275,17 @@ (define_expand "udivsi3"
 (define_insn "udivsi3_internal"
   [(set (match_operand:SI 0 "register_operand" "=l")
 	(udiv:SI (match_operand:SI 1 "register_operand" "d")
-		 (match_operand:SI 2 "nonmemory_operand" "di")))
-   (clobber (match_scratch:SI 3 "=h"))
-   (clobber (match_scratch:SI 4 "=a"))]
+		 (match_operand:SI 2 "register_operand" "d")))
+   (clobber (match_scratch:SI 3 "=h"))]
   "!optimize"
   "divu\\t$0,%1,%2"
   [(set_attr "type"	"idiv")
    (set_attr "mode"	"SI")])
 
 (define_expand "udivdi3"
-  [(set (match_operand:DI 0 "register_operand" "=l")
-	(udiv:DI (match_operand:DI 1 "register_operand" "d")
-		 (match_operand:DI 2 "register_operand" "di")))
-   (clobber (match_scratch:DI 3 "=h"))
-   (clobber (match_scratch:DI 4 "=a"))]
+  [(set (match_operand:DI 0 "register_operand" "")
+	(udiv:DI (match_operand:DI 1 "register_operand" "")
+		 (match_operand:DI 2 "register_operand" "")))]
   "TARGET_64BIT && !optimize"
   "
 {
@@ -3333,20 +3303,17 @@ (define_expand "udivdi3"
 (define_insn "udivdi3_internal"
   [(set (match_operand:DI 0 "register_operand" "=l")
 	(udiv:DI (match_operand:DI 1 "register_operand" "d")
-		 (match_operand:DI 2 "nonmemory_operand" "di")))
-   (clobber (match_scratch:SI 3 "=h"))
-   (clobber (match_scratch:SI 4 "=a"))]
+		 (match_operand:DI 2 "register_operand" "d")))
+   (clobber (match_scratch:SI 3 "=h"))]
   "TARGET_64BIT && !optimize"
   "ddivu\\t$0,%1,%2"
   [(set_attr "type"	"idiv")
    (set_attr "mode"	"DI")])
 
 (define_expand "umodsi3"
-  [(set (match_operand:SI 0 "register_operand" "=h")
-	(umod:SI (match_operand:SI 1 "register_operand" "d")
-		 (match_operand:SI 2 "register_operand" "d")))
-   (clobber (match_scratch:SI 3 "=l"))
-   (clobber (match_scratch:SI 4 "=a"))]
+  [(set (match_operand:SI 0 "register_operand" "")
+	(umod:SI (match_operand:SI 1 "register_operand" "")
+		 (match_operand:SI 2 "register_operand" "")))]
   "!optimize"
   "
 {
@@ -3364,20 +3331,17 @@ (define_expand "umodsi3"
 (define_insn "umodsi3_internal"
   [(set (match_operand:SI 0 "register_operand" "=h")
 	(umod:SI (match_operand:SI 1 "register_operand" "d")
-		 (match_operand:SI 2 "nonmemory_operand" "di")))
-   (clobber (match_scratch:SI 3 "=l"))
-   (clobber (match_scratch:SI 4 "=a"))]
+		 (match_operand:SI 2 "register_operand" "d")))
+   (clobber (match_scratch:SI 3 "=l"))]
   "!optimize"
   "divu\\t$0,%1,%2"
   [(set_attr "type"	"idiv")
    (set_attr "mode"	"SI")])
 
 (define_expand "umoddi3"
-  [(set (match_operand:DI 0 "register_operand" "=h")
-	(umod:DI (match_operand:DI 1 "register_operand" "d")
-		 (match_operand:DI 2 "register_operand" "di")))
-   (clobber (match_scratch:DI 3 "=l"))
-   (clobber (match_scratch:DI 4 "=a"))]
+  [(set (match_operand:DI 0 "register_operand" "")
+	(umod:DI (match_operand:DI 1 "register_operand" "")
+		 (match_operand:DI 2 "register_operand" "")))]
   "TARGET_64BIT && !optimize"
   "
 {
@@ -3395,9 +3359,8 @@ (define_expand "umoddi3"
 (define_insn "umoddi3_internal"
   [(set (match_operand:DI 0 "register_operand" "=h")
 	(umod:DI (match_operand:DI 1 "register_operand" "d")
-		 (match_operand:DI 2 "nonmemory_operand" "di")))
-   (clobber (match_scratch:SI 3 "=l"))
-   (clobber (match_scratch:SI 4 "=a"))]
+		 (match_operand:DI 2 "register_operand" "d")))
+   (clobber (match_scratch:SI 3 "=l"))]
   "TARGET_64BIT && !optimize"
   "ddivu\\t$0,%1,%2"
   [(set_attr "type"	"idiv")
@@ -5143,17 +5106,17 @@ (define_insn ""
    (set_attr "length"	"8,8,8,8,12,*,*,8")])
 
 (define_insn "movdi_internal2"
-  [(set (match_operand:DI 0 "nonimmediate_operand" "=d,d,e,d,m,*f,*f,*f,*d,*m,*x,*d,*x,*a,*B*C*D,*B*C*D,*d,*m")
-	(match_operand:DI 1 "move_operand" "d,U,T,m,dJ,*f,*d*J,*m,*f,*f,*J,*x,*d,*J,*d,*m,*B*C*D,*B*C*D"))]
+  [(set (match_operand:DI 0 "nonimmediate_operand" "=d,d,e,d,m,*f,*f,*f,*d,*m,*x,*d,*x,*B*C*D,*B*C*D,*d,*m")
+	(match_operand:DI 1 "move_operand" "d,U,T,m,dJ,*f,*d*J,*m,*f,*f,*J,*x,*d,*d,*m,*B*C*D,*B*C*D"))]
   "TARGET_64BIT && !TARGET_MIPS16
    && (register_operand (operands[0], DImode)
        || register_operand (operands[1], DImode)
        || (GET_CODE (operands[1]) == CONST_INT && INTVAL (operands[1]) == 0)
        || operands[1] == CONST0_RTX (DImode))"
   { return mips_output_move (operands[0], operands[1]); }
-  [(set_attr "type"	"move,const,const,load,store,move,xfer,load,xfer,store,hilo,hilo,hilo,hilo,xfer,load,xfer,store")
+  [(set_attr "type"	"move,const,const,load,store,move,xfer,load,xfer,store,hilo,hilo,hilo,xfer,load,xfer,store")
    (set_attr "mode"	"DI")
-   (set_attr "length"	"4,*,*,*,*,4,4,*,4,*,4,4,4,8,8,*,8,*")])
+   (set_attr "length"	"4,*,*,*,*,4,4,*,4,*,4,4,4,8,*,8,*")])
 
 (define_insn "*movdi_internal2_mips16"
   [(set (match_operand:DI 0 "nonimmediate_operand" "=d,y,d,d,d,d,d,m,*d")
@@ -5224,168 +5187,6 @@ (define_split
     }
 }")
 
-;; Handle input reloads in DImode.
-;; This is mainly to handle reloading HILO_REGNUM.  Note that we may
-;; see it as the source or the destination, depending upon which way
-;; reload handles the instruction.
-;; Making the second operand TImode is a trick.  The compiler may
-;; reuse the same register for operand 0 and operand 2.  Using TImode
-;; gives us two registers, so we can always use the one which is not
-;; used.
-
-(define_expand "reload_indi"
-  [(set (match_operand:DI 0 "register_operand" "=b")
-	(match_operand:DI 1 "" "b"))
-   (clobber (match_operand:TI 2 "register_operand" "=&d"))]
-  "TARGET_64BIT"
-  "
-{
-  rtx scratch = gen_rtx_REG (DImode,
-			     (REGNO (operands[0]) == REGNO (operands[2])
-			      ? REGNO (operands[2]) + 1
-			      : REGNO (operands[2])));
-
-  if (GET_CODE (operands[0]) == REG && REGNO (operands[0]) == HILO_REGNUM)
-    {
-      if (GET_CODE (operands[1]) == MEM)
-	{
-	  rtx memword, offword, hi_word, lo_word;
-	  rtx addr = find_replacement (&XEXP (operands[1], 0));
-	  rtx op1 = replace_equiv_address (operands[1], addr);
-
-	  scratch = gen_rtx_REG (SImode, REGNO (scratch));
-	  memword = adjust_address (op1, SImode, 0);
-	  offword = adjust_address (op1, SImode, 4);
-
-	  if (BYTES_BIG_ENDIAN)
-	    {
-	      hi_word = memword;
-	      lo_word = offword;
-	    }
-	  else
-	    {
-	      hi_word = offword;
-	      lo_word = memword;
-	    }
-	  emit_move_insn (scratch, hi_word);
-	  emit_move_insn (gen_rtx_REG (SImode, 64), scratch);
-	  emit_move_insn (scratch, lo_word);
-	  emit_move_insn (gen_rtx (REG, SImode, 65), scratch);
-	  emit_insn (gen_hilo_delay (operands[0]));
-	}
-      else
-	{
-	  emit_insn (gen_ashrdi3 (scratch, operands[1], GEN_INT (32)));
-	  emit_insn (gen_movdi (gen_rtx_REG (DImode, 64), scratch));
-	  emit_insn (gen_ashldi3 (scratch, operands[1], GEN_INT (32)));
-	  emit_insn (gen_ashrdi3 (scratch, scratch, GEN_INT (32)));
-	  emit_insn (gen_movdi (gen_rtx (REG, DImode, 65), scratch));
-          emit_insn (gen_hilo_delay (operands[0]));
-	}
-      DONE;
-    }
-  if (GET_CODE (operands[1]) == REG && REGNO (operands[1]) == HILO_REGNUM)
-    {
-      emit_insn (gen_movdi (scratch, gen_rtx_REG (DImode, 65)));
-      emit_insn (gen_ashldi3 (scratch, scratch, GEN_INT (32)));
-      emit_insn (gen_lshrdi3 (scratch, scratch, GEN_INT (32)));
-      emit_insn (gen_movdi (operands[0], gen_rtx_REG (DImode, 64)));
-      emit_insn (gen_ashldi3 (operands[0], operands[0], GEN_INT (32)));
-      emit_insn (gen_iordi3 (operands[0], operands[0], scratch));
-      emit_insn (gen_hilo_delay (operands[1]));
-      DONE;
-    }
-  /* This handles moves between a float register and HI/LO.  */
-  emit_move_insn (scratch, operands[1]);
-  emit_move_insn (operands[0], scratch);
-  DONE;
-}")
-
-;; Handle output reloads in DImode.
-
-;; Reloading HILO_REG in MIPS16 mode requires two scratch registers, so we
-;; use a TImode scratch reg.
-
-(define_expand "reload_outdi"
-  [(set (match_operand:DI 0 "general_operand" "=b")
-	(match_operand:DI 1 "register_operand" "b"))
-   (clobber (match_operand:TI 2 "register_operand" "=&d"))]
-  "TARGET_64BIT"
-  "
-{
-  rtx scratch = gen_rtx_REG (DImode, REGNO (operands[2]));
-
-  if (GET_CODE (operands[0]) == REG && REGNO (operands[0]) == HILO_REGNUM)
-    {
-      emit_insn (gen_ashrdi3 (scratch, operands[1], GEN_INT (32)));
-      emit_insn (gen_movdi (gen_rtx (REG, DImode, 64), scratch));
-      emit_insn (gen_ashldi3 (scratch, operands[1], GEN_INT (32)));
-      emit_insn (gen_ashrdi3 (scratch, scratch, GEN_INT (32)));
-      emit_insn (gen_movdi (gen_rtx (REG, DImode, 65), scratch));
-      emit_insn (gen_hilo_delay (operands[0]));
-      DONE;
-    }
-  if (GET_CODE (operands[1]) == REG && REGNO (operands[1]) == HILO_REGNUM)
-    {
-      if (GET_CODE (operands[0]) == MEM)
-	{
-	  rtx scratch, memword, offword, hi_word, lo_word;
-	  rtx addr = find_replacement (&XEXP (operands[0], 0));
-	  rtx op0 = replace_equiv_address (operands[0], addr);
-
-	  scratch = gen_rtx_REG (SImode, REGNO (operands[2]));
-	  memword = adjust_address (op0, SImode, 0);
-	  offword = adjust_address (op0, SImode, 4);
-
-	  if (BYTES_BIG_ENDIAN)
-	    {
-	      hi_word = memword;
-	      lo_word = offword;
-	    }
-	  else
-	    {
-	      hi_word = offword;
-	      lo_word = memword;
-	    }
-	  emit_move_insn (scratch, gen_rtx_REG (SImode, 64));
-	  emit_move_insn (hi_word, scratch);
-	  emit_move_insn (scratch, gen_rtx_REG (SImode, 65));
-	  emit_move_insn (lo_word, scratch);
-	  emit_insn (gen_hilo_delay (operands[1]));
-	}
-      else if (TARGET_MIPS16 && ! M16_REG_P (REGNO (operands[0])))
-	{
-	  /* Handle the case where operand[0] is not a 'd' register,
-	     and hence we can not directly move from the HILO register
-	     into it.  */
-	  rtx scratch2 = gen_rtx_REG (DImode, REGNO (operands[2]) + 1);
-	  emit_insn (gen_movdi (scratch, gen_rtx (REG, DImode, 65)));
-	  emit_insn (gen_ashldi3 (scratch, scratch, GEN_INT (32)));
-	  emit_insn (gen_lshrdi3 (scratch, scratch, GEN_INT (32)));
-	  emit_insn (gen_movdi (scratch2, gen_rtx (REG, DImode, 64)));
-	  emit_insn (gen_ashldi3 (scratch2, scratch2, GEN_INT (32)));
-	  emit_insn (gen_iordi3 (scratch, scratch, scratch2));
-	  emit_insn (gen_movdi (operands[0], scratch));
-	  emit_insn (gen_hilo_delay (operands[1]));
-	}
-      else
-	{
-	  emit_insn (gen_movdi (scratch, gen_rtx (REG, DImode, 65)));
-	  emit_insn (gen_ashldi3 (scratch, scratch, GEN_INT (32)));
-	  emit_insn (gen_lshrdi3 (scratch, scratch, GEN_INT (32)));
-	  emit_insn (gen_movdi (operands[0], gen_rtx (REG, DImode, 64)));
-	  emit_insn (gen_ashldi3 (operands[0], operands[0], GEN_INT (32)));
-	  emit_insn (gen_iordi3 (operands[0], operands[0], scratch));
-	  emit_insn (gen_hilo_delay (operands[1]));
-	}
-      DONE;
-    }
-  /* This handles moves between a float register and HI/LO.  */
-  emit_move_insn (scratch, operands[1]);
-  emit_move_insn (operands[0], scratch);
-  DONE;
-}")
-
 ;; 32-bit Integer moves
 
 ;; Unlike most other insns, the move insns can't be split with
@@ -5443,25 +5244,25 @@ (define_insn ""
 ;; in FP registers (off by default, use -mdebugh to enable).
 
 (define_insn "movsi_internal"
-  [(set (match_operand:SI 0 "nonimmediate_operand" "=d,d,e,d,m,*f,*f,*f,*d,*m,*d,*z,*x,*d,*x,*d,*B*C*D,*B*C*D,*d,*m")
-	(match_operand:SI 1 "move_operand" "d,U,T,m,dJ,*f,*d*J,*m,*f,*f,*z,*d,J,*x,*d,*a,*d,*m,*B*C*D,*B*C*D"))]
+  [(set (match_operand:SI 0 "nonimmediate_operand" "=d,d,e,d,m,*f,*f,*f,*d,*m,*d,*z,*x,*d,*x,*B*C*D,*B*C*D,*d,*m")
+	(match_operand:SI 1 "move_operand" "d,U,T,m,dJ,*f,*d*J,*m,*f,*f,*z,*d,J,*x,*d,*d,*m,*B*C*D,*B*C*D"))]
   "!TARGET_MIPS16
    && (register_operand (operands[0], SImode)
        || register_operand (operands[1], SImode)
        || (GET_CODE (operands[1]) == CONST_INT && INTVAL (operands[1]) == 0))"
   { return mips_output_move (operands[0], operands[1]); }
-  [(set_attr "type"	"move,const,const,load,store,move,xfer,load,xfer,store,xfer,xfer,hilo,hilo,hilo,hilo,xfer,load,xfer,store")
+  [(set_attr "type"	"move,const,const,load,store,move,xfer,load,xfer,store,xfer,xfer,hilo,hilo,hilo,xfer,load,xfer,store")
    (set_attr "mode"	"SI")
-   (set_attr "length"	"4,*,*,*,*,4,4,*,4,*,4,4,4,4,4,4,4,*,4,*")])
+   (set_attr "length"	"4,*,*,*,*,4,4,*,4,*,4,4,4,4,4,4,*,4,*")])
 
 (define_insn ""
-  [(set (match_operand:SI 0 "nonimmediate_operand" "=d,y,d,d,d,d,d,m,*d,*d")
-	(match_operand:SI 1 "move_operand" "d,d,y,K,N,U,m,d,*x,*a"))]
+  [(set (match_operand:SI 0 "nonimmediate_operand" "=d,y,d,d,d,d,d,m,*d")
+	(match_operand:SI 1 "move_operand" "d,d,y,K,N,U,m,d,*x"))]
   "TARGET_MIPS16
    && (register_operand (operands[0], SImode)
        || register_operand (operands[1], SImode))"
   { return mips_output_move (operands[0], operands[1]); }
-  [(set_attr "type"	"move,move,move,arith,arith,const,load,store,hilo,hilo")
+  [(set_attr "type"	"move,move,move,arith,arith,const,load,store,hilo")
    (set_attr "mode"	"SI")
    (set_attr_alternative "length"
 		[(const_int 4)
@@ -5476,7 +5277,6 @@ (define_insn ""
 		 (const_string "*")
 		 (const_string "*")
 		 (const_string "*")
-		 (const_int 4)
 		 (const_int 4)])])
 
 ;; On the mips16, we can split lw $r,N($r) into an add and a load,
@@ -5563,157 +5363,6 @@ (define_split
 {
   operands[1] = GEN_INT (- INTVAL (operands[1]));
 }")
-
-;; Reload HILO_REGNUM in SI mode.  This needs a scratch register in
-;; order to set the sign bit correctly in the HI register.
-
-(define_expand "reload_outsi"
-  [(set (match_operand:SI 0 "general_operand" "=b")
-	(match_operand:SI 1 "register_operand" "b"))
-   (clobber (match_operand:SI 2 "register_operand" "=&d"))]
-  "TARGET_64BIT || TARGET_MIPS16"
-  "
-{
-  if (TARGET_64BIT
-      && GET_CODE (operands[0]) == REG && REGNO (operands[0]) == HILO_REGNUM)
-    {
-      emit_insn (gen_movsi (gen_rtx_REG (SImode, 65), operands[1]));
-      emit_insn (gen_ashrsi3 (operands[2], operands[1], GEN_INT (31)));
-      emit_insn (gen_movsi (gen_rtx (REG, SImode, 64), operands[2]));
-      emit_insn (gen_hilo_delay (operands[0]));
-      DONE;
-    }
-  /* Use a mult to reload LO on mips16.  ??? This is hideous.  */
-  if (TARGET_MIPS16
-      && GET_CODE (operands[0]) == REG && REGNO (operands[0]) == LO_REGNUM)
-    {
-      emit_insn (gen_movsi (operands[2], GEN_INT (1)));
-      /* This is gen_mulsi3_internal, but we need to fill in the
-	 scratch registers.  */
-      emit_insn (gen_rtx (PARALLEL, VOIDmode,
-			  gen_rtvec (3,
-				     gen_rtx (SET, VOIDmode,
-					      operands[0],
-					      gen_rtx (MULT, SImode,
-						       operands[1],
-						       operands[2])),
-				     gen_rtx (CLOBBER, VOIDmode,
-					      gen_rtx (REG, SImode, 64)),
-				     gen_rtx (CLOBBER, VOIDmode,
-					      gen_rtx (REG, SImode, 66)))));
-      DONE;
-    }
-  /* FIXME: I don't know how to get a value into the HI register.  */
-  if (GET_CODE (operands[0]) == REG
-      && (TARGET_MIPS16 ? M16_REG_P (REGNO (operands[0]))
-	  : GP_REG_P (REGNO (operands[0]))))
-    {
-      emit_move_insn (operands[0], operands[1]);
-      DONE;
-    }
-  /* This handles moves between a float register and HI/LO.  */
-  emit_move_insn (operands[2], operands[1]);
-  emit_move_insn (operands[0], operands[2]);
-  DONE;
-}")
-
-;; Reload a value into HI or LO.  There is no mthi or mtlo on mips16,
-;; so we use a mult.  ??? This is hideous, and we ought to figure out
-;; something better.
-
-;; We use no predicate for operand1, because it may be a PLUS, and there
-;; is no convenient predicate for that.
-
-(define_expand "reload_insi"
-  [(set (match_operand:SI 0 "register_operand" "=b")
-	(match_operand:SI 1 "" "b"))
-   (clobber (match_operand:SI 2 "register_operand" "=&d"))]
-  "TARGET_MIPS16"
-  "
-{
-  if (TARGET_MIPS16
-      && GET_CODE (operands[0]) == REG && REGNO (operands[0]) == LO_REGNUM)
-    {
-      emit_insn (gen_movsi (operands[2], GEN_INT (1)));
-      /* This is gen_mulsi3_internal, but we need to fill in the
-	 scratch registers.  */
-      emit_insn (gen_rtx (PARALLEL, VOIDmode,
-			  gen_rtvec (3,
-				     gen_rtx (SET, VOIDmode,
-					      operands[0],
-					      gen_rtx (MULT, SImode,
-						       operands[1],
-						       operands[2])),
-				     gen_rtx (CLOBBER, VOIDmode,
-					      gen_rtx (REG, SImode, 64)),
-				     gen_rtx (CLOBBER, VOIDmode,
-					      gen_rtx (REG, SImode, 66)))));
-      DONE;
-    }
-
-  /* If this is a plus, then this must be an add of the stack pointer against
-     either a hard register or a pseudo.  */
-  if (TARGET_MIPS16 && GET_CODE (operands[1]) == PLUS)
-    {
-      rtx plus_op;
-
-      if (XEXP (operands[1], 0) == stack_pointer_rtx)
-	plus_op = XEXP (operands[1], 1);
-      else if (XEXP (operands[1], 1) == stack_pointer_rtx)
-	plus_op = XEXP (operands[1], 0);
-      else
-	abort ();
-
-      /* We should have a register now.  */
-      if (GET_CODE (plus_op) != REG)
-	abort ();
-
-      if (REGNO (plus_op) < FIRST_PSEUDO_REGISTER)
-	{
-	  /* We have to have at least one temporary register which is not
-	     overlapping plus_op.  */
-	  if (! rtx_equal_p (plus_op, operands[0]))
-	    {
-	      emit_move_insn (operands[0], stack_pointer_rtx);
-	      emit_insn (gen_addsi3 (operands[0], operands[0], plus_op));
-	    }
-	  else if (! rtx_equal_p (plus_op, operands[2]))
-	    {
-	      emit_move_insn (operands[2], stack_pointer_rtx);
-	      emit_insn (gen_addsi3 (operands[0], plus_op, operands[2]));
-	    }
-	  else
-	    abort ();
-	}
-      else
-	{
-	  /* We need two registers in this case.  */
-	  if (! rtx_equal_p (operands[0], operands[2]))
-	    {
-	      emit_move_insn (operands[0], stack_pointer_rtx);
-	      emit_move_insn (operands[2], plus_op);
-	      emit_insn (gen_addsi3 (operands[0], operands[0], operands[2]));
-	    }
-	  else
-	    abort ();
-	}
-      DONE;
-    }
-
-  /* FIXME: I don't know how to get a value into the HI register.  */
-  emit_move_insn (operands[0], operands[1]);
-  DONE;
-}")
-
-;; This insn is for the unspec delay for HILO.
-
-(define_insn "hilo_delay"
-  [(unspec [(match_operand 0 "register_operand" "=b")] UNSPEC_HILO_DELAY)]
-  ""
-  ""
-  [(set_attr "type" "nop")
-   (set_attr "mode" "none")
-   (set_attr "can_delay" "no")])
 
 ;; This insn handles moving CCmode values.  It's really just a
 ;; slightly simplified copy of movsi_internal2, with additional cases


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]