Commit b4d2cd97 by Doug Evans

h8300.md (cpu): New attribute.

	* h8300/h8300.md (cpu): New attribute.
	(attribute length): Add h8/300h support.
	(attribute cc): New value `cbit'.
	(all anonymous insns): Give them names.
	(move insns): Add h8/300h support.
	(tstqi, tsthi): Use btst insn if able.
	(arithmetic insns): Add h8/300h support.
	(boolean insns): Likewise.
	(negate insns): Likewise.
	(branch insns): Likewise.
	(call_value): Use call_insn_operand for operand 1.
	(shift insns): Completely rewritten.  Add h8/300h support.
	(zero/sign extension insns): Add h8/300h support.
	(extv): Deleted.
	(insv, extzv): Only use for h8/300.
	(bitfield insns): Completely rewritten.
	(fancyb*): New insns for speeding up bit accesses.

From-SVN: r7730
parent 48837e29
;;- Machine description for the Hitachi H8/300 for the GNU C compiler ;; GCC machine description for Hitachi H8/300
;; Copyright (C) 1992, 1993 Free Software Foundation, Inc. ;; Copyright (C) 1992, 1993, 1994 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 GNU CC.
...@@ -23,6 +26,12 @@ ...@@ -23,6 +26,12 @@
;; See file "rtl.def" for documentation on define_insn, match_*, et. al. ;; See file "rtl.def" for documentation on define_insn, match_*, et. al.
(define_attr "cpu" "h8300,h8300h"
(const (symbol_ref "cpu_type")))
;; ??? If we can remove the operand type on all the insns, do it.
;; ??? Otherwise, try to have the operand type on all the insns.
(define_attr "type" "branch,return,call,arith,move,float,multi" (define_attr "type" "branch,return,call,arith,move,float,multi"
(const_string "arith")) (const_string "arith"))
...@@ -31,53 +40,119 @@ ...@@ -31,53 +40,119 @@
(define_attr "length" "" (define_attr "length" ""
(cond [(eq_attr "type" "branch") (cond [(eq_attr "type" "branch")
(if_then_else (and (ge (minus (pc) (match_dup 0)) (if_then_else (and (ge (minus (pc) (match_dup 0))
(const_int -128)) (const_int -120))
(le (minus (pc) (match_dup 0)) (le (minus (pc) (match_dup 0))
(const_int 128))) (const_int 120)))
(const_int 2) (const_int 2)
(const_int 6)) (if_then_else (and (eq_attr "cpu" "h8300h")
(and (ge (minus (pc) (match_dup 0))
(const_int -32000))
(le (minus (pc) (match_dup 0))
(const_int 32000))))
(const_int 4)
(const_int 6)))
(eq_attr "type" "move") (const_int 4) (eq_attr "type" "move") (const_int 4)
(eq_attr "type" "return") (const_int 2) (eq_attr "type" "return") (const_int 2)
(eq_attr "type" "float") (const_int 12) (eq_attr "type" "float") (const_int 12)
(eq_attr "type" "call") (const_int 4)] (eq_attr "type" "call") (const_int 4)]
(const_int 200))) (const_int 200)))
(define_attr "cc" "none,clobber,none_0hit,set,compare,whoops,cbit"
(define_attr "cc" "none,clobber,none_0hit,set,compare,whoops"
(const_string "whoops")) (const_string "whoops"))
;; ---------------------------------------------------------------------- ;; ----------------------------------------------------------------------
;; move instructions ;; MOVE INSTRUCTIONS
;; ---------------------------------------------------------------------- ;; ----------------------------------------------------------------------
;; movhi ;; movqi
(define_insn "" (define_insn "movqi_push"
[(set (match_operand:HI 0 "push_operand" "=<") [(set (match_operand:QI 0 "push_operand" "=<")
(match_operand:HI 1 "register_operand" "ra"))] (match_operand:QI 1 "register_operand" "r"))]
"" ""
"mov.w %T1,%T0" "*
{
if (TARGET_H8300)
return \"push.w %T1\";
else
return \"push.l %S1\";
}"
[(set_attr "type" "move") [(set_attr "type" "move")
(set_attr "length" "2") (set (attr "length") (if_then_else (eq_attr "cpu" "h8300") (const_int 2) (const_int 4)))
(set_attr "cc" "set")]) (set_attr "cc" "set")])
(define_insn "movstricthi" (define_insn "movqi_internal"
[(set (strict_low_part (match_operand:HI 0 "general_operand_dst" "=r,r,r,o,<")) [(set (match_operand:QI 0 "general_operand_dst" "=r,r,r,o,<,r")
(match_operand:HI 1 "general_operand_src" "I,r,io,r,r"))] (match_operand:QI 1 "general_operand_src" "I,r>,io,r,r,c"))]
"register_operand (operands[0],QImode) || register_operand (operands[1], QImode)"
"@
sub.b %X0,%X0
mov.b %X1,%X0
mov.b %X1,%X0
mov.b %X1,%X0
mov.b %X1,%X0
xor %X0,%X0\;bst #0,%X0"
[(set_attr "type" "move")
(set_attr_alternative "length"
[(const_int 2) (const_int 2)
(if_then_else (eq_attr "cpu" "h8300") (const_int 4) (const_int 8))
(if_then_else (eq_attr "cpu" "h8300") (const_int 4) (const_int 8))
(if_then_else (eq_attr "cpu" "h8300") (const_int 2) (const_int 4))
(const_int 4)])
(set_attr "cc" "set,set,set,set,set,none")])
(define_expand "movqi"
[(set (match_operand:QI 0 "general_operand_dst" "")
(match_operand:QI 1 "general_operand_src" ""))]
""
"
{
/* One of the ops has to be in a register */
if (!register_operand(operand0, QImode)
&& !register_operand(operand1, QImode))
{
operands[1] = copy_to_mode_reg(QImode, operand1);
}
}")
(define_insn "movstrictqi"
[(set (strict_low_part (match_operand:QI 0 "general_operand_dst" "=r,r,r,o,<"))
(match_operand:QI 1 "general_operand_src" "I,r,io,r,r"))]
"" ""
"@ "@
sub.w %T0,%T0 sub.b %X0,%X0
mov.w %T1,%T0 mov.b %X1,%X0
mov.w %T1,%T0 mov.b %X1,%X0
mov.w %T1,%T0 mov.b %X1,%X0
mov.w %T1,%T0" mov.b %X1,%X0"
[(set_attr "type" "move") [(set_attr "type" "move")
(set_attr "length" "2,2,4,4,2") (set_attr_alternative "length"
[(const_int 2) (const_int 2)
(if_then_else (eq_attr "cpu" "h8300") (const_int 4) (const_int 8))
(if_then_else (eq_attr "cpu" "h8300") (const_int 4) (const_int 8))
(if_then_else (eq_attr "cpu" "h8300") (const_int 2) (const_int 4))])
(set_attr "cc" "set")])
;; movhi
(define_insn "movhi_push"
[(set (match_operand:HI 0 "push_operand" "=<")
(match_operand:HI 1 "register_operand" "ra"))]
""
"*
{
if (TARGET_H8300)
return \"push.w %T1\";
else
return \"push.l %S1\";
}"
[(set_attr "type" "move")
(set (attr "length") (if_then_else (eq_attr "cpu" "h8300") (const_int 2) (const_int 4)))
(set_attr "cc" "set")]) (set_attr "cc" "set")])
(define_insn "" (define_insn "movhi_internal"
[(set (match_operand:HI 0 "general_operand_dst" "=ra,ra,ra,o,<") [(set (match_operand:HI 0 "general_operand_dst" "=ra,ra,ra,o,<")
(match_operand:HI 1 "general_operand_src" "I,ra,ion,ra,ra"))] (match_operand:HI 1 "general_operand_src" "I,ra>,ion,ra,ra"))]
"" ""
"@ "@
sub.w %T0,%T0 sub.w %T0,%T0
...@@ -86,7 +161,11 @@ ...@@ -86,7 +161,11 @@
mov.w %T1,%T0 mov.w %T1,%T0
mov.w %T1,%T0" mov.w %T1,%T0"
[(set_attr "type" "move") [(set_attr "type" "move")
(set_attr "length" "2,2,4,4,2") (set_attr_alternative "length"
[(const_int 2) (const_int 2)
(if_then_else (eq_attr "cpu" "h8300") (const_int 4) (const_int 8))
(if_then_else (eq_attr "cpu" "h8300") (const_int 4) (const_int 8))
(if_then_else (eq_attr "cpu" "h8300") (const_int 2) (const_int 4))])
(set_attr "cc" "set")]) (set_attr "cc" "set")])
(define_expand "movhi" (define_expand "movhi"
...@@ -95,79 +174,84 @@ ...@@ -95,79 +174,84 @@
"" ""
" "
{ {
/* One of the ops has to be in a register. */ /* One of the ops has to be in a register */
if (! register_operand (operand1, HImode) if (!register_operand(operand1, HImode)
&& ! register_operand (operand0, HImode)) && !register_operand(operand0, HImode))
operands[1] = copy_to_mode_reg (HImode, operand1); {
operands[1] = copy_to_mode_reg(HImode, operand1);
}
}") }")
(define_insn "" (define_insn "movstricthi"
[(set (match_operand:HI 0 "register_operand" "=&ra") [(set (strict_low_part (match_operand:HI 0 "general_operand_dst" "=r,r,r,o,<"))
(plus:HI (match_operand:HI 1 "general_operand_src" "g") (match_operand:HI 1 "general_operand_src" "I,r,io,r,r"))]
(match_operand:HI 2 "register_operand" "ra")))]
""
"mov.w %T1,%T0\;add.w %T2,%T0"
[(set_attr "type" "arith")
(set_attr "length" "6")
(set_attr "cc" "set")])
;; movqi
(define_insn ""
[(set (match_operand:QI 0 "push_operand" "=<")
(match_operand:QI 1 "register_operand" "r"))]
""
"mov.w %T1,%T0"
[(set_attr "type" "move")
(set_attr "length" "2")
(set_attr "cc" "set")])
(define_insn "movstrictqi"
[(set (strict_low_part (match_operand:QI 0 "general_operand_dst" "=r,r,r,o,<"))
(match_operand:QI 1 "general_operand_src" "I,r,io,r,r"))]
"" ""
"@ "@
sub.b %X0,%X0 sub.w %T0,%T0
mov.b %X1,%X0 mov.w %T1,%T0
mov.b %X1,%X0 mov.w %T1,%T0
mov.b %X1,%X0 mov.w %T1,%T0
mov.b %X1,%X0" mov.w %T1,%T0"
[(set_attr "type" "move") [(set_attr "type" "move")
(set_attr "length" "2,2,4,4,2") (set_attr_alternative "length"
[(const_int 2) (const_int 2)
(if_then_else (eq_attr "cpu" "h8300") (const_int 4) (const_int 8))
(if_then_else (eq_attr "cpu" "h8300") (const_int 4) (const_int 8))
(if_then_else (eq_attr "cpu" "h8300") (const_int 2) (const_int 4))])
(set_attr "cc" "set")]) (set_attr "cc" "set")])
(define_insn "" ;; movsi
[(set (match_operand:QI 0 "general_operand_dst" "=r,r,r,o,<")
(match_operand:QI 1 "general_operand_src" "I,r,io,r,r"))]
""
"@
sub.b %X0,%X0
mov.b %X1,%X0
mov.b %X1,%X0
mov.b %X1,%X0
mov.b %X1,%X0"
[(set_attr "type" "move")
(set_attr "length" "2,2,4,4,2")
(set_attr "cc" "set")])
(define_expand "movqi" (define_expand "movsi"
[(set (match_operand:QI 0 "general_operand_dst" "") [(set (match_operand:SI 0 "general_operand_dst" "")
(match_operand:QI 1 "general_operand_src" ""))] (match_operand:SI 1 "general_operand_src" ""))]
"" ""
" "
{ {
/* One of the ops has to be in a register. */ if (TARGET_H8300)
if (! register_operand (operand0, QImode) {
&& ! register_operand (operand1, QImode)) if (do_movsi (operands))
operands[1] = copy_to_mode_reg (QImode, operand1); DONE;
}
else /* TARGET_H8300H */
{
/* One of the ops has to be in a register. */
if (!register_operand (operand1, SImode)
&& !register_operand (operand0, SImode))
{
operands[1] = copy_to_mode_reg (SImode, operand1);
}
}
}") }")
;; movsi (define_expand "movsf"
[(set (match_operand:SF 0 "general_operand_dst" "")
(define_insn "" (match_operand:SF 1 "general_operand_src" ""))]
[(set (match_operand:SI 0 "general_operand_dst" "=l,l,l,o,<")
(match_operand:SI 1 "general_operand_src" "I,l,ion,l,l"))]
"" ""
"
{
if (TARGET_H8300)
{
if (do_movsi (operands))
DONE;
}
else /* TARGET_H8300H */
{
/* One of the ops has to be in a register. */
if (!register_operand (operand1, SFmode)
&& !register_operand (operand0, SFmode))
{
operands[1] = copy_to_mode_reg (SFmode, operand1);
}
}
}")
(define_insn "movsi_h8300"
[(set (match_operand:SI 0 "general_operand_dst" "=r,r,r,o,<,r")
(match_operand:SI 1 "general_operand_src" "I,r,ion,r,r,>"))]
"TARGET_H8300
&& (register_operand (operands[0], SImode)
|| register_operand (operands[1], SImode))"
"* "*
{ {
int rn = -1; int rn = -1;
...@@ -176,181 +260,203 @@ ...@@ -176,181 +260,203 @@
case 0: case 0:
return \"sub.w %e0,%e0\;sub.w %f0,%f0\"; return \"sub.w %e0,%e0\;sub.w %f0,%f0\";
case 1: case 1:
return \"mov.w %e1,%e0\;mov.w %f1,%f0\"; if (REGNO(operands[0]) < REGNO(operands[1]))
return \"mov.w %e1,%e0\;mov.w %f1,%f0\";
else
return \"mov.w %f1,%f0\;mov.w %e1,%e0\";
case 2: case 2:
/* Make sure we don't trample the register we index with. */ /* Make sure we don't trample the register we index with. */
if (GET_CODE (operands[1]) == MEM) if (GET_CODE(operands[1]) == MEM)
{ {
rtx inside = XEXP (operands[1], 0); rtx inside = XEXP (operands[1],0);
if (REG_P (inside)) if (REG_P (inside))
rn = REGNO (inside); {
rn = REGNO(inside);
}
else if (GET_CODE (inside) == PLUS) else if (GET_CODE (inside) == PLUS)
{ {
rtx lhs = XEXP (inside, 0); rtx lhs = XEXP (inside,0);
rtx rhs = XEXP (inside, 1); rtx rhs = XEXP (inside,1);
if (REG_P (lhs)) if (REG_P (lhs)) rn = REGNO (lhs);
rn = REGNO (lhs); if (REG_P (rhs)) rn = REGNO (rhs);
if (REG_P (rhs))
rn = REGNO (rhs);
} }
} }
if (rn == REGNO (operands[0])) if (rn == REGNO (operands[0]))
/* Move the second word first. */ {
return \"mov.w %f1,%f0\;mov.w %e1,%e0\"; /* Move the second word first. */
return \"mov.w %f1,%f0\;mov.w %e1,%e0\";
}
else else
return \"mov.w %e1,%e0\;mov.w %f1,%f0\"; {
return \"mov.w %e1,%e0\;mov.w %f1,%f0\";
}
case 3: case 3:
return \"mov.w %e1,%e0\;mov.w %f1,%f0\"; return \"mov.w %e1,%e0\;mov.w %f1,%f0\";
case 4: case 4:
return \"mov.w %f1,%T0\;mov.w %e1,%T0\"; return \"mov.w %f1,%T0\;mov.w %e1,%T0\";
case 5:
return \"mov.w %T1,%e0\;mov.w %T1,%f0\";
} }
}" }"
[(set_attr "type" "move") [(set_attr "type" "move")
(set_attr "length" "4,4,8,8,4") (set_attr "length" "4,4,8,8,4,4")
(set_attr "cc" "clobber")])
(define_insn ""
[(set (match_operand:SI 0 "push_operand" "=<")
(match_operand:SI 1 "register_operand" "l"))]
""
"mov.w %f1,%T0\;mov.w %e1,%T0"
[(set_attr "type" "move")
(set_attr "length" "4")
(set_attr "cc" "clobber")]) (set_attr "cc" "clobber")])
(define_expand "movsi" (define_insn "movsf_h8300"
[(set (match_operand:SI 0 "general_operand_dst" "") [(set (match_operand:SF 0 "general_operand_dst" "=r,r,r,o,<,r")
(match_operand:SI 1 "general_operand_src" ""))] (match_operand:SF 1 "general_operand_src" "I,r,ion,r,r,>"))]
"" "TARGET_H8300
"if (domovsi (operands)) DONE;") && (register_operand (operands[0], SFmode)
|| register_operand (operands[1], SFmode))"
(define_insn ""
[(set (match_operand:SF 0 "general_operand_dst" "=l,l,l,o,<")
(match_operand:SF 1 "general_operand_src" "I,l,ion,l,l"))]
""
"* "*
{ {
/* This is a copy of the movsi stuff. */ /* Copy of the movsi stuff */
int rn = -1; int rn = -1;
switch (which_alternative) switch (which_alternative)
{ {
case 0: case 0:
return \"sub.w %e0,%e0\;sub.w %f0,%f0\"; return \"sub.w %e0,%e0\;sub.w %f0,%f0\";
case 1: case 1:
return \"mov.w %e1,%e0\;mov.w %f1,%f0\"; if (REGNO(operands[0]) < REGNO(operands[1]))
return \"mov.w %e1,%e0\;mov.w %f1,%f0\";
else
return \"mov.w %f1,%f0\;mov.w %e1,%e0\";
case 2: case 2:
/* Make sure we don't trample the register we index with. */ /* Make sure we don't trample the register we index with. */
if (GET_CODE (operands[1]) == MEM) if (GET_CODE (operands[1]) == MEM)
{ {
rtx inside = XEXP (operands[1], 0); rtx inside = XEXP (operands[1],0);
if (REG_P (inside)) if (REG_P (inside))
rn = REGNO (inside); {
rn = REGNO (inside);
}
else if (GET_CODE (inside) == PLUS) else if (GET_CODE (inside) == PLUS)
{ {
rtx lhs = XEXP (inside, 0); rtx lhs = XEXP (inside,0);
rtx rhs = XEXP (inside, 1); rtx rhs = XEXP (inside,1);
if (REG_P (lhs)) if (REG_P (lhs)) rn = REGNO (lhs);
rn = REGNO (lhs); if (REG_P (rhs)) rn = REGNO (rhs);
if (REG_P (rhs))
rn = REGNO (rhs);
} }
} }
if (rn == REGNO (operands[0])) if (rn == REGNO (operands[0]))
/* Move the second word first. */ {
return \"mov.w %f1,%f0\;mov.w %e1,%e0\"; /* move the second word first */
return \"mov.w %f1,%f0\;mov.w %e1,%e0\";
}
else else
return \"mov.w %e1,%e0\;mov.w %f1,%f0\"; {
return \"mov.w %e1,%e0\;mov.w %f1,%f0\";
}
case 3: case 3:
return \"mov.w %e1,%e0\;mov.w %f1,%f0\"; return \"mov.w %e1,%e0\;mov.w %f1,%f0\";
case 4: case 4:
return \"mov.w %f1,%T0\;mov.w %e1,%T0\"; return \"mov.w %f1,%T0\;mov.w %e1,%T0\";
} case 5:
return \"mov.w %T1,%e0\;mov.w %T1,%f0\";
}
}" }"
[(set_attr "type" "move") [(set_attr "type" "move")
(set_attr "length" "4,4,8,8,4") (set_attr "length" "4,4,8,8,4,4")
(set_attr "cc" "clobber")]) (set_attr "cc" "clobber")])
(define_insn "" (define_insn "movsi_h8300h"
[(set (match_operand:SF 0 "push_operand" "=<") [(set (match_operand:SI 0 "general_operand_dst" "=ra,ra,ra,o,<,ra")
(match_operand:SF 1 "register_operand" "l"))] (match_operand:SI 1 "general_operand_src" "I,ra,ion,ra,ra,>"))]
"" "TARGET_H8300H
"mov.w %f1,%T0\;mov.w %e1,%T0" && (register_operand (operands[0], SImode)
|| register_operand (operands[1], SImode))"
"@
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 "type" "move") [(set_attr "type" "move")
(set_attr "length" "4") (set_attr "length" "2,2,8,8,4,4")
(set_attr "cc" "clobber")]) (set_attr "cc" "set")])
(define_expand "movsf"
[(set (match_operand:SF 0 "general_operand_dst" "")
(match_operand:SF 1 "general_operand_src" ""))]
""
"if (domovsi (operands)) DONE;")
;; Block move (define_insn "movsf_h8300h"
[(set (match_operand:SF 0 "general_operand_dst" "=r,r,r,o,<")
(match_operand:SF 1 "general_operand_src" "I,r,ion,r,r"))]
"TARGET_H8300H
&& (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"
[(set_attr "type" "move")
(set_attr "length" "2,2,8,8,4")
(set_attr "cc" "set")])
(define_expand "movstrhi"
[(parallel [(set (mem:BLK (match_operand:BLK 0 "general_operand" ""))
(mem:BLK (match_operand:BLK 1 "general_operand" "")))
(use (match_operand:HI 2 "general_operand" ""))
(use (match_operand:HI 3 "immediate_operand" ""))
(clobber (match_dup 3))
])]
""
"
{
rtx src_ptr = copy_to_mode_reg (Pmode, XEXP (operands[1], 0));
rtx dst_ptr = copy_to_mode_reg (Pmode, XEXP (operands[0], 0));
enum machine_mode mode = INTVAL (operands[3]) >=2 ? HImode : QImode;
rtx tmpreg = gen_reg_rtx (mode);
rtx increment = mode == QImode ? const1_rtx : const2_rtx;
rtx length = operands[2];
rtx label = gen_label_rtx ();
rtx end_src_ptr = gen_reg_rtx (Pmode);
emit_insn (gen_rtx (SET, VOIDmode, end_src_ptr,
gen_rtx (PLUS, Pmode, src_ptr, length)));
emit_label (label);
emit_move_insn (tmpreg, gen_rtx (MEM, mode, src_ptr));
emit_move_insn (gen_rtx (MEM, mode, dst_ptr), tmpreg);
emit_insn (gen_rtx (SET, VOIDmode, src_ptr,
gen_rtx (PLUS, Pmode, src_ptr, increment)));
emit_insn (gen_rtx (SET, VOIDmode, dst_ptr,
gen_rtx (PLUS, Pmode, dst_ptr, increment)));
emit_insn (gen_rtx (SET, VOIDmode, cc0_rtx,
gen_rtx (COMPARE, HImode, src_ptr, end_src_ptr)));
emit_jump_insn (gen_bne (label));
DONE;
}
")
;; ---------------------------------------------------------------------- ;; ----------------------------------------------------------------------
;; Test instructions ;; TEST INSTRUCTIONS
;; ---------------------------------------------------------------------- ;; ----------------------------------------------------------------------
(define_insn "tstqi" (define_insn "tstqi"
[(set (cc0) [(set (cc0) (match_operand:QI 0 "register_operand" "ra"))]
(match_operand:QI 0 "register_operand" "ra"))]
"" ""
"cmp.b #0,%X0" "*
{
/* ??? I don't think this is right. --Jim */
if (cc_prev_status.flags & CC_DONE_CBIT)
return \"btst #0,%X0\";
else
return \"cmp.b #0,%X0\";
}"
[(set_attr "type" "arith") [(set_attr "type" "arith")
(set_attr "length" "2") (set_attr "length" "4")
(set_attr "cc" "set")]) (set_attr "cc" "set")])
(define_insn "tsthi" (define_insn "tsthi"
[(set (cc0) (match_operand:HI 0 "general_operand" "ra"))]
""
"*
{
/* ??? I don't think this is right. --Jim */
if (cc_prev_status.flags & CC_DONE_CBIT)
return \"btst #0,%0l\";
else
return \"mov.w %T0,%T0\";
}"
[(set_attr "type" "arith")
(set_attr "length" "4")
(set_attr "cc" "set")])
(define_insn "tstsi"
[(set (cc0) (match_operand:SI 0 "general_operand" "ra"))]
"TARGET_H8300H"
"*
{
/* ??? I don't think this is right. --Jim */
if (cc_prev_status.flags & CC_DONE_CBIT)
return \"btst #0,%0l\";
else
return \"mov.l %S0,%S0\";
}"
[(set_attr "type" "arith")
(set_attr "length" "4")
(set_attr "cc" "set")])
(define_insn "cmpqi"
[(set (cc0) [(set (cc0)
(match_operand:HI 0 "register_operand" "ra"))] (compare:QI (match_operand:QI 0 "register_operand" "ra")
(match_operand:QI 1 "nonmemory_operand" "rai")))]
"" ""
"mov.w %T0,%T0" "cmp.b %X1,%X0"
[(set_attr "type" "arith") [(set_attr "type" "arith")
(set_attr "length" "2") (set_attr "length" "2")
(set_attr "cc" "set")]) (set_attr "cc" "compare")])
;; ??? 300h can have an immediate operand here.
(define_insn "cmphi" (define_insn "cmphi"
[(set (cc0) [(set (cc0)
...@@ -362,111 +468,103 @@ ...@@ -362,111 +468,103 @@
(set_attr "length" "2") (set_attr "length" "2")
(set_attr "cc" "compare")]) (set_attr "cc" "compare")])
(define_insn "cmpqi" ;; ??? 300h can have an immediate operand here.
(define_insn "cmpsi"
[(set (cc0) [(set (cc0)
(compare:QI (match_operand:QI 0 "register_operand" "ra") (compare:SI (match_operand:SI 0 "register_operand" "ra")
(match_operand:QI 1 "nonmemory_operand" "rai")))] (match_operand:SI 1 "register_operand" "ra")))]
"" "TARGET_H8300H"
"cmp.b %X1,%X0" "cmp.l %S1,%S0"
[(set_attr "type" "arith") [(set_attr "type" "arith")
(set_attr "length" "2") (set_attr "length" "2")
(set_attr "cc" "compare")]) (set_attr "cc" "compare")])
;; ---------------------------------------------------------------------- ;; ----------------------------------------------------------------------
;; Add instructions ;; ADD INSTRUCTIONS
;; ---------------------------------------------------------------------- ;; ----------------------------------------------------------------------
(define_insn "" (define_insn "addqi3"
[(set (match_operand:QI 0 "register_operand" "=r")
(plus:QI (match_operand:QI 1 "register_operand" "%0")
(match_operand:QI 2 "nonmemory_operand" "ri")))]
""
"add.b %X2,%X0"
[(set_attr "type" "arith")
(set_attr "length" "2")
(set_attr "cc" "set")])
;; ??? adds operates on the 32bit register. We can use it because we don't
;; use the e0-7 registers.
;; ??? 4 can be handled in one insn on the 300h.
(define_insn "addhi3_internal"
[(set (match_operand:HI 0 "register_operand" "=ra,ra,ra,ra,r,ra") [(set (match_operand:HI 0 "register_operand" "=ra,ra,ra,ra,r,ra")
(plus:HI (match_operand:HI 1 "register_operand" "%0,0,0,0,0,0") (plus:HI (match_operand:HI 1 "register_operand" "%0,0,0,0,0,0")
(match_operand:HI 2 "nonmemory_operand" "K,M,L,N,n,ra")))] (match_operand:HI 2 "nonmemory_operand" "K,M,L,N,n,ra")))]
"" ""
"@ "@
adds %T2,%T0 adds %T2,%A0
adds #2,%T0\;adds %C2,%T0 adds #2,%A0\;adds %C2,%A0
subs %M2,%T0 subs %M2,%A0
subs #2,%T0\;subs %M2,%T0 subs #2,%A0\;subs %M2,%A0
add.b %s2,%s0\;addx %t2,%t0 add.b %s2,%s0\;addx %t2,%t0
add.w %T2,%T0" add.w %T2,%T0"
[(set_attr "type" "multi,multi,multi,multi,multi,arith") [(set_attr "type" "arith,multi,arith,multi,multi,arith")
(set_attr "length" "2,4,2,4,4,2") (set_attr "length" "2,4,2,4,4,2")
(set_attr "cc" "none_0hit,none_0hit,none_0hit,none_0hit,clobber,set")]) (set_attr "cc" "none_0hit,none_0hit,none_0hit,none_0hit,clobber,set")])
;; ??? Why is this here?
(define_expand "addhi3" (define_expand "addhi3"
[(set (match_operand:HI 0 "register_operand" "") [(set (match_operand:HI 0 "register_operand" "")
(plus:HI (match_operand:HI 1 "register_operand" "") (plus:HI (match_operand:HI 1 "register_operand" "")
(match_operand:HI 2 "nonmemory_operand" "")))] (match_operand:HI 2 "nonmemory_operand" "")))]
"" ""
" "")
{
if (operands[0] != operands[1])
emit_move_insn (operands[0], operands[1]);
}")
(define_insn "addqi3" (define_expand "addsi3"
[(set (match_operand:QI 0 "register_operand" "=r") [(set (match_operand:SI 0 "register_operand" "")
(plus:QI (match_operand:QI 1 "register_operand" "%0") (plus:SI (match_operand:SI 1 "register_operand" "")
(match_operand:QI 2 "nonmemory_operand" "ri")))] (match_operand:SI 2 "nonmemory_operand" "")))]
"" ""
"add.b %X2,%X0" "")
[(set_attr "type" "arith")
(set_attr "length" "2")
(set_attr "cc" "set")])
(define_insn "" (define_insn "addsi_h8300"
[(set (match_operand:SI 0 "register_operand" "=l,l") [(set (match_operand:SI 0 "register_operand" "=r,r,&r")
(plus:SI (match_operand:SI 1 "register_operand" "%0,0") (plus:SI (match_operand:SI 1 "register_operand" "%0,0,r")
(match_operand:SI 2 "nonmemory_operand" "l,n"))) (match_operand:SI 2 "nonmemory_operand" "n,r,r")))]
(clobber (match_operand:HI 3 "register_operand" "=&l,l"))] "TARGET_H8300"
""
"@ "@
add %w2,%w0\;addx %x2,%x0\;addx %y2,%y0\;addx %z2,%z0 add %w2,%w0\;addx %x2,%x0\;addx %y2,%y0\;addx %z2,%z0
add.w %f2,%f0\;addx %y2,%y0\;addx %z2,%z0" add.w %f2,%f0\;addx %y2,%y0\;addx %z2,%z0
[(set_attr "type" "multi") mov %f1,%f0\;mov %e1,%e0\;add.w %f2,%f0\;addx %y2,%y0\;addx %z2,%z0"
(set_attr "length" "8,6") [(set_attr "type" "arith")
(set_attr "length" "8,6,20")
(set_attr "cc" "clobber")]) (set_attr "cc" "clobber")])
(define_insn "" ;; ??? 4 can be handled in one insn on the 300h.
[(set (match_operand:SI 0 "register_operand" "=l,l") ;; ??? Should the 'n' constraint be 'i' here?
(plus:SI (match_operand:SI 1 "register_operand" "%0,0") ;; ??? We don't handle (reg + symbol_ref) which the 300h can handle.
(match_operand:SI 2 "nonmemory_operand" "n,r")))]
"" (define_insn "addsi_h8300h"
[(set (match_operand:SI 0 "register_operand" "=ra,ra,ra,ra,r,ra")
(plus:SI (match_operand:SI 1 "register_operand" "%0,0,0,0,0,0")
(match_operand:SI 2 "nonmemory_operand" "K,M,L,N,n,ra")))]
"TARGET_H8300H"
"@ "@
add %w2,%w0\;addx %x2,%x0\;addx %y2,%y0\;addx %z2,%z0 adds %S2,%S0
add.w %f2,%f0\;addx %y2,%y0\;addx %z2,%z0" adds #2,%S0\;adds %C2,%S0
[(set_attr "type" "arith") subs %M2,%S0
(set_attr "length" "8,6") subs #2,%S0\;subs %M2,%S0
(set_attr "cc" "clobber")]) add.l %S2,%S0
add.l %S2,%S0"
[(set_attr "type" "multi,multi,multi,multi,arith,arith")
(set_attr "length" "2,4,2,4,6,2")
(set_attr "cc" "none_0hit,none_0hit,none_0hit,none_0hit,clobber,clobber")])
(define_expand "addsi3"
[(set (match_dup 3) (match_operand:SI 1 "register_operand" ""))
(set (match_dup 3)
(plus:SI (match_dup 3)
(match_operand:SI 2 "nonmemory_operand" "")))
(set (match_operand:SI 0 "register_operand" "") (match_dup 3))]
""
"
{
operands[3] = gen_rtx (REG, SImode, 0);
}")
;; ----------------------------------------------------------------------;
;; Subtract instructions
;; ---------------------------------------------------------------------- ;; ----------------------------------------------------------------------
;; SUBTRACT INSTRUCTIONS
(define_insn "" ;; ----------------------------------------------------------------------
[(set (match_operand:HI 0 "register_operand" "=ra,ra,ra,r")
(minus:HI (match_operand:HI 1 "general_operand" "0,0,0,0")
(match_operand:HI 2 "nonmemory_operand" "K,M,ra,n")))]
""
"@
subs %T2,%T0
subs #2,%T0\;subs %E2,%T0
sub.w %T2,%T0
add.b %E2,%s0\;addx %F2,%t0 ; -%0"
[(set_attr "type" "multi")
(set_attr "length" "2,4,2,4")
(set_attr "cc" "none_0hit,none_0hit,set,clobber")])
(define_insn "subqi3" (define_insn "subqi3"
[(set (match_operand:QI 0 "register_operand" "=r,r") [(set (match_operand:QI 0 "register_operand" "=r,r")
...@@ -480,52 +578,115 @@ ...@@ -480,52 +578,115 @@
(set_attr "length" "2") (set_attr "length" "2")
(set_attr "cc" "set")]) (set_attr "cc" "set")])
;; ??? subs operates on the 32bit register. We can use it because we don't
;; use the e0-7 registers.
;; ??? 4 can be handled in one insn on the 300h.
;; ??? The fourth alternative can use sub.w on the 300h.
;; ??? Should the 'n' constraint be an 'i' here?
(define_insn "subhi3_internal"
[(set (match_operand:HI 0 "register_operand" "=ra,ra,ra,r")
(minus:HI (match_operand:HI 1 "general_operand" "0,0,0,0")
(match_operand:HI 2 "nonmemory_operand" "K,M,ra,n")))]
""
"@
subs %T2,%T0
subs #2,%T0\;subs %M2,%T0
sub.w %T2,%T0
add.b %E2,%s0\;addx %F2,%t0 ; -%0"
[(set_attr "type" "multi")
(set_attr "length" "2,4,2,4")
(set_attr "cc" "none_0hit,none_0hit,set,clobber")])
;; ??? Why is this here?
(define_expand "subhi3" (define_expand "subhi3"
[(set (match_operand:HI 0 "register_operand" "") [(set (match_operand:HI 0 "register_operand" "")
(minus:HI (match_operand:HI 1 "register_operand" "") (minus:HI (match_operand:HI 1 "register_operand" "")
(match_operand:HI 2 "nonmemory_operand" "")))] (match_operand:HI 2 "nonmemory_operand" "")))]
"" ""
" "")
{
if (operands[0] != operands[1])
emit_move_insn (operands[0], operands[1]);
}")
(define_insn "" (define_expand "subsi3"
[(set (match_operand:SI 0 "register_operand" "=l") [(set (match_operand:SI 0 "register_operand" "")
(minus:SI (match_operand:SI 1 "register_operand" "%0") (minus:SI (match_operand:SI 1 "register_operand" "")
(match_operand:SI 2 "register_operand" "l")))] (match_operand:SI 2 "nonmemory_operand" "")))]
"" ""
"")
(define_insn "subsi3_h8300"
[(set (match_operand:SI 0 "register_operand" "=r")
(minus:SI (match_operand:SI 1 "register_operand" "0")
(match_operand:SI 2 "register_operand" "r")))]
"TARGET_H8300"
"sub.w %f2,%f0\;subx %y2,%y0\;subx %z2,%z0" "sub.w %f2,%f0\;subx %y2,%y0\;subx %z2,%z0"
[(set_attr "type" "arith") [(set_attr "type" "arith")
(set_attr "length" "6") (set_attr "length" "6")
(set_attr "cc" "clobber")]) (set_attr "cc" "clobber")])
(define_expand "subsi3" ;; ??? 4 can be handled in one insn on the 300h.
[(set (match_dup 3) (match_operand:SI 1 "register_operand" ""))
(set (match_dup 3) (define_insn "subsi3_h8300h"
(minus:SI (match_dup 3) [(set (match_operand:SI 0 "register_operand" "=ra,ra,ra,r")
(match_operand:SI 2 "nonmemory_operand" ""))) (minus:SI (match_operand:SI 1 "general_operand" "0,0,0,0")
(set (match_operand:SI 0 "register_operand" "") (match_dup 3))] (match_operand:SI 2 "nonmemory_operand" "K,M,ra,n")))]
"" "TARGET_H8300H"
"operands[3] = gen_rtx (REG, SImode, 0);") "@
subs %T2,%T0
subs #2,%T0\;subs %E2,%T0
sub.l %S2,%S0
sub.l %S2,%S0"
[(set_attr "type" "multi")
(set_attr "length" "2,4,2,6")
(set_attr "cc" "none_0hit,none_0hit,set,set")])
;; ---------------------------------------------------------------------- ;; ----------------------------------------------------------------------
;; Multiply instruction ;; MULTIPLY INSTRUCTIONS
;; ---------------------------------------------------------------------- ;; ----------------------------------------------------------------------
;; Note that the h8/300 can only handle umulqihi3.
(define_insn "mulqihi3"
[(set (match_operand:HI 0 "register_operand" "=r")
(mult:HI (sign_extend:HI (match_operand:QI 1 "general_operand" "%0"))
(sign_extend:HI (match_operand:QI 2 "register_operand" "r"))))]
"TARGET_H8300H"
"mulxs.b %X2,%T0"
[(set_attr "type" "multi")
(set_attr "length" "4")
(set_attr "cc" "set")])
(define_insn "mulhisi3"
[(set (match_operand:SI 0 "register_operand" "=r")
(mult:SI (sign_extend:SI (match_operand:HI 1 "general_operand" "%0"))
(sign_extend:SI (match_operand:HI 2 "register_operand" "r"))))]
"TARGET_H8300H"
"mulxs.w %T2,%S0"
[(set_attr "type" "multi")
(set_attr "length" "4")
(set_attr "cc" "set")])
(define_insn "umulqihi3" (define_insn "umulqihi3"
[(set (match_operand:HI 0 "register_operand" "=r") [(set (match_operand:HI 0 "register_operand" "=r")
(mult:HI (match_operand:QI 1 "general_operand" "%0") (mult:HI (zero_extend:HI (match_operand:QI 1 "general_operand" "%0"))
(match_operand:QI 2 "register_operand" "r")))] (zero_extend:HI (match_operand:QI 2 "register_operand" "r"))))]
"" ""
"mulxu %X2,%T0" "mulxu %X2,%T0"
[(set_attr "type" "multi") [(set_attr "type" "multi")
(set_attr "length" "2") (set_attr "length" "2")
(set_attr "cc" "none_0hit")]) (set_attr "cc" "none_0hit")])
(define_insn "umulhisi3"
[(set (match_operand:SI 0 "register_operand" "=r")
(mult:SI (zero_extend:SI (match_operand:HI 1 "general_operand" "%0"))
(zero_extend:SI (match_operand:HI 2 "register_operand" "r"))))]
"TARGET_H8300H"
"mulxu.w %T2,%S0"
[(set_attr "type" "multi")
(set_attr "length" "2")
(set_attr "cc" "none_0hit")])
;; ---------------------------------------------------------------------- ;; ----------------------------------------------------------------------
;; Divide instructions ;; DIVIDE INSTRUCTIONS
;; ---------------------------------------------------------------------- ;; ----------------------------------------------------------------------
(define_insn "udivqi3" (define_insn "udivqi3"
...@@ -538,6 +699,8 @@ ...@@ -538,6 +699,8 @@
(set_attr "length" "2") (set_attr "length" "2")
(set_attr "cc" "clobber")]) (set_attr "cc" "clobber")])
;; ??? Will divxu always work here?
(define_insn "divqi3" (define_insn "divqi3"
[(set (match_operand:QI 0 "register_operand" "=r") [(set (match_operand:QI 0 "register_operand" "=r")
(div:QI (match_operand:HI 1 "general_operand" "0") (div:QI (match_operand:HI 1 "general_operand" "0")
...@@ -547,85 +710,286 @@ ...@@ -547,85 +710,286 @@
[(set_attr "type" "multi") [(set_attr "type" "multi")
(set_attr "length" "2") (set_attr "length" "2")
(set_attr "cc" "clobber")]) (set_attr "cc" "clobber")])
(define_insn "udivhi3"
[(set (match_operand:HI 0 "register_operand" "=r")
(udiv:HI (match_operand:SI 1 "general_operand" "0")
(match_operand:HI 2 "register_operand" "r")))]
"TARGET_H8300H"
"divxu.w %T2,%S0"
[(set_attr "type" "multi")
(set_attr "length" "2")
(set_attr "cc" "clobber")])
(define_insn "divhi3"
[(set (match_operand:HI 0 "register_operand" "=r")
(div:HI (match_operand:SI 1 "general_operand" "0")
(match_operand:HI 2 "register_operand" "r")))]
"TARGET_H8300H"
"divxs.w %T2,%S0"
[(set_attr "type" "multi")
(set_attr "length" "4")
(set_attr "cc" "clobber")])
;; ---------------------------------------------------------------------- ;; ----------------------------------------------------------------------
;; And instructions ;; MOD INSTRUCTIONS
;; ---------------------------------------------------------------------- ;; ----------------------------------------------------------------------
(define_insn "andqi3" (define_insn "umodqi3"
[(set (match_operand:QI 0 "general_operand" "=r") [(set (match_operand:QI 0 "register_operand" "=r")
(and:QI (match_operand:QI 1 "general_operand" "%0") (umod:QI (match_operand:HI 1 "general_operand" "0")
(match_operand:QI 2 "general_operand" "rn")))] (match_operand:QI 2 "register_operand" "r")))]
"" ""
"and %X2,%X0" "divxu %X2,%T0\;mov %t0,%s0"
[(set_attr "type" "multi")
(set_attr "length" "4")
(set_attr "cc" "clobber")])
(define_insn "modqi3"
[(set (match_operand:QI 0 "register_operand" "=r")
(mod:QI (match_operand:HI 1 "general_operand" "0")
(match_operand:QI 2 "register_operand" "r")))]
"TARGET_H8300H"
"divxs.b %X2,%T0\;mov %t0,%s0"
[(set_attr "type" "multi")
(set_attr "length" "6")
(set_attr "cc" "clobber")])
(define_insn "umodhi3"
[(set (match_operand:HI 0 "register_operand" "=r")
(umod:HI (match_operand:SI 1 "general_operand" "0")
(match_operand:HI 2 "register_operand" "r")))]
"TARGET_H8300H"
"divxu.w %T2,%S0\;mov %e0,%f0"
[(set_attr "type" "multi")
(set_attr "length" "4")
(set_attr "cc" "clobber")])
(define_insn "modhi3"
[(set (match_operand:HI 0 "register_operand" "=r")
(mod:HI (match_operand:SI 1 "general_operand" "0")
(match_operand:HI 2 "register_operand" "r")))]
"TARGET_H8300H"
"divxs.w %T2,%S0\;mov %e0,%f0"
[(set_attr "type" "multi")
(set_attr "length" "6")
(set_attr "cc" "clobber")])
;; ----------------------------------------------------------------------
;; AND INSTRUCTIONS
;; ----------------------------------------------------------------------
(define_insn "andqi3_internal"
[(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")))]
"register_operand (operands[0], QImode) || o_operand (operands[2], QImode)"
"@
and %X2,%X0
bclr %W2,%X0"
[(set_attr "type" "arith") [(set_attr "type" "arith")
(set_attr "length" "2") (set_attr "length" "2,4")
(set_attr "cc" "set")]) (set_attr "cc" "set,none_0hit")])
(define_expand "andqi3"
[(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")))]
""
"
{
if (fix_bit_operand (operands, 'O', AND))
DONE;
}")
;; ??? Should have a bclr case here also.
(define_insn "andhi3" (define_insn "andhi3"
[(set (match_operand:HI 0 "register_operand" "=r") [(set (match_operand:HI 0 "register_operand" "=r")
(and:HI (match_operand:HI 1 "register_operand" "%0") (and:HI (match_operand:HI 1 "register_operand" "%0")
(match_operand:HI 2 "general_operand" "ri")))] (match_operand:HI 2 "nonmemory_operand" "ri")))]
"" ""
"and %s2,%s0\;and %t2,%t0" "*
{
if (GET_CODE (operands[2]) == CONST_INT)
{
int i = INTVAL (operands[2]);
if ((i & 0x00ff) != 0x00ff)
output_asm_insn (\"and %s2,%s0\", operands);
if ((i & 0xff00) != 0xff00)
output_asm_insn (\"and %t2,%t0\", operands);
return \"\";
}
return \"and %s2,%s0\;and %t2,%t0;\";
}"
[(set_attr "type" "multi") [(set_attr "type" "multi")
(set_attr "length" "4") (set_attr "length" "4")
(set_attr "cc" "clobber")]) (set_attr "cc" "clobber")])
;; ??? There is an iorsi3 for TARGET_H8300. Should we have andsi3?
(define_insn "andsi3"
[(set (match_operand:SI 0 "register_operand" "=r,r")
(and:SI (match_operand:SI 1 "register_operand" "%0,0")
(match_operand:SI 2 "nonmemory_operand" "r,i")))]
"TARGET_H8300H"
"@
and %S2,%S0
and %S2,%S0"
[(set_attr "type" "arith")
(set_attr "length" "4,6")
(set_attr "cc" "clobber")])
;; ---------------------------------------------------------------------- ;; ----------------------------------------------------------------------
;; Or instructions ;; OR INSTRUCTIONS
;; ---------------------------------------------------------------------- ;; ----------------------------------------------------------------------
(define_insn "iorqi3" (define_insn "iorqi3_internal"
[(set (match_operand:QI 0 "general_operand" "=r,U") [(set (match_operand:QI 0 "bit_operand" "=U,r")
(ior:QI (match_operand:QI 1 "general_operand" "%0,0") (ior:QI (match_operand:QI 1 "bit_operand" "%0,0")
(match_operand:QI 2 "general_operand" "rn,P")))] (match_operand:QI 2 "nonmemory_operand" "P,rn")))]
"" "register_operand (operands[0], QImode) || p_operand (operands[2], QImode)"
"@ "@
or %X2,%X0 bset %V2,%X0
bset %V2,%X0" or %X2,%X0"
[(set_attr "type" "arith") [(set_attr "type" "arith")
(set_attr "length" "2,4") (set_attr "length" "4,2")
(set_attr "cc" "set,none_0hit")]) (set_attr "cc" "none_0hit,set")])
(define_expand "iorqi3"
[(set (match_operand:QI 0 "bit_operand" "=r,U")
(ior:QI (match_operand:QI 1 "bit_operand" "%0,0")
(match_operand:QI 2 "nonmemory_operand" "rn,P")))]
""
"
{
if (fix_bit_operand (operands, 'P', IOR))
DONE;
}")
;; ??? Should have a bset case here also.
(define_insn "iorhi3" (define_insn "iorhi3"
[(set (match_operand:HI 0 "general_operand" "=r,r") [(set (match_operand:HI 0 "general_operand" "=r,r")
(ior:HI (match_operand:HI 1 "general_operand" "%0,0") (ior:HI (match_operand:HI 1 "general_operand" "%0,0")
(match_operand:HI 2 "general_operand" "J,ri")))] (match_operand:HI 2 "general_operand" "J,ri")))]
"" ""
"@ "*
or %s2,%s0 {
or %s2,%s0\;or %t2,%t0" if (TARGET_H8300)
{
if (GET_CODE (operands[2]) == CONST_INT)
{
int i = INTVAL (operands[2]);
if ((i & 0x00ff) != 0)
output_asm_insn (\"or %s2,%s0\", operands);
if ((i & 0xff00) != 0)
output_asm_insn (\"or %t2,%t0\", operands);
return \"\";
}
return \"or %s2,%s0\;or %t2,%t0; %2 or2\";
}
else
{
return \"or %S2,%S0\";
}
}"
[(set_attr "type" "multi") [(set_attr "type" "multi")
(set_attr "length" "2,4") (set_attr "length" "2,4")
(set_attr "cc" "clobber,clobber")]) (set_attr "cc" "clobber,clobber")])
(define_insn "iorsi3"
[(set (match_operand:SI 0 "register_operand" "=r")
(ior:SI (match_operand:SI 1 "register_operand" "%0")
(match_operand:SI 2 "nonmemory_operand" "ri")))]
""
"*
{
if (TARGET_H8300)
{
if (GET_CODE (operands[2]) == CONST_INT)
{
int i = INTVAL (operands[2]);
if ((i & 0x000000ff) != 0)
output_asm_insn (\"or %w2,%w0\", operands);
if ((i & 0x0000ff00) != 0)
output_asm_insn (\"or %x2,%x0\", operands);
if ((i & 0x00ff0000) != 0)
output_asm_insn (\"or %y2,%y0\", operands);
if ((i & 0xff000000) != 0)
output_asm_insn (\"or %z2,%z0\", operands);
return \"\";
}
return \"or %w2,%w0\;or %x2,%x0\;or %y2,%y0\;or %z2,%z0\;\";
}
else
{
return \"or %S2,%S0\";
}
}"
[(set_attr "type" "multi")
(set_attr "length" "8")
(set_attr "cc" "clobber")])
;; ---------------------------------------------------------------------- ;; ----------------------------------------------------------------------
;; Xor instructions ;; XOR INSTRUCTIONS
;; ---------------------------------------------------------------------- ;; ----------------------------------------------------------------------
(define_insn "xorqi3" (define_insn "xorqi3_internal"
[(set (match_operand:QI 0 "general_operand" "=r") [(set (match_operand:QI 0 "bit_operand" "=r,U")
(xor:QI (match_operand:QI 1 "general_operand" "%0") (xor:QI (match_operand:QI 1 "bit_operand" "%0,0")
(match_operand:QI 2 "nonmemory_operand" "ri")))] (match_operand:QI 2 "nonmemory_operand" "rn,P")))]
"" "register_operand (operands[0], QImode) || p_operand (operands[2], QImode)"
"xor %X2,%X0" "@
xor %X2,%X0
bnot %V2,%X0"
[(set_attr "type" "arith") [(set_attr "type" "arith")
(set_attr "length" "2") (set_attr "length" "2,4")
(set_attr "cc" "set")]) (set_attr "cc" "set,none_0hit")])
(define_expand "xorqi3"
[(set (match_operand:QI 0 "bit_operand" "=r,U")
(xor:QI (match_operand:QI 1 "bit_operand" "%0,0")
(match_operand:QI 2 "nonmemory_operand" "rn,O")))]
""
"
{
if (fix_bit_operand (operands, 'O', XOR))
DONE;
}")
(define_insn "xorhi3" (define_insn "xorhi3"
[(set (match_operand:HI 0 "general_operand" "=r") [(set (match_operand:HI 0 "register_operand" "=r")
(xor:HI (match_operand:HI 1 "general_operand" "%0") (xor:HI (match_operand:HI 1 "general_operand" "%0")
(match_operand:HI 2 "nonmemory_operand" "ri")))] (match_operand:HI 2 "nonmemory_operand" "ri")))]
"" ""
"xor %s2,%s0\;xor %t2,%t0" "*
{
if (TARGET_H8300)
return \"xor %s2,%s0\;xor %t2,%t0\";
else
return \"xor %S2,%S0\";
}"
[(set_attr "type" "multi") [(set_attr "type" "multi")
(set_attr "length" "4") (set_attr "length" "4")
(set_attr "cc" "clobber")]) (set_attr "cc" "clobber")])
;; ??? There is an iorsi3 for TARGET_H8300. Should we have xorsi3?
(define_insn "xorsi3"
[(set (match_operand:SI 0 "register_operand" "=r,r")
(xor:SI (match_operand:SI 1 "register_operand" "%0,0")
(match_operand:SI 2 "nonmemory_operand" "r,i")))]
"TARGET_H8300H"
"@
xor %S2,%S0
xor %S2,%S0"
[(set_attr "type" "arith")
(set_attr "length" "4,6")
(set_attr "cc" "clobber")])
;; ---------------------------------------------------------------------- ;; ----------------------------------------------------------------------
;; Negation instructions ;; NEGATION INSTRUCTIONS
;; ---------------------------------------------------------------------- ;; ----------------------------------------------------------------------
(define_insn "negqi2" (define_insn "negqi2"
...@@ -635,28 +999,72 @@ ...@@ -635,28 +999,72 @@
"neg %X0" "neg %X0"
[(set_attr "type" "arith") [(set_attr "type" "arith")
(set_attr "length" "2") (set_attr "length" "2")
(set_attr "cc" "set")]) (set_attr "cc" "clobber")])
(define_expand "neghi2" (define_expand "neghi2"
[(set (match_operand:HI 0 "register_operand" "=r")
(neg:HI (match_operand:HI 1 "general_operand" "0")))]
""
"
{
if (TARGET_H8300)
{
emit_insn (gen_neghi2_h8300 (operands[0], operands[1]));
DONE;
}
}")
(define_expand "neghi2_h8300"
[(set (match_dup 2) [(set (match_dup 2)
(not:HI (match_operand:HI 1 "register_operand" "r"))) (not:HI (match_operand:HI 1 "register_operand" "r")))
(set (match_dup 2) (plus:HI (match_dup 2) (const_int 1))) (set (match_dup 2) (plus:HI (match_dup 2) (const_int 1)))
(set (match_operand:HI 0 "register_operand" "=r") (set (match_operand:HI 0 "register_operand" "=r")
(match_dup 2))] (match_dup 2))]
"" ""
"operands[2] = gen_reg_rtx (HImode);") "{ operands[2] = gen_reg_rtx (HImode); }")
(define_insn "neghi2_h8300h"
[(set (match_operand:HI 0 "register_operand" "=r")
(neg:HI (match_operand:HI 1 "general_operand" "0")))]
"TARGET_H8300H"
"neg %T0"
[(set_attr "type" "arith")
(set_attr "length" "2")
(set_attr "cc" "clobber")])
(define_expand "negsi2" (define_expand "negsi2"
[(set (match_operand:SI 0 "register_operand" "=r")
(neg:SI (match_operand:SI 1 "general_operand" "0")))]
""
"
{
if (TARGET_H8300)
{
emit_insn (gen_negsi2_h8300 (operands[0], operands[1]));
DONE;
}
}")
(define_expand "negsi2_h8300"
[(set (match_dup 2) [(set (match_dup 2)
(not:SI (match_operand:SI 1 "register_operand" "r"))) (not:SI (match_operand:SI 1 "register_operand" "r")))
(set (match_dup 2) (plus:SI (match_dup 2) (const_int 1))) (set (match_dup 2) (plus:SI (match_dup 2) (const_int 1)))
(set (match_operand:SI 0 "register_operand" "=r") (set (match_operand:SI 0 "register_operand" "=r")
(match_dup 2))] (match_dup 2))]
"" ""
"operands[2] = gen_reg_rtx (SImode);") "{ operands[2] = gen_reg_rtx(SImode); }")
(define_insn "negsi2_h8300h"
[(set (match_operand:SI 0 "register_operand" "=r")
(neg:SI (match_operand:SI 1 "general_operand" "0")))]
"TARGET_H8300H"
"neg %S0"
[(set_attr "type" "arith")
(set_attr "length" "2")
(set_attr "cc" "clobber")])
;; ---------------------------------------------------------------------- ;; ----------------------------------------------------------------------
;; Not instructions ;; NOT INSTRUCTIONS
;; ---------------------------------------------------------------------- ;; ----------------------------------------------------------------------
(define_insn "one_cmplqi2" (define_insn "one_cmplqi2"
...@@ -672,7 +1080,13 @@ ...@@ -672,7 +1080,13 @@
[(set (match_operand:HI 0 "register_operand" "=r") [(set (match_operand:HI 0 "register_operand" "=r")
(not:HI (match_operand:HI 1 "general_operand" "0")))] (not:HI (match_operand:HI 1 "general_operand" "0")))]
"" ""
"not %s0\;not %t0" "*
{
if (TARGET_H8300)
return \"not %s0\;not %t0\";
else
return \"not %T0\";
}"
[(set_attr "type" "arith") [(set_attr "type" "arith")
(set_attr "length" "4") (set_attr "length" "4")
(set_attr "cc" "clobber")]) (set_attr "cc" "clobber")])
...@@ -681,15 +1095,24 @@ ...@@ -681,15 +1095,24 @@
[(set (match_operand:SI 0 "register_operand" "=r") [(set (match_operand:SI 0 "register_operand" "=r")
(not:SI (match_operand:SI 1 "general_operand" "0")))] (not:SI (match_operand:SI 1 "general_operand" "0")))]
"" ""
"not %w0\;not %x0\;not %y0\;not %z0" "*
{
if (TARGET_H8300)
return \"not %w0\;not %x0\;not %y0\;not %z0\";
else
return \"not %S0\";
}"
[(set_attr "type" "arith") [(set_attr "type" "arith")
;; ??? length is wrong for 300h
(set_attr "length" "8") (set_attr "length" "8")
(set_attr "cc" "clobber")]) (set_attr "cc" "clobber")])
;; ---------------------------------------------------------------------- ;; ----------------------------------------------------------------------
;; Conditional branches ;; JUMP INSTRUCTIONS
;; ---------------------------------------------------------------------- ;; ----------------------------------------------------------------------
;; Conditional jump instructions
(define_expand "ble" (define_expand "ble"
[(set (pc) [(set (pc)
(if_then_else (le (cc0) (if_then_else (le (cc0)
...@@ -780,43 +1203,46 @@ ...@@ -780,43 +1203,46 @@
"" ""
"") "")
(define_insn "" (define_insn "branch_true"
[(set (pc) [(set (pc)
(if_then_else (if_then_else (match_operator 1 "comparison_operator"
(match_operator 1 "comparison_operator" [(cc0) (const_int 0)]) [(cc0) (const_int 0)])
(label_ref (match_operand 0 "" "")) (label_ref (match_operand 0 "" ""))
(pc)))] (pc)))]
"" ""
"* "*
{ {
if (get_attr_length (insn) == 2) if (get_attr_length (insn) == 2)
return \"b%j1 %l0\"; return \"b%j1 %l0\";
else if (get_attr_length (insn) == 4)
return \"b%j1 %l0:16\";
else else
return \"b%k1 %L0\;jmp @%l0\;%L0:\"; return \"b%k1 %L0\;jmp @%l0\;%L0:\";
}" }"
[(set_attr "type" "branch") [(set_attr "type" "branch")
(set_attr "cc" "none")]) (set_attr "cc" "none")])
(define_insn "" (define_insn "branch_false"
[(set (pc) [(set (pc)
(if_then_else (if_then_else (match_operator 1 "comparison_operator"
(match_operator 1 "comparison_operator" [(cc0) (const_int 0)]) [(cc0) (const_int 0)])
(pc) (pc)
(label_ref (match_operand 0 "" ""))))] (label_ref (match_operand 0 "" ""))))]
"" ""
;; ??? We don't take advantage of 16 bit relative jumps in the 300h.
"* "*
{ {
if (get_attr_length (insn) == 2) if (get_attr_length (insn) == 2)
return \"b%k1 %l0\"; return \"b%k1 %l0\";
else if (get_attr_length (insn) == 4)
return \"b%k1 %l0:16\";
else else
return \"b%j1 %L0\;jmp @%l0\;%L0:\"; return \"b%j1 %L0\;jmp @%l0\;%L0:\";
}" }"
[(set_attr "type" "branch") [(set_attr "type" "branch")
(set_attr "cc" "none")]) (set_attr "cc" "none")])
;; ---------------------------------------------------------------------- ;; Unconditional and other jump instructions.
;; Unconditional branches
;; ----------------------------------------------------------------------
(define_insn "jump" (define_insn "jump"
[(set (pc) [(set (pc)
...@@ -824,28 +1250,84 @@ ...@@ -824,28 +1250,84 @@
"" ""
"* "*
{ {
if (get_attr_length (insn) == 2) if (get_attr_length (insn) == 2)
return \"bra %l0\"; return \"bra %l0\";
else if (get_attr_length (insn) == 4)
return \"bra %l0:16\";
else else
return \"jmp @%l0\"; return \"jmp @%l0\";
}" }"
[(set_attr "type" "branch") [(set_attr "type" "branch")
(set_attr "cc" "none")]) (set_attr "cc" "none")])
(define_insn "tablejump" ;; 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" "r"))
(use (label_ref (match_operand 1 "" "")))])]
""
"")
(define_insn "tablejump_h8300"
[(set (pc) (match_operand:HI 0 "register_operand" "")) [(set (pc) (match_operand:HI 0 "register_operand" ""))
(use (label_ref (match_operand 1 "" "")))] (use (label_ref (match_operand 1 "" "")))]
"" "TARGET_H8300"
"jmp @%0" "jmp @%0"
[(set_attr "type" "branch") [(set_attr "type" "branch")
(set_attr "cc" "none") (set_attr "cc" "none")
(set_attr "length" "2")]) (set_attr "length" "2")])
;; Call subroutine with no return value. (define_insn "tablejump_h8300h"
[(set (pc) (match_operand:SI 0 "register_operand" ""))
(use (label_ref (match_operand 1 "" "")))]
"TARGET_H8300H"
"jmp @%0"
[(set_attr "type" "branch")
(set_attr "cc" "none")
(set_attr "length" "2")])
(define_insn "call" ;; This is a define expand, because pointers may be either 16 or 32 bits.
[(call (match_operand:QI 0 "memory_operand" "o")
(match_operand:HI 1 "general_operand" "g"))] ;(define_insn "indirect_jump"
; [(set (pc) (match_operand:HI 0 "register_operand" "r"))]
; ""
; "jmp @%0"
; [(set_attr "type" "branch")
; (set_attr "cc" "none")
; (set_attr "length" "2")])
(define_expand "indirect_jump"
[(set (pc) (match_operand 0 "jump_address_operand" "Vr"))]
""
"")
(define_insn "indirect_jump_h8300"
[(set (pc) (match_operand:HI 0 "jump_address_operand" "V,r"))]
"TARGET_H8300"
"@
jmp @%0
jmp @%0"
[(set_attr "type" "branch")
(set_attr "cc" "none")
(set_attr "length" "2")])
(define_insn "indirect_jump_h8300h"
[(set (pc) (match_operand:SI 0 "jump_address_operand" "V,r"))]
"TARGET_H8300H"
"@
jmp @%0
jmp @%0"
[(set_attr "type" "branch")
(set_attr "cc" "none")
(set_attr "length" "2")])
;; Call subroutine with no return value.
;; ??? Even though we use HImode here, this works for the 300h.
(define_insn "call"
[(call (match_operand:QI 0 "call_insn_operand" "or")
(match_operand:HI 1 "general_operand" "g"))]
"" ""
"jsr %0" "jsr %0"
[(set_attr "type" "call") [(set_attr "type" "call")
...@@ -855,9 +1337,11 @@ ...@@ -855,9 +1337,11 @@
;; Call subroutine, returning value in operand 0 ;; Call subroutine, returning value in operand 0
;; (which must be a hard register). ;; (which must be a hard register).
;; ??? Even though we use HImode here, this works on the 300h.
(define_insn "call_value" (define_insn "call_value"
[(set (match_operand 0 "" "=r") [(set (match_operand 0 "" "=r")
(call (match_operand:QI 1 "memory_operand" "o") (call (match_operand:QI 1 "call_insn_operand" "or")
(match_operand:HI 2 "general_operand" "g")))] (match_operand:HI 2 "general_operand" "g")))]
"" ""
"jsr %1" "jsr %1"
...@@ -873,450 +1357,862 @@ ...@@ -873,450 +1357,862 @@
(set_attr "cc" "none") (set_attr "cc" "none")
(set_attr "length" "2")]) (set_attr "length" "2")])
(define_insn "indirect_jump" ;; ----------------------------------------------------------------------
[(set (pc) (match_operand:HI 0 "register_operand" "r"))] ;; EXTEND INSTRUCTIONS
"" ;; ----------------------------------------------------------------------
"jmp @%0"
[(set_attr "type" "branch")
(set_attr "cc" "none")
(set_attr "length" "2")])
;; -----------------------------------------------------------------
;; Shifts
;; -----------------------------------------------------------------
;; All H8 shifts go one bit at a time, here they are defined with names
;; so can use them in the expands..
;; QI BIT SHIFTS
(define_insn "ashlqi3_one"
[(set (match_operand:QI 0 "register_operand" "=r")
(ashift:QI (match_operand:QI 1 "register_operand" "0")
(const_int 1)))]
""
"shal %X0"
[(set_attr "type" "arith")
(set_attr "length" "2")
(set_attr "cc" "set")])
(define_insn "ashrqi3_one" (define_insn "zero_extendqihi2"
[(set (match_operand:QI 0 "register_operand" "=r") [(set (match_operand:HI 0 "register_operand" "=r,r")
(ashiftrt:QI (match_operand:QI 1 "register_operand" "0") (zero_extend:HI (match_operand:QI 1 "general_operand" "0,g")))]
(const_int 1)))]
"" ""
"shar %X0" "*
[(set_attr "type" "arith") {
(set_attr "length" "2") if (which_alternative==0)
(set_attr "cc" "set")]) return \"mov.b #0,%t0\";
(define_insn "lshrqi3_one" if (TARGET_H8300)
[(set (match_operand:QI 0 "register_operand" "=r") return \"mov.b %X1,%s0\;mov.b #0,%t0\";
(lshiftrt:QI (match_operand:QI 1 "register_operand" "0") else
(const_int 1)))] {
"" /* ??? See how often this gets optimized. */
"shlr %X0" if (REG_P (operands[1]) && (REGNO (operands[1]) == REGNO (operands[0])))
[(set_attr "type" "arith") return \"extu.w %T0\";
(set_attr "length" "2") else
(set_attr "cc" "set")]) return \"mov.b %X1,%s0\;extu.w %T0\";
}
}"
[(set_attr "type" "multi")
;; ??? This length is wrong for one case.
(set_attr "length" "4")
(set_attr "cc" "clobber")])
(define_expand "ashlqi3" (define_insn "zero_extendhisi2"
[(set (match_operand:QI 0 "register_operand" "=r") [(set (match_operand:SI 0 "register_operand" "=r")
(ashift:QI (match_operand:QI 1 "register_operand" "0") (zero_extend:SI (match_operand:HI 1 "general_operand" "g")))]
(match_operand:QI 2 "nonmemory_operand" "rn")))] "TARGET_H8300H"
"" "*
"
{ {
if (can_shift (ASHIFT, operands, gen_ashlqi3_one, 4, 0)) /* ??? See how often this gets optimized. */
DONE; if (REG_P (operands[1]) && (REGNO (operands[1]) == REGNO (operands[0])))
return \"extu.l %S0\";
else else
FAIL; return \"mov.w %T1,%T0\;extu.l %S0\";
}") }"
[(set_attr "type" "multi")
;; ??? This length is wrong for one case.
(set_attr "length" "4")
(set_attr "cc" "clobber")])
(define_expand "ashrqi3" (define_insn "extendqihi2"
[(set (match_operand:QI 0 "register_operand" "=r") [(set (match_operand:HI 0 "register_operand" "=r")
(ashiftrt:QI (match_operand:QI 1 "register_operand" "0") (sign_extend:HI (match_operand:QI 1 "general_operand" "g")))]
(match_operand:QI 2 "nonmemory_operand" "rn")))]
"" ""
" "*
{ {
if (can_shift (ASHIFTRT, operands, gen_ashrqi3_one, 4, 0)) if (TARGET_H8300)
DONE; {
/* ??? See how often this gets optimized. */
if (REG_P (operands[1]) && (REGNO (operands[1]) == REGNO (operands[0])))
return \"bld #7,%s0\;subx %t0,%t0\";
else
return \"mov.b %X1,%s0\;bld #7,%s0\;subx %t0,%t0\";
}
else else
FAIL; {
}") /* ??? See how often this gets optimized. */
if (REG_P (operands[1]) && (REGNO (operands[1]) == REGNO (operands[0])))
return \"exts.w %T0\";
else
return \"mov.b %X1,%s0\;exts.w %T0\";
}
}"
[(set_attr "type" "multi")
;; ??? Length is wrong in some cases.
(set_attr "length" "6")
(set_attr "cc" "clobber")])
(define_expand "lshrqi3" (define_expand "extendhisi2"
[(set (match_operand:QI 0 "register_operand" "=r") [(set (match_operand:SI 0 "register_operand" "")
(lshiftrt:QI (match_operand:QI 1 "register_operand" "0") (sign_extend:SI (match_operand:HI 1 "general_operand" "")))]
(match_operand:QI 2 "nonmemory_operand" "rn")))]
"" ""
" "
{ {
if (can_shift (LSHIFTRT, operands, gen_lshrqi3_one, 4, 0)) if (TARGET_H8300)
DONE; emit_insn (gen_extendhisi2_h8300 (operands[0], operands[1]));
else else
FAIL; emit_insn (gen_extendhisi2_h8300h (operands[0], operands[1]));
DONE;
}") }")
;; HI BIT SHIFTS (define_expand "extendhisi2_h8300"
[(set (reg:HI 1) (match_operand:HI 1 "general_operand" ""))
(set (reg:SI 0) (sign_extend:SI (reg:HI 1)))
(set (match_operand:SI 0 "general_operand" "" ) (reg:SI 0))]
"TARGET_H8300"
"")
(define_insn "ashlhi3_one" (define_expand "extendhisi2_h8300h"
[(set (match_operand:HI 0 "register_operand" "=r") [(set (match_operand:SI 0 "register_operand" "")
(ashift:HI (match_operand:HI 1 "register_operand" "0") (sign_extend:SI (match_operand:HI 1 "general_operand" "")))]
(const_int 1)))] "TARGET_H8300H"
"" "")
"add.w %T1,%T0"
[(set_attr "type" "multi")
(set_attr "length" "4")
(set_attr "cc" "set")])
(define_insn "ashlhi3_eight" (define_insn "extendhisi2_h8300_internal"
[(set (match_operand:HI 0 "register_operand" "=r") [(set (match_operand:SI 0 "register_operand" "=r")
(ashift:HI (match_operand:HI 1 "register_operand" "0") (sign_extend:SI (match_operand:HI 1 "register_operand" "0")))]
(const_int 8)))] "TARGET_H8300"
"" "mov.w %T1,%f0\;bld #7,%x0\;subx %y0,%y0\;subx %z0,%z0"
"mov.b %s1,%t0\;mov.b #0,%s0" [(set_attr "length" "10")
[(set_attr "type" "multi")
(set_attr "length" "4")
(set_attr "cc" "clobber")]) (set_attr "cc" "clobber")])
(define_expand "ashlhi3" (define_insn "extendhisi2_h8300h_internal"
[(set (match_operand:HI 0 "register_operand" "") [(set (match_operand:SI 0 "register_operand" "=r")
(ashift:HI (sign_extend:SI (match_operand:HI 1 "general_operand" "g")))]
(match_operand:HI 1 "general_operand_src" "") "TARGET_H8300H"
(match_operand:HI 2 "nonmemory_operand" "")))] "*
""
"
{ {
if (can_shift (ASHIFT, operands, gen_ashlhi3_one, 4, gen_ashlhi3_eight)) /* ??? See how often this gets optimized. */
DONE; if (REG_P (operands[1]) && (REGNO (operands[1]) == REGNO (operands[0])))
return \"exts.l %S0\";
else else
FAIL; return \"mov.w %T1,%T0\;exts.l %S0\";
}") }"
[(set_attr "length" "10")
(set_attr "cc" "clobber")])
(define_insn "lshrhi3_one" ;; ----------------------------------------------------------------------
[(set (match_operand:HI 0 "register_operand" "=r") ;; SHIFTS
(lshiftrt:HI (match_operand:HI 1 "register_operand" "0") ;; ----------------------------------------------------------------------
(const_int 1)))] ;;
;; 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.
;; QI BIT SHIFTS
(define_expand "ashlqi3"
[(set (match_operand:QI 0 "register_operand" "")
(ashift:QI (match_operand:QI 1 "register_operand" "")
(match_operand:QI 2 "nonmemory_operand" "")))]
"" ""
"shlr %t0\;rotxr %s0" "if (expand_a_shift (QImode, ASHIFT, operands)) DONE;else FAIL;")
[(set_attr "type" "multi")
(set_attr "length" "4")
(set_attr "cc" "clobber")])
(define_insn "lshrhi3_eight" (define_expand "ashrqi3"
[(set (match_operand:HI 0 "register_operand" "=r") [(set (match_operand:QI 0 "register_operand" "")
(lshiftrt:HI (match_operand:HI 1 "register_operand" "0") (ashiftrt:QI (match_operand:QI 1 "register_operand" "")
(const_int 8)))] (match_operand:QI 2 "nonmemory_operand" "")))]
"" ""
"mov.b %t1,%s0\;mov.b #0,%t0" "if (expand_a_shift (QImode, ASHIFTRT, operands)) DONE;else FAIL;")
[(set_attr "type" "multi")
(set_attr "length" "4")
(set_attr "cc" "clobber")])
(define_expand "lshrhi3" (define_expand "lshrqi3"
[(set (match_operand:HI 0 "register_operand" "") [(set (match_operand:QI 0 "register_operand" "")
(lshiftrt:HI (lshiftrt:QI (match_operand:QI 1 "register_operand" "")
(match_operand:HI 1 "general_operand_src" "") (match_operand:QI 2 "nonmemory_operand" "")))]
(match_operand:HI 2 "nonmemory_operand" "")))]
"" ""
" "if (expand_a_shift (QImode, LSHIFTRT, operands)) DONE;else FAIL;")
{
if (can_shift (LSHIFTRT, operands, gen_lshrhi3_one, 4, gen_lshrhi3_eight))
DONE;
else
FAIL;
}")
(define_insn "ashrhi3_one" ;; WARNING: The constraints on the scratch register say one is not needed
[(set (match_operand:HI 0 "register_operand" "=r") ;; for constant shifts of 1,2,3,4. Emit_a_shift() must know this.
(ashiftrt:HI (match_operand:HI 1 "register_operand" "0")
(const_int 1)))] (define_insn "shiftbyn_QI"
[(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" "IKM,rn")]))
(clobber (match_scratch:QI 4 "=X,&r"))]
"" ""
"shar %t0\;rotxr %s0" "* return emit_a_shift (insn, operands);"
[(set_attr "type" "multi") [(set_attr "type" "arith")
(set_attr "length" "4") (set_attr "length" "20")
;; ??? We'd like to indicate that cc is set here, and it is for simple shifts.
;; However, for cases that loop or are done in pieces, cc does not contain
;; what we want. Emit_a_shift is free to tweak cc_status as desired.
(set_attr "cc" "clobber")]) (set_attr "cc" "clobber")])
; signed shift right by 8 bits ;; HI BIT SHIFTS
; fetch the carry bit from the top, copy the byte right, subtract the
; top byte from itself - carry.
(define_insn "ashrhi3_eight" (define_expand "ashlhi3"
[(set (match_operand:HI 0 "register_operand" "=r") [(set (match_operand:HI 0 "register_operand" "")
(ashiftrt:HI (match_operand:HI 1 "register_operand" "0") (ashift:HI (match_operand:HI 1 "nonmemory_operand" "")
(const_int 8)))] (match_operand:QI 2 "nonmemory_operand" "")))]
"" ""
"bld #7,%t0\;mov.b %t0,%s0\;subx %t0,%t0" "if (expand_a_shift (HImode, ASHIFT, operands)) DONE;else FAIL;")
[(set_attr "type" "multi")
(set_attr "length" "6") (define_expand "lshrhi3"
(set_attr "cc" "clobber")]) [(set (match_operand:HI 0 "register_operand" "")
(lshiftrt:HI (match_operand:HI 1 "general_operand_src" "")
(match_operand:QI 2 "nonmemory_operand" "")))]
""
"if (expand_a_shift (HImode, LSHIFTRT, operands)) DONE;else FAIL;")
(define_expand "ashrhi3" (define_expand "ashrhi3"
[(set (match_operand:HI 0 "register_operand" "") [(set (match_operand:HI 0 "register_operand" "")
(ashiftrt:HI (ashiftrt:HI (match_operand:HI 1 "register_operand" "")
(match_operand:HI 1 "general_operand_src" "") (match_operand:QI 2 "nonmemory_operand" "")))]
(match_operand:HI 2 "nonmemory_operand" "")))]
"" ""
" "if (expand_a_shift (HImode, ASHIFTRT, operands)) DONE;else FAIL;")
{
if (can_shift (ASHIFTRT, operands, gen_ashrhi3_one, 4, gen_ashrhi3_eight))
DONE;
else
FAIL;
}")
;; SI BIT SHIFTS ;; WARNING: The constraints on the scratch register say one is not needed
;; for constant shifts of 1,2,3,4. Emit_a_shift() must know this.
(define_insn "ashlsi3_one" (define_insn "shiftbyn_HI"
[(set (match_operand:SI 0 "register_operand" "=r") [(set (match_operand:HI 0 "register_operand" "=r,r")
(ashift:SI (match_operand:SI 1 "register_operand" "0") (match_operator:HI 3 "nshift_operator"
(const_int 1)))] [ (match_operand:HI 1 "register_operand" "0,0")
(match_operand:QI 2 "nonmemory_operand" "IKM,rn")]))
(clobber (match_scratch:QI 4 "=X,&r"))]
"" ""
"add.w %f1,%f0\;addx %y1,%y0\;addx %z1,%z0" "* return emit_a_shift (insn, operands);"
[(set_attr "type" "multi") [(set_attr "type" "arith")
(set_attr "length" "6") (set_attr "length" "20")
;; ??? We'd like to indicate that cc is set here, and it is for simple shifts.
;; However, for cases that loop or are done in pieces, cc does not contain
;; what we want. Emit_a_shift is free to tweak cc_status as desired.
(set_attr "cc" "clobber")]) (set_attr "cc" "clobber")])
;; SI BIT SHIFTS
(define_expand "ashlsi3" (define_expand "ashlsi3"
[(set (match_operand:SI 0 "register_operand" "") [(set (match_operand:SI 0 "register_operand" "")
(ashift:SI (ashift:SI
(match_operand:SI 1 "general_operand_src" "") (match_operand:SI 1 "general_operand_src" "")
(match_operand:SI 2 "nonmemory_operand" "")))] (match_operand:QI 2 "nonmemory_operand" "")))]
"" ""
" "if (expand_a_shift (SImode, ASHIFT, operands)) DONE;else FAIL;")
{
if (can_shift (ASHIFT, operands, gen_ashlsi3_one, 1, 0))
DONE;
else
FAIL;
}")
(define_insn "lshrsi3_one"
[(set (match_operand:SI 0 "register_operand" "=r")
(lshiftrt:SI (match_operand:SI 1 "register_operand" "0")
(const_int 1)))]
""
"shlr %z0\;rotxr %y0\;rotxr %x0\;rotxr %w0"
[(set_attr "type" "multi")
(set_attr "length" "8")
(set_attr "cc" "clobber")])
(define_expand "lshrsi3" (define_expand "lshrsi3"
[(set (match_operand:SI 0 "register_operand" "") [(set (match_operand:SI 0 "register_operand" "")
(lshiftrt:SI (lshiftrt:SI
(match_operand:SI 1 "general_operand_src" "") (match_operand:SI 1 "general_operand_src" "")
(match_operand:SI 2 "nonmemory_operand" "")))] (match_operand:QI 2 "nonmemory_operand" "")))]
""
"
{
if (can_shift (LSHIFTRT, operands, gen_lshrsi3_one, 1, 0))
DONE;
else
FAIL;
}")
(define_insn "ashrsi3_one"
[(set (match_operand:SI 0 "register_operand" "=r")
(ashiftrt:SI (match_operand:SI 1 "register_operand" "0")
(const_int 1)))]
"" ""
"shar %z0\;rotxr %y0\;rotxr %x0\;rotxr %w0" "if (expand_a_shift (SImode, LSHIFTRT, operands)) DONE;else FAIL;")
[(set_attr "type" "multi")
(set_attr "length" "16")
(set_attr "cc" "clobber")])
(define_expand "ashrsi3" (define_expand "ashrsi3"
[(set (match_operand:SI 0 "register_operand" "") [(set (match_operand:SI 0 "register_operand" "")
(ashiftrt:SI (ashiftrt:SI
(match_operand:SI 1 "general_operand_src" "") (match_operand:SI 1 "general_operand_src" "")
(match_operand:SI 2 "nonmemory_operand" "")))] (match_operand:QI 2 "nonmemory_operand" "")))]
"" ""
" "if (expand_a_shift (SImode, ASHIFTRT, operands)) DONE;else FAIL;")
{
if (can_shift (ASHIFTRT, operands, gen_ashrsi3_one, 1, 0))
DONE;
else
FAIL;
}")
;; ---------------------------------------------------------------------- ;; WARNING: The constraints on the scratch register say one is not needed
;; BIT FIELDS ;; for constant shifts of 1,2. Emit_a_shift() must know this.
;; ----------------------------------------------------------------------
(define_insn "" (define_insn "shiftbyn_SI"
[(set (zero_extract:HI (match_operand:HI 0 "register_operand" "+r") [(set (match_operand:SI 0 "register_operand" "=r,r")
(const_int 1) (match_operator:SI 3 "nshift_operator"
(match_operand:HI 2 "general_operand" "g")) [ (match_operand:SI 1 "register_operand" "0,0")
(match_operand:HI 3 "general_operand" "r"))] (match_operand:QI 2 "nonmemory_operand" "IK,rn")]))
(clobber (match_scratch:QI 4 "=X,&r"))]
"" ""
"bld #0,%3l\;bst %Z2,%0%Y1" "* return emit_a_shift (insn, operands);"
[(set_attr "type" "multi") [(set_attr "type" "arith")
(set_attr "length" "4") (set_attr "length" "20")
;; ??? We'd like to indicate that cc is set here, and it is for simple shifts.
;; However, for cases that loop or are done in pieces, cc does not contain
;; what we want. Emit_a_shift is free to tweak cc_status as desired.
(set_attr "cc" "clobber")]) (set_attr "cc" "clobber")])
(define_expand "insv" ;; -----------------------------------------------------------------
[(set (zero_extract:HI (match_operand:HI 0 "register_operand" "+r") ;; BIT FIELDS
(match_operand:HI 1 "general_operand" "g") ;; -----------------------------------------------------------------
(match_operand:HI 2 "general_operand" "g")) ;; The H8/300 has given 1/8th of its opcode space to bitfield
(match_operand:HI 3 "general_operand" "r"))] ;; instuctions so let's use them as well as we can
""
"if (INTVAL (operands[1]) != 1) FAIL;")
(define_insn "" ;; BCC and BCS patterns.
[(set (match_operand:HI 0 "register_operand" "=&r")
(zero_extract:HI (match_operand:HI 1 "register_operand" "r") (define_insn "bcs_qiqi"
(const_int 1) [(set (pc)
(match_operand:HI 3 "general_operand" "g")))] (if_then_else
(match_operator 1 "eq_operator"
[(zero_extract:QI (match_operand:QI 2 "bit_operand" "Ur")
(const_int 1)
(match_operand:HI 3 "immediate_operand" "i"))
(const_int 0)])
(label_ref (match_operand 0 "" ""))
(pc)))]
"" ""
"sub.w %T0,%T0\;bld %Z3,%T1%Y1\;rotxl %T0l" "*
[(set_attr "type" "multi") {
(set_attr "length" "6") output_asm_insn(\"bld %Z3,%Y2\", operands);
if (get_attr_length (insn) == 2)
return \"b%d1 %l0\";
else if (get_attr_length (insn) == 4)
return \"b%d1 %l0:16\";
else
return \"b%g1 %L0\;jmp @%l0\;%L0:\";
}"
[(set_attr "type" "branch")
(set_attr "cc" "clobber")]) (set_attr "cc" "clobber")])
(define_insn "" (define_insn "bcs_hihi"
[(set (match_operand:HI 0 "register_operand" "=r") [(set (pc)
(sign_extract:HI (match_operand:HI 1 "register_operand" "r") (if_then_else
(const_int 1) (match_operator 1 "eq_operator"
(match_operand:HI 3 "general_operand" "g")))] [(zero_extract:HI (match_operand:HI 2 "bit_operand" "Ur")
(const_int 1)
(match_operand:HI 3 "immediate_operand" "i"))
(const_int 0)])
(label_ref (match_operand 0 "" ""))
(pc)))]
"" ""
"bld %Z3,%1%Y1\;sub.x %0l,%0l\;mov.b %0l,%0h" "*
[(set_attr "type" "multi") {
(set_attr "length" "6") output_asm_insn(\"bld %Z3,%Y2\", operands);
if (get_attr_length (insn) == 2)
return \"%d1 %l0\";
else if (get_attr_length (insn) == 4)
return \"%d1 %l0:16\";
else
return \"%g1 %L0\;jmp @%l0\;%L0:\";
}"
[(set_attr "type" "branch")
(set_attr "cc" "clobber")]) (set_attr "cc" "clobber")])
(define_expand "extzv" (define_insn "bcs_hiqi"
[(set (match_operand:HI 0 "register_operand" "") [(set (pc)
(zero_extract:HI (match_operand:HI 1 "register_operand" "") (if_then_else
(match_operand:HI 2 "general_operand" "") (match_operator 1 "eq_operator"
(match_operand:HI 3 "general_operand" "")))] [(zero_extract:HI (match_operand:QI 2 "bit_operand" "Ur")
(const_int 1)
(match_operand:HI 3 "immediate_operand" "i"))
(const_int 0)])
(label_ref (match_operand 0 "" ""))
(pc)))]
"" ""
"if (INTVAL (operands[2]) != 1) FAIL;") "*
{
output_asm_insn(\"bld %Z3,%Y2\", operands);
if (get_attr_length (insn) == 2)
return \"%d1 %l0\";
else if (get_attr_length (insn) == 4)
return \"%d1 %l0:16\";
else
return \"%g1 %L0\;jmp @%l0\;%L0:\";
}"
[(set_attr "type" "branch")
(set_attr "cc" "clobber")])
(define_expand "extv" ;; BLD and BST patterns
[(set (match_operand:HI 0 "register_operand" "")
(sign_extract:HI (match_operand:HI 1 "register_operand" "") (define_insn "extract_1"
(match_operand:HI 2 "general_operand" "") [(set (match_operand:HI 0 "register_operand" "=&r")
(match_operand:HI 3 "immediate_operand" "")))] (zero_extract:HI (match_operand:QI 1 "bit_operand" "Ur")
(const_int 1)
(match_operand:HI 2 "immediate_operand" "i")))]
"" ""
"if (INTVAL (operands[2]) != 1) FAIL;") "sub.w %0,%0\;bld %Z2,%Y1\;bst #0,%X0")
;; ----------------------------------------------------------------------
;; Conversions
;; ----------------------------------------------------------------------
(define_insn "zero_extendqihi2" (define_insn "extract_1_hi"
[(set (match_operand:HI 0 "register_operand" "=r") [(set (match_operand:HI 0 "register_operand" "=&r")
(zero_extend:HI (zero_extract:HI (match_operand:HI 1 "bit_operand" "Ur")
(match_operand:QI 1 "general_operand" "g")))] (const_int 1)
(match_operand:HI 2 "immediate_operand" "i")))]
"" ""
"mov.b %X1,%s0\;mov.b #0,%t0" "sub.w %0,%0\;bld %Z2,%Y1\;bst #0,%X0")
[(set_attr "type" "multi")
(set_attr "length" "4")
(set_attr "cc" "clobber")])
(define_insn "extendqihi2" (define_insn "insert_1"
[(set (match_operand:HI 0 "register_operand" "=r") [(set (zero_extract:HI (match_operand:QI 0 "bit_operand" "+Ur")
(sign_extend:HI (const_int 1)
(match_operand:QI 1 "register_operand" "r")))] (match_operand:HI 1 "immediate_operand" "i"))
(zero_extract:HI (match_operand:QI 2 "bit_operand" "Ur")
(const_int 1)
(const_int 0)))]
"" ""
"* "bld #0,%X2\;bst %Z1,%Y0 ; i1")
;; This is how combine canonicalizes this pattern. This is perhaps a bug
;; in combine.c, but there is no problem with writing it this way so we do.
(define_insn "extract_insert_1"
[(set (zero_extract:QI (match_operand:QI 0 "bit_operand" "+Ur")
(const_int 1)
(match_operand:HI 1 "immediate_operand" "i"))
(lshiftrt:QI (match_operand:QI 2 "bit_operand" "Ur")
(match_operand:HI 3 "immediate_operand" "i")))]
""
"bld %Z3,%Y2\;bst %Z1,%Y0; ei1")
;; BAND, BOR, and BXOR patterns
(define_insn "bitlogical_1"
[(set (match_operand:HI 0 "bit_operand" "=Ur")
(match_operator:HI 4 "bit_operator"
[(zero_extract:HI (match_operand:QI 1 "bit_operand" "Ur")
(const_int 1)
(match_operand:HI 2 "immediate_operand" "i"))
(match_operand:HI 3 "bit_operand" "0")]))]
""
"bld %Z2,%Y1\;%b4 #0,%X0\;bst #0,%X0; bl1")
(define_insn "bitlogical_1_hi"
[(set (match_operand:HI 0 "bit_operand" "=Ur")
(match_operator:HI 4 "bit_operator"
[(zero_extract:HI (match_operand:HI 1 "bit_operand" "Ur")
(const_int 1)
(match_operand:HI 2 "immediate_operand" "i"))
(match_operand:HI 3 "bit_operand" "0")]))]
""
"bld %Z2,%Y1\;%b4 #0,%X0\;bst #0,%X0; bl2")
(define_insn "bitlogical_2"
[(set (match_operand:HI 0 "bit_operand" "=Ur")
(match_operator:HI 5 "bit_operator"
[(zero_extract:HI (match_operand:QI 1 "bit_operand" "Ur")
(const_int 1)
(match_operand:HI 2 "immediate_operand" "i"))
(zero_extract:HI (match_operand:QI 3 "bit_operand" "Ur")
(const_int 1)
(match_operand:HI 4 "immediate_operand" "i"))]))]
""
"bld %Z2,%Y1\;%b5 %Z4,%Y3\;bst #0,%X0; bl3")
(define_insn "bitlogical_2_hi"
[(set (match_operand:HI 0 "bit_operand" "=Ur")
(match_operator:HI 5 "bit_operator"
[(zero_extract:HI (match_operand:HI 1 "bit_operand" "Ur")
(const_int 1)
(match_operand:HI 2 "immediate_operand" "i"))
(zero_extract:HI (match_operand:HI 3 "bit_operand" "Ur")
(const_int 1)
(match_operand:HI 4 "immediate_operand" "i"))]))]
""
"bld %Z2,%Y1\;%b5 %Z4,%Y3\;bst #0,%X0; bl3")
;; This is how combine canonicalizes this pattern. This is perhaps a bug
;; in combine.c, but there is no problem with writing it this way so we do.
(define_insn "bitlogical_3"
[(set (zero_extract:QI (match_operand:QI 0 "bit_operand" "+Ur")
(const_int 1)
(match_operand:HI 1 "immediate_operand" "i"))
(match_operator:QI 6 "bit_operator"
[(lshiftrt:QI (match_operand:QI 2 "bit_operand" "Ur")
(match_operand:HI 3 "immediate_operand" "i"))
(lshiftrt:QI (match_operand:QI 4 "bit_operand" "Ur")
(match_operand:HI 5 "immediate_operand" "i"))]))]
""
"bld %Z3,%Y2\;%b6 %Z5,%Y4\;bst %Z1,%Y0; bl5")
;; This is how combine canonicalizes this pattern. This is perhaps a bug
;; in combine.c, but there is no problem with writing it this way so we do.
(define_insn "bitnot_1"
[(set (zero_extract:QI (match_operand:QI 0 "bit_operand" "=Ur")
(const_int 1)
(match_operand:HI 1 "immediate_operand" "i"))
(lshiftrt:QI (xor:QI (match_operand:QI 2 "bit_operand" "0")
(match_operand:HI 3 "immediate_operand" "i"))
(match_operand:HI 4 "immediate_operand" "1")))]
"GET_CODE (operands[3]) == CONST_INT && GET_CODE (operands[1]) == CONST_INT
&& exact_log2 (INTVAL (operands[3])) == INTVAL (operands[1])"
"bnot %Z1,%Y0")
;; ??? Implement BIAND, BIOR, BIXOR
;; ??? Implement BILD, BIST
;; ??? Apparently general_operand for the 1st and 2nd operands is useful,
;; but I don't know why. --Jim
(define_expand "insv"
[(set (zero_extract:HI (match_operand:QI 0 "bit_operand" "Ur")
(match_operand:HI 1 "general_operand" "g")
(match_operand:HI 2 "general_operand" "g"))
(zero_extract:HI (match_operand:QI 3 "bit_operand" "Ur")
(const_int 1)
(const_int 0)))]
;; ??? This should have word mode which is SImode for the h8/300h.
"TARGET_H8300"
"
{ {
if (REGNO (operands[1]) != REGNO (operands[0])) if (INTVAL (operands[1]) != 1)
return \"mov.b %X1,%s0\;bld #7,%s0\;subx %t0,%t0\"; FAIL;
else
return \"bld #7,%s0\;subx %t0,%t0\"; /* ??? HACK ???
}" This INSV pattern is wrong. It should use HImode for operand 3.
[(set_attr "type" "multi") Also, the zero_extract around operand 3 is superfluous and should be
deleted. Fixing this is more work than we care to do for the moment,
because it means most of the above patterns would need to be rewritten,
and we also need more combine.c patches to make this work.
So, for now, we work around this bug by simply not accepting any bitfield
inserts that have a position greater than fits in QImode. */
if (GET_CODE (operands[2]) != CONST_INT || INTVAL (operands[2]) >= 8)
FAIL;
/* The bit_operand predicate accepts any memory durint RTL generation, but
only 'U' memory afterwards, so if this is a MEM operand, we must force
it to be valid for 'U' by reloading the address. */
if (GET_CODE (operands[0]) == MEM && ! EXTRA_CONSTRAINT (operands[0], 'U'))
{
rtx mem;
mem = gen_rtx (MEM, GET_MODE (operands[0]),
copy_to_mode_reg (Pmode, XEXP (operands[0], 0)));
RTX_UNCHANGING_P (mem) = RTX_UNCHANGING_P (operands[0]);
MEM_IN_STRUCT_P (mem) = MEM_IN_STRUCT_P (operands[0]);
MEM_VOLATILE_P (mem) = MEM_VOLATILE_P (operands[0]);
operands[0] = mem;
}
/* Likewise for operands[3]. */
if (GET_CODE (operands[3]) == MEM && ! EXTRA_CONSTRAINT (operands[3], 'U'))
{
rtx mem;
mem = gen_rtx (MEM, GET_MODE (operands[3]),
copy_to_mode_reg (Pmode, XEXP (operands[3], 0)));
RTX_UNCHANGING_P (mem) = RTX_UNCHANGING_P (operands[3]);
MEM_IN_STRUCT_P (mem) = MEM_IN_STRUCT_P (operands[3]);
MEM_VOLATILE_P (mem) = MEM_VOLATILE_P (operands[3]);
operands[3] = mem;
}
}")
;; ??? Apparently general_operand for the 2nd and 3rd operands is useful,
;; but I don't know why. --Jim
(define_expand "extzv"
[(set (match_operand:HI 0 "register_operand" "")
(zero_extract:HI (match_operand:QI 1 "bit_operand" "")
(match_operand:HI 2 "general_operand" "g")
(match_operand:HI 3 "general_operand" "g")))]
;; ??? This should have word mode which is SImode for the h8/300h.
"TARGET_H8300"
"
{
if (INTVAL (operands[2]) != 1)
FAIL;
/* The bit_operand predicate accepts any memory durint RTL generation, but
only 'U' memory afterwards, so if this is a MEM operand, we must force
it to be valid for 'U' by reloading the address. */
if (GET_CODE (operands[1]) == MEM && ! EXTRA_CONSTRAINT (operands[1], 'U'))
{
rtx mem;
mem = gen_rtx (MEM, GET_MODE (operands[1]),
copy_to_mode_reg (Pmode, XEXP (operands[1], 0)));
RTX_UNCHANGING_P (mem) = RTX_UNCHANGING_P (operands[1]);
MEM_IN_STRUCT_P (mem) = MEM_IN_STRUCT_P (operands[1]);
MEM_VOLATILE_P (mem) = MEM_VOLATILE_P (operands[1]);
operands[1] = mem;
}
}")
;; -----------------------------------------------------------------
;; STACK POINTER MANIPULATIONS
;; -----------------------------------------------------------------
;; This pattern is needed because there is no way on the H8/300
;; to add a 16 bit immediate value to the stack pointer in one
;; instruction, which could leave an invalid instruction if interrupted
;; half way through. Here we add to the stack pointer from a
;; register.
(define_insn "stack_pointer_manip"
[(set (match_operand:HI 0 "register_operand" "=&ra")
(plus:HI (match_operand:HI 1 "general_operand_src" "g")
(match_operand:HI 2 "register_operand" "ra")))]
"TARGET_H8300"
"mov.w %T1,%T0\;add.w %T2,%T0"
[(set_attr "type" "arith")
(set_attr "length" "6") (set_attr "length" "6")
(set_attr "cc" "clobber")]) (set_attr "cc" "set")])
(define_insn "extendhisi2_one"
[(set (match_operand:SI 0 "register_operand" "=l")
(sign_extend:SI (match_operand:HI 1 "register_operand" "0")))]
""
"mov.w %T1,%f0\;bld #7,%x0\;subx %y0,%y0\;subx %z0,%z0"
[(set_attr "length" "10")
(set_attr "cc" "clobber")])
(define_expand "extendhisi2" ;; -------------------------------------------
[(set (reg:HI 1) (match_operand:HI 1 "general_operand" "")) ;; BLK moves
(set (reg:SI 0) (sign_extend:SI (reg:HI 1))) ;; -------------------------------------------
(set (match_operand:SI 0 "general_operand" "" ) (reg:SI 0))]
(define_expand "movstrhi"
[(parallel [(set (mem:BLK (match_operand:BLK 0 "general_operand" ""))
(mem:BLK (match_operand:BLK 1 "general_operand" "")))
(use (match_operand:HI 2 "general_operand" ""))
(use (match_operand:HI 3 "immediate_operand" ""))
(clobber (match_dup 3))
])]
"" ""
"") "
{
;; ---------------------------------------------------------------------- rtx src_ptr = copy_to_mode_reg (Pmode, XEXP(operands[1], 0));
;; peepholes rtx dst_ptr = copy_to_mode_reg (Pmode, XEXP(operands[0], 0));
;; ----------------------------------------------------------------------
int max = GET_CODE (operands[2]) == CONST_INT
? MIN (INTVAL (operands[2]), INTVAL (operands[3])) : 1;
enum machine_mode mode = max >= 2 ? HImode : QImode;
rtx tmpreg = gen_reg_rtx (mode);
rtx increment = mode == QImode ? const1_rtx : const2_rtx;
rtx length = operands[2];
rtx label = gen_label_rtx ();
rtx end_src_ptr = gen_reg_rtx (Pmode);
/* emit_move_insn (length, gen_rtx(MINUS, HImode, length, increment));*/
FAIL;
if (Pmode == HImode)
emit_insn (gen_addhi3 (end_src_ptr, src_ptr, length));
else
emit_insn (gen_addsi3 (end_src_ptr, src_ptr, length));
emit_label (label);
emit_move_insn (tmpreg, gen_rtx (MEM, mode, src_ptr));
emit_move_insn (gen_rtx (MEM, mode, dst_ptr), tmpreg);
emit_insn (gen_rtx (SET, VOIDmode, src_ptr,
gen_rtx (PLUS, Pmode, src_ptr, increment)));
emit_insn (gen_rtx (SET, VOIDmode, dst_ptr,
gen_rtx (PLUS, Pmode, dst_ptr, increment)));
emit_insn (gen_rtx (SET, VOIDmode, cc0_rtx,
gen_rtx (COMPARE, Pmode, src_ptr, end_src_ptr)));
emit_jump_insn (gen_bne (label));
DONE;
}")
;; notice a move which could be predecremented ;; ----------------------------------------------
;; Peepholes go at the end.
;; ----------------------------------------------
(define_peephole ;; Notice when two byte moves in a row could be a word move.
[(set (match_operand:HI 1 "register_operand" "")
(plus:HI (match_dup 1) (const_int -1))) (define_peephole
(set (mem:HI (match_dup 1)) [(set (match_operand:QI 0 "register_operand" "=r")
(match_operand:HI 0 "register_operand" ""))] (mem:QI (plus:HI (match_operand:HI 1 "register_operand" "ra")
"REGNO (operands[1]) != REGNO (operands[0])" (match_operand:HI 2 "immediate_operand" "n"))))
"mov.w %T0,@-%T1" (set (match_operand:QI 3 "register_operand" "=r")
[(set_attr "length" "2") (mem:QI (plus:HI (match_dup 1)
(match_operand:HI 4 "immediate_operand" "n"))))]
"(INTVAL(operands[2]) == INTVAL(operands[4])+1) && REGNO(operands[0]) +1 == REGNO(operands[3])"
"mov.w @(%u4,%T1),%T0"
[(set_attr "length" "6")
(set_attr "cc" "set")]) (set_attr "cc" "set")])
(define_peephole
[(set (mem:QI (plus:HI (match_operand:HI 1 "register_operand" "ra")
(match_operand:HI 2 "immediate_operand" "n")))
(match_operand:QI 0 "register_operand" "r"))
(set (mem:QI (plus:HI (match_dup 1)
(match_operand:HI 4 "immediate_operand" "n")))
(match_operand:QI 3 "register_operand" "r"))]
"(INTVAL(operands[2]) == INTVAL(operands[4])+1) && REGNO(operands[0]) +1 == REGNO(operands[3])"
"mov.w %T0,@(%u4,%T1)"
[(set_attr "length" "6")
(set_attr "cc" "set")])
;; Notice a move which could be post incremented.
(define_peephole (define_peephole
[(set (match_operand:HI 1 "register_operand" "") [(set (match_operand:QI 0 "register_operand" "")
(plus:HI (match_dup 1) (const_int -1))) (mem:QI (match_operand:HI 1 "register_operand" "")))
(set (mem:QI (match_dup 1)) (set (match_dup 1) (plus:HI (match_dup 1) (const_int 1)))]
(match_operand:QI 0 "register_operand" ""))] "REGNO(operands[1]) != REGNO(operands[0])"
"REGNO (operands[1]) != REGNO (operands[0])" "mov.b @%T1+,%X0"
"mov.b %X0,@-%T1"
[(set_attr "length" "2") [(set_attr "length" "2")
(set_attr "cc" "set")]) (set_attr "cc" "set")])
;; notice a move which could be post incremented
(define_peephole (define_peephole
[(set (match_operand:HI 0 "register_operand" "") [(set (match_operand:HI 0 "register_operand" "")
(mem:HI (match_operand:HI 1 "register_operand" ""))) (mem:HI (match_operand:HI 1 "register_operand" "")))
(set (match_dup 1) (plus:HI (match_dup 1) (const_int 2)))] (set (match_dup 1) (plus:HI (match_dup 1) (const_int 2)))]
"REGNO (operands[1]) != REGNO (operands[0])" "REGNO(operands[1]) != REGNO(operands[0])"
"mov.w @%T1+,%T0" "mov.w @%T1+,%T0"
[(set_attr "length" "2") [(set_attr "length" "2")
(set_attr "cc" "set")]) (set_attr "cc" "set")])
;; Notice a move which could be predecremented.
(define_peephole (define_peephole
[(set (match_operand:QI 0 "register_operand" "") [(set (match_operand:HI 1 "register_operand" "")
(mem:QI (match_operand:HI 1 "register_operand" ""))) (plus:HI (match_dup 1) (const_int -1)))
(set (match_dup 1) (plus:HI (match_dup 1) (const_int 1)))] (set (mem:QI (match_dup 1))
"REGNO (operands[1]) != REGNO (operands[0])" (match_operand:QI 0 "register_operand" ""))]
"mov.b @%T1+,%X0" "REGNO(operands[1]) != REGNO(operands[0])"
"mov.b %X0,@-%T1"
[(set_attr "length" "2") [(set_attr "length" "2")
(set_attr "cc" "set")]) (set_attr "cc" "set")])
;; notice when two byte moves in a row could be a word move (define_peephole
[(set (match_operand:HI 1 "register_operand" "")
(define_peephole (plus:HI (match_dup 1) (const_int -1)))
[(set (mem:QI (plus:HI (match_operand:HI 1 "register_operand" "ra") (set (mem:HI (match_dup 1))
(match_operand:HI 2 "immediate_operand" "n"))) (match_operand:HI 0 "register_operand" ""))]
(match_operand:QI 0 "register_operand" "r")) "REGNO(operands[1]) != REGNO(operands[0])"
(set (mem:QI (plus:HI (match_dup 1) "mov.w %T0,@-%T1"
(match_operand:HI 4 "immediate_operand" "n"))) [(set_attr "length" "2")
(match_operand:QI 3 "register_operand" "r"))]
"(INTVAL (operands[2]) == INTVAL (operands[4]) + 1)
&& (REGNO (operands[0]) + 1 == REGNO (operands[3]))"
"mov.w %T0,@(%u4,%T1)"
[(set_attr "length" "6")
(set_attr "cc" "set")]) (set_attr "cc" "set")])
(define_peephole ;(define_insn ""
[(set (match_operand:QI 0 "register_operand" "=r") ; [(set (match_operand:HI 0 "register_operand" "=r")
(mem:QI (plus:HI (match_operand:HI 1 "register_operand" "ra") ; (MEM:HI (match_operand:HI 1 "register_operand" "r")))
(match_operand:HI 2 "immediate_operand" "n")))) ; (set (match_operand:HI 3 "register_operand" "=r")
(set (match_operand:QI 3 "register_operand" "=r") ; (zero_extract:HI (match_dup 0)
(mem:QI (plus:HI (match_dup 1) ; (const_int 1)
(match_operand:HI 4 "immediate_operand" "n"))))] ; (match_operand:HI 2 "general_operand" "g")))
"(INTVAL (operands[2]) == INTVAL (operands[4]) + 1) ; (set (MEM:HI (match_dup 1) (match_dup 3)))]
&& (REGNO (operands[0]) + 1 == REGNO (operands[3]))" ; ""
"mov.w @(%u4,%T1),%T0" ; "bld #0,%3l\;bst %Z2,%0%Y1"
[(set_attr "length" "6") ; [(set_attr "type" "multi")
(set_attr "cc" "set")]) ; (set_attr "length" "4")
; (set_attr "cc" "clobber")])
(define_insn "fancybset1"
[(set (match_operand:QI 0 "bit_operand" "=Ur")
(ior:QI (subreg:QI
(ashift:HI (const_int 1)
(subreg:QI (match_operand:HI 1 "register_operand" "ri") 0)) 0)
(match_dup 0)))]
""
"bset %X1,%X0")
(define_insn "fancybset"
[(set (match_operand:QI 0 "bit_operand" "=Ur")
(ior:QI (subreg:QI
(ashift:HI (const_int 1)
(match_operand:HI 1 "nonmemory_operand" "ri") ) 0)
(match_operand:QI 2 "general_operand" "Ur")))]
""
"mov.b %X2,%X0\;bset %X1,%X0")
(define_insn "fancybclr4"
[(set (match_operand:QI 0 "general_operand" "=Ur,Ur")
(and:QI
(subreg:QI
(rotate:HI (const_int -2)
(match_operand:HI 2 "nonmemory_operand" "ri,ri") ) 0)
(match_operand:QI 1 "general_operand" "0,Ur")))
(clobber (match_scratch:HI 3 "=X,&r"))]
""
"@
bclr %X2,%X0; l1
mov.b %X1,%X3\;mov.b %3,%0\;bclr %X2,%X0; l3")
(define_insn "fancybclr5"
[(set (match_operand:QI 0 "general_operand" "=Ur,Ur")
(and:QI
(subreg:QI
(rotate:HI (const_int -2)
(match_operand:QI 2 "nonmemory_operand" "ri,ri")) 0)
(match_operand:QI 1 "general_operand" "0,Ur")))
(clobber (match_scratch:HI 3 "=X,&r"))]
""
"@
bclr %X2,%X0; l1
mov.b %X1,%X3\;mov.b %3,%0\;bclr %X2,%X0;l2")
(define_insn "fancybclr2"
[(set (match_operand:QI 0 "general_operand" "=U,r")
(and:QI
(subreg:QI
(rotate:HI (const_int -2)
(match_operand:HI 2 "nonmemory_operand" "ri,ri") ) 0)
(match_operand:QI 1 "general_operand" "0,0")))]
""
"bclr %X2,%X0")
(define_insn "fancybclr3"
[(set (match_operand:QI 0 "general_operand" "=U,r")
(and:QI
(subreg:QI
(rotate:HI (const_int -2)
(match_operand:QI 2 "nonmemory_operand" "ri,ri")) 0)
(match_operand:QI 1 "general_operand" "0,0")))]
""
"bclr %X2,%X0")
(define_insn "fancybclr"
[(set (match_operand:QI 0 "general_operand" "=r")
(and:QI (not:QI (match_operand:QI 1 "general_operand" "0"))
(match_operand:QI 2 "general_operand" "r")))]
""
"not %X0\;and %X2,%X0")
(define_insn "fancybsetp3"
[(set (match_operand:QI 0 "bit_operand" "=Ur")
(ior:QI (subreg:QI (ashift:HI (const_int 1)
(match_operand:QI 1 "register_operand" "r")) 0)
(match_operand:QI 2 "bit_operand" "0")))]
""
"bset %X1,%X0")
(define_insn "fancybsetp2"
[(set (match_operand:QI 0 "general_operand" "=r,U")
(ior:QI (subreg:QI (ashift:HI (const_int 1)
(match_operand:QI 1 "register_operand" "r,r")) 0)
(match_operand:QI 2 "general_operand" "U,r")))]
""
"mov.b %X2,%X0\;bset %X1,%X0")
(define_insn "fancybnot"
[(set (match_operand:QI 0 "bit_operand" "=Ur")
(xor:QI (subreg:QI (ashift:HI (const_int 1)
(match_operand:QI 1 "register_operand" "r")) 0)
(match_operand:QI 2 "bit_operand" "0")))]
""
"bnot %X1,%X0")
(define_insn "fancy_btst"
[(set (pc)
(if_then_else (eq (zero_extract:HI (zero_extend:HI (match_operand:QI 0 "general_operand" "Ur"))
(const_int 1)
(match_operand:HI 1 "nonmemory_operand" "rn"))
(const_int 0))
(label_ref (match_operand 2 "" ""))
(pc)))]
""
"*
{
if (get_attr_length (insn) == 2)
return \"btst %X1,%X0\;beq %l2\";
else if (get_attr_length (insn) == 4)
return \"btst %X1,%X0\;beq %l2:16\";
else
return \"btst %X1,%X0\;bne %L0\;jmp @%l2\;%L0:\";
}"
[(set_attr "type" "branch")
(set_attr "cc" "clobber")])
(define_insn "fancy_btst1"
[(set (pc)
(if_then_else (ne (zero_extract:HI (zero_extend:HI (match_operand:QI 0 "general_operand" "Ur"))
(const_int 1)
(match_operand:HI 1 "nonmemory_operand" "rn"))
(const_int 0))
(label_ref (match_operand 2 "" ""))
(pc)))]
""
"*
{
if (get_attr_length (insn) == 2)
return \"btst %X1,%X0\;bne %l2\";
else if (get_attr_length (insn) == 4)
return \"btst %X1,%X0\;bne %l2:16\";
else
return \"btst %X1,%X0\;beq %L0\;jmp @%l2\;%L0:\";
}"
[(set_attr "type" "branch")
(set_attr "cc" "clobber")])
(define_insn "pxor"
[(set (zero_extract:QI (match_operand:QI 0 "bit_operand" "=r,U")
(const_int 1)
(match_operand 1 "immediate_operand" "n,n"))
(and:QI (not:QI (match_operand:QI 2 "bit_operand" "r,U"))
(const_int 1)))]
""
"bld #0,%X2\;bist %1,%0"
[(set_attr "type" "arith")
(set_attr "length" "4")
(set_attr "cc" "clobber")])
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment