summaryrefslogtreecommitdiff
path: root/gcc/config
diff options
context:
space:
mode:
authorDJ Delorie <dj@redhat.com>2005-12-15 20:31:39 -0500
committerDJ Delorie <dj@gcc.gnu.org>2005-12-15 20:31:39 -0500
commit12ea2512c46172b9692e5110b781071dcfa86754 (patch)
treed42ce2ab6f459bf43ed2bd447cfcde5d0656e0fe /gcc/config
parent6cb8c0591503deecee9e634063ae53a7872b1020 (diff)
downloadgcc-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.c24
-rw-r--r--gcc/config/m32c/muldiv.md19
-rw-r--r--gcc/config/m32c/predicates.md5
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\")")))