;; GCC machine description for Hitachi H8/300 ;; Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, ;; 2001 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.

;; 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, 59 Temple Place - Suite 330, ;; Boston, MA 02111-1307, 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 “cpu” “h8300,h8300h” (const (symbol_ref “cpu_type”)))

;; Many logical operations should have “bit” variants if only one ;; bit is going to be operated on.

;; (and (logical op) (const_int X)) ;; If const_int only specifies a few bits (like a single byte in a 4 byte ;; operation, then it's more efficient to only apply the and and logical_op ;; to the bits we care about.

;; Some of the extend instructions accept a general_operand_src, which ;; allows all the normal memory addressing modes. The length computations ;; don't take this into account. The lengths in the MD file should be ;; “worst case” and then be adjusted to their correct values by ;; h8300_adjust_insn_length.

;; On the h8300h, adds/subs operate on the 32bit “er” registers. Right ;; now GCC doesn‘t expose the “e” half to the compiler, so using add/subs ;; for addhi and subhi is safe. ;; Long term, we want to expose the “e” half to the compiler (gives us ;; 8 more 16bit registers). At that point addhi and subhi can’t use adds/subs.

;; There's currently no way to have a insv/extzv expander for the H8/300H ;; because word_mode is different for the H8/300 and H8/300H.

;; Shifts/rotates by small constants should be handled by special ;; patterns so we get the length and cc status correct.

;; Bitfield operations no longer accept memory operands. We need ;; to add variants which operate on memory back to the MD.

;; ??? Implement remaining bit ops available on the h8300

(define_attr “type” “branch,arith” (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 -120)) (le (minus (pc) (match_dup 0)) (const_int 120))) (const_int 2) (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)))] (const_int 200)))

;; The necessity of instruction length adjustment.

(define_attr “adjust_length” “yes,no” (cond [(eq_attr “type” “branch”) (const_string “no”)] (const_string “yes”)))

;; Condition code settings. ;; none - insn does not affect cc ;; none_0hit - insn does not affect cc but it does modify operand 0 ;; This attribute is used to keep track of when operand 0 changes. ;; See the description of NOTICE_UPDATE_CC for more info. ;; set_znv - insn sets z,n,v to usable values (like a tst insn); c is unknown. ;; set_zn - insn sets z,n to usable values; v,c are unknown. ;; compare - compare instruction ;; clobber - value of cc is unknown (define_attr “cc” “none,none_0hit,set_znv,set_zn,compare,clobber” (const_string “clobber”)) ;; ---------------------------------------------------------------------- ;; MOVE INSTRUCTIONS ;; ----------------------------------------------------------------------

;; movqi

(define_insn “pushqi1_h8300” [(parallel [(set (reg:HI 7) (plus:HI (reg:HI 7) (const_int -2))) (set (mem:QI (plus:HI (reg:HI 7) (const_int -1))) (match_operand:QI 0 “register_operand” “r”))])] “TARGET_H8300” “mov.w %T0,@-r7” [(set_attr “length” “2”) (set_attr “cc” “clobber”)])

(define_insn “pushqi1_h8300hs” [(parallel [(set (reg:SI 7) (plus:SI (reg:SI 7) (const_int -4))) (set (mem:QI (plus:SI (reg:SI 7) (const_int -3))) (match_operand:QI 0 “register_operand” “r”))])] “TARGET_H8300H || TARGET_H8300S” “mov.l %S0,@-er7” [(set_attr “length” “4”) (set_attr “cc” “clobber”)])

(define_expand “pushqi1” [(use (match_operand:QI 0 “register_operand” “r”))] "" " { if (TARGET_H8300) emit_insn (gen_pushqi1_h8300 (operands[0])); else emit_insn (gen_pushqi1_h8300hs (operands[0])); DONE; }")

(define_insn "" [(set (match_operand:QI 0 “general_operand_dst” “=r,r ,<,r,r,m”) (match_operand:QI 1 “general_operand_src” " I,r>,r,n,m,r"))] “TARGET_H8300 && (register_operand (operands[0],QImode) || register_operand (operands[1], QImode))” “@ sub.b %X0,%X0 mov.b %R1,%X0 mov.b %X1,%R0 mov.b %R1,%X0 mov.b %R1,%X0 mov.b %X1,%R0” [(set_attr “length” “2,2,2,2,4,4”) (set_attr “cc” “set_zn,set_znv,set_znv,set_znv,set_znv,set_znv”)])

(define_insn "" [(set (match_operand:QI 0 “general_operand_dst” “=r,r ,<,r,r,m”) (match_operand:QI 1 “general_operand_src” " I,r>,r,n,m,r"))] “(TARGET_H8300H || TARGET_H8300S) && (register_operand (operands[0],QImode) || register_operand (operands[1], QImode))” “@ sub.b %X0,%X0 mov.b %R1,%X0 mov.b %X1,%R0 mov.b %R1,%X0 mov.b %R1,%X0 mov.b %X1,%R0” [(set_attr “length” “2,2,2,2,8,8”) (set_attr “cc” “set_zn,set_znv,set_znv,clobber,set_znv,set_znv”)])

(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,r”)) (match_operand:QI 1 “general_operand_src” “I,r,n,m”))] "" “@ sub.b %X0,%X0 mov.b %X1,%X0 mov.b %R1,%X0 mov.b %R1,%X0” [(set_attr_alternative “length” [(const_int 2) (const_int 2) (const_int 2) (if_then_else (eq_attr “cpu” “h8300”) (const_int 4) (const_int 8))]) (set_attr “cc” “set_zn,set_znv,set_znv,set_znv”)])

;; movhi

(define_expand “pushhi1_h8300” [(set (mem:QI (pre_dec:HI (reg:HI 7))) (match_operand:QI 0 “register_operand” “r”))] “TARGET_H8300” "")

(define_insn “pushhi1_h8300hs” [(parallel [(set (reg:SI 7) (plus:SI (reg:SI 7) (const_int -4))) (set (mem:HI (plus:SI (reg:SI 7) (const_int -2))) (match_operand:HI 0 “register_operand” “r”))])] “TARGET_H8300H || TARGET_H8300S” “mov.l %S0,@-er7” [(set_attr “length” “4”) (set_attr “cc” “clobber”)])

(define_expand “pushhi1” [(use (match_operand:QI 0 “register_operand” “r”))] "" " { if (TARGET_H8300) emit_insn (gen_pushhi1_h8300 (operands[0])); else emit_insn (gen_pushhi1_h8300hs (operands[0])); DONE; }")

(define_insn "" [(set (match_operand:HI 0 “general_operand_dst” “=r,r,<,r,r,m”) (match_operand:HI 1 “general_operand_src” “I,r>,r,i,m,r”))] “TARGET_H8300 && (register_operand (operands[0],HImode) || register_operand (operands[1], HImode)) && !(GET_CODE (operands[0]) == MEM && GET_CODE (XEXP (operands[0], 0)) == PRE_DEC && GET_CODE (XEXP (XEXP (operands[0], 0), 0)) == REG && GET_CODE (operands[1]) == REG && REGNO (XEXP (XEXP (operands[0], 0), 0)) == REGNO (operands[1]))” “@ sub.w %T0,%T0 mov.w %T1,%T0 mov.w %T1,%T0 mov.w %T1,%T0 mov.w %T1,%T0 mov.w %T1,%T0” [(set_attr “length” “2,2,2,4,4,4”) (set_attr “cc” “set_zn,set_znv,set_znv,set_znv,set_znv,set_znv”)])

(define_insn "" [(set (match_operand:HI 0 “general_operand_dst” “=r,r,<,r,r,m”) (match_operand:HI 1 “general_operand_src” “I,r>,r,i,m,r”))] “(TARGET_H8300H || TARGET_H8300S) && (register_operand (operands[0],HImode) || register_operand (operands[1], HImode))” “@ sub.w %T0,%T0 mov.w %T1,%T0 mov.w %T1,%T0 mov.w %T1,%T0 mov.w %T1,%T0 mov.w %T1,%T0” [(set_attr “length” “2,2,2,4,8,8”) (set_attr “cc” “set_zn,set_znv,set_znv,set_znv,set_znv,set_znv”)])

(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 “movstricthi” [(set (strict_low_part (match_operand:HI 0 “general_operand_dst” “+r,r,r,r”)) (match_operand:HI 1 “general_operand_src” “I,r,i,m”))] "" “@ sub.w %T0,%T0 mov.w %T1,%T0 mov.w %T1,%T0 mov.w %T1,%T0” [(set_attr_alternative “length” [(const_int 2) (const_int 2) (const_int 4) (if_then_else (eq_attr “cpu” “h8300”) (const_int 4) (const_int 8))]) (set_attr “cc” “set_zn,set_znv,set_znv,set_znv”)])

