aboutsummaryrefslogtreecommitdiff
path: root/gcc/config
diff options
context:
space:
mode:
authorGreta Yorsh <greta.yorsh@arm.com>2013-04-05 18:05:03 +0100
committerGreta Yorsh <gretay@gcc.gnu.org>2013-04-05 18:05:03 +0100
commit045e472c6eebe085feb5d3b95666409b78ba2b5b (patch)
tree88d13dd89c6dff412e90c30dd5eb0675a903cf66 /gcc/config
parentadcef07c9bf0b575fd5d4cf1891a894bc4333a30 (diff)
downloadgcc-045e472c6eebe085feb5d3b95666409b78ba2b5b.zip
gcc-045e472c6eebe085feb5d3b95666409b78ba2b5b.tar.gz
gcc-045e472c6eebe085feb5d3b95666409b78ba2b5b.tar.bz2
arm.md (negdi_extendsidi): New pattern.
2013-04-05 Greta Yorsh <Greta.Yorsh@arm.com> gcc/ * config/arm/arm.md (negdi_extendsidi): New pattern. (negdi_zero_extendsidi): Likewise. gcc/testsuite * gcc.target/arm/negdi-1.c: New test. * gcc.target/arm/negdi-2.c: Likewise. * gcc.target/arm/negdi-3.c: Likewise. * gcc.target/arm/negdi-4.c: Likewise. From-SVN: r197526
Diffstat (limited to 'gcc/config')
-rw-r--r--gcc/config/arm/arm.md67
1 files changed, 67 insertions, 0 deletions
diff --git a/gcc/config/arm/arm.md b/gcc/config/arm/arm.md
index 5c6d30e..e7c34bd 100644
--- a/gcc/config/arm/arm.md
+++ b/gcc/config/arm/arm.md
@@ -4344,6 +4344,73 @@
"TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
"")
+;; Negate an extended 32-bit value.
+(define_insn_and_split "*negdi_extendsidi"
+ [(set (match_operand:DI 0 "s_register_operand" "=r,&r,l,&l")
+ (neg:DI (sign_extend:DI (match_operand:SI 1 "s_register_operand" "0,r,0,l"))))
+ (clobber (reg:CC CC_REGNUM))]
+ "TARGET_32BIT"
+ "#" ; rsb\\t%Q0, %1, #0\;asr\\t%R0, %Q0, #31
+ "&& reload_completed"
+ [(const_int 0)]
+ {
+ operands[2] = gen_highpart (SImode, operands[0]);
+ operands[0] = gen_lowpart (SImode, operands[0]);
+ rtx tmp = gen_rtx_SET (VOIDmode,
+ operands[0],
+ gen_rtx_MINUS (SImode,
+ const0_rtx,
+ operands[1]));
+ if (TARGET_ARM)
+ {
+ emit_insn (tmp);
+ }
+ else
+ {
+ /* Set the flags, to emit the short encoding in Thumb2. */
+ rtx flags = gen_rtx_SET (VOIDmode,
+ gen_rtx_REG (CCmode, CC_REGNUM),
+ gen_rtx_COMPARE (CCmode,
+ const0_rtx,
+ operands[1]));
+ emit_insn (gen_rtx_PARALLEL (VOIDmode,
+ gen_rtvec (2,
+ flags,
+ tmp)));
+ }
+ emit_insn (gen_rtx_SET (VOIDmode,
+ operands[2],
+ gen_rtx_ASHIFTRT (SImode,
+ operands[0],
+ GEN_INT (31))));
+ DONE;
+ }
+ [(set_attr "length" "8,8,4,4")
+ (set_attr "arch" "a,a,t2,t2")]
+)
+
+(define_insn_and_split "*negdi_zero_extendsidi"
+ [(set (match_operand:DI 0 "s_register_operand" "=r,&r")
+ (neg:DI (zero_extend:DI (match_operand:SI 1 "s_register_operand" "0,r"))))
+ (clobber (reg:CC CC_REGNUM))]
+ "TARGET_32BIT"
+ "#" ; "rsbs\\t%Q0, %1, #0\;sbc\\t%R0,%R0,%R0"
+ ;; Don't care what register is input to sbc,
+ ;; since we just just need to propagate the carry.
+ "&& reload_completed"
+ [(parallel [(set (reg:CC CC_REGNUM)
+ (compare:CC (const_int 0) (match_dup 1)))
+ (set (match_dup 0) (minus:SI (const_int 0) (match_dup 1)))])
+ (set (match_dup 2) (minus:SI (minus:SI (match_dup 2) (match_dup 2))
+ (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
+ {
+ operands[2] = gen_highpart (SImode, operands[0]);
+ operands[0] = gen_lowpart (SImode, operands[0]);
+ }
+ [(set_attr "conds" "clob")
+ (set_attr "length" "8")] ;; length in thumb is 4
+)
+
;; abssi2 doesn't really clobber the condition codes if a different register
;; is being set. To keep things simple, assume during rtl manipulations that
;; it does, but tell the final scan operator the truth. Similarly for