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