8sa1-gcc/gcc/config/mips/mips.md
Michael Meissner bbdb5552f3 *** empty log message ***
From-SVN: r849
1992-04-28 20:33:51 +00:00

112 KiB
Raw Blame History

;; Mips.md Machine Description for MIPS based processors ;; Contributed by A. Lichnewsky, lich@inria.inria.fr ;; Changes by Michael Meissner, meissner@osf.org ;; Copyright (C) 1989, 1990, 1991, 1992 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.

;; .................... ;; ;; Attributes ;; ;; ....................

;; Classification of each insn. ;; branch conditional branch ;; jump unconditional jump ;; call unconditional call ;; load load instruction(s) ;; store store instruction(s) ;; move data movement within same register set ;; xfer transfer to/from coprocessor ;; hilo transfer of hi/lo registers ;; arith integer arithmetic instruction ;; darith double precision integer arithmetic instructions ;; imul integer multiply ;; idiv integer divide ;; icmp integer compare ;; fadd floating point add/subtract ;; fmul floating point multiply ;; fdiv floating point divide ;; fabs floating point absolute value ;; fneg floating point negation ;; fcmp floating point compare ;; fcvt floating point convert ;; fsqrt floating point square root ;; multi multiword sequence (or user asm statements) ;; nop no operation ;; pic OSF/rose half pic load

(define_attr "type" "unknown,branch,jump,call,load,store,move,xfer,hilo,arith,darith,imul,idiv,icmp,fadd,fmul,fdiv,fabs,fneg,fcmp,fcvt,fsqrt,multi,nop,pic" (const_string "unknown"))

;; Main data type used by the insn (define_attr "mode" "unknown,none,QI,HI,SI,DI,SF,DF,FPSW" (const_string "unknown"))

;; # instructions (4 bytes each) (define_attr "length" "" (const_int 1))

;; whether or not an instruction has a mandatory delay slot (define_attr "dslot" "no,yes" (if_then_else (eq_attr "type" "branch,jump,call,load,xfer,hilo,fcmp,pic") (const_string "yes") (const_string "no")))

;; Attribute describing the processor (define_attr "cpu" "default,r3000,r4000,r6000" (const (cond [(eq (symbol_ref "mips_cpu") (symbol_ref "PROCESSOR_DEFAULT")) (const_string "default") (eq (symbol_ref "mips_cpu") (symbol_ref "PROCESSOR_R3000")) (const_string "r3000") (eq (symbol_ref "mips_cpu") (symbol_ref "PROCESSOR_R4000")) (const_string "r4000") (eq (symbol_ref "mips_cpu") (symbol_ref "PROCESSOR_R6000")) (const_string "r6000")] (const_string "default"))))

;; Attribute defining whether or not we can use the branch-likely instructions ;; (MIPS ISA level 2)

(define_attr "branch_likely" "no,yes" (const (if_then_else (ge (symbol_ref "mips_isa") (const_int 2)) (const_string "yes") (const_string "no"))))

;; Describe a user's asm statement. (define_asm_attributes [(set_attr "type" "multi")])

;; ......................... ;; ;; Delay slots, can't describe load/fcmp/xfer delay slots here ;; ;; .........................

(define_delay (eq_attr "type" "branch") [(and (eq_attr "dslot" "no") (eq_attr "length" "1")) (nil) (and (eq_attr "branch_likely" "yes") (and (eq_attr "dslot" "no") (eq_attr "length" "1")))])

(define_delay (eq_attr "type" "call,jump") [(and (eq_attr "dslot" "no") (eq_attr "length" "1")) (nil) (nil)])

;; ......................... ;; ;; Functional units ;; ;; .........................

; (define_function_unit NAME MULTIPLICITY SIMULTANEITY ; TEST READY-DELAY BUSY-DELAY [CONFLICT-LIST])

;; Make the default case (PROCESSOR_DEFAULT) handle the worst case

(define_function_unit "memory" 1 0 (and (eq_attr "type" "load,pic") (eq_attr "cpu" "!r3000")) 3 0)

(define_function_unit "memory" 1 0 (and (eq_attr "type" "load,pic") (eq_attr "cpu" "r3000")) 2 0)

(define_function_unit "memory" 1 0 (eq_attr "type" "store") 1 0)

(define_function_unit "fp_comp" 1 0 (eq_attr "type" "fcmp") 2 0)

(define_function_unit "transfer" 1 0 (eq_attr "type" "xfer") 2 0) (define_function_unit "transfer" 1 0 (eq_attr "type" "hilo") 3 0)

(define_function_unit "imuldiv" 1 1 (and (eq_attr "type" "imul") (eq_attr "cpu" "!r3000,r4000")) 17 34)

(define_function_unit "imuldiv" 1 1 (and (eq_attr "type" "imul") (eq_attr "cpu" "r3000")) 12 24)

(define_function_unit "imuldiv" 1 1 (and (eq_attr "type" "imul") (eq_attr "cpu" "r4000")) 10 20)

(define_function_unit "imuldiv" 1 1 (and (eq_attr "type" "idiv") (eq_attr "cpu" "!r3000,r4000")) 38 76)

(define_function_unit "imuldiv" 1 1 (and (eq_attr "type" "idiv") (eq_attr "cpu" "r3000")) 35 70)

(define_function_unit "imuldiv" 1 1 (and (eq_attr "type" "idiv") (eq_attr "cpu" "r4000")) 69 138)

(define_function_unit "adder" 1 1 (and (eq_attr "type" "fadd") (eq_attr "cpu" "!r3000,r6000")) 4 8)

(define_function_unit "adder" 1 1 (and (eq_attr "type" "fadd") (eq_attr "cpu" "r3000")) 2 4)

(define_function_unit "adder" 1 1 (and (eq_attr "type" "fadd") (eq_attr "cpu" "r6000")) 3 6)

(define_function_unit "fast" 1 1 (and (eq_attr "type" "fabs,fneg") (eq_attr "cpu" "!r3000")) 2 4)

(define_function_unit "fast" 1 1 (and (eq_attr "type" "fabs,fneg") (eq_attr "cpu" "r3000")) 1 2)

(define_function_unit "mult" 1 1 (and (eq_attr "type" "fmul") (and (eq_attr "mode" "SF") (eq_attr "cpu" "!r3000,r6000"))) 7 14)

(define_function_unit "mult" 1 1 (and (eq_attr "type" "fmul") (and (eq_attr "mode" "SF") (eq_attr "cpu" "r3000"))) 4 8)

(define_function_unit "mult" 1 1 (and (eq_attr "type" "fmul") (and (eq_attr "mode" "SF") (eq_attr "cpu" "r6000"))) 5 10)

(define_function_unit "mult" 1 1 (and (eq_attr "type" "fmul") (and (eq_attr "mode" "DF") (eq_attr "cpu" "!r3000,r6000"))) 8 16)

(define_function_unit "mult" 1 1 (and (eq_attr "type" "fmul") (and (eq_attr "mode" "DF") (eq_attr "cpu" "r3000"))) 5 10)

(define_function_unit "mult" 1 1 (and (eq_attr "type" "fmul") (and (eq_attr "mode" "DF") (eq_attr "cpu" "r6000"))) 6 12)

(define_function_unit "divide" 1 1 (and (eq_attr "type" "fdiv") (and (eq_attr "mode" "SF") (eq_attr "cpu" "!r3000,r6000"))) 23 46)

(define_function_unit "divide" 1 1 (and (eq_attr "type" "fdiv") (and (eq_attr "mode" "SF") (eq_attr "cpu" "r3000"))) 12 24)

(define_function_unit "divide" 1 1 (and (eq_attr "type" "fdiv") (and (eq_attr "mode" "SF") (eq_attr "cpu" "r6000"))) 15 30)

(define_function_unit "divide" 1 1 (and (eq_attr "type" "fdiv") (and (eq_attr "mode" "DF") (eq_attr "cpu" "!r3000,r6000"))) 36 72)

(define_function_unit "divide" 1 1 (and (eq_attr "type" "fdiv") (and (eq_attr "mode" "DF") (eq_attr "cpu" "r3000"))) 19 34)

(define_function_unit "divide" 1 1 (and (eq_attr "type" "fdiv") (and (eq_attr "mode" "DF") (eq_attr "cpu" "r6000"))) 16 32)

(define_function_unit "sqrt" 1 1 (and (eq_attr "type" "fsqrt") (eq_attr "mode" "SF")) 54 108) (define_function_unit "sqrt" 1 1 (and (eq_attr "type" "fsqrt") (eq_attr "mode" "DF")) 112 224)

;; ;; .................... ;; ;; ADDITION ;; ;; .................... ;;

(define_insn "adddf3" [(set (match_operand:DF 0 "register_operand" "=f") (plus:DF (match_operand:DF 1 "register_operand" "f") (match_operand:DF 2 "register_operand" "f")))] "TARGET_HARD_FLOAT" "add.d\t%0,%1,%2" [(set_attr "type" "fadd") (set_attr "mode" "DF") (set_attr "length" "1")])

(define_insn "addsf3" [(set (match_operand:SF 0 "register_operand" "=f") (plus:SF (match_operand:SF 1 "register_operand" "f") (match_operand:SF 2 "register_operand" "f")))] "TARGET_HARD_FLOAT" "add.s\t%0,%1,%2" [(set_attr "type" "fadd") (set_attr "mode" "SF") (set_attr "length" "1")])

(define_insn "addsi3" [(set (match_operand:SI 0 "register_operand" "=d") (plus:SI (match_operand:SI 1 "arith_operand" "%d") (match_operand:SI 2 "arith_operand" "dI")))] "" "* { return (GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) < 0) ? "subu\t%0,%1,%n2" : "addu\t%0,%1,%2"; }" [(set_attr "type" "arith") (set_attr "mode" "SI") (set_attr "length" "1")])

(define_expand "adddi3" [(parallel [(set (match_operand:DI 0 "register_operand" "") (plus:DI (match_operand:DI 1 "register_operand" "") (match_operand:DI 2 "arith_operand" ""))) (clobber (match_dup 3))])] "!TARGET_DEBUG_G_MODE" "operands[3] = gen_reg_rtx (SImode);")

(define_insn "adddi3_internal_1" [(set (match_operand:DI 0 "register_operand" "=d,&d") (plus:DI (match_operand:DI 1 "register_operand" "0,d") (match_operand:DI 2 "register_operand" "d,d"))) (clobber (match_operand:SI 3 "register_operand" "=d,d"))] "!TARGET_DEBUG_G_MODE" "* { return (REGNO (operands[0]) == REGNO (operands[1]) && REGNO (operands[0]) == REGNO (operands[2])) ? "srl\t%3,%L0,31;sll\t%M0,%M0,1;sll\t%L0,%L1,1;addu\t%M0,%M0,%3" : "addu\t%L0,%L1,%L2;sltu\t%3,%L0,%L2;addu\t%M0,%M1,%M2;addu\t%M0,%M0,%3"; }" [(set_attr "type" "darith,darith") (set_attr "mode" "DI,DI") (set_attr "length" "4,4")])

(define_split [(set (match_operand:DI 0 "register_operand" "") (plus:DI (match_operand:DI 1 "register_operand" "") (match_operand:DI 2 "register_operand" ""))) (clobber (match_operand:SI 3 "register_operand" ""))] "reload_completed && !WORDS_BIG_ENDIAN && !TARGET_DEBUG_D_MODE && !TARGET_DEBUG_G_MODE && GET_CODE (operands[0]) == REG && GP_REG_P (REGNO (operands[0])) && GET_CODE (operands[1]) == REG && GP_REG_P (REGNO (operands[1])) && GET_CODE (operands[2]) == REG && GP_REG_P (REGNO (operands[2])) && (REGNO (operands[0]) != REGNO (operands[1]) || REGNO (operands[0]) != REGNO (operands[2]))"

[(set (subreg:SI (match_dup 0) 0) (plus:SI (subreg:SI (match_dup 1) 0) (subreg:SI (match_dup 2) 0)))

(set (match_dup 3) (ltu:SI (subreg:SI (match_dup 0) 0) (subreg:SI (match_dup 2) 0)))

(set (subreg:SI (match_dup 0) 1) (plus:SI (subreg:SI (match_dup 1) 1) (subreg:SI (match_dup 2) 1)))

(set (subreg:SI (match_dup 0) 1) (plus:SI (subreg:SI (match_dup 0) 1) (match_dup 3)))] "")

(define_split [(set (match_operand:DI 0 "register_operand" "") (plus:DI (match_operand:DI 1 "register_operand" "") (match_operand:DI 2 "register_operand" ""))) (clobber (match_operand:SI 3 "register_operand" ""))] "reload_completed && WORDS_BIG_ENDIAN && !TARGET_DEBUG_D_MODE && !TARGET_DEBUG_G_MODE && GET_CODE (operands[0]) == REG && GP_REG_P (REGNO (operands[0])) && GET_CODE (operands[1]) == REG && GP_REG_P (REGNO (operands[1])) && GET_CODE (operands[2]) == REG && GP_REG_P (REGNO (operands[2])) && (REGNO (operands[0]) != REGNO (operands[1]) || REGNO (operands[0]) != REGNO (operands[2]))"

[(set (subreg:SI (match_dup 0) 1) (plus:SI (subreg:SI (match_dup 1) 1) (subreg:SI (match_dup 2) 1)))

(set (match_dup 3) (ltu:SI (subreg:SI (match_dup 0) 1) (subreg:SI (match_dup 2) 1)))

(set (subreg:SI (match_dup 0) 0) (plus:SI (subreg:SI (match_dup 1) 0) (subreg:SI (match_dup 2) 0)))

(set (subreg:SI (match_dup 0) 0) (plus:SI (subreg:SI (match_dup 0) 0) (match_dup 3)))] "")

(define_insn "adddi3_internal_2" [(set (match_operand:DI 0 "register_operand" "=d,d,d") (plus:DI (match_operand:DI 1 "register_operand" "%d,%d,%d") (match_operand:DI 2 "small_int" "P,J,N"))) (clobber (match_operand:SI 3 "register_operand" "=d,d,d"))] "!TARGET_DEBUG_G_MODE && INTVAL (operands[2]) != -32768" "@ addu\t%L0,%L1,%2;sltu\t%3,%L0,%2;addu\t%M0,%M1,%3 move\t%L0,%L1;move\t%M0,%M1 subu\t%L0,%L1,%n2;sltu\t%3,%L0,%2;subu\t%M0,%M1,1;addu\t%M0,%M0,%3" [(set_attr "type" "darith,darith,darith") (set_attr "mode" "DI,DI,DI") (set_attr "length" "3,2,4")])

(define_split [(set (match_operand:DI 0 "register_operand" "") (plus:DI (match_operand:DI 1 "register_operand" "") (match_operand:DI 2 "small_int" ""))) (clobber (match_operand:SI 3 "register_operand" "=d"))] "reload_completed && !WORDS_BIG_ENDIAN && !TARGET_DEBUG_D_MODE && !TARGET_DEBUG_G_MODE && GET_CODE (operands[0]) == REG && GP_REG_P (REGNO (operands[0])) && GET_CODE (operands[1]) == REG && GP_REG_P (REGNO (operands[1])) && INTVAL (operands[2]) > 0"

[(set (subreg:SI (match_dup 0) 0) (plus:SI (subreg:SI (match_dup 1) 0) (match_dup 2)))

(set (match_dup 3) (ltu:SI (subreg:SI (match_dup 0) 0) (match_dup 2)))

(set (subreg:SI (match_dup 0) 1) (plus:SI (subreg:SI (match_dup 1) 1) (match_dup 3)))] "")

(define_split [(set (match_operand:DI 0 "register_operand" "") (plus:DI (match_operand:DI 1 "register_operand" "") (match_operand:DI 2 "small_int" ""))) (clobber (match_operand:SI 3 "register_operand" "=d"))] "reload_completed && WORDS_BIG_ENDIAN && !TARGET_DEBUG_D_MODE && !TARGET_DEBUG_G_MODE && GET_CODE (operands[0]) == REG && GP_REG_P (REGNO (operands[0])) && GET_CODE (operands[1]) == REG && GP_REG_P (REGNO (operands[1])) && INTVAL (operands[2]) > 0"

[(set (subreg:SI (match_dup 0) 1) (plus:SI (subreg:SI (match_dup 1) 1) (match_dup 2)))

(set (match_dup 3) (ltu:SI (subreg:SI (match_dup 0) 1) (match_dup 2)))

(set (subreg:SI (match_dup 0) 0) (plus:SI (subreg:SI (match_dup 1) 0) (match_dup 3)))] "") ;; ;; .................... ;; ;; SUBTRACTION ;; ;; .................... ;;

(define_insn "subdf3" [(set (match_operand:DF 0 "register_operand" "=f") (minus:DF (match_operand:DF 1 "register_operand" "f") (match_operand:DF 2 "register_operand" "f")))] "TARGET_HARD_FLOAT" "sub.d\t%0,%1,%2" [(set_attr "type" "fadd") (set_attr "mode" "DF") (set_attr "length" "1")])

(define_insn "subsf3" [(set (match_operand:SF 0 "register_operand" "=f") (minus:SF (match_operand:SF 1 "register_operand" "f") (match_operand:SF 2 "register_operand" "f")))] "TARGET_HARD_FLOAT" "sub.s\t%0,%1,%2" [(set_attr "type" "fadd") (set_attr "mode" "SF") (set_attr "length" "1")])

