diff mbox

[12/28] mn10300: Re-write move patterns.

Message ID 1294691517-19580-13-git-send-email-rth@redhat.com
State New
Headers show

Commit Message

Richard Henderson Jan. 10, 2011, 8:31 p.m. UTC
From: Richard Henderson <rth@twiddle.net>

Use the "D" and "A" constraints, and the enabled attribute to
unify all ofthe integer move patterns.  Delete the fake double
word move patterns; let the middle-end generate subregs as required.

Unfortunately, this somehow exposes a register pressure problem
with the udivmod pattern.  This is properly fixed with subsequent
patches that expose the MDR register.

In the meantime it is highly desirable to to preserve bisect-ability
of the patch series, so disable this pattern for AM30.
---
 gcc/config/mn10300/mn10300.md |  930 ++++++++---------------------------------
 1 files changed, 166 insertions(+), 764 deletions(-)

Comments

Jeff Law Jan. 18, 2011, 5:02 p.m. UTC | #1
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

On 01/10/11 13:31, Richard Henderson wrote:
> From: Richard Henderson <rth@twiddle.net>
> 
> Use the "D" and "A" constraints, and the enabled attribute to
> unify all ofthe integer move patterns.  Delete the fake double
> word move patterns; let the middle-end generate subregs as required.
> 
> Unfortunately, this somehow exposes a register pressure problem
> with the udivmod pattern.  This is properly fixed with subsequent
> patches that expose the MDR register.
> 
> In the meantime it is highly desirable to to preserve bisect-ability
> of the patch series, so disable this pattern for AM30.
Ideally we'd like to zap alternative 0 in the movxx patterns (nop move
register to itself).  IIRC such moves can occur in unoptimized compilations.

The mn103 series can't encode a reg->reg copy where the source and
destination registers are the same.  That situation tells the decoder
that the instruction is a multi-byte instruction and that it must look
at subsequent bytes to determine exactly what the instruction does.

IIRC returning an empty string for that case didn't work because the
empty string had some kind of special meaning in final.  (This was 13 or
14 years ago, so please forgive the IIRC's :-)

The net result is I think you have to return something for those
alternatives rather than an empty string.


It also seems to me that for movqi/movhi we want to severely disparage
the address regs on the mn103.  IIRC for the base mn103 we would trigger
reload failures if we didn't expose a0-a3 to the movqi/movhi patterns.
However, while the a0-a3 regs can hold such values, they can't be used
in arithmetic/logicals/etc in QI/HI mode.  So to avoid pessimizing code
we exposed a0-a3 in the QI/HI mode moves, but ignored them for register
class preferencing and severely disparaged them for reloading.

It also looks like you lost the movu am33 variant for movqi/movhi.  I
don't recall anything about that alternative, but I can hazard a guess
that movu is smaller than the more generic mov instruction for certain
constants.

I suspect losing the fmov variant for movqi/movhi is a good thing :-)
Presumably we ensure that the FP registers can't hold HImode/QImode
values elsewhere ;-)

It looks like you lost movu for the base mn103 in the movsi pattern and
for all the parts in the movsf pattern (it may not matter there).

The DI/DF mode stuff looks good.  We might regress a little for certain
specific constants, but it shouldn't be too bad.

Jeff