;; movsi

(define_expand “movsi” [(set (match_operand:SI 0 “general_operand_dst” "") (match_operand:SI 1 “general_operand_src” "“))] "" " { if (TARGET_H8300) { if (do_movsi (operands)) DONE; } else { /* 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); } } }”)

(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 { /* 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,io,r,r,>”))] “TARGET_H8300 && (register_operand (operands[0], SImode) || register_operand (operands[1], SImode))” “* { int rn = -1; switch (which_alternative) { case 0: return "sub.w %e0,%e0;sub.w %f0,%f0"; case 1: 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); 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 { / See if either half is zero. If so, use sub.w to clear that half. */ if (GET_CODE (operands[1]) == CONST_INT) { if ((INTVAL (operands[1]) & 0xffff) == 0) return "mov.w %e1,%e0;sub.w %f0,%f0"; if (((INTVAL (operands[1]) >> 16) & 0xffff) == 0) return "sub.w %e0,%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"; default: abort(); } }” [(set_attr “length” “4,4,8,8,4,4”) (set_attr “cc” “clobber”)])

(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,io,r,r,>”))] “TARGET_H8300 && (register_operand (operands[0], SFmode) || register_operand (operands[1], SFmode))” "* { /* Copy of the movsi stuff. / int rn = -1; switch (which_alternative) { case 0: return "sub.w %e0,%e0;sub.w %f0,%f0"; case 1: 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); 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 / Move the first word first. */ 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\";
default:
  abort();
}

}" [(set_attr “length” “4,4,8,8,4,4”) (set_attr “cc” “clobber”)])

(define_insn “movsi_h8300hs” [(set (match_operand:SI 0 “general_operand_dst” “=r,r,r,r,m,<,r,*a,*a,r”) (match_operand:SI 1 “general_operand_src” “I,r,i,m,r,r,>,I,r,*a”))] “(TARGET_H8300S || TARGET_H8300H) && (register_operand (operands[0], SImode) || register_operand (operands[1], SImode)) && !(GET_CODE (operands[0]) == MEM && GET_CODE (XEXP (operands[0], 0)) == PRE_DEC && GET_CODE (XEXP (XEXP (operands[0], 0), 0)) == REG && GET_CODE (operands[1]) == REG && REGNO (XEXP (XEXP (operands[0], 0), 0)) == REGNO (operands[1]))” "* { switch (which_alternative) { case 0: return "sub.l %S0,%S0"; case 7: return "clrmac"; case 8: return "clrmac;ldmac %1,macl"; case 9: return "stmac macl,%0"; default: if (GET_CODE (operands[1]) == CONST_INT) { int val = INTVAL (operands[1]);

  /* Look for constants which can be made by adding an 8-bit
     number to zero in one of the two low bytes.  */
  if (val == (val & 0xff))
    {
      operands[1] = GEN_INT ((char) val & 0xff);
      return \"sub.l\\t%S0,%S0\;add.b\\t%1,%w0\";
    }

  if (val == (val & 0xff00))
    {
      operands[1] = GEN_INT ((char) (val >> 8) & 0xff);
      return \"sub.l\\t%S0,%S0\;add.b\\t%1,%x0\";
    }

  /* Look for constants that can be obtained by subs, inc, and
         dec to 0.  */
  switch (val & 0xffffffff)
    {
    case 0xffffffff:
      return \"sub.l\\t%S0,%S0\;subs\\t#1,%S0\";
    case 0xfffffffe:
      return \"sub.l\\t%S0,%S0\;subs\\t#2,%S0\";
    case 0xfffffffc:
      return \"sub.l\\t%S0,%S0\;subs\\t#4,%S0\";

    case 0x0000ffff:
      return \"sub.l\\t%S0,%S0\;dec.w\\t#1,%f0\";
    case 0x0000fffe:
      return \"sub.l\\t%S0,%S0\;dec.w\\t#2,%f0\";

    case 0xffff0000:
      return \"sub.l\\t%S0,%S0\;dec.w\\t#1,%e0\";
    case 0xfffe0000:
      return \"sub.l\\t%S0,%S0\;dec.w\\t#2,%e0\";

    case 0x00010000:
      return \"sub.l\\t%S0,%S0\;inc.w\\t#1,%e0\";
    case 0x00020000:
      return \"sub.l\\t%S0,%S0\;inc.w\\t#2,%e0\";
    }
}
}

return "mov.l %S1,%S0"; }" [(set_attr “length” “2,2,10,10,10,4,4,2,6,4”) (set_attr “cc” “set_zn,set_znv,clobber,set_znv,set_znv,set_znv,set_znv,none_0hit,none_0hit,set_znv”)])

