aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorKaz Kojima <kkojima@gcc.gnu.org>2009-05-31 21:48:01 +0000
committerKaz Kojima <kkojima@gcc.gnu.org>2009-05-31 21:48:01 +0000
commited7910bb1513a00096fa7215bc3affd186eb7e9e (patch)
tree41a7964f44c8250d6c439bf45951180785a6272e /gcc
parent47ea8d4efa88226be530ca940c714cd40915abec (diff)
downloadgcc-ed7910bb1513a00096fa7215bc3affd186eb7e9e.zip
gcc-ed7910bb1513a00096fa7215bc3affd186eb7e9e.tar.gz
gcc-ed7910bb1513a00096fa7215bc3affd186eb7e9e.tar.bz2
sh.md (ashldi3_std): New define_expand.
* config/sh/sh.md (ashldi3_std): New define_expand. (ashldi3): Use it. From-SVN: r148018
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog5
-rw-r--r--gcc/config/sh/sh.md43
2 files changed, 46 insertions, 2 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 9305d0c..800f69d 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,5 +1,10 @@
2009-05-31 Kaz Kojima <kkojima@gcc.gnu.org>
+ * config/sh/sh.md (ashldi3_std): New define_expand.
+ (ashldi3): Use it.
+
+2009-05-31 Kaz Kojima <kkojima@gcc.gnu.org>
+
PR target/40313
* config/sh/sh.c: Include debug.h.
(sh_expand_epilogue): Emit a blockage insn before the frame
diff --git a/gcc/config/sh/sh.md b/gcc/config/sh/sh.md
index 54e7e30..30022d6 100644
--- a/gcc/config/sh/sh.md
+++ b/gcc/config/sh/sh.md
@@ -3850,6 +3850,34 @@ label:
[(set_attr "length" "4")
(set_attr "type" "arith")])
+;; Expander for DImode shift left with SImode operations.
+
+(define_expand "ashldi3_std"
+ [(set (match_operand:DI 0 "arith_reg_dest" "=r")
+ (ashift:DI (match_operand:DI 1 "arith_reg_operand" "r")
+ (match_operand:DI 2 "const_int_operand" "n")))]
+ "TARGET_SH1 && INTVAL (operands[2]) < 32"
+ "
+{
+ int low_word = (TARGET_LITTLE_ENDIAN ? 0 : 1);
+ int high_word = (TARGET_LITTLE_ENDIAN ? 1 : 0);
+ rtx low_src = operand_subword (operands[1], low_word, 0, DImode);
+ rtx high_src = operand_subword (operands[1], high_word, 0, DImode);
+ rtx dst = gen_reg_rtx (DImode);
+ rtx low_dst = operand_subword (dst, low_word, 1, DImode);
+ rtx high_dst = operand_subword (dst, high_word, 1, DImode);
+ rtx tmp0, tmp1;
+
+ tmp0 = gen_reg_rtx (SImode);
+ tmp1 = gen_reg_rtx (SImode);
+ emit_insn (gen_lshrsi3 (tmp0, low_src, GEN_INT (32 - INTVAL (operands[2]))));
+ emit_insn (gen_ashlsi3 (low_dst, low_src, operands[2]));
+ emit_insn (gen_ashlsi3 (tmp1, high_src, operands[2]));
+ emit_insn (gen_iorsi3 (high_dst, tmp0, tmp1));
+ emit_move_insn (operands[0], dst);
+ DONE;
+}")
+
(define_insn "ashldi3_media"
[(set (match_operand:DI 0 "arith_reg_dest" "=r,r")
(ashift:DI (match_operand:DI 1 "arith_reg_operand" "r,r")
@@ -3882,8 +3910,19 @@ label:
emit_insn (gen_ashldi3_media (operands[0], operands[1], operands[2]));
DONE;
}
- if (GET_CODE (operands[2]) != CONST_INT
- || INTVAL (operands[2]) != 1)
+ if (GET_CODE (operands[2]) == CONST_INT
+ && INTVAL (operands[2]) == 1)
+ {
+ emit_insn (gen_ashldi3_k (operands[0], operands[1]));
+ DONE;
+ }
+ else if (GET_CODE (operands[2]) == CONST_INT
+ && INTVAL (operands[2]) < 32)
+ {
+ emit_insn (gen_ashldi3_std (operands[0], operands[1], operands[2]));
+ DONE;
+ }
+ else
FAIL;
}")