;; "worst case" and then be adjusted to their correct values by
;; h8300_adjust_insn_length.
-;; On the H8/300H and H8/S, adds/subs operate on the 32bit "er"
+;; On the H8/300H and H8S, adds/subs operate on the 32bit "er"
;; registers. Right now GCC doesn't expose the "e" half to the
;; compiler, so using add/subs for addhi and subhi is safe. Long
;; term, we want to expose the "e" half to the compiler (gives us 8
;; more 16bit registers). At that point addhi and subhi can't use
;; adds/subs.
-;; There's currently no way to have a insv/extzv expander for the H8/300H
+;; There's currently no way to have an insv/extzv expander for the H8/300H
;; because word_mode is different for the H8/300 and H8/300H.
;; Shifts/rotates by small constants should be handled by special
(define_attr "adjust_length" "yes,no"
(cond [(eq_attr "type" "branch") (const_string "no")]
- (const_string "yes")))
+ (const_string "yes")))
;; Condition code settings.
;;
(define_insn "pushqi1_h8300"
[(parallel [(set (reg:HI SP_REG)
- (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"))])]
+ (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"
"mov.w\\t%T0,@-r7"
[(set_attr "length" "2")
(define_insn "pushqi1_h8300hs"
[(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" "r"))])]
+ (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"
"mov.l\\t%S0,@-er7"
[(set_attr "length" "4")
(define_expand "pushhi1_h8300"
[(set (mem:HI (pre_dec:HI (reg:HI SP_REG)))
- (match_operand:HI 0 "register_operand" ""))]
+ (match_operand:HI 0 "register_operand" ""))]
"TARGET_H8300"
"")
(define_insn "pushhi1_h8300hs"
[(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" "r"))])]
+ (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"
"mov.l\\t%S0,@-er7"
[(set_attr "length" "4")
}
/* Look for constants that can be obtained by subs, inc, and
- dec to 0. */
+ dec to 0. */
switch (val & 0xffffffff)
{
case 0xffffffff:
[(set_attr "length" "2")
(set_attr "cc" "set_zn")])
+(define_insn ""
+ [(set (cc0)
+ (and:HI (match_operand:HI 0 "register_operand" "r")
+ (match_operand:HI 1 "single_one_operand" "n")))]
+ ""
+ "*
+{
+ operands[1] = GEN_INT (INTVAL (operands[1]) & 0xffff);
+ if (INTVAL (operands[1]) > 128)
+ {
+ operands[1] = GEN_INT (INTVAL (operands[1]) >> 8);
+ return \"btst\\t%V1,%t0\";
+ }
+ return \"btst\\t%V1,%s0\";
+}"
+ [(set_attr "length" "2")
+ (set_attr "cc" "set_zn")])
+
+(define_insn ""
+ [(set (cc0)
+ (and:SI (match_operand:SI 0 "register_operand" "r")
+ (match_operand:SI 1 "single_one_operand" "n")))]
+ "(TARGET_H8300H || TARGET_H8300S)
+ && (INTVAL (operands[1]) & 0xffff) != 0"
+ "*
+{
+ operands[1] = GEN_INT (INTVAL (operands[1]) & 0xffff);
+ if (INTVAL (operands[1]) > 128)
+ {
+ operands[1] = GEN_INT (INTVAL (operands[1]) >> 8);
+ return \"btst\\t%V1,%x0\";
+ }
+ return \"btst\\t%V1,%w0\";
+}"
+ [(set_attr "length" "2")
+ (set_attr "cc" "set_zn")])
+
(define_insn "tstqi"
[(set (cc0) (match_operand:QI 0 "register_operand" "r"))]
""
[(set_attr "length" "2")
(set_attr "cc" "set_znv")])
+(define_insn ""
+ [(set (cc0)
+ (and:HI (match_operand:HI 0 "register_operand" "r")
+ (const_int -256)))]
+ ""
+ "mov.b %t0,%t0"
+ [(set_attr "length" "2")
+ (set_attr "cc" "set_znv")])
+
(define_insn "tstsi"
[(set (cc0) (match_operand:SI 0 "register_operand" "r"))]
"TARGET_H8300H || TARGET_H8300S"
[(set_attr "length" "2")
(set_attr "cc" "set_znv")])
+(define_insn ""
+ [(set (cc0)
+ (and:SI (match_operand:SI 0 "register_operand" "r")
+ (const_int -65536)))]
+ ""
+ "mov.w %e0,%e0"
+ [(set_attr "length" "2")
+ (set_attr "cc" "set_znv")])
+
(define_insn "cmpqi"
[(set (cc0)
(compare:QI (match_operand:QI 0 "register_operand" "r")
;; DIVIDE/MOD INSTRUCTIONS
;; ----------------------------------------------------------------------
-(define_expand "udivmodqi4"
- [(set (match_operand:HI 1 "register_operand" "")
- (and:HI (match_dup 1)
- (const_int 255)))
- (parallel [(set (match_operand:QI 0 "register_operand" "")
- (truncate:QI
- (udiv:HI
- (match_dup 1)
- (zero_extend:HI
- (match_operand:QI 2 "register_operand" "")))))
- (set (match_operand:QI 3 "register_operand" "")
- (truncate:QI
- (umod:HI
- (match_dup 1)
- (zero_extend:HI (match_dup 2)))))])]
- "TARGET_H8300H || TARGET_H8300S"
- "")
-
-(define_insn ""
+(define_insn "udivmodqi4"
[(set (match_operand:QI 0 "register_operand" "=r")
(truncate:QI
(udiv:HI
(umod:HI
(match_dup 1)
(zero_extend:HI (match_dup 2)))))]
- "TARGET_H8300H || TARGET_H8300S"
+ ""
"*
{
if (find_reg_note (insn, REG_UNUSED, operands[3]))
[(set_attr "length" "6")
(set_attr "cc" "clobber")])
-(define_expand "udivmodhi4"
- [(set (match_operand:SI 1 "register_operand" "")
- (and:SI (match_dup 1)
- (const_int 65535)))
- (parallel [(set (match_operand:HI 0 "register_operand" "")
- (truncate:HI
- (udiv:SI
- (match_dup 1)
- (zero_extend:SI
- (match_operand:HI 2 "register_operand" "")))))
- (set (match_operand:HI 3 "register_operand" "")
- (truncate:HI
- (umod:SI
- (match_dup 1)
- (zero_extend:SI (match_dup 2)))))])]
- "TARGET_H8300H || TARGET_H8300S"
- "")
-
-(define_insn ""
+(define_insn "udivmodhi4"
[(set (match_operand:HI 0 "register_operand" "=r")
(truncate:HI
(udiv:SI
(define_insn ""
[(set (match_operand:QI 0 "bit_operand" "=r,U")
(and:QI (match_operand:QI 1 "bit_operand" "%0,0")
- (match_operand:QI 2 "nonmemory_operand" "rn,O")))]
+ (match_operand:QI 2 "nonmemory_operand" "rn,n")))]
"register_operand (operands[0], QImode)
|| single_zero_operand (operands[2], QImode)"
"@
(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"
[(set (match_operand:HI 0 "register_operand" "=r")
(ior:HI (and:HI (match_operand:HI 2 "register_operand" "r")
(match_operand:HI 3 "single_one_operand" "n"))
- (match_operand:HI 1 "register_operand" "0")))]
+ (match_operand:HI 1 "register_operand" "0")))]
""
"*
{
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"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (ior:SI (and:SI (match_operand:SI 2 "register_operand" "r")
+ (match_operand:SI 3 "single_one_operand" "n"))
+ (match_operand:SI 1 "register_operand" "0")))]
+ "(INTVAL (operands[3]) & 0xffff) != 0"
+ "*
+{
+ 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\";
+}"
+ [(set_attr "length" "6")
(set_attr "cc" "clobber")])
(define_expand "andsi3"
{
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))
+ || GET_CODE (operands[1]) == GE
+ || GET_CODE (operands[1]) == LE
+ || GET_CODE (operands[1]) == LT))
{
cc_status.flags &= ~CC_OVERFLOW_UNUSABLE;
return 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))
+ || GET_CODE (operands[1]) == GE
+ || GET_CODE (operands[1]) == LE
+ || GET_CODE (operands[1]) == LT))
{
cc_status.flags &= ~CC_OVERFLOW_UNUSABLE;
return 0;
[(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 H8/S.
+;; ??? Even though we use HImode here, this works on the H8/300H and H8S.
(define_insn "call"
[(call (match_operand:QI 0 "call_insn_operand" "or")
;; 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 H8/S.
+;; ??? Even though we use HImode here, this works on the H8/300H and H8S.
(define_insn "call_value"
[(set (match_operand 0 "" "=r")
[(set_attr "length" "2,10")
(set_attr "cc" "set_znv,set_znv")])
-;; The compiler can synthesize a 300H variant of this which is
+;; 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"
[(set (match_operand:SI 0 "register_operand" "=r,r")
[(set_attr "length" "2")
(set_attr "cc" "set_znv")])
-;; The compiler can synthesize a 300H variant of this which is
+;; The compiler can synthesize a H8/300H variant of this which is
;; just as efficient as one that we'd create
(define_insn "extendqisi2"
[(set (match_operand:SI 0 "register_operand" "=r,r")
"TARGET_H8300"
"
{
- /* We only have single bit bitfield instructions. */
+ /* We only have single bit bit-field instructions. */
if (INTVAL (operands[1]) != 1)
FAIL;
"TARGET_H8300"
"
{
- /* We only have single bit bitfield instructions. */
+ /* We only have single bit bit-field instructions. */
if (INTVAL (operands[2]) != 1)
FAIL;
(define_insn ""
[(set (match_operand:HI 0 "register_operand" "=r")
- (ior:HI (zero_extend:HI (match_operand:QI 1 "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])
(define_insn ""
[(set (match_operand:SI 0 "register_operand" "=r")
- (ior:SI (zero_extend:SI (match_operand:HI 1 "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])
(define_insn ""
[(set (match_operand:SI 0 "register_operand" "=r")
- (ior:SI (zero_extend:SI (match_operand:QI 1 "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,%s0"
+ ""
+ "or\\t%X1,%w0"
[(set_attr "cc" "clobber")
(set_attr "length" "2")])
(define_insn ""
[(set (match_operand:HI 0 "register_operand" "=r")
- (xor:HI (zero_extend:HI (match_operand:QI 1 "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])
(define_insn ""
[(set (match_operand:SI 0 "register_operand" "=r")
- (xor:SI (zero_extend:SI (match_operand:HI 1 "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])
(define_insn ""
[(set (match_operand:SI 0 "register_operand" "=r")
- (xor:SI (zero_extend:SI (match_operand:QI 1 "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,%s0"
+ "xor\\t%X1,%w0"
[(set_attr "cc" "clobber")
(set_attr "length" "2")])
(define_insn ""
[(set (match_operand:HI 0 "register_operand" "=r")
- (ior:HI (zero_extend:HI (match_operand:QI 1 "register_operand" "0"))
+ (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])
(define_insn ""
[(set (match_operand:SI 0 "register_operand" "=r")
- (ior:SI (zero_extend:SI (match_operand:HI 1 "register_operand" "0"))
+ (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 ""
+ [(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")])
+
+;; 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"))]
+ "TARGET_H8300H || TARGET_H8300S"
+ "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"))]
+ "TARGET_H8300H || TARGET_H8300S"
+ "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)