(define_insn “movsf_h8300h” [(set (match_operand:SF 0 “general_operand_dst” “=r,r,r,m,<,r”) (match_operand:SF 1 “general_operand_src” “I,r,im,r,r,>”))] “(TARGET_H8300H || TARGET_H8300S) && (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 mov.l %S1,%S0” [(set_attr “length” “2,2,10,10,4,4”) (set_attr “cc” “set_zn,set_znv,set_znv,set_znv,set_znv,set_znv”)]) ;; ---------------------------------------------------------------------- ;; TEST INSTRUCTIONS ;; ----------------------------------------------------------------------

(define_insn "" [(set (cc0) (zero_extract:QI (match_operand:QI 0 “bit_memory_operand” “r,U”) (const_int 1) (match_operand:QI 1 “const_int_operand” “n,n”)))] "" “btst %Z1,%R0” [(set_attr “length” “2,8”) (set_attr “cc” “set_zn,set_zn”)])

(define_insn "" [(set (cc0) (zero_extract:HI (match_operand:QI 0 “bit_memory_operand” “r,U”) (const_int 1) (match_operand:QI 1 “const_int_operand” “n,n”)))] "" “btst %Z1,%Y0” [(set_attr “length” “2,8”) (set_attr “cc” “set_zn,set_zn”)])

(define_insn "" [(set (cc0) (zero_extract:SI (match_operand:QI 0 “bit_memory_operand” “r,U”) (const_int 1) (match_operand:QI 1 “const_int_operand” “n,n”)))] "" “btst %Z1,%Y0” [(set_attr “length” “2,8”) (set_attr “cc” “set_zn,set_zn”)])

(define_insn "" [(set (cc0) (zero_extract:QI (match_operand:HI 0 “register_operand” “r”) (const_int 1) (match_operand:HI 1 “const_int_operand” “n”)))] "" “btst %Z1,%R0” [(set_attr “length” “2”) (set_attr “cc” “set_zn”)])

(define_insn "" [(set (cc0) (zero_extract:HI (match_operand:HI 0 “register_operand” “r”) (const_int 1) (match_operand:HI 1 “const_int_operand” “n”)))] "" “btst %Z1,%Y0” [(set_attr “length” “2”) (set_attr “cc” “set_zn”)])

(define_insn "" [(set (cc0) (zero_extract:SI (match_operand:HI 0 “register_operand” “r”) (const_int 1) (match_operand:HI 1 “const_int_operand” “n”)))] "" “btst %Z1,%Y0” [(set_attr “length” “2”) (set_attr “cc” “set_zn”)])

(define_insn “tstqi” [(set (cc0) (match_operand:QI 0 “register_operand” “r”))] "" “mov.b %X0,%X0” [(set_attr “length” “2”) (set_attr “cc” “set_znv”)])

(define_insn “tsthi” [(set (cc0) (match_operand:HI 0 “register_operand” “r”))] "" “mov.w %T0,%T0” [(set_attr “length” “2”) (set_attr “cc” “set_znv”)])

(define_insn “tstsi” [(set (cc0) (match_operand:SI 0 “register_operand” “r”))] “TARGET_H8300H || TARGET_H8300S” “mov.l %S0,%S0” [(set_attr “length” “2”) (set_attr “cc” “set_znv”)])

(define_insn “cmpqi” [(set (cc0) (compare:QI (match_operand:QI 0 “register_operand” “r”) (match_operand:QI 1 “nonmemory_operand” “rn”)))] "" “cmp.b %X1,%X0” [(set_attr “length” “2”) (set_attr “cc” “compare”)])

(define_expand “cmphi” [(set (cc0) (compare:HI (match_operand:HI 0 “register_operand” "") (match_operand:HI 1 “nonmemory_operand” "“)))] "" " { /* Force operand1 into a register if we're compiling for the H8/300. */ if (GET_CODE (operands[1]) != REG && TARGET_H8300) operands[1] = force_reg (HImode, operands[1]); }”)

(define_insn "" [(set (cc0) (compare:HI (match_operand:HI 0 “register_operand” “r”) (match_operand:HI 1 “register_operand” “r”)))] “TARGET_H8300” “cmp.w %T1,%T0” [(set_attr “length” “2”) (set_attr “cc” “compare”)])

(define_insn "" [(set (cc0) (compare:HI (match_operand:HI 0 “register_operand” “r,r”) (match_operand:HI 1 “nonmemory_operand” “r,n”)))] “TARGET_H8300H || TARGET_H8300S” “cmp.w %T1,%T0” [(set_attr “length” “2,4”) (set_attr “cc” “compare,compare”)])

(define_insn “cmpsi” [(set (cc0) (compare:SI (match_operand:SI 0 “register_operand” “r,r”) (match_operand:SI 1 “nonmemory_operand” “r,i”)))] “TARGET_H8300H || TARGET_H8300S” “cmp.l %S1,%S0” [(set_attr “length” “2,6”) (set_attr “cc” “compare,compare”)]) ;; ---------------------------------------------------------------------- ;; ADD INSTRUCTIONS ;; ----------------------------------------------------------------------

(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” “rn”)))] "" “add.b %X2,%X0” [(set_attr “length” “2”) (set_attr “cc” “set_zn”)])

(define_expand “addhi3” [(set (match_operand:HI 0 “register_operand” "") (plus:HI (match_operand:HI 1 “register_operand” "") (match_operand:HI 2 “nonmemory_operand” "")))] "" "")

(define_insn "" [(set (match_operand:HI 0 “register_operand” “=r,r,r,r,&r”) (plus:HI (match_operand:HI 1 “register_operand” “%0,0,0,0,g”) (match_operand:HI 2 “nonmemory_operand” “L,N,n,r,r”)))] “TARGET_H8300” “@ adds %2,%A0 subs %G2,%A0 add.b %s2,%s0;addx %t2,%t0 add.w %T2,%T0 mov.w %T1,%T0;add.w %T2,%T0” [(set_attr “length” “2,2,4,2,6”) (set_attr “cc” “none_0hit,none_0hit,clobber,set_zn,set_zn”)])

(define_insn "" [(set (match_operand:HI 0 “register_operand” “=r,r,r,r”) (plus:HI (match_operand:HI 1 “register_operand” “%0,0,0,0”) (match_operand:HI 2 “nonmemory_operand” “L,N,n,r”)))] “TARGET_H8300H || TARGET_H8300S” “@ adds %2,%A0 subs %G2,%A0 add.w %T2,%T0 add.w %T2,%T0” [(set_attr “length” “2,2,4,2”) (set_attr “cc” “none_0hit,none_0hit,set_zn,set_zn”)])

(define_split [(set (match_operand:HI 0 “register_operand” "") (plus:HI (match_dup 0) (match_operand:HI 1 “two_insn_adds_subs_operand” "")))] "" [(const_int 0)] “split_adds_subs (HImode, operands); DONE;”)

(define_expand “addsi3” [(set (match_operand:SI 0 “register_operand” "") (plus:SI (match_operand:SI 1 “register_operand” "") (match_operand:SI 2 “nonmemory_operand” "")))] "" "")

(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 mov.w %f1,%f0;mov.w %e1,%e0;add.w %f2,%f0;addx %y2,%y0;addx %z2,%z0” [(set_attr “length” “8,6,10”) (set_attr “cc” “clobber”)])

(define_insn “addsi_h8300h” [(set (match_operand:SI 0 “register_operand” “=r,r,r,r”) (plus:SI (match_operand:SI 1 “register_operand” “%0,0,0,0”) (match_operand:SI 2 “nonmemory_operand” “L,N,i,r”)))] “TARGET_H8300H || TARGET_H8300S” “@ adds %2,%A0 subs %G2,%A0 add.l %S2,%S0 add.l %S2,%S0” [(set_attr “length” “2,2,6,2”) (set_attr “cc” “none_0hit,none_0hit,set_zn,set_zn”)])

(define_split [(set (match_operand:SI 0 “register_operand” "") (plus:SI (match_dup 0) (match_operand:SI 1 “two_insn_adds_subs_operand” "")))] “TARGET_H8300H || TARGET_H8300S” [(const_int 0)] “split_adds_subs (SImode, operands); DONE;”)

;; ---------------------------------------------------------------------- ;; 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,n”)))] "" “@ sub.b %X2,%X0 add.b %G2,%X0” [(set_attr “length” “2”) (set_attr “cc” “set_zn”)])

(define_expand “subhi3” [(set (match_operand:HI 0 “register_operand” "") (minus:HI (match_operand:HI 1 “general_operand” "") (match_operand:HI 2 “nonmemory_operand” "")))] "" "")

(define_insn "" [(set (match_operand:HI 0 “register_operand” “=r,&r”) (minus:HI (match_operand:HI 1 “general_operand” “0,0”) (match_operand:HI 2 “nonmemory_operand” “r,n”)))] “TARGET_H8300” “@ sub.w %T2,%T0 add.b %E2,%s0;addx %F2,%t0” [(set_attr “length” “2,4”) (set_attr “cc” “set_zn,clobber”)])

(define_insn "" [(set (match_operand:HI 0 “register_operand” “=r,&r”) (minus:HI (match_operand:HI 1 “general_operand” “0,0”) (match_operand:HI 2 “nonmemory_operand” “r,n”)))] “TARGET_H8300H || TARGET_H8300S” “@ sub.w %T2,%T0 sub.w %T2,%T0” [(set_attr “length” “2,4”) (set_attr “cc” “set_zn,set_zn”)])

(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 “length” “6”) (set_attr “cc” “clobber”)])

(define_insn “subsi3_h8300h” [(set (match_operand:SI 0 “register_operand” “=r,r”) (minus:SI (match_operand:SI 1 “general_operand” “0,0”) (match_operand:SI 2 “nonmemory_operand” “r,i”)))] “TARGET_H8300H || TARGET_H8300S” “@ sub.l %S2,%S0 sub.l %S2,%S0” [(set_attr “length” “2,6”) (set_attr “cc” “set_zn,set_zn”)]) ;; ---------------------------------------------------------------------- ;; 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 || TARGET_H8300S” “mulxs.b %X2,%T0” [(set_attr “length” “4”) (set_attr “cc” “set_zn”)])

(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 || TARGET_H8300S” “mulxs.w %T2,%S0” [(set_attr “length” “4”) (set_attr “cc” “set_zn”)])

