OSDN Git Service

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