(define_insn "subsi3" [(set (match_operand:SI 0 "register_operand" "=d") (minus:SI (match_operand:SI 1 "reg_or_0_operand" "dJ") (match_operand:SI 2 "arith_operand" "dI")))] "" "* { return (GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) < 0) ? "addu\t%0,%z1,%n2" : "subu\t%0,%z1,%2"; }" [(set_attr "type" "arith") (set_attr "mode" "SI") (set_attr "length" "1")])

(define_expand "subdi3" [(parallel [(set (match_operand:DI 0 "register_operand" "=d") (minus:DI (match_operand:DI 1 "register_operand" "d") (match_operand:DI 2 "register_operand" "d"))) (clobber (match_dup 3))])] "!TARGET_DEBUG_G_MODE" "operands[3] = gen_reg_rtx (SImode);")

(define_insn "subdi3_internal" [(set (match_operand:DI 0 "register_operand" "=d") (minus:DI (match_operand:DI 1 "register_operand" "d") (match_operand:DI 2 "register_operand" "d"))) (clobber (match_operand:SI 3 "register_operand" "=d"))] "!TARGET_DEBUG_G_MODE" "sltu\t%3,%L1,%L2;subu\t%L0,%L1,%L2;subu\t%M0,%M1,%M2;subu\t%M0,%M0,%3" [(set_attr "type" "darith") (set_attr "mode" "DI") (set_attr "length" "4")])

(define_split [(set (match_operand:DI 0 "register_operand" "") (minus:DI (match_operand:DI 1 "register_operand" "") (match_operand:DI 2 "register_operand" ""))) (clobber (match_operand:SI 3 "register_operand" ""))] "reload_completed && !WORDS_BIG_ENDIAN && !TARGET_DEBUG_D_MODE && !TARGET_DEBUG_G_MODE && GET_CODE (operands[0]) == REG && GP_REG_P (REGNO (operands[0])) && GET_CODE (operands[1]) == REG && GP_REG_P (REGNO (operands[1])) && GET_CODE (operands[2]) == REG && GP_REG_P (REGNO (operands[2]))"

[(set (match_dup 3) (ltu:SI (subreg:SI (match_dup 1) 0) (subreg:SI (match_dup 2) 0)))

(set (subreg:SI (match_dup 0) 0) (minus:SI (subreg:SI (match_dup 1) 0) (subreg:SI (match_dup 2) 0)))

(set (subreg:SI (match_dup 0) 1) (minus:SI (subreg:SI (match_dup 1) 1) (subreg:SI (match_dup 2) 1)))

(set (subreg:SI (match_dup 0) 1) (minus:SI (subreg:SI (match_dup 0) 1) (match_dup 3)))] "")

(define_split [(set (match_operand:DI 0 "register_operand" "") (minus:DI (match_operand:DI 1 "register_operand" "") (match_operand:DI 2 "register_operand" ""))) (clobber (match_operand:SI 3 "register_operand" ""))] "reload_completed && WORDS_BIG_ENDIAN && !TARGET_DEBUG_D_MODE && !TARGET_DEBUG_G_MODE && GET_CODE (operands[0]) == REG && GP_REG_P (REGNO (operands[0])) && GET_CODE (operands[1]) == REG && GP_REG_P (REGNO (operands[1])) && GET_CODE (operands[2]) == REG && GP_REG_P (REGNO (operands[2]))"

[(set (match_dup 3) (ltu:SI (subreg:SI (match_dup 1) 1) (subreg:SI (match_dup 2) 1)))

(set (subreg:SI (match_dup 0) 1) (minus:SI (subreg:SI (match_dup 1) 1) (subreg:SI (match_dup 2) 1)))

(set (subreg:SI (match_dup 0) 0) (minus:SI (subreg:SI (match_dup 1) 0) (subreg:SI (match_dup 2) 0)))

(set (subreg:SI (match_dup 0) 0) (minus:SI (subreg:SI (match_dup 0) 0) (match_dup 3)))] "")

(define_insn "subdi3_internal_2" [(set (match_operand:DI 0 "register_operand" "=d,d,d") (minus:DI (match_operand:DI 1 "register_operand" "d,d,d") (match_operand:DI 2 "small_int" "P,J,N"))) (clobber (match_operand:SI 3 "register_operand" "=d,d,d"))] "!TARGET_DEBUG_G_MODE && INTVAL (operands[2]) != -32768" "@ sltu\t%3,%L1,%2;subu\t%L0,%L1,%2;subu\t%M0,%M1,%3 move\t%L0,%L1;move\t%M0,%M1 sltu\t%3,%L1,%2;subu\t%L0,%L1,%2;subu\t%M0,%M1,1;subu\t%M0,%M0,%3" [(set_attr "type" "darith,darith,darith") (set_attr "mode" "DI,DI,DI") (set_attr "length" "3,2,4")])

(define_split [(set (match_operand:DI 0 "register_operand" "") (minus:DI (match_operand:DI 1 "register_operand" "") (match_operand:DI 2 "small_int" ""))) (clobber (match_operand:SI 3 "register_operand" ""))] "reload_completed && !WORDS_BIG_ENDIAN && !TARGET_DEBUG_D_MODE && !TARGET_DEBUG_G_MODE && GET_CODE (operands[0]) == REG && GP_REG_P (REGNO (operands[0])) && GET_CODE (operands[1]) == REG && GP_REG_P (REGNO (operands[1])) && INTVAL (operands[2]) > 0"

[(set (match_dup 3) (ltu:SI (subreg:SI (match_dup 1) 0) (match_dup 2)))

(set (subreg:SI (match_dup 0) 0) (minus:SI (subreg:SI (match_dup 1) 0) (match_dup 2)))

(set (subreg:SI (match_dup 0) 1) (minus:SI (subreg:SI (match_dup 1) 1) (match_dup 3)))] "")

(define_split [(set (match_operand:DI 0 "register_operand" "") (minus:DI (match_operand:DI 1 "register_operand" "") (match_operand:DI 2 "small_int" ""))) (clobber (match_operand:SI 3 "register_operand" ""))] "reload_completed && WORDS_BIG_ENDIAN && !TARGET_DEBUG_D_MODE && !TARGET_DEBUG_G_MODE && GET_CODE (operands[0]) == REG && GP_REG_P (REGNO (operands[0])) && GET_CODE (operands[1]) == REG && GP_REG_P (REGNO (operands[1])) && INTVAL (operands[2]) > 0"

[(set (match_dup 3) (ltu:SI (subreg:SI (match_dup 1) 1) (match_dup 2)))

(set (subreg:SI (match_dup 0) 1) (minus:SI (subreg:SI (match_dup 1) 1) (match_dup 2)))

(set (subreg:SI (match_dup 0) 0) (minus:SI (subreg:SI (match_dup 1) 0) (match_dup 3)))] "")

;; ;; .................... ;; ;; MULTIPLICATION ;; ;; .................... ;;

(define_insn "muldf3" [(set (match_operand:DF 0 "register_operand" "=f") (mult:DF (match_operand:DF 1 "register_operand" "f") (match_operand:DF 2 "register_operand" "f")))] "TARGET_HARD_FLOAT" "mul.d\t%0,%1,%2" [(set_attr "type" "fmul") (set_attr "mode" "DF") (set_attr "length" "1")])

(define_insn "mulsf3" [(set (match_operand:SF 0 "register_operand" "=f") (mult:SF (match_operand:SF 1 "register_operand" "f") (match_operand:SF 2 "register_operand" "f")))] "TARGET_HARD_FLOAT" "mul.s\t%0,%1,%2" [(set_attr "type" "fmul") (set_attr "mode" "SF") (set_attr "length" "1")])

(define_insn "mulsi3" [(set (match_operand:SI 0 "register_operand" "=d") (mult:SI (match_operand:SI 1 "register_operand" "d") (match_operand:SI 2 "register_operand" "d"))) (clobber (reg:SI 64)) (clobber (reg:SI 65))] "" "* { rtx xoperands[10];

xoperands[0] = operands[0]; xoperands[1] = gen_rtx (REG, SImode, LO_REGNUM);

output_asm_insn ("mult\t%1,%2", operands); output_asm_insn (mips_move_1word (xoperands, insn), xoperands); return ""; }" [(set_attr "type" "imul") (set_attr "mode" "SI") (set_attr "length" "3")]) ;; mult + mflo + delay

(define_split [(set (match_operand:SI 0 "register_operand" "") (mult:SI (match_operand:SI 1 "register_operand" "") (match_operand:SI 2 "register_operand" ""))) (clobber (reg:SI 64)) (clobber (reg:SI 65))] "!TARGET_DEBUG_D_MODE" [(parallel [(set (reg:SI 65) ;; low register (mult:SI (match_dup 1) (match_dup 2))) (clobber (reg:SI 64))]) (set (match_dup 0) (reg:SI 65))] "")

(define_insn "mulsi3_internal" [(set (reg:SI 65) ;; low register (mult:SI (match_operand:SI 0 "register_operand" "d") (match_operand:SI 1 "register_operand" "d"))) (clobber (reg:SI 64))] "" "mult\t%0,%1" [(set_attr "type" "imul") (set_attr "mode" "SI") (set_attr "length" "1")])

(define_insn "mulsidi3" [(set (match_operand:DI 0 "register_operand" "=d") (mult:DI (sign_extend:DI (match_operand:SI 1 "register_operand" "d")) (sign_extend:DI (match_operand:SI 2 "register_operand" "d")))) (clobber (reg:DI 64))] "" "* { rtx xoperands[10];

xoperands[0] = operands[0]; xoperands[1] = gen_rtx (REG, DImode, MD_REG_FIRST);

output_asm_insn ("mult\t%1,%2", operands); output_asm_insn (mips_move_2words (xoperands, insn), xoperands); return ""; }" [(set_attr "type" "imul") (set_attr "mode" "SI") (set_attr "length" "4")]) ;; mult + mflo + mfhi + delay

(define_insn "umulsidi3" [(set (match_operand:DI 0 "register_operand" "=d") (mult:DI (zero_extend:DI (match_operand:SI 1 "register_operand" "d")) (zero_extend:DI (match_operand:SI 2 "register_operand" "d")))) (clobber (reg:DI 64))] "" "* { rtx xoperands[10];

xoperands[0] = operands[0]; xoperands[1] = gen_rtx (REG, DImode, MD_REG_FIRST);

output_asm_insn ("multu\t%1,%2", operands); output_asm_insn (mips_move_2words (xoperands, insn), xoperands); return ""; }" [(set_attr "type" "imul") (set_attr "mode" "SI") (set_attr "length" "4")]) ;; mult + mflo + mfhi + delay

;; ;; .................... ;; ;; DIVISION and REMAINDER ;; ;; .................... ;;

(define_insn "divdf3" [(set (match_operand:DF 0 "register_operand" "=f") (div:DF (match_operand:DF 1 "register_operand" "f") (match_operand:DF 2 "register_operand" "f")))] "TARGET_HARD_FLOAT" "div.d\t%0,%1,%2" [(set_attr "type" "fdiv") (set_attr "mode" "DF") (set_attr "length" "1")])

(define_insn "divsf3" [(set (match_operand:SF 0 "register_operand" "=f") (div:SF (match_operand:SF 1 "register_operand" "f") (match_operand:SF 2 "register_operand" "f")))] "TARGET_HARD_FLOAT" "div.s\t%0,%1,%2" [(set_attr "type" "fdiv") (set_attr "mode" "SF") (set_attr "length" "1")])

;; If optimizing, prefer the divmod functions over separate div and ;; mod functions, since this will allow using one instruction for both ;; the quotient and remainder. At present, the divmod is not moved out ;; of loops if it is constant within the loop, so allow -mdebugc to ;; use the old method of doing things.

;; 64 is the multiply/divide hi register ;; 65 is the multiply/divide lo register

(define_insn "divmodsi4" [(set (match_operand:SI 0 "register_operand" "=d") (div:SI (match_operand:SI 1 "register_operand" "d") (match_operand:SI 2 "register_operand" "d"))) (set (match_operand:SI 3 "register_operand" "=d") (mod:SI (match_dup 1) (match_dup 2))) (clobber (reg:SI 64)) (clobber (reg:SI 65))] "optimize" "* { if (find_reg_note (insn, REG_UNUSED, operands[3])) return "div\t%0,%1,%2";

if (find_reg_note (insn, REG_UNUSED, operands[0])) return "rem\t%3,%1,%2";

return "div\t%0,%1,%2;mfhi\t%3"; }" [(set_attr "type" "idiv") (set_attr "mode" "SI") (set_attr "length" "13")]) ;; various tests for dividing by 0 and such

(define_insn "udivmodsi4" [(set (match_operand:SI 0 "register_operand" "=d") (udiv:SI (match_operand:SI 1 "register_operand" "d") (match_operand:SI 2 "register_operand" "d"))) (set (match_operand:SI 3 "register_operand" "=d") (umod:SI (match_dup 1) (match_dup 2))) (clobber (reg:SI 64)) (clobber (reg:SI 65))] "optimize" "* { if (find_reg_note (insn, REG_UNUSED, operands[3])) return "divu\t%0,%1,%2";

if (find_reg_note (insn, REG_UNUSED, operands[0])) return "remu\t%3,%1,%2";

return "divu\t%0,%1,%2;mfhi\t%3"; }" [(set_attr "type" "idiv") (set_attr "mode" "SI") (set_attr "length" "13")]) ;; various tests for dividing by 0 and such

(define_insn "divsi3" [(set (match_operand:SI 0 "register_operand" "=d") (div:SI (match_operand:SI 1 "register_operand" "d") (match_operand:SI 2 "register_operand" "d"))) (clobber (reg:SI 64)) (clobber (reg:SI 65))] "!optimize" "div\t%0,%1,%2" [(set_attr "type" "idiv") (set_attr "mode" "SI") (set_attr "length" "13")]) ;; various tests for dividing by 0 and such

(define_insn "modsi3" [(set (match_operand:SI 0 "register_operand" "=d") (mod:SI (match_operand:SI 1 "register_operand" "d") (match_operand:SI 2 "register_operand" "d"))) (clobber (reg:SI 64)) (clobber (reg:SI 65))] "!optimize" "rem\t%0,%1,%2" [(set_attr "type" "idiv") (set_attr "mode" "SI") (set_attr "length" "14")]) ;; various tests for dividing by 0 and such

(define_insn "udivsi3" [(set (match_operand:SI 0 "register_operand" "=d") (udiv:SI (match_operand:SI 1 "register_operand" "d") (match_operand:SI 2 "register_operand" "d"))) (clobber (reg:SI 64)) (clobber (reg:SI 65))] "!optimize" "divu\t%0,%1,%2" [(set_attr "type" "idiv") (set_attr "mode" "SI") (set_attr "length" "14")]) ;; various tests for dividing by 0 and such

(define_insn "umodsi3" [(set (match_operand:SI 0 "register_operand" "=d") (umod:SI (match_operand:SI 1 "register_operand" "d") (match_operand:SI 2 "register_operand" "d"))) (clobber (reg:SI 64)) (clobber (reg:SI 65))] "!optimize" "remu\t%0,%1,%2" [(set_attr "type" "idiv") (set_attr "mode" "SI") (set_attr "length" "14")]) ;; various tests for dividing by 0 and such

;; ;; .................... ;; ;; SQUARE ROOT ;; ;; ....................

(define_insn "sqrtdf2" [(set (match_operand:DF 0 "register_operand" "=f") (sqrt:DF (match_operand:DF 1 "register_operand" "f")))] "TARGET_HARD_FLOAT && HAVE_SQRT_P()" "sqrt.d\t%0,%1" [(set_attr "type" "fabs") (set_attr "mode" "DF") (set_attr "length" "1")])

(define_insn "sqrtsf2" [(set (match_operand:SF 0 "register_operand" "=f") (sqrt:SF (match_operand:SF 1 "register_operand" "f")))] "TARGET_HARD_FLOAT && HAVE_SQRT_P()" "sqrt.s\t%0,%1" [(set_attr "type" "fabs") (set_attr "mode" "SF") (set_attr "length" "1")])

;; ;; .................... ;; ;; ABSOLUTE VALUE ;; ;; ....................

;; Do not use the integer abs macro instruction, since that signals an ;; exception on -2147483648 (sigh).

(define_insn "abssi2" [(set (match_operand:SI 0 "register_operand" "=d") (abs:SI (match_operand:SI 1 "register_operand" "d")))] "" "* { dslots_jump_total++; dslots_jump_filled++; operands[2] = const0_rtx;

return (REGNO (operands[0]) == REGNO (operands[1])) ? "bgez\t%1,1f%#\n\tsubu\t%0,%z2,%0\n1:" : "%(bgez\t%1,1f\n\tmove\t%0,%1\n\tsubu\t%0,%z2,%0\n1:%)"; }" [(set_attr "type" "multi") (set_attr "mode" "SI") (set_attr "length" "3")])

(define_insn "absdf2" [(set (match_operand:DF 0 "register_operand" "=f") (abs:DF (match_operand:DF 1 "register_operand" "f")))] "TARGET_HARD_FLOAT" "abs.d\t%0,%1" [(set_attr "type" "fabs") (set_attr "mode" "DF") (set_attr "length" "1")])

(define_insn "abssf2" [(set (match_operand:SF 0 "register_operand" "=f") (abs:SF (match_operand:SF 1 "register_operand" "f")))] "TARGET_HARD_FLOAT" "abs.s\t%0,%1" [(set_attr "type" "fabs") (set_attr "mode" "SF") (set_attr "length" "1")])

;; ;; .................... ;; ;; FIND FIRST BIT INSTRUCTION ;; ;; .................... ;;