(define_insn “umulqihi3” [(set (match_operand:HI 0 “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 “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 || TARGET_H8300S” “mulxu.w %T2,%S0” [(set_attr “length” “2”) (set_attr “cc” “none_0hit”)])

;; This is a “bridge” instruction. Combine can‘t cram enough insns ;; together to crate a MAC instruction directly, but it can create ;; this instruction, which then allows combine to create the real ;; MAC insn. ;; ;; Unfortunately, if combine doesn’t create a MAC instruction, this ;; insn must generate reasonably correct code. Egad. (define_insn "" [(set (match_operand:SI 0 “register_operand” “=a”) (mult:SI (sign_extend:SI (mem:HI (post_inc:SI (match_operand:SI 1 “register_operand” “r”)))) (sign_extend:SI (mem:HI (post_inc:SI (match_operand:SI 2 “register_operand” “r”))))))] “TARGET_MAC” “clrmac;mac @%2+,@%1+” [(set_attr “length” “6”) (set_attr “cc” “none_0hit”)])

(define_insn "" [(set (match_operand:SI 0 “register_operand” “=a”) (plus:SI (mult:SI (sign_extend:SI (mem:HI (post_inc:SI (match_operand:SI 1 “register_operand” “r”)))) (sign_extend:SI (mem:HI (post_inc:SI (match_operand:SI 2 “register_operand” “r”))))) (match_operand:SI 3 “register_operand” “0”)))] “TARGET_MAC” “mac @%2+,@%1+” [(set_attr “length” “4”) (set_attr “cc” “none_0hit”)])

;; ---------------------------------------------------------------------- ;; DIVIDE/MOD INSTRUCTIONS ;; ----------------------------------------------------------------------

(define_insn “udivmodqi4” [(set (match_operand:QI 0 “register_operand” “=r”) (truncate:QI (udiv:HI (match_operand:HI 1 “general_operand” “0”) (zero_extend:HI (match_operand:QI 2 “register_operand” “r”))))) (set (match_operand:QI 3 “register_operand” “=r”) (truncate:QI (umod:HI (match_dup 1) (zero_extend:HI (match_dup 2)))))] “TARGET_H8300H || TARGET_H8300S” “* { if (find_reg_note (insn, REG_UNUSED, operands[3])) return "divxu.b\t%X2,%T0"; else return "divxu.b\t%X2,%T0;mov.b\t%t0,%s3"; }” [(set_attr “length” “4”) (set_attr “cc” “clobber”)])

(define_insn “divmodqi4” [(set (match_operand:QI 0 “register_operand” “=r”) (truncate:QI (div:HI (match_operand:HI 1 “general_operand” “0”) (sign_extend:HI (match_operand:QI 2 “register_operand” “r”))))) (set (match_operand:QI 3 “register_operand” “=r”) (truncate:QI (mod:HI (match_dup 1) (sign_extend:HI (match_dup 2)))))] “TARGET_H8300H || TARGET_H8300S” “* { if (find_reg_note (insn, REG_UNUSED, operands[3])) return "divxs.b\t%X2,%T0"; else return "divxs.b\t%X2,%T0;mov.b\t%t0,%s3"; }” [(set_attr “length” “6”) (set_attr “cc” “clobber”)])

(define_insn “udivmodhi4” [(set (match_operand:HI 0 “register_operand” “=r”) (truncate:HI (udiv:SI (match_operand:SI 1 “general_operand” “0”) (zero_extend:SI (match_operand:HI 2 “register_operand” “r”))))) (set (match_operand:HI 3 “register_operand” “=r”) (truncate:HI (umod:SI (match_dup 1) (zero_extend:SI (match_dup 2)))))] “TARGET_H8300H || TARGET_H8300S” “* { if (find_reg_note (insn, REG_UNUSED, operands[3])) return "divxu.w\t%T2,%S0"; else return "divxu.w\t%T2,%S0;mov.w\t%e0,%f3"; }” [(set_attr “length” “4”) (set_attr “cc” “clobber”)])

(define_insn “divmodhi4” [(set (match_operand:HI 0 “register_operand” “=r”) (truncate:HI (div:SI (match_operand:SI 1 “general_operand” “0”) (sign_extend:SI (match_operand:HI 2 “register_operand” “r”))))) (set (match_operand:HI 3 “register_operand” “=r”) (truncate:HI (mod:SI (match_dup 1) (sign_extend:SI (match_dup 2)))))] “TARGET_H8300H || TARGET_H8300S” “* { if (find_reg_note (insn, REG_UNUSED, operands[3])) return "divxs.w\t%T2,%S0"; else return "divxs.w\t%T2,%S0;mov.w\t%e0,%f3"; }” [(set_attr “length” “6”) (set_attr “cc” “clobber”)]) ;; ---------------------------------------------------------------------- ;; AND INSTRUCTIONS ;; ----------------------------------------------------------------------

(define_insn "" [(set (match_operand:QI 0 “bit_operand” “=r,U”) (and:QI (match_operand:QI 1 “bit_operand” “%0,0”) (match_operand:QI 2 “nonmemory_operand” “rn,O”)))] “register_operand (operands[0], QImode) || o_operand (operands[2], QImode)” “@ and %X2,%X0 bclr %W2,%R0” [(set_attr “length” “2,8”) (set_attr “adjust_length” “no”) (set_attr “cc” “set_znv,none_0hit”)])

(define_expand “andqi3” [(set (match_operand:QI 0 “bit_operand” "") (and:QI (match_operand:QI 1 “bit_operand” "") (match_operand:QI 2 “nonmemory_operand” "“)))] "" " { if (fix_bit_operand (operands, ‘O’, AND)) DONE; }”)

(define_expand “andhi3” [(set (match_operand:HI 0 “register_operand” "") (and:HI (match_operand:HI 1 “register_operand” "") (match_operand:HI 2 “nonmemory_operand” "")))] "" "")

(define_insn "" [(set (match_operand:HI 0 “register_operand” “=r”) (and:HI (match_operand:HI 1 “register_operand” “%0”) (match_operand:HI 2 “nonmemory_operand” “rn”)))] “TARGET_H8300” “* return output_logical_op (HImode, AND, operands);” [(set_attr “length” “4”) (set_attr “cc” “clobber”)])

(define_insn "" [(set (match_operand:HI 0 “register_operand” “=r,r”) (and:HI (match_operand:HI 1 “register_operand” “%0,0”) (match_operand:HI 2 “nonmemory_operand” “r,n”)))] “TARGET_H8300H || TARGET_H8300S” “* return output_logical_op (HImode, AND, operands);” [(set_attr “length” “2,4”) (set_attr “cc” “set_znv,clobber”)])

(define_insn “*andorhi3” [(set (match_operand:HI 0 “register_operand” “=r”) (ior:HI (and:HI (match_operand:HI 2 “register_operand” “r”) (match_operand:HI 3 “p_operand” “P”)) (match_operand:HI 1 “register_operand” “0”)))] "" “* { if (INTVAL (operands[3]) > 128) { operands[3] = GEN_INT (INTVAL (operands[3]) >> 8); return "bld\t%V3,%t2;bst\t%V3,%t0"; } return "bld\t%V3,%s2;bst\t%V3,%s0"; }” [(set_attr “length” “4”) (set_attr “cc” “clobber”)])

(define_expand “andsi3” [(set (match_operand:SI 0 “register_operand” "") (and:SI (match_operand:SI 1 “register_operand” "") (match_operand:SI 2 “nonmemory_operand” "")))] "" "")

(define_insn "" [(set (match_operand:SI 0 “register_operand” “=r”) (and:SI (match_operand:SI 1 “register_operand” “%0”) (match_operand:SI 2 “nonmemory_operand” “rn”)))] “TARGET_H8300” “* return output_logical_op (SImode, AND, operands);” [(set_attr “length” “8”) (set_attr “cc” “clobber”)])

(define_insn "" [(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,n”)))] “TARGET_H8300H || TARGET_H8300S” “* return output_logical_op (SImode, AND, operands);” [(set_attr “length” “4,6”) (set_attr “cc” “set_znv,clobber”)])

;; ---------------------------------------------------------------------- ;; OR INSTRUCTIONS ;; ----------------------------------------------------------------------

(define_insn "" [(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”)))] “register_operand (operands[0], QImode) || p_operand (operands[2], QImode)” “@ or %X2,%X0 bset %V2,%R0” [(set_attr “length” “2,8”) (set_attr “adjust_length” “no”) (set_attr “cc” “set_znv,none_0hit”)])

(define_expand “iorqi3” [(set (match_operand:QI 0 “bit_operand” "") (ior:QI (match_operand:QI 1 “bit_operand” "") (match_operand:QI 2 “nonmemory_operand” "“)))] "" " { if (fix_bit_operand (operands, ‘P’, IOR)) DONE; }”)

(define_expand “iorhi3” [(set (match_operand:HI 0 “general_operand” "") (ior:HI (match_operand:HI 1 “general_operand” "") (match_operand:HI 2 “general_operand” "")))] "" "")

(define_insn "" [(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,rn”)))] “TARGET_H8300” “* return output_logical_op (HImode, IOR, operands);” [(set_attr “length” “2,4”) (set_attr “cc” “clobber,clobber”)])

(define_insn "" [(set (match_operand:HI 0 “general_operand” “=r,r,r”) (ior:HI (match_operand:HI 1 “general_operand” “%0,0,0”) (match_operand:HI 2 “general_operand” “J,r,n”)))] “TARGET_H8300H || TARGET_H8300S” “* return output_logical_op (HImode, IOR, operands);” [(set_attr “length” “2,2,4”) (set_attr “cc” “clobber,set_znv,clobber”)])

(define_expand “iorsi3” [(set (match_operand:SI 0 “register_operand” "") (ior:SI (match_operand:SI 1 “register_operand” "") (match_operand:SI 2 “nonmemory_operand” "")))] "" "")

(define_insn "" [(set (match_operand:SI 0 “register_operand” “=r,r”) (ior:SI (match_operand:SI 1 “register_operand” “%0,0”) (match_operand:SI 2 “nonmemory_operand” “J,rn”)))] “TARGET_H8300” “* return output_logical_op (SImode, IOR, operands);” [(set_attr “length” “2,8”) (set_attr “cc” “clobber,clobber”)])

(define_insn "" [(set (match_operand:SI 0 “register_operand” “=r,r,r”) (ior:SI (match_operand:SI 1 “register_operand” “%0,0,0”) (match_operand:SI 2 “nonmemory_operand” “J,r,n”)))] “TARGET_H8300H || TARGET_H8300S” “* return output_logical_op (SImode, IOR, operands);” [(set_attr “length” “2,4,6”) (set_attr “cc” “clobber,set_znv,clobber”)])

;; ---------------------------------------------------------------------- ;; XOR INSTRUCTIONS ;; ----------------------------------------------------------------------

(define_insn "" [(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,%R0” [(set_attr “length” “2,8”) (set_attr “adjust_length” “no”) (set_attr “cc” “set_znv,none_0hit”)])

(define_expand “xorqi3” [(set (match_operand:QI 0 “bit_operand” "") (xor:QI (match_operand:QI 1 “bit_operand” "") (match_operand:QI 2 “nonmemory_operand” "“)))] "" " { if (fix_bit_operand (operands, ‘O’, XOR)) DONE; }”)

(define_expand “xorhi3” [(set (match_operand:HI 0 “register_operand” "") (xor:HI (match_operand:HI 1 “general_operand” "") (match_operand:HI 2 “nonmemory_operand” "")))] "" "")

(define_insn "" [(set (match_operand:HI 0 “register_operand” “=r,r”) (xor:HI (match_operand:HI 1 “general_operand” “%0,0”) (match_operand:HI 2 “nonmemory_operand” “J,rn”)))] “TARGET_H8300” “* return output_logical_op (HImode, XOR, operands);” [(set_attr “length” “2,4”) (set_attr “cc” “clobber,clobber”)])

(define_insn "" [(set (match_operand:HI 0 “register_operand” “=r,r,r”) (xor:HI (match_operand:HI 1 “general_operand” “%0,0,0”) (match_operand:HI 2 “nonmemory_operand” “J,r,n”)))] “TARGET_H8300H || TARGET_H8300S” “* return output_logical_op (HImode, XOR, operands);” [(set_attr “length” “2,2,4”) (set_attr “cc” “clobber,set_znv,clobber”)])

(define_expand “xorsi3” [(set (match_operand:SI 0 “register_operand” "") (xor:SI (match_operand:SI 1 “register_operand” "") (match_operand:SI 2 “nonmemory_operand” "")))] "" "")

(define_insn "" [(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” “J,rn”)))] “TARGET_H8300” “* return output_logical_op (SImode, XOR, operands);” [(set_attr “length” “2,8”) (set_attr “cc” “clobber,clobber”)])

(define_insn "" [(set (match_operand:SI 0 “register_operand” “=r,r,r”) (xor:SI (match_operand:SI 1 “register_operand” “%0,0,0”) (match_operand:SI 2 “nonmemory_operand” “J,r,n”)))] “TARGET_H8300H || TARGET_H8300S” “* return output_logical_op (SImode, XOR, operands);” [(set_attr “length” “2,4,6”) (set_attr “cc” “clobber,set_znv,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 “length” “2”) (set_attr “cc” “set_zn”)])

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

(define_insn “neghi2_h8300h” [(set (match_operand:HI 0 “register_operand” “=r”) (neg:HI (match_operand:HI 1 “general_operand” “0”)))] “TARGET_H8300H || TARGET_H8300S” “neg %T0” [(set_attr “length” “2”) (set_attr “cc” “set_zn”)])

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

(define_insn “negsi2_h8300h” [(set (match_operand:SI 0 “register_operand” “=r”) (neg:SI (match_operand:SI 1 “general_operand” “0”)))] “TARGET_H8300H || TARGET_H8300S” “neg %S0” [(set_attr “length” “2”) (set_attr “cc” “set_zn”)])

;; ---------------------------------------------------------------------- ;; 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 “length” “2”) (set_attr “cc” “set_znv”)])

(define_insn “one_cmplhi2” [(set (match_operand:HI 0 “register_operand” “=r”) (not:HI (match_operand:HI 1 “general_operand” “0”)))] "" “* { if (TARGET_H8300) return "not %s0;not %t0"; else return "not %T0"; }” [(set_attr “cc” “clobber”) (set (attr “length”) (if_then_else (eq (symbol_ref “TARGET_H8300H || TARGET_H8300S”) (const_int 0)) (const_int 4) (const_int 2)))])

(define_insn “one_cmplsi2” [(set (match_operand:SI 0 “register_operand” “=r”) (not:SI (match_operand:SI 1 “general_operand” “0”)))] "" “* { if (TARGET_H8300) return "not %w0;not %x0;not %y0;not %z0"; else return "not %S0"; }” [(set_attr “cc” “clobber”) (set (attr “length”) (if_then_else (eq (symbol_ref “TARGET_H8300H || TARGET_H8300S”) (const_int 0)) (const_int 8) (const_int 2)))]) ;; ---------------------------------------------------------------------- ;; JUMP INSTRUCTIONS ;; ----------------------------------------------------------------------

;; Conditional jump instructions

(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 “branch_true” [(set (pc) (if_then_else (match_operator 1 “comparison_operator” [(cc0) (const_int 0)]) (label_ref (match_operand 0 "" "")) (pc)))] "" "* { if ((cc_status.flags & CC_OVERFLOW_UNUSABLE) != 0 && (GET_CODE (operands[1]) == GT || GET_CODE (operands[1]) == GE || GET_CODE (operands[1]) == LE || GET_CODE (operands[1]) == LT)) { cc_status.flags &= ~CC_OVERFLOW_UNUSABLE; return 0; }

if (get_attr_length (insn) == 2) return "b%j1 %l0"; else if (get_attr_length (insn) == 4) return "b%j1 %l0:16"; else return "b%k1 .Lh8BR%=;jmp @%l0\n.Lh8BR%=:"; }" [(set_attr “type” “branch”) (set_attr “cc” “none”)])

(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 ((cc_status.flags & CC_OVERFLOW_UNUSABLE) != 0 && (GET_CODE (operands[1]) == GT || GET_CODE (operands[1]) == GE || GET_CODE (operands[1]) == LE || GET_CODE (operands[1]) == LT)) { cc_status.flags &= ~CC_OVERFLOW_UNUSABLE; return 0; }

if (get_attr_length (insn) == 2) return "b%k1 %l0"; else if (get_attr_length (insn) == 4) return "b%k1 %l0:16"; else return "b%j1 .Lh8BR%=;jmp @%l0\n.Lh8BR%=:"; }" [(set_attr “type” “branch”) (set_attr “cc” “none”)])

;; Unconditional and other jump instructions.

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

;; 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” “r”)) (use (label_ref (match_operand 1 "" "")))] “TARGET_H8300” “jmp @%0” [(set_attr “cc” “none”) (set_attr “length” “2”)])

(define_insn “tablejump_h8300h” [(set (pc) (match_operand:SI 0 “register_operand” “r”)) (use (label_ref (match_operand 1 "" "")))] “TARGET_H8300H || TARGET_H8300S” “jmp @%0” [(set_attr “cc” “none”) (set_attr “length” “2”)])

;; This is a define expand, because pointers may be either 16 or 32 bits.

(define_expand “indirect_jump” [(set (pc) (match_operand 0 “jump_address_operand” ""))] "" "")

(define_insn “indirect_jump_h8300” [(set (pc) (match_operand:HI 0 “jump_address_operand” “Vr”))] “TARGET_H8300” “jmp @%0” [(set_attr “cc” “none”) (set_attr “length” “2”)])

(define_insn “indirect_jump_h8300h” [(set (pc) (match_operand:SI 0 “jump_address_operand” “Vr”))] “TARGET_H8300H || TARGET_H8300S” “jmp @%0” [(set_attr “cc” “none”) (set_attr “length” “2”)])

;; Call subroutine with no return value.

;; ??? Even though we use HImode here, this works for the 300h.

(define_insn “call” [(call (match_operand:QI 0 “call_insn_operand” “or”) (match_operand:HI 1 “general_operand” “g”))] "" “* { if (GET_CODE (XEXP (operands[0], 0)) == SYMBOL_REF && SYMBOL_REF_FLAG (XEXP (operands[0], 0))) return "jsr\t@%0:8"; else return "jsr\t%0"; }” [(set_attr “cc” “clobber”) (set (attr “length”) (if_then_else (match_operand:QI 0 “small_call_insn_operand” "") (const_int 4) (const_int 8)))])

;; 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 “call_insn_operand” “or”) (match_operand:HI 2 “general_operand” “g”)))] "" “* { if (GET_CODE (XEXP (operands[1], 0)) == SYMBOL_REF && SYMBOL_REF_FLAG (XEXP (operands[1], 0))) return "jsr\t@%1:8"; else return "jsr\t%1"; }” [(set_attr “cc” “clobber”) (set (attr “length”) (if_then_else (match_operand:QI 0 “small_call_insn_operand” "") (const_int 4) (const_int 8)))])

