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