aboutsummaryrefslogtreecommitdiff
path: root/gcc/config
diff options
context:
space:
mode:
authorRichard Henderson <rth@redhat.com>2011-01-19 08:57:37 -0800
committerRichard Henderson <rth@gcc.gnu.org>2011-01-19 08:57:37 -0800
commitb1efde2a0bef10502751bbb5f9caf96370424805 (patch)
tree88e45d5807f38f55aad1a69b0c8b7e995a33e83b /gcc/config
parent036c8f37959ccdafc6ea055ec109eb7cc3051697 (diff)
downloadgcc-b1efde2a0bef10502751bbb5f9caf96370424805.zip
gcc-b1efde2a0bef10502751bbb5f9caf96370424805.tar.gz
gcc-b1efde2a0bef10502751bbb5f9caf96370424805.tar.bz2
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
Diffstat (limited to 'gcc/config')
-rw-r--r--gcc/config/mn10300/mn10300.md935
1 files changed, 173 insertions, 762 deletions
diff --git a/gcc/config/mn10300/mn10300.md b/gcc/config/mn10300/mn10300.md
index 8ae52c9..9cddebf 100644
--- a/gcc/config/mn10300/mn10300.md
+++ b/gcc/config/mn10300/mn10300.md
@@ -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")