OSDN Git Service

ef28accc355495c9311e1a191964a15a56d7599f
[pf3gnuchains/gcc-fork.git] / gcc / config / sparc / sparc.md
1 ;;- Machine description for SPARC chip for GNU C compiler
2 ;;  Copyright (C) 1987, 88, 89, 92-96, 1997 Free Software Foundation, Inc.
3 ;;  Contributed by Michael Tiemann (tiemann@cygnus.com)
4 ;;  64 bit SPARC V9 support by Michael Tiemann, Jim Wilson, and Doug Evans,
5 ;;  at Cygnus Support.
6
7 ;; This file is part of GNU CC.
8
9 ;; GNU CC 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 2, or (at your option)
12 ;; any later version.
13
14 ;; GNU CC 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 GNU CC; see the file COPYING.  If not, write to
21 ;; the Free Software Foundation, 59 Temple Place - Suite 330,
22 ;; Boston, MA 02111-1307, USA.
23
24 ;;- See file "rtl.def" for documentation on define_insn, match_*, et. al.
25
26 ;; The upper 32 fp regs on the v9 can't hold SFmode values.  To deal with this
27 ;; a second register class, EXTRA_FP_REGS, exists for the v9 chip.  The name
28 ;; is a bit of a misnomer as it covers all 64 fp regs.  The corresponding
29 ;; constraint letter is 'e'.  To avoid any confusion, 'e' is used instead of
30 ;; 'f' for all DF/TFmode values, including those that are specific to the v8.
31 ;;
32 ;; -mlive-g0 is *not* supported for TARGET_ARCH64, so we don't bother to
33 ;; test TARGET_LIVE_G0 if we have TARGET_ARCH64.
34
35 ;; Attribute for cpu type.
36 ;; These must match the values for enum processor_type in sparc.h.
37 (define_attr "cpu" "v7,cypress,v8,supersparc,sparclite,f930,f934,sparclet,tsc701,v8plus,v9,ultrasparc"
38   (const (symbol_ref "sparc_cpu_attr")))
39
40 ;; Attribute for the instruction set.
41 ;; At present we only need to distinguish v9/!v9, but for clarity we
42 ;; test TARGET_V8 too.
43 (define_attr "isa" "v6,v8,v9,sparclet"
44  (const
45   (cond [(symbol_ref "TARGET_V9") (const_string "v9")
46          (symbol_ref "TARGET_V8") (const_string "v8")
47          (symbol_ref "TARGET_SPARCLET") (const_string "sparclet")]
48         (const_string "v6"))))
49
50 ;; Architecture size.
51 (define_attr "arch" "arch32bit,arch64bit"
52  (const
53   (cond [(symbol_ref "TARGET_ARCH64") (const_string "arch64bit")]
54         (const_string "arch32bit"))))
55
56 ;; Whether -mlive-g0 is in effect.
57 (define_attr "live_g0" "no,yes"
58  (const
59   (cond [(symbol_ref "TARGET_LIVE_G0") (const_string "yes")]
60         (const_string "no"))))
61
62 ;; Insn type.  Used to default other attribute values.
63
64 ;; type "unary" insns have one input operand (1) and one output operand (0)
65 ;; type "binary" insns have two input operands (1,2) and one output (0)
66 ;; type "compare" insns have one or two input operands (0,1) and no output
67 ;; type "call_no_delay_slot" is a call followed by an unimp instruction.
68
69 (define_attr "type"
70   "move,unary,binary,compare,load,store,ialu,shift,uncond_branch,branch,call,call_no_delay_slot,address,imul,fpload,fpstore,fp,fpcmp,fpmul,fpdivs,fpdivd,fpsqrt,cmove,multi,misc"
71   (const_string "binary"))
72
73 ;; Set true if insn uses call-clobbered intermediate register.
74 (define_attr "use_clobbered" "false,true"
75   (if_then_else (and (eq_attr "type" "address")
76                      (match_operand 0 "clobbered_register" ""))
77                 (const_string "true")
78                 (const_string "false")))
79
80 ;; Length (in # of insns).
81 (define_attr "length" ""
82   (cond [(eq_attr "type" "load,fpload")
83          (if_then_else (match_operand 1 "symbolic_memory_operand" "")
84                        (const_int 2) (const_int 1))
85
86          (eq_attr "type" "store,fpstore")
87          (if_then_else (match_operand 0 "symbolic_memory_operand" "")
88                        (const_int 2) (const_int 1))
89
90          (eq_attr "type" "address") (const_int 2)
91
92          (eq_attr "type" "binary")
93          (if_then_else (ior (match_operand 2 "arith_operand" "")
94                             (match_operand 2 "arith_double_operand" ""))
95                        (const_int 1) (const_int 3))
96
97          (eq_attr "type" "multi") (const_int 2)
98
99          (eq_attr "type" "move,unary")
100          (if_then_else (ior (match_operand 1 "arith_operand" "")
101                             (match_operand 1 "arith_double_operand" ""))
102                        (const_int 1) (const_int 2))]
103
104         (const_int 1)))
105
106 (define_asm_attributes
107   [(set_attr "length" "1")
108    (set_attr "type" "multi")])
109
110 ;; Attributes for instruction and branch scheduling
111
112 (define_attr "in_call_delay" "false,true"
113   (cond [(eq_attr "type" "uncond_branch,branch,call,call_no_delay_slot,multi")
114                 (const_string "false")
115          (eq_attr "type" "load,fpload,store,fpstore")
116                 (if_then_else (eq_attr "length" "1")
117                               (const_string "true")
118                               (const_string "false"))
119          (eq_attr "type" "address")
120                 (if_then_else (eq_attr "use_clobbered" "false")
121                               (const_string "true")
122                               (const_string "false"))]
123         (if_then_else (eq_attr "length" "1")
124                       (const_string "true")
125                       (const_string "false"))))
126
127 (define_delay (eq_attr "type" "call")
128   [(eq_attr "in_call_delay" "true") (nil) (nil)])
129
130 ;; ??? Should implement the notion of predelay slots for floating point
131 ;; branches.  This would allow us to remove the nop always inserted before
132 ;; a floating point branch.
133
134 ;; ??? It is OK for fill_simple_delay_slots to put load/store instructions
135 ;; in a delay slot, but it is not OK for fill_eager_delay_slots to do so.
136 ;; This is because doing so will add several pipeline stalls to the path
137 ;; that the load/store did not come from.  Unfortunately, there is no way
138 ;; to prevent fill_eager_delay_slots from using load/store without completely
139 ;; disabling them.  For the SPEC benchmark set, this is a serious lose,
140 ;; because it prevents us from moving back the final store of inner loops.
141
142 (define_attr "in_branch_delay" "false,true"
143   (if_then_else (and (eq_attr "type" "!uncond_branch,branch,call,call_no_delay_slot,multi")
144                      (eq_attr "length" "1"))
145                 (const_string "true")
146                 (const_string "false")))
147
148 (define_attr "in_uncond_branch_delay" "false,true"
149   (if_then_else (and (eq_attr "type" "!uncond_branch,branch,call,call_no_delay_slot,multi")
150                      (eq_attr "length" "1"))
151                 (const_string "true")
152                 (const_string "false")))
153
154 (define_attr "in_annul_branch_delay" "false,true"
155   (if_then_else (and (eq_attr "type" "!uncond_branch,branch,call,call_no_delay_slot,multi")
156                      (eq_attr "length" "1"))
157                 (const_string "true")
158                 (const_string "false")))
159
160 (define_delay (eq_attr "type" "branch")
161   [(eq_attr "in_branch_delay" "true")
162    (nil) (eq_attr "in_annul_branch_delay" "true")])
163
164 (define_delay (eq_attr "type" "uncond_branch")
165   [(eq_attr "in_uncond_branch_delay" "true")
166    (nil) (nil)])
167    
168 ;; Function units of the SPARC
169
170 ;; (define_function_unit {name} {num-units} {n-users} {test}
171 ;;                       {ready-delay} {issue-delay} [{conflict-list}])
172
173 ;; The integer ALU.
174 ;; (Noted only for documentation; units that take one cycle do not need to
175 ;; be specified.)
176
177 ;; On the sparclite, integer multiply takes 1, 3, or 5 cycles depending on
178 ;; the inputs.
179
180 ;; (define_function_unit "alu" 1 0
181 ;;  (eq_attr "type" "unary,binary,move,address") 1 0)
182
183 ;; ---- cypress CY7C602 scheduling:
184 ;; Memory with load-delay of 1 (i.e., 2 cycle load).
185 (define_function_unit "memory" 1 0 
186   (and (eq_attr "type" "load,fpload") (eq_attr "cpu" "cypress")) 2 2)
187
188 ;; SPARC has two floating-point units: the FP ALU,
189 ;; and the FP MUL/DIV/SQRT unit.
190 ;; Instruction timings on the CY7C602 are as follows
191 ;; FABSs        4
192 ;; FADDs/d      5/5
193 ;; FCMPs/d      4/4
194 ;; FDIVs/d      23/37
195 ;; FMOVs        4
196 ;; FMULs/d      5/7
197 ;; FNEGs        4
198 ;; FSQRTs/d     34/63
199 ;; FSUBs/d      5/5
200 ;; FdTOi/s      5/5
201 ;; FsTOi/d      5/5
202 ;; FiTOs/d      9/5
203
204 ;; The CY7C602 can only support 2 fp isnsn simultaneously.
205 ;; More insns cause the chip to stall.
206
207 (define_function_unit "fp_alu" 1 0
208   (and (eq_attr "type" "fp")            (eq_attr "cpu" "cypress")) 5 5)
209 (define_function_unit "fp_mds" 1 0
210   (and (eq_attr "type" "fpmul")         (eq_attr "cpu" "cypress")) 7 7)
211 (define_function_unit "fp_mds" 1 0
212   (and (eq_attr "type" "fpdivs,fpdivd") (eq_attr "cpu" "cypress")) 37 37)
213 (define_function_unit "fp_mds" 1 0
214   (and (eq_attr "type" "fpsqrt")        (eq_attr "cpu" "cypress")) 63 63)
215
216 ;; ----- The TMS390Z55 scheduling
217 ;; The Supersparc can issue 1 - 3 insns per cycle; here we assume
218 ;; three insns/cycle, and hence multiply all costs by three.
219 ;; Combinations up to two integer, one ld/st, one fp.
220 ;; Memory delivers its result in one cycle to IU, zero cycles to FP
221 (define_function_unit "memory" 1 0
222   (and (eq_attr "type" "load")          (eq_attr "cpu" "supersparc")) 3 3)
223 (define_function_unit "memory" 1 0
224   (and (eq_attr "type" "fpload")        (eq_attr "cpu" "supersparc")) 1 3)
225 ;; at least one in three instructions can be a mem opt.
226 (define_function_unit "memory" 1 0
227   (and (eq_attr "type" "store,fpstore") (eq_attr "cpu" "supersparc")) 1 3)
228 ;; at least one in three instructions can be a shift op.
229 (define_function_unit "shift" 1 0
230   (and (eq_attr "type" "shift")         (eq_attr "cpu" "supersparc")) 1 3)
231
232 ;; There are only two write ports to the integer register file
233 ;; A store also uses a write port
234 (define_function_unit "iwport" 2 0
235   (and (eq_attr "type" "load,store,shift,ialu") (eq_attr "cpu" "supersparc")) 1 3)
236
237 ;; Timings; throughput/latency
238 ;; FADD     1/3    add/sub, format conv, compar, abs, neg
239 ;; FMUL     1/3
240 ;; FDIVs    4/6
241 ;; FDIVd    7/9
242 ;; FSQRTs   6/8
243 ;; FSQRTd  10/12
244 ;; IMUL     4/4
245
246 (define_function_unit "fp_alu" 1 0
247   (and (eq_attr "type" "fp,fpcmp") (eq_attr "cpu" "supersparc")) 9 3)
248 (define_function_unit "fp_mds" 1 0
249   (and (eq_attr "type" "fpmul")    (eq_attr "cpu" "supersparc")) 9 3)
250 (define_function_unit "fp_mds" 1 0
251   (and (eq_attr "type" "fpdivs")   (eq_attr "cpu" "supersparc")) 18 12)
252 (define_function_unit "fp_mds" 1 0
253   (and (eq_attr "type" "fpdivd")   (eq_attr "cpu" "supersparc")) 27 21)
254 (define_function_unit "fp_mds" 1 0
255   (and (eq_attr "type" "fpsqrt")   (eq_attr "cpu" "supersparc")) 36 30)
256 (define_function_unit "fp_mds" 1 0
257   (and (eq_attr "type" "imul")     (eq_attr "cpu" "supersparc")) 12 12)
258
259 ;; ----- sparclet tsc701 scheduling
260 ;; The tsc701 issues 1 insn per cycle.
261 ;; Results may be written back out of order.
262
263 ;; Loads take 2 extra cycles to complete and 4 can be buffered at a time.
264 (define_function_unit "tsc701_load" 4 1
265   (and (eq_attr "type" "load")          (eq_attr "cpu" "tsc701")) 3 1)
266 ;; Stores take 2(?) extra cycles to complete.
267 ;; It is desirable to not have any memory operation in the following 2 cycles.
268 ;; (??? or 2 memory ops in the case of std).
269 (define_function_unit "tsc701_store" 1 0
270   (and (eq_attr "type" "store")         (eq_attr "cpu" "tsc701")) 3 3
271   [(eq_attr "type" "load,store")])
272 ;; The multiply unit has a latency of 5.
273 (define_function_unit "tsc701_mul" 1 0
274   (and (eq_attr "type" "imul")          (eq_attr "cpu" "tsc701")) 5 5)
275
276 ;; ----- The UltraSPARC-1 scheduling
277 ;; The Ultrasparc can issue 1 - 4 insns per cycle; here we assume
278 ;; four insns/cycle, and hence multiply all costs by four.
279
280 ;; Memory delivers its result in three cycles to IU, three cycles to FP
281 (define_function_unit "memory" 1 0
282   (and (eq_attr "type" "load,fpload")   (eq_attr "cpu" "ultrasparc")) 12 4)
283 (define_function_unit "memory" 1 0
284   (and (eq_attr "type" "store,fpstore") (eq_attr "cpu" "ultrasparc"))  4 4)
285 (define_function_unit "ieu" 1 0
286   (and (eq_attr "type" "ialu")          (eq_attr "cpu" "ultrasparc"))  1 2)
287 (define_function_unit "ieu" 1 0
288   (and (eq_attr "type" "shift")         (eq_attr "cpu" "ultrasparc"))  1 4)
289 (define_function_unit "ieu" 1 0
290   (and (eq_attr "type" "cmove")         (eq_attr "cpu" "ultrasparc"))  8 4)
291
292 ;; Timings; throughput/latency
293 ;; ?? FADD     1/3    add/sub, format conv, compar, abs, neg
294 ;; ?? FMUL     1/3
295 ;; ?? FDIVs    1/12
296 ;; ?? FDIVd    1/22
297 ;; ?? FSQRTs   1/12
298 ;; ?? FSQRTd   1/22
299
300 (define_function_unit "fp" 1 0
301   (and (eq_attr "type" "fp")       (eq_attr "cpu" "ultrasparc")) 12 2)
302 (define_function_unit "fp" 1 0
303   (and (eq_attr "type" "fpcmp")    (eq_attr "cpu" "ultrasparc"))  8 2)
304 (define_function_unit "fp" 1 0
305   (and (eq_attr "type" "fpmul")    (eq_attr "cpu" "ultrasparc")) 12 2)
306 (define_function_unit "fp" 1 0
307   (and (eq_attr "type" "fpdivs")   (eq_attr "cpu" "ultrasparc")) 48 2)
308 (define_function_unit "fp" 1 0
309   (and (eq_attr "type" "fpdivd")   (eq_attr "cpu" "ultrasparc")) 88 2)
310 (define_function_unit "fp" 1 0
311   (and (eq_attr "type" "fpsqrt")   (eq_attr "cpu" "ultrasparc")) 48 2)
312 \f
313 ;; Compare instructions.
314 ;; This controls RTL generation and register allocation.
315
316 ;; We generate RTL for comparisons and branches by having the cmpxx 
317 ;; patterns store away the operands.  Then, the scc and bcc patterns
318 ;; emit RTL for both the compare and the branch.
319 ;;
320 ;; We do this because we want to generate different code for an sne and
321 ;; seq insn.  In those cases, if the second operand of the compare is not
322 ;; const0_rtx, we want to compute the xor of the two operands and test
323 ;; it against zero.
324 ;;
325 ;; We start with the DEFINE_EXPANDs, then the DEFINE_INSNs to match
326 ;; the patterns.  Finally, we have the DEFINE_SPLITs for some of the scc
327 ;; insns that actually require more than one machine instruction.
328
329 ;; Put cmpsi first among compare insns so it matches two CONST_INT operands.
330
331 (define_expand "cmpsi"
332   [(set (reg:CC 100)
333         (compare:CC (match_operand:SI 0 "register_operand" "")
334                     (match_operand:SI 1 "arith_operand" "")))]
335   ""
336   "
337 {
338   sparc_compare_op0 = operands[0];
339   sparc_compare_op1 = operands[1];
340   DONE;
341 }")
342
343 (define_expand "cmpdi"
344   [(set (reg:CCX 100)
345         (compare:CCX (match_operand:DI 0 "register_operand" "")
346                      (match_operand:DI 1 "arith_double_operand" "")))]
347   "TARGET_ARCH64"
348   "
349 {
350   sparc_compare_op0 = operands[0];
351   sparc_compare_op1 = operands[1];
352   DONE;
353 }")
354
355 (define_expand "cmpsf"
356   ;; The 96 here isn't ever used by anyone.
357   [(set (reg:CCFP 96)
358         (compare:CCFP (match_operand:SF 0 "register_operand" "")
359                       (match_operand:SF 1 "register_operand" "")))]
360   "TARGET_FPU"
361   "
362 {
363   sparc_compare_op0 = operands[0];
364   sparc_compare_op1 = operands[1];
365   DONE;
366 }")
367
368 (define_expand "cmpdf"
369   ;; The 96 here isn't ever used by anyone.
370   [(set (reg:CCFP 96)
371         (compare:CCFP (match_operand:DF 0 "register_operand" "")
372                       (match_operand:DF 1 "register_operand" "")))]
373   "TARGET_FPU"
374   "
375 {
376   sparc_compare_op0 = operands[0];
377   sparc_compare_op1 = operands[1];
378   DONE;
379 }")
380
381 (define_expand "cmptf"
382   ;; The 96 here isn't ever used by anyone.
383   [(set (reg:CCFP 96)
384         (compare:CCFP (match_operand:TF 0 "register_operand" "")
385                       (match_operand:TF 1 "register_operand" "")))]
386   "TARGET_FPU"
387   "
388 {
389   sparc_compare_op0 = operands[0];
390   sparc_compare_op1 = operands[1];
391   DONE;
392 }")
393
394 ;; Now the compare DEFINE_INSNs.
395
396 (define_insn "*cmpsi_insn"
397   [(set (reg:CC 100)
398         (compare:CC (match_operand:SI 0 "register_operand" "r")
399                     (match_operand:SI 1 "arith_operand" "rI")))]
400   ""
401   "cmp %0,%1"
402   [(set_attr "type" "compare")])
403
404 (define_insn "*cmpdi_sp64"
405   [(set (reg:CCX 100)
406         (compare:CCX (match_operand:DI 0 "register_operand" "r")
407                      (match_operand:DI 1 "arith_double_operand" "rHI")))]
408   "TARGET_ARCH64"
409   "cmp %0,%1"
410   [(set_attr "type" "compare")])
411
412 (define_insn "*cmpsf_fpe"
413   [(set (match_operand:CCFPE 0 "fcc_reg_operand" "=c")
414         (compare:CCFPE (match_operand:SF 1 "register_operand" "f")
415                        (match_operand:SF 2 "register_operand" "f")))]
416   "TARGET_FPU"
417   "*
418 {
419   if (TARGET_V9)
420     return \"fcmpes %0,%1,%2\";
421   return \"fcmpes %1,%2\";
422 }"
423   [(set_attr "type" "fpcmp")])
424
425 (define_insn "*cmpdf_fpe"
426   [(set (match_operand:CCFPE 0 "fcc_reg_operand" "=c")
427         (compare:CCFPE (match_operand:DF 1 "register_operand" "e")
428                        (match_operand:DF 2 "register_operand" "e")))]
429   "TARGET_FPU"
430   "*
431 {
432   if (TARGET_V9)
433     return \"fcmped %0,%1,%2\";
434   return \"fcmped %1,%2\";
435 }"
436   [(set_attr "type" "fpcmp")])
437
438 (define_insn "*cmptf_fpe"
439   [(set (match_operand:CCFPE 0 "fcc_reg_operand" "=c")
440         (compare:CCFPE (match_operand:TF 1 "register_operand" "e")
441                        (match_operand:TF 2 "register_operand" "e")))]
442   "TARGET_FPU && TARGET_HARD_QUAD"
443   "*
444 {
445   if (TARGET_V9)
446     return \"fcmpeq %0,%1,%2\";
447   return \"fcmpeq %1,%2\";
448 }"
449   [(set_attr "type" "fpcmp")])
450
451 (define_insn "*cmpsf_fp"
452   [(set (match_operand:CCFP 0 "fcc_reg_operand" "=c")
453         (compare:CCFP (match_operand:SF 1 "register_operand" "f")
454                       (match_operand:SF 2 "register_operand" "f")))]
455   "TARGET_FPU"
456   "*
457 {
458   if (TARGET_V9)
459     return \"fcmps %0,%1,%2\";
460   return \"fcmps %1,%2\";
461 }"
462   [(set_attr "type" "fpcmp")])
463
464 (define_insn "*cmpdf_fp"
465   [(set (match_operand:CCFP 0 "fcc_reg_operand" "=c")
466         (compare:CCFP (match_operand:DF 1 "register_operand" "e")
467                       (match_operand:DF 2 "register_operand" "e")))]
468   "TARGET_FPU"
469   "*
470 {
471   if (TARGET_V9)
472     return \"fcmpd %0,%1,%2\";
473   return \"fcmpd %1,%2\";
474 }"
475   [(set_attr "type" "fpcmp")])
476
477 (define_insn "*cmptf_fp"
478   [(set (match_operand:CCFP 0 "fcc_reg_operand" "=c")
479         (compare:CCFP (match_operand:TF 1 "register_operand" "e")
480                       (match_operand:TF 2 "register_operand" "e")))]
481   "TARGET_FPU && TARGET_HARD_QUAD"
482   "*
483 {
484   if (TARGET_V9)
485     return \"fcmpq %0,%1,%2\";
486   return \"fcmpq %1,%2\";
487 }"
488   [(set_attr "type" "fpcmp")])
489 \f
490 ;; Next come the scc insns.  For seq, sne, sgeu, and sltu, we can do this
491 ;; without jumps using the addx/subx instructions.  For seq/sne on v9 we use
492 ;; the same code as v8 (the addx/subx method has more applications).  The
493 ;; exception to this is "reg != 0" which can be done in one instruction on v9
494 ;; (so we do it).  For the rest, on v9 we use conditional moves; on v8, we do
495 ;; branches.
496
497 ;; Seq_special[_xxx] and sne_special[_xxx] clobber the CC reg, because they
498 ;; generate addcc/subcc instructions.
499
500 (define_expand "seqsi_special"
501   [(set (match_dup 3)
502         (xor:SI (match_operand:SI 1 "register_operand" "")
503                 (match_operand:SI 2 "register_operand" "")))
504    (parallel [(set (match_operand:SI 0 "register_operand" "")
505                    (eq:SI (match_dup 3) (const_int 0)))
506               (clobber (reg:CC 100))])]
507   "! TARGET_LIVE_G0"
508   "{ operands[3] = gen_reg_rtx (SImode); }")
509
510 (define_expand "seqdi_special"
511   [(set (match_dup 3)
512         (xor:DI (match_operand:DI 1 "register_operand" "")
513                 (match_operand:DI 2 "register_operand" "")))
514    (set (match_operand:DI 0 "register_operand" "")
515         (eq:DI (match_dup 3) (const_int 0)))]
516   "TARGET_ARCH64"
517   "{ operands[3] = gen_reg_rtx (DImode); }")
518
519 (define_expand "snesi_special"
520   [(set (match_dup 3)
521         (xor:SI (match_operand:SI 1 "register_operand" "")
522                 (match_operand:SI 2 "register_operand" "")))
523    (parallel [(set (match_operand:SI 0 "register_operand" "")
524                    (ne:SI (match_dup 3) (const_int 0)))
525               (clobber (reg:CC 100))])]
526   "! TARGET_LIVE_G0"
527   "{ operands[3] = gen_reg_rtx (SImode); }")
528
529 (define_expand "snedi_special"
530   [(set (match_dup 3)
531         (xor:DI (match_operand:DI 1 "register_operand" "")
532                 (match_operand:DI 2 "register_operand" "")))
533    (set (match_operand:DI 0 "register_operand" "")
534         (ne:DI (match_dup 3) (const_int 0)))]
535   "TARGET_ARCH64"
536   "{ operands[3] = gen_reg_rtx (DImode); }")
537
538 (define_expand "seqdi_special_trunc"
539   [(set (match_dup 3)
540         (xor:DI (match_operand:DI 1 "register_operand" "")
541                 (match_operand:DI 2 "register_operand" "")))
542    (set (match_operand:SI 0 "register_operand" "")
543         (eq:DI (match_dup 3) (const_int 0)))]
544   "TARGET_ARCH64"
545   "{ operands[3] = gen_reg_rtx (DImode); }")
546
547 (define_expand "snedi_special_trunc"
548   [(set (match_dup 3)
549         (xor:DI (match_operand:DI 1 "register_operand" "")
550                 (match_operand:DI 2 "register_operand" "")))
551    (set (match_operand:SI 0 "register_operand" "")
552         (ne:DI (match_dup 3) (const_int 0)))]
553   "TARGET_ARCH64"
554   "{ operands[3] = gen_reg_rtx (DImode); }")
555
556 (define_expand "seqsi_special_extend"
557   [(set (match_dup 3)
558         (xor:SI (match_operand:SI 1 "register_operand" "")
559                 (match_operand:SI 2 "register_operand" "")))
560    (parallel [(set (match_operand:DI 0 "register_operand" "")
561                    (eq:SI (match_dup 3) (const_int 0)))
562               (clobber (reg:CC 100))])]
563   "TARGET_ARCH64"
564   "{ operands[3] = gen_reg_rtx (SImode); }")
565
566 (define_expand "snesi_special_extend"
567   [(set (match_dup 3)
568         (xor:SI (match_operand:SI 1 "register_operand" "")
569                 (match_operand:SI 2 "register_operand" "")))
570    (parallel [(set (match_operand:DI 0 "register_operand" "")
571                    (ne:SI (match_dup 3) (const_int 0)))
572               (clobber (reg:CC 100))])]
573   "TARGET_ARCH64"
574   "{ operands[3] = gen_reg_rtx (SImode); }")
575
576 ;; ??? v9: Operand 0 needs a mode, so SImode was chosen.
577 ;; However, the code handles both SImode and DImode.
578 (define_expand "seq"
579   [(set (match_operand:SI 0 "intreg_operand" "")
580         (eq:SI (match_dup 1) (const_int 0)))]
581   "! TARGET_LIVE_G0"
582   "
583 {
584   if (GET_MODE (sparc_compare_op0) == SImode)
585     {
586       rtx pat;
587
588       if (GET_MODE (operands[0]) == SImode)
589         pat = gen_seqsi_special (operands[0], sparc_compare_op0,
590                                  sparc_compare_op1);
591       else if (! TARGET_ARCH64)
592         FAIL;
593       else
594         pat = gen_seqsi_special_extend (operands[0], sparc_compare_op0,
595                                         sparc_compare_op1);
596       emit_insn (pat);
597       DONE;
598     }
599   else if (GET_MODE (sparc_compare_op0) == DImode)
600     {
601       rtx pat;
602
603       if (! TARGET_ARCH64)
604         FAIL;
605       else if (GET_MODE (operands[0]) == SImode)
606         pat = gen_seqdi_special_trunc (operands[0], sparc_compare_op0,
607                                        sparc_compare_op1);
608       else
609         pat = gen_seqdi_special (operands[0], sparc_compare_op0,
610                                  sparc_compare_op1);
611       emit_insn (pat);
612       DONE;
613     }
614   else if (GET_MODE (sparc_compare_op0) == TFmode && ! TARGET_HARD_QUAD)
615     {
616       emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, EQ);
617       emit_insn (gen_sne (operands[0]));
618       DONE;
619     }      
620   else if (TARGET_V9)
621     {
622       if (gen_v9_scc (EQ, operands))
623         DONE;
624       /* fall through */
625     }
626   operands[1] = gen_compare_reg (EQ, sparc_compare_op0, sparc_compare_op1);
627 }")
628
629 ;; ??? v9: Operand 0 needs a mode, so SImode was chosen.
630 ;; However, the code handles both SImode and DImode.
631 (define_expand "sne"
632   [(set (match_operand:SI 0 "intreg_operand" "")
633         (ne:SI (match_dup 1) (const_int 0)))]
634   "! TARGET_LIVE_G0"
635   "
636 {
637   if (GET_MODE (sparc_compare_op0) == SImode)
638     {
639       rtx pat;
640
641       if (GET_MODE (operands[0]) == SImode)
642         pat = gen_snesi_special (operands[0], sparc_compare_op0,
643                                  sparc_compare_op1);
644       else if (! TARGET_ARCH64)
645         FAIL;
646       else
647         pat = gen_snesi_special_extend (operands[0], sparc_compare_op0,
648                                         sparc_compare_op1);
649       emit_insn (pat);
650       DONE;
651     }
652   else if (GET_MODE (sparc_compare_op0) == DImode)
653     {
654       rtx pat;
655
656       if (! TARGET_ARCH64)
657         FAIL;
658       else if (GET_MODE (operands[0]) == SImode)
659         pat = gen_snedi_special_trunc (operands[0], sparc_compare_op0,
660                                        sparc_compare_op1);
661       else
662         pat = gen_snedi_special (operands[0], sparc_compare_op0,
663                                  sparc_compare_op1);
664       emit_insn (pat);
665       DONE;
666     }
667   else if (GET_MODE (sparc_compare_op0) == TFmode && ! TARGET_HARD_QUAD)
668     {
669       emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, NE);
670       emit_insn (gen_sne (operands[0]));
671       DONE;
672     }      
673   else if (TARGET_V9)
674     {
675       if (gen_v9_scc (NE, operands))
676         DONE;
677       /* fall through */
678     }
679   operands[1] = gen_compare_reg (NE, sparc_compare_op0, sparc_compare_op1);
680 }")
681
682 (define_expand "sgt"
683   [(set (match_operand:SI 0 "intreg_operand" "")
684         (gt:SI (match_dup 1) (const_int 0)))]
685   "! TARGET_LIVE_G0"
686   "
687 {
688   if (GET_MODE (sparc_compare_op0) == TFmode && ! TARGET_HARD_QUAD)
689     {
690       emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, GT);
691       emit_insn (gen_sne (operands[0]));
692       DONE;
693     }
694   else if (TARGET_V9)
695     {
696       if (gen_v9_scc (GT, operands))
697         DONE;
698       /* fall through */
699     }
700   operands[1] = gen_compare_reg (GT, sparc_compare_op0, sparc_compare_op1);
701 }")
702
703 (define_expand "slt"
704   [(set (match_operand:SI 0 "intreg_operand" "")
705         (lt:SI (match_dup 1) (const_int 0)))]
706   "! TARGET_LIVE_G0"
707   "
708 {
709   if (GET_MODE (sparc_compare_op0) == TFmode && ! TARGET_HARD_QUAD)
710     {
711       emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, LT);
712       emit_insn (gen_sne (operands[0]));
713       DONE;
714     }
715   else if (TARGET_V9)
716     {
717       if (gen_v9_scc (LT, operands))
718         DONE;
719       /* fall through */
720     }
721   operands[1] = gen_compare_reg (LT, sparc_compare_op0, sparc_compare_op1);
722 }")
723
724 (define_expand "sge"
725   [(set (match_operand:SI 0 "intreg_operand" "")
726         (ge:SI (match_dup 1) (const_int 0)))]
727   "! TARGET_LIVE_G0"
728   "
729 {
730   if (GET_MODE (sparc_compare_op0) == TFmode && ! TARGET_HARD_QUAD)
731     {
732       emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, GE);
733       emit_insn (gen_sne (operands[0]));
734       DONE;
735     }
736   else if (TARGET_V9)
737     {
738       if (gen_v9_scc (GE, operands))
739         DONE;
740       /* fall through */
741     }
742   operands[1] = gen_compare_reg (GE, sparc_compare_op0, sparc_compare_op1);
743 }")
744
745 (define_expand "sle"
746   [(set (match_operand:SI 0 "intreg_operand" "")
747         (le:SI (match_dup 1) (const_int 0)))]
748   "! TARGET_LIVE_G0"
749   "
750 {
751   if (GET_MODE (sparc_compare_op0) == TFmode && ! TARGET_HARD_QUAD)
752     {
753       emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, LE);
754       emit_insn (gen_sne (operands[0]));
755       DONE;
756     }
757   else if (TARGET_V9)
758     {
759       if (gen_v9_scc (LE, operands))
760         DONE;
761       /* fall through */
762     }
763   operands[1] = gen_compare_reg (LE, sparc_compare_op0, sparc_compare_op1);
764 }")
765
766 (define_expand "sgtu"
767   [(set (match_operand:SI 0 "intreg_operand" "")
768         (gtu:SI (match_dup 1) (const_int 0)))]
769   "! TARGET_LIVE_G0"
770   "
771 {
772   if (! TARGET_V9)
773     {
774       rtx tem;
775
776       /* We can do ltu easily, so if both operands are registers, swap them and
777          do a LTU.  */
778       if ((GET_CODE (sparc_compare_op0) == REG
779            || GET_CODE (sparc_compare_op0) == SUBREG)
780           && (GET_CODE (sparc_compare_op1) == REG
781               || GET_CODE (sparc_compare_op1) == SUBREG))
782         {
783           tem = sparc_compare_op0;
784           sparc_compare_op0 = sparc_compare_op1;
785           sparc_compare_op1 = tem;
786           emit_insn (gen_sltu (operands[0]));
787           DONE;
788         }
789     }
790   else
791     {
792       if (gen_v9_scc (GTU, operands))
793         DONE;
794     }
795   operands[1] = gen_compare_reg (GTU, sparc_compare_op0, sparc_compare_op1);
796 }")
797
798 (define_expand "sltu"
799   [(set (match_operand:SI 0 "intreg_operand" "")
800         (ltu:SI (match_dup 1) (const_int 0)))]
801   "! TARGET_LIVE_G0"
802   "
803 {
804   if (TARGET_V9)
805     {
806       if (gen_v9_scc (LTU, operands))
807         DONE;
808     }
809   operands[1] = gen_compare_reg (LTU, sparc_compare_op0, sparc_compare_op1);
810 }")
811
812 (define_expand "sgeu"
813   [(set (match_operand:SI 0 "intreg_operand" "")
814         (geu:SI (match_dup 1) (const_int 0)))]
815   "! TARGET_LIVE_G0"
816   "
817 {
818   if (TARGET_V9)
819     {
820       if (gen_v9_scc (GEU, operands))
821         DONE;
822     }
823   operands[1] = gen_compare_reg (GEU, sparc_compare_op0, sparc_compare_op1);
824 }")
825
826 (define_expand "sleu"
827   [(set (match_operand:SI 0 "intreg_operand" "")
828         (leu:SI (match_dup 1) (const_int 0)))]
829   "! TARGET_LIVE_G0"
830   "
831 {
832   if (! TARGET_V9)
833     {
834       rtx tem;
835
836       /* We can do geu easily, so if both operands are registers, swap them and
837          do a GEU.  */
838       if ((GET_CODE (sparc_compare_op0) == REG
839            || GET_CODE (sparc_compare_op0) == SUBREG)
840           && (GET_CODE (sparc_compare_op1) == REG
841               || GET_CODE (sparc_compare_op1) == SUBREG))
842         {
843           tem = sparc_compare_op0;
844           sparc_compare_op0 = sparc_compare_op1;
845           sparc_compare_op1 = tem;
846           emit_insn (gen_sgeu (operands[0]));
847           DONE;
848         }
849     }
850   else
851     {
852       if (gen_v9_scc (LEU, operands))
853         DONE;
854     }
855   operands[1] = gen_compare_reg (LEU, sparc_compare_op0, sparc_compare_op1);
856 }")
857
858 ;; Now the DEFINE_INSNs for the scc cases.
859
860 ;; The SEQ and SNE patterns are special because they can be done
861 ;; without any branching and do not involve a COMPARE.
862
863 (define_insn "*snesi_zero"
864   [(set (match_operand:SI 0 "register_operand" "=r")
865         (ne:SI (match_operand:SI 1 "register_operand" "r")
866                (const_int 0)))
867    (clobber (reg:CC 100))]
868   "! TARGET_LIVE_G0"
869   "subcc %%g0,%1,%%g0\;addx %%g0,0,%0"
870   [(set_attr "type" "unary")
871    (set_attr "length" "2")])
872
873 (define_insn "*neg_snesi_zero"
874   [(set (match_operand:SI 0 "register_operand" "=r")
875         (neg:SI (ne:SI (match_operand:SI 1 "register_operand" "r")
876                        (const_int 0))))
877    (clobber (reg:CC 100))]
878   "! TARGET_LIVE_G0"
879   "subcc %%g0,%1,%%g0\;subx %%g0,0,%0"
880   [(set_attr "type" "unary")
881    (set_attr "length" "2")])
882
883 (define_insn "*snesi_zero_extend"
884   [(set (match_operand:DI 0 "register_operand" "=r")
885         (ne:SI (match_operand:SI 1 "register_operand" "r")
886                (const_int 0)))
887    (clobber (reg:CC 100))]
888   "TARGET_ARCH64"
889   "subcc %%g0,%1,%%g0\;addx %%g0,0,%0"
890   [(set_attr "type" "unary")
891    (set_attr "length" "2")])
892
893 (define_insn "*snedi_zero"
894   [(set (match_operand:DI 0 "register_operand" "=&r")
895         (ne:DI (match_operand:DI 1 "register_operand" "r")
896                (const_int 0)))]
897   "TARGET_ARCH64"
898   "mov 0,%0\;movrnz %1,1,%0"
899   [(set_attr "type" "unary")
900    (set_attr "length" "2")])
901
902 (define_insn "*neg_snedi_zero"
903   [(set (match_operand:DI 0 "register_operand" "=&r")
904         (neg:DI (ne:DI (match_operand:DI 1 "register_operand" "r")
905                        (const_int 0))))]
906   "TARGET_ARCH64"
907   "mov 0,%0\;movrnz %1,-1,%0"
908   [(set_attr "type" "unary")
909    (set_attr "length" "2")])
910
911 (define_insn "*snedi_zero_trunc"
912   [(set (match_operand:SI 0 "register_operand" "=&r")
913         (ne:DI (match_operand:DI 1 "register_operand" "r")
914                (const_int 0)))]
915   "TARGET_ARCH64"
916   "mov 0,%0\;movrnz %1,1,%0"
917   [(set_attr "type" "unary")
918    (set_attr "length" "2")])
919
920 (define_insn "*seqsi_zero"
921   [(set (match_operand:SI 0 "register_operand" "=r")
922         (eq:SI (match_operand:SI 1 "register_operand" "r")
923                (const_int 0)))
924    (clobber (reg:CC 100))]
925   "! TARGET_LIVE_G0"
926   "subcc %%g0,%1,%%g0\;subx %%g0,-1,%0"
927   [(set_attr "type" "unary")
928    (set_attr "length" "2")])
929
930 (define_insn "*neg_seqsi_zero"
931   [(set (match_operand:SI 0 "register_operand" "=r")
932         (neg:SI (eq:SI (match_operand:SI 1 "register_operand" "r")
933                        (const_int 0))))
934    (clobber (reg:CC 100))]
935   "! TARGET_LIVE_G0"
936   "subcc %%g0,%1,%%g0\;addx %%g0,-1,%0"
937   [(set_attr "type" "unary")
938    (set_attr "length" "2")])
939
940 (define_insn "*seqsi_zero_extend"
941   [(set (match_operand:DI 0 "register_operand" "=r")
942         (eq:SI (match_operand:SI 1 "register_operand" "r")
943                (const_int 0)))
944    (clobber (reg:CC 100))]
945   "TARGET_ARCH64"
946   "subcc %%g0,%1,%%g0\;subx %%g0,-1,%0"
947   [(set_attr "type" "unary")
948    (set_attr "length" "2")])
949
950 (define_insn "*seqdi_zero"
951   [(set (match_operand:DI 0 "register_operand" "=&r")
952         (eq:DI (match_operand:DI 1 "register_operand" "r")
953                (const_int 0)))]
954   "TARGET_ARCH64"
955   "mov 0,%0\;movrz %1,1,%0"
956   [(set_attr "type" "unary")
957    (set_attr "length" "2")])
958
959 (define_insn "*neg_seqdi_zero"
960   [(set (match_operand:DI 0 "register_operand" "=&r")
961         (neg:DI (eq:DI (match_operand:DI 1 "register_operand" "r")
962                        (const_int 0))))]
963   "TARGET_ARCH64"
964   "mov 0,%0\;movrz %1,-1,%0"
965   [(set_attr "type" "unary")
966    (set_attr "length" "2")]) 
967
968 (define_insn "*seqdi_zero_trunc"
969   [(set (match_operand:SI 0 "register_operand" "=&r")
970         (eq:DI (match_operand:DI 1 "register_operand" "r")
971                (const_int 0)))]
972   "TARGET_ARCH64"
973   "mov 0,%0\;movrz %1,1,%0"
974   [(set_attr "type" "unary")
975    (set_attr "length" "2")])
976
977 ;; We can also do (x + (i == 0)) and related, so put them in.
978 ;; ??? The addx/subx insns use the 32 bit carry flag so there are no DImode
979 ;; versions for v9.
980
981 (define_insn "*x_plus_i_ne_0"
982   [(set (match_operand:SI 0 "register_operand" "=r")
983         (plus:SI (ne:SI (match_operand:SI 1 "register_operand" "r")
984                         (const_int 0))
985                  (match_operand:SI 2 "register_operand" "r")))
986    (clobber (reg:CC 100))]
987   "! TARGET_LIVE_G0"
988   "subcc %%g0,%1,%%g0\;addx %2,0,%0"
989   [(set_attr "length" "2")])
990
991 (define_insn "*x_minus_i_ne_0"
992   [(set (match_operand:SI 0 "register_operand" "=r")
993         (minus:SI (match_operand:SI 2 "register_operand" "r")
994                   (ne:SI (match_operand:SI 1 "register_operand" "r")
995                          (const_int 0))))
996    (clobber (reg:CC 100))]
997   "! TARGET_LIVE_G0"
998   "subcc %%g0,%1,%%g0\;subx %2,0,%0"
999   [(set_attr "length" "2")])
1000
1001 (define_insn "*x_plus_i_eq_0"
1002   [(set (match_operand:SI 0 "register_operand" "=r")
1003         (plus:SI (eq:SI (match_operand:SI 1 "register_operand" "r")
1004                         (const_int 0))
1005                  (match_operand:SI 2 "register_operand" "r")))
1006    (clobber (reg:CC 100))]
1007   "! TARGET_LIVE_G0"
1008   "subcc %%g0,%1,%%g0\;subx %2,-1,%0"
1009   [(set_attr "length" "2")])
1010
1011 (define_insn "*x_minus_i_eq_0"
1012   [(set (match_operand:SI 0 "register_operand" "=r")
1013         (minus:SI (match_operand:SI 2 "register_operand" "r")
1014                   (eq:SI (match_operand:SI 1 "register_operand" "r")
1015                          (const_int 0))))
1016    (clobber (reg:CC 100))]
1017   "! TARGET_LIVE_G0"
1018   "subcc %%g0,%1,%%g0\;addx %2,-1,%0"
1019   [(set_attr "length" "2")])
1020
1021 ;; We can also do GEU and LTU directly, but these operate after a compare.
1022 ;; ??? The addx/subx insns use the 32 bit carry flag so there are no DImode
1023 ;; versions for v9.
1024
1025 (define_insn "*sltu_insn"
1026   [(set (match_operand:SI 0 "register_operand" "=r")
1027         (ltu:SI (reg:CC 100) (const_int 0)))]
1028   "! TARGET_LIVE_G0"
1029   "addx %%g0,0,%0"
1030   [(set_attr "type" "misc")])
1031
1032 (define_insn "*neg_sltu_insn"
1033   [(set (match_operand:SI 0 "register_operand" "=r")
1034         (neg:SI (ltu:SI (reg:CC 100) (const_int 0))))]
1035   "! TARGET_LIVE_G0"
1036   "subx %%g0,0,%0"
1037   [(set_attr "type" "misc")])
1038
1039 ;; ??? Combine should canonicalize these next two to the same pattern.
1040 (define_insn "*neg_sltu_minus_x"
1041   [(set (match_operand:SI 0 "register_operand" "=r")
1042         (minus:SI (neg:SI (ltu:SI (reg:CC 100) (const_int 0)))
1043                   (match_operand:SI 1 "arith_operand" "rI")))]
1044   "! TARGET_LIVE_G0"
1045   "subx %%g0,%1,%0"
1046   [(set_attr "type" "unary")])
1047
1048 (define_insn "*neg_sltu_plus_x"
1049   [(set (match_operand:SI 0 "register_operand" "=r")
1050         (neg:SI (plus:SI (ltu:SI (reg:CC 100) (const_int 0))
1051                          (match_operand:SI 1 "arith_operand" "rI"))))]
1052   "! TARGET_LIVE_G0"
1053   "subx %%g0,%1,%0"
1054   [(set_attr "type" "unary")])
1055
1056 (define_insn "*sgeu_insn"
1057   [(set (match_operand:SI 0 "register_operand" "=r")
1058         (geu:SI (reg:CC 100) (const_int 0)))]
1059   "! TARGET_LIVE_G0"
1060   "subx %%g0,-1,%0"
1061   [(set_attr "type" "misc")])
1062
1063 (define_insn "*neg_sgeu_insn"
1064   [(set (match_operand:SI 0 "register_operand" "=r")
1065         (neg:SI (geu:SI (reg:CC 100) (const_int 0))))]
1066   "! TARGET_LIVE_G0"
1067   "addx %%g0,-1,%0"
1068   [(set_attr "type" "misc")])
1069
1070 ;; We can also do (x + ((unsigned) i >= 0)) and related, so put them in.
1071 ;; ??? The addx/subx insns use the 32 bit carry flag so there are no DImode
1072 ;; versions for v9.
1073
1074 (define_insn "*sltu_plus_x"
1075   [(set (match_operand:SI 0 "register_operand" "=r")
1076         (plus:SI (ltu:SI (reg:CC 100) (const_int 0))
1077                  (match_operand:SI 1 "arith_operand" "rI")))]
1078   "! TARGET_LIVE_G0"
1079   "addx %%g0,%1,%0"
1080   [(set_attr "type" "unary")])
1081
1082 (define_insn "*sltu_plus_x_plus_y"
1083   [(set (match_operand:SI 0 "register_operand" "=r")
1084         (plus:SI (ltu:SI (reg:CC 100) (const_int 0))
1085                  (plus:SI (match_operand:SI 1 "arith_operand" "%r")
1086                           (match_operand:SI 2 "arith_operand" "rI"))))]
1087   ""
1088   "addx %1,%2,%0")
1089
1090 (define_insn "*x_minus_sltu"
1091   [(set (match_operand:SI 0 "register_operand" "=r")
1092         (minus:SI (match_operand:SI 1 "register_operand" "r")
1093                   (ltu:SI (reg:CC 100) (const_int 0))))]
1094   ""
1095   "subx %1,0,%0"
1096   [(set_attr "type" "unary")])
1097
1098 ;; ??? Combine should canonicalize these next two to the same pattern.
1099 (define_insn "*x_minus_y_minus_sltu"
1100   [(set (match_operand:SI 0 "register_operand" "=r")
1101         (minus:SI (minus:SI (match_operand:SI 1 "register_operand" "r")
1102                             (match_operand:SI 2 "arith_operand" "rI"))
1103                   (ltu:SI (reg:CC 100) (const_int 0))))]
1104   ""
1105   "subx %1,%2,%0")
1106
1107 (define_insn "*x_minus_sltu_plus_y"
1108   [(set (match_operand:SI 0 "register_operand" "=r")
1109         (minus:SI (match_operand:SI 1 "register_operand" "r")
1110                   (plus:SI (ltu:SI (reg:CC 100) (const_int 0))
1111                            (match_operand:SI 2 "arith_operand" "rI"))))]
1112   ""
1113   "subx %1,%2,%0")
1114
1115 (define_insn "*sgeu_plus_x"
1116   [(set (match_operand:SI 0 "register_operand" "=r")
1117         (plus:SI (geu:SI (reg:CC 100) (const_int 0))
1118                  (match_operand:SI 1 "register_operand" "r")))]
1119   ""
1120   "subx %1,-1,%0"
1121   [(set_attr "type" "unary")])
1122
1123 (define_insn "*x_minus_sgeu"
1124   [(set (match_operand:SI 0 "register_operand" "=r")
1125         (minus:SI (match_operand:SI 1 "register_operand" "r")
1126                   (geu:SI (reg:CC 100) (const_int 0))))]
1127   ""
1128   "addx %1,-1,%0"
1129   [(set_attr "type" "unary")])
1130
1131 ;; Now we have the generic scc insns.
1132 ;; !v9: These will be done using a jump.
1133 ;; v9: Use conditional moves which are defined elsewhere.
1134 ;; We have to exclude the cases above, since we will not want combine to
1135 ;; turn something that does not require a jump into something that does.
1136
1137 (define_insn "*scc_si"
1138   [(set (match_operand:SI 0 "register_operand" "=r")
1139         (match_operator:SI 2 "noov_compare_op"
1140                            [(match_operand 1 "icc_or_fcc_reg_operand" "")
1141                             (const_int 0)]))]
1142   ""
1143   "* return output_scc_insn (operands, insn); "
1144   [(set_attr "type" "multi")
1145    (set_attr "length" "3")])
1146
1147 (define_insn "*scc_di"
1148   [(set (match_operand:DI 0 "register_operand" "=r")
1149         (match_operator:DI 2 "noov_compare_op"
1150                            [(match_operand 1 "icc_or_fcc_reg_operand" "")
1151                             (const_int 0)]))]
1152   "TARGET_ARCH64"
1153   "* return output_scc_insn (operands, insn); "
1154   [(set_attr "type" "multi")
1155    (set_attr "length" "3")])
1156 \f
1157 ;; These control RTL generation for conditional jump insns
1158
1159 ;; The quad-word fp compare library routines all return nonzero to indicate
1160 ;; true, which is different from the equivalent libgcc routines, so we must
1161 ;; handle them specially here.
1162
1163 (define_expand "beq"
1164   [(set (pc)
1165         (if_then_else (eq (match_dup 1) (const_int 0))
1166                       (label_ref (match_operand 0 "" ""))
1167                       (pc)))]
1168   ""
1169   "
1170 {
1171   if (TARGET_ARCH64 && sparc_compare_op1 == const0_rtx
1172       && GET_CODE (sparc_compare_op0) == REG
1173       && GET_MODE (sparc_compare_op0) == DImode)
1174     {
1175       emit_v9_brxx_insn (EQ, sparc_compare_op0, operands[0]);
1176       DONE;
1177     }
1178   else if (GET_MODE (sparc_compare_op0) == TFmode && ! TARGET_HARD_QUAD)
1179     {
1180       emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, EQ);
1181       emit_jump_insn (gen_bne (operands[0]));
1182       DONE;
1183     }      
1184   operands[1] = gen_compare_reg (EQ, sparc_compare_op0, sparc_compare_op1);
1185 }")
1186
1187 (define_expand "bne"
1188   [(set (pc)
1189         (if_then_else (ne (match_dup 1) (const_int 0))
1190                       (label_ref (match_operand 0 "" ""))
1191                       (pc)))]
1192   ""
1193   "
1194 {
1195   if (TARGET_ARCH64 && sparc_compare_op1 == const0_rtx
1196       && GET_CODE (sparc_compare_op0) == REG
1197       && GET_MODE (sparc_compare_op0) == DImode)
1198     {
1199       emit_v9_brxx_insn (NE, sparc_compare_op0, operands[0]);
1200       DONE;
1201     }
1202   else if (GET_MODE (sparc_compare_op0) == TFmode && ! TARGET_HARD_QUAD)
1203     {
1204       emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, NE);
1205       emit_jump_insn (gen_bne (operands[0]));
1206       DONE;
1207     }      
1208   operands[1] = gen_compare_reg (NE, sparc_compare_op0, sparc_compare_op1);
1209 }")
1210
1211 (define_expand "bgt"
1212   [(set (pc)
1213         (if_then_else (gt (match_dup 1) (const_int 0))
1214                       (label_ref (match_operand 0 "" ""))
1215                       (pc)))]
1216   ""
1217   "
1218 {
1219   if (TARGET_ARCH64 && sparc_compare_op1 == const0_rtx
1220       && GET_CODE (sparc_compare_op0) == REG
1221       && GET_MODE (sparc_compare_op0) == DImode)
1222     {
1223       emit_v9_brxx_insn (GT, sparc_compare_op0, operands[0]);
1224       DONE;
1225     }
1226   else if (GET_MODE (sparc_compare_op0) == TFmode && ! TARGET_HARD_QUAD)
1227     {
1228       emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, GT);
1229       emit_jump_insn (gen_bne (operands[0]));
1230       DONE;
1231     }      
1232   operands[1] = gen_compare_reg (GT, sparc_compare_op0, sparc_compare_op1);
1233 }")
1234
1235 (define_expand "bgtu"
1236   [(set (pc)
1237         (if_then_else (gtu (match_dup 1) (const_int 0))
1238                       (label_ref (match_operand 0 "" ""))
1239                       (pc)))]
1240   ""
1241   "
1242 { operands[1] = gen_compare_reg (GTU, sparc_compare_op0, sparc_compare_op1);
1243 }")
1244
1245 (define_expand "blt"
1246   [(set (pc)
1247         (if_then_else (lt (match_dup 1) (const_int 0))
1248                       (label_ref (match_operand 0 "" ""))
1249                       (pc)))]
1250   ""
1251   "
1252 {
1253   if (TARGET_ARCH64 && sparc_compare_op1 == const0_rtx
1254       && GET_CODE (sparc_compare_op0) == REG
1255       && GET_MODE (sparc_compare_op0) == DImode)
1256     {
1257       emit_v9_brxx_insn (LT, sparc_compare_op0, operands[0]);
1258       DONE;
1259     }
1260   else if (GET_MODE (sparc_compare_op0) == TFmode && ! TARGET_HARD_QUAD)
1261     {
1262       emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, LT);
1263       emit_jump_insn (gen_bne (operands[0]));
1264       DONE;
1265     }      
1266   operands[1] = gen_compare_reg (LT, sparc_compare_op0, sparc_compare_op1);
1267 }")
1268
1269 (define_expand "bltu"
1270   [(set (pc)
1271         (if_then_else (ltu (match_dup 1) (const_int 0))
1272                       (label_ref (match_operand 0 "" ""))
1273                       (pc)))]
1274   ""
1275   "
1276 { operands[1] = gen_compare_reg (LTU, sparc_compare_op0, sparc_compare_op1);
1277 }")
1278
1279 (define_expand "bge"
1280   [(set (pc)
1281         (if_then_else (ge (match_dup 1) (const_int 0))
1282                       (label_ref (match_operand 0 "" ""))
1283                       (pc)))]
1284   ""
1285   "
1286 {
1287   if (TARGET_ARCH64 && sparc_compare_op1 == const0_rtx
1288       && GET_CODE (sparc_compare_op0) == REG
1289       && GET_MODE (sparc_compare_op0) == DImode)
1290     {
1291       emit_v9_brxx_insn (GE, sparc_compare_op0, operands[0]);
1292       DONE;
1293     }
1294   else if (GET_MODE (sparc_compare_op0) == TFmode && ! TARGET_HARD_QUAD)
1295     {
1296       emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, GE);
1297       emit_jump_insn (gen_bne (operands[0]));
1298       DONE;
1299     }      
1300   operands[1] = gen_compare_reg (GE, sparc_compare_op0, sparc_compare_op1);
1301 }")
1302
1303 (define_expand "bgeu"
1304   [(set (pc)
1305         (if_then_else (geu (match_dup 1) (const_int 0))
1306                       (label_ref (match_operand 0 "" ""))
1307                       (pc)))]
1308   ""
1309   "
1310 { operands[1] = gen_compare_reg (GEU, sparc_compare_op0, sparc_compare_op1);
1311 }")
1312
1313 (define_expand "ble"
1314   [(set (pc)
1315         (if_then_else (le (match_dup 1) (const_int 0))
1316                       (label_ref (match_operand 0 "" ""))
1317                       (pc)))]
1318   ""
1319   "
1320 {
1321   if (TARGET_ARCH64 && sparc_compare_op1 == const0_rtx
1322       && GET_CODE (sparc_compare_op0) == REG
1323       && GET_MODE (sparc_compare_op0) == DImode)
1324     {
1325       emit_v9_brxx_insn (LE, sparc_compare_op0, operands[0]);
1326       DONE;
1327     }
1328   else if (GET_MODE (sparc_compare_op0) == TFmode && ! TARGET_HARD_QUAD)
1329     {
1330       emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, LE);
1331       emit_jump_insn (gen_bne (operands[0]));
1332       DONE;
1333     }      
1334   operands[1] = gen_compare_reg (LE, sparc_compare_op0, sparc_compare_op1);
1335 }")
1336
1337 (define_expand "bleu"
1338   [(set (pc)
1339         (if_then_else (leu (match_dup 1) (const_int 0))
1340                       (label_ref (match_operand 0 "" ""))
1341                       (pc)))]
1342   ""
1343   "
1344 { operands[1] = gen_compare_reg (LEU, sparc_compare_op0, sparc_compare_op1);
1345 }")
1346 \f
1347 ;; Now match both normal and inverted jump.
1348
1349 (define_insn "*normal_branch"
1350   [(set (pc)
1351         (if_then_else (match_operator 0 "noov_compare_op"
1352                                       [(reg 100) (const_int 0)])
1353                       (label_ref (match_operand 1 "" ""))
1354                       (pc)))]
1355   ""
1356   "*
1357 {
1358   return output_cbranch (operands[0], 1, 0,
1359                          final_sequence && INSN_ANNULLED_BRANCH_P (insn),
1360                          ! final_sequence);
1361 }"
1362   [(set_attr "type" "branch")])
1363
1364 (define_insn "*inverted_branch"
1365   [(set (pc)
1366         (if_then_else (match_operator 0 "noov_compare_op"
1367                                       [(reg 100) (const_int 0)])
1368                       (pc)
1369                       (label_ref (match_operand 1 "" ""))))]
1370   ""
1371   "*
1372 {
1373   return output_cbranch (operands[0], 1, 1,
1374                          final_sequence && INSN_ANNULLED_BRANCH_P (insn),
1375                          ! final_sequence);
1376 }"
1377   [(set_attr "type" "branch")])
1378
1379 (define_insn "*normal_fp_branch"
1380   [(set (pc)
1381         (if_then_else (match_operator 1 "comparison_operator"
1382                                       [(match_operand:CCFP 0 "fcc_reg_operand" "c")
1383                                        (const_int 0)])
1384                       (label_ref (match_operand 2 "" ""))
1385                       (pc)))]
1386   ""
1387   "*
1388 {
1389   return output_cbranch (operands[1], 2, 0,
1390                          final_sequence && INSN_ANNULLED_BRANCH_P (insn),
1391                          ! final_sequence);
1392 }"
1393   [(set_attr "type" "branch")])
1394
1395 (define_insn "*inverted_fp_branch"
1396   [(set (pc)
1397         (if_then_else (match_operator 1 "comparison_operator"
1398                                       [(match_operand:CCFP 0 "fcc_reg_operand" "c")
1399                                        (const_int 0)])
1400                       (pc)
1401                       (label_ref (match_operand 2 "" ""))))]
1402   ""
1403   "*
1404 {
1405   return output_cbranch (operands[1], 2, 1,
1406                          final_sequence && INSN_ANNULLED_BRANCH_P (insn),
1407                          ! final_sequence);
1408 }"
1409   [(set_attr "type" "branch")])
1410
1411 (define_insn "*normal_fpe_branch"
1412   [(set (pc)
1413         (if_then_else (match_operator 1 "comparison_operator"
1414                                       [(match_operand:CCFPE 0 "fcc_reg_operand" "c")
1415                                        (const_int 0)])
1416                       (label_ref (match_operand 2 "" ""))
1417                       (pc)))]
1418   ""
1419   "*
1420 {
1421   return output_cbranch (operands[1], 2, 0,
1422                          final_sequence && INSN_ANNULLED_BRANCH_P (insn),
1423                          ! final_sequence);
1424 }"
1425   [(set_attr "type" "branch")])
1426
1427 (define_insn "*inverted_fpe_branch"
1428   [(set (pc)
1429         (if_then_else (match_operator 1 "comparison_operator"
1430                                       [(match_operand:CCFPE 0 "fcc_reg_operand" "c")
1431                                        (const_int 0)])
1432                       (pc)
1433                       (label_ref (match_operand 2 "" ""))))]
1434   ""
1435   "*
1436 {
1437   return output_cbranch (operands[1], 2, 1,
1438                          final_sequence && INSN_ANNULLED_BRANCH_P (insn),
1439                          ! final_sequence);
1440 }"
1441   [(set_attr "type" "branch")])
1442
1443 ;; Sparc V9-specific jump insns.  None of these are guaranteed to be
1444 ;; in the architecture.
1445
1446 ;; There are no 32 bit brreg insns.
1447
1448 (define_insn "*normal_int_branch_sp64"
1449   [(set (pc)
1450         (if_then_else (match_operator 0 "v9_regcmp_op"
1451                                       [(match_operand:DI 1 "register_operand" "r")
1452                                        (const_int 0)])
1453                       (label_ref (match_operand 2 "" ""))
1454                       (pc)))]
1455   "TARGET_ARCH64"
1456   "*
1457 {
1458   return output_v9branch (operands[0], 1, 2, 0,
1459                           final_sequence && INSN_ANNULLED_BRANCH_P (insn),
1460                           ! final_sequence);
1461 }"
1462   [(set_attr "type" "branch")])
1463
1464 (define_insn "*inverted_int_branch_sp64"
1465   [(set (pc)
1466         (if_then_else (match_operator 0 "v9_regcmp_op"
1467                                       [(match_operand:DI 1 "register_operand" "r")
1468                                        (const_int 0)])
1469                       (pc)
1470                       (label_ref (match_operand 2 "" ""))))]
1471   "TARGET_ARCH64"
1472   "*
1473 {
1474   return output_v9branch (operands[0], 1, 2, 1,
1475                           final_sequence && INSN_ANNULLED_BRANCH_P (insn),
1476                           ! final_sequence);
1477 }"
1478   [(set_attr "type" "branch")])
1479 \f
1480 ;; Esoteric move insns (lo_sum, high, pic).
1481
1482 (define_insn "*lo_sum_si"
1483   [(set (match_operand:SI 0 "register_operand" "=r")
1484         (lo_sum:SI (match_operand:SI 1 "register_operand" "r")
1485                    (match_operand:SI 2 "immediate_operand" "in")))]
1486   ""
1487   ;; V9 needs "add" because of the code models.  We still use "or" for v8
1488   ;; so we can compare the old compiler with the new.
1489   "* return TARGET_ARCH64 ? \"add %1,%%lo(%a2),%0\" : \"or %1,%%lo(%a2),%0\";"
1490   ;; Need to set length for this arith insn because operand2
1491   ;; is not an "arith_operand".
1492   [(set_attr "length" "1")])
1493
1494 ;; For PIC, symbol_refs are put inside unspec so that the optimizer will not
1495 ;; confuse them with real addresses.
1496 (define_insn "pic_lo_sum_si"
1497   [(set (match_operand:SI 0 "register_operand" "=r")
1498         (lo_sum:SI (match_operand:SI 1 "register_operand" "r")
1499                    (unspec:SI [(match_operand:SI 2 "immediate_operand" "in")] 0)))]
1500   "flag_pic"
1501   ;; V9 needs "add" because of the code models.  We still use "or" for v8
1502   ;; so we can compare the old compiler with the new.
1503   "* return TARGET_ARCH64 ? \"add %1,%%lo(%a2),%0\" : \"or %1,%%lo(%a2),%0\";"
1504   ;; Need to set length for this arith insn because operand2
1505   ;; is not an "arith_operand".
1506   [(set_attr "length" "1")])
1507
1508 ;; The PIC version of sethi must appear before the non-pic case so that
1509 ;; the unspec will not be matched as part of the operand.
1510 ;; For PIC, symbol_refs are put inside unspec so that the optimizer will not
1511 ;; confuse them with real addresses.
1512 (define_insn "pic_sethi_si"
1513   [(set (match_operand:SI 0 "register_operand" "=r")
1514         (high:SI (unspec:SI [(match_operand 1 "" "")] 0)))]
1515   "flag_pic && check_pic (1)"
1516   "sethi %%hi(%a1),%0"
1517   [(set_attr "type" "move")
1518    (set_attr "length" "1")])
1519
1520 (define_insn "*sethi_si"
1521   [(set (match_operand:SI 0 "register_operand" "=r")
1522         (high:SI (match_operand 1 "" "")))]
1523   "check_pic (1)"
1524   "sethi %%hi(%a1),%0"
1525   [(set_attr "type" "move")
1526    (set_attr "length" "1")])
1527
1528 (define_insn "*sethi_hi"
1529   [(set (match_operand:HI 0 "register_operand" "=r")
1530         (high:HI (match_operand 1 "" "")))]
1531   "check_pic (1)"
1532   "sethi %%hi(%a1),%0"
1533   [(set_attr "type" "move")
1534    (set_attr "length" "1")])
1535
1536 (define_insn "get_pc_via_call"
1537   [(set (pc) (label_ref (match_operand 0 "" "")))
1538    (set (reg:SI 15) (label_ref (match_operand 1 "" "")))]
1539   ""
1540   "call %l0%#"
1541   [(set_attr "type" "uncond_branch")])
1542
1543 (define_insn "get_pc_via_rdpc"
1544   [(set (match_operand:DI 0 "register_operand" "=r") (pc))]
1545   "TARGET_PTR64"
1546   "rd %%pc,%0"
1547   [(set_attr "type" "move")])
1548
1549 ;; Special pic pattern, for loading the address of a label into a register.
1550 ;; It clobbers o7 because the call puts the return address (i.e. pc value)
1551 ;; there.  The pic tablejump pattern also uses this.
1552
1553 (define_insn "move_pic_label_si"
1554   [(set (match_operand:SI 0 "register_operand" "=r")
1555         ; This was previously (label_ref:SI (match_operand 1 "" "")) but that
1556         ; loses the volatil and other flags of the original label_ref.
1557         (match_operand:SI 1 "label_ref_operand" ""))
1558    (set (reg:SI 15) (pc))]
1559   "flag_pic"
1560   "*
1561 {
1562   if (get_attr_length (insn) == 2)
1563     return \"\\n1:\;call 2f\;add %%o7,%%lo(%l1-1b),%0\\n2:\";
1564   else
1565     return \"\\n1:\;call 2f\;sethi %%hi(%l1-1b),%0\\n2:\\tor %0,%%lo(%l1-1b),%0\;add %0,%%o7,%0\";
1566 }"
1567   [(set_attr "type" "multi")
1568    ; 960 = 4096 bytes / 4 bytes/insn - 64 (for not always perfect length calcs)
1569    (set (attr "length") (if_then_else (ltu (minus (match_dup 1) (pc))
1570                                            (const_int 960))
1571                                       (const_int 2)
1572                                       (const_int 4)))])
1573
1574 ;; Special sparc64 pattern for loading the address of a label into a register.
1575 ;; The pic and non-pic cases are the same since it's the most efficient way.
1576 ;;
1577 ;; ??? The non-pic case doesn't need to use %o7, we could use a scratch
1578 ;; instead.  But the pic case doesn't need to use %o7 either.  We handle them
1579 ;; both here so that when this is fixed, they can both be fixed together.
1580 ;; Don't forget that the pic jump table stuff uses %o7 (that will need to be
1581 ;; changed too).
1582
1583 (define_insn "move_label_di"
1584   [(set (match_operand:DI 0 "register_operand" "=r")
1585         ; This was previously (label_ref:DI (match_operand 1 "" "")) but that
1586         ; loses the volatil and other flags of the original label_ref.
1587         (match_operand:DI 1 "label_ref_operand" ""))
1588    (set (reg:DI 15) (pc))]
1589   "TARGET_ARCH64"
1590   "*
1591 {
1592   if (get_attr_length (insn) == 2)
1593     return \"\\n1:\;rd %%pc,%%o7\;add %%o7,%l1-1b,%0\";
1594   else
1595     return \"\\n1:\;rd %%pc,%%o7\;sethi %%hi(%l1-1b),%0\;add %0,%%lo(%l1-1b),%0\;sra %0,0,%0\;add %0,%%o7,%0\";
1596 }"
1597   [(set_attr "type" "multi")
1598    ; 960 = 4096 bytes / 4 bytes/insn - 64 (for not always perfect length calcs)
1599    (set (attr "length") (if_then_else (ltu (minus (match_dup 1) (pc))
1600                                            (const_int 960))
1601                                       (const_int 2)
1602                                       (const_int 5)))])
1603
1604 (define_insn "*lo_sum_di_sp32"
1605   [(set (match_operand:DI 0 "register_operand" "=r")
1606         (lo_sum:DI (match_operand:DI 1 "register_operand" "0")
1607                    (match_operand:DI 2 "immediate_operand" "in")))]
1608   "! TARGET_ARCH64"
1609   "*
1610 {
1611   /* Don't output a 64 bit constant, since we can't trust the assembler to
1612      handle it correctly.  */
1613   if (GET_CODE (operands[2]) == CONST_DOUBLE)
1614     operands[2] = GEN_INT (CONST_DOUBLE_LOW (operands[2]));
1615   else if (GET_CODE (operands[2]) == CONST_INT
1616            && HOST_BITS_PER_WIDE_INT > 32
1617            && INTVAL (operands[2]) > 0xffffffff)
1618     operands[2] = GEN_INT (INTVAL (operands[2]) & 0xffffffff);
1619
1620   return \"or %L1,%%lo(%a2),%L0\";
1621 }"
1622   ;; Need to set length for this arith insn because operand2
1623   ;; is not an "arith_operand".
1624   [(set_attr "length" "1")])
1625
1626 ;; ??? Optimizer does not handle "or %o1,%lo(0),%o1". How about add?
1627
1628 (define_insn "*lo_sum_di_sp64"
1629   [(set (match_operand:DI 0 "register_operand" "=r")
1630         (lo_sum:DI (match_operand:DI 1 "register_operand" "0")
1631                    (match_operand:DI 2 "immediate_operand" "in")))]
1632   "TARGET_ARCH64"
1633   "*
1634 {
1635   /* Don't output a 64 bit constant, since we can't trust the assembler to
1636      handle it correctly.  */
1637   if (GET_CODE (operands[2]) == CONST_DOUBLE)
1638     operands[2] = GEN_INT (CONST_DOUBLE_LOW (operands[2]));
1639   else if (GET_CODE (operands[2]) == CONST_INT
1640            && HOST_BITS_PER_WIDE_INT > 32
1641            && INTVAL (operands[2]) > 0xffffffff)
1642     operands[2] = GEN_INT (INTVAL (operands[2]) & 0xffffffff);
1643
1644   /* Note that we use add here.  This is important because Medium/Anywhere
1645      code model support depends on it.  */
1646   return \"add %1,%%lo(%a2),%0\";
1647 }"
1648   ;; Need to set length for this arith insn because operand2
1649   ;; is not an "arith_operand".
1650   [(set_attr "length" "1")])
1651
1652 (define_insn "*sethi_di_sp32"
1653   [(set (match_operand:DI 0 "register_operand" "=r")
1654         (high:DI (match_operand 1 "" "")))]
1655   "! TARGET_ARCH64 && check_pic (1)"
1656   "*
1657 {
1658   rtx op0 = operands[0];
1659   rtx op1 = operands[1];
1660
1661   if (GET_CODE (op1) == CONST_INT)
1662     {
1663       operands[0] = operand_subword (op0, 1, 0, DImode);
1664       output_asm_insn (\"sethi %%hi(%a1),%0\", operands);
1665
1666       operands[0] = operand_subword (op0, 0, 0, DImode);
1667       if (INTVAL (op1) < 0)
1668         return \"mov -1,%0\";
1669       else
1670         return \"mov 0,%0\";
1671     }
1672   else if (GET_CODE (op1) == CONST_DOUBLE)
1673     {
1674       operands[0] = operand_subword (op0, 1, 0, DImode);
1675       operands[1] = GEN_INT (CONST_DOUBLE_LOW (op1));
1676       output_asm_insn (\"sethi %%hi(%a1),%0\", operands);
1677
1678       operands[0] = operand_subword (op0, 0, 0, DImode);
1679       operands[1] = GEN_INT (CONST_DOUBLE_HIGH (op1));
1680       return singlemove_string (operands);
1681     }
1682   else
1683     abort ();
1684   return \"\";
1685 }"
1686   [(set_attr "type" "move")
1687    (set_attr "length" "2")])
1688
1689 ;;; ??? This pattern originally clobbered a scratch register.  However, this
1690 ;;; is invalid, the movdi pattern may not use a temp register because it
1691 ;;; may be called from reload to reload a DImode value.  In that case, we
1692 ;;; end up with a scratch register that never gets allocated.  To avoid this,
1693 ;;; we use global register 1 which is never otherwise used by gcc as a temp.
1694 ;;; The correct solution here might be to force DImode constants to memory,
1695 ;;; e.g. by using a toc like the romp and rs6000 ports do for addresses, reg
1696 ;;; 1 will then no longer need to be considered a fixed reg.
1697
1698 (define_expand "sethi_di_sp64"
1699   [(parallel
1700      [(set (match_operand:DI 0 "register_operand" "")
1701            (high:DI (match_operand 1 "general_operand" "")))
1702       (clobber (reg:DI 1))])]
1703   "TARGET_ARCH64"
1704   "")
1705
1706 (define_insn "*sethi_di_sp64_const"
1707   [(set (match_operand:DI 0 "register_operand" "=r")
1708         (high:DI (match_operand 1 "const_double_operand" "")))
1709    (clobber (reg:DI 1))]
1710   "TARGET_ARCH64 && check_pic (1)"
1711   "*
1712 {
1713 #if HOST_BITS_PER_WIDE_INT == 32
1714   rtx high, low;
1715   
1716   split_double (operands[1], &high, &low);
1717
1718   if (high == const0_rtx)
1719     {
1720       operands[1] = low;
1721       output_asm_insn (\"sethi %%hi(%a1),%0\", operands);
1722     }
1723   else
1724     {
1725       operands[1] = high;
1726       output_asm_insn (singlemove_string (operands), operands);
1727
1728       operands[1] = low;
1729       output_asm_insn (\"sllx %0,32,%0\", operands);
1730       if (low != const0_rtx)
1731         output_asm_insn (\"sethi %%hi(%a1),%%g1; or %0,%%g1,%0\", operands);
1732     }
1733 #else
1734   rtx op = operands[1];
1735
1736   if (! SPARC_SETHI_P (INTVAL(op)))
1737     {
1738       operands[1] = GEN_INT (INTVAL (op) >> 32);
1739       output_asm_insn (singlemove_string (operands), operands);
1740
1741       output_asm_insn (\"sllx %0,32,%0\", operands);
1742       if (INTVAL (op) & 0xffffffff)
1743         {
1744           operands[1] = GEN_INT (INTVAL (op) & 0xffffffff);
1745           output_asm_insn (\"sethi %%hi(%a1),%%g1; or %0,%%g1,%0\", operands);
1746         }
1747     }
1748   else
1749     {
1750       output_asm_insn (\"sethi %%hi(%a1),%0\", operands);
1751     }
1752 #endif
1753
1754   return \"\";
1755 }"
1756   [(set_attr "type" "move")
1757    (set_attr "length" "5")])
1758
1759 ;; Most of the required support for the various code models is here.
1760 ;; We can do this because sparcs need the high insn to load the address.  We
1761 ;; just need to get high to do the right thing for each code model.  Then each
1762 ;; uses the same "%X+%lo(...)" in the load/store insn.
1763
1764 ;; When TARGET_MEDLOW, assume that the upper 32 bits of symbol addresses are
1765 ;; always 0.
1766 ;; When TARGET_MEDANY, the text and data segments have a maximum size of 32
1767 ;; bits and may be located anywhere.  MEDANY_BASE_REG contains the start
1768 ;; address of the data segment, currently %g4.
1769 ;; When TARGET_FULLANY, symbolic addresses are 64 bits.
1770
1771 (define_insn "*sethi_di_medlow"
1772   [(set (match_operand:DI 0 "register_operand" "=r")
1773         (high:DI (match_operand 1 "" "")))
1774   ;; The clobber is here because emit_move_sequence assumes the worst case.
1775    (clobber (reg:DI 1))]
1776   "TARGET_MEDLOW && check_pic (1)"
1777   "sethi %%hi(%a1),%0"
1778   [(set_attr "type" "move")
1779    (set_attr "length" "1")])
1780
1781 (define_insn "*sethi_di_medium_pic"
1782   [(set (match_operand:DI 0 "register_operand" "=r")
1783         (high:DI (match_operand 1 "sp64_medium_pic_operand" "")))]
1784   "(TARGET_MEDLOW || TARGET_MEDANY) && check_pic (1)"
1785   "sethi %%hi(%a1),%0"
1786   [(set_attr "type" "move")
1787    (set_attr "length" "1")])
1788
1789 ;; WARNING: %0 gets %hi(%1)+%g4.
1790 ;;          You cannot OR in %lo(%1), it must be added in.
1791
1792 (define_insn "*sethi_di_medany_data"
1793   [(set (match_operand:DI 0 "register_operand" "=r")
1794         (high:DI (match_operand 1 "data_segment_operand" "")))
1795   ;; The clobber is here because emit_move_sequence assumes the worst case.
1796    (clobber (reg:DI 1))]
1797   "TARGET_MEDANY && check_pic (1)"
1798   "sethi %%hi(%a1),%0; add %0,%%g4,%0"
1799   [(set_attr "type" "move")
1800    (set_attr "length" "2")])
1801
1802 (define_insn "*sethi_di_medany_text"
1803   [(set (match_operand:DI 0 "register_operand" "=r")
1804         (high:DI (match_operand 1 "text_segment_operand" "")))
1805   ;; The clobber is here because emit_move_sequence assumes the worst case.
1806    (clobber (reg:DI 1))]
1807   "TARGET_MEDANY && check_pic (1)"
1808   "sethi %%uhi(%a1),%%g1; or %%g1,%%ulo(%a1),%%g1; sllx %%g1,32,%%g1; sethi %%hi(%a1),%0; or %0,%%g1,%0"
1809   [(set_attr "type" "move")
1810    (set_attr "length" "5")])
1811
1812 (define_insn "*sethi_di_fullany"
1813   [(set (match_operand:DI 0 "register_operand" "=r")
1814         (high:DI (match_operand 1 "" "")))
1815    (clobber (reg:DI 1))]
1816   "TARGET_FULLANY && check_pic (1)"
1817   "sethi %%uhi(%a1),%%g1; or %%g1,%%ulo(%a1),%%g1; sllx %%g1,32,%%g1; sethi %%hi(%a1),%0; or %0,%%g1,%0"
1818   [(set_attr "type" "move")
1819    (set_attr "length" "5")])
1820 \f
1821 ;; Move instructions
1822
1823 (define_expand "movqi"
1824   [(set (match_operand:QI 0 "general_operand" "")
1825         (match_operand:QI 1 "general_operand" ""))]
1826   ""
1827   "
1828 {
1829   if (emit_move_sequence (operands, QImode))
1830     DONE;
1831 }")
1832
1833 (define_insn "*movqi_insn"
1834   [(set (match_operand:QI 0 "reg_or_nonsymb_mem_operand" "=r,r,r,Q")
1835         (match_operand:QI 1 "move_operand" "rI,K,Q,rJ"))]
1836   "! TARGET_LIVE_G0
1837    && (register_operand (operands[0], QImode)
1838        || register_operand (operands[1], QImode)
1839        || operands[1] == const0_rtx)"
1840   "@
1841    mov %1,%0
1842    sethi %%hi(%a1),%0
1843    ldub %1,%0
1844    stb %r1,%0"
1845   [(set_attr "type" "move,move,load,store")
1846    (set_attr "length" "1")])
1847
1848 (define_insn "*movqi_insn_liveg0"
1849   [(set (match_operand:QI 0 "reg_or_nonsymb_mem_operand" "=r,r,r,r,r,Q")
1850         (match_operand:QI 1 "move_operand" "r,J,I,K,Q,r"))]
1851   "TARGET_LIVE_G0
1852    && (register_operand (operands[0], QImode)
1853        || register_operand (operands[1], QImode))"
1854   "@
1855    mov %1,%0
1856    and %0,0,%0
1857    and %0,0,%0\;or %0,%1,%0
1858    sethi %%hi(%a1),%0
1859    ldub %1,%0
1860    stb %1,%0"
1861   [(set_attr "type" "move,move,move,move,load,store")
1862    (set_attr "length" "1,1,2,1,1,1")])
1863
1864 (define_insn "*lo_sum_qi"
1865   [(set (match_operand:QI 0 "register_operand" "=r")
1866         (subreg:QI (lo_sum:SI (match_operand:QI 1 "register_operand" "r")
1867                               (match_operand 2 "immediate_operand" "in")) 0))]
1868   ""
1869   "or %1,%%lo(%a2),%0"
1870   [(set_attr "length" "1")])
1871
1872 (define_insn "*store_qi"
1873   [(set (mem:QI (match_operand:SI 0 "symbolic_operand" ""))
1874         (match_operand:QI 1 "reg_or_0_operand" "rJ"))
1875    (clobber (match_scratch:SI 2 "=&r"))]
1876   "(reload_completed || reload_in_progress)
1877    && ! TARGET_PTR64"
1878   "sethi %%hi(%a0),%2\;stb %r1,[%2+%%lo(%a0)]"
1879   [(set_attr "type" "store")
1880    (set_attr "length" "2")])
1881
1882 (define_expand "movhi"
1883   [(set (match_operand:HI 0 "general_operand" "")
1884         (match_operand:HI 1 "general_operand" ""))]
1885   ""
1886   "
1887 {
1888   if (emit_move_sequence (operands, HImode))
1889     DONE;
1890 }")
1891
1892 (define_insn "*movhi_insn"
1893   [(set (match_operand:HI 0 "reg_or_nonsymb_mem_operand" "=r,r,r,Q")
1894         (match_operand:HI 1 "move_operand" "rI,K,Q,rJ"))]
1895   "! TARGET_LIVE_G0
1896    && (register_operand (operands[0], HImode)
1897        || register_operand (operands[1], HImode)
1898        || operands[1] == const0_rtx)"
1899   "@
1900    mov %1,%0
1901    sethi %%hi(%a1),%0
1902    lduh %1,%0
1903    sth %r1,%0"
1904   [(set_attr "type" "move,move,load,store")
1905    (set_attr "length" "1")])
1906
1907 (define_insn "*movhi_insn_liveg0"
1908   [(set (match_operand:HI 0 "reg_or_nonsymb_mem_operand" "=r,r,r,r,r,Q")
1909         (match_operand:HI 1 "move_operand" "r,J,I,K,Q,r"))]
1910   "TARGET_LIVE_G0
1911    && (register_operand (operands[0], HImode)
1912        || register_operand (operands[1], HImode))"
1913   "@
1914    mov %1,%0
1915    and %0,0,%0
1916    and %0,0,%0\;or %0,%1,%0
1917    sethi %%hi(%a1),%0
1918    lduh %1,%0
1919    sth %1,%0"
1920   [(set_attr "type" "move,move,move,move,load,store")
1921    (set_attr "length" "1,1,2,1,1,1")])
1922
1923 (define_insn "*lo_sum_hi"
1924   [(set (match_operand:HI 0 "register_operand" "=r")
1925         (lo_sum:HI (match_operand:HI 1 "register_operand" "r")
1926                    (match_operand 2 "immediate_operand" "in")))]
1927   ""
1928   "or %1,%%lo(%a2),%0"
1929   [(set_attr "length" "1")])
1930
1931 (define_insn "*store_hi"
1932   [(set (mem:HI (match_operand:SI 0 "symbolic_operand" ""))
1933         (match_operand:HI 1 "reg_or_0_operand" "rJ"))
1934    (clobber (match_scratch:SI 2 "=&r"))]
1935   "(reload_completed || reload_in_progress)
1936    && ! TARGET_PTR64"
1937   "sethi %%hi(%a0),%2\;sth %r1,[%2+%%lo(%a0)]"
1938   [(set_attr "type" "store")
1939    (set_attr "length" "2")])
1940
1941 (define_expand "movsi"
1942   [(set (match_operand:SI 0 "general_operand" "")
1943         (match_operand:SI 1 "general_operand" ""))]
1944   ""
1945   "
1946 {
1947   if (emit_move_sequence (operands, SImode))
1948     DONE;
1949 }")
1950
1951 ;; We must support both 'r' and 'f' registers here, because combine may
1952 ;; convert SFmode hard registers to SImode hard registers when simplifying
1953 ;; subreg sets.
1954
1955 ;; We cannot combine the similar 'r' and 'f' constraints, because it causes
1956 ;; problems with register allocation.  Reload might try to put an integer
1957 ;; in an fp register, or an fp number is an integer register.
1958
1959 (define_insn "*movsi_insn"
1960   [(set (match_operand:SI 0 "reg_or_nonsymb_mem_operand" "=r,f,r,r,f,Q,Q")
1961         (match_operand:SI 1 "move_operand" "rI,!f,K,Q,!Q,rJ,!f"))]
1962   "! TARGET_LIVE_G0
1963    && (register_operand (operands[0], SImode)
1964        || register_operand (operands[1], SImode)
1965        || operands[1] == const0_rtx)"
1966   "@
1967    mov %1,%0
1968    fmovs %1,%0
1969    sethi %%hi(%a1),%0
1970    ld %1,%0
1971    ld %1,%0
1972    st %r1,%0
1973    st %1,%0"
1974   [(set_attr "type" "move,fp,move,load,fpload,store,fpstore")
1975    (set_attr "length" "1")])
1976
1977 (define_insn "*movsi_insn_liveg0"
1978   [(set (match_operand:SI 0 "reg_or_nonsymb_mem_operand" "=r,r,r,f,r,r,f,Q,Q")
1979         (match_operand:SI 1 "move_operand" "r,J,I,!f,K,Q,!Q,r,!f"))]
1980   "TARGET_LIVE_G0
1981    && (register_operand (operands[0], SImode)
1982        || register_operand (operands[1], SImode))"
1983   "@
1984    mov %1,%0
1985    and %0,0,%0
1986    and %0,0,%0\;or %0,%1,%0
1987    fmovs %1,%0
1988    sethi %%hi(%a1),%0
1989    ld %1,%0
1990    ld %1,%0
1991    st %1,%0
1992    st %1,%0"
1993   [(set_attr "type" "move,move,move,fp,move,load,fpload,store,fpstore")
1994    (set_attr "length" "1,1,2,1,1,1,1,1,1")])
1995
1996 (define_insn "*store_si"
1997   [(set (mem:SI (match_operand:SI 0 "symbolic_operand" ""))
1998         (match_operand:SI 1 "reg_or_0_operand" "rJ"))
1999    (clobber (match_scratch:SI 2 "=&r"))]
2000   "(reload_completed || reload_in_progress)
2001    && ! TARGET_PTR64"
2002   "sethi %%hi(%a0),%2\;st %r1,[%2+%%lo(%a0)]"
2003   [(set_attr "type" "store")
2004    (set_attr "length" "2")])
2005
2006 (define_expand "movdi"
2007   [(set (match_operand:DI 0 "reg_or_nonsymb_mem_operand" "")
2008         (match_operand:DI 1 "general_operand" ""))]
2009   ""
2010   "
2011 {
2012   if (emit_move_sequence (operands, DImode))
2013     DONE;
2014 }")
2015
2016 (define_insn "*movdi_sp32_insn"
2017   [(set (match_operand:DI 0 "reg_or_nonsymb_mem_operand" "=r,T,U,Q,r,r,?f,?f,?Q")
2018         (match_operand:DI 1 "general_operand" "r,U,T,r,Q,i,f,Q,f"))]
2019   "! TARGET_ARCH64
2020    && (register_operand (operands[0], DImode)
2021        || register_operand (operands[1], DImode)
2022        || operands[1] == const0_rtx)"
2023   "*
2024 {
2025   if (FP_REG_P (operands[0]) || FP_REG_P (operands[1]))
2026     return output_fp_move_double (operands);
2027   return output_move_double (operands);
2028 }"
2029   [(set_attr "type" "move,store,load,store,load,multi,fp,fpload,fpstore")
2030    (set_attr "length" "2,1,1,3,3,3,2,3,3")])
2031
2032 ;;; ??? The trick used below can be extended to load any negative 32 bit
2033 ;;; constant in two instructions.  Currently the compiler will use HIGH/LO_SUM
2034 ;;; for anything not matching the HIK constraints, which results in 5
2035 ;;; instructions.  Positive 32 bit constants can be loaded in the obvious way
2036 ;;; with sethi/ori.  To extend the trick, in the xor instruction, use 
2037 ;;; xor %o0, ((op1 & 0x3ff) | -0x400), %o0
2038 ;;; This needs the original value of operands[1], not the inverted value.
2039
2040 (define_insn "*movdi_sp64_insn"
2041   [(set (match_operand:DI 0 "reg_or_nonsymb_mem_operand" "=r,r,r,Q,?f,?f,?Q")
2042         (match_operand:DI 1 "move_operand" "rI,K,Q,rJ,f,Q,f"))]
2043   "TARGET_ARCH64
2044    && (register_operand (operands[0], DImode)
2045        || register_operand (operands[1], DImode)
2046        || operands[1] == const0_rtx)"
2047   "*
2048 {
2049   switch (which_alternative)
2050     {
2051     case 0:
2052       return \"mov %1,%0\";
2053     case 1:
2054       /* Sethi does not sign extend, so we must use a little trickery
2055          to use it for negative numbers.  Invert the constant before
2056          loading it in, then use a xor immediate to invert the loaded bits
2057          (along with the upper 32 bits) to the desired constant.  This
2058          works because the sethi and immediate fields overlap.  */
2059
2060       if ((INTVAL (operands[1]) & 0x80000000) == 0)
2061         return \"sethi %%hi(%a1),%0\";
2062       else
2063         {
2064           operands[1] = GEN_INT (~INTVAL (operands[1]));
2065           output_asm_insn (\"sethi %%hi(%a1),%0\", operands);
2066           /* The low 10 bits are already zero, but invert the rest.
2067              Assemblers don't accept 0x1c00, so use -0x400 instead.  */
2068           return \"xor %0,-0x400,%0\";
2069         }
2070     case 2:
2071       return \"ldx %1,%0\";
2072     case 3:
2073       return \"stx %r1,%0\";
2074     case 4:
2075       return \"mov %1,%0\";
2076     case 5:
2077       return \"ldd %1,%0\";
2078     case 6:
2079       return \"std %1,%0\";
2080     }
2081 }"
2082   [(set_attr "type" "move,move,load,store,fp,fpload,fpstore")
2083    (set_attr "length" "1,2,1,1,1,1,1")])
2084
2085 ;; ??? There's no symbolic (set (mem:DI ...) ...).
2086 ;; Experimentation with v9 suggested one isn't needed.
2087 \f
2088 ;; Block move insns.
2089
2090 ;; ??? We get better code without it.  See output_block_move in sparc.c.
2091
2092 ;; The definition of this insn does not really explain what it does,
2093 ;; but it should suffice
2094 ;; that anything generated as this insn will be recognized as one
2095 ;; and that it will not successfully combine with anything.
2096 ;(define_expand "movstrsi"
2097 ;  [(parallel [(set (mem:BLK (match_operand:BLK 0 "general_operand" ""))
2098 ;                  (mem:BLK (match_operand:BLK 1 "general_operand" "")))
2099 ;             (use (match_operand:SI 2 "nonmemory_operand" ""))
2100 ;             (use (match_operand:SI 3 "immediate_operand" ""))
2101 ;             (clobber (match_dup 0))
2102 ;             (clobber (match_dup 1))
2103 ;             (clobber (match_scratch:SI 4 ""))
2104 ;             (clobber (reg:SI 100))
2105 ;             (clobber (reg:SI 1))])]
2106 ;  ""
2107 ;  "
2108 ;{
2109 ;  /* If the size isn't known, don't emit inline code.  output_block_move
2110 ;     would output code that's much slower than the library function.
2111 ;     Also don't output code for large blocks.  */
2112 ;  if (GET_CODE (operands[2]) != CONST_INT
2113 ;      || GET_CODE (operands[3]) != CONST_INT
2114 ;      || INTVAL (operands[2]) / INTVAL (operands[3]) > 16)
2115 ;    FAIL;
2116 ;
2117 ;  operands[0] = copy_to_mode_reg (Pmode, XEXP (operands[0], 0));
2118 ;  operands[1] = copy_to_mode_reg (Pmode, XEXP (operands[1], 0));
2119 ;  operands[2] = force_not_mem (operands[2]);
2120 ;}")
2121
2122 ;(define_insn "*block_move_insn"
2123 ;  [(set (mem:BLK (match_operand:SI 0 "register_operand" "+r"))
2124 ;       (mem:BLK (match_operand:SI 1 "register_operand" "+r")))
2125 ;   (use (match_operand:SI 2 "nonmemory_operand" "rn"))
2126 ;   (use (match_operand:SI 3 "immediate_operand" "i"))
2127 ;   (clobber (match_dup 0))
2128 ;   (clobber (match_dup 1))
2129 ;   (clobber (match_scratch:SI 4 "=&r"))
2130 ;   (clobber (reg:SI 100))
2131 ;   (clobber (reg:SI 1))]
2132 ;  ""
2133 ;  "* return output_block_move (operands);"
2134 ;  [(set_attr "type" "multi")
2135 ;   (set_attr "length" "6")])
2136 \f
2137 ;; Floating point move insns
2138
2139 ;; This pattern forces (set (reg:SF ...) (const_double ...))
2140 ;; to be reloaded by putting the constant into memory.
2141 ;; It must come before the more general movsf pattern.
2142 (define_insn "*movsf_const_insn"
2143   [(set (match_operand:SF 0 "general_operand" "=?r,f,m")
2144         (match_operand:SF 1 "" "?F,m,G"))]
2145   "TARGET_FPU && GET_CODE (operands[1]) == CONST_DOUBLE"
2146   "*
2147 {
2148   switch (which_alternative)
2149     {
2150     case 0:
2151       return singlemove_string (operands);
2152     case 1:
2153       return \"ld %1,%0\";
2154     case 2:
2155       return \"st %%g0,%0\";
2156     }
2157 }"
2158   [(set_attr "type" "load,fpload,store")
2159    (set_attr "length" "2,1,1")])
2160
2161 (define_expand "movsf"
2162   [(set (match_operand:SF 0 "general_operand" "")
2163         (match_operand:SF 1 "general_operand" ""))]
2164   ""
2165   "
2166 {
2167   if (emit_move_sequence (operands, SFmode))
2168     DONE;
2169 }")
2170
2171 (define_insn "*movsf_insn"
2172   [(set (match_operand:SF 0 "reg_or_nonsymb_mem_operand" "=f,r,f,r,Q,Q")
2173         (match_operand:SF 1 "reg_or_nonsymb_mem_operand" "f,r,Q,Q,f,r"))]
2174   "TARGET_FPU
2175    && (register_operand (operands[0], SFmode)
2176        || register_operand (operands[1], SFmode))"
2177   "@
2178    fmovs %1,%0
2179    mov %1,%0
2180    ld %1,%0
2181    ld %1,%0
2182    st %1,%0
2183    st %1,%0"
2184   [(set_attr "type" "fp,move,fpload,load,fpstore,store")])
2185
2186 ;; Exactly the same as above, except that all `f' cases are deleted.
2187 ;; This is necessary to prevent reload from ever trying to use a `f' reg
2188 ;; when -mno-fpu.
2189
2190 (define_insn "*movsf_no_f_insn"
2191   [(set (match_operand:SF 0 "reg_or_nonsymb_mem_operand" "=r,r,Q")
2192         (match_operand:SF 1 "reg_or_nonsymb_mem_operand" "r,Q,r"))]
2193   "! TARGET_FPU
2194    && (register_operand (operands[0], SFmode)
2195        || register_operand (operands[1], SFmode))"
2196   "@
2197    mov %1,%0
2198    ld %1,%0
2199    st %1,%0"
2200   [(set_attr "type" "move,load,store")])
2201
2202 (define_insn "*store_sf"
2203   [(set (mem:SF (match_operand:SI 0 "symbolic_operand" "i"))
2204         (match_operand:SF 1 "reg_or_0_operand" "rfG"))
2205    (clobber (match_scratch:SI 2 "=&r"))]
2206   "(reload_completed || reload_in_progress)
2207    && ! TARGET_PTR64"
2208   "sethi %%hi(%a0),%2\;st %r1,[%2+%%lo(%a0)]"
2209   [(set_attr "type" "store")
2210    (set_attr "length" "2")])
2211
2212 ;; This pattern forces (set (reg:DF ...) (const_double ...))
2213 ;; to be reloaded by putting the constant into memory.
2214 ;; It must come before the more general movdf pattern.
2215
2216 (define_insn "*movdf_const_insn"
2217   [(set (match_operand:DF 0 "general_operand" "=?r,e,o")
2218         (match_operand:DF 1 "" "?F,m,G"))]
2219   "TARGET_FPU && GET_CODE (operands[1]) == CONST_DOUBLE"
2220   "*
2221 {
2222   switch (which_alternative)
2223     {
2224     case 0:
2225       return output_move_double (operands);
2226     case 1:
2227       return output_fp_move_double (operands);
2228     case 2:
2229       if (TARGET_ARCH64)
2230         {
2231           return \"stx %%g0,%0\";
2232         }
2233       else
2234         {
2235           operands[1] = adj_offsettable_operand (operands[0], 4);
2236           return \"st %%g0,%0\;st %%g0,%1\";
2237         }
2238     }
2239 }"
2240   [(set_attr "type" "load,fpload,store")
2241    (set_attr "length" "3,3,3")])
2242
2243 (define_expand "movdf"
2244   [(set (match_operand:DF 0 "general_operand" "")
2245         (match_operand:DF 1 "general_operand" ""))]
2246   ""
2247   "
2248 {
2249   if (emit_move_sequence (operands, DFmode))
2250     DONE;
2251 }")
2252
2253 (define_insn "*movdf_insn"
2254   [(set (match_operand:DF 0 "reg_or_nonsymb_mem_operand" "=T,U,e,r,Q,Q,e,r")
2255         (match_operand:DF 1 "reg_or_nonsymb_mem_operand" "U,T,e,r,e,r,Q,Q"))]
2256   "TARGET_FPU
2257    && (register_operand (operands[0], DFmode)
2258        || register_operand (operands[1], DFmode))"
2259   "*
2260 {
2261   if (FP_REG_P (operands[0]) || FP_REG_P (operands[1]))
2262     return output_fp_move_double (operands);
2263   return output_move_double (operands);
2264 }"
2265   [(set_attr "type" "fpstore,fpload,fp,move,fpstore,store,fpload,load")
2266    (set_attr "length" "1,1,2,2,3,3,3,3")])
2267
2268 ;; Exactly the same as above, except that all `e' cases are deleted.
2269 ;; This is necessary to prevent reload from ever trying to use a `e' reg
2270 ;; when -mno-fpu.
2271
2272 (define_insn "*movdf_no_e_insn"
2273   [(set (match_operand:DF 0 "reg_or_nonsymb_mem_operand" "=T,U,r,Q,&r")
2274         (match_operand:DF 1 "reg_or_nonsymb_mem_operand" "U,T,r,r,Q"))]
2275   "! TARGET_FPU
2276    && (register_operand (operands[0], DFmode)
2277        || register_operand (operands[1], DFmode))"
2278   "* return output_move_double (operands);"
2279   [(set_attr "type" "store,load,move,store,load")
2280    (set_attr "length" "1,1,2,3,3")])
2281
2282 ;; Must handle overlapping registers here, since parameters can be unaligned
2283 ;; in registers.
2284
2285 (define_split
2286   [(set (match_operand:DF 0 "register_operand" "")
2287         (match_operand:DF 1 "register_operand" ""))]
2288   "! TARGET_ARCH64 && reload_completed
2289    && REGNO (operands[0]) < SPARC_FIRST_V9_FP_REG
2290    && REGNO (operands[1]) < SPARC_FIRST_V9_FP_REG"
2291   [(set (match_dup 2) (match_dup 3))
2292    (set (match_dup 4) (match_dup 5))]
2293   "
2294 {
2295   rtx first_set = operand_subword (operands[0], 0, 0, DFmode);
2296   rtx second_use = operand_subword (operands[1], 1, 0, DFmode);
2297
2298   if (REGNO (first_set) == REGNO (second_use))
2299     {
2300       operands[2] = operand_subword (operands[0], 1, 0, DFmode);
2301       operands[3] = second_use;
2302       operands[4] = first_set;
2303       operands[5] = operand_subword (operands[1], 0, 0, DFmode);
2304     }
2305   else
2306     {
2307       operands[2] = first_set;
2308       operands[3] = operand_subword (operands[1], 0, 0, DFmode);
2309       operands[4] = operand_subword (operands[0], 1, 0, DFmode);
2310       operands[5] = second_use;
2311     }
2312 }")
2313
2314 (define_insn "*store_df"
2315   [(set (mem:DF (match_operand:SI 0 "symbolic_operand" "i,i"))
2316         (match_operand:DF 1 "reg_or_0_operand" "re,G"))
2317    (clobber (match_scratch:SI 2 "=&r,&r"))]
2318   "(reload_completed || reload_in_progress)
2319    && ! TARGET_PTR64"
2320   "*
2321 {
2322   output_asm_insn (\"sethi %%hi(%a0),%2\", operands);
2323   if (which_alternative == 0)
2324     return \"std %1,[%2+%%lo(%a0)]\";
2325   else
2326     return \"st %%g0,[%2+%%lo(%a0)]\;st %%g0,[%2+%%lo(%a0+4)]\";
2327 }"
2328   [(set_attr "type" "store")
2329    (set_attr "length" "3")])
2330
2331 ;; This pattern forces (set (reg:TF ...) (const_double ...))
2332 ;; to be reloaded by putting the constant into memory.
2333 ;; It must come before the more general movtf pattern.
2334 (define_insn "*movtf_const_insn"
2335   [(set (match_operand:TF 0 "general_operand" "=?r,e,o")
2336         (match_operand:TF 1 "" "?F,m,G"))]
2337   "TARGET_FPU && GET_CODE (operands[1]) == CONST_DOUBLE"
2338   "*
2339 {
2340   switch (which_alternative)
2341     {
2342     case 0:
2343       return output_move_quad (operands);
2344     case 1:
2345       return output_fp_move_quad (operands);
2346     case 2:
2347       if (TARGET_ARCH64)
2348         {
2349           operands[1] = adj_offsettable_operand (operands[0], 8);
2350           return \"stx %%g0,%0\;stx %%g0,%1\";
2351         }
2352       else
2353         {
2354           /* ??? Do we run off the end of the array here? */
2355           operands[1] = adj_offsettable_operand (operands[0], 4);
2356           operands[2] = adj_offsettable_operand (operands[0], 8);
2357           operands[3] = adj_offsettable_operand (operands[0], 12);
2358           return \"st %%g0,%0\;st %%g0,%1\;st %%g0,%2\;st %%g0,%3\";
2359         }
2360     }
2361 }"
2362   [(set_attr "type" "load,fpload,store")
2363    (set_attr "length" "5,5,5")])
2364
2365 (define_expand "movtf"
2366   [(set (match_operand:TF 0 "general_operand" "")
2367         (match_operand:TF 1 "general_operand" ""))]
2368   ""
2369   "
2370 {
2371   if (emit_move_sequence (operands, TFmode))
2372     DONE;
2373 }")
2374
2375 (define_insn "*movtf_insn"
2376   [(set (match_operand:TF 0 "reg_or_nonsymb_mem_operand" "=e,r,Q,Q,e,&r")
2377         (match_operand:TF 1 "reg_or_nonsymb_mem_operand" "e,r,e,r,Q,Q"))]
2378   "TARGET_FPU
2379    && (register_operand (operands[0], TFmode)
2380        || register_operand (operands[1], TFmode))"
2381   "*
2382 {
2383   if (FP_REG_P (operands[0]) || FP_REG_P (operands[1]))
2384     return output_fp_move_quad (operands);
2385   return output_move_quad (operands);
2386 }"
2387   [(set_attr "type" "fp,move,fpstore,store,fpload,load")
2388    (set_attr "length" "4,4,5,5,5,5")])
2389
2390 ;; Exactly the same as above, except that all `e' cases are deleted.
2391 ;; This is necessary to prevent reload from ever trying to use a `e' reg
2392 ;; when -mno-fpu.
2393
2394 (define_insn "*movtf_no_e_insn"
2395   [(set (match_operand:TF 0 "reg_or_nonsymb_mem_operand" "=r,Q,&r")
2396         (match_operand:TF 1 "reg_or_nonsymb_mem_operand" "r,r,Q"))]
2397   "! TARGET_FPU
2398    && (register_operand (operands[0], TFmode)
2399        || register_operand (operands[1], TFmode))"
2400   "*
2401 {
2402   if (FP_REG_P (operands[0]) || FP_REG_P (operands[1]))
2403     return output_fp_move_quad (operands);
2404   return output_move_quad (operands);
2405 }"
2406   [(set_attr "type" "move,store,load")
2407    (set_attr "length" "4,5,5")])
2408
2409 ;; This is disabled because it does not work.  Long doubles have only 8
2410 ;; byte alignment.  Adding an offset of 8 or 12 to an 8 byte aligned %lo may 
2411 ;; cause it to overflow.  See also GO_IF_LEGITIMATE_ADDRESS.
2412 (define_insn "*store_tf"
2413   [(set (mem:TF (match_operand:SI 0 "symbolic_operand" "i,i"))
2414         (match_operand:TF 1 "reg_or_0_operand" "re,G"))
2415    (clobber (match_scratch:SI 2 "=&r,&r"))]
2416   "0 && (reload_completed || reload_in_progress)
2417    && ! TARGET_PTR64"
2418   "*
2419 {
2420   output_asm_insn (\"sethi %%hi(%a0),%2\", operands);
2421   if (which_alternative == 0)
2422     return \"std %1,[%2+%%lo(%a0)]\;std %S1,[%2+%%lo(%a0+8)]\";
2423   else
2424     return \"st %%g0,[%2+%%lo(%a0)]\;st %%g0,[%2+%%lo(%a0+4)]\; st %%g0,[%2+%%lo(%a0+8)]\;st %%g0,[%2+%%lo(%a0+12)]\";
2425 }"
2426   [(set_attr "type" "store")
2427    (set_attr "length" "5")])
2428 \f
2429 ;; Sparc V9 conditional move instructions.
2430
2431 ;; We can handle larger constants here for some flavors, but for now we keep
2432 ;; it simple and only allow those constants supported by all flavours.
2433 ;; Note that emit_conditional_move canonicalizes operands 2,3 so that operand
2434 ;; 3 contains the constant if one is present, but we handle either for
2435 ;; generality (sparc.c puts a constant in operand 2).
2436
2437 (define_expand "movqicc"
2438   [(set (match_operand:QI 0 "register_operand" "")
2439         (if_then_else:QI (match_operand 1 "comparison_operator" "")
2440                          (match_operand:QI 2 "arith10_operand" "")
2441                          (match_operand:QI 3 "arith10_operand" "")))]
2442   "TARGET_V9"
2443   "
2444 {
2445   enum rtx_code code = GET_CODE (operands[1]);
2446
2447   if (GET_MODE (sparc_compare_op0) == DImode
2448       && ! TARGET_ARCH64)
2449     FAIL;
2450
2451   if (sparc_compare_op1 == const0_rtx
2452       && GET_CODE (sparc_compare_op0) == REG
2453       && GET_MODE (sparc_compare_op0) == DImode
2454       && v9_regcmp_p (code))
2455     {
2456       operands[1] = gen_rtx (code, DImode,
2457                              sparc_compare_op0, sparc_compare_op1);
2458     }
2459   else
2460     {
2461       rtx cc_reg = gen_compare_reg (code,
2462                                     sparc_compare_op0, sparc_compare_op1);
2463       operands[1] = gen_rtx (code, GET_MODE (cc_reg), cc_reg, const0_rtx);
2464     }
2465 }")
2466
2467 (define_expand "movhicc"
2468   [(set (match_operand:HI 0 "register_operand" "")
2469         (if_then_else:HI (match_operand 1 "comparison_operator" "")
2470                          (match_operand:HI 2 "arith10_operand" "")
2471                          (match_operand:HI 3 "arith10_operand" "")))]
2472   "TARGET_V9"
2473   "
2474 {
2475   enum rtx_code code = GET_CODE (operands[1]);
2476
2477   if (GET_MODE (sparc_compare_op0) == DImode
2478       && ! TARGET_ARCH64)
2479     FAIL;
2480
2481   if (sparc_compare_op1 == const0_rtx
2482       && GET_CODE (sparc_compare_op0) == REG
2483       && GET_MODE (sparc_compare_op0) == DImode
2484       && v9_regcmp_p (code))
2485     {
2486       operands[1] = gen_rtx (code, DImode,
2487                              sparc_compare_op0, sparc_compare_op1);
2488     }
2489   else
2490     {
2491       rtx cc_reg = gen_compare_reg (code,
2492                                     sparc_compare_op0, sparc_compare_op1);
2493       operands[1] = gen_rtx (code, GET_MODE (cc_reg), cc_reg, const0_rtx);
2494     }
2495 }")
2496
2497 (define_expand "movsicc"
2498   [(set (match_operand:SI 0 "register_operand" "")
2499         (if_then_else:SI (match_operand 1 "comparison_operator" "")
2500                          (match_operand:SI 2 "arith10_operand" "")
2501                          (match_operand:SI 3 "arith10_operand" "")))]
2502   "TARGET_V9"
2503   "
2504 {
2505   enum rtx_code code = GET_CODE (operands[1]);
2506
2507   if (GET_MODE (sparc_compare_op0) == DImode
2508       && ! TARGET_ARCH64)
2509     FAIL;
2510
2511   if (sparc_compare_op1 == const0_rtx
2512       && GET_CODE (sparc_compare_op0) == REG
2513       && GET_MODE (sparc_compare_op0) == DImode
2514       && v9_regcmp_p (code))
2515     {
2516       operands[1] = gen_rtx (code, DImode,
2517                              sparc_compare_op0, sparc_compare_op1);
2518     }
2519   else
2520     {
2521       rtx cc_reg = gen_compare_reg (code,
2522                                     sparc_compare_op0, sparc_compare_op1);
2523       operands[1] = gen_rtx (code, GET_MODE (cc_reg), cc_reg, const0_rtx);
2524     }
2525 }")
2526
2527 (define_expand "movdicc"
2528   [(set (match_operand:DI 0 "register_operand" "")
2529         (if_then_else:DI (match_operand 1 "comparison_operator" "")
2530                          (match_operand:DI 2 "arith10_double_operand" "")
2531                          (match_operand:DI 3 "arith10_double_operand" "")))]
2532   "TARGET_ARCH64"
2533   "
2534 {
2535   enum rtx_code code = GET_CODE (operands[1]);
2536
2537   if (sparc_compare_op1 == const0_rtx
2538       && GET_CODE (sparc_compare_op0) == REG
2539       && GET_MODE (sparc_compare_op0) == DImode
2540       && v9_regcmp_p (code))
2541     {
2542       operands[1] = gen_rtx (code, DImode,
2543                              sparc_compare_op0, sparc_compare_op1);
2544     }
2545   else
2546     {
2547       rtx cc_reg = gen_compare_reg (code,
2548                                     sparc_compare_op0, sparc_compare_op1);
2549       operands[1] = gen_rtx (code, GET_MODE (cc_reg), cc_reg, const0_rtx);
2550     }
2551 }")
2552
2553 (define_expand "movsfcc"
2554   [(set (match_operand:SF 0 "register_operand" "")
2555         (if_then_else:SF (match_operand 1 "comparison_operator" "")
2556                          (match_operand:SF 2 "register_operand" "")
2557                          (match_operand:SF 3 "register_operand" "")))]
2558   "TARGET_V9 && TARGET_FPU"
2559   "
2560 {
2561   enum rtx_code code = GET_CODE (operands[1]);
2562
2563   if (GET_MODE (sparc_compare_op0) == DImode
2564       && ! TARGET_ARCH64)
2565     FAIL;
2566
2567   if (sparc_compare_op1 == const0_rtx
2568       && GET_CODE (sparc_compare_op0) == REG
2569       && GET_MODE (sparc_compare_op0) == DImode
2570       && v9_regcmp_p (code))
2571     {
2572       operands[1] = gen_rtx (code, DImode,
2573                              sparc_compare_op0, sparc_compare_op1);
2574     }
2575   else
2576     {
2577       rtx cc_reg = gen_compare_reg (code,
2578                                     sparc_compare_op0, sparc_compare_op1);
2579       operands[1] = gen_rtx (code, GET_MODE (cc_reg), cc_reg, const0_rtx);
2580     }
2581 }")
2582
2583 (define_expand "movdfcc"
2584   [(set (match_operand:DF 0 "register_operand" "")
2585         (if_then_else:DF (match_operand 1 "comparison_operator" "")
2586                          (match_operand:DF 2 "register_operand" "")
2587                          (match_operand:DF 3 "register_operand" "")))]
2588   "TARGET_V9 && TARGET_FPU"
2589   "
2590 {
2591   enum rtx_code code = GET_CODE (operands[1]);
2592
2593   if (GET_MODE (sparc_compare_op0) == DImode
2594       && ! TARGET_ARCH64)
2595     FAIL;
2596
2597   if (sparc_compare_op1 == const0_rtx
2598       && GET_CODE (sparc_compare_op0) == REG
2599       && GET_MODE (sparc_compare_op0) == DImode
2600       && v9_regcmp_p (code))
2601     {
2602       operands[1] = gen_rtx (code, DImode,
2603                              sparc_compare_op0, sparc_compare_op1);
2604     }
2605   else
2606     {
2607       rtx cc_reg = gen_compare_reg (code,
2608                                     sparc_compare_op0, sparc_compare_op1);
2609       operands[1] = gen_rtx (code, GET_MODE (cc_reg), cc_reg, const0_rtx);
2610     }
2611 }")
2612
2613 (define_expand "movtfcc"
2614   [(set (match_operand:TF 0 "register_operand" "")
2615         (if_then_else:TF (match_operand 1 "comparison_operator" "")
2616                          (match_operand:TF 2 "register_operand" "")
2617                          (match_operand:TF 3 "register_operand" "")))]
2618   "TARGET_V9 && TARGET_FPU"
2619   "
2620 {
2621   enum rtx_code code = GET_CODE (operands[1]);
2622
2623   if (GET_MODE (sparc_compare_op0) == DImode
2624       && ! TARGET_ARCH64)
2625     FAIL;
2626
2627   if (sparc_compare_op1 == const0_rtx
2628       && GET_CODE (sparc_compare_op0) == REG
2629       && GET_MODE (sparc_compare_op0) == DImode
2630       && v9_regcmp_p (code))
2631     {
2632       operands[1] = gen_rtx (code, DImode,
2633                              sparc_compare_op0, sparc_compare_op1);
2634     }
2635   else
2636     {
2637       rtx cc_reg = gen_compare_reg (code,
2638                                     sparc_compare_op0, sparc_compare_op1);
2639       operands[1] = gen_rtx (code, GET_MODE (cc_reg), cc_reg, const0_rtx);
2640     }
2641 }")
2642
2643 ;; Conditional move define_insns.
2644
2645 (define_insn "*movqi_cc_sp64"
2646   [(set (match_operand:QI 0 "register_operand" "=r,r")
2647         (if_then_else:QI (match_operator 1 "comparison_operator"
2648                                 [(match_operand 2 "icc_or_fcc_reg_operand" "X,X")
2649                                  (const_int 0)])
2650                       (match_operand:QI 3 "arith11_operand" "rL,0")
2651                       (match_operand:QI 4 "arith11_operand" "0,rL")))]
2652   "TARGET_V9"
2653   "@
2654    mov%C1 %x2,%3,%0
2655    mov%c1 %x2,%4,%0"
2656   [(set_attr "type" "cmove")])
2657
2658 (define_insn "*movhi_cc_sp64"
2659   [(set (match_operand:HI 0 "register_operand" "=r,r")
2660         (if_then_else:HI (match_operator 1 "comparison_operator"
2661                                 [(match_operand 2 "icc_or_fcc_reg_operand" "X,X")
2662                                  (const_int 0)])
2663                       (match_operand:HI 3 "arith11_operand" "rL,0")
2664                       (match_operand:HI 4 "arith11_operand" "0,rL")))]
2665   "TARGET_V9"
2666   "@
2667    mov%C1 %x2,%3,%0
2668    mov%c1 %x2,%4,%0"
2669   [(set_attr "type" "cmove")])
2670
2671 (define_insn "*movsi_cc_sp64"
2672   [(set (match_operand:SI 0 "register_operand" "=r,r")
2673         (if_then_else:SI (match_operator 1 "comparison_operator"
2674                                 [(match_operand 2 "icc_or_fcc_reg_operand" "X,X")
2675                                  (const_int 0)])
2676                       (match_operand:SI 3 "arith11_operand" "rL,0")
2677                       (match_operand:SI 4 "arith11_operand" "0,rL")))]
2678   "TARGET_V9"
2679   "@
2680    mov%C1 %x2,%3,%0
2681    mov%c1 %x2,%4,%0"
2682   [(set_attr "type" "cmove")])
2683
2684 ;; ??? The constraints of operands 3,4 need work.
2685 (define_insn "*movdi_cc_sp64"
2686   [(set (match_operand:DI 0 "register_operand" "=r,r")
2687         (if_then_else:DI (match_operator 1 "comparison_operator"
2688                                 [(match_operand 2 "icc_or_fcc_reg_operand" "X,X")
2689                                  (const_int 0)])
2690                       (match_operand:DI 3 "arith11_double_operand" "rLH,0")
2691                       (match_operand:DI 4 "arith11_double_operand" "0,rLH")))]
2692   "TARGET_ARCH64"
2693   "@
2694    mov%C1 %x2,%3,%0
2695    mov%c1 %x2,%4,%0"
2696   [(set_attr "type" "cmove")])
2697
2698 (define_insn "*movsf_cc_sp64"
2699   [(set (match_operand:SF 0 "register_operand" "=f,f")
2700         (if_then_else:SF (match_operator 1 "comparison_operator"
2701                                 [(match_operand 2 "icc_or_fcc_reg_operand" "X,X")
2702                                  (const_int 0)])
2703                       (match_operand:SF 3 "register_operand" "f,0")
2704                       (match_operand:SF 4 "register_operand" "0,f")))]
2705   "TARGET_V9 && TARGET_FPU"
2706   "@
2707    fmovs%C1 %x2,%3,%0
2708    fmovs%c1 %x2,%4,%0"
2709   [(set_attr "type" "cmove")])
2710
2711 (define_insn "*movdf_cc_sp64"
2712   [(set (match_operand:DF 0 "register_operand" "=e,e")
2713         (if_then_else:DF (match_operator 1 "comparison_operator"
2714                                 [(match_operand 2 "icc_or_fcc_reg_operand" "X,X")
2715                                  (const_int 0)])
2716                       (match_operand:DF 3 "register_operand" "e,0")
2717                       (match_operand:DF 4 "register_operand" "0,e")))]
2718   "TARGET_V9 && TARGET_FPU"
2719   "@
2720    fmovd%C1 %x2,%3,%0
2721    fmovd%c1 %x2,%4,%0"
2722   [(set_attr "type" "cmove")])
2723
2724 (define_insn "*movtf_cc_sp64"
2725   [(set (match_operand:TF 0 "register_operand" "=e,e")
2726         (if_then_else:TF (match_operator 1 "comparison_operator"
2727                                 [(match_operand 2 "icc_or_fcc_reg_operand" "X,X")
2728                                  (const_int 0)])
2729                       (match_operand:TF 3 "register_operand" "e,0")
2730                       (match_operand:TF 4 "register_operand" "0,e")))]
2731   "TARGET_V9 && TARGET_FPU && TARGET_HARD_QUAD"
2732   "@
2733    fmovq%C1 %x2,%3,%0
2734    fmovq%c1 %x2,%4,%0"
2735   [(set_attr "type" "cmove")])
2736
2737 (define_insn "*movqi_cc_reg_sp64"
2738   [(set (match_operand:QI 0 "register_operand" "=r,r")
2739         (if_then_else:QI (match_operator 1 "v9_regcmp_op"
2740                                 [(match_operand:DI 2 "register_operand" "r,r")
2741                                  (const_int 0)])
2742                       (match_operand:QI 3 "arith10_operand" "rM,0")
2743                       (match_operand:QI 4 "arith10_operand" "0,rM")))]
2744   "TARGET_ARCH64"
2745   "@
2746    movr%D1 %2,%r3,%0
2747    movr%d1 %2,%r4,%0"
2748   [(set_attr "type" "cmove")])
2749
2750 (define_insn "*movhi_cc_reg_sp64"
2751   [(set (match_operand:HI 0 "register_operand" "=r,r")
2752         (if_then_else:HI (match_operator 1 "v9_regcmp_op"
2753                                 [(match_operand:DI 2 "register_operand" "r,r")
2754                                  (const_int 0)])
2755                       (match_operand:HI 3 "arith10_operand" "rM,0")
2756                       (match_operand:HI 4 "arith10_operand" "0,rM")))]
2757   "TARGET_ARCH64"
2758   "@
2759    movr%D1 %2,%r3,%0
2760    movr%d1 %2,%r4,%0"
2761   [(set_attr "type" "cmove")])
2762
2763 (define_insn "*movsi_cc_reg_sp64"
2764   [(set (match_operand:SI 0 "register_operand" "=r,r")
2765         (if_then_else:SI (match_operator 1 "v9_regcmp_op"
2766                                 [(match_operand:DI 2 "register_operand" "r,r")
2767                                  (const_int 0)])
2768                       (match_operand:SI 3 "arith10_operand" "rM,0")
2769                       (match_operand:SI 4 "arith10_operand" "0,rM")))]
2770   "TARGET_ARCH64"
2771   "@
2772    movr%D1 %2,%r3,%0
2773    movr%d1 %2,%r4,%0"
2774   [(set_attr "type" "cmove")])
2775
2776 ;; ??? The constraints of operands 3,4 need work.
2777 (define_insn "*movdi_cc_reg_sp64"
2778   [(set (match_operand:DI 0 "register_operand" "=r,r")
2779         (if_then_else:DI (match_operator 1 "v9_regcmp_op"
2780                                 [(match_operand:DI 2 "register_operand" "r,r")
2781                                  (const_int 0)])
2782                       (match_operand:DI 3 "arith10_double_operand" "rMH,0")
2783                       (match_operand:DI 4 "arith10_double_operand" "0,rMH")))]
2784   "TARGET_ARCH64"
2785   "@
2786    movr%D1 %2,%r3,%0
2787    movr%d1 %2,%r4,%0"
2788   [(set_attr "type" "cmove")])
2789
2790 (define_insn "*movsf_cc_reg_sp64"
2791   [(set (match_operand:SF 0 "register_operand" "=f,f")
2792         (if_then_else:SF (match_operator 1 "v9_regcmp_op"
2793                                 [(match_operand:DI 2 "register_operand" "r,r")
2794                                  (const_int 0)])
2795                       (match_operand:SF 3 "register_operand" "f,0")
2796                       (match_operand:SF 4 "register_operand" "0,f")))]
2797   "TARGET_ARCH64 && TARGET_FPU"
2798   "@
2799    fmovrs%D1 %2,%3,%0
2800    fmovrs%d1 %2,%4,%0"
2801   [(set_attr "type" "cmove")])
2802
2803 (define_insn "*movdf_cc_reg_sp64"
2804   [(set (match_operand:DF 0 "register_operand" "=e,e")
2805         (if_then_else:DF (match_operator 1 "v9_regcmp_op"
2806                                 [(match_operand:DI 2 "register_operand" "r,r")
2807                                  (const_int 0)])
2808                       (match_operand:DF 3 "register_operand" "e,0")
2809                       (match_operand:DF 4 "register_operand" "0,e")))]
2810   "TARGET_ARCH64 && TARGET_FPU"
2811   "@
2812    fmovrd%D1 %2,%3,%0
2813    fmovrd%d1 %2,%4,%0"
2814   [(set_attr "type" "cmove")])
2815
2816 (define_insn "*movtf_cc_reg_sp64"
2817   [(set (match_operand:TF 0 "register_operand" "=e,e")
2818         (if_then_else:TF (match_operator 1 "v9_regcmp_op"
2819                                 [(match_operand:DI 2 "register_operand" "r,r")
2820                                  (const_int 0)])
2821                       (match_operand:TF 3 "register_operand" "e,0")
2822                       (match_operand:TF 4 "register_operand" "0,e")))]
2823   "TARGET_ARCH64 && TARGET_FPU"
2824   "@
2825    fmovrq%D1 %2,%3,%0
2826    fmovrq%d1 %2,%4,%0"
2827   [(set_attr "type" "cmove")])
2828 \f
2829 ;;- zero extension instructions
2830
2831 ;; These patterns originally accepted general_operands, however, slightly
2832 ;; better code is generated by only accepting register_operands, and then
2833 ;; letting combine generate the ldu[hb] insns.
2834
2835 (define_expand "zero_extendhisi2"
2836   [(set (match_operand:SI 0 "register_operand" "")
2837         (zero_extend:SI (match_operand:HI 1 "register_operand" "")))]
2838   ""
2839   "
2840 {
2841   rtx temp = gen_reg_rtx (SImode);
2842   rtx shift_16 = GEN_INT (16);
2843   int op1_subword = 0;
2844
2845   if (GET_CODE (operand1) == SUBREG)
2846     {
2847       op1_subword = SUBREG_WORD (operand1);
2848       operand1 = XEXP (operand1, 0);
2849     }
2850
2851   emit_insn (gen_ashlsi3 (temp, gen_rtx (SUBREG, SImode, operand1,
2852                                          op1_subword),
2853                           shift_16));
2854   emit_insn (gen_lshrsi3 (operand0, temp, shift_16));
2855   DONE;
2856 }")
2857
2858 (define_insn "*zero_extendhisi2_insn"
2859   [(set (match_operand:SI 0 "register_operand" "=r")
2860         (zero_extend:SI (match_operand:HI 1 "memory_operand" "m")))]
2861   ""
2862   "lduh %1,%0"
2863   [(set_attr "type" "load")])
2864
2865 (define_expand "zero_extendqihi2"
2866   [(set (match_operand:HI 0 "register_operand" "")
2867         (zero_extend:HI (match_operand:QI 1 "register_operand" "")))]
2868   ""
2869   "")
2870
2871 (define_insn "*zero_extendqihi2_insn"
2872   [(set (match_operand:HI 0 "register_operand" "=r,r")
2873         (zero_extend:HI (match_operand:QI 1 "sparc_operand" "r,Q")))]
2874   "GET_CODE (operands[1]) != CONST_INT"
2875   "@
2876    and %1,0xff,%0
2877    ldub %1,%0"
2878   [(set_attr "type" "unary,load")
2879    (set_attr "length" "1")])
2880
2881 (define_expand "zero_extendqisi2"
2882   [(set (match_operand:SI 0 "register_operand" "")
2883         (zero_extend:SI (match_operand:QI 1 "register_operand" "")))]
2884   ""
2885   "")
2886
2887 (define_insn "*zero_extendqisi2_insn"
2888   [(set (match_operand:SI 0 "register_operand" "=r,r")
2889         (zero_extend:SI (match_operand:QI 1 "sparc_operand" "r,Q")))]
2890   "GET_CODE (operands[1]) != CONST_INT"
2891   "@
2892    and %1,0xff,%0
2893    ldub %1,%0"
2894   [(set_attr "type" "unary,load")
2895    (set_attr "length" "1")])
2896
2897 (define_expand "zero_extendqidi2"
2898   [(set (match_operand:DI 0 "register_operand" "")
2899         (zero_extend:DI (match_operand:QI 1 "register_operand" "")))]
2900   "TARGET_ARCH64"
2901   "")
2902
2903 (define_insn "*zero_extendqidi2_insn"
2904   [(set (match_operand:DI 0 "register_operand" "=r,r")
2905         (zero_extend:DI (match_operand:QI 1 "sparc_operand" "r,Q")))]
2906   "TARGET_ARCH64 && GET_CODE (operands[1]) != CONST_INT"
2907   "@
2908    and %1,0xff,%0
2909    ldub %1,%0"
2910   [(set_attr "type" "unary,load")
2911    (set_attr "length" "1")])
2912
2913 (define_expand "zero_extendhidi2"
2914   [(set (match_operand:DI 0 "register_operand" "")
2915         (zero_extend:DI (match_operand:HI 1 "register_operand" "")))]
2916   "TARGET_ARCH64"
2917   "
2918 {
2919   rtx temp = gen_reg_rtx (DImode);
2920   rtx shift_48 = GEN_INT (48);
2921   int op1_subword = 0;
2922
2923   if (GET_CODE (operand1) == SUBREG)
2924     {
2925       op1_subword = SUBREG_WORD (operand1);
2926       operand1 = XEXP (operand1, 0);
2927     }
2928
2929   emit_insn (gen_ashldi3 (temp, gen_rtx (SUBREG, DImode, operand1,
2930                                          op1_subword),
2931                           shift_48));
2932   emit_insn (gen_lshrdi3 (operand0, temp, shift_48));
2933   DONE;
2934 }")
2935
2936 (define_insn "*zero_extendhidi2_insn"
2937   [(set (match_operand:DI 0 "register_operand" "=r")
2938         (zero_extend:DI (match_operand:HI 1 "memory_operand" "m")))]
2939   "TARGET_ARCH64"
2940   "lduh %1,%0"
2941   [(set_attr "type" "load")])
2942
2943 ;; ??? Write truncdisi pattern using sra?
2944
2945 (define_expand "zero_extendsidi2"
2946   [(set (match_operand:DI 0 "register_operand" "")
2947         (zero_extend:DI (match_operand:SI 1 "register_operand" "")))]
2948   "TARGET_ARCH64"
2949   "")
2950
2951 (define_insn "*zero_extendsidi2_insn"
2952   [(set (match_operand:DI 0 "register_operand" "=r,r")
2953         (zero_extend:DI (match_operand:SI 1 "sparc_operand" "r,Q")))]
2954   "TARGET_ARCH64 && GET_CODE (operands[1]) != CONST_INT"
2955   "@
2956    srl %1,0,%0
2957    lduw %1,%0"
2958   [(set_attr "type" "unary,load")
2959    (set_attr "length" "1")])
2960
2961 ;; Simplify comparisons of extended values.
2962
2963 (define_insn "*cmp_zero_extendqisi2"
2964   [(set (reg:CC 100)
2965         (compare:CC (zero_extend:SI (match_operand:QI 0 "register_operand" "r"))
2966                     (const_int 0)))]
2967   ""
2968   "andcc %0,0xff,%%g0"
2969   [(set_attr "type" "compare")])
2970
2971 (define_insn "*cmp_zero_extendqisi2_set"
2972   [(set (reg:CC 100)
2973         (compare:CC (zero_extend:SI (match_operand:QI 1 "register_operand" "r"))
2974                     (const_int 0)))
2975    (set (match_operand:SI 0 "register_operand" "=r")
2976         (zero_extend:SI (match_dup 1)))]
2977   ""
2978   "andcc %1,0xff,%0"
2979   [(set_attr "type" "unary")])
2980
2981 ;; Similarly, handle SI->QI mode truncation followed by a compare.
2982
2983 (define_insn "*cmp_siqi_trunc"
2984   [(set (reg:CC 100)
2985         (compare:CC (subreg:QI (match_operand:SI 0 "register_operand" "r") 0)
2986                     (const_int 0)))]
2987   ""
2988   "andcc %0,0xff,%%g0"
2989   [(set_attr "type" "compare")])
2990
2991 (define_insn "*cmp_siqi_trunc_set"
2992   [(set (reg:CC 100)
2993         (compare:CC (subreg:QI (match_operand:SI 1 "register_operand" "r") 0)
2994                     (const_int 0)))
2995    (set (match_operand:QI 0 "register_operand" "=r")
2996         (match_dup 1))]
2997   ""
2998   "andcc %1,0xff,%0"
2999   [(set_attr "type" "unary")])
3000 \f
3001 ;;- sign extension instructions
3002
3003 ;; These patterns originally accepted general_operands, however, slightly
3004 ;; better code is generated by only accepting register_operands, and then
3005 ;; letting combine generate the lds[hb] insns.
3006
3007 (define_expand "extendhisi2"
3008   [(set (match_operand:SI 0 "register_operand" "")
3009         (sign_extend:SI (match_operand:HI 1 "register_operand" "")))]
3010   ""
3011   "
3012 {
3013   rtx temp = gen_reg_rtx (SImode);
3014   rtx shift_16 = GEN_INT (16);
3015   int op1_subword = 0;
3016
3017   if (GET_CODE (operand1) == SUBREG)
3018     {
3019       op1_subword = SUBREG_WORD (operand1);
3020       operand1 = XEXP (operand1, 0);
3021     }
3022
3023   emit_insn (gen_ashlsi3 (temp, gen_rtx (SUBREG, SImode, operand1,
3024                                          op1_subword),
3025                           shift_16));
3026   emit_insn (gen_ashrsi3 (operand0, temp, shift_16));
3027   DONE;
3028 }")
3029
3030 (define_insn "*sign_extendhisi2_insn"
3031   [(set (match_operand:SI 0 "register_operand" "=r")
3032         (sign_extend:SI (match_operand:HI 1 "memory_operand" "m")))]
3033   ""
3034   "ldsh %1,%0"
3035   [(set_attr "type" "load")])
3036
3037 (define_expand "extendqihi2"
3038   [(set (match_operand:HI 0 "register_operand" "")
3039         (sign_extend:HI (match_operand:QI 1 "register_operand" "")))]
3040   ""
3041   "
3042 {
3043   rtx temp = gen_reg_rtx (SImode);
3044   rtx shift_24 = GEN_INT (24);
3045   int op1_subword = 0;
3046   int op0_subword = 0;
3047
3048   if (GET_CODE (operand1) == SUBREG)
3049     {
3050       op1_subword = SUBREG_WORD (operand1);
3051       operand1 = XEXP (operand1, 0);
3052     }
3053   if (GET_CODE (operand0) == SUBREG)
3054     {
3055       op0_subword = SUBREG_WORD (operand0);
3056       operand0 = XEXP (operand0, 0);
3057     }
3058   emit_insn (gen_ashlsi3 (temp, gen_rtx (SUBREG, SImode, operand1,
3059                                          op1_subword),
3060                           shift_24));
3061   if (GET_MODE (operand0) != SImode)
3062     operand0 = gen_rtx (SUBREG, SImode, operand0, op0_subword);
3063   emit_insn (gen_ashrsi3 (operand0, temp, shift_24));
3064   DONE;
3065 }")
3066
3067 (define_insn "*sign_extendqihi2_insn"
3068   [(set (match_operand:HI 0 "register_operand" "=r")
3069         (sign_extend:HI (match_operand:QI 1 "memory_operand" "m")))]
3070   ""
3071   "ldsb %1,%0"
3072   [(set_attr "type" "load")])
3073
3074 (define_expand "extendqisi2"
3075   [(set (match_operand:SI 0 "register_operand" "")
3076         (sign_extend:SI (match_operand:QI 1 "register_operand" "")))]
3077   ""
3078   "
3079 {
3080   rtx temp = gen_reg_rtx (SImode);
3081   rtx shift_24 = GEN_INT (24);
3082   int op1_subword = 0;
3083
3084   if (GET_CODE (operand1) == SUBREG)
3085     {
3086       op1_subword = SUBREG_WORD (operand1);
3087       operand1 = XEXP (operand1, 0);
3088     }
3089
3090   emit_insn (gen_ashlsi3 (temp, gen_rtx (SUBREG, SImode, operand1,
3091                                          op1_subword),
3092                           shift_24));
3093   emit_insn (gen_ashrsi3 (operand0, temp, shift_24));
3094   DONE;
3095 }")
3096
3097 (define_insn "*sign_extendqisi2_insn"
3098   [(set (match_operand:SI 0 "register_operand" "=r")
3099         (sign_extend:SI (match_operand:QI 1 "memory_operand" "m")))]
3100   ""
3101   "ldsb %1,%0"
3102   [(set_attr "type" "load")])
3103
3104 (define_expand "extendqidi2"
3105   [(set (match_operand:DI 0 "register_operand" "")
3106         (sign_extend:DI (match_operand:QI 1 "register_operand" "")))]
3107   "TARGET_ARCH64"
3108   "
3109 {
3110   rtx temp = gen_reg_rtx (DImode);
3111   rtx shift_56 = GEN_INT (56);
3112   int op1_subword = 0;
3113
3114   if (GET_CODE (operand1) == SUBREG)
3115     {
3116       op1_subword = SUBREG_WORD (operand1);
3117       operand1 = XEXP (operand1, 0);
3118     }
3119
3120   emit_insn (gen_ashldi3 (temp, gen_rtx (SUBREG, DImode, operand1,
3121                                          op1_subword),
3122                           shift_56));
3123   emit_insn (gen_ashrdi3 (operand0, temp, shift_56));
3124   DONE;
3125 }")
3126
3127 (define_insn "*sign_extendqidi2_insn"
3128   [(set (match_operand:DI 0 "register_operand" "=r")
3129         (sign_extend:DI (match_operand:QI 1 "memory_operand" "m")))]
3130   "TARGET_ARCH64"
3131   "ldsb %1,%0"
3132   [(set_attr "type" "load")])
3133
3134 (define_expand "extendhidi2"
3135   [(set (match_operand:DI 0 "register_operand" "")
3136         (sign_extend:DI (match_operand:HI 1 "register_operand" "")))]
3137   "TARGET_ARCH64"
3138   "
3139 {
3140   rtx temp = gen_reg_rtx (DImode);
3141   rtx shift_48 = GEN_INT (48);
3142   int op1_subword = 0;
3143
3144   if (GET_CODE (operand1) == SUBREG)
3145     {
3146       op1_subword = SUBREG_WORD (operand1);
3147       operand1 = XEXP (operand1, 0);
3148     }
3149
3150   emit_insn (gen_ashldi3 (temp, gen_rtx (SUBREG, DImode, operand1,
3151                                          op1_subword),
3152                           shift_48));
3153   emit_insn (gen_ashrdi3 (operand0, temp, shift_48));
3154   DONE;
3155 }")
3156
3157 (define_insn "*sign_extendhidi2_insn"
3158   [(set (match_operand:DI 0 "register_operand" "=r")
3159         (sign_extend:DI (match_operand:HI 1 "memory_operand" "m")))]
3160   "TARGET_ARCH64"
3161   "ldsh %1,%0"
3162   [(set_attr "type" "load")])
3163
3164 (define_expand "extendsidi2"
3165   [(set (match_operand:DI 0 "register_operand" "")
3166         (sign_extend:DI (match_operand:SI 1 "register_operand" "")))]
3167   "TARGET_ARCH64"
3168   "")
3169
3170 (define_insn "*sign_extendsidi2_insn"
3171   [(set (match_operand:DI 0 "register_operand" "=r,r")
3172         (sign_extend:DI (match_operand:SI 1 "sparc_operand" "r,Q")))]
3173   "TARGET_ARCH64"
3174   "@
3175   sra %1,0,%0
3176   ldsw %1,%0"
3177   [(set_attr "type" "unary,load")
3178    (set_attr "length" "1")])
3179 \f
3180 ;; Special pattern for optimizing bit-field compares.  This is needed
3181 ;; because combine uses this as a canonical form.
3182
3183 (define_insn "*cmp_zero_extract"
3184   [(set (reg:CC 100)
3185         (compare:CC
3186          (zero_extract:SI (match_operand:SI 0 "register_operand" "r")
3187                           (match_operand:SI 1 "small_int" "n")
3188                           (match_operand:SI 2 "small_int" "n"))
3189          (const_int 0)))]
3190   "INTVAL (operands[2]) > 19"
3191   "*
3192 {
3193   int len = INTVAL (operands[1]);
3194   int pos = 32 - INTVAL (operands[2]) - len;
3195   unsigned mask = ((1 << len) - 1) << pos;
3196
3197   operands[1] = GEN_INT (mask);
3198   return \"andcc %0,%1,%%g0\";
3199 }")
3200
3201 (define_insn "*cmp_zero_extract_sp64"
3202   [(set (reg:CCX 100)
3203         (compare:CCX
3204          (zero_extract:DI (match_operand:DI 0 "register_operand" "r")
3205                           (match_operand:SI 1 "small_int" "n")
3206                           (match_operand:SI 2 "small_int" "n"))
3207          (const_int 0)))]
3208   "TARGET_ARCH64 && INTVAL (operands[2]) > 51"
3209   "*
3210 {
3211   int len = INTVAL (operands[1]);
3212   int pos = 64 - INTVAL (operands[2]) - len;
3213   unsigned HOST_WIDE_INT mask = (((unsigned HOST_WIDE_INT) 1 << len) - 1) << pos;
3214
3215   operands[1] = GEN_INT (mask);
3216   return \"andcc %0,%1,%%g0\";
3217 }")
3218 \f
3219 ;; Conversions between float, double and long double.
3220
3221 (define_insn "extendsfdf2"
3222   [(set (match_operand:DF 0 "register_operand" "=e")
3223         (float_extend:DF
3224          (match_operand:SF 1 "register_operand" "f")))]
3225   "TARGET_FPU"
3226   "fstod %1,%0"
3227   [(set_attr "type" "fp")])
3228
3229 (define_insn "extendsftf2"
3230   [(set (match_operand:TF 0 "register_operand" "=e")
3231         (float_extend:TF
3232          (match_operand:SF 1 "register_operand" "f")))]
3233   "TARGET_FPU && TARGET_HARD_QUAD"
3234   "fstoq %1,%0"
3235   [(set_attr "type" "fp")])
3236
3237 (define_insn "extenddftf2"
3238   [(set (match_operand:TF 0 "register_operand" "=e")
3239         (float_extend:TF
3240          (match_operand:DF 1 "register_operand" "e")))]
3241   "TARGET_FPU && TARGET_HARD_QUAD"
3242   "fdtoq %1,%0"
3243   [(set_attr "type" "fp")])
3244
3245 (define_insn "truncdfsf2"
3246   [(set (match_operand:SF 0 "register_operand" "=f")
3247         (float_truncate:SF
3248          (match_operand:DF 1 "register_operand" "e")))]
3249   "TARGET_FPU"
3250   "fdtos %1,%0"
3251   [(set_attr "type" "fp")])
3252
3253 (define_insn "trunctfsf2"
3254   [(set (match_operand:SF 0 "register_operand" "=f")
3255         (float_truncate:SF
3256          (match_operand:TF 1 "register_operand" "e")))]
3257   "TARGET_FPU && TARGET_HARD_QUAD"
3258   "fqtos %1,%0"
3259   [(set_attr "type" "fp")])
3260
3261 (define_insn "trunctfdf2"
3262   [(set (match_operand:DF 0 "register_operand" "=e")
3263         (float_truncate:DF
3264          (match_operand:TF 1 "register_operand" "e")))]
3265   "TARGET_FPU && TARGET_HARD_QUAD"
3266   "fqtod %1,%0"
3267   [(set_attr "type" "fp")])
3268 \f
3269 ;; Conversion between fixed point and floating point.
3270
3271 (define_insn "floatsisf2"
3272   [(set (match_operand:SF 0 "register_operand" "=f")
3273         (float:SF (match_operand:SI 1 "register_operand" "f")))]
3274   "TARGET_FPU"
3275   "fitos %1,%0"
3276   [(set_attr "type" "fp")])
3277
3278 (define_insn "floatsidf2"
3279   [(set (match_operand:DF 0 "register_operand" "=e")
3280         (float:DF (match_operand:SI 1 "register_operand" "f")))]
3281   "TARGET_FPU"
3282   "fitod %1,%0"
3283   [(set_attr "type" "fp")])
3284
3285 (define_insn "floatsitf2"
3286   [(set (match_operand:TF 0 "register_operand" "=e")
3287         (float:TF (match_operand:SI 1 "register_operand" "f")))]
3288   "TARGET_FPU && TARGET_HARD_QUAD"
3289   "fitoq %1,%0"
3290   [(set_attr "type" "fp")])
3291
3292 ;; Now the same for 64 bit sources.
3293 ;; ??? We cannot put DImode values in fp regs (see below near fix_truncdfsi2).
3294
3295 (define_expand "floatdisf2"
3296   [(parallel [(set (match_operand:SF 0 "register_operand" "")
3297                    (float:SF (match_operand:DI 1 "general_operand" "")))
3298               (clobber (match_dup 2))
3299               (clobber (match_dup 3))])]
3300   "TARGET_ARCH64 && TARGET_FPU"
3301   "
3302 {
3303   operands[2] = gen_reg_rtx (DFmode);
3304   operands[3] = sparc64_fpconv_stack_temp ();
3305 }")
3306
3307 (define_expand "floatdidf2"
3308   [(parallel [(set (match_operand:DF 0 "register_operand" "")
3309                    (float:DF (match_operand:DI 1 "general_operand" "")))
3310               (clobber (match_dup 2))
3311               (clobber (match_dup 3))])]
3312   "TARGET_ARCH64 && TARGET_FPU"
3313   "
3314 {
3315   operands[2] = gen_reg_rtx (DFmode);
3316   operands[3] = sparc64_fpconv_stack_temp ();
3317 }")
3318
3319 (define_expand "floatditf2"
3320   [(parallel [(set (match_operand:TF 0 "register_operand" "")
3321                    (float:TF (match_operand:DI 1 "general_operand" "")))
3322               (clobber (match_dup 2))
3323               (clobber (match_dup 3))])]
3324   "TARGET_ARCH64 && TARGET_FPU && TARGET_HARD_QUAD"
3325   "
3326 {
3327   operands[2] = gen_reg_rtx (DFmode);
3328   operands[3] = sparc64_fpconv_stack_temp ();
3329 }")
3330
3331 (define_insn "*floatdisf2_insn"
3332   [(parallel [(set (match_operand:SF 0 "register_operand" "=f")
3333                    (float:SF (match_operand:DI 1 "general_operand" "rm")))
3334               (clobber (match_operand:DF 2 "register_operand" "=&e"))
3335               (clobber (match_operand:DI 3 "memory_operand" "m"))])]
3336   "TARGET_ARCH64 && TARGET_FPU"
3337   "*
3338 {
3339   if (GET_CODE (operands[1]) == MEM)
3340     output_asm_insn (\"ldd %1,%2\", operands);
3341   else
3342     output_asm_insn (\"stx %1,%3\;ldd %3,%2\", operands);
3343   return \"fxtos %2,%0\";
3344 }"
3345   [(set_attr "type" "fp")
3346    (set_attr "length" "3")])
3347
3348 (define_insn "*floatdidf2_insn"
3349   [(parallel [(set (match_operand:DF 0 "register_operand" "=e")
3350                    (float:DF (match_operand:DI 1 "general_operand" "rm")))
3351               (clobber (match_operand:DF 2 "register_operand" "=&e"))
3352               (clobber (match_operand:DI 3 "memory_operand" "m"))])]
3353   "TARGET_ARCH64 && TARGET_FPU"
3354   "*
3355 {
3356   if (GET_CODE (operands[1]) == MEM)
3357     output_asm_insn (\"ldd %1,%2\", operands);
3358   else
3359     output_asm_insn (\"stx %1,%3\;ldd %3,%2\", operands);
3360   return \"fxtod %2,%0\";
3361 }"
3362   [(set_attr "type" "fp")
3363    (set_attr "length" "3")])
3364
3365 (define_insn "*floatditf2_insn"
3366   [(parallel [(set (match_operand:TF 0 "register_operand" "=e")
3367                    (float:TF (match_operand:DI 1 "general_operand" "rm")))
3368               (clobber (match_operand:DF 2 "register_operand" "=&e"))
3369               (clobber (match_operand:DI 3 "memory_operand" "m"))])]
3370   "TARGET_ARCH64 && TARGET_FPU && TARGET_HARD_QUAD"
3371   "*
3372 {
3373   if (GET_CODE (operands[1]) == MEM)
3374     output_asm_insn (\"ldd %1,%2\", operands);
3375   else
3376     output_asm_insn (\"stx %1,%3\;ldd %3,%2\", operands);
3377   return \"fxtoq %2,%0\";
3378 }"
3379   [(set_attr "type" "fp")
3380    (set_attr "length" "3")])
3381
3382 ;; ??? Ideally, these are what we would like to use.
3383
3384 (define_insn "floatdisf2_sp64"
3385   [(set (match_operand:SF 0 "register_operand" "=f")
3386         (float:SF (match_operand:DI 1 "register_operand" "e")))]
3387   "0 && TARGET_ARCH64 && TARGET_FPU"
3388   "fxtos %1,%0"
3389   [(set_attr "type" "fp")])
3390
3391 (define_insn "floatdidf2_sp64"
3392   [(set (match_operand:DF 0 "register_operand" "=e")
3393         (float:DF (match_operand:DI 1 "register_operand" "e")))]
3394   "0 && TARGET_ARCH64 && TARGET_FPU"
3395   "fxtod %1,%0"
3396   [(set_attr "type" "fp")])
3397
3398 (define_insn "floatditf2_sp64"
3399   [(set (match_operand:TF 0 "register_operand" "=e")
3400         (float:TF (match_operand:DI 1 "register_operand" "e")))]
3401   "0 && TARGET_ARCH64 && TARGET_FPU && TARGET_HARD_QUAD"
3402   "fxtoq %1,%0"
3403   [(set_attr "type" "fp")])
3404
3405 ;; Convert a float to an actual integer.
3406 ;; Truncation is performed as part of the conversion.
3407
3408 (define_insn "fix_truncsfsi2"
3409   [(set (match_operand:SI 0 "register_operand" "=f")
3410         (fix:SI (fix:SF (match_operand:SF 1 "register_operand" "f"))))]
3411   "TARGET_FPU"
3412   "fstoi %1,%0"
3413   [(set_attr "type" "fp")])
3414
3415 (define_insn "fix_truncdfsi2"
3416   [(set (match_operand:SI 0 "register_operand" "=f")
3417         (fix:SI (fix:DF (match_operand:DF 1 "register_operand" "e"))))]
3418   "TARGET_FPU"
3419   "fdtoi %1,%0"
3420   [(set_attr "type" "fp")])
3421
3422 (define_insn "fix_trunctfsi2"
3423   [(set (match_operand:SI 0 "register_operand" "=f")
3424         (fix:SI (fix:TF (match_operand:TF 1 "register_operand" "e"))))]
3425   "TARGET_FPU && TARGET_HARD_QUAD"
3426   "fqtoi %1,%0"
3427   [(set_attr "type" "fp")])
3428
3429 ;; Now the same, for 64-bit targets
3430 ;; ??? We try to work around an interesting problem.
3431 ;; If gcc tries to do a subreg on the result it will get the wrong answer:
3432 ;; "(subreg:SI (reg:DI M int-reg) 0)" is the same as
3433 ;; "(subreg:SI (reg:DI N float-reg) 1)", but gcc does not know how to change
3434 ;; the "0" to a "1".  One could enhance alter_subreg but it is not clear how to
3435 ;; do this cleanly.
3436
3437 (define_expand "fix_truncsfdi2"
3438   [(parallel [(set (match_operand:DI 0 "general_operand" "")
3439                    (fix:DI (fix:SF (match_operand:SF 1 "register_operand" ""))))
3440               (clobber (match_dup 2))
3441               (clobber (match_dup 3))])]
3442   "TARGET_ARCH64 && TARGET_FPU"
3443   "
3444 {
3445   operands[2] = gen_reg_rtx (DFmode);
3446   operands[3] = sparc64_fpconv_stack_temp ();
3447 }")
3448
3449 (define_expand "fix_truncdfdi2"
3450   [(parallel [(set (match_operand:DI 0 "general_operand" "")
3451                    (fix:DI (fix:DF (match_operand:DF 1 "register_operand" ""))))
3452               (clobber (match_dup 2))
3453               (clobber (match_dup 3))])]
3454   "TARGET_ARCH64 && TARGET_FPU"
3455   "
3456 {
3457   operands[2] = gen_reg_rtx (DFmode);
3458   operands[3] = sparc64_fpconv_stack_temp ();
3459 }")
3460
3461 (define_expand "fix_trunctfdi2"
3462   [(parallel [(set (match_operand:DI 0 "general_operand" "")
3463                    (fix:DI (fix:TF (match_operand:TF 1 "register_operand" ""))))
3464               (clobber (match_dup 2))
3465               (clobber (match_dup 3))])]
3466   "TARGET_ARCH64 && TARGET_FPU && TARGET_HARD_QUAD"
3467   "
3468 {
3469   operands[2] = gen_reg_rtx (DFmode);
3470   operands[3] = sparc64_fpconv_stack_temp ();
3471 }")
3472
3473 (define_insn "*fix_truncsfdi2_insn"
3474   [(parallel [(set (match_operand:DI 0 "general_operand" "=rm")
3475                    (fix:DI (fix:SF (match_operand:SF 1 "register_operand" "f"))))
3476               (clobber (match_operand:DF 2 "register_operand" "=&e"))
3477               (clobber (match_operand:DI 3 "memory_operand" "m"))])]
3478   "TARGET_ARCH64 && TARGET_FPU"
3479   "*
3480 {
3481   output_asm_insn (\"fstox %1,%2\", operands);
3482   if (GET_CODE (operands[0]) == MEM)
3483     return \"std %2,%0\";
3484   else
3485     return \"std %2,%3\;ldx %3,%0\";
3486 }"
3487   [(set_attr "type" "fp")
3488    (set_attr "length" "3")])
3489
3490 (define_insn "*fix_truncdfdi2_insn"
3491   [(parallel [(set (match_operand:DI 0 "general_operand" "=rm")
3492                    (fix:DI (fix:DF (match_operand:DF 1 "register_operand" "e"))))
3493               (clobber (match_operand:DF 2 "register_operand" "=&e"))
3494               (clobber (match_operand:DI 3 "memory_operand" "m"))])]
3495   "TARGET_ARCH64 && TARGET_FPU"
3496   "*
3497 {
3498   output_asm_insn (\"fdtox %1,%2\", operands);
3499   if (GET_CODE (operands[0]) == MEM)
3500     return \"std %2,%0\";
3501   else
3502     return \"std %2,%3\;ldx %3,%0\";
3503 }"
3504   [(set_attr "type" "fp")
3505    (set_attr "length" "3")])
3506
3507 (define_insn "*fix_trunctfdi2_insn"
3508   [(parallel [(set (match_operand:DI 0 "general_operand" "=rm")
3509                    (fix:DI (fix:TF (match_operand:TF 1 "register_operand" "e"))))
3510               (clobber (match_operand:DF 2 "register_operand" "=&e"))
3511               (clobber (match_operand:DI 3 "memory_operand" "m"))])]
3512   "TARGET_ARCH64 && TARGET_FPU && TARGET_HARD_QUAD"
3513   "*
3514 {
3515   output_asm_insn (\"fqtox %1,%2\", operands);
3516   if (GET_CODE (operands[0]) == MEM)
3517     return \"std %2,%0\";
3518   else
3519     return \"std %2,%3\;ldx %3,%0\";
3520 }"
3521   [(set_attr "type" "fp")
3522    (set_attr "length" "3")])
3523
3524 ;; ??? Ideally, these are what we would like to use.
3525
3526 (define_insn "fix_truncsfdi2_sp64"
3527   [(set (match_operand:DI 0 "register_operand" "=e")
3528         (fix:DI (fix:SF (match_operand:SF 1 "register_operand" "f"))))]
3529   "0 && TARGET_ARCH64 && TARGET_FPU"
3530   "fstox %1,%0"
3531   [(set_attr "type" "fp")])
3532
3533 (define_insn "fix_truncdfdi2_sp64"
3534   [(set (match_operand:DI 0 "register_operand" "=e")
3535         (fix:DI (fix:DF (match_operand:DF 1 "register_operand" "e"))))]
3536   "0 && TARGET_ARCH64 && TARGET_FPU"
3537   "fdtox %1,%0"
3538   [(set_attr "type" "fp")])
3539
3540 (define_insn "fix_trunctfdi2_sp64"
3541   [(set (match_operand:DI 0 "register_operand" "=e")
3542         (fix:DI (fix:TF (match_operand:TF 1 "register_operand" "e"))))]
3543   "0 && TARGET_ARCH64 && TARGET_FPU && TARGET_HARD_QUAD"
3544   "fqtox %1,%0"
3545   [(set_attr "type" "fp")])
3546 \f
3547 ;;- arithmetic instructions
3548
3549 (define_expand "adddi3"
3550   [(set (match_operand:DI 0 "register_operand" "=r")
3551         (plus:DI (match_operand:DI 1 "arith_double_operand" "%r")
3552                  (match_operand:DI 2 "arith_double_operand" "rHI")))]
3553   ""
3554   "
3555 {
3556   if (! TARGET_ARCH64)
3557     {
3558       emit_insn (gen_rtx (PARALLEL, VOIDmode, gen_rtvec (2,
3559                           gen_rtx (SET, VOIDmode, operands[0],
3560                                    gen_rtx (PLUS, DImode, operands[1],
3561                                                   operands[2])),
3562                           gen_rtx (CLOBBER, VOIDmode,
3563                                    gen_rtx (REG, SImode, SPARC_ICC_REG)))));
3564       DONE;
3565     }
3566 }")
3567
3568 (define_insn "*adddi3_sp32"
3569   [(set (match_operand:DI 0 "register_operand" "=r")
3570         (plus:DI (match_operand:DI 1 "arith_double_operand" "%r")
3571                  (match_operand:DI 2 "arith_double_operand" "rHI")))
3572    (clobber (reg:SI 100))]
3573   "! TARGET_ARCH64"
3574   "*
3575 {
3576   rtx op2 = operands[2];
3577
3578   if (GET_CODE (op2) == CONST_INT
3579       || GET_CODE (op2) == CONST_DOUBLE)
3580     {
3581       rtx xoperands[4];
3582       xoperands[0] = operands[0];
3583       xoperands[1] = operands[1];
3584       if (WORDS_BIG_ENDIAN)
3585         split_double (op2, &xoperands[2], &xoperands[3]);
3586       else
3587         split_double (op2, &xoperands[3], &xoperands[2]);
3588       if (xoperands[3] == const0_rtx && xoperands[0] == xoperands[1])
3589         output_asm_insn (\"add %H1,%2,%H0\", xoperands);
3590       else
3591         output_asm_insn (\"addcc %L1,%3,%L0\;addx %H1,%2,%H0\", xoperands);
3592       return \"\";
3593     }
3594   return \"addcc %L1,%L2,%L0\;addx %H1,%H2,%H0\";
3595 }"
3596   [(set_attr "length" "2")])
3597
3598 (define_insn "*adddi3_sp64"
3599   [(set (match_operand:DI 0 "register_operand" "=r")
3600         (plus:DI (match_operand:DI 1 "arith_double_operand" "%r")
3601                  (match_operand:DI 2 "arith_double_operand" "rHI")))]
3602   "TARGET_ARCH64"
3603   "add %1,%2,%0")
3604
3605 (define_insn "addsi3"
3606   [(set (match_operand:SI 0 "register_operand" "=r")
3607         (plus:SI (match_operand:SI 1 "arith_operand" "%r")
3608                  (match_operand:SI 2 "arith_operand" "rI")))]
3609   ""
3610   "add %1,%2,%0"
3611   [(set_attr "type" "ialu")])
3612
3613 (define_insn "*cmp_cc_plus"
3614   [(set (reg:CC_NOOV 100)
3615         (compare:CC_NOOV (plus:SI (match_operand:SI 0 "arith_operand" "%r")
3616                                   (match_operand:SI 1 "arith_operand" "rI"))
3617                          (const_int 0)))]
3618   ""
3619   "addcc %0,%1,%%g0"
3620   [(set_attr "type" "compare")])
3621
3622 (define_insn "*cmp_ccx_plus"
3623   [(set (reg:CCX_NOOV 100)
3624         (compare:CCX_NOOV (plus:DI (match_operand:DI 0 "arith_double_operand" "%r")
3625                                    (match_operand:DI 1 "arith_double_operand" "rHI"))
3626                           (const_int 0)))]
3627   "TARGET_ARCH64"
3628   "addcc %0,%1,%%g0"
3629   [(set_attr "type" "compare")])
3630
3631 (define_insn "*cmp_cc_plus_set"
3632   [(set (reg:CC_NOOV 100)
3633         (compare:CC_NOOV (plus:SI (match_operand:SI 1 "arith_operand" "%r")
3634                                   (match_operand:SI 2 "arith_operand" "rI"))
3635                          (const_int 0)))
3636    (set (match_operand:SI 0 "register_operand" "=r")
3637         (plus:SI (match_dup 1) (match_dup 2)))]
3638   ""
3639   "addcc %1,%2,%0")
3640
3641 (define_insn "*cmp_ccx_plus_set"
3642   [(set (reg:CCX_NOOV 100)
3643         (compare:CCX_NOOV (plus:DI (match_operand:DI 1 "arith_double_operand" "%r")
3644                                    (match_operand:DI 2 "arith_double_operand" "rHI"))
3645                           (const_int 0)))
3646    (set (match_operand:DI 0 "register_operand" "=r")
3647         (plus:DI (match_dup 1) (match_dup 2)))]
3648   "TARGET_ARCH64"
3649   "addcc %1,%2,%0")
3650
3651 (define_expand "subdi3"
3652   [(set (match_operand:DI 0 "register_operand" "=r")
3653         (minus:DI (match_operand:DI 1 "register_operand" "r")
3654                   (match_operand:DI 2 "arith_double_operand" "rHI")))]
3655   ""
3656   "
3657 {
3658   if (! TARGET_ARCH64)
3659     {
3660       emit_insn (gen_rtx (PARALLEL, VOIDmode, gen_rtvec (2,
3661                           gen_rtx (SET, VOIDmode, operands[0],
3662                                    gen_rtx (MINUS, DImode, operands[1],
3663                                                    operands[2])),
3664                           gen_rtx (CLOBBER, VOIDmode,
3665                                    gen_rtx (REG, SImode, SPARC_ICC_REG)))));
3666       DONE;
3667     }
3668 }")
3669
3670 (define_insn "*subdi3_sp32"
3671   [(set (match_operand:DI 0 "register_operand" "=r")
3672         (minus:DI (match_operand:DI 1 "register_operand" "r")
3673                   (match_operand:DI 2 "arith_double_operand" "rHI")))
3674    (clobber (reg:SI 100))]
3675   "! TARGET_ARCH64"
3676   "*
3677 {
3678   rtx op2 = operands[2];
3679
3680   if (GET_CODE (op2) == CONST_INT
3681       || GET_CODE (op2) == CONST_DOUBLE)
3682     {
3683       rtx xoperands[4];
3684       xoperands[0] = operands[0];
3685       xoperands[1] = operands[1];
3686       if (WORDS_BIG_ENDIAN)
3687         split_double (op2, &xoperands[2], &xoperands[3]);
3688       else
3689         split_double (op2, &xoperands[3], &xoperands[2]);
3690       if (xoperands[3] == const0_rtx && xoperands[0] == xoperands[1])
3691         output_asm_insn (\"sub %H1,%2,%H0\", xoperands);
3692       else
3693         output_asm_insn (\"subcc %L1,%3,%L0\;subx %H1,%2,%H0\", xoperands);
3694       return \"\";
3695     }
3696   return \"subcc %L1,%L2,%L0\;subx %H1,%H2,%H0\";
3697 }"
3698   [(set_attr "length" "2")])
3699
3700 (define_insn "*subdi3_sp64"
3701   [(set (match_operand:DI 0 "register_operand" "=r")
3702         (minus:DI (match_operand:DI 1 "register_operand" "r")
3703                   (match_operand:DI 2 "arith_double_operand" "rHI")))]
3704   "TARGET_ARCH64"
3705   "sub %1,%2,%0")
3706
3707 (define_insn "subsi3"
3708   [(set (match_operand:SI 0 "register_operand" "=r")
3709         (minus:SI (match_operand:SI 1 "register_operand" "r")
3710                   (match_operand:SI 2 "arith_operand" "rI")))]
3711   ""
3712   "sub %1,%2,%0"
3713   [(set_attr "type" "ialu")])
3714
3715 (define_insn "*cmp_minus_cc"
3716   [(set (reg:CC_NOOV 100)
3717         (compare:CC_NOOV (minus:SI (match_operand:SI 0 "register_operand" "r")
3718                                    (match_operand:SI 1 "arith_operand" "rI"))
3719                          (const_int 0)))]
3720   ""
3721   "subcc %0,%1,%%g0"
3722   [(set_attr "type" "compare")])
3723
3724 (define_insn "*cmp_minus_ccx"
3725   [(set (reg:CCX_NOOV 100)
3726         (compare:CCX_NOOV (minus:DI (match_operand:DI 0 "register_operand" "r")
3727                                     (match_operand:DI 1 "arith_double_operand" "rHI"))
3728                           (const_int 0)))]
3729   "TARGET_ARCH64"
3730   "subcc %0,%1,%%g0"
3731   [(set_attr "type" "compare")])
3732
3733 (define_insn "*cmp_minus_cc_set"
3734   [(set (reg:CC_NOOV 100)
3735         (compare:CC_NOOV (minus:SI (match_operand:SI 1 "register_operand" "r")
3736                                    (match_operand:SI 2 "arith_operand" "rI"))
3737                          (const_int 0)))
3738    (set (match_operand:SI 0 "register_operand" "=r")
3739         (minus:SI (match_dup 1) (match_dup 2)))]
3740   ""
3741   "subcc %1,%2,%0")
3742
3743 (define_insn "*cmp_minus_ccx_set"
3744   [(set (reg:CCX_NOOV 100)
3745         (compare:CCX_NOOV (minus:DI (match_operand:DI 1 "register_operand" "r")
3746                                     (match_operand:DI 2 "arith_double_operand" "rHI"))
3747                           (const_int 0)))
3748    (set (match_operand:DI 0 "register_operand" "=r")
3749         (minus:DI (match_dup 1) (match_dup 2)))]
3750   "TARGET_ARCH64"
3751   "subcc %1,%2,%0")
3752 \f
3753 ;; Integer Multiply/Divide.
3754
3755 ;; The 32 bit multiply/divide instructions are deprecated on v9 and shouldn't
3756 ;; we used.  We still use them in 32 bit v9 compilers.
3757 ;; The 64 bit v9 compiler will (/should) widen the args and use muldi3.
3758
3759 (define_insn "mulsi3"
3760   [(set (match_operand:SI 0 "register_operand" "=r")
3761         (mult:SI (match_operand:SI 1 "arith_operand" "%r")
3762                  (match_operand:SI 2 "arith_operand" "rI")))]
3763   "TARGET_V8 || TARGET_SPARCLITE || TARGET_SPARCLET || TARGET_DEPRECATED_V8_INSNS"
3764   "smul %1,%2,%0"
3765   [(set_attr "type" "imul")])
3766
3767 (define_insn "muldi3"
3768   [(set (match_operand:DI 0 "register_operand" "=r")
3769         (mult:DI (match_operand:DI 1 "arith_double_operand" "%r")
3770                  (match_operand:DI 2 "arith_double_operand" "rHI")))]
3771   "TARGET_ARCH64"
3772   "mulx %1,%2,%0")
3773
3774 ;; It is not known whether this will match.
3775
3776 (define_insn "*cmp_mul_set"
3777   [(set (match_operand:SI 0 "register_operand" "=r")
3778         (mult:SI (match_operand:SI 1 "arith_operand" "%r")
3779                  (match_operand:SI 2 "arith_operand" "rI")))
3780    (set (reg:CC_NOOV 100)
3781         (compare:CC_NOOV (mult:SI (match_dup 1) (match_dup 2))
3782                          (const_int 0)))]
3783   "TARGET_V8 || TARGET_SPARCLITE || TARGET_DEPRECATED_V8_INSNS"
3784   "smulcc %1,%2,%0"
3785   [(set_attr "type" "imul")])
3786
3787 (define_expand "mulsidi3"
3788   [(set (match_operand:DI 0 "register_operand" "")
3789         (mult:DI (sign_extend:DI (match_operand:SI 1 "register_operand" ""))
3790                  (sign_extend:DI (match_operand:SI 2 "arith_operand" ""))))]
3791   "TARGET_V8 || TARGET_SPARCLITE || TARGET_SPARCLET || TARGET_DEPRECATED_V8_INSNS"
3792   "
3793 {
3794   if (CONSTANT_P (operands[2]))
3795     {
3796       emit_insn (gen_const_mulsidi3 (operands[0], operands[1], operands[2]));
3797       DONE;
3798     }
3799 }")
3800
3801 (define_insn "*mulsidi3_sp32"
3802   [(set (match_operand:DI 0 "register_operand" "=r")
3803         (mult:DI (sign_extend:DI (match_operand:SI 1 "register_operand" "r"))
3804                  (sign_extend:DI (match_operand:SI 2 "register_operand" "r"))))]
3805   "TARGET_V8 || TARGET_SPARCLITE || TARGET_SPARCLET || TARGET_DEPRECATED_V8_INSNS"
3806   "*
3807 {
3808   return TARGET_SPARCLET ? \"smuld %1,%2,%L0\" : \"smul %1,%2,%L0\;rd %%y,%H0\";
3809 }"
3810   [(set (attr "length")
3811         (if_then_else (eq_attr "isa" "sparclet")
3812                       (const_int 1) (const_int 2)))])
3813
3814 ;; Extra pattern, because sign_extend of a constant isn't valid.
3815
3816 (define_insn "const_mulsidi3"
3817   [(set (match_operand:DI 0 "register_operand" "=r")
3818         (mult:DI (sign_extend:DI (match_operand:SI 1 "register_operand" "r"))
3819                  (match_operand:SI 2 "small_int" "I")))]
3820   "TARGET_V8 || TARGET_SPARCLITE || TARGET_SPARCLET || TARGET_DEPRECATED_V8_INSNS"
3821   "*
3822 {
3823   return TARGET_SPARCLET ? \"smuld %1,%2,%L0\" : \"smul %1,%2,%L0\;rd %%y,%H0\";
3824 }"
3825   [(set (attr "length")
3826         (if_then_else (eq_attr "isa" "sparclet")
3827                       (const_int 1) (const_int 2)))])
3828
3829 (define_expand "smulsi3_highpart"
3830   [(set (match_operand:SI 0 "register_operand" "")
3831         (truncate:SI
3832          (lshiftrt:DI (mult:DI (sign_extend:DI (match_operand:SI 1 "register_operand" ""))
3833                                (sign_extend:DI (match_operand:SI 2 "arith_operand" "")))
3834                       (const_int 32))))]
3835   "TARGET_V8 || TARGET_SPARCLITE || TARGET_SPARCLET || TARGET_DEPRECATED_V8_INSNS"
3836   "
3837 {
3838   if (CONSTANT_P (operands[2]))
3839     {
3840       emit_insn (gen_const_smulsi3_highpart (operands[0], operands[1], operands[2]));
3841       DONE;
3842     }
3843 }")
3844
3845 (define_insn "*smulsidi3_highpart_sp32"
3846   [(set (match_operand:SI 0 "register_operand" "=r")
3847         (truncate:SI
3848          (lshiftrt:DI (mult:DI (sign_extend:DI (match_operand:SI 1 "register_operand" "r"))
3849                                (sign_extend:DI (match_operand:SI 2 "register_operand" "r")))
3850                       (const_int 32))))]
3851   "TARGET_V8 || TARGET_SPARCLITE || TARGET_SPARCLET || TARGET_DEPRECATED_V8_INSNS"
3852   "smul %1,%2,%%g0\;rd %%y,%0"
3853   [(set_attr "length" "2")])
3854
3855 (define_insn "const_smulsi3_highpart"
3856   [(set (match_operand:SI 0 "register_operand" "=r")
3857         (truncate:SI
3858          (lshiftrt:DI (mult:DI (sign_extend:DI (match_operand:SI 1 "register_operand" "r"))
3859                                (match_operand:SI 2 "register_operand" "r"))
3860                       (const_int 32))))]
3861   "TARGET_V8 || TARGET_SPARCLITE || TARGET_SPARCLET || TARGET_DEPRECATED_V8_INSNS"
3862   "smul %1,%2,%%g0\;rd %%y,%0"
3863   [(set_attr "length" "2")])
3864
3865 (define_expand "umulsidi3"
3866   [(set (match_operand:DI 0 "register_operand" "")
3867         (mult:DI (zero_extend:DI (match_operand:SI 1 "register_operand" ""))
3868                  (zero_extend:DI (match_operand:SI 2 "uns_arith_operand" ""))))]
3869   "TARGET_V8 || TARGET_SPARCLITE || TARGET_SPARCLET || TARGET_DEPRECATED_V8_INSNS"
3870   "
3871 {
3872   if (CONSTANT_P (operands[2]))
3873     {
3874       emit_insn (gen_const_umulsidi3 (operands[0], operands[1], operands[2]));
3875       DONE;
3876     }
3877 }")
3878
3879 (define_insn "*umulsidi3_sp32"
3880   [(set (match_operand:DI 0 "register_operand" "=r")
3881         (mult:DI (zero_extend:DI (match_operand:SI 1 "register_operand" "r"))
3882                  (zero_extend:DI (match_operand:SI 2 "register_operand" "r"))))]
3883   "TARGET_V8 || TARGET_SPARCLITE || TARGET_SPARCLET || TARGET_DEPRECATED_V8_INSNS"
3884   "*
3885 {
3886   return TARGET_SPARCLET ? \"umuld %1,%2,%L0\" : \"umul %1,%2,%L0\;rd %%y,%H0\";
3887 }"
3888   [(set (attr "length")
3889         (if_then_else (eq_attr "isa" "sparclet")
3890                       (const_int 1) (const_int 2)))])
3891
3892 ;; Extra pattern, because sign_extend of a constant isn't valid.
3893
3894 (define_insn "const_umulsidi3"
3895   [(set (match_operand:DI 0 "register_operand" "=r")
3896         (mult:DI (zero_extend:DI (match_operand:SI 1 "register_operand" "r"))
3897                  (match_operand:SI 2 "uns_small_int" "")))]
3898   "TARGET_V8 || TARGET_SPARCLITE || TARGET_SPARCLET || TARGET_DEPRECATED_V8_INSNS"
3899   "*
3900 {
3901   return TARGET_SPARCLET ? \"umuld %1,%2,%L0\" : \"umul %1,%2,%L0\;rd %%y,%H0\";
3902 }"
3903   [(set (attr "length")
3904         (if_then_else (eq_attr "isa" "sparclet")
3905                       (const_int 1) (const_int 2)))])
3906
3907 (define_expand "umulsi3_highpart"
3908   [(set (match_operand:SI 0 "register_operand" "")
3909         (truncate:SI
3910          (lshiftrt:DI (mult:DI (zero_extend:DI (match_operand:SI 1 "register_operand" ""))
3911                                (zero_extend:DI (match_operand:SI 2 "uns_arith_operand" "")))
3912                       (const_int 32))))]
3913   "TARGET_V8 || TARGET_SPARCLITE || TARGET_SPARCLET || TARGET_DEPRECATED_V8_INSNS"
3914   "
3915 {
3916   if (CONSTANT_P (operands[2]))
3917     {
3918       emit_insn (gen_const_umulsi3_highpart (operands[0], operands[1], operands[2]));
3919       DONE;
3920     }
3921 }")
3922
3923 (define_insn "*umulsidi3_highpart_sp32"
3924   [(set (match_operand:SI 0 "register_operand" "=r")
3925         (truncate:SI
3926          (lshiftrt:DI (mult:DI (zero_extend:DI (match_operand:SI 1 "register_operand" "r"))
3927                                (zero_extend:DI (match_operand:SI 2 "register_operand" "r")))
3928                       (const_int 32))))]
3929   "TARGET_V8 || TARGET_SPARCLITE || TARGET_SPARCLET || TARGET_DEPRECATED_V8_INSNS"
3930   "umul %1,%2,%%g0\;rd %%y,%0"
3931   [(set_attr "length" "2")])
3932
3933 (define_insn "const_umulsi3_highpart"
3934   [(set (match_operand:SI 0 "register_operand" "=r")
3935         (truncate:SI
3936          (lshiftrt:DI (mult:DI (zero_extend:DI (match_operand:SI 1 "register_operand" "r"))
3937                                (match_operand:SI 2 "uns_small_int" ""))
3938                       (const_int 32))))]
3939   "TARGET_V8 || TARGET_SPARCLITE || TARGET_SPARCLET || TARGET_DEPRECATED_V8_INSNS"
3940   "umul %1,%2,%%g0\;rd %%y,%0"
3941   [(set_attr "length" "2")])
3942
3943 ;; The v8 architecture specifies that there must be 3 instructions between
3944 ;; a y register write and a use of it for correct results.
3945
3946 (define_insn "divsi3"
3947   [(set (match_operand:SI 0 "register_operand" "=r")
3948         (div:SI (match_operand:SI 1 "register_operand" "r")
3949                 (match_operand:SI 2 "arith_operand" "rI")))
3950    (clobber (match_scratch:SI 3 "=&r"))]
3951   "TARGET_V8 || TARGET_DEPRECATED_V8_INSNS"
3952   "*
3953 {
3954   if (TARGET_V9)
3955     return \"sra %1,31,%3\;wr %%g0,%3,%%y\;sdiv %1,%2,%0\";
3956   else
3957     return \"sra %1,31,%3\;wr %%g0,%3,%%y\;nop\;nop\;nop\;sdiv %1,%2,%0\";
3958 }"
3959   [(set (attr "length")
3960         (if_then_else (eq_attr "isa" "v9")
3961                       (const_int 3) (const_int 6)))])
3962
3963 (define_insn "divdi3"
3964   [(set (match_operand:DI 0 "register_operand" "=r")
3965         (div:DI (match_operand:DI 1 "register_operand" "r")
3966                 (match_operand:DI 2 "arith_double_operand" "rHI")))]
3967   "TARGET_ARCH64"
3968   "sdivx %1,%2,%0")
3969
3970 ;; It is not known whether this will match.
3971
3972 (define_insn "*cmp_sdiv_cc_set"
3973   [(set (match_operand:SI 0 "register_operand" "=r")
3974         (div:SI (match_operand:SI 1 "register_operand" "r")
3975                 (match_operand:SI 2 "arith_operand" "rI")))
3976    (set (reg:CC 100)
3977         (compare:CC (div:SI (match_dup 1) (match_dup 2))
3978                     (const_int 0)))
3979    (clobber (match_scratch:SI 3 "=&r"))]
3980   "TARGET_V8 || TARGET_DEPRECATED_V8_INSNS"
3981   "*
3982 {
3983   if (TARGET_V9)
3984     return \"sra %1,31,%3\;wr %%g0,%3,%%y\;sdivcc %1,%2,%0\";
3985   else
3986     return \"sra %1,31,%3\;wr %%g0,%3,%%y\;nop\;nop\;nop\;sdivcc %1,%2,%0\";
3987 }"
3988   [(set (attr "length")
3989         (if_then_else (eq_attr "isa" "v9")
3990                       (const_int 3) (const_int 6)))])
3991
3992 (define_insn "udivsi3"
3993   [(set (match_operand:SI 0 "register_operand" "=r")
3994         (udiv:SI (match_operand:SI 1 "register_operand" "r")
3995                  (match_operand:SI 2 "arith_operand" "rI")))]
3996   "TARGET_V8 || TARGET_DEPRECATED_V8_INSNS"
3997   "*
3998 {
3999   if (TARGET_V9)
4000     return \"wr %%g0,%%g0,%%y\;udiv %1,%2,%0\";
4001   else
4002     return \"wr %%g0,%%g0,%%y\;nop\;nop\;nop\;udiv %1,%2,%0\";
4003 }"
4004   [(set (attr "length")
4005         (if_then_else (eq_attr "isa" "v9")
4006                       (const_int 2) (const_int 5)))])
4007
4008 (define_insn "udivdi3"
4009   [(set (match_operand:DI 0 "register_operand" "=r")
4010         (udiv:DI (match_operand:DI 1 "register_operand" "r")
4011                  (match_operand:DI 2 "arith_double_operand" "rHI")))]
4012   "TARGET_ARCH64"
4013   "udivx %1,%2,%0")
4014
4015 ;; It is not known whether this will match.
4016
4017 (define_insn "*cmp_udiv_cc_set"
4018   [(set (match_operand:SI 0 "register_operand" "=r")
4019         (udiv:SI (match_operand:SI 1 "register_operand" "r")
4020                 (match_operand:SI 2 "arith_operand" "rI")))
4021    (set (reg:CC 100)
4022         (compare:CC (udiv:SI (match_dup 1) (match_dup 2))
4023                     (const_int 0)))]
4024   "TARGET_V8 || TARGET_DEPRECATED_V8_INSNS"
4025   "*
4026 {
4027   if (TARGET_V9)
4028     return \"wr %%g0,%%g0,%%y\;udivcc %1,%2,%0\";
4029   else
4030     return \"wr %%g0,%%g0,%%y\;nop\;nop\;nop\;udivcc %1,%2,%0\";
4031 }"
4032   [(set (attr "length")
4033         (if_then_else (eq_attr "isa" "v9")
4034                       (const_int 2) (const_int 5)))])
4035
4036 ; sparclet multiply/accumulate insns
4037
4038 (define_insn "*smacsi"
4039   [(set (match_operand:SI 0 "register_operand" "=r")
4040         (plus:SI (mult:SI (match_operand:SI 1 "register_operand" "%r")
4041                           (match_operand:SI 2 "arith_operand" "rI"))
4042                  (match_operand:SI 3 "register_operand" "0")))]
4043   "TARGET_SPARCLET"
4044   "smac %1,%2,%0"
4045   [(set_attr "type" "imul")])
4046
4047 (define_insn "*smacdi"
4048   [(set (match_operand:DI 0 "register_operand" "=r")
4049         (plus:DI (mult:DI (sign_extend:DI
4050                            (match_operand:SI 1 "register_operand" "%r"))
4051                           (sign_extend:DI
4052                            (match_operand:SI 2 "register_operand" "r")))
4053                  (match_operand:DI 3 "register_operand" "0")))]
4054   "TARGET_SPARCLET"
4055   "smacd %1,%2,%L0"
4056   [(set_attr "type" "imul")])
4057
4058 (define_insn "*umacdi"
4059   [(set (match_operand:DI 0 "register_operand" "=r")
4060         (plus:DI (mult:DI (zero_extend:DI
4061                            (match_operand:SI 1 "register_operand" "%r"))
4062                           (zero_extend:DI
4063                            (match_operand:SI 2 "register_operand" "r")))
4064                  (match_operand:DI 3 "register_operand" "0")))]
4065   "TARGET_SPARCLET"
4066   "umacd %1,%2,%L0"
4067   [(set_attr "type" "imul")])
4068 \f
4069 ;;- Boolean instructions
4070 ;; We define DImode `and' so with DImode `not' we can get
4071 ;; DImode `andn'.  Other combinations are possible.
4072
4073 (define_expand "anddi3"
4074   [(set (match_operand:DI 0 "register_operand" "")
4075         (and:DI (match_operand:DI 1 "arith_double_operand" "")
4076                 (match_operand:DI 2 "arith_double_operand" "")))]
4077   ""
4078   "")
4079
4080 (define_insn "*anddi3_sp32"
4081   [(set (match_operand:DI 0 "register_operand" "=r")
4082         (and:DI (match_operand:DI 1 "arith_double_operand" "%r")
4083                 (match_operand:DI 2 "arith_double_operand" "rHI")))]
4084   "! TARGET_ARCH64"
4085   "*
4086 {
4087   rtx op2 = operands[2];
4088
4089   if (GET_CODE (op2) == CONST_INT
4090       || GET_CODE (op2) == CONST_DOUBLE)
4091     {
4092       rtx xoperands[4];
4093       xoperands[0] = operands[0];
4094       xoperands[1] = operands[1];
4095       if (WORDS_BIG_ENDIAN)
4096         split_double (op2, &xoperands[2], &xoperands[3]);
4097       else
4098         split_double (op2, &xoperands[3], &xoperands[2]);
4099       output_asm_insn (\"and %L1,%3,%L0\;and %H1,%2,%H0\", xoperands);
4100       return \"\";
4101     }
4102   return \"and %1,%2,%0\;and %R1,%R2,%R0\";
4103 }"
4104   [(set_attr "length" "2")])
4105
4106 (define_insn "*anddi3_sp64"
4107   [(set (match_operand:DI 0 "register_operand" "=r")
4108         (and:DI (match_operand:DI 1 "arith_double_operand" "%r")
4109                 (match_operand:DI 2 "arith_double_operand" "rHI")))]
4110   "TARGET_ARCH64"
4111   "and %1,%2,%0")
4112
4113 (define_insn "andsi3"
4114   [(set (match_operand:SI 0 "register_operand" "=r")
4115         (and:SI (match_operand:SI 1 "arith_operand" "%r")
4116                 (match_operand:SI 2 "arith_operand" "rI")))]
4117   ""
4118   "and %1,%2,%0"
4119   [(set_attr "type" "ialu")])
4120
4121 (define_split
4122   [(set (match_operand:SI 0 "register_operand" "")
4123         (and:SI (match_operand:SI 1 "register_operand" "")
4124                 (match_operand:SI 2 "" "")))
4125    (clobber (match_operand:SI 3 "register_operand" ""))]
4126   "GET_CODE (operands[2]) == CONST_INT
4127    && !SMALL_INT (operands[2])
4128    && (INTVAL (operands[2]) & 0x3ff) == 0x3ff"
4129   [(set (match_dup 3) (match_dup 4))
4130    (set (match_dup 0) (and:SI (not:SI (match_dup 3)) (match_dup 1)))]
4131   "
4132 {
4133   operands[4] = GEN_INT (~INTVAL (operands[2]));
4134 }")
4135
4136 (define_insn "*and_not_di_sp32"
4137   [(set (match_operand:DI 0 "register_operand" "=r")
4138         (and:DI (not:DI (match_operand:DI 1 "register_operand" "r"))
4139                 (match_operand:DI 2 "register_operand" "r")))]
4140   "! TARGET_ARCH64"
4141   "andn %2,%1,%0\;andn %R2,%R1,%R0"
4142   [(set_attr "length" "2")])
4143
4144 (define_insn "*and_not_di_sp64"
4145   [(set (match_operand:DI 0 "register_operand" "=r")
4146         (and:DI (not:DI (match_operand:DI 1 "register_operand" "r"))
4147                 (match_operand:DI 2 "register_operand" "r")))]
4148   "TARGET_ARCH64"
4149   "andn %2,%1,%0")
4150
4151 (define_insn "*and_not_si"
4152   [(set (match_operand:SI 0 "register_operand" "=r")
4153         (and:SI (not:SI (match_operand:SI 1 "register_operand" "r"))
4154                 (match_operand:SI 2 "register_operand" "r")))]
4155   ""
4156   "andn %2,%1,%0"
4157   [(set_attr "type" "ialu")])
4158
4159 (define_expand "iordi3"
4160   [(set (match_operand:DI 0 "register_operand" "")
4161         (ior:DI (match_operand:DI 1 "arith_double_operand" "")
4162                 (match_operand:DI 2 "arith_double_operand" "")))]
4163   ""
4164   "")
4165
4166 (define_insn "*iordi3_sp32"
4167   [(set (match_operand:DI 0 "register_operand" "=r")
4168         (ior:DI (match_operand:DI 1 "arith_double_operand" "%r")
4169                 (match_operand:DI 2 "arith_double_operand" "rHI")))]
4170   "! TARGET_ARCH64"
4171   "*
4172 {
4173   rtx op2 = operands[2];
4174
4175   if (GET_CODE (op2) == CONST_INT
4176       || GET_CODE (op2) == CONST_DOUBLE)
4177     {
4178       rtx xoperands[4];
4179       xoperands[0] = operands[0];
4180       xoperands[1] = operands[1];
4181       if (WORDS_BIG_ENDIAN)
4182         split_double (op2, &xoperands[2], &xoperands[3]);
4183       else
4184         split_double (op2, &xoperands[3], &xoperands[2]);
4185       output_asm_insn (\"or %L1,%3,%L0\;or %H1,%2,%H0\", xoperands);
4186       return \"\";
4187     }
4188   return \"or %1,%2,%0\;or %R1,%R2,%R0\";
4189 }"
4190   [(set_attr "length" "2")])
4191
4192 (define_insn "*iordi3_sp64"
4193   [(set (match_operand:DI 0 "register_operand" "=r")
4194         (ior:DI (match_operand:DI 1 "arith_double_operand" "%r")
4195                 (match_operand:DI 2 "arith_double_operand" "rHI")))]
4196   "TARGET_ARCH64"
4197   "or %1,%2,%0")
4198
4199 (define_insn "iorsi3"
4200   [(set (match_operand:SI 0 "register_operand" "=r")
4201         (ior:SI (match_operand:SI 1 "arith_operand" "%r")
4202                 (match_operand:SI 2 "arith_operand" "rI")))]
4203   ""
4204   "or %1,%2,%0"
4205   [(set_attr "type" "ialu")])
4206
4207 (define_split
4208   [(set (match_operand:SI 0 "register_operand" "")
4209         (ior:SI (match_operand:SI 1 "register_operand" "")
4210                 (match_operand:SI 2 "" "")))
4211    (clobber (match_operand:SI 3 "register_operand" ""))]
4212   "GET_CODE (operands[2]) == CONST_INT
4213    && !SMALL_INT (operands[2])
4214    && (INTVAL (operands[2]) & 0x3ff) == 0x3ff"
4215   [(set (match_dup 3) (match_dup 4))
4216    (set (match_dup 0) (ior:SI (not:SI (match_dup 3)) (match_dup 1)))]
4217   "
4218 {
4219   operands[4] = GEN_INT (~INTVAL (operands[2]));
4220 }")
4221
4222 (define_insn "*or_not_di_sp32"
4223   [(set (match_operand:DI 0 "register_operand" "=r")
4224         (ior:DI (not:DI (match_operand:DI 1 "register_operand" "r"))
4225                 (match_operand:DI 2 "register_operand" "r")))]
4226   "! TARGET_ARCH64"
4227   "orn %2,%1,%0\;orn %R2,%R1,%R0"
4228   [(set_attr "length" "2")])
4229
4230 (define_insn "*or_not_di_sp64"
4231   [(set (match_operand:DI 0 "register_operand" "=r")
4232         (ior:DI (not:DI (match_operand:DI 1 "register_operand" "r"))
4233                 (match_operand:DI 2 "register_operand" "r")))]
4234   "TARGET_ARCH64"
4235   "orn %2,%1,%0")
4236
4237 (define_insn "*or_not_si"
4238   [(set (match_operand:SI 0 "register_operand" "=r")
4239         (ior:SI (not:SI (match_operand:SI 1 "register_operand" "r"))
4240                 (match_operand:SI 2 "register_operand" "r")))]
4241   ""
4242   "orn %2,%1,%0"
4243   [(set_attr "type" "ialu")])
4244
4245 (define_expand "xordi3"
4246   [(set (match_operand:DI 0 "register_operand" "")
4247         (xor:DI (match_operand:DI 1 "arith_double_operand" "")
4248                 (match_operand:DI 2 "arith_double_operand" "")))]
4249   ""
4250   "")
4251
4252 (define_insn "*xorsi3_sp32"
4253   [(set (match_operand:DI 0 "register_operand" "=r")
4254         (xor:DI (match_operand:DI 1 "arith_double_operand" "%r")
4255                 (match_operand:DI 2 "arith_double_operand" "rHI")))]
4256   "! TARGET_ARCH64"
4257   "*
4258 {
4259   rtx op2 = operands[2];
4260
4261   if (GET_CODE (op2) == CONST_INT
4262       || GET_CODE (op2) == CONST_DOUBLE)
4263     {
4264       rtx xoperands[4];
4265       xoperands[0] = operands[0];
4266       xoperands[1] = operands[1];
4267       if (WORDS_BIG_ENDIAN)
4268         split_double (op2, &xoperands[2], &xoperands[3]);
4269       else
4270         split_double (op2, &xoperands[3], &xoperands[2]);
4271       output_asm_insn (\"xor %L1,%3,%L0\;xor %H1,%2,%H0\", xoperands);
4272       return \"\";
4273     }
4274   return \"xor %1,%2,%0\;xor %R1,%R2,%R0\";
4275 }"
4276   [(set_attr "length" "2")])
4277
4278 (define_insn "*xordi3_sp64"
4279   [(set (match_operand:DI 0 "register_operand" "=r")
4280         (xor:DI (match_operand:DI 1 "arith_double_operand" "%rJ")
4281                 (match_operand:DI 2 "arith_double_operand" "rHI")))]
4282   "TARGET_ARCH64"
4283   "xor %r1,%2,%0")
4284
4285 (define_insn "xorsi3"
4286   [(set (match_operand:SI 0 "register_operand" "=r")
4287         (xor:SI (match_operand:SI 1 "arith_operand" "%rJ")
4288                 (match_operand:SI 2 "arith_operand" "rI")))]
4289   ""
4290   "xor %r1,%2,%0"
4291   [(set_attr "type" "ialu")])
4292
4293 (define_split
4294   [(set (match_operand:SI 0 "register_operand" "")
4295         (xor:SI (match_operand:SI 1 "register_operand" "")
4296                 (match_operand:SI 2 "" "")))
4297    (clobber (match_operand:SI 3 "register_operand" ""))]
4298   "GET_CODE (operands[2]) == CONST_INT
4299    && !SMALL_INT (operands[2])
4300    && (INTVAL (operands[2]) & 0x3ff) == 0x3ff"
4301   [(set (match_dup 3) (match_dup 4))
4302    (set (match_dup 0) (not:SI (xor:SI (match_dup 3) (match_dup 1))))]
4303   "
4304 {
4305   operands[4] = GEN_INT (~INTVAL (operands[2]));
4306 }")
4307
4308 (define_split
4309   [(set (match_operand:SI 0 "register_operand" "")
4310         (not:SI (xor:SI (match_operand:SI 1 "register_operand" "")
4311                         (match_operand:SI 2 "" ""))))
4312    (clobber (match_operand:SI 3 "register_operand" ""))]
4313   "GET_CODE (operands[2]) == CONST_INT
4314    && !SMALL_INT (operands[2])
4315    && (INTVAL (operands[2]) & 0x3ff) == 0x3ff"
4316   [(set (match_dup 3) (match_dup 4))
4317    (set (match_dup 0) (xor:SI (match_dup 3) (match_dup 1)))]
4318   "
4319 {
4320   operands[4] = GEN_INT (~INTVAL (operands[2]));
4321 }")
4322
4323 ;; xnor patterns.  Note that (a ^ ~b) == (~a ^ b) == ~(a ^ b).
4324 ;; Combine now canonicalizes to the rightmost expression.
4325 (define_insn "*xor_not_di_sp32"
4326   [(set (match_operand:DI 0 "register_operand" "=r")
4327         (not:DI (xor:DI (match_operand:DI 1 "register_operand" "r")
4328                         (match_operand:DI 2 "register_operand" "r"))))]
4329   "! TARGET_ARCH64"
4330   "xnor %1,%2,%0\;xnor %R1,%R2,%R0"
4331   [(set_attr "length" "2")])
4332
4333 (define_insn "*xor_not_di_sp64"
4334   [(set (match_operand:DI 0 "register_operand" "=r")
4335         (not:DI (xor:DI (match_operand:DI 1 "reg_or_0_operand" "rJ")
4336                         (match_operand:DI 2 "arith_double_operand" "rHI"))))]
4337   "TARGET_ARCH64"
4338   "xnor %r1,%2,%0")
4339
4340 (define_insn "*xor_not_si"
4341   [(set (match_operand:SI 0 "register_operand" "=r")
4342         (not:SI (xor:SI (match_operand:SI 1 "reg_or_0_operand" "rJ")
4343                         (match_operand:SI 2 "arith_operand" "rI"))))]
4344   ""
4345   "xnor %r1,%2,%0"
4346   [(set_attr "type" "ialu")])
4347
4348 ;; These correspond to the above in the case where we also (or only)
4349 ;; want to set the condition code.  
4350
4351 (define_insn "*cmp_cc_arith_op"
4352   [(set (reg:CC 100)
4353         (compare:CC
4354          (match_operator:SI 2 "cc_arithop"
4355                             [(match_operand:SI 0 "arith_operand" "%r")
4356                              (match_operand:SI 1 "arith_operand" "rI")])
4357          (const_int 0)))]
4358   ""
4359   "%A2cc %0,%1,%%g0"
4360   [(set_attr "type" "compare")])
4361
4362 (define_insn "*cmp_ccx_arith_op"
4363   [(set (reg:CCX 100)
4364         (compare:CCX
4365          (match_operator:DI 2 "cc_arithop"
4366                             [(match_operand:DI 0 "arith_double_operand" "%r")
4367                              (match_operand:DI 1 "arith_double_operand" "rHI")])
4368          (const_int 0)))]
4369   "TARGET_ARCH64"
4370   "%A2cc %0,%1,%%g0"
4371   [(set_attr "type" "compare")])
4372
4373 (define_insn "*cmp_cc_arith_op_set"
4374   [(set (reg:CC 100)
4375         (compare:CC
4376          (match_operator:SI 3 "cc_arithop"
4377                             [(match_operand:SI 1 "arith_operand" "%r")
4378                              (match_operand:SI 2 "arith_operand" "rI")])
4379          (const_int 0)))
4380    (set (match_operand:SI 0 "register_operand" "=r")
4381         (match_dup 3))]
4382   ""
4383   "%A3cc %1,%2,%0")
4384
4385 (define_insn "*cmp_ccx_arith_op_set"
4386   [(set (reg:CCX 100)
4387         (compare:CCX
4388          (match_operator:DI 3 "cc_arithop"
4389                             [(match_operand:DI 1 "arith_double_operand" "%r")
4390                              (match_operand:DI 2 "arith_double_operand" "rHI")])
4391          (const_int 0)))
4392    (set (match_operand:DI 0 "register_operand" "=r")
4393         (match_dup 3))]
4394   "TARGET_ARCH64"
4395   "%A3cc %1,%2,%0")
4396
4397 (define_insn "*cmp_cc_xor_not"
4398   [(set (reg:CC 100)
4399         (compare:CC
4400          (not:SI (xor:SI (match_operand:SI 0 "reg_or_0_operand" "%rJ")
4401                          (match_operand:SI 1 "arith_operand" "rI")))
4402          (const_int 0)))]
4403   ""
4404   "xnorcc %r0,%1,%%g0"
4405   [(set_attr "type" "compare")])
4406
4407 (define_insn "*cmp_ccx_xor_not"
4408   [(set (reg:CCX 100)
4409         (compare:CCX
4410          (not:DI (xor:DI (match_operand:DI 0 "reg_or_0_operand" "%rJ")
4411                          (match_operand:DI 1 "arith_double_operand" "rHI")))
4412          (const_int 0)))]
4413   "TARGET_ARCH64"
4414   "xnorcc %r0,%1,%%g0"
4415   [(set_attr "type" "compare")])
4416
4417 (define_insn "*cmp_cc_xor_not_set"
4418   [(set (reg:CC 100)
4419         (compare:CC
4420          (not:SI (xor:SI (match_operand:SI 1 "reg_or_0_operand" "%rJ")
4421                          (match_operand:SI 2 "arith_operand" "rI")))
4422          (const_int 0)))
4423    (set (match_operand:SI 0 "register_operand" "=r")
4424         (not:SI (xor:SI (match_dup 1) (match_dup 2))))]
4425   ""
4426   "xnorcc %r1,%2,%0")
4427
4428 (define_insn "*cmp_ccx_xor_not_set"
4429   [(set (reg:CCX 100)
4430         (compare:CCX
4431          (not:DI (xor:DI (match_operand:DI 1 "reg_or_0_operand" "%rJ")
4432                          (match_operand:DI 2 "arith_double_operand" "rHI")))
4433          (const_int 0)))
4434    (set (match_operand:DI 0 "register_operand" "=r")
4435         (not:DI (xor:DI (match_dup 1) (match_dup 2))))]
4436   "TARGET_ARCH64"
4437   "xnorcc %r1,%2,%0")
4438
4439 (define_insn "*cmp_cc_arith_op_not"
4440   [(set (reg:CC 100)
4441         (compare:CC
4442          (match_operator:SI 2 "cc_arithopn"
4443                             [(not:SI (match_operand:SI 0 "arith_operand" "rI"))
4444                              (match_operand:SI 1 "reg_or_0_operand" "rJ")])
4445          (const_int 0)))]
4446   ""
4447   "%B2cc %r1,%0,%%g0"
4448   [(set_attr "type" "compare")])
4449
4450 (define_insn "*cmp_ccx_arith_op_not"
4451   [(set (reg:CCX 100)
4452         (compare:CCX
4453          (match_operator:DI 2 "cc_arithopn"
4454                             [(not:DI (match_operand:DI 0 "arith_double_operand" "rHI"))
4455                              (match_operand:DI 1 "reg_or_0_operand" "rJ")])
4456          (const_int 0)))]
4457   "TARGET_ARCH64"
4458   "%B2cc %r1,%0,%%g0"
4459   [(set_attr "type" "compare")])
4460
4461 (define_insn "*cmp_cc_arith_op_not_set"
4462   [(set (reg:CC 100)
4463         (compare:CC
4464          (match_operator:SI 3 "cc_arithopn"
4465                             [(not:SI (match_operand:SI 1 "arith_operand" "rI"))
4466                              (match_operand:SI 2 "reg_or_0_operand" "rJ")])
4467          (const_int 0)))
4468    (set (match_operand:SI 0 "register_operand" "=r")
4469         (match_dup 3))]
4470   ""
4471   "%B3cc %r2,%1,%0")
4472
4473 (define_insn "*cmp_ccx_arith_op_not_set"
4474   [(set (reg:CCX 100)
4475         (compare:CCX
4476          (match_operator:DI 3 "cc_arithopn"
4477                             [(not:DI (match_operand:DI 1 "arith_double_operand" "rHI"))
4478                              (match_operand:DI 2 "reg_or_0_operand" "rJ")])
4479          (const_int 0)))
4480    (set (match_operand:DI 0 "register_operand" "=r")
4481         (match_dup 3))]
4482   "TARGET_ARCH64"
4483   "%B3cc %r2,%1,%0")
4484
4485 ;; We cannot use the "neg" pseudo insn because the Sun assembler
4486 ;; does not know how to make it work for constants.
4487
4488 (define_expand "negdi2"
4489   [(set (match_operand:DI 0 "register_operand" "=r")
4490         (neg:DI (match_operand:DI 1 "register_operand" "r")))]
4491   ""
4492   "
4493 {
4494   if (! TARGET_ARCH64)
4495     {
4496       emit_insn (gen_rtx (PARALLEL, VOIDmode, gen_rtvec (2,
4497                           gen_rtx (SET, VOIDmode, operand0,
4498                                    gen_rtx (NEG, DImode, operand1)),
4499                           gen_rtx (CLOBBER, VOIDmode,
4500                                    gen_rtx (REG, SImode, SPARC_ICC_REG)))));
4501       DONE;
4502     }
4503 }")
4504
4505 (define_insn "*negdi2_sp32"
4506   [(set (match_operand:DI 0 "register_operand" "=r")
4507         (neg:DI (match_operand:DI 1 "register_operand" "r")))
4508    (clobber (reg:SI 100))]
4509   "! TARGET_ARCH64"
4510   "*
4511 {
4512   if (TARGET_LIVE_G0)
4513     output_asm_insn (\"and %%g0,0,%%g0\", operands);
4514   return \"subcc %%g0,%L1,%L0\;subx %%g0,%H1,%H0\";
4515 }"
4516   [(set_attr "type" "unary")
4517    ;; ??? This is wrong for TARGET_LIVE_G0 but it's not critical.
4518    (set_attr "length" "2")])
4519
4520 (define_insn "*negdi2_sp64"
4521   [(set (match_operand:DI 0 "register_operand" "=r")
4522         (neg:DI (match_operand:DI 1 "register_operand" "r")))]
4523   "TARGET_ARCH64"
4524   "sub %%g0,%1,%0"
4525   [(set_attr "type" "unary")
4526    (set_attr "length" "1")])
4527
4528 (define_insn "negsi2"
4529   [(set (match_operand:SI 0 "register_operand" "=r")
4530         (neg:SI (match_operand:SI 1 "arith_operand" "rI")))]
4531   ""
4532   "*
4533 {
4534   if (TARGET_LIVE_G0)
4535     return \"and %%g0,0,%%g0\;sub %%g0,%1,%0\";
4536   return \"sub %%g0,%1,%0\";
4537 }"
4538   [(set_attr "type" "unary")
4539    (set (attr "length")
4540         (if_then_else (eq_attr "live_g0" "yes") (const_int 2) (const_int 1)))])
4541
4542 (define_insn "*cmp_cc_neg"
4543   [(set (reg:CC_NOOV 100)
4544         (compare:CC_NOOV (neg:SI (match_operand:SI 0 "arith_operand" "rI"))
4545                          (const_int 0)))]
4546   "! TARGET_LIVE_G0"
4547   "subcc %%g0,%0,%%g0"
4548   [(set_attr "type" "compare")])
4549
4550 (define_insn "*cmp_ccx_neg"
4551   [(set (reg:CCX_NOOV 100)
4552         (compare:CCX_NOOV (neg:DI (match_operand:DI 0 "arith_double_operand" "rHI"))
4553                           (const_int 0)))]
4554   "TARGET_ARCH64"
4555   "subcc %%g0,%0,%%g0"
4556   [(set_attr "type" "compare")])
4557
4558 (define_insn "*cmp_cc_set_neg"
4559   [(set (reg:CC_NOOV 100)
4560         (compare:CC_NOOV (neg:SI (match_operand:SI 1 "arith_operand" "rI"))
4561                          (const_int 0)))
4562    (set (match_operand:SI 0 "register_operand" "=r")
4563         (neg:SI (match_dup 1)))]
4564   "! TARGET_LIVE_G0"
4565   "subcc %%g0,%1,%0"
4566   [(set_attr "type" "unary")])
4567
4568 (define_insn "*cmp_ccx_set_neg"
4569   [(set (reg:CCX_NOOV 100)
4570         (compare:CCX_NOOV (neg:DI (match_operand:DI 1 "arith_double_operand" "rHI"))
4571                           (const_int 0)))
4572    (set (match_operand:DI 0 "register_operand" "=r")
4573         (neg:DI (match_dup 1)))]
4574   "TARGET_ARCH64"
4575   "subcc %%g0,%1,%0"
4576   [(set_attr "type" "unary")])
4577
4578 ;; We cannot use the "not" pseudo insn because the Sun assembler
4579 ;; does not know how to make it work for constants.
4580 (define_expand "one_cmpldi2"
4581   [(set (match_operand:DI 0 "register_operand" "")
4582         (not:DI (match_operand:DI 1 "register_operand" "")))]
4583   ""
4584   "")
4585
4586 (define_insn "*one_cmpldi2_sp32"
4587   [(set (match_operand:DI 0 "register_operand" "=r")
4588         (not:DI (match_operand:DI 1 "register_operand" "r")))]
4589   "! TARGET_ARCH64"
4590   "xnor %1,0,%0\;xnor %R1,0,%R0"
4591   [(set_attr "type" "unary")
4592    (set_attr "length" "2")])
4593
4594 (define_insn "*one_cmpldi2_sp64"
4595   [(set (match_operand:DI 0 "register_operand" "=r")
4596         (not:DI (match_operand:DI 1 "arith_double_operand" "rHI")))]
4597   "TARGET_ARCH64"
4598   "xnor %1,0,%0"
4599   [(set_attr "type" "unary")])
4600
4601 (define_insn "one_cmplsi2"
4602   [(set (match_operand:SI 0 "register_operand" "=r,r")
4603         (not:SI (match_operand:SI 1 "arith_operand" "r,I")))]
4604   ""
4605   "*
4606 {
4607   if (which_alternative == 0)
4608     return \"xnor %1,0,%0\";
4609   if (TARGET_LIVE_G0)
4610     output_asm_insn (\"and %%g0,0,%%g0\", operands);
4611   return \"xnor %%g0,%1,%0\";
4612 }"
4613   [(set_attr "type" "unary")
4614    (set_attr_alternative "length"
4615      [(const_int 1)
4616       (if_then_else (eq_attr "live_g0" "yes") (const_int 2) (const_int 1))])])
4617
4618 (define_insn "*cmp_cc_not"
4619   [(set (reg:CC 100)
4620         (compare:CC (not:SI (match_operand:SI 0 "arith_operand" "rI"))
4621                     (const_int 0)))]
4622   "! TARGET_LIVE_G0"
4623   "xnorcc %%g0,%0,%%g0"
4624   [(set_attr "type" "compare")])
4625
4626 (define_insn "*cmp_ccx_not"
4627   [(set (reg:CCX 100)
4628         (compare:CCX (not:DI (match_operand:DI 0 "arith_double_operand" "rHI"))
4629                      (const_int 0)))]
4630   "TARGET_ARCH64"
4631   "xnorcc %%g0,%0,%%g0"
4632   [(set_attr "type" "compare")])
4633
4634 (define_insn "*cmp_cc_set_not"
4635   [(set (reg:CC 100)
4636         (compare:CC (not:SI (match_operand:SI 1 "arith_operand" "rI"))
4637                     (const_int 0)))
4638    (set (match_operand:SI 0 "register_operand" "=r")
4639         (not:SI (match_dup 1)))]
4640   "! TARGET_LIVE_G0"
4641   "xnorcc %%g0,%1,%0"
4642   [(set_attr "type" "unary")])
4643
4644 (define_insn "*cmp_ccx_set_not"
4645   [(set (reg:CCX 100)
4646         (compare:CCX (not:DI (match_operand:DI 1 "arith_double_operand" "rHI"))
4647                     (const_int 0)))
4648    (set (match_operand:DI 0 "register_operand" "=r")
4649         (not:DI (match_dup 1)))]
4650   "TARGET_ARCH64"
4651   "xnorcc %%g0,%1,%0"
4652   [(set_attr "type" "unary")])
4653 \f
4654 ;; Floating point arithmetic instructions.
4655
4656 (define_insn "addtf3"
4657   [(set (match_operand:TF 0 "register_operand" "=e")
4658         (plus:TF (match_operand:TF 1 "register_operand" "e")
4659                  (match_operand:TF 2 "register_operand" "e")))]
4660   "TARGET_FPU && TARGET_HARD_QUAD"
4661   "faddq %1,%2,%0"
4662   [(set_attr "type" "fp")])
4663
4664 (define_insn "adddf3"
4665   [(set (match_operand:DF 0 "register_operand" "=e")
4666         (plus:DF (match_operand:DF 1 "register_operand" "e")
4667                  (match_operand:DF 2 "register_operand" "e")))]
4668   "TARGET_FPU"
4669   "faddd %1,%2,%0"
4670   [(set_attr "type" "fp")])
4671
4672 (define_insn "addsf3"
4673   [(set (match_operand:SF 0 "register_operand" "=f")
4674         (plus:SF (match_operand:SF 1 "register_operand" "f")
4675                  (match_operand:SF 2 "register_operand" "f")))]
4676   "TARGET_FPU"
4677   "fadds %1,%2,%0"
4678   [(set_attr "type" "fp")])
4679
4680 (define_insn "subtf3"
4681   [(set (match_operand:TF 0 "register_operand" "=e")
4682         (minus:TF (match_operand:TF 1 "register_operand" "e")
4683                   (match_operand:TF 2 "register_operand" "e")))]
4684   "TARGET_FPU && TARGET_HARD_QUAD"
4685   "fsubq %1,%2,%0"
4686   [(set_attr "type" "fp")])
4687
4688 (define_insn "subdf3"
4689   [(set (match_operand:DF 0 "register_operand" "=e")
4690         (minus:DF (match_operand:DF 1 "register_operand" "e")
4691                   (match_operand:DF 2 "register_operand" "e")))]
4692   "TARGET_FPU"
4693   "fsubd %1,%2,%0"
4694   [(set_attr "type" "fp")])
4695
4696 (define_insn "subsf3"
4697   [(set (match_operand:SF 0 "register_operand" "=f")
4698         (minus:SF (match_operand:SF 1 "register_operand" "f")
4699                   (match_operand:SF 2 "register_operand" "f")))]
4700   "TARGET_FPU"
4701   "fsubs %1,%2,%0"
4702   [(set_attr "type" "fp")])
4703
4704 (define_insn "multf3"
4705   [(set (match_operand:TF 0 "register_operand" "=e")
4706         (mult:TF (match_operand:TF 1 "register_operand" "e")
4707                  (match_operand:TF 2 "register_operand" "e")))]
4708   "TARGET_FPU && TARGET_HARD_QUAD"
4709   "fmulq %1,%2,%0"
4710   [(set_attr "type" "fpmul")])
4711
4712 (define_insn "muldf3"
4713   [(set (match_operand:DF 0 "register_operand" "=e")
4714         (mult:DF (match_operand:DF 1 "register_operand" "e")
4715                  (match_operand:DF 2 "register_operand" "e")))]
4716   "TARGET_FPU"
4717   "fmuld %1,%2,%0"
4718   [(set_attr "type" "fpmul")])
4719
4720 (define_insn "mulsf3"
4721   [(set (match_operand:SF 0 "register_operand" "=f")
4722         (mult:SF (match_operand:SF 1 "register_operand" "f")
4723                  (match_operand:SF 2 "register_operand" "f")))]
4724   "TARGET_FPU"
4725   "fmuls %1,%2,%0"
4726   [(set_attr "type" "fpmul")])
4727
4728 (define_insn "*muldf3_extend"
4729   [(set (match_operand:DF 0 "register_operand" "=e")
4730         (mult:DF (float_extend:DF (match_operand:SF 1 "register_operand" "f"))
4731                  (float_extend:DF (match_operand:SF 2 "register_operand" "f"))))]
4732   "(TARGET_V8 || TARGET_V9) && TARGET_FPU"
4733   "fsmuld %1,%2,%0"
4734   [(set_attr "type" "fpmul")])
4735
4736 (define_insn "*multf3_extend"
4737   [(set (match_operand:TF 0 "register_operand" "=e")
4738         (mult:TF (float_extend:TF (match_operand:DF 1 "register_operand" "e"))
4739                  (float_extend:TF (match_operand:DF 2 "register_operand" "e"))))]
4740   "(TARGET_V8 || TARGET_V9) && TARGET_FPU && TARGET_HARD_QUAD"
4741   "fdmulq %1,%2,%0"
4742   [(set_attr "type" "fpmul")])
4743
4744 ;; don't have timing for quad-prec. divide.
4745 (define_insn "divtf3"
4746   [(set (match_operand:TF 0 "register_operand" "=e")
4747         (div:TF (match_operand:TF 1 "register_operand" "e")
4748                 (match_operand:TF 2 "register_operand" "e")))]
4749   "TARGET_FPU && TARGET_HARD_QUAD"
4750   "fdivq %1,%2,%0"
4751   [(set_attr "type" "fpdivd")])
4752
4753 (define_insn "divdf3"
4754   [(set (match_operand:DF 0 "register_operand" "=e")
4755         (div:DF (match_operand:DF 1 "register_operand" "e")
4756                 (match_operand:DF 2 "register_operand" "e")))]
4757   "TARGET_FPU"
4758   "fdivd %1,%2,%0"
4759   [(set_attr "type" "fpdivd")])
4760
4761 (define_insn "divsf3"
4762   [(set (match_operand:SF 0 "register_operand" "=f")
4763         (div:SF (match_operand:SF 1 "register_operand" "f")
4764                 (match_operand:SF 2 "register_operand" "f")))]
4765   "TARGET_FPU"
4766   "fdivs %1,%2,%0"
4767   [(set_attr "type" "fpdivs")])
4768
4769 (define_insn "negtf2"
4770   [(set (match_operand:TF 0 "register_operand" "=e,e")
4771         (neg:TF (match_operand:TF 1 "register_operand" "0,e")))]
4772   ; We don't use quad float insns here so we don't need TARGET_HARD_QUAD.
4773   "TARGET_FPU"
4774   "*
4775 {
4776   /* v9: can't use fnegs, won't work with upper regs.  */
4777   if (which_alternative == 0)
4778    return TARGET_V9 ? \"fnegd %0,%0\" : \"fnegs %0,%0\";
4779   else
4780    return TARGET_V9 ? \"fnegd %1,%0\;fmovd %S1,%S0\"
4781      : \"fnegs %1,%0\;fmovs %R1,%R0\;fmovs %S1,%S0\;fmovs %T1,%T0\";
4782 }"
4783   [(set_attr "type" "fp")
4784    (set_attr_alternative "length"
4785      [(const_int 1)
4786       (if_then_else (eq_attr "isa" "v9") (const_int 2) (const_int 4))])])
4787
4788 (define_insn "negdf2"
4789   [(set (match_operand:DF 0 "register_operand" "=e,e")
4790         (neg:DF (match_operand:DF 1 "register_operand" "0,e")))]
4791   "TARGET_FPU"
4792   "*
4793 {
4794   if (TARGET_V9)
4795     return \"fnegd %1,%0\";
4796   else if (which_alternative == 0)
4797    return \"fnegs %0,%0\";
4798   else
4799    return \"fnegs %1,%0\;fmovs %R1,%R0\";
4800 }"
4801   [(set_attr "type" "fp")
4802    (set_attr_alternative "length"
4803      [(const_int 1)
4804       (if_then_else (eq_attr "isa" "v9") (const_int 1) (const_int 2))])])
4805
4806 (define_insn "negsf2"
4807   [(set (match_operand:SF 0 "register_operand" "=f")
4808         (neg:SF (match_operand:SF 1 "register_operand" "f")))]
4809   "TARGET_FPU"
4810   "fnegs %1,%0"
4811   [(set_attr "type" "fp")])
4812
4813 (define_insn "abstf2"
4814   [(set (match_operand:TF 0 "register_operand" "=e,e")
4815         (abs:TF (match_operand:TF 1 "register_operand" "0,e")))]
4816   ; We don't use quad float insns here so we don't need TARGET_HARD_QUAD.
4817   "TARGET_FPU"
4818   "*
4819 {
4820   /* v9: can't use fabss, won't work with upper regs.  */
4821   if (which_alternative == 0)
4822     return TARGET_V9 ? \"fabsd %0,%0\" : \"fabss %0,%0\";
4823   else
4824     return TARGET_V9 ? \"fabsd %1,%0\;fmovd %S1,%S0\"
4825       : \"fabss %1,%0\;fmovs %R1,%R0\;fmovs %S1,%S0\;fmovs %T1,%T0\";
4826 }"
4827   [(set_attr "type" "fp")
4828    (set_attr_alternative "length"
4829      [(const_int 1)
4830       (if_then_else (eq_attr "isa" "v9") (const_int 2) (const_int 4))])])
4831
4832 (define_insn "absdf2"
4833   [(set (match_operand:DF 0 "register_operand" "=e,e")
4834         (abs:DF (match_operand:DF 1 "register_operand" "0,e")))]
4835   "TARGET_FPU"
4836   "*
4837 {
4838   if (TARGET_V9)
4839     return \"fabsd %1,%0\";
4840   else if (which_alternative == 0)
4841     return \"fabss %0,%0\";
4842   else
4843     return \"fabss %1,%0\;fmovs %R1,%R0\";
4844 }"
4845   [(set_attr "type" "fp")
4846    (set_attr_alternative "length"
4847      [(const_int 1)
4848       (if_then_else (eq_attr "isa" "v9") (const_int 1) (const_int 2))])])
4849
4850 (define_insn "abssf2"
4851   [(set (match_operand:SF 0 "register_operand" "=f")
4852         (abs:SF (match_operand:SF 1 "register_operand" "f")))]
4853   "TARGET_FPU"
4854   "fabss %1,%0"
4855   [(set_attr "type" "fp")])
4856
4857 (define_insn "sqrttf2"
4858   [(set (match_operand:TF 0 "register_operand" "=e")
4859         (sqrt:TF (match_operand:TF 1 "register_operand" "e")))]
4860   "TARGET_FPU && TARGET_HARD_QUAD"
4861   "fsqrtq %1,%0"
4862   [(set_attr "type" "fpsqrt")])
4863
4864 (define_insn "sqrtdf2"
4865   [(set (match_operand:DF 0 "register_operand" "=e")
4866         (sqrt:DF (match_operand:DF 1 "register_operand" "e")))]
4867   "TARGET_FPU"
4868   "fsqrtd %1,%0"
4869   [(set_attr "type" "fpsqrt")])
4870
4871 (define_insn "sqrtsf2"
4872   [(set (match_operand:SF 0 "register_operand" "=f")
4873         (sqrt:SF (match_operand:SF 1 "register_operand" "f")))]
4874   "TARGET_FPU"
4875   "fsqrts %1,%0"
4876   [(set_attr "type" "fpsqrt")])
4877 \f
4878 ;;- arithmetic shift instructions
4879
4880 (define_insn "ashlsi3"
4881   [(set (match_operand:SI 0 "register_operand" "=r")
4882         (ashift:SI (match_operand:SI 1 "register_operand" "r")
4883                    (match_operand:SI 2 "arith_operand" "rI")))]
4884   ""
4885   "*
4886 {
4887   if (GET_CODE (operands[2]) == CONST_INT
4888       && (unsigned HOST_WIDE_INT) INTVAL (operands[2]) > 31)
4889     operands[2] = GEN_INT (INTVAL (operands[2]) & 0x1f);
4890
4891   return \"sll %1,%2,%0\";
4892 }"
4893   [(set_attr "type" "shift")])
4894
4895 (define_insn "ashldi3"
4896   [(set (match_operand:DI 0 "register_operand" "=r")
4897         (ashift:DI (match_operand:DI 1 "register_operand" "r")
4898                    (match_operand:SI 2 "arith_operand" "rI")))]
4899   "TARGET_ARCH64"
4900   "*
4901 {
4902   if (GET_CODE (operands[2]) == CONST_INT
4903       && (unsigned HOST_WIDE_INT) INTVAL (operands[2]) > 31)
4904     operands[2] = GEN_INT (INTVAL (operands[2]) & 0x3f);
4905
4906   return \"sllx %1,%2,%0\";
4907 }")
4908
4909 (define_insn "*cmp_cc_ashift_1"
4910   [(set (reg:CC_NOOV 100)
4911         (compare:CC_NOOV (ashift:SI (match_operand:SI 0 "register_operand" "r")
4912                                     (const_int 1))
4913                          (const_int 0)))]
4914   ""
4915   "addcc %0,%0,%%g0"
4916   [(set_attr "type" "compare")])
4917
4918 (define_insn "*cmp_cc_set_ashift_1"
4919   [(set (reg:CC_NOOV 100)
4920         (compare:CC_NOOV (ashift:SI (match_operand:SI 1 "register_operand" "r")
4921                                     (const_int 1))
4922                          (const_int 0)))
4923    (set (match_operand:SI 0 "register_operand" "=r")
4924         (ashift:SI (match_dup 1) (const_int 1)))]
4925   ""
4926   "addcc %1,%1,%0")
4927
4928 (define_insn "ashrsi3"
4929   [(set (match_operand:SI 0 "register_operand" "=r")
4930         (ashiftrt:SI (match_operand:SI 1 "register_operand" "r")
4931                      (match_operand:SI 2 "arith_operand" "rI")))]
4932   ""
4933   "*
4934 {
4935   if (GET_CODE (operands[2]) == CONST_INT
4936       && (unsigned HOST_WIDE_INT) INTVAL (operands[2]) > 31)
4937     operands[2] = GEN_INT (INTVAL (operands[2]) & 0x1f);
4938
4939   return \"sra %1,%2,%0\";
4940 }"
4941   [(set_attr "type" "shift")])
4942
4943 (define_insn "ashrdi3"
4944   [(set (match_operand:DI 0 "register_operand" "=r")
4945         (ashiftrt:DI (match_operand:DI 1 "register_operand" "r")
4946                      (match_operand:SI 2 "arith_operand" "rI")))]
4947   "TARGET_ARCH64"
4948   "*
4949 {
4950   if (GET_CODE (operands[2]) == CONST_INT
4951       && (unsigned HOST_WIDE_INT) INTVAL (operands[2]) > 63)
4952     operands[2] = GEN_INT (INTVAL (operands[2]) & 0x3f);
4953
4954   return \"srax %1,%2,%0\";
4955 }")
4956
4957 (define_insn "lshrsi3"
4958   [(set (match_operand:SI 0 "register_operand" "=r")
4959         (lshiftrt:SI (match_operand:SI 1 "register_operand" "r")
4960                      (match_operand:SI 2 "arith_operand" "rI")))]
4961   ""
4962   "*
4963 {
4964   if (GET_CODE (operands[2]) == CONST_INT
4965       && (unsigned HOST_WIDE_INT) INTVAL (operands[2]) > 31)
4966     operands[2] = GEN_INT (INTVAL (operands[2]) & 0x1f);
4967
4968   return \"srl %1,%2,%0\";
4969 }"
4970   [(set_attr "type" "shift")])
4971
4972 (define_insn "lshrdi3"
4973   [(set (match_operand:DI 0 "register_operand" "=r")
4974         (lshiftrt:DI (match_operand:DI 1 "register_operand" "r")
4975                      (match_operand:SI 2 "arith_operand" "rI")))]
4976   "TARGET_ARCH64"
4977   "*
4978 {
4979   if (GET_CODE (operands[2]) == CONST_INT
4980       && (unsigned HOST_WIDE_INT) INTVAL (operands[2]) > 63)
4981     operands[2] = GEN_INT (INTVAL (operands[2]) & 0x3f);
4982
4983   return \"srlx %1,%2,%0\";
4984 }")
4985 \f
4986 ;; Unconditional and other jump instructions
4987 ;; On the Sparc, by setting the annul bit on an unconditional branch, the
4988 ;; following insn is never executed.  This saves us a nop.  Dbx does not
4989 ;; handle such branches though, so we only use them when optimizing.
4990 (define_insn "jump"
4991   [(set (pc) (label_ref (match_operand 0 "" "")))]
4992   ""
4993   "b%* %l0%("
4994   [(set_attr "type" "uncond_branch")])
4995
4996 (define_expand "tablejump"
4997   [(parallel [(set (pc) (match_operand 0 "register_operand" "r"))
4998               (use (label_ref (match_operand 1 "" "")))])]
4999   ""
5000   "
5001 {
5002   if (GET_MODE (operands[0]) != Pmode)
5003     abort ();
5004
5005   /* We need to use the PC value in %o7 that was set up when the address
5006      of the label was loaded into a register, so we need different RTL.  */
5007   if (flag_pic)
5008     {
5009       if (!TARGET_PTR64)
5010         emit_jump_insn (gen_pic_tablejump_32 (operands[0], operands[1]));
5011       else
5012         emit_jump_insn (gen_pic_tablejump_64 (operands[0], operands[1]));
5013       DONE;
5014     }
5015 }")
5016
5017 (define_insn "pic_tablejump_32"
5018   [(set (pc) (match_operand:SI 0 "register_operand" "r"))
5019    (use (label_ref (match_operand 1 "" "")))
5020    (use (reg:SI 15))]
5021   "! TARGET_PTR64"
5022   "jmp %%o7+%0%#"
5023   [(set_attr "type" "uncond_branch")])
5024
5025 (define_insn "pic_tablejump_64"
5026   [(set (pc) (match_operand:DI 0 "register_operand" "r"))
5027    (use (label_ref (match_operand 1 "" "")))
5028    (use (reg:DI 15))]
5029   "TARGET_PTR64"
5030   "jmp %%o7+%0%#"
5031   [(set_attr "type" "uncond_branch")])
5032
5033 (define_insn "*tablejump_sp32"
5034   [(set (pc) (match_operand:SI 0 "address_operand" "p"))
5035    (use (label_ref (match_operand 1 "" "")))]
5036   "! TARGET_PTR64"
5037   "jmp %a0%#"
5038   [(set_attr "type" "uncond_branch")])
5039
5040 (define_insn "*tablejump_sp64"
5041   [(set (pc) (match_operand:DI 0 "address_operand" "p"))
5042    (use (label_ref (match_operand 1 "" "")))]
5043   "TARGET_PTR64"
5044   "jmp %a0%#"
5045   [(set_attr "type" "uncond_branch")])
5046
5047 ;; This pattern recognizes the "instruction" that appears in 
5048 ;; a function call that wants a structure value, 
5049 ;; to inform the called function if compiled with Sun CC.
5050 ;(define_insn "*unimp_insn"
5051 ;  [(match_operand:SI 0 "immediate_operand" "")]
5052 ;  "GET_CODE (operands[0]) == CONST_INT && INTVAL (operands[0]) > 0"
5053 ;  "unimp %0"
5054 ;  [(set_attr "type" "marker")])
5055
5056 ;;- jump to subroutine
5057 (define_expand "call"
5058   ;; Note that this expression is not used for generating RTL.
5059   ;; All the RTL is generated explicitly below.
5060   [(call (match_operand 0 "call_operand" "")
5061          (match_operand 3 "" "i"))]
5062   ;; operands[2] is next_arg_register
5063   ;; operands[3] is struct_value_size_rtx.
5064   ""
5065   "
5066 {
5067   rtx fn_rtx, nregs_rtx;
5068
5069    if (GET_MODE (operands[0]) != FUNCTION_MODE)
5070     abort ();
5071
5072   if (GET_CODE (XEXP (operands[0], 0)) == LABEL_REF)
5073     {
5074       /* This is really a PIC sequence.  We want to represent
5075          it as a funny jump so it's delay slots can be filled. 
5076
5077          ??? But if this really *is* a CALL, will not it clobber the
5078          call-clobbered registers?  We lose this if it is a JUMP_INSN.
5079          Why cannot we have delay slots filled if it were a CALL?  */
5080
5081       if (! TARGET_ARCH64 && INTVAL (operands[3]) != 0)
5082         emit_jump_insn
5083           (gen_rtx (PARALLEL, VOIDmode,
5084                     gen_rtvec (3,
5085                                gen_rtx (SET, VOIDmode, pc_rtx,
5086                                         XEXP (operands[0], 0)),
5087                                GEN_INT (INTVAL (operands[3]) & 0xfff),
5088                                gen_rtx (CLOBBER, VOIDmode,
5089                                         gen_rtx (REG, Pmode, 15)))));
5090       else
5091         emit_jump_insn
5092           (gen_rtx (PARALLEL, VOIDmode,
5093                     gen_rtvec (2,
5094                                gen_rtx (SET, VOIDmode, pc_rtx,
5095                                         XEXP (operands[0], 0)),
5096                                gen_rtx (CLOBBER, VOIDmode,
5097                                         gen_rtx (REG, Pmode, 15)))));
5098       goto finish_call;
5099     }
5100
5101   fn_rtx = operands[0];
5102
5103   /* Count the number of parameter registers being used by this call.
5104      if that argument is NULL, it means we are using them all, which
5105      means 6 on the sparc.  */
5106 #if 0
5107   if (operands[2])
5108     nregs_rtx = GEN_INT (REGNO (operands[2]) - 8);
5109   else
5110     nregs_rtx = GEN_INT (6);
5111 #else
5112   nregs_rtx = const0_rtx;
5113 #endif
5114
5115   if (! TARGET_ARCH64 && INTVAL (operands[3]) != 0)
5116     emit_call_insn
5117       (gen_rtx (PARALLEL, VOIDmode,
5118                 gen_rtvec (3, gen_rtx (CALL, VOIDmode, fn_rtx, nregs_rtx),
5119                            GEN_INT (INTVAL (operands[3]) & 0xfff),
5120                            gen_rtx (CLOBBER, VOIDmode,
5121                                     gen_rtx (REG, Pmode, 15)))));
5122   else
5123     emit_call_insn
5124       (gen_rtx (PARALLEL, VOIDmode,
5125                 gen_rtvec (2, gen_rtx (CALL, VOIDmode, fn_rtx, nregs_rtx),
5126                            gen_rtx (CLOBBER, VOIDmode,
5127                                     gen_rtx (REG, Pmode, 15)))));
5128
5129  finish_call:
5130 #if 0
5131   /* If this call wants a structure value,
5132      emit an unimp insn to let the called function know about this.  */
5133   if (! TARGET_ARCH64 && INTVAL (operands[3]) > 0)
5134     {
5135       rtx insn = emit_insn (operands[3]);
5136       SCHED_GROUP_P (insn) = 1;
5137     }
5138 #endif
5139
5140   DONE;
5141 }")
5142
5143 ;; We can't use the same pattern for these two insns, because then registers
5144 ;; in the address may not be properly reloaded.
5145
5146 (define_insn "*call_address_sp32"
5147   [(call (mem:SI (match_operand:SI 0 "address_operand" "p"))
5148          (match_operand 1 "" ""))
5149    (clobber (reg:SI 15))]
5150   ;;- Do not use operand 1 for most machines.
5151   "! TARGET_PTR64"
5152   "call %a0,%1%#"
5153   [(set_attr "type" "call")])
5154
5155 (define_insn "*call_symbolic_sp32"
5156   [(call (mem:SI (match_operand:SI 0 "symbolic_operand" "s"))
5157          (match_operand 1 "" ""))
5158    (clobber (reg:SI 15))]
5159   ;;- Do not use operand 1 for most machines.
5160   "! TARGET_PTR64"
5161   "call %a0,%1%#"
5162   [(set_attr "type" "call")])
5163
5164 (define_insn "*call_address_sp64"
5165   [(call (mem:SI (match_operand:DI 0 "address_operand" "p"))
5166          (match_operand 1 "" ""))
5167    (clobber (reg:DI 15))]
5168   ;;- Do not use operand 1 for most machines.
5169   "TARGET_PTR64"
5170   "call %a0,%1%#"
5171   [(set_attr "type" "call")])
5172
5173 (define_insn "*call_symbolic_sp64"
5174   [(call (mem:SI (match_operand:DI 0 "symbolic_operand" "s"))
5175          (match_operand 1 "" ""))
5176    (clobber (reg:DI 15))]
5177   ;;- Do not use operand 1 for most machines.
5178   "TARGET_PTR64"
5179   "call %a0,%1%#"
5180   [(set_attr "type" "call")])
5181
5182 ;; This is a call that wants a structure value.
5183 ;; There is no such critter for v9 (??? we may need one anyway).
5184 (define_insn "*call_address_struct_value_sp32"
5185   [(call (mem:SI (match_operand:SI 0 "address_operand" "p"))
5186          (match_operand 1 "" ""))
5187    (match_operand 2 "immediate_operand" "")
5188    (clobber (reg:SI 15))]
5189   ;;- Do not use operand 1 for most machines.
5190   "! TARGET_ARCH64 && GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) >= 0"
5191   "call %a0,%1\;nop\;unimp %2"
5192   [(set_attr "type" "call_no_delay_slot")])
5193
5194 ;; This is a call that wants a structure value.
5195 ;; There is no such critter for v9 (??? we may need one anyway).
5196 (define_insn "*call_symbolic_struct_value_sp32"
5197   [(call (mem:SI (match_operand:SI 0 "symbolic_operand" "s"))
5198          (match_operand 1 "" ""))
5199    (match_operand 2 "immediate_operand" "")
5200    (clobber (reg:SI 15))]
5201   ;;- Do not use operand 1 for most machines.
5202   "! TARGET_ARCH64 && GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) >= 0"
5203   "call %a0,%1\;nop\;unimp %2"
5204   [(set_attr "type" "call_no_delay_slot")])
5205
5206 ;; This is a call that may want a structure value.  This is used for
5207 ;; untyped_calls.
5208 (define_insn "*call_address_untyped_struct_value_sp32"
5209   [(call (mem:SI (match_operand:SI 0 "address_operand" "p"))
5210          (match_operand 1 "" ""))
5211    (match_operand 2 "immediate_operand" "")
5212    (clobber (reg:SI 15))]
5213   ;;- Do not use operand 1 for most machines.
5214   "! TARGET_ARCH64 && GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) < 0"
5215   "call %a0,%1\;nop\;nop"
5216   [(set_attr "type" "call_no_delay_slot")])
5217
5218 ;; This is a call that wants a structure value.
5219 (define_insn "*call_symbolic_untyped_struct_value_sp32"
5220   [(call (mem:SI (match_operand:SI 0 "symbolic_operand" "s"))
5221          (match_operand 1 "" ""))
5222    (match_operand 2 "immediate_operand" "")
5223    (clobber (reg:SI 15))]
5224   ;;- Do not use operand 1 for most machines.
5225   "! TARGET_ARCH64 && GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) < 0"
5226   "call %a0,%1\;nop\;nop"
5227   [(set_attr "type" "call_no_delay_slot")])
5228
5229 (define_expand "call_value"
5230   ;; Note that this expression is not used for generating RTL.
5231   ;; All the RTL is generated explicitly below.
5232   [(set (match_operand 0 "register_operand" "=rf")
5233         (call (match_operand:SI 1 "" "")
5234               (match_operand 4 "" "")))]
5235   ;; operand 2 is stack_size_rtx
5236   ;; operand 3 is next_arg_register
5237   ""
5238   "
5239 {
5240   rtx fn_rtx, nregs_rtx;
5241   rtvec vec;
5242
5243   if (GET_MODE (operands[1]) != FUNCTION_MODE)
5244     abort ();
5245
5246   fn_rtx = operands[1];
5247
5248 #if 0
5249   if (operands[3])
5250     nregs_rtx = gen_rtx (CONST_INT, VOIDmode, REGNO (operands[3]) - 8);
5251   else
5252     nregs_rtx = gen_rtx (CONST_INT, VOIDmode, 6);
5253 #else
5254   nregs_rtx = const0_rtx;
5255 #endif
5256
5257   vec = gen_rtvec (2,
5258                    gen_rtx (SET, VOIDmode, operands[0],
5259                             gen_rtx (CALL, VOIDmode, fn_rtx, nregs_rtx)),
5260                    gen_rtx (CLOBBER, VOIDmode, gen_rtx (REG, Pmode, 15)));
5261
5262   emit_call_insn (gen_rtx (PARALLEL, VOIDmode, vec));
5263
5264   DONE;
5265 }")
5266
5267 (define_insn "*call_value_address_sp32"
5268   [(set (match_operand 0 "" "=rf")
5269         (call (mem:SI (match_operand:SI 1 "address_operand" "p"))
5270               (match_operand 2 "" "")))
5271    (clobber (reg:SI 15))]
5272   ;;- Do not use operand 2 for most machines.
5273   "! TARGET_PTR64"
5274   "call %a1,%2%#"
5275   [(set_attr "type" "call")])
5276
5277 (define_insn "*call_value_symbolic_sp32"
5278   [(set (match_operand 0 "" "=rf")
5279         (call (mem:SI (match_operand:SI 1 "symbolic_operand" "s"))
5280               (match_operand 2 "" "")))
5281    (clobber (reg:SI 15))]
5282   ;;- Do not use operand 2 for most machines.
5283   "! TARGET_PTR64"
5284   "call %a1,%2%#"
5285   [(set_attr "type" "call")])
5286
5287 (define_insn "*call_value_address_sp64"
5288   [(set (match_operand 0 "" "=rf")
5289         (call (mem:SI (match_operand:DI 1 "address_operand" "p"))
5290               (match_operand 2 "" "")))
5291    (clobber (reg:DI 15))]
5292   ;;- Do not use operand 2 for most machines.
5293   "TARGET_PTR64"
5294   "call %a1,%2%#"
5295   [(set_attr "type" "call")])
5296
5297 (define_insn "*call_value_symbolic_sp64"
5298   [(set (match_operand 0 "" "=rf")
5299         (call (mem:SI (match_operand:DI 1 "symbolic_operand" "s"))
5300               (match_operand 2 "" "")))
5301    (clobber (reg:DI 15))]
5302   ;;- Do not use operand 2 for most machines.
5303   "TARGET_PTR64"
5304   "call %a1,%2%#"
5305   [(set_attr "type" "call")])
5306
5307 (define_expand "untyped_call"
5308   [(parallel [(call (match_operand 0 "" "")
5309                     (const_int 0))
5310               (match_operand 1 "" "")
5311               (match_operand 2 "" "")])]
5312   ""
5313   "
5314 {
5315   int i;
5316
5317   /* Pass constm1 to indicate that it may expect a structure value, but
5318      we don't know what size it is.  */
5319   emit_call_insn (gen_call (operands[0], const0_rtx, NULL, constm1_rtx));
5320
5321   for (i = 0; i < XVECLEN (operands[2], 0); i++)
5322     {
5323       rtx set = XVECEXP (operands[2], 0, i);
5324       emit_move_insn (SET_DEST (set), SET_SRC (set));
5325     }
5326
5327   /* The optimizer does not know that the call sets the function value
5328      registers we stored in the result block.  We avoid problems by
5329      claiming that all hard registers are used and clobbered at this
5330      point.  */
5331   emit_insn (gen_blockage ());
5332
5333   DONE;
5334 }")
5335
5336 ;; UNSPEC_VOLATILE is considered to use and clobber all hard registers and
5337 ;; all of memory.  This blocks insns from being moved across this point.
5338
5339 (define_insn "blockage"
5340   [(unspec_volatile [(const_int 0)] 0)]
5341   ""
5342   "")
5343
5344 ;; Prepare to return any type including a structure value.
5345
5346 (define_expand "untyped_return"
5347   [(match_operand:BLK 0 "memory_operand" "")
5348    (match_operand 1 "" "")]
5349   ""
5350   "
5351 {
5352   rtx valreg1 = gen_rtx (REG, DImode, 24);
5353   rtx valreg2 = gen_rtx (REG, TARGET_ARCH64 ? TFmode : DFmode, 32);
5354   rtx result = operands[0];
5355
5356   if (! TARGET_ARCH64)
5357     {
5358       rtx rtnreg = gen_rtx (REG, SImode, (leaf_function ? 15 : 31));
5359       rtx value = gen_reg_rtx (SImode);
5360
5361       /* Fetch the instruction where we will return to and see if it's an unimp
5362          instruction (the most significant 10 bits will be zero).  If so,
5363          update the return address to skip the unimp instruction.  */
5364       emit_move_insn (value,
5365                       gen_rtx (MEM, SImode, plus_constant (rtnreg, 8)));
5366       emit_insn (gen_lshrsi3 (value, value, GEN_INT (22)));
5367       emit_insn (gen_update_return (rtnreg, value));
5368     }
5369
5370   /* Reload the function value registers.  */
5371   emit_move_insn (valreg1, change_address (result, DImode, XEXP (result, 0)));
5372   emit_move_insn (valreg2,
5373                   change_address (result, TARGET_ARCH64 ? TFmode : DFmode,
5374                                   plus_constant (XEXP (result, 0), 8)));
5375
5376   /* Put USE insns before the return.  */
5377   emit_insn (gen_rtx (USE, VOIDmode, valreg1));
5378   emit_insn (gen_rtx (USE, VOIDmode, valreg2));
5379
5380   /* Construct the return.  */
5381   expand_null_return ();
5382
5383   DONE;
5384 }")
5385
5386 ;; This is a bit of a hack.  We're incrementing a fixed register (%i7),
5387 ;; and parts of the compiler don't want to believe that the add is needed.
5388
5389 (define_insn "update_return"
5390   [(unspec:SI [(match_operand:SI 0 "register_operand" "r")
5391                (match_operand:SI 1 "register_operand" "r")] 0)]
5392   "! TARGET_ARCH64"
5393   "cmp %1,0\;be,a .+8\;add %0,4,%0"
5394   [(set_attr "type" "multi")])
5395 \f
5396 (define_insn "return"
5397   [(return)
5398    (use (reg:SI 31))]
5399   "! TARGET_EPILOGUE"
5400   "* return output_return (operands);"
5401   [(set_attr "type" "multi")])
5402
5403 (define_insn "nop"
5404   [(const_int 0)]
5405   ""
5406   "nop")
5407
5408 (define_expand "indirect_jump"
5409   [(set (pc) (match_operand 0 "address_operand" "p"))]
5410   ""
5411   "")
5412
5413 (define_insn "*branch_sp32"
5414   [(set (pc) (match_operand:SI 0 "address_operand" "p"))]
5415   "! TARGET_PTR64"
5416  "jmp %a0%#"
5417  [(set_attr "type" "uncond_branch")])
5418  
5419 (define_insn "*branch_sp64"
5420   [(set (pc) (match_operand:DI 0 "address_operand" "p"))]
5421   "TARGET_PTR64"
5422   "jmp %a0%#"
5423   [(set_attr "type" "uncond_branch")])
5424
5425 ;; ??? Doesn't work with -mflat.
5426 (define_expand "nonlocal_goto"
5427   [(match_operand:SI 0 "general_operand" "")
5428    (match_operand:SI 1 "general_operand" "")
5429    (match_operand:SI 2 "general_operand" "")
5430    (match_operand:SI 3 "" "")]
5431   ""
5432   "
5433 {
5434   /* Trap instruction to flush all the register windows.  */
5435   emit_insn (gen_flush_register_windows ());
5436   /* Load the fp value for the containing fn into %fp.
5437      This is needed because operands[2] refers to %fp.
5438      Virtual register instantiation fails if the virtual %fp isn't set from a
5439      register.  Thus we must copy operands[0] into a register if it isn't
5440      already one.  */
5441   if (GET_CODE (operands[0]) != REG)
5442     operands[0] = force_reg (Pmode, operands[0]);
5443   emit_move_insn (virtual_stack_vars_rtx, operands[0]);
5444   /* Find the containing function's current nonlocal goto handler,
5445      which will do any cleanups and then jump to the label.  */
5446   emit_move_insn (gen_rtx (REG, Pmode, 8), operands[1]);
5447   /* Restore %fp from stack pointer value for containing function.
5448      The restore insn that follows will move this to %sp,
5449      and reload the appropriate value into %fp.  */
5450   emit_move_insn (frame_pointer_rtx, operands[2]);
5451   /* Put in the static chain register the nonlocal label address.  */
5452   emit_move_insn (static_chain_rtx, operands[3]);
5453   /* USE of frame_pointer_rtx added for consistency; not clear if
5454      really needed.  */
5455   emit_insn (gen_rtx (USE, VOIDmode, frame_pointer_rtx));
5456   emit_insn (gen_rtx (USE, VOIDmode, stack_pointer_rtx));
5457   emit_insn (gen_rtx (USE, VOIDmode, static_chain_rtx));
5458   /* Return, restoring reg window and jumping to goto handler.  */
5459   emit_insn (gen_goto_handler_and_restore ());
5460   emit_barrier ();
5461   DONE;
5462 }")
5463
5464 ;; Special trap insn to flush register windows.
5465 (define_insn "flush_register_windows"
5466   [(unspec_volatile [(const_int 0)] 1)]
5467   ""
5468   ;; ??? Use TARGET_V9 instead?
5469   "* return TARGET_ARCH64 ? \"flushw\" : \"ta 3\";"
5470   [(set_attr "type" "misc")])
5471
5472 (define_insn "goto_handler_and_restore"
5473   [(unspec_volatile [(const_int 0)] 2)
5474    (use (reg:SI 8))]
5475   ""
5476   "jmp %%o0+0\;restore"
5477   [(set_attr "type" "misc")
5478    (set_attr "length" "2")])
5479
5480 ;; Pattern for use after a setjmp to store FP and the return register
5481 ;; into the stack area.
5482
5483 (define_expand "setjmp"
5484   [(const_int 0)]
5485   ""
5486   "
5487 {
5488   if (TARGET_ARCH64)
5489     emit_insn (gen_setjmp_64 ());
5490   else
5491     emit_insn (gen_setjmp_32 ());
5492
5493   DONE;
5494 }")
5495
5496 (define_expand "setjmp_32"
5497   [(set (mem:SI (plus:SI (reg:SI 14) (const_int 56))) (match_dup 0))
5498    (set (mem:SI (plus:SI (reg:SI 14) (const_int 60))) (reg:SI 31))]
5499   ""
5500   "
5501 { operands[0] = frame_pointer_rtx; }")
5502
5503 (define_expand "setjmp_64"
5504   [(set (mem:DI (plus:DI (reg:DI 14) (const_int 112))) (match_dup 0))
5505    (set (mem:DI (plus:DI (reg:DI 14) (const_int 120))) (reg:DI 31))]
5506   ""
5507   "
5508 { operands[0] = frame_pointer_rtx; }")
5509
5510 ;; Special pattern for the FLUSH instruction.
5511
5512 (define_insn "flush"
5513   [(unspec_volatile [(match_operand 0 "memory_operand" "m")] 3)]
5514   ""
5515   "* return TARGET_V9 ? \"flush %f0\" : \"iflush %f0\";"
5516   [(set_attr "type" "misc")])
5517 \f
5518 ;; find first set.
5519
5520 ;; The scan instruction searches from the most significant bit while ffs
5521 ;; searches from the least significant bit.  The bit index and treatment of
5522 ;; zero also differ.  It takes at least 7 instructions to get the proper
5523 ;; result.  Here is an obvious 8 instruction sequence.
5524
5525 (define_insn "ffssi2"
5526   [(set (match_operand:SI 0 "register_operand" "=&r")
5527         (ffs:SI (match_operand:SI 1 "register_operand" "r")))
5528    (clobber (match_scratch:SI 2 "=&r"))]
5529   "TARGET_SPARCLITE || TARGET_SPARCLET"
5530   "*
5531 {
5532   if (TARGET_LIVE_G0)
5533     output_asm_insn (\"and %%g0,0,%%g0\", operands);
5534   return \"sub %%g0,%1,%0\;and %0,%1,%0\;scan %0,0,%0\;mov 32,%2\;sub %2,%0,%0\;sra %0,31,%2\;and %2,31,%2\;add %2,%0,%0\";
5535 }"
5536   [(set_attr "type" "multi")
5537    (set_attr "length" "8")])
5538
5539 ;; ??? This should be a define expand, so that the extra instruction have
5540 ;; a chance of being optimized away.
5541
5542 (define_insn "ffsdi2"
5543   [(set (match_operand:DI 0 "register_operand" "=&r")
5544         (ffs:DI (match_operand:DI 1 "register_operand" "r")))
5545    (clobber (match_scratch:DI 2 "=&r"))]
5546   "TARGET_ARCH64"
5547   "neg %1,%2\;not %2,%2\;xor %1,%2,%2\;popc %2,%0\;movrz %1,0,%0"
5548   [(set_attr "type" "multi")
5549    (set_attr "length" "5")])
5550 \f
5551 ;; Split up troublesome insns for better scheduling.  */
5552
5553 ;; The following patterns are straightforward.  They can be applied
5554 ;; either before or after register allocation.
5555
5556 (define_split
5557   [(set (match_operand 0 "splittable_symbolic_memory_operand" "")
5558         (match_operand 1 "reg_or_0_operand" ""))
5559    (clobber (match_operand:SI 2 "register_operand" ""))]
5560   "! flag_pic"
5561   [(set (match_dup 2) (high:SI (match_dup 3)))
5562    (set (match_dup 4) (match_dup 1))]
5563   "
5564 {
5565   operands[3] = XEXP (operands[0], 0);
5566   operands[4] = gen_rtx (MEM, GET_MODE (operands[0]),
5567                          gen_rtx (LO_SUM, SImode, operands[2], operands[3]));
5568   MEM_IN_STRUCT_P (operands[4]) = MEM_IN_STRUCT_P (operands[0]);
5569   MEM_VOLATILE_P (operands[4]) = MEM_VOLATILE_P (operands[0]);
5570   RTX_UNCHANGING_P (operands[4]) = RTX_UNCHANGING_P (operands[0]);
5571 }")
5572
5573 (define_split
5574   [(set (match_operand 0 "splittable_immediate_memory_operand" "")
5575         (match_operand 1 "general_operand" ""))
5576    (clobber (match_operand:SI 2 "register_operand" ""))]
5577   "flag_pic"
5578   [(set (match_dup 3) (match_dup 1))]
5579   "
5580 {
5581   rtx addr = legitimize_pic_address (XEXP (operands[0], 0),
5582                                      GET_MODE (operands[0]),
5583                                      operands[2]);
5584   operands[3] = gen_rtx (MEM, GET_MODE (operands[0]), addr);
5585   MEM_IN_STRUCT_P (operands[3]) = MEM_IN_STRUCT_P (operands[0]);
5586   MEM_VOLATILE_P (operands[3]) = MEM_VOLATILE_P (operands[0]);
5587   RTX_UNCHANGING_P (operands[3]) = RTX_UNCHANGING_P (operands[0]);
5588 }")
5589
5590 (define_split
5591   [(set (match_operand 0 "register_operand" "")
5592         (match_operand 1 "splittable_immediate_memory_operand" ""))]
5593   "flag_pic"
5594   [(set (match_dup 0) (match_dup 2))]
5595   "
5596 {
5597   rtx addr = legitimize_pic_address (XEXP (operands[1], 0),
5598                                      GET_MODE (operands[1]),
5599                                      operands[0]);
5600   operands[2] = gen_rtx (MEM, GET_MODE (operands[1]), addr);
5601   MEM_IN_STRUCT_P (operands[2]) = MEM_IN_STRUCT_P (operands[1]);
5602   MEM_VOLATILE_P (operands[2]) = MEM_VOLATILE_P (operands[1]);
5603   RTX_UNCHANGING_P (operands[2]) = RTX_UNCHANGING_P (operands[1]);
5604 }")
5605
5606 ;; Sign- and Zero-extend operations can have symbolic memory operands.
5607
5608 (define_split
5609   [(set (match_operand 0 "register_operand" "")
5610         (match_operator 1 "extend_op" [(match_operand 2 "splittable_immediate_memory_operand" "")]))]
5611   "flag_pic"
5612   [(set (match_dup 0) (match_op_dup 1 [(match_dup 3)]))]
5613   "
5614 {
5615   rtx addr = legitimize_pic_address (XEXP (operands[2], 0),
5616                                      GET_MODE (operands[2]),
5617                                      operands[0]);
5618   operands[3] = gen_rtx (MEM, GET_MODE (operands[2]), addr);
5619   MEM_IN_STRUCT_P (operands[3]) = MEM_IN_STRUCT_P (operands[2]);
5620   MEM_VOLATILE_P (operands[3]) = MEM_VOLATILE_P (operands[2]);
5621   RTX_UNCHANGING_P (operands[3]) = RTX_UNCHANGING_P (operands[2]);
5622 }")
5623
5624 (define_split
5625   [(set (match_operand:SI 0 "register_operand" "")
5626         (match_operand:SI 1 "immediate_operand" ""))]
5627   "! flag_pic && (GET_CODE (operands[1]) == SYMBOL_REF
5628                   || GET_CODE (operands[1]) == CONST
5629                   || GET_CODE (operands[1]) == LABEL_REF)"
5630   [(set (match_dup 0) (high:SI (match_dup 1)))
5631    (set (match_dup 0)
5632         (lo_sum:SI (match_dup 0) (match_dup 1)))]
5633   "")
5634
5635 ;; LABEL_REFs are not modified by `legitimize_pic_address'
5636 ;; so do not recurse infinitely in the PIC case.
5637 (define_split
5638   [(set (match_operand:SI 0 "register_operand" "")
5639         (match_operand:SI 1 "immediate_operand" ""))]
5640   "flag_pic && (GET_CODE (operands[1]) == SYMBOL_REF
5641                 || GET_CODE (operands[1]) == CONST)"
5642   [(set (match_dup 0) (match_dup 1))]
5643   "
5644 {
5645   operands[1] = legitimize_pic_address (operands[1], Pmode, operands[0]);
5646 }")
5647 \f
5648 ;; These split sne/seq insns.  The forms of the resulting insns are 
5649 ;; somewhat bogus, but they avoid extra patterns and show data dependency.
5650 ;; Nothing will look at these in detail after splitting has occurred.
5651
5652 ;; ??? v9 DImode versions are missing because addc and subc use %icc.
5653
5654 (define_split
5655   [(set (match_operand:SI 0 "register_operand" "")
5656         (ne:SI (match_operand:SI 1 "register_operand" "")
5657                (const_int 0)))
5658    (clobber (reg:CC 100))]
5659   ""
5660   [(set (reg:CC_NOOV 100) (compare:CC_NOOV (neg:SI (match_dup 1))
5661                                            (const_int 0)))
5662    (set (match_dup 0) (ltu:SI (reg:CC 100) (const_int 0)))]
5663   "")
5664
5665 (define_split
5666   [(set (match_operand:SI 0 "register_operand" "")
5667         (neg:SI (ne:SI (match_operand:SI 1 "register_operand" "")
5668                        (const_int 0))))
5669    (clobber (reg:CC 100))]
5670   ""
5671   [(set (reg:CC_NOOV 100) (compare:CC_NOOV (neg:SI (match_dup 1))
5672                                            (const_int 0)))
5673    (set (match_dup 0) (neg:SI (ltu:SI (reg:CC 100) (const_int 0))))]
5674   "")
5675
5676 (define_split
5677   [(set (match_operand:SI 0 "register_operand" "")
5678         (eq:SI (match_operand:SI 1 "register_operand" "")
5679                (const_int 0)))
5680    (clobber (reg:CC 100))]
5681   ""
5682   [(set (reg:CC_NOOV 100) (compare:CC_NOOV (neg:SI (match_dup 1))
5683                                            (const_int 0)))
5684    (set (match_dup 0) (geu:SI (reg:CC 100) (const_int 0)))]
5685   "")
5686
5687 (define_split
5688   [(set (match_operand:SI 0 "register_operand" "")
5689         (neg:SI (eq:SI (match_operand:SI 1 "register_operand" "")
5690                        (const_int 0))))
5691    (clobber (reg:CC 100))]
5692   ""
5693   [(set (reg:CC_NOOV 100) (compare:CC_NOOV (neg:SI (match_dup 1))
5694                                            (const_int 0)))
5695    (set (match_dup 0) (neg:SI (geu:SI (reg:CC 100) (const_int 0))))]
5696   "")
5697
5698 (define_split
5699   [(set (match_operand:SI 0 "register_operand" "")
5700         (plus:SI (ne:SI (match_operand:SI 1 "register_operand" "")
5701                         (const_int 0))
5702                  (match_operand:SI 2 "register_operand" "")))
5703    (clobber (reg:CC 100))]
5704   ""
5705   [(set (reg:CC_NOOV 100) (compare:CC_NOOV (neg:SI (match_dup 1))
5706                                            (const_int 0)))
5707    (set (match_dup 0) (plus:SI (ltu:SI (reg:CC 100) (const_int 0))
5708                                (match_dup 2)))]
5709   "")
5710
5711 (define_split
5712   [(set (match_operand:SI 0 "register_operand" "")
5713         (minus:SI (match_operand:SI 2 "register_operand" "")
5714                   (ne:SI (match_operand:SI 1 "register_operand" "")
5715                          (const_int 0))))
5716    (clobber (reg:CC 100))]
5717   ""
5718   [(set (reg:CC_NOOV 100) (compare:CC_NOOV (neg:SI (match_dup 1))
5719                                            (const_int 0)))
5720    (set (match_dup 0) (minus:SI (match_dup 2)
5721                                 (ltu:SI (reg:CC 100) (const_int 0))))]
5722   "")
5723
5724 (define_split
5725   [(set (match_operand:SI 0 "register_operand" "")
5726         (plus:SI (eq:SI (match_operand:SI 1 "register_operand" "")
5727                         (const_int 0))
5728                  (match_operand:SI 2 "register_operand" "")))
5729    (clobber (reg:CC 100))]
5730   ""
5731   [(set (reg:CC_NOOV 100) (compare:CC_NOOV (neg:SI (match_dup 1))
5732                                            (const_int 0)))
5733    (set (match_dup 0) (plus:SI (geu:SI (reg:CC 100) (const_int 0))
5734                                (match_dup 2)))]
5735   "")
5736
5737 (define_split
5738   [(set (match_operand:SI 0 "register_operand" "")
5739         (minus:SI (match_operand:SI 2 "register_operand" "")
5740                   (eq:SI (match_operand:SI 1 "register_operand" "")
5741                          (const_int 0))))
5742    (clobber (reg:CC 100))]
5743   ""
5744   [(set (reg:CC_NOOV 100) (compare:CC_NOOV (neg:SI (match_dup 1))
5745                                            (const_int 0)))
5746    (set (match_dup 0) (minus:SI (match_dup 2)
5747                                 (geu:SI (reg:CC 100) (const_int 0))))]
5748   "")
5749 \f
5750 ;; Peepholes go at the end.
5751
5752 ;; Optimize consecutive loads or stores into ldd and std when possible.
5753 ;; The conditions in which we do this are very restricted and are 
5754 ;; explained in the code for {registers,memory}_ok_for_ldd functions.
5755
5756 (define_peephole
5757   [(set (match_operand:SI 0 "register_operand" "=rf")
5758         (match_operand:SI 1 "memory_operand" ""))
5759    (set (match_operand:SI 2 "register_operand" "=rf")
5760         (match_operand:SI 3 "memory_operand" ""))]
5761   "! TARGET_ARCH64
5762    && registers_ok_for_ldd_peep (operands[0], operands[2]) 
5763    && ! MEM_VOLATILE_P (operands[1]) && ! MEM_VOLATILE_P (operands[3])
5764    && addrs_ok_for_ldd_peep (XEXP (operands[1], 0), XEXP (operands[3], 0))" 
5765   "ldd %1,%0")
5766
5767 (define_peephole
5768   [(set (match_operand:SI 0 "memory_operand" "")
5769         (match_operand:SI 1 "register_operand" "rf"))
5770    (set (match_operand:SI 2 "memory_operand" "")
5771         (match_operand:SI 3 "register_operand" "rf"))]
5772   "! TARGET_ARCH64
5773    && registers_ok_for_ldd_peep (operands[1], operands[3]) 
5774    && ! MEM_VOLATILE_P (operands[0]) && ! MEM_VOLATILE_P (operands[2])
5775    && addrs_ok_for_ldd_peep (XEXP (operands[0], 0), XEXP (operands[2], 0))"
5776   "std %1,%0")
5777  
5778 (define_peephole
5779   [(set (match_operand:SF 0 "register_operand" "=fr")
5780         (match_operand:SF 1 "memory_operand" ""))
5781    (set (match_operand:SF 2 "register_operand" "=fr")
5782         (match_operand:SF 3 "memory_operand" ""))]
5783   "! TARGET_ARCH64
5784    && registers_ok_for_ldd_peep (operands[0], operands[2]) 
5785    && ! MEM_VOLATILE_P (operands[1]) && ! MEM_VOLATILE_P (operands[3])
5786    && addrs_ok_for_ldd_peep (XEXP (operands[1], 0), XEXP (operands[3], 0))"
5787   "ldd %1,%0")
5788
5789 (define_peephole
5790   [(set (match_operand:SF 0 "memory_operand" "")
5791         (match_operand:SF 1 "register_operand" "fr"))
5792    (set (match_operand:SF 2 "memory_operand" "")
5793         (match_operand:SF 3 "register_operand" "fr"))]
5794   "! TARGET_ARCH64
5795    && registers_ok_for_ldd_peep (operands[1], operands[3]) 
5796    && ! MEM_VOLATILE_P (operands[0]) && ! MEM_VOLATILE_P (operands[2])
5797    && addrs_ok_for_ldd_peep (XEXP (operands[0], 0), XEXP (operands[2], 0))"
5798   "std %1,%0")
5799
5800 (define_peephole
5801   [(set (match_operand:SI 0 "register_operand" "=rf")
5802         (match_operand:SI 1 "memory_operand" ""))
5803    (set (match_operand:SI 2 "register_operand" "=rf")
5804         (match_operand:SI 3 "memory_operand" ""))]
5805   "! TARGET_ARCH64
5806    && registers_ok_for_ldd_peep (operands[2], operands[0]) 
5807    && ! MEM_VOLATILE_P (operands[3]) && ! MEM_VOLATILE_P (operands[1])
5808    && addrs_ok_for_ldd_peep (XEXP (operands[3], 0), XEXP (operands[1], 0))"
5809   "ldd %3,%2")
5810
5811 (define_peephole
5812   [(set (match_operand:SI 0 "memory_operand" "")
5813         (match_operand:SI 1 "register_operand" "rf"))
5814    (set (match_operand:SI 2 "memory_operand" "")
5815         (match_operand:SI 3 "register_operand" "rf"))]
5816   "! TARGET_ARCH64
5817    && registers_ok_for_ldd_peep (operands[3], operands[1]) 
5818    && ! MEM_VOLATILE_P (operands[2]) && ! MEM_VOLATILE_P (operands[0])
5819    && addrs_ok_for_ldd_peep (XEXP (operands[2], 0), XEXP (operands[0], 0))" 
5820   "std %3,%2")
5821  
5822 (define_peephole
5823   [(set (match_operand:SF 0 "register_operand" "=fr")
5824         (match_operand:SF 1 "memory_operand" ""))
5825    (set (match_operand:SF 2 "register_operand" "=fr")
5826         (match_operand:SF 3 "memory_operand" ""))]
5827   "! TARGET_ARCH64
5828    && registers_ok_for_ldd_peep (operands[2], operands[0]) 
5829    && ! MEM_VOLATILE_P (operands[3]) && ! MEM_VOLATILE_P (operands[1])
5830    && addrs_ok_for_ldd_peep (XEXP (operands[3], 0), XEXP (operands[1], 0))"
5831   "ldd %3,%2")
5832
5833 (define_peephole
5834   [(set (match_operand:SF 0 "memory_operand" "")
5835         (match_operand:SF 1 "register_operand" "fr"))
5836    (set (match_operand:SF 2 "memory_operand" "")
5837         (match_operand:SF 3 "register_operand" "fr"))]
5838   "! TARGET_ARCH64
5839    && registers_ok_for_ldd_peep (operands[3], operands[1]) 
5840    && ! MEM_VOLATILE_P (operands[2]) && ! MEM_VOLATILE_P (operands[0])
5841    && addrs_ok_for_ldd_peep (XEXP (operands[2], 0), XEXP (operands[0], 0))"
5842   "std %3,%2")
5843  
5844 ;; Optimize the case of following a reg-reg move with a test
5845 ;; of reg just moved.  Don't allow floating point regs for operand 0 or 1.
5846 ;; This can result from a float to fix conversion.
5847
5848 (define_peephole
5849   [(set (match_operand:SI 0 "register_operand" "=r")
5850         (match_operand:SI 1 "register_operand" "r"))
5851    (set (reg:CC 100)
5852         (compare:CC (match_operand:SI 2 "register_operand" "r")
5853                     (const_int 0)))]
5854   "(rtx_equal_p (operands[2], operands[0])
5855     || rtx_equal_p (operands[2], operands[1]))
5856    && ! FP_REG_P (operands[0]) && ! FP_REG_P (operands[1])"
5857   "orcc %1,0,%0")
5858
5859 (define_peephole
5860   [(set (match_operand:DI 0 "register_operand" "=r")
5861         (match_operand:DI 1 "register_operand" "r"))
5862    (set (reg:CCX 100)
5863         (compare:CCX (match_operand:DI 2 "register_operand" "r")
5864                     (const_int 0)))]
5865   "TARGET_ARCH64
5866    && (rtx_equal_p (operands[2], operands[0])
5867        || rtx_equal_p (operands[2], operands[1]))
5868    && ! FP_REG_P (operands[0]) && ! FP_REG_P (operands[1])"
5869   "orcc %1,0,%0")
5870
5871 ;; Do {sign,zero}-extended compares somewhat more efficiently.
5872 ;; ??? Is this now the Right Way to do this?  Or will SCRATCH
5873 ;;     eventually have some impact here?
5874
5875 (define_peephole
5876   [(set (match_operand:HI 0 "register_operand" "")
5877         (match_operand:HI 1 "memory_operand" ""))
5878    (set (match_operand:SI 2 "register_operand" "")
5879         (sign_extend:SI (match_dup 0)))
5880    (set (reg:CC 100)
5881         (compare:CC (match_dup 2)
5882                     (const_int 0)))]
5883   ""
5884   "ldsh %1,%0\;orcc %0,0,%2")
5885
5886 (define_peephole
5887   [(set (match_operand:HI 0 "register_operand" "")
5888         (match_operand:HI 1 "memory_operand" ""))
5889    (set (match_operand:DI 2 "register_operand" "")
5890         (sign_extend:DI (match_dup 0)))
5891    (set (reg:CCX 100)
5892         (compare:CCX (match_dup 2)
5893                      (const_int 0)))]
5894   "TARGET_ARCH64"
5895   "ldsh %1,%0\;orcc %0,0,%2")
5896
5897 (define_peephole
5898   [(set (match_operand:QI 0 "register_operand" "")
5899         (match_operand:QI 1 "memory_operand" ""))
5900    (set (match_operand:SI 2 "register_operand" "")
5901         (sign_extend:SI (match_dup 0)))
5902    (set (reg:CC 100)
5903         (compare:CC (match_dup 2)
5904                     (const_int 0)))]
5905   ""
5906   "ldsb %1,%0\;orcc %0,0,%2")
5907
5908 (define_peephole
5909   [(set (match_operand:QI 0 "register_operand" "")
5910         (match_operand:QI 1 "memory_operand" ""))
5911    (set (match_operand:DI 2 "register_operand" "")
5912         (sign_extend:DI (match_dup 0)))
5913    (set (reg:CCX 100)
5914         (compare:CCX (match_dup 2)
5915                      (const_int 0)))]
5916   "TARGET_ARCH64"
5917   "ldsb %1,%0\;orcc %0,0,%2")
5918
5919 ;; Floating-point move peepholes
5920 ;; ??? v9: Do we want similar ones?
5921
5922 (define_peephole
5923   [(set (match_operand:SI 0 "register_operand" "=r")
5924         (lo_sum:SI (match_dup 0)
5925                    (match_operand:SI 1 "immediate_operand" "i")))
5926    (set (match_operand:DF 2 "register_operand" "=er")
5927         (mem:DF (match_dup 0)))]
5928   "RTX_UNCHANGING_P (operands[1]) && reg_unused_after (operands[0], insn)"
5929   "*
5930 {
5931   /* Go by way of output_move_double in case the register in operand 2
5932      is not properly aligned for ldd.  */
5933   operands[1] = gen_rtx (MEM, DFmode,
5934                          gen_rtx (LO_SUM, SImode, operands[0], operands[1]));
5935   operands[0] = operands[2];
5936   return output_move_double (operands);
5937 }")
5938
5939 (define_peephole
5940   [(set (match_operand:SI 0 "register_operand" "=r")
5941         (lo_sum:SI (match_dup 0)
5942                    (match_operand:SI 1 "immediate_operand" "i")))
5943    (set (match_operand:SF 2 "register_operand" "=fr")
5944         (mem:SF (match_dup 0)))]
5945   "RTX_UNCHANGING_P (operands[1]) && reg_unused_after (operands[0], insn)"
5946   "ld [%0+%%lo(%a1)],%2")
5947
5948 ;; Return peepholes.  First the "normal" ones.
5949 ;; These are necessary to catch insns ending up in the epilogue delay list.
5950
5951 (define_insn "*return_qi"
5952   [(set (match_operand:QI 0 "restore_operand" "")
5953         (match_operand:QI 1 "arith_operand" "rI"))
5954    (return)]
5955   "! TARGET_EPILOGUE && ! TARGET_LIVE_G0"
5956   "*
5957 {
5958   if (! TARGET_ARCH64 && current_function_returns_struct)
5959     return \"jmp %%i7+12\;restore %%g0,%1,%Y0\";
5960   else
5961     return \"ret\;restore %%g0,%1,%Y0\";
5962 }"
5963   [(set_attr "type" "multi")])
5964
5965 (define_insn "*return_hi"
5966   [(set (match_operand:HI 0 "restore_operand" "")
5967         (match_operand:HI 1 "arith_operand" "rI"))
5968    (return)]
5969   "! TARGET_EPILOGUE && ! TARGET_LIVE_G0"
5970   "*
5971 {
5972   if (! TARGET_ARCH64 && current_function_returns_struct)
5973     return \"jmp %%i7+12\;restore %%g0,%1,%Y0\";
5974   else
5975     return \"ret\;restore %%g0,%1,%Y0\";
5976 }"
5977   [(set_attr "type" "multi")])
5978
5979 (define_insn "*return_si"
5980   [(set (match_operand:SI 0 "restore_operand" "")
5981         (match_operand:SI 1 "arith_operand" "rI"))
5982    (return)]
5983   "! TARGET_EPILOGUE && ! TARGET_LIVE_G0"
5984   "*
5985 {
5986   if (! TARGET_ARCH64 && current_function_returns_struct)
5987     return \"jmp %%i7+12\;restore %%g0,%1,%Y0\";
5988   else
5989     return \"ret\;restore %%g0,%1,%Y0\";
5990 }"
5991   [(set_attr "type" "multi")])
5992
5993 ;; The following pattern is only generated by delayed-branch scheduling,
5994 ;; when the insn winds up in the epilogue.  This can only happen when
5995 ;; ! TARGET_FPU because otherwise fp return values are in %f0.
5996 (define_insn "*return_sf_no_fpu"
5997   [(set (match_operand:SF 0 "restore_operand" "r")
5998         (match_operand:SF 1 "register_operand" "r"))
5999    (return)]
6000   "! TARGET_FPU && ! TARGET_EPILOGUE && ! TARGET_LIVE_G0"
6001   "*
6002 {
6003   if (! TARGET_ARCH64 && current_function_returns_struct)
6004     return \"jmp %%i7+12\;restore %%g0,%1,%Y0\";
6005   else
6006     return \"ret\;restore %%g0,%1,%Y0\";
6007 }"
6008   [(set_attr "type" "multi")])
6009
6010 (define_insn "*return_addsi"
6011   [(set (match_operand:SI 0 "restore_operand" "")
6012         (plus:SI (match_operand:SI 1 "arith_operand" "%r")
6013                  (match_operand:SI 2 "arith_operand" "rI")))
6014    (return)]
6015   "! TARGET_EPILOGUE && ! TARGET_LIVE_G0
6016    && (register_operand (operands[1], SImode)
6017        || register_operand (operands[2], SImode))"
6018   "*
6019 {
6020   if (! TARGET_ARCH64 && current_function_returns_struct)
6021     return \"jmp %%i7+12\;restore %r1,%2,%Y0\";
6022   else
6023     return \"ret\;restore %r1,%2,%Y0\";
6024 }"
6025   [(set_attr "type" "multi")])
6026
6027 (define_insn "*return_di"
6028   [(set (match_operand:DI 0 "restore_operand" "")
6029         (match_operand:DI 1 "arith_double_operand" "rHI"))
6030    (return)]
6031   "TARGET_ARCH64 && ! TARGET_EPILOGUE"
6032   "ret\;restore %%g0,%1,%Y0"
6033   [(set_attr "type" "multi")])
6034
6035 (define_insn "*return_adddi"
6036   [(set (match_operand:DI 0 "restore_operand" "")
6037         (plus:DI (match_operand:DI 1 "arith_double_operand" "%r")
6038                  (match_operand:DI 2 "arith_double_operand" "rHI")))
6039    (return)]
6040   "TARGET_ARCH64 && ! TARGET_EPILOGUE
6041    && (register_operand (operands[1], DImode)
6042        || register_operand (operands[2], DImode))"
6043   "ret\;restore %r1,%2,%Y0"
6044   [(set_attr "type" "multi")])
6045
6046 (define_insn "*return_subsi"
6047   [(set (match_operand:SI 0 "restore_operand" "")
6048         (minus:SI (match_operand:SI 1 "register_operand" "r")
6049                   (match_operand:SI 2 "small_int" "I")))
6050    (return)]
6051   "! TARGET_EPILOGUE && INTVAL (operands[2]) != -4096"
6052   "ret\;restore %1,%n2,%Y0"
6053   [(set_attr "type" "multi")])
6054
6055 ;; The following pattern is only generated by delayed-branch scheduling,
6056 ;; when the insn winds up in the epilogue.
6057 (define_insn "*return_sf"
6058   [(set (reg:SF 32)
6059         (match_operand:SF 0 "register_operand" "f"))
6060    (return)]
6061   "! TARGET_EPILOGUE"
6062   "ret\;fmovs %0,%%f0"
6063   [(set_attr "type" "multi")])
6064
6065 ;; Now peepholes to do a call followed by a jump.
6066
6067 (define_peephole
6068   [(parallel [(set (match_operand 0 "" "")
6069                    (call (mem:SI (match_operand:SI 1 "call_operand_address" "ps"))
6070                          (match_operand 2 "" "")))
6071               (clobber (reg:SI 15))])
6072    (set (pc) (label_ref (match_operand 3 "" "")))]
6073   "short_branch (INSN_UID (insn), INSN_UID (operands[3]))"
6074   "call %a1,%2\;add %%o7,(%l3-.-4),%%o7")
6075
6076 (define_peephole
6077   [(parallel [(call (mem:SI (match_operand:SI 0 "call_operand_address" "ps"))
6078                     (match_operand 1 "" ""))
6079               (clobber (reg:SI 15))])
6080    (set (pc) (label_ref (match_operand 2 "" "")))]
6081   "short_branch (INSN_UID (insn), INSN_UID (operands[2]))"
6082   "*
6083 {
6084   return \"call %a0,%1\;add %%o7,(%l2-.-4),%%o7\";
6085 }")
6086
6087 (define_peephole
6088   [(parallel [(set (match_operand 0 "" "")
6089                    (call (mem:SI (match_operand:DI 1 "call_operand_address" "ps"))
6090                          (match_operand 2 "" "")))
6091               (clobber (reg:DI 15))])
6092    (set (pc) (label_ref (match_operand 3 "" "")))]
6093   "TARGET_ARCH64 && short_branch (INSN_UID (insn), INSN_UID (operands[3]))"
6094   "call %a1,%2\;add %%o7,(%l3-.-4),%%o7")
6095
6096 (define_peephole
6097   [(parallel [(call (mem:SI (match_operand:DI 0 "call_operand_address" "ps"))
6098                     (match_operand 1 "" ""))
6099               (clobber (reg:DI 15))])
6100    (set (pc) (label_ref (match_operand 2 "" "")))]
6101   "TARGET_ARCH64 && short_branch (INSN_UID (insn), INSN_UID (operands[2]))"
6102   "call %a0,%1\;add %%o7,(%l2-.-4),%%o7")
6103
6104 ;; Other miscellaneous peepholes.
6105
6106 ;; (reg:SI 100) is created by the {add,neg,sub}di patterns.
6107 (define_peephole
6108   [(parallel [(set (match_operand:SI 0 "register_operand" "=r")
6109                    (minus:SI (match_operand:SI 1 "reg_or_0_operand" "rJ")
6110                              (reg:SI 100)))
6111               (clobber (reg:CC 100))])
6112    (set (reg:CC 100) (compare (match_dup 0) (const_int 0)))]
6113   ""
6114   "subxcc %r1,0,%0")