@@ -137,6 +137,7 @@
UNSPEC_ARC_VMAC2HU
UNSPEC_ARC_VMPY2H
UNSPEC_ARC_VMPY2HU
+ UNSPEC_ARC_CC_NEZ
VUNSPEC_ARC_RTIE
VUNSPEC_ARC_SYNC
@@ -2790,6 +2791,31 @@ archs4x, archs4xd"
(set_attr "type" "cc_arith")
(set_attr "length" "4,4,4,4,8,8")])
+(define_insn "adc_f"
+ [(set (reg:CC_C CC_REG)
+ (compare:CC_C
+ (zero_extend:DI
+ (plus:SI
+ (plus:SI
+ (ltu:SI (reg:CC_C CC_REG) (const_int 0))
+ (match_operand:SI 1 "register_operand" "%r"))
+ (match_operand:SI 2 "register_operand" "r")))
+ (plus:DI
+ (ltu:DI (reg:CC_C CC_REG) (const_int 0))
+ (zero_extend:DI (match_dup 1)))))
+ (set (match_operand:SI 0 "register_operand" "=r")
+ (plus:SI
+ (plus:SI
+ (ltu:SI (reg:CC_C CC_REG) (const_int 0))
+ (match_dup 1))
+ (match_dup 2)))]
+ ""
+ "adc.f\\t%0,%1,%2"
+ [(set_attr "cond" "set")
+ (set_attr "predicable" "no")
+ (set_attr "type" "cc_arith")
+ (set_attr "length" "4")])
+
; combiner-splitter cmp / scc -> cmp / adc
(define_split
[(set (match_operand:SI 0 "dest_reg_operand" "")
@@ -3530,6 +3556,68 @@ archs4x, archs4xd"
""
[(set_attr "length" "8")])
+(define_expand "ashrdi3"
+ [(parallel
+ [(set (match_operand:DI 0 "register_operand")
+ (ashiftrt:DI (match_operand:DI 1 "register_operand")
+ (match_operand:QI 2 "const_int_operand")))
+ (clobber (reg:CC CC_REG))])]
+ ""
+{
+ if (operands[2] != const1_rtx)
+ FAIL;
+})
+
+;; Split into asr.f hi; rrc lo
+(define_insn_and_split "*ashrdi3_cnt1"
+ [(set (match_operand:DI 0 "register_operand")
+ (ashiftrt:DI (match_operand:DI 1 "register_operand")
+ (const_int 1)))
+ (clobber (reg:CC CC_REG))]
+ "arc_pre_reload_split ()"
+ "#"
+ "&& 1"
+ [(const_int 0)]
+{
+ emit_insn (gen_ashrsi3_cnt1_carry (gen_highpart (SImode, operands[0]),
+ gen_highpart (SImode, operands[1])));
+ emit_insn (gen_rrcsi2 (gen_lowpart (SImode, operands[0]),
+ gen_lowpart (SImode, operands[1])));
+ DONE;
+}
+ [(set_attr "length" "8")])
+
+(define_expand "lshrdi3"
+ [(parallel
+ [(set (match_operand:DI 0 "register_operand")
+ (lshiftrt:DI (match_operand:DI 1 "register_operand")
+ (match_operand:QI 2 "const_int_operand")))
+ (clobber (reg:CC CC_REG))])]
+ ""
+{
+ if (operands[2] != const1_rtx)
+ FAIL;
+})
+
+;; Split into lsr.f hi; rrc lo
+(define_insn_and_split "*lshrdi3_cnt1"
+ [(set (match_operand:DI 0 "register_operand")
+ (lshiftrt:DI (match_operand:DI 1 "register_operand")
+ (const_int 1)))
+ (clobber (reg:CC CC_REG))]
+ "arc_pre_reload_split ()"
+ "#"
+ "&& 1"
+ [(const_int 0)]
+{
+ emit_insn (gen_lshrsi3_cnt1_carry (gen_highpart (SImode, operands[0]),
+ gen_highpart (SImode, operands[1])));
+ emit_insn (gen_rrcsi2 (gen_lowpart (SImode, operands[0]),
+ gen_lowpart (SImode, operands[1])));
+ DONE;
+}
+ [(set_attr "length" "8")])
+
;; Rotate instructions.
(define_insn "rotrsi3_insn"
@@ -3571,6 +3659,103 @@ archs4x, archs4xd"
}
})
+;; Rotate through carry flag
+
+(define_insn "rrcsi2"
+ [(set (match_operand:SI 0 "dest_reg_operand" "=r")
+ (plus:SI
+ (lshiftrt:SI (match_operand:SI 1 "register_operand" "r")
+ (const_int 1))
+ (ashift:SI (ltu:SI (reg:CC_C CC_REG) (const_int 0))
+ (const_int 31))))]
+ ""
+ "rrc\\t%0,%1"
+ [(set_attr "type" "shift")
+ (set_attr "predicable" "no")
+ (set_attr "length" "4")])
+
+(define_insn "rrcsi2_carry"
+ [(set (reg:CC_C CC_REG)
+ (unspec:CC_C [(and:SI (match_operand:SI 1 "register_operand" "r")
+ (const_int 1))] UNSPEC_ARC_CC_NEZ))
+ (set (match_operand:SI 0 "dest_reg_operand" "=r")
+ (plus:SI
+ (lshiftrt:SI (match_dup 1) (const_int 1))
+ (ashift:SI (ltu:SI (reg:CC_C CC_REG) (const_int 0))
+ (const_int 31))))]
+ ""
+ "rrc.f\\t%0,%1"
+ [(set_attr "type" "shift")
+ (set_attr "predicable" "no")
+ (set_attr "length" "4")])
+
+;; DImode Rotate instructions
+
+(define_expand "rotldi3"
+ [(parallel
+ [(set (match_operand:DI 0 "register_operand")
+ (rotate:DI (match_operand:DI 1 "register_operand")
+ (match_operand:QI 2 "const_int_operand")))
+ (clobber (reg:CC CC_REG))])]
+ ""
+{
+ if (operands[2] != const1_rtx)
+ FAIL;
+})
+
+;; split into add.f lo; adc.f hi; adc lo
+(define_insn_and_split "*rotldi3_cnt1"
+ [(set (match_operand:DI 0 "register_operand")
+ (rotate:DI (match_operand:DI 1 "register_operand")
+ (const_int 1)))
+ (clobber (reg:CC CC_REG))]
+ "arc_pre_reload_split ()"
+ "#"
+ "&& 1"
+ [(const_int 0)]
+{
+ rtx lo0 = gen_lowpart (SImode, operands[0]);
+ rtx lo1 = gen_lowpart (SImode, operands[1]);
+ rtx hi1 = gen_highpart (SImode, operands[1]);
+ emit_insn (gen_add_f (lo0, lo1, lo1));
+ emit_insn (gen_adc_f (gen_highpart (SImode, operands[0]), hi1, hi1));
+ emit_insn (gen_adc (lo0, lo0, const0_rtx));
+ DONE;
+}
+ [(set_attr "length" "12")])
+
+(define_expand "rotrdi3"
+ [(parallel
+ [(set (match_operand:DI 0 "register_operand")
+ (rotatert:DI (match_operand:DI 1 "register_operand")
+ (match_operand:QI 2 "const_int_operand")))
+ (clobber (reg:CC CC_REG))])]
+ ""
+{
+ if (operands[2] != const1_rtx)
+ FAIL;
+})
+
+;; split into asr.f lo; rrc.f hi; rrc lo
+(define_insn_and_split "*rotrdi3_cnt1"
+ [(set (match_operand:DI 0 "register_operand")
+ (rotatert:DI (match_operand:DI 1 "register_operand")
+ (const_int 1)))
+ (clobber (reg:CC CC_REG))]
+ "arc_pre_reload_split ()"
+ "#"
+ "&& 1"
+ [(const_int 0)]
+{
+ rtx lo = gen_lowpart (SImode, operands[1]);
+ emit_insn (gen_btst_0_carry (lo));
+ emit_insn (gen_rrcsi2_carry (gen_highpart (SImode, operands[0]),
+ gen_highpart (SImode, operands[1])));
+ emit_insn (gen_rrcsi2 (gen_lowpart (SImode, operands[0]), lo));
+ DONE;
+}
+ [(set_attr "length" "12")])
+
;; Compare / branch instructions.
(define_expand "cbranchsi4"
@@ -6022,6 +6207,18 @@ archs4x, archs4xd"
(set_attr "iscompact" "maybe,false")
(set_attr "predicable" "no,no")])
+(define_insn "lshrsi3_cnt1_carry"
+ [(set (reg:CC_C CC_REG)
+ (unspec:CC_C [(and:SI (match_operand:SI 1 "register_operand" "r")
+ (const_int 1))] UNSPEC_ARC_CC_NEZ))
+ (set (match_operand:SI 0 "dest_reg_operand" "=r")
+ (lshiftrt:SI (match_dup 1) (const_int 1)))]
+ ""
+ "lsr.f\\t%0,%1"
+ [(set_attr "type" "unary")
+ (set_attr "length" "4")
+ (set_attr "predicable" "no")])
+
(define_insn "ashrsi3_cnt1"
[(set (match_operand:SI 0 "dest_reg_operand" "=q,w")
(ashiftrt:SI (match_operand:SI 1 "register_operand" "q,c")
@@ -6032,6 +6229,28 @@ archs4x, archs4xd"
(set_attr "iscompact" "maybe,false")
(set_attr "predicable" "no,no")])
+(define_insn "ashrsi3_cnt1_carry"
+ [(set (reg:CC_C CC_REG)
+ (unspec:CC_C [(and:SI (match_operand:SI 1 "register_operand" "r")
+ (const_int 1))] UNSPEC_ARC_CC_NEZ))
+ (set (match_operand:SI 0 "dest_reg_operand" "=r")
+ (ashiftrt:SI (match_dup 1) (const_int 1)))]
+ ""
+ "asr.f\\t%0,%1"
+ [(set_attr "type" "unary")
+ (set_attr "length" "4")
+ (set_attr "predicable" "no")])
+
+(define_insn "btst_0_carry"
+ [(set (reg:CC_C CC_REG)
+ (unspec:CC_C [(and:SI (match_operand:SI 0 "register_operand" "r")
+ (const_int 1))] UNSPEC_ARC_CC_NEZ))]
+ ""
+ "asr.f\\t0,%0"
+ [(set_attr "type" "unary")
+ (set_attr "length" "4")
+ (set_attr "predicable" "no")])
+
(define_peephole2
[(set (match_operand:SI 0 "register_operand" "")
(zero_extract:SI (match_dup 0)
new file mode 100644
@@ -0,0 +1,10 @@
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+
+long long foo(long long x)
+{
+ return x >> 1;
+}
+
+/* { dg-final { scan-assembler "asr.f\\s+r1,r1" } } */
+/* { dg-final { scan-assembler "rrc\\s+r0,r0" } } */
new file mode 100644
@@ -0,0 +1,10 @@
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+
+unsigned long long foo(unsigned long long x)
+{
+ return x >> 1;
+}
+
+/* { dg-final { scan-assembler "lsr.f\\s+r1,r1" } } */
+/* { dg-final { scan-assembler "rrc\\s+r0,r0" } } */
new file mode 100644
@@ -0,0 +1,11 @@
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+
+unsigned long long foo(unsigned long long x)
+{
+ return (x << 1) | (x >> 63);
+}
+
+/* { dg-final { scan-assembler "add.f\\s+r0,r0,r0" } } */
+/* { dg-final { scan-assembler "adc.f\\s+r1,r1,r1" } } */
+/* { dg-final { scan-assembler "add.cs\\s+r0,r0,1" } } */
new file mode 100644
@@ -0,0 +1,11 @@
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+
+unsigned long long foo(unsigned long long x)
+{
+ return (x >> 1) | (x << 63);
+}
+
+/* { dg-final { scan-assembler "asr.f\\s+0,r0" } } */
+/* { dg-final { scan-assembler "rrc.f\\s+r1,r1" } } */
+/* { dg-final { scan-assembler "rrc\\s+r0,r0" } } */