1169689Skan;;  Mips.md	     Machine Description for MIPS based processors
2169689Skan;;  Copyright (C) 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
3169689Skan;;  1999, 2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
4169689Skan;;  Contributed by   A. Lichnewsky, lich@inria.inria.fr
5169689Skan;;  Changes by       Michael Meissner, meissner@osf.org
6169689Skan;;  64 bit r4000 support by Ian Lance Taylor, ian@cygnus.com, and
7169689Skan;;  Brendan Eich, brendan@microunity.com.
8169689Skan
9169689Skan;; This file is part of GCC.
10169689Skan
11169689Skan;; GCC is free software; you can redistribute it and/or modify
12169689Skan;; it under the terms of the GNU General Public License as published by
13169689Skan;; the Free Software Foundation; either version 2, or (at your option)
14169689Skan;; any later version.
15169689Skan
16169689Skan;; GCC is distributed in the hope that it will be useful,
17169689Skan;; but WITHOUT ANY WARRANTY; without even the implied warranty of
18169689Skan;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19169689Skan;; GNU General Public License for more details.
20169689Skan
21169689Skan;; You should have received a copy of the GNU General Public License
22169689Skan;; along with GCC; see the file COPYING.  If not, write to
23169689Skan;; the Free Software Foundation, 51 Franklin Street, Fifth Floor,
24169689Skan;; Boston, MA 02110-1301, USA.
25169689Skan
26169689Skan(define_constants
27169689Skan  [(UNSPEC_LOAD_DF_LOW		 0)
28169689Skan   (UNSPEC_LOAD_DF_HIGH		 1)
29169689Skan   (UNSPEC_STORE_DF_HIGH	 2)
30169689Skan   (UNSPEC_GET_FNADDR		 3)
31169689Skan   (UNSPEC_BLOCKAGE		 4)
32169689Skan   (UNSPEC_CPRESTORE		 5)
33169689Skan   (UNSPEC_EH_RECEIVER		 6)
34169689Skan   (UNSPEC_EH_RETURN		 7)
35169689Skan   (UNSPEC_CONSTTABLE_INT	 8)
36169689Skan   (UNSPEC_CONSTTABLE_FLOAT	 9)
37169689Skan   (UNSPEC_ALIGN		14)
38169689Skan   (UNSPEC_HIGH			17)
39169689Skan   (UNSPEC_LOAD_LEFT		18)
40169689Skan   (UNSPEC_LOAD_RIGHT		19)
41169689Skan   (UNSPEC_STORE_LEFT		20)
42169689Skan   (UNSPEC_STORE_RIGHT		21)
43169689Skan   (UNSPEC_LOADGP		22)
44169689Skan   (UNSPEC_LOAD_CALL		23)
45169689Skan   (UNSPEC_LOAD_GOT		24)
46169689Skan   (UNSPEC_GP			25)
47169689Skan   (UNSPEC_MFHILO		26)
48169689Skan   (UNSPEC_TLS_LDM		27)
49169689Skan   (UNSPEC_TLS_GET_TP		28)
50169689Skan
51169689Skan   (UNSPEC_ADDRESS_FIRST	100)
52169689Skan
53169689Skan   (FAKE_CALL_REGNO		79)
54169689Skan
55169689Skan   ;; For MIPS Paired-Singled Floating Point Instructions.
56169689Skan
57169689Skan   (UNSPEC_MOVE_TF_PS		200)
58169689Skan   (UNSPEC_C			201)
59169689Skan
60169689Skan   ;; MIPS64/MIPS32R2 alnv.ps
61169689Skan   (UNSPEC_ALNV_PS		202)
62169689Skan
63169689Skan   ;; MIPS-3D instructions
64169689Skan   (UNSPEC_CABS			203)
65169689Skan
66169689Skan   (UNSPEC_ADDR_PS		204)
67169689Skan   (UNSPEC_CVT_PW_PS		205)
68169689Skan   (UNSPEC_CVT_PS_PW		206)
69169689Skan   (UNSPEC_MULR_PS		207)
70169689Skan   (UNSPEC_ABS_PS		208)
71169689Skan
72169689Skan   (UNSPEC_RSQRT1		209)
73169689Skan   (UNSPEC_RSQRT2		210)
74169689Skan   (UNSPEC_RECIP1		211)
75169689Skan   (UNSPEC_RECIP2		212)
76169689Skan   (UNSPEC_SINGLE_CC		213)
77169689Skan   (UNSPEC_SCC			214)
78169689Skan
79169689Skan   ;; MIPS DSP ASE Revision 0.98 3/24/2005
80169689Skan   (UNSPEC_ADDQ			300)
81169689Skan   (UNSPEC_ADDQ_S		301)
82169689Skan   (UNSPEC_SUBQ			302)
83169689Skan   (UNSPEC_SUBQ_S		303)
84169689Skan   (UNSPEC_ADDSC		304)
85169689Skan   (UNSPEC_ADDWC		305)
86169689Skan   (UNSPEC_MODSUB		306)
87169689Skan   (UNSPEC_RADDU_W_QB		307)
88169689Skan   (UNSPEC_ABSQ_S		308)
89169689Skan   (UNSPEC_PRECRQ_QB_PH		309)
90169689Skan   (UNSPEC_PRECRQ_PH_W		310)
91169689Skan   (UNSPEC_PRECRQ_RS_PH_W	311)
92169689Skan   (UNSPEC_PRECRQU_S_QB_PH	312)
93169689Skan   (UNSPEC_PRECEQ_W_PHL		313)
94169689Skan   (UNSPEC_PRECEQ_W_PHR		314)
95169689Skan   (UNSPEC_PRECEQU_PH_QBL	315)
96169689Skan   (UNSPEC_PRECEQU_PH_QBR	316)
97169689Skan   (UNSPEC_PRECEQU_PH_QBLA	317)
98169689Skan   (UNSPEC_PRECEQU_PH_QBRA	318)
99169689Skan   (UNSPEC_PRECEU_PH_QBL	319)
100169689Skan   (UNSPEC_PRECEU_PH_QBR	320)
101169689Skan   (UNSPEC_PRECEU_PH_QBLA	321)
102169689Skan   (UNSPEC_PRECEU_PH_QBRA	322)
103169689Skan   (UNSPEC_SHLL			323)
104169689Skan   (UNSPEC_SHLL_S		324)
105169689Skan   (UNSPEC_SHRL_QB		325)
106169689Skan   (UNSPEC_SHRA_PH		326)
107169689Skan   (UNSPEC_SHRA_R		327)
108169689Skan   (UNSPEC_MULEU_S_PH_QBL	328)
109169689Skan   (UNSPEC_MULEU_S_PH_QBR	329)
110169689Skan   (UNSPEC_MULQ_RS_PH		330)
111169689Skan   (UNSPEC_MULEQ_S_W_PHL	331)
112169689Skan   (UNSPEC_MULEQ_S_W_PHR	332)
113169689Skan   (UNSPEC_DPAU_H_QBL		333)
114169689Skan   (UNSPEC_DPAU_H_QBR		334)
115169689Skan   (UNSPEC_DPSU_H_QBL		335)
116169689Skan   (UNSPEC_DPSU_H_QBR		336)
117169689Skan   (UNSPEC_DPAQ_S_W_PH		337)
118169689Skan   (UNSPEC_DPSQ_S_W_PH		338)
119169689Skan   (UNSPEC_MULSAQ_S_W_PH	339)
120169689Skan   (UNSPEC_DPAQ_SA_L_W		340)
121169689Skan   (UNSPEC_DPSQ_SA_L_W		341)
122169689Skan   (UNSPEC_MAQ_S_W_PHL		342)
123169689Skan   (UNSPEC_MAQ_S_W_PHR		343)
124169689Skan   (UNSPEC_MAQ_SA_W_PHL		344)
125169689Skan   (UNSPEC_MAQ_SA_W_PHR		345)
126169689Skan   (UNSPEC_BITREV		346)
127169689Skan   (UNSPEC_INSV			347)
128169689Skan   (UNSPEC_REPL_QB		348)
129169689Skan   (UNSPEC_REPL_PH		349)
130169689Skan   (UNSPEC_CMP_EQ		350)
131169689Skan   (UNSPEC_CMP_LT		351)
132169689Skan   (UNSPEC_CMP_LE		352)
133169689Skan   (UNSPEC_CMPGU_EQ_QB		353)
134169689Skan   (UNSPEC_CMPGU_LT_QB		354)
135169689Skan   (UNSPEC_CMPGU_LE_QB		355)
136169689Skan   (UNSPEC_PICK			356)
137169689Skan   (UNSPEC_PACKRL_PH		357)
138169689Skan   (UNSPEC_EXTR_W		358)
139169689Skan   (UNSPEC_EXTR_R_W		359)
140169689Skan   (UNSPEC_EXTR_RS_W		360)
141169689Skan   (UNSPEC_EXTR_S_H		361)
142169689Skan   (UNSPEC_EXTP			362)
143169689Skan   (UNSPEC_EXTPDP		363)
144169689Skan   (UNSPEC_SHILO		364)
145169689Skan   (UNSPEC_MTHLIP		365)
146169689Skan   (UNSPEC_WRDSP		366)
147169689Skan   (UNSPEC_RDDSP		367)
148169689Skan  ]
149169689Skan)
150169689Skan
151169689Skan(include "predicates.md")
152169689Skan(include "constraints.md")
153169689Skan
154169689Skan;; ....................
155169689Skan;;
156169689Skan;;	Attributes
157169689Skan;;
158169689Skan;; ....................
159169689Skan
160169689Skan(define_attr "got" "unset,xgot_high,load"
161169689Skan  (const_string "unset"))
162169689Skan
163169689Skan;; For jal instructions, this attribute is DIRECT when the target address
164169689Skan;; is symbolic and INDIRECT when it is a register.
165169689Skan(define_attr "jal" "unset,direct,indirect"
166169689Skan  (const_string "unset"))
167169689Skan
168169689Skan;; This attribute is YES if the instruction is a jal macro (not a
169169689Skan;; real jal instruction).
170169689Skan;;
171169689Skan;; jal is always a macro for o32 and o64 abicalls because it includes an
172169689Skan;; instruction to restore $gp.  Direct jals are also macros for -mshared
173169689Skan;; abicalls because they first load the target address into $25.
174169689Skan(define_attr "jal_macro" "no,yes"
175169689Skan  (cond [(eq_attr "jal" "direct")
176169689Skan	 (symbol_ref "TARGET_ABICALLS
177169689Skan		      && (TARGET_OLDABI || !TARGET_ABSOLUTE_ABICALLS)")
178169689Skan	 (eq_attr "jal" "indirect")
179169689Skan	 (symbol_ref "TARGET_ABICALLS && TARGET_OLDABI")]
180169689Skan	(const_string "no")))
181169689Skan
182169689Skan;; Classification of each insn.
183169689Skan;; branch	conditional branch
184169689Skan;; jump		unconditional jump
185169689Skan;; call		unconditional call
186169689Skan;; load		load instruction(s)
187169689Skan;; fpload	floating point load
188169689Skan;; fpidxload    floating point indexed load
189169689Skan;; store	store instruction(s)
190169689Skan;; fpstore	floating point store
191169689Skan;; fpidxstore	floating point indexed store
192169689Skan;; prefetch	memory prefetch (register + offset)
193169689Skan;; prefetchx	memory indexed prefetch (register + register)
194169689Skan;; condmove	conditional moves
195169689Skan;; xfer		transfer to/from coprocessor
196169689Skan;; mthilo	transfer to hi/lo registers
197169689Skan;; mfhilo	transfer from hi/lo registers
198169689Skan;; const	load constant
199169689Skan;; arith	integer arithmetic and logical instructions
200169689Skan;; shift	integer shift instructions
201169689Skan;; slt		set less than instructions
202169689Skan;; clz		the clz and clo instructions
203169689Skan;; trap		trap if instructions
204169689Skan;; imul		integer multiply 2 operands
205169689Skan;; imul3	integer multiply 3 operands
206169689Skan;; imadd	integer multiply-add
207169689Skan;; idiv		integer divide
208169689Skan;; fmove	floating point register move
209169689Skan;; fadd		floating point add/subtract
210169689Skan;; fmul		floating point multiply
211169689Skan;; fmadd	floating point multiply-add
212169689Skan;; fdiv		floating point divide
213169689Skan;; frdiv	floating point reciprocal divide
214169689Skan;; frdiv1	floating point reciprocal divide step 1
215169689Skan;; frdiv2	floating point reciprocal divide step 2
216169689Skan;; fabs		floating point absolute value
217169689Skan;; fneg		floating point negation
218169689Skan;; fcmp		floating point compare
219169689Skan;; fcvt		floating point convert
220169689Skan;; fsqrt	floating point square root
221169689Skan;; frsqrt       floating point reciprocal square root
222169689Skan;; frsqrt1      floating point reciprocal square root step1
223169689Skan;; frsqrt2      floating point reciprocal square root step2
224169689Skan;; multi	multiword sequence (or user asm statements)
225169689Skan;; nop		no operation
226169689Skan(define_attr "type"
227169689Skan  "unknown,branch,jump,call,load,fpload,fpidxload,store,fpstore,fpidxstore,prefetch,prefetchx,condmove,xfer,mthilo,mfhilo,const,arith,shift,slt,clz,trap,imul,imul3,imadd,idiv,fmove,fadd,fmul,fmadd,fdiv,frdiv,frdiv1,frdiv2,fabs,fneg,fcmp,fcvt,fsqrt,frsqrt,frsqrt1,frsqrt2,multi,nop"
228169689Skan  (cond [(eq_attr "jal" "!unset") (const_string "call")
229169689Skan	 (eq_attr "got" "load") (const_string "load")]
230169689Skan	(const_string "unknown")))
231169689Skan
232169689Skan;; Main data type used by the insn
233169689Skan(define_attr "mode" "unknown,none,QI,HI,SI,DI,SF,DF,FPSW"
234169689Skan  (const_string "unknown"))
235169689Skan
236169689Skan;; Mode for conversion types (fcvt)
237169689Skan;; I2S          integer to float single (SI/DI to SF)
238169689Skan;; I2D          integer to float double (SI/DI to DF)
239169689Skan;; S2I          float to integer (SF to SI/DI)
240169689Skan;; D2I          float to integer (DF to SI/DI)
241169689Skan;; D2S          double to float single
242169689Skan;; S2D          float single to double
243169689Skan
244169689Skan(define_attr "cnv_mode" "unknown,I2S,I2D,S2I,D2I,D2S,S2D" 
245169689Skan  (const_string "unknown"))
246169689Skan
247169689Skan;; Is this an extended instruction in mips16 mode?
248169689Skan(define_attr "extended_mips16" "no,yes"
249169689Skan  (const_string "no"))
250169689Skan
251169689Skan;; Length of instruction in bytes.
252169689Skan(define_attr "length" ""
253169689Skan   (cond [;; Direct branch instructions have a range of [-0x40000,0x3fffc].
254169689Skan	  ;; If a branch is outside this range, we have a choice of two
255169689Skan	  ;; sequences.  For PIC, an out-of-range branch like:
256169689Skan	  ;;
257169689Skan	  ;;	bne	r1,r2,target
258169689Skan	  ;;	dslot
259169689Skan	  ;;
260169689Skan	  ;; becomes the equivalent of:
261169689Skan	  ;;
262169689Skan	  ;;	beq	r1,r2,1f
263169689Skan	  ;;	dslot
264169689Skan	  ;;	la	$at,target
265169689Skan	  ;;	jr	$at
266169689Skan	  ;;	nop
267169689Skan	  ;; 1:
268169689Skan	  ;;
269169689Skan	  ;; where the load address can be up to three instructions long
270169689Skan	  ;; (lw, nop, addiu).
271169689Skan	  ;;
272169689Skan	  ;; The non-PIC case is similar except that we use a direct
273169689Skan	  ;; jump instead of an la/jr pair.  Since the target of this
274169689Skan	  ;; jump is an absolute 28-bit bit address (the other bits
275169689Skan	  ;; coming from the address of the delay slot) this form cannot
276169689Skan	  ;; cross a 256MB boundary.  We could provide the option of
277169689Skan	  ;; using la/jr in this case too, but we do not do so at
278169689Skan	  ;; present.
279169689Skan	  ;;
280169689Skan	  ;; Note that this value does not account for the delay slot
281169689Skan	  ;; instruction, whose length is added separately.  If the RTL
282169689Skan	  ;; pattern has no explicit delay slot, mips_adjust_insn_length
283169689Skan	  ;; will add the length of the implicit nop.  The values for
284169689Skan	  ;; forward and backward branches will be different as well.
285169689Skan	  (eq_attr "type" "branch")
286169689Skan	  (cond [(and (le (minus (match_dup 1) (pc)) (const_int 131064))
287169689Skan                      (le (minus (pc) (match_dup 1)) (const_int 131068)))
288169689Skan                  (const_int 4)
289169689Skan		 (ne (symbol_ref "flag_pic") (const_int 0))
290169689Skan		 (const_int 24)
291169689Skan		 ] (const_int 12))
292169689Skan
293169689Skan	  (eq_attr "got" "load")
294169689Skan	  (const_int 4)
295169689Skan	  (eq_attr "got" "xgot_high")
296169689Skan	  (const_int 8)
297169689Skan
298169689Skan	  (eq_attr "type" "const")
299169689Skan	  (symbol_ref "mips_const_insns (operands[1]) * 4")
300169689Skan	  (eq_attr "type" "load,fpload")
301169689Skan	  (symbol_ref "mips_fetch_insns (operands[1]) * 4")
302169689Skan	  (eq_attr "type" "store,fpstore")
303169689Skan	  (symbol_ref "mips_fetch_insns (operands[0]) * 4")
304169689Skan
305169689Skan	  ;; In the worst case, a call macro will take 8 instructions:
306169689Skan	  ;;
307169689Skan	  ;;	 lui $25,%call_hi(FOO)
308169689Skan	  ;;	 addu $25,$25,$28
309169689Skan	  ;;     lw $25,%call_lo(FOO)($25)
310169689Skan	  ;;	 nop
311169689Skan	  ;;	 jalr $25
312169689Skan	  ;;	 nop
313169689Skan	  ;;	 lw $gp,X($sp)
314169689Skan	  ;;	 nop
315169689Skan	  (eq_attr "jal_macro" "yes")
316169689Skan	  (const_int 32)
317169689Skan
318169689Skan	  (and (eq_attr "extended_mips16" "yes")
319169689Skan	       (ne (symbol_ref "TARGET_MIPS16") (const_int 0)))
320169689Skan	  (const_int 8)
321169689Skan
322169689Skan	  ;; Various VR4120 errata require a nop to be inserted after a macc
323169689Skan	  ;; instruction.  The assembler does this for us, so account for
324169689Skan	  ;; the worst-case length here.
325169689Skan	  (and (eq_attr "type" "imadd")
326169689Skan	       (ne (symbol_ref "TARGET_FIX_VR4120") (const_int 0)))
327169689Skan	  (const_int 8)
328169689Skan
329169689Skan	  ;; VR4120 errata MD(4): if there are consecutive dmult instructions,
330169689Skan	  ;; the result of the second one is missed.  The assembler should work
331169689Skan	  ;; around this by inserting a nop after the first dmult.
332169689Skan	  (and (eq_attr "type" "imul,imul3")
333169689Skan	       (and (eq_attr "mode" "DI")
334169689Skan		    (ne (symbol_ref "TARGET_FIX_VR4120") (const_int 0))))
335169689Skan	  (const_int 8)
336169689Skan
337169689Skan	  (eq_attr "type" "idiv")
338169689Skan	  (symbol_ref "mips_idiv_insns () * 4")
339169689Skan	  ] (const_int 4)))
340169689Skan
341169689Skan;; Attribute describing the processor.  This attribute must match exactly
342169689Skan;; with the processor_type enumeration in mips.h.
343169689Skan(define_attr "cpu"
344169689Skan  "r3000,4kc,4kp,5kc,5kf,20kc,24k,24kx,m4k,r3900,r6000,r4000,r4100,r4111,r4120,r4130,r4300,r4600,r4650,r5000,r5400,r5500,r7000,r8000,r9000,sb1,sb1a,sr71000"
345169689Skan  (const (symbol_ref "mips_tune")))
346169689Skan
347169689Skan;; The type of hardware hazard associated with this instruction.
348169689Skan;; DELAY means that the next instruction cannot read the result
349169689Skan;; of this one.  HILO means that the next two instructions cannot
350169689Skan;; write to HI or LO.
351169689Skan(define_attr "hazard" "none,delay,hilo"
352169689Skan  (cond [(and (eq_attr "type" "load,fpload,fpidxload")
353169689Skan	      (ne (symbol_ref "ISA_HAS_LOAD_DELAY") (const_int 0)))
354169689Skan	 (const_string "delay")
355169689Skan
356169689Skan	 (and (eq_attr "type" "xfer")
357169689Skan	      (ne (symbol_ref "ISA_HAS_XFER_DELAY") (const_int 0)))
358169689Skan	 (const_string "delay")
359169689Skan
360169689Skan	 (and (eq_attr "type" "fcmp")
361169689Skan	      (ne (symbol_ref "ISA_HAS_FCMP_DELAY") (const_int 0)))
362169689Skan	 (const_string "delay")
363169689Skan
364169689Skan	 ;; The r4000 multiplication patterns include an mflo instruction.
365169689Skan	 (and (eq_attr "type" "imul")
366169689Skan	      (ne (symbol_ref "TARGET_FIX_R4000") (const_int 0)))
367169689Skan	 (const_string "hilo")
368169689Skan
369169689Skan	 (and (eq_attr "type" "mfhilo")
370169689Skan	      (eq (symbol_ref "ISA_HAS_HILO_INTERLOCKS") (const_int 0)))
371169689Skan	 (const_string "hilo")]
372169689Skan	(const_string "none")))
373169689Skan
374169689Skan;; Is it a single instruction?
375169689Skan(define_attr "single_insn" "no,yes"
376169689Skan  (symbol_ref "get_attr_length (insn) == (TARGET_MIPS16 ? 2 : 4)"))
377169689Skan
378169689Skan;; Can the instruction be put into a delay slot?
379169689Skan(define_attr "can_delay" "no,yes"
380169689Skan  (if_then_else (and (eq_attr "type" "!branch,call,jump")
381169689Skan		     (and (eq_attr "hazard" "none")
382169689Skan			  (eq_attr "single_insn" "yes")))
383169689Skan		(const_string "yes")
384169689Skan		(const_string "no")))
385169689Skan
386169689Skan;; Attribute defining whether or not we can use the branch-likely instructions
387169689Skan(define_attr "branch_likely" "no,yes"
388169689Skan  (const
389169689Skan   (if_then_else (ne (symbol_ref "GENERATE_BRANCHLIKELY") (const_int 0))
390169689Skan		 (const_string "yes")
391169689Skan		 (const_string "no"))))
392169689Skan
393169689Skan;; True if an instruction might assign to hi or lo when reloaded.
394169689Skan;; This is used by the TUNE_MACC_CHAINS code.
395169689Skan(define_attr "may_clobber_hilo" "no,yes"
396169689Skan  (if_then_else (eq_attr "type" "imul,imul3,imadd,idiv,mthilo")
397169689Skan		(const_string "yes")
398169689Skan		(const_string "no")))
399169689Skan
400169689Skan;; Describe a user's asm statement.
401169689Skan(define_asm_attributes
402169689Skan  [(set_attr "type" "multi")
403169689Skan   (set_attr "can_delay" "no")])
404169689Skan
405169689Skan;; This mode macro allows 32-bit and 64-bit GPR patterns to be generated
406169689Skan;; from the same template.
407169689Skan(define_mode_macro GPR [SI (DI "TARGET_64BIT")])
408169689Skan
409169689Skan;; This mode macro allows :P to be used for patterns that operate on
410169689Skan;; pointer-sized quantities.  Exactly one of the two alternatives will match.
411169689Skan(define_mode_macro P [(SI "Pmode == SImode") (DI "Pmode == DImode")])
412169689Skan
413169689Skan;; This mode macro allows :MOVECC to be used anywhere that a
414169689Skan;; conditional-move-type condition is needed.
415169689Skan(define_mode_macro MOVECC [SI (DI "TARGET_64BIT") (CC "TARGET_HARD_FLOAT")])
416169689Skan
417169689Skan;; This mode macro allows the QI and HI extension patterns to be defined from
418169689Skan;; the same template.
419169689Skan(define_mode_macro SHORT [QI HI])
420169689Skan
421169689Skan;; This mode macro allows :ANYF to be used wherever a scalar or vector
422169689Skan;; floating-point mode is allowed.
423169689Skan(define_mode_macro ANYF [(SF "TARGET_HARD_FLOAT")
424169689Skan			 (DF "TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT")
425169689Skan			 (V2SF "TARGET_PAIRED_SINGLE_FLOAT")])
426169689Skan
427169689Skan;; Like ANYF, but only applies to scalar modes.
428169689Skan(define_mode_macro SCALARF [(SF "TARGET_HARD_FLOAT")
429169689Skan			    (DF "TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT")])
430169689Skan
431169689Skan;; In GPR templates, a string like "<d>subu" will expand to "subu" in the
432169689Skan;; 32-bit version and "dsubu" in the 64-bit version.
433169689Skan(define_mode_attr d [(SI "") (DI "d")])
434169689Skan
435169689Skan;; This attribute gives the length suffix for a sign- or zero-extension
436169689Skan;; instruction.
437169689Skan(define_mode_attr size [(QI "b") (HI "h")])
438169689Skan
439169689Skan;; This attributes gives the mode mask of a SHORT.
440169689Skan(define_mode_attr mask [(QI "0x00ff") (HI "0xffff")])
441169689Skan
442169689Skan;; Mode attributes for GPR loads and stores.
443169689Skan(define_mode_attr load [(SI "lw") (DI "ld")])
444169689Skan(define_mode_attr store [(SI "sw") (DI "sd")])
445169689Skan
446169689Skan;; Similarly for MIPS IV indexed FPR loads and stores.
447169689Skan(define_mode_attr loadx [(SF "lwxc1") (DF "ldxc1") (V2SF "ldxc1")])
448169689Skan(define_mode_attr storex [(SF "swxc1") (DF "sdxc1") (V2SF "sdxc1")])
449169689Skan
450169689Skan;; The unextended ranges of the MIPS16 addiu and daddiu instructions
451169689Skan;; are different.  Some forms of unextended addiu have an 8-bit immediate
452169689Skan;; field but the equivalent daddiu has only a 5-bit field.
453169689Skan(define_mode_attr si8_di5 [(SI "8") (DI "5")])
454169689Skan
455169689Skan;; This attribute gives the best constraint to use for registers of
456169689Skan;; a given mode.
457169689Skan(define_mode_attr reg [(SI "d") (DI "d") (CC "z")])
458169689Skan
459169689Skan;; This attribute gives the format suffix for floating-point operations.
460169689Skan(define_mode_attr fmt [(SF "s") (DF "d") (V2SF "ps")])
461169689Skan
462169689Skan;; This attribute gives the upper-case mode name for one unit of a
463169689Skan;; floating-point mode.
464169689Skan(define_mode_attr UNITMODE [(SF "SF") (DF "DF") (V2SF "SF")])
465169689Skan
466169689Skan;; This attribute works around the early SB-1 rev2 core "F2" erratum:
467169689Skan;;
468169689Skan;; In certain cases, div.s and div.ps may have a rounding error
469169689Skan;; and/or wrong inexact flag.
470169689Skan;;
471169689Skan;; Therefore, we only allow div.s if not working around SB-1 rev2
472169689Skan;; errata or if a slight loss of precision is OK.
473169689Skan(define_mode_attr divide_condition
474169689Skan  [DF (SF "!TARGET_FIX_SB1 || flag_unsafe_math_optimizations")
475169689Skan   (V2SF "TARGET_SB1 && (!TARGET_FIX_SB1 || flag_unsafe_math_optimizations)")])
476169689Skan
477169689Skan; This attribute gives the condition for which sqrt instructions exist.
478169689Skan(define_mode_attr sqrt_condition
479169689Skan  [(SF "!ISA_MIPS1") (DF "!ISA_MIPS1") (V2SF "TARGET_SB1")])
480169689Skan
481169689Skan; This attribute gives the condition for which recip and rsqrt instructions
482169689Skan; exist.
483169689Skan(define_mode_attr recip_condition
484169689Skan  [(SF "ISA_HAS_FP4") (DF "ISA_HAS_FP4") (V2SF "TARGET_SB1")])
485169689Skan
486169689Skan;; This code macro allows all branch instructions to be generated from
487169689Skan;; a single define_expand template.
488169689Skan(define_code_macro any_cond [unordered ordered unlt unge uneq ltgt unle ungt
489169689Skan			     eq ne gt ge lt le gtu geu ltu leu])
490169689Skan
491169689Skan;; This code macro allows signed and unsigned widening multiplications
492169689Skan;; to use the same template.
493169689Skan(define_code_macro any_extend [sign_extend zero_extend])
494169689Skan
495169689Skan;; This code macro allows the three shift instructions to be generated
496169689Skan;; from the same template.
497169689Skan(define_code_macro any_shift [ashift ashiftrt lshiftrt])
498169689Skan
499169689Skan;; This code macro allows all native floating-point comparisons to be
500169689Skan;; generated from the same template.
501169689Skan(define_code_macro fcond [unordered uneq unlt unle eq lt le])
502169689Skan
503169689Skan;; This code macro is used for comparisons that can be implemented
504169689Skan;; by swapping the operands.
505169689Skan(define_code_macro swapped_fcond [ge gt unge ungt])
506169689Skan
507169689Skan;; <u> expands to an empty string when doing a signed operation and
508169689Skan;; "u" when doing an unsigned operation.
509169689Skan(define_code_attr u [(sign_extend "") (zero_extend "u")])
510169689Skan
511169689Skan;; <su> is like <u>, but the signed form expands to "s" rather than "".
512169689Skan(define_code_attr su [(sign_extend "s") (zero_extend "u")])
513169689Skan
514169689Skan;; <optab> expands to the name of the optab for a particular code.
515169689Skan(define_code_attr optab [(ashift "ashl")
516169689Skan			 (ashiftrt "ashr")
517169689Skan			 (lshiftrt "lshr")])
518169689Skan
519169689Skan;; <insn> expands to the name of the insn that implements a particular code.
520169689Skan(define_code_attr insn [(ashift "sll")
521169689Skan			(ashiftrt "sra")
522169689Skan			(lshiftrt "srl")])
523169689Skan
524169689Skan;; <fcond> is the c.cond.fmt condition associated with a particular code.
525169689Skan(define_code_attr fcond [(unordered "un")
526169689Skan			 (uneq "ueq")
527169689Skan			 (unlt "ult")
528169689Skan			 (unle "ule")
529169689Skan			 (eq "eq")
530169689Skan			 (lt "lt")
531169689Skan			 (le "le")])
532169689Skan
533169689Skan;; Similar, but for swapped conditions.
534169689Skan(define_code_attr swapped_fcond [(ge "le")
535169689Skan				 (gt "lt")
536169689Skan				 (unge "ule")
537169689Skan				 (ungt "ult")])
538169689Skan
539169689Skan;; .........................
540169689Skan;;
541169689Skan;;	Branch, call and jump delay slots
542169689Skan;;
543169689Skan;; .........................
544169689Skan
545169689Skan(define_delay (and (eq_attr "type" "branch")
546169689Skan		   (eq (symbol_ref "TARGET_MIPS16") (const_int 0)))
547169689Skan  [(eq_attr "can_delay" "yes")
548169689Skan   (nil)
549169689Skan   (and (eq_attr "branch_likely" "yes")
550169689Skan	(eq_attr "can_delay" "yes"))])
551169689Skan
552169689Skan(define_delay (eq_attr "type" "jump")
553169689Skan  [(eq_attr "can_delay" "yes")
554169689Skan   (nil)
555169689Skan   (nil)])
556169689Skan
557169689Skan(define_delay (and (eq_attr "type" "call")
558169689Skan		   (eq_attr "jal_macro" "no"))
559169689Skan  [(eq_attr "can_delay" "yes")
560169689Skan   (nil)
561169689Skan   (nil)])
562169689Skan
563169689Skan;; Pipeline descriptions.
564169689Skan;;
565169689Skan;; generic.md provides a fallback for processors without a specific
566169689Skan;; pipeline description.  It is derived from the old define_function_unit
567169689Skan;; version and uses the "alu" and "imuldiv" units declared below.
568169689Skan;;
569169689Skan;; Some of the processor-specific files are also derived from old
570169689Skan;; define_function_unit descriptions and simply override the parts of
571169689Skan;; generic.md that don't apply.  The other processor-specific files
572169689Skan;; are self-contained.
573169689Skan(define_automaton "alu,imuldiv")
574169689Skan
575169689Skan(define_cpu_unit "alu" "alu")
576169689Skan(define_cpu_unit "imuldiv" "imuldiv")
577169689Skan
578169689Skan(include "4k.md")
579169689Skan(include "5k.md")
580169689Skan(include "24k.md")
581169689Skan(include "3000.md")
582169689Skan(include "4000.md")
583169689Skan(include "4100.md")
584169689Skan(include "4130.md")
585169689Skan(include "4300.md")
586169689Skan(include "4600.md")
587169689Skan(include "5000.md")
588169689Skan(include "5400.md")
589169689Skan(include "5500.md")
590169689Skan(include "6000.md")
591169689Skan(include "7000.md")
592169689Skan(include "9000.md")
593169689Skan(include "sb1.md")
594169689Skan(include "sr71k.md")
595169689Skan(include "generic.md")
596169689Skan
597169689Skan;;
598169689Skan;;  ....................
599169689Skan;;
600169689Skan;;	CONDITIONAL TRAPS
601169689Skan;;
602169689Skan;;  ....................
603169689Skan;;
604169689Skan
605169689Skan(define_insn "trap"
606169689Skan  [(trap_if (const_int 1) (const_int 0))]
607169689Skan  ""
608169689Skan{
609169689Skan  if (ISA_HAS_COND_TRAP)
610169689Skan    return "teq\t$0,$0";
611169689Skan  else if (TARGET_MIPS16)
612169689Skan    return "break 0";
613169689Skan  else
614169689Skan    return "break";
615169689Skan}
616169689Skan  [(set_attr "type" "trap")])
617169689Skan
618169689Skan(define_expand "conditional_trap"
619169689Skan  [(trap_if (match_operator 0 "comparison_operator"
620169689Skan			    [(match_dup 2) (match_dup 3)])
621169689Skan	    (match_operand 1 "const_int_operand"))]
622169689Skan  "ISA_HAS_COND_TRAP"
623169689Skan{
624169689Skan  if (GET_MODE_CLASS (GET_MODE (cmp_operands[0])) == MODE_INT
625169689Skan      && operands[1] == const0_rtx)
626169689Skan    {
627169689Skan      mips_gen_conditional_trap (operands);
628169689Skan      DONE;
629169689Skan    }
630169689Skan  else
631169689Skan    FAIL;
632169689Skan})
633169689Skan
634169689Skan(define_insn "*conditional_trap<mode>"
635169689Skan  [(trap_if (match_operator:GPR 0 "trap_comparison_operator"
636169689Skan				[(match_operand:GPR 1 "reg_or_0_operand" "dJ")
637169689Skan				 (match_operand:GPR 2 "arith_operand" "dI")])
638169689Skan	    (const_int 0))]
639169689Skan  "ISA_HAS_COND_TRAP"
640169689Skan  "t%C0\t%z1,%2"
641169689Skan  [(set_attr "type" "trap")])
642169689Skan
643169689Skan;;
644169689Skan;;  ....................
645169689Skan;;
646169689Skan;;	ADDITION
647169689Skan;;
648169689Skan;;  ....................
649169689Skan;;
650169689Skan
651169689Skan(define_insn "add<mode>3"
652169689Skan  [(set (match_operand:ANYF 0 "register_operand" "=f")
653169689Skan	(plus:ANYF (match_operand:ANYF 1 "register_operand" "f")
654169689Skan		   (match_operand:ANYF 2 "register_operand" "f")))]
655169689Skan  ""
656169689Skan  "add.<fmt>\t%0,%1,%2"
657169689Skan  [(set_attr "type" "fadd")
658169689Skan   (set_attr "mode" "<UNITMODE>")])
659169689Skan
660169689Skan(define_expand "add<mode>3"
661169689Skan  [(set (match_operand:GPR 0 "register_operand")
662169689Skan	(plus:GPR (match_operand:GPR 1 "register_operand")
663169689Skan		  (match_operand:GPR 2 "arith_operand")))]
664169689Skan  "")
665169689Skan
666169689Skan(define_insn "*add<mode>3"
667169689Skan  [(set (match_operand:GPR 0 "register_operand" "=d,d")
668169689Skan	(plus:GPR (match_operand:GPR 1 "register_operand" "d,d")
669169689Skan		  (match_operand:GPR 2 "arith_operand" "d,Q")))]
670169689Skan  "!TARGET_MIPS16"
671169689Skan  "@
672169689Skan    <d>addu\t%0,%1,%2
673169689Skan    <d>addiu\t%0,%1,%2"
674169689Skan  [(set_attr "type" "arith")
675169689Skan   (set_attr "mode" "<MODE>")])
676169689Skan
677169689Skan;; We need to recognize MIPS16 stack pointer additions explicitly, since
678169689Skan;; we don't have a constraint for $sp.  These insns will be generated by
679169689Skan;; the save_restore_insns functions.
680169689Skan
681169689Skan(define_insn "*add<mode>3_sp1"
682169689Skan  [(set (reg:GPR 29)
683169689Skan	(plus:GPR (reg:GPR 29)
684169689Skan		  (match_operand:GPR 0 "const_arith_operand" "")))]
685169689Skan  "TARGET_MIPS16"
686169689Skan  "<d>addiu\t%$,%$,%0"
687169689Skan  [(set_attr "type" "arith")
688169689Skan   (set_attr "mode" "<MODE>")
689169689Skan   (set (attr "length") (if_then_else (match_operand 0 "m16_simm8_8")
690169689Skan				      (const_int 4)
691169689Skan				      (const_int 8)))])
692169689Skan
693169689Skan(define_insn "*add<mode>3_sp2"
694169689Skan  [(set (match_operand:GPR 0 "register_operand" "=d")
695169689Skan	(plus:GPR (reg:GPR 29)
696169689Skan		  (match_operand:GPR 1 "const_arith_operand" "")))]
697169689Skan  "TARGET_MIPS16"
698169689Skan  "<d>addiu\t%0,%$,%1"
699169689Skan  [(set_attr "type" "arith")
700169689Skan   (set_attr "mode" "<MODE>")
701169689Skan   (set (attr "length") (if_then_else (match_operand 1 "m16_uimm<si8_di5>_4")
702169689Skan				      (const_int 4)
703169689Skan				      (const_int 8)))])
704169689Skan
705169689Skan(define_insn "*add<mode>3_mips16"
706169689Skan  [(set (match_operand:GPR 0 "register_operand" "=d,d,d")
707169689Skan	(plus:GPR (match_operand:GPR 1 "register_operand" "0,d,d")
708169689Skan		  (match_operand:GPR 2 "arith_operand" "Q,O,d")))]
709169689Skan  "TARGET_MIPS16"
710169689Skan  "@
711169689Skan    <d>addiu\t%0,%2
712169689Skan    <d>addiu\t%0,%1,%2
713169689Skan    <d>addu\t%0,%1,%2"
714169689Skan  [(set_attr "type" "arith")
715169689Skan   (set_attr "mode" "<MODE>")
716169689Skan   (set_attr_alternative "length"
717169689Skan		[(if_then_else (match_operand 2 "m16_simm<si8_di5>_1")
718169689Skan			       (const_int 4)
719169689Skan			       (const_int 8))
720169689Skan		 (if_then_else (match_operand 2 "m16_simm4_1")
721169689Skan			       (const_int 4)
722169689Skan			       (const_int 8))
723169689Skan		 (const_int 4)])])
724169689Skan
725169689Skan
726169689Skan;; On the mips16, we can sometimes split an add of a constant which is
727169689Skan;; a 4 byte instruction into two adds which are both 2 byte
728169689Skan;; instructions.  There are two cases: one where we are adding a
729169689Skan;; constant plus a register to another register, and one where we are
730169689Skan;; simply adding a constant to a register.
731169689Skan
732169689Skan(define_split
733169689Skan  [(set (match_operand:SI 0 "register_operand")
734169689Skan	(plus:SI (match_dup 0)
735169689Skan		 (match_operand:SI 1 "const_int_operand")))]
736169689Skan  "TARGET_MIPS16 && reload_completed && !TARGET_DEBUG_D_MODE
737169689Skan   && REG_P (operands[0])
738169689Skan   && M16_REG_P (REGNO (operands[0]))
739169689Skan   && GET_CODE (operands[1]) == CONST_INT
740169689Skan   && ((INTVAL (operands[1]) > 0x7f
741169689Skan	&& INTVAL (operands[1]) <= 0x7f + 0x7f)
742169689Skan       || (INTVAL (operands[1]) < - 0x80
743169689Skan	   && INTVAL (operands[1]) >= - 0x80 - 0x80))"
744169689Skan  [(set (match_dup 0) (plus:SI (match_dup 0) (match_dup 1)))
745169689Skan   (set (match_dup 0) (plus:SI (match_dup 0) (match_dup 2)))]
746169689Skan{
747169689Skan  HOST_WIDE_INT val = INTVAL (operands[1]);
748169689Skan
749169689Skan  if (val >= 0)
750169689Skan    {
751169689Skan      operands[1] = GEN_INT (0x7f);
752169689Skan      operands[2] = GEN_INT (val - 0x7f);
753169689Skan    }
754169689Skan  else
755169689Skan    {
756169689Skan      operands[1] = GEN_INT (- 0x80);
757169689Skan      operands[2] = GEN_INT (val + 0x80);
758169689Skan    }
759169689Skan})
760169689Skan
761169689Skan(define_split
762169689Skan  [(set (match_operand:SI 0 "register_operand")
763169689Skan	(plus:SI (match_operand:SI 1 "register_operand")
764169689Skan		 (match_operand:SI 2 "const_int_operand")))]
765169689Skan  "TARGET_MIPS16 && reload_completed && !TARGET_DEBUG_D_MODE
766169689Skan   && REG_P (operands[0])
767169689Skan   && M16_REG_P (REGNO (operands[0]))
768169689Skan   && REG_P (operands[1])
769169689Skan   && M16_REG_P (REGNO (operands[1]))
770169689Skan   && REGNO (operands[0]) != REGNO (operands[1])
771169689Skan   && GET_CODE (operands[2]) == CONST_INT
772169689Skan   && ((INTVAL (operands[2]) > 0x7
773169689Skan	&& INTVAL (operands[2]) <= 0x7 + 0x7f)
774169689Skan       || (INTVAL (operands[2]) < - 0x8
775169689Skan	   && INTVAL (operands[2]) >= - 0x8 - 0x80))"
776169689Skan  [(set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))
777169689Skan   (set (match_dup 0) (plus:SI (match_dup 0) (match_dup 3)))]
778169689Skan{
779169689Skan  HOST_WIDE_INT val = INTVAL (operands[2]);
780169689Skan
781169689Skan  if (val >= 0)
782169689Skan    {
783169689Skan      operands[2] = GEN_INT (0x7);
784169689Skan      operands[3] = GEN_INT (val - 0x7);
785169689Skan    }
786169689Skan  else
787169689Skan    {
788169689Skan      operands[2] = GEN_INT (- 0x8);
789169689Skan      operands[3] = GEN_INT (val + 0x8);
790169689Skan    }
791169689Skan})
792169689Skan
793169689Skan(define_split
794169689Skan  [(set (match_operand:DI 0 "register_operand")
795169689Skan	(plus:DI (match_dup 0)
796169689Skan		 (match_operand:DI 1 "const_int_operand")))]
797169689Skan  "TARGET_MIPS16 && TARGET_64BIT && reload_completed && !TARGET_DEBUG_D_MODE
798169689Skan   && REG_P (operands[0])
799169689Skan   && M16_REG_P (REGNO (operands[0]))
800169689Skan   && GET_CODE (operands[1]) == CONST_INT
801169689Skan   && ((INTVAL (operands[1]) > 0xf
802169689Skan	&& INTVAL (operands[1]) <= 0xf + 0xf)
803169689Skan       || (INTVAL (operands[1]) < - 0x10
804169689Skan	   && INTVAL (operands[1]) >= - 0x10 - 0x10))"
805169689Skan  [(set (match_dup 0) (plus:DI (match_dup 0) (match_dup 1)))
806169689Skan   (set (match_dup 0) (plus:DI (match_dup 0) (match_dup 2)))]
807169689Skan{
808169689Skan  HOST_WIDE_INT val = INTVAL (operands[1]);
809169689Skan
810169689Skan  if (val >= 0)
811169689Skan    {
812169689Skan      operands[1] = GEN_INT (0xf);
813169689Skan      operands[2] = GEN_INT (val - 0xf);
814169689Skan    }
815169689Skan  else
816169689Skan    {
817169689Skan      operands[1] = GEN_INT (- 0x10);
818169689Skan      operands[2] = GEN_INT (val + 0x10);
819169689Skan    }
820169689Skan})
821169689Skan
822169689Skan(define_split
823169689Skan  [(set (match_operand:DI 0 "register_operand")
824169689Skan	(plus:DI (match_operand:DI 1 "register_operand")
825169689Skan		 (match_operand:DI 2 "const_int_operand")))]
826169689Skan  "TARGET_MIPS16 && TARGET_64BIT && reload_completed && !TARGET_DEBUG_D_MODE
827169689Skan   && REG_P (operands[0])
828169689Skan   && M16_REG_P (REGNO (operands[0]))
829169689Skan   && REG_P (operands[1])
830169689Skan   && M16_REG_P (REGNO (operands[1]))
831169689Skan   && REGNO (operands[0]) != REGNO (operands[1])
832169689Skan   && GET_CODE (operands[2]) == CONST_INT
833169689Skan   && ((INTVAL (operands[2]) > 0x7
834169689Skan	&& INTVAL (operands[2]) <= 0x7 + 0xf)
835169689Skan       || (INTVAL (operands[2]) < - 0x8
836169689Skan	   && INTVAL (operands[2]) >= - 0x8 - 0x10))"
837169689Skan  [(set (match_dup 0) (plus:DI (match_dup 1) (match_dup 2)))
838169689Skan   (set (match_dup 0) (plus:DI (match_dup 0) (match_dup 3)))]
839169689Skan{
840169689Skan  HOST_WIDE_INT val = INTVAL (operands[2]);
841169689Skan
842169689Skan  if (val >= 0)
843169689Skan    {
844169689Skan      operands[2] = GEN_INT (0x7);
845169689Skan      operands[3] = GEN_INT (val - 0x7);
846169689Skan    }
847169689Skan  else
848169689Skan    {
849169689Skan      operands[2] = GEN_INT (- 0x8);
850169689Skan      operands[3] = GEN_INT (val + 0x8);
851169689Skan    }
852169689Skan})
853169689Skan
854169689Skan(define_insn "*addsi3_extended"
855169689Skan  [(set (match_operand:DI 0 "register_operand" "=d,d")
856169689Skan	(sign_extend:DI
857169689Skan	     (plus:SI (match_operand:SI 1 "register_operand" "d,d")
858169689Skan		      (match_operand:SI 2 "arith_operand" "d,Q"))))]
859169689Skan  "TARGET_64BIT && !TARGET_MIPS16"
860169689Skan  "@
861169689Skan    addu\t%0,%1,%2
862169689Skan    addiu\t%0,%1,%2"
863169689Skan  [(set_attr "type" "arith")
864169689Skan   (set_attr "mode" "SI")])
865169689Skan
866169689Skan;; Split this insn so that the addiu splitters can have a crack at it.
867169689Skan;; Use a conservative length estimate until the split.
868169689Skan(define_insn_and_split "*addsi3_extended_mips16"
869169689Skan  [(set (match_operand:DI 0 "register_operand" "=d,d,d")
870169689Skan	(sign_extend:DI
871169689Skan	     (plus:SI (match_operand:SI 1 "register_operand" "0,d,d")
872169689Skan		      (match_operand:SI 2 "arith_operand" "Q,O,d"))))]
873169689Skan  "TARGET_64BIT && TARGET_MIPS16"
874169689Skan  "#"
875169689Skan  "&& reload_completed"
876169689Skan  [(set (match_dup 3) (plus:SI (match_dup 1) (match_dup 2)))]
877169689Skan  { operands[3] = gen_lowpart (SImode, operands[0]); }
878169689Skan  [(set_attr "type" "arith")
879169689Skan   (set_attr "mode" "SI")
880169689Skan   (set_attr "extended_mips16" "yes")])
881169689Skan
882169689Skan;;
883169689Skan;;  ....................
884169689Skan;;
885169689Skan;;	SUBTRACTION
886169689Skan;;
887169689Skan;;  ....................
888169689Skan;;
889169689Skan
890169689Skan(define_insn "sub<mode>3"
891169689Skan  [(set (match_operand:ANYF 0 "register_operand" "=f")
892169689Skan	(minus:ANYF (match_operand:ANYF 1 "register_operand" "f")
893169689Skan		    (match_operand:ANYF 2 "register_operand" "f")))]
894169689Skan  ""
895169689Skan  "sub.<fmt>\t%0,%1,%2"
896169689Skan  [(set_attr "type" "fadd")
897169689Skan   (set_attr "mode" "<UNITMODE>")])
898169689Skan
899169689Skan(define_insn "sub<mode>3"
900169689Skan  [(set (match_operand:GPR 0 "register_operand" "=d")
901169689Skan	(minus:GPR (match_operand:GPR 1 "register_operand" "d")
902169689Skan		   (match_operand:GPR 2 "register_operand" "d")))]
903169689Skan  ""
904169689Skan  "<d>subu\t%0,%1,%2"
905169689Skan  [(set_attr "type" "arith")
906169689Skan   (set_attr "mode" "<MODE>")])
907169689Skan
908169689Skan(define_insn "*subsi3_extended"
909169689Skan  [(set (match_operand:DI 0 "register_operand" "=d")
910169689Skan	(sign_extend:DI
911169689Skan	    (minus:SI (match_operand:SI 1 "register_operand" "d")
912169689Skan		      (match_operand:SI 2 "register_operand" "d"))))]
913169689Skan  "TARGET_64BIT"
914169689Skan  "subu\t%0,%1,%2"
915169689Skan  [(set_attr "type" "arith")
916169689Skan   (set_attr "mode" "DI")])
917169689Skan
918169689Skan;;
919169689Skan;;  ....................
920169689Skan;;
921169689Skan;;	MULTIPLICATION
922169689Skan;;
923169689Skan;;  ....................
924169689Skan;;
925169689Skan
926169689Skan(define_expand "mul<mode>3"
927169689Skan  [(set (match_operand:SCALARF 0 "register_operand")
928169689Skan	(mult:SCALARF (match_operand:SCALARF 1 "register_operand")
929169689Skan		      (match_operand:SCALARF 2 "register_operand")))]
930169689Skan  ""
931169689Skan  "")
932169689Skan
933169689Skan(define_insn "*mul<mode>3"
934169689Skan  [(set (match_operand:SCALARF 0 "register_operand" "=f")
935169689Skan	(mult:SCALARF (match_operand:SCALARF 1 "register_operand" "f")
936169689Skan		      (match_operand:SCALARF 2 "register_operand" "f")))]
937169689Skan  "!TARGET_4300_MUL_FIX"
938169689Skan  "mul.<fmt>\t%0,%1,%2"
939169689Skan  [(set_attr "type" "fmul")
940169689Skan   (set_attr "mode" "<MODE>")])
941169689Skan
942169689Skan;; Early VR4300 silicon has a CPU bug where multiplies with certain
943169689Skan;; operands may corrupt immediately following multiplies. This is a
944169689Skan;; simple fix to insert NOPs.
945169689Skan
946169689Skan(define_insn "*mul<mode>3_r4300"
947169689Skan  [(set (match_operand:SCALARF 0 "register_operand" "=f")
948169689Skan	(mult:SCALARF (match_operand:SCALARF 1 "register_operand" "f")
949169689Skan		      (match_operand:SCALARF 2 "register_operand" "f")))]
950169689Skan  "TARGET_4300_MUL_FIX"
951169689Skan  "mul.<fmt>\t%0,%1,%2\;nop"
952169689Skan  [(set_attr "type" "fmul")
953169689Skan   (set_attr "mode" "<MODE>")
954169689Skan   (set_attr "length" "8")])
955169689Skan
956169689Skan(define_insn "mulv2sf3"
957169689Skan  [(set (match_operand:V2SF 0 "register_operand" "=f")
958169689Skan	(mult:V2SF (match_operand:V2SF 1 "register_operand" "f")
959169689Skan		   (match_operand:V2SF 2 "register_operand" "f")))]
960169689Skan  "TARGET_PAIRED_SINGLE_FLOAT"
961169689Skan  "mul.ps\t%0,%1,%2"
962169689Skan  [(set_attr "type" "fmul")
963169689Skan   (set_attr "mode" "SF")])
964169689Skan
965169689Skan;; The original R4000 has a cpu bug.  If a double-word or a variable
966169689Skan;; shift executes while an integer multiplication is in progress, the
967169689Skan;; shift may give an incorrect result.  Avoid this by keeping the mflo
968169689Skan;; with the mult on the R4000.
969169689Skan;;
970169689Skan;; From "MIPS R4000PC/SC Errata, Processor Revision 2.2 and 3.0"
971169689Skan;; (also valid for MIPS R4000MC processors):
972169689Skan;;
973169689Skan;; "16. R4000PC, R4000SC: Please refer to errata 28 for an update to
974169689Skan;;	this errata description.
975169689Skan;;	The following code sequence causes the R4000 to incorrectly
976169689Skan;;	execute the Double Shift Right Arithmetic 32 (dsra32)
977169689Skan;;	instruction.  If the dsra32 instruction is executed during an
978169689Skan;;	integer multiply, the dsra32 will only shift by the amount in
979169689Skan;;	specified in the instruction rather than the amount plus 32
980169689Skan;;	bits.
981169689Skan;;	instruction 1:		mult	rs,rt		integer multiply
982169689Skan;;	instruction 2-12:	dsra32	rd,rt,rs	doubleword shift
983169689Skan;;							right arithmetic + 32
984169689Skan;;	Workaround: A dsra32 instruction placed after an integer
985169689Skan;;	multiply should not be one of the 11 instructions after the
986169689Skan;;	multiply instruction."
987169689Skan;;
988169689Skan;; and:
989169689Skan;;
990169689Skan;; "28. R4000PC, R4000SC: The text from errata 16 should be replaced by
991169689Skan;;	the following description.
992169689Skan;;	All extended shifts (shift by n+32) and variable shifts (32 and
993169689Skan;;	64-bit versions) may produce incorrect results under the
994169689Skan;;	following conditions:
995169689Skan;;	1) An integer multiply is currently executing
996169689Skan;;	2) These types of shift instructions are executed immediately
997169689Skan;;	   following an integer divide instruction.
998169689Skan;;	Workaround:
999169689Skan;;	1) Make sure no integer multiply is running wihen these
1000169689Skan;;	   instruction are executed.  If this cannot be predicted at
1001169689Skan;;	   compile time, then insert a "mfhi" to R0 instruction
1002169689Skan;;	   immediately after the integer multiply instruction.  This
1003169689Skan;;	   will cause the integer multiply to complete before the shift
1004169689Skan;;	   is executed.
1005169689Skan;;	2) Separate integer divide and these two classes of shift
1006169689Skan;;	   instructions by another instruction or a noop."
1007169689Skan;;
1008169689Skan;; These processors have PRId values of 0x00004220 and 0x00004300,
1009169689Skan;; respectively.
1010169689Skan
1011169689Skan(define_expand "mul<mode>3"
1012169689Skan  [(set (match_operand:GPR 0 "register_operand")
1013169689Skan	(mult:GPR (match_operand:GPR 1 "register_operand")
1014169689Skan		  (match_operand:GPR 2 "register_operand")))]
1015169689Skan  ""
1016169689Skan{
1017169689Skan  if (GENERATE_MULT3_<MODE>)
1018169689Skan    emit_insn (gen_mul<mode>3_mult3 (operands[0], operands[1], operands[2]));
1019169689Skan  else if (!TARGET_FIX_R4000)
1020169689Skan    emit_insn (gen_mul<mode>3_internal (operands[0], operands[1],
1021169689Skan					operands[2]));
1022169689Skan  else
1023169689Skan    emit_insn (gen_mul<mode>3_r4000 (operands[0], operands[1], operands[2]));
1024169689Skan  DONE;
1025169689Skan})
1026169689Skan
1027169689Skan(define_insn "mulsi3_mult3"
1028169689Skan  [(set (match_operand:SI 0 "register_operand" "=d,l")
1029169689Skan	(mult:SI (match_operand:SI 1 "register_operand" "d,d")
1030169689Skan		 (match_operand:SI 2 "register_operand" "d,d")))
1031169689Skan   (clobber (match_scratch:SI 3 "=h,h"))
1032169689Skan   (clobber (match_scratch:SI 4 "=l,X"))]
1033169689Skan  "GENERATE_MULT3_SI"
1034169689Skan{
1035169689Skan  if (which_alternative == 1)
1036169689Skan    return "mult\t%1,%2";
1037169689Skan  if (TARGET_MAD
1038169689Skan      || TARGET_MIPS5400
1039169689Skan      || TARGET_MIPS5500
1040169689Skan      || TARGET_MIPS7000
1041169689Skan      || TARGET_MIPS9000
1042169689Skan      || ISA_MIPS32
1043169689Skan      || ISA_MIPS32R2
1044208737Sjmallett      || ISA_MIPS64
1045208737Sjmallett      || ISA_MIPS64R2)
1046169689Skan    return "mul\t%0,%1,%2";
1047169689Skan  return "mult\t%0,%1,%2";
1048169689Skan}
1049169689Skan  [(set_attr "type" "imul3,imul")
1050169689Skan   (set_attr "mode" "SI")])
1051169689Skan
1052169689Skan(define_insn "muldi3_mult3"
1053169689Skan  [(set (match_operand:DI 0 "register_operand" "=d")
1054169689Skan	(mult:DI (match_operand:DI 1 "register_operand" "d")
1055169689Skan		 (match_operand:DI 2 "register_operand" "d")))
1056169689Skan   (clobber (match_scratch:DI 3 "=h"))
1057169689Skan   (clobber (match_scratch:DI 4 "=l"))]
1058169689Skan  "TARGET_64BIT && GENERATE_MULT3_DI"
1059169689Skan  "dmult\t%0,%1,%2"
1060169689Skan  [(set_attr "type" "imul3")
1061169689Skan   (set_attr "mode" "DI")])
1062169689Skan
1063169689Skan;; If a register gets allocated to LO, and we spill to memory, the reload
1064169689Skan;; will include a move from LO to a GPR.  Merge it into the multiplication
1065169689Skan;; if it can set the GPR directly.
1066169689Skan;;
1067169689Skan;; Operand 0: LO
1068169689Skan;; Operand 1: GPR (1st multiplication operand)
1069169689Skan;; Operand 2: GPR (2nd multiplication operand)
1070169689Skan;; Operand 3: HI
1071169689Skan;; Operand 4: GPR (destination)
1072169689Skan(define_peephole2
1073169689Skan  [(parallel
1074169689Skan       [(set (match_operand:SI 0 "register_operand")
1075169689Skan	     (mult:SI (match_operand:SI 1 "register_operand")
1076169689Skan		      (match_operand:SI 2 "register_operand")))
1077169689Skan        (clobber (match_operand:SI 3 "register_operand"))
1078169689Skan        (clobber (scratch:SI))])
1079169689Skan   (set (match_operand:SI 4 "register_operand")
1080169689Skan	(unspec [(match_dup 0) (match_dup 3)] UNSPEC_MFHILO))]
1081169689Skan  "GENERATE_MULT3_SI && peep2_reg_dead_p (2, operands[0])"
1082169689Skan  [(parallel
1083169689Skan       [(set (match_dup 4)
1084169689Skan	     (mult:SI (match_dup 1)
1085169689Skan		      (match_dup 2)))
1086169689Skan        (clobber (match_dup 3))
1087169689Skan        (clobber (match_dup 0))])])
1088169689Skan
1089169689Skan(define_insn "mul<mode>3_internal"
1090169689Skan  [(set (match_operand:GPR 0 "register_operand" "=l")
1091169689Skan	(mult:GPR (match_operand:GPR 1 "register_operand" "d")
1092169689Skan		  (match_operand:GPR 2 "register_operand" "d")))
1093169689Skan   (clobber (match_scratch:GPR 3 "=h"))]
1094169689Skan  "!TARGET_FIX_R4000"
1095169689Skan  "<d>mult\t%1,%2"
1096169689Skan  [(set_attr "type" "imul")
1097169689Skan   (set_attr "mode" "<MODE>")])
1098169689Skan
1099169689Skan(define_insn "mul<mode>3_r4000"
1100169689Skan  [(set (match_operand:GPR 0 "register_operand" "=d")
1101169689Skan	(mult:GPR (match_operand:GPR 1 "register_operand" "d")
1102169689Skan		  (match_operand:GPR 2 "register_operand" "d")))
1103169689Skan   (clobber (match_scratch:GPR 3 "=h"))
1104169689Skan   (clobber (match_scratch:GPR 4 "=l"))]
1105169689Skan  "TARGET_FIX_R4000"
1106169689Skan  "<d>mult\t%1,%2\;mflo\t%0"
1107169689Skan  [(set_attr "type" "imul")
1108169689Skan   (set_attr "mode" "<MODE>")
1109169689Skan   (set_attr "length" "8")])
1110169689Skan
1111169689Skan;; On the VR4120 and VR4130, it is better to use "mtlo $0; macc" instead
1112169689Skan;; of "mult; mflo".  They have the same latency, but the first form gives
1113169689Skan;; us an extra cycle to compute the operands.
1114169689Skan
1115169689Skan;; Operand 0: LO
1116169689Skan;; Operand 1: GPR (1st multiplication operand)
1117169689Skan;; Operand 2: GPR (2nd multiplication operand)
1118169689Skan;; Operand 3: HI
1119169689Skan;; Operand 4: GPR (destination)
1120169689Skan(define_peephole2
1121169689Skan  [(parallel
1122169689Skan       [(set (match_operand:SI 0 "register_operand")
1123169689Skan	     (mult:SI (match_operand:SI 1 "register_operand")
1124169689Skan		      (match_operand:SI 2 "register_operand")))
1125169689Skan        (clobber (match_operand:SI 3 "register_operand"))])
1126169689Skan   (set (match_operand:SI 4 "register_operand")
1127169689Skan	(unspec:SI [(match_dup 0) (match_dup 3)] UNSPEC_MFHILO))]
1128169689Skan  "ISA_HAS_MACC && !GENERATE_MULT3_SI"
1129169689Skan  [(set (match_dup 0)
1130169689Skan	(const_int 0))
1131169689Skan   (parallel
1132169689Skan       [(set (match_dup 0)
1133169689Skan	     (plus:SI (mult:SI (match_dup 1)
1134169689Skan			       (match_dup 2))
1135169689Skan		      (match_dup 0)))
1136169689Skan	(set (match_dup 4)
1137169689Skan	     (plus:SI (mult:SI (match_dup 1)
1138169689Skan			       (match_dup 2))
1139169689Skan		      (match_dup 0)))
1140169689Skan        (clobber (match_dup 3))])])
1141169689Skan
1142169689Skan;; Multiply-accumulate patterns
1143169689Skan
1144169689Skan;; For processors that can copy the output to a general register:
1145169689Skan;;
1146169689Skan;; The all-d alternative is needed because the combiner will find this
1147169689Skan;; pattern and then register alloc/reload will move registers around to
1148169689Skan;; make them fit, and we don't want to trigger unnecessary loads to LO.
1149169689Skan;;
1150169689Skan;; The last alternative should be made slightly less desirable, but adding
1151169689Skan;; "?" to the constraint is too strong, and causes values to be loaded into
1152169689Skan;; LO even when that's more costly.  For now, using "*d" mostly does the
1153169689Skan;; trick.
1154169689Skan(define_insn "*mul_acc_si"
1155169689Skan  [(set (match_operand:SI 0 "register_operand" "=l,*d,*d")
1156169689Skan	(plus:SI (mult:SI (match_operand:SI 1 "register_operand" "d,d,d")
1157169689Skan			  (match_operand:SI 2 "register_operand" "d,d,d"))
1158169689Skan		 (match_operand:SI 3 "register_operand" "0,l,*d")))
1159169689Skan   (clobber (match_scratch:SI 4 "=h,h,h"))
1160169689Skan   (clobber (match_scratch:SI 5 "=X,3,l"))
1161169689Skan   (clobber (match_scratch:SI 6 "=X,X,&d"))]
1162169689Skan  "(TARGET_MIPS3900
1163169689Skan   || ISA_HAS_MADD_MSUB)
1164169689Skan   && !TARGET_MIPS16"
1165169689Skan{
1166169689Skan  static const char *const madd[] = { "madd\t%1,%2", "madd\t%0,%1,%2" };
1167169689Skan  if (which_alternative == 2)
1168169689Skan    return "#";
1169169689Skan  if (ISA_HAS_MADD_MSUB && which_alternative != 0)
1170169689Skan    return "#";
1171169689Skan  return madd[which_alternative];
1172169689Skan}
1173169689Skan  [(set_attr "type"	"imadd,imadd,multi")
1174169689Skan   (set_attr "mode"	"SI")
1175169689Skan   (set_attr "length"	"4,4,8")])
1176169689Skan
1177169689Skan;; Split the above insn if we failed to get LO allocated.
1178169689Skan(define_split
1179169689Skan  [(set (match_operand:SI 0 "register_operand")
1180169689Skan	(plus:SI (mult:SI (match_operand:SI 1 "register_operand")
1181169689Skan			  (match_operand:SI 2 "register_operand"))
1182169689Skan		 (match_operand:SI 3 "register_operand")))
1183169689Skan   (clobber (match_scratch:SI 4))
1184169689Skan   (clobber (match_scratch:SI 5))
1185169689Skan   (clobber (match_scratch:SI 6))]
1186169689Skan  "reload_completed && !TARGET_DEBUG_D_MODE
1187169689Skan   && GP_REG_P (true_regnum (operands[0]))
1188169689Skan   && GP_REG_P (true_regnum (operands[3]))"
1189169689Skan  [(parallel [(set (match_dup 6)
1190169689Skan		   (mult:SI (match_dup 1) (match_dup 2)))
1191169689Skan	      (clobber (match_dup 4))
1192169689Skan	      (clobber (match_dup 5))])
1193169689Skan   (set (match_dup 0) (plus:SI (match_dup 6) (match_dup 3)))]
1194169689Skan  "")
1195169689Skan
1196169689Skan;; Splitter to copy result of MADD to a general register
1197169689Skan(define_split
1198169689Skan  [(set (match_operand:SI                   0 "register_operand")
1199169689Skan        (plus:SI (mult:SI (match_operand:SI 1 "register_operand")
1200169689Skan                          (match_operand:SI 2 "register_operand"))
1201169689Skan                 (match_operand:SI          3 "register_operand")))
1202169689Skan   (clobber (match_scratch:SI               4))
1203169689Skan   (clobber (match_scratch:SI               5))
1204169689Skan   (clobber (match_scratch:SI               6))]
1205169689Skan  "reload_completed && !TARGET_DEBUG_D_MODE
1206169689Skan   && GP_REG_P (true_regnum (operands[0]))
1207169689Skan   && true_regnum (operands[3]) == LO_REGNUM"
1208169689Skan  [(parallel [(set (match_dup 3)
1209169689Skan                   (plus:SI (mult:SI (match_dup 1) (match_dup 2))
1210169689Skan                            (match_dup 3)))
1211169689Skan              (clobber (match_dup 4))
1212169689Skan              (clobber (match_dup 5))
1213169689Skan              (clobber (match_dup 6))])
1214169689Skan   (set (match_dup 0) (unspec:SI [(match_dup 5) (match_dup 4)] UNSPEC_MFHILO))]
1215169689Skan  "")
1216169689Skan
1217169689Skan(define_insn "*macc"
1218169689Skan  [(set (match_operand:SI 0 "register_operand" "=l,d")
1219169689Skan	(plus:SI (mult:SI (match_operand:SI 1 "register_operand" "d,d")
1220169689Skan			  (match_operand:SI 2 "register_operand" "d,d"))
1221169689Skan		 (match_operand:SI 3 "register_operand" "0,l")))
1222169689Skan   (clobber (match_scratch:SI 4 "=h,h"))
1223169689Skan   (clobber (match_scratch:SI 5 "=X,3"))]
1224169689Skan  "ISA_HAS_MACC"
1225169689Skan{
1226169689Skan  if (which_alternative == 1)
1227169689Skan    return "macc\t%0,%1,%2";
1228169689Skan  else if (TARGET_MIPS5500)
1229169689Skan    return "madd\t%1,%2";
1230169689Skan  else
1231169689Skan    /* The VR4130 assumes that there is a two-cycle latency between a macc
1232169689Skan       that "writes" to $0 and an instruction that reads from it.  We avoid
1233169689Skan       this by assigning to $1 instead.  */
1234169689Skan    return "%[macc\t%@,%1,%2%]";
1235169689Skan}
1236169689Skan  [(set_attr "type" "imadd")
1237169689Skan   (set_attr "mode" "SI")])
1238169689Skan
1239169689Skan(define_insn "*msac"
1240169689Skan  [(set (match_operand:SI 0 "register_operand" "=l,d")
1241169689Skan        (minus:SI (match_operand:SI 1 "register_operand" "0,l")
1242169689Skan                  (mult:SI (match_operand:SI 2 "register_operand" "d,d")
1243169689Skan                           (match_operand:SI 3 "register_operand" "d,d"))))
1244169689Skan   (clobber (match_scratch:SI 4 "=h,h"))
1245169689Skan   (clobber (match_scratch:SI 5 "=X,1"))]
1246169689Skan  "ISA_HAS_MSAC"
1247169689Skan{
1248169689Skan  if (which_alternative == 1)
1249169689Skan    return "msac\t%0,%2,%3";
1250169689Skan  else if (TARGET_MIPS5500)
1251169689Skan    return "msub\t%2,%3";
1252169689Skan  else
1253169689Skan    return "msac\t$0,%2,%3";
1254169689Skan}
1255169689Skan  [(set_attr "type"     "imadd")
1256169689Skan   (set_attr "mode"     "SI")])
1257169689Skan
1258169689Skan;; An msac-like instruction implemented using negation and a macc.
1259169689Skan(define_insn_and_split "*msac_using_macc"
1260169689Skan  [(set (match_operand:SI 0 "register_operand" "=l,d")
1261169689Skan        (minus:SI (match_operand:SI 1 "register_operand" "0,l")
1262169689Skan                  (mult:SI (match_operand:SI 2 "register_operand" "d,d")
1263169689Skan                           (match_operand:SI 3 "register_operand" "d,d"))))
1264169689Skan   (clobber (match_scratch:SI 4 "=h,h"))
1265169689Skan   (clobber (match_scratch:SI 5 "=X,1"))
1266169689Skan   (clobber (match_scratch:SI 6 "=d,d"))]
1267169689Skan  "ISA_HAS_MACC && !ISA_HAS_MSAC"
1268169689Skan  "#"
1269169689Skan  "&& reload_completed"
1270169689Skan  [(set (match_dup 6)
1271169689Skan	(neg:SI (match_dup 3)))
1272169689Skan   (parallel
1273169689Skan       [(set (match_dup 0)
1274169689Skan	     (plus:SI (mult:SI (match_dup 2)
1275169689Skan			       (match_dup 6))
1276169689Skan		      (match_dup 1)))
1277169689Skan	(clobber (match_dup 4))
1278169689Skan	(clobber (match_dup 5))])]
1279169689Skan  ""
1280169689Skan  [(set_attr "type"     "imadd")
1281169689Skan   (set_attr "length"	"8")])
1282169689Skan
1283169689Skan;; Patterns generated by the define_peephole2 below.
1284169689Skan
1285169689Skan(define_insn "*macc2"
1286169689Skan  [(set (match_operand:SI 0 "register_operand" "=l")
1287169689Skan	(plus:SI (mult:SI (match_operand:SI 1 "register_operand" "d")
1288169689Skan			  (match_operand:SI 2 "register_operand" "d"))
1289169689Skan		 (match_dup 0)))
1290169689Skan   (set (match_operand:SI 3 "register_operand" "=d")
1291169689Skan	(plus:SI (mult:SI (match_dup 1)
1292169689Skan			  (match_dup 2))
1293169689Skan		 (match_dup 0)))
1294169689Skan   (clobber (match_scratch:SI 4 "=h"))]
1295169689Skan  "ISA_HAS_MACC && reload_completed"
1296169689Skan  "macc\t%3,%1,%2"
1297169689Skan  [(set_attr "type"	"imadd")
1298169689Skan   (set_attr "mode"	"SI")])
1299169689Skan
1300169689Skan(define_insn "*msac2"
1301169689Skan  [(set (match_operand:SI 0 "register_operand" "=l")
1302169689Skan	(minus:SI (match_dup 0)
1303169689Skan		  (mult:SI (match_operand:SI 1 "register_operand" "d")
1304169689Skan			   (match_operand:SI 2 "register_operand" "d"))))
1305169689Skan   (set (match_operand:SI 3 "register_operand" "=d")
1306169689Skan	(minus:SI (match_dup 0)
1307169689Skan		  (mult:SI (match_dup 1)
1308169689Skan			   (match_dup 2))))
1309169689Skan   (clobber (match_scratch:SI 4 "=h"))]
1310169689Skan  "ISA_HAS_MSAC && reload_completed"
1311169689Skan  "msac\t%3,%1,%2"
1312169689Skan  [(set_attr "type"	"imadd")
1313169689Skan   (set_attr "mode"	"SI")])
1314169689Skan
1315169689Skan;; Convert macc $0,<r1>,<r2> & mflo <r3> into macc <r3>,<r1>,<r2>
1316169689Skan;; Similarly msac.
1317169689Skan;;
1318169689Skan;; Operand 0: LO
1319169689Skan;; Operand 1: macc/msac
1320169689Skan;; Operand 2: HI
1321169689Skan;; Operand 3: GPR (destination)
1322169689Skan(define_peephole2
1323169689Skan  [(parallel
1324169689Skan       [(set (match_operand:SI 0 "register_operand")
1325169689Skan	     (match_operand:SI 1 "macc_msac_operand"))
1326169689Skan	(clobber (match_operand:SI 2 "register_operand"))
1327169689Skan	(clobber (scratch:SI))])
1328169689Skan   (set (match_operand:SI 3 "register_operand")
1329169689Skan	(unspec:SI [(match_dup 0) (match_dup 2)] UNSPEC_MFHILO))]
1330169689Skan  ""
1331169689Skan  [(parallel [(set (match_dup 0)
1332169689Skan		   (match_dup 1))
1333169689Skan	      (set (match_dup 3)
1334169689Skan		   (match_dup 1))
1335169689Skan	      (clobber (match_dup 2))])]
1336169689Skan  "")
1337169689Skan
1338169689Skan;; When we have a three-address multiplication instruction, it should
1339169689Skan;; be faster to do a separate multiply and add, rather than moving
1340169689Skan;; something into LO in order to use a macc instruction.
1341169689Skan;;
1342169689Skan;; This peephole needs a scratch register to cater for the case when one
1343169689Skan;; of the multiplication operands is the same as the destination.
1344169689Skan;;
1345169689Skan;; Operand 0: GPR (scratch)
1346169689Skan;; Operand 1: LO
1347169689Skan;; Operand 2: GPR (addend)
1348169689Skan;; Operand 3: GPR (destination)
1349169689Skan;; Operand 4: macc/msac
1350169689Skan;; Operand 5: HI
1351169689Skan;; Operand 6: new multiplication
1352169689Skan;; Operand 7: new addition/subtraction
1353169689Skan(define_peephole2
1354169689Skan  [(match_scratch:SI 0 "d")
1355169689Skan   (set (match_operand:SI 1 "register_operand")
1356169689Skan	(match_operand:SI 2 "register_operand"))
1357169689Skan   (match_dup 0)
1358169689Skan   (parallel
1359169689Skan       [(set (match_operand:SI 3 "register_operand")
1360169689Skan	     (match_operand:SI 4 "macc_msac_operand"))
1361169689Skan	(clobber (match_operand:SI 5 "register_operand"))
1362169689Skan	(clobber (match_dup 1))])]
1363169689Skan  "GENERATE_MULT3_SI
1364169689Skan   && true_regnum (operands[1]) == LO_REGNUM
1365169689Skan   && peep2_reg_dead_p (2, operands[1])
1366169689Skan   && GP_REG_P (true_regnum (operands[3]))"
1367169689Skan  [(parallel [(set (match_dup 0)
1368169689Skan		   (match_dup 6))
1369169689Skan	      (clobber (match_dup 5))
1370169689Skan	      (clobber (match_dup 1))])
1371169689Skan   (set (match_dup 3)
1372169689Skan	(match_dup 7))]
1373169689Skan{
1374169689Skan  operands[6] = XEXP (operands[4], GET_CODE (operands[4]) == PLUS ? 0 : 1);
1375169689Skan  operands[7] = gen_rtx_fmt_ee (GET_CODE (operands[4]), SImode,
1376169689Skan				operands[2], operands[0]);
1377169689Skan})
1378169689Skan
1379169689Skan;; Same as above, except LO is the initial target of the macc.
1380169689Skan;;
1381169689Skan;; Operand 0: GPR (scratch)
1382169689Skan;; Operand 1: LO
1383169689Skan;; Operand 2: GPR (addend)
1384169689Skan;; Operand 3: macc/msac
1385169689Skan;; Operand 4: HI
1386169689Skan;; Operand 5: GPR (destination)
1387169689Skan;; Operand 6: new multiplication
1388169689Skan;; Operand 7: new addition/subtraction
1389169689Skan(define_peephole2
1390169689Skan  [(match_scratch:SI 0 "d")
1391169689Skan   (set (match_operand:SI 1 "register_operand")
1392169689Skan	(match_operand:SI 2 "register_operand"))
1393169689Skan   (match_dup 0)
1394169689Skan   (parallel
1395169689Skan       [(set (match_dup 1)
1396169689Skan	     (match_operand:SI 3 "macc_msac_operand"))
1397169689Skan	(clobber (match_operand:SI 4 "register_operand"))
1398169689Skan	(clobber (scratch:SI))])
1399169689Skan   (match_dup 0)
1400169689Skan   (set (match_operand:SI 5 "register_operand")
1401169689Skan	(unspec:SI [(match_dup 1) (match_dup 4)] UNSPEC_MFHILO))]
1402169689Skan  "GENERATE_MULT3_SI && peep2_reg_dead_p (3, operands[1])"
1403169689Skan  [(parallel [(set (match_dup 0)
1404169689Skan		   (match_dup 6))
1405169689Skan	      (clobber (match_dup 4))
1406169689Skan	      (clobber (match_dup 1))])
1407169689Skan   (set (match_dup 5)
1408169689Skan	(match_dup 7))]
1409169689Skan{
1410169689Skan  operands[6] = XEXP (operands[4], GET_CODE (operands[4]) == PLUS ? 0 : 1);
1411169689Skan  operands[7] = gen_rtx_fmt_ee (GET_CODE (operands[4]), SImode,
1412169689Skan				operands[2], operands[0]);
1413169689Skan})
1414169689Skan
1415169689Skan(define_insn "*mul_sub_si"
1416169689Skan  [(set (match_operand:SI 0 "register_operand" "=l,*d,*d")
1417169689Skan        (minus:SI (match_operand:SI 1 "register_operand" "0,l,*d")
1418169689Skan                  (mult:SI (match_operand:SI 2 "register_operand" "d,d,d")
1419169689Skan                           (match_operand:SI 3 "register_operand" "d,d,d"))))
1420169689Skan   (clobber (match_scratch:SI 4 "=h,h,h"))
1421169689Skan   (clobber (match_scratch:SI 5 "=X,1,l"))
1422169689Skan   (clobber (match_scratch:SI 6 "=X,X,&d"))]
1423169689Skan  "ISA_HAS_MADD_MSUB"
1424169689Skan  "@
1425169689Skan   msub\t%2,%3
1426169689Skan   #
1427169689Skan   #"
1428169689Skan  [(set_attr "type"     "imadd,multi,multi")
1429169689Skan   (set_attr "mode"     "SI")
1430169689Skan   (set_attr "length"   "4,8,8")])
1431169689Skan
1432169689Skan;; Split the above insn if we failed to get LO allocated.
1433169689Skan(define_split
1434169689Skan  [(set (match_operand:SI 0 "register_operand")
1435169689Skan        (minus:SI (match_operand:SI 1 "register_operand")
1436169689Skan                  (mult:SI (match_operand:SI 2 "register_operand")
1437169689Skan                           (match_operand:SI 3 "register_operand"))))
1438169689Skan   (clobber (match_scratch:SI 4))
1439169689Skan   (clobber (match_scratch:SI 5))
1440169689Skan   (clobber (match_scratch:SI 6))]
1441169689Skan  "reload_completed && !TARGET_DEBUG_D_MODE
1442169689Skan   && GP_REG_P (true_regnum (operands[0]))
1443169689Skan   && GP_REG_P (true_regnum (operands[1]))"
1444169689Skan  [(parallel [(set (match_dup 6)
1445169689Skan                   (mult:SI (match_dup 2) (match_dup 3)))
1446169689Skan              (clobber (match_dup 4))
1447169689Skan              (clobber (match_dup 5))])
1448169689Skan   (set (match_dup 0) (minus:SI (match_dup 1) (match_dup 6)))]
1449169689Skan  "")
1450169689Skan
1451169689Skan;; Splitter to copy result of MSUB to a general register
1452169689Skan(define_split
1453169689Skan  [(set (match_operand:SI 0 "register_operand")
1454169689Skan        (minus:SI (match_operand:SI 1 "register_operand")
1455169689Skan                  (mult:SI (match_operand:SI 2 "register_operand")
1456169689Skan                           (match_operand:SI 3 "register_operand"))))
1457169689Skan   (clobber (match_scratch:SI 4))
1458169689Skan   (clobber (match_scratch:SI 5))
1459169689Skan   (clobber (match_scratch:SI 6))]
1460169689Skan  "reload_completed && !TARGET_DEBUG_D_MODE
1461169689Skan   && GP_REG_P (true_regnum (operands[0]))
1462169689Skan   && true_regnum (operands[1]) == LO_REGNUM"
1463169689Skan  [(parallel [(set (match_dup 1)
1464169689Skan                   (minus:SI (match_dup 1)
1465169689Skan                             (mult:SI (match_dup 2) (match_dup 3))))
1466169689Skan              (clobber (match_dup 4))
1467169689Skan              (clobber (match_dup 5))
1468169689Skan              (clobber (match_dup 6))])
1469169689Skan   (set (match_dup 0) (unspec:SI [(match_dup 5) (match_dup 4)] UNSPEC_MFHILO))]
1470169689Skan  "")
1471169689Skan
1472169689Skan(define_insn "*muls"
1473169689Skan  [(set (match_operand:SI                  0 "register_operand" "=l,d")
1474169689Skan        (neg:SI (mult:SI (match_operand:SI 1 "register_operand" "d,d")
1475169689Skan                         (match_operand:SI 2 "register_operand" "d,d"))))
1476169689Skan   (clobber (match_scratch:SI              3                    "=h,h"))
1477169689Skan   (clobber (match_scratch:SI              4                    "=X,l"))]
1478169689Skan  "ISA_HAS_MULS"
1479169689Skan  "@
1480169689Skan   muls\t$0,%1,%2
1481169689Skan   muls\t%0,%1,%2"
1482169689Skan  [(set_attr "type"     "imul,imul3")
1483169689Skan   (set_attr "mode"     "SI")])
1484169689Skan
1485169689Skan;; ??? We could define a mulditi3 pattern when TARGET_64BIT.
1486169689Skan
1487169689Skan(define_expand "<u>mulsidi3"
1488169689Skan  [(parallel
1489169689Skan      [(set (match_operand:DI 0 "register_operand")
1490169689Skan	    (mult:DI (any_extend:DI (match_operand:SI 1 "register_operand"))
1491169689Skan		     (any_extend:DI (match_operand:SI 2 "register_operand"))))
1492169689Skan       (clobber (scratch:DI))
1493169689Skan       (clobber (scratch:DI))
1494169689Skan       (clobber (scratch:DI))])]
1495169689Skan  "!TARGET_64BIT || !TARGET_FIX_R4000"
1496169689Skan{
1497169689Skan  if (!TARGET_64BIT)
1498169689Skan    {
1499169689Skan      if (!TARGET_FIX_R4000)
1500169689Skan	emit_insn (gen_<u>mulsidi3_32bit_internal (operands[0], operands[1],
1501169689Skan						   operands[2]));
1502169689Skan      else
1503169689Skan	emit_insn (gen_<u>mulsidi3_32bit_r4000 (operands[0], operands[1],
1504169689Skan					        operands[2]));
1505169689Skan      DONE;
1506169689Skan    }
1507169689Skan})
1508169689Skan
1509169689Skan(define_insn "<u>mulsidi3_32bit_internal"
1510169689Skan  [(set (match_operand:DI 0 "register_operand" "=x")
1511169689Skan	(mult:DI (any_extend:DI (match_operand:SI 1 "register_operand" "d"))
1512169689Skan		 (any_extend:DI (match_operand:SI 2 "register_operand" "d"))))]
1513169689Skan  "!TARGET_64BIT && !TARGET_FIX_R4000"
1514169689Skan  "mult<u>\t%1,%2"
1515169689Skan  [(set_attr "type" "imul")
1516169689Skan   (set_attr "mode" "SI")])
1517169689Skan
1518169689Skan(define_insn "<u>mulsidi3_32bit_r4000"
1519169689Skan  [(set (match_operand:DI 0 "register_operand" "=d")
1520169689Skan	(mult:DI (any_extend:DI (match_operand:SI 1 "register_operand" "d"))
1521169689Skan		 (any_extend:DI (match_operand:SI 2 "register_operand" "d"))))
1522169689Skan   (clobber (match_scratch:DI 3 "=x"))]
1523169689Skan  "!TARGET_64BIT && TARGET_FIX_R4000"
1524169689Skan  "mult<u>\t%1,%2\;mflo\t%L0;mfhi\t%M0"
1525169689Skan  [(set_attr "type" "imul")
1526169689Skan   (set_attr "mode" "SI")
1527169689Skan   (set_attr "length" "12")])
1528169689Skan
1529169689Skan(define_insn_and_split "*<u>mulsidi3_64bit"
1530169689Skan  [(set (match_operand:DI 0 "register_operand" "=d")
1531169689Skan	(mult:DI (any_extend:DI (match_operand:SI 1 "register_operand" "d"))
1532169689Skan		 (any_extend:DI (match_operand:SI 2 "register_operand" "d"))))
1533169689Skan   (clobber (match_scratch:DI 3 "=l"))
1534169689Skan   (clobber (match_scratch:DI 4 "=h"))
1535169689Skan   (clobber (match_scratch:DI 5 "=d"))]
1536169689Skan  "TARGET_64BIT && !TARGET_FIX_R4000"
1537169689Skan  "#"
1538169689Skan  "&& reload_completed"
1539169689Skan  [(parallel
1540169689Skan       [(set (match_dup 3)
1541169689Skan	     (sign_extend:DI
1542169689Skan		(mult:SI (match_dup 1)
1543169689Skan			 (match_dup 2))))
1544169689Skan	(set (match_dup 4)
1545169689Skan	     (ashiftrt:DI
1546169689Skan		(mult:DI (any_extend:DI (match_dup 1))
1547169689Skan			 (any_extend:DI (match_dup 2)))
1548169689Skan		(const_int 32)))])
1549169689Skan
1550169689Skan   ;; OP5 <- LO, OP0 <- HI
1551169689Skan   (set (match_dup 5) (unspec:DI [(match_dup 3) (match_dup 4)] UNSPEC_MFHILO))
1552169689Skan   (set (match_dup 0) (unspec:DI [(match_dup 4) (match_dup 3)] UNSPEC_MFHILO))
1553169689Skan
1554169689Skan   ;; Zero-extend OP5.
1555169689Skan   (set (match_dup 5)
1556169689Skan	(ashift:DI (match_dup 5)
1557169689Skan		   (const_int 32)))
1558169689Skan   (set (match_dup 5)
1559169689Skan	(lshiftrt:DI (match_dup 5)
1560169689Skan		     (const_int 32)))
1561169689Skan
1562169689Skan   ;; Shift OP0 into place.
1563169689Skan   (set (match_dup 0)
1564169689Skan	(ashift:DI (match_dup 0)
1565169689Skan		   (const_int 32)))
1566169689Skan
1567169689Skan   ;; OR the two halves together
1568169689Skan   (set (match_dup 0)
1569169689Skan	(ior:DI (match_dup 0)
1570169689Skan		(match_dup 5)))]
1571169689Skan  ""
1572169689Skan  [(set_attr "type" "imul")
1573169689Skan   (set_attr "mode" "SI")
1574169689Skan   (set_attr "length" "24")])
1575169689Skan
1576169689Skan(define_insn "*<u>mulsidi3_64bit_parts"
1577169689Skan  [(set (match_operand:DI 0 "register_operand" "=l")
1578169689Skan	(sign_extend:DI
1579169689Skan	   (mult:SI (match_operand:SI 2 "register_operand" "d")
1580169689Skan		    (match_operand:SI 3 "register_operand" "d"))))
1581169689Skan   (set (match_operand:DI 1 "register_operand" "=h")
1582169689Skan	(ashiftrt:DI
1583169689Skan	   (mult:DI (any_extend:DI (match_dup 2))
1584169689Skan		    (any_extend:DI (match_dup 3)))
1585169689Skan	   (const_int 32)))]
1586169689Skan  "TARGET_64BIT && !TARGET_FIX_R4000"
1587169689Skan  "mult<u>\t%2,%3"
1588169689Skan  [(set_attr "type" "imul")
1589169689Skan   (set_attr "mode" "SI")])
1590169689Skan
1591169689Skan;; Widening multiply with negation.
1592169689Skan(define_insn "*muls<u>_di"
1593169689Skan  [(set (match_operand:DI 0 "register_operand" "=x")
1594169689Skan        (neg:DI
1595169689Skan	 (mult:DI
1596169689Skan	  (any_extend:DI (match_operand:SI 1 "register_operand" "d"))
1597169689Skan	  (any_extend:DI (match_operand:SI 2 "register_operand" "d")))))]
1598169689Skan  "!TARGET_64BIT && ISA_HAS_MULS"
1599169689Skan  "muls<u>\t$0,%1,%2"
1600169689Skan  [(set_attr "type" "imul")
1601169689Skan   (set_attr "mode" "SI")])
1602169689Skan
1603169689Skan(define_insn "*msac<u>_di"
1604169689Skan  [(set (match_operand:DI 0 "register_operand" "=x")
1605169689Skan        (minus:DI
1606169689Skan	   (match_operand:DI 3 "register_operand" "0")
1607169689Skan	   (mult:DI
1608169689Skan	      (any_extend:DI (match_operand:SI 1 "register_operand" "d"))
1609169689Skan	      (any_extend:DI (match_operand:SI 2 "register_operand" "d")))))]
1610169689Skan  "!TARGET_64BIT && ISA_HAS_MSAC"
1611169689Skan{
1612169689Skan  if (TARGET_MIPS5500)
1613169689Skan    return "msub<u>\t%1,%2";
1614169689Skan  else
1615169689Skan    return "msac<u>\t$0,%1,%2";
1616169689Skan}
1617169689Skan  [(set_attr "type" "imadd")
1618169689Skan   (set_attr "mode" "SI")])
1619169689Skan
1620169689Skan;; _highpart patterns
1621169689Skan
1622169689Skan(define_expand "<su>mulsi3_highpart"
1623169689Skan  [(set (match_operand:SI 0 "register_operand")
1624169689Skan	(truncate:SI
1625169689Skan	 (lshiftrt:DI
1626169689Skan	  (mult:DI (any_extend:DI (match_operand:SI 1 "register_operand"))
1627169689Skan		   (any_extend:DI (match_operand:SI 2 "register_operand")))
1628169689Skan	  (const_int 32))))]
1629169689Skan  "ISA_HAS_MULHI || !TARGET_FIX_R4000"
1630169689Skan{
1631169689Skan  if (ISA_HAS_MULHI)
1632169689Skan    emit_insn (gen_<su>mulsi3_highpart_mulhi_internal (operands[0],
1633169689Skan						       operands[1],
1634169689Skan						       operands[2]));
1635169689Skan  else
1636169689Skan    emit_insn (gen_<su>mulsi3_highpart_internal (operands[0], operands[1],
1637169689Skan					         operands[2]));
1638169689Skan  DONE;
1639169689Skan})
1640169689Skan
1641169689Skan(define_insn "<su>mulsi3_highpart_internal"
1642169689Skan  [(set (match_operand:SI 0 "register_operand" "=h")
1643169689Skan	(truncate:SI
1644169689Skan	 (lshiftrt:DI
1645169689Skan	  (mult:DI (any_extend:DI (match_operand:SI 1 "register_operand" "d"))
1646169689Skan		   (any_extend:DI (match_operand:SI 2 "register_operand" "d")))
1647169689Skan	  (const_int 32))))
1648169689Skan   (clobber (match_scratch:SI 3 "=l"))]
1649169689Skan  "!ISA_HAS_MULHI && !TARGET_FIX_R4000"
1650169689Skan  "mult<u>\t%1,%2"
1651169689Skan  [(set_attr "type" "imul")
1652169689Skan   (set_attr "mode" "SI")])
1653169689Skan
1654169689Skan(define_insn "<su>mulsi3_highpart_mulhi_internal"
1655169689Skan  [(set (match_operand:SI 0 "register_operand" "=h,d")
1656169689Skan        (truncate:SI
1657169689Skan	 (lshiftrt:DI
1658169689Skan	  (mult:DI
1659169689Skan	   (any_extend:DI (match_operand:SI 1 "register_operand" "d,d"))
1660169689Skan	   (any_extend:DI (match_operand:SI 2 "register_operand" "d,d")))
1661169689Skan	  (const_int 32))))
1662169689Skan   (clobber (match_scratch:SI 3 "=l,l"))
1663169689Skan   (clobber (match_scratch:SI 4 "=X,h"))]
1664169689Skan  "ISA_HAS_MULHI"
1665169689Skan  "@
1666169689Skan   mult<u>\t%1,%2
1667169689Skan   mulhi<u>\t%0,%1,%2"
1668169689Skan  [(set_attr "type" "imul,imul3")
1669169689Skan   (set_attr "mode" "SI")])
1670169689Skan
1671169689Skan(define_insn "*<su>mulsi3_highpart_neg_mulhi_internal"
1672169689Skan  [(set (match_operand:SI 0 "register_operand" "=h,d")
1673169689Skan        (truncate:SI
1674169689Skan	 (lshiftrt:DI
1675169689Skan	  (neg:DI
1676169689Skan	   (mult:DI
1677169689Skan	    (any_extend:DI (match_operand:SI 1 "register_operand" "d,d"))
1678169689Skan	    (any_extend:DI (match_operand:SI 2 "register_operand" "d,d"))))
1679169689Skan	  (const_int 32))))
1680169689Skan   (clobber (match_scratch:SI 3 "=l,l"))
1681169689Skan   (clobber (match_scratch:SI 4 "=X,h"))]
1682169689Skan  "ISA_HAS_MULHI"
1683169689Skan  "@
1684169689Skan   mulshi<u>\t%.,%1,%2
1685169689Skan   mulshi<u>\t%0,%1,%2"
1686169689Skan  [(set_attr "type" "imul,imul3")
1687169689Skan   (set_attr "mode" "SI")])
1688169689Skan
1689169689Skan;; Disable unsigned multiplication for -mfix-vr4120.  This is for VR4120
1690169689Skan;; errata MD(0), which says that dmultu does not always produce the
1691169689Skan;; correct result.
1692169689Skan(define_insn "<su>muldi3_highpart"
1693169689Skan  [(set (match_operand:DI 0 "register_operand" "=h")
1694169689Skan	(truncate:DI
1695169689Skan	 (lshiftrt:TI
1696169689Skan	  (mult:TI
1697169689Skan	   (any_extend:TI (match_operand:DI 1 "register_operand" "d"))
1698169689Skan	   (any_extend:TI (match_operand:DI 2 "register_operand" "d")))
1699169689Skan	  (const_int 64))))
1700169689Skan   (clobber (match_scratch:DI 3 "=l"))]
1701169689Skan  "TARGET_64BIT && !TARGET_FIX_R4000
1702169689Skan   && !(<CODE> == ZERO_EXTEND && TARGET_FIX_VR4120)"
1703169689Skan  "dmult<u>\t%1,%2"
1704169689Skan  [(set_attr "type" "imul")
1705169689Skan   (set_attr "mode" "DI")])
1706169689Skan
1707169689Skan;; The R4650 supports a 32 bit multiply/ 64 bit accumulate
1708169689Skan;; instruction.  The HI/LO registers are used as a 64 bit accumulator.
1709169689Skan
1710169689Skan(define_insn "madsi"
1711169689Skan  [(set (match_operand:SI 0 "register_operand" "+l")
1712169689Skan	(plus:SI (mult:SI (match_operand:SI 1 "register_operand" "d")
1713169689Skan			  (match_operand:SI 2 "register_operand" "d"))
1714169689Skan		 (match_dup 0)))
1715169689Skan   (clobber (match_scratch:SI 3 "=h"))]
1716169689Skan  "TARGET_MAD"
1717169689Skan  "mad\t%1,%2"
1718169689Skan  [(set_attr "type"	"imadd")
1719169689Skan   (set_attr "mode"	"SI")])
1720169689Skan
1721169689Skan(define_insn "*<su>mul_acc_di"
1722169689Skan  [(set (match_operand:DI 0 "register_operand" "=x")
1723169689Skan	(plus:DI
1724169689Skan	 (mult:DI (any_extend:DI (match_operand:SI 1 "register_operand" "d"))
1725169689Skan		  (any_extend:DI (match_operand:SI 2 "register_operand" "d")))
1726169689Skan	 (match_operand:DI 3 "register_operand" "0")))]
1727169689Skan  "(TARGET_MAD || ISA_HAS_MACC)
1728169689Skan   && !TARGET_64BIT"
1729169689Skan{
1730169689Skan  if (TARGET_MAD)
1731169689Skan    return "mad<u>\t%1,%2";
1732169689Skan  else if (TARGET_MIPS5500)
1733169689Skan    return "madd<u>\t%1,%2";
1734169689Skan  else
1735169689Skan    /* See comment in *macc.  */
1736169689Skan    return "%[macc<u>\t%@,%1,%2%]";
1737169689Skan}
1738169689Skan  [(set_attr "type" "imadd")
1739169689Skan   (set_attr "mode" "SI")])
1740169689Skan
1741169689Skan;; Floating point multiply accumulate instructions.
1742169689Skan
1743169689Skan(define_insn "*madd<mode>"
1744169689Skan  [(set (match_operand:ANYF 0 "register_operand" "=f")
1745169689Skan	(plus:ANYF (mult:ANYF (match_operand:ANYF 1 "register_operand" "f")
1746169689Skan			      (match_operand:ANYF 2 "register_operand" "f"))
1747169689Skan		   (match_operand:ANYF 3 "register_operand" "f")))]
1748169689Skan  "ISA_HAS_FP4 && TARGET_FUSED_MADD"
1749169689Skan  "madd.<fmt>\t%0,%3,%1,%2"
1750169689Skan  [(set_attr "type" "fmadd")
1751169689Skan   (set_attr "mode" "<UNITMODE>")])
1752169689Skan
1753169689Skan(define_insn "*msub<mode>"
1754169689Skan  [(set (match_operand:ANYF 0 "register_operand" "=f")
1755169689Skan	(minus:ANYF (mult:ANYF (match_operand:ANYF 1 "register_operand" "f")
1756169689Skan			       (match_operand:ANYF 2 "register_operand" "f"))
1757169689Skan		    (match_operand:ANYF 3 "register_operand" "f")))]
1758169689Skan  "ISA_HAS_FP4 && TARGET_FUSED_MADD"
1759169689Skan  "msub.<fmt>\t%0,%3,%1,%2"
1760169689Skan  [(set_attr "type" "fmadd")
1761169689Skan   (set_attr "mode" "<UNITMODE>")])
1762169689Skan
1763169689Skan(define_insn "*nmadd<mode>"
1764169689Skan  [(set (match_operand:ANYF 0 "register_operand" "=f")
1765169689Skan	(neg:ANYF (plus:ANYF
1766169689Skan		   (mult:ANYF (match_operand:ANYF 1 "register_operand" "f")
1767169689Skan			      (match_operand:ANYF 2 "register_operand" "f"))
1768169689Skan		   (match_operand:ANYF 3 "register_operand" "f"))))]
1769169689Skan  "ISA_HAS_NMADD_NMSUB && TARGET_FUSED_MADD
1770169689Skan   && HONOR_SIGNED_ZEROS (<MODE>mode)
1771169689Skan   && !HONOR_NANS (<MODE>mode)"
1772169689Skan  "nmadd.<fmt>\t%0,%3,%1,%2"
1773169689Skan  [(set_attr "type" "fmadd")
1774169689Skan   (set_attr "mode" "<UNITMODE>")])
1775169689Skan
1776169689Skan(define_insn "*nmadd<mode>_fastmath"
1777169689Skan  [(set (match_operand:ANYF 0 "register_operand" "=f")
1778169689Skan	(minus:ANYF
1779169689Skan	 (mult:ANYF (neg:ANYF (match_operand:ANYF 1 "register_operand" "f"))
1780169689Skan		    (match_operand:ANYF 2 "register_operand" "f"))
1781169689Skan	 (match_operand:ANYF 3 "register_operand" "f")))]
1782169689Skan  "ISA_HAS_NMADD_NMSUB && TARGET_FUSED_MADD
1783169689Skan   && !HONOR_SIGNED_ZEROS (<MODE>mode)
1784169689Skan   && !HONOR_NANS (<MODE>mode)"
1785169689Skan  "nmadd.<fmt>\t%0,%3,%1,%2"
1786169689Skan  [(set_attr "type" "fmadd")
1787169689Skan   (set_attr "mode" "<UNITMODE>")])
1788169689Skan
1789169689Skan(define_insn "*nmsub<mode>"
1790169689Skan  [(set (match_operand:ANYF 0 "register_operand" "=f")
1791169689Skan	(neg:ANYF (minus:ANYF
1792169689Skan		   (mult:ANYF (match_operand:ANYF 2 "register_operand" "f")
1793169689Skan			      (match_operand:ANYF 3 "register_operand" "f"))
1794169689Skan		   (match_operand:ANYF 1 "register_operand" "f"))))]
1795169689Skan  "ISA_HAS_NMADD_NMSUB && TARGET_FUSED_MADD
1796169689Skan   && HONOR_SIGNED_ZEROS (<MODE>mode)
1797169689Skan   && !HONOR_NANS (<MODE>mode)"
1798169689Skan  "nmsub.<fmt>\t%0,%1,%2,%3"
1799169689Skan  [(set_attr "type" "fmadd")
1800169689Skan   (set_attr "mode" "<UNITMODE>")])
1801169689Skan
1802169689Skan(define_insn "*nmsub<mode>_fastmath"
1803169689Skan  [(set (match_operand:ANYF 0 "register_operand" "=f")
1804169689Skan	(minus:ANYF
1805169689Skan	 (match_operand:ANYF 1 "register_operand" "f")
1806169689Skan	 (mult:ANYF (match_operand:ANYF 2 "register_operand" "f")
1807169689Skan		    (match_operand:ANYF 3 "register_operand" "f"))))]
1808169689Skan  "ISA_HAS_NMADD_NMSUB && TARGET_FUSED_MADD
1809169689Skan   && !HONOR_SIGNED_ZEROS (<MODE>mode)
1810169689Skan   && !HONOR_NANS (<MODE>mode)"
1811169689Skan  "nmsub.<fmt>\t%0,%1,%2,%3"
1812169689Skan  [(set_attr "type" "fmadd")
1813169689Skan   (set_attr "mode" "<UNITMODE>")])
1814169689Skan
1815169689Skan;;
1816169689Skan;;  ....................
1817169689Skan;;
1818169689Skan;;	DIVISION and REMAINDER
1819169689Skan;;
1820169689Skan;;  ....................
1821169689Skan;;
1822169689Skan
1823169689Skan(define_expand "div<mode>3"
1824169689Skan  [(set (match_operand:ANYF 0 "register_operand")
1825169689Skan	(div:ANYF (match_operand:ANYF 1 "reg_or_1_operand")
1826169689Skan		  (match_operand:ANYF 2 "register_operand")))]
1827169689Skan  "<divide_condition>"
1828169689Skan{
1829169689Skan  if (const_1_operand (operands[1], <MODE>mode))
1830169689Skan    if (!(ISA_HAS_FP4 && flag_unsafe_math_optimizations))
1831169689Skan      operands[1] = force_reg (<MODE>mode, operands[1]);
1832169689Skan})
1833169689Skan
1834169689Skan;; These patterns work around the early SB-1 rev2 core "F1" erratum:
1835169689Skan;;
1836169689Skan;; If an mfc1 or dmfc1 happens to access the floating point register
1837169689Skan;; file at the same time a long latency operation (div, sqrt, recip,
1838169689Skan;; sqrt) iterates an intermediate result back through the floating
1839169689Skan;; point register file bypass, then instead returning the correct
1840169689Skan;; register value the mfc1 or dmfc1 operation returns the intermediate
1841169689Skan;; result of the long latency operation.
1842169689Skan;;
1843169689Skan;; The workaround is to insert an unconditional 'mov' from/to the
1844169689Skan;; long latency op destination register.
1845169689Skan
1846169689Skan(define_insn "*div<mode>3"
1847169689Skan  [(set (match_operand:ANYF 0 "register_operand" "=f")
1848169689Skan	(div:ANYF (match_operand:ANYF 1 "register_operand" "f")
1849169689Skan		  (match_operand:ANYF 2 "register_operand" "f")))]
1850169689Skan  "<divide_condition>"
1851169689Skan{
1852169689Skan  if (TARGET_FIX_SB1)
1853169689Skan    return "div.<fmt>\t%0,%1,%2\;mov.<fmt>\t%0,%0";
1854169689Skan  else
1855169689Skan    return "div.<fmt>\t%0,%1,%2";
1856169689Skan}
1857169689Skan  [(set_attr "type" "fdiv")
1858169689Skan   (set_attr "mode" "<UNITMODE>")
1859169689Skan   (set (attr "length")
1860169689Skan        (if_then_else (ne (symbol_ref "TARGET_FIX_SB1") (const_int 0))
1861169689Skan                      (const_int 8)
1862169689Skan                      (const_int 4)))])
1863169689Skan
1864169689Skan(define_insn "*recip<mode>3"
1865169689Skan  [(set (match_operand:ANYF 0 "register_operand" "=f")
1866169689Skan	(div:ANYF (match_operand:ANYF 1 "const_1_operand" "")
1867169689Skan		  (match_operand:ANYF 2 "register_operand" "f")))]
1868169689Skan  "<recip_condition> && flag_unsafe_math_optimizations"
1869169689Skan{
1870169689Skan  if (TARGET_FIX_SB1)
1871169689Skan    return "recip.<fmt>\t%0,%2\;mov.<fmt>\t%0,%0";
1872169689Skan  else
1873169689Skan    return "recip.<fmt>\t%0,%2";
1874169689Skan}
1875169689Skan  [(set_attr "type" "frdiv")
1876169689Skan   (set_attr "mode" "<UNITMODE>")
1877169689Skan   (set (attr "length")
1878169689Skan        (if_then_else (ne (symbol_ref "TARGET_FIX_SB1") (const_int 0))
1879169689Skan                      (const_int 8)
1880169689Skan                      (const_int 4)))])
1881169689Skan
1882169689Skan;; VR4120 errata MD(A1): signed division instructions do not work correctly
1883169689Skan;; with negative operands.  We use special libgcc functions instead.
1884169689Skan(define_insn "divmod<mode>4"
1885169689Skan  [(set (match_operand:GPR 0 "register_operand" "=l")
1886169689Skan	(div:GPR (match_operand:GPR 1 "register_operand" "d")
1887169689Skan		 (match_operand:GPR 2 "register_operand" "d")))
1888169689Skan   (set (match_operand:GPR 3 "register_operand" "=h")
1889169689Skan	(mod:GPR (match_dup 1)
1890169689Skan		 (match_dup 2)))]
1891169689Skan  "!TARGET_FIX_VR4120"
1892169689Skan  { return mips_output_division ("<d>div\t$0,%1,%2", operands); }
1893169689Skan  [(set_attr "type" "idiv")
1894169689Skan   (set_attr "mode" "<MODE>")])
1895169689Skan
1896169689Skan(define_insn "udivmod<mode>4"
1897169689Skan  [(set (match_operand:GPR 0 "register_operand" "=l")
1898169689Skan	(udiv:GPR (match_operand:GPR 1 "register_operand" "d")
1899169689Skan		  (match_operand:GPR 2 "register_operand" "d")))
1900169689Skan   (set (match_operand:GPR 3 "register_operand" "=h")
1901169689Skan	(umod:GPR (match_dup 1)
1902169689Skan		  (match_dup 2)))]
1903169689Skan  ""
1904169689Skan  { return mips_output_division ("<d>divu\t$0,%1,%2", operands); }
1905169689Skan  [(set_attr "type" "idiv")
1906169689Skan   (set_attr "mode" "<MODE>")])
1907169689Skan
1908169689Skan;;
1909169689Skan;;  ....................
1910169689Skan;;
1911169689Skan;;	SQUARE ROOT
1912169689Skan;;
1913169689Skan;;  ....................
1914169689Skan
1915169689Skan;; These patterns work around the early SB-1 rev2 core "F1" erratum (see
1916169689Skan;; "*div[sd]f3" comment for details).
1917169689Skan
1918169689Skan(define_insn "sqrt<mode>2"
1919169689Skan  [(set (match_operand:ANYF 0 "register_operand" "=f")
1920169689Skan	(sqrt:ANYF (match_operand:ANYF 1 "register_operand" "f")))]
1921169689Skan  "<sqrt_condition>"
1922169689Skan{
1923169689Skan  if (TARGET_FIX_SB1)
1924169689Skan    return "sqrt.<fmt>\t%0,%1\;mov.<fmt>\t%0,%0";
1925169689Skan  else
1926169689Skan    return "sqrt.<fmt>\t%0,%1";
1927169689Skan}
1928169689Skan  [(set_attr "type" "fsqrt")
1929169689Skan   (set_attr "mode" "<UNITMODE>")
1930169689Skan   (set (attr "length")
1931169689Skan        (if_then_else (ne (symbol_ref "TARGET_FIX_SB1") (const_int 0))
1932169689Skan                      (const_int 8)
1933169689Skan                      (const_int 4)))])
1934169689Skan
1935169689Skan(define_insn "*rsqrt<mode>a"
1936169689Skan  [(set (match_operand:ANYF 0 "register_operand" "=f")
1937169689Skan	(div:ANYF (match_operand:ANYF 1 "const_1_operand" "")
1938169689Skan		  (sqrt:ANYF (match_operand:ANYF 2 "register_operand" "f"))))]
1939169689Skan  "<recip_condition> && flag_unsafe_math_optimizations"
1940169689Skan{
1941169689Skan  if (TARGET_FIX_SB1)
1942169689Skan    return "rsqrt.<fmt>\t%0,%2\;mov.<fmt>\t%0,%0";
1943169689Skan  else
1944169689Skan    return "rsqrt.<fmt>\t%0,%2";
1945169689Skan}
1946169689Skan  [(set_attr "type" "frsqrt")
1947169689Skan   (set_attr "mode" "<UNITMODE>")
1948169689Skan   (set (attr "length")
1949169689Skan        (if_then_else (ne (symbol_ref "TARGET_FIX_SB1") (const_int 0))
1950169689Skan                      (const_int 8)
1951169689Skan                      (const_int 4)))])
1952169689Skan
1953169689Skan(define_insn "*rsqrt<mode>b"
1954169689Skan  [(set (match_operand:ANYF 0 "register_operand" "=f")
1955169689Skan	(sqrt:ANYF (div:ANYF (match_operand:ANYF 1 "const_1_operand" "")
1956169689Skan			     (match_operand:ANYF 2 "register_operand" "f"))))]
1957169689Skan  "<recip_condition> && flag_unsafe_math_optimizations"
1958169689Skan{
1959169689Skan  if (TARGET_FIX_SB1)
1960169689Skan    return "rsqrt.<fmt>\t%0,%2\;mov.<fmt>\t%0,%0";
1961169689Skan  else
1962169689Skan    return "rsqrt.<fmt>\t%0,%2";
1963169689Skan}
1964169689Skan  [(set_attr "type" "frsqrt")
1965169689Skan   (set_attr "mode" "<UNITMODE>")
1966169689Skan   (set (attr "length")
1967169689Skan        (if_then_else (ne (symbol_ref "TARGET_FIX_SB1") (const_int 0))
1968169689Skan                      (const_int 8)
1969169689Skan                      (const_int 4)))])
1970169689Skan
1971169689Skan;;
1972169689Skan;;  ....................
1973169689Skan;;
1974169689Skan;;	ABSOLUTE VALUE
1975169689Skan;;
1976169689Skan;;  ....................
1977169689Skan
1978169689Skan;; Do not use the integer abs macro instruction, since that signals an
1979169689Skan;; exception on -2147483648 (sigh).
1980169689Skan
1981169689Skan;; abs.fmt is an arithmetic instruction and treats all NaN inputs as
1982169689Skan;; invalid; it does not clear their sign bits.  We therefore can't use
1983169689Skan;; abs.fmt if the signs of NaNs matter.
1984169689Skan
1985169689Skan(define_insn "abs<mode>2"
1986169689Skan  [(set (match_operand:ANYF 0 "register_operand" "=f")
1987169689Skan	(abs:ANYF (match_operand:ANYF 1 "register_operand" "f")))]
1988169689Skan  "!HONOR_NANS (<MODE>mode)"
1989169689Skan  "abs.<fmt>\t%0,%1"
1990169689Skan  [(set_attr "type" "fabs")
1991169689Skan   (set_attr "mode" "<UNITMODE>")])
1992169689Skan
1993169689Skan;;
1994169689Skan;;  ...................
1995169689Skan;;
1996169689Skan;;  Count leading zeroes.
1997169689Skan;;
1998169689Skan;;  ...................
1999169689Skan;;
2000169689Skan
2001169689Skan(define_insn "clz<mode>2"
2002169689Skan  [(set (match_operand:GPR 0 "register_operand" "=d")
2003169689Skan	(clz:GPR (match_operand:GPR 1 "register_operand" "d")))]
2004169689Skan  "ISA_HAS_CLZ_CLO"
2005169689Skan  "<d>clz\t%0,%1"
2006169689Skan  [(set_attr "type" "clz")
2007169689Skan   (set_attr "mode" "<MODE>")])
2008169689Skan
2009169689Skan;;
2010169689Skan;;  ....................
2011169689Skan;;
2012169689Skan;;	NEGATION and ONE'S COMPLEMENT
2013169689Skan;;
2014169689Skan;;  ....................
2015169689Skan
2016169689Skan(define_insn "negsi2"
2017169689Skan  [(set (match_operand:SI 0 "register_operand" "=d")
2018169689Skan	(neg:SI (match_operand:SI 1 "register_operand" "d")))]
2019169689Skan  ""
2020169689Skan{
2021169689Skan  if (TARGET_MIPS16)
2022169689Skan    return "neg\t%0,%1";
2023169689Skan  else
2024169689Skan    return "subu\t%0,%.,%1";
2025169689Skan}
2026169689Skan  [(set_attr "type"	"arith")
2027169689Skan   (set_attr "mode"	"SI")])
2028169689Skan
2029169689Skan(define_insn "negdi2"
2030169689Skan  [(set (match_operand:DI 0 "register_operand" "=d")
2031169689Skan	(neg:DI (match_operand:DI 1 "register_operand" "d")))]
2032169689Skan  "TARGET_64BIT && !TARGET_MIPS16"
2033169689Skan  "dsubu\t%0,%.,%1"
2034169689Skan  [(set_attr "type"	"arith")
2035169689Skan   (set_attr "mode"	"DI")])
2036169689Skan
2037169689Skan;; neg.fmt is an arithmetic instruction and treats all NaN inputs as
2038169689Skan;; invalid; it does not flip their sign bit.  We therefore can't use
2039169689Skan;; neg.fmt if the signs of NaNs matter.
2040169689Skan
2041169689Skan(define_insn "neg<mode>2"
2042169689Skan  [(set (match_operand:ANYF 0 "register_operand" "=f")
2043169689Skan	(neg:ANYF (match_operand:ANYF 1 "register_operand" "f")))]
2044169689Skan  "!HONOR_NANS (<MODE>mode)"
2045169689Skan  "neg.<fmt>\t%0,%1"
2046169689Skan  [(set_attr "type" "fneg")
2047169689Skan   (set_attr "mode" "<UNITMODE>")])
2048169689Skan
2049169689Skan(define_insn "one_cmpl<mode>2"
2050169689Skan  [(set (match_operand:GPR 0 "register_operand" "=d")
2051169689Skan	(not:GPR (match_operand:GPR 1 "register_operand" "d")))]
2052169689Skan  ""
2053169689Skan{
2054169689Skan  if (TARGET_MIPS16)
2055169689Skan    return "not\t%0,%1";
2056169689Skan  else
2057169689Skan    return "nor\t%0,%.,%1";
2058169689Skan}
2059169689Skan  [(set_attr "type" "arith")
2060169689Skan   (set_attr "mode" "<MODE>")])
2061169689Skan
2062169689Skan;;
2063169689Skan;;  ....................
2064169689Skan;;
2065169689Skan;;	LOGICAL
2066169689Skan;;
2067169689Skan;;  ....................
2068169689Skan;;
2069169689Skan
2070169689Skan;; Many of these instructions use trivial define_expands, because we
2071169689Skan;; want to use a different set of constraints when TARGET_MIPS16.
2072169689Skan
2073169689Skan(define_expand "and<mode>3"
2074169689Skan  [(set (match_operand:GPR 0 "register_operand")
2075169689Skan	(and:GPR (match_operand:GPR 1 "register_operand")
2076169689Skan		 (match_operand:GPR 2 "uns_arith_operand")))]
2077169689Skan  ""
2078169689Skan{
2079169689Skan  if (TARGET_MIPS16)
2080169689Skan    operands[2] = force_reg (<MODE>mode, operands[2]);
2081169689Skan})
2082169689Skan
2083169689Skan(define_insn "*and<mode>3"
2084169689Skan  [(set (match_operand:GPR 0 "register_operand" "=d,d")
2085169689Skan	(and:GPR (match_operand:GPR 1 "register_operand" "%d,d")
2086169689Skan		 (match_operand:GPR 2 "uns_arith_operand" "d,K")))]
2087169689Skan  "!TARGET_MIPS16"
2088169689Skan  "@
2089169689Skan   and\t%0,%1,%2
2090169689Skan   andi\t%0,%1,%x2"
2091169689Skan  [(set_attr "type" "arith")
2092169689Skan   (set_attr "mode" "<MODE>")])
2093169689Skan
2094169689Skan(define_insn "*and<mode>3_mips16"
2095169689Skan  [(set (match_operand:GPR 0 "register_operand" "=d")
2096169689Skan	(and:GPR (match_operand:GPR 1 "register_operand" "%0")
2097169689Skan		 (match_operand:GPR 2 "register_operand" "d")))]
2098169689Skan  "TARGET_MIPS16"
2099169689Skan  "and\t%0,%2"
2100169689Skan  [(set_attr "type" "arith")
2101169689Skan   (set_attr "mode" "<MODE>")])
2102169689Skan
2103169689Skan(define_expand "ior<mode>3"
2104169689Skan  [(set (match_operand:GPR 0 "register_operand")
2105169689Skan	(ior:GPR (match_operand:GPR 1 "register_operand")
2106169689Skan		 (match_operand:GPR 2 "uns_arith_operand")))]
2107169689Skan  ""
2108169689Skan{
2109169689Skan  if (TARGET_MIPS16)
2110169689Skan    operands[2] = force_reg (<MODE>mode, operands[2]);
2111169689Skan})
2112169689Skan
2113169689Skan(define_insn "*ior<mode>3"
2114169689Skan  [(set (match_operand:GPR 0 "register_operand" "=d,d")
2115169689Skan	(ior:GPR (match_operand:GPR 1 "register_operand" "%d,d")
2116169689Skan		 (match_operand:GPR 2 "uns_arith_operand" "d,K")))]
2117169689Skan  "!TARGET_MIPS16"
2118169689Skan  "@
2119169689Skan   or\t%0,%1,%2
2120169689Skan   ori\t%0,%1,%x2"
2121169689Skan  [(set_attr "type" "arith")
2122169689Skan   (set_attr "mode" "<MODE>")])
2123169689Skan
2124169689Skan(define_insn "*ior<mode>3_mips16"
2125169689Skan  [(set (match_operand:GPR 0 "register_operand" "=d")
2126169689Skan	(ior:GPR (match_operand:GPR 1 "register_operand" "%0")
2127169689Skan		 (match_operand:GPR 2 "register_operand" "d")))]
2128169689Skan  "TARGET_MIPS16"
2129169689Skan  "or\t%0,%2"
2130169689Skan  [(set_attr "type" "arith")
2131169689Skan   (set_attr "mode" "<MODE>")])
2132169689Skan
2133169689Skan(define_expand "xor<mode>3"
2134169689Skan  [(set (match_operand:GPR 0 "register_operand")
2135169689Skan	(xor:GPR (match_operand:GPR 1 "register_operand")
2136169689Skan		 (match_operand:GPR 2 "uns_arith_operand")))]
2137169689Skan  ""
2138169689Skan  "")
2139169689Skan
2140169689Skan(define_insn ""
2141169689Skan  [(set (match_operand:GPR 0 "register_operand" "=d,d")
2142169689Skan	(xor:GPR (match_operand:GPR 1 "register_operand" "%d,d")
2143169689Skan		 (match_operand:GPR 2 "uns_arith_operand" "d,K")))]
2144169689Skan  "!TARGET_MIPS16"
2145169689Skan  "@
2146169689Skan   xor\t%0,%1,%2
2147169689Skan   xori\t%0,%1,%x2"
2148169689Skan  [(set_attr "type" "arith")
2149169689Skan   (set_attr "mode" "<MODE>")])
2150169689Skan
2151169689Skan(define_insn ""
2152169689Skan  [(set (match_operand:GPR 0 "register_operand" "=d,t,t")
2153169689Skan	(xor:GPR (match_operand:GPR 1 "register_operand" "%0,d,d")
2154169689Skan		 (match_operand:GPR 2 "uns_arith_operand" "d,K,d")))]
2155169689Skan  "TARGET_MIPS16"
2156169689Skan  "@
2157169689Skan   xor\t%0,%2
2158169689Skan   cmpi\t%1,%2
2159169689Skan   cmp\t%1,%2"
2160169689Skan  [(set_attr "type" "arith")
2161169689Skan   (set_attr "mode" "<MODE>")
2162169689Skan   (set_attr_alternative "length"
2163169689Skan		[(const_int 4)
2164169689Skan		 (if_then_else (match_operand:VOID 2 "m16_uimm8_1")
2165169689Skan			       (const_int 4)
2166169689Skan			       (const_int 8))
2167169689Skan		 (const_int 4)])])
2168169689Skan
2169169689Skan(define_insn "*nor<mode>3"
2170169689Skan  [(set (match_operand:GPR 0 "register_operand" "=d")
2171169689Skan	(and:GPR (not:GPR (match_operand:GPR 1 "register_operand" "d"))
2172169689Skan		 (not:GPR (match_operand:GPR 2 "register_operand" "d"))))]
2173169689Skan  "!TARGET_MIPS16"
2174169689Skan  "nor\t%0,%1,%2"
2175169689Skan  [(set_attr "type" "arith")
2176169689Skan   (set_attr "mode" "<MODE>")])
2177169689Skan
2178169689Skan;;
2179169689Skan;;  ....................
2180169689Skan;;
2181169689Skan;;	TRUNCATION
2182169689Skan;;
2183169689Skan;;  ....................
2184169689Skan
2185169689Skan
2186169689Skan
2187169689Skan(define_insn "truncdfsf2"
2188169689Skan  [(set (match_operand:SF 0 "register_operand" "=f")
2189169689Skan	(float_truncate:SF (match_operand:DF 1 "register_operand" "f")))]
2190169689Skan  "TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT"
2191169689Skan  "cvt.s.d\t%0,%1"
2192169689Skan  [(set_attr "type"	"fcvt")
2193169689Skan   (set_attr "cnv_mode"	"D2S")   
2194169689Skan   (set_attr "mode"	"SF")])
2195169689Skan
2196169689Skan;; Integer truncation patterns.  Truncating SImode values to smaller
2197169689Skan;; modes is a no-op, as it is for most other GCC ports.  Truncating
2198169689Skan;; DImode values to SImode is not a no-op for TARGET_64BIT since we
2199169689Skan;; need to make sure that the lower 32 bits are properly sign-extended
2200169689Skan;; (see TRULY_NOOP_TRUNCATION).  Truncating DImode values into modes
2201169689Skan;; smaller than SImode is equivalent to two separate truncations:
2202169689Skan;;
2203169689Skan;;                        A       B
2204169689Skan;;    DI ---> HI  ==  DI ---> SI ---> HI
2205169689Skan;;    DI ---> QI  ==  DI ---> SI ---> QI
2206169689Skan;;
2207169689Skan;; Step A needs a real instruction but step B does not.
2208169689Skan
2209169689Skan(define_insn "truncdisi2"
2210169689Skan  [(set (match_operand:SI 0 "nonimmediate_operand" "=d,m")
2211169689Skan        (truncate:SI (match_operand:DI 1 "register_operand" "d,d")))]
2212169689Skan  "TARGET_64BIT"
2213169689Skan  "@
2214169689Skan    sll\t%0,%1,0
2215169689Skan    sw\t%1,%0"
2216169689Skan  [(set_attr "type" "shift,store")
2217169689Skan   (set_attr "mode" "SI")
2218169689Skan   (set_attr "extended_mips16" "yes,*")])
2219169689Skan
2220169689Skan(define_insn "truncdihi2"
2221169689Skan  [(set (match_operand:HI 0 "nonimmediate_operand" "=d,m")
2222169689Skan        (truncate:HI (match_operand:DI 1 "register_operand" "d,d")))]
2223169689Skan  "TARGET_64BIT"
2224169689Skan  "@
2225169689Skan    sll\t%0,%1,0
2226169689Skan    sh\t%1,%0"
2227169689Skan  [(set_attr "type" "shift,store")
2228169689Skan   (set_attr "mode" "SI")
2229169689Skan   (set_attr "extended_mips16" "yes,*")])
2230169689Skan
2231169689Skan(define_insn "truncdiqi2"
2232169689Skan  [(set (match_operand:QI 0 "nonimmediate_operand" "=d,m")
2233169689Skan        (truncate:QI (match_operand:DI 1 "register_operand" "d,d")))]
2234169689Skan  "TARGET_64BIT"
2235169689Skan  "@
2236169689Skan    sll\t%0,%1,0
2237169689Skan    sb\t%1,%0"
2238169689Skan  [(set_attr "type" "shift,store")
2239169689Skan   (set_attr "mode" "SI")
2240169689Skan   (set_attr "extended_mips16" "yes,*")])
2241169689Skan
2242169689Skan;; Combiner patterns to optimize shift/truncate combinations.
2243169689Skan
2244169689Skan(define_insn ""
2245169689Skan  [(set (match_operand:SI 0 "register_operand" "=d")
2246169689Skan        (truncate:SI
2247169689Skan	  (ashiftrt:DI (match_operand:DI 1 "register_operand" "d")
2248169689Skan                       (match_operand:DI 2 "const_arith_operand" ""))))]
2249169689Skan  "TARGET_64BIT && !TARGET_MIPS16 && INTVAL (operands[2]) >= 32"
2250169689Skan  "dsra\t%0,%1,%2"
2251169689Skan  [(set_attr "type" "shift")
2252169689Skan   (set_attr "mode" "SI")])
2253169689Skan
2254169689Skan(define_insn ""
2255169689Skan  [(set (match_operand:SI 0 "register_operand" "=d")
2256169689Skan        (truncate:SI (lshiftrt:DI (match_operand:DI 1 "register_operand" "d")
2257169689Skan                                  (const_int 32))))]
2258169689Skan  "TARGET_64BIT && !TARGET_MIPS16"
2259169689Skan  "dsra\t%0,%1,32"
2260169689Skan  [(set_attr "type" "shift")
2261169689Skan   (set_attr "mode" "SI")])
2262169689Skan
2263169689Skan
2264169689Skan;; Combiner patterns for truncate/sign_extend combinations.  They use
2265169689Skan;; the shift/truncate patterns above.
2266169689Skan
2267169689Skan(define_insn_and_split ""
2268169689Skan  [(set (match_operand:SI 0 "register_operand" "=d")
2269169689Skan	(sign_extend:SI
2270169689Skan	    (truncate:HI (match_operand:DI 1 "register_operand" "d"))))]
2271169689Skan  "TARGET_64BIT && !TARGET_MIPS16"
2272169689Skan  "#"
2273169689Skan  "&& reload_completed"
2274169689Skan  [(set (match_dup 2)
2275169689Skan	(ashift:DI (match_dup 1)
2276169689Skan		   (const_int 48)))
2277169689Skan   (set (match_dup 0)
2278169689Skan	(truncate:SI (ashiftrt:DI (match_dup 2)
2279169689Skan				  (const_int 48))))]
2280169689Skan  { operands[2] = gen_lowpart (DImode, operands[0]); })
2281169689Skan
2282169689Skan(define_insn_and_split ""
2283169689Skan  [(set (match_operand:SI 0 "register_operand" "=d")
2284169689Skan	(sign_extend:SI
2285169689Skan	    (truncate:QI (match_operand:DI 1 "register_operand" "d"))))]
2286169689Skan  "TARGET_64BIT && !TARGET_MIPS16"
2287169689Skan  "#"
2288169689Skan  "&& reload_completed"
2289169689Skan  [(set (match_dup 2)
2290169689Skan	(ashift:DI (match_dup 1)
2291169689Skan		   (const_int 56)))
2292169689Skan   (set (match_dup 0)
2293169689Skan	(truncate:SI (ashiftrt:DI (match_dup 2)
2294169689Skan				  (const_int 56))))]
2295169689Skan  { operands[2] = gen_lowpart (DImode, operands[0]); })
2296169689Skan
2297169689Skan
2298169689Skan;; Combiner patterns to optimize truncate/zero_extend combinations.
2299169689Skan
2300169689Skan(define_insn ""
2301169689Skan  [(set (match_operand:SI 0 "register_operand" "=d")
2302169689Skan        (zero_extend:SI (truncate:HI
2303169689Skan                         (match_operand:DI 1 "register_operand" "d"))))]
2304169689Skan  "TARGET_64BIT && !TARGET_MIPS16"
2305169689Skan  "andi\t%0,%1,0xffff"
2306169689Skan  [(set_attr "type"     "arith")
2307169689Skan   (set_attr "mode"     "SI")])
2308169689Skan
2309169689Skan(define_insn ""
2310169689Skan  [(set (match_operand:SI 0 "register_operand" "=d")
2311169689Skan        (zero_extend:SI (truncate:QI
2312169689Skan                         (match_operand:DI 1 "register_operand" "d"))))]
2313169689Skan  "TARGET_64BIT && !TARGET_MIPS16"
2314169689Skan  "andi\t%0,%1,0xff"
2315169689Skan  [(set_attr "type"     "arith")
2316169689Skan   (set_attr "mode"     "SI")])
2317169689Skan
2318169689Skan(define_insn ""
2319169689Skan  [(set (match_operand:HI 0 "register_operand" "=d")
2320169689Skan        (zero_extend:HI (truncate:QI
2321169689Skan                         (match_operand:DI 1 "register_operand" "d"))))]
2322169689Skan  "TARGET_64BIT && !TARGET_MIPS16"
2323169689Skan  "andi\t%0,%1,0xff"
2324169689Skan  [(set_attr "type"     "arith")
2325169689Skan   (set_attr "mode"     "HI")])
2326169689Skan
2327169689Skan;;
2328169689Skan;;  ....................
2329169689Skan;;
2330169689Skan;;	ZERO EXTENSION
2331169689Skan;;
2332169689Skan;;  ....................
2333169689Skan
2334169689Skan;; Extension insns.
2335169689Skan
2336169689Skan(define_insn_and_split "zero_extendsidi2"
2337169689Skan  [(set (match_operand:DI 0 "register_operand" "=d,d")
2338169689Skan        (zero_extend:DI (match_operand:SI 1 "nonimmediate_operand" "d,W")))]
2339169689Skan  "TARGET_64BIT"
2340169689Skan  "@
2341169689Skan   #
2342169689Skan   lwu\t%0,%1"
2343169689Skan  "&& reload_completed && REG_P (operands[1])"
2344169689Skan  [(set (match_dup 0)
2345169689Skan        (ashift:DI (match_dup 1) (const_int 32)))
2346169689Skan   (set (match_dup 0)
2347169689Skan        (lshiftrt:DI (match_dup 0) (const_int 32)))]
2348169689Skan  { operands[1] = gen_lowpart (DImode, operands[1]); }
2349169689Skan  [(set_attr "type" "multi,load")
2350169689Skan   (set_attr "mode" "DI")
2351169689Skan   (set_attr "length" "8,*")])
2352169689Skan
2353169689Skan;; Combine is not allowed to convert this insn into a zero_extendsidi2
2354169689Skan;; because of TRULY_NOOP_TRUNCATION.
2355169689Skan
2356169689Skan(define_insn_and_split "*clear_upper32"
2357169689Skan  [(set (match_operand:DI 0 "register_operand" "=d,d")
2358169689Skan        (and:DI (match_operand:DI 1 "nonimmediate_operand" "d,o")
2359169689Skan		(const_int 4294967295)))]
2360169689Skan  "TARGET_64BIT"
2361169689Skan{
2362169689Skan  if (which_alternative == 0)
2363169689Skan    return "#";
2364169689Skan
2365169689Skan  operands[1] = gen_lowpart (SImode, operands[1]);
2366169689Skan  return "lwu\t%0,%1";
2367169689Skan}
2368169689Skan  "&& reload_completed && REG_P (operands[1])"
2369169689Skan  [(set (match_dup 0)
2370169689Skan        (ashift:DI (match_dup 1) (const_int 32)))
2371169689Skan   (set (match_dup 0)
2372169689Skan        (lshiftrt:DI (match_dup 0) (const_int 32)))]
2373169689Skan  ""
2374169689Skan  [(set_attr "type" "multi,load")
2375169689Skan   (set_attr "mode" "DI")
2376169689Skan   (set_attr "length" "8,*")])
2377169689Skan
2378169689Skan(define_expand "zero_extend<SHORT:mode><GPR:mode>2"
2379169689Skan  [(set (match_operand:GPR 0 "register_operand")
2380169689Skan        (zero_extend:GPR (match_operand:SHORT 1 "nonimmediate_operand")))]
2381169689Skan  ""
2382169689Skan{
2383169689Skan  if (TARGET_MIPS16 && !GENERATE_MIPS16E
2384169689Skan      && !memory_operand (operands[1], <SHORT:MODE>mode))
2385169689Skan    {
2386169689Skan      emit_insn (gen_and<GPR:mode>3 (operands[0],
2387169689Skan				     gen_lowpart (<GPR:MODE>mode, operands[1]),
2388169689Skan				     force_reg (<GPR:MODE>mode,
2389169689Skan						GEN_INT (<SHORT:mask>))));
2390169689Skan      DONE;
2391169689Skan    }
2392169689Skan})
2393169689Skan
2394169689Skan(define_insn "*zero_extend<SHORT:mode><GPR:mode>2"
2395169689Skan  [(set (match_operand:GPR 0 "register_operand" "=d,d")
2396169689Skan        (zero_extend:GPR
2397169689Skan	     (match_operand:SHORT 1 "nonimmediate_operand" "d,m")))]
2398169689Skan  "!TARGET_MIPS16"
2399169689Skan  "@
2400169689Skan   andi\t%0,%1,<SHORT:mask>
2401169689Skan   l<SHORT:size>u\t%0,%1"
2402169689Skan  [(set_attr "type" "arith,load")
2403169689Skan   (set_attr "mode" "<GPR:MODE>")])
2404169689Skan
2405169689Skan(define_insn "*zero_extend<SHORT:mode><GPR:mode>2_mips16e"
2406169689Skan  [(set (match_operand:GPR 0 "register_operand" "=d")
2407169689Skan        (zero_extend:GPR (match_operand:SHORT 1 "register_operand" "0")))]
2408169689Skan  "GENERATE_MIPS16E"
2409169689Skan  "ze<SHORT:size>\t%0"
2410169689Skan  [(set_attr "type" "arith")
2411169689Skan   (set_attr "mode" "<GPR:MODE>")])
2412169689Skan
2413169689Skan(define_insn "*zero_extend<SHORT:mode><GPR:mode>2_mips16"
2414169689Skan  [(set (match_operand:GPR 0 "register_operand" "=d")
2415169689Skan        (zero_extend:GPR (match_operand:SHORT 1 "memory_operand" "m")))]
2416169689Skan  "TARGET_MIPS16"
2417169689Skan  "l<SHORT:size>u\t%0,%1"
2418169689Skan  [(set_attr "type" "load")
2419169689Skan   (set_attr "mode" "<GPR:MODE>")])
2420169689Skan
2421169689Skan(define_expand "zero_extendqihi2"
2422169689Skan  [(set (match_operand:HI 0 "register_operand")
2423169689Skan	(zero_extend:HI (match_operand:QI 1 "nonimmediate_operand")))]
2424169689Skan  ""
2425169689Skan{
2426169689Skan  if (TARGET_MIPS16 && !memory_operand (operands[1], QImode))
2427169689Skan    {
2428169689Skan      emit_insn (gen_zero_extendqisi2 (gen_lowpart (SImode, operands[0]),
2429169689Skan				       operands[1]));
2430169689Skan      DONE;
2431169689Skan    }
2432169689Skan})
2433169689Skan
2434169689Skan(define_insn "*zero_extendqihi2"
2435169689Skan  [(set (match_operand:HI 0 "register_operand" "=d,d")
2436169689Skan        (zero_extend:HI (match_operand:QI 1 "nonimmediate_operand" "d,m")))]
2437169689Skan  "!TARGET_MIPS16"
2438169689Skan  "@
2439169689Skan   andi\t%0,%1,0x00ff
2440169689Skan   lbu\t%0,%1"
2441169689Skan  [(set_attr "type" "arith,load")
2442169689Skan   (set_attr "mode" "HI")])
2443169689Skan
2444169689Skan(define_insn "*zero_extendqihi2_mips16"
2445169689Skan  [(set (match_operand:HI 0 "register_operand" "=d")
2446169689Skan        (zero_extend:HI (match_operand:QI 1 "memory_operand" "m")))]
2447169689Skan  "TARGET_MIPS16"
2448169689Skan  "lbu\t%0,%1"
2449169689Skan  [(set_attr "type" "load")
2450169689Skan   (set_attr "mode" "HI")])
2451169689Skan
2452169689Skan;;
2453169689Skan;;  ....................
2454169689Skan;;
2455169689Skan;;	SIGN EXTENSION
2456169689Skan;;
2457169689Skan;;  ....................
2458169689Skan
2459169689Skan;; Extension insns.
2460169689Skan;; Those for integer source operand are ordered widest source type first.
2461169689Skan
2462169689Skan;; When TARGET_64BIT, all SImode integer registers should already be in
2463169689Skan;; sign-extended form (see TRULY_NOOP_TRUNCATION and truncdisi2).  We can
2464169689Skan;; therefore get rid of register->register instructions if we constrain
2465169689Skan;; the source to be in the same register as the destination.
2466169689Skan;;
2467169689Skan;; The register alternative has type "arith" so that the pre-reload
2468169689Skan;; scheduler will treat it as a move.  This reflects what happens if
2469169689Skan;; the register alternative needs a reload.
2470169689Skan(define_insn_and_split "extendsidi2"
2471169689Skan  [(set (match_operand:DI 0 "register_operand" "=d,d")
2472169689Skan        (sign_extend:DI (match_operand:SI 1 "nonimmediate_operand" "0,m")))]
2473169689Skan  "TARGET_64BIT"
2474169689Skan  "@
2475169689Skan   #
2476169689Skan   lw\t%0,%1"
2477169689Skan  "&& reload_completed && register_operand (operands[1], VOIDmode)"
2478169689Skan  [(const_int 0)]
2479169689Skan{
2480169689Skan  emit_note (NOTE_INSN_DELETED);
2481169689Skan  DONE;
2482169689Skan}
2483169689Skan  [(set_attr "type" "arith,load")
2484169689Skan   (set_attr "mode" "DI")])
2485169689Skan
2486169689Skan(define_expand "extend<SHORT:mode><GPR:mode>2"
2487169689Skan  [(set (match_operand:GPR 0 "register_operand")
2488169689Skan        (sign_extend:GPR (match_operand:SHORT 1 "nonimmediate_operand")))]
2489169689Skan  "")
2490169689Skan
2491169689Skan(define_insn "*extend<SHORT:mode><GPR:mode>2_mips16e"
2492169689Skan  [(set (match_operand:GPR 0 "register_operand" "=d,d")
2493169689Skan        (sign_extend:GPR (match_operand:SHORT 1 "nonimmediate_operand" "0,m")))]
2494169689Skan  "GENERATE_MIPS16E"
2495169689Skan  "@
2496169689Skan   se<SHORT:size>\t%0
2497169689Skan   l<SHORT:size>\t%0,%1"
2498169689Skan  [(set_attr "type" "arith,load")
2499169689Skan   (set_attr "mode" "<GPR:MODE>")])
2500169689Skan
2501169689Skan(define_insn_and_split "*extend<SHORT:mode><GPR:mode>2"
2502169689Skan  [(set (match_operand:GPR 0 "register_operand" "=d,d")
2503169689Skan        (sign_extend:GPR
2504169689Skan	     (match_operand:SHORT 1 "nonimmediate_operand" "d,m")))]
2505169689Skan  "!ISA_HAS_SEB_SEH && !GENERATE_MIPS16E"
2506169689Skan  "@
2507169689Skan   #
2508169689Skan   l<SHORT:size>\t%0,%1"
2509169689Skan  "&& reload_completed && REG_P (operands[1])"
2510169689Skan  [(set (match_dup 0) (ashift:GPR (match_dup 1) (match_dup 2)))
2511169689Skan   (set (match_dup 0) (ashiftrt:GPR (match_dup 0) (match_dup 2)))]
2512169689Skan{
2513169689Skan  operands[1] = gen_lowpart (<GPR:MODE>mode, operands[1]);
2514169689Skan  operands[2] = GEN_INT (GET_MODE_BITSIZE (<GPR:MODE>mode)
2515169689Skan			 - GET_MODE_BITSIZE (<SHORT:MODE>mode));
2516169689Skan}
2517169689Skan  [(set_attr "type" "arith,load")
2518169689Skan   (set_attr "mode" "<GPR:MODE>")
2519169689Skan   (set_attr "length" "8,*")])
2520169689Skan
2521169689Skan(define_insn "*extend<SHORT:mode><GPR:mode>2_se<SHORT:size>"
2522169689Skan  [(set (match_operand:GPR 0 "register_operand" "=d,d")
2523169689Skan        (sign_extend:GPR
2524169689Skan	     (match_operand:SHORT 1 "nonimmediate_operand" "d,m")))]
2525169689Skan  "ISA_HAS_SEB_SEH"
2526169689Skan  "@
2527169689Skan   se<SHORT:size>\t%0,%1
2528169689Skan   l<SHORT:size>\t%0,%1"
2529169689Skan  [(set_attr "type" "arith,load")
2530169689Skan   (set_attr "mode" "<GPR:MODE>")])
2531169689Skan
2532169689Skan;; This pattern generates the same code as extendqisi2; split it into
2533169689Skan;; that form after reload.
2534169689Skan(define_insn_and_split "extendqihi2"
2535169689Skan  [(set (match_operand:HI 0 "register_operand" "=d,d")
2536169689Skan        (sign_extend:HI (match_operand:QI 1 "nonimmediate_operand" "d,m")))]
2537169689Skan  ""
2538169689Skan  "#"
2539169689Skan  "reload_completed"
2540169689Skan  [(set (match_dup 0) (sign_extend:SI (match_dup 1)))]
2541169689Skan  { operands[0] = gen_lowpart (SImode, operands[0]); }
2542169689Skan  [(set_attr "type" "arith,load")
2543169689Skan   (set_attr "mode" "SI")
2544169689Skan   (set_attr "length" "8,*")])
2545169689Skan
2546169689Skan(define_insn "extendsfdf2"
2547169689Skan  [(set (match_operand:DF 0 "register_operand" "=f")
2548169689Skan	(float_extend:DF (match_operand:SF 1 "register_operand" "f")))]
2549169689Skan  "TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT"
2550169689Skan  "cvt.d.s\t%0,%1"
2551169689Skan  [(set_attr "type"	"fcvt")
2552169689Skan   (set_attr "cnv_mode"	"S2D")   
2553169689Skan   (set_attr "mode"	"DF")])
2554169689Skan
2555169689Skan;;
2556169689Skan;;  ....................
2557169689Skan;;
2558169689Skan;;	CONVERSIONS
2559169689Skan;;
2560169689Skan;;  ....................
2561169689Skan
2562169689Skan(define_expand "fix_truncdfsi2"
2563169689Skan  [(set (match_operand:SI 0 "register_operand")
2564169689Skan	(fix:SI (match_operand:DF 1 "register_operand")))]
2565169689Skan  "TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT"
2566169689Skan{
2567169689Skan  if (!ISA_HAS_TRUNC_W)
2568169689Skan    {
2569169689Skan      emit_insn (gen_fix_truncdfsi2_macro (operands[0], operands[1]));
2570169689Skan      DONE;
2571169689Skan    }
2572169689Skan})
2573169689Skan
2574169689Skan(define_insn "fix_truncdfsi2_insn"
2575169689Skan  [(set (match_operand:SI 0 "register_operand" "=f")
2576169689Skan	(fix:SI (match_operand:DF 1 "register_operand" "f")))]
2577169689Skan  "TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT && ISA_HAS_TRUNC_W"
2578169689Skan  "trunc.w.d %0,%1"
2579169689Skan  [(set_attr "type"	"fcvt")
2580169689Skan   (set_attr "mode"	"DF")
2581169689Skan   (set_attr "cnv_mode"	"D2I")
2582169689Skan   (set_attr "length"	"4")])
2583169689Skan
2584169689Skan(define_insn "fix_truncdfsi2_macro"
2585169689Skan  [(set (match_operand:SI 0 "register_operand" "=f")
2586169689Skan	(fix:SI (match_operand:DF 1 "register_operand" "f")))
2587169689Skan   (clobber (match_scratch:DF 2 "=d"))]
2588169689Skan  "TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT && !ISA_HAS_TRUNC_W"
2589169689Skan{
2590169689Skan  if (set_nomacro)
2591169689Skan    return ".set\tmacro\;trunc.w.d %0,%1,%2\;.set\tnomacro";
2592169689Skan  else
2593169689Skan    return "trunc.w.d %0,%1,%2";
2594169689Skan}
2595169689Skan  [(set_attr "type"	"fcvt")
2596169689Skan   (set_attr "mode"	"DF")
2597169689Skan   (set_attr "cnv_mode"	"D2I")
2598169689Skan   (set_attr "length"	"36")])
2599169689Skan
2600169689Skan(define_expand "fix_truncsfsi2"
2601169689Skan  [(set (match_operand:SI 0 "register_operand")
2602169689Skan	(fix:SI (match_operand:SF 1 "register_operand")))]
2603169689Skan  "TARGET_HARD_FLOAT"
2604169689Skan{
2605169689Skan  if (!ISA_HAS_TRUNC_W)
2606169689Skan    {
2607169689Skan      emit_insn (gen_fix_truncsfsi2_macro (operands[0], operands[1]));
2608169689Skan      DONE;
2609169689Skan    }
2610169689Skan})
2611169689Skan
2612169689Skan(define_insn "fix_truncsfsi2_insn"
2613169689Skan  [(set (match_operand:SI 0 "register_operand" "=f")
2614169689Skan	(fix:SI (match_operand:SF 1 "register_operand" "f")))]
2615169689Skan  "TARGET_HARD_FLOAT && ISA_HAS_TRUNC_W"
2616169689Skan  "trunc.w.s %0,%1"
2617169689Skan  [(set_attr "type"	"fcvt")
2618169689Skan   (set_attr "mode"	"SF")
2619169689Skan   (set_attr "cnv_mode"	"S2I")
2620169689Skan   (set_attr "length"	"4")])
2621169689Skan
2622169689Skan(define_insn "fix_truncsfsi2_macro"
2623169689Skan  [(set (match_operand:SI 0 "register_operand" "=f")
2624169689Skan	(fix:SI (match_operand:SF 1 "register_operand" "f")))
2625169689Skan   (clobber (match_scratch:SF 2 "=d"))]
2626169689Skan  "TARGET_HARD_FLOAT && !ISA_HAS_TRUNC_W"
2627169689Skan{
2628169689Skan  if (set_nomacro)
2629169689Skan    return ".set\tmacro\;trunc.w.s %0,%1,%2\;.set\tnomacro";
2630169689Skan  else
2631169689Skan    return "trunc.w.s %0,%1,%2";
2632169689Skan}
2633169689Skan  [(set_attr "type"	"fcvt")
2634169689Skan   (set_attr "mode"	"SF")
2635169689Skan   (set_attr "cnv_mode"	"S2I")
2636169689Skan   (set_attr "length"	"36")])
2637169689Skan
2638169689Skan
2639169689Skan(define_insn "fix_truncdfdi2"
2640169689Skan  [(set (match_operand:DI 0 "register_operand" "=f")
2641169689Skan	(fix:DI (match_operand:DF 1 "register_operand" "f")))]
2642169689Skan  "TARGET_HARD_FLOAT && TARGET_FLOAT64 && TARGET_DOUBLE_FLOAT"
2643169689Skan  "trunc.l.d %0,%1"
2644169689Skan  [(set_attr "type"	"fcvt")
2645169689Skan   (set_attr "mode"	"DF")
2646169689Skan   (set_attr "cnv_mode"	"D2I")
2647169689Skan   (set_attr "length"	"4")])
2648169689Skan
2649169689Skan
2650169689Skan(define_insn "fix_truncsfdi2"
2651169689Skan  [(set (match_operand:DI 0 "register_operand" "=f")
2652169689Skan	(fix:DI (match_operand:SF 1 "register_operand" "f")))]
2653169689Skan  "TARGET_HARD_FLOAT && TARGET_FLOAT64 && TARGET_DOUBLE_FLOAT"
2654169689Skan  "trunc.l.s %0,%1"
2655169689Skan  [(set_attr "type"	"fcvt")
2656169689Skan   (set_attr "mode"	"SF")
2657169689Skan   (set_attr "cnv_mode"	"S2I")
2658169689Skan   (set_attr "length"	"4")])
2659169689Skan
2660169689Skan
2661169689Skan(define_insn "floatsidf2"
2662169689Skan  [(set (match_operand:DF 0 "register_operand" "=f")
2663169689Skan	(float:DF (match_operand:SI 1 "register_operand" "f")))]
2664169689Skan  "TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT"
2665169689Skan  "cvt.d.w\t%0,%1"
2666169689Skan  [(set_attr "type"	"fcvt")
2667169689Skan   (set_attr "mode"	"DF")
2668169689Skan   (set_attr "cnv_mode"	"I2D")   
2669169689Skan   (set_attr "length"	"4")])
2670169689Skan
2671169689Skan
2672169689Skan(define_insn "floatdidf2"
2673169689Skan  [(set (match_operand:DF 0 "register_operand" "=f")
2674169689Skan	(float:DF (match_operand:DI 1 "register_operand" "f")))]
2675169689Skan  "TARGET_HARD_FLOAT && TARGET_FLOAT64 && TARGET_DOUBLE_FLOAT"
2676169689Skan  "cvt.d.l\t%0,%1"
2677169689Skan  [(set_attr "type"	"fcvt")
2678169689Skan   (set_attr "mode"	"DF")
2679169689Skan   (set_attr "cnv_mode"	"I2D")   
2680169689Skan   (set_attr "length"	"4")])
2681169689Skan
2682169689Skan
2683169689Skan(define_insn "floatsisf2"
2684169689Skan  [(set (match_operand:SF 0 "register_operand" "=f")
2685169689Skan	(float:SF (match_operand:SI 1 "register_operand" "f")))]
2686169689Skan  "TARGET_HARD_FLOAT"
2687169689Skan  "cvt.s.w\t%0,%1"
2688169689Skan  [(set_attr "type"	"fcvt")
2689169689Skan   (set_attr "mode"	"SF")
2690169689Skan   (set_attr "cnv_mode"	"I2S")   
2691169689Skan   (set_attr "length"	"4")])
2692169689Skan
2693169689Skan
2694169689Skan(define_insn "floatdisf2"
2695169689Skan  [(set (match_operand:SF 0 "register_operand" "=f")
2696169689Skan	(float:SF (match_operand:DI 1 "register_operand" "f")))]
2697169689Skan  "TARGET_HARD_FLOAT && TARGET_FLOAT64 && TARGET_DOUBLE_FLOAT"
2698169689Skan  "cvt.s.l\t%0,%1"
2699169689Skan  [(set_attr "type"	"fcvt")
2700169689Skan   (set_attr "mode"	"SF")
2701169689Skan   (set_attr "cnv_mode"	"I2S")   
2702169689Skan   (set_attr "length"	"4")])
2703169689Skan
2704169689Skan
2705169689Skan(define_expand "fixuns_truncdfsi2"
2706169689Skan  [(set (match_operand:SI 0 "register_operand")
2707169689Skan	(unsigned_fix:SI (match_operand:DF 1 "register_operand")))]
2708169689Skan  "TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT"
2709169689Skan{
2710169689Skan  rtx reg1 = gen_reg_rtx (DFmode);
2711169689Skan  rtx reg2 = gen_reg_rtx (DFmode);
2712169689Skan  rtx reg3 = gen_reg_rtx (SImode);
2713169689Skan  rtx label1 = gen_label_rtx ();
2714169689Skan  rtx label2 = gen_label_rtx ();
2715169689Skan  REAL_VALUE_TYPE offset;
2716169689Skan
2717169689Skan  real_2expN (&offset, 31);
2718169689Skan
2719169689Skan  if (reg1)			/* Turn off complaints about unreached code.  */
2720169689Skan    {
2721169689Skan      emit_move_insn (reg1, CONST_DOUBLE_FROM_REAL_VALUE (offset, DFmode));
2722169689Skan      do_pending_stack_adjust ();
2723169689Skan
2724169689Skan      emit_insn (gen_cmpdf (operands[1], reg1));
2725169689Skan      emit_jump_insn (gen_bge (label1));
2726169689Skan
2727169689Skan      emit_insn (gen_fix_truncdfsi2 (operands[0], operands[1]));
2728169689Skan      emit_jump_insn (gen_rtx_SET (VOIDmode, pc_rtx,
2729169689Skan				   gen_rtx_LABEL_REF (VOIDmode, label2)));
2730169689Skan      emit_barrier ();
2731169689Skan
2732169689Skan      emit_label (label1);
2733169689Skan      emit_move_insn (reg2, gen_rtx_MINUS (DFmode, operands[1], reg1));
2734169689Skan      emit_move_insn (reg3, GEN_INT (trunc_int_for_mode
2735169689Skan				     (BITMASK_HIGH, SImode)));
2736169689Skan
2737169689Skan      emit_insn (gen_fix_truncdfsi2 (operands[0], reg2));
2738169689Skan      emit_insn (gen_iorsi3 (operands[0], operands[0], reg3));
2739169689Skan
2740169689Skan      emit_label (label2);
2741169689Skan
2742169689Skan      /* Allow REG_NOTES to be set on last insn (labels don't have enough
2743169689Skan	 fields, and can't be used for REG_NOTES anyway).  */
2744169689Skan      emit_insn (gen_rtx_USE (VOIDmode, stack_pointer_rtx));
2745169689Skan      DONE;
2746169689Skan    }
2747169689Skan})
2748169689Skan
2749169689Skan
2750169689Skan(define_expand "fixuns_truncdfdi2"
2751169689Skan  [(set (match_operand:DI 0 "register_operand")
2752169689Skan	(unsigned_fix:DI (match_operand:DF 1 "register_operand")))]
2753169689Skan  "TARGET_HARD_FLOAT && TARGET_64BIT && TARGET_DOUBLE_FLOAT"
2754169689Skan{
2755169689Skan  rtx reg1 = gen_reg_rtx (DFmode);
2756169689Skan  rtx reg2 = gen_reg_rtx (DFmode);
2757169689Skan  rtx reg3 = gen_reg_rtx (DImode);
2758169689Skan  rtx label1 = gen_label_rtx ();
2759169689Skan  rtx label2 = gen_label_rtx ();
2760169689Skan  REAL_VALUE_TYPE offset;
2761169689Skan
2762169689Skan  real_2expN (&offset, 63);
2763169689Skan
2764169689Skan  emit_move_insn (reg1, CONST_DOUBLE_FROM_REAL_VALUE (offset, DFmode));
2765169689Skan  do_pending_stack_adjust ();
2766169689Skan
2767169689Skan  emit_insn (gen_cmpdf (operands[1], reg1));
2768169689Skan  emit_jump_insn (gen_bge (label1));
2769169689Skan
2770169689Skan  emit_insn (gen_fix_truncdfdi2 (operands[0], operands[1]));
2771169689Skan  emit_jump_insn (gen_rtx_SET (VOIDmode, pc_rtx,
2772169689Skan			       gen_rtx_LABEL_REF (VOIDmode, label2)));
2773169689Skan  emit_barrier ();
2774169689Skan
2775169689Skan  emit_label (label1);
2776169689Skan  emit_move_insn (reg2, gen_rtx_MINUS (DFmode, operands[1], reg1));
2777169689Skan  emit_move_insn (reg3, GEN_INT (BITMASK_HIGH));
2778169689Skan  emit_insn (gen_ashldi3 (reg3, reg3, GEN_INT (32)));
2779169689Skan
2780169689Skan  emit_insn (gen_fix_truncdfdi2 (operands[0], reg2));
2781169689Skan  emit_insn (gen_iordi3 (operands[0], operands[0], reg3));
2782169689Skan
2783169689Skan  emit_label (label2);
2784169689Skan
2785169689Skan  /* Allow REG_NOTES to be set on last insn (labels don't have enough
2786169689Skan     fields, and can't be used for REG_NOTES anyway).  */
2787169689Skan  emit_insn (gen_rtx_USE (VOIDmode, stack_pointer_rtx));
2788169689Skan  DONE;
2789169689Skan})
2790169689Skan
2791169689Skan
2792169689Skan(define_expand "fixuns_truncsfsi2"
2793169689Skan  [(set (match_operand:SI 0 "register_operand")
2794169689Skan	(unsigned_fix:SI (match_operand:SF 1 "register_operand")))]
2795169689Skan  "TARGET_HARD_FLOAT"
2796169689Skan{
2797169689Skan  rtx reg1 = gen_reg_rtx (SFmode);
2798169689Skan  rtx reg2 = gen_reg_rtx (SFmode);
2799169689Skan  rtx reg3 = gen_reg_rtx (SImode);
2800169689Skan  rtx label1 = gen_label_rtx ();
2801169689Skan  rtx label2 = gen_label_rtx ();
2802169689Skan  REAL_VALUE_TYPE offset;
2803169689Skan
2804169689Skan  real_2expN (&offset, 31);
2805169689Skan
2806169689Skan  emit_move_insn (reg1, CONST_DOUBLE_FROM_REAL_VALUE (offset, SFmode));
2807169689Skan  do_pending_stack_adjust ();
2808169689Skan
2809169689Skan  emit_insn (gen_cmpsf (operands[1], reg1));
2810169689Skan  emit_jump_insn (gen_bge (label1));
2811169689Skan
2812169689Skan  emit_insn (gen_fix_truncsfsi2 (operands[0], operands[1]));
2813169689Skan  emit_jump_insn (gen_rtx_SET (VOIDmode, pc_rtx,
2814169689Skan			       gen_rtx_LABEL_REF (VOIDmode, label2)));
2815169689Skan  emit_barrier ();
2816169689Skan
2817169689Skan  emit_label (label1);
2818169689Skan  emit_move_insn (reg2, gen_rtx_MINUS (SFmode, operands[1], reg1));
2819169689Skan  emit_move_insn (reg3, GEN_INT (trunc_int_for_mode
2820169689Skan				 (BITMASK_HIGH, SImode)));
2821169689Skan
2822169689Skan  emit_insn (gen_fix_truncsfsi2 (operands[0], reg2));
2823169689Skan  emit_insn (gen_iorsi3 (operands[0], operands[0], reg3));
2824169689Skan
2825169689Skan  emit_label (label2);
2826169689Skan
2827169689Skan  /* Allow REG_NOTES to be set on last insn (labels don't have enough
2828169689Skan     fields, and can't be used for REG_NOTES anyway).  */
2829169689Skan  emit_insn (gen_rtx_USE (VOIDmode, stack_pointer_rtx));
2830169689Skan  DONE;
2831169689Skan})
2832169689Skan
2833169689Skan
2834169689Skan(define_expand "fixuns_truncsfdi2"
2835169689Skan  [(set (match_operand:DI 0 "register_operand")
2836169689Skan	(unsigned_fix:DI (match_operand:SF 1 "register_operand")))]
2837169689Skan  "TARGET_HARD_FLOAT && TARGET_64BIT && TARGET_DOUBLE_FLOAT"
2838169689Skan{
2839169689Skan  rtx reg1 = gen_reg_rtx (SFmode);
2840169689Skan  rtx reg2 = gen_reg_rtx (SFmode);
2841169689Skan  rtx reg3 = gen_reg_rtx (DImode);
2842169689Skan  rtx label1 = gen_label_rtx ();
2843169689Skan  rtx label2 = gen_label_rtx ();
2844169689Skan  REAL_VALUE_TYPE offset;
2845169689Skan
2846169689Skan  real_2expN (&offset, 63);
2847169689Skan
2848169689Skan  emit_move_insn (reg1, CONST_DOUBLE_FROM_REAL_VALUE (offset, SFmode));
2849169689Skan  do_pending_stack_adjust ();
2850169689Skan
2851169689Skan  emit_insn (gen_cmpsf (operands[1], reg1));
2852169689Skan  emit_jump_insn (gen_bge (label1));
2853169689Skan
2854169689Skan  emit_insn (gen_fix_truncsfdi2 (operands[0], operands[1]));
2855169689Skan  emit_jump_insn (gen_rtx_SET (VOIDmode, pc_rtx,
2856169689Skan			       gen_rtx_LABEL_REF (VOIDmode, label2)));
2857169689Skan  emit_barrier ();
2858169689Skan
2859169689Skan  emit_label (label1);
2860169689Skan  emit_move_insn (reg2, gen_rtx_MINUS (SFmode, operands[1], reg1));
2861169689Skan  emit_move_insn (reg3, GEN_INT (BITMASK_HIGH));
2862169689Skan  emit_insn (gen_ashldi3 (reg3, reg3, GEN_INT (32)));
2863169689Skan
2864169689Skan  emit_insn (gen_fix_truncsfdi2 (operands[0], reg2));
2865169689Skan  emit_insn (gen_iordi3 (operands[0], operands[0], reg3));
2866169689Skan
2867169689Skan  emit_label (label2);
2868169689Skan
2869169689Skan  /* Allow REG_NOTES to be set on last insn (labels don't have enough
2870169689Skan     fields, and can't be used for REG_NOTES anyway).  */
2871169689Skan  emit_insn (gen_rtx_USE (VOIDmode, stack_pointer_rtx));
2872169689Skan  DONE;
2873169689Skan})
2874169689Skan
2875169689Skan;;
2876169689Skan;;  ....................
2877169689Skan;;
2878169689Skan;;	DATA MOVEMENT
2879169689Skan;;
2880169689Skan;;  ....................
2881169689Skan
2882169689Skan;; Bit field extract patterns which use lwl/lwr or ldl/ldr.
2883169689Skan
2884169689Skan(define_expand "extv"
2885169689Skan  [(set (match_operand 0 "register_operand")
2886169689Skan	(sign_extract (match_operand:QI 1 "memory_operand")
2887169689Skan		      (match_operand 2 "immediate_operand")
2888169689Skan		      (match_operand 3 "immediate_operand")))]
2889169689Skan  "!TARGET_MIPS16"
2890169689Skan{
2891169689Skan  if (mips_expand_unaligned_load (operands[0], operands[1],
2892169689Skan				  INTVAL (operands[2]),
2893169689Skan				  INTVAL (operands[3])))
2894169689Skan    DONE;
2895169689Skan  else
2896169689Skan    FAIL;
2897169689Skan})
2898169689Skan
2899169689Skan(define_expand "extzv"
2900169689Skan  [(set (match_operand 0 "register_operand")
2901169689Skan	(zero_extract (match_operand 1 "nonimmediate_operand")
2902169689Skan		      (match_operand 2 "immediate_operand")
2903169689Skan		      (match_operand 3 "immediate_operand")))]
2904169689Skan  "!TARGET_MIPS16"
2905169689Skan{
2906169689Skan  if (mips_expand_unaligned_load (operands[0], operands[1],
2907169689Skan				  INTVAL (operands[2]),
2908169689Skan				  INTVAL (operands[3])))
2909169689Skan    DONE;
2910169689Skan  else if (mips_use_ins_ext_p (operands[1], operands[2], operands[3]))
2911169689Skan    {
2912169689Skan      if (GET_MODE (operands[0]) == DImode)
2913169689Skan        emit_insn (gen_extzvdi (operands[0], operands[1], operands[2],
2914169689Skan				operands[3]));
2915169689Skan      else
2916169689Skan        emit_insn (gen_extzvsi (operands[0], operands[1], operands[2],
2917169689Skan				operands[3]));
2918169689Skan      DONE;
2919169689Skan    }
2920169689Skan  else
2921169689Skan    FAIL;
2922169689Skan})
2923169689Skan
2924169689Skan(define_insn "extzv<mode>"
2925169689Skan  [(set (match_operand:GPR 0 "register_operand" "=d")
2926169689Skan	(zero_extract:GPR (match_operand:GPR 1 "register_operand" "d")
2927169689Skan			  (match_operand:SI 2 "immediate_operand" "I")
2928169689Skan			  (match_operand:SI 3 "immediate_operand" "I")))]
2929169689Skan  "mips_use_ins_ext_p (operands[1], operands[2], operands[3])"
2930169689Skan  "<d>ext\t%0,%1,%3,%2"
2931169689Skan  [(set_attr "type"	"arith")
2932169689Skan   (set_attr "mode"	"<MODE>")])
2933169689Skan
2934169689Skan
2935169689Skan(define_expand "insv"
2936169689Skan  [(set (zero_extract (match_operand 0 "nonimmediate_operand")
2937169689Skan		      (match_operand 1 "immediate_operand")
2938169689Skan		      (match_operand 2 "immediate_operand"))
2939169689Skan	(match_operand 3 "reg_or_0_operand"))]
2940169689Skan  "!TARGET_MIPS16"
2941169689Skan{
2942169689Skan  if (mips_expand_unaligned_store (operands[0], operands[3],
2943169689Skan				   INTVAL (operands[1]),
2944169689Skan				   INTVAL (operands[2])))
2945169689Skan    DONE;
2946169689Skan  else if (mips_use_ins_ext_p (operands[0], operands[1], operands[2]))
2947169689Skan    {
2948169689Skan      if (GET_MODE (operands[0]) == DImode)
2949169689Skan        emit_insn (gen_insvdi (operands[0], operands[1], operands[2],
2950169689Skan			       operands[3]));
2951169689Skan      else
2952169689Skan        emit_insn (gen_insvsi (operands[0], operands[1], operands[2],
2953169689Skan			       operands[3]));
2954169689Skan      DONE;
2955169689Skan   }
2956169689Skan   else
2957169689Skan     FAIL;
2958169689Skan})
2959169689Skan
2960169689Skan(define_insn "insv<mode>"
2961169689Skan  [(set (zero_extract:GPR (match_operand:GPR 0 "register_operand" "+d")
2962169689Skan			  (match_operand:SI 1 "immediate_operand" "I")
2963169689Skan			  (match_operand:SI 2 "immediate_operand" "I"))
2964169689Skan	(match_operand:GPR 3 "reg_or_0_operand" "dJ"))]
2965169689Skan  "mips_use_ins_ext_p (operands[0], operands[1], operands[2])"
2966169689Skan  "<d>ins\t%0,%z3,%2,%1"
2967169689Skan  [(set_attr "type"	"arith")
2968169689Skan   (set_attr "mode"	"<MODE>")])
2969169689Skan
2970169689Skan;; Unaligned word moves generated by the bit field patterns.
2971169689Skan;;
2972169689Skan;; As far as the rtl is concerned, both the left-part and right-part
2973169689Skan;; instructions can access the whole field.  However, the real operand
2974169689Skan;; refers to just the first or the last byte (depending on endianness).
2975169689Skan;; We therefore use two memory operands to each instruction, one to
2976169689Skan;; describe the rtl effect and one to use in the assembly output.
2977169689Skan;;
2978169689Skan;; Operands 0 and 1 are the rtl-level target and source respectively.
2979169689Skan;; This allows us to use the standard length calculations for the "load"
2980169689Skan;; and "store" type attributes.
2981169689Skan
2982169689Skan(define_insn "mov_<load>l"
2983169689Skan  [(set (match_operand:GPR 0 "register_operand" "=d")
2984169689Skan	(unspec:GPR [(match_operand:BLK 1 "memory_operand" "m")
2985169689Skan		     (match_operand:QI 2 "memory_operand" "m")]
2986169689Skan		    UNSPEC_LOAD_LEFT))]
2987169689Skan  "!TARGET_MIPS16 && mips_mem_fits_mode_p (<MODE>mode, operands[1])"
2988169689Skan  "<load>l\t%0,%2"
2989169689Skan  [(set_attr "type" "load")
2990169689Skan   (set_attr "mode" "<MODE>")])
2991169689Skan
2992169689Skan(define_insn "mov_<load>r"
2993169689Skan  [(set (match_operand:GPR 0 "register_operand" "=d")
2994169689Skan	(unspec:GPR [(match_operand:BLK 1 "memory_operand" "m")
2995169689Skan		     (match_operand:QI 2 "memory_operand" "m")
2996169689Skan		     (match_operand:GPR 3 "register_operand" "0")]
2997169689Skan		    UNSPEC_LOAD_RIGHT))]
2998169689Skan  "!TARGET_MIPS16 && mips_mem_fits_mode_p (<MODE>mode, operands[1])"
2999169689Skan  "<load>r\t%0,%2"
3000169689Skan  [(set_attr "type" "load")
3001169689Skan   (set_attr "mode" "<MODE>")])
3002169689Skan
3003169689Skan(define_insn "mov_<store>l"
3004169689Skan  [(set (match_operand:BLK 0 "memory_operand" "=m")
3005169689Skan	(unspec:BLK [(match_operand:GPR 1 "reg_or_0_operand" "dJ")
3006169689Skan		     (match_operand:QI 2 "memory_operand" "m")]
3007169689Skan		    UNSPEC_STORE_LEFT))]
3008169689Skan  "!TARGET_MIPS16 && mips_mem_fits_mode_p (<MODE>mode, operands[0])"
3009169689Skan  "<store>l\t%z1,%2"
3010169689Skan  [(set_attr "type" "store")
3011169689Skan   (set_attr "mode" "<MODE>")])
3012169689Skan
3013169689Skan(define_insn "mov_<store>r"
3014169689Skan  [(set (match_operand:BLK 0 "memory_operand" "+m")
3015169689Skan	(unspec:BLK [(match_operand:GPR 1 "reg_or_0_operand" "dJ")
3016169689Skan		     (match_operand:QI 2 "memory_operand" "m")
3017169689Skan		     (match_dup 0)]
3018169689Skan		    UNSPEC_STORE_RIGHT))]
3019169689Skan  "!TARGET_MIPS16 && mips_mem_fits_mode_p (<MODE>mode, operands[0])"
3020169689Skan  "<store>r\t%z1,%2"
3021169689Skan  [(set_attr "type" "store")
3022169689Skan   (set_attr "mode" "<MODE>")])
3023169689Skan
3024169689Skan;; An instruction to calculate the high part of a 64-bit SYMBOL_GENERAL.
3025169689Skan;; The required value is:
3026169689Skan;;
3027169689Skan;;	(%highest(op1) << 48) + (%higher(op1) << 32) + (%hi(op1) << 16)
3028169689Skan;;
3029169689Skan;; which translates to:
3030169689Skan;;
3031169689Skan;;	lui	op0,%highest(op1)
3032169689Skan;;	daddiu	op0,op0,%higher(op1)
3033169689Skan;;	dsll	op0,op0,16
3034169689Skan;;	daddiu	op0,op0,%hi(op1)
3035169689Skan;;	dsll	op0,op0,16
3036169689Skan;;
3037169689Skan;; The split is deferred until after flow2 to allow the peephole2 below
3038169689Skan;; to take effect.
3039169689Skan(define_insn_and_split "*lea_high64"
3040169689Skan  [(set (match_operand:DI 0 "register_operand" "=d")
3041169689Skan	(high:DI (match_operand:DI 1 "general_symbolic_operand" "")))]
3042169689Skan  "TARGET_EXPLICIT_RELOCS && ABI_HAS_64BIT_SYMBOLS"
3043169689Skan  "#"
3044169689Skan  "&& flow2_completed"
3045169689Skan  [(set (match_dup 0) (high:DI (match_dup 2)))
3046169689Skan   (set (match_dup 0) (lo_sum:DI (match_dup 0) (match_dup 2)))
3047169689Skan   (set (match_dup 0) (ashift:DI (match_dup 0) (const_int 16)))
3048169689Skan   (set (match_dup 0) (lo_sum:DI (match_dup 0) (match_dup 3)))
3049169689Skan   (set (match_dup 0) (ashift:DI (match_dup 0) (const_int 16)))]
3050169689Skan{
3051169689Skan  operands[2] = mips_unspec_address (operands[1], SYMBOL_64_HIGH);
3052169689Skan  operands[3] = mips_unspec_address (operands[1], SYMBOL_64_MID);
3053169689Skan}
3054169689Skan  [(set_attr "length" "20")])
3055169689Skan
3056169689Skan;; Use a scratch register to reduce the latency of the above pattern
3057169689Skan;; on superscalar machines.  The optimized sequence is:
3058169689Skan;;
3059169689Skan;;	lui	op1,%highest(op2)
3060169689Skan;;	lui	op0,%hi(op2)
3061169689Skan;;	daddiu	op1,op1,%higher(op2)
3062169689Skan;;	dsll32	op1,op1,0
3063169689Skan;;	daddu	op1,op1,op0
3064169689Skan(define_peephole2
3065169689Skan  [(set (match_operand:DI 1 "register_operand")
3066169689Skan	(high:DI (match_operand:DI 2 "general_symbolic_operand")))
3067169689Skan   (match_scratch:DI 0 "d")]
3068169689Skan  "TARGET_EXPLICIT_RELOCS && ABI_HAS_64BIT_SYMBOLS"
3069169689Skan  [(set (match_dup 1) (high:DI (match_dup 3)))
3070169689Skan   (set (match_dup 0) (high:DI (match_dup 4)))
3071169689Skan   (set (match_dup 1) (lo_sum:DI (match_dup 1) (match_dup 3)))
3072169689Skan   (set (match_dup 1) (ashift:DI (match_dup 1) (const_int 32)))
3073169689Skan   (set (match_dup 1) (plus:DI (match_dup 1) (match_dup 0)))]
3074169689Skan{
3075169689Skan  operands[3] = mips_unspec_address (operands[2], SYMBOL_64_HIGH);
3076169689Skan  operands[4] = mips_unspec_address (operands[2], SYMBOL_64_LOW);
3077169689Skan})
3078169689Skan
3079169689Skan;; On most targets, the expansion of (lo_sum (high X) X) for a 64-bit
3080169689Skan;; SYMBOL_GENERAL X will take 6 cycles.  This next pattern allows combine
3081169689Skan;; to merge the HIGH and LO_SUM parts of a move if the HIGH part is only
3082169689Skan;; used once.  We can then use the sequence:
3083169689Skan;;
3084169689Skan;;	lui	op0,%highest(op1)
3085169689Skan;;	lui	op2,%hi(op1)
3086169689Skan;;	daddiu	op0,op0,%higher(op1)
3087169689Skan;;	daddiu	op2,op2,%lo(op1)
3088169689Skan;;	dsll32	op0,op0,0
3089169689Skan;;	daddu	op0,op0,op2
3090169689Skan;;
3091169689Skan;; which takes 4 cycles on most superscalar targets.
3092169689Skan(define_insn_and_split "*lea64"
3093169689Skan  [(set (match_operand:DI 0 "register_operand" "=d")
3094169689Skan	(match_operand:DI 1 "general_symbolic_operand" ""))
3095169689Skan   (clobber (match_scratch:DI 2 "=&d"))]
3096169689Skan  "TARGET_EXPLICIT_RELOCS && ABI_HAS_64BIT_SYMBOLS && cse_not_expected"
3097169689Skan  "#"
3098169689Skan  "&& reload_completed"
3099169689Skan  [(set (match_dup 0) (high:DI (match_dup 3)))
3100169689Skan   (set (match_dup 2) (high:DI (match_dup 4)))
3101169689Skan   (set (match_dup 0) (lo_sum:DI (match_dup 0) (match_dup 3)))
3102169689Skan   (set (match_dup 2) (lo_sum:DI (match_dup 2) (match_dup 4)))
3103169689Skan   (set (match_dup 0) (ashift:DI (match_dup 0) (const_int 32)))
3104169689Skan   (set (match_dup 0) (plus:DI (match_dup 0) (match_dup 2)))]
3105169689Skan{
3106169689Skan  operands[3] = mips_unspec_address (operands[1], SYMBOL_64_HIGH);
3107169689Skan  operands[4] = mips_unspec_address (operands[1], SYMBOL_64_LOW);
3108169689Skan}
3109169689Skan  [(set_attr "length" "24")])
3110169689Skan
3111169689Skan;; Insns to fetch a global symbol from a big GOT.
3112169689Skan
3113169689Skan(define_insn_and_split "*xgot_hi<mode>"
3114169689Skan  [(set (match_operand:P 0 "register_operand" "=d")
3115169689Skan	(high:P (match_operand:P 1 "global_got_operand" "")))]
3116169689Skan  "TARGET_EXPLICIT_RELOCS && TARGET_XGOT"
3117169689Skan  "#"
3118169689Skan  "&& reload_completed"
3119169689Skan  [(set (match_dup 0) (high:P (match_dup 2)))
3120169689Skan   (set (match_dup 0) (plus:P (match_dup 0) (match_dup 3)))]
3121169689Skan{
3122169689Skan  operands[2] = mips_unspec_address (operands[1], SYMBOL_GOTOFF_GLOBAL);
3123169689Skan  operands[3] = pic_offset_table_rtx;
3124169689Skan}
3125169689Skan  [(set_attr "got" "xgot_high")
3126169689Skan   (set_attr "mode" "<MODE>")])
3127169689Skan
3128169689Skan(define_insn_and_split "*xgot_lo<mode>"
3129169689Skan  [(set (match_operand:P 0 "register_operand" "=d")
3130169689Skan	(lo_sum:P (match_operand:P 1 "register_operand" "d")
3131169689Skan		  (match_operand:P 2 "global_got_operand" "")))]
3132169689Skan  "TARGET_EXPLICIT_RELOCS && TARGET_XGOT"
3133169689Skan  "#"
3134169689Skan  "&& reload_completed"
3135169689Skan  [(set (match_dup 0)
3136169689Skan	(unspec:P [(match_dup 1) (match_dup 3)] UNSPEC_LOAD_GOT))]
3137169689Skan  { operands[3] = mips_unspec_address (operands[2], SYMBOL_GOTOFF_GLOBAL); }
3138169689Skan  [(set_attr "got" "load")
3139169689Skan   (set_attr "mode" "<MODE>")])
3140169689Skan
3141169689Skan;; Insns to fetch a global symbol from a normal GOT.
3142169689Skan
3143169689Skan(define_insn_and_split "*got_disp<mode>"
3144169689Skan  [(set (match_operand:P 0 "register_operand" "=d")
3145169689Skan	(match_operand:P 1 "global_got_operand" ""))]
3146169689Skan  "TARGET_EXPLICIT_RELOCS && !TARGET_XGOT"
3147169689Skan  "#"
3148169689Skan  "&& reload_completed"
3149169689Skan  [(set (match_dup 0)
3150169689Skan	(unspec:P [(match_dup 2) (match_dup 3)] UNSPEC_LOAD_GOT))]
3151169689Skan{
3152169689Skan  operands[2] = pic_offset_table_rtx;
3153169689Skan  operands[3] = mips_unspec_address (operands[1], SYMBOL_GOTOFF_GLOBAL);
3154169689Skan}
3155169689Skan  [(set_attr "got" "load")
3156169689Skan   (set_attr "mode" "<MODE>")])
3157169689Skan
3158169689Skan;; Insns for loading the high part of a local symbol.
3159169689Skan
3160169689Skan(define_insn_and_split "*got_page<mode>"
3161169689Skan  [(set (match_operand:P 0 "register_operand" "=d")
3162169689Skan	(high:P (match_operand:P 1 "local_got_operand" "")))]
3163169689Skan  "TARGET_EXPLICIT_RELOCS"
3164169689Skan  "#"
3165169689Skan  "&& reload_completed"
3166169689Skan  [(set (match_dup 0)
3167169689Skan	(unspec:P [(match_dup 2) (match_dup 3)] UNSPEC_LOAD_GOT))]
3168169689Skan{
3169169689Skan  operands[2] = pic_offset_table_rtx;
3170169689Skan  operands[3] = mips_unspec_address (operands[1], SYMBOL_GOTOFF_PAGE);
3171169689Skan}
3172169689Skan  [(set_attr "got" "load")
3173169689Skan   (set_attr "mode" "<MODE>")])
3174169689Skan
3175169689Skan;; Lower-level instructions for loading an address from the GOT.
3176169689Skan;; We could use MEMs, but an unspec gives more optimization
3177169689Skan;; opportunities.
3178169689Skan
3179169689Skan(define_insn "load_got<mode>"
3180169689Skan  [(set (match_operand:P 0 "register_operand" "=d")
3181169689Skan	(unspec:P [(match_operand:P 1 "register_operand" "d")
3182169689Skan		   (match_operand:P 2 "immediate_operand" "")]
3183169689Skan		  UNSPEC_LOAD_GOT))]
3184169689Skan  ""
3185169689Skan  "<load>\t%0,%R2(%1)"
3186169689Skan  [(set_attr "type" "load")
3187169689Skan   (set_attr "mode" "<MODE>")
3188169689Skan   (set_attr "length" "4")])
3189169689Skan
3190169689Skan;; Instructions for adding the low 16 bits of an address to a register.
3191169689Skan;; Operand 2 is the address: print_operand works out which relocation
3192169689Skan;; should be applied.
3193169689Skan
3194169689Skan(define_insn "*low<mode>"
3195169689Skan  [(set (match_operand:P 0 "register_operand" "=d")
3196169689Skan	(lo_sum:P (match_operand:P 1 "register_operand" "d")
3197169689Skan		  (match_operand:P 2 "immediate_operand" "")))]
3198169689Skan  "!TARGET_MIPS16"
3199169689Skan  "<d>addiu\t%0,%1,%R2"
3200169689Skan  [(set_attr "type" "arith")
3201169689Skan   (set_attr "mode" "<MODE>")])
3202169689Skan
3203169689Skan(define_insn "*low<mode>_mips16"
3204169689Skan  [(set (match_operand:P 0 "register_operand" "=d")
3205169689Skan	(lo_sum:P (match_operand:P 1 "register_operand" "0")
3206169689Skan		  (match_operand:P 2 "immediate_operand" "")))]
3207169689Skan  "TARGET_MIPS16"
3208169689Skan  "<d>addiu\t%0,%R2"
3209169689Skan  [(set_attr "type" "arith")
3210169689Skan   (set_attr "mode" "<MODE>")
3211169689Skan   (set_attr "length" "8")])
3212169689Skan
3213169689Skan;; Allow combine to split complex const_int load sequences, using operand 2
3214169689Skan;; to store the intermediate results.  See move_operand for details.
3215169689Skan(define_split
3216169689Skan  [(set (match_operand:GPR 0 "register_operand")
3217169689Skan	(match_operand:GPR 1 "splittable_const_int_operand"))
3218169689Skan   (clobber (match_operand:GPR 2 "register_operand"))]
3219169689Skan  ""
3220169689Skan  [(const_int 0)]
3221169689Skan{
3222169689Skan  mips_move_integer (operands[0], operands[2], INTVAL (operands[1]));
3223169689Skan  DONE;
3224169689Skan})
3225169689Skan
3226169689Skan;; Likewise, for symbolic operands.
3227169689Skan(define_split
3228169689Skan  [(set (match_operand:P 0 "register_operand")
3229169689Skan	(match_operand:P 1 "splittable_symbolic_operand"))
3230169689Skan   (clobber (match_operand:P 2 "register_operand"))]
3231169689Skan  ""
3232169689Skan  [(set (match_dup 0) (match_dup 1))]
3233169689Skan  { operands[1] = mips_split_symbol (operands[2], operands[1]); })
3234169689Skan
3235169689Skan;; 64-bit integer moves
3236169689Skan
3237169689Skan;; Unlike most other insns, the move insns can't be split with
3238169689Skan;; different predicates, because register spilling and other parts of
3239169689Skan;; the compiler, have memoized the insn number already.
3240169689Skan
3241169689Skan(define_expand "movdi"
3242169689Skan  [(set (match_operand:DI 0 "")
3243169689Skan	(match_operand:DI 1 ""))]
3244169689Skan  ""
3245169689Skan{
3246169689Skan  if (mips_legitimize_move (DImode, operands[0], operands[1]))
3247169689Skan    DONE;
3248169689Skan})
3249169689Skan
3250169689Skan;; For mips16, we need a special case to handle storing $31 into
3251169689Skan;; memory, since we don't have a constraint to match $31.  This
3252169689Skan;; instruction can be generated by save_restore_insns.
3253169689Skan
3254169689Skan(define_insn "*mov<mode>_ra"
3255169689Skan  [(set (match_operand:GPR 0 "stack_operand" "=m")
3256169689Skan	(reg:GPR 31))]
3257169689Skan  "TARGET_MIPS16"
3258169689Skan  "<store>\t$31,%0"
3259169689Skan  [(set_attr "type" "store")
3260169689Skan   (set_attr "mode" "<MODE>")])
3261169689Skan
3262169689Skan(define_insn "*movdi_32bit"
3263169689Skan  [(set (match_operand:DI 0 "nonimmediate_operand" "=d,d,d,m,*a,*d,*B*C*D,*B*C*D,*d,*m")
3264169689Skan	(match_operand:DI 1 "move_operand" "d,i,m,d,*J*d,*a,*d,*m,*B*C*D,*B*C*D"))]
3265169689Skan  "!TARGET_64BIT && !TARGET_MIPS16
3266169689Skan   && (register_operand (operands[0], DImode)
3267169689Skan       || reg_or_0_operand (operands[1], DImode))"
3268169689Skan  { return mips_output_move (operands[0], operands[1]); }
3269169689Skan  [(set_attr "type"	"arith,arith,load,store,mthilo,mfhilo,xfer,load,xfer,store")
3270169689Skan   (set_attr "mode"	"DI")
3271169689Skan   (set_attr "length"   "8,16,*,*,8,8,8,*,8,*")])
3272169689Skan
3273169689Skan(define_insn "*movdi_32bit_mips16"
3274169689Skan  [(set (match_operand:DI 0 "nonimmediate_operand" "=d,y,d,d,d,d,m,*d")
3275169689Skan	(match_operand:DI 1 "move_operand" "d,d,y,K,N,m,d,*x"))]
3276169689Skan  "!TARGET_64BIT && TARGET_MIPS16
3277169689Skan   && (register_operand (operands[0], DImode)
3278169689Skan       || register_operand (operands[1], DImode))"
3279169689Skan  { return mips_output_move (operands[0], operands[1]); }
3280169689Skan  [(set_attr "type"	"arith,arith,arith,arith,arith,load,store,mfhilo")
3281169689Skan   (set_attr "mode"	"DI")
3282169689Skan   (set_attr "length"	"8,8,8,8,12,*,*,8")])
3283169689Skan
3284169689Skan(define_insn "*movdi_64bit"
3285169689Skan  [(set (match_operand:DI 0 "nonimmediate_operand" "=d,d,e,d,m,*f,*f,*f,*d,*m,*x,*B*C*D,*B*C*D,*d,*m")
3286169689Skan	(match_operand:DI 1 "move_operand" "d,U,T,m,dJ,*f,*d*J,*m,*f,*f,*J*d,*d,*m,*B*C*D,*B*C*D"))]
3287169689Skan  "TARGET_64BIT && !TARGET_MIPS16
3288169689Skan   && (register_operand (operands[0], DImode)
3289169689Skan       || reg_or_0_operand (operands[1], DImode))"
3290169689Skan  { return mips_output_move (operands[0], operands[1]); }
3291169689Skan  [(set_attr "type"	"arith,const,const,load,store,fmove,xfer,fpload,xfer,fpstore,mthilo,xfer,load,xfer,store")
3292169689Skan   (set_attr "mode"	"DI")
3293169689Skan   (set_attr "length"	"4,*,*,*,*,4,4,*,4,*,4,8,*,8,*")])
3294169689Skan
3295169689Skan(define_insn "*movdi_64bit_mips16"
3296169689Skan  [(set (match_operand:DI 0 "nonimmediate_operand" "=d,y,d,d,d,d,d,m")
3297169689Skan	(match_operand:DI 1 "move_operand" "d,d,y,K,N,U,m,d"))]
3298169689Skan  "TARGET_64BIT && TARGET_MIPS16
3299169689Skan   && (register_operand (operands[0], DImode)
3300169689Skan       || register_operand (operands[1], DImode))"
3301169689Skan  { return mips_output_move (operands[0], operands[1]); }
3302169689Skan  [(set_attr "type"	"arith,arith,arith,arith,arith,const,load,store")
3303169689Skan   (set_attr "mode"	"DI")
3304169689Skan   (set_attr_alternative "length"
3305169689Skan		[(const_int 4)
3306169689Skan		 (const_int 4)
3307169689Skan		 (const_int 4)
3308169689Skan		 (if_then_else (match_operand:VOID 1 "m16_uimm8_1")
3309169689Skan			       (const_int 4)
3310169689Skan			       (const_int 8))
3311169689Skan		 (if_then_else (match_operand:VOID 1 "m16_nuimm8_1")
3312169689Skan			       (const_int 8)
3313169689Skan			       (const_int 12))
3314169689Skan		 (const_string "*")
3315169689Skan		 (const_string "*")
3316169689Skan		 (const_string "*")])])
3317169689Skan
3318169689Skan
3319169689Skan;; On the mips16, we can split ld $r,N($r) into an add and a load,
3320169689Skan;; when the original load is a 4 byte instruction but the add and the
3321169689Skan;; load are 2 2 byte instructions.
3322169689Skan
3323169689Skan(define_split
3324169689Skan  [(set (match_operand:DI 0 "register_operand")
3325169689Skan	(mem:DI (plus:DI (match_dup 0)
3326169689Skan			 (match_operand:DI 1 "const_int_operand"))))]
3327169689Skan  "TARGET_64BIT && TARGET_MIPS16 && reload_completed
3328169689Skan   && !TARGET_DEBUG_D_MODE
3329169689Skan   && REG_P (operands[0])
3330169689Skan   && M16_REG_P (REGNO (operands[0]))
3331169689Skan   && GET_CODE (operands[1]) == CONST_INT
3332169689Skan   && ((INTVAL (operands[1]) < 0
3333169689Skan	&& INTVAL (operands[1]) >= -0x10)
3334169689Skan       || (INTVAL (operands[1]) >= 32 * 8
3335169689Skan	   && INTVAL (operands[1]) <= 31 * 8 + 0x8)
3336169689Skan       || (INTVAL (operands[1]) >= 0
3337169689Skan	   && INTVAL (operands[1]) < 32 * 8
3338169689Skan	   && (INTVAL (operands[1]) & 7) != 0))"
3339169689Skan  [(set (match_dup 0) (plus:DI (match_dup 0) (match_dup 1)))
3340169689Skan   (set (match_dup 0) (mem:DI (plus:DI (match_dup 0) (match_dup 2))))]
3341169689Skan{
3342169689Skan  HOST_WIDE_INT val = INTVAL (operands[1]);
3343169689Skan
3344169689Skan  if (val < 0)
3345169689Skan    operands[2] = const0_rtx;
3346169689Skan  else if (val >= 32 * 8)
3347169689Skan    {
3348169689Skan      int off = val & 7;
3349169689Skan
3350169689Skan      operands[1] = GEN_INT (0x8 + off);
3351169689Skan      operands[2] = GEN_INT (val - off - 0x8);
3352169689Skan    }
3353169689Skan  else
3354169689Skan    {
3355169689Skan      int off = val & 7;
3356169689Skan
3357169689Skan      operands[1] = GEN_INT (off);
3358169689Skan      operands[2] = GEN_INT (val - off);
3359169689Skan    }
3360169689Skan})
3361169689Skan
3362169689Skan;; 32-bit Integer moves
3363169689Skan
3364169689Skan;; Unlike most other insns, the move insns can't be split with
3365169689Skan;; different predicates, because register spilling and other parts of
3366169689Skan;; the compiler, have memoized the insn number already.
3367169689Skan
3368169689Skan(define_expand "movsi"
3369169689Skan  [(set (match_operand:SI 0 "")
3370169689Skan	(match_operand:SI 1 ""))]
3371169689Skan  ""
3372169689Skan{
3373169689Skan  if (mips_legitimize_move (SImode, operands[0], operands[1]))
3374169689Skan    DONE;
3375169689Skan})
3376169689Skan
3377169689Skan;; The difference between these two is whether or not ints are allowed
3378169689Skan;; in FP registers (off by default, use -mdebugh to enable).
3379169689Skan
3380169689Skan(define_insn "*movsi_internal"
3381169689Skan  [(set (match_operand:SI 0 "nonimmediate_operand" "=d,d,e,d,m,*f,*f,*f,*d,*m,*d,*z,*a,*d,*B*C*D,*B*C*D,*d,*m")
3382169689Skan	(match_operand:SI 1 "move_operand" "d,U,T,m,dJ,*f,*d*J,*m,*f,*f,*z,*d,*J*d,*A,*d,*m,*B*C*D,*B*C*D"))]
3383169689Skan  "!TARGET_MIPS16
3384169689Skan   && (register_operand (operands[0], SImode)
3385169689Skan       || reg_or_0_operand (operands[1], SImode))"
3386169689Skan  { return mips_output_move (operands[0], operands[1]); }
3387169689Skan  [(set_attr "type"	"arith,const,const,load,store,fmove,xfer,fpload,xfer,fpstore,xfer,xfer,mthilo,mfhilo,xfer,load,xfer,store")
3388169689Skan   (set_attr "mode"	"SI")
3389169689Skan   (set_attr "length"	"4,*,*,*,*,4,4,*,4,*,4,4,4,4,4,*,4,*")])
3390169689Skan
3391169689Skan(define_insn "*movsi_mips16"
3392169689Skan  [(set (match_operand:SI 0 "nonimmediate_operand" "=d,y,d,d,d,d,d,m")
3393169689Skan	(match_operand:SI 1 "move_operand" "d,d,y,K,N,U,m,d"))]
3394169689Skan  "TARGET_MIPS16
3395169689Skan   && (register_operand (operands[0], SImode)
3396169689Skan       || register_operand (operands[1], SImode))"
3397169689Skan  { return mips_output_move (operands[0], operands[1]); }
3398169689Skan  [(set_attr "type"	"arith,arith,arith,arith,arith,const,load,store")
3399169689Skan   (set_attr "mode"	"SI")
3400169689Skan   (set_attr_alternative "length"
3401169689Skan		[(const_int 4)
3402169689Skan		 (const_int 4)
3403169689Skan		 (const_int 4)
3404169689Skan		 (if_then_else (match_operand:VOID 1 "m16_uimm8_1")
3405169689Skan			       (const_int 4)
3406169689Skan			       (const_int 8))
3407169689Skan		 (if_then_else (match_operand:VOID 1 "m16_nuimm8_1")
3408169689Skan			       (const_int 8)
3409169689Skan			       (const_int 12))
3410169689Skan		 (const_string "*")
3411169689Skan		 (const_string "*")
3412169689Skan		 (const_string "*")])])
3413169689Skan
3414169689Skan;; On the mips16, we can split lw $r,N($r) into an add and a load,
3415169689Skan;; when the original load is a 4 byte instruction but the add and the
3416169689Skan;; load are 2 2 byte instructions.
3417169689Skan
3418169689Skan(define_split
3419169689Skan  [(set (match_operand:SI 0 "register_operand")
3420169689Skan	(mem:SI (plus:SI (match_dup 0)
3421169689Skan			 (match_operand:SI 1 "const_int_operand"))))]
3422169689Skan  "TARGET_MIPS16 && reload_completed && !TARGET_DEBUG_D_MODE
3423169689Skan   && REG_P (operands[0])
3424169689Skan   && M16_REG_P (REGNO (operands[0]))
3425169689Skan   && GET_CODE (operands[1]) == CONST_INT
3426169689Skan   && ((INTVAL (operands[1]) < 0
3427169689Skan	&& INTVAL (operands[1]) >= -0x80)
3428169689Skan       || (INTVAL (operands[1]) >= 32 * 4
3429169689Skan	   && INTVAL (operands[1]) <= 31 * 4 + 0x7c)
3430169689Skan       || (INTVAL (operands[1]) >= 0
3431169689Skan	   && INTVAL (operands[1]) < 32 * 4
3432169689Skan	   && (INTVAL (operands[1]) & 3) != 0))"
3433169689Skan  [(set (match_dup 0) (plus:SI (match_dup 0) (match_dup 1)))
3434169689Skan   (set (match_dup 0) (mem:SI (plus:SI (match_dup 0) (match_dup 2))))]
3435169689Skan{
3436169689Skan  HOST_WIDE_INT val = INTVAL (operands[1]);
3437169689Skan
3438169689Skan  if (val < 0)
3439169689Skan    operands[2] = const0_rtx;
3440169689Skan  else if (val >= 32 * 4)
3441169689Skan    {
3442169689Skan      int off = val & 3;
3443169689Skan
3444169689Skan      operands[1] = GEN_INT (0x7c + off);
3445169689Skan      operands[2] = GEN_INT (val - off - 0x7c);
3446169689Skan    }
3447169689Skan  else
3448169689Skan    {
3449169689Skan      int off = val & 3;
3450169689Skan
3451169689Skan      operands[1] = GEN_INT (off);
3452169689Skan      operands[2] = GEN_INT (val - off);
3453169689Skan    }
3454169689Skan})
3455169689Skan
3456169689Skan;; On the mips16, we can split a load of certain constants into a load
3457169689Skan;; and an add.  This turns a 4 byte instruction into 2 2 byte
3458169689Skan;; instructions.
3459169689Skan
3460169689Skan(define_split
3461169689Skan  [(set (match_operand:SI 0 "register_operand")
3462169689Skan	(match_operand:SI 1 "const_int_operand"))]
3463169689Skan  "TARGET_MIPS16 && reload_completed && !TARGET_DEBUG_D_MODE
3464169689Skan   && REG_P (operands[0])
3465169689Skan   && M16_REG_P (REGNO (operands[0]))
3466169689Skan   && GET_CODE (operands[1]) == CONST_INT
3467169689Skan   && INTVAL (operands[1]) >= 0x100
3468169689Skan   && INTVAL (operands[1]) <= 0xff + 0x7f"
3469169689Skan  [(set (match_dup 0) (match_dup 1))
3470169689Skan   (set (match_dup 0) (plus:SI (match_dup 0) (match_dup 2)))]
3471169689Skan{
3472169689Skan  int val = INTVAL (operands[1]);
3473169689Skan
3474169689Skan  operands[1] = GEN_INT (0xff);
3475169689Skan  operands[2] = GEN_INT (val - 0xff);
3476169689Skan})
3477169689Skan
3478169689Skan;; This insn handles moving CCmode values.  It's really just a
3479169689Skan;; slightly simplified copy of movsi_internal2, with additional cases
3480169689Skan;; to move a condition register to a general register and to move
3481169689Skan;; between the general registers and the floating point registers.
3482169689Skan
3483169689Skan(define_insn "movcc"
3484169689Skan  [(set (match_operand:CC 0 "nonimmediate_operand" "=d,*d,*d,*m,*d,*f,*f,*f,*m")
3485169689Skan	(match_operand:CC 1 "general_operand" "z,*d,*m,*d,*f,*d,*f,*m,*f"))]
3486169689Skan  "ISA_HAS_8CC && TARGET_HARD_FLOAT"
3487169689Skan  { return mips_output_move (operands[0], operands[1]); }
3488169689Skan  [(set_attr "type"	"xfer,arith,load,store,xfer,xfer,fmove,fpload,fpstore")
3489169689Skan   (set_attr "mode"	"SI")
3490169689Skan   (set_attr "length"	"8,4,*,*,4,4,4,*,*")])
3491169689Skan
3492169689Skan;; Reload condition code registers.  reload_incc and reload_outcc
3493169689Skan;; both handle moves from arbitrary operands into condition code
3494169689Skan;; registers.  reload_incc handles the more common case in which
3495169689Skan;; a source operand is constrained to be in a condition-code
3496169689Skan;; register, but has not been allocated to one.
3497169689Skan;;
3498169689Skan;; Sometimes, such as in movcc, we have a CCmode destination whose
3499169689Skan;; constraints do not include 'z'.  reload_outcc handles the case
3500169689Skan;; when such an operand is allocated to a condition-code register.
3501169689Skan;;
3502169689Skan;; Note that reloads from a condition code register to some
3503169689Skan;; other location can be done using ordinary moves.  Moving
3504169689Skan;; into a GPR takes a single movcc, moving elsewhere takes
3505169689Skan;; two.  We can leave these cases to the generic reload code.
3506169689Skan(define_expand "reload_incc"
3507169689Skan  [(set (match_operand:CC 0 "fcc_reload_operand" "=z")
3508169689Skan	(match_operand:CC 1 "general_operand" ""))
3509169689Skan   (clobber (match_operand:TF 2 "register_operand" "=&f"))]
3510169689Skan  "ISA_HAS_8CC && TARGET_HARD_FLOAT"
3511169689Skan{
3512169689Skan  mips_emit_fcc_reload (operands[0], operands[1], operands[2]);
3513169689Skan  DONE;
3514169689Skan})
3515169689Skan
3516169689Skan(define_expand "reload_outcc"
3517169689Skan  [(set (match_operand:CC 0 "fcc_reload_operand" "=z")
3518169689Skan	(match_operand:CC 1 "register_operand" ""))
3519169689Skan   (clobber (match_operand:TF 2 "register_operand" "=&f"))]
3520169689Skan  "ISA_HAS_8CC && TARGET_HARD_FLOAT"
3521169689Skan{
3522169689Skan  mips_emit_fcc_reload (operands[0], operands[1], operands[2]);
3523169689Skan  DONE;
3524169689Skan})
3525169689Skan
3526169689Skan;; MIPS4 supports loading and storing a floating point register from
3527169689Skan;; the sum of two general registers.  We use two versions for each of
3528169689Skan;; these four instructions: one where the two general registers are
3529169689Skan;; SImode, and one where they are DImode.  This is because general
3530169689Skan;; registers will be in SImode when they hold 32 bit values, but,
3531169689Skan;; since the 32 bit values are always sign extended, the [ls][wd]xc1
3532169689Skan;; instructions will still work correctly.
3533169689Skan
3534169689Skan;; ??? Perhaps it would be better to support these instructions by
3535169689Skan;; modifying GO_IF_LEGITIMATE_ADDRESS and friends.  However, since
3536169689Skan;; these instructions can only be used to load and store floating
3537169689Skan;; point registers, that would probably cause trouble in reload.
3538169689Skan
3539169689Skan(define_insn "*<ANYF:loadx>_<P:mode>"
3540169689Skan  [(set (match_operand:ANYF 0 "register_operand" "=f")
3541169689Skan	(mem:ANYF (plus:P (match_operand:P 1 "register_operand" "d")
3542169689Skan			  (match_operand:P 2 "register_operand" "d"))))]
3543169689Skan  "ISA_HAS_FP4"
3544169689Skan  "<ANYF:loadx>\t%0,%1(%2)"
3545169689Skan  [(set_attr "type" "fpidxload")
3546169689Skan   (set_attr "mode" "<ANYF:UNITMODE>")])
3547169689Skan
3548169689Skan(define_insn "*<ANYF:storex>_<P:mode>"
3549169689Skan  [(set (mem:ANYF (plus:P (match_operand:P 1 "register_operand" "d")
3550169689Skan			  (match_operand:P 2 "register_operand" "d")))
3551169689Skan	(match_operand:ANYF 0 "register_operand" "f"))]
3552169689Skan  "ISA_HAS_FP4"
3553169689Skan  "<ANYF:storex>\t%0,%1(%2)"
3554169689Skan  [(set_attr "type" "fpidxstore")
3555169689Skan   (set_attr "mode" "<ANYF:UNITMODE>")])
3556169689Skan
3557169689Skan;; 16-bit Integer moves
3558169689Skan
3559169689Skan;; Unlike most other insns, the move insns can't be split with
3560169689Skan;; different predicates, because register spilling and other parts of
3561169689Skan;; the compiler, have memoized the insn number already.
3562169689Skan;; Unsigned loads are used because LOAD_EXTEND_OP returns ZERO_EXTEND.
3563169689Skan
3564169689Skan(define_expand "movhi"
3565169689Skan  [(set (match_operand:HI 0 "")
3566169689Skan	(match_operand:HI 1 ""))]
3567169689Skan  ""
3568169689Skan{
3569169689Skan  if (mips_legitimize_move (HImode, operands[0], operands[1]))
3570169689Skan    DONE;
3571169689Skan})
3572169689Skan
3573169689Skan(define_insn "*movhi_internal"
3574169689Skan  [(set (match_operand:HI 0 "nonimmediate_operand" "=d,d,d,m,*d,*f,*f,*x")
3575169689Skan	(match_operand:HI 1 "move_operand"         "d,I,m,dJ,*f,*d,*f,*d"))]
3576169689Skan  "!TARGET_MIPS16
3577169689Skan   && (register_operand (operands[0], HImode)
3578169689Skan       || reg_or_0_operand (operands[1], HImode))"
3579169689Skan  "@
3580169689Skan    move\t%0,%1
3581169689Skan    li\t%0,%1
3582169689Skan    lhu\t%0,%1
3583169689Skan    sh\t%z1,%0
3584169689Skan    mfc1\t%0,%1
3585169689Skan    mtc1\t%1,%0
3586169689Skan    mov.s\t%0,%1
3587169689Skan    mt%0\t%1"
3588169689Skan  [(set_attr "type"	"arith,arith,load,store,xfer,xfer,fmove,mthilo")
3589169689Skan   (set_attr "mode"	"HI")
3590169689Skan   (set_attr "length"	"4,4,*,*,4,4,4,4")])
3591169689Skan
3592169689Skan(define_insn "*movhi_mips16"
3593169689Skan  [(set (match_operand:HI 0 "nonimmediate_operand" "=d,y,d,d,d,d,m")
3594169689Skan	(match_operand:HI 1 "move_operand"         "d,d,y,K,N,m,d"))]
3595169689Skan  "TARGET_MIPS16
3596169689Skan   && (register_operand (operands[0], HImode)
3597169689Skan       || register_operand (operands[1], HImode))"
3598169689Skan  "@
3599169689Skan    move\t%0,%1
3600169689Skan    move\t%0,%1
3601169689Skan    move\t%0,%1
3602169689Skan    li\t%0,%1
3603169689Skan    #
3604169689Skan    lhu\t%0,%1
3605169689Skan    sh\t%1,%0"
3606169689Skan  [(set_attr "type"	"arith,arith,arith,arith,arith,load,store")
3607169689Skan   (set_attr "mode"	"HI")
3608169689Skan   (set_attr_alternative "length"
3609169689Skan		[(const_int 4)
3610169689Skan		 (const_int 4)
3611169689Skan		 (const_int 4)
3612169689Skan		 (if_then_else (match_operand:VOID 1 "m16_uimm8_1")
3613169689Skan			       (const_int 4)
3614169689Skan			       (const_int 8))
3615169689Skan		 (if_then_else (match_operand:VOID 1 "m16_nuimm8_1")
3616169689Skan			       (const_int 8)
3617169689Skan			       (const_int 12))
3618169689Skan		 (const_string "*")
3619169689Skan		 (const_string "*")])])
3620169689Skan
3621169689Skan
3622169689Skan;; On the mips16, we can split lh $r,N($r) into an add and a load,
3623169689Skan;; when the original load is a 4 byte instruction but the add and the
3624169689Skan;; load are 2 2 byte instructions.
3625169689Skan
3626169689Skan(define_split
3627169689Skan  [(set (match_operand:HI 0 "register_operand")
3628169689Skan	(mem:HI (plus:SI (match_dup 0)
3629169689Skan			 (match_operand:SI 1 "const_int_operand"))))]
3630169689Skan  "TARGET_MIPS16 && reload_completed && !TARGET_DEBUG_D_MODE
3631169689Skan   && REG_P (operands[0])
3632169689Skan   && M16_REG_P (REGNO (operands[0]))
3633169689Skan   && GET_CODE (operands[1]) == CONST_INT
3634169689Skan   && ((INTVAL (operands[1]) < 0
3635169689Skan	&& INTVAL (operands[1]) >= -0x80)
3636169689Skan       || (INTVAL (operands[1]) >= 32 * 2
3637169689Skan	   && INTVAL (operands[1]) <= 31 * 2 + 0x7e)
3638169689Skan       || (INTVAL (operands[1]) >= 0
3639169689Skan	   && INTVAL (operands[1]) < 32 * 2
3640169689Skan	   && (INTVAL (operands[1]) & 1) != 0))"
3641169689Skan  [(set (match_dup 0) (plus:SI (match_dup 0) (match_dup 1)))
3642169689Skan   (set (match_dup 0) (mem:HI (plus:SI (match_dup 0) (match_dup 2))))]
3643169689Skan{
3644169689Skan  HOST_WIDE_INT val = INTVAL (operands[1]);
3645169689Skan
3646169689Skan  if (val < 0)
3647169689Skan    operands[2] = const0_rtx;
3648169689Skan  else if (val >= 32 * 2)
3649169689Skan    {
3650169689Skan      int off = val & 1;
3651169689Skan
3652169689Skan      operands[1] = GEN_INT (0x7e + off);
3653169689Skan      operands[2] = GEN_INT (val - off - 0x7e);
3654169689Skan    }
3655169689Skan  else
3656169689Skan    {
3657169689Skan      int off = val & 1;
3658169689Skan
3659169689Skan      operands[1] = GEN_INT (off);
3660169689Skan      operands[2] = GEN_INT (val - off);
3661169689Skan    }
3662169689Skan})
3663169689Skan
3664169689Skan;; 8-bit Integer moves
3665169689Skan
3666169689Skan;; Unlike most other insns, the move insns can't be split with
3667169689Skan;; different predicates, because register spilling and other parts of
3668169689Skan;; the compiler, have memoized the insn number already.
3669169689Skan;; Unsigned loads are used because LOAD_EXTEND_OP returns ZERO_EXTEND.
3670169689Skan
3671169689Skan(define_expand "movqi"
3672169689Skan  [(set (match_operand:QI 0 "")
3673169689Skan	(match_operand:QI 1 ""))]
3674169689Skan  ""
3675169689Skan{
3676169689Skan  if (mips_legitimize_move (QImode, operands[0], operands[1]))
3677169689Skan    DONE;
3678169689Skan})
3679169689Skan
3680169689Skan(define_insn "*movqi_internal"
3681169689Skan  [(set (match_operand:QI 0 "nonimmediate_operand" "=d,d,d,m,*d,*f,*f,*x")
3682169689Skan	(match_operand:QI 1 "move_operand"         "d,I,m,dJ,*f,*d,*f,*d"))]
3683169689Skan  "!TARGET_MIPS16
3684169689Skan   && (register_operand (operands[0], QImode)
3685169689Skan       || reg_or_0_operand (operands[1], QImode))"
3686169689Skan  "@
3687169689Skan    move\t%0,%1
3688169689Skan    li\t%0,%1
3689169689Skan    lbu\t%0,%1
3690169689Skan    sb\t%z1,%0
3691169689Skan    mfc1\t%0,%1
3692169689Skan    mtc1\t%1,%0
3693169689Skan    mov.s\t%0,%1
3694169689Skan    mt%0\t%1"
3695169689Skan  [(set_attr "type"	"arith,arith,load,store,xfer,xfer,fmove,mthilo")
3696169689Skan   (set_attr "mode"	"QI")
3697169689Skan   (set_attr "length"	"4,4,*,*,4,4,4,4")])
3698169689Skan
3699169689Skan(define_insn "*movqi_mips16"
3700169689Skan  [(set (match_operand:QI 0 "nonimmediate_operand" "=d,y,d,d,d,d,m")
3701169689Skan	(match_operand:QI 1 "move_operand"         "d,d,y,K,N,m,d"))]
3702169689Skan  "TARGET_MIPS16
3703169689Skan   && (register_operand (operands[0], QImode)
3704169689Skan       || register_operand (operands[1], QImode))"
3705169689Skan  "@
3706169689Skan    move\t%0,%1
3707169689Skan    move\t%0,%1
3708169689Skan    move\t%0,%1
3709169689Skan    li\t%0,%1
3710169689Skan    #
3711169689Skan    lbu\t%0,%1
3712169689Skan    sb\t%1,%0"
3713169689Skan  [(set_attr "type"	"arith,arith,arith,arith,arith,load,store")
3714169689Skan   (set_attr "mode"	"QI")
3715169689Skan   (set_attr "length"	"4,4,4,4,8,*,*")])
3716169689Skan
3717169689Skan;; On the mips16, we can split lb $r,N($r) into an add and a load,
3718169689Skan;; when the original load is a 4 byte instruction but the add and the
3719169689Skan;; load are 2 2 byte instructions.
3720169689Skan
3721169689Skan(define_split
3722169689Skan  [(set (match_operand:QI 0 "register_operand")
3723169689Skan	(mem:QI (plus:SI (match_dup 0)
3724169689Skan			 (match_operand:SI 1 "const_int_operand"))))]
3725169689Skan  "TARGET_MIPS16 && reload_completed && !TARGET_DEBUG_D_MODE
3726169689Skan   && REG_P (operands[0])
3727169689Skan   && M16_REG_P (REGNO (operands[0]))
3728169689Skan   && GET_CODE (operands[1]) == CONST_INT
3729169689Skan   && ((INTVAL (operands[1]) < 0
3730169689Skan	&& INTVAL (operands[1]) >= -0x80)
3731169689Skan       || (INTVAL (operands[1]) >= 32
3732169689Skan	   && INTVAL (operands[1]) <= 31 + 0x7f))"
3733169689Skan  [(set (match_dup 0) (plus:SI (match_dup 0) (match_dup 1)))
3734169689Skan   (set (match_dup 0) (mem:QI (plus:SI (match_dup 0) (match_dup 2))))]
3735169689Skan{
3736169689Skan  HOST_WIDE_INT val = INTVAL (operands[1]);
3737169689Skan
3738169689Skan  if (val < 0)
3739169689Skan    operands[2] = const0_rtx;
3740169689Skan  else
3741169689Skan    {
3742169689Skan      operands[1] = GEN_INT (0x7f);
3743169689Skan      operands[2] = GEN_INT (val - 0x7f);
3744169689Skan    }
3745169689Skan})
3746169689Skan
3747169689Skan;; 32-bit floating point moves
3748169689Skan
3749169689Skan(define_expand "movsf"
3750169689Skan  [(set (match_operand:SF 0 "")
3751169689Skan	(match_operand:SF 1 ""))]
3752169689Skan  ""
3753169689Skan{
3754169689Skan  if (mips_legitimize_move (SFmode, operands[0], operands[1]))
3755169689Skan    DONE;
3756169689Skan})
3757169689Skan
3758169689Skan(define_insn "*movsf_hardfloat"
3759169689Skan  [(set (match_operand:SF 0 "nonimmediate_operand" "=f,f,f,m,m,*f,*d,*d,*d,*m")
3760169689Skan	(match_operand:SF 1 "move_operand" "f,G,m,f,G,*d,*f,*G*d,*m,*d"))]
3761169689Skan  "TARGET_HARD_FLOAT
3762169689Skan   && (register_operand (operands[0], SFmode)
3763169689Skan       || reg_or_0_operand (operands[1], SFmode))"
3764169689Skan  { return mips_output_move (operands[0], operands[1]); }
3765169689Skan  [(set_attr "type"	"fmove,xfer,fpload,fpstore,store,xfer,xfer,arith,load,store")
3766169689Skan   (set_attr "mode"	"SF")
3767169689Skan   (set_attr "length"	"4,4,*,*,*,4,4,4,*,*")])
3768169689Skan
3769169689Skan(define_insn "*movsf_softfloat"
3770169689Skan  [(set (match_operand:SF 0 "nonimmediate_operand" "=d,d,m")
3771169689Skan	(match_operand:SF 1 "move_operand" "Gd,m,d"))]
3772169689Skan  "TARGET_SOFT_FLOAT && !TARGET_MIPS16
3773169689Skan   && (register_operand (operands[0], SFmode)
3774169689Skan       || reg_or_0_operand (operands[1], SFmode))"
3775169689Skan  { return mips_output_move (operands[0], operands[1]); }
3776169689Skan  [(set_attr "type"	"arith,load,store")
3777169689Skan   (set_attr "mode"	"SF")
3778169689Skan   (set_attr "length"	"4,*,*")])
3779169689Skan
3780169689Skan(define_insn "*movsf_mips16"
3781169689Skan  [(set (match_operand:SF 0 "nonimmediate_operand" "=d,y,d,d,m")
3782169689Skan	(match_operand:SF 1 "move_operand" "d,d,y,m,d"))]
3783169689Skan  "TARGET_MIPS16
3784169689Skan   && (register_operand (operands[0], SFmode)
3785169689Skan       || register_operand (operands[1], SFmode))"
3786169689Skan  { return mips_output_move (operands[0], operands[1]); }
3787169689Skan  [(set_attr "type"	"arith,arith,arith,load,store")
3788169689Skan   (set_attr "mode"	"SF")
3789169689Skan   (set_attr "length"	"4,4,4,*,*")])
3790169689Skan
3791169689Skan
3792169689Skan;; 64-bit floating point moves
3793169689Skan
3794169689Skan(define_expand "movdf"
3795169689Skan  [(set (match_operand:DF 0 "")
3796169689Skan	(match_operand:DF 1 ""))]
3797169689Skan  ""
3798169689Skan{
3799169689Skan  if (mips_legitimize_move (DFmode, operands[0], operands[1]))
3800169689Skan    DONE;
3801169689Skan})
3802169689Skan
3803169689Skan(define_insn "*movdf_hardfloat_64bit"
3804169689Skan  [(set (match_operand:DF 0 "nonimmediate_operand" "=f,f,f,m,m,*f,*d,*d,*d,*m")
3805169689Skan	(match_operand:DF 1 "move_operand" "f,G,m,f,G,*d,*f,*d*G,*m,*d"))]
3806169689Skan  "TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT && TARGET_64BIT
3807169689Skan   && (register_operand (operands[0], DFmode)
3808169689Skan       || reg_or_0_operand (operands[1], DFmode))"
3809169689Skan  { return mips_output_move (operands[0], operands[1]); }
3810169689Skan  [(set_attr "type"	"fmove,xfer,fpload,fpstore,store,xfer,xfer,arith,load,store")
3811169689Skan   (set_attr "mode"	"DF")
3812169689Skan   (set_attr "length"	"4,4,*,*,*,4,4,4,*,*")])
3813169689Skan
3814169689Skan(define_insn "*movdf_hardfloat_32bit"
3815169689Skan  [(set (match_operand:DF 0 "nonimmediate_operand" "=f,f,f,m,m,*f,*d,*d,*d,*m")
3816169689Skan	(match_operand:DF 1 "move_operand" "f,G,m,f,G,*d,*f,*d*G,*m,*d"))]
3817169689Skan  "TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT && !TARGET_64BIT
3818169689Skan   && (register_operand (operands[0], DFmode)
3819169689Skan       || reg_or_0_operand (operands[1], DFmode))"
3820169689Skan  { return mips_output_move (operands[0], operands[1]); }
3821169689Skan  [(set_attr "type"	"fmove,xfer,fpload,fpstore,store,xfer,xfer,arith,load,store")
3822169689Skan   (set_attr "mode"	"DF")
3823169689Skan   (set_attr "length"	"4,8,*,*,*,8,8,8,*,*")])
3824169689Skan
3825169689Skan(define_insn "*movdf_softfloat"
3826169689Skan  [(set (match_operand:DF 0 "nonimmediate_operand" "=d,d,m,d,f,f")
3827169689Skan	(match_operand:DF 1 "move_operand" "dG,m,dG,f,d,f"))]
3828169689Skan  "(TARGET_SOFT_FLOAT || TARGET_SINGLE_FLOAT) && !TARGET_MIPS16
3829169689Skan   && (register_operand (operands[0], DFmode)
3830169689Skan       || reg_or_0_operand (operands[1], DFmode))"
3831169689Skan  { return mips_output_move (operands[0], operands[1]); }
3832169689Skan  [(set_attr "type"	"arith,load,store,xfer,xfer,fmove")
3833169689Skan   (set_attr "mode"	"DF")
3834169689Skan   (set_attr "length"	"8,*,*,4,4,4")])
3835169689Skan
3836169689Skan(define_insn "*movdf_mips16"
3837169689Skan  [(set (match_operand:DF 0 "nonimmediate_operand" "=d,y,d,d,m")
3838169689Skan	(match_operand:DF 1 "move_operand" "d,d,y,m,d"))]
3839169689Skan  "TARGET_MIPS16
3840169689Skan   && (register_operand (operands[0], DFmode)
3841169689Skan       || register_operand (operands[1], DFmode))"
3842169689Skan  { return mips_output_move (operands[0], operands[1]); }
3843169689Skan  [(set_attr "type"	"arith,arith,arith,load,store")
3844169689Skan   (set_attr "mode"	"DF")
3845169689Skan   (set_attr "length"	"8,8,8,*,*")])
3846169689Skan
3847169689Skan(define_split
3848169689Skan  [(set (match_operand:DI 0 "nonimmediate_operand")
3849169689Skan	(match_operand:DI 1 "move_operand"))]
3850169689Skan  "reload_completed && !TARGET_64BIT
3851169689Skan   && mips_split_64bit_move_p (operands[0], operands[1])"
3852169689Skan  [(const_int 0)]
3853169689Skan{
3854169689Skan  mips_split_64bit_move (operands[0], operands[1]);
3855169689Skan  DONE;
3856169689Skan})
3857169689Skan
3858169689Skan(define_split
3859169689Skan  [(set (match_operand:DF 0 "nonimmediate_operand")
3860169689Skan	(match_operand:DF 1 "move_operand"))]
3861169689Skan  "reload_completed && !TARGET_64BIT
3862169689Skan   && mips_split_64bit_move_p (operands[0], operands[1])"
3863169689Skan  [(const_int 0)]
3864169689Skan{
3865169689Skan  mips_split_64bit_move (operands[0], operands[1]);
3866169689Skan  DONE;
3867169689Skan})
3868169689Skan
3869169689Skan;; When generating mips16 code, split moves of negative constants into
3870169689Skan;; a positive "li" followed by a negation.
3871169689Skan(define_split
3872169689Skan  [(set (match_operand 0 "register_operand")
3873169689Skan	(match_operand 1 "const_int_operand"))]
3874169689Skan  "TARGET_MIPS16 && reload_completed && INTVAL (operands[1]) < 0"
3875169689Skan  [(set (match_dup 2)
3876169689Skan	(match_dup 3))
3877169689Skan   (set (match_dup 2)
3878169689Skan	(neg:SI (match_dup 2)))]
3879169689Skan{
3880169689Skan  operands[2] = gen_lowpart (SImode, operands[0]);
3881169689Skan  operands[3] = GEN_INT (-INTVAL (operands[1]));
3882169689Skan})
3883169689Skan
3884169689Skan;; 64-bit paired-single floating point moves
3885169689Skan
3886169689Skan(define_expand "movv2sf"
3887169689Skan  [(set (match_operand:V2SF 0)
3888169689Skan	(match_operand:V2SF 1))]
3889169689Skan  "TARGET_PAIRED_SINGLE_FLOAT"
3890169689Skan{
3891169689Skan  if (mips_legitimize_move (V2SFmode, operands[0], operands[1]))
3892169689Skan    DONE;
3893169689Skan})
3894169689Skan
3895169689Skan(define_insn "movv2sf_hardfloat_64bit"
3896169689Skan  [(set (match_operand:V2SF 0 "nonimmediate_operand" "=f,f,f,m,m,*f,*d,*d,*d,*m")
3897169689Skan	(match_operand:V2SF 1 "move_operand" "f,YG,m,f,YG,*d,*f,*d*YG,*m,*d"))]
3898169689Skan  "TARGET_PAIRED_SINGLE_FLOAT
3899169689Skan   && TARGET_64BIT
3900169689Skan   && (register_operand (operands[0], V2SFmode)
3901169689Skan       || reg_or_0_operand (operands[1], V2SFmode))"
3902169689Skan  { return mips_output_move (operands[0], operands[1]); }
3903169689Skan  [(set_attr "type" "fmove,xfer,fpload,fpstore,store,xfer,xfer,arith,load,store")
3904169689Skan   (set_attr "mode" "SF")
3905169689Skan   (set_attr "length" "4,4,*,*,*,4,4,4,*,*")])
3906169689Skan
3907169689Skan;; The HI and LO registers are not truly independent.  If we move an mthi
3908169689Skan;; instruction before an mflo instruction, it will make the result of the
3909169689Skan;; mflo unpredictable.  The same goes for mtlo and mfhi.
3910169689Skan;;
3911169689Skan;; We cope with this by making the mflo and mfhi patterns use both HI and LO.
3912169689Skan;; Operand 1 is the register we want, operand 2 is the other one.
3913169689Skan;;
3914169689Skan;; When generating VR4120 or VR4130 code, we use macc{,hi} and
3915169689Skan;; dmacc{,hi} instead of mfhi and mflo.  This avoids both the normal
3916169689Skan;; MIPS III hi/lo hazards and the errata related to -mfix-vr4130.
3917169689Skan
3918169689Skan(define_expand "mfhilo_<mode>"
3919169689Skan  [(set (match_operand:GPR 0 "register_operand")
3920169689Skan	(unspec:GPR [(match_operand:GPR 1 "register_operand")
3921169689Skan		     (match_operand:GPR 2 "register_operand")]
3922169689Skan		    UNSPEC_MFHILO))])
3923169689Skan
3924169689Skan(define_insn "*mfhilo_<mode>"
3925169689Skan  [(set (match_operand:GPR 0 "register_operand" "=d,d")
3926169689Skan	(unspec:GPR [(match_operand:GPR 1 "register_operand" "h,l")
3927169689Skan		     (match_operand:GPR 2 "register_operand" "l,h")]
3928169689Skan		    UNSPEC_MFHILO))]
3929169689Skan  "!ISA_HAS_MACCHI"
3930169689Skan  "mf%1\t%0"
3931169689Skan  [(set_attr "type" "mfhilo")
3932169689Skan   (set_attr "mode" "<MODE>")])
3933169689Skan
3934169689Skan(define_insn "*mfhilo_<mode>_macc"
3935169689Skan  [(set (match_operand:GPR 0 "register_operand" "=d,d")
3936169689Skan	(unspec:GPR [(match_operand:GPR 1 "register_operand" "h,l")
3937169689Skan		     (match_operand:GPR 2 "register_operand" "l,h")]
3938169689Skan		    UNSPEC_MFHILO))]
3939169689Skan  "ISA_HAS_MACCHI"
3940169689Skan{
3941169689Skan  if (REGNO (operands[1]) == HI_REGNUM)
3942169689Skan    return "<d>macchi\t%0,%.,%.";
3943169689Skan  else
3944169689Skan    return "<d>macc\t%0,%.,%.";
3945169689Skan}
3946169689Skan  [(set_attr "type" "mfhilo")
3947169689Skan   (set_attr "mode" "<MODE>")])
3948169689Skan
3949169689Skan;; Patterns for loading or storing part of a paired floating point
3950169689Skan;; register.  We need them because odd-numbered floating-point registers
3951169689Skan;; are not fully independent: see mips_split_64bit_move.
3952169689Skan
3953169689Skan;; Load the low word of operand 0 with operand 1.
3954169689Skan(define_insn "load_df_low"
3955169689Skan  [(set (match_operand:DF 0 "register_operand" "=f,f")
3956169689Skan	(unspec:DF [(match_operand:SI 1 "general_operand" "dJ,m")]
3957169689Skan		   UNSPEC_LOAD_DF_LOW))]
3958169689Skan  "TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT && !TARGET_64BIT"
3959169689Skan{
3960169689Skan  operands[0] = mips_subword (operands[0], 0);
3961169689Skan  return mips_output_move (operands[0], operands[1]);
3962169689Skan}
3963169689Skan  [(set_attr "type"	"xfer,fpload")
3964169689Skan   (set_attr "mode"	"SF")])
3965169689Skan
3966169689Skan;; Load the high word of operand 0 from operand 1, preserving the value
3967169689Skan;; in the low word.
3968169689Skan(define_insn "load_df_high"
3969169689Skan  [(set (match_operand:DF 0 "register_operand" "=f,f")
3970169689Skan	(unspec:DF [(match_operand:SI 1 "general_operand" "dJ,m")
3971169689Skan		    (match_operand:DF 2 "register_operand" "0,0")]
3972169689Skan		   UNSPEC_LOAD_DF_HIGH))]
3973169689Skan  "TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT && !TARGET_64BIT"
3974169689Skan{
3975169689Skan  operands[0] = mips_subword (operands[0], 1);
3976169689Skan  return mips_output_move (operands[0], operands[1]);
3977169689Skan}
3978169689Skan  [(set_attr "type"	"xfer,fpload")
3979169689Skan   (set_attr "mode"	"SF")])
3980169689Skan
3981169689Skan;; Store the high word of operand 1 in operand 0.  The corresponding
3982169689Skan;; low-word move is done in the normal way.
3983169689Skan(define_insn "store_df_high"
3984169689Skan  [(set (match_operand:SI 0 "nonimmediate_operand" "=d,m")
3985169689Skan	(unspec:SI [(match_operand:DF 1 "register_operand" "f,f")]
3986169689Skan		   UNSPEC_STORE_DF_HIGH))]
3987169689Skan  "TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT && !TARGET_64BIT"
3988169689Skan{
3989169689Skan  operands[1] = mips_subword (operands[1], 1);
3990169689Skan  return mips_output_move (operands[0], operands[1]);
3991169689Skan}
3992169689Skan  [(set_attr "type"	"xfer,fpstore")
3993169689Skan   (set_attr "mode"	"SF")])
3994169689Skan
3995169689Skan;; Insn to initialize $gp for n32/n64 abicalls.  Operand 0 is the offset
3996169689Skan;; of _gp from the start of this function.  Operand 1 is the incoming
3997169689Skan;; function address.
3998169689Skan(define_insn_and_split "loadgp"
3999169689Skan  [(unspec_volatile [(match_operand 0 "" "")
4000169689Skan		     (match_operand 1 "register_operand" "")] UNSPEC_LOADGP)]
4001169689Skan  "mips_current_loadgp_style () == LOADGP_NEWABI"
4002169689Skan  "#"
4003169689Skan  ""
4004169689Skan  [(set (match_dup 2) (match_dup 3))
4005169689Skan   (set (match_dup 2) (match_dup 4))
4006169689Skan   (set (match_dup 2) (match_dup 5))]
4007169689Skan{
4008169689Skan  operands[2] = pic_offset_table_rtx;
4009169689Skan  operands[3] = gen_rtx_HIGH (Pmode, operands[0]);
4010169689Skan  operands[4] = gen_rtx_PLUS (Pmode, operands[2], operands[1]);
4011169689Skan  operands[5] = gen_rtx_LO_SUM (Pmode, operands[2], operands[0]);
4012169689Skan}
4013169689Skan  [(set_attr "length" "12")])
4014169689Skan
4015169689Skan;; Likewise, for -mno-shared code.  Operand 0 is the __gnu_local_gp symbol.
4016169689Skan(define_insn_and_split "loadgp_noshared"
4017169689Skan  [(unspec_volatile [(match_operand 0 "" "")] UNSPEC_LOADGP)]
4018169689Skan  "mips_current_loadgp_style () == LOADGP_ABSOLUTE"
4019169689Skan  "#"
4020169689Skan  ""
4021169689Skan  [(const_int 0)]
4022169689Skan{
4023169689Skan  emit_move_insn (pic_offset_table_rtx, operands[0]);
4024169689Skan  DONE;
4025169689Skan}
4026169689Skan  [(set_attr "length" "8")])
4027169689Skan
4028169689Skan;; The use of gp is hidden when not using explicit relocations.
4029169689Skan;; This blockage instruction prevents the gp load from being
4030169689Skan;; scheduled after an implicit use of gp.  It also prevents
4031169689Skan;; the load from being deleted as dead.
4032169689Skan(define_insn "loadgp_blockage"
4033169689Skan  [(unspec_volatile [(reg:DI 28)] UNSPEC_BLOCKAGE)]
4034169689Skan  ""
4035169689Skan  ""
4036169689Skan  [(set_attr "type"	"unknown")
4037169689Skan   (set_attr "mode"	"none")
4038169689Skan   (set_attr "length"	"0")])
4039169689Skan
4040169689Skan;; Emit a .cprestore directive, which normally expands to a single store
4041169689Skan;; instruction.  Note that we continue to use .cprestore for explicit reloc
4042169689Skan;; code so that jals inside inline asms will work correctly.
4043169689Skan(define_insn "cprestore"
4044169689Skan  [(unspec_volatile [(match_operand 0 "const_int_operand" "I,i")]
4045169689Skan		    UNSPEC_CPRESTORE)]
4046169689Skan  ""
4047169689Skan{
4048169689Skan  if (set_nomacro && which_alternative == 1)
4049169689Skan    return ".set\tmacro\;.cprestore\t%0\;.set\tnomacro";
4050169689Skan  else
4051169689Skan    return ".cprestore\t%0";
4052169689Skan}
4053169689Skan  [(set_attr "type" "store")
4054169689Skan   (set_attr "length" "4,12")])
4055169689Skan
4056169689Skan;; Block moves, see mips.c for more details.
4057169689Skan;; Argument 0 is the destination
4058169689Skan;; Argument 1 is the source
4059169689Skan;; Argument 2 is the length
4060169689Skan;; Argument 3 is the alignment
4061169689Skan
4062169689Skan(define_expand "movmemsi"
4063169689Skan  [(parallel [(set (match_operand:BLK 0 "general_operand")
4064169689Skan		   (match_operand:BLK 1 "general_operand"))
4065169689Skan	      (use (match_operand:SI 2 ""))
4066169689Skan	      (use (match_operand:SI 3 "const_int_operand"))])]
4067169689Skan  "!TARGET_MIPS16 && !TARGET_MEMCPY"
4068169689Skan{
4069169689Skan  if (mips_expand_block_move (operands[0], operands[1], operands[2]))
4070169689Skan    DONE;
4071169689Skan  else
4072169689Skan    FAIL;
4073169689Skan})
4074169689Skan
4075169689Skan;;
4076169689Skan;;  ....................
4077169689Skan;;
4078169689Skan;;	SHIFTS
4079169689Skan;;
4080169689Skan;;  ....................
4081169689Skan
4082169689Skan(define_expand "<optab><mode>3"
4083169689Skan  [(set (match_operand:GPR 0 "register_operand")
4084169689Skan	(any_shift:GPR (match_operand:GPR 1 "register_operand")
4085169689Skan		       (match_operand:SI 2 "arith_operand")))]
4086169689Skan  ""
4087169689Skan{
4088169689Skan  /* On the mips16, a shift of more than 8 is a four byte instruction,
4089169689Skan     so, for a shift between 8 and 16, it is just as fast to do two
4090169689Skan     shifts of 8 or less.  If there is a lot of shifting going on, we
4091169689Skan     may win in CSE.  Otherwise combine will put the shifts back
4092169689Skan     together again.  This can be called by function_arg, so we must
4093169689Skan     be careful not to allocate a new register if we've reached the
4094169689Skan     reload pass.  */
4095169689Skan  if (TARGET_MIPS16
4096169689Skan      && optimize
4097169689Skan      && GET_CODE (operands[2]) == CONST_INT
4098169689Skan      && INTVAL (operands[2]) > 8
4099169689Skan      && INTVAL (operands[2]) <= 16
4100169689Skan      && !reload_in_progress
4101169689Skan      && !reload_completed)
4102169689Skan    {
4103169689Skan      rtx temp = gen_reg_rtx (<MODE>mode);
4104169689Skan
4105169689Skan      emit_insn (gen_<optab><mode>3 (temp, operands[1], GEN_INT (8)));
4106169689Skan      emit_insn (gen_<optab><mode>3 (operands[0], temp,
4107169689Skan				     GEN_INT (INTVAL (operands[2]) - 8)));
4108169689Skan      DONE;
4109169689Skan    }
4110169689Skan})
4111169689Skan
4112169689Skan(define_insn "*<optab><mode>3"
4113169689Skan  [(set (match_operand:GPR 0 "register_operand" "=d")
4114169689Skan	(any_shift:GPR (match_operand:GPR 1 "register_operand" "d")
4115169689Skan		       (match_operand:SI 2 "arith_operand" "dI")))]
4116169689Skan  "!TARGET_MIPS16"
4117169689Skan{
4118169689Skan  if (GET_CODE (operands[2]) == CONST_INT)
4119169689Skan    operands[2] = GEN_INT (INTVAL (operands[2])
4120169689Skan			   & (GET_MODE_BITSIZE (<MODE>mode) - 1));
4121169689Skan
4122169689Skan  return "<d><insn>\t%0,%1,%2";
4123169689Skan}
4124169689Skan  [(set_attr "type" "shift")
4125169689Skan   (set_attr "mode" "<MODE>")])
4126169689Skan
4127169689Skan(define_insn "*<optab>si3_extend"
4128169689Skan  [(set (match_operand:DI 0 "register_operand" "=d")
4129169689Skan	(sign_extend:DI
4130169689Skan	   (any_shift:SI (match_operand:SI 1 "register_operand" "d")
4131169689Skan			 (match_operand:SI 2 "arith_operand" "dI"))))]
4132169689Skan  "TARGET_64BIT && !TARGET_MIPS16"
4133169689Skan{
4134169689Skan  if (GET_CODE (operands[2]) == CONST_INT)
4135169689Skan    operands[2] = GEN_INT (INTVAL (operands[2]) & 0x1f);
4136169689Skan
4137169689Skan  return "<insn>\t%0,%1,%2";
4138169689Skan}
4139169689Skan  [(set_attr "type" "shift")
4140169689Skan   (set_attr "mode" "SI")])
4141169689Skan
4142169689Skan(define_insn "*<optab>si3_mips16"
4143169689Skan  [(set (match_operand:SI 0 "register_operand" "=d,d")
4144169689Skan	(any_shift:SI (match_operand:SI 1 "register_operand" "0,d")
4145169689Skan		      (match_operand:SI 2 "arith_operand" "d,I")))]
4146169689Skan  "TARGET_MIPS16"
4147169689Skan{
4148169689Skan  if (which_alternative == 0)
4149169689Skan    return "<insn>\t%0,%2";
4150169689Skan
4151169689Skan  operands[2] = GEN_INT (INTVAL (operands[2]) & 0x1f);
4152169689Skan  return "<insn>\t%0,%1,%2";
4153169689Skan}
4154169689Skan  [(set_attr "type" "shift")
4155169689Skan   (set_attr "mode" "SI")
4156169689Skan   (set_attr_alternative "length"
4157169689Skan		[(const_int 4)
4158169689Skan		 (if_then_else (match_operand 2 "m16_uimm3_b")
4159169689Skan			       (const_int 4)
4160169689Skan			       (const_int 8))])])
4161169689Skan
4162169689Skan;; We need separate DImode MIPS16 patterns because of the irregularity
4163169689Skan;; of right shifts.
4164169689Skan(define_insn "*ashldi3_mips16"
4165169689Skan  [(set (match_operand:DI 0 "register_operand" "=d,d")
4166169689Skan	(ashift:DI (match_operand:DI 1 "register_operand" "0,d")
4167169689Skan		   (match_operand:SI 2 "arith_operand" "d,I")))]
4168169689Skan  "TARGET_64BIT && TARGET_MIPS16"
4169169689Skan{
4170169689Skan  if (which_alternative == 0)
4171169689Skan    return "dsll\t%0,%2";
4172169689Skan
4173169689Skan  operands[2] = GEN_INT (INTVAL (operands[2]) & 0x3f);
4174169689Skan  return "dsll\t%0,%1,%2";
4175169689Skan}
4176169689Skan  [(set_attr "type" "shift")
4177169689Skan   (set_attr "mode" "DI")
4178169689Skan   (set_attr_alternative "length"
4179169689Skan		[(const_int 4)
4180169689Skan		 (if_then_else (match_operand 2 "m16_uimm3_b")
4181169689Skan			       (const_int 4)
4182169689Skan			       (const_int 8))])])
4183169689Skan
4184169689Skan(define_insn "*ashrdi3_mips16"
4185169689Skan  [(set (match_operand:DI 0 "register_operand" "=d,d")
4186169689Skan	(ashiftrt:DI (match_operand:DI 1 "register_operand" "0,0")
4187169689Skan		     (match_operand:SI 2 "arith_operand" "d,I")))]
4188169689Skan  "TARGET_64BIT && TARGET_MIPS16"
4189169689Skan{
4190169689Skan  if (GET_CODE (operands[2]) == CONST_INT)
4191169689Skan    operands[2] = GEN_INT (INTVAL (operands[2]) & 0x3f);
4192169689Skan
4193169689Skan  return "dsra\t%0,%2";
4194169689Skan}
4195169689Skan  [(set_attr "type" "shift")
4196169689Skan   (set_attr "mode" "DI")
4197169689Skan   (set_attr_alternative "length"
4198169689Skan		[(const_int 4)
4199169689Skan		 (if_then_else (match_operand 2 "m16_uimm3_b")
4200169689Skan			       (const_int 4)
4201169689Skan			       (const_int 8))])])
4202169689Skan
4203169689Skan(define_insn "*lshrdi3_mips16"
4204169689Skan  [(set (match_operand:DI 0 "register_operand" "=d,d")
4205169689Skan	(lshiftrt:DI (match_operand:DI 1 "register_operand" "0,0")
4206169689Skan		     (match_operand:SI 2 "arith_operand" "d,I")))]
4207169689Skan  "TARGET_64BIT && TARGET_MIPS16"
4208169689Skan{
4209169689Skan  if (GET_CODE (operands[2]) == CONST_INT)
4210169689Skan    operands[2] = GEN_INT (INTVAL (operands[2]) & 0x3f);
4211169689Skan
4212169689Skan  return "dsrl\t%0,%2";
4213169689Skan}
4214169689Skan  [(set_attr "type" "shift")
4215169689Skan   (set_attr "mode" "DI")
4216169689Skan   (set_attr_alternative "length"
4217169689Skan		[(const_int 4)
4218169689Skan		 (if_then_else (match_operand 2 "m16_uimm3_b")
4219169689Skan			       (const_int 4)
4220169689Skan			       (const_int 8))])])
4221169689Skan
4222169689Skan;; On the mips16, we can split a 4 byte shift into 2 2 byte shifts.
4223169689Skan
4224169689Skan(define_split
4225169689Skan  [(set (match_operand:GPR 0 "register_operand")
4226169689Skan	(any_shift:GPR (match_operand:GPR 1 "register_operand")
4227169689Skan		       (match_operand:GPR 2 "const_int_operand")))]
4228169689Skan  "TARGET_MIPS16 && reload_completed && !TARGET_DEBUG_D_MODE
4229169689Skan   && GET_CODE (operands[2]) == CONST_INT
4230169689Skan   && INTVAL (operands[2]) > 8
4231169689Skan   && INTVAL (operands[2]) <= 16"
4232169689Skan  [(set (match_dup 0) (any_shift:GPR (match_dup 1) (const_int 8)))
4233169689Skan   (set (match_dup 0) (any_shift:GPR (match_dup 0) (match_dup 2)))]
4234169689Skan  { operands[2] = GEN_INT (INTVAL (operands[2]) - 8); })
4235169689Skan
4236169689Skan;; If we load a byte on the mips16 as a bitfield, the resulting
4237169689Skan;; sequence of instructions is too complicated for combine, because it
4238169689Skan;; involves four instructions: a load, a shift, a constant load into a
4239169689Skan;; register, and an and (the key problem here is that the mips16 does
4240169689Skan;; not have and immediate).  We recognize a shift of a load in order
4241169689Skan;; to make it simple enough for combine to understand.
4242169689Skan;;
4243169689Skan;; The length here is the worst case: the length of the split version
4244169689Skan;; will be more accurate.
4245169689Skan(define_insn_and_split ""
4246169689Skan  [(set (match_operand:SI 0 "register_operand" "=d")
4247169689Skan	(lshiftrt:SI (match_operand:SI 1 "memory_operand" "m")
4248169689Skan		     (match_operand:SI 2 "immediate_operand" "I")))]
4249169689Skan  "TARGET_MIPS16"
4250169689Skan  "#"
4251169689Skan  ""
4252169689Skan  [(set (match_dup 0) (match_dup 1))
4253169689Skan   (set (match_dup 0) (lshiftrt:SI (match_dup 0) (match_dup 2)))]
4254169689Skan  ""
4255169689Skan  [(set_attr "type"	"load")
4256169689Skan   (set_attr "mode"	"SI")
4257169689Skan   (set_attr "length"	"16")])
4258169689Skan
4259169689Skan(define_insn "rotr<mode>3"
4260169689Skan  [(set (match_operand:GPR 0 "register_operand" "=d")
4261169689Skan	(rotatert:GPR (match_operand:GPR 1 "register_operand" "d")
4262169689Skan		      (match_operand:SI 2 "arith_operand" "dI")))]
4263169689Skan  "ISA_HAS_ROTR_<MODE>"
4264169689Skan{
4265169689Skan  if (GET_CODE (operands[2]) == CONST_INT)
4266169689Skan    gcc_assert (INTVAL (operands[2]) >= 0
4267169689Skan		&& INTVAL (operands[2]) < GET_MODE_BITSIZE (<MODE>mode));
4268169689Skan
4269169689Skan  return "<d>ror\t%0,%1,%2";
4270169689Skan}
4271169689Skan  [(set_attr "type" "shift")
4272169689Skan   (set_attr "mode" "<MODE>")])
4273169689Skan
4274169689Skan;;
4275169689Skan;;  ....................
4276169689Skan;;
4277169689Skan;;	COMPARISONS
4278169689Skan;;
4279169689Skan;;  ....................
4280169689Skan
4281169689Skan;; Flow here is rather complex:
4282169689Skan;;
4283169689Skan;;  1)	The cmp{si,di,sf,df} routine is called.  It deposits the arguments
4284169689Skan;;	into cmp_operands[] but generates no RTL.
4285169689Skan;;
4286169689Skan;;  2)	The appropriate branch define_expand is called, which then
4287169689Skan;;	creates the appropriate RTL for the comparison and branch.
4288169689Skan;;	Different CC modes are used, based on what type of branch is
4289169689Skan;;	done, so that we can constrain things appropriately.  There
4290169689Skan;;	are assumptions in the rest of GCC that break if we fold the
4291169689Skan;;	operands into the branches for integer operations, and use cc0
4292169689Skan;;	for floating point, so we use the fp status register instead.
4293169689Skan;;	If needed, an appropriate temporary is created to hold the
4294169689Skan;;	of the integer compare.
4295169689Skan
4296169689Skan(define_expand "cmp<mode>"
4297169689Skan  [(set (cc0)
4298169689Skan	(compare:CC (match_operand:GPR 0 "register_operand")
4299169689Skan		    (match_operand:GPR 1 "nonmemory_operand")))]
4300169689Skan  ""
4301169689Skan{
4302169689Skan  cmp_operands[0] = operands[0];
4303169689Skan  cmp_operands[1] = operands[1];
4304169689Skan  DONE;
4305169689Skan})
4306169689Skan
4307169689Skan(define_expand "cmp<mode>"
4308169689Skan  [(set (cc0)
4309169689Skan	(compare:CC (match_operand:SCALARF 0 "register_operand")
4310169689Skan		    (match_operand:SCALARF 1 "register_operand")))]
4311169689Skan  ""
4312169689Skan{
4313169689Skan  cmp_operands[0] = operands[0];
4314169689Skan  cmp_operands[1] = operands[1];
4315169689Skan  DONE;
4316169689Skan})
4317169689Skan
4318169689Skan;;
4319169689Skan;;  ....................
4320169689Skan;;
4321169689Skan;;	CONDITIONAL BRANCHES
4322169689Skan;;
4323169689Skan;;  ....................
4324169689Skan
4325169689Skan;; Conditional branches on floating-point equality tests.
4326169689Skan
4327169689Skan(define_insn "*branch_fp"
4328169689Skan  [(set (pc)
4329169689Skan        (if_then_else
4330169689Skan         (match_operator 0 "equality_operator"
4331169689Skan                         [(match_operand:CC 2 "register_operand" "z")
4332169689Skan			  (const_int 0)])
4333169689Skan         (label_ref (match_operand 1 "" ""))
4334169689Skan         (pc)))]
4335169689Skan  "TARGET_HARD_FLOAT"
4336169689Skan{
4337169689Skan  return mips_output_conditional_branch (insn, operands,
4338169689Skan					 MIPS_BRANCH ("b%F0", "%Z2%1"),
4339169689Skan					 MIPS_BRANCH ("b%W0", "%Z2%1"));
4340169689Skan}
4341169689Skan  [(set_attr "type" "branch")
4342169689Skan   (set_attr "mode" "none")])
4343169689Skan
4344169689Skan(define_insn "*branch_fp_inverted"
4345169689Skan  [(set (pc)
4346169689Skan        (if_then_else
4347169689Skan         (match_operator 0 "equality_operator"
4348169689Skan                         [(match_operand:CC 2 "register_operand" "z")
4349169689Skan			  (const_int 0)])
4350169689Skan         (pc)
4351169689Skan         (label_ref (match_operand 1 "" ""))))]
4352169689Skan  "TARGET_HARD_FLOAT"
4353169689Skan{
4354169689Skan  return mips_output_conditional_branch (insn, operands,
4355169689Skan					 MIPS_BRANCH ("b%W0", "%Z2%1"),
4356169689Skan					 MIPS_BRANCH ("b%F0", "%Z2%1"));
4357169689Skan}
4358169689Skan  [(set_attr "type" "branch")
4359169689Skan   (set_attr "mode" "none")])
4360169689Skan
4361169689Skan;; Conditional branches on ordered comparisons with zero.
4362169689Skan
4363169689Skan(define_insn "*branch_order<mode>"
4364169689Skan  [(set (pc)
4365169689Skan	(if_then_else
4366169689Skan	 (match_operator 0 "order_operator"
4367169689Skan			 [(match_operand:GPR 2 "register_operand" "d")
4368169689Skan			  (const_int 0)])
4369169689Skan	 (label_ref (match_operand 1 "" ""))
4370169689Skan	 (pc)))]
4371169689Skan  "!TARGET_MIPS16"
4372169689Skan  { return mips_output_order_conditional_branch (insn, operands, false); }
4373169689Skan  [(set_attr "type" "branch")
4374169689Skan   (set_attr "mode" "none")])
4375169689Skan
4376169689Skan(define_insn "*branch_order<mode>_inverted"
4377169689Skan  [(set (pc)
4378169689Skan	(if_then_else
4379169689Skan	 (match_operator 0 "order_operator"
4380169689Skan			 [(match_operand:GPR 2 "register_operand" "d")
4381169689Skan			  (const_int 0)])
4382169689Skan	 (pc)
4383169689Skan	 (label_ref (match_operand 1 "" ""))))]
4384169689Skan  "!TARGET_MIPS16"
4385169689Skan  { return mips_output_order_conditional_branch (insn, operands, true); }
4386169689Skan  [(set_attr "type" "branch")
4387169689Skan   (set_attr "mode" "none")])
4388169689Skan
4389169689Skan;; Conditional branch on equality comparison.
4390169689Skan
4391169689Skan(define_insn "*branch_equality<mode>"
4392169689Skan  [(set (pc)
4393169689Skan	(if_then_else
4394169689Skan	 (match_operator 0 "equality_operator"
4395169689Skan			 [(match_operand:GPR 2 "register_operand" "d")
4396169689Skan			  (match_operand:GPR 3 "reg_or_0_operand" "dJ")])
4397169689Skan	 (label_ref (match_operand 1 "" ""))
4398169689Skan	 (pc)))]
4399169689Skan  "!TARGET_MIPS16"
4400169689Skan{
4401169689Skan  return mips_output_conditional_branch (insn, operands,
4402169689Skan					 MIPS_BRANCH ("b%C0", "%2,%z3,%1"),
4403169689Skan					 MIPS_BRANCH ("b%N0", "%2,%z3,%1"));
4404169689Skan}
4405169689Skan  [(set_attr "type" "branch")
4406169689Skan   (set_attr "mode" "none")])
4407169689Skan
4408169689Skan(define_insn "*branch_equality<mode>_inverted"
4409169689Skan  [(set (pc)
4410169689Skan	(if_then_else
4411169689Skan	 (match_operator 0 "equality_operator"
4412169689Skan			 [(match_operand:GPR 2 "register_operand" "d")
4413169689Skan			  (match_operand:GPR 3 "reg_or_0_operand" "dJ")])
4414169689Skan	 (pc)
4415169689Skan	 (label_ref (match_operand 1 "" ""))))]
4416169689Skan  "!TARGET_MIPS16"
4417169689Skan{
4418169689Skan  return mips_output_conditional_branch (insn, operands,
4419169689Skan					 MIPS_BRANCH ("b%N0", "%2,%z3,%1"),
4420169689Skan					 MIPS_BRANCH ("b%C0", "%2,%z3,%1"));
4421169689Skan}
4422169689Skan  [(set_attr "type" "branch")
4423169689Skan   (set_attr "mode" "none")])
4424169689Skan
4425169689Skan;; MIPS16 branches
4426169689Skan
4427169689Skan(define_insn "*branch_equality<mode>_mips16"
4428169689Skan  [(set (pc)
4429169689Skan	(if_then_else
4430169689Skan	 (match_operator 0 "equality_operator"
4431169689Skan			 [(match_operand:GPR 1 "register_operand" "d,t")
4432169689Skan			  (const_int 0)])
4433169689Skan	 (match_operand 2 "pc_or_label_operand" "")
4434169689Skan	 (match_operand 3 "pc_or_label_operand" "")))]
4435169689Skan  "TARGET_MIPS16"
4436169689Skan{
4437169689Skan  if (operands[2] != pc_rtx)
4438169689Skan    {
4439169689Skan      if (which_alternative == 0)
4440169689Skan	return "b%C0z\t%1,%2";
4441169689Skan      else
4442169689Skan	return "bt%C0z\t%2";
4443169689Skan    }
4444169689Skan  else
4445169689Skan    {
4446169689Skan      if (which_alternative == 0)
4447169689Skan	return "b%N0z\t%1,%3";
4448169689Skan      else
4449169689Skan	return "bt%N0z\t%3";
4450169689Skan    }
4451169689Skan}
4452169689Skan  [(set_attr "type" "branch")
4453169689Skan   (set_attr "mode" "none")
4454169689Skan   (set_attr "length" "8")])
4455169689Skan
4456169689Skan(define_expand "b<code>"
4457169689Skan  [(set (pc)
4458169689Skan	(if_then_else (any_cond:CC (cc0)
4459169689Skan				   (const_int 0))
4460169689Skan		      (label_ref (match_operand 0 ""))
4461169689Skan		      (pc)))]
4462169689Skan  ""
4463169689Skan{
4464169689Skan  gen_conditional_branch (operands, <CODE>);
4465169689Skan  DONE;
4466169689Skan})
4467169689Skan
4468169689Skan;; Used to implement built-in functions.
4469169689Skan(define_expand "condjump"
4470169689Skan  [(set (pc)
4471169689Skan	(if_then_else (match_operand 0)
4472169689Skan		      (label_ref (match_operand 1))
4473169689Skan		      (pc)))])
4474169689Skan
4475169689Skan;;
4476169689Skan;;  ....................
4477169689Skan;;
4478169689Skan;;	SETTING A REGISTER FROM A COMPARISON
4479169689Skan;;
4480169689Skan;;  ....................
4481169689Skan
4482169689Skan(define_expand "seq"
4483169689Skan  [(set (match_operand:SI 0 "register_operand")
4484169689Skan	(eq:SI (match_dup 1)
4485169689Skan	       (match_dup 2)))]
4486169689Skan  ""
4487169689Skan  { if (mips_emit_scc (EQ, operands[0])) DONE; else FAIL; })
4488169689Skan
4489169689Skan(define_insn "*seq_<mode>"
4490169689Skan  [(set (match_operand:GPR 0 "register_operand" "=d")
4491169689Skan	(eq:GPR (match_operand:GPR 1 "register_operand" "d")
4492169689Skan		(const_int 0)))]
4493169689Skan  "!TARGET_MIPS16"
4494169689Skan  "sltu\t%0,%1,1"
4495169689Skan  [(set_attr "type" "slt")
4496169689Skan   (set_attr "mode" "<MODE>")])
4497169689Skan
4498169689Skan(define_insn "*seq_<mode>_mips16"
4499169689Skan  [(set (match_operand:GPR 0 "register_operand" "=t")
4500169689Skan	(eq:GPR (match_operand:GPR 1 "register_operand" "d")
4501169689Skan		(const_int 0)))]
4502169689Skan  "TARGET_MIPS16"
4503169689Skan  "sltu\t%1,1"
4504169689Skan  [(set_attr "type" "slt")
4505169689Skan   (set_attr "mode" "<MODE>")])
4506169689Skan
4507169689Skan;; "sne" uses sltu instructions in which the first operand is $0.
4508169689Skan;; This isn't possible in mips16 code.
4509169689Skan
4510169689Skan(define_expand "sne"
4511169689Skan  [(set (match_operand:SI 0 "register_operand")
4512169689Skan	(ne:SI (match_dup 1)
4513169689Skan	       (match_dup 2)))]
4514169689Skan  "!TARGET_MIPS16"
4515169689Skan  { if (mips_emit_scc (NE, operands[0])) DONE; else FAIL; })
4516169689Skan
4517169689Skan(define_insn "*sne_<mode>"
4518169689Skan  [(set (match_operand:GPR 0 "register_operand" "=d")
4519169689Skan	(ne:GPR (match_operand:GPR 1 "register_operand" "d")
4520169689Skan		(const_int 0)))]
4521169689Skan  "!TARGET_MIPS16"
4522169689Skan  "sltu\t%0,%.,%1"
4523169689Skan  [(set_attr "type" "slt")
4524169689Skan   (set_attr "mode" "<MODE>")])
4525169689Skan
4526169689Skan(define_expand "sgt"
4527169689Skan  [(set (match_operand:SI 0 "register_operand")
4528169689Skan	(gt:SI (match_dup 1)
4529169689Skan	       (match_dup 2)))]
4530169689Skan  ""
4531169689Skan  { if (mips_emit_scc (GT, operands[0])) DONE; else FAIL; })
4532169689Skan
4533169689Skan(define_insn "*sgt_<mode>"
4534169689Skan  [(set (match_operand:GPR 0 "register_operand" "=d")
4535169689Skan	(gt:GPR (match_operand:GPR 1 "register_operand" "d")
4536169689Skan		(match_operand:GPR 2 "reg_or_0_operand" "dJ")))]
4537169689Skan  "!TARGET_MIPS16"
4538169689Skan  "slt\t%0,%z2,%1"
4539169689Skan  [(set_attr "type" "slt")
4540169689Skan   (set_attr "mode" "<MODE>")])
4541169689Skan
4542169689Skan(define_insn "*sgt_<mode>_mips16"
4543169689Skan  [(set (match_operand:GPR 0 "register_operand" "=t")
4544169689Skan	(gt:GPR (match_operand:GPR 1 "register_operand" "d")
4545169689Skan		(match_operand:GPR 2 "register_operand" "d")))]
4546169689Skan  "TARGET_MIPS16"
4547169689Skan  "slt\t%2,%1"
4548169689Skan  [(set_attr "type" "slt")
4549169689Skan   (set_attr "mode" "<MODE>")])
4550169689Skan
4551169689Skan(define_expand "sge"
4552169689Skan  [(set (match_operand:SI 0 "register_operand")
4553169689Skan	(ge:SI (match_dup 1)
4554169689Skan	       (match_dup 2)))]
4555169689Skan  ""
4556169689Skan  { if (mips_emit_scc (GE, operands[0])) DONE; else FAIL; })
4557169689Skan
4558169689Skan(define_insn "*sge_<mode>"
4559169689Skan  [(set (match_operand:GPR 0 "register_operand" "=d")
4560169689Skan	(ge:GPR (match_operand:GPR 1 "register_operand" "d")
4561169689Skan		(const_int 1)))]
4562169689Skan  "!TARGET_MIPS16"
4563169689Skan  "slt\t%0,%.,%1"
4564169689Skan  [(set_attr "type" "slt")
4565169689Skan   (set_attr "mode" "<MODE>")])
4566169689Skan
4567169689Skan(define_expand "slt"
4568169689Skan  [(set (match_operand:SI 0 "register_operand")
4569169689Skan	(lt:SI (match_dup 1)
4570169689Skan	       (match_dup 2)))]
4571169689Skan  ""
4572169689Skan  { if (mips_emit_scc (LT, operands[0])) DONE; else FAIL; })
4573169689Skan
4574169689Skan(define_insn "*slt_<mode>"
4575169689Skan  [(set (match_operand:GPR 0 "register_operand" "=d")
4576169689Skan	(lt:GPR (match_operand:GPR 1 "register_operand" "d")
4577169689Skan		(match_operand:GPR 2 "arith_operand" "dI")))]
4578169689Skan  "!TARGET_MIPS16"
4579169689Skan  "slt\t%0,%1,%2"
4580169689Skan  [(set_attr "type" "slt")
4581169689Skan   (set_attr "mode" "<MODE>")])
4582169689Skan
4583169689Skan(define_insn "*slt_<mode>_mips16"
4584169689Skan  [(set (match_operand:GPR 0 "register_operand" "=t,t")
4585169689Skan	(lt:GPR (match_operand:GPR 1 "register_operand" "d,d")
4586169689Skan		(match_operand:GPR 2 "arith_operand" "d,I")))]
4587169689Skan  "TARGET_MIPS16"
4588169689Skan  "slt\t%1,%2"
4589169689Skan  [(set_attr "type" "slt")
4590169689Skan   (set_attr "mode" "<MODE>")
4591169689Skan   (set_attr_alternative "length"
4592169689Skan		[(const_int 4)
4593169689Skan		 (if_then_else (match_operand 2 "m16_uimm8_1")
4594169689Skan			       (const_int 4)
4595169689Skan			       (const_int 8))])])
4596169689Skan
4597169689Skan(define_expand "sle"
4598169689Skan  [(set (match_operand:SI 0 "register_operand")
4599169689Skan	(le:SI (match_dup 1)
4600169689Skan	       (match_dup 2)))]
4601169689Skan  ""
4602169689Skan  { if (mips_emit_scc (LE, operands[0])) DONE; else FAIL; })
4603169689Skan
4604169689Skan(define_insn "*sle_<mode>"
4605169689Skan  [(set (match_operand:GPR 0 "register_operand" "=d")
4606169689Skan	(le:GPR (match_operand:GPR 1 "register_operand" "d")
4607169689Skan		(match_operand:GPR 2 "sle_operand" "")))]
4608169689Skan  "!TARGET_MIPS16"
4609169689Skan{
4610169689Skan  operands[2] = GEN_INT (INTVAL (operands[2]) + 1);
4611169689Skan  return "slt\t%0,%1,%2";
4612169689Skan}
4613169689Skan  [(set_attr "type" "slt")
4614169689Skan   (set_attr "mode" "<MODE>")])
4615169689Skan
4616169689Skan(define_insn "*sle_<mode>_mips16"
4617169689Skan  [(set (match_operand:GPR 0 "register_operand" "=t")
4618169689Skan	(le:GPR (match_operand:GPR 1 "register_operand" "d")
4619169689Skan		(match_operand:GPR 2 "sle_operand" "")))]
4620169689Skan  "TARGET_MIPS16"
4621169689Skan{
4622169689Skan  operands[2] = GEN_INT (INTVAL (operands[2]) + 1);
4623169689Skan  return "slt\t%1,%2";
4624169689Skan}
4625169689Skan  [(set_attr "type" "slt")
4626169689Skan   (set_attr "mode" "<MODE>")
4627169689Skan   (set (attr "length") (if_then_else (match_operand 2 "m16_uimm8_m1_1")
4628169689Skan				      (const_int 4)
4629169689Skan				      (const_int 8)))])
4630169689Skan
4631169689Skan(define_expand "sgtu"
4632169689Skan  [(set (match_operand:SI 0 "register_operand")
4633169689Skan	(gtu:SI (match_dup 1)
4634169689Skan		(match_dup 2)))]
4635169689Skan  ""
4636169689Skan  { if (mips_emit_scc (GTU, operands[0])) DONE; else FAIL; })
4637169689Skan
4638169689Skan(define_insn "*sgtu_<mode>"
4639169689Skan  [(set (match_operand:GPR 0 "register_operand" "=d")
4640169689Skan	(gtu:GPR (match_operand:GPR 1 "register_operand" "d")
4641169689Skan		 (match_operand:GPR 2 "reg_or_0_operand" "dJ")))]
4642169689Skan  "!TARGET_MIPS16"
4643169689Skan  "sltu\t%0,%z2,%1"
4644169689Skan  [(set_attr "type" "slt")
4645169689Skan   (set_attr "mode" "<MODE>")])
4646169689Skan
4647169689Skan(define_insn "*sgtu_<mode>_mips16"
4648169689Skan  [(set (match_operand:GPR 0 "register_operand" "=t")
4649169689Skan	(gtu:GPR (match_operand:GPR 1 "register_operand" "d")
4650169689Skan		 (match_operand:GPR 2 "register_operand" "d")))]
4651169689Skan  "TARGET_MIPS16"
4652169689Skan  "sltu\t%2,%1"
4653169689Skan  [(set_attr "type" "slt")
4654169689Skan   (set_attr "mode" "<MODE>")])
4655169689Skan
4656169689Skan(define_expand "sgeu"
4657169689Skan  [(set (match_operand:SI 0 "register_operand")
4658169689Skan        (geu:SI (match_dup 1)
4659169689Skan                (match_dup 2)))]
4660169689Skan  ""
4661169689Skan  { if (mips_emit_scc (GEU, operands[0])) DONE; else FAIL; })
4662169689Skan
4663169689Skan(define_insn "*sge_<mode>"
4664169689Skan  [(set (match_operand:GPR 0 "register_operand" "=d")
4665169689Skan	(geu:GPR (match_operand:GPR 1 "register_operand" "d")
4666169689Skan	         (const_int 1)))]
4667169689Skan  "!TARGET_MIPS16"
4668169689Skan  "sltu\t%0,%.,%1"
4669169689Skan  [(set_attr "type" "slt")
4670169689Skan   (set_attr "mode" "<MODE>")])
4671169689Skan
4672169689Skan(define_expand "sltu"
4673169689Skan  [(set (match_operand:SI 0 "register_operand")
4674169689Skan	(ltu:SI (match_dup 1)
4675169689Skan		(match_dup 2)))]
4676169689Skan  ""
4677169689Skan  { if (mips_emit_scc (LTU, operands[0])) DONE; else FAIL; })
4678169689Skan
4679169689Skan(define_insn "*sltu_<mode>"
4680169689Skan  [(set (match_operand:GPR 0 "register_operand" "=d")
4681169689Skan	(ltu:GPR (match_operand:GPR 1 "register_operand" "d")
4682169689Skan		 (match_operand:GPR 2 "arith_operand" "dI")))]
4683169689Skan  "!TARGET_MIPS16"
4684169689Skan  "sltu\t%0,%1,%2"
4685169689Skan  [(set_attr "type" "slt")
4686169689Skan   (set_attr "mode" "<MODE>")])
4687169689Skan
4688169689Skan(define_insn "*sltu_<mode>_mips16"
4689169689Skan  [(set (match_operand:GPR 0 "register_operand" "=t,t")
4690169689Skan	(ltu:GPR (match_operand:GPR 1 "register_operand" "d,d")
4691169689Skan		 (match_operand:GPR 2 "arith_operand" "d,I")))]
4692169689Skan  "TARGET_MIPS16"
4693169689Skan  "sltu\t%1,%2"
4694169689Skan  [(set_attr "type" "slt")
4695169689Skan   (set_attr "mode" "<MODE>")
4696169689Skan   (set_attr_alternative "length"
4697169689Skan		[(const_int 4)
4698169689Skan		 (if_then_else (match_operand 2 "m16_uimm8_1")
4699169689Skan			       (const_int 4)
4700169689Skan			       (const_int 8))])])
4701169689Skan
4702169689Skan(define_expand "sleu"
4703169689Skan  [(set (match_operand:SI 0 "register_operand")
4704169689Skan	(leu:SI (match_dup 1)
4705169689Skan		(match_dup 2)))]
4706169689Skan  ""
4707169689Skan  { if (mips_emit_scc (LEU, operands[0])) DONE; else FAIL; })
4708169689Skan
4709169689Skan(define_insn "*sleu_<mode>"
4710169689Skan  [(set (match_operand:GPR 0 "register_operand" "=d")
4711169689Skan	(leu:GPR (match_operand:GPR 1 "register_operand" "d")
4712169689Skan	         (match_operand:GPR 2 "sleu_operand" "")))]
4713169689Skan  "!TARGET_MIPS16"
4714169689Skan{
4715169689Skan  operands[2] = GEN_INT (INTVAL (operands[2]) + 1);
4716169689Skan  return "sltu\t%0,%1,%2";
4717169689Skan}
4718169689Skan  [(set_attr "type" "slt")
4719169689Skan   (set_attr "mode" "<MODE>")])
4720169689Skan
4721169689Skan(define_insn "*sleu_<mode>_mips16"
4722169689Skan  [(set (match_operand:GPR 0 "register_operand" "=t")
4723169689Skan	(leu:GPR (match_operand:GPR 1 "register_operand" "d")
4724169689Skan	         (match_operand:GPR 2 "sleu_operand" "")))]
4725169689Skan  "TARGET_MIPS16"
4726169689Skan{
4727169689Skan  operands[2] = GEN_INT (INTVAL (operands[2]) + 1);
4728169689Skan  return "sltu\t%1,%2";
4729169689Skan}
4730169689Skan  [(set_attr "type" "slt")
4731169689Skan   (set_attr "mode" "<MODE>")
4732169689Skan   (set (attr "length") (if_then_else (match_operand 2 "m16_uimm8_m1_1")
4733169689Skan				      (const_int 4)
4734169689Skan				      (const_int 8)))])
4735169689Skan
4736169689Skan;;
4737169689Skan;;  ....................
4738169689Skan;;
4739169689Skan;;	FLOATING POINT COMPARISONS
4740169689Skan;;
4741169689Skan;;  ....................
4742169689Skan
4743169689Skan(define_insn "s<code>_<mode>"
4744169689Skan  [(set (match_operand:CC 0 "register_operand" "=z")
4745169689Skan	(fcond:CC (match_operand:SCALARF 1 "register_operand" "f")
4746169689Skan		  (match_operand:SCALARF 2 "register_operand" "f")))]
4747169689Skan  ""
4748169689Skan  "c.<fcond>.<fmt>\t%Z0%1,%2"
4749169689Skan  [(set_attr "type" "fcmp")
4750169689Skan   (set_attr "mode" "FPSW")])
4751169689Skan
4752169689Skan(define_insn "s<code>_<mode>"
4753169689Skan  [(set (match_operand:CC 0 "register_operand" "=z")
4754169689Skan	(swapped_fcond:CC (match_operand:SCALARF 1 "register_operand" "f")
4755169689Skan		          (match_operand:SCALARF 2 "register_operand" "f")))]
4756169689Skan  ""
4757169689Skan  "c.<swapped_fcond>.<fmt>\t%Z0%2,%1"
4758169689Skan  [(set_attr "type" "fcmp")
4759169689Skan   (set_attr "mode" "FPSW")])
4760169689Skan
4761169689Skan;;
4762169689Skan;;  ....................
4763169689Skan;;
4764169689Skan;;	UNCONDITIONAL BRANCHES
4765169689Skan;;
4766169689Skan;;  ....................
4767169689Skan
4768169689Skan;; Unconditional branches.
4769169689Skan
4770169689Skan(define_insn "jump"
4771169689Skan  [(set (pc)
4772169689Skan	(label_ref (match_operand 0 "" "")))]
4773169689Skan  "!TARGET_MIPS16"
4774169689Skan{
4775169689Skan  if (flag_pic)
4776169689Skan    {
4777169689Skan      if (get_attr_length (insn) <= 8)
4778169689Skan	return "%*b\t%l0%/";
4779169689Skan      else
4780169689Skan	{
4781169689Skan	  output_asm_insn (mips_output_load_label (), operands);
4782169689Skan	  return "%*jr\t%@%/%]";
4783169689Skan	}
4784169689Skan    }
4785169689Skan  else
4786169689Skan    return "%*j\t%l0%/";
4787169689Skan}
4788169689Skan  [(set_attr "type"	"jump")
4789169689Skan   (set_attr "mode"	"none")
4790169689Skan   (set (attr "length")
4791169689Skan	;; We can't use `j' when emitting PIC.  Emit a branch if it's
4792169689Skan	;; in range, otherwise load the address of the branch target into
4793169689Skan	;; $at and then jump to it.
4794169689Skan	(if_then_else
4795169689Skan	 (ior (eq (symbol_ref "flag_pic") (const_int 0))
4796169689Skan	      (lt (abs (minus (match_dup 0)
4797169689Skan			      (plus (pc) (const_int 4))))
4798169689Skan		  (const_int 131072)))
4799169689Skan	 (const_int 4) (const_int 16)))])
4800169689Skan
4801169689Skan;; We need a different insn for the mips16, because a mips16 branch
4802169689Skan;; does not have a delay slot.
4803169689Skan
4804169689Skan(define_insn ""
4805169689Skan  [(set (pc)
4806169689Skan	(label_ref (match_operand 0 "" "")))]
4807169689Skan  "TARGET_MIPS16"
4808169689Skan  "b\t%l0"
4809169689Skan  [(set_attr "type"	"branch")
4810169689Skan   (set_attr "mode"	"none")
4811169689Skan   (set_attr "length"	"8")])
4812169689Skan
4813169689Skan(define_expand "indirect_jump"
4814169689Skan  [(set (pc) (match_operand 0 "register_operand"))]
4815169689Skan  ""
4816169689Skan{
4817169689Skan  operands[0] = force_reg (Pmode, operands[0]);
4818169689Skan  if (Pmode == SImode)
4819169689Skan    emit_jump_insn (gen_indirect_jumpsi (operands[0]));
4820169689Skan  else
4821169689Skan    emit_jump_insn (gen_indirect_jumpdi (operands[0]));
4822169689Skan  DONE;
4823169689Skan})
4824169689Skan
4825169689Skan(define_insn "indirect_jump<mode>"
4826169689Skan  [(set (pc) (match_operand:P 0 "register_operand" "d"))]
4827169689Skan  ""
4828169689Skan  "%*j\t%0%/"
4829169689Skan  [(set_attr "type" "jump")
4830169689Skan   (set_attr "mode" "none")])
4831169689Skan
4832169689Skan(define_expand "tablejump"
4833169689Skan  [(set (pc)
4834169689Skan	(match_operand 0 "register_operand"))
4835169689Skan   (use (label_ref (match_operand 1 "")))]
4836169689Skan  ""
4837169689Skan{
4838169689Skan  if (TARGET_MIPS16)
4839169689Skan    operands[0] = expand_binop (Pmode, add_optab,
4840169689Skan				convert_to_mode (Pmode, operands[0], false),
4841169689Skan				gen_rtx_LABEL_REF (Pmode, operands[1]),
4842169689Skan				0, 0, OPTAB_WIDEN);
4843169689Skan  else if (TARGET_GPWORD)
4844169689Skan    operands[0] = expand_binop (Pmode, add_optab, operands[0],
4845169689Skan				pic_offset_table_rtx, 0, 0, OPTAB_WIDEN);
4846169689Skan
4847169689Skan  if (Pmode == SImode)
4848169689Skan    emit_jump_insn (gen_tablejumpsi (operands[0], operands[1]));
4849169689Skan  else
4850169689Skan    emit_jump_insn (gen_tablejumpdi (operands[0], operands[1]));
4851169689Skan  DONE;
4852169689Skan})
4853169689Skan
4854169689Skan(define_insn "tablejump<mode>"
4855169689Skan  [(set (pc)
4856169689Skan	(match_operand:P 0 "register_operand" "d"))
4857169689Skan   (use (label_ref (match_operand 1 "" "")))]
4858169689Skan  ""
4859169689Skan  "%*j\t%0%/"
4860169689Skan  [(set_attr "type" "jump")
4861169689Skan   (set_attr "mode" "none")])
4862169689Skan
4863169689Skan;; For TARGET_ABICALLS, we save the gp in the jmp_buf as well.
4864169689Skan;; While it is possible to either pull it off the stack (in the
4865169689Skan;; o32 case) or recalculate it given t9 and our target label,
4866169689Skan;; it takes 3 or 4 insns to do so.
4867169689Skan
4868169689Skan(define_expand "builtin_setjmp_setup"
4869169689Skan  [(use (match_operand 0 "register_operand"))]
4870169689Skan  "TARGET_ABICALLS"
4871169689Skan{
4872169689Skan  rtx addr;
4873169689Skan
4874169689Skan  addr = plus_constant (operands[0], GET_MODE_SIZE (Pmode) * 3);
4875169689Skan  emit_move_insn (gen_rtx_MEM (Pmode, addr), pic_offset_table_rtx);
4876169689Skan  DONE;
4877169689Skan})
4878169689Skan
4879169689Skan;; Restore the gp that we saved above.  Despite the earlier comment, it seems
4880169689Skan;; that older code did recalculate the gp from $25.  Continue to jump through
4881169689Skan;; $25 for compatibility (we lose nothing by doing so).
4882169689Skan
4883169689Skan(define_expand "builtin_longjmp"
4884169689Skan  [(use (match_operand 0 "register_operand"))]
4885169689Skan  "TARGET_ABICALLS"
4886169689Skan{
4887169689Skan  /* The elements of the buffer are, in order:  */
4888169689Skan  int W = GET_MODE_SIZE (Pmode);
4889169689Skan  rtx fp = gen_rtx_MEM (Pmode, operands[0]);
4890169689Skan  rtx lab = gen_rtx_MEM (Pmode, plus_constant (operands[0], 1*W));
4891169689Skan  rtx stack = gen_rtx_MEM (Pmode, plus_constant (operands[0], 2*W));
4892169689Skan  rtx gpv = gen_rtx_MEM (Pmode, plus_constant (operands[0], 3*W));
4893169689Skan  rtx pv = gen_rtx_REG (Pmode, PIC_FUNCTION_ADDR_REGNUM);
4894169689Skan  /* Use gen_raw_REG to avoid being given pic_offset_table_rtx.
4895169689Skan     The target is bound to be using $28 as the global pointer
4896169689Skan     but the current function might not be.  */
4897169689Skan  rtx gp = gen_raw_REG (Pmode, GLOBAL_POINTER_REGNUM);
4898169689Skan
4899169689Skan  /* This bit is similar to expand_builtin_longjmp except that it
4900169689Skan     restores $gp as well.  */
4901169689Skan  emit_move_insn (hard_frame_pointer_rtx, fp);
4902169689Skan  emit_move_insn (pv, lab);
4903169689Skan  emit_stack_restore (SAVE_NONLOCAL, stack, NULL_RTX);
4904169689Skan  emit_move_insn (gp, gpv);
4905169689Skan  emit_insn (gen_rtx_USE (VOIDmode, hard_frame_pointer_rtx));
4906169689Skan  emit_insn (gen_rtx_USE (VOIDmode, stack_pointer_rtx));
4907169689Skan  emit_insn (gen_rtx_USE (VOIDmode, gp));
4908169689Skan  emit_indirect_jump (pv);
4909169689Skan  DONE;
4910169689Skan})
4911169689Skan
4912169689Skan;;
4913169689Skan;;  ....................
4914169689Skan;;
4915169689Skan;;	Function prologue/epilogue
4916169689Skan;;
4917169689Skan;;  ....................
4918169689Skan;;
4919169689Skan
4920169689Skan(define_expand "prologue"
4921169689Skan  [(const_int 1)]
4922169689Skan  ""
4923169689Skan{
4924169689Skan  mips_expand_prologue ();
4925169689Skan  DONE;
4926169689Skan})
4927169689Skan
4928169689Skan;; Block any insns from being moved before this point, since the
4929169689Skan;; profiling call to mcount can use various registers that aren't
4930169689Skan;; saved or used to pass arguments.
4931169689Skan
4932169689Skan(define_insn "blockage"
4933169689Skan  [(unspec_volatile [(const_int 0)] UNSPEC_BLOCKAGE)]
4934169689Skan  ""
4935169689Skan  ""
4936169689Skan  [(set_attr "type"	"unknown")
4937169689Skan   (set_attr "mode"	"none")
4938169689Skan   (set_attr "length"	"0")])
4939169689Skan
4940169689Skan(define_expand "epilogue"
4941169689Skan  [(const_int 2)]
4942169689Skan  ""
4943169689Skan{
4944169689Skan  mips_expand_epilogue (false);
4945169689Skan  DONE;
4946169689Skan})
4947169689Skan
4948169689Skan(define_expand "sibcall_epilogue"
4949169689Skan  [(const_int 2)]
4950169689Skan  ""
4951169689Skan{
4952169689Skan  mips_expand_epilogue (true);
4953169689Skan  DONE;
4954169689Skan})
4955169689Skan
4956169689Skan;; Trivial return.  Make it look like a normal return insn as that
4957169689Skan;; allows jump optimizations to work better.
4958169689Skan
4959169689Skan(define_insn "return"
4960169689Skan  [(return)]
4961169689Skan  "mips_can_use_return_insn ()"
4962169689Skan  "%*j\t$31%/"
4963169689Skan  [(set_attr "type"	"jump")
4964169689Skan   (set_attr "mode"	"none")])
4965169689Skan
4966169689Skan;; Normal return.
4967169689Skan
4968169689Skan(define_insn "return_internal"
4969169689Skan  [(return)
4970169689Skan   (use (match_operand 0 "pmode_register_operand" ""))]
4971169689Skan  ""
4972169689Skan  "%*j\t%0%/"
4973169689Skan  [(set_attr "type"	"jump")
4974169689Skan   (set_attr "mode"	"none")])
4975169689Skan
4976169689Skan;; This is used in compiling the unwind routines.
4977169689Skan(define_expand "eh_return"
4978169689Skan  [(use (match_operand 0 "general_operand"))]
4979169689Skan  ""
4980169689Skan{
4981169689Skan  enum machine_mode gpr_mode = TARGET_64BIT ? DImode : SImode;
4982169689Skan
4983169689Skan  if (GET_MODE (operands[0]) != gpr_mode)
4984169689Skan    operands[0] = convert_to_mode (gpr_mode, operands[0], 0);
4985169689Skan  if (TARGET_64BIT)
4986169689Skan    emit_insn (gen_eh_set_lr_di (operands[0]));
4987169689Skan  else
4988169689Skan    emit_insn (gen_eh_set_lr_si (operands[0]));
4989169689Skan
4990169689Skan  DONE;
4991169689Skan})
4992169689Skan
4993169689Skan;; Clobber the return address on the stack.  We can't expand this
4994169689Skan;; until we know where it will be put in the stack frame.
4995169689Skan
4996169689Skan(define_insn "eh_set_lr_si"
4997169689Skan  [(unspec [(match_operand:SI 0 "register_operand" "d")] UNSPEC_EH_RETURN)
4998169689Skan   (clobber (match_scratch:SI 1 "=&d"))]
4999169689Skan  "! TARGET_64BIT"
5000169689Skan  "#")
5001169689Skan
5002169689Skan(define_insn "eh_set_lr_di"
5003169689Skan  [(unspec [(match_operand:DI 0 "register_operand" "d")] UNSPEC_EH_RETURN)
5004169689Skan   (clobber (match_scratch:DI 1 "=&d"))]
5005169689Skan  "TARGET_64BIT"
5006169689Skan  "#")
5007169689Skan
5008169689Skan(define_split
5009169689Skan  [(unspec [(match_operand 0 "register_operand")] UNSPEC_EH_RETURN)
5010169689Skan   (clobber (match_scratch 1))]
5011169689Skan  "reload_completed && !TARGET_DEBUG_D_MODE"
5012169689Skan  [(const_int 0)]
5013169689Skan{
5014169689Skan  mips_set_return_address (operands[0], operands[1]);
5015169689Skan  DONE;
5016169689Skan})
5017169689Skan
5018169689Skan(define_insn_and_split "exception_receiver"
5019169689Skan  [(set (reg:SI 28)
5020169689Skan	(unspec_volatile:SI [(const_int 0)] UNSPEC_EH_RECEIVER))]
5021169689Skan  "TARGET_ABICALLS && TARGET_OLDABI"
5022169689Skan  "#"
5023169689Skan  "&& reload_completed"
5024169689Skan  [(const_int 0)]
5025169689Skan{
5026169689Skan  mips_restore_gp ();
5027169689Skan  DONE;
5028169689Skan}
5029169689Skan  [(set_attr "type"   "load")
5030169689Skan   (set_attr "length" "12")])
5031169689Skan
5032169689Skan;;
5033169689Skan;;  ....................
5034169689Skan;;
5035169689Skan;;	FUNCTION CALLS
5036169689Skan;;
5037169689Skan;;  ....................
5038169689Skan
5039169689Skan;; Instructions to load a call address from the GOT.  The address might
5040169689Skan;; point to a function or to a lazy binding stub.  In the latter case,
5041169689Skan;; the stub will use the dynamic linker to resolve the function, which
5042169689Skan;; in turn will change the GOT entry to point to the function's real
5043169689Skan;; address.
5044169689Skan;;
5045169689Skan;; This means that every call, even pure and constant ones, can
5046169689Skan;; potentially modify the GOT entry.  And once a stub has been called,
5047169689Skan;; we must not call it again.
5048169689Skan;;
5049169689Skan;; We represent this restriction using an imaginary fixed register that
5050169689Skan;; acts like a GOT version number.  By making the register call-clobbered,
5051169689Skan;; we tell the target-independent code that the address could be changed
5052169689Skan;; by any call insn.
5053169689Skan(define_insn "load_call<mode>"
5054169689Skan  [(set (match_operand:P 0 "register_operand" "=c")
5055169689Skan	(unspec:P [(match_operand:P 1 "register_operand" "r")
5056169689Skan		   (match_operand:P 2 "immediate_operand" "")
5057169689Skan		   (reg:P FAKE_CALL_REGNO)]
5058169689Skan		  UNSPEC_LOAD_CALL))]
5059169689Skan  "TARGET_ABICALLS"
5060169689Skan  "<load>\t%0,%R2(%1)"
5061169689Skan  [(set_attr "type" "load")
5062169689Skan   (set_attr "mode" "<MODE>")
5063169689Skan   (set_attr "length" "4")])
5064169689Skan
5065169689Skan;; Sibling calls.  All these patterns use jump instructions.
5066169689Skan
5067169689Skan;; If TARGET_SIBCALLS, call_insn_operand will only accept constant
5068169689Skan;; addresses if a direct jump is acceptable.  Since the 'S' constraint
5069169689Skan;; is defined in terms of call_insn_operand, the same is true of the
5070169689Skan;; constraints.
5071169689Skan
5072169689Skan;; When we use an indirect jump, we need a register that will be
5073169689Skan;; preserved by the epilogue.  Since TARGET_ABICALLS forces us to
5074169689Skan;; use $25 for this purpose -- and $25 is never clobbered by the
5075169689Skan;; epilogue -- we might as well use it for !TARGET_ABICALLS as well.
5076169689Skan
5077169689Skan(define_expand "sibcall"
5078169689Skan  [(parallel [(call (match_operand 0 "")
5079169689Skan		    (match_operand 1 ""))
5080169689Skan	      (use (match_operand 2 ""))	;; next_arg_reg
5081169689Skan	      (use (match_operand 3 ""))])]	;; struct_value_size_rtx
5082169689Skan  "TARGET_SIBCALLS"
5083169689Skan{
5084169689Skan  mips_expand_call (0, XEXP (operands[0], 0), operands[1], operands[2], true);
5085169689Skan  DONE;
5086169689Skan})
5087169689Skan
5088169689Skan(define_insn "sibcall_internal"
5089169689Skan  [(call (mem:SI (match_operand 0 "call_insn_operand" "j,S"))
5090169689Skan	 (match_operand 1 "" ""))]
5091169689Skan  "TARGET_SIBCALLS && SIBLING_CALL_P (insn)"
5092169689Skan  { return MIPS_CALL ("j", operands, 0); }
5093169689Skan  [(set_attr "type" "call")])
5094169689Skan
5095169689Skan(define_expand "sibcall_value"
5096169689Skan  [(parallel [(set (match_operand 0 "")
5097169689Skan		   (call (match_operand 1 "")
5098169689Skan			 (match_operand 2 "")))
5099169689Skan	      (use (match_operand 3 ""))])]		;; next_arg_reg
5100169689Skan  "TARGET_SIBCALLS"
5101169689Skan{
5102169689Skan  mips_expand_call (operands[0], XEXP (operands[1], 0),
5103169689Skan		    operands[2], operands[3], true);
5104169689Skan  DONE;
5105169689Skan})
5106169689Skan
5107169689Skan(define_insn "sibcall_value_internal"
5108169689Skan  [(set (match_operand 0 "register_operand" "=df,df")
5109169689Skan        (call (mem:SI (match_operand 1 "call_insn_operand" "j,S"))
5110169689Skan              (match_operand 2 "" "")))]
5111169689Skan  "TARGET_SIBCALLS && SIBLING_CALL_P (insn)"
5112169689Skan  { return MIPS_CALL ("j", operands, 1); }
5113169689Skan  [(set_attr "type" "call")])
5114169689Skan
5115169689Skan(define_insn "sibcall_value_multiple_internal"
5116169689Skan  [(set (match_operand 0 "register_operand" "=df,df")
5117169689Skan        (call (mem:SI (match_operand 1 "call_insn_operand" "j,S"))
5118169689Skan              (match_operand 2 "" "")))
5119169689Skan   (set (match_operand 3 "register_operand" "=df,df")
5120169689Skan	(call (mem:SI (match_dup 1))
5121169689Skan	      (match_dup 2)))]
5122169689Skan  "TARGET_SIBCALLS && SIBLING_CALL_P (insn)"
5123169689Skan  { return MIPS_CALL ("j", operands, 1); }
5124169689Skan  [(set_attr "type" "call")])
5125169689Skan
5126169689Skan(define_expand "call"
5127169689Skan  [(parallel [(call (match_operand 0 "")
5128169689Skan		    (match_operand 1 ""))
5129169689Skan	      (use (match_operand 2 ""))	;; next_arg_reg
5130169689Skan	      (use (match_operand 3 ""))])]	;; struct_value_size_rtx
5131169689Skan  ""
5132169689Skan{
5133169689Skan  mips_expand_call (0, XEXP (operands[0], 0), operands[1], operands[2], false);
5134169689Skan  DONE;
5135169689Skan})
5136169689Skan
5137169689Skan;; This instruction directly corresponds to an assembly-language "jal".
5138169689Skan;; There are four cases:
5139169689Skan;;
5140169689Skan;;    - -mno-abicalls:
5141169689Skan;;	  Both symbolic and register destinations are OK.  The pattern
5142169689Skan;;	  always expands to a single mips instruction.
5143169689Skan;;
5144169689Skan;;    - -mabicalls/-mno-explicit-relocs:
5145169689Skan;;	  Again, both symbolic and register destinations are OK.
5146169689Skan;;	  The call is treated as a multi-instruction black box.
5147169689Skan;;
5148169689Skan;;    - -mabicalls/-mexplicit-relocs with n32 or n64:
5149169689Skan;;	  Only "jal $25" is allowed.  This expands to a single "jalr $25"
5150169689Skan;;	  instruction.
5151169689Skan;;
5152169689Skan;;    - -mabicalls/-mexplicit-relocs with o32 or o64:
5153169689Skan;;	  Only "jal $25" is allowed.  The call is actually two instructions:
5154169689Skan;;	  "jalr $25" followed by an insn to reload $gp.
5155169689Skan;;
5156169689Skan;; In the last case, we can generate the individual instructions with
5157169689Skan;; a define_split.  There are several things to be wary of:
5158169689Skan;;
5159169689Skan;;   - We can't expose the load of $gp before reload.  If we did,
5160169689Skan;;     it might get removed as dead, but reload can introduce new
5161169689Skan;;     uses of $gp by rematerializing constants.
5162169689Skan;;
5163169689Skan;;   - We shouldn't restore $gp after calls that never return.
5164169689Skan;;     It isn't valid to insert instructions between a noreturn
5165169689Skan;;     call and the following barrier.
5166169689Skan;;
5167169689Skan;;   - The splitter deliberately changes the liveness of $gp.  The unsplit
5168169689Skan;;     instruction preserves $gp and so have no effect on its liveness.
5169169689Skan;;     But once we generate the separate insns, it becomes obvious that
5170169689Skan;;     $gp is not live on entry to the call.
5171169689Skan;;
5172169689Skan;; ??? The operands[2] = insn check is a hack to make the original insn
5173169689Skan;; available to the splitter.
5174169689Skan(define_insn_and_split "call_internal"
5175169689Skan  [(call (mem:SI (match_operand 0 "call_insn_operand" "c,S"))
5176169689Skan	 (match_operand 1 "" ""))
5177169689Skan   (clobber (reg:SI 31))]
5178169689Skan  ""
5179169689Skan  { return TARGET_SPLIT_CALLS ? "#" : MIPS_CALL ("jal", operands, 0); }
5180169689Skan  "reload_completed && TARGET_SPLIT_CALLS && (operands[2] = insn)"
5181169689Skan  [(const_int 0)]
5182169689Skan{
5183169689Skan  emit_call_insn (gen_call_split (operands[0], operands[1]));
5184169689Skan  if (!find_reg_note (operands[2], REG_NORETURN, 0))
5185169689Skan    mips_restore_gp ();
5186169689Skan  DONE;
5187169689Skan}
5188169689Skan  [(set_attr "jal" "indirect,direct")
5189169689Skan   (set_attr "extended_mips16" "no,yes")])
5190169689Skan
5191169689Skan(define_insn "call_split"
5192169689Skan  [(call (mem:SI (match_operand 0 "call_insn_operand" "cS"))
5193169689Skan	 (match_operand 1 "" ""))
5194169689Skan   (clobber (reg:SI 31))
5195169689Skan   (clobber (reg:SI 28))]
5196169689Skan  "TARGET_SPLIT_CALLS"
5197169689Skan  { return MIPS_CALL ("jal", operands, 0); }
5198169689Skan  [(set_attr "type" "call")])
5199169689Skan
5200169689Skan(define_expand "call_value"
5201169689Skan  [(parallel [(set (match_operand 0 "")
5202169689Skan		   (call (match_operand 1 "")
5203169689Skan			 (match_operand 2 "")))
5204169689Skan	      (use (match_operand 3 ""))])]		;; next_arg_reg
5205169689Skan  ""
5206169689Skan{
5207169689Skan  mips_expand_call (operands[0], XEXP (operands[1], 0),
5208169689Skan		    operands[2], operands[3], false);
5209169689Skan  DONE;
5210169689Skan})
5211169689Skan
5212169689Skan;; See comment for call_internal.
5213169689Skan(define_insn_and_split "call_value_internal"
5214169689Skan  [(set (match_operand 0 "register_operand" "=df,df")
5215169689Skan        (call (mem:SI (match_operand 1 "call_insn_operand" "c,S"))
5216169689Skan              (match_operand 2 "" "")))
5217169689Skan   (clobber (reg:SI 31))]
5218169689Skan  ""
5219169689Skan  { return TARGET_SPLIT_CALLS ? "#" : MIPS_CALL ("jal", operands, 1); }
5220169689Skan  "reload_completed && TARGET_SPLIT_CALLS && (operands[3] = insn)"
5221169689Skan  [(const_int 0)]
5222169689Skan{
5223169689Skan  emit_call_insn (gen_call_value_split (operands[0], operands[1],
5224169689Skan					operands[2]));
5225169689Skan  if (!find_reg_note (operands[3], REG_NORETURN, 0))
5226169689Skan    mips_restore_gp ();
5227169689Skan  DONE;
5228169689Skan}
5229169689Skan  [(set_attr "jal" "indirect,direct")
5230169689Skan   (set_attr "extended_mips16" "no,yes")])
5231169689Skan
5232169689Skan(define_insn "call_value_split"
5233169689Skan  [(set (match_operand 0 "register_operand" "=df")
5234169689Skan        (call (mem:SI (match_operand 1 "call_insn_operand" "cS"))
5235169689Skan              (match_operand 2 "" "")))
5236169689Skan   (clobber (reg:SI 31))
5237169689Skan   (clobber (reg:SI 28))]
5238169689Skan  "TARGET_SPLIT_CALLS"
5239169689Skan  { return MIPS_CALL ("jal", operands, 1); }
5240169689Skan  [(set_attr "type" "call")])
5241169689Skan
5242169689Skan;; See comment for call_internal.
5243169689Skan(define_insn_and_split "call_value_multiple_internal"
5244169689Skan  [(set (match_operand 0 "register_operand" "=df,df")
5245169689Skan        (call (mem:SI (match_operand 1 "call_insn_operand" "c,S"))
5246169689Skan              (match_operand 2 "" "")))
5247169689Skan   (set (match_operand 3 "register_operand" "=df,df")
5248169689Skan	(call (mem:SI (match_dup 1))
5249169689Skan	      (match_dup 2)))
5250169689Skan   (clobber (reg:SI 31))]
5251169689Skan  ""
5252169689Skan  { return TARGET_SPLIT_CALLS ? "#" : MIPS_CALL ("jal", operands, 1); }
5253169689Skan  "reload_completed && TARGET_SPLIT_CALLS && (operands[4] = insn)"
5254169689Skan  [(const_int 0)]
5255169689Skan{
5256169689Skan  emit_call_insn (gen_call_value_multiple_split (operands[0], operands[1],
5257169689Skan						 operands[2], operands[3]));
5258169689Skan  if (!find_reg_note (operands[4], REG_NORETURN, 0))
5259169689Skan    mips_restore_gp ();
5260169689Skan  DONE;
5261169689Skan}
5262169689Skan  [(set_attr "jal" "indirect,direct")
5263169689Skan   (set_attr "extended_mips16" "no,yes")])
5264169689Skan
5265169689Skan(define_insn "call_value_multiple_split"
5266169689Skan  [(set (match_operand 0 "register_operand" "=df")
5267169689Skan        (call (mem:SI (match_operand 1 "call_insn_operand" "cS"))
5268169689Skan              (match_operand 2 "" "")))
5269169689Skan   (set (match_operand 3 "register_operand" "=df")
5270169689Skan	(call (mem:SI (match_dup 1))
5271169689Skan	      (match_dup 2)))
5272169689Skan   (clobber (reg:SI 31))
5273169689Skan   (clobber (reg:SI 28))]
5274169689Skan  "TARGET_SPLIT_CALLS"
5275169689Skan  { return MIPS_CALL ("jal", operands, 1); }
5276169689Skan  [(set_attr "type" "call")])
5277169689Skan
5278169689Skan;; Call subroutine returning any type.
5279169689Skan
5280169689Skan(define_expand "untyped_call"
5281169689Skan  [(parallel [(call (match_operand 0 "")
5282169689Skan		    (const_int 0))
5283169689Skan	      (match_operand 1 "")
5284169689Skan	      (match_operand 2 "")])]
5285169689Skan  ""
5286169689Skan{
5287169689Skan  int i;
5288169689Skan
5289169689Skan  emit_call_insn (GEN_CALL (operands[0], const0_rtx, NULL, const0_rtx));
5290169689Skan
5291169689Skan  for (i = 0; i < XVECLEN (operands[2], 0); i++)
5292169689Skan    {
5293169689Skan      rtx set = XVECEXP (operands[2], 0, i);
5294169689Skan      emit_move_insn (SET_DEST (set), SET_SRC (set));
5295169689Skan    }
5296169689Skan
5297169689Skan  emit_insn (gen_blockage ());
5298169689Skan  DONE;
5299169689Skan})
5300169689Skan
5301169689Skan;;
5302169689Skan;;  ....................
5303169689Skan;;
5304169689Skan;;	MISC.
5305169689Skan;;
5306169689Skan;;  ....................
5307169689Skan;;
5308169689Skan
5309169689Skan
5310169689Skan(define_insn "prefetch"
5311169689Skan  [(prefetch (match_operand:QI 0 "address_operand" "p")
5312169689Skan	     (match_operand 1 "const_int_operand" "n")
5313169689Skan	     (match_operand 2 "const_int_operand" "n"))]
5314169689Skan  "ISA_HAS_PREFETCH && TARGET_EXPLICIT_RELOCS"
5315169689Skan{
5316169689Skan  operands[1] = mips_prefetch_cookie (operands[1], operands[2]);
5317169689Skan  return "pref\t%1,%a0";
5318169689Skan}
5319169689Skan  [(set_attr "type" "prefetch")])
5320169689Skan
5321169689Skan(define_insn "*prefetch_indexed_<mode>"
5322169689Skan  [(prefetch (plus:P (match_operand:P 0 "register_operand" "d")
5323169689Skan		     (match_operand:P 1 "register_operand" "d"))
5324169689Skan	     (match_operand 2 "const_int_operand" "n")
5325169689Skan	     (match_operand 3 "const_int_operand" "n"))]
5326169689Skan  "ISA_HAS_PREFETCHX && TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT"
5327169689Skan{
5328169689Skan  operands[2] = mips_prefetch_cookie (operands[2], operands[3]);
5329169689Skan  return "prefx\t%2,%1(%0)";
5330169689Skan}
5331169689Skan  [(set_attr "type" "prefetchx")])
5332169689Skan
5333169689Skan(define_insn "nop"
5334169689Skan  [(const_int 0)]
5335169689Skan  ""
5336169689Skan  "%(nop%)"
5337169689Skan  [(set_attr "type"	"nop")
5338169689Skan   (set_attr "mode"	"none")])
5339169689Skan
5340169689Skan;; Like nop, but commented out when outside a .set noreorder block.
5341169689Skan(define_insn "hazard_nop"
5342169689Skan  [(const_int 1)]
5343169689Skan  ""
5344169689Skan  {
5345169689Skan    if (set_noreorder)
5346169689Skan      return "nop";
5347169689Skan    else
5348169689Skan      return "#nop";
5349169689Skan  }
5350169689Skan  [(set_attr "type"	"nop")])
5351169689Skan
5352169689Skan;; MIPS4 Conditional move instructions.
5353169689Skan
5354169689Skan(define_insn "*mov<GPR:mode>_on_<MOVECC:mode>"
5355169689Skan  [(set (match_operand:GPR 0 "register_operand" "=d,d")
5356169689Skan	(if_then_else:GPR
5357169689Skan	 (match_operator:MOVECC 4 "equality_operator"
5358169689Skan		[(match_operand:MOVECC 1 "register_operand" "<MOVECC:reg>,<MOVECC:reg>")
5359169689Skan		 (const_int 0)])
5360169689Skan	 (match_operand:GPR 2 "reg_or_0_operand" "dJ,0")
5361169689Skan	 (match_operand:GPR 3 "reg_or_0_operand" "0,dJ")))]
5362169689Skan  "ISA_HAS_CONDMOVE"
5363169689Skan  "@
5364169689Skan    mov%T4\t%0,%z2,%1
5365169689Skan    mov%t4\t%0,%z3,%1"
5366169689Skan  [(set_attr "type" "condmove")
5367169689Skan   (set_attr "mode" "<GPR:MODE>")])
5368169689Skan
5369169689Skan(define_insn "*mov<SCALARF:mode>_on_<MOVECC:mode>"
5370169689Skan  [(set (match_operand:SCALARF 0 "register_operand" "=f,f")
5371169689Skan	(if_then_else:SCALARF
5372169689Skan	 (match_operator:MOVECC 4 "equality_operator"
5373169689Skan		[(match_operand:MOVECC 1 "register_operand" "<MOVECC:reg>,<MOVECC:reg>")
5374169689Skan		 (const_int 0)])
5375169689Skan	 (match_operand:SCALARF 2 "register_operand" "f,0")
5376169689Skan	 (match_operand:SCALARF 3 "register_operand" "0,f")))]
5377169689Skan  "ISA_HAS_CONDMOVE"
5378169689Skan  "@
5379169689Skan    mov%T4.<fmt>\t%0,%2,%1
5380169689Skan    mov%t4.<fmt>\t%0,%3,%1"
5381169689Skan  [(set_attr "type" "condmove")
5382169689Skan   (set_attr "mode" "<SCALARF:MODE>")])
5383169689Skan
5384169689Skan;; These are the main define_expand's used to make conditional moves.
5385169689Skan
5386169689Skan(define_expand "mov<mode>cc"
5387169689Skan  [(set (match_dup 4) (match_operand 1 "comparison_operator"))
5388169689Skan   (set (match_operand:GPR 0 "register_operand")
5389169689Skan	(if_then_else:GPR (match_dup 5)
5390169689Skan			  (match_operand:GPR 2 "reg_or_0_operand")
5391169689Skan			  (match_operand:GPR 3 "reg_or_0_operand")))]
5392169689Skan  "ISA_HAS_CONDMOVE"
5393169689Skan{
5394169689Skan  gen_conditional_move (operands);
5395169689Skan  DONE;
5396169689Skan})
5397169689Skan
5398169689Skan(define_expand "mov<mode>cc"
5399169689Skan  [(set (match_dup 4) (match_operand 1 "comparison_operator"))
5400169689Skan   (set (match_operand:SCALARF 0 "register_operand")
5401169689Skan	(if_then_else:SCALARF (match_dup 5)
5402169689Skan			      (match_operand:SCALARF 2 "register_operand")
5403169689Skan			      (match_operand:SCALARF 3 "register_operand")))]
5404169689Skan  "ISA_HAS_CONDMOVE"
5405169689Skan{
5406169689Skan  gen_conditional_move (operands);
5407169689Skan  DONE;
5408169689Skan})
5409169689Skan
5410169689Skan;;
5411169689Skan;;  ....................
5412169689Skan;;
5413169689Skan;;	mips16 inline constant tables
5414169689Skan;;
5415169689Skan;;  ....................
5416169689Skan;;
5417169689Skan
5418169689Skan(define_insn "consttable_int"
5419169689Skan  [(unspec_volatile [(match_operand 0 "consttable_operand" "")
5420169689Skan		     (match_operand 1 "const_int_operand" "")]
5421169689Skan		    UNSPEC_CONSTTABLE_INT)]
5422169689Skan  "TARGET_MIPS16"
5423169689Skan{
5424169689Skan  assemble_integer (operands[0], INTVAL (operands[1]),
5425169689Skan		    BITS_PER_UNIT * INTVAL (operands[1]), 1);
5426169689Skan  return "";
5427169689Skan}
5428169689Skan  [(set (attr "length") (symbol_ref "INTVAL (operands[1])"))])
5429169689Skan
5430169689Skan(define_insn "consttable_float"
5431169689Skan  [(unspec_volatile [(match_operand 0 "consttable_operand" "")]
5432169689Skan		    UNSPEC_CONSTTABLE_FLOAT)]
5433169689Skan  "TARGET_MIPS16"
5434169689Skan{
5435169689Skan  REAL_VALUE_TYPE d;
5436169689Skan
5437169689Skan  gcc_assert (GET_CODE (operands[0]) == CONST_DOUBLE);
5438169689Skan  REAL_VALUE_FROM_CONST_DOUBLE (d, operands[0]);
5439169689Skan  assemble_real (d, GET_MODE (operands[0]),
5440169689Skan		 GET_MODE_BITSIZE (GET_MODE (operands[0])));
5441169689Skan  return "";
5442169689Skan}
5443169689Skan  [(set (attr "length")
5444169689Skan	(symbol_ref "GET_MODE_SIZE (GET_MODE (operands[0]))"))])
5445169689Skan
5446169689Skan(define_insn "align"
5447169689Skan  [(unspec_volatile [(match_operand 0 "const_int_operand" "")] UNSPEC_ALIGN)]
5448169689Skan  ""
5449169689Skan  ".align\t%0"
5450169689Skan  [(set (attr "length") (symbol_ref "(1 << INTVAL (operands[0])) - 1"))])
5451169689Skan
5452169689Skan(define_split
5453169689Skan  [(match_operand 0 "small_data_pattern")]
5454169689Skan  "reload_completed"
5455169689Skan  [(match_dup 0)]
5456169689Skan  { operands[0] = mips_rewrite_small_data (operands[0]); })
5457169689Skan
5458169689Skan; Thread-Local Storage
5459169689Skan
5460169689Skan; The TLS base pointer is accessed via "rdhwr $v1, $29".  No current
5461169689Skan; MIPS architecture defines this register, and no current
5462169689Skan; implementation provides it; instead, any OS which supports TLS is
5463169689Skan; expected to trap and emulate this instruction.  rdhwr is part of the
5464169689Skan; MIPS 32r2 specification, but we use it on any architecture because
5465169689Skan; we expect it to be emulated.  Use .set to force the assembler to
5466169689Skan; accept it.
5467169689Skan
5468169689Skan(define_insn "tls_get_tp_<mode>"
5469169689Skan  [(set (match_operand:P 0 "register_operand" "=v")
5470169689Skan	(unspec:P [(const_int 0)]
5471169689Skan		  UNSPEC_TLS_GET_TP))]
5472169689Skan  "HAVE_AS_TLS && !TARGET_MIPS16"
5473169689Skan  ".set\tpush\;.set\tmips32r2\t\;rdhwr\t%0,$29\;.set\tpop"
5474169689Skan  [(set_attr "type" "unknown")
5475169689Skan   ; Since rdhwr always generates a trap for now, putting it in a delay
5476169689Skan   ; slot would make the kernel's emulation of it much slower.
5477169689Skan   (set_attr "can_delay" "no")
5478169689Skan   (set_attr "mode" "<MODE>")])
5479169689Skan
5480169689Skan; The MIPS Paired-Single Floating Point and MIPS-3D Instructions.
5481169689Skan
5482169689Skan(include "mips-ps-3d.md")
5483169689Skan
5484169689Skan; The MIPS DSP Instructions.
5485169689Skan
5486169689Skan(include "mips-dsp.md")
5487