This patch handles both signed and unsigned
builtin multiplication overflow.

Uses the "mpy.f" instruction to set the condition
codes based on the result.  In the event of an
overflow, the V flag is set, triggering a
conditional move depending on the V flag status.

For example, set "1" to "r0" in case of overflow:

        mov_s   r0,1
        mpy.f   r0,r0,r1
        j_s.d   [blink]
        mov.nv  r0,0

gcc/ChangeLog:

        * config/arc/arc.md (<su_optab>mulvsi4): New define_expand.
        (<su_optab>mulsi3_Vcmp): New define_insn.

Signed-off-by: Luis Silva <lu...@synopsys.com>
---
 gcc/config/arc/arc.md | 33 +++++++++++++++++++++++++++++++++
 1 file changed, 33 insertions(+)

diff --git a/gcc/config/arc/arc.md b/gcc/config/arc/arc.md
index bc2e8fadd91..dd245d1813c 100644
--- a/gcc/config/arc/arc.md
+++ b/gcc/config/arc/arc.md
@@ -842,6 +842,9 @@ archs4x, archs4xd"
 ; Optab prefix for sign/zero-extending operations
 (define_code_attr su_optab [(sign_extend "") (zero_extend "u")])
 
+;; Code iterator for sign/zero extension
+(define_code_iterator ANY_EXTEND [sign_extend zero_extend])
+
 (define_insn "*<SEZ_prefix>xt<SQH_postfix>_cmp0_noout"
   [(set (match_operand 0 "cc_set_register" "")
        (compare:CC_ZN (SEZ:SI (match_operand:SQH 1 "register_operand" "r"))
@@ -1068,6 +1071,36 @@ archs4x, archs4xd"
    (set_attr "cond" "set_zn")
    (set_attr "length" "*,4,4,4,8")])
 
+(define_expand "<su_optab>mulvsi4"
+  [(ANY_EXTEND:DI (match_operand:SI 0 "register_operand"))
+   (ANY_EXTEND:DI (match_operand:SI 1 "register_operand"))
+   (ANY_EXTEND:DI (match_operand:SI 2 "register_operand"))
+   (label_ref (match_operand 3 "" ""))]
+  "TARGET_MPY"
+  {
+    emit_insn (gen_<su_optab>mulsi3_Vcmp (operands[0], operands[1],
+                                         operands[2]));
+    arc_gen_unlikely_cbranch (NE, CC_Vmode, operands[3]);
+    DONE;
+  })
+
+(define_insn "<su_optab>mulsi3_Vcmp"
+  [(parallel
+    [(set
+      (reg:CC_V CC_REG)
+      (compare:CC_V
+       (mult:DI
+       (ANY_EXTEND:DI (match_operand:SI 1 "register_operand"  "%0,r,r,r"))
+       (ANY_EXTEND:DI (match_operand:SI 2 "nonmemory_operand"  "I,L,r,C32")))
+       (ANY_EXTEND:DI (mult:SI (match_dup 1) (match_dup 2)))))
+     (set (match_operand:SI 0 "register_operand"              "=r,r,r,r")
+         (mult:SI (match_dup 1) (match_dup 2)))])]
+  "register_operand (operands[1], SImode)
+   || register_operand (operands[2], SImode)"
+  "mpy<su_optab>.f\\t%0,%1,%2"
+  [(set_attr "length" "4,4,4,8")
+   (set_attr "type"   "mpy")])
+
 (define_insn "*mulsi3_cmp0"
   [(set (reg:CC_Z CC_REG)
        (compare:CC_Z
-- 
2.37.1

Reply via email to