8sa1-gcc/gcc/config/sh/sh.md
Steve Chamberlain b2358eb12c (movstrsi): Take alignment into account.
From-SVN: r4410
1993-05-10 15:59:02 +00:00

34 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.

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

;; ------------------------------------------------------------------------- ;; Attributes ;; -------------------------------------------------------------------------

(define_attr "type" "cbranch,ctable,jump,arith,other" (const_string "other"))

; If a conditional branch destination is within -100..100 bytes away ; from the instruction it can be 2 bytes long. Something in the ; range -4000..4000 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 8 bytes long.

; 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 -100)) (le (minus (pc) (match_dup 0)) (const_int 100))) (const_int 2) (if_then_else (and (ge (minus (pc) (match_dup 0)) (const_int -4000)) (le (minus (pc) (match_dup 0)) (const_int 4000))) (const_int 6) (const_int 8)))

 (eq_attr "type" "jump")
		(if_then_else (and (ge (minus (pc) (match_dup 0))
				       (const_int -4000))
				   (le (minus (pc) (match_dup 0))
				       (const_int 4000)))
			      (const_int 4)
			      (const_int 6))
 ] (const_int 2)))

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

(define_attr "dump" "yes,no,must" (const_string "no")) (define_attr "constneed" "yes,no" (const_string "no")) (define_attr "smallestsize" "" (const_int 2)) (define_attr "largestsize" "" (const_int 8)) (define_attr "constantsize" "" (const_int 4))

(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 "length" "2") (const_string "yes") (eq_attr "length" "4,6,8,10,12") (const_string "no") ] (const_string "yes")))

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

;; ------------------------------------------------------------------------- ;; 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 (match_operand:SI 0 "arith_reg_operand" "r") (const_int 0)))] "" "cmp/pl %0")

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

(define_insn "cmpeqsi_t" [(set (reg:SI 18) (eq (match_operand:SI 0 "arith_reg_operand" "r,z") (match_operand:SI 1 "arith_operand" "r,I")))] "" "cmp/eq %1,%0")

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

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

(define_insn "cmpltsi_t" [(set (reg:SI 18) (lt (match_operand:SI 0 "arith_reg_operand" "r") (match_operand:SI 1 "arith_reg_operand" "r")))] "" "cmp/gt %0,%1")

(define_insn "cmplesi_t" [(set (reg:SI 18) (le (match_operand:SI 0 "arith_reg_operand" "r") (match_operand:SI 1 "arith_reg_operand" "r")))] "" "cmp/ge %0,%1")

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

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

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

(define_insn "cmpleusi_t" [(set (reg:SI 18) (leu (match_operand:SI 0 "arith_reg_operand" "r") (match_operand:SI 1 "arith_reg_operand" "r")))] "" "cmp/hs %0,%1")

(define_insn "cmpltusi_t" [(set (reg:SI 18) (ltu (match_operand:SI 0 "arith_reg_operand" "r") (match_operand:SI 1 "arith_reg_operand" "r")))] "" "cmp/hi %0,%1")

;; 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_reg_operand" "") (match_operand:SI 1 "arith_reg_operand" "")))] "" " { sh_compare_op0 = operands[0]; sh_compare_op1 = operands[1]; DONE; }")

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

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

