8sa1-gcc/gcc/config/h8300/h8300.md
Steve Chamberlain f82eca4d69 New File.
From-SVN: r3630
1993-03-04 18:02:42 +00:00

35 KiB
Raw Blame History

;;- Machine description for the Hitachi H8/300 for the GNU C compiler ;; Copyright (C) 1992, 1993 Free Software Foundation, Inc.

;; This file is part of GNU CC.

;; GNU CC is free software; you can redistribute it and/or modify ;; it under the terms of the GNU General Public License as published by ;; the Free Software Foundation; either version 2, or (at your option) ;; any later version.

;; GNU CC is distributed in the hope that it will be useful, ;; but WITHOUT ANY WARRANTY; without even the implied warranty of ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ;; GNU General Public License for more details.

;; You should have received a copy of the GNU General Public License ;; along with GNU CC; see the file COPYING. If not, write to ;; the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.

;; The original PO technology requires these to be ordered by speed, ;; so that assigner will pick the fastest.

;; See file "rtl.def" for documentation on define_insn, match_*, et. al.

(define_attr "type" "branch,return,call,arith,move,float,multi" (const_string "arith"))

;; The size of instructions in bytes.

(define_attr "length" "" (cond [(eq_attr "type" "branch") (if_then_else (and (ge (minus (pc) (match_dup 0)) (const_int -128)) (le (minus (pc) (match_dup 0)) (const_int 128))) (const_int 2) (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" (const_string "whoops")) ;; ---------------------------------------------------------------------- ;; move instructions ;; ----------------------------------------------------------------------

;; movhi

(define_insn "" [(set (match_operand:HI 0 "push_operand" "=<") (match_operand:HI 1 "register_operand" "ra"))] "" "mov.w %T1,%T0" [(set_attr "type" "move") (set_attr "length" "2") (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"))] "" "@ 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 "cc" "set")])

(define_insn "" [(set (match_operand:HI 0 "general_operand_dst" "=ra,ra,ra,o,<") (match_operand:HI 1 "general_operand_src" "I,ra,ion,ra,ra"))] "" "@ 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 "cc" "set")])

(define_expand "movhi" [(set (match_operand:HI 0 "general_operand_dst" "") (match_operand:HI 1 "general_operand_src" ""))] "" " { /* 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"))] "" "@ 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_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")])

(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); }")

;; 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"))] "" "* { 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"; 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);
  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);
    }
}
  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\";

case 3:
  return \"mov.w	%e1,%e0\;mov.w	%f1,%f0\";
