diff options
author | YamaArashi <shadow962@live.com> | 2016-02-11 01:12:34 -0800 |
---|---|---|
committer | YamaArashi <shadow962@live.com> | 2016-02-11 01:12:34 -0800 |
commit | b84b6b23fa58beb5674b37279742eb65461ca076 (patch) | |
tree | a85da124cbf9f888a31b750ede3a832c2c6b96aa /gcc/config/mips/mips.md | |
parent | 23e2a17097740709d4466a802e03992116b12900 (diff) |
delete irrelevant configs
Diffstat (limited to 'gcc/config/mips/mips.md')
-rwxr-xr-x | gcc/config/mips/mips.md | 10710 |
1 files changed, 0 insertions, 10710 deletions
diff --git a/gcc/config/mips/mips.md b/gcc/config/mips/mips.md deleted file mode 100755 index 7e18299..0000000 --- a/gcc/config/mips/mips.md +++ /dev/null @@ -1,10710 +0,0 @@ -;; Mips.md Machine Description for MIPS based processors -;; 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. -;; Copyright (C) 1989, 90-98, 1999 Free Software Foundation, Inc. - -;; This file is part of GNU CC. - -;; GNU CC is free software; you can redistribute it and/or modify -;; it under the terms of the GNU General Public License as published by -;; the Free Software Foundation; either version 2, or (at your option) -;; any later version. - -;; GNU CC is distributed in the hope that it will be useful, -;; but WITHOUT ANY WARRANTY; without even the implied warranty of -;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -;; GNU General Public License for more details. - -;; You should have received a copy of the GNU General Public License -;; along with GNU CC; see the file COPYING. If not, write to -;; the Free Software Foundation, 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. - - - -;; .................... -;; Attributes -;; .................... - -;; Classification of each insn. -;; branch conditional branch -;; jump unconditional jump -;; call unconditional call -;; load load instruction(s) -;; store store instruction(s) -;; move data movement within same register set -;; xfer transfer to/from coprocessor -;; hilo transfer of hi/lo registers -;; arith integer arithmetic instruction -;; darith double precision integer arithmetic instructions -;; imul integer multiply -;; idiv integer divide -;; icmp integer compare -;; fadd floating point add/subtract -;; fmul floating point multiply -;; fmadd floating point multiply-add -;; fdiv floating point divide -;; fabs floating point absolute value -;; fneg floating point negation -;; fcmp floating point compare -;; fcvt floating point convert -;; fsqrt floating point square root -;; frsqrt floating point reciprocal square root CYGNUS LOCAL vr5400/raeburn -;; multi multiword sequence (or user asm statements) -;; nop no operation - -(define_attr "type" - "unknown,branch,jump,call,load,store,move,xfer,hilo,arith,darith,imul,idiv,icmp,fadd,fmul,fmadd,fdiv,fabs,fneg,fcmp,fcvt,fsqrt,frsqrt,multi,nop" ; CYGNUS LOCAL vr5400/raeburn - (const_string "unknown")) - -;; Main data type used by the insn -(define_attr "mode" "unknown,none,QI,HI,SI,DI,SF,DF,FPSW" (const_string "unknown")) - -;; # instructions (4 bytes each) -(define_attr "length" "" (const_int 1)) - -;; 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,r3000,r3900,r6000,r4000,r4100,r4300,r4600,r4650,r5000,r5400,r8000" ; CYGNUS LOCAL vr5400/raeburn - (const (symbol_ref "mips_cpu_attr"))) - -;; Does the instruction have a mandatory delay slot? -;; The 3900, is (mostly) mips1, but does not have a manditory load delay -;; slot. -(define_attr "dslot" "no,yes" - (if_then_else (ior (eq_attr "type" "branch,jump,call,xfer,hilo,fcmp") - (and (eq_attr "type" "load") - (and (eq (symbol_ref "mips_isa") (const_int 1)) - (and (eq (symbol_ref "mips16") (const_int 0)) - (eq_attr "cpu" "!r3900"))))) - (const_string "yes") - (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")))) - - -;; Describe a user's asm statement. -(define_asm_attributes - [(set_attr "type" "multi")]) - -;; whether or not generating calls to position independent functions -(define_attr "abicalls" "no,yes" - (const (symbol_ref "mips_abicalls_attr"))) - - - -;; ......................... -;; Delay slots, can't describe load/fcmp/xfer delay slots here -;; ......................... - -(define_delay (and (eq_attr "type" "branch") - (eq (symbol_ref "mips16") (const_int 0))) - [(and (eq_attr "dslot" "no") (eq_attr "length" "1")) - (nil) - (and (eq_attr "branch_likely" "yes") (and (eq_attr "dslot" "no") (eq_attr "length" "1")))]) - -(define_delay (eq_attr "type" "jump") - [(and (eq_attr "dslot" "no") (eq_attr "length" "1")) - (nil) - (nil)]) - -(define_delay (and (eq_attr "type" "call") (eq_attr "abicalls" "no")) - [(and (eq_attr "dslot" "no") (eq_attr "length" "1")) - (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,r4300,r5000,r5400")) ; CYGNUS LOCAL vr5400/raeburn - 3 0) - -(define_function_unit "memory" 1 0 - (and (eq_attr "type" "load") - (eq_attr "cpu" "r3000,r3900,r4600,r4650,r4100,r4300,r5000,r5400")) ; CYGNUS LOCAL vr5400/raeburn - 2 0) - -;; CYGNUS LOCAL law -(define_function_unit "memory" 1 0 - (and (eq_attr "type" "store") (const_int 1)) 1 0) ; - -(define_function_unit "memory" 1 0 - (and (eq_attr "type" "xfer") (const_int 1)) 2 0) ; - -(define_function_unit "imuldiv" 1 0 - (and (eq_attr "type" "hilo") - (const_int 1)) ; - 1 3) - -(define_function_unit "imuldiv" 1 0 - (and (eq_attr "type" "imul") - (eq_attr "cpu" "!r3000,r3900,r4000,r4600,r4650,r4100,r4300,r5000,r5400")) ; CYGNUS LOCAL vr5400/raeburn - 17 17) -;; END CYGNUS LOCAL - -;; 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 "mips16") (const_int 0))) - 1 5) - -(define_function_unit "imuldiv" 1 0 - (and (eq_attr "type" "imul") (eq_attr "cpu" "r3000,r3900")) - 12 12) - -(define_function_unit "imuldiv" 1 0 - (and (eq_attr "type" "imul") (eq_attr "cpu" "r4000,r4600")) - 10 10) - -(define_function_unit "imuldiv" 1 0 - (and (eq_attr "type" "imul") (eq_attr "cpu" "r4650")) - 4 4) - -(define_function_unit "imuldiv" 1 0 - (and (eq_attr "type" "imul") - (and (eq_attr "mode" "SI") (eq_attr "cpu" "r4100"))) - 1 1) - -(define_function_unit "imuldiv" 1 0 - (and (eq_attr "type" "imul") - (and (eq_attr "mode" "DI") (eq_attr "cpu" "r4100"))) - 4 4) - -(define_function_unit "imuldiv" 1 0 - (and (eq_attr "type" "imul") - (and (eq_attr "mode" "SI") (eq_attr "cpu" "r4300,r5000"))) ; - 5 5) - -(define_function_unit "imuldiv" 1 0 - (and (eq_attr "type" "imul") - (and (eq_attr "mode" "DI") (eq_attr "cpu" "r4300"))) ; - 8 8) - -(define_function_unit "imuldiv" 1 0 - (and (eq_attr "type" "imul") - (and (eq_attr "mode" "DI") (eq_attr "cpu" "r5000"))) - 9 9) - -;; CYGNUS LOCAL vr5400/raeburn -(define_function_unit "imuldiv" 1 0 - (and (eq_attr "type" "imul") - (and (eq_attr "mode" "SI") (eq_attr "cpu" "r5400"))) - 3 1) - -(define_function_unit "imuldiv" 1 0 - (and (eq_attr "type" "imul") - (and (eq_attr "mode" "DI") (eq_attr "cpu" "r5400"))) - 4 2) -;; END CYGNUS LOCAL - -(define_function_unit "imuldiv" 1 0 - (and (eq_attr "type" "idiv") - (eq_attr "cpu" "!r3000,r3900,r4000,r4600,r4650,r4100,r4300,r5000,r5400")) ; CYGNUS LOCAL vr5400/raeburn - 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"))) - 35 35) - -(define_function_unit "imuldiv" 1 0 - (and (eq_attr "type" "idiv") - (and (eq_attr "mode" "DI") (eq_attr "cpu" "r4100"))) - 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) - -;; CYGNUS LOCAL vr5400/raeburn -(define_function_unit "imuldiv" 1 0 - (and (eq_attr "type" "idiv") - (and (eq_attr "mode" "SI") (eq_attr "cpu" "r5400"))) - 34 34) - -(define_function_unit "imuldiv" 1 0 - (and (eq_attr "type" "idiv") - (and (eq_attr "mode" "DI") (eq_attr "cpu" "r5400"))) - 66 66) -;; END CYGNUS LOCAL - -;; 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,r5400")) ; CYGNUS LOCAL vr5400/raeburn - 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,r5400")) ; CYGNUS LOCAL vr5400/raeburn - 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,r5400")) ; CYGNUS LOCAL vr5400/raeburn - 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,r5400"))) ; CYGNUS LOCAL vr5400/raeburn - 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,r5400"))) ; CYGNUS LOCAL vr5400/raeburn - 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,r5400"))) ; CYGNUS LOCAL vr5400/raeburn - 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,r5400"))) ; CYGNUS LOCAL vr5400/raeburn - 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") ; CYGNUS LOCAL vr5400/raeburn - (and (eq_attr "mode" "SF") (eq_attr "cpu" "!r4600,r4650,r4300,r5000,r5400"))) ; CYGNUS LOCAL vr5400/raeburn - 54 0) - -(define_function_unit "divide" 1 1 - (and (eq_attr "type" "fsqrt,frsqrt") ; CYGNUS LOCAL vr5400/raeburn - (and (eq_attr "mode" "SF") (eq_attr "cpu" "r4600,r4650"))) - 31 0) - -(define_function_unit "divide" 1 1 - (and (eq_attr "type" "fsqrt,frsqrt") ; CYGNUS LOCAL vr5400/raeburn - (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") ; CYGNUS LOCAL vr5400/raeburn - (and (eq_attr "mode" "DF") (eq_attr "cpu" "!r4600,r4650,r4300,r5000,r5400"))) ; CYGNUS LOCAL vr5400/raeburn - 112 0) - -(define_function_unit "divide" 1 1 - (and (eq_attr "type" "fsqrt,frsqrt") ; CYGNUS LOCAL vr5400/raeburn - (and (eq_attr "mode" "DF") (eq_attr "cpu" "r4600,r4650"))) - 60 0) - -(define_function_unit "divide" 1 1 - (and (eq_attr "type" "fsqrt,frsqrt") ; CYGNUS LOCAL vr5400/raeburn - (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")) ; CYGNUS LOCAL vr5400/raeburn - (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")) ; CYGNUS LOCAL vr5400/raeburn - (and (eq_attr "mode" "DF") (eq_attr "cpu" "r4300"))) ; - 58 58) - -;; CYGNUS LOCAL vr5400/raeburn -(define_function_unit "alu_5400" 2 0 - (and (eq_attr "type" "move,arith,darith,icmp,nop") - (eq_attr "cpu" "r5400")) - 1 0) - -(define_function_unit "alu_5400" 2 0 - (and (eq_attr "type" "fadd") - (eq_attr "cpu" "r5400")) - 4 3) - -(define_function_unit "alu_5400" 2 0 - (and (eq_attr "type" "fcmp,fabs,fneg") - (eq_attr "cpu" "r5400")) - 2 1) - -(define_function_unit "alu_5400" 2 0 - (and (and (eq_attr "type" "fmul") - (eq_attr "mode" "SF")) - (eq_attr "cpu" "r5400")) - 5 4) - -(define_function_unit "alu_5400" 2 0 - (and (and (eq_attr "type" "fmul") - (eq_attr "mode" "DF")) - (eq_attr "cpu" "r5400")) - 6 5) - -(define_function_unit "alu_5400" 2 0 - (and (and (eq_attr "type" "fdiv,fsqrt") - (eq_attr "mode" "SF")) - (eq_attr "cpu" "r5400")) - 31 30) - -(define_function_unit "alu_5400" 2 0 - (and (and (eq_attr "type" "fdiv,fsqrt") - (eq_attr "mode" "DF")) - (eq_attr "cpu" "r5400")) - 59 58) - -(define_function_unit "alu_5400" 2 0 - (and (and (eq_attr "type" "frsqrt") - (eq_attr "mode" "SF")) - (eq_attr "cpu" "r5400")) - 61 60) - -(define_function_unit "alu_5400" 2 0 - (and (and (eq_attr "type" "frsqrt") - (eq_attr "mode" "DF")) - (eq_attr "cpu" "r5400")) - 121 120) - -(define_function_unit "alu_5400" 2 0 - (and (and (eq_attr "type" "fmadd") - (eq_attr "mode" "SF")) - (eq_attr "cpu" "r5400")) - 9 8) - -(define_function_unit "alu_5400" 2 0 - (and (and (eq_attr "type" "fmadd") - (eq_attr "mode" "DF")) - (eq_attr "cpu" "r5400")) - 10 9) - -(define_function_unit "alu_5400" 2 0 - (and (eq_attr "type" "fcvt") - (eq_attr "cpu" "r5400")) - 6 5) -;; END CYGNUS LOCAL - - - -;; 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) -;; (define_function_unit "imuldiv" 1 1 (eq_attr "type" "imul") 17 0) -;; (define_function_unit "imuldiv" 1 1 (eq_attr "type" "idiv") 38 0) -;; (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,frsqrt") (eq_attr "mode" "SF")) 54 0) CYGNUS LOCAL vr5400/raeburn -;; (define_function_unit "sqrt" 1 1 (and (eq_attr "type" "fsqrt,frsqrt") (eq_attr "mode" "DF")) 112 0) CYGNUS LOCAL vr5400/raeburn - - -;; .................... -;; ADDITION -;; .................... - -(define_insn "adddf3" - [(set (match_operand:DF 0 "register_operand" "=f") - (plus:DF (match_operand:DF 1 "register_operand" "f") - (match_operand:DF 2 "register_operand" "f")))] - "TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT" - "add.d\\t%0,%1,%2" - [(set_attr "type" "fadd") - (set_attr "mode" "DF") - (set_attr "length" "1")]) - -(define_insn "addsf3" - [(set (match_operand:SF 0 "register_operand" "=f") - (plus:SF (match_operand:SF 1 "register_operand" "f") - (match_operand:SF 2 "register_operand" "f")))] - "TARGET_HARD_FLOAT" - "add.s\\t%0,%1,%2" - [(set_attr "type" "fadd") - (set_attr "mode" "SF") - (set_attr "length" "1")]) - -(define_expand "addsi3" - [(set (match_operand:SI 0 "register_operand" "=d") - (plus:SI (match_operand:SI 1 "reg_or_0_operand" "dJ") - (match_operand:SI 2 "arith_operand" "dI")))] - "" - " -{ - /* The mips16 assembler handles -32768 correctly, and so does gas, - but some other MIPS assemblers think that -32768 needs to be - loaded into a register before it can be added in. */ - if (! TARGET_MIPS16 - && ! TARGET_GAS - && GET_CODE (operands[2]) == CONST_INT - && INTVAL (operands[2]) == -32768) - operands[2] = force_reg (SImode, operands[2]); -}") - -(define_insn "addsi3_internal" - [(set (match_operand:SI 0 "register_operand" "=d") - (plus:SI (match_operand:SI 1 "reg_or_0_operand" "dJ") - (match_operand:SI 2 "arith_operand" "dI")))] - "! TARGET_MIPS16 - && (TARGET_GAS - || GET_CODE (operands[2]) != CONST_INT - || INTVAL (operands[2]) != -32768)" - "addu\\t%0,%z1,%2" - [(set_attr "type" "arith") - (set_attr "mode" "SI") - (set_attr "length" "1")]) - -;; For the mips16, we need to recognize stack pointer additions -;; explicitly, since we don't have a constraint for $sp. These insns -;; will be generated by the save_restore_insns functions. - -(define_insn "" - [(set (reg:SI 29) - (plus:SI (reg:SI 29) - (match_operand:SI 0 "small_int" "I")))] - "TARGET_MIPS16" - "addu\\t%$,%$,%0" - [(set_attr "type" "arith") - (set_attr "mode" "SI") - (set (attr "length") (if_then_else (match_operand:VOID 0 "m16_simm8_8" "") - (const_int 1) - (const_int 2)))]) - -(define_insn "" - [(set (match_operand:SI 0 "register_operand" "=d") - (plus:SI (reg:SI 29) - (match_operand:SI 1 "small_int" "I")))] - "TARGET_MIPS16" - "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" "") - (const_int 1) - (const_int 2)))]) - -(define_insn "" - [(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" "IQ,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)" - "* -{ - if (REGNO (operands[0]) == REGNO (operands[1])) - return \"addu\\t%0,%2\"; - 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" "") - (const_int 1) - (const_int 2)) - (if_then_else (match_operand:VOID 2 "m16_simm4_1" "") - (const_int 1) - (const_int 2)) - (const_int 1)])]) - - -;; On the mips16, we can sometimes split an add of a constant which is -;; a 4 byte instruction into two adds which are both 2 byte -;; instructions. There are two cases: one where we are adding a -;; constant plus a register to another register, and one where we are -;; simply adding a constant to a register. - -(define_split - [(set (match_operand:SI 0 "register_operand" "") - (plus:SI (match_dup 0) - (match_operand:SI 1 "const_int_operand" "")))] - "TARGET_MIPS16 && reload_completed - && GET_CODE (operands[0]) == REG - && M16_REG_P (REGNO (operands[0])) - && GET_CODE (operands[1]) == CONST_INT - && ((INTVAL (operands[1]) > 0x7f - && INTVAL (operands[1]) <= 0x7f + 0x7f) - || (INTVAL (operands[1]) < - 0x80 - && 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]); - - if (val >= 0) - { - operands[1] = GEN_INT (0x7f); - operands[2] = GEN_INT (val - 0x7f); - } - else - { - 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" "")))] - "TARGET_MIPS16 && reload_completed - && GET_CODE (operands[0]) == REG - && M16_REG_P (REGNO (operands[0])) - && GET_CODE (operands[1]) == REG - && M16_REG_P (REGNO (operands[1])) - && REGNO (operands[0]) != REGNO (operands[1]) - && GET_CODE (operands[2]) == CONST_INT - && ((INTVAL (operands[2]) > 0x7 - && INTVAL (operands[2]) <= 0x7 + 0x7f) - || (INTVAL (operands[2]) < - 0x8 - && 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]); - - if (val >= 0) - { - operands[2] = GEN_INT (0x7); - operands[3] = GEN_INT (val - 0x7); - } - else - { - 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 "se_register_operand" "") - (match_operand:DI 2 "se_arith_operand" ""))) - (clobber (match_dup 3))])] - "TARGET_64BIT || (!TARGET_DEBUG_G_MODE && !TARGET_MIPS16)" - " -{ - /* The mips16 assembler handles -32768 correctly, and so does gas, - but some other MIPS assemblers think that -32768 needs to be - loaded into a register before it can be added in. */ - if (! TARGET_MIPS16 - && ! TARGET_GAS - && GET_CODE (operands[2]) == CONST_INT - && INTVAL (operands[2]) == -32768) - operands[2] = force_reg (DImode, operands[2]); - - 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" "4")]) - -(define_split - [(set (match_operand:DI 0 "register_operand" "") - (plus:DI (match_operand:DI 1 "register_operand" "") - (match_operand:DI 2 "register_operand" ""))) - (clobber (match_operand:SI 3 "register_operand" ""))] - "reload_completed && !WORDS_BIG_ENDIAN && !TARGET_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) 1) - (plus:SI (subreg:SI (match_dup 1) 1) - (subreg:SI (match_dup 2) 1))) - - (set (subreg:SI (match_dup 0) 1) - (plus:SI (subreg:SI (match_dup 0) 1) - (match_dup 3)))] - "") - -(define_split - [(set (match_operand:DI 0 "register_operand" "") - (plus:DI (match_operand:DI 1 "register_operand" "") - (match_operand:DI 2 "register_operand" ""))) - (clobber (match_operand:SI 3 "register_operand" ""))] - "reload_completed && WORDS_BIG_ENDIAN && !TARGET_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) 1) - (plus:SI (subreg:SI (match_dup 1) 1) - (subreg:SI (match_dup 2) 1))) - - (set (match_dup 3) - (ltu:SI (subreg:SI (match_dup 0) 1) - (subreg:SI (match_dup 2) 1))) - - (set (subreg:SI (match_dup 0) 0) - (plus:SI (subreg:SI (match_dup 1) 0) - (subreg:SI (match_dup 2) 0))) - - (set (subreg:SI (match_dup 0) 0) - (plus:SI (subreg:SI (match_dup 0) 0) - (match_dup 3)))] - "") - -(define_insn "adddi3_internal_2" - [(set (match_operand:DI 0 "register_operand" "=d,d,d") - (plus:DI (match_operand:DI 1 "register_operand" "%d,%d,%d") - (match_operand:DI 2 "small_int" "P,J,N"))) - (clobber (match_operand:SI 3 "register_operand" "=d,d,d"))] - "!TARGET_64BIT && !TARGET_DEBUG_G_MODE && !TARGET_MIPS16 - && (TARGET_GAS - || GET_CODE (operands[2]) != CONST_INT - || INTVAL (operands[2]) != -32768)" - "@ - addu\\t%L0,%L1,%2\;sltu\\t%3,%L0,%2\;addu\\t%M0,%M1,%3 - move\\t%L0,%L1\;move\\t%M0,%M1 - subu\\t%L0,%L1,%n2\;sltu\\t%3,%L0,%2\;subu\\t%M0,%M1,1\;addu\\t%M0,%M0,%3" - [(set_attr "type" "darith") - (set_attr "mode" "DI") - (set_attr "length" "3,2,4")]) - -(define_split - [(set (match_operand:DI 0 "register_operand" "") - (plus:DI (match_operand:DI 1 "register_operand" "") - (match_operand:DI 2 "small_int" ""))) - (clobber (match_operand:SI 3 "register_operand" "=d"))] - "reload_completed && !WORDS_BIG_ENDIAN && !TARGET_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) 1) - (plus:SI (subreg:SI (match_dup 1) 1) - (match_dup 3)))] - "") - -(define_split - [(set (match_operand:DI 0 "register_operand" "") - (plus:DI (match_operand:DI 1 "register_operand" "") - (match_operand:DI 2 "small_int" ""))) - (clobber (match_operand:SI 3 "register_operand" "=d"))] - "reload_completed && WORDS_BIG_ENDIAN && !TARGET_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) 1) - (plus:SI (subreg:SI (match_dup 1) 1) - (match_dup 2))) - - (set (match_dup 3) - (ltu:SI (subreg:SI (match_dup 0) 1) - (match_dup 2))) - - (set (subreg:SI (match_dup 0) 0) - (plus:SI (subreg:SI (match_dup 1) 0) - (match_dup 3)))] - "") - -(define_insn "adddi3_internal_3" - [(set (match_operand:DI 0 "register_operand" "=d") - (plus:DI (match_operand:DI 1 "se_reg_or_0_operand" "dJ") - (match_operand:DI 2 "se_arith_operand" "dI")))] - "TARGET_64BIT - && !TARGET_MIPS16 - && (TARGET_GAS - || GET_CODE (operands[2]) != CONST_INT - || INTVAL (operands[2]) != -32768)" - "* -{ - return (GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) < 0) - ? \"dsubu\\t%0,%z1,%n2\" - : \"daddu\\t%0,%z1,%2\"; -}" - [(set_attr "type" "darith") - (set_attr "mode" "DI") - (set_attr "length" "1")]) - -;; For the mips16, we need to recognize stack pointer additions -;; explicitly, since we don't have a constraint for $sp. These insns -;; will be generated by the save_restore_insns functions. - -(define_insn "" - [(set (reg:DI 29) - (plus:DI (reg:DI 29) - (match_operand:DI 0 "small_int" "I")))] - "TARGET_MIPS16 && TARGET_64BIT" - "daddu\\t%$,%$,%0" - [(set_attr "type" "arith") - (set_attr "mode" "DI") - (set (attr "length") (if_then_else (match_operand:VOID 0 "m16_simm8_8" "") - (const_int 1) - (const_int 2)))]) - -(define_insn "" - [(set (match_operand:DI 0 "register_operand" "=d") - (plus:DI (reg:DI 29) - (match_operand:DI 1 "small_int" "I")))] - "TARGET_MIPS16 && TARGET_64BIT" - "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" "") - (const_int 1) - (const_int 2)))]) - -(define_insn "" - [(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" "IQ,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)" - "* -{ - if (REGNO (operands[0]) == REGNO (operands[1])) - return \"daddu\\t%0,%2\"; - 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" "") - (const_int 1) - (const_int 2)) - (if_then_else (match_operand:VOID 2 "m16_simm4_1" "") - (const_int 1) - (const_int 2)) - (const_int 1)])]) - - -;; On the mips16, we can sometimes split an add of a constant which is -;; a 4 byte instruction into two adds which are both 2 byte -;; instructions. There are two cases: one where we are adding a -;; constant plus a register to another register, and one where we are -;; simply adding a constant to a register. - -(define_split - [(set (match_operand:DI 0 "register_operand" "") - (plus:DI (match_dup 0) - (match_operand:DI 1 "const_int_operand" "")))] - "TARGET_MIPS16 && TARGET_64BIT && reload_completed - && GET_CODE (operands[0]) == REG - && M16_REG_P (REGNO (operands[0])) - && GET_CODE (operands[1]) == CONST_INT - && ((INTVAL (operands[1]) > 0xf - && INTVAL (operands[1]) <= 0xf + 0xf) - || (INTVAL (operands[1]) < - 0x10 - && 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]); - - if (val >= 0) - { - operands[1] = GEN_INT (0xf); - operands[2] = GEN_INT (val - 0xf); - } - else - { - 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" "")))] - "TARGET_MIPS16 && TARGET_64BIT && reload_completed - && GET_CODE (operands[0]) == REG - && M16_REG_P (REGNO (operands[0])) - && GET_CODE (operands[1]) == REG - && M16_REG_P (REGNO (operands[1])) - && REGNO (operands[0]) != REGNO (operands[1]) - && GET_CODE (operands[2]) == CONST_INT - && ((INTVAL (operands[2]) > 0x7 - && INTVAL (operands[2]) <= 0x7 + 0xf) - || (INTVAL (operands[2]) < - 0x8 - && 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]); - - if (val >= 0) - { - operands[2] = GEN_INT (0x7); - operands[3] = GEN_INT (val - 0x7); - } - else - { - operands[2] = GEN_INT (- 0x8); - operands[3] = GEN_INT (val + 0x8); - } -}") - -(define_insn "addsi3_internal_2" - [(set (match_operand:DI 0 "register_operand" "=d") - (sign_extend:DI (plus:SI (match_operand:SI 1 "reg_or_0_operand" "dJ") - (match_operand:SI 2 "arith_operand" "dI"))))] - "TARGET_64BIT - && !TARGET_MIPS16 - && (TARGET_GAS - || GET_CODE (operands[2]) != CONST_INT - || INTVAL (operands[2]) != -32768)" - "* -{ - return (GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) < 0) - ? \"subu\\t%0,%z1,%n2\" - : \"addu\\t%0,%z1,%2\"; -}" - [(set_attr "type" "arith") - (set_attr "mode" "SI") - (set_attr "length" "1")]) - -(define_insn "" - [(set (match_operand:DI 0 "register_operand" "=d,d,d") - (sign_extend:DI (plus:SI (match_operand:SI 1 "register_operand" "0,d,d") - (match_operand:SI 2 "arith_operand" "I,O,d"))))] - "TARGET_MIPS16 && TARGET_64BIT" - "* -{ - if (REGNO (operands[0]) == REGNO (operands[1])) - return \"addu\\t%0,%2\"; - 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" "") - (const_int 1) - (const_int 2)) - (if_then_else (match_operand:VOID 2 "m16_simm4_1" "") - (const_int 1) - (const_int 2)) - (const_int 1)])]) - - -;; .................... -;; SUBTRACTION -;; .................... - -(define_insn "subdf3" - [(set (match_operand:DF 0 "register_operand" "=f") - (minus:DF (match_operand:DF 1 "register_operand" "f") - (match_operand:DF 2 "register_operand" "f")))] - "TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT" - "sub.d\\t%0,%1,%2" - [(set_attr "type" "fadd") - (set_attr "mode" "DF") - (set_attr "length" "1")]) - -(define_insn "subsf3" - [(set (match_operand:SF 0 "register_operand" "=f") - (minus:SF (match_operand:SF 1 "register_operand" "f") - (match_operand:SF 2 "register_operand" "f")))] - "TARGET_HARD_FLOAT" - "sub.s\\t%0,%1,%2" - [(set_attr "type" "fadd") - (set_attr "mode" "SF") - (set_attr "length" "1")]) - -(define_expand "subsi3" - [(set (match_operand:SI 0 "register_operand" "=d") - (minus:SI (match_operand:SI 1 "reg_or_0_operand" "dJ") - (match_operand:SI 2 "arith_operand" "dI")))] - "" - " -{ - if (GET_CODE (operands[2]) == CONST_INT - && (INTVAL (operands[2]) == -32768 - || (TARGET_MIPS16 - && INTVAL (operands[2]) == -0x4000))) - operands[2] = force_reg (SImode, operands[2]); -}") - -(define_insn "subsi3_internal" - [(set (match_operand:SI 0 "register_operand" "=d") - (minus:SI (match_operand:SI 1 "reg_or_0_operand" "dJ") - (match_operand:SI 2 "arith_operand" "dI")))] - "!TARGET_MIPS16 - && (GET_CODE (operands[2]) != CONST_INT || INTVAL (operands[2]) != -32768)" - "subu\\t%0,%z1,%2" - [(set_attr "type" "arith") - (set_attr "mode" "SI") - (set_attr "length" "1")]) - -;; For the mips16, we need to recognize stack pointer subtractions -;; explicitly, since we don't have a constraint for $sp. These insns -;; will be generated by the save_restore_insns functions. - -(define_insn "" - [(set (reg:SI 29) - (minus:SI (reg:SI 29) - (match_operand:SI 0 "small_int" "I")))] - "TARGET_MIPS16 - && (GET_CODE (operands[2]) != CONST_INT || INTVAL (operands[2]) != -32768)" - "addu\\t%$,%$,%n0" - [(set_attr "type" "arith") - (set_attr "mode" "SI") - (set (attr "length") (if_then_else (match_operand:VOID 0 "m16_nsimm8_8" "") - (const_int 1) - (const_int 2)))]) - -(define_insn "" - [(set (match_operand:SI 0 "register_operand" "=d") - (minus:SI (reg:SI 29) - (match_operand:SI 1 "small_int" "I")))] - "TARGET_MIPS16 - && (GET_CODE (operands[2]) != CONST_INT || INTVAL (operands[2]) != -32768)" - "addu\\t%0,%$,%n1" - [(set_attr "type" "arith") - (set_attr "mode" "SI") - (set (attr "length") (if_then_else (match_operand:VOID 1 "m16_nuimm8_4" "") - (const_int 1) - (const_int 2)))]) - - -(define_insn "" - [(set (match_operand:SI 0 "register_operand" "=d,d,d") - (minus:SI (match_operand:SI 1 "register_operand" "0,d,d") - (match_operand:SI 2 "arith_operand" "I,O,d")))] - "TARGET_MIPS16 - && (GET_CODE (operands[2]) != CONST_INT - || (INTVAL (operands[2]) != -32768 && INTVAL (operands[2]) != -0x4000))" - "* -{ - if (REGNO (operands[0]) == REGNO (operands[1])) - return \"subu\\t%0,%2\"; - return \"subu\\t%0,%1,%2\"; -}" - [(set_attr "type" "arith") - (set_attr "mode" "SI") - (set_attr_alternative "length" - [(if_then_else (match_operand:VOID 2 "m16_nsimm8_1" "") - (const_int 1) - (const_int 2)) - (if_then_else (match_operand:VOID 2 "m16_nsimm4_1" "") - (const_int 1) - (const_int 2)) - (const_int 1)])]) - -;; On the mips16, we can sometimes split an subtract of a constant -;; which is a 4 byte instruction into two adds which are both 2 byte -;; instructions. There are two cases: one where we are setting a -;; register to a register minus a constant, and one where we are -;; simply subtracting a constant from a register. - -(define_split - [(set (match_operand:SI 0 "register_operand" "") - (minus:SI (match_dup 0) - (match_operand:SI 1 "const_int_operand" "")))] - "TARGET_MIPS16 && reload_completed - && GET_CODE (operands[0]) == REG - && M16_REG_P (REGNO (operands[0])) - && GET_CODE (operands[1]) == CONST_INT - && ((INTVAL (operands[1]) > 0x80 - && INTVAL (operands[1]) <= 0x80 + 0x80) - || (INTVAL (operands[1]) < - 0x7f - && INTVAL (operands[1]) >= - 0x7f - 0x7f))" - [(set (match_dup 0) (minus:SI (match_dup 0) (match_dup 1))) - (set (match_dup 0) (minus:SI (match_dup 0) (match_dup 2)))] - " -{ - HOST_WIDE_INT val = INTVAL (operands[1]); - - if (val >= 0) - { - operands[1] = GEN_INT (0x80); - operands[2] = GEN_INT (val - 0x80); - } - else - { - operands[1] = GEN_INT (- 0x7f); - operands[2] = GEN_INT (val + 0x7f); - } -}") - -(define_split - [(set (match_operand:SI 0 "register_operand" "") - (minus:SI (match_operand:SI 1 "register_operand" "") - (match_operand:SI 2 "const_int_operand" "")))] - "TARGET_MIPS16 && reload_completed - && GET_CODE (operands[0]) == REG - && M16_REG_P (REGNO (operands[0])) - && GET_CODE (operands[1]) == REG - && M16_REG_P (REGNO (operands[1])) - && REGNO (operands[0]) != REGNO (operands[1]) - && GET_CODE (operands[2]) == CONST_INT - && ((INTVAL (operands[2]) > 0x8 - && INTVAL (operands[2]) <= 0x8 + 0x80) - || (INTVAL (operands[2]) < - 0x7 - && INTVAL (operands[2]) >= - 0x7 - 0x7f))" - [(set (match_dup 0) (minus:SI (match_dup 1) (match_dup 2))) - (set (match_dup 0) (minus:SI (match_dup 0) (match_dup 3)))] - " -{ - HOST_WIDE_INT val = INTVAL (operands[2]); - - if (val >= 0) - { - operands[2] = GEN_INT (0x8); - operands[3] = GEN_INT (val - 0x8); - } - else - { - operands[2] = GEN_INT (- 0x7); - operands[3] = GEN_INT (val + 0x7); - } -}") - -(define_expand "subdi3" - [(parallel [(set (match_operand:DI 0 "register_operand" "=d") - (minus:DI (match_operand:DI 1 "se_register_operand" "d") - (match_operand:DI 2 "se_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" "4")]) - -(define_split - [(set (match_operand:DI 0 "register_operand" "") - (minus:DI (match_operand:DI 1 "register_operand" "") - (match_operand:DI 2 "register_operand" ""))) - (clobber (match_operand:SI 3 "register_operand" ""))] - "reload_completed && !WORDS_BIG_ENDIAN && !TARGET_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) 1) - (minus:SI (subreg:SI (match_dup 1) 1) - (subreg:SI (match_dup 2) 1))) - - (set (subreg:SI (match_dup 0) 1) - (minus:SI (subreg:SI (match_dup 0) 1) - (match_dup 3)))] - "") - -(define_split - [(set (match_operand:DI 0 "register_operand" "") - (minus:DI (match_operand:DI 1 "register_operand" "") - (match_operand:DI 2 "register_operand" ""))) - (clobber (match_operand:SI 3 "register_operand" ""))] - "reload_completed && WORDS_BIG_ENDIAN && !TARGET_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) 1) - (subreg:SI (match_dup 2) 1))) - - (set (subreg:SI (match_dup 0) 1) - (minus:SI (subreg:SI (match_dup 1) 1) - (subreg:SI (match_dup 2) 1))) - - (set (subreg:SI (match_dup 0) 0) - (minus:SI (subreg:SI (match_dup 1) 0) - (subreg:SI (match_dup 2) 0))) - - (set (subreg:SI (match_dup 0) 0) - (minus:SI (subreg:SI (match_dup 0) 0) - (match_dup 3)))] - "") - -(define_insn "subdi3_internal_2" - [(set (match_operand:DI 0 "register_operand" "=d,d,d") - (minus:DI (match_operand:DI 1 "register_operand" "d,d,d") - (match_operand:DI 2 "small_int" "P,J,N"))) - (clobber (match_operand:SI 3 "register_operand" "=d,d,d"))] - "!TARGET_64BIT && !TARGET_DEBUG_G_MODE && !TARGET_MIPS16 - && INTVAL (operands[2]) != -32768" - "@ - sltu\\t%3,%L1,%2\;subu\\t%L0,%L1,%2\;subu\\t%M0,%M1,%3 - move\\t%L0,%L1\;move\\t%M0,%M1 - sltu\\t%3,%L1,%2\;subu\\t%L0,%L1,%2\;subu\\t%M0,%M1,1\;subu\\t%M0,%M0,%3" - [(set_attr "type" "darith") - (set_attr "mode" "DI") - (set_attr "length" "3,2,4")]) - -(define_split - [(set (match_operand:DI 0 "register_operand" "") - (minus:DI (match_operand:DI 1 "register_operand" "") - (match_operand:DI 2 "small_int" ""))) - (clobber (match_operand:SI 3 "register_operand" ""))] - "reload_completed && !WORDS_BIG_ENDIAN && !TARGET_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 (match_dup 3) - (ltu:SI (subreg:SI (match_dup 1) 0) - (match_dup 2))) - - (set (subreg:SI (match_dup 0) 0) - (minus:SI (subreg:SI (match_dup 1) 0) - (match_dup 2))) - - (set (subreg:SI (match_dup 0) 1) - (minus:SI (subreg:SI (match_dup 1) 1) - (match_dup 3)))] - "") - -(define_split - [(set (match_operand:DI 0 "register_operand" "") - (minus:DI (match_operand:DI 1 "register_operand" "") - (match_operand:DI 2 "small_int" ""))) - (clobber (match_operand:SI 3 "register_operand" ""))] - "reload_completed && WORDS_BIG_ENDIAN && !TARGET_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 (match_dup 3) - (ltu:SI (subreg:SI (match_dup 1) 1) - (match_dup 2))) - - (set (subreg:SI (match_dup 0) 1) - (minus:SI (subreg:SI (match_dup 1) 1) - (match_dup 2))) - - (set (subreg:SI (match_dup 0) 0) - (minus:SI (subreg:SI (match_dup 1) 0) - (match_dup 3)))] - "") - -(define_insn "subdi3_internal_3" - [(set (match_operand:DI 0 "register_operand" "=d") - (minus:DI (match_operand:DI 1 "se_reg_or_0_operand" "dJ") - (match_operand:DI 2 "se_arith_operand" "dI")))] - "TARGET_64BIT && !TARGET_MIPS16 - && (GET_CODE (operands[2]) != CONST_INT || INTVAL (operands[2]) != -32768)" - "* -{ - return (GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) < 0) - ? \"daddu\\t%0,%z1,%n2\" - : \"dsubu\\t%0,%z1,%2\"; -}" - [(set_attr "type" "darith") - (set_attr "mode" "DI") - (set_attr "length" "1")]) - -;; For the mips16, we need to recognize stack pointer subtractions -;; explicitly, since we don't have a constraint for $sp. These insns -;; will be generated by the save_restore_insns functions. - -(define_insn "" - [(set (reg:DI 29) - (minus:DI (reg:DI 29) - (match_operand:DI 0 "small_int" "I")))] - "TARGET_MIPS16 - && (GET_CODE (operands[2]) != CONST_INT || INTVAL (operands[2]) != -32768)" - "daddu\\t%$,%$,%n0" - [(set_attr "type" "arith") - (set_attr "mode" "DI") - (set (attr "length") (if_then_else (match_operand:VOID 0 "m16_nsimm8_8" "") - (const_int 1) - (const_int 2)))]) - -(define_insn "" - [(set (match_operand:DI 0 "register_operand" "=d") - (minus:DI (reg:DI 29) - (match_operand:DI 1 "small_int" "I")))] - "TARGET_MIPS16 - && (GET_CODE (operands[2]) != CONST_INT || INTVAL (operands[2]) != -32768)" - "daddu\\t%0,%$,%n1" - [(set_attr "type" "arith") - (set_attr "mode" "DI") - (set (attr "length") (if_then_else (match_operand:VOID 0 "m16_nuimm5_4" "") - (const_int 1) - (const_int 2)))]) - -(define_insn "" - [(set (match_operand:DI 0 "register_operand" "=d,d,d") - (minus:DI (match_operand:DI 1 "register_operand" "0,d,d") - (match_operand:DI 2 "arith_operand" "I,O,d")))] - "TARGET_MIPS16 - && (GET_CODE (operands[2]) != CONST_INT - || (INTVAL (operands[2]) != -32768 && INTVAL (operands[2]) != -0x4000))" - "* -{ - if (REGNO (operands[0]) == REGNO (operands[1])) - return \"dsubu\\t%0,%2\"; - return \"dsubu\\t%0,%1,%2\"; -}" - [(set_attr "type" "arith") - (set_attr "mode" "DI") - (set_attr_alternative "length" - [(if_then_else (match_operand:VOID 2 "m16_nsimm5_1" "") - (const_int 1) - (const_int 2)) - (if_then_else (match_operand:VOID 2 "m16_nsimm4_1" "") - (const_int 1) - (const_int 2)) - (const_int 1)])]) - -;; On the mips16, we can sometimes split an add of a constant which is -;; a 4 byte instruction into two adds which are both 2 byte -;; instructions. There are two cases: one where we are adding a -;; constant plus a register to another register, and one where we are -;; simply adding a constant to a register. - -(define_split - [(set (match_operand:DI 0 "register_operand" "") - (minus:DI (match_dup 0) - (match_operand:DI 1 "const_int_operand" "")))] - "TARGET_MIPS16 && TARGET_64BIT && reload_completed - && GET_CODE (operands[0]) == REG - && M16_REG_P (REGNO (operands[0])) - && GET_CODE (operands[1]) == CONST_INT - && ((INTVAL (operands[1]) > 0x10 - && INTVAL (operands[1]) <= 0x10 + 0x10) - || (INTVAL (operands[1]) < - 0xf - && INTVAL (operands[1]) >= - 0xf - 0xf))" - [(set (match_dup 0) (minus:DI (match_dup 0) (match_dup 1))) - (set (match_dup 0) (minus:DI (match_dup 0) (match_dup 2)))] - " -{ - HOST_WIDE_INT val = INTVAL (operands[1]); - - if (val >= 0) - { - operands[1] = GEN_INT (0xf); - operands[2] = GEN_INT (val - 0xf); - } - else - { - operands[1] = GEN_INT (- 0x10); - operands[2] = GEN_INT (val + 0x10); - } -}") - -(define_split - [(set (match_operand:DI 0 "register_operand" "") - (minus:DI (match_operand:DI 1 "register_operand" "") - (match_operand:DI 2 "const_int_operand" "")))] - "TARGET_MIPS16 && TARGET_64BIT && reload_completed - && GET_CODE (operands[0]) == REG - && M16_REG_P (REGNO (operands[0])) - && GET_CODE (operands[1]) == REG - && M16_REG_P (REGNO (operands[1])) - && REGNO (operands[0]) != REGNO (operands[1]) - && GET_CODE (operands[2]) == CONST_INT - && ((INTVAL (operands[2]) > 0x8 - && INTVAL (operands[2]) <= 0x8 + 0x10) - || (INTVAL (operands[2]) < - 0x7 - && INTVAL (operands[2]) >= - 0x7 - 0xf))" - [(set (match_dup 0) (minus:DI (match_dup 1) (match_dup 2))) - (set (match_dup 0) (minus:DI (match_dup 0) (match_dup 3)))] - " -{ - HOST_WIDE_INT val = INTVAL (operands[2]); - - if (val >= 0) - { - operands[2] = GEN_INT (0x8); - operands[3] = GEN_INT (val - 0x8); - } - else - { - operands[2] = GEN_INT (- 0x7); - operands[3] = GEN_INT (val + 0x7); - } -}") - -(define_insn "subsi3_internal_2" - [(set (match_operand:DI 0 "register_operand" "=d") - (sign_extend:DI (minus:SI (match_operand:SI 1 "reg_or_0_operand" "dJ") - (match_operand:SI 2 "arith_operand" "dI"))))] - "TARGET_64BIT && !TARGET_MIPS16 - && (GET_CODE (operands[2]) != CONST_INT || INTVAL (operands[2]) != -32768)" - "* -{ - return (GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) < 0) - ? \"addu\\t%0,%z1,%n2\" - : \"subu\\t%0,%z1,%2\"; -}" - [(set_attr "type" "arith") - (set_attr "mode" "DI") - (set_attr "length" "1")]) - -(define_insn "" - [(set (match_operand:DI 0 "register_operand" "=d,d,d") - (sign_extend:DI (minus:SI (match_operand:SI 1 "register_operand" "0,d,d") - (match_operand:SI 2 "arith_operand" "I,O,d"))))] - "TARGET_64BIT && TARGET_MIPS16 - && (GET_CODE (operands[2]) != CONST_INT - || (INTVAL (operands[2]) != -32768 && INTVAL (operands[2]) != -0x4000))" - "* -{ - if (REGNO (operands[0]) == REGNO (operands[1])) - return \"subu\\t%0,%2\"; - return \"subu\\t%0,%1,%2\"; -}" - [(set_attr "type" "arith") - (set_attr "mode" "SI") - (set_attr_alternative "length" - [(if_then_else (match_operand:VOID 2 "m16_nsimm8_1" "") - (const_int 1) - (const_int 2)) - (if_then_else (match_operand:VOID 2 "m16_nsimm4_1" "") - (const_int 1) - (const_int 2)) - (const_int 1)])]) - - - -;; .................... -;; MULTIPLICATION -;; .................... - -;; 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")))] - "TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT" - " -{ - if (mips_cpu != PROCESSOR_R4300) - 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 && mips_cpu != PROCESSOR_R4300" - "mul.d\\t%0,%1,%2" - [(set_attr "type" "fmul") - (set_attr "mode" "DF") - (set_attr "length" "1")]) - -(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 && mips_cpu == PROCESSOR_R4300" - "* -{ - output_asm_insn (\"mul.d\\t%0,%1,%2\", operands); - if (TARGET_4300_MUL_FIX) - output_asm_insn (\"nop\", operands); - return \"\"; -}" - [(set_attr "type" "fmul") - (set_attr "mode" "DF") - (set_attr "length" "2")]) ;; mul.d + nop - -(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")))] - "TARGET_HARD_FLOAT" - " -{ - if (mips_cpu != PROCESSOR_R4300) - 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 && mips_cpu != PROCESSOR_R4300" - "mul.s\\t%0,%1,%2" - [(set_attr "type" "fmul") - (set_attr "mode" "SF") - (set_attr "length" "1")]) - -(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 && mips_cpu == PROCESSOR_R4300" - "* -{ - output_asm_insn (\"mul.s\\t%0,%1,%2\", operands); - if (TARGET_4300_MUL_FIX) - output_asm_insn (\"nop\", operands); - return \"\"; -}" - [(set_attr "type" "fmul") - (set_attr "mode" "SF") - (set_attr "length" "2")]) ;; mul.s + nop - - -;; ??? 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. - -(define_expand "mulsi3" - [(set (match_operand:SI 0 "register_operand" "=l") - (mult:SI (match_operand:SI 1 "register_operand" "d") - (match_operand:SI 2 "register_operand" "d"))) - (clobber (match_scratch:SI 3 "=h")) - (clobber (match_scratch:SI 4 "=a"))] - "" - " -{ - if (HAVE_mulsi3_mult3) - emit_insn (gen_mulsi3_mult3 (operands[0], operands[1], operands[2])); - else if (mips_cpu != PROCESSOR_R4000 || TARGET_MIPS16) - 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") - (mult:SI (match_operand:SI 1 "register_operand" "d,d") - (match_operand:SI 2 "register_operand" "d,d"))) - (clobber (match_scratch:SI 3 "=h,h")) - (clobber (match_scratch:SI 4 "=l,X")) - (clobber (match_scratch:SI 5 "=a,a"))] - "(GENERATE_MULT3 - || TARGET_MIPS5400 /* CYGNUS LOCAL vr5400/raeburn */ - || TARGET_MAD) - && !0" ;; CYGNUS LOCAL law - "* -{ - if (which_alternative == 1) - return \"mult\\t%1,%2\"; - if (TARGET_MIPS5400 /* CYGNUS LOCAL vr5400/raeburn */ - || TARGET_MAD) - return \"mul\\t%0,%1,%2\"; - return \"mult\\t%0,%1,%2\"; -}" - [(set_attr "type" "imul") - (set_attr "mode" "SI") - (set_attr "length" "1")]) - -(define_insn "mulsi3_internal" - [(set (match_operand:SI 0 "register_operand" "=l") - (mult:SI (match_operand:SI 1 "register_operand" "d") - (match_operand:SI 2 "register_operand" "d"))) - (clobber (match_scratch:SI 3 "=h")) - (clobber (match_scratch:SI 4 "=a"))] - "mips_cpu != PROCESSOR_R4000 || TARGET_MIPS16" - "mult\\t%1,%2" - [(set_attr "type" "imul") - (set_attr "mode" "SI") - (set_attr "length" "1")]) - -(define_insn "mulsi3_r4000" - [(set (match_operand:SI 0 "register_operand" "=d") - (mult:SI (match_operand:SI 1 "register_operand" "d") - (match_operand:SI 2 "register_operand" "d"))) - (clobber (match_scratch:SI 3 "=h")) - (clobber (match_scratch:SI 4 "=l")) - (clobber (match_scratch:SI 5 "=a"))] - "mips_cpu == PROCESSOR_R4000 && !TARGET_MIPS16" - "* -{ - rtx xoperands[10]; - - xoperands[0] = operands[0]; - xoperands[1] = gen_rtx (REG, SImode, LO_REGNUM); - - output_asm_insn (\"mult\\t%1,%2\", operands); - output_asm_insn (mips_move_1word (xoperands, insn, FALSE), xoperands); - return \"\"; -}" - [(set_attr "type" "imul") - (set_attr "mode" "SI") - (set_attr "length" "3")]) ;; mult + mflo + delay - -;; Multiply-accumulate patterns - -;; For processors that can copy the output to a general register: -;; The all-d alternative is needed because the combiner will find this -;; pattern and then register alloc/reload will move registers around to -;; make them fit, and we don't want to trigger unnecessary loads to LO. -;; The last alternative should be made slightly less desirable, but adding -;; "?" to the constraint is too strong, and causes values to be loaded into -;; LO even when that's more costly. For now, using "*d" mostly does the -;; trick. - -(define_insn "*mul_acc_si" - [(set (match_operand:SI 0 "register_operand" "=l,*d,*d") - (plus:SI (mult:SI (match_operand:SI 1 "register_operand" "d,d,d") - (match_operand:SI 2 "register_operand" "d,d,d")) - (match_operand:SI 3 "register_operand" "0,l,*d"))) - (clobber (match_scratch:SI 4 "=h,h,h")) - (clobber (match_scratch:SI 5 "=X,3,l")) - (clobber (match_scratch:SI 6 "=a,a,a")) - (clobber (match_scratch:SI 7 "=X,X,d"))] - "(TARGET_MIPS3900 - || TARGET_MIPS5400) /* CYGNUS LOCAL vr5400/raeburn */ - && !TARGET_MIPS16" - "* -{ - static char *const madd[] = { \"madd\\t%1,%2\", \"madd\\t%0,%1,%2\" }; - static char *const macc[] = { \"macc\\t$0,%1,%2\", \"macc\\t%0,%1,%2\" }; /* CYGNUS LOCAL vr5400/raeburn */ - if (which_alternative == 2) - return \"#\"; - /* CYGNUS LOCAL vr5400/raeburn */ - if (TARGET_MIPS5400) - return macc[which_alternative]; - /* END CYGNUS LOCAL */ - return madd[which_alternative]; -}" - [(set_attr "type" "imul,imul,multi") - (set_attr "mode" "SI") - (set_attr "length" "1,1,2")]) - -;; 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 "")) - (clobber (match_scratch:SI 7 ""))] - "reload_completed && GP_REG_P (true_regnum (operands[0])) && GP_REG_P (true_regnum (operands[3]))" - [(parallel [(set (match_dup 7) - (mult:SI (match_dup 1) (match_dup 2))) - (clobber (match_dup 4)) - (clobber (match_dup 5)) - (clobber (match_dup 6))]) - (set (match_dup 0) (plus:SI (match_dup 7) (match_dup 3)))] - "") - -;; CYGNUS LOCAL vr5400/raeburn -(define_insn "*muls_r5400" - [(set (match_operand:SI 0 "register_operand" "=l,d") - (neg:SI (mult:SI (match_operand:SI 1 "register_operand" "d,d") - (match_operand:SI 2 "register_operand" "d,d")))) - (clobber (match_scratch:SI 3 "=h,h")) - (clobber (match_scratch:SI 4 "=a,a")) - (clobber (match_scratch:SI 5 "=X,l"))] - "TARGET_MIPS5400" - "@ - muls\\t$0,%1,%2 - muls\\t%0,%1,%2" - [(set_attr "type" "imul") - (set_attr "mode" "SI")]) - -;; See comments above for mul_acc_si. -(define_insn "*msac_r5400" - [(set (match_operand:SI 0 "register_operand" "=l,*d,*d") - (minus:SI (match_operand:SI 1 "register_operand" "0,l,*d") - (mult:SI (match_operand:SI 2 "register_operand" "d,d,d") - (match_operand:SI 3 "register_operand" "d,d,d")))) - (clobber (match_scratch:SI 4 "=h,h,h")) - (clobber (match_scratch:SI 5 "=X,1,l")) - (clobber (match_scratch:SI 6 "=a,a,a")) - (clobber (match_scratch:SI 7 "=X,X,d"))] - "TARGET_MIPS5400" - "@ - msac\\t$0,%2,%3 - msac\\t%0,%2,%3 - #" - [(set_attr "type" "imul,imul,multi") - (set_attr "mode" "SI") - (set_attr "length" "1,1,2")]) - -(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 "")) - (clobber (match_scratch:SI 7 ""))] - "reload_completed && GP_REG_P (true_regnum (operands[0])) && GP_REG_P (true_regnum (operands[1]))" - [(parallel [(set (match_dup 7) - (mult:SI (match_dup 2) (match_dup 3))) - (clobber (match_dup 4)) - (clobber (match_dup 5)) - (clobber (match_dup 6))]) - (set (match_dup 0) (minus:SI (match_dup 1) (match_dup 7)))] - "") -;; END CYGNUS LOCAL - -(define_expand "muldi3" - [(set (match_operand:DI 0 "register_operand" "=l") - (mult:DI (match_operand:DI 1 "se_register_operand" "d") - (match_operand:DI 2 "register_operand" "d"))) - (clobber (match_scratch:DI 3 "=h")) - (clobber (match_scratch:DI 4 "=a"))] - "TARGET_64BIT && !0" ;; CYGNUS LOCAL law - - " -{ - if (GENERATE_MULT3 || mips_cpu == PROCESSOR_R4000 || TARGET_MIPS16) - emit_insn (gen_muldi3_internal2 (operands[0], operands[1], operands[2])); - else - emit_insn (gen_muldi3_internal (operands[0], operands[1], operands[2])); - DONE; -}") - -;; Don't accept both operands using se_register_operand, because if -;; both operands are sign extended we would prefer to use mult in the -;; mulsidi3 pattern. Commutativity should permit either operand to be -;; sign extended. - -(define_insn "muldi3_internal" - [(set (match_operand:DI 0 "register_operand" "=l") - (mult:DI (match_operand:DI 1 "se_register_operand" "d") - (match_operand:DI 2 "register_operand" "d"))) - (clobber (match_scratch:DI 3 "=h")) - (clobber (match_scratch:DI 4 "=a"))] - "TARGET_64BIT && mips_cpu != PROCESSOR_R4000 && !TARGET_MIPS16 && !0" ;; CYGNUS LOCAL law - "dmult\\t%1,%2" - [(set_attr "type" "imul") - (set_attr "mode" "DI") - (set_attr "length" "1")]) - -(define_insn "muldi3_internal2" - [(set (match_operand:DI 0 "register_operand" "=d") - (mult:DI (match_operand:DI 1 "se_register_operand" "d") - (match_operand:DI 2 "register_operand" "d"))) - (clobber (match_scratch:DI 3 "=h")) - (clobber (match_scratch:DI 4 "=l")) - (clobber (match_scratch:DI 5 "=a"))] - "TARGET_64BIT && (GENERATE_MULT3 || mips_cpu == PROCESSOR_R4000 || TARGET_MIPS16) && !0" ;; CYGNUS LOCAL law - "* -{ - if (GENERATE_MULT3) - output_asm_insn (\"dmult\\t%0,%1,%2\", operands); - else - { - rtx xoperands[10]; - - xoperands[0] = operands[0]; - xoperands[1] = gen_rtx (REG, DImode, LO_REGNUM); - - output_asm_insn (\"dmult\\t%1,%2\", operands); - output_asm_insn (mips_move_1word (xoperands, insn, FALSE), xoperands); - } - return \"\"; -}" - [(set_attr "type" "imul") - (set_attr "mode" "DI") - (set (attr "length") - (if_then_else (ne (symbol_ref "GENERATE_MULT3") (const_int 0)) - (const_int 1) - (const_int 3)))]) ;; mult + mflo + delay - -;; ??? We could define a mulditi3 pattern when TARGET_64BIT. - -(define_expand "mulsidi3" - [(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"))))] - "" - " -{ - rtx dummy = gen_rtx (SIGN_EXTEND, DImode, const0_rtx); - if (TARGET_64BIT) - emit_insn (gen_mulsidi3_64bit (operands[0], operands[1], operands[2], - dummy, dummy)); - else - emit_insn (gen_mulsidi3_internal (operands[0], operands[1], operands[2], - dummy, dummy)); - DONE; -}") - -(define_expand "umulsidi3" - [(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"))))] - "" - " -{ - rtx dummy = gen_rtx (ZERO_EXTEND, DImode, const0_rtx); - if (TARGET_64BIT) - emit_insn (gen_mulsidi3_64bit (operands[0], operands[1], operands[2], - dummy, dummy)); - else - emit_insn (gen_mulsidi3_internal (operands[0], operands[1], operands[2], - dummy, dummy)); - DONE; -}") - -(define_insn "mulsidi3_internal" - [(set (match_operand:DI 0 "register_operand" "=x") - (mult:DI (match_operator:DI 3 "extend_operator" - [(match_operand:SI 1 "register_operand" "d")]) - (match_operator:DI 4 "extend_operator" - [(match_operand:SI 2 "register_operand" "d")]))) - (clobber (match_scratch:SI 5 "=a"))] - "!TARGET_64BIT && GET_CODE (operands[3]) == GET_CODE (operands[4])" - "* -{ - if (GET_CODE (operands[3]) == SIGN_EXTEND) - return \"mult\\t%1,%2\"; - return \"multu\\t%1,%2\"; -}" - [(set_attr "type" "imul") - (set_attr "mode" "SI") - (set_attr "length" "1")]) - - -(define_insn "mulsidi3_64bit" - [(set (match_operand:DI 0 "register_operand" "=a") - (mult:DI (match_operator:DI 3 "extend_operator" - [(match_operand:SI 1 "register_operand" "d")]) - (match_operator:DI 4 "extend_operator" - [(match_operand:SI 2 "register_operand" "d")]))) - (clobber (match_scratch:DI 5 "=l")) - (clobber (match_scratch:DI 6 "=h"))] - "TARGET_64BIT && !0 && GET_CODE (operands[3]) == GET_CODE (operands[4])" ;; CYGNUS LOCAL law - "* -{ - if (GET_CODE (operands[3]) == SIGN_EXTEND) - return \"mult\\t%1,%2\"; - return \"multu\\t%1,%2\"; -}" - [(set_attr "type" "imul") - (set_attr "mode" "SI") - (set_attr "length" "1")]) - -;; CYGNUS LOCAL vr5400/raeburn - -;; widening multiply with accumulator and/or negation -;; These don't match yet for zero-extending; too complex for combine? -;; Possible additions we should have: -;; "=x" variants for when !TARGET_64BIT ? -;; all-d alternatives with splits like pure SImode versions -(define_insn "*muls_r5400_di" - [(set (match_operand:DI 0 "register_operand" "=a") - (neg:DI - (mult:DI (match_operator:DI 3 "extend_operator" - [(match_operand:SI 1 "register_operand" "d")]) - (match_operator:DI 4 "extend_operator" - [(match_operand:SI 2 "register_operand" "d")])))) - (clobber (match_scratch:SI 5 "=h")) - (clobber (match_scratch:SI 6 "=l"))] - "TARGET_64BIT && TARGET_MIPS5400 && GET_CODE (operands[3]) == GET_CODE (operands[4])" - "* -{ - if (GET_CODE (operands[3]) == SIGN_EXTEND) - return \"muls\\t$0,%1,%2\"; - else - return \"mulsu\\t$0,%1,%2\"; -}" - [(set_attr "type" "imul") - (set_attr "mode" "SI")]) - -(define_insn "*msac_r5400_di" - [(set (match_operand:DI 0 "register_operand" "=a") - (minus:DI (match_operand:DI 3 "register_operand" "0") - (mult:DI (match_operator:DI 4 "extend_operator" - [(match_operand:SI 1 "register_operand" "d")]) - (match_operator:DI 5 "extend_operator" - [(match_operand:SI 2 "register_operand" "d")])))) - (clobber (match_scratch:SI 6 "=h")) - (clobber (match_scratch:SI 7 "=l"))] - "TARGET_64BIT && TARGET_MIPS5400 && GET_CODE (operands[4]) == GET_CODE (operands[5])" - "* -{ - if (GET_CODE (operands[4]) == SIGN_EXTEND) - return \"msac\\t$0,%1,%2\"; - else - return \"msacu\\t$0,%1,%2\"; -}" - [(set_attr "type" "imul") - (set_attr "mode" "SI")]) -;; END CYGNUS LOCAL - -;; _highpart patterns -(define_expand "smulsi3_highpart" - [(set (match_operand:SI 0 "register_operand" "=h") - (truncate:SI - (lshiftrt:DI (mult:DI (sign_extend:DI (match_operand:SI 1 "register_operand" "d")) - (sign_extend:DI (match_operand:SI 2 "register_operand" "d"))) - (const_int 32))))] - "" - " -{ - rtx dummy = gen_rtx (SIGN_EXTEND, DImode, const0_rtx); - rtx dummy2 = gen_rtx_LSHIFTRT (DImode, const0_rtx, const0_rtx); -#ifndef NO_MD_PROTOTYPES - rtx (*genfn) PROTO((rtx, rtx, rtx, rtx, rtx, rtx)); -#else - rtx (*genfn) (); -#endif - genfn = gen_xmulsi3_highpart_internal; - /* CYGNUS LOCAL vr5400/raeburn */ - if (TARGET_MIPS5400) - genfn = gen_xmulsi3_highpart_5400; - /* END CYGNUS LOCAL */ - emit_insn ((*genfn) (operands[0], operands[1], operands[2], dummy, - dummy, dummy2)); - DONE; -}") - -(define_expand "umulsi3_highpart" - [(set (match_operand:SI 0 "register_operand" "=h") - (truncate:SI - (lshiftrt:DI (mult:DI (zero_extend:DI (match_operand:SI 1 "register_operand" "d")) - (zero_extend:DI (match_operand:SI 2 "register_operand" "d"))) - (const_int 32))))] - "" - " -{ - rtx dummy = gen_rtx (ZERO_EXTEND, DImode, const0_rtx); - rtx dummy2 = gen_rtx_LSHIFTRT (DImode, const0_rtx, const0_rtx); -#ifndef NO_MD_PROTOTYPES - rtx (*genfn) PROTO((rtx, rtx, rtx, rtx, rtx, rtx)); -#else - rtx (*genfn) (); -#endif - genfn = gen_xmulsi3_highpart_internal; - /* CYGNUS LOCAL vr5400/raeburn */ - if (TARGET_MIPS5400) - genfn = gen_xmulsi3_highpart_5400; - /* END CYGNUS LOCAL */ - emit_insn ((*genfn) (operands[0], operands[1], operands[2], dummy, - dummy, dummy2)); - DONE; -}") - - -(define_insn "xmulsi3_highpart_internal" - [(set (match_operand:SI 0 "register_operand" "=h") - (truncate:SI - (match_operator:DI 5 "highpart_shift_operator" - [(mult:DI (match_operator:DI 3 "extend_operator" - [(match_operand:SI 1 "register_operand" "d")]) - (match_operator:DI 4 "extend_operator" - [(match_operand:SI 2 "register_operand" "d")])) - (const_int 32)]))) - (clobber (match_scratch:SI 6 "=l")) - (clobber (match_scratch:SI 7 "=a"))] - "! TARGET_MIPS5400 && !0 && GET_CODE (operands[3]) == GET_CODE (operands[4])" ;; CYGNUS LOCAL vr5400/raeburn ;; CYGNUS LOCAL law - "* -{ - if (GET_CODE (operands[3]) == SIGN_EXTEND) - return \"mult\\t%1,%2\"; - else - return \"multu\\t%1,%2\"; -}" - [(set_attr "type" "imul") - (set_attr "mode" "SI") - (set_attr "length" "1")]) - -;; CYGNUS LOCAL vr5400/raeburn -(define_insn "xmulsi3_highpart_5400" - [(set (match_operand:SI 0 "register_operand" "=h,d") - (truncate:SI - (match_operator:DI 5 "highpart_shift_operator" - [(mult:DI (match_operator:DI 3 "extend_operator" - [(match_operand:SI 1 "register_operand" "d,d")]) - (match_operator:DI 4 "extend_operator" - [(match_operand:SI 2 "register_operand" "d,d")])) - (const_int 32)]))) - (clobber (match_scratch:SI 6 "=l,l")) - (clobber (match_scratch:SI 7 "=a,a")) - (clobber (match_scratch:SI 8 "=X,h"))] - "TARGET_MIPS5400 && GET_CODE (operands[3]) == GET_CODE (operands[4])" - "* -{ - char *const sign[] = { \"mult\\t%1,%2\", \"mulhi\\t%0,%1,%2\" }; - char *const zero[] = { \"multu\\t%1,%2\", \"mulhiu\\t%0,%1,%2\" }; - if (GET_CODE (operands[3]) == SIGN_EXTEND) - return sign[which_alternative]; - else - return zero[which_alternative]; -}" - [(set_attr "type" "imul") - (set_attr "mode" "SI") - (set_attr "length" "1")]) - -(define_insn "*xmulsi3_neg_highpart_5400" - [(set (match_operand:SI 0 "register_operand" "=h,d") - (truncate:SI - (match_operator:DI 5 "highpart_shift_operator" - [(neg:DI - (mult:DI (match_operator:DI 3 "extend_operator" - [(match_operand:SI 1 "register_operand" "d,d")]) - (match_operator:DI 4 "extend_operator" - [(match_operand:SI 2 "register_operand" "d,d")]))) - (const_int 32)]))) - (clobber (match_scratch:SI 6 "=l,l")) - (clobber (match_scratch:SI 7 "=a,a")) - (clobber (match_scratch:SI 8 "=X,h"))] - "TARGET_MIPS5400 && GET_CODE (operands[3]) == GET_CODE (operands[4])" - "* -{ - char *const sign[] = { \"mulshi\\t$0,%1,%2\", \"mulshi\\t%0,%1,%2\" }; - char *const zero[] = { \"mulshiu\\t$0,%1,%2\", \"mulshiu\\t%0,%1,%2\" }; - if (GET_CODE (operands[3]) == SIGN_EXTEND) - return sign[which_alternative]; - else - return zero[which_alternative]; -}" - [(set_attr "type" "imul") - (set_attr "mode" "SI") - (set_attr "length" "1")]) -;; END CYGNUS LOCAL - -(define_insn "smuldi3_highpart" - [(set (match_operand:DI 0 "register_operand" "=h") - (truncate:DI - (lshiftrt:TI (mult:TI (sign_extend:TI (match_operand:DI 1 "se_register_operand" "d")) - (sign_extend:TI (match_operand:DI 2 "se_register_operand" "d"))) - (const_int 64)))) - (clobber (match_scratch:DI 3 "=l")) - (clobber (match_scratch:DI 4 "=a"))] - "TARGET_64BIT && !0" ;; CYGNUS LOCAL law - "dmult\\t%1,%2" - [(set_attr "type" "imul") - (set_attr "mode" "DI") - (set_attr "length" "1")]) - -(define_insn "umuldi3_highpart" - [(set (match_operand:DI 0 "register_operand" "=h") - (truncate:DI - (lshiftrt:TI (mult:TI (zero_extend:TI (match_operand:DI 1 "se_register_operand" "d")) - (zero_extend:TI (match_operand:DI 2 "se_register_operand" "d"))) - (const_int 64)))) - (clobber (match_scratch:DI 3 "=l")) - (clobber (match_scratch:DI 4 "=a"))] - "TARGET_64BIT && !0" ;; CYGNUS LOCAL law - "dmultu\\t%1,%2" - [(set_attr "type" "imul") - (set_attr "mode" "DI") - (set_attr "length" "1")]) - -;; The R4650 supports a 32 bit multiply/ 64 bit accumulate -;; instruction. The HI/LO registers are used as a 64 bit accumulator. - -(define_insn "madsi" - [(set (match_operand:SI 0 "register_operand" "+l") - (plus:SI (mult:SI (match_operand:SI 1 "register_operand" "d") - (match_operand:SI 2 "register_operand" "d")) - (match_dup 0))) - (clobber (match_scratch:SI 3 "=h")) - (clobber (match_scratch:SI 4 "=a"))] - "TARGET_MAD" - "mad\\t%1,%2" - [(set_attr "type" "imul") - (set_attr "mode" "SI") - (set_attr "length" "1")]) - -(define_insn "*mul_acc_di" - [(set (match_operand:DI 0 "register_operand" "+x") - (plus:DI (mult:DI (match_operator:DI 3 "extend_operator" - [(match_operand:SI 1 "register_operand" "d")]) - (match_operator:DI 4 "extend_operator" - [(match_operand:SI 2 "register_operand" "d")])) - (match_dup 0))) - (clobber (match_scratch:SI 5 "=a"))] - "TARGET_MAD - && ! TARGET_64BIT - && GET_CODE (operands[3]) == GET_CODE (operands[4])" - "* -{ - if (GET_CODE (operands[3]) == SIGN_EXTEND) - return \"mad\\t%1,%2\"; - else - return \"madu\\t%1,%2\"; -}" - [(set_attr "type" "imul") - (set_attr "mode" "SI") - (set_attr "length" "1")]) - -(define_insn "*mul_acc_64bit_di" - [(set (match_operand:DI 0 "register_operand" "+a") - (plus:DI (mult:DI (match_operator:DI 3 "extend_operator" - [(match_operand:SI 1 "register_operand" "d")]) - (match_operator:DI 4 "extend_operator" - [(match_operand:SI 2 "register_operand" "d")])) - (match_dup 0))) - (clobber (match_scratch:SI 5 "=h")) - (clobber (match_scratch:SI 6 "=l"))] - "(TARGET_MAD || TARGET_MIPS5400) /* CYGNUS LOCAL vr5400/raeburn */ - && TARGET_64BIT && GET_CODE (operands[3]) == GET_CODE (operands[4])" - "* -{ - if (TARGET_MAD) - { - if (GET_CODE (operands[3]) == SIGN_EXTEND) - return \"mad\\t%1,%2\"; - else - return \"madu\\t%1,%2\"; - } - /* CYGNUS LOCAL vr5400/raeburn */ - else if (TARGET_MIPS5400) - { - if (GET_CODE (operands[3]) == SIGN_EXTEND) - return \"macc\\t$0,%1,%2\"; - else - return \"maccu\\t$0,%1,%2\"; - } - /* END CYGNUS LOCAL */ - else - abort (); -}" - [(set_attr "type" "imul") - (set_attr "mode" "SI") - (set_attr "length" "1")]) - -;; Floating point multiply accumulate instructions. - -(define_insn "" - [(set (match_operand:DF 0 "register_operand" "=f") - (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")))] - "mips_isa >= 4 && TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT" - "madd.d\\t%0,%3,%1,%2" - [(set_attr "type" "fmadd") - (set_attr "mode" "DF") - (set_attr "length" "1")]) - -(define_insn "" - [(set (match_operand:SF 0 "register_operand" "=f") - (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")))] - "mips_isa >= 4 && TARGET_HARD_FLOAT" - "madd.s\\t%0,%3,%1,%2" - [(set_attr "type" "fmadd") - (set_attr "mode" "SF") - (set_attr "length" "1")]) - -(define_insn "" - [(set (match_operand:DF 0 "register_operand" "=f") - (minus:DF (mult:DF (match_operand:DF 1 "register_operand" "f") - (match_operand:DF 2 "register_operand" "f")) - (match_operand:DF 3 "register_operand" "f")))] - "mips_isa >= 4 && TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT" - "msub.d\\t%0,%3,%1,%2" - [(set_attr "type" "fmadd") - (set_attr "mode" "DF") - (set_attr "length" "1")]) - -(define_insn "" - [(set (match_operand:SF 0 "register_operand" "=f") - (minus:SF (mult:SF (match_operand:SF 1 "register_operand" "f") - (match_operand:SF 2 "register_operand" "f")) - (match_operand:SF 3 "register_operand" "f")))] - - "mips_isa >= 4 && TARGET_HARD_FLOAT" - "msub.s\\t%0,%3,%1,%2" - [(set_attr "type" "fmadd") - (set_attr "mode" "SF") - (set_attr "length" "1")]) - -(define_insn "" - [(set (match_operand:DF 0 "register_operand" "=f") - (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"))))] - "mips_isa >= 4 && TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT" - "nmadd.d\\t%0,%3,%1,%2" - [(set_attr "type" "fmadd") - (set_attr "mode" "DF") - (set_attr "length" "1")]) - -(define_insn "" - [(set (match_operand:SF 0 "register_operand" "=f") - (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"))))] - "mips_isa >= 4 && TARGET_HARD_FLOAT" - "nmadd.s\\t%0,%3,%1,%2" - [(set_attr "type" "fmadd") - (set_attr "mode" "SF") - (set_attr "length" "1")]) - -(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"))))] - "mips_isa >= 4 && TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT" - "nmsub.d\\t%0,%1,%2,%3" - [(set_attr "type" "fmadd") - (set_attr "mode" "DF") - (set_attr "length" "1")]) - -(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"))))] - "mips_isa >= 4 && TARGET_HARD_FLOAT" - "nmsub.s\\t%0,%1,%2,%3" - [(set_attr "type" "fmadd") - (set_attr "mode" "SF") - (set_attr "length" "1")]) - -;; .................... -;; DIVISION and REMAINDER -;; .................... - -(define_insn "divdf3" - [(set (match_operand:DF 0 "register_operand" "=f") - (div:DF (match_operand:DF 1 "register_operand" "f") - (match_operand:DF 2 "register_operand" "f")))] - "TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT" - "div.d\\t%0,%1,%2" - [(set_attr "type" "fdiv") - (set_attr "mode" "DF") - (set_attr "length" "1")]) - -(define_insn "divsf3" - [(set (match_operand:SF 0 "register_operand" "=f") - (div:SF (match_operand:SF 1 "register_operand" "f") - (match_operand:SF 2 "register_operand" "f")))] - "TARGET_HARD_FLOAT" - "div.s\\t%0,%1,%2" - [(set_attr "type" "fdiv") - (set_attr "mode" "SF") - (set_attr "length" "1")]) - -(define_insn "" - [(set (match_operand:DF 0 "register_operand" "=f") - (div:DF (match_operand:DF 1 "const_float_1_operand" "") - (match_operand:DF 2 "register_operand" "f")))] - "mips_isa >= 4 && TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT && flag_fast_math" - "recip.d\\t%0,%2" - [(set_attr "type" "fdiv") - (set_attr "mode" "DF") - (set_attr "length" "1")]) - -(define_insn "" - [(set (match_operand:SF 0 "register_operand" "=f") - (div:SF (match_operand:SF 1 "const_float_1_operand" "") - (match_operand:SF 2 "register_operand" "f")))] - "mips_isa >= 4 && TARGET_HARD_FLOAT && flag_fast_math" - "recip.s\\t%0,%2" - [(set_attr "type" "fdiv") - (set_attr "mode" "SF") - (set_attr "length" "1")]) - -;; If optimizing, prefer the divmod functions over separate div and -;; mod functions, since this will allow using one instruction for both -;; the quotient and remainder. At present, the divmod is not moved out -;; of loops if it is constant within the loop, so allow -mdebugc to -;; use the old method of doing things. - -;; 64 is the multiply/divide hi register -;; 65 is the multiply/divide lo register - -;; ??? We can't accept constants here, because the MIPS assembler will replace -;; a divide by power of 2 with a shift, and then the remainder is no longer -;; available. - -(define_expand "divmodsi4" - [(set (match_operand:SI 0 "register_operand" "=d") - (div:SI (match_operand:SI 1 "register_operand" "d") - (match_operand:SI 2 "register_operand" "d"))) - (set (match_operand:SI 3 "register_operand" "=d") - (mod:SI (match_dup 1) - (match_dup 2))) - (clobber (match_scratch:SI 4 "=l")) - (clobber (match_scratch:SI 5 "=h")) - (clobber (match_scratch:SI 6 "=a"))] - "optimize" - " -{ - rtx label; - - - emit_insn (gen_divmodsi4_internal (operands[0], operands[1], operands[2], - operands[3])); - if (!TARGET_NO_CHECK_ZERO_DIV) - { - emit_insn (gen_div_trap (operands[2], - GEN_INT (0), - GEN_INT (0x7))); - } - if (TARGET_CHECK_RANGE_DIV) - { - emit_insn (gen_div_trap (operands[2], - copy_to_mode_reg (SImode, GEN_INT (-1)), - GEN_INT (0x6))); - emit_insn (gen_div_trap (operands[2], - copy_to_mode_reg (SImode, GEN_INT (0x80000000)), - GEN_INT (0x6))); - } - - DONE; -}") - - -(define_insn "divmodsi4_internal" - [(set (match_operand:SI 0 "register_operand" "=l") - (div:SI (match_operand:SI 1 "register_operand" "d") - (match_operand:SI 2 "register_operand" "d"))) - (set (match_operand:SI 3 "register_operand" "=h") - (mod:SI (match_dup 1) - (match_dup 2))) - (clobber (match_scratch:SI 6 "=a"))] - "optimize && !0" ;; CYGNUS LOCAL law - "div\\t$0,%1,%2" - [(set_attr "type" "idiv") - (set_attr "mode" "SI") - (set_attr "length" "1")]) - -(define_expand "divmoddi4" - [(set (match_operand:DI 0 "register_operand" "=d") - (div:DI (match_operand:DI 1 "se_register_operand" "d") - (match_operand:DI 2 "se_register_operand" "d"))) - (set (match_operand:DI 3 "register_operand" "=d") - (mod:DI (match_dup 1) - (match_dup 2))) - (clobber (match_scratch:DI 4 "=l")) - (clobber (match_scratch:DI 5 "=h")) - (clobber (match_scratch:DI 6 "=a"))] - "TARGET_64BIT && optimize && !0" ;; CYGNUS LOCAL law - " -{ - rtx label; - - emit_insn (gen_divmoddi4_internal (operands[0], operands[1], operands[2], - operands[3])); - if (!TARGET_NO_CHECK_ZERO_DIV) - { - emit_insn (gen_div_trap (operands[2], - GEN_INT (0), - GEN_INT (0x7))); - } - if (TARGET_CHECK_RANGE_DIV) - { - emit_insn (gen_div_trap (operands[2], - copy_to_mode_reg (DImode, GEN_INT (-1)), - GEN_INT (0x6))); - emit_insn (gen_div_trap (operands[2], - copy_to_mode_reg (DImode, GEN_INT (0x80000000)), - GEN_INT (0x6))); - } - - DONE; -}") - -(define_insn "divmoddi4_internal" - [(set (match_operand:DI 0 "register_operand" "=l") - (div:DI (match_operand:DI 1 "se_register_operand" "d") - (match_operand:DI 2 "se_register_operand" "d"))) - (set (match_operand:DI 3 "register_operand" "=h") - (mod:DI (match_dup 1) - (match_dup 2))) - (clobber (match_scratch:DI 6 "=a"))] - "TARGET_64BIT && optimize && !0" ;; CYGNUS LOCAL law - "ddiv\\t$0,%1,%2" - [(set_attr "type" "idiv") - (set_attr "mode" "SI") - (set_attr "length" "1")]) - -(define_expand "udivmodsi4" - [(set (match_operand:SI 0 "register_operand" "=d") - (udiv:SI (match_operand:SI 1 "register_operand" "d") - (match_operand:SI 2 "register_operand" "d"))) - (set (match_operand:SI 3 "register_operand" "=d") - (umod:SI (match_dup 1) - (match_dup 2))) - (clobber (match_scratch:SI 4 "=l")) - (clobber (match_scratch:SI 5 "=h")) - (clobber (match_scratch:SI 6 "=a"))] - "optimize" - " -{ - rtx label; - - emit_insn (gen_udivmodsi4_internal (operands[0], operands[1], operands[2], - operands[3])); - if (!TARGET_NO_CHECK_ZERO_DIV) - { - emit_insn (gen_div_trap (operands[2], - GEN_INT (0), - GEN_INT (0x7))); - } - - DONE; -}") - - -(define_insn "udivmodsi4_internal" - [(set (match_operand:SI 0 "register_operand" "=l") - (udiv:SI (match_operand:SI 1 "register_operand" "d") - (match_operand:SI 2 "register_operand" "d"))) - (set (match_operand:SI 3 "register_operand" "=h") - (umod:SI (match_dup 1) - (match_dup 2))) - (clobber (match_scratch:SI 6 "=a"))] - "optimize && !0" ;; CYGNUS LOCAL law - "divu\\t$0,%1,%2" - [(set_attr "type" "idiv") - (set_attr "mode" "SI") - (set_attr "length" "1")]) - -(define_expand "udivmoddi4" - [(set (match_operand:DI 0 "register_operand" "=d") - (udiv:DI (match_operand:DI 1 "se_register_operand" "d") - (match_operand:DI 2 "se_register_operand" "d"))) - (set (match_operand:DI 3 "register_operand" "=d") - (umod:DI (match_dup 1) - (match_dup 2))) - (clobber (match_scratch:DI 4 "=l")) - (clobber (match_scratch:DI 5 "=h")) - (clobber (match_scratch:DI 6 "=a"))] - "TARGET_64BIT && optimize && !0" ;; CYGNUS LOCAL law - " -{ - rtx label; - - emit_insn (gen_udivmoddi4_internal (operands[0], operands[1], operands[2], - operands[3])); - if (!TARGET_NO_CHECK_ZERO_DIV) - { - emit_insn (gen_div_trap (operands[2], - GEN_INT (0), - GEN_INT (0x7))); - } - - DONE; -}") - -(define_insn "udivmoddi4_internal" - [(set (match_operand:DI 0 "register_operand" "=l") - (udiv:DI (match_operand:DI 1 "se_register_operand" "d") - (match_operand:DI 2 "se_register_operand" "d"))) - (set (match_operand:DI 3 "register_operand" "=h") - (umod:DI (match_dup 1) - (match_dup 2))) - (clobber (match_scratch:DI 6 "=a"))] - "TARGET_64BIT && optimize && !0" ;; CYGNUS LOCAL law - "ddivu\\t$0,%1,%2" - [(set_attr "type" "idiv") - (set_attr "mode" "SI") - (set_attr "length" "1")]) - -;; Division trap - - ;; Division trap - -(define_expand "div_trap" - [(trap_if (eq (match_operand 0 "register_operand" "d") - (match_operand 1 "true_reg_or_0_operand" "dJ")) - (match_operand 2 "immediate_operand" ""))] - "" - " -{ - if (TARGET_MIPS16) - emit_insn (gen_div_trap_mips16 (operands[0],operands[1],operands[2])); - else - emit_insn (gen_div_trap_normal (operands[0],operands[1],operands[2])); - DONE; -}") - -(define_insn "div_trap_normal" - [(trap_if (eq (match_operand 0 "register_operand" "d") - (match_operand 1 "true_reg_or_0_operand" "dJ")) - (match_operand 2 "immediate_operand" ""))] - "!TARGET_MIPS16" - "* -{ - rtx link; - int have_dep_anti = 0; - - /* For divmod if one division is not needed then we don't need an extra - divide by zero trap, which is anti dependent on previous trap */ - for (link = LOG_LINKS (insn); link; link = XEXP (link, 1)) - - if ((int) REG_DEP_ANTI == (int) REG_NOTE_KIND (link) - && GET_CODE (XEXP (link, 0)) == INSN - && GET_CODE (PATTERN (XEXP (link, 0))) == TRAP_IF - && REGNO (operands[1]) == 0) - have_dep_anti = 1; - if (! have_dep_anti) - { - if (GENERATE_BRANCHLIKELY) - { - if (GET_CODE (operands[1]) == CONST_INT) - return \"%(beql\\t%0,$0,1f\\n\\tbreak\\t%2\\n1:%)\"; - else - return \"%(beql\\t%0,%1,1f\\n\\tbreak\\t%2\\n1:%)\"; - } - else - { - if (GET_CODE (operands[1]) == CONST_INT) - return \"%(bne\\t%0,$0,1f\\n\\tnop\\n\\tbreak\\t%2\\n1:%)\"; - else - return \"%(bne\\t%0,%1,1f\\n\\tnop\\n\\tbreak\\t%2\\n1:%)\"; - } - } - return \"\"; -}" - [(set_attr "type" "unknown") - (set_attr "length" "3")]) - - -;; The mips16 bne insns is a macro which uses reg 24 as an intermediate. - -(define_insn "div_trap_mips16" - [(trap_if (eq (match_operand 0 "register_operand" "d") - (match_operand 1 "true_reg_or_0_operand" "dJ")) - (match_operand 2 "immediate_operand" "")) - (clobber (reg:SI 24))] - "TARGET_MIPS16" - "* -{ - rtx link; - int have_dep_anti = 0; - - /* For divmod if one division is not needed then we don't need an extra - divide by zero trap, which is anti dependent on previous trap */ - for (link = LOG_LINKS (insn); link; link = XEXP (link, 1)) - - if ((int) REG_DEP_ANTI == (int) REG_NOTE_KIND (link) - && GET_CODE (XEXP (link, 0)) == INSN - && GET_CODE (PATTERN (XEXP (link, 0))) == TRAP_IF - && REGNO (operands[1]) == 0) - have_dep_anti = 1; - if (! have_dep_anti) - { - /* No branch delay slots on mips16. */ - if (GET_CODE (operands[1]) == CONST_INT) - return \"%(bnez\\t%0,1f\\n\\tbreak\\t%2\\n1:%)\"; - else - return \"%(bne\\t%0,%1,1f\\n\\tbreak\\t%2\\n1:%)\"; - } - return \"\"; -}" - [(set_attr "type" "unknown") - (set_attr "length" "3")]) - -(define_expand "divsi3" - [(set (match_operand:SI 0 "register_operand" "=l") - (div:SI (match_operand:SI 1 "register_operand" "d") - (match_operand:SI 2 "register_operand" "d"))) - (clobber (match_scratch:SI 3 "=h")) - (clobber (match_scratch:SI 4 "=a"))] - "!optimize" - " -{ - rtx label; - - emit_insn (gen_divsi3_internal (operands[0], operands[1], operands[2])); - if (!TARGET_NO_CHECK_ZERO_DIV) - { - emit_insn (gen_div_trap (operands[2], - GEN_INT (0), - GEN_INT (0x7))); - } - if (TARGET_CHECK_RANGE_DIV) - { - emit_insn (gen_div_trap (operands[2], - copy_to_mode_reg (SImode, GEN_INT (-1)), - GEN_INT (0x6))); - emit_insn (gen_div_trap (operands[2], - copy_to_mode_reg (SImode, GEN_INT (0x80000000)), - GEN_INT (0x6))); - } - - DONE; -}") - -(define_insn "divsi3_internal" - [(set (match_operand:SI 0 "register_operand" "=l") - (div:SI (match_operand:SI 1 "register_operand" "d") - (match_operand:SI 2 "nonmemory_operand" "di"))) - (clobber (match_scratch:SI 3 "=h")) - (clobber (match_scratch:SI 4 "=a"))] - "!optimize" - "div\\t$0,%1,%2" - [(set_attr "type" "idiv") - (set_attr "mode" "SI") - (set_attr "length" "1")]) - -(define_expand "divdi3" - [(set (match_operand:DI 0 "register_operand" "=l") - (div:DI (match_operand:DI 1 "se_register_operand" "d") - (match_operand:DI 2 "se_register_operand" "d"))) - (clobber (match_scratch:DI 3 "=h")) - (clobber (match_scratch:DI 4 "=a"))] - "TARGET_64BIT && !optimize && !0" ;; CYGNUS LOCAL law - " -{ - rtx label; - - emit_insn (gen_divdi3_internal (operands[0], operands[1], operands[2])); - if (!TARGET_NO_CHECK_ZERO_DIV) - { - emit_insn (gen_div_trap (operands[2], - GEN_INT (0), - GEN_INT (0x7))); - } - if (TARGET_CHECK_RANGE_DIV) - { - emit_insn (gen_div_trap (operands[2], - copy_to_mode_reg (DImode, GEN_INT (-1)), - GEN_INT (0x6))); - emit_insn (gen_div_trap (operands[2], - copy_to_mode_reg (DImode, GEN_INT (0x80000000)), - GEN_INT (0x6))); - } - - DONE; -}") - -(define_insn "divdi3_internal" - [(set (match_operand:DI 0 "register_operand" "=l") - (div:DI (match_operand:DI 1 "se_register_operand" "d") - (match_operand:DI 2 "se_nonmemory_operand" "di"))) - (clobber (match_scratch:SI 3 "=h")) - (clobber (match_scratch:SI 4 "=a"))] - "TARGET_64BIT && !optimize && !0" ;; CYGNUS LOCAL law - "ddiv\\t$0,%1,%2" - [(set_attr "type" "idiv") - (set_attr "mode" "DI") - (set_attr "length" "1")]) - -(define_expand "modsi3" - [(set (match_operand:SI 0 "register_operand" "=h") - (mod:SI (match_operand:SI 1 "register_operand" "d") - (match_operand:SI 2 "register_operand" "d"))) - (clobber (match_scratch:SI 3 "=l")) - (clobber (match_scratch:SI 4 "=a"))] - "!optimize" - " -{ - rtx label; - - emit_insn (gen_modsi3_internal (operands[0], operands[1], operands[2])); - if (!TARGET_NO_CHECK_ZERO_DIV) - { - emit_insn (gen_div_trap (operands[2], - GEN_INT (0), - GEN_INT (0x7))); - } - if (TARGET_CHECK_RANGE_DIV) - { - emit_insn (gen_div_trap (operands[2], - copy_to_mode_reg (SImode, GEN_INT (-1)), - GEN_INT (0x6))); - emit_insn (gen_div_trap (operands[2], - copy_to_mode_reg (SImode, GEN_INT (0x80000000)), - GEN_INT (0x6))); - } - - DONE; -}") - -(define_insn "modsi3_internal" - [(set (match_operand:SI 0 "register_operand" "=h") - (mod:SI (match_operand:SI 1 "register_operand" "d") - (match_operand:SI 2 "nonmemory_operand" "di"))) - (clobber (match_scratch:SI 3 "=l")) - (clobber (match_scratch:SI 4 "=a"))] - "!optimize" - "div\\t$0,%1,%2" - [(set_attr "type" "idiv") - (set_attr "mode" "SI") - (set_attr "length" "1")]) - -(define_expand "moddi3" - [(set (match_operand:DI 0 "register_operand" "=h") - (mod:DI (match_operand:DI 1 "se_register_operand" "d") - (match_operand:DI 2 "se_register_operand" "d"))) - (clobber (match_scratch:DI 3 "=l")) - (clobber (match_scratch:DI 4 "=a"))] - "TARGET_64BIT && !optimize && !0" ;; CYGNUS LOCAL law - " -{ - rtx label; - - emit_insn (gen_moddi3_internal (operands[0], operands[1], operands[2])); - if (!TARGET_NO_CHECK_ZERO_DIV) - { - emit_insn (gen_div_trap (operands[2], - GEN_INT (0), - GEN_INT (0x7))); - } - if (TARGET_CHECK_RANGE_DIV) - { - emit_insn (gen_div_trap (operands[2], - copy_to_mode_reg (DImode, GEN_INT (-1)), - GEN_INT (0x6))); - emit_insn (gen_div_trap (operands[2], - copy_to_mode_reg (DImode, GEN_INT (0x80000000)), - GEN_INT (0x6))); - } - - DONE; -}") - -(define_insn "moddi3_internal" - [(set (match_operand:DI 0 "register_operand" "=h") - (mod:DI (match_operand:DI 1 "se_register_operand" "d") - (match_operand:DI 2 "se_nonmemory_operand" "di"))) - (clobber (match_scratch:SI 3 "=l")) - (clobber (match_scratch:SI 4 "=a"))] - "TARGET_64BIT && !optimize && !0" ;; CYGNUS LOCAL law - "ddiv\\t$0,%1,%2" - [(set_attr "type" "idiv") - (set_attr "mode" "DI") - (set_attr "length" "1")]) - -(define_expand "udivsi3" - [(set (match_operand:SI 0 "register_operand" "=l") - (udiv:SI (match_operand:SI 1 "register_operand" "d") - (match_operand:SI 2 "register_operand" "d"))) - (clobber (match_scratch:SI 3 "=h")) - (clobber (match_scratch:SI 4 "=a"))] - "!optimize" - " -{ - rtx label; - - emit_insn (gen_udivsi3_internal (operands[0], operands[1], operands[2])); - if (!TARGET_NO_CHECK_ZERO_DIV) - { - emit_insn (gen_div_trap (operands[2], - GEN_INT (0), - GEN_INT (0x7))); - } - - DONE; -}") - -(define_insn "udivsi3_internal" - [(set (match_operand:SI 0 "register_operand" "=l") - (udiv:SI (match_operand:SI 1 "register_operand" "d") - (match_operand:SI 2 "nonmemory_operand" "di"))) - (clobber (match_scratch:SI 3 "=h")) - (clobber (match_scratch:SI 4 "=a"))] - "!optimize" - "divu\\t$0,%1,%2" - [(set_attr "type" "idiv") - (set_attr "mode" "SI") - (set_attr "length" "1")]) - -(define_expand "udivdi3" - [(set (match_operand:DI 0 "register_operand" "=l") - (udiv:DI (match_operand:DI 1 "se_register_operand" "d") - (match_operand:DI 2 "se_register_operand" "di"))) - (clobber (match_scratch:DI 3 "=h")) - (clobber (match_scratch:DI 4 "=a"))] - "TARGET_64BIT && !optimize && !0" ;; CYGNUS LOCAL law - " -{ - rtx label; - - emit_insn (gen_udivdi3_internal (operands[0], operands[1], operands[2])); - if (!TARGET_NO_CHECK_ZERO_DIV) - { - emit_insn (gen_div_trap (operands[2], - GEN_INT (0), - GEN_INT (0x7))); - } - - DONE; -}") - -(define_insn "udivdi3_internal" - [(set (match_operand:DI 0 "register_operand" "=l") - (udiv:DI (match_operand:DI 1 "se_register_operand" "d") - (match_operand:DI 2 "se_nonmemory_operand" "di"))) - (clobber (match_scratch:SI 3 "=h")) - (clobber (match_scratch:SI 4 "=a"))] - "TARGET_64BIT && !optimize && !0" ;; CYGNUS LOCAL law - "ddivu\\t$0,%1,%2" - [(set_attr "type" "idiv") - (set_attr "mode" "DI") - (set_attr "length" "1")]) - -(define_expand "umodsi3" - [(set (match_operand:SI 0 "register_operand" "=h") - (umod:SI (match_operand:SI 1 "register_operand" "d") - (match_operand:SI 2 "register_operand" "d"))) - (clobber (match_scratch:SI 3 "=l")) - (clobber (match_scratch:SI 4 "=a"))] - "!optimize" - " -{ - rtx label; - - emit_insn (gen_umodsi3_internal (operands[0], operands[1], operands[2])); - if (!TARGET_NO_CHECK_ZERO_DIV) - { - emit_insn (gen_div_trap (operands[2], - GEN_INT (0), - GEN_INT (0x7))); - } - - DONE; -}") - -(define_insn "umodsi3_internal" - [(set (match_operand:SI 0 "register_operand" "=h") - (umod:SI (match_operand:SI 1 "register_operand" "d") - (match_operand:SI 2 "nonmemory_operand" "di"))) - (clobber (match_scratch:SI 3 "=l")) - (clobber (match_scratch:SI 4 "=a"))] - "!optimize" - "divu\\t$0,%1,%2" - [(set_attr "type" "idiv") - (set_attr "mode" "SI") - (set_attr "length" "1")]) - -(define_expand "umoddi3" - [(set (match_operand:DI 0 "register_operand" "=h") - (umod:DI (match_operand:DI 1 "se_register_operand" "d") - (match_operand:DI 2 "se_register_operand" "di"))) - (clobber (match_scratch:DI 3 "=l")) - (clobber (match_scratch:DI 4 "=a"))] - "TARGET_64BIT && !optimize && !0" ;; CYGNUS LOCAL law - " -{ - rtx label; - - emit_insn (gen_umoddi3_internal (operands[0], operands[1], operands[2])); - if (!TARGET_NO_CHECK_ZERO_DIV) - { - emit_insn (gen_div_trap (operands[2], - GEN_INT (0), - GEN_INT (0x7))); - } - - DONE; -}") - -(define_insn "umoddi3_internal" - [(set (match_operand:DI 0 "register_operand" "=h") - (umod:DI (match_operand:DI 1 "se_register_operand" "d") - (match_operand:DI 2 "se_nonmemory_operand" "di"))) - (clobber (match_scratch:SI 3 "=l")) - (clobber (match_scratch:SI 4 "=a"))] - "TARGET_64BIT && !optimize && !0" ;; CYGNUS LOCAL law - "ddivu\\t$0,%1,%2" - [(set_attr "type" "idiv") - (set_attr "mode" "DI") - (set_attr "length" "1")]) - -;; .................... -;; SQUARE ROOT -;; .................... - -(define_insn "sqrtdf2" - [(set (match_operand:DF 0 "register_operand" "=f") - (sqrt:DF (match_operand:DF 1 "register_operand" "f")))] - "TARGET_HARD_FLOAT && HAVE_SQRT_P() && TARGET_DOUBLE_FLOAT" - "sqrt.d\\t%0,%1" - [(set_attr "type" "fsqrt") - (set_attr "mode" "DF") - (set_attr "length" "1")]) - -(define_insn "sqrtsf2" - [(set (match_operand:SF 0 "register_operand" "=f") - (sqrt:SF (match_operand:SF 1 "register_operand" "f")))] - "TARGET_HARD_FLOAT && HAVE_SQRT_P()" - "sqrt.s\\t%0,%1" - [(set_attr "type" "fsqrt") - (set_attr "mode" "SF") - (set_attr "length" "1")]) - -(define_insn "" - [(set (match_operand:DF 0 "register_operand" "=f") - (div:DF (match_operand:DF 1 "const_float_1_operand" "") - (sqrt:DF (match_operand:DF 2 "register_operand" "f"))))] - "mips_isa >= 4 && TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT && flag_fast_math" - "rsqrt.d\\t%0,%2" - [(set_attr "type" "frsqrt") ; CYGNUS LOCAL vr5400/raeburn - (set_attr "mode" "DF") - (set_attr "length" "1")]) - -(define_insn "" - [(set (match_operand:SF 0 "register_operand" "=f") - (div:SF (match_operand:SF 1 "const_float_1_operand" "") - (sqrt:SF (match_operand:SF 2 "register_operand" "f"))))] - "mips_isa >= 4 && TARGET_HARD_FLOAT && flag_fast_math" - "rsqrt.s\\t%0,%2" - [(set_attr "type" "frsqrt") ; CYGNUS LOCAL vr5400/raeburn - (set_attr "mode" "SF") - (set_attr "length" "1")]) - - -;; .................... -;; ABSOLUTE VALUE -;; .................... - -;; Do not use the integer abs macro instruction, since that signals an -;; exception on -2147483648 (sigh). - -(define_insn "abssi2" - [(set (match_operand:SI 0 "register_operand" "=d") - (abs:SI (match_operand:SI 1 "register_operand" "d")))] - "!TARGET_MIPS16" - "* -{ - dslots_jump_total++; - dslots_jump_filled++; - 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\\n1:%)\"; - else - return \"bgez\\t%1,1f%#\\n\\tsubu\\t%0,%z2,%0\\n1:\"; - } - else - return \"%(bgez\\t%1,1f\\n\\tmove\\t%0,%1\\n\\tsubu\\t%0,%z2,%0\\n1:%)\"; -}" - [(set_attr "type" "multi") - (set_attr "mode" "SI") - (set_attr "length" "3")]) - -(define_insn "absdi2" - [(set (match_operand:DI 0 "register_operand" "=d") - (abs:DI (match_operand:DI 1 "se_register_operand" "d")))] - "TARGET_64BIT && !TARGET_MIPS16" - "* -{ - dslots_jump_total++; - dslots_jump_filled++; - operands[2] = const0_rtx; - - if (REGNO (operands[0]) == REGNO (operands[1])) - return \"%(bltzl\\t%1,1f\\n\\tdsubu\\t%0,%z2,%0\\n1:%)\"; - else - return \"%(bgez\\t%1,1f\\n\\tmove\\t%0,%1\\n\\tdsubu\\t%0,%z2,%0\\n1:%)\"; -}" - [(set_attr "type" "multi") - (set_attr "mode" "DI") - (set_attr "length" "3")]) - -(define_insn "absdf2" - [(set (match_operand:DF 0 "register_operand" "=f") - (abs:DF (match_operand:DF 1 "register_operand" "f")))] - "TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT" - "abs.d\\t%0,%1" - [(set_attr "type" "fabs") - (set_attr "mode" "DF") - (set_attr "length" "1")]) - -(define_insn "abssf2" - [(set (match_operand:SF 0 "register_operand" "=f") - (abs:SF (match_operand:SF 1 "register_operand" "f")))] - "TARGET_HARD_FLOAT" - "abs.s\\t%0,%1" - [(set_attr "type" "fabs") - (set_attr "mode" "SF") - (set_attr "length" "1")]) - - -;; .................... -;; FIND FIRST BIT INSTRUCTION -;; .................... - -(define_insn "ffssi2" - [(set (match_operand:SI 0 "register_operand" "=&d") - (ffs:SI (match_operand:SI 1 "register_operand" "d"))) - (clobber (match_scratch:SI 2 "=&d")) - (clobber (match_scratch:SI 3 "=&d"))] - "!TARGET_MIPS16" - "* -{ - dslots_jump_total += 2; - dslots_jump_filled += 2; - operands[4] = const0_rtx; - - if (optimize && find_reg_note (insn, REG_DEAD, operands[1])) - return \"%(\\ -move\\t%0,%z4\\n\\ -\\tbeq\\t%1,%z4,2f\\n\\ -1:\\tand\\t%2,%1,0x0001\\n\\ -\\taddu\\t%0,%0,1\\n\\ -\\tbeq\\t%2,%z4,1b\\n\\ -\\tsrl\\t%1,%1,1\\n\\ -2:%)\"; - - return \"%(\\ -move\\t%0,%z4\\n\\ -\\tmove\\t%3,%1\\n\\ -\\tbeq\\t%3,%z4,2f\\n\\ -1:\\tand\\t%2,%3,0x0001\\n\\ -\\taddu\\t%0,%0,1\\n\\ -\\tbeq\\t%2,%z4,1b\\n\\ -\\tsrl\\t%3,%3,1\\n\\ -2:%)\"; -}" - [(set_attr "type" "multi") - (set_attr "mode" "SI") - (set_attr "length" "6")]) - -(define_insn "ffsdi2" - [(set (match_operand:DI 0 "register_operand" "=&d") - (ffs:DI (match_operand:DI 1 "se_register_operand" "d"))) - (clobber (match_scratch:DI 2 "=&d")) - (clobber (match_scratch:DI 3 "=&d"))] - "TARGET_64BIT && !TARGET_MIPS16" - "* -{ - dslots_jump_total += 2; - dslots_jump_filled += 2; - operands[4] = const0_rtx; - - if (optimize && find_reg_note (insn, REG_DEAD, operands[1])) - return \"%(\\ -move\\t%0,%z4\\n\\ -\\tbeq\\t%1,%z4,2f\\n\\ -1:\\tand\\t%2,%1,0x0001\\n\\ -\\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:%)\"; -}" - [(set_attr "type" "multi") - (set_attr "mode" "DI") - (set_attr "length" "6")]) - - -;; .................... -;; NEGATION and ONE'S COMPLEMENT -;; .................... - -(define_insn "negsi2" - [(set (match_operand:SI 0 "register_operand" "=d") - (neg:SI (match_operand:SI 1 "register_operand" "d")))] - "" - "* -{ - if (TARGET_MIPS16) - return \"neg\\t%0,%1\"; - operands[2] = const0_rtx; - return \"subu\\t%0,%z2,%1\"; -}" - [(set_attr "type" "arith") - (set_attr "mode" "SI") - (set_attr "length" "1")]) - -(define_expand "negdi2" - [(parallel [(set (match_operand:DI 0 "register_operand" "=d") - (neg:DI (match_operand:DI 1 "se_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" "4")]) - -(define_insn "negdi2_internal_2" - [(set (match_operand:DI 0 "register_operand" "=d") - (neg:DI (match_operand:DI 1 "se_register_operand" "d")))] - "TARGET_64BIT && !TARGET_MIPS16" - "* -{ - operands[2] = const0_rtx; - return \"dsubu\\t%0,%z2,%1\"; -}" - [(set_attr "type" "arith") - (set_attr "mode" "DI") - (set_attr "length" "1")]) - -(define_insn "negdf2" - [(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" - [(set_attr "type" "fneg") - (set_attr "mode" "DF") - (set_attr "length" "1")]) - -(define_insn "negsf2" - [(set (match_operand:SF 0 "register_operand" "=f") - (neg:SF (match_operand:SF 1 "register_operand" "f")))] - "TARGET_HARD_FLOAT" - "neg.s\\t%0,%1" - [(set_attr "type" "fneg") - (set_attr "mode" "SF") - (set_attr "length" "1")]) - -(define_insn "one_cmplsi2" - [(set (match_operand:SI 0 "register_operand" "=d") - (not:SI (match_operand:SI 1 "register_operand" "d")))] - "" - "* -{ - if (TARGET_MIPS16) - return \"not\\t%0,%1\"; - operands[2] = const0_rtx; - return \"nor\\t%0,%z2,%1\"; -}" - [(set_attr "type" "arith") - (set_attr "mode" "SI") - (set_attr "length" "1")]) - -(define_insn "one_cmpldi2" - [(set (match_operand:DI 0 "register_operand" "=d") - (not:DI (match_operand:DI 1 "se_register_operand" "d")))] - "" - "* -{ - if (TARGET_MIPS16) - { - if (TARGET_64BIT) - return \"not\\t%0,%1\"; - return \"not\\t%M0,%M1\;not\\t%L0,%L1\"; - } - operands[2] = const0_rtx; - if (TARGET_64BIT) - return \"nor\\t%0,%z2,%1\"; - return \"nor\\t%M0,%z2,%M1\;nor\\t%L0,%z2,%L1\"; -}" - [(set_attr "type" "darith") - (set_attr "mode" "DI") - (set (attr "length") - (if_then_else (ge (symbol_ref "mips_isa") (const_int 3)) - (const_int 1) - (const_int 2)))]) - -(define_split - [(set (match_operand:DI 0 "register_operand" "") - (not:DI (match_operand:DI 1 "register_operand" "")))] - "reload_completed && !TARGET_64BIT && !TARGET_DEBUG_D_MODE && !TARGET_DEBUG_G_MODE - && GET_CODE (operands[0]) == REG && GP_REG_P (REGNO (operands[0])) - && GET_CODE (operands[1]) == REG && GP_REG_P (REGNO (operands[1]))" - - [(set (subreg:SI (match_dup 0) 0) (not:SI (subreg:SI (match_dup 1) 0))) - (set (subreg:SI (match_dup 0) 1) (not:SI (subreg:SI (match_dup 1) 1)))] - "") - - -;; .................... -;; LOGICAL -;; .................... - -;; Many of these instructions uses 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")))] - "" - " -{ - if (TARGET_MIPS16) - operands[2] = force_reg (SImode, operands[2]); -}") - -(define_insn "" - [(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")))] - "!TARGET_MIPS16" - "@ - and\\t%0,%1,%2 - andi\\t%0,%1,%x2" - [(set_attr "type" "arith") - (set_attr "mode" "SI") - (set_attr "length" "1")]) - -(define_insn "" - [(set (match_operand:SI 0 "register_operand" "=d") - (and:SI (match_operand:SI 1 "register_operand" "%0") - (match_operand:SI 2 "register_operand" "d")))] - "TARGET_MIPS16" - "and\\t%0,%2" - [(set_attr "type" "arith") - (set_attr "mode" "SI") - (set_attr "length" "1")]) - -(define_expand "anddi3" - [(set (match_operand:DI 0 "register_operand" "=d") - (and:DI (match_operand:DI 1 "se_register_operand" "d") - (match_operand:DI 2 "se_register_operand" "d")))] - "TARGET_64BIT || !TARGET_DEBUG_G_MODE" - " -{ - if (TARGET_MIPS16) - operands[2] = force_reg (DImode, operands[2]); -}") - -(define_insn "" - [(set (match_operand:DI 0 "register_operand" "=d") - (and:DI (match_operand:DI 1 "se_register_operand" "d") - (match_operand:DI 2 "se_register_operand" "d")))] - "(TARGET_64BIT || !TARGET_DEBUG_G_MODE) && !TARGET_MIPS16" - "* -{ - if (TARGET_64BIT) - return \"and\\t%0,%1,%2\"; - return \"and\\t%M0,%M1,%M2\;and\\t%L0,%L1,%L2\"; -}" - [(set_attr "type" "darith") - (set_attr "mode" "DI") - (set (attr "length") - (if_then_else (ne (symbol_ref "TARGET_64BIT") (const_int 0)) - (const_int 1) - (const_int 2)))]) - -(define_insn "" - [(set (match_operand:DI 0 "register_operand" "=d") - (and:DI (match_operand:DI 1 "se_register_operand" "0") - (match_operand:DI 2 "se_register_operand" "d")))] - "(TARGET_64BIT || !TARGET_DEBUG_G_MODE) && TARGET_MIPS16" - "* -{ - if (TARGET_64BIT) - return \"and\\t%0,%2\"; - return \"and\\t%M0,%M2\;and\\t%L0,%L2\"; -}" - [(set_attr "type" "darith") - (set_attr "mode" "DI") - (set (attr "length") - (if_then_else (ge (symbol_ref "mips_isa") (const_int 3)) - (const_int 1) - (const_int 2)))]) - -(define_split - [(set (match_operand:DI 0 "register_operand" "") - (and:DI (match_operand:DI 1 "register_operand" "") - (match_operand:DI 2 "register_operand" "")))] - "reload_completed && !TARGET_64BIT && !TARGET_DEBUG_D_MODE && !TARGET_DEBUG_G_MODE - && GET_CODE (operands[0]) == REG && GP_REG_P (REGNO (operands[0])) - && GET_CODE (operands[1]) == REG && GP_REG_P (REGNO (operands[1])) - && GET_CODE (operands[2]) == REG && GP_REG_P (REGNO (operands[2]))" - - [(set (subreg:SI (match_dup 0) 0) (and:SI (subreg:SI (match_dup 1) 0) (subreg:SI (match_dup 2) 0))) - (set (subreg:SI (match_dup 0) 1) (and:SI (subreg:SI (match_dup 1) 1) (subreg:SI (match_dup 2) 1)))] - "") - -(define_insn "anddi3_internal1" - [(set (match_operand:DI 0 "register_operand" "=d,d") - (and:DI (match_operand:DI 1 "se_register_operand" "%d,d") - (match_operand:DI 2 "se_uns_arith_operand" "d,K")))] - "TARGET_64BIT && !TARGET_MIPS16" - "@ - and\\t%0,%1,%2 - andi\\t%0,%1,%x2" - [(set_attr "type" "arith") - (set_attr "mode" "DI") - (set_attr "length" "1")]) - -(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")))] - "" - " -{ - if (TARGET_MIPS16) - operands[2] = force_reg (SImode, operands[2]); -}") - -(define_insn "" - [(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")))] - "!TARGET_MIPS16" - "@ - or\\t%0,%1,%2 - ori\\t%0,%1,%x2" - [(set_attr "type" "arith") - (set_attr "mode" "SI") - (set_attr "length" "1")]) - -(define_insn "" - [(set (match_operand:SI 0 "register_operand" "=d") - (ior:SI (match_operand:SI 1 "register_operand" "%0") - (match_operand:SI 2 "register_operand" "d")))] - "TARGET_MIPS16" - "or\\t%0,%2" - [(set_attr "type" "arith") - (set_attr "mode" "SI") - (set_attr "length" "1")]) - -;;; ??? There is no iordi3 pattern which accepts 'K' constants when -;;; TARGET_64BIT - -(define_expand "iordi3" - [(set (match_operand:DI 0 "register_operand" "=d") - (ior:DI (match_operand:DI 1 "se_register_operand" "d") - (match_operand:DI 2 "se_register_operand" "d")))] - "TARGET_64BIT || !TARGET_DEBUG_G_MODE" - "") - -(define_insn "" - [(set (match_operand:DI 0 "register_operand" "=d") - (ior:DI (match_operand:DI 1 "se_register_operand" "d") - (match_operand:DI 2 "se_register_operand" "d")))] - "(TARGET_64BIT || !TARGET_DEBUG_G_MODE) && !TARGET_MIPS16" - "* -{ - if (TARGET_64BIT) - return \"or\\t%0,%1,%2\"; - return \"or\\t%M0,%M1,%M2\;or\\t%L0,%L1,%L2\"; -}" - [(set_attr "type" "darith") - (set_attr "mode" "DI") - (set (attr "length") - (if_then_else (ne (symbol_ref "TARGET_64BIT") (const_int 0)) - (const_int 1) - (const_int 2)))]) - -(define_insn "" - [(set (match_operand:DI 0 "register_operand" "=d") - (ior:DI (match_operand:DI 1 "se_register_operand" "0") - (match_operand:DI 2 "se_register_operand" "d")))] - "(TARGET_64BIT || !TARGET_DEBUG_G_MODE) && TARGET_MIPS16" - "* -{ - if (TARGET_64BIT) - return \"or\\t%0,%2\"; - return \"or\\t%M0,%M2\;or\\t%L0,%L2\"; -}" - [(set_attr "type" "darith") - (set_attr "mode" "DI") - (set (attr "length") - (if_then_else (ge (symbol_ref "mips_isa") (const_int 3)) - (const_int 1) - (const_int 2)))]) - -(define_split - [(set (match_operand:DI 0 "register_operand" "") - (ior:DI (match_operand:DI 1 "register_operand" "") - (match_operand:DI 2 "register_operand" "")))] - "reload_completed && !TARGET_64BIT && !TARGET_DEBUG_D_MODE && !TARGET_DEBUG_G_MODE - && GET_CODE (operands[0]) == REG && GP_REG_P (REGNO (operands[0])) - && GET_CODE (operands[1]) == REG && GP_REG_P (REGNO (operands[1])) - && GET_CODE (operands[2]) == REG && GP_REG_P (REGNO (operands[2]))" - - [(set (subreg:SI (match_dup 0) 0) (ior:SI (subreg:SI (match_dup 1) 0) (subreg:SI (match_dup 2) 0))) - (set (subreg:SI (match_dup 0) 1) (ior:SI (subreg:SI (match_dup 1) 1) (subreg:SI (match_dup 2) 1)))] - "") - -(define_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")))] - "" - "") - -(define_insn "" - [(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")))] - "!TARGET_MIPS16" - "@ - xor\\t%0,%1,%2 - xori\\t%0,%1,%x2" - [(set_attr "type" "arith") - (set_attr "mode" "SI") - (set_attr "length" "1")]) - -(define_insn "" - [(set (match_operand:SI 0 "register_operand" "=d,t,t") - (xor:SI (match_operand:SI 1 "uns_arith_operand" "%0,d,d") - (match_operand:SI 2 "uns_arith_operand" "d,K,d")))] - "TARGET_MIPS16" - "@ - 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 1) - (if_then_else (match_operand:VOID 2 "m16_uimm8_1" "") - (const_int 1) - (const_int 2)) - (const_int 1)])]) - -;; ??? If delete the 32-bit long long patterns, then could merge this with -;; the following xordi3_internal pattern. -(define_expand "xordi3" - [(set (match_operand:DI 0 "register_operand" "=d") - (xor:DI (match_operand:DI 1 "se_register_operand" "d") - (match_operand:DI 2 "se_register_operand" "d")))] - "TARGET_64BIT || !TARGET_DEBUG_G_MODE" - "") - -(define_insn "" - [(set (match_operand:DI 0 "register_operand" "=d") - (xor:DI (match_operand:DI 1 "se_register_operand" "d") - (match_operand:DI 2 "se_register_operand" "d")))] - "(TARGET_64BIT || !TARGET_DEBUG_G_MODE) && !TARGET_MIPS16" - "* -{ - if (TARGET_64BIT) - return \"xor\\t%0,%1,%2\"; - return \"xor\\t%M0,%M1,%M2\;xor\\t%L0,%L1,%L2\"; -}" - [(set_attr "type" "darith") - (set_attr "mode" "DI") - (set (attr "length") - (if_then_else (ne (symbol_ref "TARGET_64BIT") (const_int 0)) - (const_int 1) - (const_int 2)))]) - -(define_insn "" - [(set (match_operand:DI 0 "register_operand" "=d") - (xor:DI (match_operand:DI 1 "se_register_operand" "0") - (match_operand:DI 2 "se_register_operand" "d")))] - "!TARGET_64BIT && TARGET_MIPS16" - "xor\\t%M0,%M2\;xor\\t%L0,%L2" - [(set_attr "type" "darith") - (set_attr "mode" "DI") - (set_attr "length" "2")]) - -(define_insn "" - [(set (match_operand:DI 0 "register_operand" "=d,t,t") - (xor:DI (match_operand:DI 1 "se_register_operand" "%0,d,d") - (match_operand:DI 2 "se_uns_arith_operand" "d,K,d")))] - "TARGET_64BIT && TARGET_MIPS16" - "@ - 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 1) - (if_then_else (match_operand:VOID 2 "m16_uimm8_1" "") - (const_int 1) - (const_int 2)) - (const_int 1)])]) - -(define_split - [(set (match_operand:DI 0 "register_operand" "") - (xor:DI (match_operand:DI 1 "register_operand" "") - (match_operand:DI 2 "register_operand" "")))] - "reload_completed && !TARGET_64BIT && !TARGET_DEBUG_D_MODE && !TARGET_DEBUG_G_MODE - && GET_CODE (operands[0]) == REG && GP_REG_P (REGNO (operands[0])) - && GET_CODE (operands[1]) == REG && GP_REG_P (REGNO (operands[1])) - && GET_CODE (operands[2]) == REG && GP_REG_P (REGNO (operands[2]))" - - [(set (subreg:SI (match_dup 0) 0) (xor:SI (subreg:SI (match_dup 1) 0) (subreg:SI (match_dup 2) 0))) - (set (subreg:SI (match_dup 0) 1) (xor:SI (subreg:SI (match_dup 1) 1) (subreg:SI (match_dup 2) 1)))] - "") - -(define_insn "xordi3_immed" - [(set (match_operand:DI 0 "register_operand" "=d") - (xor:DI (match_operand:DI 1 "se_register_operand" "d") - (match_operand:DI 2 "se_uns_arith_operand" "K")))] - "TARGET_64BIT && !TARGET_MIPS16" - "xori\\t%0,%1,%x2" - [(set_attr "type" "arith") - (set_attr "mode" "DI") - (set_attr "length" "1")]) - -(define_insn "*norsi3" - [(set (match_operand:SI 0 "register_operand" "=d") - (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" - [(set_attr "type" "arith") - (set_attr "mode" "SI") - (set_attr "length" "1")]) - -(define_insn "*nordi3" - [(set (match_operand:DI 0 "register_operand" "=d") - (and:DI (not:DI (match_operand:DI 1 "se_register_operand" "d")) - (not:DI (match_operand:DI 2 "se_register_operand" "d"))))] - "!TARGET_MIPS16" - "* -{ - if (TARGET_64BIT) - return \"nor\\t%0,%z1,%z2\"; - return \"nor\\t%M0,%M1,%M2\;nor\\t%L0,%L1,%L2\"; -}" - [(set_attr "type" "darith") - (set_attr "mode" "DI") - (set (attr "length") - (if_then_else (ne (symbol_ref "TARGET_64BIT") (const_int 0)) - (const_int 1) - (const_int 2)))]) - -(define_split - [(set (match_operand:DI 0 "register_operand" "") - (and:DI (not:DI (match_operand:DI 1 "register_operand" "")) - (not:DI (match_operand:DI 2 "register_operand" ""))))] - "reload_completed && !TARGET_MIPS16 && !TARGET_64BIT && !TARGET_DEBUG_D_MODE && !TARGET_DEBUG_G_MODE - && GET_CODE (operands[0]) == REG && GP_REG_P (REGNO (operands[0])) - && GET_CODE (operands[1]) == REG && GP_REG_P (REGNO (operands[1])) - && GET_CODE (operands[2]) == REG && GP_REG_P (REGNO (operands[2]))" - - [(set (subreg:SI (match_dup 0) 0) (and:SI (not:SI (subreg:SI (match_dup 1) 0)) (not:SI (subreg:SI (match_dup 2) 0)))) - (set (subreg:SI (match_dup 0) 1) (and:SI (not:SI (subreg:SI (match_dup 1) 1)) (not:SI (subreg:SI (match_dup 2) 1))))] - "") - -;; .................... -;; TRUNCATION -;; .................... - -(define_insn "truncdfsf2" - [(set (match_operand:SF 0 "register_operand" "=f") - (float_truncate:SF (match_operand:DF 1 "register_operand" "f")))] - "TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT" - "cvt.s.d\\t%0,%1" - [(set_attr "type" "fcvt") - (set_attr "mode" "SF") - (set_attr "length" "1")]) - -(define_insn "truncdisi2" - [(set (match_operand:SI 0 "register_operand" "=d") - (truncate:SI (match_operand:DI 1 "se_register_operand" "d")))] - "TARGET_64BIT" - "* -{ - if (TARGET_MIPS16) - return \"dsll\\t%0,%1,32\;dsra\\t%0,32\"; - return \"dsll\\t%0,%1,32\;dsra\\t%0,%0,32\"; -}" - [(set_attr "type" "darith") - (set_attr "mode" "SI") - (set (attr "length") (if_then_else (eq (symbol_ref "mips16") (const_int 0)) - (const_int 2) - (const_int 4)))]) - -(define_insn "truncdihi2" - [(set (match_operand:HI 0 "register_operand" "=d") - (truncate:HI (match_operand:DI 1 "se_register_operand" "d")))] - "TARGET_64BIT" - "* -{ - if (TARGET_MIPS16) - return \"dsll\\t%0,%1,48\;dsra\\t%0,48\"; - return \"andi\\t%0,%1,0xffff\"; -}" - [(set_attr "type" "darith") - (set_attr "mode" "HI") - (set (attr "length") (if_then_else (eq (symbol_ref "mips16") (const_int 0)) - (const_int 1) - (const_int 4)))]) -(define_insn "truncdiqi2" - [(set (match_operand:QI 0 "register_operand" "=d") - (truncate:QI (match_operand:DI 1 "se_register_operand" "d")))] - "TARGET_64BIT" - "* -{ - if (TARGET_MIPS16) - return \"dsll\\t%0,%1,56\;dsra\\t%0,56\"; - return \"andi\\t%0,%1,0x00ff\"; -}" - [(set_attr "type" "darith") - (set_attr "mode" "QI") - (set (attr "length") (if_then_else (eq (symbol_ref "mips16") (const_int 0)) - (const_int 1) - (const_int 4)))]) - -;; Combiner patterns to optimize shift/truncate combinations. -(define_insn "" - [(set (match_operand:SI 0 "register_operand" "=d") - (truncate:SI (ashiftrt:DI (match_operand:DI 1 "se_register_operand" "d") - (match_operand:DI 2 "small_int" "I"))))] - "TARGET_64BIT && !TARGET_MIPS16" - "* -{ - int shift_amt = INTVAL (operands[2]) & 0x3f; - - if (shift_amt < 32) - { - operands[2] = GEN_INT (32 - shift_amt); - return \"dsll\\t%0,%1,%2\;dsra\\t%0,%0,32\"; - } - else - { - operands[2] = GEN_INT (shift_amt); - return \"dsra\\t%0,%1,%2\"; - } -}" - [(set_attr "type" "darith") - (set_attr "mode" "SI") - (set_attr "length" "2")]) - -(define_insn "" - [(set (match_operand:SI 0 "register_operand" "=d") - (truncate:SI (lshiftrt:DI (match_operand:DI 1 "se_register_operand" "d") - (match_operand:DI 2 "small_int" "I"))))] - "TARGET_64BIT && !TARGET_MIPS16" - "* -{ - int shift_amt = INTVAL (operands[2]) & 0x3f; - - if (shift_amt < 32) - { - operands[2] = GEN_INT (32 - shift_amt); - return \"dsll\\t%0,%1,%2\;dsra\\t%0,%0,32\"; - } - else if (shift_amt == 32) - return \"dsra\\t%0,%1,32\"; - else - { - operands[2] = GEN_INT (shift_amt); - return \"dsrl\\t%0,%1,%2\"; - } -}" - [(set_attr "type" "darith") - (set_attr "mode" "SI") - (set_attr "length" "2")]) - -(define_insn "" - [(set (match_operand:SI 0 "register_operand" "=d") - (truncate:SI (ashift:DI (match_operand:DI 1 "se_register_operand" "d") - (match_operand:DI 2 "small_int" "I"))))] - "TARGET_64BIT" - "* -{ - int shift_amt = INTVAL (operands[2]) & 0x3f; - - if (shift_amt < 32) - { - operands[2] = GEN_INT (32 + shift_amt); - if (TARGET_MIPS16) - return \"dsll\\t%0,%1,%2\;dsra\\t%0,32\"; - return \"dsll\\t%0,%1,%2\;dsra\\t%0,%0,32\"; - } - else - return \"move\\t%0,%.\"; -}" - [(set_attr "type" "darith") - (set_attr "mode" "SI") - (set_attr "length" "2")]) - -;; Combiner patterns to optimize truncate/zero_extend combinations. - -(define_insn "" - [(set (match_operand:SI 0 "register_operand" "=d") - (zero_extend:SI (truncate:HI - (match_operand:DI 1 "se_register_operand" "d"))))] - "TARGET_64BIT && !TARGET_MIPS16" - "andi\\t%0,%1,0xffff" - [(set_attr "type" "darith") - (set_attr "mode" "SI") - (set_attr "length" "1")]) - -(define_insn "" - [(set (match_operand:SI 0 "register_operand" "=d") - (zero_extend:SI (truncate:QI - (match_operand:DI 1 "se_register_operand" "d"))))] - "TARGET_64BIT && !TARGET_MIPS16" - "andi\\t%0,%1,0xff" - [(set_attr "type" "darith") - (set_attr "mode" "SI") - (set_attr "length" "1")]) - -(define_insn "" - [(set (match_operand:HI 0 "register_operand" "=d") - (zero_extend:HI (truncate:QI - (match_operand:DI 1 "se_register_operand" "d"))))] - "TARGET_64BIT && !TARGET_MIPS16" - "andi\\t%0,%1,0xff" - [(set_attr "type" "darith") - (set_attr "mode" "HI") - (set_attr "length" "1")]) - -;; .................... -;; ZERO EXTENSION -;; .................... - -;; Extension insns. -;; Those for integer source operand are ordered widest source type first. - -(define_expand "zero_extendsidi2" - [(set (match_operand:DI 0 "register_operand" "") - (zero_extend:DI (match_operand:SI 1 "nonimmediate_operand" "")))] - "TARGET_64BIT" - " -{ - if (optimize && GET_CODE (operands[1]) == MEM) - operands[1] = force_not_mem (operands[1]); - - if (GET_CODE (operands[1]) != MEM) - { - rtx op1 = gen_lowpart (DImode, operands[1]); - rtx temp = gen_reg_rtx (DImode); - rtx shift = GEN_INT (32); - - emit_insn (gen_ashldi3 (temp, op1, shift)); - emit_insn (gen_lshrdi3 (operands[0], temp, shift)); - DONE; - } -}") - -(define_insn "zero_extendsidi2_internal" - [(set (match_operand:DI 0 "register_operand" "=d,d") - (zero_extend:DI (match_operand:SI 1 "memory_operand" "R,m")))] - "TARGET_64BIT" - "* return mips_move_1word (operands, insn, TRUE);" - [(set_attr "type" "load") - (set_attr "mode" "DI") - (set_attr "length" "1,2")]) - -(define_expand "zero_extendhisi2" - [(set (match_operand:SI 0 "register_operand" "") - (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "")))] - "" - " -{ - if (TARGET_MIPS16 && GET_CODE (operands[1]) != MEM) - { - rtx op = gen_lowpart (SImode, operands[1]); - rtx temp = force_reg (SImode, GEN_INT (0xffff)); - - emit_insn (gen_andsi3 (operands[0], op, temp)); - DONE; - } -}") - -(define_insn "" - [(set (match_operand:SI 0 "register_operand" "=d,d,d") - (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "d,R,m")))] - "!TARGET_MIPS16" - "* -{ - if (which_alternative == 0) - return \"andi\\t%0,%1,0xffff\"; - else - return mips_move_1word (operands, insn, TRUE); -}" - [(set_attr "type" "arith,load,load") - (set_attr "mode" "SI") - (set_attr "length" "1,1,2")]) - -(define_insn "" - [(set (match_operand:SI 0 "register_operand" "=d,d") - (zero_extend:SI (match_operand:HI 1 "memory_operand" "R,m")))] - "TARGET_MIPS16" - "* return mips_move_1word (operands, insn, TRUE);" - [(set_attr "type" "load,load") - (set_attr "mode" "SI") - (set_attr "length" "1,2")]) - -(define_expand "zero_extendhidi2" - [(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) - { - rtx op = gen_lowpart (DImode, operands[1]); - rtx temp = force_reg (DImode, GEN_INT (0xffff)); - - emit_insn (gen_anddi3 (operands[0], op, temp)); - DONE; - } -}") - -(define_insn "" - [(set (match_operand:DI 0 "register_operand" "=d,d,d") - (zero_extend:DI (match_operand:HI 1 "nonimmediate_operand" "d,R,m")))] - "TARGET_64BIT && !TARGET_MIPS16" - "* -{ - if (which_alternative == 0) - return \"andi\\t%0,%1,0xffff\"; - else - return mips_move_1word (operands, insn, TRUE); -}" - [(set_attr "type" "arith,load,load") - (set_attr "mode" "DI") - (set_attr "length" "1,1,2")]) - -(define_insn "" - [(set (match_operand:DI 0 "register_operand" "=d,d") - (zero_extend:DI (match_operand:HI 1 "memory_operand" "R,m")))] - "TARGET_64BIT && TARGET_MIPS16" - "* return mips_move_1word (operands, insn, TRUE);" - [(set_attr "type" "load,load") - (set_attr "mode" "DI") - (set_attr "length" "1,2")]) - -(define_expand "zero_extendqihi2" - [(set (match_operand:HI 0 "register_operand" "") - (zero_extend:HI (match_operand:QI 1 "nonimmediate_operand" "")))] - "" - " -{ - if (TARGET_MIPS16 && GET_CODE (operands[1]) != MEM) - { - rtx op0 = gen_lowpart (SImode, operands[0]); - rtx op1 = gen_lowpart (SImode, operands[1]); - rtx temp = force_reg (SImode, GEN_INT (0xff)); - - emit_insn (gen_andsi3 (op0, op1, temp)); - DONE; - } -}") - -(define_insn "" - [(set (match_operand:HI 0 "register_operand" "=d,d,d") - (zero_extend:HI (match_operand:QI 1 "nonimmediate_operand" "d,R,m")))] - "!TARGET_MIPS16" - "* -{ - if (which_alternative == 0) - return \"andi\\t%0,%1,0x00ff\"; - else - return mips_move_1word (operands, insn, TRUE); -}" - [(set_attr "type" "arith,load,load") - (set_attr "mode" "HI") - (set_attr "length" "1,1,2")]) - -(define_insn "" - [(set (match_operand:HI 0 "register_operand" "=d,d") - (zero_extend:HI (match_operand:QI 1 "memory_operand" "R,m")))] - "TARGET_MIPS16" - "* return mips_move_1word (operands, insn, TRUE);" - [(set_attr "type" "load,load") - (set_attr "mode" "HI") - (set_attr "length" "1,2")]) - -(define_expand "zero_extendqisi2" - [(set (match_operand:SI 0 "register_operand" "") - (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "")))] - "" - " -{ - if (TARGET_MIPS16 && GET_CODE (operands[1]) != MEM) - { - rtx op = gen_lowpart (SImode, operands[1]); - rtx temp = force_reg (SImode, GEN_INT (0xff)); - - emit_insn (gen_andsi3 (operands[0], op, temp)); - DONE; - } -}") - -(define_insn "" - [(set (match_operand:SI 0 "register_operand" "=d,d,d") - (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "d,R,m")))] - "!TARGET_MIPS16" - "* -{ - if (which_alternative == 0) - return \"andi\\t%0,%1,0x00ff\"; - else - return mips_move_1word (operands, insn, TRUE); -}" - [(set_attr "type" "arith,load,load") - (set_attr "mode" "SI") - (set_attr "length" "1,1,2")]) - -(define_insn "" - [(set (match_operand:SI 0 "register_operand" "=d,d") - (zero_extend:SI (match_operand:QI 1 "memory_operand" "R,m")))] - "TARGET_MIPS16" - "* return mips_move_1word (operands, insn, TRUE);" - [(set_attr "type" "load,load") - (set_attr "mode" "SI") - (set_attr "length" "1,2")]) - -(define_expand "zero_extendqidi2" - [(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) - { - rtx op = gen_lowpart (DImode, operands[1]); - rtx temp = force_reg (DImode, GEN_INT (0xff)); - - emit_insn (gen_anddi3 (operands[0], op, temp)); - DONE; - } -}") - -(define_insn "" - [(set (match_operand:DI 0 "register_operand" "=d,d,d") - (zero_extend:DI (match_operand:QI 1 "nonimmediate_operand" "d,R,m")))] - "TARGET_64BIT && !TARGET_MIPS16" - "* -{ - if (which_alternative == 0) - return \"andi\\t%0,%1,0x00ff\"; - else - return mips_move_1word (operands, insn, TRUE); -}" - [(set_attr "type" "arith,load,load") - (set_attr "mode" "DI") - (set_attr "length" "1,1,2")]) - -;; These can be created when a paradoxical subreg operand with an implicit -;; sign_extend operator is reloaded. Because of the subreg, this is really -;; a zero extend. -;; ??? It might be possible to eliminate the need for these patterns by adding -;; more support to reload for implicit sign_extend operators. -(define_insn "*paradoxical_extendhidi2" - [(set (match_operand:DI 0 "register_operand" "=d,d") - (sign_extend:DI - (subreg:SI (match_operand:HI 1 "memory_operand" "R,m") 0)))] - "TARGET_64BIT" - "* -{ - return mips_move_1word (operands, insn, TRUE); -}" - [(set_attr "type" "load,load") - (set_attr "mode" "DI") - (set_attr "length" "1,2")]) - -(define_insn "" - [(set (match_operand:DI 0 "register_operand" "=d,d") - (zero_extend:DI (match_operand:QI 1 "memory_operand" "R,m")))] - "TARGET_64BIT && TARGET_MIPS16" - "* return mips_move_1word (operands, insn, TRUE);" - [(set_attr "type" "load,load") - (set_attr "mode" "DI") - (set_attr "length" "1,2")]) - -;; .................... -;; SIGN EXTENSION -;; .................... - -;; Extension insns. -;; Those for integer source operand are ordered widest source type first. - -;; In 64 bit mode, 32 bit values in general registers are always -;; correctly sign extended. That means that if the target is a -;; general register, we can sign extend from SImode to DImode just by -;; doing a move. - -;; CYGNUS LOCAL law -(define_insn "extendsidi2" - [(set (match_operand:DI 0 "register_operand" "=d,y,d,*d,d,d") - (sign_extend:DI (match_operand:SI 1 "nonimmediate_operand" "d,d,y,*x*w,R,m")))] - "TARGET_64BIT" - "* return mips_move_1word (operands, insn, FALSE);" - [(set_attr "type" "move,move,move,hilo,load,load") - (set_attr "mode" "DI") - (set_attr "length" "1,1,1,1,1,2")]) - -;; These patterns originally accepted general_operands, however, slightly -;; better code is generated by only accepting register_operands, and then -;; letting combine generate the lh and lb insns. - -(define_expand "extendhidi2" - [(set (match_operand:DI 0 "register_operand" "") - (sign_extend:DI (match_operand:HI 1 "nonimmediate_operand" "")))] - "TARGET_64BIT" - " -{ - if (optimize && GET_CODE (operands[1]) == MEM) - operands[1] = force_not_mem (operands[1]); - - if (GET_CODE (operands[1]) != MEM) - { - rtx op1 = gen_lowpart (DImode, operands[1]); - rtx temp = gen_reg_rtx (DImode); - rtx shift = GEN_INT (48); - - emit_insn (gen_ashldi3 (temp, op1, shift)); - emit_insn (gen_ashrdi3 (operands[0], temp, shift)); - DONE; - } -}") - -(define_insn "extendhidi2_internal" - [(set (match_operand:DI 0 "register_operand" "=d,d") - (sign_extend:DI (match_operand:HI 1 "memory_operand" "R,m")))] - "TARGET_64BIT" - "* return mips_move_1word (operands, insn, FALSE);" - [(set_attr "type" "load") - (set_attr "mode" "DI") - (set_attr "length" "1,2")]) - -(define_expand "extendhisi2" - [(set (match_operand:SI 0 "register_operand" "") - (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "")))] - "" - " -{ - if (optimize && GET_CODE (operands[1]) == MEM) - operands[1] = force_not_mem (operands[1]); - - if (GET_CODE (operands[1]) != MEM) - { - rtx op1 = gen_lowpart (SImode, operands[1]); - rtx temp = gen_reg_rtx (SImode); - rtx shift = GEN_INT (16); - - emit_insn (gen_ashlsi3 (temp, op1, shift)); - emit_insn (gen_ashrsi3 (operands[0], temp, shift)); - DONE; - } -}") - -(define_insn "extendhisi2_internal" - [(set (match_operand:SI 0 "register_operand" "=d,d") - (sign_extend:SI (match_operand:HI 1 "memory_operand" "R,m")))] - "" - "* return mips_move_1word (operands, insn, FALSE);" - [(set_attr "type" "load") - (set_attr "mode" "SI") - (set_attr "length" "1,2")]) - -(define_expand "extendqihi2" - [(set (match_operand:HI 0 "register_operand" "") - (sign_extend:HI (match_operand:QI 1 "nonimmediate_operand" "")))] - "" - " -{ - if (optimize && GET_CODE (operands[1]) == MEM) - operands[1] = force_not_mem (operands[1]); - - if (GET_CODE (operands[1]) != MEM) - { - rtx op0 = gen_lowpart (SImode, operands[0]); - rtx op1 = gen_lowpart (SImode, operands[1]); - rtx temp = gen_reg_rtx (SImode); - rtx shift = GEN_INT (24); - - emit_insn (gen_ashlsi3 (temp, op1, shift)); - emit_insn (gen_ashrsi3 (op0, temp, shift)); - DONE; - } -}") - -(define_insn "extendqihi2_internal" - [(set (match_operand:HI 0 "register_operand" "=d,d") - (sign_extend:HI (match_operand:QI 1 "memory_operand" "R,m")))] - "" - "* return mips_move_1word (operands, insn, FALSE);" - [(set_attr "type" "load") - (set_attr "mode" "SI") - (set_attr "length" "1,2")]) - - -(define_expand "extendqisi2" - [(set (match_operand:SI 0 "register_operand" "") - (sign_extend:SI (match_operand:QI 1 "nonimmediate_operand" "")))] - "" - " -{ - if (optimize && GET_CODE (operands[1]) == MEM) - operands[1] = force_not_mem (operands[1]); - - if (GET_CODE (operands[1]) != MEM) - { - rtx op1 = gen_lowpart (SImode, operands[1]); - rtx temp = gen_reg_rtx (SImode); - rtx shift = GEN_INT (24); - - emit_insn (gen_ashlsi3 (temp, op1, shift)); - emit_insn (gen_ashrsi3 (operands[0], temp, shift)); - DONE; - } -}") - -(define_insn "extendqisi2_insn" - [(set (match_operand:SI 0 "register_operand" "=d,d") - (sign_extend:SI (match_operand:QI 1 "memory_operand" "R,m")))] - "" - "* return mips_move_1word (operands, insn, FALSE);" - [(set_attr "type" "load") - (set_attr "mode" "SI") - (set_attr "length" "1,2")]) - -(define_expand "extendqidi2" - [(set (match_operand:DI 0 "register_operand" "") - (sign_extend:DI (match_operand:QI 1 "nonimmediate_operand" "")))] - "TARGET_64BIT" - " -{ - if (optimize && GET_CODE (operands[1]) == MEM) - operands[1] = force_not_mem (operands[1]); - - if (GET_CODE (operands[1]) != MEM) - { - rtx op1 = gen_lowpart (DImode, operands[1]); - rtx temp = gen_reg_rtx (DImode); - rtx shift = GEN_INT (56); - - emit_insn (gen_ashldi3 (temp, op1, shift)); - emit_insn (gen_ashrdi3 (operands[0], temp, shift)); - DONE; - } -}") - -(define_insn "extendqidi2_insn" - [(set (match_operand:DI 0 "register_operand" "=d,d") - (sign_extend:DI (match_operand:QI 1 "memory_operand" "R,m")))] - "TARGET_64BIT" - "* return mips_move_1word (operands, insn, FALSE);" - [(set_attr "type" "load") - (set_attr "mode" "DI") - (set_attr "length" "1,2")]) - - -(define_insn "extendsfdf2" - [(set (match_operand:DF 0 "register_operand" "=f") - (float_extend:DF (match_operand:SF 1 "register_operand" "f")))] - "TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT" - "cvt.d.s\\t%0,%1" - [(set_attr "type" "fcvt") - (set_attr "mode" "DF") - (set_attr "length" "1")]) - - - -;; .................... -;; CONVERSIONS -;; .................... - -;; The SImode scratch register can not be shared with address regs used for -;; operand zero, because then the address in the move instruction will be -;; clobbered. We mark the scratch register as early clobbered to prevent this. - -;; We need the ?X in alternative 1 so that it will be choosen only if the -;; destination is a floating point register. Otherwise, alternative 1 can -;; have lower cost than alternative 0 (because there is one less loser), and -;; can be choosen when it won't work (because integral reloads into FP -;; registers are not supported). - -(define_insn "fix_truncdfsi2" - [(set (match_operand:SI 0 "general_operand" "=d,*f,R,To") - (fix:SI (match_operand:DF 1 "register_operand" "f,*f,f,f"))) - (clobber (match_scratch:SI 2 "=d,*d,&d,&d")) - (clobber (match_scratch:DF 3 "=f,?*X,f,f"))] - "TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT" - "* -{ - rtx xoperands[10]; - - if (which_alternative == 1) - return \"trunc.w.d %0,%1,%2\"; - - output_asm_insn (\"trunc.w.d %3,%1,%2\", operands); - - xoperands[0] = operands[0]; - xoperands[1] = operands[3]; - output_asm_insn (mips_move_1word (xoperands, insn, FALSE), xoperands); - return \"\"; -}" - [(set_attr "type" "fcvt") - (set_attr "mode" "DF") - (set_attr "length" "11,9,10,11")]) - - -(define_insn "fix_truncsfsi2" - [(set (match_operand:SI 0 "general_operand" "=d,*f,R,To") - (fix:SI (match_operand:SF 1 "register_operand" "f,*f,f,f"))) - (clobber (match_scratch:SI 2 "=d,*d,&d,&d")) - (clobber (match_scratch:SF 3 "=f,?*X,f,f"))] - "TARGET_HARD_FLOAT && !0" ;; CYGNUS LOCAL law - "* -{ - rtx xoperands[10]; - - if (which_alternative == 1) - return \"trunc.w.s %0,%1,%2\"; - - output_asm_insn (\"trunc.w.s %3,%1,%2\", operands); - - xoperands[0] = operands[0]; - xoperands[1] = operands[3]; - output_asm_insn (mips_move_1word (xoperands, insn, FALSE), xoperands); - return \"\"; -}" - [(set_attr "type" "fcvt") - (set_attr "mode" "SF") - (set_attr "length" "11,9,10,11")]) - - -;;; ??? 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 "general_operand" "=d,*f,R,To") - (fix:DI (match_operand:DF 1 "register_operand" "f,*f,f,f"))) - (clobber (match_scratch:DF 2 "=f,?*X,f,f"))] - "TARGET_HARD_FLOAT && TARGET_64BIT && TARGET_DOUBLE_FLOAT" - "* -{ - rtx xoperands[10]; - - if (which_alternative == 1) - return \"trunc.l.d %0,%1\"; - - output_asm_insn (\"trunc.l.d %2,%1\", operands); - - xoperands[0] = operands[0]; - xoperands[1] = operands[2]; - output_asm_insn (mips_move_2words (xoperands, insn, FALSE), xoperands); - return \"\"; -}" - [(set_attr "type" "fcvt") - (set_attr "mode" "DF") - (set_attr "length" "2,1,2,3")]) - - -;;; ??? 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 "general_operand" "=d,*f,R,To") - (fix:DI (match_operand:SF 1 "register_operand" "f,*f,f,f"))) - (clobber (match_scratch:DF 2 "=f,?*X,f,f"))] - "TARGET_HARD_FLOAT && TARGET_64BIT && TARGET_DOUBLE_FLOAT" - "* -{ - rtx xoperands[10]; - - if (which_alternative == 1) - return \"trunc.l.s %0,%1\"; - - output_asm_insn (\"trunc.l.s %2,%1\", operands); - - xoperands[0] = operands[0]; - xoperands[1] = operands[2]; - output_asm_insn (mips_move_2words (xoperands, insn, FALSE), xoperands); - return \"\"; -}" - [(set_attr "type" "fcvt") - (set_attr "mode" "SF") - (set_attr "length" "2,1,2,3")]) - - -(define_insn "floatsidf2" - [(set (match_operand:DF 0 "register_operand" "=f,f,f") - (float:DF (match_operand:SI 1 "nonimmediate_operand" "d,R,m")))] - "TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT" - "* -{ - dslots_load_total++; - if (GET_CODE (operands[1]) == MEM) - return \"l.s\\t%0,%1%#\;cvt.d.w\\t%0,%0\"; - - return \"mtc1\\t%1,%0%#\;cvt.d.w\\t%0,%0\"; -}" - [(set_attr "type" "fcvt") - (set_attr "mode" "DF") - (set_attr "length" "3,4,3")]) - - -(define_insn "floatdidf2" - [(set (match_operand:DF 0 "register_operand" "=f,f,f") - (float:DF (match_operand:DI 1 "se_nonimmediate_operand" "d,R,m")))] - "TARGET_HARD_FLOAT && TARGET_64BIT && TARGET_DOUBLE_FLOAT" - "* -{ - dslots_load_total++; - if (GET_CODE (operands[1]) == MEM) - return \"l.d\\t%0,%1%#\;cvt.d.l\\t%0,%0\"; - - return \"dmtc1\\t%1,%0%#\;cvt.d.l\\t%0,%0\"; -}" - [(set_attr "type" "fcvt") - (set_attr "mode" "DF") - (set_attr "length" "3,4,3")]) - - -(define_insn "floatsisf2" - [(set (match_operand:SF 0 "register_operand" "=f,f,f") - (float:SF (match_operand:SI 1 "nonimmediate_operand" "d,R,m")))] - "TARGET_HARD_FLOAT" - "* -{ - dslots_load_total++; - if (GET_CODE (operands[1]) == MEM) - return \"l.s\\t%0,%1%#\;cvt.s.w\\t%0,%0\"; - - return \"mtc1\\t%1,%0%#\;cvt.s.w\\t%0,%0\"; -}" - [(set_attr "type" "fcvt") - (set_attr "mode" "SF") - (set_attr "length" "3,4,3")]) - - -(define_insn "floatdisf2" - [(set (match_operand:SF 0 "register_operand" "=f,f,f") - (float:SF (match_operand:DI 1 "se_nonimmediate_operand" "d,R,m")))] - "TARGET_HARD_FLOAT && TARGET_64BIT && TARGET_DOUBLE_FLOAT" - "* -{ - dslots_load_total++; - if (GET_CODE (operands[1]) == MEM) - return \"l.d\\t%0,%1%#\;cvt.s.l\\t%0,%0\"; - - return \"dmtc1\\t%1,%0%#\;cvt.s.l\\t%0,%0\"; -}" - [(set_attr "type" "fcvt") - (set_attr "mode" "SF") - (set_attr "length" "3,4,3")]) - - -(define_expand "fixuns_truncdfsi2" - [(set (match_operand:SI 0 "register_operand" "") - (unsigned_fix:SI (match_operand:DF 1 "register_operand" "")))] - "TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT" - " -{ - rtx reg1 = gen_reg_rtx (DFmode); - rtx reg2 = gen_reg_rtx (DFmode); - rtx reg3 = gen_reg_rtx (SImode); - rtx label1 = gen_label_rtx (); - rtx label2 = gen_label_rtx (); - REAL_VALUE_TYPE offset = REAL_VALUE_LDEXP (1.0, 31); - - if (reg1) /* turn off complaints about unreached code */ - { - emit_move_insn (reg1, immed_real_const_1 (offset, DFmode)); - do_pending_stack_adjust (); - - emit_insn (gen_cmpdf (operands[1], reg1)); - emit_jump_insn (gen_bge (label1)); - - emit_insn (gen_fix_truncdfsi2 (operands[0], operands[1])); - emit_jump_insn (gen_rtx (SET, VOIDmode, pc_rtx, - gen_rtx (LABEL_REF, VOIDmode, label2))); - emit_barrier (); - - emit_label (label1); - emit_move_insn (reg2, gen_rtx (MINUS, DFmode, operands[1], reg1)); - emit_move_insn (reg3, GEN_INT (0x80000000)); - - emit_insn (gen_fix_truncdfsi2 (operands[0], reg2)); - emit_insn (gen_iorsi3 (operands[0], operands[0], reg3)); - - emit_label (label2); - - /* allow REG_NOTES to be set on last insn (labels don't have enough - fields, and can't be used for REG_NOTES anyway). */ - emit_insn (gen_rtx (USE, VOIDmode, stack_pointer_rtx)); - DONE; - } -}") - - -(define_expand "fixuns_truncdfdi2" - [(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); - rtx reg3 = gen_reg_rtx (DImode); - rtx label1 = gen_label_rtx (); - rtx label2 = gen_label_rtx (); - REAL_VALUE_TYPE offset = REAL_VALUE_LDEXP (1.0, 63); - - if (reg1) /* turn off complaints about unreached code */ - { - emit_move_insn (reg1, immed_real_const_1 (offset, DFmode)); - do_pending_stack_adjust (); - - emit_insn (gen_cmpdf (operands[1], reg1)); - emit_jump_insn (gen_bge (label1)); - - emit_insn (gen_fix_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 (0x80000000)); - 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_label (label2); - - /* allow REG_NOTES to be set on last insn (labels don't have enough - fields, and can't be used for REG_NOTES anyway). */ - emit_insn (gen_rtx (USE, VOIDmode, stack_pointer_rtx)); - DONE; - } -}") - - -(define_expand "fixuns_truncsfsi2" - [(set (match_operand:SI 0 "register_operand" "") - (unsigned_fix:SI (match_operand:SF 1 "register_operand" "")))] - "TARGET_HARD_FLOAT && !0" ;; CYGNUS LOCAL law - " -{ - rtx reg1 = gen_reg_rtx (SFmode); - rtx reg2 = gen_reg_rtx (SFmode); - rtx reg3 = gen_reg_rtx (SImode); - rtx label1 = gen_label_rtx (); - rtx label2 = gen_label_rtx (); - REAL_VALUE_TYPE offset = REAL_VALUE_LDEXP (1.0, 31); - - if (reg1) /* turn off complaints about unreached code */ - { - emit_move_insn (reg1, immed_real_const_1 (offset, SFmode)); - do_pending_stack_adjust (); - - emit_insn (gen_cmpsf (operands[1], reg1)); - emit_jump_insn (gen_bge (label1)); - - emit_insn (gen_fix_truncsfsi2 (operands[0], operands[1])); - emit_jump_insn (gen_rtx (SET, VOIDmode, pc_rtx, - gen_rtx (LABEL_REF, VOIDmode, label2))); - emit_barrier (); - - emit_label (label1); - emit_move_insn (reg2, gen_rtx (MINUS, SFmode, operands[1], reg1)); - emit_move_insn (reg3, GEN_INT (0x80000000)); - - emit_insn (gen_fix_truncsfsi2 (operands[0], reg2)); - emit_insn (gen_iorsi3 (operands[0], operands[0], reg3)); - - emit_label (label2); - - /* allow REG_NOTES to be set on last insn (labels don't have enough - fields, and can't be used for REG_NOTES anyway). */ - emit_insn (gen_rtx (USE, VOIDmode, stack_pointer_rtx)); - DONE; - } -}") - - -(define_expand "fixuns_truncsfdi2" - [(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); - rtx reg3 = gen_reg_rtx (DImode); - rtx label1 = gen_label_rtx (); - rtx label2 = gen_label_rtx (); - REAL_VALUE_TYPE offset = REAL_VALUE_LDEXP (1.0, 63); - - if (reg1) /* turn off complaints about unreached code */ - { - emit_move_insn (reg1, immed_real_const_1 (offset, SFmode)); - do_pending_stack_adjust (); - - emit_insn (gen_cmpsf (operands[1], reg1)); - emit_jump_insn (gen_bge (label1)); - - emit_insn (gen_fix_truncsfdi2 (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 (0x80000000)); - emit_insn (gen_ashldi3 (reg3, reg3, GEN_INT (32))); - - emit_insn (gen_fix_truncsfdi2 (operands[0], reg2)); - emit_insn (gen_iordi3 (operands[0], operands[0], reg3)); - - emit_label (label2); - - /* allow REG_NOTES to be set on last insn (labels don't have enough - fields, and can't be used for REG_NOTES anyway). */ - emit_insn (gen_rtx (USE, VOIDmode, stack_pointer_rtx)); - DONE; - } -}") - - -;; .................... -;; DATA MOVEMENT -;; .................... - -;; Bit field extract patterns which use lwl/lwr. - -;; ??? There could be HImode variants for the ulh/ulhu/ush macros. -;; It isn't clear whether this will give better code. - -;; Only specify the mode operand 1, the rest are assumed to be word_mode. -(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" "")))] - "!TARGET_MIPS16" - " -{ - /* If the field does not start on a byte boundary, then fail. */ - if (INTVAL (operands[3]) % 8 != 0) - FAIL; - - /* MIPS I and MIPS II can only handle a 32bit field. */ - if (!TARGET_64BIT && INTVAL (operands[2]) != 32) - FAIL; - - /* MIPS III and MIPS IV can handle both 32bit and 64bit fields. */ - if (TARGET_64BIT - && INTVAL (operands[2]) != 64 - && INTVAL (operands[2]) != 32) - FAIL; - - /* This can happen for a 64 bit target, when extracting a value from - a 64 bit union member. extract_bit_field doesn't verify that our - source matches the predicate, so we force it to be a MEM here. */ - if (GET_CODE (operands[1]) != MEM) - FAIL; - - /* Change the mode to BLKmode for aliasing purposes. */ - operands[1] = change_address (operands[1], BLKmode, XEXP (operands[1], 0)); - - /* Otherwise, emit a l[wd]l/l[wd]r pair to load the value. */ - if (INTVAL (operands[2]) == 64) - emit_insn (gen_movdi_uld (operands[0], operands[1])); - else - { - if (TARGET_64BIT) - { - operands[0] = gen_lowpart (SImode, operands[0]); - if (operands[0] == NULL_RTX) - FAIL; - } - emit_insn (gen_movsi_ulw (operands[0], operands[1])); - } - DONE; -}") - -;; Only specify the mode operand 1, the rest are assumed to be word_mode. -(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" "")))] - "!TARGET_MIPS16" - " -{ - /* If the field does not start on a byte boundary, then fail. */ - if (INTVAL (operands[3]) % 8 != 0) - FAIL; - - /* MIPS I and MIPS II can only handle a 32bit field. */ - if (!TARGET_64BIT && INTVAL (operands[2]) != 32) - FAIL; - - /* MIPS III and MIPS IV can handle both 32bit and 64bit fields. */ - if (TARGET_64BIT - && INTVAL (operands[2]) != 64 - && INTVAL (operands[2]) != 32) - FAIL; - - /* This can happen for a 64 bit target, when extracting a value from - a 64 bit union member. extract_bit_field doesn't verify that our - source matches the predicate, so we force it to be a MEM here. */ - if (GET_CODE (operands[1]) != MEM) - FAIL; - - /* Change the mode to BLKmode for aliasing purposes. */ - operands[1] = change_address (operands[1], BLKmode, XEXP (operands[1], 0)); - - /* Otherwise, emit a lwl/lwr pair to load the value. */ - if (INTVAL (operands[2]) == 64) - emit_insn (gen_movdi_uld (operands[0], operands[1])); - else - { - if (TARGET_64BIT) - { - operands[0] = gen_lowpart (SImode, operands[0]); - if (operands[0] == NULL_RTX) - FAIL; - } - emit_insn (gen_movsi_ulw (operands[0], operands[1])); - } - DONE; -}") - -;; Only specify the mode operands 0, the rest are assumed to be word_mode. -(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 "register_operand" ""))] - "!TARGET_MIPS16" - " -{ - /* If the field does not start on a byte boundary, then fail. */ - if (INTVAL (operands[2]) % 8 != 0) - FAIL; - - /* MIPS I and MIPS II can only handle a 32bit field. */ - if (!TARGET_64BIT && INTVAL (operands[1]) != 32) - FAIL; - - /* MIPS III and MIPS IV can handle both 32bit and 64bit fields. */ - if (TARGET_64BIT - && INTVAL (operands[1]) != 64 - && INTVAL (operands[1]) != 32) - FAIL; - - /* This can happen for a 64 bit target, when storing into a 32 bit union - member. store_bit_field doesn't verify that our target matches the - predicate, so we force it to be a MEM here. */ - if (GET_CODE (operands[0]) != MEM) - FAIL; - - /* Change the mode to BLKmode for aliasing purposes. */ - operands[0] = change_address (operands[0], BLKmode, XEXP (operands[0], 0)); - - /* Otherwise, emit a s[wd]l/s[wd]r pair to load the value. */ - if (INTVAL (operands[1]) == 64) - emit_insn (gen_movdi_usd (operands[0], operands[3])); - else - { - if (TARGET_64BIT) - { - operands[3] = gen_lowpart (SImode, operands[3]); - if (operands[3] == NULL_RTX) - FAIL; - } - emit_insn (gen_movsi_usw (operands[0], operands[3])); - } - DONE; -}") - -;; unaligned word moves generated by the bit field patterns - -(define_insn "movsi_ulw" - [(set (match_operand:SI 0 "register_operand" "=&d,&d") - (unspec:SI [(match_operand:BLK 1 "general_operand" "R,o")] 0))] - "!TARGET_MIPS16" - "* -{ - rtx offset = const0_rtx; - rtx addr = XEXP (operands[1], 0); - rtx mem_addr = eliminate_constant_term (addr, &offset); - char *ret; - - if (TARGET_STATS) - mips_count_memory_refs (operands[1], 2); - - /* The stack/frame pointers are always aligned, so we can convert - to the faster lw if we are referencing an aligned stack location. */ - - if ((INTVAL (offset) & 3) == 0 - && (mem_addr == stack_pointer_rtx || mem_addr == frame_pointer_rtx)) - ret = \"lw\\t%0,%1\"; - else - ret = \"ulw\\t%0,%1\"; - - return mips_fill_delay_slot (ret, DELAY_LOAD, operands, insn); -}" - [(set_attr "type" "load,load") - (set_attr "mode" "SI") - (set_attr "length" "2,4")]) - -(define_insn "movsi_usw" - [(set (match_operand:BLK 0 "memory_operand" "=R,o") - (unspec:BLK [(match_operand:SI 1 "reg_or_0_operand" "dJ,dJ")] 1))] - "!TARGET_MIPS16" - "* -{ - rtx offset = const0_rtx; - rtx addr = XEXP (operands[0], 0); - rtx mem_addr = eliminate_constant_term (addr, &offset); - - if (TARGET_STATS) - mips_count_memory_refs (operands[0], 2); - - /* The stack/frame pointers are always aligned, so we can convert - to the faster sw if we are referencing an aligned stack location. */ - - if ((INTVAL (offset) & 3) == 0 - && (mem_addr == stack_pointer_rtx || mem_addr == frame_pointer_rtx)) - return \"sw\\t%1,%0\"; - - return \"usw\\t%z1,%0\"; -}" - [(set_attr "type" "store") - (set_attr "mode" "SI") - (set_attr "length" "2,4")]) - -;; Bit field extract patterns which use ldl/ldr. - -;; unaligned double word moves generated by the bit field patterns - -(define_insn "movdi_uld" - [(set (match_operand:DI 0 "register_operand" "=&d,&d") - (unspec:DI [(match_operand:BLK 1 "general_operand" "R,o")] 0))] - "" - "* -{ - rtx offset = const0_rtx; - rtx addr = XEXP (operands[1], 0); - rtx mem_addr = eliminate_constant_term (addr, &offset); - char *ret; - - if (TARGET_STATS) - mips_count_memory_refs (operands[1], 2); - - /* The stack/frame pointers are always aligned, so we can convert - to the faster lw if we are referencing an aligned stack location. */ - - if ((INTVAL (offset) & 7) == 0 - && (mem_addr == stack_pointer_rtx || mem_addr == frame_pointer_rtx)) - ret = \"ld\\t%0,%1\"; - else - ret = \"uld\\t%0,%1\"; - - return mips_fill_delay_slot (ret, DELAY_LOAD, operands, insn); -}" - [(set_attr "type" "load,load") - (set_attr "mode" "SI") - (set_attr "length" "2,4")]) - -(define_insn "movdi_usd" - [(set (match_operand:BLK 0 "memory_operand" "=R,o") - (unspec:BLK [(match_operand:DI 1 "reg_or_0_operand" "dJ,dJ")] 1))] - "" - "* -{ - rtx offset = const0_rtx; - rtx addr = XEXP (operands[0], 0); - rtx mem_addr = eliminate_constant_term (addr, &offset); - - if (TARGET_STATS) - mips_count_memory_refs (operands[0], 2); - - /* The stack/frame pointers are always aligned, so we can convert - to the faster sw if we are referencing an aligned stack location. */ - - if ((INTVAL (offset) & 7) == 0 - && (mem_addr == stack_pointer_rtx || mem_addr == frame_pointer_rtx)) - return \"sd\\t%1,%0\"; - - return \"usd\\t%z1,%0\"; -}" - [(set_attr "type" "store") - (set_attr "mode" "SI") - (set_attr "length" "2,4")]) - -;; These two patterns support loading addresses with two instructions instead -;; of using the macro instruction la. - -;; ??? mips_move_1word has support for HIGH, so this pattern may be -;; unnecessary. - -(define_insn "high" - [(set (match_operand:SI 0 "register_operand" "=r") - (high:SI (match_operand:SI 1 "immediate_operand" "")))] - "mips_split_addresses && !TARGET_MIPS16" - "lui\\t%0,%%hi(%1) # high" - [(set_attr "type" "move") - (set_attr "length" "1")]) - -(define_insn "low" - [(set (match_operand:SI 0 "register_operand" "=r") - (lo_sum:SI (match_operand:SI 1 "register_operand" "r") - (match_operand:SI 2 "immediate_operand" "")))] - "mips_split_addresses && !TARGET_MIPS16" - "addiu\\t%0,%1,%%lo(%2) # low" - [(set_attr "type" "arith") - (set_attr "mode" "SI") - (set_attr "length" "1")]) - - -;; 64-bit integer moves - -;; Unlike most other insns, the move insns can't be split with -;; different predicates, because register spilling and other parts of -;; the compiler, have memoized the insn number already. - -(define_expand "movdi" - [(set (match_operand:DI 0 "nonimmediate_operand" "") - (match_operand:DI 1 "general_operand" ""))] - "" - " -{ - if (mips_split_addresses && mips_check_split (operands[1], DImode)) - { - enum machine_mode mode = GET_MODE (operands[0]); - rtx tem = ((reload_in_progress | reload_completed) - ? operands[0] : gen_reg_rtx (mode)); - - emit_insn (gen_rtx (SET, VOIDmode, tem, - gen_rtx (HIGH, mode, operands[1]))); - - operands[1] = gen_rtx (LO_SUM, mode, tem, operands[1]); - } - - /* 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_rtx, - force_reg (DImode, temp)); - emit_move_insn (operands[0], force_reg (DImode, temp)); - DONE; - } - - /* If operands[1] is a constant address illegal for pic, then we need to - handle it just like LEGITIMIZE_ADDRESS does. */ - if (flag_pic && pic_address_needs_scratch (operands[1])) - { - rtx temp = force_reg (DImode, XEXP (XEXP (operands[1], 0), 0)); - rtx temp2 = XEXP (XEXP (operands[1], 0), 1); - - if (! SMALL_INT (temp2)) - temp2 = force_reg (DImode, temp2); - - emit_move_insn (operands[0], gen_rtx (PLUS, DImode, temp, temp2)); - DONE; - } - - /* On the mips16, we can handle a GP relative reference by adding in - $gp. We need to check the name to see whether this is a string - constant. */ - if (TARGET_MIPS16 - && register_operand (operands[0], DImode) - && GET_CODE (operands[1]) == SYMBOL_REF - && SYMBOL_REF_FLAG (operands[1])) - { - char *name = XSTR (operands[1], 0); - - if (name[0] != '*' - || strncmp (name + 1, LOCAL_LABEL_PREFIX, - sizeof LOCAL_LABEL_PREFIX - 1) != 0) - { - rtx base_reg; - - if (reload_in_progress || reload_completed) - { - /* In movsi we use the constant table here. However, in - this case, we're better off copying $28 into a - register and adding, because the constant table entry - would be 8 bytes. */ - base_reg = operands[0]; - emit_move_insn (base_reg, - gen_rtx (CONST, DImode, - gen_rtx (REG, DImode, - GP_REG_FIRST + 28))); - } - else - { - base_reg = gen_reg_rtx (Pmode); - emit_move_insn (base_reg, mips16_gp_pseudo_reg ()); - } - - emit_move_insn (operands[0], - gen_rtx (PLUS, Pmode, base_reg, - mips16_gp_offset (operands[1]))); - DONE; - } - } - - if ((reload_in_progress | reload_completed) == 0 - && !register_operand (operands[0], DImode) - && !register_operand (operands[1], DImode) - && (TARGET_MIPS16 - || ((GET_CODE (operands[1]) != CONST_INT || INTVAL (operands[1]) != 0) - && operands[1] != CONST0_RTX (DImode)))) - { - rtx temp = force_reg (DImode, operands[1]); - emit_move_insn (operands[0], 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" "R,m") - (reg:DI 31))] - "TARGET_MIPS16 && TARGET_64BIT" - "* -{ - operands[1] = gen_rtx (REG, DImode, 31); - return mips_move_2words (operands, insn); -}" - [(set_attr "type" "store") - (set_attr "mode" "DI") - (set_attr "length" "1,2")]) - -;; CYGNUS LOCAL law -(define_insn "movdi_internal" - [(set (match_operand:DI 0 "nonimmediate_operand" "=d,d,d,d,R,o,*x*w,*d,*x*w") - (match_operand:DI 1 "general_operand" "d,iF,R,o,d,d,J,*x,*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))" - "* return mips_move_2words (operands, insn); " - [(set_attr "type" "move,arith,load,load,store,store,hilo,hilo,hilo") - (set_attr "mode" "DI") - (set_attr "length" "2,4,2,4,2,4,2,2,2")]) - -;; CYGNUS LOCAL law -(define_insn "" - [(set (match_operand:DI 0 "nonimmediate_operand" "=d,y,d,d,d,d,d,R,To,*d") - (match_operand:DI 1 "general_operand" "d,d,y,K,N,R,To,d,d,*x*w"))] - "!TARGET_64BIT && TARGET_MIPS16 - && (register_operand (operands[0], DImode) - || register_operand (operands[1], DImode))" - "* return mips_move_2words (operands, insn);" - [(set_attr "type" "move,move,move,arith,arith,load,load,store,store,hilo") - (set_attr "mode" "DI") - (set_attr "length" "2,2,2,2,3,2,4,2,4,2")]) - -(define_split - [(set (match_operand:DI 0 "register_operand" "") - (match_operand:DI 1 "register_operand" ""))] - "reload_completed && !TARGET_64BIT && !TARGET_DEBUG_D_MODE && !TARGET_DEBUG_G_MODE - && GET_CODE (operands[0]) == REG && GP_REG_P (REGNO (operands[0])) - && GET_CODE (operands[1]) == REG && GP_REG_P (REGNO (operands[1]))" - - [(set (subreg:SI (match_dup 0) 0) (subreg:SI (match_dup 1) 0)) - (set (subreg:SI (match_dup 0) 1) (subreg:SI (match_dup 1) 1))] - "") - -;; CYGNUS LOCAL law -(define_insn "movdi_internal2" - [(set (match_operand:DI 0 "nonimmediate_operand" "=d,d,d,d,d,d,R,m,*x*w,*d,*x*w,*a*q") - (match_operand:DI 1 "movdi_operand" "d,S,IKL,Mnis,R,m,dJ,dJ,J,*x*w,*d,*J"))] - "TARGET_64BIT && !TARGET_MIPS16 - && (register_operand (operands[0], DImode) - || se_register_operand (operands[1], DImode) - || (GET_CODE (operands[1]) == CONST_INT && INTVAL (operands[1]) == 0) - || operands[1] == CONST0_RTX (DImode))" - "* return mips_move_2words (operands, insn); " - [(set_attr "type" "move,load,arith,arith,load,load,store,store,hilo,hilo,hilo,hilo") - (set_attr "mode" "DI") - (set_attr "length" "1,2,1,2,1,2,1,2,1,1,1,2")]) - -;; CYGNUS LOCAL law -(define_insn "" - [(set (match_operand:DI 0 "nonimmediate_operand" "=d,y,d,d,d,d,d,d,R,m,*d") - (match_operand:DI 1 "movdi_operand" "d,d,y,K,N,s,R,m,d,d,*x*w"))] - "TARGET_64BIT && TARGET_MIPS16 - && (register_operand (operands[0], DImode) - || se_register_operand (operands[1], DImode))" - "* return mips_move_2words (operands, insn);" - [(set_attr "type" "move,move,move,arith,arith,arith,load,load,store,store,hilo") - (set_attr "mode" "DI") - (set_attr_alternative "length" - [(const_int 1) - (const_int 1) - (const_int 1) - (if_then_else (match_operand:VOID 1 "m16_uimm8_1" "") - (const_int 1) - (const_int 2)) - (if_then_else (match_operand:VOID 1 "m16_nuimm8_1" "") - (const_int 2) - (const_int 3)) - (if_then_else (match_operand:VOID 1 "m16_usym5_4" "") - (const_int 1) - (const_int 2)) - (const_int 1) - (const_int 2) - (const_int 1) - (const_int 2) - (const_int 1)])]) - -;; On the mips16, we can split ld $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:DI 0 "register_operand" "") - (mem:DI (plus:DI (match_dup 0) - (match_operand:DI 1 "const_int_operand" ""))))] - "TARGET_64BIT && TARGET_MIPS16 && reload_completed - && GET_CODE (operands[0]) == REG - && M16_REG_P (REGNO (operands[0])) - && GET_CODE (operands[1]) == CONST_INT - && ((INTVAL (operands[1]) < 0 - && INTVAL (operands[1]) >= -0x10) - || (INTVAL (operands[1]) >= 32 * 8 - && INTVAL (operands[1]) <= 31 * 8 + 0x8) - || (INTVAL (operands[1]) >= 0 - && INTVAL (operands[1]) < 32 * 8 - && (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); - else if (val >= 32 * 8) - { - int off = val & 7; - - operands[1] = GEN_INT (0x8 + off); - operands[2] = GEN_INT (val - off - 0x8); - } - else - { - int off = val & 7; - - operands[1] = GEN_INT (off); - operands[2] = GEN_INT (val - off); - } -}") - -;; Handle input reloads in DImode. -;; This is mainly to handle reloading HILO_REGNUM. Note that we may -;; see it as the source or the destination, depending upon which way -;; reload handles the instruction. -;; Making the second operand TImode is a trick. The compiler may -;; reuse the same register for operand 0 and operand 2. Using TImode -;; gives us two registers, so we can always use the one which is not -;; used. - -(define_expand "reload_indi" - [(set (match_operand:DI 0 "register_operand" "=b") - (match_operand:DI 1 "" "b")) - (clobber (match_operand:TI 2 "register_operand" "=&d"))] - "TARGET_64BIT" - " -{ - rtx scratch = gen_rtx (REG, DImode, - (REGNO (operands[0]) == REGNO (operands[2]) - ? REGNO (operands[2]) + 1 - : REGNO (operands[2]))); - - if (GET_CODE (operands[0]) == REG && REGNO (operands[0]) == HILO_REGNUM) - { - if (GET_CODE (operands[1]) == MEM) - { - rtx memword, offword, hiword, loword; - rtx addr = find_replacement (&XEXP (operands[1], 0)); - rtx op1 = change_address (operands[1], VOIDmode, addr); - - scratch = gen_rtx (REG, SImode, REGNO (scratch)); - memword = change_address (op1, SImode, NULL_RTX); - offword = change_address (adj_offsettable_operand (op1, 4), - SImode, NULL_RTX); - if (BYTES_BIG_ENDIAN) - { - hiword = memword; - loword = offword; - } - else - { - hiword = offword; - loword = memword; - } - emit_move_insn (scratch, hiword); - emit_move_insn (gen_rtx (REG, SImode, 64), scratch); - emit_move_insn (scratch, loword); - emit_move_insn (gen_rtx (REG, SImode, 65), scratch); - emit_insn (gen_rtx_USE (VOIDmode, operands[0])); - } - else - { - emit_insn (gen_ashrdi3 (scratch, operands[1], GEN_INT (32))); - emit_insn (gen_movdi (gen_rtx (REG, DImode, 64), scratch)); - emit_insn (gen_ashldi3 (scratch, operands[1], GEN_INT (32))); - emit_insn (gen_ashrdi3 (scratch, scratch, GEN_INT (32))); - emit_insn (gen_movdi (gen_rtx (REG, DImode, 65), scratch)); - emit_insn (gen_rtx_USE (VOIDmode, operands[0])); - } - DONE; - } - if (GET_CODE (operands[1]) == REG && REGNO (operands[1]) == HILO_REGNUM) - { - emit_insn (gen_movdi (scratch, gen_rtx (REG, DImode, 65))); - emit_insn (gen_ashldi3 (scratch, scratch, GEN_INT (32))); - emit_insn (gen_lshrdi3 (scratch, scratch, GEN_INT (32))); - emit_insn (gen_movdi (operands[0], gen_rtx (REG, DImode, 64))); - emit_insn (gen_ashldi3 (operands[0], operands[0], GEN_INT (32))); - emit_insn (gen_iordi3 (operands[0], operands[0], scratch)); - emit_insn (gen_rtx_USE (VOIDmode, operands[1])); - DONE; - } - /* This handles moves between a float register and HI/LO. */ - emit_move_insn (scratch, operands[1]); - emit_move_insn (operands[0], scratch); - DONE; -}") - -;; Handle output reloads in DImode. - -;; Reloading HILO_REG in MIPS16 mode requires two scratch registers, so we -;; use a TImode scratch reg. - -(define_expand "reload_outdi" - [(set (match_operand:DI 0 "" "=b") - (match_operand:DI 1 "se_register_operand" "b")) - (clobber (match_operand:TI 2 "register_operand" "=&d"))] - "TARGET_64BIT" - " -{ - rtx scratch = gen_rtx_REG (DImode, REGNO (operands[2])); - - if (GET_CODE (operands[0]) == REG && REGNO (operands[0]) == HILO_REGNUM) - { - emit_insn (gen_ashrdi3 (scratch, operands[1], GEN_INT (32))); - emit_insn (gen_movdi (gen_rtx (REG, DImode, 64), scratch)); - emit_insn (gen_ashldi3 (scratch, operands[1], GEN_INT (32))); - emit_insn (gen_ashrdi3 (scratch, scratch, GEN_INT (32))); - emit_insn (gen_movdi (gen_rtx (REG, DImode, 65), scratch)); - emit_insn (gen_rtx_USE (VOIDmode, operands[0])); - DONE; - } - if (GET_CODE (operands[1]) == REG && REGNO (operands[1]) == HILO_REGNUM) - { - if (GET_CODE (operands[0]) == MEM) - { - rtx scratch, memword, offword, hiword, loword; - rtx addr = find_replacement (&XEXP (operands[0], 0)); - rtx op0 = change_address (operands[0], VOIDmode, addr); - - scratch = gen_rtx (REG, SImode, REGNO (operands[2])); - memword = change_address (op0, SImode, NULL_RTX); - offword = change_address (adj_offsettable_operand (op0, 4), - SImode, NULL_RTX); - if (BYTES_BIG_ENDIAN) - { - hiword = memword; - loword = offword; - } - else - { - hiword = offword; - loword = memword; - } - emit_move_insn (scratch, gen_rtx (REG, SImode, 64)); - emit_move_insn (hiword, scratch); - emit_move_insn (scratch, gen_rtx (REG, SImode, 65)); - emit_move_insn (loword, scratch); - emit_insn (gen_rtx_USE (VOIDmode, operands[1])); - } - else if (TARGET_MIPS16 && ! M16_REG_P (REGNO (operands[0]))) - { - /* Handle the case where operand[0] is not a 'd' register, - and hence we can not directly move from the HILO register - into it. */ - rtx scratch2 = gen_rtx_REG (DImode, REGNO (operands[2]) + 1); - emit_insn (gen_movdi (scratch, gen_rtx (REG, DImode, 65))); - emit_insn (gen_ashldi3 (scratch, scratch, GEN_INT (32))); - emit_insn (gen_lshrdi3 (scratch, scratch, GEN_INT (32))); - emit_insn (gen_movdi (scratch2, gen_rtx (REG, DImode, 64))); - emit_insn (gen_ashldi3 (scratch2, scratch2, GEN_INT (32))); - emit_insn (gen_iordi3 (scratch, scratch, scratch2)); - emit_insn (gen_movdi (operands[0], scratch)); - emit_insn (gen_rtx_USE (VOIDmode, operands[1])); - } - else - { - emit_insn (gen_movdi (scratch, gen_rtx (REG, DImode, 65))); - emit_insn (gen_ashldi3 (scratch, scratch, GEN_INT (32))); - emit_insn (gen_lshrdi3 (scratch, scratch, GEN_INT (32))); - emit_insn (gen_movdi (operands[0], gen_rtx (REG, DImode, 64))); - emit_insn (gen_ashldi3 (operands[0], operands[0], GEN_INT (32))); - emit_insn (gen_iordi3 (operands[0], operands[0], scratch)); - emit_insn (gen_rtx_USE (VOIDmode, operands[1])); - } - DONE; - } - /* This handles moves between a float register and HI/LO. */ - emit_move_insn (scratch, operands[1]); - emit_move_insn (operands[0], scratch); - DONE; -}") - -;; 32-bit Integer moves - -(define_split - [(set (match_operand:SI 0 "register_operand" "") - (match_operand:SI 1 "large_int" ""))] - "!TARGET_DEBUG_D_MODE && !TARGET_MIPS16" - [(set (match_dup 0) - (match_dup 2)) - (set (match_dup 0) - (ior:SI (match_dup 0) - (match_dup 3)))] - " -{ - operands[2] = GEN_INT (INTVAL (operands[1]) & 0xffff0000); - operands[3] = GEN_INT (INTVAL (operands[1]) & 0x0000ffff); -}") - -;; Unlike most other insns, the move insns can't be split with -;; different predicates, because register spilling and other parts of -;; the compiler, have memoized the insn number already. - -(define_expand "movsi" - [(set (match_operand:SI 0 "nonimmediate_operand" "") - (match_operand:SI 1 "general_operand" ""))] - "" - " -{ - if (mips_split_addresses && mips_check_split (operands[1], SImode)) - { - enum machine_mode mode = GET_MODE (operands[0]); - rtx tem = ((reload_in_progress | reload_completed) - ? operands[0] : gen_reg_rtx (mode)); - - emit_insn (gen_rtx (SET, VOIDmode, tem, - gen_rtx (HIGH, mode, operands[1]))); - - operands[1] = gen_rtx (LO_SUM, mode, tem, operands[1]); - } - - /* 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_rtx, - force_reg (SImode, temp)); - emit_move_insn (operands[0], force_reg (SImode, temp)); - DONE; - } - - /* If operands[1] is a constant address invalid for pic, then we need to - handle it just like LEGITIMIZE_ADDRESS does. */ - if (flag_pic && pic_address_needs_scratch (operands[1])) - { - rtx temp = force_reg (SImode, XEXP (XEXP (operands[1], 0), 0)); - rtx temp2 = XEXP (XEXP (operands[1], 0), 1); - - if (! SMALL_INT (temp2)) - temp2 = force_reg (SImode, temp2); - - emit_move_insn (operands[0], gen_rtx (PLUS, SImode, temp, temp2)); - DONE; - } - - /* On the mips16, we can handle a GP relative reference by adding in - $gp. We need to check the name to see whether this is a string - constant. */ - if (TARGET_MIPS16 - && register_operand (operands[0], SImode) - && GET_CODE (operands[1]) == SYMBOL_REF - && SYMBOL_REF_FLAG (operands[1])) - { - char *name = XSTR (operands[1], 0); - - if (name[0] != '*' - || strncmp (name + 1, LOCAL_LABEL_PREFIX, - sizeof LOCAL_LABEL_PREFIX - 1) != 0) - { - rtx base_reg; - - if (reload_in_progress || reload_completed) - { - /* We need to reload this address. In this case we - aren't going to have a chance to combine loading the - address with the load or store. That means that we - can either generate a 2 byte move followed by a 4 - byte addition, or a 2 byte load with a 4 byte entry - in the constant table. Since the entry in the - constant table might be shared, we're better off, on - average, loading the address from the constant table. */ - emit_move_insn (operands[0], - force_const_mem (SImode, operands[1])); - DONE; - } - - base_reg = gen_reg_rtx (Pmode); - emit_move_insn (base_reg, mips16_gp_pseudo_reg ()); - - emit_move_insn (operands[0], - gen_rtx (PLUS, Pmode, base_reg, - mips16_gp_offset (operands[1]))); - DONE; - } - } - - if ((reload_in_progress | reload_completed) == 0 - && !register_operand (operands[0], SImode) - && !register_operand (operands[1], SImode) - && (TARGET_MIPS16 - || GET_CODE (operands[1]) != CONST_INT - || INTVAL (operands[1]) != 0)) - { - rtx temp = force_reg (SImode, operands[1]); - emit_move_insn (operands[0], 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:SI 0 "memory_operand" "R,m") - (reg:SI 31))] - "TARGET_MIPS16" - "* -{ - operands[1] = gen_rtx (REG, SImode, 31); - return mips_move_1word (operands, insn, FALSE); -}" - [(set_attr "type" "store") - (set_attr "mode" "SI") - (set_attr "length" "1,2")]) - -;; The difference between these two is whether or not ints are allowed -;; in FP registers (off by default, use -mdebugh to enable). - -;; CYGNUS LOCAL law -(define_insn "movsi_internal1" - [(set (match_operand:SI 0 "nonimmediate_operand" "=d,d,d,d,d,d,R,m,*d,*f*z,*f,*f,*f,*R,*m,*x*w,*x*w,*d,*d") - (match_operand:SI 1 "move_operand" "d,S,IKL,Mnis,R,m,dJ,dJ,*f*z,*d,*f,*R,*m,*f,*f,J,*d,*x*w,*a*q"))] - "TARGET_DEBUG_H_MODE && !TARGET_MIPS16 - && (register_operand (operands[0], SImode) - || register_operand (operands[1], SImode) - || (GET_CODE (operands[1]) == CONST_INT && INTVAL (operands[1]) == 0))" - "* return mips_move_1word (operands, insn, FALSE);" - [(set_attr "type" "move,load,arith,arith,load,load,store,store,xfer,xfer,move,load,load,store,store,hilo,hilo,hilo,hilo") - (set_attr "mode" "SI") - (set_attr "length" "1,2,1,2,1,2,1,2,1,1,1,1,2,1,2,1,1,1,1")]) - -;; CYGNUS LOCAL law -(define_insn "movsi_internal2" - [(set (match_operand:SI 0 "nonimmediate_operand" "=d,d,d,d,d,d,R,m,*d,*z,*x*w,*d,*x*w,*d") - (match_operand:SI 1 "move_operand" "d,S,IKL,Mnis,R,m,dJ,dJ,*z,*d,J,*x*w,*d,*a*q"))] - "!TARGET_DEBUG_H_MODE && !TARGET_MIPS16 - && (register_operand (operands[0], SImode) - || register_operand (operands[1], SImode) - || (GET_CODE (operands[1]) == CONST_INT && INTVAL (operands[1]) == 0))" - "* return mips_move_1word (operands, insn, FALSE);" - [(set_attr "type" "move,load,arith,arith,load,load,store,store,xfer,xfer,hilo,hilo,hilo,hilo") - (set_attr "mode" "SI") - (set_attr "length" "1,2,1,2,1,2,1,2,1,1,1,1,1,1")]) - -;; This is the mips16 movsi instruction. We accept a small integer as -;; the source if the destination is a GP memory reference. This is -;; because we want the combine pass to turn adding a GP reference to a -;; register into a direct GP reference, but the combine pass will pass -;; in the source as a constant if it finds an equivalent one. If the -;; instruction is recognized, reload will force the constant back out -;; into a register. - -(define_insn "" - [(set (match_operand:SI 0 "nonimmediate_operand" "=d,y,d,d,d,d,d,d,d,R,m,*d,*d") - (match_operand:SI 1 "move_operand" "d,d,y,S,K,N,s,R,m,d,d,*x,*a"))] - "TARGET_MIPS16 - && (register_operand (operands[0], SImode) - || register_operand (operands[1], SImode) - || (GET_CODE (operands[0]) == MEM - && GET_CODE (XEXP (operands[0], 0)) == PLUS - && GET_CODE (XEXP (XEXP (operands[0], 0), 1)) == CONST - && mips16_gp_offset_p (XEXP (XEXP (operands[0], 0), 1)) - && GET_CODE (operands[1]) == CONST_INT - && (SMALL_INT (operands[1]) - || SMALL_INT_UNSIGNED (operands[1]))))" - "* return mips_move_1word (operands, insn, FALSE);" - [(set_attr "type" "move,move,move,load,arith,arith,arith,load,load,store,store,hilo,hilo") - (set_attr "mode" "SI") - (set_attr_alternative "length" - [(const_int 1) - (const_int 1) - (const_int 1) - (const_int 2) - (if_then_else (match_operand:VOID 1 "m16_uimm8_1" "") - (const_int 1) - (const_int 2)) - (if_then_else (match_operand:VOID 1 "m16_nuimm8_1" "") - (const_int 2) - (const_int 3)) - (if_then_else (match_operand:VOID 1 "m16_usym8_4" "") - (const_int 1) - (const_int 2)) - (const_int 1) - (const_int 2) - (const_int 1) - (const_int 2) - (const_int 1) - (const_int 1)])]) - -;; 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" "") - (mem:SI (plus:SI (match_dup 0) - (match_operand:SI 1 "const_int_operand" ""))))] - "TARGET_MIPS16 && reload_completed - && GET_CODE (operands[0]) == REG - && M16_REG_P (REGNO (operands[0])) - && GET_CODE (operands[1]) == CONST_INT - && ((INTVAL (operands[1]) < 0 - && INTVAL (operands[1]) >= -0x80) - || (INTVAL (operands[1]) >= 32 * 4 - && INTVAL (operands[1]) <= 31 * 4 + 0x7c) - || (INTVAL (operands[1]) >= 0 - && INTVAL (operands[1]) < 32 * 4 - && (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); - else if (val >= 32 * 4) - { - int off = val & 3; - - operands[1] = GEN_INT (0x7c + off); - operands[2] = GEN_INT (val - off - 0x7c); - } - else - { - int off = val & 3; - - 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" ""))] - "TARGET_MIPS16 && reload_completed - && GET_CODE (operands[0]) == REG - && M16_REG_P (REGNO (operands[0])) - && GET_CODE (operands[1]) == CONST_INT - && INTVAL (operands[1]) >= 0x100 - && 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_move_1word will generate anyhow. - -(define_split - [(set (match_operand:SI 0 "register_operand" "") - (match_operand:SI 1 "const_int_operand" ""))] - "TARGET_MIPS16 && reload_completed - && 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])); -}") - -;; Reload HILO_REGNUM in SI mode. This needs a scratch register in -;; order to set the sign bit correctly in the HI register. - -(define_expand "reload_outsi" - [(set (match_operand:SI 0 "general_operand" "=b") - (match_operand:SI 1 "register_operand" "b")) - (clobber (match_operand:SI 2 "register_operand" "=&d"))] - "TARGET_64BIT || TARGET_MIPS16" - " -{ - if (TARGET_64BIT - && GET_CODE (operands[0]) == REG && REGNO (operands[0]) == HILO_REGNUM) - { - emit_insn (gen_movsi (gen_rtx (REG, SImode, 65), operands[1])); - emit_insn (gen_ashrsi3 (operands[2], operands[1], GEN_INT (31))); - emit_insn (gen_movsi (gen_rtx (REG, SImode, 64), operands[2])); - emit_insn (gen_rtx_USE (VOIDmode, operands[0])); - DONE; - } - /* Use a mult to reload LO on mips16. ??? This is hideous. */ - if (TARGET_MIPS16 - && GET_CODE (operands[0]) == REG && REGNO (operands[0]) == LO_REGNUM) - { - emit_insn (gen_movsi (operands[2], GEN_INT (1))); - /* This is gen_mulsi3_internal, but we need to fill in the - scratch registers. */ - emit_insn (gen_rtx (PARALLEL, VOIDmode, - gen_rtvec (3, - gen_rtx (SET, VOIDmode, - operands[0], - gen_rtx (MULT, SImode, - operands[1], - operands[2])), - gen_rtx (CLOBBER, VOIDmode, - gen_rtx (REG, SImode, 64)), - gen_rtx (CLOBBER, VOIDmode, - gen_rtx (REG, SImode, 66))))); - DONE; - } - /* FIXME: I don't know how to get a value into the HI register. */ - if (GET_CODE (operands[0]) == REG - && (TARGET_MIPS16 ? M16_REG_P (REGNO (operands[0])) - : GP_REG_P (REGNO (operands[0])))) - { - emit_move_insn (operands[0], operands[1]); - DONE; - } - /* This handles moves between a float register and HI/LO. */ - emit_move_insn (operands[2], operands[1]); - emit_move_insn (operands[0], operands[2]); - DONE; -}") - -;; Reload a value into HI or LO. There is no mthi or mtlo on mips16, -;; so we use a mult. ??? This is hideous, and we ought to figure out -;; something better. - -;; We use no predicate for operand1, because it may be a PLUS, and there -;; is no convenient predicate for that. - -(define_expand "reload_insi" - [(set (match_operand:SI 0 "register_operand" "=b") - (match_operand:SI 1 "" "b")) - (clobber (match_operand:SI 2 "register_operand" "=&d"))] - "TARGET_MIPS16" - " -{ - if (TARGET_MIPS16 - && GET_CODE (operands[0]) == REG && REGNO (operands[0]) == LO_REGNUM) - { - emit_insn (gen_movsi (operands[2], GEN_INT (1))); - /* This is gen_mulsi3_internal, but we need to fill in the - scratch registers. */ - emit_insn (gen_rtx (PARALLEL, VOIDmode, - gen_rtvec (3, - gen_rtx (SET, VOIDmode, - operands[0], - gen_rtx (MULT, SImode, - operands[1], - operands[2])), - gen_rtx (CLOBBER, VOIDmode, - gen_rtx (REG, SImode, 64)), - gen_rtx (CLOBBER, VOIDmode, - gen_rtx (REG, SImode, 66))))); - DONE; - } - - /* If this is a plus, then this must be an add of the stack pointer against - either a hard register or a pseudo. */ - if (TARGET_MIPS16 && GET_CODE (operands[1]) == PLUS) - { - rtx plus_op; - - if (XEXP (operands[1], 0) == stack_pointer_rtx) - plus_op = XEXP (operands[1], 1); - else if (XEXP (operands[1], 1) == stack_pointer_rtx) - plus_op = XEXP (operands[1], 0); - else - abort (); - - /* We should have a register now. */ - if (GET_CODE (plus_op) != REG) - abort (); - - if (REGNO (plus_op) < FIRST_PSEUDO_REGISTER) - { - /* We have to have at least one temporary register which is not - overlapping plus_op. */ - if (! rtx_equal_p (plus_op, operands[0])) - { - emit_move_insn (operands[0], stack_pointer_rtx); - emit_insn (gen_addsi3 (operands[0], operands[0], plus_op)); - } - else if (! rtx_equal_p (plus_op, operands[2])) - { - emit_move_insn (operands[2], stack_pointer_rtx); - emit_insn (gen_addsi3 (operands[0], plus_op, operands[2])); - } - else - abort (); - } - else - { - /* We need two registers in this case. */ - if (! rtx_equal_p (operands[0], operands[2])) - { - emit_move_insn (operands[0], stack_pointer_rtx); - emit_move_insn (operands[2], plus_op); - emit_insn (gen_addsi3 (operands[0], operands[0], operands[2])); - } - else - abort (); - } - DONE; - } - - /* FIXME: I don't know how to get a value into the HI register. */ - emit_move_insn (operands[0], operands[1]); - DONE; -}") - -;; This insn handles moving CCmode values. It's really just a -;; slightly simplified copy of movsi_internal2, with additional cases -;; to move a condition register to a general register and to move -;; between the general registers and the floating point registers. - -(define_insn "movcc" - [(set (match_operand:CC 0 "nonimmediate_operand" "=d,*d,*d,*d,*R,*m,*d,*f,*f,*f,*f,*R,*m") - (match_operand:CC 1 "general_operand" "z,*d,*R,*m,*d,*d,*f,*d,*f,*R,*m,*f,*f"))] - "mips_isa >= 4 && TARGET_HARD_FLOAT" - "* return mips_move_1word (operands, insn, FALSE);" - [(set_attr "type" "move,move,load,load,store,store,xfer,xfer,move,load,load,store,store") - (set_attr "mode" "SI") - (set_attr "length" "2,1,1,2,1,2,1,1,1,1,2,1,2")]) - -;; Reload condition code registers. These need scratch registers. - -(define_expand "reload_incc" - [(set (match_operand:CC 0 "register_operand" "=z") - (match_operand:CC 1 "general_operand" "z")) - (clobber (match_operand:TF 2 "register_operand" "=&f"))] - "mips_isa >= 4 && TARGET_HARD_FLOAT" - " -{ - rtx source; - rtx fp1, fp2; - - /* This is called when are copying some value into a condition code - register. Operand 0 is the condition code register. Operand 1 - is the source. Operand 2 is a scratch register; we use TFmode - because we actually need two floating point registers. */ - if (! ST_REG_P (true_regnum (operands[0])) - || ! FP_REG_P (true_regnum (operands[2]))) - abort (); - - /* We need to get the source in SFmode so that the insn is - recognized. */ - if (GET_CODE (operands[1]) == MEM) - source = change_address (operands[1], SFmode, NULL_RTX); - else if (GET_CODE (operands[1]) == REG || GET_CODE (operands[1]) == SUBREG) - source = gen_rtx (REG, SFmode, true_regnum (operands[1])); - else - source = operands[1]; - - fp1 = gen_rtx (REG, SFmode, REGNO (operands[2])); - fp2 = gen_rtx (REG, SFmode, REGNO (operands[2]) + 1); - - emit_insn (gen_move_insn (fp1, source)); - emit_insn (gen_move_insn (fp2, gen_rtx (REG, SFmode, 0))); - emit_insn (gen_rtx (SET, VOIDmode, operands[0], - gen_rtx (LT, CCmode, fp2, fp1))); - - DONE; -}") - -(define_expand "reload_outcc" - [(set (match_operand:CC 0 "general_operand" "=z") - (match_operand:CC 1 "register_operand" "z")) - (clobber (match_operand:CC 2 "register_operand" "=&d"))] - "mips_isa >= 4 && TARGET_HARD_FLOAT" - " -{ - /* This is called when we are copying a condition code register out - to save it somewhere. Operand 0 should be the location we are - going to save it to. Operand 1 should be the condition code - register. Operand 2 should be a scratch general purpose register - created for us by reload. The mips_secondary_reload_class - function should have told reload that we don't need a scratch - register if the destination is a general purpose register anyhow. */ - if (ST_REG_P (true_regnum (operands[0])) - || GP_REG_P (true_regnum (operands[0])) - || ! ST_REG_P (true_regnum (operands[1])) - || ! GP_REG_P (true_regnum (operands[2]))) - abort (); - - /* All we have to do is copy the value from the condition code to - the data register, which movcc can handle, and then store the - value into the real final destination. */ - emit_insn (gen_move_insn (operands[2], operands[1])); - emit_insn (gen_move_insn (operands[0], 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 -;; these four instructions: one where the two general registers are -;; SImode, and one where they are DImode. This is because general -;; registers will be in SImode when they hold 32 bit values, but, -;; since the 32 bit values are always sign extended, the [ls][wd]xc1 -;; instructions will still work correctly. - -;; ??? Perhaps it would be better to support these instructions by -;; modifying GO_IF_LEGITIMATE_ADDRESS and friends. However, since -;; these instructions can only be used to load and store floating -;; point registers, that would probably cause trouble in reload. - -(define_insn "" - [(set (match_operand:SF 0 "register_operand" "=f") - (mem:SF (plus:SI (match_operand:SI 1 "register_operand" "d") - (match_operand:SI 2 "register_operand" "d"))))] - "mips_isa >= 4 && TARGET_HARD_FLOAT" - "lwxc1\\t%0,%1(%2)" - [(set_attr "type" "load") - (set_attr "mode" "SF") - (set_attr "length" "1")]) - -(define_insn "" - [(set (match_operand:SF 0 "register_operand" "=f") - (mem:SF (plus:DI (match_operand:DI 1 "se_register_operand" "d") - (match_operand:DI 2 "se_register_operand" "d"))))] - "mips_isa >= 4 && TARGET_HARD_FLOAT" - "lwxc1\\t%0,%1(%2)" - [(set_attr "type" "load") - (set_attr "mode" "SF") - (set_attr "length" "1")]) - -(define_insn "" - [(set (match_operand:DF 0 "register_operand" "=f") - (mem:DF (plus:SI (match_operand:SI 1 "register_operand" "d") - (match_operand:SI 2 "register_operand" "d"))))] - "mips_isa >= 4 && TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT" - "ldxc1\\t%0,%1(%2)" - [(set_attr "type" "load") - (set_attr "mode" "DF") - (set_attr "length" "1")]) - -(define_insn "" - [(set (match_operand:DF 0 "register_operand" "=f") - (mem:DF (plus:DI (match_operand:DI 1 "se_register_operand" "d") - (match_operand:DI 2 "se_register_operand" "d"))))] - "mips_isa >= 4 && TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT" - "ldxc1\\t%0,%1(%2)" - [(set_attr "type" "load") - (set_attr "mode" "DF") - (set_attr "length" "1")]) - -(define_insn "" - [(set (mem:SF (plus:SI (match_operand:SI 1 "register_operand" "d") - (match_operand:SI 2 "register_operand" "d"))) - (match_operand:SF 0 "register_operand" "=f"))] - "mips_isa >= 4 && TARGET_HARD_FLOAT" - "swxc1\\t%0,%1(%2)" - [(set_attr "type" "store") - (set_attr "mode" "SF") - (set_attr "length" "1")]) - -(define_insn "" - [(set (mem:SF (plus:DI (match_operand:DI 1 "se_register_operand" "d") - (match_operand:DI 2 "se_register_operand" "d"))) - (match_operand:SF 0 "register_operand" "=f"))] - "mips_isa >= 4 && TARGET_HARD_FLOAT" - "swxc1\\t%0,%1(%2)" - [(set_attr "type" "store") - (set_attr "mode" "SF") - (set_attr "length" "1")]) - -(define_insn "" - [(set (mem:DF (plus:SI (match_operand:SI 1 "register_operand" "d") - (match_operand:SI 2 "register_operand" "d"))) - (match_operand:DF 0 "register_operand" "=f"))] - "mips_isa >= 4 && TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT" - "sdxc1\\t%0,%1(%2)" - [(set_attr "type" "store") - (set_attr "mode" "DF") - (set_attr "length" "1")]) - -(define_insn "" - [(set (mem:DF (plus:DI (match_operand:DI 1 "se_register_operand" "d") - (match_operand:DI 2 "se_register_operand" "d"))) - (match_operand:DF 0 "register_operand" "=f"))] - "mips_isa >= 4 && TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT" - "sdxc1\\t%0,%1(%2)" - [(set_attr "type" "store") - (set_attr "mode" "DF") - (set_attr "length" "1")]) - -;; 16-bit Integer moves - -;; Unlike most other insns, the move insns can't be split with -;; different predicates, because register spilling and other parts of -;; the compiler, have memoized the insn number already. -;; Unsigned loads are used because BYTE_LOADS_ZERO_EXTEND is defined - -(define_expand "movhi" - [(set (match_operand:HI 0 "nonimmediate_operand" "") - (match_operand:HI 1 "general_operand" ""))] - "" - " -{ - 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). - -(define_insn "movhi_internal1" - [(set (match_operand:HI 0 "nonimmediate_operand" "=d,d,d,d,R,m,*d,*f,*f*z,*x,*d") - (match_operand:HI 1 "general_operand" "d,IK,R,m,dJ,dJ,*f*z,*d,*f,*d,*x"))] - "TARGET_DEBUG_H_MODE && !TARGET_MIPS16 - && (register_operand (operands[0], HImode) - || register_operand (operands[1], HImode) - || (GET_CODE (operands[1]) == CONST_INT && INTVAL (operands[1]) == 0))" - "* return mips_move_1word (operands, insn, TRUE);" - [(set_attr "type" "move,arith,load,load,store,store,xfer,xfer,move,hilo,hilo") - (set_attr "mode" "HI") - (set_attr "length" "1,1,1,2,1,2,1,1,1,1,1")]) - -(define_insn "movhi_internal2" - [(set (match_operand:HI 0 "nonimmediate_operand" "=d,d,d,d,R,m,*d,*z,*x,*d") - (match_operand:HI 1 "general_operand" "d,IK,R,m,dJ,dJ,*z,*d,*d,*x"))] - "!TARGET_DEBUG_H_MODE && !TARGET_MIPS16 - && (register_operand (operands[0], HImode) - || register_operand (operands[1], HImode) - || (GET_CODE (operands[1]) == CONST_INT && INTVAL (operands[1]) == 0))" - "* return mips_move_1word (operands, insn, TRUE);" - [(set_attr "type" "move,arith,load,load,store,store,xfer,xfer,hilo,hilo") - (set_attr "mode" "HI") - (set_attr "length" "1,1,1,2,1,2,1,1,1,1")]) - -(define_insn "" - [(set (match_operand:HI 0 "nonimmediate_operand" "=d,y,d,d,d,d,d,R,m,*d") - (match_operand:HI 1 "general_operand" "d,d,y,K,N,R,m,d,d,*x"))] - "TARGET_MIPS16 - && (register_operand (operands[0], HImode) - || register_operand (operands[1], HImode))" - "* return mips_move_1word (operands, insn, TRUE);" - [(set_attr "type" "move,move,move,arith,arith,load,load,store,store,hilo") - (set_attr "mode" "HI") - (set_attr_alternative "length" - [(const_int 1) - (const_int 1) - (const_int 1) - (if_then_else (match_operand:VOID 1 "m16_uimm8_1" "") - (const_int 1) - (const_int 2)) - (if_then_else (match_operand:VOID 1 "m16_nuimm8_1" "") - (const_int 2) - (const_int 3)) - (const_int 1) - (const_int 2) - (const_int 1) - (const_int 2) - (const_int 1)])]) - - -;; On the mips16, we can split lh $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:HI 0 "register_operand" "") - (mem:HI (plus:SI (match_dup 0) - (match_operand:SI 1 "const_int_operand" ""))))] - "TARGET_MIPS16 && reload_completed - && GET_CODE (operands[0]) == REG - && M16_REG_P (REGNO (operands[0])) - && GET_CODE (operands[1]) == CONST_INT - && ((INTVAL (operands[1]) < 0 - && INTVAL (operands[1]) >= -0x80) - || (INTVAL (operands[1]) >= 32 * 2 - && INTVAL (operands[1]) <= 31 * 2 + 0x7e) - || (INTVAL (operands[1]) >= 0 - && INTVAL (operands[1]) < 32 * 2 - && (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); - else if (val >= 32 * 2) - { - int off = val & 1; - - operands[1] = GEN_INT (0x7e + off); - operands[2] = GEN_INT (val - off - 0x7e); - } - else - { - int off = val & 1; - - 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 - -(define_expand "movqi" - [(set (match_operand:QI 0 "nonimmediate_operand" "") - (match_operand:QI 1 "general_operand" ""))] - "" - " -{ - 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; - } -}") - -;; 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_internal1" - [(set (match_operand:QI 0 "nonimmediate_operand" "=d,d,d,d,R,m,*d,*f*z,*f,*x,*d") - (match_operand:QI 1 "general_operand" "d,IK,R,m,dJ,dJ,*f*z,*d,*f,*d,*x"))] - "TARGET_DEBUG_H_MODE && !TARGET_MIPS16 - && (register_operand (operands[0], QImode) - || register_operand (operands[1], QImode) - || (GET_CODE (operands[1]) == CONST_INT && INTVAL (operands[1]) == 0))" - "* return mips_move_1word (operands, insn, TRUE);" - [(set_attr "type" "move,arith,load,load,store,store,xfer,xfer,move,hilo,hilo") - (set_attr "mode" "QI") - (set_attr "length" "1,1,1,2,1,2,1,1,1,1,1")]) - -(define_insn "movqi_internal2" - [(set (match_operand:QI 0 "nonimmediate_operand" "=d,d,d,d,R,m,*d,*z,*x,*d") - (match_operand:QI 1 "general_operand" "d,IK,R,m,dJ,dJ,*z,*d,*d,*x"))] - "!TARGET_DEBUG_H_MODE && !TARGET_MIPS16 - && (register_operand (operands[0], QImode) - || register_operand (operands[1], QImode) - || (GET_CODE (operands[1]) == CONST_INT && INTVAL (operands[1]) == 0))" - "* return mips_move_1word (operands, insn, TRUE);" - [(set_attr "type" "move,arith,load,load,store,store,xfer,xfer,hilo,hilo") - (set_attr "mode" "QI") - (set_attr "length" "1,1,1,2,1,2,1,1,1,1")]) - -(define_insn "" - [(set (match_operand:QI 0 "nonimmediate_operand" "=d,y,d,d,d,d,d,R,m,*d") - (match_operand:QI 1 "general_operand" "d,d,y,K,N,R,m,d,d,*x"))] - "TARGET_MIPS16 - && (register_operand (operands[0], QImode) - || register_operand (operands[1], QImode))" - "* return mips_move_1word (operands, insn, TRUE);" - [(set_attr "type" "move,move,move,arith,arith,load,load,store,store,hilo") - (set_attr "mode" "QI") - (set_attr_alternative "length" - [(const_int 1) - (const_int 1) - (const_int 1) - (if_then_else (match_operand:VOID 1 "m16_uimm8_1" "") - (const_int 1) - (const_int 2)) - (if_then_else (match_operand:VOID 1 "m16_nuimm8_1" "") - (const_int 2) - (const_int 3)) - (const_int 1) - (const_int 2) - (const_int 1) - (const_int 2) - (const_int 1)])]) - - -;; 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" "") - (mem:QI (plus:SI (match_dup 0) - (match_operand:SI 1 "const_int_operand" ""))))] - "TARGET_MIPS16 && reload_completed - && GET_CODE (operands[0]) == REG - && M16_REG_P (REGNO (operands[0])) - && GET_CODE (operands[1]) == CONST_INT - && ((INTVAL (operands[1]) < 0 - && INTVAL (operands[1]) >= -0x80) - || (INTVAL (operands[1]) >= 32 - && 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); - 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" ""))] - "" - " -{ - if ((reload_in_progress | reload_completed) == 0 - && !register_operand (operands[0], SFmode) - && !register_operand (operands[1], SFmode) - && (TARGET_MIPS16 - || ((GET_CODE (operands[1]) != CONST_INT || INTVAL (operands[1]) != 0) - && operands[1] != CONST0_RTX (SFmode)))) - { - rtx temp = force_reg (SFmode, operands[1]); - emit_move_insn (operands[0], temp); - DONE; - } -}") - -(define_insn "movsf_internal1" - [(set (match_operand:SF 0 "nonimmediate_operand" "=f,f,f,f,R,m,*f,*d,*d,*d,*d,*R,*m") - (match_operand:SF 1 "general_operand" "f,G,R,Fm,fG,fG,*d,*f,*G*d,*R,*F*m,*d,*d"))] - "TARGET_HARD_FLOAT - && (register_operand (operands[0], SFmode) - || register_operand (operands[1], SFmode) - || (GET_CODE (operands[1]) == CONST_INT && INTVAL (operands[1]) == 0) - || operands[1] == CONST0_RTX (SFmode))" - "* return mips_move_1word (operands, insn, FALSE);" - [(set_attr "type" "move,xfer,load,load,store,store,xfer,xfer,move,load,load,store,store") - (set_attr "mode" "SF") - (set_attr "length" "1,1,1,2,1,2,1,1,1,1,2,1,2")]) - - -(define_insn "movsf_internal2" - [(set (match_operand:SF 0 "nonimmediate_operand" "=d,d,d,R,m") - (match_operand:SF 1 "general_operand" " Gd,R,Fm,d,d"))] - "TARGET_SOFT_FLOAT && !TARGET_MIPS16 - && (register_operand (operands[0], SFmode) - || register_operand (operands[1], SFmode) - || (GET_CODE (operands[1]) == CONST_INT && INTVAL (operands[1]) == 0) - || operands[1] == CONST0_RTX (SFmode))" - "* return mips_move_1word (operands, insn, FALSE);" - [(set_attr "type" "move,load,load,store,store") - (set_attr "mode" "SF") - (set_attr "length" "1,1,2,1,2")]) - -(define_insn "" - [(set (match_operand:SF 0 "nonimmediate_operand" "=d,y,d,d,d,R,m") - (match_operand:SF 1 "general_operand" "d,d,y,R,Fm,d,d"))] - "TARGET_MIPS16 - && (register_operand (operands[0], SFmode) - || register_operand (operands[1], SFmode))" - "* return mips_move_1word (operands, insn, FALSE);" - [(set_attr "type" "move,move,move,load,load,store,store") - (set_attr "mode" "SF") - (set_attr "length" "1,1,1,1,2,1,2")]) - - -;; 64-bit floating point moves - -(define_expand "movdf" - [(set (match_operand:DF 0 "nonimmediate_operand" "") - (match_operand:DF 1 "general_operand" ""))] - "" - " -{ - if ((reload_in_progress | reload_completed) == 0 - && !register_operand (operands[0], DFmode) - && !register_operand (operands[1], DFmode) - && (TARGET_MIPS16 - || ((GET_CODE (operands[1]) != CONST_INT || INTVAL (operands[1]) != 0) - && operands[1] != CONST0_RTX (DFmode)))) - { - rtx temp = force_reg (DFmode, operands[1]); - emit_move_insn (operands[0], temp); - DONE; - } -}") - -(define_insn "movdf_internal1" - [(set (match_operand:DF 0 "nonimmediate_operand" "=f,f,f,R,To,f,*f,*d,*d,*d,*d,*R,*T") - (match_operand:DF 1 "general_operand" "f,R,To,fG,fG,F,*d,*f,*d*G,*R,*T*F,*d,*d"))] - "TARGET_HARD_FLOAT && !(TARGET_FLOAT64 && !TARGET_64BIT) - && TARGET_DOUBLE_FLOAT - && (register_operand (operands[0], DFmode) - || register_operand (operands[1], DFmode) - || (GET_CODE (operands[1]) == CONST_INT && INTVAL (operands[1]) == 0) - || operands[1] == CONST0_RTX (DFmode))" - "* return mips_move_2words (operands, insn); " - [(set_attr "type" "move,load,load,store,store,load,xfer,xfer,move,load,load,store,store") - (set_attr "mode" "DF") - (set_attr "length" "1,2,4,2,4,4,2,2,2,2,4,2,4")]) - -(define_insn "movdf_internal1a" - [(set (match_operand:DF 0 "nonimmediate_operand" "=f,f,R,R,To,To,f,*d,*d,*d,*To,*R") - (match_operand:DF 1 "general_operand" " f,To,f,G,f,G,F,*F,*To,*R,*d,*d"))] - "TARGET_HARD_FLOAT && (TARGET_FLOAT64 && !TARGET_64BIT) - && TARGET_DOUBLE_FLOAT - && (register_operand (operands[0], DFmode) - || register_operand (operands[1], DFmode) - || (GET_CODE (operands [0]) == MEM - && ((GET_CODE (operands[1]) == CONST_INT - && INTVAL (operands[1]) == 0) - || operands[1] == CONST0_RTX (DFmode))))" - "* return mips_move_2words (operands, insn); " - [(set_attr "type" "move,load,store,store,store,store,load,load,load,load,store,store") - (set_attr "mode" "DF") - (set_attr "length" "1,2,1,1,2,2,2,2,2,1,2,1")]) - -(define_insn "movdf_internal2" - [(set (match_operand:DF 0 "nonimmediate_operand" "=d,d,d,R,To") - (match_operand:DF 1 "general_operand" "dG,R,ToF,d,d"))] - "(TARGET_SOFT_FLOAT || TARGET_SINGLE_FLOAT) && !TARGET_MIPS16 - && (register_operand (operands[0], DFmode) - || register_operand (operands[1], DFmode) - || (GET_CODE (operands[1]) == CONST_INT && INTVAL (operands[1]) == 0) - || operands[1] == CONST0_RTX (DFmode))" - "* return mips_move_2words (operands, insn); " - [(set_attr "type" "move,load,load,store,store") - (set_attr "mode" "DF") - (set_attr "length" "2,2,4,2,4")]) - -(define_insn "" - [(set (match_operand:DF 0 "nonimmediate_operand" "=d,y,d,d,d,R,To") - (match_operand:DF 1 "general_operand" "d,d,y,R,ToF,d,d"))] - "TARGET_MIPS16 - && (register_operand (operands[0], DFmode) - || register_operand (operands[1], DFmode))" - "* return mips_move_2words (operands, insn);" - [(set_attr "type" "move,move,move,load,load,store,store") - (set_attr "mode" "DF") - (set_attr "length" "2,2,2,2,4,2,4")]) - -(define_split - [(set (match_operand:DF 0 "register_operand" "") - (match_operand:DF 1 "register_operand" ""))] - "reload_completed && !TARGET_64BIT && !TARGET_DEBUG_D_MODE && !TARGET_DEBUG_G_MODE - && GET_CODE (operands[0]) == REG && GP_REG_P (REGNO (operands[0])) - && GET_CODE (operands[1]) == REG && GP_REG_P (REGNO (operands[1]))" - [(set (subreg:SI (match_dup 0) 0) (subreg:SI (match_dup 1) 0)) - (set (subreg:SI (match_dup 0) 1) (subreg:SI (match_dup 1) 1))] - "") - -;; Instructions to load the global pointer register. -;; This is volatile to make sure that the scheduler won't move any symbol_ref -;; uses in front of it. All symbol_refs implicitly use the gp reg. - -(define_insn "loadgp" - [(set (reg:DI 28) - (unspec_volatile:DI [(match_operand:DI 0 "address_operand" "") - (match_operand:DI 1 "register_operand" "")] 2)) - (clobber (reg:DI 1))] - "" - "%[lui\\t$1,%%hi(%%neg(%%gp_rel(%a0)))\\n\\taddiu\\t$1,$1,%%lo(%%neg(%%gp_rel(%a0)))\\n\\tdaddu\\t$gp,$1,%1%]" - [(set_attr "type" "move") - (set_attr "mode" "DI") - (set_attr "length" "3")]) - -;; Block moves, see mips.c for more details. -;; Argument 0 is the destination -;; Argument 1 is the source -;; Argument 2 is the length -;; Argument 3 is the alignment - -(define_expand "movstrsi" - [(parallel [(set (match_operand:BLK 0 "general_operand" "") - (match_operand:BLK 1 "general_operand" "")) - (use (match_operand:SI 2 "arith32_operand" "")) - (use (match_operand:SI 3 "immediate_operand" ""))])] - "!TARGET_MIPS16" - " -{ - if (operands[0]) /* avoid unused code messages */ - { - expand_block_move (operands); - DONE; - } -}") - -;; Insn generated by block moves - -(define_insn "movstrsi_internal" - [(set (match_operand:BLK 0 "memory_operand" "=o") ;; destination - (match_operand:BLK 1 "memory_operand" "o")) ;; source - (clobber (match_scratch:SI 4 "=&d")) ;; temp 1 - (clobber (match_scratch:SI 5 "=&d")) ;; temp 2 - (clobber (match_scratch:SI 6 "=&d")) ;; temp 3 - (clobber (match_scratch:SI 7 "=&d")) ;; temp 4 - (use (match_operand:SI 2 "small_int" "I")) ;; # bytes to move - (use (match_operand:SI 3 "small_int" "I")) ;; alignment - (use (const_int 0))] ;; normal block move - "" - "* return output_block_move (insn, operands, 4, BLOCK_MOVE_NORMAL);" - [(set_attr "type" "store") - (set_attr "mode" "none") - (set_attr "length" "20")]) - -;; We need mips16 versions, because an offset from the stack pointer -;; is not offsettable, since the stack pointer can only handle 4 and 8 -;; byte loads. - -(define_insn "" - [(set (match_operand:BLK 0 "memory_operand" "=d") ;; destination - (match_operand:BLK 1 "memory_operand" "d")) ;; source - (clobber (match_scratch:SI 4 "=&d")) ;; temp 1 - (clobber (match_scratch:SI 5 "=&d")) ;; temp 2 - (clobber (match_scratch:SI 6 "=&d")) ;; temp 3 - (clobber (match_scratch:SI 7 "=&d")) ;; temp 4 - (use (match_operand:SI 2 "small_int" "I")) ;; # bytes to move - (use (match_operand:SI 3 "small_int" "I")) ;; alignment - (use (const_int 0))] ;; normal block move - "TARGET_MIPS16" - "* return output_block_move (insn, operands, 4, BLOCK_MOVE_NORMAL);" - [(set_attr "type" "multi") - (set_attr "mode" "none") - (set_attr "length" "20")]) - -(define_insn "" - [(set (match_operand:BLK 0 "memory_operand" "=d") ;; destination - (match_operand:BLK 1 "memory_operand" "o")) ;; source - (clobber (match_scratch:SI 4 "=&d")) ;; temp 1 - (clobber (match_scratch:SI 5 "=&d")) ;; temp 2 - (clobber (match_scratch:SI 6 "=&d")) ;; temp 3 - (clobber (match_scratch:SI 7 "=&d")) ;; temp 4 - (use (match_operand:SI 2 "small_int" "I")) ;; # bytes to move - (use (match_operand:SI 3 "small_int" "I")) ;; alignment - (use (const_int 0))] ;; normal block move - "TARGET_MIPS16" - "* return output_block_move (insn, operands, 4, BLOCK_MOVE_NORMAL);" - [(set_attr "type" "multi") - (set_attr "mode" "none") - (set_attr "length" "20")]) - -(define_insn "" - [(set (match_operand:BLK 0 "memory_operand" "=o") ;; destination - (match_operand:BLK 1 "memory_operand" "d")) ;; source - (clobber (match_scratch:SI 4 "=&d")) ;; temp 1 - (clobber (match_scratch:SI 5 "=&d")) ;; temp 2 - (clobber (match_scratch:SI 6 "=&d")) ;; temp 3 - (clobber (match_scratch:SI 7 "=&d")) ;; temp 4 - (use (match_operand:SI 2 "small_int" "I")) ;; # bytes to move - (use (match_operand:SI 3 "small_int" "I")) ;; alignment - (use (const_int 0))] ;; normal block move - "TARGET_MIPS16" - "* return output_block_move (insn, operands, 4, BLOCK_MOVE_NORMAL);" - [(set_attr "type" "multi") - (set_attr "mode" "none") - (set_attr "length" "20")]) - -;; Split a block move into 2 parts, the first part is everything -;; except for the last move, and the second part is just the last -;; store, which is exactly 1 instruction (ie, not a usw), so it can -;; fill a delay slot. This also prevents a bug in delayed branches -;; from showing up, which reuses one of the registers in our clobbers. - -(define_split - [(set (mem:BLK (match_operand:SI 0 "register_operand" "")) - (mem:BLK (match_operand:SI 1 "register_operand" ""))) - (clobber (match_operand:SI 4 "register_operand" "")) - (clobber (match_operand:SI 5 "register_operand" "")) - (clobber (match_operand:SI 6 "register_operand" "")) - (clobber (match_operand:SI 7 "register_operand" "")) - (use (match_operand:SI 2 "small_int" "")) - (use (match_operand:SI 3 "small_int" "")) - (use (const_int 0))] - - "reload_completed && !TARGET_DEBUG_D_MODE && INTVAL (operands[2]) > 0" - - ;; All but the last move - [(parallel [(set (mem:BLK (match_dup 0)) - (mem:BLK (match_dup 1))) - (clobber (match_dup 4)) - (clobber (match_dup 5)) - (clobber (match_dup 6)) - (clobber (match_dup 7)) - (use (match_dup 2)) - (use (match_dup 3)) - (use (const_int 1))]) - - ;; The last store, so it can fill a delay slot - (parallel [(set (mem:BLK (match_dup 0)) - (mem:BLK (match_dup 1))) - (clobber (match_dup 4)) - (clobber (match_dup 5)) - (clobber (match_dup 6)) - (clobber (match_dup 7)) - (use (match_dup 2)) - (use (match_dup 3)) - (use (const_int 2))])] - - "") - -(define_insn "movstrsi_internal2" - [(set (match_operand:BLK 0 "memory_operand" "=o") ;; destination - (match_operand:BLK 1 "memory_operand" "o")) ;; source - (clobber (match_scratch:SI 4 "=&d")) ;; temp 1 - (clobber (match_scratch:SI 5 "=&d")) ;; temp 2 - (clobber (match_scratch:SI 6 "=&d")) ;; temp 3 - (clobber (match_scratch:SI 7 "=&d")) ;; temp 4 - (use (match_operand:SI 2 "small_int" "I")) ;; # bytes to move - (use (match_operand:SI 3 "small_int" "I")) ;; alignment - (use (const_int 1))] ;; all but last store - "" - "* return output_block_move (insn, operands, 4, BLOCK_MOVE_NOT_LAST);" - [(set_attr "type" "store") - (set_attr "mode" "none") - (set_attr "length" "20")]) - -(define_insn "" - [(set (match_operand:BLK 0 "memory_operand" "=d") ;; destination - (match_operand:BLK 1 "memory_operand" "d")) ;; source - (clobber (match_scratch:SI 4 "=&d")) ;; temp 1 - (clobber (match_scratch:SI 5 "=&d")) ;; temp 2 - (clobber (match_scratch:SI 6 "=&d")) ;; temp 3 - (clobber (match_scratch:SI 7 "=&d")) ;; temp 4 - (use (match_operand:SI 2 "small_int" "I")) ;; # bytes to move - (use (match_operand:SI 3 "small_int" "I")) ;; alignment - (use (const_int 1))] ;; all but last store - "TARGET_MIPS16" - "* return output_block_move (insn, operands, 4, BLOCK_MOVE_NOT_LAST);" - [(set_attr "type" "multi") - (set_attr "mode" "none") - (set_attr "length" "20")]) - -(define_insn "movstrsi_internal3" - [(set (match_operand:BLK 0 "memory_operand" "=Ro") ;; destination - (match_operand:BLK 1 "memory_operand" "Ro")) ;; source - (clobber (match_scratch:SI 4 "=&d")) ;; temp 1 - (clobber (match_scratch:SI 5 "=&d")) ;; temp 2 - (clobber (match_scratch:SI 6 "=&d")) ;; temp 3 - (clobber (match_scratch:SI 7 "=&d")) ;; temp 4 - (use (match_operand:SI 2 "small_int" "I")) ;; # bytes to move - (use (match_operand:SI 3 "small_int" "I")) ;; alignment - (use (const_int 2))] ;; just last store of block move - "" - "* return output_block_move (insn, operands, 4, BLOCK_MOVE_LAST);" - [(set_attr "type" "store") - (set_attr "mode" "none") - (set_attr "length" "1")]) - -(define_insn "" - [(set (match_operand:BLK 0 "memory_operand" "=d") ;; destination - (match_operand:BLK 1 "memory_operand" "d")) ;; source - (clobber (match_scratch:SI 4 "=&d")) ;; temp 1 - (clobber (match_scratch:SI 5 "=&d")) ;; temp 2 - (clobber (match_scratch:SI 6 "=&d")) ;; temp 3 - (clobber (match_scratch:SI 7 "=&d")) ;; temp 4 - (use (match_operand:SI 2 "small_int" "I")) ;; # bytes to move - (use (match_operand:SI 3 "small_int" "I")) ;; alignment - (use (const_int 2))] ;; just last store of block move - "TARGET_MIPS16" - "* return output_block_move (insn, operands, 4, BLOCK_MOVE_LAST);" - [(set_attr "type" "store") - (set_attr "mode" "none") - (set_attr "length" "1")]) - - -;; .................... -;; SHIFTS -;; .................... - -;; Many of these instructions uses 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")))] - "" - " -{ - /* 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 (SImode); - - emit_insn (gen_ashlsi3_internal2 (temp, operands[1], GEN_INT (8))); - emit_insn (gen_ashlsi3_internal2 (operands[0], temp, - 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") - (set_attr "mode" "SI") - (set_attr "length" "1")]) - -(define_insn "ashlsi3_internal2" - [(set (match_operand:SI 0 "register_operand" "=d,d") - (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\"; - - 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") - (set_attr "mode" "SI") - (set_attr_alternative "length" - [(const_int 1) - (if_then_else (match_operand:VOID 2 "m16_uimm3_b" "") - (const_int 1) - (const_int 2))])]) - -;; 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" "")))] - "TARGET_MIPS16 - && reload_completed - && 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); -}") - -(define_expand "ashldi3" - [(parallel [(set (match_operand:DI 0 "register_operand" "") - (ashift:DI (match_operand:DI 1 "se_register_operand" "") - (match_operand:SI 2 "arith_operand" ""))) - (clobber (match_dup 3))])] - "TARGET_64BIT || (!TARGET_DEBUG_G_MODE && !TARGET_MIPS16)" - " -{ - 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) - { - 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])); - 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; - dslots_jump_total += 3; - dslots_jump_filled += 2; - - return \"sll\\t%3,%2,26\\n\\ -\\tbgez\\t%3,1f\\n\\ -\\tsll\\t%M0,%L1,%2\\n\\ -\\t%(b\\t3f\\n\\ -\\tmove\\t%L0,%z4%)\\n\\ -\\n\\ -1:\\n\\ -\\t%(beq\\t%3,%z4,2f\\n\\ -\\tsll\\t%M0,%M1,%2%)\\n\\ -\\n\\ -\\tsubu\\t%3,%z4,%2\\n\\ -\\tsrl\\t%3,%L1,%3\\n\\ -\\tor\\t%M0,%M0,%3\\n\\ -2:\\n\\ -\\tsll\\t%L0,%L1,%2\\n\\ -3:\"; -}" - [(set_attr "type" "darith") - (set_attr "mode" "SI") - (set_attr "length" "12")]) - - -(define_insn "ashldi3_internal2" - [(set (match_operand:DI 0 "register_operand" "=d") - (ashift:DI (match_operand:DI 1 "register_operand" "d") - (match_operand:SI 2 "small_int" "IJK"))) - (clobber (match_operand:SI 3 "register_operand" "=d"))] - "!TARGET_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" "2")]) - - -(define_split - [(set (match_operand:DI 0 "register_operand" "") - (ashift:DI (match_operand:DI 1 "register_operand" "") - (match_operand:SI 2 "small_int" ""))) - (clobber (match_operand:SI 3 "register_operand" ""))] - "reload_completed && !WORDS_BIG_ENDIAN && !TARGET_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) 1) (ashift:SI (subreg:SI (match_dup 1) 0) (match_dup 2))) - (set (subreg:SI (match_dup 0) 0) (const_int 0))] - - "operands[2] = GEN_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) 1) (match_dup 2))) - (set (subreg:SI (match_dup 0) 1) (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" "4")]) - - -(define_split - [(set (match_operand:DI 0 "register_operand" "") - (ashift:DI (match_operand:DI 1 "register_operand" "") - (match_operand:SI 2 "small_int" ""))) - (clobber (match_operand:SI 3 "register_operand" ""))] - "reload_completed && !WORDS_BIG_ENDIAN && !TARGET_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) 1) - (ashift:SI (subreg:SI (match_dup 1) 1) - (match_dup 2))) - - (set (match_dup 3) - (lshiftrt:SI (subreg:SI (match_dup 1) 0) - (match_dup 4))) - - (set (subreg:SI (match_dup 0) 1) - (ior:SI (subreg:SI (match_dup 0) 1) - (match_dup 3))) - - (set (subreg:SI (match_dup 0) 0) - (ashift:SI (subreg:SI (match_dup 1) 0) - (match_dup 2)))] - " -{ - int amount = INTVAL (operands[2]); - operands[2] = GEN_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) 1) - (match_dup 4))) - - (set (subreg:SI (match_dup 0) 0) - (ior:SI (subreg:SI (match_dup 0) 0) - (match_dup 3))) - - (set (subreg:SI (match_dup 0) 1) - (ashift:SI (subreg:SI (match_dup 1) 1) - (match_dup 2)))] - " -{ - int amount = INTVAL (operands[2]); - operands[2] = GEN_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 "se_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") - (set_attr "mode" "DI") - (set_attr "length" "1")]) - -(define_insn "" - [(set (match_operand:DI 0 "register_operand" "=d,d") - (ashift:DI (match_operand:DI 1 "se_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\"; - - 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") - (set_attr "mode" "DI") - (set_attr_alternative "length" - [(const_int 1) - (if_then_else (match_operand:VOID 2 "m16_uimm3_b" "") - (const_int 1) - (const_int 2))])]) - - -;; 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" "")))] - "TARGET_MIPS16 && TARGET_64BIT - && reload_completed - && GET_CODE (operands[2]) == CONST_INT - && INTVAL (operands[2]) > 8 - && 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); -}") - -(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")))] - "" - " -{ - /* 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 (SImode); - - emit_insn (gen_ashrsi3_internal2 (temp, operands[1], GEN_INT (8))); - emit_insn (gen_ashrsi3_internal2 (operands[0], temp, - 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") - (set_attr "mode" "SI") - (set_attr "length" "1")]) - -(define_insn "ashrsi3_internal2" - [(set (match_operand:SI 0 "register_operand" "=d,d") - (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\"; - - 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") - (set_attr "mode" "SI") - (set_attr_alternative "length" - [(const_int 1) - (if_then_else (match_operand:VOID 2 "m16_uimm3_b" "") - (const_int 1) - (const_int 2))])]) - - -;; 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" "")))] - "TARGET_MIPS16 - && reload_completed - && 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); -}") - -(define_expand "ashrdi3" - [(parallel [(set (match_operand:DI 0 "register_operand" "") - (ashiftrt:DI (match_operand:DI 1 "se_register_operand" "") - (match_operand:SI 2 "arith_operand" ""))) - (clobber (match_dup 3))])] - "TARGET_64BIT || (!TARGET_DEBUG_G_MODE && !TARGET_MIPS16)" - " -{ - 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) - { - 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; - } - - emit_insn (gen_ashrdi3_internal4 (operands[0], operands[1], - operands[2])); - 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; - dslots_jump_total += 3; - dslots_jump_filled += 2; - - return \"sll\\t%3,%2,26\\n\\ -\\tbgez\\t%3,1f\\n\\ -\\tsra\\t%L0,%M1,%2\\n\\ -\\t%(b\\t3f\\n\\ -\\tsra\\t%M0,%M1,31%)\\n\\ -\\n\\ -1:\\n\\ -\\t%(beq\\t%3,%z4,2f\\n\\ -\\tsrl\\t%L0,%L1,%2%)\\n\\ -\\n\\ -\\tsubu\\t%3,%z4,%2\\n\\ -\\tsll\\t%3,%M1,%3\\n\\ -\\tor\\t%L0,%L0,%3\\n\\ -2:\\n\\ -\\tsra\\t%M0,%M1,%2\\n\\ -3:\"; -}" - [(set_attr "type" "darith") - (set_attr "mode" "DI") - (set_attr "length" "12")]) - - -(define_insn "ashrdi3_internal2" - [(set (match_operand:DI 0 "register_operand" "=d") - (ashiftrt:DI (match_operand:DI 1 "register_operand" "d") - (match_operand:SI 2 "small_int" "IJK"))) - (clobber (match_operand:SI 3 "register_operand" "=d"))] - "!TARGET_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" "2")]) - - -(define_split - [(set (match_operand:DI 0 "register_operand" "") - (ashiftrt:DI (match_operand:DI 1 "register_operand" "") - (match_operand:SI 2 "small_int" ""))) - (clobber (match_operand:SI 3 "register_operand" ""))] - "reload_completed && !WORDS_BIG_ENDIAN && !TARGET_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) 1) (match_dup 2))) - (set (subreg:SI (match_dup 0) 1) (ashiftrt:SI (subreg:SI (match_dup 1) 1) (const_int 31)))] - - "operands[2] = GEN_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) 1) (ashiftrt:SI (subreg:SI (match_dup 1) 0) (match_dup 2))) - (set (subreg:SI (match_dup 0) 0) (ashiftrt:SI (subreg:SI (match_dup 1) 0) (const_int 31)))] - - "operands[2] = GEN_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" "4")]) - - -(define_split - [(set (match_operand:DI 0 "register_operand" "") - (ashiftrt:DI (match_operand:DI 1 "register_operand" "") - (match_operand:SI 2 "small_int" ""))) - (clobber (match_operand:SI 3 "register_operand" ""))] - "reload_completed && !WORDS_BIG_ENDIAN && !TARGET_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) 1) - (match_dup 4))) - - (set (subreg:SI (match_dup 0) 0) - (ior:SI (subreg:SI (match_dup 0) 0) - (match_dup 3))) - - (set (subreg:SI (match_dup 0) 1) - (ashiftrt:SI (subreg:SI (match_dup 1) 1) - (match_dup 2)))] - " -{ - int amount = INTVAL (operands[2]); - operands[2] = GEN_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) 1) - (lshiftrt:SI (subreg:SI (match_dup 1) 1) - (match_dup 2))) - - (set (match_dup 3) - (ashift:SI (subreg:SI (match_dup 1) 0) - (match_dup 4))) - - (set (subreg:SI (match_dup 0) 1) - (ior:SI (subreg:SI (match_dup 0) 1) - (match_dup 3))) - - (set (subreg:SI (match_dup 0) 0) - (ashiftrt:SI (subreg:SI (match_dup 1) 0) - (match_dup 2)))] - " -{ - int amount = INTVAL (operands[2]); - operands[2] = GEN_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 "se_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") - (set_attr "mode" "DI") - (set_attr "length" "1")]) - -(define_insn "" - [(set (match_operand:DI 0 "register_operand" "=d,d") - (ashiftrt:DI (match_operand:DI 1 "se_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") - (set_attr "mode" "DI") - (set_attr_alternative "length" - [(const_int 1) - (if_then_else (match_operand:VOID 2 "m16_uimm3_b" "") - (const_int 1) - (const_int 2))])]) - -;; 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" "")))] - "TARGET_MIPS16 && TARGET_64BIT - && reload_completed - && GET_CODE (operands[2]) == CONST_INT - && INTVAL (operands[2]) > 8 - && 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); -}") - -(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")))] - "" - " -{ - /* 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 (SImode); - - emit_insn (gen_lshrsi3_internal2 (temp, operands[1], GEN_INT (8))); - emit_insn (gen_lshrsi3_internal2 (operands[0], temp, - 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") - (set_attr "mode" "SI") - (set_attr "length" "1")]) - -(define_insn "lshrsi3_internal2" - [(set (match_operand:SI 0 "register_operand" "=d,d") - (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\"; - - 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") - (set_attr "mode" "SI") - (set_attr_alternative "length" - [(const_int 1) - (if_then_else (match_operand:VOID 2 "m16_uimm3_b" "") - (const_int 1) - (const_int 2))])]) - - -;; 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" "")))] - "TARGET_MIPS16 - && reload_completed - && 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); -}") - -;; If we load a byte on the mips16 as a bitfield, the resulting -;; sequence of instructions is too complicated for combine, because it -;; involves four instructions: a load, a shift, a constant load into a -;; 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. - -(define_insn "" - [(set (match_operand:SI 0 "register_operand" "=d,d") - (lshiftrt:SI (match_operand:SI 1 "memory_operand" "R,m") - (match_operand:SI 2 "immediate_operand" "I,I")))] - "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 2) - (const_int 3)) - (if_then_else (match_operand:VOID 2 "m16_uimm3_b" "") - (const_int 3) - (const_int 4))])]) - -(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" - [(set (match_dup 0) (match_dup 1)) - (set (match_dup 0) (lshiftrt:SI (match_dup 0) (match_dup 2)))] - "") - -(define_expand "lshrdi3" - [(parallel [(set (match_operand:DI 0 "register_operand" "") - (lshiftrt:DI (match_operand:DI 1 "se_register_operand" "") - (match_operand:SI 2 "arith_operand" ""))) - (clobber (match_dup 3))])] - "TARGET_64BIT || (!TARGET_DEBUG_G_MODE && !TARGET_MIPS16)" - " -{ - 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) - { - 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])); - 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; - dslots_jump_total += 3; - dslots_jump_filled += 2; - - return \"sll\\t%3,%2,26\\n\\ -\\tbgez\\t%3,1f\\n\\ -\\tsrl\\t%L0,%M1,%2\\n\\ -\\t%(b\\t3f\\n\\ -\\tmove\\t%M0,%z4%)\\n\\ -\\n\\ -1:\\n\\ -\\t%(beq\\t%3,%z4,2f\\n\\ -\\tsrl\\t%L0,%L1,%2%)\\n\\ -\\n\\ -\\tsubu\\t%3,%z4,%2\\n\\ -\\tsll\\t%3,%M1,%3\\n\\ -\\tor\\t%L0,%L0,%3\\n\\ -2:\\n\\ -\\tsrl\\t%M0,%M1,%2\\n\\ -3:\"; -}" - [(set_attr "type" "darith") - (set_attr "mode" "DI") - (set_attr "length" "12")]) - - -(define_insn "lshrdi3_internal2" - [(set (match_operand:DI 0 "register_operand" "=d") - (lshiftrt:DI (match_operand:DI 1 "register_operand" "d") - (match_operand:SI 2 "small_int" "IJK"))) - (clobber (match_operand:SI 3 "register_operand" "=d"))] - "!TARGET_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" "2")]) - - -(define_split - [(set (match_operand:DI 0 "register_operand" "") - (lshiftrt:DI (match_operand:DI 1 "register_operand" "") - (match_operand:SI 2 "small_int" ""))) - (clobber (match_operand:SI 3 "register_operand" ""))] - "reload_completed && !WORDS_BIG_ENDIAN && !TARGET_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) 1) (match_dup 2))) - (set (subreg:SI (match_dup 0) 1) (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) 1) (lshiftrt:SI (subreg:SI (match_dup 1) 0) (match_dup 2))) - (set (subreg:SI (match_dup 0) 0) (const_int 0))] - - "operands[2] = GEN_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" "4")]) - - -(define_split - [(set (match_operand:DI 0 "register_operand" "") - (lshiftrt:DI (match_operand:DI 1 "register_operand" "") - (match_operand:SI 2 "small_int" ""))) - (clobber (match_operand:SI 3 "register_operand" ""))] - "reload_completed && !WORDS_BIG_ENDIAN && !TARGET_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) 1) - (match_dup 4))) - - (set (subreg:SI (match_dup 0) 0) - (ior:SI (subreg:SI (match_dup 0) 0) - (match_dup 3))) - - (set (subreg:SI (match_dup 0) 1) - (lshiftrt:SI (subreg:SI (match_dup 1) 1) - (match_dup 2)))] - " -{ - int amount = INTVAL (operands[2]); - operands[2] = GEN_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) 1) - (lshiftrt:SI (subreg:SI (match_dup 1) 1) - (match_dup 2))) - - (set (match_dup 3) - (ashift:SI (subreg:SI (match_dup 1) 0) - (match_dup 4))) - - (set (subreg:SI (match_dup 0) 1) - (ior:SI (subreg:SI (match_dup 0) 1) - (match_dup 3))) - - (set (subreg:SI (match_dup 0) 0) - (lshiftrt:SI (subreg:SI (match_dup 1) 0) - (match_dup 2)))] - " -{ - int amount = INTVAL (operands[2]); - operands[2] = GEN_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 "se_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") - (set_attr "length" "1")]) - -;; CYGNUS LOCAL vr5400/raeburn -(define_insn "rotrsi3" - [(set (match_operand:SI 0 "register_operand" "=d") - (rotatert:SI (match_operand:SI 1 "register_operand" "d") - (match_operand:SI 2 "arith_operand" "dn")))] - "TARGET_MIPS5400" - "* -{ - if (GET_CODE (operands[2]) == CONST_INT) - operands[2] = GEN_INT (INTVAL (operands[2]) & 0x1f); - - return \"ror\\t%0,%1,%2\"; -}" - [(set_attr "type" "arith") - (set_attr "mode" "SI")]) - -(define_insn "rotrdi3" - [(set (match_operand:DI 0 "register_operand" "=d") - (rotatert:DI (match_operand:DI 1 "register_operand" "d") - (match_operand:DI 2 "arith_operand" "dn")))] - "TARGET_MIPS5400 && TARGET_64BIT" - "* -{ - if (GET_CODE (operands[2]) == CONST_INT) - operands[2] = GEN_INT (INTVAL (operands[2]) & 0x1f); - - return \"dror\\t%0,%1,%2\"; -}" - [(set_attr "type" "arith") - (set_attr "mode" "DI")]) -;; END CYGNUS LOCAL - -(define_insn "" - [(set (match_operand:DI 0 "register_operand" "=d,d") - (lshiftrt:DI (match_operand:DI 1 "se_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") - (set_attr "mode" "DI") - (set_attr_alternative "length" - [(const_int 1) - (if_then_else (match_operand:VOID 2 "m16_uimm3_b" "") - (const_int 1) - (const_int 2))])]) - -;; 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" "")))] - "TARGET_MIPS16 - && reload_completed - && 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); -}") - - -;; .................... -;; COMPARISONS -;; .................... - -;; 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. -;; 2) The appropriate branch define_expand is called, which then -;; creates the appropriate RTL for the comparison and branch. -;; Different CC modes are used, based on what type of branch is -;; done, so that we can constrain things appropriately. There -;; are assumptions in the rest of GCC that break if we fold the -;; operands into the branchs for integer operations, and use cc0 -;; for floating point, so we use the fp status register instead. -;; If needed, an appropriate temporary is created to hold the -;; of the integer compare. - -(define_expand "cmpsi" - [(set (cc0) - (compare:CC (match_operand:SI 0 "register_operand" "") - (match_operand:SI 1 "arith_operand" "")))] - "" - " -{ - if (operands[0]) /* avoid unused code message */ - { - branch_cmp[0] = operands[0]; - branch_cmp[1] = operands[1]; - branch_type = CMP_SI; - DONE; - } -}") - -(define_expand "tstsi" - [(set (cc0) - (match_operand:SI 0 "register_operand" ""))] - "" - " -{ - if (operands[0]) /* avoid unused code message */ - { - branch_cmp[0] = operands[0]; - branch_cmp[1] = const0_rtx; - branch_type = CMP_SI; - DONE; - } -}") - -(define_expand "cmpdi" - [(set (cc0) - (compare:CC (match_operand:DI 0 "se_register_operand" "") - (match_operand:DI 1 "se_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 "se_register_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; - } -}") - -(define_expand "cmpdf" - [(set (cc0) - (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; - } -}") - -(define_expand "cmpsf" - [(set (cc0) - (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; - } -}") - - -;; .................... -;; CONDITIONAL BRANCHES -;; .................... - -(define_insn "branch_fp_ne" - [(set (pc) - (if_then_else (ne:CC (match_operand:CC 0 "register_operand" "z") - (const_int 0)) - (match_operand 1 "pc_or_label_operand" "") - (match_operand 2 "pc_or_label_operand" "")))] - "TARGET_HARD_FLOAT" - "* -{ - mips_branch_likely = (final_sequence && INSN_ANNULLED_BRANCH_P (insn)); - return (operands[1] != pc_rtx) ? \"%*bc1t%?\\t%Z0%1\" : \"%*bc1f%?\\t%Z0%2\"; -}" - [(set_attr "type" "branch") - (set_attr "mode" "none") - (set_attr "length" "1")]) - -(define_insn "branch_fp_eq" - [(set (pc) - (if_then_else (eq:CC (match_operand:CC 0 "register_operand" "z") - (const_int 0)) - (match_operand 1 "pc_or_label_operand" "") - (match_operand 2 "pc_or_label_operand" "")))] - "TARGET_HARD_FLOAT" - "* -{ - mips_branch_likely = (final_sequence && INSN_ANNULLED_BRANCH_P (insn)); - return (operands[1] != pc_rtx) ? \"%*bc1f%?\\t%Z0%1\" : \"%*bc1t%?\\t%Z0%2\"; -}" - [(set_attr "type" "branch") - (set_attr "mode" "none") - (set_attr "length" "1")]) - -(define_insn "branch_zero" - [(set (pc) - (if_then_else (match_operator:SI 0 "cmp_op" - [(match_operand:SI 1 "register_operand" "d") - (const_int 0)]) - (match_operand 2 "pc_or_label_operand" "") - (match_operand 3 "pc_or_label_operand" "")))] - "!TARGET_MIPS16" - "* -{ - mips_branch_likely = (final_sequence && INSN_ANNULLED_BRANCH_P (insn)); - if (operands[2] != pc_rtx) - { /* normal jump */ - switch (GET_CODE (operands[0])) - { - case EQ: return \"%*beq%?\\t%z1,%.,%2\"; - case NE: return \"%*bne%?\\t%z1,%.,%2\"; - case GTU: return \"%*bne%?\\t%z1,%.,%2\"; - case LEU: return \"%*beq%?\\t%z1,%.,%2\"; - case GEU: return \"%*j\\t%2\"; - case LTU: return \"%*bne%?\\t%.,%.,%2\"; - default: - break; - } - - return \"%*b%C0z%?\\t%z1,%2\"; - } - else - { /* inverted jump */ - switch (GET_CODE (operands[0])) - { - case EQ: return \"%*bne%?\\t%z1,%.,%3\"; - case NE: return \"%*beq%?\\t%z1,%.,%3\"; - case GTU: return \"%*beq%?\\t%z1,%.,%3\"; - case LEU: return \"%*bne%?\\t%z1,%.,%3\"; - case GEU: return \"%*beq%?\\t%.,%.,%3\"; - case LTU: return \"%*j\\t%3\"; - default: - break; - } - - return \"%*b%N0z%?\\t%z1,%3\"; - } -}" - [(set_attr "type" "branch") - (set_attr "mode" "none") - (set_attr "length" "1")]) - - -(define_insn "" - [(set (pc) - (if_then_else (match_operator:SI 0 "equality_op" - [(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\"; - else - return \"%*bt%C0z\\t%2\"; - } - else - { - if (which_alternative == 0) - return \"%*b%N0z\\t%1,%3\"; - else - return \"%*bt%N0z\\t%3\"; - } -}" - [(set_attr "type" "branch") - (set_attr "mode" "none") - (set_attr "length" "2")]) - -(define_insn "branch_zero_di" - [(set (pc) - (if_then_else (match_operator:DI 0 "cmp_op" - [(match_operand:DI 1 "se_register_operand" "d") - (const_int 0)]) - (match_operand 2 "pc_or_label_operand" "") - (match_operand 3 "pc_or_label_operand" "")))] - "!TARGET_MIPS16" - "* -{ - mips_branch_likely = (final_sequence && INSN_ANNULLED_BRANCH_P (insn)); - if (operands[2] != pc_rtx) - { /* normal jump */ - switch (GET_CODE (operands[0])) - { - case EQ: return \"%*beq%?\\t%z1,%.,%2\"; - case NE: return \"%*bne%?\\t%z1,%.,%2\"; - case GTU: return \"%*bne%?\\t%z1,%.,%2\"; - case LEU: return \"%*beq%?\\t%z1,%.,%2\"; - case GEU: return \"%*j\\t%2\"; - case LTU: return \"%*bne%?\\t%.,%.,%2\"; - default: - break; - } - - return \"%*b%C0z%?\\t%z1,%2\"; - } - else - { /* inverted jump */ - switch (GET_CODE (operands[0])) - { - case EQ: return \"%*bne%?\\t%z1,%.,%3\"; - case NE: return \"%*beq%?\\t%z1,%.,%3\"; - case GTU: return \"%*beq%?\\t%z1,%.,%3\"; - case LEU: return \"%*bne%?\\t%z1,%.,%3\"; - case GEU: return \"%*beq%?\\t%.,%.,%3\"; - case LTU: return \"%*j\\t%3\"; - default: - break; - } - - return \"%*b%N0z%?\\t%z1,%3\"; - } -}" - [(set_attr "type" "branch") - (set_attr "mode" "none") - (set_attr "length" "1")]) - -(define_insn "" - [(set (pc) - (if_then_else (match_operator:DI 0 "equality_op" - [(match_operand:DI 1 "se_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\"; - else - return \"%*bt%C0z\\t%2\"; - } - else - { - if (which_alternative == 0) - return \"%*b%N0z\\t%1,%3\"; - else - return \"%*bt%N0z\\t%3\"; - } -}" - [(set_attr "type" "branch") - (set_attr "mode" "none") - (set_attr "length" "2")]) - - -(define_insn "branch_equality" - [(set (pc) - (if_then_else (match_operator:SI 0 "equality_op" - [(match_operand:SI 1 "register_operand" "d") - (match_operand:SI 2 "register_operand" "d")]) - (match_operand 3 "pc_or_label_operand" "") - (match_operand 4 "pc_or_label_operand" "")))] - "!TARGET_MIPS16" - "* -{ - mips_branch_likely = (final_sequence && INSN_ANNULLED_BRANCH_P (insn)); - return (operands[3] != pc_rtx) - ? \"%*b%C0%?\\t%z1,%z2,%3\" - : \"%*b%N0%?\\t%z1,%z2,%4\"; -}" - [(set_attr "type" "branch") - (set_attr "mode" "none") - (set_attr "length" "1")]) - - -(define_insn "branch_equality_di" - [(set (pc) - (if_then_else (match_operator:DI 0 "equality_op" - [(match_operand:DI 1 "se_register_operand" "d") - (match_operand:DI 2 "se_register_operand" "d")]) - (match_operand 3 "pc_or_label_operand" "") - (match_operand 4 "pc_or_label_operand" "")))] - "!TARGET_MIPS16" - "* -{ - mips_branch_likely = (final_sequence && INSN_ANNULLED_BRANCH_P (insn)); - return (operands[3] != pc_rtx) - ? \"%*b%C0%?\\t%z1,%z2,%3\" - : \"%*b%N0%?\\t%z1,%z2,%4\"; -}" - [(set_attr "type" "branch") - (set_attr "mode" "none") - (set_attr "length" "1")]) - - -(define_expand "beq" - [(set (pc) - (if_then_else (eq:CC (cc0) - (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - " -{ - if (operands[0]) /* avoid unused code warning */ - { - gen_conditional_branch (operands, EQ); - DONE; - } -}") - -(define_expand "bne" - [(set (pc) - (if_then_else (ne:CC (cc0) - (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - " -{ - if (operands[0]) /* avoid unused code warning */ - { - gen_conditional_branch (operands, NE); - DONE; - } -}") - -(define_expand "bgt" - [(set (pc) - (if_then_else (gt:CC (cc0) - (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - " -{ - if (operands[0]) /* avoid unused code warning */ - { - gen_conditional_branch (operands, GT); - DONE; - } -}") - -(define_expand "bge" - [(set (pc) - (if_then_else (ge:CC (cc0) - (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - " -{ - if (operands[0]) /* avoid unused code warning */ - { - gen_conditional_branch (operands, GE); - DONE; - } -}") - -(define_expand "blt" - [(set (pc) - (if_then_else (lt:CC (cc0) - (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - " -{ - if (operands[0]) /* avoid unused code warning */ - { - gen_conditional_branch (operands, LT); - DONE; - } -}") - -(define_expand "ble" - [(set (pc) - (if_then_else (le:CC (cc0) - (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - " -{ - if (operands[0]) /* avoid unused code warning */ - { - gen_conditional_branch (operands, LE); - DONE; - } -}") - -(define_expand "bgtu" - [(set (pc) - (if_then_else (gtu:CC (cc0) - (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - " -{ - if (operands[0]) /* avoid unused code warning */ - { - gen_conditional_branch (operands, GTU); - DONE; - } -}") - -(define_expand "bgeu" - [(set (pc) - (if_then_else (geu:CC (cc0) - (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - " -{ - if (operands[0]) /* avoid unused code warning */ - { - gen_conditional_branch (operands, GEU); - DONE; - } -}") - - -(define_expand "bltu" - [(set (pc) - (if_then_else (ltu:CC (cc0) - (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - " -{ - if (operands[0]) /* avoid unused code warning */ - { - gen_conditional_branch (operands, LTU); - DONE; - } -}") - -(define_expand "bleu" - [(set (pc) - (if_then_else (leu:CC (cc0) - (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - " -{ - if (operands[0]) /* avoid unused code warning */ - { - gen_conditional_branch (operands, LEU); - DONE; - } -}") - - -;; .................... -;; SETTING A REGISTER FROM A COMPARISON -;; .................... - -(define_expand "seq" - [(set (match_operand:SI 0 "register_operand" "=d") - (eq:SI (match_dup 1) - (match_dup 2)))] - "" - " -{ - 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 (EQ, operands[0], operands[1], operands[2], (int *)0); - DONE; - } - - if (GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) < 0) - operands[2] = force_reg (SImode, operands[2]); - - /* fall through and generate default code */ -}") - - -(define_insn "seq_si_zero" - [(set (match_operand:SI 0 "register_operand" "=d") - (eq:SI (match_operand:SI 1 "register_operand" "d") - (const_int 0)))] - "!TARGET_MIPS16" - "sltu\\t%0,%1,1" - [(set_attr "type" "arith") - (set_attr "mode" "SI") - (set_attr "length" "1")]) - -(define_insn "" - [(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") - (set_attr "length" "1")]) - -(define_insn "seq_di_zero" - [(set (match_operand:DI 0 "register_operand" "=d") - (eq:DI (match_operand:DI 1 "se_register_operand" "d") - (const_int 0)))] - "TARGET_64BIT && !TARGET_MIPS16" - "sltu\\t%0,%1,1" - [(set_attr "type" "arith") - (set_attr "mode" "DI") - (set_attr "length" "1")]) - -(define_insn "" - [(set (match_operand:DI 0 "register_operand" "=t") - (eq:DI (match_operand:DI 1 "se_register_operand" "d") - (const_int 0)))] - "TARGET_64BIT && TARGET_MIPS16" - "sltu\\t%1,1" - [(set_attr "type" "arith") - (set_attr "mode" "DI") - (set_attr "length" "1")]) - -(define_insn "seq_si" - [(set (match_operand:SI 0 "register_operand" "=d,d") - (eq:SI (match_operand:SI 1 "register_operand" "%d,d") - (match_operand:SI 2 "uns_arith_operand" "d,K")))] - "TARGET_DEBUG_C_MODE && !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" "2")]) - -(define_split - [(set (match_operand:SI 0 "register_operand" "") - (eq:SI (match_operand:SI 1 "register_operand" "") - (match_operand:SI 2 "uns_arith_operand" "")))] - "TARGET_DEBUG_C_MODE && !TARGET_DEBUG_D_MODE && !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 "se_register_operand" "%d,d") - (match_operand:DI 2 "se_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" "2")]) - -(define_split - [(set (match_operand:DI 0 "register_operand" "") - (eq:DI (match_operand:DI 1 "se_register_operand" "") - (match_operand:DI 2 "se_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)))] - "") - -;; On the mips16 the default code is better than using sltu. - -(define_expand "sne" - [(set (match_operand:SI 0 "register_operand" "=d") - (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]); - - /* fall through and generate default code */ -}") - -(define_insn "sne_si_zero" - [(set (match_operand:SI 0 "register_operand" "=d") - (ne:SI (match_operand:SI 1 "register_operand" "d") - (const_int 0)))] - "!TARGET_MIPS16" - "sltu\\t%0,%.,%1" - [(set_attr "type" "arith") - (set_attr "mode" "SI") - (set_attr "length" "1")]) - -(define_insn "sne_di_zero" - [(set (match_operand:DI 0 "register_operand" "=d") - (ne:DI (match_operand:DI 1 "se_register_operand" "d") - (const_int 0)))] - "TARGET_64BIT && !TARGET_MIPS16" - "sltu\\t%0,%.,%1" - [(set_attr "type" "arith") - (set_attr "mode" "DI") - (set_attr "length" "1")]) - -(define_insn "sne_si" - [(set (match_operand:SI 0 "register_operand" "=d,d") - (ne:SI (match_operand:SI 1 "register_operand" "%d,d") - (match_operand:SI 2 "uns_arith_operand" "d,K")))] - "TARGET_DEBUG_C_MODE && !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" "2")]) - -(define_split - [(set (match_operand:SI 0 "register_operand" "") - (ne:SI (match_operand:SI 1 "register_operand" "") - (match_operand:SI 2 "uns_arith_operand" "")))] - "TARGET_DEBUG_C_MODE && !TARGET_DEBUG_D_MODE && !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 "se_register_operand" "%d,d") - (match_operand:DI 2 "se_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" "2")]) - -(define_split - [(set (match_operand:DI 0 "register_operand" "") - (ne:DI (match_operand:DI 1 "se_register_operand" "") - (match_operand:DI 2 "se_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)))] - "") - -(define_expand "sgt" - [(set (match_operand:SI 0 "register_operand" "=d") - (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]); - - /* fall through and generate default code */ -}") - -(define_insn "sgt_si" - [(set (match_operand:SI 0 "register_operand" "=d") - (gt:SI (match_operand:SI 1 "register_operand" "d") - (match_operand:SI 2 "reg_or_0_operand" "dJ")))] - "!TARGET_MIPS16" - "slt\\t%0,%z2,%1" - [(set_attr "type" "arith") - (set_attr "mode" "SI") - (set_attr "length" "1")]) - -(define_insn "" - [(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") - (set_attr "length" "1")]) - -(define_insn "sgt_di" - [(set (match_operand:DI 0 "register_operand" "=d") - (gt:DI (match_operand:DI 1 "se_register_operand" "d") - (match_operand:DI 2 "se_reg_or_0_operand" "dJ")))] - "TARGET_64BIT && !TARGET_MIPS16" - "slt\\t%0,%z2,%1" - [(set_attr "type" "arith") - (set_attr "mode" "DI") - (set_attr "length" "1")]) - -(define_insn "" - [(set (match_operand:DI 0 "register_operand" "=d") - (gt:DI (match_operand:DI 1 "se_register_operand" "d") - (match_operand:DI 2 "se_register_operand" "d")))] - "TARGET_64BIT && TARGET_MIPS16" - "slt\\t%2,%1" - [(set_attr "type" "arith") - (set_attr "mode" "DI") - (set_attr "length" "1")]) - -(define_expand "sge" - [(set (match_operand:SI 0 "register_operand" "=d") - (ge:SI (match_dup 1) - (match_dup 2)))] - "" - " -{ - if (branch_type != CMP_SI && (!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 (GE, operands[0], operands[1], operands[2], (int *)0); - DONE; - } - - /* fall through and generate default code */ -}") - -(define_insn "sge_si" - [(set (match_operand:SI 0 "register_operand" "=d") - (ge:SI (match_operand:SI 1 "register_operand" "d") - (match_operand:SI 2 "arith_operand" "dI")))] - "TARGET_DEBUG_C_MODE && !TARGET_MIPS16" - "slt\\t%0,%1,%2\;xori\\t%0,%0,0x0001" - [(set_attr "type" "arith") - (set_attr "mode" "SI") - (set_attr "length" "2")]) - -(define_split - [(set (match_operand:SI 0 "register_operand" "") - (ge:SI (match_operand:SI 1 "register_operand" "") - (match_operand:SI 2 "arith_operand" "")))] - "TARGET_DEBUG_C_MODE && !TARGET_DEBUG_D_MODE && !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)))] - "") - -(define_insn "sge_di" - [(set (match_operand:DI 0 "register_operand" "=d") - (ge:DI (match_operand:DI 1 "se_register_operand" "d") - (match_operand:DI 2 "se_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" "2")]) - -(define_split - [(set (match_operand:DI 0 "register_operand" "") - (ge:DI (match_operand:DI 1 "se_register_operand" "") - (match_operand:DI 2 "se_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)))] - "") - -(define_expand "slt" - [(set (match_operand:SI 0 "register_operand" "=d") - (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 */ -}") - -(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") - (set_attr "length" "1")]) - -(define_insn "" - [(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") - (set_attr_alternative "length" - [(const_int 1) - (if_then_else (match_operand:VOID 2 "m16_uimm8_1" "") - (const_int 1) - (const_int 2))])]) - -(define_insn "slt_di" - [(set (match_operand:DI 0 "register_operand" "=d") - (lt:DI (match_operand:DI 1 "se_register_operand" "d") - (match_operand:DI 2 "se_arith_operand" "dI")))] - "TARGET_64BIT && !TARGET_MIPS16" - "slt\\t%0,%1,%2" - [(set_attr "type" "arith") - (set_attr "mode" "DI") - (set_attr "length" "1")]) - -(define_insn "" - [(set (match_operand:DI 0 "register_operand" "=t,t") - (lt:DI (match_operand:DI 1 "se_register_operand" "d,d") - (match_operand:DI 2 "se_arith_operand" "d,I")))] - "TARGET_64BIT && TARGET_MIPS16" - "slt\\t%1,%2" - [(set_attr "type" "arith") - (set_attr "mode" "DI") - (set_attr_alternative "length" - [(const_int 1) - (if_then_else (match_operand:VOID 2 "m16_uimm8_1" "") - (const_int 1) - (const_int 2))])]) - -(define_expand "sle" - [(set (match_operand:SI 0 "register_operand" "=d") - (le: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 (LE, operands[0], operands[1], operands[2], (int *)0); - DONE; - } - - if (GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) >= 32767) - operands[2] = force_reg (SImode, operands[2]); - - /* fall through and generate default code */ -}") - -(define_insn "sle_si_const" - [(set (match_operand:SI 0 "register_operand" "=d") - (le:SI (match_operand:SI 1 "register_operand" "d") - (match_operand:SI 2 "small_int" "I")))] - "!TARGET_MIPS16 && INTVAL (operands[2]) < 32767" - "* -{ - operands[2] = GEN_INT (INTVAL (operands[2])+1); - return \"slt\\t%0,%1,%2\"; -}" - [(set_attr "type" "arith") - (set_attr "mode" "SI") - (set_attr "length" "1")]) - -(define_insn "" - [(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" - "* -{ - 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" "") - (const_int 1) - (const_int 2)))]) - -(define_insn "sle_di_const" - [(set (match_operand:DI 0 "register_operand" "=d") - (le:DI (match_operand:DI 1 "se_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 \"slt\\t%0,%1,%2\"; -}" - [(set_attr "type" "arith") - (set_attr "mode" "DI") - (set_attr "length" "1")]) - -(define_insn "" - [(set (match_operand:DI 0 "register_operand" "=t") - (le:DI (match_operand:DI 1 "se_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 \"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" "") - (const_int 1) - (const_int 2)))]) - -(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" "2")]) - -(define_split - [(set (match_operand:SI 0 "register_operand" "") - (le:SI (match_operand:SI 1 "register_operand" "") - (match_operand:SI 2 "register_operand" "")))] - "TARGET_DEBUG_C_MODE && !TARGET_DEBUG_D_MODE && !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 "se_register_operand" "d") - (match_operand:DI 2 "se_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" "2")]) - -(define_split - [(set (match_operand:DI 0 "register_operand" "") - (le:DI (match_operand:DI 1 "se_register_operand" "") - (match_operand:DI 2 "se_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") - (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]); - - /* fall through and generate default code */ -}") - -(define_insn "sgtu_si" - [(set (match_operand:SI 0 "register_operand" "=d") - (gtu:SI (match_operand:SI 1 "register_operand" "d") - (match_operand:SI 2 "reg_or_0_operand" "dJ")))] - "" - "sltu\\t%0,%z2,%1" - [(set_attr "type" "arith") - (set_attr "mode" "SI") - (set_attr "length" "1")]) - -(define_insn "" - [(set (match_operand:SI 0 "register_operand" "=t") - (gtu:SI (match_operand:SI 1 "register_operand" "d") - (match_operand:SI 2 "register_operand" "d")))] - "" - "sltu\\t%2,%1" - [(set_attr "type" "arith") - (set_attr "mode" "SI") - (set_attr "length" "1")]) - -(define_insn "sgtu_di" - [(set (match_operand:DI 0 "register_operand" "=d") - (gtu:DI (match_operand:DI 1 "se_register_operand" "d") - (match_operand:DI 2 "se_reg_or_0_operand" "dJ")))] - "TARGET_64BIT" - "sltu\\t%0,%z2,%1" - [(set_attr "type" "arith") - (set_attr "mode" "DI") - (set_attr "length" "1")]) - -(define_insn "" - [(set (match_operand:DI 0 "register_operand" "=t") - (gtu:DI (match_operand:DI 1 "se_register_operand" "d") - (match_operand:DI 2 "se_register_operand" "d")))] - "TARGET_64BIT" - "sltu\\t%2,%1" - [(set_attr "type" "arith") - (set_attr "mode" "DI") - (set_attr "length" "1")]) - -(define_expand "sgeu" - [(set (match_operand:SI 0 "register_operand" "=d") - (geu:SI (match_dup 1) - (match_dup 2)))] - "" - " -{ - if (branch_type != CMP_SI && (!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 */ -}") - -(define_insn "sgeu_si" - [(set (match_operand:SI 0 "register_operand" "=d") - (geu:SI (match_operand:SI 1 "register_operand" "d") - (match_operand:SI 2 "arith_operand" "dI")))] - "TARGET_DEBUG_C_MODE && !TARGET_MIPS16" - "sltu\\t%0,%1,%2\;xori\\t%0,%0,0x0001" - [(set_attr "type" "arith") - (set_attr "mode" "SI") - (set_attr "length" "2")]) - -(define_split - [(set (match_operand:SI 0 "register_operand" "") - (geu:SI (match_operand:SI 1 "register_operand" "") - (match_operand:SI 2 "arith_operand" "")))] - "TARGET_DEBUG_C_MODE && !TARGET_DEBUG_D_MODE && !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)))] - "") - -(define_insn "sgeu_di" - [(set (match_operand:DI 0 "register_operand" "=d") - (geu:DI (match_operand:DI 1 "se_register_operand" "d") - (match_operand:DI 2 "se_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" "2")]) - -(define_split - [(set (match_operand:DI 0 "register_operand" "") - (geu:DI (match_operand:DI 1 "se_register_operand" "") - (match_operand:DI 2 "se_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)))] - "") - -(define_expand "sltu" - [(set (match_operand:SI 0 "register_operand" "=d") - (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; - } - - /* fall through and generate default code */ -}") - -(define_insn "sltu_si" - [(set (match_operand:SI 0 "register_operand" "=d") - (ltu:SI (match_operand:SI 1 "register_operand" "d") - (match_operand:SI 2 "arith_operand" "dI")))] - "!TARGET_MIPS16" - "sltu\\t%0,%1,%2" - [(set_attr "type" "arith") - (set_attr "mode" "SI") - (set_attr "length" "1")]) - -(define_insn "" - [(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") - (set_attr_alternative "length" - [(const_int 1) - (if_then_else (match_operand:VOID 2 "m16_uimm8_1" "") - (const_int 1) - (const_int 2))])]) - -(define_insn "sltu_di" - [(set (match_operand:DI 0 "register_operand" "=d") - (ltu:DI (match_operand:DI 1 "se_register_operand" "d") - (match_operand:DI 2 "se_arith_operand" "dI")))] - "TARGET_64BIT && !TARGET_MIPS16" - "sltu\\t%0,%1,%2" - [(set_attr "type" "arith") - (set_attr "mode" "DI") - (set_attr "length" "1")]) - -(define_insn "" - [(set (match_operand:DI 0 "register_operand" "=t,t") - (ltu:DI (match_operand:DI 1 "se_register_operand" "d,d") - (match_operand:DI 2 "se_arith_operand" "d,I")))] - "TARGET_64BIT && TARGET_MIPS16" - "sltu\\t%1,%2" - [(set_attr "type" "arith") - (set_attr "mode" "DI") - (set_attr_alternative "length" - [(const_int 1) - (if_then_else (match_operand:VOID 2 "m16_uimm8_1" "") - (const_int 1) - (const_int 2))])]) - -(define_expand "sleu" - [(set (match_operand:SI 0 "register_operand" "=d") - (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 (GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) >= 32767) - operands[2] = force_reg (SImode, operands[2]); - - /* fall through and generate default code */ -}") - -(define_insn "sleu_si_const" - [(set (match_operand:SI 0 "register_operand" "=d") - (leu:SI (match_operand:SI 1 "register_operand" "d") - (match_operand:SI 2 "small_int" "I")))] - "!TARGET_MIPS16 && INTVAL (operands[2]) < 32767" - "* -{ - operands[2] = GEN_INT (INTVAL (operands[2])+1); - return \"sltu\\t%0,%1,%2\"; -}" - [(set_attr "type" "arith") - (set_attr "mode" "SI") - (set_attr "length" "1")]) - -(define_insn "" - [(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 1) - (const_int 2)))]) - -(define_insn "sleu_di_const" - [(set (match_operand:DI 0 "register_operand" "=d") - (leu:DI (match_operand:DI 1 "se_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%0,%1,%2\"; -}" - [(set_attr "type" "arith") - (set_attr "mode" "DI") - (set_attr "length" "1")]) - -(define_insn "" - [(set (match_operand:DI 0 "register_operand" "=t") - (leu:DI (match_operand:DI 1 "se_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" "") - (const_int 1) - (const_int 2)))]) - -(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" "2")]) - -(define_split - [(set (match_operand:SI 0 "register_operand" "") - (leu:SI (match_operand:SI 1 "register_operand" "") - (match_operand:SI 2 "register_operand" "")))] - "TARGET_DEBUG_C_MODE && !TARGET_DEBUG_D_MODE && !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" - [(set (match_operand:DI 0 "register_operand" "=d") - (leu:DI (match_operand:DI 1 "se_register_operand" "d") - (match_operand:DI 2 "se_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" "2")]) - -(define_split - [(set (match_operand:DI 0 "register_operand" "") - (leu:DI (match_operand:DI 1 "se_register_operand" "") - (match_operand:DI 2 "se_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)))] - "") - - -;; .................... -;; FLOATING POINT COMPARISONS -;; .................... - -(define_insn "seq_df" - [(set (match_operand:CC 0 "register_operand" "=z") - (eq:CC (match_operand:DF 1 "register_operand" "f") - (match_operand:DF 2 "register_operand" "f")))] - "TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT" - "* -{ - return mips_fill_delay_slot (\"c.eq.d\\t%Z0%1,%2\", DELAY_FCMP, operands, insn); -}" - [(set_attr "type" "fcmp") - (set_attr "mode" "FPSW") - (set_attr "length" "1")]) - -(define_insn "slt_df" - [(set (match_operand:CC 0 "register_operand" "=z") - (lt:CC (match_operand:DF 1 "register_operand" "f") - (match_operand:DF 2 "register_operand" "f")))] - "TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT" - "* -{ - return mips_fill_delay_slot (\"c.lt.d\\t%Z0%1,%2\", DELAY_FCMP, operands, insn); -}" - [(set_attr "type" "fcmp") - (set_attr "mode" "FPSW") - (set_attr "length" "1")]) - -(define_insn "sle_df" - [(set (match_operand:CC 0 "register_operand" "=z") - (le:CC (match_operand:DF 1 "register_operand" "f") - (match_operand:DF 2 "register_operand" "f")))] - "TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT" - "* -{ - return mips_fill_delay_slot (\"c.le.d\\t%Z0%1,%2\", DELAY_FCMP, operands, insn); -}" - [(set_attr "type" "fcmp") - (set_attr "mode" "FPSW") - (set_attr "length" "1")]) - -(define_insn "sgt_df" - [(set (match_operand:CC 0 "register_operand" "=z") - (gt:CC (match_operand:DF 1 "register_operand" "f") - (match_operand:DF 2 "register_operand" "f")))] - "TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT" - "* -{ - return mips_fill_delay_slot (\"c.lt.d\\t%Z0%2,%1\", DELAY_FCMP, operands, insn); -}" - [(set_attr "type" "fcmp") - (set_attr "mode" "FPSW") - (set_attr "length" "1")]) - -(define_insn "sge_df" - [(set (match_operand:CC 0 "register_operand" "=z") - (ge:CC (match_operand:DF 1 "register_operand" "f") - (match_operand:DF 2 "register_operand" "f")))] - "TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT" - "* -{ - return mips_fill_delay_slot (\"c.le.d\\t%Z0%2,%1\", DELAY_FCMP, operands, insn); -}" - [(set_attr "type" "fcmp") - (set_attr "mode" "FPSW") - (set_attr "length" "1")]) - -(define_insn "seq_sf" - [(set (match_operand:CC 0 "register_operand" "=z") - (eq:CC (match_operand:SF 1 "register_operand" "f") - (match_operand:SF 2 "register_operand" "f")))] - "TARGET_HARD_FLOAT" - "* -{ - return mips_fill_delay_slot (\"c.eq.s\\t%Z0%1,%2\", DELAY_FCMP, operands, insn); -}" - [(set_attr "type" "fcmp") - (set_attr "mode" "FPSW") - (set_attr "length" "1")]) - -(define_insn "slt_sf" - [(set (match_operand:CC 0 "register_operand" "=z") - (lt:CC (match_operand:SF 1 "register_operand" "f") - (match_operand:SF 2 "register_operand" "f")))] - "TARGET_HARD_FLOAT" - "* -{ - return mips_fill_delay_slot (\"c.lt.s\\t%Z0%1,%2\", DELAY_FCMP, operands, insn); -}" - [(set_attr "type" "fcmp") - (set_attr "mode" "FPSW") - (set_attr "length" "1")]) - -(define_insn "sle_sf" - [(set (match_operand:CC 0 "register_operand" "=z") - (le:CC (match_operand:SF 1 "register_operand" "f") - (match_operand:SF 2 "register_operand" "f")))] - "TARGET_HARD_FLOAT" - "* -{ - return mips_fill_delay_slot (\"c.le.s\\t%Z0%1,%2\", DELAY_FCMP, operands, insn); -}" - [(set_attr "type" "fcmp") - (set_attr "mode" "FPSW") - (set_attr "length" "1")]) - -(define_insn "sgt_sf" - [(set (match_operand:CC 0 "register_operand" "=z") - (gt:CC (match_operand:SF 1 "register_operand" "f") - (match_operand:SF 2 "register_operand" "f")))] - "TARGET_HARD_FLOAT" - "* -{ - return mips_fill_delay_slot (\"c.lt.s\\t%Z0%2,%1\", DELAY_FCMP, operands, insn); -}" - [(set_attr "type" "fcmp") - (set_attr "mode" "FPSW") - (set_attr "length" "1")]) - -(define_insn "sge_sf" - [(set (match_operand:CC 0 "register_operand" "=z") - (ge:CC (match_operand:SF 1 "register_operand" "f") - (match_operand:SF 2 "register_operand" "f")))] - "TARGET_HARD_FLOAT" - "* -{ - return mips_fill_delay_slot (\"c.le.s\\t%Z0%2,%1\", DELAY_FCMP, operands, insn); -}" - [(set_attr "type" "fcmp") - (set_attr "mode" "FPSW") - (set_attr "length" "1")]) - - -;; .................... -;; UNCONDITIONAL BRANCHES -;; .................... - -;; Unconditional branches. - -(define_insn "jump" - [(set (pc) - (label_ref (match_operand 0 "" "")))] - "!TARGET_MIPS16" - "* -{ - if (GET_CODE (operands[0]) == REG) - return \"%*j\\t%0\"; - /* ??? I don't know why this is necessary. This works around an - assembler problem that appears when a label is defined, then referenced - in a switch table, then used in a `j' instruction. */ - else if (mips_abi != ABI_32 && mips_abi != ABI_O64) - return \"%*b\\t%l0\"; - else - return \"%*j\\t%l0\"; -}" - [(set_attr "type" "jump") - (set_attr "mode" "none") - (set_attr "length" "1")]) - -;; We need a different insn for the mips16, because a mips16 branch -;; does not have a delay slot. - -(define_insn "" - [(set (pc) - (label_ref (match_operand 0 "" "")))] - "TARGET_MIPS16 && GET_CODE (operands[0]) != REG" - "b\\t%l0" - [(set_attr "type" "branch") - (set_attr "mode" "none") - (set_attr "length" "2")]) - -(define_expand "indirect_jump" - [(set (pc) (match_operand 0 "register_operand" "d"))] - "" - " -{ - 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); - - if (!(Pmode == DImode)) - emit_jump_insn (gen_indirect_jump_internal1 (operands[0])); - else - emit_jump_insn (gen_indirect_jump_internal2 (operands[0])); - - DONE; - } -}") - -(define_insn "indirect_jump_internal1" - [(set (pc) (match_operand:SI 0 "register_operand" "d"))] - "!(Pmode == DImode)" - "%*j\\t%0" - [(set_attr "type" "jump") - (set_attr "mode" "none") - (set_attr "length" "1")]) - -(define_insn "indirect_jump_internal2" - [(set (pc) (match_operand:DI 0 "se_register_operand" "d"))] - "Pmode == DImode" - "%*j\\t%0" - [(set_attr "type" "jump") - (set_attr "mode" "none") - (set_attr "length" "1")]) - -(define_expand "tablejump" - [(set (pc) - (match_operand 0 "register_operand" "d")) - (use (label_ref (match_operand 1 "" "")))] - "" - " -{ - if (operands[0]) /* eliminate unused code warnings */ - { - if (TARGET_MIPS16) - { - if (GET_MODE (operands[0]) != HImode) - abort (); - if (!(Pmode == DImode)) - emit_jump_insn (gen_tablejump_mips161 (operands[0], operands[1])); - else - emit_jump_insn (gen_tablejump_mips162 (operands[0], operands[1])); - DONE; - } - - if (GET_MODE (operands[0]) != Pmode) - abort (); - - if (! flag_pic) - { - if (!(Pmode == DImode)) - emit_jump_insn (gen_tablejump_internal1 (operands[0], operands[1])); - else - emit_jump_insn (gen_tablejump_internal2 (operands[0], operands[1])); - } - else - { - if (!(Pmode == DImode)) - emit_jump_insn (gen_tablejump_internal3 (operands[0], operands[1])); - else - emit_jump_insn (gen_tablejump_internal4 (operands[0], operands[1])); - } - - DONE; - } -}") - -(define_insn "tablejump_internal1" - [(set (pc) - (match_operand:SI 0 "register_operand" "d")) - (use (label_ref (match_operand 1 "" "")))] - "!(Pmode == DImode)" - "%*j\\t%0" - [(set_attr "type" "jump") - (set_attr "mode" "none") - (set_attr "length" "1")]) - -(define_insn "tablejump_internal2" - [(set (pc) - (match_operand:DI 0 "se_register_operand" "d")) - (use (label_ref (match_operand 1 "" "")))] - "Pmode == DImode" - "%*j\\t%0" - [(set_attr "type" "jump") - (set_attr "mode" "none") - (set_attr "length" "1")]) - -(define_expand "tablejump_internal3" - [(parallel [(set (pc) - (plus:SI (match_operand:SI 0 "register_operand" "d") - (label_ref:SI (match_operand:SI 1 "" "")))) - (use (label_ref:SI (match_dup 1)))])] - "" - "") - -(define_expand "tablejump_mips161" - [(set (pc) (plus:SI (sign_extend:SI - (match_operand:HI 0 "register_operand" "d")) - (label_ref:SI (match_operand:SI 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_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:SI 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_insn (gen_tablejump_internal2 (t3, operands[1])); - DONE; - } -}") - -;;; Make sure that this only matches the insn before ADDR_DIFF_VEC. Otherwise -;;; it is not valid. ??? With the USE, the condition tests may not be required -;;; any longer. - -;;; ??? The length depends on the ABI. It is two for o32, and one for n32. -;;; We just use the conservative number here. - -(define_insn "" - [(set (pc) - (plus:SI (match_operand:SI 0 "register_operand" "d") - (label_ref:SI (match_operand:SI 1 "" "")))) - (use (label_ref:SI (match_dup 1)))] - "!(Pmode == DImode) && next_active_insn (insn) != 0 - && GET_CODE (PATTERN (next_active_insn (insn))) == ADDR_DIFF_VEC - && PREV_INSN (next_active_insn (insn)) == operands[1]" - "* -{ - /* .cpadd expands to add REG,REG,$gp when pic, and nothing when not pic. */ - if (mips_abi == ABI_32 || mips_abi == ABI_O64) - output_asm_insn (\".cpadd\\t%0\", operands); - return \"%*j\\t%0\"; -}" - [(set_attr "type" "jump") - (set_attr "mode" "none") - (set_attr "length" "2")]) - -(define_expand "tablejump_internal4" - [(parallel [(set (pc) - (plus:DI (match_operand:DI 0 "se_register_operand" "d") - (label_ref:DI (match_operand:SI 1 "" "")))) - (use (label_ref:DI (match_dup 1)))])] - "" - "") - -;;; Make sure that this only matches the insn before ADDR_DIFF_VEC. Otherwise -;;; it is not valid. ??? With the USE, the condition tests may not be required -;;; any longer. - -(define_insn "" - [(set (pc) - (plus:DI (match_operand:DI 0 "se_register_operand" "d") - (label_ref:DI (match_operand:SI 1 "" "")))) - (use (label_ref:DI (match_dup 1)))] - "Pmode == DImode && next_active_insn (insn) != 0 - && GET_CODE (PATTERN (next_active_insn (insn))) == ADDR_DIFF_VEC - && PREV_INSN (next_active_insn (insn)) == operands[1]" - "%*j\\t%0" - [(set_attr "type" "jump") - (set_attr "mode" "none") - (set_attr "length" "1")]) - -;; 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" "d") - (match_operand:SI 1 "arith_operand" "dI"))) - (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" - " -{ - /* We need slightly different code for eight byte table entries. */ - if (Pmode == DImode) - abort (); - - if (operands[0]) - { - rtx reg = gen_reg_rtx (SImode); - - /* If the index is too large, go to the default label. */ - emit_insn (gen_subsi3 (reg, operands[0], operands[1])); - emit_insn (gen_cmpsi (reg, operands[2])); - emit_insn (gen_bgtu (operands[4])); - - /* Do the PIC jump. */ - emit_insn (gen_casesi_internal (reg, operands[3], gen_reg_rtx (SImode))); - - 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" - "* -{ - output_asm_insn (\"%(bal\\t%S1\;sll\\t%0,2\\n%S1:\", operands); - output_asm_insn (\"addu\\t%0,%0,$31%)\", operands); - output_asm_insn (\"lw\\t%0,%1-%S1(%0)\;addu\\t%0,%0,$31\", operands); - return \"j\\t%0\"; -}" - [(set_attr "type" "jump") - (set_attr "mode" "none") - (set_attr "length" "6")]) - -;; For o32/n32/n64, we save the gp in the jmp_buf as well. While it is -;; possible to either pull it off the stack (in the o32 case) or recalculate -;; it given t9 and our target label, it takes 3 or 4 insns to do so, and -;; this is easy. - -(define_expand "builtin_setjmp_setup" - [(unspec [(match_operand 0 "register_operand" "r")] 20)] - "TARGET_ABICALLS" - " -{ - if (Pmode == DImode) - emit_insn (gen_builtin_setjmp_setup_64 (operands[0])); - else - emit_insn (gen_builtin_setjmp_setup_32 (operands[0])); - DONE; -}") - -(define_expand "builtin_setjmp_setup_32" - [(set (mem:SI (plus:SI (match_operand:SI 0 "register_operand" "r") - (const_int 12))) - (reg:SI 28))] - "TARGET_ABICALLS && ! (Pmode == DImode)" - "") - -(define_expand "builtin_setjmp_setup_64" - [(set (mem:DI (plus:DI (match_operand:DI 0 "register_operand" "r") - (const_int 24))) - (reg:DI 28))] - "TARGET_ABICALLS && Pmode == DImode" - "") - -;; For o32/n32/n64, we need to arrange for longjmp to put the -;; target address in t9 so that we can use it for loading $gp. - -(define_expand "builtin_longjmp" - [(unspec_volatile [(match_operand 0 "register_operand" "r")] 3)] - "TARGET_ABICALLS" - " -{ - /* The elements of the buffer are, in order: */ - int W = (Pmode == DImode ? 8 : 4); - rtx fp = gen_rtx_MEM (Pmode, operands[0]); - rtx lab = gen_rtx_MEM (Pmode, plus_constant (operands[0], 1*W)); - rtx stack = gen_rtx_MEM (Pmode, plus_constant (operands[0], 2*W)); - rtx gpv = gen_rtx_MEM (Pmode, plus_constant (operands[0], 3*W)); - rtx pv = gen_rtx_REG (Pmode, 25); - rtx gp = gen_rtx_REG (Pmode, 28); - - /* This bit is the same as expand_builtin_longjmp. */ - emit_move_insn (hard_frame_pointer_rtx, fp); - emit_move_insn (pv, lab); - emit_stack_restore (SAVE_NONLOCAL, stack, NULL_RTX); - emit_move_insn (gp, gpv); - emit_insn (gen_rtx_USE (VOIDmode, hard_frame_pointer_rtx)); - emit_insn (gen_rtx_USE (VOIDmode, stack_pointer_rtx)); - emit_insn (gen_rtx_USE (VOIDmode, gp)); - emit_indirect_jump (pv); - DONE; -}") - -;; .................... -;; Function prologue/epilogue -;; .................... - -(define_expand "prologue" - [(const_int 1)] - "" - " -{ - if (mips_isa >= 0) /* avoid unused code warnings */ - { - 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 -;; saved or used to pass arguments. - -(define_insn "blockage" - [(unspec_volatile [(const_int 0)] 0)] - "" - "" - [(set_attr "type" "unknown") - (set_attr "mode" "none") - (set_attr "length" "0")]) - -(define_expand "epilogue" - [(const_int 2)] - "" - " -{ - if (mips_isa >= 0) /* avoid unused code warnings */ - { - mips_expand_epilogue (); - DONE; - } -}") - -;; Trivial return. Make it look like a normal return insn as that -;; allows jump optimizations to work better . -(define_insn "return" - [(return)] - "mips_can_use_return_insn ()" - "%*j\\t$31" - [(set_attr "type" "jump") - (set_attr "mode" "none") - (set_attr "length" "1")]) - -;; Normal return. -;; We match any mode for the return address, so that this will work with -;; both 32 bit and 64 bit targets. -(define_insn "return_internal" - [(use (match_operand 0 "register_operand" "")) - (return)] - "" - "* -{ - return \"%*j\\t%0\"; -}" - [(set_attr "type" "jump") - (set_attr "mode" "none") - (set_attr "length" "1")]) - -;; 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 "" "")] 1)) - (clobber (reg:SI 31))] - "TARGET_EMBEDDED_PIC - && GET_CODE (operands[1]) == SYMBOL_REF" - "%($LF%= = . + 8\;bal\\t$LF%=\;la\\t%0,%1-$LF%=%)\;addu\\t%0,%0,$31" - [(set_attr "type" "call") - (set_attr "mode" "none") - (set_attr "length" "4")]) - - -;; .................... -;; FUNCTION CALLS -;; .................... - -;; calls.c now passes a third argument, make saber happy - -(define_expand "call" - [(parallel [(call (match_operand 0 "memory_operand" "m") - (match_operand 1 "" "i")) - (clobber (reg:SI 31)) - (use (match_operand 2 "" "")) ;; next_arg_reg - (use (match_operand 3 "" ""))])] ;; struct_value_size_rtx - "" - " -{ - rtx addr; - - if (operands[0]) /* eliminate unused code warnings */ - { - addr = XEXP (operands[0], 0); - if ((GET_CODE (addr) != REG && (!CONSTANT_ADDRESS_P (addr) || TARGET_LONG_CALLS)) - || ! call_insn_operand (addr, VOIDmode)) - XEXP (operands[0], 0) = copy_to_mode_reg (Pmode, addr); - - /* In order to pass small structures by value in registers - compatibly with the MIPS compiler, we need to shift the value - into the high part of the register. Function_arg has encoded - a PARALLEL rtx, holding a vector of adjustments to be made - as the next_arg_reg variable, so we split up the insns, - and emit them separately. */ - - if (operands[2] != (rtx)0 && GET_CODE (operands[2]) == PARALLEL) - { - rtvec adjust = XVEC (operands[2], 0); - int num = GET_NUM_ELEM (adjust); - int i; - - for (i = 0; i < num; i++) - emit_insn (RTVEC_ELT (adjust, i)); - } - - if (TARGET_MIPS16 - && mips16_hard_float - && operands[2] != 0 - && (int) GET_MODE (operands[2]) != 0) - { - if (build_mips16_call_stub (NULL_RTX, operands[0], operands[1], - (int) GET_MODE (operands[2]))) - DONE; - } - - emit_call_insn (gen_call_internal0 (operands[0], operands[1], - gen_rtx (REG, SImode, GP_REG_FIRST + 31))); - - DONE; - } -}") - -(define_expand "call_internal0" - [(parallel [(call (match_operand 0 "" "") - (match_operand 1 "" "")) - (clobber (match_operand:SI 2 "" ""))])] - "" - "") - -;; We need to recognize reg:SI 31 specially for the mips16, because we -;; don't have a constraint letter for it. - -(define_insn "" - [(call (mem (match_operand 0 "call_insn_operand" "ei")) - (match_operand 1 "" "i")) - (clobber (match_operand:SI 2 "register_operand" "=y"))] - "TARGET_MIPS16 && !TARGET_ABICALLS && !TARGET_LONG_CALLS - && GET_CODE (operands[2]) == REG && REGNO (operands[2]) == 31" - "%*jal\\t%0" - [(set_attr "type" "call") - (set_attr "mode" "none") - (set_attr "length" "2")]) - -(define_insn "call_internal1" - [(call (mem (match_operand 0 "call_insn_operand" "ri")) - (match_operand 1 "" "i")) - (clobber (match_operand:SI 2 "register_operand" "=d"))] - "!TARGET_ABICALLS && !TARGET_LONG_CALLS" - "* -{ - register rtx target = operands[0]; - - if (GET_CODE (target) == SYMBOL_REF) - return \"%*jal\\t%0\"; - else if (GET_CODE (target) == CONST_INT) - return \"%[li\\t%@,%0\\n\\t%*jal\\t%2,%@%]\"; - else - return \"%*jal\\t%2,%0\"; -}" - [(set_attr "type" "call") - (set_attr "mode" "none") - (set_attr "length" "1")]) - -(define_insn "call_internal2" - [(call (mem (match_operand 0 "call_insn_operand" "ri")) - (match_operand 1 "" "i")) - (clobber (match_operand:SI 2 "register_operand" "=d"))] - "TARGET_ABICALLS && !TARGET_LONG_CALLS" - "* -{ - register rtx target = operands[0]; - - if (GET_CODE (target) == SYMBOL_REF) - { - if (GET_MODE (target) == SImode) - return \"la\\t%^,%0\\n\\tjal\\t%2,%^\"; - else - return \"dla\\t%^,%0\\n\\tjal\\t%2,%^\"; - } - else if (GET_CODE (target) == CONST_INT) - return \"li\\t%^,%0\\n\\tjal\\t%2,%^\"; - else if (REGNO (target) != PIC_FUNCTION_ADDR_REGNUM) - return \"move\\t%^,%0\\n\\tjal\\t%2,%^\"; - else - return \"jal\\t%2,%0\"; -}" - [(set_attr "type" "call") - (set_attr "mode" "none") - (set_attr "length" "2")]) - -(define_insn "call_internal3a" - [(call (mem:SI (match_operand:SI 0 "register_operand" "r")) - (match_operand 1 "" "i")) - (clobber (match_operand:SI 2 "register_operand" "=d"))] - "!(Pmode == DImode) && !TARGET_ABICALLS && TARGET_LONG_CALLS" - "%*jal\\t%2,%0" - [(set_attr "type" "call") - (set_attr "mode" "none") - (set_attr "length" "1")]) - -(define_insn "call_internal3b" - [(call (mem:DI (match_operand:DI 0 "se_register_operand" "r")) - (match_operand 1 "" "i")) - (clobber (match_operand:SI 2 "register_operand" "=d"))] - "Pmode == DImode && !TARGET_ABICALLS && TARGET_LONG_CALLS" - "%*jal\\t%2,%0" - [(set_attr "type" "call") - (set_attr "mode" "none") - (set_attr "length" "1")]) - -(define_insn "call_internal4a" - [(call (mem:SI (match_operand:SI 0 "register_operand" "r")) - (match_operand 1 "" "i")) - (clobber (match_operand:SI 2 "register_operand" "=d"))] - "!(Pmode == DImode) && TARGET_ABICALLS && TARGET_LONG_CALLS" - "* -{ - if (REGNO (operands[0]) != PIC_FUNCTION_ADDR_REGNUM) - return \"move\\t%^,%0\\n\\tjal\\t%2,%^\"; - else - return \"jal\\t%2,%0\"; -}" - [(set_attr "type" "call") - (set_attr "mode" "none") - (set_attr "length" "2")]) - -(define_insn "call_internal4b" - [(call (mem:DI (match_operand:DI 0 "se_register_operand" "r")) - (match_operand 1 "" "i")) - (clobber (match_operand:SI 2 "register_operand" "=d"))] - "Pmode == DImode && TARGET_ABICALLS && TARGET_LONG_CALLS" - "* -{ - if (REGNO (operands[0]) != PIC_FUNCTION_ADDR_REGNUM) - return \"move\\t%^,%0\\n\\tjal\\t%2,%^\"; - else - return \"jal\\t%2,%0\"; -}" - [(set_attr "type" "call") - (set_attr "mode" "none") - (set_attr "length" "2")]) - -;; calls.c now passes a fourth argument, make saber happy - -(define_expand "call_value" - [(parallel [(set (match_operand 0 "register_operand" "=df") - (call (match_operand 1 "memory_operand" "m") - (match_operand 2 "" "i"))) - (clobber (reg:SI 31)) - (use (match_operand 3 "" ""))])] ;; next_arg_reg - "" - " -{ - rtx addr; - - if (operands[0]) /* eliminate unused code warning */ - { - addr = XEXP (operands[1], 0); - if ((GET_CODE (addr) != REG && (!CONSTANT_ADDRESS_P (addr) || TARGET_LONG_CALLS)) - || ! call_insn_operand (addr, VOIDmode)) - XEXP (operands[1], 0) = copy_to_mode_reg (Pmode, addr); - - /* In order to pass small structures by value in registers - compatibly with the MIPS compiler, we need to shift the value - into the high part of the register. Function_arg has encoded - a PARALLEL rtx, holding a vector of adjustments to be made - as the next_arg_reg variable, so we split up the insns, - and emit them separately. */ - - if (operands[3] != (rtx)0 && GET_CODE (operands[3]) == PARALLEL) - { - rtvec adjust = XVEC (operands[3], 0); - int num = GET_NUM_ELEM (adjust); - int i; - - for (i = 0; i < num; i++) - emit_insn (RTVEC_ELT (adjust, i)); - } - - if (TARGET_MIPS16 - && mips16_hard_float - && ((operands[3] != 0 - && (int) GET_MODE (operands[3]) != 0) - || GET_MODE_CLASS (GET_MODE (operands[0])) == MODE_FLOAT)) - { - if (build_mips16_call_stub (operands[0], operands[1], operands[2], - (operands[3] == 0 ? 0 - : (int) GET_MODE (operands[3])))) - DONE; - } - - /* Handle Irix6 function calls that have multiple non-contiguous - results. */ - if (GET_CODE (operands[0]) == PARALLEL && XVECLEN (operands[0], 0) > 1) - { - emit_call_insn (gen_call_value_multiple_internal0 - (XEXP (XVECEXP (operands[0], 0, 0), 0), - operands[1], operands[2], - XEXP (XVECEXP (operands[0], 0, 1), 0), - gen_rtx (REG, SImode, GP_REG_FIRST + 31))); - DONE; - } - - /* We have a call returning a DImode structure in an FP reg. - Strip off the now unnecessary PARALLEL. */ - if (GET_CODE (operands[0]) == PARALLEL) - operands[0] = XEXP (XVECEXP (operands[0], 0, 0), 0); - - emit_call_insn (gen_call_value_internal0 (operands[0], operands[1], operands[2], - gen_rtx (REG, SImode, GP_REG_FIRST + 31))); - - DONE; - } -}") - -(define_expand "call_value_internal0" - [(parallel [(set (match_operand 0 "" "") - (call (match_operand 1 "" "") - (match_operand 2 "" ""))) - (clobber (match_operand:SI 3 "" ""))])] - "" - "") - -;; Recognize $31 specially on the mips16, because we don't have a -;; constraint letter for it. - -(define_insn "" - [(set (match_operand 0 "register_operand" "=d") - (call (mem (match_operand 1 "call_insn_operand" "ei")) - (match_operand 2 "" "i"))) - (clobber (match_operand:SI 3 "register_operand" "=y"))] - "TARGET_MIPS16 && !TARGET_ABICALLS && !TARGET_LONG_CALLS - && GET_CODE (operands[3]) == REG && REGNO (operands[3]) == 31" - "%*jal\\t%1" - [(set_attr "type" "call") - (set_attr "mode" "none") - (set_attr "length" "2")]) - -(define_insn "call_value_internal1" - [(set (match_operand 0 "register_operand" "=df") - (call (mem (match_operand 1 "call_insn_operand" "ri")) - (match_operand 2 "" "i"))) - (clobber (match_operand:SI 3 "register_operand" "=d"))] - "!TARGET_ABICALLS && !TARGET_LONG_CALLS" - "* -{ - register rtx target = operands[1]; - - if (GET_CODE (target) == SYMBOL_REF) - return \"%*jal\\t%1\"; - else if (GET_CODE (target) == CONST_INT) - return \"%[li\\t%@,%1\\n\\t%*jal\\t%3,%@%]\"; - else - return \"%*jal\\t%3,%1\"; -}" - [(set_attr "type" "call") - (set_attr "mode" "none") - (set_attr "length" "1")]) - -(define_insn "call_value_internal2" - [(set (match_operand 0 "register_operand" "=df") - (call (mem (match_operand 1 "call_insn_operand" "ri")) - (match_operand 2 "" "i"))) - (clobber (match_operand:SI 3 "register_operand" "=d"))] - "TARGET_ABICALLS && !TARGET_LONG_CALLS" - "* -{ - register rtx target = operands[1]; - - if (GET_CODE (target) == SYMBOL_REF) - { - if (GET_MODE (target) == SImode) - return \"la\\t%^,%1\\n\\tjal\\t%3,%^\"; - else - return \"dla\\t%^,%1\\n\\tjal\\t%3,%^\"; - } - else if (GET_CODE (target) == CONST_INT) - return \"li\\t%^,%1\\n\\tjal\\t%3,%^\"; - else if (REGNO (target) != PIC_FUNCTION_ADDR_REGNUM) - return \"move\\t%^,%1\\n\\tjal\\t%3,%^\"; - else - return \"jal\\t%3,%1\"; -}" - [(set_attr "type" "call") - (set_attr "mode" "none") - (set_attr "length" "2")]) - -(define_insn "call_value_internal3a" - [(set (match_operand 0 "register_operand" "=df") - (call (mem:SI (match_operand:SI 1 "register_operand" "r")) - (match_operand 2 "" "i"))) - (clobber (match_operand:SI 3 "register_operand" "=d"))] - "!TARGET_MIPS16 - && !(Pmode == DImode) && !TARGET_ABICALLS && TARGET_LONG_CALLS" - "%*jal\\t%3,%1" - [(set_attr "type" "call") - (set_attr "mode" "none") - (set_attr "length" "1")]) - -(define_insn "call_value_internal3b" - [(set (match_operand 0 "register_operand" "=df") - (call (mem:DI (match_operand:DI 1 "se_register_operand" "r")) - (match_operand 2 "" "i"))) - (clobber (match_operand:SI 3 "register_operand" "=d"))] - "!TARGET_MIPS16 - && Pmode == DImode && !TARGET_ABICALLS && TARGET_LONG_CALLS" - "%*jal\\t%3,%1" - [(set_attr "type" "call") - (set_attr "mode" "none") - (set_attr "length" "1")]) - -(define_insn "call_value_internal3c" - [(set (match_operand 0 "register_operand" "=df") - (call (mem:SI (match_operand:SI 1 "register_operand" "e")) - (match_operand 2 "" "i"))) - (clobber (match_operand:SI 3 "register_operand" "=y"))] - "TARGET_MIPS16 && !(Pmode == DImode) && !TARGET_ABICALLS && TARGET_LONG_CALLS - && GET_CODE (operands[3]) == REG && REGNO (operands[3]) == 31" - "%*jal\\t%3,%1" - [(set_attr "type" "call") - (set_attr "mode" "none") - (set_attr "length" "1")]) - -(define_insn "call_value_internal4a" - [(set (match_operand 0 "register_operand" "=df") - (call (mem:SI (match_operand:SI 1 "register_operand" "r")) - (match_operand 2 "" "i"))) - (clobber (match_operand:SI 3 "register_operand" "=d"))] - "!(Pmode == DImode) && TARGET_ABICALLS && TARGET_LONG_CALLS" - "* -{ - if (REGNO (operands[1]) != PIC_FUNCTION_ADDR_REGNUM) - return \"move\\t%^,%1\\n\\tjal\\t%3,%^\"; - else - return \"jal\\t%3,%1\"; -}" - [(set_attr "type" "call") - (set_attr "mode" "none") - (set_attr "length" "2")]) - -(define_insn "call_value_internal4b" - [(set (match_operand 0 "register_operand" "=df") - (call (mem:DI (match_operand:DI 1 "se_register_operand" "r")) - (match_operand 2 "" "i"))) - (clobber (match_operand:SI 3 "register_operand" "=d"))] - "Pmode == DImode && TARGET_ABICALLS && TARGET_LONG_CALLS" - "* -{ - if (REGNO (operands[1]) != PIC_FUNCTION_ADDR_REGNUM) - return \"move\\t%^,%1\\n\\tjal\\t%3,%^\"; - else - return \"jal\\t%3,%1\"; -}" - [(set_attr "type" "call") - (set_attr "mode" "none") - (set_attr "length" "2")]) - -(define_expand "call_value_multiple_internal0" - [(parallel [(set (match_operand 0 "" "") - (call (match_operand 1 "" "") - (match_operand 2 "" ""))) - (set (match_operand 3 "" "") - (call (match_dup 1) - (match_dup 2))) - (clobber (match_operand:SI 4 "" ""))])] - "" - "") - -;; ??? May eventually need all 6 versions of the call patterns with multiple -;; return values. - -(define_insn "call_value_multiple_internal2" - [(set (match_operand 0 "register_operand" "=df") - (call (mem (match_operand 1 "call_insn_operand" "ri")) - (match_operand 2 "" "i"))) - (set (match_operand 3 "register_operand" "=df") - (call (mem (match_dup 1)) - (match_dup 2))) - (clobber (match_operand:SI 4 "register_operand" "=d"))] - "TARGET_ABICALLS && !TARGET_LONG_CALLS" - "* -{ - register rtx target = operands[1]; - - if (GET_CODE (target) == SYMBOL_REF) - { - if (GET_MODE (target) == SImode) - return \"la\\t%^,%1\\n\\tjal\\t%4,%^\"; - else - return \"la\\t%^,%1\\n\\tjal\\t%4,%^\"; - } - else if (GET_CODE (target) == CONST_INT) - return \"li\\t%^,%1\\n\\tjal\\t%4,%^\"; - else if (REGNO (target) != PIC_FUNCTION_ADDR_REGNUM) - return \"move\\t%^,%1\\n\\tjal\\t%4,%^\"; - else - return \"jal\\t%4,%1\"; -}" - [(set_attr "type" "call") - (set_attr "mode" "none") - (set_attr "length" "2")]) - - -;; Call subroutine returning any type. - -(define_expand "untyped_call" - [(parallel [(call (match_operand 0 "" "") - (const_int 0)) - (match_operand 1 "" "") - (match_operand 2 "" "")])] - "" - " -{ - if (operands[0]) /* silence statement not reached warnings */ - { - int i; - - emit_call_insn (gen_call (operands[0], const0_rtx, NULL, const0_rtx)); - - for (i = 0; i < XVECLEN (operands[2], 0); i++) - { - rtx set = XVECEXP (operands[2], 0, i); - emit_move_insn (SET_DEST (set), SET_SRC (set)); - } - - emit_insn (gen_blockage ()); - DONE; - } -}") - -;; .................... -;; MISC. -;; .................... - -(define_insn "nop" - [(const_int 0)] - "" - "%(nop%)" - [(set_attr "type" "nop") - (set_attr "mode" "none") - (set_attr "length" "1")]) - -;; 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 */ -;; }") - -;; 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_operand:SI 2 "reg_or_0_operand" "dJ,0") - (match_operand:SI 3 "reg_or_0_operand" "0,dJ")))] - "mips_isa >= 4 || 0" ;; CYGNUS LOCAL law - "@ - mov%B4\\t%0,%z2,%1 - mov%b4\\t%0,%z3,%1" - [(set_attr "type" "move") - (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 "se_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")))] - "mips_isa >= 4 || 0" ;; CYGNUS LOCAL law - "@ - mov%B4\\t%0,%z2,%1 - mov%b4\\t%0,%z3,%1" - [(set_attr "type" "move") - (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_operand:SI 1 "reg_or_0_operand" "dJ,0") - (match_operand:SI 2 "reg_or_0_operand" "0,dJ")))] - "mips_isa >= 4 && TARGET_HARD_FLOAT" - "@ - mov%T3\\t%0,%z1,%4 - mov%t3\\t%0,%z2,%4" - [(set_attr "type" "move") - (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_operand:DI 2 "se_reg_or_0_operand" "dJ,0") - (match_operand:DI 3 "se_reg_or_0_operand" "0,dJ")))] - "mips_isa >= 4 || 0" ;; CYGNUS LOCAL law - "@ - mov%B4\\t%0,%z2,%1 - mov%b4\\t%0,%z3,%1" - [(set_attr "type" "move") - (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 "se_register_operand" "d,d") - (const_int 0)]) - (match_operand:DI 2 "se_reg_or_0_operand" "dJ,0") - (match_operand:DI 3 "se_reg_or_0_operand" "0,dJ")))] - "mips_isa >= 4 || 0" ;; CYGNUS LOCAL law - "@ - mov%B4\\t%0,%z2,%1 - mov%b4\\t%0,%z3,%1" - [(set_attr "type" "move") - (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_operand:DI 1 "se_reg_or_0_operand" "dJ,0") - (match_operand:DI 2 "se_reg_or_0_operand" "0,dJ")))] - "mips_isa >= 4 && TARGET_HARD_FLOAT" - "@ - mov%T3\\t%0,%z1,%4 - mov%t3\\t%0,%z2,%4" - [(set_attr "type" "move") - (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_operand:SF 2 "register_operand" "f,0") - (match_operand:SF 3 "register_operand" "0,f")))] - "mips_isa >= 4 && TARGET_HARD_FLOAT" - "@ - mov%B4.s\\t%0,%2,%1 - mov%b4.s\\t%0,%3,%1" - [(set_attr "type" "move") - (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_operand:SF 1 "register_operand" "f,0") - (match_operand:SF 2 "register_operand" "0,f")))] - "mips_isa >= 4 && TARGET_HARD_FLOAT" - "@ - mov%T3.s\\t%0,%1,%4 - mov%t3.s\\t%0,%2,%4" - [(set_attr "type" "move") - (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_operand:DF 2 "register_operand" "f,0") - (match_operand:DF 3 "register_operand" "0,f")))] - "mips_isa >= 4 && TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT" - "@ - mov%B4.d\\t%0,%2,%1 - mov%b4.d\\t%0,%3,%1" - [(set_attr "type" "move") - (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_operand:DF 1 "register_operand" "f,0") - (match_operand:DF 2 "register_operand" "0,f")))] - "mips_isa >= 4 && TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT" - "@ - mov%T3.d\\t%0,%1,%4 - mov%t3.d\\t%0,%2,%4" - [(set_attr "type" "move") - (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" "") - (if_then_else:SI (match_dup 5) - (match_operand:SI 2 "reg_or_0_operand" "") - (match_operand:SI 3 "reg_or_0_operand" "")))] - "mips_isa >= 4 || 0" ;; CYGNUS LOCAL law - " -{ - - gen_conditional_move (operands); - DONE; -}") - -(define_expand "movdicc" - [(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 "se_reg_or_0_operand" "") - (match_operand:DI 3 "se_reg_or_0_operand" "")))] - "mips_isa >= 4 || 0" ;; CYGNUS LOCAL law - " -{ - - gen_conditional_move (operands); - DONE; -}") - -(define_expand "movsfcc" - [(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" "")))] - "mips_isa >= 4 && 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" "") - (if_then_else:DF (match_dup 5) - (match_operand:DF 2 "register_operand" "") - (match_operand:DF 3 "register_operand" "")))] - "mips_isa >= 4 && TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT" - " -{ - gen_conditional_move (operands); - DONE; -}") - -;; .................... -;; mips16 inline constant tables -;; .................... - -(define_insn "consttable_qi" - [(unspec_volatile [(match_operand:QI 0 "consttable_operand" "=g")] 10)] - "TARGET_MIPS16" - "* -{ - assemble_integer (operands[0], 1, 1); - return \"\"; -}" - [(set_attr "type" "unknown") - (set_attr "mode" "QI") - (set_attr "length" "2")]) - -(define_insn "consttable_hi" - [(unspec_volatile [(match_operand:HI 0 "consttable_operand" "=g")] 11)] - "TARGET_MIPS16" - "* -{ - assemble_integer (operands[0], 2, 1); - return \"\"; -}" - [(set_attr "type" "unknown") - (set_attr "mode" "HI") - (set_attr "length" "2")]) - -(define_insn "consttable_si" - [(unspec_volatile [(match_operand:SI 0 "consttable_operand" "=g")] 12)] - "TARGET_MIPS16" - "* -{ - assemble_integer (operands[0], 4, 1); - return \"\"; -}" - [(set_attr "type" "unknown") - (set_attr "mode" "SI") - (set_attr "length" "2")]) - -(define_insn "consttable_di" - [(unspec_volatile [(match_operand:DI 0 "consttable_operand" "=g")] 13)] - "TARGET_MIPS16" - "* -{ - assemble_integer (operands[0], 8, 1); - return \"\"; -}" - [(set_attr "type" "unknown") - (set_attr "mode" "DI") - (set_attr "length" "4")]) - -(define_insn "consttable_sf" - [(unspec_volatile [(match_operand:SF 0 "consttable_operand" "=g")] 14)] - "TARGET_MIPS16" - "* -{ - union real_extract u; - - if (GET_CODE (operands[0]) != CONST_DOUBLE) - abort (); - bcopy ((char *) &CONST_DOUBLE_LOW (operands[0]), (char *) &u, sizeof u); - assemble_real (u.d, SFmode); - return \"\"; -}" - [(set_attr "type" "unknown") - (set_attr "mode" "SF") - (set_attr "length" "2")]) - -(define_insn "consttable_df" - [(unspec_volatile [(match_operand:DF 0 "consttable_operand" "=g")] 15)] - "TARGET_MIPS16" - "* -{ - union real_extract u; - - if (GET_CODE (operands[0]) != CONST_DOUBLE) - abort (); - bcopy ((char *) &CONST_DOUBLE_LOW (operands[0]), (char *) &u, sizeof u); - assemble_real (u.d, DFmode); - return \"\"; -}" - [(set_attr "type" "unknown") - (set_attr "mode" "DF") - (set_attr "length" "4")]) - -(define_insn "align_2" - [(unspec_volatile [(const_int 0)] 16)] - "TARGET_MIPS16" - ".align 1" - [(set_attr "type" "unknown") - (set_attr "mode" "HI") - (set_attr "length" "2")]) - -(define_insn "align_4" - [(unspec_volatile [(const_int 0)] 17)] - "TARGET_MIPS16" - ".align 2" - [(set_attr "type" "unknown") - (set_attr "mode" "SI") - (set_attr "length" "2")]) - -(define_insn "align_8" - [(unspec_volatile [(const_int 0)] 18)] - "TARGET_MIPS16" - ".align 3" - [(set_attr "type" "unknown") - (set_attr "mode" "DI") - (set_attr "length" "3")]) - -;; .................... -;; 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" "2")]) - -(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" "2")]) - -;; 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" "2")]) - -(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" "2")]) |