From: Jeff Law Date: Thu, 7 May 2020 22:21:48 +0000 (-0400) Subject: Move all patterns and expanders out of h8300.md and into other files that are include... X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=f5fb834c96ee4dc828299f984c46608814c9f0a2;p=gcc.git Move all patterns and expanders out of h8300.md and into other files that are included into h8300.md * config/h8300/h8300.md: Move expanders and patterns into files based on functionality. * config/h8300/addsub.md: New file. * config/h8300/bitfield.md: New file * config/h8300/combiner.md: New file * config/h8300/divmod.md: New file * config/h8300/extensions.md: New file * config/h8300/jumpcall.md: New file * config/h8300/logical.md: New file * config/h8300/movepush.md: New file * config/h8300/multiply.md: New file * config/h8300/other.md: New file * config/h8300/proepi.md: New file * config/h8300/shiftrotate.md: New file * config/h8300/testcompare.md: New file commit da1de1d91088ac506c1bed0fba9b0f04c5b8c876 --- diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 0db7c65ac83..ce5c3eac23c 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,5 +1,21 @@ 2020-05-07 Jeff Law + * config/h8300/h8300.md: Move expanders and patterns into + files based on functionality. + * config/h8300/addsub.md: New file. + * config/h8300/bitfield.md: New file + * config/h8300/combiner.md: New file + * config/h8300/divmod.md: New file + * config/h8300/extensions.md: New file + * config/h8300/jumpcall.md: New file + * config/h8300/logical.md: New file + * config/h8300/movepush.md: New file + * config/h8300/multiply.md: New file + * config/h8300/other.md: New file + * config/h8300/proepi.md: New file + * config/h8300/shiftrotate.md: New file + * config/h8300/testcompare.md: New file + * config/h8300/h8300.md (adds/subs splitters): Merge into single splitter. (negation expanders and patterns): Simplify and combine using diff --git a/gcc/config/h8300/addsub.md b/gcc/config/h8300/addsub.md new file mode 100644 index 00000000000..f3392856b76 --- /dev/null +++ b/gcc/config/h8300/addsub.md @@ -0,0 +1,159 @@ +;; ---------------------------------------------------------------------- +;; ADD INSTRUCTIONS +;; ---------------------------------------------------------------------- + +(define_expand "add3" + [(set (match_operand:QHSI 0 "register_operand" "") + (plus:QHSI (match_operand:QHSI 1 "register_operand" "") + (match_operand:QHSI 2 "h8300_src_operand" "")))] + "" + "") + +(define_insn "*addqi3" + [(set (match_operand:QI 0 "h8300_dst_operand" "=rQ") + (plus:QI (match_operand:QI 1 "h8300_dst_operand" "%0") + (match_operand:QI 2 "h8300_src_operand" "rQi")))] + "h8300_operands_match_p (operands)" + "add.b %X2,%X0" + [(set_attr "length_table" "add") + (set_attr "cc" "set_zn")]) + +(define_insn "*addhi3_h8300hs" + [(set (match_operand:HI 0 "register_operand" "=r,r,r,r,r") + (plus:HI (match_operand:HI 1 "register_operand" "%0,0,0,0,0") + (match_operand:HI 2 "h8300_src_operand" "L,N,J,n,r")))] + "!TARGET_H8300SX" + "@ + adds %2,%S0 + subs %G2,%S0 + add.b %t2,%t0 + add.w %T2,%T0 + add.w %T2,%T0" + [(set_attr "length" "2,2,2,4,2") + (set_attr "cc" "none_0hit,none_0hit,clobber,set_zn,set_zn")]) + +(define_insn "*add3_incdec" + [(set (match_operand:HSI 0 "register_operand" "=r,r") + (unspec:HSI [(match_operand:HSI 1 "register_operand" "0,0") + (match_operand:HSI 2 "incdec_operand" "M,O")] + UNSPEC_INCDEC))] + "" + { + if (which_alternative == 0) + return mode == HImode ? "inc.w\t%2,%T0" : "inc.l\t%2,%S0"; + else if (which_alternative == 1) + return mode == HImode ? "dec.w\t%G2,%T0" : "dec.l\t%G2,%S0"; + gcc_unreachable (); + } + [(set_attr "length" "2,2") + (set_attr "cc" "set_zn,set_zn")]) + +(define_insn "*addhi3_h8sx" + [(set (match_operand:HI 0 "h8300_dst_operand" "=rU,rU,r,rQ") + (plus:HI (match_operand:HI 1 "h8300_dst_operand" "%0,0,0,0") + (match_operand:HI 2 "h8300_src_operand" "P3>X,P3mode, operands); + DONE; + }) + + +(define_insn "*addsi_h8300hs" + [(set (match_operand:SI 0 "h8300_dst_operand" "=rQ,rQ") + (plus:SI (match_operand:SI 1 "h8300_dst_operand" "%0,0") + (match_operand:SI 2 "h8300_src_operand" "i,rQ")))] + "h8300_operands_match_p (operands)" +{ + return output_plussi (operands); +} + [(set (attr "length") + (symbol_ref "compute_plussi_length (operands)")) + (set (attr "cc") + (symbol_ref "compute_plussi_cc (operands)"))]) + +;; ---------------------------------------------------------------------- +;; SUBTRACT INSTRUCTIONS +;; ---------------------------------------------------------------------- + +(define_expand "sub3" + [(set (match_operand:QHSI 0 "register_operand" "") + (minus:QHSI (match_operand:QHSI 1 "register_operand" "") + (match_operand:QHSI 2 "h8300_src_operand" "")))] + "" + { + }) + +(define_insn "*subqi3" + [(set (match_operand:QI 0 "h8300_dst_operand" "=rQ") + (minus:QI (match_operand:QI 1 "h8300_dst_operand" "0") + (match_operand:QI 2 "h8300_dst_operand" "rQ")))] + "h8300_operands_match_p (operands)" + "sub.b %X2,%X0" + [(set_attr "length_table" "add") + (set_attr "cc" "set_zn")]) + +(define_insn "*sub3_h8300hs" + [(set (match_operand:HSI 0 "h8300_dst_operand" "=rQ,rQ") + (minus:HSI (match_operand:HSI 1 "h8300_dst_operand" "0,0") + (match_operand:HSI 2 "h8300_src_operand" "rQ,i")))] + "h8300_operands_match_p (operands)" + { + if (mode == HImode) + return "sub.w %T2,%T0"; + else if (mode == SImode) + return "sub.l %S2,%S0"; + gcc_unreachable (); + } + [(set_attr "length_table" "add") + (set_attr "cc" "set_zn")]) + +;; ---------------------------------------------------------------------- +;; NEGATION INSTRUCTIONS +;; ---------------------------------------------------------------------- + +(define_expand "neg2" + [(set (match_operand:QHSIF 0 "register_operand" "") + (neg:QHSIF (match_operand:QHSIF 1 "register_operand" "")))] + "" + "") + +(define_insn "*neg2" + [(set (match_operand:QHSI 0 "h8300_dst_operand" "=rQ") + (neg:QHSI (match_operand:QHSI 1 "h8300_dst_operand" "0")))] + "" + { + if (mode == E_QImode) + return "neg %X0"; + if (mode == E_HImode) + return "neg.w %T0"; + if (mode == E_SImode) + return "neg.l %S0"; + gcc_unreachable (); + } + [(set_attr "length_table" "unary") + (set_attr "cc" "set_zn")]) + + +(define_insn "*negsf2_h8300hs" + [(set (match_operand:SF 0 "register_operand" "=r") + (neg:SF (match_operand:SF 1 "register_operand" "0")))] + "" + "xor.w\\t#32768,%e0" + [(set_attr "length" "4")]) + diff --git a/gcc/config/h8300/bitfield.md b/gcc/config/h8300/bitfield.md new file mode 100644 index 00000000000..bed712d830b --- /dev/null +++ b/gcc/config/h8300/bitfield.md @@ -0,0 +1,440 @@ +;; ----------------------------------------------------------------- +;; BIT FIELDS +;; ----------------------------------------------------------------- +;; The H8/300 has given 1/8th of its opcode space to bitfield +;; instructions so let's use them as well as we can. + +;; You'll never believe all these patterns perform one basic action -- +;; load a bit from the source, optionally invert the bit, then store it +;; in the destination (which is known to be zero). +;; +;; Combine obviously need some work to better identify this situation and +;; canonicalize the form better. + +;; +;; Inverted loads with a 16bit destination. +;; + +(define_insn "" + [(set (match_operand:HI 0 "register_operand" "=&r") + (zero_extract:HI (xor:HI (match_operand:HI 1 "register_operand" "r") + (match_operand:HI 3 "const_int_operand" "n")) + (const_int 1) + (match_operand:HI 2 "const_int_operand" "n")))] + "(TARGET_H8300SX) + && (1 << INTVAL (operands[2])) == INTVAL (operands[3])" + "sub.w %0,%0\;bild %Z2,%Y1\;bst #0,%X0" + [(set_attr "length" "8")]) + +;; +;; Normal loads with a 32bit destination. +;; + +(define_insn "*extzv_1_r_h8300hs" + [(set (match_operand:SI 0 "register_operand" "=r,r") + (zero_extract:SI (match_operand:SI 1 "register_operand" "?0,r") + (const_int 1) + (match_operand 2 "const_int_operand" "n,n")))] + "INTVAL (operands[2]) < 16" +{ + return output_simode_bld (0, operands); +} + [(set_attr "cc" "set_znv,set_znv") + (set_attr "length" "8,6")]) + +;; +;; Inverted loads with a 32bit destination. +;; + +(define_insn "*extzv_1_r_inv_h8300hs" + [(set (match_operand:SI 0 "register_operand" "=r,r") + (zero_extract:SI (xor:SI (match_operand:SI 1 "register_operand" "?0,r") + (match_operand 3 "const_int_operand" "n,n")) + (const_int 1) + (match_operand 2 "const_int_operand" "n,n")))] + "INTVAL (operands[2]) < 16 + && (1 << INTVAL (operands[2])) == INTVAL (operands[3])" +{ + return output_simode_bld (1, operands); +} + [(set_attr "cc" "set_znv,set_znv") + (set_attr "length" "8,6")]) + +(define_expand "insv" + [(set (zero_extract:HI (match_operand:HI 0 "general_operand" "") + (match_operand:HI 1 "general_operand" "") + (match_operand:HI 2 "general_operand" "")) + (match_operand:HI 3 "general_operand" ""))] + "TARGET_H8300SX" + { + if (GET_CODE (operands[1]) == CONST_INT + && GET_CODE (operands[2]) == CONST_INT + && INTVAL (operands[1]) <= 8 + && INTVAL (operands[2]) >= 0 + && INTVAL (operands[1]) + INTVAL (operands[2]) <= 8 + && memory_operand (operands[0], GET_MODE (operands[0]))) + { + /* If the source operand is zero, it's better to use AND rather + than BFST. Likewise OR if the operand is all ones. */ + if (GET_CODE (operands[3]) == CONST_INT) + { + HOST_WIDE_INT mask = (1 << INTVAL (operands[1])) - 1; + if ((INTVAL (operands[3]) & mask) == 0) + FAIL; + if ((INTVAL (operands[3]) & mask) == mask) + FAIL; + } + if (! bit_memory_operand (operands[0], GET_MODE (operands[0]))) + { + if (!can_create_pseudo_p ()) + FAIL; + operands[0] = replace_equiv_address (operands[0], force_reg (Pmode, + XEXP (operands[0], 0))); + } + operands[3] = gen_lowpart (QImode, operands[3]); + if (! operands[3]) + FAIL; + if (! register_operand (operands[3], QImode)) + { + if (!can_create_pseudo_p ()) + FAIL; + operands[3] = force_reg (QImode, operands[3]); + } + emit_insn (gen_bfst (adjust_address (operands[0], QImode, 0), + operands[3], operands[1], operands[2])); + DONE; + } + FAIL; + }) + +(define_insn "" + [(set (zero_extract:HI (match_operand:HI 0 "register_operand" "+r") + (const_int 1) + (match_operand:HI 1 "immediate_operand" "n")) + (match_operand:HI 2 "register_operand" "r"))] + "" + "bld #0,%R2\;bst %Z1,%Y0 ; i1" + [(set_attr "length" "4")]) + +(define_expand "extzv" + [(set (match_operand:HI 0 "register_operand" "") + (zero_extract:HI (match_operand:HI 1 "bit_operand" "") + (match_operand:HI 2 "general_operand" "") + (match_operand:HI 3 "general_operand" "")))] + "TARGET_H8300SX" + { + if (GET_CODE (operands[2]) == CONST_INT + && GET_CODE (operands[3]) == CONST_INT + && INTVAL (operands[2]) <= 8 + && INTVAL (operands[3]) >= 0 + && INTVAL (operands[2]) + INTVAL (operands[3]) <= 8 + && memory_operand (operands[1], QImode)) + { + rtx temp; + + /* Optimize the case where we're extracting into a paradoxical + subreg. It's only necessary to extend to the inner reg. */ + if (GET_CODE (operands[0]) == SUBREG + && subreg_lowpart_p (operands[0]) + && (GET_MODE_SIZE (GET_MODE (SUBREG_REG (operands[0]))) + < GET_MODE_SIZE (GET_MODE (operands[0]))) + && (GET_MODE_CLASS (GET_MODE (SUBREG_REG (operands[0]))) + == MODE_INT)) + operands[0] = SUBREG_REG (operands[0]); + + if (!can_create_pseudo_p ()) + temp = gen_lowpart (QImode, operands[0]); + else + temp = gen_reg_rtx (QImode); + if (! temp) + FAIL; + if (! bit_memory_operand (operands[1], QImode)) + { + if (!can_create_pseudo_p ()) + FAIL; + operands[1] = replace_equiv_address (operands[1], + force_reg (Pmode, XEXP (operands[1], 0))); + } + emit_insn (gen_bfld (temp, operands[1], operands[2], operands[3])); + convert_move (operands[0], temp, 1); + DONE; + } + FAIL; + }) + +;; BAND, BOR, and BXOR patterns + +(define_insn "" + [(set (match_operand:HI 0 "bit_operand" "=Ur") + (match_operator:HI 4 "bit_operator" + [(zero_extract:HI (match_operand:HI 1 "register_operand" "r") + (const_int 1) + (match_operand:HI 2 "immediate_operand" "n")) + (match_operand:HI 3 "bit_operand" "0")]))] + "" + "bld %Z2,%Y1\;b%c4 #0,%R0\;bst #0,%R0; bl1" + [(set_attr "length" "6")]) + +(define_insn "" + [(set (match_operand:HI 0 "bit_operand" "=Ur") + (match_operator:HI 5 "bit_operator" + [(zero_extract:HI (match_operand:HI 1 "register_operand" "r") + (const_int 1) + (match_operand:HI 2 "immediate_operand" "n")) + (zero_extract:HI (match_operand:HI 3 "register_operand" "r") + (const_int 1) + (match_operand:HI 4 "immediate_operand" "n"))]))] + "" + "bld %Z2,%Y1\;b%c5 %Z4,%Y3\;bst #0,%R0; bl3" + [(set_attr "length" "6")]) + +(define_insn "bfld" + [(set (match_operand:QI 0 "register_operand" "=r") + (zero_extract:QI (match_operand:QI 1 "bit_memory_operand" "WU") + (match_operand:QI 2 "immediate_operand" "n") + (match_operand:QI 3 "immediate_operand" "n")))] + "TARGET_H8300SX && INTVAL (operands[2]) + INTVAL (operands[3]) <= 8" +{ + operands[2] = GEN_INT ((1 << (INTVAL (operands[2]) + INTVAL (operands[3]))) + - (1 << INTVAL (operands[3]))); + return "bfld %2,%1,%R0"; +} + [(set_attr "cc" "none_0hit") + (set_attr "length_table" "bitfield")]) + +(define_insn "bfst" + [(set (zero_extract:QI (match_operand:QI 0 "bit_memory_operand" "+WU") + (match_operand:QI 2 "immediate_operand" "n") + (match_operand:QI 3 "immediate_operand" "n")) + (match_operand:QI 1 "register_operand" "r"))] + "TARGET_H8300SX && INTVAL (operands[2]) + INTVAL (operands[3]) <= 8" +{ + operands[2] = GEN_INT ((1 << (INTVAL (operands[2]) + INTVAL (operands[3]))) + - (1 << INTVAL (operands[3]))); + return "bfst %R1,%2,%0"; +} + [(set_attr "cc" "none_0hit") + (set_attr "length_table" "bitfield")]) + +(define_expand "cstoreqi4" + [(use (match_operator 1 "eqne_operator" + [(match_operand:QI 2 "h8300_dst_operand" "") + (match_operand:QI 3 "h8300_src_operand" "")])) + (clobber (match_operand:HI 0 "register_operand"))] + "TARGET_H8300SX" + { + h8300_expand_store (operands); + DONE; + }) + +(define_expand "cstorehi4" + [(use (match_operator 1 "eqne_operator" + [(match_operand:HI 2 "h8300_dst_operand" "") + (match_operand:HI 3 "h8300_src_operand" "")])) + (clobber (match_operand:HI 0 "register_operand"))] + "TARGET_H8300SX" + { + h8300_expand_store (operands); + DONE; + }) + +(define_expand "cstoresi4" + [(use (match_operator 1 "eqne_operator" + [(match_operand:SI 2 "h8300_dst_operand" "") + (match_operand:SI 3 "h8300_src_operand" "")])) + (clobber (match_operand:HI 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)]))] + "TARGET_H8300SX" + "mulu.w #0,%T0\;b%k1 .Lh8BR%=\;inc.w #1,%T0\\n.Lh8BR%=:" + [(set_attr "cc" "clobber")]) + +(define_insn_and_split "*cmpstz" + [(set (zero_extract:QI (match_operand:QI 0 "bit_memory_operand" "+WU,WU") + (const_int 1) + (match_operand:QI 1 "immediate_operand" "n,n")) + (match_operator:QI 2 "eqne_operator" + [(match_operand 3 "h8300_dst_operand" "r,rQ") + (match_operand 4 "h8300_src_operand" "I,rQi")]))] + "TARGET_H8300SX + && (GET_MODE (operands[3]) == GET_MODE (operands[4]) + || GET_CODE (operands[4]) == CONST_INT) + && GET_MODE_CLASS (GET_MODE (operands[3])) == MODE_INT + && GET_MODE_SIZE (GET_MODE (operands[3])) <= 4" + "#" + "reload_completed" + [(set (cc0) (match_dup 5)) + (set (zero_extract:QI (match_dup 0) (const_int 1) (match_dup 1)) + (match_op_dup:QI 2 [(cc0) (const_int 0)]))] + { + operands[5] = gen_rtx_COMPARE (VOIDmode, operands[3], operands[4]); + } + [(set_attr "cc" "set_znv,compare")]) + +(define_insn "*bstz" + [(set (zero_extract:QI (match_operand:QI 0 "bit_memory_operand" "+WU") + (const_int 1) + (match_operand:QI 1 "immediate_operand" "n")) + (eq:QI (cc0) (const_int 0)))] + "TARGET_H8300SX && reload_completed" + "bstz %1,%0" + [(set_attr "cc" "none_0hit") + (set_attr "length_table" "unary")]) + +(define_insn "*bistz" + [(set (zero_extract:QI (match_operand:QI 0 "bit_memory_operand" "+WU") + (const_int 1) + (match_operand:QI 1 "immediate_operand" "n")) + (ne:QI (cc0) (const_int 0)))] + "TARGET_H8300SX && reload_completed" + "bistz %1,%0" + [(set_attr "cc" "none_0hit") + (set_attr "length_table" "unary")]) + +(define_insn_and_split "*cmpcondbset" + [(set (match_operand:QI 0 "nonimmediate_operand" "=WU,WU") + (if_then_else:QI (match_operator 1 "eqne_operator" + [(match_operand 2 "h8300_dst_operand" "r,rQ") + (match_operand 3 "h8300_src_operand" "I,rQi")]) + (ior:QI (match_operand:QI 4 "bit_memory_operand" "0,0") + (match_operand:QI 5 "single_one_operand" "n,n")) + (match_dup 4)))] + "TARGET_H8300SX" + "#" + "reload_completed" + [(set (cc0) (match_dup 6)) + (set (match_dup 0) + (if_then_else:QI (match_op_dup 1 [(cc0) (const_int 0)]) + (ior:QI (match_dup 4) (match_dup 5)) + (match_dup 4)))] + { + operands[6] = gen_rtx_COMPARE (VOIDmode, operands[2], operands[3]); + } + [(set_attr "cc" "set_znv,compare")]) + +(define_insn "*condbset" + [(set (match_operand:QI 0 "bit_memory_operand" "=WU") + (if_then_else:QI (match_operator:QI 2 "eqne_operator" + [(cc0) (const_int 0)]) + (ior:QI (match_operand:QI 3 "bit_memory_operand" "0") + (match_operand:QI 1 "single_one_operand" "n")) + (match_dup 3)))] + "TARGET_H8300SX && reload_completed" + "bset/%j2\t%V1,%0" + [(set_attr "cc" "none_0hit") + (set_attr "length_table" "logicb")]) + +(define_insn_and_split "*cmpcondbclr" + [(set (match_operand:QI 0 "nonimmediate_operand" "=WU,WU") + (if_then_else:QI (match_operator 1 "eqne_operator" + [(match_operand 2 "h8300_dst_operand" "r,rQ") + (match_operand 3 "h8300_src_operand" "I,rQi")]) + (and:QI (match_operand:QI 4 "bit_memory_operand" "0,0") + (match_operand:QI 5 "single_zero_operand" "n,n")) + (match_dup 4)))] + "TARGET_H8300SX" + "#" + "reload_completed" + [(set (cc0) (match_dup 6)) + (set (match_dup 0) + (if_then_else:QI (match_op_dup 1 [(cc0) (const_int 0)]) + (and:QI (match_dup 4) (match_dup 5)) + (match_dup 4)))] + { + operands[6] = gen_rtx_COMPARE (VOIDmode, operands[2], operands[3]); + } + [(set_attr "cc" "set_znv,compare")]) + +(define_insn "*condbclr" + [(set (match_operand:QI 0 "bit_memory_operand" "=WU") + (if_then_else:QI (match_operator:QI 2 "eqne_operator" + [(cc0) (const_int 0)]) + (and:QI (match_operand:QI 3 "bit_memory_operand" "0") + (match_operand:QI 1 "single_zero_operand" "n")) + (match_dup 3)))] + "TARGET_H8300SX && reload_completed" + "bclr/%j2\t%W1,%0" + [(set_attr "cc" "none_0hit") + (set_attr "length_table" "logicb")]) + +(define_insn_and_split "*cmpcondbsetreg" + [(set (match_operand:QI 0 "nonimmediate_operand" "=WU,WU") + (if_then_else:QI (match_operator 1 "eqne_operator" + [(match_operand 2 "h8300_dst_operand" "r,rQ") + (match_operand 3 "h8300_src_operand" "I,rQi")]) + (ior:QI (match_operand:QI 4 "bit_memory_operand" "0,0") + (ashift:QI (const_int 1) + (match_operand:QI 5 "register_operand" "r,r"))) + (match_dup 4)))] + "TARGET_H8300SX" + "#" + "reload_completed" + [(set (cc0) (match_dup 6)) + (set (match_dup 0) + (if_then_else:QI (match_op_dup 1 [(cc0) (const_int 0)]) + (ior:QI (match_dup 4) + (ashift:QI (const_int 1) + (match_operand:QI 5 "register_operand" "r,r"))) + (match_dup 4)))] + { + operands[6] = gen_rtx_COMPARE (VOIDmode, operands[2], operands[3]); + } + [(set_attr "cc" "set_znv,compare")]) + +(define_insn "*condbsetreg" + [(set (match_operand:QI 0 "bit_memory_operand" "=WU") + (if_then_else:QI (match_operator:QI 2 "eqne_operator" + [(cc0) (const_int 0)]) + (ior:QI (match_operand:QI 3 "bit_memory_operand" "0") + (ashift:QI (const_int 1) + (match_operand:QI 1 "register_operand" "r"))) + (match_dup 3)))] + "TARGET_H8300SX && reload_completed" + "bset/%j2\t%R1,%0" + [(set_attr "cc" "none_0hit") + (set_attr "length_table" "logicb")]) + +(define_insn_and_split "*cmpcondbclrreg" + [(set (match_operand:QI 0 "nonimmediate_operand" "=WU,WU") + (if_then_else:QI (match_operator 1 "eqne_operator" + [(match_operand 2 "h8300_dst_operand" "r,rQ") + (match_operand 3 "h8300_src_operand" "I,rQi")]) + (and:QI (match_operand:QI 4 "bit_memory_operand" "0,0") + (ashift:QI (const_int 1) + (match_operand:QI 5 "register_operand" "r,r"))) + (match_dup 4)))] + "TARGET_H8300SX" + "#" + "reload_completed" + [(set (cc0) (match_dup 6)) + (set (match_dup 0) + (if_then_else:QI (match_op_dup 1 [(cc0) (const_int 0)]) + (and:QI (match_dup 4) + (ashift:QI (const_int 1) + (match_operand:QI 5 "register_operand" "r,r"))) + (match_dup 4)))] + { + operands[6] = gen_rtx_COMPARE (VOIDmode, operands[2], operands[3]); + } + [(set_attr "cc" "set_znv,compare")]) + +(define_insn "*condbclrreg" + [(set (match_operand:QI 0 "bit_memory_operand" "=WU") + (if_then_else:QI (match_operator:QI 2 "eqne_operator" + [(cc0) (const_int 0)]) + (and:QI (match_operand:QI 3 "bit_memory_operand" "0") + (ashift:QI (const_int 1) + (match_operand:QI 1 "register_operand" "r"))) + (match_dup 3)))] + "TARGET_H8300SX && reload_completed" + "bclr/%j2\t%R1,%0" + [(set_attr "cc" "none_0hit") + (set_attr "length_table" "logicb")]) + diff --git a/gcc/config/h8300/combiner.md b/gcc/config/h8300/combiner.md new file mode 100644 index 00000000000..f59ff5f15bd --- /dev/null +++ b/gcc/config/h8300/combiner.md @@ -0,0 +1,775 @@ +;; ----------------------------------------------------------------- +;; COMBINE PATTERNS +;; ----------------------------------------------------------------- + +;; insv:SI + +(define_insn "*insv_si_1_n" + [(set (zero_extract:SI (match_operand:SI 0 "register_operand" "+r") + (const_int 1) + (match_operand:SI 1 "const_int_operand" "n")) + (match_operand:SI 2 "register_operand" "r"))] + "INTVAL (operands[1]) < 16" + "bld\\t#0,%w2\;bst\\t%Z1,%Y0" + [(set_attr "length" "4")]) + +(define_insn "*insv_si_1_n_lshiftrt" + [(set (zero_extract:SI (match_operand:SI 0 "register_operand" "+r") + (const_int 1) + (match_operand:SI 1 "const_int_operand" "n")) + (lshiftrt:SI (match_operand:SI 2 "register_operand" "r") + (match_operand:SI 3 "const_int_operand" "n")))] + "INTVAL (operands[1]) < 16 && INTVAL (operands[3]) < 16" + "bld\\t%Z3,%Y2\;bst\\t%Z1,%Y0" + [(set_attr "length" "4")]) + +(define_insn "*insv_si_1_n_lshiftrt_16" + [(set (zero_extract:SI (match_operand:SI 0 "register_operand" "+r") + (const_int 1) + (match_operand:SI 1 "const_int_operand" "n")) + (lshiftrt:SI (match_operand:SI 2 "register_operand" "r") + (const_int 16)))] + "INTVAL (operands[1]) < 16" + "rotr.w\\t%e2\;rotl.w\\t%e2\;bst\\t%Z1,%Y0" + [(set_attr "length" "6")]) + +(define_insn "*insv_si_8_8" + [(set (zero_extract:SI (match_operand:SI 0 "register_operand" "+r") + (const_int 8) + (const_int 8)) + (match_operand:SI 1 "register_operand" "r"))] + "" + "mov.b\\t%w1,%x0" + [(set_attr "length" "2")]) + +(define_insn "*insv_si_8_8_lshiftrt_8" + [(set (zero_extract:SI (match_operand:SI 0 "register_operand" "+r") + (const_int 8) + (const_int 8)) + (lshiftrt:SI (match_operand:SI 1 "register_operand" "r") + (const_int 8)))] + "" + "mov.b\\t%x1,%x0" + [(set_attr "length" "2")]) + +;; extzv:SI + +(define_insn "*extzv_8_8" + [(set (match_operand:SI 0 "register_operand" "=r,r") + (zero_extract:SI (match_operand:SI 1 "register_operand" "?0,r") + (const_int 8) + (const_int 8)))] + "" + "@ + mov.b\\t%x1,%w0\;extu.w\\t%f0\;extu.l\\t%S0 + sub.l\\t%S0,%S0\;mov.b\\t%x1,%w0" + [(set_attr "cc" "set_znv,clobber") + (set_attr "length" "6,4")]) + +(define_insn "*extzv_8_16" + [(set (match_operand:SI 0 "register_operand" "=r") + (zero_extract:SI (match_operand:SI 1 "register_operand" "r") + (const_int 8) + (const_int 16)))] + "" + "mov.w\\t%e1,%f0\;extu.w\\t%f0\;extu.l\\t%S0" + [(set_attr "cc" "set_znv") + (set_attr "length" "6")]) + +(define_insn "*extzv_16_8" + [(set (match_operand:SI 0 "register_operand" "=r") + (zero_extract:SI (match_operand:SI 1 "register_operand" "r") + (const_int 16) + (const_int 8))) + (clobber (match_scratch:SI 2 "=&r"))] + "TARGET_H8300H" + "mov.w\\t%e1,%f2\;mov.b\\t%x1,%w0\;mov.b\\t%w2,%x0\;extu.l\\t%S0" + [(set_attr "length" "8") + (set_attr "cc" "set_znv")]) + +;; Extract the exponent of a float. + +(define_insn_and_split "*extzv_8_23" + [(set (match_operand:SI 0 "register_operand" "=r") + (zero_extract:SI (match_operand:SI 1 "register_operand" "0") + (const_int 8) + (const_int 23)))] + "" + "#" + "&& reload_completed" + [(parallel [(set (match_dup 0) + (ashift:SI (match_dup 0) + (const_int 1))) + (clobber (scratch:QI))]) + (parallel [(set (match_dup 0) + (lshiftrt:SI (match_dup 0) + (const_int 24))) + (clobber (scratch:QI))])] + "") + +;; and:SI + +;; ((SImode) HImode) << 15 + +(define_insn_and_split "*twoshifts_l16_r1" + [(set (match_operand:SI 0 "register_operand" "=r") + (and:SI (ashift:SI (match_operand:SI 1 "register_operand" "0") + (const_int 15)) + (const_int 2147450880)))] + "" + "#" + "&& reload_completed" + [(parallel [(set (match_dup 0) + (ashift:SI (match_dup 0) + (const_int 16))) + (clobber (scratch:QI))]) + (parallel [(set (match_dup 0) + (lshiftrt:SI (match_dup 0) + (const_int 1))) + (clobber (scratch:QI))])] + "") + +;; Transform (SImode << B) & 0xffff into (SImode) (HImode << B). + +(define_insn_and_split "*andsi3_ashift_n_lower" + [(set (match_operand:SI 0 "register_operand" "=r,r") + (and:SI (ashift:SI (match_operand:SI 1 "register_operand" "0,0") + (match_operand:QI 2 "const_int_operand" "S,n")) + (match_operand:SI 3 "const_int_operand" "n,n"))) + (clobber (match_scratch:QI 4 "=X,&r"))] + "INTVAL (operands[2]) <= 15 + && UINTVAL (operands[3]) == ((HOST_WIDE_INT_M1U << INTVAL (operands[2])) + & 0xffff)" + "#" + "&& reload_completed" + [(parallel [(set (match_dup 5) + (ashift:HI (match_dup 5) + (match_dup 2))) + (clobber (match_dup 4))]) + (set (match_dup 0) + (zero_extend:SI (match_dup 5)))] + { + operands[5] = gen_rtx_REG (HImode, REGNO (operands[0])); + }) + +;; Accept (A >> 30) & 2 and the like. + +(define_insn "*andsi3_lshiftrt_n_sb" + [(set (match_operand:SI 0 "register_operand" "=r") + (and:SI (lshiftrt:SI (match_operand:SI 1 "register_operand" "0") + (match_operand:SI 2 "const_int_operand" "n")) + (match_operand:SI 3 "single_one_operand" "n")))] + "exact_log2 (INTVAL (operands[3])) < 16 + && INTVAL (operands[2]) + exact_log2 (INTVAL (operands[3])) == 31" +{ + operands[3] = GEN_INT (exact_log2 (INTVAL (operands[3]))); + return "shll.l\\t%S0\;xor.l\\t%S0,%S0\;bst\\t%Z3,%Y0"; +} + [(set_attr "length" "8")]) + +(define_insn_and_split "*andsi3_lshiftrt_9_sb" + [(set (match_operand:SI 0 "register_operand" "=r") + (and:SI (lshiftrt:SI (match_operand:SI 1 "register_operand" "0") + (const_int 9)) + (const_int 4194304)))] + "" + "#" + "&& reload_completed" + [(set (match_dup 0) + (and:SI (lshiftrt:SI (match_dup 0) + (const_int 25)) + (const_int 64))) + (parallel [(set (match_dup 0) + (ashift:SI (match_dup 0) + (const_int 16))) + (clobber (scratch:QI))])] + "") + +;; plus:SI + +(define_insn "*addsi3_upper" + [(set (match_operand:SI 0 "register_operand" "=r") + (plus:SI (mult:SI (match_operand:SI 1 "register_operand" "r") + (const_int 65536)) + (match_operand:SI 2 "register_operand" "0")))] + "" + "add.w\\t%f1,%e0" + [(set_attr "length" "2")]) + +(define_insn "*addsi3_lshiftrt_16_zexthi" + [(set (match_operand:SI 0 "register_operand" "=r") + (plus:SI (lshiftrt:SI (match_operand:SI 1 "register_operand" "r") + (const_int 16)) + (zero_extend:SI (match_operand:HI 2 "register_operand" "0"))))] + "" + "add.w\\t%e1,%f0\;xor.w\\t%e0,%e0\;rotxl.w\\t%e0" + [(set_attr "length" "6")]) + +(define_insn_and_split "*addsi3_and_r_1" + [(set (match_operand:SI 0 "register_operand" "=r") + (plus:SI (and:SI (match_operand:SI 1 "register_operand" "r") + (const_int 1)) + (match_operand:SI 2 "register_operand" "0")))] + "" + "#" + "&& reload_completed" + [(set (cc0) (compare (zero_extract:SI (match_dup 1) + (const_int 1) + (const_int 0)) + (const_int 0))) + (set (pc) + (if_then_else (eq (cc0) + (const_int 0)) + (label_ref (match_dup 3)) + (pc))) + (set (match_dup 2) + (plus:SI (match_dup 2) + (const_int 1))) + (match_dup 3)] + { + operands[3] = gen_label_rtx (); + }) + +(define_insn_and_split "*addsi3_and_not_r_1" + [(set (match_operand:SI 0 "register_operand" "=r") + (plus:SI (and:SI (not:SI (match_operand:SI 1 "register_operand" "r")) + (const_int 1)) + (match_operand:SI 2 "register_operand" "0")))] + "" + "#" + "&& reload_completed" + [(set (cc0) (compare (zero_extract:SI (match_dup 1) + (const_int 1) + (const_int 0)) + (const_int 0))) + (set (pc) + (if_then_else (ne (cc0) + (const_int 0)) + (label_ref (match_dup 3)) + (pc))) + (set (match_dup 2) + (plus:SI (match_dup 2) + (const_int 1))) + (match_dup 3)] + { + operands[3] = gen_label_rtx (); + }) + +;; [ix]or:HI + +(define_insn "*ixorhi3_zext" + [(set (match_operand:HI 0 "register_operand" "=r") + (match_operator:HI 1 "iorxor_operator" + [(zero_extend:HI (match_operand:QI 2 "register_operand" "r")) + (match_operand:HI 3 "register_operand" "0")]))] + "" + "%c1.b\\t%X2,%s0" + [(set_attr "length" "2")]) + +;; [ix]or:SI + +(define_insn "*ixorsi3_zext_qi" + [(set (match_operand:SI 0 "register_operand" "=r") + (match_operator:SI 1 "iorxor_operator" + [(zero_extend:SI (match_operand:QI 2 "register_operand" "r")) + (match_operand:SI 3 "register_operand" "0")]))] + "" + "%c1.b\\t%X2,%w0" + [(set_attr "length" "2")]) + +(define_insn "*ixorsi3_zext_hi" + [(set (match_operand:SI 0 "register_operand" "=r") + (match_operator:SI 1 "iorxor_operator" + [(zero_extend:SI (match_operand:HI 2 "register_operand" "r")) + (match_operand:SI 3 "register_operand" "0")]))] + "" + "%c1.w\\t%T2,%f0" + [(set_attr "length" "2")]) + +(define_insn "*ixorsi3_ashift_16" + [(set (match_operand:SI 0 "register_operand" "=r") + (match_operator:SI 1 "iorxor_operator" + [(ashift:SI (match_operand:SI 2 "register_operand" "r") + (const_int 16)) + (match_operand:SI 3 "register_operand" "0")]))] + "" + "%c1.w\\t%f2,%e0" + [(set_attr "length" "2")]) + +(define_insn "*ixorsi3_lshiftrt_16" + [(set (match_operand:SI 0 "register_operand" "=r") + (match_operator:SI 1 "iorxor_operator" + [(lshiftrt:SI (match_operand:SI 2 "register_operand" "r") + (const_int 16)) + (match_operand:SI 3 "register_operand" "0")]))] + "" + "%c1.w\\t%e2,%f0" + [(set_attr "length" "2")]) + +;; ior:HI + +(define_insn "*iorhi3_ashift_8" + [(set (match_operand:HI 0 "register_operand" "=r") + (ior:HI (ashift:HI (match_operand:HI 1 "register_operand" "r") + (const_int 8)) + (match_operand:HI 2 "register_operand" "0")))] + "" + "or.b\\t%s1,%t0" + [(set_attr "length" "2")]) + +(define_insn "*iorhi3_lshiftrt_8" + [(set (match_operand:HI 0 "register_operand" "=r") + (ior:HI (lshiftrt:HI (match_operand:HI 1 "register_operand" "r") + (const_int 8)) + (match_operand:HI 2 "register_operand" "0")))] + "" + "or.b\\t%t1,%s0" + [(set_attr "length" "2")]) + +(define_insn "*iorhi3_two_qi" + [(set (match_operand:HI 0 "register_operand" "=r") + (ior:HI (zero_extend:HI (match_operand:QI 1 "register_operand" "0")) + (ashift:HI (match_operand:HI 2 "register_operand" "r") + (const_int 8))))] + "" + "mov.b\\t%s2,%t0" + [(set_attr "length" "2")]) + +(define_insn "*iorhi3_two_qi_mem" + [(set (match_operand:HI 0 "register_operand" "=&r") + (ior:HI (zero_extend:HI (match_operand:QI 1 "memory_operand" "m")) + (ashift:HI (subreg:HI (match_operand:QI 2 "memory_operand" "m") 0) + (const_int 8))))] + "" + "mov.b\\t%X2,%t0\;mov.b\\t%X1,%s0" + [(set_attr "length" "16")]) + +(define_split + [(set (match_operand:HI 0 "register_operand" "") + (ior:HI (zero_extend:HI (match_operand:QI 1 "memory_operand" "")) + (ashift:HI (subreg:HI (match_operand:QI 2 "memory_operand" "") 0) + (const_int 8))))] + "reload_completed + && byte_accesses_mergeable_p (XEXP (operands[2], 0), XEXP (operands[1], 0))" + [(set (match_dup 0) + (match_dup 3))] + { + operands[3] = gen_rtx_MEM (HImode, XEXP (operands[2], 0)); + }) + +;; ior:SI + +(define_insn "*iorsi3_two_hi" + [(set (match_operand:SI 0 "register_operand" "=r") + (ior:SI (zero_extend:SI (match_operand:HI 1 "register_operand" "0")) + (ashift:SI (match_operand:SI 2 "register_operand" "r") + (const_int 16))))] + "" + "mov.w\\t%f2,%e0" + [(set_attr "length" "2")]) + +(define_insn_and_split "*iorsi3_two_qi_zext" + [(set (match_operand:SI 0 "register_operand" "=&r") + (ior:SI (zero_extend:SI (match_operand:QI 1 "memory_operand" "m")) + (and:SI (ashift:SI (subreg:SI (match_operand:QI 2 "memory_operand" "m") 0) + (const_int 8)) + (const_int 65280))))] + "" + "#" + "&& reload_completed" + [(set (match_dup 3) + (ior:HI (zero_extend:HI (match_dup 1)) + (ashift:HI (subreg:HI (match_dup 2) 0) + (const_int 8)))) + (set (match_dup 0) + (zero_extend:SI (match_dup 3)))] + { + operands[3] = gen_rtx_REG (HImode, REGNO (operands[0])); + }) + +(define_insn "*iorsi3_e2f" + [(set (match_operand:SI 0 "register_operand" "=r") + (ior:SI (and:SI (match_operand:SI 1 "register_operand" "0") + (const_int -65536)) + (lshiftrt:SI (match_operand:SI 2 "register_operand" "r") + (const_int 16))))] + "" + "mov.w\\t%e2,%f0" + [(set_attr "length" "2")]) + +(define_insn_and_split "*iorsi3_two_qi_sext" + [(set (match_operand:SI 0 "register_operand" "=r") + (ior:SI (zero_extend:SI (match_operand:QI 1 "register_operand" "0")) + (ashift:SI (sign_extend:SI (match_operand:QI 2 "register_operand" "r")) + (const_int 8))))] + "" + "#" + "&& reload_completed" + [(set (match_dup 3) + (ior:HI (zero_extend:HI (match_dup 1)) + (ashift:HI (match_dup 4) + (const_int 8)))) + (set (match_dup 0) + (sign_extend:SI (match_dup 3)))] + { + operands[3] = gen_rtx_REG (HImode, REGNO (operands[0])); + operands[4] = gen_rtx_REG (HImode, REGNO (operands[2])); + }) + +(define_insn "*iorsi3_w" + [(set (match_operand:SI 0 "register_operand" "=r,&r") + (ior:SI (and:SI (match_operand:SI 1 "register_operand" "0,0") + (const_int -256)) + (zero_extend:SI (match_operand:QI 2 "general_operand_src" "r,g>"))))] + "" + "mov.b\\t%X2,%w0" + [(set_attr "length" "2,8")]) + +(define_insn "*iorsi3_ashift_31" + [(set (match_operand:SI 0 "register_operand" "=&r") + (ior:SI (ashift:SI (match_operand:SI 1 "register_operand" "r") + (const_int 31)) + (match_operand:SI 2 "register_operand" "0")))] + "" + "rotxl.l\\t%S0\;bor\\t#0,%w1\;rotxr.l\\t%S0" + [(set_attr "length" "6") + (set_attr "cc" "set_znv")]) + +(define_insn "*iorsi3_and_ashift" + [(set (match_operand:SI 0 "register_operand" "=r") + (ior:SI (and:SI (ashift:SI (match_operand:SI 1 "register_operand" "r") + (match_operand:SI 2 "const_int_operand" "n")) + (match_operand:SI 3 "single_one_operand" "n")) + (match_operand:SI 4 "register_operand" "0")))] + "(INTVAL (operands[3]) & ~0xffff) == 0" +{ + rtx srcpos = GEN_INT (exact_log2 (INTVAL (operands[3])) + - INTVAL (operands[2])); + rtx dstpos = GEN_INT (exact_log2 (INTVAL (operands[3]))); + operands[2] = srcpos; + operands[3] = dstpos; + return "bld\\t%Z2,%Y1\;bor\\t%Z3,%Y0\;bst\\t%Z3,%Y0"; +} + [(set_attr "length" "6")]) + +(define_insn "*iorsi3_and_lshiftrt" + [(set (match_operand:SI 0 "register_operand" "=r") + (ior:SI (and:SI (lshiftrt:SI (match_operand:SI 1 "register_operand" "r") + (match_operand:SI 2 "const_int_operand" "n")) + (match_operand:SI 3 "single_one_operand" "n")) + (match_operand:SI 4 "register_operand" "0")))] + "((INTVAL (operands[3]) << INTVAL (operands[2])) & ~0xffff) == 0" +{ + rtx srcpos = GEN_INT (exact_log2 (INTVAL (operands[3])) + + INTVAL (operands[2])); + rtx dstpos = GEN_INT (exact_log2 (INTVAL (operands[3]))); + operands[2] = srcpos; + operands[3] = dstpos; + return "bld\\t%Z2,%Y1\;bor\\t%Z3,%Y0\;bst\\t%Z3,%Y0"; +} + [(set_attr "length" "6")]) + +(define_insn "*iorsi3_zero_extract" + [(set (match_operand:SI 0 "register_operand" "=r") + (ior:SI (zero_extract:SI (match_operand:SI 1 "register_operand" "r") + (const_int 1) + (match_operand:SI 2 "const_int_operand" "n")) + (match_operand:SI 3 "register_operand" "0")))] + "INTVAL (operands[2]) < 16" + "bld\\t%Z2,%Y1\;bor\\t#0,%w0\;bst\\t#0,%w0" + [(set_attr "length" "6")]) + +(define_insn "*iorsi3_and_lshiftrt_n_sb" + [(set (match_operand:SI 0 "register_operand" "=r") + (ior:SI (and:SI (lshiftrt:SI (match_operand:SI 1 "register_operand" "r") + (const_int 30)) + (const_int 2)) + (match_operand:SI 2 "register_operand" "0")))] + "" + "rotl.l\\t%S1\;rotr.l\\t%S1\;bor\\t#1,%w0\;bst\\t#1,%w0" + [(set_attr "length" "8")]) + +(define_insn "*iorsi3_and_lshiftrt_9_sb" + [(set (match_operand:SI 0 "register_operand" "=r") + (ior:SI (and:SI (lshiftrt:SI (match_operand:SI 1 "register_operand" "r") + (const_int 9)) + (const_int 4194304)) + (match_operand:SI 2 "register_operand" "0"))) + (clobber (match_scratch:HI 3 "=&r"))] + "" +{ + if (find_regno_note (insn, REG_DEAD, REGNO (operands[1]))) + return "shll.l\\t%S1\;xor.w\\t%T3,%T3\;bst\\t#6,%s3\;or.w\\t%T3,%e0"; + else + return "rotl.l\\t%S1\;rotr.l\\t%S1\;xor.w\\t%T3,%T3\;bst\\t#6,%s3\;or.w\\t%T3,%e0"; +} + [(set_attr "length" "10")]) + +;; Used to OR the exponent of a float. + +(define_insn "*iorsi3_shift" + [(set (match_operand:SI 0 "register_operand" "=r") + (ior:SI (ashift:SI (match_operand:SI 1 "register_operand" "r") + (const_int 23)) + (match_operand:SI 2 "register_operand" "0"))) + (clobber (match_scratch:SI 3 "=&r"))] + "" + "#") + +(define_split + [(set (match_operand:SI 0 "register_operand" "") + (ior:SI (ashift:SI (match_operand:SI 1 "register_operand" "") + (const_int 23)) + (match_dup 0))) + (clobber (match_operand:SI 2 "register_operand" ""))] + "epilogue_completed + && find_regno_note (insn, REG_DEAD, REGNO (operands[1])) + && REGNO (operands[0]) != REGNO (operands[1])" + [(parallel [(set (match_dup 3) + (ashift:HI (match_dup 3) + (const_int 7))) + (clobber (scratch:QI))]) + (set (match_dup 0) + (ior:SI (ashift:SI (match_dup 1) + (const_int 16)) + (match_dup 0)))] + { + operands[3] = gen_rtx_REG (HImode, REGNO (operands[1])); + }) + +(define_split + [(set (match_operand:SI 0 "register_operand" "") + (ior:SI (ashift:SI (match_operand:SI 1 "register_operand" "") + (const_int 23)) + (match_dup 0))) + (clobber (match_operand:SI 2 "register_operand" ""))] + "epilogue_completed + && !(find_regno_note (insn, REG_DEAD, REGNO (operands[1])) + && REGNO (operands[0]) != REGNO (operands[1]))" + [(set (match_dup 2) + (match_dup 1)) + (parallel [(set (match_dup 3) + (ashift:HI (match_dup 3) + (const_int 7))) + (clobber (scratch:QI))]) + (set (match_dup 0) + (ior:SI (ashift:SI (match_dup 2) + (const_int 16)) + (match_dup 0)))] + { + operands[3] = gen_rtx_REG (HImode, REGNO (operands[2])); + }) + +(define_insn "*iorsi2_and_1_lshiftrt_1" + [(set (match_operand:SI 0 "register_operand" "=r") + (ior:SI (and:SI (match_operand:SI 1 "register_operand" "0") + (const_int 1)) + (lshiftrt:SI (match_dup 1) + (const_int 1))))] + "" + "shlr.l\\t%S0\;bor\\t#0,%w0\;bst\\t#0,%w0" + [(set_attr "length" "6")]) + +(define_insn_and_split "*iorsi3_ashift_16_ashift_24" + [(set (match_operand:SI 0 "register_operand" "=r") + (ior:SI (ashift:SI (match_operand:SI 1 "register_operand" "0") + (const_int 16)) + (ashift:SI (match_operand:SI 2 "register_operand" "r") + (const_int 24))))] + "" + "#" + "&& reload_completed" + [(set (match_dup 3) + (ior:HI (ashift:HI (match_dup 4) + (const_int 8)) + (match_dup 3))) + (parallel [(set (match_dup 0) + (ashift:SI (match_dup 0) + (const_int 16))) + (clobber (scratch:QI))])] + { + operands[3] = gen_rtx_REG (HImode, REGNO (operands[0])); + operands[4] = gen_rtx_REG (HImode, REGNO (operands[2])); + }) + +(define_insn_and_split "*iorsi3_ashift_16_ashift_24_mem" + [(set (match_operand:SI 0 "register_operand" "=&r") + (ior:SI (and:SI (ashift:SI (subreg:SI (match_operand:QI 1 "memory_operand" "m") 0) + (const_int 16)) + (const_int 16711680)) + (ashift:SI (subreg:SI (match_operand:QI 2 "memory_operand" "m") 0) + (const_int 24))))] + "" + "#" + "&& reload_completed" + [(set (match_dup 3) + (ior:HI (zero_extend:HI (match_dup 1)) + (ashift:HI (subreg:HI (match_dup 2) 0) + (const_int 8)))) + (parallel [(set (match_dup 0) + (ashift:SI (match_dup 0) + (const_int 16))) + (clobber (scratch:QI))])] + { + operands[3] = gen_rtx_REG (HImode, REGNO (operands[0])); + }) + +;; Used to add the exponent of a float. + +(define_insn "*addsi3_shift" + [(set (match_operand:SI 0 "register_operand" "=r") + (plus:SI (mult:SI (match_operand:SI 1 "register_operand" "r") + (const_int 8388608)) + (match_operand:SI 2 "register_operand" "0"))) + (clobber (match_scratch:SI 3 "=&r"))] + "" + "#") + +(define_split + [(set (match_operand:SI 0 "register_operand" "") + (plus:SI (mult:SI (match_operand:SI 1 "register_operand" "") + (const_int 8388608)) + (match_dup 0))) + (clobber (match_operand:SI 2 "register_operand" ""))] + "epilogue_completed + && find_regno_note (insn, REG_DEAD, REGNO (operands[1])) + && REGNO (operands[0]) != REGNO (operands[1])" + [(parallel [(set (match_dup 3) + (ashift:HI (match_dup 3) + (const_int 7))) + (clobber (scratch:QI))]) + (set (match_dup 0) + (plus:SI (mult:SI (match_dup 1) + (const_int 65536)) + (match_dup 0)))] + { + operands[3] = gen_rtx_REG (HImode, REGNO (operands[1])); + }) + +(define_split + [(set (match_operand:SI 0 "register_operand" "") + (plus:SI (mult:SI (match_operand:SI 1 "register_operand" "") + (const_int 8388608)) + (match_dup 0))) + (clobber (match_operand:SI 2 "register_operand" ""))] + "epilogue_completed + && !(find_regno_note (insn, REG_DEAD, REGNO (operands[1])) + && REGNO (operands[0]) != REGNO (operands[1]))" + [(set (match_dup 2) + (match_dup 1)) + (parallel [(set (match_dup 3) + (ashift:HI (match_dup 3) + (const_int 7))) + (clobber (scratch:QI))]) + (set (match_dup 0) + (plus:SI (mult:SI (match_dup 2) + (const_int 65536)) + (match_dup 0)))] + { + operands[3] = gen_rtx_REG (HImode, REGNO (operands[2])); + }) + +;; ashift:SI + +(define_insn_and_split "*ashiftsi_sextqi_7" + [(set (match_operand:SI 0 "register_operand" "=r") + (ashift:SI (sign_extend:SI (match_operand:QI 1 "register_operand" "0")) + (const_int 7)))] + "" + "#" + "&& reload_completed" + [(parallel [(set (match_dup 2) + (ashift:HI (match_dup 2) + (const_int 8))) + (clobber (scratch:QI))]) + (set (match_dup 0) + (sign_extend:SI (match_dup 2))) + (parallel [(set (match_dup 0) + (ashiftrt:SI (match_dup 0) + (const_int 1))) + (clobber (scratch:QI))])] + { + operands[2] = gen_rtx_REG (HImode, REGNO (operands[0])); + }) + +;; Storing a part of HImode to QImode. + +(define_insn "" + [(set (match_operand:QI 0 "general_operand_dst" "=rm<") + (subreg:QI (lshiftrt:HI (match_operand:HI 1 "register_operand" "r") + (const_int 8)) 1))] + "" + "mov.b\\t%t1,%R0" + [(set_attr "cc" "set_znv") + (set_attr "length" "8")]) + +;; Storing a part of SImode to QImode. + +(define_insn "" + [(set (match_operand:QI 0 "general_operand_dst" "=rm<") + (subreg:QI (lshiftrt:SI (match_operand:SI 1 "register_operand" "r") + (const_int 8)) 3))] + "" + "mov.b\\t%x1,%R0" + [(set_attr "cc" "set_znv") + (set_attr "length" "8")]) + +(define_insn "" + [(set (match_operand:QI 0 "general_operand_dst" "=rm<") + (subreg:QI (lshiftrt:SI (match_operand:SI 1 "register_operand" "r") + (const_int 16)) 3)) + (clobber (match_scratch:SI 2 "=&r"))] + "" + "mov.w\\t%e1,%f2\;mov.b\\t%w2,%R0" + [(set_attr "cc" "set_znv") + (set_attr "length" "10")]) + +(define_insn "" + [(set (match_operand:QI 0 "general_operand_dst" "=rm<") + (subreg:QI (lshiftrt:SI (match_operand:SI 1 "register_operand" "r") + (const_int 24)) 3)) + (clobber (match_scratch:SI 2 "=&r"))] + "" + "mov.w\\t%e1,%f2\;mov.b\\t%x2,%R0" + [(set_attr "cc" "set_znv") + (set_attr "length" "10")]) + +(define_insn_and_split "" + [(set (pc) + (if_then_else (eq (zero_extract:SI (subreg:SI (match_operand:QI 0 "register_operand" "") 0) + (const_int 1) + (const_int 7)) + (const_int 0)) + (label_ref (match_operand 1 "" "")) + (pc)))] + "" + "#" + "" + [(set (cc0) (compare (match_dup 0) + (const_int 0))) + (set (pc) + (if_then_else (ge (cc0) + (const_int 0)) + (label_ref (match_dup 1)) + (pc)))] + "") + +(define_insn_and_split "" + [(set (pc) + (if_then_else (ne (zero_extract:SI (subreg:SI (match_operand:QI 0 "register_operand" "") 0) + (const_int 1) + (const_int 7)) + (const_int 0)) + (label_ref (match_operand 1 "" "")) + (pc)))] + "" + "#" + "" + [(set (cc0) (compare (match_dup 0) + (const_int 0))) + (set (pc) + (if_then_else (lt (cc0) + (const_int 0)) + (label_ref (match_dup 1)) + (pc)))] + "") diff --git a/gcc/config/h8300/divmod.md b/gcc/config/h8300/divmod.md new file mode 100644 index 00000000000..7e0d7f09dc9 --- /dev/null +++ b/gcc/config/h8300/divmod.md @@ -0,0 +1,99 @@ +;; ---------------------------------------------------------------------- +;; DIVIDE/MOD INSTRUCTIONS +;; ---------------------------------------------------------------------- + +(define_insn "udiv3" + [(set (match_operand:HSI 0 "register_operand" "=r") + (udiv:HSI (match_operand:HSI 1 "register_operand" "0") + (match_operand:HSI 2 "reg_or_nibble_operand" "r IP4>X")))] + "TARGET_H8300SX" + { return mode == HImode ? "divu.w\\t%T2,%T0" : "divu.l\\t%S2,%S0"; } + [(set_attr "length" "4")]) + +(define_insn "div3" + [(set (match_operand:HSI 0 "register_operand" "=r") + (div:HSI (match_operand:HSI 1 "register_operand" "0") + (match_operand:HSI 2 "reg_or_nibble_operand" "r IP4>X")))] + "TARGET_H8300SX" + { return mode == HImode ? "divs.w\\t%T2,%T0" : "divs.l\\t%S2,%S0"; } + [(set_attr "length" "4")]) + +(define_insn "udivmodqi4" + [(set (match_operand:QI 0 "register_operand" "=r") + (truncate:QI + (udiv:HI + (match_operand:HI 1 "register_operand" "0") + (zero_extend:HI (match_operand:QI 2 "register_operand" "r"))))) + (set (match_operand:QI 3 "register_operand" "=r") + (truncate:QI + (umod:HI + (match_dup 1) + (zero_extend:HI (match_dup 2)))))] + "" +{ + if (find_reg_note (insn, REG_UNUSED, operands[3])) + return "divxu.b\\t%X2,%T0"; + else + return "divxu.b\\t%X2,%T0\;mov.b\\t%t0,%s3"; +} + [(set_attr "length" "4")]) + +(define_insn "divmodqi4" + [(set (match_operand:QI 0 "register_operand" "=r") + (truncate:QI + (div:HI + (match_operand:HI 1 "register_operand" "0") + (sign_extend:HI (match_operand:QI 2 "register_operand" "r"))))) + (set (match_operand:QI 3 "register_operand" "=r") + (truncate:QI + (mod:HI + (match_dup 1) + (sign_extend:HI (match_dup 2)))))] + "" +{ + if (find_reg_note (insn, REG_UNUSED, operands[3])) + return "divxs.b\\t%X2,%T0"; + else + return "divxs.b\\t%X2,%T0\;mov.b\\t%t0,%s3"; +} + [(set_attr "length" "6")]) + +(define_insn "udivmodhi4" + [(set (match_operand:HI 0 "register_operand" "=r") + (truncate:HI + (udiv:SI + (match_operand:SI 1 "register_operand" "0") + (zero_extend:SI (match_operand:HI 2 "register_operand" "r"))))) + (set (match_operand:HI 3 "register_operand" "=r") + (truncate:HI + (umod:SI + (match_dup 1) + (zero_extend:SI (match_dup 2)))))] + "" +{ + if (find_reg_note (insn, REG_UNUSED, operands[3])) + return "divxu.w\\t%T2,%S0"; + else + return "divxu.w\\t%T2,%S0\;mov.w\\t%e0,%f3"; +} + [(set_attr "length" "4")]) + +(define_insn "divmodhi4" + [(set (match_operand:HI 0 "register_operand" "=r") + (truncate:HI + (div:SI + (match_operand:SI 1 "register_operand" "0") + (sign_extend:SI (match_operand:HI 2 "register_operand" "r"))))) + (set (match_operand:HI 3 "register_operand" "=r") + (truncate:HI + (mod:SI + (match_dup 1) + (sign_extend:SI (match_dup 2)))))] + "" +{ + if (find_reg_note (insn, REG_UNUSED, operands[3])) + return "divxs.w\\t%T2,%S0"; + else + return "divxs.w\\t%T2,%S0\;mov.w\\t%e0,%f3"; +} + [(set_attr "length" "6")]) diff --git a/gcc/config/h8300/extensions.md b/gcc/config/h8300/extensions.md new file mode 100644 index 00000000000..cf6fb6d1eb9 --- /dev/null +++ b/gcc/config/h8300/extensions.md @@ -0,0 +1,152 @@ +;; ---------------------------------------------------------------------- +;; EXTEND INSTRUCTIONS +;; ---------------------------------------------------------------------- + +(define_expand "zero_extendqi2" + [(set (match_operand:HSI 0 "register_operand" "") + (zero_extend:HSI (match_operand:QI 1 "general_operand_src" "")))] + "" + { + if (TARGET_H8300SX) + operands[1] = force_reg (QImode, operands[1]); + }) + +(define_insn "*zero_extendqihi2_h8300hs" + [(set (match_operand:HI 0 "register_operand" "=r,r") + (zero_extend:HI (match_operand:QI 1 "general_operand_src" "0,g>")))] + "" + "@ + extu.w %T0 + #" + [(set_attr "length" "2,10") + (set_attr "cc" "set_znv,set_znv")]) + +;; Split the zero extension of a general operand (actually a memory +;; operand) into a load of the operand and the actual zero extension +;; so that 1) the length will be accurate, and 2) the zero extensions +;; appearing at the end of basic blocks may be merged. + +(define_split + [(set (match_operand:HI 0 "register_operand" "") + (zero_extend:HI (match_operand:QI 1 "general_operand_src" "")))] + "reload_completed" + [(set (match_dup 2) + (match_dup 1)) + (set (match_dup 0) + (zero_extend:HI (match_dup 2)))] + { + operands[2] = gen_rtx_REG (QImode, REGNO (operands[0])); + }) + +(define_insn "*zero_extendqisi2_h8300hs" + [(set (match_operand:SI 0 "register_operand" "=r,r") + (zero_extend:SI (match_operand:QI 1 "general_operand_src" "0,g>")))] + "!TARGET_H8300SX" + "#") + +(define_split + [(set (match_operand:SI 0 "register_operand" "") + (zero_extend:SI (match_operand:QI 1 "general_operand_src" "")))] + "!TARGET_H8300SX + && reg_overlap_mentioned_p (operands[0], operands[1]) + && reload_completed" + [(set (match_dup 2) + (match_dup 1)) + (set (match_dup 3) + (zero_extend:HI (match_dup 2))) + (set (match_dup 0) + (zero_extend:SI (match_dup 3)))] + { + operands[2] = gen_lowpart (QImode, operands[0]); + operands[3] = gen_lowpart (HImode, operands[0]); + }) + +(define_split + [(set (match_operand:SI 0 "register_operand" "") + (zero_extend:SI (match_operand:QI 1 "general_operand_src" "")))] + "!TARGET_H8300SX + && !reg_overlap_mentioned_p (operands[0], operands[1]) + && reload_completed" + [(set (match_dup 0) + (const_int 0)) + (set (strict_low_part (match_dup 2)) + (match_dup 1))] + { + operands[2] = gen_rtx_REG (QImode, REGNO (operands[0])); + }) + +(define_insn "*zero_extendqisi2_h8sx" + [(set (match_operand:SI 0 "register_operand" "=r") + (zero_extend:SI (match_operand:QI 1 "register_operand" "0")))] + "TARGET_H8300SX" + "extu.l\t#2,%0" + [(set_attr "length" "2") + (set_attr "cc" "set_znv")]) + +(define_expand "zero_extendhisi2" + [(set (match_operand:SI 0 "register_operand" "") + (zero_extend:SI (match_operand:HI 1 "register_operand" "")))] + "" + "") + +(define_insn "*zero_extendhisi2_h8300hs" + [(set (match_operand:SI 0 "register_operand" "=r") + (zero_extend:SI (match_operand:HI 1 "register_operand" "0")))] + "" + "extu.l %S0" + [(set_attr "length" "2") + (set_attr "cc" "set_znv")]) + +(define_expand "extendqi2" + [(set (match_operand:HSI 0 "register_operand" "") + (sign_extend:HSI (match_operand:QI 1 "register_operand" "")))] + "" + "") + +(define_insn "*extendqihi2_h8300hs" + [(set (match_operand:HI 0 "register_operand" "=r") + (sign_extend:HI (match_operand:QI 1 "register_operand" "0")))] + "" + "exts.w %T0" + [(set_attr "length" "2") + (set_attr "cc" "set_znv")]) + +;; The following pattern is needed because without the pattern, the +;; combiner would split (sign_extend:SI (reg:QI)) into two 24-bit +;; shifts, one ashift and one ashiftrt. + +(define_insn_and_split "*extendqisi2_h8300hs" + [(set (match_operand:SI 0 "register_operand" "=r") + (sign_extend:SI (match_operand:QI 1 "register_operand" "0")))] + "!TARGET_H8300SX" + "#" + "&& reload_completed" + [(set (match_dup 2) + (sign_extend:HI (match_dup 1))) + (set (match_dup 0) + (sign_extend:SI (match_dup 2)))] + { + operands[2] = gen_rtx_REG (HImode, REGNO (operands[0])); + }) + +(define_insn "*extendqisi2_h8sx" + [(set (match_operand:SI 0 "register_operand" "=r") + (sign_extend:SI (match_operand:QI 1 "register_operand" "0")))] + "TARGET_H8300SX" + "exts.l\t#2,%0" + [(set_attr "length" "2") + (set_attr "cc" "set_znv")]) + +(define_expand "extendhisi2" + [(set (match_operand:SI 0 "register_operand" "") + (sign_extend:SI (match_operand:HI 1 "register_operand" "")))] + "" + "") + +(define_insn "*extendhisi2_h8300hs" + [(set (match_operand:SI 0 "register_operand" "=r") + (sign_extend:SI (match_operand:HI 1 "register_operand" "0")))] + "" + "exts.l %S0" + [(set_attr "length" "2") + (set_attr "cc" "set_znv")]) diff --git a/gcc/config/h8300/h8300.md b/gcc/config/h8300/h8300.md index 4fc55b675e2..e9b598d375a 100644 --- a/gcc/config/h8300/h8300.md +++ b/gcc/config/h8300/h8300.md @@ -195,3149 +195,18 @@ (define_code_iterator ors [ior xor]) -;; ---------------------------------------------------------------------- -;; MOVE INSTRUCTIONS -;; ---------------------------------------------------------------------- - -;; movqi - -(define_insn "*movqi_h8nosx" - [(set (match_operand:QI 0 "general_operand_dst" "=r,r ,<,r,r,m") - (match_operand:QI 1 "general_operand_src" " I,r>,r,n,m,r"))] - "!TARGET_H8300SX - && h8300_move_ok (operands[0], operands[1])" - "@ - sub.b %X0,%X0 - mov.b %R1,%X0 - mov.b %X1,%R0 - mov.b %R1,%X0 - mov.b %R1,%X0 - mov.b %X1,%R0" - [(set (attr "length") - (symbol_ref "compute_mov_length (operands)")) - (set_attr "cc" "set_zn,set_znv,set_znv,set_znv,set_znv,set_znv")]) - -(define_insn "*movqi_h8sx" - [(set (match_operand:QI 0 "general_operand_dst" "=Z,rQ") - (match_operand:QI 1 "general_operand_src" "P4>X,rQi"))] - "TARGET_H8300SX" - "@ - mov.b %X1:4,%X0 - mov.b %X1,%X0" - [(set_attr "length_table" "mov_imm4,movb") - (set_attr "cc" "set_znv")]) - -(define_expand "mov" - [(set (match_operand:QHSIF 0 "general_operand_dst" "") - (match_operand:QHSIF 1 "general_operand_src" ""))] - "" - { - enum machine_mode mode = mode; - if (!TARGET_H8300SX) - { - /* Other H8 chips, except the H8/SX family can only handle a - single memory operand, which is checked by h8300_move_ok. - - We could perhaps have h8300_move_ok handle the H8/SX better - and just remove the !TARGET_H8300SX conditional. */ - if (!h8300_move_ok (operands[0], operands[1])) - operands[1] = copy_to_mode_reg (mode, operand1); - } - }) - -(define_insn "movstrictqi" - [(set (strict_low_part (match_operand:QI 0 "general_operand_dst" "+r,r")) - (match_operand:QI 1 "general_operand_src" "I,rmi>"))] - "" - "@ - sub.b %X0,%X0 - mov.b %X1,%X0" - [(set_attr "length" "2,*") - (set_attr "length_table" "*,movb") - (set_attr "cc" "set_zn,set_znv")]) - -;; movhi - -(define_insn "*movhi_h8nosx" - [(set (match_operand:HI 0 "general_operand_dst" "=r,r,<,r,r,m") - (match_operand:HI 1 "general_operand_src" "I,r>,r,i,m,r"))] - "!TARGET_H8300SX - && h8300_move_ok (operands[0], operands[1])" - "@ - sub.w %T0,%T0 - mov.w %T1,%T0 - mov.w %T1,%T0 - mov.w %T1,%T0 - mov.w %T1,%T0 - mov.w %T1,%T0" - [(set (attr "length") - (symbol_ref "compute_mov_length (operands)")) - (set_attr "cc" "set_zn,set_znv,set_znv,set_znv,set_znv,set_znv")]) - -(define_insn "*movhi_h8sx" - [(set (match_operand:HI 0 "general_operand_dst" "=r,r,Z,Q,rQ") - (match_operand:HI 1 "general_operand_src" "I,P3>X,P4>X,IP8>X,rQi"))] - "TARGET_H8300SX" - "@ - sub.w %T0,%T0 - mov.w %T1:3,%T0 - mov.w %T1:4,%T0 - mov.w %T1,%T0 - mov.w %T1,%T0" - [(set_attr "length_table" "*,*,mov_imm4,short_immediate,movw") - (set_attr "length" "2,2,*,*,*") - (set_attr "cc" "set_zn,set_znv,set_znv,set_znv,set_znv")]) - -(define_insn "movstricthi" - [(set (strict_low_part (match_operand:HI 0 "general_operand_dst" "+r,r,r")) - (match_operand:HI 1 "general_operand_src" "I,P3>X,rmi"))] - "" - "@ - sub.w %T0,%T0 - mov.w %T1,%T0 - mov.w %T1,%T0" - [(set_attr "length" "2,2,*") - (set_attr "length_table" "*,*,movw") - (set_attr "cc" "set_zn,set_znv,set_znv")]) - -;; movsi -(define_insn "*movsi_h8300hs" - [(set (match_operand:SI 0 "general_operand_dst" "=r,r,r,<,r,r,m,*a,*a,r") - (match_operand:SI 1 "general_operand_src" "I,r,i,r,>,m,r,I,r,*a"))] - "(TARGET_H8300S || TARGET_H8300H) && !TARGET_H8300SX - && h8300_move_ok (operands[0], operands[1])" -{ - switch (which_alternative) - { - case 0: - return "sub.l %S0,%S0"; - case 7: - return "clrmac"; - case 8: - return "clrmac\;ldmac %1,macl"; - case 9: - return "stmac macl,%0"; - default: - if (GET_CODE (operands[1]) == CONST_INT) - { - int val = INTVAL (operands[1]); - - /* Look for constants which can be made by adding an 8-bit - number to zero in one of the two low bytes. */ - if (val == (val & 0xff)) - { - operands[1] = GEN_INT ((char) val & 0xff); - return "sub.l\\t%S0,%S0\;add.b\\t%1,%w0"; - } - - if (val == (val & 0xff00)) - { - operands[1] = GEN_INT ((char) (val >> 8) & 0xff); - return "sub.l\\t%S0,%S0\;add.b\\t%1,%x0"; - } - - /* Look for constants that can be obtained by subs, inc, and - dec to 0. */ - switch (val & 0xffffffff) - { - case 0xffffffff: - return "sub.l\\t%S0,%S0\;subs\\t#1,%S0"; - case 0xfffffffe: - return "sub.l\\t%S0,%S0\;subs\\t#2,%S0"; - case 0xfffffffc: - return "sub.l\\t%S0,%S0\;subs\\t#4,%S0"; - - case 0x0000ffff: - return "sub.l\\t%S0,%S0\;dec.w\\t#1,%f0"; - case 0x0000fffe: - return "sub.l\\t%S0,%S0\;dec.w\\t#2,%f0"; - - case 0xffff0000: - return "sub.l\\t%S0,%S0\;dec.w\\t#1,%e0"; - case 0xfffe0000: - return "sub.l\\t%S0,%S0\;dec.w\\t#2,%e0"; - - case 0x00010000: - return "sub.l\\t%S0,%S0\;inc.w\\t#1,%e0"; - case 0x00020000: - return "sub.l\\t%S0,%S0\;inc.w\\t#2,%e0"; - } - } - } - return "mov.l %S1,%S0"; -} - [(set (attr "length") - (symbol_ref "compute_mov_length (operands)")) - (set_attr "cc" "set_zn,set_znv,clobber,set_znv,set_znv,set_znv,set_znv,none_0hit,none_0hit,set_znv")]) - -(define_insn "*movsi_h8sx" - [(set (match_operand:SI 0 "general_operand_dst" "=r,r,Q,rQ,*a,*a,r") - (match_operand:SI 1 "general_operand_src" "I,P3>X,IP8>X,rQi,I,r,*a"))] - "TARGET_H8300SX" - "@ - sub.l %S0,%S0 - mov.l %S1:3,%S0 - mov.l %S1,%S0 - mov.l %S1,%S0 - clrmac - clrmac\;ldmac %1,macl - stmac macl,%0" - [(set_attr "length_table" "*,*,short_immediate,movl,*,*,*") - (set_attr "length" "2,2,*,*,2,6,4") - (set_attr "cc" "set_zn,set_znv,set_znv,set_znv,none_0hit,none_0hit,set_znv")]) - -(define_insn "*movsf_h8sx" - [(set (match_operand:SF 0 "general_operand_dst" "=r,rQ") - (match_operand:SF 1 "general_operand_src" "G,rQi"))] - "TARGET_H8300SX" - "@ - sub.l %S0,%S0 - mov.l %S1,%S0" - [(set_attr "length" "2,*") - (set_attr "length_table" "*,movl") - (set_attr "cc" "set_zn,set_znv")]) - +(include "movepush.md") (include "mova.md") - -(define_insn "*movsf_h8300hs" - [(set (match_operand:SF 0 "general_operand_dst" "=r,r,r,m,<,r") - (match_operand:SF 1 "general_operand_src" "G,r,im,r,r,>"))] - "!TARGET_H8300SX - && (register_operand (operands[0], SFmode) - || register_operand (operands[1], SFmode))" - "@ - sub.l %S0,%S0 - mov.l %S1,%S0 - mov.l %S1,%S0 - mov.l %S1,%S0 - mov.l %S1,%S0 - mov.l %S1,%S0" - [(set (attr "length") - (symbol_ref "compute_mov_length (operands)")) - (set_attr "cc" "set_zn,set_znv,set_znv,set_znv,set_znv,set_znv")]) - -;; ---------------------------------------------------------------------- -;; PUSH INSTRUCTIONS -;; ---------------------------------------------------------------------- - -(define_insn "*push1_h8300hs_" - [(set (mem:QHI - (pre_modify:P - (reg:P SP_REG) - (plus:P (reg:P SP_REG) (const_int -4)))) - (match_operand:QHI 0 "register_no_sp_elim_operand" "r"))] - "" - "mov.l\\t%S0,@-er7" - [(set_attr "length" "4")]) - - -;; ---------------------------------------------------------------------- -;; TEST INSTRUCTIONS -;; ---------------------------------------------------------------------- - -(define_insn_and_split "*tst_extzv_1_n" - [(set (cc0) - (compare (zero_extract:SI (match_operand:QI 0 "general_operand_src" "r,U,mn>") - (const_int 1) - (match_operand 1 "const_int_operand" "n,n,n")) - (const_int 0))) - (clobber (match_scratch:QI 2 "=X,X,&r"))] - "" - "@ - btst\\t%Z1,%Y0 - btst\\t%Z1,%Y0 - #" - "&& reload_completed - && !satisfies_constraint_U (operands[0])" - [(set (match_dup 2) - (match_dup 0)) - (parallel [(set (cc0) (compare (zero_extract:SI (match_dup 2) - (const_int 1) - (match_dup 1)) - (const_int 0))) - (clobber (scratch:QI))])] - "" - [(set_attr "length" "2,8,10") - (set_attr "cc" "set_zn,set_zn,set_zn")]) - -(define_insn "" - [(set (cc0) - (compare (zero_extract:HSI (match_operand:HSI 0 "register_operand" "r") - (const_int 1) - (match_operand 1 "const_int_operand" "n")) - (const_int 0)))] - "INTVAL (operands[1]) <= 15" - "btst %Z1,%Y0" - [(set_attr "length" "2") - (set_attr "cc" "set_zn")]) - -(define_insn_and_split "*tstsi_upper_bit" - [(set (cc0) - (compare (zero_extract:SI (match_operand:SI 0 "register_operand" "r") - (const_int 1) - (match_operand 1 "const_int_operand" "n")) - (const_int 0))) - (clobber (match_scratch:SI 2 "=&r"))] - "INTVAL (operands[1]) >= 16" - "#" - "&& reload_completed" - [(set (match_dup 2) - (ior:SI (and:SI (match_dup 2) - (const_int -65536)) - (lshiftrt:SI (match_dup 0) - (const_int 16)))) - (set (cc0) - (compare (zero_extract:SI (match_dup 2) - (const_int 1) - (match_dup 3)) - (const_int 0)))] - { - operands[3] = GEN_INT (INTVAL (operands[1]) - 16); - }) - -(define_insn "*tstsi_variable_bit" - [(set (cc0) - (compare (zero_extract:SI (match_operand:SI 0 "register_operand" "r") - (const_int 1) - (and:SI (match_operand:SI 1 "register_operand" "r") - (const_int 7))) - (const_int 0)))] - "" - "btst %w1,%w0" - [(set_attr "length" "2") - (set_attr "cc" "set_zn")]) - -(define_insn_and_split "*tstsi_variable_bit_qi" - [(set (cc0) - (compare (zero_extract:SI (zero_extend:SI (match_operand:QI 0 "general_operand_src" "r,U,mn>")) - (const_int 1) - (and:SI (match_operand:SI 1 "register_operand" "r,r,r") - (const_int 7))) - (const_int 0))) - (clobber (match_scratch:QI 2 "=X,X,&r"))] - "" - "@ - btst\\t%w1,%X0 - btst\\t%w1,%X0 - #" - "&& reload_completed - && !satisfies_constraint_U (operands[0])" - [(set (match_dup 2) - (match_dup 0)) - (parallel [(set (cc0) - (compare (zero_extract:SI (zero_extend:SI (match_dup 2)) - (const_int 1) - (and:SI (match_dup 1) - (const_int 7))) - (const_int 0))) - (clobber (scratch:QI))])] - "" - [(set_attr "length" "2,8,10") - (set_attr "cc" "set_zn,set_zn,set_zn")]) - -(define_insn "*tst" - [(set (cc0) - (compare (match_operand:QHI 0 "register_operand" "r") - (const_int 0)))] - "" - { - if (mode == QImode) - return "mov.b %X0,%X0"; - else if (mode == HImode) - return "mov.w %T0,%T0"; - gcc_unreachable (); - } - [(set_attr "length" "2") - (set_attr "cc" "set_znv")]) - -(define_insn "*tsthi_upper" - [(set (cc0) - (compare (and:HI (match_operand:HI 0 "register_operand" "r") - (const_int -256)) - (const_int 0)))] - "" - "mov.b %t0,%t0" - [(set_attr "length" "2") - (set_attr "cc" "set_znv")]) - -(define_insn "*tstsi" - [(set (cc0) - (compare (match_operand:SI 0 "register_operand" "r") - (const_int 0)))] - "" - "mov.l %S0,%S0" - [(set_attr "length" "2") - (set_attr "cc" "set_znv")]) - -(define_insn "*tstsi_upper" - [(set (cc0) - (compare (and:SI (match_operand:SI 0 "register_operand" "r") - (const_int -65536)) - (const_int 0)))] - "" - "mov.w %e0,%e0" - [(set_attr "length" "2") - (set_attr "cc" "set_znv")]) - -(define_insn "*cmpqi" - [(set (cc0) - (compare (match_operand:QI 0 "h8300_dst_operand" "rQ") - (match_operand:QI 1 "h8300_src_operand" "rQi")))] - "" - "cmp.b %X1,%X0" - [(set_attr "length_table" "add") - (set_attr "cc" "compare")]) - -(define_insn "*cmphi_h8300hs_znvc" - [(set (cc0) - (compare (match_operand:HI 0 "h8300_dst_operand" "rU,rQ") - (match_operand:HI 1 "h8300_src_operand" "P3>X,rQi")))] - "" -{ - switch (which_alternative) - { - case 0: - if (!TARGET_H8300SX) - return "cmp.w %T1,%T0"; - else - return "cmp.w %T1:3,%T0"; - case 1: - return "cmp.w %T1,%T0"; - default: - gcc_unreachable (); - } -} - [(set_attr "length_table" "short_immediate,add") - (set_attr "cc" "compare,compare")]) - -(define_insn "cmpsi" - [(set (cc0) - (compare (match_operand:SI 0 "h8300_dst_operand" "r,rQ") - (match_operand:SI 1 "h8300_src_operand" "P3>X,rQi")))] - "" -{ - switch (which_alternative) - { - case 0: - if (!TARGET_H8300SX) - return "cmp.l %S1,%S0"; - else - return "cmp.l %S1:3,%S0"; - case 1: - return "cmp.l %S1,%S0"; - default: - gcc_unreachable (); - } -} - [(set_attr "length" "2,*") - (set_attr "length_table" "*,add") - (set_attr "cc" "compare,compare")]) - -;; ---------------------------------------------------------------------- -;; ADD INSTRUCTIONS -;; ---------------------------------------------------------------------- - -(define_expand "add3" - [(set (match_operand:QHSI 0 "register_operand" "") - (plus:QHSI (match_operand:QHSI 1 "register_operand" "") - (match_operand:QHSI 2 "h8300_src_operand" "")))] - "" - "") - -(define_insn "*addqi3" - [(set (match_operand:QI 0 "h8300_dst_operand" "=rQ") - (plus:QI (match_operand:QI 1 "h8300_dst_operand" "%0") - (match_operand:QI 2 "h8300_src_operand" "rQi")))] - "h8300_operands_match_p (operands)" - "add.b %X2,%X0" - [(set_attr "length_table" "add") - (set_attr "cc" "set_zn")]) - -(define_insn "*addhi3_h8300hs" - [(set (match_operand:HI 0 "register_operand" "=r,r,r,r,r") - (plus:HI (match_operand:HI 1 "register_operand" "%0,0,0,0,0") - (match_operand:HI 2 "h8300_src_operand" "L,N,J,n,r")))] - "!TARGET_H8300SX" - "@ - adds %2,%S0 - subs %G2,%S0 - add.b %t2,%t0 - add.w %T2,%T0 - add.w %T2,%T0" - [(set_attr "length" "2,2,2,4,2") - (set_attr "cc" "none_0hit,none_0hit,clobber,set_zn,set_zn")]) - -(define_insn "*add3_incdec" - [(set (match_operand:HSI 0 "register_operand" "=r,r") - (unspec:HSI [(match_operand:HSI 1 "register_operand" "0,0") - (match_operand:HSI 2 "incdec_operand" "M,O")] - UNSPEC_INCDEC))] - "" - { - if (which_alternative == 0) - return mode == HImode ? "inc.w\t%2,%T0" : "inc.l\t%2,%S0"; - else if (which_alternative == 1) - return mode == HImode ? "dec.w\t%G2,%T0" : "dec.l\t%G2,%S0"; - gcc_unreachable (); - } - [(set_attr "length" "2,2") - (set_attr "cc" "set_zn,set_zn")]) - -(define_insn "*addhi3_h8sx" - [(set (match_operand:HI 0 "h8300_dst_operand" "=rU,rU,r,rQ") - (plus:HI (match_operand:HI 1 "h8300_dst_operand" "%0,0,0,0") - (match_operand:HI 2 "h8300_src_operand" "P3>X,P3mode, operands); - DONE; - }) - - -(define_insn "*addsi_h8300hs" - [(set (match_operand:SI 0 "h8300_dst_operand" "=rQ,rQ") - (plus:SI (match_operand:SI 1 "h8300_dst_operand" "%0,0") - (match_operand:SI 2 "h8300_src_operand" "i,rQ")))] - "h8300_operands_match_p (operands)" -{ - return output_plussi (operands); -} - [(set (attr "length") - (symbol_ref "compute_plussi_length (operands)")) - (set (attr "cc") - (symbol_ref "compute_plussi_cc (operands)"))]) - -;; ---------------------------------------------------------------------- -;; SUBTRACT INSTRUCTIONS -;; ---------------------------------------------------------------------- - -(define_expand "sub3" - [(set (match_operand:QHSI 0 "register_operand" "") - (minus:QHSI (match_operand:QHSI 1 "register_operand" "") - (match_operand:QHSI 2 "h8300_src_operand" "")))] - "" - { - }) - -(define_insn "*subqi3" - [(set (match_operand:QI 0 "h8300_dst_operand" "=rQ") - (minus:QI (match_operand:QI 1 "h8300_dst_operand" "0") - (match_operand:QI 2 "h8300_dst_operand" "rQ")))] - "h8300_operands_match_p (operands)" - "sub.b %X2,%X0" - [(set_attr "length_table" "add") - (set_attr "cc" "set_zn")]) - -(define_insn "*sub3_h8300hs" - [(set (match_operand:HSI 0 "h8300_dst_operand" "=rQ,rQ") - (minus:HSI (match_operand:HSI 1 "h8300_dst_operand" "0,0") - (match_operand:HSI 2 "h8300_src_operand" "rQ,i")))] - "h8300_operands_match_p (operands)" - { - if (mode == HImode) - return "sub.w %T2,%T0"; - else if (mode == SImode) - return "sub.l %S2,%S0"; - gcc_unreachable (); - } - [(set_attr "length_table" "add") - (set_attr "cc" "set_zn")]) - - -;; ---------------------------------------------------------------------- -;; MULTIPLY INSTRUCTIONS -;; ---------------------------------------------------------------------- - -;; Note that the H8/300 can only handle umulqihi3. - -(define_expand "mulqihi3" - [(set (match_operand:HI 0 "register_operand" "") - (mult:HI (sign_extend:HI (match_operand:QI 1 "register_operand" "")) - ;; intentionally-mismatched modes - (match_operand:QI 2 "reg_or_nibble_operand" "")))] - "" - { - if (GET_MODE (operands[2]) != VOIDmode) - operands[2] = gen_rtx_SIGN_EXTEND (HImode, operands[2]); - }) - -(define_insn "*mulqihi3_const" - [(set (match_operand:HI 0 "register_operand" "=r") - (mult:HI (sign_extend:HI (match_operand:QI 1 "register_operand" "%0")) - (match_operand:QI 2 "nibble_operand" "IP4>X")))] - "TARGET_H8300SX" - "mulxs.b %X2,%T0" - [(set_attr "length" "4") - (set_attr "cc" "set_zn")]) - -(define_insn "*mulqihi3" - [(set (match_operand:HI 0 "register_operand" "=r") - (mult:HI (sign_extend:HI (match_operand:QI 1 "register_operand" "%0")) - (sign_extend:HI (match_operand:QI 2 "register_operand" "r"))))] - "" - "mulxs.b %X2,%T0" - [(set_attr "length" "4") - (set_attr "cc" "set_zn")]) - -(define_expand "mulhisi3" - [(set (match_operand:SI 0 "register_operand" "") - (mult:SI (sign_extend:SI (match_operand:HI 1 "register_operand" "")) - ;; intentionally-mismatched modes - (match_operand:HI 2 "reg_or_nibble_operand" "")))] - "" - { - if (GET_MODE (operands[2]) != VOIDmode) - operands[2] = gen_rtx_SIGN_EXTEND (SImode, operands[2]); - }) - -(define_insn "*mulhisi3_const" - [(set (match_operand:SI 0 "register_operand" "=r") - (mult:SI (sign_extend:SI (match_operand:HI 1 "register_operand" "%0")) - (match_operand:SI 2 "nibble_operand" "IP4>X")))] - "TARGET_H8300SX" - "mulxs.w %T2,%S0" - [(set_attr "length" "4") - (set_attr "cc" "set_zn")]) - -(define_insn "*mulhisi3" - [(set (match_operand:SI 0 "register_operand" "=r") - (mult:SI (sign_extend:SI (match_operand:HI 1 "register_operand" "%0")) - (sign_extend:SI (match_operand:HI 2 "register_operand" "r"))))] - "" - "mulxs.w %T2,%S0" - [(set_attr "length" "4") - (set_attr "cc" "set_zn")]) - -(define_expand "umulqihi3" - [(set (match_operand:HI 0 "register_operand" "") - (mult:HI (zero_extend:HI (match_operand:QI 1 "register_operand" "")) - ;; intentionally-mismatched modes - (match_operand:QI 2 "reg_or_nibble_operand" "")))] - "" - { - if (GET_MODE (operands[2]) != VOIDmode) - operands[2] = gen_rtx_ZERO_EXTEND (HImode, operands[2]); - }) - -(define_insn "*umulqihi3_const" - [(set (match_operand:HI 0 "register_operand" "=r") - (mult:HI (zero_extend:HI (match_operand:QI 1 "register_operand" "%0")) - (match_operand:QI 2 "nibble_operand" "IP4>X")))] - "TARGET_H8300SX" - "mulxu.b %X2,%T0" - [(set_attr "length" "4") - (set_attr "cc" "set_zn")]) - -(define_insn "*umulqihi3" - [(set (match_operand:HI 0 "register_operand" "=r") - (mult:HI (zero_extend:HI (match_operand:QI 1 "register_operand" "%0")) - (zero_extend:HI (match_operand:QI 2 "register_operand" "r"))))] - "" - "mulxu.b %X2,%T0" - [(set_attr "length" "2") - (set_attr "cc" "none_0hit")]) - -(define_expand "umulhisi3" - [(set (match_operand:SI 0 "register_operand" "") - (mult:SI (zero_extend:SI (match_operand:HI 1 "register_operand" "")) - ;; intentionally-mismatched modes - (match_operand:HI 2 "reg_or_nibble_operand" "")))] - "" - { - if (GET_MODE (operands[2]) != VOIDmode) - operands[2] = gen_rtx_ZERO_EXTEND (SImode, operands[2]); - }) - -(define_insn "*umulhisi3_const" - [(set (match_operand:SI 0 "register_operand" "=r") - (mult:SI (zero_extend:SI (match_operand:HI 1 "register_operand" "%0")) - (match_operand:SI 2 "nibble_operand" "IP4>X")))] - "TARGET_H8300SX" - "mulxu.w %T2,%S0" - [(set_attr "length" "4") - (set_attr "cc" "set_zn")]) - -(define_insn "*umulhisi3" - [(set (match_operand:SI 0 "register_operand" "=r") - (mult:SI (zero_extend:SI (match_operand:HI 1 "register_operand" "%0")) - (zero_extend:SI (match_operand:HI 2 "register_operand" "r"))))] - "" - "mulxu.w %T2,%S0" - [(set_attr "length" "2") - (set_attr "cc" "none_0hit")]) - -;; We could have used mulu.[wl] here, but mulu.[lw] is only available -;; on a H8SX with a multiplier, whereas muls.w seems to be available -;; on all H8SX variants. - -(define_insn "mul3" - [(set (match_operand:HSI 0 "register_operand" "=r") - (mult:HSI (match_operand:HSI 1 "register_operand" "%0") - (match_operand:HSI 2 "reg_or_nibble_operand" "r IP4>X")))] - "TARGET_H8300SX" - { return mode == HImode ? "muls.w\\t%T2,%T0" : "muls.l\\t%S2,%S0"; } - [(set_attr "length" "4") - (set_attr "cc" "set_zn")]) - -(define_insn "smulsi3_highpart" - [(set (match_operand:SI 0 "register_operand" "=r") - (truncate:SI - (lshiftrt:DI - (mult:DI - (sign_extend:DI (match_operand:SI 1 "register_operand" "%0")) - (sign_extend:DI (match_operand:SI 2 "reg_or_nibble_operand" "r IP4>X"))) - (const_int 32))))] - "TARGET_H8300SXMUL" - "muls/u.l\\t%S2,%S0" - [(set_attr "length" "4") - (set_attr "cc" "set_zn")]) - -(define_insn "umulsi3_highpart" - [(set (match_operand:SI 0 "register_operand" "=r") - (truncate:SI - (ashiftrt:DI - (mult:DI - (zero_extend:DI (match_operand:SI 1 "register_operand" "%0")) - (zero_extend:DI (match_operand:SI 2 "reg_or_nibble_operand" "r IP4>X"))) - (const_int 32))))] - "TARGET_H8300SX" - "mulu/u.l\\t%S2,%S0" - [(set_attr "length" "4") - (set_attr "cc" "none_0hit")]) - -;; This is a "bridge" instruction. Combine can't cram enough insns -;; together to crate a MAC instruction directly, but it can create -;; this instruction, which then allows combine to create the real -;; MAC insn. -;; -;; Unfortunately, if combine doesn't create a MAC instruction, this -;; insn must generate reasonably correct code. Egad. - -(define_insn "" - [(set (match_operand:SI 0 "register_operand" "=a") - (mult:SI - (sign_extend:SI - (mem:HI (post_inc:SI (match_operand:SI 1 "register_operand" "r")))) - (sign_extend:SI - (mem:HI (post_inc:SI (match_operand:SI 2 "register_operand" "r"))))))] - "TARGET_MAC" - "clrmac\;mac @%2+,@%1+" - [(set_attr "length" "6") - (set_attr "cc" "none_0hit")]) - -(define_insn "" - [(set (match_operand:SI 0 "register_operand" "=a") - (plus:SI (mult:SI - (sign_extend:SI (mem:HI - (post_inc:SI (match_operand:SI 1 "register_operand" "r")))) - (sign_extend:SI (mem:HI - (post_inc:SI (match_operand:SI 2 "register_operand" "r"))))) - (match_operand:SI 3 "register_operand" "0")))] - "TARGET_MAC" - "mac @%2+,@%1+" - [(set_attr "length" "4") - (set_attr "cc" "none_0hit")]) - -;; ---------------------------------------------------------------------- -;; DIVIDE/MOD INSTRUCTIONS -;; ---------------------------------------------------------------------- - -(define_insn "udiv3" - [(set (match_operand:HSI 0 "register_operand" "=r") - (udiv:HSI (match_operand:HSI 1 "register_operand" "0") - (match_operand:HSI 2 "reg_or_nibble_operand" "r IP4>X")))] - "TARGET_H8300SX" - { return mode == HImode ? "divu.w\\t%T2,%T0" : "divu.l\\t%S2,%S0"; } - [(set_attr "length" "4")]) - -(define_insn "div3" - [(set (match_operand:HSI 0 "register_operand" "=r") - (div:HSI (match_operand:HSI 1 "register_operand" "0") - (match_operand:HSI 2 "reg_or_nibble_operand" "r IP4>X")))] - "TARGET_H8300SX" - { return mode == HImode ? "divs.w\\t%T2,%T0" : "divs.l\\t%S2,%S0"; } - [(set_attr "length" "4")]) - -(define_insn "udivmodqi4" - [(set (match_operand:QI 0 "register_operand" "=r") - (truncate:QI - (udiv:HI - (match_operand:HI 1 "register_operand" "0") - (zero_extend:HI (match_operand:QI 2 "register_operand" "r"))))) - (set (match_operand:QI 3 "register_operand" "=r") - (truncate:QI - (umod:HI - (match_dup 1) - (zero_extend:HI (match_dup 2)))))] - "" -{ - if (find_reg_note (insn, REG_UNUSED, operands[3])) - return "divxu.b\\t%X2,%T0"; - else - return "divxu.b\\t%X2,%T0\;mov.b\\t%t0,%s3"; -} - [(set_attr "length" "4")]) - -(define_insn "divmodqi4" - [(set (match_operand:QI 0 "register_operand" "=r") - (truncate:QI - (div:HI - (match_operand:HI 1 "register_operand" "0") - (sign_extend:HI (match_operand:QI 2 "register_operand" "r"))))) - (set (match_operand:QI 3 "register_operand" "=r") - (truncate:QI - (mod:HI - (match_dup 1) - (sign_extend:HI (match_dup 2)))))] - "" -{ - if (find_reg_note (insn, REG_UNUSED, operands[3])) - return "divxs.b\\t%X2,%T0"; - else - return "divxs.b\\t%X2,%T0\;mov.b\\t%t0,%s3"; -} - [(set_attr "length" "6")]) - -(define_insn "udivmodhi4" - [(set (match_operand:HI 0 "register_operand" "=r") - (truncate:HI - (udiv:SI - (match_operand:SI 1 "register_operand" "0") - (zero_extend:SI (match_operand:HI 2 "register_operand" "r"))))) - (set (match_operand:HI 3 "register_operand" "=r") - (truncate:HI - (umod:SI - (match_dup 1) - (zero_extend:SI (match_dup 2)))))] - "" -{ - if (find_reg_note (insn, REG_UNUSED, operands[3])) - return "divxu.w\\t%T2,%S0"; - else - return "divxu.w\\t%T2,%S0\;mov.w\\t%e0,%f3"; -} - [(set_attr "length" "4")]) - -(define_insn "divmodhi4" - [(set (match_operand:HI 0 "register_operand" "=r") - (truncate:HI - (div:SI - (match_operand:SI 1 "register_operand" "0") - (sign_extend:SI (match_operand:HI 2 "register_operand" "r"))))) - (set (match_operand:HI 3 "register_operand" "=r") - (truncate:HI - (mod:SI - (match_dup 1) - (sign_extend:SI (match_dup 2)))))] - "" -{ - if (find_reg_note (insn, REG_UNUSED, operands[3])) - return "divxs.w\\t%T2,%S0"; - else - return "divxs.w\\t%T2,%S0\;mov.w\\t%e0,%f3"; -} - [(set_attr "length" "6")]) - -;; ---------------------------------------------------------------------- -;; AND INSTRUCTIONS -;; ---------------------------------------------------------------------- - -(define_insn "bclrqi_msx" - [(set (match_operand:QI 0 "bit_register_indirect_operand" "=WU") - (and:QI (match_operand:QI 1 "bit_register_indirect_operand" "%0") - (match_operand:QI 2 "single_zero_operand" "Y0")))] - "TARGET_H8300SX && rtx_equal_p (operands[0], operands[1])" - "bclr\\t%W2,%0" - [(set_attr "length" "8")]) - -(define_split - [(set (match_operand:HI 0 "bit_register_indirect_operand") - (and:HI (match_operand:HI 1 "bit_register_indirect_operand") - (match_operand:HI 2 "single_zero_operand")))] - "TARGET_H8300SX" - [(set (match_dup 0) - (and:QI (match_dup 1) - (match_dup 2)))] - { - if (abs (INTVAL (operands[2])) > 0xFF) - { - operands[0] = adjust_address (operands[0], QImode, 0); - operands[1] = adjust_address (operands[1], QImode, 0); - operands[2] = GEN_INT ((INTVAL (operands[2])) >> 8); - } - else - { - operands[0] = adjust_address (operands[0], QImode, 1); - operands[1] = adjust_address (operands[1], QImode, 1); - } - }) - -(define_insn "bclrhi_msx" - [(set (match_operand:HI 0 "bit_register_indirect_operand" "=m") - (and:HI (match_operand:HI 1 "bit_register_indirect_operand" "%0") - (match_operand:HI 2 "single_zero_operand" "Y0")))] - "TARGET_H8300SX" - "bclr\\t%W2,%0" - [(set_attr "length" "8")]) - -(define_insn "*andqi3_2" - [(set (match_operand:QI 0 "bit_operand" "=U,rQ,r") - (and:QI (match_operand:QI 1 "bit_operand" "%0,0,WU") - (match_operand:QI 2 "h8300_src_operand" "Y0,rQi,IP1>X")))] - "TARGET_H8300SX" - "@ - bclr\\t %W2,%R0 - and %X2,%X0 - bfld %2,%1,%R0" - [(set_attr "length" "8,*,8") - (set_attr "length_table" "*,logicb,*") - (set_attr "cc" "none_0hit,set_znv,none_0hit")]) - -(define_insn "andqi3_1" - [(set (match_operand:QI 0 "bit_operand" "=U,r") - (and:QI (match_operand:QI 1 "bit_operand" "%0,0") - (match_operand:QI 2 "h8300_src_operand" "Y0,rn")))] - "register_operand (operands[0], QImode) - || single_zero_operand (operands[2], QImode)" - "@ - bclr %W2,%R0 - and %X2,%X0" - [(set_attr "length" "2,8") - (set_attr "cc" "none_0hit,set_znv")]) - -(define_expand "and3" - [(set (match_operand:QHSI 0 "register_operand" "") - (and:QHSI (match_operand:QHSI 1 "register_operand" "") - (match_operand:QHSI 2 "h8300_src_operand" "")))] - "" - "") - -(define_insn "*andor3" - [(set (match_operand:QHSI 0 "register_operand" "=r") - (ior:QHSI (and:QHSI (match_operand:QHSI 2 "register_operand" "r") - (match_operand:QHSI 3 "single_one_operand" "n")) - (match_operand:QHSI 1 "register_operand" "0")))] - "(mode == QImode - || mode == HImode - || (mode == SImode - && (INTVAL (operands[3]) & 0xffff) != 0))" - { - if (mode == QImode) - return "bld\\t%V3,%X2\;bor\\t%V3,%X0\;bst\\t%V3,%X0"; - - if (mode == HImode) - { - operands[3] = GEN_INT (INTVAL (operands[3]) & 0xffff); - if (INTVAL (operands[3]) > 128) - { - operands[3] = GEN_INT (INTVAL (operands[3]) >> 8); - return "bld\\t%V3,%t2\;bor\\t%V3,%t0\;bst\\t%V3,%t0"; - } - return "bld\\t%V3,%s2\;bor\\t%V3,%s0\;bst\\t%V3,%s0"; - } - - if (mode == SImode) - { - operands[3] = GEN_INT (INTVAL (operands[3]) & 0xffff); - if (INTVAL (operands[3]) > 128) - { - operands[3] = GEN_INT (INTVAL (operands[3]) >> 8); - return "bld\\t%V3,%x2\;bor\\t%V3,%x0\;bst\\t%V3,%x0"; - } - return "bld\\t%V3,%w2\;bor\\t%V3,%w0\;bst\\t%V3,%w0"; - } - - gcc_unreachable (); - - } - [(set_attr "length" "6")]) - -(define_insn "*andorsi3_shift_8" - [(set (match_operand:SI 0 "register_operand" "=r") - (ior:SI (and:SI (ashift:SI (match_operand:SI 2 "register_operand" "r") - (const_int 8)) - (const_int 65280)) - (match_operand:SI 1 "register_operand" "0")))] - "" - "or.b\\t%w2,%x0" - [(set_attr "length" "2")]) - -;; ---------------------------------------------------------------------- -;; OR/XOR INSTRUCTIONS -;; ---------------------------------------------------------------------- - -(define_insn "bqi_msx" - [(set (match_operand:QI 0 "bit_register_indirect_operand" "=WU") - (ors:QI (match_operand:QI 1 "bit_register_indirect_operand" "%0") - (match_operand:QI 2 "single_one_operand" "Y2")))] - "TARGET_H8300SX && rtx_equal_p (operands[0], operands[1])" - { return == IOR ? "bset\\t%V2,%0" : "bnot\\t%V2,%0"; } - [(set_attr "length" "8")]) - -(define_insn "bhi_msx" - [(set (match_operand:HI 0 "bit_register_indirect_operand" "=m") - (ors:HI (match_operand:HI 1 "bit_register_indirect_operand" "%0") - (match_operand:HI 2 "single_one_operand" "Y2")))] - "TARGET_H8300SX" - { return == IOR ? "bset\\t%V2,%0" : "bnot\\t%V2,%0"; } - [(set_attr "length" "8")]) - -(define_insn "qi3_1" - [(set (match_operand:QI 0 "bit_operand" "=U,rQ") - (ors:QI (match_operand:QI 1 "bit_operand" "%0,0") - (match_operand:QI 2 "h8300_src_operand" "Y2,rQi")))] - "TARGET_H8300SX || register_operand (operands[0], QImode) - || single_one_operand (operands[2], QImode)" - { - if (which_alternative == 0) - return == IOR ? "bset\\t%V2,%R0" : "bnot\\t%V2,%R0"; - else if (which_alternative == 1) - return == IOR ? "or\\t%X2,%X0" : "xor\\t%X2,%X0"; - gcc_unreachable (); - } - [(set_attr "length" "8,*") - (set_attr "length_table" "*,logicb") - (set_attr "cc" "none_0hit,set_znv")]) - -(define_expand "3" - [(set (match_operand:QHSI 0 "register_operand" "") - (ors:QHSI (match_operand:QHSI 1 "register_operand" "") - (match_operand:QHSI 2 "h8300_src_operand" "")))] - "" - "") - -;; ---------------------------------------------------------------------- -;; {AND,IOR,XOR}{HI3,SI3} PATTERNS -;; ---------------------------------------------------------------------- - -(define_insn "*logical3" - [(set (match_operand:HSI 0 "h8300_dst_operand" "=rQ") - (match_operator:HSI 3 "bit_operator" - [(match_operand:HSI 1 "h8300_dst_operand" "%0") - (match_operand:HSI 2 "h8300_src_operand" "rQi")]))] - "h8300_operands_match_p (operands)" - { return output_logical_op (mode, operands); } - [(set (attr "length") - (symbol_ref "compute_logical_op_length (mode, operands)")) - (set (attr "cc") - (symbol_ref "compute_logical_op_cc (mode, operands)"))]) - -;; ---------------------------------------------------------------------- -;; NEGATION INSTRUCTIONS -;; ---------------------------------------------------------------------- - -(define_expand "neg2" - [(set (match_operand:QHSIF 0 "register_operand" "") - (neg:QHSIF (match_operand:QHSIF 1 "register_operand" "")))] - "" - "") - -(define_insn "*neg2" - [(set (match_operand:QHSI 0 "h8300_dst_operand" "=rQ") - (neg:QHSI (match_operand:QHSI 1 "h8300_dst_operand" "0")))] - "" - { - if (mode == E_QImode) - return "neg %X0"; - if (mode == E_HImode) - return "neg.w %T0"; - if (mode == E_SImode) - return "neg.l %S0"; - gcc_unreachable (); - } - [(set_attr "length_table" "unary") - (set_attr "cc" "set_zn")]) - - -(define_insn "*negsf2_h8300hs" - [(set (match_operand:SF 0 "register_operand" "=r") - (neg:SF (match_operand:SF 1 "register_operand" "0")))] - "" - "xor.w\\t#32768,%e0" - [(set_attr "length" "4")]) - - -;; ---------------------------------------------------------------------- -;; ABSOLUTE VALUE INSTRUCTIONS -;; ---------------------------------------------------------------------- - -(define_insn "abssf2" - [(set (match_operand:SF 0 "register_operand" "=r") - (abs:SF (match_operand:SF 1 "register_operand" "0")))] - "" - "and.w\\t#32767,%e0" - [(set_attr "length" "4")]) - -;; ---------------------------------------------------------------------- -;; NOT INSTRUCTIONS -;; ---------------------------------------------------------------------- - -(define_insn "one_cmpl2" - [(set (match_operand:QHSI 0 "h8300_dst_operand" "=rQ") - (not:QHSI (match_operand:QHSI 1 "h8300_dst_operand" "0")))] - "" - { - if (mode == E_QImode) - return "not %X0"; - if (mode == E_HImode) - return "not.w %T0"; - if (mode == E_SImode) - return "not.l %S0"; - gcc_unreachable (); - } - [(set_attr "length_table" "unary") - (set_attr "cc" "set_znv")]) - - -;; ---------------------------------------------------------------------- -;; JUMP INSTRUCTIONS -;; ---------------------------------------------------------------------- - -;; Conditional jump instructions - -(define_expand "cbranchqi4" - [(use (match_operator 0 "ordered_comparison_operator" - [(match_operand:QI 1 "h8300_dst_operand" "") - (match_operand:QI 2 "h8300_src_operand" "")])) - (use (match_operand 3 ""))] - "" - { - h8300_expand_branch (operands); - DONE; - }) - -(define_expand "cbranchhi4" - [(use (match_operator 0 "ordered_comparison_operator" - [(match_operand:HI 1 "h8300_dst_operand" "") - (match_operand:HI 2 "h8300_src_operand" "")])) - (use (match_operand 3 ""))] - "" - { - h8300_expand_branch (operands); - DONE; - }) - -(define_expand "cbranchsi4" - [(use (match_operator 0 "ordered_comparison_operator" - [(match_operand:SI 1 "h8300_dst_operand" "") - (match_operand:SI 2 "h8300_src_operand" "")])) - (use (match_operand 3 ""))] - "" - { - h8300_expand_branch (operands); - DONE; - }) - -(define_insn "branch_true" - [(set (pc) - (if_then_else (match_operator 1 "comparison_operator" - [(cc0) (const_int 0)]) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" -{ - if ((cc_status.flags & CC_OVERFLOW_UNUSABLE) != 0 - && (GET_CODE (operands[1]) == GT - || GET_CODE (operands[1]) == GE - || GET_CODE (operands[1]) == LE - || GET_CODE (operands[1]) == LT)) - { - cc_status.flags &= ~CC_OVERFLOW_UNUSABLE; - return 0; - } - - if (get_attr_length (insn) == 2) - return "b%j1 %l0"; - else if (get_attr_length (insn) == 4) - return "b%j1 %l0:16"; - else - return "b%k1 .Lh8BR%=\;jmp @%l0\\n.Lh8BR%=:"; -} - [(set_attr "type" "branch") - (set_attr "cc" "none")]) - -(define_insn "branch_false" - [(set (pc) - (if_then_else (match_operator 1 "comparison_operator" - [(cc0) (const_int 0)]) - (pc) - (label_ref (match_operand 0 "" ""))))] - "" -{ - if ((cc_status.flags & CC_OVERFLOW_UNUSABLE) != 0 - && (GET_CODE (operands[1]) == GT - || GET_CODE (operands[1]) == GE - || GET_CODE (operands[1]) == LE - || GET_CODE (operands[1]) == LT)) - { - cc_status.flags &= ~CC_OVERFLOW_UNUSABLE; - return 0; - } - - if (get_attr_length (insn) == 2) - return "b%k1 %l0"; - else if (get_attr_length (insn) == 4) - return "b%k1 %l0:16"; - else - return "b%j1 .Lh8BR%=\;jmp @%l0\\n.Lh8BR%=:"; -} - [(set_attr "type" "branch") - (set_attr "cc" "none")]) - -(define_insn "*brabc" - [(set (pc) - (if_then_else (eq (zero_extract (match_operand:QI 1 "bit_memory_operand" "WU") - (const_int 1) - (match_operand:QI 2 "immediate_operand" "n")) - (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "TARGET_H8300SX" -{ - switch (get_attr_length (insn) - - h8300_insn_length_from_table (insn, operands)) - { - case 2: - return "bra/bc %2,%R1,%l0"; - case 4: - return "bra/bc %2,%R1,%l0:16"; - default: - return "bra/bs %2,%R1,.Lh8BR%=\;jmp @%l0\\n.Lh8BR%=:"; - } -} - [(set_attr "type" "bitbranch") - (set_attr "length_table" "bitbranch") - (set_attr "cc" "none")]) - -(define_insn "*brabs" - [(set (pc) - (if_then_else (ne (zero_extract (match_operand:QI 1 "bit_memory_operand" "WU") - (const_int 1) - (match_operand:QI 2 "immediate_operand" "n")) - (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "TARGET_H8300SX" -{ - switch (get_attr_length (insn) - - h8300_insn_length_from_table (insn, operands)) - { - case 2: - return "bra/bs %2,%R1,%l0"; - case 4: - return "bra/bs %2,%R1,%l0:16"; - default: - return "bra/bc %2,%R1,.Lh8BR%=\;jmp @%l0\\n.Lh8BR%=:"; - } -} - [(set_attr "type" "bitbranch") - (set_attr "length_table" "bitbranch") - (set_attr "cc" "none")]) - -;; Unconditional and other jump instructions. - -(define_insn "jump" - [(set (pc) - (label_ref (match_operand 0 "" "")))] - "" -{ - if (final_sequence != 0) - { - if (get_attr_length (insn) == 2) - return "bra/s %l0"; - else - { - /* The branch isn't short enough to use bra/s. Output the - branch and delay slot in their normal order. - - If this is a backward branch, it will now be branching two - bytes further than previously thought. The length-based - test for bra vs. jump is very conservative though, so the - branch will still be within range. */ - rtx_sequence *seq; - int seen; - - seq = final_sequence; - final_sequence = 0; - final_scan_insn (seq->insn (1), asm_out_file, optimize, 1, & seen); - final_scan_insn (seq->insn (0), asm_out_file, optimize, 1, & seen); - seq->insn (1)->set_deleted (); - return ""; - } - } - else if (get_attr_length (insn) == 2) - return "bra %l0"; - else if (get_attr_length (insn) == 4) - return "bra %l0:16"; - else - return "jmp @%l0"; -} - [(set_attr "type" "branch") - (set (attr "delay_slot") - (if_then_else (match_test "TARGET_H8300SX") - (const_string "jump") - (const_string "none"))) - (set_attr "cc" "none")]) - -;; This is a define expand, because pointers may be either 16 or 32 bits. - -(define_expand "tablejump" - [(parallel [(set (pc) (match_operand 0 "register_operand" "")) - (use (label_ref (match_operand 1 "" "")))])] - "" - "") - -(define_insn "tablejump" - [(set (pc) (match_operand:P 0 "register_operand" "r")) - (use (label_ref (match_operand 1 "" "")))] - "" - { - if (mode == E_HImode) - return "jmp @%0"; - if (mode == E_SImode) - return "jmp @%S0"; - gcc_unreachable (); - } - [(set_attr "cc" "none") - (set_attr "length" "2")]) - -;; This is a define expand, because pointers may be either 16 or 32 bits. - -(define_expand "indirect_jump" - [(set (pc) (match_operand 0 "jump_address_operand" ""))] - "" - "") - -(define_insn "*indirect_jump_" - [(set (pc) (match_operand:P 0 "jump_address_operand" "Vr"))] - "" - { - if (mode == E_HImode) - return "jmp @%0"; - if (mode == E_SImode) - return "jmp @%S0"; - gcc_unreachable (); - } - [(set_attr "cc" "none") - (set_attr "length" "2")]) - -;; Call subroutine with no return value. - -;; ??? Even though we use HImode here, this works on the H8/300H and H8S. - -(define_expand "call" - [(call (match_operand:QI 0 "call_expander_operand" "") - (match_operand 1 "general_operand" ""))] - "" - { - if (!register_operand (XEXP (operands[0], 0), Pmode) - && GET_CODE (XEXP (operands[0], 0)) != SYMBOL_REF) - XEXP (operands[0], 0) = force_reg (Pmode, XEXP (operands[0], 0)); - }) - -(define_insn "call_insn_" - [(call (mem:QI (match_operand 0 "call_insn_operand" "Cr")) - (match_operand:P 1 "general_operand" "g"))] - "" -{ - rtx xoperands[1]; - xoperands[0] = gen_rtx_MEM (QImode, operands[0]); - gcc_assert (GET_MODE (operands[0]) == Pmode); - if (GET_CODE (XEXP (xoperands[0], 0)) == SYMBOL_REF - && (SYMBOL_REF_FLAGS (XEXP (xoperands[0], 0)) & SYMBOL_FLAG_FUNCVEC_FUNCTION)) - output_asm_insn ("jsr\\t@%0:8", xoperands); - else - output_asm_insn ("jsr\\t%0", xoperands); - return ""; -} - [(set_attr "type" "call") - (set (attr "length") - (if_then_else (match_operand:QI 0 "small_call_insn_operand" "") - (const_int 2) - (const_int 4)))]) - -;; Call subroutine, returning value in operand 0 -;; (which must be a hard register). - -;; ??? Even though we use HImode here, this works on the H8/300H and H8S. - -(define_expand "call_value" - [(set (match_operand 0 "" "") - (call (match_operand:QI 1 "call_expander_operand" "") - (match_operand 2 "general_operand" "")))] - "" - { - if (!register_operand (XEXP (operands[1], 0), Pmode) - && GET_CODE (XEXP (operands[1], 0)) != SYMBOL_REF) - XEXP (operands[1], 0) = force_reg (Pmode, XEXP (operands[1], 0)); - }) - -(define_insn "call_value_insn_" - [(set (match_operand 0 "" "=r") - (call (mem:QI (match_operand 1 "call_insn_operand" "Cr")) - (match_operand:P 2 "general_operand" "g")))] - "" -{ - rtx xoperands[2]; - gcc_assert (GET_MODE (operands[1]) == Pmode); - xoperands[0] = operands[0]; - xoperands[1] = gen_rtx_MEM (QImode, operands[1]); - if (GET_CODE (XEXP (xoperands[1], 0)) == SYMBOL_REF - && (SYMBOL_REF_FLAGS (XEXP (xoperands[1], 0)) & SYMBOL_FLAG_FUNCVEC_FUNCTION)) - output_asm_insn ("jsr\\t@%1:8", xoperands); - else - output_asm_insn ("jsr\\t%1", xoperands); - return ""; -} - [(set_attr "type" "call") - (set (attr "length") - (if_then_else (match_operand:QI 0 "small_call_insn_operand" "") - (const_int 2) - (const_int 4)))]) - -(define_insn "nop" - [(const_int 0)] - "" - "nop" - [(set_attr "cc" "none") - (set_attr "length" "2")]) - -;; ---------------------------------------------------------------------- -;; PROLOGUE/EPILOGUE-RELATED INSTRUCTIONS -;; ---------------------------------------------------------------------- - -(define_expand "push_h8300hs_advanced" - [(set (mem:SI (pre_dec:SI (reg:SI SP_REG))) - (match_operand:SI 0 "register_operand" ""))] - "TARGET_H8300H && TARGET_H8300S && !TARGET_NORMAL_MODE" - "") - -(define_expand "push_h8300hs_normal" - [(set (mem:SI (pre_dec:HI (reg:HI SP_REG))) - (match_operand:SI 0 "register_operand" ""))] - "TARGET_H8300H && TARGET_H8300S && TARGET_NORMAL_MODE" - "") - -(define_expand "pop_h8300hs_advanced" - [(set (match_operand:SI 0 "register_operand" "") - (mem:SI (post_inc:SI (reg:SI SP_REG))))] - "TARGET_H8300H && TARGET_H8300S && !TARGET_NORMAL_MODE" - "") - -(define_expand "pop_h8300hs_normal" - [(set (match_operand:SI 0 "register_operand" "") - (mem:SI (post_inc:HI (reg:HI SP_REG))))] - "TARGET_H8300H && TARGET_H8300S && TARGET_NORMAL_MODE" - "") - -(define_insn "ldm_h8300sx" - [(match_parallel 0 "h8300_ldm_parallel" - [(set (match_operand:SI 1 "register_operand" "") - (match_operand:SI 2 "memory_operand" ""))])] - "TARGET_H8300S" -{ - operands[3] = SET_DEST (XVECEXP (operands[0], 0, - XVECLEN (operands[0], 0) - 2)); - return "ldm.l\t@er7+,%S1-%S3"; -} - [(set_attr "cc" "none") - (set_attr "length" "4")]) - -(define_insn "stm_h8300sx" - [(match_parallel 0 "h8300_stm_parallel" - [(set (match_operand:SI 1 "memory_operand" "") - (match_operand:SI 2 "register_operand" ""))])] - "TARGET_H8300S" -{ - operands[3] = SET_SRC (XVECEXP (operands[0], 0, - XVECLEN (operands[0], 0) - 2)); - return "stm.l\t%S2-%S3,@-er7"; -} - [(set_attr "cc" "none") - (set_attr "length" "4")]) - -(define_insn "return_h8sx" - [(match_parallel 0 "h8300_return_parallel" - [(return) - (set (match_operand:SI 1 "register_operand" "") - (match_operand:SI 2 "memory_operand" ""))])] - "TARGET_H8300SX" -{ - operands[3] = SET_DEST (XVECEXP (operands[0], 0, - XVECLEN (operands[0], 0) - 2)); - if (h8300_current_function_interrupt_function_p () - || h8300_current_function_monitor_function_p ()) - return "rte/l\t%S1-%S3"; - else - return "rts/l\t%S1-%S3"; -} - [(set_attr "cc" "none") - (set_attr "can_delay" "no") - (set_attr "length" "2")]) - -(define_expand "return" - [(return)] - "h8300_can_use_return_insn_p ()" - "") - -(define_insn "*return_1" - [(return)] - "reload_completed" -{ - if (h8300_current_function_interrupt_function_p () - || h8300_current_function_monitor_function_p ()) - return "rte"; - else - return "rts"; -} - [(set_attr "cc" "none") - (set_attr "can_delay" "no") - (set_attr "length" "2")]) - -(define_expand "prologue" - [(const_int 0)] - "" - { - h8300_expand_prologue (); - DONE; - }) - -(define_expand "epilogue" - [(return)] - "" - { - h8300_expand_epilogue (); - DONE; - }) - -(define_insn "monitor_prologue" - [(unspec_volatile [(const_int 0)] UNSPEC_MONITOR)] - "" -{ - if (TARGET_H8300H && TARGET_NORMAL_MODE) - return "subs\\t#2,er7\;mov.l\\ter0,@-er7\;stc\\tccr,r0l\;mov.b\\tr0l,@(4,er7)\;mov.l\\t@er7+,er0\;orc\\t#128,ccr"; - else if (TARGET_H8300H) - return "mov.l\\ter0,@-er7\;stc\\tccr,r0l\;mov.b\\tr0l,@(4,er7)\;mov.l\\t@er7+,er0\;orc\\t#128,ccr"; - else if (TARGET_H8300S && TARGET_NEXR ) - return "mov.l\\ter0,@-er7\;stc\tccr,r0l\;mov.b\tr0l,@(4,er7)\;mov.l\\t@er7+,er0\;orc\t#128,ccr"; - else if (TARGET_H8300S && TARGET_NEXR && TARGET_NORMAL_MODE) - return "subs\\t#2,er7\;mov.l\\ter0,@-er7\;stc\tccr,r0l\;mov.b\tr0l,@(4,er7)\;mov.l\\t@er7+,er0\;orc\t#128,ccr"; - else if (TARGET_H8300S && TARGET_NORMAL_MODE) - return "subs\\t#2,er7\;stc\texr,@-er7\;mov.l\\ter0,@-er7\;stc\tccr,r0l\;mov.b\tr0l,@(6,er7)\;mov.l\\t@er7+,er0\;orc\t#128,ccr"; - else if (TARGET_H8300S) - return "stc\texr,@-er7\;mov.l\\ter0,@-er7\;stc\tccr,r0l\;mov.b\tr0l,@(6,er7)\;mov.l\\t@er7+,er0\;orc\t#128,ccr"; - gcc_unreachable (); -} - [(set_attr "length" "20")]) - -;; ---------------------------------------------------------------------- -;; EXTEND INSTRUCTIONS -;; ---------------------------------------------------------------------- - -(define_expand "zero_extendqi2" - [(set (match_operand:HSI 0 "register_operand" "") - (zero_extend:HSI (match_operand:QI 1 "general_operand_src" "")))] - "" - { - if (TARGET_H8300SX) - operands[1] = force_reg (QImode, operands[1]); - }) - -(define_insn "*zero_extendqihi2_h8300hs" - [(set (match_operand:HI 0 "register_operand" "=r,r") - (zero_extend:HI (match_operand:QI 1 "general_operand_src" "0,g>")))] - "" - "@ - extu.w %T0 - #" - [(set_attr "length" "2,10") - (set_attr "cc" "set_znv,set_znv")]) - -;; Split the zero extension of a general operand (actually a memory -;; operand) into a load of the operand and the actual zero extension -;; so that 1) the length will be accurate, and 2) the zero extensions -;; appearing at the end of basic blocks may be merged. - -(define_split - [(set (match_operand:HI 0 "register_operand" "") - (zero_extend:HI (match_operand:QI 1 "general_operand_src" "")))] - "reload_completed" - [(set (match_dup 2) - (match_dup 1)) - (set (match_dup 0) - (zero_extend:HI (match_dup 2)))] - { - operands[2] = gen_rtx_REG (QImode, REGNO (operands[0])); - }) - -(define_insn "*zero_extendqisi2_h8300hs" - [(set (match_operand:SI 0 "register_operand" "=r,r") - (zero_extend:SI (match_operand:QI 1 "general_operand_src" "0,g>")))] - "!TARGET_H8300SX" - "#") - -(define_split - [(set (match_operand:SI 0 "register_operand" "") - (zero_extend:SI (match_operand:QI 1 "general_operand_src" "")))] - "!TARGET_H8300SX - && reg_overlap_mentioned_p (operands[0], operands[1]) - && reload_completed" - [(set (match_dup 2) - (match_dup 1)) - (set (match_dup 3) - (zero_extend:HI (match_dup 2))) - (set (match_dup 0) - (zero_extend:SI (match_dup 3)))] - { - operands[2] = gen_lowpart (QImode, operands[0]); - operands[3] = gen_lowpart (HImode, operands[0]); - }) - -(define_split - [(set (match_operand:SI 0 "register_operand" "") - (zero_extend:SI (match_operand:QI 1 "general_operand_src" "")))] - "!TARGET_H8300SX - && !reg_overlap_mentioned_p (operands[0], operands[1]) - && reload_completed" - [(set (match_dup 0) - (const_int 0)) - (set (strict_low_part (match_dup 2)) - (match_dup 1))] - { - operands[2] = gen_rtx_REG (QImode, REGNO (operands[0])); - }) - -(define_insn "*zero_extendqisi2_h8sx" - [(set (match_operand:SI 0 "register_operand" "=r") - (zero_extend:SI (match_operand:QI 1 "register_operand" "0")))] - "TARGET_H8300SX" - "extu.l\t#2,%0" - [(set_attr "length" "2") - (set_attr "cc" "set_znv")]) - -(define_expand "zero_extendhisi2" - [(set (match_operand:SI 0 "register_operand" "") - (zero_extend:SI (match_operand:HI 1 "register_operand" "")))] - "" - "") - -(define_insn "*zero_extendhisi2_h8300hs" - [(set (match_operand:SI 0 "register_operand" "=r") - (zero_extend:SI (match_operand:HI 1 "register_operand" "0")))] - "" - "extu.l %S0" - [(set_attr "length" "2") - (set_attr "cc" "set_znv")]) - -(define_expand "extendqi2" - [(set (match_operand:HSI 0 "register_operand" "") - (sign_extend:HSI (match_operand:QI 1 "register_operand" "")))] - "" - "") - -(define_insn "*extendqihi2_h8300hs" - [(set (match_operand:HI 0 "register_operand" "=r") - (sign_extend:HI (match_operand:QI 1 "register_operand" "0")))] - "" - "exts.w %T0" - [(set_attr "length" "2") - (set_attr "cc" "set_znv")]) - -;; The following pattern is needed because without the pattern, the -;; combiner would split (sign_extend:SI (reg:QI)) into two 24-bit -;; shifts, one ashift and one ashiftrt. - -(define_insn_and_split "*extendqisi2_h8300hs" - [(set (match_operand:SI 0 "register_operand" "=r") - (sign_extend:SI (match_operand:QI 1 "register_operand" "0")))] - "!TARGET_H8300SX" - "#" - "&& reload_completed" - [(set (match_dup 2) - (sign_extend:HI (match_dup 1))) - (set (match_dup 0) - (sign_extend:SI (match_dup 2)))] - { - operands[2] = gen_rtx_REG (HImode, REGNO (operands[0])); - }) - -(define_insn "*extendqisi2_h8sx" - [(set (match_operand:SI 0 "register_operand" "=r") - (sign_extend:SI (match_operand:QI 1 "register_operand" "0")))] - "TARGET_H8300SX" - "exts.l\t#2,%0" - [(set_attr "length" "2") - (set_attr "cc" "set_znv")]) - -(define_expand "extendhisi2" - [(set (match_operand:SI 0 "register_operand" "") - (sign_extend:SI (match_operand:HI 1 "register_operand" "")))] - "" - "") - -(define_insn "*extendhisi2_h8300hs" - [(set (match_operand:SI 0 "register_operand" "=r") - (sign_extend:SI (match_operand:HI 1 "register_operand" "0")))] - "" - "exts.l %S0" - [(set_attr "length" "2") - (set_attr "cc" "set_znv")]) - -;; ---------------------------------------------------------------------- -;; SHIFTS -;; ---------------------------------------------------------------------- -;; -;; We make some attempt to provide real efficient shifting. One example is -;; doing an 8-bit shift of a 16-bit value by moving a byte reg into the other -;; reg and moving 0 into the former reg. -;; -;; We also try to achieve this in a uniform way. IE: We don't try to achieve -;; this in both rtl and at insn emit time. Ideally, we'd use rtl as that would -;; give the optimizer more cracks at the code. However, we wish to do things -;; like optimizing shifting the sign bit to bit 0 by rotating the other way. -;; There is rtl to handle this (rotate + and), but the H8/300 doesn't handle -;; 16-bit rotates. Also, if we emit complicated rtl, combine may not be able -;; to detect cases it can optimize. -;; -;; For these and other fuzzy reasons, I've decided to go the less pretty but -;; easier "do it at insn emit time" route. - - -(define_expand "ashl3" - [(set (match_operand:QHSI 0 "register_operand" "") - (ashift:QHSI (match_operand:QHSI 1 "register_operand" "") - (match_operand:QI 2 "nonmemory_operand" "")))] - "" - { - if (expand_a_shift (mode, ASHIFT, operands)) - DONE; - }) - -(define_expand "ashr3" - [(set (match_operand:QHSI 0 "register_operand" "") - (ashiftrt:QHSI (match_operand:QHSI 1 "register_operand" "") - (match_operand:QI 2 "nonmemory_operand" "")))] - "" - { - if (expand_a_shift (mode, ASHIFTRT, operands)) - DONE; - }) - -(define_expand "lshr3" - [(set (match_operand:QHSI 0 "register_operand" "") - (lshiftrt:QHSI (match_operand:QHSI 1 "register_operand" "") - (match_operand:QI 2 "nonmemory_operand" "")))] - "" - { - if (expand_a_shift (mode, LSHIFTRT, operands)) - DONE; - }) - -;; QI/HI/SI BIT SHIFTS -;; Sub-optimal WRT the scratch operand - -(define_insn "" - [(set (match_operand:QHSI 0 "h8300_dst_operand" "=rQ") - (match_operator:QHSI 3 "h8sx_unary_shift_operator" - [(match_operand:QHSI 1 "h8300_dst_operand" "0") - (match_operand:QI 2 "const_int_operand" "")]))] - "h8300_operands_match_p (operands)" -{ - if (mode == E_QImode) - return output_h8sx_shift (operands, 'b', 'X'); - if (mode == E_HImode) - return output_h8sx_shift (operands, 'w', 'T'); - if (mode == E_SImode) - return output_h8sx_shift (operands, 'l', 'S'); - gcc_unreachable (); -} - [(set_attr "length_table" "unary") - (set_attr "cc" "set_znv")]) - -(define_insn "" - [(set (match_operand:QHSI 0 "register_operand" "=r") - (match_operator:QHSI 3 "h8sx_binary_shift_operator" - [(match_operand:QHSI 1 "register_operand" "0") - (match_operand:QI 2 "nonmemory_operand" "r P5>X")]))] - "" -{ - if (mode == QImode) - return output_h8sx_shift (operands, 'b', 'X'); - if (mode == HImode) - return output_h8sx_shift (operands, 'w', 'T'); - if (mode == SImode) - return output_h8sx_shift (operands, 'l', 'S'); - gcc_unreachable (); -} - [(set_attr "length" "4") - (set_attr "cc" "set_znv")]) - -(define_insn "*shiftqi" - [(set (match_operand:QI 0 "register_operand" "=r,r") - (match_operator:QI 3 "nshift_operator" - [(match_operand:QI 1 "register_operand" "0,0") - (match_operand:QI 2 "nonmemory_operand" "R,rn")])) - (clobber (match_scratch:QI 4 "=X,&r"))] - "" -{ - return output_a_shift (operands); -} - [(set (attr "length") - (symbol_ref "compute_a_shift_length (insn, operands)")) - (set (attr "cc") - (symbol_ref "compute_a_shift_cc (insn, operands)"))]) - -(define_insn "*shifthi" - [(set (match_operand:HI 0 "register_operand" "=r,r") - (match_operator:HI 3 "nshift_operator" - [(match_operand:HI 1 "register_operand" "0,0") - (match_operand:QI 2 "nonmemory_operand" "S,rn")])) - (clobber (match_scratch:QI 4 "=X,&r"))] - "" -{ - return output_a_shift (operands); -} - [(set (attr "length") - (symbol_ref "compute_a_shift_length (insn, operands)")) - (set (attr "cc") - (symbol_ref "compute_a_shift_cc (insn, operands)"))]) - -(define_insn "*shiftsi" - [(set (match_operand:SI 0 "register_operand" "=r,r") - (match_operator:SI 3 "nshift_operator" - [(match_operand:SI 1 "register_operand" "0,0") - (match_operand:QI 2 "nonmemory_operand" "T,rn")])) - (clobber (match_scratch:QI 4 "=X,&r"))] - "" -{ - return output_a_shift (operands); -} - [(set (attr "length") - (symbol_ref "compute_a_shift_length (insn, operands)")) - (set (attr "cc") - (symbol_ref "compute_a_shift_cc (insn, operands)"))]) - - -;; Split a variable shift into a loop. If the register containing -;; the shift count dies, then we just use that register. - -(define_split - [(set (match_operand 0 "register_operand" "") - (match_operator 2 "nshift_operator" - [(match_dup 0) - (match_operand:QI 1 "register_operand" "")])) - (clobber (match_operand:QI 3 "register_operand" ""))] - "epilogue_completed - && find_regno_note (insn, REG_DEAD, REGNO (operands[1]))" - [(set (cc0) (compare (match_dup 1) (const_int 0))) - (set (pc) - (if_then_else (le (cc0) (const_int 0)) - (label_ref (match_dup 5)) - (pc))) - (match_dup 4) - (parallel - [(set (match_dup 0) - (match_op_dup 2 [(match_dup 0) (const_int 1)])) - (clobber (scratch:QI))]) - (set (match_dup 1) (plus:QI (match_dup 1) (const_int -1))) - (set (cc0) (compare (match_dup 1) (const_int 0))) - (set (pc) - (if_then_else (ne (cc0) (const_int 0)) - (label_ref (match_dup 4)) - (pc))) - (match_dup 5)] - { - operands[4] = gen_label_rtx (); - operands[5] = gen_label_rtx (); - }) - -(define_split - [(set (match_operand 0 "register_operand" "") - (match_operator 2 "nshift_operator" - [(match_dup 0) - (match_operand:QI 1 "register_operand" "")])) - (clobber (match_operand:QI 3 "register_operand" ""))] - "epilogue_completed - && !find_regno_note (insn, REG_DEAD, REGNO (operands[1]))" - [(set (match_dup 3) - (match_dup 1)) - (set (cc0) (compare (match_dup 3) (const_int 0))) - (set (pc) - (if_then_else (le (cc0) (const_int 0)) - (label_ref (match_dup 5)) - (pc))) - (match_dup 4) - (parallel - [(set (match_dup 0) - (match_op_dup 2 [(match_dup 0) (const_int 1)])) - (clobber (scratch:QI))]) - (set (match_dup 3) (plus:QI (match_dup 3) (const_int -1))) - (set (cc0) (compare (match_dup 3) (const_int 0))) - (set (pc) - (if_then_else (ne (cc0) (const_int 0)) - (label_ref (match_dup 4)) - (pc))) - (match_dup 5)] - { - operands[4] = gen_label_rtx (); - operands[5] = gen_label_rtx (); - }) - -;; ---------------------------------------------------------------------- -;; ROTATIONS -;; ---------------------------------------------------------------------- - -(define_expand "rotl3" - [(set (match_operand:QHSI 0 "register_operand" "") - (rotate:QHSI (match_operand:QHSI 1 "register_operand" "") - (match_operand:QI 2 "nonmemory_operand" "")))] - "" - { - if (expand_a_rotate (operands)) - DONE; - }) - -(define_insn "rotl3_1" - [(set (match_operand:QHSI 0 "register_operand" "=r") - (rotate:QHSI (match_operand:QHSI 1 "register_operand" "0") - (match_operand:QI 2 "immediate_operand" "")))] - "" -{ - return output_a_rotate (ROTATE, operands); -} - [(set (attr "length") - (symbol_ref "compute_a_rotate_length (operands)"))]) - -;; ----------------------------------------------------------------- -;; BIT FIELDS -;; ----------------------------------------------------------------- -;; The H8/300 has given 1/8th of its opcode space to bitfield -;; instructions so let's use them as well as we can. - -;; You'll never believe all these patterns perform one basic action -- -;; load a bit from the source, optionally invert the bit, then store it -;; in the destination (which is known to be zero). -;; -;; Combine obviously need some work to better identify this situation and -;; canonicalize the form better. - -;; -;; Inverted loads with a 16bit destination. -;; - -(define_insn "" - [(set (match_operand:HI 0 "register_operand" "=&r") - (zero_extract:HI (xor:HI (match_operand:HI 1 "register_operand" "r") - (match_operand:HI 3 "const_int_operand" "n")) - (const_int 1) - (match_operand:HI 2 "const_int_operand" "n")))] - "(TARGET_H8300SX) - && (1 << INTVAL (operands[2])) == INTVAL (operands[3])" - "sub.w %0,%0\;bild %Z2,%Y1\;bst #0,%X0" - [(set_attr "length" "8")]) - -;; -;; Normal loads with a 32bit destination. -;; - -(define_insn "*extzv_1_r_h8300hs" - [(set (match_operand:SI 0 "register_operand" "=r,r") - (zero_extract:SI (match_operand:SI 1 "register_operand" "?0,r") - (const_int 1) - (match_operand 2 "const_int_operand" "n,n")))] - "INTVAL (operands[2]) < 16" -{ - return output_simode_bld (0, operands); -} - [(set_attr "cc" "set_znv,set_znv") - (set_attr "length" "8,6")]) - -;; -;; Inverted loads with a 32bit destination. -;; - -(define_insn "*extzv_1_r_inv_h8300hs" - [(set (match_operand:SI 0 "register_operand" "=r,r") - (zero_extract:SI (xor:SI (match_operand:SI 1 "register_operand" "?0,r") - (match_operand 3 "const_int_operand" "n,n")) - (const_int 1) - (match_operand 2 "const_int_operand" "n,n")))] - "INTVAL (operands[2]) < 16 - && (1 << INTVAL (operands[2])) == INTVAL (operands[3])" -{ - return output_simode_bld (1, operands); -} - [(set_attr "cc" "set_znv,set_znv") - (set_attr "length" "8,6")]) - -(define_expand "insv" - [(set (zero_extract:HI (match_operand:HI 0 "general_operand" "") - (match_operand:HI 1 "general_operand" "") - (match_operand:HI 2 "general_operand" "")) - (match_operand:HI 3 "general_operand" ""))] - "TARGET_H8300SX" - { - if (GET_CODE (operands[1]) == CONST_INT - && GET_CODE (operands[2]) == CONST_INT - && INTVAL (operands[1]) <= 8 - && INTVAL (operands[2]) >= 0 - && INTVAL (operands[1]) + INTVAL (operands[2]) <= 8 - && memory_operand (operands[0], GET_MODE (operands[0]))) - { - /* If the source operand is zero, it's better to use AND rather - than BFST. Likewise OR if the operand is all ones. */ - if (GET_CODE (operands[3]) == CONST_INT) - { - HOST_WIDE_INT mask = (1 << INTVAL (operands[1])) - 1; - if ((INTVAL (operands[3]) & mask) == 0) - FAIL; - if ((INTVAL (operands[3]) & mask) == mask) - FAIL; - } - if (! bit_memory_operand (operands[0], GET_MODE (operands[0]))) - { - if (!can_create_pseudo_p ()) - FAIL; - operands[0] = replace_equiv_address (operands[0], force_reg (Pmode, - XEXP (operands[0], 0))); - } - operands[3] = gen_lowpart (QImode, operands[3]); - if (! operands[3]) - FAIL; - if (! register_operand (operands[3], QImode)) - { - if (!can_create_pseudo_p ()) - FAIL; - operands[3] = force_reg (QImode, operands[3]); - } - emit_insn (gen_bfst (adjust_address (operands[0], QImode, 0), - operands[3], operands[1], operands[2])); - DONE; - } - FAIL; - }) - -(define_insn "" - [(set (zero_extract:HI (match_operand:HI 0 "register_operand" "+r") - (const_int 1) - (match_operand:HI 1 "immediate_operand" "n")) - (match_operand:HI 2 "register_operand" "r"))] - "" - "bld #0,%R2\;bst %Z1,%Y0 ; i1" - [(set_attr "length" "4")]) - -(define_expand "extzv" - [(set (match_operand:HI 0 "register_operand" "") - (zero_extract:HI (match_operand:HI 1 "bit_operand" "") - (match_operand:HI 2 "general_operand" "") - (match_operand:HI 3 "general_operand" "")))] - "TARGET_H8300SX" - { - if (GET_CODE (operands[2]) == CONST_INT - && GET_CODE (operands[3]) == CONST_INT - && INTVAL (operands[2]) <= 8 - && INTVAL (operands[3]) >= 0 - && INTVAL (operands[2]) + INTVAL (operands[3]) <= 8 - && memory_operand (operands[1], QImode)) - { - rtx temp; - - /* Optimize the case where we're extracting into a paradoxical - subreg. It's only necessary to extend to the inner reg. */ - if (GET_CODE (operands[0]) == SUBREG - && subreg_lowpart_p (operands[0]) - && (GET_MODE_SIZE (GET_MODE (SUBREG_REG (operands[0]))) - < GET_MODE_SIZE (GET_MODE (operands[0]))) - && (GET_MODE_CLASS (GET_MODE (SUBREG_REG (operands[0]))) - == MODE_INT)) - operands[0] = SUBREG_REG (operands[0]); - - if (!can_create_pseudo_p ()) - temp = gen_lowpart (QImode, operands[0]); - else - temp = gen_reg_rtx (QImode); - if (! temp) - FAIL; - if (! bit_memory_operand (operands[1], QImode)) - { - if (!can_create_pseudo_p ()) - FAIL; - operands[1] = replace_equiv_address (operands[1], - force_reg (Pmode, XEXP (operands[1], 0))); - } - emit_insn (gen_bfld (temp, operands[1], operands[2], operands[3])); - convert_move (operands[0], temp, 1); - DONE; - } - FAIL; - }) - -;; BAND, BOR, and BXOR patterns - -(define_insn "" - [(set (match_operand:HI 0 "bit_operand" "=Ur") - (match_operator:HI 4 "bit_operator" - [(zero_extract:HI (match_operand:HI 1 "register_operand" "r") - (const_int 1) - (match_operand:HI 2 "immediate_operand" "n")) - (match_operand:HI 3 "bit_operand" "0")]))] - "" - "bld %Z2,%Y1\;b%c4 #0,%R0\;bst #0,%R0; bl1" - [(set_attr "length" "6")]) - -(define_insn "" - [(set (match_operand:HI 0 "bit_operand" "=Ur") - (match_operator:HI 5 "bit_operator" - [(zero_extract:HI (match_operand:HI 1 "register_operand" "r") - (const_int 1) - (match_operand:HI 2 "immediate_operand" "n")) - (zero_extract:HI (match_operand:HI 3 "register_operand" "r") - (const_int 1) - (match_operand:HI 4 "immediate_operand" "n"))]))] - "" - "bld %Z2,%Y1\;b%c5 %Z4,%Y3\;bst #0,%R0; bl3" - [(set_attr "length" "6")]) - -(define_insn "bfld" - [(set (match_operand:QI 0 "register_operand" "=r") - (zero_extract:QI (match_operand:QI 1 "bit_memory_operand" "WU") - (match_operand:QI 2 "immediate_operand" "n") - (match_operand:QI 3 "immediate_operand" "n")))] - "TARGET_H8300SX && INTVAL (operands[2]) + INTVAL (operands[3]) <= 8" -{ - operands[2] = GEN_INT ((1 << (INTVAL (operands[2]) + INTVAL (operands[3]))) - - (1 << INTVAL (operands[3]))); - return "bfld %2,%1,%R0"; -} - [(set_attr "cc" "none_0hit") - (set_attr "length_table" "bitfield")]) - -(define_insn "bfst" - [(set (zero_extract:QI (match_operand:QI 0 "bit_memory_operand" "+WU") - (match_operand:QI 2 "immediate_operand" "n") - (match_operand:QI 3 "immediate_operand" "n")) - (match_operand:QI 1 "register_operand" "r"))] - "TARGET_H8300SX && INTVAL (operands[2]) + INTVAL (operands[3]) <= 8" -{ - operands[2] = GEN_INT ((1 << (INTVAL (operands[2]) + INTVAL (operands[3]))) - - (1 << INTVAL (operands[3]))); - return "bfst %R1,%2,%0"; -} - [(set_attr "cc" "none_0hit") - (set_attr "length_table" "bitfield")]) - -(define_expand "cstoreqi4" - [(use (match_operator 1 "eqne_operator" - [(match_operand:QI 2 "h8300_dst_operand" "") - (match_operand:QI 3 "h8300_src_operand" "")])) - (clobber (match_operand:HI 0 "register_operand"))] - "TARGET_H8300SX" - { - h8300_expand_store (operands); - DONE; - }) - -(define_expand "cstorehi4" - [(use (match_operator 1 "eqne_operator" - [(match_operand:HI 2 "h8300_dst_operand" "") - (match_operand:HI 3 "h8300_src_operand" "")])) - (clobber (match_operand:HI 0 "register_operand"))] - "TARGET_H8300SX" - { - h8300_expand_store (operands); - DONE; - }) - -(define_expand "cstoresi4" - [(use (match_operator 1 "eqne_operator" - [(match_operand:SI 2 "h8300_dst_operand" "") - (match_operand:SI 3 "h8300_src_operand" "")])) - (clobber (match_operand:HI 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)]))] - "TARGET_H8300SX" - "mulu.w #0,%T0\;b%k1 .Lh8BR%=\;inc.w #1,%T0\\n.Lh8BR%=:" - [(set_attr "cc" "clobber")]) - -(define_insn_and_split "*cmpstz" - [(set (zero_extract:QI (match_operand:QI 0 "bit_memory_operand" "+WU,WU") - (const_int 1) - (match_operand:QI 1 "immediate_operand" "n,n")) - (match_operator:QI 2 "eqne_operator" - [(match_operand 3 "h8300_dst_operand" "r,rQ") - (match_operand 4 "h8300_src_operand" "I,rQi")]))] - "TARGET_H8300SX - && (GET_MODE (operands[3]) == GET_MODE (operands[4]) - || GET_CODE (operands[4]) == CONST_INT) - && GET_MODE_CLASS (GET_MODE (operands[3])) == MODE_INT - && GET_MODE_SIZE (GET_MODE (operands[3])) <= 4" - "#" - "reload_completed" - [(set (cc0) (match_dup 5)) - (set (zero_extract:QI (match_dup 0) (const_int 1) (match_dup 1)) - (match_op_dup:QI 2 [(cc0) (const_int 0)]))] - { - operands[5] = gen_rtx_COMPARE (VOIDmode, operands[3], operands[4]); - } - [(set_attr "cc" "set_znv,compare")]) - -(define_insn "*bstz" - [(set (zero_extract:QI (match_operand:QI 0 "bit_memory_operand" "+WU") - (const_int 1) - (match_operand:QI 1 "immediate_operand" "n")) - (eq:QI (cc0) (const_int 0)))] - "TARGET_H8300SX && reload_completed" - "bstz %1,%0" - [(set_attr "cc" "none_0hit") - (set_attr "length_table" "unary")]) - -(define_insn "*bistz" - [(set (zero_extract:QI (match_operand:QI 0 "bit_memory_operand" "+WU") - (const_int 1) - (match_operand:QI 1 "immediate_operand" "n")) - (ne:QI (cc0) (const_int 0)))] - "TARGET_H8300SX && reload_completed" - "bistz %1,%0" - [(set_attr "cc" "none_0hit") - (set_attr "length_table" "unary")]) - -(define_insn_and_split "*cmpcondbset" - [(set (match_operand:QI 0 "nonimmediate_operand" "=WU,WU") - (if_then_else:QI (match_operator 1 "eqne_operator" - [(match_operand 2 "h8300_dst_operand" "r,rQ") - (match_operand 3 "h8300_src_operand" "I,rQi")]) - (ior:QI (match_operand:QI 4 "bit_memory_operand" "0,0") - (match_operand:QI 5 "single_one_operand" "n,n")) - (match_dup 4)))] - "TARGET_H8300SX" - "#" - "reload_completed" - [(set (cc0) (match_dup 6)) - (set (match_dup 0) - (if_then_else:QI (match_op_dup 1 [(cc0) (const_int 0)]) - (ior:QI (match_dup 4) (match_dup 5)) - (match_dup 4)))] - { - operands[6] = gen_rtx_COMPARE (VOIDmode, operands[2], operands[3]); - } - [(set_attr "cc" "set_znv,compare")]) - -(define_insn "*condbset" - [(set (match_operand:QI 0 "bit_memory_operand" "=WU") - (if_then_else:QI (match_operator:QI 2 "eqne_operator" - [(cc0) (const_int 0)]) - (ior:QI (match_operand:QI 3 "bit_memory_operand" "0") - (match_operand:QI 1 "single_one_operand" "n")) - (match_dup 3)))] - "TARGET_H8300SX && reload_completed" - "bset/%j2\t%V1,%0" - [(set_attr "cc" "none_0hit") - (set_attr "length_table" "logicb")]) - -(define_insn_and_split "*cmpcondbclr" - [(set (match_operand:QI 0 "nonimmediate_operand" "=WU,WU") - (if_then_else:QI (match_operator 1 "eqne_operator" - [(match_operand 2 "h8300_dst_operand" "r,rQ") - (match_operand 3 "h8300_src_operand" "I,rQi")]) - (and:QI (match_operand:QI 4 "bit_memory_operand" "0,0") - (match_operand:QI 5 "single_zero_operand" "n,n")) - (match_dup 4)))] - "TARGET_H8300SX" - "#" - "reload_completed" - [(set (cc0) (match_dup 6)) - (set (match_dup 0) - (if_then_else:QI (match_op_dup 1 [(cc0) (const_int 0)]) - (and:QI (match_dup 4) (match_dup 5)) - (match_dup 4)))] - { - operands[6] = gen_rtx_COMPARE (VOIDmode, operands[2], operands[3]); - } - [(set_attr "cc" "set_znv,compare")]) - -(define_insn "*condbclr" - [(set (match_operand:QI 0 "bit_memory_operand" "=WU") - (if_then_else:QI (match_operator:QI 2 "eqne_operator" - [(cc0) (const_int 0)]) - (and:QI (match_operand:QI 3 "bit_memory_operand" "0") - (match_operand:QI 1 "single_zero_operand" "n")) - (match_dup 3)))] - "TARGET_H8300SX && reload_completed" - "bclr/%j2\t%W1,%0" - [(set_attr "cc" "none_0hit") - (set_attr "length_table" "logicb")]) - -(define_insn_and_split "*cmpcondbsetreg" - [(set (match_operand:QI 0 "nonimmediate_operand" "=WU,WU") - (if_then_else:QI (match_operator 1 "eqne_operator" - [(match_operand 2 "h8300_dst_operand" "r,rQ") - (match_operand 3 "h8300_src_operand" "I,rQi")]) - (ior:QI (match_operand:QI 4 "bit_memory_operand" "0,0") - (ashift:QI (const_int 1) - (match_operand:QI 5 "register_operand" "r,r"))) - (match_dup 4)))] - "TARGET_H8300SX" - "#" - "reload_completed" - [(set (cc0) (match_dup 6)) - (set (match_dup 0) - (if_then_else:QI (match_op_dup 1 [(cc0) (const_int 0)]) - (ior:QI (match_dup 4) - (ashift:QI (const_int 1) - (match_operand:QI 5 "register_operand" "r,r"))) - (match_dup 4)))] - { - operands[6] = gen_rtx_COMPARE (VOIDmode, operands[2], operands[3]); - } - [(set_attr "cc" "set_znv,compare")]) - -(define_insn "*condbsetreg" - [(set (match_operand:QI 0 "bit_memory_operand" "=WU") - (if_then_else:QI (match_operator:QI 2 "eqne_operator" - [(cc0) (const_int 0)]) - (ior:QI (match_operand:QI 3 "bit_memory_operand" "0") - (ashift:QI (const_int 1) - (match_operand:QI 1 "register_operand" "r"))) - (match_dup 3)))] - "TARGET_H8300SX && reload_completed" - "bset/%j2\t%R1,%0" - [(set_attr "cc" "none_0hit") - (set_attr "length_table" "logicb")]) - -(define_insn_and_split "*cmpcondbclrreg" - [(set (match_operand:QI 0 "nonimmediate_operand" "=WU,WU") - (if_then_else:QI (match_operator 1 "eqne_operator" - [(match_operand 2 "h8300_dst_operand" "r,rQ") - (match_operand 3 "h8300_src_operand" "I,rQi")]) - (and:QI (match_operand:QI 4 "bit_memory_operand" "0,0") - (ashift:QI (const_int 1) - (match_operand:QI 5 "register_operand" "r,r"))) - (match_dup 4)))] - "TARGET_H8300SX" - "#" - "reload_completed" - [(set (cc0) (match_dup 6)) - (set (match_dup 0) - (if_then_else:QI (match_op_dup 1 [(cc0) (const_int 0)]) - (and:QI (match_dup 4) - (ashift:QI (const_int 1) - (match_operand:QI 5 "register_operand" "r,r"))) - (match_dup 4)))] - { - operands[6] = gen_rtx_COMPARE (VOIDmode, operands[2], operands[3]); - } - [(set_attr "cc" "set_znv,compare")]) - -(define_insn "*condbclrreg" - [(set (match_operand:QI 0 "bit_memory_operand" "=WU") - (if_then_else:QI (match_operator:QI 2 "eqne_operator" - [(cc0) (const_int 0)]) - (and:QI (match_operand:QI 3 "bit_memory_operand" "0") - (ashift:QI (const_int 1) - (match_operand:QI 1 "register_operand" "r"))) - (match_dup 3)))] - "TARGET_H8300SX && reload_completed" - "bclr/%j2\t%R1,%0" - [(set_attr "cc" "none_0hit") - (set_attr "length_table" "logicb")]) - - -;; ----------------------------------------------------------------- -;; COMBINE PATTERNS -;; ----------------------------------------------------------------- - -;; insv:SI - -(define_insn "*insv_si_1_n" - [(set (zero_extract:SI (match_operand:SI 0 "register_operand" "+r") - (const_int 1) - (match_operand:SI 1 "const_int_operand" "n")) - (match_operand:SI 2 "register_operand" "r"))] - "INTVAL (operands[1]) < 16" - "bld\\t#0,%w2\;bst\\t%Z1,%Y0" - [(set_attr "length" "4")]) - -(define_insn "*insv_si_1_n_lshiftrt" - [(set (zero_extract:SI (match_operand:SI 0 "register_operand" "+r") - (const_int 1) - (match_operand:SI 1 "const_int_operand" "n")) - (lshiftrt:SI (match_operand:SI 2 "register_operand" "r") - (match_operand:SI 3 "const_int_operand" "n")))] - "INTVAL (operands[1]) < 16 && INTVAL (operands[3]) < 16" - "bld\\t%Z3,%Y2\;bst\\t%Z1,%Y0" - [(set_attr "length" "4")]) - -(define_insn "*insv_si_1_n_lshiftrt_16" - [(set (zero_extract:SI (match_operand:SI 0 "register_operand" "+r") - (const_int 1) - (match_operand:SI 1 "const_int_operand" "n")) - (lshiftrt:SI (match_operand:SI 2 "register_operand" "r") - (const_int 16)))] - "INTVAL (operands[1]) < 16" - "rotr.w\\t%e2\;rotl.w\\t%e2\;bst\\t%Z1,%Y0" - [(set_attr "length" "6")]) - -(define_insn "*insv_si_8_8" - [(set (zero_extract:SI (match_operand:SI 0 "register_operand" "+r") - (const_int 8) - (const_int 8)) - (match_operand:SI 1 "register_operand" "r"))] - "" - "mov.b\\t%w1,%x0" - [(set_attr "length" "2")]) - -(define_insn "*insv_si_8_8_lshiftrt_8" - [(set (zero_extract:SI (match_operand:SI 0 "register_operand" "+r") - (const_int 8) - (const_int 8)) - (lshiftrt:SI (match_operand:SI 1 "register_operand" "r") - (const_int 8)))] - "" - "mov.b\\t%x1,%x0" - [(set_attr "length" "2")]) - -;; extzv:SI - -(define_insn "*extzv_8_8" - [(set (match_operand:SI 0 "register_operand" "=r,r") - (zero_extract:SI (match_operand:SI 1 "register_operand" "?0,r") - (const_int 8) - (const_int 8)))] - "" - "@ - mov.b\\t%x1,%w0\;extu.w\\t%f0\;extu.l\\t%S0 - sub.l\\t%S0,%S0\;mov.b\\t%x1,%w0" - [(set_attr "cc" "set_znv,clobber") - (set_attr "length" "6,4")]) - -(define_insn "*extzv_8_16" - [(set (match_operand:SI 0 "register_operand" "=r") - (zero_extract:SI (match_operand:SI 1 "register_operand" "r") - (const_int 8) - (const_int 16)))] - "" - "mov.w\\t%e1,%f0\;extu.w\\t%f0\;extu.l\\t%S0" - [(set_attr "cc" "set_znv") - (set_attr "length" "6")]) - -(define_insn "*extzv_16_8" - [(set (match_operand:SI 0 "register_operand" "=r") - (zero_extract:SI (match_operand:SI 1 "register_operand" "r") - (const_int 16) - (const_int 8))) - (clobber (match_scratch:SI 2 "=&r"))] - "TARGET_H8300H" - "mov.w\\t%e1,%f2\;mov.b\\t%x1,%w0\;mov.b\\t%w2,%x0\;extu.l\\t%S0" - [(set_attr "length" "8") - (set_attr "cc" "set_znv")]) - -;; Extract the exponent of a float. - -(define_insn_and_split "*extzv_8_23" - [(set (match_operand:SI 0 "register_operand" "=r") - (zero_extract:SI (match_operand:SI 1 "register_operand" "0") - (const_int 8) - (const_int 23)))] - "" - "#" - "&& reload_completed" - [(parallel [(set (match_dup 0) - (ashift:SI (match_dup 0) - (const_int 1))) - (clobber (scratch:QI))]) - (parallel [(set (match_dup 0) - (lshiftrt:SI (match_dup 0) - (const_int 24))) - (clobber (scratch:QI))])] - "") - -;; and:SI - -;; ((SImode) HImode) << 15 - -(define_insn_and_split "*twoshifts_l16_r1" - [(set (match_operand:SI 0 "register_operand" "=r") - (and:SI (ashift:SI (match_operand:SI 1 "register_operand" "0") - (const_int 15)) - (const_int 2147450880)))] - "" - "#" - "&& reload_completed" - [(parallel [(set (match_dup 0) - (ashift:SI (match_dup 0) - (const_int 16))) - (clobber (scratch:QI))]) - (parallel [(set (match_dup 0) - (lshiftrt:SI (match_dup 0) - (const_int 1))) - (clobber (scratch:QI))])] - "") - -;; Transform (SImode << B) & 0xffff into (SImode) (HImode << B). - -(define_insn_and_split "*andsi3_ashift_n_lower" - [(set (match_operand:SI 0 "register_operand" "=r,r") - (and:SI (ashift:SI (match_operand:SI 1 "register_operand" "0,0") - (match_operand:QI 2 "const_int_operand" "S,n")) - (match_operand:SI 3 "const_int_operand" "n,n"))) - (clobber (match_scratch:QI 4 "=X,&r"))] - "INTVAL (operands[2]) <= 15 - && UINTVAL (operands[3]) == ((HOST_WIDE_INT_M1U << INTVAL (operands[2])) - & 0xffff)" - "#" - "&& reload_completed" - [(parallel [(set (match_dup 5) - (ashift:HI (match_dup 5) - (match_dup 2))) - (clobber (match_dup 4))]) - (set (match_dup 0) - (zero_extend:SI (match_dup 5)))] - { - operands[5] = gen_rtx_REG (HImode, REGNO (operands[0])); - }) - -;; Accept (A >> 30) & 2 and the like. - -(define_insn "*andsi3_lshiftrt_n_sb" - [(set (match_operand:SI 0 "register_operand" "=r") - (and:SI (lshiftrt:SI (match_operand:SI 1 "register_operand" "0") - (match_operand:SI 2 "const_int_operand" "n")) - (match_operand:SI 3 "single_one_operand" "n")))] - "exact_log2 (INTVAL (operands[3])) < 16 - && INTVAL (operands[2]) + exact_log2 (INTVAL (operands[3])) == 31" -{ - operands[3] = GEN_INT (exact_log2 (INTVAL (operands[3]))); - return "shll.l\\t%S0\;xor.l\\t%S0,%S0\;bst\\t%Z3,%Y0"; -} - [(set_attr "length" "8")]) - -(define_insn_and_split "*andsi3_lshiftrt_9_sb" - [(set (match_operand:SI 0 "register_operand" "=r") - (and:SI (lshiftrt:SI (match_operand:SI 1 "register_operand" "0") - (const_int 9)) - (const_int 4194304)))] - "" - "#" - "&& reload_completed" - [(set (match_dup 0) - (and:SI (lshiftrt:SI (match_dup 0) - (const_int 25)) - (const_int 64))) - (parallel [(set (match_dup 0) - (ashift:SI (match_dup 0) - (const_int 16))) - (clobber (scratch:QI))])] - "") - -;; plus:SI - -(define_insn "*addsi3_upper" - [(set (match_operand:SI 0 "register_operand" "=r") - (plus:SI (mult:SI (match_operand:SI 1 "register_operand" "r") - (const_int 65536)) - (match_operand:SI 2 "register_operand" "0")))] - "" - "add.w\\t%f1,%e0" - [(set_attr "length" "2")]) - -(define_insn "*addsi3_lshiftrt_16_zexthi" - [(set (match_operand:SI 0 "register_operand" "=r") - (plus:SI (lshiftrt:SI (match_operand:SI 1 "register_operand" "r") - (const_int 16)) - (zero_extend:SI (match_operand:HI 2 "register_operand" "0"))))] - "" - "add.w\\t%e1,%f0\;xor.w\\t%e0,%e0\;rotxl.w\\t%e0" - [(set_attr "length" "6")]) - -(define_insn_and_split "*addsi3_and_r_1" - [(set (match_operand:SI 0 "register_operand" "=r") - (plus:SI (and:SI (match_operand:SI 1 "register_operand" "r") - (const_int 1)) - (match_operand:SI 2 "register_operand" "0")))] - "" - "#" - "&& reload_completed" - [(set (cc0) (compare (zero_extract:SI (match_dup 1) - (const_int 1) - (const_int 0)) - (const_int 0))) - (set (pc) - (if_then_else (eq (cc0) - (const_int 0)) - (label_ref (match_dup 3)) - (pc))) - (set (match_dup 2) - (plus:SI (match_dup 2) - (const_int 1))) - (match_dup 3)] - { - operands[3] = gen_label_rtx (); - }) - -(define_insn_and_split "*addsi3_and_not_r_1" - [(set (match_operand:SI 0 "register_operand" "=r") - (plus:SI (and:SI (not:SI (match_operand:SI 1 "register_operand" "r")) - (const_int 1)) - (match_operand:SI 2 "register_operand" "0")))] - "" - "#" - "&& reload_completed" - [(set (cc0) (compare (zero_extract:SI (match_dup 1) - (const_int 1) - (const_int 0)) - (const_int 0))) - (set (pc) - (if_then_else (ne (cc0) - (const_int 0)) - (label_ref (match_dup 3)) - (pc))) - (set (match_dup 2) - (plus:SI (match_dup 2) - (const_int 1))) - (match_dup 3)] - { - operands[3] = gen_label_rtx (); - }) - -;; [ix]or:HI - -(define_insn "*ixorhi3_zext" - [(set (match_operand:HI 0 "register_operand" "=r") - (match_operator:HI 1 "iorxor_operator" - [(zero_extend:HI (match_operand:QI 2 "register_operand" "r")) - (match_operand:HI 3 "register_operand" "0")]))] - "" - "%c1.b\\t%X2,%s0" - [(set_attr "length" "2")]) - -;; [ix]or:SI - -(define_insn "*ixorsi3_zext_qi" - [(set (match_operand:SI 0 "register_operand" "=r") - (match_operator:SI 1 "iorxor_operator" - [(zero_extend:SI (match_operand:QI 2 "register_operand" "r")) - (match_operand:SI 3 "register_operand" "0")]))] - "" - "%c1.b\\t%X2,%w0" - [(set_attr "length" "2")]) - -(define_insn "*ixorsi3_zext_hi" - [(set (match_operand:SI 0 "register_operand" "=r") - (match_operator:SI 1 "iorxor_operator" - [(zero_extend:SI (match_operand:HI 2 "register_operand" "r")) - (match_operand:SI 3 "register_operand" "0")]))] - "" - "%c1.w\\t%T2,%f0" - [(set_attr "length" "2")]) - -(define_insn "*ixorsi3_ashift_16" - [(set (match_operand:SI 0 "register_operand" "=r") - (match_operator:SI 1 "iorxor_operator" - [(ashift:SI (match_operand:SI 2 "register_operand" "r") - (const_int 16)) - (match_operand:SI 3 "register_operand" "0")]))] - "" - "%c1.w\\t%f2,%e0" - [(set_attr "length" "2")]) - -(define_insn "*ixorsi3_lshiftrt_16" - [(set (match_operand:SI 0 "register_operand" "=r") - (match_operator:SI 1 "iorxor_operator" - [(lshiftrt:SI (match_operand:SI 2 "register_operand" "r") - (const_int 16)) - (match_operand:SI 3 "register_operand" "0")]))] - "" - "%c1.w\\t%e2,%f0" - [(set_attr "length" "2")]) - -;; ior:HI - -(define_insn "*iorhi3_ashift_8" - [(set (match_operand:HI 0 "register_operand" "=r") - (ior:HI (ashift:HI (match_operand:HI 1 "register_operand" "r") - (const_int 8)) - (match_operand:HI 2 "register_operand" "0")))] - "" - "or.b\\t%s1,%t0" - [(set_attr "length" "2")]) - -(define_insn "*iorhi3_lshiftrt_8" - [(set (match_operand:HI 0 "register_operand" "=r") - (ior:HI (lshiftrt:HI (match_operand:HI 1 "register_operand" "r") - (const_int 8)) - (match_operand:HI 2 "register_operand" "0")))] - "" - "or.b\\t%t1,%s0" - [(set_attr "length" "2")]) - -(define_insn "*iorhi3_two_qi" - [(set (match_operand:HI 0 "register_operand" "=r") - (ior:HI (zero_extend:HI (match_operand:QI 1 "register_operand" "0")) - (ashift:HI (match_operand:HI 2 "register_operand" "r") - (const_int 8))))] - "" - "mov.b\\t%s2,%t0" - [(set_attr "length" "2")]) - -(define_insn "*iorhi3_two_qi_mem" - [(set (match_operand:HI 0 "register_operand" "=&r") - (ior:HI (zero_extend:HI (match_operand:QI 1 "memory_operand" "m")) - (ashift:HI (subreg:HI (match_operand:QI 2 "memory_operand" "m") 0) - (const_int 8))))] - "" - "mov.b\\t%X2,%t0\;mov.b\\t%X1,%s0" - [(set_attr "length" "16")]) - -(define_split - [(set (match_operand:HI 0 "register_operand" "") - (ior:HI (zero_extend:HI (match_operand:QI 1 "memory_operand" "")) - (ashift:HI (subreg:HI (match_operand:QI 2 "memory_operand" "") 0) - (const_int 8))))] - "reload_completed - && byte_accesses_mergeable_p (XEXP (operands[2], 0), XEXP (operands[1], 0))" - [(set (match_dup 0) - (match_dup 3))] - { - operands[3] = gen_rtx_MEM (HImode, XEXP (operands[2], 0)); - }) - -;; ior:SI - -(define_insn "*iorsi3_two_hi" - [(set (match_operand:SI 0 "register_operand" "=r") - (ior:SI (zero_extend:SI (match_operand:HI 1 "register_operand" "0")) - (ashift:SI (match_operand:SI 2 "register_operand" "r") - (const_int 16))))] - "" - "mov.w\\t%f2,%e0" - [(set_attr "length" "2")]) - -(define_insn_and_split "*iorsi3_two_qi_zext" - [(set (match_operand:SI 0 "register_operand" "=&r") - (ior:SI (zero_extend:SI (match_operand:QI 1 "memory_operand" "m")) - (and:SI (ashift:SI (subreg:SI (match_operand:QI 2 "memory_operand" "m") 0) - (const_int 8)) - (const_int 65280))))] - "" - "#" - "&& reload_completed" - [(set (match_dup 3) - (ior:HI (zero_extend:HI (match_dup 1)) - (ashift:HI (subreg:HI (match_dup 2) 0) - (const_int 8)))) - (set (match_dup 0) - (zero_extend:SI (match_dup 3)))] - { - operands[3] = gen_rtx_REG (HImode, REGNO (operands[0])); - }) - -(define_insn "*iorsi3_e2f" - [(set (match_operand:SI 0 "register_operand" "=r") - (ior:SI (and:SI (match_operand:SI 1 "register_operand" "0") - (const_int -65536)) - (lshiftrt:SI (match_operand:SI 2 "register_operand" "r") - (const_int 16))))] - "" - "mov.w\\t%e2,%f0" - [(set_attr "length" "2")]) - -(define_insn_and_split "*iorsi3_two_qi_sext" - [(set (match_operand:SI 0 "register_operand" "=r") - (ior:SI (zero_extend:SI (match_operand:QI 1 "register_operand" "0")) - (ashift:SI (sign_extend:SI (match_operand:QI 2 "register_operand" "r")) - (const_int 8))))] - "" - "#" - "&& reload_completed" - [(set (match_dup 3) - (ior:HI (zero_extend:HI (match_dup 1)) - (ashift:HI (match_dup 4) - (const_int 8)))) - (set (match_dup 0) - (sign_extend:SI (match_dup 3)))] - { - operands[3] = gen_rtx_REG (HImode, REGNO (operands[0])); - operands[4] = gen_rtx_REG (HImode, REGNO (operands[2])); - }) - -(define_insn "*iorsi3_w" - [(set (match_operand:SI 0 "register_operand" "=r,&r") - (ior:SI (and:SI (match_operand:SI 1 "register_operand" "0,0") - (const_int -256)) - (zero_extend:SI (match_operand:QI 2 "general_operand_src" "r,g>"))))] - "" - "mov.b\\t%X2,%w0" - [(set_attr "length" "2,8")]) - -(define_insn "*iorsi3_ashift_31" - [(set (match_operand:SI 0 "register_operand" "=&r") - (ior:SI (ashift:SI (match_operand:SI 1 "register_operand" "r") - (const_int 31)) - (match_operand:SI 2 "register_operand" "0")))] - "" - "rotxl.l\\t%S0\;bor\\t#0,%w1\;rotxr.l\\t%S0" - [(set_attr "length" "6") - (set_attr "cc" "set_znv")]) - -(define_insn "*iorsi3_and_ashift" - [(set (match_operand:SI 0 "register_operand" "=r") - (ior:SI (and:SI (ashift:SI (match_operand:SI 1 "register_operand" "r") - (match_operand:SI 2 "const_int_operand" "n")) - (match_operand:SI 3 "single_one_operand" "n")) - (match_operand:SI 4 "register_operand" "0")))] - "(INTVAL (operands[3]) & ~0xffff) == 0" -{ - rtx srcpos = GEN_INT (exact_log2 (INTVAL (operands[3])) - - INTVAL (operands[2])); - rtx dstpos = GEN_INT (exact_log2 (INTVAL (operands[3]))); - operands[2] = srcpos; - operands[3] = dstpos; - return "bld\\t%Z2,%Y1\;bor\\t%Z3,%Y0\;bst\\t%Z3,%Y0"; -} - [(set_attr "length" "6")]) - -(define_insn "*iorsi3_and_lshiftrt" - [(set (match_operand:SI 0 "register_operand" "=r") - (ior:SI (and:SI (lshiftrt:SI (match_operand:SI 1 "register_operand" "r") - (match_operand:SI 2 "const_int_operand" "n")) - (match_operand:SI 3 "single_one_operand" "n")) - (match_operand:SI 4 "register_operand" "0")))] - "((INTVAL (operands[3]) << INTVAL (operands[2])) & ~0xffff) == 0" -{ - rtx srcpos = GEN_INT (exact_log2 (INTVAL (operands[3])) - + INTVAL (operands[2])); - rtx dstpos = GEN_INT (exact_log2 (INTVAL (operands[3]))); - operands[2] = srcpos; - operands[3] = dstpos; - return "bld\\t%Z2,%Y1\;bor\\t%Z3,%Y0\;bst\\t%Z3,%Y0"; -} - [(set_attr "length" "6")]) - -(define_insn "*iorsi3_zero_extract" - [(set (match_operand:SI 0 "register_operand" "=r") - (ior:SI (zero_extract:SI (match_operand:SI 1 "register_operand" "r") - (const_int 1) - (match_operand:SI 2 "const_int_operand" "n")) - (match_operand:SI 3 "register_operand" "0")))] - "INTVAL (operands[2]) < 16" - "bld\\t%Z2,%Y1\;bor\\t#0,%w0\;bst\\t#0,%w0" - [(set_attr "length" "6")]) - -(define_insn "*iorsi3_and_lshiftrt_n_sb" - [(set (match_operand:SI 0 "register_operand" "=r") - (ior:SI (and:SI (lshiftrt:SI (match_operand:SI 1 "register_operand" "r") - (const_int 30)) - (const_int 2)) - (match_operand:SI 2 "register_operand" "0")))] - "" - "rotl.l\\t%S1\;rotr.l\\t%S1\;bor\\t#1,%w0\;bst\\t#1,%w0" - [(set_attr "length" "8")]) - -(define_insn "*iorsi3_and_lshiftrt_9_sb" - [(set (match_operand:SI 0 "register_operand" "=r") - (ior:SI (and:SI (lshiftrt:SI (match_operand:SI 1 "register_operand" "r") - (const_int 9)) - (const_int 4194304)) - (match_operand:SI 2 "register_operand" "0"))) - (clobber (match_scratch:HI 3 "=&r"))] - "" -{ - if (find_regno_note (insn, REG_DEAD, REGNO (operands[1]))) - return "shll.l\\t%S1\;xor.w\\t%T3,%T3\;bst\\t#6,%s3\;or.w\\t%T3,%e0"; - else - return "rotl.l\\t%S1\;rotr.l\\t%S1\;xor.w\\t%T3,%T3\;bst\\t#6,%s3\;or.w\\t%T3,%e0"; -} - [(set_attr "length" "10")]) - -;; Used to OR the exponent of a float. - -(define_insn "*iorsi3_shift" - [(set (match_operand:SI 0 "register_operand" "=r") - (ior:SI (ashift:SI (match_operand:SI 1 "register_operand" "r") - (const_int 23)) - (match_operand:SI 2 "register_operand" "0"))) - (clobber (match_scratch:SI 3 "=&r"))] - "" - "#") - -(define_split - [(set (match_operand:SI 0 "register_operand" "") - (ior:SI (ashift:SI (match_operand:SI 1 "register_operand" "") - (const_int 23)) - (match_dup 0))) - (clobber (match_operand:SI 2 "register_operand" ""))] - "epilogue_completed - && find_regno_note (insn, REG_DEAD, REGNO (operands[1])) - && REGNO (operands[0]) != REGNO (operands[1])" - [(parallel [(set (match_dup 3) - (ashift:HI (match_dup 3) - (const_int 7))) - (clobber (scratch:QI))]) - (set (match_dup 0) - (ior:SI (ashift:SI (match_dup 1) - (const_int 16)) - (match_dup 0)))] - { - operands[3] = gen_rtx_REG (HImode, REGNO (operands[1])); - }) - -(define_split - [(set (match_operand:SI 0 "register_operand" "") - (ior:SI (ashift:SI (match_operand:SI 1 "register_operand" "") - (const_int 23)) - (match_dup 0))) - (clobber (match_operand:SI 2 "register_operand" ""))] - "epilogue_completed - && !(find_regno_note (insn, REG_DEAD, REGNO (operands[1])) - && REGNO (operands[0]) != REGNO (operands[1]))" - [(set (match_dup 2) - (match_dup 1)) - (parallel [(set (match_dup 3) - (ashift:HI (match_dup 3) - (const_int 7))) - (clobber (scratch:QI))]) - (set (match_dup 0) - (ior:SI (ashift:SI (match_dup 2) - (const_int 16)) - (match_dup 0)))] - { - operands[3] = gen_rtx_REG (HImode, REGNO (operands[2])); - }) - -(define_insn "*iorsi2_and_1_lshiftrt_1" - [(set (match_operand:SI 0 "register_operand" "=r") - (ior:SI (and:SI (match_operand:SI 1 "register_operand" "0") - (const_int 1)) - (lshiftrt:SI (match_dup 1) - (const_int 1))))] - "" - "shlr.l\\t%S0\;bor\\t#0,%w0\;bst\\t#0,%w0" - [(set_attr "length" "6")]) - -(define_insn_and_split "*iorsi3_ashift_16_ashift_24" - [(set (match_operand:SI 0 "register_operand" "=r") - (ior:SI (ashift:SI (match_operand:SI 1 "register_operand" "0") - (const_int 16)) - (ashift:SI (match_operand:SI 2 "register_operand" "r") - (const_int 24))))] - "" - "#" - "&& reload_completed" - [(set (match_dup 3) - (ior:HI (ashift:HI (match_dup 4) - (const_int 8)) - (match_dup 3))) - (parallel [(set (match_dup 0) - (ashift:SI (match_dup 0) - (const_int 16))) - (clobber (scratch:QI))])] - { - operands[3] = gen_rtx_REG (HImode, REGNO (operands[0])); - operands[4] = gen_rtx_REG (HImode, REGNO (operands[2])); - }) - -(define_insn_and_split "*iorsi3_ashift_16_ashift_24_mem" - [(set (match_operand:SI 0 "register_operand" "=&r") - (ior:SI (and:SI (ashift:SI (subreg:SI (match_operand:QI 1 "memory_operand" "m") 0) - (const_int 16)) - (const_int 16711680)) - (ashift:SI (subreg:SI (match_operand:QI 2 "memory_operand" "m") 0) - (const_int 24))))] - "" - "#" - "&& reload_completed" - [(set (match_dup 3) - (ior:HI (zero_extend:HI (match_dup 1)) - (ashift:HI (subreg:HI (match_dup 2) 0) - (const_int 8)))) - (parallel [(set (match_dup 0) - (ashift:SI (match_dup 0) - (const_int 16))) - (clobber (scratch:QI))])] - { - operands[3] = gen_rtx_REG (HImode, REGNO (operands[0])); - }) - -;; Used to add the exponent of a float. - -(define_insn "*addsi3_shift" - [(set (match_operand:SI 0 "register_operand" "=r") - (plus:SI (mult:SI (match_operand:SI 1 "register_operand" "r") - (const_int 8388608)) - (match_operand:SI 2 "register_operand" "0"))) - (clobber (match_scratch:SI 3 "=&r"))] - "" - "#") - -(define_split - [(set (match_operand:SI 0 "register_operand" "") - (plus:SI (mult:SI (match_operand:SI 1 "register_operand" "") - (const_int 8388608)) - (match_dup 0))) - (clobber (match_operand:SI 2 "register_operand" ""))] - "epilogue_completed - && find_regno_note (insn, REG_DEAD, REGNO (operands[1])) - && REGNO (operands[0]) != REGNO (operands[1])" - [(parallel [(set (match_dup 3) - (ashift:HI (match_dup 3) - (const_int 7))) - (clobber (scratch:QI))]) - (set (match_dup 0) - (plus:SI (mult:SI (match_dup 1) - (const_int 65536)) - (match_dup 0)))] - { - operands[3] = gen_rtx_REG (HImode, REGNO (operands[1])); - }) - -(define_split - [(set (match_operand:SI 0 "register_operand" "") - (plus:SI (mult:SI (match_operand:SI 1 "register_operand" "") - (const_int 8388608)) - (match_dup 0))) - (clobber (match_operand:SI 2 "register_operand" ""))] - "epilogue_completed - && !(find_regno_note (insn, REG_DEAD, REGNO (operands[1])) - && REGNO (operands[0]) != REGNO (operands[1]))" - [(set (match_dup 2) - (match_dup 1)) - (parallel [(set (match_dup 3) - (ashift:HI (match_dup 3) - (const_int 7))) - (clobber (scratch:QI))]) - (set (match_dup 0) - (plus:SI (mult:SI (match_dup 2) - (const_int 65536)) - (match_dup 0)))] - { - operands[3] = gen_rtx_REG (HImode, REGNO (operands[2])); - }) - -;; ashift:SI - -(define_insn_and_split "*ashiftsi_sextqi_7" - [(set (match_operand:SI 0 "register_operand" "=r") - (ashift:SI (sign_extend:SI (match_operand:QI 1 "register_operand" "0")) - (const_int 7)))] - "" - "#" - "&& reload_completed" - [(parallel [(set (match_dup 2) - (ashift:HI (match_dup 2) - (const_int 8))) - (clobber (scratch:QI))]) - (set (match_dup 0) - (sign_extend:SI (match_dup 2))) - (parallel [(set (match_dup 0) - (ashiftrt:SI (match_dup 0) - (const_int 1))) - (clobber (scratch:QI))])] - { - operands[2] = gen_rtx_REG (HImode, REGNO (operands[0])); - }) - -;; Storing a part of HImode to QImode. - -(define_insn "" - [(set (match_operand:QI 0 "general_operand_dst" "=rm<") - (subreg:QI (lshiftrt:HI (match_operand:HI 1 "register_operand" "r") - (const_int 8)) 1))] - "" - "mov.b\\t%t1,%R0" - [(set_attr "cc" "set_znv") - (set_attr "length" "8")]) - -;; Storing a part of SImode to QImode. - -(define_insn "" - [(set (match_operand:QI 0 "general_operand_dst" "=rm<") - (subreg:QI (lshiftrt:SI (match_operand:SI 1 "register_operand" "r") - (const_int 8)) 3))] - "" - "mov.b\\t%x1,%R0" - [(set_attr "cc" "set_znv") - (set_attr "length" "8")]) - -(define_insn "" - [(set (match_operand:QI 0 "general_operand_dst" "=rm<") - (subreg:QI (lshiftrt:SI (match_operand:SI 1 "register_operand" "r") - (const_int 16)) 3)) - (clobber (match_scratch:SI 2 "=&r"))] - "" - "mov.w\\t%e1,%f2\;mov.b\\t%w2,%R0" - [(set_attr "cc" "set_znv") - (set_attr "length" "10")]) - -(define_insn "" - [(set (match_operand:QI 0 "general_operand_dst" "=rm<") - (subreg:QI (lshiftrt:SI (match_operand:SI 1 "register_operand" "r") - (const_int 24)) 3)) - (clobber (match_scratch:SI 2 "=&r"))] - "" - "mov.w\\t%e1,%f2\;mov.b\\t%x2,%R0" - [(set_attr "cc" "set_znv") - (set_attr "length" "10")]) - -(define_insn_and_split "" - [(set (pc) - (if_then_else (eq (zero_extract:SI (subreg:SI (match_operand:QI 0 "register_operand" "") 0) - (const_int 1) - (const_int 7)) - (const_int 0)) - (label_ref (match_operand 1 "" "")) - (pc)))] - "" - "#" - "" - [(set (cc0) (compare (match_dup 0) - (const_int 0))) - (set (pc) - (if_then_else (ge (cc0) - (const_int 0)) - (label_ref (match_dup 1)) - (pc)))] - "") - -(define_insn_and_split "" - [(set (pc) - (if_then_else (ne (zero_extract:SI (subreg:SI (match_operand:QI 0 "register_operand" "") 0) - (const_int 1) - (const_int 7)) - (const_int 0)) - (label_ref (match_operand 1 "" "")) - (pc)))] - "" - "#" - "" - [(set (cc0) (compare (match_dup 0) - (const_int 0))) - (set (pc) - (if_then_else (lt (cc0) - (const_int 0)) - (label_ref (match_dup 1)) - (pc)))] - "") - +(include "testcompare.md") +(include "addsub.md") +(include "multiply.md") +(include "divmod.md") +(include "logical.md") +(include "other.md") +(include "jumpcall.md") +(include "proepi.md") +(include "extensions.md") +(include "shiftrotate.md") +(include "bitfield.md") +(include "combiner.md") (include "peepholes.md") diff --git a/gcc/config/h8300/jumpcall.md b/gcc/config/h8300/jumpcall.md new file mode 100644 index 00000000000..4c0a5ccf8af --- /dev/null +++ b/gcc/config/h8300/jumpcall.md @@ -0,0 +1,306 @@ +;; ---------------------------------------------------------------------- +;; JUMP INSTRUCTIONS +;; ---------------------------------------------------------------------- + +;; Conditional jump instructions + +(define_expand "cbranchqi4" + [(use (match_operator 0 "ordered_comparison_operator" + [(match_operand:QI 1 "h8300_dst_operand" "") + (match_operand:QI 2 "h8300_src_operand" "")])) + (use (match_operand 3 ""))] + "" + { + h8300_expand_branch (operands); + DONE; + }) + +(define_expand "cbranchhi4" + [(use (match_operator 0 "ordered_comparison_operator" + [(match_operand:HI 1 "h8300_dst_operand" "") + (match_operand:HI 2 "h8300_src_operand" "")])) + (use (match_operand 3 ""))] + "" + { + h8300_expand_branch (operands); + DONE; + }) + +(define_expand "cbranchsi4" + [(use (match_operator 0 "ordered_comparison_operator" + [(match_operand:SI 1 "h8300_dst_operand" "") + (match_operand:SI 2 "h8300_src_operand" "")])) + (use (match_operand 3 ""))] + "" + { + h8300_expand_branch (operands); + DONE; + }) + +(define_insn "branch_true" + [(set (pc) + (if_then_else (match_operator 1 "comparison_operator" + [(cc0) (const_int 0)]) + (label_ref (match_operand 0 "" "")) + (pc)))] + "" +{ + if ((cc_status.flags & CC_OVERFLOW_UNUSABLE) != 0 + && (GET_CODE (operands[1]) == GT + || GET_CODE (operands[1]) == GE + || GET_CODE (operands[1]) == LE + || GET_CODE (operands[1]) == LT)) + { + cc_status.flags &= ~CC_OVERFLOW_UNUSABLE; + return 0; + } + + if (get_attr_length (insn) == 2) + return "b%j1 %l0"; + else if (get_attr_length (insn) == 4) + return "b%j1 %l0:16"; + else + return "b%k1 .Lh8BR%=\;jmp @%l0\\n.Lh8BR%=:"; +} + [(set_attr "type" "branch") + (set_attr "cc" "none")]) + +(define_insn "branch_false" + [(set (pc) + (if_then_else (match_operator 1 "comparison_operator" + [(cc0) (const_int 0)]) + (pc) + (label_ref (match_operand 0 "" ""))))] + "" +{ + if ((cc_status.flags & CC_OVERFLOW_UNUSABLE) != 0 + && (GET_CODE (operands[1]) == GT + || GET_CODE (operands[1]) == GE + || GET_CODE (operands[1]) == LE + || GET_CODE (operands[1]) == LT)) + { + cc_status.flags &= ~CC_OVERFLOW_UNUSABLE; + return 0; + } + + if (get_attr_length (insn) == 2) + return "b%k1 %l0"; + else if (get_attr_length (insn) == 4) + return "b%k1 %l0:16"; + else + return "b%j1 .Lh8BR%=\;jmp @%l0\\n.Lh8BR%=:"; +} + [(set_attr "type" "branch") + (set_attr "cc" "none")]) + +(define_insn "*brabc" + [(set (pc) + (if_then_else (eq (zero_extract (match_operand:QI 1 "bit_memory_operand" "WU") + (const_int 1) + (match_operand:QI 2 "immediate_operand" "n")) + (const_int 0)) + (label_ref (match_operand 0 "" "")) + (pc)))] + "TARGET_H8300SX" +{ + switch (get_attr_length (insn) + - h8300_insn_length_from_table (insn, operands)) + { + case 2: + return "bra/bc %2,%R1,%l0"; + case 4: + return "bra/bc %2,%R1,%l0:16"; + default: + return "bra/bs %2,%R1,.Lh8BR%=\;jmp @%l0\\n.Lh8BR%=:"; + } +} + [(set_attr "type" "bitbranch") + (set_attr "length_table" "bitbranch") + (set_attr "cc" "none")]) + +(define_insn "*brabs" + [(set (pc) + (if_then_else (ne (zero_extract (match_operand:QI 1 "bit_memory_operand" "WU") + (const_int 1) + (match_operand:QI 2 "immediate_operand" "n")) + (const_int 0)) + (label_ref (match_operand 0 "" "")) + (pc)))] + "TARGET_H8300SX" +{ + switch (get_attr_length (insn) + - h8300_insn_length_from_table (insn, operands)) + { + case 2: + return "bra/bs %2,%R1,%l0"; + case 4: + return "bra/bs %2,%R1,%l0:16"; + default: + return "bra/bc %2,%R1,.Lh8BR%=\;jmp @%l0\\n.Lh8BR%=:"; + } +} + [(set_attr "type" "bitbranch") + (set_attr "length_table" "bitbranch") + (set_attr "cc" "none")]) + +;; Unconditional and other jump instructions. + +(define_insn "jump" + [(set (pc) + (label_ref (match_operand 0 "" "")))] + "" +{ + if (final_sequence != 0) + { + if (get_attr_length (insn) == 2) + return "bra/s %l0"; + else + { + /* The branch isn't short enough to use bra/s. Output the + branch and delay slot in their normal order. + + If this is a backward branch, it will now be branching two + bytes further than previously thought. The length-based + test for bra vs. jump is very conservative though, so the + branch will still be within range. */ + rtx_sequence *seq; + int seen; + + seq = final_sequence; + final_sequence = 0; + final_scan_insn (seq->insn (1), asm_out_file, optimize, 1, & seen); + final_scan_insn (seq->insn (0), asm_out_file, optimize, 1, & seen); + seq->insn (1)->set_deleted (); + return ""; + } + } + else if (get_attr_length (insn) == 2) + return "bra %l0"; + else if (get_attr_length (insn) == 4) + return "bra %l0:16"; + else + return "jmp @%l0"; +} + [(set_attr "type" "branch") + (set (attr "delay_slot") + (if_then_else (match_test "TARGET_H8300SX") + (const_string "jump") + (const_string "none"))) + (set_attr "cc" "none")]) + +;; This is a define expand, because pointers may be either 16 or 32 bits. + +(define_expand "tablejump" + [(parallel [(set (pc) (match_operand 0 "register_operand" "")) + (use (label_ref (match_operand 1 "" "")))])] + "" + "") + +(define_insn "tablejump" + [(set (pc) (match_operand:P 0 "register_operand" "r")) + (use (label_ref (match_operand 1 "" "")))] + "" + { + if (mode == E_HImode) + return "jmp @%0"; + if (mode == E_SImode) + return "jmp @%S0"; + abort (); + } + [(set_attr "cc" "none") + (set_attr "length" "2")]) + +;; This is a define expand, because pointers may be either 16 or 32 bits. + +(define_expand "indirect_jump" + [(set (pc) (match_operand 0 "jump_address_operand" ""))] + "" + "") + +(define_insn "*indirect_jump_" + [(set (pc) (match_operand:P 0 "jump_address_operand" "Vr"))] + "" + { + if (mode == E_HImode) + return "jmp @%0"; + if (mode == E_SImode) + return "jmp @%S0"; + abort (); + } + [(set_attr "cc" "none") + (set_attr "length" "2")]) + +;; Call subroutine with no return value. + +;; ??? Even though we use HImode here, this works on the H8/300H and H8S. + +(define_expand "call" + [(call (match_operand:QI 0 "call_expander_operand" "") + (match_operand 1 "general_operand" ""))] + "" + { + if (!register_operand (XEXP (operands[0], 0), Pmode) + && GET_CODE (XEXP (operands[0], 0)) != SYMBOL_REF) + XEXP (operands[0], 0) = force_reg (Pmode, XEXP (operands[0], 0)); + }) + +(define_insn "call_insn_" + [(call (mem:QI (match_operand 0 "call_insn_operand" "Cr")) + (match_operand:P 1 "general_operand" "g"))] + "" +{ + rtx xoperands[1]; + xoperands[0] = gen_rtx_MEM (QImode, operands[0]); + gcc_assert (GET_MODE (operands[0]) == Pmode); + if (GET_CODE (XEXP (xoperands[0], 0)) == SYMBOL_REF + && (SYMBOL_REF_FLAGS (XEXP (xoperands[0], 0)) & SYMBOL_FLAG_FUNCVEC_FUNCTION)) + output_asm_insn ("jsr\\t@%0:8", xoperands); + else + output_asm_insn ("jsr\\t%0", xoperands); + return ""; +} + [(set_attr "type" "call") + (set (attr "length") + (if_then_else (match_operand:QI 0 "small_call_insn_operand" "") + (const_int 2) + (const_int 4)))]) + +;; Call subroutine, returning value in operand 0 +;; (which must be a hard register). + +;; ??? Even though we use HImode here, this works on the H8/300H and H8S. + +(define_expand "call_value" + [(set (match_operand 0 "" "") + (call (match_operand:QI 1 "call_expander_operand" "") + (match_operand 2 "general_operand" "")))] + "" + { + if (!register_operand (XEXP (operands[1], 0), Pmode) + && GET_CODE (XEXP (operands[1], 0)) != SYMBOL_REF) + XEXP (operands[1], 0) = force_reg (Pmode, XEXP (operands[1], 0)); + }) + +(define_insn "call_value_insn_" + [(set (match_operand 0 "" "=r") + (call (mem:QI (match_operand 1 "call_insn_operand" "Cr")) + (match_operand:P 2 "general_operand" "g")))] + "" +{ + rtx xoperands[2]; + gcc_assert (GET_MODE (operands[1]) == Pmode); + xoperands[0] = operands[0]; + xoperands[1] = gen_rtx_MEM (QImode, operands[1]); + if (GET_CODE (XEXP (xoperands[1], 0)) == SYMBOL_REF + && (SYMBOL_REF_FLAGS (XEXP (xoperands[1], 0)) & SYMBOL_FLAG_FUNCVEC_FUNCTION)) + output_asm_insn ("jsr\\t@%1:8", xoperands); + else + output_asm_insn ("jsr\\t%1", xoperands); + return ""; +} + [(set_attr "type" "call") + (set (attr "length") + (if_then_else (match_operand:QI 0 "small_call_insn_operand" "") + (const_int 2) + (const_int 4)))]) + diff --git a/gcc/config/h8300/logical.md b/gcc/config/h8300/logical.md new file mode 100644 index 00000000000..9dd863cdd8c --- /dev/null +++ b/gcc/config/h8300/logical.md @@ -0,0 +1,204 @@ +;; ---------------------------------------------------------------------- +;; AND INSTRUCTIONS +;; ---------------------------------------------------------------------- + +(define_insn "bclrqi_msx" + [(set (match_operand:QI 0 "bit_register_indirect_operand" "=WU") + (and:QI (match_operand:QI 1 "bit_register_indirect_operand" "%0") + (match_operand:QI 2 "single_zero_operand" "Y0")))] + "TARGET_H8300SX && rtx_equal_p (operands[0], operands[1])" + "bclr\\t%W2,%0" + [(set_attr "length" "8")]) + +(define_split + [(set (match_operand:HI 0 "bit_register_indirect_operand") + (and:HI (match_operand:HI 1 "bit_register_indirect_operand") + (match_operand:HI 2 "single_zero_operand")))] + "TARGET_H8300SX" + [(set (match_dup 0) + (and:QI (match_dup 1) + (match_dup 2)))] + { + if (abs (INTVAL (operands[2])) > 0xFF) + { + operands[0] = adjust_address (operands[0], QImode, 0); + operands[1] = adjust_address (operands[1], QImode, 0); + operands[2] = GEN_INT ((INTVAL (operands[2])) >> 8); + } + else + { + operands[0] = adjust_address (operands[0], QImode, 1); + operands[1] = adjust_address (operands[1], QImode, 1); + } + }) + +(define_insn "bclrhi_msx" + [(set (match_operand:HI 0 "bit_register_indirect_operand" "=m") + (and:HI (match_operand:HI 1 "bit_register_indirect_operand" "%0") + (match_operand:HI 2 "single_zero_operand" "Y0")))] + "TARGET_H8300SX" + "bclr\\t%W2,%0" + [(set_attr "length" "8")]) + +(define_insn "*andqi3_2" + [(set (match_operand:QI 0 "bit_operand" "=U,rQ,r") + (and:QI (match_operand:QI 1 "bit_operand" "%0,0,WU") + (match_operand:QI 2 "h8300_src_operand" "Y0,rQi,IP1>X")))] + "TARGET_H8300SX" + "@ + bclr\\t %W2,%R0 + and %X2,%X0 + bfld %2,%1,%R0" + [(set_attr "length" "8,*,8") + (set_attr "length_table" "*,logicb,*") + (set_attr "cc" "none_0hit,set_znv,none_0hit")]) + +(define_insn "andqi3_1" + [(set (match_operand:QI 0 "bit_operand" "=U,r") + (and:QI (match_operand:QI 1 "bit_operand" "%0,0") + (match_operand:QI 2 "h8300_src_operand" "Y0,rn")))] + "register_operand (operands[0], QImode) + || single_zero_operand (operands[2], QImode)" + "@ + bclr %W2,%R0 + and %X2,%X0" + [(set_attr "length" "2,8") + (set_attr "cc" "none_0hit,set_znv")]) + +(define_expand "and3" + [(set (match_operand:QHSI 0 "register_operand" "") + (and:QHSI (match_operand:QHSI 1 "register_operand" "") + (match_operand:QHSI 2 "h8300_src_operand" "")))] + "" + "") + +(define_insn "*andor3" + [(set (match_operand:QHSI 0 "register_operand" "=r") + (ior:QHSI (and:QHSI (match_operand:QHSI 2 "register_operand" "r") + (match_operand:QHSI 3 "single_one_operand" "n")) + (match_operand:QHSI 1 "register_operand" "0")))] + "(mode == QImode + || mode == HImode + || (mode == SImode + && (INTVAL (operands[3]) & 0xffff) != 0))" + { + if (mode == QImode) + return "bld\\t%V3,%X2\;bor\\t%V3,%X0\;bst\\t%V3,%X0"; + + if (mode == HImode) + { + operands[3] = GEN_INT (INTVAL (operands[3]) & 0xffff); + if (INTVAL (operands[3]) > 128) + { + operands[3] = GEN_INT (INTVAL (operands[3]) >> 8); + return "bld\\t%V3,%t2\;bor\\t%V3,%t0\;bst\\t%V3,%t0"; + } + return "bld\\t%V3,%s2\;bor\\t%V3,%s0\;bst\\t%V3,%s0"; + } + + if (mode == SImode) + { + operands[3] = GEN_INT (INTVAL (operands[3]) & 0xffff); + if (INTVAL (operands[3]) > 128) + { + operands[3] = GEN_INT (INTVAL (operands[3]) >> 8); + return "bld\\t%V3,%x2\;bor\\t%V3,%x0\;bst\\t%V3,%x0"; + } + return "bld\\t%V3,%w2\;bor\\t%V3,%w0\;bst\\t%V3,%w0"; + } + + gcc_unreachable (); + + } + [(set_attr "length" "6")]) + +(define_insn "*andorsi3_shift_8" + [(set (match_operand:SI 0 "register_operand" "=r") + (ior:SI (and:SI (ashift:SI (match_operand:SI 2 "register_operand" "r") + (const_int 8)) + (const_int 65280)) + (match_operand:SI 1 "register_operand" "0")))] + "" + "or.b\\t%w2,%x0" + [(set_attr "length" "2")]) + +;; ---------------------------------------------------------------------- +;; OR/XOR INSTRUCTIONS +;; ---------------------------------------------------------------------- + +(define_insn "bqi_msx" + [(set (match_operand:QI 0 "bit_register_indirect_operand" "=WU") + (ors:QI (match_operand:QI 1 "bit_register_indirect_operand" "%0") + (match_operand:QI 2 "single_one_operand" "Y2")))] + "TARGET_H8300SX && rtx_equal_p (operands[0], operands[1])" + { return == IOR ? "bset\\t%V2,%0" : "bnot\\t%V2,%0"; } + [(set_attr "length" "8")]) + +(define_insn "bhi_msx" + [(set (match_operand:HI 0 "bit_register_indirect_operand" "=m") + (ors:HI (match_operand:HI 1 "bit_register_indirect_operand" "%0") + (match_operand:HI 2 "single_one_operand" "Y2")))] + "TARGET_H8300SX" + { return == IOR ? "bset\\t%V2,%0" : "bnot\\t%V2,%0"; } + [(set_attr "length" "8")]) + +(define_insn "qi3_1" + [(set (match_operand:QI 0 "bit_operand" "=U,rQ") + (ors:QI (match_operand:QI 1 "bit_operand" "%0,0") + (match_operand:QI 2 "h8300_src_operand" "Y2,rQi")))] + "TARGET_H8300SX || register_operand (operands[0], QImode) + || single_one_operand (operands[2], QImode)" + { + if (which_alternative == 0) + return == IOR ? "bset\\t%V2,%R0" : "bnot\\t%V2,%R0"; + else if (which_alternative == 1) + return == IOR ? "or\\t%X2,%X0" : "xor\\t%X2,%X0"; + gcc_unreachable (); + } + [(set_attr "length" "8,*") + (set_attr "length_table" "*,logicb") + (set_attr "cc" "none_0hit,set_znv")]) + +(define_expand "3" + [(set (match_operand:QHSI 0 "register_operand" "") + (ors:QHSI (match_operand:QHSI 1 "register_operand" "") + (match_operand:QHSI 2 "h8300_src_operand" "")))] + "" + "") + +;; ---------------------------------------------------------------------- +;; {AND,IOR,XOR}{HI3,SI3} PATTERNS +;; ---------------------------------------------------------------------- + +(define_insn "*logical3" + [(set (match_operand:HSI 0 "h8300_dst_operand" "=rQ") + (match_operator:HSI 3 "bit_operator" + [(match_operand:HSI 1 "h8300_dst_operand" "%0") + (match_operand:HSI 2 "h8300_src_operand" "rQi")]))] + "h8300_operands_match_p (operands)" + { return output_logical_op (mode, operands); } + [(set (attr "length") + (symbol_ref "compute_logical_op_length (mode, operands)")) + (set (attr "cc") + (symbol_ref "compute_logical_op_cc (mode, operands)"))]) + + +;; ---------------------------------------------------------------------- +;; NOT INSTRUCTIONS +;; ---------------------------------------------------------------------- + +(define_insn "one_cmpl2" + [(set (match_operand:QHSI 0 "h8300_dst_operand" "=rQ") + (not:QHSI (match_operand:QHSI 1 "h8300_dst_operand" "0")))] + "" + { + if (mode == E_QImode) + return "not %X0"; + if (mode == E_HImode) + return "not.w %T0"; + if (mode == E_SImode) + return "not.l %S0"; + gcc_unreachable (); + } + [(set_attr "length_table" "unary") + (set_attr "cc" "set_znv")]) diff --git a/gcc/config/h8300/movepush.md b/gcc/config/h8300/movepush.md new file mode 100644 index 00000000000..a8241b90a45 --- /dev/null +++ b/gcc/config/h8300/movepush.md @@ -0,0 +1,233 @@ +;; ---------------------------------------------------------------------- +;; MOVE INSTRUCTIONS +;; ---------------------------------------------------------------------- + +;; movqi + +(define_insn "*movqi_h8nosx" + [(set (match_operand:QI 0 "general_operand_dst" "=r,r ,<,r,r,m") + (match_operand:QI 1 "general_operand_src" " I,r>,r,n,m,r"))] + "!TARGET_H8300SX + && h8300_move_ok (operands[0], operands[1])" + "@ + sub.b %X0,%X0 + mov.b %R1,%X0 + mov.b %X1,%R0 + mov.b %R1,%X0 + mov.b %R1,%X0 + mov.b %X1,%R0" + [(set (attr "length") + (symbol_ref "compute_mov_length (operands)")) + (set_attr "cc" "set_zn,set_znv,set_znv,set_znv,set_znv,set_znv")]) + +(define_insn "*movqi_h8sx" + [(set (match_operand:QI 0 "general_operand_dst" "=Z,rQ") + (match_operand:QI 1 "general_operand_src" "P4>X,rQi"))] + "TARGET_H8300SX" + "@ + mov.b %X1:4,%X0 + mov.b %X1,%X0" + [(set_attr "length_table" "mov_imm4,movb") + (set_attr "cc" "set_znv")]) + +(define_expand "mov" + [(set (match_operand:QHSIF 0 "general_operand_dst" "") + (match_operand:QHSIF 1 "general_operand_src" ""))] + "" + { + enum machine_mode mode = mode; + if (!TARGET_H8300SX) + { + /* Other H8 chips, except the H8/SX family can only handle a + single memory operand, which is checked by h8300_move_ok. + + We could perhaps have h8300_move_ok handle the H8/SX better + and just remove the !TARGET_H8300SX conditional. */ + if (!h8300_move_ok (operands[0], operands[1])) + operands[1] = copy_to_mode_reg (mode, operand1); + } + }) + +(define_insn "movstrictqi" + [(set (strict_low_part (match_operand:QI 0 "general_operand_dst" "+r,r")) + (match_operand:QI 1 "general_operand_src" "I,rmi>"))] + "" + "@ + sub.b %X0,%X0 + mov.b %X1,%X0" + [(set_attr "length" "2,*") + (set_attr "length_table" "*,movb") + (set_attr "cc" "set_zn,set_znv")]) + +;; movhi + +(define_insn "*movhi_h8nosx" + [(set (match_operand:HI 0 "general_operand_dst" "=r,r,<,r,r,m") + (match_operand:HI 1 "general_operand_src" "I,r>,r,i,m,r"))] + "!TARGET_H8300SX + && h8300_move_ok (operands[0], operands[1])" + "@ + sub.w %T0,%T0 + mov.w %T1,%T0 + mov.w %T1,%T0 + mov.w %T1,%T0 + mov.w %T1,%T0 + mov.w %T1,%T0" + [(set (attr "length") + (symbol_ref "compute_mov_length (operands)")) + (set_attr "cc" "set_zn,set_znv,set_znv,set_znv,set_znv,set_znv")]) + +(define_insn "*movhi_h8sx" + [(set (match_operand:HI 0 "general_operand_dst" "=r,r,Z,Q,rQ") + (match_operand:HI 1 "general_operand_src" "I,P3>X,P4>X,IP8>X,rQi"))] + "TARGET_H8300SX" + "@ + sub.w %T0,%T0 + mov.w %T1:3,%T0 + mov.w %T1:4,%T0 + mov.w %T1,%T0 + mov.w %T1,%T0" + [(set_attr "length_table" "*,*,mov_imm4,short_immediate,movw") + (set_attr "length" "2,2,*,*,*") + (set_attr "cc" "set_zn,set_znv,set_znv,set_znv,set_znv")]) + +(define_insn "movstricthi" + [(set (strict_low_part (match_operand:HI 0 "general_operand_dst" "+r,r,r")) + (match_operand:HI 1 "general_operand_src" "I,P3>X,rmi"))] + "" + "@ + sub.w %T0,%T0 + mov.w %T1,%T0 + mov.w %T1,%T0" + [(set_attr "length" "2,2,*") + (set_attr "length_table" "*,*,movw") + (set_attr "cc" "set_zn,set_znv,set_znv")]) + +;; movsi +(define_insn "*movsi_h8300hs" + [(set (match_operand:SI 0 "general_operand_dst" "=r,r,r,<,r,r,m,*a,*a,r") + (match_operand:SI 1 "general_operand_src" "I,r,i,r,>,m,r,I,r,*a"))] + "(TARGET_H8300S || TARGET_H8300H) && !TARGET_H8300SX + && h8300_move_ok (operands[0], operands[1])" +{ + switch (which_alternative) + { + case 0: + return "sub.l %S0,%S0"; + case 7: + return "clrmac"; + case 8: + return "clrmac\;ldmac %1,macl"; + case 9: + return "stmac macl,%0"; + default: + if (GET_CODE (operands[1]) == CONST_INT) + { + int val = INTVAL (operands[1]); + + /* Look for constants which can be made by adding an 8-bit + number to zero in one of the two low bytes. */ + if (val == (val & 0xff)) + { + operands[1] = GEN_INT ((char) val & 0xff); + return "sub.l\\t%S0,%S0\;add.b\\t%1,%w0"; + } + + if (val == (val & 0xff00)) + { + operands[1] = GEN_INT ((char) (val >> 8) & 0xff); + return "sub.l\\t%S0,%S0\;add.b\\t%1,%x0"; + } + + /* Look for constants that can be obtained by subs, inc, and + dec to 0. */ + switch (val & 0xffffffff) + { + case 0xffffffff: + return "sub.l\\t%S0,%S0\;subs\\t#1,%S0"; + case 0xfffffffe: + return "sub.l\\t%S0,%S0\;subs\\t#2,%S0"; + case 0xfffffffc: + return "sub.l\\t%S0,%S0\;subs\\t#4,%S0"; + + case 0x0000ffff: + return "sub.l\\t%S0,%S0\;dec.w\\t#1,%f0"; + case 0x0000fffe: + return "sub.l\\t%S0,%S0\;dec.w\\t#2,%f0"; + + case 0xffff0000: + return "sub.l\\t%S0,%S0\;dec.w\\t#1,%e0"; + case 0xfffe0000: + return "sub.l\\t%S0,%S0\;dec.w\\t#2,%e0"; + + case 0x00010000: + return "sub.l\\t%S0,%S0\;inc.w\\t#1,%e0"; + case 0x00020000: + return "sub.l\\t%S0,%S0\;inc.w\\t#2,%e0"; + } + } + } + return "mov.l %S1,%S0"; +} + [(set (attr "length") + (symbol_ref "compute_mov_length (operands)")) + (set_attr "cc" "set_zn,set_znv,clobber,set_znv,set_znv,set_znv,set_znv,none_0hit,none_0hit,set_znv")]) + +(define_insn "*movsi_h8sx" + [(set (match_operand:SI 0 "general_operand_dst" "=r,r,Q,rQ,*a,*a,r") + (match_operand:SI 1 "general_operand_src" "I,P3>X,IP8>X,rQi,I,r,*a"))] + "TARGET_H8300SX" + "@ + sub.l %S0,%S0 + mov.l %S1:3,%S0 + mov.l %S1,%S0 + mov.l %S1,%S0 + clrmac + clrmac\;ldmac %1,macl + stmac macl,%0" + [(set_attr "length_table" "*,*,short_immediate,movl,*,*,*") + (set_attr "length" "2,2,*,*,2,6,4") + (set_attr "cc" "set_zn,set_znv,set_znv,set_znv,none_0hit,none_0hit,set_znv")]) + +(define_insn "*movsf_h8sx" + [(set (match_operand:SF 0 "general_operand_dst" "=r,rQ") + (match_operand:SF 1 "general_operand_src" "G,rQi"))] + "TARGET_H8300SX" + "@ + sub.l %S0,%S0 + mov.l %S1,%S0" + [(set_attr "length" "2,*") + (set_attr "length_table" "*,movl") + (set_attr "cc" "set_zn,set_znv")]) + +(define_insn "*movsf_h8300hs" + [(set (match_operand:SF 0 "general_operand_dst" "=r,r,r,m,<,r") + (match_operand:SF 1 "general_operand_src" "G,r,im,r,r,>"))] + "!TARGET_H8300SX + && (register_operand (operands[0], SFmode) + || register_operand (operands[1], SFmode))" + "@ + sub.l %S0,%S0 + mov.l %S1,%S0 + mov.l %S1,%S0 + mov.l %S1,%S0 + mov.l %S1,%S0 + mov.l %S1,%S0" + [(set (attr "length") + (symbol_ref "compute_mov_length (operands)")) + (set_attr "cc" "set_zn,set_znv,set_znv,set_znv,set_znv,set_znv")]) + +;; ---------------------------------------------------------------------- +;; PUSH INSTRUCTIONS +;; ---------------------------------------------------------------------- + +(define_insn "*push1_h8300hs_" + [(set (mem:QHI + (pre_modify:P + (reg:P SP_REG) + (plus:P (reg:P SP_REG) (const_int -4)))) + (match_operand:QHI 0 "register_no_sp_elim_operand" "r"))] + "" + "mov.l\\t%S0,@-er7" + [(set_attr "length" "4")]) + diff --git a/gcc/config/h8300/multiply.md b/gcc/config/h8300/multiply.md new file mode 100644 index 00000000000..4e9112f970c --- /dev/null +++ b/gcc/config/h8300/multiply.md @@ -0,0 +1,194 @@ +;; ---------------------------------------------------------------------- +;; MULTIPLY INSTRUCTIONS +;; ---------------------------------------------------------------------- + +;; Note that the H8/300 can only handle umulqihi3. + +(define_expand "mulqihi3" + [(set (match_operand:HI 0 "register_operand" "") + (mult:HI (sign_extend:HI (match_operand:QI 1 "register_operand" "")) + ;; intentionally-mismatched modes + (match_operand:QI 2 "reg_or_nibble_operand" "")))] + "" + { + if (GET_MODE (operands[2]) != VOIDmode) + operands[2] = gen_rtx_SIGN_EXTEND (HImode, operands[2]); + }) + +(define_insn "*mulqihi3_const" + [(set (match_operand:HI 0 "register_operand" "=r") + (mult:HI (sign_extend:HI (match_operand:QI 1 "register_operand" "%0")) + (match_operand:QI 2 "nibble_operand" "IP4>X")))] + "TARGET_H8300SX" + "mulxs.b %X2,%T0" + [(set_attr "length" "4") + (set_attr "cc" "set_zn")]) + +(define_insn "*mulqihi3" + [(set (match_operand:HI 0 "register_operand" "=r") + (mult:HI (sign_extend:HI (match_operand:QI 1 "register_operand" "%0")) + (sign_extend:HI (match_operand:QI 2 "register_operand" "r"))))] + "" + "mulxs.b %X2,%T0" + [(set_attr "length" "4") + (set_attr "cc" "set_zn")]) + +(define_expand "mulhisi3" + [(set (match_operand:SI 0 "register_operand" "") + (mult:SI (sign_extend:SI (match_operand:HI 1 "register_operand" "")) + ;; intentionally-mismatched modes + (match_operand:HI 2 "reg_or_nibble_operand" "")))] + "" + { + if (GET_MODE (operands[2]) != VOIDmode) + operands[2] = gen_rtx_SIGN_EXTEND (SImode, operands[2]); + }) + +(define_insn "*mulhisi3_const" + [(set (match_operand:SI 0 "register_operand" "=r") + (mult:SI (sign_extend:SI (match_operand:HI 1 "register_operand" "%0")) + (match_operand:SI 2 "nibble_operand" "IP4>X")))] + "TARGET_H8300SX" + "mulxs.w %T2,%S0" + [(set_attr "length" "4") + (set_attr "cc" "set_zn")]) + +(define_insn "*mulhisi3" + [(set (match_operand:SI 0 "register_operand" "=r") + (mult:SI (sign_extend:SI (match_operand:HI 1 "register_operand" "%0")) + (sign_extend:SI (match_operand:HI 2 "register_operand" "r"))))] + "" + "mulxs.w %T2,%S0" + [(set_attr "length" "4") + (set_attr "cc" "set_zn")]) + +(define_expand "umulqihi3" + [(set (match_operand:HI 0 "register_operand" "") + (mult:HI (zero_extend:HI (match_operand:QI 1 "register_operand" "")) + ;; intentionally-mismatched modes + (match_operand:QI 2 "reg_or_nibble_operand" "")))] + "" + { + if (GET_MODE (operands[2]) != VOIDmode) + operands[2] = gen_rtx_ZERO_EXTEND (HImode, operands[2]); + }) + +(define_insn "*umulqihi3_const" + [(set (match_operand:HI 0 "register_operand" "=r") + (mult:HI (zero_extend:HI (match_operand:QI 1 "register_operand" "%0")) + (match_operand:QI 2 "nibble_operand" "IP4>X")))] + "TARGET_H8300SX" + "mulxu.b %X2,%T0" + [(set_attr "length" "4") + (set_attr "cc" "set_zn")]) + +(define_insn "*umulqihi3" + [(set (match_operand:HI 0 "register_operand" "=r") + (mult:HI (zero_extend:HI (match_operand:QI 1 "register_operand" "%0")) + (zero_extend:HI (match_operand:QI 2 "register_operand" "r"))))] + "" + "mulxu.b %X2,%T0" + [(set_attr "length" "2") + (set_attr "cc" "none_0hit")]) + +(define_expand "umulhisi3" + [(set (match_operand:SI 0 "register_operand" "") + (mult:SI (zero_extend:SI (match_operand:HI 1 "register_operand" "")) + ;; intentionally-mismatched modes + (match_operand:HI 2 "reg_or_nibble_operand" "")))] + "" + { + if (GET_MODE (operands[2]) != VOIDmode) + operands[2] = gen_rtx_ZERO_EXTEND (SImode, operands[2]); + }) + +(define_insn "*umulhisi3_const" + [(set (match_operand:SI 0 "register_operand" "=r") + (mult:SI (zero_extend:SI (match_operand:HI 1 "register_operand" "%0")) + (match_operand:SI 2 "nibble_operand" "IP4>X")))] + "TARGET_H8300SX" + "mulxu.w %T2,%S0" + [(set_attr "length" "4") + (set_attr "cc" "set_zn")]) + +(define_insn "*umulhisi3" + [(set (match_operand:SI 0 "register_operand" "=r") + (mult:SI (zero_extend:SI (match_operand:HI 1 "register_operand" "%0")) + (zero_extend:SI (match_operand:HI 2 "register_operand" "r"))))] + "" + "mulxu.w %T2,%S0" + [(set_attr "length" "2") + (set_attr "cc" "none_0hit")]) + +;; We could have used mulu.[wl] here, but mulu.[lw] is only available +;; on a H8SX with a multiplier, whereas muls.w seems to be available +;; on all H8SX variants. + +(define_insn "mul3" + [(set (match_operand:HSI 0 "register_operand" "=r") + (mult:HSI (match_operand:HSI 1 "register_operand" "%0") + (match_operand:HSI 2 "reg_or_nibble_operand" "r IP4>X")))] + "TARGET_H8300SX" + { return mode == HImode ? "muls.w\\t%T2,%T0" : "muls.l\\t%S2,%S0"; } + [(set_attr "length" "4") + (set_attr "cc" "set_zn")]) + +(define_insn "smulsi3_highpart" + [(set (match_operand:SI 0 "register_operand" "=r") + (truncate:SI + (lshiftrt:DI + (mult:DI + (sign_extend:DI (match_operand:SI 1 "register_operand" "%0")) + (sign_extend:DI (match_operand:SI 2 "reg_or_nibble_operand" "r IP4>X"))) + (const_int 32))))] + "TARGET_H8300SXMUL" + "muls/u.l\\t%S2,%S0" + [(set_attr "length" "4") + (set_attr "cc" "set_zn")]) + +(define_insn "umulsi3_highpart" + [(set (match_operand:SI 0 "register_operand" "=r") + (truncate:SI + (ashiftrt:DI + (mult:DI + (zero_extend:DI (match_operand:SI 1 "register_operand" "%0")) + (zero_extend:DI (match_operand:SI 2 "reg_or_nibble_operand" "r IP4>X"))) + (const_int 32))))] + "TARGET_H8300SX" + "mulu/u.l\\t%S2,%S0" + [(set_attr "length" "4") + (set_attr "cc" "none_0hit")]) + +;; This is a "bridge" instruction. Combine can't cram enough insns +;; together to crate a MAC instruction directly, but it can create +;; this instruction, which then allows combine to create the real +;; MAC insn. +;; +;; Unfortunately, if combine doesn't create a MAC instruction, this +;; insn must generate reasonably correct code. Egad. + +(define_insn "" + [(set (match_operand:SI 0 "register_operand" "=a") + (mult:SI + (sign_extend:SI + (mem:HI (post_inc:SI (match_operand:SI 1 "register_operand" "r")))) + (sign_extend:SI + (mem:HI (post_inc:SI (match_operand:SI 2 "register_operand" "r"))))))] + "TARGET_MAC" + "clrmac\;mac @%2+,@%1+" + [(set_attr "length" "6") + (set_attr "cc" "none_0hit")]) + +(define_insn "" + [(set (match_operand:SI 0 "register_operand" "=a") + (plus:SI (mult:SI + (sign_extend:SI (mem:HI + (post_inc:SI (match_operand:SI 1 "register_operand" "r")))) + (sign_extend:SI (mem:HI + (post_inc:SI (match_operand:SI 2 "register_operand" "r"))))) + (match_operand:SI 3 "register_operand" "0")))] + "TARGET_MAC" + "mac @%2+,@%1+" + [(set_attr "length" "4") + (set_attr "cc" "none_0hit")]) + diff --git a/gcc/config/h8300/other.md b/gcc/config/h8300/other.md new file mode 100644 index 00000000000..4b96a7c4a40 --- /dev/null +++ b/gcc/config/h8300/other.md @@ -0,0 +1,17 @@ +;; ---------------------------------------------------------------------- +;; ABSOLUTE VALUE INSTRUCTIONS +;; ---------------------------------------------------------------------- + +(define_insn "abssf2" + [(set (match_operand:SF 0 "register_operand" "=r") + (abs:SF (match_operand:SF 1 "register_operand" "0")))] + "" + "and.w\\t#32767,%e0" + [(set_attr "length" "4")]) + +(define_insn "nop" + [(const_int 0)] + "" + "nop" + [(set_attr "cc" "none") + (set_attr "length" "2")]) diff --git a/gcc/config/h8300/proepi.md b/gcc/config/h8300/proepi.md new file mode 100644 index 00000000000..9d19ff54084 --- /dev/null +++ b/gcc/config/h8300/proepi.md @@ -0,0 +1,127 @@ +;; ---------------------------------------------------------------------- +;; PROLOGUE/EPILOGUE-RELATED INSTRUCTIONS +;; ---------------------------------------------------------------------- + +(define_expand "push_h8300hs_advanced" + [(set (mem:SI (pre_dec:SI (reg:SI SP_REG))) + (match_operand:SI 0 "register_operand" ""))] + "TARGET_H8300H && TARGET_H8300S && !TARGET_NORMAL_MODE" + "") + +(define_expand "push_h8300hs_normal" + [(set (mem:SI (pre_dec:HI (reg:HI SP_REG))) + (match_operand:SI 0 "register_operand" ""))] + "TARGET_H8300H && TARGET_H8300S && TARGET_NORMAL_MODE" + "") + +(define_expand "pop_h8300hs_advanced" + [(set (match_operand:SI 0 "register_operand" "") + (mem:SI (post_inc:SI (reg:SI SP_REG))))] + "TARGET_H8300H && TARGET_H8300S && !TARGET_NORMAL_MODE" + "") + +(define_expand "pop_h8300hs_normal" + [(set (match_operand:SI 0 "register_operand" "") + (mem:SI (post_inc:HI (reg:HI SP_REG))))] + "TARGET_H8300H && TARGET_H8300S && TARGET_NORMAL_MODE" + "") + +(define_insn "ldm_h8300sx" + [(match_parallel 0 "h8300_ldm_parallel" + [(set (match_operand:SI 1 "register_operand" "") + (match_operand:SI 2 "memory_operand" ""))])] + "TARGET_H8300S" +{ + operands[3] = SET_DEST (XVECEXP (operands[0], 0, + XVECLEN (operands[0], 0) - 2)); + return "ldm.l\t@er7+,%S1-%S3"; +} + [(set_attr "cc" "none") + (set_attr "length" "4")]) + +(define_insn "stm_h8300sx" + [(match_parallel 0 "h8300_stm_parallel" + [(set (match_operand:SI 1 "memory_operand" "") + (match_operand:SI 2 "register_operand" ""))])] + "TARGET_H8300S" +{ + operands[3] = SET_SRC (XVECEXP (operands[0], 0, + XVECLEN (operands[0], 0) - 2)); + return "stm.l\t%S2-%S3,@-er7"; +} + [(set_attr "cc" "none") + (set_attr "length" "4")]) + +(define_insn "return_h8sx" + [(match_parallel 0 "h8300_return_parallel" + [(return) + (set (match_operand:SI 1 "register_operand" "") + (match_operand:SI 2 "memory_operand" ""))])] + "TARGET_H8300SX" +{ + operands[3] = SET_DEST (XVECEXP (operands[0], 0, + XVECLEN (operands[0], 0) - 2)); + if (h8300_current_function_interrupt_function_p () + || h8300_current_function_monitor_function_p ()) + return "rte/l\t%S1-%S3"; + else + return "rts/l\t%S1-%S3"; +} + [(set_attr "cc" "none") + (set_attr "can_delay" "no") + (set_attr "length" "2")]) + +(define_expand "return" + [(return)] + "h8300_can_use_return_insn_p ()" + "") + +(define_insn "*return_1" + [(return)] + "reload_completed" +{ + if (h8300_current_function_interrupt_function_p () + || h8300_current_function_monitor_function_p ()) + return "rte"; + else + return "rts"; +} + [(set_attr "cc" "none") + (set_attr "can_delay" "no") + (set_attr "length" "2")]) + +(define_expand "prologue" + [(const_int 0)] + "" + { + h8300_expand_prologue (); + DONE; + }) + +(define_expand "epilogue" + [(return)] + "" + { + h8300_expand_epilogue (); + DONE; + }) + +(define_insn "monitor_prologue" + [(unspec_volatile [(const_int 0)] UNSPEC_MONITOR)] + "" +{ + if (TARGET_H8300H && TARGET_NORMAL_MODE) + return "subs\\t#2,er7\;mov.l\\ter0,@-er7\;stc\\tccr,r0l\;mov.b\\tr0l,@(4,er7)\;mov.l\\t@er7+,er0\;orc\\t#128,ccr"; + else if (TARGET_H8300H) + return "mov.l\\ter0,@-er7\;stc\\tccr,r0l\;mov.b\\tr0l,@(4,er7)\;mov.l\\t@er7+,er0\;orc\\t#128,ccr"; + else if (TARGET_H8300S && TARGET_NEXR ) + return "mov.l\\ter0,@-er7\;stc\tccr,r0l\;mov.b\tr0l,@(4,er7)\;mov.l\\t@er7+,er0\;orc\t#128,ccr"; + else if (TARGET_H8300S && TARGET_NEXR && TARGET_NORMAL_MODE) + return "subs\\t#2,er7\;mov.l\\ter0,@-er7\;stc\tccr,r0l\;mov.b\tr0l,@(4,er7)\;mov.l\\t@er7+,er0\;orc\t#128,ccr"; + else if (TARGET_H8300S && TARGET_NORMAL_MODE) + return "subs\\t#2,er7\;stc\texr,@-er7\;mov.l\\ter0,@-er7\;stc\tccr,r0l\;mov.b\tr0l,@(6,er7)\;mov.l\\t@er7+,er0\;orc\t#128,ccr"; + else if (TARGET_H8300S) + return "stc\texr,@-er7\;mov.l\\ter0,@-er7\;stc\tccr,r0l\;mov.b\tr0l,@(6,er7)\;mov.l\\t@er7+,er0\;orc\t#128,ccr"; + gcc_unreachable (); +} + [(set_attr "length" "20")]) diff --git a/gcc/config/h8300/shiftrotate.md b/gcc/config/h8300/shiftrotate.md new file mode 100644 index 00000000000..75606d7c50b --- /dev/null +++ b/gcc/config/h8300/shiftrotate.md @@ -0,0 +1,223 @@ +;; ---------------------------------------------------------------------- +;; SHIFTS +;; ---------------------------------------------------------------------- +;; +;; We make some attempt to provide real efficient shifting. One example is +;; doing an 8-bit shift of a 16-bit value by moving a byte reg into the other +;; reg and moving 0 into the former reg. +;; +;; We also try to achieve this in a uniform way. IE: We don't try to achieve +;; this in both rtl and at insn emit time. Ideally, we'd use rtl as that would +;; give the optimizer more cracks at the code. However, we wish to do things +;; like optimizing shifting the sign bit to bit 0 by rotating the other way. +;; There is rtl to handle this (rotate + and), but the H8/300 doesn't handle +;; 16-bit rotates. Also, if we emit complicated rtl, combine may not be able +;; to detect cases it can optimize. +;; +;; For these and other fuzzy reasons, I've decided to go the less pretty but +;; easier "do it at insn emit time" route. + + +(define_expand "ashl3" + [(set (match_operand:QHSI 0 "register_operand" "") + (ashift:QHSI (match_operand:QHSI 1 "register_operand" "") + (match_operand:QI 2 "nonmemory_operand" "")))] + "" + { + if (expand_a_shift (mode, ASHIFT, operands)) + DONE; + }) + +(define_expand "ashr3" + [(set (match_operand:QHSI 0 "register_operand" "") + (ashiftrt:QHSI (match_operand:QHSI 1 "register_operand" "") + (match_operand:QI 2 "nonmemory_operand" "")))] + "" + { + if (expand_a_shift (mode, ASHIFTRT, operands)) + DONE; + }) + +(define_expand "lshr3" + [(set (match_operand:QHSI 0 "register_operand" "") + (lshiftrt:QHSI (match_operand:QHSI 1 "register_operand" "") + (match_operand:QI 2 "nonmemory_operand" "")))] + "" + { + if (expand_a_shift (mode, LSHIFTRT, operands)) + DONE; + }) + +;; QI/HI/SI BIT SHIFTS + +(define_insn "" + [(set (match_operand:QHSI 0 "h8300_dst_operand" "=rQ") + (match_operator:QHSI 3 "h8sx_unary_shift_operator" + [(match_operand:QHSI 1 "h8300_dst_operand" "0") + (match_operand:QI 2 "const_int_operand" "")]))] + "h8300_operands_match_p (operands)" +{ + if (mode == E_QImode) + return output_h8sx_shift (operands, 'b', 'X'); + if (mode == E_HImode) + return output_h8sx_shift (operands, 'w', 'T'); + if (mode == E_SImode) + return output_h8sx_shift (operands, 'l', 'S'); + gcc_unreachable (); +} + [(set_attr "length_table" "unary") + (set_attr "cc" "set_znv")]) + +(define_insn "" + [(set (match_operand:QHSI 0 "register_operand" "=r") + (match_operator:QHSI 3 "h8sx_binary_shift_operator" + [(match_operand:QHSI 1 "register_operand" "0") + (match_operand:QI 2 "nonmemory_operand" "r P5>X")]))] + "" +{ + if (mode == QImode) + return output_h8sx_shift (operands, 'b', 'X'); + if (mode == HImode) + return output_h8sx_shift (operands, 'w', 'T'); + if (mode == SImode) + return output_h8sx_shift (operands, 'l', 'S'); + gcc_unreachable (); +} + [(set_attr "length" "4") + (set_attr "cc" "set_znv")]) + +(define_insn "*shiftqi" + [(set (match_operand:QI 0 "register_operand" "=r,r") + (match_operator:QI 3 "nshift_operator" + [(match_operand:QI 1 "register_operand" "0,0") + (match_operand:QI 2 "nonmemory_operand" "R,rn")])) + (clobber (match_scratch:QI 4 "=X,&r"))] + "" +{ + return output_a_shift (operands); +} + [(set (attr "length") + (symbol_ref "compute_a_shift_length (insn, operands)")) + (set (attr "cc") + (symbol_ref "compute_a_shift_cc (insn, operands)"))]) + +(define_insn "*shifthi" + [(set (match_operand:HI 0 "register_operand" "=r,r") + (match_operator:HI 3 "nshift_operator" + [(match_operand:HI 1 "register_operand" "0,0") + (match_operand:QI 2 "nonmemory_operand" "S,rn")])) + (clobber (match_scratch:QI 4 "=X,&r"))] + "" +{ + return output_a_shift (operands); +} + [(set (attr "length") + (symbol_ref "compute_a_shift_length (insn, operands)")) + (set (attr "cc") + (symbol_ref "compute_a_shift_cc (insn, operands)"))]) + +(define_insn "*shiftsi" + [(set (match_operand:SI 0 "register_operand" "=r,r") + (match_operator:SI 3 "nshift_operator" + [(match_operand:SI 1 "register_operand" "0,0") + (match_operand:QI 2 "nonmemory_operand" "T,rn")])) + (clobber (match_scratch:QI 4 "=X,&r"))] + "" +{ + return output_a_shift (operands); +} + [(set (attr "length") + (symbol_ref "compute_a_shift_length (insn, operands)")) + (set (attr "cc") + (symbol_ref "compute_a_shift_cc (insn, operands)"))]) + + +;; Split a variable shift into a loop. If the register containing +;; the shift count dies, then we just use that register. + +(define_split + [(set (match_operand 0 "register_operand" "") + (match_operator 2 "nshift_operator" + [(match_dup 0) + (match_operand:QI 1 "register_operand" "")])) + (clobber (match_operand:QI 3 "register_operand" ""))] + "epilogue_completed + && find_regno_note (insn, REG_DEAD, REGNO (operands[1]))" + [(set (cc0) (compare (match_dup 1) (const_int 0))) + (set (pc) + (if_then_else (le (cc0) (const_int 0)) + (label_ref (match_dup 5)) + (pc))) + (match_dup 4) + (parallel + [(set (match_dup 0) + (match_op_dup 2 [(match_dup 0) (const_int 1)])) + (clobber (scratch:QI))]) + (set (match_dup 1) (plus:QI (match_dup 1) (const_int -1))) + (set (cc0) (compare (match_dup 1) (const_int 0))) + (set (pc) + (if_then_else (ne (cc0) (const_int 0)) + (label_ref (match_dup 4)) + (pc))) + (match_dup 5)] + { + operands[4] = gen_label_rtx (); + operands[5] = gen_label_rtx (); + }) + +(define_split + [(set (match_operand 0 "register_operand" "") + (match_operator 2 "nshift_operator" + [(match_dup 0) + (match_operand:QI 1 "register_operand" "")])) + (clobber (match_operand:QI 3 "register_operand" ""))] + "epilogue_completed + && !find_regno_note (insn, REG_DEAD, REGNO (operands[1]))" + [(set (match_dup 3) + (match_dup 1)) + (set (cc0) (compare (match_dup 3) (const_int 0))) + (set (pc) + (if_then_else (le (cc0) (const_int 0)) + (label_ref (match_dup 5)) + (pc))) + (match_dup 4) + (parallel + [(set (match_dup 0) + (match_op_dup 2 [(match_dup 0) (const_int 1)])) + (clobber (scratch:QI))]) + (set (match_dup 3) (plus:QI (match_dup 3) (const_int -1))) + (set (cc0) (compare (match_dup 3) (const_int 0))) + (set (pc) + (if_then_else (ne (cc0) (const_int 0)) + (label_ref (match_dup 4)) + (pc))) + (match_dup 5)] + { + operands[4] = gen_label_rtx (); + operands[5] = gen_label_rtx (); + }) + +;; ---------------------------------------------------------------------- +;; ROTATIONS +;; ---------------------------------------------------------------------- + +(define_expand "rotl3" + [(set (match_operand:QHSI 0 "register_operand" "") + (rotate:QHSI (match_operand:QHSI 1 "register_operand" "") + (match_operand:QI 2 "nonmemory_operand" "")))] + "" + { + if (expand_a_rotate (operands)) + DONE; + }) + +(define_insn "rotl3_1" + [(set (match_operand:QHSI 0 "register_operand" "=r") + (rotate:QHSI (match_operand:QHSI 1 "register_operand" "0") + (match_operand:QI 2 "immediate_operand" "")))] + "" +{ + return output_a_rotate (ROTATE, operands); +} + [(set (attr "length") + (symbol_ref "compute_a_rotate_length (operands)"))]) diff --git a/gcc/config/h8300/testcompare.md b/gcc/config/h8300/testcompare.md new file mode 100644 index 00000000000..2e4cb5afee7 --- /dev/null +++ b/gcc/config/h8300/testcompare.md @@ -0,0 +1,201 @@ +;; ---------------------------------------------------------------------- +;; TEST INSTRUCTIONS +;; ---------------------------------------------------------------------- + +(define_insn_and_split "*tst_extzv_1_n" + [(set (cc0) + (compare (zero_extract:SI (match_operand:QI 0 "general_operand_src" "r,U,mn>") + (const_int 1) + (match_operand 1 "const_int_operand" "n,n,n")) + (const_int 0))) + (clobber (match_scratch:QI 2 "=X,X,&r"))] + "" + "@ + btst\\t%Z1,%Y0 + btst\\t%Z1,%Y0 + #" + "&& reload_completed + && !satisfies_constraint_U (operands[0])" + [(set (match_dup 2) + (match_dup 0)) + (parallel [(set (cc0) (compare (zero_extract:SI (match_dup 2) + (const_int 1) + (match_dup 1)) + (const_int 0))) + (clobber (scratch:QI))])] + "" + [(set_attr "length" "2,8,10") + (set_attr "cc" "set_zn,set_zn,set_zn")]) + +(define_insn "" + [(set (cc0) + (compare (zero_extract:HSI (match_operand:HSI 0 "register_operand" "r") + (const_int 1) + (match_operand 1 "const_int_operand" "n")) + (const_int 0)))] + "INTVAL (operands[1]) <= 15" + "btst %Z1,%Y0" + [(set_attr "length" "2") + (set_attr "cc" "set_zn")]) + +(define_insn_and_split "*tstsi_upper_bit" + [(set (cc0) + (compare (zero_extract:SI (match_operand:SI 0 "register_operand" "r") + (const_int 1) + (match_operand 1 "const_int_operand" "n")) + (const_int 0))) + (clobber (match_scratch:SI 2 "=&r"))] + "INTVAL (operands[1]) >= 16" + "#" + "&& reload_completed" + [(set (match_dup 2) + (ior:SI (and:SI (match_dup 2) + (const_int -65536)) + (lshiftrt:SI (match_dup 0) + (const_int 16)))) + (set (cc0) + (compare (zero_extract:SI (match_dup 2) + (const_int 1) + (match_dup 3)) + (const_int 0)))] + { + operands[3] = GEN_INT (INTVAL (operands[1]) - 16); + }) + +(define_insn "*tstsi_variable_bit" + [(set (cc0) + (compare (zero_extract:SI (match_operand:SI 0 "register_operand" "r") + (const_int 1) + (and:SI (match_operand:SI 1 "register_operand" "r") + (const_int 7))) + (const_int 0)))] + "" + "btst %w1,%w0" + [(set_attr "length" "2") + (set_attr "cc" "set_zn")]) + +(define_insn_and_split "*tstsi_variable_bit_qi" + [(set (cc0) + (compare (zero_extract:SI (zero_extend:SI (match_operand:QI 0 "general_operand_src" "r,U,mn>")) + (const_int 1) + (and:SI (match_operand:SI 1 "register_operand" "r,r,r") + (const_int 7))) + (const_int 0))) + (clobber (match_scratch:QI 2 "=X,X,&r"))] + "" + "@ + btst\\t%w1,%X0 + btst\\t%w1,%X0 + #" + "&& reload_completed + && !satisfies_constraint_U (operands[0])" + [(set (match_dup 2) + (match_dup 0)) + (parallel [(set (cc0) + (compare (zero_extract:SI (zero_extend:SI (match_dup 2)) + (const_int 1) + (and:SI (match_dup 1) + (const_int 7))) + (const_int 0))) + (clobber (scratch:QI))])] + "" + [(set_attr "length" "2,8,10") + (set_attr "cc" "set_zn,set_zn,set_zn")]) + +(define_insn "*tst" + [(set (cc0) + (compare (match_operand:QHI 0 "register_operand" "r") + (const_int 0)))] + "" + { + if (mode == QImode) + return "mov.b %X0,%X0"; + else if (mode == HImode) + return "mov.w %T0,%T0"; + gcc_unreachable (); + } + [(set_attr "length" "2") + (set_attr "cc" "set_znv")]) + +(define_insn "*tsthi_upper" + [(set (cc0) + (compare (and:HI (match_operand:HI 0 "register_operand" "r") + (const_int -256)) + (const_int 0)))] + "" + "mov.b %t0,%t0" + [(set_attr "length" "2") + (set_attr "cc" "set_znv")]) + +(define_insn "*tstsi" + [(set (cc0) + (compare (match_operand:SI 0 "register_operand" "r") + (const_int 0)))] + "" + "mov.l %S0,%S0" + [(set_attr "length" "2") + (set_attr "cc" "set_znv")]) + +(define_insn "*tstsi_upper" + [(set (cc0) + (compare (and:SI (match_operand:SI 0 "register_operand" "r") + (const_int -65536)) + (const_int 0)))] + "" + "mov.w %e0,%e0" + [(set_attr "length" "2") + (set_attr "cc" "set_znv")]) + +(define_insn "*cmpqi" + [(set (cc0) + (compare (match_operand:QI 0 "h8300_dst_operand" "rQ") + (match_operand:QI 1 "h8300_src_operand" "rQi")))] + "" + "cmp.b %X1,%X0" + [(set_attr "length_table" "add") + (set_attr "cc" "compare")]) + +(define_insn "*cmphi_h8300hs_znvc" + [(set (cc0) + (compare (match_operand:HI 0 "h8300_dst_operand" "rU,rQ") + (match_operand:HI 1 "h8300_src_operand" "P3>X,rQi")))] + "" +{ + switch (which_alternative) + { + case 0: + if (!TARGET_H8300SX) + return "cmp.w %T1,%T0"; + else + return "cmp.w %T1:3,%T0"; + case 1: + return "cmp.w %T1,%T0"; + default: + gcc_unreachable (); + } +} + [(set_attr "length_table" "short_immediate,add") + (set_attr "cc" "compare,compare")]) + +(define_insn "cmpsi" + [(set (cc0) + (compare (match_operand:SI 0 "h8300_dst_operand" "r,rQ") + (match_operand:SI 1 "h8300_src_operand" "P3>X,rQi")))] + "" +{ + switch (which_alternative) + { + case 0: + if (!TARGET_H8300SX) + return "cmp.l %S1,%S0"; + else + return "cmp.l %S1:3,%S0"; + case 1: + return "cmp.l %S1,%S0"; + default: + gcc_unreachable (); + } +} + [(set_attr "length" "2,*") + (set_attr "length_table" "*,add") + (set_attr "cc" "compare,compare")])