(define_insn "ffssi2" [(set (match_operand:SI 0 "register_operand" "=&d") (ffs:SI (match_operand:SI 1 "register_operand" "d"))) (clobber (match_scratch:SI 2 "d")) (clobber (match_scratch:SI 3 "d"))] "" "* { dslots_jump_total += 2; dslots_jump_filled += 2; operands[4] = const0_rtx;

if (optimize && find_reg_note (insn, REG_DEAD, operands[1])) return "%(\ move\t%0,%z4\n\ \tbeq\t%1,%z4,2f\n\ 1:\tand\t%2,%1,0x0001\n\ \taddu\t%0,%0,1\n\ \tbeq\t%2,%z4,1b\n\ \tsrl\t%1,%1,1\n\ 2:%)";

return "%(\ move\t%0,%z4\n\ \tmove\t%3,%1\n\ \tbeq\t%3,%z4,2f\n\ 1:\tand\t%2,%3,0x0001\n\ \taddu\t%0,%0,1\n\ \tbeq\t%2,%z4,1b\n\ \tsrl\t%3,%3,1\n\ 2:%)"; }" [(set_attr "type" "multi") (set_attr "mode" "SI") (set_attr "length" "6")])

;; ;; .................... ;; ;; NEGATION and ONE'S COMPLEMENT ;; ;; ....................

(define_insn "negsi2" [(set (match_operand:SI 0 "register_operand" "=d") (neg:SI (match_operand:SI 1 "register_operand" "d")))] "" "* { operands[2] = const0_rtx; return "subu\t%0,%z2,%1"; }" [(set_attr "type" "arith") (set_attr "mode" "SI") (set_attr "length" "1")])

(define_expand "negdi3" [(parallel [(set (match_operand:DI 0 "register_operand" "=d") (neg:DI (match_operand:DI 1 "register_operand" "d"))) (clobber (match_dup 2))])] "!TARGET_DEBUG_G_MODE" "operands[2] = gen_reg_rtx (SImode);")

(define_insn "negdi3_internal" [(set (match_operand:DI 0 "register_operand" "=d") (neg:DI (match_operand:DI 1 "register_operand" "d"))) (clobber (match_operand:SI 2 "register_operand" "=d"))] "!TARGET_DEBUG_G_MODE" "* { operands[3] = const0_rtx; return "subu\t%L0,%z3,%L1;subu\t%M0,%z3,%M1;sltu\t%2,%z3,%L0;subu\t%M0,%M0,%2"; }" [(set_attr "type" "darith") (set_attr "mode" "DI") (set_attr "length" "4")])

(define_insn "negdf2" [(set (match_operand:DF 0 "register_operand" "=f") (neg:DF (match_operand:DF 1 "register_operand" "f")))] "TARGET_HARD_FLOAT" "neg.d\t%0,%1" [(set_attr "type" "fneg") (set_attr "mode" "DF") (set_attr "length" "1")])

(define_insn "negsf2" [(set (match_operand:SF 0 "register_operand" "=f") (neg:SF (match_operand:SF 1 "register_operand" "f")))] "TARGET_HARD_FLOAT" "neg.s\t%0,%1" [(set_attr "type" "fneg") (set_attr "mode" "SF") (set_attr "length" "1")])

(define_insn "one_cmplsi2" [(set (match_operand:SI 0 "register_operand" "=d") (not:SI (match_operand:SI 1 "register_operand" "d")))] "" "* { operands[2] = const0_rtx; return "nor\t%0,%z2,%1"; }" [(set_attr "type" "arith") (set_attr "mode" "SI") (set_attr "length" "1")])

(define_insn "one_cmpldi2" [(set (match_operand:DI 0 "register_operand" "=d") (not:SI (match_operand:DI 1 "register_operand" "d")))] "" "* { operands[2] = const0_rtx; return "nor\t%M0,%z2,%M1;nor\t%L0,%z2,%L1"; }" [(set_attr "type" "darith") (set_attr "mode" "DI") (set_attr "length" "2")])

(define_split [(set (match_operand:DI 0 "register_operand" "") (not:DI (match_operand:DI 1 "register_operand" "")))] "reload_completed && !TARGET_DEBUG_D_MODE && !TARGET_DEBUG_G_MODE && GET_CODE (operands[0]) == REG && GP_REG_P (REGNO (operands[0])) && GET_CODE (operands[1]) == REG && GP_REG_P (REGNO (operands[1]))"

[(set (subreg:SI (match_dup 0) 0) (not:SI (subreg:SI (match_dup 1) 0))) (set (subreg:SI (match_dup 0) 1) (not:SI (subreg:SI (match_dup 1) 1)))] "")

;; Simple hack to recognize the "nor" instruction on the MIPS ;; This must appear before the normal or patterns, so that the ;; combiner will correctly fold things.

(define_insn "norsi3" [(set (match_operand:SI 0 "register_operand" "=d") (not:SI (ior:SI (match_operand:SI 1 "reg_or_0_operand" "dJ") (match_operand:SI 2 "reg_or_0_operand" "dJ"))))] "" "nor\t%0,%z1,%z2" [(set_attr "type" "arith") (set_attr "mode" "SI") (set_attr "length" "1")])

(define_insn "nordi3" [(set (match_operand:DI 0 "register_operand" "=d") (not:DI (ior:DI (match_operand:DI 1 "register_operand" "d") (match_operand:DI 2 "register_operand" "d"))))] "" "nor\t%M0,%M1,%M2;nor\t%L0,%L1,%L2" [(set_attr "type" "darith") (set_attr "mode" "DI") (set_attr "length" "2")])

(define_split [(set (match_operand:DI 0 "register_operand" "") (not:DI (ior:DI (match_operand:DI 1 "register_operand" "") (match_operand:DI 2 "register_operand" ""))))] "reload_completed && !TARGET_DEBUG_D_MODE && !TARGET_DEBUG_G_MODE && GET_CODE (operands[0]) == REG && GP_REG_P (REGNO (operands[0])) && GET_CODE (operands[1]) == REG && GP_REG_P (REGNO (operands[1])) && GET_CODE (operands[2]) == REG && GP_REG_P (REGNO (operands[2]))"

[(set (subreg:SI (match_dup 0) 0) (not:SI (ior:SI (subreg:SI (match_dup 1) 0) (subreg:SI (match_dup 2) 0)))) (set (subreg:SI (match_dup 0) 1) (not:SI (ior:SI (subreg:SI (match_dup 1) 1) (subreg:SI (match_dup 2) 1))))] "")

;; ;; .................... ;; ;; LOGICAL ;; ;; .................... ;;

;; Be more liberal in allowing logical operations than the machine actually ;; supports. This causes better code to be generated for bitfields, since ;; the optimizer can fold things together, at the expense of not moving the ;; constant out of loops.

(define_insn "andsi3" [(set (match_operand:SI 0 "register_operand" "=d,d,?d,?d") (and:SI (match_operand:SI 1 "arith32_operand" "%d,d,d,d") (match_operand:SI 2 "arith32_operand" "d,K,I,M")))] "" "@ and\t%0,%1,%2 andi\t%0,%1,%x2 %[li\t%@,%X2;and\t%0,%1,%@%] %[li\t%@,%X2;and\t%0,%1,%@%]" [(set_attr "type" "arith,arith,multi,multi") (set_attr "mode" "SI,SI,SI,SI") (set_attr "length" "1,1,2,3")])

(define_insn "anddi3" [(set (match_operand:DI 0 "register_operand" "=d") (and:DI (match_operand:DI 1 "register_operand" "d") (match_operand:DI 2 "register_operand" "d")))] "!TARGET_DEBUG_G_MODE" "and\t%M0,%M1,%M2;and\t%L0,%L1,%L2" [(set_attr "type" "darith") (set_attr "mode" "DI") (set_attr "length" "2")])

(define_split [(set (match_operand:DI 0 "register_operand" "") (and:DI (match_operand:DI 1 "register_operand" "") (match_operand:DI 2 "register_operand" "")))] "reload_completed && !TARGET_DEBUG_D_MODE && !TARGET_DEBUG_G_MODE && GET_CODE (operands[0]) == REG && GP_REG_P (REGNO (operands[0])) && GET_CODE (operands[1]) == REG && GP_REG_P (REGNO (operands[1])) && GET_CODE (operands[2]) == REG && GP_REG_P (REGNO (operands[2]))"

[(set (subreg:SI (match_dup 0) 0) (and:SI (subreg:SI (match_dup 1) 0) (subreg:SI (match_dup 2) 0))) (set (subreg:SI (match_dup 0) 1) (and:SI (subreg:SI (match_dup 1) 1) (subreg:SI (match_dup 2) 1)))] "")

(define_insn "iorsi3" [(set (match_operand:SI 0 "register_operand" "=d,d,?d,?d") (ior:SI (match_operand:SI 1 "arith32_operand" "%d,d,d,d") (match_operand:SI 2 "arith32_operand" "d,K,I,M")))] "" "@ or\t%0,%1,%2 ori\t%0,%1,%x2 %[li\t%@,%X2;or\t%0,%1,%@%] %[li\t%@,%X2;or\t%0,%1,%@%]" [(set_attr "type" "arith,arith,multi,multi") (set_attr "mode" "SI,SI,SI,SI") (set_attr "length" "1,1,2,3")])

(define_insn "iordi3" [(set (match_operand:DI 0 "register_operand" "=d") (ior:DI (match_operand:DI 1 "register_operand" "d") (match_operand:DI 2 "register_operand" "d")))] "!TARGET_DEBUG_G_MODE" "or\t%M0,%M1,%M2;or\t%L0,%L1,%L2" [(set_attr "type" "darith") (set_attr "mode" "DI") (set_attr "length" "2")])

(define_split [(set (match_operand:DI 0 "register_operand" "") (ior:DI (match_operand:DI 1 "register_operand" "") (match_operand:DI 2 "register_operand" "")))] "reload_completed && !TARGET_DEBUG_D_MODE && !TARGET_DEBUG_G_MODE && GET_CODE (operands[0]) == REG && GP_REG_P (REGNO (operands[0])) && GET_CODE (operands[1]) == REG && GP_REG_P (REGNO (operands[1])) && GET_CODE (operands[2]) == REG && GP_REG_P (REGNO (operands[2]))"

[(set (subreg:SI (match_dup 0) 0) (ior:SI (subreg:SI (match_dup 1) 0) (subreg:SI (match_dup 2) 0))) (set (subreg:SI (match_dup 0) 1) (ior:SI (subreg:SI (match_dup 1) 1) (subreg:SI (match_dup 2) 1)))] "")

(define_insn "xorsi3" [(set (match_operand:SI 0 "register_operand" "=d,d,?d,?d") (xor:SI (match_operand:SI 1 "arith32_operand" "%d,d,d,d") (match_operand:SI 2 "arith32_operand" "d,K,I,M")))] "" "@ xor\t%0,%1,%2 xori\t%0,%1,%x2 %[li\t%@,%X2;xor\t%0,%1,%@%] %[li\t%@,%X2;xor\t%0,%1,%@%]" [(set_attr "type" "arith,arith,multi,multi") (set_attr "mode" "SI,SI,SI,SI") (set_attr "length" "1,1,2,3")])

(define_insn "xordi3" [(set (match_operand:DI 0 "register_operand" "=d") (xor:DI (match_operand:DI 1 "register_operand" "d") (match_operand:DI 2 "register_operand" "d")))] "!TARGET_DEBUG_G_MODE" "xor\t%M0,%M1,%M2;xor\t%L0,%L1,%L2" [(set_attr "type" "darith") (set_attr "mode" "DI") (set_attr "length" "2")])

(define_split [(set (match_operand:DI 0 "register_operand" "") (xor:DI (match_operand:DI 1 "register_operand" "") (match_operand:DI 2 "register_operand" "")))] "reload_completed && !TARGET_DEBUG_D_MODE && !TARGET_DEBUG_G_MODE && GET_CODE (operands[0]) == REG && GP_REG_P (REGNO (operands[0])) && GET_CODE (operands[1]) == REG && GP_REG_P (REGNO (operands[1])) && GET_CODE (operands[2]) == REG && GP_REG_P (REGNO (operands[2]))"

[(set (subreg:SI (match_dup 0) 0) (xor:SI (subreg:SI (match_dup 1) 0) (subreg:SI (match_dup 2) 0))) (set (subreg:SI (match_dup 0) 1) (xor:SI (subreg:SI (match_dup 1) 1) (subreg:SI (match_dup 2) 1)))] "")

;; ;; .................... ;; ;; TRUNCATION ;; ;; ....................

(define_insn "truncdfsf2" [(set (match_operand:SF 0 "register_operand" "=f") (float_truncate:SF (match_operand:DF 1 "register_operand" "f")))] "TARGET_HARD_FLOAT" "cvt.s.d\t%0,%1" [(set_attr "type" "fcvt") (set_attr "mode" "SF") (set_attr "length" "1")])

;; ;; .................... ;; ;; ZERO EXTENSION ;; ;; ....................

;; Extension insns. ;; Those for integer source operand ;; are ordered widest source type first.

(define_insn "zero_extendhisi2" [(set (match_operand:SI 0 "register_operand" "=d,d,d") (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "d,R,m")))] "" "* { if (which_alternative == 0) return "andi\t%0,%1,0xffff"; else return mips_move_1word (operands, insn, TRUE); }" [(set_attr "type" "arith,load,load") (set_attr "mode" "SI,SI,SI") (set_attr "length" "1,1,2")])

(define_insn "zero_extendqihi2" [(set (match_operand:HI 0 "register_operand" "=d,d,d") (zero_extend:HI (match_operand:QI 1 "nonimmediate_operand" "d,R,m")))] "" "* { if (which_alternative == 0) return "andi\t%0,%1,0x00ff"; else return mips_move_1word (operands, insn, TRUE); }" [(set_attr "type" "arith,load,load") (set_attr "mode" "HI,HI,HI") (set_attr "length" "1,1,2")])

(define_insn "zero_extendqisi2" [(set (match_operand:SI 0 "register_operand" "=d,d,d") (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "d,R,m")))] "" "* { if (which_alternative == 0) return "andi\t%0,%1,0x00ff"; else return mips_move_1word (operands, insn, TRUE); }" [(set_attr "type" "arith,load,load") (set_attr "mode" "SI,SI,SI") (set_attr "length" "1,1,2")])

;; ;; .................... ;; ;; SIGN EXTENSION ;; ;; ....................

;; Extension insns. ;; Those for integer source operand ;; are ordered widest source type first.

;; These patterns originally accepted general_operands, however, slightly ;; better code is generated by only accepting register_operands, and then ;; letting combine generate the lh and lb insns.

(define_expand "extendhisi2" [(set (match_operand:SI 0 "register_operand" "") (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "")))] "" " { if (optimize && GET_CODE (operands[1]) == MEM) operands[1] = force_not_mem (operands[1]);

if (GET_CODE (operands[1]) != MEM) { rtx op1 = gen_lowpart (SImode, operands[1]); rtx temp = gen_reg_rtx (SImode); rtx shift = gen_rtx (CONST_INT, VOIDmode, 16);

  emit_insn (gen_ashlsi3 (temp, op1, shift));
  emit_insn (gen_ashrsi3 (operands[0], temp, shift));
  DONE;
}

}")

(define_insn "extendhisi2_internal" [(set (match_operand:SI 0 "register_operand" "=d,d") (sign_extend:SI (match_operand:HI 1 "memory_operand" "R,m")))] "" "* return mips_move_1word (operands, insn, FALSE);" [(set_attr "type" "load,load") (set_attr "mode" "SI,SI") (set_attr "length" "1,2")])

(define_expand "extendqihi2" [(set (match_operand:HI 0 "register_operand" "") (sign_extend:HI (match_operand:QI 1 "nonimmediate_operand" "")))] "" " { if (optimize && GET_CODE (operands[1]) == MEM) operands[1] = force_not_mem (operands[1]);

if (GET_CODE (operands[1]) != MEM) { rtx op0 = gen_lowpart (SImode, operands[0]); rtx op1 = gen_lowpart (SImode, operands[1]); rtx temp = gen_reg_rtx (SImode); rtx shift = gen_rtx (CONST_INT, VOIDmode, 24);

  emit_insn (gen_ashlsi3 (temp, op1, shift));
  emit_insn (gen_ashrsi3 (op0, temp, shift));
  DONE;
}

}")

(define_insn "extendqihi2_internal" [(set (match_operand:HI 0 "register_operand" "=d,d") (sign_extend:HI (match_operand:QI 1 "memory_operand" "R,m")))] "" "* return mips_move_1word (operands, insn, FALSE);" [(set_attr "type" "load,load") (set_attr "mode" "SI,SI") (set_attr "length" "1,2")])

(define_expand "extendqisi2" [(set (match_operand:SI 0 "register_operand" "") (sign_extend:SI (match_operand:QI 1 "nonimmediate_operand" "")))] "" " { if (optimize && GET_CODE (operands[1]) == MEM) operands[1] = force_not_mem (operands[1]);

if (GET_CODE (operands[1]) != MEM) { rtx op1 = gen_lowpart (SImode, operands[1]); rtx temp = gen_reg_rtx (SImode); rtx shift = gen_rtx (CONST_INT, VOIDmode, 24);

  emit_insn (gen_ashlsi3 (temp, op1, shift));
  emit_insn (gen_ashrsi3 (operands[0], temp, shift));
  DONE;
}

}")

