8sa1-gcc/gcc/config/sh/sh.md
Torbjorn Granlund 58371476ee (subdi3): Delete % from constraints.
From-SVN: r8402
1994-11-07 22:52:31 +00:00

54 KiB
Raw Blame History

;;- Machine description the Hitachi SH ;; Copyright (C) 1993 Free Software Foundation, Inc. ;; Contributed by Steve Chamberlain (sac@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, 675 Mass Ave, Cambridge, MA 02139, USA.

;; Special constraints for SH machine description: ;; ;; t -- T ;; x -- mac ;; l -- pr ;; z -- r0 ;; ;; Special formats used for outputting SH instructions: ;; ;; %. -- print a .s if insn needs delay slot ;; %* -- print a local label ;; %^ -- increment the local label number ;; %# -- output a nop if there is nothing to put in the delay slot ;; %R -- print the next register or memory location along, ie the lsw in ;; a double word value ;; %O -- print a constant without the # ;; %M -- print a constant as its negative ;; ;; ;; Special predicates: ;; ;; arith_operand -- operand is valid source for arithmetic op ;; arith_reg_operand -- operand is valid register for arithmetic op ;; byte_index_operand -- operand is ok as an index in a mov.b ;; general_movdst_operand -- operand is valid move destination ;; general_movsrc_operand -- operand is valid move source ;; logical_operand -- operand is valid source for logical op ;; pop_operand -- operand is a pop from the stack ;; system_reg_operand -- operand is MACL, MACH, or PR ;; ------------------------------------------------------------------------- ;; Attributes ;; -------------------------------------------------------------------------

; Target CPU.

(define_attr "cpu" "sh0,sh1,sh2,sh3" (const (symbol_ref "sh_cpu")))

(define_attr "interrupt_function" "no,yes" (const (symbol_ref "pragma_interrupt"))) ;; ;; cbranch conditional branch instructions ;; jump unconditional jumps ;; arith ordinary arithmetic ;; load from memory ;; store to memory ;; move register to register ;; smpy single precision integer multiply ;; dmpy double precision integer multiply ;; return rts ;; pload load of pr reg (can't be put into delay slot of rts) ;; pcloadsi pc relative load of SI value ;; pcloadhi pc relative load of HI value ;; rte return from exception ;; sfunc special function call with known used registers

(define_attr "type" "cbranch,jump,arith,other,load,store,move,smpy,dmpy,return,pload,pcloadsi,pcloadhi,rte,sfunc" (const_string "other"))

; If a conditional branch destination is within -120..120 bytes away ; from the instruction it can be 2 bytes long. Something in the ; range -4090..4090 bytes can be 6 bytes long, all other conditional ; branches are 8 bytes long.

; An unconditional jump which can reach forward or back 4k can be ; 6 bytes long (including the delay slot). If it is too big, it ; must be 10 bytes long.

; If a pcrel instruction is within 500 bytes of the constant, then the insn is ; 2 bytes long, otherwise 12 bytes ; All other instructions are two bytes long by default.

(define_attr "length" "" (cond [(eq_attr "type" "cbranch") (if_then_else (and (ge (minus (pc) (match_dup 0)) (const_int -122)) (le (minus (pc) (match_dup 0)) (const_int 122))) (const_int 2) (if_then_else (and (ge (minus (pc) (match_dup 0)) (const_int -4090)) (le (minus (pc) (match_dup 0)) (const_int 4090))) (const_int 6) (const_int 16)))

 (eq_attr "type" "jump")
 (if_then_else (and (ge (minus (pc) (match_dup 0))
			(const_int -4090))
		    (le (minus (pc) (match_dup 0))
			(const_int 4090)))
	       (const_int 4)
	       (const_int 10))
 (eq_attr "type" "pcloadsi")
 (if_then_else (gt (pc) (minus (match_dup 0) (const_int 1000)))
	       (const_int 2)
	       (const_int 12))
 (eq_attr "type" "pcloadhi")
 (if_then_else (gt (pc) (minus (match_dup 0) (const_int 500)))
	       (const_int 2)
	       (const_int 12))

 ] (const_int 2)))

;; (define_function_unit {name} {num-units} {n-users} {test} ;; {ready-delay} {issue-delay} [{conflict-list}])

(define_function_unit "memory" 1 0 (eq_attr "type" "load,pcloadsi,pcloadhi") 2 0) (define_function_unit "mpy" 1 0 (eq_attr "type" "smpy") 3 0) (define_function_unit "mpy" 1 0 (eq_attr "type" "dmpy") 5 0)

(define_attr "needs_delay_slot" "yes,no" (cond [(eq_attr "type" "jump") (const_string "yes") (eq_attr "type" "return") (const_string "yes")] (const_string "no")))

(define_delay (eq_attr "needs_delay_slot" "yes") [(eq_attr "in_delay_slot" "yes") (nil) (nil)])

(define_delay (eq_attr "type" "return") [(and (eq_attr "in_delay_slot" "yes") (ior (eq_attr "interrupt_function" "no") (eq_attr "hit_stack" "no"))) (nil) (nil)])

(define_attr "hit_stack" "yes,no" (const_string "no"))

(define_delay (and (eq_attr "type" "cbranch") (eq_attr "cpu" "sh2")) [(eq_attr "in_delay_slot" "yes") (nil) (nil)])

(define_attr "in_delay_slot" "maybe,yes,no" (cond [(eq_attr "type" "cbranch") (const_string "no") (eq_attr "type" "jump") (const_string "no") (eq_attr "type" "pload") (const_string "no") (eq_attr "type" "pcloadsi") (const_string "no") (eq_attr "type" "pcloadhi") (const_string "no") (eq_attr "type" "return") (const_string "no") (eq_attr "length" "2") (const_string "yes") (eq_attr "length" "4,6,8,10,12") (const_string "no") ] (const_string "yes")))

;; ------------------------------------------------------------------------- ;; SImode signed integer comparisons ;; -------------------------------------------------------------------------

(define_insn "" [(set (match_operand:SI 0 "arith_reg_operand" "=r") (eq:SI (reg:SI 18) (const_int 1)))] "" "movt %0 !movt1")

(define_insn "" [(set (reg:SI 18) (gt:SI (match_operand:SI 0 "arith_reg_operand" "r") (const_int 0)))] "" "cmp/pl %0")

(define_insn "" [(set (reg:SI 18) (ge:SI (match_operand:SI 0 "arith_reg_operand" "r") (const_int 0)))] "" "cmp/pz %0")

(define_insn "cmpeq_0" [(set (reg:SI 18) (eq:SI (match_operand:SI 0 "arith_reg_operand" "r") (const_int 0)))] "" "tst %0,%0 ! t0")

(define_insn "cmpeqsi_t" [(set (reg:SI 18) (eq:SI (match_operand:SI 0 "arith_operand" "r,N,z,r") (match_operand:SI 1 "arith_operand" "N,r,rI,r")))] "" "@ tst %0,%0 !t1 tst %1,%1 !t2 cmp/eq %1,%0 cmp/eq %1,%0")

(define_insn "cmpgtsi_t" [(set (reg:SI 18) (gt:SI (match_operand:SI 0 "arith_reg_operand" "r,r") (match_operand:SI 1 "arith_operand" "N,r")))] "" "@ cmp/pl %0 cmp/gt %1,%0")

(define_insn "cmpgesi_t" [(set (reg:SI 18) (ge:SI (match_operand:SI 0 "arith_reg_operand" "r,r") (match_operand:SI 1 "arith_operand" "N,r")))] "" "@ cmp/pz %0 cmp/ge %1,%0")

;; ------------------------------------------------------------------------- ;; SImode unsigned integer comparisons ;; -------------------------------------------------------------------------

(define_insn "cmpgeusi_t" [(set (reg:SI 18) (geu:SI (match_operand:SI 0 "arith_reg_operand" "r,r") (match_operand:SI 1 "arith_operand" "N,r")))] "" "@ cmp/pz %1 cmp/hs %1,%0")

(define_insn "cmpgtusi_t" [(set (reg:SI 18) (gtu:SI (match_operand:SI 0 "arith_operand" "r,r") (match_operand:SI 1 "arith_operand" "N,r")))] "" "@ cmp/pl %1 cmp/hi %1,%0")

;; We save the compare operands in the cmpxx patterns and use them when ;; we generate the branch.

(define_expand "cmpsi" [(set (reg:SI 18) (compare (match_operand:SI 0 "arith_operand" "") (match_operand:SI 1 "arith_operand" "")))] "" " { sh_compare_op0 = operands[0]; sh_compare_op1 = operands[1]; DONE; }")

;; ------------------------------------------------------------------------- ;; Addition instructions ;; -------------------------------------------------------------------------

;; this should be a define split.

(define_insn "adddi3" [(set (match_operand:DI 0 "register_operand" "=r") (plus:DI (match_operand:DI 1 "register_operand" "%0") (match_operand:DI 2 "register_operand" "r"))) (clobber (reg:SI 18))] "" "clrt;addc %R2,%R0;addc %2,%0" [(set_attr "length" "6")])

(define_insn "addsi3_real" [(set (match_operand:SI 0 "arith_reg_operand" "=r") (plus:SI (match_operand:SI 1 "arith_reg_operand" "%0") (match_operand:SI 2 "arith_operand" "rI")))] "" "add %2,%0" [(set_attr "length" "2") (set_attr "type" "arith")])

(define_expand "addsi3" [(set (match_operand:SI 0 "arith_reg_operand" "=r") (plus:SI (match_operand:SI 1 "arith_operand" "%0") (match_operand:SI 2 "arith_operand" "rI")))] "" "")

;; ------------------------------------------------------------------------- ;; Subtraction instructions ;; -------------------------------------------------------------------------

(define_insn "subdi3" [(set (match_operand:DI 0 "register_operand" "=r") (minus:DI (match_operand:DI 1 "register_operand" "0") (match_operand:DI 2 "register_operand" "r"))) (clobber (reg:SI 18))] "" "clrt;subc %R2,%R0;subc %2,%0" [(set_attr "length" "6")])

(define_insn "subsi3" [(set (match_operand:SI 0 "arith_reg_operand" "=r") (minus:SI (match_operand:SI 1 "arith_reg_operand" "0") (match_operand:SI 2 "arith_operand" "r")))] "" "sub %2,%0" [(set_attr "type" "arith")])

;; ------------------------------------------------------------------------- ;; Division instructions ;; -------------------------------------------------------------------------

;; we take advantage of the library routines which don't clobber as many ;; registers as a normal function call would.

(define_insn "" [(set (reg:SI 0) (udiv:SI (reg:SI 4) (reg:SI 5))) (clobber (reg:SI 18)) (clobber (reg:SI 17)) (clobber (reg:SI 6)) (clobber (reg:SI 4)) (use (match_operand:SI 0 "register_operand" "r"))] "" "jsr @%0%#" [(set_attr "type" "sfunc") (set_attr "length" "4") (set_attr "needs_delay_slot" "yes")])

(define_expand "udivsi3" [(set (reg:SI 4) (match_operand:SI 1 "general_operand" "g")) (set (reg:SI 5) (match_operand:SI 2 "general_operand" "g")) (set (match_dup 3) (symbol_ref:SI "__udivsi3")) (parallel[(set (reg:SI 0) (udiv:SI (reg:SI 4) (reg:SI 5))) (clobber (reg:SI 18)) (clobber (reg:SI 17)) (clobber (reg:SI 6)) (clobber (reg:SI 4)) (use (match_dup 3))]) (set (match_operand:SI 0 "general_operand" "=g") (reg:SI 0))] "" "operands[3] = gen_reg_rtx(SImode);")

(define_insn "" [(set (reg:SI 0) (div:SI (reg:SI 4) (reg:SI 5))) (clobber (reg:SI 18)) (clobber (reg:SI 17)) (clobber (reg:SI 1)) (clobber (reg:SI 2)) (clobber (reg:SI 3)) (use (match_operand:SI 0 "register_operand" "r"))] "" "jsr @%0%#" [(set_attr "type" "sfunc") (set_attr "length" "4") (set_attr "needs_delay_slot" "yes")])

(define_expand "divsi3" [(set (reg:SI 4) (match_operand:SI 1 "general_operand" "g")) (set (reg:SI 5) (match_operand:SI 2 "general_operand" "g")) (set (match_dup 3) (symbol_ref:SI "__sdivsi3")) (parallel[(set (reg:SI 0) (div:SI (reg:SI 4) (reg:SI 5))) (clobber (reg:SI 18)) (clobber (reg:SI 17)) (clobber (reg:SI 1)) (clobber (reg:SI 2)) (clobber (reg:SI 3)) (use (match_dup 3))]) (set (match_operand:SI 0 "general_operand" "=g") (reg:SI 0))] "" "operands[3] = gen_reg_rtx(SImode);")

;; ------------------------------------------------------------------------- ;; Multiplication instructions ;; -------------------------------------------------------------------------

(define_insn "" [(set (reg:SI 21) (mult:SI (zero_extend:SI (match_operand:HI 1 "arith_reg_operand" "r")) (zero_extend:SI (match_operand:HI 2 "arith_reg_operand" "r"))))] "" "mulu %2,%1" [(set_attr "type" "smpy")])

(define_insn "" [(set (reg:SI 21) (mult:SI (sign_extend:SI (match_operand:HI 1 "arith_reg_operand" "r")) (sign_extend:SI (match_operand:HI 2 "arith_reg_operand" "r"))))] "" "muls %2,%1" [(set_attr "type" "smpy")])

(define_expand "mulhisi3" [(set (reg:SI 21) (mult:SI (sign_extend:SI (match_operand:HI 1 "mac_operand" "r")) (sign_extend:SI (match_operand:HI 2 "mac_operand" "r")))) (set (match_operand:SI 0 "arith_reg_operand" "=r") (reg:SI 21))] "" "")

(define_expand "umulhisi3" [(set (reg:SI 21) (mult:SI (zero_extend:SI (match_operand:HI 1 "arith_reg_operand" "r")) (zero_extend:SI (match_operand:HI 2 "arith_reg_operand" "r")))) (set (match_operand:SI 0 "arith_reg_operand" "=r") (reg:SI 21))] "" "")

;; mulsi3 on the SH2 can be done in one instruction, on the SH1 we generate ;; a call to a routine which clobbers known registers.

(define_insn "" [(set (reg:SI 0) (mult:SI (reg:SI 4) (reg:SI 5))) (clobber (reg:SI 21)) (clobber (reg:SI 18)) (clobber (reg:SI 17)) (clobber (reg:SI 3)) (clobber (reg:SI 2)) (clobber (reg:SI 1)) (use (match_operand:SI 0 "register_operand" "r"))] "" "jsr @%0%#" [(set_attr "type" "sfunc") (set_attr "length" "4") (set_attr "needs_delay_slot" "yes")])

(define_expand "mulsi3_call" [(set (reg:SI 4) (match_operand:SI 1 "general_operand" "g")) (set (reg:SI 5) (match_operand:SI 2 "general_operand" "g")) (set (match_dup 3) (symbol_ref:SI "__mulsi3")) (parallel[(set (reg:SI 0) (mult:SI (reg:SI 4) (reg:SI 5))) (clobber (reg:SI 21)) (clobber (reg:SI 18)) (clobber (reg:SI 17)) (clobber (reg:SI 3)) (clobber (reg:SI 2)) (clobber (reg:SI 1)) (use (match_dup 3))]) (set (match_operand:SI 0 "general_operand" "=g") (reg:SI 0))] "" "operands[3] = gen_reg_rtx(SImode);")

(define_insn "mul_l" [(set (reg:SI 21) (mult:SI (match_operand:SI 0 "arith_reg_operand" "r") (match_operand:SI 1 "arith_reg_operand" "r")))] "TARGET_SH2" "mul.l %1,%0" [(set_attr "type" "smpy")])

(define_expand "mulsi3" [(set (reg:SI 21) (mult:SI (match_operand:SI 1 "arith_reg_operand" "r") (match_operand:SI 2 "arith_reg_operand" "r"))) (set (match_operand:SI 0 "arith_reg_operand" "=r") (reg:SI 21))] "TARGET_SH2" "")

(define_insn "" [(set (reg:DI 20) (mult:DI (sign_extend:DI (match_operand:SI 1 "arith_reg_operand" "r")) (sign_extend:DI (match_operand:SI 2 "arith_reg_operand" "r"))))] "TARGET_SH2" "dmuls.l %2,%1" [(set_attr "type" "dmpy")])

(define_expand "mulsidi3" [(set (reg:DI 20) (mult:DI (sign_extend:DI (match_operand:SI 1 "arith_reg_operand" "r")) (sign_extend:DI (match_operand:SI 2 "arith_reg_operand" "r")))) (set (match_operand:DI 0 "arith_reg_operand" "=r") (reg:DI 20))] "TARGET_SH2" "")

(define_insn "" [(set (reg:DI 20) (mult:DI (zero_extend:DI (match_operand:SI 1 "arith_reg_operand" "r")) (zero_extend:DI (match_operand:SI 2 "arith_reg_operand" "r"))))] "TARGET_SH2" "dmulu.l %2,%1" [(set_attr "type" "dmpy")])

(define_expand "umulsidi3" [(set (reg:DI 20) (mult:DI (zero_extend:DI (match_operand:SI 1 "arith_reg_operand" "r")) (zero_extend:DI (match_operand:SI 2 "arith_reg_operand" "r")))) (set (match_operand:DI 0 "arith_reg_operand" "=r") (reg:DI 20))] "TARGET_SH2" "")

;; ------------------------------------------------------------------------- ;; Logical operations ;; -------------------------------------------------------------------------

(define_insn "and_ffff" [(set (match_operand:SI 0 "arith_reg_operand" "=r") (and:SI (match_operand:SI 1 "arith_reg_operand" "r") (const_int 65535)))] "" "extu.w %1,%0" [(set_attr "type" "arith")])

(define_insn "and_ff" [(set (match_operand:SI 0 "arith_reg_operand" "=r") (and:SI (match_operand:SI 1 "arith_reg_operand" "r") (const_int 255)))] "" "extu.b %1,%0" [(set_attr "type" "arith")])

(define_insn "" [(set (match_operand:SI 0 "arith_reg_operand" "=r,z") (and:SI (match_operand:SI 1 "arith_reg_operand" "%0,0") (match_operand:SI 2 "logical_operand" "r,L")))] "" "and %2,%0" [(set_attr "type" "arith")])

(define_expand "andsi3" [(set (match_operand:SI 0 "arith_reg_operand" "") (and:SI (match_operand:SI 1 "arith_reg_operand" "") (match_operand:SI 2 "logical_operand" "")))] "" "")

(define_insn "iorsi3" [(set (match_operand:SI 0 "arith_reg_operand" "=r,z") (ior:SI (match_operand:SI 1 "arith_reg_operand" "%0,0") (match_operand:SI 2 "logical_operand" "r,L")))] "" "or %2,%0")

(define_insn "xorsi3" [(set (match_operand:SI 0 "arith_reg_operand" "=z,r") (xor:SI (match_operand:SI 1 "arith_reg_operand" "%0,0") (match_operand:SI 2 "logical_operand" "L,r")))] "" "xor %2,%0" [(set_attr "type" "arith")])

;; ------------------------------------------------------------------------- ;; Shifts and rotates ;; -------------------------------------------------------------------------

(define_insn "rotlsi3_k" [(set (match_operand:SI 0 "arith_reg_operand" "=r") (rotate:SI (match_operand:SI 1 "arith_reg_operand" "0") (const_int 1))) (clobber (reg:SI 18))] "" "rotl %0")

(define_expand "rotlsi3" [(parallel[(set (match_operand:SI 0 "arith_reg_operand" "") (rotate:SI (match_operand:SI 1 "arith_reg_operand" "") (match_operand:SI 2 "immediate_operand" ""))) (clobber (reg:SI 18))])] "" "{ if (GET_CODE(operands[2]) != CONST_INT || INTVAL(operands[2]) != 1) FAIL;}")

(define_insn "rotrsi3_k" [(set (match_operand:SI 0 "arith_reg_operand" "=r") (rotatert:SI (match_operand:SI 1 "arith_reg_operand" "0") (const_int 1))) (clobber (reg:SI 18))] "" "rotr %0")

(define_expand "rotrsi3" [(parallel[(set (match_operand:SI 0 "arith_reg_operand" "") (rotatert:SI (match_operand:SI 1 "arith_reg_operand" "") (match_operand:SI 2 "immediate_operand" ""))) (clobber (reg:SI 18))])] "" "{ if (GET_CODE(operands[2]) != CONST_INT || INTVAL(operands[2]) != 1) FAIL;}")

;; ;; shift left

(define_insn "ashlsi3_k" [(set (match_operand:SI 0 "arith_reg_operand" "=r,r") (ashift:SI (match_operand:SI 1 "arith_reg_operand" "0,0") (match_operand:SI 2 "immediate_operand" "M,K"))) (clobber (reg:SI 18))] "CONST_OK_FOR_K (INTVAL (operands[2]))" "@ shll %0 shll%O2 %0")

; seperate pattern for shifts by any N. Look at pnum_clobbers ; to see if this is being recognised inside combine. If so, dont ; match, since combine will try and merge shifts, which will break ; scheduling

(define_insn "ashlsi3_n" [(set (match_operand:SI 0 "arith_reg_operand" "=r") (ashift:SI (match_operand:SI 1 "arith_reg_operand" "0") (match_operand:SI 2 "immediate_operand" "n"))) (clobber (reg:SI 18))] "fake_shift()" "*return output_shift("shll", operands[0], operands[2], ASHIFT);" [(set_attr "length" "12") (set_attr "in_delay_slot" "no") (set_attr "type" "arith")])

(define_expand "ashlsi3" [(parallel[(set (match_operand:SI 0 "arith_reg_operand" "") (ashift:SI (match_operand:SI 1 "arith_reg_operand" "") (match_operand:SI 2 "immediate_operand" ""))) (clobber (reg:SI 18))])] "" "if (gen_shifty_op (ASHIFT, operands)) DONE; else FAIL;")

; ; arithmetic shift right ;

(define_insn "ashrsi3_k" [(set (match_operand:SI 0 "arith_reg_operand" "=r") (ashiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0") (match_operand:SI 2 "immediate_operand" "M"))) (clobber (reg:SI 18))] "INTVAL(operands[2]) == 1" "shar %0" [(set_attr "type" "arith")])

(define_insn "ashrsi3_16" [(set (match_operand:SI 0 "arith_reg_operand" "=r") (ashiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0") (match_operand:SI 2 "immediate_operand" "i"))) (clobber (reg:SI 18))] "INTVAL(operands[2]) == 16" "shlr16 %0;exts.w %0,%0" [(set_attr "type" "arith") (set_attr "length" "4")])

; an arithmetic shift right by 16 is better as a logical shift and a ; sign extend

;(define_split ; [(set (match_operand:SI 0 "arith_reg_operand" "=r") ; (ashiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0") ; (const_int 16))) ; (clobber (reg:SI 18))] ; "" ; [(set (match_dup 3) (match_dup 0)) ; (set (match_dup 3) (lshiftrt:SI (match_dup 3) (const_int 16))) ; (set (match_dup 0) (sign_extend:SI (subreg:HI (match_dup 3) 0)))] ; "operands[3] = gen_reg_rtx (SImode);")

(define_insn "ashrsi3_n" [(set (reg:SI 4) (ashiftrt:SI (reg:SI 4) (match_operand:SI 0 "immediate_operand" "i"))) (clobber (reg:SI 18)) (clobber (reg:SI 17)) (use (match_operand:SI 1 "arith_reg_operand" "r"))] "" "jsr @%1%#" [(set_attr "type" "sfunc") (set_attr "in_delay_slot" "no") (set_attr "length" "4") (set_attr "needs_delay_slot" "yes")])

(define_expand "ashrsi3" [(parallel[(set (match_operand:SI 0 "arith_reg_operand" "=r") (ashiftrt:SI (match_operand:SI 1 "arith_reg_operand" "r") (match_operand:SI 2 "nonmemory_operand" "M"))) (clobber (reg:SI 18))])] "" "if (gen_shifty_op (ASHIFTRT, operands)) DONE; else FAIL;")

; logical shift right ;

(define_insn "lshrsi3_k" [(set (match_operand:SI 0 "arith_reg_operand" "=r,r") (lshiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0,0") (match_operand:SI 2 "immediate_operand" "M,K"))) (clobber (reg:SI 18))] "CONST_OK_FOR_K (INTVAL (operands[2]))" "@ shlr %0 shlr%O2 %0")

; seperate pattern for shifts by any N.

(define_insn "lshrsi3_n" [(set (match_operand:SI 0 "arith_reg_operand" "=r") (lshiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0") (match_operand:SI 2 "immediate_operand" "n"))) (clobber (reg:SI 18))] "fake_shift()" "* return output_shift ("shlr", operands[0], operands[2], LSHIFTRT);" [(set_attr "length" "12") (set_attr "in_delay_slot" "no") (set_attr "type" "arith")])

(define_expand "lshrsi3" [(parallel[(set (match_operand:SI 0 "arith_reg_operand" "") (lshiftrt:SI (match_operand:SI 1 "arith_reg_operand" "") (match_operand:SI 2 "immediate_operand" ""))) (clobber (reg:SI 18))])] "" "if (gen_shifty_op (LSHIFTRT, operands)) DONE; else FAIL;")

(define_insn "ashldi3_k" [(set (match_operand:DI 0 "arith_reg_operand" "=r") (ashift:DI (match_operand:DI 1 "arith_reg_operand" "0") (const_int 1))) (clobber (reg:SI 18))] "" "shll %R0;rotcl %0" [(set_attr "length" "4")])

(define_expand "ashldi3" [(parallel[(set (match_operand:DI 0 "arith_reg_operand" "") (ashift:DI (match_operand:DI 1 "arith_reg_operand" "") (match_operand:DI 2 "immediate_operand" ""))) (clobber (reg:SI 18))])]

"" "{ if (GET_CODE (operands[2]) != CONST_INT || INTVAL (operands[2]) != 1) FAIL;} ")

(define_insn "lshrdi3_k" [(set (match_operand:DI 0 "arith_reg_operand" "=r") (lshiftrt:DI (match_operand:DI 1 "arith_reg_operand" "0") (const_int 1))) (clobber (reg:SI 18))] "" "shlr %0;rotcr %R0" [(set_attr "length" "4")])

(define_expand "lshrdi3" [(parallel[(set (match_operand:DI 0 "arith_reg_operand" "") (lshiftrt:DI (match_operand:DI 1 "arith_reg_operand" "") (match_operand:DI 2 "immediate_operand" ""))) (clobber (reg:SI 18))])] "" "{ if (GET_CODE (operands[2]) != CONST_INT || INTVAL (operands[2]) != 1) FAIL;} ")

(define_insn "ashrdi3_k" [(set (match_operand:DI 0 "arith_reg_operand" "=r") (ashiftrt:DI (match_operand:DI 1 "arith_reg_operand" "0") (const_int 1))) (clobber (reg:SI 18))] "" "shar %0;rotcr %R0" [(set_attr "length" "4")])

(define_expand "ashrdi3" [(parallel[(set (match_operand:DI 0 "arith_reg_operand" "") (ashiftrt:DI (match_operand:DI 1 "arith_reg_operand" "") (match_operand:DI 2 "immediate_operand" ""))) (clobber (reg:SI 18))])] "" "{ if (GET_CODE (operands[2]) != CONST_INT || INTVAL (operands[2]) != 1) FAIL; } ")

;; ------------------------------------------------------------------------- ;; Unary arithmetic ;; -------------------------------------------------------------------------

(define_insn "negc" [(set (match_operand:SI 0 "arith_reg_operand" "=r") (neg:SI (plus:SI (reg:SI 18) (match_operand:SI 1 "arith_reg_operand" "r"))))] "" "negc %1,%0" [(set_attr "length" "2") (set_attr "type" "arith")])

(define_expand "negdi2" [(set (match_operand:DI 0 "arith_reg_operand" "=r") (neg:DI (match_operand:DI 1 "arith_reg_operand" "r"))) (clobber (reg:SI 18))] "" "{ rtx low_src = operand_subword (operands[1], 1, 0, DImode); rtx high_src = operand_subword (operands[1], 0, 0, DImode);

rtx low_dst = operand_subword (operands[0], 1, 1, DImode); rtx high_dst = operand_subword (operands[0], 0, 1, DImode);

emit_insn (gen_clrt ()); emit_insn (gen_negc (low_dst, low_src)); emit_insn (gen_negc (high_dst, high_src)); DONE; } ")

(define_insn "negsi2" [(set (match_operand:SI 0 "arith_reg_operand" "=r") (neg:SI (match_operand:SI 1 "arith_reg_operand" "r")))] "" "neg %1,%0" [(set_attr "type" "arith")])

(define_insn "one_cmplsi2" [(set (match_operand:SI 0 "arith_reg_operand" "=r") (not:SI (match_operand:SI 1 "arith_reg_operand" "r")))] "" "not %1,%0" [(set_attr "type" "arith")])

;; ------------------------------------------------------------------------- ;; Zero extension instructions ;; -------------------------------------------------------------------------

(define_insn "zero_extendhisi2" [(set (match_operand:SI 0 "arith_reg_operand" "=r") (zero_extend:SI (match_operand:HI 1 "arith_reg_operand" "r")))] "" "extu.w %1,%0" [(set_attr "type" "arith")])

(define_insn "zero_extendqisi2" [(set (match_operand:SI 0 "arith_reg_operand" "=r") (zero_extend:SI (match_operand:QI 1 "arith_reg_operand" "r")))] "" "extu.b %1,%0" [(set_attr "type" "arith")])

(define_insn "zero_extendqihi2" [(set (match_operand:HI 0 "arith_reg_operand" "=r") (zero_extend:HI (match_operand:QI 1 "arith_reg_operand" "r")))] "" "extu.b %1,%0" [(set_attr "type" "arith")])

;; ------------------------------------------------------------------------- ;; Sign extension instructions ;; -------------------------------------------------------------------------

(define_insn "extendsidi2" [(set (match_operand:DI 0 "arith_reg_operand" "=r,r") (sign_extend:DI (match_operand:SI 1 "arith_reg_operand" "0,r"))) (clobber (reg:SI 18))] "" "@ mov %1,%0;shll %0;subc %0,%0 ! b sidi2 mov %1,%0;mov %1,%R0;shll %0;subc %0,%0 ! a sidi2" [(set_attr "length" "6,8")])

(define_insn "extendhisi2" [(set (match_operand:SI 0 "arith_reg_operand" "=r,z,r") (sign_extend:SI (match_operand:HI 1 "arith_operand" "r,u,m")))] "" "@ exts.w %1,%0 mov.w %1,%0 mov.w %1,%0" [(set_attr "type" "arith,load,load")])

(define_insn "extendqisi2" [(set (match_operand:SI 0 "arith_reg_operand" "=r,z,r") (sign_extend:SI (match_operand:QI 1 "general_movsrc_operand" "r,U,m")))] "" "@ exts.b %1,%0 mov.b %1,%0 !p9 mov.b %1,%0 !p8" [(set_attr "type" "arith,load,load")])

(define_insn "extendqihi2" [(set (match_operand:HI 0 "arith_reg_operand" "=r,z,r") (sign_extend:HI (match_operand:QI 1 "general_movsrc_operand" "r,U,m")))] "" "@ exts.b %1,%0 mov.b %1,%0 !p7 mov.b %1,%0 ! p6" [(set_attr "type" "arith,load,load")])

;; ------------------------------------------------------------------------- ;; Move instructions ;; -------------------------------------------------------------------------

;; define push and pop so it is easy for sh.c

(define_insn "push" [(set (mem:SI (pre_dec:SI (reg:SI 15))) (match_operand:SI 0 "register_operand" "r,lx"))] "" "@ mov.l %0,@-r15 sts.l %0,@-r15 ! push" [(set_attr "type" "store") (set_attr "hit_stack" "yes")])

(define_insn "pop" [(set (match_operand:SI 0 "register_operand" "=r,lx") (mem:SI (post_inc:SI (reg:SI 15))))] "" "@ mov.l @r15+,%0 lds.l @r15+,%0" [(set_attr "type" "load,pload") (set_attr "hit_stack" "yes")])

(define_insn "" [(set (match_operand:SI 0 "push_operand" "=<,<") (match_operand:SI 1 "arith_reg_operand" "r,xl"))] "" "@ mov.l %1,%0 sts.l %1,%0" [(set_attr "type" "store")])

(define_insn "" [(set (match_operand:SI 0 "arith_reg_operand" "=r,xl") (match_operand:SI 1 "pop_operand" "=>,>"))] "" "@ mov.l %1,%0 lds.l %1,%0" [(set_attr "type" "load")])

(define_insn "clrt" [(set (reg:SI 18) (const_int 0))] "" "clrt")

;(define_insn "movsi_pi" ; [(set (match_operand:SI 0 "general_movdst_operand" "=r") ; (mem:SI (post_inc (match_operand:SI 1 "register_operand" "r"))))] ; "" ; "mov.l @%1,%0;add #4,%1" ; [(set_attr "length" "4")])

(define_insn "movsi_i" [(set (match_operand:SI 0 "general_movdst_operand" "=r,r,r,r,r,<m,<,xl,xl,t,r") (match_operand:SI 1 "general_movsrc_operand" "Q,rI,>m,xl,t,r,xl,r,>,r,i"))] "" "@ mov.l %1,%0 mov %1,%0 mov.l %1,%0 sts %1,%0 movt %0 mov.l %1,%0 sts.l %1,%0 lds %1,%0 lds.l %1,%0 tst %1,%1;bt T%;bra F%;sett;T%:clrt;F%:%^ fake %1,%0" [(set_attr "type" "pcloadsi,move,load,move,store,store,move,load,move,move,move")])

(define_expand "movsi" [(set (match_operand:SI 0 "general_movdst_operand" "") (match_operand:SI 1 "general_movsrc_operand" ""))] ""

"{ if (prepare_move_operands(operands, SImode)) DONE; } ")

(define_insn "movqi_i" [(set (match_operand:QI 0 "general_movdst_operand" "=r,r,>m,r,r,l") (match_operand:QI 1 "general_movsrc_operand" "ri,<m,r,t,l,r"))] "arith_reg_operand (operands[0], QImode) || arith_reg_operand (operands[1], QImode)" "@ mov %1,%0 mov.b %1,%0 mov.b %1,%0 movt %0 sts %1,%0 lds %1,%0" [(set_attr "length" "2,2,2,2,2,2") (set_attr "type" "move,load,store,move,move,move")])

(define_expand "movqi" [(set (match_operand:QI 0 "general_operand" "") (match_operand:QI 1 "general_operand" ""))] "" "if (prepare_move_operands(operands, QImode)) DONE; ")

(define_insn "movhi_i" [(set (match_operand:HI 0 "general_movdst_operand" "=r,r,r,r,<m,r,r,l") (match_operand:HI 1 "general_movsrc_operand" "Q,rI,>m,t,r,i,l,r"))] "" "@ mov.w %1,%0 mov %1,%0 mov.w %1,%0 movt %0 mov.w %1,%0 fake %1,%0 sts %1,%0 lds %1,%0" [(set_attr "length" "*,2,2,2,2,2,2,2") (set_attr "type" "pcloadhi,move,load,move,store,move,move,move")])

(define_expand "movhi" [(set (match_operand:HI 0 "general_movdst_operand" "") (match_operand:HI 1 "general_movsrc_operand" ""))] "" "if (prepare_move_operands (operands, HImode)) DONE;")

(define_insn "" [(set (match_operand:DI 0 "push_operand" "=<") (match_operand:DI 1 "arith_reg_operand" "r"))] "" "mov.l %R1,%0;mov.l %1,%0" [(set_attr "length" "4") (set_attr "type" "store")])

(define_insn "" [(set (match_operand:DI 0 "general_movdst_operand" "=r,r,r,m,r") (match_operand:DI 1 "general_movsrc_operand" "Q,r,m,r,i"))] "register_operand (operands[0], DImode) || register_operand (operands[1], DImode)" "* return output_movedouble (insn, operands, DImode);" [(set_attr "length" "*,4,4,4,4") (set_attr "type" "pcloadsi,move,load,store,move")])

;; If the output is a register and the input is memory, we have to be careful ;; and see which word needs to be loaded first. ;; (define_split [(set (match_operand:DI 0 "general_movdst_operand" "") (match_operand:DI 1 "general_movsrc_operand" ""))] "! (GET_CODE (operands[0]) == REG && REGNO (operands[0]) >= FIRST_PSEUDO_REGISTER) && ! (GET_CODE (operands[1]) == REG && REGNO (operands[1]) >= FIRST_PSEUDO_REGISTER) && ! (GET_CODE (operands[0]) == REG && GET_CODE (operands[1]) == REG && ! reload_completed && reg_overlap_mentioned_p (operands[0], operands[1])) && ! EXTRA_CONSTRAINT_Q (operands[1])" [(set (match_dup 2) (match_dup 3)) (set (match_dup 4) (match_dup 5))] " { if (GET_CODE (operands[0]) != REG || ! refers_to_regno_p (REGNO (operands[0]), REGNO (operands[0]) + 1, operands[1], 0)) { operands[2] = operand_subword (operands[0], 0, 0, DImode); operands[3] = operand_subword (operands[1], 0, 0, DImode); operands[4] = operand_subword (operands[0], 1, 0, DImode); operands[5] = operand_subword (operands[1], 1, 0, DImode); } else { operands[2] = operand_subword (operands[0], 1, 0, DImode); operands[3] = operand_subword (operands[1], 1, 0, DImode); operands[4] = operand_subword (operands[0], 0, 0, DImode); operands[5] = operand_subword (operands[1], 0, 0, DImode); }

if (operands[2] == 0 || operands[3] == 0 || operands[4] == 0 || operands[5] == 0) FAIL; }")

(define_expand "movdi" [(set (match_operand:DI 0 "general_movdst_operand" "") (match_operand:DI 1 "general_movsrc_operand" ""))] "" "if ( prepare_move_operands(operands, DImode)) DONE; ")

(define_insn "" [(set (match_operand:DF 0 "push_operand" "=<") (match_operand:DF 1 "arith_reg_operand" "r"))] "" "mov.l %R1,%0;mov.l %1,%0" [(set_attr "length" "4") (set_attr "type" "store")])

(define_insn "movdf_k" [(set (match_operand:DF 0 "general_movdst_operand" "=r,r,m") (match_operand:DF 1 "general_movsrc_operand" "r,m,r"))] "register_operand (operands[0], DFmode) || register_operand (operands[1], DFmode)" "* return output_movedouble (insn, operands, DFmode);" [(set_attr "length" "4") (set_attr "type" "move,load,store")])

;; If the output is a register and the input is memory, we have to be careful ;; and see which word needs to be loaded first. ;; (define_split [(set (match_operand:DF 0 "general_movdst_operand" "") (match_operand:DF 1 "general_movsrc_operand" ""))] "! (GET_CODE (operands[0]) == REG && REGNO (operands[0]) >= FIRST_PSEUDO_REGISTER) && ! (GET_CODE (operands[1]) == REG && REGNO (operands[1]) >= FIRST_PSEUDO_REGISTER) && ! (GET_CODE (operands[0]) == REG && GET_CODE (operands[1]) == REG && ! reload_completed && reg_overlap_mentioned_p (operands[0], operands[1]))" [(set (match_dup 2) (match_dup 3)) (set (match_dup 4) (match_dup 5))] " { if (GET_CODE (operands[0]) != REG || ! refers_to_regno_p (REGNO (operands[0]), REGNO (operands[0]) + 1, operands[1], 0)) { operands[2] = operand_subword (operands[0], 0, 0, DFmode); operands[3] = operand_subword (operands[1], 0, 0, DFmode); operands[4] = operand_subword (operands[0], 1, 0, DFmode); operands[5] = operand_subword (operands[1], 1, 0, DFmode); } else { operands[2] = operand_subword (operands[0], 1, 0, DFmode); operands[3] = operand_subword (operands[1], 1, 0, DFmode); operands[4] = operand_subword (operands[0], 0, 0, DFmode); operands[5] = operand_subword (operands[1], 0, 0, DFmode); }

if (operands[2] == 0 || operands[3] == 0 || operands[4] == 0 || operands[5] == 0) FAIL; }")

(define_expand "movdf" [(set (match_operand:DF 0 "general_movdst_operand" "") (match_operand:DF 1 "general_movsrc_operand" ""))] "" "{ if (prepare_move_operands(operands, DFmode)) DONE; } ")

(define_insn "" [(set (match_operand:SF 0 "push_operand" "=<") (match_operand:SF 1 "arith_reg_operand" "r"))] "" "mov.l %1,%0" [(set_attr "type" "store")])

(define_insn "movsf_i" [(set (match_operand:SF 0 "general_movdst_operand" "=>,r,r,r,r,m,l,r") (match_operand:SF 1 "general_movsrc_operand" "r,<,r,I,m,r,r,l"))] "" "@ mov.l %1,@%N0;add #4,%N0 !bad add #-4,%1;mov.l @%N1,%0 !bad mov %1,%0 mov %1,%0 mov.l %1,%0 mov.l %1,%0 lds %1,%0 sts %1,%0" [(set_attr "type" "store,load,move,move,load,store,move,move") (set_attr "length" "4,4,,,,,,")])

(define_expand "movsf" [(set (match_operand:SF 0 "general_movdst_operand" "") (match_operand:SF 1 "general_movsrc_operand" ""))] "" "if (prepare_move_operands (operands, SFmode)) DONE;")

;; ------------------------------------------------------------------------ ;; Define the real conditional branch instructions. ;; ------------------------------------------------------------------------

(define_insn "branch_true" [(set (pc) (if_then_else (eq (reg:SI 18) (const_int 1)) (label_ref (match_operand 0 "" "")) (pc)))] "" "* return output_branch (1, insn);" [(set_attr "type" "cbranch")])

(define_insn "branch_false" [(set (pc) (if_then_else (ne (reg:SI 18) (const_int 1)) (label_ref (match_operand 0 "" "")) (pc)))] "" "* return output_branch (0, insn);" [(set_attr "type" "cbranch")])

(define_insn "inverse_branch_true" [(set (pc) (if_then_else (eq (reg:SI 18) (const_int 1)) (pc) (label_ref (match_operand 0 "" ""))))] "" "* return output_branch (0, insn);" [(set_attr "type" "cbranch")])

(define_insn "inverse_branch_false" [(set (pc) (if_then_else (ne (reg:SI 18) (const_int 1)) (pc) (label_ref (match_operand 0 "" ""))))] "" "* return output_branch (1, insn);" [(set_attr "type" "cbranch")])

;; Conditional branch insns

(define_expand "beq" [(set (reg:SI 18) (eq:SI (match_dup 1) (match_dup 2))) (set (pc) (if_then_else (eq (reg:SI 18) (const_int 1)) (label_ref (match_operand 0 "" "")) (pc)))] "" "from_compare (operands, EQ);")

; There is no bne compare, so we reverse the branch arms.

(define_expand "bne" [(set (reg:SI 18) (eq:SI (match_dup 1) (match_dup 2))) (set (pc) (if_then_else (eq (reg:SI 18) (const_int 1)) (pc) (label_ref (match_operand 0 "" ""))))] "" "from_compare (operands, NE);")

(define_expand "bgt" [(set (reg:SI 18) (gt:SI (match_dup 1) (match_dup 2))) (set (pc) (if_then_else (eq (reg:SI 18) (const_int 1)) (label_ref (match_operand 0 "" "")) (pc))) ] "" "from_compare (operands, GT);")

(define_expand "blt" [(set (reg:SI 18) (ge:SI (match_dup 1) (match_dup 2))) (set (pc) (if_then_else (eq (reg:SI 18)(const_int 1)) (pc) (label_ref (match_operand 0 "" ""))))] "" "from_compare (operands, LT);")

(define_expand "ble" [(set (reg:SI 18) (gt:SI (match_dup 1) (match_dup 2))) (set (pc) (if_then_else (eq (reg:SI 18) (const_int 1)) (pc) (label_ref (match_operand 0 "" "")))) ] "" "from_compare (operands, LE);")

(define_expand "bge" [(set (reg:SI 18) (ge:SI (match_dup 1) (match_dup 2))) (set (pc) (if_then_else (eq (reg:SI 18) (const_int 1)) (label_ref (match_operand 0 "" "")) (pc))) ] "" "from_compare (operands, GE);")

(define_expand "bgtu" [(set (reg:SI 18) (gtu:SI (match_dup 1) (match_dup 2))) (set (pc) (if_then_else (eq (reg:SI 18) (const_int 1)) (label_ref (match_operand 0 "" "")) (pc)))] "" "from_compare (operands, GTU); ")

(define_expand "bltu" [(set (reg:SI 18) (geu:SI (match_dup 1) (match_dup 2))) (set (pc) (if_then_else (eq (reg:SI 18) (const_int 1)) (pc) (label_ref (match_operand 0 "" ""))))] "" "from_compare (operands, LTU);")

(define_expand "bgeu" [(set (reg:SI 18) (geu:SI (match_dup 1) (match_dup 2))) (set (pc) (if_then_else (eq (reg:SI 18) (const_int 1)) (label_ref (match_operand 0 "" "")) (pc))) ] "" "from_compare (operands, GEU);")

(define_expand "bleu" [(set (reg:SI 18) (gtu:SI (match_dup 1) (match_dup 2))) (set (pc) (if_then_else (eq (reg:SI 18) (const_int 1)) (pc) (label_ref (match_operand 0 "" ""))))] "" "from_compare (operands, LEU);")

;; ------------------------------------------------------------------------ ;; Jump and linkage insns ;; ------------------------------------------------------------------------

(define_insn "jump" [(set (pc) (label_ref (match_operand 0 "" "")))] "" "* { if (get_attr_length(insn) == 10) { return output_far_jump(insn, operands[0]); } else { return "bra %l0%#"; } }" [(set_attr "type" "jump") (set_attr "needs_delay_slot" "yes")])

(define_insn "bsr" [(call (mem:SI (match_operand 0 "bsr_operand" "i")) (match_operand 1 "" "")) (clobber (reg:SI 17))] "TARGET_BSR" "bsr %O0%#" [(set_attr "needs_delay_slot" "yes") (set_attr "in_delay_slot" "no") (set_attr "length" "4")])

(define_insn "calli" [(call (mem:SI (match_operand:SI 0 "arith_reg_operand" "r")) (match_operand 1 "" "")) (clobber (reg:SI 17))] "" "jsr @%0%#" [(set_attr "needs_delay_slot" "yes") (set_attr "in_delay_slot" "no") (set_attr "length" "4")])

(define_insn "bsr_value" [(set (match_operand 0 "" "=rf") (call (mem:SI (match_operand 1 "bsr_operand" "i")) (match_operand 2 "" ""))) (clobber (reg:SI 17))] "TARGET_BSR" "bsr %O1%#" [(set_attr "needs_delay_slot" "yes") (set_attr "in_delay_slot" "no") (set_attr "length" "4")])

(define_insn "call_valuei" [(set (match_operand 0 "" "=rf") (call (mem:SI (match_operand:SI 1 "arith_reg_operand" "r")) (match_operand 2 "" ""))) (clobber (reg:SI 17))] "" "jsr @%1%#" [(set_attr "needs_delay_slot" "yes") (set_attr "in_delay_slot" "no") (set_attr "length" "4")])

(define_expand "call" [(parallel[(call (match_operand 0 "arith_reg_operand" "o") (match_operand 1 "" "")) (clobber (reg:SI 17))])] "" "expand_acall(0, operands); DONE;")

(define_expand "call_value" [(parallel[(set (match_operand 0 "" "=rf") (call (match_operand 1 "arith_reg_operand" "o") (match_operand 2 "" ""))) (clobber (reg:SI 17))])] "" "expand_acall(1, operands); DONE; ")

(define_insn "indirect_jump" [(set (pc) (match_operand:SI 0 "arith_reg_operand" "r"))] "" "jmp @%0%#" [(set_attr "needs_delay_slot" "yes") (set_attr "in_delay_slot" "no") (set_attr "length" "4")])

;; ------------------------------------------------------------------------ ;; Misc insns ;; ------------------------------------------------------------------------

(define_insn "dect" [(parallel[ (set (reg:SI 18) (eq:SI (match_operand:SI 0 "register_operand" "=r") (const_int 1)))

     (set (match_dup 0)
	  (plus:SI (match_dup 0)
		   (const_int -1)))])]

"TARGET_SH2" "dt %0")

(define_insn "nop" [(const_int 0)] "" "or r0,r0")

; experimental use of auto inc and dec made these... ; can be deleted

(define_insn "fake" [(set (match_operand:QI 0 "register_operand" "=r") (mem:QI (pre_dec:SI (match_operand:SI 1 "register_operand" "r"))))] "" "add #-1,%1;mov.b @%1,%0 !bad" [(set_attr "length" "4")])

;; Load address of a label. This is only generated by the casesi expand.

(define_insn "mova" [(set (reg:SI 0) (label_ref (match_operand 0 "" "")))] "" "mova %O0,r0" [(set_attr "in_delay_slot" "no")])

;; case instruction for switch statements.

;; Operand 0 is index ;; operand 1 is the minimum bound ;; operand 2 is the maximum bound - minimum bound + 1 ;; operand 3 is CODE_LABEL for the table; ;; operand 4 is the CODE_LABEL to go to if index out of range.

(define_expand "casesi" [(set (match_dup 5) (match_operand:SI 0 "arith_reg_operand" "")) (set (match_dup 5) (minus:SI (match_dup 5) (match_operand:SI 1 "arith_operand" ""))) (set (reg:SI 18) (gtu:SI (match_dup 5) (match_operand:SI 2 "arith_operand" ""))) (set (pc) (if_then_else (eq (reg:SI 18) (const_int 1)) (label_ref (match_operand 4 "" "")) (pc))) (set (match_dup 6) (match_dup 5)) (parallel[(set (match_dup 6) (ashift:SI (match_dup 6) (match_dup 7))) (clobber (reg:SI 18))]) (set (reg:SI 0) (label_ref (match_operand 3 "" ""))) (parallel[(set (reg:SI 0) (plus:SI (reg:SI 0) (mem:HI (plus:SI (reg:SI 0) (match_dup 6))))) (set (match_dup 6) (mem:HI (plus:SI (reg:SI 0) (match_dup 6))))]) (set (pc) (reg:SI 0))] "" " { operands[1] = copy_to_mode_reg (SImode, operands[1]); operands[2] = copy_to_mode_reg (SImode, operands[2]); operands[5] = gen_reg_rtx (SImode); operands[6] = gen_reg_rtx (SImode); operands[7] = GEN_INT (TARGET_BIGTABLE ? 2 : 1); }")

(define_insn "casesi_worker" [(set (reg:SI 0) (plus:SI (reg:SI 0) (mem:HI (plus:SI (reg:SI 0) (match_operand:SI 0 "register_operand" "=r"))))) (set (match_dup 0) (mem:HI (plus:SI (reg:SI 0) (match_dup 0))))] "" "* if (TARGET_BIGTABLE) return "mov.l @(r0,%0),%0;add %0,r0"; else return "mov.w @(r0,%0),%0;add %0,r0";" [(set_attr "needs_delay_slot" "no") (set_attr "in_delay_slot" "no") (set_attr "length" "4")])

(define_insn "return" [(return)] "reload_completed" "%@ %#" [(set_attr "type" "return")])

(define_expand "prologue" [(const_int 0)] "" "sh_expand_prologue (); DONE;")

(define_expand "epilogue" [(return)] "" "sh_expand_epilogue ();")

(define_insn "blockage" [(unspec_volatile [(const_int 0)] 0)] "" "" [(set_attr "length" "0")])

;; ------------------------------------------------------------------------ ;; Scc instructions ;; ------------------------------------------------------------------------

(define_insn "movt" [(set (match_operand:SI 0 "arith_reg_operand" "=r") (eq:SI (reg:SI 18) (const_int 1)))] "" "movt %0 ! ")

(define_expand "seq" [(set (match_operand:SI 0 "arith_reg_operand" "") (match_dup 1))] "" "operands[1] = prepare_scc_operands (EQ);")

(define_expand "slt" [(set (match_operand:SI 0 "arith_reg_operand" "") (match_dup 1))] "" "operands[1] = prepare_scc_operands (LT);")

(define_expand "sle" [(set (match_operand:SI 0 "arith_reg_operand" "") (match_dup 1))] "" "operands[1] = prepare_scc_operands (LE);")

(define_expand "sgt" [(set (match_operand:SI 0 "arith_reg_operand" "") (match_dup 1))] "" "operands[1] = prepare_scc_operands (GT);")

(define_expand "sge" [(set (match_operand:SI 0 "arith_reg_operand" "") (match_dup 1))] "" "operands[1] = prepare_scc_operands (GE);")

(define_expand "sgtu" [(set (match_operand:SI 0 "arith_reg_operand" "") (match_dup 1))] "" "operands[1] = prepare_scc_operands (GTU);")

(define_expand "sltu" [(set (match_operand:SI 0 "arith_reg_operand" "") (match_dup 1))] "" "operands[1] = prepare_scc_operands (LTU);")

(define_expand "sleu" [(set (match_operand:SI 0 "arith_reg_operand" "") (match_dup 1))] "" "operands[1] = prepare_scc_operands (LEU);")

(define_expand "sgeu" [(set (match_operand:SI 0 "arith_reg_operand" "") (match_dup 1))] "" "operands[1] = prepare_scc_operands (GEU);")

(define_expand "sne" [(set (match_operand:SI 0 "arith_reg_operand" "") (match_dup 1)) (set (match_dup 0) (xor:SI (match_dup 0) (const_int 1)))] "" "operands[1] = prepare_scc_operands (EQ);")

;; ------------------------------------------------------------------------- ;; Peepholes ;; -------------------------------------------------------------------------

(define_peephole [(set (match_operand:QI 0 "arith_reg_operand" "") (mem:QI (match_operand:SI 1 "arith_reg_operand" ""))) (set (match_dup 1) (plus:SI (match_dup 1) (const_int 1)))] "REGNO (operands[1]) != REGNO (operands[0])" "mov.b @%1+,%0")

(define_peephole [(set (match_operand:HI 0 "arith_reg_operand" "") (mem:HI (match_operand:SI 1 "arith_reg_operand" ""))) (set (match_dup 1) (plus:SI (match_dup 1) (const_int 2)))] "REGNO (operands[1]) != REGNO (operands[0])" "mov.w @%1+,%0")

(define_peephole [(set (match_operand:SI 0 "arith_reg_operand" "") (mem:SI (match_operand:SI 1 "arith_reg_operand" ""))) (set (match_dup 1) (plus:SI (match_dup 1) (const_int 4)))] "REGNO (operands[1]) != REGNO (operands[0])" "mov.l @%1+,%0")

(define_peephole [(set (match_operand:QI 0 "register_operand" "=r") (match_operand:QI 1 "memory_operand" "g")) (set (match_operand:SI 2 "register_operand" "=r") (sign_extend:SI (match_dup 0)))] "REGNO (operands[0]) == REGNO (operands[2])" "mov.b %1,%0 !p 5")

(define_peephole [(set (match_operand:QI 0 "register_operand" "=r") (match_operand:QI 1 "general_movsrc_operand" "g")) (set (match_operand:SI 2 "register_operand" "=r") (sign_extend:SI (match_dup 0)))] "REGNO (operands[0]) != REGNO (operands[2]) && 0 && dead_or_set_p (insn, operands[0])" "mov.b %1,%2 ! p4")

;; ------------------------------------------------------------------------- ;; Peepholes ;; -------------------------------------------------------------------------

(define_peephole [(set (reg:SI 0) (label_ref (match_operand 0 "" ""))) (set (match_operand:SI 1 "register_operand" "=r") (reg:SI 0)) (set (reg:SI 0) (label_ref (match_dup 0))) (set (match_operand:SI 2 "register_operand" "=r") (reg:SI 0))] "" "mova %O0,r0;mov r0,%1;mov r0,%2" [(set_attr "length" "6") (set_attr "in_delay_slot" "no")])

;; ------------------------------------------------------------------------- ;; Combine patterns ;; -------------------------------------------------------------------------

(define_insn "" [(set (match_operand:SI 0 "register_operand" "=r") (plus:SI (match_operand:HI 1 "register_operand" "%0") (match_operand:SI 2 "register_operand" "r")))] "" "add %2,%0 ! why")

(define_insn "addc_2" [(set (match_operand:SI 0 "arith_reg_operand" "=&r") (plus:SI (reg:SI 18) (match_operand:SI 1 "arith_reg_operand" "r"))) (clobber (reg:SI 18))] "" "mov #0,%0;addc %1,%0 ! addc1" [(set_attr "length" "4")])

(define_insn "combine_1" [(set (match_operand:SI 0 "arith_reg_operand" "=r") (sign_extend:SI (mem:QI (match_operand:SI 1 "arith_reg_operand" "r"))))] "" "mov.b @%1,%0 ! why" [(set_attr "type" "load")])

(define_insn "combine_2" [(set (reg:SI 18) (eq:SI (and:SI (match_operand:SI 0 "arith_reg_operand" "z,r") (match_operand:SI 1 "arith_operand" "L,r")) (const_int 0)))] "" "tst %1,%0 !t2c")

(define_split [(set (pc) (if_then_else (match_operator 2 "equality_operator" [(match_operand:SI 0 "arith_reg_operand" "r") (const_int 0)]) (label_ref (match_operand 1 "" "")) (pc))) (clobber (reg:SI 18))] "" [(set (reg:SI 18) (eq:SI (and:SI (match_dup 0) (match_dup 0)) (const_int 0))) (set (pc) (if_then_else (match_op_dup 2 [(reg:SI 18) (const_int 1)]) (label_ref (match_dup 1)) (pc)))] "")

;; ------------------------------------------------------------------------- ;; Instructions to cope with inline literal tables ;; -------------------------------------------------------------------------

; 2 byte integer in line

(define_insn "consttable_2" [(unspec_volatile [(match_operand:SI 0 "general_operand" "=g")] 2)] "" "* { assemble_integer (operands[0], 2, 1); return ""; }" [(set_attr "length" "2") (set_attr "in_delay_slot" "no")])

; 4 byte integer in line

(define_insn "consttable_4" [(unspec_volatile [(match_operand:SI 0 "general_operand" "=g")] 4)] "" "* { assemble_integer (operands[0], 4, 1); return ""; }" [(set_attr "length" "4") (set_attr "in_delay_slot" "no")])

; 8 byte integer in line

(define_insn "consttable_8" [(unspec_volatile [(match_operand:SI 0 "general_operand" "=g")] 6)] "" "* { assemble_integer (operands[0], 8, 1); return ""; }" [(set_attr "length" "8") (set_attr "in_delay_slot" "no")])

; align to a two byte boundary

(define_insn "align_2" [(unspec_volatile [(const_int 0)] 10)] "" ".align 1" [(set_attr "length" "0") (set_attr "in_delay_slot" "no")])

; align to a four byte boundary

(define_insn "align_4" [(unspec_volatile [(const_int 0)] 5)] "" ".align 2" [(set_attr "in_delay_slot" "no")])

; emitted at the end of the literal table, used to emit the ; 32bit branch labels if needed.

(define_insn "consttable_end" [(unspec_volatile [(const_int 0)] 11)] "" "* return output_jump_label_table ();" [(set_attr "in_delay_slot" "no")])

;(define_split ; [(set (subreg:SI (match_operand:QI 0 "register_operand" "=r") 0) ; (plus:SI (subreg:SI (match_operand:QI 1 "general_operand" "g") 0) ; (subreg:SI (match_operand:QI 2 "general_operand" "g") 0)))] ; "" ; [(set (match_dup 3) (plus:SI (match_dup 1) (match_dup 2))) ; (set (match_dup 1) (subreg:SI (match_dup 3) 0))] ; "operands[3] = gen_reg_rtx(SImode);")

; byte arithmetic involving constants which need to be sign extended can be ; fixed up...

(define_split [(set (subreg:SI (match_operand:QI 0 "register_operand" "=r") 0) (plus:SI (subreg:SI (match_operand:QI 1 "register_operand" "0") 0) (subreg:SI (match_operand 2 "immediate_operand" "n") 0)))] "" [(set (match_dup 4) (plus:SI (match_dup 2) (match_dup 3))) (set (match_dup 0) (and:SI (match_dup 0) (const_int 255)))] "{ int i = INTVAL(operands[2]) & 0xff; if (i > 127) i = i - 256; operands[3] = GEN_INT(i); operands[4] = gen_reg_rtx(SImode);} ")

;; these instructions don't really exist - they are needed ;; before machine_dependent_reorg

(define_insn "movsi_k" [(set (match_operand:SI 0 "register_operand" "=r") (match_operand:SI 1 "immediate_operand" ""))] "" "! this is a fake")

(define_insn "movhi_k" [(set (match_operand:HI 0 "register_operand" "=r") (match_operand:HI 1 "immediate_operand" ""))] "" "! this is a fake")

(define_insn "movdi_k" [(set (match_operand:DI 0 "register_operand" "=r") (match_operand:DI 1 "immediate_operand" ""))] "" "! this is a fake")

;; ------------------------------------------------------------------------- ;; Misc ;; -------------------------------------------------------------------------

;; String/block move insn.

(define_expand "movstrsi" [(parallel [(set (mem:BLK (match_operand:BLK 0 "" "")) (mem:BLK (match_operand:BLK 1 "" ""))) (use (match_operand:SI 2 "nonmemory_operand" "")) (use (match_operand:SI 3 "immediate_operand" "")) (clobber (reg:SI 17)) (clobber (reg:SI 4)) (clobber (reg:SI 5)) (clobber (reg:SI 0))])] "" " { if(expand_block_move (operands)) DONE; else FAIL; }")

(define_insn "block_move_real" [(parallel [(set (mem:BLK (reg:SI 4)) (mem:BLK (reg:SI 5))) (use (match_operand:SI 0 "arith_reg_operand" "r")) (clobber (reg:SI 17)) (clobber (reg:SI 4)) (clobber (reg:SI 5)) (clobber (reg:SI 0))])] "" "jsr @%0%#" [(set_attr "length" "4") (set_attr "type" "sfunc") (set_attr "needs_delay_slot" "yes")])

(define_insn "block_lump_real" [(parallel [(set (mem:BLK (reg:SI 4)) (mem:BLK (reg:SI 5))) (use (match_operand:SI 0 "arith_reg_operand" "r")) (use (reg:SI 6)) (clobber (reg:SI 17)) (clobber (reg:SI 4)) (clobber (reg:SI 5)) (clobber (reg:SI 6)) (clobber (reg:SI 0))])] "" "jsr @%0%#" [(set_attr "length" "4") (set_attr "type" "sfunc") (set_attr "needs_delay_slot" "yes")])

(define_insn "mac" [(set (reg:SI 21) (mult:SI (sign_extend:SI (mem:HI (post_inc:SI (match_operand:SI 0 "arith_reg_operand" "r")))) (sign_extend:SI (mem:HI (post_inc:SI (match_operand:SI 1 "arith_reg_operand" "r"))))))] "" "mac.w @%0+,@%1+")