(define_insn “nop” [(const_int 0)] "" “nop” [(set_attr “cc” “none”) (set_attr “length” “2”)]) ;; ---------------------------------------------------------------------- ;; EXTEND INSTRUCTIONS ;; ----------------------------------------------------------------------

(define_expand “zero_extendqihi2” [(set (match_operand:HI 0 “register_operand” "") (zero_extend:HI (match_operand:QI 1 “general_operand_src” "")))] "" "")

(define_insn "" [(set (match_operand:HI 0 “register_operand” “=r,r”) (zero_extend:HI (match_operand:QI 1 “general_operand_src” “0,g>”)))] “TARGET_H8300” “@ mov.b #0,%t0 mov.b %R1,%s0;mov.b #0,%t0” [(set_attr “length” “2,10”) (set_attr “cc” “clobber,clobber”)])

(define_insn "" [(set (match_operand:HI 0 “register_operand” “=r,r”) (zero_extend:HI (match_operand:QI 1 “general_operand_src” “0,g>”)))] “TARGET_H8300H || TARGET_H8300S” “@ extu.w %T0 mov.b %R1,%s0;extu.w %T0” [(set_attr “length” “2,10”) (set_attr “cc” “set_znv,set_znv”)])

;; The compiler can synthesize a 300H variant of this which is ;; just as efficient as one that we'd create (define_insn “zero_extendqisi2” [(set (match_operand:SI 0 “register_operand” “=r,r”) (zero_extend:SI (match_operand:QI 1 “general_operand_src” “0,g>”)))] “TARGET_H8300” “@ mov.b #0,%x0;sub.w %e0,%e0 mov.b %R1,%w0;mov.b #0,%x0;sub.w %e0,%e0” [(set_attr “length” “4,6”) (set_attr “cc” “clobber,clobber”)])

(define_expand “zero_extendhisi2” [(set (match_operand:SI 0 “register_operand” "") (zero_extend:SI (match_operand:HI 1 “register_operand” "")))] "" "")

;; %e prints the high part of a CONST_INT, not the low part. Arggh. (define_insn "" [(set (match_operand:SI 0 “register_operand” “=r,r,r”) (zero_extend:SI (match_operand:HI 1 “general_operand_src” “0,i,g>”)))] “TARGET_H8300” “@ sub.w %e0,%e0 mov.w %f1,%f0;sub.w %e0,%e0 mov.w %e1,%f0;sub.w %e0,%e0” [(set_attr “length” “2,4,4”) (set_attr “cc” “clobber,clobber,clobber”)])

(define_insn "" [(set (match_operand:SI 0 “register_operand” “=r”) (zero_extend:SI (match_operand:HI 1 “register_operand” “0”)))] “TARGET_H8300H || TARGET_H8300S” “extu.l %S0” [(set_attr “length” “2”) (set_attr “cc” “set_znv”)])

(define_expand “extendqihi2” [(set (match_operand:HI 0 “register_operand” "") (sign_extend:HI (match_operand:QI 1 “register_operand” "")))] "" "")

(define_insn "" [(set (match_operand:HI 0 “register_operand” “=r,r”) (sign_extend:HI (match_operand:QI 1 “general_operand_src” “0,g>”)))] “TARGET_H8300” “@ bld #7,%s0;subx %t0,%t0 mov.b %R1,%s0;bld #7,%s0;subx %t0,%t0” [(set_attr “length” “4,6”) (set_attr “cc” “clobber,clobber”)])

(define_insn "" [(set (match_operand:HI 0 “register_operand” “=r”) (sign_extend:HI (match_operand:QI 1 “register_operand” “0”)))] “TARGET_H8300H || TARGET_H8300S” “exts.w %T0” [(set_attr “length” “2”) (set_attr “cc” “set_znv”)])

;; The compiler can synthesize a 300H variant of this which is ;; just as efficient as one that we'd create (define_insn “extendqisi2” [(set (match_operand:SI 0 “register_operand” “=r,r”) (sign_extend:SI (match_operand:QI 1 “general_operand_src” “0,g>”)))] “TARGET_H8300” “@ bld #7,%w0;subx %x0,%x0;subx %y0,%y0;subx %z0,%z0 mov.b %R1,%w0;bld #7,%w0;subx %x0,%x0;subx %y0,%y0;subx %z0,%z0” [(set_attr “length” “8,10”) (set_attr “cc” “clobber,clobber”)])

(define_expand “extendhisi2” [(set (match_operand:SI 0 “register_operand” "") (sign_extend:SI (match_operand:HI 1 “register_operand” "")))] "" "")

(define_insn "" [(set (match_operand:SI 0 “register_operand” “=r,r”) (sign_extend:SI (match_operand:HI 1 “general_operand_src” “0,g>”)))] “TARGET_H8300” “@ bld #7,%x0;subx %y0,%y0;subx %z0,%z0 mov.w %T1,%f0;bld #7,%x0;subx %y0,%y0;subx %z0,%z0” [(set_attr “length” “6,8”) (set_attr “cc” “clobber,clobber”)])

(define_insn "" [(set (match_operand:SI 0 “register_operand” “=r”) (sign_extend:SI (match_operand:HI 1 “register_operand” “0”)))] “TARGET_H8300H || TARGET_H8300S” “exts.l %S0” [(set_attr “length” “2”) (set_attr “cc” “set_znv”)]) ;; ---------------------------------------------------------------------- ;; 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” "")))] "" “if (expand_a_shift (QImode, ASHIFT, operands)) DONE;else FAIL;”)