(define_insn "extendqisi2_insn" [(set (match_operand:SI 0 "register_operand" "=d,d") (sign_extend:SI (match_operand:QI 1 "memory_operand" "R,m")))] "" "* return mips_move_1word (operands, insn, FALSE);" [(set_attr "type" "load,load") (set_attr "mode" "SI,SI") (set_attr "length" "1,2")])

(define_insn "extendsfdf2" [(set (match_operand:DF 0 "register_operand" "=f") (float_extend:DF (match_operand:SF 1 "register_operand" "f")))] "TARGET_HARD_FLOAT" "cvt.d.s\t%0,%1" [(set_attr "type" "fcvt") (set_attr "mode" "DF") (set_attr "length" "1")])

;; ;; .................... ;; ;; CONVERSIONS ;; ;; ....................

(define_insn "fix_truncdfsi2_internal" [(set (match_operand:SI 0 "general_operand" "=d,*f,R,o") (fix:SI (match_operand:DF 1 "register_operand" "f,*f,f,f"))) (clobber (match_operand:SI 2 "register_operand" "d,*d,d,d")) (clobber (match_operand:DF 3 "register_operand" "f,f,f,f"))] "TARGET_HARD_FLOAT" " { rtx xoperands[10];

if (which_alternative == 1) return "trunc.w.d %0,%1,%2";

output_asm_insn ("trunc.w.d %3,%1,%2", operands);

xoperands[0] = operands[0]; xoperands[1] = operands[3]; output_asm_insn (mips_move_1word (xoperands, insn, FALSE), xoperands); return ""; }" [(set_attr "type" "fcvt,fcvt,fcvt,fcvt") (set_attr "mode" "DF,DF,DF,DF") (set_attr "length" "14,12,13,14")])

(define_expand "fix_truncdfsi2" [(parallel [(set (match_operand:SI 0 "register_operand" "=d") (fix:SI (match_operand:DF 1 "register_operand" "f"))) (clobber (match_dup 2)) (clobber (match_dup 3))])] "TARGET_HARD_FLOAT" " { operands[2] = gen_reg_rtx (SImode); /* gp reg that saves FP status bits / operands[3] = gen_reg_rtx (DFmode); / fp reg that gets the conversion */

/* Fall through and generate default code */ }")

(define_insn "fix_truncsfsi2_internal" [(set (match_operand:SI 0 "general_operand" "=d,*f,R,o") (fix:SI (match_operand:SF 1 "register_operand" "f,*f,f,f"))) (clobber (match_operand:SI 2 "register_operand" "d,*d,d,d")) (clobber (match_operand:SF 3 "register_operand" "f,f,f,f"))] "TARGET_HARD_FLOAT" " { rtx xoperands[10];

if (which_alternative == 1) return "trunc.w.s %0,%1,%2";

output_asm_insn ("trunc.w.s %3,%1,%2", operands);

xoperands[0] = operands[0]; xoperands[1] = operands[3]; output_asm_insn (mips_move_1word (xoperands, insn, FALSE), xoperands); return ""; }" [(set_attr "type" "fcvt,fcvt,fcvt,fcvt") (set_attr "mode" "SF,SF,SF,SF") (set_attr "length" "14,12,13,14")])

(define_expand "fix_truncsfsi2" [(parallel [(set (match_operand:SI 0 "register_operand" "=f") (fix:SI (match_operand:SF 1 "register_operand" "f"))) (clobber (match_dup 2)) (clobber (match_dup 3))])] "TARGET_HARD_FLOAT" " { operands[2] = gen_reg_rtx (SImode); /* gp reg that saves FP status bits / operands[3] = gen_reg_rtx (SFmode); / fp reg that gets the conversion */

/* Fall through and generate default code */ }")

(define_insn "floatsidf2" [(set (match_operand:DF 0 "register_operand" "=f,f,f") (float:DF (match_operand:SI 1 "nonimmediate_operand" "d,R,m")))] "TARGET_HARD_FLOAT" "* { dslots_load_total++; if (GET_CODE (operands[1]) == MEM) return "ld.s\t%0,%1%#;cvt.d.w\t%0,%0";

return "mtc1\t%1,%0%#;cvt.d.w\t%0,%0"; }" [(set_attr "type" "fcvt,fcvt,fcvt") (set_attr "mode" "DF,DF,DF") (set_attr "length" "3,4,3")])

(define_insn "floatsisf2" [(set (match_operand:SF 0 "register_operand" "=f,f,f") (float:SF (match_operand:SI 1 "nonimmediate_operand" "d,R,m")))] "TARGET_HARD_FLOAT" "* { dslots_load_total++; if (GET_CODE (operands[1]) == MEM) return "ld.s\t%0,%1%#;cvt.s.w\t%0,%0";

return "mtc1\t%1,%0%#;cvt.s.w\t%0,%0"; }" [(set_attr "type" "fcvt,fcvt,fcvt") (set_attr "mode" "SF,SF,SF") (set_attr "length" "3,4,3")])

(define_expand "fixuns_truncdfsi2" [(set (match_operand:SI 0 "register_operand" "") (unsigned_fix:SI (match_operand:DF 1 "register_operand" "")))] "TARGET_HARD_FLOAT" " { rtx reg1 = gen_reg_rtx (DFmode); rtx reg2 = gen_reg_rtx (DFmode); rtx reg3 = gen_reg_rtx (SImode); rtx label1 = gen_label_rtx (); rtx label2 = gen_label_rtx (); REAL_VALUE_TYPE offset = REAL_VALUE_LDEXP (1.0, 31);

if (reg1) /* turn off complaints about unreached code */ { extern rtx gen_cmpdf (); emit_move_insn (reg1, immed_real_const_1 (offset, DFmode)); do_pending_stack_adjust ();

  emit_insn (gen_cmpdf (operands[1], reg1));
  emit_jump_insn (gen_bge (label1));

  emit_insn (gen_fix_truncdfsi2 (operands[0], operands[1]));
  emit_jump_insn (gen_rtx (SET, VOIDmode, pc_rtx,
		       gen_rtx (LABEL_REF, VOIDmode, label2)));
  emit_barrier ();

  emit_label (label1);
  emit_move_insn (reg2, gen_rtx (MINUS, DFmode, operands[1], reg1));
  emit_move_insn (reg3, gen_rtx (CONST_INT, VOIDmode, 0x80000000));

  emit_insn (gen_fix_truncdfsi2 (operands[0], reg2));
  emit_insn (gen_iorsi3 (operands[0], operands[0], reg3));

  emit_label (label2);

  /* allow REG_NOTES to be set on last insn (labels don't have enough
 fields, and can't be used for REG_NOTES anyway).  */
  emit_insn (gen_rtx (USE, VOIDmode, stack_pointer_rtx));
  DONE;
}

}")

(define_expand "fixuns_truncsfsi2" [(set (match_operand:SI 0 "register_operand" "") (unsigned_fix:SI (match_operand:SF 1 "register_operand" "")))] "TARGET_HARD_FLOAT" " { rtx reg1 = gen_reg_rtx (SFmode); rtx reg2 = gen_reg_rtx (SFmode); rtx reg3 = gen_reg_rtx (SImode); rtx label1 = gen_label_rtx (); rtx label2 = gen_label_rtx (); REAL_VALUE_TYPE offset = REAL_VALUE_LDEXP (1.0, 31);

if (reg1) /* turn off complaints about unreached code */ { extern rtx gen_cmpsf (); emit_move_insn (reg1, immed_real_const_1 (offset, SFmode)); do_pending_stack_adjust ();

  emit_insn (gen_cmpsf (operands[1], reg1));
  emit_jump_insn (gen_bge (label1));

  emit_insn (gen_fix_truncsfsi2 (operands[0], operands[1]));
  emit_jump_insn (gen_rtx (SET, VOIDmode, pc_rtx,
		       gen_rtx (LABEL_REF, VOIDmode, label2)));
  emit_barrier ();

  emit_label (label1);
  emit_move_insn (reg2, gen_rtx (MINUS, SFmode, operands[1], reg1));
  emit_move_insn (reg3, gen_rtx (CONST_INT, VOIDmode, 0x80000000));

  emit_insn (gen_fix_truncsfsi2 (operands[0], reg2));
  emit_insn (gen_iorsi3 (operands[0], operands[0], reg3));

  emit_label (label2);

  /* allow REG_NOTES to be set on last insn (labels don't have enough
 fields, and can't be used for REG_NOTES anyway).  */
  emit_insn (gen_rtx (USE, VOIDmode, stack_pointer_rtx));
  DONE;
}

}")

;; ;; .................... ;; ;; DATA MOVEMENT ;; ;; ....................

;; unaligned word moves generated by the block moves.

(define_expand "movsi_unaligned" [(set (match_operand:SI 0 "general_operand" "") (unspec [(match_operand:SI 1 "general_operand" "")] 0))] "" " { extern rtx force_reg (); extern rtx gen_movsi_ulw (); extern rtx gen_movsi ();

/* Handle loads. */ if (GET_CODE (operands[0]) == MEM) { rtx reg = gen_reg_rtx (SImode); rtx insn = emit_insn (gen_movsi_ulw (reg, operands[1])); rtx addr = XEXP (operands[0], 0); if (CONSTANT_P (addr)) REG_NOTES (insn) = gen_rtx (EXPR_LIST, REG_EQUIV, addr, REG_NOTES (insn));

  if (reg_or_0_operand (operands[1], SImode))
DONE;

  operands[1] = reg;
}

/* Generate appropriate load, store. If not a load or store, do a normal movsi. */ if (GET_CODE (operands[0]) != MEM && GET_CODE (operands[1]) != MEM) { emit_insn (gen_movsi (operands[0], operands[1])); DONE; }

/* Fall through and generate normal code. */ }")

(define_insn "movsi_ulw" [(set (match_operand:SI 0 "register_operand" "=&d,&d,d,d") (unspec [(match_operand:SI 1 "general_operand" "R,o,dIKL,M")] 0))] "" "* { extern rtx eliminate_constant_term (); enum rtx_code code; char *ret; rtx offset; rtx addr; rtx mem_addr;

if (which_alternative != 0) return mips_move_1word (operands, insn, FALSE);

if (TARGET_STATS) mips_count_memory_refs (operands[1], 2);

/* The stack/frame pointers are always aligned, so we can convert to the faster lw if we are referencing an aligned stack location. */

offset = const0_rtx; addr = XEXP (operands[1], 0); mem_addr = eliminate_constant_term (addr, &offset);

if ((INTVAL (offset) & (UNITS_PER_WORD-1)) == 0 && (mem_addr == stack_pointer_rtx || mem_addr == frame_pointer_rtx)) ret = "lw\t%0,%1";

else { ret = "ulw\t%0,%1"; if (TARGET_GAS) { enum rtx_code code = GET_CODE (addr);

  if (code == CONST || code == SYMBOL_REF || code == LABEL_REF)
    {
      operands[2] = gen_rtx (REG, SImode, GP_REG_FIRST + 1);
      ret = \"%[la\\t%2,%1\;ulw\\t%0,0(%2)%]\";
    }
}
}

return mips_fill_delay_slot (ret, DELAY_LOAD, operands, insn); }" [(set_attr "type" "load,load,move,arith") (set_attr "mode" "SI,SI,SI,SI") (set_attr "length" "2,4,1,2")])

(define_insn "movsi_usw" [(set (match_operand:SI 0 "memory_operand" "=R,o") (unspec [(match_operand:SI 1 "reg_or_0_operand" "dJ,dJ")] 0))] "" "* { extern rtx eliminate_constant_term (); rtx offset = const0_rtx; rtx addr = XEXP (operands[0], 0); rtx mem_addr = eliminate_constant_term (addr, &offset);

if (TARGET_STATS) mips_count_memory_refs (operands[0], 2);

/* The stack/frame pointers are always aligned, so we can convert to the faster sw if we are referencing an aligned stack location. */

if ((INTVAL (offset) & (UNITS_PER_WORD-1)) == 0 && (mem_addr == stack_pointer_rtx || mem_addr == frame_pointer_rtx)) return "sw\t%1,%0";

if (TARGET_GAS) { enum rtx_code code = GET_CODE (XEXP (operands[0], 0));

  if (code == CONST || code == SYMBOL_REF || code == LABEL_REF)
{
  operands[2] = gen_rtx (REG, SImode, GP_REG_FIRST + 1);
  return \"%[la\\t%2,%0\;usw\\t%z1,0(%2)%]\";
}
}

return "usw\t%z1,%0"; }" [(set_attr "type" "store,store") (set_attr "mode" "SI,SI") (set_attr "length" "2,4")])

;; 64-bit integer moves

;; Unlike most other insns, the move insns can't be split with ;; different predicates, because register spilling and other parts of ;; the compiler, have memoized the insn number already.

(define_insn "movdi" [(set (match_operand:DI 0 "nonimmediate_operand" "=d,d,d,d,R,o,*d,*x") (match_operand:DI 1 "general_operand" "d,iF,R,o,d,d,*x,d"))] "" " return mips_move_2words (operands, insn); " [(set_attr "type" "move,arith,load,load,store,store,hilo,hilo") (set_attr "mode" "DI,DI,DI,DI,DI,DI,DI,DI") (set_attr "length" "2,4,2,4,2,4,2,2")])

(define_split [(set (match_operand:DI 0 "register_operand" "") (match_operand:DI 1 "register_operand" ""))] "reload_completed && !TARGET_DEBUG_D_MODE && !TARGET_DEBUG_G_MODE && GET_CODE (operands[0]) == REG && GP_REG_P (REGNO (operands[0])) && GET_CODE (operands[1]) == REG && GP_REG_P (REGNO (operands[1]))"

[(set (subreg:SI (match_dup 0) 0) (subreg:SI (match_dup 1) 0)) (set (subreg:SI (match_dup 0) 1) (subreg:SI (match_dup 1) 1))] "")

;; 32-bit Integer moves

(define_split [(set (match_operand:SI 0 "register_operand" "") (match_operand:SI 1 "large_int" ""))] "!TARGET_DEBUG_D_MODE" [(set (match_dup 0) (match_dup 2)) (set (match_dup 0) (ior:SI (match_dup 0) (match_dup 3)))] " { operands[2] = gen_rtx (CONST_INT, VOIDmode, INTVAL (operands[1]) & 0xffff0000); operands[3] = gen_rtx (CONST_INT, VOIDmode, INTVAL (operands[1]) & 0x0000ffff); }")

;; Unlike most other insns, the move insns can't be split with ;; different predicates, because register spilling and other parts of ;; the compiler, have memoized the insn number already.

(define_expand "movsi" [(set (match_operand:SI 0 "nonimmediate_operand" "") (match_operand:SI 1 "general_operand" ""))] "" " { /* If this is a half-pic address being moved to a register, convert the address into a load, so that scheduling and stuff works properly. */

if (HALF_PIC_P() && GET_CODE (operands[0]) == REG && GET_CODE (operands[1]) == SYMBOL_REF && HALF_PIC_ADDRESS_P (operands[1])) { rtx ptr = HALF_PIC_PTR (operands[1]); if (XSTR (ptr, 0) != XSTR (operands[1], 0)) { emit_move_insn (operands[0], gen_rtx (MEM, Pmode, ptr)); DONE; } } }")

(define_insn "movsi_internal" [(set (match_operand:SI 0 "nonimmediate_operand" "=d,d,d,d,d,d,R,m,*d,*fs,*f,*f,*f,*R,*m,*x,*d") (match_operand:SI 1 "general_operand" "d,S,IKL,Mnis,R,m,dJ,dJ,*fs,*d,*f,*R,*m,*f,*f,*d,x"))] "" " return mips_move_1word (operands, insn, TRUE);" [(set_attr "type" "move,pic,arith,arith,load,load,store,store,xfer,xfer,move,load,load,store,store,hilo,hilo") (set_attr "mode" "SI,SI,SI,SI,SI,SI,SI,SI,SI,SI,SI,SI,SI,SI,SI,SI,SI") (set_attr "length" "1,4,1,2,1,2,1,2,1,1,1,1,2,1,2,1,1")])

;; 16-bit Integer moves

;; Unlike most other insns, the move insns can't be split with ;; different predicates, because register spilling and other parts of ;; the compiler, have memoized the insn number already. ;; Unsigned loads are used because BYTE_LOADS_ZERO_EXTEND is defined

(define_insn "movhi" [(set (match_operand:HI 0 "nonimmediate_operand" "=d,d,d,d,R,m,*d,*f,*f,*x,*d") (match_operand:HI 1 "general_operand" "d,IK,R,m,dJ,dJ,*fs,*d,*f,*d,x"))] "" " return mips_move_1word (operands, insn, TRUE);" [(set_attr "type" "move,arith,load,load,store,store,xfer,xfer,move,hilo,hilo") (set_attr "mode" "HI,HI,HI,HI,HI,HI,HI,HI,HI,HI,HI") (set_attr "length" "1,1,1,2,1,2,1,1,1,1,1")])

;; 8-bit Integer moves

;; Unlike most other insns, the move insns can't be split with ;; different predicates, because register spilling and other parts of ;; the compiler, have memoized the insn number already. ;; Unsigned loads are used because BYTE_LOADS_ZERO_EXTEND is defined

(define_insn "movqi" [(set (match_operand:QI 0 "nonimmediate_operand" "=d,d,d,d,R,m,*d,*f,*f,*x,*d") (match_operand:QI 1 "general_operand" "d,IK,R,m,dJ,dJ,*fs,*d,*f,*d,x"))] "" " return mips_move_1word (operands, insn, TRUE);" [(set_attr "type" "move,arith,load,load,store,store,xfer,xfer,move,hilo,hilo") (set_attr "mode" "QI,QI,QI,QI,QI,QI,QI,QI,QI,QI,QI") (set_attr "length" "1,1,1,2,1,2,1,1,1,1,1")])

