Commit b1efde2a by Richard Henderson Committed by Richard Henderson

mn10300: Re-write move patterns.

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.

From-SVN: r169004
parent 036c8f37
2011-01-19 Richard Henderson <rth@redhat.com>
* config/mn10300/mn10300.md (*am33_movqi, *mn10300_movqi): Merge into
(*movqi_internal): ... here.
(*am33_movhi, *mn10300_movhi): Merge into...
(*movhi_internal): ... here.
(*movsi_internal): Use "r" instead of "dax" in constraints. Use "A"
as the source/destination of moves from/to SP.
(movsf): Only allow for AM33-2.
(*movsf_internal): Use "r" instead of "dax"; use "F" instead of
any integer constant constraint. Only allow for AM33-2. Tidy
all of the alternative outputs.
(movdi, movdf, *am33_2_movdf, *mn10300_movdf): Remove.
(udivmodsi4): Delete expander and promote *udivmodsi4. Disallow
for MN103.
(udivsi3, umodsi3): New patterns for MN103 only.
2011-01-19 Joern Rennecke <amylaar@spamcop.net> 2011-01-19 Joern Rennecke <amylaar@spamcop.net>
* doc/tm.texi.in: Spell out that a lack of register class unions * doc/tm.texi.in: Spell out that a lack of register class unions
......
...@@ -188,107 +188,42 @@ ...@@ -188,107 +188,42 @@
[(set (match_operand:QI 0 "nonimmediate_operand") [(set (match_operand:QI 0 "nonimmediate_operand")
(match_operand:QI 1 "general_operand"))] (match_operand:QI 1 "general_operand"))]
"" ""
"
{ {
/* One of the ops has to be in a register. */ /* One of the ops has to be in a register. */
if (!register_operand (operand0, QImode) if (!register_operand (operand0, QImode)
&& !register_operand (operand1, QImode)) && !register_operand (operand1, QImode))
operands[1] = copy_to_mode_reg (QImode, operand1); operands[1] = force_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))
])
]
)
(define_insn "*mn10300_movqi" (define_insn "*movqi_internal"
[(set (match_operand:QI 0 "nonimmediate_operand" "=d*a,d,d,!*a,d*a,d,m") [(set (match_operand:QI 0 "nonimmediate_operand" "=*r,D*r,D*r,D,m")
(match_operand:QI 1 "general_operand" "0, I,i,i, da, m,d"))] (match_operand:QI 1 "general_operand" " 0,D*r, i,m,D"))]
"register_operand (operands[0], QImode) "(register_operand (operands[0], QImode)
|| register_operand (operands[1], QImode)" || register_operand (operands[1], QImode))"
"*
{ {
switch (which_alternative) switch (which_alternative)
{ {
case 0: case 0:
return \"nop\"; return "";
case 1: case 1:
case 2: case 2:
return "mov %1,%0";
case 3: case 3:
case 4: case 4:
gcc_assert (! CONST_DOUBLE_P (operands[1])); return "movbu %1,%0";
return \"mov %1,%0\";
case 5:
case 6:
return \"movbu %1,%0\";
default: default:
gcc_unreachable (); gcc_unreachable ();
} }
}" }
[(set_attr_alternative "timings" [(set_attr_alternative "timings"
[(const_int 11) [(const_int 11)
(const_int 11) (const_int 11)
(if_then_else (eq_attr "cpu" "am34") (const_int 11)
(const_int 11) (const_int 22)) (if_then_else (eq_attr "cpu" "am34")
(if_then_else (eq_attr "cpu" "am34") (const_int 13) (const_int 24))
(const_int 11) (const_int 22)) (if_then_else (eq_attr "cpu" "am34")
(if_then_else (eq_attr "cpu" "am34") (const_int 11) (const_int 22))
(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))
])
]
) )
;; movhi ;; movhi
...@@ -297,107 +232,52 @@ ...@@ -297,107 +232,52 @@
[(set (match_operand:HI 0 "nonimmediate_operand") [(set (match_operand:HI 0 "nonimmediate_operand")
(match_operand:HI 1 "general_operand"))] (match_operand:HI 1 "general_operand"))]
"" ""
"
{ {
/* One of the ops has to be in a register. */ /* One of the ops has to be in a register. */
if (!register_operand (operand1, HImode) if (!register_operand (operand1, HImode)
&& !register_operand (operand0, HImode)) && !register_operand (operand0, HImode))
operands[1] = copy_to_mode_reg (HImode, operand1); operands[1] = force_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))
])
]
)
(define_insn "*mn10300_movhi" (define_insn "*movhi_internal"
[(set (match_operand:HI 0 "nonimmediate_operand" "=d*a,d,d,!*a,d*a,d,m") [(set (match_operand:HI 0 "nonimmediate_operand" "=*r,D*r,D*r,D,m")
(match_operand:HI 1 "general_operand" "0, I,i,i, da, m,d"))] (match_operand:HI 1 "general_operand" " 0, i,D*r,m,D"))]
"register_operand (operands[0], HImode) "(register_operand (operands[0], HImode)
|| register_operand (operands[1], HImode)" || register_operand (operands[1], HImode))"
"*
{ {
switch (which_alternative) switch (which_alternative)
{ {
case 0: case 0:
return \"nop\"; return "";
case 1: case 1:
/* Note that "MOV imm8,An" is already zero-extending, and is 2 bytes.
We have "MOV imm16,Dn" at 3 bytes. The only win for the 4 byte
movu is for an 8-bit unsigned move into Rn. */
if (TARGET_AM33
&& CONST_INT_P (operands[1])
&& IN_RANGE (INTVAL (operands[1]), 0x80, 0xff)
&& REGNO_EXTENDED_P (REGNO (operands[0]), 1))
return "movu %1,%0";
/* FALLTHRU */
case 2: case 2:
return "mov %1,%0";
case 3: case 3:
case 4: case 4:
gcc_assert (! CONST_DOUBLE_P (operands[1])); return "movhu %1,%0";
return \"mov %1,%0\";
case 5:
case 6:
return \"movhu %1,%0\";
default: default:
gcc_unreachable (); gcc_unreachable ();
} }
}" }
[(set_attr_alternative "timings" [(set_attr_alternative "timings"
[(const_int 11) [(const_int 11)
(const_int 11) (const_int 11)
(if_then_else (eq_attr "cpu" "am34") (if_then_else (eq_attr "cpu" "am34")
(const_int 11) (const_int 22)) (const_int 11) (const_int 22))
(if_then_else (eq_attr "cpu" "am34") (if_then_else (eq_attr "cpu" "am34")
(const_int 11) (const_int 22)) (const_int 13) (const_int 24))
(if_then_else (eq_attr "cpu" "am34") (if_then_else (eq_attr "cpu" "am34")
(const_int 11) (const_int 22)) (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))
])
]
) )
;; movsi and helpers ;; movsi and helpers
...@@ -457,12 +337,11 @@ ...@@ -457,12 +337,11 @@
[(set (match_operand:SI 0 "nonimmediate_operand") [(set (match_operand:SI 0 "nonimmediate_operand")
(match_operand:SI 1 "general_operand"))] (match_operand:SI 1 "general_operand"))]
"" ""
"
{ {
/* One of the ops has to be in a register. */ /* One of the ops has to be in a register. */
if (!register_operand (operand1, SImode) if (!register_operand (operand1, SImode)
&& !register_operand (operand0, SImode)) && !register_operand (operand0, SImode))
operands[1] = copy_to_mode_reg (SImode, operand1); operands[1] = force_reg (SImode, operand1);
if (flag_pic) if (flag_pic)
{ {
rtx temp; rtx temp;
...@@ -493,594 +372,123 @@ ...@@ -493,594 +372,123 @@
0, OPTAB_LIB_WIDEN); 0, OPTAB_LIB_WIDEN);
} }
} }
}") })
(define_insn "*movsi_internal" (define_insn "*movsi_internal"
[(set (match_operand:SI 0 "nonimmediate_operand" [(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" (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[0], SImode)
|| register_operand (operands[1], SImode)" || register_operand (operands[1], SImode)"
"* {
{ switch (which_alternative)
if (which_alternative == 0) {
return \"nop\"; case 0:
return "";
gcc_assert (! CONST_DOUBLE_P (operands[1])); case 1: /* imm-reg*/
/* See movhi for a discussion of sizes for 8-bit movu. Note that the
if (REGNO_REG_CLASS (true_regnum (operands[0])) == EXTENDED_REGS 24-bit movu is 6 bytes, which is the same size as the full 32-bit
&& CONST_INT_P (operands[1])) mov form for An and Dn. So again movu is only a win for Rn. */
{ if (TARGET_AM33
HOST_WIDE_INT val = INTVAL (operands[1]); && CONST_INT_P (operands[1])
&& REGNO_EXTENDED_P (REGNO (operands[0]), 1))
if (((val & 0x80) && ! (val & 0xffffff00)) {
|| ((val & 0x800000) && ! (val & 0xff000000))) HOST_WIDE_INT val = INTVAL (operands[1]);
return \"movu %1, %0\"; if (IN_RANGE (val, 0x80, 0xff)
} || IN_RANGE (val, 0x800000, 0xffffff))
return "movu %1,%0";
return \"mov %1, %0\"; }
}" /* FALLTHRU */
[(set_attr_alternative "timings" case 2: /* reg-reg */
[(const_int 11) case 3: /* reg-mem */
(if_then_else (eq_attr "cpu" "am34") case 4: /* mem-reg */
(const_int 13) (const_int 24)) case 5: /* sp-reg */
(if_then_else (eq_attr "cpu" "am34") case 6: /* reg-sp */
(const_int 13) (const_int 24)) case 7: /* imm-sp */
(if_then_else (eq_attr "cpu" "am34") return "mov %1,%0";
(const_int 13) (const_int 24)) default:
(if_then_else (eq_attr "cpu" "am34") gcc_unreachable ();
(const_int 13) (const_int 24)) }
(if_then_else (eq_attr "cpu" "am34") }
(const_int 13) (const_int 24)) [(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" (define_expand "movsf"
[(set (match_operand:SF 0 "nonimmediate_operand") [(set (match_operand:SF 0 "nonimmediate_operand")
(match_operand:SF 1 "general_operand"))] (match_operand:SF 1 "general_operand"))]
"" "TARGET_AM33_2"
"
{ {
/* One of the ops has to be in a register. */ /* One of the ops has to be in a register. */
if (!register_operand (operand1, SFmode) if (!register_operand (operand1, SFmode)
&& !register_operand (operand0, SFmode)) && !register_operand (operand0, SFmode))
operands[1] = copy_to_mode_reg (SFmode, operand1); operands[1] = force_reg (SFmode, operand1);
}") })
(define_insn "*movsf_internal" (define_insn "*movsf_internal"
[(set (match_operand:SF 0 "nonimmediate_operand" [(set (match_operand:SF 0 "nonimmediate_operand" "=rf,r,f,r,f,r,f,r,m,f,Q")
;; 0 1 2 3 4 5 (match_operand:SF 1 "general_operand" " 0,F,F,r,f,f,r,m,r,Q,f"))]
"=fdxa, dxa, f, dxaQ, daxm, dax") "TARGET_AM33_2
(match_operand:SF 1 "general_operand" && (register_operand (operands[0], SFmode)
" 0, G, fdxaQF, f, dax, daxFm")) || register_operand (operands[1], SFmode))"
]
"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)"
"*
{ {
long val[2];
REAL_VALUE_TYPE rv;
switch (which_alternative) switch (which_alternative)
{ {
case 0: case 0:
case 1: return "";
return \"nop\"; case 1:
case 3:
case 2: case 7:
return \"mov 0, %L0\;mov 0, %H0\"; case 8:
return "mov %1,%0";
case 3: case 2:
if (rtx_equal_p (operands[0], operands[1])) case 4:
return \"sub %L1,%L0\;mov %L0,%H0\"; case 5:
else case 6:
return \"mov %1,%L0\;mov %L0,%H0\"; case 9:
case 4: case 10:
case 5: return "fmov %1,%0";
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 \"\";
}
default: default:
gcc_unreachable (); gcc_unreachable ();
} }
}" }
;; The timing of "37" is an approximation of the worst case sceanario.
[(set_attr_alternative "timings" [(set_attr_alternative "timings"
[(const_int 11) [(const_int 11)
(const_int 22) (const_int 22)
(const_int 22) (if_then_else (eq_attr "cpu" "am34")
(const_int 22) (const_int 47) (const_int 25))
(const_int 22) (const_int 11)
(const_int 37) (if_then_else (eq_attr "cpu" "am34")
(const_int 37) (const_int 13) (const_int 14))
(const_int 37) (if_then_else (eq_attr "cpu" "am34")
(const_int 37) (const_int 13) (const_int 12))
(const_int 37) (if_then_else (eq_attr "cpu" "am34")
(const_int 37) (const_int 13) (const_int 14))
(const_int 37) (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 ;; ADD INSTRUCTIONS
...@@ -1394,42 +802,23 @@ ...@@ -1394,42 +802,23 @@
(const_int 24) (const_int 23)))] (const_int 24) (const_int 23)))]
) )
(define_expand "udivmodsi4" ;; ??? This pattern causes too-high register pressure for MN103.
[(parallel [(set (match_operand:SI 0 "register_operand") ;; ??? To be fixed by exposing the MDR register properly.
(udiv:SI (match_operand:SI 1 "general_operand") (define_insn "udivmodsi4"
(match_operand:SI 2 "general_operand"))) [(set (match_operand:SI 0 "register_operand" "=D")
(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")
(udiv:SI (match_operand:SI 1 "register_operand" "0") (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") (set (match_operand:SI 3 "register_operand" "=&d")
(umod:SI (match_dup 1) (match_dup 2))) (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])) if (find_reg_note (insn, REG_UNUSED, operands[3]))
return \"divu %2,%0\"; return "divu %2,%0";
else else
return \"divu %2,%0\;mov mdr,%3\"; return "divu %2,%0\;mov mdr,%3";
}" }
;; Timings: AM33 AM34 ;; Timings: AM33 AM34
;; SUB 1/1 1/1 ;; SUB 1/1 1/1
;; MOV 1/1 1/1 ;; MOV 1/1 1/1
...@@ -1441,6 +830,28 @@ ...@@ -1441,6 +830,28 @@
(const_int 4546) (const_int 4142)))] (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" (define_insn "divmodsi4"
[(set (match_operand:SI 0 "register_operand" "=dx") [(set (match_operand:SI 0 "register_operand" "=dx")
(div:SI (match_operand:SI 1 "register_operand" "0") (div:SI (match_operand:SI 1 "register_operand" "0")
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment