summaryrefslogtreecommitdiff
path: root/gcc/config/h8300/h8300.md
diff options
context:
space:
mode:
authordje <dje@138bc75d-0d04-0410-961f-82ee72b054a4>1994-07-11 22:53:08 +0000
committerdje <dje@138bc75d-0d04-0410-961f-82ee72b054a4>1994-07-11 22:53:08 +0000
commit4ec308e403f4445bee66886b5109796812b62fe9 (patch)
treeb22eff71ad1077e1e050934fd3c0a196d4b71c4a /gcc/config/h8300/h8300.md
parentb839e0b4e0cf8e87b0b1ee93fa0edea8d1352acb (diff)
downloadgcc-4ec308e403f4445bee66886b5109796812b62fe9.tar.gz
* 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. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@7730 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/config/h8300/h8300.md')
-rw-r--r--gcc/config/h8300/h8300.md2306
1 files changed, 1601 insertions, 705 deletions
diff --git a/gcc/config/h8300/h8300.md b/gcc/config/h8300/h8300.md
index 8355ac82f0a..5c5c3ae69d0 100644
--- a/gcc/config/h8300/h8300.md
+++ b/gcc/config/h8300/h8300.md
@@ -1,5 +1,8 @@
-;;- Machine description for the Hitachi H8/300 for the GNU C compiler
-;; Copyright (C) 1992, 1993 Free Software Foundation, Inc.
+;; GCC machine description for Hitachi H8/300
+;; 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.
@@ -23,6 +26,12 @@
;; 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"
(const_string "arith"))
@@ -31,53 +40,119 @@
(define_attr "length" ""
(cond [(eq_attr "type" "branch")
(if_then_else (and (ge (minus (pc) (match_dup 0))
- (const_int -128))
+ (const_int -120))
(le (minus (pc) (match_dup 0))
- (const_int 128)))
+ (const_int 120)))
(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" "return") (const_int 2)
(eq_attr "type" "float") (const_int 12)
(eq_attr "type" "call") (const_int 4)]
(const_int 200)))
-
-(define_attr "cc" "none,clobber,none_0hit,set,compare,whoops"
+(define_attr "cc" "none,clobber,none_0hit,set,compare,whoops,cbit"
(const_string "whoops"))
-
+
;; ----------------------------------------------------------------------
-;; move instructions
+;; MOVE INSTRUCTIONS
;; ----------------------------------------------------------------------
-;; movhi
+;; movqi
-(define_insn ""
- [(set (match_operand:HI 0 "push_operand" "=<")
- (match_operand:HI 1 "register_operand" "ra"))]
+(define_insn "movqi_push"
+ [(set (match_operand:QI 0 "push_operand" "=<")
+ (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 "length" "2")
+ (set (attr "length") (if_then_else (eq_attr "cpu" "h8300") (const_int 2) (const_int 4)))
(set_attr "cc" "set")])
-(define_insn "movstricthi"
- [(set (strict_low_part (match_operand:HI 0 "general_operand_dst" "=r,r,r,o,<"))
- (match_operand:HI 1 "general_operand_src" "I,r,io,r,r"))]
+(define_insn "movqi_internal"
+ [(set (match_operand:QI 0 "general_operand_dst" "=r,r,r,o,<,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
- mov.w %T1,%T0
- mov.w %T1,%T0
- mov.w %T1,%T0
- mov.w %T1,%T0"
+ 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_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 ""
+(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")])
+
+(define_insn "movhi_internal"
[(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
@@ -86,7 +161,11 @@
mov.w %T1,%T0
mov.w %T1,%T0"
[(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")])
(define_expand "movhi"
@@ -95,79 +174,84 @@
""
"
{
- /* One of the ops has to be in a register. */
- if (! register_operand (operand1, HImode)
- && ! register_operand (operand0, HImode))
- operands[1] = copy_to_mode_reg (HImode, operand1);
+ /* One of the ops has to be in a register */
+ if (!register_operand(operand1, HImode)
+ && !register_operand(operand0, HImode))
+ {
+ operands[1] = copy_to_mode_reg(HImode, operand1);
+ }
}")
-(define_insn ""
- [(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")))]
- ""
- "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"))]
+(define_insn "movstricthi"
+ [(set (strict_low_part (match_operand:HI 0 "general_operand_dst" "=r,r,r,o,<"))
+ (match_operand:HI 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"
+ sub.w %T0,%T0
+ mov.w %T1,%T0
+ mov.w %T1,%T0
+ mov.w %T1,%T0
+ mov.w %T1,%T0"
[(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")])
-(define_insn ""
- [(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")])
+;; movsi
-(define_expand "movqi"
- [(set (match_operand:QI 0 "general_operand_dst" "")
- (match_operand:QI 1 "general_operand_src" ""))]
+(define_expand "movsi"
+ [(set (match_operand:SI 0 "general_operand_dst" "")
+ (match_operand:SI 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);
+ 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, SImode)
+ && !register_operand (operand0, SImode))
+ {
+ operands[1] = copy_to_mode_reg (SImode, operand1);
+ }
+ }
}")
-;; movsi
-
-(define_insn ""
- [(set (match_operand:SI 0 "general_operand_dst" "=l,l,l,o,<")
- (match_operand:SI 1 "general_operand_src" "I,l,ion,l,l"))]
+(define_expand "movsf"
+ [(set (match_operand:SF 0 "general_operand_dst" "")
+ (match_operand:SF 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. */
+ 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;
@@ -176,181 +260,203 @@
case 0:
return \"sub.w %e0,%e0\;sub.w %f0,%f0\";
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:
/* 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);
- if (REG_P (inside))
- rn = REGNO (inside);
+ rtx inside = XEXP (operands[1],0);
+ if (REG_P (inside))
+ {
+ rn = REGNO(inside);
+ }
else if (GET_CODE (inside) == PLUS)
{
- rtx lhs = XEXP (inside, 0);
- rtx rhs = XEXP (inside, 1);
- if (REG_P (lhs))
- rn = REGNO (lhs);
- if (REG_P (rhs))
- rn = REGNO (rhs);
+ rtx lhs = XEXP (inside,0);
+ rtx rhs = XEXP (inside,1);
+ if (REG_P (lhs)) rn = REGNO (lhs);
+ if (REG_P (rhs)) rn = REGNO (rhs);
}
}
- if (rn == REGNO (operands[0]))
- /* Move the second word first. */
- return \"mov.w %f1,%f0\;mov.w %e1,%e0\";
+ if (rn == REGNO (operands[0]))
+ {
+ /* Move the second word first. */
+ return \"mov.w %f1,%f0\;mov.w %e1,%e0\";
+ }
else
- return \"mov.w %e1,%e0\;mov.w %f1,%f0\";
+ {
+ return \"mov.w %e1,%e0\;mov.w %f1,%f0\";
+ }
case 3:
return \"mov.w %e1,%e0\;mov.w %f1,%f0\";
case 4:
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 "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")])
-
-(define_expand "movsi"
- [(set (match_operand:SI 0 "general_operand_dst" "")
- (match_operand:SI 1 "general_operand_src" ""))]
- ""
- "if (domovsi (operands)) DONE;")
-
-(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"))]
- ""
+(define_insn "movsf_h8300"
+ [(set (match_operand:SF 0 "general_operand_dst" "=r,r,r,o,<,r")
+ (match_operand:SF 1 "general_operand_src" "I,r,ion,r,r,>"))]
+ "TARGET_H8300
+ && (register_operand (operands[0], SFmode)
+ || register_operand (operands[1], SFmode))"
"*
{
- /* This is a copy of the movsi stuff. */
+ /* Copy of the movsi stuff */
int rn = -1;
switch (which_alternative)
{
case 0:
return \"sub.w %e0,%e0\;sub.w %f0,%f0\";
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:
/* Make sure we don't trample the register we index with. */
if (GET_CODE (operands[1]) == MEM)
{
- rtx inside = XEXP (operands[1], 0);
+ rtx inside = XEXP (operands[1],0);
if (REG_P (inside))
- rn = REGNO (inside);
+ {
+ rn = REGNO (inside);
+ }
else if (GET_CODE (inside) == PLUS)
{
- rtx lhs = XEXP (inside, 0);
- rtx rhs = XEXP (inside, 1);
- if (REG_P (lhs))
- rn = REGNO (lhs);
- if (REG_P (rhs))
- rn = REGNO (rhs);
+ rtx lhs = XEXP (inside,0);
+ rtx rhs = XEXP (inside,1);
+ if (REG_P (lhs)) rn = REGNO (lhs);
+ if (REG_P (rhs)) rn = REGNO (rhs);
}
}
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
- return \"mov.w %e1,%e0\;mov.w %f1,%f0\";
+ {
+ return \"mov.w %e1,%e0\;mov.w %f1,%f0\";
+ }
case 3:
return \"mov.w %e1,%e0\;mov.w %f1,%f0\";
case 4:
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 "length" "4,4,8,8,4")
+ (set_attr "length" "4,4,8,8,4,4")
(set_attr "cc" "clobber")])
-(define_insn ""
- [(set (match_operand:SF 0 "push_operand" "=<")
- (match_operand:SF 1 "register_operand" "l"))]
- ""
- "mov.w %f1,%T0\;mov.w %e1,%T0"
+(define_insn "movsi_h8300h"
+ [(set (match_operand:SI 0 "general_operand_dst" "=ra,ra,ra,o,<,ra")
+ (match_operand:SI 1 "general_operand_src" "I,ra,ion,ra,ra,>"))]
+ "TARGET_H8300H
+ && (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 "length" "4")
- (set_attr "cc" "clobber")])
-
-(define_expand "movsf"
- [(set (match_operand:SF 0 "general_operand_dst" "")
- (match_operand:SF 1 "general_operand_src" ""))]
- ""
- "if (domovsi (operands)) DONE;")
+ (set_attr "length" "2,2,8,8,4,4")
+ (set_attr "cc" "set")])
-;; 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"
- [(set (cc0)
- (match_operand:QI 0 "register_operand" "ra"))]
+ [(set (cc0) (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 "length" "2")
+ (set_attr "length" "4")
(set_attr "cc" "set")])
(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)
- (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 "length" "2")
- (set_attr "cc" "set")])
+ (set_attr "cc" "compare")])
+
+;; ??? 300h can have an immediate operand here.
(define_insn "cmphi"
[(set (cc0)
@@ -362,170 +468,225 @@
(set_attr "length" "2")
(set_attr "cc" "compare")])
-(define_insn "cmpqi"
+;; ??? 300h can have an immediate operand here.
+
+(define_insn "cmpsi"
[(set (cc0)
- (compare:QI (match_operand:QI 0 "register_operand" "ra")
- (match_operand:QI 1 "nonmemory_operand" "rai")))]
- ""
- "cmp.b %X1,%X0"
+ (compare:SI (match_operand:SI 0 "register_operand" "ra")
+ (match_operand:SI 1 "register_operand" "ra")))]
+ "TARGET_H8300H"
+ "cmp.l %S1,%S0"
[(set_attr "type" "arith")
(set_attr "length" "2")
(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")
(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 #2,%T0\;adds %C2,%T0
- subs %M2,%T0
- subs #2,%T0\;subs %M2,%T0
+ adds %T2,%A0
+ adds #2,%A0\;adds %C2,%A0
+ subs %M2,%A0
+ subs #2,%A0\;subs %M2,%A0
add.b %s2,%s0\;addx %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 "cc" "none_0hit,none_0hit,none_0hit,none_0hit,clobber,set")])
+;; ??? Why is this here?
(define_expand "addhi3"
[(set (match_operand:HI 0 "register_operand" "")
(plus:HI (match_operand:HI 1 "register_operand" "")
(match_operand:HI 2 "nonmemory_operand" "")))]
""
- "
-{
- if (operands[0] != operands[1])
- emit_move_insn (operands[0], operands[1]);
-}")
+ "")
-(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")))]
+(define_expand "addsi3"
+ [(set (match_operand:SI 0 "register_operand" "")
+ (plus:SI (match_operand:SI 1 "register_operand" "")
+ (match_operand:SI 2 "nonmemory_operand" "")))]
""
- "add.b %X2,%X0"
- [(set_attr "type" "arith")
- (set_attr "length" "2")
- (set_attr "cc" "set")])
+ "")
-(define_insn ""
- [(set (match_operand:SI 0 "register_operand" "=l,l")
- (plus:SI (match_operand:SI 1 "register_operand" "%0,0")
- (match_operand:SI 2 "nonmemory_operand" "l,n")))
- (clobber (match_operand:HI 3 "register_operand" "=&l,l"))]
- ""
+(define_insn "addsi_h8300"
+ [(set (match_operand:SI 0 "register_operand" "=r,r,&r")
+ (plus:SI (match_operand:SI 1 "register_operand" "%0,0,r")
+ (match_operand:SI 2 "nonmemory_operand" "n,r,r")))]
+ "TARGET_H8300"
"@
- add %w2,%w0\;addx %x2,%x0\;addx %y2,%y0\;addx %z2,%z0
- add.w %f2,%f0\;addx %y2,%y0\;addx %z2,%z0"
- [(set_attr "type" "multi")
- (set_attr "length" "8,6")
+ add %w2,%w0\;addx %x2,%x0\;addx %y2,%y0\;addx %z2,%z0
+ add.w %f2,%f0\;addx %y2,%y0\;addx %z2,%z0
+ mov %f1,%f0\;mov %e1,%e0\;add.w %f2,%f0\;addx %y2,%y0\;addx %z2,%z0"
+ [(set_attr "type" "arith")
+ (set_attr "length" "8,6,20")
(set_attr "cc" "clobber")])
-(define_insn ""
- [(set (match_operand:SI 0 "register_operand" "=l,l")
- (plus:SI (match_operand:SI 1 "register_operand" "%0,0")
- (match_operand:SI 2 "nonmemory_operand" "n,r")))]
+;; ??? 4 can be handled in one insn on the 300h.
+;; ??? Should the 'n' constraint be 'i' here?
+;; ??? We don't handle (reg + symbol_ref) which the 300h can handle.
+
+(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"
+ "@
+ adds %S2,%S0
+ adds #2,%S0\;adds %C2,%S0
+ subs %M2,%S0
+ subs #2,%S0\;subs %M2,%S0
+ 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")])
+
+;; ----------------------------------------------------------------------
+;; SUBTRACT INSTRUCTIONS
+;; ----------------------------------------------------------------------
+
+(define_insn "subqi3"
+ [(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")))]
""
"@
- add %w2,%w0\;addx %x2,%x0\;addx %y2,%y0\;addx %z2,%z0
- add.w %f2,%f0\;addx %y2,%y0\;addx %z2,%z0"
+ sub.b %X2,%X0
+ add.b %G2,%X0"
[(set_attr "type" "arith")
- (set_attr "length" "8,6")
- (set_attr "cc" "clobber")])
+ (set_attr "length" "2")
+ (set_attr "cc" "set")])
-(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
-;; ----------------------------------------------------------------------
+;; ??? 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 ""
+(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 %E2,%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")])
-(define_insn "subqi3"
- [(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")])
-
+;; ??? Why is this here?
(define_expand "subhi3"
[(set (match_operand:HI 0 "register_operand" "")
(minus:HI (match_operand:HI 1 "register_operand" "")
(match_operand:HI 2 "nonmemory_operand" "")))]
""
- "
-{
- if (operands[0] != operands[1])
- emit_move_insn (operands[0], operands[1]);
-}")
+ "")
-(define_insn ""
- [(set (match_operand:SI 0 "register_operand" "=l")
- (minus:SI (match_operand:SI 1 "register_operand" "%0")
- (match_operand:SI 2 "register_operand" "l")))]
+(define_expand "subsi3"
+ [(set (match_operand:SI 0 "register_operand" "")
+ (minus:SI (match_operand:SI 1 "register_operand" "")
+ (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"
[(set_attr "type" "arith")
(set_attr "length" "6")
(set_attr "cc" "clobber")])
-(define_expand "subsi3"
- [(set (match_dup 3) (match_operand:SI 1 "register_operand" ""))
- (set (match_dup 3)
- (minus: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);")
+;; ??? 4 can be handled in one insn on the 300h.
+
+(define_insn "subsi3_h8300h"
+ [(set (match_operand:SI 0 "register_operand" "=ra,ra,ra,r")
+ (minus:SI (match_operand:SI 1 "general_operand" "0,0,0,0")
+ (match_operand:SI 2 "nonmemory_operand" "K,M,ra,n")))]
+ "TARGET_H8300H"
+ "@
+ 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"
[(set (match_operand:HI 0 "register_operand" "=r")
- (mult:HI (match_operand:QI 1 "general_operand" "%0")
- (match_operand:QI 2 "register_operand" "r")))]
+ (mult:HI (zero_extend:HI (match_operand:QI 1 "general_operand" "%0"))
+ (zero_extend:HI (match_operand:QI 2 "register_operand" "r"))))]
""
"mulxu %X2,%T0"
[(set_attr "type" "multi")
(set_attr "length" "2")
(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"
@@ -538,6 +699,8 @@
(set_attr "length" "2")
(set_attr "cc" "clobber")])
+;; ??? Will divxu always work here?
+
(define_insn "divqi3"
[(set (match_operand:QI 0 "register_operand" "=r")
(div:QI (match_operand:HI 1 "general_operand" "0")
@@ -547,85 +710,286 @@
[(set_attr "type" "multi")
(set_attr "length" "2")
(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"
- [(set (match_operand:QI 0 "general_operand" "=r")
- (and:QI (match_operand:QI 1 "general_operand" "%0")
- (match_operand:QI 2 "general_operand" "rn")))]
+(define_insn "umodqi3"
+ [(set (match_operand:QI 0 "register_operand" "=r")
+ (umod:QI (match_operand:HI 1 "general_operand" "0")
+ (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 "length" "2")
- (set_attr "cc" "set")])
+ (set_attr "length" "2,4")
+ (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"
[(set (match_operand:HI 0 "register_operand" "=r")
(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 "length" "4")
(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"
- [(set (match_operand:QI 0 "general_operand" "=r,U")
- (ior:QI (match_operand:QI 1 "general_operand" "%0,0")
- (match_operand:QI 2 "general_operand" "rn,P")))]
- ""
+(define_insn "iorqi3_internal"
+ [(set (match_operand:QI 0 "bit_operand" "=U,r")
+ (ior:QI (match_operand:QI 1 "bit_operand" "%0,0")
+ (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 "length" "2,4")
- (set_attr "cc" "set,none_0hit")])
+ (set_attr "length" "4,2")
+ (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"
[(set (match_operand:HI 0 "general_operand" "=r,r")
(ior:HI (match_operand:HI 1 "general_operand" "%0,0")
(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 "length" "2,4")
(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"
- [(set (match_operand:QI 0 "general_operand" "=r")
- (xor:QI (match_operand:QI 1 "general_operand" "%0")
- (match_operand:QI 2 "nonmemory_operand" "ri")))]
- ""
- "xor %X2,%X0"
+(define_insn "xorqi3_internal"
+ [(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,P")))]
+ "register_operand (operands[0], QImode) || p_operand (operands[2], QImode)"
+ "@
+ xor %X2,%X0
+ bnot %V2,%X0"
[(set_attr "type" "arith")
- (set_attr "length" "2")
- (set_attr "cc" "set")])
+ (set_attr "length" "2,4")
+ (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"
- [(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")
(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 "length" "4")
(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"
@@ -635,28 +999,72 @@
"neg %X0"
[(set_attr "type" "arith")
(set_attr "length" "2")
- (set_attr "cc" "set")])
+ (set_attr "cc" "clobber")])
(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)
(not:HI (match_operand:HI 1 "register_operand" "r")))
(set (match_dup 2) (plus:HI (match_dup 2) (const_int 1)))
(set (match_operand:HI 0 "register_operand" "=r")
(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"
+ [(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)
(not:SI (match_operand:SI 1 "register_operand" "r")))
(set (match_dup 2) (plus:SI (match_dup 2) (const_int 1)))
(set (match_operand:SI 0 "register_operand" "=r")
(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"
@@ -672,7 +1080,13 @@
[(set (match_operand:HI 0 "register_operand" "=r")
(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 "length" "4")
(set_attr "cc" "clobber")])
@@ -681,15 +1095,24 @@
[(set (match_operand:SI 0 "register_operand" "=r")
(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")
+;; ??? length is wrong for 300h
(set_attr "length" "8")
(set_attr "cc" "clobber")])
-
+
;; ----------------------------------------------------------------------
-;; Conditional branches
+;; JUMP INSTRUCTIONS
;; ----------------------------------------------------------------------
+;; Conditional jump instructions
+
(define_expand "ble"
[(set (pc)
(if_then_else (le (cc0)
@@ -780,43 +1203,46 @@
""
"")
-(define_insn ""
+(define_insn "branch_true"
[(set (pc)
- (if_then_else
- (match_operator 1 "comparison_operator" [(cc0) (const_int 0)])
- (label_ref (match_operand 0 "" ""))
- (pc)))]
+ (if_then_else (match_operator 1 "comparison_operator"
+ [(cc0) (const_int 0)])
+ (label_ref (match_operand 0 "" ""))
+ (pc)))]
""
"*
{
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
- 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")])
-(define_insn ""
+(define_insn "branch_false"
[(set (pc)
- (if_then_else
- (match_operator 1 "comparison_operator" [(cc0) (const_int 0)])
- (pc)
- (label_ref (match_operand 0 "" ""))))]
+ (if_then_else (match_operator 1 "comparison_operator"
+ [(cc0) (const_int 0)])
+ (pc)
+ (label_ref (match_operand 0 "" ""))))]
""
+;; ??? We don't take advantage of 16 bit relative jumps in the 300h.
"*
{
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
- return \"b%j1 %L0\;jmp @%l0\;%L0:\";
+ return \"b%j1 %L0\;jmp @%l0\;%L0:\";
}"
[(set_attr "type" "branch")
(set_attr "cc" "none")])
-
-;; ----------------------------------------------------------------------
-;; Unconditional branches
-;; ----------------------------------------------------------------------
+
+;; Unconditional and other jump instructions.
(define_insn "jump"
[(set (pc)
@@ -824,27 +1250,83 @@
""
"*
{
- if (get_attr_length (insn) == 2)
- return \"bra %l0\";
+ if (get_attr_length (insn) == 2)
+ return \"bra %l0\";
+ else if (get_attr_length (insn) == 4)
+ return \"bra %l0:16\";
else
- return \"jmp @%l0\";
+ return \"jmp @%l0\";
}"
[(set_attr "type" "branch")
(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" ""))
(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"
+ [(set_attr "type" "branch")
+ (set_attr "cc" "none")
+ (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.
+;; ??? Even though we use HImode here, this works for the 300h.
+
(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"))]
""
"jsr %0"
@@ -855,9 +1337,11 @@
;; Call subroutine, returning value in operand 0
;; (which must be a hard register).
+;; ??? Even though we use HImode here, this works on the 300h.
+
(define_insn "call_value"
[(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")))]
""
"jsr %1"
@@ -873,450 +1357,862 @@
(set_attr "cc" "none")
(set_attr "length" "2")])
-(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")])
-
-;; -----------------------------------------------------------------
-;; 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")])
+;; ----------------------------------------------------------------------
+;; EXTEND INSTRUCTIONS
+;; ----------------------------------------------------------------------
-(define_insn "ashrqi3_one"
- [(set (match_operand:QI 0 "register_operand" "=r")
- (ashiftrt:QI (match_operand:QI 1 "register_operand" "0")
- (const_int 1)))]
+(define_insn "zero_extendqihi2"
+ [(set (match_operand:HI 0 "register_operand" "=r,r")
+ (zero_extend:HI (match_operand:QI 1 "general_operand" "0,g")))]
""
- "shar %X0"
- [(set_attr "type" "arith")
- (set_attr "length" "2")
- (set_attr "cc" "set")])
+ "*
+{
+ if (which_alternative==0)
+ return \"mov.b #0,%t0\";
-(define_insn "lshrqi3_one"
- [(set (match_operand:QI 0 "register_operand" "=r")
- (lshiftrt:QI (match_operand:QI 1 "register_operand" "0")
- (const_int 1)))]
- ""
- "shlr %X0"
- [(set_attr "type" "arith")
- (set_attr "length" "2")
- (set_attr "cc" "set")])
+ if (TARGET_H8300)
+ return \"mov.b %X1,%s0\;mov.b #0,%t0\";
+ else
+ {
+ /* ??? See how often this gets optimized. */
+ if (REG_P (operands[1]) && (REGNO (operands[1]) == REGNO (operands[0])))
+ return \"extu.w %T0\";
+ else
+ 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"
- [(set (match_operand:QI 0 "register_operand" "=r")
- (ashift:QI (match_operand:QI 1 "register_operand" "0")
- (match_operand:QI 2 "nonmemory_operand" "rn")))]
- ""
- "
+(define_insn "zero_extendhisi2"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (zero_extend:SI (match_operand:HI 1 "general_operand" "g")))]
+ "TARGET_H8300H"
+ "*
{
- if (can_shift (ASHIFT, operands, gen_ashlqi3_one, 4, 0))
- DONE;
+ /* ??? See how often this gets optimized. */
+ if (REG_P (operands[1]) && (REGNO (operands[1]) == REGNO (operands[0])))
+ return \"extu.l %S0\";
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"
- [(set (match_operand:QI 0 "register_operand" "=r")
- (ashiftrt:QI (match_operand:QI 1 "register_operand" "0")
- (match_operand:QI 2 "nonmemory_operand" "rn")))]
+(define_insn "extendqihi2"
+ [(set (match_operand:HI 0 "register_operand" "=r")
+ (sign_extend:HI (match_operand:QI 1 "general_operand" "g")))]
""
- "
+ "*
{
- if (can_shift (ASHIFTRT, operands, gen_ashrqi3_one, 4, 0))
- DONE;
+ if (TARGET_H8300)
+ {
+ /* ??? 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
- 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"
- [(set (match_operand:QI 0 "register_operand" "=r")
- (lshiftrt:QI (match_operand:QI 1 "register_operand" "0")
- (match_operand:QI 2 "nonmemory_operand" "rn")))]
+(define_expand "extendhisi2"
+ [(set (match_operand:SI 0 "register_operand" "")
+ (sign_extend:SI (match_operand:HI 1 "general_operand" "")))]
""
"
{
- if (can_shift (LSHIFTRT, operands, gen_lshrqi3_one, 4, 0))
- DONE;
+ if (TARGET_H8300)
+ emit_insn (gen_extendhisi2_h8300 (operands[0], operands[1]));
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"
- [(set (match_operand:HI 0 "register_operand" "=r")
- (ashift:HI (match_operand:HI 1 "register_operand" "0")
- (const_int 1)))]
- ""
- "add.w %T1,%T0"
- [(set_attr "type" "multi")
- (set_attr "length" "4")
- (set_attr "cc" "set")])
+(define_expand "extendhisi2_h8300h"
+ [(set (match_operand:SI 0 "register_operand" "")
+ (sign_extend:SI (match_operand:HI 1 "general_operand" "")))]
+ "TARGET_H8300H"
+ "")
-(define_insn "ashlhi3_eight"
- [(set (match_operand:HI 0 "register_operand" "=r")
- (ashift:HI (match_operand:HI 1 "register_operand" "0")
- (const_int 8)))]
- ""
- "mov.b %s1,%t0\;mov.b #0,%s0"
- [(set_attr "type" "multi")
- (set_attr "length" "4")
+(define_insn "extendhisi2_h8300_internal"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (sign_extend:SI (match_operand:HI 1 "register_operand" "0")))]
+ "TARGET_H8300"
+ "mov.w %T1,%f0\;bld #7,%x0\;subx %y0,%y0\;subx %z0,%z0"
+ [(set_attr "length" "10")
(set_attr "cc" "clobber")])
-(define_expand "ashlhi3"
- [(set (match_operand:HI 0 "register_operand" "")
- (ashift:HI
- (match_operand:HI 1 "general_operand_src" "")
- (match_operand:HI 2 "nonmemory_operand" "")))]
- ""
- "
+(define_insn "extendhisi2_h8300h_internal"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (sign_extend:SI (match_operand:HI 1 "general_operand" "g")))]
+ "TARGET_H8300H"
+ "*
{
- if (can_shift (ASHIFT, operands, gen_ashlhi3_one, 4, gen_ashlhi3_eight))
- DONE;
+ /* ??? See how often this gets optimized. */
+ if (REG_P (operands[1]) && (REGNO (operands[1]) == REGNO (operands[0])))
+ return \"exts.l %S0\";
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")
- (lshiftrt:HI (match_operand:HI 1 "register_operand" "0")
- (const_int 1)))]
+;; ----------------------------------------------------------------------
+;; SHIFTS
+;; ----------------------------------------------------------------------
+;;
+;; We make some attempt to provide real efficient shifting. One example is
+;; doing an 8 bit shift of a 16 bit value by moving a byte reg into the other
+;; reg and moving 0 into the former reg.
+;;
+;; We also try to achieve this in a uniform way. IE: We don't try to achieve
+;; this in both rtl and at insn emit time. Ideally, we'd use rtl as that would
+;; give the optimizer more cracks at the code. However, we wish to do things
+;; like optimizing shifting the sign bit to bit 0 by rotating the other way.
+;; There is rtl to handle this (rotate + and), but the h8/300 doesn't handle
+;; 16 bit rotates. Also, if we emit complicated rtl, combine may not be able
+;; to detect cases it can optimize.
+;;
+;; For these and other fuzzy reasons, I've decided to go the less pretty but
+;; easier "do it at insn emit time" route.
+
+;; 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"
- [(set_attr "type" "multi")
- (set_attr "length" "4")
- (set_attr "cc" "clobber")])
+ "if (expand_a_shift (QImode, ASHIFT, operands)) DONE;else FAIL;")
-(define_insn "lshrhi3_eight"
- [(set (match_operand:HI 0 "register_operand" "=r")
- (lshiftrt:HI (match_operand:HI 1 "register_operand" "0")
- (const_int 8)))]
+(define_expand "ashrqi3"
+ [(set (match_operand:QI 0 "register_operand" "")
+ (ashiftrt:QI (match_operand:QI 1 "register_operand" "")
+ (match_operand:QI 2 "nonmemory_operand" "")))]
""
- "mov.b %t1,%s0\;mov.b #0,%t0"
- [(set_attr "type" "multi")
- (set_attr "length" "4")
- (set_attr "cc" "clobber")])
+ "if (expand_a_shift (QImode, ASHIFTRT, operands)) DONE;else FAIL;")
-(define_expand "lshrhi3"
- [(set (match_operand:HI 0 "register_operand" "")
- (lshiftrt:HI
- (match_operand:HI 1 "general_operand_src" "")
- (match_operand:HI 2 "nonmemory_operand" "")))]
+(define_expand "lshrqi3"
+ [(set (match_operand:QI 0 "register_operand" "")
+ (lshiftrt:QI (match_operand:QI 1 "register_operand" "")
+ (match_operand:QI 2 "nonmemory_operand" "")))]
""
- "
-{
- if (can_shift (LSHIFTRT, operands, gen_lshrhi3_one, 4, gen_lshrhi3_eight))
- DONE;
- else
- FAIL;
-}")
+ "if (expand_a_shift (QImode, LSHIFTRT, operands)) DONE;else FAIL;")
-(define_insn "ashrhi3_one"
- [(set (match_operand:HI 0 "register_operand" "=r")
- (ashiftrt:HI (match_operand:HI 1 "register_operand" "0")
- (const_int 1)))]
+;; 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 "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"
- [(set_attr "type" "multi")
- (set_attr "length" "4")
+ "* 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")])
-; signed shift right by 8 bits
-; fetch the carry bit from the top, copy the byte right, subtract the
-; top byte from itself - carry.
+;; HI BIT SHIFTS
-(define_insn "ashrhi3_eight"
- [(set (match_operand:HI 0 "register_operand" "=r")
- (ashiftrt:HI (match_operand:HI 1 "register_operand" "0")
- (const_int 8)))]
+(define_expand "ashlhi3"
+ [(set (match_operand:HI 0 "register_operand" "")
+ (ashift:HI (match_operand:HI 1 "nonmemory_operand" "")
+ (match_operand:QI 2 "nonmemory_operand" "")))]
""
- "bld #7,%t0\;mov.b %t0,%s0\;subx %t0,%t0"
- [(set_attr "type" "multi")
- (set_attr "length" "6")
- (set_attr "cc" "clobber")])
+ "if (expand_a_shift (HImode, ASHIFT, operands)) DONE;else FAIL;")
+
+(define_expand "lshrhi3"
+ [(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"
[(set (match_operand:HI 0 "register_operand" "")
- (ashiftrt:HI
- (match_operand:HI 1 "general_operand_src" "")
- (match_operand:HI 2 "nonmemory_operand" "")))]
+ (ashiftrt:HI (match_operand:HI 1 "register_operand" "")
+ (match_operand:QI 2 "nonmemory_operand" "")))]
""
- "
-{
- if (can_shift (ASHIFTRT, operands, gen_ashrhi3_one, 4, gen_ashrhi3_eight))
- DONE;
- else
- FAIL;
-}")
+ "if (expand_a_shift (HImode, ASHIFTRT, operands)) 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"
- [(set (match_operand:SI 0 "register_operand" "=r")
- (ashift:SI (match_operand:SI 1 "register_operand" "0")
- (const_int 1)))]
+(define_insn "shiftbyn_HI"
+ [(set (match_operand:HI 0 "register_operand" "=r,r")
+ (match_operator:HI 3 "nshift_operator"
+ [ (match_operand:HI 1 "register_operand" "0,0")
+ (match_operand:QI 2 "nonmemory_operand" "IKM,rn")]))
+ (clobber (match_scratch:QI 4 "=X,&r"))]
""
- "add.w %f1,%f0\;addx %y1,%y0\;addx %z1,%z0"
- [(set_attr "type" "multi")
- (set_attr "length" "6")
+ "* 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")])
+;; SI BIT SHIFTS
+
(define_expand "ashlsi3"
[(set (match_operand:SI 0 "register_operand" "")
(ashift:SI
(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"
- [(set_attr "type" "multi")
- (set_attr "length" "8")
- (set_attr "cc" "clobber")])
+ "if (expand_a_shift (SImode, ASHIFT, operands)) DONE;else FAIL;")
(define_expand "lshrsi3"
[(set (match_operand:SI 0 "register_operand" "")
(lshiftrt:SI
(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"
- [(set_attr "type" "multi")
- (set_attr "length" "16")
- (set_attr "cc" "clobber")])
+ "if (expand_a_shift (SImode, LSHIFTRT, operands)) DONE;else FAIL;")
(define_expand "ashrsi3"
[(set (match_operand:SI 0 "register_operand" "")
(ashiftrt:SI
(match_operand:SI 1 "general_operand_src" "")
- (match_operand:SI 2 "nonmemory_operand" "")))]
+ (match_operand:QI 2 "nonmemory_operand" "")))]
""
- "
-{
- if (can_shift (ASHIFTRT, operands, gen_ashrsi3_one, 1, 0))
- DONE;
- else
- FAIL;
-}")
+ "if (expand_a_shift (SImode, ASHIFTRT, operands)) DONE;else FAIL;")
-;; ----------------------------------------------------------------------
-;; BIT FIELDS
-;; ----------------------------------------------------------------------
+;; 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 ""
- [(set (zero_extract:HI (match_operand:HI 0 "register_operand" "+r")
- (const_int 1)
- (match_operand:HI 2 "general_operand" "g"))
- (match_operand:HI 3 "general_operand" "r"))]
+(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"))]
""
- "bld #0,%3l\;bst %Z2,%0%Y1"
- [(set_attr "type" "multi")
- (set_attr "length" "4")
+ "* 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")])
-(define_expand "insv"
- [(set (zero_extract:HI (match_operand:HI 0 "register_operand" "+r")
- (match_operand:HI 1 "general_operand" "g")
- (match_operand:HI 2 "general_operand" "g"))
- (match_operand:HI 3 "general_operand" "r"))]
- ""
- "if (INTVAL (operands[1]) != 1) FAIL;")
+;; -----------------------------------------------------------------
+;; 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
-(define_insn ""
- [(set (match_operand:HI 0 "register_operand" "=&r")
- (zero_extract:HI (match_operand:HI 1 "register_operand" "r")
- (const_int 1)
- (match_operand:HI 3 "general_operand" "g")))]
+;; 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)))]
""
- "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")])
-(define_insn ""
- [(set (match_operand:HI 0 "register_operand" "=r")
- (sign_extract:HI (match_operand:HI 1 "register_operand" "r")
- (const_int 1)
- (match_operand:HI 3 "general_operand" "g")))]
+(define_insn "bcs_hihi"
+ [(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)))]
""
- "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")])
-(define_expand "extzv"
- [(set (match_operand:HI 0 "register_operand" "")
- (zero_extract:HI (match_operand:HI 1 "register_operand" "")
- (match_operand:HI 2 "general_operand" "")
- (match_operand:HI 3 "general_operand" "")))]
+(define_insn "bcs_hiqi"
+ [(set (pc)
+ (if_then_else
+ (match_operator 1 "eq_operator"
+ [(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"
- [(set (match_operand:HI 0 "register_operand" "")
- (sign_extract:HI (match_operand:HI 1 "register_operand" "")
- (match_operand:HI 2 "general_operand" "")
- (match_operand:HI 3 "immediate_operand" "")))]
+;; BLD and BST patterns
+
+(define_insn "extract_1"
+ [(set (match_operand:HI 0 "register_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[2]) != 1) FAIL;")
-
-;; ----------------------------------------------------------------------
-;; Conversions
-;; ----------------------------------------------------------------------
+ "sub.w %0,%0\;bld %Z2,%Y1\;bst #0,%X0")
-(define_insn "zero_extendqihi2"
- [(set (match_operand:HI 0 "register_operand" "=r")
- (zero_extend:HI
- (match_operand:QI 1 "general_operand" "g")))]
+(define_insn "extract_1_hi"
+ [(set (match_operand:HI 0 "register_operand" "=&r")
+ (zero_extract:HI (match_operand:HI 1 "bit_operand" "Ur")
+ (const_int 1)
+ (match_operand:HI 2 "immediate_operand" "i")))]
""
- "mov.b %X1,%s0\;mov.b #0,%t0"
- [(set_attr "type" "multi")
- (set_attr "length" "4")
- (set_attr "cc" "clobber")])
+ "sub.w %0,%0\;bld %Z2,%Y1\;bst #0,%X0")
-(define_insn "extendqihi2"
- [(set (match_operand:HI 0 "register_operand" "=r")
- (sign_extend:HI
- (match_operand:QI 1 "register_operand" "r")))]
+(define_insn "insert_1"
+ [(set (zero_extract:HI (match_operand:QI 0 "bit_operand" "+Ur")
+ (const_int 1)
+ (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]))
- return \"mov.b %X1,%s0\;bld #7,%s0\;subx %t0,%t0\";
- else
- return \"bld #7,%s0\;subx %t0,%t0\";
-}"
- [(set_attr "type" "multi")
+ if (INTVAL (operands[1]) != 1)
+ FAIL;
+
+ /* ??? HACK ???
+ This INSV pattern is wrong. It should use HImode for operand 3.
+ 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 "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" ""))
- (set (reg:SI 0) (sign_extend:SI (reg:HI 1)))
- (set (match_operand:SI 0 "general_operand" "" ) (reg:SI 0))]
+;; -------------------------------------------
+;; BLK moves
+;; -------------------------------------------
+
+(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))
+ ])]
""
- "")
-
-;; ----------------------------------------------------------------------
-;; peepholes
-;; ----------------------------------------------------------------------
+ "
+{
+ 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
+ ? 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
- [(set (match_operand:HI 1 "register_operand" "")
- (plus:HI (match_dup 1) (const_int -1)))
- (set (mem:HI (match_dup 1))
- (match_operand:HI 0 "register_operand" ""))]
- "REGNO (operands[1]) != REGNO (operands[0])"
- "mov.w %T0,@-%T1"
- [(set_attr "length" "2")
+;; Notice when two byte moves in a row could be a word move.
+
+(define_peephole
+ [(set (match_operand:QI 0 "register_operand" "=r")
+ (mem:QI (plus:HI (match_operand:HI 1 "register_operand" "ra")
+ (match_operand:HI 2 "immediate_operand" "n"))))
+ (set (match_operand:QI 3 "register_operand" "=r")
+ (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")])
+(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
- [(set (match_operand:HI 1 "register_operand" "")
- (plus:HI (match_dup 1) (const_int -1)))
- (set (mem:QI (match_dup 1))
- (match_operand:QI 0 "register_operand" ""))]
- "REGNO (operands[1]) != REGNO (operands[0])"
- "mov.b %X0,@-%T1"
+ [(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")])
-;; notice a move which could be post incremented
-
(define_peephole
[(set (match_operand:HI 0 "register_operand" "")
(mem:HI (match_operand:HI 1 "register_operand" "")))
(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"
[(set_attr "length" "2")
(set_attr "cc" "set")])
+;; Notice a move which could be predecremented.
+
(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 (match_operand:HI 1 "register_operand" "")
+ (plus:HI (match_dup 1) (const_int -1)))
+ (set (mem:QI (match_dup 1))
+ (match_operand:QI 0 "register_operand" ""))]
+ "REGNO(operands[1]) != REGNO(operands[0])"
+ "mov.b %X0,@-%T1"
[(set_attr "length" "2")
(set_attr "cc" "set")])
-;; notice when two byte moves in a row could be a word move
-
-(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")
+(define_peephole
+ [(set (match_operand:HI 1 "register_operand" "")
+ (plus:HI (match_dup 1) (const_int -1)))
+ (set (mem:HI (match_dup 1))
+ (match_operand:HI 0 "register_operand" ""))]
+ "REGNO(operands[1]) != REGNO(operands[0])"
+ "mov.w %T0,@-%T1"
+ [(set_attr "length" "2")
(set_attr "cc" "set")])
-(define_peephole
- [(set (match_operand:QI 0 "register_operand" "=r")
- (mem:QI (plus:HI (match_operand:HI 1 "register_operand" "ra")
- (match_operand:HI 2 "immediate_operand" "n"))))
- (set (match_operand:QI 3 "register_operand" "=r")
- (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")])
+;(define_insn ""
+; [(set (match_operand:HI 0 "register_operand" "=r")
+; (MEM:HI (match_operand:HI 1 "register_operand" "r")))
+; (set (match_operand:HI 3 "register_operand" "=r")
+; (zero_extract:HI (match_dup 0)
+; (const_int 1)
+; (match_operand:HI 2 "general_operand" "g")))
+; (set (MEM:HI (match_dup 1) (match_dup 3)))]
+; ""
+; "bld #0,%3l\;bst %Z2,%0%Y1"
+; [(set_attr "type" "multi")
+; (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")])