;; 32-bit floating point moves

(define_insn "movsf" [(set (match_operand:SF 0 "nonimmediate_operand" "=f,f,f,f,R,m,*f,*d,*d,*d,*d,*R,*m") (match_operand:SF 1 "general_operand" "f,G,R,Em,fG,fG,*d,*f,*Gd,*R,*Em,*d,d"))] "" " return mips_move_1word (operands, insn, FALSE);" [(set_attr "type" "move,xfer,load,load,store,store,xfer,xfer,move,load,load,store,store") (set_attr "mode" "SF,SF,SF,SF,SF,SF,SF,SF,SF,SF,SF,SF,SF") (set_attr "length" "1,1,1,2,1,2,1,1,1,1,2,1,2")])

;; 64-bit floating point moves

(define_insn "movdf" [(set (match_operand:DF 0 "nonimmediate_operand" "=f,f,f,R,o,f,*f,*d,*d,*d,*d,*R,*o") (match_operand:DF 1 "general_operand" "f,R,o,fG,fG,E,*d,*f,*dG,*R,*oE,*d,d"))] "" " return mips_move_2words (operands, insn); " [(set_attr "type" "move,load,load,store,store,load,xfer,xfer,move,load,load,store,store") (set_attr "mode" "DF,DF,DF,DF,DF,DF,DF,DF,DF,DF,DF,DF,DF") (set_attr "length" "1,2,4,2,4,4,2,2,2,2,4,2,4")])

(define_split [(set (match_operand:DF 0 "register_operand" "") (match_operand:DF 1 "register_operand" ""))] "reload_completed && !TARGET_DEBUG_D_MODE && !TARGET_DEBUG_G_MODE && GET_CODE (operands[0]) == REG && GP_REG_P (REGNO (operands[0])) && GET_CODE (operands[1]) == REG && GP_REG_P (REGNO (operands[1]))"

[(set (subreg:SI (match_dup 0) 0) (subreg:SI (match_dup 1) 0)) (set (subreg:SI (match_dup 0) 1) (subreg:SI (match_dup 1) 1))] "")

;; Block moves, see mips.c for more details. ;; Argument 0 is the destination ;; Argument 1 is the source ;; Argument 2 is the length ;; Argument 3 is the alignment

(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 "arith32_operand" "")) (use (match_operand:SI 3 "immediate_operand" ""))])] "" " { if (operands[0]) /* avoid unused code messages */ { expand_block_move (operands); DONE; } }")

;; Insn generated by block moves

