diff options
author | DJ Delorie <dj@redhat.com> | 2005-12-15 20:31:39 -0500 |
---|---|---|
committer | DJ Delorie <dj@gcc.gnu.org> | 2005-12-15 20:31:39 -0500 |
commit | 12ea2512c46172b9692e5110b781071dcfa86754 (patch) | |
tree | d42ce2ab6f459bf43ed2bd447cfcde5d0656e0fe /gcc/config | |
parent | 6cb8c0591503deecee9e634063ae53a7872b1020 (diff) | |
download | gcc-12ea2512c46172b9692e5110b781071dcfa86754.tar.gz |
predicates.md (m32c_psi_scale): New.
* config/m32c/predicates.md (m32c_psi_scale): New.
* config/m32c/m32c.c (m32c_expand_neg_mulpsi3): New.
* config/m32c/muldiv.md (mulpsi3): Support negative constants.
From-SVN: r108620
Diffstat (limited to 'gcc/config')
-rw-r--r-- | gcc/config/m32c/m32c.c | 24 | ||||
-rw-r--r-- | gcc/config/m32c/muldiv.md | 19 | ||||
-rw-r--r-- | gcc/config/m32c/predicates.md | 5 |
3 files changed, 45 insertions, 3 deletions
diff --git a/gcc/config/m32c/m32c.c b/gcc/config/m32c/m32c.c index 97b095328e4..8580922a402 100644 --- a/gcc/config/m32c/m32c.c +++ b/gcc/config/m32c/m32c.c @@ -2798,6 +2798,30 @@ m32c_prepare_shift (rtx * operands, int scale, int bits) return 0; } +/* The m32c has a limited range of operations that work on PSImode + values; we have to expand to SI, do the math, and truncate back to + PSI. Yes, this is expensive, but hopefully gcc will learn to avoid + those cases. */ +void +m32c_expand_neg_mulpsi3 (rtx * operands) +{ + /* operands: a = b * i */ + rtx temp1; /* b as SI */ + rtx temp2; /* -b as SI */ + rtx temp3; /* -b as PSI */ + rtx scale; + + temp1 = gen_reg_rtx (SImode); + temp2 = gen_reg_rtx (SImode); + temp3 = gen_reg_rtx (PSImode); + scale = GEN_INT (- INTVAL (operands[2])); + + emit_insn (gen_zero_extendpsisi2 (temp1, operands[1])); + emit_insn (gen_negsi2 (temp2, temp1)); + emit_insn (gen_truncsipsi2 (temp3, temp2)); + emit_insn (gen_mulpsi3 (operands[0], temp3, scale)); +} + /* Pattern Output Functions */ /* Returns TRUE if the current function is a leaf, and thus we can diff --git a/gcc/config/m32c/muldiv.md b/gcc/config/m32c/muldiv.md index e80d4dc763a..bf6f35755dd 100644 --- a/gcc/config/m32c/muldiv.md +++ b/gcc/config/m32c/muldiv.md @@ -127,16 +127,29 @@ ; GCC expects to be able to multiply pointer-sized integers too, but -; fortunately it only multiplies by powers of two. -(define_insn "mulpsi3" +; fortunately it only multiplies by powers of two, although sometimes +; they're negative. +(define_insn "mulpsi3_op" [(set (match_operand:PSI 0 "mra_operand" "=RsiSd") (mult:PSI (match_operand:PSI 1 "mra_operand" "%0") - (match_operand 2 "const_int_operand" "Ilb")))] + (match_operand 2 "m32c_psi_scale" "Ilb")))] "TARGET_A24" "shl.l\t%b2,%0" [(set_attr "flags" "szc")] ) +(define_expand "mulpsi3" + [(set (match_operand:PSI 0 "mra_operand" "=RsiSd") + (mult:PSI (match_operand:PSI 1 "mra_operand" "%0") + (match_operand 2 "m32c_psi_scale" "Ilb")))] + "TARGET_A24" + "if (INTVAL(operands[2]) < 0) + { + m32c_expand_neg_mulpsi3 (operands); + DONE; + }" + ) + (define_expand "divmodqi4" diff --git a/gcc/config/m32c/predicates.md b/gcc/config/m32c/predicates.md index 362f20d1118..0c80e1a5e5a 100644 --- a/gcc/config/m32c/predicates.md +++ b/gcc/config/m32c/predicates.md @@ -195,3 +195,8 @@ (ior (match_operand 0 "m32c_r0_operand") (ior (match_operand 0 "m32c_mem0_operand") (match_code "parallel")))) + +; TRUE for constants we can multiply pointers by +(define_predicate "m32c_psi_scale" + (and (match_operand 0 "const_int_operand") + (match_test "m32c_const_ok_for_constraint_p(INTVAL(op), 'I', \"Ilb\")"))) |