From f82eca4d69a0de0717974aa307d57f9afa369410 Mon Sep 17 00:00:00 2001 From: Steve Chamberlain Date: Thu, 4 Mar 1993 18:02:42 +0000 Subject: [PATCH] New File. From-SVN: r3630 --- gcc/config/h8300/h8300.md | 1322 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 1322 insertions(+) create mode 100644 gcc/config/h8300/h8300.md diff --git a/gcc/config/h8300/h8300.md b/gcc/config/h8300/h8300.md new file mode 100644 index 0000000..55b4a5e --- /dev/null +++ b/gcc/config/h8300/h8300.md @@ -0,0 +1,1322 @@ +;;- 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")]) -- 2.7.4