OSDN Git Service

Undo cvs entry 1.4 "Reorg sethi_{hi,si} patterns." and add comment why.
[pf3gnuchains/gcc-fork.git] / gcc / config / sparc / sparc.md
1 ;;- Machine description for SPARC chip for GNU C compiler
2 ;;  Copyright (C) 1987, 88, 89, 92-96, 1997 Free Software Foundation, Inc.
3 ;;  Contributed by Michael Tiemann (tiemann@cygnus.com)
4 ;;  64 bit SPARC V9 support by Michael Tiemann, Jim Wilson, and Doug Evans,
5 ;;  at Cygnus Support.
6
7 ;; This file is part of GNU CC.
8
9 ;; GNU CC is free software; you can redistribute it and/or modify
10 ;; it under the terms of the GNU General Public License as published by
11 ;; the Free Software Foundation; either version 2, or (at your option)
12 ;; any later version.
13
14 ;; GNU CC is distributed in the hope that it will be useful,
15 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
16 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17 ;; GNU General Public License for more details.
18
19 ;; You should have received a copy of the GNU General Public License
20 ;; along with GNU CC; see the file COPYING.  If not, write to
21 ;; the Free Software Foundation, 59 Temple Place - Suite 330,
22 ;; Boston, MA 02111-1307, USA.
23
24 ;;- See file "rtl.def" for documentation on define_insn, match_*, et. al.
25
26 ;; The upper 32 fp regs on the v9 can't hold SFmode values.  To deal with this
27 ;; a second register class, EXTRA_FP_REGS, exists for the v9 chip.  The name
28 ;; is a bit of a misnomer as it covers all 64 fp regs.  The corresponding
29 ;; constraint letter is 'e'.  To avoid any confusion, 'e' is used instead of
30 ;; 'f' for all DF/TFmode values, including those that are specific to the v8.
31 ;;
32 ;; -mlive-g0 is *not* supported for TARGET_ARCH64, so we don't bother to
33 ;; test TARGET_LIVE_G0 if we have TARGET_ARCH64.
34
35 ;; Attribute for cpu type.
36 ;; These must match the values for enum processor_type in sparc.h.
37 (define_attr "cpu" "v7,cypress,v8,supersparc,sparclite,f930,f934,sparclet,tsc701,v8plus,v9,ultrasparc"
38   (const (symbol_ref "sparc_cpu_attr")))
39
40 ;; Attribute for the instruction set.
41 ;; At present we only need to distinguish v9/!v9, but for clarity we
42 ;; test TARGET_V8 too.
43 (define_attr "isa" "v6,v8,v9,sparclet"
44  (const
45   (cond [(symbol_ref "TARGET_V9") (const_string "v9")
46          (symbol_ref "TARGET_V8") (const_string "v8")
47          (symbol_ref "TARGET_SPARCLET") (const_string "sparclet")]
48         (const_string "v6"))))
49
50 ;; Architecture size.
51 (define_attr "arch" "arch32bit,arch64bit"
52  (const
53   (cond [(symbol_ref "TARGET_ARCH64") (const_string "arch64bit")]
54         (const_string "arch32bit"))))
55
56 ;; Whether -mlive-g0 is in effect.
57 (define_attr "live_g0" "no,yes"
58  (const
59   (cond [(symbol_ref "TARGET_LIVE_G0") (const_string "yes")]
60         (const_string "no"))))
61
62 ;; Insn type.  Used to default other attribute values.
63
64 ;; type "unary" insns have one input operand (1) and one output operand (0)
65 ;; type "binary" insns have two input operands (1,2) and one output (0)
66 ;; type "compare" insns have one or two input operands (0,1) and no output
67 ;; type "call_no_delay_slot" is a call followed by an unimp instruction.
68
69 (define_attr "type"
70   "move,unary,binary,compare,load,store,ialu,shift,uncond_branch,branch,call,call_no_delay_slot,address,imul,fpload,fpstore,fp,fpcmp,fpmul,fpdivs,fpdivd,fpsqrt,cmove,multi,misc"
71   (const_string "binary"))
72
73 ;; Set true if insn uses call-clobbered intermediate register.
74 (define_attr "use_clobbered" "false,true"
75   (if_then_else (and (eq_attr "type" "address")
76                      (match_operand 0 "clobbered_register" ""))
77                 (const_string "true")
78                 (const_string "false")))
79
80 ;; Length (in # of insns).
81 (define_attr "length" ""
82   (cond [(eq_attr "type" "load,fpload")
83          (if_then_else (match_operand 1 "symbolic_memory_operand" "")
84                        (const_int 2) (const_int 1))
85
86          (eq_attr "type" "store,fpstore")
87          (if_then_else (match_operand 0 "symbolic_memory_operand" "")
88                        (const_int 2) (const_int 1))
89
90          (eq_attr "type" "address") (const_int 2)
91
92          (eq_attr "type" "binary")
93          (if_then_else (ior (match_operand 2 "arith_operand" "")
94                             (match_operand 2 "arith_double_operand" ""))
95                        (const_int 1) (const_int 3))
96
97          (eq_attr "type" "multi") (const_int 2)
98
99          (eq_attr "type" "move,unary")
100          (if_then_else (ior (match_operand 1 "arith_operand" "")
101                             (match_operand 1 "arith_double_operand" ""))
102                        (const_int 1) (const_int 2))]
103
104         (const_int 1)))
105
106 (define_asm_attributes
107   [(set_attr "length" "1")
108    (set_attr "type" "multi")])
109
110 ;; Attributes for instruction and branch scheduling
111
112 (define_attr "in_call_delay" "false,true"
113   (cond [(eq_attr "type" "uncond_branch,branch,call,call_no_delay_slot,multi")
114                 (const_string "false")
115          (eq_attr "type" "load,fpload,store,fpstore")
116                 (if_then_else (eq_attr "length" "1")
117                               (const_string "true")
118                               (const_string "false"))
119          (eq_attr "type" "address")
120                 (if_then_else (eq_attr "use_clobbered" "false")
121                               (const_string "true")
122                               (const_string "false"))]
123         (if_then_else (eq_attr "length" "1")
124                       (const_string "true")
125                       (const_string "false"))))
126
127 (define_delay (eq_attr "type" "call")
128   [(eq_attr "in_call_delay" "true") (nil) (nil)])
129
130 ;; ??? Should implement the notion of predelay slots for floating point
131 ;; branches.  This would allow us to remove the nop always inserted before
132 ;; a floating point branch.
133
134 ;; ??? It is OK for fill_simple_delay_slots to put load/store instructions
135 ;; in a delay slot, but it is not OK for fill_eager_delay_slots to do so.
136 ;; This is because doing so will add several pipeline stalls to the path
137 ;; that the load/store did not come from.  Unfortunately, there is no way
138 ;; to prevent fill_eager_delay_slots from using load/store without completely
139 ;; disabling them.  For the SPEC benchmark set, this is a serious lose,
140 ;; because it prevents us from moving back the final store of inner loops.
141
142 (define_attr "in_branch_delay" "false,true"
143   (if_then_else (and (eq_attr "type" "!uncond_branch,branch,call,call_no_delay_slot,multi")
144                      (eq_attr "length" "1"))
145                 (const_string "true")
146                 (const_string "false")))
147
148 (define_attr "in_uncond_branch_delay" "false,true"
149   (if_then_else (and (eq_attr "type" "!uncond_branch,branch,call,call_no_delay_slot,multi")
150                      (eq_attr "length" "1"))
151                 (const_string "true")
152                 (const_string "false")))
153
154 (define_attr "in_annul_branch_delay" "false,true"
155   (if_then_else (and (eq_attr "type" "!uncond_branch,branch,call,call_no_delay_slot,multi")
156                      (eq_attr "length" "1"))
157                 (const_string "true")
158                 (const_string "false")))
159
160 (define_delay (eq_attr "type" "branch")
161   [(eq_attr "in_branch_delay" "true")
162    (nil) (eq_attr "in_annul_branch_delay" "true")])
163
164 (define_delay (eq_attr "type" "uncond_branch")
165   [(eq_attr "in_uncond_branch_delay" "true")
166    (nil) (nil)])
167    
168 ;; Function units of the SPARC
169
170 ;; (define_function_unit {name} {num-units} {n-users} {test}
171 ;;                       {ready-delay} {issue-delay} [{conflict-list}])
172
173 ;; The integer ALU.
174 ;; (Noted only for documentation; units that take one cycle do not need to
175 ;; be specified.)
176
177 ;; On the sparclite, integer multiply takes 1, 3, or 5 cycles depending on
178 ;; the inputs.
179
180 ;; (define_function_unit "alu" 1 0
181 ;;  (eq_attr "type" "unary,binary,move,address") 1 0)
182
183 ;; ---- cypress CY7C602 scheduling:
184 ;; Memory with load-delay of 1 (i.e., 2 cycle load).
185 (define_function_unit "memory" 1 0 
186   (and (eq_attr "type" "load,fpload") (eq_attr "cpu" "cypress")) 2 2)
187
188 ;; SPARC has two floating-point units: the FP ALU,
189 ;; and the FP MUL/DIV/SQRT unit.
190 ;; Instruction timings on the CY7C602 are as follows
191 ;; FABSs        4
192 ;; FADDs/d      5/5
193 ;; FCMPs/d      4/4
194 ;; FDIVs/d      23/37
195 ;; FMOVs        4
196 ;; FMULs/d      5/7
197 ;; FNEGs        4
198 ;; FSQRTs/d     34/63
199 ;; FSUBs/d      5/5
200 ;; FdTOi/s      5/5
201 ;; FsTOi/d      5/5
202 ;; FiTOs/d      9/5
203
204 ;; The CY7C602 can only support 2 fp isnsn simultaneously.
205 ;; More insns cause the chip to stall.
206
207 (define_function_unit "fp_alu" 1 0
208   (and (eq_attr "type" "fp")            (eq_attr "cpu" "cypress")) 5 5)
209 (define_function_unit "fp_mds" 1 0
210   (and (eq_attr "type" "fpmul")         (eq_attr "cpu" "cypress")) 7 7)
211 (define_function_unit "fp_mds" 1 0
212   (and (eq_attr "type" "fpdivs,fpdivd") (eq_attr "cpu" "cypress")) 37 37)
213 (define_function_unit "fp_mds" 1 0
214   (and (eq_attr "type" "fpsqrt")        (eq_attr "cpu" "cypress")) 63 63)
215
216 ;; ----- The TMS390Z55 scheduling
217 ;; The Supersparc can issue 1 - 3 insns per cycle; here we assume
218 ;; three insns/cycle, and hence multiply all costs by three.
219 ;; Combinations up to two integer, one ld/st, one fp.
220 ;; Memory delivers its result in one cycle to IU, zero cycles to FP
221 (define_function_unit "memory" 1 0
222   (and (eq_attr "type" "load")          (eq_attr "cpu" "supersparc")) 3 3)
223 (define_function_unit "memory" 1 0
224   (and (eq_attr "type" "fpload")        (eq_attr "cpu" "supersparc")) 1 3)
225 ;; at least one in three instructions can be a mem opt.
226 (define_function_unit "memory" 1 0
227   (and (eq_attr "type" "store,fpstore") (eq_attr "cpu" "supersparc")) 1 3)
228 ;; at least one in three instructions can be a shift op.
229 (define_function_unit "shift" 1 0
230   (and (eq_attr "type" "shift")         (eq_attr "cpu" "supersparc")) 1 3)
231
232 ;; There are only two write ports to the integer register file
233 ;; A store also uses a write port
234 (define_function_unit "iwport" 2 0
235   (and (eq_attr "type" "load,store,shift,ialu") (eq_attr "cpu" "supersparc")) 1 3)
236
237 ;; Timings; throughput/latency
238 ;; FADD     1/3    add/sub, format conv, compar, abs, neg
239 ;; FMUL     1/3
240 ;; FDIVs    4/6
241 ;; FDIVd    7/9
242 ;; FSQRTs   6/8
243 ;; FSQRTd  10/12
244 ;; IMUL     4/4
245
246 (define_function_unit "fp_alu" 1 0
247   (and (eq_attr "type" "fp,fpcmp") (eq_attr "cpu" "supersparc")) 9 3)
248 (define_function_unit "fp_mds" 1 0
249   (and (eq_attr "type" "fpmul")    (eq_attr "cpu" "supersparc")) 9 3)
250 (define_function_unit "fp_mds" 1 0
251   (and (eq_attr "type" "fpdivs")   (eq_attr "cpu" "supersparc")) 18 12)
252 (define_function_unit "fp_mds" 1 0
253   (and (eq_attr "type" "fpdivd")   (eq_attr "cpu" "supersparc")) 27 21)
254 (define_function_unit "fp_mds" 1 0
255   (and (eq_attr "type" "fpsqrt")   (eq_attr "cpu" "supersparc")) 36 30)
256 (define_function_unit "fp_mds" 1 0
257   (and (eq_attr "type" "imul")     (eq_attr "cpu" "supersparc")) 12 12)
258
259 ;; ----- sparclet tsc701 scheduling
260 ;; The tsc701 issues 1 insn per cycle.
261 ;; Results may be written back out of order.
262
263 ;; Loads take 2 extra cycles to complete and 4 can be buffered at a time.
264 (define_function_unit "tsc701_load" 4 1
265   (and (eq_attr "type" "load")          (eq_attr "cpu" "tsc701")) 3 1)
266 ;; Stores take 2(?) extra cycles to complete.
267 ;; It is desirable to not have any memory operation in the following 2 cycles.
268 ;; (??? or 2 memory ops in the case of std).
269 (define_function_unit "tsc701_store" 1 0
270   (and (eq_attr "type" "store")         (eq_attr "cpu" "tsc701")) 3 3
271   [(eq_attr "type" "load,store")])
272 ;; The multiply unit has a latency of 5.
273 (define_function_unit "tsc701_mul" 1 0
274   (and (eq_attr "type" "imul")          (eq_attr "cpu" "tsc701")) 5 5)
275
276 ;; ----- The UltraSPARC-1 scheduling
277 ;; The Ultrasparc can issue 1 - 4 insns per cycle; here we assume
278 ;; four insns/cycle, and hence multiply all costs by four.
279
280 ;; Memory delivers its result in three cycles to IU, three cycles to FP
281 (define_function_unit "memory" 1 0
282   (and (eq_attr "type" "load,fpload")   (eq_attr "cpu" "ultrasparc")) 12 4)
283 (define_function_unit "memory" 1 0
284   (and (eq_attr "type" "store,fpstore") (eq_attr "cpu" "ultrasparc"))  4 4)
285 (define_function_unit "ieu" 1 0
286   (and (eq_attr "type" "ialu")          (eq_attr "cpu" "ultrasparc"))  1 2)
287 (define_function_unit "ieu" 1 0
288   (and (eq_attr "type" "shift")         (eq_attr "cpu" "ultrasparc"))  1 4)
289 (define_function_unit "ieu" 1 0
290   (and (eq_attr "type" "cmove")         (eq_attr "cpu" "ultrasparc"))  8 4)
291
292 ;; Timings; throughput/latency
293 ;; ?? FADD     1/3    add/sub, format conv, compar, abs, neg
294 ;; ?? FMUL     1/3
295 ;; ?? FDIVs    1/12
296 ;; ?? FDIVd    1/22
297 ;; ?? FSQRTs   1/12
298 ;; ?? FSQRTd   1/22
299
300 (define_function_unit "fp" 1 0
301   (and (eq_attr "type" "fp")       (eq_attr "cpu" "ultrasparc")) 12 2)
302 (define_function_unit "fp" 1 0
303   (and (eq_attr "type" "fpcmp")    (eq_attr "cpu" "ultrasparc"))  8 2)
304 (define_function_unit "fp" 1 0
305   (and (eq_attr "type" "fpmul")    (eq_attr "cpu" "ultrasparc")) 12 2)
306 (define_function_unit "fp" 1 0
307   (and (eq_attr "type" "fpdivs")   (eq_attr "cpu" "ultrasparc")) 48 2)
308 (define_function_unit "fp" 1 0
309   (and (eq_attr "type" "fpdivd")   (eq_attr "cpu" "ultrasparc")) 88 2)
310 (define_function_unit "fp" 1 0
311   (and (eq_attr "type" "fpsqrt")   (eq_attr "cpu" "ultrasparc")) 48 2)
312 \f
313 ;; Compare instructions.
314 ;; This controls RTL generation and register allocation.
315
316 ;; We generate RTL for comparisons and branches by having the cmpxx 
317 ;; patterns store away the operands.  Then, the scc and bcc patterns
318 ;; emit RTL for both the compare and the branch.
319 ;;
320 ;; We do this because we want to generate different code for an sne and
321 ;; seq insn.  In those cases, if the second operand of the compare is not
322 ;; const0_rtx, we want to compute the xor of the two operands and test
323 ;; it against zero.
324 ;;
325 ;; We start with the DEFINE_EXPANDs, then the DEFINE_INSNs to match
326 ;; the patterns.  Finally, we have the DEFINE_SPLITs for some of the scc
327 ;; insns that actually require more than one machine instruction.
328
329 ;; Put cmpsi first among compare insns so it matches two CONST_INT operands.
330
331 (define_expand "cmpsi"
332   [(set (reg:CC 100)
333         (compare:CC (match_operand:SI 0 "register_operand" "")
334                     (match_operand:SI 1 "arith_operand" "")))]
335   ""
336   "
337 {
338   sparc_compare_op0 = operands[0];
339   sparc_compare_op1 = operands[1];
340   DONE;
341 }")
342
343 (define_expand "cmpdi"
344   [(set (reg:CCX 100)
345         (compare:CCX (match_operand:DI 0 "register_operand" "")
346                      (match_operand:DI 1 "arith_double_operand" "")))]
347   "TARGET_ARCH64"
348   "
349 {
350   sparc_compare_op0 = operands[0];
351   sparc_compare_op1 = operands[1];
352   DONE;
353 }")
354
355 (define_expand "cmpsf"
356   ;; The 96 here isn't ever used by anyone.
357   [(set (reg:CCFP 96)
358         (compare:CCFP (match_operand:SF 0 "register_operand" "")
359                       (match_operand:SF 1 "register_operand" "")))]
360   "TARGET_FPU"
361   "
362 {
363   sparc_compare_op0 = operands[0];
364   sparc_compare_op1 = operands[1];
365   DONE;
366 }")
367
368 (define_expand "cmpdf"
369   ;; The 96 here isn't ever used by anyone.
370   [(set (reg:CCFP 96)
371         (compare:CCFP (match_operand:DF 0 "register_operand" "")
372                       (match_operand:DF 1 "register_operand" "")))]
373   "TARGET_FPU"
374   "
375 {
376   sparc_compare_op0 = operands[0];
377   sparc_compare_op1 = operands[1];
378   DONE;
379 }")
380
381 (define_expand "cmptf"
382   ;; The 96 here isn't ever used by anyone.
383   [(set (reg:CCFP 96)
384         (compare:CCFP (match_operand:TF 0 "register_operand" "")
385                       (match_operand:TF 1 "register_operand" "")))]
386   "TARGET_FPU"
387   "
388 {
389   sparc_compare_op0 = operands[0];
390   sparc_compare_op1 = operands[1];
391   DONE;
392 }")
393
394 ;; Now the compare DEFINE_INSNs.
395
396 (define_insn "*cmpsi_insn"
397   [(set (reg:CC 100)
398         (compare:CC (match_operand:SI 0 "register_operand" "r")
399                     (match_operand:SI 1 "arith_operand" "rI")))]
400   ""
401   "cmp %0,%1"
402   [(set_attr "type" "compare")])
403
404 (define_insn "*cmpdi_sp64"
405   [(set (reg:CCX 100)
406         (compare:CCX (match_operand:DI 0 "register_operand" "r")
407                      (match_operand:DI 1 "arith_double_operand" "rHI")))]
408   "TARGET_ARCH64"
409   "cmp %0,%1"
410   [(set_attr "type" "compare")])
411
412 (define_insn "*cmpsf_fpe"
413   [(set (match_operand:CCFPE 0 "fcc_reg_operand" "=c")
414         (compare:CCFPE (match_operand:SF 1 "register_operand" "f")
415                        (match_operand:SF 2 "register_operand" "f")))]
416   "TARGET_FPU"
417   "*
418 {
419   if (TARGET_V9)
420     return \"fcmpes %0,%1,%2\";
421   return \"fcmpes %1,%2\";
422 }"
423   [(set_attr "type" "fpcmp")])
424
425 (define_insn "*cmpdf_fpe"
426   [(set (match_operand:CCFPE 0 "fcc_reg_operand" "=c")
427         (compare:CCFPE (match_operand:DF 1 "register_operand" "e")
428                        (match_operand:DF 2 "register_operand" "e")))]
429   "TARGET_FPU"
430   "*
431 {
432   if (TARGET_V9)
433     return \"fcmped %0,%1,%2\";
434   return \"fcmped %1,%2\";
435 }"
436   [(set_attr "type" "fpcmp")])
437
438 (define_insn "*cmptf_fpe"
439   [(set (match_operand:CCFPE 0 "fcc_reg_operand" "=c")
440         (compare:CCFPE (match_operand:TF 1 "register_operand" "e")
441                        (match_operand:TF 2 "register_operand" "e")))]
442   "TARGET_FPU && TARGET_HARD_QUAD"
443   "*
444 {
445   if (TARGET_V9)
446     return \"fcmpeq %0,%1,%2\";
447   return \"fcmpeq %1,%2\";
448 }"
449   [(set_attr "type" "fpcmp")])
450
451 (define_insn "*cmpsf_fp"
452   [(set (match_operand:CCFP 0 "fcc_reg_operand" "=c")
453         (compare:CCFP (match_operand:SF 1 "register_operand" "f")
454                       (match_operand:SF 2 "register_operand" "f")))]
455   "TARGET_FPU"
456   "*
457 {
458   if (TARGET_V9)
459     return \"fcmps %0,%1,%2\";
460   return \"fcmps %1,%2\";
461 }"
462   [(set_attr "type" "fpcmp")])
463
464 (define_insn "*cmpdf_fp"
465   [(set (match_operand:CCFP 0 "fcc_reg_operand" "=c")
466         (compare:CCFP (match_operand:DF 1 "register_operand" "e")
467                       (match_operand:DF 2 "register_operand" "e")))]
468   "TARGET_FPU"
469   "*
470 {
471   if (TARGET_V9)
472     return \"fcmpd %0,%1,%2\";
473   return \"fcmpd %1,%2\";
474 }"
475   [(set_attr "type" "fpcmp")])
476
477 (define_insn "*cmptf_fp"
478   [(set (match_operand:CCFP 0 "fcc_reg_operand" "=c")
479         (compare:CCFP (match_operand:TF 1 "register_operand" "e")
480                       (match_operand:TF 2 "register_operand" "e")))]
481   "TARGET_FPU && TARGET_HARD_QUAD"
482   "*
483 {
484   if (TARGET_V9)
485     return \"fcmpq %0,%1,%2\";
486   return \"fcmpq %1,%2\";
487 }"
488   [(set_attr "type" "fpcmp")])
489 \f
490 ;; Next come the scc insns.  For seq, sne, sgeu, and sltu, we can do this
491 ;; without jumps using the addx/subx instructions.  For seq/sne on v9 we use
492 ;; the same code as v8 (the addx/subx method has more applications).  The
493 ;; exception to this is "reg != 0" which can be done in one instruction on v9
494 ;; (so we do it).  For the rest, on v9 we use conditional moves; on v8, we do
495 ;; branches.
496
497 ;; Seq_special[_xxx] and sne_special[_xxx] clobber the CC reg, because they
498 ;; generate addcc/subcc instructions.
499
500 (define_expand "seqsi_special"
501   [(set (match_dup 3)
502         (xor:SI (match_operand:SI 1 "register_operand" "")
503                 (match_operand:SI 2 "register_operand" "")))
504    (parallel [(set (match_operand:SI 0 "register_operand" "")
505                    (eq:SI (match_dup 3) (const_int 0)))
506               (clobber (reg:CC 100))])]
507   "! TARGET_LIVE_G0"
508   "{ operands[3] = gen_reg_rtx (SImode); }")
509
510 (define_expand "seqdi_special"
511   [(set (match_dup 3)
512         (xor:DI (match_operand:DI 1 "register_operand" "")
513                 (match_operand:DI 2 "register_operand" "")))
514    (set (match_operand:DI 0 "register_operand" "")
515         (eq:DI (match_dup 3) (const_int 0)))]
516   "TARGET_ARCH64"
517   "{ operands[3] = gen_reg_rtx (DImode); }")
518
519 (define_expand "snesi_special"
520   [(set (match_dup 3)
521         (xor:SI (match_operand:SI 1 "register_operand" "")
522                 (match_operand:SI 2 "register_operand" "")))
523    (parallel [(set (match_operand:SI 0 "register_operand" "")
524                    (ne:SI (match_dup 3) (const_int 0)))
525               (clobber (reg:CC 100))])]
526   "! TARGET_LIVE_G0"
527   "{ operands[3] = gen_reg_rtx (SImode); }")
528
529 (define_expand "snedi_special"
530   [(set (match_dup 3)
531         (xor:DI (match_operand:DI 1 "register_operand" "")
532                 (match_operand:DI 2 "register_operand" "")))
533    (set (match_operand:DI 0 "register_operand" "")
534         (ne:DI (match_dup 3) (const_int 0)))]
535   "TARGET_ARCH64"
536   "{ operands[3] = gen_reg_rtx (DImode); }")
537
538 (define_expand "seqdi_special_trunc"
539   [(set (match_dup 3)
540         (xor:DI (match_operand:DI 1 "register_operand" "")
541                 (match_operand:DI 2 "register_operand" "")))
542    (set (match_operand:SI 0 "register_operand" "")
543         (eq:DI (match_dup 3) (const_int 0)))]
544   "TARGET_ARCH64"
545   "{ operands[3] = gen_reg_rtx (DImode); }")
546
547 (define_expand "snedi_special_trunc"
548   [(set (match_dup 3)
549         (xor:DI (match_operand:DI 1 "register_operand" "")
550                 (match_operand:DI 2 "register_operand" "")))
551    (set (match_operand:SI 0 "register_operand" "")
552         (ne:DI (match_dup 3) (const_int 0)))]
553   "TARGET_ARCH64"
554   "{ operands[3] = gen_reg_rtx (DImode); }")
555
556 (define_expand "seqsi_special_extend"
557   [(set (match_dup 3)
558         (xor:SI (match_operand:SI 1 "register_operand" "")
559                 (match_operand:SI 2 "register_operand" "")))
560    (parallel [(set (match_operand:DI 0 "register_operand" "")
561                    (eq:SI (match_dup 3) (const_int 0)))
562               (clobber (reg:CC 100))])]
563   "TARGET_ARCH64"
564   "{ operands[3] = gen_reg_rtx (SImode); }")
565
566 (define_expand "snesi_special_extend"
567   [(set (match_dup 3)
568         (xor:SI (match_operand:SI 1 "register_operand" "")
569                 (match_operand:SI 2 "register_operand" "")))
570    (parallel [(set (match_operand:DI 0 "register_operand" "")
571                    (ne:SI (match_dup 3) (const_int 0)))
572               (clobber (reg:CC 100))])]
573   "TARGET_ARCH64"
574   "{ operands[3] = gen_reg_rtx (SImode); }")
575
576 ;; ??? v9: Operand 0 needs a mode, so SImode was chosen.
577 ;; However, the code handles both SImode and DImode.
578 (define_expand "seq"
579   [(set (match_operand:SI 0 "intreg_operand" "")
580         (eq:SI (match_dup 1) (const_int 0)))]
581   "! TARGET_LIVE_G0"
582   "
583 {
584   if (GET_MODE (sparc_compare_op0) == SImode)
585     {
586       rtx pat;
587
588       if (GET_MODE (operands[0]) == SImode)
589         pat = gen_seqsi_special (operands[0], sparc_compare_op0,
590                                  sparc_compare_op1);
591       else if (! TARGET_ARCH64)
592         FAIL;
593       else
594         pat = gen_seqsi_special_extend (operands[0], sparc_compare_op0,
595                                         sparc_compare_op1);
596       emit_insn (pat);
597       DONE;
598     }
599   else if (GET_MODE (sparc_compare_op0) == DImode)
600     {
601       rtx pat;
602
603       if (! TARGET_ARCH64)
604         FAIL;
605       else if (GET_MODE (operands[0]) == SImode)
606         pat = gen_seqdi_special_trunc (operands[0], sparc_compare_op0,
607                                        sparc_compare_op1);
608       else
609         pat = gen_seqdi_special (operands[0], sparc_compare_op0,
610                                  sparc_compare_op1);
611       emit_insn (pat);
612       DONE;
613     }
614   else if (GET_MODE (sparc_compare_op0) == TFmode && ! TARGET_HARD_QUAD)
615     {
616       emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, EQ);
617       emit_insn (gen_sne (operands[0]));
618       DONE;
619     }      
620   else if (TARGET_V9)
621     {
622       if (gen_v9_scc (EQ, operands))
623         DONE;
624       /* fall through */
625     }
626   operands[1] = gen_compare_reg (EQ, sparc_compare_op0, sparc_compare_op1);
627 }")
628
629 ;; ??? v9: Operand 0 needs a mode, so SImode was chosen.
630 ;; However, the code handles both SImode and DImode.
631 (define_expand "sne"
632   [(set (match_operand:SI 0 "intreg_operand" "")
633         (ne:SI (match_dup 1) (const_int 0)))]
634   "! TARGET_LIVE_G0"
635   "
636 {
637   if (GET_MODE (sparc_compare_op0) == SImode)
638     {
639       rtx pat;
640
641       if (GET_MODE (operands[0]) == SImode)
642         pat = gen_snesi_special (operands[0], sparc_compare_op0,
643                                  sparc_compare_op1);
644       else if (! TARGET_ARCH64)
645         FAIL;
646       else
647         pat = gen_snesi_special_extend (operands[0], sparc_compare_op0,
648                                         sparc_compare_op1);
649       emit_insn (pat);
650       DONE;
651     }
652   else if (GET_MODE (sparc_compare_op0) == DImode)
653     {
654       rtx pat;
655
656       if (! TARGET_ARCH64)
657         FAIL;
658       else if (GET_MODE (operands[0]) == SImode)
659         pat = gen_snedi_special_trunc (operands[0], sparc_compare_op0,
660                                        sparc_compare_op1);
661       else
662         pat = gen_snedi_special (operands[0], sparc_compare_op0,
663                                  sparc_compare_op1);
664       emit_insn (pat);
665       DONE;
666     }
667   else if (GET_MODE (sparc_compare_op0) == TFmode && ! TARGET_HARD_QUAD)
668     {
669       emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, NE);
670       emit_insn (gen_sne (operands[0]));
671       DONE;
672     }      
673   else if (TARGET_V9)
674     {
675       if (gen_v9_scc (NE, operands))
676         DONE;
677       /* fall through */
678     }
679   operands[1] = gen_compare_reg (NE, sparc_compare_op0, sparc_compare_op1);
680 }")
681
682 (define_expand "sgt"
683   [(set (match_operand:SI 0 "intreg_operand" "")
684         (gt:SI (match_dup 1) (const_int 0)))]
685   "! TARGET_LIVE_G0"
686   "
687 {
688   if (GET_MODE (sparc_compare_op0) == TFmode && ! TARGET_HARD_QUAD)
689     {
690       emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, GT);
691       emit_insn (gen_sne (operands[0]));
692       DONE;
693     }
694   else if (TARGET_V9)
695     {
696       if (gen_v9_scc (GT, operands))
697         DONE;
698       /* fall through */
699     }
700   operands[1] = gen_compare_reg (GT, sparc_compare_op0, sparc_compare_op1);
701 }")
702
703 (define_expand "slt"
704   [(set (match_operand:SI 0 "intreg_operand" "")
705         (lt:SI (match_dup 1) (const_int 0)))]
706   "! TARGET_LIVE_G0"
707   "
708 {
709   if (GET_MODE (sparc_compare_op0) == TFmode && ! TARGET_HARD_QUAD)
710     {
711       emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, LT);
712       emit_insn (gen_sne (operands[0]));
713       DONE;
714     }
715   else if (TARGET_V9)
716     {
717       if (gen_v9_scc (LT, operands))
718         DONE;
719       /* fall through */
720     }
721   operands[1] = gen_compare_reg (LT, sparc_compare_op0, sparc_compare_op1);
722 }")
723
724 (define_expand "sge"
725   [(set (match_operand:SI 0 "intreg_operand" "")
726         (ge:SI (match_dup 1) (const_int 0)))]
727   "! TARGET_LIVE_G0"
728   "
729 {
730   if (GET_MODE (sparc_compare_op0) == TFmode && ! TARGET_HARD_QUAD)
731     {
732       emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, GE);
733       emit_insn (gen_sne (operands[0]));
734       DONE;
735     }
736   else if (TARGET_V9)
737     {
738       if (gen_v9_scc (GE, operands))
739         DONE;
740       /* fall through */
741     }
742   operands[1] = gen_compare_reg (GE, sparc_compare_op0, sparc_compare_op1);
743 }")
744
745 (define_expand "sle"
746   [(set (match_operand:SI 0 "intreg_operand" "")
747         (le:SI (match_dup 1) (const_int 0)))]
748   "! TARGET_LIVE_G0"
749   "
750 {
751   if (GET_MODE (sparc_compare_op0) == TFmode && ! TARGET_HARD_QUAD)
752     {
753       emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, LE);
754       emit_insn (gen_sne (operands[0]));
755       DONE;
756     }
757   else if (TARGET_V9)
758     {
759       if (gen_v9_scc (LE, operands))
760         DONE;
761       /* fall through */
762     }
763   operands[1] = gen_compare_reg (LE, sparc_compare_op0, sparc_compare_op1);
764 }")
765
766 (define_expand "sgtu"
767   [(set (match_operand:SI 0 "intreg_operand" "")
768         (gtu:SI (match_dup 1) (const_int 0)))]
769   "! TARGET_LIVE_G0"
770   "
771 {
772   if (! TARGET_V9)
773     {
774       rtx tem;
775
776       /* We can do ltu easily, so if both operands are registers, swap them and
777          do a LTU.  */
778       if ((GET_CODE (sparc_compare_op0) == REG
779            || GET_CODE (sparc_compare_op0) == SUBREG)
780           && (GET_CODE (sparc_compare_op1) == REG
781               || GET_CODE (sparc_compare_op1) == SUBREG))
782         {
783           tem = sparc_compare_op0;
784           sparc_compare_op0 = sparc_compare_op1;
785           sparc_compare_op1 = tem;
786           emit_insn (gen_sltu (operands[0]));
787           DONE;
788         }
789     }
790   else
791     {
792       if (gen_v9_scc (GTU, operands))
793         DONE;
794     }
795   operands[1] = gen_compare_reg (GTU, sparc_compare_op0, sparc_compare_op1);
796 }")
797
798 (define_expand "sltu"
799   [(set (match_operand:SI 0 "intreg_operand" "")
800         (ltu:SI (match_dup 1) (const_int 0)))]
801   "! TARGET_LIVE_G0"
802   "
803 {
804   if (TARGET_V9)
805     {
806       if (gen_v9_scc (LTU, operands))
807         DONE;
808     }
809   operands[1] = gen_compare_reg (LTU, sparc_compare_op0, sparc_compare_op1);
810 }")
811
812 (define_expand "sgeu"
813   [(set (match_operand:SI 0 "intreg_operand" "")
814         (geu:SI (match_dup 1) (const_int 0)))]
815   "! TARGET_LIVE_G0"
816   "
817 {
818   if (TARGET_V9)
819     {
820       if (gen_v9_scc (GEU, operands))
821         DONE;
822     }
823   operands[1] = gen_compare_reg (GEU, sparc_compare_op0, sparc_compare_op1);
824 }")
825
826 (define_expand "sleu"
827   [(set (match_operand:SI 0 "intreg_operand" "")
828         (leu:SI (match_dup 1) (const_int 0)))]
829   "! TARGET_LIVE_G0"
830   "
831 {
832   if (! TARGET_V9)
833     {
834       rtx tem;
835
836       /* We can do geu easily, so if both operands are registers, swap them and
837          do a GEU.  */
838       if ((GET_CODE (sparc_compare_op0) == REG
839            || GET_CODE (sparc_compare_op0) == SUBREG)
840           && (GET_CODE (sparc_compare_op1) == REG
841               || GET_CODE (sparc_compare_op1) == SUBREG))
842         {
843           tem = sparc_compare_op0;
844           sparc_compare_op0 = sparc_compare_op1;
845           sparc_compare_op1 = tem;
846           emit_insn (gen_sgeu (operands[0]));
847           DONE;
848         }
849     }
850   else
851     {
852       if (gen_v9_scc (LEU, operands))
853         DONE;
854     }
855   operands[1] = gen_compare_reg (LEU, sparc_compare_op0, sparc_compare_op1);
856 }")
857
858 ;; Now the DEFINE_INSNs for the scc cases.
859
860 ;; The SEQ and SNE patterns are special because they can be done
861 ;; without any branching and do not involve a COMPARE.
862
863 (define_insn "*snesi_zero"
864   [(set (match_operand:SI 0 "register_operand" "=r")
865         (ne:SI (match_operand:SI 1 "register_operand" "r")
866                (const_int 0)))
867    (clobber (reg:CC 100))]
868   "! TARGET_LIVE_G0"
869   "subcc %%g0,%1,%%g0\;addx %%g0,0,%0"
870   [(set_attr "type" "unary")
871    (set_attr "length" "2")])
872
873 (define_insn "*neg_snesi_zero"
874   [(set (match_operand:SI 0 "register_operand" "=r")
875         (neg:SI (ne:SI (match_operand:SI 1 "register_operand" "r")
876                        (const_int 0))))
877    (clobber (reg:CC 100))]
878   "! TARGET_LIVE_G0"
879   "subcc %%g0,%1,%%g0\;subx %%g0,0,%0"
880   [(set_attr "type" "unary")
881    (set_attr "length" "2")])
882
883 (define_insn "*snesi_zero_extend"
884   [(set (match_operand:DI 0 "register_operand" "=r")
885         (ne:SI (match_operand:SI 1 "register_operand" "r")
886                (const_int 0)))
887    (clobber (reg:CC 100))]
888   "TARGET_ARCH64"
889   "subcc %%g0,%1,%%g0\;addx %%g0,0,%0"
890   [(set_attr "type" "unary")
891    (set_attr "length" "2")])
892
893 (define_insn "*snedi_zero"
894   [(set (match_operand:DI 0 "register_operand" "=&r")
895         (ne:DI (match_operand:DI 1 "register_operand" "r")
896                (const_int 0)))]
897   "TARGET_ARCH64"
898   "mov 0,%0\;movrnz %1,1,%0"
899   [(set_attr "type" "unary")
900    (set_attr "length" "2")])
901
902 (define_insn "*neg_snedi_zero"
903   [(set (match_operand:DI 0 "register_operand" "=&r")
904         (neg:DI (ne:DI (match_operand:DI 1 "register_operand" "r")
905                        (const_int 0))))]
906   "TARGET_ARCH64"
907   "mov 0,%0\;movrnz %1,-1,%0"
908   [(set_attr "type" "unary")
909    (set_attr "length" "2")])
910
911 (define_insn "*snedi_zero_trunc"
912   [(set (match_operand:SI 0 "register_operand" "=&r")
913         (ne:DI (match_operand:DI 1 "register_operand" "r")
914                (const_int 0)))]
915   "TARGET_ARCH64"
916   "mov 0,%0\;movrnz %1,1,%0"
917   [(set_attr "type" "unary")
918    (set_attr "length" "2")])
919
920 (define_insn "*seqsi_zero"
921   [(set (match_operand:SI 0 "register_operand" "=r")
922         (eq:SI (match_operand:SI 1 "register_operand" "r")
923                (const_int 0)))
924    (clobber (reg:CC 100))]
925   "! TARGET_LIVE_G0"
926   "subcc %%g0,%1,%%g0\;subx %%g0,-1,%0"
927   [(set_attr "type" "unary")
928    (set_attr "length" "2")])
929
930 (define_insn "*neg_seqsi_zero"
931   [(set (match_operand:SI 0 "register_operand" "=r")
932         (neg:SI (eq:SI (match_operand:SI 1 "register_operand" "r")
933                        (const_int 0))))
934    (clobber (reg:CC 100))]
935   "! TARGET_LIVE_G0"
936   "subcc %%g0,%1,%%g0\;addx %%g0,-1,%0"
937   [(set_attr "type" "unary")
938    (set_attr "length" "2")])
939
940 (define_insn "*seqsi_zero_extend"
941   [(set (match_operand:DI 0 "register_operand" "=r")
942         (eq:SI (match_operand:SI 1 "register_operand" "r")
943                (const_int 0)))
944    (clobber (reg:CC 100))]
945   "TARGET_ARCH64"
946   "subcc %%g0,%1,%%g0\;subx %%g0,-1,%0"
947   [(set_attr "type" "unary")
948    (set_attr "length" "2")])
949
950 (define_insn "*seqdi_zero"
951   [(set (match_operand:DI 0 "register_operand" "=&r")
952         (eq:DI (match_operand:DI 1 "register_operand" "r")
953                (const_int 0)))]
954   "TARGET_ARCH64"
955   "mov 0,%0\;movrz %1,1,%0"
956   [(set_attr "type" "unary")
957    (set_attr "length" "2")])
958
959 (define_insn "*neg_seqdi_zero"
960   [(set (match_operand:DI 0 "register_operand" "=&r")
961         (neg:DI (eq:DI (match_operand:DI 1 "register_operand" "r")
962                        (const_int 0))))]
963   "TARGET_ARCH64"
964   "mov 0,%0\;movrz %1,-1,%0"
965   [(set_attr "type" "unary")
966    (set_attr "length" "2")]) 
967
968 (define_insn "*seqdi_zero_trunc"
969   [(set (match_operand:SI 0 "register_operand" "=&r")
970         (eq:DI (match_operand:DI 1 "register_operand" "r")
971                (const_int 0)))]
972   "TARGET_ARCH64"
973   "mov 0,%0\;movrz %1,1,%0"
974   [(set_attr "type" "unary")
975    (set_attr "length" "2")])
976
977 ;; We can also do (x + (i == 0)) and related, so put them in.
978 ;; ??? The addx/subx insns use the 32 bit carry flag so there are no DImode
979 ;; versions for v9.
980
981 (define_insn "*x_plus_i_ne_0"
982   [(set (match_operand:SI 0 "register_operand" "=r")
983         (plus:SI (ne:SI (match_operand:SI 1 "register_operand" "r")
984                         (const_int 0))
985                  (match_operand:SI 2 "register_operand" "r")))
986    (clobber (reg:CC 100))]
987   "! TARGET_LIVE_G0"
988   "subcc %%g0,%1,%%g0\;addx %2,0,%0"
989   [(set_attr "length" "2")])
990
991 (define_insn "*x_minus_i_ne_0"
992   [(set (match_operand:SI 0 "register_operand" "=r")
993         (minus:SI (match_operand:SI 2 "register_operand" "r")
994                   (ne:SI (match_operand:SI 1 "register_operand" "r")
995                          (const_int 0))))
996    (clobber (reg:CC 100))]
997   "! TARGET_LIVE_G0"
998   "subcc %%g0,%1,%%g0\;subx %2,0,%0"
999   [(set_attr "length" "2")])
1000
1001 (define_insn "*x_plus_i_eq_0"
1002   [(set (match_operand:SI 0 "register_operand" "=r")
1003         (plus:SI (eq:SI (match_operand:SI 1 "register_operand" "r")
1004                         (const_int 0))
1005                  (match_operand:SI 2 "register_operand" "r")))
1006    (clobber (reg:CC 100))]
1007   "! TARGET_LIVE_G0"
1008   "subcc %%g0,%1,%%g0\;subx %2,-1,%0"
1009   [(set_attr "length" "2")])
1010
1011 (define_insn "*x_minus_i_eq_0"
1012   [(set (match_operand:SI 0 "register_operand" "=r")
1013         (minus:SI (match_operand:SI 2 "register_operand" "r")
1014                   (eq:SI (match_operand:SI 1 "register_operand" "r")
1015                          (const_int 0))))
1016    (clobber (reg:CC 100))]
1017   "! TARGET_LIVE_G0"
1018   "subcc %%g0,%1,%%g0\;addx %2,-1,%0"
1019   [(set_attr "length" "2")])
1020
1021 ;; We can also do GEU and LTU directly, but these operate after a compare.
1022 ;; ??? The addx/subx insns use the 32 bit carry flag so there are no DImode
1023 ;; versions for v9.
1024
1025 (define_insn "*sltu_insn"
1026   [(set (match_operand:SI 0 "register_operand" "=r")
1027         (ltu:SI (reg:CC 100) (const_int 0)))]
1028   "! TARGET_LIVE_G0"
1029   "addx %%g0,0,%0"
1030   [(set_attr "type" "misc")])
1031
1032 (define_insn "*neg_sltu_insn"
1033   [(set (match_operand:SI 0 "register_operand" "=r")
1034         (neg:SI (ltu:SI (reg:CC 100) (const_int 0))))]
1035   "! TARGET_LIVE_G0"
1036   "subx %%g0,0,%0"
1037   [(set_attr "type" "misc")])
1038
1039 ;; ??? Combine should canonicalize these next two to the same pattern.
1040 (define_insn "*neg_sltu_minus_x"
1041   [(set (match_operand:SI 0 "register_operand" "=r")
1042         (minus:SI (neg:SI (ltu:SI (reg:CC 100) (const_int 0)))
1043                   (match_operand:SI 1 "arith_operand" "rI")))]
1044   "! TARGET_LIVE_G0"
1045   "subx %%g0,%1,%0"
1046   [(set_attr "type" "unary")])
1047
1048 (define_insn "*neg_sltu_plus_x"
1049   [(set (match_operand:SI 0 "register_operand" "=r")
1050         (neg:SI (plus:SI (ltu:SI (reg:CC 100) (const_int 0))
1051                          (match_operand:SI 1 "arith_operand" "rI"))))]
1052   "! TARGET_LIVE_G0"
1053   "subx %%g0,%1,%0"
1054   [(set_attr "type" "unary")])
1055
1056 (define_insn "*sgeu_insn"
1057   [(set (match_operand:SI 0 "register_operand" "=r")
1058         (geu:SI (reg:CC 100) (const_int 0)))]
1059   "! TARGET_LIVE_G0"
1060   "subx %%g0,-1,%0"
1061   [(set_attr "type" "misc")])
1062
1063 (define_insn "*neg_sgeu_insn"
1064   [(set (match_operand:SI 0 "register_operand" "=r")
1065         (neg:SI (geu:SI (reg:CC 100) (const_int 0))))]
1066   "! TARGET_LIVE_G0"
1067   "addx %%g0,-1,%0"
1068   [(set_attr "type" "misc")])
1069
1070 ;; We can also do (x + ((unsigned) i >= 0)) and related, so put them in.
1071 ;; ??? The addx/subx insns use the 32 bit carry flag so there are no DImode
1072 ;; versions for v9.
1073
1074 (define_insn "*sltu_plus_x"
1075   [(set (match_operand:SI 0 "register_operand" "=r")
1076         (plus:SI (ltu:SI (reg:CC 100) (const_int 0))
1077                  (match_operand:SI 1 "arith_operand" "rI")))]
1078   "! TARGET_LIVE_G0"
1079   "addx %%g0,%1,%0"
1080   [(set_attr "type" "unary")])
1081
1082 (define_insn "*sltu_plus_x_plus_y"
1083   [(set (match_operand:SI 0 "register_operand" "=r")
1084         (plus:SI (ltu:SI (reg:CC 100) (const_int 0))
1085                  (plus:SI (match_operand:SI 1 "arith_operand" "%r")
1086                           (match_operand:SI 2 "arith_operand" "rI"))))]
1087   ""
1088   "addx %1,%2,%0")
1089
1090 (define_insn "*x_minus_sltu"
1091   [(set (match_operand:SI 0 "register_operand" "=r")
1092         (minus:SI (match_operand:SI 1 "register_operand" "r")
1093                   (ltu:SI (reg:CC 100) (const_int 0))))]
1094   ""
1095   "subx %1,0,%0"
1096   [(set_attr "type" "unary")])
1097
1098 ;; ??? Combine should canonicalize these next two to the same pattern.
1099 (define_insn "*x_minus_y_minus_sltu"
1100   [(set (match_operand:SI 0 "register_operand" "=r")
1101         (minus:SI (minus:SI (match_operand:SI 1 "register_operand" "r")
1102                             (match_operand:SI 2 "arith_operand" "rI"))
1103                   (ltu:SI (reg:CC 100) (const_int 0))))]
1104   ""
1105   "subx %1,%2,%0")
1106
1107 (define_insn "*x_minus_sltu_plus_y"
1108   [(set (match_operand:SI 0 "register_operand" "=r")
1109         (minus:SI (match_operand:SI 1 "register_operand" "r")
1110                   (plus:SI (ltu:SI (reg:CC 100) (const_int 0))
1111                            (match_operand:SI 2 "arith_operand" "rI"))))]
1112   ""
1113   "subx %1,%2,%0")
1114
1115 (define_insn "*sgeu_plus_x"
1116   [(set (match_operand:SI 0 "register_operand" "=r")
1117         (plus:SI (geu:SI (reg:CC 100) (const_int 0))
1118                  (match_operand:SI 1 "register_operand" "r")))]
1119   ""
1120   "subx %1,-1,%0"
1121   [(set_attr "type" "unary")])
1122
1123 (define_insn "*x_minus_sgeu"
1124   [(set (match_operand:SI 0 "register_operand" "=r")
1125         (minus:SI (match_operand:SI 1 "register_operand" "r")
1126                   (geu:SI (reg:CC 100) (const_int 0))))]
1127   ""
1128   "addx %1,-1,%0"
1129   [(set_attr "type" "unary")])
1130
1131 ;; Now we have the generic scc insns.
1132 ;; !v9: These will be done using a jump.
1133 ;; v9: Use conditional moves which are defined elsewhere.
1134 ;; We have to exclude the cases above, since we will not want combine to
1135 ;; turn something that does not require a jump into something that does.
1136
1137 (define_insn "*scc_si"
1138   [(set (match_operand:SI 0 "register_operand" "=r")
1139         (match_operator:SI 2 "noov_compare_op"
1140                            [(match_operand 1 "icc_or_fcc_reg_operand" "")
1141                             (const_int 0)]))]
1142   ""
1143   "* return output_scc_insn (operands, insn); "
1144   [(set_attr "type" "multi")
1145    (set_attr "length" "3")])
1146
1147 (define_insn "*scc_di"
1148   [(set (match_operand:DI 0 "register_operand" "=r")
1149         (match_operator:DI 2 "noov_compare_op"
1150                            [(match_operand 1 "icc_or_fcc_reg_operand" "")
1151                             (const_int 0)]))]
1152   "TARGET_ARCH64"
1153   "* return output_scc_insn (operands, insn); "
1154   [(set_attr "type" "multi")
1155    (set_attr "length" "3")])
1156 \f
1157 ;; These control RTL generation for conditional jump insns
1158
1159 ;; The quad-word fp compare library routines all return nonzero to indicate
1160 ;; true, which is different from the equivalent libgcc routines, so we must
1161 ;; handle them specially here.
1162
1163 (define_expand "beq"
1164   [(set (pc)
1165         (if_then_else (eq (match_dup 1) (const_int 0))
1166                       (label_ref (match_operand 0 "" ""))
1167                       (pc)))]
1168   ""
1169   "
1170 {
1171   if (TARGET_ARCH64 && sparc_compare_op1 == const0_rtx
1172       && GET_CODE (sparc_compare_op0) == REG
1173       && GET_MODE (sparc_compare_op0) == DImode)
1174     {
1175       emit_v9_brxx_insn (EQ, sparc_compare_op0, operands[0]);
1176       DONE;
1177     }
1178   else if (GET_MODE (sparc_compare_op0) == TFmode && ! TARGET_HARD_QUAD)
1179     {
1180       emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, EQ);
1181       emit_jump_insn (gen_bne (operands[0]));
1182       DONE;
1183     }      
1184   operands[1] = gen_compare_reg (EQ, sparc_compare_op0, sparc_compare_op1);
1185 }")
1186
1187 (define_expand "bne"
1188   [(set (pc)
1189         (if_then_else (ne (match_dup 1) (const_int 0))
1190                       (label_ref (match_operand 0 "" ""))
1191                       (pc)))]
1192   ""
1193   "
1194 {
1195   if (TARGET_ARCH64 && sparc_compare_op1 == const0_rtx
1196       && GET_CODE (sparc_compare_op0) == REG
1197       && GET_MODE (sparc_compare_op0) == DImode)
1198     {
1199       emit_v9_brxx_insn (NE, sparc_compare_op0, operands[0]);
1200       DONE;
1201     }
1202   else if (GET_MODE (sparc_compare_op0) == TFmode && ! TARGET_HARD_QUAD)
1203     {
1204       emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, NE);
1205       emit_jump_insn (gen_bne (operands[0]));
1206       DONE;
1207     }      
1208   operands[1] = gen_compare_reg (NE, sparc_compare_op0, sparc_compare_op1);
1209 }")
1210
1211 (define_expand "bgt"
1212   [(set (pc)
1213         (if_then_else (gt (match_dup 1) (const_int 0))
1214                       (label_ref (match_operand 0 "" ""))
1215                       (pc)))]
1216   ""
1217   "
1218 {
1219   if (TARGET_ARCH64 && sparc_compare_op1 == const0_rtx
1220       && GET_CODE (sparc_compare_op0) == REG
1221       && GET_MODE (sparc_compare_op0) == DImode)
1222     {
1223       emit_v9_brxx_insn (GT, sparc_compare_op0, operands[0]);
1224       DONE;
1225     }
1226   else if (GET_MODE (sparc_compare_op0) == TFmode && ! TARGET_HARD_QUAD)
1227     {
1228       emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, GT);
1229       emit_jump_insn (gen_bne (operands[0]));
1230       DONE;
1231     }      
1232   operands[1] = gen_compare_reg (GT, sparc_compare_op0, sparc_compare_op1);
1233 }")
1234
1235 (define_expand "bgtu"
1236   [(set (pc)
1237         (if_then_else (gtu (match_dup 1) (const_int 0))
1238                       (label_ref (match_operand 0 "" ""))
1239                       (pc)))]
1240   ""
1241   "
1242 { operands[1] = gen_compare_reg (GTU, sparc_compare_op0, sparc_compare_op1);
1243 }")
1244
1245 (define_expand "blt"
1246   [(set (pc)
1247         (if_then_else (lt (match_dup 1) (const_int 0))
1248                       (label_ref (match_operand 0 "" ""))
1249                       (pc)))]
1250   ""
1251   "
1252 {
1253   if (TARGET_ARCH64 && sparc_compare_op1 == const0_rtx
1254       && GET_CODE (sparc_compare_op0) == REG
1255       && GET_MODE (sparc_compare_op0) == DImode)
1256     {
1257       emit_v9_brxx_insn (LT, sparc_compare_op0, operands[0]);
1258       DONE;
1259     }
1260   else if (GET_MODE (sparc_compare_op0) == TFmode && ! TARGET_HARD_QUAD)
1261     {
1262       emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, LT);
1263       emit_jump_insn (gen_bne (operands[0]));
1264       DONE;
1265     }      
1266   operands[1] = gen_compare_reg (LT, sparc_compare_op0, sparc_compare_op1);
1267 }")
1268
1269 (define_expand "bltu"
1270   [(set (pc)
1271         (if_then_else (ltu (match_dup 1) (const_int 0))
1272                       (label_ref (match_operand 0 "" ""))
1273                       (pc)))]
1274   ""
1275   "
1276 { operands[1] = gen_compare_reg (LTU, sparc_compare_op0, sparc_compare_op1);
1277 }")
1278
1279 (define_expand "bge"
1280   [(set (pc)
1281         (if_then_else (ge (match_dup 1) (const_int 0))
1282                       (label_ref (match_operand 0 "" ""))
1283                       (pc)))]
1284   ""
1285   "
1286 {
1287   if (TARGET_ARCH64 && sparc_compare_op1 == const0_rtx
1288       && GET_CODE (sparc_compare_op0) == REG
1289       && GET_MODE (sparc_compare_op0) == DImode)
1290     {
1291       emit_v9_brxx_insn (GE, sparc_compare_op0, operands[0]);
1292       DONE;
1293     }
1294   else if (GET_MODE (sparc_compare_op0) == TFmode && ! TARGET_HARD_QUAD)
1295     {
1296       emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, GE);
1297       emit_jump_insn (gen_bne (operands[0]));
1298       DONE;
1299     }      
1300   operands[1] = gen_compare_reg (GE, sparc_compare_op0, sparc_compare_op1);
1301 }")
1302
1303 (define_expand "bgeu"
1304   [(set (pc)
1305         (if_then_else (geu (match_dup 1) (const_int 0))
1306                       (label_ref (match_operand 0 "" ""))
1307                       (pc)))]
1308   ""
1309   "
1310 { operands[1] = gen_compare_reg (GEU, sparc_compare_op0, sparc_compare_op1);
1311 }")
1312
1313 (define_expand "ble"
1314   [(set (pc)
1315         (if_then_else (le (match_dup 1) (const_int 0))
1316                       (label_ref (match_operand 0 "" ""))
1317                       (pc)))]
1318   ""
1319   "
1320 {
1321   if (TARGET_ARCH64 && sparc_compare_op1 == const0_rtx
1322       && GET_CODE (sparc_compare_op0) == REG
1323       && GET_MODE (sparc_compare_op0) == DImode)
1324     {
1325       emit_v9_brxx_insn (LE, sparc_compare_op0, operands[0]);
1326       DONE;
1327     }
1328   else if (GET_MODE (sparc_compare_op0) == TFmode && ! TARGET_HARD_QUAD)
1329     {
1330       emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, LE);
1331       emit_jump_insn (gen_bne (operands[0]));
1332       DONE;
1333     }      
1334   operands[1] = gen_compare_reg (LE, sparc_compare_op0, sparc_compare_op1);
1335 }")
1336
1337 (define_expand "bleu"
1338   [(set (pc)
1339         (if_then_else (leu (match_dup 1) (const_int 0))
1340                       (label_ref (match_operand 0 "" ""))
1341                       (pc)))]
1342   ""
1343   "
1344 { operands[1] = gen_compare_reg (LEU, sparc_compare_op0, sparc_compare_op1);
1345 }")
1346 \f
1347 ;; Now match both normal and inverted jump.
1348
1349 (define_insn "*normal_branch"
1350   [(set (pc)
1351         (if_then_else (match_operator 0 "noov_compare_op"
1352                                       [(reg 100) (const_int 0)])
1353                       (label_ref (match_operand 1 "" ""))
1354                       (pc)))]
1355   ""
1356   "*
1357 {
1358   return output_cbranch (operands[0], 1, 0,
1359                          final_sequence && INSN_ANNULLED_BRANCH_P (insn),
1360                          ! final_sequence);
1361 }"
1362   [(set_attr "type" "branch")])
1363
1364 (define_insn "*inverted_branch"
1365   [(set (pc)
1366         (if_then_else (match_operator 0 "noov_compare_op"
1367                                       [(reg 100) (const_int 0)])
1368                       (pc)
1369                       (label_ref (match_operand 1 "" ""))))]
1370   ""
1371   "*
1372 {
1373   return output_cbranch (operands[0], 1, 1,
1374                          final_sequence && INSN_ANNULLED_BRANCH_P (insn),
1375                          ! final_sequence);
1376 }"
1377   [(set_attr "type" "branch")])
1378
1379 (define_insn "*normal_fp_branch"
1380   [(set (pc)
1381         (if_then_else (match_operator 1 "comparison_operator"
1382                                       [(match_operand:CCFP 0 "fcc_reg_operand" "c")
1383                                        (const_int 0)])
1384                       (label_ref (match_operand 2 "" ""))
1385                       (pc)))]
1386   ""
1387   "*
1388 {
1389   return output_cbranch (operands[1], 2, 0,
1390                          final_sequence && INSN_ANNULLED_BRANCH_P (insn),
1391                          ! final_sequence);
1392 }"
1393   [(set_attr "type" "branch")])
1394
1395 (define_insn "*inverted_fp_branch"
1396   [(set (pc)
1397         (if_then_else (match_operator 1 "comparison_operator"
1398                                       [(match_operand:CCFP 0 "fcc_reg_operand" "c")
1399                                        (const_int 0)])
1400                       (pc)
1401                       (label_ref (match_operand 2 "" ""))))]
1402   ""
1403   "*
1404 {
1405   return output_cbranch (operands[1], 2, 1,
1406                          final_sequence && INSN_ANNULLED_BRANCH_P (insn),
1407                          ! final_sequence);
1408 }"
1409   [(set_attr "type" "branch")])
1410
1411 (define_insn "*normal_fpe_branch"
1412   [(set (pc)
1413         (if_then_else (match_operator 1 "comparison_operator"
1414                                       [(match_operand:CCFPE 0 "fcc_reg_operand" "c")
1415                                        (const_int 0)])
1416                       (label_ref (match_operand 2 "" ""))
1417                       (pc)))]
1418   ""
1419   "*
1420 {
1421   return output_cbranch (operands[1], 2, 0,
1422                          final_sequence && INSN_ANNULLED_BRANCH_P (insn),
1423                          ! final_sequence);
1424 }"
1425   [(set_attr "type" "branch")])
1426
1427 (define_insn "*inverted_fpe_branch"
1428   [(set (pc)
1429         (if_then_else (match_operator 1 "comparison_operator"
1430                                       [(match_operand:CCFPE 0 "fcc_reg_operand" "c")
1431                                        (const_int 0)])
1432                       (pc)
1433                       (label_ref (match_operand 2 "" ""))))]
1434   ""
1435   "*
1436 {
1437   return output_cbranch (operands[1], 2, 1,
1438                          final_sequence && INSN_ANNULLED_BRANCH_P (insn),
1439                          ! final_sequence);
1440 }"
1441   [(set_attr "type" "branch")])
1442
1443 ;; Sparc V9-specific jump insns.  None of these are guaranteed to be
1444 ;; in the architecture.
1445
1446 ;; There are no 32 bit brreg insns.
1447
1448 (define_insn "*normal_int_branch_sp64"
1449   [(set (pc)
1450         (if_then_else (match_operator 0 "v9_regcmp_op"
1451                                       [(match_operand:DI 1 "register_operand" "r")
1452                                        (const_int 0)])
1453                       (label_ref (match_operand 2 "" ""))
1454                       (pc)))]
1455   "TARGET_ARCH64"
1456   "*
1457 {
1458   return output_v9branch (operands[0], 1, 2, 0,
1459                           final_sequence && INSN_ANNULLED_BRANCH_P (insn),
1460                           ! final_sequence);
1461 }"
1462   [(set_attr "type" "branch")])
1463
1464 (define_insn "*inverted_int_branch_sp64"
1465   [(set (pc)
1466         (if_then_else (match_operator 0 "v9_regcmp_op"
1467                                       [(match_operand:DI 1 "register_operand" "r")
1468                                        (const_int 0)])
1469                       (pc)
1470                       (label_ref (match_operand 2 "" ""))))]
1471   "TARGET_ARCH64"
1472   "*
1473 {
1474   return output_v9branch (operands[0], 1, 2, 1,
1475                           final_sequence && INSN_ANNULLED_BRANCH_P (insn),
1476                           ! final_sequence);
1477 }"
1478   [(set_attr "type" "branch")])
1479 \f
1480 ;; Esoteric move insns (lo_sum, high, pic).
1481
1482 (define_insn "*lo_sum_si"
1483   [(set (match_operand:SI 0 "register_operand" "=r")
1484         (lo_sum:SI (match_operand:SI 1 "register_operand" "r")
1485                    (match_operand:SI 2 "immediate_operand" "in")))]
1486   ""
1487   ;; V9 needs "add" because of the code models.  We still use "or" for v8
1488   ;; so we can compare the old compiler with the new.
1489   "* return TARGET_ARCH64 ? \"add %1,%%lo(%a2),%0\" : \"or %1,%%lo(%a2),%0\";"
1490   ;; Need to set length for this arith insn because operand2
1491   ;; is not an "arith_operand".
1492   [(set_attr "length" "1")])
1493
1494 ;; For PIC, symbol_refs are put inside unspec so that the optimizer will not
1495 ;; confuse them with real addresses.
1496 (define_insn "pic_lo_sum_si"
1497   [(set (match_operand:SI 0 "register_operand" "=r")
1498         (lo_sum:SI (match_operand:SI 1 "register_operand" "r")
1499                    (unspec:SI [(match_operand:SI 2 "immediate_operand" "in")] 0)))]
1500   "flag_pic"
1501   ;; V9 needs "add" because of the code models.  We still use "or" for v8
1502   ;; so we can compare the old compiler with the new.
1503   "* return TARGET_ARCH64 ? \"add %1,%%lo(%a2),%0\" : \"or %1,%%lo(%a2),%0\";"
1504   ;; Need to set length for this arith insn because operand2
1505   ;; is not an "arith_operand".
1506   [(set_attr "length" "1")])
1507
1508 ;; The PIC version of sethi must appear before the non-pic case so that
1509 ;; the unspec will not be matched as part of the operand.
1510 ;; For PIC, symbol_refs are put inside unspec so that the optimizer will not
1511 ;; confuse them with real addresses.
1512 (define_insn "pic_sethi_si"
1513   [(set (match_operand:SI 0 "register_operand" "=r")
1514         (high:SI (unspec:SI [(match_operand 1 "" "")] 0)))]
1515   "flag_pic && check_pic (1)"
1516   "sethi %%hi(%a1),%0"
1517   [(set_attr "type" "move")
1518    (set_attr "length" "1")])
1519
1520 (define_insn "pic_lo_sum_di"
1521   [(set (match_operand:DI 0 "register_operand" "=r")
1522         (lo_sum:SI (match_operand:DI 1 "register_operand" "r")
1523                    (unspec:SI [(match_operand:DI 2 "immediate_operand" "in")] 0)))]
1524   "TARGET_ARCH64 && flag_pic"
1525   "add %1,%%lo(%a2),%0"
1526   [(set_attr "length" "1")])
1527
1528 (define_insn "pic_sethi_di"
1529   [(set (match_operand:DI 0 "register_operand" "=r")
1530         (high:SI (unspec:SI [(match_operand 1 "" "")] 0)))]
1531   "TARGET_ARCH64 && flag_pic && check_pic (1)"
1532   "sethi %%hi(%a1),%0"
1533   [(set_attr "type" "move")
1534    (set_attr "length" "1")])
1535
1536 (define_insn "get_pc_via_call"
1537   [(set (pc) (label_ref (match_operand 0 "" "")))
1538    (set (reg:SI 15) (label_ref (match_operand 1 "" "")))]
1539   ""
1540   "call %l0%#"
1541   [(set_attr "type" "uncond_branch")])
1542
1543 (define_insn "get_pc_via_rdpc"
1544   [(set (match_operand:DI 0 "register_operand" "=r") (pc))]
1545   "TARGET_PTR64"
1546   "rd %%pc,%0"
1547   [(set_attr "type" "move")])
1548
1549 ;; Special pic pattern, for loading the address of a label into a register.
1550 ;; It clobbers o7 because the call puts the return address (i.e. pc value)
1551 ;; there.  The pic tablejump pattern also uses this.
1552
1553 (define_insn "move_pic_label_si"
1554   [(set (match_operand:SI 0 "register_operand" "=r")
1555         ; This was previously (label_ref:SI (match_operand 1 "" "")) but that
1556         ; loses the volatil and other flags of the original label_ref.
1557         (match_operand:SI 1 "label_ref_operand" ""))
1558    (set (reg:SI 15) (pc))]
1559   "flag_pic"
1560   "*
1561 {
1562   if (get_attr_length (insn) == 2)
1563     return \"\\n1:\;call 2f\;add %%o7,%%lo(%l1-1b),%0\\n2:\";
1564   else
1565     return \"\\n1:\;call 2f\;sethi %%hi(%l1-1b),%0\\n2:\\tor %0,%%lo(%l1-1b),%0\;add %0,%%o7,%0\";
1566 }"
1567   [(set_attr "type" "multi")
1568    ; 960 = 4096 bytes / 4 bytes/insn - 64 (for not always perfect length calcs)
1569    (set (attr "length") (if_then_else (ltu (minus (match_dup 1) (pc))
1570                                            (const_int 960))
1571                                       (const_int 2)
1572                                       (const_int 4)))])
1573
1574 ;; Special sparc64 pattern for loading the address of a label into a register.
1575 ;; The pic and non-pic cases are the same since it's the most efficient way.
1576 ;;
1577 ;; ??? The non-pic case doesn't need to use %o7, we could use a scratch
1578 ;; instead.  But the pic case doesn't need to use %o7 either.  We handle them
1579 ;; both here so that when this is fixed, they can both be fixed together.
1580 ;; Don't forget that the pic jump table stuff uses %o7 (that will need to be
1581 ;; changed too).
1582
1583 (define_insn "move_label_di"
1584   [(set (match_operand:DI 0 "register_operand" "=r")
1585         ; This was previously (label_ref:DI (match_operand 1 "" "")) but that
1586         ; loses the volatil and other flags of the original label_ref.
1587         (match_operand:DI 1 "label_ref_operand" ""))
1588    (set (reg:DI 15) (pc))]
1589   "TARGET_ARCH64"
1590   "*
1591 {
1592   if (get_attr_length (insn) == 2)
1593     return \"\\n1:\;rd %%pc,%%o7\;add %%o7,%l1-1b,%0\";
1594   else
1595     return \"\\n1:\;rd %%pc,%%o7\;sethi %%hi(%l1-1b),%0\;add %0,%%lo(%l1-1b),%0\;sra %0,0,%0\;add %0,%%o7,%0\";
1596 }"
1597   [(set_attr "type" "multi")
1598    ; 960 = 4096 bytes / 4 bytes/insn - 64 (for not always perfect length calcs)
1599    (set (attr "length") (if_then_else (ltu (minus (match_dup 1) (pc))
1600                                            (const_int 960))
1601                                       (const_int 2)
1602                                       (const_int 5)))])
1603
1604 (define_insn "*sethi_hi"
1605   [(set (match_operand:HI 0 "register_operand" "=r")
1606         (high:HI (match_operand 1 "" "")))]
1607   "check_pic (1)"
1608   "sethi %%hi(%a1),%0"
1609   [(set_attr "type" "move")
1610    (set_attr "length" "1")])
1611
1612 ;; This must appear after the PIC sethi so that the PIC unspec will not
1613 ;; be matched as part of the operand.
1614 (define_insn "*sethi_si"
1615   [(set (match_operand:SI 0 "register_operand" "=r")
1616         (high:SI (match_operand 1 "" "")))]
1617   "check_pic (1)"
1618   "sethi %%hi(%a1),%0"
1619   [(set_attr "type" "move")
1620    (set_attr "length" "1")])
1621
1622 (define_insn "*lo_sum_di_sp32"
1623   [(set (match_operand:DI 0 "register_operand" "=r")
1624         (lo_sum:DI (match_operand:DI 1 "register_operand" "0")
1625                    (match_operand:DI 2 "immediate_operand" "in")))]
1626   "! TARGET_ARCH64"
1627   "*
1628 {
1629   /* Don't output a 64 bit constant, since we can't trust the assembler to
1630      handle it correctly.  */
1631   if (GET_CODE (operands[2]) == CONST_DOUBLE)
1632     operands[2] = GEN_INT (CONST_DOUBLE_LOW (operands[2]));
1633   else if (GET_CODE (operands[2]) == CONST_INT
1634            && HOST_BITS_PER_WIDE_INT > 32
1635            && INTVAL (operands[2]) > 0xffffffff)
1636     operands[2] = GEN_INT (INTVAL (operands[2]) & 0xffffffff);
1637
1638   return \"or %L1,%%lo(%a2),%L0\";
1639 }"
1640   ;; Need to set length for this arith insn because operand2
1641   ;; is not an "arith_operand".
1642   [(set_attr "length" "1")])
1643
1644 ;; ??? Optimizer does not handle "or %o1,%lo(0),%o1". How about add?
1645
1646 (define_insn "*lo_sum_di_sp64"
1647   [(set (match_operand:DI 0 "register_operand" "=r")
1648         (lo_sum:DI (match_operand:DI 1 "register_operand" "0")
1649                    (match_operand:DI 2 "immediate_operand" "in")))]
1650   "TARGET_ARCH64"
1651   "*
1652 {
1653   /* Don't output a 64 bit constant, since we can't trust the assembler to
1654      handle it correctly.  */
1655   if (GET_CODE (operands[2]) == CONST_DOUBLE)
1656     operands[2] = GEN_INT (CONST_DOUBLE_LOW (operands[2]));
1657   else if (GET_CODE (operands[2]) == CONST_INT
1658            && HOST_BITS_PER_WIDE_INT > 32
1659            && INTVAL (operands[2]) > 0xffffffff)
1660     operands[2] = GEN_INT (INTVAL (operands[2]) & 0xffffffff);
1661
1662   /* Note that we use add here.  This is important because Medium/Anywhere
1663      code model support depends on it.  */
1664   return \"add %1,%%lo(%a2),%0\";
1665 }"
1666   ;; Need to set length for this arith insn because operand2
1667   ;; is not an "arith_operand".
1668   [(set_attr "length" "1")])
1669
1670 (define_insn "*sethi_di_sp32"
1671   [(set (match_operand:DI 0 "register_operand" "=r")
1672         (high:DI (match_operand 1 "" "")))]
1673   "! TARGET_ARCH64 && check_pic (1)"
1674   "*
1675 {
1676   rtx op0 = operands[0];
1677   rtx op1 = operands[1];
1678
1679   if (GET_CODE (op1) == CONST_INT)
1680     {
1681       operands[0] = operand_subword (op0, 1, 0, DImode);
1682       output_asm_insn (\"sethi %%hi(%a1),%0\", operands);
1683
1684       operands[0] = operand_subword (op0, 0, 0, DImode);
1685       if (INTVAL (op1) < 0)
1686         return \"mov -1,%0\";
1687       else
1688         return \"mov 0,%0\";
1689     }
1690   else if (GET_CODE (op1) == CONST_DOUBLE)
1691     {
1692       operands[0] = operand_subword (op0, 1, 0, DImode);
1693       operands[1] = GEN_INT (CONST_DOUBLE_LOW (op1));
1694       output_asm_insn (\"sethi %%hi(%a1),%0\", operands);
1695
1696       operands[0] = operand_subword (op0, 0, 0, DImode);
1697       operands[1] = GEN_INT (CONST_DOUBLE_HIGH (op1));
1698       return singlemove_string (operands);
1699     }
1700   else
1701     abort ();
1702   return \"\";
1703 }"
1704   [(set_attr "type" "move")
1705    (set_attr "length" "2")])
1706
1707 ;;; ??? This pattern originally clobbered a scratch register.  However, this
1708 ;;; is invalid, the movdi pattern may not use a temp register because it
1709 ;;; may be called from reload to reload a DImode value.  In that case, we
1710 ;;; end up with a scratch register that never gets allocated.  To avoid this,
1711 ;;; we use global register 1 which is never otherwise used by gcc as a temp.
1712 ;;; The correct solution here might be to force DImode constants to memory,
1713 ;;; e.g. by using a toc like the romp and rs6000 ports do for addresses, reg
1714 ;;; 1 will then no longer need to be considered a fixed reg.
1715
1716 (define_expand "sethi_di_sp64"
1717   [(parallel
1718      [(set (match_operand:DI 0 "register_operand" "")
1719            (high:DI (match_operand 1 "general_operand" "")))
1720       (clobber (reg:DI 1))])]
1721   "TARGET_ARCH64"
1722   "")
1723
1724 (define_insn "*sethi_di_sp64_const"
1725   [(set (match_operand:DI 0 "register_operand" "=r")
1726         (high:DI (match_operand 1 "const_double_operand" "")))
1727    (clobber (reg:DI 1))]
1728   "TARGET_ARCH64 && check_pic (1)"
1729   "*
1730 {
1731 #if HOST_BITS_PER_WIDE_INT == 32
1732   rtx high, low;
1733   
1734   split_double (operands[1], &high, &low);
1735
1736   if (high == const0_rtx)
1737     {
1738       operands[1] = low;
1739       output_asm_insn (\"sethi %%hi(%a1),%0\", operands);
1740     }
1741   else
1742     {
1743       operands[1] = high;
1744       output_asm_insn (singlemove_string (operands), operands);
1745
1746       operands[1] = low;
1747       output_asm_insn (\"sllx %0,32,%0\", operands);
1748       if (low != const0_rtx)
1749         output_asm_insn (\"sethi %%hi(%a1),%%g1; or %0,%%g1,%0\", operands);
1750     }
1751 #else
1752   rtx op = operands[1];
1753
1754   if (! SPARC_SETHI_P (INTVAL(op)))
1755     {
1756       operands[1] = GEN_INT (INTVAL (op) >> 32);
1757       output_asm_insn (singlemove_string (operands), operands);
1758
1759       output_asm_insn (\"sllx %0,32,%0\", operands);
1760       if (INTVAL (op) & 0xffffffff)
1761         {
1762           operands[1] = GEN_INT (INTVAL (op) & 0xffffffff);
1763           output_asm_insn (\"sethi %%hi(%a1),%%g1; or %0,%%g1,%0\", operands);
1764         }
1765     }
1766   else
1767     {
1768       output_asm_insn (\"sethi %%hi(%a1),%0\", operands);
1769     }
1770 #endif
1771
1772   return \"\";
1773 }"
1774   [(set_attr "type" "move")
1775    (set_attr "length" "5")])
1776
1777 ;; Most of the required support for the various code models is here.
1778 ;; We can do this because sparcs need the high insn to load the address.  We
1779 ;; just need to get high to do the right thing for each code model.  Then each
1780 ;; uses the same "%X+%lo(...)" in the load/store insn.
1781
1782 ;; When TARGET_MEDLOW, assume that the upper 32 bits of symbol addresses are
1783 ;; always 0.
1784 ;; When TARGET_MEDANY, the text and data segments have a maximum size of 32
1785 ;; bits and may be located anywhere.  MEDANY_BASE_REG contains the start
1786 ;; address of the data segment, currently %g4.
1787 ;; When TARGET_FULLANY, symbolic addresses are 64 bits.
1788
1789 (define_insn "*sethi_di_medlow"
1790   [(set (match_operand:DI 0 "register_operand" "=r")
1791         (high:DI (match_operand 1 "" "")))
1792   ;; The clobber is here because emit_move_sequence assumes the worst case.
1793    (clobber (reg:DI 1))]
1794   "TARGET_MEDLOW && check_pic (1)"
1795   "sethi %%hi(%a1),%0"
1796   [(set_attr "type" "move")
1797    (set_attr "length" "1")])
1798
1799 (define_insn "*sethi_di_medium_pic"
1800   [(set (match_operand:DI 0 "register_operand" "=r")
1801         (high:DI (match_operand 1 "sp64_medium_pic_operand" "")))]
1802   "(TARGET_MEDLOW || TARGET_MEDANY) && check_pic (1)"
1803   "sethi %%hi(%a1),%0"
1804   [(set_attr "type" "move")
1805    (set_attr "length" "1")])
1806
1807 ;; WARNING: %0 gets %hi(%1)+%g4.
1808 ;;          You cannot OR in %lo(%1), it must be added in.
1809
1810 (define_insn "*sethi_di_medany_data"
1811   [(set (match_operand:DI 0 "register_operand" "=r")
1812         (high:DI (match_operand 1 "data_segment_operand" "")))
1813   ;; The clobber is here because emit_move_sequence assumes the worst case.
1814    (clobber (reg:DI 1))]
1815   "TARGET_MEDANY && check_pic (1)"
1816   "sethi %%hi(%a1),%0; add %0,%%g4,%0"
1817   [(set_attr "type" "move")
1818    (set_attr "length" "2")])
1819
1820 (define_insn "*sethi_di_medany_text"
1821   [(set (match_operand:DI 0 "register_operand" "=r")
1822         (high:DI (match_operand 1 "text_segment_operand" "")))
1823   ;; The clobber is here because emit_move_sequence assumes the worst case.
1824    (clobber (reg:DI 1))]
1825   "TARGET_MEDANY && check_pic (1)"
1826   "sethi %%uhi(%a1),%%g1; or %%g1,%%ulo(%a1),%%g1; sllx %%g1,32,%%g1; sethi %%hi(%a1),%0; or %0,%%g1,%0"
1827   [(set_attr "type" "move")
1828    (set_attr "length" "5")])
1829
1830 (define_insn "*sethi_di_fullany"
1831   [(set (match_operand:DI 0 "register_operand" "=r")
1832         (high:DI (match_operand 1 "" "")))
1833    (clobber (reg:DI 1))]
1834   "TARGET_FULLANY && check_pic (1)"
1835   "sethi %%uhi(%a1),%%g1; or %%g1,%%ulo(%a1),%%g1; sllx %%g1,32,%%g1; sethi %%hi(%a1),%0; or %0,%%g1,%0"
1836   [(set_attr "type" "move")
1837    (set_attr "length" "5")])
1838 \f
1839 ;; Move instructions
1840
1841 (define_expand "movqi"
1842   [(set (match_operand:QI 0 "general_operand" "")
1843         (match_operand:QI 1 "general_operand" ""))]
1844   ""
1845   "
1846 {
1847   if (emit_move_sequence (operands, QImode))
1848     DONE;
1849 }")
1850
1851 (define_insn "*movqi_insn"
1852   [(set (match_operand:QI 0 "reg_or_nonsymb_mem_operand" "=r,r,r,Q")
1853         (match_operand:QI 1 "move_operand" "rI,K,Q,rJ"))]
1854   "! TARGET_LIVE_G0
1855    && (register_operand (operands[0], QImode)
1856        || register_operand (operands[1], QImode)
1857        || operands[1] == const0_rtx)"
1858   "@
1859    mov %1,%0
1860    sethi %%hi(%a1),%0
1861    ldub %1,%0
1862    stb %r1,%0"
1863   [(set_attr "type" "move,move,load,store")
1864    (set_attr "length" "1")])
1865
1866 (define_insn "*movqi_insn_liveg0"
1867   [(set (match_operand:QI 0 "reg_or_nonsymb_mem_operand" "=r,r,r,r,r,Q")
1868         (match_operand:QI 1 "move_operand" "r,J,I,K,Q,r"))]
1869   "TARGET_LIVE_G0
1870    && (register_operand (operands[0], QImode)
1871        || register_operand (operands[1], QImode))"
1872   "@
1873    mov %1,%0
1874    and %0,0,%0
1875    and %0,0,%0\;or %0,%1,%0
1876    sethi %%hi(%a1),%0
1877    ldub %1,%0
1878    stb %1,%0"
1879   [(set_attr "type" "move,move,move,move,load,store")
1880    (set_attr "length" "1,1,2,1,1,1")])
1881
1882 (define_insn "*lo_sum_qi"
1883   [(set (match_operand:QI 0 "register_operand" "=r")
1884         (subreg:QI (lo_sum:SI (match_operand:QI 1 "register_operand" "r")
1885                               (match_operand 2 "immediate_operand" "in")) 0))]
1886   ""
1887   "or %1,%%lo(%a2),%0"
1888   [(set_attr "length" "1")])
1889
1890 (define_insn "*store_qi"
1891   [(set (mem:QI (match_operand:SI 0 "symbolic_operand" ""))
1892         (match_operand:QI 1 "reg_or_0_operand" "rJ"))
1893    (clobber (match_scratch:SI 2 "=&r"))]
1894   "(reload_completed || reload_in_progress)
1895    && ! TARGET_PTR64"
1896   "sethi %%hi(%a0),%2\;stb %r1,[%2+%%lo(%a0)]"
1897   [(set_attr "type" "store")
1898    (set_attr "length" "2")])
1899
1900 (define_expand "movhi"
1901   [(set (match_operand:HI 0 "general_operand" "")
1902         (match_operand:HI 1 "general_operand" ""))]
1903   ""
1904   "
1905 {
1906   if (emit_move_sequence (operands, HImode))
1907     DONE;
1908 }")
1909
1910 (define_insn "*movhi_insn"
1911   [(set (match_operand:HI 0 "reg_or_nonsymb_mem_operand" "=r,r,r,Q")
1912         (match_operand:HI 1 "move_operand" "rI,K,Q,rJ"))]
1913   "! TARGET_LIVE_G0
1914    && (register_operand (operands[0], HImode)
1915        || register_operand (operands[1], HImode)
1916        || operands[1] == const0_rtx)"
1917   "@
1918    mov %1,%0
1919    sethi %%hi(%a1),%0
1920    lduh %1,%0
1921    sth %r1,%0"
1922   [(set_attr "type" "move,move,load,store")
1923    (set_attr "length" "1")])
1924
1925 (define_insn "*movhi_insn_liveg0"
1926   [(set (match_operand:HI 0 "reg_or_nonsymb_mem_operand" "=r,r,r,r,r,Q")
1927         (match_operand:HI 1 "move_operand" "r,J,I,K,Q,r"))]
1928   "TARGET_LIVE_G0
1929    && (register_operand (operands[0], HImode)
1930        || register_operand (operands[1], HImode))"
1931   "@
1932    mov %1,%0
1933    and %0,0,%0
1934    and %0,0,%0\;or %0,%1,%0
1935    sethi %%hi(%a1),%0
1936    lduh %1,%0
1937    sth %1,%0"
1938   [(set_attr "type" "move,move,move,move,load,store")
1939    (set_attr "length" "1,1,2,1,1,1")])
1940
1941 (define_insn "*lo_sum_hi"
1942   [(set (match_operand:HI 0 "register_operand" "=r")
1943         (lo_sum:HI (match_operand:HI 1 "register_operand" "r")
1944                    (match_operand 2 "immediate_operand" "in")))]
1945   ""
1946   "or %1,%%lo(%a2),%0"
1947   [(set_attr "length" "1")])
1948
1949 (define_insn "*store_hi"
1950   [(set (mem:HI (match_operand:SI 0 "symbolic_operand" ""))
1951         (match_operand:HI 1 "reg_or_0_operand" "rJ"))
1952    (clobber (match_scratch:SI 2 "=&r"))]
1953   "(reload_completed || reload_in_progress)
1954    && ! TARGET_PTR64"
1955   "sethi %%hi(%a0),%2\;sth %r1,[%2+%%lo(%a0)]"
1956   [(set_attr "type" "store")
1957    (set_attr "length" "2")])
1958
1959 (define_expand "movsi"
1960   [(set (match_operand:SI 0 "general_operand" "")
1961         (match_operand:SI 1 "general_operand" ""))]
1962   ""
1963   "
1964 {
1965   if (emit_move_sequence (operands, SImode))
1966     DONE;
1967 }")
1968
1969 ;; We must support both 'r' and 'f' registers here, because combine may
1970 ;; convert SFmode hard registers to SImode hard registers when simplifying
1971 ;; subreg sets.
1972
1973 ;; We cannot combine the similar 'r' and 'f' constraints, because it causes
1974 ;; problems with register allocation.  Reload might try to put an integer
1975 ;; in an fp register, or an fp number is an integer register.
1976
1977 (define_insn "*movsi_insn"
1978   [(set (match_operand:SI 0 "reg_or_nonsymb_mem_operand" "=r,f,r,r,f,Q,Q")
1979         (match_operand:SI 1 "move_operand" "rI,!f,K,Q,!Q,rJ,!f"))]
1980   "! TARGET_LIVE_G0
1981    && (register_operand (operands[0], SImode)
1982        || register_operand (operands[1], SImode)
1983        || operands[1] == const0_rtx)"
1984   "@
1985    mov %1,%0
1986    fmovs %1,%0
1987    sethi %%hi(%a1),%0
1988    ld %1,%0
1989    ld %1,%0
1990    st %r1,%0
1991    st %1,%0"
1992   [(set_attr "type" "move,fp,move,load,fpload,store,fpstore")
1993    (set_attr "length" "1")])
1994
1995 (define_insn "*movsi_insn_liveg0"
1996   [(set (match_operand:SI 0 "reg_or_nonsymb_mem_operand" "=r,r,r,f,r,r,f,Q,Q")
1997         (match_operand:SI 1 "move_operand" "r,J,I,!f,K,Q,!Q,r,!f"))]
1998   "TARGET_LIVE_G0
1999    && (register_operand (operands[0], SImode)
2000        || register_operand (operands[1], SImode))"
2001   "@
2002    mov %1,%0
2003    and %0,0,%0
2004    and %0,0,%0\;or %0,%1,%0
2005    fmovs %1,%0
2006    sethi %%hi(%a1),%0
2007    ld %1,%0
2008    ld %1,%0
2009    st %1,%0
2010    st %1,%0"
2011   [(set_attr "type" "move,move,move,fp,move,load,fpload,store,fpstore")
2012    (set_attr "length" "1,1,2,1,1,1,1,1,1")])
2013
2014 (define_insn "*store_si"
2015   [(set (mem:SI (match_operand:SI 0 "symbolic_operand" ""))
2016         (match_operand:SI 1 "reg_or_0_operand" "rJ"))
2017    (clobber (match_scratch:SI 2 "=&r"))]
2018   "(reload_completed || reload_in_progress)
2019    && ! TARGET_PTR64"
2020   "sethi %%hi(%a0),%2\;st %r1,[%2+%%lo(%a0)]"
2021   [(set_attr "type" "store")
2022    (set_attr "length" "2")])
2023
2024 (define_expand "movdi"
2025   [(set (match_operand:DI 0 "reg_or_nonsymb_mem_operand" "")
2026         (match_operand:DI 1 "general_operand" ""))]
2027   ""
2028   "
2029 {
2030   if (emit_move_sequence (operands, DImode))
2031     DONE;
2032 }")
2033
2034 (define_insn "*movdi_sp32_insn"
2035   [(set (match_operand:DI 0 "reg_or_nonsymb_mem_operand" "=r,T,U,Q,r,r,?f,?f,?Q")
2036         (match_operand:DI 1 "general_operand" "r,U,T,r,Q,i,f,Q,f"))]
2037   "! TARGET_ARCH64
2038    && (register_operand (operands[0], DImode)
2039        || register_operand (operands[1], DImode)
2040        || operands[1] == const0_rtx)"
2041   "*
2042 {
2043   if (FP_REG_P (operands[0]) || FP_REG_P (operands[1]))
2044     return output_fp_move_double (operands);
2045   return output_move_double (operands);
2046 }"
2047   [(set_attr "type" "move,store,load,store,load,multi,fp,fpload,fpstore")
2048    (set_attr "length" "2,1,1,3,3,3,2,3,3")])
2049
2050 ;;; ??? The trick used below can be extended to load any negative 32 bit
2051 ;;; constant in two instructions.  Currently the compiler will use HIGH/LO_SUM
2052 ;;; for anything not matching the HIK constraints, which results in 5
2053 ;;; instructions.  Positive 32 bit constants can be loaded in the obvious way
2054 ;;; with sethi/ori.  To extend the trick, in the xor instruction, use 
2055 ;;; xor %o0, ((op1 & 0x3ff) | -0x400), %o0
2056 ;;; This needs the original value of operands[1], not the inverted value.
2057
2058 (define_insn "*movdi_sp64_insn"
2059   [(set (match_operand:DI 0 "reg_or_nonsymb_mem_operand" "=r,r,r,Q,?f,?f,?Q")
2060         (match_operand:DI 1 "move_operand" "rI,K,Q,rJ,f,Q,f"))]
2061   "TARGET_ARCH64
2062    && (register_operand (operands[0], DImode)
2063        || register_operand (operands[1], DImode)
2064        || operands[1] == const0_rtx)"
2065   "*
2066 {
2067   switch (which_alternative)
2068     {
2069     case 0:
2070       return \"mov %1,%0\";
2071     case 1:
2072       /* Sethi does not sign extend, so we must use a little trickery
2073          to use it for negative numbers.  Invert the constant before
2074          loading it in, then use a xor immediate to invert the loaded bits
2075          (along with the upper 32 bits) to the desired constant.  This
2076          works because the sethi and immediate fields overlap.  */
2077
2078       if ((INTVAL (operands[1]) & 0x80000000) == 0)
2079         return \"sethi %%hi(%a1),%0\";
2080       else
2081         {
2082           operands[1] = GEN_INT (~INTVAL (operands[1]));
2083           output_asm_insn (\"sethi %%hi(%a1),%0\", operands);
2084           /* The low 10 bits are already zero, but invert the rest.
2085              Assemblers don't accept 0x1c00, so use -0x400 instead.  */
2086           return \"xor %0,-0x400,%0\";
2087         }
2088     case 2:
2089       return \"ldx %1,%0\";
2090     case 3:
2091       return \"stx %r1,%0\";
2092     case 4:
2093       return \"mov %1,%0\";
2094     case 5:
2095       return \"ldd %1,%0\";
2096     case 6:
2097       return \"std %1,%0\";
2098     }
2099 }"
2100   [(set_attr "type" "move,move,load,store,fp,fpload,fpstore")
2101    (set_attr "length" "1,2,1,1,1,1,1")])
2102
2103 ;; ??? There's no symbolic (set (mem:DI ...) ...).
2104 ;; Experimentation with v9 suggested one isn't needed.
2105 \f
2106 ;; Block move insns.
2107
2108 ;; ??? We get better code without it.  See output_block_move in sparc.c.
2109
2110 ;; The definition of this insn does not really explain what it does,
2111 ;; but it should suffice
2112 ;; that anything generated as this insn will be recognized as one
2113 ;; and that it will not successfully combine with anything.
2114 ;(define_expand "movstrsi"
2115 ;  [(parallel [(set (mem:BLK (match_operand:BLK 0 "general_operand" ""))
2116 ;                  (mem:BLK (match_operand:BLK 1 "general_operand" "")))
2117 ;             (use (match_operand:SI 2 "nonmemory_operand" ""))
2118 ;             (use (match_operand:SI 3 "immediate_operand" ""))
2119 ;             (clobber (match_dup 0))
2120 ;             (clobber (match_dup 1))
2121 ;             (clobber (match_scratch:SI 4 ""))
2122 ;             (clobber (reg:SI 100))
2123 ;             (clobber (reg:SI 1))])]
2124 ;  ""
2125 ;  "
2126 ;{
2127 ;  /* If the size isn't known, don't emit inline code.  output_block_move
2128 ;     would output code that's much slower than the library function.
2129 ;     Also don't output code for large blocks.  */
2130 ;  if (GET_CODE (operands[2]) != CONST_INT
2131 ;      || GET_CODE (operands[3]) != CONST_INT
2132 ;      || INTVAL (operands[2]) / INTVAL (operands[3]) > 16)
2133 ;    FAIL;
2134 ;
2135 ;  operands[0] = copy_to_mode_reg (Pmode, XEXP (operands[0], 0));
2136 ;  operands[1] = copy_to_mode_reg (Pmode, XEXP (operands[1], 0));
2137 ;  operands[2] = force_not_mem (operands[2]);
2138 ;}")
2139
2140 ;(define_insn "*block_move_insn"
2141 ;  [(set (mem:BLK (match_operand:SI 0 "register_operand" "+r"))
2142 ;       (mem:BLK (match_operand:SI 1 "register_operand" "+r")))
2143 ;   (use (match_operand:SI 2 "nonmemory_operand" "rn"))
2144 ;   (use (match_operand:SI 3 "immediate_operand" "i"))
2145 ;   (clobber (match_dup 0))
2146 ;   (clobber (match_dup 1))
2147 ;   (clobber (match_scratch:SI 4 "=&r"))
2148 ;   (clobber (reg:SI 100))
2149 ;   (clobber (reg:SI 1))]
2150 ;  ""
2151 ;  "* return output_block_move (operands);"
2152 ;  [(set_attr "type" "multi")
2153 ;   (set_attr "length" "6")])
2154 \f
2155 ;; Floating point move insns
2156
2157 ;; This pattern forces (set (reg:SF ...) (const_double ...))
2158 ;; to be reloaded by putting the constant into memory.
2159 ;; It must come before the more general movsf pattern.
2160 (define_insn "*movsf_const_insn"
2161   [(set (match_operand:SF 0 "general_operand" "=?r,f,m")
2162         (match_operand:SF 1 "" "?F,m,G"))]
2163   "TARGET_FPU && GET_CODE (operands[1]) == CONST_DOUBLE"
2164   "*
2165 {
2166   switch (which_alternative)
2167     {
2168     case 0:
2169       return singlemove_string (operands);
2170     case 1:
2171       return \"ld %1,%0\";
2172     case 2:
2173       return \"st %%g0,%0\";
2174     }
2175 }"
2176   [(set_attr "type" "load,fpload,store")
2177    (set_attr "length" "2,1,1")])
2178
2179 (define_expand "movsf"
2180   [(set (match_operand:SF 0 "general_operand" "")
2181         (match_operand:SF 1 "general_operand" ""))]
2182   ""
2183   "
2184 {
2185   if (emit_move_sequence (operands, SFmode))
2186     DONE;
2187 }")
2188
2189 (define_insn "*movsf_insn"
2190   [(set (match_operand:SF 0 "reg_or_nonsymb_mem_operand" "=f,r,f,r,Q,Q")
2191         (match_operand:SF 1 "reg_or_nonsymb_mem_operand" "f,r,Q,Q,f,r"))]
2192   "TARGET_FPU
2193    && (register_operand (operands[0], SFmode)
2194        || register_operand (operands[1], SFmode))"
2195   "@
2196    fmovs %1,%0
2197    mov %1,%0
2198    ld %1,%0
2199    ld %1,%0
2200    st %1,%0
2201    st %1,%0"
2202   [(set_attr "type" "fp,move,fpload,load,fpstore,store")])
2203
2204 ;; Exactly the same as above, except that all `f' cases are deleted.
2205 ;; This is necessary to prevent reload from ever trying to use a `f' reg
2206 ;; when -mno-fpu.
2207
2208 (define_insn "*movsf_no_f_insn"
2209   [(set (match_operand:SF 0 "reg_or_nonsymb_mem_operand" "=r,r,Q")
2210         (match_operand:SF 1 "reg_or_nonsymb_mem_operand" "r,Q,r"))]
2211   "! TARGET_FPU
2212    && (register_operand (operands[0], SFmode)
2213        || register_operand (operands[1], SFmode))"
2214   "@
2215    mov %1,%0
2216    ld %1,%0
2217    st %1,%0"
2218   [(set_attr "type" "move,load,store")])
2219
2220 (define_insn "*store_sf"
2221   [(set (mem:SF (match_operand:SI 0 "symbolic_operand" "i"))
2222         (match_operand:SF 1 "reg_or_0_operand" "rfG"))
2223    (clobber (match_scratch:SI 2 "=&r"))]
2224   "(reload_completed || reload_in_progress)
2225    && ! TARGET_PTR64"
2226   "sethi %%hi(%a0),%2\;st %r1,[%2+%%lo(%a0)]"
2227   [(set_attr "type" "store")
2228    (set_attr "length" "2")])
2229
2230 ;; This pattern forces (set (reg:DF ...) (const_double ...))
2231 ;; to be reloaded by putting the constant into memory.
2232 ;; It must come before the more general movdf pattern.
2233
2234 (define_insn "*movdf_const_insn"
2235   [(set (match_operand:DF 0 "general_operand" "=?r,e,o")
2236         (match_operand:DF 1 "" "?F,m,G"))]
2237   "TARGET_FPU && GET_CODE (operands[1]) == CONST_DOUBLE"
2238   "*
2239 {
2240   switch (which_alternative)
2241     {
2242     case 0:
2243       return output_move_double (operands);
2244     case 1:
2245       return output_fp_move_double (operands);
2246     case 2:
2247       if (TARGET_ARCH64)
2248         {
2249           return \"stx %%g0,%0\";
2250         }
2251       else
2252         {
2253           operands[1] = adj_offsettable_operand (operands[0], 4);
2254           return \"st %%g0,%0\;st %%g0,%1\";
2255         }
2256     }
2257 }"
2258   [(set_attr "type" "load,fpload,store")
2259    (set_attr "length" "3,3,3")])
2260
2261 (define_expand "movdf"
2262   [(set (match_operand:DF 0 "general_operand" "")
2263         (match_operand:DF 1 "general_operand" ""))]
2264   ""
2265   "
2266 {
2267   if (emit_move_sequence (operands, DFmode))
2268     DONE;
2269 }")
2270
2271 (define_insn "*movdf_insn"
2272   [(set (match_operand:DF 0 "reg_or_nonsymb_mem_operand" "=T,U,e,r,Q,Q,e,r")
2273         (match_operand:DF 1 "reg_or_nonsymb_mem_operand" "U,T,e,r,e,r,Q,Q"))]
2274   "TARGET_FPU
2275    && (register_operand (operands[0], DFmode)
2276        || register_operand (operands[1], DFmode))"
2277   "*
2278 {
2279   if (FP_REG_P (operands[0]) || FP_REG_P (operands[1]))
2280     return output_fp_move_double (operands);
2281   return output_move_double (operands);
2282 }"
2283   [(set_attr "type" "fpstore,fpload,fp,move,fpstore,store,fpload,load")
2284    (set_attr "length" "1,1,2,2,3,3,3,3")])
2285
2286 ;; Exactly the same as above, except that all `e' cases are deleted.
2287 ;; This is necessary to prevent reload from ever trying to use a `e' reg
2288 ;; when -mno-fpu.
2289
2290 (define_insn "*movdf_no_e_insn"
2291   [(set (match_operand:DF 0 "reg_or_nonsymb_mem_operand" "=T,U,r,Q,&r")
2292         (match_operand:DF 1 "reg_or_nonsymb_mem_operand" "U,T,r,r,Q"))]
2293   "! TARGET_FPU
2294    && (register_operand (operands[0], DFmode)
2295        || register_operand (operands[1], DFmode))"
2296   "* return output_move_double (operands);"
2297   [(set_attr "type" "store,load,move,store,load")
2298    (set_attr "length" "1,1,2,3,3")])
2299
2300 ;; Must handle overlapping registers here, since parameters can be unaligned
2301 ;; in registers.
2302
2303 (define_split
2304   [(set (match_operand:DF 0 "register_operand" "")
2305         (match_operand:DF 1 "register_operand" ""))]
2306   "! TARGET_ARCH64 && reload_completed
2307    && REGNO (operands[0]) < SPARC_FIRST_V9_FP_REG
2308    && REGNO (operands[1]) < SPARC_FIRST_V9_FP_REG"
2309   [(set (match_dup 2) (match_dup 3))
2310    (set (match_dup 4) (match_dup 5))]
2311   "
2312 {
2313   rtx first_set = operand_subword (operands[0], 0, 0, DFmode);
2314   rtx second_use = operand_subword (operands[1], 1, 0, DFmode);
2315
2316   if (REGNO (first_set) == REGNO (second_use))
2317     {
2318       operands[2] = operand_subword (operands[0], 1, 0, DFmode);
2319       operands[3] = second_use;
2320       operands[4] = first_set;
2321       operands[5] = operand_subword (operands[1], 0, 0, DFmode);
2322     }
2323   else
2324     {
2325       operands[2] = first_set;
2326       operands[3] = operand_subword (operands[1], 0, 0, DFmode);
2327       operands[4] = operand_subword (operands[0], 1, 0, DFmode);
2328       operands[5] = second_use;
2329     }
2330 }")
2331
2332 (define_insn "*store_df"
2333   [(set (mem:DF (match_operand:SI 0 "symbolic_operand" "i,i"))
2334         (match_operand:DF 1 "reg_or_0_operand" "re,G"))
2335    (clobber (match_scratch:SI 2 "=&r,&r"))]
2336   "(reload_completed || reload_in_progress)
2337    && ! TARGET_PTR64"
2338   "*
2339 {
2340   output_asm_insn (\"sethi %%hi(%a0),%2\", operands);
2341   if (which_alternative == 0)
2342     return \"std %1,[%2+%%lo(%a0)]\";
2343   else
2344     return \"st %%g0,[%2+%%lo(%a0)]\;st %%g0,[%2+%%lo(%a0+4)]\";
2345 }"
2346   [(set_attr "type" "store")
2347    (set_attr "length" "3")])
2348
2349 ;; This pattern forces (set (reg:TF ...) (const_double ...))
2350 ;; to be reloaded by putting the constant into memory.
2351 ;; It must come before the more general movtf pattern.
2352 (define_insn "*movtf_const_insn"
2353   [(set (match_operand:TF 0 "general_operand" "=?r,e,o")
2354         (match_operand:TF 1 "" "?F,m,G"))]
2355   "TARGET_FPU && GET_CODE (operands[1]) == CONST_DOUBLE"
2356   "*
2357 {
2358   switch (which_alternative)
2359     {
2360     case 0:
2361       return output_move_quad (operands);
2362     case 1:
2363       return output_fp_move_quad (operands);
2364     case 2:
2365       if (TARGET_ARCH64)
2366         {
2367           operands[1] = adj_offsettable_operand (operands[0], 8);
2368           return \"stx %%g0,%0\;stx %%g0,%1\";
2369         }
2370       else
2371         {
2372           /* ??? Do we run off the end of the array here? */
2373           operands[1] = adj_offsettable_operand (operands[0], 4);
2374           operands[2] = adj_offsettable_operand (operands[0], 8);
2375           operands[3] = adj_offsettable_operand (operands[0], 12);
2376           return \"st %%g0,%0\;st %%g0,%1\;st %%g0,%2\;st %%g0,%3\";
2377         }
2378     }
2379 }"
2380   [(set_attr "type" "load,fpload,store")
2381    (set_attr "length" "5,5,5")])
2382
2383 (define_expand "movtf"
2384   [(set (match_operand:TF 0 "general_operand" "")
2385         (match_operand:TF 1 "general_operand" ""))]
2386   ""
2387   "
2388 {
2389   if (emit_move_sequence (operands, TFmode))
2390     DONE;
2391 }")
2392
2393 (define_insn "*movtf_insn"
2394   [(set (match_operand:TF 0 "reg_or_nonsymb_mem_operand" "=e,r,Q,Q,e,&r")
2395         (match_operand:TF 1 "reg_or_nonsymb_mem_operand" "e,r,e,r,Q,Q"))]
2396   "TARGET_FPU
2397    && (register_operand (operands[0], TFmode)
2398        || register_operand (operands[1], TFmode))"
2399   "*
2400 {
2401   if (FP_REG_P (operands[0]) || FP_REG_P (operands[1]))
2402     return output_fp_move_quad (operands);
2403   return output_move_quad (operands);
2404 }"
2405   [(set_attr "type" "fp,move,fpstore,store,fpload,load")
2406    (set_attr "length" "4,4,5,5,5,5")])
2407
2408 ;; Exactly the same as above, except that all `e' cases are deleted.
2409 ;; This is necessary to prevent reload from ever trying to use a `e' reg
2410 ;; when -mno-fpu.
2411
2412 (define_insn "*movtf_no_e_insn"
2413   [(set (match_operand:TF 0 "reg_or_nonsymb_mem_operand" "=r,Q,&r")
2414         (match_operand:TF 1 "reg_or_nonsymb_mem_operand" "r,r,Q"))]
2415   "! TARGET_FPU
2416    && (register_operand (operands[0], TFmode)
2417        || register_operand (operands[1], TFmode))"
2418   "*
2419 {
2420   if (FP_REG_P (operands[0]) || FP_REG_P (operands[1]))
2421     return output_fp_move_quad (operands);
2422   return output_move_quad (operands);
2423 }"
2424   [(set_attr "type" "move,store,load")
2425    (set_attr "length" "4,5,5")])
2426
2427 ;; This is disabled because it does not work.  Long doubles have only 8
2428 ;; byte alignment.  Adding an offset of 8 or 12 to an 8 byte aligned %lo may 
2429 ;; cause it to overflow.  See also GO_IF_LEGITIMATE_ADDRESS.
2430 (define_insn "*store_tf"
2431   [(set (mem:TF (match_operand:SI 0 "symbolic_operand" "i,i"))
2432         (match_operand:TF 1 "reg_or_0_operand" "re,G"))
2433    (clobber (match_scratch:SI 2 "=&r,&r"))]
2434   "0 && (reload_completed || reload_in_progress)
2435    && ! TARGET_PTR64"
2436   "*
2437 {
2438   output_asm_insn (\"sethi %%hi(%a0),%2\", operands);
2439   if (which_alternative == 0)
2440     return \"std %1,[%2+%%lo(%a0)]\;std %S1,[%2+%%lo(%a0+8)]\";
2441   else
2442     return \"st %%g0,[%2+%%lo(%a0)]\;st %%g0,[%2+%%lo(%a0+4)]\; st %%g0,[%2+%%lo(%a0+8)]\;st %%g0,[%2+%%lo(%a0+12)]\";
2443 }"
2444   [(set_attr "type" "store")
2445    (set_attr "length" "5")])
2446 \f
2447 ;; Sparc V9 conditional move instructions.
2448
2449 ;; We can handle larger constants here for some flavors, but for now we keep
2450 ;; it simple and only allow those constants supported by all flavours.
2451 ;; Note that emit_conditional_move canonicalizes operands 2,3 so that operand
2452 ;; 3 contains the constant if one is present, but we handle either for
2453 ;; generality (sparc.c puts a constant in operand 2).
2454
2455 (define_expand "movqicc"
2456   [(set (match_operand:QI 0 "register_operand" "")
2457         (if_then_else:QI (match_operand 1 "comparison_operator" "")
2458                          (match_operand:QI 2 "arith10_operand" "")
2459                          (match_operand:QI 3 "arith10_operand" "")))]
2460   "TARGET_V9"
2461   "
2462 {
2463   enum rtx_code code = GET_CODE (operands[1]);
2464
2465   if (GET_MODE (sparc_compare_op0) == DImode
2466       && ! TARGET_ARCH64)
2467     FAIL;
2468
2469   if (sparc_compare_op1 == const0_rtx
2470       && GET_CODE (sparc_compare_op0) == REG
2471       && GET_MODE (sparc_compare_op0) == DImode
2472       && v9_regcmp_p (code))
2473     {
2474       operands[1] = gen_rtx (code, DImode,
2475                              sparc_compare_op0, sparc_compare_op1);
2476     }
2477   else
2478     {
2479       rtx cc_reg = gen_compare_reg (code,
2480                                     sparc_compare_op0, sparc_compare_op1);
2481       operands[1] = gen_rtx (code, GET_MODE (cc_reg), cc_reg, const0_rtx);
2482     }
2483 }")
2484
2485 (define_expand "movhicc"
2486   [(set (match_operand:HI 0 "register_operand" "")
2487         (if_then_else:HI (match_operand 1 "comparison_operator" "")
2488                          (match_operand:HI 2 "arith10_operand" "")
2489                          (match_operand:HI 3 "arith10_operand" "")))]
2490   "TARGET_V9"
2491   "
2492 {
2493   enum rtx_code code = GET_CODE (operands[1]);
2494
2495   if (GET_MODE (sparc_compare_op0) == DImode
2496       && ! TARGET_ARCH64)
2497     FAIL;
2498
2499   if (sparc_compare_op1 == const0_rtx
2500       && GET_CODE (sparc_compare_op0) == REG
2501       && GET_MODE (sparc_compare_op0) == DImode
2502       && v9_regcmp_p (code))
2503     {
2504       operands[1] = gen_rtx (code, DImode,
2505                              sparc_compare_op0, sparc_compare_op1);
2506     }
2507   else
2508     {
2509       rtx cc_reg = gen_compare_reg (code,
2510                                     sparc_compare_op0, sparc_compare_op1);
2511       operands[1] = gen_rtx (code, GET_MODE (cc_reg), cc_reg, const0_rtx);
2512     }
2513 }")
2514
2515 (define_expand "movsicc"
2516   [(set (match_operand:SI 0 "register_operand" "")
2517         (if_then_else:SI (match_operand 1 "comparison_operator" "")
2518                          (match_operand:SI 2 "arith10_operand" "")
2519                          (match_operand:SI 3 "arith10_operand" "")))]
2520   "TARGET_V9"
2521   "
2522 {
2523   enum rtx_code code = GET_CODE (operands[1]);
2524
2525   if (GET_MODE (sparc_compare_op0) == DImode
2526       && ! TARGET_ARCH64)
2527     FAIL;
2528
2529   if (sparc_compare_op1 == const0_rtx
2530       && GET_CODE (sparc_compare_op0) == REG
2531       && GET_MODE (sparc_compare_op0) == DImode
2532       && v9_regcmp_p (code))
2533     {
2534       operands[1] = gen_rtx (code, DImode,
2535                              sparc_compare_op0, sparc_compare_op1);
2536     }
2537   else
2538     {
2539       rtx cc_reg = gen_compare_reg (code,
2540                                     sparc_compare_op0, sparc_compare_op1);
2541       operands[1] = gen_rtx (code, GET_MODE (cc_reg), cc_reg, const0_rtx);
2542     }
2543 }")
2544
2545 (define_expand "movdicc"
2546   [(set (match_operand:DI 0 "register_operand" "")
2547         (if_then_else:DI (match_operand 1 "comparison_operator" "")
2548                          (match_operand:DI 2 "arith10_double_operand" "")
2549                          (match_operand:DI 3 "arith10_double_operand" "")))]
2550   "TARGET_ARCH64"
2551   "
2552 {
2553   enum rtx_code code = GET_CODE (operands[1]);
2554
2555   if (sparc_compare_op1 == const0_rtx
2556       && GET_CODE (sparc_compare_op0) == REG
2557       && GET_MODE (sparc_compare_op0) == DImode
2558       && v9_regcmp_p (code))
2559     {
2560       operands[1] = gen_rtx (code, DImode,
2561                              sparc_compare_op0, sparc_compare_op1);
2562     }
2563   else
2564     {
2565       rtx cc_reg = gen_compare_reg (code,
2566                                     sparc_compare_op0, sparc_compare_op1);
2567       operands[1] = gen_rtx (code, GET_MODE (cc_reg), cc_reg, const0_rtx);
2568     }
2569 }")
2570
2571 (define_expand "movsfcc"
2572   [(set (match_operand:SF 0 "register_operand" "")
2573         (if_then_else:SF (match_operand 1 "comparison_operator" "")
2574                          (match_operand:SF 2 "register_operand" "")
2575                          (match_operand:SF 3 "register_operand" "")))]
2576   "TARGET_V9 && TARGET_FPU"
2577   "
2578 {
2579   enum rtx_code code = GET_CODE (operands[1]);
2580
2581   if (GET_MODE (sparc_compare_op0) == DImode
2582       && ! TARGET_ARCH64)
2583     FAIL;
2584
2585   if (sparc_compare_op1 == const0_rtx
2586       && GET_CODE (sparc_compare_op0) == REG
2587       && GET_MODE (sparc_compare_op0) == DImode
2588       && v9_regcmp_p (code))
2589     {
2590       operands[1] = gen_rtx (code, DImode,
2591                              sparc_compare_op0, sparc_compare_op1);
2592     }
2593   else
2594     {
2595       rtx cc_reg = gen_compare_reg (code,
2596                                     sparc_compare_op0, sparc_compare_op1);
2597       operands[1] = gen_rtx (code, GET_MODE (cc_reg), cc_reg, const0_rtx);
2598     }
2599 }")
2600
2601 (define_expand "movdfcc"
2602   [(set (match_operand:DF 0 "register_operand" "")
2603         (if_then_else:DF (match_operand 1 "comparison_operator" "")
2604                          (match_operand:DF 2 "register_operand" "")
2605                          (match_operand:DF 3 "register_operand" "")))]
2606   "TARGET_V9 && TARGET_FPU"
2607   "
2608 {
2609   enum rtx_code code = GET_CODE (operands[1]);
2610
2611   if (GET_MODE (sparc_compare_op0) == DImode
2612       && ! TARGET_ARCH64)
2613     FAIL;
2614
2615   if (sparc_compare_op1 == const0_rtx
2616       && GET_CODE (sparc_compare_op0) == REG
2617       && GET_MODE (sparc_compare_op0) == DImode
2618       && v9_regcmp_p (code))
2619     {
2620       operands[1] = gen_rtx (code, DImode,
2621                              sparc_compare_op0, sparc_compare_op1);
2622     }
2623   else
2624     {
2625       rtx cc_reg = gen_compare_reg (code,
2626                                     sparc_compare_op0, sparc_compare_op1);
2627       operands[1] = gen_rtx (code, GET_MODE (cc_reg), cc_reg, const0_rtx);
2628     }
2629 }")
2630
2631 (define_expand "movtfcc"
2632   [(set (match_operand:TF 0 "register_operand" "")
2633         (if_then_else:TF (match_operand 1 "comparison_operator" "")
2634                          (match_operand:TF 2 "register_operand" "")
2635                          (match_operand:TF 3 "register_operand" "")))]
2636   "TARGET_V9 && TARGET_FPU"
2637   "
2638 {
2639   enum rtx_code code = GET_CODE (operands[1]);
2640
2641   if (GET_MODE (sparc_compare_op0) == DImode
2642       && ! TARGET_ARCH64)
2643     FAIL;
2644
2645   if (sparc_compare_op1 == const0_rtx
2646       && GET_CODE (sparc_compare_op0) == REG
2647       && GET_MODE (sparc_compare_op0) == DImode
2648       && v9_regcmp_p (code))
2649     {
2650       operands[1] = gen_rtx (code, DImode,
2651                              sparc_compare_op0, sparc_compare_op1);
2652     }
2653   else
2654     {
2655       rtx cc_reg = gen_compare_reg (code,
2656                                     sparc_compare_op0, sparc_compare_op1);
2657       operands[1] = gen_rtx (code, GET_MODE (cc_reg), cc_reg, const0_rtx);
2658     }
2659 }")
2660
2661 ;; Conditional move define_insns.
2662
2663 (define_insn "*movqi_cc_sp64"
2664   [(set (match_operand:QI 0 "register_operand" "=r,r")
2665         (if_then_else:QI (match_operator 1 "comparison_operator"
2666                                 [(match_operand 2 "icc_or_fcc_reg_operand" "X,X")
2667                                  (const_int 0)])
2668                       (match_operand:QI 3 "arith11_operand" "rL,0")
2669                       (match_operand:QI 4 "arith11_operand" "0,rL")))]
2670   "TARGET_V9"
2671   "@
2672    mov%C1 %x2,%3,%0
2673    mov%c1 %x2,%4,%0"
2674   [(set_attr "type" "cmove")])
2675
2676 (define_insn "*movhi_cc_sp64"
2677   [(set (match_operand:HI 0 "register_operand" "=r,r")
2678         (if_then_else:HI (match_operator 1 "comparison_operator"
2679                                 [(match_operand 2 "icc_or_fcc_reg_operand" "X,X")
2680                                  (const_int 0)])
2681                       (match_operand:HI 3 "arith11_operand" "rL,0")
2682                       (match_operand:HI 4 "arith11_operand" "0,rL")))]
2683   "TARGET_V9"
2684   "@
2685    mov%C1 %x2,%3,%0
2686    mov%c1 %x2,%4,%0"
2687   [(set_attr "type" "cmove")])
2688
2689 (define_insn "*movsi_cc_sp64"
2690   [(set (match_operand:SI 0 "register_operand" "=r,r")
2691         (if_then_else:SI (match_operator 1 "comparison_operator"
2692                                 [(match_operand 2 "icc_or_fcc_reg_operand" "X,X")
2693                                  (const_int 0)])
2694                       (match_operand:SI 3 "arith11_operand" "rL,0")
2695                       (match_operand:SI 4 "arith11_operand" "0,rL")))]
2696   "TARGET_V9"
2697   "@
2698    mov%C1 %x2,%3,%0
2699    mov%c1 %x2,%4,%0"
2700   [(set_attr "type" "cmove")])
2701
2702 ;; ??? The constraints of operands 3,4 need work.
2703 (define_insn "*movdi_cc_sp64"
2704   [(set (match_operand:DI 0 "register_operand" "=r,r")
2705         (if_then_else:DI (match_operator 1 "comparison_operator"
2706                                 [(match_operand 2 "icc_or_fcc_reg_operand" "X,X")
2707                                  (const_int 0)])
2708                       (match_operand:DI 3 "arith11_double_operand" "rLH,0")
2709                       (match_operand:DI 4 "arith11_double_operand" "0,rLH")))]
2710   "TARGET_ARCH64"
2711   "@
2712    mov%C1 %x2,%3,%0
2713    mov%c1 %x2,%4,%0"
2714   [(set_attr "type" "cmove")])
2715
2716 (define_insn "*movsf_cc_sp64"
2717   [(set (match_operand:SF 0 "register_operand" "=f,f")
2718         (if_then_else:SF (match_operator 1 "comparison_operator"
2719                                 [(match_operand 2 "icc_or_fcc_reg_operand" "X,X")
2720                                  (const_int 0)])
2721                       (match_operand:SF 3 "register_operand" "f,0")
2722                       (match_operand:SF 4 "register_operand" "0,f")))]
2723   "TARGET_V9 && TARGET_FPU"
2724   "@
2725    fmovs%C1 %x2,%3,%0
2726    fmovs%c1 %x2,%4,%0"
2727   [(set_attr "type" "cmove")])
2728
2729 (define_insn "*movdf_cc_sp64"
2730   [(set (match_operand:DF 0 "register_operand" "=e,e")
2731         (if_then_else:DF (match_operator 1 "comparison_operator"
2732                                 [(match_operand 2 "icc_or_fcc_reg_operand" "X,X")
2733                                  (const_int 0)])
2734                       (match_operand:DF 3 "register_operand" "e,0")
2735                       (match_operand:DF 4 "register_operand" "0,e")))]
2736   "TARGET_V9 && TARGET_FPU"
2737   "@
2738    fmovd%C1 %x2,%3,%0
2739    fmovd%c1 %x2,%4,%0"
2740   [(set_attr "type" "cmove")])
2741
2742 (define_insn "*movtf_cc_sp64"
2743   [(set (match_operand:TF 0 "register_operand" "=e,e")
2744         (if_then_else:TF (match_operator 1 "comparison_operator"
2745                                 [(match_operand 2 "icc_or_fcc_reg_operand" "X,X")
2746                                  (const_int 0)])
2747                       (match_operand:TF 3 "register_operand" "e,0")
2748                       (match_operand:TF 4 "register_operand" "0,e")))]
2749   "TARGET_V9 && TARGET_FPU && TARGET_HARD_QUAD"
2750   "@
2751    fmovq%C1 %x2,%3,%0
2752    fmovq%c1 %x2,%4,%0"
2753   [(set_attr "type" "cmove")])
2754
2755 (define_insn "*movqi_cc_reg_sp64"
2756   [(set (match_operand:QI 0 "register_operand" "=r,r")
2757         (if_then_else:QI (match_operator 1 "v9_regcmp_op"
2758                                 [(match_operand:DI 2 "register_operand" "r,r")
2759                                  (const_int 0)])
2760                       (match_operand:QI 3 "arith10_operand" "rM,0")
2761                       (match_operand:QI 4 "arith10_operand" "0,rM")))]
2762   "TARGET_ARCH64"
2763   "@
2764    movr%D1 %2,%r3,%0
2765    movr%d1 %2,%r4,%0"
2766   [(set_attr "type" "cmove")])
2767
2768 (define_insn "*movhi_cc_reg_sp64"
2769   [(set (match_operand:HI 0 "register_operand" "=r,r")
2770         (if_then_else:HI (match_operator 1 "v9_regcmp_op"
2771                                 [(match_operand:DI 2 "register_operand" "r,r")
2772                                  (const_int 0)])
2773                       (match_operand:HI 3 "arith10_operand" "rM,0")
2774                       (match_operand:HI 4 "arith10_operand" "0,rM")))]
2775   "TARGET_ARCH64"
2776   "@
2777    movr%D1 %2,%r3,%0
2778    movr%d1 %2,%r4,%0"
2779   [(set_attr "type" "cmove")])
2780
2781 (define_insn "*movsi_cc_reg_sp64"
2782   [(set (match_operand:SI 0 "register_operand" "=r,r")
2783         (if_then_else:SI (match_operator 1 "v9_regcmp_op"
2784                                 [(match_operand:DI 2 "register_operand" "r,r")
2785                                  (const_int 0)])
2786                       (match_operand:SI 3 "arith10_operand" "rM,0")
2787                       (match_operand:SI 4 "arith10_operand" "0,rM")))]
2788   "TARGET_ARCH64"
2789   "@
2790    movr%D1 %2,%r3,%0
2791    movr%d1 %2,%r4,%0"
2792   [(set_attr "type" "cmove")])
2793
2794 ;; ??? The constraints of operands 3,4 need work.
2795 (define_insn "*movdi_cc_reg_sp64"
2796   [(set (match_operand:DI 0 "register_operand" "=r,r")
2797         (if_then_else:DI (match_operator 1 "v9_regcmp_op"
2798                                 [(match_operand:DI 2 "register_operand" "r,r")
2799                                  (const_int 0)])
2800                       (match_operand:DI 3 "arith10_double_operand" "rMH,0")
2801                       (match_operand:DI 4 "arith10_double_operand" "0,rMH")))]
2802   "TARGET_ARCH64"
2803   "@
2804    movr%D1 %2,%r3,%0
2805    movr%d1 %2,%r4,%0"
2806   [(set_attr "type" "cmove")])
2807
2808 (define_insn "*movsf_cc_reg_sp64"
2809   [(set (match_operand:SF 0 "register_operand" "=f,f")
2810         (if_then_else:SF (match_operator 1 "v9_regcmp_op"
2811                                 [(match_operand:DI 2 "register_operand" "r,r")
2812                                  (const_int 0)])
2813                       (match_operand:SF 3 "register_operand" "f,0")
2814                       (match_operand:SF 4 "register_operand" "0,f")))]
2815   "TARGET_ARCH64 && TARGET_FPU"
2816   "@
2817    fmovrs%D1 %2,%3,%0
2818    fmovrs%d1 %2,%4,%0"
2819   [(set_attr "type" "cmove")])
2820
2821 (define_insn "*movdf_cc_reg_sp64"
2822   [(set (match_operand:DF 0 "register_operand" "=e,e")
2823         (if_then_else:DF (match_operator 1 "v9_regcmp_op"
2824                                 [(match_operand:DI 2 "register_operand" "r,r")
2825                                  (const_int 0)])
2826                       (match_operand:DF 3 "register_operand" "e,0")
2827                       (match_operand:DF 4 "register_operand" "0,e")))]
2828   "TARGET_ARCH64 && TARGET_FPU"
2829   "@
2830    fmovrd%D1 %2,%3,%0
2831    fmovrd%d1 %2,%4,%0"
2832   [(set_attr "type" "cmove")])
2833
2834 (define_insn "*movtf_cc_reg_sp64"
2835   [(set (match_operand:TF 0 "register_operand" "=e,e")
2836         (if_then_else:TF (match_operator 1 "v9_regcmp_op"
2837                                 [(match_operand:DI 2 "register_operand" "r,r")
2838                                  (const_int 0)])
2839                       (match_operand:TF 3 "register_operand" "e,0")
2840                       (match_operand:TF 4 "register_operand" "0,e")))]
2841   "TARGET_ARCH64 && TARGET_FPU"
2842   "@
2843    fmovrq%D1 %2,%3,%0
2844    fmovrq%d1 %2,%4,%0"
2845   [(set_attr "type" "cmove")])
2846 \f
2847 ;;- zero extension instructions
2848
2849 ;; These patterns originally accepted general_operands, however, slightly
2850 ;; better code is generated by only accepting register_operands, and then
2851 ;; letting combine generate the ldu[hb] insns.
2852
2853 (define_expand "zero_extendhisi2"
2854   [(set (match_operand:SI 0 "register_operand" "")
2855         (zero_extend:SI (match_operand:HI 1 "register_operand" "")))]
2856   ""
2857   "
2858 {
2859   rtx temp = gen_reg_rtx (SImode);
2860   rtx shift_16 = GEN_INT (16);
2861   int op1_subword = 0;
2862
2863   if (GET_CODE (operand1) == SUBREG)
2864     {
2865       op1_subword = SUBREG_WORD (operand1);
2866       operand1 = XEXP (operand1, 0);
2867     }
2868
2869   emit_insn (gen_ashlsi3 (temp, gen_rtx (SUBREG, SImode, operand1,
2870                                          op1_subword),
2871                           shift_16));
2872   emit_insn (gen_lshrsi3 (operand0, temp, shift_16));
2873   DONE;
2874 }")
2875
2876 (define_insn "*zero_extendhisi2_insn"
2877   [(set (match_operand:SI 0 "register_operand" "=r")
2878         (zero_extend:SI (match_operand:HI 1 "memory_operand" "m")))]
2879   ""
2880   "lduh %1,%0"
2881   [(set_attr "type" "load")])
2882
2883 (define_expand "zero_extendqihi2"
2884   [(set (match_operand:HI 0 "register_operand" "")
2885         (zero_extend:HI (match_operand:QI 1 "register_operand" "")))]
2886   ""
2887   "")
2888
2889 (define_insn "*zero_extendqihi2_insn"
2890   [(set (match_operand:HI 0 "register_operand" "=r,r")
2891         (zero_extend:HI (match_operand:QI 1 "sparc_operand" "r,Q")))]
2892   "GET_CODE (operands[1]) != CONST_INT"
2893   "@
2894    and %1,0xff,%0
2895    ldub %1,%0"
2896   [(set_attr "type" "unary,load")
2897    (set_attr "length" "1")])
2898
2899 (define_expand "zero_extendqisi2"
2900   [(set (match_operand:SI 0 "register_operand" "")
2901         (zero_extend:SI (match_operand:QI 1 "register_operand" "")))]
2902   ""
2903   "")
2904
2905 (define_insn "*zero_extendqisi2_insn"
2906   [(set (match_operand:SI 0 "register_operand" "=r,r")
2907         (zero_extend:SI (match_operand:QI 1 "sparc_operand" "r,Q")))]
2908   "GET_CODE (operands[1]) != CONST_INT"
2909   "@
2910    and %1,0xff,%0
2911    ldub %1,%0"
2912   [(set_attr "type" "unary,load")
2913    (set_attr "length" "1")])
2914
2915 (define_expand "zero_extendqidi2"
2916   [(set (match_operand:DI 0 "register_operand" "")
2917         (zero_extend:DI (match_operand:QI 1 "register_operand" "")))]
2918   "TARGET_ARCH64"
2919   "")
2920
2921 (define_insn "*zero_extendqidi2_insn"
2922   [(set (match_operand:DI 0 "register_operand" "=r,r")
2923         (zero_extend:DI (match_operand:QI 1 "sparc_operand" "r,Q")))]
2924   "TARGET_ARCH64 && GET_CODE (operands[1]) != CONST_INT"
2925   "@
2926    and %1,0xff,%0
2927    ldub %1,%0"
2928   [(set_attr "type" "unary,load")
2929    (set_attr "length" "1")])
2930
2931 (define_expand "zero_extendhidi2"
2932   [(set (match_operand:DI 0 "register_operand" "")
2933         (zero_extend:DI (match_operand:HI 1 "register_operand" "")))]
2934   "TARGET_ARCH64"
2935   "
2936 {
2937   rtx temp = gen_reg_rtx (DImode);
2938   rtx shift_48 = GEN_INT (48);
2939   int op1_subword = 0;
2940
2941   if (GET_CODE (operand1) == SUBREG)
2942     {
2943       op1_subword = SUBREG_WORD (operand1);
2944       operand1 = XEXP (operand1, 0);
2945     }
2946
2947   emit_insn (gen_ashldi3 (temp, gen_rtx (SUBREG, DImode, operand1,
2948                                          op1_subword),
2949                           shift_48));
2950   emit_insn (gen_lshrdi3 (operand0, temp, shift_48));
2951   DONE;
2952 }")
2953
2954 (define_insn "*zero_extendhidi2_insn"
2955   [(set (match_operand:DI 0 "register_operand" "=r")
2956         (zero_extend:DI (match_operand:HI 1 "memory_operand" "m")))]
2957   "TARGET_ARCH64"
2958   "lduh %1,%0"
2959   [(set_attr "type" "load")])
2960
2961 ;; ??? Write truncdisi pattern using sra?
2962
2963 (define_expand "zero_extendsidi2"
2964   [(set (match_operand:DI 0 "register_operand" "")
2965         (zero_extend:DI (match_operand:SI 1 "register_operand" "")))]
2966   "TARGET_ARCH64"
2967   "")
2968
2969 (define_insn "*zero_extendsidi2_insn"
2970   [(set (match_operand:DI 0 "register_operand" "=r,r")
2971         (zero_extend:DI (match_operand:SI 1 "sparc_operand" "r,Q")))]
2972   "TARGET_ARCH64 && GET_CODE (operands[1]) != CONST_INT"
2973   "@
2974    srl %1,0,%0
2975    lduw %1,%0"
2976   [(set_attr "type" "unary,load")
2977    (set_attr "length" "1")])
2978
2979 ;; Simplify comparisons of extended values.
2980
2981 (define_insn "*cmp_zero_extendqisi2"
2982   [(set (reg:CC 100)
2983         (compare:CC (zero_extend:SI (match_operand:QI 0 "register_operand" "r"))
2984                     (const_int 0)))]
2985   ""
2986   "andcc %0,0xff,%%g0"
2987   [(set_attr "type" "compare")])
2988
2989 (define_insn "*cmp_zero_extendqisi2_set"
2990   [(set (reg:CC 100)
2991         (compare:CC (zero_extend:SI (match_operand:QI 1 "register_operand" "r"))
2992                     (const_int 0)))
2993    (set (match_operand:SI 0 "register_operand" "=r")
2994         (zero_extend:SI (match_dup 1)))]
2995   ""
2996   "andcc %1,0xff,%0"
2997   [(set_attr "type" "unary")])
2998
2999 ;; Similarly, handle SI->QI mode truncation followed by a compare.
3000
3001 (define_insn "*cmp_siqi_trunc"
3002   [(set (reg:CC 100)
3003         (compare:CC (subreg:QI (match_operand:SI 0 "register_operand" "r") 0)
3004                     (const_int 0)))]
3005   ""
3006   "andcc %0,0xff,%%g0"
3007   [(set_attr "type" "compare")])
3008
3009 (define_insn "*cmp_siqi_trunc_set"
3010   [(set (reg:CC 100)
3011         (compare:CC (subreg:QI (match_operand:SI 1 "register_operand" "r") 0)
3012                     (const_int 0)))
3013    (set (match_operand:QI 0 "register_operand" "=r")
3014         (match_dup 1))]
3015   ""
3016   "andcc %1,0xff,%0"
3017   [(set_attr "type" "unary")])
3018 \f
3019 ;;- sign extension instructions
3020
3021 ;; These patterns originally accepted general_operands, however, slightly
3022 ;; better code is generated by only accepting register_operands, and then
3023 ;; letting combine generate the lds[hb] insns.
3024
3025 (define_expand "extendhisi2"
3026   [(set (match_operand:SI 0 "register_operand" "")
3027         (sign_extend:SI (match_operand:HI 1 "register_operand" "")))]
3028   ""
3029   "
3030 {
3031   rtx temp = gen_reg_rtx (SImode);
3032   rtx shift_16 = GEN_INT (16);
3033   int op1_subword = 0;
3034
3035   if (GET_CODE (operand1) == SUBREG)
3036     {
3037       op1_subword = SUBREG_WORD (operand1);
3038       operand1 = XEXP (operand1, 0);
3039     }
3040
3041   emit_insn (gen_ashlsi3 (temp, gen_rtx (SUBREG, SImode, operand1,
3042                                          op1_subword),
3043                           shift_16));
3044   emit_insn (gen_ashrsi3 (operand0, temp, shift_16));
3045   DONE;
3046 }")
3047
3048 (define_insn "*sign_extendhisi2_insn"
3049   [(set (match_operand:SI 0 "register_operand" "=r")
3050         (sign_extend:SI (match_operand:HI 1 "memory_operand" "m")))]
3051   ""
3052   "ldsh %1,%0"
3053   [(set_attr "type" "load")])
3054
3055 (define_expand "extendqihi2"
3056   [(set (match_operand:HI 0 "register_operand" "")
3057         (sign_extend:HI (match_operand:QI 1 "register_operand" "")))]
3058   ""
3059   "
3060 {
3061   rtx temp = gen_reg_rtx (SImode);
3062   rtx shift_24 = GEN_INT (24);
3063   int op1_subword = 0;
3064   int op0_subword = 0;
3065
3066   if (GET_CODE (operand1) == SUBREG)
3067     {
3068       op1_subword = SUBREG_WORD (operand1);
3069       operand1 = XEXP (operand1, 0);
3070     }
3071   if (GET_CODE (operand0) == SUBREG)
3072     {
3073       op0_subword = SUBREG_WORD (operand0);
3074       operand0 = XEXP (operand0, 0);
3075     }
3076   emit_insn (gen_ashlsi3 (temp, gen_rtx (SUBREG, SImode, operand1,
3077                                          op1_subword),
3078                           shift_24));
3079   if (GET_MODE (operand0) != SImode)
3080     operand0 = gen_rtx (SUBREG, SImode, operand0, op0_subword);
3081   emit_insn (gen_ashrsi3 (operand0, temp, shift_24));
3082   DONE;
3083 }")
3084
3085 (define_insn "*sign_extendqihi2_insn"
3086   [(set (match_operand:HI 0 "register_operand" "=r")
3087         (sign_extend:HI (match_operand:QI 1 "memory_operand" "m")))]
3088   ""
3089   "ldsb %1,%0"
3090   [(set_attr "type" "load")])
3091
3092 (define_expand "extendqisi2"
3093   [(set (match_operand:SI 0 "register_operand" "")
3094         (sign_extend:SI (match_operand:QI 1 "register_operand" "")))]
3095   ""
3096   "
3097 {
3098   rtx temp = gen_reg_rtx (SImode);
3099   rtx shift_24 = GEN_INT (24);
3100   int op1_subword = 0;
3101
3102   if (GET_CODE (operand1) == SUBREG)
3103     {
3104       op1_subword = SUBREG_WORD (operand1);
3105       operand1 = XEXP (operand1, 0);
3106     }
3107
3108   emit_insn (gen_ashlsi3 (temp, gen_rtx (SUBREG, SImode, operand1,
3109                                          op1_subword),
3110                           shift_24));
3111   emit_insn (gen_ashrsi3 (operand0, temp, shift_24));
3112   DONE;
3113 }")
3114
3115 (define_insn "*sign_extendqisi2_insn"
3116   [(set (match_operand:SI 0 "register_operand" "=r")
3117         (sign_extend:SI (match_operand:QI 1 "memory_operand" "m")))]
3118   ""
3119   "ldsb %1,%0"
3120   [(set_attr "type" "load")])
3121
3122 (define_expand "extendqidi2"
3123   [(set (match_operand:DI 0 "register_operand" "")
3124         (sign_extend:DI (match_operand:QI 1 "register_operand" "")))]
3125   "TARGET_ARCH64"
3126   "
3127 {
3128   rtx temp = gen_reg_rtx (DImode);
3129   rtx shift_56 = GEN_INT (56);
3130   int op1_subword = 0;
3131
3132   if (GET_CODE (operand1) == SUBREG)
3133     {
3134       op1_subword = SUBREG_WORD (operand1);
3135       operand1 = XEXP (operand1, 0);
3136     }
3137
3138   emit_insn (gen_ashldi3 (temp, gen_rtx (SUBREG, DImode, operand1,
3139                                          op1_subword),
3140                           shift_56));
3141   emit_insn (gen_ashrdi3 (operand0, temp, shift_56));
3142   DONE;
3143 }")
3144
3145 (define_insn "*sign_extendqidi2_insn"
3146   [(set (match_operand:DI 0 "register_operand" "=r")
3147         (sign_extend:DI (match_operand:QI 1 "memory_operand" "m")))]
3148   "TARGET_ARCH64"
3149   "ldsb %1,%0"
3150   [(set_attr "type" "load")])
3151
3152 (define_expand "extendhidi2"
3153   [(set (match_operand:DI 0 "register_operand" "")
3154         (sign_extend:DI (match_operand:HI 1 "register_operand" "")))]
3155   "TARGET_ARCH64"
3156   "
3157 {
3158   rtx temp = gen_reg_rtx (DImode);
3159   rtx shift_48 = GEN_INT (48);
3160   int op1_subword = 0;
3161
3162   if (GET_CODE (operand1) == SUBREG)
3163     {
3164       op1_subword = SUBREG_WORD (operand1);
3165       operand1 = XEXP (operand1, 0);
3166     }
3167
3168   emit_insn (gen_ashldi3 (temp, gen_rtx (SUBREG, DImode, operand1,
3169                                          op1_subword),
3170                           shift_48));
3171   emit_insn (gen_ashrdi3 (operand0, temp, shift_48));
3172   DONE;
3173 }")
3174
3175 (define_insn "*sign_extendhidi2_insn"
3176   [(set (match_operand:DI 0 "register_operand" "=r")
3177         (sign_extend:DI (match_operand:HI 1 "memory_operand" "m")))]
3178   "TARGET_ARCH64"
3179   "ldsh %1,%0"
3180   [(set_attr "type" "load")])
3181
3182 (define_expand "extendsidi2"
3183   [(set (match_operand:DI 0 "register_operand" "")
3184         (sign_extend:DI (match_operand:SI 1 "register_operand" "")))]
3185   "TARGET_ARCH64"
3186   "")
3187
3188 (define_insn "*sign_extendsidi2_insn"
3189   [(set (match_operand:DI 0 "register_operand" "=r,r")
3190         (sign_extend:DI (match_operand:SI 1 "sparc_operand" "r,Q")))]
3191   "TARGET_ARCH64"
3192   "@
3193   sra %1,0,%0
3194   ldsw %1,%0"
3195   [(set_attr "type" "unary,load")
3196    (set_attr "length" "1")])
3197 \f
3198 ;; Special pattern for optimizing bit-field compares.  This is needed
3199 ;; because combine uses this as a canonical form.
3200
3201 (define_insn "*cmp_zero_extract"
3202   [(set (reg:CC 100)
3203         (compare:CC
3204          (zero_extract:SI (match_operand:SI 0 "register_operand" "r")
3205                           (match_operand:SI 1 "small_int" "n")
3206                           (match_operand:SI 2 "small_int" "n"))
3207          (const_int 0)))]
3208   "INTVAL (operands[2]) > 19"
3209   "*
3210 {
3211   int len = INTVAL (operands[1]);
3212   int pos = 32 - INTVAL (operands[2]) - len;
3213   unsigned mask = ((1 << len) - 1) << pos;
3214
3215   operands[1] = GEN_INT (mask);
3216   return \"andcc %0,%1,%%g0\";
3217 }")
3218
3219 (define_insn "*cmp_zero_extract_sp64"
3220   [(set (reg:CCX 100)
3221         (compare:CCX
3222          (zero_extract:DI (match_operand:DI 0 "register_operand" "r")
3223                           (match_operand:SI 1 "small_int" "n")
3224                           (match_operand:SI 2 "small_int" "n"))
3225          (const_int 0)))]
3226   "TARGET_ARCH64 && INTVAL (operands[2]) > 51"
3227   "*
3228 {
3229   int len = INTVAL (operands[1]);
3230   int pos = 64 - INTVAL (operands[2]) - len;
3231   unsigned HOST_WIDE_INT mask = (((unsigned HOST_WIDE_INT) 1 << len) - 1) << pos;
3232
3233   operands[1] = GEN_INT (mask);
3234   return \"andcc %0,%1,%%g0\";
3235 }")
3236 \f
3237 ;; Conversions between float, double and long double.
3238
3239 (define_insn "extendsfdf2"
3240   [(set (match_operand:DF 0 "register_operand" "=e")
3241         (float_extend:DF
3242          (match_operand:SF 1 "register_operand" "f")))]
3243   "TARGET_FPU"
3244   "fstod %1,%0"
3245   [(set_attr "type" "fp")])
3246
3247 (define_insn "extendsftf2"
3248   [(set (match_operand:TF 0 "register_operand" "=e")
3249         (float_extend:TF
3250          (match_operand:SF 1 "register_operand" "f")))]
3251   "TARGET_FPU && TARGET_HARD_QUAD"
3252   "fstoq %1,%0"
3253   [(set_attr "type" "fp")])
3254
3255 (define_insn "extenddftf2"
3256   [(set (match_operand:TF 0 "register_operand" "=e")
3257         (float_extend:TF
3258          (match_operand:DF 1 "register_operand" "e")))]
3259   "TARGET_FPU && TARGET_HARD_QUAD"
3260   "fdtoq %1,%0"
3261   [(set_attr "type" "fp")])
3262
3263 (define_insn "truncdfsf2"
3264   [(set (match_operand:SF 0 "register_operand" "=f")
3265         (float_truncate:SF
3266          (match_operand:DF 1 "register_operand" "e")))]
3267   "TARGET_FPU"
3268   "fdtos %1,%0"
3269   [(set_attr "type" "fp")])
3270
3271 (define_insn "trunctfsf2"
3272   [(set (match_operand:SF 0 "register_operand" "=f")
3273         (float_truncate:SF
3274          (match_operand:TF 1 "register_operand" "e")))]
3275   "TARGET_FPU && TARGET_HARD_QUAD"
3276   "fqtos %1,%0"
3277   [(set_attr "type" "fp")])
3278
3279 (define_insn "trunctfdf2"
3280   [(set (match_operand:DF 0 "register_operand" "=e")
3281         (float_truncate:DF
3282          (match_operand:TF 1 "register_operand" "e")))]
3283   "TARGET_FPU && TARGET_HARD_QUAD"
3284   "fqtod %1,%0"
3285   [(set_attr "type" "fp")])
3286 \f
3287 ;; Conversion between fixed point and floating point.
3288
3289 (define_insn "floatsisf2"
3290   [(set (match_operand:SF 0 "register_operand" "=f")
3291         (float:SF (match_operand:SI 1 "register_operand" "f")))]
3292   "TARGET_FPU"
3293   "fitos %1,%0"
3294   [(set_attr "type" "fp")])
3295
3296 (define_insn "floatsidf2"
3297   [(set (match_operand:DF 0 "register_operand" "=e")
3298         (float:DF (match_operand:SI 1 "register_operand" "f")))]
3299   "TARGET_FPU"
3300   "fitod %1,%0"
3301   [(set_attr "type" "fp")])
3302
3303 (define_insn "floatsitf2"
3304   [(set (match_operand:TF 0 "register_operand" "=e")
3305         (float:TF (match_operand:SI 1 "register_operand" "f")))]
3306   "TARGET_FPU && TARGET_HARD_QUAD"
3307   "fitoq %1,%0"
3308   [(set_attr "type" "fp")])
3309
3310 ;; Now the same for 64 bit sources.
3311 ;; ??? We cannot put DImode values in fp regs (see below near fix_truncdfsi2).
3312
3313 (define_expand "floatdisf2"
3314   [(parallel [(set (match_operand:SF 0 "register_operand" "")
3315                    (float:SF (match_operand:DI 1 "general_operand" "")))
3316               (clobber (match_dup 2))
3317               (clobber (match_dup 3))])]
3318   "TARGET_ARCH64 && TARGET_FPU"
3319   "
3320 {
3321   operands[2] = gen_reg_rtx (DFmode);
3322   operands[3] = sparc64_fpconv_stack_temp ();
3323 }")
3324
3325 (define_expand "floatdidf2"
3326   [(parallel [(set (match_operand:DF 0 "register_operand" "")
3327                    (float:DF (match_operand:DI 1 "general_operand" "")))
3328               (clobber (match_dup 2))
3329               (clobber (match_dup 3))])]
3330   "TARGET_ARCH64 && TARGET_FPU"
3331   "
3332 {
3333   operands[2] = gen_reg_rtx (DFmode);
3334   operands[3] = sparc64_fpconv_stack_temp ();
3335 }")
3336
3337 (define_expand "floatditf2"
3338   [(parallel [(set (match_operand:TF 0 "register_operand" "")
3339                    (float:TF (match_operand:DI 1 "general_operand" "")))
3340               (clobber (match_dup 2))
3341               (clobber (match_dup 3))])]
3342   "TARGET_ARCH64 && TARGET_FPU && TARGET_HARD_QUAD"
3343   "
3344 {
3345   operands[2] = gen_reg_rtx (DFmode);
3346   operands[3] = sparc64_fpconv_stack_temp ();
3347 }")
3348
3349 (define_insn "*floatdisf2_insn"
3350   [(parallel [(set (match_operand:SF 0 "register_operand" "=f")
3351                    (float:SF (match_operand:DI 1 "general_operand" "rm")))
3352               (clobber (match_operand:DF 2 "register_operand" "=&e"))
3353               (clobber (match_operand:DI 3 "memory_operand" "m"))])]
3354   "TARGET_ARCH64 && TARGET_FPU"
3355   "*
3356 {
3357   if (GET_CODE (operands[1]) == MEM)
3358     output_asm_insn (\"ldd %1,%2\", operands);
3359   else
3360     output_asm_insn (\"stx %1,%3\;ldd %3,%2\", operands);
3361   return \"fxtos %2,%0\";
3362 }"
3363   [(set_attr "type" "fp")
3364    (set_attr "length" "3")])
3365
3366 (define_insn "*floatdidf2_insn"
3367   [(parallel [(set (match_operand:DF 0 "register_operand" "=e")
3368                    (float:DF (match_operand:DI 1 "general_operand" "rm")))
3369               (clobber (match_operand:DF 2 "register_operand" "=&e"))
3370               (clobber (match_operand:DI 3 "memory_operand" "m"))])]
3371   "TARGET_ARCH64 && TARGET_FPU"
3372   "*
3373 {
3374   if (GET_CODE (operands[1]) == MEM)
3375     output_asm_insn (\"ldd %1,%2\", operands);
3376   else
3377     output_asm_insn (\"stx %1,%3\;ldd %3,%2\", operands);
3378   return \"fxtod %2,%0\";
3379 }"
3380   [(set_attr "type" "fp")
3381    (set_attr "length" "3")])
3382
3383 (define_insn "*floatditf2_insn"
3384   [(parallel [(set (match_operand:TF 0 "register_operand" "=e")
3385                    (float:TF (match_operand:DI 1 "general_operand" "rm")))
3386               (clobber (match_operand:DF 2 "register_operand" "=&e"))
3387               (clobber (match_operand:DI 3 "memory_operand" "m"))])]
3388   "TARGET_ARCH64 && TARGET_FPU && TARGET_HARD_QUAD"
3389   "*
3390 {
3391   if (GET_CODE (operands[1]) == MEM)
3392     output_asm_insn (\"ldd %1,%2\", operands);
3393   else
3394     output_asm_insn (\"stx %1,%3\;ldd %3,%2\", operands);
3395   return \"fxtoq %2,%0\";
3396 }"
3397   [(set_attr "type" "fp")
3398    (set_attr "length" "3")])
3399
3400 ;; ??? Ideally, these are what we would like to use.
3401
3402 (define_insn "floatdisf2_sp64"
3403   [(set (match_operand:SF 0 "register_operand" "=f")
3404         (float:SF (match_operand:DI 1 "register_operand" "e")))]
3405   "0 && TARGET_ARCH64 && TARGET_FPU"
3406   "fxtos %1,%0"
3407   [(set_attr "type" "fp")])
3408
3409 (define_insn "floatdidf2_sp64"
3410   [(set (match_operand:DF 0 "register_operand" "=e")
3411         (float:DF (match_operand:DI 1 "register_operand" "e")))]
3412   "0 && TARGET_ARCH64 && TARGET_FPU"
3413   "fxtod %1,%0"
3414   [(set_attr "type" "fp")])