OSDN Git Service

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