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_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 "type" "move")
(set_attr "length" "2,2,4,4,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 "" (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" ""))]
"" ""
" "
{ {
if (TARGET_H8300)
{
if (do_movsi (operands))
DONE;
}
else /* TARGET_H8300H */
{
/* One of the ops has to be in a register. */ /* One of the ops has to be in a register. */
if (! register_operand (operand0, QImode) if (!register_operand (operand1, SImode)
&& ! register_operand (operand1, QImode)) && !register_operand (operand0, SImode))
operands[1] = copy_to_mode_reg (QImode, operand1); {
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:
if (REGNO(operands[0]) < REGNO(operands[1]))
return \"mov.w %e1,%e0\;mov.w %f1,%f0\"; 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. */ /* Move the second word first. */
return \"mov.w %f1,%f0\;mov.w %e1,%e0\"; 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:
if (REGNO(operands[0]) < REGNO(operands[1]))
return \"mov.w %e1,%e0\;mov.w %f1,%f0\"; 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. */ {
/* move the second word first */
return \"mov.w %f1,%f0\;mov.w %e1,%e0\"; 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_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; (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")])
;; ---------------------------------------------------------------------- ;; ----------------------------------------------------------------------
;; 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,170 +468,225 @@ ...@@ -362,170 +468,225 @@
(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:HI 0 "register_operand" "=ra,ra,ra,ra,r,ra") [(set (match_operand:QI 0 "register_operand" "=r")
(plus:HI (match_operand:HI 1 "register_operand" "%0,0,0,0,0,0") (plus:QI (match_operand:QI 1 "register_operand" "%0")
(match_operand:HI 2 "nonmemory_operand" "K,M,L,N,n,ra")))] (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")
(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")))]
""
"@ "@
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" "")) ;; SUBTRACT INSTRUCTIONS
(set (match_dup 3) ;; ----------------------------------------------------------------------
(plus:SI (match_dup 3)
(match_operand:SI 2 "nonmemory_operand" ""))) (define_insn "subqi3"
(set (match_operand:SI 0 "register_operand" "") (match_dup 3))] [(set (match_operand:QI 0 "register_operand" "=r,r")
(minus:QI (match_operand:QI 1 "register_operand" "0,0")
(match_operand:QI 2 "nonmemory_operand" "r,i")))]
"" ""
" "@
{ sub.b %X2,%X0
operands[3] = gen_rtx (REG, SImode, 0); add.b %G2,%X0"
}") [(set_attr "type" "arith")
(set_attr "length" "2")
(set_attr "cc" "set")])
;; ----------------------------------------------------------------------; ;; ??? subs operates on the 32bit register. We can use it because we don't
;; Subtract instructions ;; 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 "" (define_insn "subhi3_internal"
[(set (match_operand:HI 0 "register_operand" "=ra,ra,ra,r") [(set (match_operand:HI 0 "register_operand" "=ra,ra,ra,r")
(minus:HI (match_operand:HI 1 "general_operand" "0,0,0,0") (minus:HI (match_operand:HI 1 "general_operand" "0,0,0,0")
(match_operand:HI 2 "nonmemory_operand" "K,M,ra,n")))] (match_operand:HI 2 "nonmemory_operand" "K,M,ra,n")))]
"" ""
"@ "@
subs %T2,%T0 subs %T2,%T0
subs #2,%T0\;subs %E2,%T0 subs #2,%T0\;subs %M2,%T0
sub.w %T2,%T0 sub.w %T2,%T0
add.b %E2,%s0\;addx %F2,%t0 ; -%0" add.b %E2,%s0\;addx %F2,%t0 ; -%0"
[(set_attr "type" "multi") [(set_attr "type" "multi")
(set_attr "length" "2,4,2,4") (set_attr "length" "2,4,2,4")
(set_attr "cc" "none_0hit,none_0hit,set,clobber")]) (set_attr "cc" "none_0hit,none_0hit,set,clobber")])
(define_insn "subqi3" ;; ??? Why is this here?
[(set (match_operand:QI 0 "register_operand" "=r,r")
(minus:QI (match_operand:QI 1 "register_operand" "0,0")
(match_operand:QI 2 "nonmemory_operand" "r,i")))]
""
"@
sub.b %X2,%X0
add.b %G2,%X0"
[(set_attr "type" "arith")
(set_attr "length" "2")
(set_attr "cc" "set")])
(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")
...@@ -548,84 +711,285 @@ ...@@ -548,84 +711,285 @@
(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,29 +999,73 @@ ...@@ -635,29 +999,73 @@
"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"
;; Not instructions [(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
;; ----------------------------------------------------------------------
(define_insn "one_cmplqi2" (define_insn "one_cmplqi2"
[(set (match_operand:QI 0 "register_operand" "=r") [(set (match_operand:QI 0 "register_operand" "=r")
...@@ -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,10 +1203,10 @@ ...@@ -780,10 +1203,10 @@
"" ""
"") "")
(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)))]
"" ""
...@@ -791,32 +1214,35 @@ ...@@ -791,32 +1214,35 @@
{ {
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)
...@@ -826,25 +1252,81 @@ ...@@ -826,25 +1252,81 @@
{ {
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"
[(set_attr "type" "branch")
(set_attr "cc" "none")
(set_attr "length" "2")])
(define_insn "tablejump_h8300h"
[(set (pc) (match_operand:SI 0 "register_operand" ""))
(use (label_ref (match_operand 1 "" "")))]
"TARGET_H8300H"
"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")])
;; This is a define expand, because pointers may be either 16 or 32 bits.
;(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. ;; Call subroutine with no return value.
;; ??? Even though we use HImode here, this works for the 300h.
(define_insn "call" (define_insn "call"
[(call (match_operand:QI 0 "memory_operand" "o") [(call (match_operand:QI 0 "call_insn_operand" "or")
(match_operand:HI 1 "general_operand" "g"))] (match_operand:HI 1 "general_operand" "g"))]
"" ""
"jsr %0" "jsr %0"
...@@ -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 else
FAIL; return \"mov.b %X1,%s0\;bld #7,%s0\;subx %t0,%t0\";
}") }
else
{
/* ??? 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 (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" "if (expand_a_shift (SImode, ASHIFT, operands)) DONE;else FAIL;")
[(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;")
;; WARNING: The constraints on the scratch register say one is not needed
;; for constant shifts of 1,2. Emit_a_shift() must know this.
(define_insn "shiftbyn_SI"
[(set (match_operand:SI 0 "register_operand" "=r,r")
(match_operator:SI 3 "nshift_operator"
[ (match_operand:SI 1 "register_operand" "0,0")
(match_operand:QI 2 "nonmemory_operand" "IK,rn")]))
(clobber (match_scratch:QI 4 "=X,&r"))]
""
"* return emit_a_shift (insn, operands);"
[(set_attr "type" "arith")
(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")])
;; -----------------------------------------------------------------
;; BIT FIELDS
;; -----------------------------------------------------------------
;; The H8/300 has given 1/8th of its opcode space to bitfield
;; instuctions so let's use them as well as we can
;; BCC and BCS patterns.
(define_insn "bcs_qiqi"
[(set (pc)
(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)))]
""
"*
{ {
if (can_shift (ASHIFTRT, operands, gen_ashrsi3_one, 1, 0)) output_asm_insn(\"bld %Z3,%Y2\", operands);
DONE; if (get_attr_length (insn) == 2)
return \"b%d1 %l0\";
else if (get_attr_length (insn) == 4)
return \"b%d1 %l0:16\";
else else
FAIL; return \"b%g1 %L0\;jmp @%l0\;%L0:\";
}") }"
[(set_attr "type" "branch")
(set_attr "cc" "clobber")])
;; ---------------------------------------------------------------------- (define_insn "bcs_hihi"
;; BIT FIELDS [(set (pc)
;; ---------------------------------------------------------------------- (if_then_else
(match_operator 1 "eq_operator"
[(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)))]
""
"*
{
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_insn "" (define_insn "bcs_hiqi"
[(set (zero_extract:HI (match_operand:HI 0 "register_operand" "+r") [(set (pc)
(if_then_else
(match_operator 1 "eq_operator"
[(zero_extract:HI (match_operand:QI 2 "bit_operand" "Ur")
(const_int 1) (const_int 1)
(match_operand:HI 2 "general_operand" "g")) (match_operand:HI 3 "immediate_operand" "i"))
(match_operand:HI 3 "general_operand" "r"))] (const_int 0)])
(label_ref (match_operand 0 "" ""))
(pc)))]
"" ""
"bld #0,%3l\;bst %Z2,%0%Y1" "*
[(set_attr "type" "multi") {
(set_attr "length" "4") 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 "insv" ;; BLD and BST patterns
[(set (zero_extract:HI (match_operand:HI 0 "register_operand" "+r")
(match_operand:HI 1 "general_operand" "g") (define_insn "extract_1"
(match_operand:HI 2 "general_operand" "g")) [(set (match_operand:HI 0 "register_operand" "=&r")
(match_operand:HI 3 "general_operand" "r"))] (zero_extract:HI (match_operand:QI 1 "bit_operand" "Ur")
(const_int 1)
(match_operand:HI 2 "immediate_operand" "i")))]
"" ""
"if (INTVAL (operands[1]) != 1) FAIL;") "sub.w %0,%0\;bld %Z2,%Y1\;bst #0,%X0")
(define_insn "" (define_insn "extract_1_hi"
[(set (match_operand:HI 0 "register_operand" "=&r") [(set (match_operand:HI 0 "register_operand" "=&r")
(zero_extract:HI (match_operand:HI 1 "register_operand" "r") (zero_extract:HI (match_operand:HI 1 "bit_operand" "Ur")
(const_int 1) (const_int 1)
(match_operand:HI 3 "general_operand" "g")))] (match_operand:HI 2 "immediate_operand" "i")))]
"" ""
"sub.w %T0,%T0\;bld %Z3,%T1%Y1\;rotxl %T0l" "sub.w %0,%0\;bld %Z2,%Y1\;bst #0,%X0")
[(set_attr "type" "multi")
(set_attr "length" "6")
(set_attr "cc" "clobber")])
(define_insn "" (define_insn "insert_1"
[(set (match_operand:HI 0 "register_operand" "=r") [(set (zero_extract:HI (match_operand:QI 0 "bit_operand" "+Ur")
(sign_extract:HI (match_operand:HI 1 "register_operand" "r")
(const_int 1) (const_int 1)
(match_operand:HI 3 "general_operand" "g")))] (match_operand:HI 1 "immediate_operand" "i"))
(zero_extract:HI (match_operand:QI 2 "bit_operand" "Ur")
(const_int 1)
(const_int 0)))]
"" ""
"bld %Z3,%1%Y1\;sub.x %0l,%0l\;mov.b %0l,%0h" "bld #0,%X2\;bst %Z1,%Y0 ; i1")
[(set_attr "type" "multi")
(set_attr "length" "6")
(set_attr "cc" "clobber")])
(define_expand "extzv" ;; This is how combine canonicalizes this pattern. This is perhaps a bug
[(set (match_operand:HI 0 "register_operand" "") ;; in combine.c, but there is no problem with writing it this way so we do.
(zero_extract:HI (match_operand:HI 1 "register_operand" "") (define_insn "extract_insert_1"
(match_operand:HI 2 "general_operand" "") [(set (zero_extract:QI (match_operand:QI 0 "bit_operand" "+Ur")
(match_operand:HI 3 "general_operand" "")))] (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")))]
"" ""
"if (INTVAL (operands[2]) != 1) FAIL;") "bld %Z3,%Y2\;bst %Z1,%Y0; ei1")
(define_expand "extv" ;; BAND, BOR, and BXOR patterns
[(set (match_operand:HI 0 "register_operand" "")
(sign_extract:HI (match_operand:HI 1 "register_operand" "") (define_insn "bitlogical_1"
(match_operand:HI 2 "general_operand" "") [(set (match_operand:HI 0 "bit_operand" "=Ur")
(match_operand:HI 3 "immediate_operand" "")))] (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")]))]
"" ""
"if (INTVAL (operands[2]) != 1) FAIL;") "bld %Z2,%Y1\;%b4 #0,%X0\;bst #0,%X0; bl1")
;; ---------------------------------------------------------------------- (define_insn "bitlogical_1_hi"
;; Conversions [(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 "zero_extendqihi2" (define_insn "bitlogical_2"
[(set (match_operand:HI 0 "register_operand" "=r") [(set (match_operand:HI 0 "bit_operand" "=Ur")
(zero_extend:HI (match_operator:HI 5 "bit_operator"
(match_operand:QI 1 "general_operand" "g")))] [(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"))]))]
"" ""
"mov.b %X1,%s0\;mov.b #0,%t0" "bld %Z2,%Y1\;%b5 %Z4,%Y3\;bst #0,%X0; bl3")
[(set_attr "type" "multi")
(set_attr "length" "4")
(set_attr "cc" "clobber")])
(define_insn "extendqihi2" (define_insn "bitlogical_2_hi"
[(set (match_operand:HI 0 "register_operand" "=r") [(set (match_operand:HI 0 "bit_operand" "=Ur")
(sign_extend:HI (match_operator:HI 5 "bit_operator"
(match_operand:QI 1 "register_operand" "r")))] [(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));
rtx dst_ptr = copy_to_mode_reg (Pmode, XEXP(operands[0], 0));
;; ---------------------------------------------------------------------- int max = GET_CODE (operands[2]) == CONST_INT
;; peepholes ? 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);
;; notice a move which could be predecremented /* 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;
}")
;; ----------------------------------------------
;; Peepholes go at the end.
;; ----------------------------------------------
;; Notice when two byte moves in a row could be a word move.
(define_peephole (define_peephole
[(set (match_operand:HI 1 "register_operand" "") [(set (match_operand:QI 0 "register_operand" "=r")
(plus:HI (match_dup 1) (const_int -1))) (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" ""))] (set (match_operand:QI 3 "register_operand" "=r")
"REGNO (operands[1]) != REGNO (operands[0])" (mem:QI (plus:HI (match_dup 1)
"mov.w %T0,@-%T1" (match_operand:HI 4 "immediate_operand" "n"))))]
[(set_attr "length" "2") "(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 (define_peephole
[(set (match_operand:HI 1 "register_operand" "") [(set (mem:QI (plus:HI (match_operand:HI 1 "register_operand" "ra")
(plus:HI (match_dup 1) (const_int -1))) (match_operand:HI 2 "immediate_operand" "n")))
(set (mem:QI (match_dup 1)) (match_operand:QI 0 "register_operand" "r"))
(match_operand:QI 0 "register_operand" ""))] (set (mem:QI (plus:HI (match_dup 1)
"REGNO (operands[1]) != REGNO (operands[0])" (match_operand:HI 4 "immediate_operand" "n")))
"mov.b %X0,@-%T1" (match_operand:QI 3 "register_operand" "r"))]
[(set_attr "length" "2") "(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")])
;; notice a move which could be post incremented ;; Notice a move which could be post incremented.
(define_peephole
[(set (match_operand:QI 0 "register_operand" "")
(mem:QI (match_operand:HI 1 "register_operand" "")))
(set (match_dup 1) (plus:HI (match_dup 1) (const_int 1)))]
"REGNO(operands[1]) != REGNO(operands[0])"
"mov.b @%T1+,%X0"
[(set_attr "length" "2")
(set_attr "cc" "set")])
(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 (define_peephole
[(set (mem:QI (plus:HI (match_operand:HI 1 "register_operand" "ra") [(set (match_operand:HI 1 "register_operand" "")
(match_operand:HI 2 "immediate_operand" "n"))) (plus:HI (match_dup 1) (const_int -1)))
(match_operand:QI 0 "register_operand" "r")) (set (mem:HI (match_dup 1))
(set (mem:QI (plus:HI (match_dup 1) (match_operand:HI 0 "register_operand" ""))]
(match_operand:HI 4 "immediate_operand" "n"))) "REGNO(operands[1]) != REGNO(operands[0])"
(match_operand:QI 3 "register_operand" "r"))] "mov.w %T0,@-%T1"
"(INTVAL (operands[2]) == INTVAL (operands[4]) + 1) [(set_attr "length" "2")
&& (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