(define_insn "movstrsi_internal" [(set (match_operand:BLK 0 "memory_operand" "=Ro") ;; destination (match_operand:BLK 1 "memory_operand" "Ro")) ;; source (clobber (match_scratch:SI 4 "=&d")) ;; temp 1 (clobber (match_scratch:SI 5 "=&d")) ;; temp 2 (clobber (match_scratch:SI 6 "=&d")) ;; temp 3 (clobber (match_scratch:SI 7 "=&d")) ;; temp 4 (use (match_operand:SI 2 "small_int" "I")) ;; # bytes to move (use (match_operand:SI 3 "small_int" "I")) ;; alignment (use (const_int 0))] ;; normal block move "" "* return output_block_move (insn, operands, 4, BLOCK_MOVE_NORMAL);" [(set_attr "type" "multi") (set_attr "mode" "none") (set_attr "length" "20")])

;; Split a block move into 2 parts, the first part is everything ;; except for the last move, and the second part is just the last ;; store, which is exactly 1 instruction (ie, not a usw), so it can ;; fill a delay slot. This also prevents a bug in delayed branches ;; from showing up, which reuses one of the registers in our clobbers.

(define_split [(set (mem:BLK (match_operand:SI 0 "register_operand" "")) (mem:BLK (match_operand:SI 1 "register_operand" ""))) (clobber (match_operand:SI 4 "register_operand" "")) (clobber (match_operand:SI 5 "register_operand" "")) (clobber (match_operand:SI 6 "register_operand" "")) (clobber (match_operand:SI 7 "register_operand" "")) (use (match_operand:SI 2 "small_int" "")) (use (match_operand:SI 3 "small_int" "")) (use (const_int 0))]

"reload_completed && !TARGET_DEBUG_D_MODE && INTVAL (operands[2]) > 0"

;; All but the last move [(parallel [(set (mem:BLK (match_dup 0)) (mem:BLK (match_dup 1))) (clobber (match_dup 4)) (clobber (match_dup 5)) (clobber (match_dup 6)) (clobber (match_dup 7)) (use (match_dup 2)) (use (match_dup 3)) (use (const_int 1))])

;; The last store, so it can fill a delay slot (parallel [(set (mem:BLK (match_dup 0)) (mem:BLK (match_dup 1))) (clobber (match_dup 4)) (clobber (match_dup 5)) (clobber (match_dup 6)) (clobber (match_dup 7)) (use (match_dup 2)) (use (match_dup 3)) (use (const_int 2))])]

"")

(define_insn "movstrsi_internal2" [(set (match_operand:BLK 0 "memory_operand" "=Ro") ;; destination (match_operand:BLK 1 "memory_operand" "Ro")) ;; source (clobber (match_scratch:SI 4 "=&d")) ;; temp 1 (clobber (match_scratch:SI 5 "=&d")) ;; temp 2 (clobber (match_scratch:SI 6 "=&d")) ;; temp 3 (clobber (match_scratch:SI 7 "=&d")) ;; temp 4 (use (match_operand:SI 2 "small_int" "I")) ;; # bytes to move (use (match_operand:SI 3 "small_int" "I")) ;; alignment (use (const_int 1))] ;; all but last store "" "* return output_block_move (insn, operands, 4, BLOCK_MOVE_NOT_LAST);" [(set_attr "type" "multi") (set_attr "mode" "none") (set_attr "length" "20")])

(define_insn "movstrsi_internal3" [(set (match_operand:BLK 0 "memory_operand" "=Ro") ;; destination (match_operand:BLK 1 "memory_operand" "Ro")) ;; source (clobber (match_scratch:SI 4 "=&d")) ;; temp 1 (clobber (match_scratch:SI 5 "=&d")) ;; temp 2 (clobber (match_scratch:SI 6 "=&d")) ;; temp 3 (clobber (match_scratch:SI 7 "=&d")) ;; temp 4 (use (match_operand:SI 2 "small_int" "I")) ;; # bytes to move (use (match_operand:SI 3 "small_int" "I")) ;; alignment (use (const_int 2))] ;; just last store of block mvoe "" "* return output_block_move (insn, operands, 4, BLOCK_MOVE_LAST);" [(set_attr "type" "store") (set_attr "mode" "none") (set_attr "length" "1")])

;; ;; .................... ;; ;; SHIFTS ;; ;; ....................

(define_insn "ashlsi3" [(set (match_operand:SI 0 "register_operand" "=d") (ashift:SI (match_operand:SI 1 "register_operand" "d") (match_operand:SI 2 "arith_operand" "dI")))] "" "* { if (GET_CODE (operands[2]) == CONST_INT) operands[2] = gen_rtx (CONST_INT, VOIDmode, (XINT (operands[2], 0))& 0x1f);

return "sll\t%0,%1,%2"; }" [(set_attr "type" "arith") (set_attr "mode" "SI") (set_attr "length" "1")])

(define_expand "ashldi3" [(parallel [(set (match_operand:DI 0 "register_operand" "") (ashift:DI (match_operand:DI 1 "register_operand" "") (match_operand:SI 2 "arith_operand" ""))) (clobber (match_dup 3))])] "!TARGET_DEBUG_G_MODE" "operands[3] = gen_reg_rtx (SImode);")

(define_insn "ashldi3_internal" [(set (match_operand:DI 0 "register_operand" "=d") (ashift:DI (match_operand:DI 1 "register_operand" "d") (match_operand:SI 2 "register_operand" "d"))) (clobber (match_operand:SI 3 "register_operand" "=d"))] "!TARGET_DEBUG_G_MODE" "* { operands[4] = const0_rtx; dslots_jump_total += 3; dslots_jump_filled += 2;

return "sll\t%3,%2,26\n\ \tbgez\t%3,1f\n\ \tsll\t%M0,%L1,%2\n\ \t%(b\t3f\n\ \tmove\t%L0,%z4%)\n\ \n\ 1:\n\ \t%(beq\t%3,%z4,2f\n\ \tsll\t%M0,%M1,%2%)\n\ \n\ \tsubu\t%3,%z4,%2\n\ \tsrl\t%3,%L1,%3\n\ \tor\t%M0,%M0,%3\n\ 2:\n\ \tsll\t%L0,%L1,%2\n\ 3:"; }" [(set_attr "type" "darith") (set_attr "mode" "SI") (set_attr "length" "12")])

(define_insn "ashldi3_internal2" [(set (match_operand:DI 0 "register_operand" "=d") (ashift:DI (match_operand:DI 1 "register_operand" "d") (match_operand:SI 2 "small_int" "IJK"))) (clobber (match_operand:SI 3 "register_operand" "=d"))] "!TARGET_DEBUG_G_MODE && (INTVAL (operands[2]) & 32) != 0" "* { operands[2] = gen_rtx (CONST_INT, VOIDmode, (XINT (operands[2], 0))& 0x1f); operands[4] = const0_rtx; return "sll\t%M0,%L1,%2;move\t%L0,%z4"; }" [(set_attr "type" "darith") (set_attr "mode" "DI") (set_attr "length" "2")])

(define_split [(set (match_operand:DI 0 "register_operand" "") (ashift:DI (match_operand:DI 1 "register_operand" "") (match_operand:SI 2 "small_int" ""))) (clobber (match_operand:SI 3 "register_operand" ""))] "reload_completed && !WORDS_BIG_ENDIAN && !TARGET_DEBUG_D_MODE && !TARGET_DEBUG_G_MODE && GET_CODE (operands[0]) == REG && REGNO (operands[0]) < FIRST_PSEUDO_REGISTER && GET_CODE (operands[1]) == REG && REGNO (operands[1]) < FIRST_PSEUDO_REGISTER && (INTVAL (operands[2]) & 32) != 0"

[(set (subreg:SI (match_dup 0) 1) (ashift:SI (subreg:SI (match_dup 1) 0) (match_dup 2))) (set (subreg:SI (match_dup 0) 0) (const_int 0))]

"operands[2] = gen_rtx (CONST_INT, VOIDmode, (XINT (operands[2], 0))& 0x1f);")

(define_split [(set (match_operand:DI 0 "register_operand" "") (ashift:DI (match_operand:DI 1 "register_operand" "") (match_operand:SI 2 "small_int" ""))) (clobber (match_operand:SI 3 "register_operand" ""))] "reload_completed && WORDS_BIG_ENDIAN && !TARGET_DEBUG_D_MODE && !TARGET_DEBUG_G_MODE && GET_CODE (operands[0]) == REG && REGNO (operands[0]) < FIRST_PSEUDO_REGISTER && GET_CODE (operands[1]) == REG && REGNO (operands[1]) < FIRST_PSEUDO_REGISTER && (INTVAL (operands[2]) & 32) != 0"

[(set (subreg:SI (match_dup 0) 0) (ashift:SI (subreg:SI (match_dup 1) 1) (match_dup 2))) (set (subreg:SI (match_dup 0) 1) (const_int 0))]

"operands[2] = gen_rtx (CONST_INT, VOIDmode, (XINT (operands[2], 0))& 0x1f);")

(define_insn "ashldi3_internal3" [(set (match_operand:DI 0 "register_operand" "=d") (ashift:DI (match_operand:DI 1 "register_operand" "d") (match_operand:SI 2 "small_int" "IJK"))) (clobber (match_operand:SI 3 "register_operand" "=d"))] "!TARGET_DEBUG_G_MODE && (INTVAL (operands[2]) & 63) < 32 && (INTVAL (operands[2]) & 63) != 0" "* { int amount = INTVAL (operands[2]);

operands[2] = gen_rtx (CONST_INT, VOIDmode, (amount & 31)); operands[4] = const0_rtx; operands[5] = gen_rtx (CONST_INT, VOIDmode, ((-amount) & 31));

return "sll\t%M0,%M1,%2;srl\t%3,%L1,%5;or\t%M0,%M0,%3;sll\t%L0,%L1,%2"; }" [(set_attr "type" "darith") (set_attr "mode" "DI") (set_attr "length" "4")])

(define_split [(set (match_operand:DI 0 "register_operand" "") (ashift:DI (match_operand:DI 1 "register_operand" "") (match_operand:SI 2 "small_int" ""))) (clobber (match_operand:SI 3 "register_operand" ""))] "reload_completed && !WORDS_BIG_ENDIAN && !TARGET_DEBUG_D_MODE && !TARGET_DEBUG_G_MODE && GET_CODE (operands[0]) == REG && REGNO (operands[0]) < FIRST_PSEUDO_REGISTER && GET_CODE (operands[1]) == REG && REGNO (operands[1]) < FIRST_PSEUDO_REGISTER && (INTVAL (operands[2]) & 63) < 32 && (INTVAL (operands[2]) & 63) != 0"

[(set (subreg:SI (match_dup 0) 1) (ashift:SI (subreg:SI (match_dup 1) 1) (match_dup 2)))

(set (match_dup 3) (lshiftrt:SI (subreg:SI (match_dup 1) 0) (match_dup 4)))

(set (subreg:SI (match_dup 0) 1) (ior:SI (subreg:SI (match_dup 0) 1) (match_dup 3)))

(set (subreg:SI (match_dup 0) 0) (ashift:SI (subreg:SI (match_dup 1) 0) (match_dup 2)))] " { int amount = INTVAL (operands[2]); operands[2] = gen_rtx (CONST_INT, VOIDmode, (amount & 31)); operands[4] = gen_rtx (CONST_INT, VOIDmode, ((-amount) & 31)); }")

(define_split [(set (match_operand:DI 0 "register_operand" "") (ashift:DI (match_operand:DI 1 "register_operand" "") (match_operand:SI 2 "small_int" ""))) (clobber (match_operand:SI 3 "register_operand" ""))] "reload_completed && WORDS_BIG_ENDIAN && !TARGET_DEBUG_D_MODE && !TARGET_DEBUG_G_MODE && GET_CODE (operands[0]) == REG && REGNO (operands[0]) < FIRST_PSEUDO_REGISTER && GET_CODE (operands[1]) == REG && REGNO (operands[1]) < FIRST_PSEUDO_REGISTER && (INTVAL (operands[2]) & 63) < 32 && (INTVAL (operands[2]) & 63) != 0"

[(set (subreg:SI (match_dup 0) 0) (ashift:SI (subreg:SI (match_dup 1) 0) (match_dup 2)))

(set (match_dup 3) (lshiftrt:SI (subreg:SI (match_dup 1) 1) (match_dup 4)))

(set (subreg:SI (match_dup 0) 0) (ior:SI (subreg:SI (match_dup 0) 0) (match_dup 3)))

(set (subreg:SI (match_dup 0) 1) (ashift:SI (subreg:SI (match_dup 1) 1) (match_dup 2)))] " { int amount = INTVAL (operands[2]); operands[2] = gen_rtx (CONST_INT, VOIDmode, (amount & 31)); operands[4] = gen_rtx (CONST_INT, VOIDmode, ((-amount) & 31)); }")

(define_insn "ashrsi3" [(set (match_operand:SI 0 "register_operand" "=d") (ashiftrt:SI (match_operand:SI 1 "register_operand" "d") (match_operand:SI 2 "arith_operand" "dI")))] "" "* { if (GET_CODE (operands[2]) == CONST_INT) operands[2] = gen_rtx (CONST_INT, VOIDmode, (XINT (operands[2], 0))& 0x1f);

return "sra\t%0,%1,%2"; }" [(set_attr "type" "arith") (set_attr "mode" "SI") (set_attr "length" "1")])

(define_expand "ashrdi3" [(parallel [(set (match_operand:DI 0 "register_operand" "") (ashiftrt:DI (match_operand:DI 1 "register_operand" "") (match_operand:SI 2 "arith_operand" ""))) (clobber (match_dup 3))])] "!TARGET_DEBUG_G_MODE" "operands[3] = gen_reg_rtx (SImode);")

(define_insn "ashrdi3_internal" [(set (match_operand:DI 0 "register_operand" "=d") (ashiftrt:DI (match_operand:DI 1 "register_operand" "d") (match_operand:SI 2 "register_operand" "d"))) (clobber (match_operand:SI 3 "register_operand" "=d"))] "!TARGET_DEBUG_G_MODE" "* { operands[4] = const0_rtx; dslots_jump_total += 3; dslots_jump_filled += 2;

return "sll\t%3,%2,26\n\ \tbgez\t%3,1f\n\ \tsra\t%L0,%M1,%2\n\ \t%(b\t3f\n\ \tsra\t%M0,%M1,31%)\n\ \n\ 1:\n\ \t%(beq\t%3,%z4,2f\n\ \tsrl\t%L0,%L1,%2%)\n\ \n\ \tsubu\t%3,%z4,%2\n\ \tsll\t%3,%M1,%3\n\ \tor\t%L0,%L0,%3\n\ 2:\n\ \tsra\t%M0,%M1,%2\n\ 3:"; }" [(set_attr "type" "darith") (set_attr "mode" "DI") (set_attr "length" "12")])

(define_insn "ashrdi3_internal2" [(set (match_operand:DI 0 "register_operand" "=d") (ashiftrt:DI (match_operand:DI 1 "register_operand" "d") (match_operand:SI 2 "small_int" "IJK"))) (clobber (match_operand:SI 3 "register_operand" "=d"))] "!TARGET_DEBUG_G_MODE && (INTVAL (operands[2]) & 32) != 0" "* { operands[2] = gen_rtx (CONST_INT, VOIDmode, (XINT (operands[2], 0))& 0x1f); return "sra\t%L0,%M1,%2;sra\t%M0,%M1,31"; }" [(set_attr "type" "darith") (set_attr "mode" "DI") (set_attr "length" "2")])

(define_split [(set (match_operand:DI 0 "register_operand" "") (ashiftrt:DI (match_operand:DI 1 "register_operand" "") (match_operand:SI 2 "small_int" ""))) (clobber (match_operand:SI 3 "register_operand" ""))] "reload_completed && !WORDS_BIG_ENDIAN && !TARGET_DEBUG_D_MODE && !TARGET_DEBUG_G_MODE && GET_CODE (operands[0]) == REG && REGNO (operands[0]) < FIRST_PSEUDO_REGISTER && GET_CODE (operands[1]) == REG && REGNO (operands[1]) < FIRST_PSEUDO_REGISTER && (INTVAL (operands[2]) & 32) != 0"

[(set (subreg:SI (match_dup 0) 0) (ashiftrt:SI (subreg:SI (match_dup 1) 1) (match_dup 2))) (set (subreg:SI (match_dup 0) 1) (ashiftrt:SI (subreg:SI (match_dup 1) 1) (const_int 31)))]

"operands[2] = gen_rtx (CONST_INT, VOIDmode, (XINT (operands[2], 0))& 0x1f);")

(define_split [(set (match_operand:DI 0 "register_operand" "") (ashiftrt:DI (match_operand:DI 1 "register_operand" "") (match_operand:SI 2 "small_int" ""))) (clobber (match_operand:SI 3 "register_operand" ""))] "reload_completed && WORDS_BIG_ENDIAN && !TARGET_DEBUG_D_MODE && !TARGET_DEBUG_G_MODE && GET_CODE (operands[0]) == REG && REGNO (operands[0]) < FIRST_PSEUDO_REGISTER && GET_CODE (operands[1]) == REG && REGNO (operands[1]) < FIRST_PSEUDO_REGISTER && (INTVAL (operands[2]) & 32) != 0"

[(set (subreg:SI (match_dup 0) 1) (ashiftrt:SI (subreg:SI (match_dup 1) 0) (match_dup 2))) (set (subreg:SI (match_dup 0) 0) (ashiftrt:SI (subreg:SI (match_dup 1) 0) (const_int 31)))]

"operands[2] = gen_rtx (CONST_INT, VOIDmode, (XINT (operands[2], 0))& 0x1f);")

(define_insn "ashrdi3_internal3" [(set (match_operand:DI 0 "register_operand" "=d") (ashiftrt:DI (match_operand:DI 1 "register_operand" "d") (match_operand:SI 2 "small_int" "IJK"))) (clobber (match_operand:SI 3 "register_operand" "=d"))] "!TARGET_DEBUG_G_MODE && (INTVAL (operands[2]) & 63) < 32 && (INTVAL (operands[2]) & 63) != 0" "* { int amount = INTVAL (operands[2]);

operands[2] = gen_rtx (CONST_INT, VOIDmode, (amount & 31)); operands[4] = gen_rtx (CONST_INT, VOIDmode, ((-amount) & 31));

return "srl\t%L0,%L1,%2;sll\t%3,%M1,%4;or\t%L0,%L0,%3;sra\t%M0,%M1,%2"; }" [(set_attr "type" "darith") (set_attr "mode" "DI") (set_attr "length" "4")])

(define_split [(set (match_operand:DI 0 "register_operand" "") (ashiftrt:DI (match_operand:DI 1 "register_operand" "") (match_operand:SI 2 "small_int" ""))) (clobber (match_operand:SI 3 "register_operand" ""))] "reload_completed && !WORDS_BIG_ENDIAN && !TARGET_DEBUG_D_MODE && !TARGET_DEBUG_G_MODE && GET_CODE (operands[0]) == REG && REGNO (operands[0]) < FIRST_PSEUDO_REGISTER && GET_CODE (operands[1]) == REG && REGNO (operands[1]) < FIRST_PSEUDO_REGISTER && (INTVAL (operands[2]) & 63) < 32 && (INTVAL (operands[2]) & 63) != 0"

[(set (subreg:SI (match_dup 0) 0) (lshiftrt:SI (subreg:SI (match_dup 1) 0) (match_dup 2)))

(set (match_dup 3) (ashift:SI (subreg:SI (match_dup 1) 1) (match_dup 4)))

(set (subreg:SI (match_dup 0) 0) (ior:SI (subreg:SI (match_dup 0) 0) (match_dup 3)))

(set (subreg:SI (match_dup 0) 1) (ashiftrt:SI (subreg:SI (match_dup 1) 1) (match_dup 2)))] " { int amount = INTVAL (operands[2]); operands[2] = gen_rtx (CONST_INT, VOIDmode, (amount & 31)); operands[4] = gen_rtx (CONST_INT, VOIDmode, ((-amount) & 31)); }")

(define_split [(set (match_operand:DI 0 "register_operand" "") (ashiftrt:DI (match_operand:DI 1 "register_operand" "") (match_operand:SI 2 "small_int" ""))) (clobber (match_operand:SI 3 "register_operand" ""))] "reload_completed && WORDS_BIG_ENDIAN && !TARGET_DEBUG_D_MODE && !TARGET_DEBUG_G_MODE && GET_CODE (operands[0]) == REG && REGNO (operands[0]) < FIRST_PSEUDO_REGISTER && GET_CODE (operands[1]) == REG && REGNO (operands[1]) < FIRST_PSEUDO_REGISTER && (INTVAL (operands[2]) & 63) < 32 && (INTVAL (operands[2]) & 63) != 0"

[(set (subreg:SI (match_dup 0) 1) (lshiftrt:SI (subreg:SI (match_dup 1) 1) (match_dup 2)))

(set (match_dup 3) (ashift:SI (subreg:SI (match_dup 1) 0) (match_dup 4)))

(set (subreg:SI (match_dup 0) 1) (ior:SI (subreg:SI (match_dup 0) 1) (match_dup 3)))

(set (subreg:SI (match_dup 0) 0) (ashiftrt:SI (subreg:SI (match_dup 1) 0) (match_dup 2)))] " { int amount = INTVAL (operands[2]); operands[2] = gen_rtx (CONST_INT, VOIDmode, (amount & 31)); operands[4] = gen_rtx (CONST_INT, VOIDmode, ((-amount) & 31)); }")

(define_insn "lshrsi3" [(set (match_operand:SI 0 "register_operand" "=d") (lshiftrt:SI (match_operand:SI 1 "register_operand" "d") (match_operand:SI 2 "arith_operand" "dI")))] "" "* { if (GET_CODE (operands[2]) == CONST_INT) operands[2] = gen_rtx (CONST_INT, VOIDmode, (XINT (operands[2], 0))& 0x1f);

return "srl\t%0,%1,%2"; }" [(set_attr "type" "arith") (set_attr "mode" "SI") (set_attr "length" "1")])

(define_expand "lshrdi3" [(parallel [(set (match_operand:DI 0 "register_operand" "") (lshiftrt:DI (match_operand:DI 1 "register_operand" "") (match_operand:SI 2 "arith_operand" ""))) (clobber (match_dup 3))])] "!TARGET_DEBUG_G_MODE" "operands[3] = gen_reg_rtx (SImode);")

(define_insn "lshrdi3_internal" [(set (match_operand:DI 0 "register_operand" "=&d") (lshiftrt:DI (match_operand:DI 1 "register_operand" "d") (match_operand:SI 2 "register_operand" "d"))) (clobber (match_operand:SI 3 "register_operand" "=d"))] "!TARGET_DEBUG_G_MODE" "* { operands[4] = const0_rtx; dslots_jump_total += 3; dslots_jump_filled += 2;

return "sll\t%3,%2,26\n\ \tbgez\t%3,1f\n\ \tsrl\t%L0,%M1,%2\n\ \t%(b\t3f\n\ \tmove\t%M0,%z4%)\n\ \n\ 1:\n\ \t%(beq\t%3,%z4,2f\n\ \tsrl\t%L0,%L1,%2%)\n\ \n\ \tsubu\t%3,%z4,%2\n\ \tsll\t%3,%M1,%3\n\ \tor\t%L0,%L0,%3\n\ 2:\n\ \tsrl\t%M0,%M1,%2\n\ 3:"; }" [(set_attr "type" "darith") (set_attr "mode" "DI") (set_attr "length" "12")])

(define_insn "lshrdi3_internal2" [(set (match_operand:DI 0 "register_operand" "=d") (lshiftrt:DI (match_operand:DI 1 "register_operand" "d") (match_operand:SI 2 "small_int" "IJK"))) (clobber (match_operand:SI 3 "register_operand" "=d"))] "!TARGET_DEBUG_G_MODE && (INTVAL (operands[2]) & 32) != 0" "* { operands[2] = gen_rtx (CONST_INT, VOIDmode, (XINT (operands[2], 0))& 0x1f); operands[4] = const0_rtx; return "srl\t%L0,%M1,%2;move\t%M0,%z4"; }" [(set_attr "type" "darith") (set_attr "mode" "DI") (set_attr "length" "2")])

(define_split [(set (match_operand:DI 0 "register_operand" "") (lshiftrt:DI (match_operand:DI 1 "register_operand" "") (match_operand:SI 2 "small_int" ""))) (clobber (match_operand:SI 3 "register_operand" ""))] "reload_completed && !WORDS_BIG_ENDIAN && !TARGET_DEBUG_D_MODE && !TARGET_DEBUG_G_MODE && GET_CODE (operands[0]) == REG && REGNO (operands[0]) < FIRST_PSEUDO_REGISTER && GET_CODE (operands[1]) == REG && REGNO (operands[1]) < FIRST_PSEUDO_REGISTER && (INTVAL (operands[2]) & 32) != 0"

[(set (subreg:SI (match_dup 0) 0) (lshiftrt:SI (subreg:SI (match_dup 1) 1) (match_dup 2))) (set (subreg:SI (match_dup 0) 1) (const_int 0))]

"operands[2] = gen_rtx (CONST_INT, VOIDmode, (XINT (operands[2], 0))& 0x1f);")

(define_split [(set (match_operand:DI 0 "register_operand" "") (lshiftrt:DI (match_operand:DI 1 "register_operand" "") (match_operand:SI 2 "small_int" ""))) (clobber (match_operand:SI 3 "register_operand" ""))] "reload_completed && WORDS_BIG_ENDIAN && !TARGET_DEBUG_D_MODE && !TARGET_DEBUG_G_MODE && GET_CODE (operands[0]) == REG && REGNO (operands[0]) < FIRST_PSEUDO_REGISTER && GET_CODE (operands[1]) == REG && REGNO (operands[1]) < FIRST_PSEUDO_REGISTER && (INTVAL (operands[2]) & 32) != 0"

[(set (subreg:SI (match_dup 0) 1) (lshiftrt:SI (subreg:SI (match_dup 1) 0) (match_dup 2))) (set (subreg:SI (match_dup 0) 0) (const_int 0))]

"operands[2] = gen_rtx (CONST_INT, VOIDmode, (XINT (operands[2], 0))& 0x1f);")

(define_insn "lshrdi3_internal3" [(set (match_operand:DI 0 "register_operand" "=d") (lshiftrt:DI (match_operand:DI 1 "register_operand" "d") (match_operand:SI 2 "small_int" "IJK"))) (clobber (match_operand:SI 3 "register_operand" "=d"))] "!TARGET_DEBUG_G_MODE && (INTVAL (operands[2]) & 63) < 32 && (INTVAL (operands[2]) & 63) != 0" "* { int amount = INTVAL (operands[2]);

operands[2] = gen_rtx (CONST_INT, VOIDmode, (amount & 31)); operands[4] = gen_rtx (CONST_INT, VOIDmode, ((-amount) & 31));

return "srl\t%L0,%L1,%2;sll\t%3,%M1,%4;or\t%L0,%L0,%3;srl\t%M0,%M1,%2"; }" [(set_attr "type" "darith") (set_attr "mode" "DI") (set_attr "length" "4")])

(define_split [(set (match_operand:DI 0 "register_operand" "") (lshiftrt:DI (match_operand:DI 1 "register_operand" "") (match_operand:SI 2 "small_int" ""))) (clobber (match_operand:SI 3 "register_operand" ""))] "reload_completed && !WORDS_BIG_ENDIAN && !TARGET_DEBUG_D_MODE && !TARGET_DEBUG_G_MODE && GET_CODE (operands[0]) == REG && REGNO (operands[0]) < FIRST_PSEUDO_REGISTER && GET_CODE (operands[1]) == REG && REGNO (operands[1]) < FIRST_PSEUDO_REGISTER && (INTVAL (operands[2]) & 63) < 32 && (INTVAL (operands[2]) & 63) != 0"

[(set (subreg:SI (match_dup 0) 0) (lshiftrt:SI (subreg:SI (match_dup 1) 0) (match_dup 2)))

(set (match_dup 3) (ashift:SI (subreg:SI (match_dup 1) 1) (match_dup 4)))

(set (subreg:SI (match_dup 0) 0) (ior:SI (subreg:SI (match_dup 0) 0) (match_dup 3)))

(set (subreg:SI (match_dup 0) 1) (lshiftrt:SI (subreg:SI (match_dup 1) 1) (match_dup 2)))] " { int amount = INTVAL (operands[2]); operands[2] = gen_rtx (CONST_INT, VOIDmode, (amount & 31)); operands[4] = gen_rtx (CONST_INT, VOIDmode, ((-amount) & 31)); }")

(define_split [(set (match_operand:DI 0 "register_operand" "") (lshiftrt:DI (match_operand:DI 1 "register_operand" "") (match_operand:SI 2 "small_int" ""))) (clobber (match_operand:SI 3 "register_operand" ""))] "reload_completed && WORDS_BIG_ENDIAN && !TARGET_DEBUG_D_MODE && !TARGET_DEBUG_G_MODE && GET_CODE (operands[0]) == REG && REGNO (operands[0]) < FIRST_PSEUDO_REGISTER && GET_CODE (operands[1]) == REG && REGNO (operands[1]) < FIRST_PSEUDO_REGISTER && (INTVAL (operands[2]) & 63) < 32 && (INTVAL (operands[2]) & 63) != 0"

[(set (subreg:SI (match_dup 0) 1) (lshiftrt:SI (subreg:SI (match_dup 1) 1) (match_dup 2)))

(set (match_dup 3) (ashift:SI (subreg:SI (match_dup 1) 0) (match_dup 4)))

(set (subreg:SI (match_dup 0) 1) (ior:SI (subreg:SI (match_dup 0) 1) (match_dup 3)))

(set (subreg:SI (match_dup 0) 0) (lshiftrt:SI (subreg:SI (match_dup 1) 0) (match_dup 2)))] " { int amount = INTVAL (operands[2]); operands[2] = gen_rtx (CONST_INT, VOIDmode, (amount & 31)); operands[4] = gen_rtx (CONST_INT, VOIDmode, ((-amount) & 31)); }")

;; ;; .................... ;; ;; COMPARISONS ;; ;; ....................

;; Flow here is rather complex: ;; ;; 1) The cmp{si,sf,df} routine is called. It deposits the ;; arguments into the branch_cmp array, and the type into ;; branch_type. No RTL is generated. ;; ;; 2) The appropriate branch define_expand is called, which then ;; creates the appropriate RTL for the comparison and branch. ;; Different CC modes are used, based on what type of branch is ;; done, so that we can constrain things appropriately. There ;; are assumptions in the rest of GCC that break if we fold the ;; operands into the branchs for integer operations, and use cc0 ;; for floating point, so we use the fp status register instead. ;; If needed, an appropriate temporary is created to hold the ;; of the integer compare.

(define_expand "cmpsi" [(set (cc0) (compare:CC (match_operand:SI 0 "register_operand" "") (match_operand:SI 1 "arith_operand" "")))] "" " { if (operands[0]) /* avoid unused code message */ { branch_cmp[0] = operands[0]; branch_cmp[1] = operands[1]; branch_type = CMP_SI; DONE; } }")

(define_expand "tstsi" [(set (cc0) (match_operand:SI 0 "register_operand" ""))] "" " { if (operands[0]) /* avoid unused code message */ { branch_cmp[0] = operands[0]; branch_cmp[1] = const0_rtx; branch_type = CMP_SI; DONE; } }")

(define_expand "cmpdf" [(set (cc0) (compare:CC_FP (match_operand:DF 0 "register_operand" "") (match_operand:DF 1 "register_operand" "")))] "TARGET_HARD_FLOAT" " { if (operands[0]) /* avoid unused code message */ { branch_cmp[0] = operands[0]; branch_cmp[1] = operands[1]; branch_type = CMP_DF; DONE; } }")

(define_expand "cmpsf" [(set (cc0) (compare:CC_FP (match_operand:SF 0 "register_operand" "") (match_operand:SF 1 "register_operand" "")))] "TARGET_HARD_FLOAT" " { if (operands[0]) /* avoid unused code message */ { branch_cmp[0] = operands[0]; branch_cmp[1] = operands[1]; branch_type = CMP_SF; DONE; } }")

;; ;; .................... ;; ;; CONDITIONAL BRANCHES ;; ;; ....................

(define_insn "branch_fp_ne" [(set (pc) (if_then_else (ne:CC_FP (reg:CC_FP 66) (const_int 0)) (match_operand 0 "pc_or_label_operand" "") (match_operand 1 "pc_or_label_operand" "")))] "" "* { mips_branch_likely = (final_sequence && INSN_ANNULLED_BRANCH_P (insn)); return (operands[0] != pc_rtx) ? "%*bc1t%?\t%0" : "%*bc1f%?\t%1"; }" [(set_attr "type" "branch") (set_attr "mode" "none") (set_attr "length" "1")])

(define_insn "branch_fp_ne_rev" [(set (pc) (if_then_else (ne:CC_REV_FP (reg:CC_REV_FP 66) (const_int 0)) (match_operand 0 "pc_or_label_operand" "") (match_operand 1 "pc_or_label_operand" "")))] "" "* { mips_branch_likely = (final_sequence && INSN_ANNULLED_BRANCH_P (insn)); return (operands[0] != pc_rtx) ? "%*bc1f%?\t%0" : "%*bc1t%?\t%1"; }" [(set_attr "type" "branch") (set_attr "mode" "none") (set_attr "length" "1")])

(define_insn "branch_fp_eq" [(set (pc) (if_then_else (eq:CC_FP (reg:CC_FP 66) (const_int 0)) (match_operand 0 "pc_or_label_operand" "") (match_operand 1 "pc_or_label_operand" "")))] "" "* { mips_branch_likely = (final_sequence && INSN_ANNULLED_BRANCH_P (insn)); return (operands[0] != pc_rtx) ? "%*bc1f%?\t%0" : "%*bc1t%?\t%1"; }" [(set_attr "type" "branch") (set_attr "mode" "none") (set_attr "length" "1")])

(define_insn "branch_fp_eq_rev" [(set (pc) (if_then_else (eq:CC_REV_FP (reg:CC_REV_FP 66) (const_int 0)) (match_operand 0 "pc_or_label_operand" "") (match_operand 1 "pc_or_label_operand" "")))] "" "* { mips_branch_likely = (final_sequence && INSN_ANNULLED_BRANCH_P (insn)); return (operands[0] != pc_rtx) ? "%*bc1t%?\t%0" : "%*bc1f%?\t%1"; }" [(set_attr "type" "branch") (set_attr "mode" "none") (set_attr "length" "1")])

(define_insn "branch_zero" [(set (pc) (if_then_else (match_operator:SI 0 "cmp_op" [(match_operand:SI 1 "arith32_operand" "rn") (const_int 0)]) (match_operand 2 "pc_or_label_operand" "") (match_operand 3 "pc_or_label_operand" "")))] "" "* { mips_branch_likely = (final_sequence && INSN_ANNULLED_BRANCH_P (insn));

/* Handle places where CSE has folded a constant into the register operand. */ if (GET_CODE (operands[1]) == CONST_INT) { int value = INTVAL (operands[1]); int truth = 0;

  switch (GET_CODE (operands[0]))
{
default:  abort ();
case EQ:  truth = (value == 0);			break;
case NE:  truth = (value != 0);			break;
case GT:  truth = (value >  0);			break;
case GE:  truth = (value >= 0);			break;
case LT:  truth = (value <  0);			break;
case LE:  truth = (value <= 0);			break;
case GTU: truth = (((unsigned)value) >  0);	break;
case GEU: truth = 1;				break;
case LTU: truth = 0;				break;
case LEU: truth = (((unsigned)value) <= 0);	break;
}

  if (operands[2] != pc_rtx)
return (truth) ? \"%*j\\t%2\" : \"#bne\\t%z1,%.,%2\";
  else
return (truth) ? \"#bne\\t%z1,%.,%3\" : \"%*j\\t%3\";
}

if (operands[2] != pc_rtx) { /* normal jump */ switch (GET_CODE (operands[0])) { case EQ: return "%*beq%?\t%z1,%.,%2"; case NE: return "%*bne%?\t%z1,%.,%2"; case GTU: return "%*bne%?\t%z1,%.,%2"; case LEU: return "%*beq%?\t%z1,%.,%2"; case GEU: return "%*j\t%2"; case LTU: return "#%*bltuz\t%z1,%2"; }

  return \"%*b%C0z%?\\t%z1,%2\";
}

else { /* inverted jump */ switch (GET_CODE (operands[0])) { case EQ: return "%*bne%?\t%z1,%.,%3"; case NE: return "%*beq%?\t%z1,%.,%3"; case GTU: return "%*beq%?\t%z1,%.,%3"; case LEU: return "%*bne%?\t%z1,%.,%3"; case GEU: return "#%*bgeuz\t%z1,%3"; case LTU: return "%*j\t%3"; }

  return \"%*b%N0z%?\\t%z1,%3\";
}

}" [(set_attr "type" "branch") (set_attr "mode" "none") (set_attr "length" "1")])

(define_insn "branch_equality" [(set (pc) (if_then_else (match_operator:SI 0 "equality_op" [(match_operand:SI 1 "register_operand" "d") (match_operand:SI 2 "register_operand" "d")]) (match_operand 3 "pc_or_label_operand" "") (match_operand 4 "pc_or_label_operand" "")))] "" "* { mips_branch_likely = (final_sequence && INSN_ANNULLED_BRANCH_P (insn)); return (operands[3] != pc_rtx) ? "%*b%C0%?\t%z1,%z2,%3" : "%*b%N0%?\t%z1,%z2,%4"; }" [(set_attr "type" "branch") (set_attr "mode" "none") (set_attr "length" "1")])

(define_expand "beq" [(set (pc) (if_then_else (eq:CC_EQ (cc0) (const_int 0)) (label_ref (match_operand 0 "" "")) (pc)))] "" " { if (operands[0]) /* avoid unused code warning */ { gen_conditional_branch (operands, EQ); DONE; } }")

(define_expand "bne" [(set (pc) (if_then_else (ne:CC_EQ (cc0) (const_int 0)) (label_ref (match_operand 0 "" "")) (pc)))] "" " { if (operands[0]) /* avoid unused code warning */ { gen_conditional_branch (operands, NE); DONE; } }")

(define_expand "bgt" [(set (pc) (if_then_else (gt:CC (cc0) (const_int 0)) (label_ref (match_operand 0 "" "")) (pc)))] "" " { if (operands[0]) /* avoid unused code warning */ { gen_conditional_branch (operands, GT); DONE; } }")

(define_expand "bge" [(set (pc) (if_then_else (ge:CC (cc0) (const_int 0)) (label_ref (match_operand 0 "" "")) (pc)))] "" " { if (operands[0]) /* avoid unused code warning */ { gen_conditional_branch (operands, GE); DONE; } }")

(define_expand "blt" [(set (pc) (if_then_else (lt:CC (cc0) (const_int 0)) (label_ref (match_operand 0 "" "")) (pc)))] "" " { if (operands[0]) /* avoid unused code warning */ { gen_conditional_branch (operands, LT); DONE; } }")

(define_expand "ble" [(set (pc) (if_then_else (le:CC (cc0) (const_int 0)) (label_ref (match_operand 0 "" "")) (pc)))] "" " { if (operands[0]) /* avoid unused code warning */ { gen_conditional_branch (operands, LE); DONE; } }")

(define_expand "bgtu" [(set (pc) (if_then_else (gtu:CC (cc0) (const_int 0)) (label_ref (match_operand 0 "" "")) (pc)))] "" " { if (operands[0]) /* avoid unused code warning */ { gen_conditional_branch (operands, GTU); DONE; } }")

(define_expand "bgeu" [(set (pc) (if_then_else (geu:CC (cc0) (const_int 0)) (label_ref (match_operand 0 "" "")) (pc)))] "" " { if (operands[0]) /* avoid unused code warning */ { gen_conditional_branch (operands, GEU); DONE; } }")

(define_expand "bltu" [(set (pc) (if_then_else (ltu:CC (cc0) (const_int 0)) (label_ref (match_operand 0 "" "")) (pc)))] "" " { if (operands[0]) /* avoid unused code warning */ { gen_conditional_branch (operands, LTU); DONE; } }")

(define_expand "bleu" [(set (pc) (if_then_else (leu:CC (cc0) (const_int 0)) (label_ref (match_operand 0 "" "")) (pc)))] "" " { if (operands[0]) /* avoid unused code warning */ { gen_conditional_branch (operands, LEU); DONE; } }")

;; ;; .................... ;; ;; SETTING A REGISTER FROM A COMPARISON ;; ;; ....................

(define_expand "seq" [(set (match_operand:SI 0 "register_operand" "=d") (eq:SI (match_dup 1) (match_dup 2)))] "" " { extern rtx force_reg ();

if (branch_type != CMP_SI) FAIL;

/* set up operands from compare. */ operands[1] = branch_cmp[0]; operands[2] = branch_cmp[1];

if (!TARGET_DEBUG_C_MODE) { gen_int_relational (EQ, operands[0], operands[1], operands[2], (int *)0); DONE; }

if (GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) < 0) operands[2] = force_reg (SImode, operands[2]);

/* fall through and generate default code */ }")

(define_insn "seq_si_zero" [(set (match_operand:SI 0 "register_operand" "=d") (eq:SI (match_operand:SI 1 "register_operand" "d") (const_int 0)))] "" "sltu\t%0,%1,1" [(set_attr "type" "arith") (set_attr "mode" "SI") (set_attr "length" "1")])

(define_insn "seq_si" [(set (match_operand:SI 0 "register_operand" "=d,d") (eq:SI (match_operand:SI 1 "register_operand" "%d,d") (match_operand:SI 2 "uns_arith_operand" "d,K")))] "TARGET_DEBUG_C_MODE" "@ xor\t%0,%1,%2;sltu\t%0,%0,1 xori\t%0,%1,%2;sltu\t%0,%0,1" [(set_attr "type" "arith,arith") (set_attr "mode" "SI,SI") (set_attr "length" "2,2")])

(define_split [(set (match_operand:SI 0 "register_operand" "") (eq:SI (match_operand:SI 1 "register_operand" "") (match_operand:SI 2 "uns_arith_operand" "")))] "TARGET_DEBUG_C_MODE && !TARGET_DEBUG_D_MODE && (GET_CODE (operands[2]) != CONST_INT || INTVAL (operands[2]) != 0)" [(set (match_dup 0) (xor:SI (match_dup 1) (match_dup 2))) (set (match_dup 0) (ltu:SI (match_dup 0) (const_int 1)))] "")

(define_expand "sne" [(set (match_operand:SI 0 "register_operand" "=d") (ne:SI (match_dup 1) (match_dup 2)))] "" " { extern rtx force_reg ();

if (branch_type != CMP_SI) FAIL;

/* set up operands from compare. */ operands[1] = branch_cmp[0]; operands[2] = branch_cmp[1];

if (!TARGET_DEBUG_C_MODE) { gen_int_relational (NE, operands[0], operands[1], operands[2], (int *)0); DONE; }

if (GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) < 0) operands[2] = force_reg (SImode, operands[2]);

/* fall through and generate default code */ }")

(define_insn "sne_si_zero" [(set (match_operand:SI 0 "register_operand" "=d") (ne:SI (match_operand:SI 1 "register_operand" "d") (const_int 0)))] "" "sltu\t%0,%.,%1" [(set_attr "type" "arith") (set_attr "mode" "SI") (set_attr "length" "1")])

(define_insn "sne_si" [(set (match_operand:SI 0 "register_operand" "=d,d") (ne:SI (match_operand:SI 1 "register_operand" "%d,d") (match_operand:SI 2 "uns_arith_operand" "d,K")))] "TARGET_DEBUG_C_MODE" "@ xor\t%0,%1,%2;sltu\t%0,%.,%0 xori\t%0,%1,%x2;sltu\t%0,%.,%0" [(set_attr "type" "arith,arith") (set_attr "mode" "SI,SI") (set_attr "length" "2,2")])

(define_split [(set (match_operand:SI 0 "register_operand" "") (ne:SI (match_operand:SI 1 "register_operand" "") (match_operand:SI 2 "uns_arith_operand" "")))] "TARGET_DEBUG_C_MODE && !TARGET_DEBUG_D_MODE && (GET_CODE (operands[2]) != CONST_INT || INTVAL (operands[2]) != 0)" [(set (match_dup 0) (xor:SI (match_dup 1) (match_dup 2))) (set (match_dup 0) (gtu:SI (match_dup 0) (const_int 0)))] "")

(define_expand "sgt" [(set (match_operand:SI 0 "register_operand" "=d") (gt:SI (match_dup 1) (match_dup 2)))] "" " { extern rtx force_reg ();

if (branch_type != CMP_SI) FAIL;

/* set up operands from compare. */ operands[1] = branch_cmp[0]; operands[2] = branch_cmp[1];

if (!TARGET_DEBUG_C_MODE) { gen_int_relational (GT, operands[0], operands[1], operands[2], (int *)0); DONE; }

if (GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) != 0) operands[2] = force_reg (SImode, operands[2]);

/* fall through and generate default code */ }")

(define_insn "sgt_si" [(set (match_operand:SI 0 "register_operand" "=d") (gt:SI (match_operand:SI 1 "register_operand" "d") (match_operand:SI 2 "reg_or_0_operand" "dJ")))] "" "slt\t%0,%z2,%1" [(set_attr "type" "arith") (set_attr "mode" "SI") (set_attr "length" "1")])

(define_expand "sge" [(set (match_operand:SI 0 "register_operand" "=d") (ge:SI (match_dup 1) (match_dup 2)))] "" " { if (branch_type != CMP_SI) FAIL;

/* set up operands from compare. */ operands[1] = branch_cmp[0]; operands[2] = branch_cmp[1];

if (!TARGET_DEBUG_C_MODE) { gen_int_relational (GE, operands[0], operands[1], operands[2], (int *)0); DONE; }

/* fall through and generate default code */ }")

(define_insn "sge_si" [(set (match_operand:SI 0 "register_operand" "=d") (ge:SI (match_operand:SI 1 "register_operand" "d") (match_operand:SI 2 "arith_operand" "dI")))] "TARGET_DEBUG_C_MODE" "slt\t%0,%1,%2;xori\t%0,%0,0x0001" [(set_attr "type" "arith") (set_attr "mode" "SI") (set_attr "length" "2")])

(define_split [(set (match_operand:SI 0 "register_operand" "") (ge:SI (match_operand:SI 1 "register_operand" "") (match_operand:SI 2 "arith_operand" "")))] "TARGET_DEBUG_C_MODE && !TARGET_DEBUG_D_MODE" [(set (match_dup 0) (lt:SI (match_dup 1) (match_dup 2))) (set (match_dup 0) (xor:SI (match_dup 0) (const_int 1)))] "")

(define_expand "slt" [(set (match_operand:SI 0 "register_operand" "=d") (lt:SI (match_dup 1) (match_dup 2)))] "" " { if (branch_type != CMP_SI) FAIL;

/* set up operands from compare. */ operands[1] = branch_cmp[0]; operands[2] = branch_cmp[1];

if (!TARGET_DEBUG_C_MODE) { gen_int_relational (LT, operands[0], operands[1], operands[2], (int *)0); DONE; }

/* fall through and generate default code */ }")

(define_insn "slt_si" [(set (match_operand:SI 0 "register_operand" "=d") (lt:SI (match_operand:SI 1 "register_operand" "d") (match_operand:SI 2 "arith_operand" "dI")))] "" "slt\t%0,%1,%2" [(set_attr "type" "arith") (set_attr "mode" "SI") (set_attr "length" "1")])

(define_expand "sle" [(set (match_operand:SI 0 "register_operand" "=d") (le:SI (match_dup 1) (match_dup 2)))] "" " { extern rtx force_reg ();

if (branch_type != CMP_SI) FAIL;

/* set up operands from compare. */ operands[1] = branch_cmp[0]; operands[2] = branch_cmp[1];

if (!TARGET_DEBUG_C_MODE) { gen_int_relational (LE, operands[0], operands[1], operands[2], (int *)0); DONE; }

if (GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) >= 32767) operands[2] = force_reg (SImode, operands[2]);

/* fall through and generate default code */ }")