(define_insn "addsi3_i" [(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_reg_operand" "%0") (match_operand:SI 2 "arith_operand" "rI")))] "" "")

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

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

(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_reg_operand" "r")))] "" "sub %2,%0" [(set_attr "type" "arith")])

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

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

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

(define_insn "" [(set (reg:SI 21) (mult:SI (match_operand:SI 1 "arith_reg_operand" "r") (match_operand:SI 2 "arith_reg_operand" "r")))] "TARGET_HAS_MULSI3" "muls.l %2,%1")

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

(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_HAS_MULSI3" "dmuls.l %2,%1")

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

(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_HAS_MULSI3" "dmulu.l %2,%1")

(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_HAS_MULSI3" "") ;; ------------------------------------------------------------------------- ;; Logical operations ;; -------------------------------------------------------------------------

(define_insn "andsi3" [(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_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" "=r,z") (xor:SI (match_operand:SI 1 "arith_reg_operand" "%0,0") (match_operand:SI 2 "logical_operand" "r,L")))] "" "xor %2,%0" [(set_attr "type" "arith")])

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

(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" "L,n")))] "" "*return output_shift("shll", operands[0], operands[2]);" [(set_attr "length" "2,12") (set_attr "in_delay_slot" "yes,no") (set_attr "type" "arith")])

(define_expand "ashlsi3" [(set (match_operand:SI 0 "arith_reg_operand" "") (ashift:SI (match_operand:SI 1 "arith_reg_operand" "") (match_operand:SI 2 "immediate_operand" "")))] "" "if (!ok_shift_value(operands[2])) FAIL;")

(define_insn "ashrsi3_k" [(set (match_operand:SI 0 "arith_reg_operand" "=r") (ashiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0") (const_int 1)))] "" "shar %0" [(set_attr "type" "arith")])

(define_expand "ashrsi3" [(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")))] "" " { if (GET_CODE (operands[2]) != CONST_INT || INTVAL (operands[2]) != 1) FAIL; } ")

(define_insn "lshrsi3_k" [(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" "L")))] "" "* return output_shift ("shlr", operands[0], operands[2]);" [(set_attr "length" "12") (set_attr "in_delay_slot" "no") (set_attr "type" "arith")])

(define_expand "lshrsi3" [(set (match_operand:SI 0 "arith_reg_operand" "") (lshiftrt:SI (match_operand:SI 1 "arith_reg_operand" "") (match_operand:SI 2 "nonmemory_operand" "")))] "" "if (!ok_shift_value (operands[2])) FAIL; ")

(define_insn "ashldi3_k" [(set (match_operand:DI 0 "arith_reg_operand" "=r") (ashift:DI (match_operand:DI 1 "arith_reg_operand" "0") (match_operand:DI 2 "immediate_operand" "I"))) (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") (match_operand:DI 2 "immediate_operand" "I"))) (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") (match_operand:DI 2 "immediate_operand" ""))) (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 "negdi2" [(set (match_operand:DI 0 "arith_reg_operand" "=&r") (neg:DI (match_operand:DI 1 "arith_reg_operand" "0"))) (clobber (reg:SI 18))] "" "clrt;negc %R1,%R0;negc %1,%0" [(set_attr "length" "6") (set_attr "type" "arith")])

(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") (sign_extend:DI (match_operand:SI 1 "arith_reg_operand" "0")))] "" "mov %1,%0;shll %0;subc %0,%0" [(set_attr "length" "6")])

(define_insn "extendhisi2" [(set (match_operand:SI 0 "arith_reg_operand" "=r") (sign_extend:SI (match_operand:HI 1 "arith_reg_operand" "r")))] "" "exts.w %1,%0")

(define_insn "extendqisi2" [(set (match_operand:SI 0 "arith_reg_operand" "=r") (sign_extend:SI (match_operand:QI 1 "arith_reg_operand" "r")))] "" "exts.b %1,%0")

(define_insn "extendqihi2" [(set (match_operand:HI 0 "arith_reg_operand" "=r") (sign_extend:HI (match_operand:QI 1 "arith_reg_operand" "r")))] "" "exts.b %1,%0")

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

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

(define_insn "movsi_pcrel" [(set (match_operand:SI 0 "arith_reg_operand" "=r") (match_operand:SI 1 "hard_immediate_operand" "i"))] "" "* return output_movepcrel (insn, operands, SImode);" [(set_attr "length" "2") (set_attr "in_delay_slot" "no") (set_attr "constneed" "yes") (set_attr "smallestsize" "2") (set_attr "largestsize" "8")])

(define_insn "movsi_i" [(set (match_operand:SI 0 "general_operand" "=r,r,r,m,l,r,r,r,t") (match_operand:SI 1 "general_operand" "r,I,m,r,r,l,t,x,r"))] "" "@ mov %1,%0 mov %1,%0 mov.l %1,%0 mov.l %1,%0 mov %1,%0 mov %1,%0 movt %0 sts %1,%0 tst %1,%1;bt T%;bra F%;sett;T%:clrt;F%:%^" [(set_attr "length" "2,2,2,2,2,2,2,2,10")])

(define_expand "movsi" [(set (match_operand:SI 0 "general_operand" "") (match_operand:SI 1 "general_operand" ""))] "" "{ prepare_move_operands(operands, SImode); } ")

(define_insn "movqi_i" [(set (match_operand:QI 0 "general_operand" "=r,r,z,m,r,m,r,r") (match_operand:QI 1 "general_operand" "r,n,m,z,m,r,x,t"))] "" "@ mov %1,%0 mov %1,%0 mov.b %1,%0 !4 mov.b %1,%0 !5 mov.b %1,%0 !6 mov.b %1,%0 ! 7 sts %1,%0 movt %0")

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

(define_insn "movhi_pcrel" [(set (match_operand:HI 0 "arith_reg_operand" "=r") (match_operand:HI 1 "hard_immediate_operand" "i"))] "" "* return output_movepcrel (insn, operands, SImode);" [(set_attr "length" "2") (set_attr "in_delay_slot" "no") (set_attr "constneed" "yes") (set_attr "smallestsize" "2") (set_attr "largestsize" "8")])

(define_insn "movhi_i" [(set (match_operand:HI 0 "general_operand" "=r,r,m,z,m,r,r") (match_operand:HI 1 "general_operand" "rI,m,r,m,z,x,t"))] "" "@ mov %1,%0 mov.w %1,%0 mov.w %1,%0 mov.w %1,%0 mov.w %1,%0 sts %1,%0 movt %0")

(define_expand "movhi" [(set (match_operand:HI 0 "general_operand" "") (match_operand:HI 1 "general_operand" ""))] "" "prepare_move_operands (operands, HImode);")

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

(define_insn "movdi_pcrel" [(set (match_operand:DI 0 "arith_reg_operand" "=r") (match_operand:DI 1 "hard_immediate_operand" "i"))] "" "* return output_movepcrel (insn, operands, DImode);" [(set_attr "length" "4") (set_attr "in_delay_slot" "no") (set_attr "constneed" "yes") (set_attr "smallestsize" "4") (set_attr "constantsize" "8") (set_attr "largestsize" "18")])

(define_insn "movdi_k" [(set (match_operand:DI 0 "general_operand" "=r,r,m,r,r,m,r") (match_operand:DI 1 "general_operand" "r,m,r,I,m,r,x"))] "" "* return output_movedouble(operands, DImode);" [(set_attr "length" "4")])

(define_expand "movdi" [(set (match_operand:DI 0 "general_operand" "") (match_operand:DI 1 "general_operand" ""))] "" "prepare_move_operands (operands, DImode);")

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

(define_insn "movdf_pcrel" [(set (match_operand:DF 0 "arith_reg_operand" "=r") (match_operand:DF 1 "hard_immediate_operand" "i"))] "" "* return output_movepcrel (insn, operands, DFmode);" [(set_attr "length" "4") (set_attr "in_delay_slot" "no") (set_attr "constneed" "yes") (set_attr "smallestsize" "4") (set_attr "constantsize" "8") (set_attr "largestsize" "18")])

(define_insn "movdf_k" [(set (match_operand:DF 0 "general_operand" "=r,r,m") (match_operand:DF 1 "general_operand" "r,m,r"))] "" "* return output_movedouble(operands, DFmode);" [(set_attr "length" "4")])

(define_expand "movdf" [(set (match_operand:DF 0 "general_operand" "") (match_operand:DF 1 "general_operand" ""))] "" "prepare_move_operands(operands, DFmode);")

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

(define_insn "movsf_pcrel" [(set (match_operand:SF 0 "arith_reg_operand" "=r") (match_operand:SF 1 "hard_immediate_operand" "i"))] "" "* return output_movepcrel (insn, operands, SFmode);" [(set_attr "length" "2") (set_attr "in_delay_slot" "no") (set_attr "constneed" "yes") (set_attr "smallestsize" "2") (set_attr "largestsize" "8")])

(define_insn "movsf_i" [(set (match_operand:SF 0 "general_operand" "=r,r,r,m,l,r,m,r") (match_operand:SF 1 "general_operand" "r,I,m,r,r,l,r,m"))] "" "@ mov %1,%0 mov %1,%0 mov.l %1,%0 mov.l %1,%0 mov %1,%0 mov %1,%0 mov %1,%0 mov %1,%0")

(define_expand "movsf" [(set (match_operand:SF 0 "general_operand" "") (match_operand:SF 1 "general_operand" ""))] "" "prepare_move_operands(operands, SFmode);")

;; ------------------------------------------------------------------------ ;; 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)))] "" " { operands[1] = sh_compare_op0; operands[2] = sh_compare_op1; }")

; 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 "" ""))))] "" " { operands[1] = sh_compare_op0; operands[2] = sh_compare_op1; }")

(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)))] "" " { operands[1] = sh_compare_op0; operands[2] = sh_compare_op1; }")

(define_expand "blt" [(set (reg:SI 18) (lt: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)))] "" " { operands[1] = sh_compare_op0; operands[2] = sh_compare_op1; }")

(define_expand "ble" [(set (reg:SI 18) (le: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)))] "" " { operands[1] = sh_compare_op0; operands[2] = sh_compare_op1; }")

(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)))] "" " { operands[1] = sh_compare_op0; operands[2] = sh_compare_op1; }")

(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)))] "" " { operands[1] = sh_compare_op0; operands[2] = sh_compare_op1; }")