(define_expand “ashrqi3” [(set (match_operand:QI 0 “register_operand” "") (ashiftrt:QI (match_operand:QI 1 “register_operand” "") (match_operand:QI 2 “nonmemory_operand” "")))] "" “if (expand_a_shift (QImode, ASHIFTRT, operands)) DONE;else FAIL;”)

(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 (expand_a_shift (QImode, LSHIFTRT, operands)) DONE;else FAIL;”)

(define_insn "" [(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” “KM,rn”)])) (clobber (match_scratch:QI 4 “=X,&r”))] "" “* return emit_a_shift (insn, operands);” [(set_attr “length” “20”) (set_attr “cc” “clobber”)])

;; HI BIT SHIFTS

(define_expand “ashlhi3” [(set (match_operand:HI 0 “register_operand” "") (ashift:HI (match_operand:HI 1 “nonmemory_operand” "") (match_operand:QI 2 “nonmemory_operand” "")))] "" “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” "") (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 “register_operand” "") (match_operand:QI 2 “nonmemory_operand” "")))] "" “if (expand_a_shift (HImode, ASHIFTRT, operands)) DONE;else FAIL;”)

(define_insn "" [(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” “KM,rn”)])) (clobber (match_scratch:QI 4 “=X,&r”))] "" “* return emit_a_shift (insn, operands);” [(set_attr “length” “20”) (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” "") (match_operand:QI 2 “nonmemory_operand” "")))] "" “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” "") (match_operand:QI 2 “nonmemory_operand” "")))] "" “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” "") (match_operand:QI 2 “nonmemory_operand” "")))] "" “if (expand_a_shift (SImode, ASHIFTRT, operands)) DONE;else FAIL;”)

(define_insn "" [(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” “K,rn”)])) (clobber (match_scratch:QI 4 “=X,&r”))] "" “* return emit_a_shift (insn, operands);” [(set_attr “length” “20”) (set_attr “cc” “clobber”)]) ;; ---------------------------------------------------------------------- ;; ROTATIONS ;; ----------------------------------------------------------------------

(define_expand “rotlqi3” [(set (match_operand:QI 0 “register_operand” "") (rotate:QI (match_operand:QI 1 “register_operand” "") (match_operand:QI 2 “nonmemory_operand” "")))] "" “if (expand_a_rotate (ROTATE, operands)) DONE;else FAIL;”)