(define_insn "sle_si_const" [(set (match_operand:SI 0 "register_operand" "=d") (le:SI (match_operand:SI 1 "register_operand" "d") (match_operand:SI 2 "small_int" "I")))] "INTVAL (operands[2]) < 32767" "* { operands[2] = gen_rtx (CONST_INT, VOIDmode, INTVAL (operands[2])+1); return "slt\t%0,%1,%2"; }" [(set_attr "type" "arith") (set_attr "mode" "SI") (set_attr "length" "1")])

(define_insn "sle_si_reg" [(set (match_operand:SI 0 "register_operand" "=d") (le:SI (match_operand:SI 1 "register_operand" "d") (match_operand:SI 2 "register_operand" "d")))] "TARGET_DEBUG_C_MODE" "slt\t%0,%z2,%1;xori\t%0,%0,0x0001" [(set_attr "type" "arith") (set_attr "mode" "SI") (set_attr "length" "2")])

(define_split [(set (match_operand:SI 0 "register_operand" "") (le:SI (match_operand:SI 1 "register_operand" "") (match_operand:SI 2 "register_operand" "")))] "TARGET_DEBUG_C_MODE && !TARGET_DEBUG_D_MODE" [(set (match_dup 0) (lt:SI (match_dup 2) (match_dup 1))) (set (match_dup 0) (xor:SI (match_dup 0) (const_int 1)))] "")