(define_expand "bltu" [(set (reg:SI 18) (ltu: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)))] "" " { operands[1] = sh_compare_op0; operands[2] = sh_compare_op1; }")

(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)))] "" " { operands[1] = sh_compare_op0; operands[2] = sh_compare_op1; }")

(define_expand "bleu" [(set (reg:SI 18) (leu: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)))] "" " { operands[1] = sh_compare_op0; operands[2] = sh_compare_op1; }")

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

(define_insn "jump_real" [(set (pc) (label_ref (match_operand 0 "" "")))] "" "* { if (get_attr_length(insn) == 6) { return "mov.l %I0,r13;jmp @r13%#"; } else { return "bra %l0%#"; } }" [(set_attr "type" "jump") (set_attr "needs_delay_slot" "yes")])

(define_expand "jump" [(set (pc) (label_ref (match_operand 0 "" "")))] "" " { emit_insn(gen_jump_real(operand0)); DONE; } ")

(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 "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))])] "" " { if (GET_CODE (operands[0]) == MEM) { operands[0] = gen_rtx(MEM,GET_MODE (operands[0]), force_reg (Pmode, XEXP (operands[0], 0))); } }")

(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))])] "" " { if (GET_CODE (operands[1]) == MEM) { operands[1] = gen_rtx (MEM, GET_MODE (operands[1]), force_reg (Pmode, XEXP (operands[1], 0))); } }")