case 4:
  return \"mov.w	%f1,%T0\;mov.w	%e1,%T0\";
}

}" [(set_attr "type" "move") (set_attr "length" "4,4,8,8,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"))] "" "* { /* This is a 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"; 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);
  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);
    }
}
  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\";

case 3:
  return \"mov.w	%e1,%e0\;mov.w	%f1,%f0\";
case 4:
  return \"mov.w	%f1,%T0\;mov.w	%e1,%T0\";

} }" [(set_attr "type" "move") (set_attr "length" "4,4,8,8,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" [(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;")

;; 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; } ") ;; ---------------------------------------------------------------------- ;; Test instructions ;; ----------------------------------------------------------------------

(define_insn "tstqi" [(set (cc0) (match_operand:QI 0 "register_operand" "ra"))] "" "cmp.b #0,%X0" [(set_attr "type" "arith") (set_attr "length" "2") (set_attr "cc" "set")])

(define_insn "tsthi" [(set (cc0) (match_operand:HI 0 "register_operand" "ra"))] "" "mov.w %T0,%T0" [(set_attr "type" "arith") (set_attr "length" "2") (set_attr "cc" "set")])

(define_insn "cmphi" [(set (cc0) (compare:HI (match_operand:HI 0 "register_operand" "ra") (match_operand:HI 1 "register_operand" "ra")))] "" "cmp.w %T1,%T0" [(set_attr "type" "arith") (set_attr "length" "2") (set_attr "cc" "compare")])

(define_insn "cmpqi" [(set (cc0) (compare:QI (match_operand:QI 0 "register_operand" "ra") (match_operand:QI 1 "nonmemory_operand" "rai")))] "" "cmp.b %X1,%X0" [(set_attr "type" "arith") (set_attr "length" "2") (set_attr "cc" "compare")]) ;; ---------------------------------------------------------------------- ;; Add instructions ;; ----------------------------------------------------------------------

(define_insn "" [(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 add.b %s2,%s0;addx %t2,%t0 add.w %T2,%T0" [(set_attr "type" "multi,multi,multi,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")])

(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")))] "" "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"))] "" "@ 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") (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")))] "" "@ 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" "arith") (set_attr "length" "8,6") (set_attr "cc" "clobber")])

(define_expand "addsi3" [(set (match_dup 3) (match_operand:SI 1 "register_operand" "")) (set (match_dup 3) (plus:SI (match_dup 3) (match_operand:SI 2 "nonmemory_operand" ""))) (set (match_operand:SI 0 "register_operand" "") (match_dup 3))] "" " { operands[3] = gen_rtx (REG, SImode, 0); }") ;; ----------------------------------------------------------------------; ;; Subtract instructions ;; ----------------------------------------------------------------------

(define_insn "" [(set (match_operand:HI 0 "register_operand" "=ra,ra,ra,r") (minus:HI (match_operand:HI 1 "general_operand" "0,0,0,0") (match_operand:HI 2 "nonmemory_operand" "K,M,ra,n")))] "" "@ subs %T2,%T0 subs #2,%T0;subs %E2,%T0 sub.w %T2,%T0 add.b %E2,%s0;addx %F2,%t0 ; -%0" [(set_attr "type" "multi") (set_attr "length" "2,4,2,4") (set_attr "cc" "none_0hit,none_0hit,set,clobber")])

(define_insn "subqi3" [(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" [(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")))] "" "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);")

;; ---------------------------------------------------------------------- ;; Multiply instruction ;; ----------------------------------------------------------------------

(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")))] "" "mulxu %X2,%T0" [(set_attr "type" "multi") (set_attr "length" "2") (set_attr "cc" "none_0hit")])

;; ---------------------------------------------------------------------- ;; Divide instructions ;; ----------------------------------------------------------------------

(define_insn "udivqi3" [(set (match_operand:QI 0 "register_operand" "=r") (udiv:QI (match_operand:HI 1 "general_operand" "0") (match_operand:QI 2 "register_operand" "r")))] "" "divxu %X2,%T0" [(set_attr "type" "multi") (set_attr "length" "2") (set_attr "cc" "clobber")])

(define_insn "divqi3" [(set (match_operand:QI 0 "register_operand" "=r") (div:QI (match_operand:HI 1 "general_operand" "0") (match_operand:QI 2 "register_operand" "r")))] "" "divxu %X2,%T0" [(set_attr "type" "multi") (set_attr "length" "2") (set_attr "cc" "clobber")]) ;; ---------------------------------------------------------------------- ;; And 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")))] "" "and %X2,%X0" [(set_attr "type" "arith") (set_attr "length" "2") (set_attr "cc" "set")])

(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")))] "" "and %s2,%s0;and %t2,%t0" [(set_attr "type" "multi") (set_attr "length" "4") (set_attr "cc" "clobber")]) ;; ---------------------------------------------------------------------- ;; 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")))] "" "@ or %X2,%X0 bset %V2,%X0" [(set_attr "type" "arith") (set_attr "length" "2,4") (set_attr "cc" "set,none_0hit")])

(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" [(set_attr "type" "multi") (set_attr "length" "2,4") (set_attr "cc" "clobber,clobber")]) ;; ---------------------------------------------------------------------- ;; 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" [(set_attr "type" "arith") (set_attr "length" "2") (set_attr "cc" "set")])

(define_insn "xorhi3" [(set (match_operand:HI 0 "general_operand" "=r") (xor:HI (match_operand:HI 1 "general_operand" "%0") (match_operand:HI 2 "nonmemory_operand" "ri")))] "" "xor %s2,%s0;xor %t2,%t0" [(set_attr "type" "multi") (set_attr "length" "4") (set_attr "cc" "clobber")]) ;; ---------------------------------------------------------------------- ;; Negation instructions ;; ----------------------------------------------------------------------

(define_insn "negqi2" [(set (match_operand:QI 0 "register_operand" "=r") (neg:QI (match_operand:QI 1 "general_operand" "0")))] "" "neg %X0" [(set_attr "type" "arith") (set_attr "length" "2") (set_attr "cc" "set")])

(define_expand "neghi2" [(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);")

(define_expand "negsi2" [(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);") ;; ---------------------------------------------------------------------- ;; Not instructions ;; ----------------------------------------------------------------------

(define_insn "one_cmplqi2" [(set (match_operand:QI 0 "register_operand" "=r") (not:QI (match_operand:QI 1 "general_operand" "0")))] "" "not %X0" [(set_attr "type" "arith") (set_attr "length" "2") (set_attr "cc" "set")])

(define_insn "one_cmplhi2" [(set (match_operand:HI 0 "register_operand" "=r") (not:HI (match_operand:HI 1 "general_operand" "0")))] "" "not %s0;not %t0" [(set_attr "type" "arith") (set_attr "length" "4") (set_attr "cc" "clobber")])

(define_insn "one_cmplsi2" [(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" [(set_attr "type" "arith") (set_attr "length" "8") (set_attr "cc" "clobber")]) ;; ---------------------------------------------------------------------- ;; Conditional branches ;; ----------------------------------------------------------------------

(define_expand "ble" [(set (pc) (if_then_else (le (cc0) (const_int 0)) (label_ref (match_operand 0 "" "")) (pc)))] "" "")

(define_expand "bleu" [(set (pc) (if_then_else (leu (cc0) (const_int 0)) (label_ref (match_operand 0 "" "")) (pc)))] "" "")

(define_expand "bge" [(set (pc) (if_then_else (ge (cc0) (const_int 0)) (label_ref (match_operand 0 "" "")) (pc)))] "" "")

(define_expand "bgeu" [(set (pc) (if_then_else (geu (cc0) (const_int 0)) (label_ref (match_operand 0 "" "")) (pc)))] "" "")

(define_expand "blt" [(set (pc) (if_then_else (lt (cc0) (const_int 0)) (label_ref (match_operand 0 "" "")) (pc)))] "" "")

(define_expand "bltu" [(set (pc) (if_then_else (ltu (cc0) (const_int 0)) (label_ref (match_operand 0 "" "")) (pc)))] "" "")

(define_expand "bgt" [(set (pc) (if_then_else (gt (cc0) (const_int 0)) (label_ref (match_operand 0 "" "")) (pc)))] "" "")

(define_expand "bgtu" [(set (pc) (if_then_else (gtu (cc0) (const_int 0)) (label_ref (match_operand 0 "" "")) (pc)))] "" "")

(define_expand "beq" [(set (pc) (if_then_else (eq (cc0) (const_int 0)) (label_ref (match_operand 0 "" "")) (pc)))] "" "")

(define_expand "bne" [(set (pc) (if_then_else (ne (cc0) (const_int 0)) (label_ref (match_operand 0 "" "")) (pc)))] "" "")

(define_insn "" [(set (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"; else return "b%k1 %L0;jmp @%l0;%L0:"; }" [(set_attr "type" "branch") (set_attr "cc" "none")])

(define_insn "" [(set (pc) (if_then_else (match_operator 1 "comparison_operator" [(cc0) (const_int 0)]) (pc) (label_ref (match_operand 0 "" ""))))] "" "* { if (get_attr_length (insn) == 2) return "b%k1 %l0"; else return "b%j1 %L0;jmp @%l0;%L0:"; }" [(set_attr "type" "branch") (set_attr "cc" "none")]) ;; ---------------------------------------------------------------------- ;; Unconditional branches ;; ----------------------------------------------------------------------

(define_insn "jump" [(set (pc) (label_ref (match_operand 0 "" "")))] "" "* { if (get_attr_length (insn) == 2) return "bra %l0"; else return "jmp @%l0"; }" [(set_attr "type" "branch") (set_attr "cc" "none")])

(define_insn "tablejump" [(set (pc) (match_operand:HI 0 "register_operand" "")) (use (label_ref (match_operand 1 "" "")))] "" "jmp @%0" [(set_attr "type" "branch") (set_attr "cc" "none") (set_attr "length" "2")])

;; Call subroutine with no return value.

(define_insn "call" [(call (match_operand:QI 0 "memory_operand" "o") (match_operand:HI 1 "general_operand" "g"))] "" "jsr %0" [(set_attr "type" "call") (set_attr "cc" "clobber") (set_attr "length" "4")])

;; Call subroutine, returning value in operand 0 ;; (which must be a hard register).

(define_insn "call_value" [(set (match_operand 0 "" "=r") (call (match_operand:QI 1 "memory_operand" "o") (match_operand:HI 2 "general_operand" "g")))] "" "jsr %1" [(set_attr "type" "call") (set_attr "cc" "clobber") (set_attr "length" "4")])

(define_insn "nop" [(const_int 0)] "" "nop" [(set_attr "type" "multi") (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")])

(define_insn "ashrqi3_one" [(set (match_operand:QI 0 "register_operand" "=r") (ashiftrt:QI (match_operand:QI 1 "register_operand" "0") (const_int 1)))] "" "shar %X0" [(set_attr "type" "arith") (set_attr "length" "2") (set_attr "cc" "set")])

(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")])

(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")))] "" " { if (can_shift (ASHIFT, operands, gen_ashlqi3_one, 4, 0)) DONE; else FAIL; }")

(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")))] "" " { if (can_shift (ASHIFTRT, operands, gen_ashrqi3_one, 4, 0)) DONE; else FAIL; }")

(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")))] "" " { if (can_shift (LSHIFTRT, operands, gen_lshrqi3_one, 4, 0)) DONE; else FAIL; }")

;; HI BIT SHIFTS

(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_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") (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" "")))] "" " { if (can_shift (ASHIFT, operands, gen_ashlhi3_one, 4, gen_ashlhi3_eight)) DONE; else FAIL; }")

(define_insn "lshrhi3_one" [(set (match_operand:HI 0 "register_operand" "=r") (lshiftrt:HI (match_operand:HI 1 "register_operand" "0") (const_int 1)))] "" "shlr %t0;rotxr %s0" [(set_attr "type" "multi") (set_attr "length" "4") (set_attr "cc" "clobber")])

(define_insn "lshlhi3_eight" [(set (match_operand:HI 0 "register_operand" "=r") (lshiftrt:HI (match_operand:HI 1 "register_operand" "0") (const_int 8)))] "" "mov.b %t1,%s0;mov.b #0,%t0" [(set_attr "type" "multi") (set_attr "length" "4") (set_attr "cc" "clobber")])

(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" "")))] "" " { if (can_shift (LSHIFTRT, operands, gen_lshrhi3_one, 4, gen_lshlhi3_eight)) 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)))] "" "shar %t0;rotxr %s0" [(set_attr "type" "multi") (set_attr "length" "4") (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.

(define_insn "ashrhi3_eight" [(set (match_operand:HI 0 "register_operand" "=r") (ashiftrt:HI (match_operand:HI 1 "register_operand" "0") (const_int 8)))] "" "bld #7,%t0;mov.b %t0,%s0;subx %t0,%t0" [(set_attr "type" "multi") (set_attr "length" "6") (set_attr "cc" "clobber")])

(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" "")))] "" " { if (can_shift (ASHIFTRT, operands, gen_ashrhi3_one, 4, gen_ashrhi3_eight)) DONE; else FAIL; }")

;; SI BIT SHIFTS

(define_insn "ashlsi3_one" [(set (match_operand:SI 0 "register_operand" "=r") (ashift:SI (match_operand:SI 1 "register_operand" "0") (const_int 1)))] "" "add.w %f1,%f0;addx %y1,%y0;addx %z1,%z0" [(set_attr "type" "multi") (set_attr "length" "6") (set_attr "cc" "clobber")])

(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" "")))] "" " { if (can_shift (ASHIFT, operands, gen_ashlsi3_one, 1, 0)) DONE; else FAIL; }")

(define_insn "lshrsi3_one" [(set (match_operand:SI 0 "register_operand" "=r") (lshiftrt:SI (match_operand:SI 1 "register_operand" "0") (const_int 1)))] "" "shlr %z0;rotxr %y0;rotxr %x0;rotxr %w0" [(set_attr "type" "multi") (set_attr "length" "8") (set_attr "cc" "clobber")])

(define_expand "lshrsi3" [(set (match_operand:SI 0 "register_operand" "") (lshiftrt:SI (match_operand:SI 1 "general_operand_src" "") (match_operand:SI 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")])

(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" "")))] "" " { if (can_shift (ASHIFTRT, operands, gen_ashrsi3_one, 1, 0)) DONE; else FAIL; }")

;; ---------------------------------------------------------------------- ;; BIT FIELDS ;; ----------------------------------------------------------------------

(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"))] "" "bld #0,%3l;bst %Z2,%0%Y1" [(set_attr "type" "multi") (set_attr "length" "4") (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;")

(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")))] "" "sub.w %T0,%T0;bld %Z3,%T1%Y1;rotxl %T0l" [(set_attr "type" "multi") (set_attr "length" "6") (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")))] "" "bld %Z3,%1%Y1;sub.x %0l,%0l;mov.b %0l,%0h" [(set_attr "type" "multi") (set_attr "length" "6") (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" "")))] "" "if (INTVAL (operands[2]) != 1) FAIL;")

(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" "")))] "" "if (INTVAL (operands[2]) != 1) FAIL;") ;; ---------------------------------------------------------------------- ;; Conversions ;; ----------------------------------------------------------------------

(define_insn "zero_extendqihi2" [(set (match_operand:HI 0 "register_operand" "=r") (zero_extend:HI (match_operand:QI 1 "general_operand" "g")))] "" "mov.b %X1,%s0;mov.b #0,%t0" [(set_attr "type" "multi") (set_attr "length" "4") (set_attr "cc" "clobber")])

(define_insn "extendqihi2" [(set (match_operand:HI 0 "register_operand" "=r") (sign_extend:HI (match_operand:QI 1 "register_operand" "r")))] "" "* { 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") (set_attr "length" "6") (set_attr "cc" "clobber")])

(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))] "" "") ;; ---------------------------------------------------------------------- ;; peepholes ;; ----------------------------------------------------------------------

;; notice a move which could be predecremented

(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: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 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])" "mov.w @%T1+,%T0" [(set_attr "length" "2") (set_attr "cc" "set")])

(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")])

;; 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") (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")])