aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJeff Law <jlaw@localhost.localdomain>2021-08-27 17:01:37 -0400
committerJeff Law <jlaw@localhost.localdomain>2021-08-27 17:01:37 -0400
commitee914ec4f811243ad72aceea4748687c74f38bc6 (patch)
tree828b93a8960fe4c65aa95aae24652c2b82bbd2ba
parent10c834f976c349970ee4b8eb3b4fce140972f256 (diff)
downloadgcc-ee914ec4f811243ad72aceea4748687c74f38bc6.zip
gcc-ee914ec4f811243ad72aceea4748687c74f38bc6.tar.gz
gcc-ee914ec4f811243ad72aceea4748687c74f38bc6.tar.bz2
Support limited setcc for H8
gcc/ * config/h8300/bitfield.md (cstore<mode>4): Remove expander. * config/h8300/h8300.c (h8300_expand_branch): Remove function. * config/h8300/h8300-protos.h (h8300_expadn_branch): Remove prototype. * config/h8300/h8300.md (eqne): New code iterator. (geultu, geultu_to_c): Similarly. * config/h8300/testcompare.md (cstore<mode>4): Dummy expander. (store_c_<mode>, store_c_i_<mode>): New define_insn_and_splits (cmp<mode>_c): New pattern
-rw-r--r--gcc/config/h8300/bitfield.md11
-rw-r--r--gcc/config/h8300/h8300-protos.h1
-rw-r--r--gcc/config/h8300/h8300.c24
-rw-r--r--gcc/config/h8300/h8300.md8
-rw-r--r--gcc/config/h8300/testcompare.md80
5 files changed, 89 insertions, 35 deletions
diff --git a/gcc/config/h8300/bitfield.md b/gcc/config/h8300/bitfield.md
index 82cb161..0d28c75 100644
--- a/gcc/config/h8300/bitfield.md
+++ b/gcc/config/h8300/bitfield.md
@@ -338,17 +338,6 @@
}
[(set_attr "length_table" "bitfield")])
-;;(define_expand "cstore<mode>4"
-;; [(use (match_operator 1 "eqne_operator"
-;; [(match_operand:QHSI 2 "h8300_dst_operand" "")
-;; (match_operand:QHSI 3 "h8300_src_operand" "")]))
-;; (clobber (match_operand:QHSI 0 "register_operand"))]
-;; "TARGET_H8300SX"
-;; {
-;; h8300_expand_store (operands);
-;; DONE;
-;; })
-
;;(define_insn "*bstzhireg"
;; [(set (match_operand:HI 0 "register_operand" "=r")
;; (match_operator:HI 1 "eqne_operator" [(cc0) (const_int 0)]))]
diff --git a/gcc/config/h8300/h8300-protos.h b/gcc/config/h8300/h8300-protos.h
index 3d34401..4a9624f 100644
--- a/gcc/config/h8300/h8300-protos.h
+++ b/gcc/config/h8300/h8300-protos.h
@@ -45,7 +45,6 @@ extern int compute_a_shift_cc (rtx *, rtx_code);
#ifdef HAVE_ATTR_cc
extern enum attr_cc compute_plussi_cc (rtx *);
#endif
-extern void h8300_expand_branch (rtx[]);
extern void h8300_expand_store (rtx[]);
extern bool expand_a_shift (machine_mode, enum rtx_code, rtx[]);
extern int h8300_shift_needs_scratch_p (int, machine_mode, rtx_code);
diff --git a/gcc/config/h8300/h8300.c b/gcc/config/h8300/h8300.c
index 5f7251a..a63c322 100644
--- a/gcc/config/h8300/h8300.c
+++ b/gcc/config/h8300/h8300.c
@@ -3256,30 +3256,8 @@ compute_logical_op_length (machine_mode mode, rtx_code code, rtx *operands, rtx_
return length;
}
-
#if 0
-/* Expand a conditional branch. */
-
-void
-h8300_expand_branch (rtx operands[])
-{
- enum rtx_code code = GET_CODE (operands[0]);
- rtx op0 = operands[1];
- rtx op1 = operands[2];
- rtx label = operands[3];
- rtx tmp;
-
- tmp = gen_rtx_COMPARE (VOIDmode, op0, op1);
- emit_insn (gen_rtx_SET (cc0_rtx, tmp));
-
- tmp = gen_rtx_fmt_ee (code, VOIDmode, cc0_rtx, const0_rtx);
- tmp = gen_rtx_IF_THEN_ELSE (VOIDmode, tmp,
- gen_rtx_LABEL_REF (VOIDmode, label),
- pc_rtx);
- emit_jump_insn (gen_rtx_SET (pc_rtx, tmp));
-}
-
-
+
/* Expand a conditional store. */
void
diff --git a/gcc/config/h8300/h8300.md b/gcc/config/h8300/h8300.md
index 7f49e42..89bfcf1 100644
--- a/gcc/config/h8300/h8300.md
+++ b/gcc/config/h8300/h8300.md
@@ -233,6 +233,14 @@
(define_code_iterator logicals [ior xor and])
(define_code_iterator ors [ior xor])
+
+(define_code_iterator eqne [eq ne])
+
+;; For storing the C flag, map from the unsigned comparison to the right
+;; code for testing the C bit.
+(define_code_iterator geultu [geu ltu])
+(define_code_attr geultu_to_c [(geu "eq") (ltu "ne")])
+
(include "movepush.md")
(include "mova.md")
diff --git a/gcc/config/h8300/testcompare.md b/gcc/config/h8300/testcompare.md
index 2919053..9ff7a51 100644
--- a/gcc/config/h8300/testcompare.md
+++ b/gcc/config/h8300/testcompare.md
@@ -70,6 +70,22 @@
"mov.w %e0,%e0"
[(set_attr "length" "2")])
+(define_insn "*cmp<mode>_c"
+ [(set (reg:CCC CC_REG)
+ (ltu (match_operand:QHSI 0 "h8300_dst_operand" "rQ")
+ (match_operand:QHSI 1 "h8300_src_operand" "rQi")))]
+ "reload_completed"
+ {
+ if (<MODE>mode == QImode)
+ return "cmp.b %X1,%X0";
+ else if (<MODE>mode == HImode)
+ return "cmp.w %T1,%T0";
+ else if (<MODE>mode == SImode)
+ return "cmp.l %S1,%S0";
+ gcc_unreachable ();
+ }
+ [(set_attr "length_table" "add")])
+
(define_insn "*cmpqi"
[(set (reg:CC CC_REG)
(compare (match_operand:QI 0 "h8300_dst_operand" "rQ")
@@ -144,3 +160,67 @@
[(parallel [(set (reg:CCZN CC_REG) (compare:CCZN (match_dup 1) (const_int 0)))
(set (match_dup 0) (match_dup 1))])])
+;; This exists solely to convince ifcvt to try some store-flag sequences.
+;;
+;; Essentially we don't want to expose a general store-flag capability.
+;; The only generally useful/profitable case is when we want to test the
+;; C bit. In that case we can use addx, subx, bst, or bist to get the bit
+;; into a GPR.
+;;
+;; Others could be handled with stc, shifts and masking, but it likely isn't
+;; profitable.
+;;
+(define_expand "cstore<mode>4"
+ [(use (match_operator 1 "eqne_operator"
+ [(match_operand:QHSI 2 "h8300_dst_operand" "")
+ (match_operand:QHSI 3 "h8300_src_operand" "")]))
+ (clobber (match_operand:QHSI 0 "register_operand"))]
+ ""
+ {
+ FAIL;
+ })
+
+;; Storing the C bit is pretty simple since there are many ways to
+;; introduce it into a GPR. addx, subx and a variety of bit manipulation
+;; instructions
+;;
+(define_insn "*store_c_<mode>"
+ [(set (match_operand:QHSI 0 "register_operand" "=r")
+ (eqne:QHSI (reg:CCC CC_REG) (const_int 0)))]
+ "reload_completed"
+ {
+ if (<CODE> == NE)
+ {
+ if (<MODE>mode == QImode)
+ return "xor.b\t%X0,%X0\;bst\t#0,%X0";
+ else if (<MODE>mode == HImode)
+ return "xor.w\t%T0,%T0\;bst\t#0,%s0";
+ else if (<MODE>mode == SImode)
+ return "xor.l\t%S0,%S0\;bst\t#0,%w0";
+ gcc_unreachable ();
+ }
+ else if (<CODE> == EQ)
+ {
+ if (<MODE>mode == QImode)
+ return "xor.b\t%X0,%X0\;bist\t#0,%X0";
+ else if (<MODE>mode == HImode)
+ return "xor.w\t%T0,%T0\;bist\t#0,%s0";
+ else if (<MODE>mode == SImode)
+ return "xor.l\t%S0,%S0\;bist\t#0,%w0";
+ gcc_unreachable ();
+ }
+ }
+ [(set (attr "length") (symbol_ref "<MODE>mode == SImode ? 6 : 4"))])
+
+;; Recognize this scc and generate code we can match
+(define_insn_and_split "*store_c_i_<mode>"
+ [(set (match_operand:QHSI 0 "register_operand" "=r")
+ (geultu:QHSI (match_operand:QHSI 1 "register_operand" "r")
+ (match_operand:QHSI 2 "register_operand" "r")))]
+ ""
+ "#"
+ "&& reload_completed"
+ [(set (reg:CCC CC_REG)
+ (ltu:CCC (match_dup 1) (match_dup 2)))
+ (set (match_dup 0)
+ (<geultu_to_c>:QHSI (reg:CCC CC_REG) (const_int 0)))])