;; GCC machine description for Hitachi H8/300
;; Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
-;; 2001, 2002 Free Software Foundation, Inc.
+;; 2001, 2002, 2003 Free Software Foundation, Inc.
;; Contributed by Steve Chamberlain (sac@cygnus.com),
;; Jim Wilson (wilson@cygnus.com), and Doug Evans (dje@cygnus.com).
-;; This file is part of GNU CC.
+;; This file is part of GCC.
-;; GNU CC is free software; you can redistribute it and/or modify
+;; GCC is free software; you can redistribute it and/or modify
;; it under the terms of the GNU General Public License as published by
;; the Free Software Foundation; either version 2, or (at your option)
;; any later version.
-;; GNU CC is distributed in the hope that it will be useful,
+;; GCC is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
;; GNU General Public License for more details.
;; You should have received a copy of the GNU General Public License
-;; along with GNU CC; see the file COPYING. If not, write to
+;; along with GCC; see the file COPYING. If not, write to
;; the Free Software Foundation, 59 Temple Place - Suite 330,
;; Boston, MA 02111-1307, USA.
;; ----------------------------------------------------------------------
(define_constants
+ [(UNSPEC_INCDEC 0)
+ (UNSPEC_MONITOR 1)])
+
+(define_constants
[(SC_REG 3)
(FP_REG 6)
(SP_REG 7)
(plus:HI (reg:HI SP_REG) (const_int -2)))
(set (mem:QI (plus:HI (reg:HI SP_REG) (const_int -1)))
(match_operand:QI 0 "register_operand" "r"))])]
- "TARGET_H8300"
+ "TARGET_H8300
+ && REGNO (operands[0]) != SP_REG"
"mov.w\\t%T0,@-r7"
[(set_attr "length" "2")
(set_attr "cc" "clobber")])
(plus:SI (reg:SI SP_REG) (const_int -4)))
(set (mem:QI (plus:SI (reg:SI SP_REG) (const_int -3)))
(match_operand:QI 0 "register_operand" "r"))])]
- "TARGET_H8300H || TARGET_H8300S"
+ "(TARGET_H8300H || TARGET_H8300S)
+ && REGNO (operands[0]) != SP_REG"
"mov.l\\t%S0,@-er7"
[(set_attr "length" "4")
(set_attr "cc" "clobber")])
(define_expand "pushhi1_h8300"
[(set (mem:HI (pre_dec:HI (reg:HI SP_REG)))
(match_operand:HI 0 "register_operand" ""))]
- "TARGET_H8300"
+ "TARGET_H8300
+ && REGNO (operands[0]) != SP_REG"
"")
(define_insn "pushhi1_h8300hs"
(plus:SI (reg:SI SP_REG) (const_int -4)))
(set (mem:HI (plus:SI (reg:SI SP_REG) (const_int -2)))
(match_operand:HI 0 "register_operand" "r"))])]
- "TARGET_H8300H || TARGET_H8300S"
+ "(TARGET_H8300H || TARGET_H8300S)
+ && REGNO (operands[0]) != SP_REG"
"mov.l\\t%S0,@-er7"
[(set_attr "length" "4")
(set_attr "cc" "clobber")])
|| register_operand (operands[1], SImode))"
"*
{
- int rn = -1;
+ unsigned int rn = -1;
switch (which_alternative)
{
case 0:
"*
{
/* Copy of the movsi stuff. */
- int rn = -1;
+ unsigned int rn = -1;
switch (which_alternative)
{
case 0:
(set_attr "cc" "clobber")])
(define_insn "movsi_h8300hs"
- [(set (match_operand:SI 0 "general_operand_dst" "=r,r,r,r,m,<,r,*a,*a,r")
- (match_operand:SI 1 "general_operand_src" "I,r,i,m,r,r,>,I,r,*a"))]
+ [(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)
&& (register_operand (operands[0], SImode)
|| register_operand (operands[1], SImode))
}
return \"mov.l %S1,%S0\";
}"
- [(set_attr "length" "2,2,6,10,10,4,4,2,6,4")
+ [(set_attr "length" "2,2,6,4,4,10,10,2,6,4")
(set_attr "cc" "set_zn,set_znv,clobber,set_znv,set_znv,set_znv,set_znv,none_0hit,none_0hit,set_znv")])
(define_insn "movsf_h8300h"
[(set_attr "length" "2")
(set_attr "cc" "set_zn")])
-(define_insn ""
- [(set (cc0) (zero_extract:SI (match_operand:QI 0 "bit_memory_operand" "r,U")
+(define_insn "*tst_extzv_bitqi_1_n"
+ [(set (cc0) (zero_extract:SI (match_operand:QI 0 "bit_operand" "r,U")
(const_int 1)
(match_operand 1 "const_int_operand" "n,n")))]
- "TARGET_H8300H || TARGET_H8300S"
+ "(TARGET_H8300H || TARGET_H8300S)
+ && INTVAL (operands[1]) != 7"
"btst %Z1,%Y0"
[(set_attr "length" "2,8")
(set_attr "cc" "set_zn,set_zn")])
+(define_insn_and_split "*tst_extzv_memqi_1_n"
+ [(set (cc0) (zero_extract:SI (match_operand:QI 0 "memory_operand" "m")
+ (const_int 1)
+ (match_operand 1 "const_int_operand" "n")))
+ (clobber (match_scratch:QI 2 "=&r"))]
+ "(TARGET_H8300H || TARGET_H8300S)
+ && !EXTRA_CONSTRAINT (operands[0], 'U')
+ && INTVAL (operands[1]) != 7"
+ "#"
+ "&& reload_completed"
+ [(set (match_dup 2)
+ (match_dup 0))
+ (set (cc0) (zero_extract:SI (match_dup 2)
+ (const_int 1)
+ (match_dup 1)))]
+ "")
+
(define_insn ""
[(set (cc0) (zero_extract:SI (match_operand:SI 0 "register_operand" "r")
(const_int 1)
(define_insn "cmpqi"
[(set (cc0)
- (compare:QI (match_operand:QI 0 "register_operand" "r")
- (match_operand:QI 1 "nonmemory_operand" "rn")))]
+ (compare (match_operand:QI 0 "register_operand" "r")
+ (match_operand:QI 1 "nonmemory_operand" "rn")))]
""
"cmp.b %X1,%X0"
[(set_attr "length" "2")
(define_expand "cmphi"
[(set (cc0)
- (compare:HI (match_operand:HI 0 "register_operand" "")
- (match_operand:HI 1 "nonmemory_operand" "")))]
+ (compare (match_operand:HI 0 "register_operand" "")
+ (match_operand:HI 1 "nonmemory_operand" "")))]
""
"
{
operands[1] = force_reg (HImode, operands[1]);
}")
-(define_insn ""
+(define_insn "*cmphi_h8300"
[(set (cc0)
- (compare:HI (match_operand:HI 0 "register_operand" "r")
- (match_operand:HI 1 "register_operand" "r")))]
+ (compare (match_operand:HI 0 "register_operand" "r")
+ (match_operand:HI 1 "register_operand" "r")))]
"TARGET_H8300"
"cmp.w %T1,%T0"
[(set_attr "length" "2")
(set_attr "cc" "compare")])
-(define_insn ""
+(define_insn "*cmphi_h8300hs"
[(set (cc0)
- (compare:HI (match_operand:HI 0 "register_operand" "r,r")
- (match_operand:HI 1 "nonmemory_operand" "r,n")))]
+ (compare (match_operand:HI 0 "register_operand" "r,r")
+ (match_operand:HI 1 "nonmemory_operand" "r,n")))]
"TARGET_H8300H || TARGET_H8300S"
"cmp.w %T1,%T0"
[(set_attr "length" "2,4")
(define_insn "cmpsi"
[(set (cc0)
- (compare:SI (match_operand:SI 0 "register_operand" "r,r")
- (match_operand:SI 1 "nonmemory_operand" "r,i")))]
+ (compare (match_operand:SI 0 "register_operand" "r,r")
+ (match_operand:SI 1 "nonmemory_operand" "r,i")))]
"TARGET_H8300H || TARGET_H8300S"
"cmp.l %S1,%S0"
[(set_attr "length" "2,6")
""
"")
-(define_insn ""
- [(set (match_operand:HI 0 "register_operand" "=r,r,r,r,&r")
- (plus:HI (match_operand:HI 1 "register_operand" "%0,0,0,0,g")
- (match_operand:HI 2 "nonmemory_operand" "L,N,n,r,r")))]
+(define_insn "*addhi3_h8300"
+ [(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 "nonmemory_operand" "L,N,J,n,r")))]
"TARGET_H8300"
"@
adds %2,%T0
subs %G2,%T0
+ add.b %t2,%t0
add.b %s2,%s0\;addx %t2,%t0
- add.w %T2,%T0
- mov.w %T1,%T0\;add.w %T2,%T0"
- [(set_attr "length" "2,2,4,2,6")
- (set_attr "cc" "none_0hit,none_0hit,clobber,set_zn,set_zn")])
+ add.w %T2,%T0"
+ [(set_attr "length" "2,2,2,4,2")
+ (set_attr "cc" "none_0hit,none_0hit,clobber,clobber,set_zn")])
-(define_insn ""
- [(set (match_operand:HI 0 "register_operand" "=r,r,r,r")
- (plus:HI (match_operand:HI 1 "register_operand" "%0,0,0,0")
- (match_operand:HI 2 "nonmemory_operand" "L,N,n,r")))]
+;; This splitter is very important to make the stack adjustment
+;; interrupt-safe. The combination of add.b and addx is unsafe!
+;;
+;; We apply this split after the peephole2 pass so that we won't end
+;; up creating too many adds/subs when a scratch register is
+;; available, which is actually a common case because stack unrolling
+;; tends to happen immediately after a function call.
+
+(define_split
+ [(set (match_operand:HI 0 "stack_pointer_operand" "")
+ (plus:HI (match_dup 0)
+ (match_operand 1 "const_int_gt_2_operand" "")))]
+ "TARGET_H8300 && flow2_completed"
+ [(const_int 0)]
+ "split_adds_subs (HImode, operands); DONE;")
+
+(define_peephole2
+ [(match_scratch:HI 2 "r")
+ (set (match_operand:HI 0 "stack_pointer_operand" "")
+ (plus:HI (match_dup 0)
+ (match_operand:HI 1 "const_int_ge_8_operand" "")))]
+ "TARGET_H8300"
+ [(set (match_dup 2)
+ (match_dup 1))
+ (set (match_dup 0)
+ (plus:HI (match_dup 0)
+ (match_dup 2)))]
+ "")
+
+(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 "nonmemory_operand" "L,N,J,n,r")))]
"TARGET_H8300H || TARGET_H8300S"
"@
adds %2,%S0
subs %G2,%S0
+ add.b %t2,%t0
add.w %T2,%T0
add.w %T2,%T0"
- [(set_attr "length" "2,2,4,2")
- (set_attr "cc" "none_0hit,none_0hit,set_zn,set_zn")])
+ [(set_attr "length" "2,2,2,4,2")
+ (set_attr "cc" "none_0hit,none_0hit,clobber,set_zn,set_zn")])
+
+(define_insn "*addhi3_incdec"
+ [(set (match_operand:HI 0 "register_operand" "=r,r")
+ (unspec:HI [(match_operand:HI 1 "register_operand" "0,0")
+ (match_operand:HI 2 "incdec_operand" "M,O")]
+ UNSPEC_INCDEC))]
+ "TARGET_H8300H || TARGET_H8300S"
+ "@
+ inc.w %2,%T0
+ dec.w %G2,%T0"
+ [(set_attr "length" "2,2")
+ (set_attr "cc" "set_zn,set_zn")])
(define_split
[(set (match_operand:HI 0 "register_operand" "")
"")
(define_insn "addsi_h8300"
- [(set (match_operand:SI 0 "register_operand" "=r,r,&r")
- (plus:SI (match_operand:SI 1 "register_operand" "%0,0,r")
- (match_operand:SI 2 "nonmemory_operand" "n,r,r")))]
+ [(set (match_operand:SI 0 "register_operand" "=r,r")
+ (plus:SI (match_operand:SI 1 "register_operand" "%0,0")
+ (match_operand:SI 2 "nonmemory_operand" "n,r")))]
"TARGET_H8300"
- "@
- add %w2,%w0\;addx %x2,%x0\;addx %y2,%y0\;addx %z2,%z0
- add.w %f2,%f0\;addx %y2,%y0\;addx %z2,%z0
- mov.w %f1,%f0\;mov.w %e1,%e0\;add.w %f2,%f0\;addx %y2,%y0\;addx %z2,%z0"
- [(set_attr "length" "8,6,10")
- (set_attr "cc" "clobber")])
+ "* return output_plussi (operands);"
+ [(set (attr "length")
+ (symbol_ref "compute_plussi_length (operands)"))
+ (set (attr "cc")
+ (symbol_ref "compute_plussi_cc (operands)"))])
(define_insn "addsi_h8300h"
- [(set (match_operand:SI 0 "register_operand" "=r,r,r,r")
- (plus:SI (match_operand:SI 1 "register_operand" "%0,0,0,0")
- (match_operand:SI 2 "nonmemory_operand" "L,N,i,r")))]
+ [(set (match_operand:SI 0 "register_operand" "=r,r")
+ (plus:SI (match_operand:SI 1 "register_operand" "%0,0")
+ (match_operand:SI 2 "nonmemory_operand" "i,r")))]
+ "TARGET_H8300H || TARGET_H8300S"
+ "* return output_plussi (operands);"
+ [(set (attr "length")
+ (symbol_ref "compute_plussi_length (operands)"))
+ (set (attr "cc")
+ (symbol_ref "compute_plussi_cc (operands)"))])
+
+(define_insn "*addsi3_incdec"
+ [(set (match_operand:SI 0 "register_operand" "=r,r")
+ (unspec:SI [(match_operand:SI 1 "register_operand" "0,0")
+ (match_operand:SI 2 "incdec_operand" "M,O")]
+ UNSPEC_INCDEC))]
"TARGET_H8300H || TARGET_H8300S"
"@
- adds %2,%S0
- subs %G2,%S0
- add.l %S2,%S0
- add.l %S2,%S0"
- [(set_attr "length" "2,2,6,2")
- (set_attr "cc" "none_0hit,none_0hit,set_zn,set_zn")])
+ inc.l %2,%S0
+ dec.l %G2,%S0"
+ [(set_attr "length" "2,2")
+ (set_attr "cc" "set_zn,set_zn")])
(define_split
[(set (match_operand:SI 0 "register_operand" "")
(match_operand:QI 3 "single_one_operand" "n"))
(match_operand:QI 1 "register_operand" "0")))]
""
- "bld\\t%V3,%X2\;bst\\t%V3,%X0"
- [(set_attr "length" "4")
+ "bld\\t%V3,%X2\;bor\\t%V3,%X0\;bst\\t%V3,%X0"
+ [(set_attr "length" "6")
(set_attr "cc" "clobber")])
(define_insn "*andorhi3"
if (INTVAL (operands[3]) > 128)
{
operands[3] = GEN_INT (INTVAL (operands[3]) >> 8);
- return \"bld\\t%V3,%t2\;bst\\t%V3,%t0\";
+ return \"bld\\t%V3,%t2\;bor\\t%V3,%t0\;bst\\t%V3,%t0\";
}
- return \"bld\\t%V3,%s2\;bst\\t%V3,%s0\";
+ return \"bld\\t%V3,%s2\;bor\\t%V3,%s0\;bst\\t%V3,%s0\";
}"
- [(set_attr "length" "4")
+ [(set_attr "length" "6")
(set_attr "cc" "clobber")])
(define_insn "*andorsi3"
if (INTVAL (operands[3]) > 128)
{
operands[3] = GEN_INT (INTVAL (operands[3]) >> 8);
- return \"bld\\t%V3,%x2\;bst\\t%V3,%x0\";
+ return \"bld\\t%V3,%x2\;bor\\t%V3,%x0\;bst\\t%V3,%x0\";
}
- return \"bld\\t%V3,%w2\;bst\\t%V3,%w0\";
+ return \"bld\\t%V3,%w2\;bor\\t%V3,%w0\;bst\\t%V3,%w0\";
}"
- [(set_attr "length" "4")
+ [(set_attr "length" "6")
+ (set_attr "cc" "clobber")])
+
+(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")
(set_attr "cc" "clobber")])
(define_expand "andsi3"
[(set_attr "length" "2")
(set_attr "cc" "set_zn")])
+(define_expand "negsf2"
+ [(set (match_operand:SF 0 "register_operand" "")
+ (neg:SF (match_operand:SF 1 "register_operand" "")))]
+ ""
+ "")
+
+(define_insn "*negsf2_h8300"
+ [(set (match_operand:SF 0 "register_operand" "=r")
+ (neg:SF (match_operand:SF 1 "register_operand" "0")))]
+ "TARGET_H8300"
+ "xor.b\\t#128,%z0"
+ [(set_attr "cc" "clobber")
+ (set_attr "length" "2")])
+
+(define_insn "*negsf2_h8300hs"
+ [(set (match_operand:SF 0 "register_operand" "=r")
+ (neg:SF (match_operand:SF 1 "register_operand" "0")))]
+ "TARGET_H8300H || TARGET_H8300S"
+ "xor.w\\t#32768,%e0"
+ [(set_attr "cc" "clobber")
+ (set_attr "length" "4")])
+\f
+;; ----------------------------------------------------------------------
+;; ABSOLUTE VALUE INSTRUCTIONS
+;; ----------------------------------------------------------------------
+
+(define_expand "abssf2"
+ [(set (match_operand:SF 0 "register_operand" "")
+ (abs:SF (match_operand:SF 1 "register_operand" "")))]
+ ""
+ "")
+
+(define_insn "*abssf2_h8300"
+ [(set (match_operand:SF 0 "register_operand" "=r")
+ (abs:SF (match_operand:SF 1 "register_operand" "0")))]
+ "TARGET_H8300"
+ "and.b\\t#127,%z0"
+ [(set_attr "cc" "clobber")
+ (set_attr "length" "2")])
+
+(define_insn "*abssf2_h8300hs"
+ [(set (match_operand:SF 0 "register_operand" "=r")
+ (abs:SF (match_operand:SF 1 "register_operand" "0")))]
+ "TARGET_H8300H || TARGET_H8300S"
+ "and.w\\t#32767,%e0"
+ [(set_attr "cc" "clobber")
+ (set_attr "length" "4")])
+\f
;; ----------------------------------------------------------------------
;; NOT INSTRUCTIONS
;; ----------------------------------------------------------------------
[(set_attr "cc" "none")
(set_attr "length" "2")])
+(define_insn "tablejump_normal_mode"
+ [(set (pc) (match_operand:HI 0 "register_operand" "r"))
+ (use (label_ref (match_operand 1 "" "")))]
+ "(TARGET_H8300H || TARGET_H8300S) && TARGET_NORMAL_MODE"
+ "jmp @%S0"
+ [(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_attr "cc" "none")
(set_attr "length" "2")])
+(define_insn "indirect_jump_normal_mode"
+ [(set (pc) (match_operand:HI 0 "jump_address_operand" "Vr"))]
+ "(TARGET_H8300H || TARGET_H8300S) && TARGET_NORMAL_MODE"
+ "jmp @%S0"
+ [(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.
(set_attr "length" "2")])
\f
;; ----------------------------------------------------------------------
+;; PROLOGUE/EPILOGUE-RELATED INSTRUCTIONS
+;; ----------------------------------------------------------------------
+
+(define_expand "push_h8300"
+ [(set (mem:HI (pre_dec:HI (reg:HI SP_REG)))
+ (match_operand:HI 0 "register_operand" "=r"))]
+
+ "TARGET_H8300"
+ "")
+
+(define_expand "push_h8300hs"
+ [(set (mem:SI (pre_dec:SI (reg:SI SP_REG)))
+ (match_operand:SI 0 "register_operand" "=r"))]
+ "TARGET_H8300H && TARGET_H8300S"
+ "")
+
+(define_expand "pop_h8300"
+ [(set (match_operand:HI 0 "register_operand" "=r")
+ (mem:HI (post_inc:HI (reg:HI SP_REG))))]
+ "TARGET_H8300"
+ "")
+
+(define_expand "pop_h8300hs"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (mem:SI (post_inc:SI (reg:SI SP_REG))))]
+ "TARGET_H8300H && TARGET_H8300S"
+ "")
+
+(define_insn "stm_h8300s_2"
+ [(parallel
+ [(set (reg:SI SP_REG)
+ (plus:SI (reg:SI SP_REG) (const_int -8)))
+ (set (mem:SI (plus:SI (reg:SI SP_REG) (const_int -4)))
+ (match_operand:SI 0 "register_operand" ""))
+ (set (mem:SI (plus:SI (reg:SI SP_REG) (const_int -8)))
+ (match_operand:SI 1 "register_operand" ""))])]
+ "TARGET_H8300S
+ && ((REGNO (operands[0]) == 0 && REGNO (operands[1]) == 1)
+ || (REGNO (operands[0]) == 2 && REGNO (operands[1]) == 3)
+ || (REGNO (operands[0]) == 4 && REGNO (operands[1]) == 5))"
+ "stm.l\\t%S0-%S1,@-er7"
+ [(set_attr "cc" "none")
+ (set_attr "length" "4")])
+
+(define_insn "stm_h8300s_3"
+ [(parallel
+ [(set (reg:SI SP_REG)
+ (plus:SI (reg:SI SP_REG) (const_int -12)))
+ (set (mem:SI (plus:SI (reg:SI SP_REG) (const_int -4)))
+ (match_operand:SI 0 "register_operand" ""))
+ (set (mem:SI (plus:SI (reg:SI SP_REG) (const_int -8)))
+ (match_operand:SI 1 "register_operand" ""))
+ (set (mem:SI (plus:SI (reg:SI SP_REG) (const_int -12)))
+ (match_operand:SI 2 "register_operand" ""))])]
+ "TARGET_H8300S
+ && ((REGNO (operands[0]) == 0
+ && REGNO (operands[1]) == 1
+ && REGNO (operands[2]) == 2)
+ || (REGNO (operands[0]) == 4
+ && REGNO (operands[1]) == 5
+ && REGNO (operands[2]) == 6))"
+ "stm.l\\t%S0-%S2,@-er7"
+ [(set_attr "cc" "none")
+ (set_attr "length" "4")])
+
+(define_insn "stm_h8300s_4"
+ [(parallel
+ [(set (reg:SI SP_REG)
+ (plus:SI (reg:SI SP_REG) (const_int -16)))
+ (set (mem:SI (plus:SI (reg:SI SP_REG) (const_int -4)))
+ (match_operand:SI 0 "register_operand" ""))
+ (set (mem:SI (plus:SI (reg:SI SP_REG) (const_int -8)))
+ (match_operand:SI 1 "register_operand" ""))
+ (set (mem:SI (plus:SI (reg:SI SP_REG) (const_int -12)))
+ (match_operand:SI 2 "register_operand" ""))
+ (set (mem:SI (plus:SI (reg:SI SP_REG) (const_int -16)))
+ (match_operand:SI 3 "register_operand" ""))])]
+ "TARGET_H8300S
+ && REGNO (operands[0]) == 0
+ && REGNO (operands[1]) == 1
+ && REGNO (operands[2]) == 2
+ && REGNO (operands[3]) == 3"
+ "stm.l\\t%S0-%S3,@-er7"
+ [(set_attr "cc" "none")
+ (set_attr "length" "4")])
+
+(define_insn "ldm_h8300s_2"
+ [(parallel
+ [(set (reg:SI SP_REG)
+ (plus:SI (reg:SI SP_REG) (const_int 8)))
+ (set (mem:SI (plus:SI (reg:SI SP_REG) (const_int 4)))
+ (match_operand:SI 0 "register_operand" ""))
+ (set (mem:SI (reg:SI SP_REG))
+ (match_operand:SI 1 "register_operand" ""))])]
+ "TARGET_H8300S
+ && ((REGNO (operands[0]) == 0 && REGNO (operands[1]) == 1)
+ || (REGNO (operands[0]) == 2 && REGNO (operands[1]) == 3)
+ || (REGNO (operands[0]) == 4 && REGNO (operands[1]) == 5))"
+ "ldm.l\\t@er7+,%S0-%S1"
+ [(set_attr "cc" "none")
+ (set_attr "length" "4")])
+
+(define_insn "ldm_h8300s_3"
+ [(parallel
+ [(set (reg:SI SP_REG)
+ (plus:SI (reg:SI SP_REG) (const_int 12)))
+ (set (mem:SI (plus:SI (reg:SI SP_REG) (const_int 8)))
+ (match_operand:SI 0 "register_operand" ""))
+ (set (mem:SI (plus:SI (reg:SI SP_REG) (const_int 4)))
+ (match_operand:SI 1 "register_operand" ""))
+ (set (mem:SI (reg:SI SP_REG))
+ (match_operand:SI 2 "register_operand" ""))])]
+ "TARGET_H8300S
+ && ((REGNO (operands[0]) == 0
+ && REGNO (operands[1]) == 1
+ && REGNO (operands[2]) == 2)
+ || (REGNO (operands[0]) == 4
+ && REGNO (operands[1]) == 5
+ && REGNO (operands[2]) == 6))"
+ "ldm.l\\t@er7+,%S0-%S2"
+ [(set_attr "cc" "none")
+ (set_attr "length" "4")])
+
+(define_insn "ldm_h8300s_4"
+ [(parallel
+ [(set (reg:SI SP_REG)
+ (plus:SI (reg:SI SP_REG) (const_int 16)))
+ (set (mem:SI (plus:SI (reg:SI SP_REG) (const_int 12)))
+ (match_operand:SI 0 "register_operand" ""))
+ (set (mem:SI (plus:SI (reg:SI SP_REG) (const_int 8)))
+ (match_operand:SI 1 "register_operand" ""))
+ (set (mem:SI (plus:SI (reg:SI SP_REG) (const_int 4)))
+ (match_operand:SI 2 "register_operand" ""))
+ (set (mem:SI (reg:SI SP_REG))
+ (match_operand:SI 3 "register_operand" ""))])]
+ "TARGET_H8300S
+ && REGNO (operands[0]) == 0
+ && REGNO (operands[1]) == 1
+ && REGNO (operands[2]) == 2
+ && REGNO (operands[3]) == 3"
+ "ldm.l\\t@er7+,%S0-%S3"
+ [(set_attr "cc" "none")
+ (set_attr "length" "4")])
+
+(define_expand "return"
+ [(return)]
+ "h8300_can_use_return_insn_p ()"
+ "")
+
+(define_insn "*return_1"
+ [(return)]
+ "reload_completed"
+ "*
+{
+ if (h8300_current_function_interrupt_function_p ())
+ return \"rte\";
+ else
+ return \"rts\";
+}"
+ [(set_attr "cc" "none")
+ (set_attr "length" "2")])
+
+(define_expand "prologue"
+ [(const_int 0)]
+ ""
+ "h8300_expand_prologue (); DONE;")
+
+(define_expand "epilogue"
+ [(return)]
+ ""
+ "h8300_expand_epilogue ();")
+
+(define_insn "monitor_prologue"
+ [(unspec_volatile [(const_int 0)] UNSPEC_MONITOR)]
+ ""
+ "*
+{
+ if (TARGET_H8300)
+ return \"subs\\t#2,r7\;mov.w\\tr0,@-r7\;stc\\tccr,r0l\;mov.b\tr0l,@(2,r7)\;mov.w\\t@r7+,r0\;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)
+ 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\";
+ abort ();
+}"
+ [(set_attr "length" "20")
+ (set_attr "cc" "clobber")])
+\f
+;; ----------------------------------------------------------------------
;; EXTEND INSTRUCTIONS
;; ----------------------------------------------------------------------
""
"")
-(define_insn ""
+(define_insn "*zero_extendqihi2_h8300"
[(set (match_operand:HI 0 "register_operand" "=r,r")
(zero_extend:HI (match_operand:QI 1 "general_operand_src" "0,g>")))]
"TARGET_H8300"
"@
mov.b #0,%t0
- mov.b %R1,%s0\;mov.b #0,%t0"
+ #"
[(set_attr "length" "2,10")
(set_attr "cc" "clobber,clobber")])
-(define_insn ""
+(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>")))]
"TARGET_H8300H || TARGET_H8300S"
"@
extu.w %T0
- mov.b %R1,%s0\;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]));")
+
;; The compiler can synthesize a H8/300H variant of this which is
;; just as efficient as one that we'd create
(define_insn "zero_extendqisi2"
"@
mov.b #0,%x0\;sub.w %e0,%e0
mov.b %R1,%w0\;mov.b #0,%x0\;sub.w %e0,%e0"
- [(set_attr "length" "4,6")
+ [(set_attr "length" "4,8")
(set_attr "cc" "clobber,clobber")])
(define_expand "zero_extendhisi2"
"")
;; %e prints the high part of a CONST_INT, not the low part. Arggh.
-(define_insn ""
+(define_insn "*zero_extendhisi2_h8300"
[(set (match_operand:SI 0 "register_operand" "=r,r,r")
(zero_extend:SI (match_operand:HI 1 "general_operand_src" "0,i,g>")))]
"TARGET_H8300"
sub.w %e0,%e0
mov.w %f1,%f0\;sub.w %e0,%e0
mov.w %e1,%f0\;sub.w %e0,%e0"
- [(set_attr "length" "2,4,4")
+ [(set_attr "length" "2,4,6")
(set_attr "cc" "clobber,clobber,clobber")])
(define_insn ""
[(set_attr "length" "2")
(set_attr "cc" "set_znv")])
-;; The compiler can synthesize a H8/300H variant of this which is
-;; just as efficient as one that we'd create
-(define_insn "extendqisi2"
+(define_expand "extendqisi2"
[(set (match_operand:SI 0 "register_operand" "=r,r")
+ (sign_extend:SI (match_operand:QI 1 "register_operand" "")))]
+ ""
+ "")
+
+(define_insn "*extendqisi2_h8300"
+ [(set (match_operand:SI 0 "register_operand" "")
(sign_extend:SI (match_operand:QI 1 "general_operand_src" "0,g>")))]
"TARGET_H8300"
"@
bld #7,%w0\;subx %x0,%x0\;subx %y0,%y0\;subx %z0,%z0
mov.b %R1,%w0\;bld #7,%w0\;subx %x0,%x0\;subx %y0,%y0\;subx %z0,%z0"
- [(set_attr "length" "8,10")
+ [(set_attr "length" "8,12")
(set_attr "cc" "clobber,clobber")])
+;; The following pattern is needed because without the pattern, the
+;; combiner would split (sign_extend:SI (reg:QI)) into 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_H8300H || TARGET_H8300S)"
+ "#"
+ "&& 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_expand "extendhisi2"
[(set (match_operand:SI 0 "register_operand" "")
(sign_extend:SI (match_operand:HI 1 "register_operand" "")))]
""
"")
-(define_insn ""
+(define_insn "*extendhisi2_h8300"
[(set (match_operand:SI 0 "register_operand" "=r,r")
(sign_extend:SI (match_operand:HI 1 "general_operand_src" "0,g>")))]
"TARGET_H8300"
"@
bld #7,%x0\;subx %y0,%y0\;subx %z0,%z0
mov.w %T1,%f0\;bld #7,%x0\;subx %y0,%y0\;subx %z0,%z0"
- [(set_attr "length" "6,8")
+ [(set_attr "length" "6,10")
(set_attr "cc" "clobber,clobber")])
(define_insn ""
(ashift:QI (match_operand:QI 1 "register_operand" "")
(match_operand:QI 2 "nonmemory_operand" "")))]
""
- "if (expand_a_shift (QImode, ASHIFT, operands)) DONE; else FAIL;")
+ "expand_a_shift (QImode, ASHIFT, operands); DONE;")
(define_expand "ashrqi3"
[(set (match_operand:QI 0 "register_operand" "")
(ashiftrt:QI (match_operand:QI 1 "register_operand" "")
(match_operand:QI 2 "nonmemory_operand" "")))]
""
- "if (expand_a_shift (QImode, ASHIFTRT, operands)) DONE; else FAIL;")
+ "expand_a_shift (QImode, ASHIFTRT, operands); DONE;")
(define_expand "lshrqi3"
[(set (match_operand:QI 0 "register_operand" "")
(lshiftrt:QI (match_operand:QI 1 "register_operand" "")
(match_operand:QI 2 "nonmemory_operand" "")))]
""
- "if (expand_a_shift (QImode, LSHIFTRT, operands)) DONE; else FAIL;")
+ "expand_a_shift (QImode, LSHIFTRT, operands); DONE;")
(define_insn ""
[(set (match_operand:QI 0 "register_operand" "=r,r")
(ashift:HI (match_operand:HI 1 "nonmemory_operand" "")
(match_operand:QI 2 "nonmemory_operand" "")))]
""
- "if (expand_a_shift (HImode, ASHIFT, operands)) DONE; else FAIL;")
+ "expand_a_shift (HImode, ASHIFT, operands); DONE;")
(define_expand "lshrhi3"
[(set (match_operand:HI 0 "register_operand" "")
(lshiftrt:HI (match_operand:HI 1 "general_operand" "")
(match_operand:QI 2 "nonmemory_operand" "")))]
""
- "if (expand_a_shift (HImode, LSHIFTRT, operands)) DONE; else FAIL;")
+ "expand_a_shift (HImode, LSHIFTRT, operands); DONE;")
(define_expand "ashrhi3"
[(set (match_operand:HI 0 "register_operand" "")
(ashiftrt:HI (match_operand:HI 1 "register_operand" "")
(match_operand:QI 2 "nonmemory_operand" "")))]
""
- "if (expand_a_shift (HImode, ASHIFTRT, operands)) DONE; else FAIL;")
+ "expand_a_shift (HImode, ASHIFTRT, operands); DONE;")
(define_insn ""
[(set (match_operand:HI 0 "register_operand" "=r,r")
(ashift:SI (match_operand:SI 1 "general_operand" "")
(match_operand:QI 2 "nonmemory_operand" "")))]
""
- "if (expand_a_shift (SImode, ASHIFT, operands)) DONE; else FAIL;")
+ "expand_a_shift (SImode, ASHIFT, operands); DONE;")
(define_expand "lshrsi3"
[(set (match_operand:SI 0 "register_operand" "")
(lshiftrt:SI (match_operand:SI 1 "general_operand" "")
(match_operand:QI 2 "nonmemory_operand" "")))]
""
- "if (expand_a_shift (SImode, LSHIFTRT, operands)) DONE; else FAIL;")
+ "expand_a_shift (SImode, LSHIFTRT, operands); DONE;")
(define_expand "ashrsi3"
[(set (match_operand:SI 0 "register_operand" "")
(ashiftrt:SI (match_operand:SI 1 "general_operand" "")
(match_operand:QI 2 "nonmemory_operand" "")))]
""
- "if (expand_a_shift (SImode, ASHIFTRT, operands)) DONE; else FAIL;")
+ "expand_a_shift (SImode, ASHIFTRT, operands); DONE;")
(define_insn ""
[(set (match_operand:SI 0 "register_operand" "=r,r")
[(set (attr "length")
(symbol_ref "compute_a_shift_length (insn, operands)"))
(set_attr "cc" "clobber")])
+
+;; Split a variable shift into a loop. If the register containing
+;; the shift count dies, then we just use that register.
+
+(define_split
+ [(parallel
+ [(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" ""))])]
+ "flow2_completed
+ && find_regno_note (insn, REG_DEAD, REGNO (operands[1]))"
+ [(set (cc0)
+ (match_dup 1))
+ (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)
+ (match_dup 1))
+ (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
+ [(parallel
+ [(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" ""))])]
+ "flow2_completed
+ && !find_regno_note (insn, REG_DEAD, REGNO (operands[1]))"
+ [(set (match_dup 3)
+ (match_dup 1))
+ (set (cc0)
+ (match_dup 3))
+ (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)
+ (match_dup 3))
+ (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 ();")
\f
;; ----------------------------------------------------------------------
;; ROTATIONS
;; Normal loads with a 32bit destination.
;;
-(define_insn ""
+(define_insn "*extzv_1_r_h8300"
[(set (match_operand:SI 0 "register_operand" "=&r")
(zero_extract:SI (match_operand:HI 1 "register_operand" "r")
(const_int 1)
&& INTVAL (operands[2]) < 16"
"* return output_simode_bld (0, operands);"
[(set_attr "cc" "clobber")
- (set_attr "length" "6")])
+ (set_attr "length" "8")])
-(define_insn ""
+(define_insn "*extzv_1_r_h8300hs"
[(set (match_operand:SI 0 "register_operand" "=r")
(zero_extract:SI (match_operand:SI 1 "register_operand" "r")
(const_int 1)
&& INTVAL (operands[2]) < 16"
"* return output_simode_bld (0, operands);"
[(set_attr "cc" "clobber")
- (set_attr "length" "6")])
+ (set_attr "length" "8")])
;;
;; Inverted loads with a 32bit destination.
;;
-(define_insn ""
+(define_insn "*extzv_1_r_inv_h8300"
[(set (match_operand:SI 0 "register_operand" "=&r")
(zero_extract:SI (xor:HI (match_operand:HI 1 "register_operand" "r")
(match_operand:HI 3 "const_int_operand" "n"))
&& (1 << INTVAL (operands[2])) == INTVAL (operands[3])"
"* return output_simode_bld (1, operands);"
[(set_attr "cc" "clobber")
- (set_attr "length" "6")])
+ (set_attr "length" "8")])
-(define_insn ""
+(define_insn "*extzv_1_r_inv_h8300hs"
[(set (match_operand:SI 0 "register_operand" "=r")
(zero_extract:SI (xor:SI (match_operand:SI 1 "register_operand" "r")
(match_operand 3 "const_int_operand" "n"))
&& (1 << INTVAL (operands[2])) == INTVAL (operands[3])"
"* return output_simode_bld (1, operands);"
[(set_attr "cc" "clobber")
- (set_attr "length" "6")])
+ (set_attr "length" "8")])
(define_expand "insv"
[(set (zero_extract:HI (match_operand:HI 0 "general_operand" "")
;; COMBINE PATTERNS
;; -----------------------------------------------------------------
-(define_insn ""
- [(set (match_operand:HI 0 "register_operand" "=r")
- (ior:HI (zero_extend:HI (match_operand:QI 1 "register_operand" "r"))
- (match_operand:HI 2 "register_operand" "0")))]
- "REG_P (operands[0])
- && REG_P (operands[1])
- && REGNO (operands[0]) != REGNO (operands[1])"
- "or\\t%X1,%s0"
- [(set_attr "cc" "clobber")
- (set_attr "length" "2")])
+;; extzv:SI
-(define_insn ""
+(define_insn "*extzv_8_8"
[(set (match_operand:SI 0 "register_operand" "=r")
- (ior:SI (zero_extend:SI (match_operand:HI 1 "register_operand" "r"))
- (match_operand:SI 2 "register_operand" "0")))]
- "(TARGET_H8300H || TARGET_H8300S)
- && REG_P (operands[0])
- && REG_P (operands[1])
- && (REGNO (operands[0]) != REGNO (operands[1]))"
- "or.w\\t%T1,%f0"
- [(set_attr "cc" "clobber")
- (set_attr "length" "2")])
+ (zero_extract:SI (match_operand:SI 1 "register_operand" "r")
+ (const_int 8)
+ (const_int 8)))]
+ "TARGET_H8300H || TARGET_H8300S"
+ "mov.b\\t%x1,%w0\;extu.w\\t%f0\;extu.l\\t%S0"
+ [(set_attr "cc" "set_znv")
+ (set_attr "length" "6")])
-(define_insn ""
+(define_insn "*extzv_8_16"
[(set (match_operand:SI 0 "register_operand" "=r")
- (ior:SI (zero_extend:SI (match_operand:QI 1 "register_operand" "r"))
- (match_operand:SI 2 "register_operand" "0")))]
- "REG_P (operands[0])
- && REG_P (operands[1])
- && REGNO (operands[0]) != REGNO (operands[1])"
- "or\\t%X1,%w0"
- [(set_attr "cc" "clobber")
- (set_attr "length" "2")])
+ (zero_extract:SI (match_operand:SI 1 "register_operand" "r")
+ (const_int 8)
+ (const_int 16)))]
+ "TARGET_H8300H || TARGET_H8300S"
+ "mov.w\\t%e1,%f0\;extu.w\\t%f0\;extu.l\\t%S0"
+ [(set_attr "cc" "set_znv")
+ (set_attr "length" "6")])
-(define_insn ""
- [(set (match_operand:HI 0 "register_operand" "=r")
- (xor:HI (zero_extend:HI (match_operand:QI 1 "register_operand" "r"))
- (match_operand:HI 2 "register_operand" "0")))]
- "REG_P (operands[0])
- && REG_P (operands[1])
- && REGNO (operands[0]) != REGNO (operands[1])"
- "xor\\t%X1,%s0"
- [(set_attr "cc" "clobber")
- (set_attr "length" "2")])
+;; Extract the exponent of a float.
-(define_insn ""
+(define_insn_and_split "*extzv_8_23"
[(set (match_operand:SI 0 "register_operand" "=r")
- (xor:SI (zero_extend:SI (match_operand:HI 1 "register_operand" "r"))
- (match_operand:SI 2 "register_operand" "0")))]
- "(TARGET_H8300H || TARGET_H8300S)
- && REG_P (operands[0])
- && REG_P (operands[1])
- && (REGNO (operands[0]) != REGNO (operands[1]))"
- "xor.w\\t%T1,%f0"
- [(set_attr "cc" "clobber")
- (set_attr "length" "2")])
+ (zero_extract:SI (match_operand:SI 1 "register_operand" "0")
+ (const_int 8)
+ (const_int 23)))]
+ "(TARGET_H8300H || TARGET_H8300S)"
+ "#"
+ "&& 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))])]
+ "")
-(define_insn ""
+;; and:SI
+
+;; ((SImode) HImode) << 15
+
+(define_insn_and_split "*twoshifts_l16_r1"
[(set (match_operand:SI 0 "register_operand" "=r")
- (xor:SI (zero_extend:SI (match_operand:QI 1 "register_operand" "r"))
- (match_operand:SI 2 "register_operand" "0")))]
- "REG_P (operands[0])
- && REG_P (operands[1])
- && REGNO (operands[0]) != REGNO (operands[1])"
- "xor\\t%X1,%w0"
+ (and:SI (ashift:SI (match_operand:SI 1 "register_operand" "0")
+ (const_int 15))
+ (const_int 2147450880)))]
+ "(TARGET_H8300H || TARGET_H8300S)"
+ "#"
+ "&& 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"))]
+ "(TARGET_H8300H || TARGET_H8300S)
+ && INTVAL (operands[2]) <= 15
+ && INTVAL (operands[3]) == ((-1 << 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")))]
+ "(TARGET_H8300H || TARGET_H8300S)
+ && 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")
+ (set_attr "cc" "clobber")])
+
+(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)))]
+ "(TARGET_H8300H || TARGET_H8300S)"
+ "#"
+ "&& 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")))]
+ "TARGET_H8300H || TARGET_H8300S"
+ "add.w\\t%f1,%e0"
+ [(set_attr "length" "2")
+ (set_attr "cc" "clobber")])
+
+(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"))))]
+ "TARGET_H8300H || TARGET_H8300S"
+ "add.w\\t%e1,%f0\;xor.w\\t%e0,%e0\;rotxl.w\\t%e0,%e0"
+ [(set_attr "cc" "clobber")
+ (set_attr "length" "6")])
+
+;; ior:HI
+
+(define_insn "*iorhi3_zext"
+ [(set (match_operand:HI 0 "register_operand" "=r")
+ (ior:HI (zero_extend:HI (match_operand:QI 1 "register_operand" "r"))
+ (match_operand:HI 2 "register_operand" "0")))]
+ ""
+ "or\\t%X1,%s0"
[(set_attr "cc" "clobber")
(set_attr "length" "2")])
-(define_insn ""
+(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 "cc" "clobber")
+ (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 "cc" "clobber")
+ (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))))]
- "REG_P (operands[0])
- && REG_P (operands[2])
- && REGNO (operands[0]) != REGNO (operands[2])"
+ ""
"mov.b\\t%s2,%t0"
[(set_attr "cc" "clobber")
(set_attr "length" "2")])
-(define_insn ""
+;; ior:SI
+
+(define_insn "*iorsi3_zexthi"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (ior:SI (zero_extend:SI (match_operand:HI 1 "register_operand" "r"))
+ (match_operand:SI 2 "register_operand" "0")))]
+ "TARGET_H8300H || TARGET_H8300S"
+ "or.w\\t%T1,%f0"
+ [(set_attr "cc" "clobber")
+ (set_attr "length" "2")])
+
+(define_insn "*iorsi3_zextqi"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (ior:SI (zero_extend:SI (match_operand:QI 1 "register_operand" "r"))
+ (match_operand:SI 2 "register_operand" "0")))]
+ ""
+ "or\\t%X1,%w0"
+ [(set_attr "cc" "clobber")
+ (set_attr "length" "2")])
+
+(define_insn "*iorsi3_ashift_16"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (ior:SI (ashift:SI (match_operand:SI 1 "register_operand" "r")
+ (const_int 16))
+ (match_operand:SI 2 "register_operand" "0")))]
+ "TARGET_H8300H || TARGET_H8300S"
+ "or.w\\t%f1,%e0"
+ [(set_attr "cc" "clobber")
+ (set_attr "length" "2")])
+
+(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))))]
- "(TARGET_H8300H || TARGET_H8300S)
- && REG_P (operands[0])
- && REG_P (operands[2])
- && (REGNO (operands[0]) != REGNO (operands[2]))"
+ "TARGET_H8300H || TARGET_H8300S"
"mov.w\\t%f2,%e0"
[(set_attr "cc" "clobber")
(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))))]
+ "(TARGET_H8300H || TARGET_H8300S)"
+ "#"
+ "&& 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>"))))]
+ "TARGET_H8300H || TARGET_H8300S"
+ "mov.b\\t%X2,%w0"
+ [(set_attr "length" "2,8")
+ (set_attr "cc" "clobber,clobber")])
+
+(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")))]
+ "TARGET_H8300H || TARGET_H8300S"
+ "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_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")))]
+ "(TARGET_H8300H || TARGET_H8300S)"
+ "rotl.l\\t%S1\;rotr.l\\t%S1\;bor\\t#1,%w0\;bst\\t#1,%w0"
+ [(set_attr "length" "8")
+ (set_attr "cc" "clobber")])
+
+(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"))]
+ "(TARGET_H8300H || TARGET_H8300S)"
+ "*
+{
+ 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")
+ (set_attr "cc" "clobber")])
+
+;; 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"))]
+ "TARGET_H8300H || TARGET_H8300S"
+ "#")
+
+(define_split
+ [(parallel
+ [(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" ""))])]
+ "(TARGET_H8300H || TARGET_H8300S)
+ && flow2_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
+ [(parallel
+ [(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" ""))])]
+ "(TARGET_H8300H || TARGET_H8300S)
+ && flow2_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))))]
+ "TARGET_H8300H || TARGET_H8300S"
+ "shlr.l\\t%S0\;bor\\t#0,%w0\;bst\\t#0,%w0"
+ [(set_attr "length" "6")
+ (set_attr "cc" "clobber")])
+
+;; 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"))]
+ "TARGET_H8300H || TARGET_H8300S"
+ "#")
+
+(define_split
+ [(parallel
+ [(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" ""))])]
+ "(TARGET_H8300H || TARGET_H8300S)
+ && flow2_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
+ [(parallel
+ [(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" ""))])]
+ "(TARGET_H8300H || TARGET_H8300S)
+ && flow2_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]));")
+
+;; xor:HI
+
+(define_insn "*xorhi3_zextqi"
+ [(set (match_operand:HI 0 "register_operand" "=r")
+ (xor:HI (zero_extend:HI (match_operand:QI 1 "register_operand" "r"))
+ (match_operand:HI 2 "register_operand" "0")))]
+ ""
+ "xor\\t%X1,%s0"
+ [(set_attr "cc" "clobber")
+ (set_attr "length" "2")])
+
+;; xor:SI
+
+(define_insn "*xorsi3_zexthi"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (xor:SI (zero_extend:SI (match_operand:HI 1 "register_operand" "r"))
+ (match_operand:SI 2 "register_operand" "0")))]
+ "TARGET_H8300H || TARGET_H8300S"
+ "xor.w\\t%T1,%f0"
+ [(set_attr "cc" "clobber")
+ (set_attr "length" "2")])
+
+(define_insn "*xorsi3_zextqi"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (xor:SI (zero_extend:SI (match_operand:QI 1 "register_operand" "r"))
+ (match_operand:SI 2 "register_operand" "0")))]
+ ""
+ "xor\\t%X1,%w0"
+ [(set_attr "cc" "clobber")
+ (set_attr "length" "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)))]
+ "(TARGET_H8300H || TARGET_H8300S)"
+ "#"
+ "&& 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 ""
"TARGET_H8300H || TARGET_H8300S"
"mov.w\\t%e1,%f2\;mov.b\\t%w2,%R0"
[(set_attr "cc" "set_znv")
- (set_attr "length" "8")])
+ (set_attr "length" "10")])
(define_insn ""
[(set (match_operand:QI 0 "general_operand_dst" "=rm<")
"TARGET_H8300H || TARGET_H8300S"
"mov.w\\t%e1,%f2\;mov.b\\t%x2,%R0"
[(set_attr "cc" "set_znv")
- (set_attr "length" "8")])
+ (set_attr "length" "10")])
(define_insn_and_split ""
[(set (pc)
(label_ref (match_dup 1))
(pc)))]
"")
+\f
+;; -----------------------------------------------------------------
+;; PEEPHOLE PATTERNS
+;; -----------------------------------------------------------------
+
+;; Convert (A >> B) & C to (A & 255) >> B if C == 255 >> B.
+
+(define_peephole2
+ [(parallel
+ [(set (match_operand:HI 0 "register_operand" "")
+ (lshiftrt:HI (match_dup 0)
+ (match_operand:HI 1 "const_int_operand" "")))
+ (clobber (match_operand:HI 2 "" ""))])
+ (set (match_dup 0)
+ (and:HI (match_dup 0)
+ (match_operand:HI 3 "const_int_operand" "")))]
+ "INTVAL (operands[3]) == (255 >> INTVAL (operands[1]))"
+ [(set (match_dup 0)
+ (and:HI (match_dup 0)
+ (const_int 255)))
+ (parallel
+ [(set (match_dup 0)
+ (lshiftrt:HI (match_dup 0)
+ (match_dup 1)))
+ (clobber (match_dup 2))])]
+ "")
+
+;; Convert (A << B) & C to (A & 255) << B if C == 255 << B.
+
+(define_peephole2
+ [(parallel
+ [(set (match_operand:HI 0 "register_operand" "")
+ (ashift:HI (match_dup 0)
+ (match_operand:HI 1 "const_int_operand" "")))
+ (clobber (match_operand:HI 2 "" ""))])
+ (set (match_dup 0)
+ (and:HI (match_dup 0)
+ (match_operand:HI 3 "const_int_operand" "")))]
+ "INTVAL (operands[3]) == (255 << INTVAL (operands[1]))"
+ [(set (match_dup 0)
+ (and:HI (match_dup 0)
+ (const_int 255)))
+ (parallel
+ [(set (match_dup 0)
+ (ashift:HI (match_dup 0)
+ (match_dup 1)))
+ (clobber (match_dup 2))])]
+ "")
+
+;; Convert (A >> B) & C to (A & 255) >> B if C == 255 >> B.
+
+(define_peephole2
+ [(parallel
+ [(set (match_operand:SI 0 "register_operand" "")
+ (lshiftrt:SI (match_dup 0)
+ (match_operand:SI 1 "const_int_operand" "")))
+ (clobber (match_operand:SI 2 "" ""))])
+ (set (match_dup 0)
+ (and:SI (match_dup 0)
+ (match_operand:SI 3 "const_int_operand" "")))]
+ "INTVAL (operands[3]) == (255 >> INTVAL (operands[1]))"
+ [(set (match_dup 0)
+ (and:SI (match_dup 0)
+ (const_int 255)))
+ (parallel
+ [(set (match_dup 0)
+ (lshiftrt:SI (match_dup 0)
+ (match_dup 1)))
+ (clobber (match_dup 2))])]
+ "")
+
+;; Convert (A << B) & C to (A & 255) << B if C == 255 << B.
+
+(define_peephole2
+ [(parallel
+ [(set (match_operand:SI 0 "register_operand" "")
+ (ashift:SI (match_dup 0)
+ (match_operand:SI 1 "const_int_operand" "")))
+ (clobber (match_operand:SI 2 "" ""))])
+ (set (match_dup 0)
+ (and:SI (match_dup 0)
+ (match_operand:SI 3 "const_int_operand" "")))]
+ "INTVAL (operands[3]) == (255 << INTVAL (operands[1]))"
+ [(set (match_dup 0)
+ (and:SI (match_dup 0)
+ (const_int 255)))
+ (parallel
+ [(set (match_dup 0)
+ (ashift:SI (match_dup 0)
+ (match_dup 1)))
+ (clobber (match_dup 2))])]
+ "")
+
+;; Convert (A >> B) & C to (A & 65535) >> B if C == 65535 >> B.
+
+(define_peephole2
+ [(parallel
+ [(set (match_operand:SI 0 "register_operand" "")
+ (lshiftrt:SI (match_dup 0)
+ (match_operand:SI 1 "const_int_operand" "")))
+ (clobber (match_operand:SI 2 "" ""))])
+ (set (match_dup 0)
+ (and:SI (match_dup 0)
+ (match_operand:SI 3 "const_int_operand" "")))]
+ "INTVAL (operands[3]) == (65535 >> INTVAL (operands[1]))"
+ [(set (match_dup 0)
+ (and:SI (match_dup 0)
+ (const_int 65535)))
+ (parallel
+ [(set (match_dup 0)
+ (lshiftrt:SI (match_dup 0)
+ (match_dup 1)))
+ (clobber (match_dup 2))])]
+ "")
+
+;; Convert (A << B) & C to (A & 65535) << B if C == 65535 << B.
+
+(define_peephole2
+ [(parallel
+ [(set (match_operand:SI 0 "register_operand" "")
+ (ashift:SI (match_dup 0)
+ (match_operand:SI 1 "const_int_operand" "")))
+ (clobber (match_operand:SI 2 "" ""))])
+ (set (match_dup 0)
+ (and:SI (match_dup 0)
+ (match_operand:SI 3 "const_int_operand" "")))]
+ "INTVAL (operands[3]) == (65535 << INTVAL (operands[1]))"
+ [(set (match_dup 0)
+ (and:SI (match_dup 0)
+ (const_int 65535)))
+ (parallel
+ [(set (match_dup 0)
+ (ashift:SI (match_dup 0)
+ (match_dup 1)))
+ (clobber (match_dup 2))])]
+ "")
+
+;; Convert a QImode push into an SImode push so that the
+;; define_peephole2 below can cram multiple pushes into one stm.l.
+
+(define_peephole2
+ [(parallel [(set (reg:SI SP_REG)
+ (plus:SI (reg:SI SP_REG) (const_int -4)))
+ (set (mem:QI (plus:SI (reg:SI SP_REG) (const_int -3)))
+ (match_operand:QI 0 "register_operand" ""))])]
+ "TARGET_H8300S"
+ [(set (mem:SI (pre_dec:SI (reg:SI SP_REG)))
+ (match_dup 0))]
+ "operands[0] = gen_rtx_REG (SImode, REGNO (operands[0]));")
+
+;; Convert a HImode push into an SImode push so that the
+;; define_peephole2 below can cram multiple pushes into one stm.l.
+
+(define_peephole2
+ [(parallel [(set (reg:SI SP_REG)
+ (plus:SI (reg:SI SP_REG) (const_int -4)))
+ (set (mem:HI (plus:SI (reg:SI SP_REG) (const_int -2)))
+ (match_operand:HI 0 "register_operand" ""))])]
+ "TARGET_H8300S"
+ [(set (mem:SI (pre_dec:SI (reg:SI SP_REG)))
+ (match_dup 0))]
+ "operands[0] = gen_rtx_REG (SImode, REGNO (operands[0]));")
+
+;; Cram four pushes into stm.l.
+
+(define_peephole2
+ [(set (mem:SI (pre_dec:SI (reg:SI SP_REG)))
+ (match_operand:SI 0 "register_operand" ""))
+ (set (mem:SI (pre_dec:SI (reg:SI SP_REG)))
+ (match_operand:SI 1 "register_operand" ""))
+ (set (mem:SI (pre_dec:SI (reg:SI SP_REG)))
+ (match_operand:SI 2 "register_operand" ""))
+ (set (mem:SI (pre_dec:SI (reg:SI SP_REG)))
+ (match_operand:SI 3 "register_operand" ""))]
+ "TARGET_H8300S
+ && REGNO (operands[0]) == 0
+ && REGNO (operands[1]) == 1
+ && REGNO (operands[2]) == 2
+ && REGNO (operands[3]) == 3"
+ [(parallel [(set (reg:SI SP_REG)
+ (plus:SI (reg:SI SP_REG)
+ (const_int -16)))
+ (set (mem:SI (plus:SI (reg:SI SP_REG) (const_int -4)))
+ (match_dup 0))
+ (set (mem:SI (plus:SI (reg:SI SP_REG) (const_int -8)))
+ (match_dup 1))
+ (set (mem:SI (plus:SI (reg:SI SP_REG) (const_int -12)))
+ (match_dup 2))
+ (set (mem:SI (plus:SI (reg:SI SP_REG) (const_int -16)))
+ (match_dup 3))])]
+ "")
+
+;; Cram three pushes into stm.l.
+
+(define_peephole2
+ [(set (mem:SI (pre_dec:SI (reg:SI SP_REG)))
+ (match_operand:SI 0 "register_operand" ""))
+ (set (mem:SI (pre_dec:SI (reg:SI SP_REG)))
+ (match_operand:SI 1 "register_operand" ""))
+ (set (mem:SI (pre_dec:SI (reg:SI SP_REG)))
+ (match_operand:SI 2 "register_operand" ""))]
+ "TARGET_H8300S
+ && ((REGNO (operands[0]) == 0
+ && REGNO (operands[1]) == 1
+ && REGNO (operands[2]) == 2)
+ || (REGNO (operands[0]) == 4
+ && REGNO (operands[1]) == 5
+ && REGNO (operands[2]) == 6))"
+ [(parallel [(set (reg:SI SP_REG)
+ (plus:SI (reg:SI SP_REG)
+ (const_int -12)))
+ (set (mem:SI (plus:SI (reg:SI SP_REG) (const_int -4)))
+ (match_dup 0))
+ (set (mem:SI (plus:SI (reg:SI SP_REG) (const_int -8)))
+ (match_dup 1))
+ (set (mem:SI (plus:SI (reg:SI SP_REG) (const_int -12)))
+ (match_dup 2))])]
+ "")
+
+;; Cram two pushes into stm.l.
+
+(define_peephole2
+ [(set (mem:SI (pre_dec:SI (reg:SI SP_REG)))
+ (match_operand:SI 0 "register_operand" ""))
+ (set (mem:SI (pre_dec:SI (reg:SI SP_REG)))
+ (match_operand:SI 1 "register_operand" ""))]
+ "TARGET_H8300S
+ && ((REGNO (operands[0]) == 0 && REGNO (operands[1]) == 1)
+ || (REGNO (operands[0]) == 2 && REGNO (operands[1]) == 3)
+ || (REGNO (operands[0]) == 4 && REGNO (operands[1]) == 5))"
+ [(parallel [(set (reg:SI SP_REG)
+ (plus:SI (reg:SI SP_REG)
+ (const_int -8)))
+ (set (mem:SI (plus:SI (reg:SI SP_REG) (const_int -4)))
+ (match_dup 0))
+ (set (mem:SI (plus:SI (reg:SI SP_REG) (const_int -8)))
+ (match_dup 1))])]
+ "")
+
+;; Turn
+;;
+;; mov.w #2,r0
+;; add.w r7,r0 (6 bytes)
+;;
+;; into
+;;
+;; mov.w r7,r0
+;; adds #2,r0 (4 bytes)
+
+(define_peephole2
+ [(set (match_operand:HI 0 "register_operand" "")
+ (match_operand:HI 1 "const_int_operand" ""))
+ (set (match_dup 0)
+ (plus:HI (match_dup 0)
+ (match_operand:HI 2 "register_operand" "")))]
+ "REG_P (operands[0]) && REG_P (operands[2])
+ && REGNO (operands[0]) != REGNO (operands[2])
+ && (CONST_OK_FOR_J (INTVAL (operands[1]))
+ || CONST_OK_FOR_L (INTVAL (operands[1]))
+ || CONST_OK_FOR_N (INTVAL (operands[1])))"
+ [(set (match_dup 0)
+ (match_dup 2))
+ (set (match_dup 0)
+ (plus:HI (match_dup 0)
+ (match_dup 1)))]
+ "")
+
+;; Turn
+;;
+;; sub.l er0,er0
+;; add.b #4,r0l
+;; add.l er7,er0 (6 bytes)
+;;
+;; into
+;;
+;; mov.l er7,er0
+;; adds #4,er0 (4 bytes)
+
+(define_peephole2
+ [(set (match_operand:SI 0 "register_operand" "")
+ (match_operand:SI 1 "const_int_operand" ""))
+ (set (match_dup 0)
+ (plus:SI (match_dup 0)
+ (match_operand:SI 2 "register_operand" "")))]
+ "(TARGET_H8300H || TARGET_H8300S)
+ && REG_P (operands[0]) && REG_P (operands[2])
+ && REGNO (operands[0]) != REGNO (operands[2])
+ && (CONST_OK_FOR_L (INTVAL (operands[1]))
+ || CONST_OK_FOR_N (INTVAL (operands[1])))"
+ [(set (match_dup 0)
+ (match_dup 2))
+ (set (match_dup 0)
+ (plus:SI (match_dup 0)
+ (match_dup 1)))]
+ "")
+
+;; Turn
+;;
+;; mov.l er7,er0
+;; add.l #10,er0 (takes 8 bytes)
+;;
+;; into
+;;
+;; sub.l er0,er0
+;; add.b #10,r0l
+;; add.l er7,er0 (takes 6 bytes)
+
+(define_peephole2
+ [(set (match_operand:SI 0 "register_operand" "")
+ (match_operand:SI 1 "register_operand" ""))
+ (set (match_dup 0)
+ (plus:SI (match_dup 0)
+ (match_operand:SI 2 "const_int_operand" "")))]
+ "(TARGET_H8300H || TARGET_H8300S)
+ && REG_P (operands[0]) && REG_P (operands[1])
+ && REGNO (operands[0]) != REGNO (operands[1])
+ && !CONST_OK_FOR_L (INTVAL (operands[2]))
+ && !CONST_OK_FOR_N (INTVAL (operands[2]))
+ && ((INTVAL (operands[2]) & 0xff) == INTVAL (operands[2])
+ || (INTVAL (operands[2]) & 0xff00) == INTVAL (operands[2])
+ || INTVAL (operands[2]) == 0xffff
+ || INTVAL (operands[2]) == 0xfffe)"
+ [(set (match_dup 0)
+ (match_dup 2))
+ (set (match_dup 0)
+ (plus:SI (match_dup 0)
+ (match_dup 1)))]
+ "")
+
+;; Turn
+;;
+;; subs #1,er4
+;; mov.w r4,r4
+;; bne .L2028
+;;
+;; into
+;;
+;; dec.w #1,r4
+;; bne .L2028
+
+(define_peephole2
+ [(set (match_operand:HI 0 "register_operand" "")
+ (plus:HI (match_dup 0)
+ (match_operand 1 "incdec_operand" "")))
+ (set (cc0)
+ (match_dup 0))
+ (set (pc)
+ (if_then_else (match_operator 3 "eqne_operator"
+ [(cc0) (const_int 0)])
+ (label_ref (match_operand 2 "" ""))
+ (pc)))]
+ "TARGET_H8300H || TARGET_H8300S"
+ [(set (match_operand:HI 0 "register_operand" "")
+ (unspec:HI [(match_dup 0)
+ (match_dup 1)]
+ UNSPEC_INCDEC))
+ (set (cc0)
+ (match_dup 0))
+ (set (pc)
+ (if_then_else (match_op_dup 3 [(cc0) (const_int 0)])
+ (label_ref (match_dup 2))
+ (pc)))]
+ "")
+
+;; The SImode version of the previous pattern.
+
+(define_peephole2
+ [(set (match_operand:SI 0 "register_operand" "")
+ (plus:SI (match_dup 0)
+ (match_operand 1 "incdec_operand" "")))
+ (set (cc0)
+ (match_dup 0))
+ (set (pc)
+ (if_then_else (match_operator 3 "eqne_operator"
+ [(cc0) (const_int 0)])
+ (label_ref (match_operand 2 "" ""))
+ (pc)))]
+ "TARGET_H8300H || TARGET_H8300S"
+ [(set (match_operand:SI 0 "register_operand" "")
+ (unspec:SI [(match_dup 0)
+ (match_dup 1)]
+ UNSPEC_INCDEC))
+ (set (cc0)
+ (match_dup 0))
+ (set (pc)
+ (if_then_else (match_op_dup 3 [(cc0) (const_int 0)])
+ (label_ref (match_dup 2))
+ (pc)))]
+ "")
+
+;; (compare (reg:SI) (const_int)) takes 6 bytes, so we try to achieve
+;; the equivalent with shorter sequences. Here is the summary. Cases
+;; are grouped for each define_peephole2.
+;;
+;; reg const_int use insn
+;; --------------------------------------------------------
+;; live -2 eq/ne copy and inc.l
+;; live -1 eq/ne copy and inc.l
+;; live 1 eq/ne copy and dec.l
+;; live 2 eq/ne copy and dec.l
+;;
+;; dead -2 eq/ne inc.l
+;; dead -1 eq/ne inc.l
+;; dead 1 eq/ne dec.l
+;; dead 2 eq/ne dec.l
+;;
+;; dead 0x000000?? except 1 and 2 eq/ne xor.b and test
+;; dead 0x0000??00 eq/ne xor.b and test
+;; dead 0x0000ffff eq/ne not.w and test
+;; dead 0xffff0000 eq/ne not.w and test
+;;
+;; dead 0xffffff?? except -1 and -2 eq/ne xor.b and not.l
+;; dead 0xffff??ff eq/ne xor.b and not.l
+;;
+;; dead 1 geu/ltu and.b and test
+;; dead 3 geu/ltu and.b and test
+;; dead 7 geu/ltu and.b and test
+;; dead 15 geu/ltu and.b and test
+;; dead 31 geu/ltu and.b and test
+;; dead 63 geu/ltu and.b and test
+;; dead 127 geu/ltu and.b and test
+;; dead 255 geu/ltu and.b and test
+;;
+;; dead 65535 geu/ltu mov.w
+
+;; For a small constant, it is cheaper to actually do the subtraction
+;; and then test the register.
+
+(define_peephole2
+ [(set (cc0)
+ (compare (match_operand:HI 0 "register_operand" "")
+ (match_operand:HI 1 "incdec_operand" "")))
+ (set (pc)
+ (if_then_else (match_operator 3 "eqne_operator"
+ [(cc0) (const_int 0)])
+ (label_ref (match_operand 2 "" ""))
+ (pc)))]
+ "(TARGET_H8300H || TARGET_H8300S)
+ && peep2_reg_dead_p (1, operands[0])"
+ [(set (match_dup 0)
+ (unspec:HI [(match_dup 0)
+ (match_dup 4)]
+ UNSPEC_INCDEC))
+ (set (cc0)
+ (match_dup 0))
+ (set (pc)
+ (if_then_else (match_op_dup 3 [(cc0) (const_int 0)])
+ (label_ref (match_dup 2))
+ (pc)))]
+ "operands[4] = GEN_INT (- INTVAL (operands[1]));")
+
+;; The SImode version of the previous pattern.
+
+(define_peephole2
+ [(set (cc0)
+ (compare (match_operand:SI 0 "register_operand" "")
+ (match_operand:SI 1 "incdec_operand" "")))
+ (set (pc)
+ (if_then_else (match_operator 3 "eqne_operator"
+ [(cc0) (const_int 0)])
+ (label_ref (match_operand 2 "" ""))
+ (pc)))]
+ "(TARGET_H8300H || TARGET_H8300S)
+ && peep2_reg_dead_p (1, operands[0])"
+ [(set (match_dup 0)
+ (unspec:SI [(match_dup 0)
+ (match_dup 4)]
+ UNSPEC_INCDEC))
+ (set (cc0)
+ (match_dup 0))
+ (set (pc)
+ (if_then_else (match_op_dup 3 [(cc0) (const_int 0)])
+ (label_ref (match_dup 2))
+ (pc)))]
+ "operands[4] = GEN_INT (- INTVAL (operands[1]));")
+
+;; For certain (in)equaltity comparisions against a constant, we can
+;; XOR the register with the constant, and test the register against
+;; 0.
+
+(define_peephole2
+ [(set (cc0)
+ (compare (match_operand:SI 0 "register_operand" "")
+ (match_operand:SI 1 "const_int_operand" "")))
+ (set (pc)
+ (if_then_else (match_operator 3 "eqne_operator"
+ [(cc0) (const_int 0)])
+ (label_ref (match_operand 2 "" ""))
+ (pc)))]
+ "(TARGET_H8300H || TARGET_H8300S)
+ && peep2_reg_dead_p (1, operands[0])
+ && ((INTVAL (operands[1]) & 0x00ff) == INTVAL (operands[1])
+ || (INTVAL (operands[1]) & 0xff00) == INTVAL (operands[1])
+ || INTVAL (operands[1]) == 0x0000ffff
+ || INTVAL (operands[1]) == 0xffff0000)
+ && INTVAL (operands[1]) != 1
+ && INTVAL (operands[1]) != 2"
+ [(set (match_dup 0)
+ (xor:SI (match_dup 0)
+ (match_dup 1)))
+ (set (cc0)
+ (match_dup 0))
+ (set (pc)
+ (if_then_else (match_op_dup 3 [(cc0) (const_int 0)])
+ (label_ref (match_dup 2))
+ (pc)))]
+ "")
+
+(define_peephole2
+ [(set (cc0)
+ (compare (match_operand:SI 0 "register_operand" "")
+ (match_operand:SI 1 "const_int_operand" "")))
+ (set (pc)
+ (if_then_else (match_operator 3 "eqne_operator"
+ [(cc0) (const_int 0)])
+ (label_ref (match_operand 2 "" ""))
+ (pc)))]
+ "(TARGET_H8300H || TARGET_H8300S)
+ && peep2_reg_dead_p (1, operands[0])
+ && ((INTVAL (operands[1]) | 0x00ff) == -1
+ || (INTVAL (operands[1]) | 0xff00) == -1)
+ && INTVAL (operands[1]) != -1
+ && INTVAL (operands[1]) != -2"
+ [(set (match_dup 0)
+ (xor:SI (match_dup 0)
+ (match_dup 4)))
+ (set (match_dup 0)
+ (not:SI (match_dup 0)))
+ (set (cc0)
+ (match_dup 0))
+ (set (pc)
+ (if_then_else (match_op_dup 3 [(cc0) (const_int 0)])
+ (label_ref (match_dup 2))
+ (pc)))]
+ "operands[4] = GEN_INT (INTVAL (operands[1]) ^ -1);")
+
+;; Transform A <= 1 to (A & 0xfffffffe) == 0.
+
+(define_peephole2
+ [(set (cc0)
+ (compare (match_operand:SI 0 "register_operand" "")
+ (match_operand:SI 1 "const_int_operand" "")))
+ (set (pc)
+ (if_then_else (match_operator 2 "gtuleu_operator"
+ [(cc0) (const_int 0)])
+ (label_ref (match_operand 3 "" ""))
+ (pc)))]
+ "(TARGET_H8300H || TARGET_H8300S)
+ && peep2_reg_dead_p (1, operands[0])
+ && (INTVAL (operands[1]) == 1
+ || INTVAL (operands[1]) == 3
+ || INTVAL (operands[1]) == 7
+ || INTVAL (operands[1]) == 15
+ || INTVAL (operands[1]) == 31
+ || INTVAL (operands[1]) == 63
+ || INTVAL (operands[1]) == 127
+ || INTVAL (operands[1]) == 255)"
+ [(set (match_dup 0)
+ (and:SI (match_dup 0)
+ (match_dup 5)))
+ (set (cc0)
+ (match_dup 0))
+ (set (pc)
+ (if_then_else (match_dup 4)
+ (label_ref (match_dup 3))
+ (pc)))]
+ "operands[4] = ((GET_CODE (operands[2]) == GTU) ?
+ gen_rtx_NE (VOIDmode, cc0_rtx, const0_rtx) :
+ gen_rtx_EQ (VOIDmode, cc0_rtx, const0_rtx));
+ operands[5] = GEN_INT (~INTVAL (operands[1]));")
+
+;; Transform A <= 255 to (A & 0xff00) == 0.
+
+(define_peephole2
+ [(set (cc0)
+ (compare (match_operand:HI 0 "register_operand" "")
+ (const_int 255)))
+ (set (pc)
+ (if_then_else (match_operator 1 "gtuleu_operator"
+ [(cc0) (const_int 0)])
+ (label_ref (match_operand 2 "" ""))
+ (pc)))]
+ "TARGET_H8300H || TARGET_H8300S"
+ [(set (cc0)
+ (and:HI (match_dup 0)
+ (const_int -256)))
+ (set (pc)
+ (if_then_else (match_dup 4)
+ (label_ref (match_dup 2))
+ (pc)))]
+ "operands[4] = ((GET_CODE (operands[1]) == GTU) ?
+ gen_rtx_NE (VOIDmode, cc0_rtx, const0_rtx) :
+ gen_rtx_EQ (VOIDmode, cc0_rtx, const0_rtx));")
+
+;; Transform A <= 65535 to (A & 0xffff0000) == 0.
+
+(define_peephole2
+ [(set (cc0)
+ (compare (match_operand:SI 0 "register_operand" "")
+ (const_int 65535)))
+ (set (pc)
+ (if_then_else (match_operator 1 "gtuleu_operator"
+ [(cc0) (const_int 0)])
+ (label_ref (match_operand 2 "" ""))
+ (pc)))]
+ "TARGET_H8300H || TARGET_H8300S"
+ [(set (cc0)
+ (and:SI (match_dup 0)
+ (const_int -65536)))
+ (set (pc)
+ (if_then_else (match_dup 4)
+ (label_ref (match_dup 2))
+ (pc)))]
+ "operands[4] = ((GET_CODE (operands[1]) == GTU) ?
+ gen_rtx_NE (VOIDmode, cc0_rtx, const0_rtx) :
+ gen_rtx_EQ (VOIDmode, cc0_rtx, const0_rtx));")
+
+;; For constants like -1, -2, 1, 2, it is still cheaper to make a copy
+;; of the register being tested, do the subtraction on the copy, and
+;; then test the copy. We avoid this transformation if we see more
+;; than one copy of the same compare insn.
+
+(define_peephole2
+ [(match_scratch:SI 4 "r")
+ (set (cc0)
+ (compare (match_operand:SI 0 "register_operand" "")
+ (match_operand:SI 1 "incdec_operand" "")))
+ (set (pc)
+ (if_then_else (match_operator 3 "eqne_operator"
+ [(cc0) (const_int 0)])
+ (label_ref (match_operand 2 "" ""))
+ (pc)))]
+ "(TARGET_H8300H || TARGET_H8300S)
+ && !peep2_reg_dead_p (1, operands[0])
+ && !rtx_equal_p (PATTERN (insn),
+ PATTERN (next_nonnote_insn (next_nonnote_insn (insn))))"
+ [(set (match_dup 4)
+ (match_dup 0))
+ (set (match_dup 4)
+ (unspec:SI [(match_dup 4)
+ (match_dup 5)]
+ UNSPEC_INCDEC))
+ (set (cc0)
+ (match_dup 4))
+ (set (pc)
+ (if_then_else (match_op_dup 3 [(cc0) (const_int 0)])
+ (label_ref (match_dup 2))
+ (pc)))]
+ "operands[5] = GEN_INT (- INTVAL (operands[1]));")
+
+;; Narrow the mode of testing if possible.
+
+(define_peephole2
+ [(set (match_operand:HI 0 "register_operand" "")
+ (and:HI (match_dup 0)
+ (match_operand:HI 1 "const_int_qi_operand" "")))
+ (set (cc0)
+ (match_dup 0))
+ (set (pc)
+ (if_then_else (match_operator 3 "eqne_operator"
+ [(cc0) (const_int 0)])
+ (label_ref (match_operand 2 "" ""))
+ (pc)))]
+ "peep2_reg_dead_p (2, operands[0])"
+ [(set (match_dup 4)
+ (and:QI (match_dup 4)
+ (match_dup 5)))
+ (set (cc0)
+ (match_dup 4))
+ (set (pc)
+ (if_then_else (match_op_dup 3 [(cc0) (const_int 0)])
+ (label_ref (match_dup 2))
+ (pc)))]
+ "operands[4] = gen_rtx_REG (QImode, REGNO (operands[0]));
+ operands[5] = GEN_INT (trunc_int_for_mode (INTVAL (operands[1]), QImode));")
+
+(define_peephole2
+ [(set (match_operand:SI 0 "register_operand" "")
+ (and:SI (match_dup 0)
+ (match_operand:SI 1 "const_int_qi_operand" "")))
+ (set (cc0)
+ (match_dup 0))
+ (set (pc)
+ (if_then_else (match_operator 3 "eqne_operator"
+ [(cc0) (const_int 0)])
+ (label_ref (match_operand 2 "" ""))
+ (pc)))]
+ "peep2_reg_dead_p (2, operands[0])"
+ [(set (match_dup 4)
+ (and:QI (match_dup 4)
+ (match_dup 5)))
+ (set (cc0)
+ (match_dup 4))
+ (set (pc)
+ (if_then_else (match_op_dup 3 [(cc0) (const_int 0)])
+ (label_ref (match_dup 2))
+ (pc)))]
+ "operands[4] = gen_rtx_REG (QImode, REGNO (operands[0]));
+ operands[5] = GEN_INT (trunc_int_for_mode (INTVAL (operands[1]), QImode));")
+
+(define_peephole2
+ [(set (match_operand:SI 0 "register_operand" "")
+ (and:SI (match_dup 0)
+ (match_operand:SI 1 "const_int_hi_operand" "")))
+ (set (cc0)
+ (match_dup 0))
+ (set (pc)
+ (if_then_else (match_operator 3 "eqne_operator"
+ [(cc0) (const_int 0)])
+ (label_ref (match_operand 2 "" ""))
+ (pc)))]
+ "peep2_reg_dead_p (2, operands[0])"
+ [(set (match_dup 4)
+ (and:HI (match_dup 4)
+ (match_dup 5)))
+ (set (cc0)
+ (match_dup 4))
+ (set (pc)
+ (if_then_else (match_op_dup 3 [(cc0) (const_int 0)])
+ (label_ref (match_dup 2))
+ (pc)))]
+ "operands[4] = gen_rtx_REG (HImode, REGNO (operands[0]));
+ operands[5] = GEN_INT (trunc_int_for_mode (INTVAL (operands[1]), HImode));")