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>
* doc/tm.texi.in: Spell out that a lack of register class unions
......
......@@ -188,107 +188,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
......@@ -297,107 +232,52 @@
[(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:
/* 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:
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
......@@ -457,12 +337,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;
......@@ -493,594 +372,123 @@
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*/
/* See movhi for a discussion of sizes for 8-bit movu. Note that the
24-bit movu is 6 bytes, which is the same size as the full 32-bit
mov form for An and Dn. So again movu is only a win for Rn. */
if (TARGET_AM33
&& CONST_INT_P (operands[1])
&& REGNO_EXTENDED_P (REGNO (operands[0]), 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
......@@ -1394,42 +802,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
......@@ -1441,6 +830,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")
......
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