> ---
>  gcc/config/mn10300/mn10300.md |  930 ++++++++---------------------------------
>  1 files changed, 166 insertions(+), 764 deletions(-)
> 
> diff --git a/gcc/config/mn10300/mn10300.md b/gcc/config/mn10300/mn10300.md
> index 04ec1b1..6e0e1a2 100644
> --- a/gcc/config/mn10300/mn10300.md
> +++ b/gcc/config/mn10300/mn10300.md
> @@ -181,107 +181,42 @@
>    [(set (match_operand:QI 0 "nonimmediate_operand")
>  	(match_operand:QI 1 "general_operand"))]
>    ""
> -  "
>  {
>    /* One of the ops has to be in a register.  */
>    if (!register_operand (operand0, QImode)
>        && !register_operand (operand1, QImode))
> -    operands[1] = copy_to_mode_reg (QImode, operand1);
> -}")
> -
> -(define_insn "*am33_movqi"
> -  [(set (match_operand:QI 0 "nonimmediate_operand"
> -			  ;; 0       1      2      3     4       5
> -			  "=d*x*a*f, d*x*a, d*x*a, m,   *f,      d*x*a")
> -	(match_operand:QI 1 "general_operand"
> -			   "0,       d*xai, m,     d*xa, d*xa*f, *f"))]
> -  "TARGET_AM33
> -   && (register_operand (operands[0], QImode)
> -       || register_operand (operands[1], QImode))"
> -  "*
> -  {
> -    switch (which_alternative)
> -      {
> -      case 0:
> -        return \"nop\";
> -      case 1:
> -        gcc_assert (! CONST_DOUBLE_P (operands[1]));
> -
> -        if (REGNO_REG_CLASS (true_regnum (operands[0])) == EXTENDED_REGS
> -	    && CONST_INT_P (operands[1]))
> -	  {
> -	    HOST_WIDE_INT val = INTVAL (operands[1]);
> -
> -	    if (((val & 0x80) && ! (val & 0xffffff00))
> -	        || ((val & 0x800000) && ! (val & 0xff000000)))
> -	      return \"movu %1,%0\";
> -	  }
> -        return \"mov %1,%0\";
> -      case 2:
> -      case 3:
> -        return \"movbu %1,%0\";
> -      case 4:
> -      case 5:
> -        return \"fmov %1,%0\";
> -      default:
> -        gcc_unreachable ();
> -      }
> -  }"
> -  [(set_attr_alternative "timings"
> -			 [(const_int 11)
> -			  (if_then_else (eq_attr "cpu" "am34")
> -					(const_int 11) (const_int 22))
> -			  (if_then_else (eq_attr "cpu" "am34")
> -					(const_int 13) (const_int 24))
> -			  (if_then_else (eq_attr "cpu" "am34")
> -					(const_int 13) (const_int 24))
> -			  (if_then_else (eq_attr "cpu" "am34")
> -					(const_int 47) (const_int 25))
> -			  (if_then_else (eq_attr "cpu" "am34")
> -					(const_int 47) (const_int 25))
> -			 ])
> -  ]
> -)
> +    operands[1] = force_reg (QImode, operand1);
> +})
>  
> -(define_insn "*mn10300_movqi"
> -  [(set (match_operand:QI 0 "nonimmediate_operand" "=d*a,d,d,!*a,d*a,d,m")
> -	(match_operand:QI 1 "general_operand"       "0,  I,i,i,  da, m,d"))]
> -  "register_operand (operands[0], QImode)
> -   || register_operand (operands[1], QImode)"
> -  "*
> +(define_insn "*movqi_internal"
> +  [(set (match_operand:QI 0 "nonimmediate_operand" "=*r,D*r,D*r,D,m")
> +	(match_operand:QI 1 "general_operand"      "  0,D*r,  i,m,D"))]
> +  "(register_operand (operands[0], QImode)
> +    || register_operand (operands[1], QImode))"
>  {
>    switch (which_alternative)
>      {
>      case 0:
> -      return \"nop\";
> +      return "";
>      case 1:
>      case 2:
> +      return "mov %1,%0";
>      case 3:
>      case 4:
> -      gcc_assert (! CONST_DOUBLE_P (operands[1]));
> -      return \"mov %1,%0\";
> -    case 5:
> -    case 6:
> -      return \"movbu %1,%0\";
> +      return "movbu %1,%0";
>      default:
>        gcc_unreachable ();
>      }
> -}"
> +}
>    [(set_attr_alternative "timings"
> -			 [(const_int 11)
> -			  (const_int 11)
> -			  (if_then_else (eq_attr "cpu" "am34")
> -			  		(const_int 11) (const_int 22))
> -			  (if_then_else (eq_attr "cpu" "am34")
> -			  		(const_int 11) (const_int 22))
> -			  (if_then_else (eq_attr "cpu" "am34")
> -			  		(const_int 11) (const_int 22))
> -			  (if_then_else (eq_attr "cpu" "am34")
> -			  		(const_int 13) (const_int 24))
> -			  (if_then_else (eq_attr "cpu" "am34")
> -			  		(const_int 13) (const_int 24))
> -			 ])
> -  ]
> +	 [(const_int 11)
> +	  (const_int 11)
> +	  (const_int 11)
> +	  (if_then_else (eq_attr "cpu" "am34")
> +			(const_int 13) (const_int 24))
> +	  (if_then_else (eq_attr "cpu" "am34")
> +			(const_int 11) (const_int 22))
> +	 ])]
>  )
>  
>  ;; movhi
> @@ -290,107 +225,48 @@
>    [(set (match_operand:HI 0 "nonimmediate_operand")
>  	(match_operand:HI 1 "general_operand"))]
>    ""
> -  "
>  {
>    /* One of the ops has to be in a register.  */
>    if (!register_operand (operand1, HImode)
>        && !register_operand (operand0, HImode))
> -    operands[1] = copy_to_mode_reg (HImode, operand1);
> -}")
> -
> -(define_insn "*am33_movhi"
> -  [(set (match_operand:HI 0 "nonimmediate_operand"
> -			  ;; 0       1       2      3     4         5
> -			  "=d*x*a*f, d*x*a,  d*x*a, m,    *f,       d*x*a")
> -	(match_operand:HI 1 "general_operand"
> -			  "0,        d*x*ai, m,     d*x*a, d*x*a*f, *f"))]
> -  "TARGET_AM33
> -   && (register_operand (operands[0], HImode)
> -       || register_operand (operands[1], HImode))"
> -  "*
> -{
> -  switch (which_alternative)
> -    {
> -    case 0:
> -      return \"nop\";
> -    case 1:
> -      gcc_assert (! CONST_DOUBLE_P (operands[1]));
> -
> -      if (REGNO_REG_CLASS (true_regnum (operands[0])) == EXTENDED_REGS
> -	  && CONST_INT_P (operands[1]))
> -	{
> -	  HOST_WIDE_INT val = INTVAL (operands[1]);
> -
> -	  if (((val & 0x80) && ! (val & 0xffffff00))
> -	      || ((val & 0x800000) && ! (val & 0xff000000)))
> -	    return \"movu %1,%0\";
> -	}
> -      return \"mov %1,%0\";
> -    case 2:
> -    case 3:
> -      return \"movhu %1,%0\";
> -    case 4:
> -    case 5:
> -      return \"fmov %1,%0\";
> -    default:
> -      gcc_unreachable ();
> -    }
> -}"
> -  [(set_attr_alternative "timings"
> -			 [(const_int 11)
> -			  (if_then_else (eq_attr "cpu" "am34")
> -			  		(const_int 11) (const_int 22))
> -			  (if_then_else (eq_attr "cpu" "am34")
> -			  		(const_int 13) (const_int 24))
> -			  (if_then_else (eq_attr "cpu" "am34")
> -			  		(const_int 13) (const_int 24))
> -			  (if_then_else (eq_attr "cpu" "am34")
> -			  		(const_int 47) (const_int 25))
> -			  (if_then_else (eq_attr "cpu" "am34")
> -			  		(const_int 47) (const_int 25))
> -			 ])
> -  ]
> -)
> +    operands[1] = force_reg (HImode, operand1);
> +})
>  
> -(define_insn "*mn10300_movhi"
> -  [(set (match_operand:HI 0 "nonimmediate_operand" "=d*a,d,d,!*a,d*a,d,m")
> -	(match_operand:HI 1 "general_operand"       "0,  I,i,i,  da, m,d"))]
> -  "register_operand (operands[0], HImode)
> -   || register_operand (operands[1], HImode)"
> -  "*
> +(define_insn "*movhi_internal"
> +  [(set (match_operand:HI 0 "nonimmediate_operand" "=*r,D*r,D*r,D,m")
> +	(match_operand:HI 1 "general_operand"      "  0,  i,D*r,m,D"))]
> +  "(register_operand (operands[0], HImode)
> +    || register_operand (operands[1], HImode))"
>  {
>    switch (which_alternative)
>      {
>      case 0:
> -      return \"nop\";
> +      return "";
>      case 1:
> +      if (TARGET_AM33
> +	  && CONST_INT_P (operands[1])
> +	  && IN_RANGE (INTVAL (operands[1]), 0x80, 0xff))
> +	return "movu %1,%0";
> +      /* FALLTHRU */
>      case 2:
> +      return "mov %1,%0";
>      case 3:
>      case 4:
> -      gcc_assert (! CONST_DOUBLE_P (operands[1]));
> -      return \"mov %1,%0\";
> -    case 5:
> -    case 6:
> -      return \"movhu %1,%0\";
> +      return "movhu %1,%0";
>      default:
>        gcc_unreachable ();
>      }
> -}"
> +}
>    [(set_attr_alternative "timings"
> -			 [(const_int 11)
> -			  (const_int 11)
> -			  (if_then_else (eq_attr "cpu" "am34")
> -			  		(const_int 11) (const_int 22))
> -			  (if_then_else (eq_attr "cpu" "am34")
> -			  		(const_int 11) (const_int 22))
> -			  (if_then_else (eq_attr "cpu" "am34")
> -			  		(const_int 11) (const_int 22))
> -			  (if_then_else (eq_attr "cpu" "am34")
> -			  		(const_int 13) (const_int 24))
> -			  (if_then_else (eq_attr "cpu" "am34")
> -			  		(const_int 13) (const_int 24))
> -			 ])
> -  ]
> +	 [(const_int 11)
> +	  (const_int 11)
> +	  (if_then_else (eq_attr "cpu" "am34")
> +	  		(const_int 11) (const_int 22))
> +	  (if_then_else (eq_attr "cpu" "am34")
> +	  		(const_int 13) (const_int 24))
> +	  (if_then_else (eq_attr "cpu" "am34")
> +	  		(const_int 11) (const_int 22))
> +	 ])]
>  )
>  
>  ;; movsi and helpers
> @@ -450,12 +326,11 @@
>    [(set (match_operand:SI 0 "nonimmediate_operand")
>  	(match_operand:SI 1 "general_operand"))]
>    ""
> -  "
>  {
>    /* One of the ops has to be in a register.  */
>    if (!register_operand (operand1, SImode)
>        && !register_operand (operand0, SImode))
> -    operands[1] = copy_to_mode_reg (SImode, operand1);
> +    operands[1] = force_reg (SImode, operand1);
>    if (flag_pic)
>      {
>        rtx temp;
> @@ -486,594 +361,118 @@
>  				      0, OPTAB_LIB_WIDEN);
>  	}
>      }
> -}")
> +})
>  
>  (define_insn "*movsi_internal"
>    [(set (match_operand:SI 0 "nonimmediate_operand"
> -			  "=dax, dax,  m,   dax, ax,!*y")
> +			  "=r,r,r,m,r, A,*y,*y")
>  	(match_operand:SI 1 "general_operand"
> -			  "0,    Idax, dax, im, !*y, ax"))
> -  ]
> +			  " 0,i,r,r,m,*y, A, i"))]
>    "register_operand (operands[0], SImode)
>     || register_operand (operands[1], SImode)"
> -  "*
> -  {
> -    if (which_alternative == 0)
> -      return \"nop\";
> -
> -    gcc_assert (! CONST_DOUBLE_P (operands[1]));
> -
> -    if (REGNO_REG_CLASS (true_regnum (operands[0])) == EXTENDED_REGS
> -        && CONST_INT_P (operands[1]))
> -      {
> -        HOST_WIDE_INT val = INTVAL (operands[1]);
> -
> -        if (((val & 0x80) && ! (val & 0xffffff00))
> -            || ((val & 0x800000) && ! (val & 0xff000000)))
> -          return \"movu %1, %0\";
> -      }
> -
> -    return \"mov %1, %0\";
> -  }"
> -  [(set_attr_alternative "timings"
> -			 [(const_int 11)
> -			  (if_then_else (eq_attr "cpu" "am34")
> -					(const_int 13) (const_int 24))
> -			  (if_then_else (eq_attr "cpu" "am34")
> -					(const_int 13) (const_int 24))
> -			  (if_then_else (eq_attr "cpu" "am34")
> -					(const_int 13) (const_int 24))
> -			  (if_then_else (eq_attr "cpu" "am34")
> -					(const_int 13) (const_int 24))
> -			  (if_then_else (eq_attr "cpu" "am34")
> -					(const_int 13) (const_int 24))
> -			 ])
> -  ]
> +{
> +  switch (which_alternative)
> +    {
> +    case 0:
> +      return "";
> +    case 1: /* imm-reg*/
> +      if (TARGET_AM33 && CONST_INT_P (operands[1]))
> +	{
> +	  HOST_WIDE_INT val = INTVAL (operands[1]);
> +	  if (IN_RANGE (val, 0x80, 0xff)
> +	      || IN_RANGE (val, 0x800000, 0xffffff))
> +	    return "movu %1,%0";
> +	}
> +      /* FALLTHRU */
> +    case 2:  /* reg-reg */
> +    case 3:  /* reg-mem */
> +    case 4:  /* mem-reg */
> +    case 5:  /* sp-reg */
> +    case 6:  /* reg-sp */
> +    case 7:  /* imm-sp */
> +      return "mov %1,%0";
> +    default:
> +      gcc_unreachable ();
> +    }
> +}
> +  [(set_attr "isa" "*,*,*,*,*,*,*,am33")
> +   (set_attr_alternative "timings"
> +	 [(const_int 11)
> +	  (const_int 22)
> +	  (const_int 11)
> +	  (if_then_else (eq_attr "cpu" "am34")
> +			(const_int 11) (const_int 22))
> +	  (if_then_else (eq_attr "cpu" "am34")
> +			(const_int 13) (const_int 24))
> +	  (if_then_else (eq_attr "cpu" "am34")
> +			(const_int 11) (const_int 22))
> +	  (if_then_else (eq_attr "cpu" "am34")
> +			(const_int 13) (const_int 24))
> +	  (const_int 11)
> +	 ])]
>  )
>  
>  (define_expand "movsf"
>    [(set (match_operand:SF 0 "nonimmediate_operand")
>  	(match_operand:SF 1 "general_operand"))]
> -  ""
> -  "
> +  "TARGET_AM33_2"
>  {
>    /* One of the ops has to be in a register.  */
>    if (!register_operand (operand1, SFmode)
>        && !register_operand (operand0, SFmode))
> -    operands[1] = copy_to_mode_reg (SFmode, operand1);
> -}")
> +    operands[1] = force_reg (SFmode, operand1);
> +})
>  
>  (define_insn "*movsf_internal"
> -  [(set (match_operand:SF 0 "nonimmediate_operand"
> -			  ;; 0    1    2       3     4     5
> -			  "=fdxa, dxa, f,      dxaQ, daxm, dax")
> -	(match_operand:SF 1 "general_operand"
> -			  " 0,    G,   fdxaQF, f,    dax,  daxFm"))
> -  ]
> -  "register_operand (operands[0], SFmode)
> -   || register_operand (operands[1], SFmode)"
> -  "*
> -  {
> -    switch (which_alternative)
> -      {
> -      case 0:
> -        return \"nop\";
> -      /* case 1: below.  */
> -      case 2:
> -      case 3:
> -        return \"fmov %1, %0\";
> -      case 1:
> -      case 4:
> -      case 5:
> -        if (REGNO_REG_CLASS (true_regnum (operands[0])) == EXTENDED_REGS
> -	    && CONST_INT_P (operands[1]))
> -	  {
> -	    HOST_WIDE_INT val = INTVAL (operands[1]);
> -
> -	    if (((val & 0x80) && ! (val & 0xffffff00))
> -	        || ((val & 0x800000) && ! (val & 0xff000000)))
> -	      return \"movu %1, %0\";
> -	  }
> -        return \"mov %1, %0\";
> -      default:
> -        gcc_unreachable ();
> -      }
> -  }"
> -  [(set_attr_alternative "timings"
> -			 [(const_int 11)
> -			  (if_then_else (eq_attr "cpu" "am34")
> -					(const_int 13) (const_int 24))
> -			  (if_then_else (eq_attr "cpu" "am34")
> -					(const_int 47) (const_int 25))
> -			  (if_then_else (eq_attr "cpu" "am34")
> -					(const_int 47) (const_int 25))
> -			  (if_then_else (eq_attr "cpu" "am34")
> -					(const_int 13) (const_int 24))
> -			  (if_then_else (eq_attr "cpu" "am34")
> -					(const_int 13) (const_int 24))
> -			 ])
> -  ]
> -)
> -
> -(define_expand "movdi"
> -  [(set (match_operand:DI 0 "nonimmediate_operand")
> -	(match_operand:DI 1 "general_operand"))]
> -  ""
> -  "
> -{
> -  /* One of the ops has to be in a register.  */
> -  if (!register_operand (operand1, DImode)
> -      && !register_operand (operand0, DImode))
> -    operands[1] = copy_to_mode_reg (DImode, operand1);
> -}")
> -
> -
> -(define_insn "*movdi_internal"                   ;;   0 1  2  3 4   5   6  7 8  9
> -  [(set (match_operand:DI 0 "nonimmediate_operand" "=dx,ax,dx,a,dxm,dxm,a, a,dx,a")
> -	(match_operand:DI 1 "general_operand"        "0,0, I, I,dx, a,  dx,a,im,im"))]
> -  "register_operand (operands[0], DImode)
> -   || register_operand (operands[1], DImode)"
> -  "*
> +  [(set (match_operand:SF 0 "nonimmediate_operand" "=rf,r,f,r,f,r,f,r,m,f,Q")
> +	(match_operand:SF 1 "general_operand"	   "  0,F,F,r,f,f,r,m,r,Q,f"))]
> +  "TARGET_AM33_2
> +   && (register_operand (operands[0], SFmode)
> +       || register_operand (operands[1], SFmode))"
>  {
> -  long val[2];
> -  REAL_VALUE_TYPE rv;
> -
>    switch (which_alternative)
>      {
> -      case 0:
> -      case 1:
> -	return \"nop\";
> -
> -      case 2:
> -	return \"mov 0, %L0\;mov 0, %H0\";
> -
> -      case 3:
> -	if (rtx_equal_p (operands[0], operands[1]))
> -	  return \"sub %L1,%L0\;mov %L0,%H0\";
> -	else
> -	  return \"mov %1,%L0\;mov %L0,%H0\";
> -      case 4:
> -      case 5:
> -      case 6:
> -      case 7:
> -      case 8:
> -      case 9:
> -	if (CONST_INT_P (operands[1]))
> -	  {
> -	    rtx low, high;
> -	    split_double (operands[1], &low, &high);
> -	    val[0] = INTVAL (low);
> -	    val[1] = INTVAL (high);
> -	  }
> -	if (CONST_DOUBLE_P (operands[1]))
> -	  {
> -	    if (GET_MODE (operands[1]) == DFmode)
> -	      {
> -		REAL_VALUE_FROM_CONST_DOUBLE (rv, operands[1]);
> -		REAL_VALUE_TO_TARGET_DOUBLE (rv, val);
> -	      }
> -	    else if (GET_MODE (operands[1]) == VOIDmode
> -		     || GET_MODE (operands[1]) == DImode)
> -	      {
> -		val[0] = CONST_DOUBLE_LOW (operands[1]);
> -		val[1] = CONST_DOUBLE_HIGH (operands[1]);
> -	      }
> -	  }
> -
> -	if (MEM_P (operands[1])
> -	    && reg_overlap_mentioned_p (operands[0], XEXP (operands[1], 0)))
> -	  {
> -	    rtx temp = operands[0];
> -
> -	    while (GET_CODE (temp) == SUBREG)
> -	      temp = SUBREG_REG (temp);
> -
> -	    gcc_assert (REG_P (temp));
> -
> -	    if (reg_overlap_mentioned_p (gen_rtx_REG (SImode, REGNO (temp)),
> -					 XEXP (operands[1], 0)))
> -	      return \"mov %H1,%H0\;mov %L1,%L0\";
> -	    else
> -	      return \"mov %L1,%L0\;mov %H1,%H0\";
> -
> -	  }
> -	else if (MEM_P (operands[1])
> -		 && CONSTANT_ADDRESS_P (XEXP (operands[1], 0))
> -		 && REGNO_REG_CLASS (REGNO (operands[0])) == ADDRESS_REGS)
> -	  {
> -	    rtx xoperands[2];
> -
> -	    xoperands[0] = operands[0];
> -	    xoperands[1] = XEXP (operands[1], 0);
> -
> -	    output_asm_insn (\"mov %1,%L0\;mov (4,%L0),%H0\;mov (%L0),%L0\",
> -			     xoperands);
> -	    return \"\";
> -	  }
> -	else
> -	  {
> -	    if ((CONST_INT_P (operands[1])
> -		 || CONST_DOUBLE_P (operands[1]))
> -		&& val[0] == 0)
> -	      {
> -		if (REGNO_REG_CLASS (REGNO (operands[0])) == DATA_REGS)
> -		  output_asm_insn (\"mov 0, %L0\", operands);
> -		else
> -		  output_asm_insn (\"mov %L1,%L0\", operands);
> -	      }
> -	    else if ((CONST_INT_P (operands[1])
> -		      || CONST_DOUBLE_P (operands[1]))
> -		     && (REGNO_REG_CLASS (true_regnum (operands[0]))
> -			 == EXTENDED_REGS)
> -		     && (((val[0] & 0x80) && ! (val[0] & 0xffffff00))
> -			 || ((val[0] & 0x800000) && ! (val[0] & 0xff000000))))
> -	      output_asm_insn (\"movu %L1,%L0\", operands);
> -	    else
> -	      output_asm_insn (\"mov %L1,%L0\", operands);
> -
> -	    if ((CONST_INT_P (operands[1])
> -		 || CONST_DOUBLE_P (operands[1]))
> -		&& val[1] == 0)
> -	      {
> -		if (REGNO_REG_CLASS (REGNO (operands[0])) == DATA_REGS)
> -		  output_asm_insn (\"mov 0, %H0\", operands);
> -		else
> -		  output_asm_insn (\"mov %H1,%H0\", operands);
> -	      }
> -	    else if ((CONST_INT_P (operands[1])
> -		      || CONST_DOUBLE_P (operands[1]))
> -		     && val[0] == val[1])
> -	      output_asm_insn (\"mov %L0,%H0\", operands);
> -	    else if ((CONST_INT_P (operands[1])
> -		      || CONST_DOUBLE_P (operands[1]))
> -		     && (REGNO_REG_CLASS (true_regnum (operands[0]))
> -			 == EXTENDED_REGS)
> -		     && (((val[1] & 0x80) && ! (val[1] & 0xffffff00))
> -			 || ((val[1] & 0x800000) && ! (val[1] & 0xff000000))))
> -	      output_asm_insn (\"movu %H1,%H0\", operands);
> -	    else
> -	      output_asm_insn (\"mov %H1,%H0\", operands);
> -	    return \"\";
> -	  }
> -    default:
> -      gcc_unreachable ();
> -    }
> -  }"
> -  ;; The timing of "37" is an approximation of the worst case sceanario.
> -  [(set_attr_alternative "timings"
> -			 [(const_int 11)
> -			  (const_int 11)
> -			  (const_int 22)
> -			  (const_int 22)
> -			  (const_int 37)
> -			  (const_int 37)
> -			  (const_int 37)
> -			  (const_int 37)
> -			  (const_int 37)
> -			  (const_int 37)
> -			 ])
> -  ]
> -)
> -
> -(define_expand "movdf"
> -  [(set (match_operand:DF 0 "nonimmediate_operand")
> -	(match_operand:DF 1 "general_operand"))]
> -  ""
> -  "
> -{
> -  /* One of the ops has to be in a register.  */
> -  if (!register_operand (operand1, DFmode)
> -      && !register_operand (operand0, DFmode))
> -    operands[1] = copy_to_mode_reg (DFmode, operand1);
> -}")
> -
> -(define_insn "*am33_2_movdf"
> -  [(set (match_operand:DF 0 "nonimmediate_operand"
> -			  ;; 0   1   2    3    4 5 6   7   8  9 10 11
> -			  "=fdax,dax,fdxa,f,   f,Q,dxm,dxm,a, a,dx,a")
> -	(match_operand:DF 1 "general_operand"
> -			  " 0,   G,  f,   dxaF,Q,f,dx, a,  dx,a,Fm,Fm"))]
> -  "TARGET_AM33_2
> -   && (register_operand (operands[0], DFmode)
> -       || register_operand (operands[1], DFmode))"
> -  "*
> -  {
> -    long val[2];
> -    REAL_VALUE_TYPE rv;
> -
> -    switch (which_alternative)
> -      {
> -      case 0:
> -	return \"nop\";
> -
> -      case 1:
> -	return \"mov 0, %L0\; mov 0, %H0\";
> -
> -      case 2:
> -      case 3:
> -        return \"fmov %L1, %L0\; fmov %H1, %H0\";
> -
> -      case 4:
> -	if (MEM_P (operands[1])
> -	    && CONST_INT_P (XEXP (operands[1], 0))
> -	    && (INTVAL (XEXP (operands[1], 0)) & 7) == 0)
> -	  return \"fmov %D1, %D0\";
> -	else
> -          return \"fmov %L1, %L0\; fmov %H1, %H0\";
> -
> -      case 5:
> -	if (MEM_P (operands[0])
> -	    && CONST_INT_P (XEXP (operands[0], 0))
> -	    && (INTVAL (XEXP (operands[0], 0)) & 7) == 0)
> -	  return \"fmov %D1, %D0\";
> -	else
> -          return \"fmov %L1, %L0\; fmov %H1, %H0\";
> -
> -      case 6:
> -      case 7:
> -      case 8:
> -      case 9:
> -      case 10:
> -      case 11:
> -	if (CONST_INT_P (operands[1]))
> -	  {
> -	    rtx low, high;
> -	    split_double (operands[1], &low, &high);
> -	    val[0] = INTVAL (low);
> -	    val[1] = INTVAL (high);
> -	  }
> -	if (CONST_DOUBLE_P (operands[1]))
> -	  {
> -	    if (GET_MODE (operands[1]) == DFmode)
> -	      {
> -		REAL_VALUE_FROM_CONST_DOUBLE (rv, operands[1]);
> -		REAL_VALUE_TO_TARGET_DOUBLE (rv, val);
> -	      }
> -	    else if (GET_MODE (operands[1]) == VOIDmode
> -		     || GET_MODE (operands[1]) == DImode)
> -	      {
> -		val[0] = CONST_DOUBLE_LOW (operands[1]);
> -		val[1] = CONST_DOUBLE_HIGH (operands[1]);
> -	      }
> -	  }
> -
> -	if (MEM_P (operands[1])
> -	    && reg_overlap_mentioned_p (operands[0], XEXP (operands[1], 0)))
> -	  {
> -	    rtx temp = operands[0];
> -
> -	    while (GET_CODE (temp) == SUBREG)
> -	      temp = SUBREG_REG (temp);
> -
> -	    gcc_assert (REG_P (temp));
> -
> -	    if (reg_overlap_mentioned_p (gen_rtx_REG (SImode, REGNO (temp)),
> -					 XEXP (operands[1], 0)))
> -	      return \"mov %H1, %H0\; mov %L1, %L0\";
> -	    else
> -	      return \"mov %L1, %L0\; mov %H1, %H0\";
> -
> -	  }
> -	else if (MEM_P (operands[1])
> -		 && CONSTANT_ADDRESS_P (XEXP (operands[1], 0))
> -		 && REGNO_REG_CLASS (REGNO (operands[0])) == ADDRESS_REGS)
> -	  {
> -	    rtx xoperands[2];
> -
> -	    xoperands[0] = operands[0];
> -	    xoperands[1] = XEXP (operands[1], 0);
> -
> -	    output_asm_insn (\"mov %1, %L0\; mov (4, %L0), %H0\; mov (%L0), %L0\",
> -			     xoperands);
> -	    return \"\";
> -	  }
> -	else
> -	  {
> -	    if ((CONST_INT_P (operands[1])
> -		 || CONST_DOUBLE_P (operands[1]))
> -		&& val[0] == 0)
> -	      {
> -		if (REGNO_REG_CLASS (REGNO (operands[0])) == DATA_REGS)
> -		  output_asm_insn (\"mov 0, %L0\", operands);
> -		else
> -		  output_asm_insn (\"mov %L1,%L0\", operands);
> -	      }
> -	    else if ((CONST_INT_P (operands[1])
> -		      || CONST_DOUBLE_P (operands[1]))
> -		     && (REGNO_REG_CLASS (true_regnum (operands[0]))
> -			 == EXTENDED_REGS)
> -		     && (((val[0] & 0x80) && ! (val[0] & 0xffffff00))
> -			 || ((val[0] & 0x800000) && ! (val[0] & 0xff000000))))
> -	      output_asm_insn (\"movu %L1, %L0\", operands);
> -	    else
> -	      output_asm_insn (\"mov %L1, %L0\", operands);
> -
> -	    if ((CONST_INT_P (operands[1])
> -		 || CONST_DOUBLE_P (operands[1]))
> -		&& val[1] == 0)
> -	      {
> -		if (REGNO_REG_CLASS (REGNO (operands[0])) == DATA_REGS)
> -		  output_asm_insn (\"mov 0, %H0\", operands);
> -		else
> -		  output_asm_insn (\"mov %H1, %H0\", operands);
> -	      }
> -	    else if ((CONST_INT_P (operands[1])
> -		      || CONST_DOUBLE_P (operands[1]))
> -		     && val[0] == val[1])
> -	      output_asm_insn (\"mov %L0,%H0\", operands);
> -	    else if ((CONST_INT_P (operands[1])
> -		      || CONST_DOUBLE_P (operands[1]))
> -		     && (REGNO_REG_CLASS (true_regnum (operands[0]))
> -			 == EXTENDED_REGS)
> -		     && (((val[1] & 0x80) && ! (val[1] & 0xffffff00))
> -			 || ((val[1] & 0x800000) && ! (val[1] & 0xff000000))))
> -	      output_asm_insn (\"movu %H1, %H0\", operands);
> -	    else
> -	      output_asm_insn (\"mov %H1, %H0\", operands);
> -	    return \"\";
> -	  }
> +    case 0:
> +      return "";
> +    case 1:
> +    case 3:
> +    case 7:
> +    case 8:
> +      return "mov %1,%0";
> +    case 2:
> +    case 4:
> +    case 5:
> +    case 6:
> +    case 9:
> +    case 10:
> +      return "fmov %1,%0";
>      default:
>        gcc_unreachable ();
>      }
> -  }"
> -  ;; The timing of "37" is an approximation of the worst case sceanario.
> +}
>    [(set_attr_alternative "timings"
> -			 [(const_int 11)
> -			  (const_int 22)
> -			  (const_int 22)
> -			  (const_int 22)
> -			  (const_int 22)
> -			  (const_int 37)
> -			  (const_int 37)
> -			  (const_int 37)
> -			  (const_int 37)
> -			  (const_int 37)
> -			  (const_int 37)
> -			  (const_int 37)
> -			 ])
> -  ]
> +		 [(const_int 11)
> +		  (const_int 22)
> +		  (if_then_else (eq_attr "cpu" "am34")
> +				(const_int 47) (const_int 25))
> +		  (const_int 11)
> +		  (if_then_else (eq_attr "cpu" "am34")
> +				(const_int 13) (const_int 14))
> +		  (if_then_else (eq_attr "cpu" "am34")
> +				(const_int 13) (const_int 12))
> +		  (if_then_else (eq_attr "cpu" "am34")
> +				(const_int 13) (const_int 14))
> +		  (if_then_else (eq_attr "cpu" "am34")
> +				(const_int 13) (const_int 24))
> +		  (if_then_else (eq_attr "cpu" "am34")
> +				(const_int 13) (const_int 24))
> +		  (if_then_else (eq_attr "cpu" "am34")
> +				(const_int 13) (const_int 24))
> +		  (if_then_else (eq_attr "cpu" "am34")
> +				(const_int 13) (const_int 24))
> +		 ])]
>  )
>  
> -(define_insn "*mn10300_movdf"
> -  [(set (match_operand:DF 0 "nonimmediate_operand"
> -			  ;;0    1    2    3    4   5  6   7
> -			  "=dxa, dax, dxm, dxm, a,  a, dx, a")
> -	(match_operand:DF 1 "general_operand"
> -			  " 0,   G,   dx,  a,   dx, a, Fm, Fm"))]
> -  "register_operand (operands[0], DFmode)
> -   || register_operand (operands[1], DFmode)"
> -  "*
> -  {
> -    long val[2];
> -    REAL_VALUE_TYPE rv;
> -
> -    switch (which_alternative)
> -      {
> -      case 0:
> -	return \"nop\";
> -
> -      case 1:
> -	return \"mov 0, %L0\; mov 0, %H0\";
> -
> -      case 2:
> -      case 3:
> -      case 4:
> -      case 5:
> -      case 6:
> -      case 7:
> -	if (CONST_INT_P (operands[1]))
> -	  {
> -	    rtx low, high;
> -	    split_double (operands[1], &low, &high);
> -	    val[0] = INTVAL (low);
> -	    val[1] = INTVAL (high);
> -	  }
> -        if (CONST_DOUBLE_P (operands[1]))
> -	  {
> -	    if (GET_MODE (operands[1]) == DFmode)
> -	      {
> -		REAL_VALUE_FROM_CONST_DOUBLE (rv, operands[1]);
> -		REAL_VALUE_TO_TARGET_DOUBLE (rv, val);
> -	      }
> -	    else if (GET_MODE (operands[1]) == VOIDmode
> -		     || GET_MODE (operands[1]) == DImode)
> -	      {
> -		val[0] = CONST_DOUBLE_LOW (operands[1]);
> -		val[1] = CONST_DOUBLE_HIGH (operands[1]);
> -	      }
> -	  }
> -
> -	if (MEM_P (operands[1])
> -	    && reg_overlap_mentioned_p (operands[0], XEXP (operands[1], 0)))
> -	  {
> -	    rtx temp = operands[0];
> -
> -	    while (GET_CODE (temp) == SUBREG)
> -	      temp = SUBREG_REG (temp);
> -
> -	    gcc_assert (REG_P (temp));
> -
> -	    if (reg_overlap_mentioned_p (gen_rtx_REG (SImode, REGNO (temp)),
> -					 XEXP (operands[1], 0)))
> -	      return \"mov %H1, %H0\; mov %L1, %L0\";
> -	    else
> -	      return \"mov %L1, %L0\; mov %H1, %H0\";
> -	  }
> -	else if (MEM_P (operands[1])
> -		 && CONSTANT_ADDRESS_P (XEXP (operands[1], 0))
> -		 && REGNO_REG_CLASS (REGNO (operands[0])) == ADDRESS_REGS)
> -	  {
> -	    rtx xoperands[2];
> -
> -	    xoperands[0] = operands[0];
> -	    xoperands[1] = XEXP (operands[1], 0);
> -
> -	    output_asm_insn (\"mov %1, %L0\; mov (4, %L0), %H0\; mov (%L0), %L0\",
> -			     xoperands);
> -	    return \"\";
> -	  }
> -	else
> -	  {
> -	    if ((CONST_INT_P (operands[1])
> -		 || CONST_DOUBLE_P (operands[1]))
> -		&& val[0] == 0)
> -	      {
> -		if (REGNO_REG_CLASS (REGNO (operands[0])) == DATA_REGS)
> -		  output_asm_insn (\"mov 0, %L0\", operands);
> -		else
> -		  output_asm_insn (\"mov %L1, %L0\", operands);
> -	      }
> -	    else if ((CONST_INT_P (operands[1])
> -		      || CONST_DOUBLE_P (operands[1]))
> -		     && (REGNO_REG_CLASS (true_regnum (operands[0]))
> -			 == EXTENDED_REGS)
> -		     && (((val[0] & 0x80) && ! (val[0] & 0xffffff00))
> -			 || ((val[0] & 0x800000) && ! (val[0] & 0xff000000))))
> -	      output_asm_insn (\"movu %L1, %L0\", operands);
> -	    else
> -	      output_asm_insn (\"mov %L1, %L0\", operands);
> -
> -	    if ((CONST_INT_P (operands[1])
> -		 || CONST_DOUBLE_P (operands[1]))
> -		&& val[1] == 0)
> -	      {
> -		if (REGNO_REG_CLASS (REGNO (operands[0])) == DATA_REGS)
> -		  output_asm_insn (\"mov 0, %H0\", operands);
> -		else
> -		  output_asm_insn (\"mov %H1, %H0\", operands);
> -	      }
> -	    else if ((CONST_INT_P (operands[1])
> -		      || CONST_DOUBLE_P (operands[1]))
> -		     && val[0] == val[1])
> -	      output_asm_insn (\"mov %L0, %H0\", operands);
> -	    else if ((CONST_INT_P (operands[1])
> -		      || CONST_DOUBLE_P (operands[1]))
> -		     && (REGNO_REG_CLASS (true_regnum (operands[0]))
> -			 == EXTENDED_REGS)
> -		     && (((val[1] & 0x80) && ! (val[1] & 0xffffff00))
> -			 || ((val[1] & 0x800000) && ! (val[1] & 0xff000000))))
> -	      output_asm_insn (\"movu %H1, %H0\", operands);
> -	    else
> -	      output_asm_insn (\"mov %H1, %H0\", operands);
> -	    return \"\";
> -	  }
> -    default:
> -      gcc_unreachable ();
> -    }
> -  }"
> -  ;; Timings of "37" is approximation of the worst case sceanario.
> -  [(set_attr_alternative "timings"
> -			 [(const_int 11)
> -			  (const_int 22)
> -			  (const_int 37)
> -			  (const_int 37)
> -			  (const_int 37)
> -			  (const_int 37)
> -			  (const_int 37)
> -			  (const_int 37)
> -			 ])
> -  ]
> -)
>  
>  ;; ----------------------------------------------------------------------
>  ;; ADD INSTRUCTIONS
> @@ -1363,42 +762,23 @@
>    	      		 	       (const_int 24) (const_int 23)))]
>  )
>  
> -(define_expand "udivmodsi4"
> -  [(parallel [(set (match_operand:SI          0 "register_operand")
> -		   (udiv:SI (match_operand:SI 1 "general_operand")
> -			    (match_operand:SI 2 "general_operand")))
> -	      (set (match_operand:SI          3 "register_operand")
> -		   (umod:SI (match_dup 1) (match_dup 2)))
> -	      (clobber (reg:CC CC_REG))
> -	     ])
> -  ]
> -  ""
> -  "{
> -    if (!register_operand (operands[1], SImode))
> -      operands[1] = copy_to_mode_reg (SImode, operands[1]);
> -    if (!register_operand (operands[2], SImode))
> -      operands[2] = copy_to_mode_reg (SImode, operands[2]);
> -   }"
> -)
> -
> -(define_insn "*udivmodsi4"
> -  [(set (match_operand:SI          0 "register_operand" "=dx")
> +;; ??? This pattern causes too-high register pressure for MN103.
> +;; ??? To be fixed by exposing the MDR register properly.
> +(define_insn "udivmodsi4"
> +  [(set (match_operand:SI          0 "register_operand" "=D")
>  	(udiv:SI (match_operand:SI 1 "register_operand" "0")
> -		 (match_operand:SI 2 "register_operand" "dx")))
> +		 (match_operand:SI 2 "register_operand" "D")))
>     (set (match_operand:SI          3 "register_operand" "=&d")
>  	(umod:SI (match_dup 1) (match_dup 2)))
> -   (clobber (reg:CC CC_REG))
> -  ]
> -  ""
> -  "*
> +   (clobber (reg:CC CC_REG))]
> +  "TARGET_AM33"
>  {
> -  output_asm_insn (\"sub %3,%3\;mov %3,mdr\", operands);
> -
> +  output_asm_insn ("clr %3\;ext %3", operands);
>    if (find_reg_note (insn, REG_UNUSED, operands[3]))
> -    return \"divu %2,%0\";
> +    return "divu %2,%0";
>    else
> -    return \"divu %2,%0\;mov mdr,%3\";
> -}"
> +    return "divu %2,%0\;mov mdr,%3";
> +}
>    ;; Timings:  AM33   AM34
>    ;;  SUB       1/1    1/1
>    ;;  MOV       1/1    1/1
> @@ -1410,6 +790,28 @@
>    	      		 	       (const_int 4546) (const_int 4142)))]
>  )
>  
> +;; ??? In the meantime MN103 can use these two patterns,
> +;; which reduce the register pressure by one.
> +(define_insn "udivsi3"
> +  [(set (match_operand:SI          0 "register_operand" "=&d")
> +	(udiv:SI (match_operand:SI 1 "register_operand" "d")
> +		 (match_operand:SI 2 "register_operand" "d")))
> +   (clobber (reg:CC CC_REG))]
> +  "!TARGET_AM33"
> +  "clr %0\;ext %0\;mov %1,%0\;divu %2,%0"
> +  [(set_attr "timings" "4142")]
> +)
> +
> +(define_insn "umodsi3"
> +  [(set (match_operand:SI          0 "register_operand" "=&d")
> +	(umod:SI (match_operand:SI 1 "register_operand" "d")
> +		 (match_operand:SI 2 "register_operand" "d")))
> +   (clobber (reg:CC CC_REG))]
> +  "!TARGET_AM33"
> +  "clr %0\;ext %0\;mov %1,%0\;divu %2,%0\;mov mdr,%0"
> +  [(set_attr "timings" "4142")]
> +)
> +
>  (define_insn "divmodsi4"
>    [(set (match_operand:SI          0 "register_operand" "=dx")
>  	(div:SI (match_operand:SI  1 "register_operand"  "0")

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.11 (GNU/Linux)
Comment: Using GnuPG with Fedora - http://enigmail.mozdev.org/

iQEcBAEBAgAGBQJNNce0AAoJEBRtltQi2kC7xYMH/2Ak9sB1KWEPkb7r2XSC5Gvu
vZ/TjCQ+glV53LBJNtDzBo4D2QGrY576ex5aYRjmwsmwKItnjAezIIJk2VHRxXVv
7lsTpG8qT2iNbj8NQW8g30Vh6SGok7zd3vNZ4t7YztHV89LDSOmaRwtGktiTDhPu
F9k+CBqqFeZukAGDTYGHLFw1XHqsJJ57X9WzCOiS14zRAFiIeWCnqbZgDk/VRRuL
XJn0EPCCGDiBfh2L/2BmVGYfZ3Cmfzg5WvDij63UPXaVTocRMORsR231UA3eoo+P
fJ2s293SncpGCAdieJZZs1Kb/qu0Gj35VS9Xo+mKvOIf6DS1ybCqFFHkj/4AIjc=
=S+LB
-----END PGP SIGNATURE-----
Richard Henderson Jan. 18, 2011, 6:13 p.m. UTC | #2
On 01/18/2011 09:02 AM, Jeff Law wrote:
> IIRC returning an empty string for that case didn't work because the
> empty string had some kind of special meaning in final.  (This was 13 or
> 14 years ago, so please forgive the IIRC's :-)
> 
> The net result is I think you have to return something for those
> alternatives rather than an empty string.

Not since I've been working on GCC.  We do this a lot -- emit stuff by
hand then return "" to tell final that nothing else need be output.  If
you insist, we can continue to return nop here, but I don't think it's
necessary.

> It also seems to me that for movqi/movhi we want to severely disparage
> the address regs on the mn103.  IIRC for the base mn103 we would trigger
> reload failures if we didn't expose a0-a3 to the movqi/movhi patterns.
> However, while the a0-a3 regs can hold such values, they can't be used
> in arithmetic/logicals/etc in QI/HI mode.  So to avoid pessimizing code
> we exposed a0-a3 in the QI/HI mode moves, but ignored them for register
> class preferencing and severely disparaged them for reloading.

I have ignored them for register class preferencing:

> +(define_insn "*movqi_internal"
> +  [(set (match_operand:QI 0 "nonimmediate_operand" "=*r,D*r,D*r,D,m")
> +	   (match_operand:QI 1 "general_operand"      "  0,D*r,  i,m,D"))]

Note that for mn103, D*r resolves to a DATA_REGS preference, with
GENERAL_REGS used for the legal register set.

As for pessimising, I'm not sure what else really needs to be done, given
that the only other operation for which Q/HImode is valid is extension.

> It also looks like you lost the movu am33 variant for movqi/movhi.  I
> don't recall anything about that alternative, but I can hazard a guess
> that movu is smaller than the more generic mov instruction for certain
> constants.

It is still present in movhi:

>      case 1:
> +      if (TARGET_AM33
> +	  && CONST_INT_P (operands[1])
> +	  && IN_RANGE (INTVAL (operands[1]), 0x80, 0xff))
> +	return "movu %1,%0";

What I dropped were the useless extra tests for movu.  There's no point
in loading 0x80 via movu when -128 via mov is 1 byte smaller for QImode.

> It looks like you lost movu for the base mn103 in the movsi pattern and
> for all the parts in the movsf pattern (it may not matter there).

Err, base mn103 doesn't have movu at all.

As for movsf, movu would only be usable for a small set of subnormal
operands.  Combine that with wanting to load that subnormal into an
integer register, as opposed to a floating-point register, and I think
that is rare enough not to be useful.

It does look as if I'm missing an EXTENDED_REGISTER check there in some
of the tests; the sizes of mov imm vary a bit between data, addr, and
extended register sets...


r~
Jeff Law Jan. 19, 2011, 3:58 p.m. UTC | #3
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

On 01/18/11 11:13, Richard Henderson wrote:
> On 01/18/2011 09:02 AM, Jeff Law wrote:
>> IIRC returning an empty string for that case didn't work because the
>> empty string had some kind of special meaning in final.  (This was 13 or
>> 14 years ago, so please forgive the IIRC's :-)
>>
>> The net result is I think you have to return something for those
>> alternatives rather than an empty string.
> 
> Not since I've been working on GCC.  We do this a lot -- emit stuff by
> hand then return "" to tell final that nothing else need be output.  If
> you insist, we can continue to return nop here, but I don't think it's
> necessary.
I'll go with your call on this one.  There was certainly some reason I
didn't do this before, but I simply can't remember what it was...    I
thought I'd documented this nonsense thoroughly in a long block comment,
but I can't seem to find it anywhere.


> 
> As for pessimising, I'm not sure what else really needs to be done, given
> that the only other operation for which Q/HImode is valid is extension.
I think what may have tended to happen is with the '!' for A regs was
that we could use an address register for a source/destination in a
movqi/movhi since it didn't need reloads.  In some cases that's
sufficient to keep reload happy.

I'm willing to hope that Bernd's work from 1998 & IRA would minimize the
chances of running into those problems again.  On top of that, I suspect
nobody is still using the base mn103 anymore.

There's also the slim possibility that this was a mn102 problem and I
carried the changes into the mn103 port.



> 
>> It also looks like you lost the movu am33 variant for movqi/movhi.  I
>> don't recall anything about that alternative, but I can hazard a guess
>> that movu is smaller than the more generic mov instruction for certain
>> constants.
> 
> It is still present in movhi:
> 
>>      case 1:
>> +      if (TARGET_AM33
>> +	  && CONST_INT_P (operands[1])
>> +	  && IN_RANGE (INTVAL (operands[1]), 0x80, 0xff))
>> +	return "movu %1,%0";
> 
> What I dropped were the useless extra tests for movu.  There's no point
> in loading 0x80 via movu when -128 via mov is 1 byte smaller for QImode.
Ok.  As I mentioned, I don't have any recollection of movu, so if your
sequence is smaller, that's all good :-)

Jeff
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.11 (GNU/Linux)
Comment: Using GnuPG with Fedora - http://enigmail.mozdev.org/

iQEcBAEBAgAGBQJNNwo5AAoJEBRtltQi2kC78i8H/RX3QLkdkriMLgoqxrXOcSL5
K9uGc/icLZfhGiDyNXuQ5gQV8PaczETw5WKu9IJImh7Kh25Lm8Ekn2hcmxn04uoJ
nB5D+sl7ro+80Dev/tsCU/qawvz7YY9WCbEueOlMo9Yo5MHiCJ0hAHv+cBO8w2xM
dEyMy6fBZ9BE7NuUwRnu24BbR90VnNrNUbSfR1s5LOWuj1+5amU0TkPQdJ18wOjp
C+djO8OPNjgrc3qIklBUhRKdaYnMuS+KkRd2SszqRBft5o7Ue7XPfzUhdfnjzmUU
Blyo1qzDviuGXNNgVpJVU5rFCf/LtmJCj8gnb34AW008UEQbwIuJrK/clO9QPGk=
=Wtn5
-----END PGP SIGNATURE-----
Hans-Peter Nilsson Jan. 19, 2011, 6:45 p.m. UTC | #4
On Wed, 19 Jan 2011, Jeff Law wrote:
> On 01/18/11 11:13, Richard Henderson wrote:
> > On 01/18/2011 09:02 AM, Jeff Law wrote:
> >> IIRC returning an empty string for that case didn't work because the
> >> empty string had some kind of special meaning in final.  (This was 13 or
> >> 14 years ago, so please forgive the IIRC's :-)
> >>
> >> The net result is I think you have to return something for those
> >> alternatives rather than an empty string.
> >
> > Not since I've been working on GCC.  We do this a lot -- emit stuff by
> > hand then return "" to tell final that nothing else need be output.  If
> > you insist, we can continue to return nop here, but I don't think it's
> > necessary.
> I'll go with your call on this one.  There was certainly some reason I
> didn't do this before, but I simply can't remember what it was...    I
> thought I'd documented this nonsense thoroughly in a long block comment,
> but I can't seem to find it anywhere.

Regarding the special-empty-string-meaning, maybe you were
thinking of branch patterns that should return NULL when, for
CC0 targets, e.g. cc_status indicates an invalid removal of a
compare insn, such that final_scan_insn has to put it back:

	/* If the C code returns 0, it means that it is a jump insn
	   which follows a deleted test insn, and that test insn
	   needs to be reinserted.  */

(Whoops, not inside #ifdef HAVE_cc0; dunno when else it can happen.)

brgds, H-P
diff mbox

Patch

diff --git a/gcc/config/mn10300/mn10300.md b/gcc/config/mn10300/mn10300.md
index 04ec1b1..6e0e1a2 100644
--- a/gcc/config/mn10300/mn10300.md
+++ b/gcc/config/mn10300/mn10300.md
@@ -181,107 +181,42 @@ 
   [(set (match_operand:QI 0 "nonimmediate_operand")
 	(match_operand:QI 1 "general_operand"))]
   ""
-  "
 {
   /* One of the ops has to be in a register.  */
   if (!register_operand (operand0, QImode)
       && !register_operand (operand1, QImode))
-    operands[1] = copy_to_mode_reg (QImode, operand1);
-}")
-
-(define_insn "*am33_movqi"
-  [(set (match_operand:QI 0 "nonimmediate_operand"
-			  ;; 0       1      2      3     4       5
-			  "=d*x*a*f, d*x*a, d*x*a, m,   *f,      d*x*a")
-	(match_operand:QI 1 "general_operand"
-			   "0,       d*xai, m,     d*xa, d*xa*f, *f"))]
-  "TARGET_AM33
-   && (register_operand (operands[0], QImode)
-       || register_operand (operands[1], QImode))"
-  "*
-  {
-    switch (which_alternative)
-      {
-      case 0:
-        return \"nop\";
-      case 1:
-        gcc_assert (! CONST_DOUBLE_P (operands[1]));
-
-        if (REGNO_REG_CLASS (true_regnum (operands[0])) == EXTENDED_REGS
-	    && CONST_INT_P (operands[1]))
-	  {
-	    HOST_WIDE_INT val = INTVAL (operands[1]);
-
-	    if (((val & 0x80) && ! (val & 0xffffff00))
-	        || ((val & 0x800000) && ! (val & 0xff000000)))
-	      return \"movu %1,%0\";
-	  }
-        return \"mov %1,%0\";
-      case 2:
-      case 3:
-        return \"movbu %1,%0\";
-      case 4:
-      case 5:
-        return \"fmov %1,%0\";
-      default:
-        gcc_unreachable ();
-      }
-  }"
-  [(set_attr_alternative "timings"
-			 [(const_int 11)
-			  (if_then_else (eq_attr "cpu" "am34")
-					(const_int 11) (const_int 22))
-			  (if_then_else (eq_attr "cpu" "am34")
-					(const_int 13) (const_int 24))
-			  (if_then_else (eq_attr "cpu" "am34")
-					(const_int 13) (const_int 24))
-			  (if_then_else (eq_attr "cpu" "am34")
-					(const_int 47) (const_int 25))
-			  (if_then_else (eq_attr "cpu" "am34")
-					(const_int 47) (const_int 25))
-			 ])
-  ]
-)
+    operands[1] = force_reg (QImode, operand1);
+})
 
-(define_insn "*mn10300_movqi"
-  [(set (match_operand:QI 0 "nonimmediate_operand" "=d*a,d,d,!*a,d*a,d,m")
-	(match_operand:QI 1 "general_operand"       "0,  I,i,i,  da, m,d"))]
-  "register_operand (operands[0], QImode)
-   || register_operand (operands[1], QImode)"
-  "*
+(define_insn "*movqi_internal"
+  [(set (match_operand:QI 0 "nonimmediate_operand" "=*r,D*r,D*r,D,m")
+	(match_operand:QI 1 "general_operand"      "  0,D*r,  i,m,D"))]
+  "(register_operand (operands[0], QImode)
+    || register_operand (operands[1], QImode))"
 {
   switch (which_alternative)
     {
     case 0:
-      return \"nop\";
+      return "";
     case 1:
     case 2:
+      return "mov %1,%0";
     case 3:
     case 4:
-      gcc_assert (! CONST_DOUBLE_P (operands[1]));
-      return \"mov %1,%0\";
-    case 5:
-    case 6:
-      return \"movbu %1,%0\";
+      return "movbu %1,%0";
     default:
       gcc_unreachable ();
     }
-}"
+}
   [(set_attr_alternative "timings"
-			 [(const_int 11)
-			  (const_int 11)
-			  (if_then_else (eq_attr "cpu" "am34")
-			  		(const_int 11) (const_int 22))
-			  (if_then_else (eq_attr "cpu" "am34")
-			  		(const_int 11) (const_int 22))
-			  (if_then_else (eq_attr "cpu" "am34")
-			  		(const_int 11) (const_int 22))
-			  (if_then_else (eq_attr "cpu" "am34")
-			  		(const_int 13) (const_int 24))
-			  (if_then_else (eq_attr "cpu" "am34")
-			  		(const_int 13) (const_int 24))
-			 ])
-  ]
+	 [(const_int 11)
+	  (const_int 11)
+	  (const_int 11)
+	  (if_then_else (eq_attr "cpu" "am34")
+			(const_int 13) (const_int 24))
+	  (if_then_else (eq_attr "cpu" "am34")
+			(const_int 11) (const_int 22))
+	 ])]
 )
 
 ;; movhi
@@ -290,107 +225,48 @@ 
   [(set (match_operand:HI 0 "nonimmediate_operand")
 	(match_operand:HI 1 "general_operand"))]
   ""
-  "
 {
   /* One of the ops has to be in a register.  */
   if (!register_operand (operand1, HImode)
       && !register_operand (operand0, HImode))
-    operands[1] = copy_to_mode_reg (HImode, operand1);
-}")
-
-(define_insn "*am33_movhi"
-  [(set (match_operand:HI 0 "nonimmediate_operand"
-			  ;; 0       1       2      3     4         5
-			  "=d*x*a*f, d*x*a,  d*x*a, m,    *f,       d*x*a")
-	(match_operand:HI 1 "general_operand"
-			  "0,        d*x*ai, m,     d*x*a, d*x*a*f, *f"))]
-  "TARGET_AM33
-   && (register_operand (operands[0], HImode)
-       || register_operand (operands[1], HImode))"
-  "*
-{
-  switch (which_alternative)
-    {
-    case 0:
-      return \"nop\";
-    case 1:
-      gcc_assert (! CONST_DOUBLE_P (operands[1]));
-
-      if (REGNO_REG_CLASS (true_regnum (operands[0])) == EXTENDED_REGS
-	  && CONST_INT_P (operands[1]))
-	{
-	  HOST_WIDE_INT val = INTVAL (operands[1]);
-
-	  if (((val & 0x80) && ! (val & 0xffffff00))
-	      || ((val & 0x800000) && ! (val & 0xff000000)))
-	    return \"movu %1,%0\";
-	}
-      return \"mov %1,%0\";
-    case 2:
-    case 3:
-      return \"movhu %1,%0\";
-    case 4:
-    case 5:
-      return \"fmov %1,%0\";
-    default:
-      gcc_unreachable ();
-    }
-}"
-  [(set_attr_alternative "timings"
-			 [(const_int 11)
-			  (if_then_else (eq_attr "cpu" "am34")
-			  		(const_int 11) (const_int 22))
-			  (if_then_else (eq_attr "cpu" "am34")
-			  		(const_int 13) (const_int 24))
-			  (if_then_else (eq_attr "cpu" "am34")
-			  		(const_int 13) (const_int 24))
-			  (if_then_else (eq_attr "cpu" "am34")
-			  		(const_int 47) (const_int 25))
-			  (if_then_else (eq_attr "cpu" "am34")
-			  		(const_int 47) (const_int 25))
-			 ])
-  ]
-)
+    operands[1] = force_reg (HImode, operand1);
+})
 
-(define_insn "*mn10300_movhi"
-  [(set (match_operand:HI 0 "nonimmediate_operand" "=d*a,d,d,!*a,d*a,d,m")
-	(match_operand:HI 1 "general_operand"       "0,  I,i,i,  da, m,d"))]
-  "register_operand (operands[0], HImode)
-   || register_operand (operands[1], HImode)"
-  "*
+(define_insn "*movhi_internal"
+  [(set (match_operand:HI 0 "nonimmediate_operand" "=*r,D*r,D*r,D,m")
+	(match_operand:HI 1 "general_operand"      "  0,  i,D*r,m,D"))]
+  "(register_operand (operands[0], HImode)
+    || register_operand (operands[1], HImode))"
 {
   switch (which_alternative)
     {
     case 0:
-      return \"nop\";
+      return "";
     case 1:
+      if (TARGET_AM33
+	  && CONST_INT_P (operands[1])
+	  && IN_RANGE (INTVAL (operands[1]), 0x80, 0xff))
+	return "movu %1,%0";
+      /* FALLTHRU */
     case 2:
+      return "mov %1,%0";
     case 3:
     case 4:
-      gcc_assert (! CONST_DOUBLE_P (operands[1]));
-      return \"mov %1,%0\";
-    case 5:
-    case 6:
-      return \"movhu %1,%0\";
+      return "movhu %1,%0";
     default:
       gcc_unreachable ();
     }
-}"
+}
   [(set_attr_alternative "timings"
-			 [(const_int 11)
-			  (const_int 11)
-			  (if_then_else (eq_attr "cpu" "am34")
-			  		(const_int 11) (const_int 22))
-			  (if_then_else (eq_attr "cpu" "am34")
-			  		(const_int 11) (const_int 22))
-			  (if_then_else (eq_attr "cpu" "am34")
-			  		(const_int 11) (const_int 22))
-			  (if_then_else (eq_attr "cpu" "am34")
-			  		(const_int 13) (const_int 24))
-			  (if_then_else (eq_attr "cpu" "am34")
-			  		(const_int 13) (const_int 24))
-			 ])
-  ]
+	 [(const_int 11)
+	  (const_int 11)
+	  (if_then_else (eq_attr "cpu" "am34")
+	  		(const_int 11) (const_int 22))
+	  (if_then_else (eq_attr "cpu" "am34")
+	  		(const_int 13) (const_int 24))
+	  (if_then_else (eq_attr "cpu" "am34")
+	  		(const_int 11) (const_int 22))
+	 ])]
 )
 
 ;; movsi and helpers
@@ -450,12 +326,11 @@ 
   [(set (match_operand:SI 0 "nonimmediate_operand")
 	(match_operand:SI 1 "general_operand"))]
   ""
-  "
 {
   /* One of the ops has to be in a register.  */
   if (!register_operand (operand1, SImode)
       && !register_operand (operand0, SImode))
-    operands[1] = copy_to_mode_reg (SImode, operand1);
+    operands[1] = force_reg (SImode, operand1);
   if (flag_pic)
     {
       rtx temp;
@@ -486,594 +361,118 @@ 
 				      0, OPTAB_LIB_WIDEN);
 	}
     }
-}")
+})
 
 (define_insn "*movsi_internal"
   [(set (match_operand:SI 0 "nonimmediate_operand"
-			  "=dax, dax,  m,   dax, ax,!*y")
+			  "=r,r,r,m,r, A,*y,*y")
 	(match_operand:SI 1 "general_operand"
-			  "0,    Idax, dax, im, !*y, ax"))
-  ]
+			  " 0,i,r,r,m,*y, A, i"))]
   "register_operand (operands[0], SImode)
    || register_operand (operands[1], SImode)"
-  "*
-  {
-    if (which_alternative == 0)
-      return \"nop\";
-
-    gcc_assert (! CONST_DOUBLE_P (operands[1]));
-
-    if (REGNO_REG_CLASS (true_regnum (operands[0])) == EXTENDED_REGS
-        && CONST_INT_P (operands[1]))
-      {
-        HOST_WIDE_INT val = INTVAL (operands[1]);
-
-        if (((val & 0x80) && ! (val & 0xffffff00))
-            || ((val & 0x800000) && ! (val & 0xff000000)))
-          return \"movu %1, %0\";
-      }
-
-    return \"mov %1, %0\";
-  }"
-  [(set_attr_alternative "timings"
-			 [(const_int 11)
-			  (if_then_else (eq_attr "cpu" "am34")
-					(const_int 13) (const_int 24))
-			  (if_then_else (eq_attr "cpu" "am34")
-					(const_int 13) (const_int 24))
-			  (if_then_else (eq_attr "cpu" "am34")
-					(const_int 13) (const_int 24))
-			  (if_then_else (eq_attr "cpu" "am34")
-					(const_int 13) (const_int 24))
-			  (if_then_else (eq_attr "cpu" "am34")
-					(const_int 13) (const_int 24))
-			 ])
-  ]
+{
+  switch (which_alternative)
+    {
+    case 0:
+      return "";
+    case 1: /* imm-reg*/
+      if (TARGET_AM33 && CONST_INT_P (operands[1]))
+	{
+	  HOST_WIDE_INT val = INTVAL (operands[1]);
+	  if (IN_RANGE (val, 0x80, 0xff)
+	      || IN_RANGE (val, 0x800000, 0xffffff))
+	    return "movu %1,%0";
+	}
+      /* FALLTHRU */
+    case 2:  /* reg-reg */
+    case 3:  /* reg-mem */
+    case 4:  /* mem-reg */
+    case 5:  /* sp-reg */
+    case 6:  /* reg-sp */
+    case 7:  /* imm-sp */
+      return "mov %1,%0";
+    default:
+      gcc_unreachable ();
+    }
+}
+  [(set_attr "isa" "*,*,*,*,*,*,*,am33")
+   (set_attr_alternative "timings"
+	 [(const_int 11)
+	  (const_int 22)
+	  (const_int 11)
+	  (if_then_else (eq_attr "cpu" "am34")
+			(const_int 11) (const_int 22))
+	  (if_then_else (eq_attr "cpu" "am34")
+			(const_int 13) (const_int 24))
+	  (if_then_else (eq_attr "cpu" "am34")
+			(const_int 11) (const_int 22))
+	  (if_then_else (eq_attr "cpu" "am34")
+			(const_int 13) (const_int 24))
+	  (const_int 11)
+	 ])]
 )
 
 (define_expand "movsf"
   [(set (match_operand:SF 0 "nonimmediate_operand")
 	(match_operand:SF 1 "general_operand"))]
-  ""
-  "
+  "TARGET_AM33_2"
 {
   /* One of the ops has to be in a register.  */
   if (!register_operand (operand1, SFmode)
       && !register_operand (operand0, SFmode))
-    operands[1] = copy_to_mode_reg (SFmode, operand1);
-}")
+    operands[1] = force_reg (SFmode, operand1);
+})
 
 (define_insn "*movsf_internal"
-  [(set (match_operand:SF 0 "nonimmediate_operand"
-			  ;; 0    1    2       3     4     5
-			  "=fdxa, dxa, f,      dxaQ, daxm, dax")
-	(match_operand:SF 1 "general_operand"
-			  " 0,    G,   fdxaQF, f,    dax,  daxFm"))
-  ]
-  "register_operand (operands[0], SFmode)
-   || register_operand (operands[1], SFmode)"
-  "*
-  {
-    switch (which_alternative)
-      {
-      case 0:
-        return \"nop\";
-      /* case 1: below.  */
-      case 2:
-      case 3:
-        return \"fmov %1, %0\";
-      case 1:
-      case 4:
-      case 5:
-        if (REGNO_REG_CLASS (true_regnum (operands[0])) == EXTENDED_REGS
-	    && CONST_INT_P (operands[1]))
-	  {
-	    HOST_WIDE_INT val = INTVAL (operands[1]);
-
-	    if (((val & 0x80) && ! (val & 0xffffff00))
-	        || ((val & 0x800000) && ! (val & 0xff000000)))
-	      return \"movu %1, %0\";
-	  }
-        return \"mov %1, %0\";
-      default:
-        gcc_unreachable ();
-      }
-  }"
-  [(set_attr_alternative "timings"
-			 [(const_int 11)
-			  (if_then_else (eq_attr "cpu" "am34")
-					(const_int 13) (const_int 24))
-			  (if_then_else (eq_attr "cpu" "am34")
-					(const_int 47) (const_int 25))
-			  (if_then_else (eq_attr "cpu" "am34")
-					(const_int 47) (const_int 25))
-			  (if_then_else (eq_attr "cpu" "am34")
-					(const_int 13) (const_int 24))
-			  (if_then_else (eq_attr "cpu" "am34")
-					(const_int 13) (const_int 24))
-			 ])
-  ]
-)
-
-(define_expand "movdi"
-  [(set (match_operand:DI 0 "nonimmediate_operand")
-	(match_operand:DI 1 "general_operand"))]
-  ""
-  "
-{
-  /* One of the ops has to be in a register.  */
-  if (!register_operand (operand1, DImode)
-      && !register_operand (operand0, DImode))
-    operands[1] = copy_to_mode_reg (DImode, operand1);
-}")
-
-
-(define_insn "*movdi_internal"                   ;;   0 1  2  3 4   5   6  7 8  9
-  [(set (match_operand:DI 0 "nonimmediate_operand" "=dx,ax,dx,a,dxm,dxm,a, a,dx,a")
-	(match_operand:DI 1 "general_operand"        "0,0, I, I,dx, a,  dx,a,im,im"))]
-  "register_operand (operands[0], DImode)
-   || register_operand (operands[1], DImode)"
-  "*
+  [(set (match_operand:SF 0 "nonimmediate_operand" "=rf,r,f,r,f,r,f,r,m,f,Q")
+	(match_operand:SF 1 "general_operand"	   "  0,F,F,r,f,f,r,m,r,Q,f"))]
+  "TARGET_AM33_2
+   && (register_operand (operands[0], SFmode)
+       || register_operand (operands[1], SFmode))"
 {
-  long val[2];
-  REAL_VALUE_TYPE rv;
-
   switch (which_alternative)
     {
-      case 0:
-      case 1:
-	return \"nop\";
-
-      case 2:
-	return \"mov 0, %L0\;mov 0, %H0\";
-
-      case 3:
-	if (rtx_equal_p (operands[0], operands[1]))
-	  return \"sub %L1,%L0\;mov %L0,%H0\";
-	else
-	  return \"mov %1,%L0\;mov %L0,%H0\";
-      case 4:
-      case 5:
-      case 6:
-      case 7:
-      case 8:
-      case 9:
-	if (CONST_INT_P (operands[1]))
-	  {
-	    rtx low, high;
-	    split_double (operands[1], &low, &high);
-	    val[0] = INTVAL (low);
-	    val[1] = INTVAL (high);
-	  }
-	if (CONST_DOUBLE_P (operands[1]))
-	  {
-	    if (GET_MODE (operands[1]) == DFmode)
-	      {
-		REAL_VALUE_FROM_CONST_DOUBLE (rv, operands[1]);
-		REAL_VALUE_TO_TARGET_DOUBLE (rv, val);
-	      }
-	    else if (GET_MODE (operands[1]) == VOIDmode
-		     || GET_MODE (operands[1]) == DImode)
-	      {
-		val[0] = CONST_DOUBLE_LOW (operands[1]);
-		val[1] = CONST_DOUBLE_HIGH (operands[1]);
-	      }
-	  }
-
-	if (MEM_P (operands[1])
-	    && reg_overlap_mentioned_p (operands[0], XEXP (operands[1], 0)))
-	  {
-	    rtx temp = operands[0];
-
-	    while (GET_CODE (temp) == SUBREG)
-	      temp = SUBREG_REG (temp);
-
-	    gcc_assert (REG_P (temp));
-
-	    if (reg_overlap_mentioned_p (gen_rtx_REG (SImode, REGNO (temp)),
-					 XEXP (operands[1], 0)))
-	      return \"mov %H1,%H0\;mov %L1,%L0\";
-	    else
-	      return \"mov %L1,%L0\;mov %H1,%H0\";
-
-	  }
-	else if (MEM_P (operands[1])
-		 && CONSTANT_ADDRESS_P (XEXP (operands[1], 0))
-		 && REGNO_REG_CLASS (REGNO (operands[0])) == ADDRESS_REGS)
-	  {
-	    rtx xoperands[2];
-
-	    xoperands[0] = operands[0];
-	    xoperands[1] = XEXP (operands[1], 0);
-
-	    output_asm_insn (\"mov %1,%L0\;mov (4,%L0),%H0\;mov (%L0),%L0\",
-			     xoperands);
-	    return \"\";
-	  }
-	else
-	  {
-	    if ((CONST_INT_P (operands[1])
-		 || CONST_DOUBLE_P (operands[1]))
-		&& val[0] == 0)
-	      {
-		if (REGNO_REG_CLASS (REGNO (operands[0])) == DATA_REGS)
-		  output_asm_insn (\"mov 0, %L0\", operands);
-		else
-		  output_asm_insn (\"mov %L1,%L0\", operands);
-	      }
-	    else if ((CONST_INT_P (operands[1])
-		      || CONST_DOUBLE_P (operands[1]))
-		     && (REGNO_REG_CLASS (true_regnum (operands[0]))
-			 == EXTENDED_REGS)
-		     && (((val[0] & 0x80) && ! (val[0] & 0xffffff00))
-			 || ((val[0] & 0x800000) && ! (val[0] & 0xff000000))))
-	      output_asm_insn (\"movu %L1,%L0\", operands);
-	    else
-	      output_asm_insn (\"mov %L1,%L0\", operands);
-
-	    if ((CONST_INT_P (operands[1])
-		 || CONST_DOUBLE_P (operands[1]))
-		&& val[1] == 0)
-	      {
-		if (REGNO_REG_CLASS (REGNO (operands[0])) == DATA_REGS)
-		  output_asm_insn (\"mov 0, %H0\", operands);
-		else
-		  output_asm_insn (\"mov %H1,%H0\", operands);
-	      }
-	    else if ((CONST_INT_P (operands[1])
-		      || CONST_DOUBLE_P (operands[1]))
-		     && val[0] == val[1])
-	      output_asm_insn (\"mov %L0,%H0\", operands);
-	    else if ((CONST_INT_P (operands[1])
-		      || CONST_DOUBLE_P (operands[1]))
-		     && (REGNO_REG_CLASS (true_regnum (operands[0]))
-			 == EXTENDED_REGS)
-		     && (((val[1] & 0x80) && ! (val[1] & 0xffffff00))
-			 || ((val[1] & 0x800000) && ! (val[1] & 0xff000000))))
-	      output_asm_insn (\"movu %H1,%H0\", operands);
-	    else
-	      output_asm_insn (\"mov %H1,%H0\", operands);
-	    return \"\";
-	  }
-    default:
-      gcc_unreachable ();
-    }
-  }"
-  ;; The timing of "37" is an approximation of the worst case sceanario.
-  [(set_attr_alternative "timings"
-			 [(const_int 11)
-			  (const_int 11)
-			  (const_int 22)
-			  (const_int 22)
-			  (const_int 37)
-			  (const_int 37)
-			  (const_int 37)
-			  (const_int 37)
-			  (const_int 37)
-			  (const_int 37)
-			 ])
-  ]
-)
-
-(define_expand "movdf"
-  [(set (match_operand:DF 0 "nonimmediate_operand")
-	(match_operand:DF 1 "general_operand"))]
-  ""
-  "
-{
-  /* One of the ops has to be in a register.  */
-  if (!register_operand (operand1, DFmode)
-      && !register_operand (operand0, DFmode))
-    operands[1] = copy_to_mode_reg (DFmode, operand1);
-}")
-
-(define_insn "*am33_2_movdf"
-  [(set (match_operand:DF 0 "nonimmediate_operand"
-			  ;; 0   1   2    3    4 5 6   7   8  9 10 11
-			  "=fdax,dax,fdxa,f,   f,Q,dxm,dxm,a, a,dx,a")
-	(match_operand:DF 1 "general_operand"
-			  " 0,   G,  f,   dxaF,Q,f,dx, a,  dx,a,Fm,Fm"))]
-  "TARGET_AM33_2
-   && (register_operand (operands[0], DFmode)
-       || register_operand (operands[1], DFmode))"
-  "*
-  {
-    long val[2];
-    REAL_VALUE_TYPE rv;
-
-    switch (which_alternative)
-      {
-      case 0:
-	return \"nop\";
-
-      case 1:
-	return \"mov 0, %L0\; mov 0, %H0\";
-
-      case 2:
-      case 3:
-        return \"fmov %L1, %L0\; fmov %H1, %H0\";
-
-      case 4:
-	if (MEM_P (operands[1])
-	    && CONST_INT_P (XEXP (operands[1], 0))
-	    && (INTVAL (XEXP (operands[1], 0)) & 7) == 0)
-	  return \"fmov %D1, %D0\";
-	else
-          return \"fmov %L1, %L0\; fmov %H1, %H0\";
-
-      case 5:
-	if (MEM_P (operands[0])
-	    && CONST_INT_P (XEXP (operands[0], 0))
-	    && (INTVAL (XEXP (operands[0], 0)) & 7) == 0)
-	  return \"fmov %D1, %D0\";
-	else
-          return \"fmov %L1, %L0\; fmov %H1, %H0\";
-
-      case 6:
-      case 7:
-      case 8:
-      case 9:
-      case 10:
-      case 11:
-	if (CONST_INT_P (operands[1]))
-	  {
-	    rtx low, high;
-	    split_double (operands[1], &low, &high);
-	    val[0] = INTVAL (low);
-	    val[1] = INTVAL (high);
-	  }
-	if (CONST_DOUBLE_P (operands[1]))
-	  {
-	    if (GET_MODE (operands[1]) == DFmode)
-	      {
-		REAL_VALUE_FROM_CONST_DOUBLE (rv, operands[1]);
-		REAL_VALUE_TO_TARGET_DOUBLE (rv, val);
-	      }
-	    else if (GET_MODE (operands[1]) == VOIDmode
-		     || GET_MODE (operands[1]) == DImode)
-	      {
-		val[0] = CONST_DOUBLE_LOW (operands[1]);
-		val[1] = CONST_DOUBLE_HIGH (operands[1]);
-	      }
-	  }
-
-	if (MEM_P (operands[1])
-	    && reg_overlap_mentioned_p (operands[0], XEXP (operands[1], 0)))
-	  {
-	    rtx temp = operands[0];
-
-	    while (GET_CODE (temp) == SUBREG)
-	      temp = SUBREG_REG (temp);
-
-	    gcc_assert (REG_P (temp));
-
-	    if (reg_overlap_mentioned_p (gen_rtx_REG (SImode, REGNO (temp)),
-					 XEXP (operands[1], 0)))
-	      return \"mov %H1, %H0\; mov %L1, %L0\";
-	    else
-	      return \"mov %L1, %L0\; mov %H1, %H0\";
-
-	  }
-	else if (MEM_P (operands[1])
-		 && CONSTANT_ADDRESS_P (XEXP (operands[1], 0))
-		 && REGNO_REG_CLASS (REGNO (operands[0])) == ADDRESS_REGS)
-	  {
-	    rtx xoperands[2];
-
-	    xoperands[0] = operands[0];
-	    xoperands[1] = XEXP (operands[1], 0);
-
-	    output_asm_insn (\"mov %1, %L0\; mov (4, %L0), %H0\; mov (%L0), %L0\",
-			     xoperands);
-	    return \"\";
-	  }
-	else
-	  {
-	    if ((CONST_INT_P (operands[1])
-		 || CONST_DOUBLE_P (operands[1]))
-		&& val[0] == 0)
-	      {
-		if (REGNO_REG_CLASS (REGNO (operands[0])) == DATA_REGS)
-		  output_asm_insn (\"mov 0, %L0\", operands);
-		else
-		  output_asm_insn (\"mov %L1,%L0\", operands);
-	      }
-	    else if ((CONST_INT_P (operands[1])
-		      || CONST_DOUBLE_P (operands[1]))
-		     && (REGNO_REG_CLASS (true_regnum (operands[0]))
-			 == EXTENDED_REGS)
-		     && (((val[0] & 0x80) && ! (val[0] & 0xffffff00))
-			 || ((val[0] & 0x800000) && ! (val[0] & 0xff000000))))
-	      output_asm_insn (\"movu %L1, %L0\", operands);
-	    else
-	      output_asm_insn (\"mov %L1, %L0\", operands);
-
-	    if ((CONST_INT_P (operands[1])
-		 || CONST_DOUBLE_P (operands[1]))
-		&& val[1] == 0)
-	      {
-		if (REGNO_REG_CLASS (REGNO (operands[0])) == DATA_REGS)
-		  output_asm_insn (\"mov 0, %H0\", operands);
-		else
-		  output_asm_insn (\"mov %H1, %H0\", operands);
-	      }
-	    else if ((CONST_INT_P (operands[1])
-		      || CONST_DOUBLE_P (operands[1]))
-		     && val[0] == val[1])
-	      output_asm_insn (\"mov %L0,%H0\", operands);
-	    else if ((CONST_INT_P (operands[1])
-		      || CONST_DOUBLE_P (operands[1]))
-		     && (REGNO_REG_CLASS (true_regnum (operands[0]))
-			 == EXTENDED_REGS)
-		     && (((val[1] & 0x80) && ! (val[1] & 0xffffff00))
-			 || ((val[1] & 0x800000) && ! (val[1] & 0xff000000))))
-	      output_asm_insn (\"movu %H1, %H0\", operands);
-	    else
-	      output_asm_insn (\"mov %H1, %H0\", operands);
-	    return \"\";
-	  }
+    case 0:
+      return "";
+    case 1:
+    case 3:
+    case 7:
+    case 8:
+      return "mov %1,%0";
+    case 2:
+    case 4:
+    case 5:
+    case 6:
+    case 9:
+    case 10:
+      return "fmov %1,%0";
     default:
       gcc_unreachable ();
     }
-  }"
-  ;; The timing of "37" is an approximation of the worst case sceanario.
+}
   [(set_attr_alternative "timings"
-			 [(const_int 11)
-			  (const_int 22)
-			  (const_int 22)
-			  (const_int 22)
-			  (const_int 22)
-			  (const_int 37)
-			  (const_int 37)
-			  (const_int 37)
-			  (const_int 37)
-			  (const_int 37)
-			  (const_int 37)
-			  (const_int 37)
-			 ])
-  ]
+		 [(const_int 11)
+		  (const_int 22)
+		  (if_then_else (eq_attr "cpu" "am34")
+				(const_int 47) (const_int 25))
+		  (const_int 11)
+		  (if_then_else (eq_attr "cpu" "am34")
+				(const_int 13) (const_int 14))
+		  (if_then_else (eq_attr "cpu" "am34")
+				(const_int 13) (const_int 12))
+		  (if_then_else (eq_attr "cpu" "am34")
+				(const_int 13) (const_int 14))
+		  (if_then_else (eq_attr "cpu" "am34")
+				(const_int 13) (const_int 24))
+		  (if_then_else (eq_attr "cpu" "am34")
+				(const_int 13) (const_int 24))
+		  (if_then_else (eq_attr "cpu" "am34")
+				(const_int 13) (const_int 24))
+		  (if_then_else (eq_attr "cpu" "am34")
+				(const_int 13) (const_int 24))
+		 ])]
 )
 
-(define_insn "*mn10300_movdf"
-  [(set (match_operand:DF 0 "nonimmediate_operand"
-			  ;;0    1    2    3    4   5  6   7
-			  "=dxa, dax, dxm, dxm, a,  a, dx, a")
-	(match_operand:DF 1 "general_operand"
-			  " 0,   G,   dx,  a,   dx, a, Fm, Fm"))]
-  "register_operand (operands[0], DFmode)
-   || register_operand (operands[1], DFmode)"
-  "*
-  {
-    long val[2];
-    REAL_VALUE_TYPE rv;
-
-    switch (which_alternative)
-      {
-      case 0:
-	return \"nop\";
-
-      case 1:
-	return \"mov 0, %L0\; mov 0, %H0\";
-
-      case 2:
-      case 3:
-      case 4:
-      case 5:
-      case 6:
-      case 7:
-	if (CONST_INT_P (operands[1]))
-	  {
-	    rtx low, high;
-	    split_double (operands[1], &low, &high);
-	    val[0] = INTVAL (low);
-	    val[1] = INTVAL (high);
-	  }
-        if (CONST_DOUBLE_P (operands[1]))
-	  {
-	    if (GET_MODE (operands[1]) == DFmode)
-	      {
-		REAL_VALUE_FROM_CONST_DOUBLE (rv, operands[1]);
-		REAL_VALUE_TO_TARGET_DOUBLE (rv, val);
-	      }
-	    else if (GET_MODE (operands[1]) == VOIDmode
-		     || GET_MODE (operands[1]) == DImode)
-	      {
-		val[0] = CONST_DOUBLE_LOW (operands[1]);
-		val[1] = CONST_DOUBLE_HIGH (operands[1]);
-	      }
-	  }
-
-	if (MEM_P (operands[1])
-	    && reg_overlap_mentioned_p (operands[0], XEXP (operands[1], 0)))
-	  {
-	    rtx temp = operands[0];
-
-	    while (GET_CODE (temp) == SUBREG)
-	      temp = SUBREG_REG (temp);
-
-	    gcc_assert (REG_P (temp));
-
-	    if (reg_overlap_mentioned_p (gen_rtx_REG (SImode, REGNO (temp)),
-					 XEXP (operands[1], 0)))
-	      return \"mov %H1, %H0\; mov %L1, %L0\";
-	    else
-	      return \"mov %L1, %L0\; mov %H1, %H0\";
-	  }
-	else if (MEM_P (operands[1])
-		 && CONSTANT_ADDRESS_P (XEXP (operands[1], 0))
-		 && REGNO_REG_CLASS (REGNO (operands[0])) == ADDRESS_REGS)
-	  {
-	    rtx xoperands[2];
-
-	    xoperands[0] = operands[0];
-	    xoperands[1] = XEXP (operands[1], 0);
-
-	    output_asm_insn (\"mov %1, %L0\; mov (4, %L0), %H0\; mov (%L0), %L0\",
-			     xoperands);
-	    return \"\";
-	  }
-	else
-	  {
-	    if ((CONST_INT_P (operands[1])
-		 || CONST_DOUBLE_P (operands[1]))
-		&& val[0] == 0)
-	      {
-		if (REGNO_REG_CLASS (REGNO (operands[0])) == DATA_REGS)
-		  output_asm_insn (\"mov 0, %L0\", operands);
-		else
-		  output_asm_insn (\"mov %L1, %L0\", operands);
-	      }
-	    else if ((CONST_INT_P (operands[1])
-		      || CONST_DOUBLE_P (operands[1]))
-		     && (REGNO_REG_CLASS (true_regnum (operands[0]))
-			 == EXTENDED_REGS)
-		     && (((val[0] & 0x80) && ! (val[0] & 0xffffff00))
-			 || ((val[0] & 0x800000) && ! (val[0] & 0xff000000))))
-	      output_asm_insn (\"movu %L1, %L0\", operands);
-	    else
-	      output_asm_insn (\"mov %L1, %L0\", operands);
-
-	    if ((CONST_INT_P (operands[1])
-		 || CONST_DOUBLE_P (operands[1]))
-		&& val[1] == 0)
-	      {
-		if (REGNO_REG_CLASS (REGNO (operands[0])) == DATA_REGS)
-		  output_asm_insn (\"mov 0, %H0\", operands);
-		else
-		  output_asm_insn (\"mov %H1, %H0\", operands);
-	      }
-	    else if ((CONST_INT_P (operands[1])
-		      || CONST_DOUBLE_P (operands[1]))
-		     && val[0] == val[1])
-	      output_asm_insn (\"mov %L0, %H0\", operands);
-	    else if ((CONST_INT_P (operands[1])
-		      || CONST_DOUBLE_P (operands[1]))
-		     && (REGNO_REG_CLASS (true_regnum (operands[0]))
-			 == EXTENDED_REGS)
-		     && (((val[1] & 0x80) && ! (val[1] & 0xffffff00))
-			 || ((val[1] & 0x800000) && ! (val[1] & 0xff000000))))
-	      output_asm_insn (\"movu %H1, %H0\", operands);
-	    else
-	      output_asm_insn (\"mov %H1, %H0\", operands);
-	    return \"\";
-	  }
-    default:
-      gcc_unreachable ();
-    }
-  }"
-  ;; Timings of "37" is approximation of the worst case sceanario.
-  [(set_attr_alternative "timings"
-			 [(const_int 11)
-			  (const_int 22)
-			  (const_int 37)
-			  (const_int 37)
-			  (const_int 37)
-			  (const_int 37)
-			  (const_int 37)
-			  (const_int 37)
-			 ])
-  ]
-)
 
 ;; ----------------------------------------------------------------------
 ;; ADD INSTRUCTIONS
@@ -1363,42 +762,23 @@ 
   	      		 	       (const_int 24) (const_int 23)))]
 )
 
-(define_expand "udivmodsi4"
-  [(parallel [(set (match_operand:SI          0 "register_operand")
-		   (udiv:SI (match_operand:SI 1 "general_operand")
-			    (match_operand:SI 2 "general_operand")))
-	      (set (match_operand:SI          3 "register_operand")
-		   (umod:SI (match_dup 1) (match_dup 2)))
-	      (clobber (reg:CC CC_REG))
-	     ])
-  ]
-  ""
-  "{
-    if (!register_operand (operands[1], SImode))
-      operands[1] = copy_to_mode_reg (SImode, operands[1]);
-    if (!register_operand (operands[2], SImode))
-      operands[2] = copy_to_mode_reg (SImode, operands[2]);
-   }"
-)
-
-(define_insn "*udivmodsi4"
-  [(set (match_operand:SI          0 "register_operand" "=dx")
+;; ??? This pattern causes too-high register pressure for MN103.
+;; ??? To be fixed by exposing the MDR register properly.
+(define_insn "udivmodsi4"
+  [(set (match_operand:SI          0 "register_operand" "=D")
 	(udiv:SI (match_operand:SI 1 "register_operand" "0")
-		 (match_operand:SI 2 "register_operand" "dx")))
+		 (match_operand:SI 2 "register_operand" "D")))
    (set (match_operand:SI          3 "register_operand" "=&d")
 	(umod:SI (match_dup 1) (match_dup 2)))
-   (clobber (reg:CC CC_REG))
-  ]
-  ""
-  "*
+   (clobber (reg:CC CC_REG))]
+  "TARGET_AM33"
 {
-  output_asm_insn (\"sub %3,%3\;mov %3,mdr\", operands);
-
+  output_asm_insn ("clr %3\;ext %3", operands);
   if (find_reg_note (insn, REG_UNUSED, operands[3]))
-    return \"divu %2,%0\";
+    return "divu %2,%0";
   else
-    return \"divu %2,%0\;mov mdr,%3\";
-}"
+    return "divu %2,%0\;mov mdr,%3";
+}
   ;; Timings:  AM33   AM34
   ;;  SUB       1/1    1/1
   ;;  MOV       1/1    1/1
@@ -1410,6 +790,28 @@ 
   	      		 	       (const_int 4546) (const_int 4142)))]
 )
 
+;; ??? In the meantime MN103 can use these two patterns,
+;; which reduce the register pressure by one.
+(define_insn "udivsi3"
+  [(set (match_operand:SI          0 "register_operand" "=&d")
+	(udiv:SI (match_operand:SI 1 "register_operand" "d")
+		 (match_operand:SI 2 "register_operand" "d")))
+   (clobber (reg:CC CC_REG))]
+  "!TARGET_AM33"
+  "clr %0\;ext %0\;mov %1,%0\;divu %2,%0"
+  [(set_attr "timings" "4142")]
+)
+
+(define_insn "umodsi3"
+  [(set (match_operand:SI          0 "register_operand" "=&d")
+	(umod:SI (match_operand:SI 1 "register_operand" "d")
+		 (match_operand:SI 2 "register_operand" "d")))
+   (clobber (reg:CC CC_REG))]
+  "!TARGET_AM33"
+  "clr %0\;ext %0\;mov %1,%0\;divu %2,%0\;mov mdr,%0"
+  [(set_attr "timings" "4142")]
+)
+
 (define_insn "divmodsi4"
   [(set (match_operand:SI          0 "register_operand" "=dx")
 	(div:SI (match_operand:SI  1 "register_operand"  "0")