(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 "nop" [(const_int 0)] "" "or r0,r0")

(define_insn "tablejump" [(set (pc) (match_operand:SI 0 "arith_reg_operand" "r")) (use (label_ref (match_operand 1 "" "")))] "" "!table jump;jmp @%0;or r0,r0;%!" [(set_attr "needs_delay_slot" "no") (set_attr "in_delay_slot" "no") (set_attr "type" "jump") (set_attr "dump" "no")]) ;; ------------------------------------------------------------------------ ;; Scc instructions ;; ------------------------------------------------------------------------

(define_insn "" [(set (match_operand:SI 0 "arith_reg_operand" "=r") (eq (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);")

(define_insn "anddi3" [(set (match_operand:DI 0 "arith_reg_operand" "=r") (and:DI (match_operand:DI 1 "arith_reg_operand" "%0") (match_operand:DI 2 "arith_reg_operand" "r")))] "" "and %2,%0;and %R2,%R0" [(set_attr "length" "4")])

(define_insn "iordi3" [(set (match_operand:DI 0 "arith_reg_operand" "=r") (ior:DI (match_operand:DI 1 "arith_reg_operand" "%0") (match_operand:DI 2 "arith_reg_operand" "r")))] "" "or %2,%0;or %R2,%R0" [(set_attr "length" "4")])

(define_insn "xordi3" [(set (match_operand:DI 0 "arith_reg_operand" "=r") (xor:DI (match_operand:DI 1 "arith_reg_operand" "%0") (match_operand:DI 2 "arith_reg_operand" "r")))] "" "xor %2,%0;xor %R2,%R0" [(set_attr "length" "4")])

;; ------------------------------------------------------------------------ ;; Block move ;; ------------------------------------------------------------------------

(define_expand "movstrsi" [(parallel [(set (mem:BLK (match_operand:BLK 0 "general_operand" "")) (mem:BLK (match_operand:BLK 1 "general_operand" ""))) (use (match_operand:SI 2 "general_operand" "")) (use (match_operand:SI 3 "immediate_operand" "")) ])] "" " { rtx src_ptr = copy_to_mode_reg(Pmode,XEXP(operands[1], 0)); rtx dst_ptr = copy_to_mode_reg(Pmode,XEXP(operands[0], 0)); int maxsize = GET_CODE (operands[2]) == CONST_INT ? MAX (INTVAL (operands[2]), INTVAL (operands[3])) : 1; enum machine_mode mode = (maxsize >= 4) ? SImode : (maxsize >= 2) ? HImode : QImode;

rtx tmpreg = gen_reg_rtx(mode); rtx increment = GEN_INT(GET_MODE_SIZE(mode)); rtx length = operands[2]; rtx label = gen_label_rtx(); rtx end_src_ptr = gen_reg_rtx(Pmode);

/* If done first rtl emmiting stage we can't generate a loop / / if (!rtx_equal_function_value_matters) FAIL;*/

if (GET_CODE (length) != CONST_INT) length = convert_to_mode (Pmode, length, 1);

if (!arith_operand (length, SImode)) length = force_reg (SImode, length);

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_insn(gen_rtx(SET, VOIDmode, src_ptr, gen_rtx(PLUS, Pmode, src_ptr, increment)));

emit_move_insn(gen_rtx(MEM, mode, dst_ptr), tmpreg);

emit_insn(gen_rtx(SET, VOIDmode, dst_ptr, gen_rtx(PLUS, Pmode, dst_ptr, increment)));

sh_compare_op0 = src_ptr; sh_compare_op1 = end_src_ptr;

emit_insn(gen_cmpeqsi_t(src_ptr, end_src_ptr)); emit_jump_insn(gen_bne(label)); emit_insn(gen_rtx(SET, VOIDmode, dst_ptr, dst_ptr));

DONE; } ")

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