* config/m32c/predicates.md (m32c_psi_scale): New.
authordj <dj@138bc75d-0d04-0410-961f-82ee72b054a4>
Fri, 16 Dec 2005 01:31:39 +0000 (01:31 +0000)
committerdj <dj@138bc75d-0d04-0410-961f-82ee72b054a4>
Fri, 16 Dec 2005 01:31:39 +0000 (01:31 +0000)
* config/m32c/m32c.c (m32c_expand_neg_mulpsi3): New.
* config/m32c/muldiv.md (mulpsi3): Support negative constants.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@108620 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/ChangeLog
gcc/config/m32c/m32c.c
gcc/config/m32c/muldiv.md
gcc/config/m32c/predicates.md

index 0690daa..584f6e5 100644 (file)
@@ -1,3 +1,9 @@
+2005-12-15  DJ Delorie  <dj@redhat.com>
+
+       * 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.
+
 2005-12-16  Jan Hubicka  <jh@suse.cz>
 
        PR rtl-optimization/25224
index 97b0953..8580922 100644 (file)
@@ -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
index e80d4dc..bf6f357 100644 (file)
 
 
 ; 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"
index 362f20d..0c80e1a 100644 (file)
   (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\")")))