(define_expand "sgtu" [(set (match_operand:SI 0 "register_operand" "=d") (gtu:SI (match_dup 1) (match_dup 2)))] "" " { extern rtx force_reg ();

if (branch_type != CMP_SI) FAIL;

/* set up operands from compare. */ operands[1] = branch_cmp[0]; operands[2] = branch_cmp[1];

if (!TARGET_DEBUG_C_MODE) { gen_int_relational (GTU, operands[0], operands[1], operands[2], (int *)0); DONE; }

if (GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) != 0) operands[2] = force_reg (SImode, operands[2]);

/* fall through and generate default code */ }")

(define_insn "sgtu_si" [(set (match_operand:SI 0 "register_operand" "=d") (gtu:SI (match_operand:SI 1 "register_operand" "d") (match_operand:SI 2 "reg_or_0_operand" "dJ")))] "" "sltu\t%0,%z2,%1" [(set_attr "type" "arith") (set_attr "mode" "SI") (set_attr "length" "1")])

(define_expand "sgeu" [(set (match_operand:SI 0 "register_operand" "=d") (geu:SI (match_dup 1) (match_dup 2)))] "" " { if (branch_type != CMP_SI) FAIL;

/* set up operands from compare. */ operands[1] = branch_cmp[0]; operands[2] = branch_cmp[1];

if (!TARGET_DEBUG_C_MODE) { gen_int_relational (GEU, operands[0], operands[1], operands[2], (int *)0); DONE; }

/* fall through and generate default code */ }")

(define_insn "sgeu_si" [(set (match_operand:SI 0 "register_operand" "=d") (geu:SI (match_operand:SI 1 "register_operand" "d") (match_operand:SI 2 "arith_operand" "dI")))] "TARGET_DEBUG_C_MODE" "sltu\t%0,%1,%2;xori\t%0,%0,0x0001" [(set_attr "type" "arith") (set_attr "mode" "SI") (set_attr "length" "2")])

(define_split [(set (match_operand:SI 0 "register_operand" "") (geu:SI (match_operand:SI 1 "register_operand" "") (match_operand:SI 2 "arith_operand" "")))] "TARGET_DEBUG_C_MODE && !TARGET_DEBUG_D_MODE" [(set (match_dup 0) (ltu:SI (match_dup 1) (match_dup 2))) (set (match_dup 0) (xor:SI (match_dup 0) (const_int 1)))] "")

(define_expand "sltu" [(set (match_operand:SI 0 "register_operand" "=d") (ltu:SI (match_dup 1) (match_dup 2)))] "" " { if (branch_type != CMP_SI) FAIL;

/* set up operands from compare. */ operands[1] = branch_cmp[0]; operands[2] = branch_cmp[1];

if (!TARGET_DEBUG_C_MODE) { gen_int_relational (LTU, operands[0], operands[1], operands[2], (int *)0); DONE; }

/* fall through and generate default code */ }")

(define_insn "sltu_si" [(set (match_operand:SI 0 "register_operand" "=d") (ltu:SI (match_operand:SI 1 "register_operand" "d") (match_operand:SI 2 "arith_operand" "dI")))] "" "sltu\t%0,%1,%2" [(set_attr "type" "arith") (set_attr "mode" "SI") (set_attr "length" "1")])

(define_expand "sleu" [(set (match_operand:SI 0 "register_operand" "=d") (leu:SI (match_dup 1) (match_dup 2)))] "" " { extern rtx force_reg ();

if (branch_type != CMP_SI) FAIL;

/* set up operands from compare. */ operands[1] = branch_cmp[0]; operands[2] = branch_cmp[1];

if (!TARGET_DEBUG_C_MODE) { gen_int_relational (LEU, operands[0], operands[1], operands[2], (int *)0); DONE; }

if (GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) >= 32767) operands[2] = force_reg (SImode, operands[2]);

/* fall through and generate default code */ }")

(define_insn "sleu_si_const" [(set (match_operand:SI 0 "register_operand" "=d") (leu:SI (match_operand:SI 1 "register_operand" "d") (match_operand:SI 2 "small_int" "I")))] "INTVAL (operands[2]) < 32767" "* { operands[2] = gen_rtx (CONST_INT, VOIDmode, INTVAL (operands[2])+1); return "sltu\t%0,%1,%2"; }" [(set_attr "type" "arith") (set_attr "mode" "SI") (set_attr "length" "1")])

(define_insn "sleu_si_reg" [(set (match_operand:SI 0 "register_operand" "=d") (leu:SI (match_operand:SI 1 "register_operand" "d") (match_operand:SI 2 "register_operand" "d")))] "TARGET_DEBUG_C_MODE" "sltu\t%0,%z2,%1;xori\t%0,%0,0x0001" [(set_attr "type" "arith") (set_attr "mode" "SI") (set_attr "length" "2")])

(define_split [(set (match_operand:SI 0 "register_operand" "") (leu:SI (match_operand:SI 1 "register_operand" "") (match_operand:SI 2 "register_operand" "")))] "TARGET_DEBUG_C_MODE && !TARGET_DEBUG_D_MODE" [(set (match_dup 0) (ltu:SI (match_dup 2) (match_dup 1))) (set (match_dup 0) (xor:SI (match_dup 0) (const_int 1)))] "")

;; ;; .................... ;; ;; FLOATING POINT COMPARISONS ;; ;; ....................

(define_insn "seq_df" [(set (reg:CC_FP 66) (eq:CC_FP (match_operand:DF 0 "register_operand" "f") (match_operand:DF 1 "register_operand" "f")))] "" "* { rtx xoperands[10]; xoperands[0] = gen_rtx (REG, CC_FPmode, FPSW_REGNUM); xoperands[1] = operands[0]; xoperands[2] = operands[1];

return mips_fill_delay_slot ("c.eq.d\t%0,%1", DELAY_FCMP, xoperands, insn); }" [(set_attr "type" "fcmp") (set_attr "mode" "FPSW") (set_attr "length" "1")])

(define_insn "sne_df" [(set (reg:CC_REV_FP 66) (ne:CC_REV_FP (match_operand:DF 0 "register_operand" "f") (match_operand:DF 1 "register_operand" "f")))] "" "* { rtx xoperands[10]; xoperands[0] = gen_rtx (REG, CC_FPmode, FPSW_REGNUM); xoperands[1] = operands[0]; xoperands[2] = operands[1];

return mips_fill_delay_slot ("c.eq.d\t%0,%1", DELAY_FCMP, xoperands, insn); }" [(set_attr "type" "fcmp") (set_attr "mode" "FPSW") (set_attr "length" "1")])

(define_insn "slt_df" [(set (reg:CC_FP 66) (lt:CC_FP (match_operand:DF 0 "register_operand" "f") (match_operand:DF 1 "register_operand" "f")))] "" "* { rtx xoperands[10]; xoperands[0] = gen_rtx (REG, CC_FPmode, FPSW_REGNUM); xoperands[1] = operands[0]; xoperands[2] = operands[1];

return mips_fill_delay_slot ("c.lt.d\t%0,%1", DELAY_FCMP, xoperands, insn); }" [(set_attr "type" "fcmp") (set_attr "mode" "FPSW") (set_attr "length" "1")])

(define_insn "sle_df" [(set (reg:CC_FP 66) (le:CC_FP (match_operand:DF 0 "register_operand" "f") (match_operand:DF 1 "register_operand" "f")))] "" "* { rtx xoperands[10]; xoperands[0] = gen_rtx (REG, CC_FPmode, FPSW_REGNUM); xoperands[1] = operands[0]; xoperands[2] = operands[1];

return mips_fill_delay_slot ("c.le.d\t%0,%1", DELAY_FCMP, xoperands, insn); }" [(set_attr "type" "fcmp") (set_attr "mode" "FPSW") (set_attr "length" "1")])

(define_insn "sgt_df" [(set (reg:CC_FP 66) (gt:CC_FP (match_operand:DF 0 "register_operand" "f") (match_operand:DF 1 "register_operand" "f")))] "" "* { rtx xoperands[10]; xoperands[0] = gen_rtx (REG, CC_FPmode, FPSW_REGNUM); xoperands[1] = operands[0]; xoperands[2] = operands[1];

return mips_fill_delay_slot ("c.lt.d\t%1,%0", DELAY_FCMP, xoperands, insn); }" [(set_attr "type" "fcmp") (set_attr "mode" "FPSW") (set_attr "length" "1")])

(define_insn "sge_df" [(set (reg:CC_FP 66) (ge:CC_FP (match_operand:DF 0 "register_operand" "f") (match_operand:DF 1 "register_operand" "f")))] "" "* { rtx xoperands[10]; xoperands[0] = gen_rtx (REG, CC_FPmode, FPSW_REGNUM); xoperands[1] = operands[0]; xoperands[2] = operands[1];

return mips_fill_delay_slot ("c.le.d\t%1,%0", DELAY_FCMP, xoperands, insn); }" [(set_attr "type" "fcmp") (set_attr "mode" "FPSW") (set_attr "length" "1")])

(define_insn "seq_sf" [(set (reg:CC_FP 66) (eq:CC_FP (match_operand:SF 0 "register_operand" "f") (match_operand:SF 1 "register_operand" "f")))] "" "* { rtx xoperands[10]; xoperands[0] = gen_rtx (REG, CC_FPmode, FPSW_REGNUM); xoperands[1] = operands[0]; xoperands[2] = operands[1];

return mips_fill_delay_slot ("c.eq.s\t%0,%1", DELAY_FCMP, xoperands, insn); }" [(set_attr "type" "fcmp") (set_attr "mode" "FPSW") (set_attr "length" "1")])

(define_insn "sne_sf" [(set (reg:CC_REV_FP 66) (ne:CC_REV_FP (match_operand:SF 0 "register_operand" "f") (match_operand:SF 1 "register_operand" "f")))] "" "* { rtx xoperands[10]; xoperands[0] = gen_rtx (REG, CC_FPmode, FPSW_REGNUM); xoperands[1] = operands[0]; xoperands[2] = operands[1];

return mips_fill_delay_slot ("c.eq.s\t%0,%1", DELAY_FCMP, xoperands, insn); }" [(set_attr "type" "fcmp") (set_attr "mode" "FPSW") (set_attr "length" "1")])

(define_insn "slt_sf" [(set (reg:CC_FP 66) (lt:CC_FP (match_operand:SF 0 "register_operand" "f") (match_operand:SF 1 "register_operand" "f")))] "" "* { rtx xoperands[10]; xoperands[0] = gen_rtx (REG, CC_FPmode, FPSW_REGNUM); xoperands[1] = operands[0]; xoperands[2] = operands[1];

return mips_fill_delay_slot ("c.lt.s\t%0,%1", DELAY_FCMP, xoperands, insn); }" [(set_attr "type" "fcmp") (set_attr "mode" "FPSW") (set_attr "length" "1")])

(define_insn "sle_sf" [(set (reg:CC_FP 66) (le:CC_FP (match_operand:SF 0 "register_operand" "f") (match_operand:SF 1 "register_operand" "f")))] "" "* { rtx xoperands[10]; xoperands[0] = gen_rtx (REG, CC_FPmode, FPSW_REGNUM); xoperands[1] = operands[0]; xoperands[2] = operands[1];

return mips_fill_delay_slot ("c.le.s\t%0,%1", DELAY_FCMP, xoperands, insn); }" [(set_attr "type" "fcmp") (set_attr "mode" "FPSW") (set_attr "length" "1")])

(define_insn "sgt_sf" [(set (reg:CC_FP 66) (gt:CC_FP (match_operand:SF 0 "register_operand" "f") (match_operand:SF 1 "register_operand" "f")))] "" "* { rtx xoperands[10]; xoperands[0] = gen_rtx (REG, CC_FPmode, FPSW_REGNUM); xoperands[1] = operands[0]; xoperands[2] = operands[1];

return mips_fill_delay_slot ("c.lt.s\t%1,%0", DELAY_FCMP, xoperands, insn); }" [(set_attr "type" "fcmp") (set_attr "mode" "FPSW") (set_attr "length" "1")])

(define_insn "sge_sf" [(set (reg:CC_FP 66) (ge:CC_FP (match_operand:SF 0 "register_operand" "f") (match_operand:SF 1 "register_operand" "f")))] "" "* { rtx xoperands[10]; xoperands[0] = gen_rtx (REG, CC_FPmode, FPSW_REGNUM); xoperands[1] = operands[0]; xoperands[2] = operands[1];

return mips_fill_delay_slot ("c.le.s\t%1,%0", DELAY_FCMP, xoperands, insn); }" [(set_attr "type" "fcmp") (set_attr "mode" "FPSW") (set_attr "length" "1")])

;; ;; .................... ;; ;; UNCONDITIONAL BRANCHES ;; ;; ....................

;; Unconditional branches.

(define_insn "jump" [(set (pc) (label_ref (match_operand 0 "" "")))] "" "* { if (GET_CODE (operands[0]) == REG) return "%*j\t%0"; else return "%*j\t%l0"; }" [(set_attr "type" "jump") (set_attr "mode" "none") (set_attr "length" "1")])

(define_insn "indirect_jump" [(set (pc) (match_operand:SI 0 "register_operand" "d"))] "" "%*j\t%0" [(set_attr "type" "jump") (set_attr "mode" "none") (set_attr "length" "1")])

(define_insn "tablejump" [(set (pc) (match_operand:SI 0 "register_operand" "d")) (use (label_ref (match_operand 1 "" "")))] "" "%*j\t%0" [(set_attr "type" "jump") (set_attr "mode" "none") (set_attr "length" "1")])

;; Function return, only allow after optimization, so that we can ;; eliminate jumps to jumps if no stack space is used.

(define_insn "return" [(return)] "null_epilogue ()" "* { operands[0] = gen_rtx (REG, SImode, GP_REG_FIRST + 31); return "%*j\t%0"; }" [(set_attr "type" "jump") (set_attr "mode" "none") (set_attr "length" "1")])

;; ;; .................... ;; ;; FUNCTION CALLS ;; ;; ....................

;; calls.c now passes a third argument, make saber happy

(define_expand "call" [(parallel [(call (match_operand 0 "memory_operand" "m") (match_operand 1 "" "i")) (clobber (match_operand 2 "" ""))])] ;; overwrite op2 with $31 "" " { rtx addr;

operands[2] = gen_rtx (REG, SImode, GP_REG_FIRST + 31);

addr = XEXP (operands[0], 0); if (GET_CODE (addr) != REG && !CONSTANT_ADDRESS_P (addr)) XEXP (operands[0], 0) = force_reg (FUNCTION_MODE, addr); }")

(define_insn "call_internal" [(call (match_operand 0 "memory_operand" "m") (match_operand 1 "" "i")) (clobber (match_operand:SI 2 "register_operand" "=d"))] "" "* { register rtx target = XEXP (operands[0], 0);

if (GET_CODE (target) == SYMBOL_REF) return "%*jal\t%0";

else { operands[0] = target; operands[1] = gen_rtx (REG, SImode, GP_REG_FIRST + 31); return "%*jal\t%1,%0"; } }" [(set_attr "type" "call") (set_attr "mode" "none") (set_attr "length" "1")])

;; calls.c now passes a fourth argument, make saber happy

(define_expand "call_value" [(parallel [(set (match_operand 0 "register_operand" "=df") (call (match_operand 1 "memory_operand" "m") (match_operand 2 "" "i"))) (clobber (match_operand 3 "" ""))])] ;; overwrite op3 with $31 "" " { rtx addr;

operands[3] = gen_rtx (REG, SImode, GP_REG_FIRST + 31);

addr = XEXP (operands[1], 0); if (GET_CODE (addr) != REG && !CONSTANT_ADDRESS_P (addr)) XEXP (operands[1], 0) = force_reg (FUNCTION_MODE, addr); }")

(define_insn "call_value_internal" [(set (match_operand 0 "register_operand" "=df") (call (match_operand 1 "memory_operand" "m") (match_operand 2 "" "i"))) (clobber (match_operand:SI 3 "register_operand" "=d"))] "" "* { register rtx target = XEXP (operands[1], 0);

if (GET_CODE (target) == SYMBOL_REF) return "%*jal\t%1";

else { operands[1] = target; operands[2] = gen_rtx (REG, SImode, GP_REG_FIRST + 31); return "%*jal\t%2,%1"; } }" [(set_attr "type" "call") (set_attr "mode" "none") (set_attr "length" "1")])

;; ;; .................... ;; ;; MISC. ;; ;; .................... ;;

(define_insn "nop" [(const_int 0)] "" "%(nop%)" [(set_attr "type" "nop") (set_attr "mode" "none") (set_attr "length" "1")])

(define_expand "probe" [(set (match_dup 0) (match_dup 1))] "" " { operands[0] = gen_reg_rtx (SImode); operands[1] = gen_rtx (MEM, SImode, stack_pointer_rtx); MEM_VOLATILE_P (operands[1]) = TRUE;

/* fall through and generate default code */ }")

;; ;; Local variables: ;; mode:emacs-lisp ;; comment-start: ";; " ;; eval: (set-syntax-table (copy-sequence (syntax-table))) ;; eval: (modify-syntax-entry ?[ "(]") ;; eval: (modify-syntax-entry ?] ")[") ;; eval: (modify-syntax-entry ?{ "(}") ;; eval: (modify-syntax-entry ?} "){") ;; End: