OSDN Git Service

2aac850a2bdb97414ef1ba42ca378f7e99a79548
[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 "*sethi_hi"
1483   [(set (match_operand:HI 0 "register_operand" "=r")
1484         (high:HI (match_operand 1 "" "")))]
1485   "check_pic (1)"
1486   "sethi %%hi(%a1),%0"
1487   [(set_attr "type" "move")
1488    (set_attr "length" "1")])
1489
1490 (define_insn "*sethi_si"
1491   [(set (match_operand:SI 0 "register_operand" "=r")
1492         (high:SI (match_operand 1 "" "")))]
1493   "check_pic (1)"
1494   "sethi %%hi(%a1),%0"
1495   [(set_attr "type" "move")
1496    (set_attr "length" "1")])
1497
1498 (define_insn "*lo_sum_si"
1499   [(set (match_operand:SI 0 "register_operand" "=r")
1500         (lo_sum:SI (match_operand:SI 1 "register_operand" "r")
1501                    (match_operand:SI 2 "immediate_operand" "in")))]
1502   ""
1503   ;; V9 needs "add" because of the code models.  We still use "or" for v8
1504   ;; so we can compare the old compiler with the new.
1505   "* return TARGET_ARCH64 ? \"add %1,%%lo(%a2),%0\" : \"or %1,%%lo(%a2),%0\";"
1506   ;; Need to set length for this arith insn because operand2
1507   ;; is not an "arith_operand".
1508   [(set_attr "length" "1")])
1509
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_lo_sum_si"
1513   [(set (match_operand:SI 0 "register_operand" "=r")
1514         (lo_sum:SI (match_operand:SI 1 "register_operand" "r")
1515                    (unspec:SI [(match_operand:SI 2 "immediate_operand" "in")] 0)))]
1516   "flag_pic"
1517   ;; V9 needs "add" because of the code models.  We still use "or" for v8
1518   ;; so we can compare the old compiler with the new.
1519   "* return TARGET_ARCH64 ? \"add %1,%%lo(%a2),%0\" : \"or %1,%%lo(%a2),%0\";"
1520   ;; Need to set length for this arith insn because operand2
1521   ;; is not an "arith_operand".
1522   [(set_attr "length" "1")])
1523
1524 ;; The PIC version of sethi must appear before the non-pic case so that
1525 ;; the unspec will not be matched as part of the operand.
1526 ;; For PIC, symbol_refs are put inside unspec so that the optimizer will not
1527 ;; confuse them with real addresses.
1528 (define_insn "pic_sethi_si"
1529   [(set (match_operand:SI 0 "register_operand" "=r")
1530         (high:SI (unspec:SI [(match_operand 1 "" "")] 0)))]
1531   "flag_pic && check_pic (1)"
1532   "sethi %%hi(%a1),%0"
1533   [(set_attr "type" "move")
1534    (set_attr "length" "1")])
1535
1536 (define_insn "pic_lo_sum_di"
1537   [(set (match_operand:DI 0 "register_operand" "=r")
1538         (lo_sum:SI (match_operand:DI 1 "register_operand" "r")
1539                    (unspec:SI [(match_operand:DI 2 "immediate_operand" "in")] 0)))]
1540   "TARGET_ARCH64 && flag_pic"
1541   "add %1,%%lo(%a2),%0"
1542   [(set_attr "length" "1")])
1543
1544 (define_insn "pic_sethi_di"
1545   [(set (match_operand:DI 0 "register_operand" "=r")
1546         (high:SI (unspec:SI [(match_operand 1 "" "")] 0)))]
1547   "TARGET_ARCH64 && flag_pic && check_pic (1)"
1548   "sethi %%hi(%a1),%0"
1549   [(set_attr "type" "move")
1550    (set_attr "length" "1")])
1551
1552 (define_insn "get_pc_via_call"
1553   [(set (pc) (label_ref (match_operand 0 "" "")))
1554    (set (reg:SI 15) (label_ref (match_operand 1 "" "")))]
1555   ""
1556   "call %l0%#"
1557   [(set_attr "type" "uncond_branch")])
1558
1559 (define_insn "get_pc_via_rdpc"
1560   [(set (match_operand:DI 0 "register_operand" "=r") (pc))]
1561   "TARGET_PTR64"
1562   "rd %%pc,%0"
1563   [(set_attr "type" "move")])
1564
1565 ;; Special pic pattern, for loading the address of a label into a register.
1566 ;; It clobbers o7 because the call puts the return address (i.e. pc value)
1567 ;; there.  The pic tablejump pattern also uses this.
1568
1569 (define_insn "move_pic_label_si"
1570   [(set (match_operand:SI 0 "register_operand" "=r")
1571         ; This was previously (label_ref:SI (match_operand 1 "" "")) but that
1572         ; loses the volatil and other flags of the original label_ref.
1573         (match_operand:SI 1 "label_ref_operand" ""))
1574    (set (reg:SI 15) (pc))]
1575   "flag_pic"
1576   "*
1577 {
1578   if (get_attr_length (insn) == 2)
1579     return \"\\n1:\;call 2f\;add %%o7,%%lo(%l1-1b),%0\\n2:\";
1580   else
1581     return \"\\n1:\;call 2f\;sethi %%hi(%l1-1b),%0\\n2:\\tor %0,%%lo(%l1-1b),%0\;add %0,%%o7,%0\";
1582 }"
1583   [(set_attr "type" "multi")
1584    ; 960 = 4096 bytes / 4 bytes/insn - 64 (for not always perfect length calcs)
1585    (set (attr "length") (if_then_else (ltu (minus (match_dup 1) (pc))
1586                                            (const_int 960))
1587                                       (const_int 2)
1588                                       (const_int 4)))])
1589
1590 ;; Special sparc64 pattern for loading the address of a label into a register.
1591 ;; The pic and non-pic cases are the same since it's the most efficient way.
1592 ;;
1593 ;; ??? The non-pic case doesn't need to use %o7, we could use a scratch
1594 ;; instead.  But the pic case doesn't need to use %o7 either.  We handle them
1595 ;; both here so that when this is fixed, they can both be fixed together.
1596 ;; Don't forget that the pic jump table stuff uses %o7 (that will need to be
1597 ;; changed too).
1598
1599 (define_insn "move_label_di"
1600   [(set (match_operand:DI 0 "register_operand" "=r")
1601         ; This was previously (label_ref:DI (match_operand 1 "" "")) but that
1602         ; loses the volatil and other flags of the original label_ref.
1603         (match_operand:DI 1 "label_ref_operand" ""))
1604    (set (reg:DI 15) (pc))]
1605   "TARGET_ARCH64"
1606   "*
1607 {
1608   if (get_attr_length (insn) == 2)
1609     return \"\\n1:\;rd %%pc,%%o7\;add %%o7,%l1-1b,%0\";
1610   else
1611     return \"\\n1:\;rd %%pc,%%o7\;sethi %%hi(%l1-1b),%0\;add %0,%%lo(%l1-1b),%0\;sra %0,0,%0\;add %0,%%o7,%0\";
1612 }"
1613   [(set_attr "type" "multi")
1614    ; 960 = 4096 bytes / 4 bytes/insn - 64 (for not always perfect length calcs)
1615    (set (attr "length") (if_then_else (ltu (minus (match_dup 1) (pc))
1616                                            (const_int 960))
1617                                       (const_int 2)
1618                                       (const_int 5)))])
1619
1620 (define_insn "*lo_sum_di_sp32"
1621   [(set (match_operand:DI 0 "register_operand" "=r")
1622         (lo_sum:DI (match_operand:DI 1 "register_operand" "0")
1623                    (match_operand:DI 2 "immediate_operand" "in")))]
1624   "! TARGET_ARCH64"
1625   "*
1626 {
1627   /* Don't output a 64 bit constant, since we can't trust the assembler to
1628      handle it correctly.  */
1629   if (GET_CODE (operands[2]) == CONST_DOUBLE)
1630     operands[2] = GEN_INT (CONST_DOUBLE_LOW (operands[2]));
1631   else if (GET_CODE (operands[2]) == CONST_INT
1632            && HOST_BITS_PER_WIDE_INT > 32
1633            && INTVAL (operands[2]) > 0xffffffff)
1634     operands[2] = GEN_INT (INTVAL (operands[2]) & 0xffffffff);
1635
1636   return \"or %L1,%%lo(%a2),%L0\";
1637 }"
1638   ;; Need to set length for this arith insn because operand2
1639   ;; is not an "arith_operand".
1640   [(set_attr "length" "1")])
1641
1642 ;; ??? Optimizer does not handle "or %o1,%lo(0),%o1". How about add?
1643
1644 (define_insn "*lo_sum_di_sp64"
1645   [(set (match_operand:DI 0 "register_operand" "=r")
1646         (lo_sum:DI (match_operand:DI 1 "register_operand" "0")
1647                    (match_operand:DI 2 "immediate_operand" "in")))]
1648   "TARGET_ARCH64"
1649   "*
1650 {
1651   /* Don't output a 64 bit constant, since we can't trust the assembler to
1652      handle it correctly.  */
1653   if (GET_CODE (operands[2]) == CONST_DOUBLE)
1654     operands[2] = GEN_INT (CONST_DOUBLE_LOW (operands[2]));
1655   else if (GET_CODE (operands[2]) == CONST_INT
1656            && HOST_BITS_PER_WIDE_INT > 32
1657            && INTVAL (operands[2]) > 0xffffffff)
1658     operands[2] = GEN_INT (INTVAL (operands[2]) & 0xffffffff);
1659
1660   /* Note that we use add here.  This is important because Medium/Anywhere
1661      code model support depends on it.  */
1662   return \"add %1,%%lo(%a2),%0\";
1663 }"
1664   ;; Need to set length for this arith insn because operand2
1665   ;; is not an "arith_operand".
1666   [(set_attr "length" "1")])
1667
1668 (define_insn "*sethi_di_sp32"
1669   [(set (match_operand:DI 0 "register_operand" "=r")
1670         (high:DI (match_operand 1 "" "")))]
1671   "! TARGET_ARCH64 && check_pic (1)"
1672   "*
1673 {
1674   rtx op0 = operands[0];
1675   rtx op1 = operands[1];
1676
1677   if (GET_CODE (op1) == CONST_INT)
1678     {
1679       operands[0] = operand_subword (op0, 1, 0, DImode);
1680       output_asm_insn (\"sethi %%hi(%a1),%0\", operands);
1681
1682       operands[0] = operand_subword (op0, 0, 0, DImode);
1683       if (INTVAL (op1) < 0)
1684         return \"mov -1,%0\";
1685       else
1686         return \"mov 0,%0\";
1687     }
1688   else if (GET_CODE (op1) == CONST_DOUBLE)
1689     {
1690       operands[0] = operand_subword (op0, 1, 0, DImode);
1691       operands[1] = GEN_INT (CONST_DOUBLE_LOW (op1));
1692       output_asm_insn (\"sethi %%hi(%a1),%0\", operands);
1693
1694       operands[0] = operand_subword (op0, 0, 0, DImode);
1695       operands[1] = GEN_INT (CONST_DOUBLE_HIGH (op1));
1696       return singlemove_string (operands);
1697     }
1698   else
1699     abort ();
1700   return \"\";
1701 }"
1702   [(set_attr "type" "move")
1703    (set_attr "length" "2")])
1704
1705 ;;; ??? This pattern originally clobbered a scratch register.  However, this
1706 ;;; is invalid, the movdi pattern may not use a temp register because it
1707 ;;; may be called from reload to reload a DImode value.  In that case, we
1708 ;;; end up with a scratch register that never gets allocated.  To avoid this,
1709 ;;; we use global register 1 which is never otherwise used by gcc as a temp.
1710 ;;; The correct solution here might be to force DImode constants to memory,
1711 ;;; e.g. by using a toc like the romp and rs6000 ports do for addresses, reg
1712 ;;; 1 will then no longer need to be considered a fixed reg.
1713
1714 (define_expand "sethi_di_sp64"
1715   [(parallel
1716      [(set (match_operand:DI 0 "register_operand" "")
1717            (high:DI (match_operand 1 "general_operand" "")))
1718       (clobber (reg:DI 1))])]
1719   "TARGET_ARCH64"
1720   "")
1721
1722 (define_insn "*sethi_di_sp64_const"
1723   [(set (match_operand:DI 0 "register_operand" "=r")
1724         (high:DI (match_operand 1 "const_double_operand" "")))
1725    (clobber (reg:DI 1))]
1726   "TARGET_ARCH64 && check_pic (1)"
1727   "*
1728 {
1729 #if HOST_BITS_PER_WIDE_INT == 32
1730   rtx high, low;
1731   
1732   split_double (operands[1], &high, &low);
1733
1734   if (high == const0_rtx)
1735     {
1736       operands[1] = low;
1737       output_asm_insn (\"sethi %%hi(%a1),%0\", operands);
1738     }
1739   else
1740     {
1741       operands[1] = high;
1742       output_asm_insn (singlemove_string (operands), operands);
1743
1744       operands[1] = low;
1745       output_asm_insn (\"sllx %0,32,%0\", operands);
1746       if (low != const0_rtx)
1747         output_asm_insn (\"sethi %%hi(%a1),%%g1; or %0,%%g1,%0\", operands);
1748     }
1749 #else
1750   rtx op = operands[1];
1751
1752   if (! SPARC_SETHI_P (INTVAL(op)))
1753     {
1754       operands[1] = GEN_INT (INTVAL (op) >> 32);
1755       output_asm_insn (singlemove_string (operands), operands);
1756
1757       output_asm_insn (\"sllx %0,32,%0\", operands);
1758       if (INTVAL (op) & 0xffffffff)
1759         {
1760           operands[1] = GEN_INT (INTVAL (op) & 0xffffffff);
1761           output_asm_insn (\"sethi %%hi(%a1),%%g1; or %0,%%g1,%0\", operands);
1762         }
1763     }
1764   else
1765     {
1766       output_asm_insn (\"sethi %%hi(%a1),%0\", operands);
1767     }
1768 #endif
1769
1770   return \"\";
1771 }"
1772   [(set_attr "type" "move")
1773    (set_attr "length" "5")])
1774
1775 ;; Most of the required support for the various code models is here.
1776 ;; We can do this because sparcs need the high insn to load the address.  We
1777 ;; just need to get high to do the right thing for each code model.  Then each
1778 ;; uses the same "%X+%lo(...)" in the load/store insn.
1779
1780 ;; When TARGET_MEDLOW, assume that the upper 32 bits of symbol addresses are
1781 ;; always 0.
1782 ;; When TARGET_MEDANY, the text and data segments have a maximum size of 32
1783 ;; bits and may be located anywhere.  MEDANY_BASE_REG contains the start
1784 ;; address of the data segment, currently %g4.
1785 ;; When TARGET_FULLANY, symbolic addresses are 64 bits.
1786
1787 (define_insn "*sethi_di_medlow"
1788   [(set (match_operand:DI 0 "register_operand" "=r")
1789         (high:DI (match_operand 1 "" "")))
1790   ;; The clobber is here because emit_move_sequence assumes the worst case.
1791    (clobber (reg:DI 1))]
1792   "TARGET_MEDLOW && check_pic (1)"
1793   "sethi %%hi(%a1),%0"
1794   [(set_attr "type" "move")
1795    (set_attr "length" "1")])
1796
1797 (define_insn "*sethi_di_medium_pic"
1798   [(set (match_operand:DI 0 "register_operand" "=r")
1799         (high:DI (match_operand 1 "sp64_medium_pic_operand" "")))]
1800   "(TARGET_MEDLOW || TARGET_MEDANY) && check_pic (1)"
1801   "sethi %%hi(%a1),%0"
1802   [(set_attr "type" "move")
1803    (set_attr "length" "1")])
1804
1805 ;; WARNING: %0 gets %hi(%1)+%g4.
1806 ;;          You cannot OR in %lo(%1), it must be added in.
1807
1808 (define_insn "*sethi_di_medany_data"
1809   [(set (match_operand:DI 0 "register_operand" "=r")
1810         (high:DI (match_operand 1 "data_segment_operand" "")))
1811   ;; The clobber is here because emit_move_sequence assumes the worst case.
1812    (clobber (reg:DI 1))]
1813   "TARGET_MEDANY && check_pic (1)"
1814   "sethi %%hi(%a1),%0; add %0,%%g4,%0"
1815   [(set_attr "type" "move")
1816    (set_attr "length" "2")])
1817
1818 (define_insn "*sethi_di_medany_text"
1819   [(set (match_operand:DI 0 "register_operand" "=r")
1820         (high:DI (match_operand 1 "text_segment_operand" "")))
1821   ;; The clobber is here because emit_move_sequence assumes the worst case.
1822    (clobber (reg:DI 1))]
1823   "TARGET_MEDANY && check_pic (1)"
1824   "sethi %%uhi(%a1),%%g1; or %%g1,%%ulo(%a1),%%g1; sllx %%g1,32,%%g1; sethi %%hi(%a1),%0; or %0,%%g1,%0"
1825   [(set_attr "type" "move")
1826    (set_attr "length" "5")])
1827
1828 (define_insn "*sethi_di_fullany"
1829   [(set (match_operand:DI 0 "register_operand" "=r")
1830         (high:DI (match_operand 1 "" "")))
1831    (clobber (reg:DI 1))]
1832   "TARGET_FULLANY && check_pic (1)"
1833   "sethi %%uhi(%a1),%%g1; or %%g1,%%ulo(%a1),%%g1; sllx %%g1,32,%%g1; sethi %%hi(%a1),%0; or %0,%%g1,%0"
1834   [(set_attr "type" "move")
1835    (set_attr "length" "5")])
1836 \f
1837 ;; Move instructions
1838
1839 (define_expand "movqi"
1840   [(set (match_operand:QI 0 "general_operand" "")
1841         (match_operand:QI 1 "general_operand" ""))]
1842   ""
1843   "
1844 {
1845   if (emit_move_sequence (operands, QImode))
1846     DONE;
1847 }")
1848
1849 (define_insn "*movqi_insn"
1850   [(set (match_operand:QI 0 "reg_or_nonsymb_mem_operand" "=r,r,r,Q")
1851         (match_operand:QI 1 "move_operand" "rI,K,Q,rJ"))]
1852   "! TARGET_LIVE_G0
1853    && (register_operand (operands[0], QImode)
1854        || register_operand (operands[1], QImode)
1855        || operands[1] == const0_rtx)"
1856   "@
1857    mov %1,%0
1858    sethi %%hi(%a1),%0
1859    ldub %1,%0
1860    stb %r1,%0"
1861   [(set_attr "type" "move,move,load,store")
1862    (set_attr "length" "1")])
1863
1864 (define_insn "*movqi_insn_liveg0"
1865   [(set (match_operand:QI 0 "reg_or_nonsymb_mem_operand" "=r,r,r,r,r,Q")
1866         (match_operand:QI 1 "move_operand" "r,J,I,K,Q,r"))]
1867   "TARGET_LIVE_G0
1868    && (register_operand (operands[0], QImode)
1869        || register_operand (operands[1], QImode))"
1870   "@
1871    mov %1,%0
1872    and %0,0,%0
1873    and %0,0,%0\;or %0,%1,%0
1874    sethi %%hi(%a1),%0
1875    ldub %1,%0
1876    stb %1,%0"
1877   [(set_attr "type" "move,move,move,move,load,store")
1878    (set_attr "length" "1,1,2,1,1,1")])
1879
1880 (define_insn "*lo_sum_qi"
1881   [(set (match_operand:QI 0 "register_operand" "=r")
1882         (subreg:QI (lo_sum:SI (match_operand:QI 1 "register_operand" "r")
1883                               (match_operand 2 "immediate_operand" "in")) 0))]
1884   ""
1885   "or %1,%%lo(%a2),%0"
1886   [(set_attr "length" "1")])
1887
1888 (define_insn "*store_qi"
1889   [(set (mem:QI (match_operand:SI 0 "symbolic_operand" ""))
1890         (match_operand:QI 1 "reg_or_0_operand" "rJ"))
1891    (clobber (match_scratch:SI 2 "=&r"))]
1892   "(reload_completed || reload_in_progress)
1893    && ! TARGET_PTR64"
1894   "sethi %%hi(%a0),%2\;stb %r1,[%2+%%lo(%a0)]"
1895   [(set_attr "type" "store")
1896    (set_attr "length" "2")])
1897
1898 (define_expand "movhi"
1899   [(set (match_operand:HI 0 "general_operand" "")
1900         (match_operand:HI 1 "general_operand" ""))]
1901   ""
1902   "
1903 {
1904   if (emit_move_sequence (operands, HImode))
1905     DONE;
1906 }")
1907
1908 (define_insn "*movhi_insn"
1909   [(set (match_operand:HI 0 "reg_or_nonsymb_mem_operand" "=r,r,r,Q")
1910         (match_operand:HI 1 "move_operand" "rI,K,Q,rJ"))]
1911   "! TARGET_LIVE_G0
1912    && (register_operand (operands[0], HImode)
1913        || register_operand (operands[1], HImode)
1914        || operands[1] == const0_rtx)"
1915   "@
1916    mov %1,%0
1917    sethi %%hi(%a1),%0
1918    lduh %1,%0
1919    sth %r1,%0"
1920   [(set_attr "type" "move,move,load,store")
1921    (set_attr "length" "1")])
1922
1923 (define_insn "*movhi_insn_liveg0"
1924   [(set (match_operand:HI 0 "reg_or_nonsymb_mem_operand" "=r,r,r,r,r,Q")
1925         (match_operand:HI 1 "move_operand" "r,J,I,K,Q,r"))]
1926   "TARGET_LIVE_G0
1927    && (register_operand (operands[0], HImode)
1928        || register_operand (operands[1], HImode))"
1929   "@
1930    mov %1,%0
1931    and %0,0,%0
1932    and %0,0,%0\;or %0,%1,%0
1933    sethi %%hi(%a1),%0
1934    lduh %1,%0
1935    sth %1,%0"
1936   [(set_attr "type" "move,move,move,move,load,store")
1937    (set_attr "length" "1,1,2,1,1,1")])
1938
1939 (define_insn "*lo_sum_hi"
1940   [(set (match_operand:HI 0 "register_operand" "=r")
1941         (lo_sum:HI (match_operand:HI 1 "register_operand" "r")
1942                    (match_operand 2 "immediate_operand" "in")))]
1943   ""
1944   "or %1,%%lo(%a2),%0"
1945   [(set_attr "length" "1")])
1946
1947 (define_insn "*store_hi"
1948   [(set (mem:HI (match_operand:SI 0 "symbolic_operand" ""))
1949         (match_operand:HI 1 "reg_or_0_operand" "rJ"))
1950    (clobber (match_scratch:SI 2 "=&r"))]
1951   "(reload_completed || reload_in_progress)
1952    && ! TARGET_PTR64"
1953   "sethi %%hi(%a0),%2\;sth %r1,[%2+%%lo(%a0)]"
1954   [(set_attr "type" "store")
1955    (set_attr "length" "2")])
1956
1957 (define_expand "movsi"
1958   [(set (match_operand:SI 0 "general_operand" "")
1959         (match_operand:SI 1 "general_operand" ""))]
1960   ""
1961   "
1962 {
1963   if (emit_move_sequence (operands, SImode))
1964     DONE;
1965 }")
1966
1967 ;; We must support both 'r' and 'f' registers here, because combine may
1968 ;; convert SFmode hard registers to SImode hard registers when simplifying
1969 ;; subreg sets.
1970
1971 ;; We cannot combine the similar 'r' and 'f' constraints, because it causes
1972 ;; problems with register allocation.  Reload might try to put an integer
1973 ;; in an fp register, or an fp number is an integer register.
1974
1975 (define_insn "*movsi_insn"
1976   [(set (match_operand:SI 0 "reg_or_nonsymb_mem_operand" "=r,f,r,r,f,Q,Q")
1977         (match_operand:SI 1 "move_operand" "rI,!f,K,Q,!Q,rJ,!f"))]
1978   "! TARGET_LIVE_G0
1979    && (register_operand (operands[0], SImode)
1980        || register_operand (operands[1], SImode)
1981        || operands[1] == const0_rtx)"
1982   "@
1983    mov %1,%0
1984    fmovs %1,%0
1985    sethi %%hi(%a1),%0
1986    ld %1,%0
1987    ld %1,%0
1988    st %r1,%0
1989    st %1,%0"
1990   [(set_attr "type" "move,fp,move,load,fpload,store,fpstore")
1991    (set_attr "length" "1")])
1992
1993 (define_insn "*movsi_insn_liveg0"
1994   [(set (match_operand:SI 0 "reg_or_nonsymb_mem_operand" "=r,r,r,f,r,r,f,Q,Q")
1995         (match_operand:SI 1 "move_operand" "r,J,I,!f,K,Q,!Q,r,!f"))]
1996   "TARGET_LIVE_G0
1997    && (register_operand (operands[0], SImode)
1998        || register_operand (operands[1], SImode))"
1999   "@
2000    mov %1,%0
2001    and %0,0,%0
2002    and %0,0,%0\;or %0,%1,%0
2003    fmovs %1,%0
2004    sethi %%hi(%a1),%0
2005    ld %1,%0
2006    ld %1,%0
2007    st %1,%0
2008    st %1,%0"
2009   [(set_attr "type" "move,move,move,fp,move,load,fpload,store,fpstore")
2010    (set_attr "length" "1,1,2,1,1,1,1,1,1")])
2011
2012 (define_insn "*store_si"
2013   [(set (mem:SI (match_operand:SI 0 "symbolic_operand" ""))
2014         (match_operand:SI 1 "reg_or_0_operand" "rJ"))
2015    (clobber (match_scratch:SI 2 "=&r"))]
2016   "(reload_completed || reload_in_progress)
2017    && ! TARGET_PTR64"
2018   "sethi %%hi(%a0),%2\;st %r1,[%2+%%lo(%a0)]"
2019   [(set_attr "type" "store")
2020    (set_attr "length" "2")])
2021
2022 (define_expand "movdi"
2023   [(set (match_operand:DI 0 "reg_or_nonsymb_mem_operand" "")
2024         (match_operand:DI 1 "general_operand" ""))]
2025   ""
2026   "
2027 {
2028   if (emit_move_sequence (operands, DImode))
2029     DONE;
2030 }")
2031
2032 (define_insn "*movdi_sp32_insn"
2033   [(set (match_operand:DI 0 "reg_or_nonsymb_mem_operand" "=r,T,U,Q,r,r,?f,?f,?Q")
2034         (match_operand:DI 1 "general_operand" "r,U,T,r,Q,i,f,Q,f"))]
2035   "! TARGET_ARCH64
2036    && (register_operand (operands[0], DImode)
2037        || register_operand (operands[1], DImode)
2038        || operands[1] == const0_rtx)"
2039   "*
2040 {
2041   if (FP_REG_P (operands[0]) || FP_REG_P (operands[1]))
2042     return output_fp_move_double (operands);
2043   return output_move_double (operands);
2044 }"
2045   [(set_attr "type" "move,store,load,store,load,multi,fp,fpload,fpstore")
2046    (set_attr "length" "2,1,1,3,3,3,2,3,3")])
2047
2048 ;;; ??? The trick used below can be extended to load any negative 32 bit
2049 ;;; constant in two instructions.  Currently the compiler will use HIGH/LO_SUM
2050 ;;; for anything not matching the HIK constraints, which results in 5
2051 ;;; instructions.  Positive 32 bit constants can be loaded in the obvious way
2052 ;;; with sethi/ori.  To extend the trick, in the xor instruction, use 
2053 ;;; xor %o0, ((op1 & 0x3ff) | -0x400), %o0
2054 ;;; This needs the original value of operands[1], not the inverted value.
2055
2056 (define_insn "*movdi_sp64_insn"
2057   [(set (match_operand:DI 0 "reg_or_nonsymb_mem_operand" "=r,r,r,Q,?f,?f,?Q")
2058         (match_operand:DI 1 "move_operand" "rI,K,Q,rJ,f,Q,f"))]
2059   "TARGET_ARCH64
2060    && (register_operand (operands[0], DImode)
2061        || register_operand (operands[1], DImode)
2062        || operands[1] == const0_rtx)"
2063   "*
2064 {
2065   switch (which_alternative)
2066     {
2067     case 0:
2068       return \"mov %1,%0\";
2069     case 1:
2070       /* Sethi does not sign extend, so we must use a little trickery
2071          to use it for negative numbers.  Invert the constant before
2072          loading it in, then use a xor immediate to invert the loaded bits
2073          (along with the upper 32 bits) to the desired constant.  This
2074          works because the sethi and immediate fields overlap.  */
2075
2076       if ((INTVAL (operands[1]) & 0x80000000) == 0)
2077         return \"sethi %%hi(%a1),%0\";
2078       else
2079         {
2080           operands[1] = GEN_INT (~INTVAL (operands[1]));
2081           output_asm_insn (\"sethi %%hi(%a1),%0\", operands);
2082           /* The low 10 bits are already zero, but invert the rest.
2083              Assemblers don't accept 0x1c00, so use -0x400 instead.  */
2084           return \"xor %0,-0x400,%0\";
2085         }
2086     case 2:
2087       return \"ldx %1,%0\";
2088     case 3:
2089       return \"stx %r1,%0\";
2090     case 4:
2091       return \"mov %1,%0\";
2092     case 5:
2093       return \"ldd %1,%0\";
2094     case 6:
2095       return \"std %1,%0\";
2096     }
2097 }"
2098   [(set_attr "type" "move,move,load,store,fp,fpload,fpstore")
2099    (set_attr "length" "1,2,1,1,1,1,1")])
2100
2101 ;; ??? There's no symbolic (set (mem:DI ...) ...).
2102 ;; Experimentation with v9 suggested one isn't needed.
2103 \f
2104 ;; Block move insns.
2105
2106 ;; ??? We get better code without it.  See output_block_move in sparc.c.
2107
2108 ;; The definition of this insn does not really explain what it does,
2109 ;; but it should suffice
2110 ;; that anything generated as this insn will be recognized as one
2111 ;; and that it will not successfully combine with anything.
2112 ;(define_expand "movstrsi"
2113 ;  [(parallel [(set (mem:BLK (match_operand:BLK 0 "general_operand" ""))
2114 ;                  (mem:BLK (match_operand:BLK 1 "general_operand" "")))
2115 ;             (use (match_operand:SI 2 "nonmemory_operand" ""))
2116 ;             (use (match_operand:SI 3 "immediate_operand" ""))
2117 ;             (clobber (match_dup 0))
2118 ;             (clobber (match_dup 1))
2119 ;             (clobber (match_scratch:SI 4 ""))
2120 ;             (clobber (reg:SI 100))
2121 ;             (clobber (reg:SI 1))])]
2122 ;  ""
2123 ;  "
2124 ;{
2125 ;  /* If the size isn't known, don't emit inline code.  output_block_move
2126 ;     would output code that's much slower than the library function.
2127 ;     Also don't output code for large blocks.  */
2128 ;  if (GET_CODE (operands[2]) != CONST_INT
2129 ;      || GET_CODE (operands[3]) != CONST_INT
2130 ;      || INTVAL (operands[2]) / INTVAL (operands[3]) > 16)
2131 ;    FAIL;
2132 ;
2133 ;  operands[0] = copy_to_mode_reg (Pmode, XEXP (operands[0], 0));
2134 ;  operands[1] = copy_to_mode_reg (Pmode, XEXP (operands[1], 0));
2135 ;  operands[2] = force_not_mem (operands[2]);
2136 ;}")
2137
2138 ;(define_insn "*block_move_insn"
2139 ;  [(set (mem:BLK (match_operand:SI 0 "register_operand" "+r"))
2140 ;       (mem:BLK (match_operand:SI 1 "register_operand" "+r")))
2141 ;   (use (match_operand:SI 2 "nonmemory_operand" "rn"))
2142 ;   (use (match_operand:SI 3 "immediate_operand" "i"))
2143 ;   (clobber (match_dup 0))
2144 ;   (clobber (match_dup 1))
2145 ;   (clobber (match_scratch:SI 4 "=&r"))
2146 ;   (clobber (reg:SI 100))
2147 ;   (clobber (reg:SI 1))]
2148 ;  ""
2149 ;  "* return output_block_move (operands);"
2150 ;  [(set_attr "type" "multi")
2151 ;   (set_attr "length" "6")])
2152 \f
2153 ;; Floating point move insns
2154
2155 ;; This pattern forces (set (reg:SF ...) (const_double ...))
2156 ;; to be reloaded by putting the constant into memory.
2157 ;; It must come before the more general movsf pattern.
2158 (define_insn "*movsf_const_insn"
2159   [(set (match_operand:SF 0 "general_operand" "=?r,f,m")
2160         (match_operand:SF 1 "" "?F,m,G"))]
2161   "TARGET_FPU && GET_CODE (operands[1]) == CONST_DOUBLE"
2162   "*
2163 {
2164   switch (which_alternative)
2165     {
2166     case 0:
2167       return singlemove_string (operands);
2168     case 1:
2169       return \"ld %1,%0\";
2170     case 2:
2171       return \"st %%g0,%0\";
2172     }
2173 }"
2174   [(set_attr "type" "load,fpload,store")
2175    (set_attr "length" "2,1,1")])
2176
2177 (define_expand "movsf"
2178   [(set (match_operand:SF 0 "general_operand" "")
2179         (match_operand:SF 1 "general_operand" ""))]
2180   ""
2181   "
2182 {
2183   if (emit_move_sequence (operands, SFmode))
2184     DONE;
2185 }")
2186
2187 (define_insn "*movsf_insn"
2188   [(set (match_operand:SF 0 "reg_or_nonsymb_mem_operand" "=f,r,f,r,Q,Q")
2189         (match_operand:SF 1 "reg_or_nonsymb_mem_operand" "f,r,Q,Q,f,r"))]
2190   "TARGET_FPU
2191    && (register_operand (operands[0], SFmode)
2192        || register_operand (operands[1], SFmode))"
2193   "@
2194    fmovs %1,%0
2195    mov %1,%0
2196    ld %1,%0
2197    ld %1,%0
2198    st %1,%0
2199    st %1,%0"
2200   [(set_attr "type" "fp,move,fpload,load,fpstore,store")])
2201
2202 ;; Exactly the same as above, except that all `f' cases are deleted.
2203 ;; This is necessary to prevent reload from ever trying to use a `f' reg
2204 ;; when -mno-fpu.
2205
2206 (define_insn "*movsf_no_f_insn"
2207   [(set (match_operand:SF 0 "reg_or_nonsymb_mem_operand" "=r,r,Q")
2208         (match_operand:SF 1 "reg_or_nonsymb_mem_operand" "r,Q,r"))]
2209   "! TARGET_FPU
2210    && (register_operand (operands[0], SFmode)
2211        || register_operand (operands[1], SFmode))"
2212   "@
2213    mov %1,%0
2214    ld %1,%0
2215    st %1,%0"
2216   [(set_attr "type" "move,load,store")])
2217
2218 (define_insn "*store_sf"
2219   [(set (mem:SF (match_operand:SI 0 "symbolic_operand" "i"))
2220         (match_operand:SF 1 "reg_or_0_operand" "rfG"))
2221    (clobber (match_scratch:SI 2 "=&r"))]
2222   "(reload_completed || reload_in_progress)
2223    && ! TARGET_PTR64"
2224   "sethi %%hi(%a0),%2\;st %r1,[%2+%%lo(%a0)]"
2225   [(set_attr "type" "store")
2226    (set_attr "length" "2")])
2227
2228 ;; This pattern forces (set (reg:DF ...) (const_double ...))
2229 ;; to be reloaded by putting the constant into memory.
2230 ;; It must come before the more general movdf pattern.
2231
2232 (define_insn "*movdf_const_insn"
2233   [(set (match_operand:DF 0 "general_operand" "=?r,e,o")
2234         (match_operand:DF 1 "" "?F,m,G"))]
2235   "TARGET_FPU && GET_CODE (operands[1]) == CONST_DOUBLE"
2236   "*
2237 {
2238   switch (which_alternative)
2239     {
2240     case 0:
2241       return output_move_double (operands);
2242     case 1:
2243       return output_fp_move_double (operands);
2244     case 2:
2245       if (TARGET_ARCH64)
2246         {
2247           return \"stx %%g0,%0\";
2248         }
2249       else
2250         {
2251           operands[1] = adj_offsettable_operand (operands[0], 4);
2252           return \"st %%g0,%0\;st %%g0,%1\";
2253         }
2254     }
2255 }"
2256   [(set_attr "type" "load,fpload,store")
2257    (set_attr "length" "3,3,3")])
2258
2259 (define_expand "movdf"
2260   [(set (match_operand:DF 0 "general_operand" "")
2261         (match_operand:DF 1 "general_operand" ""))]
2262   ""
2263   "
2264 {
2265   if (emit_move_sequence (operands, DFmode))
2266     DONE;
2267 }")
2268
2269 (define_insn "*movdf_insn"
2270   [(set (match_operand:DF 0 "reg_or_nonsymb_mem_operand" "=T,U,e,r,Q,Q,e,r")
2271         (match_operand:DF 1 "reg_or_nonsymb_mem_operand" "U,T,e,r,e,r,Q,Q"))]
2272   "TARGET_FPU
2273    && (register_operand (operands[0], DFmode)
2274        || register_operand (operands[1], DFmode))"
2275   "*
2276 {
2277   if (FP_REG_P (operands[0]) || FP_REG_P (operands[1]))
2278     return output_fp_move_double (operands);
2279   return output_move_double (operands);
2280 }"
2281   [(set_attr "type" "fpstore,fpload,fp,move,fpstore,store,fpload,load")
2282    (set_attr "length" "1,1,2,2,3,3,3,3")])
2283
2284 ;; Exactly the same as above, except that all `e' cases are deleted.
2285 ;; This is necessary to prevent reload from ever trying to use a `e' reg
2286 ;; when -mno-fpu.
2287
2288 (define_insn "*movdf_no_e_insn"
2289   [(set (match_operand:DF 0 "reg_or_nonsymb_mem_operand" "=T,U,r,Q,&r")
2290         (match_operand:DF 1 "reg_or_nonsymb_mem_operand" "U,T,r,r,Q"))]
2291   "! TARGET_FPU
2292    && (register_operand (operands[0], DFmode)
2293        || register_operand (operands[1], DFmode))"
2294   "* return output_move_double (operands);"
2295   [(set_attr "type" "store,load,move,store,load")
2296    (set_attr "length" "1,1,2,3,3")])
2297
2298 ;; Must handle overlapping registers here, since parameters can be unaligned
2299 ;; in registers.
2300
2301 (define_split
2302   [(set (match_operand:DF 0 "register_operand" "")
2303         (match_operand:DF 1 "register_operand" ""))]
2304   "! TARGET_ARCH64 && reload_completed
2305    && REGNO (operands[0]) < SPARC_FIRST_V9_FP_REG
2306    && REGNO (operands[1]) < SPARC_FIRST_V9_FP_REG"
2307   [(set (match_dup 2) (match_dup 3))
2308    (set (match_dup 4) (match_dup 5))]
2309   "
2310 {
2311   rtx first_set = operand_subword (operands[0], 0, 0, DFmode);
2312   rtx second_use = operand_subword (operands[1], 1, 0, DFmode);
2313
2314   if (REGNO (first_set) == REGNO (second_use))
2315     {
2316       operands[2] = operand_subword (operands[0], 1, 0, DFmode);
2317       operands[3] = second_use;
2318       operands[4] = first_set;
2319       operands[5] = operand_subword (operands[1], 0, 0, DFmode);
2320     }
2321   else
2322     {
2323       operands[2] = first_set;
2324       operands[3] = operand_subword (operands[1], 0, 0, DFmode);
2325       operands[4] = operand_subword (operands[0], 1, 0, DFmode);
2326       operands[5] = second_use;
2327     }
2328 }")
2329
2330 (define_insn "*store_df"
2331   [(set (mem:DF (match_operand:SI 0 "symbolic_operand" "i,i"))
2332         (match_operand:DF 1 "reg_or_0_operand" "re,G"))
2333    (clobber (match_scratch:SI 2 "=&r,&r"))]
2334   "(reload_completed || reload_in_progress)
2335    && ! TARGET_PTR64"
2336   "*
2337 {
2338   output_asm_insn (\"sethi %%hi(%a0),%2\", operands);
2339   if (which_alternative == 0)
2340     return \"std %1,[%2+%%lo(%a0)]\";
2341   else
2342     return \"st %%g0,[%2+%%lo(%a0)]\;st %%g0,[%2+%%lo(%a0+4)]\";
2343 }"
2344   [(set_attr "type" "store")
2345    (set_attr "length" "3")])
2346
2347 ;; This pattern forces (set (reg:TF ...) (const_double ...))
2348 ;; to be reloaded by putting the constant into memory.
2349 ;; It must come before the more general movtf pattern.
2350 (define_insn "*movtf_const_insn"
2351   [(set (match_operand:TF 0 "general_operand" "=?r,e,o")
2352         (match_operand:TF 1 "" "?F,m,G"))]
2353   "TARGET_FPU && GET_CODE (operands[1]) == CONST_DOUBLE"
2354   "*
2355 {
2356   switch (which_alternative)
2357     {
2358     case 0:
2359       return output_move_quad (operands);
2360     case 1:
2361       return output_fp_move_quad (operands);
2362     case 2:
2363       if (TARGET_ARCH64)
2364         {
2365           operands[1] = adj_offsettable_operand (operands[0], 8);
2366           return \"stx %%g0,%0\;stx %%g0,%1\";
2367         }
2368       else
2369         {
2370           /* ??? Do we run off the end of the array here? */
2371           operands[1] = adj_offsettable_operand (operands[0], 4);
2372           operands[2] = adj_offsettable_operand (operands[0], 8);
2373           operands[3] = adj_offsettable_operand (operands[0], 12);
2374           return \"st %%g0,%0\;st %%g0,%1\;st %%g0,%2\;st %%g0,%3\";
2375         }
2376     }
2377 }"
2378   [(set_attr "type" "load,fpload,store")
2379    (set_attr "length" "5,5,5")])
2380
2381 (define_expand "movtf"
2382   [(set (match_operand:TF 0 "general_operand" "")
2383         (match_operand:TF 1 "general_operand" ""))]
2384   ""
2385   "
2386 {
2387   if (emit_move_sequence (operands, TFmode))
2388     DONE;
2389 }")
2390
2391 (define_insn "*movtf_insn"
2392   [(set (match_operand:TF 0 "reg_or_nonsymb_mem_operand" "=e,r,Q,Q,e,&r")
2393         (match_operand:TF 1 "reg_or_nonsymb_mem_operand" "e,r,e,r,Q,Q"))]
2394   "TARGET_FPU
2395    && (register_operand (operands[0], TFmode)
2396        || register_operand (operands[1], TFmode))"
2397   "*
2398 {
2399   if (FP_REG_P (operands[0]) || FP_REG_P (operands[1]))
2400     return output_fp_move_quad (operands);
2401   return output_move_quad (operands);
2402 }"
2403   [(set_attr "type" "fp,move,fpstore,store,fpload,load")
2404    (set_attr "length" "4,4,5,5,5,5")])
2405
2406 ;; Exactly the same as above, except that all `e' cases are deleted.
2407 ;; This is necessary to prevent reload from ever trying to use a `e' reg
2408 ;; when -mno-fpu.
2409
2410 (define_insn "*movtf_no_e_insn"
2411   [(set (match_operand:TF 0 "reg_or_nonsymb_mem_operand" "=r,Q,&r")
2412         (match_operand:TF 1 "reg_or_nonsymb_mem_operand" "r,r,Q"))]
2413   "! TARGET_FPU
2414    && (register_operand (operands[0], TFmode)
2415        || register_operand (operands[1], TFmode))"
2416   "*
2417 {
2418   if (FP_REG_P (operands[0]) || FP_REG_P (operands[1]))
2419     return output_fp_move_quad (operands);
2420   return output_move_quad (operands);
2421 }"
2422   [(set_attr "type" "move,store,load")
2423    (set_attr "length" "4,5,5")])
2424
2425 ;; This is disabled because it does not work.  Long doubles have only 8
2426 ;; byte alignment.  Adding an offset of 8 or 12 to an 8 byte aligned %lo may 
2427 ;; cause it to overflow.  See also GO_IF_LEGITIMATE_ADDRESS.
2428 (define_insn "*store_tf"
2429   [(set (mem:TF (match_operand:SI 0 "symbolic_operand" "i,i"))
2430         (match_operand:TF 1 "reg_or_0_operand" "re,G"))
2431    (clobber (match_scratch:SI 2 "=&r,&r"))]
2432   "0 && (reload_completed || reload_in_progress)
2433    && ! TARGET_PTR64"
2434   "*
2435 {
2436   output_asm_insn (\"sethi %%hi(%a0),%2\", operands);
2437   if (which_alternative == 0)
2438     return \"std %1,[%2+%%lo(%a0)]\;std %S1,[%2+%%lo(%a0+8)]\";
2439   else
2440     return \"st %%g0,[%2+%%lo(%a0)]\;st %%g0,[%2+%%lo(%a0+4)]\; st %%g0,[%2+%%lo(%a0+8)]\;st %%g0,[%2+%%lo(%a0+12)]\";
2441 }"
2442   [(set_attr "type" "store")
2443    (set_attr "length" "5")])
2444 \f
2445 ;; Sparc V9 conditional move instructions.
2446
2447 ;; We can handle larger constants here for some flavors, but for now we keep
2448 ;; it simple and only allow those constants supported by all flavours.
2449 ;; Note that emit_conditional_move canonicalizes operands 2,3 so that operand
2450 ;; 3 contains the constant if one is present, but we handle either for
2451 ;; generality (sparc.c puts a constant in operand 2).
2452
2453 (define_expand "movqicc"
2454   [(set (match_operand:QI 0 "register_operand" "")
2455         (if_then_else:QI (match_operand 1 "comparison_operator" "")
2456                          (match_operand:QI 2 "arith10_operand" "")
2457                          (match_operand:QI 3 "arith10_operand" "")))]
2458   "TARGET_V9"
2459   "
2460 {
2461   enum rtx_code code = GET_CODE (operands[1]);
2462
2463   if (GET_MODE (sparc_compare_op0) == DImode
2464       && ! TARGET_ARCH64)
2465     FAIL;
2466
2467   if (sparc_compare_op1 == const0_rtx
2468       && GET_CODE (sparc_compare_op0) == REG
2469       && GET_MODE (sparc_compare_op0) == DImode
2470       && v9_regcmp_p (code))
2471     {
2472       operands[1] = gen_rtx (code, DImode,
2473                              sparc_compare_op0, sparc_compare_op1);
2474     }
2475   else
2476     {
2477       rtx cc_reg = gen_compare_reg (code,
2478                                     sparc_compare_op0, sparc_compare_op1);
2479       operands[1] = gen_rtx (code, GET_MODE (cc_reg), cc_reg, const0_rtx);
2480     }
2481 }")
2482
2483 (define_expand "movhicc"
2484   [(set (match_operand:HI 0 "register_operand" "")
2485         (if_then_else:HI (match_operand 1 "comparison_operator" "")
2486                          (match_operand:HI 2 "arith10_operand" "")
2487                          (match_operand:HI 3 "arith10_operand" "")))]
2488   "TARGET_V9"
2489   "
2490 {
2491   enum rtx_code code = GET_CODE (operands[1]);
2492
2493   if (GET_MODE (sparc_compare_op0) == DImode
2494       && ! TARGET_ARCH64)
2495     FAIL;
2496
2497   if (sparc_compare_op1 == const0_rtx
2498       && GET_CODE (sparc_compare_op0) == REG
2499       && GET_MODE (sparc_compare_op0) == DImode
2500       && v9_regcmp_p (code))
2501     {
2502       operands[1] = gen_rtx (code, DImode,
2503                              sparc_compare_op0, sparc_compare_op1);
2504     }
2505   else
2506     {
2507       rtx cc_reg = gen_compare_reg (code,
2508                                     sparc_compare_op0, sparc_compare_op1);
2509       operands[1] = gen_rtx (code, GET_MODE (cc_reg), cc_reg, const0_rtx);
2510     }
2511 }")
2512
2513 (define_expand "movsicc"
2514   [(set (match_operand:SI 0 "register_operand" "")
2515         (if_then_else:SI (match_operand 1 "comparison_operator" "")
2516                          (match_operand:SI 2 "arith10_operand" "")
2517                          (match_operand:SI 3 "arith10_operand" "")))]
2518   "TARGET_V9"
2519   "
2520 {
2521   enum rtx_code code = GET_CODE (operands[1]);
2522
2523   if (GET_MODE (sparc_compare_op0) == DImode
2524       && ! TARGET_ARCH64)
2525     FAIL;
2526
2527   if (sparc_compare_op1 == const0_rtx
2528       && GET_CODE (sparc_compare_op0) == REG
2529       && GET_MODE (sparc_compare_op0) == DImode
2530       && v9_regcmp_p (code))
2531     {
2532       operands[1] = gen_rtx (code, DImode,
2533                              sparc_compare_op0, sparc_compare_op1);
2534     }
2535   else
2536     {
2537       rtx cc_reg = gen_compare_reg (code,
2538                                     sparc_compare_op0, sparc_compare_op1);
2539       operands[1] = gen_rtx (code, GET_MODE (cc_reg), cc_reg, const0_rtx);
2540     }
2541 }")
2542
2543 (define_expand "movdicc"
2544   [(set (match_operand:DI 0 "register_operand" "")
2545         (if_then_else:DI (match_operand 1 "comparison_operator" "")
2546                          (match_operand:DI 2 "arith10_double_operand" "")
2547                          (match_operand:DI 3 "arith10_double_operand" "")))]
2548   "TARGET_ARCH64"
2549   "
2550 {
2551   enum rtx_code code = GET_CODE (operands[1]);
2552
2553   if (sparc_compare_op1 == const0_rtx
2554       && GET_CODE (sparc_compare_op0) == REG
2555       && GET_MODE (sparc_compare_op0) == DImode
2556       && v9_regcmp_p (code))
2557     {
2558       operands[1] = gen_rtx (code, DImode,
2559                              sparc_compare_op0, sparc_compare_op1);
2560     }
2561   else
2562     {
2563       rtx cc_reg = gen_compare_reg (code,
2564                                     sparc_compare_op0, sparc_compare_op1);
2565       operands[1] = gen_rtx (code, GET_MODE (cc_reg), cc_reg, const0_rtx);
2566     }
2567 }")
2568
2569 (define_expand "movsfcc"
2570   [(set (match_operand:SF 0 "register_operand" "")
2571         (if_then_else:SF (match_operand 1 "comparison_operator" "")
2572                          (match_operand:SF 2 "register_operand" "")
2573                          (match_operand:SF 3 "register_operand" "")))]
2574   "TARGET_V9 && TARGET_FPU"
2575   "
2576 {
2577   enum rtx_code code = GET_CODE (operands[1]);
2578
2579   if (GET_MODE (sparc_compare_op0) == DImode
2580       && ! TARGET_ARCH64)
2581     FAIL;
2582
2583   if (sparc_compare_op1 == const0_rtx
2584       && GET_CODE (sparc_compare_op0) == REG
2585       && GET_MODE (sparc_compare_op0) == DImode
2586       && v9_regcmp_p (code))
2587     {
2588       operands[1] = gen_rtx (code, DImode,
2589                              sparc_compare_op0, sparc_compare_op1);
2590     }
2591   else
2592     {
2593       rtx cc_reg = gen_compare_reg (code,
2594                                     sparc_compare_op0, sparc_compare_op1);
2595       operands[1] = gen_rtx (code, GET_MODE (cc_reg), cc_reg, const0_rtx);
2596     }
2597 }")
2598
2599 (define_expand "movdfcc"
2600   [(set (match_operand:DF 0 "register_operand" "")
2601         (if_then_else:DF (match_operand 1 "comparison_operator" "")
2602                          (match_operand:DF 2 "register_operand" "")
2603                          (match_operand:DF 3 "register_operand" "")))]
2604   "TARGET_V9 && TARGET_FPU"
2605   "
2606 {
2607   enum rtx_code code = GET_CODE (operands[1]);
2608
2609   if (GET_MODE (sparc_compare_op0) == DImode
2610       && ! TARGET_ARCH64)
2611     FAIL;
2612
2613   if (sparc_compare_op1 == const0_rtx
2614       && GET_CODE (sparc_compare_op0) == REG
2615       && GET_MODE (sparc_compare_op0) == DImode
2616       && v9_regcmp_p (code))
2617     {
2618       operands[1] = gen_rtx (code, DImode,
2619                              sparc_compare_op0, sparc_compare_op1);
2620     }
2621   else
2622     {
2623       rtx cc_reg = gen_compare_reg (code,
2624                                     sparc_compare_op0, sparc_compare_op1);
2625       operands[1] = gen_rtx (code, GET_MODE (cc_reg), cc_reg, const0_rtx);
2626     }
2627 }")
2628
2629 (define_expand "movtfcc"
2630   [(set (match_operand:TF 0 "register_operand" "")
2631         (if_then_else:TF (match_operand 1 "comparison_operator" "")
2632                          (match_operand:TF 2 "register_operand" "")
2633                          (match_operand:TF 3 "register_operand" "")))]
2634   "TARGET_V9 && TARGET_FPU"
2635   "
2636 {
2637   enum rtx_code code = GET_CODE (operands[1]);
2638
2639   if (GET_MODE (sparc_compare_op0) == DImode
2640       && ! TARGET_ARCH64)
2641     FAIL;
2642
2643   if (sparc_compare_op1 == const0_rtx
2644       && GET_CODE (sparc_compare_op0) == REG
2645       && GET_MODE (sparc_compare_op0) == DImode
2646       && v9_regcmp_p (code))
2647     {
2648       operands[1] = gen_rtx (code, DImode,
2649                              sparc_compare_op0, sparc_compare_op1);
2650     }
2651   else
2652     {
2653       rtx cc_reg = gen_compare_reg (code,
2654                                     sparc_compare_op0, sparc_compare_op1);
2655       operands[1] = gen_rtx (code, GET_MODE (cc_reg), cc_reg, const0_rtx);
2656     }
2657 }")
2658
2659 ;; Conditional move define_insns.
2660
2661 (define_insn "*movqi_cc_sp64"
2662   [(set (match_operand:QI 0 "register_operand" "=r,r")
2663         (if_then_else:QI (match_operator 1 "comparison_operator"
2664                                 [(match_operand 2 "icc_or_fcc_reg_operand" "X,X")
2665                                  (const_int 0)])
2666                       (match_operand:QI 3 "arith11_operand" "rL,0")
2667                       (match_operand:QI 4 "arith11_operand" "0,rL")))]
2668   "TARGET_V9"
2669   "@
2670    mov%C1 %x2,%3,%0
2671    mov%c1 %x2,%4,%0"
2672   [(set_attr "type" "cmove")])
2673
2674 (define_insn "*movhi_cc_sp64"
2675   [(set (match_operand:HI 0 "register_operand" "=r,r")
2676         (if_then_else:HI (match_operator 1 "comparison_operator"
2677                                 [(match_operand 2 "icc_or_fcc_reg_operand" "X,X")
2678                                  (const_int 0)])
2679                       (match_operand:HI 3 "arith11_operand" "rL,0")
2680                       (match_operand:HI 4 "arith11_operand" "0,rL")))]
2681   "TARGET_V9"
2682   "@
2683    mov%C1 %x2,%3,%0
2684    mov%c1 %x2,%4,%0"
2685   [(set_attr "type" "cmove")])
2686
2687 (define_insn "*movsi_cc_sp64"
2688   [(set (match_operand:SI 0 "register_operand" "=r,r")
2689         (if_then_else:SI (match_operator 1 "comparison_operator"
2690                                 [(match_operand 2 "icc_or_fcc_reg_operand" "X,X")
2691                                  (const_int 0)])
2692                       (match_operand:SI 3 "arith11_operand" "rL,0")
2693                       (match_operand:SI 4 "arith11_operand" "0,rL")))]
2694   "TARGET_V9"
2695   "@
2696    mov%C1 %x2,%3,%0
2697    mov%c1 %x2,%4,%0"
2698   [(set_attr "type" "cmove")])
2699
2700 ;; ??? The constraints of operands 3,4 need work.
2701 (define_insn "*movdi_cc_sp64"
2702   [(set (match_operand:DI 0 "register_operand" "=r,r")
2703         (if_then_else:DI (match_operator 1 "comparison_operator"
2704                                 [(match_operand 2 "icc_or_fcc_reg_operand" "X,X")
2705                                  (const_int 0)])
2706                       (match_operand:DI 3 "arith11_double_operand" "rLH,0")
2707                       (match_operand:DI 4 "arith11_double_operand" "0,rLH")))]
2708   "TARGET_ARCH64"
2709   "@
2710    mov%C1 %x2,%3,%0
2711    mov%c1 %x2,%4,%0"
2712   [(set_attr "type" "cmove")])
2713
2714 (define_insn "*movsf_cc_sp64"
2715   [(set (match_operand:SF 0 "register_operand" "=f,f")
2716         (if_then_else:SF (match_operator 1 "comparison_operator"
2717                                 [(match_operand 2 "icc_or_fcc_reg_operand" "X,X")
2718                                  (const_int 0)])
2719                       (match_operand:SF 3 "register_operand" "f,0")
2720                       (match_operand:SF 4 "register_operand" "0,f")))]
2721   "TARGET_V9 && TARGET_FPU"
2722   "@
2723    fmovs%C1 %x2,%3,%0
2724    fmovs%c1 %x2,%4,%0"
2725   [(set_attr "type" "cmove")])
2726
2727 (define_insn "*movdf_cc_sp64"
2728   [(set (match_operand:DF 0 "register_operand" "=e,e")
2729         (if_then_else:DF (match_operator 1 "comparison_operator"
2730                                 [(match_operand 2 "icc_or_fcc_reg_operand" "X,X")
2731                                  (const_int 0)])
2732                       (match_operand:DF 3 "register_operand" "e,0")
2733                       (match_operand:DF 4 "register_operand" "0,e")))]
2734   "TARGET_V9 && TARGET_FPU"
2735   "@
2736    fmovd%C1 %x2,%3,%0
2737    fmovd%c1 %x2,%4,%0"
2738   [(set_attr "type" "cmove")])
2739
2740 (define_insn "*movtf_cc_sp64"
2741   [(set (match_operand:TF 0 "register_operand" "=e,e")
2742         (if_then_else:TF (match_operator 1 "comparison_operator"
2743                                 [(match_operand 2 "icc_or_fcc_reg_operand" "X,X")
2744                                  (const_int 0)])
2745                       (match_operand:TF 3 "register_operand" "e,0")
2746                       (match_operand:TF 4 "register_operand" "0,e")))]
2747   "TARGET_V9 && TARGET_FPU && TARGET_HARD_QUAD"
2748   "@
2749    fmovq%C1 %x2,%3,%0
2750    fmovq%c1 %x2,%4,%0"
2751   [(set_attr "type" "cmove")])
2752
2753 (define_insn "*movqi_cc_reg_sp64"
2754   [(set (match_operand:QI 0 "register_operand" "=r,r")
2755         (if_then_else:QI (match_operator 1 "v9_regcmp_op"
2756                                 [(match_operand:DI 2 "register_operand" "r,r")
2757                                  (const_int 0)])
2758                       (match_operand:QI 3 "arith10_operand" "rM,0")
2759                       (match_operand:QI 4 "arith10_operand" "0,rM")))]
2760   "TARGET_ARCH64"
2761   "@
2762    movr%D1 %2,%r3,%0
2763    movr%d1 %2,%r4,%0"
2764   [(set_attr "type" "cmove")])
2765
2766 (define_insn "*movhi_cc_reg_sp64"
2767   [(set (match_operand:HI 0 "register_operand" "=r,r")
2768         (if_then_else:HI (match_operator 1 "v9_regcmp_op"
2769                                 [(match_operand:DI 2 "register_operand" "r,r")
2770                                  (const_int 0)])
2771                       (match_operand:HI 3 "arith10_operand" "rM,0")
2772                       (match_operand:HI 4 "arith10_operand" "0,rM")))]
2773   "TARGET_ARCH64"
2774   "@
2775    movr%D1 %2,%r3,%0
2776    movr%d1 %2,%r4,%0"
2777   [(set_attr "type" "cmove")])
2778
2779 (define_insn "*movsi_cc_reg_sp64"
2780   [(set (match_operand:SI 0 "register_operand" "=r,r")
2781         (if_then_else:SI (match_operator 1 "v9_regcmp_op"
2782                                 [(match_operand:DI 2 "register_operand" "r,r")
2783                                  (const_int 0)])
2784                       (match_operand:SI 3 "arith10_operand" "rM,0")
2785                       (match_operand:SI 4 "arith10_operand" "0,rM")))]
2786   "TARGET_ARCH64"
2787   "@
2788    movr%D1 %2,%r3,%0
2789    movr%d1 %2,%r4,%0"
2790   [(set_attr "type" "cmove")])
2791
2792 ;; ??? The constraints of operands 3,4 need work.
2793 (define_insn "*movdi_cc_reg_sp64"
2794   [(set (match_operand:DI 0 "register_operand" "=r,r")
2795         (if_then_else:DI (match_operator 1 "v9_regcmp_op"
2796                                 [(match_operand:DI 2 "register_operand" "r,r")
2797                                  (const_int 0)])
2798                       (match_operand:DI 3 "arith10_double_operand" "rMH,0")
2799                       (match_operand:DI 4 "arith10_double_operand" "0,rMH")))]
2800   "TARGET_ARCH64"
2801   "@
2802    movr%D1 %2,%r3,%0
2803    movr%d1 %2,%r4,%0"
2804   [(set_attr "type" "cmove")])
2805
2806 (define_insn "*movsf_cc_reg_sp64"
2807   [(set (match_operand:SF 0 "register_operand" "=f,f")
2808         (if_then_else:SF (match_operator 1 "v9_regcmp_op"
2809                                 [(match_operand:DI 2 "register_operand" "r,r")
2810                                  (const_int 0)])
2811                       (match_operand:SF 3 "register_operand" "f,0")
2812                       (match_operand:SF 4 "register_operand" "0,f")))]
2813   "TARGET_ARCH64 && TARGET_FPU"
2814   "@
2815    fmovrs%D1 %2,%3,%0
2816    fmovrs%d1 %2,%4,%0"
2817   [(set_attr "type" "cmove")])
2818
2819 (define_insn "*movdf_cc_reg_sp64"
2820   [(set (match_operand:DF 0 "register_operand" "=e,e")
2821         (if_then_else:DF (match_operator 1 "v9_regcmp_op"
2822                                 [(match_operand:DI 2 "register_operand" "r,r")
2823                                  (const_int 0)])
2824                       (match_operand:DF 3 "register_operand" "e,0")
2825                       (match_operand:DF 4 "register_operand" "0,e")))]
2826   "TARGET_ARCH64 && TARGET_FPU"
2827   "@
2828    fmovrd%D1 %2,%3,%0
2829    fmovrd%d1 %2,%4,%0"
2830   [(set_attr "type" "cmove")])
2831
2832 (define_insn "*movtf_cc_reg_sp64"
2833   [(set (match_operand:TF 0 "register_operand" "=e,e")
2834         (if_then_else:TF (match_operator 1 "v9_regcmp_op"
2835                                 [(match_operand:DI 2 "register_operand" "r,r")
2836                                  (const_int 0)])
2837                       (match_operand:TF 3 "register_operand" "e,0")
2838                       (match_operand:TF 4 "register_operand" "0,e")))]
2839   "TARGET_ARCH64 && TARGET_FPU"
2840   "@
2841    fmovrq%D1 %2,%3,%0
2842    fmovrq%d1 %2,%4,%0"
2843   [(set_attr "type" "cmove")])
2844 \f
2845 ;;- zero extension instructions
2846
2847 ;; These patterns originally accepted general_operands, however, slightly
2848 ;; better code is generated by only accepting register_operands, and then
2849 ;; letting combine generate the ldu[hb] insns.
2850
2851 (define_expand "zero_extendhisi2"
2852   [(set (match_operand:SI 0 "register_operand" "")
2853         (zero_extend:SI (match_operand:HI 1 "register_operand" "")))]
2854   ""
2855   "
2856 {
2857   rtx temp = gen_reg_rtx (SImode);
2858   rtx shift_16 = GEN_INT (16);
2859   int op1_subword = 0;
2860
2861   if (GET_CODE (operand1) == SUBREG)
2862     {
2863       op1_subword = SUBREG_WORD (operand1);
2864       operand1 = XEXP (operand1, 0);
2865     }
2866
2867   emit_insn (gen_ashlsi3 (temp, gen_rtx (SUBREG, SImode, operand1,
2868                                          op1_subword),
2869                           shift_16));
2870   emit_insn (gen_lshrsi3 (operand0, temp, shift_16));
2871   DONE;
2872 }")
2873
2874 (define_insn "*zero_extendhisi2_insn"
2875   [(set (match_operand:SI 0 "register_operand" "=r")
2876         (zero_extend:SI (match_operand:HI 1 "memory_operand" "m")))]
2877   ""
2878   "lduh %1,%0"
2879   [(set_attr "type" "load")])
2880
2881 (define_expand "zero_extendqihi2"
2882   [(set (match_operand:HI 0 "register_operand" "")
2883         (zero_extend:HI (match_operand:QI 1 "register_operand" "")))]
2884   ""
2885   "")
2886
2887 (define_insn "*zero_extendqihi2_insn"
2888   [(set (match_operand:HI 0 "register_operand" "=r,r")
2889         (zero_extend:HI (match_operand:QI 1 "sparc_operand" "r,Q")))]
2890   "GET_CODE (operands[1]) != CONST_INT"
2891   "@
2892    and %1,0xff,%0
2893    ldub %1,%0"
2894   [(set_attr "type" "unary,load")
2895    (set_attr "length" "1")])
2896
2897 (define_expand "zero_extendqisi2"
2898   [(set (match_operand:SI 0 "register_operand" "")
2899         (zero_extend:SI (match_operand:QI 1 "register_operand" "")))]
2900   ""
2901   "")
2902
2903 (define_insn "*zero_extendqisi2_insn"
2904   [(set (match_operand:SI 0 "register_operand" "=r,r")
2905         (zero_extend:SI (match_operand:QI 1 "sparc_operand" "r,Q")))]
2906   "GET_CODE (operands[1]) != CONST_INT"
2907   "@
2908    and %1,0xff,%0
2909    ldub %1,%0"
2910   [(set_attr "type" "unary,load")
2911    (set_attr "length" "1")])
2912
2913 (define_expand "zero_extendqidi2"
2914   [(set (match_operand:DI 0 "register_operand" "")
2915         (zero_extend:DI (match_operand:QI 1 "register_operand" "")))]
2916   "TARGET_ARCH64"
2917   "")
2918
2919 (define_insn "*zero_extendqidi2_insn"
2920   [(set (match_operand:DI 0 "register_operand" "=r,r")
2921         (zero_extend:DI (match_operand:QI 1 "sparc_operand" "r,Q")))]
2922   "TARGET_ARCH64 && GET_CODE (operands[1]) != CONST_INT"
2923   "@
2924    and %1,0xff,%0
2925    ldub %1,%0"
2926   [(set_attr "type" "unary,load")
2927    (set_attr "length" "1")])
2928
2929 (define_expand "zero_extendhidi2"
2930   [(set (match_operand:DI 0 "register_operand" "")
2931         (zero_extend:DI (match_operand:HI 1 "register_operand" "")))]
2932   "TARGET_ARCH64"
2933   "
2934 {
2935   rtx temp = gen_reg_rtx (DImode);
2936   rtx shift_48 = GEN_INT (48);
2937   int op1_subword = 0;
2938
2939   if (GET_CODE (operand1) == SUBREG)
2940     {
2941       op1_subword = SUBREG_WORD (operand1);
2942       operand1 = XEXP (operand1, 0);
2943     }
2944
2945   emit_insn (gen_ashldi3 (temp, gen_rtx (SUBREG, DImode, operand1,
2946                                          op1_subword),
2947                           shift_48));
2948   emit_insn (gen_lshrdi3 (operand0, temp, shift_48));
2949   DONE;
2950 }")
2951
2952 (define_insn "*zero_extendhidi2_insn"
2953   [(set (match_operand:DI 0 "register_operand" "=r")
2954         (zero_extend:DI (match_operand:HI 1 "memory_operand" "m")))]
2955   "TARGET_ARCH64"
2956   "lduh %1,%0"
2957   [(set_attr "type" "load")])
2958
2959 ;; ??? Write truncdisi pattern using sra?
2960
2961 (define_expand "zero_extendsidi2"
2962   [(set (match_operand:DI 0 "register_operand" "")
2963         (zero_extend:DI (match_operand:SI 1 "register_operand" "")))]
2964   "TARGET_ARCH64"
2965   "")
2966
2967 (define_insn "*zero_extendsidi2_insn"
2968   [(set (match_operand:DI 0 "register_operand" "=r,r")
2969         (zero_extend:DI (match_operand:SI 1 "sparc_operand" "r,Q")))]
2970   "TARGET_ARCH64 && GET_CODE (operands[1]) != CONST_INT"
2971   "@
2972    srl %1,0,%0
2973    lduw %1,%0"
2974   [(set_attr "type" "unary,load")
2975    (set_attr "length" "1")])
2976
2977 ;; Simplify comparisons of extended values.
2978
2979 (define_insn "*cmp_zero_extendqisi2"
2980   [(set (reg:CC 100)
2981         (compare:CC (zero_extend:SI (match_operand:QI 0 "register_operand" "r"))
2982                     (const_int 0)))]
2983   ""
2984   "andcc %0,0xff,%%g0"
2985   [(set_attr "type" "compare")])
2986
2987 (define_insn "*cmp_zero_extendqisi2_set"
2988   [(set (reg:CC 100)
2989         (compare:CC (zero_extend:SI (match_operand:QI 1 "register_operand" "r"))
2990                     (const_int 0)))
2991    (set (match_operand:SI 0 "register_operand" "=r")
2992         (zero_extend:SI (match_dup 1)))]
2993   ""
2994   "andcc %1,0xff,%0"
2995   [(set_attr "type" "unary")])
2996
2997 ;; Similarly, handle SI->QI mode truncation followed by a compare.
2998
2999 (define_insn "*cmp_siqi_trunc"
3000   [(set (reg:CC 100)
3001         (compare:CC (subreg:QI (match_operand:SI 0 "register_operand" "r") 0)
3002                     (const_int 0)))]
3003   ""
3004   "andcc %0,0xff,%%g0"
3005   [(set_attr "type" "compare")])
3006
3007 (define_insn "*cmp_siqi_trunc_set"
3008   [(set (reg:CC 100)
3009         (compare:CC (subreg:QI (match_operand:SI 1 "register_operand" "r") 0)
3010                     (const_int 0)))
3011    (set (match_operand:QI 0 "register_operand" "=r")
3012         (match_dup 1))]
3013   ""
3014   "andcc %1,0xff,%0"
3015   [(set_attr "type" "unary")])
3016 \f
3017 ;;- sign extension instructions
3018
3019 ;; These patterns originally accepted general_operands, however, slightly
3020 ;; better code is generated by only accepting register_operands, and then
3021 ;; letting combine generate the lds[hb] insns.
3022
3023 (define_expand "extendhisi2"
3024   [(set (match_operand:SI 0 "register_operand" "")
3025         (sign_extend:SI (match_operand:HI 1 "register_operand" "")))]
3026   ""
3027   "
3028 {
3029   rtx temp = gen_reg_rtx (SImode);
3030   rtx shift_16 = GEN_INT (16);
3031   int op1_subword = 0;
3032
3033   if (GET_CODE (operand1) == SUBREG)
3034     {
3035       op1_subword = SUBREG_WORD (operand1);
3036       operand1 = XEXP (operand1, 0);
3037     }
3038
3039   emit_insn (gen_ashlsi3 (temp, gen_rtx (SUBREG, SImode, operand1,
3040                                          op1_subword),
3041                           shift_16));
3042   emit_insn (gen_ashrsi3 (operand0, temp, shift_16));
3043   DONE;
3044 }")
3045
3046 (define_insn "*sign_extendhisi2_insn"
3047   [(set (match_operand:SI 0 "register_operand" "=r")
3048         (sign_extend:SI (match_operand:HI 1 "memory_operand" "m")))]
3049   ""
3050   "ldsh %1,%0"
3051   [(set_attr "type" "load")])
3052
3053 (define_expand "extendqihi2"
3054   [(set (match_operand:HI 0 "register_operand" "")
3055         (sign_extend:HI (match_operand:QI 1 "register_operand" "")))]
3056   ""
3057   "
3058 {
3059   rtx temp = gen_reg_rtx (SImode);
3060   rtx shift_24 = GEN_INT (24);
3061   int op1_subword = 0;
3062   int op0_subword = 0;
3063
3064   if (GET_CODE (operand1) == SUBREG)
3065     {
3066       op1_subword = SUBREG_WORD (operand1);
3067       operand1 = XEXP (operand1, 0);
3068     }
3069   if (GET_CODE (operand0) == SUBREG)
3070     {
3071       op0_subword = SUBREG_WORD (operand0);
3072       operand0 = XEXP (operand0, 0);
3073     }
3074   emit_insn (gen_ashlsi3 (temp, gen_rtx (SUBREG, SImode, operand1,
3075                                          op1_subword),
3076                           shift_24));
3077   if (GET_MODE (operand0) != SImode)
3078     operand0 = gen_rtx (SUBREG, SImode, operand0, op0_subword);
3079   emit_insn (gen_ashrsi3 (operand0, temp, shift_24));
3080   DONE;
3081 }")
3082
3083 (define_insn "*sign_extendqihi2_insn"
3084   [(set (match_operand:HI 0 "register_operand" "=r")
3085         (sign_extend:HI (match_operand:QI 1 "memory_operand" "m")))]
3086   ""
3087   "ldsb %1,%0"
3088   [(set_attr "type" "load")])
3089
3090 (define_expand "extendqisi2"
3091   [(set (match_operand:SI 0 "register_operand" "")
3092         (sign_extend:SI (match_operand:QI 1 "register_operand" "")))]
3093   ""
3094   "
3095 {
3096   rtx temp = gen_reg_rtx (SImode);
3097   rtx shift_24 = GEN_INT (24);
3098   int op1_subword = 0;
3099
3100   if (GET_CODE (operand1) == SUBREG)
3101     {
3102       op1_subword = SUBREG_WORD (operand1);
3103       operand1 = XEXP (operand1, 0);
3104     }
3105
3106   emit_insn (gen_ashlsi3 (temp, gen_rtx (SUBREG, SImode, operand1,
3107                                          op1_subword),
3108                           shift_24));
3109   emit_insn (gen_ashrsi3 (operand0, temp, shift_24));
3110   DONE;
3111 }")
3112
3113 (define_insn "*sign_extendqisi2_insn"
3114   [(set (match_operand:SI 0 "register_operand" "=r")
3115         (sign_extend:SI (match_operand:QI 1 "memory_operand" "m")))]
3116   ""
3117   "ldsb %1,%0"
3118   [(set_attr "type" "load")])
3119
3120 (define_expand "extendqidi2"
3121   [(set (match_operand:DI 0 "register_operand" "")
3122         (sign_extend:DI (match_operand:QI 1 "register_operand" "")))]
3123   "TARGET_ARCH64"
3124   "
3125 {
3126   rtx temp = gen_reg_rtx (DImode);
3127   rtx shift_56 = GEN_INT (56);
3128   int op1_subword = 0;
3129
3130   if (GET_CODE (operand1) == SUBREG)
3131     {
3132       op1_subword = SUBREG_WORD (operand1);
3133       operand1 = XEXP (operand1, 0);
3134     }
3135
3136   emit_insn (gen_ashldi3 (temp, gen_rtx (SUBREG, DImode, operand1,
3137                                          op1_subword),
3138                           shift_56));
3139   emit_insn (gen_ashrdi3 (operand0, temp, shift_56));
3140   DONE;
3141 }")
3142
3143 (define_insn "*sign_extendqidi2_insn"
3144   [(set (match_operand:DI 0 "register_operand" "=r")
3145         (sign_extend:DI (match_operand:QI 1 "memory_operand" "m")))]
3146   "TARGET_ARCH64"
3147   "ldsb %1,%0"
3148   [(set_attr "type" "load")])
3149
3150 (define_expand "extendhidi2"
3151   [(set (match_operand:DI 0 "register_operand" "")
3152         (sign_extend:DI (match_operand:HI 1 "register_operand" "")))]
3153   "TARGET_ARCH64"
3154   "
3155 {
3156   rtx temp = gen_reg_rtx (DImode);
3157   rtx shift_48 = GEN_INT (48);
3158   int op1_subword = 0;
3159
3160   if (GET_CODE (operand1) == SUBREG)
3161     {
3162       op1_subword = SUBREG_WORD (operand1);
3163       operand1 = XEXP (operand1, 0);
3164     }
3165
3166   emit_insn (gen_ashldi3 (temp, gen_rtx (SUBREG, DImode, operand1,
3167                                          op1_subword),
3168                           shift_48));
3169   emit_insn (gen_ashrdi3 (operand0, temp, shift_48));
3170   DONE;
3171 }")
3172
3173 (define_insn "*sign_extendhidi2_insn"
3174   [(set (match_operand:DI 0 "register_operand" "=r")
3175         (sign_extend:DI (match_operand:HI 1 "memory_operand" "m")))]
3176   "TARGET_ARCH64"
3177   "ldsh %1,%0"
3178   [(set_attr "type" "load")])
3179
3180 (define_expand "extendsidi2"
3181   [(set (match_operand:DI 0 "register_operand" "")
3182         (sign_extend:DI (match_operand:SI 1 "register_operand" "")))]
3183   "TARGET_ARCH64"
3184   "")
3185
3186 (define_insn "*sign_extendsidi2_insn"
3187   [(set (match_operand:DI 0 "register_operand" "=r,r")
3188         (sign_extend:DI (match_operand:SI 1 "sparc_operand" "r,Q")))]
3189   "TARGET_ARCH64"
3190   "@
3191   sra %1,0,%0
3192   ldsw %1,%0"
3193   [(set_attr "type" "unary,load")
3194    (set_attr "length" "1")])
3195 \f
3196 ;; Special pattern for optimizing bit-field compares.  This is needed
3197 ;; because combine uses this as a canonical form.
3198
3199 (define_insn "*cmp_zero_extract"
3200   [(set (reg:CC 100)
3201         (compare:CC
3202          (zero_extract:SI (match_operand:SI 0 "register_operand" "r")
3203                           (match_operand:SI 1 "small_int" "n")
3204                           (match_operand:SI 2 "small_int" "n"))
3205          (const_int 0)))]
3206   "INTVAL (operands[2]) > 19"
3207   "*
3208 {
3209   int len = INTVAL (operands[1]);
3210   int pos = 32 - INTVAL (operands[2]) - len;
3211   unsigned mask = ((1 << len) - 1) << pos;
3212
3213   operands[1] = GEN_INT (mask);
3214   return \"andcc %0,%1,%%g0\";
3215 }")
3216
3217 (define_insn "*cmp_zero_extract_sp64"
3218   [(set (reg:CCX 100)
3219         (compare:CCX
3220          (zero_extract:DI (match_operand:DI 0 "register_operand" "r")
3221                           (match_operand:SI 1 "small_int" "n")
3222                           (match_operand:SI 2 "small_int" "n"))
3223          (const_int 0)))]
3224   "TARGET_ARCH64 && INTVAL (operands[2]) > 51"
3225   "*
3226 {
3227   int len = INTVAL (operands[1]);
3228   int pos = 64 - INTVAL (operands[2]) - len;
3229   unsigned HOST_WIDE_INT mask = (((unsigned HOST_WIDE_INT) 1 << len) - 1) << pos;
3230
3231   operands[1] = GEN_INT (mask);
3232   return \"andcc %0,%1,%%g0\";
3233 }")
3234 \f
3235 ;; Conversions between float, double and long double.
3236
3237 (define_insn "extendsfdf2"
3238   [(set (match_operand:DF 0 "register_operand" "=e")
3239         (float_extend:DF
3240          (match_operand:SF 1 "register_operand" "f")))]
3241   "TARGET_FPU"
3242   "fstod %1,%0"
3243   [(set_attr "type" "fp")])
3244
3245 (define_insn "extendsftf2"
3246   [(set (match_operand:TF 0 "register_operand" "=e")
3247         (float_extend:TF
3248          (match_operand:SF 1 "register_operand" "f")))]
3249   "TARGET_FPU && TARGET_HARD_QUAD"
3250   "fstoq %1,%0"
3251   [(set_attr "type" "fp")])
3252
3253 (define_insn "extenddftf2"
3254   [(set (match_operand:TF 0 "register_operand" "=e")
3255         (float_extend:TF
3256          (match_operand:DF 1 "register_operand" "e")))]
3257   "TARGET_FPU && TARGET_HARD_QUAD"
3258   "fdtoq %1,%0"
3259   [(set_attr "type" "fp")])
3260
3261 (define_insn "truncdfsf2"
3262   [(set (match_operand:SF 0 "register_operand" "=f")
3263         (float_truncate:SF
3264          (match_operand:DF 1 "register_operand" "e")))]
3265   "TARGET_FPU"
3266   "fdtos %1,%0"
3267   [(set_attr "type" "fp")])
3268
3269 (define_insn "trunctfsf2"
3270   [(set (match_operand:SF 0 "register_operand" "=f")
3271         (float_truncate:SF
3272          (match_operand:TF 1 "register_operand" "e")))]
3273   "TARGET_FPU && TARGET_HARD_QUAD"
3274   "fqtos %1,%0"
3275   [(set_attr "type" "fp")])
3276
3277 (define_insn "trunctfdf2"
3278   [(set (match_operand:DF 0 "register_operand" "=e")
3279         (float_truncate:DF
3280          (match_operand:TF 1 "register_operand" "e")))]
3281   "TARGET_FPU && TARGET_HARD_QUAD"
3282   "fqtod %1,%0"
3283   [(set_attr "type" "fp")])
3284 \f
3285 ;; Conversion between fixed point and floating point.
3286
3287 (define_insn "floatsisf2"
3288   [(set (match_operand:SF 0 "register_operand" "=f")
3289         (float:SF (match_operand:SI 1 "register_operand" "f")))]
3290   "TARGET_FPU"
3291   "fitos %1,%0"
3292   [(set_attr "type" "fp")])
3293
3294 (define_insn "floatsidf2"
3295   [(set (match_operand:DF 0 "register_operand" "=e")
3296         (float:DF (match_operand:SI 1 "register_operand" "f")))]
3297   "TARGET_FPU"
3298   "fitod %1,%0"
3299   [(set_attr "type" "fp")])
3300
3301 (define_insn "floatsitf2"
3302   [(set (match_operand:TF 0 "register_operand" "=e")
3303         (float:TF (match_operand:SI 1 "register_operand" "f")))]
3304   "TARGET_FPU && TARGET_HARD_QUAD"
3305   "fitoq %1,%0"
3306   [(set_attr "type" "fp")])
3307
3308 ;; Now the same for 64 bit sources.
3309 ;; ??? We cannot put DImode values in fp regs (see below near fix_truncdfsi2).
3310
3311 (define_expand "floatdisf2"
3312   [(parallel [(set (match_operand:SF 0 "register_operand" "")
3313                    (float:SF (match_operand:DI 1 "general_operand" "")))
3314               (clobber (match_dup 2))
3315               (clobber (match_dup 3))])]
3316   "TARGET_ARCH64 && TARGET_FPU"
3317   "
3318 {
3319   operands[2] = gen_reg_rtx (DFmode);
3320   operands[3] = sparc64_fpconv_stack_temp ();
3321 }")
3322
3323 (define_expand "floatdidf2"
3324   [(parallel [(set (match_operand:DF 0 "register_operand" "")
3325                    (float:DF (match_operand:DI 1 "general_operand" "")))
3326               (clobber (match_dup 2))
3327               (clobber (match_dup 3))])]
3328   "TARGET_ARCH64 && TARGET_FPU"
3329   "
3330 {
3331   operands[2] = gen_reg_rtx (DFmode);
3332   operands[3] = sparc64_fpconv_stack_temp ();
3333 }")
3334
3335 (define_expand "floatditf2"
3336   [(parallel [(set (match_operand:TF 0 "register_operand" "")
3337                    (float:TF (match_operand:DI 1 "general_operand" "")))
3338               (clobber (match_dup 2))
3339               (clobber (match_dup 3))])]
3340   "TARGET_ARCH64 && TARGET_FPU && TARGET_HARD_QUAD"
3341   "
3342 {
3343   operands[2] = gen_reg_rtx (DFmode);
3344   operands[3] = sparc64_fpconv_stack_temp ();
3345 }")
3346
3347 (define_insn "*floatdisf2_insn"
3348   [(parallel [(set (match_operand:SF 0 "register_operand" "=f")
3349                    (float:SF (match_operand:DI 1 "general_operand" "rm")))
3350               (clobber (match_operand:DF 2 "register_operand" "=&e"))
3351               (clobber (match_operand:DI 3 "memory_operand" "m"))])]
3352   "TARGET_ARCH64 && TARGET_FPU"
3353   "*
3354 {
3355   if (GET_CODE (operands[1]) == MEM)
3356     output_asm_insn (\"ldd %1,%2\", operands);
3357   else
3358     output_asm_insn (\"stx %1,%3\;ldd %3,%2\", operands);
3359   return \"fxtos %2,%0\";
3360 }"
3361   [(set_attr "type" "fp")
3362    (set_attr "length" "3")])
3363
3364 (define_insn "*floatdidf2_insn"
3365   [(parallel [(set (match_operand:DF 0 "register_operand" "=e")
3366                    (float:DF (match_operand:DI 1 "general_operand" "rm")))
3367               (clobber (match_operand:DF 2 "register_operand" "=&e"))
3368               (clobber (match_operand:DI 3 "memory_operand" "m"))])]
3369   "TARGET_ARCH64 && TARGET_FPU"
3370   "*
3371 {
3372   if (GET_CODE (operands[1]) == MEM)
3373     output_asm_insn (\"ldd %1,%2\", operands);
3374   else
3375     output_asm_insn (\"stx %1,%3\;ldd %3,%2\", operands);
3376   return \"fxtod %2,%0\";
3377 }"
3378   [(set_attr "type" "fp")
3379    (set_attr "length" "3")])
3380
3381 (define_insn "*floatditf2_insn"
3382   [(parallel [(set (match_operand:TF 0 "register_operand" "=e")
3383                    (float:TF (match_operand:DI 1 "general_operand" "rm")))
3384               (clobber (match_operand:DF 2 "register_operand" "=&e"))
3385               (clobber (match_operand:DI 3 "memory_operand" "m"))])]
3386   "TARGET_ARCH64 && TARGET_FPU && TARGET_HARD_QUAD"
3387   "*
3388 {
3389   if (GET_CODE (operands[1]) == MEM)
3390     output_asm_insn (\"ldd %1,%2\", operands);
3391   else
3392     output_asm_insn (\"stx %1,%3\;ldd %3,%2\", operands);
3393   return \"fxtoq %2,%0\";
3394 }"
3395   [(set_attr "type" "fp")
3396    (set_attr "length" "3")])
3397
3398 ;; ??? Ideally, these are what we would like to use.
3399
3400 (define_insn "floatdisf2_sp64"
3401   [(set (match_operand:SF 0 "register_operand" "=f")
3402         (float:SF (match_operand:DI 1 "register_operand" "e")))]
3403   "0 && TARGET_ARCH64 && TARGET_FPU"
3404   "fxtos %1,%0"
3405   [(set_attr "type" "fp")])
3406
3407 (define_insn "floatdidf2_sp64"
3408   [(set (match_operand:DF 0 "register_operand" "=e")
3409         (float:DF (match_operand:DI 1 "register_operand" "e")))]
3410   "0 && TARGET_ARCH64 && TARGET_FPU"
3411   "fxtod %1,%0"
3412   [(set_attr "type" "fp")])
3413
3414 (define_insn "floatditf2_sp64"
3415   [(set (match_operand:TF 0 "register_operand" "=e")
3416         (float:TF (match_operand:DI 1 "register_operand" "e")))]
3417   "0 && TARGET_ARCH64 && TARGET_FPU && TARGET_HARD_QUAD"
3418   "fxtoq %1,%0"
3419   [(set_attr "type" "fp")])
3420
3421 ;; Convert a float to an actual integer.
3422 ;; Truncation is performed as part of the conversion.
3423
3424 (define_insn "fix_truncsfsi2"
3425   [(set (match_operand:SI 0 "register_operand" "=f")
3426         (fix:SI (fix:SF (match_operand:SF 1 "register_operand" "f"))))]
3427   "TARGET_FPU"
3428   "fstoi %1,%0"
3429   [(set_attr "type" "fp")])
3430
3431 (define_insn "fix_truncdfsi2"
3432   [(set (match_operand:SI 0 "register_operand" "=f")
3433         (fix:SI (fix:DF (match_operand:DF 1 "register_operand" "e"))))]
3434   "TARGET_FPU"
3435   "fdtoi %1,%0"
3436   [(set_attr "type" "fp")])
3437
3438 (define_insn "fix_trunctfsi2"
3439   [(set (match_operand:SI 0 "register_operand" "=f")
3440         (fix:SI (fix:TF (match_operand:TF 1 "register_operand" "e"))))]
3441   "TARGET_FPU && TARGET_HARD_QUAD"
3442   "fqtoi %1,%0"
3443   [(set_attr "type" "fp")])
3444
3445 ;; Now the same, for 64-bit targets
3446 ;; ??? We try to work around an interesting problem.
3447 ;; If gcc tries to do a subreg on the result it will get the wrong answer:
3448 ;; "(subreg:SI (reg:DI M int-reg) 0)" is the same as
3449 ;; "(subreg:SI (reg:DI N float-reg) 1)", but gcc does not know how to change
3450 ;; the "0" to a "1".  One could enhance alter_subreg but it is not clear how to
3451 ;; do this cleanly.
3452
3453 (define_expand "fix_truncsfdi2"
3454   [(parallel [(set (match_operand:DI 0 "general_operand" "")
3455                    (fix:DI (fix:SF (match_operand:SF 1 "register_operand" ""))))
3456               (clobber (match_dup 2))
3457               (clobber (match_dup 3))])]
3458   "TARGET_ARCH64 && TARGET_FPU"
3459   "
3460 {
3461   operands[2] = gen_reg_rtx (DFmode);
3462   operands[3] = sparc64_fpconv_stack_temp ();
3463 }")
3464
3465 (define_expand "fix_truncdfdi2"
3466   [(parallel [(set (match_operand:DI 0 "general_operand" "")
3467                    (fix:DI (fix:DF (match_operand:DF 1 "register_operand" ""))))
3468               (clobber (match_dup 2))
3469               (clobber (match_dup 3))])]
3470   "TARGET_ARCH64 && TARGET_FPU"
3471   "
3472 {
3473   operands[2] = gen_reg_rtx (DFmode);
3474   operands[3] = sparc64_fpconv_stack_temp ();
3475 }")
3476
3477 (define_expand "fix_trunctfdi2"
3478   [(parallel [(set (match_operand:DI 0 "general_operand" "")
3479                    (fix:DI (fix:TF (match_operand:TF 1 "register_operand" ""))))
3480               (clobber (match_dup 2))
3481               (clobber (match_dup 3))])]
3482   "TARGET_ARCH64 && TARGET_FPU && TARGET_HARD_QUAD"
3483   "
3484 {
3485   operands[2] = gen_reg_rtx (DFmode);
3486   operands[3] = sparc64_fpconv_stack_temp ();
3487 }")
3488
3489 (define_insn "*fix_truncsfdi2_insn"
3490   [(parallel [(set (match_operand:DI 0 "general_operand" "=rm")
3491                    (fix:DI (fix:SF (match_operand:SF 1 "register_operand" "f"))))
3492               (clobber (match_operand:DF 2 "register_operand" "=&e"))
3493               (clobber (match_operand:DI 3 "memory_operand" "m"))])]
3494   "TARGET_ARCH64 && TARGET_FPU"
3495   "*
3496 {
3497   output_asm_insn (\"fstox %1,%2\", operands);
3498   if (GET_CODE (operands[0]) == MEM)
3499     return \"std %2,%0\";
3500   else
3501     return \"std %2,%3\;ldx %3,%0\";
3502 }"
3503   [(set_attr "type" "fp")
3504    (set_attr "length" "3")])
3505
3506 (define_insn "*fix_truncdfdi2_insn"
3507   [(parallel [(set (match_operand:DI 0 "general_operand" "=rm")
3508                    (fix:DI (fix:DF (match_operand:DF 1 "register_operand" "e"))))
3509               (clobber (match_operand:DF 2 "register_operand" "=&e"))
3510               (clobber (match_operand:DI 3 "memory_operand" "m"))])]
3511   "TARGET_ARCH64 && TARGET_FPU"
3512   "*
3513 {
3514   output_asm_insn (\"fdtox %1,%2\", operands);
3515   if (GET_CODE (operands[0]) == MEM)
3516     return \"std %2,%0\";
3517   else
3518     return \"std %2,%3\;ldx %3,%0\";
3519 }"
3520   [(set_attr "type" "fp")
3521    (set_attr "length" "3")])
3522
3523 (define_insn "*fix_trunctfdi2_insn"
3524   [(parallel [(set (match_operand:DI 0 "general_operand" "=rm")
3525                    (fix:DI (fix:TF (match_operand:TF 1 "register_operand" "e"))))
3526               (clobber (match_operand:DF 2 "register_operand" "=&e"))
3527               (clobber (match_operand:DI 3 "memory_operand" "m"))])]
3528   "TARGET_ARCH64 && TARGET_FPU && TARGET_HARD_QUAD"
3529   "*
3530 {
3531   output_asm_insn (\"fqtox %1,%2\", operands);
3532   if (GET_CODE (operands[0]) == MEM)
3533     return \"std %2,%0\";
3534   else
3535     return \"std %2,%3\;ldx %3,%0\";
3536 }"
3537   [(set_attr "type" "fp")
3538    (set_attr "length" "3")])
3539
3540 ;; ??? Ideally, these are what we would like to use.
3541
3542 (define_insn "fix_truncsfdi2_sp64"
3543   [(set (match_operand:DI 0 "register_operand" "=e")
3544         (fix:DI (fix:SF (match_operand:SF 1 "register_operand" "f"))))]
3545   "0 && TARGET_ARCH64 && TARGET_FPU"
3546   "fstox %1,%0"
3547   [(set_attr "type" "fp")])
3548
3549 (define_insn "fix_truncdfdi2_sp64"
3550   [(set (match_operand:DI 0 "register_operand" "=e")
3551         (fix:DI (fix:DF (match_operand:DF 1 "register_operand" "e"))))]
3552   "0 && TARGET_ARCH64 && TARGET_FPU"
3553   "fdtox %1,%0"
3554   [(set_attr "type" "fp")])
3555
3556 (define_insn "fix_trunctfdi2_sp64"
3557   [(set (match_operand:DI 0 "register_operand" "=e")
3558         (fix:DI (fix:TF (match_operand:TF 1 "register_operand" "e"))))]
3559   "0 && TARGET_ARCH64 && TARGET_FPU && TARGET_HARD_QUAD"
3560   "fqtox %1,%0"
3561   [(set_attr "type" "fp")])
3562 \f
3563 ;;- arithmetic instructions
3564
3565 (define_expand "adddi3"
3566   [(set (match_operand:DI 0 "register_operand" "=r")
3567         (plus:DI (match_operand:DI 1 "arith_double_operand" "%r")
3568                  (match_operand:DI 2 "arith_double_operand" "rHI")))]
3569   ""
3570   "
3571 {
3572   if (! TARGET_ARCH64)
3573     {
3574       emit_insn (gen_rtx (PARALLEL, VOIDmode, gen_rtvec (2,
3575                           gen_rtx (SET, VOIDmode, operands[0],
3576                                    gen_rtx (PLUS, DImode, operands[1],
3577                                                   operands[2])),
3578                           gen_rtx (CLOBBER, VOIDmode,
3579                                    gen_rtx (REG, SImode, SPARC_ICC_REG)))));
3580       DONE;
3581     }
3582 }")
3583
3584 (define_insn "*adddi3_sp32"
3585   [(set (match_operand:DI 0 "register_operand" "=r")
3586         (plus:DI (match_operand:DI 1 "arith_double_operand" "%r")
3587                  (match_operand:DI 2 "arith_double_operand" "rHI")))
3588    (clobber (reg:SI 100))]
3589   "! TARGET_ARCH64"
3590   "*
3591 {
3592   rtx op2 = operands[2];
3593
3594   if (GET_CODE (op2) == CONST_INT
3595       || GET_CODE (op2) == CONST_DOUBLE)
3596     {
3597       rtx xoperands[4];
3598       xoperands[0] = operands[0];
3599       xoperands[1] = operands[1];
3600       if (WORDS_BIG_ENDIAN)
3601         split_double (op2, &xoperands[2], &xoperands[3]);
3602       else
3603         split_double (op2, &xoperands[3], &xoperands[2]);
3604       if (xoperands[3] == const0_rtx && xoperands[0] == xoperands[1])
3605         output_asm_insn (\"add %H1,%2,%H0\", xoperands);
3606       else
3607         output_asm_insn (\"addcc %L1,%3,%L0\;addx %H1,%2,%H0\", xoperands);
3608       return \"\";
3609     }
3610   return \"addcc %L1,%L2,%L0\;addx %H1,%H2,%H0\";
3611 }"
3612   [(set_attr "length" "2")])
3613
3614 (define_insn "*adddi3_sp64"
3615   [(set (match_operand:DI 0 "register_operand" "=r")
3616         (plus:DI (match_operand:DI 1 "arith_double_operand" "%r")
3617                  (match_operand:DI 2 "arith_double_operand" "rHI")))]
3618   "TARGET_ARCH64"
3619   "add %1,%2,%0")
3620
3621 (define_insn "addsi3"
3622   [(set (match_operand:SI 0 "register_operand" "=r")
3623         (plus:SI (match_operand:SI 1 "arith_operand" "%r")
3624                  (match_operand:SI 2 "arith_operand" "rI")))]
3625   ""
3626   "add %1,%2,%0"
3627   [(set_attr "type" "ialu")])
3628
3629 (define_insn "*cmp_cc_plus"
3630   [(set (reg:CC_NOOV 100)
3631         (compare:CC_NOOV (plus:SI (match_operand:SI 0 "arith_operand" "%r")
3632                                   (match_operand:SI 1 "arith_operand" "rI"))
3633                          (const_int 0)))]
3634   ""
3635   "addcc %0,%1,%%g0"
3636   [(set_attr "type" "compare")])
3637
3638 (define_insn "*cmp_ccx_plus"
3639   [(set (reg:CCX_NOOV 100)
3640         (compare:CCX_NOOV (plus:DI (match_operand:DI 0 "arith_double_operand" "%r")
3641                                    (match_operand:DI 1 "arith_double_operand" "rHI"))
3642                           (const_int 0)))]
3643   "TARGET_ARCH64"
3644   "addcc %0,%1,%%g0"
3645   [(set_attr "type" "compare")])
3646
3647 (define_insn "*cmp_cc_plus_set"
3648   [(set (reg:CC_NOOV 100)
3649         (compare:CC_NOOV (plus:SI (match_operand:SI 1 "arith_operand" "%r")
3650                                   (match_operand:SI 2 "arith_operand" "rI"))
3651                          (const_int 0)))
3652    (set (match_operand:SI 0 "register_operand" "=r")
3653         (plus:SI (match_dup 1) (match_dup 2)))]
3654   ""
3655   "addcc %1,%2,%0")
3656
3657 (define_insn "*cmp_ccx_plus_set"
3658   [(set (reg:CCX_NOOV 100)
3659         (compare:CCX_NOOV (plus:DI (match_operand:DI 1 "arith_double_operand" "%r")
3660                                    (match_operand:DI 2 "arith_double_operand" "rHI"))
3661                           (const_int 0)))
3662    (set (match_operand:DI 0 "register_operand" "=r")
3663         (plus:DI (match_dup 1) (match_dup 2)))]
3664   "TARGET_ARCH64"
3665   "addcc %1,%2,%0")
3666
3667 (define_expand "subdi3"
3668   [(set (match_operand:DI 0 "register_operand" "=r")
3669         (minus:DI (match_operand:DI 1 "register_operand" "r")
3670                   (match_operand:DI 2 "arith_double_operand" "rHI")))]
3671   ""
3672   "
3673 {
3674   if (! TARGET_ARCH64)
3675     {
3676       emit_insn (gen_rtx (PARALLEL, VOIDmode, gen_rtvec (2,
3677                           gen_rtx (SET, VOIDmode, operands[0],
3678                                    gen_rtx (MINUS, DImode, operands[1],
3679                                                    operands[2])),
3680                           gen_rtx (CLOBBER, VOIDmode,
3681                                    gen_rtx (REG, SImode, SPARC_ICC_REG)))));
3682       DONE;
3683     }
3684 }")
3685
3686 (define_insn "*subdi3_sp32"
3687   [(set (match_operand:DI 0 "register_operand" "=r")
3688         (minus:DI (match_operand:DI 1 "register_operand" "r")
3689                   (match_operand:DI 2 "arith_double_operand" "rHI")))
3690    (clobber (reg:SI 100))]
3691   "! TARGET_ARCH64"
3692   "*
3693 {
3694   rtx op2 = operands[2];
3695
3696   if (GET_CODE (op2) == CONST_INT
3697       || GET_CODE (op2) == CONST_DOUBLE)
3698     {
3699       rtx xoperands[4];
3700       xoperands[0] = operands[0];
3701       xoperands[1] = operands[1];
3702       if (WORDS_BIG_ENDIAN)
3703         split_double (op2, &xoperands[2], &xoperands[3]);
3704       else
3705         split_double (op2, &xoperands[3], &xoperands[2]);
3706       if (xoperands[3] == const0_rtx && xoperands[0] == xoperands[1])
3707         output_asm_insn (\"sub %H1,%2,%H0\", xoperands);
3708       else
3709         output_asm_insn (\"subcc %L1,%3,%L0\;subx %H1,%2,%H0\", xoperands);
3710       return \"\";
3711     }
3712   return \"subcc %L1,%L2,%L0\;subx %H1,%H2,%H0\";
3713 }"
3714   [(set_attr "length" "2")])
3715
3716 (define_insn "*subdi3_sp64"
3717   [(set (match_operand:DI 0 "register_operand" "=r")
3718         (minus:DI (match_operand:DI 1 "register_operand" "r")
3719                   (match_operand:DI 2 "arith_double_operand" "rHI")))]
3720   "TARGET_ARCH64"
3721   "sub %1,%2,%0")
3722
3723 (define_insn "subsi3"
3724   [(set (match_operand:SI 0 "register_operand" "=r")
3725         (minus:SI (match_operand:SI 1 "register_operand" "r")
3726                   (match_operand:SI 2 "arith_operand" "rI")))]
3727   ""
3728   "sub %1,%2,%0"
3729   [(set_attr "type" "ialu")])
3730
3731 (define_insn "*cmp_minus_cc"
3732   [(set (reg:CC_NOOV 100)
3733         (compare:CC_NOOV (minus:SI (match_operand:SI 0 "register_operand" "r")
3734                                    (match_operand:SI 1 "arith_operand" "rI"))
3735                          (const_int 0)))]
3736   ""
3737   "subcc %0,%1,%%g0"
3738   [(set_attr "type" "compare")])
3739
3740 (define_insn "*cmp_minus_ccx"
3741   [(set (reg:CCX_NOOV 100)
3742         (compare:CCX_NOOV (minus:DI (match_operand:DI 0 "register_operand" "r")
3743                                     (match_operand:DI 1 "arith_double_operand" "rHI"))
3744                           (const_int 0)))]
3745   "TARGET_ARCH64"
3746   "subcc %0,%1,%%g0"
3747   [(set_attr "type" "compare")])
3748
3749 (define_insn "*cmp_minus_cc_set"
3750   [(set (reg:CC_NOOV 100)
3751         (compare:CC_NOOV (minus:SI (match_operand:SI 1 "register_operand" "r")
3752                                    (match_operand:SI 2 "arith_operand" "rI"))
3753                          (const_int 0)))
3754    (set (match_operand:SI 0 "register_operand" "=r")
3755         (minus:SI (match_dup 1) (match_dup 2)))]
3756   ""
3757   "subcc %1,%2,%0")
3758
3759 (define_insn "*cmp_minus_ccx_set"
3760   [(set (reg:CCX_NOOV 100)
3761         (compare:CCX_NOOV (minus:DI (match_operand:DI 1 "register_operand" "r")
3762                                     (match_operand:DI 2 "arith_double_operand" "rHI"))
3763                           (const_int 0)))
3764    (set (match_operand:DI 0 "register_operand" "=r")
3765         (minus:DI (match_dup 1) (match_dup 2)))]
3766   "TARGET_ARCH64"
3767   "subcc %1,%2,%0")
3768 \f
3769 ;; Integer Multiply/Divide.
3770
3771 ;; The 32 bit multiply/divide instructions are deprecated on v9 and shouldn't
3772 ;; we used.  We still use them in 32 bit v9 compilers.
3773 ;; The 64 bit v9 compiler will (/should) widen the args and use muldi3.
3774
3775 (define_insn "mulsi3"
3776   [(set (match_operand:SI 0 "register_operand" "=r")
3777         (mult:SI (match_operand:SI 1 "arith_operand" "%r")
3778                  (match_operand:SI 2 "arith_operand" "rI")))]
3779   "TARGET_V8 || TARGET_SPARCLITE || TARGET_SPARCLET || TARGET_DEPRECATED_V8_INSNS"
3780   "smul %1,%2,%0"
3781   [(set_attr "type" "imul")])
3782
3783 (define_insn "muldi3"
3784   [(set (match_operand:DI 0 "register_operand" "=r")
3785         (mult:DI (match_operand:DI 1 "arith_double_operand" "%r")
3786                  (match_operand:DI 2 "arith_double_operand" "rHI")))]
3787   "TARGET_ARCH64"
3788   "mulx %1,%2,%0")
3789
3790 ;; It is not known whether this will match.
3791
3792 (define_insn "*cmp_mul_set"
3793   [(set (match_operand:SI 0 "register_operand" "=r")
3794         (mult:SI (match_operand:SI 1 "arith_operand" "%r")
3795                  (match_operand:SI 2 "arith_operand" "rI")))
3796    (set (reg:CC_NOOV 100)
3797         (compare:CC_NOOV (mult:SI (match_dup 1) (match_dup 2))
3798                          (const_int 0)))]
3799   "TARGET_V8 || TARGET_SPARCLITE || TARGET_DEPRECATED_V8_INSNS"
3800   "smulcc %1,%2,%0"
3801   [(set_attr "type" "imul")])
3802
3803 (define_expand "mulsidi3"
3804   [(set (match_operand:DI 0 "register_operand" "")
3805         (mult:DI (sign_extend:DI (match_operand:SI 1 "register_operand" ""))
3806                  (sign_extend:DI (match_operand:SI 2 "arith_operand" ""))))]
3807   "TARGET_V8 || TARGET_SPARCLITE || TARGET_SPARCLET || TARGET_DEPRECATED_V8_INSNS"
3808   "
3809 {
3810   if (CONSTANT_P (operands[2]))
3811     {
3812       emit_insn (gen_const_mulsidi3 (operands[0], operands[1], operands[2]));
3813       DONE;
3814     }
3815 }")
3816
3817 (define_insn "*mulsidi3_sp32"
3818   [(set (match_operand:DI 0 "register_operand" "=r")
3819         (mult:DI (sign_extend:DI (match_operand:SI 1 "register_operand" "r"))
3820                  (sign_extend:DI (match_operand:SI 2 "register_operand" "r"))))]
3821   "TARGET_V8 || TARGET_SPARCLITE || TARGET_SPARCLET || TARGET_DEPRECATED_V8_INSNS"
3822   "*
3823 {
3824   return TARGET_SPARCLET ? \"smuld %1,%2,%L0\" : \"smul %1,%2,%L0\;rd %%y,%H0\";
3825 }"
3826   [(set (attr "length")
3827         (if_then_else (eq_attr "isa" "sparclet")
3828                       (const_int 1) (const_int 2)))])
3829
3830 ;; Extra pattern, because sign_extend of a constant isn't valid.
3831
3832 (define_insn "const_mulsidi3"
3833   [(set (match_operand:DI 0 "register_operand" "=r")
3834         (mult:DI (sign_extend:DI (match_operand:SI 1 "register_operand" "r"))
3835                  (match_operand:SI 2 "small_int" "I")))]
3836   "TARGET_V8 || TARGET_SPARCLITE || TARGET_SPARCLET || TARGET_DEPRECATED_V8_INSNS"
3837   "*
3838 {
3839   return TARGET_SPARCLET ? \"smuld %1,%2,%L0\" : \"smul %1,%2,%L0\;rd %%y,%H0\";
3840 }"
3841   [(set (attr "length")
3842         (if_then_else (eq_attr "isa" "sparclet")
3843                       (const_int 1) (const_int 2)))])
3844
3845 (define_expand "smulsi3_highpart"
3846   [(set (match_operand:SI 0 "register_operand" "")
3847         (truncate:SI
3848          (lshiftrt:DI (mult:DI (sign_extend:DI (match_operand:SI 1 "register_operand" ""))
3849                                (sign_extend:DI (match_operand:SI 2 "arith_operand" "")))
3850                       (const_int 32))))]
3851   "TARGET_V8 || TARGET_SPARCLITE || TARGET_SPARCLET || TARGET_DEPRECATED_V8_INSNS"
3852   "
3853 {
3854   if (CONSTANT_P (operands[2]))
3855     {
3856       emit_insn (gen_const_smulsi3_highpart (operands[0], operands[1], operands[2]));
3857       DONE;
3858     }
3859 }")
3860
3861 (define_insn "*smulsidi3_highpart_sp32"
3862   [(set (match_operand:SI 0 "register_operand" "=r")
3863         (truncate:SI
3864          (lshiftrt:DI (mult:DI (sign_extend:DI (match_operand:SI 1 "register_operand" "r"))
3865                                (sign_extend:DI (match_operand:SI 2 "register_operand" "r")))
3866                       (const_int 32))))]
3867   "TARGET_V8 || TARGET_SPARCLITE || TARGET_SPARCLET || TARGET_DEPRECATED_V8_INSNS"
3868   "smul %1,%2,%%g0\;rd %%y,%0"
3869   [(set_attr "length" "2")])
3870
3871 (define_insn "const_smulsi3_highpart"
3872   [(set (match_operand:SI 0 "register_operand" "=r")
3873         (truncate:SI
3874          (lshiftrt:DI (mult:DI (sign_extend:DI (match_operand:SI 1 "register_operand" "r"))
3875                                (match_operand:SI 2 "register_operand" "r"))
3876                       (const_int 32))))]
3877   "TARGET_V8 || TARGET_SPARCLITE || TARGET_SPARCLET || TARGET_DEPRECATED_V8_INSNS"
3878   "smul %1,%2,%%g0\;rd %%y,%0"
3879   [(set_attr "length" "2")])
3880
3881 (define_expand "umulsidi3"
3882   [(set (match_operand:DI 0 "register_operand" "")
3883         (mult:DI (zero_extend:DI (match_operand:SI 1 "register_operand" ""))
3884                  (zero_extend:DI (match_operand:SI 2 "uns_arith_operand" ""))))]
3885   "TARGET_V8 || TARGET_SPARCLITE || TARGET_SPARCLET || TARGET_DEPRECATED_V8_INSNS"
3886   "
3887 {
3888   if (CONSTANT_P (operands[2]))
3889     {
3890       emit_insn (gen_const_umulsidi3 (operands[0], operands[1], operands[2]));
3891       DONE;
3892     }
3893 }")
3894
3895 (define_insn "*umulsidi3_sp32"
3896   [(set (match_operand:DI 0 "register_operand" "=r")
3897         (mult:DI (zero_extend:DI (match_operand:SI 1 "register_operand" "r"))
3898                  (zero_extend:DI (match_operand:SI 2 "register_operand" "r"))))]
3899   "TARGET_V8 || TARGET_SPARCLITE || TARGET_SPARCLET || TARGET_DEPRECATED_V8_INSNS"
3900   "*
3901 {
3902   return TARGET_SPARCLET ? \"umuld %1,%2,%L0\" : \"umul %1,%2,%L0\;rd %%y,%H0\";
3903 }"
3904   [(set (attr "length")
3905         (if_then_else (eq_attr "isa" "sparclet")
3906                       (const_int 1) (const_int 2)))])
3907
3908 ;; Extra pattern, because sign_extend of a constant isn't valid.
3909
3910 (define_insn "const_umulsidi3"
3911   [(set (match_operand:DI 0 "register_operand" "=r")
3912         (mult:DI (zero_extend:DI (match_operand:SI 1 "register_operand" "r"))
3913                  (match_operand:SI 2 "uns_small_int" "")))]
3914   "TARGET_V8 || TARGET_SPARCLITE || TARGET_SPARCLET || TARGET_DEPRECATED_V8_INSNS"
3915   "*
3916 {
3917   return TARGET_SPARCLET ? \"umuld %1,%2,%L0\" : \"umul %1,%2,%L0\;rd %%y,%H0\";
3918 }"
3919   [(set (attr "length")
3920         (if_then_else (eq_attr "isa" "sparclet")
3921                       (const_int 1) (const_int 2)))])
3922
3923 (define_expand "umulsi3_highpart"
3924   [(set (match_operand:SI 0 "register_operand" "")
3925         (truncate:SI
3926          (lshiftrt:DI (mult:DI (zero_extend:DI (match_operand:SI 1 "register_operand" ""))
3927                                (zero_extend:DI (match_operand:SI 2 "uns_arith_operand" "")))
3928                       (const_int 32))))]
3929   "TARGET_V8 || TARGET_SPARCLITE || TARGET_SPARCLET || TARGET_DEPRECATED_V8_INSNS"
3930   "
3931 {
3932   if (CONSTANT_P (operands[2]))
3933     {
3934       emit_insn (gen_const_umulsi3_highpart (operands[0], operands[1], operands[2]));
3935       DONE;
3936     }
3937 }")
3938
3939 (define_insn "*umulsidi3_highpart_sp32"
3940   [(set (match_operand:SI 0 "register_operand" "=r")
3941         (truncate:SI
3942          (lshiftrt:DI (mult:DI (zero_extend:DI (match_operand:SI 1 "register_operand" "r"))
3943                                (zero_extend:DI (match_operand:SI 2 "register_operand" "r")))
3944                       (const_int 32))))]
3945   "TARGET_V8 || TARGET_SPARCLITE || TARGET_SPARCLET || TARGET_DEPRECATED_V8_INSNS"
3946   "umul %1,%2,%%g0\;rd %%y,%0"
3947   [(set_attr "length" "2")])
3948
3949 (define_insn "const_umulsi3_highpart"
3950   [(set (match_operand:SI 0 "register_operand" "=r")
3951         (truncate:SI
3952          (lshiftrt:DI (mult:DI (zero_extend:DI (match_operand:SI 1 "register_operand" "r"))
3953                                (match_operand:SI 2 "uns_small_int" ""))
3954                       (const_int 32))))]
3955   "TARGET_V8 || TARGET_SPARCLITE || TARGET_SPARCLET || TARGET_DEPRECATED_V8_INSNS"
3956   "umul %1,%2,%%g0\;rd %%y,%0"
3957   [(set_attr "length" "2")])
3958
3959 ;; The v8 architecture specifies that there must be 3 instructions between
3960 ;; a y register write and a use of it for correct results.
3961
3962 (define_insn "divsi3"
3963   [(set (match_operand:SI 0 "register_operand" "=r")
3964         (div:SI (match_operand:SI 1 "register_operand" "r")
3965                 (match_operand:SI 2 "arith_operand" "rI")))
3966    (clobber (match_scratch:SI 3 "=&r"))]
3967   "TARGET_V8 || TARGET_DEPRECATED_V8_INSNS"
3968   "*
3969 {
3970   if (TARGET_V9)
3971     return \"sra %1,31,%3\;wr %%g0,%3,%%y\;sdiv %1,%2,%0\";
3972   else
3973     return \"sra %1,31,%3\;wr %%g0,%3,%%y\;nop\;nop\;nop\;sdiv %1,%2,%0\";
3974 }"
3975   [(set (attr "length")
3976         (if_then_else (eq_attr "isa" "v9")