X-Git-Url: http://git.sourceforge.jp/view?a=blobdiff_plain;f=gcc%2Fconfig%2Fmips%2Fmips.md;h=8a6440e41c3d81ddcbd090692f37e74d8f826820;hb=e375923d7f6c366c2c53e2612ff504be0b8a1602;hp=6df4084b2aeea0c47268f990ee0df45df520ec19;hpb=4bf8b1d95b1873d9c3cda8dc240688a5eeed4646;p=pf3gnuchains%2Fgcc-fork.git diff --git a/gcc/config/mips/mips.md b/gcc/config/mips/mips.md index 6df4084b2ae..8a6440e41c3 100644 --- a/gcc/config/mips/mips.md +++ b/gcc/config/mips/mips.md @@ -1,90 +1,81 @@ ;; Mips.md Machine Description for MIPS based processors ;; Copyright (C) 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, -;; 1999, 2000, 2001, 2002, 2003 Free Software Foundation, Inc. +;; 1999, 2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc. ;; Contributed by A. Lichnewsky, lich@inria.inria.fr ;; Changes by Michael Meissner, meissner@osf.org ;; 64 bit r4000 support by Ian Lance Taylor, ian@cygnus.com, and ;; Brendan Eich, brendan@microunity.com. -;; This file is part of GNU CC. +;; This file is part of GCC. -;; GNU CC is free software; you can redistribute it and/or modify +;; GCC 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, +;; GCC 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 +;; along with GCC; see the file COPYING. If not, write to ;; the Free Software Foundation, 59 Temple Place - Suite 330, ;; Boston, MA 02111-1307, USA. -;; ??? Currently does not have define_function_unit support for the R8000. -;; Must include new entries for fmadd in addition to existing entries. - (define_constants [(UNSPEC_LOAD_DF_LOW 0) (UNSPEC_LOAD_DF_HIGH 1) (UNSPEC_STORE_DF_HIGH 2) - (UNSPEC_GET_FNADDR 4) - (UNSPEC_BLOCKAGE 6) - (UNSPEC_CPRESTORE 8) - (UNSPEC_EH_RECEIVER 10) - (UNSPEC_EH_RETURN 11) - (UNSPEC_CONSTTABLE_QI 12) - (UNSPEC_CONSTTABLE_HI 13) - (UNSPEC_CONSTTABLE_SI 14) - (UNSPEC_CONSTTABLE_DI 15) - (UNSPEC_CONSTTABLE_SF 16) - (UNSPEC_CONSTTABLE_DF 17) - (UNSPEC_ALIGN_2 18) - (UNSPEC_ALIGN_4 19) - (UNSPEC_ALIGN_8 20) - (UNSPEC_HIGH 22) - (UNSPEC_LWL 23) - (UNSPEC_LWR 24) - (UNSPEC_SWL 25) - (UNSPEC_SWR 26) - (UNSPEC_LDL 27) - (UNSPEC_LDR 28) - (UNSPEC_SDL 29) - (UNSPEC_SDR 30) - - ;; Constants used in relocation unspecs. RELOC_GOT_PAGE and RELOC_GOT_DISP - ;; are really only available for n32 and n64. However, it is convenient - ;; to reuse them for SVR4 PIC, where they represent the local and global - ;; forms of R_MIPS_GOT16. - (RELOC_GPREL16 100) - (RELOC_GOT_HI 101) - (RELOC_GOT_LO 102) - (RELOC_GOT_PAGE 103) - (RELOC_GOT_DISP 104) - (RELOC_CALL16 105) - (RELOC_CALL_HI 106) - (RELOC_CALL_LO 107) - (RELOC_LOADGP_HI 108) - (RELOC_LOADGP_LO 109)]) + (UNSPEC_GET_FNADDR 3) + (UNSPEC_BLOCKAGE 4) + (UNSPEC_CPRESTORE 5) + (UNSPEC_EH_RECEIVER 6) + (UNSPEC_EH_RETURN 7) + (UNSPEC_CONSTTABLE_INT 8) + (UNSPEC_CONSTTABLE_FLOAT 9) + (UNSPEC_ALIGN 14) + (UNSPEC_HIGH 17) + (UNSPEC_LWL 18) + (UNSPEC_LWR 19) + (UNSPEC_SWL 20) + (UNSPEC_SWR 21) + (UNSPEC_LDL 22) + (UNSPEC_LDR 23) + (UNSPEC_SDL 24) + (UNSPEC_SDR 25) + (UNSPEC_LOADGP 26) + (UNSPEC_LOAD_CALL 27) + (UNSPEC_LOAD_GOT 28) + (UNSPEC_GP 29) + (UNSPEC_MFHILO 30) + + (UNSPEC_ADDRESS_FIRST 100) + + (FAKE_CALL_REGNO 79)]) + +(include "predicates.md") - ;; .................... ;; ;; Attributes ;; ;; .................... +(define_attr "got" "unset,xgot_high,load" + (const_string "unset")) + ;; For jal instructions, this attribute is DIRECT when the target address ;; is symbolic and INDIRECT when it is a register. (define_attr "jal" "unset,direct,indirect" (const_string "unset")) -;; True for multi-instruction jal macros. jal is always a macro -;; in SVR4 PIC since it includes an instruction to restore $gp. -;; Direct jals are also macros in NewABI PIC since they load the -;; target address into $25. +;; This attribute is YES if the instruction is a jal macro (not a +;; real jal instruction). +;; +;; jal is always a macro in SVR4 PIC since it includes an instruction to +;; restore $gp. Direct jals are also macros in NewABI PIC since they +;; load the target address into $25. (define_attr "jal_macro" "no,yes" (cond [(eq_attr "jal" "direct") (symbol_ref "TARGET_ABICALLS != 0") @@ -97,19 +88,27 @@ ;; jump unconditional jump ;; call unconditional call ;; load load instruction(s) +;; fpload floating point load +;; fpidxload floating point indexed load ;; store store instruction(s) -;; prefetch memory prefetch -;; move data movement within same register set +;; fpstore floating point store +;; fpidxstore floating point indexed store +;; prefetch memory prefetch (register + offset) +;; prefetchx memory indexed prefetch (register + register) ;; condmove conditional moves ;; xfer transfer to/from coprocessor -;; hilo transfer of hi/lo registers -;; arith integer arithmetic instruction -;; darith double precision integer arithmetic instructions +;; mthilo transfer to hi/lo registers +;; mfhilo transfer from hi/lo registers ;; const load constant +;; arith integer arithmetic and logical instructions +;; shift integer shift instructions +;; slt set less than instructions +;; clz the clz and clo instructions +;; trap trap if instructions ;; imul integer multiply ;; imadd integer multiply-add ;; idiv integer divide -;; icmp integer compare +;; fmove floating point register move ;; fadd floating point add/subtract ;; fmul floating point multiply ;; fmadd floating point multiply-add @@ -123,43 +122,73 @@ ;; multi multiword sequence (or user asm statements) ;; nop no operation (define_attr "type" - "unknown,branch,jump,call,load,store,prefetch,move,condmove,xfer,hilo,const,arith,darith,imul,imadd,idiv,icmp,fadd,fmul,fmadd,fdiv,fabs,fneg,fcmp,fcvt,fsqrt,frsqrt,multi,nop" - (cond [(eq_attr "jal" "!unset") - (const_string "call")] + "unknown,branch,jump,call,load,fpload,fpidxload,store,fpstore,fpidxstore,prefetch,prefetchx,condmove,xfer,mthilo,mfhilo,const,arith,shift,slt,clz,trap,imul,imadd,idiv,fmove,fadd,fmul,fmadd,fdiv,fabs,fneg,fcmp,fcvt,fsqrt,frsqrt,multi,nop" + (cond [(eq_attr "jal" "!unset") (const_string "call") + (eq_attr "got" "load") (const_string "load")] (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")) +(define_attr "mode" "unknown,none,QI,HI,SI,DI,SF,DF,FPSW" + (const_string "unknown")) ;; Is this an extended instruction in mips16 mode? (define_attr "extended_mips16" "no,yes" (const_string "no")) -;; Length (in # of bytes). A conditional branch is allowed only to a -;; location within a signed 18-bit offset of the delay slot. If that -;; provides too smal a range, we use the `j' instruction. This -;; instruction takes a 28-bit value, but that value is not an offset. -;; Instead, it's bitwise-ored with the high-order four bits of the -;; instruction in the delay slot, which means it cannot be used to -;; cross a 256MB boundary. We could fall back back on the jr, -;; instruction which allows full access to the entire address space, -;; but we do not do so at present. - +;; Length of instruction in bytes. (define_attr "length" "" - (cond [(eq_attr "type" "branch") - (cond [(lt (abs (minus (match_dup 1) (plus (pc) (const_int 4)))) - (const_int 131072)) - (const_int 4) - (ne (symbol_ref "flag_pic && ! TARGET_EMBEDDED_PIC") - (const_int 0)) + (cond [;; Direct branch instructions have a range of [-0x40000,0x3fffc]. + ;; If a branch is outside this range, we have a choice of two + ;; sequences. For PIC, an out-of-range branch like: + ;; + ;; bne r1,r2,target + ;; dslot + ;; + ;; becomes the equivalent of: + ;; + ;; beq r1,r2,1f + ;; dslot + ;; la $at,target + ;; jr $at + ;; nop + ;; 1: + ;; + ;; where the load address can be up to three instructions long + ;; (lw, nop, addiu). + ;; + ;; The non-PIC case is similar except that we use a direct + ;; jump instead of an la/jr pair. Since the target of this + ;; jump is an absolute 28-bit bit address (the other bits + ;; coming from the address of the delay slot) this form cannot + ;; cross a 256MB boundary. We could provide the option of + ;; using la/jr in this case too, but we do not do so at + ;; present. + ;; + ;; Note that this value does not account for the delay slot + ;; instruction, whose length is added separately. If the RTL + ;; pattern has no explicit delay slot, mips_adjust_insn_length + ;; will add the length of the implicit nop. The values for + ;; forward and backward branches will be different as well. + (eq_attr "type" "branch") + (cond [(and (le (minus (match_dup 1) (pc)) (const_int 131064)) + (le (minus (pc) (match_dup 1)) (const_int 131068))) + (const_int 4) + (ne (symbol_ref "flag_pic") (const_int 0)) (const_int 24) ] (const_int 12)) + + (eq_attr "got" "load") + (const_int 4) + (eq_attr "got" "xgot_high") + (const_int 8) + (eq_attr "type" "const") (symbol_ref "mips_const_insns (operands[1]) * 4") - (eq_attr "type" "load") + (eq_attr "type" "load,fpload,fpidxload") (symbol_ref "mips_fetch_insns (operands[1]) * 4") - (eq_attr "type" "store") + (eq_attr "type" "store,fpstore,fpidxstore") (symbol_ref "mips_fetch_insns (operands[0]) * 4") + ;; In the worst case, a call macro will take 8 instructions: ;; ;; lui $25,%call_hi(FOO) @@ -172,30 +201,34 @@ ;; nop (eq_attr "jal_macro" "yes") (const_int 32) + (and (eq_attr "extended_mips16" "yes") (ne (symbol_ref "TARGET_MIPS16") (const_int 0))) (const_int 8) - (and (eq_attr "type" "idiv") - (ne (symbol_ref "TARGET_CHECK_ZERO_DIV") (const_int 0))) - (cond [(ne (symbol_ref "TARGET_MIPS16") (const_int 0)) - (const_int 12)] - (const_int 16)) + + ;; Various VR4120 errata require a nop to be inserted after a macc + ;; instruction. The assembler does this for us, so account for + ;; the worst-case length here. + (and (eq_attr "type" "imadd") + (ne (symbol_ref "TARGET_FIX_VR4120") (const_int 0))) + (const_int 8) + + ;; VR4120 errata MD(4): if there are consecutive dmult instructions, + ;; the result of the second one is missed. The assembler should work + ;; around this by inserting a nop after the first dmult. + (and (eq_attr "type" "imul") + (and (eq_attr "mode" "DI") + (ne (symbol_ref "TARGET_FIX_VR4120") (const_int 0)))) + (const_int 8) + + (eq_attr "type" "idiv") + (symbol_ref "mips_idiv_insns () * 4") ] (const_int 4))) ;; Attribute describing the processor. This attribute must match exactly ;; with the processor_type enumeration in mips.h. - -;; Attribute describing the processor -;; (define_attr "cpu" "default,r3000,r6000,r4000" -;; (const -;; (cond [(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")))) - -;; ??? Fix everything that tests this attribute. (define_attr "cpu" - "default,4kc,5kc,20kc,m4k,r3000,r3900,r6000,r4000,r4100,r4111,r4120,r4300,r4600,r4650,r5000,r5400,r5500,r7000,r8000,r9000,sb1,sr71000" + "default,4kc,5kc,20kc,m4k,r3000,r3900,r6000,r4000,r4100,r4111,r4120,r4130,r4300,r4600,r4650,r5000,r5400,r5500,r7000,r8000,r9000,sb1,sr71000" (const (symbol_ref "mips_tune"))) ;; The type of hardware hazard associated with this instruction. @@ -203,7 +236,7 @@ ;; of this one. HILO means that the next two instructions cannot ;; write to HI or LO. (define_attr "hazard" "none,delay,hilo" - (cond [(and (eq_attr "type" "load") + (cond [(and (eq_attr "type" "load,fpload,fpidxload") (ne (symbol_ref "ISA_HAS_LOAD_DELAY") (const_int 0))) (const_string "delay") @@ -217,12 +250,11 @@ ;; The r4000 multiplication patterns include an mflo instruction. (and (eq_attr "type" "imul") - (ne (symbol_ref "TARGET_MIPS4000") (const_int 0))) + (ne (symbol_ref "TARGET_FIX_R4000") (const_int 0))) (const_string "hilo") - (and (eq_attr "type" "hilo") - (and (eq (symbol_ref "ISA_HAS_HILO_INTERLOCKS") (const_int 0)) - (match_operand 1 "hilo_operand" ""))) + (and (eq_attr "type" "mfhilo") + (eq (symbol_ref "ISA_HAS_HILO_INTERLOCKS") (const_int 0))) (const_string "hilo")] (const_string "none"))) @@ -239,23 +271,26 @@ (const_string "no"))) ;; Attribute defining whether or not we can use the branch-likely instructions - (define_attr "branch_likely" "no,yes" (const (if_then_else (ne (symbol_ref "GENERATE_BRANCHLIKELY") (const_int 0)) (const_string "yes") (const_string "no")))) +;; True if an instruction might assign to hi or lo when reloaded. +;; This is used by the TUNE_MACC_CHAINS code. +(define_attr "may_clobber_hilo" "no,yes" + (if_then_else (eq_attr "type" "imul,imadd,idiv,mthilo") + (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 +;; Branch, call and jump delay slots ;; ;; ......................... @@ -276,358 +311,38 @@ [(eq_attr "can_delay" "yes") (nil) (nil)]) - - - -;; ......................... -;; -;; Functional units -;; -;; ......................... - -; (define_function_unit NAME MULTIPLICITY SIMULTANEITY -; TEST READY-DELAY ISSUE-DELAY [CONFLICT-LIST]) - -;; Make the default case (PROCESSOR_DEFAULT) handle the worst case - -(define_function_unit "memory" 1 0 - (and (eq_attr "type" "load") - (eq_attr "cpu" "!r3000,r3900,r4600,r4650,r4100,r4120,r4300,r5000")) - 3 0) - -(define_function_unit "memory" 1 0 - (and (eq_attr "type" "load") - (eq_attr "cpu" "r3000,r3900,r4600,r4650,r4100,r4120,r4300,r5000")) - 2 0) - -(define_function_unit "memory" 1 0 (eq_attr "type" "store") 1 0) - -(define_function_unit "memory" 1 0 (eq_attr "type" "xfer") 2 0) - -(define_function_unit "imuldiv" 1 0 - (eq_attr "type" "hilo") - 1 3) - -(define_function_unit "imuldiv" 1 0 - (and (eq_attr "type" "imul,imadd") - (eq_attr "cpu" "!r3000,r3900,r4000,r4600,r4650,r4100,r4120,r4300,r5000")) - 17 17) - -;; On them mips16, we want to stronly discourage a mult from appearing -;; after an mflo, since that requires explicit nop instructions. We -;; do this by pretending that mflo ties up the function unit for long -;; enough that the scheduler will ignore load stalls and the like when -;; selecting instructions to between the two instructions. - -(define_function_unit "imuldiv" 1 0 - (and (eq_attr "type" "hilo") (ne (symbol_ref "TARGET_MIPS16") (const_int 0))) - 1 5) - -(define_function_unit "imuldiv" 1 0 - (and (eq_attr "type" "imul,imadd") (eq_attr "cpu" "r3000,r3900")) - 12 12) - -(define_function_unit "imuldiv" 1 0 - (and (eq_attr "type" "imul,imadd") (eq_attr "cpu" "r4000,r4600")) - 10 10) - -(define_function_unit "imuldiv" 1 0 - (and (eq_attr "type" "imul,imadd") (eq_attr "cpu" "r4650")) - 4 4) - -(define_function_unit "imuldiv" 1 0 - (and (eq_attr "type" "imul,imadd") - (and (eq_attr "mode" "SI") (eq_attr "cpu" "r4100,r4120"))) - 1 1) - -(define_function_unit "imuldiv" 1 0 - (and (eq_attr "type" "imul,imadd") - (and (eq_attr "mode" "DI") (eq_attr "cpu" "r4100,r4120"))) - 4 4) - -(define_function_unit "imuldiv" 1 0 - (and (eq_attr "type" "imul,imadd") - (and (eq_attr "mode" "SI") (eq_attr "cpu" "r4300,r5000"))) - 5 5) - -(define_function_unit "imuldiv" 1 0 - (and (eq_attr "type" "imul,imadd") - (and (eq_attr "mode" "DI") (eq_attr "cpu" "r4300"))) - 8 8) - -(define_function_unit "imuldiv" 1 0 - (and (eq_attr "type" "imul,imadd") - (and (eq_attr "mode" "DI") (eq_attr "cpu" "r5000"))) - 9 9) - -(define_function_unit "imuldiv" 1 0 - (and (eq_attr "type" "idiv") - (eq_attr "cpu" "!r3000,r3900,r4000,r4600,r4650,r4100,r4120,r4300,r5000")) - 38 38) - -(define_function_unit "imuldiv" 1 0 - (and (eq_attr "type" "idiv") (eq_attr "cpu" "r3000,r3900")) - 35 35) - -(define_function_unit "imuldiv" 1 0 - (and (eq_attr "type" "idiv") (eq_attr "cpu" "r4600")) - 42 42) - -(define_function_unit "imuldiv" 1 0 - (and (eq_attr "type" "idiv") (eq_attr "cpu" "r4650")) - 36 36) - -(define_function_unit "imuldiv" 1 0 - (and (eq_attr "type" "idiv") (eq_attr "cpu" "r4000")) - 69 69) - -(define_function_unit "imuldiv" 1 0 - (and (eq_attr "type" "idiv") - (and (eq_attr "mode" "SI") (eq_attr "cpu" "r4100,r4120"))) - 35 35) - -(define_function_unit "imuldiv" 1 0 - (and (eq_attr "type" "idiv") - (and (eq_attr "mode" "DI") (eq_attr "cpu" "r4100,r4120"))) - 67 67) - -(define_function_unit "imuldiv" 1 0 - (and (eq_attr "type" "idiv") - (and (eq_attr "mode" "SI") (eq_attr "cpu" "r4300"))) - 37 37) - -(define_function_unit "imuldiv" 1 0 - (and (eq_attr "type" "idiv") - (and (eq_attr "mode" "DI") (eq_attr "cpu" "r4300"))) - 69 69) - -(define_function_unit "imuldiv" 1 0 - (and (eq_attr "type" "idiv") - (and (eq_attr "mode" "SI") (eq_attr "cpu" "r5000"))) - 36 36) - -(define_function_unit "imuldiv" 1 0 - (and (eq_attr "type" "idiv") - (and (eq_attr "mode" "DI") (eq_attr "cpu" "r5000"))) - 68 68) - -;; The R4300 does *NOT* have a separate Floating Point Unit, instead -;; the FP hardware is part of the normal ALU circuitry. This means FP -;; instructions affect the pipe-line, and no functional unit -;; parallelism can occur on R4300 processors. To force GCC into coding -;; for only a single functional unit, we force the R4300 FP -;; instructions to be processed in the "imuldiv" unit. - -(define_function_unit "adder" 1 1 - (and (eq_attr "type" "fcmp") (eq_attr "cpu" "!r3000,r3900,r6000,r4300,r5000")) - 3 0) - -(define_function_unit "adder" 1 1 - (and (eq_attr "type" "fcmp") (eq_attr "cpu" "r3000,r3900,r6000")) - 2 0) - -(define_function_unit "adder" 1 1 - (and (eq_attr "type" "fcmp") (eq_attr "cpu" "r5000")) - 1 0) - -(define_function_unit "adder" 1 1 - (and (eq_attr "type" "fadd") (eq_attr "cpu" "!r3000,r3900,r6000,r4300")) - 4 0) - -(define_function_unit "adder" 1 1 - (and (eq_attr "type" "fadd") (eq_attr "cpu" "r3000,r3900")) - 2 0) - -(define_function_unit "adder" 1 1 - (and (eq_attr "type" "fadd") (eq_attr "cpu" "r6000")) - 3 0) - -(define_function_unit "adder" 1 1 - (and (eq_attr "type" "fabs,fneg") - (eq_attr "cpu" "!r3000,r3900,r4600,r4650,r4300,r5000")) - 2 0) - -(define_function_unit "adder" 1 1 - (and (eq_attr "type" "fabs,fneg") (eq_attr "cpu" "r3000,r3900,r4600,r4650,r5000")) - 1 0) - -(define_function_unit "mult" 1 1 - (and (eq_attr "type" "fmul") - (and (eq_attr "mode" "SF") - (eq_attr "cpu" "!r3000,r3900,r6000,r4600,r4650,r4300,r5000"))) - 7 0) - -(define_function_unit "mult" 1 1 - (and (eq_attr "type" "fmul") - (and (eq_attr "mode" "SF") (eq_attr "cpu" "r3000,r3900,r5000"))) - 4 0) - -(define_function_unit "mult" 1 1 - (and (eq_attr "type" "fmul") - (and (eq_attr "mode" "SF") (eq_attr "cpu" "r6000"))) - 5 0) - -(define_function_unit "mult" 1 1 - (and (eq_attr "type" "fmul") - (and (eq_attr "mode" "SF") (eq_attr "cpu" "r4600,r4650"))) - 8 0) - -(define_function_unit "mult" 1 1 - (and (eq_attr "type" "fmul") - (and (eq_attr "mode" "DF") (eq_attr "cpu" "!r3000,r3900,r6000,r4300,r5000"))) - 8 0) - -(define_function_unit "mult" 1 1 - (and (eq_attr "type" "fmul") - (and (eq_attr "mode" "DF") (eq_attr "cpu" "r3000,r3900,r5000"))) - 5 0) - -(define_function_unit "mult" 1 1 - (and (eq_attr "type" "fmul") - (and (eq_attr "mode" "DF") (eq_attr "cpu" "r6000"))) - 6 0) - -(define_function_unit "divide" 1 1 - (and (eq_attr "type" "fdiv") - (and (eq_attr "mode" "SF") - (eq_attr "cpu" "!r3000,r3900,r6000,r4600,r4650,r4300,r5000"))) - 23 0) - -(define_function_unit "divide" 1 1 - (and (eq_attr "type" "fdiv") - (and (eq_attr "mode" "SF") (eq_attr "cpu" "r3000,r3900"))) - 12 0) - -(define_function_unit "divide" 1 1 - (and (eq_attr "type" "fdiv") - (and (eq_attr "mode" "SF") (eq_attr "cpu" "r6000"))) - 15 0) - -(define_function_unit "divide" 1 1 - (and (eq_attr "type" "fdiv") - (and (eq_attr "mode" "SF") (eq_attr "cpu" "r4600,r4650"))) - 32 0) - -(define_function_unit "divide" 1 1 - (and (eq_attr "type" "fdiv") - (and (eq_attr "mode" "SF") (eq_attr "cpu" "r5000"))) - 21 0) - -(define_function_unit "divide" 1 1 - (and (eq_attr "type" "fdiv") - (and (eq_attr "mode" "DF") - (eq_attr "cpu" "!r3000,r3900,r6000,r4600,r4650,r4300"))) - 36 0) - -(define_function_unit "divide" 1 1 - (and (eq_attr "type" "fdiv") - (and (eq_attr "mode" "DF") (eq_attr "cpu" "r3000,r3900"))) - 19 0) - -(define_function_unit "divide" 1 1 - (and (eq_attr "type" "fdiv") - (and (eq_attr "mode" "DF") (eq_attr "cpu" "r6000"))) - 16 0) - -(define_function_unit "divide" 1 1 - (and (eq_attr "type" "fdiv") - (and (eq_attr "mode" "DF") (eq_attr "cpu" "r4600,r4650"))) - 61 0) - -;;; ??? Is this number right? -(define_function_unit "divide" 1 1 - (and (eq_attr "type" "fsqrt,frsqrt") - (and (eq_attr "mode" "SF") (eq_attr "cpu" "!r4600,r4650,r4300,r5000"))) - 54 0) - -(define_function_unit "divide" 1 1 - (and (eq_attr "type" "fsqrt,frsqrt") - (and (eq_attr "mode" "SF") (eq_attr "cpu" "r4600,r4650"))) - 31 0) - -(define_function_unit "divide" 1 1 - (and (eq_attr "type" "fsqrt,frsqrt") - (and (eq_attr "mode" "SF") (eq_attr "cpu" "r5000"))) - 21 0) - -;;; ??? Is this number right? -(define_function_unit "divide" 1 1 - (and (eq_attr "type" "fsqrt,frsqrt") - (and (eq_attr "mode" "DF") (eq_attr "cpu" "!r4600,r4650,r4300,r5000"))) - 112 0) - -(define_function_unit "divide" 1 1 - (and (eq_attr "type" "fsqrt,frsqrt") - (and (eq_attr "mode" "DF") (eq_attr "cpu" "r4600,r4650"))) - 60 0) - -(define_function_unit "divide" 1 1 - (and (eq_attr "type" "fsqrt,frsqrt") - (and (eq_attr "mode" "DF") (eq_attr "cpu" "r5000"))) - 36 0) - -;; R4300 FP instruction classes treated as part of the "imuldiv" -;; functional unit: - -(define_function_unit "imuldiv" 1 0 - (and (eq_attr "type" "fadd") (eq_attr "cpu" "r4300")) - 3 3) - -(define_function_unit "imuldiv" 1 0 - (and (eq_attr "type" "fcmp,fabs,fneg") (eq_attr "cpu" "r4300")) - 1 1) - -(define_function_unit "imuldiv" 1 0 - (and (eq_attr "type" "fmul") (and (eq_attr "mode" "SF") (eq_attr "cpu" "r4300"))) - 5 5) -(define_function_unit "imuldiv" 1 0 - (and (eq_attr "type" "fmul") (and (eq_attr "mode" "DF") (eq_attr "cpu" "r4300"))) - 8 8) - -(define_function_unit "imuldiv" 1 0 - (and (and (eq_attr "type" "fdiv") (eq_attr "type" "fsqrt,frsqrt")) - (and (eq_attr "mode" "SF") (eq_attr "cpu" "r4300"))) - 29 29) -(define_function_unit "imuldiv" 1 0 - (and (and (eq_attr "type" "fdiv") (eq_attr "type" "fsqrt,frsqrt")) - (and (eq_attr "mode" "DF") (eq_attr "cpu" "r4300"))) - 58 58) -;; The following functional units do not use the cpu type, and use -;; much less memory in genattrtab.c. - -;; (define_function_unit "memory" 1 0 (eq_attr "type" "load") 3 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) +;; Pipeline descriptions. ;; -;; (define_function_unit "imuldiv" 1 1 (eq_attr "type" "imul") 17 0) -;; (define_function_unit "imuldiv" 1 1 (eq_attr "type" "idiv") 38 0) +;; generic.md provides a fallback for processors without a specific +;; pipeline description. It is derived from the old define_function_unit +;; version and uses the "alu" and "imuldiv" units declared below. ;; -;; (define_function_unit "adder" 1 1 (eq_attr "type" "fadd") 4 0) -;; (define_function_unit "adder" 1 1 (eq_attr "type" "fabs,fneg") 2 0) -;; -;; (define_function_unit "mult" 1 1 (and (eq_attr "type" "fmul") (eq_attr "mode" "SF")) 7 0) -;; (define_function_unit "mult" 1 1 (and (eq_attr "type" "fmul") (eq_attr "mode" "DF")) 8 0) -;; -;; (define_function_unit "divide" 1 1 (and (eq_attr "type" "fdiv") (eq_attr "mode" "SF")) 23 0) -;; (define_function_unit "divide" 1 1 (and (eq_attr "type" "fdiv") (eq_attr "mode" "DF")) 36 0) -;; -;; (define_function_unit "sqrt" 1 1 (and (eq_attr "type" "fsqrt") (eq_attr "mode" "SF")) 54 0) -;; (define_function_unit "sqrt" 1 1 (and (eq_attr "type" "fsqrt") (eq_attr "mode" "DF")) 112 0) - -;; Include scheduling descriptions. - +;; Some of the processor-specific files are also derived from old +;; define_function_unit descriptions and simply override the parts of +;; generic.md that don't apply. The other processor-specific files +;; are self-contained. +(define_automaton "alu,imuldiv") + +(define_cpu_unit "alu" "alu") +(define_cpu_unit "imuldiv" "imuldiv") + +(include "3000.md") +(include "4000.md") +(include "4100.md") +(include "4130.md") +(include "4300.md") +(include "4600.md") +(include "5000.md") (include "5400.md") (include "5500.md") +(include "6000.md") (include "7000.md") (include "9000.md") +(include "sb1.md") (include "sr71k.md") - - +(include "generic.md") + ;; ;; .................... ;; @@ -639,39 +354,49 @@ (define_insn "trap" [(trap_if (const_int 1) (const_int 0))] "" - "* { if (ISA_HAS_COND_TRAP) - return \"teq\\t$0,$0\"; + return "teq\t$0,$0"; /* The IRIX 6 O32 assembler requires the first break operand. */ - else if (TARGET_MIPS16 || ! TARGET_GAS) - return \"break 0\"; + else if (TARGET_MIPS16 || !TARGET_GAS) + return "break 0"; else - return \"break\"; -}") + return "break"; +} + [(set_attr "type" "trap")]) (define_expand "conditional_trap" - [(trap_if (match_operator 0 "cmp_op" + [(trap_if (match_operator 0 "comparison_operator" [(match_dup 2) (match_dup 3)]) - (match_operand 1 "const_int_operand" ""))] + (match_operand 1 "const_int_operand"))] "ISA_HAS_COND_TRAP" - " { - mips_gen_conditional_trap (operands); - DONE; -}") - -;; Match a TRAP_IF with 2nd arg of 0. The div_trap_* insns match a -;; 2nd arg of any CONST_INT, so this insn must appear first. -;; gen_div_trap always generates TRAP_IF with 2nd arg of 6 or 7. + if (operands[1] == const0_rtx) + { + mips_gen_conditional_trap (operands); + DONE; + } + else + FAIL; +}) (define_insn "" - [(trap_if (match_operator 0 "trap_cmp_op" - [(match_operand:SI 1 "reg_or_0_operand" "d") - (match_operand:SI 2 "nonmemory_operand" "dI")]) + [(trap_if (match_operator 0 "trap_comparison_operator" + [(match_operand:SI 1 "reg_or_0_operand" "dJ") + (match_operand:SI 2 "arith_operand" "dI")]) (const_int 0))] "ISA_HAS_COND_TRAP" - "t%C0\\t%z1,%z2") + "t%C0\t%z1,%z2" + [(set_attr "type" "trap")]) + +(define_insn "" + [(trap_if (match_operator 0 "trap_comparison_operator" + [(match_operand:DI 1 "reg_or_0_operand" "dJ") + (match_operand:DI 2 "arith_operand" "dI")]) + (const_int 0))] + "TARGET_64BIT && ISA_HAS_COND_TRAP" + "t%C0\t%z1,%z2" + [(set_attr "type" "trap")]) ;; ;; .................... @@ -686,7 +411,7 @@ (plus:DF (match_operand:DF 1 "register_operand" "f") (match_operand:DF 2 "register_operand" "f")))] "TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT" - "add.d\\t%0,%1,%2" + "add.d\t%0,%1,%2" [(set_attr "type" "fadd") (set_attr "mode" "DF")]) @@ -695,38 +420,15 @@ (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" + "add.s\t%0,%1,%2" [(set_attr "type" "fadd") (set_attr "mode" "SF")]) (define_expand "addsi3" - [(set (match_operand:SI 0 "register_operand" "") - (plus:SI (match_operand:SI 1 "reg_or_0_operand" "") - (match_operand:SI 2 "arith_operand" "")))] - "" - " -{ - /* If a large stack adjustment was forced into a register, we may be - asked to generate rtx such as: - - (set (reg:SI sp) (plus:SI (reg:SI sp) (reg:SI pseudo))) - - but no such instruction is available in mips16. Handle it by - using a temporary. */ - if (TARGET_MIPS16 - && REGNO (operands[0]) == STACK_POINTER_REGNUM - && ((GET_CODE (operands[1]) == REG - && REGNO (operands[1]) != STACK_POINTER_REGNUM) - || GET_CODE (operands[2]) != CONST_INT)) - { - rtx tmp = gen_reg_rtx (SImode); - - emit_move_insn (tmp, operands[1]); - emit_insn (gen_addsi3 (tmp, tmp, operands[2])); - emit_move_insn (operands[0], tmp); - DONE; - } -}") + [(set (match_operand:SI 0 "register_operand") + (plus:SI (match_operand:SI 1 "reg_or_0_operand") + (match_operand:SI 2 "arith_operand")))] + "") (define_insn "addsi3_internal" [(set (match_operand:SI 0 "register_operand" "=d,d") @@ -734,8 +436,8 @@ (match_operand:SI 2 "arith_operand" "d,Q")))] "!TARGET_MIPS16" "@ - addu\\t%0,%z1,%2 - addiu\\t%0,%z1,%2" + addu\t%0,%z1,%2 + addiu\t%0,%z1,%2" [(set_attr "type" "arith") (set_attr "mode" "SI")]) @@ -746,24 +448,24 @@ (define_insn "" [(set (reg:SI 29) (plus:SI (reg:SI 29) - (match_operand:SI 0 "small_int" "I")))] + (match_operand:SI 0 "const_arith_operand" "")))] "TARGET_MIPS16" - "addu\\t%$,%$,%0" + "addu\t%$,%$,%0" [(set_attr "type" "arith") (set_attr "mode" "SI") - (set (attr "length") (if_then_else (match_operand:VOID 0 "m16_simm8_8" "") + (set (attr "length") (if_then_else (match_operand:VOID 0 "m16_simm8_8") (const_int 4) (const_int 8)))]) (define_insn "" [(set (match_operand:SI 0 "register_operand" "=d") (plus:SI (reg:SI 29) - (match_operand:SI 1 "small_int" "I")))] + (match_operand:SI 1 "const_arith_operand" "")))] "TARGET_MIPS16" - "addu\\t%0,%$,%1" + "addu\t%0,%$,%1" [(set_attr "type" "arith") (set_attr "mode" "SI") - (set (attr "length") (if_then_else (match_operand:VOID 1 "m16_uimm8_4" "") + (set (attr "length") (if_then_else (match_operand:VOID 1 "m16_uimm8_4") (const_int 4) (const_int 8)))]) @@ -771,32 +473,20 @@ [(set (match_operand:SI 0 "register_operand" "=d,d,d") (plus:SI (match_operand:SI 1 "register_operand" "0,d,d") (match_operand:SI 2 "arith_operand" "Q,O,d")))] - "TARGET_MIPS16 - && (GET_CODE (operands[1]) != REG - || REGNO (operands[1]) >= FIRST_PSEUDO_REGISTER - || M16_REG_P (REGNO (operands[1])) - || REGNO (operands[1]) == ARG_POINTER_REGNUM - || REGNO (operands[1]) == FRAME_POINTER_REGNUM - || REGNO (operands[1]) == STACK_POINTER_REGNUM) - && (GET_CODE (operands[2]) != REG - || REGNO (operands[2]) >= FIRST_PSEUDO_REGISTER - || M16_REG_P (REGNO (operands[2])) - || REGNO (operands[2]) == ARG_POINTER_REGNUM - || REGNO (operands[2]) == FRAME_POINTER_REGNUM - || REGNO (operands[2]) == STACK_POINTER_REGNUM)" - "* + "TARGET_MIPS16" { if (REGNO (operands[0]) == REGNO (operands[1])) - return \"addu\\t%0,%2\"; - return \"addu\\t%0,%1,%2\"; -}" + return "addu\t%0,%2"; + else + return "addu\t%0,%1,%2"; +} [(set_attr "type" "arith") (set_attr "mode" "SI") (set_attr_alternative "length" - [(if_then_else (match_operand:VOID 2 "m16_simm8_1" "") + [(if_then_else (match_operand:VOID 2 "m16_simm8_1") (const_int 4) (const_int 8)) - (if_then_else (match_operand:VOID 2 "m16_simm4_1" "") + (if_then_else (match_operand:VOID 2 "m16_simm4_1") (const_int 4) (const_int 8)) (const_int 4)])]) @@ -809,9 +499,9 @@ ;; simply adding a constant to a register. (define_split - [(set (match_operand:SI 0 "register_operand" "") + [(set (match_operand:SI 0 "register_operand") (plus:SI (match_dup 0) - (match_operand:SI 1 "const_int_operand" "")))] + (match_operand:SI 1 "const_int_operand")))] "TARGET_MIPS16 && reload_completed && !TARGET_DEBUG_D_MODE && GET_CODE (operands[0]) == REG && M16_REG_P (REGNO (operands[0])) @@ -822,7 +512,6 @@ && INTVAL (operands[1]) >= - 0x80 - 0x80))" [(set (match_dup 0) (plus:SI (match_dup 0) (match_dup 1))) (set (match_dup 0) (plus:SI (match_dup 0) (match_dup 2)))] - " { HOST_WIDE_INT val = INTVAL (operands[1]); @@ -836,12 +525,12 @@ operands[1] = GEN_INT (- 0x80); operands[2] = GEN_INT (val + 0x80); } -}") +}) (define_split - [(set (match_operand:SI 0 "register_operand" "") - (plus:SI (match_operand:SI 1 "register_operand" "") - (match_operand:SI 2 "const_int_operand" "")))] + [(set (match_operand:SI 0 "register_operand") + (plus:SI (match_operand:SI 1 "register_operand") + (match_operand:SI 2 "const_int_operand")))] "TARGET_MIPS16 && reload_completed && !TARGET_DEBUG_D_MODE && GET_CODE (operands[0]) == REG && M16_REG_P (REGNO (operands[0])) @@ -855,7 +544,6 @@ && INTVAL (operands[2]) >= - 0x8 - 0x80))" [(set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2))) (set (match_dup 0) (plus:SI (match_dup 0) (match_dup 3)))] - " { HOST_WIDE_INT val = INTVAL (operands[2]); @@ -869,195 +557,23 @@ operands[2] = GEN_INT (- 0x8); operands[3] = GEN_INT (val + 0x8); } -}") +}) (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_64BIT || (!TARGET_DEBUG_G_MODE && !TARGET_MIPS16)" - " -{ - /* If a large stack adjustment was forced into a register, we may be - asked to generate rtx such as: - - (set (reg:DI sp) (plus:DI (reg:DI sp) (reg:DI pseudo))) - - but no such instruction is available in mips16. Handle it by - using a temporary. */ - if (TARGET_MIPS16 - && REGNO (operands[0]) == STACK_POINTER_REGNUM - && ((GET_CODE (operands[1]) == REG - && REGNO (operands[1]) != STACK_POINTER_REGNUM) - || GET_CODE (operands[2]) != CONST_INT)) - { - rtx tmp = gen_reg_rtx (DImode); - - emit_move_insn (tmp, operands[1]); - emit_insn (gen_addsi3 (tmp, tmp, operands[2])); - emit_move_insn (operands[0], tmp); - DONE; - } - - if (TARGET_64BIT) - { - emit_insn (gen_adddi3_internal_3 (operands[0], operands[1], - operands[2])); - DONE; - } - - 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_64BIT && !TARGET_DEBUG_G_MODE && !TARGET_MIPS16" - "* -{ - 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") - (set_attr "mode" "DI") - (set_attr "length" "16")]) - -(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_64BIT - && !TARGET_DEBUG_D_MODE && !TARGET_DEBUG_G_MODE && !TARGET_MIPS16 - && 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) 4) - (plus:SI (subreg:SI (match_dup 1) 4) - (subreg:SI (match_dup 2) 4))) + [(set (match_operand:DI 0 "register_operand") + (plus:DI (match_operand:DI 1 "register_operand") + (match_operand:DI 2 "arith_operand")))] + "TARGET_64BIT") - (set (subreg:SI (match_dup 0) 4) - (plus:SI (subreg:SI (match_dup 0) 4) - (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_64BIT - && !TARGET_DEBUG_D_MODE && !TARGET_DEBUG_G_MODE && !TARGET_MIPS16 - && 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) 4) - (plus:SI (subreg:SI (match_dup 1) 4) - (subreg:SI (match_dup 2) 4))) - - (set (match_dup 3) - (ltu:SI (subreg:SI (match_dup 0) 4) - (subreg:SI (match_dup 2) 4))) - - (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_64BIT && !TARGET_DEBUG_G_MODE && !TARGET_MIPS16" - "@ - 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") - (set_attr "mode" "DI") - (set_attr "length" "12,8,16")]) - -(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" ""))] - "reload_completed && !WORDS_BIG_ENDIAN && !TARGET_64BIT - && !TARGET_DEBUG_D_MODE && !TARGET_DEBUG_G_MODE && !TARGET_MIPS16 - && 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) 4) - (plus:SI (subreg:SI (match_dup 1) 4) - (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" ""))] - "reload_completed && WORDS_BIG_ENDIAN && !TARGET_64BIT - && !TARGET_DEBUG_D_MODE && !TARGET_DEBUG_G_MODE && !TARGET_MIPS16 - && 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) 4) - (plus:SI (subreg:SI (match_dup 1) 4) - (match_dup 2))) - - (set (match_dup 3) - (ltu:SI (subreg:SI (match_dup 0) 4) - (match_dup 2))) - - (set (subreg:SI (match_dup 0) 0) - (plus:SI (subreg:SI (match_dup 1) 0) - (match_dup 3)))] - "") - -(define_insn "adddi3_internal_3" +(define_insn "adddi3_internal" [(set (match_operand:DI 0 "register_operand" "=d,d") (plus:DI (match_operand:DI 1 "reg_or_0_operand" "dJ,dJ") (match_operand:DI 2 "arith_operand" "d,Q")))] "TARGET_64BIT && !TARGET_MIPS16" "@ - daddu\\t%0,%z1,%2 - daddiu\\t%0,%z1,%2" - [(set_attr "type" "darith") + daddu\t%0,%z1,%2 + daddiu\t%0,%z1,%2" + [(set_attr "type" "arith") (set_attr "mode" "DI")]) ;; For the mips16, we need to recognize stack pointer additions @@ -1067,24 +583,24 @@ (define_insn "" [(set (reg:DI 29) (plus:DI (reg:DI 29) - (match_operand:DI 0 "small_int" "I")))] + (match_operand:DI 0 "const_arith_operand" "")))] "TARGET_MIPS16 && TARGET_64BIT" - "daddu\\t%$,%$,%0" + "daddu\t%$,%$,%0" [(set_attr "type" "arith") (set_attr "mode" "DI") - (set (attr "length") (if_then_else (match_operand:VOID 0 "m16_simm8_8" "") + (set (attr "length") (if_then_else (match_operand:VOID 0 "m16_simm8_8") (const_int 4) (const_int 8)))]) (define_insn "" [(set (match_operand:DI 0 "register_operand" "=d") (plus:DI (reg:DI 29) - (match_operand:DI 1 "small_int" "I")))] + (match_operand:DI 1 "const_arith_operand" "")))] "TARGET_MIPS16 && TARGET_64BIT" - "daddu\\t%0,%$,%1" + "daddu\t%0,%$,%1" [(set_attr "type" "arith") (set_attr "mode" "DI") - (set (attr "length") (if_then_else (match_operand:VOID 0 "m16_uimm5_4" "") + (set (attr "length") (if_then_else (match_operand:VOID 0 "m16_uimm5_4") (const_int 4) (const_int 8)))]) @@ -1092,32 +608,20 @@ [(set (match_operand:DI 0 "register_operand" "=d,d,d") (plus:DI (match_operand:DI 1 "register_operand" "0,d,d") (match_operand:DI 2 "arith_operand" "Q,O,d")))] - "TARGET_MIPS16 && TARGET_64BIT - && (GET_CODE (operands[1]) != REG - || REGNO (operands[1]) >= FIRST_PSEUDO_REGISTER - || M16_REG_P (REGNO (operands[1])) - || REGNO (operands[1]) == ARG_POINTER_REGNUM - || REGNO (operands[1]) == FRAME_POINTER_REGNUM - || REGNO (operands[1]) == STACK_POINTER_REGNUM) - && (GET_CODE (operands[2]) != REG - || REGNO (operands[2]) >= FIRST_PSEUDO_REGISTER - || M16_REG_P (REGNO (operands[2])) - || REGNO (operands[2]) == ARG_POINTER_REGNUM - || REGNO (operands[2]) == FRAME_POINTER_REGNUM - || REGNO (operands[2]) == STACK_POINTER_REGNUM)" - "* + "TARGET_MIPS16 && TARGET_64BIT" { if (REGNO (operands[0]) == REGNO (operands[1])) - return \"daddu\\t%0,%2\"; - return \"daddu\\t%0,%1,%2\"; -}" + return "daddu\t%0,%2"; + else + return "daddu\t%0,%1,%2"; +} [(set_attr "type" "arith") (set_attr "mode" "DI") (set_attr_alternative "length" - [(if_then_else (match_operand:VOID 2 "m16_simm5_1" "") + [(if_then_else (match_operand:VOID 2 "m16_simm5_1") (const_int 4) (const_int 8)) - (if_then_else (match_operand:VOID 2 "m16_simm4_1" "") + (if_then_else (match_operand:VOID 2 "m16_simm4_1") (const_int 4) (const_int 8)) (const_int 4)])]) @@ -1130,9 +634,9 @@ ;; simply adding a constant to a register. (define_split - [(set (match_operand:DI 0 "register_operand" "") + [(set (match_operand:DI 0 "register_operand") (plus:DI (match_dup 0) - (match_operand:DI 1 "const_int_operand" "")))] + (match_operand:DI 1 "const_int_operand")))] "TARGET_MIPS16 && TARGET_64BIT && reload_completed && !TARGET_DEBUG_D_MODE && GET_CODE (operands[0]) == REG && M16_REG_P (REGNO (operands[0])) @@ -1143,7 +647,6 @@ && INTVAL (operands[1]) >= - 0x10 - 0x10))" [(set (match_dup 0) (plus:DI (match_dup 0) (match_dup 1))) (set (match_dup 0) (plus:DI (match_dup 0) (match_dup 2)))] - " { HOST_WIDE_INT val = INTVAL (operands[1]); @@ -1157,12 +660,12 @@ operands[1] = GEN_INT (- 0x10); operands[2] = GEN_INT (val + 0x10); } -}") +}) (define_split - [(set (match_operand:DI 0 "register_operand" "") - (plus:DI (match_operand:DI 1 "register_operand" "") - (match_operand:DI 2 "const_int_operand" "")))] + [(set (match_operand:DI 0 "register_operand") + (plus:DI (match_operand:DI 1 "register_operand") + (match_operand:DI 2 "const_int_operand")))] "TARGET_MIPS16 && TARGET_64BIT && reload_completed && !TARGET_DEBUG_D_MODE && GET_CODE (operands[0]) == REG && M16_REG_P (REGNO (operands[0])) @@ -1176,7 +679,6 @@ && INTVAL (operands[2]) >= - 0x8 - 0x10))" [(set (match_dup 0) (plus:DI (match_dup 1) (match_dup 2))) (set (match_dup 0) (plus:DI (match_dup 0) (match_dup 3)))] - " { HOST_WIDE_INT val = INTVAL (operands[2]); @@ -1190,7 +692,7 @@ operands[2] = GEN_INT (- 0x8); operands[3] = GEN_INT (val + 0x8); } -}") +}) (define_insn "addsi3_internal_2" [(set (match_operand:DI 0 "register_operand" "=d,d") @@ -1198,8 +700,8 @@ (match_operand:SI 2 "arith_operand" "d,Q"))))] "TARGET_64BIT && !TARGET_MIPS16" "@ - addu\\t%0,%z1,%2 - addiu\\t%0,%z1,%2" + addu\t%0,%z1,%2 + addiu\t%0,%z1,%2" [(set_attr "type" "arith") (set_attr "mode" "SI")]) @@ -1208,23 +710,22 @@ (sign_extend:DI (plus:SI (match_operand:SI 1 "register_operand" "0,d,d") (match_operand:SI 2 "arith_operand" "Q,O,d"))))] "TARGET_MIPS16 && TARGET_64BIT" - "* { if (REGNO (operands[0]) == REGNO (operands[1])) - return \"addu\\t%0,%2\"; - return \"addu\\t%0,%1,%2\"; -}" + return "addu\t%0,%2"; + else + return "addu\t%0,%1,%2"; +} [(set_attr "type" "arith") (set_attr "mode" "SI") (set_attr_alternative "length" - [(if_then_else (match_operand:VOID 2 "m16_simm8_1" "") + [(if_then_else (match_operand:VOID 2 "m16_simm8_1") (const_int 4) (const_int 8)) - (if_then_else (match_operand:VOID 2 "m16_simm4_1" "") + (if_then_else (match_operand:VOID 2 "m16_simm4_1") (const_int 4) (const_int 8)) (const_int 4)])]) - ;; ;; .................... @@ -1239,7 +740,7 @@ (minus:DF (match_operand:DF 1 "register_operand" "f") (match_operand:DF 2 "register_operand" "f")))] "TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT" - "sub.d\\t%0,%1,%2" + "sub.d\t%0,%1,%2" [(set_attr "type" "fadd") (set_attr "mode" "DF")]) @@ -1248,14 +749,14 @@ (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" + "sub.s\t%0,%1,%2" [(set_attr "type" "fadd") (set_attr "mode" "SF")]) (define_expand "subsi3" - [(set (match_operand:SI 0 "register_operand" "") - (minus:SI (match_operand:SI 1 "register_operand" "") - (match_operand:SI 2 "register_operand" "")))] + [(set (match_operand:SI 0 "register_operand") + (minus:SI (match_operand:SI 1 "register_operand") + (match_operand:SI 2 "register_operand")))] "" "") @@ -1264,102 +765,17 @@ (minus:SI (match_operand:SI 1 "register_operand" "d") (match_operand:SI 2 "register_operand" "d")))] "" - "subu\\t%0,%z1,%2" + "subu\t%0,%z1,%2" [(set_attr "type" "arith") (set_attr "mode" "SI")]) -(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_64BIT || (!TARGET_DEBUG_G_MODE && !TARGET_MIPS16)" - " -{ - if (TARGET_64BIT) - { - emit_insn (gen_subdi3_internal_3 (operands[0], operands[1], - operands[2])); - DONE; - } - - 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_64BIT && !TARGET_DEBUG_G_MODE && !TARGET_MIPS16" - "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" "16")]) - -(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_64BIT - && !TARGET_DEBUG_D_MODE && !TARGET_DEBUG_G_MODE && !TARGET_MIPS16 - && 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) 4) - (minus:SI (subreg:SI (match_dup 1) 4) - (subreg:SI (match_dup 2) 4))) - - (set (subreg:SI (match_dup 0) 4) - (minus:SI (subreg:SI (match_dup 0) 4) - (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_64BIT - && !TARGET_DEBUG_D_MODE && !TARGET_DEBUG_G_MODE && !TARGET_MIPS16 - && 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) 4) - (subreg:SI (match_dup 2) 4))) - - (set (subreg:SI (match_dup 0) 4) - (minus:SI (subreg:SI (match_dup 1) 4) - (subreg:SI (match_dup 2) 4))) - - (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_3" +(define_insn "subdi3" [(set (match_operand:DI 0 "register_operand" "=d") (minus:DI (match_operand:DI 1 "register_operand" "d") (match_operand:DI 2 "register_operand" "d")))] "TARGET_64BIT" - "dsubu\\t%0,%1,%2" - [(set_attr "type" "darith") + "dsubu\t%0,%1,%2" + [(set_attr "type" "arith") (set_attr "mode" "DI")]) (define_insn "subsi3_internal_2" @@ -1380,108 +796,125 @@ ;; .................... ;; -;; Early Vr4300 silicon has a CPU bug where multiplies with certain -;; operands may corrupt immediately following multiplies. This is a -;; simple fix to insert NOPs. - (define_expand "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")))] + [(set (match_operand:DF 0 "register_operand") + (mult:DF (match_operand:DF 1 "register_operand") + (match_operand:DF 2 "register_operand")))] "TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT" - " -{ - if (!TARGET_MIPS4300) - emit_insn (gen_muldf3_internal (operands[0], operands[1], operands[2])); - else - emit_insn (gen_muldf3_r4300 (operands[0], operands[1], operands[2])); - DONE; -}") + "") (define_insn "muldf3_internal" [(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 && TARGET_DOUBLE_FLOAT && !TARGET_MIPS4300" - "mul.d\\t%0,%1,%2" + "TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT && !TARGET_4300_MUL_FIX" + "mul.d\t%0,%1,%2" [(set_attr "type" "fmul") (set_attr "mode" "DF")]) +;; Early VR4300 silicon has a CPU bug where multiplies with certain +;; operands may corrupt immediately following multiplies. This is a +;; simple fix to insert NOPs. + (define_insn "muldf3_r4300" [(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 && TARGET_DOUBLE_FLOAT && TARGET_MIPS4300" - "* -{ - output_asm_insn (\"mul.d\\t%0,%1,%2\", operands); - if (TARGET_4300_MUL_FIX) - output_asm_insn (\"nop\", operands); - return \"\"; -}" + "TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT && TARGET_4300_MUL_FIX" + "mul.d\t%0,%1,%2\;nop" [(set_attr "type" "fmul") (set_attr "mode" "DF") - (set_attr "length" "8")]) ;; mul.d + nop + (set_attr "length" "8")]) (define_expand "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")))] + [(set (match_operand:SF 0 "register_operand") + (mult:SF (match_operand:SF 1 "register_operand") + (match_operand:SF 2 "register_operand")))] "TARGET_HARD_FLOAT" - " -{ - if (!TARGET_MIPS4300) - emit_insn( gen_mulsf3_internal (operands[0], operands[1], operands[2])); - else - emit_insn( gen_mulsf3_r4300 (operands[0], operands[1], operands[2])); - DONE; -}") + "") (define_insn "mulsf3_internal" [(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 && !TARGET_MIPS4300" - "mul.s\\t%0,%1,%2" + "TARGET_HARD_FLOAT && !TARGET_4300_MUL_FIX" + "mul.s\t%0,%1,%2" [(set_attr "type" "fmul") (set_attr "mode" "SF")]) +;; See muldf3_r4300. + (define_insn "mulsf3_r4300" [(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 && TARGET_MIPS4300" - "* -{ - output_asm_insn (\"mul.s\\t%0,%1,%2\", operands); - if (TARGET_4300_MUL_FIX) - output_asm_insn (\"nop\", operands); - return \"\"; -}" + "TARGET_HARD_FLOAT && TARGET_4300_MUL_FIX" + "mul.s\t%0,%1,%2\;nop" [(set_attr "type" "fmul") (set_attr "mode" "SF") - (set_attr "length" "8")]) ;; mul.s + nop + (set_attr "length" "8")]) -;; ??? The R4000 (only) has a cpu bug. If a double-word shift executes while -;; a multiply is in progress, it may give an incorrect result. Avoid -;; this by keeping the mflo with the mult on the R4000. +;; The original R4000 has a cpu bug. If a double-word or a variable +;; shift executes while an integer multiplication is in progress, the +;; shift may give an incorrect result. Avoid this by keeping the mflo +;; with the mult on the R4000. +;; +;; From "MIPS R4000PC/SC Errata, Processor Revision 2.2 and 3.0" +;; (also valid for MIPS R4000MC processors): +;; +;; "16. R4000PC, R4000SC: Please refer to errata 28 for an update to +;; this errata description. +;; The following code sequence causes the R4000 to incorrectly +;; execute the Double Shift Right Arithmetic 32 (dsra32) +;; instruction. If the dsra32 instruction is executed during an +;; integer multiply, the dsra32 will only shift by the amount in +;; specified in the instruction rather than the amount plus 32 +;; bits. +;; instruction 1: mult rs,rt integer multiply +;; instruction 2-12: dsra32 rd,rt,rs doubleword shift +;; right arithmetic + 32 +;; Workaround: A dsra32 instruction placed after an integer +;; multiply should not be one of the 11 instructions after the +;; multiply instruction." +;; +;; and: +;; +;; "28. R4000PC, R4000SC: The text from errata 16 should be replaced by +;; the following description. +;; All extended shifts (shift by n+32) and variable shifts (32 and +;; 64-bit versions) may produce incorrect results under the +;; following conditions: +;; 1) An integer multiply is currently executing +;; 2) These types of shift instructions are executed immediately +;; following an integer divide instruction. +;; Workaround: +;; 1) Make sure no integer multiply is running wihen these +;; instruction are executed. If this cannot be predicted at +;; compile time, then insert a "mfhi" to R0 instruction +;; immediately after the integer multiply instruction. This +;; will cause the integer multiply to complete before the shift +;; is executed. +;; 2) Separate integer divide and these two classes of shift +;; instructions by another instruction or a noop." +;; +;; These processors have PRId values of 0x00004220 and 0x00004300, +;; respectively. (define_expand "mulsi3" - [(set (match_operand:SI 0 "register_operand" "") - (mult:SI (match_operand:SI 1 "register_operand" "") - (match_operand:SI 2 "register_operand" "")))] + [(set (match_operand:SI 0 "register_operand") + (mult:SI (match_operand:SI 1 "register_operand") + (match_operand:SI 2 "register_operand")))] "" - " { if (GENERATE_MULT3_SI || TARGET_MAD) emit_insn (gen_mulsi3_mult3 (operands[0], operands[1], operands[2])); - else if (!TARGET_MIPS4000 || TARGET_MIPS16) + else if (!TARGET_FIX_R4000) emit_insn (gen_mulsi3_internal (operands[0], operands[1], operands[2])); else emit_insn (gen_mulsi3_r4000 (operands[0], operands[1], operands[2])); DONE; -}") +}) (define_insn "mulsi3_mult3" [(set (match_operand:SI 0 "register_operand" "=d,l") @@ -1491,10 +924,9 @@ (clobber (match_scratch:SI 4 "=l,X"))] "GENERATE_MULT3_SI || TARGET_MAD" - "* { if (which_alternative == 1) - return \"mult\\t%1,%2\"; + return "mult\t%1,%2"; if (TARGET_MAD || TARGET_MIPS5400 || TARGET_MIPS5500 @@ -1503,9 +935,9 @@ || ISA_MIPS32 || ISA_MIPS32R2 || ISA_MIPS64) - return \"mul\\t%0,%1,%2\"; - return \"mult\\t%0,%1,%2\"; -}" + return "mul\t%0,%1,%2"; + return "mult\t%0,%1,%2"; +} [(set_attr "type" "imul") (set_attr "mode" "SI")]) @@ -1520,17 +952,14 @@ ;; Operand 4: GPR (destination) (define_peephole2 [(parallel - [(set (match_operand:SI 0 "register_operand" "") - (mult:SI (match_operand:SI 1 "register_operand" "") - (match_operand:SI 2 "register_operand" ""))) - (clobber (match_operand:SI 3 "register_operand" "")) + [(set (match_operand:SI 0 "register_operand") + (mult:SI (match_operand:SI 1 "register_operand") + (match_operand:SI 2 "register_operand"))) + (clobber (match_operand:SI 3 "register_operand")) (clobber (scratch:SI))]) - (set (match_operand:SI 4 "register_operand" "") - (match_dup 0))] - "GENERATE_MULT3_SI - && true_regnum (operands[0]) == LO_REGNUM - && GP_REG_P (true_regnum (operands[4])) - && peep2_reg_dead_p (2, operands[0])" + (set (match_operand:SI 4 "register_operand") + (unspec [(match_dup 0) (match_dup 3)] UNSPEC_MFHILO))] + "GENERATE_MULT3_SI && peep2_reg_dead_p (2, operands[0])" [(parallel [(set (match_dup 4) (mult:SI (match_dup 1) @@ -1543,8 +972,8 @@ (mult:SI (match_operand:SI 1 "register_operand" "d") (match_operand:SI 2 "register_operand" "d"))) (clobber (match_scratch:SI 3 "=h"))] - "!TARGET_MIPS4000 || TARGET_MIPS16" - "mult\\t%1,%2" + "!TARGET_FIX_R4000" + "mult\t%1,%2" [(set_attr "type" "imul") (set_attr "mode" "SI")]) @@ -1554,12 +983,43 @@ (match_operand:SI 2 "register_operand" "d"))) (clobber (match_scratch:SI 3 "=h")) (clobber (match_scratch:SI 4 "=l"))] - "TARGET_MIPS4000 && !TARGET_MIPS16" + "TARGET_FIX_R4000" "mult\t%1,%2\;mflo\t%0" [(set_attr "type" "imul") (set_attr "mode" "SI") (set_attr "length" "8")]) +;; On the VR4120 and VR4130, it is better to use "mtlo $0; macc" instead +;; of "mult; mflo". They have the same latency, but the first form gives +;; us an extra cycle to compute the operands. + +;; Operand 0: LO +;; Operand 1: GPR (1st multiplication operand) +;; Operand 2: GPR (2nd multiplication operand) +;; Operand 3: HI +;; Operand 4: GPR (destination) +(define_peephole2 + [(parallel + [(set (match_operand:SI 0 "register_operand") + (mult:SI (match_operand:SI 1 "register_operand") + (match_operand:SI 2 "register_operand"))) + (clobber (match_operand:SI 3 "register_operand"))]) + (set (match_operand:SI 4 "register_operand") + (unspec:SI [(match_dup 0) (match_dup 3)] UNSPEC_MFHILO))] + "ISA_HAS_MACC && !GENERATE_MULT3_SI" + [(set (match_dup 0) + (const_int 0)) + (parallel + [(set (match_dup 0) + (plus:SI (mult:SI (match_dup 1) + (match_dup 2)) + (match_dup 0))) + (set (match_dup 4) + (plus:SI (mult:SI (match_dup 1) + (match_dup 2)) + (match_dup 0))) + (clobber (match_dup 3))])]) + ;; Multiply-accumulate patterns ;; For processors that can copy the output to a general register: @@ -1583,28 +1043,27 @@ "(TARGET_MIPS3900 || ISA_HAS_MADD_MSUB) && !TARGET_MIPS16" - "* { - static const char *const madd[] = { \"madd\\t%1,%2\", \"madd\\t%0,%1,%2\" }; + static const char *const madd[] = { "madd\t%1,%2", "madd\t%0,%1,%2" }; if (which_alternative == 2) - return \"#\"; + return "#"; if (ISA_HAS_MADD_MSUB && which_alternative != 0) - return \"#\"; + return "#"; return madd[which_alternative]; -}" +} [(set_attr "type" "imadd,imadd,multi") (set_attr "mode" "SI") (set_attr "length" "4,4,8")]) ;; Split the above insn if we failed to get LO allocated. (define_split - [(set (match_operand:SI 0 "register_operand" "") - (plus:SI (mult:SI (match_operand:SI 1 "register_operand" "") - (match_operand:SI 2 "register_operand" "")) - (match_operand:SI 3 "register_operand" ""))) - (clobber (match_scratch:SI 4 "")) - (clobber (match_scratch:SI 5 "")) - (clobber (match_scratch:SI 6 ""))] + [(set (match_operand:SI 0 "register_operand") + (plus:SI (mult:SI (match_operand:SI 1 "register_operand") + (match_operand:SI 2 "register_operand")) + (match_operand:SI 3 "register_operand"))) + (clobber (match_scratch:SI 4)) + (clobber (match_scratch:SI 5)) + (clobber (match_scratch:SI 6))] "reload_completed && !TARGET_DEBUG_D_MODE && GP_REG_P (true_regnum (operands[0])) && GP_REG_P (true_regnum (operands[3]))" @@ -1617,13 +1076,13 @@ ;; Splitter to copy result of MADD to a general register (define_split - [(set (match_operand:SI 0 "register_operand" "") - (plus:SI (mult:SI (match_operand:SI 1 "register_operand" "") - (match_operand:SI 2 "register_operand" "")) - (match_operand:SI 3 "register_operand" ""))) - (clobber (match_scratch:SI 4 "")) - (clobber (match_scratch:SI 5 "")) - (clobber (match_scratch:SI 6 ""))] + [(set (match_operand:SI 0 "register_operand") + (plus:SI (mult:SI (match_operand:SI 1 "register_operand") + (match_operand:SI 2 "register_operand")) + (match_operand:SI 3 "register_operand"))) + (clobber (match_scratch:SI 4)) + (clobber (match_scratch:SI 5)) + (clobber (match_scratch:SI 6))] "reload_completed && !TARGET_DEBUG_D_MODE && GP_REG_P (true_regnum (operands[0])) && true_regnum (operands[3]) == LO_REGNUM" @@ -1633,7 +1092,7 @@ (clobber (match_dup 4)) (clobber (match_dup 5)) (clobber (match_dup 6))]) - (set (match_dup 0) (match_dup 3))] + (set (match_dup 0) (unspec:SI [(match_dup 5) (match_dup 4)] UNSPEC_MFHILO))] "") (define_insn "*macc" @@ -1644,19 +1103,66 @@ (clobber (match_scratch:SI 4 "=h,h")) (clobber (match_scratch:SI 5 "=X,3"))] "ISA_HAS_MACC" - "* { if (which_alternative == 1) - return \"macc\\t%0,%1,%2\"; + return "macc\t%0,%1,%2"; else if (TARGET_MIPS5500) - return \"madd\\t%1,%2\"; + return "madd\t%1,%2"; else - return \"macc\\t%.,%1,%2\"; -}" + /* The VR4130 assumes that there is a two-cycle latency between a macc + that "writes" to $0 and an instruction that reads from it. We avoid + this by assigning to $1 instead. */ + return "%[macc\t%@,%1,%2%]"; +} [(set_attr "type" "imadd") (set_attr "mode" "SI")]) -;; Pattern generated by define_peephole2 below +(define_insn "*msac" + [(set (match_operand:SI 0 "register_operand" "=l,d") + (minus:SI (match_operand:SI 1 "register_operand" "0,l") + (mult:SI (match_operand:SI 2 "register_operand" "d,d") + (match_operand:SI 3 "register_operand" "d,d")))) + (clobber (match_scratch:SI 4 "=h,h")) + (clobber (match_scratch:SI 5 "=X,1"))] + "ISA_HAS_MSAC" +{ + if (which_alternative == 1) + return "msac\t%0,%2,%3"; + else if (TARGET_MIPS5500) + return "msub\t%2,%3"; + else + return "msac\t$0,%2,%3"; +} + [(set_attr "type" "imadd") + (set_attr "mode" "SI")]) + +;; An msac-like instruction implemented using negation and a macc. +(define_insn_and_split "*msac_using_macc" + [(set (match_operand:SI 0 "register_operand" "=l,d") + (minus:SI (match_operand:SI 1 "register_operand" "0,l") + (mult:SI (match_operand:SI 2 "register_operand" "d,d") + (match_operand:SI 3 "register_operand" "d,d")))) + (clobber (match_scratch:SI 4 "=h,h")) + (clobber (match_scratch:SI 5 "=X,1")) + (clobber (match_scratch:SI 6 "=d,d"))] + "ISA_HAS_MACC && !ISA_HAS_MSAC" + "#" + "&& reload_completed" + [(set (match_dup 6) + (neg:SI (match_dup 3))) + (parallel + [(set (match_dup 0) + (plus:SI (mult:SI (match_dup 2) + (match_dup 6)) + (match_dup 1))) + (clobber (match_dup 4)) + (clobber (match_dup 5))])] + "" + [(set_attr "type" "imadd") + (set_attr "length" "8")]) + +;; Patterns generated by the define_peephole2 below. + (define_insn "*macc2" [(set (match_operand:SI 0 "register_operand" "=l") (plus:SI (mult:SI (match_operand:SI 1 "register_operand" "d") @@ -1668,39 +1174,46 @@ (match_dup 0))) (clobber (match_scratch:SI 4 "=h"))] "ISA_HAS_MACC && reload_completed" - "macc\\t%3,%1,%2" + "macc\t%3,%1,%2" + [(set_attr "type" "imadd") + (set_attr "mode" "SI")]) + +(define_insn "*msac2" + [(set (match_operand:SI 0 "register_operand" "=l") + (minus:SI (match_dup 0) + (mult:SI (match_operand:SI 1 "register_operand" "d") + (match_operand:SI 2 "register_operand" "d")))) + (set (match_operand:SI 3 "register_operand" "=d") + (minus:SI (match_dup 0) + (mult:SI (match_dup 1) + (match_dup 2)))) + (clobber (match_scratch:SI 4 "=h"))] + "ISA_HAS_MSAC && reload_completed" + "msac\t%3,%1,%2" [(set_attr "type" "imadd") (set_attr "mode" "SI")]) ;; Convert macc $0,, & mflo into macc ,, +;; Similarly msac. ;; ;; Operand 0: LO -;; Operand 1: GPR (1st multiplication operand) -;; Operand 2: GPR (2nd multiplication operand) -;; Operand 3: HI -;; Operand 4: GPR (destination) +;; Operand 1: macc/msac +;; Operand 2: HI +;; Operand 3: GPR (destination) (define_peephole2 [(parallel - [(set (match_operand:SI 0 "register_operand" "") - (plus:SI (mult:SI (match_operand:SI 1 "register_operand" "") - (match_operand:SI 2 "register_operand" "")) - (match_dup 0))) - (clobber (match_operand:SI 3 "register_operand" "")) + [(set (match_operand:SI 0 "register_operand") + (match_operand:SI 1 "macc_msac_operand")) + (clobber (match_operand:SI 2 "register_operand")) (clobber (scratch:SI))]) - (set (match_operand:SI 4 "register_operand" "") - (match_dup 0))] - "ISA_HAS_MACC - && true_regnum (operands[0]) == LO_REGNUM - && GP_REG_P (true_regnum (operands[4]))" + (set (match_operand:SI 3 "register_operand") + (unspec:SI [(match_dup 0) (match_dup 2)] UNSPEC_MFHILO))] + "" [(parallel [(set (match_dup 0) - (plus:SI (mult:SI (match_dup 1) - (match_dup 2)) - (match_dup 0))) - (set (match_dup 4) - (plus:SI (mult:SI (match_dup 1) - (match_dup 2)) - (match_dup 0))) - (clobber (match_dup 3))])] + (match_dup 1)) + (set (match_dup 3) + (match_dup 1)) + (clobber (match_dup 2))])] "") ;; When we have a three-address multiplication instruction, it should @@ -1714,72 +1227,71 @@ ;; Operand 1: LO ;; Operand 2: GPR (addend) ;; Operand 3: GPR (destination) -;; Operand 4: GPR (1st multiplication operand) -;; Operand 5: GPR (2nd multiplication operand) -;; Operand 6: HI +;; Operand 4: macc/msac +;; Operand 5: HI +;; Operand 6: new multiplication +;; Operand 7: new addition/subtraction (define_peephole2 [(match_scratch:SI 0 "d") - (set (match_operand:SI 1 "register_operand" "") - (match_operand:SI 2 "register_operand" "")) + (set (match_operand:SI 1 "register_operand") + (match_operand:SI 2 "register_operand")) (match_dup 0) (parallel - [(set (match_operand:SI 3 "register_operand" "") - (plus:SI (mult:SI (match_operand:SI 4 "register_operand" "") - (match_operand:SI 5 "register_operand" "")) - (match_dup 1))) - (clobber (match_operand:SI 6 "register_operand" "")) + [(set (match_operand:SI 3 "register_operand") + (match_operand:SI 4 "macc_msac_operand")) + (clobber (match_operand:SI 5 "register_operand")) (clobber (match_dup 1))])] - "ISA_HAS_MACC && GENERATE_MULT3_SI + "GENERATE_MULT3_SI && true_regnum (operands[1]) == LO_REGNUM && peep2_reg_dead_p (2, operands[1]) && GP_REG_P (true_regnum (operands[3]))" [(parallel [(set (match_dup 0) - (mult:SI (match_dup 4) - (match_dup 5))) - (clobber (match_dup 6)) + (match_dup 6)) + (clobber (match_dup 5)) (clobber (match_dup 1))]) (set (match_dup 3) - (plus:SI (match_dup 0) - (match_dup 2)))] - "") + (match_dup 7))] +{ + operands[6] = XEXP (operands[4], GET_CODE (operands[4]) == PLUS ? 0 : 1); + operands[7] = gen_rtx_fmt_ee (GET_CODE (operands[4]), SImode, + operands[2], operands[0]); +}) ;; Same as above, except LO is the initial target of the macc. ;; ;; Operand 0: GPR (scratch) ;; Operand 1: LO ;; Operand 2: GPR (addend) -;; Operand 3: GPR (1st multiplication operand) -;; Operand 4: GPR (2nd multiplication operand) -;; Operand 5: HI -;; Operand 6: GPR (destination) +;; Operand 3: macc/msac +;; Operand 4: HI +;; Operand 5: GPR (destination) +;; Operand 6: new multiplication +;; Operand 7: new addition/subtraction (define_peephole2 [(match_scratch:SI 0 "d") - (set (match_operand:SI 1 "register_operand" "") - (match_operand:SI 2 "register_operand" "")) + (set (match_operand:SI 1 "register_operand") + (match_operand:SI 2 "register_operand")) (match_dup 0) (parallel [(set (match_dup 1) - (plus:SI (mult:SI (match_operand:SI 3 "register_operand" "") - (match_operand:SI 4 "register_operand" "")) - (match_dup 1))) - (clobber (match_operand:SI 5 "register_operand" "")) + (match_operand:SI 3 "macc_msac_operand")) + (clobber (match_operand:SI 4 "register_operand")) (clobber (scratch:SI))]) (match_dup 0) - (set (match_operand:SI 6 "register_operand" "") - (match_dup 1))] - "ISA_HAS_MACC && GENERATE_MULT3_SI - && true_regnum (operands[1]) == LO_REGNUM - && peep2_reg_dead_p (3, operands[1]) - && GP_REG_P (true_regnum (operands[6]))" + (set (match_operand:SI 5 "register_operand") + (unspec:SI [(match_dup 1) (match_dup 4)] UNSPEC_MFHILO))] + "GENERATE_MULT3_SI && peep2_reg_dead_p (3, operands[1])" [(parallel [(set (match_dup 0) - (mult:SI (match_dup 3) - (match_dup 4))) - (clobber (match_dup 5)) + (match_dup 6)) + (clobber (match_dup 4)) (clobber (match_dup 1))]) - (set (match_dup 6) - (plus:SI (match_dup 0) - (match_dup 2)))] - "") + (set (match_dup 5) + (match_dup 7))] +{ + operands[6] = XEXP (operands[4], GET_CODE (operands[4]) == PLUS ? 0 : 1); + operands[7] = gen_rtx_fmt_ee (GET_CODE (operands[4]), SImode, + operands[2], operands[0]); +}) (define_insn "*mul_sub_si" [(set (match_operand:SI 0 "register_operand" "=l,*d,*d") @@ -1790,25 +1302,23 @@ (clobber (match_scratch:SI 5 "=X,1,l")) (clobber (match_scratch:SI 6 "=X,X,&d"))] "ISA_HAS_MADD_MSUB" - "* -{ - if (which_alternative != 0) - return \"#\"; - return \"msub\\t%2,%3\"; -}" + "@ + msub\t%2,%3 + # + #" [(set_attr "type" "imadd,multi,multi") (set_attr "mode" "SI") (set_attr "length" "4,8,8")]) ;; Split the above insn if we failed to get LO allocated. (define_split - [(set (match_operand:SI 0 "register_operand" "") - (minus:SI (match_operand:SI 1 "register_operand" "") - (mult:SI (match_operand:SI 2 "register_operand" "") - (match_operand:SI 3 "register_operand" "")))) - (clobber (match_scratch:SI 4 "")) - (clobber (match_scratch:SI 5 "")) - (clobber (match_scratch:SI 6 ""))] + [(set (match_operand:SI 0 "register_operand") + (minus:SI (match_operand:SI 1 "register_operand") + (mult:SI (match_operand:SI 2 "register_operand") + (match_operand:SI 3 "register_operand")))) + (clobber (match_scratch:SI 4)) + (clobber (match_scratch:SI 5)) + (clobber (match_scratch:SI 6))] "reload_completed && !TARGET_DEBUG_D_MODE && GP_REG_P (true_regnum (operands[0])) && GP_REG_P (true_regnum (operands[1]))" @@ -1821,13 +1331,13 @@ ;; Splitter to copy result of MSUB to a general register (define_split - [(set (match_operand:SI 0 "register_operand" "") - (minus:SI (match_operand:SI 1 "register_operand" "") - (mult:SI (match_operand:SI 2 "register_operand" "") - (match_operand:SI 3 "register_operand" "")))) - (clobber (match_scratch:SI 4 "")) - (clobber (match_scratch:SI 5 "")) - (clobber (match_scratch:SI 6 ""))] + [(set (match_operand:SI 0 "register_operand") + (minus:SI (match_operand:SI 1 "register_operand") + (mult:SI (match_operand:SI 2 "register_operand") + (match_operand:SI 3 "register_operand")))) + (clobber (match_scratch:SI 4)) + (clobber (match_scratch:SI 5)) + (clobber (match_scratch:SI 6))] "reload_completed && !TARGET_DEBUG_D_MODE && GP_REG_P (true_regnum (operands[0])) && true_regnum (operands[1]) == LO_REGNUM" @@ -1837,7 +1347,7 @@ (clobber (match_dup 4)) (clobber (match_dup 5)) (clobber (match_dup 6))]) - (set (match_dup 0) (match_dup 1))] + (set (match_dup 0) (unspec:SI [(match_dup 5) (match_dup 4)] UNSPEC_MFHILO))] "") (define_insn "*muls" @@ -1848,106 +1358,106 @@ (clobber (match_scratch:SI 4 "=X,l"))] "ISA_HAS_MULS" "@ - muls\\t$0,%1,%2 - muls\\t%0,%1,%2" + muls\t$0,%1,%2 + muls\t%0,%1,%2" [(set_attr "type" "imul") (set_attr "mode" "SI")]) -(define_insn "*msac" - [(set (match_operand:SI 0 "register_operand" "=l,d") - (minus:SI (match_operand:SI 1 "register_operand" "0,l") - (mult:SI (match_operand:SI 2 "register_operand" "d,d") - (match_operand:SI 3 "register_operand" "d,d")))) - (clobber (match_scratch:SI 4 "=h,h")) - (clobber (match_scratch:SI 5 "=X,1"))] - "ISA_HAS_MSAC" - "* -{ - if (which_alternative == 1) - return \"msac\\t%0,%2,%3\"; - else if (TARGET_MIPS5500) - return \"msub\\t%2,%3\"; - else - return \"msac\\t$0,%2,%3\"; -}" - [(set_attr "type" "imadd") - (set_attr "mode" "SI")]) - (define_expand "muldi3" - [(set (match_operand:DI 0 "register_operand" "") - (mult:DI (match_operand:DI 1 "register_operand" "") - (match_operand:DI 2 "register_operand" "")))] + [(set (match_operand:DI 0 "register_operand") + (mult:DI (match_operand:DI 1 "register_operand") + (match_operand:DI 2 "register_operand")))] "TARGET_64BIT" - - " { - if (GENERATE_MULT3_DI || TARGET_MIPS4000) - emit_insn (gen_muldi3_internal2 (operands[0], operands[1], operands[2])); - else + if (GENERATE_MULT3_DI) + emit_insn (gen_muldi3_mult3 (operands[0], operands[1], operands[2])); + else if (!TARGET_FIX_R4000) emit_insn (gen_muldi3_internal (operands[0], operands[1], operands[2])); + else + emit_insn (gen_muldi3_r4000 (operands[0], operands[1], operands[2])); DONE; -}") +}) + +(define_insn "muldi3_mult3" + [(set (match_operand:DI 0 "register_operand" "=d") + (mult:DI (match_operand:DI 1 "register_operand" "d") + (match_operand:DI 2 "register_operand" "d"))) + (clobber (match_scratch:DI 3 "=h")) + (clobber (match_scratch:DI 4 "=l"))] + "TARGET_64BIT && GENERATE_MULT3_DI" + "dmult\t%0,%1,%2" + [(set_attr "type" "imul") + (set_attr "mode" "DI")]) (define_insn "muldi3_internal" [(set (match_operand:DI 0 "register_operand" "=l") (mult:DI (match_operand:DI 1 "register_operand" "d") (match_operand:DI 2 "register_operand" "d"))) (clobber (match_scratch:DI 3 "=h"))] - "TARGET_64BIT && !TARGET_MIPS4000" - "dmult\\t%1,%2" + "TARGET_64BIT && !TARGET_FIX_R4000" + "dmult\t%1,%2" [(set_attr "type" "imul") (set_attr "mode" "DI")]) -(define_insn "muldi3_internal2" +(define_insn "muldi3_r4000" [(set (match_operand:DI 0 "register_operand" "=d") (mult:DI (match_operand:DI 1 "register_operand" "d") (match_operand:DI 2 "register_operand" "d"))) (clobber (match_scratch:DI 3 "=h")) (clobber (match_scratch:DI 4 "=l"))] - "TARGET_64BIT && (GENERATE_MULT3_DI || TARGET_MIPS4000)" - { - if (GENERATE_MULT3_DI) - return "dmult\t%0,%1,%2"; - else - return "dmult\t%1,%2\n\tmflo\t%0"; - } + "TARGET_64BIT && TARGET_FIX_R4000" + "dmult\t%1,%2\;mflo\t%0" [(set_attr "type" "imul") (set_attr "mode" "DI") - (set (attr "length") - (if_then_else (ne (symbol_ref "GENERATE_MULT3_DI") (const_int 0)) - (const_int 4) - (const_int 8)))]) + (set_attr "length" "8")]) ;; ??? We could define a mulditi3 pattern when TARGET_64BIT. (define_expand "mulsidi3" [(parallel - [(set (match_operand:DI 0 "register_operand" "") + [(set (match_operand:DI 0 "register_operand") (mult:DI - (sign_extend:DI (match_operand:SI 1 "register_operand" "")) - (sign_extend:DI (match_operand:SI 2 "register_operand" "")))) + (sign_extend:DI (match_operand:SI 1 "register_operand")) + (sign_extend:DI (match_operand:SI 2 "register_operand")))) (clobber (scratch:DI)) (clobber (scratch:DI)) (clobber (scratch:DI))])] - "" - { - if (!TARGET_64BIT) - { - emit_insn (gen_mulsidi3_32bit (operands[0], operands[1], operands[2])); - DONE; - } - }) - -(define_insn "mulsidi3_32bit" + "!TARGET_64BIT || !TARGET_FIX_R4000" +{ + if (!TARGET_64BIT) + { + if (!TARGET_FIX_R4000) + emit_insn (gen_mulsidi3_32bit_internal (operands[0], operands[1], + operands[2])); + else + emit_insn (gen_mulsidi3_32bit_r4000 (operands[0], operands[1], + operands[2])); + DONE; + } +}) + +(define_insn "mulsidi3_32bit_internal" [(set (match_operand:DI 0 "register_operand" "=x") (mult:DI (sign_extend:DI (match_operand:SI 1 "register_operand" "d")) (sign_extend:DI (match_operand:SI 2 "register_operand" "d"))))] - "!TARGET_64BIT" - "mult\\t%1,%2" + "!TARGET_64BIT && !TARGET_FIX_R4000" + "mult\t%1,%2" [(set_attr "type" "imul") (set_attr "mode" "SI")]) +(define_insn "mulsidi3_32bit_r4000" + [(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 (match_scratch:DI 3 "=x"))] + "!TARGET_64BIT && TARGET_FIX_R4000" + "mult\t%1,%2\;mflo\t%L0;mfhi\t%M0" + [(set_attr "type" "imul") + (set_attr "mode" "SI") + (set_attr "length" "12")]) + (define_insn_and_split "*mulsidi3_64bit" [(set (match_operand:DI 0 "register_operand" "=d") (mult:DI (match_operator:DI 1 "extend_operator" @@ -1957,7 +1467,8 @@ (clobber (match_scratch:DI 5 "=l")) (clobber (match_scratch:DI 6 "=h")) (clobber (match_scratch:DI 7 "=d"))] - "TARGET_64BIT && GET_CODE (operands[1]) == GET_CODE (operands[2])" + "TARGET_64BIT && !TARGET_FIX_R4000 + && GET_CODE (operands[1]) == GET_CODE (operands[2])" "#" "&& reload_completed" [(parallel @@ -1972,8 +1483,8 @@ (const_int 32)))]) ;; OP7 <- LO, OP0 <- HI - (set (match_dup 7) (match_dup 5)) - (set (match_dup 0) (match_dup 6)) + (set (match_dup 7) (unspec:DI [(match_dup 5) (match_dup 6)] UNSPEC_MFHILO)) + (set (match_dup 0) (unspec:DI [(match_dup 6) (match_dup 5)] UNSPEC_MFHILO)) ;; Zero-extend OP7. (set (match_dup 7) @@ -2008,45 +1519,62 @@ (match_operator:DI 4 "extend_operator" [(match_dup 2)]) (match_operator:DI 5 "extend_operator" [(match_dup 3)])) (const_int 32)))] - "TARGET_64BIT && GET_CODE (operands[4]) == GET_CODE (operands[5])" - { - if (GET_CODE (operands[4]) == SIGN_EXTEND) - return "mult\t%2,%3"; - else - return "multu\t%2,%3"; - } + "TARGET_64BIT && !TARGET_FIX_R4000 + && GET_CODE (operands[4]) == GET_CODE (operands[5])" +{ + if (GET_CODE (operands[4]) == SIGN_EXTEND) + return "mult\t%2,%3"; + else + return "multu\t%2,%3"; +} [(set_attr "type" "imul") (set_attr "mode" "SI")]) (define_expand "umulsidi3" [(parallel - [(set (match_operand:DI 0 "register_operand" "") + [(set (match_operand:DI 0 "register_operand") (mult:DI - (zero_extend:DI (match_operand:SI 1 "register_operand" "")) - (zero_extend:DI (match_operand:SI 2 "register_operand" "")))) + (zero_extend:DI (match_operand:SI 1 "register_operand")) + (zero_extend:DI (match_operand:SI 2 "register_operand")))) (clobber (scratch:DI)) (clobber (scratch:DI)) (clobber (scratch:DI))])] - "" - { - if (!TARGET_64BIT) - { - emit_insn (gen_umulsidi3_32bit (operands[0], operands[1], - operands[2])); - DONE; - } - }) + "!TARGET_64BIT || !TARGET_FIX_R4000" +{ + if (!TARGET_64BIT) + { + if (!TARGET_FIX_R4000) + emit_insn (gen_umulsidi3_32bit_internal (operands[0], operands[1], + operands[2])); + else + emit_insn (gen_umulsidi3_32bit_r4000 (operands[0], operands[1], + operands[2])); + DONE; + } +}) -(define_insn "umulsidi3_32bit" +(define_insn "umulsidi3_32bit_internal" [(set (match_operand:DI 0 "register_operand" "=x") (mult:DI (zero_extend:DI (match_operand:SI 1 "register_operand" "d")) (zero_extend:DI (match_operand:SI 2 "register_operand" "d"))))] - "!TARGET_64BIT" - "multu\\t%1,%2" + "!TARGET_64BIT && !TARGET_FIX_R4000" + "multu\t%1,%2" [(set_attr "type" "imul") (set_attr "mode" "SI")]) +(define_insn "umulsidi3_32bit_r4000" + [(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 (match_scratch:DI 3 "=x"))] + "!TARGET_64BIT && TARGET_FIX_R4000" + "multu\t%1,%2\;mflo\t%L0;mfhi\t%M0" + [(set_attr "type" "imul") + (set_attr "mode" "SI") + (set_attr "length" "12")]) + ;; Widening multiply with negation. (define_insn "*muls_di" [(set (match_operand:DI 0 "register_operand" "=x") @@ -2055,7 +1583,7 @@ (sign_extend:DI (match_operand:SI 1 "register_operand" "d")) (sign_extend:DI (match_operand:SI 2 "register_operand" "d")))))] "!TARGET_64BIT && ISA_HAS_MULS" - "muls\\t$0,%1,%2" + "muls\t$0,%1,%2" [(set_attr "type" "imul") (set_attr "length" "4") (set_attr "mode" "SI")]) @@ -2067,7 +1595,7 @@ (zero_extend:DI (match_operand:SI 1 "register_operand" "d")) (zero_extend:DI (match_operand:SI 2 "register_operand" "d")))))] "!TARGET_64BIT && ISA_HAS_MULS" - "mulsu\\t$0,%1,%2" + "mulsu\t$0,%1,%2" [(set_attr "type" "imul") (set_attr "length" "4") (set_attr "mode" "SI")]) @@ -2080,13 +1608,12 @@ (sign_extend:DI (match_operand:SI 1 "register_operand" "d")) (sign_extend:DI (match_operand:SI 2 "register_operand" "d")))))] "!TARGET_64BIT && ISA_HAS_MSAC" - "* { if (TARGET_MIPS5500) - return \"msub\\t%1,%2\"; + return "msub\t%1,%2"; else - return \"msac\\t$0,%1,%2\"; -}" + return "msac\t$0,%1,%2"; +} [(set_attr "type" "imadd") (set_attr "length" "4") (set_attr "mode" "SI")]) @@ -2099,27 +1626,25 @@ (zero_extend:DI (match_operand:SI 1 "register_operand" "d")) (zero_extend:DI (match_operand:SI 2 "register_operand" "d")))))] "!TARGET_64BIT && ISA_HAS_MSAC" - "* { if (TARGET_MIPS5500) - return \"msubu\\t%1,%2\"; + return "msubu\t%1,%2"; else - return \"msacu\\t$0,%1,%2\"; -}" + return "msacu\t$0,%1,%2"; +} [(set_attr "type" "imadd") (set_attr "length" "4") (set_attr "mode" "SI")]) ;; _highpart patterns (define_expand "umulsi3_highpart" - [(set (match_operand:SI 0 "register_operand" "") + [(set (match_operand:SI 0 "register_operand") (truncate:SI (lshiftrt:DI - (mult:DI (zero_extend:DI (match_operand:SI 1 "register_operand" "")) - (zero_extend:DI (match_operand:SI 2 "register_operand" ""))) + (mult:DI (zero_extend:DI (match_operand:SI 1 "register_operand")) + (zero_extend:DI (match_operand:SI 2 "register_operand"))) (const_int 32))))] - "" - " + "ISA_HAS_MULHI || !TARGET_FIX_R4000" { if (ISA_HAS_MULHI) emit_insn (gen_umulsi3_highpart_mulhi_internal (operands[0], operands[1], @@ -2128,7 +1653,7 @@ emit_insn (gen_umulsi3_highpart_internal (operands[0], operands[1], operands[2])); DONE; -}") +}) (define_insn "umulsi3_highpart_internal" [(set (match_operand:SI 0 "register_operand" "=h") @@ -2138,8 +1663,8 @@ (zero_extend:DI (match_operand:SI 2 "register_operand" "d"))) (const_int 32)))) (clobber (match_scratch:SI 3 "=l"))] - "!ISA_HAS_MULHI" - "multu\\t%1,%2" + "!ISA_HAS_MULHI && !TARGET_FIX_R4000" + "multu\t%1,%2" [(set_attr "type" "imul") (set_attr "mode" "SI") (set_attr "length" "4")]) @@ -2155,8 +1680,8 @@ (clobber (match_scratch:SI 4 "=X,h"))] "ISA_HAS_MULHI" "@ - multu\\t%1,%2 - mulhiu\\t%0,%1,%2" + multu\t%1,%2 + mulhiu\t%0,%1,%2" [(set_attr "type" "imul") (set_attr "mode" "SI") (set_attr "length" "4")]) @@ -2173,21 +1698,20 @@ (clobber (match_scratch:SI 4 "=X,h"))] "ISA_HAS_MULHI" "@ - mulshiu\\t%.,%1,%2 - mulshiu\\t%0,%1,%2" + mulshiu\t%.,%1,%2 + mulshiu\t%0,%1,%2" [(set_attr "type" "imul") (set_attr "mode" "SI") (set_attr "length" "4")]) (define_expand "smulsi3_highpart" - [(set (match_operand:SI 0 "register_operand" "") + [(set (match_operand:SI 0 "register_operand") (truncate:SI (lshiftrt:DI - (mult:DI (sign_extend:DI (match_operand:SI 1 "register_operand" "")) - (sign_extend:DI (match_operand:SI 2 "register_operand" ""))) + (mult:DI (sign_extend:DI (match_operand:SI 1 "register_operand")) + (sign_extend:DI (match_operand:SI 2 "register_operand"))) (const_int 32))))] - "" - " + "ISA_HAS_MULHI || !TARGET_FIX_R4000" { if (ISA_HAS_MULHI) emit_insn (gen_smulsi3_highpart_mulhi_internal (operands[0], operands[1], @@ -2196,7 +1720,7 @@ emit_insn (gen_smulsi3_highpart_internal (operands[0], operands[1], operands[2])); DONE; -}") +}) (define_insn "smulsi3_highpart_internal" [(set (match_operand:SI 0 "register_operand" "=h") @@ -2206,8 +1730,8 @@ (sign_extend:DI (match_operand:SI 2 "register_operand" "d"))) (const_int 32)))) (clobber (match_scratch:SI 3 "=l"))] - "!ISA_HAS_MULHI" - "mult\\t%1,%2" + "!ISA_HAS_MULHI && !TARGET_FIX_R4000" + "mult\t%1,%2" [(set_attr "type" "imul") (set_attr "mode" "SI") (set_attr "length" "4")]) @@ -2223,8 +1747,8 @@ (clobber (match_scratch:SI 4 "=X,h"))] "ISA_HAS_MULHI" "@ - mult\\t%1,%2 - mulhi\\t%0,%1,%2" + mult\t%1,%2 + mulhi\t%0,%1,%2" [(set_attr "type" "imul") (set_attr "mode" "SI") (set_attr "length" "4")]) @@ -2241,8 +1765,8 @@ (clobber (match_scratch:SI 4 "=X,h"))] "ISA_HAS_MULHI" "@ - mulshi\\t%.,%1,%2 - mulshi\\t%0,%1,%2" + mulshi\t%.,%1,%2 + mulshi\t%0,%1,%2" [(set_attr "type" "imul") (set_attr "mode" "SI")]) @@ -2255,11 +1779,13 @@ (sign_extend:TI (match_operand:DI 2 "register_operand" "d"))) (const_int 64)))) (clobber (match_scratch:DI 3 "=l"))] - "TARGET_64BIT" - "dmult\\t%1,%2" + "TARGET_64BIT && !TARGET_FIX_R4000" + "dmult\t%1,%2" [(set_attr "type" "imul") (set_attr "mode" "DI")]) +;; Disable this pattern for -mfix-vr4120. This is for VR4120 errata MD(0), +;; which says that dmultu does not always produce the correct result. (define_insn "umuldi3_highpart" [(set (match_operand:DI 0 "register_operand" "=h") (truncate:DI @@ -2269,8 +1795,8 @@ (zero_extend:TI (match_operand:DI 2 "register_operand" "d"))) (const_int 64)))) (clobber (match_scratch:DI 3 "=l"))] - "TARGET_64BIT" - "dmultu\\t%1,%2" + "TARGET_64BIT && !TARGET_FIX_R4000 && !TARGET_FIX_VR4120" + "dmultu\t%1,%2" [(set_attr "type" "imul") (set_attr "mode" "DI")]) @@ -2285,7 +1811,7 @@ (match_dup 0))) (clobber (match_scratch:SI 3 "=h"))] "TARGET_MAD" - "mad\\t%1,%2" + "mad\t%1,%2" [(set_attr "type" "imadd") (set_attr "mode" "SI")]) @@ -2297,15 +1823,15 @@ (match_operand:DI 3 "register_operand" "0")))] "(TARGET_MAD || ISA_HAS_MACC) && !TARGET_64BIT" - "* { if (TARGET_MAD) - return \"madu\\t%1,%2\"; + return "madu\t%1,%2"; else if (TARGET_MIPS5500) - return \"maddu\\t%1,%2\"; + return "maddu\t%1,%2"; else - return \"maccu\\t%.,%1,%2\"; -}" + /* See comment in *macc. */ + return "%[maccu\t%@,%1,%2%]"; +} [(set_attr "type" "imadd") (set_attr "mode" "SI")]) @@ -2318,15 +1844,15 @@ (match_operand:DI 3 "register_operand" "0")))] "(TARGET_MAD || ISA_HAS_MACC) && !TARGET_64BIT" - "* { if (TARGET_MAD) - return \"mad\\t%1,%2\"; + return "mad\t%1,%2"; else if (TARGET_MIPS5500) - return \"madd\\t%1,%2\"; + return "madd\t%1,%2"; else - return \"macc\\t%.,%1,%2\"; -}" + /* See comment in *macc. */ + return "%[macc\t%@,%1,%2%]"; +} [(set_attr "type" "imadd") (set_attr "mode" "SI")]) @@ -2338,7 +1864,7 @@ (match_operand:DF 2 "register_operand" "f")) (match_operand:DF 3 "register_operand" "f")))] "ISA_HAS_FP4 && TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT && TARGET_FUSED_MADD" - "madd.d\\t%0,%3,%1,%2" + "madd.d\t%0,%3,%1,%2" [(set_attr "type" "fmadd") (set_attr "mode" "DF")]) @@ -2348,7 +1874,7 @@ (match_operand:SF 2 "register_operand" "f")) (match_operand:SF 3 "register_operand" "f")))] "ISA_HAS_FP4 && TARGET_HARD_FLOAT && TARGET_FUSED_MADD" - "madd.s\\t%0,%3,%1,%2" + "madd.s\t%0,%3,%1,%2" [(set_attr "type" "fmadd") (set_attr "mode" "SF")]) @@ -2358,7 +1884,7 @@ (match_operand:DF 2 "register_operand" "f")) (match_operand:DF 3 "register_operand" "f")))] "ISA_HAS_FP4 && TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT && TARGET_FUSED_MADD" - "msub.d\\t%0,%3,%1,%2" + "msub.d\t%0,%3,%1,%2" [(set_attr "type" "fmadd") (set_attr "mode" "DF")]) @@ -2369,7 +1895,7 @@ (match_operand:SF 3 "register_operand" "f")))] "ISA_HAS_FP4 && TARGET_HARD_FLOAT && TARGET_FUSED_MADD" - "msub.s\\t%0,%3,%1,%2" + "msub.s\t%0,%3,%1,%2" [(set_attr "type" "fmadd") (set_attr "mode" "SF")]) @@ -2378,8 +1904,20 @@ (neg:DF (plus:DF (mult:DF (match_operand:DF 1 "register_operand" "f") (match_operand:DF 2 "register_operand" "f")) (match_operand:DF 3 "register_operand" "f"))))] - "ISA_HAS_NMADD_NMSUB && TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT && TARGET_FUSED_MADD" - "nmadd.d\\t%0,%3,%1,%2" + "ISA_HAS_NMADD_NMSUB && TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT + && TARGET_FUSED_MADD && HONOR_SIGNED_ZEROS (DFmode)" + "nmadd.d\t%0,%3,%1,%2" + [(set_attr "type" "fmadd") + (set_attr "mode" "DF")]) + +(define_insn "" + [(set (match_operand:DF 0 "register_operand" "=f") + (minus:DF (mult:DF (neg:DF (match_operand:DF 1 "register_operand" "f")) + (match_operand:DF 2 "register_operand" "f")) + (match_operand:DF 3 "register_operand" "f")))] + "ISA_HAS_NMADD_NMSUB && TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT + && TARGET_FUSED_MADD && !HONOR_SIGNED_ZEROS (DFmode)" + "nmadd.d\t%0,%3,%1,%2" [(set_attr "type" "fmadd") (set_attr "mode" "DF")]) @@ -2388,28 +1926,64 @@ (neg:SF (plus:SF (mult:SF (match_operand:SF 1 "register_operand" "f") (match_operand:SF 2 "register_operand" "f")) (match_operand:SF 3 "register_operand" "f"))))] - "ISA_HAS_NMADD_NMSUB && TARGET_HARD_FLOAT && TARGET_FUSED_MADD" - "nmadd.s\\t%0,%3,%1,%2" + "ISA_HAS_NMADD_NMSUB && TARGET_HARD_FLOAT && TARGET_FUSED_MADD + && HONOR_SIGNED_ZEROS (SFmode)" + "nmadd.s\t%0,%3,%1,%2" + [(set_attr "type" "fmadd") + (set_attr "mode" "SF")]) + +(define_insn "" + [(set (match_operand:SF 0 "register_operand" "=f") + (minus:SF (mult:SF (neg:SF (match_operand:SF 1 "register_operand" "f")) + (match_operand:SF 2 "register_operand" "f")) + (match_operand:SF 3 "register_operand" "f")))] + "ISA_HAS_NMADD_NMSUB && TARGET_HARD_FLOAT && TARGET_FUSED_MADD + && !HONOR_SIGNED_ZEROS (SFmode)" + "nmadd.s\t%0,%3,%1,%2" [(set_attr "type" "fmadd") (set_attr "mode" "SF")]) (define_insn "" [(set (match_operand:DF 0 "register_operand" "=f") + (neg:DF (minus:DF (mult:DF (match_operand:DF 2 "register_operand" "f") + (match_operand:DF 3 "register_operand" "f")) + (match_operand:DF 1 "register_operand" "f"))))] + "ISA_HAS_NMADD_NMSUB && TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT + && TARGET_FUSED_MADD && HONOR_SIGNED_ZEROS (DFmode)" + "nmsub.d\t%0,%1,%2,%3" + [(set_attr "type" "fmadd") + (set_attr "mode" "DF")]) + +(define_insn "" + [(set (match_operand:DF 0 "register_operand" "=f") (minus:DF (match_operand:DF 1 "register_operand" "f") (mult:DF (match_operand:DF 2 "register_operand" "f") (match_operand:DF 3 "register_operand" "f"))))] - "ISA_HAS_NMADD_NMSUB && TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT && TARGET_FUSED_MADD" - "nmsub.d\\t%0,%1,%2,%3" + "ISA_HAS_NMADD_NMSUB && TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT + && TARGET_FUSED_MADD && !HONOR_SIGNED_ZEROS (DFmode)" + "nmsub.d\t%0,%1,%2,%3" [(set_attr "type" "fmadd") (set_attr "mode" "DF")]) (define_insn "" [(set (match_operand:SF 0 "register_operand" "=f") + (neg:SF (minus:SF (mult:SF (match_operand:SF 2 "register_operand" "f") + (match_operand:SF 3 "register_operand" "f")) + (match_operand:SF 1 "register_operand" "f"))))] + "ISA_HAS_NMADD_NMSUB && TARGET_HARD_FLOAT && TARGET_FUSED_MADD + && HONOR_SIGNED_ZEROS (SFmode)" + "nmsub.s\t%0,%1,%2,%3" + [(set_attr "type" "fmadd") + (set_attr "mode" "SF")]) + +(define_insn "" + [(set (match_operand:SF 0 "register_operand" "=f") (minus:SF (match_operand:SF 1 "register_operand" "f") (mult:SF (match_operand:SF 2 "register_operand" "f") (match_operand:SF 3 "register_operand" "f"))))] - "ISA_HAS_NMADD_NMSUB && TARGET_HARD_FLOAT && TARGET_FUSED_MADD" - "nmsub.s\\t%0,%1,%2,%3" + "ISA_HAS_NMADD_NMSUB && TARGET_HARD_FLOAT && TARGET_FUSED_MADD + && !HONOR_SIGNED_ZEROS (SFmode)" + "nmsub.s\t%0,%1,%2,%3" [(set_attr "type" "fmadd") (set_attr "mode" "SF")]) @@ -2421,42 +1995,132 @@ ;; .................... ;; -(define_insn "divdf3" +(define_expand "divdf3" + [(set (match_operand:DF 0 "register_operand") + (div:DF (match_operand:DF 1 "reg_or_1_operand") + (match_operand:DF 2 "register_operand")))] + "TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT" +{ + if (const_1_operand (operands[1], DFmode)) + if (!(ISA_HAS_FP4 && flag_unsafe_math_optimizations)) + operands[1] = force_reg (DFmode, operands[1]); +}) + +;; This pattern works around the early SB-1 rev2 core "F1" erratum: +;; +;; If an mfc1 or dmfc1 happens to access the floating point register +;; file at the same time a long latency operation (div, sqrt, recip, +;; sqrt) iterates an intermediate result back through the floating +;; point register file bypass, then instead returning the correct +;; register value the mfc1 or dmfc1 operation returns the intermediate +;; result of the long latency operation. +;; +;; The workaround is to insert an unconditional 'mov' from/to the +;; long latency op destination register. + +(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 && TARGET_DOUBLE_FLOAT" - "div.d\\t%0,%1,%2" +{ + if (TARGET_FIX_SB1) + return "div.d\t%0,%1,%2\;mov.d\t%0,%0"; + else + return "div.d\t%0,%1,%2"; +} [(set_attr "type" "fdiv") - (set_attr "mode" "DF")]) + (set_attr "mode" "DF") + (set (attr "length") + (if_then_else (ne (symbol_ref "TARGET_FIX_SB1") (const_int 0)) + (const_int 8) + (const_int 4)))]) + + +;; This pattern works around the early SB-1 rev2 core "F2" erratum: +;; +;; In certain cases, div.s and div.ps may have a rounding error +;; and/or wrong inexact flag. +;; +;; Therefore, we only allow div.s if not working around SB-1 rev2 +;; errata, or if working around those errata and a slight loss of +;; precision is OK (i.e., flag_unsafe_math_optimizations is set). +(define_expand "divsf3" + [(set (match_operand:SF 0 "register_operand") + (div:SF (match_operand:SF 1 "reg_or_1_operand") + (match_operand:SF 2 "register_operand")))] + "TARGET_HARD_FLOAT && (!TARGET_FIX_SB1 || flag_unsafe_math_optimizations)" +{ + if (const_1_operand (operands[1], SFmode)) + if (!(ISA_HAS_FP4 && flag_unsafe_math_optimizations)) + operands[1] = force_reg (SFmode, operands[1]); +}) -(define_insn "divsf3" +;; This pattern works around the early SB-1 rev2 core "F1" erratum (see +;; "divdf3" comment for details). +;; +;; This pattern works around the early SB-1 rev2 core "F2" erratum (see +;; "divsf3" comment for details). +(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" + "TARGET_HARD_FLOAT && (!TARGET_FIX_SB1 || flag_unsafe_math_optimizations)" +{ + if (TARGET_FIX_SB1) + return "div.s\t%0,%1,%2\;mov.s\t%0,%0"; + else + return "div.s\t%0,%1,%2"; +} [(set_attr "type" "fdiv") - (set_attr "mode" "SF")]) + (set_attr "mode" "SF") + (set (attr "length") + (if_then_else (ne (symbol_ref "TARGET_FIX_SB1") (const_int 0)) + (const_int 8) + (const_int 4)))]) +;; This pattern works around the early SB-1 rev2 core "F1" erratum (see +;; "divdf3" comment for details). (define_insn "" [(set (match_operand:DF 0 "register_operand" "=f") - (div:DF (match_operand:DF 1 "const_float_1_operand" "") + (div:DF (match_operand:DF 1 "const_1_operand" "") (match_operand:DF 2 "register_operand" "f")))] "ISA_HAS_FP4 && TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT && flag_unsafe_math_optimizations" - "recip.d\\t%0,%2" +{ + if (TARGET_FIX_SB1) + return "recip.d\t%0,%2\;mov.d\t%0,%0"; + else + return "recip.d\t%0,%2"; +} [(set_attr "type" "fdiv") - (set_attr "mode" "DF")]) + (set_attr "mode" "DF") + (set (attr "length") + (if_then_else (ne (symbol_ref "TARGET_FIX_SB1") (const_int 0)) + (const_int 8) + (const_int 4)))]) +;; This pattern works around the early SB-1 rev2 core "F1" erratum (see +;; "divdf3" comment for details). (define_insn "" [(set (match_operand:SF 0 "register_operand" "=f") - (div:SF (match_operand:SF 1 "const_float_1_operand" "") + (div:SF (match_operand:SF 1 "const_1_operand" "") (match_operand:SF 2 "register_operand" "f")))] "ISA_HAS_FP4 && TARGET_HARD_FLOAT && flag_unsafe_math_optimizations" - "recip.s\\t%0,%2" +{ + if (TARGET_FIX_SB1) + return "recip.s\t%0,%2\;mov.s\t%0,%0"; + else + return "recip.s\t%0,%2"; +} [(set_attr "type" "fdiv") - (set_attr "mode" "SF")]) + (set_attr "mode" "SF") + (set (attr "length") + (if_then_else (ne (symbol_ref "TARGET_FIX_SB1") (const_int 0)) + (const_int 8) + (const_int 4)))]) +;; VR4120 errata MD(A1): signed division instructions do not work correctly +;; with negative operands. We use special libgcc functions instead. (define_insn "divmodsi4" [(set (match_operand:SI 0 "register_operand" "=l") (div:SI (match_operand:SI 1 "register_operand" "d") @@ -2464,8 +2128,8 @@ (set (match_operand:SI 3 "register_operand" "=h") (mod:SI (match_dup 1) (match_dup 2)))] - "" - { return mips_output_division ("div\\t$0,%1,%2", operands); } + "!TARGET_FIX_VR4120" + { return mips_output_division ("div\t$0,%1,%2", operands); } [(set_attr "type" "idiv") (set_attr "mode" "SI")]) @@ -2476,8 +2140,8 @@ (set (match_operand:DI 3 "register_operand" "=h") (mod:DI (match_dup 1) (match_dup 2)))] - "TARGET_64BIT" - { return mips_output_division ("ddiv\\t$0,%1,%2", operands); } + "TARGET_64BIT && !TARGET_FIX_VR4120" + { return mips_output_division ("ddiv\t$0,%1,%2", operands); } [(set_attr "type" "idiv") (set_attr "mode" "DI")]) @@ -2489,7 +2153,7 @@ (umod:SI (match_dup 1) (match_dup 2)))] "" - { return mips_output_division ("divu\\t$0,%1,%2", operands); } + { return mips_output_division ("divu\t$0,%1,%2", operands); } [(set_attr "type" "idiv") (set_attr "mode" "SI")]) @@ -2501,9 +2165,10 @@ (umod:DI (match_dup 1) (match_dup 2)))] "TARGET_64BIT" - { return mips_output_division ("ddivu\\t$0,%1,%2", operands); } + { return mips_output_division ("ddivu\t$0,%1,%2", operands); } [(set_attr "type" "idiv") (set_attr "mode" "DI")]) + ;; ;; .................... ;; @@ -2511,40 +2176,123 @@ ;; ;; .................... +;; This pattern works around the early SB-1 rev2 core "F1" erratum (see +;; "divdf3" comment for details). (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() && TARGET_DOUBLE_FLOAT" - "sqrt.d\\t%0,%1" +{ + if (TARGET_FIX_SB1) + return "sqrt.d\t%0,%1\;mov.d\t%0,%0"; + else + return "sqrt.d\t%0,%1"; +} [(set_attr "type" "fsqrt") - (set_attr "mode" "DF")]) + (set_attr "mode" "DF") + (set (attr "length") + (if_then_else (ne (symbol_ref "TARGET_FIX_SB1") (const_int 0)) + (const_int 8) + (const_int 4)))]) +;; This pattern works around the early SB-1 rev2 core "F1" erratum (see +;; "divdf3" comment for details). (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" +{ + if (TARGET_FIX_SB1) + return "sqrt.s\t%0,%1\;mov.s\t%0,%0"; + else + return "sqrt.s\t%0,%1"; +} [(set_attr "type" "fsqrt") - (set_attr "mode" "SF")]) + (set_attr "mode" "SF") + (set (attr "length") + (if_then_else (ne (symbol_ref "TARGET_FIX_SB1") (const_int 0)) + (const_int 8) + (const_int 4)))]) +;; This pattern works around the early SB-1 rev2 core "F1" erratum (see +;; "divdf3" comment for details). (define_insn "" [(set (match_operand:DF 0 "register_operand" "=f") - (div:DF (match_operand:DF 1 "const_float_1_operand" "") + (div:DF (match_operand:DF 1 "const_1_operand" "") (sqrt:DF (match_operand:DF 2 "register_operand" "f"))))] "ISA_HAS_FP4 && TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT && flag_unsafe_math_optimizations" - "rsqrt.d\\t%0,%2" +{ + if (TARGET_FIX_SB1) + return "rsqrt.d\t%0,%2\;mov.d\t%0,%0"; + else + return "rsqrt.d\t%0,%2"; +} [(set_attr "type" "frsqrt") - (set_attr "mode" "DF")]) + (set_attr "mode" "DF") + (set (attr "length") + (if_then_else (ne (symbol_ref "TARGET_FIX_SB1") (const_int 0)) + (const_int 8) + (const_int 4)))]) +;; This pattern works around the early SB-1 rev2 core "F1" erratum (see +;; "divdf3" comment for details). (define_insn "" [(set (match_operand:SF 0 "register_operand" "=f") - (div:SF (match_operand:SF 1 "const_float_1_operand" "") + (div:SF (match_operand:SF 1 "const_1_operand" "") (sqrt:SF (match_operand:SF 2 "register_operand" "f"))))] "ISA_HAS_FP4 && TARGET_HARD_FLOAT && flag_unsafe_math_optimizations" - "rsqrt.s\\t%0,%2" +{ + if (TARGET_FIX_SB1) + return "rsqrt.s\t%0,%2\;mov.s\t%0,%0"; + else + return "rsqrt.s\t%0,%2"; +} [(set_attr "type" "frsqrt") - (set_attr "mode" "SF")]) + (set_attr "mode" "SF") + (set (attr "length") + (if_then_else (ne (symbol_ref "TARGET_FIX_SB1") (const_int 0)) + (const_int 8) + (const_int 4)))]) + +;; This pattern works around the early SB-1 rev2 core "F1" erratum (see +;; "divdf3" comment for details). +(define_insn "" + [(set (match_operand:DF 0 "register_operand" "=f") + (sqrt:DF (div:DF (match_operand:DF 1 "const_1_operand" "") + (match_operand:DF 2 "register_operand" "f"))))] + "ISA_HAS_FP4 && TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT && flag_unsafe_math_optimizations" +{ + if (TARGET_FIX_SB1) + return "rsqrt.d\t%0,%2\;mov.d\t%0,%0"; + else + return "rsqrt.d\t%0,%2"; +} + [(set_attr "type" "frsqrt") + (set_attr "mode" "DF") + (set (attr "length") + (if_then_else (ne (symbol_ref "TARGET_FIX_SB1") (const_int 0)) + (const_int 8) + (const_int 4)))]) +;; This pattern works around the early SB-1 rev2 core "F1" erratum (see +;; "divdf3" comment for details). +(define_insn "" + [(set (match_operand:SF 0 "register_operand" "=f") + (sqrt:SF (div:SF (match_operand:SF 1 "const_1_operand" "") + (match_operand:SF 2 "register_operand" "f"))))] + "ISA_HAS_FP4 && TARGET_HARD_FLOAT && flag_unsafe_math_optimizations" +{ + if (TARGET_FIX_SB1) + return "rsqrt.s\t%0,%2\;mov.s\t%0,%0"; + else + return "rsqrt.s\t%0,%2"; +} + [(set_attr "type" "frsqrt") + (set_attr "mode" "SF") + (set (attr "length") + (if_then_else (ne (symbol_ref "TARGET_FIX_SB1") (const_int 0)) + (const_int 8) + (const_int 4)))]) ;; ;; .................... @@ -2560,20 +2308,19 @@ [(set (match_operand:SI 0 "register_operand" "=d") (abs:SI (match_operand:SI 1 "register_operand" "d")))] "!TARGET_MIPS16" - "* { operands[2] = const0_rtx; if (REGNO (operands[0]) == REGNO (operands[1])) { if (GENERATE_BRANCHLIKELY) - return \"%(bltzl\\t%1,1f\\n\\tsubu\\t%0,%z2,%0\\n%~1:%)\"; + return "%(bltzl\t%1,1f\;subu\t%0,%z2,%0\n%~1:%)"; else - return \"bgez\\t%1,1f%#\\n\\tsubu\\t%0,%z2,%0\\n%~1:\"; + return "bgez\t%1,1f%#\;subu\t%0,%z2,%0\n%~1:"; } else - return \"%(bgez\\t%1,1f\\n\\tmove\\t%0,%1\\n\\tsubu\\t%0,%z2,%0\\n%~1:%)\"; -}" + return "%(bgez\t%1,1f\;move\t%0,%1\;subu\t%0,%z2,%0\n%~1:%)"; +} [(set_attr "type" "multi") (set_attr "mode" "SI") (set_attr "length" "12")]) @@ -2582,7 +2329,6 @@ [(set (match_operand:DI 0 "register_operand" "=d") (abs:DI (match_operand:DI 1 "register_operand" "d")))] "TARGET_64BIT && !TARGET_MIPS16" - "* { unsigned int regno1; operands[2] = const0_rtx; @@ -2593,10 +2339,10 @@ regno1 = REGNO (XEXP (operands[1], 0)); if (REGNO (operands[0]) == regno1) - return \"%(bltzl\\t%1,1f\\n\\tdsubu\\t%0,%z2,%0\\n%~1:%)\"; + return "%(bltzl\t%1,1f\;dsubu\t%0,%z2,%0\n%~1:%)"; else - return \"%(bgez\\t%1,1f\\n\\tmove\\t%0,%1\\n\\tdsubu\\t%0,%z2,%0\\n%~1:%)\"; -}" + return "%(bgez\t%1,1f\;move\t%0,%1\;dsubu\t%0,%z2,%0\n%~1:%)"; +} [(set_attr "type" "multi") (set_attr "mode" "DI") (set_attr "length" "12")]) @@ -2605,7 +2351,7 @@ [(set (match_operand:DF 0 "register_operand" "=f") (abs:DF (match_operand:DF 1 "register_operand" "f")))] "TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT" - "abs.d\\t%0,%1" + "abs.d\t%0,%1" [(set_attr "type" "fabs") (set_attr "mode" "DF")]) @@ -2613,10 +2359,9 @@ [(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" + "abs.s\t%0,%1" [(set_attr "type" "fabs") (set_attr "mode" "SF")]) - ;; ;; .................... @@ -2632,30 +2377,27 @@ (clobber (match_scratch:SI 2 "=&d")) (clobber (match_scratch:SI 3 "=&d"))] "!TARGET_MIPS16" - "* { - 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:%)\"; -}" + return "%(\ +move\t%0,%.\;\ +beq\t%1,%.,2f\n\ +%~1:\tand\t%2,%1,0x0001\;\ +addu\t%0,%0,1\;\ +beq\t%2,%.,1b\;\ +srl\t%1,%1,1\n\ +%~2:%)"; + + return "%(\ +move\t%0,%.\;\ +move\t%3,%1\;\ +beq\t%3,%.,2f\n\ +%~1:\tand\t%2,%3,0x0001\;\ +addu\t%0,%0,1\;\ +beq\t%2,%.,1b\;\ +srl\t%3,%3,1\n\ +%~2:%)"; +} [(set_attr "type" "multi") (set_attr "mode" "SI") (set_attr "length" "28")]) @@ -2666,36 +2408,31 @@ move\\t%0,%z4\\n\\ (clobber (match_scratch:DI 2 "=&d")) (clobber (match_scratch:DI 3 "=&d"))] "TARGET_64BIT && !TARGET_MIPS16" - "* { - 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\\ -\\tdaddu\\t%0,%0,1\\n\\ -\\tbeq\\t%2,%z4,1b\\n\\ -\\tdsrl\\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\\ -\\tdaddu\\t%0,%0,1\\n\\ -\\tbeq\\t%2,%z4,1b\\n\\ -\\tdsrl\\t%3,%3,1\\n\\ -%~2:%)\"; -}" + return "%(\ +move\t%0,%.\;\ +beq\t%1,%.,2f\n\ +%~1:\tand\t%2,%1,0x0001\;\ +daddu\t%0,%0,1\;\ +beq\t%2,%.,1b\;\ +dsrl\t%1,%1,1\n\ +%~2:%)"; + + return "%(\ +move\t%0,%.\;\ +move\t%3,%1\;\ +beq\t%3,%.,2f\n\ +%~1:\tand\t%2,%3,0x0001\;\ +daddu\t%0,%0,1\;\ +beq\t%2,%.,1b\;\ +dsrl\t%3,%3,1\n\ +%~2:%)"; +} [(set_attr "type" "multi") (set_attr "mode" "DI") (set_attr "length" "28")]) - - ;; ;; ................... ;; @@ -2708,18 +2445,18 @@ move\\t%0,%z4\\n\\ [(set (match_operand:SI 0 "register_operand" "=d") (clz:SI (match_operand:SI 1 "register_operand" "d")))] "ISA_HAS_CLZ_CLO" - "clz\\t%0,%1" - [(set_attr "type" "arith") + "clz\t%0,%1" + [(set_attr "type" "clz") (set_attr "mode" "SI")]) (define_insn "clzdi2" [(set (match_operand:DI 0 "register_operand" "=d") (clz:DI (match_operand:DI 1 "register_operand" "d")))] "ISA_HAS_DCLZ_DCLO" - "dclz\\t%0,%1" - [(set_attr "type" "arith") + "dclz\t%0,%1" + [(set_attr "type" "clz") (set_attr "mode" "DI")]) - + ;; ;; .................... ;; @@ -2731,55 +2468,20 @@ move\\t%0,%z4\\n\\ [(set (match_operand:SI 0 "register_operand" "=d") (neg:SI (match_operand:SI 1 "register_operand" "d")))] "" - "* { if (TARGET_MIPS16) - return \"neg\\t%0,%1\"; - operands[2] = const0_rtx; - return \"subu\\t%0,%z2,%1\"; -}" + return "neg\t%0,%1"; + else + return "subu\t%0,%.,%1"; +} [(set_attr "type" "arith") (set_attr "mode" "SI")]) -(define_expand "negdi2" - [(parallel [(set (match_operand:DI 0 "register_operand" "=d") - (neg:DI (match_operand:DI 1 "register_operand" "d"))) - (clobber (match_dup 2))])] - "(TARGET_64BIT || !TARGET_DEBUG_G_MODE) && !TARGET_MIPS16" - " -{ - if (TARGET_64BIT) - { - emit_insn (gen_negdi2_internal_2 (operands[0], operands[1])); - DONE; - } - - operands[2] = gen_reg_rtx (SImode); -}") - -(define_insn "negdi2_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_64BIT && !TARGET_DEBUG_G_MODE && !TARGET_MIPS16" - "* -{ - 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" "16")]) - -(define_insn "negdi2_internal_2" +(define_insn "negdi2" [(set (match_operand:DI 0 "register_operand" "=d") (neg:DI (match_operand:DI 1 "register_operand" "d")))] "TARGET_64BIT && !TARGET_MIPS16" - "* -{ - operands[2] = const0_rtx; - return \"dsubu\\t%0,%z2,%1\"; -}" + "dsubu\t%0,%.,%1" [(set_attr "type" "arith") (set_attr "mode" "DI")]) @@ -2787,7 +2489,7 @@ move\\t%0,%z4\\n\\ [(set (match_operand:DF 0 "register_operand" "=f") (neg:DF (match_operand:DF 1 "register_operand" "f")))] "TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT" - "neg.d\\t%0,%1" + "neg.d\t%0,%1" [(set_attr "type" "fneg") (set_attr "mode" "DF")]) @@ -2795,7 +2497,7 @@ move\\t%0,%z4\\n\\ [(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" + "neg.s\t%0,%1" [(set_attr "type" "fneg") (set_attr "mode" "SF")]) @@ -2803,13 +2505,12 @@ move\\t%0,%z4\\n\\ [(set (match_operand:SI 0 "register_operand" "=d") (not:SI (match_operand:SI 1 "register_operand" "d")))] "" - "* { if (TARGET_MIPS16) - return \"not\\t%0,%1\"; - operands[2] = const0_rtx; - return \"nor\\t%0,%z2,%1\"; -}" + return "not\t%0,%1"; + else + return "nor\t%0,%.,%1"; +} [(set_attr "type" "arith") (set_attr "mode" "SI")]) @@ -2817,13 +2518,13 @@ move\\t%0,%z4\\n\\ [(set (match_operand:DI 0 "register_operand" "=d") (not:DI (match_operand:DI 1 "register_operand" "d")))] "TARGET_64BIT" - "* { if (TARGET_MIPS16) - return \"not\\t%0,%1\"; - return \"nor\\t%0,%.,%1\"; -}" - [(set_attr "type" "darith") + return "not\t%0,%1"; + else + return "nor\t%0,%.,%1"; +} + [(set_attr "type" "arith") (set_attr "mode" "DI")]) ;; @@ -2834,22 +2535,21 @@ move\\t%0,%z4\\n\\ ;; .................... ;; -;; Many of these instructions uses trivial define_expands, because we +;; Many of these instructions use trivial define_expands, because we ;; want to use a different set of constraints when TARGET_MIPS16. (define_expand "andsi3" - [(set (match_operand:SI 0 "register_operand" "=d,d") - (and:SI (match_operand:SI 1 "uns_arith_operand" "%d,d") - (match_operand:SI 2 "uns_arith_operand" "d,K")))] + [(set (match_operand:SI 0 "register_operand") + (and:SI (match_operand:SI 1 "uns_arith_operand") + (match_operand:SI 2 "uns_arith_operand")))] "" - " { if (TARGET_MIPS16) { operands[1] = force_reg (SImode, operands[1]); operands[2] = force_reg (SImode, operands[2]); } -}") +}) (define_insn "" [(set (match_operand:SI 0 "register_operand" "=d,d") @@ -2857,8 +2557,8 @@ move\\t%0,%z4\\n\\ (match_operand:SI 2 "uns_arith_operand" "d,K")))] "!TARGET_MIPS16" "@ - and\\t%0,%1,%2 - andi\\t%0,%1,%x2" + and\t%0,%1,%2 + andi\t%0,%1,%x2" [(set_attr "type" "arith") (set_attr "mode" "SI")]) @@ -2867,23 +2567,22 @@ move\\t%0,%z4\\n\\ (and:SI (match_operand:SI 1 "register_operand" "%0") (match_operand:SI 2 "register_operand" "d")))] "TARGET_MIPS16" - "and\\t%0,%2" + "and\t%0,%2" [(set_attr "type" "arith") (set_attr "mode" "SI")]) (define_expand "anddi3" - [(set (match_operand:DI 0 "register_operand" "") - (and:DI (match_operand:DI 1 "register_operand" "") - (match_operand:DI 2 "uns_arith_operand" "")))] + [(set (match_operand:DI 0 "register_operand") + (and:DI (match_operand:DI 1 "register_operand") + (match_operand:DI 2 "uns_arith_operand")))] "TARGET_64BIT" - " { if (TARGET_MIPS16) { operands[1] = force_reg (DImode, operands[1]); operands[2] = force_reg (DImode, operands[2]); } -}") +}) (define_insn "" [(set (match_operand:DI 0 "register_operand" "=d,d") @@ -2891,9 +2590,9 @@ move\\t%0,%z4\\n\\ (match_operand:DI 2 "uns_arith_operand" "d,K")))] "TARGET_64BIT && !TARGET_MIPS16" "@ - and\\t%0,%1,%2 - andi\\t%0,%1,%x2" - [(set_attr "type" "darith") + and\t%0,%1,%2 + andi\t%0,%1,%x2" + [(set_attr "type" "arith") (set_attr "mode" "DI")]) (define_insn "" @@ -2901,23 +2600,22 @@ move\\t%0,%z4\\n\\ (and:DI (match_operand:DI 1 "register_operand" "0") (match_operand:DI 2 "register_operand" "d")))] "TARGET_64BIT && TARGET_MIPS16" - "and\\t%0,%2" - [(set_attr "type" "darith") + "and\t%0,%2" + [(set_attr "type" "arith") (set_attr "mode" "DI")]) (define_expand "iorsi3" - [(set (match_operand:SI 0 "register_operand" "=d,d") - (ior:SI (match_operand:SI 1 "uns_arith_operand" "%d,d") - (match_operand:SI 2 "uns_arith_operand" "d,K")))] + [(set (match_operand:SI 0 "register_operand") + (ior:SI (match_operand:SI 1 "uns_arith_operand") + (match_operand:SI 2 "uns_arith_operand")))] "" - " { if (TARGET_MIPS16) { operands[1] = force_reg (SImode, operands[1]); operands[2] = force_reg (SImode, operands[2]); } -}") +}) (define_insn "" [(set (match_operand:SI 0 "register_operand" "=d,d") @@ -2925,8 +2623,8 @@ move\\t%0,%z4\\n\\ (match_operand:SI 2 "uns_arith_operand" "d,K")))] "!TARGET_MIPS16" "@ - or\\t%0,%1,%2 - ori\\t%0,%1,%x2" + or\t%0,%1,%2 + ori\t%0,%1,%x2" [(set_attr "type" "arith") (set_attr "mode" "SI")]) @@ -2935,23 +2633,22 @@ move\\t%0,%z4\\n\\ (ior:SI (match_operand:SI 1 "register_operand" "%0") (match_operand:SI 2 "register_operand" "d")))] "TARGET_MIPS16" - "or\\t%0,%2" + "or\t%0,%2" [(set_attr "type" "arith") (set_attr "mode" "SI")]) (define_expand "iordi3" - [(set (match_operand:DI 0 "register_operand" "") - (ior:DI (match_operand:DI 1 "register_operand" "") - (match_operand:DI 2 "uns_arith_operand" "")))] + [(set (match_operand:DI 0 "register_operand") + (ior:DI (match_operand:DI 1 "register_operand") + (match_operand:DI 2 "uns_arith_operand")))] "TARGET_64BIT" - " { if (TARGET_MIPS16) { operands[1] = force_reg (DImode, operands[1]); operands[2] = force_reg (DImode, operands[2]); } -}") +}) (define_insn "" [(set (match_operand:DI 0 "register_operand" "=d,d") @@ -2961,7 +2658,7 @@ move\\t%0,%z4\\n\\ "@ or\t%0,%1,%2 ori\t%0,%1,%x2" - [(set_attr "type" "darith") + [(set_attr "type" "arith") (set_attr "mode" "DI")]) (define_insn "" @@ -2970,13 +2667,13 @@ move\\t%0,%z4\\n\\ (match_operand:DI 2 "register_operand" "d")))] "TARGET_64BIT && TARGET_MIPS16" "or\t%0,%2" - [(set_attr "type" "darith") + [(set_attr "type" "arith") (set_attr "mode" "DI")]) (define_expand "xorsi3" - [(set (match_operand:SI 0 "register_operand" "=d,d") - (xor:SI (match_operand:SI 1 "uns_arith_operand" "%d,d") - (match_operand:SI 2 "uns_arith_operand" "d,K")))] + [(set (match_operand:SI 0 "register_operand") + (xor:SI (match_operand:SI 1 "uns_arith_operand") + (match_operand:SI 2 "uns_arith_operand")))] "" "") @@ -2986,8 +2683,8 @@ move\\t%0,%z4\\n\\ (match_operand:SI 2 "uns_arith_operand" "d,K")))] "!TARGET_MIPS16" "@ - xor\\t%0,%1,%2 - xori\\t%0,%1,%x2" + xor\t%0,%1,%2 + xori\t%0,%1,%x2" [(set_attr "type" "arith") (set_attr "mode" "SI")]) @@ -2997,31 +2694,30 @@ move\\t%0,%z4\\n\\ (match_operand:SI 2 "uns_arith_operand" "d,K,d")))] "TARGET_MIPS16" "@ - xor\\t%0,%2 - cmpi\\t%1,%2 - cmp\\t%1,%2" + xor\t%0,%2 + cmpi\t%1,%2 + cmp\t%1,%2" [(set_attr "type" "arith") (set_attr "mode" "SI") (set_attr_alternative "length" [(const_int 4) - (if_then_else (match_operand:VOID 2 "m16_uimm8_1" "") + (if_then_else (match_operand:VOID 2 "m16_uimm8_1") (const_int 4) (const_int 8)) (const_int 4)])]) (define_expand "xordi3" - [(set (match_operand:DI 0 "register_operand" "") - (xor:DI (match_operand:DI 1 "register_operand" "") - (match_operand:DI 2 "uns_arith_operand" "")))] + [(set (match_operand:DI 0 "register_operand") + (xor:DI (match_operand:DI 1 "register_operand") + (match_operand:DI 2 "uns_arith_operand")))] "TARGET_64BIT" - " { if (TARGET_MIPS16) { operands[1] = force_reg (DImode, operands[1]); operands[2] = force_reg (DImode, operands[2]); } -}") +}) (define_insn "" [(set (match_operand:DI 0 "register_operand" "=d,d") @@ -3031,7 +2727,7 @@ move\\t%0,%z4\\n\\ "@ xor\t%0,%1,%2 xori\t%0,%1,%x2" - [(set_attr "type" "darith") + [(set_attr "type" "arith") (set_attr "mode" "DI")]) (define_insn "" @@ -3040,14 +2736,14 @@ move\\t%0,%z4\\n\\ (match_operand:DI 2 "uns_arith_operand" "d,K,d")))] "TARGET_64BIT && TARGET_MIPS16" "@ - xor\\t%0,%2 - cmpi\\t%1,%2 - cmp\\t%1,%2" + xor\t%0,%2 + cmpi\t%1,%2 + cmp\t%1,%2" [(set_attr "type" "arith") (set_attr "mode" "DI") (set_attr_alternative "length" [(const_int 4) - (if_then_else (match_operand:VOID 2 "m16_uimm8_1" "") + (if_then_else (match_operand:VOID 2 "m16_uimm8_1") (const_int 4) (const_int 8)) (const_int 4)])]) @@ -3057,7 +2753,7 @@ move\\t%0,%z4\\n\\ (and:SI (not:SI (match_operand:SI 1 "register_operand" "d")) (not:SI (match_operand:SI 2 "register_operand" "d"))))] "!TARGET_MIPS16" - "nor\\t%0,%z1,%z2" + "nor\t%0,%z1,%z2" [(set_attr "type" "arith") (set_attr "mode" "SI")]) @@ -3066,8 +2762,8 @@ move\\t%0,%z4\\n\\ (and:DI (not:DI (match_operand:DI 1 "register_operand" "d")) (not:DI (match_operand:DI 2 "register_operand" "d"))))] "TARGET_64BIT && !TARGET_MIPS16" - "nor\\t%0,%z1,%z2" - [(set_attr "type" "darith") + "nor\t%0,%z1,%z2" + [(set_attr "type" "arith") (set_attr "mode" "DI")]) ;; @@ -3083,7 +2779,7 @@ move\\t%0,%z4\\n\\ [(set (match_operand:SF 0 "register_operand" "=f") (float_truncate:SF (match_operand:DF 1 "register_operand" "f")))] "TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT" - "cvt.s.d\\t%0,%1" + "cvt.s.d\t%0,%1" [(set_attr "type" "fcvt") (set_attr "mode" "SF")]) @@ -3107,7 +2803,7 @@ move\\t%0,%z4\\n\\ "@ sll\t%0,%1,0 sw\t%1,%0" - [(set_attr "type" "darith,store") + [(set_attr "type" "shift,store") (set_attr "mode" "SI") (set_attr "extended_mips16" "yes,*")]) @@ -3118,7 +2814,7 @@ move\\t%0,%z4\\n\\ "@ sll\t%0,%1,0 sh\t%1,%0" - [(set_attr "type" "darith,store") + [(set_attr "type" "shift,store") (set_attr "mode" "SI") (set_attr "extended_mips16" "yes,*")]) @@ -3129,7 +2825,7 @@ move\\t%0,%z4\\n\\ "@ sll\t%0,%1,0 sb\t%1,%0" - [(set_attr "type" "darith,store") + [(set_attr "type" "shift,store") (set_attr "mode" "SI") (set_attr "extended_mips16" "yes,*")]) @@ -3137,11 +2833,12 @@ move\\t%0,%z4\\n\\ (define_insn "" [(set (match_operand:SI 0 "register_operand" "=d") - (truncate:SI (ashiftrt:DI (match_operand:DI 1 "register_operand" "d") - (match_operand:DI 2 "small_int" "I"))))] + (truncate:SI + (ashiftrt:DI (match_operand:DI 1 "register_operand" "d") + (match_operand:DI 2 "const_arith_operand" ""))))] "TARGET_64BIT && !TARGET_MIPS16 && INTVAL (operands[2]) >= 32" - "dsra\\t%0,%1,%2" - [(set_attr "type" "darith") + "dsra\t%0,%1,%2" + [(set_attr "type" "shift") (set_attr "mode" "SI")]) (define_insn "" @@ -3149,8 +2846,8 @@ move\\t%0,%z4\\n\\ (truncate:SI (lshiftrt:DI (match_operand:DI 1 "register_operand" "d") (const_int 32))))] "TARGET_64BIT && !TARGET_MIPS16" - "dsra\\t%0,%1,32" - [(set_attr "type" "darith") + "dsra\t%0,%1,32" + [(set_attr "type" "shift") (set_attr "mode" "SI")]) @@ -3195,8 +2892,8 @@ move\\t%0,%z4\\n\\ (zero_extend:SI (truncate:HI (match_operand:DI 1 "register_operand" "d"))))] "TARGET_64BIT && !TARGET_MIPS16" - "andi\\t%0,%1,0xffff" - [(set_attr "type" "darith") + "andi\t%0,%1,0xffff" + [(set_attr "type" "arith") (set_attr "mode" "SI")]) (define_insn "" @@ -3204,8 +2901,8 @@ move\\t%0,%z4\\n\\ (zero_extend:SI (truncate:QI (match_operand:DI 1 "register_operand" "d"))))] "TARGET_64BIT && !TARGET_MIPS16" - "andi\\t%0,%1,0xff" - [(set_attr "type" "darith") + "andi\t%0,%1,0xff" + [(set_attr "type" "arith") (set_attr "mode" "SI")]) (define_insn "" @@ -3213,10 +2910,9 @@ move\\t%0,%z4\\n\\ (zero_extend:HI (truncate:QI (match_operand:DI 1 "register_operand" "d"))))] "TARGET_64BIT && !TARGET_MIPS16" - "andi\\t%0,%1,0xff" - [(set_attr "type" "darith") + "andi\t%0,%1,0xff" + [(set_attr "type" "arith") (set_attr "mode" "HI")]) - ;; ;; .................... @@ -3239,22 +2935,22 @@ move\\t%0,%z4\\n\\ (set (match_dup 0) (lshiftrt:DI (match_dup 0) (const_int 32)))] "operands[1] = gen_lowpart (DImode, operands[1]);" - [(set_attr "type" "arith") - (set_attr "mode" "DI")]) + [(set_attr "type" "multi") + (set_attr "mode" "DI") + (set_attr "length" "8")]) (define_insn "*zero_extendsidi2_mem" [(set (match_operand:DI 0 "register_operand" "=d") - (zero_extend:DI (match_operand:SI 1 "memory_operand" "m")))] - "TARGET_64BIT && !TARGET_MIPS16" + (zero_extend:DI (match_operand:SI 1 "memory_operand" "W")))] + "TARGET_64BIT" "lwu\t%0,%1" [(set_attr "type" "load") (set_attr "mode" "DI")]) (define_expand "zero_extendhisi2" - [(set (match_operand:SI 0 "register_operand" "") - (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "")))] + [(set (match_operand:SI 0 "register_operand") + (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand")))] "" - " { if (TARGET_MIPS16 && GET_CODE (operands[1]) != MEM) { @@ -3264,7 +2960,7 @@ move\\t%0,%z4\\n\\ emit_insn (gen_andsi3 (operands[0], op, temp)); DONE; } -}") +}) (define_insn "" [(set (match_operand:SI 0 "register_operand" "=d,d") @@ -3286,10 +2982,9 @@ move\\t%0,%z4\\n\\ (set_attr "mode" "SI")]) (define_expand "zero_extendhidi2" - [(set (match_operand:DI 0 "register_operand" "") - (zero_extend:DI (match_operand:HI 1 "nonimmediate_operand" "")))] + [(set (match_operand:DI 0 "register_operand") + (zero_extend:DI (match_operand:HI 1 "nonimmediate_operand")))] "TARGET_64BIT" - " { if (TARGET_MIPS16 && GET_CODE (operands[1]) != MEM) { @@ -3299,7 +2994,7 @@ move\\t%0,%z4\\n\\ emit_insn (gen_anddi3 (operands[0], op, temp)); DONE; } -}") +}) (define_insn "" [(set (match_operand:DI 0 "register_operand" "=d,d") @@ -3321,10 +3016,9 @@ move\\t%0,%z4\\n\\ (set_attr "mode" "DI")]) (define_expand "zero_extendqihi2" - [(set (match_operand:HI 0 "register_operand" "") - (zero_extend:HI (match_operand:QI 1 "nonimmediate_operand" "")))] + [(set (match_operand:HI 0 "register_operand") + (zero_extend:HI (match_operand:QI 1 "nonimmediate_operand")))] "" - " { if (TARGET_MIPS16 && GET_CODE (operands[1]) != MEM) { @@ -3335,7 +3029,7 @@ move\\t%0,%z4\\n\\ emit_insn (gen_andsi3 (op0, op1, temp)); DONE; } -}") +}) (define_insn "" [(set (match_operand:HI 0 "register_operand" "=d,d") @@ -3357,10 +3051,9 @@ move\\t%0,%z4\\n\\ (set_attr "mode" "HI")]) (define_expand "zero_extendqisi2" - [(set (match_operand:SI 0 "register_operand" "") - (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "")))] + [(set (match_operand:SI 0 "register_operand") + (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand")))] "" - " { if (TARGET_MIPS16 && GET_CODE (operands[1]) != MEM) { @@ -3370,7 +3063,7 @@ move\\t%0,%z4\\n\\ emit_insn (gen_andsi3 (operands[0], op, temp)); DONE; } -}") +}) (define_insn "" [(set (match_operand:SI 0 "register_operand" "=d,d") @@ -3392,10 +3085,9 @@ move\\t%0,%z4\\n\\ (set_attr "mode" "SI")]) (define_expand "zero_extendqidi2" - [(set (match_operand:DI 0 "register_operand" "") - (zero_extend:DI (match_operand:QI 1 "nonimmediate_operand" "")))] + [(set (match_operand:DI 0 "register_operand") + (zero_extend:DI (match_operand:QI 1 "nonimmediate_operand")))] "TARGET_64BIT" - " { if (TARGET_MIPS16 && GET_CODE (operands[1]) != MEM) { @@ -3405,7 +3097,7 @@ move\\t%0,%z4\\n\\ emit_insn (gen_anddi3 (operands[0], op, temp)); DONE; } -}") +}) (define_insn "" [(set (match_operand:DI 0 "register_operand" "=d,d") @@ -3436,30 +3128,29 @@ move\\t%0,%z4\\n\\ ;; Extension insns. ;; Those for integer source operand are ordered widest source type first. -(define_expand "extendsidi2" - [(set (match_operand:DI 0 "register_operand" "") - (sign_extend:DI (match_operand:SI 1 "move_operand" "")))] - "TARGET_64BIT" - " -{ - if (symbolic_operand (operands[1], SImode)) - { - emit_move_insn (operands[0], convert_memory_address (DImode, operands[1])); - DONE; - } - -}") - -(define_insn "*extendsidi2" +;; When TARGET_64BIT, all SImode integer registers should already be in +;; sign-extended form (see TRULY_NOOP_TRUNCATION and truncdisi2). We can +;; therefore get rid of register->register instructions if we constrain +;; the source to be in the same register as the destination. +;; +;; The register alternative has type "arith" so that the pre-reload +;; scheduler will treat it as a move. This reflects what happens if +;; the register alternative needs a reload. +(define_insn_and_split "extendsidi2" [(set (match_operand:DI 0 "register_operand" "=d,d") - (sign_extend:DI (match_operand:SI 1 "nonimmediate_operand" "d,m")))] + (sign_extend:DI (match_operand:SI 1 "nonimmediate_operand" "0,m")))] "TARGET_64BIT" "@ - sll\t%0,%1,0 + # lw\t%0,%1" + "&& reload_completed && register_operand (operands[1], VOIDmode)" + [(const_int 0)] +{ + emit_note (NOTE_INSN_DELETED); + DONE; +} [(set_attr "type" "arith,load") - (set_attr "mode" "DI") - (set_attr "extended_mips16" "yes,*")]) + (set_attr "mode" "DI")]) ;; These patterns originally accepted general_operands, however, slightly ;; better code is generated by only accepting register_operands, and then @@ -3469,8 +3160,8 @@ move\\t%0,%z4\\n\\ ;; all non-mem patterns after reload. (define_expand "extendhidi2" - [(set (match_operand:DI 0 "register_operand" "") - (sign_extend:DI (match_operand:HI 1 "nonimmediate_operand" "")))] + [(set (match_operand:DI 0 "register_operand") + (sign_extend:DI (match_operand:HI 1 "nonimmediate_operand")))] "TARGET_64BIT" "") @@ -3481,8 +3172,8 @@ move\\t%0,%z4\\n\\ "#") (define_split - [(set (match_operand:DI 0 "register_operand" "") - (sign_extend:DI (match_operand:HI 1 "register_operand" "")))] + [(set (match_operand:DI 0 "register_operand") + (sign_extend:DI (match_operand:HI 1 "register_operand")))] "TARGET_64BIT && reload_completed" [(set (match_dup 0) (ashift:DI (match_dup 1) (const_int 48))) @@ -3499,17 +3190,17 @@ move\\t%0,%z4\\n\\ (set_attr "mode" "DI")]) (define_expand "extendhisi2" - [(set (match_operand:SI 0 "register_operand" "") - (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "")))] + [(set (match_operand:SI 0 "register_operand") + (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand")))] "" - " - if (ISA_HAS_SEB_SEH) - { - emit_insn (gen_extendhisi2_hw (operands[0], - force_reg (HImode, operands[1]))); - DONE; - } -") +{ + if (ISA_HAS_SEB_SEH) + { + emit_insn (gen_extendhisi2_hw (operands[0], + force_reg (HImode, operands[1]))); + DONE; + } +}) (define_insn "*extendhisi2" [(set (match_operand:SI 0 "register_operand" "=d") @@ -3518,8 +3209,8 @@ move\\t%0,%z4\\n\\ "#") (define_split - [(set (match_operand:SI 0 "register_operand" "") - (sign_extend:SI (match_operand:HI 1 "register_operand" "")))] + [(set (match_operand:SI 0 "register_operand") + (sign_extend:SI (match_operand:HI 1 "register_operand")))] "reload_completed" [(set (match_dup 0) (ashift:SI (match_dup 1) (const_int 16))) @@ -3539,13 +3230,13 @@ move\\t%0,%z4\\n\\ [(set (match_operand:SI 0 "register_operand" "=r") (sign_extend:SI (match_operand:HI 1 "register_operand" "r")))] "ISA_HAS_SEB_SEH" - "seh\\t%0,%1" + "seh\t%0,%1" [(set_attr "type" "arith") (set_attr "mode" "SI")]) (define_expand "extendqihi2" - [(set (match_operand:HI 0 "register_operand" "") - (sign_extend:HI (match_operand:QI 1 "nonimmediate_operand" "")))] + [(set (match_operand:HI 0 "register_operand") + (sign_extend:HI (match_operand:QI 1 "nonimmediate_operand")))] "" "") @@ -3556,8 +3247,8 @@ move\\t%0,%z4\\n\\ "#") (define_split - [(set (match_operand:HI 0 "register_operand" "") - (sign_extend:HI (match_operand:QI 1 "register_operand" "")))] + [(set (match_operand:HI 0 "register_operand") + (sign_extend:HI (match_operand:QI 1 "register_operand")))] "reload_completed" [(set (match_dup 0) (ashift:SI (match_dup 1) (const_int 24))) @@ -3576,17 +3267,17 @@ move\\t%0,%z4\\n\\ (define_expand "extendqisi2" - [(set (match_operand:SI 0 "register_operand" "") - (sign_extend:SI (match_operand:QI 1 "nonimmediate_operand" "")))] + [(set (match_operand:SI 0 "register_operand") + (sign_extend:SI (match_operand:QI 1 "nonimmediate_operand")))] "" - " - if (ISA_HAS_SEB_SEH) - { - emit_insn (gen_extendqisi2_hw (operands[0], - force_reg (QImode, operands[1]))); - DONE; - } -") +{ + if (ISA_HAS_SEB_SEH) + { + emit_insn (gen_extendqisi2_hw (operands[0], + force_reg (QImode, operands[1]))); + DONE; + } +}) (define_insn "*extendqisi2" [(set (match_operand:SI 0 "register_operand" "=d") @@ -3595,8 +3286,8 @@ move\\t%0,%z4\\n\\ "#") (define_split - [(set (match_operand:SI 0 "register_operand" "") - (sign_extend:SI (match_operand:QI 1 "register_operand" "")))] + [(set (match_operand:SI 0 "register_operand") + (sign_extend:SI (match_operand:QI 1 "register_operand")))] "reload_completed" [(set (match_dup 0) (ashift:SI (match_dup 1) (const_int 24))) @@ -3616,13 +3307,13 @@ move\\t%0,%z4\\n\\ [(set (match_operand:SI 0 "register_operand" "=r") (sign_extend:SI (match_operand:QI 1 "register_operand" "r")))] "ISA_HAS_SEB_SEH" - "seb\\t%0,%1" + "seb\t%0,%1" [(set_attr "type" "arith") (set_attr "mode" "SI")]) (define_expand "extendqidi2" - [(set (match_operand:DI 0 "register_operand" "") - (sign_extend:DI (match_operand:QI 1 "nonimmediate_operand" "")))] + [(set (match_operand:DI 0 "register_operand") + (sign_extend:DI (match_operand:QI 1 "nonimmediate_operand")))] "TARGET_64BIT" "") @@ -3633,8 +3324,8 @@ move\\t%0,%z4\\n\\ "#") (define_split - [(set (match_operand:DI 0 "register_operand" "") - (sign_extend:DI (match_operand:QI 1 "register_operand" "")))] + [(set (match_operand:DI 0 "register_operand") + (sign_extend:DI (match_operand:QI 1 "register_operand")))] "TARGET_64BIT && reload_completed" [(set (match_dup 0) (ashift:DI (match_dup 1) (const_int 56))) @@ -3654,12 +3345,10 @@ move\\t%0,%z4\\n\\ [(set (match_operand:DF 0 "register_operand" "=f") (float_extend:DF (match_operand:SF 1 "register_operand" "f")))] "TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT" - "cvt.d.s\\t%0,%1" + "cvt.d.s\t%0,%1" [(set_attr "type" "fcvt") (set_attr "mode" "DF")]) - - ;; ;; .................... ;; @@ -3668,8 +3357,8 @@ move\\t%0,%z4\\n\\ ;; .................... (define_expand "fix_truncdfsi2" - [(set (match_operand:SI 0 "register_operand" "=f") - (fix:SI (match_operand:DF 1 "register_operand" "f")))] + [(set (match_operand:SI 0 "register_operand") + (fix:SI (match_operand:DF 1 "register_operand")))] "TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT" { if (!ISA_HAS_TRUNC_W) @@ -3693,18 +3382,19 @@ move\\t%0,%z4\\n\\ (fix:SI (match_operand:DF 1 "register_operand" "f"))) (clobber (match_scratch:DF 2 "=d"))] "TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT && !ISA_HAS_TRUNC_W" - { - if (set_nomacro) - return ".set\tmacro\n\ttrunc.w.d %0,%1,%2\n\t.set\tnomacro"; +{ + if (set_nomacro) + return ".set\tmacro\;trunc.w.d %0,%1,%2\;.set\tnomacro"; + else return "trunc.w.d %0,%1,%2"; - } +} [(set_attr "type" "fcvt") (set_attr "mode" "DF") (set_attr "length" "36")]) (define_expand "fix_truncsfsi2" - [(set (match_operand:SI 0 "register_operand" "=f") - (fix:SI (match_operand:SF 1 "register_operand" "f")))] + [(set (match_operand:SI 0 "register_operand") + (fix:SI (match_operand:SF 1 "register_operand")))] "TARGET_HARD_FLOAT" { if (!ISA_HAS_TRUNC_W) @@ -3728,23 +3418,16 @@ move\\t%0,%z4\\n\\ (fix:SI (match_operand:SF 1 "register_operand" "f"))) (clobber (match_scratch:SF 2 "=d"))] "TARGET_HARD_FLOAT && !ISA_HAS_TRUNC_W" - { - if (set_nomacro) - return ".set\tmacro\n\ttrunc.w.s %0,%1,%2\n\t.set\tnomacro"; +{ + if (set_nomacro) + return ".set\tmacro\;trunc.w.s %0,%1,%2\;.set\tnomacro"; + else return "trunc.w.s %0,%1,%2"; - } +} [(set_attr "type" "fcvt") (set_attr "mode" "DF") (set_attr "length" "36")]) -;;; ??? trunc.l.d is mentioned in the appendix of the 1993 r4000/r4600 manuals -;;; but not in the chapter that describes the FPU. It is not mentioned at all -;;; in the 1991 manuals. The r4000 at Cygnus does not have this instruction. - -;;; Deleting this means that we now need two libgcc2.a libraries. One for -;;; the 32 bit calling convention and one for the 64 bit calling convention. - -;;; If this is disabled, then fixuns_truncdfdi2 must be disabled also. (define_insn "fix_truncdfdi2" [(set (match_operand:DI 0 "register_operand" "=f") @@ -3756,9 +3439,6 @@ move\\t%0,%z4\\n\\ (set_attr "length" "4")]) -;;; ??? trunc.l.s is mentioned in the appendix of the 1993 r4000/r4600 manuals -;;; but not in the chapter that describes the FPU. It is not mentioned at all -;;; in the 1991 manuals. The r4000 at Cygnus does not have this instruction. (define_insn "fix_truncsfdi2" [(set (match_operand:DI 0 "register_operand" "=f") (fix:DI (match_operand:SF 1 "register_operand" "f")))] @@ -3773,7 +3453,7 @@ move\\t%0,%z4\\n\\ [(set (match_operand:DF 0 "register_operand" "=f") (float:DF (match_operand:SI 1 "register_operand" "f")))] "TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT" - "cvt.d.w\\t%0,%1" + "cvt.d.w\t%0,%1" [(set_attr "type" "fcvt") (set_attr "mode" "DF") (set_attr "length" "4")]) @@ -3783,7 +3463,7 @@ move\\t%0,%z4\\n\\ [(set (match_operand:DF 0 "register_operand" "=f") (float:DF (match_operand:DI 1 "register_operand" "f")))] "TARGET_HARD_FLOAT && TARGET_FLOAT64 && TARGET_DOUBLE_FLOAT" - "cvt.d.l\\t%0,%1" + "cvt.d.l\t%0,%1" [(set_attr "type" "fcvt") (set_attr "mode" "DF") (set_attr "length" "4")]) @@ -3793,7 +3473,7 @@ move\\t%0,%z4\\n\\ [(set (match_operand:SF 0 "register_operand" "=f") (float:SF (match_operand:SI 1 "register_operand" "f")))] "TARGET_HARD_FLOAT" - "cvt.s.w\\t%0,%1" + "cvt.s.w\t%0,%1" [(set_attr "type" "fcvt") (set_attr "mode" "SF") (set_attr "length" "4")]) @@ -3803,17 +3483,16 @@ move\\t%0,%z4\\n\\ [(set (match_operand:SF 0 "register_operand" "=f") (float:SF (match_operand:DI 1 "register_operand" "f")))] "TARGET_HARD_FLOAT && TARGET_FLOAT64 && TARGET_DOUBLE_FLOAT" - "cvt.s.l\\t%0,%1" + "cvt.s.l\t%0,%1" [(set_attr "type" "fcvt") (set_attr "mode" "SF") (set_attr "length" "4")]) (define_expand "fixuns_truncdfsi2" - [(set (match_operand:SI 0 "register_operand" "") - (unsigned_fix:SI (match_operand:DF 1 "register_operand" "")))] + [(set (match_operand:SI 0 "register_operand") + (unsigned_fix:SI (match_operand:DF 1 "register_operand")))] "TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT" - " { rtx reg1 = gen_reg_rtx (DFmode); rtx reg2 = gen_reg_rtx (DFmode); @@ -3824,7 +3503,7 @@ move\\t%0,%z4\\n\\ real_2expN (&offset, 31); - if (reg1) /* turn off complaints about unreached code */ + if (reg1) /* Turn off complaints about unreached code. */ { emit_move_insn (reg1, CONST_DOUBLE_FROM_REAL_VALUE (offset, DFmode)); do_pending_stack_adjust (); @@ -3847,19 +3526,18 @@ move\\t%0,%z4\\n\\ emit_label (label2); - /* allow REG_NOTES to be set on last insn (labels don't have enough + /* 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_truncdfdi2" - [(set (match_operand:DI 0 "register_operand" "") - (unsigned_fix:DI (match_operand:DF 1 "register_operand" "")))] + [(set (match_operand:DI 0 "register_operand") + (unsigned_fix:DI (match_operand:DF 1 "register_operand")))] "TARGET_HARD_FLOAT && TARGET_64BIT && TARGET_DOUBLE_FLOAT" - " { rtx reg1 = gen_reg_rtx (DFmode); rtx reg2 = gen_reg_rtx (DFmode); @@ -3870,42 +3548,38 @@ move\\t%0,%z4\\n\\ real_2expN (&offset, 63); - if (reg1) /* turn off complaints about unreached code */ - { - emit_move_insn (reg1, CONST_DOUBLE_FROM_REAL_VALUE (offset, DFmode)); - do_pending_stack_adjust (); + emit_move_insn (reg1, CONST_DOUBLE_FROM_REAL_VALUE (offset, DFmode)); + do_pending_stack_adjust (); - emit_insn (gen_cmpdf (operands[1], reg1)); - emit_jump_insn (gen_bge (label1)); + emit_insn (gen_cmpdf (operands[1], reg1)); + emit_jump_insn (gen_bge (label1)); - emit_insn (gen_fix_truncdfdi2 (operands[0], operands[1])); - emit_jump_insn (gen_rtx_SET (VOIDmode, pc_rtx, - gen_rtx_LABEL_REF (VOIDmode, label2))); - emit_barrier (); + emit_insn (gen_fix_truncdfdi2 (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_INT (BITMASK_HIGH)); - emit_insn (gen_ashldi3 (reg3, reg3, GEN_INT (32))); + emit_label (label1); + emit_move_insn (reg2, gen_rtx_MINUS (DFmode, operands[1], reg1)); + emit_move_insn (reg3, GEN_INT (BITMASK_HIGH)); + emit_insn (gen_ashldi3 (reg3, reg3, GEN_INT (32))); - emit_insn (gen_fix_truncdfdi2 (operands[0], reg2)); - emit_insn (gen_iordi3 (operands[0], operands[0], reg3)); + emit_insn (gen_fix_truncdfdi2 (operands[0], reg2)); + emit_insn (gen_iordi3 (operands[0], operands[0], reg3)); - emit_label (label2); + 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; - } -}") + /* 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" "")))] + [(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); @@ -3916,42 +3590,38 @@ move\\t%0,%z4\\n\\ real_2expN (&offset, 31); - if (reg1) /* turn off complaints about unreached code */ - { - emit_move_insn (reg1, CONST_DOUBLE_FROM_REAL_VALUE (offset, SFmode)); - do_pending_stack_adjust (); + emit_move_insn (reg1, CONST_DOUBLE_FROM_REAL_VALUE (offset, SFmode)); + do_pending_stack_adjust (); - emit_insn (gen_cmpsf (operands[1], reg1)); - emit_jump_insn (gen_bge (label1)); + 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_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_INT (trunc_int_for_mode - (BITMASK_HIGH, SImode))); + emit_label (label1); + emit_move_insn (reg2, gen_rtx_MINUS (SFmode, operands[1], reg1)); + emit_move_insn (reg3, GEN_INT (trunc_int_for_mode + (BITMASK_HIGH, SImode))); - emit_insn (gen_fix_truncsfsi2 (operands[0], reg2)); - emit_insn (gen_iorsi3 (operands[0], operands[0], reg3)); + emit_insn (gen_fix_truncsfsi2 (operands[0], reg2)); + emit_insn (gen_iorsi3 (operands[0], operands[0], reg3)); - emit_label (label2); + 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; - } -}") + /* 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_truncsfdi2" - [(set (match_operand:DI 0 "register_operand" "") - (unsigned_fix:DI (match_operand:SF 1 "register_operand" "")))] + [(set (match_operand:DI 0 "register_operand") + (unsigned_fix:DI (match_operand:SF 1 "register_operand")))] "TARGET_HARD_FLOAT && TARGET_64BIT && TARGET_DOUBLE_FLOAT" - " { rtx reg1 = gen_reg_rtx (SFmode); rtx reg2 = gen_reg_rtx (SFmode); @@ -3962,36 +3632,32 @@ move\\t%0,%z4\\n\\ real_2expN (&offset, 63); - if (reg1) /* turn off complaints about unreached code */ - { - emit_move_insn (reg1, CONST_DOUBLE_FROM_REAL_VALUE (offset, SFmode)); - do_pending_stack_adjust (); - - emit_insn (gen_cmpsf (operands[1], reg1)); - emit_jump_insn (gen_bge (label1)); + emit_move_insn (reg1, CONST_DOUBLE_FROM_REAL_VALUE (offset, SFmode)); + do_pending_stack_adjust (); - emit_insn (gen_fix_truncsfdi2 (operands[0], operands[1])); - emit_jump_insn (gen_rtx_SET (VOIDmode, pc_rtx, - gen_rtx_LABEL_REF (VOIDmode, label2))); - emit_barrier (); + emit_insn (gen_cmpsf (operands[1], reg1)); + emit_jump_insn (gen_bge (label1)); - emit_label (label1); - emit_move_insn (reg2, gen_rtx_MINUS (SFmode, operands[1], reg1)); - emit_move_insn (reg3, GEN_INT (BITMASK_HIGH)); - emit_insn (gen_ashldi3 (reg3, reg3, GEN_INT (32))); + emit_insn (gen_fix_truncsfdi2 (operands[0], operands[1])); + emit_jump_insn (gen_rtx_SET (VOIDmode, pc_rtx, + gen_rtx_LABEL_REF (VOIDmode, label2))); + emit_barrier (); - emit_insn (gen_fix_truncsfdi2 (operands[0], reg2)); - emit_insn (gen_iordi3 (operands[0], operands[0], reg3)); + emit_label (label1); + emit_move_insn (reg2, gen_rtx_MINUS (SFmode, operands[1], reg1)); + emit_move_insn (reg3, GEN_INT (BITMASK_HIGH)); + emit_insn (gen_ashldi3 (reg3, reg3, GEN_INT (32))); - emit_label (label2); + emit_insn (gen_fix_truncsfdi2 (operands[0], reg2)); + emit_insn (gen_iordi3 (operands[0], operands[0], reg3)); - /* 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; - } -}") + 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; +}) ;; ;; .................... @@ -4003,49 +3669,49 @@ move\\t%0,%z4\\n\\ ;; Bit field extract patterns which use lwl/lwr or ldl/ldr. (define_expand "extv" - [(set (match_operand 0 "register_operand" "") - (sign_extract (match_operand:QI 1 "memory_operand" "") - (match_operand 2 "immediate_operand" "") - (match_operand 3 "immediate_operand" "")))] + [(set (match_operand 0 "register_operand") + (sign_extract (match_operand:QI 1 "memory_operand") + (match_operand 2 "immediate_operand") + (match_operand 3 "immediate_operand")))] "!TARGET_MIPS16" - { - if (mips_expand_unaligned_load (operands[0], operands[1], - INTVAL (operands[2]), - INTVAL (operands[3]))) - DONE; - else - FAIL; - }) +{ + if (mips_expand_unaligned_load (operands[0], operands[1], + INTVAL (operands[2]), + INTVAL (operands[3]))) + DONE; + else + FAIL; +}) (define_expand "extzv" - [(set (match_operand 0 "register_operand" "") - (zero_extract (match_operand:QI 1 "memory_operand" "") - (match_operand 2 "immediate_operand" "") - (match_operand 3 "immediate_operand" "")))] + [(set (match_operand 0 "register_operand") + (zero_extract (match_operand:QI 1 "memory_operand") + (match_operand 2 "immediate_operand") + (match_operand 3 "immediate_operand")))] "!TARGET_MIPS16" - { - if (mips_expand_unaligned_load (operands[0], operands[1], - INTVAL (operands[2]), - INTVAL (operands[3]))) - DONE; - else - FAIL; - }) +{ + if (mips_expand_unaligned_load (operands[0], operands[1], + INTVAL (operands[2]), + INTVAL (operands[3]))) + DONE; + else + FAIL; +}) (define_expand "insv" - [(set (zero_extract (match_operand:QI 0 "memory_operand" "") - (match_operand 1 "immediate_operand" "") - (match_operand 2 "immediate_operand" "")) - (match_operand 3 "reg_or_0_operand" ""))] + [(set (zero_extract (match_operand:QI 0 "memory_operand") + (match_operand 1 "immediate_operand") + (match_operand 2 "immediate_operand")) + (match_operand 3 "reg_or_0_operand"))] "!TARGET_MIPS16" - { - if (mips_expand_unaligned_store (operands[0], operands[3], - INTVAL (operands[1]), - INTVAL (operands[2]))) - DONE; - else - FAIL; - }) +{ + if (mips_expand_unaligned_store (operands[0], operands[3], + INTVAL (operands[1]), + INTVAL (operands[2]))) + DONE; + else + FAIL; +}) ;; Unaligned word moves generated by the bit field patterns. ;; @@ -4054,11 +3720,15 @@ move\\t%0,%z4\\n\\ ;; refers to just the first or the last byte (depending on endianness). ;; We therefore use two memory operands to each instruction, one to ;; describe the rtl effect and one to use in the assembly output. +;; +;; Operands 0 and 1 are the rtl-level target and source respectively. +;; This allows us to use the standard length calculations for the "load" +;; and "store" type attributes. (define_insn "mov_lwl" [(set (match_operand:SI 0 "register_operand" "=d") - (unspec:SI [(match_operand:BLK 1 "general_operand" "m") - (match_operand:QI 2 "general_operand" "m")] + (unspec:SI [(match_operand:BLK 1 "memory_operand" "m") + (match_operand:QI 2 "memory_operand" "m")] UNSPEC_LWL))] "!TARGET_MIPS16" "lwl\t%0,%2" @@ -4068,8 +3738,8 @@ move\\t%0,%z4\\n\\ (define_insn "mov_lwr" [(set (match_operand:SI 0 "register_operand" "=d") - (unspec:SI [(match_operand:BLK 1 "general_operand" "m") - (match_operand:QI 2 "general_operand" "m") + (unspec:SI [(match_operand:BLK 1 "memory_operand" "m") + (match_operand:QI 2 "memory_operand" "m") (match_operand:SI 3 "register_operand" "0")] UNSPEC_LWR))] "!TARGET_MIPS16" @@ -4081,7 +3751,7 @@ move\\t%0,%z4\\n\\ (define_insn "mov_swl" [(set (match_operand:BLK 0 "memory_operand" "=m") (unspec:BLK [(match_operand:SI 1 "reg_or_0_operand" "dJ") - (match_operand:QI 2 "general_operand" "m")] + (match_operand:QI 2 "memory_operand" "m")] UNSPEC_SWL))] "!TARGET_MIPS16" "swl\t%z1,%2" @@ -4091,7 +3761,7 @@ move\\t%0,%z4\\n\\ (define_insn "mov_swr" [(set (match_operand:BLK 0 "memory_operand" "+m") (unspec:BLK [(match_operand:SI 1 "reg_or_0_operand" "dJ") - (match_operand:QI 2 "general_operand" "m") + (match_operand:QI 2 "memory_operand" "m") (match_dup 0)] UNSPEC_SWR))] "!TARGET_MIPS16" @@ -4102,8 +3772,8 @@ move\\t%0,%z4\\n\\ (define_insn "mov_ldl" [(set (match_operand:DI 0 "register_operand" "=d") - (unspec:DI [(match_operand:BLK 1 "general_operand" "m") - (match_operand:QI 2 "general_operand" "m")] + (unspec:DI [(match_operand:BLK 1 "memory_operand" "m") + (match_operand:QI 2 "memory_operand" "m")] UNSPEC_LDL))] "TARGET_64BIT && !TARGET_MIPS16" "ldl\t%0,%2" @@ -4112,8 +3782,8 @@ move\\t%0,%z4\\n\\ (define_insn "mov_ldr" [(set (match_operand:DI 0 "register_operand" "=d") - (unspec:DI [(match_operand:BLK 1 "general_operand" "m") - (match_operand:QI 2 "general_operand" "m") + (unspec:DI [(match_operand:BLK 1 "memory_operand" "m") + (match_operand:QI 2 "memory_operand" "m") (match_operand:DI 3 "register_operand" "0")] UNSPEC_LDR))] "TARGET_64BIT && !TARGET_MIPS16" @@ -4125,7 +3795,7 @@ move\\t%0,%z4\\n\\ (define_insn "mov_sdl" [(set (match_operand:BLK 0 "memory_operand" "=m") (unspec:BLK [(match_operand:DI 1 "reg_or_0_operand" "dJ") - (match_operand:QI 2 "general_operand" "m")] + (match_operand:QI 2 "memory_operand" "m")] UNSPEC_SDL))] "TARGET_64BIT && !TARGET_MIPS16" "sdl\t%z1,%2" @@ -4135,7 +3805,7 @@ move\\t%0,%z4\\n\\ (define_insn "mov_sdr" [(set (match_operand:BLK 0 "memory_operand" "+m") (unspec:BLK [(match_operand:DI 1 "reg_or_0_operand" "dJ") - (match_operand:QI 2 "general_operand" "m") + (match_operand:QI 2 "memory_operand" "m") (match_dup 0)] UNSPEC_SDR))] "TARGET_64BIT && !TARGET_MIPS16" @@ -4143,46 +3813,247 @@ move\\t%0,%z4\\n\\ [(set_attr "type" "store") (set_attr "mode" "DI")]) +;; An instruction to calculate the high part of a 64-bit SYMBOL_GENERAL. +;; The required value is: +;; +;; (%highest(op1) << 48) + (%higher(op1) << 32) + (%hi(op1) << 16) +;; +;; which translates to: +;; +;; lui op0,%highest(op1) +;; daddiu op0,op0,%higher(op1) +;; dsll op0,op0,16 +;; daddiu op0,op0,%hi(op1) +;; dsll op0,op0,16 +(define_insn_and_split "*lea_high64" + [(set (match_operand:DI 0 "register_operand" "=d") + (high:DI (match_operand:DI 1 "general_symbolic_operand" "")))] + "TARGET_EXPLICIT_RELOCS && ABI_HAS_64BIT_SYMBOLS" + "#" + "&& reload_completed" + [(set (match_dup 0) (high:DI (match_dup 2))) + (set (match_dup 0) (lo_sum:DI (match_dup 0) (match_dup 2))) + (set (match_dup 0) (ashift:DI (match_dup 0) (const_int 16))) + (set (match_dup 0) (lo_sum:DI (match_dup 0) (match_dup 3))) + (set (match_dup 0) (ashift:DI (match_dup 0) (const_int 16)))] +{ + operands[2] = mips_unspec_address (operands[1], SYMBOL_64_HIGH); + operands[3] = mips_unspec_address (operands[1], SYMBOL_64_MID); +} + [(set_attr "length" "20")]) + +;; On most targets, the expansion of (lo_sum (high X) X) for a 64-bit +;; SYMBOL_GENERAL X will take 6 cycles. This next pattern allows combine +;; to merge the HIGH and LO_SUM parts of a move if the HIGH part is only +;; used once. We can then use the sequence: +;; +;; lui op0,%highest(op1) +;; lui op2,%hi(op1) +;; daddiu op0,op0,%higher(op1) +;; daddiu op2,op2,%lo(op1) +;; dsll32 op0,op0,0 +;; daddu op0,op0,op2 +;; +;; which takes 4 cycles on most superscalar targets. +(define_insn_and_split "*lea64" + [(set (match_operand:DI 0 "register_operand" "=d") + (match_operand:DI 1 "general_symbolic_operand" "")) + (clobber (match_scratch:DI 2 "=&d"))] + "TARGET_EXPLICIT_RELOCS && ABI_HAS_64BIT_SYMBOLS && cse_not_expected" + "#" + "&& reload_completed" + [(set (match_dup 0) (high:DI (match_dup 3))) + (set (match_dup 2) (high:DI (match_dup 4))) + (set (match_dup 0) (lo_sum:DI (match_dup 0) (match_dup 3))) + (set (match_dup 2) (lo_sum:DI (match_dup 2) (match_dup 4))) + (set (match_dup 0) (ashift:DI (match_dup 0) (const_int 32))) + (set (match_dup 0) (plus:DI (match_dup 0) (match_dup 2)))] +{ + operands[3] = mips_unspec_address (operands[1], SYMBOL_64_HIGH); + operands[4] = mips_unspec_address (operands[1], SYMBOL_64_LOW); +} + [(set_attr "length" "24")]) -;; Instructions for loading a relocation expression using "lui". +;; Insns to fetch a global symbol from a big GOT. -(define_insn "luisi" - [(set (match_operand:SI 0 "register_operand" "=r") - (unspec:SI [(match_operand 1 "const_arith_operand" "")] UNSPEC_HIGH))] - "" - "lui\t%0,%1" - [(set_attr "type" "arith")]) +(define_insn_and_split "*xgot_hisi" + [(set (match_operand:SI 0 "register_operand" "=d") + (high:SI (match_operand:SI 1 "global_got_operand" "")))] + "TARGET_EXPLICIT_RELOCS && TARGET_XGOT" + "#" + "&& reload_completed" + [(set (match_dup 0) (high:SI (match_dup 2))) + (set (match_dup 0) (plus:SI (match_dup 0) (match_dup 3)))] +{ + operands[2] = mips_unspec_address (operands[1], SYMBOL_GOTOFF_GLOBAL); + operands[3] = pic_offset_table_rtx; +} + [(set_attr "got" "xgot_high")]) -(define_insn "luidi" - [(set (match_operand:DI 0 "register_operand" "=r") - (unspec:DI [(match_operand 1 "const_arith_operand" "")] UNSPEC_HIGH))] - "TARGET_64BIT" - "lui\t%0,%1" - [(set_attr "type" "arith")]) +(define_insn_and_split "*xgot_losi" + [(set (match_operand:SI 0 "register_operand" "=d") + (lo_sum:SI (match_operand:SI 1 "register_operand" "d") + (match_operand:SI 2 "global_got_operand" "")))] + "TARGET_EXPLICIT_RELOCS && TARGET_XGOT" + "#" + "&& reload_completed" + [(set (match_dup 0) + (unspec:SI [(match_dup 1) (match_dup 3)] UNSPEC_LOAD_GOT))] + { operands[3] = mips_unspec_address (operands[2], SYMBOL_GOTOFF_GLOBAL); } + [(set_attr "got" "load")]) + +(define_insn_and_split "*xgot_hidi" + [(set (match_operand:DI 0 "register_operand" "=d") + (high:DI (match_operand:DI 1 "global_got_operand" "")))] + "TARGET_EXPLICIT_RELOCS && TARGET_XGOT" + "#" + "&& reload_completed" + [(set (match_dup 0) (high:DI (match_dup 2))) + (set (match_dup 0) (plus:DI (match_dup 0) (match_dup 3)))] +{ + operands[2] = mips_unspec_address (operands[1], SYMBOL_GOTOFF_GLOBAL); + operands[3] = pic_offset_table_rtx; +} + [(set_attr "got" "xgot_high")]) + +(define_insn_and_split "*xgot_lodi" + [(set (match_operand:DI 0 "register_operand" "=d") + (lo_sum:DI (match_operand:DI 1 "register_operand" "d") + (match_operand:DI 2 "global_got_operand" "")))] + "TARGET_EXPLICIT_RELOCS && TARGET_XGOT" + "#" + "&& reload_completed" + [(set (match_dup 0) + (unspec:DI [(match_dup 1) (match_dup 3)] UNSPEC_LOAD_GOT))] + { operands[3] = mips_unspec_address (operands[2], SYMBOL_GOTOFF_GLOBAL); } + [(set_attr "got" "load")]) + +;; Insns to fetch a global symbol from a normal GOT. + +(define_insn_and_split "*got_dispsi" + [(set (match_operand:SI 0 "register_operand" "=d") + (match_operand:SI 1 "global_got_operand" ""))] + "TARGET_EXPLICIT_RELOCS && !TARGET_XGOT" + "#" + "&& reload_completed" + [(set (match_dup 0) + (unspec:SI [(match_dup 2) (match_dup 3)] UNSPEC_LOAD_GOT))] +{ + operands[2] = pic_offset_table_rtx; + operands[3] = mips_unspec_address (operands[1], SYMBOL_GOTOFF_GLOBAL); +} + [(set_attr "got" "load")]) + +(define_insn_and_split "*got_dispdi" + [(set (match_operand:DI 0 "register_operand" "=d") + (match_operand:DI 1 "global_got_operand" ""))] + "TARGET_EXPLICIT_RELOCS && !TARGET_XGOT" + "#" + "&& reload_completed" + [(set (match_dup 0) + (unspec:DI [(match_dup 2) (match_dup 3)] UNSPEC_LOAD_GOT))] +{ + operands[2] = pic_offset_table_rtx; + operands[3] = mips_unspec_address (operands[1], SYMBOL_GOTOFF_GLOBAL); +} + [(set_attr "got" "load")]) + +;; Insns for loading the high part of a local symbol. + +(define_insn_and_split "*got_pagesi" + [(set (match_operand:SI 0 "register_operand" "=d") + (high:SI (match_operand:SI 1 "local_got_operand" "")))] + "TARGET_EXPLICIT_RELOCS" + "#" + "&& reload_completed" + [(set (match_dup 0) + (unspec:SI [(match_dup 2) (match_dup 3)] UNSPEC_LOAD_GOT))] +{ + operands[2] = pic_offset_table_rtx; + operands[3] = mips_unspec_address (operands[1], SYMBOL_GOTOFF_PAGE); +} + [(set_attr "got" "load")]) +(define_insn_and_split "*got_pagedi" + [(set (match_operand:DI 0 "register_operand" "=d") + (high:DI (match_operand:DI 1 "local_got_operand" "")))] + "TARGET_EXPLICIT_RELOCS" + "#" + "&& reload_completed" + [(set (match_dup 0) + (unspec:DI [(match_dup 2) (match_dup 3)] UNSPEC_LOAD_GOT))] +{ + operands[2] = pic_offset_table_rtx; + operands[3] = mips_unspec_address (operands[1], SYMBOL_GOTOFF_PAGE); +} + [(set_attr "got" "load")]) + +;; Lower-level instructions for loading an address from the GOT. +;; We could use MEMs, but an unspec gives more optimization +;; opportunities. + +(define_insn "*load_gotsi" + [(set (match_operand:SI 0 "register_operand" "=d") + (unspec:SI [(match_operand:SI 1 "register_operand" "d") + (match_operand:SI 2 "immediate_operand" "")] + UNSPEC_LOAD_GOT))] + "TARGET_ABICALLS" + "lw\t%0,%R2(%1)" + [(set_attr "type" "load") + (set_attr "length" "4")]) + +(define_insn "*load_gotdi" + [(set (match_operand:DI 0 "register_operand" "=d") + (unspec:DI [(match_operand:DI 1 "register_operand" "d") + (match_operand:DI 2 "immediate_operand" "")] + UNSPEC_LOAD_GOT))] + "TARGET_ABICALLS" + "ld\t%0,%R2(%1)" + [(set_attr "type" "load") + (set_attr "length" "4")]) ;; Instructions for adding the low 16 bits of an address to a register. ;; Operand 2 is the address: print_operand works out which relocation ;; should be applied. -(define_insn "lowsi" - [(set (match_operand:SI 0 "register_operand" "=r") - (lo_sum:SI (match_operand:SI 1 "register_operand" "r") +(define_insn "*lowsi" + [(set (match_operand:SI 0 "register_operand" "=d") + (lo_sum:SI (match_operand:SI 1 "register_operand" "d") (match_operand:SI 2 "immediate_operand" "")))] "!TARGET_MIPS16" - "addiu\\t%0,%1,%R2" + "addiu\t%0,%1,%R2" [(set_attr "type" "arith") (set_attr "mode" "SI")]) -(define_insn "lowdi" - [(set (match_operand:DI 0 "register_operand" "=r") - (lo_sum:DI (match_operand:DI 1 "register_operand" "r") +(define_insn "*lowdi" + [(set (match_operand:DI 0 "register_operand" "=d") + (lo_sum:DI (match_operand:DI 1 "register_operand" "d") (match_operand:DI 2 "immediate_operand" "")))] "!TARGET_MIPS16 && TARGET_64BIT" - "daddiu\\t%0,%1,%R2" + "daddiu\t%0,%1,%R2" [(set_attr "type" "arith") (set_attr "mode" "DI")]) +(define_insn "*lowsi_mips16" + [(set (match_operand:SI 0 "register_operand" "=d") + (lo_sum:SI (match_operand:SI 1 "register_operand" "0") + (match_operand:SI 2 "immediate_operand" "")))] + "TARGET_MIPS16" + "addiu\t%0,%R2" + [(set_attr "type" "arith") + (set_attr "mode" "SI") + (set_attr "length" "8")]) + +(define_insn "*lowdi_mips16" + [(set (match_operand:DI 0 "register_operand" "=d") + (lo_sum:DI (match_operand:DI 1 "register_operand" "0") + (match_operand:DI 2 "immediate_operand" "")))] + "TARGET_MIPS16 && TARGET_64BIT" + "daddiu\t%0,%R2" + [(set_attr "type" "arith") + (set_attr "mode" "DI") + (set_attr "length" "8")]) + ;; 64-bit integer moves ;; Unlike most other insns, the move insns can't be split with @@ -4190,104 +4061,81 @@ move\\t%0,%z4\\n\\ ;; the compiler, have memoized the insn number already. (define_expand "movdi" - [(set (match_operand:DI 0 "nonimmediate_operand" "") - (match_operand:DI 1 "" ""))] + [(set (match_operand:DI 0 "") + (match_operand:DI 1 ""))] "" - " { if (mips_legitimize_move (DImode, operands[0], operands[1])) DONE; - - /* If we are generating embedded PIC code, and we are referring to a - symbol in the .text section, we must use an offset from the start - of the function. */ - if (TARGET_EMBEDDED_PIC - && (GET_CODE (operands[1]) == LABEL_REF - || (GET_CODE (operands[1]) == SYMBOL_REF - && ! SYMBOL_REF_FLAG (operands[1])))) - { - rtx temp; - - temp = embedded_pic_offset (operands[1]); - temp = gen_rtx_PLUS (Pmode, embedded_pic_fnaddr_reg (), - force_reg (DImode, temp)); - emit_move_insn (operands[0], force_reg (DImode, temp)); - DONE; - } -}") +}) ;; For mips16, we need a special case to handle storing $31 into ;; memory, since we don't have a constraint to match $31. This ;; instruction can be generated by save_restore_insns. (define_insn "" - [(set (match_operand:DI 0 "memory_operand" "=m") + [(set (match_operand:DI 0 "stack_operand" "=m") (reg:DI 31))] "TARGET_MIPS16 && TARGET_64BIT" "sd\t$31,%0" [(set_attr "type" "store") (set_attr "mode" "DI")]) -(define_insn "movdi_internal" - [(set (match_operand:DI 0 "nonimmediate_operand" "=d,d,d,m,*x,*d,*x,*B*C*D,*B*C*D,*d,*m") - (match_operand:DI 1 "general_operand" "d,iF,m,d,J,*x,*d,*d,*m,*B*C*D,*B*C*D"))] +(define_insn "*movdi_32bit" + [(set (match_operand:DI 0 "nonimmediate_operand" "=d,d,d,m,*x,*d,*B*C*D,*B*C*D,*d,*m") + (match_operand:DI 1 "move_operand" "d,i,m,d,*J*d,*x,*d,*m,*B*C*D,*B*C*D"))] "!TARGET_64BIT && !TARGET_MIPS16 && (register_operand (operands[0], DImode) - || register_operand (operands[1], DImode) - || (GET_CODE (operands[1]) == CONST_INT && INTVAL (operands[1]) == 0) - || operands[1] == CONST0_RTX (DImode))" + || reg_or_0_operand (operands[1], DImode))" { return mips_output_move (operands[0], operands[1]); } - [(set_attr "type" "move,arith,load,store,hilo,hilo,hilo,xfer,load,xfer,store") + [(set_attr "type" "arith,arith,load,store,mthilo,mfhilo,xfer,load,xfer,store") (set_attr "mode" "DI") - (set_attr "length" "8,16,*,*,8,8,8,8,*,8,*")]) + (set_attr "length" "8,16,*,*,8,8,8,*,8,*")]) -(define_insn "" +(define_insn "*movdi_32bit_mips16" [(set (match_operand:DI 0 "nonimmediate_operand" "=d,y,d,d,d,d,m,*d") - (match_operand:DI 1 "general_operand" "d,d,y,K,N,m,d,*x"))] + (match_operand:DI 1 "move_operand" "d,d,y,K,N,m,d,*x"))] "!TARGET_64BIT && TARGET_MIPS16 && (register_operand (operands[0], DImode) || register_operand (operands[1], DImode))" { return mips_output_move (operands[0], operands[1]); } - [(set_attr "type" "move,move,move,arith,arith,load,store,hilo") + [(set_attr "type" "arith,arith,arith,arith,arith,load,store,mfhilo") (set_attr "mode" "DI") (set_attr "length" "8,8,8,8,12,*,*,8")]) -(define_insn "movdi_internal2" - [(set (match_operand:DI 0 "nonimmediate_operand" "=d,d,e,d,m,*f,*f,*f,*d,*m,*x,*d,*x,*B*C*D,*B*C*D,*d,*m") - (match_operand:DI 1 "move_operand" "d,U,T,m,dJ,*f,*d*J,*m,*f,*f,*J,*x,*d,*d,*m,*B*C*D,*B*C*D"))] +(define_insn "*movdi_64bit" + [(set (match_operand:DI 0 "nonimmediate_operand" "=d,d,e,d,m,*f,*f,*f,*d,*m,*x,*B*C*D,*B*C*D,*d,*m") + (match_operand:DI 1 "move_operand" "d,U,T,m,dJ,*f,*d*J,*m,*f,*f,*J*d,*d,*m,*B*C*D,*B*C*D"))] "TARGET_64BIT && !TARGET_MIPS16 && (register_operand (operands[0], DImode) - || register_operand (operands[1], DImode) - || (GET_CODE (operands[1]) == CONST_INT && INTVAL (operands[1]) == 0) - || operands[1] == CONST0_RTX (DImode))" + || reg_or_0_operand (operands[1], DImode))" { return mips_output_move (operands[0], operands[1]); } - [(set_attr "type" "move,const,const,load,store,move,xfer,load,xfer,store,hilo,hilo,hilo,xfer,load,xfer,store") + [(set_attr "type" "arith,const,const,load,store,fmove,xfer,fpload,xfer,fpstore,mthilo,xfer,load,xfer,store") (set_attr "mode" "DI") - (set_attr "length" "4,*,*,*,*,4,4,*,4,*,4,4,4,8,*,8,*")]) + (set_attr "length" "4,*,*,*,*,4,4,*,4,*,4,8,*,8,*")]) -(define_insn "*movdi_internal2_mips16" - [(set (match_operand:DI 0 "nonimmediate_operand" "=d,y,d,d,d,d,d,m,*d") - (match_operand:DI 1 "move_operand" "d,d,y,K,N,U,m,d,*x"))] +(define_insn "*movdi_64bit_mips16" + [(set (match_operand:DI 0 "nonimmediate_operand" "=d,y,d,d,d,d,d,m") + (match_operand:DI 1 "move_operand" "d,d,y,K,N,U,m,d"))] "TARGET_64BIT && TARGET_MIPS16 && (register_operand (operands[0], DImode) || register_operand (operands[1], DImode))" { return mips_output_move (operands[0], operands[1]); } - [(set_attr "type" "move,move,move,arith,arith,const,load,store,hilo") + [(set_attr "type" "arith,arith,arith,arith,arith,const,load,store") (set_attr "mode" "DI") (set_attr_alternative "length" [(const_int 4) (const_int 4) (const_int 4) - (if_then_else (match_operand:VOID 1 "m16_uimm8_1" "") + (if_then_else (match_operand:VOID 1 "m16_uimm8_1") (const_int 4) (const_int 8)) - (if_then_else (match_operand:VOID 1 "m16_nuimm8_1" "") + (if_then_else (match_operand:VOID 1 "m16_nuimm8_1") (const_int 8) (const_int 12)) (const_string "*") (const_string "*") - (const_string "*") - (const_int 4)])]) + (const_string "*")])]) ;; On the mips16, we can split ld $r,N($r) into an add and a load, @@ -4295,9 +4143,9 @@ move\\t%0,%z4\\n\\ ;; load are 2 2 byte instructions. (define_split - [(set (match_operand:DI 0 "register_operand" "") + [(set (match_operand:DI 0 "register_operand") (mem:DI (plus:DI (match_dup 0) - (match_operand:DI 1 "const_int_operand" ""))))] + (match_operand:DI 1 "const_int_operand"))))] "TARGET_64BIT && TARGET_MIPS16 && reload_completed && !TARGET_DEBUG_D_MODE && GET_CODE (operands[0]) == REG @@ -4312,12 +4160,11 @@ move\\t%0,%z4\\n\\ && (INTVAL (operands[1]) & 7) != 0))" [(set (match_dup 0) (plus:DI (match_dup 0) (match_dup 1))) (set (match_dup 0) (mem:DI (plus:DI (match_dup 0) (match_dup 2))))] - " { HOST_WIDE_INT val = INTVAL (operands[1]); if (val < 0) - operands[2] = GEN_INT (0); + operands[2] = const0_rtx; else if (val >= 32 * 8) { int off = val & 7; @@ -4332,7 +4179,7 @@ move\\t%0,%z4\\n\\ operands[1] = GEN_INT (off); operands[2] = GEN_INT (val - off); } -}") +}) ;; 32-bit Integer moves @@ -4341,99 +4188,69 @@ move\\t%0,%z4\\n\\ ;; the compiler, have memoized the insn number already. (define_expand "movsi" - [(set (match_operand:SI 0 "nonimmediate_operand" "") - (match_operand:SI 1 "" ""))] + [(set (match_operand:SI 0 "") + (match_operand:SI 1 ""))] "" - " { if (mips_legitimize_move (SImode, operands[0], operands[1])) DONE; +}) - /* If we are generating embedded PIC code, and we are referring to a - symbol in the .text section, we must use an offset from the start - of the function. */ - if (TARGET_EMBEDDED_PIC - && (GET_CODE (operands[1]) == LABEL_REF - || (GET_CODE (operands[1]) == SYMBOL_REF - && ! SYMBOL_REF_FLAG (operands[1])))) - { - rtx temp; - - temp = embedded_pic_offset (operands[1]); - temp = gen_rtx_PLUS (Pmode, embedded_pic_fnaddr_reg (), - force_reg (SImode, temp)); - emit_move_insn (operands[0], force_reg (SImode, temp)); - DONE; - } -}") - -;; We can only store $ra directly into a small sp offset. Should the -;; offset be too wide, non-constant or not sp-based, leave it up to -;; reload to choose a scratch register. +;; We can only store $ra directly into a small sp offset. (define_insn "" - [(set (mem:SI (plus:SI (reg:SI 29) - (match_operand:SI 0 "small_int" "n"))) + [(set (match_operand:SI 0 "stack_operand" "=m") (reg:SI 31))] "TARGET_MIPS16" - "sw\\t$31,%0($sp)" + "sw\t$31,%0" [(set_attr "type" "store") - (set_attr "mode" "SI") - (set_attr_alternative - "length" - [(if_then_else - (lt (symbol_ref "(unsigned HOST_WIDE_INT) INTVAL (operands[0])") - (const_int 1024)) - (const_int 4) - (const_int 8))])]) + (set_attr "mode" "SI")]) ;; The difference between these two is whether or not ints are allowed ;; in FP registers (off by default, use -mdebugh to enable). -(define_insn "movsi_internal" - [(set (match_operand:SI 0 "nonimmediate_operand" "=d,d,e,d,m,*f,*f,*f,*d,*m,*d,*z,*x,*d,*x,*B*C*D,*B*C*D,*d,*m") - (match_operand:SI 1 "move_operand" "d,U,T,m,dJ,*f,*d*J,*m,*f,*f,*z,*d,J,*x,*d,*d,*m,*B*C*D,*B*C*D"))] +(define_insn "*movsi_internal" + [(set (match_operand:SI 0 "nonimmediate_operand" "=d,d,e,d,m,*f,*f,*f,*d,*m,*d,*z,*x,*B*C*D,*B*C*D,*d,*m") + (match_operand:SI 1 "move_operand" "d,U,T,m,dJ,*f,*d*J,*m,*f,*f,*z,*d,*J*d,*d,*m,*B*C*D,*B*C*D"))] "!TARGET_MIPS16 && (register_operand (operands[0], SImode) - || register_operand (operands[1], SImode) - || (GET_CODE (operands[1]) == CONST_INT && INTVAL (operands[1]) == 0))" + || reg_or_0_operand (operands[1], SImode))" { return mips_output_move (operands[0], operands[1]); } - [(set_attr "type" "move,const,const,load,store,move,xfer,load,xfer,store,xfer,xfer,hilo,hilo,hilo,xfer,load,xfer,store") + [(set_attr "type" "arith,const,const,load,store,fmove,xfer,fpload,xfer,fpstore,xfer,xfer,mthilo,xfer,load,xfer,store") (set_attr "mode" "SI") - (set_attr "length" "4,*,*,*,*,4,4,*,4,*,4,4,4,4,4,4,*,4,*")]) + (set_attr "length" "4,*,*,*,*,4,4,*,4,*,4,4,4,4,*,4,*")]) -(define_insn "" - [(set (match_operand:SI 0 "nonimmediate_operand" "=d,y,d,d,d,d,d,m,*d") - (match_operand:SI 1 "move_operand" "d,d,y,K,N,U,m,d,*x"))] +(define_insn "*movsi_mips16" + [(set (match_operand:SI 0 "nonimmediate_operand" "=d,y,d,d,d,d,d,m") + (match_operand:SI 1 "move_operand" "d,d,y,K,N,U,m,d"))] "TARGET_MIPS16 && (register_operand (operands[0], SImode) || register_operand (operands[1], SImode))" { return mips_output_move (operands[0], operands[1]); } - [(set_attr "type" "move,move,move,arith,arith,const,load,store,hilo") + [(set_attr "type" "arith,arith,arith,arith,arith,const,load,store") (set_attr "mode" "SI") (set_attr_alternative "length" [(const_int 4) (const_int 4) (const_int 4) - (if_then_else (match_operand:VOID 1 "m16_uimm8_1" "") + (if_then_else (match_operand:VOID 1 "m16_uimm8_1") (const_int 4) (const_int 8)) - (if_then_else (match_operand:VOID 1 "m16_nuimm8_1" "") + (if_then_else (match_operand:VOID 1 "m16_nuimm8_1") (const_int 8) (const_int 12)) (const_string "*") (const_string "*") - (const_string "*") - (const_int 4)])]) + (const_string "*")])]) ;; On the mips16, we can split lw $r,N($r) into an add and a load, ;; when the original load is a 4 byte instruction but the add and the ;; load are 2 2 byte instructions. (define_split - [(set (match_operand:SI 0 "register_operand" "") + [(set (match_operand:SI 0 "register_operand") (mem:SI (plus:SI (match_dup 0) - (match_operand:SI 1 "const_int_operand" ""))))] + (match_operand:SI 1 "const_int_operand"))))] "TARGET_MIPS16 && reload_completed && !TARGET_DEBUG_D_MODE && GET_CODE (operands[0]) == REG && M16_REG_P (REGNO (operands[0])) @@ -4447,12 +4264,11 @@ move\\t%0,%z4\\n\\ && (INTVAL (operands[1]) & 3) != 0))" [(set (match_dup 0) (plus:SI (match_dup 0) (match_dup 1))) (set (match_dup 0) (mem:SI (plus:SI (match_dup 0) (match_dup 2))))] - " { HOST_WIDE_INT val = INTVAL (operands[1]); if (val < 0) - operands[2] = GEN_INT (0); + operands[2] = const0_rtx; else if (val >= 32 * 4) { int off = val & 3; @@ -4467,15 +4283,15 @@ move\\t%0,%z4\\n\\ operands[1] = GEN_INT (off); operands[2] = GEN_INT (val - off); } -}") +}) ;; On the mips16, we can split a load of certain constants into a load ;; and an add. This turns a 4 byte instruction into 2 2 byte ;; instructions. (define_split - [(set (match_operand:SI 0 "register_operand" "") - (match_operand:SI 1 "const_int_operand" ""))] + [(set (match_operand:SI 0 "register_operand") + (match_operand:SI 1 "const_int_operand"))] "TARGET_MIPS16 && reload_completed && !TARGET_DEBUG_D_MODE && GET_CODE (operands[0]) == REG && M16_REG_P (REGNO (operands[0])) @@ -4484,32 +4300,12 @@ move\\t%0,%z4\\n\\ && INTVAL (operands[1]) <= 0xff + 0x7f" [(set (match_dup 0) (match_dup 1)) (set (match_dup 0) (plus:SI (match_dup 0) (match_dup 2)))] - " { int val = INTVAL (operands[1]); operands[1] = GEN_INT (0xff); operands[2] = GEN_INT (val - 0xff); -}") - -;; On the mips16, we can split a load of a negative constant into a -;; load and a neg. That's what mips_output_move will generate anyhow. - -(define_split - [(set (match_operand:SI 0 "register_operand" "") - (match_operand:SI 1 "const_int_operand" ""))] - "TARGET_MIPS16 && reload_completed && !TARGET_DEBUG_D_MODE - && GET_CODE (operands[0]) == REG - && M16_REG_P (REGNO (operands[0])) - && GET_CODE (operands[1]) == CONST_INT - && INTVAL (operands[1]) < 0 - && INTVAL (operands[1]) > - 0x8000" - [(set (match_dup 0) (match_dup 1)) - (set (match_dup 0) (neg:SI (match_dup 0)))] - " -{ - operands[1] = GEN_INT (- INTVAL (operands[1])); -}") +}) ;; This insn handles moving CCmode values. It's really just a ;; slightly simplified copy of movsi_internal2, with additional cases @@ -4521,7 +4317,7 @@ move\\t%0,%z4\\n\\ (match_operand:CC 1 "general_operand" "z,*d,*m,*d,*f,*d,*f,*m,*f"))] "ISA_HAS_8CC && TARGET_HARD_FLOAT" { return mips_output_move (operands[0], operands[1]); } - [(set_attr "type" "move,move,load,store,xfer,xfer,move,load,store") + [(set_attr "type" "xfer,arith,load,store,xfer,xfer,fmove,fpload,fpstore") (set_attr "mode" "SI") (set_attr "length" "8,4,*,*,4,4,4,*,*")]) @@ -4540,26 +4336,24 @@ move\\t%0,%z4\\n\\ ;; into a GPR takes a single movcc, moving elsewhere takes ;; two. We can leave these cases to the generic reload code. (define_expand "reload_incc" - [(set (match_operand:CC 0 "fcc_register_operand" "=z") + [(set (match_operand:CC 0 "fcc_reload_operand" "=z") (match_operand:CC 1 "general_operand" "")) (clobber (match_operand:TF 2 "register_operand" "=&f"))] "ISA_HAS_8CC && TARGET_HARD_FLOAT" - " { mips_emit_fcc_reload (operands[0], operands[1], operands[2]); DONE; -}") +}) (define_expand "reload_outcc" - [(set (match_operand:CC 0 "fcc_register_operand" "=z") + [(set (match_operand:CC 0 "fcc_reload_operand" "=z") (match_operand:CC 1 "register_operand" "")) (clobber (match_operand:TF 2 "register_operand" "=&f"))] "ISA_HAS_8CC && TARGET_HARD_FLOAT" - " { mips_emit_fcc_reload (operands[0], operands[1], operands[2]); DONE; -}") +}) ;; MIPS4 supports loading and storing a floating point register from ;; the sum of two general registers. We use two versions for each of @@ -4579,8 +4373,8 @@ move\\t%0,%z4\\n\\ (mem:SF (plus:SI (match_operand:SI 1 "register_operand" "d") (match_operand:SI 2 "register_operand" "d"))))] "ISA_HAS_FP4 && TARGET_HARD_FLOAT" - "lwxc1\\t%0,%1(%2)" - [(set_attr "type" "load") + "lwxc1\t%0,%1(%2)" + [(set_attr "type" "fpidxload") (set_attr "mode" "SF") (set_attr "length" "4")]) @@ -4589,8 +4383,8 @@ move\\t%0,%z4\\n\\ (mem:SF (plus:DI (match_operand:DI 1 "register_operand" "d") (match_operand:DI 2 "register_operand" "d"))))] "ISA_HAS_FP4 && TARGET_HARD_FLOAT" - "lwxc1\\t%0,%1(%2)" - [(set_attr "type" "load") + "lwxc1\t%0,%1(%2)" + [(set_attr "type" "fpidxload") (set_attr "mode" "SF") (set_attr "length" "4")]) @@ -4599,8 +4393,8 @@ move\\t%0,%z4\\n\\ (mem:DF (plus:SI (match_operand:SI 1 "register_operand" "d") (match_operand:SI 2 "register_operand" "d"))))] "ISA_HAS_FP4 && TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT" - "ldxc1\\t%0,%1(%2)" - [(set_attr "type" "load") + "ldxc1\t%0,%1(%2)" + [(set_attr "type" "fpidxload") (set_attr "mode" "DF") (set_attr "length" "4")]) @@ -4609,8 +4403,8 @@ move\\t%0,%z4\\n\\ (mem:DF (plus:DI (match_operand:DI 1 "register_operand" "d") (match_operand:DI 2 "register_operand" "d"))))] "ISA_HAS_FP4 && TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT" - "ldxc1\\t%0,%1(%2)" - [(set_attr "type" "load") + "ldxc1\t%0,%1(%2)" + [(set_attr "type" "fpidxload") (set_attr "mode" "DF") (set_attr "length" "4")]) @@ -4619,8 +4413,8 @@ move\\t%0,%z4\\n\\ (match_operand:SI 2 "register_operand" "d"))) (match_operand:SF 0 "register_operand" "f"))] "ISA_HAS_FP4 && TARGET_HARD_FLOAT" - "swxc1\\t%0,%1(%2)" - [(set_attr "type" "store") + "swxc1\t%0,%1(%2)" + [(set_attr "type" "fpidxstore") (set_attr "mode" "SF") (set_attr "length" "4")]) @@ -4629,8 +4423,8 @@ move\\t%0,%z4\\n\\ (match_operand:DI 2 "register_operand" "d"))) (match_operand:SF 0 "register_operand" "f"))] "ISA_HAS_FP4 && TARGET_HARD_FLOAT" - "swxc1\\t%0,%1(%2)" - [(set_attr "type" "store") + "swxc1\t%0,%1(%2)" + [(set_attr "type" "fpidxstore") (set_attr "mode" "SF") (set_attr "length" "4")]) @@ -4639,8 +4433,8 @@ move\\t%0,%z4\\n\\ (match_operand:SI 2 "register_operand" "d"))) (match_operand:DF 0 "register_operand" "f"))] "ISA_HAS_FP4 && TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT" - "sdxc1\\t%0,%1(%2)" - [(set_attr "type" "store") + "sdxc1\t%0,%1(%2)" + [(set_attr "type" "fpidxstore") (set_attr "mode" "DF") (set_attr "length" "4")]) @@ -4649,8 +4443,8 @@ move\\t%0,%z4\\n\\ (match_operand:DI 2 "register_operand" "d"))) (match_operand:DF 0 "register_operand" "f"))] "ISA_HAS_FP4 && TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT" - "sdxc1\\t%0,%1(%2)" - [(set_attr "type" "store") + "sdxc1\t%0,%1(%2)" + [(set_attr "type" "fpidxstore") (set_attr "mode" "DF") (set_attr "length" "4")]) @@ -4659,37 +4453,23 @@ move\\t%0,%z4\\n\\ ;; 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 +;; Unsigned loads are used because LOAD_EXTEND_OP returns ZERO_EXTEND. (define_expand "movhi" - [(set (match_operand:HI 0 "nonimmediate_operand" "") - (match_operand:HI 1 "general_operand" ""))] + [(set (match_operand:HI 0 "") + (match_operand:HI 1 ""))] "" - " -{ - if ((reload_in_progress | reload_completed) == 0 - && !register_operand (operands[0], HImode) - && !register_operand (operands[1], HImode) - && (TARGET_MIPS16 - || (GET_CODE (operands[1]) != CONST_INT - || INTVAL (operands[1]) != 0))) - { - rtx temp = force_reg (HImode, operands[1]); - emit_move_insn (operands[0], temp); - DONE; - } -}") - -;; The difference between these two is whether or not ints are allowed -;; in FP registers (off by default, use -mdebugh to enable). +{ + if (mips_legitimize_move (HImode, operands[0], operands[1])) + DONE; +}) -(define_insn "movhi_internal" - [(set (match_operand:HI 0 "nonimmediate_operand" "=d,d,d,m,*d,*f,*f,*x,*d") - (match_operand:HI 1 "general_operand" "d,IK,m,dJ,*f,*d,*f,*d,*x"))] +(define_insn "*movhi_internal" + [(set (match_operand:HI 0 "nonimmediate_operand" "=d,d,d,m,*d,*f,*f,*x") + (match_operand:HI 1 "move_operand" "d,I,m,dJ,*f,*d,*f,*d"))] "!TARGET_MIPS16 && (register_operand (operands[0], HImode) - || register_operand (operands[1], HImode) - || (GET_CODE (operands[1]) == CONST_INT && INTVAL (operands[1]) == 0))" + || reg_or_0_operand (operands[1], HImode))" "@ move\t%0,%1 li\t%0,%1 @@ -4698,15 +4478,14 @@ move\\t%0,%z4\\n\\ mfc1\t%0,%1 mtc1\t%1,%0 mov.s\t%0,%1 - mt%0\t%1 - mf%1\t%0" - [(set_attr "type" "move,arith,load,store,xfer,xfer,move,hilo,hilo") + mt%0\t%1" + [(set_attr "type" "arith,arith,load,store,xfer,xfer,fmove,mthilo") (set_attr "mode" "HI") - (set_attr "length" "4,4,*,*,4,4,4,4,4")]) + (set_attr "length" "4,4,*,*,4,4,4,4")]) -(define_insn "" - [(set (match_operand:HI 0 "nonimmediate_operand" "=d,y,d,d,d,d,m,*d") - (match_operand:HI 1 "general_operand" "d,d,y,K,N,m,d,*x"))] +(define_insn "*movhi_mips16" + [(set (match_operand:HI 0 "nonimmediate_operand" "=d,y,d,d,d,d,m") + (match_operand:HI 1 "move_operand" "d,d,y,K,N,m,d"))] "TARGET_MIPS16 && (register_operand (operands[0], HImode) || register_operand (operands[1], HImode))" @@ -4715,25 +4494,23 @@ move\\t%0,%z4\\n\\ move\t%0,%1 move\t%0,%1 li\t%0,%1 - li\t%0,%n1\;neg\t%0 + # lhu\t%0,%1 - sh\t%1,%0 - mf%1\t%0" - [(set_attr "type" "move,move,move,arith,arith,load,store,hilo") + sh\t%1,%0" + [(set_attr "type" "arith,arith,arith,arith,arith,load,store") (set_attr "mode" "HI") (set_attr_alternative "length" [(const_int 4) (const_int 4) (const_int 4) - (if_then_else (match_operand:VOID 1 "m16_uimm8_1" "") + (if_then_else (match_operand:VOID 1 "m16_uimm8_1") (const_int 4) (const_int 8)) - (if_then_else (match_operand:VOID 1 "m16_nuimm8_1" "") + (if_then_else (match_operand:VOID 1 "m16_nuimm8_1") (const_int 8) (const_int 12)) (const_string "*") - (const_string "*") - (const_int 4)])]) + (const_string "*")])]) ;; On the mips16, we can split lh $r,N($r) into an add and a load, @@ -4741,9 +4518,9 @@ move\\t%0,%z4\\n\\ ;; load are 2 2 byte instructions. (define_split - [(set (match_operand:HI 0 "register_operand" "") + [(set (match_operand:HI 0 "register_operand") (mem:HI (plus:SI (match_dup 0) - (match_operand:SI 1 "const_int_operand" ""))))] + (match_operand:SI 1 "const_int_operand"))))] "TARGET_MIPS16 && reload_completed && !TARGET_DEBUG_D_MODE && GET_CODE (operands[0]) == REG && M16_REG_P (REGNO (operands[0])) @@ -4757,12 +4534,11 @@ move\\t%0,%z4\\n\\ && (INTVAL (operands[1]) & 1) != 0))" [(set (match_dup 0) (plus:SI (match_dup 0) (match_dup 1))) (set (match_dup 0) (mem:HI (plus:SI (match_dup 0) (match_dup 2))))] - " { HOST_WIDE_INT val = INTVAL (operands[1]); if (val < 0) - operands[2] = GEN_INT (0); + operands[2] = const0_rtx; else if (val >= 32 * 2) { int off = val & 1; @@ -4777,44 +4553,30 @@ move\\t%0,%z4\\n\\ operands[1] = GEN_INT (off); operands[2] = GEN_INT (val - off); } -}") +}) ;; 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 +;; Unsigned loads are used because LOAD_EXTEND_OP returns ZERO_EXTEND. (define_expand "movqi" - [(set (match_operand:QI 0 "nonimmediate_operand" "") - (match_operand:QI 1 "general_operand" ""))] + [(set (match_operand:QI 0 "") + (match_operand:QI 1 ""))] "" - " -{ - if ((reload_in_progress | reload_completed) == 0 - && !register_operand (operands[0], QImode) - && !register_operand (operands[1], QImode) - && (TARGET_MIPS16 - || (GET_CODE (operands[1]) != CONST_INT - || INTVAL (operands[1]) != 0))) - { - rtx temp = force_reg (QImode, operands[1]); - emit_move_insn (operands[0], temp); - DONE; - } -}") +{ + if (mips_legitimize_move (QImode, operands[0], operands[1])) + DONE; +}) -;; The difference between these two is whether or not ints are allowed -;; in FP registers (off by default, use -mdebugh to enable). - -(define_insn "movqi_internal" - [(set (match_operand:QI 0 "nonimmediate_operand" "=d,d,d,m,*d,*f,*f,*x,*d") - (match_operand:QI 1 "general_operand" "d,IK,m,dJ,*f,*d,*f,*d,*x"))] +(define_insn "*movqi_internal" + [(set (match_operand:QI 0 "nonimmediate_operand" "=d,d,d,m,*d,*f,*f,*x") + (match_operand:QI 1 "move_operand" "d,I,m,dJ,*f,*d,*f,*d"))] "!TARGET_MIPS16 && (register_operand (operands[0], QImode) - || register_operand (operands[1], QImode) - || (GET_CODE (operands[1]) == CONST_INT && INTVAL (operands[1]) == 0))" + || reg_or_0_operand (operands[1], QImode))" "@ move\t%0,%1 li\t%0,%1 @@ -4823,15 +4585,14 @@ move\\t%0,%z4\\n\\ mfc1\t%0,%1 mtc1\t%1,%0 mov.s\t%0,%1 - mt%0\t%1 - mf%1\t%0" - [(set_attr "type" "move,arith,load,store,xfer,xfer,move,hilo,hilo") + mt%0\t%1" + [(set_attr "type" "arith,arith,load,store,xfer,xfer,fmove,mthilo") (set_attr "mode" "QI") - (set_attr "length" "4,4,*,*,4,4,4,4,4")]) + (set_attr "length" "4,4,*,*,4,4,4,4")]) -(define_insn "" - [(set (match_operand:QI 0 "nonimmediate_operand" "=d,y,d,d,d,d,m,*d") - (match_operand:QI 1 "general_operand" "d,d,y,K,N,m,d,*x"))] +(define_insn "*movqi_mips16" + [(set (match_operand:QI 0 "nonimmediate_operand" "=d,y,d,d,d,d,m") + (match_operand:QI 1 "move_operand" "d,d,y,K,N,m,d"))] "TARGET_MIPS16 && (register_operand (operands[0], QImode) || register_operand (operands[1], QImode))" @@ -4840,22 +4601,21 @@ move\\t%0,%z4\\n\\ move\t%0,%1 move\t%0,%1 li\t%0,%1 - li\t%0,%n1\;neg\t%0 + # lbu\t%0,%1 - sb\t%1,%0 - mf%1\t%0" - [(set_attr "type" "move,move,move,arith,arith,load,store,hilo") + sb\t%1,%0" + [(set_attr "type" "arith,arith,arith,arith,arith,load,store") (set_attr "mode" "QI") - (set_attr "length" "4,4,4,4,8,*,*,4")]) + (set_attr "length" "4,4,4,4,8,*,*")]) ;; On the mips16, we can split lb $r,N($r) into an add and a load, ;; when the original load is a 4 byte instruction but the add and the ;; load are 2 2 byte instructions. (define_split - [(set (match_operand:QI 0 "register_operand" "") + [(set (match_operand:QI 0 "register_operand") (mem:QI (plus:SI (match_dup 0) - (match_operand:SI 1 "const_int_operand" ""))))] + (match_operand:SI 1 "const_int_operand"))))] "TARGET_MIPS16 && reload_completed && !TARGET_DEBUG_D_MODE && GET_CODE (operands[0]) == REG && M16_REG_P (REGNO (operands[0])) @@ -4866,63 +4626,59 @@ move\\t%0,%z4\\n\\ && INTVAL (operands[1]) <= 31 + 0x7f))" [(set (match_dup 0) (plus:SI (match_dup 0) (match_dup 1))) (set (match_dup 0) (mem:QI (plus:SI (match_dup 0) (match_dup 2))))] - " { HOST_WIDE_INT val = INTVAL (operands[1]); if (val < 0) - operands[2] = GEN_INT (0); + operands[2] = const0_rtx; else { operands[1] = GEN_INT (0x7f); operands[2] = GEN_INT (val - 0x7f); } -}") +}) ;; 32-bit floating point moves (define_expand "movsf" - [(set (match_operand:SF 0 "nonimmediate_operand" "") - (match_operand:SF 1 "general_operand" ""))] + [(set (match_operand:SF 0 "") + (match_operand:SF 1 ""))] "" - " { - if ((reload_in_progress | reload_completed) == 0 - && !register_operand (operands[0], SFmode) - && !nonmemory_operand (operands[1], SFmode)) - operands[1] = force_reg (SFmode, operands[1]); -}") + if (mips_legitimize_move (SFmode, operands[0], operands[1])) + DONE; +}) -(define_insn "movsf_internal1" +(define_insn "*movsf_hardfloat" [(set (match_operand:SF 0 "nonimmediate_operand" "=f,f,f,m,*f,*d,*d,*d,*m") - (match_operand:SF 1 "general_operand" "f,G,m,fG,*d,*f,*G*d,*m,*d"))] + (match_operand:SF 1 "move_operand" "f,G,m,fG,*d,*f,*G*d,*m,*d"))] "TARGET_HARD_FLOAT && (register_operand (operands[0], SFmode) - || nonmemory_operand (operands[1], SFmode))" + || reg_or_0_operand (operands[1], SFmode))" { return mips_output_move (operands[0], operands[1]); } - [(set_attr "type" "move,xfer,load,store,xfer,xfer,move,load,store") + [(set_attr "type" "fmove,xfer,fpload,fpstore,xfer,xfer,arith,load,store") (set_attr "mode" "SF") (set_attr "length" "4,4,*,*,4,4,4,*,*")]) -(define_insn "movsf_internal2" +(define_insn "*movsf_softfloat" [(set (match_operand:SF 0 "nonimmediate_operand" "=d,d,m") - (match_operand:SF 1 "general_operand" " Gd,m,d"))] + (match_operand:SF 1 "move_operand" "Gd,m,d"))] "TARGET_SOFT_FLOAT && !TARGET_MIPS16 && (register_operand (operands[0], SFmode) - || nonmemory_operand (operands[1], SFmode))" + || reg_or_0_operand (operands[1], SFmode))" { return mips_output_move (operands[0], operands[1]); } - [(set_attr "type" "move,load,store") + [(set_attr "type" "arith,load,store") (set_attr "mode" "SF") (set_attr "length" "4,*,*")]) -(define_insn "" +(define_insn "*movsf_mips16" [(set (match_operand:SF 0 "nonimmediate_operand" "=d,y,d,d,m") - (match_operand:SF 1 "nonimmediate_operand" "d,d,y,m,d"))] + (match_operand:SF 1 "move_operand" "d,d,y,m,d"))] "TARGET_MIPS16 && (register_operand (operands[0], SFmode) || register_operand (operands[1], SFmode))" { return mips_output_move (operands[0], operands[1]); } - [(set_attr "type" "move,move,move,load,store") + [(set_attr "type" "arith,arith,arith,load,store") (set_attr "mode" "SF") (set_attr "length" "4,4,4,*,*")]) @@ -4930,82 +4686,119 @@ move\\t%0,%z4\\n\\ ;; 64-bit floating point moves (define_expand "movdf" - [(set (match_operand:DF 0 "nonimmediate_operand" "") - (match_operand:DF 1 "general_operand" ""))] + [(set (match_operand:DF 0 "") + (match_operand:DF 1 ""))] "" - " { - if ((reload_in_progress | reload_completed) == 0 - && !register_operand (operands[0], DFmode) - && !nonmemory_operand (operands[1], DFmode)) - operands[1] = force_reg (DFmode, operands[1]); -}") + if (mips_legitimize_move (DFmode, operands[0], operands[1])) + DONE; +}) -(define_insn "movdf_internal1a" +(define_insn "*movdf_hardfloat_64bit" [(set (match_operand:DF 0 "nonimmediate_operand" "=f,f,f,m,*f,*d,*d,*d,*m") - (match_operand:DF 1 "general_operand" "f,G,m,fG,*d,*f,*d*G,*m,*d"))] + (match_operand:DF 1 "move_operand" "f,G,m,fG,*d,*f,*d*G,*m,*d"))] "TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT && TARGET_64BIT && (register_operand (operands[0], DFmode) - || nonmemory_operand (operands[1], DFmode))" + || reg_or_0_operand (operands[1], DFmode))" { return mips_output_move (operands[0], operands[1]); } - [(set_attr "type" "move,xfer,load,store,xfer,xfer,move,load,store") + [(set_attr "type" "fmove,xfer,fpload,fpstore,xfer,xfer,arith,load,store") (set_attr "mode" "DF") (set_attr "length" "4,4,*,*,4,4,4,*,*")]) -(define_insn "movdf_internal1b" +(define_insn "*movdf_hardfloat_32bit" [(set (match_operand:DF 0 "nonimmediate_operand" "=f,f,f,m,*f,*d,*d,*d,*m") - (match_operand:DF 1 "general_operand" "f,G,m,fG,*d,*f,*d*G,*m,*d"))] + (match_operand:DF 1 "move_operand" "f,G,m,fG,*d,*f,*d*G,*m,*d"))] "TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT && !TARGET_64BIT && (register_operand (operands[0], DFmode) - || nonmemory_operand (operands[1], DFmode))" + || reg_or_0_operand (operands[1], DFmode))" { return mips_output_move (operands[0], operands[1]); } - [(set_attr "type" "move,xfer,load,store,xfer,xfer,move,load,store") + [(set_attr "type" "fmove,xfer,fpload,fpstore,xfer,xfer,arith,load,store") (set_attr "mode" "DF") (set_attr "length" "4,8,*,*,8,8,8,*,*")]) -(define_insn "movdf_internal2" +(define_insn "*movdf_softfloat" [(set (match_operand:DF 0 "nonimmediate_operand" "=d,d,m,d,f,f") - (match_operand:DF 1 "general_operand" "dG,m,dG,f,d,f"))] + (match_operand:DF 1 "move_operand" "dG,m,dG,f,d,f"))] "(TARGET_SOFT_FLOAT || TARGET_SINGLE_FLOAT) && !TARGET_MIPS16 && (register_operand (operands[0], DFmode) - || nonmemory_operand (operands[1], DFmode))" + || reg_or_0_operand (operands[1], DFmode))" { return mips_output_move (operands[0], operands[1]); } - [(set_attr "type" "move,load,store,xfer,xfer,move") + [(set_attr "type" "arith,load,store,xfer,xfer,fmove") (set_attr "mode" "DF") (set_attr "length" "8,*,*,4,4,4")]) -(define_insn "" +(define_insn "*movdf_mips16" [(set (match_operand:DF 0 "nonimmediate_operand" "=d,y,d,d,m") - (match_operand:DF 1 "nonimmediate_operand" "d,d,y,m,d"))] + (match_operand:DF 1 "move_operand" "d,d,y,m,d"))] "TARGET_MIPS16 && (register_operand (operands[0], DFmode) || register_operand (operands[1], DFmode))" { return mips_output_move (operands[0], operands[1]); } - [(set_attr "type" "move,move,move,load,store") + [(set_attr "type" "arith,arith,arith,load,store") (set_attr "mode" "DF") (set_attr "length" "8,8,8,*,*")]) (define_split - [(set (match_operand:DI 0 "nonimmediate_operand" "") - (match_operand:DI 1 "general_operand" ""))] + [(set (match_operand:DI 0 "nonimmediate_operand") + (match_operand:DI 1 "move_operand"))] "reload_completed && !TARGET_64BIT && mips_split_64bit_move_p (operands[0], operands[1])" [(const_int 0)] - { - mips_split_64bit_move (operands[0], operands[1]); - DONE; - }) +{ + mips_split_64bit_move (operands[0], operands[1]); + DONE; +}) (define_split - [(set (match_operand:DF 0 "nonimmediate_operand" "") - (match_operand:DF 1 "general_operand" ""))] + [(set (match_operand:DF 0 "nonimmediate_operand") + (match_operand:DF 1 "move_operand"))] "reload_completed && !TARGET_64BIT && mips_split_64bit_move_p (operands[0], operands[1])" [(const_int 0)] - { - mips_split_64bit_move (operands[0], operands[1]); - DONE; - }) +{ + mips_split_64bit_move (operands[0], operands[1]); + DONE; +}) + +;; When generating mips16 code, split moves of negative constants into +;; a positive "li" followed by a negation. +(define_split + [(set (match_operand 0 "register_operand") + (match_operand 1 "const_int_operand"))] + "TARGET_MIPS16 && reload_completed && INTVAL (operands[1]) < 0" + [(set (match_dup 2) + (match_dup 3)) + (set (match_dup 2) + (neg:SI (match_dup 2)))] +{ + operands[2] = gen_lowpart (SImode, operands[0]); + operands[3] = GEN_INT (-INTVAL (operands[1])); +}) + +;; The HI and LO registers are not truly independent. If we move an mthi +;; instruction before an mflo instruction, it will make the result of the +;; mflo unpredictable. The same goes for mtlo and mfhi. +;; +;; We cope with this by making the mflo and mfhi patterns use both HI and LO. +;; Operand 1 is the register we want, operand 2 is the other one. + +(define_insn "mfhilo_di" + [(set (match_operand:DI 0 "register_operand" "=d,d") + (unspec:DI [(match_operand:DI 1 "register_operand" "h,l") + (match_operand:DI 2 "register_operand" "l,h")] + UNSPEC_MFHILO))] + "TARGET_64BIT" + "mf%1\t%0" + [(set_attr "type" "mfhilo")]) + +(define_insn "mfhilo_si" + [(set (match_operand:SI 0 "register_operand" "=d,d") + (unspec:SI [(match_operand:SI 1 "register_operand" "h,l") + (match_operand:SI 2 "register_operand" "l,h")] + UNSPEC_MFHILO))] + "" + "mf%1\t%0" + [(set_attr "type" "mfhilo")]) ;; Patterns for loading or storing part of a paired floating point ;; register. We need them because odd-numbered floating-point registers @@ -5017,13 +4810,12 @@ move\\t%0,%z4\\n\\ (unspec:DF [(match_operand:SI 1 "general_operand" "dJ,m")] UNSPEC_LOAD_DF_LOW))] "TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT && !TARGET_64BIT" - { - operands[0] = mips_subword (operands[0], 0); - return mips_output_move (operands[0], operands[1]); - } - [(set_attr "type" "xfer,load") - (set_attr "mode" "SF") - (set_attr "length" "4")]) +{ + operands[0] = mips_subword (operands[0], 0); + return mips_output_move (operands[0], operands[1]); +} + [(set_attr "type" "xfer,fpload") + (set_attr "mode" "SF")]) ;; Load the high word of operand 0 from operand 1, preserving the value ;; in the low word. @@ -5033,13 +4825,12 @@ move\\t%0,%z4\\n\\ (match_operand:DF 2 "register_operand" "0,0")] UNSPEC_LOAD_DF_HIGH))] "TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT && !TARGET_64BIT" - { - operands[0] = mips_subword (operands[0], 1); - return mips_output_move (operands[0], operands[1]); - } - [(set_attr "type" "xfer,load") - (set_attr "mode" "SF") - (set_attr "length" "4")]) +{ + operands[0] = mips_subword (operands[0], 1); + return mips_output_move (operands[0], operands[1]); +} + [(set_attr "type" "xfer,fpload") + (set_attr "mode" "SF")]) ;; Store the high word of operand 1 in operand 0. The corresponding ;; low-word move is done in the normal way. @@ -5048,13 +4839,32 @@ move\\t%0,%z4\\n\\ (unspec:SI [(match_operand:DF 1 "register_operand" "f,f")] UNSPEC_STORE_DF_HIGH))] "TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT && !TARGET_64BIT" - { - operands[1] = mips_subword (operands[1], 1); - return mips_output_move (operands[0], operands[1]); - } - [(set_attr "type" "xfer,store") - (set_attr "mode" "SF") - (set_attr "length" "4")]) +{ + operands[1] = mips_subword (operands[1], 1); + return mips_output_move (operands[0], operands[1]); +} + [(set_attr "type" "xfer,fpstore") + (set_attr "mode" "SF")]) + +;; Insn to initialize $gp for n32/n64 abicalls. Operand 0 is the offset +;; of _gp from the start of this function. Operand 1 is the incoming +;; function address. +(define_insn_and_split "loadgp" + [(unspec_volatile [(match_operand 0 "" "") + (match_operand 1 "register_operand" "")] UNSPEC_LOADGP)] + "TARGET_ABICALLS && TARGET_NEWABI" + "#" + "" + [(set (match_dup 2) (match_dup 3)) + (set (match_dup 2) (match_dup 4)) + (set (match_dup 2) (match_dup 5))] +{ + operands[2] = pic_offset_table_rtx; + operands[3] = gen_rtx_HIGH (Pmode, operands[0]); + operands[4] = gen_rtx_PLUS (Pmode, operands[2], operands[1]); + operands[5] = gen_rtx_LO_SUM (Pmode, operands[2], operands[0]); +} + [(set_attr "length" "12")]) ;; The use of gp is hidden when not using explicit relocations. ;; This blockage instruction prevents the gp load from being @@ -5068,16 +4878,21 @@ move\\t%0,%z4\\n\\ (set_attr "mode" "none") (set_attr "length" "0")]) -;; Emit a .cprestore directive, which expands to a single store instruction. -;; Note that we continue to use .cprestore for explicit reloc code so that -;; jals inside inlines asms will work correctly. +;; Emit a .cprestore directive, which normally expands to a single store +;; instruction. Note that we continue to use .cprestore for explicit reloc +;; code so that jals inside inline asms will work correctly. (define_insn "cprestore" - [(unspec_volatile [(match_operand 0 "const_int_operand" "")] + [(unspec_volatile [(match_operand 0 "const_int_operand" "I,i")] UNSPEC_CPRESTORE)] "" - ".cprestore\t%0" +{ + if (set_nomacro && which_alternative == 1) + return ".set\tmacro\;.cprestore\t%0\;.set\tnomacro"; + else + return ".cprestore\t%0"; +} [(set_attr "type" "store") - (set_attr "length" "4")]) + (set_attr "length" "4,12")]) ;; Block moves, see mips.c for more details. ;; Argument 0 is the destination @@ -5085,18 +4900,18 @@ move\\t%0,%z4\\n\\ ;; Argument 2 is the length ;; Argument 3 is the alignment -(define_expand "movstrsi" - [(parallel [(set (match_operand:BLK 0 "general_operand" "") - (match_operand:BLK 1 "general_operand" "")) - (use (match_operand:SI 2 "" "")) - (use (match_operand:SI 3 "const_int_operand" ""))])] +(define_expand "movmemsi" + [(parallel [(set (match_operand:BLK 0 "general_operand") + (match_operand:BLK 1 "general_operand")) + (use (match_operand:SI 2 "")) + (use (match_operand:SI 3 "const_int_operand"))])] "!TARGET_MIPS16 && !TARGET_MEMCPY" - { - if (mips_expand_block_move (operands[0], operands[1], operands[2])) - DONE; - else - FAIL; - }) +{ + if (mips_expand_block_move (operands[0], operands[1], operands[2])) + DONE; + else + FAIL; +}) ;; ;; .................... @@ -5105,15 +4920,14 @@ move\\t%0,%z4\\n\\ ;; ;; .................... -;; Many of these instructions uses trivial define_expands, because we +;; Many of these instructions use trivial define_expands, because we ;; want to use a different set of constraints when TARGET_MIPS16. (define_expand "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")))] + [(set (match_operand:SI 0 "register_operand") + (ashift:SI (match_operand:SI 1 "register_operand") + (match_operand:SI 2 "arith_operand")))] "" - " { /* On the mips16, a shift of more than 8 is a four byte instruction, so, for a shift between 8 and 16, it is just as fast to do two @@ -5137,21 +4951,20 @@ move\\t%0,%z4\\n\\ GEN_INT (INTVAL (operands[2]) - 8))); DONE; } -}") +}) (define_insn "ashlsi3_internal1" [(set (match_operand:SI 0 "register_operand" "=d") (ashift:SI (match_operand:SI 1 "register_operand" "d") (match_operand:SI 2 "arith_operand" "dI")))] "!TARGET_MIPS16" - "* { if (GET_CODE (operands[2]) == CONST_INT) operands[2] = GEN_INT (INTVAL (operands[2]) & 0x1f); - return \"sll\\t%0,%1,%2\"; -}" - [(set_attr "type" "arith") + return "sll\t%0,%1,%2"; +} + [(set_attr "type" "shift") (set_attr "mode" "SI")]) (define_insn "ashlsi3_internal1_extend" @@ -5159,14 +4972,13 @@ move\\t%0,%z4\\n\\ (sign_extend:DI (ashift:SI (match_operand:SI 1 "register_operand" "d") (match_operand:SI 2 "arith_operand" "dI"))))] "TARGET_64BIT && !TARGET_MIPS16" - "* { if (GET_CODE (operands[2]) == CONST_INT) operands[2] = GEN_INT (INTVAL (operands[2]) & 0x1f); - return \"sll\\t%0,%1,%2\"; -}" - [(set_attr "type" "arith") + return "sll\t%0,%1,%2"; +} + [(set_attr "type" "shift") (set_attr "mode" "DI")]) @@ -5175,273 +4987,80 @@ move\\t%0,%z4\\n\\ (ashift:SI (match_operand:SI 1 "register_operand" "0,d") (match_operand:SI 2 "arith_operand" "d,I")))] "TARGET_MIPS16" - "* { if (which_alternative == 0) - return \"sll\\t%0,%2\"; + return "sll\t%0,%2"; if (GET_CODE (operands[2]) == CONST_INT) operands[2] = GEN_INT (INTVAL (operands[2]) & 0x1f); - return \"sll\\t%0,%1,%2\"; -}" - [(set_attr "type" "arith") + return "sll\t%0,%1,%2"; +} + [(set_attr "type" "shift") (set_attr "mode" "SI") (set_attr_alternative "length" [(const_int 4) - (if_then_else (match_operand:VOID 2 "m16_uimm3_b" "") + (if_then_else (match_operand:VOID 2 "m16_uimm3_b") (const_int 4) (const_int 8))])]) ;; On the mips16, we can split a 4 byte shift into 2 2 byte shifts. (define_split - [(set (match_operand:SI 0 "register_operand" "") - (ashift:SI (match_operand:SI 1 "register_operand" "") - (match_operand:SI 2 "const_int_operand" "")))] + [(set (match_operand:SI 0 "register_operand") + (ashift:SI (match_operand:SI 1 "register_operand") + (match_operand:SI 2 "const_int_operand")))] "TARGET_MIPS16 && reload_completed && !TARGET_DEBUG_D_MODE && GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) > 8 && INTVAL (operands[2]) <= 16" [(set (match_dup 0) (ashift:SI (match_dup 1) (const_int 8))) (set (match_dup 0) (ashift:SI (match_dup 0) (match_dup 2)))] -" -{ - operands[2] = GEN_INT (INTVAL (operands[2]) - 8); -}") + { operands[2] = GEN_INT (INTVAL (operands[2]) - 8); }) (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_64BIT || (!TARGET_DEBUG_G_MODE && !TARGET_MIPS16)" - " + [(set (match_operand:DI 0 "register_operand") + (ashift:DI (match_operand:DI 1 "register_operand") + (match_operand:SI 2 "arith_operand")))] + "TARGET_64BIT" { - if (TARGET_64BIT) + /* On the mips16, a shift of more than 8 is a four byte + instruction, so, for a shift between 8 and 16, it is just as + fast to do two shifts of 8 or less. If there is a lot of + shifting going on, we may win in CSE. Otherwise combine will + put the shifts back together again. This can be called by + function_arg, so we must be careful not to allocate a new + register if we've reached the reload pass. */ + if (TARGET_MIPS16 + && optimize + && GET_CODE (operands[2]) == CONST_INT + && INTVAL (operands[2]) > 8 + && INTVAL (operands[2]) <= 16 + && ! reload_in_progress + && ! reload_completed) { - /* On the mips16, a shift of more than 8 is a four byte - instruction, so, for a shift between 8 and 16, it is just as - fast to do two shifts of 8 or less. If there is a lot of - shifting going on, we may win in CSE. Otherwise combine will - put the shifts back together again. This can be called by - function_arg, so we must be careful not to allocate a new - register if we've reached the reload pass. */ - if (TARGET_MIPS16 - && optimize - && GET_CODE (operands[2]) == CONST_INT - && INTVAL (operands[2]) > 8 - && INTVAL (operands[2]) <= 16 - && ! reload_in_progress - && ! reload_completed) - { - rtx temp = gen_reg_rtx (DImode); + rtx temp = gen_reg_rtx (DImode); - emit_insn (gen_ashldi3_internal4 (temp, operands[1], GEN_INT (8))); - emit_insn (gen_ashldi3_internal4 (operands[0], temp, - GEN_INT (INTVAL (operands[2]) - 8))); - DONE; - } - - emit_insn (gen_ashldi3_internal4 (operands[0], operands[1], - operands[2])); + emit_insn (gen_ashldi3_internal (temp, operands[1], GEN_INT (8))); + emit_insn (gen_ashldi3_internal (operands[0], temp, + GEN_INT (INTVAL (operands[2]) - 8))); DONE; } - - 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_64BIT && !TARGET_DEBUG_G_MODE && !TARGET_MIPS16" - "* -{ - operands[4] = const0_rtx; - - 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" "48")]) - - -(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_64BIT && !TARGET_DEBUG_G_MODE && !TARGET_MIPS16 - && (INTVAL (operands[2]) & 32) != 0" - "* -{ - operands[2] = GEN_INT (INTVAL (operands[2]) & 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" "8")]) - - -(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_64BIT - && !TARGET_DEBUG_D_MODE && !TARGET_DEBUG_G_MODE && !TARGET_MIPS16 - && 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) 4) (ashift:SI (subreg:SI (match_dup 1) 0) (match_dup 2))) - (set (subreg:SI (match_dup 0) 0) (const_int 0))] - - "operands[2] = GEN_INT (INTVAL (operands[2]) & 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_64BIT - && !TARGET_DEBUG_D_MODE && !TARGET_DEBUG_G_MODE && !TARGET_MIPS16 - && 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) 4) (match_dup 2))) - (set (subreg:SI (match_dup 0) 4) (const_int 0))] - - "operands[2] = GEN_INT (INTVAL (operands[2]) & 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_64BIT && !TARGET_DEBUG_G_MODE && !TARGET_MIPS16 - && (INTVAL (operands[2]) & 63) < 32 - && (INTVAL (operands[2]) & 63) != 0" - "* -{ - int amount = INTVAL (operands[2]); - - operands[2] = GEN_INT (amount & 31); - operands[4] = const0_rtx; - operands[5] = GEN_INT ((-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" "16")]) - - -(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_64BIT - && !TARGET_DEBUG_D_MODE && !TARGET_DEBUG_G_MODE && !TARGET_MIPS16 - && 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) 4) - (ashift:SI (subreg:SI (match_dup 1) 4) - (match_dup 2))) - - (set (match_dup 3) - (lshiftrt:SI (subreg:SI (match_dup 1) 0) - (match_dup 4))) - - (set (subreg:SI (match_dup 0) 4) - (ior:SI (subreg:SI (match_dup 0) 4) - (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_INT (amount & 31); - operands[4] = GEN_INT ((-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_64BIT - && !TARGET_DEBUG_D_MODE && !TARGET_DEBUG_G_MODE && !TARGET_MIPS16 - && 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) 4) - (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) 4) - (ashift:SI (subreg:SI (match_dup 1) 4) - (match_dup 2)))] - " -{ - int amount = INTVAL (operands[2]); - operands[2] = GEN_INT (amount & 31); - operands[4] = GEN_INT ((-amount) & 31); -}") - - -(define_insn "ashldi3_internal4" [(set (match_operand:DI 0 "register_operand" "=d") (ashift:DI (match_operand:DI 1 "register_operand" "d") (match_operand:SI 2 "arith_operand" "dI")))] "TARGET_64BIT && !TARGET_MIPS16" - "* { if (GET_CODE (operands[2]) == CONST_INT) operands[2] = GEN_INT (INTVAL (operands[2]) & 0x3f); - return \"dsll\\t%0,%1,%2\"; -}" - [(set_attr "type" "arith") + return "dsll\t%0,%1,%2"; +} + [(set_attr "type" "shift") (set_attr "mode" "DI")]) (define_insn "" @@ -5449,21 +5068,20 @@ move\\t%0,%z4\\n\\ (ashift:DI (match_operand:DI 1 "register_operand" "0,d") (match_operand:SI 2 "arith_operand" "d,I")))] "TARGET_64BIT && TARGET_MIPS16" - "* { if (which_alternative == 0) - return \"dsll\\t%0,%2\"; + return "dsll\t%0,%2"; if (GET_CODE (operands[2]) == CONST_INT) operands[2] = GEN_INT (INTVAL (operands[2]) & 0x3f); - return \"dsll\\t%0,%1,%2\"; -}" - [(set_attr "type" "arith") + return "dsll\t%0,%1,%2"; +} + [(set_attr "type" "shift") (set_attr "mode" "DI") (set_attr_alternative "length" [(const_int 4) - (if_then_else (match_operand:VOID 2 "m16_uimm3_b" "") + (if_then_else (match_operand:VOID 2 "m16_uimm3_b") (const_int 4) (const_int 8))])]) @@ -5471,9 +5089,9 @@ move\\t%0,%z4\\n\\ ;; On the mips16, we can split a 4 byte shift into 2 2 byte shifts. (define_split - [(set (match_operand:DI 0 "register_operand" "") - (ashift:DI (match_operand:DI 1 "register_operand" "") - (match_operand:SI 2 "const_int_operand" "")))] + [(set (match_operand:DI 0 "register_operand") + (ashift:DI (match_operand:DI 1 "register_operand") + (match_operand:SI 2 "const_int_operand")))] "TARGET_MIPS16 && TARGET_64BIT && !TARGET_DEBUG_D_MODE && reload_completed && GET_CODE (operands[2]) == CONST_INT @@ -5481,17 +5099,13 @@ move\\t%0,%z4\\n\\ && INTVAL (operands[2]) <= 16" [(set (match_dup 0) (ashift:DI (match_dup 1) (const_int 8))) (set (match_dup 0) (ashift:DI (match_dup 0) (match_dup 2)))] -" -{ - operands[2] = GEN_INT (INTVAL (operands[2]) - 8); -}") + { operands[2] = GEN_INT (INTVAL (operands[2]) - 8); }) (define_expand "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")))] + [(set (match_operand:SI 0 "register_operand") + (ashiftrt:SI (match_operand:SI 1 "register_operand") + (match_operand:SI 2 "arith_operand")))] "" - " { /* On the mips16, a shift of more than 8 is a four byte instruction, so, for a shift between 8 and 16, it is just as fast to do two @@ -5511,21 +5125,20 @@ move\\t%0,%z4\\n\\ GEN_INT (INTVAL (operands[2]) - 8))); DONE; } -}") +}) (define_insn "ashrsi3_internal1" [(set (match_operand:SI 0 "register_operand" "=d") (ashiftrt:SI (match_operand:SI 1 "register_operand" "d") (match_operand:SI 2 "arith_operand" "dI")))] "!TARGET_MIPS16" - "* { if (GET_CODE (operands[2]) == CONST_INT) operands[2] = GEN_INT (INTVAL (operands[2]) & 0x1f); - return \"sra\\t%0,%1,%2\"; -}" - [(set_attr "type" "arith") + return "sra\t%0,%1,%2"; +} + [(set_attr "type" "shift") (set_attr "mode" "SI")]) (define_insn "ashrsi3_internal2" @@ -5533,21 +5146,20 @@ move\\t%0,%z4\\n\\ (ashiftrt:SI (match_operand:SI 1 "register_operand" "0,d") (match_operand:SI 2 "arith_operand" "d,I")))] "TARGET_MIPS16" - "* { if (which_alternative == 0) - return \"sra\\t%0,%2\"; + return "sra\t%0,%2"; if (GET_CODE (operands[2]) == CONST_INT) operands[2] = GEN_INT (INTVAL (operands[2]) & 0x1f); - return \"sra\\t%0,%1,%2\"; -}" - [(set_attr "type" "arith") + return "sra\t%0,%1,%2"; +} + [(set_attr "type" "shift") (set_attr "mode" "SI") (set_attr_alternative "length" [(const_int 4) - (if_then_else (match_operand:VOID 2 "m16_uimm3_b" "") + (if_then_else (match_operand:VOID 2 "m16_uimm3_b") (const_int 4) (const_int 8))])]) @@ -5555,245 +5167,56 @@ move\\t%0,%z4\\n\\ ;; On the mips16, we can split a 4 byte shift into 2 2 byte shifts. (define_split - [(set (match_operand:SI 0 "register_operand" "") - (ashiftrt:SI (match_operand:SI 1 "register_operand" "") - (match_operand:SI 2 "const_int_operand" "")))] + [(set (match_operand:SI 0 "register_operand") + (ashiftrt:SI (match_operand:SI 1 "register_operand") + (match_operand:SI 2 "const_int_operand")))] "TARGET_MIPS16 && reload_completed && !TARGET_DEBUG_D_MODE && GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) > 8 && INTVAL (operands[2]) <= 16" [(set (match_dup 0) (ashiftrt:SI (match_dup 1) (const_int 8))) (set (match_dup 0) (ashiftrt:SI (match_dup 0) (match_dup 2)))] -" -{ - operands[2] = GEN_INT (INTVAL (operands[2]) - 8); -}") + { operands[2] = GEN_INT (INTVAL (operands[2]) - 8); }) (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_64BIT || (!TARGET_DEBUG_G_MODE && !TARGET_MIPS16)" - " + [(set (match_operand:DI 0 "register_operand") + (ashiftrt:DI (match_operand:DI 1 "register_operand") + (match_operand:SI 2 "arith_operand")))] + "TARGET_64BIT" { - if (TARGET_64BIT) + /* On the mips16, a shift of more than 8 is a four byte + instruction, so, for a shift between 8 and 16, it is just as + fast to do two shifts of 8 or less. If there is a lot of + shifting going on, we may win in CSE. Otherwise combine will + put the shifts back together again. */ + if (TARGET_MIPS16 + && optimize + && GET_CODE (operands[2]) == CONST_INT + && INTVAL (operands[2]) > 8 + && INTVAL (operands[2]) <= 16) { - /* On the mips16, a shift of more than 8 is a four byte - instruction, so, for a shift between 8 and 16, it is just as - fast to do two shifts of 8 or less. If there is a lot of - shifting going on, we may win in CSE. Otherwise combine will - put the shifts back together again. */ - if (TARGET_MIPS16 - && optimize - && GET_CODE (operands[2]) == CONST_INT - && INTVAL (operands[2]) > 8 - && INTVAL (operands[2]) <= 16) - { - rtx temp = gen_reg_rtx (DImode); - - emit_insn (gen_ashrdi3_internal4 (temp, operands[1], GEN_INT (8))); - emit_insn (gen_ashrdi3_internal4 (operands[0], temp, - GEN_INT (INTVAL (operands[2]) - 8))); - DONE; - } + rtx temp = gen_reg_rtx (DImode); - emit_insn (gen_ashrdi3_internal4 (operands[0], operands[1], - operands[2])); + emit_insn (gen_ashrdi3_internal (temp, operands[1], GEN_INT (8))); + emit_insn (gen_ashrdi3_internal (operands[0], temp, + GEN_INT (INTVAL (operands[2]) - 8))); DONE; } - - 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_64BIT && !TARGET_DEBUG_G_MODE && !TARGET_MIPS16" - "* -{ - operands[4] = const0_rtx; - - 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" "48")]) - - -(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_64BIT && !TARGET_DEBUG_G_MODE && (INTVAL (operands[2]) & 32) != 0" - "* -{ - operands[2] = GEN_INT (INTVAL (operands[2]) & 0x1f); - return \"sra\\t%L0,%M1,%2\;sra\\t%M0,%M1,31\"; -}" - [(set_attr "type" "darith") - (set_attr "mode" "DI") - (set_attr "length" "8")]) - - -(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_64BIT - && !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) 4) (match_dup 2))) - (set (subreg:SI (match_dup 0) 4) (ashiftrt:SI (subreg:SI (match_dup 1) 4) (const_int 31)))] - - "operands[2] = GEN_INT (INTVAL (operands[2]) & 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_64BIT - && !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) 4) (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_INT (INTVAL (operands[2]) & 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_64BIT && !TARGET_DEBUG_G_MODE && !TARGET_MIPS16 - && (INTVAL (operands[2]) & 63) < 32 - && (INTVAL (operands[2]) & 63) != 0" - "* -{ - int amount = INTVAL (operands[2]); - - operands[2] = GEN_INT (amount & 31); - operands[4] = GEN_INT ((-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" "16")]) - - -(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_64BIT - && !TARGET_DEBUG_D_MODE && !TARGET_DEBUG_G_MODE && !TARGET_MIPS16 - && 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) 4) - (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) 4) - (ashiftrt:SI (subreg:SI (match_dup 1) 4) - (match_dup 2)))] - " -{ - int amount = INTVAL (operands[2]); - operands[2] = GEN_INT (amount & 31); - operands[4] = GEN_INT ((-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_64BIT - && !TARGET_DEBUG_D_MODE && !TARGET_DEBUG_G_MODE && !TARGET_MIPS16 - && 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) 4) - (lshiftrt:SI (subreg:SI (match_dup 1) 4) - (match_dup 2))) - - (set (match_dup 3) - (ashift:SI (subreg:SI (match_dup 1) 0) - (match_dup 4))) - - (set (subreg:SI (match_dup 0) 4) - (ior:SI (subreg:SI (match_dup 0) 4) - (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_INT (amount & 31); - operands[4] = GEN_INT ((-amount) & 31); -}") - - -(define_insn "ashrdi3_internal4" [(set (match_operand:DI 0 "register_operand" "=d") (ashiftrt:DI (match_operand:DI 1 "register_operand" "d") (match_operand:SI 2 "arith_operand" "dI")))] "TARGET_64BIT && !TARGET_MIPS16" - "* { if (GET_CODE (operands[2]) == CONST_INT) operands[2] = GEN_INT (INTVAL (operands[2]) & 0x3f); - return \"dsra\\t%0,%1,%2\"; -}" - [(set_attr "type" "arith") + return "dsra\t%0,%1,%2"; +} + [(set_attr "type" "shift") (set_attr "mode" "DI")]) (define_insn "" @@ -5801,27 +5224,26 @@ move\\t%0,%z4\\n\\ (ashiftrt:DI (match_operand:DI 1 "register_operand" "0,0") (match_operand:SI 2 "arith_operand" "d,I")))] "TARGET_64BIT && TARGET_MIPS16" - "* { if (GET_CODE (operands[2]) == CONST_INT) operands[2] = GEN_INT (INTVAL (operands[2]) & 0x3f); - return \"dsra\\t%0,%2\"; -}" - [(set_attr "type" "arith") + return "dsra\t%0,%2"; +} + [(set_attr "type" "shift") (set_attr "mode" "DI") (set_attr_alternative "length" [(const_int 4) - (if_then_else (match_operand:VOID 2 "m16_uimm3_b" "") + (if_then_else (match_operand:VOID 2 "m16_uimm3_b") (const_int 4) (const_int 8))])]) ;; On the mips16, we can split a 4 byte shift into 2 2 byte shifts. (define_split - [(set (match_operand:DI 0 "register_operand" "") - (ashiftrt:DI (match_operand:DI 1 "register_operand" "") - (match_operand:SI 2 "const_int_operand" "")))] + [(set (match_operand:DI 0 "register_operand") + (ashiftrt:DI (match_operand:DI 1 "register_operand") + (match_operand:SI 2 "const_int_operand")))] "TARGET_MIPS16 && TARGET_64BIT && !TARGET_DEBUG_D_MODE && reload_completed && GET_CODE (operands[2]) == CONST_INT @@ -5829,17 +5251,13 @@ move\\t%0,%z4\\n\\ && INTVAL (operands[2]) <= 16" [(set (match_dup 0) (ashiftrt:DI (match_dup 1) (const_int 8))) (set (match_dup 0) (ashiftrt:DI (match_dup 0) (match_dup 2)))] -" -{ - operands[2] = GEN_INT (INTVAL (operands[2]) - 8); -}") + { operands[2] = GEN_INT (INTVAL (operands[2]) - 8); }) (define_expand "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")))] + [(set (match_operand:SI 0 "register_operand") + (lshiftrt:SI (match_operand:SI 1 "register_operand") + (match_operand:SI 2 "arith_operand")))] "" - " { /* On the mips16, a shift of more than 8 is a four byte instruction, so, for a shift between 8 and 16, it is just as fast to do two @@ -5859,21 +5277,20 @@ move\\t%0,%z4\\n\\ GEN_INT (INTVAL (operands[2]) - 8))); DONE; } -}") +}) (define_insn "lshrsi3_internal1" [(set (match_operand:SI 0 "register_operand" "=d") (lshiftrt:SI (match_operand:SI 1 "register_operand" "d") (match_operand:SI 2 "arith_operand" "dI")))] "!TARGET_MIPS16" - "* { if (GET_CODE (operands[2]) == CONST_INT) operands[2] = GEN_INT (INTVAL (operands[2]) & 0x1f); - return \"srl\\t%0,%1,%2\"; -}" - [(set_attr "type" "arith") + return "srl\t%0,%1,%2"; +} + [(set_attr "type" "shift") (set_attr "mode" "SI")]) (define_insn "lshrsi3_internal2" @@ -5881,21 +5298,20 @@ move\\t%0,%z4\\n\\ (lshiftrt:SI (match_operand:SI 1 "register_operand" "0,d") (match_operand:SI 2 "arith_operand" "d,I")))] "TARGET_MIPS16" - "* { if (which_alternative == 0) - return \"srl\\t%0,%2\"; + return "srl\t%0,%2"; if (GET_CODE (operands[2]) == CONST_INT) operands[2] = GEN_INT (INTVAL (operands[2]) & 0x1f); - return \"srl\\t%0,%1,%2\"; -}" - [(set_attr "type" "arith") + return "srl\t%0,%1,%2"; +} + [(set_attr "type" "shift") (set_attr "mode" "SI") (set_attr_alternative "length" [(const_int 4) - (if_then_else (match_operand:VOID 2 "m16_uimm3_b" "") + (if_then_else (match_operand:VOID 2 "m16_uimm3_b") (const_int 4) (const_int 8))])]) @@ -5903,19 +5319,16 @@ move\\t%0,%z4\\n\\ ;; On the mips16, we can split a 4 byte shift into 2 2 byte shifts. (define_split - [(set (match_operand:SI 0 "register_operand" "") - (lshiftrt:SI (match_operand:SI 1 "register_operand" "") - (match_operand:SI 2 "const_int_operand" "")))] + [(set (match_operand:SI 0 "register_operand") + (lshiftrt:SI (match_operand:SI 1 "register_operand") + (match_operand:SI 2 "const_int_operand")))] "TARGET_MIPS16 && reload_completed && !TARGET_DEBUG_D_MODE && GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) > 8 && INTVAL (operands[2]) <= 16" [(set (match_dup 0) (lshiftrt:SI (match_dup 1) (const_int 8))) (set (match_dup 0) (lshiftrt:SI (match_dup 0) (match_dup 2)))] -" -{ - operands[2] = GEN_INT (INTVAL (operands[2]) - 8); -}") + { operands[2] = GEN_INT (INTVAL (operands[2]) - 8); }) ;; If we load a byte on the mips16 as a bitfield, the resulting ;; sequence of instructions is too complicated for combine, because it @@ -5923,276 +5336,80 @@ move\\t%0,%z4\\n\\ ;; register, and an and (the key problem here is that the mips16 does ;; not have and immediate). We recognize a shift of a load in order ;; to make it simple enough for combine to understand. - -;; ??? FIXME: turn into a define_insn_and_split -(define_insn "" +;; +;; The length here is the worst case: the length of the split version +;; will be more accurate. +(define_insn_and_split "" [(set (match_operand:SI 0 "register_operand" "=d") (lshiftrt:SI (match_operand:SI 1 "memory_operand" "m") (match_operand:SI 2 "immediate_operand" "I")))] - "0 && TARGET_MIPS16" - "lw\\t%0,%1\;srl\\t%0,%2" - [(set_attr "type" "load") - (set_attr "mode" "SI") - (set_attr_alternative "length" - [(if_then_else (match_operand:VOID 2 "m16_uimm3_b" "") - (const_int 12) - (const_int 16))])]) - -(define_split - [(set (match_operand:SI 0 "register_operand" "") - (lshiftrt:SI (match_operand:SI 1 "memory_operand" "") - (match_operand:SI 2 "immediate_operand" "")))] - "TARGET_MIPS16 && !TARGET_DEBUG_D_MODE" + "TARGET_MIPS16" + "#" + "" [(set (match_dup 0) (match_dup 1)) (set (match_dup 0) (lshiftrt:SI (match_dup 0) (match_dup 2)))] - "") + "" + [(set_attr "type" "load") + (set_attr "mode" "SI") + (set_attr "length" "16")]) (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_64BIT || (!TARGET_DEBUG_G_MODE && !TARGET_MIPS16)" - " + [(set (match_operand:DI 0 "register_operand") + (lshiftrt:DI (match_operand:DI 1 "register_operand") + (match_operand:SI 2 "arith_operand")))] + "TARGET_64BIT" { - if (TARGET_64BIT) + /* On the mips16, a shift of more than 8 is a four byte + instruction, so, for a shift between 8 and 16, it is just as + fast to do two shifts of 8 or less. If there is a lot of + shifting going on, we may win in CSE. Otherwise combine will + put the shifts back together again. */ + if (TARGET_MIPS16 + && optimize + && GET_CODE (operands[2]) == CONST_INT + && INTVAL (operands[2]) > 8 + && INTVAL (operands[2]) <= 16) { - /* On the mips16, a shift of more than 8 is a four byte - instruction, so, for a shift between 8 and 16, it is just as - fast to do two shifts of 8 or less. If there is a lot of - shifting going on, we may win in CSE. Otherwise combine will - put the shifts back together again. */ - if (TARGET_MIPS16 - && optimize - && GET_CODE (operands[2]) == CONST_INT - && INTVAL (operands[2]) > 8 - && INTVAL (operands[2]) <= 16) - { - rtx temp = gen_reg_rtx (DImode); + rtx temp = gen_reg_rtx (DImode); - emit_insn (gen_lshrdi3_internal4 (temp, operands[1], GEN_INT (8))); - emit_insn (gen_lshrdi3_internal4 (operands[0], temp, - GEN_INT (INTVAL (operands[2]) - 8))); - DONE; - } - - emit_insn (gen_lshrdi3_internal4 (operands[0], operands[1], - operands[2])); + emit_insn (gen_lshrdi3_internal (temp, operands[1], GEN_INT (8))); + emit_insn (gen_lshrdi3_internal (operands[0], temp, + GEN_INT (INTVAL (operands[2]) - 8))); DONE; } - - 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_64BIT && !TARGET_DEBUG_G_MODE && !TARGET_MIPS16" - "* -{ - operands[4] = const0_rtx; - - 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" "48")]) - - -(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_64BIT && !TARGET_DEBUG_G_MODE && !TARGET_MIPS16 - && (INTVAL (operands[2]) & 32) != 0" - "* -{ - operands[2] = GEN_INT (INTVAL (operands[2]) & 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" "8")]) - + (match_operand:SI 2 "arith_operand" "dI")))] + "TARGET_64BIT && !TARGET_MIPS16" +{ + if (GET_CODE (operands[2]) == CONST_INT) + operands[2] = GEN_INT (INTVAL (operands[2]) & 0x3f); -(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_64BIT - && !TARGET_DEBUG_D_MODE && !TARGET_DEBUG_G_MODE && !TARGET_MIPS16 - && 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) 4) (match_dup 2))) - (set (subreg:SI (match_dup 0) 4) (const_int 0))] - - "operands[2] = GEN_INT (INTVAL (operands[2]) & 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_64BIT - && !TARGET_DEBUG_D_MODE && !TARGET_DEBUG_G_MODE && !TARGET_MIPS16 - && 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) 4) (lshiftrt:SI (subreg:SI (match_dup 1) 0) (match_dup 2))) - (set (subreg:SI (match_dup 0) 0) (const_int 0))] - - "operands[2] = GEN_INT (INTVAL (operands[2]) & 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_64BIT && !TARGET_DEBUG_G_MODE && !TARGET_MIPS16 - && (INTVAL (operands[2]) & 63) < 32 - && (INTVAL (operands[2]) & 63) != 0" - "* -{ - int amount = INTVAL (operands[2]); - - operands[2] = GEN_INT (amount & 31); - operands[4] = GEN_INT ((-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" "16")]) - - -(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_64BIT - && !TARGET_DEBUG_D_MODE && !TARGET_DEBUG_G_MODE && !TARGET_MIPS16 - && 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) 4) - (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) 4) - (lshiftrt:SI (subreg:SI (match_dup 1) 4) - (match_dup 2)))] - " -{ - int amount = INTVAL (operands[2]); - operands[2] = GEN_INT (amount & 31); - operands[4] = GEN_INT ((-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_64BIT - && !TARGET_DEBUG_D_MODE && !TARGET_DEBUG_G_MODE && !TARGET_MIPS16 - && 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) 4) - (lshiftrt:SI (subreg:SI (match_dup 1) 4) - (match_dup 2))) - - (set (match_dup 3) - (ashift:SI (subreg:SI (match_dup 1) 0) - (match_dup 4))) - - (set (subreg:SI (match_dup 0) 4) - (ior:SI (subreg:SI (match_dup 0) 4) - (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_INT (amount & 31); - operands[4] = GEN_INT ((-amount) & 31); -}") - - -(define_insn "lshrdi3_internal4" - [(set (match_operand:DI 0 "register_operand" "=d") - (lshiftrt:DI (match_operand:DI 1 "register_operand" "d") - (match_operand:SI 2 "arith_operand" "dI")))] - "TARGET_64BIT && !TARGET_MIPS16" - "* -{ - if (GET_CODE (operands[2]) == CONST_INT) - operands[2] = GEN_INT (INTVAL (operands[2]) & 0x3f); - - return \"dsrl\\t%0,%1,%2\"; -}" - [(set_attr "type" "arith") - (set_attr "mode" "DI")]) + return "dsrl\t%0,%1,%2"; +} + [(set_attr "type" "shift") + (set_attr "mode" "DI")]) (define_insn "" [(set (match_operand:DI 0 "register_operand" "=d,d") (lshiftrt:DI (match_operand:DI 1 "register_operand" "0,0") (match_operand:SI 2 "arith_operand" "d,I")))] "TARGET_64BIT && TARGET_MIPS16" - "* { if (GET_CODE (operands[2]) == CONST_INT) operands[2] = GEN_INT (INTVAL (operands[2]) & 0x3f); - return \"dsrl\\t%0,%2\"; -}" - [(set_attr "type" "arith") + return "dsrl\t%0,%2"; +} + [(set_attr "type" "shift") (set_attr "mode" "DI") (set_attr_alternative "length" [(const_int 4) - (if_then_else (match_operand:VOID 2 "m16_uimm3_b" "") + (if_then_else (match_operand:VOID 2 "m16_uimm3_b") (const_int 4) (const_int 8))])]) @@ -6201,18 +5418,17 @@ move\\t%0,%z4\\n\\ (rotatert:SI (match_operand:SI 1 "register_operand" "d") (match_operand:SI 2 "arith_operand" "dn")))] "ISA_HAS_ROTR_SI" - "* { if (TARGET_SR71K && GET_CODE (operands[2]) != CONST_INT) - return \"rorv\\t%0,%1,%2\"; + return "rorv\t%0,%1,%2"; if ((GET_CODE (operands[2]) == CONST_INT) && (INTVAL (operands[2]) < 0 || INTVAL (operands[2]) >= 32)) abort (); - return \"ror\\t%0,%1,%2\"; -}" - [(set_attr "type" "arith") + return "ror\t%0,%1,%2"; +} + [(set_attr "type" "shift") (set_attr "mode" "SI")]) (define_insn "rotrdi3" @@ -6220,44 +5436,39 @@ move\\t%0,%z4\\n\\ (rotatert:DI (match_operand:DI 1 "register_operand" "d") (match_operand:DI 2 "arith_operand" "dn")))] "ISA_HAS_ROTR_DI" - "* { - if (TARGET_SR71K) + if (TARGET_SR71K) { if (GET_CODE (operands[2]) != CONST_INT) - return \"drorv\\t%0,%1,%2\"; + return "drorv\t%0,%1,%2"; if (INTVAL (operands[2]) >= 32 && INTVAL (operands[2]) <= 63) - return \"dror32\\t%0,%1,%2\"; + return "dror32\t%0,%1,%2"; } if ((GET_CODE (operands[2]) == CONST_INT) && (INTVAL (operands[2]) < 0 || INTVAL (operands[2]) >= 64)) abort (); - return \"dror\\t%0,%1,%2\"; -}" - [(set_attr "type" "arith") + return "dror\t%0,%1,%2"; +} + [(set_attr "type" "shift") (set_attr "mode" "DI")]) ;; On the mips16, we can split a 4 byte shift into 2 2 byte shifts. (define_split - [(set (match_operand:DI 0 "register_operand" "") - (lshiftrt:DI (match_operand:DI 1 "register_operand" "") - (match_operand:SI 2 "const_int_operand" "")))] + [(set (match_operand:DI 0 "register_operand") + (lshiftrt:DI (match_operand:DI 1 "register_operand") + (match_operand:SI 2 "const_int_operand")))] "TARGET_MIPS16 && reload_completed && !TARGET_DEBUG_D_MODE && GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) > 8 && INTVAL (operands[2]) <= 16" [(set (match_dup 0) (lshiftrt:DI (match_dup 1) (const_int 8))) (set (match_dup 0) (lshiftrt:DI (match_dup 0) (match_dup 2)))] -" -{ - operands[2] = GEN_INT (INTVAL (operands[2]) - 8); -}") - + { operands[2] = GEN_INT (INTVAL (operands[2]) - 8); }) ;; ;; .................... @@ -6268,114 +5479,62 @@ move\\t%0,%z4\\n\\ ;; Flow here is rather complex: ;; -;; 1) The cmp{si,di,sf,df} routine is called. It deposits the -;; arguments into the branch_cmp array, and the type into -;; branch_type. No RTL is generated. +;; 1) The cmp{si,di,sf,df} routine is called. It deposits the arguments +;; into cmp_operands[] but generates no RTL. ;; ;; 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 +;; operands into the branches 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" ""))] + (compare:CC (match_operand:SI 0 "register_operand") + (match_operand:SI 1 "nonmemory_operand")))] "" - " { - if (operands[0]) /* avoid unused code message */ - { - branch_cmp[0] = operands[0]; - branch_cmp[1] = const0_rtx; - branch_type = CMP_SI; - DONE; - } -}") + cmp_operands[0] = operands[0]; + cmp_operands[1] = operands[1]; + DONE; +}) (define_expand "cmpdi" [(set (cc0) - (compare:CC (match_operand:DI 0 "register_operand" "") - (match_operand:DI 1 "arith_operand" "")))] - "TARGET_64BIT" - " -{ - if (operands[0]) /* avoid unused code message */ - { - branch_cmp[0] = operands[0]; - branch_cmp[1] = operands[1]; - branch_type = CMP_DI; - DONE; - } -}") - -(define_expand "tstdi" - [(set (cc0) - (match_operand:DI 0 "register_operand" ""))] + (compare:CC (match_operand:DI 0 "register_operand") + (match_operand:DI 1 "nonmemory_operand")))] "TARGET_64BIT" - " { - if (operands[0]) /* avoid unused code message */ - { - branch_cmp[0] = operands[0]; - branch_cmp[1] = const0_rtx; - branch_type = CMP_DI; - DONE; - } -}") + cmp_operands[0] = operands[0]; + cmp_operands[1] = operands[1]; + DONE; +}) (define_expand "cmpdf" [(set (cc0) - (compare:CC (match_operand:DF 0 "register_operand" "") - (match_operand:DF 1 "register_operand" "")))] + (compare:CC (match_operand:DF 0 "register_operand") + (match_operand:DF 1 "register_operand")))] "TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT" - " { - if (operands[0]) /* avoid unused code message */ - { - branch_cmp[0] = operands[0]; - branch_cmp[1] = operands[1]; - branch_type = CMP_DF; - DONE; - } -}") + cmp_operands[0] = operands[0]; + cmp_operands[1] = operands[1]; + DONE; +}) (define_expand "cmpsf" [(set (cc0) - (compare:CC (match_operand:SF 0 "register_operand" "") - (match_operand:SF 1 "register_operand" "")))] + (compare:CC (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; - } -}") - + cmp_operands[0] = operands[0]; + cmp_operands[1] = operands[1]; + DONE; +}) ;; ;; .................... @@ -6389,13 +5548,12 @@ move\\t%0,%z4\\n\\ (define_insn "branch_fp" [(set (pc) (if_then_else - (match_operator:CC 0 "cmp_op" + (match_operator:CC 0 "comparison_operator" [(match_operand:CC 2 "register_operand" "z") (const_int 0)]) (label_ref (match_operand 1 "" "")) (pc)))] "TARGET_HARD_FLOAT" - "* { return mips_output_conditional_branch (insn, operands, @@ -6403,20 +5561,19 @@ move\\t%0,%z4\\n\\ /*float_p=*/1, /*inverted_p=*/0, get_attr_length (insn)); -}" +} [(set_attr "type" "branch") (set_attr "mode" "none")]) (define_insn "branch_fp_inverted" [(set (pc) (if_then_else - (match_operator:CC 0 "cmp_op" + (match_operator:CC 0 "comparison_operator" [(match_operand:CC 2 "register_operand" "z") (const_int 0)]) (pc) (label_ref (match_operand 1 "" ""))))] "TARGET_HARD_FLOAT" - "* { return mips_output_conditional_branch (insn, operands, @@ -6424,7 +5581,7 @@ move\\t%0,%z4\\n\\ /*float_p=*/1, /*inverted_p=*/1, get_attr_length (insn)); -}" +} [(set_attr "type" "branch") (set_attr "mode" "none")]) @@ -6433,13 +5590,12 @@ move\\t%0,%z4\\n\\ (define_insn "branch_zero" [(set (pc) (if_then_else - (match_operator:SI 0 "cmp_op" + (match_operator:SI 0 "comparison_operator" [(match_operand:SI 2 "register_operand" "d") (const_int 0)]) (label_ref (match_operand 1 "" "")) (pc)))] "!TARGET_MIPS16" - "* { return mips_output_conditional_branch (insn, operands, @@ -6447,20 +5603,19 @@ move\\t%0,%z4\\n\\ /*float_p=*/0, /*inverted_p=*/0, get_attr_length (insn)); -}" +} [(set_attr "type" "branch") (set_attr "mode" "none")]) (define_insn "branch_zero_inverted" [(set (pc) (if_then_else - (match_operator:SI 0 "cmp_op" + (match_operator:SI 0 "comparison_operator" [(match_operand:SI 2 "register_operand" "d") (const_int 0)]) (pc) (label_ref (match_operand 1 "" ""))))] "!TARGET_MIPS16" - "* { return mips_output_conditional_branch (insn, operands, @@ -6468,20 +5623,19 @@ move\\t%0,%z4\\n\\ /*float_p=*/0, /*inverted_p=*/1, get_attr_length (insn)); -}" +} [(set_attr "type" "branch") (set_attr "mode" "none")]) (define_insn "branch_zero_di" [(set (pc) (if_then_else - (match_operator:DI 0 "cmp_op" + (match_operator:DI 0 "comparison_operator" [(match_operand:DI 2 "register_operand" "d") (const_int 0)]) (label_ref (match_operand 1 "" "")) (pc)))] "!TARGET_MIPS16" - "* { return mips_output_conditional_branch (insn, operands, @@ -6489,20 +5643,19 @@ move\\t%0,%z4\\n\\ /*float_p=*/0, /*inverted_p=*/0, get_attr_length (insn)); -}" +} [(set_attr "type" "branch") (set_attr "mode" "none")]) (define_insn "branch_zero_di_inverted" [(set (pc) (if_then_else - (match_operator:DI 0 "cmp_op" + (match_operator:DI 0 "comparison_operator" [(match_operand:DI 2 "register_operand" "d") (const_int 0)]) (pc) (label_ref (match_operand 1 "" ""))))] "!TARGET_MIPS16" - "* { return mips_output_conditional_branch (insn, operands, @@ -6510,7 +5663,7 @@ move\\t%0,%z4\\n\\ /*float_p=*/0, /*inverted_p=*/1, get_attr_length (insn)); -}" +} [(set_attr "type" "branch") (set_attr "mode" "none")]) @@ -6519,13 +5672,12 @@ move\\t%0,%z4\\n\\ (define_insn "branch_equality" [(set (pc) (if_then_else - (match_operator:SI 0 "equality_op" + (match_operator:SI 0 "equality_operator" [(match_operand:SI 2 "register_operand" "d") (match_operand:SI 3 "register_operand" "d")]) (label_ref (match_operand 1 "" "")) (pc)))] "!TARGET_MIPS16" - "* { return mips_output_conditional_branch (insn, operands, @@ -6533,20 +5685,19 @@ move\\t%0,%z4\\n\\ /*float_p=*/0, /*inverted_p=*/0, get_attr_length (insn)); -}" +} [(set_attr "type" "branch") (set_attr "mode" "none")]) (define_insn "branch_equality_di" [(set (pc) (if_then_else - (match_operator:DI 0 "equality_op" + (match_operator:DI 0 "equality_operator" [(match_operand:DI 2 "register_operand" "d") (match_operand:DI 3 "register_operand" "d")]) (label_ref (match_operand 1 "" "")) (pc)))] "!TARGET_MIPS16" - "* { return mips_output_conditional_branch (insn, operands, @@ -6554,20 +5705,19 @@ move\\t%0,%z4\\n\\ /*float_p=*/0, /*inverted_p=*/0, get_attr_length (insn)); -}" +} [(set_attr "type" "branch") (set_attr "mode" "none")]) (define_insn "branch_equality_inverted" [(set (pc) (if_then_else - (match_operator:SI 0 "equality_op" + (match_operator:SI 0 "equality_operator" [(match_operand:SI 2 "register_operand" "d") (match_operand:SI 3 "register_operand" "d")]) (pc) (label_ref (match_operand 1 "" ""))))] "!TARGET_MIPS16" - "* { return mips_output_conditional_branch (insn, operands, @@ -6575,20 +5725,19 @@ move\\t%0,%z4\\n\\ /*float_p=*/0, /*inverted_p=*/1, get_attr_length (insn)); -}" +} [(set_attr "type" "branch") (set_attr "mode" "none")]) (define_insn "branch_equality_di_inverted" [(set (pc) (if_then_else - (match_operator:DI 0 "equality_op" + (match_operator:DI 0 "equality_operator" [(match_operand:DI 2 "register_operand" "d") (match_operand:DI 3 "register_operand" "d")]) (pc) (label_ref (match_operand 1 "" ""))))] "!TARGET_MIPS16" - "* { return mips_output_conditional_branch (insn, operands, @@ -6596,7 +5745,7 @@ move\\t%0,%z4\\n\\ /*float_p=*/0, /*inverted_p=*/1, get_attr_length (insn)); -}" +} [(set_attr "type" "branch") (set_attr "mode" "none")]) @@ -6604,58 +5753,58 @@ move\\t%0,%z4\\n\\ (define_insn "" [(set (pc) - (if_then_else (match_operator:SI 0 "equality_op" - [(match_operand:SI 1 "register_operand" "d,t") - (const_int 0)]) + (if_then_else + (match_operator:SI 0 "equality_operator" + [(match_operand:SI 1 "register_operand" "d,t") + (const_int 0)]) (match_operand 2 "pc_or_label_operand" "") (match_operand 3 "pc_or_label_operand" "")))] "TARGET_MIPS16" - "* { if (operands[2] != pc_rtx) { if (which_alternative == 0) - return \"b%C0z\\t%1,%2\"; + return "b%C0z\t%1,%2"; else - return \"bt%C0z\\t%2\"; + return "bt%C0z\t%2"; } else { if (which_alternative == 0) - return \"b%N0z\\t%1,%3\"; + return "b%N0z\t%1,%3"; else - return \"bt%N0z\\t%3\"; + return "bt%N0z\t%3"; } -}" +} [(set_attr "type" "branch") (set_attr "mode" "none") (set_attr "length" "8")]) (define_insn "" [(set (pc) - (if_then_else (match_operator:DI 0 "equality_op" - [(match_operand:DI 1 "register_operand" "d,t") - (const_int 0)]) + (if_then_else + (match_operator:DI 0 "equality_operator" + [(match_operand:DI 1 "register_operand" "d,t") + (const_int 0)]) (match_operand 2 "pc_or_label_operand" "") (match_operand 3 "pc_or_label_operand" "")))] "TARGET_MIPS16" - "* { if (operands[2] != pc_rtx) { if (which_alternative == 0) - return \"b%C0z\\t%1,%2\"; + return "b%C0z\t%1,%2"; else - return \"bt%C0z\\t%2\"; + return "bt%C0z\t%2"; } else { if (which_alternative == 0) - return \"b%N0z\\t%1,%3\"; + return "b%N0z\t%1,%3"; else - return \"bt%N0z\\t%3\"; + return "bt%N0z\t%3"; } -}" +} [(set_attr "type" "branch") (set_attr "mode" "none") (set_attr "length" "8")]) @@ -6664,282 +5813,217 @@ move\\t%0,%z4\\n\\ [(set (pc) (if_then_else (unordered:CC (cc0) (const_int 0)) - (label_ref (match_operand 0 "" "")) + (label_ref (match_operand 0 "")) (pc)))] "" - " { - if (operands[0]) /* avoid unused code warning */ - { - gen_conditional_branch (operands, UNORDERED); - DONE; - } -}") + gen_conditional_branch (operands, UNORDERED); + DONE; +}) (define_expand "bordered" [(set (pc) (if_then_else (ordered:CC (cc0) (const_int 0)) - (label_ref (match_operand 0 "" "")) + (label_ref (match_operand 0 "")) (pc)))] "" - " { - if (operands[0]) /* avoid unused code warning */ - { - gen_conditional_branch (operands, ORDERED); - DONE; - } -}") + gen_conditional_branch (operands, ORDERED); + DONE; +}) (define_expand "bunlt" [(set (pc) (if_then_else (unlt:CC (cc0) (const_int 0)) - (label_ref (match_operand 0 "" "")) + (label_ref (match_operand 0 "")) (pc)))] "" - " { - if (operands[0]) /* avoid unused code warning */ - { - gen_conditional_branch (operands, UNLT); - DONE; - } -}") + gen_conditional_branch (operands, UNLT); + DONE; +}) (define_expand "bunge" [(set (pc) (if_then_else (unge:CC (cc0) (const_int 0)) - (label_ref (match_operand 0 "" "")) + (label_ref (match_operand 0 "")) (pc)))] "" - " { gen_conditional_branch (operands, UNGE); DONE; -}") +}) (define_expand "buneq" [(set (pc) (if_then_else (uneq:CC (cc0) (const_int 0)) - (label_ref (match_operand 0 "" "")) + (label_ref (match_operand 0 "")) (pc)))] "" - " { - if (operands[0]) /* avoid unused code warning */ - { - gen_conditional_branch (operands, UNEQ); - DONE; - } -}") + gen_conditional_branch (operands, UNEQ); + DONE; +}) (define_expand "bltgt" [(set (pc) (if_then_else (ltgt:CC (cc0) (const_int 0)) - (label_ref (match_operand 0 "" "")) + (label_ref (match_operand 0 "")) (pc)))] "" - " { gen_conditional_branch (operands, LTGT); DONE; -}") +}) (define_expand "bunle" [(set (pc) (if_then_else (unle:CC (cc0) (const_int 0)) - (label_ref (match_operand 0 "" "")) + (label_ref (match_operand 0 "")) (pc)))] "" - " { - if (operands[0]) /* avoid unused code warning */ - { - gen_conditional_branch (operands, UNLE); - DONE; - } -}") + gen_conditional_branch (operands, UNLE); + DONE; +}) (define_expand "bungt" [(set (pc) (if_then_else (ungt:CC (cc0) (const_int 0)) - (label_ref (match_operand 0 "" "")) + (label_ref (match_operand 0 "")) (pc)))] "" - " { gen_conditional_branch (operands, UNGT); DONE; -}") +}) (define_expand "beq" [(set (pc) (if_then_else (eq:CC (cc0) (const_int 0)) - (label_ref (match_operand 0 "" "")) + (label_ref (match_operand 0 "")) (pc)))] "" - " { - if (operands[0]) /* avoid unused code warning */ - { - gen_conditional_branch (operands, EQ); - DONE; - } -}") + gen_conditional_branch (operands, EQ); + DONE; +}) (define_expand "bne" [(set (pc) (if_then_else (ne:CC (cc0) (const_int 0)) - (label_ref (match_operand 0 "" "")) + (label_ref (match_operand 0 "")) (pc)))] "" - " { - if (operands[0]) /* avoid unused code warning */ - { - gen_conditional_branch (operands, NE); - DONE; - } -}") + 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 "" "")) + (label_ref (match_operand 0 "")) (pc)))] "" - " { - if (operands[0]) /* avoid unused code warning */ - { - gen_conditional_branch (operands, GT); - DONE; - } -}") + 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 "" "")) + (label_ref (match_operand 0 "")) (pc)))] "" - " { - if (operands[0]) /* avoid unused code warning */ - { - gen_conditional_branch (operands, GE); - DONE; - } -}") + 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 "" "")) + (label_ref (match_operand 0 "")) (pc)))] "" - " { - if (operands[0]) /* avoid unused code warning */ - { - gen_conditional_branch (operands, LT); - DONE; - } -}") + 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 "" "")) + (label_ref (match_operand 0 "")) (pc)))] "" - " { - if (operands[0]) /* avoid unused code warning */ - { - gen_conditional_branch (operands, LE); - DONE; - } -}") + 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 "" "")) + (label_ref (match_operand 0 "")) (pc)))] "" - " { - if (operands[0]) /* avoid unused code warning */ - { - gen_conditional_branch (operands, GTU); - DONE; - } -}") + 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 "" "")) + (label_ref (match_operand 0 "")) (pc)))] "" - " { - if (operands[0]) /* avoid unused code warning */ - { - gen_conditional_branch (operands, GEU); - DONE; - } -}") - + 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 "" "")) + (label_ref (match_operand 0 "")) (pc)))] "" - " { - if (operands[0]) /* avoid unused code warning */ - { - gen_conditional_branch (operands, LTU); - DONE; - } -}") + 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 "" "")) + (label_ref (match_operand 0 "")) (pc)))] "" - " { - if (operands[0]) /* avoid unused code warning */ - { - gen_conditional_branch (operands, LEU); - DONE; - } -}") - + gen_conditional_branch (operands, LEU); + DONE; +}) ;; ;; .................... @@ -6949,884 +6033,439 @@ move\\t%0,%z4\\n\\ ;; .................... (define_expand "seq" - [(set (match_operand:SI 0 "register_operand" "=d") + [(set (match_operand:SI 0 "register_operand") (eq:SI (match_dup 1) (match_dup 2)))] "" - " -{ - if (branch_type != CMP_SI && (!TARGET_64BIT || branch_type != CMP_DI)) - FAIL; - - /* set up operands from compare. */ - operands[1] = branch_cmp[0]; - operands[2] = branch_cmp[1]; + { if (mips_emit_scc (EQ, operands[0])) DONE; else FAIL; }) - if (TARGET_64BIT || !TARGET_DEBUG_C_MODE || TARGET_MIPS16) - { - 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" +(define_insn "*seq_si" [(set (match_operand:SI 0 "register_operand" "=d") (eq:SI (match_operand:SI 1 "register_operand" "d") (const_int 0)))] "!TARGET_MIPS16" - "sltu\\t%0,%1,1" - [(set_attr "type" "arith") - (set_attr "mode" "SI")]) + "sltu\t%0,%1,1" + [(set_attr "type" "slt") + (set_attr "mode" "SI")]) -(define_insn "" +(define_insn "*seq_si_mips16" [(set (match_operand:SI 0 "register_operand" "=t") (eq:SI (match_operand:SI 1 "register_operand" "d") (const_int 0)))] "TARGET_MIPS16" - "sltu\\t%1,1" - [(set_attr "type" "arith") - (set_attr "mode" "SI")]) + "sltu\t%1,1" + [(set_attr "type" "slt") + (set_attr "mode" "SI")]) -(define_insn "seq_di_zero" +(define_insn "*seq_di" [(set (match_operand:DI 0 "register_operand" "=d") (eq:DI (match_operand:DI 1 "register_operand" "d") (const_int 0)))] "TARGET_64BIT && !TARGET_MIPS16" - "sltu\\t%0,%1,1" - [(set_attr "type" "arith") - (set_attr "mode" "DI")]) + "sltu\t%0,%1,1" + [(set_attr "type" "slt") + (set_attr "mode" "DI")]) -(define_insn "" +(define_insn "*seq_di_mips16" [(set (match_operand:DI 0 "register_operand" "=t") (eq:DI (match_operand:DI 1 "register_operand" "d") (const_int 0)))] "TARGET_64BIT && TARGET_MIPS16" - "sltu\\t%1,1" - [(set_attr "type" "arith") - (set_attr "mode" "DI")]) - -(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 && !TARGET_MIPS16" - "@ - xor\\t%0,%1,%2\;sltu\\t%0,%0,1 - xori\\t%0,%1,%2\;sltu\\t%0,%0,1" - [(set_attr "type" "arith") - (set_attr "mode" "SI") - (set_attr "length" "8")]) - -(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 && !TARGET_MIPS16 - && (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_insn "seq_di" - [(set (match_operand:DI 0 "register_operand" "=d,d") - (eq:DI (match_operand:DI 1 "register_operand" "%d,d") - (match_operand:DI 2 "uns_arith_operand" "d,K")))] - "TARGET_64BIT && TARGET_DEBUG_C_MODE && !TARGET_MIPS16" - "@ - xor\\t%0,%1,%2\;sltu\\t%0,%0,1 - xori\\t%0,%1,%2\;sltu\\t%0,%0,1" - [(set_attr "type" "arith") - (set_attr "mode" "DI") - (set_attr "length" "8")]) - -(define_split - [(set (match_operand:DI 0 "register_operand" "") - (eq:DI (match_operand:DI 1 "register_operand" "") - (match_operand:DI 2 "uns_arith_operand" "")))] - "TARGET_64BIT && TARGET_DEBUG_C_MODE && !TARGET_DEBUG_D_MODE - && !TARGET_MIPS16 - && (GET_CODE (operands[2]) != CONST_INT || INTVAL (operands[2]) != 0)" - [(set (match_dup 0) - (xor:DI (match_dup 1) - (match_dup 2))) - (set (match_dup 0) - (ltu:DI (match_dup 0) - (const_int 1)))] - "") + "sltu\t%1,1" + [(set_attr "type" "slt") + (set_attr "mode" "DI")]) -;; On the mips16 the default code is better than using sltu. +;; "sne" uses sltu instructions in which the first operand is $0. +;; This isn't possible in mips16 code. (define_expand "sne" - [(set (match_operand:SI 0 "register_operand" "=d") + [(set (match_operand:SI 0 "register_operand") (ne:SI (match_dup 1) (match_dup 2)))] "!TARGET_MIPS16" - " -{ - if (branch_type != CMP_SI && (!TARGET_64BIT || branch_type != CMP_DI)) - FAIL; - - /* set up operands from compare. */ - operands[1] = branch_cmp[0]; - operands[2] = branch_cmp[1]; - - if (TARGET_64BIT || !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]); + { if (mips_emit_scc (NE, operands[0])) DONE; else FAIL; }) - /* fall through and generate default code */ -}") - -(define_insn "sne_si_zero" +(define_insn "*sne_si" [(set (match_operand:SI 0 "register_operand" "=d") (ne:SI (match_operand:SI 1 "register_operand" "d") (const_int 0)))] "!TARGET_MIPS16" - "sltu\\t%0,%.,%1" - [(set_attr "type" "arith") - (set_attr "mode" "SI")]) + "sltu\t%0,%.,%1" + [(set_attr "type" "slt") + (set_attr "mode" "SI")]) -(define_insn "sne_di_zero" +(define_insn "*sne_di" [(set (match_operand:DI 0 "register_operand" "=d") (ne:DI (match_operand:DI 1 "register_operand" "d") (const_int 0)))] "TARGET_64BIT && !TARGET_MIPS16" - "sltu\\t%0,%.,%1" - [(set_attr "type" "arith") - (set_attr "mode" "DI")]) - -(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 && !TARGET_MIPS16" - "@ - xor\\t%0,%1,%2\;sltu\\t%0,%.,%0 - xori\\t%0,%1,%x2\;sltu\\t%0,%.,%0" - [(set_attr "type" "arith") - (set_attr "mode" "SI") - (set_attr "length" "8")]) - -(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 && !TARGET_MIPS16 - && (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_insn "sne_di" - [(set (match_operand:DI 0 "register_operand" "=d,d") - (ne:DI (match_operand:DI 1 "register_operand" "%d,d") - (match_operand:DI 2 "uns_arith_operand" "d,K")))] - "TARGET_64BIT && TARGET_DEBUG_C_MODE && !TARGET_MIPS16" - "@ - xor\\t%0,%1,%2\;sltu\\t%0,%.,%0 - xori\\t%0,%1,%x2\;sltu\\t%0,%.,%0" - [(set_attr "type" "arith") - (set_attr "mode" "DI") - (set_attr "length" "8")]) - -(define_split - [(set (match_operand:DI 0 "register_operand" "") - (ne:DI (match_operand:DI 1 "register_operand" "") - (match_operand:DI 2 "uns_arith_operand" "")))] - "TARGET_64BIT && TARGET_DEBUG_C_MODE && !TARGET_DEBUG_D_MODE - && !TARGET_MIPS16 - && (GET_CODE (operands[2]) != CONST_INT || INTVAL (operands[2]) != 0)" - [(set (match_dup 0) - (xor:DI (match_dup 1) - (match_dup 2))) - (set (match_dup 0) - (gtu:DI (match_dup 0) - (const_int 0)))] - "") + "sltu\t%0,%.,%1" + [(set_attr "type" "slt") + (set_attr "mode" "DI")]) (define_expand "sgt" - [(set (match_operand:SI 0 "register_operand" "=d") + [(set (match_operand:SI 0 "register_operand") (gt:SI (match_dup 1) (match_dup 2)))] "" - " -{ - if (branch_type != CMP_SI && (!TARGET_64BIT || branch_type != CMP_DI)) - FAIL; - - /* set up operands from compare. */ - operands[1] = branch_cmp[0]; - operands[2] = branch_cmp[1]; - - if (TARGET_64BIT || !TARGET_DEBUG_C_MODE || TARGET_MIPS16) - { - 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]); + { if (mips_emit_scc (GT, operands[0])) DONE; else FAIL; }) - /* fall through and generate default code */ -}") - -(define_insn "sgt_si" +(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")))] "!TARGET_MIPS16" - "slt\\t%0,%z2,%1" - [(set_attr "type" "arith") - (set_attr "mode" "SI")]) + "slt\t%0,%z2,%1" + [(set_attr "type" "slt") + (set_attr "mode" "SI")]) -(define_insn "" +(define_insn "*sgt_si_mips16" [(set (match_operand:SI 0 "register_operand" "=t") (gt:SI (match_operand:SI 1 "register_operand" "d") (match_operand:SI 2 "register_operand" "d")))] "TARGET_MIPS16" - "slt\\t%2,%1" - [(set_attr "type" "arith") - (set_attr "mode" "SI")]) + "slt\t%2,%1" + [(set_attr "type" "slt") + (set_attr "mode" "SI")]) -(define_insn "sgt_di" +(define_insn "*sgt_di" [(set (match_operand:DI 0 "register_operand" "=d") (gt:DI (match_operand:DI 1 "register_operand" "d") (match_operand:DI 2 "reg_or_0_operand" "dJ")))] "TARGET_64BIT && !TARGET_MIPS16" - "slt\\t%0,%z2,%1" - [(set_attr "type" "arith") - (set_attr "mode" "DI")]) + "slt\t%0,%z2,%1" + [(set_attr "type" "slt") + (set_attr "mode" "DI")]) -(define_insn "" - [(set (match_operand:DI 0 "register_operand" "=d") +(define_insn "*sgt_di_mips16" + [(set (match_operand:DI 0 "register_operand" "=t") (gt:DI (match_operand:DI 1 "register_operand" "d") (match_operand:DI 2 "register_operand" "d")))] "TARGET_64BIT && TARGET_MIPS16" - "slt\\t%2,%1" - [(set_attr "type" "arith") - (set_attr "mode" "DI")]) + "slt\t%2,%1" + [(set_attr "type" "slt") + (set_attr "mode" "DI")]) (define_expand "sge" - [(set (match_operand:SI 0 "register_operand" "=d") + [(set (match_operand:SI 0 "register_operand") (ge:SI (match_dup 1) (match_dup 2)))] "" - " -{ - if (branch_type != CMP_SI && (!TARGET_64BIT || branch_type != CMP_DI)) - FAIL; - - /* set up operands from compare. */ - operands[1] = branch_cmp[0]; - operands[2] = branch_cmp[1]; + { if (mips_emit_scc (GE, operands[0])) DONE; else FAIL; }) - if (TARGET_64BIT || !TARGET_DEBUG_C_MODE || TARGET_MIPS16) - { - gen_int_relational (GE, operands[0], operands[1], operands[2], (int *)0); - DONE; - } - - /* fall through and generate default code */ -}") - -(define_insn "sge_si" +(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 && !TARGET_MIPS16" - "slt\\t%0,%1,%2\;xori\\t%0,%0,0x0001" - [(set_attr "type" "arith") - (set_attr "mode" "SI") - (set_attr "length" "8")]) - -(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 && !TARGET_MIPS16" - [(set (match_dup 0) - (lt:SI (match_dup 1) - (match_dup 2))) - (set (match_dup 0) - (xor:SI (match_dup 0) - (const_int 1)))] - "") + (const_int 1)))] + "!TARGET_MIPS16" + "slt\t%0,%.,%1" + [(set_attr "type" "slt") + (set_attr "mode" "SI")]) -(define_insn "sge_di" +(define_insn "*sge_di" [(set (match_operand:DI 0 "register_operand" "=d") (ge:DI (match_operand:DI 1 "register_operand" "d") - (match_operand:DI 2 "arith_operand" "dI")))] - "TARGET_64BIT && TARGET_DEBUG_C_MODE && !TARGET_MIPS16" - "slt\\t%0,%1,%2\;xori\\t%0,%0,0x0001" - [(set_attr "type" "arith") - (set_attr "mode" "DI") - (set_attr "length" "8")]) - -(define_split - [(set (match_operand:DI 0 "register_operand" "") - (ge:DI (match_operand:DI 1 "register_operand" "") - (match_operand:DI 2 "arith_operand" "")))] - "TARGET_64BIT && TARGET_DEBUG_C_MODE && !TARGET_DEBUG_D_MODE - && !TARGET_MIPS16" - [(set (match_dup 0) - (lt:DI (match_dup 1) - (match_dup 2))) - (set (match_dup 0) - (xor:DI (match_dup 0) - (const_int 1)))] - "") + (const_int 1)))] + "TARGET_64BIT && !TARGET_MIPS16" + "slt\t%0,%.,%1" + [(set_attr "type" "slt") + (set_attr "mode" "DI")]) (define_expand "slt" - [(set (match_operand:SI 0 "register_operand" "=d") + [(set (match_operand:SI 0 "register_operand") (lt:SI (match_dup 1) (match_dup 2)))] "" - " -{ - if (branch_type != CMP_SI && (!TARGET_64BIT || branch_type != CMP_DI)) - FAIL; - - /* set up operands from compare. */ - operands[1] = branch_cmp[0]; - operands[2] = branch_cmp[1]; - - if (TARGET_64BIT || !TARGET_DEBUG_C_MODE || TARGET_MIPS16) - { - gen_int_relational (LT, operands[0], operands[1], operands[2], (int *)0); - DONE; - } - - /* fall through and generate default code */ -}") + { if (mips_emit_scc (LT, operands[0])) DONE; else FAIL; }) -(define_insn "slt_si" +(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")))] "!TARGET_MIPS16" - "slt\\t%0,%1,%2" - [(set_attr "type" "arith") - (set_attr "mode" "SI")]) + "slt\t%0,%1,%2" + [(set_attr "type" "slt") + (set_attr "mode" "SI")]) -(define_insn "" +(define_insn "*slt_si_mips16" [(set (match_operand:SI 0 "register_operand" "=t,t") (lt:SI (match_operand:SI 1 "register_operand" "d,d") (match_operand:SI 2 "arith_operand" "d,I")))] "TARGET_MIPS16" - "slt\\t%1,%2" - [(set_attr "type" "arith") - (set_attr "mode" "SI") + "slt\t%1,%2" + [(set_attr "type" "slt") + (set_attr "mode" "SI") (set_attr_alternative "length" [(const_int 4) - (if_then_else (match_operand:VOID 2 "m16_uimm8_1" "") + (if_then_else (match_operand:VOID 2 "m16_uimm8_1") (const_int 4) (const_int 8))])]) -(define_insn "slt_di" +(define_insn "*slt_di" [(set (match_operand:DI 0 "register_operand" "=d") (lt:DI (match_operand:DI 1 "register_operand" "d") (match_operand:DI 2 "arith_operand" "dI")))] "TARGET_64BIT && !TARGET_MIPS16" - "slt\\t%0,%1,%2" - [(set_attr "type" "arith") - (set_attr "mode" "DI")]) + "slt\t%0,%1,%2" + [(set_attr "type" "slt") + (set_attr "mode" "DI")]) -(define_insn "" +(define_insn "*slt_di_mips16" [(set (match_operand:DI 0 "register_operand" "=t,t") (lt:DI (match_operand:DI 1 "register_operand" "d,d") (match_operand:DI 2 "arith_operand" "d,I")))] "TARGET_64BIT && TARGET_MIPS16" - "slt\\t%1,%2" - [(set_attr "type" "arith") - (set_attr "mode" "DI") + "slt\t%1,%2" + [(set_attr "type" "slt") + (set_attr "mode" "DI") (set_attr_alternative "length" [(const_int 4) - (if_then_else (match_operand:VOID 2 "m16_uimm8_1" "") + (if_then_else (match_operand:VOID 2 "m16_uimm8_1") (const_int 4) (const_int 8))])]) (define_expand "sle" - [(set (match_operand:SI 0 "register_operand" "=d") + [(set (match_operand:SI 0 "register_operand") (le:SI (match_dup 1) (match_dup 2)))] "" - " -{ - if (branch_type != CMP_SI && (!TARGET_64BIT || branch_type != CMP_DI)) - FAIL; + { if (mips_emit_scc (LE, operands[0])) DONE; else FAIL; }) - /* set up operands from compare. */ - operands[1] = branch_cmp[0]; - operands[2] = branch_cmp[1]; - - if (TARGET_64BIT || !TARGET_DEBUG_C_MODE || TARGET_MIPS16) - { - 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" +(define_insn "*sle_si" [(set (match_operand:SI 0 "register_operand" "=d") (le:SI (match_operand:SI 1 "register_operand" "d") - (match_operand:SI 2 "small_int" "I")))] - "!TARGET_MIPS16 && INTVAL (operands[2]) < 32767" - "* + (match_operand:SI 2 "sle_operand" "")))] + "!TARGET_MIPS16" { - operands[2] = GEN_INT (INTVAL (operands[2])+1); - return \"slt\\t%0,%1,%2\"; -}" - [(set_attr "type" "arith") - (set_attr "mode" "SI")]) + operands[2] = GEN_INT (INTVAL (operands[2]) + 1); + return "slt\t%0,%1,%2"; +} + [(set_attr "type" "slt") + (set_attr "mode" "SI")]) -(define_insn "" +(define_insn "*sle_si_mips16" [(set (match_operand:SI 0 "register_operand" "=t") (le:SI (match_operand:SI 1 "register_operand" "d") - (match_operand:SI 2 "small_int" "I")))] - "TARGET_MIPS16 && INTVAL (operands[2]) < 32767" - "* + (match_operand:SI 2 "sle_operand" "")))] + "TARGET_MIPS16" { - operands[2] = GEN_INT (INTVAL (operands[2])+1); - return \"slt\\t%1,%2\"; -}" - [(set_attr "type" "arith") - (set_attr "mode" "SI") - (set (attr "length") (if_then_else (match_operand:VOID 2 "m16_uimm8_m1_1" "") + operands[2] = GEN_INT (INTVAL (operands[2]) + 1); + return "slt\t%1,%2"; +} + [(set_attr "type" "slt") + (set_attr "mode" "SI") + (set (attr "length") (if_then_else (match_operand:VOID 2 "m16_uimm8_m1_1") (const_int 4) (const_int 8)))]) -(define_insn "sle_di_const" +(define_insn "*sle_di" [(set (match_operand:DI 0 "register_operand" "=d") (le:DI (match_operand:DI 1 "register_operand" "d") - (match_operand:DI 2 "small_int" "I")))] - "TARGET_64BIT && !TARGET_MIPS16 && INTVAL (operands[2]) < 32767" - "* + (match_operand:DI 2 "sle_operand" "")))] + "TARGET_64BIT && !TARGET_MIPS16" { - operands[2] = GEN_INT (INTVAL (operands[2])+1); - return \"slt\\t%0,%1,%2\"; -}" - [(set_attr "type" "arith") - (set_attr "mode" "DI")]) + operands[2] = GEN_INT (INTVAL (operands[2]) + 1); + return "slt\t%0,%1,%2"; +} + [(set_attr "type" "slt") + (set_attr "mode" "DI")]) -(define_insn "" +(define_insn "*sle_di_mips16" [(set (match_operand:DI 0 "register_operand" "=t") (le:DI (match_operand:DI 1 "register_operand" "d") - (match_operand:DI 2 "small_int" "I")))] - "TARGET_64BIT && TARGET_MIPS16 && INTVAL (operands[2]) < 32767" - "* + (match_operand:DI 2 "sle_operand" "")))] + "TARGET_64BIT && TARGET_MIPS16" { - operands[2] = GEN_INT (INTVAL (operands[2])+1); - return \"slt\\t%1,%2\"; -}" - [(set_attr "type" "arith") - (set_attr "mode" "DI") - (set (attr "length") (if_then_else (match_operand:VOID 2 "m16_uimm8_m1_1" "") + operands[2] = GEN_INT (INTVAL (operands[2]) + 1); + return "slt\t%1,%2"; +} + [(set_attr "type" "slt") + (set_attr "mode" "DI") + (set (attr "length") (if_then_else (match_operand:VOID 2 "m16_uimm8_m1_1") (const_int 4) (const_int 8)))]) -(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 && !TARGET_MIPS16" - "slt\\t%0,%z2,%1\;xori\\t%0,%0,0x0001" - [(set_attr "type" "arith") - (set_attr "mode" "SI") - (set_attr "length" "8")]) - -(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 && !TARGET_MIPS16" - [(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_insn "sle_di_reg" - [(set (match_operand:DI 0 "register_operand" "=d") - (le:DI (match_operand:DI 1 "register_operand" "d") - (match_operand:DI 2 "register_operand" "d")))] - "TARGET_64BIT && TARGET_DEBUG_C_MODE && !TARGET_MIPS16" - "slt\\t%0,%z2,%1\;xori\\t%0,%0,0x0001" - [(set_attr "type" "arith") - (set_attr "mode" "DI") - (set_attr "length" "8")]) - -(define_split - [(set (match_operand:DI 0 "register_operand" "") - (le:DI (match_operand:DI 1 "register_operand" "") - (match_operand:DI 2 "register_operand" "")))] - "TARGET_64BIT && TARGET_DEBUG_C_MODE && !TARGET_DEBUG_D_MODE - && !TARGET_MIPS16" - [(set (match_dup 0) - (lt:DI (match_dup 2) - (match_dup 1))) - (set (match_dup 0) - (xor:DI (match_dup 0) - (const_int 1)))] - "") - (define_expand "sgtu" - [(set (match_operand:SI 0 "register_operand" "=d") + [(set (match_operand:SI 0 "register_operand") (gtu:SI (match_dup 1) (match_dup 2)))] "" - " -{ - if (branch_type != CMP_SI && (!TARGET_64BIT || branch_type != CMP_DI)) - FAIL; - - /* set up operands from compare. */ - operands[1] = branch_cmp[0]; - operands[2] = branch_cmp[1]; - - if (TARGET_64BIT || !TARGET_DEBUG_C_MODE || TARGET_MIPS16) - { - 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]); + { if (mips_emit_scc (GTU, operands[0])) DONE; else FAIL; }) - /* fall through and generate default code */ -}") - -(define_insn "sgtu_si" +(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")))] "!TARGET_MIPS16" - "sltu\\t%0,%z2,%1" - [(set_attr "type" "arith") - (set_attr "mode" "SI")]) + "sltu\t%0,%z2,%1" + [(set_attr "type" "slt") + (set_attr "mode" "SI")]) -(define_insn "" +(define_insn "*sgtu_si_mips16" [(set (match_operand:SI 0 "register_operand" "=t") (gtu:SI (match_operand:SI 1 "register_operand" "d") (match_operand:SI 2 "register_operand" "d")))] "TARGET_MIPS16" - "sltu\\t%2,%1" - [(set_attr "type" "arith") - (set_attr "mode" "SI")]) + "sltu\t%2,%1" + [(set_attr "type" "slt") + (set_attr "mode" "SI")]) -(define_insn "sgtu_di" +(define_insn "*sgtu_di" [(set (match_operand:DI 0 "register_operand" "=d") (gtu:DI (match_operand:DI 1 "register_operand" "d") (match_operand:DI 2 "reg_or_0_operand" "dJ")))] "TARGET_64BIT && !TARGET_MIPS16" - "sltu\\t%0,%z2,%1" - [(set_attr "type" "arith") - (set_attr "mode" "DI")]) + "sltu\t%0,%z2,%1" + [(set_attr "type" "slt") + (set_attr "mode" "DI")]) -(define_insn "" +(define_insn "*sgtu_di_mips16" [(set (match_operand:DI 0 "register_operand" "=t") (gtu:DI (match_operand:DI 1 "register_operand" "d") (match_operand:DI 2 "register_operand" "d")))] "TARGET_64BIT && TARGET_MIPS16" - "sltu\\t%2,%1" - [(set_attr "type" "arith") - (set_attr "mode" "DI")]) + "sltu\t%2,%1" + [(set_attr "type" "slt") + (set_attr "mode" "DI")]) (define_expand "sgeu" - [(set (match_operand:SI 0 "register_operand" "=d") + [(set (match_operand:SI 0 "register_operand") (geu:SI (match_dup 1) (match_dup 2)))] "" - " -{ - if (branch_type != CMP_SI && (!TARGET_64BIT || branch_type != CMP_DI)) - FAIL; - - /* set up operands from compare. */ - operands[1] = branch_cmp[0]; - operands[2] = branch_cmp[1]; - - if (TARGET_64BIT || !TARGET_DEBUG_C_MODE || TARGET_MIPS16) - { - gen_int_relational (GEU, operands[0], operands[1], operands[2], (int *)0); - DONE; - } - - /* fall through and generate default code */ -}") + { if (mips_emit_scc (GEU, operands[0])) DONE; else FAIL; }) -(define_insn "sgeu_si" +(define_insn "*sge_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 && !TARGET_MIPS16" - "sltu\\t%0,%1,%2\;xori\\t%0,%0,0x0001" - [(set_attr "type" "arith") - (set_attr "mode" "SI") - (set_attr "length" "8")]) - -(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 && !TARGET_MIPS16" - [(set (match_dup 0) - (ltu:SI (match_dup 1) - (match_dup 2))) - (set (match_dup 0) - (xor:SI (match_dup 0) - (const_int 1)))] - "") + (const_int 1)))] + "!TARGET_MIPS16" + "sltu\t%0,%.,%1" + [(set_attr "type" "slt") + (set_attr "mode" "SI")]) -(define_insn "sgeu_di" +(define_insn "*sge_di" [(set (match_operand:DI 0 "register_operand" "=d") (geu:DI (match_operand:DI 1 "register_operand" "d") - (match_operand:DI 2 "arith_operand" "dI")))] - "TARGET_64BIT && TARGET_DEBUG_C_MODE && !TARGET_MIPS16" - "sltu\\t%0,%1,%2\;xori\\t%0,%0,0x0001" - [(set_attr "type" "arith") - (set_attr "mode" "DI") - (set_attr "length" "8")]) - -(define_split - [(set (match_operand:DI 0 "register_operand" "") - (geu:DI (match_operand:DI 1 "register_operand" "") - (match_operand:DI 2 "arith_operand" "")))] - "TARGET_64BIT && TARGET_DEBUG_C_MODE && !TARGET_DEBUG_D_MODE - && !TARGET_MIPS16" - [(set (match_dup 0) - (ltu:DI (match_dup 1) - (match_dup 2))) - (set (match_dup 0) - (xor:DI (match_dup 0) - (const_int 1)))] - "") + (const_int 1)))] + "TARGET_64BIT && !TARGET_MIPS16" + "sltu\t%0,%.,%1" + [(set_attr "type" "slt") + (set_attr "mode" "DI")]) (define_expand "sltu" - [(set (match_operand:SI 0 "register_operand" "=d") + [(set (match_operand:SI 0 "register_operand") (ltu:SI (match_dup 1) (match_dup 2)))] "" - " -{ - if (branch_type != CMP_SI && (!TARGET_64BIT || branch_type != CMP_DI)) - FAIL; - - /* set up operands from compare. */ - operands[1] = branch_cmp[0]; - operands[2] = branch_cmp[1]; - - if (TARGET_64BIT || !TARGET_DEBUG_C_MODE || TARGET_MIPS16) - { - gen_int_relational (LTU, operands[0], operands[1], operands[2], (int *)0); - DONE; - } + { if (mips_emit_scc (LTU, operands[0])) DONE; else FAIL; }) - /* fall through and generate default code */ -}") - -(define_insn "sltu_si" +(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")))] "!TARGET_MIPS16" - "sltu\\t%0,%1,%2" - [(set_attr "type" "arith") - (set_attr "mode" "SI")]) + "sltu\t%0,%1,%2" + [(set_attr "type" "slt") + (set_attr "mode" "SI")]) -(define_insn "" +(define_insn "*sltu_si_mips16" [(set (match_operand:SI 0 "register_operand" "=t,t") (ltu:SI (match_operand:SI 1 "register_operand" "d,d") (match_operand:SI 2 "arith_operand" "d,I")))] "TARGET_MIPS16" - "sltu\\t%1,%2" - [(set_attr "type" "arith") - (set_attr "mode" "SI") + "sltu\t%1,%2" + [(set_attr "type" "slt") + (set_attr "mode" "SI") (set_attr_alternative "length" [(const_int 4) - (if_then_else (match_operand:VOID 2 "m16_uimm8_1" "") + (if_then_else (match_operand:VOID 2 "m16_uimm8_1") (const_int 4) (const_int 8))])]) -(define_insn "sltu_di" +(define_insn "*sltu_di" [(set (match_operand:DI 0 "register_operand" "=d") (ltu:DI (match_operand:DI 1 "register_operand" "d") (match_operand:DI 2 "arith_operand" "dI")))] "TARGET_64BIT && !TARGET_MIPS16" - "sltu\\t%0,%1,%2" - [(set_attr "type" "arith") - (set_attr "mode" "DI")]) + "sltu\t%0,%1,%2" + [(set_attr "type" "slt") + (set_attr "mode" "DI")]) -(define_insn "" +(define_insn "*sltu_di_mips16" [(set (match_operand:DI 0 "register_operand" "=t,t") (ltu:DI (match_operand:DI 1 "register_operand" "d,d") (match_operand:DI 2 "arith_operand" "d,I")))] "TARGET_64BIT && TARGET_MIPS16" - "sltu\\t%1,%2" - [(set_attr "type" "arith") - (set_attr "mode" "DI") + "sltu\t%1,%2" + [(set_attr "type" "slt") + (set_attr "mode" "DI") (set_attr_alternative "length" [(const_int 4) - (if_then_else (match_operand:VOID 2 "m16_uimm8_1" "") + (if_then_else (match_operand:VOID 2 "m16_uimm8_1") (const_int 4) (const_int 8))])]) (define_expand "sleu" - [(set (match_operand:SI 0 "register_operand" "=d") + [(set (match_operand:SI 0 "register_operand") (leu:SI (match_dup 1) (match_dup 2)))] "" - " -{ - if (branch_type != CMP_SI && (!TARGET_64BIT || branch_type != CMP_DI)) - FAIL; - - /* set up operands from compare. */ - operands[1] = branch_cmp[0]; - operands[2] = branch_cmp[1]; - - if (TARGET_64BIT || !TARGET_DEBUG_C_MODE || TARGET_MIPS16) - { - gen_int_relational (LEU, operands[0], operands[1], operands[2], (int *)0); - DONE; - } + { if (mips_emit_scc (LEU, operands[0])) DONE; else FAIL; }) - 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" +(define_insn "*sleu_si" [(set (match_operand:SI 0 "register_operand" "=d") (leu:SI (match_operand:SI 1 "register_operand" "d") - (match_operand:SI 2 "small_int" "I")))] - "!TARGET_MIPS16 && INTVAL (operands[2]) < 32767" - "* + (match_operand:SI 2 "sleu_operand" "")))] + "!TARGET_MIPS16" { operands[2] = GEN_INT (INTVAL (operands[2]) + 1); - return \"sltu\\t%0,%1,%2\"; -}" - [(set_attr "type" "arith") - (set_attr "mode" "SI")]) + return "sltu\t%0,%1,%2"; +} + [(set_attr "type" "slt") + (set_attr "mode" "SI")]) -(define_insn "" +(define_insn "*sleu_si_mips16" [(set (match_operand:SI 0 "register_operand" "=t") (leu:SI (match_operand:SI 1 "register_operand" "d") - (match_operand:SI 2 "small_int" "I")))] - "TARGET_MIPS16 && INTVAL (operands[2]) < 32767" - "* -{ - operands[2] = GEN_INT (INTVAL (operands[2])+1); - return \"sltu\\t%1,%2\"; -}" - [(set_attr "type" "arith") - (set_attr "mode" "SI") - (set (attr "length") (if_then_else (match_operand:VOID 2 "m16_uimm8_m1_1" "") - (const_int 4) - (const_int 8)))]) - -(define_insn "sleu_di_const" - [(set (match_operand:DI 0 "register_operand" "=d") - (leu:DI (match_operand:DI 1 "register_operand" "d") - (match_operand:DI 2 "small_int" "I")))] - "TARGET_64BIT && !TARGET_MIPS16 && INTVAL (operands[2]) < 32767" - "* + (match_operand:SI 2 "sleu_operand" "")))] + "TARGET_MIPS16" { operands[2] = GEN_INT (INTVAL (operands[2]) + 1); - return \"sltu\\t%0,%1,%2\"; -}" - [(set_attr "type" "arith") - (set_attr "mode" "DI")]) - -(define_insn "" - [(set (match_operand:DI 0 "register_operand" "=t") - (leu:DI (match_operand:DI 1 "register_operand" "d") - (match_operand:DI 2 "small_int" "I")))] - "TARGET_64BIT && TARGET_MIPS16 && INTVAL (operands[2]) < 32767" - "* -{ - operands[2] = GEN_INT (INTVAL (operands[2])+1); - return \"sltu\\t%1,%2\"; -}" - [(set_attr "type" "arith") - (set_attr "mode" "DI") - (set (attr "length") (if_then_else (match_operand:VOID 2 "m16_uimm8_m1_1" "") + return "sltu\t%1,%2"; +} + [(set_attr "type" "slt") + (set_attr "mode" "SI") + (set (attr "length") (if_then_else (match_operand:VOID 2 "m16_uimm8_m1_1") (const_int 4) (const_int 8)))]) -(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 && !TARGET_MIPS16" - "sltu\\t%0,%z2,%1\;xori\\t%0,%0,0x0001" - [(set_attr "type" "arith") - (set_attr "mode" "SI") - (set_attr "length" "8")]) - -(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 && !TARGET_MIPS16" - [(set (match_dup 0) - (ltu:SI (match_dup 2) - (match_dup 1))) - (set (match_dup 0) - (xor:SI (match_dup 0) - (const_int 1)))] - "") - -(define_insn "sleu_di_reg" +(define_insn "*sleu_di" [(set (match_operand:DI 0 "register_operand" "=d") (leu:DI (match_operand:DI 1 "register_operand" "d") - (match_operand:DI 2 "register_operand" "d")))] - "TARGET_64BIT && TARGET_DEBUG_C_MODE && !TARGET_MIPS16" - "sltu\\t%0,%z2,%1\;xori\\t%0,%0,0x0001" - [(set_attr "type" "arith") - (set_attr "mode" "DI") - (set_attr "length" "8")]) - -(define_split - [(set (match_operand:DI 0 "register_operand" "") - (leu:DI (match_operand:DI 1 "register_operand" "") - (match_operand:DI 2 "register_operand" "")))] - "TARGET_64BIT && TARGET_DEBUG_C_MODE && !TARGET_DEBUG_D_MODE - && !TARGET_MIPS16" - [(set (match_dup 0) - (ltu:DI (match_dup 2) - (match_dup 1))) - (set (match_dup 0) - (xor:DI (match_dup 0) - (const_int 1)))] - "") + (match_operand:DI 2 "sleu_operand" "")))] + "TARGET_64BIT && !TARGET_MIPS16" +{ + operands[2] = GEN_INT (INTVAL (operands[2]) + 1); + return "sltu\t%0,%1,%2"; +} + [(set_attr "type" "slt") + (set_attr "mode" "DI")]) +(define_insn "*sleu_di_mips16" + [(set (match_operand:DI 0 "register_operand" "=t") + (leu:DI (match_operand:DI 1 "register_operand" "d") + (match_operand:DI 2 "sleu_operand" "")))] + "TARGET_64BIT && TARGET_MIPS16" +{ + operands[2] = GEN_INT (INTVAL (operands[2]) + 1); + return "sltu\t%1,%2"; +} + [(set_attr "type" "slt") + (set_attr "mode" "DI") + (set (attr "length") (if_then_else (match_operand:VOID 2 "m16_uimm8_m1_1") + (const_int 4) + (const_int 8)))]) ;; ;; .................... @@ -7996,7 +6635,6 @@ move\\t%0,%z4\\n\\ "c.le.s\t%Z0%2,%1" [(set_attr "type" "fcmp") (set_attr "mode" "FPSW")]) - ;; ;; .................... @@ -8011,30 +6649,28 @@ move\\t%0,%z4\\n\\ [(set (pc) (label_ref (match_operand 0 "" "")))] "!TARGET_MIPS16" - "* { - if (flag_pic && ! TARGET_EMBEDDED_PIC) + if (flag_pic) { if (get_attr_length (insn) <= 8) - return \"%*b\\t%l0%/\"; + return "%*b\t%l0%/"; else { output_asm_insn (mips_output_load_label (), operands); - return \"%*jr\\t%@%/%]\"; + return "%*jr\t%@%/%]"; } } else - return \"%*j\\t%l0%/\"; -}" + return "%*j\t%l0%/"; +} [(set_attr "type" "jump") (set_attr "mode" "none") (set (attr "length") - ;; we can't use `j' when emitting non-embedded PIC, so we emit - ;; branch, if it's in range, or load the address of the branch - ;; target into $at in a PIC-compatible way and then jump to it. + ;; We can't use `j' when emitting PIC. Emit a branch if it's + ;; in range, otherwise load the address of the branch target into + ;; $at and then jump to it. (if_then_else - (ior (eq (symbol_ref "flag_pic && ! TARGET_EMBEDDED_PIC") - (const_int 0)) + (ior (eq (symbol_ref "flag_pic") (const_int 0)) (lt (abs (minus (match_dup 0) (plus (pc) (const_int 4)))) (const_int 131072))) @@ -8047,32 +6683,28 @@ move\\t%0,%z4\\n\\ [(set (pc) (label_ref (match_operand 0 "" "")))] "TARGET_MIPS16" - "b\\t%l0" + "b\t%l0" [(set_attr "type" "branch") (set_attr "mode" "none") (set_attr "length" "8")]) (define_expand "indirect_jump" - [(set (pc) (match_operand 0 "register_operand" "d"))] + [(set (pc) (match_operand 0 "register_operand"))] "" - " { rtx dest; - if (operands[0]) /* eliminate unused code warnings */ - { - dest = operands[0]; - if (GET_CODE (dest) != REG || GET_MODE (dest) != Pmode) - operands[0] = copy_to_mode_reg (Pmode, dest); + dest = operands[0]; + if (GET_CODE (dest) != REG || GET_MODE (dest) != Pmode) + operands[0] = copy_to_mode_reg (Pmode, dest); - if (!(Pmode == DImode)) - emit_jump_insn (gen_indirect_jump_internal1 (operands[0])); - else - emit_jump_insn (gen_indirect_jump_internal2 (operands[0])); + if (!(Pmode == DImode)) + emit_jump_insn (gen_indirect_jump_internal1 (operands[0])); + else + emit_jump_insn (gen_indirect_jump_internal2 (operands[0])); - DONE; - } -}") + DONE; +}) (define_insn "indirect_jump_internal1" [(set (pc) (match_operand:SI 0 "register_operand" "d"))] @@ -8090,38 +6722,34 @@ move\\t%0,%z4\\n\\ (define_expand "tablejump" [(set (pc) - (match_operand 0 "register_operand" "d")) - (use (label_ref (match_operand 1 "" "")))] + (match_operand 0 "register_operand")) + (use (label_ref (match_operand 1 "")))] "" - " { - if (operands[0]) /* eliminate unused code warnings */ + if (TARGET_MIPS16) { - if (TARGET_MIPS16) - { - if (GET_MODE (operands[0]) != HImode) - abort (); - if (!(Pmode == DImode)) - emit_insn (gen_tablejump_mips161 (operands[0], operands[1])); - else - emit_insn (gen_tablejump_mips162 (operands[0], operands[1])); - DONE; - } - - if (GET_MODE (operands[0]) != ptr_mode) + if (GET_MODE (operands[0]) != HImode) abort (); - - if (TARGET_GPWORD) - operands[0] = expand_binop (ptr_mode, add_optab, operands[0], - pic_offset_table_rtx, 0, 0, OPTAB_WIDEN); - - if (Pmode == SImode) - emit_jump_insn (gen_tablejump_internal1 (operands[0], operands[1])); + if (!(Pmode == DImode)) + emit_insn (gen_tablejump_mips161 (operands[0], operands[1])); else - emit_jump_insn (gen_tablejump_internal2 (operands[0], operands[1])); + emit_insn (gen_tablejump_mips162 (operands[0], operands[1])); DONE; } -}") + + if (GET_MODE (operands[0]) != ptr_mode) + abort (); + + if (TARGET_GPWORD) + operands[0] = expand_binop (ptr_mode, add_optab, operands[0], + pic_offset_table_rtx, 0, 0, OPTAB_WIDEN); + + if (Pmode == SImode) + emit_jump_insn (gen_tablejump_internal1 (operands[0], operands[1])); + else + emit_jump_insn (gen_tablejump_internal2 (operands[0], operands[1])); + DONE; +}) (define_insn "tablejump_internal1" [(set (pc) @@ -8142,139 +6770,38 @@ move\\t%0,%z4\\n\\ (set_attr "mode" "none")]) (define_expand "tablejump_mips161" - [(set (pc) (plus:SI (sign_extend:SI - (match_operand:HI 0 "register_operand" "d")) - (label_ref:SI (match_operand 1 "" ""))))] + [(set (pc) (plus:SI (sign_extend:SI (match_operand:HI 0 "register_operand")) + (label_ref:SI (match_operand 1 ""))))] "TARGET_MIPS16 && !(Pmode == DImode)" - " { - if (operands[0]) /* eliminate unused code warnings. */ - { - rtx t1, t2, t3; - - t1 = gen_reg_rtx (SImode); - t2 = gen_reg_rtx (SImode); - t3 = gen_reg_rtx (SImode); - emit_insn (gen_extendhisi2 (t1, operands[0])); - emit_move_insn (t2, gen_rtx_LABEL_REF (SImode, operands[1])); - emit_insn (gen_addsi3 (t3, t1, t2)); - emit_jump_insn (gen_tablejump_internal1 (t3, operands[1])); - DONE; - } -}") + rtx t1, t2, t3; + + t1 = gen_reg_rtx (SImode); + t2 = gen_reg_rtx (SImode); + t3 = gen_reg_rtx (SImode); + emit_insn (gen_extendhisi2 (t1, operands[0])); + emit_move_insn (t2, gen_rtx_LABEL_REF (SImode, operands[1])); + emit_insn (gen_addsi3 (t3, t1, t2)); + emit_jump_insn (gen_tablejump_internal1 (t3, operands[1])); + DONE; +}) (define_expand "tablejump_mips162" - [(set (pc) (plus:DI (sign_extend:DI - (match_operand:HI 0 "register_operand" "d")) - (label_ref:DI (match_operand 1 "" ""))))] + [(set (pc) (plus:DI (sign_extend:DI (match_operand:HI 0 "register_operand")) + (label_ref:DI (match_operand 1 ""))))] "TARGET_MIPS16 && Pmode == DImode" - " { - if (operands[0]) /* eliminate unused code warnings. */ - { - rtx t1, t2, t3; - - t1 = gen_reg_rtx (DImode); - t2 = gen_reg_rtx (DImode); - t3 = gen_reg_rtx (DImode); - emit_insn (gen_extendhidi2 (t1, operands[0])); - emit_move_insn (t2, gen_rtx_LABEL_REF (DImode, operands[1])); - emit_insn (gen_adddi3 (t3, t1, t2)); - emit_jump_insn (gen_tablejump_internal2 (t3, operands[1])); - DONE; - } -}") - -;; Implement a switch statement when generating embedded PIC code. -;; Switches are implemented by `tablejump' when not using -membedded-pic. - -(define_expand "casesi" - [(set (match_dup 5) - (minus:SI (match_operand:SI 0 "register_operand" "") - (match_operand:SI 1 "const_int_operand" ""))) - (set (cc0) - (compare:CC (match_dup 5) - (match_operand:SI 2 "arith_operand" ""))) - (set (pc) - (if_then_else (gtu (cc0) - (const_int 0)) - (label_ref (match_operand 4 "" "")) - (pc))) - (parallel - [(set (pc) - (mem:SI (plus:SI (mult:SI (match_dup 5) - (const_int 4)) - (label_ref (match_operand 3 "" ""))))) - (clobber (match_scratch:SI 6 "")) - (clobber (reg:SI 31))])] - "TARGET_EMBEDDED_PIC" - " -{ - if (operands[0]) - { - rtx index; - - /* If the index is too large, go to the default label. */ - index = expand_binop (SImode, sub_optab, operands[0], - operands[1], 0, 0, OPTAB_WIDEN); - emit_insn (gen_cmpsi (index, operands[2])); - emit_insn (gen_bgtu (operands[4])); - - /* Do the PIC jump. */ - if (Pmode != DImode) - emit_jump_insn (gen_casesi_internal (index, operands[3], - gen_reg_rtx (SImode))); - else - emit_jump_insn (gen_casesi_internal_di (index, operands[3], - gen_reg_rtx (DImode))); + rtx t1, t2, t3; - DONE; - } -}") - -;; An embedded PIC switch statement looks like this: -;; bal $LS1 -;; sll $reg,$index,2 -;; $LS1: -;; addu $reg,$reg,$31 -;; lw $reg,$L1-$LS1($reg) -;; addu $reg,$reg,$31 -;; j $reg -;; $L1: -;; .word case1-$LS1 -;; .word case2-$LS1 -;; ... - -(define_insn "casesi_internal" - [(set (pc) - (mem:SI (plus:SI (mult:SI (match_operand:SI 0 "register_operand" "d") - (const_int 4)) - (label_ref (match_operand 1 "" ""))))) - (clobber (match_operand:SI 2 "register_operand" "=d")) - (clobber (reg:SI 31))] - "TARGET_EMBEDDED_PIC" - "%(bal\\t%S1\;sll\\t%2,%0,2\\n%~%S1:\;addu\\t%2,%2,$31%)\;\\ -lw\\t%2,%1-%S1(%2)\;addu\\t%2,%2,$31\\n\\t%*j\\t%2%/" - [(set_attr "type" "jump") - (set_attr "mode" "none") - (set_attr "length" "24")]) - -;; This code assumes that the table index will never be >= 29 bits wide, -;; which allows the 'sign extend' from SI to DI be a no-op. -(define_insn "casesi_internal_di" - [(set (pc) - (mem:DI (plus:DI (sign_extend:DI - (mult:SI (match_operand:SI 0 "register_operand" "d") - (const_int 8))) - (label_ref (match_operand 1 "" ""))))) - (clobber (match_operand:DI 2 "register_operand" "=d")) - (clobber (reg:DI 31))] - "TARGET_EMBEDDED_PIC" - "%(bal\\t%S1\;sll\\t%2,%0,3\\n%~%S1:\;daddu\\t%2,%2,$31%)\;\\ -ld\\t%2,%1-%S1(%2)\;daddu\\t%2,%2,$31\\n\\t%*j\\t%2%/" - [(set_attr "type" "jump") - (set_attr "mode" "none") - (set_attr "length" "24")]) + t1 = gen_reg_rtx (DImode); + t2 = gen_reg_rtx (DImode); + t3 = gen_reg_rtx (DImode); + emit_insn (gen_extendhidi2 (t1, operands[0])); + emit_move_insn (t2, gen_rtx_LABEL_REF (DImode, operands[1])); + emit_insn (gen_adddi3 (t3, t1, t2)); + emit_jump_insn (gen_tablejump_internal2 (t3, operands[1])); + DONE; +}) ;; For TARGET_ABICALLS, we save the gp in the jmp_buf as well. ;; While it is possible to either pull it off the stack (in the @@ -8282,24 +6809,23 @@ ld\\t%2,%1-%S1(%2)\;daddu\\t%2,%2,$31\\n\\t%*j\\t%2%/" ;; it takes 3 or 4 insns to do so. (define_expand "builtin_setjmp_setup" - [(use (match_operand 0 "register_operand" ""))] + [(use (match_operand 0 "register_operand"))] "TARGET_ABICALLS" - { - rtx addr; +{ + rtx addr; - addr = plus_constant (operands[0], GET_MODE_SIZE (Pmode) * 3); - emit_move_insn (gen_rtx_MEM (Pmode, addr), pic_offset_table_rtx); - DONE; - }) + addr = plus_constant (operands[0], GET_MODE_SIZE (Pmode) * 3); + emit_move_insn (gen_rtx_MEM (Pmode, addr), pic_offset_table_rtx); + DONE; +}) -;; Restore the gp that we saved above. Despite the comment, it seems that -;; older code did recalculate the gp from $25. Continue to jump through +;; Restore the gp that we saved above. Despite the earlier comment, it seems +;; that older code did recalculate the gp from $25. Continue to jump through ;; $25 for compatibility (we lose nothing by doing so). (define_expand "builtin_longjmp" - [(use (match_operand 0 "register_operand" "r"))] + [(use (match_operand 0 "register_operand"))] "TARGET_ABICALLS" - " { /* The elements of the buffer are, in order: */ int W = GET_MODE_SIZE (Pmode); @@ -8324,7 +6850,7 @@ ld\\t%2,%1-%S1(%2)\;daddu\\t%2,%2,$31\\n\\t%*j\\t%2%/" emit_insn (gen_rtx_USE (VOIDmode, gp)); emit_indirect_jump (pv); DONE; -}") +}) ;; ;; .................... @@ -8337,14 +6863,10 @@ ld\\t%2,%1-%S1(%2)\;daddu\\t%2,%2,$31\\n\\t%*j\\t%2%/" (define_expand "prologue" [(const_int 1)] "" - " { - if (mips_isa >= 0) /* avoid unused code warnings */ - { - mips_expand_prologue (); - DONE; - } -}") + mips_expand_prologue (); + DONE; +}) ;; Block any insns from being moved before this point, since the ;; profiling call to mcount can use various registers that aren't @@ -8375,7 +6897,8 @@ ld\\t%2,%1-%S1(%2)\;daddu\\t%2,%2,$31\\n\\t%*j\\t%2%/" }) ;; Trivial return. Make it look like a normal return insn as that -;; allows jump optimizations to work better . +;; allows jump optimizations to work better. + (define_insn "return" [(return)] "mips_can_use_return_insn ()" @@ -8386,32 +6909,17 @@ ld\\t%2,%1-%S1(%2)\;daddu\\t%2,%2,$31\\n\\t%*j\\t%2%/" ;; Normal return. (define_insn "return_internal" - [(use (match_operand 0 "pmode_register_operand" "")) - (return)] + [(return) + (use (match_operand 0 "pmode_register_operand" ""))] "" "%*j\t%0%/" [(set_attr "type" "jump") (set_attr "mode" "none")]) -;; When generating embedded PIC code we need to get the address of the -;; current function. This specialized instruction does just that. - -(define_insn "get_fnaddr" - [(set (match_operand 0 "register_operand" "=d") - (unspec [(match_operand 1 "" "")] UNSPEC_GET_FNADDR)) - (clobber (reg:SI 31))] - "TARGET_EMBEDDED_PIC - && GET_CODE (operands[1]) == SYMBOL_REF" - "%($LF%= = . + 8\;bal\\t$LF%=\;nop;la\\t%0,%1-$LF%=%)\;addu\\t%0,%0,$31" - [(set_attr "type" "call") - (set_attr "mode" "none") - (set_attr "length" "20")]) - ;; This is used in compiling the unwind routines. (define_expand "eh_return" - [(use (match_operand 0 "general_operand" ""))] + [(use (match_operand 0 "general_operand"))] "" - " { enum machine_mode gpr_mode = TARGET_64BIT ? DImode : SImode; @@ -8423,7 +6931,7 @@ ld\\t%2,%1-%S1(%2)\;daddu\\t%2,%2,$31\\n\\t%*j\\t%2%/" emit_insn (gen_eh_set_lr_si (operands[0])); DONE; -}") +}) ;; Clobber the return address on the stack. We can't expand this ;; until we know where it will be put in the stack frame. @@ -8441,23 +6949,28 @@ ld\\t%2,%1-%S1(%2)\;daddu\\t%2,%2,$31\\n\\t%*j\\t%2%/" "#") (define_split - [(unspec [(match_operand 0 "register_operand" "")] UNSPEC_EH_RETURN) - (clobber (match_scratch 1 ""))] + [(unspec [(match_operand 0 "register_operand")] UNSPEC_EH_RETURN) + (clobber (match_scratch 1))] "reload_completed && !TARGET_DEBUG_D_MODE" [(const_int 0)] - " { mips_set_return_address (operands[0], operands[1]); DONE; -}") +}) -(define_insn "exception_receiver" +(define_insn_and_split "exception_receiver" [(set (reg:SI 28) - (unspec_volatile [(const_int 0)] UNSPEC_EH_RECEIVER))] - "TARGET_ABICALLS && (mips_abi == ABI_32 || mips_abi == ABI_O64)" - { return mips_restore_gp (operands); } + (unspec_volatile:SI [(const_int 0)] UNSPEC_EH_RECEIVER))] + "TARGET_ABICALLS && TARGET_OLDABI" + "#" + "&& reload_completed" + [(const_int 0)] +{ + mips_restore_gp (); + DONE; +} [(set_attr "type" "load") - (set_attr "length" "8")]) + (set_attr "length" "12")]) ;; ;; .................... @@ -8466,11 +6979,48 @@ ld\\t%2,%1-%S1(%2)\;daddu\\t%2,%2,$31\\n\\t%*j\\t%2%/" ;; ;; .................... -;; Sibling calls. All these patterns use direct jumps. +;; Instructions to load a call address from the GOT. The address might +;; point to a function or to a lazy binding stub. In the latter case, +;; the stub will use the dynamic linker to resolve the function, which +;; in turn will change the GOT entry to point to the function's real +;; address. +;; +;; This means that every call, even pure and constant ones, can +;; potentially modify the GOT entry. And once a stub has been called, +;; we must not call it again. +;; +;; We represent this restriction using an imaginary fixed register that +;; acts like a GOT version number. By making the register call-clobbered, +;; we tell the target-independent code that the address could be changed +;; by any call insn. +(define_insn "load_callsi" + [(set (match_operand:SI 0 "register_operand" "=c") + (unspec:SI [(match_operand:SI 1 "register_operand" "r") + (match_operand:SI 2 "immediate_operand" "") + (reg:SI FAKE_CALL_REGNO)] + UNSPEC_LOAD_CALL))] + "TARGET_ABICALLS" + "lw\t%0,%R2(%1)" + [(set_attr "type" "load") + (set_attr "length" "4")]) + +(define_insn "load_calldi" + [(set (match_operand:DI 0 "register_operand" "=c") + (unspec:DI [(match_operand:DI 1 "register_operand" "r") + (match_operand:DI 2 "immediate_operand" "") + (reg:DI FAKE_CALL_REGNO)] + UNSPEC_LOAD_CALL))] + "TARGET_ABICALLS" + "ld\t%0,%R2(%1)" + [(set_attr "type" "load") + (set_attr "length" "4")]) + +;; Sibling calls. All these patterns use jump instructions. -;; call_insn_operand will only accepts constant addresses if a direct -;; jump is acceptable. Since the 'S' constraint is defined in terms of -;; call_insn_operand, the same is true of the constraints. +;; If TARGET_SIBCALLS, call_insn_operand will only accept constant +;; addresses if a direct jump is acceptable. Since the 'S' constraint +;; is defined in terms of call_insn_operand, the same is true of the +;; constraints. ;; When we use an indirect jump, we need a register that will be ;; preserved by the epilogue. Since TARGET_ABICALLS forces us to @@ -8478,10 +7028,10 @@ ld\\t%2,%1-%S1(%2)\;daddu\\t%2,%2,$31\\n\\t%*j\\t%2%/" ;; epilogue -- we might as well use it for !TARGET_ABICALLS as well. (define_expand "sibcall" - [(parallel [(call (match_operand 0 "" "") - (match_operand 1 "" "")) - (use (match_operand 2 "" "")) ;; next_arg_reg - (use (match_operand 3 "" ""))])] ;; struct_value_size_rtx + [(parallel [(call (match_operand 0 "") + (match_operand 1 "")) + (use (match_operand 2 "")) ;; next_arg_reg + (use (match_operand 3 ""))])] ;; struct_value_size_rtx "TARGET_SIBCALLS" { mips_expand_call (0, XEXP (operands[0], 0), operands[1], operands[2], true); @@ -8498,10 +7048,10 @@ ld\\t%2,%1-%S1(%2)\;daddu\\t%2,%2,$31\\n\\t%*j\\t%2%/" [(set_attr "type" "call")]) (define_expand "sibcall_value" - [(parallel [(set (match_operand 0 "" "") - (call (match_operand 1 "" "") - (match_operand 2 "" ""))) - (use (match_operand 3 "" ""))])] ;; next_arg_reg + [(parallel [(set (match_operand 0 "") + (call (match_operand 1 "") + (match_operand 2 ""))) + (use (match_operand 3 ""))])] ;; next_arg_reg "TARGET_SIBCALLS" { mips_expand_call (operands[0], XEXP (operands[1], 0), @@ -8533,29 +7083,67 @@ ld\\t%2,%1-%S1(%2)\;daddu\\t%2,%2,$31\\n\\t%*j\\t%2%/" [(set_attr "type" "call")]) (define_expand "call" - [(parallel [(call (match_operand 0 "" "") - (match_operand 1 "" "")) - (use (match_operand 2 "" "")) ;; next_arg_reg - (use (match_operand 3 "" ""))])] ;; struct_value_size_rtx + [(parallel [(call (match_operand 0 "") + (match_operand 1 "")) + (use (match_operand 2 "")) ;; next_arg_reg + (use (match_operand 3 ""))])] ;; struct_value_size_rtx "" { mips_expand_call (0, XEXP (operands[0], 0), operands[1], operands[2], false); DONE; }) +;; This instruction directly corresponds to an assembly-language "jal". +;; There are four cases: +;; +;; - -mno-abicalls: +;; Both symbolic and register destinations are OK. The pattern +;; always expands to a single mips instruction. +;; +;; - -mabicalls/-mno-explicit-relocs: +;; Again, both symbolic and register destinations are OK. +;; The call is treated as a multi-instruction black box. +;; +;; - -mabicalls/-mexplicit-relocs with n32 or n64: +;; Only "jal $25" is allowed. This expands to a single "jalr $25" +;; instruction. +;; +;; - -mabicalls/-mexplicit-relocs with o32 or o64: +;; Only "jal $25" is allowed. The call is actually two instructions: +;; "jalr $25" followed by an insn to reload $gp. +;; +;; In the last case, we can generate the individual instructions with +;; a define_split. There are several things to be wary of: +;; +;; - We can't expose the load of $gp before reload. If we did, +;; it might get removed as dead, but reload can introduce new +;; uses of $gp by rematerializing constants. +;; +;; - We shouldn't restore $gp after calls that never return. +;; It isn't valid to insert instructions between a noreturn +;; call and the following barrier. +;; +;; - The splitter deliberately changes the liveness of $gp. The unsplit +;; instruction preserves $gp and so have no effect on its liveness. +;; But once we generate the separate insns, it becomes obvious that +;; $gp is not live on entry to the call. +;; +;; ??? The operands[2] = insn check is a hack to make the original insn +;; available to the splitter. (define_insn_and_split "call_internal" [(call (mem:SI (match_operand 0 "call_insn_operand" "c,S")) (match_operand 1 "" "")) (clobber (reg:SI 31))] "" - "%*jal\t%0%/" - "reload_completed && TARGET_SPLIT_CALLS" + { return TARGET_SPLIT_CALLS ? "#" : "%*jal\t%0%/"; } + "reload_completed && TARGET_SPLIT_CALLS && (operands[2] = insn)" [(const_int 0)] - { - emit_call_insn (gen_call_split (operands[0], operands[1])); - emit_insn (gen_exception_receiver ()); - DONE; - } +{ + emit_call_insn (gen_call_split (operands[0], operands[1])); + if (!find_reg_note (operands[2], REG_NORETURN, 0)) + mips_restore_gp (); + DONE; +} [(set_attr "jal" "indirect,direct") (set_attr "extended_mips16" "no,yes")]) @@ -8563,16 +7151,16 @@ ld\\t%2,%1-%S1(%2)\;daddu\\t%2,%2,$31\\n\\t%*j\\t%2%/" [(call (mem:SI (match_operand 0 "call_insn_operand" "c")) (match_operand 1 "" "")) (clobber (reg:SI 31)) - (const_int 1)] + (clobber (reg:SI 28))] "TARGET_SPLIT_CALLS" "%*jalr\t%0%/" [(set_attr "type" "call")]) (define_expand "call_value" - [(parallel [(set (match_operand 0 "" "") - (call (match_operand 1 "" "") - (match_operand 2 "" ""))) - (use (match_operand 3 "" ""))])] ;; next_arg_reg + [(parallel [(set (match_operand 0 "") + (call (match_operand 1 "") + (match_operand 2 ""))) + (use (match_operand 3 ""))])] ;; next_arg_reg "" { mips_expand_call (operands[0], XEXP (operands[1], 0), @@ -8580,21 +7168,23 @@ ld\\t%2,%1-%S1(%2)\;daddu\\t%2,%2,$31\\n\\t%*j\\t%2%/" DONE; }) +;; See comment for call_internal. (define_insn_and_split "call_value_internal" [(set (match_operand 0 "register_operand" "=df,df") (call (mem:SI (match_operand 1 "call_insn_operand" "c,S")) (match_operand 2 "" ""))) (clobber (reg:SI 31))] "" - "%*jal\t%1%/" - "reload_completed && TARGET_SPLIT_CALLS" + { return TARGET_SPLIT_CALLS ? "#" : "%*jal\t%1%/"; } + "reload_completed && TARGET_SPLIT_CALLS && (operands[3] = insn)" [(const_int 0)] - { - emit_call_insn (gen_call_value_split (operands[0], operands[1], - operands[2])); - emit_insn (gen_exception_receiver ()); - DONE; - } +{ + emit_call_insn (gen_call_value_split (operands[0], operands[1], + operands[2])); + if (!find_reg_note (operands[3], REG_NORETURN, 0)) + mips_restore_gp (); + DONE; +} [(set_attr "jal" "indirect,direct") (set_attr "extended_mips16" "no,yes")]) @@ -8603,11 +7193,12 @@ ld\\t%2,%1-%S1(%2)\;daddu\\t%2,%2,$31\\n\\t%*j\\t%2%/" (call (mem:SI (match_operand 1 "call_insn_operand" "c")) (match_operand 2 "" ""))) (clobber (reg:SI 31)) - (const_int 1)] + (clobber (reg:SI 28))] "TARGET_SPLIT_CALLS" "%*jalr\t%1%/" [(set_attr "type" "call")]) +;; See comment for call_internal. (define_insn_and_split "call_value_multiple_internal" [(set (match_operand 0 "register_operand" "=df,df") (call (mem:SI (match_operand 1 "call_insn_operand" "c,S")) @@ -8617,15 +7208,16 @@ ld\\t%2,%1-%S1(%2)\;daddu\\t%2,%2,$31\\n\\t%*j\\t%2%/" (match_dup 2))) (clobber (reg:SI 31))] "" - "%*jal\t%1%/" - "reload_completed && TARGET_SPLIT_CALLS" + { return TARGET_SPLIT_CALLS ? "#" : "%*jal\t%1%/"; } + "reload_completed && TARGET_SPLIT_CALLS && (operands[4] = insn)" [(const_int 0)] - { - emit_call_insn (gen_call_value_multiple_split (operands[0], operands[1], - operands[2], operands[3])); - emit_insn (gen_exception_receiver ()); - DONE; - } +{ + emit_call_insn (gen_call_value_multiple_split (operands[0], operands[1], + operands[2], operands[3])); + if (!find_reg_note (operands[4], REG_NORETURN, 0)) + mips_restore_gp (); + DONE; +} [(set_attr "jal" "indirect,direct") (set_attr "extended_mips16" "no,yes")]) @@ -8637,7 +7229,7 @@ ld\\t%2,%1-%S1(%2)\;daddu\\t%2,%2,$31\\n\\t%*j\\t%2%/" (call (mem:SI (match_dup 1)) (match_dup 2))) (clobber (reg:SI 31)) - (const_int 1)] + (clobber (reg:SI 28))] "TARGET_SPLIT_CALLS" "%*jalr\t%1%/" [(set_attr "type" "call")]) @@ -8645,12 +7237,11 @@ ld\\t%2,%1-%S1(%2)\;daddu\\t%2,%2,$31\\n\\t%*j\\t%2%/" ;; Call subroutine returning any type. (define_expand "untyped_call" - [(parallel [(call (match_operand 0 "" "") + [(parallel [(call (match_operand 0 "") (const_int 0)) - (match_operand 1 "" "") - (match_operand 2 "" "")])] + (match_operand 1 "") + (match_operand 2 "")])] "" - " { int i; @@ -8664,7 +7255,7 @@ ld\\t%2,%1-%S1(%2)\;daddu\\t%2,%2,$31\\n\\t%*j\\t%2%/" emit_insn (gen_blockage ()); DONE; -}") +}) ;; ;; .................... @@ -8676,9 +7267,9 @@ ld\\t%2,%1-%S1(%2)\;daddu\\t%2,%2,$31\\n\\t%*j\\t%2%/" (define_expand "prefetch" - [(prefetch (match_operand 0 "address_operand" "") - (match_operand 1 "const_int_operand" "") - (match_operand 2 "const_int_operand" ""))] + [(prefetch (match_operand 0 "address_operand") + (match_operand 1 "const_int_operand") + (match_operand 2 "const_int_operand"))] "ISA_HAS_PREFETCH" { if (symbolic_operand (operands[0], GET_MODE (operands[0]))) @@ -8687,36 +7278,60 @@ ld\\t%2,%1-%S1(%2)\;daddu\\t%2,%2,$31\\n\\t%*j\\t%2%/" (define_insn "prefetch_si_address" [(prefetch (plus:SI (match_operand:SI 0 "register_operand" "r") - (match_operand:SI 3 "const_int_operand" "i")) + (match_operand:SI 3 "const_int_operand" "I")) (match_operand:SI 1 "const_int_operand" "n") (match_operand:SI 2 "const_int_operand" "n"))] "ISA_HAS_PREFETCH && Pmode == SImode" - "* return mips_emit_prefetch (operands);" + { return mips_emit_prefetch (operands); } [(set_attr "type" "prefetch")]) +(define_insn "prefetch_indexed_si" + [(prefetch (plus:SI (match_operand:SI 0 "register_operand" "r") + (match_operand:SI 3 "register_operand" "r")) + (match_operand:SI 1 "const_int_operand" "n") + (match_operand:SI 2 "const_int_operand" "n"))] + "ISA_HAS_PREFETCHX && TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT && Pmode == SImode" + { return mips_emit_prefetch (operands); } + [(set_attr "type" "prefetchx")]) + (define_insn "prefetch_si" [(prefetch (match_operand:SI 0 "register_operand" "r") (match_operand:SI 1 "const_int_operand" "n") (match_operand:SI 2 "const_int_operand" "n"))] "ISA_HAS_PREFETCH && Pmode == SImode" - "* return mips_emit_prefetch (operands);" +{ + operands[3] = const0_rtx; + return mips_emit_prefetch (operands); +} [(set_attr "type" "prefetch")]) (define_insn "prefetch_di_address" [(prefetch (plus:DI (match_operand:DI 0 "register_operand" "r") - (match_operand:DI 3 "const_int_operand" "i")) + (match_operand:DI 3 "const_int_operand" "I")) (match_operand:DI 1 "const_int_operand" "n") (match_operand:DI 2 "const_int_operand" "n"))] "ISA_HAS_PREFETCH && Pmode == DImode" - "* return mips_emit_prefetch (operands);" + { return mips_emit_prefetch (operands); } [(set_attr "type" "prefetch")]) +(define_insn "prefetch_indexed_di" + [(prefetch (plus:DI (match_operand:DI 0 "register_operand" "r") + (match_operand:DI 3 "register_operand" "r")) + (match_operand:DI 1 "const_int_operand" "n") + (match_operand:DI 2 "const_int_operand" "n"))] + "ISA_HAS_PREFETCHX && TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT && Pmode == DImode" + { return mips_emit_prefetch (operands); } + [(set_attr "type" "prefetchx")]) + (define_insn "prefetch_di" [(prefetch (match_operand:DI 0 "register_operand" "r") (match_operand:DI 1 "const_int_operand" "n") (match_operand:DI 2 "const_int_operand" "n"))] "ISA_HAS_PREFETCH && Pmode == DImode" - "* return mips_emit_prefetch (operands);" +{ + operands[3] = const0_rtx; + return mips_emit_prefetch (operands); +} [(set_attr "type" "prefetch")]) (define_insn "nop" @@ -8736,264 +7351,239 @@ ld\\t%2,%1-%S1(%2)\;daddu\\t%2,%2,$31\\n\\t%*j\\t%2%/" else return "#nop"; } - [(set_attr "type" "arith")]) - -;; The MIPS chip does not seem to require stack probes. -;; -;; (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 */ -;; }") -;; + [(set_attr "type" "nop")]) -;; ;; MIPS4 Conditional move instructions. (define_insn "" [(set (match_operand:SI 0 "register_operand" "=d,d") (if_then_else:SI - (match_operator 4 "equality_op" - [(match_operand:SI 1 "register_operand" "d,d") - (const_int 0)]) + (match_operator:SI 4 "equality_operator" + [(match_operand:SI 1 "register_operand" "d,d") + (const_int 0)]) (match_operand:SI 2 "reg_or_0_operand" "dJ,0") (match_operand:SI 3 "reg_or_0_operand" "0,dJ")))] "ISA_HAS_CONDMOVE || ISA_HAS_INT_CONDMOVE" "@ - mov%B4\\t%0,%z2,%1 - mov%b4\\t%0,%z3,%1" + mov%B4\t%0,%z2,%1 + mov%b4\t%0,%z3,%1" [(set_attr "type" "condmove") (set_attr "mode" "SI")]) (define_insn "" [(set (match_operand:SI 0 "register_operand" "=d,d") (if_then_else:SI - (match_operator 4 "equality_op" - [(match_operand:DI 1 "register_operand" "d,d") - (const_int 0)]) + (match_operator:DI 4 "equality_operator" + [(match_operand:DI 1 "register_operand" "d,d") + (const_int 0)]) (match_operand:SI 2 "reg_or_0_operand" "dJ,0") (match_operand:SI 3 "reg_or_0_operand" "0,dJ")))] "ISA_HAS_CONDMOVE || ISA_HAS_INT_CONDMOVE" "@ - mov%B4\\t%0,%z2,%1 - mov%b4\\t%0,%z3,%1" + mov%B4\t%0,%z2,%1 + mov%b4\t%0,%z3,%1" [(set_attr "type" "condmove") (set_attr "mode" "SI")]) (define_insn "" [(set (match_operand:SI 0 "register_operand" "=d,d") (if_then_else:SI - (match_operator 3 "equality_op" [(match_operand:CC 4 - "register_operand" - "z,z") - (const_int 0)]) + (match_operator:CC 3 "equality_operator" + [(match_operand:CC 4 "register_operand" "z,z") + (const_int 0)]) (match_operand:SI 1 "reg_or_0_operand" "dJ,0") (match_operand:SI 2 "reg_or_0_operand" "0,dJ")))] "ISA_HAS_CONDMOVE && TARGET_HARD_FLOAT" "@ - mov%T3\\t%0,%z1,%4 - mov%t3\\t%0,%z2,%4" + mov%T3\t%0,%z1,%4 + mov%t3\t%0,%z2,%4" [(set_attr "type" "condmove") (set_attr "mode" "SI")]) (define_insn "" [(set (match_operand:DI 0 "register_operand" "=d,d") (if_then_else:DI - (match_operator 4 "equality_op" - [(match_operand:SI 1 "register_operand" "d,d") - (const_int 0)]) + (match_operator:SI 4 "equality_operator" + [(match_operand:SI 1 "register_operand" "d,d") + (const_int 0)]) (match_operand:DI 2 "reg_or_0_operand" "dJ,0") (match_operand:DI 3 "reg_or_0_operand" "0,dJ")))] "(ISA_HAS_CONDMOVE || ISA_HAS_INT_CONDMOVE) && TARGET_64BIT" "@ - mov%B4\\t%0,%z2,%1 - mov%b4\\t%0,%z3,%1" + mov%B4\t%0,%z2,%1 + mov%b4\t%0,%z3,%1" [(set_attr "type" "condmove") (set_attr "mode" "DI")]) (define_insn "" [(set (match_operand:DI 0 "register_operand" "=d,d") (if_then_else:DI - (match_operator 4 "equality_op" - [(match_operand:DI 1 "register_operand" "d,d") - (const_int 0)]) + (match_operator:DI 4 "equality_operator" + [(match_operand:DI 1 "register_operand" "d,d") + (const_int 0)]) (match_operand:DI 2 "reg_or_0_operand" "dJ,0") (match_operand:DI 3 "reg_or_0_operand" "0,dJ")))] "(ISA_HAS_CONDMOVE || ISA_HAS_INT_CONDMOVE) && TARGET_64BIT" "@ - mov%B4\\t%0,%z2,%1 - mov%b4\\t%0,%z3,%1" + mov%B4\t%0,%z2,%1 + mov%b4\t%0,%z3,%1" [(set_attr "type" "condmove") (set_attr "mode" "DI")]) (define_insn "" [(set (match_operand:DI 0 "register_operand" "=d,d") (if_then_else:DI - (match_operator 3 "equality_op" [(match_operand:CC 4 - "register_operand" - "z,z") - (const_int 0)]) + (match_operator:CC 3 "equality_operator" + [(match_operand:CC 4 "register_operand" "z,z") + (const_int 0)]) (match_operand:DI 1 "reg_or_0_operand" "dJ,0") (match_operand:DI 2 "reg_or_0_operand" "0,dJ")))] "ISA_HAS_CONDMOVE && TARGET_HARD_FLOAT && TARGET_64BIT" "@ - mov%T3\\t%0,%z1,%4 - mov%t3\\t%0,%z2,%4" + mov%T3\t%0,%z1,%4 + mov%t3\t%0,%z2,%4" [(set_attr "type" "condmove") (set_attr "mode" "DI")]) (define_insn "" [(set (match_operand:SF 0 "register_operand" "=f,f") (if_then_else:SF - (match_operator 4 "equality_op" - [(match_operand:SI 1 "register_operand" "d,d") - (const_int 0)]) + (match_operator:SI 4 "equality_operator" + [(match_operand:SI 1 "register_operand" "d,d") + (const_int 0)]) (match_operand:SF 2 "register_operand" "f,0") (match_operand:SF 3 "register_operand" "0,f")))] "ISA_HAS_CONDMOVE && TARGET_HARD_FLOAT" "@ - mov%B4.s\\t%0,%2,%1 - mov%b4.s\\t%0,%3,%1" + mov%B4.s\t%0,%2,%1 + mov%b4.s\t%0,%3,%1" [(set_attr "type" "condmove") (set_attr "mode" "SF")]) (define_insn "" [(set (match_operand:SF 0 "register_operand" "=f,f") (if_then_else:SF - (match_operator 4 "equality_op" - [(match_operand:DI 1 "register_operand" "d,d") - (const_int 0)]) + (match_operator:DI 4 "equality_operator" + [(match_operand:DI 1 "register_operand" "d,d") + (const_int 0)]) (match_operand:SF 2 "register_operand" "f,0") (match_operand:SF 3 "register_operand" "0,f")))] "ISA_HAS_CONDMOVE && TARGET_HARD_FLOAT" "@ - mov%B4.s\\t%0,%2,%1 - mov%b4.s\\t%0,%3,%1" + mov%B4.s\t%0,%2,%1 + mov%b4.s\t%0,%3,%1" [(set_attr "type" "condmove") (set_attr "mode" "SF")]) (define_insn "" [(set (match_operand:SF 0 "register_operand" "=f,f") (if_then_else:SF - (match_operator 3 "equality_op" [(match_operand:CC 4 - "register_operand" - "z,z") - (const_int 0)]) + (match_operator:CC 3 "equality_operator" + [(match_operand:CC 4 "register_operand" "z,z") + (const_int 0)]) (match_operand:SF 1 "register_operand" "f,0") (match_operand:SF 2 "register_operand" "0,f")))] "ISA_HAS_CONDMOVE && TARGET_HARD_FLOAT" "@ - mov%T3.s\\t%0,%1,%4 - mov%t3.s\\t%0,%2,%4" + mov%T3.s\t%0,%1,%4 + mov%t3.s\t%0,%2,%4" [(set_attr "type" "condmove") (set_attr "mode" "SF")]) (define_insn "" [(set (match_operand:DF 0 "register_operand" "=f,f") (if_then_else:DF - (match_operator 4 "equality_op" - [(match_operand:SI 1 "register_operand" "d,d") - (const_int 0)]) + (match_operator:SI 4 "equality_operator" + [(match_operand:SI 1 "register_operand" "d,d") + (const_int 0)]) (match_operand:DF 2 "register_operand" "f,0") (match_operand:DF 3 "register_operand" "0,f")))] "ISA_HAS_CONDMOVE && TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT" "@ - mov%B4.d\\t%0,%2,%1 - mov%b4.d\\t%0,%3,%1" + mov%B4.d\t%0,%2,%1 + mov%b4.d\t%0,%3,%1" [(set_attr "type" "condmove") (set_attr "mode" "DF")]) (define_insn "" [(set (match_operand:DF 0 "register_operand" "=f,f") (if_then_else:DF - (match_operator 4 "equality_op" - [(match_operand:DI 1 "register_operand" "d,d") - (const_int 0)]) + (match_operator:DI 4 "equality_operator" + [(match_operand:DI 1 "register_operand" "d,d") + (const_int 0)]) (match_operand:DF 2 "register_operand" "f,0") (match_operand:DF 3 "register_operand" "0,f")))] "ISA_HAS_CONDMOVE && TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT" "@ - mov%B4.d\\t%0,%2,%1 - mov%b4.d\\t%0,%3,%1" + mov%B4.d\t%0,%2,%1 + mov%b4.d\t%0,%3,%1" [(set_attr "type" "condmove") (set_attr "mode" "DF")]) (define_insn "" [(set (match_operand:DF 0 "register_operand" "=f,f") (if_then_else:DF - (match_operator 3 "equality_op" [(match_operand:CC 4 - "register_operand" - "z,z") - (const_int 0)]) + (match_operator:CC 3 "equality_operator" + [(match_operand:CC 4 "register_operand" "z,z") + (const_int 0)]) (match_operand:DF 1 "register_operand" "f,0") (match_operand:DF 2 "register_operand" "0,f")))] "ISA_HAS_CONDMOVE && TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT" "@ - mov%T3.d\\t%0,%1,%4 - mov%t3.d\\t%0,%2,%4" + mov%T3.d\t%0,%1,%4 + mov%t3.d\t%0,%2,%4" [(set_attr "type" "condmove") (set_attr "mode" "DF")]) ;; These are the main define_expand's used to make conditional moves. (define_expand "movsicc" - [(set (match_dup 4) (match_operand 1 "comparison_operator" "")) - (set (match_operand:SI 0 "register_operand" "") + [(set (match_dup 4) (match_operand 1 "comparison_operator")) + (set (match_operand:SI 0 "register_operand") (if_then_else:SI (match_dup 5) - (match_operand:SI 2 "reg_or_0_operand" "") - (match_operand:SI 3 "reg_or_0_operand" "")))] + (match_operand:SI 2 "reg_or_0_operand") + (match_operand:SI 3 "reg_or_0_operand")))] "ISA_HAS_CONDMOVE || ISA_HAS_INT_CONDMOVE" - " { gen_conditional_move (operands); DONE; -}") +}) (define_expand "movdicc" - [(set (match_dup 4) (match_operand 1 "comparison_operator" "")) - (set (match_operand:DI 0 "register_operand" "") + [(set (match_dup 4) (match_operand 1 "comparison_operator")) + (set (match_operand:DI 0 "register_operand") (if_then_else:DI (match_dup 5) - (match_operand:DI 2 "reg_or_0_operand" "") - (match_operand:DI 3 "reg_or_0_operand" "")))] + (match_operand:DI 2 "reg_or_0_operand") + (match_operand:DI 3 "reg_or_0_operand")))] "(ISA_HAS_CONDMOVE || ISA_HAS_INT_CONDMOVE) && TARGET_64BIT" - " { gen_conditional_move (operands); DONE; -}") +}) (define_expand "movsfcc" - [(set (match_dup 4) (match_operand 1 "comparison_operator" "")) - (set (match_operand:SF 0 "register_operand" "") + [(set (match_dup 4) (match_operand 1 "comparison_operator")) + (set (match_operand:SF 0 "register_operand") (if_then_else:SF (match_dup 5) - (match_operand:SF 2 "register_operand" "") - (match_operand:SF 3 "register_operand" "")))] + (match_operand:SF 2 "register_operand") + (match_operand:SF 3 "register_operand")))] "ISA_HAS_CONDMOVE && TARGET_HARD_FLOAT" - " { gen_conditional_move (operands); DONE; -}") +}) (define_expand "movdfcc" - [(set (match_dup 4) (match_operand 1 "comparison_operator" "")) - (set (match_operand:DF 0 "register_operand" "") + [(set (match_dup 4) (match_operand 1 "comparison_operator")) + (set (match_operand:DF 0 "register_operand") (if_then_else:DF (match_dup 5) - (match_operand:DF 2 "register_operand" "") - (match_operand:DF 3 "register_operand" "")))] + (match_operand:DF 2 "register_operand") + (match_operand:DF 3 "register_operand")))] "ISA_HAS_CONDMOVE && TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT" - " { gen_conditional_move (operands); DONE; -}") +}) ;; ;; .................... @@ -9003,233 +7593,43 @@ ld\\t%2,%1-%S1(%2)\;daddu\\t%2,%2,$31\\n\\t%*j\\t%2%/" ;; .................... ;; -(define_insn "consttable_qi" - [(unspec_volatile [(match_operand:QI 0 "consttable_operand" "=g")] - UNSPEC_CONSTTABLE_QI)] - "TARGET_MIPS16" - "* -{ - assemble_integer (operands[0], 1, BITS_PER_UNIT, 1); - return \"\"; -}" - [(set_attr "type" "unknown") - (set_attr "mode" "QI") - (set_attr "length" "8")]) - -(define_insn "consttable_hi" - [(unspec_volatile [(match_operand:HI 0 "consttable_operand" "=g")] - UNSPEC_CONSTTABLE_HI)] - "TARGET_MIPS16" - "* -{ - assemble_integer (operands[0], 2, BITS_PER_UNIT * 2, 1); - return \"\"; -}" - [(set_attr "type" "unknown") - (set_attr "mode" "HI") - (set_attr "length" "8")]) - -(define_insn "consttable_si" - [(unspec_volatile [(match_operand:SI 0 "consttable_operand" "=g")] - UNSPEC_CONSTTABLE_SI)] - "TARGET_MIPS16" - "* -{ - assemble_integer (operands[0], 4, BITS_PER_UNIT * 4, 1); - return \"\"; -}" - [(set_attr "type" "unknown") - (set_attr "mode" "SI") - (set_attr "length" "8")]) - -(define_insn "consttable_di" - [(unspec_volatile [(match_operand:DI 0 "consttable_operand" "=g")] - UNSPEC_CONSTTABLE_DI)] - "TARGET_MIPS16" - "* -{ - assemble_integer (operands[0], 8, BITS_PER_UNIT * 8, 1); - return \"\"; -}" - [(set_attr "type" "unknown") - (set_attr "mode" "DI") - (set_attr "length" "16")]) - -(define_insn "consttable_sf" - [(unspec_volatile [(match_operand:SF 0 "consttable_operand" "=g")] - UNSPEC_CONSTTABLE_SF)] +(define_insn "consttable_int" + [(unspec_volatile [(match_operand 0 "consttable_operand" "") + (match_operand 1 "const_int_operand" "")] + UNSPEC_CONSTTABLE_INT)] "TARGET_MIPS16" - "* { - REAL_VALUE_TYPE d; - - if (GET_CODE (operands[0]) != CONST_DOUBLE) - abort (); - REAL_VALUE_FROM_CONST_DOUBLE (d, operands[0]); - assemble_real (d, SFmode, GET_MODE_ALIGNMENT (SFmode)); - return \"\"; -}" - [(set_attr "type" "unknown") - (set_attr "mode" "SF") - (set_attr "length" "8")]) + assemble_integer (operands[0], INTVAL (operands[1]), + BITS_PER_UNIT * INTVAL (operands[1]), 1); + return ""; +} + [(set (attr "length") (symbol_ref "INTVAL (operands[1])"))]) -(define_insn "consttable_df" - [(unspec_volatile [(match_operand:DF 0 "consttable_operand" "=g")] - UNSPEC_CONSTTABLE_DF)] +(define_insn "consttable_float" + [(unspec_volatile [(match_operand 0 "consttable_operand" "")] + UNSPEC_CONSTTABLE_FLOAT)] "TARGET_MIPS16" - "* { REAL_VALUE_TYPE d; if (GET_CODE (operands[0]) != CONST_DOUBLE) abort (); REAL_VALUE_FROM_CONST_DOUBLE (d, operands[0]); - assemble_real (d, DFmode, GET_MODE_ALIGNMENT (DFmode)); - return \"\"; -}" - [(set_attr "type" "unknown") - (set_attr "mode" "DF") - (set_attr "length" "16")]) - -(define_insn "align_2" - [(unspec_volatile [(const_int 0)] UNSPEC_ALIGN_2)] - "TARGET_MIPS16" - ".align 1" - [(set_attr "type" "unknown") - (set_attr "mode" "HI") - (set_attr "length" "8")]) - -(define_insn "align_4" - [(unspec_volatile [(const_int 0)] UNSPEC_ALIGN_4)] - "TARGET_MIPS16" - ".align 2" - [(set_attr "type" "unknown") - (set_attr "mode" "SI") - (set_attr "length" "8")]) - -(define_insn "align_8" - [(unspec_volatile [(const_int 0)] UNSPEC_ALIGN_8)] - "TARGET_MIPS16" - ".align 3" - [(set_attr "type" "unknown") - (set_attr "mode" "DI") - (set_attr "length" "12")]) + assemble_real (d, GET_MODE (operands[0]), + GET_MODE_BITSIZE (GET_MODE (operands[0]))); + return ""; +} + [(set (attr "length") + (symbol_ref "GET_MODE_SIZE (GET_MODE (operands[0]))"))]) + +(define_insn "align" + [(unspec_volatile [(match_operand 0 "const_int_operand" "")] UNSPEC_ALIGN)] + "" + ".align\t%0" + [(set (attr "length") (symbol_ref "(1 << INTVAL (operands[0])) - 1"))]) -;; -;; .................... -;; -;; mips16 peepholes -;; -;; .................... -;; - -;; On the mips16, reload will sometimes decide that a pseudo register -;; should go into $24, and then later on have to reload that register. -;; When that happens, we get a load of a general register followed by -;; a move from the general register to $24 followed by a branch. -;; These peepholes catch the common case, and fix it to just use the -;; general register for the branch. - -(define_peephole - [(set (match_operand:SI 0 "register_operand" "=t") - (match_operand:SI 1 "register_operand" "d")) - (set (pc) - (if_then_else (match_operator:SI 2 "equality_op" [(match_dup 0) - (const_int 0)]) - (match_operand 3 "pc_or_label_operand" "") - (match_operand 4 "pc_or_label_operand" "")))] - "TARGET_MIPS16 - && GET_CODE (operands[0]) == REG - && REGNO (operands[0]) == 24 - && dead_or_set_p (insn, operands[0]) - && GET_CODE (operands[1]) == REG - && M16_REG_P (REGNO (operands[1]))" - "* -{ - if (operands[3] != pc_rtx) - return \"b%C2z\\t%1,%3\"; - else - return \"b%N2z\\t%1,%4\"; -}" - [(set_attr "type" "branch") - (set_attr "mode" "none") - (set_attr "length" "8")]) - -(define_peephole - [(set (match_operand:DI 0 "register_operand" "=t") - (match_operand:DI 1 "register_operand" "d")) - (set (pc) - (if_then_else (match_operator:DI 2 "equality_op" [(match_dup 0) - (const_int 0)]) - (match_operand 3 "pc_or_label_operand" "") - (match_operand 4 "pc_or_label_operand" "")))] - "TARGET_MIPS16 && TARGET_64BIT - && GET_CODE (operands[0]) == REG - && REGNO (operands[0]) == 24 - && dead_or_set_p (insn, operands[0]) - && GET_CODE (operands[1]) == REG - && M16_REG_P (REGNO (operands[1]))" - "* -{ - if (operands[3] != pc_rtx) - return \"b%C2z\\t%1,%3\"; - else - return \"b%N2z\\t%1,%4\"; -}" - [(set_attr "type" "branch") - (set_attr "mode" "none") - (set_attr "length" "8")]) - -;; We can also have the reverse reload: reload will spill $24 into -;; another register, and then do a branch on that register when it -;; could have just stuck with $24. - -(define_peephole - [(set (match_operand:SI 0 "register_operand" "=d") - (match_operand:SI 1 "register_operand" "t")) - (set (pc) - (if_then_else (match_operator:SI 2 "equality_op" [(match_dup 0) - (const_int 0)]) - (match_operand 3 "pc_or_label_operand" "") - (match_operand 4 "pc_or_label_operand" "")))] - "TARGET_MIPS16 - && GET_CODE (operands[1]) == REG - && REGNO (operands[1]) == 24 - && GET_CODE (operands[0]) == REG - && M16_REG_P (REGNO (operands[0])) - && dead_or_set_p (insn, operands[0])" - "* -{ - if (operands[3] != pc_rtx) - return \"bt%C2z\\t%3\"; - else - return \"bt%N2z\\t%4\"; -}" - [(set_attr "type" "branch") - (set_attr "mode" "none") - (set_attr "length" "8")]) - -(define_peephole - [(set (match_operand:DI 0 "register_operand" "=d") - (match_operand:DI 1 "register_operand" "t")) - (set (pc) - (if_then_else (match_operator:DI 2 "equality_op" [(match_dup 0) - (const_int 0)]) - (match_operand 3 "pc_or_label_operand" "") - (match_operand 4 "pc_or_label_operand" "")))] - "TARGET_MIPS16 && TARGET_64BIT - && GET_CODE (operands[1]) == REG - && REGNO (operands[1]) == 24 - && GET_CODE (operands[0]) == REG - && M16_REG_P (REGNO (operands[0])) - && dead_or_set_p (insn, operands[0])" - "* -{ - if (operands[3] != pc_rtx) - return \"bt%C2z\\t%3\"; - else - return \"bt%N2z\\t%4\"; -}" - [(set_attr "type" "branch") - (set_attr "mode" "none") - (set_attr "length" "8")]) +(define_split + [(match_operand 0 "small_data_pattern")] + "reload_completed" + [(match_dup 0)] + { operands[0] = mips_rewrite_small_data (operands[0]); })