(define_insn “*rotlqi3_1” [(set (match_operand:QI 0 “register_operand” “=r”) (rotate:QI (match_operand:QI 1 “register_operand” “0”) (match_operand:QI 2 “immediate_operand” "")))] "" “* return emit_a_rotate (ROTATE, operands);” [(set_attr “length” “20”) (set_attr “cc” “clobber”)])

(define_expand “rotlhi3” [(set (match_operand:HI 0 “register_operand” "") (rotate:HI (match_operand:HI 1 “register_operand” "") (match_operand:QI 2 “nonmemory_operand” "")))] "" “if (expand_a_rotate (ROTATE, operands)) DONE;else FAIL;”)

(define_insn “*rotlhi3_1” [(set (match_operand:HI 0 “register_operand” “=r”) (rotate:HI (match_operand:HI 1 “register_operand” “0”) (match_operand:QI 2 “immediate_operand” "")))] "" “* return emit_a_rotate (ROTATE, operands);” [(set_attr “length” “20”) (set_attr “cc” “clobber”)])

(define_expand “rotlsi3” [(set (match_operand:SI 0 “register_operand” "") (rotate:SI (match_operand:SI 1 “register_operand” "") (match_operand:QI 2 “nonmemory_operand” "")))] “TARGET_H8300H || TARGET_H8300S” “if (expand_a_rotate (ROTATE, operands)) DONE;else FAIL;”)

(define_insn “*rotlsi3_1” [(set (match_operand:SI 0 “register_operand” “=r”) (rotate:SI (match_operand:SI 1 “register_operand” “0”) (match_operand:QI 2 “immediate_operand” "")))] “TARGET_H8300H || TARGET_H8300S” “* return emit_a_rotate (ROTATE, operands);” [(set_attr “length” “20”) (set_attr “cc” “clobber”)]) ;; ----------------------------------------------------------------- ;; BIT FIELDS ;; ----------------------------------------------------------------- ;; The H8/300 has given 1/8th of its opcode space to bitfield ;; instructions so let's use them as well as we can.

;; You'll never believe all these patterns perform one basic action -- ;; load a bit from the source, optionally invert the bit, then store it ;; in the destination (which is known to be zero). ;; ;; Combine obviously need some work to better identify this situation and ;; canonicalize the form better.

;; ;; Normal loads with a 16bit destination. ;; ;; Yes, both cases are needed. ;; (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 2 “immediate_operand” “n”)))] "" “sub.w %0,%0;bld %Z2,%Y1;bst #0,%X0” [(set_attr “cc” “clobber”) (set_attr “length” “6”)])

(define_insn "" [(set (match_operand:HI 0 “register_operand” “=&r”) (subreg:HI (zero_extract:SI (match_operand:HI 1 “register_operand” “r”) (const_int 1) (match_operand:HI 2 “immediate_operand” “n”)) 2))] "" “sub.w %0,%0;bld %Z2,%Y1;bst #0,%X0” [(set_attr “cc” “clobber”) (set_attr “length” “6”)])

;; ;; Inverted loads with a 16bit destination. ;; ;; Yes, all four cases are needed. ;;

(define_insn "" [(set (match_operand:HI 0 “register_operand” “=&r”) (zero_extract:HI (xor:HI (match_operand:HI 1 “register_operand” “r”) (match_operand:HI 3 “p_operand” “P”)) (const_int 1) (match_operand:HI 2 “const_int_operand” “n”)))] “(1 << INTVAL (operands[2])) == INTVAL (operands[3])” “sub.w %0,%0;bild %Z2,%Y1;bst #0,%X0” [(set_attr “cc” “clobber”) (set_attr “length” “8”)])

(define_insn "" [(set (match_operand:HI 0 “register_operand” “=&r”) (and:HI (not:HI (lshiftrt:HI (match_operand:HI 1 “bit_operand” “Ur”) (match_operand:HI 2 “const_int_operand” “n”))) (const_int 1)))] "" “sub.w %0,%0;bild %Z2,%Y1;bst #0,%X0” [(set_attr “cc” “clobber”) (set_attr “length” “8”)])

(define_insn "" [(set (match_operand:HI 0 “register_operand” “=&r”) (and:HI (not:HI (subreg:HI (lshiftrt:SI (match_operand:SI 1 “register_operand” “Ur”) (match_operand:SI 2 “const_int_operand” “n”)) 2)) (const_int 1)))] “INTVAL (operands[2]) < 16” “sub.w %0,%0;bild %Z2,%Y1;bst #0,%X0” [(set_attr “cc” “clobber”) (set_attr “length” “8”)])

(define_insn "" [(set (match_operand:HI 0 “register_operand” “=&r”) (and:HI (not:HI (subreg:HI (lshiftrt:SI (match_operand:SI 1 “bit_operand” “Ur”) (match_operand:SI 2 “const_int_operand” “n”)) 0)) (const_int 1)))] “(TARGET_H8300H || TARGET_H8300S) && INTVAL (operands[2]) < 16” “sub.w %0,%0;bild %Z2,%Y1;bst #0,%X0” [(set_attr “cc” “clobber”) (set_attr “length” “8”)])

;; ;; Normal loads with a 32bit destination. ;; ;; Yes, all three cases are needed. ;; (define_insn "" [(set (match_operand:SI 0 “register_operand” “=&r”) (zero_extract:SI (match_operand:HI 1 “register_operand” “r”) (const_int 1) (match_operand:HI 2 “const_int_operand” “n”)))] "" “* return output_simode_bld (0, 0, operands);” [(set_attr “cc” “clobber”) (set (attr “length”) (if_then_else (eq (symbol_ref “TARGET_H8300H || TARGET_H8300S”) (const_int 0)) (const_int 10) (const_int 8)))])

(define_insn "" [(set (match_operand:SI 0 “register_operand” “=&r”) (and:SI (zero_extend:SI (lshiftrt:QI (match_operand:QI 1 “bit_operand” “Ur”) (match_operand:QI 2 “const_int_operand” “n”))) (const_int 1)))] "" “* return output_simode_bld (0, 0, operands);” [(set_attr “cc” “clobber”) (set (attr “length”) (if_then_else (eq (symbol_ref “TARGET_H8300H || TARGET_H8300S”) (const_int 0)) (const_int 10) (const_int 8)))])

(define_insn "" [(set (match_operand:SI 0 “register_operand” “=&r”) (and:SI (zero_extend:SI (lshiftrt:HI (match_operand:HI 1 “bit_operand” “Ur”) (match_operand:HI 2 “const_int_operand” “n”))) (const_int 1)))] "" “* return output_simode_bld (0, 0, operands);” [(set_attr “cc” “clobber”) (set (attr “length”) (if_then_else (eq (symbol_ref “TARGET_H8300H || TARGET_H8300S”) (const_int 0)) (const_int 10) (const_int 8)))])

;; ;; Inverted loads with a 32bit destination. ;; ;; Yes, all seven cases are needed. ;; (define_insn "" [(set (match_operand:SI 0 “register_operand” “=&r”) (and:SI (not:SI (zero_extend:SI (match_operand:HI 1 “register_operand” “r”))) (match_operand:SI 2 “p_operand” “P”)))] "" “* return output_simode_bld (1, 1, operands);” [(set_attr “cc” “clobber”) (set (attr “length”) (if_then_else (eq (symbol_ref “TARGET_H8300H || TARGET_H8300S”) (const_int 0)) (const_int 10) (const_int 8)))]) (define_insn "" [(set (match_operand:SI 0 “register_operand” “=&r”) (and:SI (not:SI (zero_extend:SI (lshiftrt:HI (match_operand:HI 1 “bit_operand” “Ur”) (match_operand:HI 2 “const_int_operand” “n”)))) (const_int 1)))] "" “* return output_simode_bld (1, 0, operands);” [(set_attr “cc” “clobber”) (set (attr “length”) (if_then_else (eq (symbol_ref “TARGET_H8300H || TARGET_H8300S”) (const_int 0)) (const_int 10) (const_int 8)))])

(define_insn "" [(set (match_operand:SI 0 “register_operand” “=&r”) (and:SI (not:SI (zero_extend:SI (match_operand:QI 1 “register_operand” “r”))) (match_operand:SI 2 “p_operand” “P”)))] "" “* return output_simode_bld (1, 1, operands);” [(set_attr “cc” “clobber”) (set (attr “length”) (if_then_else (eq (symbol_ref “TARGET_H8300H || TARGET_H8300S”) (const_int 0)) (const_int 10) (const_int 8)))]) (define_insn "" [(set (match_operand:SI 0 “register_operand” “=&r”) (and:SI (not:SI (zero_extend:SI (lshiftrt:QI (match_operand:QI 1 “bit_operand” “Ur”) (match_operand:QI 2 “const_int_operand” “n”)))) (const_int 1)))] "" “* return output_simode_bld (1, 0, operands);” [(set_attr “cc” “clobber”) (set (attr “length”) (if_then_else (eq (symbol_ref “TARGET_H8300H || TARGET_H8300S”) (const_int 0)) (const_int 10) (const_int 8)))])

(define_insn "" [(set (match_operand:SI 0 “register_operand” “=&r”) (and:SI (not:SI (subreg:SI (lshiftrt:HI (match_operand:HI 1 “bit_operand” “Ur”) (match_operand:HI 2 “const_int_operand” “n”)) 0)) (const_int 1)))] “1” “* return output_simode_bld (1, 0, operands);” [(set_attr “cc” “clobber”) (set (attr “length”) (if_then_else (eq (symbol_ref “TARGET_H8300H || TARGET_H8300S”) (const_int 0)) (const_int 10) (const_int 8)))])

(define_insn "" [(set (match_operand:SI 0 “register_operand” “=&r”) (and:SI (not:SI (subreg:SI (lshiftrt:QI (match_operand:QI 1 “bit_operand” “Ur”) (match_operand:QI 2 “const_int_operand” “n”)) 0)) (const_int 1)))] “1” “* return output_simode_bld (1, 0, operands);” [(set_attr “cc” “clobber”) (set (attr “length”) (if_then_else (eq (symbol_ref “TARGET_H8300H || TARGET_H8300S”) (const_int 0)) (const_int 10) (const_int 8)))])

(define_insn "" [(set (match_operand:SI 0 “register_operand” “=&r”) (zero_extract:SI (xor:HI (match_operand:HI 1 “register_operand” “r”) (match_operand:HI 3 “p_operand” “P”)) (const_int 1) (match_operand:HI 2 “const_int_operand” “n”)))] “(1 << INTVAL (operands[2])) == INTVAL (operands[3])” “sub.w %0,%0;bild %Z2,%Y1;bst #0,%X0” [(set_attr “cc” “clobber”) (set_attr “length” “8”)])

(define_expand “insv” [(set (zero_extract:HI (match_operand:HI 0 “general_operand” "") (match_operand:HI 1 “general_operand” "") (match_operand:HI 2 “general_operand” "")) (match_operand:HI 3 “general_operand” ""))] “TARGET_H8300” " { /* We only have single bit bitfield instructions. */ if (INTVAL (operands[1]) != 1) FAIL;

/* For now, we don't allow memory operands. */ if (GET_CODE (operands[0]) == MEM || GET_CODE (operands[3]) == MEM) FAIL; }")

(define_insn "" [(set (zero_extract:HI (match_operand:HI 0 “register_operand” “+r”) (const_int 1) (match_operand:HI 1 “immediate_operand” “n”)) (match_operand:HI 2 “register_operand” “r”))] "" “bld #0,%R2;bst %Z1,%Y0 ; i1” [(set_attr “cc” “clobber”) (set_attr “length” “4”)])

(define_expand “extzv” [(set (match_operand:HI 0 “register_operand” "") (zero_extract:HI (match_operand:HI 1 “bit_operand” "") (match_operand:HI 2 “general_operand” "") (match_operand:HI 3 “general_operand” "")))] “TARGET_H8300” " { /* We only have single bit bitfield instructions. */ if (INTVAL (operands[2]) != 1) FAIL;

/* For now, we don't allow memory operands. */ if (GET_CODE (operands[1]) == MEM) FAIL; }")

;; BAND, BOR, and BXOR patterns

(define_insn "" [(set (match_operand:HI 0 “bit_operand” “=Ur”) (match_operator:HI 4 “bit_operator” [(zero_extract:HI (match_operand:HI 1 “register_operand” “r”) (const_int 1) (match_operand:HI 2 “immediate_operand” “n”)) (match_operand:HI 3 “bit_operand” “0”)]))] "" “bld %Z2,%Y1;%b4 #0,%R0;bst #0,%R0; bl1” [(set_attr “cc” “clobber”) (set_attr “length” “6”) (set_attr “adjust_length” “no”)])

(define_insn "" [(set (match_operand:HI 0 “bit_operand” “=Ur”) (match_operator:HI 5 “bit_operator” [(zero_extract:HI (match_operand:HI 1 “register_operand” “r”) (const_int 1) (match_operand:HI 2 “immediate_operand” “n”)) (zero_extract:HI (match_operand:HI 3 “register_operand” “r”) (const_int 1) (match_operand:HI 4 “immediate_operand” “n”))]))] "" “bld %Z2,%Y1;%b5 %Z4,%Y3;bst #0,%R0; bl3” [(set_attr “cc” “clobber”) (set_attr “length” “6”) (set_attr “adjust_length” “no”)]) ;; ----------------------------------------------------------------- ;; COMBINE PATTERNS ;; -----------------------------------------------------------------

(define_insn "" [(set (match_operand:HI 0 “register_operand” “=r”) (ior:HI (zero_extend:HI (match_operand:QI 1 “register_operand” “r”)) (match_operand:HI 2 “register_operand” “0”)))] “REGNO (operands[0]) != REGNO (operands[1])” “or\t%X1,%s0” [(set_attr “cc” “clobber”) (set_attr “length” “2”)])

(define_insn "" [(set (match_operand:SI 0 “register_operand” “=r”) (ior:SI (zero_extend:SI (match_operand:HI 1 “register_operand” “r”)) (match_operand:SI 2 “register_operand” “0”)))] “(TARGET_H8300H || TARGET_H8300S) && (REGNO (operands[0]) != REGNO (operands[1]))” “or.w\t%T1,%f0” [(set_attr “cc” “clobber”) (set_attr “length” “2”)])

(define_insn "" [(set (match_operand:SI 0 “register_operand” “=r”) (ior:SI (zero_extend:SI (match_operand:QI 1 “register_operand” “r”)) (match_operand:SI 2 “register_operand” “0”)))] “REGNO (operands[0]) != REGNO (operands[1])” “or\t%X1,%s0” [(set_attr “cc” “clobber”) (set_attr “length” “2”)])

(define_insn "" [(set (match_operand:HI 0 “register_operand” “=r”) (xor:HI (zero_extend:HI (match_operand:QI 1 “register_operand” “r”)) (match_operand:HI 2 “register_operand” “0”)))] “REGNO (operands[0]) != REGNO (operands[1])” “xor\t%X1,%s0” [(set_attr “cc” “clobber”) (set_attr “length” “2”)])

(define_insn "" [(set (match_operand:SI 0 “register_operand” “=r”) (xor:SI (zero_extend:SI (match_operand:HI 1 “register_operand” “r”)) (match_operand:SI 2 “register_operand” “0”)))] “(TARGET_H8300H || TARGET_H8300S) && (REGNO (operands[0]) != REGNO (operands[1]))” “xor.w\t%T1,%f0” [(set_attr “cc” “clobber”) (set_attr “length” “2”)])

(define_insn "" [(set (match_operand:SI 0 “register_operand” “=r”) (xor:SI (zero_extend:SI (match_operand:QI 1 “register_operand” “r”)) (match_operand:SI 2 “register_operand” “0”)))] “REGNO (operands[0]) != REGNO (operands[1])” “xor\t%X1,%s0” [(set_attr “cc” “clobber”) (set_attr “length” “2”)])

(define_insn "" [(set (match_operand:HI 0 “register_operand” “=r”) (ior:HI (zero_extend:HI (match_operand:QI 1 “register_operand” “0”)) (ashift:HI (match_operand:HI 2 “register_operand” “r”) (const_int 8))))] “REGNO (operands[0]) != REGNO (operands[2])” “mov.b\t%s2,%t0” [(set_attr “cc” “clobber”) (set_attr “length” “2”)])

(define_insn "" [(set (match_operand:SI 0 “register_operand” “=r”) (ior:SI (zero_extend:SI (match_operand:HI 1 “register_operand” “0”)) (ashift:SI (match_operand:SI 2 “register_operand” “r”) (const_int 16))))] “(TARGET_H8300H || TARGET_H8300S) && (REGNO (operands[0]) != REGNO (operands[2]))” “mov.w\t%f2,%e0” [(set_attr “cc” “clobber”) (set_attr “length” “2”)])