xref: /openbsd/gnu/usr.bin/gcc/gcc/config/sparc/sparc.md (revision 8529ddd3)
1;; Machine description for SPARC chip for GNU C compiler
2;;  Copyright (C) 1987, 1988, 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
3;;  1999, 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
4;;  Contributed by Michael Tiemann (tiemann@cygnus.com)
5;;  64-bit SPARC-V9 support by Michael Tiemann, Jim Wilson, and Doug Evans,
6;;  at Cygnus Support.
7
8;; This file is part of GNU CC.
9
10;; GNU CC is free software; you can redistribute it and/or modify
11;; it under the terms of the GNU General Public License as published by
12;; the Free Software Foundation; either version 2, or (at your option)
13;; any later version.
14
15;; GNU CC is distributed in the hope that it will be useful,
16;; but WITHOUT ANY WARRANTY; without even the implied warranty of
17;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18;; GNU General Public License for more details.
19
20;; You should have received a copy of the GNU General Public License
21;; along with GNU CC; see the file COPYING.  If not, write to
22;; the Free Software Foundation, 59 Temple Place - Suite 330,
23;; Boston, MA 02111-1307, USA.
24
25;;- See file "rtl.def" for documentation on define_insn, match_*, et. al.
26
27(define_constants
28  [(UNSPEC_MOVE_PIC		0)
29   (UNSPEC_UPDATE_RETURN	1)
30   (UNSPEC_GET_PC		2)
31   (UNSPEC_MOVE_PIC_LABEL	5)
32   (UNSPEC_SETH44		6)
33   (UNSPEC_SETM44		7)
34   (UNSPEC_SETHH		9)
35   (UNSPEC_SETLM		10)
36   (UNSPEC_EMB_HISUM		11)
37   (UNSPEC_EMB_TEXTUHI		13)
38   (UNSPEC_EMB_TEXTHI		14)
39   (UNSPEC_EMB_TEXTULO		15)
40   (UNSPEC_EMB_SETHM		18)
41  ])
42
43(define_constants
44  [(UNSPECV_BLOCKAGE		0)
45   (UNSPECV_FLUSHW		1)
46   (UNSPECV_GOTO		2)
47   (UNSPECV_GOTO_V9		3)
48   (UNSPECV_FLUSH		4)
49   (UNSPECV_SETJMP		5)
50  ])
51
52;; The upper 32 fp regs on the v9 can't hold SFmode values.  To deal with this
53;; a second register class, EXTRA_FP_REGS, exists for the v9 chip.  The name
54;; is a bit of a misnomer as it covers all 64 fp regs.  The corresponding
55;; constraint letter is 'e'.  To avoid any confusion, 'e' is used instead of
56;; 'f' for all DF/TFmode values, including those that are specific to the v8.
57
58;; Attribute for cpu type.
59;; These must match the values for enum processor_type in sparc.h.
60(define_attr "cpu"
61  "v7,
62   cypress,
63   v8,
64   supersparc,
65   sparclite,f930,f934,
66   hypersparc,sparclite86x,
67   sparclet,tsc701,
68   v9,
69   ultrasparc,
70   ultrasparc3"
71  (const (symbol_ref "sparc_cpu_attr")))
72
73;; Attribute for the instruction set.
74;; At present we only need to distinguish v9/!v9, but for clarity we
75;; test TARGET_V8 too.
76(define_attr "isa" "v6,v8,v9,sparclet"
77 (const
78  (cond [(symbol_ref "TARGET_V9") (const_string "v9")
79	 (symbol_ref "TARGET_V8") (const_string "v8")
80	 (symbol_ref "TARGET_SPARCLET") (const_string "sparclet")]
81	(const_string "v6"))))
82
83;; Architecture size.
84(define_attr "arch" "arch32bit,arch64bit"
85 (const
86  (cond [(symbol_ref "TARGET_ARCH64") (const_string "arch64bit")]
87	(const_string "arch32bit"))))
88
89;; Insn type.
90
91(define_attr "type"
92  "ialu,compare,shift,
93   load,sload,store,
94   uncond_branch,branch,call,sibcall,call_no_delay_slot,
95   imul,idiv,
96   fpload,fpstore,
97   fp,fpmove,
98   fpcmove,fpcrmove,
99   fpcmp,
100   fpmul,fpdivs,fpdivd,
101   fpsqrts,fpsqrtd,
102   cmove,
103   ialuX,
104   multi,flushw,iflush,trap"
105  (const_string "ialu"))
106
107;; true if branch/call has empty delay slot and will emit a nop in it
108(define_attr "empty_delay_slot" "false,true"
109  (symbol_ref "empty_delay_slot (insn)"))
110
111(define_attr "branch_type" "none,icc,fcc,reg" (const_string "none"))
112
113(define_attr "pic" "false,true"
114  (symbol_ref "flag_pic != 0"))
115
116(define_attr "current_function_calls_alloca" "false,true"
117  (symbol_ref "current_function_calls_alloca != 0"))
118
119(define_attr "flat" "false,true"
120  (symbol_ref "TARGET_FLAT != 0"))
121
122;; Length (in # of insns).
123;; Beware that setting a length greater or equal to 3 for conditional branches
124;; has a side-effect (see output_cbranch and output_v9branch).
125(define_attr "length" ""
126  (cond [(eq_attr "type" "uncond_branch,call,sibcall")
127	   (if_then_else (eq_attr "empty_delay_slot" "true")
128	     (const_int 2)
129	     (const_int 1))
130	 (eq_attr "branch_type" "icc")
131	   (if_then_else (match_operand 0 "noov_compare64_op" "")
132	     (if_then_else (lt (pc) (match_dup 1))
133	       (if_then_else (lt (minus (match_dup 1) (pc)) (const_int 260000))
134		 (if_then_else (eq_attr "empty_delay_slot" "true")
135		   (const_int 2)
136		   (const_int 1))
137		 (if_then_else (eq_attr "empty_delay_slot" "true")
138		   (const_int 4)
139		   (const_int 3)))
140	       (if_then_else (lt (minus (pc) (match_dup 1)) (const_int 260000))
141		 (if_then_else (eq_attr "empty_delay_slot" "true")
142		   (const_int 2)
143		   (const_int 1))
144		 (if_then_else (eq_attr "empty_delay_slot" "true")
145		   (const_int 4)
146		   (const_int 3))))
147	     (if_then_else (eq_attr "empty_delay_slot" "true")
148	       (const_int 2)
149	       (const_int 1)))
150	 (eq_attr "branch_type" "fcc")
151	   (if_then_else (match_operand 0 "fcc0_reg_operand" "")
152	     (if_then_else (eq_attr "empty_delay_slot" "true")
153	       (if_then_else (eq (symbol_ref "TARGET_V9") (const_int 0))
154		 (const_int 3)
155		 (const_int 2))
156	       (if_then_else (eq (symbol_ref "TARGET_V9") (const_int 0))
157		 (const_int 2)
158		 (const_int 1)))
159	     (if_then_else (lt (pc) (match_dup 2))
160	       (if_then_else (lt (minus (match_dup 2) (pc)) (const_int 260000))
161		 (if_then_else (eq_attr "empty_delay_slot" "true")
162		   (const_int 2)
163		   (const_int 1))
164		 (if_then_else (eq_attr "empty_delay_slot" "true")
165		   (const_int 4)
166		   (const_int 3)))
167	       (if_then_else (lt (minus (pc) (match_dup 2)) (const_int 260000))
168		 (if_then_else (eq_attr "empty_delay_slot" "true")
169		   (const_int 2)
170		   (const_int 1))
171		 (if_then_else (eq_attr "empty_delay_slot" "true")
172		   (const_int 4)
173		   (const_int 3)))))
174	 (eq_attr "branch_type" "reg")
175	   (if_then_else (lt (pc) (match_dup 2))
176	     (if_then_else (lt (minus (match_dup 2) (pc)) (const_int 32000))
177	       (if_then_else (eq_attr "empty_delay_slot" "true")
178		 (const_int 2)
179		 (const_int 1))
180	       (if_then_else (eq_attr "empty_delay_slot" "true")
181		 (const_int 4)
182		 (const_int 3)))
183	     (if_then_else (lt (minus (pc) (match_dup 2)) (const_int 32000))
184	       (if_then_else (eq_attr "empty_delay_slot" "true")
185		 (const_int 2)
186		 (const_int 1))
187	       (if_then_else (eq_attr "empty_delay_slot" "true")
188		 (const_int 4)
189		 (const_int 3))))
190	 ] (const_int 1)))
191
192;; FP precision.
193(define_attr "fptype" "single,double" (const_string "single"))
194
195;; UltraSPARC-III integer load type.
196(define_attr "us3load_type" "2cycle,3cycle" (const_string "2cycle"))
197
198(define_asm_attributes
199  [(set_attr "length" "2")
200   (set_attr "type" "multi")])
201
202;; Attributes for instruction and branch scheduling
203
204(define_attr "in_call_delay" "false,true"
205  (cond [(eq_attr "type" "uncond_branch,branch,call,sibcall,call_no_delay_slot,multi")
206	 	(const_string "false")
207	 (eq_attr "type" "load,fpload,store,fpstore")
208	 	(if_then_else (eq_attr "length" "1")
209			      (const_string "true")
210			      (const_string "false"))]
211	(if_then_else (eq_attr "length" "1")
212		      (const_string "true")
213		      (const_string "false"))))
214
215(define_delay (eq_attr "type" "call")
216  [(eq_attr "in_call_delay" "true") (nil) (nil)])
217
218(define_attr "eligible_for_sibcall_delay" "false,true"
219  (symbol_ref "eligible_for_sibcall_delay (insn)"))
220
221(define_delay (eq_attr "type" "sibcall")
222  [(eq_attr "eligible_for_sibcall_delay" "true") (nil) (nil)])
223
224(define_attr "leaf_function" "false,true"
225  (const (symbol_ref "current_function_uses_only_leaf_regs")))
226
227;; ??? Should implement the notion of predelay slots for floating point
228;; branches.  This would allow us to remove the nop always inserted before
229;; a floating point branch.
230
231;; ??? It is OK for fill_simple_delay_slots to put load/store instructions
232;; in a delay slot, but it is not OK for fill_eager_delay_slots to do so.
233;; This is because doing so will add several pipeline stalls to the path
234;; that the load/store did not come from.  Unfortunately, there is no way
235;; to prevent fill_eager_delay_slots from using load/store without completely
236;; disabling them.  For the SPEC benchmark set, this is a serious lose,
237;; because it prevents us from moving back the final store of inner loops.
238
239(define_attr "in_branch_delay" "false,true"
240  (if_then_else (and (eq_attr "type" "!uncond_branch,branch,call,sibcall,call_no_delay_slot,multi")
241		     (eq_attr "length" "1"))
242		(const_string "true")
243		(const_string "false")))
244
245(define_attr "in_uncond_branch_delay" "false,true"
246  (if_then_else (and (eq_attr "type" "!uncond_branch,branch,call,sibcall,call_no_delay_slot,multi")
247		     (eq_attr "length" "1"))
248		(const_string "true")
249		(const_string "false")))
250
251(define_attr "in_annul_branch_delay" "false,true"
252  (if_then_else (and (eq_attr "type" "!uncond_branch,branch,call,sibcall,call_no_delay_slot,multi")
253		     (eq_attr "length" "1"))
254		(const_string "true")
255		(const_string "false")))
256
257(define_delay (eq_attr "type" "branch")
258  [(eq_attr "in_branch_delay" "true")
259   (nil) (eq_attr "in_annul_branch_delay" "true")])
260
261(define_delay (eq_attr "type" "uncond_branch")
262  [(eq_attr "in_uncond_branch_delay" "true")
263   (nil) (nil)])
264
265;; Include SPARC DFA schedulers
266
267(include "cypress.md")
268(include "supersparc.md")
269(include "hypersparc.md")
270(include "sparclet.md")
271(include "ultra1_2.md")
272(include "ultra3.md")
273
274
275;; Compare instructions.
276;; This controls RTL generation and register allocation.
277
278;; We generate RTL for comparisons and branches by having the cmpxx
279;; patterns store away the operands.  Then, the scc and bcc patterns
280;; emit RTL for both the compare and the branch.
281;;
282;; We do this because we want to generate different code for an sne and
283;; seq insn.  In those cases, if the second operand of the compare is not
284;; const0_rtx, we want to compute the xor of the two operands and test
285;; it against zero.
286;;
287;; We start with the DEFINE_EXPANDs, then the DEFINE_INSNs to match
288;; the patterns.  Finally, we have the DEFINE_SPLITs for some of the scc
289;; insns that actually require more than one machine instruction.
290
291;; Put cmpsi first among compare insns so it matches two CONST_INT operands.
292
293(define_expand "cmpsi"
294  [(set (reg:CC 100)
295	(compare:CC (match_operand:SI 0 "compare_operand" "")
296		    (match_operand:SI 1 "arith_operand" "")))]
297  ""
298{
299  if (GET_CODE (operands[0]) == ZERO_EXTRACT && operands[1] != const0_rtx)
300    operands[0] = force_reg (SImode, operands[0]);
301
302  sparc_compare_op0 = operands[0];
303  sparc_compare_op1 = operands[1];
304  DONE;
305})
306
307(define_expand "cmpdi"
308  [(set (reg:CCX 100)
309	(compare:CCX (match_operand:DI 0 "compare_operand" "")
310		     (match_operand:DI 1 "arith_double_operand" "")))]
311  "TARGET_ARCH64"
312{
313  if (GET_CODE (operands[0]) == ZERO_EXTRACT && operands[1] != const0_rtx)
314    operands[0] = force_reg (DImode, operands[0]);
315
316  sparc_compare_op0 = operands[0];
317  sparc_compare_op1 = operands[1];
318  DONE;
319})
320
321(define_expand "cmpsf"
322  ;; The 96 here isn't ever used by anyone.
323  [(set (reg:CCFP 96)
324	(compare:CCFP (match_operand:SF 0 "register_operand" "")
325		      (match_operand:SF 1 "register_operand" "")))]
326  "TARGET_FPU"
327{
328  sparc_compare_op0 = operands[0];
329  sparc_compare_op1 = operands[1];
330  DONE;
331})
332
333(define_expand "cmpdf"
334  ;; The 96 here isn't ever used by anyone.
335  [(set (reg:CCFP 96)
336	(compare:CCFP (match_operand:DF 0 "register_operand" "")
337		      (match_operand:DF 1 "register_operand" "")))]
338  "TARGET_FPU"
339{
340  sparc_compare_op0 = operands[0];
341  sparc_compare_op1 = operands[1];
342  DONE;
343})
344
345(define_expand "cmptf"
346  ;; The 96 here isn't ever used by anyone.
347  [(set (reg:CCFP 96)
348	(compare:CCFP (match_operand:TF 0 "register_operand" "")
349		      (match_operand:TF 1 "register_operand" "")))]
350  "TARGET_FPU"
351{
352  sparc_compare_op0 = operands[0];
353  sparc_compare_op1 = operands[1];
354  DONE;
355})
356
357;; Now the compare DEFINE_INSNs.
358
359(define_insn "*cmpsi_insn"
360  [(set (reg:CC 100)
361	(compare:CC (match_operand:SI 0 "register_operand" "r")
362		    (match_operand:SI 1 "arith_operand" "rI")))]
363  ""
364  "cmp\t%0, %1"
365  [(set_attr "type" "compare")])
366
367(define_insn "*cmpdi_sp64"
368  [(set (reg:CCX 100)
369	(compare:CCX (match_operand:DI 0 "register_operand" "r")
370		     (match_operand:DI 1 "arith_double_operand" "rHI")))]
371  "TARGET_ARCH64"
372  "cmp\t%0, %1"
373  [(set_attr "type" "compare")])
374
375(define_insn "*cmpsf_fpe"
376  [(set (match_operand:CCFPE 0 "fcc_reg_operand" "=c")
377	(compare:CCFPE (match_operand:SF 1 "register_operand" "f")
378		       (match_operand:SF 2 "register_operand" "f")))]
379  "TARGET_FPU"
380{
381  if (TARGET_V9)
382    return "fcmpes\t%0, %1, %2";
383  return "fcmpes\t%1, %2";
384}
385  [(set_attr "type" "fpcmp")])
386
387(define_insn "*cmpdf_fpe"
388  [(set (match_operand:CCFPE 0 "fcc_reg_operand" "=c")
389	(compare:CCFPE (match_operand:DF 1 "register_operand" "e")
390		       (match_operand:DF 2 "register_operand" "e")))]
391  "TARGET_FPU"
392{
393  if (TARGET_V9)
394    return "fcmped\t%0, %1, %2";
395  return "fcmped\t%1, %2";
396}
397  [(set_attr "type" "fpcmp")
398   (set_attr "fptype" "double")])
399
400(define_insn "*cmptf_fpe"
401  [(set (match_operand:CCFPE 0 "fcc_reg_operand" "=c")
402	(compare:CCFPE (match_operand:TF 1 "register_operand" "e")
403		       (match_operand:TF 2 "register_operand" "e")))]
404  "TARGET_FPU && TARGET_HARD_QUAD"
405{
406  if (TARGET_V9)
407    return "fcmpeq\t%0, %1, %2";
408  return "fcmpeq\t%1, %2";
409}
410  [(set_attr "type" "fpcmp")])
411
412(define_insn "*cmpsf_fp"
413  [(set (match_operand:CCFP 0 "fcc_reg_operand" "=c")
414	(compare:CCFP (match_operand:SF 1 "register_operand" "f")
415		      (match_operand:SF 2 "register_operand" "f")))]
416  "TARGET_FPU"
417{
418  if (TARGET_V9)
419    return "fcmps\t%0, %1, %2";
420  return "fcmps\t%1, %2";
421}
422  [(set_attr "type" "fpcmp")])
423
424(define_insn "*cmpdf_fp"
425  [(set (match_operand:CCFP 0 "fcc_reg_operand" "=c")
426	(compare:CCFP (match_operand:DF 1 "register_operand" "e")
427		      (match_operand:DF 2 "register_operand" "e")))]
428  "TARGET_FPU"
429{
430  if (TARGET_V9)
431    return "fcmpd\t%0, %1, %2";
432  return "fcmpd\t%1, %2";
433}
434  [(set_attr "type" "fpcmp")
435   (set_attr "fptype" "double")])
436
437(define_insn "*cmptf_fp"
438  [(set (match_operand:CCFP 0 "fcc_reg_operand" "=c")
439	(compare:CCFP (match_operand:TF 1 "register_operand" "e")
440		      (match_operand:TF 2 "register_operand" "e")))]
441  "TARGET_FPU && TARGET_HARD_QUAD"
442{
443  if (TARGET_V9)
444    return "fcmpq\t%0, %1, %2";
445  return "fcmpq\t%1, %2";
446}
447  [(set_attr "type" "fpcmp")])
448
449;; Next come the scc insns.  For seq, sne, sgeu, and sltu, we can do this
450;; without jumps using the addx/subx instructions.  For seq/sne on v9 we use
451;; the same code as v8 (the addx/subx method has more applications).  The
452;; exception to this is "reg != 0" which can be done in one instruction on v9
453;; (so we do it).  For the rest, on v9 we use conditional moves; on v8, we do
454;; branches.
455
456;; Seq_special[_xxx] and sne_special[_xxx] clobber the CC reg, because they
457;; generate addcc/subcc instructions.
458
459(define_expand "seqsi_special"
460  [(set (match_dup 3)
461	(xor:SI (match_operand:SI 1 "register_operand" "")
462		(match_operand:SI 2 "register_operand" "")))
463   (parallel [(set (match_operand:SI 0 "register_operand" "")
464		   (eq:SI (match_dup 3) (const_int 0)))
465	      (clobber (reg:CC 100))])]
466  ""
467  { operands[3] = gen_reg_rtx (SImode); })
468
469(define_expand "seqdi_special"
470  [(set (match_dup 3)
471	(xor:DI (match_operand:DI 1 "register_operand" "")
472		(match_operand:DI 2 "register_operand" "")))
473   (set (match_operand:DI 0 "register_operand" "")
474	(eq:DI (match_dup 3) (const_int 0)))]
475  "TARGET_ARCH64"
476  { operands[3] = gen_reg_rtx (DImode); })
477
478(define_expand "snesi_special"
479  [(set (match_dup 3)
480	(xor:SI (match_operand:SI 1 "register_operand" "")
481		(match_operand:SI 2 "register_operand" "")))
482   (parallel [(set (match_operand:SI 0 "register_operand" "")
483		   (ne:SI (match_dup 3) (const_int 0)))
484	      (clobber (reg:CC 100))])]
485  ""
486  { operands[3] = gen_reg_rtx (SImode); })
487
488(define_expand "snedi_special"
489  [(set (match_dup 3)
490	(xor:DI (match_operand:DI 1 "register_operand" "")
491		(match_operand:DI 2 "register_operand" "")))
492   (set (match_operand:DI 0 "register_operand" "")
493	(ne:DI (match_dup 3) (const_int 0)))]
494  "TARGET_ARCH64"
495  { operands[3] = gen_reg_rtx (DImode); })
496
497(define_expand "seqdi_special_trunc"
498  [(set (match_dup 3)
499	(xor:DI (match_operand:DI 1 "register_operand" "")
500		(match_operand:DI 2 "register_operand" "")))
501   (set (match_operand:SI 0 "register_operand" "")
502	(eq:SI (match_dup 3) (const_int 0)))]
503  "TARGET_ARCH64"
504  { operands[3] = gen_reg_rtx (DImode); })
505
506(define_expand "snedi_special_trunc"
507  [(set (match_dup 3)
508	(xor:DI (match_operand:DI 1 "register_operand" "")
509		(match_operand:DI 2 "register_operand" "")))
510   (set (match_operand:SI 0 "register_operand" "")
511	(ne:SI (match_dup 3) (const_int 0)))]
512  "TARGET_ARCH64"
513  { operands[3] = gen_reg_rtx (DImode); })
514
515(define_expand "seqsi_special_extend"
516  [(set (match_dup 3)
517	(xor:SI (match_operand:SI 1 "register_operand" "")
518		(match_operand:SI 2 "register_operand" "")))
519   (parallel [(set (match_operand:DI 0 "register_operand" "")
520		   (eq:DI (match_dup 3) (const_int 0)))
521	      (clobber (reg:CC 100))])]
522  "TARGET_ARCH64"
523  { operands[3] = gen_reg_rtx (SImode); })
524
525(define_expand "snesi_special_extend"
526  [(set (match_dup 3)
527	(xor:SI (match_operand:SI 1 "register_operand" "")
528		(match_operand:SI 2 "register_operand" "")))
529   (parallel [(set (match_operand:DI 0 "register_operand" "")
530		   (ne:DI (match_dup 3) (const_int 0)))
531	      (clobber (reg:CC 100))])]
532  "TARGET_ARCH64"
533  { operands[3] = gen_reg_rtx (SImode); })
534
535;; ??? v9: Operand 0 needs a mode, so SImode was chosen.
536;; However, the code handles both SImode and DImode.
537(define_expand "seq"
538  [(set (match_operand:SI 0 "intreg_operand" "")
539	(eq:SI (match_dup 1) (const_int 0)))]
540  ""
541{
542  if (GET_MODE (sparc_compare_op0) == SImode)
543    {
544      rtx pat;
545
546      if (GET_MODE (operands[0]) == SImode)
547	pat = gen_seqsi_special (operands[0], sparc_compare_op0,
548				 sparc_compare_op1);
549      else if (! TARGET_ARCH64)
550	FAIL;
551      else
552	pat = gen_seqsi_special_extend (operands[0], sparc_compare_op0,
553					sparc_compare_op1);
554      emit_insn (pat);
555      DONE;
556    }
557  else if (GET_MODE (sparc_compare_op0) == DImode)
558    {
559      rtx pat;
560
561      if (! TARGET_ARCH64)
562	FAIL;
563      else if (GET_MODE (operands[0]) == SImode)
564	pat = gen_seqdi_special_trunc (operands[0], sparc_compare_op0,
565				       sparc_compare_op1);
566      else
567	pat = gen_seqdi_special (operands[0], sparc_compare_op0,
568				 sparc_compare_op1);
569      emit_insn (pat);
570      DONE;
571    }
572  else if (GET_MODE (sparc_compare_op0) == TFmode && ! TARGET_HARD_QUAD)
573    {
574      sparc_emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, EQ);
575      emit_jump_insn (gen_sne (operands[0]));
576      DONE;
577    }
578  else if (TARGET_V9)
579    {
580      if (gen_v9_scc (EQ, operands))
581	DONE;
582      /* fall through */
583    }
584  FAIL;
585})
586
587;; ??? v9: Operand 0 needs a mode, so SImode was chosen.
588;; However, the code handles both SImode and DImode.
589(define_expand "sne"
590  [(set (match_operand:SI 0 "intreg_operand" "")
591	(ne:SI (match_dup 1) (const_int 0)))]
592  ""
593{
594  if (GET_MODE (sparc_compare_op0) == SImode)
595    {
596      rtx pat;
597
598      if (GET_MODE (operands[0]) == SImode)
599	pat = gen_snesi_special (operands[0], sparc_compare_op0,
600				 sparc_compare_op1);
601      else if (! TARGET_ARCH64)
602	FAIL;
603      else
604	pat = gen_snesi_special_extend (operands[0], sparc_compare_op0,
605					sparc_compare_op1);
606      emit_insn (pat);
607      DONE;
608    }
609  else if (GET_MODE (sparc_compare_op0) == DImode)
610    {
611      rtx pat;
612
613      if (! TARGET_ARCH64)
614	FAIL;
615      else if (GET_MODE (operands[0]) == SImode)
616	pat = gen_snedi_special_trunc (operands[0], sparc_compare_op0,
617				       sparc_compare_op1);
618      else
619	pat = gen_snedi_special (operands[0], sparc_compare_op0,
620				 sparc_compare_op1);
621      emit_insn (pat);
622      DONE;
623    }
624  else if (GET_MODE (sparc_compare_op0) == TFmode && ! TARGET_HARD_QUAD)
625    {
626      sparc_emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, NE);
627      emit_jump_insn (gen_sne (operands[0]));
628      DONE;
629    }
630  else if (TARGET_V9)
631    {
632      if (gen_v9_scc (NE, operands))
633	DONE;
634      /* fall through */
635    }
636  FAIL;
637})
638
639(define_expand "sgt"
640  [(set (match_operand:SI 0 "intreg_operand" "")
641	(gt:SI (match_dup 1) (const_int 0)))]
642  ""
643{
644  if (GET_MODE (sparc_compare_op0) == TFmode && ! TARGET_HARD_QUAD)
645    {
646      sparc_emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, GT);
647      emit_jump_insn (gen_sne (operands[0]));
648      DONE;
649    }
650  else if (TARGET_V9)
651    {
652      if (gen_v9_scc (GT, operands))
653	DONE;
654      /* fall through */
655    }
656  FAIL;
657})
658
659(define_expand "slt"
660  [(set (match_operand:SI 0 "intreg_operand" "")
661	(lt:SI (match_dup 1) (const_int 0)))]
662  ""
663{
664  if (GET_MODE (sparc_compare_op0) == TFmode && ! TARGET_HARD_QUAD)
665    {
666      sparc_emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, LT);
667      emit_jump_insn (gen_sne (operands[0]));
668      DONE;
669    }
670  else if (TARGET_V9)
671    {
672      if (gen_v9_scc (LT, operands))
673	DONE;
674      /* fall through */
675    }
676  FAIL;
677})
678
679(define_expand "sge"
680  [(set (match_operand:SI 0 "intreg_operand" "")
681	(ge:SI (match_dup 1) (const_int 0)))]
682  ""
683{
684  if (GET_MODE (sparc_compare_op0) == TFmode && ! TARGET_HARD_QUAD)
685    {
686      sparc_emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, GE);
687      emit_jump_insn (gen_sne (operands[0]));
688      DONE;
689    }
690  else if (TARGET_V9)
691    {
692      if (gen_v9_scc (GE, operands))
693	DONE;
694      /* fall through */
695    }
696  FAIL;
697})
698
699(define_expand "sle"
700  [(set (match_operand:SI 0 "intreg_operand" "")
701	(le:SI (match_dup 1) (const_int 0)))]
702  ""
703{
704  if (GET_MODE (sparc_compare_op0) == TFmode && ! TARGET_HARD_QUAD)
705    {
706      sparc_emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, LE);
707      emit_jump_insn (gen_sne (operands[0]));
708      DONE;
709    }
710  else if (TARGET_V9)
711    {
712      if (gen_v9_scc (LE, operands))
713	DONE;
714      /* fall through */
715    }
716  FAIL;
717})
718
719(define_expand "sgtu"
720  [(set (match_operand:SI 0 "intreg_operand" "")
721	(gtu:SI (match_dup 1) (const_int 0)))]
722  ""
723{
724  if (! TARGET_V9)
725    {
726      rtx tem, pat;
727
728      /* We can do ltu easily, so if both operands are registers, swap them and
729	 do a LTU.  */
730      if ((GET_CODE (sparc_compare_op0) == REG
731	   || GET_CODE (sparc_compare_op0) == SUBREG)
732	  && (GET_CODE (sparc_compare_op1) == REG
733	      || GET_CODE (sparc_compare_op1) == SUBREG))
734	{
735	  tem = sparc_compare_op0;
736	  sparc_compare_op0 = sparc_compare_op1;
737	  sparc_compare_op1 = tem;
738	  pat = gen_sltu (operands[0]);
739          if (pat == NULL_RTX)
740            FAIL;
741          emit_insn (pat);
742	  DONE;
743	}
744    }
745  else
746    {
747      if (gen_v9_scc (GTU, operands))
748	DONE;
749    }
750  FAIL;
751})
752
753(define_expand "sltu"
754  [(set (match_operand:SI 0 "intreg_operand" "")
755	(ltu:SI (match_dup 1) (const_int 0)))]
756  ""
757{
758  if (TARGET_V9)
759    {
760      if (gen_v9_scc (LTU, operands))
761	DONE;
762    }
763  operands[1] = gen_compare_reg (LTU, sparc_compare_op0, sparc_compare_op1);
764})
765
766(define_expand "sgeu"
767  [(set (match_operand:SI 0 "intreg_operand" "")
768	(geu:SI (match_dup 1) (const_int 0)))]
769  ""
770{
771  if (TARGET_V9)
772    {
773      if (gen_v9_scc (GEU, operands))
774	DONE;
775    }
776  operands[1] = gen_compare_reg (GEU, sparc_compare_op0, sparc_compare_op1);
777})
778
779(define_expand "sleu"
780  [(set (match_operand:SI 0 "intreg_operand" "")
781	(leu:SI (match_dup 1) (const_int 0)))]
782  ""
783{
784  if (! TARGET_V9)
785    {
786      rtx tem, pat;
787
788      /* We can do geu easily, so if both operands are registers, swap them and
789	 do a GEU.  */
790      if ((GET_CODE (sparc_compare_op0) == REG
791	   || GET_CODE (sparc_compare_op0) == SUBREG)
792	  && (GET_CODE (sparc_compare_op1) == REG
793	      || GET_CODE (sparc_compare_op1) == SUBREG))
794	{
795	  tem = sparc_compare_op0;
796	  sparc_compare_op0 = sparc_compare_op1;
797	  sparc_compare_op1 = tem;
798	  pat = gen_sgeu (operands[0]);
799          if (pat == NULL_RTX)
800            FAIL;
801          emit_insn (pat);
802	  DONE;
803	}
804    }
805  else
806    {
807      if (gen_v9_scc (LEU, operands))
808	DONE;
809    }
810  FAIL;
811})
812
813;; Now the DEFINE_INSNs for the scc cases.
814
815;; The SEQ and SNE patterns are special because they can be done
816;; without any branching and do not involve a COMPARE.  We want
817;; them to always use the splitz below so the results can be
818;; scheduled.
819
820(define_insn_and_split "*snesi_zero"
821  [(set (match_operand:SI 0 "register_operand" "=r")
822	(ne:SI (match_operand:SI 1 "register_operand" "r")
823	       (const_int 0)))
824   (clobber (reg:CC 100))]
825  ""
826  "#"
827  ""
828  [(set (reg:CC_NOOV 100) (compare:CC_NOOV (neg:SI (match_dup 1))
829					   (const_int 0)))
830   (set (match_dup 0) (ltu:SI (reg:CC 100) (const_int 0)))]
831  ""
832  [(set_attr "length" "2")])
833
834(define_insn_and_split "*neg_snesi_zero"
835  [(set (match_operand:SI 0 "register_operand" "=r")
836	(neg:SI (ne:SI (match_operand:SI 1 "register_operand" "r")
837		       (const_int 0))))
838   (clobber (reg:CC 100))]
839  ""
840  "#"
841  ""
842  [(set (reg:CC_NOOV 100) (compare:CC_NOOV (neg:SI (match_dup 1))
843					   (const_int 0)))
844   (set (match_dup 0) (neg:SI (ltu:SI (reg:CC 100) (const_int 0))))]
845  ""
846  [(set_attr "length" "2")])
847
848(define_insn_and_split "*snesi_zero_extend"
849  [(set (match_operand:DI 0 "register_operand" "=r")
850        (ne:DI (match_operand:SI 1 "register_operand" "r")
851               (const_int 0)))
852   (clobber (reg:CC 100))]
853  "TARGET_ARCH64"
854  "#"
855  "&& 1"
856  [(set (reg:CC_NOOV 100) (compare:CC_NOOV (minus:SI (const_int 0)
857                                                     (match_dup 1))
858                                           (const_int 0)))
859   (set (match_dup 0) (zero_extend:DI (plus:SI (plus:SI (const_int 0)
860                                                        (const_int 0))
861                                               (ltu:SI (reg:CC_NOOV 100)
862                                                       (const_int 0)))))]
863  ""
864  [(set_attr "length" "2")])
865
866(define_insn_and_split "*snedi_zero"
867  [(set (match_operand:DI 0 "register_operand" "=&r")
868        (ne:DI (match_operand:DI 1 "register_operand" "r")
869               (const_int 0)))]
870  "TARGET_ARCH64"
871  "#"
872  "&& ! reg_overlap_mentioned_p (operands[1], operands[0])"
873  [(set (match_dup 0) (const_int 0))
874   (set (match_dup 0) (if_then_else:DI (ne:DI (match_dup 1)
875                                              (const_int 0))
876                                       (const_int 1)
877                                       (match_dup 0)))]
878  ""
879  [(set_attr "length" "2")])
880
881(define_insn_and_split "*neg_snedi_zero"
882  [(set (match_operand:DI 0 "register_operand" "=&r")
883        (neg:DI (ne:DI (match_operand:DI 1 "register_operand" "r")
884                       (const_int 0))))]
885  "TARGET_ARCH64"
886  "#"
887  "&& ! reg_overlap_mentioned_p (operands[1], operands[0])"
888  [(set (match_dup 0) (const_int 0))
889   (set (match_dup 0) (if_then_else:DI (ne:DI (match_dup 1)
890                                              (const_int 0))
891                                       (const_int -1)
892                                       (match_dup 0)))]
893  ""
894  [(set_attr "length" "2")])
895
896(define_insn_and_split "*snedi_zero_trunc"
897  [(set (match_operand:SI 0 "register_operand" "=&r")
898        (ne:SI (match_operand:DI 1 "register_operand" "r")
899               (const_int 0)))]
900  "TARGET_ARCH64"
901  "#"
902  "&& ! reg_overlap_mentioned_p (operands[1], operands[0])"
903  [(set (match_dup 0) (const_int 0))
904   (set (match_dup 0) (if_then_else:SI (ne:DI (match_dup 1)
905                                              (const_int 0))
906                                       (const_int 1)
907                                       (match_dup 0)))]
908  ""
909  [(set_attr "length" "2")])
910
911(define_insn_and_split "*seqsi_zero"
912  [(set (match_operand:SI 0 "register_operand" "=r")
913	(eq:SI (match_operand:SI 1 "register_operand" "r")
914	       (const_int 0)))
915   (clobber (reg:CC 100))]
916  ""
917  "#"
918  ""
919  [(set (reg:CC_NOOV 100) (compare:CC_NOOV (neg:SI (match_dup 1))
920					   (const_int 0)))
921   (set (match_dup 0) (geu:SI (reg:CC 100) (const_int 0)))]
922  ""
923  [(set_attr "length" "2")])
924
925(define_insn_and_split "*neg_seqsi_zero"
926  [(set (match_operand:SI 0 "register_operand" "=r")
927	(neg:SI (eq:SI (match_operand:SI 1 "register_operand" "r")
928		       (const_int 0))))
929   (clobber (reg:CC 100))]
930  ""
931  "#"
932  ""
933  [(set (reg:CC_NOOV 100) (compare:CC_NOOV (neg:SI (match_dup 1))
934					   (const_int 0)))
935   (set (match_dup 0) (neg:SI (geu:SI (reg:CC 100) (const_int 0))))]
936  ""
937  [(set_attr "length" "2")])
938
939(define_insn_and_split "*seqsi_zero_extend"
940  [(set (match_operand:DI 0 "register_operand" "=r")
941        (eq:DI (match_operand:SI 1 "register_operand" "r")
942               (const_int 0)))
943   (clobber (reg:CC 100))]
944  "TARGET_ARCH64"
945  "#"
946  "&& 1"
947  [(set (reg:CC_NOOV 100) (compare:CC_NOOV (minus:SI (const_int 0)
948                                                     (match_dup 1))
949                                           (const_int 0)))
950   (set (match_dup 0) (zero_extend:DI (minus:SI (minus:SI (const_int 0)
951                                                          (const_int -1))
952                                                (ltu:SI (reg:CC_NOOV 100)
953                                                        (const_int 0)))))]
954  ""
955  [(set_attr "length" "2")])
956
957(define_insn_and_split "*seqdi_zero"
958  [(set (match_operand:DI 0 "register_operand" "=&r")
959        (eq:DI (match_operand:DI 1 "register_operand" "r")
960               (const_int 0)))]
961  "TARGET_ARCH64"
962  "#"
963  "&& ! reg_overlap_mentioned_p (operands[1], operands[0])"
964  [(set (match_dup 0) (const_int 0))
965   (set (match_dup 0) (if_then_else:DI (eq:DI (match_dup 1)
966                                              (const_int 0))
967                                       (const_int 1)
968                                       (match_dup 0)))]
969  ""
970  [(set_attr "length" "2")])
971
972(define_insn_and_split "*neg_seqdi_zero"
973  [(set (match_operand:DI 0 "register_operand" "=&r")
974        (neg:DI (eq:DI (match_operand:DI 1 "register_operand" "r")
975                       (const_int 0))))]
976  "TARGET_ARCH64"
977  "#"
978  "&& ! reg_overlap_mentioned_p (operands[1], operands[0])"
979  [(set (match_dup 0) (const_int 0))
980   (set (match_dup 0) (if_then_else:DI (eq:DI (match_dup 1)
981                                              (const_int 0))
982                                       (const_int -1)
983                                       (match_dup 0)))]
984  ""
985  [(set_attr "length" "2")])
986
987(define_insn_and_split "*seqdi_zero_trunc"
988  [(set (match_operand:SI 0 "register_operand" "=&r")
989        (eq:SI (match_operand:DI 1 "register_operand" "r")
990               (const_int 0)))]
991  "TARGET_ARCH64"
992  "#"
993  "&& ! reg_overlap_mentioned_p (operands[1], operands[0])"
994  [(set (match_dup 0) (const_int 0))
995   (set (match_dup 0) (if_then_else:SI (eq:DI (match_dup 1)
996                                              (const_int 0))
997                                       (const_int 1)
998                                       (match_dup 0)))]
999  ""
1000  [(set_attr "length" "2")])
1001
1002;; We can also do (x + (i == 0)) and related, so put them in.
1003;; ??? The addx/subx insns use the 32 bit carry flag so there are no DImode
1004;; versions for v9.
1005
1006(define_insn_and_split "*x_plus_i_ne_0"
1007  [(set (match_operand:SI 0 "register_operand" "=r")
1008	(plus:SI (ne:SI (match_operand:SI 1 "register_operand" "r")
1009			(const_int 0))
1010		 (match_operand:SI 2 "register_operand" "r")))
1011   (clobber (reg:CC 100))]
1012  ""
1013  "#"
1014  ""
1015  [(set (reg:CC_NOOV 100) (compare:CC_NOOV (neg:SI (match_dup 1))
1016					   (const_int 0)))
1017   (set (match_dup 0) (plus:SI (ltu:SI (reg:CC 100) (const_int 0))
1018			       (match_dup 2)))]
1019  ""
1020  [(set_attr "length" "2")])
1021
1022(define_insn_and_split "*x_minus_i_ne_0"
1023  [(set (match_operand:SI 0 "register_operand" "=r")
1024	(minus:SI (match_operand:SI 2 "register_operand" "r")
1025		  (ne:SI (match_operand:SI 1 "register_operand" "r")
1026			 (const_int 0))))
1027   (clobber (reg:CC 100))]
1028  ""
1029  "#"
1030  ""
1031  [(set (reg:CC_NOOV 100) (compare:CC_NOOV (neg:SI (match_dup 1))
1032					   (const_int 0)))
1033   (set (match_dup 0) (minus:SI (match_dup 2)
1034				(ltu:SI (reg:CC 100) (const_int 0))))]
1035  ""
1036  [(set_attr "length" "2")])
1037
1038(define_insn_and_split "*x_plus_i_eq_0"
1039  [(set (match_operand:SI 0 "register_operand" "=r")
1040	(plus:SI (eq:SI (match_operand:SI 1 "register_operand" "r")
1041			(const_int 0))
1042		 (match_operand:SI 2 "register_operand" "r")))
1043   (clobber (reg:CC 100))]
1044  ""
1045  "#"
1046  ""
1047  [(set (reg:CC_NOOV 100) (compare:CC_NOOV (neg:SI (match_dup 1))
1048					   (const_int 0)))
1049   (set (match_dup 0) (plus:SI (geu:SI (reg:CC 100) (const_int 0))
1050			       (match_dup 2)))]
1051  ""
1052  [(set_attr "length" "2")])
1053
1054(define_insn_and_split "*x_minus_i_eq_0"
1055  [(set (match_operand:SI 0 "register_operand" "=r")
1056	(minus:SI (match_operand:SI 2 "register_operand" "r")
1057		  (eq:SI (match_operand:SI 1 "register_operand" "r")
1058			 (const_int 0))))
1059   (clobber (reg:CC 100))]
1060  ""
1061  "#"
1062  ""
1063  [(set (reg:CC_NOOV 100) (compare:CC_NOOV (neg:SI (match_dup 1))
1064					   (const_int 0)))
1065   (set (match_dup 0) (minus:SI (match_dup 2)
1066				(geu:SI (reg:CC 100) (const_int 0))))]
1067  ""
1068  [(set_attr "length" "2")])
1069
1070;; We can also do GEU and LTU directly, but these operate after a compare.
1071;; ??? The addx/subx insns use the 32 bit carry flag so there are no DImode
1072;; versions for v9.
1073
1074(define_insn "*sltu_insn"
1075  [(set (match_operand:SI 0 "register_operand" "=r")
1076	(ltu:SI (reg:CC 100) (const_int 0)))]
1077  ""
1078  "addx\t%%g0, 0, %0"
1079  [(set_attr "type" "ialuX")])
1080
1081(define_insn "*neg_sltu_insn"
1082  [(set (match_operand:SI 0 "register_operand" "=r")
1083	(neg:SI (ltu:SI (reg:CC 100) (const_int 0))))]
1084  ""
1085  "subx\t%%g0, 0, %0"
1086  [(set_attr "type" "ialuX")])
1087
1088;; ??? Combine should canonicalize these next two to the same pattern.
1089(define_insn "*neg_sltu_minus_x"
1090  [(set (match_operand:SI 0 "register_operand" "=r")
1091	(minus:SI (neg:SI (ltu:SI (reg:CC 100) (const_int 0)))
1092		  (match_operand:SI 1 "arith_operand" "rI")))]
1093  ""
1094  "subx\t%%g0, %1, %0"
1095  [(set_attr "type" "ialuX")])
1096
1097(define_insn "*neg_sltu_plus_x"
1098  [(set (match_operand:SI 0 "register_operand" "=r")
1099	(neg:SI (plus:SI (ltu:SI (reg:CC 100) (const_int 0))
1100			 (match_operand:SI 1 "arith_operand" "rI"))))]
1101  ""
1102  "subx\t%%g0, %1, %0"
1103  [(set_attr "type" "ialuX")])
1104
1105(define_insn "*sgeu_insn"
1106  [(set (match_operand:SI 0 "register_operand" "=r")
1107	(geu:SI (reg:CC 100) (const_int 0)))]
1108  ""
1109  "subx\t%%g0, -1, %0"
1110  [(set_attr "type" "ialuX")])
1111
1112(define_insn "*neg_sgeu_insn"
1113  [(set (match_operand:SI 0 "register_operand" "=r")
1114	(neg:SI (geu:SI (reg:CC 100) (const_int 0))))]
1115  ""
1116  "addx\t%%g0, -1, %0"
1117  [(set_attr "type" "ialuX")])
1118
1119;; We can also do (x + ((unsigned) i >= 0)) and related, so put them in.
1120;; ??? The addx/subx insns use the 32 bit carry flag so there are no DImode
1121;; versions for v9.
1122
1123(define_insn "*sltu_plus_x"
1124  [(set (match_operand:SI 0 "register_operand" "=r")
1125	(plus:SI (ltu:SI (reg:CC 100) (const_int 0))
1126		 (match_operand:SI 1 "arith_operand" "rI")))]
1127  ""
1128  "addx\t%%g0, %1, %0"
1129  [(set_attr "type" "ialuX")])
1130
1131(define_insn "*sltu_plus_x_plus_y"
1132  [(set (match_operand:SI 0 "register_operand" "=r")
1133	(plus:SI (ltu:SI (reg:CC 100) (const_int 0))
1134		 (plus:SI (match_operand:SI 1 "arith_operand" "%r")
1135			  (match_operand:SI 2 "arith_operand" "rI"))))]
1136  ""
1137  "addx\t%1, %2, %0"
1138  [(set_attr "type" "ialuX")])
1139
1140(define_insn "*x_minus_sltu"
1141  [(set (match_operand:SI 0 "register_operand" "=r")
1142	(minus:SI (match_operand:SI 1 "register_operand" "r")
1143		  (ltu:SI (reg:CC 100) (const_int 0))))]
1144  ""
1145  "subx\t%1, 0, %0"
1146  [(set_attr "type" "ialuX")])
1147
1148;; ??? Combine should canonicalize these next two to the same pattern.
1149(define_insn "*x_minus_y_minus_sltu"
1150  [(set (match_operand:SI 0 "register_operand" "=r")
1151	(minus:SI (minus:SI (match_operand:SI 1 "reg_or_0_operand" "rJ")
1152			    (match_operand:SI 2 "arith_operand" "rI"))
1153		  (ltu:SI (reg:CC 100) (const_int 0))))]
1154  ""
1155  "subx\t%r1, %2, %0"
1156  [(set_attr "type" "ialuX")])
1157
1158(define_insn "*x_minus_sltu_plus_y"
1159  [(set (match_operand:SI 0 "register_operand" "=r")
1160	(minus:SI (match_operand:SI 1 "reg_or_0_operand" "rJ")
1161		  (plus:SI (ltu:SI (reg:CC 100) (const_int 0))
1162			   (match_operand:SI 2 "arith_operand" "rI"))))]
1163  ""
1164  "subx\t%r1, %2, %0"
1165  [(set_attr "type" "ialuX")])
1166
1167(define_insn "*sgeu_plus_x"
1168  [(set (match_operand:SI 0 "register_operand" "=r")
1169	(plus:SI (geu:SI (reg:CC 100) (const_int 0))
1170		 (match_operand:SI 1 "register_operand" "r")))]
1171  ""
1172  "subx\t%1, -1, %0"
1173  [(set_attr "type" "ialuX")])
1174
1175(define_insn "*x_minus_sgeu"
1176  [(set (match_operand:SI 0 "register_operand" "=r")
1177	(minus:SI (match_operand:SI 1 "register_operand" "r")
1178		  (geu:SI (reg:CC 100) (const_int 0))))]
1179  ""
1180  "addx\t%1, -1, %0"
1181  [(set_attr "type" "ialuX")])
1182
1183(define_split
1184  [(set (match_operand:SI 0 "register_operand" "")
1185	(match_operator:SI 2 "noov_compare_op"
1186			   [(match_operand 1 "icc_or_fcc_reg_operand" "")
1187			    (const_int 0)]))]
1188  ;; 32 bit LTU/GEU are better implemented using addx/subx
1189  "TARGET_V9 && REGNO (operands[1]) == SPARC_ICC_REG
1190   && (GET_MODE (operands[1]) == CCXmode
1191       || (GET_CODE (operands[2]) != LTU && GET_CODE (operands[2]) != GEU))"
1192  [(set (match_dup 0) (const_int 0))
1193   (set (match_dup 0)
1194	(if_then_else:SI (match_op_dup:SI 2 [(match_dup 1) (const_int 0)])
1195			 (const_int 1)
1196			 (match_dup 0)))]
1197  "")
1198
1199
1200;; These control RTL generation for conditional jump insns
1201
1202;; The quad-word fp compare library routines all return nonzero to indicate
1203;; true, which is different from the equivalent libgcc routines, so we must
1204;; handle them specially here.
1205
1206(define_expand "beq"
1207  [(set (pc)
1208	(if_then_else (eq (match_dup 1) (const_int 0))
1209		      (label_ref (match_operand 0 "" ""))
1210		      (pc)))]
1211  ""
1212{
1213  if (TARGET_ARCH64 && sparc_compare_op1 == const0_rtx
1214      && GET_CODE (sparc_compare_op0) == REG
1215      && GET_MODE (sparc_compare_op0) == DImode)
1216    {
1217      emit_v9_brxx_insn (EQ, sparc_compare_op0, operands[0]);
1218      DONE;
1219    }
1220  else if (GET_MODE (sparc_compare_op0) == TFmode && ! TARGET_HARD_QUAD)
1221    {
1222      sparc_emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, EQ);
1223      emit_jump_insn (gen_bne (operands[0]));
1224      DONE;
1225    }
1226  operands[1] = gen_compare_reg (EQ, sparc_compare_op0, sparc_compare_op1);
1227})
1228
1229(define_expand "bne"
1230  [(set (pc)
1231	(if_then_else (ne (match_dup 1) (const_int 0))
1232		      (label_ref (match_operand 0 "" ""))
1233		      (pc)))]
1234  ""
1235{
1236  if (TARGET_ARCH64 && sparc_compare_op1 == const0_rtx
1237      && GET_CODE (sparc_compare_op0) == REG
1238      && GET_MODE (sparc_compare_op0) == DImode)
1239    {
1240      emit_v9_brxx_insn (NE, sparc_compare_op0, operands[0]);
1241      DONE;
1242    }
1243  else if (GET_MODE (sparc_compare_op0) == TFmode && ! TARGET_HARD_QUAD)
1244    {
1245      sparc_emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, NE);
1246      emit_jump_insn (gen_bne (operands[0]));
1247      DONE;
1248    }
1249  operands[1] = gen_compare_reg (NE, sparc_compare_op0, sparc_compare_op1);
1250})
1251
1252(define_expand "bgt"
1253  [(set (pc)
1254	(if_then_else (gt (match_dup 1) (const_int 0))
1255		      (label_ref (match_operand 0 "" ""))
1256		      (pc)))]
1257  ""
1258{
1259  if (TARGET_ARCH64 && sparc_compare_op1 == const0_rtx
1260      && GET_CODE (sparc_compare_op0) == REG
1261      && GET_MODE (sparc_compare_op0) == DImode)
1262    {
1263      emit_v9_brxx_insn (GT, sparc_compare_op0, operands[0]);
1264      DONE;
1265    }
1266  else if (GET_MODE (sparc_compare_op0) == TFmode && ! TARGET_HARD_QUAD)
1267    {
1268      sparc_emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, GT);
1269      emit_jump_insn (gen_bne (operands[0]));
1270      DONE;
1271    }
1272  operands[1] = gen_compare_reg (GT, sparc_compare_op0, sparc_compare_op1);
1273})
1274
1275(define_expand "bgtu"
1276  [(set (pc)
1277	(if_then_else (gtu (match_dup 1) (const_int 0))
1278		      (label_ref (match_operand 0 "" ""))
1279		      (pc)))]
1280  ""
1281{
1282  operands[1] = gen_compare_reg (GTU, sparc_compare_op0, sparc_compare_op1);
1283})
1284
1285(define_expand "blt"
1286  [(set (pc)
1287	(if_then_else (lt (match_dup 1) (const_int 0))
1288		      (label_ref (match_operand 0 "" ""))
1289		      (pc)))]
1290  ""
1291{
1292  if (TARGET_ARCH64 && sparc_compare_op1 == const0_rtx
1293      && GET_CODE (sparc_compare_op0) == REG
1294      && GET_MODE (sparc_compare_op0) == DImode)
1295    {
1296      emit_v9_brxx_insn (LT, sparc_compare_op0, operands[0]);
1297      DONE;
1298    }
1299  else if (GET_MODE (sparc_compare_op0) == TFmode && ! TARGET_HARD_QUAD)
1300    {
1301      sparc_emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, LT);
1302      emit_jump_insn (gen_bne (operands[0]));
1303      DONE;
1304    }
1305  operands[1] = gen_compare_reg (LT, sparc_compare_op0, sparc_compare_op1);
1306})
1307
1308(define_expand "bltu"
1309  [(set (pc)
1310	(if_then_else (ltu (match_dup 1) (const_int 0))
1311		      (label_ref (match_operand 0 "" ""))
1312		      (pc)))]
1313  ""
1314{
1315  operands[1] = gen_compare_reg (LTU, sparc_compare_op0, sparc_compare_op1);
1316})
1317
1318(define_expand "bge"
1319  [(set (pc)
1320	(if_then_else (ge (match_dup 1) (const_int 0))
1321		      (label_ref (match_operand 0 "" ""))
1322		      (pc)))]
1323  ""
1324{
1325  if (TARGET_ARCH64 && sparc_compare_op1 == const0_rtx
1326      && GET_CODE (sparc_compare_op0) == REG
1327      && GET_MODE (sparc_compare_op0) == DImode)
1328    {
1329      emit_v9_brxx_insn (GE, sparc_compare_op0, operands[0]);
1330      DONE;
1331    }
1332  else if (GET_MODE (sparc_compare_op0) == TFmode && ! TARGET_HARD_QUAD)
1333    {
1334      sparc_emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, GE);
1335      emit_jump_insn (gen_bne (operands[0]));
1336      DONE;
1337    }
1338  operands[1] = gen_compare_reg (GE, sparc_compare_op0, sparc_compare_op1);
1339})
1340
1341(define_expand "bgeu"
1342  [(set (pc)
1343	(if_then_else (geu (match_dup 1) (const_int 0))
1344		      (label_ref (match_operand 0 "" ""))
1345		      (pc)))]
1346  ""
1347{
1348  operands[1] = gen_compare_reg (GEU, sparc_compare_op0, sparc_compare_op1);
1349})
1350
1351(define_expand "ble"
1352  [(set (pc)
1353	(if_then_else (le (match_dup 1) (const_int 0))
1354		      (label_ref (match_operand 0 "" ""))
1355		      (pc)))]
1356  ""
1357{
1358  if (TARGET_ARCH64 && sparc_compare_op1 == const0_rtx
1359      && GET_CODE (sparc_compare_op0) == REG
1360      && GET_MODE (sparc_compare_op0) == DImode)
1361    {
1362      emit_v9_brxx_insn (LE, sparc_compare_op0, operands[0]);
1363      DONE;
1364    }
1365  else if (GET_MODE (sparc_compare_op0) == TFmode && ! TARGET_HARD_QUAD)
1366    {
1367      sparc_emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, LE);
1368      emit_jump_insn (gen_bne (operands[0]));
1369      DONE;
1370    }
1371  operands[1] = gen_compare_reg (LE, sparc_compare_op0, sparc_compare_op1);
1372})
1373
1374(define_expand "bleu"
1375  [(set (pc)
1376	(if_then_else (leu (match_dup 1) (const_int 0))
1377		      (label_ref (match_operand 0 "" ""))
1378		      (pc)))]
1379  ""
1380{
1381  operands[1] = gen_compare_reg (LEU, sparc_compare_op0, sparc_compare_op1);
1382})
1383
1384(define_expand "bunordered"
1385  [(set (pc)
1386	(if_then_else (unordered (match_dup 1) (const_int 0))
1387		      (label_ref (match_operand 0 "" ""))
1388		      (pc)))]
1389  ""
1390{
1391  if (GET_MODE (sparc_compare_op0) == TFmode && ! TARGET_HARD_QUAD)
1392    {
1393      sparc_emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1,
1394				UNORDERED);
1395      emit_jump_insn (gen_beq (operands[0]));
1396      DONE;
1397    }
1398  operands[1] = gen_compare_reg (UNORDERED, sparc_compare_op0,
1399				 sparc_compare_op1);
1400})
1401
1402(define_expand "bordered"
1403  [(set (pc)
1404	(if_then_else (ordered (match_dup 1) (const_int 0))
1405		      (label_ref (match_operand 0 "" ""))
1406		      (pc)))]
1407  ""
1408{
1409  if (GET_MODE (sparc_compare_op0) == TFmode && ! TARGET_HARD_QUAD)
1410    {
1411      sparc_emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, ORDERED);
1412      emit_jump_insn (gen_bne (operands[0]));
1413      DONE;
1414    }
1415  operands[1] = gen_compare_reg (ORDERED, sparc_compare_op0,
1416				 sparc_compare_op1);
1417})
1418
1419(define_expand "bungt"
1420  [(set (pc)
1421	(if_then_else (ungt (match_dup 1) (const_int 0))
1422		      (label_ref (match_operand 0 "" ""))
1423		      (pc)))]
1424  ""
1425{
1426  if (GET_MODE (sparc_compare_op0) == TFmode && ! TARGET_HARD_QUAD)
1427    {
1428      sparc_emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, UNGT);
1429      emit_jump_insn (gen_bgt (operands[0]));
1430      DONE;
1431    }
1432  operands[1] = gen_compare_reg (UNGT, sparc_compare_op0, sparc_compare_op1);
1433})
1434
1435(define_expand "bunlt"
1436  [(set (pc)
1437	(if_then_else (unlt (match_dup 1) (const_int 0))
1438		      (label_ref (match_operand 0 "" ""))
1439		      (pc)))]
1440  ""
1441{
1442  if (GET_MODE (sparc_compare_op0) == TFmode && ! TARGET_HARD_QUAD)
1443    {
1444      sparc_emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, UNLT);
1445      emit_jump_insn (gen_bne (operands[0]));
1446      DONE;
1447    }
1448  operands[1] = gen_compare_reg (UNLT, sparc_compare_op0, sparc_compare_op1);
1449})
1450
1451(define_expand "buneq"
1452  [(set (pc)
1453	(if_then_else (uneq (match_dup 1) (const_int 0))
1454		      (label_ref (match_operand 0 "" ""))
1455		      (pc)))]
1456  ""
1457{
1458  if (GET_MODE (sparc_compare_op0) == TFmode && ! TARGET_HARD_QUAD)
1459    {
1460      sparc_emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, UNEQ);
1461      emit_jump_insn (gen_beq (operands[0]));
1462      DONE;
1463    }
1464  operands[1] = gen_compare_reg (UNEQ, sparc_compare_op0, sparc_compare_op1);
1465})
1466
1467(define_expand "bunge"
1468  [(set (pc)
1469	(if_then_else (unge (match_dup 1) (const_int 0))
1470		      (label_ref (match_operand 0 "" ""))
1471		      (pc)))]
1472  ""
1473{
1474  if (GET_MODE (sparc_compare_op0) == TFmode && ! TARGET_HARD_QUAD)
1475    {
1476      sparc_emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, UNGE);
1477      emit_jump_insn (gen_bne (operands[0]));
1478      DONE;
1479    }
1480  operands[1] = gen_compare_reg (UNGE, sparc_compare_op0, sparc_compare_op1);
1481})
1482
1483(define_expand "bunle"
1484  [(set (pc)
1485	(if_then_else (unle (match_dup 1) (const_int 0))
1486		      (label_ref (match_operand 0 "" ""))
1487		      (pc)))]
1488  ""
1489{
1490  if (GET_MODE (sparc_compare_op0) == TFmode && ! TARGET_HARD_QUAD)
1491    {
1492      sparc_emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, UNLE);
1493      emit_jump_insn (gen_bne (operands[0]));
1494      DONE;
1495    }
1496  operands[1] = gen_compare_reg (UNLE, sparc_compare_op0, sparc_compare_op1);
1497})
1498
1499(define_expand "bltgt"
1500  [(set (pc)
1501	(if_then_else (ltgt (match_dup 1) (const_int 0))
1502		      (label_ref (match_operand 0 "" ""))
1503		      (pc)))]
1504  ""
1505{
1506  if (GET_MODE (sparc_compare_op0) == TFmode && ! TARGET_HARD_QUAD)
1507    {
1508      sparc_emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, LTGT);
1509      emit_jump_insn (gen_bne (operands[0]));
1510      DONE;
1511    }
1512  operands[1] = gen_compare_reg (LTGT, sparc_compare_op0, sparc_compare_op1);
1513})
1514
1515;; Now match both normal and inverted jump.
1516
1517;; XXX fpcmp nop braindamage
1518(define_insn "*normal_branch"
1519  [(set (pc)
1520	(if_then_else (match_operator 0 "noov_compare_op"
1521				      [(reg 100) (const_int 0)])
1522		      (label_ref (match_operand 1 "" ""))
1523		      (pc)))]
1524  ""
1525{
1526  return output_cbranch (operands[0], operands[1], 1, 0,
1527			 final_sequence && INSN_ANNULLED_BRANCH_P (insn),
1528			 ! final_sequence, insn);
1529}
1530  [(set_attr "type" "branch")
1531   (set_attr "branch_type" "icc")])
1532
1533;; XXX fpcmp nop braindamage
1534(define_insn "*inverted_branch"
1535  [(set (pc)
1536	(if_then_else (match_operator 0 "noov_compare_op"
1537				      [(reg 100) (const_int 0)])
1538		      (pc)
1539		      (label_ref (match_operand 1 "" ""))))]
1540  ""
1541{
1542  return output_cbranch (operands[0], operands[1], 1, 1,
1543			 final_sequence && INSN_ANNULLED_BRANCH_P (insn),
1544			 ! final_sequence, insn);
1545}
1546  [(set_attr "type" "branch")
1547   (set_attr "branch_type" "icc")])
1548
1549;; XXX fpcmp nop braindamage
1550(define_insn "*normal_fp_branch"
1551  [(set (pc)
1552	(if_then_else (match_operator 1 "comparison_operator"
1553				      [(match_operand:CCFP 0 "fcc_reg_operand" "c")
1554				       (const_int 0)])
1555		      (label_ref (match_operand 2 "" ""))
1556		      (pc)))]
1557  ""
1558{
1559  return output_cbranch (operands[1], operands[2], 2, 0,
1560			 final_sequence && INSN_ANNULLED_BRANCH_P (insn),
1561			 ! final_sequence, insn);
1562}
1563  [(set_attr "type" "branch")
1564   (set_attr "branch_type" "fcc")])
1565
1566;; XXX fpcmp nop braindamage
1567(define_insn "*inverted_fp_branch"
1568  [(set (pc)
1569	(if_then_else (match_operator 1 "comparison_operator"
1570				      [(match_operand:CCFP 0 "fcc_reg_operand" "c")
1571				       (const_int 0)])
1572		      (pc)
1573		      (label_ref (match_operand 2 "" ""))))]
1574  ""
1575{
1576  return output_cbranch (operands[1], operands[2], 2, 1,
1577			 final_sequence && INSN_ANNULLED_BRANCH_P (insn),
1578			 ! final_sequence, insn);
1579}
1580  [(set_attr "type" "branch")
1581   (set_attr "branch_type" "fcc")])
1582
1583;; XXX fpcmp nop braindamage
1584(define_insn "*normal_fpe_branch"
1585  [(set (pc)
1586	(if_then_else (match_operator 1 "comparison_operator"
1587				      [(match_operand:CCFPE 0 "fcc_reg_operand" "c")
1588				       (const_int 0)])
1589		      (label_ref (match_operand 2 "" ""))
1590		      (pc)))]
1591  ""
1592{
1593  return output_cbranch (operands[1], operands[2], 2, 0,
1594			 final_sequence && INSN_ANNULLED_BRANCH_P (insn),
1595			 ! final_sequence, insn);
1596}
1597  [(set_attr "type" "branch")
1598   (set_attr "branch_type" "fcc")])
1599
1600;; XXX fpcmp nop braindamage
1601(define_insn "*inverted_fpe_branch"
1602  [(set (pc)
1603	(if_then_else (match_operator 1 "comparison_operator"
1604				      [(match_operand:CCFPE 0 "fcc_reg_operand" "c")
1605				       (const_int 0)])
1606		      (pc)
1607		      (label_ref (match_operand 2 "" ""))))]
1608  ""
1609{
1610  return output_cbranch (operands[1], operands[2], 2, 1,
1611			 final_sequence && INSN_ANNULLED_BRANCH_P (insn),
1612			 ! final_sequence, insn);
1613}
1614  [(set_attr "type" "branch")
1615   (set_attr "branch_type" "fcc")])
1616
1617;; SPARC V9-specific jump insns.  None of these are guaranteed to be
1618;; in the architecture.
1619
1620;; There are no 32 bit brreg insns.
1621
1622;; XXX
1623(define_insn "*normal_int_branch_sp64"
1624  [(set (pc)
1625	(if_then_else (match_operator 0 "v9_regcmp_op"
1626				      [(match_operand:DI 1 "register_operand" "r")
1627				       (const_int 0)])
1628		      (label_ref (match_operand 2 "" ""))
1629		      (pc)))]
1630  "TARGET_ARCH64"
1631{
1632  return output_v9branch (operands[0], operands[2], 1, 2, 0,
1633			  final_sequence && INSN_ANNULLED_BRANCH_P (insn),
1634			  ! final_sequence, insn);
1635}
1636  [(set_attr "type" "branch")
1637   (set_attr "branch_type" "reg")])
1638
1639;; XXX
1640(define_insn "*inverted_int_branch_sp64"
1641  [(set (pc)
1642	(if_then_else (match_operator 0 "v9_regcmp_op"
1643				      [(match_operand:DI 1 "register_operand" "r")
1644				       (const_int 0)])
1645		      (pc)
1646		      (label_ref (match_operand 2 "" ""))))]
1647  "TARGET_ARCH64"
1648{
1649  return output_v9branch (operands[0], operands[2], 1, 2, 1,
1650			  final_sequence && INSN_ANNULLED_BRANCH_P (insn),
1651			  ! final_sequence, insn);
1652}
1653  [(set_attr "type" "branch")
1654   (set_attr "branch_type" "reg")])
1655
1656;; Load program counter insns.
1657
1658(define_insn "get_pc"
1659  [(clobber (reg:SI 15))
1660   (set (match_operand 0 "register_operand" "=r")
1661	(unspec [(match_operand 1 "" "") (match_operand 2 "" "")] UNSPEC_GET_PC))]
1662  "flag_pic && REGNO (operands[0]) == 23"
1663  "sethi\t%%hi(%a1-4), %0\n\tcall\t%a2\n\tadd\t%0, %%lo(%a1+4), %0"
1664  [(set_attr "type" "multi")
1665   (set_attr "length" "3")])
1666
1667
1668;; Move instructions
1669
1670(define_expand "movqi"
1671  [(set (match_operand:QI 0 "general_operand" "")
1672	(match_operand:QI 1 "general_operand" ""))]
1673  ""
1674{
1675  /* Working with CONST_INTs is easier, so convert
1676     a double if needed.  */
1677  if (GET_CODE (operands[1]) == CONST_DOUBLE)
1678    {
1679      operands[1] = GEN_INT (trunc_int_for_mode
1680			     (CONST_DOUBLE_LOW (operands[1]), QImode));
1681    }
1682
1683  /* Handle sets of MEM first.  */
1684  if (GET_CODE (operands[0]) == MEM)
1685    {
1686      if (reg_or_0_operand (operands[1], QImode))
1687	goto movqi_is_ok;
1688
1689      if (! reload_in_progress)
1690	{
1691	  operands[0] = validize_mem (operands[0]);
1692	  operands[1] = force_reg (QImode, operands[1]);
1693	}
1694    }
1695
1696  /* Fixup PIC cases.  */
1697  if (flag_pic)
1698    {
1699      if (CONSTANT_P (operands[1])
1700	  && pic_address_needs_scratch (operands[1]))
1701	operands[1] = legitimize_pic_address (operands[1], QImode, 0);
1702
1703      if (symbolic_operand (operands[1], QImode))
1704	{
1705	  operands[1] = legitimize_pic_address (operands[1],
1706						QImode,
1707						(reload_in_progress ?
1708						 operands[0] :
1709						 NULL_RTX));
1710	  goto movqi_is_ok;
1711	}
1712    }
1713
1714  /* All QI constants require only one insn, so proceed.  */
1715
1716 movqi_is_ok:
1717  ;
1718})
1719
1720(define_insn "*movqi_insn"
1721  [(set (match_operand:QI 0 "nonimmediate_operand" "=r,r,m")
1722	(match_operand:QI 1 "input_operand"   "rI,m,rJ"))]
1723  "(register_operand (operands[0], QImode)
1724    || reg_or_0_operand (operands[1], QImode))"
1725  "@
1726   mov\t%1, %0
1727   ldub\t%1, %0
1728   stb\t%r1, %0"
1729  [(set_attr "type" "*,load,store")
1730   (set_attr "us3load_type" "*,3cycle,*")])
1731
1732(define_expand "movhi"
1733  [(set (match_operand:HI 0 "general_operand" "")
1734	(match_operand:HI 1 "general_operand" ""))]
1735  ""
1736{
1737  /* Working with CONST_INTs is easier, so convert
1738     a double if needed.  */
1739  if (GET_CODE (operands[1]) == CONST_DOUBLE)
1740    operands[1] = GEN_INT (CONST_DOUBLE_LOW (operands[1]));
1741
1742  /* Handle sets of MEM first.  */
1743  if (GET_CODE (operands[0]) == MEM)
1744    {
1745      if (reg_or_0_operand (operands[1], HImode))
1746	goto movhi_is_ok;
1747
1748      if (! reload_in_progress)
1749	{
1750	  operands[0] = validize_mem (operands[0]);
1751	  operands[1] = force_reg (HImode, operands[1]);
1752	}
1753    }
1754
1755  /* Fixup PIC cases.  */
1756  if (flag_pic)
1757    {
1758      if (CONSTANT_P (operands[1])
1759	  && pic_address_needs_scratch (operands[1]))
1760	operands[1] = legitimize_pic_address (operands[1], HImode, 0);
1761
1762      if (symbolic_operand (operands[1], HImode))
1763	{
1764	  operands[1] = legitimize_pic_address (operands[1],
1765						HImode,
1766						(reload_in_progress ?
1767						 operands[0] :
1768						 NULL_RTX));
1769	  goto movhi_is_ok;
1770	}
1771    }
1772
1773  /* This makes sure we will not get rematched due to splittage.  */
1774  if (! CONSTANT_P (operands[1]) || input_operand (operands[1], HImode))
1775    ;
1776  else if (CONSTANT_P (operands[1])
1777	   && GET_CODE (operands[1]) != HIGH
1778	   && GET_CODE (operands[1]) != LO_SUM)
1779    {
1780      sparc_emit_set_const32 (operands[0], operands[1]);
1781      DONE;
1782    }
1783 movhi_is_ok:
1784  ;
1785})
1786
1787(define_insn "*movhi_const64_special"
1788  [(set (match_operand:HI 0 "register_operand" "=r")
1789	(match_operand:HI 1 "const64_high_operand" ""))]
1790  "TARGET_ARCH64"
1791  "sethi\t%%hi(%a1), %0")
1792
1793(define_insn "*movhi_insn"
1794  [(set (match_operand:HI 0 "nonimmediate_operand" "=r,r,r,m")
1795	(match_operand:HI 1 "input_operand"   "rI,K,m,rJ"))]
1796  "(register_operand (operands[0], HImode)
1797    || reg_or_0_operand (operands[1], HImode))"
1798  "@
1799   mov\t%1, %0
1800   sethi\t%%hi(%a1), %0
1801   lduh\t%1, %0
1802   sth\t%r1, %0"
1803  [(set_attr "type" "*,*,load,store")
1804   (set_attr "us3load_type" "*,*,3cycle,*")])
1805
1806;; We always work with constants here.
1807(define_insn "*movhi_lo_sum"
1808  [(set (match_operand:HI 0 "register_operand" "=r")
1809	(ior:HI (match_operand:HI 1 "arith_operand" "%r")
1810                (match_operand:HI 2 "arith_operand" "I")))]
1811  ""
1812  "or\t%1, %2, %0")
1813
1814(define_expand "movsi"
1815  [(set (match_operand:SI 0 "general_operand" "")
1816	(match_operand:SI 1 "general_operand" ""))]
1817  ""
1818{
1819  /* Working with CONST_INTs is easier, so convert
1820     a double if needed.  */
1821  if (GET_CODE (operands[1]) == CONST_DOUBLE)
1822    operands[1] = GEN_INT (CONST_DOUBLE_LOW (operands[1]));
1823
1824  /* Handle sets of MEM first.  */
1825  if (GET_CODE (operands[0]) == MEM)
1826    {
1827      if (reg_or_0_operand (operands[1], SImode))
1828	goto movsi_is_ok;
1829
1830      if (! reload_in_progress)
1831	{
1832	  operands[0] = validize_mem (operands[0]);
1833	  operands[1] = force_reg (SImode, operands[1]);
1834	}
1835    }
1836
1837  /* Fixup PIC cases.  */
1838  if (flag_pic)
1839    {
1840      if (CONSTANT_P (operands[1])
1841	  && pic_address_needs_scratch (operands[1]))
1842	operands[1] = legitimize_pic_address (operands[1], SImode, 0);
1843
1844      if (GET_CODE (operands[1]) == LABEL_REF)
1845	{
1846	  /* shit */
1847	  emit_insn (gen_movsi_pic_label_ref (operands[0], operands[1]));
1848	  DONE;
1849	}
1850
1851      if (symbolic_operand (operands[1], SImode))
1852	{
1853	  operands[1] = legitimize_pic_address (operands[1],
1854						SImode,
1855						(reload_in_progress ?
1856						 operands[0] :
1857						 NULL_RTX));
1858	  goto movsi_is_ok;
1859	}
1860    }
1861
1862  /* If we are trying to toss an integer constant into the
1863     FPU registers, force it into memory.  */
1864  if (GET_CODE (operands[0]) == REG
1865      && REGNO (operands[0]) >= SPARC_FIRST_FP_REG
1866      && REGNO (operands[0]) <= SPARC_LAST_V9_FP_REG
1867      && CONSTANT_P (operands[1]))
1868    operands[1] = validize_mem (force_const_mem (GET_MODE (operands[0]),
1869						 operands[1]));
1870
1871  /* This makes sure we will not get rematched due to splittage.  */
1872  if (! CONSTANT_P (operands[1]) || input_operand (operands[1], SImode))
1873    ;
1874  else if (CONSTANT_P (operands[1])
1875	   && GET_CODE (operands[1]) != HIGH
1876	   && GET_CODE (operands[1]) != LO_SUM)
1877    {
1878      sparc_emit_set_const32 (operands[0], operands[1]);
1879      DONE;
1880    }
1881 movsi_is_ok:
1882  ;
1883})
1884
1885;; This is needed to show CSE exactly which bits are set
1886;; in a 64-bit register by sethi instructions.
1887(define_insn "*movsi_const64_special"
1888  [(set (match_operand:SI 0 "register_operand" "=r")
1889	(match_operand:SI 1 "const64_high_operand" ""))]
1890  "TARGET_ARCH64"
1891  "sethi\t%%hi(%a1), %0")
1892
1893(define_insn "*movsi_insn"
1894  [(set (match_operand:SI 0 "nonimmediate_operand" "=r,f,r,r,r,f,m,m,d")
1895	(match_operand:SI 1 "input_operand"   "rI,!f,K,J,m,!m,rJ,!f,J"))]
1896  "(register_operand (operands[0], SImode)
1897    || reg_or_0_operand (operands[1], SImode))"
1898  "@
1899   mov\t%1, %0
1900   fmovs\t%1, %0
1901   sethi\t%%hi(%a1), %0
1902   clr\t%0
1903   ld\t%1, %0
1904   ld\t%1, %0
1905   st\t%r1, %0
1906   st\t%1, %0
1907   fzeros\t%0"
1908  [(set_attr "type" "*,fpmove,*,*,load,fpload,store,fpstore,fpmove")])
1909
1910(define_insn "*movsi_lo_sum"
1911  [(set (match_operand:SI 0 "register_operand" "=r")
1912	(lo_sum:SI (match_operand:SI 1 "register_operand" "r")
1913                   (match_operand:SI 2 "immediate_operand" "in")))]
1914  ""
1915  "or\t%1, %%lo(%a2), %0")
1916
1917(define_insn "*movsi_high"
1918  [(set (match_operand:SI 0 "register_operand" "=r")
1919	(high:SI (match_operand:SI 1 "immediate_operand" "in")))]
1920  ""
1921  "sethi\t%%hi(%a1), %0")
1922
1923;; The next two patterns must wrap the SYMBOL_REF in an UNSPEC
1924;; so that CSE won't optimize the address computation away.
1925(define_insn "movsi_lo_sum_pic"
1926  [(set (match_operand:SI 0 "register_operand" "=r")
1927        (lo_sum:SI (match_operand:SI 1 "register_operand" "r")
1928                   (unspec:SI [(match_operand:SI 2 "immediate_operand" "in")] UNSPEC_MOVE_PIC)))]
1929  "flag_pic"
1930  "or\t%1, %%lo(%a2), %0")
1931
1932(define_insn "movsi_high_pic"
1933  [(set (match_operand:SI 0 "register_operand" "=r")
1934        (high:SI (unspec:SI [(match_operand 1 "" "")] UNSPEC_MOVE_PIC)))]
1935  "flag_pic && check_pic (1)"
1936  "sethi\t%%hi(%a1), %0")
1937
1938(define_expand "movsi_pic_label_ref"
1939  [(set (match_dup 3) (high:SI
1940     (unspec:SI [(match_operand:SI 1 "label_ref_operand" "")
1941		 (match_dup 2)] UNSPEC_MOVE_PIC_LABEL)))
1942   (set (match_dup 4) (lo_sum:SI (match_dup 3)
1943     (unspec:SI [(match_dup 1) (match_dup 2)] UNSPEC_MOVE_PIC_LABEL)))
1944   (set (match_operand:SI 0 "register_operand" "=r")
1945	(minus:SI (match_dup 5) (match_dup 4)))]
1946  "flag_pic"
1947{
1948  current_function_uses_pic_offset_table = 1;
1949  operands[2] = gen_rtx_SYMBOL_REF (Pmode, "_GLOBAL_OFFSET_TABLE_");
1950  if (no_new_pseudos)
1951    {
1952      operands[3] = operands[0];
1953      operands[4] = operands[0];
1954    }
1955  else
1956    {
1957      operands[3] = gen_reg_rtx (SImode);
1958      operands[4] = gen_reg_rtx (SImode);
1959    }
1960  operands[5] = pic_offset_table_rtx;
1961})
1962
1963(define_insn "*movsi_high_pic_label_ref"
1964  [(set (match_operand:SI 0 "register_operand" "=r")
1965      (high:SI
1966        (unspec:SI [(match_operand:SI 1 "label_ref_operand" "")
1967		    (match_operand:SI 2 "" "")] UNSPEC_MOVE_PIC_LABEL)))]
1968  "flag_pic"
1969  "sethi\t%%hi(%a2-(%a1-.)), %0")
1970
1971(define_insn "*movsi_lo_sum_pic_label_ref"
1972  [(set (match_operand:SI 0 "register_operand" "=r")
1973      (lo_sum:SI (match_operand:SI 1 "register_operand" "r")
1974        (unspec:SI [(match_operand:SI 2 "label_ref_operand" "")
1975		    (match_operand:SI 3 "" "")] UNSPEC_MOVE_PIC_LABEL)))]
1976  "flag_pic"
1977  "or\t%1, %%lo(%a3-(%a2-.)), %0")
1978
1979(define_expand "movdi"
1980  [(set (match_operand:DI 0 "reg_or_nonsymb_mem_operand" "")
1981	(match_operand:DI 1 "general_operand" ""))]
1982  ""
1983{
1984  /* Where possible, convert CONST_DOUBLE into a CONST_INT.  */
1985  if (GET_CODE (operands[1]) == CONST_DOUBLE
1986#if HOST_BITS_PER_WIDE_INT == 32
1987      && ((CONST_DOUBLE_HIGH (operands[1]) == 0
1988	   && (CONST_DOUBLE_LOW (operands[1]) & 0x80000000) == 0)
1989	  || (CONST_DOUBLE_HIGH (operands[1]) == (HOST_WIDE_INT) 0xffffffff
1990	      && (CONST_DOUBLE_LOW (operands[1]) & 0x80000000) != 0))
1991#endif
1992      )
1993    operands[1] = GEN_INT (CONST_DOUBLE_LOW (operands[1]));
1994
1995  /* Handle MEM cases first.  */
1996  if (GET_CODE (operands[0]) == MEM)
1997    {
1998      /* If it's a REG, we can always do it.
1999	 The const zero case is more complex, on v9
2000	 we can always perform it.  */
2001      if (register_operand (operands[1], DImode)
2002	  || (TARGET_V9
2003              && (operands[1] == const0_rtx)))
2004        goto movdi_is_ok;
2005
2006      if (! reload_in_progress)
2007	{
2008	  operands[0] = validize_mem (operands[0]);
2009	  operands[1] = force_reg (DImode, operands[1]);
2010	}
2011    }
2012
2013  if (flag_pic)
2014    {
2015      if (CONSTANT_P (operands[1])
2016	  && pic_address_needs_scratch (operands[1]))
2017	operands[1] = legitimize_pic_address (operands[1], DImode, 0);
2018
2019      if (GET_CODE (operands[1]) == LABEL_REF)
2020        {
2021          if (! TARGET_ARCH64)
2022            abort ();
2023          emit_insn (gen_movdi_pic_label_ref (operands[0], operands[1]));
2024          DONE;
2025        }
2026
2027      if (symbolic_operand (operands[1], DImode))
2028	{
2029	  operands[1] = legitimize_pic_address (operands[1],
2030						DImode,
2031						(reload_in_progress ?
2032						 operands[0] :
2033						 NULL_RTX));
2034	  goto movdi_is_ok;
2035	}
2036    }
2037
2038  /* If we are trying to toss an integer constant into the
2039     FPU registers, force it into memory.  */
2040  if (GET_CODE (operands[0]) == REG
2041      && REGNO (operands[0]) >= SPARC_FIRST_FP_REG
2042      && REGNO (operands[0]) <= SPARC_LAST_V9_FP_REG
2043      && CONSTANT_P (operands[1]))
2044    operands[1] = validize_mem (force_const_mem (GET_MODE (operands[0]),
2045						 operands[1]));
2046
2047  /* This makes sure we will not get rematched due to splittage.  */
2048  if (! CONSTANT_P (operands[1]) || input_operand (operands[1], DImode))
2049    ;
2050  else if (TARGET_ARCH64
2051           && GET_CODE (operands[1]) != HIGH
2052           && GET_CODE (operands[1]) != LO_SUM)
2053    {
2054      sparc_emit_set_const64 (operands[0], operands[1]);
2055      DONE;
2056    }
2057
2058 movdi_is_ok:
2059  ;
2060})
2061
2062;; Be careful, fmovd does not exist when !v9.
2063;; We match MEM moves directly when we have correct even
2064;; numbered registers, but fall into splits otherwise.
2065;; The constraint ordering here is really important to
2066;; avoid insane problems in reload, especially for patterns
2067;; of the form:
2068;;
2069;; (set (mem:DI (plus:SI (reg:SI 30 %fp)
2070;;                       (const_int -5016)))
2071;;      (reg:DI 2 %g2))
2072;;
2073
2074(define_insn "*movdi_insn_sp32_v9"
2075  [(set (match_operand:DI 0 "nonimmediate_operand"
2076					"=T,o,T,U,o,r,r,r,?T,?f,?f,?o,?e,?e,?W")
2077        (match_operand:DI 1 "input_operand"
2078					" J,J,U,T,r,o,i,r, f, T, o, f, e, W, e"))]
2079  "! TARGET_ARCH64 && TARGET_V9
2080   && (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)"
2081  "@
2082   stx\t%%g0, %0
2083   #
2084   std\t%1, %0
2085   ldd\t%1, %0
2086   #
2087   #
2088   #
2089   #
2090   std\t%1, %0
2091   ldd\t%1, %0
2092   #
2093   #
2094   fmovd\\t%1, %0
2095   ldd\\t%1, %0
2096   std\\t%1, %0"
2097  [(set_attr "type" "store,store,store,load,*,*,*,*,fpstore,fpload,*,*,fpmove,fpload,fpstore")
2098   (set_attr "length" "*,2,*,*,2,2,2,2,*,*,2,2,*,*,*")
2099   (set_attr "fptype" "*,*,*,*,*,*,*,*,*,*,*,*,double,*,*")])
2100
2101(define_insn "*movdi_insn_sp32"
2102  [(set (match_operand:DI 0 "nonimmediate_operand"
2103				"=o,T,U,o,r,r,r,?T,?f,?f,?o,?f")
2104        (match_operand:DI 1 "input_operand"
2105				" J,U,T,r,o,i,r, f, T, o, f, f"))]
2106  "! TARGET_ARCH64
2107   && (register_operand (operands[0], DImode)
2108       || register_operand (operands[1], DImode))"
2109  "@
2110   #
2111   std\t%1, %0
2112   ldd\t%1, %0
2113   #
2114   #
2115   #
2116   #
2117   std\t%1, %0
2118   ldd\t%1, %0
2119   #
2120   #
2121   #"
2122  [(set_attr "type" "store,store,load,*,*,*,*,fpstore,fpload,*,*,*")
2123   (set_attr "length" "2,*,*,2,2,2,2,*,*,2,2,2")])
2124
2125;; The following are generated by sparc_emit_set_const64
2126(define_insn "*movdi_sp64_dbl"
2127  [(set (match_operand:DI 0 "register_operand" "=r")
2128        (match_operand:DI 1 "const64_operand" ""))]
2129  "(TARGET_ARCH64
2130    && HOST_BITS_PER_WIDE_INT != 64)"
2131  "mov\t%1, %0")
2132
2133;; This is needed to show CSE exactly which bits are set
2134;; in a 64-bit register by sethi instructions.
2135(define_insn "*movdi_const64_special"
2136  [(set (match_operand:DI 0 "register_operand" "=r")
2137	(match_operand:DI 1 "const64_high_operand" ""))]
2138  "TARGET_ARCH64"
2139  "sethi\t%%hi(%a1), %0")
2140
2141(define_insn "*movdi_insn_sp64_novis"
2142  [(set (match_operand:DI 0 "nonimmediate_operand" "=r,r,r,r,m,?e,?e,?W")
2143        (match_operand:DI 1 "input_operand"   "rI,N,J,m,rJ,e,W,e"))]
2144  "TARGET_ARCH64 && ! TARGET_VIS
2145   && (register_operand (operands[0], DImode)
2146       || reg_or_0_operand (operands[1], DImode))"
2147  "@
2148   mov\t%1, %0
2149   sethi\t%%hi(%a1), %0
2150   clr\t%0
2151   ldx\t%1, %0
2152   stx\t%r1, %0
2153   fmovd\t%1, %0
2154   ldd\t%1, %0
2155   std\t%1, %0"
2156  [(set_attr "type" "*,*,*,load,store,fpmove,fpload,fpstore")
2157   (set_attr "fptype" "*,*,*,*,*,double,*,*")])
2158
2159(define_insn "*movdi_insn_sp64_vis"
2160  [(set (match_operand:DI 0 "nonimmediate_operand" "=r,r,r,r,m,?e,?e,?W,b")
2161        (match_operand:DI 1 "input_operand"   "rI,N,J,m,rJ,e,W,e,J"))]
2162  "TARGET_ARCH64 && TARGET_VIS &&
2163   (register_operand (operands[0], DImode)
2164    || reg_or_0_operand (operands[1], DImode))"
2165  "@
2166   mov\t%1, %0
2167   sethi\t%%hi(%a1), %0
2168   clr\t%0
2169   ldx\t%1, %0
2170   stx\t%r1, %0
2171   fmovd\t%1, %0
2172   ldd\t%1, %0
2173   std\t%1, %0
2174   fzero\t%0"
2175  [(set_attr "type" "*,*,*,load,store,fpmove,fpload,fpstore,fpmove")
2176   (set_attr "fptype" "*,*,*,*,*,double,*,*,double")])
2177
2178(define_expand "movdi_pic_label_ref"
2179  [(set (match_dup 3) (high:DI
2180     (unspec:DI [(match_operand:DI 1 "label_ref_operand" "")
2181                 (match_dup 2)] UNSPEC_MOVE_PIC_LABEL)))
2182   (set (match_dup 4) (lo_sum:DI (match_dup 3)
2183     (unspec:DI [(match_dup 1) (match_dup 2)] UNSPEC_MOVE_PIC_LABEL)))
2184   (set (match_operand:DI 0 "register_operand" "=r")
2185        (minus:DI (match_dup 5) (match_dup 4)))]
2186  "TARGET_ARCH64 && flag_pic"
2187{
2188  current_function_uses_pic_offset_table = 1;
2189  operands[2] = gen_rtx_SYMBOL_REF (Pmode, "_GLOBAL_OFFSET_TABLE_");
2190  if (no_new_pseudos)
2191    {
2192      operands[3] = operands[0];
2193      operands[4] = operands[0];
2194    }
2195  else
2196    {
2197      operands[3] = gen_reg_rtx (DImode);
2198      operands[4] = gen_reg_rtx (DImode);
2199    }
2200  operands[5] = pic_offset_table_rtx;
2201})
2202
2203(define_insn "*movdi_high_pic_label_ref"
2204  [(set (match_operand:DI 0 "register_operand" "=r")
2205        (high:DI
2206          (unspec:DI [(match_operand:DI 1 "label_ref_operand" "")
2207                      (match_operand:DI 2 "" "")] UNSPEC_MOVE_PIC_LABEL)))]
2208  "TARGET_ARCH64 && flag_pic"
2209  "sethi\t%%hi(%a2-(%a1-.)), %0")
2210
2211(define_insn "*movdi_lo_sum_pic_label_ref"
2212  [(set (match_operand:DI 0 "register_operand" "=r")
2213      (lo_sum:DI (match_operand:DI 1 "register_operand" "r")
2214        (unspec:DI [(match_operand:DI 2 "label_ref_operand" "")
2215                    (match_operand:DI 3 "" "")] UNSPEC_MOVE_PIC_LABEL)))]
2216  "TARGET_ARCH64 && flag_pic"
2217  "or\t%1, %%lo(%a3-(%a2-.)), %0")
2218
2219;; SPARC-v9 code model support insns.  See sparc_emit_set_symbolic_const64
2220;; in sparc.c to see what is going on here... PIC stuff comes first.
2221
2222(define_insn "movdi_lo_sum_pic"
2223  [(set (match_operand:DI 0 "register_operand" "=r")
2224        (lo_sum:DI (match_operand:DI 1 "register_operand" "r")
2225                   (unspec:DI [(match_operand:DI 2 "immediate_operand" "in")] UNSPEC_MOVE_PIC)))]
2226  "TARGET_ARCH64 && flag_pic"
2227  "or\t%1, %%lo(%a2), %0")
2228
2229(define_insn "movdi_high_pic"
2230  [(set (match_operand:DI 0 "register_operand" "=r")
2231        (high:DI (unspec:DI [(match_operand 1 "" "")] UNSPEC_MOVE_PIC)))]
2232  "TARGET_ARCH64 && flag_pic && check_pic (1)"
2233  "sethi\t%%hi(%a1), %0")
2234
2235(define_insn "*sethi_di_medlow_embmedany_pic"
2236  [(set (match_operand:DI 0 "register_operand" "=r")
2237        (high:DI (match_operand:DI 1 "sp64_medium_pic_operand" "")))]
2238  "(TARGET_CM_MEDLOW || TARGET_CM_EMBMEDANY) && check_pic (1)"
2239  "sethi\t%%hi(%a1), %0")
2240
2241(define_insn "*sethi_di_medlow"
2242  [(set (match_operand:DI 0 "register_operand" "=r")
2243        (high:DI (match_operand:DI 1 "symbolic_operand" "")))]
2244  "TARGET_CM_MEDLOW && check_pic (1)"
2245  "sethi\t%%hi(%a1), %0")
2246
2247(define_insn "*losum_di_medlow"
2248  [(set (match_operand:DI 0 "register_operand" "=r")
2249        (lo_sum:DI (match_operand:DI 1 "register_operand" "r")
2250                   (match_operand:DI 2 "symbolic_operand" "")))]
2251  "TARGET_CM_MEDLOW"
2252  "or\t%1, %%lo(%a2), %0")
2253
2254(define_insn "seth44"
2255  [(set (match_operand:DI 0 "register_operand" "=r")
2256        (high:DI (unspec:DI [(match_operand:DI 1 "symbolic_operand" "")] UNSPEC_SETH44)))]
2257  "TARGET_CM_MEDMID"
2258  "sethi\t%%h44(%a1), %0")
2259
2260(define_insn "setm44"
2261  [(set (match_operand:DI 0 "register_operand" "=r")
2262        (lo_sum:DI (match_operand:DI 1 "register_operand" "r")
2263                   (unspec:DI [(match_operand:DI 2 "symbolic_operand" "")] UNSPEC_SETM44)))]
2264  "TARGET_CM_MEDMID"
2265  "or\t%1, %%m44(%a2), %0")
2266
2267(define_insn "setl44"
2268  [(set (match_operand:DI 0 "register_operand" "=r")
2269        (lo_sum:DI (match_operand:DI 1 "register_operand" "r")
2270                   (match_operand:DI 2 "symbolic_operand" "")))]
2271  "TARGET_CM_MEDMID"
2272  "or\t%1, %%l44(%a2), %0")
2273
2274(define_insn "sethh"
2275  [(set (match_operand:DI 0 "register_operand" "=r")
2276        (high:DI (unspec:DI [(match_operand:DI 1 "symbolic_operand" "")] UNSPEC_SETHH)))]
2277  "TARGET_CM_MEDANY"
2278  "sethi\t%%hh(%a1), %0")
2279
2280(define_insn "setlm"
2281  [(set (match_operand:DI 0 "register_operand" "=r")
2282        (high:DI (unspec:DI [(match_operand:DI 1 "symbolic_operand" "")] UNSPEC_SETLM)))]
2283  "TARGET_CM_MEDANY"
2284  "sethi\t%%lm(%a1), %0")
2285
2286(define_insn "sethm"
2287  [(set (match_operand:DI 0 "register_operand" "=r")
2288        (lo_sum:DI (match_operand:DI 1 "register_operand" "r")
2289                   (unspec:DI [(match_operand:DI 2 "symbolic_operand" "")] UNSPEC_EMB_SETHM)))]
2290  "TARGET_CM_MEDANY"
2291  "or\t%1, %%hm(%a2), %0")
2292
2293(define_insn "setlo"
2294  [(set (match_operand:DI 0 "register_operand" "=r")
2295        (lo_sum:DI (match_operand:DI 1 "register_operand" "r")
2296                   (match_operand:DI 2 "symbolic_operand" "")))]
2297  "TARGET_CM_MEDANY"
2298  "or\t%1, %%lo(%a2), %0")
2299
2300(define_insn "embmedany_sethi"
2301  [(set (match_operand:DI 0 "register_operand" "=r")
2302        (high:DI (unspec:DI [(match_operand:DI 1 "data_segment_operand" "")] UNSPEC_EMB_HISUM)))]
2303  "TARGET_CM_EMBMEDANY && check_pic (1)"
2304  "sethi\t%%hi(%a1), %0")
2305
2306(define_insn "embmedany_losum"
2307  [(set (match_operand:DI 0 "register_operand" "=r")
2308        (lo_sum:DI (match_operand:DI 1 "register_operand" "r")
2309                   (match_operand:DI 2 "data_segment_operand" "")))]
2310  "TARGET_CM_EMBMEDANY"
2311  "add\t%1, %%lo(%a2), %0")
2312
2313(define_insn "embmedany_brsum"
2314  [(set (match_operand:DI 0 "register_operand" "=r")
2315        (unspec:DI [(match_operand:DI 1 "register_operand" "r")] UNSPEC_EMB_HISUM))]
2316  "TARGET_CM_EMBMEDANY"
2317  "add\t%1, %_, %0")
2318
2319(define_insn "embmedany_textuhi"
2320  [(set (match_operand:DI 0 "register_operand" "=r")
2321        (high:DI (unspec:DI [(match_operand:DI 1 "text_segment_operand" "")] UNSPEC_EMB_TEXTUHI)))]
2322  "TARGET_CM_EMBMEDANY && check_pic (1)"
2323  "sethi\t%%uhi(%a1), %0")
2324
2325(define_insn "embmedany_texthi"
2326  [(set (match_operand:DI 0 "register_operand" "=r")
2327        (high:DI (unspec:DI [(match_operand:DI 1 "text_segment_operand" "")] UNSPEC_EMB_TEXTHI)))]
2328  "TARGET_CM_EMBMEDANY && check_pic (1)"
2329  "sethi\t%%hi(%a1), %0")
2330
2331(define_insn "embmedany_textulo"
2332  [(set (match_operand:DI 0 "register_operand" "=r")
2333        (lo_sum:DI (match_operand:DI 1 "register_operand" "r")
2334                   (unspec:DI [(match_operand:DI 2 "text_segment_operand" "")] UNSPEC_EMB_TEXTULO)))]
2335  "TARGET_CM_EMBMEDANY"
2336  "or\t%1, %%ulo(%a2), %0")
2337
2338(define_insn "embmedany_textlo"
2339  [(set (match_operand:DI 0 "register_operand" "=r")
2340        (lo_sum:DI (match_operand:DI 1 "register_operand" "r")
2341                   (match_operand:DI 2 "text_segment_operand" "")))]
2342  "TARGET_CM_EMBMEDANY"
2343  "or\t%1, %%lo(%a2), %0")
2344
2345;; Now some patterns to help reload out a bit.
2346(define_expand "reload_indi"
2347  [(parallel [(match_operand:DI 0 "register_operand" "=r")
2348              (match_operand:DI 1 "immediate_operand" "")
2349              (match_operand:TI 2 "register_operand" "=&r")])]
2350  "(TARGET_CM_MEDANY
2351    || TARGET_CM_EMBMEDANY)
2352   && ! flag_pic"
2353{
2354  sparc_emit_set_symbolic_const64 (operands[0], operands[1], operands[2]);
2355  DONE;
2356})
2357
2358(define_expand "reload_outdi"
2359  [(parallel [(match_operand:DI 0 "register_operand" "=r")
2360              (match_operand:DI 1 "immediate_operand" "")
2361              (match_operand:TI 2 "register_operand" "=&r")])]
2362  "(TARGET_CM_MEDANY
2363    || TARGET_CM_EMBMEDANY)
2364   && ! flag_pic"
2365{
2366  sparc_emit_set_symbolic_const64 (operands[0], operands[1], operands[2]);
2367  DONE;
2368})
2369
2370;; Split up putting CONSTs and REGs into DI regs when !arch64
2371(define_split
2372  [(set (match_operand:DI 0 "register_operand" "")
2373        (match_operand:DI 1 "const_int_operand" ""))]
2374  "! TARGET_ARCH64 && reload_completed"
2375  [(clobber (const_int 0))]
2376{
2377#if HOST_BITS_PER_WIDE_INT == 32
2378  emit_insn (gen_movsi (gen_highpart (SImode, operands[0]),
2379			(INTVAL (operands[1]) < 0) ?
2380			constm1_rtx :
2381			const0_rtx));
2382  emit_insn (gen_movsi (gen_lowpart (SImode, operands[0]),
2383			operands[1]));
2384#else
2385  unsigned int low, high;
2386
2387  low = trunc_int_for_mode (INTVAL (operands[1]), SImode);
2388  high = trunc_int_for_mode (INTVAL (operands[1]) >> 32, SImode);
2389  emit_insn (gen_movsi (gen_highpart (SImode, operands[0]), GEN_INT (high)));
2390
2391  /* Slick... but this trick loses if this subreg constant part
2392     can be done in one insn.  */
2393  if (low == high && (low & 0x3ff) != 0 && low + 0x1000 >= 0x2000)
2394    emit_insn (gen_movsi (gen_lowpart (SImode, operands[0]),
2395			  gen_highpart (SImode, operands[0])));
2396  else
2397    emit_insn (gen_movsi (gen_lowpart (SImode, operands[0]), GEN_INT (low)));
2398#endif
2399  DONE;
2400})
2401
2402(define_split
2403  [(set (match_operand:DI 0 "register_operand" "")
2404        (match_operand:DI 1 "const_double_operand" ""))]
2405  "reload_completed
2406   && (! TARGET_V9
2407       || (! TARGET_ARCH64
2408           && ((GET_CODE (operands[0]) == REG
2409                && REGNO (operands[0]) < 32)
2410               || (GET_CODE (operands[0]) == SUBREG
2411                   && GET_CODE (SUBREG_REG (operands[0])) == REG
2412                   && REGNO (SUBREG_REG (operands[0])) < 32))))"
2413  [(clobber (const_int 0))]
2414{
2415  emit_insn (gen_movsi (gen_highpart (SImode, operands[0]),
2416			GEN_INT (CONST_DOUBLE_HIGH (operands[1]))));
2417
2418  /* Slick... but this trick loses if this subreg constant part
2419     can be done in one insn.  */
2420  if (CONST_DOUBLE_LOW (operands[1]) == CONST_DOUBLE_HIGH (operands[1])
2421      && !(SPARC_SETHI32_P (CONST_DOUBLE_HIGH (operands[1]))
2422	   || SPARC_SIMM13_P (CONST_DOUBLE_HIGH (operands[1]))))
2423    {
2424      emit_insn (gen_movsi (gen_lowpart (SImode, operands[0]),
2425			    gen_highpart (SImode, operands[0])));
2426    }
2427  else
2428    {
2429      emit_insn (gen_movsi (gen_lowpart (SImode, operands[0]),
2430			    GEN_INT (CONST_DOUBLE_LOW (operands[1]))));
2431    }
2432  DONE;
2433})
2434
2435(define_split
2436  [(set (match_operand:DI 0 "register_operand" "")
2437        (match_operand:DI 1 "register_operand" ""))]
2438  "reload_completed
2439   && (! TARGET_V9
2440       || (! TARGET_ARCH64
2441           && ((GET_CODE (operands[0]) == REG
2442                && REGNO (operands[0]) < 32)
2443               || (GET_CODE (operands[0]) == SUBREG
2444                   && GET_CODE (SUBREG_REG (operands[0])) == REG
2445                   && REGNO (SUBREG_REG (operands[0])) < 32))))"
2446  [(clobber (const_int 0))]
2447{
2448  rtx set_dest = operands[0];
2449  rtx set_src = operands[1];
2450  rtx dest1, dest2;
2451  rtx src1, src2;
2452
2453  dest1 = gen_highpart (SImode, set_dest);
2454  dest2 = gen_lowpart (SImode, set_dest);
2455  src1 = gen_highpart (SImode, set_src);
2456  src2 = gen_lowpart (SImode, set_src);
2457
2458  /* Now emit using the real source and destination we found, swapping
2459     the order if we detect overlap.  */
2460  if (reg_overlap_mentioned_p (dest1, src2))
2461    {
2462      emit_insn (gen_movsi (dest2, src2));
2463      emit_insn (gen_movsi (dest1, src1));
2464    }
2465  else
2466    {
2467      emit_insn (gen_movsi (dest1, src1));
2468      emit_insn (gen_movsi (dest2, src2));
2469    }
2470  DONE;
2471})
2472
2473;; Now handle the cases of memory moves from/to non-even
2474;; DI mode register pairs.
2475(define_split
2476  [(set (match_operand:DI 0 "register_operand" "")
2477        (match_operand:DI 1 "memory_operand" ""))]
2478  "(! TARGET_ARCH64
2479    && reload_completed
2480    && sparc_splitdi_legitimate (operands[0], operands[1]))"
2481  [(clobber (const_int 0))]
2482{
2483  rtx word0 = adjust_address (operands[1], SImode, 0);
2484  rtx word1 = adjust_address (operands[1], SImode, 4);
2485  rtx high_part = gen_highpart (SImode, operands[0]);
2486  rtx low_part = gen_lowpart (SImode, operands[0]);
2487
2488  if (reg_overlap_mentioned_p (high_part, word1))
2489    {
2490      emit_insn (gen_movsi (low_part, word1));
2491      emit_insn (gen_movsi (high_part, word0));
2492    }
2493  else
2494    {
2495      emit_insn (gen_movsi (high_part, word0));
2496      emit_insn (gen_movsi (low_part, word1));
2497    }
2498  DONE;
2499})
2500
2501(define_split
2502  [(set (match_operand:DI 0 "memory_operand" "")
2503        (match_operand:DI 1 "register_operand" ""))]
2504  "(! TARGET_ARCH64
2505    && reload_completed
2506    && sparc_splitdi_legitimate (operands[1], operands[0]))"
2507  [(clobber (const_int 0))]
2508{
2509  emit_insn (gen_movsi (adjust_address (operands[0], SImode, 0),
2510			gen_highpart (SImode, operands[1])));
2511  emit_insn (gen_movsi (adjust_address (operands[0], SImode, 4),
2512			gen_lowpart (SImode, operands[1])));
2513  DONE;
2514})
2515
2516(define_split
2517  [(set (match_operand:DI 0 "memory_operand" "")
2518        (const_int 0))]
2519  "reload_completed
2520   && (! TARGET_V9
2521       || (! TARGET_ARCH64
2522	   && ! mem_min_alignment (operands[0], 8)))
2523   && offsettable_memref_p (operands[0])"
2524  [(clobber (const_int 0))]
2525{
2526  emit_insn (gen_movsi (adjust_address (operands[0], SImode, 0), const0_rtx));
2527  emit_insn (gen_movsi (adjust_address (operands[0], SImode, 4), const0_rtx));
2528  DONE;
2529})
2530
2531;; Floating point move insns
2532
2533(define_insn "*movsf_insn_novis"
2534  [(set (match_operand:SF 0 "nonimmediate_operand" "=f,*r,*r,*r,*r,*r,f,m,m")
2535	(match_operand:SF 1 "input_operand"         "f,G,Q,*rR,S,m,m,f,*rG"))]
2536  "(TARGET_FPU && ! TARGET_VIS)
2537   && (register_operand (operands[0], SFmode)
2538       || register_operand (operands[1], SFmode)
2539       || fp_zero_operand (operands[1], SFmode))"
2540{
2541  if (GET_CODE (operands[1]) == CONST_DOUBLE
2542      && (which_alternative == 2
2543          || which_alternative == 3
2544          || which_alternative == 4))
2545    {
2546      REAL_VALUE_TYPE r;
2547      long i;
2548
2549      REAL_VALUE_FROM_CONST_DOUBLE (r, operands[1]);
2550      REAL_VALUE_TO_TARGET_SINGLE (r, i);
2551      operands[1] = GEN_INT (i);
2552    }
2553
2554  switch (which_alternative)
2555    {
2556    case 0:
2557      return "fmovs\t%1, %0";
2558    case 1:
2559      return "clr\t%0";
2560    case 2:
2561      return "sethi\t%%hi(%a1), %0";
2562    case 3:
2563      return "mov\t%1, %0";
2564    case 4:
2565      return "#";
2566    case 5:
2567    case 6:
2568      return "ld\t%1, %0";
2569    case 7:
2570    case 8:
2571      return "st\t%r1, %0";
2572    default:
2573      abort();
2574    }
2575}
2576  [(set_attr "type" "fpmove,*,*,*,*,load,fpload,fpstore,store")])
2577
2578(define_insn "*movsf_insn_vis"
2579  [(set (match_operand:SF 0 "nonimmediate_operand" "=f,f,*r,*r,*r,*r,*r,f,m,m")
2580	(match_operand:SF 1 "input_operand"         "f,G,G,Q,*rR,S,m,m,f,*rG"))]
2581  "(TARGET_FPU && TARGET_VIS)
2582   && (register_operand (operands[0], SFmode)
2583       || register_operand (operands[1], SFmode)
2584       || fp_zero_operand (operands[1], SFmode))"
2585{
2586  if (GET_CODE (operands[1]) == CONST_DOUBLE
2587      && (which_alternative == 3
2588          || which_alternative == 4
2589          || which_alternative == 5))
2590    {
2591      REAL_VALUE_TYPE r;
2592      long i;
2593
2594      REAL_VALUE_FROM_CONST_DOUBLE (r, operands[1]);
2595      REAL_VALUE_TO_TARGET_SINGLE (r, i);
2596      operands[1] = GEN_INT (i);
2597    }
2598
2599  switch (which_alternative)
2600    {
2601    case 0:
2602      return "fmovs\t%1, %0";
2603    case 1:
2604      return "fzeros\t%0";
2605    case 2:
2606      return "clr\t%0";
2607    case 3:
2608      return "sethi\t%%hi(%a1), %0";
2609    case 4:
2610      return "mov\t%1, %0";
2611    case 5:
2612      return "#";
2613    case 6:
2614    case 7:
2615      return "ld\t%1, %0";
2616    case 8:
2617    case 9:
2618      return "st\t%r1, %0";
2619    default:
2620      abort();
2621    }
2622}
2623  [(set_attr "type" "fpmove,fpmove,*,*,*,*,load,fpload,fpstore,store")])
2624
2625;; Exactly the same as above, except that all `f' cases are deleted.
2626;; This is necessary to prevent reload from ever trying to use a `f' reg
2627;; when -mno-fpu.
2628
2629(define_insn "*movsf_no_f_insn"
2630  [(set (match_operand:SF 0 "nonimmediate_operand" "=r,r,r,r,r,m")
2631	(match_operand:SF 1 "input_operand"    "G,Q,rR,S,m,rG"))]
2632  "! TARGET_FPU
2633   && (register_operand (operands[0], SFmode)
2634       || register_operand (operands[1], SFmode)
2635       || fp_zero_operand (operands[1], SFmode))"
2636{
2637  if (GET_CODE (operands[1]) == CONST_DOUBLE
2638      && (which_alternative == 1
2639          || which_alternative == 2
2640          || which_alternative == 3))
2641    {
2642      REAL_VALUE_TYPE r;
2643      long i;
2644
2645      REAL_VALUE_FROM_CONST_DOUBLE (r, operands[1]);
2646      REAL_VALUE_TO_TARGET_SINGLE (r, i);
2647      operands[1] = GEN_INT (i);
2648    }
2649
2650  switch (which_alternative)
2651    {
2652    case 0:
2653      return "clr\t%0";
2654    case 1:
2655      return "sethi\t%%hi(%a1), %0";
2656    case 2:
2657      return "mov\t%1, %0";
2658    case 3:
2659      return "#";
2660    case 4:
2661      return "ld\t%1, %0";
2662    case 5:
2663      return "st\t%r1, %0";
2664    default:
2665      abort();
2666    }
2667}
2668  [(set_attr "type" "*,*,*,*,load,store")])
2669
2670(define_insn "*movsf_lo_sum"
2671  [(set (match_operand:SF 0 "register_operand" "=r")
2672        (lo_sum:SF (match_operand:SF 1 "register_operand" "r")
2673                   (match_operand:SF 2 "const_double_operand" "S")))]
2674  "fp_high_losum_p (operands[2])"
2675{
2676  REAL_VALUE_TYPE r;
2677  long i;
2678
2679  REAL_VALUE_FROM_CONST_DOUBLE (r, operands[2]);
2680  REAL_VALUE_TO_TARGET_SINGLE (r, i);
2681  operands[2] = GEN_INT (i);
2682  return "or\t%1, %%lo(%a2), %0";
2683})
2684
2685(define_insn "*movsf_high"
2686  [(set (match_operand:SF 0 "register_operand" "=r")
2687        (high:SF (match_operand:SF 1 "const_double_operand" "S")))]
2688  "fp_high_losum_p (operands[1])"
2689{
2690  REAL_VALUE_TYPE r;
2691  long i;
2692
2693  REAL_VALUE_FROM_CONST_DOUBLE (r, operands[1]);
2694  REAL_VALUE_TO_TARGET_SINGLE (r, i);
2695  operands[1] = GEN_INT (i);
2696  return "sethi\t%%hi(%1), %0";
2697})
2698
2699(define_split
2700  [(set (match_operand:SF 0 "register_operand" "")
2701        (match_operand:SF 1 "const_double_operand" ""))]
2702  "fp_high_losum_p (operands[1])
2703   && (GET_CODE (operands[0]) == REG
2704       && REGNO (operands[0]) < 32)"
2705  [(set (match_dup 0) (high:SF (match_dup 1)))
2706   (set (match_dup 0) (lo_sum:SF (match_dup 0) (match_dup 1)))])
2707
2708(define_expand "movsf"
2709  [(set (match_operand:SF 0 "general_operand" "")
2710	(match_operand:SF 1 "general_operand" ""))]
2711  ""
2712{
2713  /* Force SFmode constants into memory.  */
2714  if (GET_CODE (operands[0]) == REG
2715      && CONSTANT_P (operands[1]))
2716    {
2717      /* emit_group_store will send such bogosity to us when it is
2718         not storing directly into memory.  So fix this up to avoid
2719         crashes in output_constant_pool.  */
2720      if (operands [1] == const0_rtx)
2721        operands[1] = CONST0_RTX (SFmode);
2722
2723      if (TARGET_VIS && fp_zero_operand (operands[1], SFmode))
2724	goto movsf_is_ok;
2725
2726      /* We are able to build any SF constant in integer registers
2727	 with at most 2 instructions.  */
2728      if (REGNO (operands[0]) < 32)
2729	goto movsf_is_ok;
2730
2731      operands[1] = validize_mem (force_const_mem (GET_MODE (operands[0]),
2732                                                   operands[1]));
2733    }
2734
2735  /* Handle sets of MEM first.  */
2736  if (GET_CODE (operands[0]) == MEM)
2737    {
2738      if (register_operand (operands[1], SFmode)
2739	  || fp_zero_operand (operands[1], SFmode))
2740	goto movsf_is_ok;
2741
2742      if (! reload_in_progress)
2743	{
2744	  operands[0] = validize_mem (operands[0]);
2745	  operands[1] = force_reg (SFmode, operands[1]);
2746	}
2747    }
2748
2749  /* Fixup PIC cases.  */
2750  if (flag_pic)
2751    {
2752      if (CONSTANT_P (operands[1])
2753	  && pic_address_needs_scratch (operands[1]))
2754	operands[1] = legitimize_pic_address (operands[1], SFmode, 0);
2755
2756      if (symbolic_operand (operands[1], SFmode))
2757	{
2758	  operands[1] = legitimize_pic_address (operands[1],
2759						SFmode,
2760						(reload_in_progress ?
2761						 operands[0] :
2762						 NULL_RTX));
2763	}
2764    }
2765
2766 movsf_is_ok:
2767  ;
2768})
2769
2770(define_expand "movdf"
2771  [(set (match_operand:DF 0 "general_operand" "")
2772	(match_operand:DF 1 "general_operand" ""))]
2773  ""
2774{
2775  /* Force DFmode constants into memory.  */
2776  if (GET_CODE (operands[0]) == REG
2777      && CONSTANT_P (operands[1]))
2778    {
2779      /* emit_group_store will send such bogosity to us when it is
2780         not storing directly into memory.  So fix this up to avoid
2781         crashes in output_constant_pool.  */
2782      if (operands [1] == const0_rtx)
2783        operands[1] = CONST0_RTX (DFmode);
2784
2785      if ((TARGET_VIS || REGNO (operands[0]) < 32)
2786	  && fp_zero_operand (operands[1], DFmode))
2787	goto movdf_is_ok;
2788
2789      /* We are able to build any DF constant in integer registers.  */
2790      if (REGNO (operands[0]) < 32
2791	  && (reload_completed || reload_in_progress))
2792	goto movdf_is_ok;
2793
2794      operands[1] = validize_mem (force_const_mem (GET_MODE (operands[0]),
2795                                                   operands[1]));
2796    }
2797
2798  /* Handle MEM cases first.  */
2799  if (GET_CODE (operands[0]) == MEM)
2800    {
2801      if (register_operand (operands[1], DFmode)
2802	  || fp_zero_operand (operands[1], DFmode))
2803	goto movdf_is_ok;
2804
2805      if (! reload_in_progress)
2806	{
2807	  operands[0] = validize_mem (operands[0]);
2808	  operands[1] = force_reg (DFmode, operands[1]);
2809	}
2810    }
2811
2812  /* Fixup PIC cases.  */
2813  if (flag_pic)
2814    {
2815      if (CONSTANT_P (operands[1])
2816	  && pic_address_needs_scratch (operands[1]))
2817	operands[1] = legitimize_pic_address (operands[1], DFmode, 0);
2818
2819      if (symbolic_operand (operands[1], DFmode))
2820	{
2821	  operands[1] = legitimize_pic_address (operands[1],
2822						DFmode,
2823						(reload_in_progress ?
2824						 operands[0] :
2825						 NULL_RTX));
2826	}
2827    }
2828
2829 movdf_is_ok:
2830  ;
2831})
2832
2833;; Be careful, fmovd does not exist when !v9.
2834(define_insn "*movdf_insn_sp32"
2835  [(set (match_operand:DF 0 "nonimmediate_operand" "=e,W,U,T,o,e,*r,o,e,o")
2836	(match_operand:DF 1 "input_operand"    "W#F,e,T,U,G,e,*rFo,*r,o#F,e"))]
2837  "TARGET_FPU
2838   && ! TARGET_V9
2839   && (register_operand (operands[0], DFmode)
2840       || register_operand (operands[1], DFmode)
2841       || fp_zero_operand (operands[1], DFmode))"
2842  "@
2843  ldd\t%1, %0
2844  std\t%1, %0
2845  ldd\t%1, %0
2846  std\t%1, %0
2847  #
2848  #
2849  #
2850  #
2851  #
2852  #"
2853 [(set_attr "type" "fpload,fpstore,load,store,*,*,*,*,*,*")
2854  (set_attr "length" "*,*,*,*,2,2,2,2,2,2")])
2855
2856(define_insn "*movdf_no_e_insn_sp32"
2857  [(set (match_operand:DF 0 "nonimmediate_operand" "=U,T,o,r,o")
2858	(match_operand:DF 1 "input_operand"    "T,U,G,ro,r"))]
2859  "! TARGET_FPU
2860   && ! TARGET_V9
2861   && ! TARGET_ARCH64
2862   && (register_operand (operands[0], DFmode)
2863       || register_operand (operands[1], DFmode)
2864       || fp_zero_operand (operands[1], DFmode))"
2865  "@
2866  ldd\t%1, %0
2867  std\t%1, %0
2868  #
2869  #
2870  #"
2871  [(set_attr "type" "load,store,*,*,*")
2872   (set_attr "length" "*,*,2,2,2")])
2873
2874(define_insn "*movdf_no_e_insn_v9_sp32"
2875  [(set (match_operand:DF 0 "nonimmediate_operand" "=U,T,T,r,o")
2876	(match_operand:DF 1 "input_operand"    "T,U,G,ro,rG"))]
2877  "! TARGET_FPU
2878   && TARGET_V9
2879   && ! TARGET_ARCH64
2880   && (register_operand (operands[0], DFmode)
2881       || register_operand (operands[1], DFmode)
2882       || fp_zero_operand (operands[1], DFmode))"
2883  "@
2884  ldd\t%1, %0
2885  std\t%1, %0
2886  stx\t%r1, %0
2887  #
2888  #"
2889  [(set_attr "type" "load,store,store,*,*")
2890   (set_attr "length" "*,*,*,2,2")])
2891
2892;; We have available v9 double floats but not 64-bit
2893;; integer registers and no VIS.
2894(define_insn "*movdf_insn_v9only_novis"
2895  [(set (match_operand:DF 0 "nonimmediate_operand" "=e,e,T,W,U,T,f,*r,o")
2896        (match_operand:DF 1 "input_operand"    "e,W#F,G,e,T,U,o#F,*roF,*rGf"))]
2897  "TARGET_FPU
2898   && TARGET_V9
2899   && ! TARGET_VIS
2900   && ! TARGET_ARCH64
2901   && (register_operand (operands[0], DFmode)
2902       || register_operand (operands[1], DFmode)
2903       || fp_zero_operand (operands[1], DFmode))"
2904  "@
2905  fmovd\t%1, %0
2906  ldd\t%1, %0
2907  stx\t%r1, %0
2908  std\t%1, %0
2909  ldd\t%1, %0
2910  std\t%1, %0
2911  #
2912  #
2913  #"
2914  [(set_attr "type" "fpmove,load,store,store,load,store,*,*,*")
2915   (set_attr "length" "*,*,*,*,*,*,2,2,2")
2916   (set_attr "fptype" "double,*,*,*,*,*,*,*,*")])
2917
2918;; We have available v9 double floats but not 64-bit
2919;; integer registers but we have VIS.
2920(define_insn "*movdf_insn_v9only_vis"
2921  [(set (match_operand:DF 0 "nonimmediate_operand" "=e,e,e,T,W,U,T,f,*r,o")
2922        (match_operand:DF 1 "input_operand" "G,e,W#F,G,e,T,U,o#F,*roGF,*rGf"))]
2923  "TARGET_FPU
2924   && TARGET_VIS
2925   && ! TARGET_ARCH64
2926   && (register_operand (operands[0], DFmode)
2927       || register_operand (operands[1], DFmode)
2928       || fp_zero_operand (operands[1], DFmode))"
2929  "@
2930  fzero\t%0
2931  fmovd\t%1, %0
2932  ldd\t%1, %0
2933  stx\t%r1, %0
2934  std\t%1, %0
2935  ldd\t%1, %0
2936  std\t%1, %0
2937  #
2938  #
2939  #"
2940  [(set_attr "type" "fpmove,fpmove,load,store,store,load,store,*,*,*")
2941   (set_attr "length" "*,*,*,*,*,*,*,2,2,2")
2942   (set_attr "fptype" "double,double,*,*,*,*,*,*,*,*")])
2943
2944;; We have available both v9 double floats and 64-bit
2945;; integer registers. No VIS though.
2946(define_insn "*movdf_insn_sp64_novis"
2947  [(set (match_operand:DF 0 "nonimmediate_operand" "=e,e,W,*r,*r,m,*r")
2948        (match_operand:DF 1 "input_operand"    "e,W#F,e,*rG,m,*rG,F"))]
2949  "TARGET_FPU
2950   && ! TARGET_VIS
2951   && TARGET_ARCH64
2952   && (register_operand (operands[0], DFmode)
2953       || register_operand (operands[1], DFmode)
2954       || fp_zero_operand (operands[1], DFmode))"
2955  "@
2956  fmovd\t%1, %0
2957  ldd\t%1, %0
2958  std\t%1, %0
2959  mov\t%r1, %0
2960  ldx\t%1, %0
2961  stx\t%r1, %0
2962  #"
2963  [(set_attr "type" "fpmove,load,store,*,load,store,*")
2964   (set_attr "length" "*,*,*,*,*,*,2")
2965   (set_attr "fptype" "double,*,*,*,*,*,*")])
2966
2967;; We have available both v9 double floats and 64-bit
2968;; integer registers. And we have VIS.
2969(define_insn "*movdf_insn_sp64_vis"
2970  [(set (match_operand:DF 0 "nonimmediate_operand" "=e,e,e,W,*r,*r,m,*r")
2971        (match_operand:DF 1 "input_operand"    "G,e,W#F,e,*rG,m,*rG,F"))]
2972  "TARGET_FPU
2973   && TARGET_VIS
2974   && TARGET_ARCH64
2975   && (register_operand (operands[0], DFmode)
2976       || register_operand (operands[1], DFmode)
2977       || fp_zero_operand (operands[1], DFmode))"
2978  "@
2979  fzero\t%0
2980  fmovd\t%1, %0
2981  ldd\t%1, %0
2982  std\t%1, %0
2983  mov\t%r1, %0
2984  ldx\t%1, %0
2985  stx\t%r1, %0
2986  #"
2987  [(set_attr "type" "fpmove,fpmove,load,store,*,load,store,*")
2988   (set_attr "length" "*,*,*,*,*,*,*,2")
2989   (set_attr "fptype" "double,double,*,*,*,*,*,*")])
2990
2991(define_insn "*movdf_no_e_insn_sp64"
2992  [(set (match_operand:DF 0 "nonimmediate_operand" "=r,r,m")
2993        (match_operand:DF 1 "input_operand"    "r,m,rG"))]
2994  "! TARGET_FPU
2995   && TARGET_ARCH64
2996   && (register_operand (operands[0], DFmode)
2997       || register_operand (operands[1], DFmode)
2998       || fp_zero_operand (operands[1], DFmode))"
2999  "@
3000  mov\t%1, %0
3001  ldx\t%1, %0
3002  stx\t%r1, %0"
3003  [(set_attr "type" "*,load,store")])
3004
3005(define_split
3006  [(set (match_operand:DF 0 "register_operand" "")
3007        (match_operand:DF 1 "const_double_operand" ""))]
3008  "TARGET_FPU
3009   && (GET_CODE (operands[0]) == REG
3010       && REGNO (operands[0]) < 32)
3011   && ! fp_zero_operand(operands[1], DFmode)
3012   && reload_completed"
3013  [(clobber (const_int 0))]
3014{
3015  REAL_VALUE_TYPE r;
3016  long l[2];
3017
3018  REAL_VALUE_FROM_CONST_DOUBLE (r, operands[1]);
3019  REAL_VALUE_TO_TARGET_DOUBLE (r, l);
3020  operands[0] = gen_rtx_raw_REG (DImode, REGNO (operands[0]));
3021
3022  if (TARGET_ARCH64)
3023    {
3024#if HOST_BITS_PER_WIDE_INT == 64
3025      HOST_WIDE_INT val;
3026
3027      val = ((HOST_WIDE_INT)(unsigned long)l[1] |
3028             ((HOST_WIDE_INT)(unsigned long)l[0] << 32));
3029      emit_insn (gen_movdi (operands[0], GEN_INT (val)));
3030#else
3031      emit_insn (gen_movdi (operands[0],
3032                            immed_double_const (l[1], l[0], DImode)));
3033#endif
3034    }
3035  else
3036    {
3037      emit_insn (gen_movsi (gen_highpart (SImode, operands[0]),
3038			    GEN_INT (l[0])));
3039
3040      /* Slick... but this trick loses if this subreg constant part
3041         can be done in one insn.  */
3042      if (l[1] == l[0]
3043          && !(SPARC_SETHI32_P (l[0])
3044	       || SPARC_SIMM13_P (l[0])))
3045        {
3046          emit_insn (gen_movsi (gen_lowpart (SImode, operands[0]),
3047			        gen_highpart (SImode, operands[0])));
3048        }
3049      else
3050        {
3051          emit_insn (gen_movsi (gen_lowpart (SImode, operands[0]),
3052			        GEN_INT (l[1])));
3053        }
3054    }
3055  DONE;
3056})
3057
3058;; Ok, now the splits to handle all the multi insn and
3059;; mis-aligned memory address cases.
3060;; In these splits please take note that we must be
3061;; careful when V9 but not ARCH64 because the integer
3062;; register DFmode cases must be handled.
3063(define_split
3064  [(set (match_operand:DF 0 "register_operand" "")
3065        (match_operand:DF 1 "register_operand" ""))]
3066  "(! TARGET_V9
3067    || (! TARGET_ARCH64
3068        && ((GET_CODE (operands[0]) == REG
3069             && REGNO (operands[0]) < 32)
3070            || (GET_CODE (operands[0]) == SUBREG
3071                && GET_CODE (SUBREG_REG (operands[0])) == REG
3072                && REGNO (SUBREG_REG (operands[0])) < 32))))
3073   && reload_completed"
3074  [(clobber (const_int 0))]
3075{
3076  rtx set_dest = operands[0];
3077  rtx set_src = operands[1];
3078  rtx dest1, dest2;
3079  rtx src1, src2;
3080
3081  dest1 = gen_highpart (SFmode, set_dest);
3082  dest2 = gen_lowpart (SFmode, set_dest);
3083  src1 = gen_highpart (SFmode, set_src);
3084  src2 = gen_lowpart (SFmode, set_src);
3085
3086  /* Now emit using the real source and destination we found, swapping
3087     the order if we detect overlap.  */
3088  if (reg_overlap_mentioned_p (dest1, src2))
3089    {
3090      emit_insn (gen_movsf (dest2, src2));
3091      emit_insn (gen_movsf (dest1, src1));
3092    }
3093  else
3094    {
3095      emit_insn (gen_movsf (dest1, src1));
3096      emit_insn (gen_movsf (dest2, src2));
3097    }
3098  DONE;
3099})
3100
3101(define_split
3102  [(set (match_operand:DF 0 "register_operand" "")
3103	(match_operand:DF 1 "memory_operand" ""))]
3104  "reload_completed
3105   && ! TARGET_ARCH64
3106   && (((REGNO (operands[0]) % 2) != 0)
3107       || ! mem_min_alignment (operands[1], 8))
3108   && offsettable_memref_p (operands[1])"
3109  [(clobber (const_int 0))]
3110{
3111  rtx word0 = adjust_address (operands[1], SFmode, 0);
3112  rtx word1 = adjust_address (operands[1], SFmode, 4);
3113
3114  if (reg_overlap_mentioned_p (gen_highpart (SFmode, operands[0]), word1))
3115    {
3116      emit_insn (gen_movsf (gen_lowpart (SFmode, operands[0]),
3117			    word1));
3118      emit_insn (gen_movsf (gen_highpart (SFmode, operands[0]),
3119			    word0));
3120    }
3121  else
3122    {
3123      emit_insn (gen_movsf (gen_highpart (SFmode, operands[0]),
3124			    word0));
3125      emit_insn (gen_movsf (gen_lowpart (SFmode, operands[0]),
3126			    word1));
3127    }
3128  DONE;
3129})
3130
3131(define_split
3132  [(set (match_operand:DF 0 "memory_operand" "")
3133	(match_operand:DF 1 "register_operand" ""))]
3134  "reload_completed
3135   && ! TARGET_ARCH64
3136   && (((REGNO (operands[1]) % 2) != 0)
3137       || ! mem_min_alignment (operands[0], 8))
3138   && offsettable_memref_p (operands[0])"
3139  [(clobber (const_int 0))]
3140{
3141  rtx word0 = adjust_address (operands[0], SFmode, 0);
3142  rtx word1 = adjust_address (operands[0], SFmode, 4);
3143
3144  emit_insn (gen_movsf (word0,
3145			gen_highpart (SFmode, operands[1])));
3146  emit_insn (gen_movsf (word1,
3147			gen_lowpart (SFmode, operands[1])));
3148  DONE;
3149})
3150
3151(define_split
3152  [(set (match_operand:DF 0 "memory_operand" "")
3153        (match_operand:DF 1 "fp_zero_operand" ""))]
3154  "reload_completed
3155   && (! TARGET_V9
3156       || (! TARGET_ARCH64
3157	   && ! mem_min_alignment (operands[0], 8)))
3158   && offsettable_memref_p (operands[0])"
3159  [(clobber (const_int 0))]
3160{
3161  rtx dest1, dest2;
3162
3163  dest1 = adjust_address (operands[0], SFmode, 0);
3164  dest2 = adjust_address (operands[0], SFmode, 4);
3165
3166  emit_insn (gen_movsf (dest1, CONST0_RTX (SFmode)));
3167  emit_insn (gen_movsf (dest2, CONST0_RTX (SFmode)));
3168  DONE;
3169})
3170
3171(define_split
3172  [(set (match_operand:DF 0 "register_operand" "")
3173        (match_operand:DF 1 "fp_zero_operand" ""))]
3174  "reload_completed
3175   && ! TARGET_ARCH64
3176   && ((GET_CODE (operands[0]) == REG
3177	&& REGNO (operands[0]) < 32)
3178       || (GET_CODE (operands[0]) == SUBREG
3179	   && GET_CODE (SUBREG_REG (operands[0])) == REG
3180	   && REGNO (SUBREG_REG (operands[0])) < 32))"
3181  [(clobber (const_int 0))]
3182{
3183  rtx set_dest = operands[0];
3184  rtx dest1, dest2;
3185
3186  dest1 = gen_highpart (SFmode, set_dest);
3187  dest2 = gen_lowpart (SFmode, set_dest);
3188  emit_insn (gen_movsf (dest1, CONST0_RTX (SFmode)));
3189  emit_insn (gen_movsf (dest2, CONST0_RTX (SFmode)));
3190  DONE;
3191})
3192
3193(define_expand "movtf"
3194  [(set (match_operand:TF 0 "general_operand" "")
3195	(match_operand:TF 1 "general_operand" ""))]
3196  ""
3197{
3198  /* Force TFmode constants into memory.  */
3199  if (GET_CODE (operands[0]) == REG
3200      && CONSTANT_P (operands[1]))
3201    {
3202      /* emit_group_store will send such bogosity to us when it is
3203         not storing directly into memory.  So fix this up to avoid
3204         crashes in output_constant_pool.  */
3205      if (operands [1] == const0_rtx)
3206        operands[1] = CONST0_RTX (TFmode);
3207
3208      if (TARGET_VIS && fp_zero_operand (operands[1], TFmode))
3209	goto movtf_is_ok;
3210
3211      operands[1] = validize_mem (force_const_mem (GET_MODE (operands[0]),
3212                                                   operands[1]));
3213    }
3214
3215  /* Handle MEM cases first, note that only v9 guarentees
3216     full 16-byte alignment for quads.  */
3217  if (GET_CODE (operands[0]) == MEM)
3218    {
3219      if (register_operand (operands[1], TFmode)
3220	  || fp_zero_operand (operands[1], TFmode))
3221	goto movtf_is_ok;
3222
3223      if (! reload_in_progress)
3224	{
3225	  operands[0] = validize_mem (operands[0]);
3226	  operands[1] = force_reg (TFmode, operands[1]);
3227	}
3228    }
3229
3230  /* Fixup PIC cases.  */
3231  if (flag_pic)
3232    {
3233      if (CONSTANT_P (operands[1])
3234	  && pic_address_needs_scratch (operands[1]))
3235	operands[1] = legitimize_pic_address (operands[1], TFmode, 0);
3236
3237      if (symbolic_operand (operands[1], TFmode))
3238	{
3239	  operands[1] = legitimize_pic_address (operands[1],
3240						TFmode,
3241						(reload_in_progress ?
3242						 operands[0] :
3243						 NULL_RTX));
3244	}
3245    }
3246
3247 movtf_is_ok:
3248  ;
3249})
3250
3251;; Be careful, fmovq and {st,ld}{x,q} do not exist when !arch64 so
3252;; we must split them all.  :-(
3253(define_insn "*movtf_insn_sp32"
3254  [(set (match_operand:TF 0 "nonimmediate_operand" "=e,o,U,r")
3255	(match_operand:TF 1 "input_operand"    "oe,GeUr,o,roG"))]
3256  "TARGET_FPU
3257   && ! TARGET_VIS
3258   && ! TARGET_ARCH64
3259   && (register_operand (operands[0], TFmode)
3260       || register_operand (operands[1], TFmode)
3261       || fp_zero_operand (operands[1], TFmode))"
3262  "#"
3263  [(set_attr "length" "4")])
3264
3265(define_insn "*movtf_insn_vis_sp32"
3266  [(set (match_operand:TF 0 "nonimmediate_operand" "=e,o,U,r")
3267	(match_operand:TF 1 "input_operand"    "Goe,GeUr,o,roG"))]
3268  "TARGET_FPU
3269   && TARGET_VIS
3270   && ! TARGET_ARCH64
3271   && (register_operand (operands[0], TFmode)
3272       || register_operand (operands[1], TFmode)
3273       || fp_zero_operand (operands[1], TFmode))"
3274  "#"
3275  [(set_attr "length" "4")])
3276
3277;; Exactly the same as above, except that all `e' cases are deleted.
3278;; This is necessary to prevent reload from ever trying to use a `e' reg
3279;; when -mno-fpu.
3280
3281(define_insn "*movtf_no_e_insn_sp32"
3282  [(set (match_operand:TF 0 "nonimmediate_operand" "=o,U,o,r,o")
3283	(match_operand:TF 1 "input_operand"    "G,o,U,roG,r"))]
3284  "! TARGET_FPU
3285   && ! TARGET_ARCH64
3286   && (register_operand (operands[0], TFmode)
3287       || register_operand (operands[1], TFmode)
3288       || fp_zero_operand (operands[1], TFmode))"
3289  "#"
3290  [(set_attr "length" "4")])
3291
3292;; Now handle the float reg cases directly when arch64,
3293;; hard_quad, and proper reg number alignment are all true.
3294(define_insn "*movtf_insn_hq_sp64"
3295  [(set (match_operand:TF 0 "nonimmediate_operand" "=e,e,m,o,r")
3296        (match_operand:TF 1 "input_operand"    "e,m,e,Gr,roG"))]
3297  "TARGET_FPU
3298   && ! TARGET_VIS
3299   && TARGET_ARCH64
3300   && TARGET_HARD_QUAD
3301   && (register_operand (operands[0], TFmode)
3302       || register_operand (operands[1], TFmode)
3303       || fp_zero_operand (operands[1], TFmode))"
3304  "@
3305  fmovq\t%1, %0
3306  ldq\t%1, %0
3307  stq\t%1, %0
3308  #
3309  #"
3310  [(set_attr "type" "fpmove,fpload,fpstore,*,*")
3311   (set_attr "length" "*,*,*,2,2")])
3312
3313(define_insn "*movtf_insn_hq_vis_sp64"
3314  [(set (match_operand:TF 0 "nonimmediate_operand" "=e,e,m,eo,r,o")
3315        (match_operand:TF 1 "input_operand"    "e,m,e,G,roG,r"))]
3316  "TARGET_FPU
3317   && TARGET_VIS
3318   && TARGET_ARCH64
3319   && TARGET_HARD_QUAD
3320   && (register_operand (operands[0], TFmode)
3321       || register_operand (operands[1], TFmode)
3322       || fp_zero_operand (operands[1], TFmode))"
3323  "@
3324  fmovq\t%1, %0
3325  ldq\t%1, %0
3326  stq\t%1, %0
3327  #
3328  #
3329  #"
3330  [(set_attr "type" "fpmove,fpload,fpstore,*,*,*")
3331   (set_attr "length" "*,*,*,2,2,2")])
3332
3333;; Now we allow the integer register cases even when
3334;; only arch64 is true.
3335(define_insn "*movtf_insn_sp64"
3336  [(set (match_operand:TF 0 "nonimmediate_operand" "=e,o,r")
3337        (match_operand:TF 1 "input_operand"    "oe,Ger,orG"))]
3338  "TARGET_FPU
3339   && ! TARGET_VIS
3340   && TARGET_ARCH64
3341   && ! TARGET_HARD_QUAD
3342   && (register_operand (operands[0], TFmode)
3343       || register_operand (operands[1], TFmode)
3344       || fp_zero_operand (operands[1], TFmode))"
3345  "#"
3346  [(set_attr "length" "2")])
3347
3348(define_insn "*movtf_insn_vis_sp64"
3349  [(set (match_operand:TF 0 "nonimmediate_operand" "=e,o,r")
3350        (match_operand:TF 1 "input_operand"    "Goe,Ger,orG"))]
3351  "TARGET_FPU
3352   && TARGET_VIS
3353   && TARGET_ARCH64
3354   && ! TARGET_HARD_QUAD
3355   && (register_operand (operands[0], TFmode)
3356       || register_operand (operands[1], TFmode)
3357       || fp_zero_operand (operands[1], TFmode))"
3358  "#"
3359  [(set_attr "length" "2")])
3360
3361(define_insn "*movtf_no_e_insn_sp64"
3362  [(set (match_operand:TF 0 "nonimmediate_operand" "=r,o")
3363        (match_operand:TF 1 "input_operand"    "orG,rG"))]
3364  "! TARGET_FPU
3365   && TARGET_ARCH64
3366   && (register_operand (operands[0], TFmode)
3367       || register_operand (operands[1], TFmode)
3368       || fp_zero_operand (operands[1], TFmode))"
3369  "#"
3370  [(set_attr "length" "2")])
3371
3372;; Now all the splits to handle multi-insn TF mode moves.
3373(define_split
3374  [(set (match_operand:TF 0 "register_operand" "")
3375        (match_operand:TF 1 "register_operand" ""))]
3376  "reload_completed
3377   && (! TARGET_ARCH64
3378       || (TARGET_FPU
3379           && ! TARGET_HARD_QUAD)
3380       || ! fp_register_operand (operands[0], TFmode))"
3381  [(clobber (const_int 0))]
3382{
3383  rtx set_dest = operands[0];
3384  rtx set_src = operands[1];
3385  rtx dest1, dest2;
3386  rtx src1, src2;
3387
3388  dest1 = gen_df_reg (set_dest, 0);
3389  dest2 = gen_df_reg (set_dest, 1);
3390  src1 = gen_df_reg (set_src, 0);
3391  src2 = gen_df_reg (set_src, 1);
3392
3393  /* Now emit using the real source and destination we found, swapping
3394     the order if we detect overlap.  */
3395  if (reg_overlap_mentioned_p (dest1, src2))
3396    {
3397      emit_insn (gen_movdf (dest2, src2));
3398      emit_insn (gen_movdf (dest1, src1));
3399    }
3400  else
3401    {
3402      emit_insn (gen_movdf (dest1, src1));
3403      emit_insn (gen_movdf (dest2, src2));
3404    }
3405  DONE;
3406})
3407
3408(define_split
3409  [(set (match_operand:TF 0 "nonimmediate_operand" "")
3410        (match_operand:TF 1 "fp_zero_operand" ""))]
3411  "reload_completed"
3412  [(clobber (const_int 0))]
3413{
3414  rtx set_dest = operands[0];
3415  rtx dest1, dest2;
3416
3417  switch (GET_CODE (set_dest))
3418    {
3419    case REG:
3420      dest1 = gen_df_reg (set_dest, 0);
3421      dest2 = gen_df_reg (set_dest, 1);
3422      break;
3423    case MEM:
3424      dest1 = adjust_address (set_dest, DFmode, 0);
3425      dest2 = adjust_address (set_dest, DFmode, 8);
3426      break;
3427    default:
3428      abort ();
3429    }
3430
3431  emit_insn (gen_movdf (dest1, CONST0_RTX (DFmode)));
3432  emit_insn (gen_movdf (dest2, CONST0_RTX (DFmode)));
3433  DONE;
3434})
3435
3436(define_split
3437  [(set (match_operand:TF 0 "register_operand" "")
3438        (match_operand:TF 1 "memory_operand" ""))]
3439  "(reload_completed
3440    && offsettable_memref_p (operands[1])
3441    && (! TARGET_ARCH64
3442	|| ! TARGET_HARD_QUAD
3443	|| ! fp_register_operand (operands[0], TFmode)))"
3444  [(clobber (const_int 0))]
3445{
3446  rtx word0 = adjust_address (operands[1], DFmode, 0);
3447  rtx word1 = adjust_address (operands[1], DFmode, 8);
3448  rtx set_dest, dest1, dest2;
3449
3450  set_dest = operands[0];
3451
3452  dest1 = gen_df_reg (set_dest, 0);
3453  dest2 = gen_df_reg (set_dest, 1);
3454
3455  /* Now output, ordering such that we don't clobber any registers
3456     mentioned in the address.  */
3457  if (reg_overlap_mentioned_p (dest1, word1))
3458
3459    {
3460      emit_insn (gen_movdf (dest2, word1));
3461      emit_insn (gen_movdf (dest1, word0));
3462    }
3463  else
3464   {
3465      emit_insn (gen_movdf (dest1, word0));
3466      emit_insn (gen_movdf (dest2, word1));
3467   }
3468  DONE;
3469})
3470
3471(define_split
3472  [(set (match_operand:TF 0 "memory_operand" "")
3473	(match_operand:TF 1 "register_operand" ""))]
3474  "(reload_completed
3475    && offsettable_memref_p (operands[0])
3476    && (! TARGET_ARCH64
3477	|| ! TARGET_HARD_QUAD
3478	|| ! fp_register_operand (operands[1], TFmode)))"
3479  [(clobber (const_int 0))]
3480{
3481  rtx set_src = operands[1];
3482
3483  emit_insn (gen_movdf (adjust_address (operands[0], DFmode, 0),
3484			gen_df_reg (set_src, 0)));
3485  emit_insn (gen_movdf (adjust_address (operands[0], DFmode, 8),
3486			gen_df_reg (set_src, 1)));
3487  DONE;
3488})
3489
3490;; SPARC V9 conditional move instructions.
3491
3492;; We can handle larger constants here for some flavors, but for now we keep
3493;; it simple and only allow those constants supported by all flavors.
3494;; Note that emit_conditional_move canonicalizes operands 2,3 so that operand
3495;; 3 contains the constant if one is present, but we handle either for
3496;; generality (sparc.c puts a constant in operand 2).
3497
3498(define_expand "movqicc"
3499  [(set (match_operand:QI 0 "register_operand" "")
3500	(if_then_else:QI (match_operand 1 "comparison_operator" "")
3501			 (match_operand:QI 2 "arith10_operand" "")
3502			 (match_operand:QI 3 "arith10_operand" "")))]
3503  "TARGET_V9"
3504{
3505  enum rtx_code code = GET_CODE (operands[1]);
3506
3507  if (GET_MODE (sparc_compare_op0) == DImode
3508      && ! TARGET_ARCH64)
3509    FAIL;
3510
3511  if (sparc_compare_op1 == const0_rtx
3512      && GET_CODE (sparc_compare_op0) == REG
3513      && GET_MODE (sparc_compare_op0) == DImode
3514      && v9_regcmp_p (code))
3515    {
3516      operands[1] = gen_rtx_fmt_ee (code, DImode,
3517			     sparc_compare_op0, sparc_compare_op1);
3518    }
3519  else
3520    {
3521      rtx cc_reg = gen_compare_reg (code,
3522				    sparc_compare_op0, sparc_compare_op1);
3523      operands[1] = gen_rtx_fmt_ee (code, GET_MODE (cc_reg), cc_reg, const0_rtx);
3524    }
3525})
3526
3527(define_expand "movhicc"
3528  [(set (match_operand:HI 0 "register_operand" "")
3529	(if_then_else:HI (match_operand 1 "comparison_operator" "")
3530			 (match_operand:HI 2 "arith10_operand" "")
3531			 (match_operand:HI 3 "arith10_operand" "")))]
3532  "TARGET_V9"
3533{
3534  enum rtx_code code = GET_CODE (operands[1]);
3535
3536  if (GET_MODE (sparc_compare_op0) == DImode
3537      && ! TARGET_ARCH64)
3538    FAIL;
3539
3540  if (sparc_compare_op1 == const0_rtx
3541      && GET_CODE (sparc_compare_op0) == REG
3542      && GET_MODE (sparc_compare_op0) == DImode
3543      && v9_regcmp_p (code))
3544    {
3545      operands[1] = gen_rtx_fmt_ee (code, DImode,
3546			     sparc_compare_op0, sparc_compare_op1);
3547    }
3548  else
3549    {
3550      rtx cc_reg = gen_compare_reg (code,
3551				    sparc_compare_op0, sparc_compare_op1);
3552      operands[1] = gen_rtx_fmt_ee (code, GET_MODE (cc_reg), cc_reg, const0_rtx);
3553    }
3554})
3555
3556(define_expand "movsicc"
3557  [(set (match_operand:SI 0 "register_operand" "")
3558	(if_then_else:SI (match_operand 1 "comparison_operator" "")
3559			 (match_operand:SI 2 "arith10_operand" "")
3560			 (match_operand:SI 3 "arith10_operand" "")))]
3561  "TARGET_V9"
3562{
3563  enum rtx_code code = GET_CODE (operands[1]);
3564  enum machine_mode op0_mode = GET_MODE (sparc_compare_op0);
3565
3566  if (sparc_compare_op1 == const0_rtx
3567      && GET_CODE (sparc_compare_op0) == REG
3568      && (TARGET_ARCH64 && op0_mode == DImode && v9_regcmp_p (code)))
3569    {
3570      operands[1] = gen_rtx_fmt_ee (code, op0_mode,
3571			     sparc_compare_op0, sparc_compare_op1);
3572    }
3573  else
3574    {
3575      rtx cc_reg = gen_compare_reg (code,
3576				    sparc_compare_op0, sparc_compare_op1);
3577      operands[1] = gen_rtx_fmt_ee (code, GET_MODE (cc_reg),
3578				    cc_reg, const0_rtx);
3579    }
3580})
3581
3582(define_expand "movdicc"
3583  [(set (match_operand:DI 0 "register_operand" "")
3584	(if_then_else:DI (match_operand 1 "comparison_operator" "")
3585			 (match_operand:DI 2 "arith10_double_operand" "")
3586			 (match_operand:DI 3 "arith10_double_operand" "")))]
3587  "TARGET_ARCH64"
3588{
3589  enum rtx_code code = GET_CODE (operands[1]);
3590
3591  if (sparc_compare_op1 == const0_rtx
3592      && GET_CODE (sparc_compare_op0) == REG
3593      && GET_MODE (sparc_compare_op0) == DImode
3594      && v9_regcmp_p (code))
3595    {
3596      operands[1] = gen_rtx_fmt_ee (code, DImode,
3597			     sparc_compare_op0, sparc_compare_op1);
3598    }
3599  else
3600    {
3601      rtx cc_reg = gen_compare_reg (code,
3602				    sparc_compare_op0, sparc_compare_op1);
3603      operands[1] = gen_rtx_fmt_ee (code, GET_MODE (cc_reg),
3604				    cc_reg, const0_rtx);
3605    }
3606})
3607
3608(define_expand "movsfcc"
3609  [(set (match_operand:SF 0 "register_operand" "")
3610	(if_then_else:SF (match_operand 1 "comparison_operator" "")
3611			 (match_operand:SF 2 "register_operand" "")
3612			 (match_operand:SF 3 "register_operand" "")))]
3613  "TARGET_V9 && TARGET_FPU"
3614{
3615  enum rtx_code code = GET_CODE (operands[1]);
3616
3617  if (GET_MODE (sparc_compare_op0) == DImode
3618      && ! TARGET_ARCH64)
3619    FAIL;
3620
3621  if (sparc_compare_op1 == const0_rtx
3622      && GET_CODE (sparc_compare_op0) == REG
3623      && GET_MODE (sparc_compare_op0) == DImode
3624      && v9_regcmp_p (code))
3625    {
3626      operands[1] = gen_rtx_fmt_ee (code, DImode,
3627			     sparc_compare_op0, sparc_compare_op1);
3628    }
3629  else
3630    {
3631      rtx cc_reg = gen_compare_reg (code,
3632				    sparc_compare_op0, sparc_compare_op1);
3633      operands[1] = gen_rtx_fmt_ee (code, GET_MODE (cc_reg), cc_reg, const0_rtx);
3634    }
3635})
3636
3637(define_expand "movdfcc"
3638  [(set (match_operand:DF 0 "register_operand" "")
3639	(if_then_else:DF (match_operand 1 "comparison_operator" "")
3640			 (match_operand:DF 2 "register_operand" "")
3641			 (match_operand:DF 3 "register_operand" "")))]
3642  "TARGET_V9 && TARGET_FPU"
3643{
3644  enum rtx_code code = GET_CODE (operands[1]);
3645
3646  if (GET_MODE (sparc_compare_op0) == DImode
3647      && ! TARGET_ARCH64)
3648    FAIL;
3649
3650  if (sparc_compare_op1 == const0_rtx
3651      && GET_CODE (sparc_compare_op0) == REG
3652      && GET_MODE (sparc_compare_op0) == DImode
3653      && v9_regcmp_p (code))
3654    {
3655      operands[1] = gen_rtx_fmt_ee (code, DImode,
3656			     sparc_compare_op0, sparc_compare_op1);
3657    }
3658  else
3659    {
3660      rtx cc_reg = gen_compare_reg (code,
3661				    sparc_compare_op0, sparc_compare_op1);
3662      operands[1] = gen_rtx_fmt_ee (code, GET_MODE (cc_reg), cc_reg, const0_rtx);
3663    }
3664})
3665
3666(define_expand "movtfcc"
3667  [(set (match_operand:TF 0 "register_operand" "")
3668	(if_then_else:TF (match_operand 1 "comparison_operator" "")
3669			 (match_operand:TF 2 "register_operand" "")
3670			 (match_operand:TF 3 "register_operand" "")))]
3671  "TARGET_V9 && TARGET_FPU"
3672{
3673  enum rtx_code code = GET_CODE (operands[1]);
3674
3675  if (GET_MODE (sparc_compare_op0) == DImode
3676      && ! TARGET_ARCH64)
3677    FAIL;
3678
3679  if (sparc_compare_op1 == const0_rtx
3680      && GET_CODE (sparc_compare_op0) == REG
3681      && GET_MODE (sparc_compare_op0) == DImode
3682      && v9_regcmp_p (code))
3683    {
3684      operands[1] = gen_rtx_fmt_ee (code, DImode,
3685			     sparc_compare_op0, sparc_compare_op1);
3686    }
3687  else
3688    {
3689      rtx cc_reg = gen_compare_reg (code,
3690				    sparc_compare_op0, sparc_compare_op1);
3691      operands[1] = gen_rtx_fmt_ee (code, GET_MODE (cc_reg), cc_reg, const0_rtx);
3692    }
3693})
3694
3695;; Conditional move define_insns.
3696
3697(define_insn "*movqi_cc_sp64"
3698  [(set (match_operand:QI 0 "register_operand" "=r,r")
3699	(if_then_else:QI (match_operator 1 "comparison_operator"
3700				[(match_operand 2 "icc_or_fcc_reg_operand" "X,X")
3701				 (const_int 0)])
3702                         (match_operand:QI 3 "arith11_operand" "rL,0")
3703                         (match_operand:QI 4 "arith11_operand" "0,rL")))]
3704  "TARGET_V9"
3705  "@
3706   mov%C1\t%x2, %3, %0
3707   mov%c1\t%x2, %4, %0"
3708  [(set_attr "type" "cmove")])
3709
3710(define_insn "*movhi_cc_sp64"
3711  [(set (match_operand:HI 0 "register_operand" "=r,r")
3712	(if_then_else:HI (match_operator 1 "comparison_operator"
3713				[(match_operand 2 "icc_or_fcc_reg_operand" "X,X")
3714				 (const_int 0)])
3715                         (match_operand:HI 3 "arith11_operand" "rL,0")
3716                         (match_operand:HI 4 "arith11_operand" "0,rL")))]
3717  "TARGET_V9"
3718  "@
3719   mov%C1\t%x2, %3, %0
3720   mov%c1\t%x2, %4, %0"
3721  [(set_attr "type" "cmove")])
3722
3723(define_insn "*movsi_cc_sp64"
3724  [(set (match_operand:SI 0 "register_operand" "=r,r")
3725	(if_then_else:SI (match_operator 1 "comparison_operator"
3726				[(match_operand 2 "icc_or_fcc_reg_operand" "X,X")
3727				 (const_int 0)])
3728                         (match_operand:SI 3 "arith11_operand" "rL,0")
3729                         (match_operand:SI 4 "arith11_operand" "0,rL")))]
3730  "TARGET_V9"
3731  "@
3732   mov%C1\t%x2, %3, %0
3733   mov%c1\t%x2, %4, %0"
3734  [(set_attr "type" "cmove")])
3735
3736;; ??? The constraints of operands 3,4 need work.
3737(define_insn "*movdi_cc_sp64"
3738  [(set (match_operand:DI 0 "register_operand" "=r,r")
3739	(if_then_else:DI (match_operator 1 "comparison_operator"
3740				[(match_operand 2 "icc_or_fcc_reg_operand" "X,X")
3741				 (const_int 0)])
3742                         (match_operand:DI 3 "arith11_double_operand" "rLH,0")
3743                         (match_operand:DI 4 "arith11_double_operand" "0,rLH")))]
3744  "TARGET_ARCH64"
3745  "@
3746   mov%C1\t%x2, %3, %0
3747   mov%c1\t%x2, %4, %0"
3748  [(set_attr "type" "cmove")])
3749
3750(define_insn "*movdi_cc_sp64_trunc"
3751  [(set (match_operand:SI 0 "register_operand" "=r,r")
3752	(if_then_else:SI (match_operator 1 "comparison_operator"
3753				[(match_operand 2 "icc_or_fcc_reg_operand" "X,X")
3754				 (const_int 0)])
3755                         (match_operand:SI 3 "arith11_double_operand" "rLH,0")
3756                         (match_operand:SI 4 "arith11_double_operand" "0,rLH")))]
3757  "TARGET_ARCH64"
3758  "@
3759   mov%C1\t%x2, %3, %0
3760   mov%c1\t%x2, %4, %0"
3761  [(set_attr "type" "cmove")])
3762
3763(define_insn "*movsf_cc_sp64"
3764  [(set (match_operand:SF 0 "register_operand" "=f,f")
3765	(if_then_else:SF (match_operator 1 "comparison_operator"
3766				[(match_operand 2 "icc_or_fcc_reg_operand" "X,X")
3767				 (const_int 0)])
3768                         (match_operand:SF 3 "register_operand" "f,0")
3769                         (match_operand:SF 4 "register_operand" "0,f")))]
3770  "TARGET_V9 && TARGET_FPU"
3771  "@
3772   fmovs%C1\t%x2, %3, %0
3773   fmovs%c1\t%x2, %4, %0"
3774  [(set_attr "type" "fpcmove")])
3775
3776(define_insn "movdf_cc_sp64"
3777  [(set (match_operand:DF 0 "register_operand" "=e,e")
3778	(if_then_else:DF (match_operator 1 "comparison_operator"
3779				[(match_operand 2 "icc_or_fcc_reg_operand" "X,X")
3780				 (const_int 0)])
3781                         (match_operand:DF 3 "register_operand" "e,0")
3782                         (match_operand:DF 4 "register_operand" "0,e")))]
3783  "TARGET_V9 && TARGET_FPU"
3784  "@
3785   fmovd%C1\t%x2, %3, %0
3786   fmovd%c1\t%x2, %4, %0"
3787  [(set_attr "type" "fpcmove")
3788   (set_attr "fptype" "double")])
3789
3790(define_insn "*movtf_cc_hq_sp64"
3791  [(set (match_operand:TF 0 "register_operand" "=e,e")
3792	(if_then_else:TF (match_operator 1 "comparison_operator"
3793				[(match_operand 2 "icc_or_fcc_reg_operand" "X,X")
3794				 (const_int 0)])
3795                         (match_operand:TF 3 "register_operand" "e,0")
3796                         (match_operand:TF 4 "register_operand" "0,e")))]
3797  "TARGET_V9 && TARGET_FPU && TARGET_HARD_QUAD"
3798  "@
3799   fmovq%C1\t%x2, %3, %0
3800   fmovq%c1\t%x2, %4, %0"
3801  [(set_attr "type" "fpcmove")])
3802
3803(define_insn_and_split "*movtf_cc_sp64"
3804  [(set (match_operand:TF 0 "register_operand" "=e,e")
3805	(if_then_else:TF (match_operator 1 "comparison_operator"
3806			    [(match_operand 2 "icc_or_fcc_reg_operand" "X,X")
3807			     (const_int 0)])
3808                         (match_operand:TF 3 "register_operand" "e,0")
3809                         (match_operand:TF 4 "register_operand" "0,e")))]
3810  "TARGET_V9 && TARGET_FPU && !TARGET_HARD_QUAD"
3811  "#"
3812  "&& reload_completed"
3813  [(clobber (const_int 0))]
3814{
3815  rtx set_dest = operands[0];
3816  rtx set_srca = operands[3];
3817  rtx set_srcb = operands[4];
3818  int third = rtx_equal_p (set_dest, set_srca);
3819  rtx dest1, dest2;
3820  rtx srca1, srca2, srcb1, srcb2;
3821
3822  dest1 = gen_df_reg (set_dest, 0);
3823  dest2 = gen_df_reg (set_dest, 1);
3824  srca1 = gen_df_reg (set_srca, 0);
3825  srca2 = gen_df_reg (set_srca, 1);
3826  srcb1 = gen_df_reg (set_srcb, 0);
3827  srcb2 = gen_df_reg (set_srcb, 1);
3828
3829  /* Now emit using the real source and destination we found, swapping
3830     the order if we detect overlap.  */
3831  if ((third && reg_overlap_mentioned_p (dest1, srcb2))
3832      || (!third && reg_overlap_mentioned_p (dest1, srca2)))
3833    {
3834      emit_insn (gen_movdf_cc_sp64 (dest2, operands[1], operands[2], srca2, srcb2));
3835      emit_insn (gen_movdf_cc_sp64 (dest1, operands[1], operands[2], srca1, srcb1));
3836    }
3837  else
3838    {
3839      emit_insn (gen_movdf_cc_sp64 (dest1, operands[1], operands[2], srca1, srcb1));
3840      emit_insn (gen_movdf_cc_sp64 (dest2, operands[1], operands[2], srca2, srcb2));
3841    }
3842  DONE;
3843}
3844  [(set_attr "length" "2")])
3845
3846(define_insn "*movqi_cc_reg_sp64"
3847  [(set (match_operand:QI 0 "register_operand" "=r,r")
3848	(if_then_else:QI (match_operator 1 "v9_regcmp_op"
3849				[(match_operand:DI 2 "register_operand" "r,r")
3850				 (const_int 0)])
3851                         (match_operand:QI 3 "arith10_operand" "rM,0")
3852                         (match_operand:QI 4 "arith10_operand" "0,rM")))]
3853  "TARGET_ARCH64"
3854  "@
3855   movr%D1\t%2, %r3, %0
3856   movr%d1\t%2, %r4, %0"
3857  [(set_attr "type" "cmove")])
3858
3859(define_insn "*movhi_cc_reg_sp64"
3860  [(set (match_operand:HI 0 "register_operand" "=r,r")
3861	(if_then_else:HI (match_operator 1 "v9_regcmp_op"
3862				[(match_operand:DI 2 "register_operand" "r,r")
3863				 (const_int 0)])
3864                         (match_operand:HI 3 "arith10_operand" "rM,0")
3865                         (match_operand:HI 4 "arith10_operand" "0,rM")))]
3866  "TARGET_ARCH64"
3867  "@
3868   movr%D1\t%2, %r3, %0
3869   movr%d1\t%2, %r4, %0"
3870  [(set_attr "type" "cmove")])
3871
3872(define_insn "*movsi_cc_reg_sp64"
3873  [(set (match_operand:SI 0 "register_operand" "=r,r")
3874	(if_then_else:SI (match_operator 1 "v9_regcmp_op"
3875				[(match_operand:DI 2 "register_operand" "r,r")
3876				 (const_int 0)])
3877                         (match_operand:SI 3 "arith10_operand" "rM,0")
3878                         (match_operand:SI 4 "arith10_operand" "0,rM")))]
3879  "TARGET_ARCH64"
3880  "@
3881   movr%D1\t%2, %r3, %0
3882   movr%d1\t%2, %r4, %0"
3883  [(set_attr "type" "cmove")])
3884
3885;; ??? The constraints of operands 3,4 need work.
3886(define_insn "*movdi_cc_reg_sp64"
3887  [(set (match_operand:DI 0 "register_operand" "=r,r")
3888	(if_then_else:DI (match_operator 1 "v9_regcmp_op"
3889				[(match_operand:DI 2 "register_operand" "r,r")
3890				 (const_int 0)])
3891                         (match_operand:DI 3 "arith10_double_operand" "rMH,0")
3892                         (match_operand:DI 4 "arith10_double_operand" "0,rMH")))]
3893  "TARGET_ARCH64"
3894  "@
3895   movr%D1\t%2, %r3, %0
3896   movr%d1\t%2, %r4, %0"
3897  [(set_attr "type" "cmove")])
3898
3899(define_insn "*movdi_cc_reg_sp64_trunc"
3900  [(set (match_operand:SI 0 "register_operand" "=r,r")
3901	(if_then_else:SI (match_operator 1 "v9_regcmp_op"
3902				[(match_operand:DI 2 "register_operand" "r,r")
3903				 (const_int 0)])
3904                         (match_operand:SI 3 "arith10_double_operand" "rMH,0")
3905                         (match_operand:SI 4 "arith10_double_operand" "0,rMH")))]
3906  "TARGET_ARCH64"
3907  "@
3908   movr%D1\t%2, %r3, %0
3909   movr%d1\t%2, %r4, %0"
3910  [(set_attr "type" "cmove")])
3911
3912(define_insn "*movsf_cc_reg_sp64"
3913  [(set (match_operand:SF 0 "register_operand" "=f,f")
3914	(if_then_else:SF (match_operator 1 "v9_regcmp_op"
3915				[(match_operand:DI 2 "register_operand" "r,r")
3916				 (const_int 0)])
3917                         (match_operand:SF 3 "register_operand" "f,0")
3918                         (match_operand:SF 4 "register_operand" "0,f")))]
3919  "TARGET_ARCH64 && TARGET_FPU"
3920  "@
3921   fmovrs%D1\t%2, %3, %0
3922   fmovrs%d1\t%2, %4, %0"
3923  [(set_attr "type" "fpcrmove")])
3924
3925(define_insn "movdf_cc_reg_sp64"
3926  [(set (match_operand:DF 0 "register_operand" "=e,e")
3927	(if_then_else:DF (match_operator 1 "v9_regcmp_op"
3928				[(match_operand:DI 2 "register_operand" "r,r")
3929				 (const_int 0)])
3930                         (match_operand:DF 3 "register_operand" "e,0")
3931                         (match_operand:DF 4 "register_operand" "0,e")))]
3932  "TARGET_ARCH64 && TARGET_FPU"
3933  "@
3934   fmovrd%D1\t%2, %3, %0
3935   fmovrd%d1\t%2, %4, %0"
3936  [(set_attr "type" "fpcrmove")
3937   (set_attr "fptype" "double")])
3938
3939(define_insn "*movtf_cc_reg_hq_sp64"
3940  [(set (match_operand:TF 0 "register_operand" "=e,e")
3941	(if_then_else:TF (match_operator 1 "v9_regcmp_op"
3942				[(match_operand:DI 2 "register_operand" "r,r")
3943				 (const_int 0)])
3944                         (match_operand:TF 3 "register_operand" "e,0")
3945                         (match_operand:TF 4 "register_operand" "0,e")))]
3946  "TARGET_ARCH64 && TARGET_FPU && TARGET_HARD_QUAD"
3947  "@
3948   fmovrq%D1\t%2, %3, %0
3949   fmovrq%d1\t%2, %4, %0"
3950  [(set_attr "type" "fpcrmove")])
3951
3952(define_insn_and_split "*movtf_cc_reg_sp64"
3953  [(set (match_operand:TF 0 "register_operand" "=e,e")
3954	(if_then_else:TF (match_operator 1 "v9_regcmp_op"
3955				[(match_operand:DI 2 "register_operand" "r,r")
3956				 (const_int 0)])
3957                         (match_operand:TF 3 "register_operand" "e,0")
3958                         (match_operand:TF 4 "register_operand" "0,e")))]
3959  "TARGET_ARCH64 && TARGET_FPU && ! TARGET_HARD_QUAD"
3960  "#"
3961  "&& reload_completed"
3962  [(clobber (const_int 0))]
3963{
3964  rtx set_dest = operands[0];
3965  rtx set_srca = operands[3];
3966  rtx set_srcb = operands[4];
3967  int third = rtx_equal_p (set_dest, set_srca);
3968  rtx dest1, dest2;
3969  rtx srca1, srca2, srcb1, srcb2;
3970
3971  dest1 = gen_df_reg (set_dest, 0);
3972  dest2 = gen_df_reg (set_dest, 1);
3973  srca1 = gen_df_reg (set_srca, 0);
3974  srca2 = gen_df_reg (set_srca, 1);
3975  srcb1 = gen_df_reg (set_srcb, 0);
3976  srcb2 = gen_df_reg (set_srcb, 1);
3977
3978  /* Now emit using the real source and destination we found, swapping
3979     the order if we detect overlap.  */
3980  if ((third && reg_overlap_mentioned_p (dest1, srcb2))
3981      || (!third && reg_overlap_mentioned_p (dest1, srca2)))
3982    {
3983      emit_insn (gen_movdf_cc_reg_sp64 (dest2, operands[1], operands[2], srca2, srcb2));
3984      emit_insn (gen_movdf_cc_reg_sp64 (dest1, operands[1], operands[2], srca1, srcb1));
3985    }
3986  else
3987    {
3988      emit_insn (gen_movdf_cc_reg_sp64 (dest1, operands[1], operands[2], srca1, srcb1));
3989      emit_insn (gen_movdf_cc_reg_sp64 (dest2, operands[1], operands[2], srca2, srcb2));
3990    }
3991  DONE;
3992}
3993  [(set_attr "length" "2")])
3994
3995
3996;;- zero extension instructions
3997
3998;; These patterns originally accepted general_operands, however, slightly
3999;; better code is generated by only accepting register_operands, and then
4000;; letting combine generate the ldu[hb] insns.
4001
4002(define_expand "zero_extendhisi2"
4003  [(set (match_operand:SI 0 "register_operand" "")
4004	(zero_extend:SI (match_operand:HI 1 "register_operand" "")))]
4005  ""
4006{
4007  rtx temp = gen_reg_rtx (SImode);
4008  rtx shift_16 = GEN_INT (16);
4009  int op1_subbyte = 0;
4010
4011  if (GET_CODE (operand1) == SUBREG)
4012    {
4013      op1_subbyte = SUBREG_BYTE (operand1);
4014      op1_subbyte /= GET_MODE_SIZE (SImode);
4015      op1_subbyte *= GET_MODE_SIZE (SImode);
4016      operand1 = XEXP (operand1, 0);
4017    }
4018
4019  emit_insn (gen_ashlsi3 (temp, gen_rtx_SUBREG (SImode, operand1, op1_subbyte),
4020			  shift_16));
4021  emit_insn (gen_lshrsi3 (operand0, temp, shift_16));
4022  DONE;
4023})
4024
4025(define_insn "*zero_extendhisi2_insn"
4026  [(set (match_operand:SI 0 "register_operand" "=r")
4027	(zero_extend:SI (match_operand:HI 1 "memory_operand" "m")))]
4028  ""
4029  "lduh\t%1, %0"
4030  [(set_attr "type" "load")
4031   (set_attr "us3load_type" "3cycle")])
4032
4033(define_expand "zero_extendqihi2"
4034  [(set (match_operand:HI 0 "register_operand" "")
4035	(zero_extend:HI (match_operand:QI 1 "register_operand" "")))]
4036  ""
4037  "")
4038
4039(define_insn "*zero_extendqihi2_insn"
4040  [(set (match_operand:HI 0 "register_operand" "=r,r")
4041	(zero_extend:HI (match_operand:QI 1 "input_operand" "r,m")))]
4042  "GET_CODE (operands[1]) != CONST_INT"
4043  "@
4044   and\t%1, 0xff, %0
4045   ldub\t%1, %0"
4046  [(set_attr "type" "*,load")
4047   (set_attr "us3load_type" "*,3cycle")])
4048
4049(define_expand "zero_extendqisi2"
4050  [(set (match_operand:SI 0 "register_operand" "")
4051	(zero_extend:SI (match_operand:QI 1 "register_operand" "")))]
4052  ""
4053  "")
4054
4055(define_insn "*zero_extendqisi2_insn"
4056  [(set (match_operand:SI 0 "register_operand" "=r,r")
4057	(zero_extend:SI (match_operand:QI 1 "input_operand" "r,m")))]
4058  "GET_CODE (operands[1]) != CONST_INT"
4059  "@
4060   and\t%1, 0xff, %0
4061   ldub\t%1, %0"
4062  [(set_attr "type" "*,load")
4063   (set_attr "us3load_type" "*,3cycle")])
4064
4065(define_expand "zero_extendqidi2"
4066  [(set (match_operand:DI 0 "register_operand" "")
4067	(zero_extend:DI (match_operand:QI 1 "register_operand" "")))]
4068  "TARGET_ARCH64"
4069  "")
4070
4071(define_insn "*zero_extendqidi2_insn"
4072  [(set (match_operand:DI 0 "register_operand" "=r,r")
4073	(zero_extend:DI (match_operand:QI 1 "input_operand" "r,m")))]
4074  "TARGET_ARCH64 && GET_CODE (operands[1]) != CONST_INT"
4075  "@
4076   and\t%1, 0xff, %0
4077   ldub\t%1, %0"
4078  [(set_attr "type" "*,load")
4079   (set_attr "us3load_type" "*,3cycle")])
4080
4081(define_expand "zero_extendhidi2"
4082  [(set (match_operand:DI 0 "register_operand" "")
4083	(zero_extend:DI (match_operand:HI 1 "register_operand" "")))]
4084  "TARGET_ARCH64"
4085{
4086  rtx temp = gen_reg_rtx (DImode);
4087  rtx shift_48 = GEN_INT (48);
4088  int op1_subbyte = 0;
4089
4090  if (GET_CODE (operand1) == SUBREG)
4091    {
4092      op1_subbyte = SUBREG_BYTE (operand1);
4093      op1_subbyte /= GET_MODE_SIZE (DImode);
4094      op1_subbyte *= GET_MODE_SIZE (DImode);
4095      operand1 = XEXP (operand1, 0);
4096    }
4097
4098  emit_insn (gen_ashldi3 (temp, gen_rtx_SUBREG (DImode, operand1, op1_subbyte),
4099			  shift_48));
4100  emit_insn (gen_lshrdi3 (operand0, temp, shift_48));
4101  DONE;
4102})
4103
4104(define_insn "*zero_extendhidi2_insn"
4105  [(set (match_operand:DI 0 "register_operand" "=r")
4106	(zero_extend:DI (match_operand:HI 1 "memory_operand" "m")))]
4107  "TARGET_ARCH64"
4108  "lduh\t%1, %0"
4109  [(set_attr "type" "load")
4110   (set_attr "us3load_type" "3cycle")])
4111
4112
4113;; ??? Write truncdisi pattern using sra?
4114
4115(define_expand "zero_extendsidi2"
4116  [(set (match_operand:DI 0 "register_operand" "")
4117	(zero_extend:DI (match_operand:SI 1 "register_operand" "")))]
4118  ""
4119  "")
4120
4121(define_insn "*zero_extendsidi2_insn_sp64"
4122  [(set (match_operand:DI 0 "register_operand" "=r,r")
4123	(zero_extend:DI (match_operand:SI 1 "input_operand" "r,m")))]
4124  "TARGET_ARCH64 && GET_CODE (operands[1]) != CONST_INT"
4125  "@
4126   srl\t%1, 0, %0
4127   lduw\t%1, %0"
4128  [(set_attr "type" "shift,load")])
4129
4130(define_insn_and_split "*zero_extendsidi2_insn_sp32"
4131  [(set (match_operand:DI 0 "register_operand" "=r")
4132        (zero_extend:DI (match_operand:SI 1 "register_operand" "r")))]
4133  "! TARGET_ARCH64"
4134  "#"
4135  "&& reload_completed"
4136  [(set (match_dup 2) (match_dup 3))
4137   (set (match_dup 4) (match_dup 5))]
4138{
4139  rtx dest1, dest2;
4140
4141  dest1 = gen_highpart (SImode, operands[0]);
4142  dest2 = gen_lowpart (SImode, operands[0]);
4143
4144  /* Swap the order in case of overlap.  */
4145  if (REGNO (dest1) == REGNO (operands[1]))
4146    {
4147      operands[2] = dest2;
4148      operands[3] = operands[1];
4149      operands[4] = dest1;
4150      operands[5] = const0_rtx;
4151    }
4152  else
4153    {
4154      operands[2] = dest1;
4155      operands[3] = const0_rtx;
4156      operands[4] = dest2;
4157      operands[5] = operands[1];
4158    }
4159}
4160  [(set_attr "length" "2")])
4161
4162;; Simplify comparisons of extended values.
4163
4164(define_insn "*cmp_zero_extendqisi2"
4165  [(set (reg:CC 100)
4166	(compare:CC (zero_extend:SI (match_operand:QI 0 "register_operand" "r"))
4167		    (const_int 0)))]
4168  ""
4169  "andcc\t%0, 0xff, %%g0"
4170  [(set_attr "type" "compare")])
4171
4172(define_insn "*cmp_zero_qi"
4173  [(set (reg:CC 100)
4174	(compare:CC (match_operand:QI 0 "register_operand" "r")
4175		    (const_int 0)))]
4176  ""
4177  "andcc\t%0, 0xff, %%g0"
4178  [(set_attr "type" "compare")])
4179
4180(define_insn "*cmp_zero_extendqisi2_set"
4181  [(set (reg:CC 100)
4182	(compare:CC (zero_extend:SI (match_operand:QI 1 "register_operand" "r"))
4183		    (const_int 0)))
4184   (set (match_operand:SI 0 "register_operand" "=r")
4185	(zero_extend:SI (match_dup 1)))]
4186  ""
4187  "andcc\t%1, 0xff, %0"
4188  [(set_attr "type" "compare")])
4189
4190(define_insn "*cmp_zero_extendqisi2_andcc_set"
4191  [(set (reg:CC 100)
4192	(compare:CC (and:SI (match_operand:SI 1 "register_operand" "r")
4193			    (const_int 255))
4194		    (const_int 0)))
4195   (set (match_operand:SI 0 "register_operand" "=r")
4196	(zero_extend:SI (subreg:QI (match_dup 1) 0)))]
4197  ""
4198  "andcc\t%1, 0xff, %0"
4199  [(set_attr "type" "compare")])
4200
4201(define_insn "*cmp_zero_extendqidi2"
4202  [(set (reg:CCX 100)
4203	(compare:CCX (zero_extend:DI (match_operand:QI 0 "register_operand" "r"))
4204		     (const_int 0)))]
4205  "TARGET_ARCH64"
4206  "andcc\t%0, 0xff, %%g0"
4207  [(set_attr "type" "compare")])
4208
4209(define_insn "*cmp_zero_qi_sp64"
4210  [(set (reg:CCX 100)
4211	(compare:CCX (match_operand:QI 0 "register_operand" "r")
4212		     (const_int 0)))]
4213  "TARGET_ARCH64"
4214  "andcc\t%0, 0xff, %%g0"
4215  [(set_attr "type" "compare")])
4216
4217(define_insn "*cmp_zero_extendqidi2_set"
4218  [(set (reg:CCX 100)
4219	(compare:CCX (zero_extend:DI (match_operand:QI 1 "register_operand" "r"))
4220		     (const_int 0)))
4221   (set (match_operand:DI 0 "register_operand" "=r")
4222	(zero_extend:DI (match_dup 1)))]
4223  "TARGET_ARCH64"
4224  "andcc\t%1, 0xff, %0"
4225  [(set_attr "type" "compare")])
4226
4227(define_insn "*cmp_zero_extendqidi2_andcc_set"
4228  [(set (reg:CCX 100)
4229	(compare:CCX (and:DI (match_operand:DI 1 "register_operand" "r")
4230			     (const_int 255))
4231		     (const_int 0)))
4232   (set (match_operand:DI 0 "register_operand" "=r")
4233	(zero_extend:DI (subreg:QI (match_dup 1) 0)))]
4234  "TARGET_ARCH64"
4235  "andcc\t%1, 0xff, %0"
4236  [(set_attr "type" "compare")])
4237
4238;; Similarly, handle {SI,DI}->QI mode truncation followed by a compare.
4239
4240(define_insn "*cmp_siqi_trunc"
4241  [(set (reg:CC 100)
4242	(compare:CC (subreg:QI (match_operand:SI 0 "register_operand" "r") 3)
4243		    (const_int 0)))]
4244  ""
4245  "andcc\t%0, 0xff, %%g0"
4246  [(set_attr "type" "compare")])
4247
4248(define_insn "*cmp_siqi_trunc_set"
4249  [(set (reg:CC 100)
4250	(compare:CC (subreg:QI (match_operand:SI 1 "register_operand" "r") 3)
4251		    (const_int 0)))
4252   (set (match_operand:QI 0 "register_operand" "=r")
4253	(subreg:QI (match_dup 1) 3))]
4254  ""
4255  "andcc\t%1, 0xff, %0"
4256  [(set_attr "type" "compare")])
4257
4258(define_insn "*cmp_diqi_trunc"
4259  [(set (reg:CC 100)
4260	(compare:CC (subreg:QI (match_operand:DI 0 "register_operand" "r") 7)
4261		    (const_int 0)))]
4262  "TARGET_ARCH64"
4263  "andcc\t%0, 0xff, %%g0"
4264  [(set_attr "type" "compare")])
4265
4266(define_insn "*cmp_diqi_trunc_set"
4267  [(set (reg:CC 100)
4268	(compare:CC (subreg:QI (match_operand:DI 1 "register_operand" "r") 7)
4269		    (const_int 0)))
4270   (set (match_operand:QI 0 "register_operand" "=r")
4271	(subreg:QI (match_dup 1) 7))]
4272  "TARGET_ARCH64"
4273  "andcc\t%1, 0xff, %0"
4274  [(set_attr "type" "compare")])
4275
4276;;- sign extension instructions
4277
4278;; These patterns originally accepted general_operands, however, slightly
4279;; better code is generated by only accepting register_operands, and then
4280;; letting combine generate the lds[hb] insns.
4281
4282(define_expand "extendhisi2"
4283  [(set (match_operand:SI 0 "register_operand" "")
4284	(sign_extend:SI (match_operand:HI 1 "register_operand" "")))]
4285  ""
4286{
4287  rtx temp = gen_reg_rtx (SImode);
4288  rtx shift_16 = GEN_INT (16);
4289  int op1_subbyte = 0;
4290
4291  if (GET_CODE (operand1) == SUBREG)
4292    {
4293      op1_subbyte = SUBREG_BYTE (operand1);
4294      op1_subbyte /= GET_MODE_SIZE (SImode);
4295      op1_subbyte *= GET_MODE_SIZE (SImode);
4296      operand1 = XEXP (operand1, 0);
4297    }
4298
4299  emit_insn (gen_ashlsi3 (temp, gen_rtx_SUBREG (SImode, operand1, op1_subbyte),
4300			  shift_16));
4301  emit_insn (gen_ashrsi3 (operand0, temp, shift_16));
4302  DONE;
4303})
4304
4305(define_insn "*sign_extendhisi2_insn"
4306  [(set (match_operand:SI 0 "register_operand" "=r")
4307	(sign_extend:SI (match_operand:HI 1 "memory_operand" "m")))]
4308  ""
4309  "ldsh\t%1, %0"
4310  [(set_attr "type" "sload")
4311   (set_attr "us3load_type" "3cycle")])
4312
4313(define_expand "extendqihi2"
4314  [(set (match_operand:HI 0 "register_operand" "")
4315	(sign_extend:HI (match_operand:QI 1 "register_operand" "")))]
4316  ""
4317{
4318  rtx temp = gen_reg_rtx (SImode);
4319  rtx shift_24 = GEN_INT (24);
4320  int op1_subbyte = 0;
4321  int op0_subbyte = 0;
4322
4323  if (GET_CODE (operand1) == SUBREG)
4324    {
4325      op1_subbyte = SUBREG_BYTE (operand1);
4326      op1_subbyte /= GET_MODE_SIZE (SImode);
4327      op1_subbyte *= GET_MODE_SIZE (SImode);
4328      operand1 = XEXP (operand1, 0);
4329    }
4330  if (GET_CODE (operand0) == SUBREG)
4331    {
4332      op0_subbyte = SUBREG_BYTE (operand0);
4333      op0_subbyte /= GET_MODE_SIZE (SImode);
4334      op0_subbyte *= GET_MODE_SIZE (SImode);
4335      operand0 = XEXP (operand0, 0);
4336    }
4337  emit_insn (gen_ashlsi3 (temp, gen_rtx_SUBREG (SImode, operand1, op1_subbyte),
4338			  shift_24));
4339  if (GET_MODE (operand0) != SImode)
4340    operand0 = gen_rtx_SUBREG (SImode, operand0, op0_subbyte);
4341  emit_insn (gen_ashrsi3 (operand0, temp, shift_24));
4342  DONE;
4343})
4344
4345(define_insn "*sign_extendqihi2_insn"
4346  [(set (match_operand:HI 0 "register_operand" "=r")
4347	(sign_extend:HI (match_operand:QI 1 "memory_operand" "m")))]
4348  ""
4349  "ldsb\t%1, %0"
4350  [(set_attr "type" "sload")
4351   (set_attr "us3load_type" "3cycle")])
4352
4353(define_expand "extendqisi2"
4354  [(set (match_operand:SI 0 "register_operand" "")
4355	(sign_extend:SI (match_operand:QI 1 "register_operand" "")))]
4356  ""
4357{
4358  rtx temp = gen_reg_rtx (SImode);
4359  rtx shift_24 = GEN_INT (24);
4360  int op1_subbyte = 0;
4361
4362  if (GET_CODE (operand1) == SUBREG)
4363    {
4364      op1_subbyte = SUBREG_BYTE (operand1);
4365      op1_subbyte /= GET_MODE_SIZE (SImode);
4366      op1_subbyte *= GET_MODE_SIZE (SImode);
4367      operand1 = XEXP (operand1, 0);
4368    }
4369
4370  emit_insn (gen_ashlsi3 (temp, gen_rtx_SUBREG (SImode, operand1, op1_subbyte),
4371			  shift_24));
4372  emit_insn (gen_ashrsi3 (operand0, temp, shift_24));
4373  DONE;
4374})
4375
4376(define_insn "*sign_extendqisi2_insn"
4377  [(set (match_operand:SI 0 "register_operand" "=r")
4378	(sign_extend:SI (match_operand:QI 1 "memory_operand" "m")))]
4379  ""
4380  "ldsb\t%1, %0"
4381  [(set_attr "type" "sload")
4382   (set_attr "us3load_type" "3cycle")])
4383
4384(define_expand "extendqidi2"
4385  [(set (match_operand:DI 0 "register_operand" "")
4386	(sign_extend:DI (match_operand:QI 1 "register_operand" "")))]
4387  "TARGET_ARCH64"
4388{
4389  rtx temp = gen_reg_rtx (DImode);
4390  rtx shift_56 = GEN_INT (56);
4391  int op1_subbyte = 0;
4392
4393  if (GET_CODE (operand1) == SUBREG)
4394    {
4395      op1_subbyte = SUBREG_BYTE (operand1);
4396      op1_subbyte /= GET_MODE_SIZE (DImode);
4397      op1_subbyte *= GET_MODE_SIZE (DImode);
4398      operand1 = XEXP (operand1, 0);
4399    }
4400
4401  emit_insn (gen_ashldi3 (temp, gen_rtx_SUBREG (DImode, operand1, op1_subbyte),
4402			  shift_56));
4403  emit_insn (gen_ashrdi3 (operand0, temp, shift_56));
4404  DONE;
4405})
4406
4407(define_insn "*sign_extendqidi2_insn"
4408  [(set (match_operand:DI 0 "register_operand" "=r")
4409	(sign_extend:DI (match_operand:QI 1 "memory_operand" "m")))]
4410  "TARGET_ARCH64"
4411  "ldsb\t%1, %0"
4412  [(set_attr "type" "sload")
4413   (set_attr "us3load_type" "3cycle")])
4414
4415(define_expand "extendhidi2"
4416  [(set (match_operand:DI 0 "register_operand" "")
4417	(sign_extend:DI (match_operand:HI 1 "register_operand" "")))]
4418  "TARGET_ARCH64"
4419{
4420  rtx temp = gen_reg_rtx (DImode);
4421  rtx shift_48 = GEN_INT (48);
4422  int op1_subbyte = 0;
4423
4424  if (GET_CODE (operand1) == SUBREG)
4425    {
4426      op1_subbyte = SUBREG_BYTE (operand1);
4427      op1_subbyte /= GET_MODE_SIZE (DImode);
4428      op1_subbyte *= GET_MODE_SIZE (DImode);
4429      operand1 = XEXP (operand1, 0);
4430    }
4431
4432  emit_insn (gen_ashldi3 (temp, gen_rtx_SUBREG (DImode, operand1, op1_subbyte),
4433			  shift_48));
4434  emit_insn (gen_ashrdi3 (operand0, temp, shift_48));
4435  DONE;
4436})
4437
4438(define_insn "*sign_extendhidi2_insn"
4439  [(set (match_operand:DI 0 "register_operand" "=r")
4440	(sign_extend:DI (match_operand:HI 1 "memory_operand" "m")))]
4441  "TARGET_ARCH64"
4442  "ldsh\t%1, %0"
4443  [(set_attr "type" "sload")
4444   (set_attr "us3load_type" "3cycle")])
4445
4446(define_expand "extendsidi2"
4447  [(set (match_operand:DI 0 "register_operand" "")
4448	(sign_extend:DI (match_operand:SI 1 "register_operand" "")))]
4449  "TARGET_ARCH64"
4450  "")
4451
4452(define_insn "*sign_extendsidi2_insn"
4453  [(set (match_operand:DI 0 "register_operand" "=r,r")
4454	(sign_extend:DI (match_operand:SI 1 "input_operand" "r,m")))]
4455  "TARGET_ARCH64"
4456  "@
4457  sra\t%1, 0, %0
4458  ldsw\t%1, %0"
4459  [(set_attr "type" "shift,sload")
4460   (set_attr "us3load_type" "*,3cycle")])
4461
4462;; Special pattern for optimizing bit-field compares.  This is needed
4463;; because combine uses this as a canonical form.
4464
4465(define_insn "*cmp_zero_extract"
4466  [(set (reg:CC 100)
4467	(compare:CC
4468	 (zero_extract:SI (match_operand:SI 0 "register_operand" "r")
4469			  (match_operand:SI 1 "small_int_or_double" "n")
4470			  (match_operand:SI 2 "small_int_or_double" "n"))
4471	 (const_int 0)))]
4472  "(GET_CODE (operands[2]) == CONST_INT
4473    && INTVAL (operands[2]) > 19)
4474   || (GET_CODE (operands[2]) == CONST_DOUBLE
4475       && CONST_DOUBLE_LOW (operands[2]) > 19)"
4476{
4477  int len = (GET_CODE (operands[1]) == CONST_INT
4478             ? INTVAL (operands[1])
4479             : CONST_DOUBLE_LOW (operands[1]));
4480  int pos = 32 -
4481            (GET_CODE (operands[2]) == CONST_INT
4482             ? INTVAL (operands[2])
4483             : CONST_DOUBLE_LOW (operands[2])) - len;
4484  HOST_WIDE_INT mask = ((1 << len) - 1) << pos;
4485
4486  operands[1] = GEN_INT (mask);
4487  return "andcc\t%0, %1, %%g0";
4488}
4489  [(set_attr "type" "compare")])
4490
4491(define_insn "*cmp_zero_extract_sp64"
4492  [(set (reg:CCX 100)
4493	(compare:CCX
4494	 (zero_extract:DI (match_operand:DI 0 "register_operand" "r")
4495			  (match_operand:SI 1 "small_int_or_double" "n")
4496			  (match_operand:SI 2 "small_int_or_double" "n"))
4497	 (const_int 0)))]
4498  "TARGET_ARCH64
4499   && ((GET_CODE (operands[2]) == CONST_INT
4500        && INTVAL (operands[2]) > 51)
4501       || (GET_CODE (operands[2]) == CONST_DOUBLE
4502           && CONST_DOUBLE_LOW (operands[2]) > 51))"
4503{
4504  int len = (GET_CODE (operands[1]) == CONST_INT
4505             ? INTVAL (operands[1])
4506             : CONST_DOUBLE_LOW (operands[1]));
4507  int pos = 64 -
4508            (GET_CODE (operands[2]) == CONST_INT
4509             ? INTVAL (operands[2])
4510             : CONST_DOUBLE_LOW (operands[2])) - len;
4511  HOST_WIDE_INT mask = (((unsigned HOST_WIDE_INT) 1 << len) - 1) << pos;
4512
4513  operands[1] = GEN_INT (mask);
4514  return "andcc\t%0, %1, %%g0";
4515}
4516  [(set_attr "type" "compare")])
4517
4518;; Conversions between float, double and long double.
4519
4520(define_insn "extendsfdf2"
4521  [(set (match_operand:DF 0 "register_operand" "=e")
4522	(float_extend:DF
4523	 (match_operand:SF 1 "register_operand" "f")))]
4524  "TARGET_FPU"
4525  "fstod\t%1, %0"
4526  [(set_attr "type" "fp")
4527   (set_attr "fptype" "double")])
4528
4529(define_expand "extendsftf2"
4530  [(set (match_operand:TF 0 "nonimmediate_operand" "")
4531	(float_extend:TF
4532	 (match_operand:SF 1 "register_operand" "")))]
4533  "TARGET_FPU && (TARGET_HARD_QUAD || TARGET_ARCH64)"
4534  "emit_tfmode_cvt (FLOAT_EXTEND, operands); DONE;")
4535
4536(define_insn "*extendsftf2_hq"
4537  [(set (match_operand:TF 0 "register_operand" "=e")
4538	(float_extend:TF
4539	 (match_operand:SF 1 "register_operand" "f")))]
4540  "TARGET_FPU && TARGET_HARD_QUAD"
4541  "fstoq\t%1, %0"
4542  [(set_attr "type" "fp")])
4543
4544(define_expand "extenddftf2"
4545  [(set (match_operand:TF 0 "nonimmediate_operand" "")
4546	(float_extend:TF
4547	 (match_operand:DF 1 "register_operand" "")))]
4548  "TARGET_FPU && (TARGET_HARD_QUAD || TARGET_ARCH64)"
4549  "emit_tfmode_cvt (FLOAT_EXTEND, operands); DONE;")
4550
4551(define_insn "*extenddftf2_hq"
4552  [(set (match_operand:TF 0 "register_operand" "=e")
4553	(float_extend:TF
4554	 (match_operand:DF 1 "register_operand" "e")))]
4555  "TARGET_FPU && TARGET_HARD_QUAD"
4556  "fdtoq\t%1, %0"
4557  [(set_attr "type" "fp")])
4558
4559(define_insn "truncdfsf2"
4560  [(set (match_operand:SF 0 "register_operand" "=f")
4561	(float_truncate:SF
4562	 (match_operand:DF 1 "register_operand" "e")))]
4563  "TARGET_FPU"
4564  "fdtos\t%1, %0"
4565  [(set_attr "type" "fp")
4566   (set_attr "fptype" "double")])
4567
4568(define_expand "trunctfsf2"
4569  [(set (match_operand:SF 0 "register_operand" "")
4570	(float_truncate:SF
4571	 (match_operand:TF 1 "general_operand" "")))]
4572  "TARGET_FPU && (TARGET_HARD_QUAD || TARGET_ARCH64)"
4573  "emit_tfmode_cvt (FLOAT_TRUNCATE, operands); DONE;")
4574
4575(define_insn "*trunctfsf2_hq"
4576  [(set (match_operand:SF 0 "register_operand" "=f")
4577	(float_truncate:SF
4578	 (match_operand:TF 1 "register_operand" "e")))]
4579  "TARGET_FPU && TARGET_HARD_QUAD"
4580  "fqtos\t%1, %0"
4581  [(set_attr "type" "fp")])
4582
4583(define_expand "trunctfdf2"
4584  [(set (match_operand:DF 0 "register_operand" "")
4585	(float_truncate:DF
4586	 (match_operand:TF 1 "general_operand" "")))]
4587  "TARGET_FPU && (TARGET_HARD_QUAD || TARGET_ARCH64)"
4588  "emit_tfmode_cvt (FLOAT_TRUNCATE, operands); DONE;")
4589
4590(define_insn "*trunctfdf2_hq"
4591  [(set (match_operand:DF 0 "register_operand" "=e")
4592	(float_truncate:DF
4593	 (match_operand:TF 1 "register_operand" "e")))]
4594  "TARGET_FPU && TARGET_HARD_QUAD"
4595  "fqtod\t%1, %0"
4596  [(set_attr "type" "fp")])
4597
4598;; Conversion between fixed point and floating point.
4599
4600(define_insn "floatsisf2"
4601  [(set (match_operand:SF 0 "register_operand" "=f")
4602	(float:SF (match_operand:SI 1 "register_operand" "f")))]
4603  "TARGET_FPU"
4604  "fitos\t%1, %0"
4605  [(set_attr "type" "fp")
4606   (set_attr "fptype" "double")])
4607
4608(define_insn "floatsidf2"
4609  [(set (match_operand:DF 0 "register_operand" "=e")
4610	(float:DF (match_operand:SI 1 "register_operand" "f")))]
4611  "TARGET_FPU"
4612  "fitod\t%1, %0"
4613  [(set_attr "type" "fp")
4614   (set_attr "fptype" "double")])
4615
4616(define_expand "floatsitf2"
4617  [(set (match_operand:TF 0 "nonimmediate_operand" "")
4618	(float:TF (match_operand:SI 1 "register_operand" "")))]
4619  "TARGET_FPU && (TARGET_HARD_QUAD || TARGET_ARCH64)"
4620  "emit_tfmode_cvt (FLOAT, operands); DONE;")
4621
4622(define_insn "*floatsitf2_hq"
4623  [(set (match_operand:TF 0 "register_operand" "=e")
4624	(float:TF (match_operand:SI 1 "register_operand" "f")))]
4625  "TARGET_FPU && TARGET_HARD_QUAD"
4626  "fitoq\t%1, %0"
4627  [(set_attr "type" "fp")])
4628
4629(define_expand "floatunssitf2"
4630  [(set (match_operand:TF 0 "nonimmediate_operand" "")
4631	(unsigned_float:TF (match_operand:SI 1 "register_operand" "")))]
4632  "TARGET_FPU && TARGET_ARCH64 && ! TARGET_HARD_QUAD"
4633  "emit_tfmode_cvt (UNSIGNED_FLOAT, operands); DONE;")
4634
4635;; Now the same for 64 bit sources.
4636
4637(define_insn "floatdisf2"
4638  [(set (match_operand:SF 0 "register_operand" "=f")
4639	(float:SF (match_operand:DI 1 "register_operand" "e")))]
4640  "TARGET_V9 && TARGET_FPU"
4641  "fxtos\t%1, %0"
4642  [(set_attr "type" "fp")
4643   (set_attr "fptype" "double")])
4644
4645(define_expand "floatunsdisf2"
4646  [(use (match_operand:SF 0 "register_operand" ""))
4647   (use (match_operand:DI 1 "general_operand" ""))]
4648  "TARGET_ARCH64 && TARGET_FPU"
4649  "sparc_emit_floatunsdi (operands, SFmode); DONE;")
4650
4651(define_insn "floatdidf2"
4652  [(set (match_operand:DF 0 "register_operand" "=e")
4653	(float:DF (match_operand:DI 1 "register_operand" "e")))]
4654  "TARGET_V9 && TARGET_FPU"
4655  "fxtod\t%1, %0"
4656  [(set_attr "type" "fp")
4657   (set_attr "fptype" "double")])
4658
4659(define_expand "floatunsdidf2"
4660  [(use (match_operand:DF 0 "register_operand" ""))
4661   (use (match_operand:DI 1 "general_operand" ""))]
4662  "TARGET_ARCH64 && TARGET_FPU"
4663  "sparc_emit_floatunsdi (operands, DFmode); DONE;")
4664
4665(define_expand "floatditf2"
4666  [(set (match_operand:TF 0 "nonimmediate_operand" "")
4667	(float:TF (match_operand:DI 1 "register_operand" "")))]
4668  "TARGET_FPU && TARGET_V9 && (TARGET_HARD_QUAD || TARGET_ARCH64)"
4669  "emit_tfmode_cvt (FLOAT, operands); DONE;")
4670
4671(define_insn "*floatditf2_hq"
4672  [(set (match_operand:TF 0 "register_operand" "=e")
4673	(float:TF (match_operand:DI 1 "register_operand" "e")))]
4674  "TARGET_V9 && TARGET_FPU && TARGET_HARD_QUAD"
4675  "fxtoq\t%1, %0"
4676  [(set_attr "type" "fp")])
4677
4678(define_expand "floatunsditf2"
4679  [(set (match_operand:TF 0 "nonimmediate_operand" "")
4680	(unsigned_float:TF (match_operand:DI 1 "register_operand" "")))]
4681  "TARGET_FPU && TARGET_ARCH64 && ! TARGET_HARD_QUAD"
4682  "emit_tfmode_cvt (UNSIGNED_FLOAT, operands); DONE;")
4683
4684;; Convert a float to an actual integer.
4685;; Truncation is performed as part of the conversion.
4686
4687(define_insn "fix_truncsfsi2"
4688  [(set (match_operand:SI 0 "register_operand" "=f")
4689	(fix:SI (fix:SF (match_operand:SF 1 "register_operand" "f"))))]
4690  "TARGET_FPU"
4691  "fstoi\t%1, %0"
4692  [(set_attr "type" "fp")
4693   (set_attr "fptype" "double")])
4694
4695(define_insn "fix_truncdfsi2"
4696  [(set (match_operand:SI 0 "register_operand" "=f")
4697	(fix:SI (fix:DF (match_operand:DF 1 "register_operand" "e"))))]
4698  "TARGET_FPU"
4699  "fdtoi\t%1, %0"
4700  [(set_attr "type" "fp")
4701   (set_attr "fptype" "double")])
4702
4703(define_expand "fix_trunctfsi2"
4704  [(set (match_operand:SI 0 "register_operand" "")
4705	(fix:SI (match_operand:TF 1 "general_operand" "")))]
4706  "TARGET_FPU && (TARGET_HARD_QUAD || TARGET_ARCH64)"
4707  "emit_tfmode_cvt (FIX, operands); DONE;")
4708
4709(define_insn "*fix_trunctfsi2_hq"
4710  [(set (match_operand:SI 0 "register_operand" "=f")
4711	(fix:SI (match_operand:TF 1 "register_operand" "e")))]
4712  "TARGET_FPU && TARGET_HARD_QUAD"
4713  "fqtoi\t%1, %0"
4714  [(set_attr "type" "fp")])
4715
4716(define_expand "fixuns_trunctfsi2"
4717  [(set (match_operand:SI 0 "register_operand" "")
4718	(unsigned_fix:SI (match_operand:TF 1 "general_operand" "")))]
4719  "TARGET_FPU && TARGET_ARCH64 && ! TARGET_HARD_QUAD"
4720  "emit_tfmode_cvt (UNSIGNED_FIX, operands); DONE;")
4721
4722;; Now the same, for V9 targets
4723
4724(define_insn "fix_truncsfdi2"
4725  [(set (match_operand:DI 0 "register_operand" "=e")
4726	(fix:DI (fix:SF (match_operand:SF 1 "register_operand" "f"))))]
4727  "TARGET_V9 && TARGET_FPU"
4728  "fstox\t%1, %0"
4729  [(set_attr "type" "fp")
4730   (set_attr "fptype" "double")])
4731
4732(define_expand "fixuns_truncsfdi2"
4733  [(use (match_operand:DI 0 "register_operand" ""))
4734   (use (match_operand:SF 1 "general_operand" ""))]
4735  "TARGET_ARCH64 && TARGET_FPU"
4736  "sparc_emit_fixunsdi (operands, SFmode); DONE;")
4737
4738(define_insn "fix_truncdfdi2"
4739  [(set (match_operand:DI 0 "register_operand" "=e")
4740	(fix:DI (fix:DF (match_operand:DF 1 "register_operand" "e"))))]
4741  "TARGET_V9 && TARGET_FPU"
4742  "fdtox\t%1, %0"
4743  [(set_attr "type" "fp")
4744   (set_attr "fptype" "double")])
4745
4746(define_expand "fixuns_truncdfdi2"
4747  [(use (match_operand:DI 0 "register_operand" ""))
4748   (use (match_operand:DF 1 "general_operand" ""))]
4749  "TARGET_ARCH64 && TARGET_FPU"
4750  "sparc_emit_fixunsdi (operands, DFmode); DONE;")
4751
4752(define_expand "fix_trunctfdi2"
4753  [(set (match_operand:DI 0 "register_operand" "")
4754	(fix:DI (match_operand:TF 1 "general_operand" "")))]
4755  "TARGET_V9 && TARGET_FPU && (TARGET_HARD_QUAD || TARGET_ARCH64)"
4756  "emit_tfmode_cvt (FIX, operands); DONE;")
4757
4758(define_insn "*fix_trunctfdi2_hq"
4759  [(set (match_operand:DI 0 "register_operand" "=e")
4760	(fix:DI (match_operand:TF 1 "register_operand" "e")))]
4761  "TARGET_V9 && TARGET_FPU && TARGET_HARD_QUAD"
4762  "fqtox\t%1, %0"
4763  [(set_attr "type" "fp")])
4764
4765(define_expand "fixuns_trunctfdi2"
4766  [(set (match_operand:DI 0 "register_operand" "")
4767	(unsigned_fix:DI (match_operand:TF 1 "general_operand" "")))]
4768  "TARGET_FPU && TARGET_ARCH64 && ! TARGET_HARD_QUAD"
4769  "emit_tfmode_cvt (UNSIGNED_FIX, operands); DONE;")
4770
4771;;- arithmetic instructions
4772
4773(define_expand "adddi3"
4774  [(set (match_operand:DI 0 "register_operand" "")
4775	(plus:DI (match_operand:DI 1 "register_operand" "")
4776		 (match_operand:DI 2 "arith_double_add_operand" "")))]
4777  ""
4778{
4779  if (! TARGET_ARCH64)
4780    {
4781      emit_insn (gen_rtx_PARALLEL (VOIDmode, gen_rtvec (2,
4782			  gen_rtx_SET (VOIDmode, operands[0],
4783				   gen_rtx_PLUS (DImode, operands[1],
4784						 operands[2])),
4785			  gen_rtx_CLOBBER (VOIDmode,
4786				   gen_rtx_REG (CCmode, SPARC_ICC_REG)))));
4787      DONE;
4788    }
4789})
4790
4791(define_insn_and_split "adddi3_insn_sp32"
4792  [(set (match_operand:DI 0 "register_operand" "=r")
4793	(plus:DI (match_operand:DI 1 "arith_double_operand" "%r")
4794		 (match_operand:DI 2 "arith_double_operand" "rHI")))
4795   (clobber (reg:CC 100))]
4796  "! TARGET_ARCH64"
4797  "#"
4798  "&& reload_completed"
4799  [(parallel [(set (reg:CC_NOOV 100)
4800		   (compare:CC_NOOV (plus:SI (match_dup 4)
4801					     (match_dup 5))
4802				    (const_int 0)))
4803	      (set (match_dup 3)
4804		   (plus:SI (match_dup 4) (match_dup 5)))])
4805   (set (match_dup 6)
4806	(plus:SI (plus:SI (match_dup 7)
4807			  (match_dup 8))
4808		 (ltu:SI (reg:CC_NOOV 100) (const_int 0))))]
4809{
4810  operands[3] = gen_lowpart (SImode, operands[0]);
4811  operands[4] = gen_lowpart (SImode, operands[1]);
4812  operands[5] = gen_lowpart (SImode, operands[2]);
4813  operands[6] = gen_highpart (SImode, operands[0]);
4814  operands[7] = gen_highpart_mode (SImode, DImode, operands[1]);
4815#if HOST_BITS_PER_WIDE_INT == 32
4816  if (GET_CODE (operands[2]) == CONST_INT)
4817    {
4818      if (INTVAL (operands[2]) < 0)
4819	operands[8] = constm1_rtx;
4820      else
4821	operands[8] = const0_rtx;
4822    }
4823  else
4824#endif
4825    operands[8] = gen_highpart_mode (SImode, DImode, operands[2]);
4826}
4827  [(set_attr "length" "2")])
4828
4829(define_split
4830  [(set (match_operand:DI 0 "register_operand" "")
4831	(minus:DI (match_operand:DI 1 "arith_double_operand" "")
4832		  (match_operand:DI 2 "arith_double_operand" "")))
4833   (clobber (reg:CC 100))]
4834  "! TARGET_ARCH64 && reload_completed"
4835  [(parallel [(set (reg:CC_NOOV 100)
4836		   (compare:CC_NOOV (minus:SI (match_dup 4)
4837					      (match_dup 5))
4838				    (const_int 0)))
4839	      (set (match_dup 3)
4840		   (minus:SI (match_dup 4) (match_dup 5)))])
4841   (set (match_dup 6)
4842	(minus:SI (minus:SI (match_dup 7)
4843			    (match_dup 8))
4844		  (ltu:SI (reg:CC_NOOV 100) (const_int 0))))]
4845{
4846  operands[3] = gen_lowpart (SImode, operands[0]);
4847  operands[4] = gen_lowpart (SImode, operands[1]);
4848  operands[5] = gen_lowpart (SImode, operands[2]);
4849  operands[6] = gen_highpart (SImode, operands[0]);
4850  operands[7] = gen_highpart (SImode, operands[1]);
4851#if HOST_BITS_PER_WIDE_INT == 32
4852  if (GET_CODE (operands[2]) == CONST_INT)
4853    {
4854      if (INTVAL (operands[2]) < 0)
4855	operands[8] = constm1_rtx;
4856      else
4857	operands[8] = const0_rtx;
4858    }
4859  else
4860#endif
4861    operands[8] = gen_highpart_mode (SImode, DImode, operands[2]);
4862})
4863
4864;; LTU here means "carry set"
4865(define_insn "addx"
4866  [(set (match_operand:SI 0 "register_operand" "=r")
4867	(plus:SI (plus:SI (match_operand:SI 1 "arith_operand" "%r")
4868			  (match_operand:SI 2 "arith_operand" "rI"))
4869		 (ltu:SI (reg:CC_NOOV 100) (const_int 0))))]
4870  ""
4871  "addx\t%1, %2, %0"
4872  [(set_attr "type" "ialuX")])
4873
4874(define_insn_and_split "*addx_extend_sp32"
4875  [(set (match_operand:DI 0 "register_operand" "=r")
4876	(zero_extend:DI (plus:SI (plus:SI
4877                                  (match_operand:SI 1 "reg_or_0_operand" "%rJ")
4878                                  (match_operand:SI 2 "arith_operand" "rI"))
4879                                 (ltu:SI (reg:CC_NOOV 100) (const_int 0)))))]
4880  "! TARGET_ARCH64"
4881  "#"
4882  "&& reload_completed"
4883  [(set (match_dup 3) (plus:SI (plus:SI (match_dup 1) (match_dup 2))
4884                               (ltu:SI (reg:CC_NOOV 100) (const_int 0))))
4885   (set (match_dup 4) (const_int 0))]
4886  "operands[3] = gen_lowpart (SImode, operands[0]);
4887   operands[4] = gen_highpart_mode (SImode, DImode, operands[1]);"
4888  [(set_attr "length" "2")])
4889
4890(define_insn "*addx_extend_sp64"
4891  [(set (match_operand:DI 0 "register_operand" "=r")
4892	(zero_extend:DI (plus:SI (plus:SI (match_operand:SI 1 "reg_or_0_operand" "%rJ")
4893                                          (match_operand:SI 2 "arith_operand" "rI"))
4894                                 (ltu:SI (reg:CC_NOOV 100) (const_int 0)))))]
4895  "TARGET_ARCH64"
4896  "addx\t%r1, %2, %0"
4897  [(set_attr "type" "ialuX")])
4898
4899(define_insn "subx"
4900  [(set (match_operand:SI 0 "register_operand" "=r")
4901	(minus:SI (minus:SI (match_operand:SI 1 "reg_or_0_operand" "rJ")
4902			    (match_operand:SI 2 "arith_operand" "rI"))
4903		  (ltu:SI (reg:CC_NOOV 100) (const_int 0))))]
4904  ""
4905  "subx\t%r1, %2, %0"
4906  [(set_attr "type" "ialuX")])
4907
4908(define_insn "*subx_extend_sp64"
4909  [(set (match_operand:DI 0 "register_operand" "=r")
4910	(zero_extend:DI (minus:SI (minus:SI (match_operand:SI 1 "reg_or_0_operand" "rJ")
4911                                            (match_operand:SI 2 "arith_operand" "rI"))
4912                                  (ltu:SI (reg:CC_NOOV 100) (const_int 0)))))]
4913  "TARGET_ARCH64"
4914  "subx\t%r1, %2, %0"
4915  [(set_attr "type" "ialuX")])
4916
4917(define_insn_and_split "*subx_extend"
4918  [(set (match_operand:DI 0 "register_operand" "=r")
4919	(zero_extend:DI (minus:SI (minus:SI (match_operand:SI 1 "reg_or_0_operand" "rJ")
4920                                            (match_operand:SI 2 "arith_operand" "rI"))
4921                                  (ltu:SI (reg:CC_NOOV 100) (const_int 0)))))]
4922  "! TARGET_ARCH64"
4923  "#"
4924  "&& reload_completed"
4925  [(set (match_dup 3) (minus:SI (minus:SI (match_dup 1) (match_dup 2))
4926                                (ltu:SI (reg:CC_NOOV 100) (const_int 0))))
4927   (set (match_dup 4) (const_int 0))]
4928  "operands[3] = gen_lowpart (SImode, operands[0]);
4929   operands[4] = gen_highpart (SImode, operands[0]);"
4930  [(set_attr "length" "2")])
4931
4932(define_insn_and_split ""
4933  [(set (match_operand:DI 0 "register_operand" "=r")
4934        (plus:DI (zero_extend:DI (match_operand:SI 1 "register_operand" "r"))
4935                 (match_operand:DI 2 "register_operand" "r")))
4936   (clobber (reg:CC 100))]
4937  "! TARGET_ARCH64"
4938  "#"
4939  "&& reload_completed"
4940  [(parallel [(set (reg:CC_NOOV 100)
4941                   (compare:CC_NOOV (plus:SI (match_dup 3) (match_dup 1))
4942                                    (const_int 0)))
4943              (set (match_dup 5) (plus:SI (match_dup 3) (match_dup 1)))])
4944   (set (match_dup 6)
4945        (plus:SI (plus:SI (match_dup 4) (const_int 0))
4946                 (ltu:SI (reg:CC_NOOV 100) (const_int 0))))]
4947  "operands[3] = gen_lowpart (SImode, operands[2]);
4948   operands[4] = gen_highpart (SImode, operands[2]);
4949   operands[5] = gen_lowpart (SImode, operands[0]);
4950   operands[6] = gen_highpart (SImode, operands[0]);"
4951  [(set_attr "length" "2")])
4952
4953(define_insn "*adddi3_sp64"
4954  [(set (match_operand:DI 0 "register_operand" "=r,r")
4955	(plus:DI (match_operand:DI 1 "register_operand" "%r,r")
4956		 (match_operand:DI 2 "arith_double_add_operand" "rHI,O")))]
4957  "TARGET_ARCH64"
4958  "@
4959   add\t%1, %2, %0
4960   sub\t%1, -%2, %0")
4961
4962(define_insn "addsi3"
4963  [(set (match_operand:SI 0 "register_operand" "=r,r,d")
4964	(plus:SI (match_operand:SI 1 "register_operand" "%r,r,d")
4965		 (match_operand:SI 2 "arith_add_operand" "rI,O,d")))]
4966  ""
4967  "@
4968   add\t%1, %2, %0
4969   sub\t%1, -%2, %0
4970   fpadd32s\t%1, %2, %0"
4971  [(set_attr "type" "*,*,fp")])
4972
4973(define_insn "*cmp_cc_plus"
4974  [(set (reg:CC_NOOV 100)
4975	(compare:CC_NOOV (plus:SI (match_operand:SI 0 "arith_operand" "%r")
4976				  (match_operand:SI 1 "arith_operand" "rI"))
4977			 (const_int 0)))]
4978  ""
4979  "addcc\t%0, %1, %%g0"
4980  [(set_attr "type" "compare")])
4981
4982(define_insn "*cmp_ccx_plus"
4983  [(set (reg:CCX_NOOV 100)
4984	(compare:CCX_NOOV (plus:DI (match_operand:DI 0 "arith_double_operand" "%r")
4985				   (match_operand:DI 1 "arith_double_operand" "rHI"))
4986			  (const_int 0)))]
4987  "TARGET_ARCH64"
4988  "addcc\t%0, %1, %%g0"
4989  [(set_attr "type" "compare")])
4990
4991(define_insn "*cmp_cc_plus_set"
4992  [(set (reg:CC_NOOV 100)
4993	(compare:CC_NOOV (plus:SI (match_operand:SI 1 "arith_operand" "%r")
4994				  (match_operand:SI 2 "arith_operand" "rI"))
4995			 (const_int 0)))
4996   (set (match_operand:SI 0 "register_operand" "=r")
4997	(plus:SI (match_dup 1) (match_dup 2)))]
4998  ""
4999  "addcc\t%1, %2, %0"
5000  [(set_attr "type" "compare")])
5001
5002(define_insn "*cmp_ccx_plus_set"
5003  [(set (reg:CCX_NOOV 100)
5004	(compare:CCX_NOOV (plus:DI (match_operand:DI 1 "arith_double_operand" "%r")
5005				   (match_operand:DI 2 "arith_double_operand" "rHI"))
5006			  (const_int 0)))
5007   (set (match_operand:DI 0 "register_operand" "=r")
5008	(plus:DI (match_dup 1) (match_dup 2)))]
5009  "TARGET_ARCH64"
5010  "addcc\t%1, %2, %0"
5011  [(set_attr "type" "compare")])
5012
5013(define_expand "subdi3"
5014  [(set (match_operand:DI 0 "register_operand" "")
5015	(minus:DI (match_operand:DI 1 "register_operand" "")
5016		  (match_operand:DI 2 "arith_double_add_operand" "")))]
5017  ""
5018{
5019  if (! TARGET_ARCH64)
5020    {
5021      emit_insn (gen_rtx_PARALLEL (VOIDmode, gen_rtvec (2,
5022			  gen_rtx_SET (VOIDmode, operands[0],
5023				   gen_rtx_MINUS (DImode, operands[1],
5024						  operands[2])),
5025			  gen_rtx_CLOBBER (VOIDmode,
5026				   gen_rtx_REG (CCmode, SPARC_ICC_REG)))));
5027      DONE;
5028    }
5029})
5030
5031(define_insn_and_split "*subdi3_sp32"
5032  [(set (match_operand:DI 0 "register_operand" "=r")
5033        (minus:DI (match_operand:DI 1 "register_operand" "r")
5034                  (match_operand:DI 2 "arith_double_operand" "rHI")))
5035   (clobber (reg:CC 100))]
5036  "! TARGET_ARCH64"
5037  "#"
5038  "&& reload_completed
5039   && (GET_CODE (operands[2]) == CONST_INT
5040       || GET_CODE (operands[2]) == CONST_DOUBLE)"
5041  [(clobber (const_int 0))]
5042{
5043  rtx highp, lowp;
5044
5045  highp = gen_highpart_mode (SImode, DImode, operands[2]);
5046  lowp = gen_lowpart (SImode, operands[2]);
5047  if ((lowp == const0_rtx)
5048      && (operands[0] == operands[1]))
5049    {
5050      emit_insn (gen_rtx_SET (VOIDmode,
5051                              gen_highpart (SImode, operands[0]),
5052                              gen_rtx_MINUS (SImode,
5053                                             gen_highpart_mode (SImode, DImode,
5054								operands[1]),
5055                                             highp)));
5056    }
5057  else
5058    {
5059      emit_insn (gen_cmp_minus_cc_set (gen_lowpart (SImode, operands[0]),
5060                                       gen_lowpart (SImode, operands[1]),
5061                                       lowp));
5062      emit_insn (gen_subx (gen_highpart (SImode, operands[0]),
5063                           gen_highpart_mode (SImode, DImode, operands[1]),
5064                           highp));
5065    }
5066  DONE;
5067}
5068  [(set_attr "length" "2")])
5069
5070(define_split
5071  [(set (match_operand:DI 0 "register_operand" "")
5072        (minus:DI (match_operand:DI 1 "register_operand" "")
5073                  (match_operand:DI 2 "register_operand" "")))
5074   (clobber (reg:CC 100))]
5075  "! TARGET_ARCH64
5076   && reload_completed"
5077  [(clobber (const_int 0))]
5078{
5079  emit_insn (gen_cmp_minus_cc_set (gen_lowpart (SImode, operands[0]),
5080                                   gen_lowpart (SImode, operands[1]),
5081                                   gen_lowpart (SImode, operands[2])));
5082  emit_insn (gen_subx (gen_highpart (SImode, operands[0]),
5083                       gen_highpart (SImode, operands[1]),
5084                       gen_highpart (SImode, operands[2])));
5085  DONE;
5086})
5087
5088(define_insn_and_split ""
5089  [(set (match_operand:DI 0 "register_operand" "=r")
5090      (minus:DI (match_operand:DI 1 "register_operand" "r")
5091                (zero_extend:DI (match_operand:SI 2 "register_operand" "r"))))
5092   (clobber (reg:CC 100))]
5093  "! TARGET_ARCH64"
5094  "#"
5095  "&& reload_completed"
5096  [(parallel [(set (reg:CC_NOOV 100)
5097                   (compare:CC_NOOV (minus:SI (match_dup 3) (match_dup 2))
5098                                    (const_int 0)))
5099              (set (match_dup 5) (minus:SI (match_dup 3) (match_dup 2)))])
5100   (set (match_dup 6)
5101        (minus:SI (minus:SI (match_dup 4) (const_int 0))
5102                  (ltu:SI (reg:CC_NOOV 100) (const_int 0))))]
5103  "operands[3] = gen_lowpart (SImode, operands[1]);
5104   operands[4] = gen_highpart (SImode, operands[1]);
5105   operands[5] = gen_lowpart (SImode, operands[0]);
5106   operands[6] = gen_highpart (SImode, operands[0]);"
5107  [(set_attr "length" "2")])
5108
5109(define_insn "*subdi3_sp64"
5110  [(set (match_operand:DI 0 "register_operand" "=r,r")
5111	(minus:DI (match_operand:DI 1 "register_operand" "r,r")
5112		  (match_operand:DI 2 "arith_double_add_operand" "rHI,O")))]
5113  "TARGET_ARCH64"
5114  "@
5115   sub\t%1, %2, %0
5116   add\t%1, -%2, %0")
5117
5118(define_insn "subsi3"
5119  [(set (match_operand:SI 0 "register_operand" "=r,r,d")
5120	(minus:SI (match_operand:SI 1 "register_operand" "r,r,d")
5121		  (match_operand:SI 2 "arith_add_operand" "rI,O,d")))]
5122  ""
5123  "@
5124   sub\t%1, %2, %0
5125   add\t%1, -%2, %0
5126   fpsub32s\t%1, %2, %0"
5127  [(set_attr "type" "*,*,fp")])
5128
5129(define_insn "*cmp_minus_cc"
5130  [(set (reg:CC_NOOV 100)
5131	(compare:CC_NOOV (minus:SI (match_operand:SI 0 "reg_or_0_operand" "rJ")
5132				   (match_operand:SI 1 "arith_operand" "rI"))
5133			 (const_int 0)))]
5134  ""
5135  "subcc\t%r0, %1, %%g0"
5136  [(set_attr "type" "compare")])
5137
5138(define_insn "*cmp_minus_ccx"
5139  [(set (reg:CCX_NOOV 100)
5140	(compare:CCX_NOOV (minus:DI (match_operand:DI 0 "register_operand" "r")
5141				    (match_operand:DI 1 "arith_double_operand" "rHI"))
5142			  (const_int 0)))]
5143  "TARGET_ARCH64"
5144  "subcc\t%0, %1, %%g0"
5145  [(set_attr "type" "compare")])
5146
5147(define_insn "cmp_minus_cc_set"
5148  [(set (reg:CC_NOOV 100)
5149	(compare:CC_NOOV (minus:SI (match_operand:SI 1 "reg_or_0_operand" "rJ")
5150				   (match_operand:SI 2 "arith_operand" "rI"))
5151			 (const_int 0)))
5152   (set (match_operand:SI 0 "register_operand" "=r")
5153	(minus:SI (match_dup 1) (match_dup 2)))]
5154  ""
5155  "subcc\t%r1, %2, %0"
5156  [(set_attr "type" "compare")])
5157
5158(define_insn "*cmp_minus_ccx_set"
5159  [(set (reg:CCX_NOOV 100)
5160	(compare:CCX_NOOV (minus:DI (match_operand:DI 1 "register_operand" "r")
5161				    (match_operand:DI 2 "arith_double_operand" "rHI"))
5162			  (const_int 0)))
5163   (set (match_operand:DI 0 "register_operand" "=r")
5164	(minus:DI (match_dup 1) (match_dup 2)))]
5165  "TARGET_ARCH64"
5166  "subcc\t%1, %2, %0"
5167  [(set_attr "type" "compare")])
5168
5169;; Integer Multiply/Divide.
5170
5171;; The 32 bit multiply/divide instructions are deprecated on v9, but at
5172;; least in UltraSPARC I, II and IIi it is a win tick-wise.
5173
5174(define_insn "mulsi3"
5175  [(set (match_operand:SI 0 "register_operand" "=r")
5176	(mult:SI (match_operand:SI 1 "arith_operand" "%r")
5177		 (match_operand:SI 2 "arith_operand" "rI")))]
5178  "TARGET_HARD_MUL"
5179  "smul\t%1, %2, %0"
5180  [(set_attr "type" "imul")])
5181
5182(define_expand "muldi3"
5183  [(set (match_operand:DI 0 "register_operand" "=r")
5184	(mult:DI (match_operand:DI 1 "arith_double_operand" "%r")
5185		 (match_operand:DI 2 "arith_double_operand" "rHI")))]
5186  "TARGET_ARCH64 || TARGET_V8PLUS"
5187{
5188  if (TARGET_V8PLUS)
5189    {
5190      emit_insn (gen_muldi3_v8plus (operands[0], operands[1], operands[2]));
5191      DONE;
5192    }
5193})
5194
5195(define_insn "*muldi3_sp64"
5196  [(set (match_operand:DI 0 "register_operand" "=r")
5197	(mult:DI (match_operand:DI 1 "arith_double_operand" "%r")
5198		 (match_operand:DI 2 "arith_double_operand" "rHI")))]
5199  "TARGET_ARCH64"
5200  "mulx\t%1, %2, %0"
5201  [(set_attr "type" "imul")])
5202
5203;; V8plus wide multiply.
5204;; XXX
5205(define_insn "muldi3_v8plus"
5206  [(set (match_operand:DI 0 "register_operand" "=r,h")
5207	(mult:DI (match_operand:DI 1 "arith_double_operand" "%r,0")
5208		 (match_operand:DI 2 "arith_double_operand" "rI,rI")))
5209   (clobber (match_scratch:SI 3 "=&h,X"))
5210   (clobber (match_scratch:SI 4 "=&h,X"))]
5211  "TARGET_V8PLUS"
5212{
5213  if (sparc_check_64 (operands[1], insn) <= 0)
5214    output_asm_insn ("srl\t%L1, 0, %L1", operands);
5215  if (which_alternative == 1)
5216    output_asm_insn ("sllx\t%H1, 32, %H1", operands);
5217  if (GET_CODE (operands[2]) == CONST_INT)
5218    {
5219      if (which_alternative == 1)
5220	return "or\t%L1, %H1, %H1\n\tmulx\t%H1, %2, %L0\;srlx\t%L0, 32, %H0";
5221      else
5222	return "sllx\t%H1, 32, %3\n\tor\t%L1, %3, %3\n\tmulx\t%3, %2, %3\n\tsrlx\t%3, 32, %H0\n\tmov\t%3, %L0";
5223    }
5224  else if (rtx_equal_p (operands[1], operands[2]))
5225    {
5226      if (which_alternative == 1)
5227	return "or\t%L1, %H1, %H1\n\tmulx\t%H1, %H1, %L0\;srlx\t%L0, 32, %H0";
5228      else
5229	return "sllx\t%H1, 32, %3\n\tor\t%L1, %3, %3\n\tmulx\t%3, %3, %3\n\tsrlx\t%3, 32, %H0\n\tmov\t%3, %L0";
5230    }
5231  if (sparc_check_64 (operands[2], insn) <= 0)
5232    output_asm_insn ("srl\t%L2, 0, %L2", operands);
5233  if (which_alternative == 1)
5234    return "or\t%L1, %H1, %H1\n\tsllx\t%H2, 32, %L1\n\tor\t%L2, %L1, %L1\n\tmulx\t%H1, %L1, %L0\;srlx\t%L0, 32, %H0";
5235  else
5236    return "sllx\t%H1, 32, %3\n\tsllx\t%H2, 32, %4\n\tor\t%L1, %3, %3\n\tor\t%L2, %4, %4\n\tmulx\t%3, %4, %3\n\tsrlx\t%3, 32, %H0\n\tmov\t%3, %L0";
5237}
5238  [(set_attr "type" "multi")
5239   (set_attr "length" "9,8")])
5240
5241(define_insn "*cmp_mul_set"
5242  [(set (reg:CC 100)
5243	(compare:CC (mult:SI (match_operand:SI 1 "arith_operand" "%r")
5244		    (match_operand:SI 2 "arith_operand" "rI"))
5245		    (const_int 0)))
5246   (set (match_operand:SI 0 "register_operand" "=r")
5247	(mult:SI (match_dup 1) (match_dup 2)))]
5248  "TARGET_V8 || TARGET_SPARCLITE || TARGET_DEPRECATED_V8_INSNS"
5249  "smulcc\t%1, %2, %0"
5250  [(set_attr "type" "imul")])
5251
5252(define_expand "mulsidi3"
5253  [(set (match_operand:DI 0 "register_operand" "")
5254	(mult:DI (sign_extend:DI (match_operand:SI 1 "register_operand" ""))
5255		 (sign_extend:DI (match_operand:SI 2 "arith_operand" ""))))]
5256  "TARGET_HARD_MUL"
5257{
5258  if (CONSTANT_P (operands[2]))
5259    {
5260      if (TARGET_V8PLUS)
5261	emit_insn (gen_const_mulsidi3_v8plus (operands[0], operands[1],
5262					      operands[2]));
5263      else if (TARGET_ARCH32)
5264	emit_insn (gen_const_mulsidi3_sp32 (operands[0], operands[1],
5265					    operands[2]));
5266      else
5267	emit_insn (gen_const_mulsidi3_sp64 (operands[0], operands[1],
5268					    operands[2]));
5269      DONE;
5270    }
5271  if (TARGET_V8PLUS)
5272    {
5273      emit_insn (gen_mulsidi3_v8plus (operands[0], operands[1], operands[2]));
5274      DONE;
5275    }
5276})
5277
5278;; V9 puts the 64 bit product in a 64 bit register.  Only out or global
5279;; registers can hold 64 bit values in the V8plus environment.
5280;; XXX
5281(define_insn "mulsidi3_v8plus"
5282  [(set (match_operand:DI 0 "register_operand" "=h,r")
5283	(mult:DI (sign_extend:DI (match_operand:SI 1 "register_operand" "r,r"))
5284		 (sign_extend:DI (match_operand:SI 2 "register_operand" "r,r"))))
5285   (clobber (match_scratch:SI 3 "=X,&h"))]
5286  "TARGET_V8PLUS"
5287  "@
5288   smul\t%1, %2, %L0\n\tsrlx\t%L0, 32, %H0
5289   smul\t%1, %2, %3\n\tsrlx\t%3, 32, %H0\n\tmov\t%3, %L0"
5290  [(set_attr "type" "multi")
5291   (set_attr "length" "2,3")])
5292
5293;; XXX
5294(define_insn "const_mulsidi3_v8plus"
5295  [(set (match_operand:DI 0 "register_operand" "=h,r")
5296	(mult:DI (sign_extend:DI (match_operand:SI 1 "register_operand" "r,r"))
5297		 (match_operand:DI 2 "small_int" "I,I")))
5298   (clobber (match_scratch:SI 3 "=X,&h"))]
5299  "TARGET_V8PLUS"
5300  "@
5301   smul\t%1, %2, %L0\n\tsrlx\t%L0, 32, %H0
5302   smul\t%1, %2, %3\n\tsrlx\t%3, 32, %H0\n\tmov\t%3, %L0"
5303  [(set_attr "type" "multi")
5304   (set_attr "length" "2,3")])
5305
5306;; XXX
5307(define_insn "*mulsidi3_sp32"
5308  [(set (match_operand:DI 0 "register_operand" "=r")
5309	(mult:DI (sign_extend:DI (match_operand:SI 1 "register_operand" "r"))
5310		 (sign_extend:DI (match_operand:SI 2 "register_operand" "r"))))]
5311  "TARGET_HARD_MUL32"
5312{
5313  return TARGET_SPARCLET
5314         ? "smuld\t%1, %2, %L0"
5315         : "smul\t%1, %2, %L0\n\trd\t%%y, %H0";
5316}
5317  [(set (attr "type")
5318	(if_then_else (eq_attr "isa" "sparclet")
5319		      (const_string "imul") (const_string "multi")))
5320   (set (attr "length")
5321	(if_then_else (eq_attr "isa" "sparclet")
5322		      (const_int 1) (const_int 2)))])
5323
5324(define_insn "*mulsidi3_sp64"
5325  [(set (match_operand:DI 0 "register_operand" "=r")
5326	(mult:DI (sign_extend:DI (match_operand:SI 1 "register_operand" "r"))
5327		 (sign_extend:DI (match_operand:SI 2 "register_operand" "r"))))]
5328  "TARGET_DEPRECATED_V8_INSNS && TARGET_ARCH64"
5329  "smul\t%1, %2, %0"
5330  [(set_attr "type" "imul")])
5331
5332;; Extra pattern, because sign_extend of a constant isn't valid.
5333
5334;; XXX
5335(define_insn "const_mulsidi3_sp32"
5336  [(set (match_operand:DI 0 "register_operand" "=r")
5337	(mult:DI (sign_extend:DI (match_operand:SI 1 "register_operand" "r"))
5338		 (match_operand:DI 2 "small_int" "I")))]
5339  "TARGET_HARD_MUL32"
5340{
5341  return TARGET_SPARCLET
5342         ? "smuld\t%1, %2, %L0"
5343         : "smul\t%1, %2, %L0\n\trd\t%%y, %H0";
5344}
5345  [(set (attr "type")
5346	(if_then_else (eq_attr "isa" "sparclet")
5347		      (const_string "imul") (const_string "multi")))
5348   (set (attr "length")
5349	(if_then_else (eq_attr "isa" "sparclet")
5350		      (const_int 1) (const_int 2)))])
5351
5352(define_insn "const_mulsidi3_sp64"
5353  [(set (match_operand:DI 0 "register_operand" "=r")
5354	(mult:DI (sign_extend:DI (match_operand:SI 1 "register_operand" "r"))
5355		 (match_operand:DI 2 "small_int" "I")))]
5356  "TARGET_DEPRECATED_V8_INSNS && TARGET_ARCH64"
5357  "smul\t%1, %2, %0"
5358  [(set_attr "type" "imul")])
5359
5360(define_expand "smulsi3_highpart"
5361  [(set (match_operand:SI 0 "register_operand" "")
5362	(truncate:SI
5363	 (lshiftrt:DI (mult:DI (sign_extend:DI (match_operand:SI 1 "register_operand" ""))
5364			       (sign_extend:DI (match_operand:SI 2 "arith_operand" "")))
5365		      (const_int 32))))]
5366  "TARGET_HARD_MUL && TARGET_ARCH32"
5367{
5368  if (CONSTANT_P (operands[2]))
5369    {
5370      if (TARGET_V8PLUS)
5371	{
5372	  emit_insn (gen_const_smulsi3_highpart_v8plus (operands[0],
5373							operands[1],
5374							operands[2],
5375							GEN_INT (32)));
5376	  DONE;
5377	}
5378      emit_insn (gen_const_smulsi3_highpart (operands[0], operands[1], operands[2]));
5379      DONE;
5380    }
5381  if (TARGET_V8PLUS)
5382    {
5383      emit_insn (gen_smulsi3_highpart_v8plus (operands[0], operands[1],
5384					      operands[2], GEN_INT (32)));
5385      DONE;
5386    }
5387})
5388
5389;; XXX
5390(define_insn "smulsi3_highpart_v8plus"
5391  [(set (match_operand:SI 0 "register_operand" "=h,r")
5392	(truncate:SI
5393	 (lshiftrt:DI (mult:DI (sign_extend:DI (match_operand:SI 1 "register_operand" "r,r"))
5394			       (sign_extend:DI (match_operand:SI 2 "register_operand" "r,r")))
5395		      (match_operand:SI 3 "const_int_operand" "i,i"))))
5396   (clobber (match_scratch:SI 4 "=X,&h"))]
5397  "TARGET_V8PLUS"
5398  "@
5399   smul\t%1, %2, %0\;srlx\t%0, %3, %0
5400   smul\t%1, %2, %4\;srlx\t%4, %3, %0"
5401  [(set_attr "type" "multi")
5402   (set_attr "length" "2")])
5403
5404;; The combiner changes TRUNCATE in the previous pattern to SUBREG.
5405;; XXX
5406(define_insn ""
5407  [(set (match_operand:SI 0 "register_operand" "=h,r")
5408	(subreg:SI
5409	 (lshiftrt:DI
5410	  (mult:DI (sign_extend:DI (match_operand:SI 1 "register_operand" "r,r"))
5411		   (sign_extend:DI (match_operand:SI 2 "register_operand" "r,r")))
5412	  (match_operand:SI 3 "const_int_operand" "i,i"))
5413	 4))
5414   (clobber (match_scratch:SI 4 "=X,&h"))]
5415  "TARGET_V8PLUS"
5416  "@
5417   smul\t%1, %2, %0\n\tsrlx\t%0, %3, %0
5418   smul\t%1, %2, %4\n\tsrlx\t%4, %3, %0"
5419  [(set_attr "type" "multi")
5420   (set_attr "length" "2")])
5421
5422;; XXX
5423(define_insn "const_smulsi3_highpart_v8plus"
5424  [(set (match_operand:SI 0 "register_operand" "=h,r")
5425	(truncate:SI
5426	 (lshiftrt:DI (mult:DI (sign_extend:DI (match_operand:SI 1 "register_operand" "r,r"))
5427			       (match_operand:DI 2 "small_int" "i,i"))
5428		      (match_operand:SI 3 "const_int_operand" "i,i"))))
5429   (clobber (match_scratch:SI 4 "=X,&h"))]
5430  "TARGET_V8PLUS"
5431  "@
5432   smul\t%1, %2, %0\n\tsrlx\t%0, %3, %0
5433   smul\t%1, %2, %4\n\tsrlx\t%4, %3, %0"
5434  [(set_attr "type" "multi")
5435   (set_attr "length" "2")])
5436
5437;; XXX
5438(define_insn "*smulsi3_highpart_sp32"
5439  [(set (match_operand:SI 0 "register_operand" "=r")
5440	(truncate:SI
5441	 (lshiftrt:DI (mult:DI (sign_extend:DI (match_operand:SI 1 "register_operand" "r"))
5442			       (sign_extend:DI (match_operand:SI 2 "register_operand" "r")))
5443		      (const_int 32))))]
5444  "TARGET_HARD_MUL32"
5445  "smul\t%1, %2, %%g0\n\trd\t%%y, %0"
5446  [(set_attr "type" "multi")
5447   (set_attr "length" "2")])
5448
5449;; XXX
5450(define_insn "const_smulsi3_highpart"
5451  [(set (match_operand:SI 0 "register_operand" "=r")
5452	(truncate:SI
5453	 (lshiftrt:DI (mult:DI (sign_extend:DI (match_operand:SI 1 "register_operand" "r"))
5454			       (match_operand:DI 2 "small_int" "i"))
5455		      (const_int 32))))]
5456  "TARGET_HARD_MUL32"
5457  "smul\t%1, %2, %%g0\n\trd\t%%y, %0"
5458  [(set_attr "type" "multi")
5459   (set_attr "length" "2")])
5460
5461(define_expand "umulsidi3"
5462  [(set (match_operand:DI 0 "register_operand" "")
5463	(mult:DI (zero_extend:DI (match_operand:SI 1 "register_operand" ""))
5464		 (zero_extend:DI (match_operand:SI 2 "uns_arith_operand" ""))))]
5465  "TARGET_HARD_MUL"
5466{
5467  if (CONSTANT_P (operands[2]))
5468    {
5469      if (TARGET_V8PLUS)
5470	emit_insn (gen_const_umulsidi3_v8plus (operands[0], operands[1],
5471					       operands[2]));
5472      else if (TARGET_ARCH32)
5473	emit_insn (gen_const_umulsidi3_sp32 (operands[0], operands[1],
5474					     operands[2]));
5475      else
5476	emit_insn (gen_const_umulsidi3_sp64 (operands[0], operands[1],
5477					     operands[2]));
5478      DONE;
5479    }
5480  if (TARGET_V8PLUS)
5481    {
5482      emit_insn (gen_umulsidi3_v8plus (operands[0], operands[1], operands[2]));
5483      DONE;
5484    }
5485})
5486
5487;; XXX
5488(define_insn "umulsidi3_v8plus"
5489  [(set (match_operand:DI 0 "register_operand" "=h,r")
5490	(mult:DI (zero_extend:DI (match_operand:SI 1 "register_operand" "r,r"))
5491		 (zero_extend:DI (match_operand:SI 2 "register_operand" "r,r"))))
5492   (clobber (match_scratch:SI 3 "=X,&h"))]
5493  "TARGET_V8PLUS"
5494  "@
5495   umul\t%1, %2, %L0\n\tsrlx\t%L0, 32, %H0
5496   umul\t%1, %2, %3\n\tsrlx\t%3, 32, %H0\n\tmov\t%3, %L0"
5497  [(set_attr "type" "multi")
5498   (set_attr "length" "2,3")])
5499
5500;; XXX
5501(define_insn "*umulsidi3_sp32"
5502  [(set (match_operand:DI 0 "register_operand" "=r")
5503	(mult:DI (zero_extend:DI (match_operand:SI 1 "register_operand" "r"))
5504		 (zero_extend:DI (match_operand:SI 2 "register_operand" "r"))))]
5505  "TARGET_HARD_MUL32"
5506{
5507  return TARGET_SPARCLET
5508         ? "umuld\t%1, %2, %L0"
5509         : "umul\t%1, %2, %L0\n\trd\t%%y, %H0";
5510}
5511  [(set (attr "type")
5512        (if_then_else (eq_attr "isa" "sparclet")
5513                      (const_string "imul") (const_string "multi")))
5514   (set (attr "length")
5515	(if_then_else (eq_attr "isa" "sparclet")
5516		      (const_int 1) (const_int 2)))])
5517
5518(define_insn "*umulsidi3_sp64"
5519  [(set (match_operand:DI 0 "register_operand" "=r")
5520	(mult:DI (zero_extend:DI (match_operand:SI 1 "register_operand" "r"))
5521		 (zero_extend:DI (match_operand:SI 2 "register_operand" "r"))))]
5522  "TARGET_DEPRECATED_V8_INSNS && TARGET_ARCH64"
5523  "umul\t%1, %2, %0"
5524  [(set_attr "type" "imul")])
5525
5526;; Extra pattern, because sign_extend of a constant isn't valid.
5527
5528;; XXX
5529(define_insn "const_umulsidi3_sp32"
5530  [(set (match_operand:DI 0 "register_operand" "=r")
5531	(mult:DI (zero_extend:DI (match_operand:SI 1 "register_operand" "r"))
5532		 (match_operand:DI 2 "uns_small_int" "")))]
5533  "TARGET_HARD_MUL32"
5534{
5535  return TARGET_SPARCLET
5536         ? "umuld\t%1, %s2, %L0"
5537         : "umul\t%1, %s2, %L0\n\trd\t%%y, %H0";
5538}
5539  [(set (attr "type")
5540	(if_then_else (eq_attr "isa" "sparclet")
5541		      (const_string "imul") (const_string "multi")))
5542   (set (attr "length")
5543	(if_then_else (eq_attr "isa" "sparclet")
5544		      (const_int 1) (const_int 2)))])
5545
5546(define_insn "const_umulsidi3_sp64"
5547  [(set (match_operand:DI 0 "register_operand" "=r")
5548	(mult:DI (zero_extend:DI (match_operand:SI 1 "register_operand" "r"))
5549		 (match_operand:DI 2 "uns_small_int" "")))]
5550  "TARGET_DEPRECATED_V8_INSNS && TARGET_ARCH64"
5551  "umul\t%1, %s2, %0"
5552  [(set_attr "type" "imul")])
5553
5554;; XXX
5555(define_insn "const_umulsidi3_v8plus"
5556  [(set (match_operand:DI 0 "register_operand" "=h,r")
5557	(mult:DI (zero_extend:DI (match_operand:SI 1 "register_operand" "r,r"))
5558		 (match_operand:DI 2 "uns_small_int" "")))
5559   (clobber (match_scratch:SI 3 "=X,h"))]
5560  "TARGET_V8PLUS"
5561  "@
5562   umul\t%1, %s2, %L0\n\tsrlx\t%L0, 32, %H0
5563   umul\t%1, %s2, %3\n\tsrlx\t%3, 32, %H0\n\tmov\t%3, %L0"
5564  [(set_attr "type" "multi")
5565   (set_attr "length" "2,3")])
5566
5567(define_expand "umulsi3_highpart"
5568  [(set (match_operand:SI 0 "register_operand" "")
5569	(truncate:SI
5570	 (lshiftrt:DI (mult:DI (zero_extend:DI (match_operand:SI 1 "register_operand" ""))
5571			       (zero_extend:DI (match_operand:SI 2 "uns_arith_operand" "")))
5572		      (const_int 32))))]
5573  "TARGET_HARD_MUL && TARGET_ARCH32"
5574{
5575  if (CONSTANT_P (operands[2]))
5576    {
5577      if (TARGET_V8PLUS)
5578	{
5579	  emit_insn (gen_const_umulsi3_highpart_v8plus (operands[0],
5580							operands[1],
5581							operands[2],
5582							GEN_INT (32)));
5583	  DONE;
5584	}
5585      emit_insn (gen_const_umulsi3_highpart (operands[0], operands[1], operands[2]));
5586      DONE;
5587    }
5588  if (TARGET_V8PLUS)
5589    {
5590      emit_insn (gen_umulsi3_highpart_v8plus (operands[0], operands[1],
5591					      operands[2], GEN_INT (32)));
5592      DONE;
5593    }
5594})
5595
5596;; XXX
5597(define_insn "umulsi3_highpart_v8plus"
5598  [(set (match_operand:SI 0 "register_operand" "=h,r")
5599	(truncate:SI
5600	 (lshiftrt:DI (mult:DI (zero_extend:DI (match_operand:SI 1 "register_operand" "r,r"))
5601			       (zero_extend:DI (match_operand:SI 2 "register_operand" "r,r")))
5602		      (match_operand:SI 3 "const_int_operand" "i,i"))))
5603   (clobber (match_scratch:SI 4 "=X,h"))]
5604  "TARGET_V8PLUS"
5605  "@
5606   umul\t%1, %2, %0\n\tsrlx\t%0, %3, %0
5607   umul\t%1, %2, %4\n\tsrlx\t%4, %3, %0"
5608  [(set_attr "type" "multi")
5609   (set_attr "length" "2")])
5610
5611;; XXX
5612(define_insn "const_umulsi3_highpart_v8plus"
5613  [(set (match_operand:SI 0 "register_operand" "=h,r")
5614	(truncate:SI
5615	 (lshiftrt:DI (mult:DI (zero_extend:DI (match_operand:SI 1 "register_operand" "r,r"))
5616			       (match_operand:DI 2 "uns_small_int" ""))
5617		      (match_operand:SI 3 "const_int_operand" "i,i"))))
5618   (clobber (match_scratch:SI 4 "=X,h"))]
5619  "TARGET_V8PLUS"
5620  "@
5621   umul\t%1, %s2, %0\n\tsrlx\t%0, %3, %0
5622   umul\t%1, %s2, %4\n\tsrlx\t%4, %3, %0"
5623  [(set_attr "type" "multi")
5624   (set_attr "length" "2")])
5625
5626;; XXX
5627(define_insn "*umulsi3_highpart_sp32"
5628  [(set (match_operand:SI 0 "register_operand" "=r")
5629	(truncate:SI
5630	 (lshiftrt:DI (mult:DI (zero_extend:DI (match_operand:SI 1 "register_operand" "r"))
5631			       (zero_extend:DI (match_operand:SI 2 "register_operand" "r")))
5632		      (const_int 32))))]
5633  "TARGET_HARD_MUL32"
5634  "umul\t%1, %2, %%g0\n\trd\t%%y, %0"
5635  [(set_attr "type" "multi")
5636   (set_attr "length" "2")])
5637
5638;; XXX
5639(define_insn "const_umulsi3_highpart"
5640  [(set (match_operand:SI 0 "register_operand" "=r")
5641	(truncate:SI
5642	 (lshiftrt:DI (mult:DI (zero_extend:DI (match_operand:SI 1 "register_operand" "r"))
5643			       (match_operand:DI 2 "uns_small_int" ""))
5644		      (const_int 32))))]
5645  "TARGET_HARD_MUL32"
5646  "umul\t%1, %s2, %%g0\n\trd\t%%y, %0"
5647  [(set_attr "type" "multi")
5648   (set_attr "length" "2")])
5649
5650;; The v8 architecture specifies that there must be 3 instructions between
5651;; a y register write and a use of it for correct results.
5652
5653(define_expand "divsi3"
5654  [(parallel [(set (match_operand:SI 0 "register_operand" "=r,r")
5655		   (div:SI (match_operand:SI 1 "register_operand" "r,r")
5656			   (match_operand:SI 2 "input_operand" "rI,m")))
5657	      (clobber (match_scratch:SI 3 "=&r,&r"))])]
5658  "TARGET_V8 || TARGET_DEPRECATED_V8_INSNS"
5659{
5660  if (TARGET_ARCH64)
5661    {
5662      operands[3] = gen_reg_rtx(SImode);
5663      emit_insn (gen_ashrsi3 (operands[3], operands[1], GEN_INT (31)));
5664      emit_insn (gen_divsi3_sp64 (operands[0], operands[1], operands[2],
5665				  operands[3]));
5666      DONE;
5667    }
5668})
5669
5670(define_insn "divsi3_sp32"
5671  [(set (match_operand:SI 0 "register_operand" "=r,r")
5672	(div:SI (match_operand:SI 1 "register_operand" "r,r")
5673		(match_operand:SI 2 "input_operand" "rI,m")))
5674   (clobber (match_scratch:SI 3 "=&r,&r"))]
5675  "(TARGET_V8 || TARGET_DEPRECATED_V8_INSNS)
5676   && TARGET_ARCH32"
5677{
5678  if (which_alternative == 0)
5679    if (TARGET_V9)
5680      return "sra\t%1, 31, %3\n\twr\t%3, 0, %%y\n\tsdiv\t%1, %2, %0";
5681    else
5682      return "sra\t%1, 31, %3\n\twr\t%3, 0, %%y\n\tnop\n\tnop\n\tnop\n\tsdiv\t%1, %2, %0";
5683  else
5684    if (TARGET_V9)
5685      return "sra\t%1, 31, %3\n\twr\t%3, 0, %%y\n\tld\t%2, %3\n\tsdiv\t%1, %3, %0";
5686    else
5687      return "sra\t%1, 31, %3\n\twr\t%3, 0, %%y\n\tld\t%2, %3\n\tnop\n\tnop\n\tsdiv\t%1, %3, %0";
5688}
5689  [(set_attr "type" "multi")
5690   (set (attr "length")
5691	(if_then_else (eq_attr "isa" "v9")
5692		      (const_int 4) (const_int 6)))])
5693
5694(define_insn "divsi3_sp64"
5695  [(set (match_operand:SI 0 "register_operand" "=r")
5696	(div:SI (match_operand:SI 1 "register_operand" "r")
5697		(match_operand:SI 2 "input_operand" "rI")))
5698   (use (match_operand:SI 3 "register_operand" "r"))]
5699  "TARGET_DEPRECATED_V8_INSNS && TARGET_ARCH64"
5700  "wr\t%%g0, %3, %%y\n\tsdiv\t%1, %2, %0"
5701  [(set_attr "type" "multi")
5702   (set_attr "length" "2")])
5703
5704(define_insn "divdi3"
5705  [(set (match_operand:DI 0 "register_operand" "=r")
5706	(div:DI (match_operand:DI 1 "register_operand" "r")
5707		(match_operand:DI 2 "arith_double_operand" "rHI")))]
5708  "TARGET_ARCH64"
5709  "sdivx\t%1, %2, %0"
5710  [(set_attr "type" "idiv")])
5711
5712(define_insn "*cmp_sdiv_cc_set"
5713  [(set (reg:CC 100)
5714	(compare:CC (div:SI (match_operand:SI 1 "register_operand" "r")
5715			    (match_operand:SI 2 "arith_operand" "rI"))
5716		    (const_int 0)))
5717   (set (match_operand:SI 0 "register_operand" "=r")
5718	(div:SI (match_dup 1) (match_dup 2)))
5719   (clobber (match_scratch:SI 3 "=&r"))]
5720  "TARGET_V8 || TARGET_DEPRECATED_V8_INSNS"
5721{
5722  if (TARGET_V9)
5723    return "sra\t%1, 31, %3\n\twr\t%3, 0, %%y\n\tsdivcc\t%1, %2, %0";
5724  else
5725    return "sra\t%1, 31, %3\n\twr\t%3, 0, %%y\n\tnop\n\tnop\n\tnop\n\tsdivcc\t%1, %2, %0";
5726}
5727  [(set_attr "type" "multi")
5728   (set (attr "length")
5729	(if_then_else (eq_attr "isa" "v9")
5730		      (const_int 3) (const_int 6)))])
5731
5732;; XXX
5733(define_expand "udivsi3"
5734  [(set (match_operand:SI 0 "register_operand" "")
5735	(udiv:SI (match_operand:SI 1 "reg_or_nonsymb_mem_operand" "")
5736		 (match_operand:SI 2 "input_operand" "")))]
5737  "TARGET_V8 || TARGET_DEPRECATED_V8_INSNS"
5738  "")
5739
5740(define_insn "udivsi3_sp32"
5741  [(set (match_operand:SI 0 "register_operand" "=r,&r,&r")
5742	(udiv:SI (match_operand:SI 1 "reg_or_nonsymb_mem_operand" "r,r,m")
5743		 (match_operand:SI 2 "input_operand" "rI,m,r")))]
5744  "(TARGET_V8
5745    || TARGET_DEPRECATED_V8_INSNS)
5746   && TARGET_ARCH32"
5747{
5748  output_asm_insn ("wr\t%%g0, %%g0, %%y", operands);
5749  switch (which_alternative)
5750    {
5751    default:
5752      return "nop\n\tnop\n\tnop\n\tudiv\t%1, %2, %0";
5753    case 1:
5754      return "ld\t%2, %0\n\tnop\n\tnop\n\tudiv\t%1, %0, %0";
5755    case 2:
5756      return "ld\t%1, %0\n\tnop\n\tnop\n\tudiv\t%0, %2, %0";
5757    }
5758}
5759  [(set_attr "type" "multi")
5760   (set_attr "length" "5")])
5761
5762(define_insn "udivsi3_sp64"
5763  [(set (match_operand:SI 0 "register_operand" "=r")
5764	(udiv:SI (match_operand:SI 1 "reg_or_nonsymb_mem_operand" "r")
5765		 (match_operand:SI 2 "input_operand" "rI")))]
5766  "TARGET_DEPRECATED_V8_INSNS && TARGET_ARCH64"
5767  "wr\t%%g0, 0, %%y\n\tudiv\t%1, %2, %0"
5768  [(set_attr "type" "multi")
5769   (set_attr "length" "2")])
5770
5771(define_insn "udivdi3"
5772  [(set (match_operand:DI 0 "register_operand" "=r")
5773	(udiv:DI (match_operand:DI 1 "register_operand" "r")
5774		 (match_operand:DI 2 "arith_double_operand" "rHI")))]
5775  "TARGET_ARCH64"
5776  "udivx\t%1, %2, %0"
5777  [(set_attr "type" "idiv")])
5778
5779(define_insn "*cmp_udiv_cc_set"
5780  [(set (reg:CC 100)
5781	(compare:CC (udiv:SI (match_operand:SI 1 "register_operand" "r")
5782			     (match_operand:SI 2 "arith_operand" "rI"))
5783		    (const_int 0)))
5784   (set (match_operand:SI 0 "register_operand" "=r")
5785	(udiv:SI (match_dup 1) (match_dup 2)))]
5786  "TARGET_V8
5787   || TARGET_DEPRECATED_V8_INSNS"
5788{
5789  if (TARGET_V9)
5790    return "wr\t%%g0, %%g0, %%y\n\tudivcc\t%1, %2, %0";
5791  else
5792    return "wr\t%%g0, %%g0, %%y\n\tnop\n\tnop\n\tnop\n\tudivcc\t%1, %2, %0";
5793}
5794  [(set_attr "type" "multi")
5795   (set (attr "length")
5796	(if_then_else (eq_attr "isa" "v9")
5797		      (const_int 2) (const_int 5)))])
5798
5799; sparclet multiply/accumulate insns
5800
5801(define_insn "*smacsi"
5802  [(set (match_operand:SI 0 "register_operand" "=r")
5803	(plus:SI (mult:SI (match_operand:SI 1 "register_operand" "%r")
5804			  (match_operand:SI 2 "arith_operand" "rI"))
5805		 (match_operand:SI 3 "register_operand" "0")))]
5806  "TARGET_SPARCLET"
5807  "smac\t%1, %2, %0"
5808  [(set_attr "type" "imul")])
5809
5810(define_insn "*smacdi"
5811  [(set (match_operand:DI 0 "register_operand" "=r")
5812	(plus:DI (mult:DI (sign_extend:DI
5813			   (match_operand:SI 1 "register_operand" "%r"))
5814			  (sign_extend:DI
5815			   (match_operand:SI 2 "register_operand" "r")))
5816		 (match_operand:DI 3 "register_operand" "0")))]
5817  "TARGET_SPARCLET"
5818  "smacd\t%1, %2, %L0"
5819  [(set_attr "type" "imul")])
5820
5821(define_insn "*umacdi"
5822  [(set (match_operand:DI 0 "register_operand" "=r")
5823	(plus:DI (mult:DI (zero_extend:DI
5824			   (match_operand:SI 1 "register_operand" "%r"))
5825			  (zero_extend:DI
5826			   (match_operand:SI 2 "register_operand" "r")))
5827		 (match_operand:DI 3 "register_operand" "0")))]
5828  "TARGET_SPARCLET"
5829  "umacd\t%1, %2, %L0"
5830  [(set_attr "type" "imul")])
5831
5832;;- Boolean instructions
5833;; We define DImode `and' so with DImode `not' we can get
5834;; DImode `andn'.  Other combinations are possible.
5835
5836(define_expand "anddi3"
5837  [(set (match_operand:DI 0 "register_operand" "")
5838	(and:DI (match_operand:DI 1 "arith_double_operand" "")
5839		(match_operand:DI 2 "arith_double_operand" "")))]
5840  ""
5841  "")
5842
5843(define_insn "*anddi3_sp32"
5844  [(set (match_operand:DI 0 "register_operand" "=r,b")
5845	(and:DI (match_operand:DI 1 "arith_double_operand" "%r,b")
5846		(match_operand:DI 2 "arith_double_operand" "rHI,b")))]
5847  "! TARGET_ARCH64"
5848  "@
5849  #
5850  fand\t%1, %2, %0"
5851  [(set_attr "type" "*,fp")
5852   (set_attr "length" "2,*")
5853   (set_attr "fptype" "double")])
5854
5855(define_insn "*anddi3_sp64"
5856  [(set (match_operand:DI 0 "register_operand" "=r,b")
5857	(and:DI (match_operand:DI 1 "arith_double_operand" "%r,b")
5858		(match_operand:DI 2 "arith_double_operand" "rHI,b")))]
5859  "TARGET_ARCH64"
5860  "@
5861   and\t%1, %2, %0
5862   fand\t%1, %2, %0"
5863  [(set_attr "type" "*,fp")
5864   (set_attr "fptype" "double")])
5865
5866(define_insn "andsi3"
5867  [(set (match_operand:SI 0 "register_operand" "=r,d")
5868	(and:SI (match_operand:SI 1 "arith_operand" "%r,d")
5869		(match_operand:SI 2 "arith_operand" "rI,d")))]
5870  ""
5871  "@
5872   and\t%1, %2, %0
5873   fands\t%1, %2, %0"
5874  [(set_attr "type" "*,fp")])
5875
5876(define_split
5877  [(set (match_operand:SI 0 "register_operand" "")
5878	(and:SI (match_operand:SI 1 "register_operand" "")
5879		(match_operand:SI 2 "" "")))
5880   (clobber (match_operand:SI 3 "register_operand" ""))]
5881  "GET_CODE (operands[2]) == CONST_INT
5882   && !SMALL_INT32 (operands[2])
5883   && (INTVAL (operands[2]) & 0x3ff) == 0x3ff"
5884  [(set (match_dup 3) (match_dup 4))
5885   (set (match_dup 0) (and:SI (not:SI (match_dup 3)) (match_dup 1)))]
5886{
5887  operands[4] = GEN_INT (~INTVAL (operands[2]));
5888})
5889
5890;; Split DImode logical operations requiring two instructions.
5891(define_split
5892  [(set (match_operand:DI 0 "register_operand" "")
5893	(match_operator:DI 1 "cc_arithop"	; AND, IOR, XOR
5894			   [(match_operand:DI 2 "register_operand" "")
5895			    (match_operand:DI 3 "arith_double_operand" "")]))]
5896  "! TARGET_ARCH64
5897   && reload_completed
5898   && ((GET_CODE (operands[0]) == REG
5899        && REGNO (operands[0]) < 32)
5900       || (GET_CODE (operands[0]) == SUBREG
5901           && GET_CODE (SUBREG_REG (operands[0])) == REG
5902           && REGNO (SUBREG_REG (operands[0])) < 32))"
5903  [(set (match_dup 4) (match_op_dup:SI 1 [(match_dup 6) (match_dup 8)]))
5904   (set (match_dup 5) (match_op_dup:SI 1 [(match_dup 7) (match_dup 9)]))]
5905{
5906  operands[4] = gen_highpart (SImode, operands[0]);
5907  operands[5] = gen_lowpart (SImode, operands[0]);
5908  operands[6] = gen_highpart (SImode, operands[2]);
5909  operands[7] = gen_lowpart (SImode, operands[2]);
5910#if HOST_BITS_PER_WIDE_INT == 32
5911  if (GET_CODE (operands[3]) == CONST_INT)
5912    {
5913      if (INTVAL (operands[3]) < 0)
5914	operands[8] = constm1_rtx;
5915      else
5916	operands[8] = const0_rtx;
5917    }
5918  else
5919#endif
5920    operands[8] = gen_highpart_mode (SImode, DImode, operands[3]);
5921  operands[9] = gen_lowpart (SImode, operands[3]);
5922})
5923
5924(define_insn_and_split "*and_not_di_sp32"
5925  [(set (match_operand:DI 0 "register_operand" "=r,b")
5926	(and:DI (not:DI (match_operand:DI 1 "register_operand" "r,b"))
5927		(match_operand:DI 2 "register_operand" "r,b")))]
5928  "! TARGET_ARCH64"
5929  "@
5930   #
5931   fandnot1\t%1, %2, %0"
5932  "&& reload_completed
5933   && ((GET_CODE (operands[0]) == REG
5934        && REGNO (operands[0]) < 32)
5935       || (GET_CODE (operands[0]) == SUBREG
5936           && GET_CODE (SUBREG_REG (operands[0])) == REG
5937           && REGNO (SUBREG_REG (operands[0])) < 32))"
5938  [(set (match_dup 3) (and:SI (not:SI (match_dup 4)) (match_dup 5)))
5939   (set (match_dup 6) (and:SI (not:SI (match_dup 7)) (match_dup 8)))]
5940  "operands[3] = gen_highpart (SImode, operands[0]);
5941   operands[4] = gen_highpart (SImode, operands[1]);
5942   operands[5] = gen_highpart (SImode, operands[2]);
5943   operands[6] = gen_lowpart (SImode, operands[0]);
5944   operands[7] = gen_lowpart (SImode, operands[1]);
5945   operands[8] = gen_lowpart (SImode, operands[2]);"
5946  [(set_attr "type" "*,fp")
5947   (set_attr "length" "2,*")
5948   (set_attr "fptype" "double")])
5949
5950(define_insn "*and_not_di_sp64"
5951  [(set (match_operand:DI 0 "register_operand" "=r,b")
5952	(and:DI (not:DI (match_operand:DI 1 "register_operand" "r,b"))
5953		(match_operand:DI 2 "register_operand" "r,b")))]
5954  "TARGET_ARCH64"
5955  "@
5956   andn\t%2, %1, %0
5957   fandnot1\t%1, %2, %0"
5958  [(set_attr "type" "*,fp")
5959   (set_attr "fptype" "double")])
5960
5961(define_insn "*and_not_si"
5962  [(set (match_operand:SI 0 "register_operand" "=r,d")
5963	(and:SI (not:SI (match_operand:SI 1 "register_operand" "r,d"))
5964		(match_operand:SI 2 "register_operand" "r,d")))]
5965  ""
5966  "@
5967   andn\t%2, %1, %0
5968   fandnot1s\t%1, %2, %0"
5969  [(set_attr "type" "*,fp")])
5970
5971(define_expand "iordi3"
5972  [(set (match_operand:DI 0 "register_operand" "")
5973	(ior:DI (match_operand:DI 1 "arith_double_operand" "")
5974		(match_operand:DI 2 "arith_double_operand" "")))]
5975  ""
5976  "")
5977
5978(define_insn "*iordi3_sp32"
5979  [(set (match_operand:DI 0 "register_operand" "=r,b")
5980	(ior:DI (match_operand:DI 1 "arith_double_operand" "%r,b")
5981		(match_operand:DI 2 "arith_double_operand" "rHI,b")))]
5982  "! TARGET_ARCH64"
5983  "@
5984  #
5985  for\t%1, %2, %0"
5986  [(set_attr "type" "*,fp")
5987   (set_attr "length" "2,*")
5988   (set_attr "fptype" "double")])
5989
5990(define_insn "*iordi3_sp64"
5991  [(set (match_operand:DI 0 "register_operand" "=r,b")
5992	(ior:DI (match_operand:DI 1 "arith_double_operand" "%r,b")
5993		(match_operand:DI 2 "arith_double_operand" "rHI,b")))]
5994  "TARGET_ARCH64"
5995  "@
5996  or\t%1, %2, %0
5997  for\t%1, %2, %0"
5998  [(set_attr "type" "*,fp")
5999   (set_attr "fptype" "double")])
6000
6001(define_insn "iorsi3"
6002  [(set (match_operand:SI 0 "register_operand" "=r,d")
6003	(ior:SI (match_operand:SI 1 "arith_operand" "%r,d")
6004		(match_operand:SI 2 "arith_operand" "rI,d")))]
6005  ""
6006  "@
6007   or\t%1, %2, %0
6008   fors\t%1, %2, %0"
6009  [(set_attr "type" "*,fp")])
6010
6011(define_split
6012  [(set (match_operand:SI 0 "register_operand" "")
6013	(ior:SI (match_operand:SI 1 "register_operand" "")
6014		(match_operand:SI 2 "" "")))
6015   (clobber (match_operand:SI 3 "register_operand" ""))]
6016  "GET_CODE (operands[2]) == CONST_INT
6017   && !SMALL_INT32 (operands[2])
6018   && (INTVAL (operands[2]) & 0x3ff) == 0x3ff"
6019  [(set (match_dup 3) (match_dup 4))
6020   (set (match_dup 0) (ior:SI (not:SI (match_dup 3)) (match_dup 1)))]
6021{
6022  operands[4] = GEN_INT (~INTVAL (operands[2]));
6023})
6024
6025(define_insn_and_split "*or_not_di_sp32"
6026  [(set (match_operand:DI 0 "register_operand" "=r,b")
6027	(ior:DI (not:DI (match_operand:DI 1 "register_operand" "r,b"))
6028		(match_operand:DI 2 "register_operand" "r,b")))]
6029  "! TARGET_ARCH64"
6030  "@
6031   #
6032   fornot1\t%1, %2, %0"
6033  "&& reload_completed
6034   && ((GET_CODE (operands[0]) == REG
6035        && REGNO (operands[0]) < 32)
6036       || (GET_CODE (operands[0]) == SUBREG
6037           && GET_CODE (SUBREG_REG (operands[0])) == REG
6038           && REGNO (SUBREG_REG (operands[0])) < 32))"
6039  [(set (match_dup 3) (ior:SI (not:SI (match_dup 4)) (match_dup 5)))
6040   (set (match_dup 6) (ior:SI (not:SI (match_dup 7)) (match_dup 8)))]
6041  "operands[3] = gen_highpart (SImode, operands[0]);
6042   operands[4] = gen_highpart (SImode, operands[1]);
6043   operands[5] = gen_highpart (SImode, operands[2]);
6044   operands[6] = gen_lowpart (SImode, operands[0]);
6045   operands[7] = gen_lowpart (SImode, operands[1]);
6046   operands[8] = gen_lowpart (SImode, operands[2]);"
6047  [(set_attr "type" "*,fp")
6048   (set_attr "length" "2,*")
6049   (set_attr "fptype" "double")])
6050
6051(define_insn "*or_not_di_sp64"
6052  [(set (match_operand:DI 0 "register_operand" "=r,b")
6053	(ior:DI (not:DI (match_operand:DI 1 "register_operand" "r,b"))
6054		(match_operand:DI 2 "register_operand" "r,b")))]
6055  "TARGET_ARCH64"
6056  "@
6057  orn\t%2, %1, %0
6058  fornot1\t%1, %2, %0"
6059  [(set_attr "type" "*,fp")
6060   (set_attr "fptype" "double")])
6061
6062(define_insn "*or_not_si"
6063  [(set (match_operand:SI 0 "register_operand" "=r,d")
6064	(ior:SI (not:SI (match_operand:SI 1 "register_operand" "r,d"))
6065		(match_operand:SI 2 "register_operand" "r,d")))]
6066  ""
6067  "@
6068   orn\t%2, %1, %0
6069   fornot1s\t%1, %2, %0"
6070  [(set_attr "type" "*,fp")])
6071
6072(define_expand "xordi3"
6073  [(set (match_operand:DI 0 "register_operand" "")
6074	(xor:DI (match_operand:DI 1 "arith_double_operand" "")
6075		(match_operand:DI 2 "arith_double_operand" "")))]
6076  ""
6077  "")
6078
6079(define_insn "*xordi3_sp32"
6080  [(set (match_operand:DI 0 "register_operand" "=r,b")
6081	(xor:DI (match_operand:DI 1 "arith_double_operand" "%r,b")
6082		(match_operand:DI 2 "arith_double_operand" "rHI,b")))]
6083  "! TARGET_ARCH64"
6084  "@
6085  #
6086  fxor\t%1, %2, %0"
6087  [(set_attr "type" "*,fp")
6088   (set_attr "length" "2,*")
6089   (set_attr "fptype" "double")])
6090
6091(define_insn "*xordi3_sp64"
6092  [(set (match_operand:DI 0 "register_operand" "=r,b")
6093	(xor:DI (match_operand:DI 1 "arith_double_operand" "%rJ,b")
6094		(match_operand:DI 2 "arith_double_operand" "rHI,b")))]
6095  "TARGET_ARCH64"
6096  "@
6097  xor\t%r1, %2, %0
6098  fxor\t%1, %2, %0"
6099  [(set_attr "type" "*,fp")
6100   (set_attr "fptype" "double")])
6101
6102(define_insn "*xordi3_sp64_dbl"
6103  [(set (match_operand:DI 0 "register_operand" "=r")
6104	(xor:DI (match_operand:DI 1 "register_operand" "r")
6105		(match_operand:DI 2 "const64_operand" "")))]
6106  "(TARGET_ARCH64
6107    && HOST_BITS_PER_WIDE_INT != 64)"
6108  "xor\t%1, %2, %0")
6109
6110(define_insn "xorsi3"
6111  [(set (match_operand:SI 0 "register_operand" "=r,d")
6112	(xor:SI (match_operand:SI 1 "arith_operand" "%rJ,d")
6113		(match_operand:SI 2 "arith_operand" "rI,d")))]
6114  ""
6115  "@
6116   xor\t%r1, %2, %0
6117   fxors\t%1, %2, %0"
6118  [(set_attr "type" "*,fp")])
6119
6120(define_split
6121  [(set (match_operand:SI 0 "register_operand" "")
6122	(xor:SI (match_operand:SI 1 "register_operand" "")
6123		(match_operand:SI 2 "" "")))
6124   (clobber (match_operand:SI 3 "register_operand" ""))]
6125  "GET_CODE (operands[2]) == CONST_INT
6126   && !SMALL_INT32 (operands[2])
6127   && (INTVAL (operands[2]) & 0x3ff) == 0x3ff"
6128  [(set (match_dup 3) (match_dup 4))
6129   (set (match_dup 0) (not:SI (xor:SI (match_dup 3) (match_dup 1))))]
6130{
6131  operands[4] = GEN_INT (~INTVAL (operands[2]));
6132})
6133
6134(define_split
6135  [(set (match_operand:SI 0 "register_operand" "")
6136	(not:SI (xor:SI (match_operand:SI 1 "register_operand" "")
6137			(match_operand:SI 2 "" ""))))
6138   (clobber (match_operand:SI 3 "register_operand" ""))]
6139  "GET_CODE (operands[2]) == CONST_INT
6140   && !SMALL_INT32 (operands[2])
6141   && (INTVAL (operands[2]) & 0x3ff) == 0x3ff"
6142  [(set (match_dup 3) (match_dup 4))
6143   (set (match_dup 0) (xor:SI (match_dup 3) (match_dup 1)))]
6144{
6145  operands[4] = GEN_INT (~INTVAL (operands[2]));
6146})
6147
6148;; xnor patterns.  Note that (a ^ ~b) == (~a ^ b) == ~(a ^ b).
6149;; Combine now canonicalizes to the rightmost expression.
6150(define_insn_and_split "*xor_not_di_sp32"
6151  [(set (match_operand:DI 0 "register_operand" "=r,b")
6152	(not:DI (xor:DI (match_operand:DI 1 "register_operand" "r,b")
6153			(match_operand:DI 2 "register_operand" "r,b"))))]
6154  "! TARGET_ARCH64"
6155  "@
6156   #
6157   fxnor\t%1, %2, %0"
6158  "&& reload_completed
6159   && ((GET_CODE (operands[0]) == REG
6160        && REGNO (operands[0]) < 32)
6161       || (GET_CODE (operands[0]) == SUBREG
6162           && GET_CODE (SUBREG_REG (operands[0])) == REG
6163           && REGNO (SUBREG_REG (operands[0])) < 32))"
6164  [(set (match_dup 3) (not:SI (xor:SI (match_dup 4) (match_dup 5))))
6165   (set (match_dup 6) (not:SI (xor:SI (match_dup 7) (match_dup 8))))]
6166  "operands[3] = gen_highpart (SImode, operands[0]);
6167   operands[4] = gen_highpart (SImode, operands[1]);
6168   operands[5] = gen_highpart (SImode, operands[2]);
6169   operands[6] = gen_lowpart (SImode, operands[0]);
6170   operands[7] = gen_lowpart (SImode, operands[1]);
6171   operands[8] = gen_lowpart (SImode, operands[2]);"
6172  [(set_attr "type" "*,fp")
6173   (set_attr "length" "2,*")
6174   (set_attr "fptype" "double")])
6175
6176(define_insn "*xor_not_di_sp64"
6177  [(set (match_operand:DI 0 "register_operand" "=r,b")
6178	(not:DI (xor:DI (match_operand:DI 1 "reg_or_0_operand" "rJ,b")
6179			(match_operand:DI 2 "arith_double_operand" "rHI,b"))))]
6180  "TARGET_ARCH64"
6181  "@
6182  xnor\t%r1, %2, %0
6183  fxnor\t%1, %2, %0"
6184  [(set_attr "type" "*,fp")
6185   (set_attr "fptype" "double")])
6186
6187(define_insn "*xor_not_si"
6188  [(set (match_operand:SI 0 "register_operand" "=r,d")
6189	(not:SI (xor:SI (match_operand:SI 1 "reg_or_0_operand" "rJ,d")
6190			(match_operand:SI 2 "arith_operand" "rI,d"))))]
6191  ""
6192  "@
6193   xnor\t%r1, %2, %0
6194   fxnors\t%1, %2, %0"
6195  [(set_attr "type" "*,fp")])
6196
6197;; These correspond to the above in the case where we also (or only)
6198;; want to set the condition code.
6199
6200(define_insn "*cmp_cc_arith_op"
6201  [(set (reg:CC 100)
6202	(compare:CC
6203	 (match_operator:SI 2 "cc_arithop"
6204			    [(match_operand:SI 0 "arith_operand" "%r")
6205			     (match_operand:SI 1 "arith_operand" "rI")])
6206	 (const_int 0)))]
6207  ""
6208  "%A2cc\t%0, %1, %%g0"
6209  [(set_attr "type" "compare")])
6210
6211(define_insn "*cmp_ccx_arith_op"
6212  [(set (reg:CCX 100)
6213	(compare:CCX
6214	 (match_operator:DI 2 "cc_arithop"
6215			    [(match_operand:DI 0 "arith_double_operand" "%r")
6216			     (match_operand:DI 1 "arith_double_operand" "rHI")])
6217	 (const_int 0)))]
6218  "TARGET_ARCH64"
6219  "%A2cc\t%0, %1, %%g0"
6220  [(set_attr "type" "compare")])
6221
6222(define_insn "*cmp_cc_arith_op_set"
6223  [(set (reg:CC 100)
6224	(compare:CC
6225	 (match_operator:SI 3 "cc_arithop"
6226			    [(match_operand:SI 1 "arith_operand" "%r")
6227			     (match_operand:SI 2 "arith_operand" "rI")])
6228	 (const_int 0)))
6229   (set (match_operand:SI 0 "register_operand" "=r")
6230	(match_operator:SI 4 "cc_arithop" [(match_dup 1) (match_dup 2)]))]
6231  "GET_CODE (operands[3]) == GET_CODE (operands[4])"
6232  "%A3cc\t%1, %2, %0"
6233  [(set_attr "type" "compare")])
6234
6235(define_insn "*cmp_ccx_arith_op_set"
6236  [(set (reg:CCX 100)
6237	(compare:CCX
6238	 (match_operator:DI 3 "cc_arithop"
6239			    [(match_operand:DI 1 "arith_double_operand" "%r")
6240			     (match_operand:DI 2 "arith_double_operand" "rHI")])
6241	 (const_int 0)))
6242   (set (match_operand:DI 0 "register_operand" "=r")
6243	(match_operator:DI 4 "cc_arithop" [(match_dup 1) (match_dup 2)]))]
6244  "TARGET_ARCH64 && GET_CODE (operands[3]) == GET_CODE (operands[4])"
6245  "%A3cc\t%1, %2, %0"
6246  [(set_attr "type" "compare")])
6247
6248(define_insn "*cmp_cc_xor_not"
6249  [(set (reg:CC 100)
6250	(compare:CC
6251	 (not:SI (xor:SI (match_operand:SI 0 "reg_or_0_operand" "%rJ")
6252			 (match_operand:SI 1 "arith_operand" "rI")))
6253	 (const_int 0)))]
6254  ""
6255  "xnorcc\t%r0, %1, %%g0"
6256  [(set_attr "type" "compare")])
6257
6258(define_insn "*cmp_ccx_xor_not"
6259  [(set (reg:CCX 100)
6260	(compare:CCX
6261	 (not:DI (xor:DI (match_operand:DI 0 "reg_or_0_operand" "%rJ")
6262			 (match_operand:DI 1 "arith_double_operand" "rHI")))
6263	 (const_int 0)))]
6264  "TARGET_ARCH64"
6265  "xnorcc\t%r0, %1, %%g0"
6266  [(set_attr "type" "compare")])
6267
6268(define_insn "*cmp_cc_xor_not_set"
6269  [(set (reg:CC 100)
6270	(compare:CC
6271	 (not:SI (xor:SI (match_operand:SI 1 "reg_or_0_operand" "%rJ")
6272			 (match_operand:SI 2 "arith_operand" "rI")))
6273	 (const_int 0)))
6274   (set (match_operand:SI 0 "register_operand" "=r")
6275	(not:SI (xor:SI (match_dup 1) (match_dup 2))))]
6276  ""
6277  "xnorcc\t%r1, %2, %0"
6278  [(set_attr "type" "compare")])
6279
6280(define_insn "*cmp_ccx_xor_not_set"
6281  [(set (reg:CCX 100)
6282	(compare:CCX
6283	 (not:DI (xor:DI (match_operand:DI 1 "reg_or_0_operand" "%rJ")
6284			 (match_operand:DI 2 "arith_double_operand" "rHI")))
6285	 (const_int 0)))
6286   (set (match_operand:DI 0 "register_operand" "=r")
6287	(not:DI (xor:DI (match_dup 1) (match_dup 2))))]
6288  "TARGET_ARCH64"
6289  "xnorcc\t%r1, %2, %0"
6290  [(set_attr "type" "compare")])
6291
6292(define_insn "*cmp_cc_arith_op_not"
6293  [(set (reg:CC 100)
6294	(compare:CC
6295	 (match_operator:SI 2 "cc_arithopn"
6296			    [(not:SI (match_operand:SI 0 "arith_operand" "rI"))
6297			     (match_operand:SI 1 "reg_or_0_operand" "rJ")])
6298	 (const_int 0)))]
6299  ""
6300  "%B2cc\t%r1, %0, %%g0"
6301  [(set_attr "type" "compare")])
6302
6303(define_insn "*cmp_ccx_arith_op_not"
6304  [(set (reg:CCX 100)
6305	(compare:CCX
6306	 (match_operator:DI 2 "cc_arithopn"
6307			    [(not:DI (match_operand:DI 0 "arith_double_operand" "rHI"))
6308			     (match_operand:DI 1 "reg_or_0_operand" "rJ")])
6309	 (const_int 0)))]
6310  "TARGET_ARCH64"
6311  "%B2cc\t%r1, %0, %%g0"
6312  [(set_attr "type" "compare")])
6313
6314(define_insn "*cmp_cc_arith_op_not_set"
6315  [(set (reg:CC 100)
6316	(compare:CC
6317	 (match_operator:SI 3 "cc_arithopn"
6318			    [(not:SI (match_operand:SI 1 "arith_operand" "rI"))
6319			     (match_operand:SI 2 "reg_or_0_operand" "rJ")])
6320	 (const_int 0)))
6321   (set (match_operand:SI 0 "register_operand" "=r")
6322	(match_operator:SI 4 "cc_arithopn"
6323			    [(not:SI (match_dup 1)) (match_dup 2)]))]
6324  "GET_CODE (operands[3]) == GET_CODE (operands[4])"
6325  "%B3cc\t%r2, %1, %0"
6326  [(set_attr "type" "compare")])
6327
6328(define_insn "*cmp_ccx_arith_op_not_set"
6329  [(set (reg:CCX 100)
6330	(compare:CCX
6331	 (match_operator:DI 3 "cc_arithopn"
6332			    [(not:DI (match_operand:DI 1 "arith_double_operand" "rHI"))
6333			     (match_operand:DI 2 "reg_or_0_operand" "rJ")])
6334	 (const_int 0)))
6335   (set (match_operand:DI 0 "register_operand" "=r")
6336	(match_operator:DI 4 "cc_arithopn"
6337			    [(not:DI (match_dup 1)) (match_dup 2)]))]
6338  "TARGET_ARCH64 && GET_CODE (operands[3]) == GET_CODE (operands[4])"
6339  "%B3cc\t%r2, %1, %0"
6340  [(set_attr "type" "compare")])
6341
6342;; We cannot use the "neg" pseudo insn because the Sun assembler
6343;; does not know how to make it work for constants.
6344
6345(define_expand "negdi2"
6346  [(set (match_operand:DI 0 "register_operand" "=r")
6347	(neg:DI (match_operand:DI 1 "register_operand" "r")))]
6348  ""
6349{
6350  if (! TARGET_ARCH64)
6351    {
6352      emit_insn (gen_rtx_PARALLEL
6353		 (VOIDmode,
6354		  gen_rtvec (2,
6355			     gen_rtx_SET (VOIDmode, operand0,
6356					  gen_rtx_NEG (DImode, operand1)),
6357			     gen_rtx_CLOBBER (VOIDmode,
6358					      gen_rtx_REG (CCmode,
6359							   SPARC_ICC_REG)))));
6360      DONE;
6361    }
6362})
6363
6364(define_insn_and_split "*negdi2_sp32"
6365  [(set (match_operand:DI 0 "register_operand" "=r")
6366	(neg:DI (match_operand:DI 1 "register_operand" "r")))
6367   (clobber (reg:CC 100))]
6368  "TARGET_ARCH32"
6369  "#"
6370  "&& reload_completed"
6371  [(parallel [(set (reg:CC_NOOV 100)
6372                   (compare:CC_NOOV (minus:SI (const_int 0) (match_dup 5))
6373                                    (const_int 0)))
6374              (set (match_dup 4) (minus:SI (const_int 0) (match_dup 5)))])
6375   (set (match_dup 2) (minus:SI (minus:SI (const_int 0) (match_dup 3))
6376                                (ltu:SI (reg:CC 100) (const_int 0))))]
6377  "operands[2] = gen_highpart (SImode, operands[0]);
6378   operands[3] = gen_highpart (SImode, operands[1]);
6379   operands[4] = gen_lowpart (SImode, operands[0]);
6380   operands[5] = gen_lowpart (SImode, operands[1]);"
6381  [(set_attr "length" "2")])
6382
6383(define_insn "*negdi2_sp64"
6384  [(set (match_operand:DI 0 "register_operand" "=r")
6385	(neg:DI (match_operand:DI 1 "register_operand" "r")))]
6386  "TARGET_ARCH64"
6387  "sub\t%%g0, %1, %0")
6388
6389(define_insn "negsi2"
6390  [(set (match_operand:SI 0 "register_operand" "=r")
6391        (neg:SI (match_operand:SI 1 "arith_operand" "rI")))]
6392  ""
6393  "sub\t%%g0, %1, %0")
6394
6395(define_insn "*cmp_cc_neg"
6396  [(set (reg:CC_NOOV 100)
6397	(compare:CC_NOOV (neg:SI (match_operand:SI 0 "arith_operand" "rI"))
6398			 (const_int 0)))]
6399  ""
6400  "subcc\t%%g0, %0, %%g0"
6401  [(set_attr "type" "compare")])
6402
6403(define_insn "*cmp_ccx_neg"
6404  [(set (reg:CCX_NOOV 100)
6405	(compare:CCX_NOOV (neg:DI (match_operand:DI 0 "arith_double_operand" "rHI"))
6406			  (const_int 0)))]
6407  "TARGET_ARCH64"
6408  "subcc\t%%g0, %0, %%g0"
6409  [(set_attr "type" "compare")])
6410
6411(define_insn "*cmp_cc_set_neg"
6412  [(set (reg:CC_NOOV 100)
6413	(compare:CC_NOOV (neg:SI (match_operand:SI 1 "arith_operand" "rI"))
6414			 (const_int 0)))
6415   (set (match_operand:SI 0 "register_operand" "=r")
6416	(neg:SI (match_dup 1)))]
6417  ""
6418  "subcc\t%%g0, %1, %0"
6419  [(set_attr "type" "compare")])
6420
6421(define_insn "*cmp_ccx_set_neg"
6422  [(set (reg:CCX_NOOV 100)
6423	(compare:CCX_NOOV (neg:DI (match_operand:DI 1 "arith_double_operand" "rHI"))
6424			  (const_int 0)))
6425   (set (match_operand:DI 0 "register_operand" "=r")
6426	(neg:DI (match_dup 1)))]
6427  "TARGET_ARCH64"
6428  "subcc\t%%g0, %1, %0"
6429  [(set_attr "type" "compare")])
6430
6431;; We cannot use the "not" pseudo insn because the Sun assembler
6432;; does not know how to make it work for constants.
6433(define_expand "one_cmpldi2"
6434  [(set (match_operand:DI 0 "register_operand" "")
6435	(not:DI (match_operand:DI 1 "register_operand" "")))]
6436  ""
6437  "")
6438
6439(define_insn_and_split "*one_cmpldi2_sp32"
6440  [(set (match_operand:DI 0 "register_operand" "=r,b")
6441	(not:DI (match_operand:DI 1 "register_operand" "r,b")))]
6442  "! TARGET_ARCH64"
6443  "@
6444   #
6445   fnot1\t%1, %0"
6446  "&& reload_completed
6447   && ((GET_CODE (operands[0]) == REG
6448        && REGNO (operands[0]) < 32)
6449       || (GET_CODE (operands[0]) == SUBREG
6450           && GET_CODE (SUBREG_REG (operands[0])) == REG
6451           && REGNO (SUBREG_REG (operands[0])) < 32))"
6452  [(set (match_dup 2) (not:SI (xor:SI (match_dup 3) (const_int 0))))
6453   (set (match_dup 4) (not:SI (xor:SI (match_dup 5) (const_int 0))))]
6454  "operands[2] = gen_highpart (SImode, operands[0]);
6455   operands[3] = gen_highpart (SImode, operands[1]);
6456   operands[4] = gen_lowpart (SImode, operands[0]);
6457   operands[5] = gen_lowpart (SImode, operands[1]);"
6458  [(set_attr "type" "*,fp")
6459   (set_attr "length" "2,*")
6460   (set_attr "fptype" "double")])
6461
6462(define_insn "*one_cmpldi2_sp64"
6463  [(set (match_operand:DI 0 "register_operand" "=r,b")
6464	(not:DI (match_operand:DI 1 "arith_double_operand" "rHI,b")))]
6465  "TARGET_ARCH64"
6466  "@
6467   xnor\t%%g0, %1, %0
6468   fnot1\t%1, %0"
6469  [(set_attr "type" "*,fp")
6470   (set_attr "fptype" "double")])
6471
6472(define_insn "one_cmplsi2"
6473  [(set (match_operand:SI 0 "register_operand" "=r,d")
6474	(not:SI (match_operand:SI 1 "arith_operand" "rI,d")))]
6475  ""
6476  "@
6477  xnor\t%%g0, %1, %0
6478  fnot1s\t%1, %0"
6479  [(set_attr "type" "*,fp")])
6480
6481(define_insn "*cmp_cc_not"
6482  [(set (reg:CC 100)
6483	(compare:CC (not:SI (match_operand:SI 0 "arith_operand" "rI"))
6484		    (const_int 0)))]
6485  ""
6486  "xnorcc\t%%g0, %0, %%g0"
6487  [(set_attr "type" "compare")])
6488
6489(define_insn "*cmp_ccx_not"
6490  [(set (reg:CCX 100)
6491	(compare:CCX (not:DI (match_operand:DI 0 "arith_double_operand" "rHI"))
6492		     (const_int 0)))]
6493  "TARGET_ARCH64"
6494  "xnorcc\t%%g0, %0, %%g0"
6495  [(set_attr "type" "compare")])
6496
6497(define_insn "*cmp_cc_set_not"
6498  [(set (reg:CC 100)
6499	(compare:CC (not:SI (match_operand:SI 1 "arith_operand" "rI"))
6500		    (const_int 0)))
6501   (set (match_operand:SI 0 "register_operand" "=r")
6502	(not:SI (match_dup 1)))]
6503  ""
6504  "xnorcc\t%%g0, %1, %0"
6505  [(set_attr "type" "compare")])
6506
6507(define_insn "*cmp_ccx_set_not"
6508  [(set (reg:CCX 100)
6509	(compare:CCX (not:DI (match_operand:DI 1 "arith_double_operand" "rHI"))
6510		    (const_int 0)))
6511   (set (match_operand:DI 0 "register_operand" "=r")
6512	(not:DI (match_dup 1)))]
6513  "TARGET_ARCH64"
6514  "xnorcc\t%%g0, %1, %0"
6515  [(set_attr "type" "compare")])
6516
6517(define_insn "*cmp_cc_set"
6518  [(set (match_operand:SI 0 "register_operand" "=r")
6519	(match_operand:SI 1 "register_operand" "r"))
6520   (set (reg:CC 100)
6521	(compare:CC (match_dup 1)
6522		    (const_int 0)))]
6523  ""
6524  "orcc\t%1, 0, %0"
6525  [(set_attr "type" "compare")])
6526
6527(define_insn "*cmp_ccx_set64"
6528  [(set (match_operand:DI 0 "register_operand" "=r")
6529	(match_operand:DI 1 "register_operand" "r"))
6530   (set (reg:CCX 100)
6531	(compare:CCX (match_dup 1)
6532		     (const_int 0)))]
6533  "TARGET_ARCH64"
6534  "orcc\t%1, 0, %0"
6535   [(set_attr "type" "compare")])
6536
6537;; Floating point arithmetic instructions.
6538
6539(define_expand "addtf3"
6540  [(set (match_operand:TF 0 "nonimmediate_operand" "")
6541	(plus:TF (match_operand:TF 1 "general_operand" "")
6542		 (match_operand:TF 2 "general_operand" "")))]
6543  "TARGET_FPU && (TARGET_HARD_QUAD || TARGET_ARCH64)"
6544  "emit_tfmode_binop (PLUS, operands); DONE;")
6545
6546(define_insn "*addtf3_hq"
6547  [(set (match_operand:TF 0 "register_operand" "=e")
6548	(plus:TF (match_operand:TF 1 "register_operand" "e")
6549		 (match_operand:TF 2 "register_operand" "e")))]
6550  "TARGET_FPU && TARGET_HARD_QUAD"
6551  "faddq\t%1, %2, %0"
6552  [(set_attr "type" "fp")])
6553
6554(define_insn "adddf3"
6555  [(set (match_operand:DF 0 "register_operand" "=e")
6556	(plus:DF (match_operand:DF 1 "register_operand" "e")
6557		 (match_operand:DF 2 "register_operand" "e")))]
6558  "TARGET_FPU"
6559  "faddd\t%1, %2, %0"
6560  [(set_attr "type" "fp")
6561   (set_attr "fptype" "double")])
6562
6563(define_insn "addsf3"
6564  [(set (match_operand:SF 0 "register_operand" "=f")
6565	(plus:SF (match_operand:SF 1 "register_operand" "f")
6566		 (match_operand:SF 2 "register_operand" "f")))]
6567  "TARGET_FPU"
6568  "fadds\t%1, %2, %0"
6569  [(set_attr "type" "fp")])
6570
6571(define_expand "subtf3"
6572  [(set (match_operand:TF 0 "nonimmediate_operand" "")
6573	(minus:TF (match_operand:TF 1 "general_operand" "")
6574		  (match_operand:TF 2 "general_operand" "")))]
6575  "TARGET_FPU && (TARGET_HARD_QUAD || TARGET_ARCH64)"
6576  "emit_tfmode_binop (MINUS, operands); DONE;")
6577
6578(define_insn "*subtf3_hq"
6579  [(set (match_operand:TF 0 "register_operand" "=e")
6580	(minus:TF (match_operand:TF 1 "register_operand" "e")
6581		  (match_operand:TF 2 "register_operand" "e")))]
6582  "TARGET_FPU && TARGET_HARD_QUAD"
6583  "fsubq\t%1, %2, %0"
6584  [(set_attr "type" "fp")])
6585
6586(define_insn "subdf3"
6587  [(set (match_operand:DF 0 "register_operand" "=e")
6588	(minus:DF (match_operand:DF 1 "register_operand" "e")
6589		  (match_operand:DF 2 "register_operand" "e")))]
6590  "TARGET_FPU"
6591  "fsubd\t%1, %2, %0"
6592  [(set_attr "type" "fp")
6593   (set_attr "fptype" "double")])
6594
6595(define_insn "subsf3"
6596  [(set (match_operand:SF 0 "register_operand" "=f")
6597	(minus:SF (match_operand:SF 1 "register_operand" "f")
6598		  (match_operand:SF 2 "register_operand" "f")))]
6599  "TARGET_FPU"
6600  "fsubs\t%1, %2, %0"
6601  [(set_attr "type" "fp")])
6602
6603(define_expand "multf3"
6604  [(set (match_operand:TF 0 "nonimmediate_operand" "")
6605	(mult:TF (match_operand:TF 1 "general_operand" "")
6606		 (match_operand:TF 2 "general_operand" "")))]
6607  "TARGET_FPU && (TARGET_HARD_QUAD || TARGET_ARCH64)"
6608  "emit_tfmode_binop (MULT, operands); DONE;")
6609
6610(define_insn "*multf3_hq"
6611  [(set (match_operand:TF 0 "register_operand" "=e")
6612	(mult:TF (match_operand:TF 1 "register_operand" "e")
6613		 (match_operand:TF 2 "register_operand" "e")))]
6614  "TARGET_FPU && TARGET_HARD_QUAD"
6615  "fmulq\t%1, %2, %0"
6616  [(set_attr "type" "fpmul")])
6617
6618(define_insn "muldf3"
6619  [(set (match_operand:DF 0 "register_operand" "=e")
6620	(mult:DF (match_operand:DF 1 "register_operand" "e")
6621		 (match_operand:DF 2 "register_operand" "e")))]
6622  "TARGET_FPU"
6623  "fmuld\t%1, %2, %0"
6624  [(set_attr "type" "fpmul")
6625   (set_attr "fptype" "double")])
6626
6627(define_insn "mulsf3"
6628  [(set (match_operand:SF 0 "register_operand" "=f")
6629	(mult:SF (match_operand:SF 1 "register_operand" "f")
6630		 (match_operand:SF 2 "register_operand" "f")))]
6631  "TARGET_FPU"
6632  "fmuls\t%1, %2, %0"
6633  [(set_attr "type" "fpmul")])
6634
6635(define_insn "*muldf3_extend"
6636  [(set (match_operand:DF 0 "register_operand" "=e")
6637	(mult:DF (float_extend:DF (match_operand:SF 1 "register_operand" "f"))
6638		 (float_extend:DF (match_operand:SF 2 "register_operand" "f"))))]
6639  "(TARGET_V8 || TARGET_V9) && TARGET_FPU"
6640  "fsmuld\t%1, %2, %0"
6641  [(set_attr "type" "fpmul")
6642   (set_attr "fptype" "double")])
6643
6644(define_insn "*multf3_extend"
6645  [(set (match_operand:TF 0 "register_operand" "=e")
6646	(mult:TF (float_extend:TF (match_operand:DF 1 "register_operand" "e"))
6647		 (float_extend:TF (match_operand:DF 2 "register_operand" "e"))))]
6648  "(TARGET_V8 || TARGET_V9) && TARGET_FPU && TARGET_HARD_QUAD"
6649  "fdmulq\t%1, %2, %0"
6650  [(set_attr "type" "fpmul")])
6651
6652(define_expand "divtf3"
6653  [(set (match_operand:TF 0 "nonimmediate_operand" "")
6654	(div:TF (match_operand:TF 1 "general_operand" "")
6655		(match_operand:TF 2 "general_operand" "")))]
6656  "TARGET_FPU && (TARGET_HARD_QUAD || TARGET_ARCH64)"
6657  "emit_tfmode_binop (DIV, operands); DONE;")
6658
6659;; don't have timing for quad-prec. divide.
6660(define_insn "*divtf3_hq"
6661  [(set (match_operand:TF 0 "register_operand" "=e")
6662	(div:TF (match_operand:TF 1 "register_operand" "e")
6663		(match_operand:TF 2 "register_operand" "e")))]
6664  "TARGET_FPU && TARGET_HARD_QUAD"
6665  "fdivq\t%1, %2, %0"
6666  [(set_attr "type" "fpdivd")])
6667
6668(define_insn "divdf3"
6669  [(set (match_operand:DF 0 "register_operand" "=e")
6670	(div:DF (match_operand:DF 1 "register_operand" "e")
6671		(match_operand:DF 2 "register_operand" "e")))]
6672  "TARGET_FPU"
6673  "fdivd\t%1, %2, %0"
6674  [(set_attr "type" "fpdivd")
6675   (set_attr "fptype" "double")])
6676
6677(define_insn "divsf3"
6678  [(set (match_operand:SF 0 "register_operand" "=f")
6679	(div:SF (match_operand:SF 1 "register_operand" "f")
6680		(match_operand:SF 2 "register_operand" "f")))]
6681  "TARGET_FPU"
6682  "fdivs\t%1, %2, %0"
6683  [(set_attr "type" "fpdivs")])
6684
6685(define_expand "negtf2"
6686  [(set (match_operand:TF 0 "register_operand" "=e,e")
6687	(neg:TF (match_operand:TF 1 "register_operand" "0,e")))]
6688  "TARGET_FPU"
6689  "")
6690
6691(define_insn_and_split "*negtf2_notv9"
6692  [(set (match_operand:TF 0 "register_operand" "=e,e")
6693	(neg:TF (match_operand:TF 1 "register_operand" "0,e")))]
6694  ; We don't use quad float insns here so we don't need TARGET_HARD_QUAD.
6695  "TARGET_FPU
6696   && ! TARGET_V9"
6697  "@
6698  fnegs\t%0, %0
6699  #"
6700  "&& reload_completed
6701   && sparc_absnegfloat_split_legitimate (operands[0], operands[1])"
6702  [(set (match_dup 2) (neg:SF (match_dup 3)))
6703   (set (match_dup 4) (match_dup 5))
6704   (set (match_dup 6) (match_dup 7))]
6705  "operands[2] = gen_rtx_raw_REG (SFmode, REGNO (operands[0]));
6706   operands[3] = gen_rtx_raw_REG (SFmode, REGNO (operands[1]));
6707   operands[4] = gen_rtx_raw_REG (SFmode, REGNO (operands[0]) + 1);
6708   operands[5] = gen_rtx_raw_REG (SFmode, REGNO (operands[1]) + 1);
6709   operands[6] = gen_rtx_raw_REG (DFmode, REGNO (operands[0]) + 2);
6710   operands[7] = gen_rtx_raw_REG (DFmode, REGNO (operands[1]) + 2);"
6711  [(set_attr "type" "fpmove,*")
6712   (set_attr "length" "*,2")])
6713
6714(define_insn_and_split "*negtf2_v9"
6715  [(set (match_operand:TF 0 "register_operand" "=e,e")
6716	(neg:TF (match_operand:TF 1 "register_operand" "0,e")))]
6717  ; We don't use quad float insns here so we don't need TARGET_HARD_QUAD.
6718  "TARGET_FPU && TARGET_V9"
6719  "@
6720  fnegd\t%0, %0
6721  #"
6722  "&& reload_completed
6723   && sparc_absnegfloat_split_legitimate (operands[0], operands[1])"
6724  [(set (match_dup 2) (neg:DF (match_dup 3)))
6725   (set (match_dup 4) (match_dup 5))]
6726  "operands[2] = gen_rtx_raw_REG (DFmode, REGNO (operands[0]));
6727   operands[3] = gen_rtx_raw_REG (DFmode, REGNO (operands[1]));
6728   operands[4] = gen_rtx_raw_REG (DFmode, REGNO (operands[0]) + 2);
6729   operands[5] = gen_rtx_raw_REG (DFmode, REGNO (operands[1]) + 2);"
6730  [(set_attr "type" "fpmove,*")
6731   (set_attr "length" "*,2")
6732   (set_attr "fptype" "double")])
6733
6734(define_expand "negdf2"
6735  [(set (match_operand:DF 0 "register_operand" "")
6736	(neg:DF (match_operand:DF 1 "register_operand" "")))]
6737  "TARGET_FPU"
6738  "")
6739
6740(define_insn_and_split "*negdf2_notv9"
6741  [(set (match_operand:DF 0 "register_operand" "=e,e")
6742	(neg:DF (match_operand:DF 1 "register_operand" "0,e")))]
6743  "TARGET_FPU && ! TARGET_V9"
6744  "@
6745  fnegs\t%0, %0
6746  #"
6747  "&& reload_completed
6748   && sparc_absnegfloat_split_legitimate (operands[0], operands[1])"
6749  [(set (match_dup 2) (neg:SF (match_dup 3)))
6750   (set (match_dup 4) (match_dup 5))]
6751  "operands[2] = gen_rtx_raw_REG (SFmode, REGNO (operands[0]));
6752   operands[3] = gen_rtx_raw_REG (SFmode, REGNO (operands[1]));
6753   operands[4] = gen_rtx_raw_REG (SFmode, REGNO (operands[0]) + 1);
6754   operands[5] = gen_rtx_raw_REG (SFmode, REGNO (operands[1]) + 1);"
6755  [(set_attr "type" "fpmove,*")
6756   (set_attr "length" "*,2")])
6757
6758(define_insn "*negdf2_v9"
6759  [(set (match_operand:DF 0 "register_operand" "=e")
6760	(neg:DF (match_operand:DF 1 "register_operand" "e")))]
6761  "TARGET_FPU && TARGET_V9"
6762  "fnegd\t%1, %0"
6763  [(set_attr "type" "fpmove")
6764   (set_attr "fptype" "double")])
6765
6766(define_insn "negsf2"
6767  [(set (match_operand:SF 0 "register_operand" "=f")
6768	(neg:SF (match_operand:SF 1 "register_operand" "f")))]
6769  "TARGET_FPU"
6770  "fnegs\t%1, %0"
6771  [(set_attr "type" "fpmove")])
6772
6773(define_expand "abstf2"
6774  [(set (match_operand:TF 0 "register_operand" "")
6775	(abs:TF (match_operand:TF 1 "register_operand" "")))]
6776  "TARGET_FPU"
6777  "")
6778
6779(define_insn_and_split "*abstf2_notv9"
6780  [(set (match_operand:TF 0 "register_operand" "=e,e")
6781	(abs:TF (match_operand:TF 1 "register_operand" "0,e")))]
6782  ; We don't use quad float insns here so we don't need TARGET_HARD_QUAD.
6783  "TARGET_FPU && ! TARGET_V9"
6784  "@
6785  fabss\t%0, %0
6786  #"
6787  "&& reload_completed
6788   && sparc_absnegfloat_split_legitimate (operands[0], operands[1])"
6789  [(set (match_dup 2) (abs:SF (match_dup 3)))
6790   (set (match_dup 4) (match_dup 5))
6791   (set (match_dup 6) (match_dup 7))]
6792  "operands[2] = gen_rtx_raw_REG (SFmode, REGNO (operands[0]));
6793   operands[3] = gen_rtx_raw_REG (SFmode, REGNO (operands[1]));
6794   operands[4] = gen_rtx_raw_REG (SFmode, REGNO (operands[0]) + 1);
6795   operands[5] = gen_rtx_raw_REG (SFmode, REGNO (operands[1]) + 1);
6796   operands[6] = gen_rtx_raw_REG (DFmode, REGNO (operands[0]) + 2);
6797   operands[7] = gen_rtx_raw_REG (DFmode, REGNO (operands[1]) + 2);"
6798  [(set_attr "type" "fpmove,*")
6799   (set_attr "length" "*,2")])
6800
6801(define_insn "*abstf2_hq_v9"
6802  [(set (match_operand:TF 0 "register_operand" "=e,e")
6803	(abs:TF (match_operand:TF 1 "register_operand" "0,e")))]
6804  "TARGET_FPU && TARGET_V9 && TARGET_HARD_QUAD"
6805  "@
6806  fabsd\t%0, %0
6807  fabsq\t%1, %0"
6808  [(set_attr "type" "fpmove")
6809   (set_attr "fptype" "double,*")])
6810
6811(define_insn_and_split "*abstf2_v9"
6812  [(set (match_operand:TF 0 "register_operand" "=e,e")
6813	(abs:TF (match_operand:TF 1 "register_operand" "0,e")))]
6814  "TARGET_FPU && TARGET_V9 && !TARGET_HARD_QUAD"
6815  "@
6816  fabsd\t%0, %0
6817  #"
6818  "&& reload_completed
6819   && sparc_absnegfloat_split_legitimate (operands[0], operands[1])"
6820  [(set (match_dup 2) (abs:DF (match_dup 3)))
6821   (set (match_dup 4) (match_dup 5))]
6822  "operands[2] = gen_rtx_raw_REG (DFmode, REGNO (operands[0]));
6823   operands[3] = gen_rtx_raw_REG (DFmode, REGNO (operands[1]));
6824   operands[4] = gen_rtx_raw_REG (DFmode, REGNO (operands[0]) + 2);
6825   operands[5] = gen_rtx_raw_REG (DFmode, REGNO (operands[1]) + 2);"
6826  [(set_attr "type" "fpmove,*")
6827   (set_attr "length" "*,2")
6828   (set_attr "fptype" "double,*")])
6829
6830(define_expand "absdf2"
6831  [(set (match_operand:DF 0 "register_operand" "")
6832	(abs:DF (match_operand:DF 1 "register_operand" "")))]
6833  "TARGET_FPU"
6834  "")
6835
6836(define_insn_and_split "*absdf2_notv9"
6837  [(set (match_operand:DF 0 "register_operand" "=e,e")
6838	(abs:DF (match_operand:DF 1 "register_operand" "0,e")))]
6839  "TARGET_FPU && ! TARGET_V9"
6840  "@
6841  fabss\t%0, %0
6842  #"
6843  "&& reload_completed
6844   && sparc_absnegfloat_split_legitimate (operands[0], operands[1])"
6845  [(set (match_dup 2) (abs:SF (match_dup 3)))
6846   (set (match_dup 4) (match_dup 5))]
6847  "operands[2] = gen_rtx_raw_REG (SFmode, REGNO (operands[0]));
6848   operands[3] = gen_rtx_raw_REG (SFmode, REGNO (operands[1]));
6849   operands[4] = gen_rtx_raw_REG (SFmode, REGNO (operands[0]) + 1);
6850   operands[5] = gen_rtx_raw_REG (SFmode, REGNO (operands[1]) + 1);"
6851  [(set_attr "type" "fpmove,*")
6852   (set_attr "length" "*,2")])
6853
6854(define_insn "*absdf2_v9"
6855  [(set (match_operand:DF 0 "register_operand" "=e")
6856	(abs:DF (match_operand:DF 1 "register_operand" "e")))]
6857  "TARGET_FPU && TARGET_V9"
6858  "fabsd\t%1, %0"
6859  [(set_attr "type" "fpmove")
6860   (set_attr "fptype" "double")])
6861
6862(define_insn "abssf2"
6863  [(set (match_operand:SF 0 "register_operand" "=f")
6864	(abs:SF (match_operand:SF 1 "register_operand" "f")))]
6865  "TARGET_FPU"
6866  "fabss\t%1, %0"
6867  [(set_attr "type" "fpmove")])
6868
6869(define_expand "sqrttf2"
6870  [(set (match_operand:TF 0 "nonimmediate_operand" "")
6871	(sqrt:TF (match_operand:TF 1 "general_operand" "")))]
6872  "TARGET_FPU && (TARGET_HARD_QUAD || TARGET_ARCH64)"
6873  "emit_tfmode_unop (SQRT, operands); DONE;")
6874
6875(define_insn "*sqrttf2_hq"
6876  [(set (match_operand:TF 0 "register_operand" "=e")
6877	(sqrt:TF (match_operand:TF 1 "register_operand" "e")))]
6878  "TARGET_FPU && TARGET_HARD_QUAD"
6879  "fsqrtq\t%1, %0"
6880  [(set_attr "type" "fpsqrtd")])
6881
6882(define_insn "sqrtdf2"
6883  [(set (match_operand:DF 0 "register_operand" "=e")
6884	(sqrt:DF (match_operand:DF 1 "register_operand" "e")))]
6885  "TARGET_FPU"
6886  "fsqrtd\t%1, %0"
6887  [(set_attr "type" "fpsqrtd")
6888   (set_attr "fptype" "double")])
6889
6890(define_insn "sqrtsf2"
6891  [(set (match_operand:SF 0 "register_operand" "=f")
6892	(sqrt:SF (match_operand:SF 1 "register_operand" "f")))]
6893  "TARGET_FPU"
6894  "fsqrts\t%1, %0"
6895  [(set_attr "type" "fpsqrts")])
6896
6897;;- arithmetic shift instructions
6898
6899(define_insn "ashlsi3"
6900  [(set (match_operand:SI 0 "register_operand" "=r")
6901	(ashift:SI (match_operand:SI 1 "register_operand" "r")
6902		   (match_operand:SI 2 "arith_operand" "rI")))]
6903  ""
6904{
6905  if (operands[2] == const1_rtx)
6906    return "add\t%1, %1, %0";
6907  if (GET_CODE (operands[2]) == CONST_INT)
6908    operands[2] = GEN_INT (INTVAL (operands[2]) & 0x1f);
6909  return "sll\t%1, %2, %0";
6910}
6911  [(set (attr "type")
6912	(if_then_else (match_operand 2 "const1_operand" "")
6913		      (const_string "ialu") (const_string "shift")))])
6914
6915(define_expand "ashldi3"
6916  [(set (match_operand:DI 0 "register_operand" "=r")
6917	(ashift:DI (match_operand:DI 1 "register_operand" "r")
6918		   (match_operand:SI 2 "arith_operand" "rI")))]
6919  "TARGET_ARCH64 || TARGET_V8PLUS"
6920{
6921  if (! TARGET_ARCH64)
6922    {
6923      if (GET_CODE (operands[2]) == CONST_INT)
6924	FAIL;
6925      emit_insn (gen_ashldi3_v8plus (operands[0], operands[1], operands[2]));
6926      DONE;
6927    }
6928})
6929
6930(define_insn "*ashldi3_sp64"
6931  [(set (match_operand:DI 0 "register_operand" "=r")
6932	(ashift:DI (match_operand:DI 1 "register_operand" "r")
6933		   (match_operand:SI 2 "arith_operand" "rI")))]
6934  "TARGET_ARCH64"
6935{
6936  if (operands[2] == const1_rtx)
6937    return "add\t%1, %1, %0";
6938  if (GET_CODE (operands[2]) == CONST_INT)
6939    operands[2] = GEN_INT (INTVAL (operands[2]) & 0x3f);
6940  return "sllx\t%1, %2, %0";
6941}
6942  [(set (attr "type")
6943	(if_then_else (match_operand 2 "const1_operand" "")
6944		      (const_string "ialu") (const_string "shift")))])
6945
6946;; XXX UGH!
6947(define_insn "ashldi3_v8plus"
6948  [(set (match_operand:DI 0 "register_operand" "=&h,&h,r")
6949	(ashift:DI (match_operand:DI 1 "arith_operand" "rI,0,rI")
6950		   (match_operand:SI 2 "arith_operand" "rI,rI,rI")))
6951   (clobber (match_scratch:SI 3 "=X,X,&h"))]
6952  "TARGET_V8PLUS"
6953  { return sparc_v8plus_shift (operands, insn, "sllx"); }
6954  [(set_attr "type" "multi")
6955   (set_attr "length" "5,5,6")])
6956
6957;; Optimize (1LL<<x)-1
6958;; XXX this also needs to be fixed to handle equal subregs
6959;; XXX first before we could re-enable it.
6960;(define_insn ""
6961;  [(set (match_operand:DI 0 "register_operand" "=h")
6962;	(plus:DI (ashift:DI (const_int 1)
6963;			    (match_operand:SI 1 "arith_operand" "rI"))
6964;		 (const_int -1)))]
6965;  "0 && TARGET_V8PLUS"
6966;{
6967;  if (GET_CODE (operands[1]) == REG && REGNO (operands[1]) == REGNO (operands[0]))
6968;    return "mov\t1, %L0\;sllx\t%L0, %1, %L0\;sub\t%L0, 1, %L0\;srlx\t%L0, 32, %H0";
6969;  return "mov\t1, %H0\;sllx\t%H0, %1, %L0\;sub\t%L0, 1, %L0\;srlx\t%L0, 32, %H0";
6970;}
6971;  [(set_attr "type" "multi")
6972;   (set_attr "length" "4")])
6973
6974(define_insn "*cmp_cc_ashift_1"
6975  [(set (reg:CC_NOOV 100)
6976	(compare:CC_NOOV (ashift:SI (match_operand:SI 0 "register_operand" "r")
6977				    (const_int 1))
6978			 (const_int 0)))]
6979  ""
6980  "addcc\t%0, %0, %%g0"
6981  [(set_attr "type" "compare")])
6982
6983(define_insn "*cmp_cc_set_ashift_1"
6984  [(set (reg:CC_NOOV 100)
6985	(compare:CC_NOOV (ashift:SI (match_operand:SI 1 "register_operand" "r")
6986				    (const_int 1))
6987			 (const_int 0)))
6988   (set (match_operand:SI 0 "register_operand" "=r")
6989	(ashift:SI (match_dup 1) (const_int 1)))]
6990  ""
6991  "addcc\t%1, %1, %0"
6992  [(set_attr "type" "compare")])
6993
6994(define_insn "ashrsi3"
6995  [(set (match_operand:SI 0 "register_operand" "=r")
6996	(ashiftrt:SI (match_operand:SI 1 "register_operand" "r")
6997		     (match_operand:SI 2 "arith_operand" "rI")))]
6998  ""
6999  {
7000     if (GET_CODE (operands[2]) == CONST_INT)
7001       operands[2] = GEN_INT (INTVAL (operands[2]) & 0x1f);
7002     return "sra\t%1, %2, %0";
7003  }
7004  [(set_attr "type" "shift")])
7005
7006(define_insn "*ashrsi3_extend"
7007  [(set (match_operand:DI 0 "register_operand" "=r")
7008	(sign_extend:DI (ashiftrt:SI (match_operand:SI 1 "register_operand" "r")
7009				     (match_operand:SI 2 "arith_operand" "r"))))]
7010  "TARGET_ARCH64"
7011  "sra\t%1, %2, %0"
7012  [(set_attr "type" "shift")])
7013
7014;; This handles the case as above, but with constant shift instead of
7015;; register. Combiner "simplifies" it for us a little bit though.
7016(define_insn "*ashrsi3_extend2"
7017  [(set (match_operand:DI 0 "register_operand" "=r")
7018	(ashiftrt:DI (ashift:DI (subreg:DI (match_operand:SI 1 "register_operand" "r") 0)
7019				(const_int 32))
7020		     (match_operand:SI 2 "small_int_or_double" "n")))]
7021  "TARGET_ARCH64
7022   && ((GET_CODE (operands[2]) == CONST_INT
7023        && INTVAL (operands[2]) >= 32 && INTVAL (operands[2]) < 64)
7024       || (GET_CODE (operands[2]) == CONST_DOUBLE
7025	   && !CONST_DOUBLE_HIGH (operands[2])
7026           && CONST_DOUBLE_LOW (operands[2]) >= 32
7027           && CONST_DOUBLE_LOW (operands[2]) < 64))"
7028{
7029  operands[2] = GEN_INT (INTVAL (operands[2]) - 32);
7030
7031  return "sra\t%1, %2, %0";
7032}
7033  [(set_attr "type" "shift")])
7034
7035(define_expand "ashrdi3"
7036  [(set (match_operand:DI 0 "register_operand" "=r")
7037	(ashiftrt:DI (match_operand:DI 1 "register_operand" "r")
7038		     (match_operand:SI 2 "arith_operand" "rI")))]
7039  "TARGET_ARCH64 || TARGET_V8PLUS"
7040{
7041  if (! TARGET_ARCH64)
7042    {
7043      if (GET_CODE (operands[2]) == CONST_INT)
7044        FAIL;	/* prefer generic code in this case */
7045      emit_insn (gen_ashrdi3_v8plus (operands[0], operands[1], operands[2]));
7046      DONE;
7047    }
7048})
7049
7050(define_insn "*ashrdi3_sp64"
7051  [(set (match_operand:DI 0 "register_operand" "=r")
7052	(ashiftrt:DI (match_operand:DI 1 "register_operand" "r")
7053		     (match_operand:SI 2 "arith_operand" "rI")))]
7054  "TARGET_ARCH64"
7055
7056  {
7057    if (GET_CODE (operands[2]) == CONST_INT)
7058      operands[2] = GEN_INT (INTVAL (operands[2]) & 0x3f);
7059    return "srax\t%1, %2, %0";
7060  }
7061  [(set_attr "type" "shift")])
7062
7063;; XXX
7064(define_insn "ashrdi3_v8plus"
7065  [(set (match_operand:DI 0 "register_operand" "=&h,&h,r")
7066	(ashiftrt:DI (match_operand:DI 1 "arith_operand" "rI,0,rI")
7067		     (match_operand:SI 2 "arith_operand" "rI,rI,rI")))
7068   (clobber (match_scratch:SI 3 "=X,X,&h"))]
7069  "TARGET_V8PLUS"
7070  { return sparc_v8plus_shift (operands, insn, "srax"); }
7071  [(set_attr "type" "multi")
7072   (set_attr "length" "5,5,6")])
7073
7074(define_insn "lshrsi3"
7075  [(set (match_operand:SI 0 "register_operand" "=r")
7076	(lshiftrt:SI (match_operand:SI 1 "register_operand" "r")
7077		     (match_operand:SI 2 "arith_operand" "rI")))]
7078  ""
7079  {
7080    if (GET_CODE (operands[2]) == CONST_INT)
7081      operands[2] = GEN_INT (INTVAL (operands[2]) & 0x1f);
7082    return "srl\t%1, %2, %0";
7083  }
7084  [(set_attr "type" "shift")])
7085
7086;; This handles the case where
7087;; (zero_extend:DI (lshiftrt:SI (match_operand:SI) (match_operand:SI))),
7088;; but combiner "simplifies" it for us.
7089(define_insn "*lshrsi3_extend"
7090  [(set (match_operand:DI 0 "register_operand" "=r")
7091	(and:DI (subreg:DI (lshiftrt:SI (match_operand:SI 1 "register_operand" "r")
7092			   (match_operand:SI 2 "arith_operand" "r")) 0)
7093		(match_operand 3 "" "")))]
7094  "TARGET_ARCH64
7095   && ((GET_CODE (operands[3]) == CONST_DOUBLE
7096           && CONST_DOUBLE_HIGH (operands[3]) == 0
7097           && CONST_DOUBLE_LOW (operands[3]) == 0xffffffff)
7098       || (HOST_BITS_PER_WIDE_INT >= 64
7099	   && GET_CODE (operands[3]) == CONST_INT
7100           && (unsigned HOST_WIDE_INT) INTVAL (operands[3]) == 0xffffffff))"
7101  "srl\t%1, %2, %0"
7102  [(set_attr "type" "shift")])
7103
7104;; This handles the case where
7105;; (lshiftrt:DI (zero_extend:DI (match_operand:SI)) (const_int >=0 < 32))
7106;; but combiner "simplifies" it for us.
7107(define_insn "*lshrsi3_extend2"
7108  [(set (match_operand:DI 0 "register_operand" "=r")
7109	(zero_extract:DI (subreg:DI (match_operand:SI 1 "register_operand" "r") 0)
7110			 (match_operand 2 "small_int_or_double" "n")
7111			 (const_int 32)))]
7112  "TARGET_ARCH64
7113   && ((GET_CODE (operands[2]) == CONST_INT
7114        && (unsigned HOST_WIDE_INT) INTVAL (operands[2]) < 32)
7115       || (GET_CODE (operands[2]) == CONST_DOUBLE
7116	   && CONST_DOUBLE_HIGH (operands[2]) == 0
7117           && (unsigned HOST_WIDE_INT) CONST_DOUBLE_LOW (operands[2]) < 32))"
7118{
7119  operands[2] = GEN_INT (32 - INTVAL (operands[2]));
7120
7121  return "srl\t%1, %2, %0";
7122}
7123  [(set_attr "type" "shift")])
7124
7125(define_expand "lshrdi3"
7126  [(set (match_operand:DI 0 "register_operand" "=r")
7127	(lshiftrt:DI (match_operand:DI 1 "register_operand" "r")
7128		     (match_operand:SI 2 "arith_operand" "rI")))]
7129  "TARGET_ARCH64 || TARGET_V8PLUS"
7130{
7131  if (! TARGET_ARCH64)
7132    {
7133      if (GET_CODE (operands[2]) == CONST_INT)
7134        FAIL;
7135      emit_insn (gen_lshrdi3_v8plus (operands[0], operands[1], operands[2]));
7136      DONE;
7137    }
7138})
7139
7140(define_insn "*lshrdi3_sp64"
7141  [(set (match_operand:DI 0 "register_operand" "=r")
7142	(lshiftrt:DI (match_operand:DI 1 "register_operand" "r")
7143		     (match_operand:SI 2 "arith_operand" "rI")))]
7144  "TARGET_ARCH64"
7145  {
7146    if (GET_CODE (operands[2]) == CONST_INT)
7147      operands[2] = GEN_INT (INTVAL (operands[2]) & 0x3f);
7148    return "srlx\t%1, %2, %0";
7149  }
7150  [(set_attr "type" "shift")])
7151
7152;; XXX
7153(define_insn "lshrdi3_v8plus"
7154  [(set (match_operand:DI 0 "register_operand" "=&h,&h,r")
7155	(lshiftrt:DI (match_operand:DI 1 "arith_operand" "rI,0,rI")
7156		     (match_operand:SI 2 "arith_operand" "rI,rI,rI")))
7157   (clobber (match_scratch:SI 3 "=X,X,&h"))]
7158  "TARGET_V8PLUS"
7159  { return sparc_v8plus_shift (operands, insn, "srlx"); }
7160  [(set_attr "type" "multi")
7161   (set_attr "length" "5,5,6")])
7162
7163(define_insn ""
7164  [(set (match_operand:SI 0 "register_operand" "=r")
7165	(ashiftrt:SI (subreg:SI (lshiftrt:DI (match_operand:DI 1 "register_operand" "r")
7166					     (const_int 32)) 4)
7167		     (match_operand:SI 2 "small_int_or_double" "n")))]
7168  "TARGET_ARCH64
7169   && ((GET_CODE (operands[2]) == CONST_INT
7170        && (unsigned HOST_WIDE_INT) INTVAL (operands[2]) < 32)
7171       || (GET_CODE (operands[2]) == CONST_DOUBLE
7172	   && !CONST_DOUBLE_HIGH (operands[2])
7173           && (unsigned HOST_WIDE_INT) CONST_DOUBLE_LOW (operands[2]) < 32))"
7174{
7175  operands[2] = GEN_INT (INTVAL (operands[2]) + 32);
7176
7177  return "srax\t%1, %2, %0";
7178}
7179  [(set_attr "type" "shift")])
7180
7181(define_insn ""
7182  [(set (match_operand:SI 0 "register_operand" "=r")
7183	(lshiftrt:SI (subreg:SI (ashiftrt:DI (match_operand:DI 1 "register_operand" "r")
7184					     (const_int 32)) 4)
7185		     (match_operand:SI 2 "small_int_or_double" "n")))]
7186  "TARGET_ARCH64
7187   && ((GET_CODE (operands[2]) == CONST_INT
7188        && (unsigned HOST_WIDE_INT) INTVAL (operands[2]) < 32)
7189       || (GET_CODE (operands[2]) == CONST_DOUBLE
7190	   && !CONST_DOUBLE_HIGH (operands[2])
7191           && (unsigned HOST_WIDE_INT) CONST_DOUBLE_LOW (operands[2]) < 32))"
7192{
7193  operands[2] = GEN_INT (INTVAL (operands[2]) + 32);
7194
7195  return "srlx\t%1, %2, %0";
7196}
7197  [(set_attr "type" "shift")])
7198
7199(define_insn ""
7200  [(set (match_operand:SI 0 "register_operand" "=r")
7201	(ashiftrt:SI (subreg:SI (ashiftrt:DI (match_operand:DI 1 "register_operand" "r")
7202					     (match_operand:SI 2 "small_int_or_double" "n")) 4)
7203		     (match_operand:SI 3 "small_int_or_double" "n")))]
7204  "TARGET_ARCH64
7205   && GET_CODE (operands[2]) == CONST_INT && GET_CODE (operands[3]) == CONST_INT
7206   && (unsigned HOST_WIDE_INT) INTVAL (operands[2]) >= 32
7207   && (unsigned HOST_WIDE_INT) INTVAL (operands[3]) < 32
7208   && (unsigned HOST_WIDE_INT) (INTVAL (operands[2]) + INTVAL (operands[3])) < 64"
7209{
7210  operands[2] = GEN_INT (INTVAL (operands[2]) + INTVAL (operands[3]));
7211
7212  return "srax\t%1, %2, %0";
7213}
7214  [(set_attr "type" "shift")])
7215
7216(define_insn ""
7217  [(set (match_operand:SI 0 "register_operand" "=r")
7218	(lshiftrt:SI (subreg:SI (lshiftrt:DI (match_operand:DI 1 "register_operand" "r")
7219					     (match_operand:SI 2 "small_int_or_double" "n")) 4)
7220		     (match_operand:SI 3 "small_int_or_double" "n")))]
7221  "TARGET_ARCH64
7222   && GET_CODE (operands[2]) == CONST_INT && GET_CODE (operands[3]) == CONST_INT
7223   && (unsigned HOST_WIDE_INT) INTVAL (operands[2]) >= 32
7224   && (unsigned HOST_WIDE_INT) INTVAL (operands[3]) < 32
7225   && (unsigned HOST_WIDE_INT) (INTVAL (operands[2]) + INTVAL (operands[3])) < 64"
7226{
7227  operands[2] = GEN_INT (INTVAL (operands[2]) + INTVAL (operands[3]));
7228
7229  return "srlx\t%1, %2, %0";
7230}
7231  [(set_attr "type" "shift")])
7232
7233;; Unconditional and other jump instructions
7234(define_insn "jump"
7235  [(set (pc) (label_ref (match_operand 0 "" "")))]
7236  ""
7237  "* return output_ubranch (operands[0], 0, insn);"
7238  [(set_attr "type" "uncond_branch")])
7239
7240(define_expand "tablejump"
7241  [(parallel [(set (pc) (match_operand 0 "register_operand" "r"))
7242	      (use (label_ref (match_operand 1 "" "")))])]
7243  ""
7244{
7245  if (GET_MODE (operands[0]) != CASE_VECTOR_MODE)
7246    abort ();
7247
7248  /* In pic mode, our address differences are against the base of the
7249     table.  Add that base value back in; CSE ought to be able to combine
7250     the two address loads.  */
7251  if (flag_pic)
7252    {
7253      rtx tmp, tmp2;
7254      tmp = gen_rtx_LABEL_REF (Pmode, operands[1]);
7255      tmp2 = operands[0];
7256      if (CASE_VECTOR_MODE != Pmode)
7257        tmp2 = gen_rtx_SIGN_EXTEND (Pmode, tmp2);
7258      tmp = gen_rtx_PLUS (Pmode, tmp2, tmp);
7259      operands[0] = memory_address (Pmode, tmp);
7260    }
7261})
7262
7263(define_insn "*tablejump_sp32"
7264  [(set (pc) (match_operand:SI 0 "address_operand" "p"))
7265   (use (label_ref (match_operand 1 "" "")))]
7266  "! TARGET_ARCH64"
7267  "jmp\t%a0%#"
7268  [(set_attr "type" "uncond_branch")])
7269
7270(define_insn "*tablejump_sp64"
7271  [(set (pc) (match_operand:DI 0 "address_operand" "p"))
7272   (use (label_ref (match_operand 1 "" "")))]
7273  "TARGET_ARCH64"
7274  "jmp\t%a0%#"
7275  [(set_attr "type" "uncond_branch")])
7276
7277;; This pattern recognizes the "instruction" that appears in
7278;; a function call that wants a structure value,
7279;; to inform the called function if compiled with Sun CC.
7280;(define_insn "*unimp_insn"
7281;  [(match_operand:SI 0 "immediate_operand" "")]
7282;  "GET_CODE (operands[0]) == CONST_INT && INTVAL (operands[0]) > 0"
7283;  "unimp\t%0"
7284;  [(set_attr "type" "marker")])
7285
7286;;- jump to subroutine
7287(define_expand "call"
7288  ;; Note that this expression is not used for generating RTL.
7289  ;; All the RTL is generated explicitly below.
7290  [(call (match_operand 0 "call_operand" "")
7291	 (match_operand 3 "" "i"))]
7292  ;; operands[2] is next_arg_register
7293  ;; operands[3] is struct_value_size_rtx.
7294  ""
7295{
7296  rtx fn_rtx, nregs_rtx;
7297
7298   if (GET_MODE (operands[0]) != FUNCTION_MODE)
7299    abort ();
7300
7301  if (GET_CODE (XEXP (operands[0], 0)) == LABEL_REF)
7302    {
7303      /* This is really a PIC sequence.  We want to represent
7304	 it as a funny jump so its delay slots can be filled.
7305
7306	 ??? But if this really *is* a CALL, will not it clobber the
7307	 call-clobbered registers?  We lose this if it is a JUMP_INSN.
7308	 Why cannot we have delay slots filled if it were a CALL?  */
7309
7310      if (! TARGET_ARCH64 && INTVAL (operands[3]) != 0)
7311	emit_jump_insn
7312	  (gen_rtx_PARALLEL
7313	   (VOIDmode,
7314	    gen_rtvec (3,
7315		       gen_rtx_SET (VOIDmode, pc_rtx, XEXP (operands[0], 0)),
7316		       operands[3],
7317		       gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (Pmode, 15)))));
7318      else
7319	emit_jump_insn
7320	  (gen_rtx_PARALLEL
7321	   (VOIDmode,
7322	    gen_rtvec (2,
7323		       gen_rtx_SET (VOIDmode, pc_rtx, XEXP (operands[0], 0)),
7324		       gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (Pmode, 15)))));
7325      goto finish_call;
7326    }
7327
7328  fn_rtx = operands[0];
7329
7330  /* Count the number of parameter registers being used by this call.
7331     if that argument is NULL, it means we are using them all, which
7332     means 6 on the sparc.  */
7333#if 0
7334  if (operands[2])
7335    nregs_rtx = GEN_INT (REGNO (operands[2]) - 8);
7336  else
7337    nregs_rtx = GEN_INT (6);
7338#else
7339  nregs_rtx = const0_rtx;
7340#endif
7341
7342  if (! TARGET_ARCH64 && INTVAL (operands[3]) != 0)
7343    emit_call_insn
7344      (gen_rtx_PARALLEL
7345       (VOIDmode,
7346	gen_rtvec (3, gen_rtx_CALL (VOIDmode, fn_rtx, nregs_rtx),
7347		   operands[3],
7348		   gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (Pmode, 15)))));
7349  else
7350    emit_call_insn
7351      (gen_rtx_PARALLEL
7352       (VOIDmode,
7353	gen_rtvec (2, gen_rtx_CALL (VOIDmode, fn_rtx, nregs_rtx),
7354		   gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (Pmode, 15)))));
7355
7356 finish_call:
7357#if 0
7358  /* If this call wants a structure value,
7359     emit an unimp insn to let the called function know about this.  */
7360  if (! TARGET_ARCH64 && INTVAL (operands[3]) > 0)
7361    {
7362      rtx insn = emit_insn (operands[3]);
7363      SCHED_GROUP_P (insn) = 1;
7364    }
7365#endif
7366
7367  DONE;
7368})
7369
7370;; We can't use the same pattern for these two insns, because then registers
7371;; in the address may not be properly reloaded.
7372
7373(define_insn "*call_address_sp32"
7374  [(call (mem:SI (match_operand:SI 0 "address_operand" "p"))
7375	 (match_operand 1 "" ""))
7376   (clobber (reg:SI 15))]
7377  ;;- Do not use operand 1 for most machines.
7378  "! TARGET_ARCH64"
7379  "call\t%a0, %1%#"
7380  [(set_attr "type" "call")])
7381
7382(define_insn "*call_symbolic_sp32"
7383  [(call (mem:SI (match_operand:SI 0 "symbolic_operand" "s"))
7384	 (match_operand 1 "" ""))
7385   (clobber (reg:SI 15))]
7386  ;;- Do not use operand 1 for most machines.
7387  "! TARGET_ARCH64"
7388  "call\t%a0, %1%#"
7389  [(set_attr "type" "call")])
7390
7391(define_insn "*call_address_sp64"
7392  [(call (mem:DI (match_operand:DI 0 "address_operand" "p"))
7393	 (match_operand 1 "" ""))
7394   (clobber (reg:DI 15))]
7395  ;;- Do not use operand 1 for most machines.
7396  "TARGET_ARCH64"
7397  "call\t%a0, %1%#"
7398  [(set_attr "type" "call")])
7399
7400(define_insn "*call_symbolic_sp64"
7401  [(call (mem:DI (match_operand:DI 0 "symbolic_operand" "s"))
7402	 (match_operand 1 "" ""))
7403   (clobber (reg:DI 15))]
7404  ;;- Do not use operand 1 for most machines.
7405  "TARGET_ARCH64"
7406  "call\t%a0, %1%#"
7407  [(set_attr "type" "call")])
7408
7409;; This is a call that wants a structure value.
7410;; There is no such critter for v9 (??? we may need one anyway).
7411(define_insn "*call_address_struct_value_sp32"
7412  [(call (mem:SI (match_operand:SI 0 "address_operand" "p"))
7413	 (match_operand 1 "" ""))
7414   (match_operand 2 "immediate_operand" "")
7415   (clobber (reg:SI 15))]
7416  ;;- Do not use operand 1 for most machines.
7417  "! TARGET_ARCH64 && GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) >= 0"
7418  "call\t%a0, %1\n\tnop\n\tunimp\t%2"
7419  [(set_attr "type" "call_no_delay_slot")
7420   (set_attr "length" "3")])
7421
7422;; This is a call that wants a structure value.
7423;; There is no such critter for v9 (??? we may need one anyway).
7424(define_insn "*call_symbolic_struct_value_sp32"
7425  [(call (mem:SI (match_operand:SI 0 "symbolic_operand" "s"))
7426	 (match_operand 1 "" ""))
7427   (match_operand 2 "immediate_operand" "")
7428   (clobber (reg:SI 15))]
7429  ;;- Do not use operand 1 for most machines.
7430  "! TARGET_ARCH64 && GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) >= 0"
7431  "call\t%a0, %1\n\tnop\n\tunimp\t%2"
7432  [(set_attr "type" "call_no_delay_slot")
7433   (set_attr "length" "3")])
7434
7435;; This is a call that may want a structure value.  This is used for
7436;; untyped_calls.
7437(define_insn "*call_address_untyped_struct_value_sp32"
7438  [(call (mem:SI (match_operand:SI 0 "address_operand" "p"))
7439	 (match_operand 1 "" ""))
7440   (match_operand 2 "immediate_operand" "")
7441   (clobber (reg:SI 15))]
7442  ;;- Do not use operand 1 for most machines.
7443  "! TARGET_ARCH64 && GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) < 0"
7444  "call\t%a0, %1\n\tnop\n\tnop"
7445  [(set_attr "type" "call_no_delay_slot")
7446   (set_attr "length" "3")])
7447
7448;; This is a call that wants a structure value.
7449(define_insn "*call_symbolic_untyped_struct_value_sp32"
7450  [(call (mem:SI (match_operand:SI 0 "symbolic_operand" "s"))
7451	 (match_operand 1 "" ""))
7452   (match_operand 2 "immediate_operand" "")
7453   (clobber (reg:SI 15))]
7454  ;;- Do not use operand 1 for most machines.
7455  "! TARGET_ARCH64 && GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) < 0"
7456  "call\t%a0, %1\n\tnop\n\tnop"
7457  [(set_attr "type" "call_no_delay_slot")
7458   (set_attr "length" "3")])
7459
7460(define_expand "call_value"
7461  ;; Note that this expression is not used for generating RTL.
7462  ;; All the RTL is generated explicitly below.
7463  [(set (match_operand 0 "register_operand" "=rf")
7464	(call (match_operand 1 "" "")
7465	      (match_operand 4 "" "")))]
7466  ;; operand 2 is stack_size_rtx
7467  ;; operand 3 is next_arg_register
7468  ""
7469{
7470  rtx fn_rtx, nregs_rtx;
7471  rtvec vec;
7472
7473  if (GET_MODE (operands[1]) != FUNCTION_MODE)
7474    abort ();
7475
7476  fn_rtx = operands[1];
7477
7478#if 0
7479  if (operands[3])
7480    nregs_rtx = GEN_INT (REGNO (operands[3]) - 8);
7481  else
7482    nregs_rtx = GEN_INT (6);
7483#else
7484  nregs_rtx = const0_rtx;
7485#endif
7486
7487  vec = gen_rtvec (2,
7488		   gen_rtx_SET (VOIDmode, operands[0],
7489				gen_rtx_CALL (VOIDmode, fn_rtx, nregs_rtx)),
7490		   gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (Pmode, 15)));
7491
7492  emit_call_insn (gen_rtx_PARALLEL (VOIDmode, vec));
7493
7494  DONE;
7495})
7496
7497(define_insn "*call_value_address_sp32"
7498  [(set (match_operand 0 "" "=rf")
7499	(call (mem:SI (match_operand:SI 1 "address_operand" "p"))
7500	      (match_operand 2 "" "")))
7501   (clobber (reg:SI 15))]
7502  ;;- Do not use operand 2 for most machines.
7503  "! TARGET_ARCH64"
7504  "call\t%a1, %2%#"
7505  [(set_attr "type" "call")])
7506
7507(define_insn "*call_value_symbolic_sp32"
7508  [(set (match_operand 0 "" "=rf")
7509	(call (mem:SI (match_operand:SI 1 "symbolic_operand" "s"))
7510	      (match_operand 2 "" "")))
7511   (clobber (reg:SI 15))]
7512  ;;- Do not use operand 2 for most machines.
7513  "! TARGET_ARCH64"
7514  "call\t%a1, %2%#"
7515  [(set_attr "type" "call")])
7516
7517(define_insn "*call_value_address_sp64"
7518  [(set (match_operand 0 "" "")
7519	(call (mem:DI (match_operand:DI 1 "address_operand" "p"))
7520	      (match_operand 2 "" "")))
7521   (clobber (reg:DI 15))]
7522  ;;- Do not use operand 2 for most machines.
7523  "TARGET_ARCH64"
7524  "call\t%a1, %2%#"
7525  [(set_attr "type" "call")])
7526
7527(define_insn "*call_value_symbolic_sp64"
7528  [(set (match_operand 0 "" "")
7529	(call (mem:DI (match_operand:DI 1 "symbolic_operand" "s"))
7530	      (match_operand 2 "" "")))
7531   (clobber (reg:DI 15))]
7532  ;;- Do not use operand 2 for most machines.
7533  "TARGET_ARCH64"
7534  "call\t%a1, %2%#"
7535  [(set_attr "type" "call")])
7536
7537(define_expand "untyped_call"
7538  [(parallel [(call (match_operand 0 "" "")
7539		    (const_int 0))
7540	      (match_operand 1 "" "")
7541	      (match_operand 2 "" "")])]
7542  ""
7543{
7544  int i;
7545
7546  /* Pass constm1 to indicate that it may expect a structure value, but
7547     we don't know what size it is.  */
7548  emit_call_insn (GEN_CALL (operands[0], const0_rtx, NULL, constm1_rtx));
7549
7550  for (i = 0; i < XVECLEN (operands[2], 0); i++)
7551    {
7552      rtx set = XVECEXP (operands[2], 0, i);
7553      emit_move_insn (SET_DEST (set), SET_SRC (set));
7554    }
7555
7556  /* The optimizer does not know that the call sets the function value
7557     registers we stored in the result block.  We avoid problems by
7558     claiming that all hard registers are used and clobbered at this
7559     point.  */
7560  emit_insn (gen_blockage ());
7561
7562  DONE;
7563})
7564
7565;;- tail calls
7566(define_expand "sibcall"
7567  [(parallel [(call (match_operand 0 "call_operand" "") (const_int 0))
7568	      (return)])]
7569  ""
7570  "")
7571
7572(define_insn "*sibcall_symbolic_sp32"
7573  [(call (mem:SI (match_operand:SI 0 "symbolic_operand" "s"))
7574	 (match_operand 1 "" ""))
7575   (return)]
7576  "! TARGET_ARCH64"
7577  "* return output_sibcall(insn, operands[0]);"
7578  [(set_attr "type" "sibcall")])
7579
7580(define_insn "*sibcall_symbolic_sp64"
7581  [(call (mem:DI (match_operand:DI 0 "symbolic_operand" "s"))
7582	 (match_operand 1 "" ""))
7583   (return)]
7584  "TARGET_ARCH64"
7585  "* return output_sibcall(insn, operands[0]);"
7586  [(set_attr "type" "sibcall")])
7587
7588(define_expand "sibcall_value"
7589  [(parallel [(set (match_operand 0 "register_operand" "=rf")
7590		(call (match_operand 1 "" "") (const_int 0)))
7591	      (return)])]
7592  ""
7593  "")
7594
7595(define_insn "*sibcall_value_symbolic_sp32"
7596  [(set (match_operand 0 "" "=rf")
7597	(call (mem:SI (match_operand:SI 1 "symbolic_operand" "s"))
7598	      (match_operand 2 "" "")))
7599   (return)]
7600  "! TARGET_ARCH64"
7601  "* return output_sibcall(insn, operands[1]);"
7602  [(set_attr "type" "sibcall")])
7603
7604(define_insn "*sibcall_value_symbolic_sp64"
7605  [(set (match_operand 0 "" "")
7606	(call (mem:DI (match_operand:DI 1 "symbolic_operand" "s"))
7607	      (match_operand 2 "" "")))
7608   (return)]
7609  "TARGET_ARCH64"
7610  "* return output_sibcall(insn, operands[1]);"
7611  [(set_attr "type" "sibcall")])
7612
7613(define_expand "sibcall_epilogue"
7614  [(const_int 0)]
7615  ""
7616  "DONE;")
7617
7618;; UNSPEC_VOLATILE is considered to use and clobber all hard registers and
7619;; all of memory.  This blocks insns from being moved across this point.
7620
7621(define_insn "blockage"
7622  [(unspec_volatile [(const_int 0)] UNSPECV_BLOCKAGE)]
7623  ""
7624  ""
7625  [(set_attr "length" "0")])
7626
7627;; Prepare to return any type including a structure value.
7628
7629(define_expand "untyped_return"
7630  [(match_operand:BLK 0 "memory_operand" "")
7631   (match_operand 1 "" "")]
7632  ""
7633{
7634  rtx valreg1 = gen_rtx_REG (DImode, 24);
7635  rtx valreg2 = gen_rtx_REG (TARGET_ARCH64 ? TFmode : DFmode, 32);
7636  rtx result = operands[0];
7637
7638  if (! TARGET_ARCH64)
7639    {
7640      rtx rtnreg = gen_rtx_REG (SImode, (current_function_uses_only_leaf_regs
7641					 ? 15 : 31));
7642      rtx value = gen_reg_rtx (SImode);
7643
7644      /* Fetch the instruction where we will return to and see if it's an unimp
7645	 instruction (the most significant 10 bits will be zero).  If so,
7646	 update the return address to skip the unimp instruction.  */
7647      emit_move_insn (value,
7648		      gen_rtx_MEM (SImode, plus_constant (rtnreg, 8)));
7649      emit_insn (gen_lshrsi3 (value, value, GEN_INT (22)));
7650      emit_insn (gen_update_return (rtnreg, value));
7651    }
7652
7653  /* Reload the function value registers.  */
7654  emit_move_insn (valreg1, adjust_address (result, DImode, 0));
7655  emit_move_insn (valreg2,
7656		  adjust_address (result, TARGET_ARCH64 ? TFmode : DFmode, 8));
7657
7658  /* Put USE insns before the return.  */
7659  emit_insn (gen_rtx_USE (VOIDmode, valreg1));
7660  emit_insn (gen_rtx_USE (VOIDmode, valreg2));
7661
7662  /* Construct the return.  */
7663  expand_null_return ();
7664
7665  DONE;
7666})
7667
7668;; This is a bit of a hack.  We're incrementing a fixed register (%i7),
7669;; and parts of the compiler don't want to believe that the add is needed.
7670
7671(define_insn "update_return"
7672  [(unspec:SI [(match_operand:SI 0 "register_operand" "r")
7673	       (match_operand:SI 1 "register_operand" "r")] UNSPEC_UPDATE_RETURN)]
7674  "! TARGET_ARCH64"
7675  "cmp\t%1, 0\;be,a\t.+8\;add\t%0, 4, %0"
7676  [(set_attr "type" "multi")
7677   (set_attr "length" "3")])
7678
7679(define_insn "nop"
7680  [(const_int 0)]
7681  ""
7682  "nop")
7683
7684(define_expand "indirect_jump"
7685  [(set (pc) (match_operand 0 "address_operand" "p"))]
7686  ""
7687  "")
7688
7689(define_insn "*branch_sp32"
7690  [(set (pc) (match_operand:SI 0 "address_operand" "p"))]
7691  "! TARGET_ARCH64"
7692 "jmp\t%a0%#"
7693 [(set_attr "type" "uncond_branch")])
7694
7695(define_insn "*branch_sp64"
7696  [(set (pc) (match_operand:DI 0 "address_operand" "p"))]
7697  "TARGET_ARCH64"
7698  "jmp\t%a0%#"
7699  [(set_attr "type" "uncond_branch")])
7700
7701;; ??? Doesn't work with -mflat.
7702(define_expand "nonlocal_goto"
7703  [(match_operand:SI 0 "general_operand" "")
7704   (match_operand:SI 1 "general_operand" "")
7705   (match_operand:SI 2 "general_operand" "")
7706   (match_operand:SI 3 "" "")]
7707  ""
7708{
7709#if 0
7710  rtx chain = operands[0];
7711#endif
7712  rtx lab = operands[1];
7713  rtx stack = operands[2];
7714  rtx fp = operands[3];
7715  rtx labreg;
7716
7717  /* Trap instruction to flush all the register windows.  */
7718  emit_insn (gen_flush_register_windows ());
7719
7720  /* Load the fp value for the containing fn into %fp.  This is needed
7721     because STACK refers to %fp.  Note that virtual register instantiation
7722     fails if the virtual %fp isn't set from a register.  */
7723  if (GET_CODE (fp) != REG)
7724    fp = force_reg (Pmode, fp);
7725  emit_move_insn (virtual_stack_vars_rtx, fp);
7726
7727  /* Find the containing function's current nonlocal goto handler,
7728     which will do any cleanups and then jump to the label.  */
7729  labreg = gen_rtx_REG (Pmode, 8);
7730  emit_move_insn (labreg, lab);
7731
7732  /* Restore %fp from stack pointer value for containing function.
7733     The restore insn that follows will move this to %sp,
7734     and reload the appropriate value into %fp.  */
7735  emit_move_insn (hard_frame_pointer_rtx, stack);
7736
7737  /* USE of frame_pointer_rtx added for consistency; not clear if
7738     really needed.  */
7739  /*emit_insn (gen_rtx_USE (VOIDmode, frame_pointer_rtx));*/
7740  emit_insn (gen_rtx_USE (VOIDmode, stack_pointer_rtx));
7741
7742#if 0
7743  /* Return, restoring reg window and jumping to goto handler.  */
7744  if (TARGET_V9 && GET_CODE (chain) == CONST_INT
7745      && ! (INTVAL (chain) & ~(HOST_WIDE_INT)0xffffffff))
7746    {
7747      emit_jump_insn (gen_goto_handler_and_restore_v9 (labreg,
7748						       static_chain_rtx,
7749						       chain));
7750      emit_barrier ();
7751      DONE;
7752    }
7753  /* Put in the static chain register the nonlocal label address.  */
7754  emit_move_insn (static_chain_rtx, chain);
7755#endif
7756
7757  emit_insn (gen_rtx_USE (VOIDmode, static_chain_rtx));
7758  emit_jump_insn (gen_goto_handler_and_restore (labreg));
7759  emit_barrier ();
7760  DONE;
7761})
7762
7763;; Special trap insn to flush register windows.
7764(define_insn "flush_register_windows"
7765  [(unspec_volatile [(const_int 0)] UNSPECV_FLUSHW)]
7766  ""
7767  { return TARGET_V9 ? "flushw" : "ta\t3"; }
7768  [(set_attr "type" "flushw")])
7769
7770(define_insn "goto_handler_and_restore"
7771  [(unspec_volatile [(match_operand 0 "register_operand" "=r")] UNSPECV_GOTO)]
7772  "GET_MODE (operands[0]) == Pmode"
7773  "jmp\t%0+0\n\trestore"
7774  [(set_attr "type" "multi")
7775   (set_attr "length" "2")])
7776
7777;;(define_insn "goto_handler_and_restore_v9"
7778;;  [(unspec_volatile [(match_operand:SI 0 "register_operand" "=r,r")
7779;;		     (match_operand:SI 1 "register_operand" "=r,r")
7780;;		     (match_operand:SI 2 "const_int_operand" "I,n")] UNSPECV_GOTO_V9)]
7781;;  "TARGET_V9 && ! TARGET_ARCH64"
7782;;  "@
7783;;   return\t%0+0\n\tmov\t%2, %Y1
7784;;   sethi\t%%hi(%2), %1\n\treturn\t%0+0\n\tor\t%Y1, %%lo(%2), %Y1"
7785;;  [(set_attr "type" "multi")
7786;;   (set_attr "length" "2,3")])
7787;;
7788;;(define_insn "*goto_handler_and_restore_v9_sp64"
7789;;  [(unspec_volatile [(match_operand:DI 0 "register_operand" "=r,r")
7790;;		     (match_operand:DI 1 "register_operand" "=r,r")
7791;;		     (match_operand:SI 2 "const_int_operand" "I,n")] UNSPECV_GOTO_V9)]
7792;;  "TARGET_V9 && TARGET_ARCH64"
7793;;  "@
7794;;   return\t%0+0\n\tmov\t%2, %Y1
7795;;   sethi\t%%hi(%2), %1\n\treturn\t%0+0\n\tor\t%Y1, %%lo(%2), %Y1"
7796;;  [(set_attr "type" "multi")
7797;;   (set_attr "length" "2,3")])
7798
7799;; For __builtin_setjmp we need to flush register windows iff the function
7800;; calls alloca as well, because otherwise the register window might be
7801;; saved after %sp adjustement and thus setjmp would crash
7802(define_expand "builtin_setjmp_setup"
7803  [(match_operand 0 "register_operand" "r")]
7804  ""
7805{
7806  emit_insn (gen_do_builtin_setjmp_setup ());
7807  DONE;
7808})
7809
7810(define_insn "do_builtin_setjmp_setup"
7811  [(unspec_volatile [(const_int 0)] UNSPECV_SETJMP)]
7812  ""
7813{
7814  if (! current_function_calls_alloca)
7815    return "";
7816  if (! TARGET_V9 || TARGET_FLAT)
7817    return "\tta\t3\n";
7818  fputs ("\tflushw\n", asm_out_file);
7819  if (flag_pic)
7820    fprintf (asm_out_file, "\tst%c\t%%l7, [%%sp+%d]\n",
7821	     TARGET_ARCH64 ? 'x' : 'w',
7822	     SPARC_STACK_BIAS + 7 * UNITS_PER_WORD);
7823  fprintf (asm_out_file, "\tst%c\t%%fp, [%%sp+%d]\n",
7824	   TARGET_ARCH64 ? 'x' : 'w',
7825	   SPARC_STACK_BIAS + 14 * UNITS_PER_WORD);
7826  fprintf (asm_out_file, "\tst%c\t%%i7, [%%sp+%d]\n",
7827	   TARGET_ARCH64 ? 'x' : 'w',
7828	   SPARC_STACK_BIAS + 15 * UNITS_PER_WORD);
7829  return "";
7830}
7831  [(set_attr "type" "multi")
7832   (set (attr "length")
7833        (cond [(eq_attr "current_function_calls_alloca" "false")
7834                 (const_int 0)
7835               (eq_attr "flat" "true")
7836                 (const_int 1)
7837               (eq_attr "isa" "!v9")
7838                 (const_int 1)
7839               (eq_attr "pic" "true")
7840                 (const_int 4)] (const_int 3)))])
7841
7842;; Pattern for use after a setjmp to store FP and the return register
7843;; into the stack area.
7844
7845(define_expand "setjmp"
7846  [(const_int 0)]
7847  ""
7848{
7849  if (TARGET_ARCH64)
7850    emit_insn (gen_setjmp_64 ());
7851  else
7852    emit_insn (gen_setjmp_32 ());
7853  DONE;
7854})
7855
7856(define_expand "setjmp_32"
7857  [(set (mem:SI (plus:SI (reg:SI 14) (const_int 56))) (match_dup 0))
7858   (set (mem:SI (plus:SI (reg:SI 14) (const_int 60))) (reg:SI 31))]
7859  ""
7860  { operands[0] = frame_pointer_rtx; })
7861
7862(define_expand "setjmp_64"
7863  [(set (mem:DI (plus:DI (reg:DI 14) (const_int 112))) (match_dup 0))
7864   (set (mem:DI (plus:DI (reg:DI 14) (const_int 120))) (reg:DI 31))]
7865  ""
7866  { operands[0] = frame_pointer_rtx; })
7867
7868;; Special pattern for the FLUSH instruction.
7869
7870; We do SImode and DImode versions of this to quiet down genrecog's complaints
7871; of the define_insn otherwise missing a mode.  We make "flush", aka
7872; gen_flush, the default one since sparc_initialize_trampoline uses
7873; it on SImode mem values.
7874
7875(define_insn "flush"
7876  [(unspec_volatile [(match_operand:SI 0 "memory_operand" "m")] UNSPECV_FLUSH)]
7877  ""
7878  { return TARGET_V9 ? "flush\t%f0" : "iflush\t%f0"; }
7879  [(set_attr "type" "iflush")])
7880
7881(define_insn "flushdi"
7882  [(unspec_volatile [(match_operand:DI 0 "memory_operand" "m")] UNSPECV_FLUSH)]
7883  ""
7884  { return TARGET_V9 ? "flush\t%f0" : "iflush\t%f0"; }
7885  [(set_attr "type" "iflush")])
7886
7887
7888;; find first set.
7889
7890;; The scan instruction searches from the most significant bit while ffs
7891;; searches from the least significant bit.  The bit index and treatment of
7892;; zero also differ.  It takes at least 7 instructions to get the proper
7893;; result.  Here is an obvious 8 instruction sequence.
7894
7895;; XXX
7896(define_insn "ffssi2"
7897  [(set (match_operand:SI 0 "register_operand" "=&r")
7898	(ffs:SI (match_operand:SI 1 "register_operand" "r")))
7899   (clobber (match_scratch:SI 2 "=&r"))]
7900  "TARGET_SPARCLITE || TARGET_SPARCLET"
7901{
7902  return "sub\t%%g0, %1, %0\;and\t%0, %1, %0\;scan\t%0, 0, %0\;mov\t32, %2\;sub\t%2, %0, %0\;sra\t%0, 31, %2\;and\t%2, 31, %2\;add\t%2, %0, %0";
7903}
7904  [(set_attr "type" "multi")
7905   (set_attr "length" "8")])
7906
7907;; ??? This should be a define expand, so that the extra instruction have
7908;; a chance of being optimized away.
7909
7910;; Disabled because none of the UltraSPARCs implement popc.  The HAL R1
7911;; does, but no one uses that and we don't have a switch for it.
7912;
7913;(define_insn "ffsdi2"
7914;  [(set (match_operand:DI 0 "register_operand" "=&r")
7915;	(ffs:DI (match_operand:DI 1 "register_operand" "r")))
7916;   (clobber (match_scratch:DI 2 "=&r"))]
7917;  "TARGET_ARCH64"
7918;  "neg\t%1, %2\;xnor\t%1, %2, %2\;popc\t%2, %0\;movzr\t%1, 0, %0"
7919;  [(set_attr "type" "multi")
7920;   (set_attr "length" "4")])
7921
7922
7923
7924;; Peepholes go at the end.
7925
7926;; Optimize consecutive loads or stores into ldd and std when possible.
7927;; The conditions in which we do this are very restricted and are
7928;; explained in the code for {registers,memory}_ok_for_ldd functions.
7929
7930(define_peephole2
7931  [(set (match_operand:SI 0 "memory_operand" "")
7932      (const_int 0))
7933   (set (match_operand:SI 1 "memory_operand" "")
7934      (const_int 0))]
7935  "TARGET_V9
7936   && mems_ok_for_ldd_peep (operands[0], operands[1], NULL_RTX)"
7937  [(set (match_dup 0)
7938       (const_int 0))]
7939  "operands[0] = widen_memory_access (operands[0], DImode, 0);")
7940
7941(define_peephole2
7942  [(set (match_operand:SI 0 "memory_operand" "")
7943      (const_int 0))
7944   (set (match_operand:SI 1 "memory_operand" "")
7945      (const_int 0))]
7946  "TARGET_V9
7947   && mems_ok_for_ldd_peep (operands[1], operands[0], NULL_RTX)"
7948  [(set (match_dup 1)
7949       (const_int 0))]
7950  "operands[1] = widen_memory_access (operands[1], DImode, 0);")
7951
7952(define_peephole2
7953  [(set (match_operand:SI 0 "register_operand" "")
7954        (match_operand:SI 1 "memory_operand" ""))
7955   (set (match_operand:SI 2 "register_operand" "")
7956        (match_operand:SI 3 "memory_operand" ""))]
7957  "registers_ok_for_ldd_peep (operands[0], operands[2])
7958   && mems_ok_for_ldd_peep (operands[1], operands[3], operands[0])"
7959  [(set (match_dup 0)
7960	(match_dup 1))]
7961  "operands[1] = widen_memory_access (operands[1], DImode, 0);
7962   operands[0] = gen_rtx_REG (DImode, REGNO (operands[0]));")
7963
7964(define_peephole2
7965  [(set (match_operand:SI 0 "memory_operand" "")
7966        (match_operand:SI 1 "register_operand" ""))
7967   (set (match_operand:SI 2 "memory_operand" "")
7968        (match_operand:SI 3 "register_operand" ""))]
7969  "registers_ok_for_ldd_peep (operands[1], operands[3])
7970   && mems_ok_for_ldd_peep (operands[0], operands[2], NULL_RTX)"
7971  [(set (match_dup 0)
7972	(match_dup 1))]
7973  "operands[0] = widen_memory_access (operands[0], DImode, 0);
7974   operands[1] = gen_rtx_REG (DImode, REGNO (operands[1]));")
7975
7976(define_peephole2
7977  [(set (match_operand:SF 0 "register_operand" "")
7978        (match_operand:SF 1 "memory_operand" ""))
7979   (set (match_operand:SF 2 "register_operand" "")
7980        (match_operand:SF 3 "memory_operand" ""))]
7981  "registers_ok_for_ldd_peep (operands[0], operands[2])
7982   && mems_ok_for_ldd_peep (operands[1], operands[3], operands[0])"
7983  [(set (match_dup 0)
7984	(match_dup 1))]
7985  "operands[1] = widen_memory_access (operands[1], DFmode, 0);
7986   operands[0] = gen_rtx_REG (DFmode, REGNO (operands[0]));")
7987
7988(define_peephole2
7989  [(set (match_operand:SF 0 "memory_operand" "")
7990        (match_operand:SF 1 "register_operand" ""))
7991   (set (match_operand:SF 2 "memory_operand" "")
7992        (match_operand:SF 3 "register_operand" ""))]
7993  "registers_ok_for_ldd_peep (operands[1], operands[3])
7994  && mems_ok_for_ldd_peep (operands[0], operands[2], NULL_RTX)"
7995  [(set (match_dup 0)
7996	(match_dup 1))]
7997  "operands[0] = widen_memory_access (operands[0], DFmode, 0);
7998   operands[1] = gen_rtx_REG (DFmode, REGNO (operands[1]));")
7999
8000(define_peephole2
8001  [(set (match_operand:SI 0 "register_operand" "")
8002        (match_operand:SI 1 "memory_operand" ""))
8003   (set (match_operand:SI 2 "register_operand" "")
8004        (match_operand:SI 3 "memory_operand" ""))]
8005  "registers_ok_for_ldd_peep (operands[2], operands[0])
8006  && mems_ok_for_ldd_peep (operands[3], operands[1], operands[0])"
8007  [(set (match_dup 2)
8008	(match_dup 3))]
8009   "operands[3] = widen_memory_access (operands[3], DImode, 0);
8010    operands[2] = gen_rtx_REG (DImode, REGNO (operands[2]));")
8011
8012(define_peephole2
8013  [(set (match_operand:SI 0 "memory_operand" "")
8014        (match_operand:SI 1 "register_operand" ""))
8015   (set (match_operand:SI 2 "memory_operand" "")
8016        (match_operand:SI 3 "register_operand" ""))]
8017  "registers_ok_for_ldd_peep (operands[3], operands[1])
8018  && mems_ok_for_ldd_peep (operands[2], operands[0], NULL_RTX)"
8019  [(set (match_dup 2)
8020	(match_dup 3))]
8021  "operands[2] = widen_memory_access (operands[2], DImode, 0);
8022   operands[3] = gen_rtx_REG (DImode, REGNO (operands[3]));
8023   ")
8024
8025(define_peephole2
8026  [(set (match_operand:SF 0 "register_operand" "")
8027        (match_operand:SF 1 "memory_operand" ""))
8028   (set (match_operand:SF 2 "register_operand" "")
8029        (match_operand:SF 3 "memory_operand" ""))]
8030  "registers_ok_for_ldd_peep (operands[2], operands[0])
8031  && mems_ok_for_ldd_peep (operands[3], operands[1], operands[0])"
8032  [(set (match_dup 2)
8033	(match_dup 3))]
8034  "operands[3] = widen_memory_access (operands[3], DFmode, 0);
8035   operands[2] = gen_rtx_REG (DFmode, REGNO (operands[2]));")
8036
8037(define_peephole2
8038  [(set (match_operand:SF 0 "memory_operand" "")
8039        (match_operand:SF 1 "register_operand" ""))
8040   (set (match_operand:SF 2 "memory_operand" "")
8041        (match_operand:SF 3 "register_operand" ""))]
8042  "registers_ok_for_ldd_peep (operands[3], operands[1])
8043  && mems_ok_for_ldd_peep (operands[2], operands[0], NULL_RTX)"
8044  [(set (match_dup 2)
8045	(match_dup 3))]
8046  "operands[2] = widen_memory_access (operands[2], DFmode, 0);
8047   operands[3] = gen_rtx_REG (DFmode, REGNO (operands[3]));")
8048
8049;; Optimize the case of following a reg-reg move with a test
8050;; of reg just moved.  Don't allow floating point regs for operand 0 or 1.
8051;; This can result from a float to fix conversion.
8052
8053(define_peephole2
8054  [(set (match_operand:SI 0 "register_operand" "")
8055	(match_operand:SI 1 "register_operand" ""))
8056   (set (reg:CC 100)
8057	(compare:CC (match_operand:SI 2 "register_operand" "")
8058		    (const_int 0)))]
8059  "(rtx_equal_p (operands[2], operands[0])
8060    || rtx_equal_p (operands[2], operands[1]))
8061    && ! SPARC_FP_REG_P (REGNO (operands[0]))
8062    && ! SPARC_FP_REG_P (REGNO (operands[1]))"
8063  [(parallel [(set (match_dup 0) (match_dup 1))
8064	      (set (reg:CC 100)
8065		   (compare:CC (match_dup 1) (const_int 0)))])]
8066  "")
8067
8068(define_peephole2
8069  [(set (match_operand:DI 0 "register_operand" "")
8070	(match_operand:DI 1 "register_operand" ""))
8071   (set (reg:CCX 100)
8072	(compare:CCX (match_operand:DI 2 "register_operand" "")
8073		    (const_int 0)))]
8074  "TARGET_ARCH64
8075   && (rtx_equal_p (operands[2], operands[0])
8076       || rtx_equal_p (operands[2], operands[1]))
8077   && ! SPARC_FP_REG_P (REGNO (operands[0]))
8078   && ! SPARC_FP_REG_P (REGNO (operands[1]))"
8079  [(parallel [(set (match_dup 0) (match_dup 1))
8080	      (set (reg:CCX 100)
8081		   (compare:CCX (match_dup 1) (const_int 0)))])]
8082  "")
8083
8084;; Return peepholes.  These are generated by sparc_nonflat_function_epilogue
8085;; who then immediately calls final_scan_insn.
8086
8087(define_insn "*return_qi"
8088  [(set (match_operand:QI 0 "restore_operand" "")
8089	(match_operand:QI 1 "arith_operand" "rI"))
8090   (return)]
8091  "sparc_emitting_epilogue"
8092{
8093  if (! TARGET_ARCH64 && current_function_returns_struct)
8094    return "jmp\t%%i7+12\n\trestore %%g0, %1, %Y0";
8095  else if (TARGET_V9 && (GET_CODE (operands[1]) == CONST_INT
8096			 || IN_OR_GLOBAL_P (operands[1])))
8097    return "return\t%%i7+8\n\tmov\t%Y1, %Y0";
8098  else
8099    return "ret\n\trestore %%g0, %1, %Y0";
8100}
8101  [(set_attr "type" "multi")
8102   (set_attr "length" "2")])
8103
8104(define_insn "*return_hi"
8105  [(set (match_operand:HI 0 "restore_operand" "")
8106	(match_operand:HI 1 "arith_operand" "rI"))
8107   (return)]
8108  "sparc_emitting_epilogue"
8109{
8110  if (! TARGET_ARCH64 && current_function_returns_struct)
8111    return "jmp\t%%i7+12\n\trestore %%g0, %1, %Y0";
8112  else if (TARGET_V9 && (GET_CODE (operands[1]) == CONST_INT
8113			 || IN_OR_GLOBAL_P (operands[1])))
8114    return "return\t%%i7+8\n\tmov\t%Y1, %Y0";
8115  else
8116    return "ret\;restore %%g0, %1, %Y0";
8117}
8118  [(set_attr "type" "multi")
8119   (set_attr "length" "2")])
8120
8121(define_insn "*return_si"
8122  [(set (match_operand:SI 0 "restore_operand" "")
8123	(match_operand:SI 1 "arith_operand" "rI"))
8124   (return)]
8125  "sparc_emitting_epilogue"
8126{
8127  if (! TARGET_ARCH64 && current_function_returns_struct)
8128    return "jmp\t%%i7+12\n\trestore %%g0, %1, %Y0";
8129  else if (TARGET_V9 && (GET_CODE (operands[1]) == CONST_INT
8130			 || IN_OR_GLOBAL_P (operands[1])))
8131    return "return\t%%i7+8\n\tmov\t%Y1, %Y0";
8132  else
8133    return "ret\;restore %%g0, %1, %Y0";
8134}
8135  [(set_attr "type" "multi")
8136   (set_attr "length" "2")])
8137
8138(define_insn "*return_sf_no_fpu"
8139  [(set (match_operand:SF 0 "restore_operand" "=r")
8140	(match_operand:SF 1 "register_operand" "r"))
8141   (return)]
8142  "sparc_emitting_epilogue"
8143{
8144  if (! TARGET_ARCH64 && current_function_returns_struct)
8145    return "jmp\t%%i7+12\n\trestore %%g0, %1, %Y0";
8146  else if (TARGET_V9 && IN_OR_GLOBAL_P (operands[1]))
8147    return "return\t%%i7+8\n\tmov\t%Y1, %Y0";
8148  else
8149    return "ret\;restore %%g0, %1, %Y0";
8150}
8151  [(set_attr "type" "multi")
8152   (set_attr "length" "2")])
8153
8154(define_insn "*return_df_no_fpu"
8155  [(set (match_operand:DF 0 "restore_operand" "=r")
8156	(match_operand:DF 1 "register_operand" "r"))
8157   (return)]
8158  "sparc_emitting_epilogue && TARGET_ARCH64"
8159{
8160  if (IN_OR_GLOBAL_P (operands[1]))
8161    return "return\t%%i7+8\n\tmov\t%Y1, %Y0";
8162  else
8163    return "ret\;restore %%g0, %1, %Y0";
8164}
8165  [(set_attr "type" "multi")
8166   (set_attr "length" "2")])
8167
8168(define_insn "*return_addsi"
8169  [(set (match_operand:SI 0 "restore_operand" "")
8170	(plus:SI (match_operand:SI 1 "register_operand" "r")
8171		 (match_operand:SI 2 "arith_operand" "rI")))
8172   (return)]
8173  "sparc_emitting_epilogue"
8174{
8175  if (! TARGET_ARCH64 && current_function_returns_struct)
8176    return "jmp\t%%i7+12\n\trestore %r1, %2, %Y0";
8177  /* If operands are global or in registers, can use return */
8178  else if (TARGET_V9 && IN_OR_GLOBAL_P (operands[1])
8179	   && (GET_CODE (operands[2]) == CONST_INT
8180	       || IN_OR_GLOBAL_P (operands[2])))
8181    return "return\t%%i7+8\n\tadd\t%Y1, %Y2, %Y0";
8182  else
8183    return "ret\;restore %r1, %2, %Y0";
8184}
8185  [(set_attr "type" "multi")
8186   (set_attr "length" "2")])
8187
8188(define_insn "*return_losum_si"
8189  [(set (match_operand:SI 0 "restore_operand" "")
8190	(lo_sum:SI (match_operand:SI 1 "register_operand" "r")
8191		   (match_operand:SI 2 "immediate_operand" "in")))
8192   (return)]
8193  "sparc_emitting_epilogue && ! TARGET_CM_MEDMID"
8194{
8195  if (! TARGET_ARCH64 && current_function_returns_struct)
8196    return "jmp\t%%i7+12\n\trestore %r1, %%lo(%a2), %Y0";
8197  /* If operands are global or in registers, can use return */
8198  else if (TARGET_V9 && IN_OR_GLOBAL_P (operands[1]))
8199    return "return\t%%i7+8\n\tor\t%Y1, %%lo(%a2), %Y0";
8200  else
8201    return "ret\;restore %r1, %%lo(%a2), %Y0";
8202}
8203  [(set_attr "type" "multi")
8204   (set_attr "length" "2")])
8205
8206(define_insn "*return_di"
8207  [(set (match_operand:DI 0 "restore_operand" "")
8208	(match_operand:DI 1 "arith_double_operand" "rHI"))
8209   (return)]
8210  "sparc_emitting_epilogue && TARGET_ARCH64"
8211  "ret\;restore %%g0, %1, %Y0"
8212  [(set_attr "type" "multi")
8213   (set_attr "length" "2")])
8214
8215(define_insn "*return_adddi"
8216  [(set (match_operand:DI 0 "restore_operand" "")
8217	(plus:DI (match_operand:DI 1 "arith_operand" "%r")
8218		 (match_operand:DI 2 "arith_double_operand" "rHI")))
8219   (return)]
8220  "sparc_emitting_epilogue && TARGET_ARCH64"
8221  "ret\;restore %r1, %2, %Y0"
8222  [(set_attr "type" "multi")
8223   (set_attr "length" "2")])
8224
8225(define_insn "*return_losum_di"
8226  [(set (match_operand:DI 0 "restore_operand" "")
8227	(lo_sum:DI (match_operand:DI 1 "arith_operand" "%r")
8228		   (match_operand:DI 2 "immediate_operand" "in")))
8229   (return)]
8230  "sparc_emitting_epilogue && TARGET_ARCH64 && ! TARGET_CM_MEDMID"
8231  "ret\;restore %r1, %%lo(%a2), %Y0"
8232  [(set_attr "type" "multi")
8233   (set_attr "length" "2")])
8234
8235(define_insn "*return_sf"
8236  [(set (reg:SF 32)
8237	(match_operand:SF 0 "register_operand" "f"))
8238   (return)]
8239  "sparc_emitting_epilogue"
8240  "ret\;fmovs\t%0, %%f0"
8241  [(set_attr "type" "multi")
8242   (set_attr "length" "2")])
8243
8244;; ??? UltraSPARC-III note: A memory operation loading into the floating point register
8245;; ??? file, if it hits the prefetch cache, has a chance to dual-issue with other memory
8246;; ??? operations.  With DFA we might be able to model this, but it requires a lot of
8247;; ??? state.
8248(define_expand "prefetch"
8249  [(match_operand 0 "address_operand" "")
8250   (match_operand 1 "const_int_operand" "")
8251   (match_operand 2 "const_int_operand" "")]
8252  "TARGET_V9"
8253{
8254  if (TARGET_ARCH64)
8255    emit_insn (gen_prefetch_64 (operands[0], operands[1], operands[2]));
8256  else
8257    emit_insn (gen_prefetch_32 (operands[0], operands[1], operands[2]));
8258  DONE;
8259})
8260
8261(define_insn "prefetch_64"
8262  [(prefetch (match_operand:DI 0 "address_operand" "p")
8263	     (match_operand:DI 1 "const_int_operand" "n")
8264	     (match_operand:DI 2 "const_int_operand" "n"))]
8265  ""
8266{
8267  static const char * const prefetch_instr[2][2] = {
8268    {
8269      "prefetch\t[%a0], 1", /* no locality: prefetch for one read */
8270      "prefetch\t[%a0], 0", /* medium to high locality: prefetch for several reads */
8271    },
8272    {
8273      "prefetch\t[%a0], 3", /* no locality: prefetch for one write */
8274      "prefetch\t[%a0], 2", /* medium to high locality: prefetch for several writes */
8275    }
8276  };
8277  int read_or_write = INTVAL (operands[1]);
8278  int locality = INTVAL (operands[2]);
8279
8280  if (read_or_write != 0 && read_or_write != 1)
8281    abort ();
8282  if (locality < 0 || locality > 3)
8283    abort ();
8284  return prefetch_instr [read_or_write][locality == 0 ? 0 : 1];
8285}
8286  [(set_attr "type" "load")])
8287
8288(define_insn "prefetch_32"
8289  [(prefetch (match_operand:SI 0 "address_operand" "p")
8290	     (match_operand:SI 1 "const_int_operand" "n")
8291	     (match_operand:SI 2 "const_int_operand" "n"))]
8292  ""
8293{
8294  static const char * const prefetch_instr[2][2] = {
8295    {
8296      "prefetch\t[%a0], 1", /* no locality: prefetch for one read */
8297      "prefetch\t[%a0], 0", /* medium to high locality: prefetch for several reads */
8298    },
8299    {
8300      "prefetch\t[%a0], 3", /* no locality: prefetch for one write */
8301      "prefetch\t[%a0], 2", /* medium to high locality: prefetch for several writes */
8302    }
8303  };
8304  int read_or_write = INTVAL (operands[1]);
8305  int locality = INTVAL (operands[2]);
8306
8307  if (read_or_write != 0 && read_or_write != 1)
8308    abort ();
8309  if (locality < 0 || locality > 3)
8310    abort ();
8311  return prefetch_instr [read_or_write][locality == 0 ? 0 : 1];
8312}
8313  [(set_attr "type" "load")])
8314
8315(define_expand "prologue"
8316  [(const_int 1)]
8317  "flag_pic && current_function_uses_pic_offset_table"
8318{
8319  load_pic_register ();
8320  DONE;
8321})
8322
8323;; We need to reload %l7 for -mflat -fpic,
8324;; otherwise %l7 should be preserved simply
8325;; by loading the function's register window
8326(define_expand "exception_receiver"
8327  [(const_int 0)]
8328  "TARGET_FLAT && flag_pic"
8329{
8330  load_pic_register ();
8331  DONE;
8332})
8333
8334;; Likewise
8335(define_expand "builtin_setjmp_receiver"
8336  [(label_ref (match_operand 0 "" ""))]
8337  "TARGET_FLAT && flag_pic"
8338{
8339  load_pic_register ();
8340  DONE;
8341})
8342
8343(define_insn "trap"
8344  [(trap_if (const_int 1) (const_int 5))]
8345  ""
8346  "ta\t5"
8347  [(set_attr "type" "trap")])
8348
8349(define_expand "conditional_trap"
8350  [(trap_if (match_operator 0 "noov_compare_op"
8351			    [(match_dup 2) (match_dup 3)])
8352	    (match_operand:SI 1 "arith_operand" ""))]
8353  ""
8354  "operands[2] = gen_compare_reg (GET_CODE (operands[0]),
8355				  sparc_compare_op0, sparc_compare_op1);
8356   operands[3] = const0_rtx;")
8357
8358(define_insn ""
8359  [(trap_if (match_operator 0 "noov_compare_op" [(reg:CC 100) (const_int 0)])
8360	    (match_operand:SI 1 "arith_operand" "rM"))]
8361  ""
8362  "t%C0\t%1"
8363  [(set_attr "type" "trap")])
8364
8365(define_insn ""
8366  [(trap_if (match_operator 0 "noov_compare_op" [(reg:CCX 100) (const_int 0)])
8367	    (match_operand:SI 1 "arith_operand" "rM"))]
8368  "TARGET_V9"
8369  "t%C0\t%%xcc, %1"
8370  [(set_attr "type" "trap")])
8371