From: Richard Henderson Date: Wed, 19 Jan 2011 16:57:37 +0000 (-0800) Subject: mn10300: Re-write move patterns. X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=b1efde2a0bef10502751bbb5f9caf96370424805;p=gcc.git 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 --- diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 9af2456e621..46ebaee53f2 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,20 @@ +2011-01-19 Richard Henderson + + * 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 * doc/tm.texi.in: Spell out that a lack of register class unions diff --git a/gcc/config/mn10300/mn10300.md b/gcc/config/mn10300/mn10300.md index 8ae52c904e1..9cddebf3e79 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")