Message ID | 1294691517-19580-13-git-send-email-rth@redhat.com |
---|---|
State | New |
Headers | show |
-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 On 01/10/11 13:31, Richard Henderson wrote: > From: Richard Henderson <rth@twiddle.net> > > Use the "D" and "A" constraints, and the enabled attribute to > unify all ofthe integer move patterns. Delete the fake double > word move patterns; let the middle-end generate subregs as required. > > Unfortunately, this somehow exposes a register pressure problem > with the udivmod pattern. This is properly fixed with subsequent > patches that expose the MDR register. > > In the meantime it is highly desirable to to preserve bisect-ability > of the patch series, so disable this pattern for AM30. Ideally we'd like to zap alternative 0 in the movxx patterns (nop move register to itself). IIRC such moves can occur in unoptimized compilations. The mn103 series can't encode a reg->reg copy where the source and destination registers are the same. That situation tells the decoder that the instruction is a multi-byte instruction and that it must look at subsequent bytes to determine exactly what the instruction does. IIRC returning an empty string for that case didn't work because the empty string had some kind of special meaning in final. (This was 13 or 14 years ago, so please forgive the IIRC's :-) The net result is I think you have to return something for those alternatives rather than an empty string. It also seems to me that for movqi/movhi we want to severely disparage the address regs on the mn103. IIRC for the base mn103 we would trigger reload failures if we didn't expose a0-a3 to the movqi/movhi patterns. However, while the a0-a3 regs can hold such values, they can't be used in arithmetic/logicals/etc in QI/HI mode. So to avoid pessimizing code we exposed a0-a3 in the QI/HI mode moves, but ignored them for register class preferencing and severely disparaged them for reloading. It also looks like you lost the movu am33 variant for movqi/movhi. I don't recall anything about that alternative, but I can hazard a guess that movu is smaller than the more generic mov instruction for certain constants. I suspect losing the fmov variant for movqi/movhi is a good thing :-) Presumably we ensure that the FP registers can't hold HImode/QImode values elsewhere ;-) It looks like you lost movu for the base mn103 in the movsi pattern and for all the parts in the movsf pattern (it may not matter there). The DI/DF mode stuff looks good. We might regress a little for certain specific constants, but it shouldn't be too bad. Jeff > --- > gcc/config/mn10300/mn10300.md | 930 ++++++++--------------------------------- > 1 files changed, 166 insertions(+), 764 deletions(-) > > diff --git a/gcc/config/mn10300/mn10300.md b/gcc/config/mn10300/mn10300.md > index 04ec1b1..6e0e1a2 100644 > --- a/gcc/config/mn10300/mn10300.md > +++ b/gcc/config/mn10300/mn10300.md > @@ -181,107 +181,42 @@ > [(set (match_operand:QI 0 "nonimmediate_operand") > (match_operand:QI 1 "general_operand"))] > "" > - " > { > /* One of the ops has to be in a register. */ > if (!register_operand (operand0, QImode) > && !register_operand (operand1, QImode)) > - operands[1] = copy_to_mode_reg (QImode, operand1); > -}") > - > -(define_insn "*am33_movqi" > - [(set (match_operand:QI 0 "nonimmediate_operand" > - ;; 0 1 2 3 4 5 > - "=d*x*a*f, d*x*a, d*x*a, m, *f, d*x*a") > - (match_operand:QI 1 "general_operand" > - "0, d*xai, m, d*xa, d*xa*f, *f"))] > - "TARGET_AM33 > - && (register_operand (operands[0], QImode) > - || register_operand (operands[1], QImode))" > - "* > - { > - switch (which_alternative) > - { > - case 0: > - return \"nop\"; > - case 1: > - gcc_assert (! CONST_DOUBLE_P (operands[1])); > - > - if (REGNO_REG_CLASS (true_regnum (operands[0])) == EXTENDED_REGS > - && CONST_INT_P (operands[1])) > - { > - HOST_WIDE_INT val = INTVAL (operands[1]); > - > - if (((val & 0x80) && ! (val & 0xffffff00)) > - || ((val & 0x800000) && ! (val & 0xff000000))) > - return \"movu %1,%0\"; > - } > - return \"mov %1,%0\"; > - case 2: > - case 3: > - return \"movbu %1,%0\"; > - case 4: > - case 5: > - return \"fmov %1,%0\"; > - default: > - gcc_unreachable (); > - } > - }" > - [(set_attr_alternative "timings" > - [(const_int 11) > - (if_then_else (eq_attr "cpu" "am34") > - (const_int 11) (const_int 22)) > - (if_then_else (eq_attr "cpu" "am34") > - (const_int 13) (const_int 24)) > - (if_then_else (eq_attr "cpu" "am34") > - (const_int 13) (const_int 24)) > - (if_then_else (eq_attr "cpu" "am34") > - (const_int 47) (const_int 25)) > - (if_then_else (eq_attr "cpu" "am34") > - (const_int 47) (const_int 25)) > - ]) > - ] > -) > + operands[1] = force_reg (QImode, operand1); > +}) > > -(define_insn "*mn10300_movqi" > - [(set (match_operand:QI 0 "nonimmediate_operand" "=d*a,d,d,!*a,d*a,d,m") > - (match_operand:QI 1 "general_operand" "0, I,i,i, da, m,d"))] > - "register_operand (operands[0], QImode) > - || register_operand (operands[1], QImode)" > - "* > +(define_insn "*movqi_internal" > + [(set (match_operand:QI 0 "nonimmediate_operand" "=*r,D*r,D*r,D,m") > + (match_operand:QI 1 "general_operand" " 0,D*r, i,m,D"))] > + "(register_operand (operands[0], QImode) > + || register_operand (operands[1], QImode))" > { > switch (which_alternative) > { > case 0: > - return \"nop\"; > + return ""; > case 1: > case 2: > + return "mov %1,%0"; > case 3: > case 4: > - gcc_assert (! CONST_DOUBLE_P (operands[1])); > - return \"mov %1,%0\"; > - case 5: > - case 6: > - return \"movbu %1,%0\"; > + return "movbu %1,%0"; > default: > gcc_unreachable (); > } > -}" > +} > [(set_attr_alternative "timings" > - [(const_int 11) > - (const_int 11) > - (if_then_else (eq_attr "cpu" "am34") > - (const_int 11) (const_int 22)) > - (if_then_else (eq_attr "cpu" "am34") > - (const_int 11) (const_int 22)) > - (if_then_else (eq_attr "cpu" "am34") > - (const_int 11) (const_int 22)) > - (if_then_else (eq_attr "cpu" "am34") > - (const_int 13) (const_int 24)) > - (if_then_else (eq_attr "cpu" "am34") > - (const_int 13) (const_int 24)) > - ]) > - ] > + [(const_int 11) > + (const_int 11) > + (const_int 11) > + (if_then_else (eq_attr "cpu" "am34") > + (const_int 13) (const_int 24)) > + (if_then_else (eq_attr "cpu" "am34") > + (const_int 11) (const_int 22)) > + ])] > ) > > ;; movhi > @@ -290,107 +225,48 @@ > [(set (match_operand:HI 0 "nonimmediate_operand") > (match_operand:HI 1 "general_operand"))] > "" > - " > { > /* One of the ops has to be in a register. */ > if (!register_operand (operand1, HImode) > && !register_operand (operand0, HImode)) > - operands[1] = copy_to_mode_reg (HImode, operand1); > -}") > - > -(define_insn "*am33_movhi" > - [(set (match_operand:HI 0 "nonimmediate_operand" > - ;; 0 1 2 3 4 5 > - "=d*x*a*f, d*x*a, d*x*a, m, *f, d*x*a") > - (match_operand:HI 1 "general_operand" > - "0, d*x*ai, m, d*x*a, d*x*a*f, *f"))] > - "TARGET_AM33 > - && (register_operand (operands[0], HImode) > - || register_operand (operands[1], HImode))" > - "* > -{ > - switch (which_alternative) > - { > - case 0: > - return \"nop\"; > - case 1: > - gcc_assert (! CONST_DOUBLE_P (operands[1])); > - > - if (REGNO_REG_CLASS (true_regnum (operands[0])) == EXTENDED_REGS > - && CONST_INT_P (operands[1])) > - { > - HOST_WIDE_INT val = INTVAL (operands[1]); > - > - if (((val & 0x80) && ! (val & 0xffffff00)) > - || ((val & 0x800000) && ! (val & 0xff000000))) > - return \"movu %1,%0\"; > - } > - return \"mov %1,%0\"; > - case 2: > - case 3: > - return \"movhu %1,%0\"; > - case 4: > - case 5: > - return \"fmov %1,%0\"; > - default: > - gcc_unreachable (); > - } > -}" > - [(set_attr_alternative "timings" > - [(const_int 11) > - (if_then_else (eq_attr "cpu" "am34") > - (const_int 11) (const_int 22)) > - (if_then_else (eq_attr "cpu" "am34") > - (const_int 13) (const_int 24)) > - (if_then_else (eq_attr "cpu" "am34") > - (const_int 13) (const_int 24)) > - (if_then_else (eq_attr "cpu" "am34") > - (const_int 47) (const_int 25)) > - (if_then_else (eq_attr "cpu" "am34") > - (const_int 47) (const_int 25)) > - ]) > - ] > -) > + operands[1] = force_reg (HImode, operand1); > +}) > > -(define_insn "*mn10300_movhi" > - [(set (match_operand:HI 0 "nonimmediate_operand" "=d*a,d,d,!*a,d*a,d,m") > - (match_operand:HI 1 "general_operand" "0, I,i,i, da, m,d"))] > - "register_operand (operands[0], HImode) > - || register_operand (operands[1], HImode)" > - "* > +(define_insn "*movhi_internal" > + [(set (match_operand:HI 0 "nonimmediate_operand" "=*r,D*r,D*r,D,m") > + (match_operand:HI 1 "general_operand" " 0, i,D*r,m,D"))] > + "(register_operand (operands[0], HImode) > + || register_operand (operands[1], HImode))" > { > switch (which_alternative) > { > case 0: > - return \"nop\"; > + return ""; > case 1: > + if (TARGET_AM33 > + && CONST_INT_P (operands[1]) > + && IN_RANGE (INTVAL (operands[1]), 0x80, 0xff)) > + return "movu %1,%0"; > + /* FALLTHRU */ > case 2: > + return "mov %1,%0"; > case 3: > case 4: > - gcc_assert (! CONST_DOUBLE_P (operands[1])); > - return \"mov %1,%0\"; > - case 5: > - case 6: > - return \"movhu %1,%0\"; > + return "movhu %1,%0"; > default: > gcc_unreachable (); > } > -}" > +} > [(set_attr_alternative "timings" > - [(const_int 11) > - (const_int 11) > - (if_then_else (eq_attr "cpu" "am34") > - (const_int 11) (const_int 22)) > - (if_then_else (eq_attr "cpu" "am34") > - (const_int 11) (const_int 22)) > - (if_then_else (eq_attr "cpu" "am34") > - (const_int 11) (const_int 22)) > - (if_then_else (eq_attr "cpu" "am34") > - (const_int 13) (const_int 24)) > - (if_then_else (eq_attr "cpu" "am34") > - (const_int 13) (const_int 24)) > - ]) > - ] > + [(const_int 11) > + (const_int 11) > + (if_then_else (eq_attr "cpu" "am34") > + (const_int 11) (const_int 22)) > + (if_then_else (eq_attr "cpu" "am34") > + (const_int 13) (const_int 24)) > + (if_then_else (eq_attr "cpu" "am34") > + (const_int 11) (const_int 22)) > + ])] > ) > > ;; movsi and helpers > @@ -450,12 +326,11 @@ > [(set (match_operand:SI 0 "nonimmediate_operand") > (match_operand:SI 1 "general_operand"))] > "" > - " > { > /* One of the ops has to be in a register. */ > if (!register_operand (operand1, SImode) > && !register_operand (operand0, SImode)) > - operands[1] = copy_to_mode_reg (SImode, operand1); > + operands[1] = force_reg (SImode, operand1); > if (flag_pic) > { > rtx temp; > @@ -486,594 +361,118 @@ > 0, OPTAB_LIB_WIDEN); > } > } > -}") > +}) > > (define_insn "*movsi_internal" > [(set (match_operand:SI 0 "nonimmediate_operand" > - "=dax, dax, m, dax, ax,!*y") > + "=r,r,r,m,r, A,*y,*y") > (match_operand:SI 1 "general_operand" > - "0, Idax, dax, im, !*y, ax")) > - ] > + " 0,i,r,r,m,*y, A, i"))] > "register_operand (operands[0], SImode) > || register_operand (operands[1], SImode)" > - "* > - { > - if (which_alternative == 0) > - return \"nop\"; > - > - gcc_assert (! CONST_DOUBLE_P (operands[1])); > - > - if (REGNO_REG_CLASS (true_regnum (operands[0])) == EXTENDED_REGS > - && CONST_INT_P (operands[1])) > - { > - HOST_WIDE_INT val = INTVAL (operands[1]); > - > - if (((val & 0x80) && ! (val & 0xffffff00)) > - || ((val & 0x800000) && ! (val & 0xff000000))) > - return \"movu %1, %0\"; > - } > - > - return \"mov %1, %0\"; > - }" > - [(set_attr_alternative "timings" > - [(const_int 11) > - (if_then_else (eq_attr "cpu" "am34") > - (const_int 13) (const_int 24)) > - (if_then_else (eq_attr "cpu" "am34") > - (const_int 13) (const_int 24)) > - (if_then_else (eq_attr "cpu" "am34") > - (const_int 13) (const_int 24)) > - (if_then_else (eq_attr "cpu" "am34") > - (const_int 13) (const_int 24)) > - (if_then_else (eq_attr "cpu" "am34") > - (const_int 13) (const_int 24)) > - ]) > - ] > +{ > + switch (which_alternative) > + { > + case 0: > + return ""; > + case 1: /* imm-reg*/ > + if (TARGET_AM33 && CONST_INT_P (operands[1])) > + { > + HOST_WIDE_INT val = INTVAL (operands[1]); > + if (IN_RANGE (val, 0x80, 0xff) > + || IN_RANGE (val, 0x800000, 0xffffff)) > + return "movu %1,%0"; > + } > + /* FALLTHRU */ > + case 2: /* reg-reg */ > + case 3: /* reg-mem */ > + case 4: /* mem-reg */ > + case 5: /* sp-reg */ > + case 6: /* reg-sp */ > + case 7: /* imm-sp */ > + return "mov %1,%0"; > + default: > + gcc_unreachable (); > + } > +} > + [(set_attr "isa" "*,*,*,*,*,*,*,am33") > + (set_attr_alternative "timings" > + [(const_int 11) > + (const_int 22) > + (const_int 11) > + (if_then_else (eq_attr "cpu" "am34") > + (const_int 11) (const_int 22)) > + (if_then_else (eq_attr "cpu" "am34") > + (const_int 13) (const_int 24)) > + (if_then_else (eq_attr "cpu" "am34") > + (const_int 11) (const_int 22)) > + (if_then_else (eq_attr "cpu" "am34") > + (const_int 13) (const_int 24)) > + (const_int 11) > + ])] > ) > > (define_expand "movsf" > [(set (match_operand:SF 0 "nonimmediate_operand") > (match_operand:SF 1 "general_operand"))] > - "" > - " > + "TARGET_AM33_2" > { > /* One of the ops has to be in a register. */ > if (!register_operand (operand1, SFmode) > && !register_operand (operand0, SFmode)) > - operands[1] = copy_to_mode_reg (SFmode, operand1); > -}") > + operands[1] = force_reg (SFmode, operand1); > +}) > > (define_insn "*movsf_internal" > - [(set (match_operand:SF 0 "nonimmediate_operand" > - ;; 0 1 2 3 4 5 > - "=fdxa, dxa, f, dxaQ, daxm, dax") > - (match_operand:SF 1 "general_operand" > - " 0, G, fdxaQF, f, dax, daxFm")) > - ] > - "register_operand (operands[0], SFmode) > - || register_operand (operands[1], SFmode)" > - "* > - { > - switch (which_alternative) > - { > - case 0: > - return \"nop\"; > - /* case 1: below. */ > - case 2: > - case 3: > - return \"fmov %1, %0\"; > - case 1: > - case 4: > - case 5: > - if (REGNO_REG_CLASS (true_regnum (operands[0])) == EXTENDED_REGS > - && CONST_INT_P (operands[1])) > - { > - HOST_WIDE_INT val = INTVAL (operands[1]); > - > - if (((val & 0x80) && ! (val & 0xffffff00)) > - || ((val & 0x800000) && ! (val & 0xff000000))) > - return \"movu %1, %0\"; > - } > - return \"mov %1, %0\"; > - default: > - gcc_unreachable (); > - } > - }" > - [(set_attr_alternative "timings" > - [(const_int 11) > - (if_then_else (eq_attr "cpu" "am34") > - (const_int 13) (const_int 24)) > - (if_then_else (eq_attr "cpu" "am34") > - (const_int 47) (const_int 25)) > - (if_then_else (eq_attr "cpu" "am34") > - (const_int 47) (const_int 25)) > - (if_then_else (eq_attr "cpu" "am34") > - (const_int 13) (const_int 24)) > - (if_then_else (eq_attr "cpu" "am34") > - (const_int 13) (const_int 24)) > - ]) > - ] > -) > - > -(define_expand "movdi" > - [(set (match_operand:DI 0 "nonimmediate_operand") > - (match_operand:DI 1 "general_operand"))] > - "" > - " > -{ > - /* One of the ops has to be in a register. */ > - if (!register_operand (operand1, DImode) > - && !register_operand (operand0, DImode)) > - operands[1] = copy_to_mode_reg (DImode, operand1); > -}") > - > - > -(define_insn "*movdi_internal" ;; 0 1 2 3 4 5 6 7 8 9 > - [(set (match_operand:DI 0 "nonimmediate_operand" "=dx,ax,dx,a,dxm,dxm,a, a,dx,a") > - (match_operand:DI 1 "general_operand" "0,0, I, I,dx, a, dx,a,im,im"))] > - "register_operand (operands[0], DImode) > - || register_operand (operands[1], DImode)" > - "* > + [(set (match_operand:SF 0 "nonimmediate_operand" "=rf,r,f,r,f,r,f,r,m,f,Q") > + (match_operand:SF 1 "general_operand" " 0,F,F,r,f,f,r,m,r,Q,f"))] > + "TARGET_AM33_2 > + && (register_operand (operands[0], SFmode) > + || register_operand (operands[1], SFmode))" > { > - long val[2]; > - REAL_VALUE_TYPE rv; > - > switch (which_alternative) > { > - case 0: > - case 1: > - return \"nop\"; > - > - case 2: > - return \"mov 0, %L0\;mov 0, %H0\"; > - > - case 3: > - if (rtx_equal_p (operands[0], operands[1])) > - return \"sub %L1,%L0\;mov %L0,%H0\"; > - else > - return \"mov %1,%L0\;mov %L0,%H0\"; > - case 4: > - case 5: > - case 6: > - case 7: > - case 8: > - case 9: > - if (CONST_INT_P (operands[1])) > - { > - rtx low, high; > - split_double (operands[1], &low, &high); > - val[0] = INTVAL (low); > - val[1] = INTVAL (high); > - } > - if (CONST_DOUBLE_P (operands[1])) > - { > - if (GET_MODE (operands[1]) == DFmode) > - { > - REAL_VALUE_FROM_CONST_DOUBLE (rv, operands[1]); > - REAL_VALUE_TO_TARGET_DOUBLE (rv, val); > - } > - else if (GET_MODE (operands[1]) == VOIDmode > - || GET_MODE (operands[1]) == DImode) > - { > - val[0] = CONST_DOUBLE_LOW (operands[1]); > - val[1] = CONST_DOUBLE_HIGH (operands[1]); > - } > - } > - > - if (MEM_P (operands[1]) > - && reg_overlap_mentioned_p (operands[0], XEXP (operands[1], 0))) > - { > - rtx temp = operands[0]; > - > - while (GET_CODE (temp) == SUBREG) > - temp = SUBREG_REG (temp); > - > - gcc_assert (REG_P (temp)); > - > - if (reg_overlap_mentioned_p (gen_rtx_REG (SImode, REGNO (temp)), > - XEXP (operands[1], 0))) > - return \"mov %H1,%H0\;mov %L1,%L0\"; > - else > - return \"mov %L1,%L0\;mov %H1,%H0\"; > - > - } > - else if (MEM_P (operands[1]) > - && CONSTANT_ADDRESS_P (XEXP (operands[1], 0)) > - && REGNO_REG_CLASS (REGNO (operands[0])) == ADDRESS_REGS) > - { > - rtx xoperands[2]; > - > - xoperands[0] = operands[0]; > - xoperands[1] = XEXP (operands[1], 0); > - > - output_asm_insn (\"mov %1,%L0\;mov (4,%L0),%H0\;mov (%L0),%L0\", > - xoperands); > - return \"\"; > - } > - else > - { > - if ((CONST_INT_P (operands[1]) > - || CONST_DOUBLE_P (operands[1])) > - && val[0] == 0) > - { > - if (REGNO_REG_CLASS (REGNO (operands[0])) == DATA_REGS) > - output_asm_insn (\"mov 0, %L0\", operands); > - else > - output_asm_insn (\"mov %L1,%L0\", operands); > - } > - else if ((CONST_INT_P (operands[1]) > - || CONST_DOUBLE_P (operands[1])) > - && (REGNO_REG_CLASS (true_regnum (operands[0])) > - == EXTENDED_REGS) > - && (((val[0] & 0x80) && ! (val[0] & 0xffffff00)) > - || ((val[0] & 0x800000) && ! (val[0] & 0xff000000)))) > - output_asm_insn (\"movu %L1,%L0\", operands); > - else > - output_asm_insn (\"mov %L1,%L0\", operands); > - > - if ((CONST_INT_P (operands[1]) > - || CONST_DOUBLE_P (operands[1])) > - && val[1] == 0) > - { > - if (REGNO_REG_CLASS (REGNO (operands[0])) == DATA_REGS) > - output_asm_insn (\"mov 0, %H0\", operands); > - else > - output_asm_insn (\"mov %H1,%H0\", operands); > - } > - else if ((CONST_INT_P (operands[1]) > - || CONST_DOUBLE_P (operands[1])) > - && val[0] == val[1]) > - output_asm_insn (\"mov %L0,%H0\", operands); > - else if ((CONST_INT_P (operands[1]) > - || CONST_DOUBLE_P (operands[1])) > - && (REGNO_REG_CLASS (true_regnum (operands[0])) > - == EXTENDED_REGS) > - && (((val[1] & 0x80) && ! (val[1] & 0xffffff00)) > - || ((val[1] & 0x800000) && ! (val[1] & 0xff000000)))) > - output_asm_insn (\"movu %H1,%H0\", operands); > - else > - output_asm_insn (\"mov %H1,%H0\", operands); > - return \"\"; > - } > - default: > - gcc_unreachable (); > - } > - }" > - ;; The timing of "37" is an approximation of the worst case sceanario. > - [(set_attr_alternative "timings" > - [(const_int 11) > - (const_int 11) > - (const_int 22) > - (const_int 22) > - (const_int 37) > - (const_int 37) > - (const_int 37) > - (const_int 37) > - (const_int 37) > - (const_int 37) > - ]) > - ] > -) > - > -(define_expand "movdf" > - [(set (match_operand:DF 0 "nonimmediate_operand") > - (match_operand:DF 1 "general_operand"))] > - "" > - " > -{ > - /* One of the ops has to be in a register. */ > - if (!register_operand (operand1, DFmode) > - && !register_operand (operand0, DFmode)) > - operands[1] = copy_to_mode_reg (DFmode, operand1); > -}") > - > -(define_insn "*am33_2_movdf" > - [(set (match_operand:DF 0 "nonimmediate_operand" > - ;; 0 1 2 3 4 5 6 7 8 9 10 11 > - "=fdax,dax,fdxa,f, f,Q,dxm,dxm,a, a,dx,a") > - (match_operand:DF 1 "general_operand" > - " 0, G, f, dxaF,Q,f,dx, a, dx,a,Fm,Fm"))] > - "TARGET_AM33_2 > - && (register_operand (operands[0], DFmode) > - || register_operand (operands[1], DFmode))" > - "* > - { > - long val[2]; > - REAL_VALUE_TYPE rv; > - > - switch (which_alternative) > - { > - case 0: > - return \"nop\"; > - > - case 1: > - return \"mov 0, %L0\; mov 0, %H0\"; > - > - case 2: > - case 3: > - return \"fmov %L1, %L0\; fmov %H1, %H0\"; > - > - case 4: > - if (MEM_P (operands[1]) > - && CONST_INT_P (XEXP (operands[1], 0)) > - && (INTVAL (XEXP (operands[1], 0)) & 7) == 0) > - return \"fmov %D1, %D0\"; > - else > - return \"fmov %L1, %L0\; fmov %H1, %H0\"; > - > - case 5: > - if (MEM_P (operands[0]) > - && CONST_INT_P (XEXP (operands[0], 0)) > - && (INTVAL (XEXP (operands[0], 0)) & 7) == 0) > - return \"fmov %D1, %D0\"; > - else > - return \"fmov %L1, %L0\; fmov %H1, %H0\"; > - > - case 6: > - case 7: > - case 8: > - case 9: > - case 10: > - case 11: > - if (CONST_INT_P (operands[1])) > - { > - rtx low, high; > - split_double (operands[1], &low, &high); > - val[0] = INTVAL (low); > - val[1] = INTVAL (high); > - } > - if (CONST_DOUBLE_P (operands[1])) > - { > - if (GET_MODE (operands[1]) == DFmode) > - { > - REAL_VALUE_FROM_CONST_DOUBLE (rv, operands[1]); > - REAL_VALUE_TO_TARGET_DOUBLE (rv, val); > - } > - else if (GET_MODE (operands[1]) == VOIDmode > - || GET_MODE (operands[1]) == DImode) > - { > - val[0] = CONST_DOUBLE_LOW (operands[1]); > - val[1] = CONST_DOUBLE_HIGH (operands[1]); > - } > - } > - > - if (MEM_P (operands[1]) > - && reg_overlap_mentioned_p (operands[0], XEXP (operands[1], 0))) > - { > - rtx temp = operands[0]; > - > - while (GET_CODE (temp) == SUBREG) > - temp = SUBREG_REG (temp); > - > - gcc_assert (REG_P (temp)); > - > - if (reg_overlap_mentioned_p (gen_rtx_REG (SImode, REGNO (temp)), > - XEXP (operands[1], 0))) > - return \"mov %H1, %H0\; mov %L1, %L0\"; > - else > - return \"mov %L1, %L0\; mov %H1, %H0\"; > - > - } > - else if (MEM_P (operands[1]) > - && CONSTANT_ADDRESS_P (XEXP (operands[1], 0)) > - && REGNO_REG_CLASS (REGNO (operands[0])) == ADDRESS_REGS) > - { > - rtx xoperands[2]; > - > - xoperands[0] = operands[0]; > - xoperands[1] = XEXP (operands[1], 0); > - > - output_asm_insn (\"mov %1, %L0\; mov (4, %L0), %H0\; mov (%L0), %L0\", > - xoperands); > - return \"\"; > - } > - else > - { > - if ((CONST_INT_P (operands[1]) > - || CONST_DOUBLE_P (operands[1])) > - && val[0] == 0) > - { > - if (REGNO_REG_CLASS (REGNO (operands[0])) == DATA_REGS) > - output_asm_insn (\"mov 0, %L0\", operands); > - else > - output_asm_insn (\"mov %L1,%L0\", operands); > - } > - else if ((CONST_INT_P (operands[1]) > - || CONST_DOUBLE_P (operands[1])) > - && (REGNO_REG_CLASS (true_regnum (operands[0])) > - == EXTENDED_REGS) > - && (((val[0] & 0x80) && ! (val[0] & 0xffffff00)) > - || ((val[0] & 0x800000) && ! (val[0] & 0xff000000)))) > - output_asm_insn (\"movu %L1, %L0\", operands); > - else > - output_asm_insn (\"mov %L1, %L0\", operands); > - > - if ((CONST_INT_P (operands[1]) > - || CONST_DOUBLE_P (operands[1])) > - && val[1] == 0) > - { > - if (REGNO_REG_CLASS (REGNO (operands[0])) == DATA_REGS) > - output_asm_insn (\"mov 0, %H0\", operands); > - else > - output_asm_insn (\"mov %H1, %H0\", operands); > - } > - else if ((CONST_INT_P (operands[1]) > - || CONST_DOUBLE_P (operands[1])) > - && val[0] == val[1]) > - output_asm_insn (\"mov %L0,%H0\", operands); > - else if ((CONST_INT_P (operands[1]) > - || CONST_DOUBLE_P (operands[1])) > - && (REGNO_REG_CLASS (true_regnum (operands[0])) > - == EXTENDED_REGS) > - && (((val[1] & 0x80) && ! (val[1] & 0xffffff00)) > - || ((val[1] & 0x800000) && ! (val[1] & 0xff000000)))) > - output_asm_insn (\"movu %H1, %H0\", operands); > - else > - output_asm_insn (\"mov %H1, %H0\", operands); > - return \"\"; > - } > + case 0: > + return ""; > + case 1: > + case 3: > + case 7: > + case 8: > + return "mov %1,%0"; > + case 2: > + case 4: > + case 5: > + case 6: > + case 9: > + case 10: > + return "fmov %1,%0"; > default: > gcc_unreachable (); > } > - }" > - ;; The timing of "37" is an approximation of the worst case sceanario. > +} > [(set_attr_alternative "timings" > - [(const_int 11) > - (const_int 22) > - (const_int 22) > - (const_int 22) > - (const_int 22) > - (const_int 37) > - (const_int 37) > - (const_int 37) > - (const_int 37) > - (const_int 37) > - (const_int 37) > - (const_int 37) > - ]) > - ] > + [(const_int 11) > + (const_int 22) > + (if_then_else (eq_attr "cpu" "am34") > + (const_int 47) (const_int 25)) > + (const_int 11) > + (if_then_else (eq_attr "cpu" "am34") > + (const_int 13) (const_int 14)) > + (if_then_else (eq_attr "cpu" "am34") > + (const_int 13) (const_int 12)) > + (if_then_else (eq_attr "cpu" "am34") > + (const_int 13) (const_int 14)) > + (if_then_else (eq_attr "cpu" "am34") > + (const_int 13) (const_int 24)) > + (if_then_else (eq_attr "cpu" "am34") > + (const_int 13) (const_int 24)) > + (if_then_else (eq_attr "cpu" "am34") > + (const_int 13) (const_int 24)) > + (if_then_else (eq_attr "cpu" "am34") > + (const_int 13) (const_int 24)) > + ])] > ) > > -(define_insn "*mn10300_movdf" > - [(set (match_operand:DF 0 "nonimmediate_operand" > - ;;0 1 2 3 4 5 6 7 > - "=dxa, dax, dxm, dxm, a, a, dx, a") > - (match_operand:DF 1 "general_operand" > - " 0, G, dx, a, dx, a, Fm, Fm"))] > - "register_operand (operands[0], DFmode) > - || register_operand (operands[1], DFmode)" > - "* > - { > - long val[2]; > - REAL_VALUE_TYPE rv; > - > - switch (which_alternative) > - { > - case 0: > - return \"nop\"; > - > - case 1: > - return \"mov 0, %L0\; mov 0, %H0\"; > - > - case 2: > - case 3: > - case 4: > - case 5: > - case 6: > - case 7: > - if (CONST_INT_P (operands[1])) > - { > - rtx low, high; > - split_double (operands[1], &low, &high); > - val[0] = INTVAL (low); > - val[1] = INTVAL (high); > - } > - if (CONST_DOUBLE_P (operands[1])) > - { > - if (GET_MODE (operands[1]) == DFmode) > - { > - REAL_VALUE_FROM_CONST_DOUBLE (rv, operands[1]); > - REAL_VALUE_TO_TARGET_DOUBLE (rv, val); > - } > - else if (GET_MODE (operands[1]) == VOIDmode > - || GET_MODE (operands[1]) == DImode) > - { > - val[0] = CONST_DOUBLE_LOW (operands[1]); > - val[1] = CONST_DOUBLE_HIGH (operands[1]); > - } > - } > - > - if (MEM_P (operands[1]) > - && reg_overlap_mentioned_p (operands[0], XEXP (operands[1], 0))) > - { > - rtx temp = operands[0]; > - > - while (GET_CODE (temp) == SUBREG) > - temp = SUBREG_REG (temp); > - > - gcc_assert (REG_P (temp)); > - > - if (reg_overlap_mentioned_p (gen_rtx_REG (SImode, REGNO (temp)), > - XEXP (operands[1], 0))) > - return \"mov %H1, %H0\; mov %L1, %L0\"; > - else > - return \"mov %L1, %L0\; mov %H1, %H0\"; > - } > - else if (MEM_P (operands[1]) > - && CONSTANT_ADDRESS_P (XEXP (operands[1], 0)) > - && REGNO_REG_CLASS (REGNO (operands[0])) == ADDRESS_REGS) > - { > - rtx xoperands[2]; > - > - xoperands[0] = operands[0]; > - xoperands[1] = XEXP (operands[1], 0); > - > - output_asm_insn (\"mov %1, %L0\; mov (4, %L0), %H0\; mov (%L0), %L0\", > - xoperands); > - return \"\"; > - } > - else > - { > - if ((CONST_INT_P (operands[1]) > - || CONST_DOUBLE_P (operands[1])) > - && val[0] == 0) > - { > - if (REGNO_REG_CLASS (REGNO (operands[0])) == DATA_REGS) > - output_asm_insn (\"mov 0, %L0\", operands); > - else > - output_asm_insn (\"mov %L1, %L0\", operands); > - } > - else if ((CONST_INT_P (operands[1]) > - || CONST_DOUBLE_P (operands[1])) > - && (REGNO_REG_CLASS (true_regnum (operands[0])) > - == EXTENDED_REGS) > - && (((val[0] & 0x80) && ! (val[0] & 0xffffff00)) > - || ((val[0] & 0x800000) && ! (val[0] & 0xff000000)))) > - output_asm_insn (\"movu %L1, %L0\", operands); > - else > - output_asm_insn (\"mov %L1, %L0\", operands); > - > - if ((CONST_INT_P (operands[1]) > - || CONST_DOUBLE_P (operands[1])) > - && val[1] == 0) > - { > - if (REGNO_REG_CLASS (REGNO (operands[0])) == DATA_REGS) > - output_asm_insn (\"mov 0, %H0\", operands); > - else > - output_asm_insn (\"mov %H1, %H0\", operands); > - } > - else if ((CONST_INT_P (operands[1]) > - || CONST_DOUBLE_P (operands[1])) > - && val[0] == val[1]) > - output_asm_insn (\"mov %L0, %H0\", operands); > - else if ((CONST_INT_P (operands[1]) > - || CONST_DOUBLE_P (operands[1])) > - && (REGNO_REG_CLASS (true_regnum (operands[0])) > - == EXTENDED_REGS) > - && (((val[1] & 0x80) && ! (val[1] & 0xffffff00)) > - || ((val[1] & 0x800000) && ! (val[1] & 0xff000000)))) > - output_asm_insn (\"movu %H1, %H0\", operands); > - else > - output_asm_insn (\"mov %H1, %H0\", operands); > - return \"\"; > - } > - default: > - gcc_unreachable (); > - } > - }" > - ;; Timings of "37" is approximation of the worst case sceanario. > - [(set_attr_alternative "timings" > - [(const_int 11) > - (const_int 22) > - (const_int 37) > - (const_int 37) > - (const_int 37) > - (const_int 37) > - (const_int 37) > - (const_int 37) > - ]) > - ] > -) > > ;; ---------------------------------------------------------------------- > ;; ADD INSTRUCTIONS > @@ -1363,42 +762,23 @@ > (const_int 24) (const_int 23)))] > ) > > -(define_expand "udivmodsi4" > - [(parallel [(set (match_operand:SI 0 "register_operand") > - (udiv:SI (match_operand:SI 1 "general_operand") > - (match_operand:SI 2 "general_operand"))) > - (set (match_operand:SI 3 "register_operand") > - (umod:SI (match_dup 1) (match_dup 2))) > - (clobber (reg:CC CC_REG)) > - ]) > - ] > - "" > - "{ > - if (!register_operand (operands[1], SImode)) > - operands[1] = copy_to_mode_reg (SImode, operands[1]); > - if (!register_operand (operands[2], SImode)) > - operands[2] = copy_to_mode_reg (SImode, operands[2]); > - }" > -) > - > -(define_insn "*udivmodsi4" > - [(set (match_operand:SI 0 "register_operand" "=dx") > +;; ??? This pattern causes too-high register pressure for MN103. > +;; ??? To be fixed by exposing the MDR register properly. > +(define_insn "udivmodsi4" > + [(set (match_operand:SI 0 "register_operand" "=D") > (udiv:SI (match_operand:SI 1 "register_operand" "0") > - (match_operand:SI 2 "register_operand" "dx"))) > + (match_operand:SI 2 "register_operand" "D"))) > (set (match_operand:SI 3 "register_operand" "=&d") > (umod:SI (match_dup 1) (match_dup 2))) > - (clobber (reg:CC CC_REG)) > - ] > - "" > - "* > + (clobber (reg:CC CC_REG))] > + "TARGET_AM33" > { > - output_asm_insn (\"sub %3,%3\;mov %3,mdr\", operands); > - > + output_asm_insn ("clr %3\;ext %3", operands); > if (find_reg_note (insn, REG_UNUSED, operands[3])) > - return \"divu %2,%0\"; > + return "divu %2,%0"; > else > - return \"divu %2,%0\;mov mdr,%3\"; > -}" > + return "divu %2,%0\;mov mdr,%3"; > +} > ;; Timings: AM33 AM34 > ;; SUB 1/1 1/1 > ;; MOV 1/1 1/1 > @@ -1410,6 +790,28 @@ > (const_int 4546) (const_int 4142)))] > ) > > +;; ??? In the meantime MN103 can use these two patterns, > +;; which reduce the register pressure by one. > +(define_insn "udivsi3" > + [(set (match_operand:SI 0 "register_operand" "=&d") > + (udiv:SI (match_operand:SI 1 "register_operand" "d") > + (match_operand:SI 2 "register_operand" "d"))) > + (clobber (reg:CC CC_REG))] > + "!TARGET_AM33" > + "clr %0\;ext %0\;mov %1,%0\;divu %2,%0" > + [(set_attr "timings" "4142")] > +) > + > +(define_insn "umodsi3" > + [(set (match_operand:SI 0 "register_operand" "=&d") > + (umod:SI (match_operand:SI 1 "register_operand" "d") > + (match_operand:SI 2 "register_operand" "d"))) > + (clobber (reg:CC CC_REG))] > + "!TARGET_AM33" > + "clr %0\;ext %0\;mov %1,%0\;divu %2,%0\;mov mdr,%0" > + [(set_attr "timings" "4142")] > +) > + > (define_insn "divmodsi4" > [(set (match_operand:SI 0 "register_operand" "=dx") > (div:SI (match_operand:SI 1 "register_operand" "0") -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.11 (GNU/Linux) Comment: Using GnuPG with Fedora - http://enigmail.mozdev.org/ iQEcBAEBAgAGBQJNNce0AAoJEBRtltQi2kC7xYMH/2Ak9sB1KWEPkb7r2XSC5Gvu vZ/TjCQ+glV53LBJNtDzBo4D2QGrY576ex5aYRjmwsmwKItnjAezIIJk2VHRxXVv 7lsTpG8qT2iNbj8NQW8g30Vh6SGok7zd3vNZ4t7YztHV89LDSOmaRwtGktiTDhPu F9k+CBqqFeZukAGDTYGHLFw1XHqsJJ57X9WzCOiS14zRAFiIeWCnqbZgDk/VRRuL XJn0EPCCGDiBfh2L/2BmVGYfZ3Cmfzg5WvDij63UPXaVTocRMORsR231UA3eoo+P fJ2s293SncpGCAdieJZZs1Kb/qu0Gj35VS9Xo+mKvOIf6DS1ybCqFFHkj/4AIjc= =S+LB -----END PGP SIGNATURE-----
On 01/18/2011 09:02 AM, Jeff Law wrote: > IIRC returning an empty string for that case didn't work because the > empty string had some kind of special meaning in final. (This was 13 or > 14 years ago, so please forgive the IIRC's :-) > > The net result is I think you have to return something for those > alternatives rather than an empty string. Not since I've been working on GCC. We do this a lot -- emit stuff by hand then return "" to tell final that nothing else need be output. If you insist, we can continue to return nop here, but I don't think it's necessary. > It also seems to me that for movqi/movhi we want to severely disparage > the address regs on the mn103. IIRC for the base mn103 we would trigger > reload failures if we didn't expose a0-a3 to the movqi/movhi patterns. > However, while the a0-a3 regs can hold such values, they can't be used > in arithmetic/logicals/etc in QI/HI mode. So to avoid pessimizing code > we exposed a0-a3 in the QI/HI mode moves, but ignored them for register > class preferencing and severely disparaged them for reloading. I have ignored them for register class preferencing: > +(define_insn "*movqi_internal" > + [(set (match_operand:QI 0 "nonimmediate_operand" "=*r,D*r,D*r,D,m") > + (match_operand:QI 1 "general_operand" " 0,D*r, i,m,D"))] Note that for mn103, D*r resolves to a DATA_REGS preference, with GENERAL_REGS used for the legal register set. As for pessimising, I'm not sure what else really needs to be done, given that the only other operation for which Q/HImode is valid is extension. > It also looks like you lost the movu am33 variant for movqi/movhi. I > don't recall anything about that alternative, but I can hazard a guess > that movu is smaller than the more generic mov instruction for certain > constants. It is still present in movhi: > case 1: > + if (TARGET_AM33 > + && CONST_INT_P (operands[1]) > + && IN_RANGE (INTVAL (operands[1]), 0x80, 0xff)) > + return "movu %1,%0"; What I dropped were the useless extra tests for movu. There's no point in loading 0x80 via movu when -128 via mov is 1 byte smaller for QImode. > It looks like you lost movu for the base mn103 in the movsi pattern and > for all the parts in the movsf pattern (it may not matter there). Err, base mn103 doesn't have movu at all. As for movsf, movu would only be usable for a small set of subnormal operands. Combine that with wanting to load that subnormal into an integer register, as opposed to a floating-point register, and I think that is rare enough not to be useful. It does look as if I'm missing an EXTENDED_REGISTER check there in some of the tests; the sizes of mov imm vary a bit between data, addr, and extended register sets... r~
-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 On 01/18/11 11:13, Richard Henderson wrote: > On 01/18/2011 09:02 AM, Jeff Law wrote: >> IIRC returning an empty string for that case didn't work because the >> empty string had some kind of special meaning in final. (This was 13 or >> 14 years ago, so please forgive the IIRC's :-) >> >> The net result is I think you have to return something for those >> alternatives rather than an empty string. > > Not since I've been working on GCC. We do this a lot -- emit stuff by > hand then return "" to tell final that nothing else need be output. If > you insist, we can continue to return nop here, but I don't think it's > necessary. I'll go with your call on this one. There was certainly some reason I didn't do this before, but I simply can't remember what it was... I thought I'd documented this nonsense thoroughly in a long block comment, but I can't seem to find it anywhere. > > As for pessimising, I'm not sure what else really needs to be done, given > that the only other operation for which Q/HImode is valid is extension. I think what may have tended to happen is with the '!' for A regs was that we could use an address register for a source/destination in a movqi/movhi since it didn't need reloads. In some cases that's sufficient to keep reload happy. I'm willing to hope that Bernd's work from 1998 & IRA would minimize the chances of running into those problems again. On top of that, I suspect nobody is still using the base mn103 anymore. There's also the slim possibility that this was a mn102 problem and I carried the changes into the mn103 port. > >> It also looks like you lost the movu am33 variant for movqi/movhi. I >> don't recall anything about that alternative, but I can hazard a guess >> that movu is smaller than the more generic mov instruction for certain >> constants. > > It is still present in movhi: > >> case 1: >> + if (TARGET_AM33 >> + && CONST_INT_P (operands[1]) >> + && IN_RANGE (INTVAL (operands[1]), 0x80, 0xff)) >> + return "movu %1,%0"; > > What I dropped were the useless extra tests for movu. There's no point > in loading 0x80 via movu when -128 via mov is 1 byte smaller for QImode. Ok. As I mentioned, I don't have any recollection of movu, so if your sequence is smaller, that's all good :-) Jeff -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.11 (GNU/Linux) Comment: Using GnuPG with Fedora - http://enigmail.mozdev.org/ iQEcBAEBAgAGBQJNNwo5AAoJEBRtltQi2kC78i8H/RX3QLkdkriMLgoqxrXOcSL5 K9uGc/icLZfhGiDyNXuQ5gQV8PaczETw5WKu9IJImh7Kh25Lm8Ekn2hcmxn04uoJ nB5D+sl7ro+80Dev/tsCU/qawvz7YY9WCbEueOlMo9Yo5MHiCJ0hAHv+cBO8w2xM dEyMy6fBZ9BE7NuUwRnu24BbR90VnNrNUbSfR1s5LOWuj1+5amU0TkPQdJ18wOjp C+djO8OPNjgrc3qIklBUhRKdaYnMuS+KkRd2SszqRBft5o7Ue7XPfzUhdfnjzmUU Blyo1qzDviuGXNNgVpJVU5rFCf/LtmJCj8gnb34AW008UEQbwIuJrK/clO9QPGk= =Wtn5 -----END PGP SIGNATURE-----
On Wed, 19 Jan 2011, Jeff Law wrote: > On 01/18/11 11:13, Richard Henderson wrote: > > On 01/18/2011 09:02 AM, Jeff Law wrote: > >> IIRC returning an empty string for that case didn't work because the > >> empty string had some kind of special meaning in final. (This was 13 or > >> 14 years ago, so please forgive the IIRC's :-) > >> > >> The net result is I think you have to return something for those > >> alternatives rather than an empty string. > > > > Not since I've been working on GCC. We do this a lot -- emit stuff by > > hand then return "" to tell final that nothing else need be output. If > > you insist, we can continue to return nop here, but I don't think it's > > necessary. > I'll go with your call on this one. There was certainly some reason I > didn't do this before, but I simply can't remember what it was... I > thought I'd documented this nonsense thoroughly in a long block comment, > but I can't seem to find it anywhere. Regarding the special-empty-string-meaning, maybe you were thinking of branch patterns that should return NULL when, for CC0 targets, e.g. cc_status indicates an invalid removal of a compare insn, such that final_scan_insn has to put it back: /* If the C code returns 0, it means that it is a jump insn which follows a deleted test insn, and that test insn needs to be reinserted. */ (Whoops, not inside #ifdef HAVE_cc0; dunno when else it can happen.) brgds, H-P
diff --git a/gcc/config/mn10300/mn10300.md b/gcc/config/mn10300/mn10300.md index 04ec1b1..6e0e1a2 100644 --- a/gcc/config/mn10300/mn10300.md +++ b/gcc/config/mn10300/mn10300.md @@ -181,107 +181,42 @@ [(set (match_operand:QI 0 "nonimmediate_operand") (match_operand:QI 1 "general_operand"))] "" - " { /* One of the ops has to be in a register. */ if (!register_operand (operand0, QImode) && !register_operand (operand1, QImode)) - operands[1] = copy_to_mode_reg (QImode, operand1); -}") - -(define_insn "*am33_movqi" - [(set (match_operand:QI 0 "nonimmediate_operand" - ;; 0 1 2 3 4 5 - "=d*x*a*f, d*x*a, d*x*a, m, *f, d*x*a") - (match_operand:QI 1 "general_operand" - "0, d*xai, m, d*xa, d*xa*f, *f"))] - "TARGET_AM33 - && (register_operand (operands[0], QImode) - || register_operand (operands[1], QImode))" - "* - { - switch (which_alternative) - { - case 0: - return \"nop\"; - case 1: - gcc_assert (! CONST_DOUBLE_P (operands[1])); - - if (REGNO_REG_CLASS (true_regnum (operands[0])) == EXTENDED_REGS - && CONST_INT_P (operands[1])) - { - HOST_WIDE_INT val = INTVAL (operands[1]); - - if (((val & 0x80) && ! (val & 0xffffff00)) - || ((val & 0x800000) && ! (val & 0xff000000))) - return \"movu %1,%0\"; - } - return \"mov %1,%0\"; - case 2: - case 3: - return \"movbu %1,%0\"; - case 4: - case 5: - return \"fmov %1,%0\"; - default: - gcc_unreachable (); - } - }" - [(set_attr_alternative "timings" - [(const_int 11) - (if_then_else (eq_attr "cpu" "am34") - (const_int 11) (const_int 22)) - (if_then_else (eq_attr "cpu" "am34") - (const_int 13) (const_int 24)) - (if_then_else (eq_attr "cpu" "am34") - (const_int 13) (const_int 24)) - (if_then_else (eq_attr "cpu" "am34") - (const_int 47) (const_int 25)) - (if_then_else (eq_attr "cpu" "am34") - (const_int 47) (const_int 25)) - ]) - ] -) + operands[1] = force_reg (QImode, operand1); +}) -(define_insn "*mn10300_movqi" - [(set (match_operand:QI 0 "nonimmediate_operand" "=d*a,d,d,!*a,d*a,d,m") - (match_operand:QI 1 "general_operand" "0, I,i,i, da, m,d"))] - "register_operand (operands[0], QImode) - || register_operand (operands[1], QImode)" - "* +(define_insn "*movqi_internal" + [(set (match_operand:QI 0 "nonimmediate_operand" "=*r,D*r,D*r,D,m") + (match_operand:QI 1 "general_operand" " 0,D*r, i,m,D"))] + "(register_operand (operands[0], QImode) + || register_operand (operands[1], QImode))" { switch (which_alternative) { case 0: - return \"nop\"; + return ""; case 1: case 2: + return "mov %1,%0"; case 3: case 4: - gcc_assert (! CONST_DOUBLE_P (operands[1])); - return \"mov %1,%0\"; - case 5: - case 6: - return \"movbu %1,%0\"; + return "movbu %1,%0"; default: gcc_unreachable (); } -}" +} [(set_attr_alternative "timings" - [(const_int 11) - (const_int 11) - (if_then_else (eq_attr "cpu" "am34") - (const_int 11) (const_int 22)) - (if_then_else (eq_attr "cpu" "am34") - (const_int 11) (const_int 22)) - (if_then_else (eq_attr "cpu" "am34") - (const_int 11) (const_int 22)) - (if_then_else (eq_attr "cpu" "am34") - (const_int 13) (const_int 24)) - (if_then_else (eq_attr "cpu" "am34") - (const_int 13) (const_int 24)) - ]) - ] + [(const_int 11) + (const_int 11) + (const_int 11) + (if_then_else (eq_attr "cpu" "am34") + (const_int 13) (const_int 24)) + (if_then_else (eq_attr "cpu" "am34") + (const_int 11) (const_int 22)) + ])] ) ;; movhi @@ -290,107 +225,48 @@ [(set (match_operand:HI 0 "nonimmediate_operand") (match_operand:HI 1 "general_operand"))] "" - " { /* One of the ops has to be in a register. */ if (!register_operand (operand1, HImode) && !register_operand (operand0, HImode)) - operands[1] = copy_to_mode_reg (HImode, operand1); -}") - -(define_insn "*am33_movhi" - [(set (match_operand:HI 0 "nonimmediate_operand" - ;; 0 1 2 3 4 5 - "=d*x*a*f, d*x*a, d*x*a, m, *f, d*x*a") - (match_operand:HI 1 "general_operand" - "0, d*x*ai, m, d*x*a, d*x*a*f, *f"))] - "TARGET_AM33 - && (register_operand (operands[0], HImode) - || register_operand (operands[1], HImode))" - "* -{ - switch (which_alternative) - { - case 0: - return \"nop\"; - case 1: - gcc_assert (! CONST_DOUBLE_P (operands[1])); - - if (REGNO_REG_CLASS (true_regnum (operands[0])) == EXTENDED_REGS - && CONST_INT_P (operands[1])) - { - HOST_WIDE_INT val = INTVAL (operands[1]); - - if (((val & 0x80) && ! (val & 0xffffff00)) - || ((val & 0x800000) && ! (val & 0xff000000))) - return \"movu %1,%0\"; - } - return \"mov %1,%0\"; - case 2: - case 3: - return \"movhu %1,%0\"; - case 4: - case 5: - return \"fmov %1,%0\"; - default: - gcc_unreachable (); - } -}" - [(set_attr_alternative "timings" - [(const_int 11) - (if_then_else (eq_attr "cpu" "am34") - (const_int 11) (const_int 22)) - (if_then_else (eq_attr "cpu" "am34") - (const_int 13) (const_int 24)) - (if_then_else (eq_attr "cpu" "am34") - (const_int 13) (const_int 24)) - (if_then_else (eq_attr "cpu" "am34") - (const_int 47) (const_int 25)) - (if_then_else (eq_attr "cpu" "am34") - (const_int 47) (const_int 25)) - ]) - ] -) + operands[1] = force_reg (HImode, operand1); +}) -(define_insn "*mn10300_movhi" - [(set (match_operand:HI 0 "nonimmediate_operand" "=d*a,d,d,!*a,d*a,d,m") - (match_operand:HI 1 "general_operand" "0, I,i,i, da, m,d"))] - "register_operand (operands[0], HImode) - || register_operand (operands[1], HImode)" - "* +(define_insn "*movhi_internal" + [(set (match_operand:HI 0 "nonimmediate_operand" "=*r,D*r,D*r,D,m") + (match_operand:HI 1 "general_operand" " 0, i,D*r,m,D"))] + "(register_operand (operands[0], HImode) + || register_operand (operands[1], HImode))" { switch (which_alternative) { case 0: - return \"nop\"; + return ""; case 1: + if (TARGET_AM33 + && CONST_INT_P (operands[1]) + && IN_RANGE (INTVAL (operands[1]), 0x80, 0xff)) + return "movu %1,%0"; + /* FALLTHRU */ case 2: + return "mov %1,%0"; case 3: case 4: - gcc_assert (! CONST_DOUBLE_P (operands[1])); - return \"mov %1,%0\"; - case 5: - case 6: - return \"movhu %1,%0\"; + return "movhu %1,%0"; default: gcc_unreachable (); } -}" +} [(set_attr_alternative "timings" - [(const_int 11) - (const_int 11) - (if_then_else (eq_attr "cpu" "am34") - (const_int 11) (const_int 22)) - (if_then_else (eq_attr "cpu" "am34") - (const_int 11) (const_int 22)) - (if_then_else (eq_attr "cpu" "am34") - (const_int 11) (const_int 22)) - (if_then_else (eq_attr "cpu" "am34") - (const_int 13) (const_int 24)) - (if_then_else (eq_attr "cpu" "am34") - (const_int 13) (const_int 24)) - ]) - ] + [(const_int 11) + (const_int 11) + (if_then_else (eq_attr "cpu" "am34") + (const_int 11) (const_int 22)) + (if_then_else (eq_attr "cpu" "am34") + (const_int 13) (const_int 24)) + (if_then_else (eq_attr "cpu" "am34") + (const_int 11) (const_int 22)) + ])] ) ;; movsi and helpers @@ -450,12 +326,11 @@ [(set (match_operand:SI 0 "nonimmediate_operand") (match_operand:SI 1 "general_operand"))] "" - " { /* One of the ops has to be in a register. */ if (!register_operand (operand1, SImode) && !register_operand (operand0, SImode)) - operands[1] = copy_to_mode_reg (SImode, operand1); + operands[1] = force_reg (SImode, operand1); if (flag_pic) { rtx temp; @@ -486,594 +361,118 @@ 0, OPTAB_LIB_WIDEN); } } -}") +}) (define_insn "*movsi_internal" [(set (match_operand:SI 0 "nonimmediate_operand" - "=dax, dax, m, dax, ax,!*y") + "=r,r,r,m,r, A,*y,*y") (match_operand:SI 1 "general_operand" - "0, Idax, dax, im, !*y, ax")) - ] + " 0,i,r,r,m,*y, A, i"))] "register_operand (operands[0], SImode) || register_operand (operands[1], SImode)" - "* - { - if (which_alternative == 0) - return \"nop\"; - - gcc_assert (! CONST_DOUBLE_P (operands[1])); - - if (REGNO_REG_CLASS (true_regnum (operands[0])) == EXTENDED_REGS - && CONST_INT_P (operands[1])) - { - HOST_WIDE_INT val = INTVAL (operands[1]); - - if (((val & 0x80) && ! (val & 0xffffff00)) - || ((val & 0x800000) && ! (val & 0xff000000))) - return \"movu %1, %0\"; - } - - return \"mov %1, %0\"; - }" - [(set_attr_alternative "timings" - [(const_int 11) - (if_then_else (eq_attr "cpu" "am34") - (const_int 13) (const_int 24)) - (if_then_else (eq_attr "cpu" "am34") - (const_int 13) (const_int 24)) - (if_then_else (eq_attr "cpu" "am34") - (const_int 13) (const_int 24)) - (if_then_else (eq_attr "cpu" "am34") - (const_int 13) (const_int 24)) - (if_then_else (eq_attr "cpu" "am34") - (const_int 13) (const_int 24)) - ]) - ] +{ + switch (which_alternative) + { + case 0: + return ""; + case 1: /* imm-reg*/ + if (TARGET_AM33 && CONST_INT_P (operands[1])) + { + HOST_WIDE_INT val = INTVAL (operands[1]); + if (IN_RANGE (val, 0x80, 0xff) + || IN_RANGE (val, 0x800000, 0xffffff)) + return "movu %1,%0"; + } + /* FALLTHRU */ + case 2: /* reg-reg */ + case 3: /* reg-mem */ + case 4: /* mem-reg */ + case 5: /* sp-reg */ + case 6: /* reg-sp */ + case 7: /* imm-sp */ + return "mov %1,%0"; + default: + gcc_unreachable (); + } +} + [(set_attr "isa" "*,*,*,*,*,*,*,am33") + (set_attr_alternative "timings" + [(const_int 11) + (const_int 22) + (const_int 11) + (if_then_else (eq_attr "cpu" "am34") + (const_int 11) (const_int 22)) + (if_then_else (eq_attr "cpu" "am34") + (const_int 13) (const_int 24)) + (if_then_else (eq_attr "cpu" "am34") + (const_int 11) (const_int 22)) + (if_then_else (eq_attr "cpu" "am34") + (const_int 13) (const_int 24)) + (const_int 11) + ])] ) (define_expand "movsf" [(set (match_operand:SF 0 "nonimmediate_operand") (match_operand:SF 1 "general_operand"))] - "" - " + "TARGET_AM33_2" { /* One of the ops has to be in a register. */ if (!register_operand (operand1, SFmode) && !register_operand (operand0, SFmode)) - operands[1] = copy_to_mode_reg (SFmode, operand1); -}") + operands[1] = force_reg (SFmode, operand1); +}) (define_insn "*movsf_internal" - [(set (match_operand:SF 0 "nonimmediate_operand" - ;; 0 1 2 3 4 5 - "=fdxa, dxa, f, dxaQ, daxm, dax") - (match_operand:SF 1 "general_operand" - " 0, G, fdxaQF, f, dax, daxFm")) - ] - "register_operand (operands[0], SFmode) - || register_operand (operands[1], SFmode)" - "* - { - switch (which_alternative) - { - case 0: - return \"nop\"; - /* case 1: below. */ - case 2: - case 3: - return \"fmov %1, %0\"; - case 1: - case 4: - case 5: - if (REGNO_REG_CLASS (true_regnum (operands[0])) == EXTENDED_REGS - && CONST_INT_P (operands[1])) - { - HOST_WIDE_INT val = INTVAL (operands[1]); - - if (((val & 0x80) && ! (val & 0xffffff00)) - || ((val & 0x800000) && ! (val & 0xff000000))) - return \"movu %1, %0\"; - } - return \"mov %1, %0\"; - default: - gcc_unreachable (); - } - }" - [(set_attr_alternative "timings" - [(const_int 11) - (if_then_else (eq_attr "cpu" "am34") - (const_int 13) (const_int 24)) - (if_then_else (eq_attr "cpu" "am34") - (const_int 47) (const_int 25)) - (if_then_else (eq_attr "cpu" "am34") - (const_int 47) (const_int 25)) - (if_then_else (eq_attr "cpu" "am34") - (const_int 13) (const_int 24)) - (if_then_else (eq_attr "cpu" "am34") - (const_int 13) (const_int 24)) - ]) - ] -) - -(define_expand "movdi" - [(set (match_operand:DI 0 "nonimmediate_operand") - (match_operand:DI 1 "general_operand"))] - "" - " -{ - /* One of the ops has to be in a register. */ - if (!register_operand (operand1, DImode) - && !register_operand (operand0, DImode)) - operands[1] = copy_to_mode_reg (DImode, operand1); -}") - - -(define_insn "*movdi_internal" ;; 0 1 2 3 4 5 6 7 8 9 - [(set (match_operand:DI 0 "nonimmediate_operand" "=dx,ax,dx,a,dxm,dxm,a, a,dx,a") - (match_operand:DI 1 "general_operand" "0,0, I, I,dx, a, dx,a,im,im"))] - "register_operand (operands[0], DImode) - || register_operand (operands[1], DImode)" - "* + [(set (match_operand:SF 0 "nonimmediate_operand" "=rf,r,f,r,f,r,f,r,m,f,Q") + (match_operand:SF 1 "general_operand" " 0,F,F,r,f,f,r,m,r,Q,f"))] + "TARGET_AM33_2 + && (register_operand (operands[0], SFmode) + || register_operand (operands[1], SFmode))" { - long val[2]; - REAL_VALUE_TYPE rv; - switch (which_alternative) { - case 0: - case 1: - return \"nop\"; - - case 2: - return \"mov 0, %L0\;mov 0, %H0\"; - - case 3: - if (rtx_equal_p (operands[0], operands[1])) - return \"sub %L1,%L0\;mov %L0,%H0\"; - else - return \"mov %1,%L0\;mov %L0,%H0\"; - case 4: - case 5: - case 6: - case 7: - case 8: - case 9: - if (CONST_INT_P (operands[1])) - { - rtx low, high; - split_double (operands[1], &low, &high); - val[0] = INTVAL (low); - val[1] = INTVAL (high); - } - if (CONST_DOUBLE_P (operands[1])) - { - if (GET_MODE (operands[1]) == DFmode) - { - REAL_VALUE_FROM_CONST_DOUBLE (rv, operands[1]); - REAL_VALUE_TO_TARGET_DOUBLE (rv, val); - } - else if (GET_MODE (operands[1]) == VOIDmode - || GET_MODE (operands[1]) == DImode) - { - val[0] = CONST_DOUBLE_LOW (operands[1]); - val[1] = CONST_DOUBLE_HIGH (operands[1]); - } - } - - if (MEM_P (operands[1]) - && reg_overlap_mentioned_p (operands[0], XEXP (operands[1], 0))) - { - rtx temp = operands[0]; - - while (GET_CODE (temp) == SUBREG) - temp = SUBREG_REG (temp); - - gcc_assert (REG_P (temp)); - - if (reg_overlap_mentioned_p (gen_rtx_REG (SImode, REGNO (temp)), - XEXP (operands[1], 0))) - return \"mov %H1,%H0\;mov %L1,%L0\"; - else - return \"mov %L1,%L0\;mov %H1,%H0\"; - - } - else if (MEM_P (operands[1]) - && CONSTANT_ADDRESS_P (XEXP (operands[1], 0)) - && REGNO_REG_CLASS (REGNO (operands[0])) == ADDRESS_REGS) - { - rtx xoperands[2]; - - xoperands[0] = operands[0]; - xoperands[1] = XEXP (operands[1], 0); - - output_asm_insn (\"mov %1,%L0\;mov (4,%L0),%H0\;mov (%L0),%L0\", - xoperands); - return \"\"; - } - else - { - if ((CONST_INT_P (operands[1]) - || CONST_DOUBLE_P (operands[1])) - && val[0] == 0) - { - if (REGNO_REG_CLASS (REGNO (operands[0])) == DATA_REGS) - output_asm_insn (\"mov 0, %L0\", operands); - else - output_asm_insn (\"mov %L1,%L0\", operands); - } - else if ((CONST_INT_P (operands[1]) - || CONST_DOUBLE_P (operands[1])) - && (REGNO_REG_CLASS (true_regnum (operands[0])) - == EXTENDED_REGS) - && (((val[0] & 0x80) && ! (val[0] & 0xffffff00)) - || ((val[0] & 0x800000) && ! (val[0] & 0xff000000)))) - output_asm_insn (\"movu %L1,%L0\", operands); - else - output_asm_insn (\"mov %L1,%L0\", operands); - - if ((CONST_INT_P (operands[1]) - || CONST_DOUBLE_P (operands[1])) - && val[1] == 0) - { - if (REGNO_REG_CLASS (REGNO (operands[0])) == DATA_REGS) - output_asm_insn (\"mov 0, %H0\", operands); - else - output_asm_insn (\"mov %H1,%H0\", operands); - } - else if ((CONST_INT_P (operands[1]) - || CONST_DOUBLE_P (operands[1])) - && val[0] == val[1]) - output_asm_insn (\"mov %L0,%H0\", operands); - else if ((CONST_INT_P (operands[1]) - || CONST_DOUBLE_P (operands[1])) - && (REGNO_REG_CLASS (true_regnum (operands[0])) - == EXTENDED_REGS) - && (((val[1] & 0x80) && ! (val[1] & 0xffffff00)) - || ((val[1] & 0x800000) && ! (val[1] & 0xff000000)))) - output_asm_insn (\"movu %H1,%H0\", operands); - else - output_asm_insn (\"mov %H1,%H0\", operands); - return \"\"; - } - default: - gcc_unreachable (); - } - }" - ;; The timing of "37" is an approximation of the worst case sceanario. - [(set_attr_alternative "timings" - [(const_int 11) - (const_int 11) - (const_int 22) - (const_int 22) - (const_int 37) - (const_int 37) - (const_int 37) - (const_int 37) - (const_int 37) - (const_int 37) - ]) - ] -) - -(define_expand "movdf" - [(set (match_operand:DF 0 "nonimmediate_operand") - (match_operand:DF 1 "general_operand"))] - "" - " -{ - /* One of the ops has to be in a register. */ - if (!register_operand (operand1, DFmode) - && !register_operand (operand0, DFmode)) - operands[1] = copy_to_mode_reg (DFmode, operand1); -}") - -(define_insn "*am33_2_movdf" - [(set (match_operand:DF 0 "nonimmediate_operand" - ;; 0 1 2 3 4 5 6 7 8 9 10 11 - "=fdax,dax,fdxa,f, f,Q,dxm,dxm,a, a,dx,a") - (match_operand:DF 1 "general_operand" - " 0, G, f, dxaF,Q,f,dx, a, dx,a,Fm,Fm"))] - "TARGET_AM33_2 - && (register_operand (operands[0], DFmode) - || register_operand (operands[1], DFmode))" - "* - { - long val[2]; - REAL_VALUE_TYPE rv; - - switch (which_alternative) - { - case 0: - return \"nop\"; - - case 1: - return \"mov 0, %L0\; mov 0, %H0\"; - - case 2: - case 3: - return \"fmov %L1, %L0\; fmov %H1, %H0\"; - - case 4: - if (MEM_P (operands[1]) - && CONST_INT_P (XEXP (operands[1], 0)) - && (INTVAL (XEXP (operands[1], 0)) & 7) == 0) - return \"fmov %D1, %D0\"; - else - return \"fmov %L1, %L0\; fmov %H1, %H0\"; - - case 5: - if (MEM_P (operands[0]) - && CONST_INT_P (XEXP (operands[0], 0)) - && (INTVAL (XEXP (operands[0], 0)) & 7) == 0) - return \"fmov %D1, %D0\"; - else - return \"fmov %L1, %L0\; fmov %H1, %H0\"; - - case 6: - case 7: - case 8: - case 9: - case 10: - case 11: - if (CONST_INT_P (operands[1])) - { - rtx low, high; - split_double (operands[1], &low, &high); - val[0] = INTVAL (low); - val[1] = INTVAL (high); - } - if (CONST_DOUBLE_P (operands[1])) - { - if (GET_MODE (operands[1]) == DFmode) - { - REAL_VALUE_FROM_CONST_DOUBLE (rv, operands[1]); - REAL_VALUE_TO_TARGET_DOUBLE (rv, val); - } - else if (GET_MODE (operands[1]) == VOIDmode - || GET_MODE (operands[1]) == DImode) - { - val[0] = CONST_DOUBLE_LOW (operands[1]); - val[1] = CONST_DOUBLE_HIGH (operands[1]); - } - } - - if (MEM_P (operands[1]) - && reg_overlap_mentioned_p (operands[0], XEXP (operands[1], 0))) - { - rtx temp = operands[0]; - - while (GET_CODE (temp) == SUBREG) - temp = SUBREG_REG (temp); - - gcc_assert (REG_P (temp)); - - if (reg_overlap_mentioned_p (gen_rtx_REG (SImode, REGNO (temp)), - XEXP (operands[1], 0))) - return \"mov %H1, %H0\; mov %L1, %L0\"; - else - return \"mov %L1, %L0\; mov %H1, %H0\"; - - } - else if (MEM_P (operands[1]) - && CONSTANT_ADDRESS_P (XEXP (operands[1], 0)) - && REGNO_REG_CLASS (REGNO (operands[0])) == ADDRESS_REGS) - { - rtx xoperands[2]; - - xoperands[0] = operands[0]; - xoperands[1] = XEXP (operands[1], 0); - - output_asm_insn (\"mov %1, %L0\; mov (4, %L0), %H0\; mov (%L0), %L0\", - xoperands); - return \"\"; - } - else - { - if ((CONST_INT_P (operands[1]) - || CONST_DOUBLE_P (operands[1])) - && val[0] == 0) - { - if (REGNO_REG_CLASS (REGNO (operands[0])) == DATA_REGS) - output_asm_insn (\"mov 0, %L0\", operands); - else - output_asm_insn (\"mov %L1,%L0\", operands); - } - else if ((CONST_INT_P (operands[1]) - || CONST_DOUBLE_P (operands[1])) - && (REGNO_REG_CLASS (true_regnum (operands[0])) - == EXTENDED_REGS) - && (((val[0] & 0x80) && ! (val[0] & 0xffffff00)) - || ((val[0] & 0x800000) && ! (val[0] & 0xff000000)))) - output_asm_insn (\"movu %L1, %L0\", operands); - else - output_asm_insn (\"mov %L1, %L0\", operands); - - if ((CONST_INT_P (operands[1]) - || CONST_DOUBLE_P (operands[1])) - && val[1] == 0) - { - if (REGNO_REG_CLASS (REGNO (operands[0])) == DATA_REGS) - output_asm_insn (\"mov 0, %H0\", operands); - else - output_asm_insn (\"mov %H1, %H0\", operands); - } - else if ((CONST_INT_P (operands[1]) - || CONST_DOUBLE_P (operands[1])) - && val[0] == val[1]) - output_asm_insn (\"mov %L0,%H0\", operands); - else if ((CONST_INT_P (operands[1]) - || CONST_DOUBLE_P (operands[1])) - && (REGNO_REG_CLASS (true_regnum (operands[0])) - == EXTENDED_REGS) - && (((val[1] & 0x80) && ! (val[1] & 0xffffff00)) - || ((val[1] & 0x800000) && ! (val[1] & 0xff000000)))) - output_asm_insn (\"movu %H1, %H0\", operands); - else - output_asm_insn (\"mov %H1, %H0\", operands); - return \"\"; - } + case 0: + return ""; + case 1: + case 3: + case 7: + case 8: + return "mov %1,%0"; + case 2: + case 4: + case 5: + case 6: + case 9: + case 10: + return "fmov %1,%0"; default: gcc_unreachable (); } - }" - ;; The timing of "37" is an approximation of the worst case sceanario. +} [(set_attr_alternative "timings" - [(const_int 11) - (const_int 22) - (const_int 22) - (const_int 22) - (const_int 22) - (const_int 37) - (const_int 37) - (const_int 37) - (const_int 37) - (const_int 37) - (const_int 37) - (const_int 37) - ]) - ] + [(const_int 11) + (const_int 22) + (if_then_else (eq_attr "cpu" "am34") + (const_int 47) (const_int 25)) + (const_int 11) + (if_then_else (eq_attr "cpu" "am34") + (const_int 13) (const_int 14)) + (if_then_else (eq_attr "cpu" "am34") + (const_int 13) (const_int 12)) + (if_then_else (eq_attr "cpu" "am34") + (const_int 13) (const_int 14)) + (if_then_else (eq_attr "cpu" "am34") + (const_int 13) (const_int 24)) + (if_then_else (eq_attr "cpu" "am34") + (const_int 13) (const_int 24)) + (if_then_else (eq_attr "cpu" "am34") + (const_int 13) (const_int 24)) + (if_then_else (eq_attr "cpu" "am34") + (const_int 13) (const_int 24)) + ])] ) -(define_insn "*mn10300_movdf" - [(set (match_operand:DF 0 "nonimmediate_operand" - ;;0 1 2 3 4 5 6 7 - "=dxa, dax, dxm, dxm, a, a, dx, a") - (match_operand:DF 1 "general_operand" - " 0, G, dx, a, dx, a, Fm, Fm"))] - "register_operand (operands[0], DFmode) - || register_operand (operands[1], DFmode)" - "* - { - long val[2]; - REAL_VALUE_TYPE rv; - - switch (which_alternative) - { - case 0: - return \"nop\"; - - case 1: - return \"mov 0, %L0\; mov 0, %H0\"; - - case 2: - case 3: - case 4: - case 5: - case 6: - case 7: - if (CONST_INT_P (operands[1])) - { - rtx low, high; - split_double (operands[1], &low, &high); - val[0] = INTVAL (low); - val[1] = INTVAL (high); - } - if (CONST_DOUBLE_P (operands[1])) - { - if (GET_MODE (operands[1]) == DFmode) - { - REAL_VALUE_FROM_CONST_DOUBLE (rv, operands[1]); - REAL_VALUE_TO_TARGET_DOUBLE (rv, val); - } - else if (GET_MODE (operands[1]) == VOIDmode - || GET_MODE (operands[1]) == DImode) - { - val[0] = CONST_DOUBLE_LOW (operands[1]); - val[1] = CONST_DOUBLE_HIGH (operands[1]); - } - } - - if (MEM_P (operands[1]) - && reg_overlap_mentioned_p (operands[0], XEXP (operands[1], 0))) - { - rtx temp = operands[0]; - - while (GET_CODE (temp) == SUBREG) - temp = SUBREG_REG (temp); - - gcc_assert (REG_P (temp)); - - if (reg_overlap_mentioned_p (gen_rtx_REG (SImode, REGNO (temp)), - XEXP (operands[1], 0))) - return \"mov %H1, %H0\; mov %L1, %L0\"; - else - return \"mov %L1, %L0\; mov %H1, %H0\"; - } - else if (MEM_P (operands[1]) - && CONSTANT_ADDRESS_P (XEXP (operands[1], 0)) - && REGNO_REG_CLASS (REGNO (operands[0])) == ADDRESS_REGS) - { - rtx xoperands[2]; - - xoperands[0] = operands[0]; - xoperands[1] = XEXP (operands[1], 0); - - output_asm_insn (\"mov %1, %L0\; mov (4, %L0), %H0\; mov (%L0), %L0\", - xoperands); - return \"\"; - } - else - { - if ((CONST_INT_P (operands[1]) - || CONST_DOUBLE_P (operands[1])) - && val[0] == 0) - { - if (REGNO_REG_CLASS (REGNO (operands[0])) == DATA_REGS) - output_asm_insn (\"mov 0, %L0\", operands); - else - output_asm_insn (\"mov %L1, %L0\", operands); - } - else if ((CONST_INT_P (operands[1]) - || CONST_DOUBLE_P (operands[1])) - && (REGNO_REG_CLASS (true_regnum (operands[0])) - == EXTENDED_REGS) - && (((val[0] & 0x80) && ! (val[0] & 0xffffff00)) - || ((val[0] & 0x800000) && ! (val[0] & 0xff000000)))) - output_asm_insn (\"movu %L1, %L0\", operands); - else - output_asm_insn (\"mov %L1, %L0\", operands); - - if ((CONST_INT_P (operands[1]) - || CONST_DOUBLE_P (operands[1])) - && val[1] == 0) - { - if (REGNO_REG_CLASS (REGNO (operands[0])) == DATA_REGS) - output_asm_insn (\"mov 0, %H0\", operands); - else - output_asm_insn (\"mov %H1, %H0\", operands); - } - else if ((CONST_INT_P (operands[1]) - || CONST_DOUBLE_P (operands[1])) - && val[0] == val[1]) - output_asm_insn (\"mov %L0, %H0\", operands); - else if ((CONST_INT_P (operands[1]) - || CONST_DOUBLE_P (operands[1])) - && (REGNO_REG_CLASS (true_regnum (operands[0])) - == EXTENDED_REGS) - && (((val[1] & 0x80) && ! (val[1] & 0xffffff00)) - || ((val[1] & 0x800000) && ! (val[1] & 0xff000000)))) - output_asm_insn (\"movu %H1, %H0\", operands); - else - output_asm_insn (\"mov %H1, %H0\", operands); - return \"\"; - } - default: - gcc_unreachable (); - } - }" - ;; Timings of "37" is approximation of the worst case sceanario. - [(set_attr_alternative "timings" - [(const_int 11) - (const_int 22) - (const_int 37) - (const_int 37) - (const_int 37) - (const_int 37) - (const_int 37) - (const_int 37) - ]) - ] -) ;; ---------------------------------------------------------------------- ;; ADD INSTRUCTIONS @@ -1363,42 +762,23 @@ (const_int 24) (const_int 23)))] ) -(define_expand "udivmodsi4" - [(parallel [(set (match_operand:SI 0 "register_operand") - (udiv:SI (match_operand:SI 1 "general_operand") - (match_operand:SI 2 "general_operand"))) - (set (match_operand:SI 3 "register_operand") - (umod:SI (match_dup 1) (match_dup 2))) - (clobber (reg:CC CC_REG)) - ]) - ] - "" - "{ - if (!register_operand (operands[1], SImode)) - operands[1] = copy_to_mode_reg (SImode, operands[1]); - if (!register_operand (operands[2], SImode)) - operands[2] = copy_to_mode_reg (SImode, operands[2]); - }" -) - -(define_insn "*udivmodsi4" - [(set (match_operand:SI 0 "register_operand" "=dx") +;; ??? This pattern causes too-high register pressure for MN103. +;; ??? To be fixed by exposing the MDR register properly. +(define_insn "udivmodsi4" + [(set (match_operand:SI 0 "register_operand" "=D") (udiv:SI (match_operand:SI 1 "register_operand" "0") - (match_operand:SI 2 "register_operand" "dx"))) + (match_operand:SI 2 "register_operand" "D"))) (set (match_operand:SI 3 "register_operand" "=&d") (umod:SI (match_dup 1) (match_dup 2))) - (clobber (reg:CC CC_REG)) - ] - "" - "* + (clobber (reg:CC CC_REG))] + "TARGET_AM33" { - output_asm_insn (\"sub %3,%3\;mov %3,mdr\", operands); - + output_asm_insn ("clr %3\;ext %3", operands); if (find_reg_note (insn, REG_UNUSED, operands[3])) - return \"divu %2,%0\"; + return "divu %2,%0"; else - return \"divu %2,%0\;mov mdr,%3\"; -}" + return "divu %2,%0\;mov mdr,%3"; +} ;; Timings: AM33 AM34 ;; SUB 1/1 1/1 ;; MOV 1/1 1/1 @@ -1410,6 +790,28 @@ (const_int 4546) (const_int 4142)))] ) +;; ??? In the meantime MN103 can use these two patterns, +;; which reduce the register pressure by one. +(define_insn "udivsi3" + [(set (match_operand:SI 0 "register_operand" "=&d") + (udiv:SI (match_operand:SI 1 "register_operand" "d") + (match_operand:SI 2 "register_operand" "d"))) + (clobber (reg:CC CC_REG))] + "!TARGET_AM33" + "clr %0\;ext %0\;mov %1,%0\;divu %2,%0" + [(set_attr "timings" "4142")] +) + +(define_insn "umodsi3" + [(set (match_operand:SI 0 "register_operand" "=&d") + (umod:SI (match_operand:SI 1 "register_operand" "d") + (match_operand:SI 2 "register_operand" "d"))) + (clobber (reg:CC CC_REG))] + "!TARGET_AM33" + "clr %0\;ext %0\;mov %1,%0\;divu %2,%0\;mov mdr,%0" + [(set_attr "timings" "4142")] +) + (define_insn "divmodsi4" [(set (match_operand:SI 0 "register_operand" "=dx") (div:SI (match_operand:SI 1 "register_operand" "0")
From: Richard Henderson <rth@twiddle.net> Use the "D" and "A" constraints, and the enabled attribute to unify all ofthe integer move patterns. Delete the fake double word move patterns; let the middle-end generate subregs as required. Unfortunately, this somehow exposes a register pressure problem with the udivmod pattern. This is properly fixed with subsequent patches that expose the MDR register. In the meantime it is highly desirable to to preserve bisect-ability of the patch series, so disable this pattern for AM30. --- gcc/config/mn10300/mn10300.md | 930 ++++++++--------------------------------- 1 files changed, 166 insertions(+), 764 deletions(-)